summaryrefslogtreecommitdiff
path: root/public/assets-2.0.0/js
diff options
context:
space:
mode:
authorGreg Roach <fisharebest@gmail.com>2017-12-30 14:22:13 +0000
committerGreg Roach <fisharebest@gmail.com>2018-01-02 20:18:10 +0000
commit27c4cda0cb98970e86f55c22a8248833b6cf40d9 (patch)
tree7f7f01577ead547aaefa1db79c77830836f6b5f6 /public/assets-2.0.0/js
parent87f36d93a85c7feb25fe17c05ec58b902d02c08f (diff)
downloadwebtrees-27c4cda0cb98970e86f55c22a8248833b6cf40d9.tar.gz
webtrees-27c4cda0cb98970e86f55c22a8248833b6cf40d9.tar.bz2
webtrees-27c4cda0cb98970e86f55c22a8248833b6cf40d9.zip
Use npm/webpack/babel/laravel-mix to manage and bundle assets
Diffstat (limited to 'public/assets-2.0.0/js')
-rw-r--r--public/assets-2.0.0/js/vendor.js63138
-rw-r--r--public/assets-2.0.0/js/webtrees.js998
2 files changed, 64136 insertions, 0 deletions
diff --git a/public/assets-2.0.0/js/vendor.js b/public/assets-2.0.0/js/vendor.js
new file mode 100644
index 0000000000..8d58c980a1
--- /dev/null
+++ b/public/assets-2.0.0/js/vendor.js
@@ -0,0 +1,63138 @@
+/******/ (function(modules) { // webpackBootstrap
+/******/ // The module cache
+/******/ var installedModules = {};
+/******/
+/******/ // The require function
+/******/ function __webpack_require__(moduleId) {
+/******/
+/******/ // Check if module is in cache
+/******/ if(installedModules[moduleId]) {
+/******/ return installedModules[moduleId].exports;
+/******/ }
+/******/ // Create a new module (and put it into the cache)
+/******/ var module = installedModules[moduleId] = {
+/******/ i: moduleId,
+/******/ l: false,
+/******/ exports: {}
+/******/ };
+/******/
+/******/ // Execute the module function
+/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
+/******/
+/******/ // Flag the module as loaded
+/******/ module.l = true;
+/******/
+/******/ // Return the exports of the module
+/******/ return module.exports;
+/******/ }
+/******/
+/******/
+/******/ // expose the modules object (__webpack_modules__)
+/******/ __webpack_require__.m = modules;
+/******/
+/******/ // expose the module cache
+/******/ __webpack_require__.c = installedModules;
+/******/
+/******/ // define getter function for harmony exports
+/******/ __webpack_require__.d = function(exports, name, getter) {
+/******/ if(!__webpack_require__.o(exports, name)) {
+/******/ Object.defineProperty(exports, name, {
+/******/ configurable: false,
+/******/ enumerable: true,
+/******/ get: getter
+/******/ });
+/******/ }
+/******/ };
+/******/
+/******/ // getDefaultExport function for compatibility with non-harmony modules
+/******/ __webpack_require__.n = function(module) {
+/******/ var getter = module && module.__esModule ?
+/******/ function getDefault() { return module['default']; } :
+/******/ function getModuleExports() { return module; };
+/******/ __webpack_require__.d(getter, 'a', getter);
+/******/ return getter;
+/******/ };
+/******/
+/******/ // Object.prototype.hasOwnProperty.call
+/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ // __webpack_public_path__
+/******/ __webpack_require__.p = "";
+/******/
+/******/ // Load entry module and return exports
+/******/ return __webpack_require__(__webpack_require__.s = 124);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function(module) {var require;//! moment.js
+//! version : 2.20.1
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+
+;(function (global, factory) {
+ true ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ global.moment = factory()
+}(this, (function () { 'use strict';
+
+var hookCallback;
+
+function hooks () {
+ return hookCallback.apply(null, arguments);
+}
+
+// This is done to register the method called with moment()
+// without creating circular dependencies.
+function setHookCallback (callback) {
+ hookCallback = callback;
+}
+
+function isArray(input) {
+ return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
+}
+
+function isObject(input) {
+ // IE8 will treat undefined and null as object if it wasn't for
+ // input != null
+ return input != null && Object.prototype.toString.call(input) === '[object Object]';
+}
+
+function isObjectEmpty(obj) {
+ if (Object.getOwnPropertyNames) {
+ return (Object.getOwnPropertyNames(obj).length === 0);
+ } else {
+ var k;
+ for (k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+function isUndefined(input) {
+ return input === void 0;
+}
+
+function isNumber(input) {
+ return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
+}
+
+function isDate(input) {
+ return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
+}
+
+function map(arr, fn) {
+ var res = [], i;
+ for (i = 0; i < arr.length; ++i) {
+ res.push(fn(arr[i], i));
+ }
+ return res;
+}
+
+function hasOwnProp(a, b) {
+ return Object.prototype.hasOwnProperty.call(a, b);
+}
+
+function extend(a, b) {
+ for (var i in b) {
+ if (hasOwnProp(b, i)) {
+ a[i] = b[i];
+ }
+ }
+
+ if (hasOwnProp(b, 'toString')) {
+ a.toString = b.toString;
+ }
+
+ if (hasOwnProp(b, 'valueOf')) {
+ a.valueOf = b.valueOf;
+ }
+
+ return a;
+}
+
+function createUTC (input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, true).utc();
+}
+
+function defaultParsingFlags() {
+ // We need to deep clone this object.
+ return {
+ empty : false,
+ unusedTokens : [],
+ unusedInput : [],
+ overflow : -2,
+ charsLeftOver : 0,
+ nullInput : false,
+ invalidMonth : null,
+ invalidFormat : false,
+ userInvalidated : false,
+ iso : false,
+ parsedDateParts : [],
+ meridiem : null,
+ rfc2822 : false,
+ weekdayMismatch : false
+ };
+}
+
+function getParsingFlags(m) {
+ if (m._pf == null) {
+ m._pf = defaultParsingFlags();
+ }
+ return m._pf;
+}
+
+var some;
+if (Array.prototype.some) {
+ some = Array.prototype.some;
+} else {
+ some = function (fun) {
+ var t = Object(this);
+ var len = t.length >>> 0;
+
+ for (var i = 0; i < len; i++) {
+ if (i in t && fun.call(this, t[i], i, t)) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+}
+
+function isValid(m) {
+ if (m._isValid == null) {
+ var flags = getParsingFlags(m);
+ var parsedParts = some.call(flags.parsedDateParts, function (i) {
+ return i != null;
+ });
+ var isNowValid = !isNaN(m._d.getTime()) &&
+ flags.overflow < 0 &&
+ !flags.empty &&
+ !flags.invalidMonth &&
+ !flags.invalidWeekday &&
+ !flags.weekdayMismatch &&
+ !flags.nullInput &&
+ !flags.invalidFormat &&
+ !flags.userInvalidated &&
+ (!flags.meridiem || (flags.meridiem && parsedParts));
+
+ if (m._strict) {
+ isNowValid = isNowValid &&
+ flags.charsLeftOver === 0 &&
+ flags.unusedTokens.length === 0 &&
+ flags.bigHour === undefined;
+ }
+
+ if (Object.isFrozen == null || !Object.isFrozen(m)) {
+ m._isValid = isNowValid;
+ }
+ else {
+ return isNowValid;
+ }
+ }
+ return m._isValid;
+}
+
+function createInvalid (flags) {
+ var m = createUTC(NaN);
+ if (flags != null) {
+ extend(getParsingFlags(m), flags);
+ }
+ else {
+ getParsingFlags(m).userInvalidated = true;
+ }
+
+ return m;
+}
+
+// Plugins that add properties should also add the key here (null value),
+// so we can properly clone ourselves.
+var momentProperties = hooks.momentProperties = [];
+
+function copyConfig(to, from) {
+ var i, prop, val;
+
+ if (!isUndefined(from._isAMomentObject)) {
+ to._isAMomentObject = from._isAMomentObject;
+ }
+ if (!isUndefined(from._i)) {
+ to._i = from._i;
+ }
+ if (!isUndefined(from._f)) {
+ to._f = from._f;
+ }
+ if (!isUndefined(from._l)) {
+ to._l = from._l;
+ }
+ if (!isUndefined(from._strict)) {
+ to._strict = from._strict;
+ }
+ if (!isUndefined(from._tzm)) {
+ to._tzm = from._tzm;
+ }
+ if (!isUndefined(from._isUTC)) {
+ to._isUTC = from._isUTC;
+ }
+ if (!isUndefined(from._offset)) {
+ to._offset = from._offset;
+ }
+ if (!isUndefined(from._pf)) {
+ to._pf = getParsingFlags(from);
+ }
+ if (!isUndefined(from._locale)) {
+ to._locale = from._locale;
+ }
+
+ if (momentProperties.length > 0) {
+ for (i = 0; i < momentProperties.length; i++) {
+ prop = momentProperties[i];
+ val = from[prop];
+ if (!isUndefined(val)) {
+ to[prop] = val;
+ }
+ }
+ }
+
+ return to;
+}
+
+var updateInProgress = false;
+
+// Moment prototype object
+function Moment(config) {
+ copyConfig(this, config);
+ this._d = new Date(config._d != null ? config._d.getTime() : NaN);
+ if (!this.isValid()) {
+ this._d = new Date(NaN);
+ }
+ // Prevent infinite loop in case updateOffset creates new moment
+ // objects.
+ if (updateInProgress === false) {
+ updateInProgress = true;
+ hooks.updateOffset(this);
+ updateInProgress = false;
+ }
+}
+
+function isMoment (obj) {
+ return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
+}
+
+function absFloor (number) {
+ if (number < 0) {
+ // -0 -> 0
+ return Math.ceil(number) || 0;
+ } else {
+ return Math.floor(number);
+ }
+}
+
+function toInt(argumentForCoercion) {
+ var coercedNumber = +argumentForCoercion,
+ value = 0;
+
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+ value = absFloor(coercedNumber);
+ }
+
+ return value;
+}
+
+// compare two arrays, return the number of differences
+function compareArrays(array1, array2, dontConvert) {
+ var len = Math.min(array1.length, array2.length),
+ lengthDiff = Math.abs(array1.length - array2.length),
+ diffs = 0,
+ i;
+ for (i = 0; i < len; i++) {
+ if ((dontConvert && array1[i] !== array2[i]) ||
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
+ diffs++;
+ }
+ }
+ return diffs + lengthDiff;
+}
+
+function warn(msg) {
+ if (hooks.suppressDeprecationWarnings === false &&
+ (typeof console !== 'undefined') && console.warn) {
+ console.warn('Deprecation warning: ' + msg);
+ }
+}
+
+function deprecate(msg, fn) {
+ var firstTime = true;
+
+ return extend(function () {
+ if (hooks.deprecationHandler != null) {
+ hooks.deprecationHandler(null, msg);
+ }
+ if (firstTime) {
+ var args = [];
+ var arg;
+ for (var i = 0; i < arguments.length; i++) {
+ arg = '';
+ if (typeof arguments[i] === 'object') {
+ arg += '\n[' + i + '] ';
+ for (var key in arguments[0]) {
+ arg += key + ': ' + arguments[0][key] + ', ';
+ }
+ arg = arg.slice(0, -2); // Remove trailing comma and space
+ } else {
+ arg = arguments[i];
+ }
+ args.push(arg);
+ }
+ warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
+ firstTime = false;
+ }
+ return fn.apply(this, arguments);
+ }, fn);
+}
+
+var deprecations = {};
+
+function deprecateSimple(name, msg) {
+ if (hooks.deprecationHandler != null) {
+ hooks.deprecationHandler(name, msg);
+ }
+ if (!deprecations[name]) {
+ warn(msg);
+ deprecations[name] = true;
+ }
+}
+
+hooks.suppressDeprecationWarnings = false;
+hooks.deprecationHandler = null;
+
+function isFunction(input) {
+ return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
+}
+
+function set (config) {
+ var prop, i;
+ for (i in config) {
+ prop = config[i];
+ if (isFunction(prop)) {
+ this[i] = prop;
+ } else {
+ this['_' + i] = prop;
+ }
+ }
+ this._config = config;
+ // Lenient ordinal parsing accepts just a number in addition to
+ // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
+ // TODO: Remove "ordinalParse" fallback in next major release.
+ this._dayOfMonthOrdinalParseLenient = new RegExp(
+ (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
+ '|' + (/\d{1,2}/).source);
+}
+
+function mergeConfigs(parentConfig, childConfig) {
+ var res = extend({}, parentConfig), prop;
+ for (prop in childConfig) {
+ if (hasOwnProp(childConfig, prop)) {
+ if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
+ res[prop] = {};
+ extend(res[prop], parentConfig[prop]);
+ extend(res[prop], childConfig[prop]);
+ } else if (childConfig[prop] != null) {
+ res[prop] = childConfig[prop];
+ } else {
+ delete res[prop];
+ }
+ }
+ }
+ for (prop in parentConfig) {
+ if (hasOwnProp(parentConfig, prop) &&
+ !hasOwnProp(childConfig, prop) &&
+ isObject(parentConfig[prop])) {
+ // make sure changes to properties don't modify parent config
+ res[prop] = extend({}, res[prop]);
+ }
+ }
+ return res;
+}
+
+function Locale(config) {
+ if (config != null) {
+ this.set(config);
+ }
+}
+
+var keys;
+
+if (Object.keys) {
+ keys = Object.keys;
+} else {
+ keys = function (obj) {
+ var i, res = [];
+ for (i in obj) {
+ if (hasOwnProp(obj, i)) {
+ res.push(i);
+ }
+ }
+ return res;
+ };
+}
+
+var defaultCalendar = {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+};
+
+function calendar (key, mom, now) {
+ var output = this._calendar[key] || this._calendar['sameElse'];
+ return isFunction(output) ? output.call(mom, now) : output;
+}
+
+var defaultLongDateFormat = {
+ LTS : 'h:mm:ss A',
+ LT : 'h:mm A',
+ L : 'MM/DD/YYYY',
+ LL : 'MMMM D, YYYY',
+ LLL : 'MMMM D, YYYY h:mm A',
+ LLLL : 'dddd, MMMM D, YYYY h:mm A'
+};
+
+function longDateFormat (key) {
+ var format = this._longDateFormat[key],
+ formatUpper = this._longDateFormat[key.toUpperCase()];
+
+ if (format || !formatUpper) {
+ return format;
+ }
+
+ this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
+ return val.slice(1);
+ });
+
+ return this._longDateFormat[key];
+}
+
+var defaultInvalidDate = 'Invalid date';
+
+function invalidDate () {
+ return this._invalidDate;
+}
+
+var defaultOrdinal = '%d';
+var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
+
+function ordinal (number) {
+ return this._ordinal.replace('%d', number);
+}
+
+var defaultRelativeTime = {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ ss : '%d seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+};
+
+function relativeTime (number, withoutSuffix, string, isFuture) {
+ var output = this._relativeTime[string];
+ return (isFunction(output)) ?
+ output(number, withoutSuffix, string, isFuture) :
+ output.replace(/%d/i, number);
+}
+
+function pastFuture (diff, output) {
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+ return isFunction(format) ? format(output) : format.replace(/%s/i, output);
+}
+
+var aliases = {};
+
+function addUnitAlias (unit, shorthand) {
+ var lowerCase = unit.toLowerCase();
+ aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
+}
+
+function normalizeUnits(units) {
+ return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
+}
+
+function normalizeObjectUnits(inputObject) {
+ var normalizedInput = {},
+ normalizedProp,
+ prop;
+
+ for (prop in inputObject) {
+ if (hasOwnProp(inputObject, prop)) {
+ normalizedProp = normalizeUnits(prop);
+ if (normalizedProp) {
+ normalizedInput[normalizedProp] = inputObject[prop];
+ }
+ }
+ }
+
+ return normalizedInput;
+}
+
+var priorities = {};
+
+function addUnitPriority(unit, priority) {
+ priorities[unit] = priority;
+}
+
+function getPrioritizedUnits(unitsObj) {
+ var units = [];
+ for (var u in unitsObj) {
+ units.push({unit: u, priority: priorities[u]});
+ }
+ units.sort(function (a, b) {
+ return a.priority - b.priority;
+ });
+ return units;
+}
+
+function zeroFill(number, targetLength, forceSign) {
+ var absNumber = '' + Math.abs(number),
+ zerosToFill = targetLength - absNumber.length,
+ sign = number >= 0;
+ return (sign ? (forceSign ? '+' : '') : '-') +
+ Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
+}
+
+var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
+
+var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
+
+var formatFunctions = {};
+
+var formatTokenFunctions = {};
+
+// token: 'M'
+// padded: ['MM', 2]
+// ordinal: 'Mo'
+// callback: function () { this.month() + 1 }
+function addFormatToken (token, padded, ordinal, callback) {
+ var func = callback;
+ if (typeof callback === 'string') {
+ func = function () {
+ return this[callback]();
+ };
+ }
+ if (token) {
+ formatTokenFunctions[token] = func;
+ }
+ if (padded) {
+ formatTokenFunctions[padded[0]] = function () {
+ return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
+ };
+ }
+ if (ordinal) {
+ formatTokenFunctions[ordinal] = function () {
+ return this.localeData().ordinal(func.apply(this, arguments), token);
+ };
+ }
+}
+
+function removeFormattingTokens(input) {
+ if (input.match(/\[[\s\S]/)) {
+ return input.replace(/^\[|\]$/g, '');
+ }
+ return input.replace(/\\/g, '');
+}
+
+function makeFormatFunction(format) {
+ var array = format.match(formattingTokens), i, length;
+
+ for (i = 0, length = array.length; i < length; i++) {
+ if (formatTokenFunctions[array[i]]) {
+ array[i] = formatTokenFunctions[array[i]];
+ } else {
+ array[i] = removeFormattingTokens(array[i]);
+ }
+ }
+
+ return function (mom) {
+ var output = '', i;
+ for (i = 0; i < length; i++) {
+ output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
+ }
+ return output;
+ };
+}
+
+// format date using native date object
+function formatMoment(m, format) {
+ if (!m.isValid()) {
+ return m.localeData().invalidDate();
+ }
+
+ format = expandFormat(format, m.localeData());
+ formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
+
+ return formatFunctions[format](m);
+}
+
+function expandFormat(format, locale) {
+ var i = 5;
+
+ function replaceLongDateFormatTokens(input) {
+ return locale.longDateFormat(input) || input;
+ }
+
+ localFormattingTokens.lastIndex = 0;
+ while (i >= 0 && localFormattingTokens.test(format)) {
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
+ localFormattingTokens.lastIndex = 0;
+ i -= 1;
+ }
+
+ return format;
+}
+
+var match1 = /\d/; // 0 - 9
+var match2 = /\d\d/; // 00 - 99
+var match3 = /\d{3}/; // 000 - 999
+var match4 = /\d{4}/; // 0000 - 9999
+var match6 = /[+-]?\d{6}/; // -999999 - 999999
+var match1to2 = /\d\d?/; // 0 - 99
+var match3to4 = /\d\d\d\d?/; // 999 - 9999
+var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
+var match1to3 = /\d{1,3}/; // 0 - 999
+var match1to4 = /\d{1,4}/; // 0 - 9999
+var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
+
+var matchUnsigned = /\d+/; // 0 - inf
+var matchSigned = /[+-]?\d+/; // -inf - inf
+
+var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
+var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
+
+var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
+
+// any word (or two) characters or numbers including two/three word month in arabic.
+// includes scottish gaelic two word and hyphenated months
+var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
+
+
+var regexes = {};
+
+function addRegexToken (token, regex, strictRegex) {
+ regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
+ return (isStrict && strictRegex) ? strictRegex : regex;
+ };
+}
+
+function getParseRegexForToken (token, config) {
+ if (!hasOwnProp(regexes, token)) {
+ return new RegExp(unescapeFormat(token));
+ }
+
+ return regexes[token](config._strict, config._locale);
+}
+
+// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+function unescapeFormat(s) {
+ return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
+ return p1 || p2 || p3 || p4;
+ }));
+}
+
+function regexEscape(s) {
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+}
+
+var tokens = {};
+
+function addParseToken (token, callback) {
+ var i, func = callback;
+ if (typeof token === 'string') {
+ token = [token];
+ }
+ if (isNumber(callback)) {
+ func = function (input, array) {
+ array[callback] = toInt(input);
+ };
+ }
+ for (i = 0; i < token.length; i++) {
+ tokens[token[i]] = func;
+ }
+}
+
+function addWeekParseToken (token, callback) {
+ addParseToken(token, function (input, array, config, token) {
+ config._w = config._w || {};
+ callback(input, config._w, config, token);
+ });
+}
+
+function addTimeToArrayFromToken(token, input, config) {
+ if (input != null && hasOwnProp(tokens, token)) {
+ tokens[token](input, config._a, config, token);
+ }
+}
+
+var YEAR = 0;
+var MONTH = 1;
+var DATE = 2;
+var HOUR = 3;
+var MINUTE = 4;
+var SECOND = 5;
+var MILLISECOND = 6;
+var WEEK = 7;
+var WEEKDAY = 8;
+
+// FORMATTING
+
+addFormatToken('Y', 0, 0, function () {
+ var y = this.year();
+ return y <= 9999 ? '' + y : '+' + y;
+});
+
+addFormatToken(0, ['YY', 2], 0, function () {
+ return this.year() % 100;
+});
+
+addFormatToken(0, ['YYYY', 4], 0, 'year');
+addFormatToken(0, ['YYYYY', 5], 0, 'year');
+addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
+
+// ALIASES
+
+addUnitAlias('year', 'y');
+
+// PRIORITIES
+
+addUnitPriority('year', 1);
+
+// PARSING
+
+addRegexToken('Y', matchSigned);
+addRegexToken('YY', match1to2, match2);
+addRegexToken('YYYY', match1to4, match4);
+addRegexToken('YYYYY', match1to6, match6);
+addRegexToken('YYYYYY', match1to6, match6);
+
+addParseToken(['YYYYY', 'YYYYYY'], YEAR);
+addParseToken('YYYY', function (input, array) {
+ array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
+});
+addParseToken('YY', function (input, array) {
+ array[YEAR] = hooks.parseTwoDigitYear(input);
+});
+addParseToken('Y', function (input, array) {
+ array[YEAR] = parseInt(input, 10);
+});
+
+// HELPERS
+
+function daysInYear(year) {
+ return isLeapYear(year) ? 366 : 365;
+}
+
+function isLeapYear(year) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+}
+
+// HOOKS
+
+hooks.parseTwoDigitYear = function (input) {
+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+};
+
+// MOMENTS
+
+var getSetYear = makeGetSet('FullYear', true);
+
+function getIsLeapYear () {
+ return isLeapYear(this.year());
+}
+
+function makeGetSet (unit, keepTime) {
+ return function (value) {
+ if (value != null) {
+ set$1(this, unit, value);
+ hooks.updateOffset(this, keepTime);
+ return this;
+ } else {
+ return get(this, unit);
+ }
+ };
+}
+
+function get (mom, unit) {
+ return mom.isValid() ?
+ mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
+}
+
+function set$1 (mom, unit, value) {
+ if (mom.isValid() && !isNaN(value)) {
+ if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
+ }
+ else {
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+ }
+ }
+}
+
+// MOMENTS
+
+function stringGet (units) {
+ units = normalizeUnits(units);
+ if (isFunction(this[units])) {
+ return this[units]();
+ }
+ return this;
+}
+
+
+function stringSet (units, value) {
+ if (typeof units === 'object') {
+ units = normalizeObjectUnits(units);
+ var prioritized = getPrioritizedUnits(units);
+ for (var i = 0; i < prioritized.length; i++) {
+ this[prioritized[i].unit](units[prioritized[i].unit]);
+ }
+ } else {
+ units = normalizeUnits(units);
+ if (isFunction(this[units])) {
+ return this[units](value);
+ }
+ }
+ return this;
+}
+
+function mod(n, x) {
+ return ((n % x) + x) % x;
+}
+
+var indexOf;
+
+if (Array.prototype.indexOf) {
+ indexOf = Array.prototype.indexOf;
+} else {
+ indexOf = function (o) {
+ // I know
+ var i;
+ for (i = 0; i < this.length; ++i) {
+ if (this[i] === o) {
+ return i;
+ }
+ }
+ return -1;
+ };
+}
+
+function daysInMonth(year, month) {
+ if (isNaN(year) || isNaN(month)) {
+ return NaN;
+ }
+ var modMonth = mod(month, 12);
+ year += (month - modMonth) / 12;
+ return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
+}
+
+// FORMATTING
+
+addFormatToken('M', ['MM', 2], 'Mo', function () {
+ return this.month() + 1;
+});
+
+addFormatToken('MMM', 0, 0, function (format) {
+ return this.localeData().monthsShort(this, format);
+});
+
+addFormatToken('MMMM', 0, 0, function (format) {
+ return this.localeData().months(this, format);
+});
+
+// ALIASES
+
+addUnitAlias('month', 'M');
+
+// PRIORITY
+
+addUnitPriority('month', 8);
+
+// PARSING
+
+addRegexToken('M', match1to2);
+addRegexToken('MM', match1to2, match2);
+addRegexToken('MMM', function (isStrict, locale) {
+ return locale.monthsShortRegex(isStrict);
+});
+addRegexToken('MMMM', function (isStrict, locale) {
+ return locale.monthsRegex(isStrict);
+});
+
+addParseToken(['M', 'MM'], function (input, array) {
+ array[MONTH] = toInt(input) - 1;
+});
+
+addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
+ var month = config._locale.monthsParse(input, token, config._strict);
+ // if we didn't find a month name, mark the date as invalid.
+ if (month != null) {
+ array[MONTH] = month;
+ } else {
+ getParsingFlags(config).invalidMonth = input;
+ }
+});
+
+// LOCALES
+
+var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
+var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
+function localeMonths (m, format) {
+ if (!m) {
+ return isArray(this._months) ? this._months :
+ this._months['standalone'];
+ }
+ return isArray(this._months) ? this._months[m.month()] :
+ this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
+}
+
+var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
+function localeMonthsShort (m, format) {
+ if (!m) {
+ return isArray(this._monthsShort) ? this._monthsShort :
+ this._monthsShort['standalone'];
+ }
+ return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
+ this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
+}
+
+function handleStrictParse(monthName, format, strict) {
+ var i, ii, mom, llc = monthName.toLocaleLowerCase();
+ if (!this._monthsParse) {
+ // this is not used
+ this._monthsParse = [];
+ this._longMonthsParse = [];
+ this._shortMonthsParse = [];
+ for (i = 0; i < 12; ++i) {
+ mom = createUTC([2000, i]);
+ this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
+ this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
+ }
+ }
+
+ if (strict) {
+ if (format === 'MMM') {
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._longMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ } else {
+ if (format === 'MMM') {
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._longMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._longMonthsParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ }
+}
+
+function localeMonthsParse (monthName, format, strict) {
+ var i, mom, regex;
+
+ if (this._monthsParseExact) {
+ return handleStrictParse.call(this, monthName, format, strict);
+ }
+
+ if (!this._monthsParse) {
+ this._monthsParse = [];
+ this._longMonthsParse = [];
+ this._shortMonthsParse = [];
+ }
+
+ // TODO: add sorting
+ // Sorting makes sure if one month (or abbr) is a prefix of another
+ // see sorting in computeMonthsParse
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, i]);
+ if (strict && !this._longMonthsParse[i]) {
+ this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
+ this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
+ }
+ if (!strict && !this._monthsParse[i]) {
+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
+ return i;
+ } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
+ return i;
+ } else if (!strict && this._monthsParse[i].test(monthName)) {
+ return i;
+ }
+ }
+}
+
+// MOMENTS
+
+function setMonth (mom, value) {
+ var dayOfMonth;
+
+ if (!mom.isValid()) {
+ // No op
+ return mom;
+ }
+
+ if (typeof value === 'string') {
+ if (/^\d+$/.test(value)) {
+ value = toInt(value);
+ } else {
+ value = mom.localeData().monthsParse(value);
+ // TODO: Another silent failure?
+ if (!isNumber(value)) {
+ return mom;
+ }
+ }
+ }
+
+ dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
+ return mom;
+}
+
+function getSetMonth (value) {
+ if (value != null) {
+ setMonth(this, value);
+ hooks.updateOffset(this, true);
+ return this;
+ } else {
+ return get(this, 'Month');
+ }
+}
+
+function getDaysInMonth () {
+ return daysInMonth(this.year(), this.month());
+}
+
+var defaultMonthsShortRegex = matchWord;
+function monthsShortRegex (isStrict) {
+ if (this._monthsParseExact) {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ computeMonthsParse.call(this);
+ }
+ if (isStrict) {
+ return this._monthsShortStrictRegex;
+ } else {
+ return this._monthsShortRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_monthsShortRegex')) {
+ this._monthsShortRegex = defaultMonthsShortRegex;
+ }
+ return this._monthsShortStrictRegex && isStrict ?
+ this._monthsShortStrictRegex : this._monthsShortRegex;
+ }
+}
+
+var defaultMonthsRegex = matchWord;
+function monthsRegex (isStrict) {
+ if (this._monthsParseExact) {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ computeMonthsParse.call(this);
+ }
+ if (isStrict) {
+ return this._monthsStrictRegex;
+ } else {
+ return this._monthsRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ this._monthsRegex = defaultMonthsRegex;
+ }
+ return this._monthsStrictRegex && isStrict ?
+ this._monthsStrictRegex : this._monthsRegex;
+ }
+}
+
+function computeMonthsParse () {
+ function cmpLenRev(a, b) {
+ return b.length - a.length;
+ }
+
+ var shortPieces = [], longPieces = [], mixedPieces = [],
+ i, mom;
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, i]);
+ shortPieces.push(this.monthsShort(mom, ''));
+ longPieces.push(this.months(mom, ''));
+ mixedPieces.push(this.months(mom, ''));
+ mixedPieces.push(this.monthsShort(mom, ''));
+ }
+ // Sorting makes sure if one month (or abbr) is a prefix of another it
+ // will match the longer piece.
+ shortPieces.sort(cmpLenRev);
+ longPieces.sort(cmpLenRev);
+ mixedPieces.sort(cmpLenRev);
+ for (i = 0; i < 12; i++) {
+ shortPieces[i] = regexEscape(shortPieces[i]);
+ longPieces[i] = regexEscape(longPieces[i]);
+ }
+ for (i = 0; i < 24; i++) {
+ mixedPieces[i] = regexEscape(mixedPieces[i]);
+ }
+
+ this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+ this._monthsShortRegex = this._monthsRegex;
+ this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
+ this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
+}
+
+function createDate (y, m, d, h, M, s, ms) {
+ // can't just apply() to create a date:
+ // https://stackoverflow.com/q/181348
+ var date = new Date(y, m, d, h, M, s, ms);
+
+ // the date constructor remaps years 0-99 to 1900-1999
+ if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
+ date.setFullYear(y);
+ }
+ return date;
+}
+
+function createUTCDate (y) {
+ var date = new Date(Date.UTC.apply(null, arguments));
+
+ // the Date.UTC function remaps years 0-99 to 1900-1999
+ if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
+ date.setUTCFullYear(y);
+ }
+ return date;
+}
+
+// start-of-first-week - start-of-year
+function firstWeekOffset(year, dow, doy) {
+ var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
+ fwd = 7 + dow - doy,
+ // first-week day local weekday -- which local weekday is fwd
+ fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
+
+ return -fwdlw + fwd - 1;
+}
+
+// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
+function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
+ var localWeekday = (7 + weekday - dow) % 7,
+ weekOffset = firstWeekOffset(year, dow, doy),
+ dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
+ resYear, resDayOfYear;
+
+ if (dayOfYear <= 0) {
+ resYear = year - 1;
+ resDayOfYear = daysInYear(resYear) + dayOfYear;
+ } else if (dayOfYear > daysInYear(year)) {
+ resYear = year + 1;
+ resDayOfYear = dayOfYear - daysInYear(year);
+ } else {
+ resYear = year;
+ resDayOfYear = dayOfYear;
+ }
+
+ return {
+ year: resYear,
+ dayOfYear: resDayOfYear
+ };
+}
+
+function weekOfYear(mom, dow, doy) {
+ var weekOffset = firstWeekOffset(mom.year(), dow, doy),
+ week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
+ resWeek, resYear;
+
+ if (week < 1) {
+ resYear = mom.year() - 1;
+ resWeek = week + weeksInYear(resYear, dow, doy);
+ } else if (week > weeksInYear(mom.year(), dow, doy)) {
+ resWeek = week - weeksInYear(mom.year(), dow, doy);
+ resYear = mom.year() + 1;
+ } else {
+ resYear = mom.year();
+ resWeek = week;
+ }
+
+ return {
+ week: resWeek,
+ year: resYear
+ };
+}
+
+function weeksInYear(year, dow, doy) {
+ var weekOffset = firstWeekOffset(year, dow, doy),
+ weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
+ return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
+}
+
+// FORMATTING
+
+addFormatToken('w', ['ww', 2], 'wo', 'week');
+addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
+
+// ALIASES
+
+addUnitAlias('week', 'w');
+addUnitAlias('isoWeek', 'W');
+
+// PRIORITIES
+
+addUnitPriority('week', 5);
+addUnitPriority('isoWeek', 5);
+
+// PARSING
+
+addRegexToken('w', match1to2);
+addRegexToken('ww', match1to2, match2);
+addRegexToken('W', match1to2);
+addRegexToken('WW', match1to2, match2);
+
+addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
+ week[token.substr(0, 1)] = toInt(input);
+});
+
+// HELPERS
+
+// LOCALES
+
+function localeWeek (mom) {
+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
+}
+
+var defaultLocaleWeek = {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+};
+
+function localeFirstDayOfWeek () {
+ return this._week.dow;
+}
+
+function localeFirstDayOfYear () {
+ return this._week.doy;
+}
+
+// MOMENTS
+
+function getSetWeek (input) {
+ var week = this.localeData().week(this);
+ return input == null ? week : this.add((input - week) * 7, 'd');
+}
+
+function getSetISOWeek (input) {
+ var week = weekOfYear(this, 1, 4).week;
+ return input == null ? week : this.add((input - week) * 7, 'd');
+}
+
+// FORMATTING
+
+addFormatToken('d', 0, 'do', 'day');
+
+addFormatToken('dd', 0, 0, function (format) {
+ return this.localeData().weekdaysMin(this, format);
+});
+
+addFormatToken('ddd', 0, 0, function (format) {
+ return this.localeData().weekdaysShort(this, format);
+});
+
+addFormatToken('dddd', 0, 0, function (format) {
+ return this.localeData().weekdays(this, format);
+});
+
+addFormatToken('e', 0, 0, 'weekday');
+addFormatToken('E', 0, 0, 'isoWeekday');
+
+// ALIASES
+
+addUnitAlias('day', 'd');
+addUnitAlias('weekday', 'e');
+addUnitAlias('isoWeekday', 'E');
+
+// PRIORITY
+addUnitPriority('day', 11);
+addUnitPriority('weekday', 11);
+addUnitPriority('isoWeekday', 11);
+
+// PARSING
+
+addRegexToken('d', match1to2);
+addRegexToken('e', match1to2);
+addRegexToken('E', match1to2);
+addRegexToken('dd', function (isStrict, locale) {
+ return locale.weekdaysMinRegex(isStrict);
+});
+addRegexToken('ddd', function (isStrict, locale) {
+ return locale.weekdaysShortRegex(isStrict);
+});
+addRegexToken('dddd', function (isStrict, locale) {
+ return locale.weekdaysRegex(isStrict);
+});
+
+addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
+ var weekday = config._locale.weekdaysParse(input, token, config._strict);
+ // if we didn't get a weekday name, mark the date as invalid
+ if (weekday != null) {
+ week.d = weekday;
+ } else {
+ getParsingFlags(config).invalidWeekday = input;
+ }
+});
+
+addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
+ week[token] = toInt(input);
+});
+
+// HELPERS
+
+function parseWeekday(input, locale) {
+ if (typeof input !== 'string') {
+ return input;
+ }
+
+ if (!isNaN(input)) {
+ return parseInt(input, 10);
+ }
+
+ input = locale.weekdaysParse(input);
+ if (typeof input === 'number') {
+ return input;
+ }
+
+ return null;
+}
+
+function parseIsoWeekday(input, locale) {
+ if (typeof input === 'string') {
+ return locale.weekdaysParse(input) % 7 || 7;
+ }
+ return isNaN(input) ? null : input;
+}
+
+// LOCALES
+
+var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
+function localeWeekdays (m, format) {
+ if (!m) {
+ return isArray(this._weekdays) ? this._weekdays :
+ this._weekdays['standalone'];
+ }
+ return isArray(this._weekdays) ? this._weekdays[m.day()] :
+ this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
+}
+
+var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
+function localeWeekdaysShort (m) {
+ return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
+}
+
+var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
+function localeWeekdaysMin (m) {
+ return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
+}
+
+function handleStrictParse$1(weekdayName, format, strict) {
+ var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
+ if (!this._weekdaysParse) {
+ this._weekdaysParse = [];
+ this._shortWeekdaysParse = [];
+ this._minWeekdaysParse = [];
+
+ for (i = 0; i < 7; ++i) {
+ mom = createUTC([2000, 1]).day(i);
+ this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
+ this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
+ this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
+ }
+ }
+
+ if (strict) {
+ if (format === 'dddd') {
+ ii = indexOf.call(this._weekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else if (format === 'ddd') {
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ } else {
+ if (format === 'dddd') {
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else if (format === 'ddd') {
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ }
+}
+
+function localeWeekdaysParse (weekdayName, format, strict) {
+ var i, mom, regex;
+
+ if (this._weekdaysParseExact) {
+ return handleStrictParse$1.call(this, weekdayName, format, strict);
+ }
+
+ if (!this._weekdaysParse) {
+ this._weekdaysParse = [];
+ this._minWeekdaysParse = [];
+ this._shortWeekdaysParse = [];
+ this._fullWeekdaysParse = [];
+ }
+
+ for (i = 0; i < 7; i++) {
+ // make the regex if we don't have it already
+
+ mom = createUTC([2000, 1]).day(i);
+ if (strict && !this._fullWeekdaysParse[i]) {
+ this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
+ this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
+ this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
+ }
+ if (!this._weekdaysParse[i]) {
+ regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
+ return i;
+ } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
+ return i;
+ } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
+ return i;
+ } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
+ return i;
+ }
+ }
+}
+
+// MOMENTS
+
+function getSetDayOfWeek (input) {
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+ if (input != null) {
+ input = parseWeekday(input, this.localeData());
+ return this.add(input - day, 'd');
+ } else {
+ return day;
+ }
+}
+
+function getSetLocaleDayOfWeek (input) {
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
+ return input == null ? weekday : this.add(input - weekday, 'd');
+}
+
+function getSetISODayOfWeek (input) {
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+
+ // behaves the same as moment#day except
+ // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
+ // as a setter, sunday should belong to the previous week.
+
+ if (input != null) {
+ var weekday = parseIsoWeekday(input, this.localeData());
+ return this.day(this.day() % 7 ? weekday : weekday - 7);
+ } else {
+ return this.day() || 7;
+ }
+}
+
+var defaultWeekdaysRegex = matchWord;
+function weekdaysRegex (isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysStrictRegex;
+ } else {
+ return this._weekdaysRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ this._weekdaysRegex = defaultWeekdaysRegex;
+ }
+ return this._weekdaysStrictRegex && isStrict ?
+ this._weekdaysStrictRegex : this._weekdaysRegex;
+ }
+}
+
+var defaultWeekdaysShortRegex = matchWord;
+function weekdaysShortRegex (isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysShortStrictRegex;
+ } else {
+ return this._weekdaysShortRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysShortRegex')) {
+ this._weekdaysShortRegex = defaultWeekdaysShortRegex;
+ }
+ return this._weekdaysShortStrictRegex && isStrict ?
+ this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
+ }
+}
+
+var defaultWeekdaysMinRegex = matchWord;
+function weekdaysMinRegex (isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysMinStrictRegex;
+ } else {
+ return this._weekdaysMinRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysMinRegex')) {
+ this._weekdaysMinRegex = defaultWeekdaysMinRegex;
+ }
+ return this._weekdaysMinStrictRegex && isStrict ?
+ this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
+ }
+}
+
+
+function computeWeekdaysParse () {
+ function cmpLenRev(a, b) {
+ return b.length - a.length;
+ }
+
+ var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
+ i, mom, minp, shortp, longp;
+ for (i = 0; i < 7; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, 1]).day(i);
+ minp = this.weekdaysMin(mom, '');
+ shortp = this.weekdaysShort(mom, '');
+ longp = this.weekdays(mom, '');
+ minPieces.push(minp);
+ shortPieces.push(shortp);
+ longPieces.push(longp);
+ mixedPieces.push(minp);
+ mixedPieces.push(shortp);
+ mixedPieces.push(longp);
+ }
+ // Sorting makes sure if one weekday (or abbr) is a prefix of another it
+ // will match the longer piece.
+ minPieces.sort(cmpLenRev);
+ shortPieces.sort(cmpLenRev);
+ longPieces.sort(cmpLenRev);
+ mixedPieces.sort(cmpLenRev);
+ for (i = 0; i < 7; i++) {
+ shortPieces[i] = regexEscape(shortPieces[i]);
+ longPieces[i] = regexEscape(longPieces[i]);
+ mixedPieces[i] = regexEscape(mixedPieces[i]);
+ }
+
+ this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+ this._weekdaysShortRegex = this._weekdaysRegex;
+ this._weekdaysMinRegex = this._weekdaysRegex;
+
+ this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
+ this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
+ this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
+}
+
+// FORMATTING
+
+function hFormat() {
+ return this.hours() % 12 || 12;
+}
+
+function kFormat() {
+ return this.hours() || 24;
+}
+
+addFormatToken('H', ['HH', 2], 0, 'hour');
+addFormatToken('h', ['hh', 2], 0, hFormat);
+addFormatToken('k', ['kk', 2], 0, kFormat);
+
+addFormatToken('hmm', 0, 0, function () {
+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
+});
+
+addFormatToken('hmmss', 0, 0, function () {
+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
+ zeroFill(this.seconds(), 2);
+});
+
+addFormatToken('Hmm', 0, 0, function () {
+ return '' + this.hours() + zeroFill(this.minutes(), 2);
+});
+
+addFormatToken('Hmmss', 0, 0, function () {
+ return '' + this.hours() + zeroFill(this.minutes(), 2) +
+ zeroFill(this.seconds(), 2);
+});
+
+function meridiem (token, lowercase) {
+ addFormatToken(token, 0, 0, function () {
+ return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
+ });
+}
+
+meridiem('a', true);
+meridiem('A', false);
+
+// ALIASES
+
+addUnitAlias('hour', 'h');
+
+// PRIORITY
+addUnitPriority('hour', 13);
+
+// PARSING
+
+function matchMeridiem (isStrict, locale) {
+ return locale._meridiemParse;
+}
+
+addRegexToken('a', matchMeridiem);
+addRegexToken('A', matchMeridiem);
+addRegexToken('H', match1to2);
+addRegexToken('h', match1to2);
+addRegexToken('k', match1to2);
+addRegexToken('HH', match1to2, match2);
+addRegexToken('hh', match1to2, match2);
+addRegexToken('kk', match1to2, match2);
+
+addRegexToken('hmm', match3to4);
+addRegexToken('hmmss', match5to6);
+addRegexToken('Hmm', match3to4);
+addRegexToken('Hmmss', match5to6);
+
+addParseToken(['H', 'HH'], HOUR);
+addParseToken(['k', 'kk'], function (input, array, config) {
+ var kInput = toInt(input);
+ array[HOUR] = kInput === 24 ? 0 : kInput;
+});
+addParseToken(['a', 'A'], function (input, array, config) {
+ config._isPm = config._locale.isPM(input);
+ config._meridiem = input;
+});
+addParseToken(['h', 'hh'], function (input, array, config) {
+ array[HOUR] = toInt(input);
+ getParsingFlags(config).bigHour = true;
+});
+addParseToken('hmm', function (input, array, config) {
+ var pos = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos));
+ array[MINUTE] = toInt(input.substr(pos));
+ getParsingFlags(config).bigHour = true;
+});
+addParseToken('hmmss', function (input, array, config) {
+ var pos1 = input.length - 4;
+ var pos2 = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos1));
+ array[MINUTE] = toInt(input.substr(pos1, 2));
+ array[SECOND] = toInt(input.substr(pos2));
+ getParsingFlags(config).bigHour = true;
+});
+addParseToken('Hmm', function (input, array, config) {
+ var pos = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos));
+ array[MINUTE] = toInt(input.substr(pos));
+});
+addParseToken('Hmmss', function (input, array, config) {
+ var pos1 = input.length - 4;
+ var pos2 = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos1));
+ array[MINUTE] = toInt(input.substr(pos1, 2));
+ array[SECOND] = toInt(input.substr(pos2));
+});
+
+// LOCALES
+
+function localeIsPM (input) {
+ // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
+ // Using charAt should be more compatible.
+ return ((input + '').toLowerCase().charAt(0) === 'p');
+}
+
+var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
+function localeMeridiem (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'pm' : 'PM';
+ } else {
+ return isLower ? 'am' : 'AM';
+ }
+}
+
+
+// MOMENTS
+
+// Setting the hour should keep the time, because the user explicitly
+// specified which hour he wants. So trying to maintain the same hour (in
+// a new timezone) makes sense. Adding/subtracting hours does not follow
+// this rule.
+var getSetHour = makeGetSet('Hours', true);
+
+// months
+// week
+// weekdays
+// meridiem
+var baseConfig = {
+ calendar: defaultCalendar,
+ longDateFormat: defaultLongDateFormat,
+ invalidDate: defaultInvalidDate,
+ ordinal: defaultOrdinal,
+ dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
+ relativeTime: defaultRelativeTime,
+
+ months: defaultLocaleMonths,
+ monthsShort: defaultLocaleMonthsShort,
+
+ week: defaultLocaleWeek,
+
+ weekdays: defaultLocaleWeekdays,
+ weekdaysMin: defaultLocaleWeekdaysMin,
+ weekdaysShort: defaultLocaleWeekdaysShort,
+
+ meridiemParse: defaultLocaleMeridiemParse
+};
+
+// internal storage for locale config files
+var locales = {};
+var localeFamilies = {};
+var globalLocale;
+
+function normalizeLocale(key) {
+ return key ? key.toLowerCase().replace('_', '-') : key;
+}
+
+// pick the locale from the array
+// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
+// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
+function chooseLocale(names) {
+ var i = 0, j, next, locale, split;
+
+ while (i < names.length) {
+ split = normalizeLocale(names[i]).split('-');
+ j = split.length;
+ next = normalizeLocale(names[i + 1]);
+ next = next ? next.split('-') : null;
+ while (j > 0) {
+ locale = loadLocale(split.slice(0, j).join('-'));
+ if (locale) {
+ return locale;
+ }
+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
+ //the next array item is better than a shallower substring of this one
+ break;
+ }
+ j--;
+ }
+ i++;
+ }
+ return null;
+}
+
+function loadLocale(name) {
+ var oldLocale = null;
+ // TODO: Find a better way to register and load all the locales in Node
+ if (!locales[name] && (typeof module !== 'undefined') &&
+ module && module.exports) {
+ try {
+ oldLocale = globalLocale._abbr;
+ var aliasedRequire = require;
+ __webpack_require__(135)("./" + name);
+ getSetGlobalLocale(oldLocale);
+ } catch (e) {}
+ }
+ return locales[name];
+}
+
+// This function will load locale and then set the global locale. If
+// no arguments are passed in, it will simply return the current global
+// locale key.
+function getSetGlobalLocale (key, values) {
+ var data;
+ if (key) {
+ if (isUndefined(values)) {
+ data = getLocale(key);
+ }
+ else {
+ data = defineLocale(key, values);
+ }
+
+ if (data) {
+ // moment.duration._locale = moment._locale = data;
+ globalLocale = data;
+ }
+ }
+
+ return globalLocale._abbr;
+}
+
+function defineLocale (name, config) {
+ if (config !== null) {
+ var parentConfig = baseConfig;
+ config.abbr = name;
+ if (locales[name] != null) {
+ deprecateSimple('defineLocaleOverride',
+ 'use moment.updateLocale(localeName, config) to change ' +
+ 'an existing locale. moment.defineLocale(localeName, ' +
+ 'config) should only be used for creating a new locale ' +
+ 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
+ parentConfig = locales[name]._config;
+ } else if (config.parentLocale != null) {
+ if (locales[config.parentLocale] != null) {
+ parentConfig = locales[config.parentLocale]._config;
+ } else {
+ if (!localeFamilies[config.parentLocale]) {
+ localeFamilies[config.parentLocale] = [];
+ }
+ localeFamilies[config.parentLocale].push({
+ name: name,
+ config: config
+ });
+ return null;
+ }
+ }
+ locales[name] = new Locale(mergeConfigs(parentConfig, config));
+
+ if (localeFamilies[name]) {
+ localeFamilies[name].forEach(function (x) {
+ defineLocale(x.name, x.config);
+ });
+ }
+
+ // backwards compat for now: also set the locale
+ // make sure we set the locale AFTER all child locales have been
+ // created, so we won't end up with the child locale set.
+ getSetGlobalLocale(name);
+
+
+ return locales[name];
+ } else {
+ // useful for testing
+ delete locales[name];
+ return null;
+ }
+}
+
+function updateLocale(name, config) {
+ if (config != null) {
+ var locale, tmpLocale, parentConfig = baseConfig;
+ // MERGE
+ tmpLocale = loadLocale(name);
+ if (tmpLocale != null) {
+ parentConfig = tmpLocale._config;
+ }
+ config = mergeConfigs(parentConfig, config);
+ locale = new Locale(config);
+ locale.parentLocale = locales[name];
+ locales[name] = locale;
+
+ // backwards compat for now: also set the locale
+ getSetGlobalLocale(name);
+ } else {
+ // pass null for config to unupdate, useful for tests
+ if (locales[name] != null) {
+ if (locales[name].parentLocale != null) {
+ locales[name] = locales[name].parentLocale;
+ } else if (locales[name] != null) {
+ delete locales[name];
+ }
+ }
+ }
+ return locales[name];
+}
+
+// returns locale data
+function getLocale (key) {
+ var locale;
+
+ if (key && key._locale && key._locale._abbr) {
+ key = key._locale._abbr;
+ }
+
+ if (!key) {
+ return globalLocale;
+ }
+
+ if (!isArray(key)) {
+ //short-circuit everything else
+ locale = loadLocale(key);
+ if (locale) {
+ return locale;
+ }
+ key = [key];
+ }
+
+ return chooseLocale(key);
+}
+
+function listLocales() {
+ return keys(locales);
+}
+
+function checkOverflow (m) {
+ var overflow;
+ var a = m._a;
+
+ if (a && getParsingFlags(m).overflow === -2) {
+ overflow =
+ a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
+ a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
+ a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
+ a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
+ a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
+ a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
+ -1;
+
+ if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
+ overflow = DATE;
+ }
+ if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
+ overflow = WEEK;
+ }
+ if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
+ overflow = WEEKDAY;
+ }
+
+ getParsingFlags(m).overflow = overflow;
+ }
+
+ return m;
+}
+
+// Pick the first defined of two or three arguments.
+function defaults(a, b, c) {
+ if (a != null) {
+ return a;
+ }
+ if (b != null) {
+ return b;
+ }
+ return c;
+}
+
+function currentDateArray(config) {
+ // hooks is actually the exported moment object
+ var nowValue = new Date(hooks.now());
+ if (config._useUTC) {
+ return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
+ }
+ return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
+}
+
+// convert an array to a date.
+// the array should mirror the parameters below
+// note: all values past the year are optional and will default to the lowest possible value.
+// [year, month, day , hour, minute, second, millisecond]
+function configFromArray (config) {
+ var i, date, input = [], currentDate, expectedWeekday, yearToUse;
+
+ if (config._d) {
+ return;
+ }
+
+ currentDate = currentDateArray(config);
+
+ //compute day of the year from weeks and weekdays
+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
+ dayOfYearFromWeekInfo(config);
+ }
+
+ //if the day of the year is set, figure out what it is
+ if (config._dayOfYear != null) {
+ yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
+
+ if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
+ getParsingFlags(config)._overflowDayOfYear = true;
+ }
+
+ date = createUTCDate(yearToUse, 0, config._dayOfYear);
+ config._a[MONTH] = date.getUTCMonth();
+ config._a[DATE] = date.getUTCDate();
+ }
+
+ // Default to current date.
+ // * if no year, month, day of month are given, default to today
+ // * if day of month is given, default month and year
+ // * if month is given, default only year
+ // * if year is given, don't default anything
+ for (i = 0; i < 3 && config._a[i] == null; ++i) {
+ config._a[i] = input[i] = currentDate[i];
+ }
+
+ // Zero out whatever was not defaulted, including time
+ for (; i < 7; i++) {
+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+ }
+
+ // Check for 24:00:00.000
+ if (config._a[HOUR] === 24 &&
+ config._a[MINUTE] === 0 &&
+ config._a[SECOND] === 0 &&
+ config._a[MILLISECOND] === 0) {
+ config._nextDay = true;
+ config._a[HOUR] = 0;
+ }
+
+ config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
+ expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
+
+ // Apply timezone offset from input. The actual utcOffset can be changed
+ // with parseZone.
+ if (config._tzm != null) {
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+ }
+
+ if (config._nextDay) {
+ config._a[HOUR] = 24;
+ }
+
+ // check for mismatching day of week
+ if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) {
+ getParsingFlags(config).weekdayMismatch = true;
+ }
+}
+
+function dayOfYearFromWeekInfo(config) {
+ var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
+
+ w = config._w;
+ if (w.GG != null || w.W != null || w.E != null) {
+ dow = 1;
+ doy = 4;
+
+ // TODO: We need to take the current isoWeekYear, but that depends on
+ // how we interpret now (local, utc, fixed offset). So create
+ // a now version of current config (take local/utc/offset flags, and
+ // create now).
+ weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
+ week = defaults(w.W, 1);
+ weekday = defaults(w.E, 1);
+ if (weekday < 1 || weekday > 7) {
+ weekdayOverflow = true;
+ }
+ } else {
+ dow = config._locale._week.dow;
+ doy = config._locale._week.doy;
+
+ var curWeek = weekOfYear(createLocal(), dow, doy);
+
+ weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
+
+ // Default to current week.
+ week = defaults(w.w, curWeek.week);
+
+ if (w.d != null) {
+ // weekday -- low day numbers are considered next week
+ weekday = w.d;
+ if (weekday < 0 || weekday > 6) {
+ weekdayOverflow = true;
+ }
+ } else if (w.e != null) {
+ // local weekday -- counting starts from begining of week
+ weekday = w.e + dow;
+ if (w.e < 0 || w.e > 6) {
+ weekdayOverflow = true;
+ }
+ } else {
+ // default to begining of week
+ weekday = dow;
+ }
+ }
+ if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
+ getParsingFlags(config)._overflowWeeks = true;
+ } else if (weekdayOverflow != null) {
+ getParsingFlags(config)._overflowWeekday = true;
+ } else {
+ temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
+ config._a[YEAR] = temp.year;
+ config._dayOfYear = temp.dayOfYear;
+ }
+}
+
+// iso 8601 regex
+// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
+var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
+var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
+
+var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
+
+var isoDates = [
+ ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
+ ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
+ ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
+ ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
+ ['YYYY-DDD', /\d{4}-\d{3}/],
+ ['YYYY-MM', /\d{4}-\d\d/, false],
+ ['YYYYYYMMDD', /[+-]\d{10}/],
+ ['YYYYMMDD', /\d{8}/],
+ // YYYYMM is NOT allowed by the standard
+ ['GGGG[W]WWE', /\d{4}W\d{3}/],
+ ['GGGG[W]WW', /\d{4}W\d{2}/, false],
+ ['YYYYDDD', /\d{7}/]
+];
+
+// iso time formats and regexes
+var isoTimes = [
+ ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
+ ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
+ ['HH:mm:ss', /\d\d:\d\d:\d\d/],
+ ['HH:mm', /\d\d:\d\d/],
+ ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
+ ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
+ ['HHmmss', /\d\d\d\d\d\d/],
+ ['HHmm', /\d\d\d\d/],
+ ['HH', /\d\d/]
+];
+
+var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
+
+// date from iso format
+function configFromISO(config) {
+ var i, l,
+ string = config._i,
+ match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
+ allowTime, dateFormat, timeFormat, tzFormat;
+
+ if (match) {
+ getParsingFlags(config).iso = true;
+
+ for (i = 0, l = isoDates.length; i < l; i++) {
+ if (isoDates[i][1].exec(match[1])) {
+ dateFormat = isoDates[i][0];
+ allowTime = isoDates[i][2] !== false;
+ break;
+ }
+ }
+ if (dateFormat == null) {
+ config._isValid = false;
+ return;
+ }
+ if (match[3]) {
+ for (i = 0, l = isoTimes.length; i < l; i++) {
+ if (isoTimes[i][1].exec(match[3])) {
+ // match[2] should be 'T' or space
+ timeFormat = (match[2] || ' ') + isoTimes[i][0];
+ break;
+ }
+ }
+ if (timeFormat == null) {
+ config._isValid = false;
+ return;
+ }
+ }
+ if (!allowTime && timeFormat != null) {
+ config._isValid = false;
+ return;
+ }
+ if (match[4]) {
+ if (tzRegex.exec(match[4])) {
+ tzFormat = 'Z';
+ } else {
+ config._isValid = false;
+ return;
+ }
+ }
+ config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
+ configFromStringAndFormat(config);
+ } else {
+ config._isValid = false;
+ }
+}
+
+// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
+var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
+
+function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
+ var result = [
+ untruncateYear(yearStr),
+ defaultLocaleMonthsShort.indexOf(monthStr),
+ parseInt(dayStr, 10),
+ parseInt(hourStr, 10),
+ parseInt(minuteStr, 10)
+ ];
+
+ if (secondStr) {
+ result.push(parseInt(secondStr, 10));
+ }
+
+ return result;
+}
+
+function untruncateYear(yearStr) {
+ var year = parseInt(yearStr, 10);
+ if (year <= 49) {
+ return 2000 + year;
+ } else if (year <= 999) {
+ return 1900 + year;
+ }
+ return year;
+}
+
+function preprocessRFC2822(s) {
+ // Remove comments and folding whitespace and replace multiple-spaces with a single space
+ return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').trim();
+}
+
+function checkWeekday(weekdayStr, parsedInput, config) {
+ if (weekdayStr) {
+ // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
+ var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
+ weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
+ if (weekdayProvided !== weekdayActual) {
+ getParsingFlags(config).weekdayMismatch = true;
+ config._isValid = false;
+ return false;
+ }
+ }
+ return true;
+}
+
+var obsOffsets = {
+ UT: 0,
+ GMT: 0,
+ EDT: -4 * 60,
+ EST: -5 * 60,
+ CDT: -5 * 60,
+ CST: -6 * 60,
+ MDT: -6 * 60,
+ MST: -7 * 60,
+ PDT: -7 * 60,
+ PST: -8 * 60
+};
+
+function calculateOffset(obsOffset, militaryOffset, numOffset) {
+ if (obsOffset) {
+ return obsOffsets[obsOffset];
+ } else if (militaryOffset) {
+ // the only allowed military tz is Z
+ return 0;
+ } else {
+ var hm = parseInt(numOffset, 10);
+ var m = hm % 100, h = (hm - m) / 100;
+ return h * 60 + m;
+ }
+}
+
+// date and time from ref 2822 format
+function configFromRFC2822(config) {
+ var match = rfc2822.exec(preprocessRFC2822(config._i));
+ if (match) {
+ var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
+ if (!checkWeekday(match[1], parsedArray, config)) {
+ return;
+ }
+
+ config._a = parsedArray;
+ config._tzm = calculateOffset(match[8], match[9], match[10]);
+
+ config._d = createUTCDate.apply(null, config._a);
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+
+ getParsingFlags(config).rfc2822 = true;
+ } else {
+ config._isValid = false;
+ }
+}
+
+// date from iso format or fallback
+function configFromString(config) {
+ var matched = aspNetJsonRegex.exec(config._i);
+
+ if (matched !== null) {
+ config._d = new Date(+matched[1]);
+ return;
+ }
+
+ configFromISO(config);
+ if (config._isValid === false) {
+ delete config._isValid;
+ } else {
+ return;
+ }
+
+ configFromRFC2822(config);
+ if (config._isValid === false) {
+ delete config._isValid;
+ } else {
+ return;
+ }
+
+ // Final attempt, use Input Fallback
+ hooks.createFromInputFallback(config);
+}
+
+hooks.createFromInputFallback = deprecate(
+ 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
+ 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
+ 'discouraged and will be removed in an upcoming major release. Please refer to ' +
+ 'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
+ function (config) {
+ config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+ }
+);
+
+// constant that refers to the ISO standard
+hooks.ISO_8601 = function () {};
+
+// constant that refers to the RFC 2822 form
+hooks.RFC_2822 = function () {};
+
+// date from string and format string
+function configFromStringAndFormat(config) {
+ // TODO: Move this to another part of the creation flow to prevent circular deps
+ if (config._f === hooks.ISO_8601) {
+ configFromISO(config);
+ return;
+ }
+ if (config._f === hooks.RFC_2822) {
+ configFromRFC2822(config);
+ return;
+ }
+ config._a = [];
+ getParsingFlags(config).empty = true;
+
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
+ var string = '' + config._i,
+ i, parsedInput, tokens, token, skipped,
+ stringLength = string.length,
+ totalParsedInputLength = 0;
+
+ tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
+
+ for (i = 0; i < tokens.length; i++) {
+ token = tokens[i];
+ parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
+ // console.log('token', token, 'parsedInput', parsedInput,
+ // 'regex', getParseRegexForToken(token, config));
+ if (parsedInput) {
+ skipped = string.substr(0, string.indexOf(parsedInput));
+ if (skipped.length > 0) {
+ getParsingFlags(config).unusedInput.push(skipped);
+ }
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
+ totalParsedInputLength += parsedInput.length;
+ }
+ // don't parse if it's not a known token
+ if (formatTokenFunctions[token]) {
+ if (parsedInput) {
+ getParsingFlags(config).empty = false;
+ }
+ else {
+ getParsingFlags(config).unusedTokens.push(token);
+ }
+ addTimeToArrayFromToken(token, parsedInput, config);
+ }
+ else if (config._strict && !parsedInput) {
+ getParsingFlags(config).unusedTokens.push(token);
+ }
+ }
+
+ // add remaining unparsed input length to the string
+ getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
+ if (string.length > 0) {
+ getParsingFlags(config).unusedInput.push(string);
+ }
+
+ // clear _12h flag if hour is <= 12
+ if (config._a[HOUR] <= 12 &&
+ getParsingFlags(config).bigHour === true &&
+ config._a[HOUR] > 0) {
+ getParsingFlags(config).bigHour = undefined;
+ }
+
+ getParsingFlags(config).parsedDateParts = config._a.slice(0);
+ getParsingFlags(config).meridiem = config._meridiem;
+ // handle meridiem
+ config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
+
+ configFromArray(config);
+ checkOverflow(config);
+}
+
+
+function meridiemFixWrap (locale, hour, meridiem) {
+ var isPm;
+
+ if (meridiem == null) {
+ // nothing to do
+ return hour;
+ }
+ if (locale.meridiemHour != null) {
+ return locale.meridiemHour(hour, meridiem);
+ } else if (locale.isPM != null) {
+ // Fallback
+ isPm = locale.isPM(meridiem);
+ if (isPm && hour < 12) {
+ hour += 12;
+ }
+ if (!isPm && hour === 12) {
+ hour = 0;
+ }
+ return hour;
+ } else {
+ // this is not supposed to happen
+ return hour;
+ }
+}
+
+// date from string and array of format strings
+function configFromStringAndArray(config) {
+ var tempConfig,
+ bestMoment,
+
+ scoreToBeat,
+ i,
+ currentScore;
+
+ if (config._f.length === 0) {
+ getParsingFlags(config).invalidFormat = true;
+ config._d = new Date(NaN);
+ return;
+ }
+
+ for (i = 0; i < config._f.length; i++) {
+ currentScore = 0;
+ tempConfig = copyConfig({}, config);
+ if (config._useUTC != null) {
+ tempConfig._useUTC = config._useUTC;
+ }
+ tempConfig._f = config._f[i];
+ configFromStringAndFormat(tempConfig);
+
+ if (!isValid(tempConfig)) {
+ continue;
+ }
+
+ // if there is any input that was not parsed add a penalty for that format
+ currentScore += getParsingFlags(tempConfig).charsLeftOver;
+
+ //or tokens
+ currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
+
+ getParsingFlags(tempConfig).score = currentScore;
+
+ if (scoreToBeat == null || currentScore < scoreToBeat) {
+ scoreToBeat = currentScore;
+ bestMoment = tempConfig;
+ }
+ }
+
+ extend(config, bestMoment || tempConfig);
+}
+
+function configFromObject(config) {
+ if (config._d) {
+ return;
+ }
+
+ var i = normalizeObjectUnits(config._i);
+ config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
+ return obj && parseInt(obj, 10);
+ });
+
+ configFromArray(config);
+}
+
+function createFromConfig (config) {
+ var res = new Moment(checkOverflow(prepareConfig(config)));
+ if (res._nextDay) {
+ // Adding is smart enough around DST
+ res.add(1, 'd');
+ res._nextDay = undefined;
+ }
+
+ return res;
+}
+
+function prepareConfig (config) {
+ var input = config._i,
+ format = config._f;
+
+ config._locale = config._locale || getLocale(config._l);
+
+ if (input === null || (format === undefined && input === '')) {
+ return createInvalid({nullInput: true});
+ }
+
+ if (typeof input === 'string') {
+ config._i = input = config._locale.preparse(input);
+ }
+
+ if (isMoment(input)) {
+ return new Moment(checkOverflow(input));
+ } else if (isDate(input)) {
+ config._d = input;
+ } else if (isArray(format)) {
+ configFromStringAndArray(config);
+ } else if (format) {
+ configFromStringAndFormat(config);
+ } else {
+ configFromInput(config);
+ }
+
+ if (!isValid(config)) {
+ config._d = null;
+ }
+
+ return config;
+}
+
+function configFromInput(config) {
+ var input = config._i;
+ if (isUndefined(input)) {
+ config._d = new Date(hooks.now());
+ } else if (isDate(input)) {
+ config._d = new Date(input.valueOf());
+ } else if (typeof input === 'string') {
+ configFromString(config);
+ } else if (isArray(input)) {
+ config._a = map(input.slice(0), function (obj) {
+ return parseInt(obj, 10);
+ });
+ configFromArray(config);
+ } else if (isObject(input)) {
+ configFromObject(config);
+ } else if (isNumber(input)) {
+ // from milliseconds
+ config._d = new Date(input);
+ } else {
+ hooks.createFromInputFallback(config);
+ }
+}
+
+function createLocalOrUTC (input, format, locale, strict, isUTC) {
+ var c = {};
+
+ if (locale === true || locale === false) {
+ strict = locale;
+ locale = undefined;
+ }
+
+ if ((isObject(input) && isObjectEmpty(input)) ||
+ (isArray(input) && input.length === 0)) {
+ input = undefined;
+ }
+ // object construction must be done this way.
+ // https://github.com/moment/moment/issues/1423
+ c._isAMomentObject = true;
+ c._useUTC = c._isUTC = isUTC;
+ c._l = locale;
+ c._i = input;
+ c._f = format;
+ c._strict = strict;
+
+ return createFromConfig(c);
+}
+
+function createLocal (input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, false);
+}
+
+var prototypeMin = deprecate(
+ 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
+ function () {
+ var other = createLocal.apply(null, arguments);
+ if (this.isValid() && other.isValid()) {
+ return other < this ? this : other;
+ } else {
+ return createInvalid();
+ }
+ }
+);
+
+var prototypeMax = deprecate(
+ 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
+ function () {
+ var other = createLocal.apply(null, arguments);
+ if (this.isValid() && other.isValid()) {
+ return other > this ? this : other;
+ } else {
+ return createInvalid();
+ }
+ }
+);
+
+// Pick a moment m from moments so that m[fn](other) is true for all
+// other. This relies on the function fn to be transitive.
+//
+// moments should either be an array of moment objects or an array, whose
+// first element is an array of moment objects.
+function pickBy(fn, moments) {
+ var res, i;
+ if (moments.length === 1 && isArray(moments[0])) {
+ moments = moments[0];
+ }
+ if (!moments.length) {
+ return createLocal();
+ }
+ res = moments[0];
+ for (i = 1; i < moments.length; ++i) {
+ if (!moments[i].isValid() || moments[i][fn](res)) {
+ res = moments[i];
+ }
+ }
+ return res;
+}
+
+// TODO: Use [].sort instead?
+function min () {
+ var args = [].slice.call(arguments, 0);
+
+ return pickBy('isBefore', args);
+}
+
+function max () {
+ var args = [].slice.call(arguments, 0);
+
+ return pickBy('isAfter', args);
+}
+
+var now = function () {
+ return Date.now ? Date.now() : +(new Date());
+};
+
+var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
+
+function isDurationValid(m) {
+ for (var key in m) {
+ if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
+ return false;
+ }
+ }
+
+ var unitHasDecimal = false;
+ for (var i = 0; i < ordering.length; ++i) {
+ if (m[ordering[i]]) {
+ if (unitHasDecimal) {
+ return false; // only allow non-integers for smallest unit
+ }
+ if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
+ unitHasDecimal = true;
+ }
+ }
+ }
+
+ return true;
+}
+
+function isValid$1() {
+ return this._isValid;
+}
+
+function createInvalid$1() {
+ return createDuration(NaN);
+}
+
+function Duration (duration) {
+ var normalizedInput = normalizeObjectUnits(duration),
+ years = normalizedInput.year || 0,
+ quarters = normalizedInput.quarter || 0,
+ months = normalizedInput.month || 0,
+ weeks = normalizedInput.week || 0,
+ days = normalizedInput.day || 0,
+ hours = normalizedInput.hour || 0,
+ minutes = normalizedInput.minute || 0,
+ seconds = normalizedInput.second || 0,
+ milliseconds = normalizedInput.millisecond || 0;
+
+ this._isValid = isDurationValid(normalizedInput);
+
+ // representation for dateAddRemove
+ this._milliseconds = +milliseconds +
+ seconds * 1e3 + // 1000
+ minutes * 6e4 + // 1000 * 60
+ hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
+ // Because of dateAddRemove treats 24 hours as different from a
+ // day when working around DST, we need to store them separately
+ this._days = +days +
+ weeks * 7;
+ // It is impossible to translate months into days without knowing
+ // which months you are are talking about, so we have to store
+ // it separately.
+ this._months = +months +
+ quarters * 3 +
+ years * 12;
+
+ this._data = {};
+
+ this._locale = getLocale();
+
+ this._bubble();
+}
+
+function isDuration (obj) {
+ return obj instanceof Duration;
+}
+
+function absRound (number) {
+ if (number < 0) {
+ return Math.round(-1 * number) * -1;
+ } else {
+ return Math.round(number);
+ }
+}
+
+// FORMATTING
+
+function offset (token, separator) {
+ addFormatToken(token, 0, 0, function () {
+ var offset = this.utcOffset();
+ var sign = '+';
+ if (offset < 0) {
+ offset = -offset;
+ sign = '-';
+ }
+ return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
+ });
+}
+
+offset('Z', ':');
+offset('ZZ', '');
+
+// PARSING
+
+addRegexToken('Z', matchShortOffset);
+addRegexToken('ZZ', matchShortOffset);
+addParseToken(['Z', 'ZZ'], function (input, array, config) {
+ config._useUTC = true;
+ config._tzm = offsetFromString(matchShortOffset, input);
+});
+
+// HELPERS
+
+// timezone chunker
+// '+10:00' > ['10', '00']
+// '-1530' > ['-15', '30']
+var chunkOffset = /([\+\-]|\d\d)/gi;
+
+function offsetFromString(matcher, string) {
+ var matches = (string || '').match(matcher);
+
+ if (matches === null) {
+ return null;
+ }
+
+ var chunk = matches[matches.length - 1] || [];
+ var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
+ var minutes = +(parts[1] * 60) + toInt(parts[2]);
+
+ return minutes === 0 ?
+ 0 :
+ parts[0] === '+' ? minutes : -minutes;
+}
+
+// Return a moment from input, that is local/utc/zone equivalent to model.
+function cloneWithOffset(input, model) {
+ var res, diff;
+ if (model._isUTC) {
+ res = model.clone();
+ diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
+ // Use low-level api, because this fn is low-level api.
+ res._d.setTime(res._d.valueOf() + diff);
+ hooks.updateOffset(res, false);
+ return res;
+ } else {
+ return createLocal(input).local();
+ }
+}
+
+function getDateOffset (m) {
+ // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+ // https://github.com/moment/moment/pull/1871
+ return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
+}
+
+// HOOKS
+
+// This function will be called whenever a moment is mutated.
+// It is intended to keep the offset in sync with the timezone.
+hooks.updateOffset = function () {};
+
+// MOMENTS
+
+// keepLocalTime = true means only change the timezone, without
+// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
+// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
+// +0200, so we adjust the time as needed, to be valid.
+//
+// Keeping the time actually adds/subtracts (one hour)
+// from the actual represented time. That is why we call updateOffset
+// a second time. In case it wants us to change the offset again
+// _changeInProgress == true case, then we have to adjust, because
+// there is no such time in the given timezone.
+function getSetOffset (input, keepLocalTime, keepMinutes) {
+ var offset = this._offset || 0,
+ localAdjust;
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ if (input != null) {
+ if (typeof input === 'string') {
+ input = offsetFromString(matchShortOffset, input);
+ if (input === null) {
+ return this;
+ }
+ } else if (Math.abs(input) < 16 && !keepMinutes) {
+ input = input * 60;
+ }
+ if (!this._isUTC && keepLocalTime) {
+ localAdjust = getDateOffset(this);
+ }
+ this._offset = input;
+ this._isUTC = true;
+ if (localAdjust != null) {
+ this.add(localAdjust, 'm');
+ }
+ if (offset !== input) {
+ if (!keepLocalTime || this._changeInProgress) {
+ addSubtract(this, createDuration(input - offset, 'm'), 1, false);
+ } else if (!this._changeInProgress) {
+ this._changeInProgress = true;
+ hooks.updateOffset(this, true);
+ this._changeInProgress = null;
+ }
+ }
+ return this;
+ } else {
+ return this._isUTC ? offset : getDateOffset(this);
+ }
+}
+
+function getSetZone (input, keepLocalTime) {
+ if (input != null) {
+ if (typeof input !== 'string') {
+ input = -input;
+ }
+
+ this.utcOffset(input, keepLocalTime);
+
+ return this;
+ } else {
+ return -this.utcOffset();
+ }
+}
+
+function setOffsetToUTC (keepLocalTime) {
+ return this.utcOffset(0, keepLocalTime);
+}
+
+function setOffsetToLocal (keepLocalTime) {
+ if (this._isUTC) {
+ this.utcOffset(0, keepLocalTime);
+ this._isUTC = false;
+
+ if (keepLocalTime) {
+ this.subtract(getDateOffset(this), 'm');
+ }
+ }
+ return this;
+}
+
+function setOffsetToParsedOffset () {
+ if (this._tzm != null) {
+ this.utcOffset(this._tzm, false, true);
+ } else if (typeof this._i === 'string') {
+ var tZone = offsetFromString(matchOffset, this._i);
+ if (tZone != null) {
+ this.utcOffset(tZone);
+ }
+ else {
+ this.utcOffset(0, true);
+ }
+ }
+ return this;
+}
+
+function hasAlignedHourOffset (input) {
+ if (!this.isValid()) {
+ return false;
+ }
+ input = input ? createLocal(input).utcOffset() : 0;
+
+ return (this.utcOffset() - input) % 60 === 0;
+}
+
+function isDaylightSavingTime () {
+ return (
+ this.utcOffset() > this.clone().month(0).utcOffset() ||
+ this.utcOffset() > this.clone().month(5).utcOffset()
+ );
+}
+
+function isDaylightSavingTimeShifted () {
+ if (!isUndefined(this._isDSTShifted)) {
+ return this._isDSTShifted;
+ }
+
+ var c = {};
+
+ copyConfig(c, this);
+ c = prepareConfig(c);
+
+ if (c._a) {
+ var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
+ this._isDSTShifted = this.isValid() &&
+ compareArrays(c._a, other.toArray()) > 0;
+ } else {
+ this._isDSTShifted = false;
+ }
+
+ return this._isDSTShifted;
+}
+
+function isLocal () {
+ return this.isValid() ? !this._isUTC : false;
+}
+
+function isUtcOffset () {
+ return this.isValid() ? this._isUTC : false;
+}
+
+function isUtc () {
+ return this.isValid() ? this._isUTC && this._offset === 0 : false;
+}
+
+// ASP.NET json date format regex
+var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
+
+// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
+// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
+// and further modified to allow for strings containing both week and day
+var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
+
+function createDuration (input, key) {
+ var duration = input,
+ // matching against regexp is expensive, do it on demand
+ match = null,
+ sign,
+ ret,
+ diffRes;
+
+ if (isDuration(input)) {
+ duration = {
+ ms : input._milliseconds,
+ d : input._days,
+ M : input._months
+ };
+ } else if (isNumber(input)) {
+ duration = {};
+ if (key) {
+ duration[key] = input;
+ } else {
+ duration.milliseconds = input;
+ }
+ } else if (!!(match = aspNetRegex.exec(input))) {
+ sign = (match[1] === '-') ? -1 : 1;
+ duration = {
+ y : 0,
+ d : toInt(match[DATE]) * sign,
+ h : toInt(match[HOUR]) * sign,
+ m : toInt(match[MINUTE]) * sign,
+ s : toInt(match[SECOND]) * sign,
+ ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
+ };
+ } else if (!!(match = isoRegex.exec(input))) {
+ sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
+ duration = {
+ y : parseIso(match[2], sign),
+ M : parseIso(match[3], sign),
+ w : parseIso(match[4], sign),
+ d : parseIso(match[5], sign),
+ h : parseIso(match[6], sign),
+ m : parseIso(match[7], sign),
+ s : parseIso(match[8], sign)
+ };
+ } else if (duration == null) {// checks for null or undefined
+ duration = {};
+ } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
+ diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
+
+ duration = {};
+ duration.ms = diffRes.milliseconds;
+ duration.M = diffRes.months;
+ }
+
+ ret = new Duration(duration);
+
+ if (isDuration(input) && hasOwnProp(input, '_locale')) {
+ ret._locale = input._locale;
+ }
+
+ return ret;
+}
+
+createDuration.fn = Duration.prototype;
+createDuration.invalid = createInvalid$1;
+
+function parseIso (inp, sign) {
+ // We'd normally use ~~inp for this, but unfortunately it also
+ // converts floats to ints.
+ // inp may be undefined, so careful calling replace on it.
+ var res = inp && parseFloat(inp.replace(',', '.'));
+ // apply sign while we're at it
+ return (isNaN(res) ? 0 : res) * sign;
+}
+
+function positiveMomentsDifference(base, other) {
+ var res = {milliseconds: 0, months: 0};
+
+ res.months = other.month() - base.month() +
+ (other.year() - base.year()) * 12;
+ if (base.clone().add(res.months, 'M').isAfter(other)) {
+ --res.months;
+ }
+
+ res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
+
+ return res;
+}
+
+function momentsDifference(base, other) {
+ var res;
+ if (!(base.isValid() && other.isValid())) {
+ return {milliseconds: 0, months: 0};
+ }
+
+ other = cloneWithOffset(other, base);
+ if (base.isBefore(other)) {
+ res = positiveMomentsDifference(base, other);
+ } else {
+ res = positiveMomentsDifference(other, base);
+ res.milliseconds = -res.milliseconds;
+ res.months = -res.months;
+ }
+
+ return res;
+}
+
+// TODO: remove 'name' arg after deprecation is removed
+function createAdder(direction, name) {
+ return function (val, period) {
+ var dur, tmp;
+ //invert the arguments, but complain about it
+ if (period !== null && !isNaN(+period)) {
+ deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
+ 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
+ tmp = val; val = period; period = tmp;
+ }
+
+ val = typeof val === 'string' ? +val : val;
+ dur = createDuration(val, period);
+ addSubtract(this, dur, direction);
+ return this;
+ };
+}
+
+function addSubtract (mom, duration, isAdding, updateOffset) {
+ var milliseconds = duration._milliseconds,
+ days = absRound(duration._days),
+ months = absRound(duration._months);
+
+ if (!mom.isValid()) {
+ // No op
+ return;
+ }
+
+ updateOffset = updateOffset == null ? true : updateOffset;
+
+ if (months) {
+ setMonth(mom, get(mom, 'Month') + months * isAdding);
+ }
+ if (days) {
+ set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
+ }
+ if (milliseconds) {
+ mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
+ }
+ if (updateOffset) {
+ hooks.updateOffset(mom, days || months);
+ }
+}
+
+var add = createAdder(1, 'add');
+var subtract = createAdder(-1, 'subtract');
+
+function getCalendarFormat(myMoment, now) {
+ var diff = myMoment.diff(now, 'days', true);
+ return diff < -6 ? 'sameElse' :
+ diff < -1 ? 'lastWeek' :
+ diff < 0 ? 'lastDay' :
+ diff < 1 ? 'sameDay' :
+ diff < 2 ? 'nextDay' :
+ diff < 7 ? 'nextWeek' : 'sameElse';
+}
+
+function calendar$1 (time, formats) {
+ // We want to compare the start of today, vs this.
+ // Getting start-of-today depends on whether we're local/utc/offset or not.
+ var now = time || createLocal(),
+ sod = cloneWithOffset(now, this).startOf('day'),
+ format = hooks.calendarFormat(this, sod) || 'sameElse';
+
+ var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
+
+ return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
+}
+
+function clone () {
+ return new Moment(this);
+}
+
+function isAfter (input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input);
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
+ if (units === 'millisecond') {
+ return this.valueOf() > localInput.valueOf();
+ } else {
+ return localInput.valueOf() < this.clone().startOf(units).valueOf();
+ }
+}
+
+function isBefore (input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input);
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
+ if (units === 'millisecond') {
+ return this.valueOf() < localInput.valueOf();
+ } else {
+ return this.clone().endOf(units).valueOf() < localInput.valueOf();
+ }
+}
+
+function isBetween (from, to, units, inclusivity) {
+ inclusivity = inclusivity || '()';
+ return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
+ (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
+}
+
+function isSame (input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input),
+ inputMs;
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(units || 'millisecond');
+ if (units === 'millisecond') {
+ return this.valueOf() === localInput.valueOf();
+ } else {
+ inputMs = localInput.valueOf();
+ return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
+ }
+}
+
+function isSameOrAfter (input, units) {
+ return this.isSame(input, units) || this.isAfter(input,units);
+}
+
+function isSameOrBefore (input, units) {
+ return this.isSame(input, units) || this.isBefore(input,units);
+}
+
+function diff (input, units, asFloat) {
+ var that,
+ zoneDelta,
+ delta, output;
+
+ if (!this.isValid()) {
+ return NaN;
+ }
+
+ that = cloneWithOffset(input, this);
+
+ if (!that.isValid()) {
+ return NaN;
+ }
+
+ zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
+
+ units = normalizeUnits(units);
+
+ switch (units) {
+ case 'year': output = monthDiff(this, that) / 12; break;
+ case 'month': output = monthDiff(this, that); break;
+ case 'quarter': output = monthDiff(this, that) / 3; break;
+ case 'second': output = (this - that) / 1e3; break; // 1000
+ case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
+ case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
+ case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
+ case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
+ default: output = this - that;
+ }
+
+ return asFloat ? output : absFloor(output);
+}
+
+function monthDiff (a, b) {
+ // difference in months
+ var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
+ // b is in (anchor - 1 month, anchor + 1 month)
+ anchor = a.clone().add(wholeMonthDiff, 'months'),
+ anchor2, adjust;
+
+ if (b - anchor < 0) {
+ anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
+ // linear across the month
+ adjust = (b - anchor) / (anchor - anchor2);
+ } else {
+ anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
+ // linear across the month
+ adjust = (b - anchor) / (anchor2 - anchor);
+ }
+
+ //check for negative zero, return zero if negative zero
+ return -(wholeMonthDiff + adjust) || 0;
+}
+
+hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
+hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
+
+function toString () {
+ return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
+}
+
+function toISOString(keepOffset) {
+ if (!this.isValid()) {
+ return null;
+ }
+ var utc = keepOffset !== true;
+ var m = utc ? this.clone().utc() : this;
+ if (m.year() < 0 || m.year() > 9999) {
+ return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ');
+ }
+ if (isFunction(Date.prototype.toISOString)) {
+ // native implementation is ~50x faster, use it when we can
+ if (utc) {
+ return this.toDate().toISOString();
+ } else {
+ return new Date(this._d.valueOf()).toISOString().replace('Z', formatMoment(m, 'Z'));
+ }
+ }
+ return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ');
+}
+
+/**
+ * Return a human readable representation of a moment that can
+ * also be evaluated to get a new moment which is the same
+ *
+ * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
+ */
+function inspect () {
+ if (!this.isValid()) {
+ return 'moment.invalid(/* ' + this._i + ' */)';
+ }
+ var func = 'moment';
+ var zone = '';
+ if (!this.isLocal()) {
+ func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
+ zone = 'Z';
+ }
+ var prefix = '[' + func + '("]';
+ var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
+ var datetime = '-MM-DD[T]HH:mm:ss.SSS';
+ var suffix = zone + '[")]';
+
+ return this.format(prefix + year + datetime + suffix);
+}
+
+function format (inputString) {
+ if (!inputString) {
+ inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
+ }
+ var output = formatMoment(this, inputString);
+ return this.localeData().postformat(output);
+}
+
+function from (time, withoutSuffix) {
+ if (this.isValid() &&
+ ((isMoment(time) && time.isValid()) ||
+ createLocal(time).isValid())) {
+ return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
+ } else {
+ return this.localeData().invalidDate();
+ }
+}
+
+function fromNow (withoutSuffix) {
+ return this.from(createLocal(), withoutSuffix);
+}
+
+function to (time, withoutSuffix) {
+ if (this.isValid() &&
+ ((isMoment(time) && time.isValid()) ||
+ createLocal(time).isValid())) {
+ return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
+ } else {
+ return this.localeData().invalidDate();
+ }
+}
+
+function toNow (withoutSuffix) {
+ return this.to(createLocal(), withoutSuffix);
+}
+
+// If passed a locale key, it will set the locale for this
+// instance. Otherwise, it will return the locale configuration
+// variables for this instance.
+function locale (key) {
+ var newLocaleData;
+
+ if (key === undefined) {
+ return this._locale._abbr;
+ } else {
+ newLocaleData = getLocale(key);
+ if (newLocaleData != null) {
+ this._locale = newLocaleData;
+ }
+ return this;
+ }
+}
+
+var lang = deprecate(
+ 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
+ function (key) {
+ if (key === undefined) {
+ return this.localeData();
+ } else {
+ return this.locale(key);
+ }
+ }
+);
+
+function localeData () {
+ return this._locale;
+}
+
+function startOf (units) {
+ units = normalizeUnits(units);
+ // the following switch intentionally omits break keywords
+ // to utilize falling through the cases.
+ switch (units) {
+ case 'year':
+ this.month(0);
+ /* falls through */
+ case 'quarter':
+ case 'month':
+ this.date(1);
+ /* falls through */
+ case 'week':
+ case 'isoWeek':
+ case 'day':
+ case 'date':
+ this.hours(0);
+ /* falls through */
+ case 'hour':
+ this.minutes(0);
+ /* falls through */
+ case 'minute':
+ this.seconds(0);
+ /* falls through */
+ case 'second':
+ this.milliseconds(0);
+ }
+
+ // weeks are a special case
+ if (units === 'week') {
+ this.weekday(0);
+ }
+ if (units === 'isoWeek') {
+ this.isoWeekday(1);
+ }
+
+ // quarters are also special
+ if (units === 'quarter') {
+ this.month(Math.floor(this.month() / 3) * 3);
+ }
+
+ return this;
+}
+
+function endOf (units) {
+ units = normalizeUnits(units);
+ if (units === undefined || units === 'millisecond') {
+ return this;
+ }
+
+ // 'date' is an alias for 'day', so it should be considered as such.
+ if (units === 'date') {
+ units = 'day';
+ }
+
+ return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
+}
+
+function valueOf () {
+ return this._d.valueOf() - ((this._offset || 0) * 60000);
+}
+
+function unix () {
+ return Math.floor(this.valueOf() / 1000);
+}
+
+function toDate () {
+ return new Date(this.valueOf());
+}
+
+function toArray () {
+ var m = this;
+ return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
+}
+
+function toObject () {
+ var m = this;
+ return {
+ years: m.year(),
+ months: m.month(),
+ date: m.date(),
+ hours: m.hours(),
+ minutes: m.minutes(),
+ seconds: m.seconds(),
+ milliseconds: m.milliseconds()
+ };
+}
+
+function toJSON () {
+ // new Date(NaN).toJSON() === null
+ return this.isValid() ? this.toISOString() : null;
+}
+
+function isValid$2 () {
+ return isValid(this);
+}
+
+function parsingFlags () {
+ return extend({}, getParsingFlags(this));
+}
+
+function invalidAt () {
+ return getParsingFlags(this).overflow;
+}
+
+function creationData() {
+ return {
+ input: this._i,
+ format: this._f,
+ locale: this._locale,
+ isUTC: this._isUTC,
+ strict: this._strict
+ };
+}
+
+// FORMATTING
+
+addFormatToken(0, ['gg', 2], 0, function () {
+ return this.weekYear() % 100;
+});
+
+addFormatToken(0, ['GG', 2], 0, function () {
+ return this.isoWeekYear() % 100;
+});
+
+function addWeekYearFormatToken (token, getter) {
+ addFormatToken(0, [token, token.length], 0, getter);
+}
+
+addWeekYearFormatToken('gggg', 'weekYear');
+addWeekYearFormatToken('ggggg', 'weekYear');
+addWeekYearFormatToken('GGGG', 'isoWeekYear');
+addWeekYearFormatToken('GGGGG', 'isoWeekYear');
+
+// ALIASES
+
+addUnitAlias('weekYear', 'gg');
+addUnitAlias('isoWeekYear', 'GG');
+
+// PRIORITY
+
+addUnitPriority('weekYear', 1);
+addUnitPriority('isoWeekYear', 1);
+
+
+// PARSING
+
+addRegexToken('G', matchSigned);
+addRegexToken('g', matchSigned);
+addRegexToken('GG', match1to2, match2);
+addRegexToken('gg', match1to2, match2);
+addRegexToken('GGGG', match1to4, match4);
+addRegexToken('gggg', match1to4, match4);
+addRegexToken('GGGGG', match1to6, match6);
+addRegexToken('ggggg', match1to6, match6);
+
+addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
+ week[token.substr(0, 2)] = toInt(input);
+});
+
+addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
+ week[token] = hooks.parseTwoDigitYear(input);
+});
+
+// MOMENTS
+
+function getSetWeekYear (input) {
+ return getSetWeekYearHelper.call(this,
+ input,
+ this.week(),
+ this.weekday(),
+ this.localeData()._week.dow,
+ this.localeData()._week.doy);
+}
+
+function getSetISOWeekYear (input) {
+ return getSetWeekYearHelper.call(this,
+ input, this.isoWeek(), this.isoWeekday(), 1, 4);
+}
+
+function getISOWeeksInYear () {
+ return weeksInYear(this.year(), 1, 4);
+}
+
+function getWeeksInYear () {
+ var weekInfo = this.localeData()._week;
+ return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
+}
+
+function getSetWeekYearHelper(input, week, weekday, dow, doy) {
+ var weeksTarget;
+ if (input == null) {
+ return weekOfYear(this, dow, doy).year;
+ } else {
+ weeksTarget = weeksInYear(input, dow, doy);
+ if (week > weeksTarget) {
+ week = weeksTarget;
+ }
+ return setWeekAll.call(this, input, week, weekday, dow, doy);
+ }
+}
+
+function setWeekAll(weekYear, week, weekday, dow, doy) {
+ var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
+ date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
+
+ this.year(date.getUTCFullYear());
+ this.month(date.getUTCMonth());
+ this.date(date.getUTCDate());
+ return this;
+}
+
+// FORMATTING
+
+addFormatToken('Q', 0, 'Qo', 'quarter');
+
+// ALIASES
+
+addUnitAlias('quarter', 'Q');
+
+// PRIORITY
+
+addUnitPriority('quarter', 7);
+
+// PARSING
+
+addRegexToken('Q', match1);
+addParseToken('Q', function (input, array) {
+ array[MONTH] = (toInt(input) - 1) * 3;
+});
+
+// MOMENTS
+
+function getSetQuarter (input) {
+ return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
+}
+
+// FORMATTING
+
+addFormatToken('D', ['DD', 2], 'Do', 'date');
+
+// ALIASES
+
+addUnitAlias('date', 'D');
+
+// PRIOROITY
+addUnitPriority('date', 9);
+
+// PARSING
+
+addRegexToken('D', match1to2);
+addRegexToken('DD', match1to2, match2);
+addRegexToken('Do', function (isStrict, locale) {
+ // TODO: Remove "ordinalParse" fallback in next major release.
+ return isStrict ?
+ (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
+ locale._dayOfMonthOrdinalParseLenient;
+});
+
+addParseToken(['D', 'DD'], DATE);
+addParseToken('Do', function (input, array) {
+ array[DATE] = toInt(input.match(match1to2)[0]);
+});
+
+// MOMENTS
+
+var getSetDayOfMonth = makeGetSet('Date', true);
+
+// FORMATTING
+
+addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
+
+// ALIASES
+
+addUnitAlias('dayOfYear', 'DDD');
+
+// PRIORITY
+addUnitPriority('dayOfYear', 4);
+
+// PARSING
+
+addRegexToken('DDD', match1to3);
+addRegexToken('DDDD', match3);
+addParseToken(['DDD', 'DDDD'], function (input, array, config) {
+ config._dayOfYear = toInt(input);
+});
+
+// HELPERS
+
+// MOMENTS
+
+function getSetDayOfYear (input) {
+ var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
+ return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
+}
+
+// FORMATTING
+
+addFormatToken('m', ['mm', 2], 0, 'minute');
+
+// ALIASES
+
+addUnitAlias('minute', 'm');
+
+// PRIORITY
+
+addUnitPriority('minute', 14);
+
+// PARSING
+
+addRegexToken('m', match1to2);
+addRegexToken('mm', match1to2, match2);
+addParseToken(['m', 'mm'], MINUTE);
+
+// MOMENTS
+
+var getSetMinute = makeGetSet('Minutes', false);
+
+// FORMATTING
+
+addFormatToken('s', ['ss', 2], 0, 'second');
+
+// ALIASES
+
+addUnitAlias('second', 's');
+
+// PRIORITY
+
+addUnitPriority('second', 15);
+
+// PARSING
+
+addRegexToken('s', match1to2);
+addRegexToken('ss', match1to2, match2);
+addParseToken(['s', 'ss'], SECOND);
+
+// MOMENTS
+
+var getSetSecond = makeGetSet('Seconds', false);
+
+// FORMATTING
+
+addFormatToken('S', 0, 0, function () {
+ return ~~(this.millisecond() / 100);
+});
+
+addFormatToken(0, ['SS', 2], 0, function () {
+ return ~~(this.millisecond() / 10);
+});
+
+addFormatToken(0, ['SSS', 3], 0, 'millisecond');
+addFormatToken(0, ['SSSS', 4], 0, function () {
+ return this.millisecond() * 10;
+});
+addFormatToken(0, ['SSSSS', 5], 0, function () {
+ return this.millisecond() * 100;
+});
+addFormatToken(0, ['SSSSSS', 6], 0, function () {
+ return this.millisecond() * 1000;
+});
+addFormatToken(0, ['SSSSSSS', 7], 0, function () {
+ return this.millisecond() * 10000;
+});
+addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
+ return this.millisecond() * 100000;
+});
+addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
+ return this.millisecond() * 1000000;
+});
+
+
+// ALIASES
+
+addUnitAlias('millisecond', 'ms');
+
+// PRIORITY
+
+addUnitPriority('millisecond', 16);
+
+// PARSING
+
+addRegexToken('S', match1to3, match1);
+addRegexToken('SS', match1to3, match2);
+addRegexToken('SSS', match1to3, match3);
+
+var token;
+for (token = 'SSSS'; token.length <= 9; token += 'S') {
+ addRegexToken(token, matchUnsigned);
+}
+
+function parseMs(input, array) {
+ array[MILLISECOND] = toInt(('0.' + input) * 1000);
+}
+
+for (token = 'S'; token.length <= 9; token += 'S') {
+ addParseToken(token, parseMs);
+}
+// MOMENTS
+
+var getSetMillisecond = makeGetSet('Milliseconds', false);
+
+// FORMATTING
+
+addFormatToken('z', 0, 0, 'zoneAbbr');
+addFormatToken('zz', 0, 0, 'zoneName');
+
+// MOMENTS
+
+function getZoneAbbr () {
+ return this._isUTC ? 'UTC' : '';
+}
+
+function getZoneName () {
+ return this._isUTC ? 'Coordinated Universal Time' : '';
+}
+
+var proto = Moment.prototype;
+
+proto.add = add;
+proto.calendar = calendar$1;
+proto.clone = clone;
+proto.diff = diff;
+proto.endOf = endOf;
+proto.format = format;
+proto.from = from;
+proto.fromNow = fromNow;
+proto.to = to;
+proto.toNow = toNow;
+proto.get = stringGet;
+proto.invalidAt = invalidAt;
+proto.isAfter = isAfter;
+proto.isBefore = isBefore;
+proto.isBetween = isBetween;
+proto.isSame = isSame;
+proto.isSameOrAfter = isSameOrAfter;
+proto.isSameOrBefore = isSameOrBefore;
+proto.isValid = isValid$2;
+proto.lang = lang;
+proto.locale = locale;
+proto.localeData = localeData;
+proto.max = prototypeMax;
+proto.min = prototypeMin;
+proto.parsingFlags = parsingFlags;
+proto.set = stringSet;
+proto.startOf = startOf;
+proto.subtract = subtract;
+proto.toArray = toArray;
+proto.toObject = toObject;
+proto.toDate = toDate;
+proto.toISOString = toISOString;
+proto.inspect = inspect;
+proto.toJSON = toJSON;
+proto.toString = toString;
+proto.unix = unix;
+proto.valueOf = valueOf;
+proto.creationData = creationData;
+
+// Year
+proto.year = getSetYear;
+proto.isLeapYear = getIsLeapYear;
+
+// Week Year
+proto.weekYear = getSetWeekYear;
+proto.isoWeekYear = getSetISOWeekYear;
+
+// Quarter
+proto.quarter = proto.quarters = getSetQuarter;
+
+// Month
+proto.month = getSetMonth;
+proto.daysInMonth = getDaysInMonth;
+
+// Week
+proto.week = proto.weeks = getSetWeek;
+proto.isoWeek = proto.isoWeeks = getSetISOWeek;
+proto.weeksInYear = getWeeksInYear;
+proto.isoWeeksInYear = getISOWeeksInYear;
+
+// Day
+proto.date = getSetDayOfMonth;
+proto.day = proto.days = getSetDayOfWeek;
+proto.weekday = getSetLocaleDayOfWeek;
+proto.isoWeekday = getSetISODayOfWeek;
+proto.dayOfYear = getSetDayOfYear;
+
+// Hour
+proto.hour = proto.hours = getSetHour;
+
+// Minute
+proto.minute = proto.minutes = getSetMinute;
+
+// Second
+proto.second = proto.seconds = getSetSecond;
+
+// Millisecond
+proto.millisecond = proto.milliseconds = getSetMillisecond;
+
+// Offset
+proto.utcOffset = getSetOffset;
+proto.utc = setOffsetToUTC;
+proto.local = setOffsetToLocal;
+proto.parseZone = setOffsetToParsedOffset;
+proto.hasAlignedHourOffset = hasAlignedHourOffset;
+proto.isDST = isDaylightSavingTime;
+proto.isLocal = isLocal;
+proto.isUtcOffset = isUtcOffset;
+proto.isUtc = isUtc;
+proto.isUTC = isUtc;
+
+// Timezone
+proto.zoneAbbr = getZoneAbbr;
+proto.zoneName = getZoneName;
+
+// Deprecations
+proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
+proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
+proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
+proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
+proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
+
+function createUnix (input) {
+ return createLocal(input * 1000);
+}
+
+function createInZone () {
+ return createLocal.apply(null, arguments).parseZone();
+}
+
+function preParsePostFormat (string) {
+ return string;
+}
+
+var proto$1 = Locale.prototype;
+
+proto$1.calendar = calendar;
+proto$1.longDateFormat = longDateFormat;
+proto$1.invalidDate = invalidDate;
+proto$1.ordinal = ordinal;
+proto$1.preparse = preParsePostFormat;
+proto$1.postformat = preParsePostFormat;
+proto$1.relativeTime = relativeTime;
+proto$1.pastFuture = pastFuture;
+proto$1.set = set;
+
+// Month
+proto$1.months = localeMonths;
+proto$1.monthsShort = localeMonthsShort;
+proto$1.monthsParse = localeMonthsParse;
+proto$1.monthsRegex = monthsRegex;
+proto$1.monthsShortRegex = monthsShortRegex;
+
+// Week
+proto$1.week = localeWeek;
+proto$1.firstDayOfYear = localeFirstDayOfYear;
+proto$1.firstDayOfWeek = localeFirstDayOfWeek;
+
+// Day of Week
+proto$1.weekdays = localeWeekdays;
+proto$1.weekdaysMin = localeWeekdaysMin;
+proto$1.weekdaysShort = localeWeekdaysShort;
+proto$1.weekdaysParse = localeWeekdaysParse;
+
+proto$1.weekdaysRegex = weekdaysRegex;
+proto$1.weekdaysShortRegex = weekdaysShortRegex;
+proto$1.weekdaysMinRegex = weekdaysMinRegex;
+
+// Hours
+proto$1.isPM = localeIsPM;
+proto$1.meridiem = localeMeridiem;
+
+function get$1 (format, index, field, setter) {
+ var locale = getLocale();
+ var utc = createUTC().set(setter, index);
+ return locale[field](utc, format);
+}
+
+function listMonthsImpl (format, index, field) {
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+
+ if (index != null) {
+ return get$1(format, index, field, 'month');
+ }
+
+ var i;
+ var out = [];
+ for (i = 0; i < 12; i++) {
+ out[i] = get$1(format, i, field, 'month');
+ }
+ return out;
+}
+
+// ()
+// (5)
+// (fmt, 5)
+// (fmt)
+// (true)
+// (true, 5)
+// (true, fmt, 5)
+// (true, fmt)
+function listWeekdaysImpl (localeSorted, format, index, field) {
+ if (typeof localeSorted === 'boolean') {
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+ } else {
+ format = localeSorted;
+ index = format;
+ localeSorted = false;
+
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+ }
+
+ var locale = getLocale(),
+ shift = localeSorted ? locale._week.dow : 0;
+
+ if (index != null) {
+ return get$1(format, (index + shift) % 7, field, 'day');
+ }
+
+ var i;
+ var out = [];
+ for (i = 0; i < 7; i++) {
+ out[i] = get$1(format, (i + shift) % 7, field, 'day');
+ }
+ return out;
+}
+
+function listMonths (format, index) {
+ return listMonthsImpl(format, index, 'months');
+}
+
+function listMonthsShort (format, index) {
+ return listMonthsImpl(format, index, 'monthsShort');
+}
+
+function listWeekdays (localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
+}
+
+function listWeekdaysShort (localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
+}
+
+function listWeekdaysMin (localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
+}
+
+getSetGlobalLocale('en', {
+ dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (toInt(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ }
+});
+
+// Side effect imports
+hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
+hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
+
+var mathAbs = Math.abs;
+
+function abs () {
+ var data = this._data;
+
+ this._milliseconds = mathAbs(this._milliseconds);
+ this._days = mathAbs(this._days);
+ this._months = mathAbs(this._months);
+
+ data.milliseconds = mathAbs(data.milliseconds);
+ data.seconds = mathAbs(data.seconds);
+ data.minutes = mathAbs(data.minutes);
+ data.hours = mathAbs(data.hours);
+ data.months = mathAbs(data.months);
+ data.years = mathAbs(data.years);
+
+ return this;
+}
+
+function addSubtract$1 (duration, input, value, direction) {
+ var other = createDuration(input, value);
+
+ duration._milliseconds += direction * other._milliseconds;
+ duration._days += direction * other._days;
+ duration._months += direction * other._months;
+
+ return duration._bubble();
+}
+
+// supports only 2.0-style add(1, 's') or add(duration)
+function add$1 (input, value) {
+ return addSubtract$1(this, input, value, 1);
+}
+
+// supports only 2.0-style subtract(1, 's') or subtract(duration)
+function subtract$1 (input, value) {
+ return addSubtract$1(this, input, value, -1);
+}
+
+function absCeil (number) {
+ if (number < 0) {
+ return Math.floor(number);
+ } else {
+ return Math.ceil(number);
+ }
+}
+
+function bubble () {
+ var milliseconds = this._milliseconds;
+ var days = this._days;
+ var months = this._months;
+ var data = this._data;
+ var seconds, minutes, hours, years, monthsFromDays;
+
+ // if we have a mix of positive and negative values, bubble down first
+ // check: https://github.com/moment/moment/issues/2166
+ if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
+ (milliseconds <= 0 && days <= 0 && months <= 0))) {
+ milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
+ days = 0;
+ months = 0;
+ }
+
+ // The following code bubbles up values, see the tests for
+ // examples of what that means.
+ data.milliseconds = milliseconds % 1000;
+
+ seconds = absFloor(milliseconds / 1000);
+ data.seconds = seconds % 60;
+
+ minutes = absFloor(seconds / 60);
+ data.minutes = minutes % 60;
+
+ hours = absFloor(minutes / 60);
+ data.hours = hours % 24;
+
+ days += absFloor(hours / 24);
+
+ // convert days to months
+ monthsFromDays = absFloor(daysToMonths(days));
+ months += monthsFromDays;
+ days -= absCeil(monthsToDays(monthsFromDays));
+
+ // 12 months -> 1 year
+ years = absFloor(months / 12);
+ months %= 12;
+
+ data.days = days;
+ data.months = months;
+ data.years = years;
+
+ return this;
+}
+
+function daysToMonths (days) {
+ // 400 years have 146097 days (taking into account leap year rules)
+ // 400 years have 12 months === 4800
+ return days * 4800 / 146097;
+}
+
+function monthsToDays (months) {
+ // the reverse of daysToMonths
+ return months * 146097 / 4800;
+}
+
+function as (units) {
+ if (!this.isValid()) {
+ return NaN;
+ }
+ var days;
+ var months;
+ var milliseconds = this._milliseconds;
+
+ units = normalizeUnits(units);
+
+ if (units === 'month' || units === 'year') {
+ days = this._days + milliseconds / 864e5;
+ months = this._months + daysToMonths(days);
+ return units === 'month' ? months : months / 12;
+ } else {
+ // handle milliseconds separately because of floating point math errors (issue #1867)
+ days = this._days + Math.round(monthsToDays(this._months));
+ switch (units) {
+ case 'week' : return days / 7 + milliseconds / 6048e5;
+ case 'day' : return days + milliseconds / 864e5;
+ case 'hour' : return days * 24 + milliseconds / 36e5;
+ case 'minute' : return days * 1440 + milliseconds / 6e4;
+ case 'second' : return days * 86400 + milliseconds / 1000;
+ // Math.floor prevents floating point math errors here
+ case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
+ default: throw new Error('Unknown unit ' + units);
+ }
+ }
+}
+
+// TODO: Use this.as('ms')?
+function valueOf$1 () {
+ if (!this.isValid()) {
+ return NaN;
+ }
+ return (
+ this._milliseconds +
+ this._days * 864e5 +
+ (this._months % 12) * 2592e6 +
+ toInt(this._months / 12) * 31536e6
+ );
+}
+
+function makeAs (alias) {
+ return function () {
+ return this.as(alias);
+ };
+}
+
+var asMilliseconds = makeAs('ms');
+var asSeconds = makeAs('s');
+var asMinutes = makeAs('m');
+var asHours = makeAs('h');
+var asDays = makeAs('d');
+var asWeeks = makeAs('w');
+var asMonths = makeAs('M');
+var asYears = makeAs('y');
+
+function clone$1 () {
+ return createDuration(this);
+}
+
+function get$2 (units) {
+ units = normalizeUnits(units);
+ return this.isValid() ? this[units + 's']() : NaN;
+}
+
+function makeGetter(name) {
+ return function () {
+ return this.isValid() ? this._data[name] : NaN;
+ };
+}
+
+var milliseconds = makeGetter('milliseconds');
+var seconds = makeGetter('seconds');
+var minutes = makeGetter('minutes');
+var hours = makeGetter('hours');
+var days = makeGetter('days');
+var months = makeGetter('months');
+var years = makeGetter('years');
+
+function weeks () {
+ return absFloor(this.days() / 7);
+}
+
+var round = Math.round;
+var thresholds = {
+ ss: 44, // a few seconds to seconds
+ s : 45, // seconds to minute
+ m : 45, // minutes to hour
+ h : 22, // hours to day
+ d : 26, // days to month
+ M : 11 // months to year
+};
+
+// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
+ return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+}
+
+function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
+ var duration = createDuration(posNegDuration).abs();
+ var seconds = round(duration.as('s'));
+ var minutes = round(duration.as('m'));
+ var hours = round(duration.as('h'));
+ var days = round(duration.as('d'));
+ var months = round(duration.as('M'));
+ var years = round(duration.as('y'));
+
+ var a = seconds <= thresholds.ss && ['s', seconds] ||
+ seconds < thresholds.s && ['ss', seconds] ||
+ minutes <= 1 && ['m'] ||
+ minutes < thresholds.m && ['mm', minutes] ||
+ hours <= 1 && ['h'] ||
+ hours < thresholds.h && ['hh', hours] ||
+ days <= 1 && ['d'] ||
+ days < thresholds.d && ['dd', days] ||
+ months <= 1 && ['M'] ||
+ months < thresholds.M && ['MM', months] ||
+ years <= 1 && ['y'] || ['yy', years];
+
+ a[2] = withoutSuffix;
+ a[3] = +posNegDuration > 0;
+ a[4] = locale;
+ return substituteTimeAgo.apply(null, a);
+}
+
+// This function allows you to set the rounding function for relative time strings
+function getSetRelativeTimeRounding (roundingFunction) {
+ if (roundingFunction === undefined) {
+ return round;
+ }
+ if (typeof(roundingFunction) === 'function') {
+ round = roundingFunction;
+ return true;
+ }
+ return false;
+}
+
+// This function allows you to set a threshold for relative time strings
+function getSetRelativeTimeThreshold (threshold, limit) {
+ if (thresholds[threshold] === undefined) {
+ return false;
+ }
+ if (limit === undefined) {
+ return thresholds[threshold];
+ }
+ thresholds[threshold] = limit;
+ if (threshold === 's') {
+ thresholds.ss = limit - 1;
+ }
+ return true;
+}
+
+function humanize (withSuffix) {
+ if (!this.isValid()) {
+ return this.localeData().invalidDate();
+ }
+
+ var locale = this.localeData();
+ var output = relativeTime$1(this, !withSuffix, locale);
+
+ if (withSuffix) {
+ output = locale.pastFuture(+this, output);
+ }
+
+ return locale.postformat(output);
+}
+
+var abs$1 = Math.abs;
+
+function sign(x) {
+ return ((x > 0) - (x < 0)) || +x;
+}
+
+function toISOString$1() {
+ // for ISO strings we do not use the normal bubbling rules:
+ // * milliseconds bubble up until they become hours
+ // * days do not bubble at all
+ // * months bubble up until they become years
+ // This is because there is no context-free conversion between hours and days
+ // (think of clock changes)
+ // and also not between days and months (28-31 days per month)
+ if (!this.isValid()) {
+ return this.localeData().invalidDate();
+ }
+
+ var seconds = abs$1(this._milliseconds) / 1000;
+ var days = abs$1(this._days);
+ var months = abs$1(this._months);
+ var minutes, hours, years;
+
+ // 3600 seconds -> 60 minutes -> 1 hour
+ minutes = absFloor(seconds / 60);
+ hours = absFloor(minutes / 60);
+ seconds %= 60;
+ minutes %= 60;
+
+ // 12 months -> 1 year
+ years = absFloor(months / 12);
+ months %= 12;
+
+
+ // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
+ var Y = years;
+ var M = months;
+ var D = days;
+ var h = hours;
+ var m = minutes;
+ var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
+ var total = this.asSeconds();
+
+ if (!total) {
+ // this is the same as C#'s (Noda) and python (isodate)...
+ // but not other JS (goog.date)
+ return 'P0D';
+ }
+
+ var totalSign = total < 0 ? '-' : '';
+ var ymSign = sign(this._months) !== sign(total) ? '-' : '';
+ var daysSign = sign(this._days) !== sign(total) ? '-' : '';
+ var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
+
+ return totalSign + 'P' +
+ (Y ? ymSign + Y + 'Y' : '') +
+ (M ? ymSign + M + 'M' : '') +
+ (D ? daysSign + D + 'D' : '') +
+ ((h || m || s) ? 'T' : '') +
+ (h ? hmsSign + h + 'H' : '') +
+ (m ? hmsSign + m + 'M' : '') +
+ (s ? hmsSign + s + 'S' : '');
+}
+
+var proto$2 = Duration.prototype;
+
+proto$2.isValid = isValid$1;
+proto$2.abs = abs;
+proto$2.add = add$1;
+proto$2.subtract = subtract$1;
+proto$2.as = as;
+proto$2.asMilliseconds = asMilliseconds;
+proto$2.asSeconds = asSeconds;
+proto$2.asMinutes = asMinutes;
+proto$2.asHours = asHours;
+proto$2.asDays = asDays;
+proto$2.asWeeks = asWeeks;
+proto$2.asMonths = asMonths;
+proto$2.asYears = asYears;
+proto$2.valueOf = valueOf$1;
+proto$2._bubble = bubble;
+proto$2.clone = clone$1;
+proto$2.get = get$2;
+proto$2.milliseconds = milliseconds;
+proto$2.seconds = seconds;
+proto$2.minutes = minutes;
+proto$2.hours = hours;
+proto$2.days = days;
+proto$2.weeks = weeks;
+proto$2.months = months;
+proto$2.years = years;
+proto$2.humanize = humanize;
+proto$2.toISOString = toISOString$1;
+proto$2.toString = toISOString$1;
+proto$2.toJSON = toISOString$1;
+proto$2.locale = locale;
+proto$2.localeData = localeData;
+
+// Deprecations
+proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
+proto$2.lang = lang;
+
+// Side effect imports
+
+// FORMATTING
+
+addFormatToken('X', 0, 0, 'unix');
+addFormatToken('x', 0, 0, 'valueOf');
+
+// PARSING
+
+addRegexToken('x', matchSigned);
+addRegexToken('X', matchTimestamp);
+addParseToken('X', function (input, array, config) {
+ config._d = new Date(parseFloat(input, 10) * 1000);
+});
+addParseToken('x', function (input, array, config) {
+ config._d = new Date(toInt(input));
+});
+
+// Side effect imports
+
+
+hooks.version = '2.20.1';
+
+setHookCallback(createLocal);
+
+hooks.fn = proto;
+hooks.min = min;
+hooks.max = max;
+hooks.now = now;
+hooks.utc = createUTC;
+hooks.unix = createUnix;
+hooks.months = listMonths;
+hooks.isDate = isDate;
+hooks.locale = getSetGlobalLocale;
+hooks.invalid = createInvalid;
+hooks.duration = createDuration;
+hooks.isMoment = isMoment;
+hooks.weekdays = listWeekdays;
+hooks.parseZone = createInZone;
+hooks.localeData = getLocale;
+hooks.isDuration = isDuration;
+hooks.monthsShort = listMonthsShort;
+hooks.weekdaysMin = listWeekdaysMin;
+hooks.defineLocale = defineLocale;
+hooks.updateLocale = updateLocale;
+hooks.locales = listLocales;
+hooks.weekdaysShort = listWeekdaysShort;
+hooks.normalizeUnits = normalizeUnits;
+hooks.relativeTimeRounding = getSetRelativeTimeRounding;
+hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
+hooks.calendarFormat = getCalendarFormat;
+hooks.prototype = proto;
+
+// currently HTML5 input type only supports 24-hour formats
+hooks.HTML5_FMT = {
+ DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" />
+ DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" />
+ DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" />
+ DATE: 'YYYY-MM-DD', // <input type="date" />
+ TIME: 'HH:mm', // <input type="time" />
+ TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" />
+ TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" />
+ WEEK: 'YYYY-[W]WW', // <input type="week" />
+ MONTH: 'YYYY-MM' // <input type="month" />
+};
+
+return hooks;
+
+})));
+
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(134)(module)))
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
+ * jQuery JavaScript Library v3.2.1
+ * https://jquery.com/
+ *
+ * Includes Sizzle.js
+ * https://sizzlejs.com/
+ *
+ * Copyright JS Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2017-03-20T18:59Z
+ */
+( function( global, factory ) {
+
+ "use strict";
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
+// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
+// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
+// enough that all such attempts are guarded in a try block.
+"use strict";
+
+var arr = [];
+
+var document = window.document;
+
+var getProto = Object.getPrototypeOf;
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var fnToString = hasOwn.toString;
+
+var ObjectFunctionString = fnToString.call( Object );
+
+var support = {};
+
+
+
+ function DOMEval( code, doc ) {
+ doc = doc || document;
+
+ var script = doc.createElement( "script" );
+
+ script.text = code;
+ doc.head.appendChild( script ).parentNode.removeChild( script );
+ }
+/* global Symbol */
+// Defining this global in .eslintrc.json would create a danger of using the global
+// unguarded in another place, it seems safer to define global only for this module
+
+
+
+var
+ version = "3.2.1",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android <=4.0 only
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([a-z])/g,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn = jQuery.prototype = {
+
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+
+ // Return all the elements in a clean array
+ if ( num == null ) {
+ return slice.call( this );
+ }
+
+ // Return just the one element from the set
+ return num < 0 ? this[ num + this.length ] : this[ num ];
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ each: function( callback ) {
+ return jQuery.each( this, callback );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map( this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ } ) );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor();
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: arr.sort,
+ splice: arr.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[ 0 ] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // Skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
+ target = {};
+ }
+
+ // Extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+
+ // Only deal with non-null/undefined values
+ if ( ( options = arguments[ i ] ) != null ) {
+
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
+ ( copyIsArray = Array.isArray( copy ) ) ) ) {
+
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && Array.isArray( src ) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject( src ) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend( {
+
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ isFunction: function( obj ) {
+ return jQuery.type( obj ) === "function";
+ },
+
+ isWindow: function( obj ) {
+ return obj != null && obj === obj.window;
+ },
+
+ isNumeric: function( obj ) {
+
+ // As of jQuery 3.0, isNumeric is limited to
+ // strings and numbers (primitives or objects)
+ // that can be coerced to finite numbers (gh-2662)
+ var type = jQuery.type( obj );
+ return ( type === "number" || type === "string" ) &&
+
+ // parseFloat NaNs numeric-cast false positives ("")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ !isNaN( obj - parseFloat( obj ) );
+ },
+
+ isPlainObject: function( obj ) {
+ var proto, Ctor;
+
+ // Detect obvious negatives
+ // Use toString instead of jQuery.type to catch host objects
+ if ( !obj || toString.call( obj ) !== "[object Object]" ) {
+ return false;
+ }
+
+ proto = getProto( obj );
+
+ // Objects with no prototype (e.g., `Object.create( null )`) are plain
+ if ( !proto ) {
+ return true;
+ }
+
+ // Objects with prototype are plain iff they were constructed by a global Object function
+ Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
+ return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
+ },
+
+ isEmptyObject: function( obj ) {
+
+ /* eslint-disable no-unused-vars */
+ // See https://github.com/eslint/eslint/issues/6125
+ var name;
+
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+
+ // Support: Android <=2.3 only (functionish RegExp)
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call( obj ) ] || "object" :
+ typeof obj;
+ },
+
+ // Evaluates a script in a global context
+ globalEval: function( code ) {
+ DOMEval( code );
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Support: IE <=9 - 11, Edge 12 - 13
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ each: function( obj, callback ) {
+ var length, i = 0;
+
+ if ( isArrayLike( obj ) ) {
+ length = obj.length;
+ for ( ; i < length; i++ ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android <=4.0 only
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArrayLike( Object( arr ) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ return arr == null ? -1 : indexOf.call( arr, elem, i );
+ },
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ for ( ; j < len; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var length, value,
+ i = 0,
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArrayLike( elems ) ) {
+ length = elems.length;
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var tmp, args, proxy;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ now: Date.now,
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+} );
+
+if ( typeof Symbol === "function" ) {
+ jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
+}
+
+// Populate the class2type map
+jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
+function( i, name ) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+} );
+
+function isArrayLike( obj ) {
+
+ // Support: real iOS 8.2 only (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = !!obj && "length" in obj && obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.3.3
+ * https://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2016-08-08
+ */
+(function( window ) {
+
+var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + 1 * new Date(),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf as it's faster than native
+ // https://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
+ var i = 0,
+ len = list.length;
+ for ( ; i < len; i++ ) {
+ if ( list[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+
+ // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + identifier + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + identifier + ")" ),
+ "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
+ "TAG": new RegExp( "^(" + identifier + "|[*])" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+
+ // CSS escapes
+ // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ },
+
+ // CSS string/identifier serialization
+ // https://drafts.csswg.org/cssom/#common-serializing-idioms
+ rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
+ fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ },
+
+ disabledAncestor = addCombinator(
+ function( elem ) {
+ return elem.disabled === true && ("form" in elem || "label" in elem);
+ },
+ { dir: "parentNode", next: "legend" }
+ );
+
+// Optimize for push.apply( _, NodeList )
+try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var m, i, elem, nid, match, groups, newSelector,
+ newContext = context && context.ownerDocument,
+
+ // nodeType defaults to 9, since context defaults to document
+ nodeType = context ? context.nodeType : 9;
+
+ results = results || [];
+
+ // Return early from calls with invalid selector or context
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+ return results;
+ }
+
+ // Try to shortcut find operations (as opposed to filters) in HTML documents
+ if ( !seed ) {
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+ context = context || document;
+
+ if ( documentIsHTML ) {
+
+ // If the selector is sufficiently simple, try using a "get*By*" DOM method
+ // (excepting DocumentFragment context, where the methods don't exist)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+
+ // ID selector
+ if ( (m = match[1]) ) {
+
+ // Document context
+ if ( nodeType === 9 ) {
+ if ( (elem = context.getElementById( m )) ) {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+
+ // Element context
+ } else {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( newContext && (elem = newContext.getElementById( m )) &&
+ contains( context, elem ) &&
+ elem.id === m ) {
+
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Type selector
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Class selector
+ } else if ( (m = match[3]) && support.getElementsByClassName &&
+ context.getElementsByClassName ) {
+
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // Take advantage of querySelectorAll
+ if ( support.qsa &&
+ !compilerCache[ selector + " " ] &&
+ (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+
+ if ( nodeType !== 1 ) {
+ newContext = context;
+ newSelector = selector;
+
+ // qSA looks outside Element context, which is not what we want
+ // Thanks to Andrew Dupont for this workaround technique
+ // Support: IE <=8
+ // Exclude object elements
+ } else if ( context.nodeName.toLowerCase() !== "object" ) {
+
+ // Capture the context ID, setting it first if necessary
+ if ( (nid = context.getAttribute( "id" )) ) {
+ nid = nid.replace( rcssescape, fcssescape );
+ } else {
+ context.setAttribute( "id", (nid = expando) );
+ }
+
+ // Prefix every selector in the list
+ groups = tokenize( selector );
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = "#" + nid + " " + toSelector( groups[i] );
+ }
+ newSelector = groups.join( "," );
+
+ // Expand context for sibling selectors
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+ context;
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch ( qsaError ) {
+ } finally {
+ if ( nid === expando ) {
+ context.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {function(string, object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key + " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key + " " ] = value);
+ }
+ return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created element and returns a boolean result
+ */
+function assert( fn ) {
+ var el = document.createElement("fieldset");
+
+ try {
+ return !!fn( el );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( el.parentNode ) {
+ el.parentNode.removeChild( el );
+ }
+ // release memory in IE
+ el = null;
+ }
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = arr.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ a.sourceIndex - b.sourceIndex;
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for :enabled/:disabled
+ * @param {Boolean} disabled true for :disabled; false for :enabled
+ */
+function createDisabledPseudo( disabled ) {
+
+ // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
+ return function( elem ) {
+
+ // Only certain elements can match :enabled or :disabled
+ // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
+ // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
+ if ( "form" in elem ) {
+
+ // Check for inherited disabledness on relevant non-disabled elements:
+ // * listed form-associated elements in a disabled fieldset
+ // https://html.spec.whatwg.org/multipage/forms.html#category-listed
+ // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
+ // * option elements in a disabled optgroup
+ // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
+ // All such elements have a "form" property.
+ if ( elem.parentNode && elem.disabled === false ) {
+
+ // Option elements defer to a parent optgroup if present
+ if ( "label" in elem ) {
+ if ( "label" in elem.parentNode ) {
+ return elem.parentNode.disabled === disabled;
+ } else {
+ return elem.disabled === disabled;
+ }
+ }
+
+ // Support: IE 6 - 11
+ // Use the isDisabled shortcut property to check for disabled fieldset ancestors
+ return elem.isDisabled === disabled ||
+
+ // Where there is no isDisabled, check manually
+ /* jshint -W018 */
+ elem.isDisabled !== !disabled &&
+ disabledAncestor( elem ) === disabled;
+ }
+
+ return elem.disabled === disabled;
+
+ // Try to winnow out elements that can't be disabled before trusting the disabled property.
+ // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
+ // even exist on them, let alone have a boolean value.
+ } else if ( "label" in elem ) {
+ return elem.disabled === disabled;
+ }
+
+ // Remaining elements are neither :enabled nor :disabled
+ return false;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var hasCompare, subWindow,
+ doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // Return early if doc is invalid or already selected
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Update global variables
+ document = doc;
+ docElem = document.documentElement;
+ documentIsHTML = !isXML( document );
+
+ // Support: IE 9-11, Edge
+ // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
+ if ( preferredDoc !== document &&
+ (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
+
+ // Support: IE 11, Edge
+ if ( subWindow.addEventListener ) {
+ subWindow.addEventListener( "unload", unloadHandler, false );
+
+ // Support: IE 9 - 10 only
+ } else if ( subWindow.attachEvent ) {
+ subWindow.attachEvent( "onunload", unloadHandler );
+ }
+ }
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties
+ // (excepting IE8 booleans)
+ support.attributes = assert(function( el ) {
+ el.className = "i";
+ return !el.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( el ) {
+ el.appendChild( document.createComment("") );
+ return !el.getElementsByTagName("*").length;
+ });
+
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( document.getElementsByClassName );
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programmatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( el ) {
+ docElem.appendChild( el ).id = expando;
+ return !document.getElementsByName || !document.getElementsByName( expando ).length;
+ });
+
+ // ID filter and find
+ if ( support.getById ) {
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var elem = context.getElementById( id );
+ return elem ? [ elem ] : [];
+ }
+ };
+ } else {
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== "undefined" &&
+ elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+
+ // Support: IE 6 - 7 only
+ // getElementById is not reliable as a find shortcut
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var node, i, elems,
+ elem = context.getElementById( id );
+
+ if ( elem ) {
+
+ // Verify the id attribute
+ node = elem.getAttributeNode("id");
+ if ( node && node.value === id ) {
+ return [ elem ];
+ }
+
+ // Fall back on getElementsByName
+ elems = context.getElementsByName( id );
+ i = 0;
+ while ( (elem = elems[i++]) ) {
+ node = elem.getAttributeNode("id");
+ if ( node && node.value === id ) {
+ return [ elem ];
+ }
+ }
+ }
+
+ return [];
+ }
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
+ }
+ } :
+
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See https://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( el ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // https://bugs.jquery.com/ticket/12359
+ docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
+ "<select id='" + expando + "-\r\\' msallowcapture=''>" +
+ "<option selected=''></option></select>";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( el.querySelectorAll("[msallowcapture^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !el.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
+ if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !el.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibling-combinator selector` fails
+ if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
+ });
+
+ assert(function( el ) {
+ el.innerHTML = "<a href='' disabled='disabled'></a>" +
+ "<select disabled='disabled'><option/></select>";
+
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = document.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ el.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( el.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( el.querySelectorAll(":enabled").length !== 2 ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Support: IE9-11+
+ // IE's :disabled selector does not pick up the children of disabled fieldsets
+ docElem.appendChild( el ).disabled = true;
+ if ( el.querySelectorAll(":disabled").length !== 2 ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ el.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( el ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( el, "*" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( el, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully self-exclusive
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === document ? -1 :
+ b === document ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return document;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ !compilerCache[ expr + " " ] &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch (e) {}
+ }
+
+ return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+};
+
+Sizzle.escape = function( sel ) {
+ return (sel + "").replace( rcssescape, fcssescape );
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ while ( (node = elem[i++]) ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, uniqueCache, outerCache, node, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType,
+ diff = false;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) {
+
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+
+ // Seek `elem` from a previously-cached index
+
+ // ...in a gzip-friendly way
+ node = parent;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex && cache[ 2 ];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ } else {
+ // Use previously-cached element index if available
+ if ( useCache ) {
+ // ...in a gzip-friendly way
+ node = elem;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex;
+ }
+
+ // xml :nth-child(...)
+ // or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ if ( diff === false ) {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) &&
+ ++diff ) {
+
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ uniqueCache[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ // Don't keep the element (issue #299)
+ input[0] = null;
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": createDisabledPseudo( false ),
+ "disabled": createDisabledPseudo( true ),
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( (tokens = []) );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ skip = combinator.next,
+ key = skip || dir,
+ checkNonElements = base && key === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ return false;
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var oldCache, uniqueCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
+
+ if ( skip && skip === elem.nodeName.toLowerCase() ) {
+ elem = elem[ dir ] || elem;
+ } else if ( (oldCache = uniqueCache[ key ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ uniqueCache[ key ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context === document || context || outermost;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ if ( !context && elem.ownerDocument !== document ) {
+ setDocument( elem );
+ xml = !documentIsHTML;
+ }
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context || document, xml) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // `i` is now the count of elements visited above, and adding it to `matchedCount`
+ // makes the latter nonnegative.
+ matchedCount += i;
+
+ // Apply set filters to unmatched elements
+ // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
+ // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
+ // no element matchers and no seed.
+ // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
+ // case, which will result in a "00" `matchedCount` that differs from `i` but is also
+ // numerically zero.
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is only one selector in the list and no seed
+ // (the latter of which guarantees us context)
+ if ( match.length === 1 ) {
+
+ // Reduce context if the leading compound selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( el ) {
+ // Should return 1, but returns 4 (following)
+ return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( el ) {
+ el.innerHTML = "<a href='#'></a>";
+ return el.firstChild.getAttribute("href") === "#" ;
+}) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( el ) {
+ el.innerHTML = "<input/>";
+ el.firstChild.setAttribute( "value", "" );
+ return el.firstChild.getAttribute( "value" ) === "";
+}) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( el ) {
+ return el.getAttribute("disabled") == null;
+}) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+
+// Deprecated
+jQuery.expr[ ":" ] = jQuery.expr.pseudos;
+jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+jQuery.escapeSelector = Sizzle.escape;
+
+
+
+
+var dir = function( elem, dir, until ) {
+ var matched = [],
+ truncate = until !== undefined;
+
+ while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
+ if ( elem.nodeType === 1 ) {
+ if ( truncate && jQuery( elem ).is( until ) ) {
+ break;
+ }
+ matched.push( elem );
+ }
+ }
+ return matched;
+};
+
+
+var siblings = function( n, elem ) {
+ var matched = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ matched.push( n );
+ }
+ }
+
+ return matched;
+};
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+
+
+function nodeName( elem, name ) {
+
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+
+};
+var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ return !!qualifier.call( elem, i, elem ) !== not;
+ } );
+ }
+
+ // Single element
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ } );
+ }
+
+ // Arraylike of elements (jQuery, arguments, Array)
+ if ( typeof qualifier !== "string" ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
+ } );
+ }
+
+ // Simple selector that can be filtered directly, removing non-Elements
+ if ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ // Complex selector, compare the two sets, removing non-Elements
+ qualifier = jQuery.filter( qualifier, elements );
+ return jQuery.grep( elements, function( elem ) {
+ return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
+ } );
+}
+
+jQuery.filter = function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ if ( elems.length === 1 && elem.nodeType === 1 ) {
+ return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
+ }
+
+ return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ } ) );
+};
+
+jQuery.fn.extend( {
+ find: function( selector ) {
+ var i, ret,
+ len = this.length,
+ self = this;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter( function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ } ) );
+ }
+
+ ret = this.pushStack( [] );
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ return len > 1 ? jQuery.uniqueSort( ret ) : ret;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], false ) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], true ) );
+ },
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ }
+} );
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ // Shortcut simple #id case for speed
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
+
+ init = jQuery.fn.init = function( selector, context, root ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Method init() accepts an alternate rootjQuery
+ // so migrate can support jQuery.sub (gh-2101)
+ root = root || rootjQuery;
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector[ 0 ] === "<" &&
+ selector[ selector.length - 1 ] === ">" &&
+ selector.length >= 3 ) {
+
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && ( match[ 1 ] || !context ) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[ 1 ] ) {
+ context = context instanceof jQuery ? context[ 0 ] : context;
+
+ // Option to run scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ jQuery.merge( this, jQuery.parseHTML(
+ match[ 1 ],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[ 2 ] );
+
+ if ( elem ) {
+
+ // Inject the element directly into the jQuery object
+ this[ 0 ] = elem;
+ this.length = 1;
+ }
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || root ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this[ 0 ] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return root.ready !== undefined ?
+ root.ready( selector ) :
+
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+
+ // Methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend( {
+ has: function( target ) {
+ var targets = jQuery( target, this ),
+ l = targets.length;
+
+ return this.filter( function() {
+ var i = 0;
+ for ( ; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[ i ] ) ) {
+ return true;
+ }
+ }
+ } );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ targets = typeof selectors !== "string" && jQuery( selectors );
+
+ // Positional selectors never match, since there's no _selection_ context
+ if ( !rneedsContext.test( selectors ) ) {
+ for ( ; i < l; i++ ) {
+ for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
+
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && ( targets ?
+ targets.index( cur ) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector( cur, selectors ) ) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
+ },
+
+ // Determine the position of an element within the set
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // Index in selector
+ if ( typeof elem === "string" ) {
+ return indexOf.call( jQuery( elem ), this[ 0 ] );
+ }
+
+ // Locate the position of the desired element
+ return indexOf.call( this,
+
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[ 0 ] : elem
+ );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.uniqueSort(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter( selector )
+ );
+ }
+} );
+
+function sibling( cur, dir ) {
+ while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
+ return cur;
+}
+
+jQuery.each( {
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return siblings( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return siblings( elem.firstChild );
+ },
+ contents: function( elem ) {
+ if ( nodeName( elem, "iframe" ) ) {
+ return elem.contentDocument;
+ }
+
+ // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
+ // Treat the template element as a regular one in browsers that
+ // don't support it.
+ if ( nodeName( elem, "template" ) ) {
+ elem = elem.content || elem;
+ }
+
+ return jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var matched = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ matched = jQuery.filter( selector, matched );
+ }
+
+ if ( this.length > 1 ) {
+
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ jQuery.uniqueSort( matched );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ matched.reverse();
+ }
+ }
+
+ return this.pushStack( matched );
+ };
+} );
+var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
+
+
+
+// Convert String-formatted options into Object-formatted ones
+function createOptions( options ) {
+ var object = {};
+ jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ } );
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ createOptions( options ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+
+ // Last fire value for non-forgettable lists
+ memory,
+
+ // Flag to know if list was already fired
+ fired,
+
+ // Flag to prevent firing
+ locked,
+
+ // Actual callback list
+ list = [],
+
+ // Queue of execution data for repeatable lists
+ queue = [],
+
+ // Index of currently firing callback (modified by add/remove as needed)
+ firingIndex = -1,
+
+ // Fire callbacks
+ fire = function() {
+
+ // Enforce single-firing
+ locked = locked || options.once;
+
+ // Execute callbacks for all pending executions,
+ // respecting firingIndex overrides and runtime changes
+ fired = firing = true;
+ for ( ; queue.length; firingIndex = -1 ) {
+ memory = queue.shift();
+ while ( ++firingIndex < list.length ) {
+
+ // Run callback and check for early termination
+ if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
+ options.stopOnFalse ) {
+
+ // Jump to end and forget the data so .add doesn't re-fire
+ firingIndex = list.length;
+ memory = false;
+ }
+ }
+ }
+
+ // Forget the data if we're done with it
+ if ( !options.memory ) {
+ memory = false;
+ }
+
+ firing = false;
+
+ // Clean up if we're done firing for good
+ if ( locked ) {
+
+ // Keep an empty list if we have data for future add calls
+ if ( memory ) {
+ list = [];
+
+ // Otherwise, this object is spent
+ } else {
+ list = "";
+ }
+ }
+ },
+
+ // Actual Callbacks object
+ self = {
+
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+
+ // If we have memory from a past run, we should fire after adding
+ if ( memory && !firing ) {
+ firingIndex = list.length - 1;
+ queue.push( memory );
+ }
+
+ ( function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ if ( jQuery.isFunction( arg ) ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
+
+ // Inspect recursively
+ add( arg );
+ }
+ } );
+ } )( arguments );
+
+ if ( memory && !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Remove a callback from the list
+ remove: function() {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+
+ // Handle firing indexes
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ } );
+ return this;
+ },
+
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ?
+ jQuery.inArray( fn, list ) > -1 :
+ list.length > 0;
+ },
+
+ // Remove all callbacks from the list
+ empty: function() {
+ if ( list ) {
+ list = [];
+ }
+ return this;
+ },
+
+ // Disable .fire and .add
+ // Abort any current/pending executions
+ // Clear all callbacks and values
+ disable: function() {
+ locked = queue = [];
+ list = memory = "";
+ return this;
+ },
+ disabled: function() {
+ return !list;
+ },
+
+ // Disable .fire
+ // Also disable .add unless we have memory (since it would have no effect)
+ // Abort any pending executions
+ lock: function() {
+ locked = queue = [];
+ if ( !memory && !firing ) {
+ list = memory = "";
+ }
+ return this;
+ },
+ locked: function() {
+ return !!locked;
+ },
+
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( !locked ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ queue.push( args );
+ if ( !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+
+
+function Identity( v ) {
+ return v;
+}
+function Thrower( ex ) {
+ throw ex;
+}
+
+function adoptValue( value, resolve, reject, noValue ) {
+ var method;
+
+ try {
+
+ // Check for promise aspect first to privilege synchronous behavior
+ if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
+ method.call( value ).done( resolve ).fail( reject );
+
+ // Other thenables
+ } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
+ method.call( value, resolve, reject );
+
+ // Other non-thenables
+ } else {
+
+ // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
+ // * false: [ value ].slice( 0 ) => resolve( value )
+ // * true: [ value ].slice( 1 ) => resolve()
+ resolve.apply( undefined, [ value ].slice( noValue ) );
+ }
+
+ // For Promises/A+, convert exceptions into rejections
+ // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
+ // Deferred#then to conditionally suppress rejection.
+ } catch ( value ) {
+
+ // Support: Android 4.0 only
+ // Strict mode functions invoked without .call/.apply get global-object context
+ reject.apply( undefined, [ value ] );
+ }
+}
+
+jQuery.extend( {
+
+ Deferred: function( func ) {
+ var tuples = [
+
+ // action, add listener, callbacks,
+ // ... .then handlers, argument index, [final state]
+ [ "notify", "progress", jQuery.Callbacks( "memory" ),
+ jQuery.Callbacks( "memory" ), 2 ],
+ [ "resolve", "done", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), 0, "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), 1, "rejected" ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ "catch": function( fn ) {
+ return promise.then( null, fn );
+ },
+
+ // Keep pipe for back-compat
+ pipe: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+
+ return jQuery.Deferred( function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+
+ // Map tuples (progress, done, fail) to arguments (done, fail, progress)
+ var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
+
+ // deferred.progress(function() { bind to newDefer or newDefer.notify })
+ // deferred.done(function() { bind to newDefer or newDefer.resolve })
+ // deferred.fail(function() { bind to newDefer or newDefer.reject })
+ deferred[ tuple[ 1 ] ]( function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .progress( newDefer.notify )
+ .done( newDefer.resolve )
+ .fail( newDefer.reject );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ](
+ this,
+ fn ? [ returned ] : arguments
+ );
+ }
+ } );
+ } );
+ fns = null;
+ } ).promise();
+ },
+ then: function( onFulfilled, onRejected, onProgress ) {
+ var maxDepth = 0;
+ function resolve( depth, deferred, handler, special ) {
+ return function() {
+ var that = this,
+ args = arguments,
+ mightThrow = function() {
+ var returned, then;
+
+ // Support: Promises/A+ section 2.3.3.3.3
+ // https://promisesaplus.com/#point-59
+ // Ignore double-resolution attempts
+ if ( depth < maxDepth ) {
+ return;
+ }
+
+ returned = handler.apply( that, args );
+
+ // Support: Promises/A+ section 2.3.1
+ // https://promisesaplus.com/#point-48
+ if ( returned === deferred.promise() ) {
+ throw new TypeError( "Thenable self-resolution" );
+ }
+
+ // Support: Promises/A+ sections 2.3.3.1, 3.5
+ // https://promisesaplus.com/#point-54
+ // https://promisesaplus.com/#point-75
+ // Retrieve `then` only once
+ then = returned &&
+
+ // Support: Promises/A+ section 2.3.4
+ // https://promisesaplus.com/#point-64
+ // Only check objects and functions for thenability
+ ( typeof returned === "object" ||
+ typeof returned === "function" ) &&
+ returned.then;
+
+ // Handle a returned thenable
+ if ( jQuery.isFunction( then ) ) {
+
+ // Special processors (notify) just wait for resolution
+ if ( special ) {
+ then.call(
+ returned,
+ resolve( maxDepth, deferred, Identity, special ),
+ resolve( maxDepth, deferred, Thrower, special )
+ );
+
+ // Normal processors (resolve) also hook into progress
+ } else {
+
+ // ...and disregard older resolution values
+ maxDepth++;
+
+ then.call(
+ returned,
+ resolve( maxDepth, deferred, Identity, special ),
+ resolve( maxDepth, deferred, Thrower, special ),
+ resolve( maxDepth, deferred, Identity,
+ deferred.notifyWith )
+ );
+ }
+
+ // Handle all other returned values
+ } else {
+
+ // Only substitute handlers pass on context
+ // and multiple values (non-spec behavior)
+ if ( handler !== Identity ) {
+ that = undefined;
+ args = [ returned ];
+ }
+
+ // Process the value(s)
+ // Default process is resolve
+ ( special || deferred.resolveWith )( that, args );
+ }
+ },
+
+ // Only normal processors (resolve) catch and reject exceptions
+ process = special ?
+ mightThrow :
+ function() {
+ try {
+ mightThrow();
+ } catch ( e ) {
+
+ if ( jQuery.Deferred.exceptionHook ) {
+ jQuery.Deferred.exceptionHook( e,
+ process.stackTrace );
+ }
+
+ // Support: Promises/A+ section 2.3.3.3.4.1
+ // https://promisesaplus.com/#point-61
+ // Ignore post-resolution exceptions
+ if ( depth + 1 >= maxDepth ) {
+
+ // Only substitute handlers pass on context
+ // and multiple values (non-spec behavior)
+ if ( handler !== Thrower ) {
+ that = undefined;
+ args = [ e ];
+ }
+
+ deferred.rejectWith( that, args );
+ }
+ }
+ };
+
+ // Support: Promises/A+ section 2.3.3.3.1
+ // https://promisesaplus.com/#point-57
+ // Re-resolve promises immediately to dodge false rejection from
+ // subsequent errors
+ if ( depth ) {
+ process();
+ } else {
+
+ // Call an optional hook to record the stack, in case of exception
+ // since it's otherwise lost when execution goes async
+ if ( jQuery.Deferred.getStackHook ) {
+ process.stackTrace = jQuery.Deferred.getStackHook();
+ }
+ window.setTimeout( process );
+ }
+ };
+ }
+
+ return jQuery.Deferred( function( newDefer ) {
+
+ // progress_handlers.add( ... )
+ tuples[ 0 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onProgress ) ?
+ onProgress :
+ Identity,
+ newDefer.notifyWith
+ )
+ );
+
+ // fulfilled_handlers.add( ... )
+ tuples[ 1 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onFulfilled ) ?
+ onFulfilled :
+ Identity
+ )
+ );
+
+ // rejected_handlers.add( ... )
+ tuples[ 2 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onRejected ) ?
+ onRejected :
+ Thrower
+ )
+ );
+ } ).promise();
+ },
+
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 5 ];
+
+ // promise.progress = list.add
+ // promise.done = list.add
+ // promise.fail = list.add
+ promise[ tuple[ 1 ] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(
+ function() {
+
+ // state = "resolved" (i.e., fulfilled)
+ // state = "rejected"
+ state = stateString;
+ },
+
+ // rejected_callbacks.disable
+ // fulfilled_callbacks.disable
+ tuples[ 3 - i ][ 2 ].disable,
+
+ // progress_callbacks.lock
+ tuples[ 0 ][ 2 ].lock
+ );
+ }
+
+ // progress_handlers.fire
+ // fulfilled_handlers.fire
+ // rejected_handlers.fire
+ list.add( tuple[ 3 ].fire );
+
+ // deferred.notify = function() { deferred.notifyWith(...) }
+ // deferred.resolve = function() { deferred.resolveWith(...) }
+ // deferred.reject = function() { deferred.rejectWith(...) }
+ deferred[ tuple[ 0 ] ] = function() {
+ deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
+ return this;
+ };
+
+ // deferred.notifyWith = list.fireWith
+ // deferred.resolveWith = list.fireWith
+ // deferred.rejectWith = list.fireWith
+ deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
+ } );
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( singleValue ) {
+ var
+
+ // count of uncompleted subordinates
+ remaining = arguments.length,
+
+ // count of unprocessed arguments
+ i = remaining,
+
+ // subordinate fulfillment data
+ resolveContexts = Array( i ),
+ resolveValues = slice.call( arguments ),
+
+ // the master Deferred
+ master = jQuery.Deferred(),
+
+ // subordinate callback factory
+ updateFunc = function( i ) {
+ return function( value ) {
+ resolveContexts[ i ] = this;
+ resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+ if ( !( --remaining ) ) {
+ master.resolveWith( resolveContexts, resolveValues );
+ }
+ };
+ };
+
+ // Single- and empty arguments are adopted like Promise.resolve
+ if ( remaining <= 1 ) {
+ adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
+ !remaining );
+
+ // Use .then() to unwrap secondary thenables (cf. gh-3000)
+ if ( master.state() === "pending" ||
+ jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
+
+ return master.then();
+ }
+ }
+
+ // Multiple arguments are aggregated like Promise.all array elements
+ while ( i-- ) {
+ adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
+ }
+
+ return master.promise();
+ }
+} );
+
+
+// These usually indicate a programmer mistake during development,
+// warn about them ASAP rather than swallowing them by default.
+var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
+
+jQuery.Deferred.exceptionHook = function( error, stack ) {
+
+ // Support: IE 8 - 9 only
+ // Console exists when dev tools are open, which can happen at any time
+ if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
+ window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
+ }
+};
+
+
+
+
+jQuery.readyException = function( error ) {
+ window.setTimeout( function() {
+ throw error;
+ } );
+};
+
+
+
+
+// The deferred used on DOM ready
+var readyList = jQuery.Deferred();
+
+jQuery.fn.ready = function( fn ) {
+
+ readyList
+ .then( fn )
+
+ // Wrap jQuery.readyException in a function so that the lookup
+ // happens at the time of error handling instead of callback
+ // registration.
+ .catch( function( error ) {
+ jQuery.readyException( error );
+ } );
+
+ return this;
+};
+
+jQuery.extend( {
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+ }
+} );
+
+jQuery.ready.then = readyList.then;
+
+// The ready event handler and self cleanup method
+function completed() {
+ document.removeEventListener( "DOMContentLoaded", completed );
+ window.removeEventListener( "load", completed );
+ jQuery.ready();
+}
+
+// Catch cases where $(document).ready() is called
+// after the browser event has already occurred.
+// Support: IE <=9 - 10 only
+// Older IE sometimes signals "interactive" too soon
+if ( document.readyState === "complete" ||
+ ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
+
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ window.setTimeout( jQuery.ready );
+
+} else {
+
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed );
+}
+
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ len = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ access( elems, fn, i, key[ i ], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < len; i++ ) {
+ fn(
+ elems[ i ], key, raw ?
+ value :
+ value.call( elems[ i ], i, fn( elems[ i ], key ) )
+ );
+ }
+ }
+ }
+
+ if ( chainable ) {
+ return elems;
+ }
+
+ // Gets
+ if ( bulk ) {
+ return fn.call( elems );
+ }
+
+ return len ? fn( elems[ 0 ], key ) : emptyGet;
+};
+var acceptData = function( owner ) {
+
+ // Accepts only:
+ // - Node
+ // - Node.ELEMENT_NODE
+ // - Node.DOCUMENT_NODE
+ // - Object
+ // - Any
+ return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+};
+
+
+
+
+function Data() {
+ this.expando = jQuery.expando + Data.uid++;
+}
+
+Data.uid = 1;
+
+Data.prototype = {
+
+ cache: function( owner ) {
+
+ // Check if the owner object already has a cache
+ var value = owner[ this.expando ];
+
+ // If not, create one
+ if ( !value ) {
+ value = {};
+
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return an empty object.
+ if ( acceptData( owner ) ) {
+
+ // If it is a node unlikely to be stringify-ed or looped over
+ // use plain assignment
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = value;
+
+ // Otherwise secure it in a non-enumerable property
+ // configurable must be true to allow the property to be
+ // deleted when data is removed
+ } else {
+ Object.defineProperty( owner, this.expando, {
+ value: value,
+ configurable: true
+ } );
+ }
+ }
+ }
+
+ return value;
+ },
+ set: function( owner, data, value ) {
+ var prop,
+ cache = this.cache( owner );
+
+ // Handle: [ owner, key, value ] args
+ // Always use camelCase key (gh-2257)
+ if ( typeof data === "string" ) {
+ cache[ jQuery.camelCase( data ) ] = value;
+
+ // Handle: [ owner, { properties } ] args
+ } else {
+
+ // Copy the properties one-by-one to the cache object
+ for ( prop in data ) {
+ cache[ jQuery.camelCase( prop ) ] = data[ prop ];
+ }
+ }
+ return cache;
+ },
+ get: function( owner, key ) {
+ return key === undefined ?
+ this.cache( owner ) :
+
+ // Always use camelCase key (gh-2257)
+ owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
+ },
+ access: function( owner, key, value ) {
+
+ // In cases where either:
+ //
+ // 1. No key was specified
+ // 2. A string key was specified, but no value provided
+ //
+ // Take the "read" path and allow the get method to determine
+ // which value to return, respectively either:
+ //
+ // 1. The entire cache object
+ // 2. The data stored at the key
+ //
+ if ( key === undefined ||
+ ( ( key && typeof key === "string" ) && value === undefined ) ) {
+
+ return this.get( owner, key );
+ }
+
+ // When the key is not a string, or both a key and value
+ // are specified, set or extend (existing objects) with either:
+ //
+ // 1. An object of properties
+ // 2. A key and value
+ //
+ this.set( owner, key, value );
+
+ // Since the "set" path can have two possible entry points
+ // return the expected data based on which path was taken[*]
+ return value !== undefined ? value : key;
+ },
+ remove: function( owner, key ) {
+ var i,
+ cache = owner[ this.expando ];
+
+ if ( cache === undefined ) {
+ return;
+ }
+
+ if ( key !== undefined ) {
+
+ // Support array or space separated string of keys
+ if ( Array.isArray( key ) ) {
+
+ // If key is an array of keys...
+ // We always set camelCase keys, so remove that.
+ key = key.map( jQuery.camelCase );
+ } else {
+ key = jQuery.camelCase( key );
+
+ // If a key with the spaces exists, use it.
+ // Otherwise, create an array by matching non-whitespace
+ key = key in cache ?
+ [ key ] :
+ ( key.match( rnothtmlwhite ) || [] );
+ }
+
+ i = key.length;
+
+ while ( i-- ) {
+ delete cache[ key[ i ] ];
+ }
+ }
+
+ // Remove the expando if there's no more data
+ if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
+
+ // Support: Chrome <=35 - 45
+ // Webkit & Blink performance suffers when deleting properties
+ // from DOM nodes, so set to undefined instead
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = undefined;
+ } else {
+ delete owner[ this.expando ];
+ }
+ }
+ },
+ hasData: function( owner ) {
+ var cache = owner[ this.expando ];
+ return cache !== undefined && !jQuery.isEmptyObject( cache );
+ }
+};
+var dataPriv = new Data();
+
+var dataUser = new Data();
+
+
+
+// Implementation Summary
+//
+// 1. Enforce API surface and semantic compatibility with 1.9.x branch
+// 2. Improve the module's maintainability by reducing the storage
+// paths to a single mechanism.
+// 3. Use the same single mechanism to support "private" and "user" data.
+// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+// 5. Avoid exposing implementation details on user objects (eg. expando properties)
+// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /[A-Z]/g;
+
+function getData( data ) {
+ if ( data === "true" ) {
+ return true;
+ }
+
+ if ( data === "false" ) {
+ return false;
+ }
+
+ if ( data === "null" ) {
+ return null;
+ }
+
+ // Only convert to a number if it doesn't change the string
+ if ( data === +data + "" ) {
+ return +data;
+ }
+
+ if ( rbrace.test( data ) ) {
+ return JSON.parse( data );
+ }
+
+ return data;
+}
+
+function dataAttr( elem, key, data ) {
+ var name;
+
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+ name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = getData( data );
+ } catch ( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ dataUser.set( elem, key, data );
+ } else {
+ data = undefined;
+ }
+ }
+ return data;
+}
+
+jQuery.extend( {
+ hasData: function( elem ) {
+ return dataUser.hasData( elem ) || dataPriv.hasData( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return dataUser.access( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ dataUser.remove( elem, name );
+ },
+
+ // TODO: Now that all calls to _data and _removeData have been replaced
+ // with direct calls to dataPriv methods, these can be deprecated.
+ _data: function( elem, name, data ) {
+ return dataPriv.access( elem, name, data );
+ },
+
+ _removeData: function( elem, name ) {
+ dataPriv.remove( elem, name );
+ }
+} );
+
+jQuery.fn.extend( {
+ data: function( key, value ) {
+ var i, name, data,
+ elem = this[ 0 ],
+ attrs = elem && elem.attributes;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = dataUser.get( elem );
+
+ if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
+ i = attrs.length;
+ while ( i-- ) {
+
+ // Support: IE 11 only
+ // The attrs elements can be null (#14894)
+ if ( attrs[ i ] ) {
+ name = attrs[ i ].name;
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice( 5 ) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ }
+ dataPriv.set( elem, "hasDataAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each( function() {
+ dataUser.set( this, key );
+ } );
+ }
+
+ return access( this, function( value ) {
+ var data;
+
+ // The calling jQuery object (element matches) is not empty
+ // (and therefore has an element appears at this[ 0 ]) and the
+ // `value` parameter was not undefined. An empty jQuery object
+ // will result in `undefined` for elem = this[ 0 ] which will
+ // throw an exception if an attempt to read a data cache is made.
+ if ( elem && value === undefined ) {
+
+ // Attempt to get data from the cache
+ // The key will always be camelCased in Data
+ data = dataUser.get( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // Attempt to "discover" the data in
+ // HTML5 custom data-* attrs
+ data = dataAttr( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // We tried really hard, but the data doesn't exist.
+ return;
+ }
+
+ // Set the data...
+ this.each( function() {
+
+ // We always store the camelCased key
+ dataUser.set( this, key, value );
+ } );
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each( function() {
+ dataUser.remove( this, key );
+ } );
+ }
+} );
+
+
+jQuery.extend( {
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = dataPriv.get( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || Array.isArray( data ) ) {
+ queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // Clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // Not public - generate a queueHooks object, or return the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
+ empty: jQuery.Callbacks( "once memory" ).add( function() {
+ dataPriv.remove( elem, [ type + "queue", key ] );
+ } )
+ } );
+ }
+} );
+
+jQuery.fn.extend( {
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[ 0 ], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each( function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // Ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ } );
+ },
+ dequeue: function( type ) {
+ return this.each( function() {
+ jQuery.dequeue( this, type );
+ } );
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while ( i-- ) {
+ tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+} );
+var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
+
+var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
+
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHiddenWithinTree = function( elem, el ) {
+
+ // isHiddenWithinTree might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+
+ // Inline style trumps all
+ return elem.style.display === "none" ||
+ elem.style.display === "" &&
+
+ // Otherwise, check computed style
+ // Support: Firefox <=43 - 45
+ // Disconnected elements can have computed display: none, so first confirm that elem is
+ // in the document.
+ jQuery.contains( elem.ownerDocument, elem ) &&
+
+ jQuery.css( elem, "display" ) === "none";
+ };
+
+var swap = function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+};
+
+
+
+
+function adjustCSS( elem, prop, valueParts, tween ) {
+ var adjusted,
+ scale = 1,
+ maxIterations = 20,
+ currentValue = tween ?
+ function() {
+ return tween.cur();
+ } :
+ function() {
+ return jQuery.css( elem, prop, "" );
+ },
+ initial = currentValue(),
+ unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
+ rcssNum.exec( jQuery.css( elem, prop ) );
+
+ if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
+
+ // Trust units reported by jQuery.css
+ unit = unit || initialInUnit[ 3 ];
+
+ // Make sure we update the tween properties later on
+ valueParts = valueParts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ initialInUnit = +initial || 1;
+
+ do {
+
+ // If previous iteration zeroed out, double until we get *something*.
+ // Use string for doubling so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ initialInUnit = initialInUnit / scale;
+ jQuery.style( elem, prop, initialInUnit + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // Break the loop if scale is unchanged or perfect, or if we've just had enough.
+ } while (
+ scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
+ );
+ }
+
+ if ( valueParts ) {
+ initialInUnit = +initialInUnit || +initial || 0;
+
+ // Apply relative offset (+=/-=) if specified
+ adjusted = valueParts[ 1 ] ?
+ initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
+ +valueParts[ 2 ];
+ if ( tween ) {
+ tween.unit = unit;
+ tween.start = initialInUnit;
+ tween.end = adjusted;
+ }
+ }
+ return adjusted;
+}
+
+
+var defaultDisplayMap = {};
+
+function getDefaultDisplay( elem ) {
+ var temp,
+ doc = elem.ownerDocument,
+ nodeName = elem.nodeName,
+ display = defaultDisplayMap[ nodeName ];
+
+ if ( display ) {
+ return display;
+ }
+
+ temp = doc.body.appendChild( doc.createElement( nodeName ) );
+ display = jQuery.css( temp, "display" );
+
+ temp.parentNode.removeChild( temp );
+
+ if ( display === "none" ) {
+ display = "block";
+ }
+ defaultDisplayMap[ nodeName ] = display;
+
+ return display;
+}
+
+function showHide( elements, show ) {
+ var display, elem,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ // Determine new display value for elements that need to change
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ display = elem.style.display;
+ if ( show ) {
+
+ // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
+ // check is required in this first loop unless we have a nonempty display value (either
+ // inline or about-to-be-restored)
+ if ( display === "none" ) {
+ values[ index ] = dataPriv.get( elem, "display" ) || null;
+ if ( !values[ index ] ) {
+ elem.style.display = "";
+ }
+ }
+ if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
+ values[ index ] = getDefaultDisplay( elem );
+ }
+ } else {
+ if ( display !== "none" ) {
+ values[ index ] = "none";
+
+ // Remember what we're overwriting
+ dataPriv.set( elem, "display", display );
+ }
+ }
+ }
+
+ // Set the display of the elements in a second loop to avoid constant reflow
+ for ( index = 0; index < length; index++ ) {
+ if ( values[ index ] != null ) {
+ elements[ index ].style.display = values[ index ];
+ }
+ }
+
+ return elements;
+}
+
+jQuery.fn.extend( {
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ if ( typeof state === "boolean" ) {
+ return state ? this.show() : this.hide();
+ }
+
+ return this.each( function() {
+ if ( isHiddenWithinTree( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ } );
+ }
+} );
+var rcheckableType = ( /^(?:checkbox|radio)$/i );
+
+var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
+
+var rscriptType = ( /^$|\/(?:java|ecma)script/i );
+
+
+
+// We have to close these tags to support XHTML (#13200)
+var wrapMap = {
+
+ // Support: IE <=9 only
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+ // XHTML parsers do not magically insert elements in the
+ // same way that tag soup parsers do. So we cannot shorten
+ // this by omitting <tbody> or other required elements.
+ thead: [ 1, "<table>", "</table>" ],
+ col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ _default: [ 0, "", "" ]
+};
+
+// Support: IE <=9 only
+wrapMap.optgroup = wrapMap.option;
+
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function getAll( context, tag ) {
+
+ // Support: IE <=9 - 11 only
+ // Use typeof to avoid zero-argument method invocation on host objects (#15151)
+ var ret;
+
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ ret = context.getElementsByTagName( tag || "*" );
+
+ } else if ( typeof context.querySelectorAll !== "undefined" ) {
+ ret = context.querySelectorAll( tag || "*" );
+
+ } else {
+ ret = [];
+ }
+
+ if ( tag === undefined || tag && nodeName( context, tag ) ) {
+ return jQuery.merge( [ context ], ret );
+ }
+
+ return ret;
+}
+
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ dataPriv.set(
+ elems[ i ],
+ "globalEval",
+ !refElements || dataPriv.get( refElements[ i ], "globalEval" )
+ );
+ }
+}
+
+
+var rhtml = /<|&#?\w+;/;
+
+function buildFragment( elems, context, scripts, selection, ignored ) {
+ var elem, tmp, tag, wrap, contains, j,
+ fragment = context.createDocumentFragment(),
+ nodes = [],
+ i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+ tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
+
+ // Descend through wrappers to the right content
+ j = wrap[ 0 ];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Remember the top-level container
+ tmp = fragment.firstChild;
+
+ // Ensure the created nodes are orphaned (#12392)
+ tmp.textContent = "";
+ }
+ }
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+
+ i = 0;
+ while ( ( elem = nodes[ i++ ] ) ) {
+
+ // Skip elements already in the context collection (trac-4087)
+ if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
+ if ( ignored ) {
+ ignored.push( elem );
+ }
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( fragment.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( ( elem = tmp[ j++ ] ) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ return fragment;
+}
+
+
+( function() {
+ var fragment = document.createDocumentFragment(),
+ div = fragment.appendChild( document.createElement( "div" ) ),
+ input = document.createElement( "input" );
+
+ // Support: Android 4.0 - 4.3 only
+ // Check state lost if the name is set (#11217)
+ // Support: Windows Web Apps (WWA)
+ // `name` and `type` must use .setAttribute for WWA (#14901)
+ input.setAttribute( "type", "radio" );
+ input.setAttribute( "checked", "checked" );
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+
+ // Support: Android <=4.1 only
+ // Older WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE <=11 only
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ div.innerHTML = "<textarea>x</textarea>";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+} )();
+var documentElement = document.documentElement;
+
+
+
+var
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+// Support: IE <=9 only
+// See #13393 for more info
+function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+}
+
+function on( elem, types, selector, data, fn, one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ on( elem, type, selector, data, types[ type ], one );
+ }
+ return elem;
+ }
+
+ if ( data == null && fn == null ) {
+
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return elem;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return elem.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ } );
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var handleObjIn, eventHandle, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.get( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Ensure that invalid selectors throw exceptions at attach time
+ // Evaluate against documentElement in case elem is a non-element node (e.g., document)
+ if ( selector ) {
+ jQuery.find.matchesSelector( documentElement, selector );
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !( events = elemData.events ) ) {
+ events = elemData.events = {};
+ }
+ if ( !( eventHandle = elemData.handle ) ) {
+ eventHandle = elemData.handle = function( e ) {
+
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
+ jQuery.event.dispatch.apply( elem, arguments ) : undefined;
+ };
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+ // There *must* be a type, no attaching namespace-only handlers
+ if ( !type ) {
+ continue;
+ }
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend( {
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join( "." )
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !( handlers = events[ type ] ) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener if the special events handler returns false
+ if ( !special.setup ||
+ special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var j, origCount, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
+
+ if ( !elemData || !( events = elemData.events ) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[ 2 ] &&
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector ||
+ selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown ||
+ special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove data and the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ dataPriv.remove( elem, "handle events" );
+ }
+ },
+
+ dispatch: function( nativeEvent ) {
+
+ // Make a writable jQuery.Event from the native event object
+ var event = jQuery.event.fix( nativeEvent );
+
+ var i, j, ret, matched, handleObj, handlerQueue,
+ args = new Array( arguments.length ),
+ handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[ 0 ] = event;
+
+ for ( i = 1; i < arguments.length; i++ ) {
+ args[ i ] = arguments[ i ];
+ }
+
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( ( handleObj = matched.handlers[ j++ ] ) &&
+ !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or 2) have namespace(s)
+ // a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
+ handleObj.handler ).apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( ( event.result = ret ) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var i, handleObj, sel, matchedHandlers, matchedSelectors,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ if ( delegateCount &&
+
+ // Support: IE <=9
+ // Black-hole SVG <use> instance trees (trac-13180)
+ cur.nodeType &&
+
+ // Support: Firefox <=42
+ // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
+ // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
+ // Support: IE 11 only
+ // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
+ !( event.type === "click" && event.button >= 1 ) ) {
+
+ for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
+ matchedHandlers = [];
+ matchedSelectors = {};
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matchedSelectors[ sel ] === undefined ) {
+ matchedSelectors[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) > -1 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matchedSelectors[ sel ] ) {
+ matchedHandlers.push( handleObj );
+ }
+ }
+ if ( matchedHandlers.length ) {
+ handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ cur = this;
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
+ }
+
+ return handlerQueue;
+ },
+
+ addProp: function( name, hook ) {
+ Object.defineProperty( jQuery.Event.prototype, name, {
+ enumerable: true,
+ configurable: true,
+
+ get: jQuery.isFunction( hook ) ?
+ function() {
+ if ( this.originalEvent ) {
+ return hook( this.originalEvent );
+ }
+ } :
+ function() {
+ if ( this.originalEvent ) {
+ return this.originalEvent[ name ];
+ }
+ },
+
+ set: function( value ) {
+ Object.defineProperty( this, name, {
+ enumerable: true,
+ configurable: true,
+ writable: true,
+ value: value
+ } );
+ }
+ } );
+ },
+
+ fix: function( originalEvent ) {
+ return originalEvent[ jQuery.expando ] ?
+ originalEvent :
+ new jQuery.Event( originalEvent );
+ },
+
+ special: {
+ load: {
+
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ focus: {
+
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== safeActiveElement() && this.focus ) {
+ this.focus();
+ return false;
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === safeActiveElement() && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+ click: {
+
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
+ this.click();
+ return false;
+ }
+ },
+
+ // For cross-browser consistency, don't fire native .click() on links
+ _default: function( event ) {
+ return nodeName( event.target, "a" );
+ }
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Support: Firefox 20+
+ // Firefox doesn't alert if the returnValue field is not set.
+ if ( event.result !== undefined && event.originalEvent ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ }
+};
+
+jQuery.removeEvent = function( elem, type, handle ) {
+
+ // This "if" is needed for plain objects
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle );
+ }
+};
+
+jQuery.Event = function( src, props ) {
+
+ // Allow instantiation without the 'new' keyword
+ if ( !( this instanceof jQuery.Event ) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = src.defaultPrevented ||
+ src.defaultPrevented === undefined &&
+
+ // Support: Android <=2.3 only
+ src.returnValue === false ?
+ returnTrue :
+ returnFalse;
+
+ // Create target properties
+ // Support: Safari <=6 - 7 only
+ // Target should not be a text node (#504, #13143)
+ this.target = ( src.target && src.target.nodeType === 3 ) ?
+ src.target.parentNode :
+ src.target;
+
+ this.currentTarget = src.currentTarget;
+ this.relatedTarget = src.relatedTarget;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ constructor: jQuery.Event,
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+ isSimulated: false,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.preventDefault();
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopPropagation();
+ }
+ },
+ stopImmediatePropagation: function() {
+ var e = this.originalEvent;
+
+ this.isImmediatePropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopImmediatePropagation();
+ }
+
+ this.stopPropagation();
+ }
+};
+
+// Includes all common event props including KeyEvent and MouseEvent specific props
+jQuery.each( {
+ altKey: true,
+ bubbles: true,
+ cancelable: true,
+ changedTouches: true,
+ ctrlKey: true,
+ detail: true,
+ eventPhase: true,
+ metaKey: true,
+ pageX: true,
+ pageY: true,
+ shiftKey: true,
+ view: true,
+ "char": true,
+ charCode: true,
+ key: true,
+ keyCode: true,
+ button: true,
+ buttons: true,
+ clientX: true,
+ clientY: true,
+ offsetX: true,
+ offsetY: true,
+ pointerId: true,
+ pointerType: true,
+ screenX: true,
+ screenY: true,
+ targetTouches: true,
+ toElement: true,
+ touches: true,
+
+ which: function( event ) {
+ var button = event.button;
+
+ // Add which for key events
+ if ( event.which == null && rkeyEvent.test( event.type ) ) {
+ return event.charCode != null ? event.charCode : event.keyCode;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
+ if ( button & 1 ) {
+ return 1;
+ }
+
+ if ( button & 2 ) {
+ return 3;
+ }
+
+ if ( button & 4 ) {
+ return 2;
+ }
+
+ return 0;
+ }
+
+ return event.which;
+ }
+}, jQuery.event.addProp );
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+// so that event delegation works in jQuery.
+// Do the same for pointerenter/pointerleave and pointerover/pointerout
+//
+// Support: Safari 7 only
+// Safari sends mouseenter too often; see:
+// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
+// for the description of the bug (it existed in older Chrome versions as well).
+jQuery.each( {
+ mouseenter: "mouseover",
+ mouseleave: "mouseout",
+ pointerenter: "pointerover",
+ pointerleave: "pointerout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mouseenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+} );
+
+jQuery.fn.extend( {
+
+ on: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn );
+ },
+ one: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ?
+ handleObj.origType + "." + handleObj.namespace :
+ handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each( function() {
+ jQuery.event.remove( this, types, fn, selector );
+ } );
+ }
+} );
+
+
+var
+
+ /* eslint-disable max-len */
+
+ // See https://github.com/eslint/eslint/issues/3229
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
+
+ /* eslint-enable */
+
+ // Support: IE <=10 - 11, Edge 12 - 13
+ // In IE/Edge using regex groups here causes severe slowdowns.
+ // See https://connect.microsoft.com/IE/feedback/details/1736512/
+ rnoInnerhtml = /<script|<style|<link/i,
+
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
+
+// Prefer a tbody over its parent table for containing new rows
+function manipulationTarget( elem, content ) {
+ if ( nodeName( elem, "table" ) &&
+ nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
+
+ return jQuery( ">tbody", elem )[ 0 ] || elem;
+ }
+
+ return elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+
+ if ( match ) {
+ elem.type = match[ 1 ];
+ } else {
+ elem.removeAttribute( "type" );
+ }
+
+ return elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+ var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
+
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // 1. Copy private data: events, handlers, etc.
+ if ( dataPriv.hasData( src ) ) {
+ pdataOld = dataPriv.access( src );
+ pdataCur = dataPriv.set( dest, pdataOld );
+ events = pdataOld.events;
+
+ if ( events ) {
+ delete pdataCur.handle;
+ pdataCur.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+ }
+
+ // 2. Copy user data
+ if ( dataUser.hasData( src ) ) {
+ udataOld = dataUser.access( src );
+ udataCur = jQuery.extend( {}, udataOld );
+
+ dataUser.set( dest, udataCur );
+ }
+}
+
+// Fix IE bugs, see support tests
+function fixInput( src, dest ) {
+ var nodeName = dest.nodeName.toLowerCase();
+
+ // Fails to persist the checked state of a cloned checkbox or radio button.
+ if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+ dest.checked = src.checked;
+
+ // Fails to return the selected option to the default selected state when cloning options
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+
+function domManip( collection, args, callback, ignored ) {
+
+ // Flatten any nested arrays
+ args = concat.apply( [], args );
+
+ var fragment, first, scripts, hasScripts, node, doc,
+ i = 0,
+ l = collection.length,
+ iNoClone = l - 1,
+ value = args[ 0 ],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction ||
+ ( l > 1 && typeof value === "string" &&
+ !support.checkClone && rchecked.test( value ) ) ) {
+ return collection.each( function( index ) {
+ var self = collection.eq( index );
+ if ( isFunction ) {
+ args[ 0 ] = value.call( this, index, self.html() );
+ }
+ domManip( self, args, callback, ignored );
+ } );
+ }
+
+ if ( l ) {
+ fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ // Require either new content or an interest in ignored elements to invoke the callback
+ if ( first || ignored ) {
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item
+ // instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call( collection[ i ], node, i );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !dataPriv.access( node, "globalEval" ) &&
+ jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+
+ // Optional AJAX dependency, but won't run scripts if not present
+ if ( jQuery._evalUrl ) {
+ jQuery._evalUrl( node.src );
+ }
+ } else {
+ DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return collection;
+}
+
+function remove( elem, selector, keepData ) {
+ var node,
+ nodes = selector ? jQuery.filter( selector, elem ) : elem,
+ i = 0;
+
+ for ( ; ( node = nodes[ i ] ) != null; i++ ) {
+ if ( !keepData && node.nodeType === 1 ) {
+ jQuery.cleanData( getAll( node ) );
+ }
+
+ if ( node.parentNode ) {
+ if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
+ setGlobalEval( getAll( node, "script" ) );
+ }
+ node.parentNode.removeChild( node );
+ }
+ }
+
+ return elem;
+}
+
+jQuery.extend( {
+ htmlPrefilter: function( html ) {
+ return html.replace( rxhtmlTag, "<$1></$2>" );
+ },
+
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var i, l, srcElements, destElements,
+ clone = elem.cloneNode( true ),
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ // Fix IE cloning issues
+ if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
+ !jQuery.isXMLDoc( elem ) ) {
+
+ // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ fixInput( srcElements[ i ], destElements[ i ] );
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ cloneCopyEvent( srcElements[ i ], destElements[ i ] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ // Return the cloned set
+ return clone;
+ },
+
+ cleanData: function( elems ) {
+ var data, elem, type,
+ special = jQuery.event.special,
+ i = 0;
+
+ for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
+ if ( acceptData( elem ) ) {
+ if ( ( data = elem[ dataPriv.expando ] ) ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Support: Chrome <=35 - 45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataPriv.expando ] = undefined;
+ }
+ if ( elem[ dataUser.expando ] ) {
+
+ // Support: Chrome <=35 - 45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataUser.expando ] = undefined;
+ }
+ }
+ }
+ }
+} );
+
+jQuery.fn.extend( {
+ detach: function( selector ) {
+ return remove( this, selector, true );
+ },
+
+ remove: function( selector ) {
+ return remove( this, selector );
+ },
+
+ text: function( value ) {
+ return access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().each( function() {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.textContent = value;
+ }
+ } );
+ }, null, value, arguments.length );
+ },
+
+ append: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.appendChild( elem );
+ }
+ } );
+ },
+
+ prepend: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.insertBefore( elem, target.firstChild );
+ }
+ } );
+ },
+
+ before: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ } );
+ },
+
+ after: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ } );
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; ( elem = this[ i ] ) != null; i++ ) {
+ if ( elem.nodeType === 1 ) {
+
+ // Prevent memory leaks
+ jQuery.cleanData( getAll( elem, false ) );
+
+ // Remove any remaining nodes
+ elem.textContent = "";
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function() {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ } );
+ },
+
+ html: function( value ) {
+ return access( this, function( value ) {
+ var elem = this[ 0 ] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined && elem.nodeType === 1 ) {
+ return elem.innerHTML;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
+
+ value = jQuery.htmlPrefilter( value );
+
+ try {
+ for ( ; i < l; i++ ) {
+ elem = this[ i ] || {};
+
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch ( e ) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function() {
+ var ignored = [];
+
+ // Make the changes, replacing each non-ignored context element with the new content
+ return domManip( this, arguments, function( elem ) {
+ var parent = this.parentNode;
+
+ if ( jQuery.inArray( this, ignored ) < 0 ) {
+ jQuery.cleanData( getAll( this ) );
+ if ( parent ) {
+ parent.replaceChild( elem, this );
+ }
+ }
+
+ // Force callback invocation
+ }, ignored );
+ }
+} );
+
+jQuery.each( {
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1,
+ i = 0;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone( true );
+ jQuery( insert[ i ] )[ original ]( elems );
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // .get() because push.apply(_, arraylike) throws on ancient WebKit
+ push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+} );
+var rmargin = ( /^margin/ );
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+var getStyles = function( elem ) {
+
+ // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
+ // IE throws on elements created in popups
+ // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+ var view = elem.ownerDocument.defaultView;
+
+ if ( !view || !view.opener ) {
+ view = window;
+ }
+
+ return view.getComputedStyle( elem );
+ };
+
+
+
+( function() {
+
+ // Executing both pixelPosition & boxSizingReliable tests require only one layout
+ // so they're executed at the same time to save the second computation.
+ function computeStyleTests() {
+
+ // This is a singleton, we need to execute it only once
+ if ( !div ) {
+ return;
+ }
+
+ div.style.cssText =
+ "box-sizing:border-box;" +
+ "position:relative;display:block;" +
+ "margin:auto;border:1px;padding:1px;" +
+ "top:1%;width:50%";
+ div.innerHTML = "";
+ documentElement.appendChild( container );
+
+ var divStyle = window.getComputedStyle( div );
+ pixelPositionVal = divStyle.top !== "1%";
+
+ // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
+ reliableMarginLeftVal = divStyle.marginLeft === "2px";
+ boxSizingReliableVal = divStyle.width === "4px";
+
+ // Support: Android 4.0 - 4.3 only
+ // Some styles come back with percentage values, even though they shouldn't
+ div.style.marginRight = "50%";
+ pixelMarginRightVal = divStyle.marginRight === "4px";
+
+ documentElement.removeChild( container );
+
+ // Nullify the div so it wouldn't be stored in the memory and
+ // it will also be a sign that checks already performed
+ div = null;
+ }
+
+ var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
+ container = document.createElement( "div" ),
+ div = document.createElement( "div" );
+
+ // Finish early in limited (non-browser) environments
+ if ( !div.style ) {
+ return;
+ }
+
+ // Support: IE <=9 - 11 only
+ // Style of cloned element affects source element cloned (#8908)
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
+ "padding:0;margin-top:1px;position:absolute";
+ container.appendChild( div );
+
+ jQuery.extend( support, {
+ pixelPosition: function() {
+ computeStyleTests();
+ return pixelPositionVal;
+ },
+ boxSizingReliable: function() {
+ computeStyleTests();
+ return boxSizingReliableVal;
+ },
+ pixelMarginRight: function() {
+ computeStyleTests();
+ return pixelMarginRightVal;
+ },
+ reliableMarginLeft: function() {
+ computeStyleTests();
+ return reliableMarginLeftVal;
+ }
+ } );
+} )();
+
+
+function curCSS( elem, name, computed ) {
+ var width, minWidth, maxWidth, ret,
+
+ // Support: Firefox 51+
+ // Retrieving style before computed somehow
+ // fixes an issue with getting wrong values
+ // on detached elements
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+
+ // getPropertyValue is needed for:
+ // .css('filter') (IE 9 only, #12537)
+ // .css('--customProperty) (#3144)
+ if ( computed ) {
+ ret = computed.getPropertyValue( name ) || computed[ name ];
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Android Browser returns percentage for some values,
+ // but width seems to be reliably pixels.
+ // This is against the CSSOM draft spec:
+ // https://drafts.csswg.org/cssom/#resolved-values
+ if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret !== undefined ?
+
+ // Support: IE <=9 - 11 only
+ // IE returns zIndex value as an integer.
+ ret + "" :
+ ret;
+}
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+
+ // Define the hook, we'll check on the first run if it's really needed.
+ return {
+ get: function() {
+ if ( conditionFn() ) {
+
+ // Hook not needed (or it's not possible to use it due
+ // to missing dependency), remove it.
+ delete this.get;
+ return;
+ }
+
+ // Hook needed; redefine it so that the support test is not executed again.
+ return ( this.get = hookFn ).apply( this, arguments );
+ }
+ };
+}
+
+
+var
+
+ // Swappable if display is none or starts with table
+ // except "table", "table-cell", or "table-caption"
+ // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rcustomProp = /^--/,
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: "0",
+ fontWeight: "400"
+ },
+
+ cssPrefixes = [ "Webkit", "Moz", "ms" ],
+ emptyStyle = document.createElement( "div" ).style;
+
+// Return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( name ) {
+
+ // Shortcut for names that are not vendor prefixed
+ if ( name in emptyStyle ) {
+ return name;
+ }
+
+ // Check for vendor prefixed names
+ var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in emptyStyle ) {
+ return name;
+ }
+ }
+}
+
+// Return a property mapped along what jQuery.cssProps suggests or to
+// a vendor prefixed property.
+function finalPropName( name ) {
+ var ret = jQuery.cssProps[ name ];
+ if ( !ret ) {
+ ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;
+ }
+ return ret;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+
+ // Any relative (+/-) values have already been
+ // normalized at this point
+ var matches = rcssNum.exec( value );
+ return matches ?
+
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i,
+ val = 0;
+
+ // If we already have the right measurement, avoid augmentation
+ if ( extra === ( isBorderBox ? "border" : "content" ) ) {
+ i = 4;
+
+ // Otherwise initialize for horizontal or vertical properties
+ } else {
+ i = name === "width" ? 1 : 0;
+ }
+
+ for ( ; i < 4; i += 2 ) {
+
+ // Both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // At this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+
+ // At this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // At this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with computed style
+ var valueIsBorderBox,
+ styles = getStyles( elem ),
+ val = curCSS( elem, name, styles ),
+ isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test( val ) ) {
+ return val;
+ }
+
+ // Check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox &&
+ ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+ // Fall back to offsetWidth/Height when value is "auto"
+ // This happens for inline elements with no explicit setting (gh-3571)
+ if ( val === "auto" ) {
+ val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];
+ }
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+
+ // Use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+jQuery.extend( {
+
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Don't automatically add "px" to these possibly-unitless properties
+ cssNumber: {
+ "animationIterationCount": true,
+ "columnCount": true,
+ "fillOpacity": true,
+ "flexGrow": true,
+ "flexShrink": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "order": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ "float": "cssFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ isCustomProp = rcustomProp.test( name ),
+ style = elem.style;
+
+ // Make sure that we're working with the right name. We don't
+ // want to query the value if it is a CSS custom property
+ // since they are user-defined.
+ if ( !isCustomProp ) {
+ name = finalPropName( origName );
+ }
+
+ // Gets hook for the prefixed version, then unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // Convert "+=" or "-=" to relative numbers (#7345)
+ if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
+ value = adjustCSS( elem, name, ret );
+
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that null and NaN values aren't set (#7116)
+ if ( value == null || value !== value ) {
+ return;
+ }
+
+ // If a number was passed in, add the unit (except for certain CSS properties)
+ if ( type === "number" ) {
+ value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
+ }
+
+ // background-* props affect original clone's values
+ if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !( "set" in hooks ) ||
+ ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
+
+ if ( isCustomProp ) {
+ style.setProperty( name, value );
+ } else {
+ style[ name ] = value;
+ }
+ }
+
+ } else {
+
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks &&
+ ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
+
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var val, num, hooks,
+ origName = jQuery.camelCase( name ),
+ isCustomProp = rcustomProp.test( name );
+
+ // Make sure that we're working with the right name. We don't
+ // want to modify the value if it is a CSS custom property
+ // since they are user-defined.
+ if ( !isCustomProp ) {
+ name = finalPropName( origName );
+ }
+
+ // Try prefixed name followed by the unprefixed name
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ // Convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Make numeric if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || isFinite( num ) ? num || 0 : val;
+ }
+
+ return val;
+ }
+} );
+
+jQuery.each( [ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+
+ // Certain elements can have dimension info if we invisibly show them
+ // but it must have a current display style that would benefit
+ return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
+
+ // Support: Safari 8+
+ // Table columns in Safari have non-zero offsetWidth & zero
+ // getBoundingClientRect().width unless display is changed.
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a disconnected node
+ // in IE throws an error.
+ ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
+ swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ } ) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var matches,
+ styles = extra && getStyles( elem ),
+ subtract = extra && augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ );
+
+ // Convert to pixels if value adjustment is needed
+ if ( subtract && ( matches = rcssNum.exec( value ) ) &&
+ ( matches[ 3 ] || "px" ) !== "px" ) {
+
+ elem.style[ name ] = value;
+ value = jQuery.css( elem, name );
+ }
+
+ return setPositiveNumber( elem, value, subtract );
+ }
+ };
+} );
+
+jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
+ function( elem, computed ) {
+ if ( computed ) {
+ return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
+ elem.getBoundingClientRect().left -
+ swap( elem, { marginLeft: 0 }, function() {
+ return elem.getBoundingClientRect().left;
+ } )
+ ) + "px";
+ }
+ }
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each( {
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // Assumes a single number if not a string
+ parts = typeof value === "string" ? value.split( " " ) : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+} );
+
+jQuery.fn.extend( {
+ css: function( name, value ) {
+ return access( this, function( elem, name, value ) {
+ var styles, len,
+ map = {},
+ i = 0;
+
+ if ( Array.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ }
+} );
+
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || jQuery.easing._default;
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ // Use a property on the element directly when it is not a DOM element,
+ // or when there is no matching style property that exists.
+ if ( tween.elem.nodeType !== 1 ||
+ tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // Passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails.
+ // Simple values such as "10px" are parsed to Float;
+ // complex values such as "rotate(1rad)" are returned as-is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+
+ // Use step hook for back compat.
+ // Use cssHook if its there.
+ // Use .style if available and use plain properties where available.
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.nodeType === 1 &&
+ ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
+ jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Support: IE <=9 only
+// Panic based approach to setting things on disconnected nodes
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p * Math.PI ) / 2;
+ },
+ _default: "swing"
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+ fxNow, inProgress,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rrun = /queueHooks$/;
+
+function schedule() {
+ if ( inProgress ) {
+ if ( document.hidden === false && window.requestAnimationFrame ) {
+ window.requestAnimationFrame( schedule );
+ } else {
+ window.setTimeout( schedule, jQuery.fx.interval );
+ }
+
+ jQuery.fx.tick();
+ }
+}
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ window.setTimeout( function() {
+ fxNow = undefined;
+ } );
+ return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ i = 0,
+ attrs = { height: type };
+
+ // If we include width, step value is 1 to do all cssExpand values,
+ // otherwise step value is 2 to skip over Left and Right
+ includeWidth = includeWidth ? 1 : 0;
+ for ( ; i < 4; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
+
+ // We're done with this property
+ return tween;
+ }
+ }
+}
+
+function defaultPrefilter( elem, props, opts ) {
+ var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
+ isBox = "width" in props || "height" in props,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHiddenWithinTree( elem ),
+ dataShow = dataPriv.get( elem, "fxshow" );
+
+ // Queue-skipping animations hijack the fx hooks
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always( function() {
+
+ // Ensure the complete handler is called before this completes
+ anim.always( function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ } );
+ } );
+ }
+
+ // Detect show/hide animations
+ for ( prop in props ) {
+ value = props[ prop ];
+ if ( rfxtypes.test( value ) ) {
+ delete props[ prop ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+
+ // Pretend to be hidden if this is a "show" and
+ // there is still data from a stopped show/hide
+ if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+ hidden = true;
+
+ // Ignore all other no-op show/hide data
+ } else {
+ continue;
+ }
+ }
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+ }
+ }
+
+ // Bail out if this is a no-op like .hide().hide()
+ propTween = !jQuery.isEmptyObject( props );
+ if ( !propTween && jQuery.isEmptyObject( orig ) ) {
+ return;
+ }
+
+ // Restrict "overflow" and "display" styles during box animations
+ if ( isBox && elem.nodeType === 1 ) {
+
+ // Support: IE <=9 - 11, Edge 12 - 13
+ // Record all 3 overflow attributes because IE does not infer the shorthand
+ // from identically-valued overflowX and overflowY
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Identify a display type, preferring old show/hide data over the CSS cascade
+ restoreDisplay = dataShow && dataShow.display;
+ if ( restoreDisplay == null ) {
+ restoreDisplay = dataPriv.get( elem, "display" );
+ }
+ display = jQuery.css( elem, "display" );
+ if ( display === "none" ) {
+ if ( restoreDisplay ) {
+ display = restoreDisplay;
+ } else {
+
+ // Get nonempty value(s) by temporarily forcing visibility
+ showHide( [ elem ], true );
+ restoreDisplay = elem.style.display || restoreDisplay;
+ display = jQuery.css( elem, "display" );
+ showHide( [ elem ] );
+ }
+ }
+
+ // Animate inline elements as inline-block
+ if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
+ if ( jQuery.css( elem, "float" ) === "none" ) {
+
+ // Restore the original display value at the end of pure show/hide animations
+ if ( !propTween ) {
+ anim.done( function() {
+ style.display = restoreDisplay;
+ } );
+ if ( restoreDisplay == null ) {
+ display = style.display;
+ restoreDisplay = display === "none" ? "" : display;
+ }
+ }
+ style.display = "inline-block";
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ anim.always( function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ } );
+ }
+
+ // Implement show/hide animations
+ propTween = false;
+ for ( prop in orig ) {
+
+ // General show/hide setup for this element animation
+ if ( !propTween ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
+ }
+
+ // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+
+ // Show elements before animating them
+ if ( hidden ) {
+ showHide( [ elem ], true );
+ }
+
+ /* eslint-disable no-loop-func */
+
+ anim.done( function() {
+
+ /* eslint-enable no-loop-func */
+
+ // The final step of a "hide" animation is actually hiding the element
+ if ( !hidden ) {
+ showHide( [ elem ] );
+ }
+ dataPriv.remove( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ } );
+ }
+
+ // Per-property setup
+ propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = propTween.start;
+ if ( hidden ) {
+ propTween.end = propTween.start;
+ propTween.start = 0;
+ }
+ }
+ }
+}
+
+function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( Array.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // Not quite $.extend, this won't overwrite existing keys.
+ // Reusing 'index' because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = Animation.prefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+
+ // Don't match elem in the :animated selector
+ delete tick.elem;
+ } ),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+
+ // Support: Android 2.3 only
+ // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ] );
+
+ // If there's more to do, yield
+ if ( percent < 1 && length ) {
+ return remaining;
+ }
+
+ // If this was an empty animation, synthesize a final progress notification
+ if ( !length ) {
+ deferred.notifyWith( elem, [ animation, 1, 0 ] );
+ }
+
+ // Resolve the animation and report its conclusion
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ },
+ animation = deferred.promise( {
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, {
+ specialEasing: {},
+ easing: jQuery.easing._default
+ }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+
+ // If we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // Resolve when we played the last frame; otherwise, reject
+ if ( gotoEnd ) {
+ deferred.notifyWith( elem, [ animation, 1, 0 ] );
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ } ),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length; index++ ) {
+ result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ if ( jQuery.isFunction( result.stop ) ) {
+ jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
+ jQuery.proxy( result.stop, result );
+ }
+ return result;
+ }
+ }
+
+ jQuery.map( props, createTween, animation );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ // Attach callbacks from options
+ animation
+ .progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ } )
+ );
+
+ return animation;
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+ tweeners: {
+ "*": [ function( prop, value ) {
+ var tween = this.createTween( prop, value );
+ adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
+ return tween;
+ } ]
+ },
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.match( rnothtmlwhite );
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length; index++ ) {
+ prop = props[ index ];
+ Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
+ Animation.tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilters: [ defaultPrefilter ],
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ Animation.prefilters.unshift( callback );
+ } else {
+ Animation.prefilters.push( callback );
+ }
+ }
+} );
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ // Go to the end state if fx are off
+ if ( jQuery.fx.off ) {
+ opt.duration = 0;
+
+ } else {
+ if ( typeof opt.duration !== "number" ) {
+ if ( opt.duration in jQuery.fx.speeds ) {
+ opt.duration = jQuery.fx.speeds[ opt.duration ];
+
+ } else {
+ opt.duration = jQuery.fx.speeds._default;
+ }
+ }
+ }
+
+ // Normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.fn.extend( {
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // Show any hidden elements after setting opacity to 0
+ return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
+
+ // Animate to the value specified
+ .end().animate( { opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+ // Empty animations, or finishing resolves immediately
+ if ( empty || dataPriv.get( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each( function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = dataPriv.get( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this &&
+ ( type == null || timers[ index ].queue === type ) ) {
+
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // Start the next in the queue if the last step wasn't forced.
+ // Timers currently will call their complete callbacks, which
+ // will dequeue but only if they were gotoEnd.
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ } );
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each( function() {
+ var index,
+ data = dataPriv.get( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // Enable finishing flag on private data
+ data.finish = true;
+
+ // Empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.stop ) {
+ hooks.stop.call( this, true );
+ }
+
+ // Look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // Look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // Turn off finishing flag
+ delete data.finish;
+ } );
+ }
+} );
+
+jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+} );
+
+// Generate shortcuts for custom animations
+jQuery.each( {
+ slideDown: genFx( "show" ),
+ slideUp: genFx( "hide" ),
+ slideToggle: genFx( "toggle" ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+} );
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+ var timer,
+ i = 0,
+ timers = jQuery.timers;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+
+ // Run the timer and safely remove it when done (allowing for external removal)
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ jQuery.timers.push( timer );
+ jQuery.fx.start();
+};
+
+jQuery.fx.interval = 13;
+jQuery.fx.start = function() {
+ if ( inProgress ) {
+ return;
+ }
+
+ inProgress = true;
+ schedule();
+};
+
+jQuery.fx.stop = function() {
+ inProgress = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+
+ // Default speed
+ _default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = window.setTimeout( next, time );
+ hooks.stop = function() {
+ window.clearTimeout( timeout );
+ };
+ } );
+};
+
+
+( function() {
+ var input = document.createElement( "input" ),
+ select = document.createElement( "select" ),
+ opt = select.appendChild( document.createElement( "option" ) );
+
+ input.type = "checkbox";
+
+ // Support: Android <=4.3 only
+ // Default value for a checkbox should be "on"
+ support.checkOn = input.value !== "";
+
+ // Support: IE <=11 only
+ // Must access selectedIndex to make default options select
+ support.optSelected = opt.selected;
+
+ // Support: IE <=11 only
+ // An input loses its value after becoming a radio
+ input = document.createElement( "input" );
+ input.value = "t";
+ input.type = "radio";
+ support.radioValue = input.value === "t";
+} )();
+
+
+var boolHook,
+ attrHandle = jQuery.expr.attrHandle;
+
+jQuery.fn.extend( {
+ attr: function( name, value ) {
+ return access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each( function() {
+ jQuery.removeAttr( this, name );
+ } );
+ }
+} );
+
+jQuery.extend( {
+ attr: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set attributes on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ // Attribute hooks are determined by the lowercase version
+ // Grab necessary hook if one is defined
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+ hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
+ }
+
+ if ( value !== undefined ) {
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+ }
+
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ ret = jQuery.find.attr( elem, name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ? undefined : ret;
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !support.radioValue && value === "radio" &&
+ nodeName( elem, "input" ) ) {
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name,
+ i = 0,
+
+ // Attribute names can contain non-HTML whitespace characters
+ // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
+ attrNames = value && value.match( rnothtmlwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( ( name = attrNames[ i++ ] ) ) {
+ elem.removeAttribute( name );
+ }
+ }
+ }
+} );
+
+// Hooks for boolean attributes
+boolHook = {
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ elem.setAttribute( name, name );
+ }
+ return name;
+ }
+};
+
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+ var getter = attrHandle[ name ] || jQuery.find.attr;
+
+ attrHandle[ name ] = function( elem, name, isXML ) {
+ var ret, handle,
+ lowercaseName = name.toLowerCase();
+
+ if ( !isXML ) {
+
+ // Avoid an infinite loop by temporarily removing this function from the getter
+ handle = attrHandle[ lowercaseName ];
+ attrHandle[ lowercaseName ] = ret;
+ ret = getter( elem, name, isXML ) != null ?
+ lowercaseName :
+ null;
+ attrHandle[ lowercaseName ] = handle;
+ }
+ return ret;
+ };
+} );
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button)$/i,
+ rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend( {
+ prop: function( name, value ) {
+ return access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ return this.each( function() {
+ delete this[ jQuery.propFix[ name ] || name ];
+ } );
+ }
+} );
+
+jQuery.extend( {
+ prop: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set properties on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ return ( elem[ name ] = value );
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ return elem[ name ];
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+
+ // Support: IE <=9 - 11 only
+ // elem.tabIndex doesn't always return the
+ // correct value when it hasn't been explicitly set
+ // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ // Use proper attribute retrieval(#12072)
+ var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+ if ( tabindex ) {
+ return parseInt( tabindex, 10 );
+ }
+
+ if (
+ rfocusable.test( elem.nodeName ) ||
+ rclickable.test( elem.nodeName ) &&
+ elem.href
+ ) {
+ return 0;
+ }
+
+ return -1;
+ }
+ }
+ },
+
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ }
+} );
+
+// Support: IE <=11 only
+// Accessing the selectedIndex property
+// forces the browser to respect setting selected
+// on the option
+// The getter ensures a default option is selected
+// when in an optgroup
+// eslint rule "no-unused-expressions" is disabled for this code
+// since it considers such accessions noop
+if ( !support.optSelected ) {
+ jQuery.propHooks.selected = {
+ get: function( elem ) {
+
+ /* eslint no-unused-expressions: "off" */
+
+ var parent = elem.parentNode;
+ if ( parent && parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ return null;
+ },
+ set: function( elem ) {
+
+ /* eslint no-unused-expressions: "off" */
+
+ var parent = elem.parentNode;
+ if ( parent ) {
+ parent.selectedIndex;
+
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ }
+ };
+}
+
+jQuery.each( [
+ "tabIndex",
+ "readOnly",
+ "maxLength",
+ "cellSpacing",
+ "cellPadding",
+ "rowSpan",
+ "colSpan",
+ "useMap",
+ "frameBorder",
+ "contentEditable"
+], function() {
+ jQuery.propFix[ this.toLowerCase() ] = this;
+} );
+
+
+
+
+ // Strip and collapse whitespace according to HTML spec
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace
+ function stripAndCollapse( value ) {
+ var tokens = value.match( rnothtmlwhite ) || [];
+ return tokens.join( " " );
+ }
+
+
+function getClass( elem ) {
+ return elem.getAttribute && elem.getAttribute( "class" ) || "";
+}
+
+jQuery.fn.extend( {
+ addClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnothtmlwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+ cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = stripAndCollapse( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( !arguments.length ) {
+ return this.attr( "class", "" );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnothtmlwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = stripAndCollapse( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value;
+
+ if ( typeof stateVal === "boolean" && type === "string" ) {
+ return stateVal ? this.addClass( value ) : this.removeClass( value );
+ }
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).toggleClass(
+ value.call( this, i, getClass( this ), stateVal ),
+ stateVal
+ );
+ } );
+ }
+
+ return this.each( function() {
+ var className, i, self, classNames;
+
+ if ( type === "string" ) {
+
+ // Toggle individual class names
+ i = 0;
+ self = jQuery( this );
+ classNames = value.match( rnothtmlwhite ) || [];
+
+ while ( ( className = classNames[ i++ ] ) ) {
+
+ // Check each className given, space separated list
+ if ( self.hasClass( className ) ) {
+ self.removeClass( className );
+ } else {
+ self.addClass( className );
+ }
+ }
+
+ // Toggle whole class name
+ } else if ( value === undefined || type === "boolean" ) {
+ className = getClass( this );
+ if ( className ) {
+
+ // Store className if set
+ dataPriv.set( this, "__className__", className );
+ }
+
+ // If the element has a class name or if we're passed `false`,
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ if ( this.setAttribute ) {
+ this.setAttribute( "class",
+ className || value === false ?
+ "" :
+ dataPriv.get( this, "__className__" ) || ""
+ );
+ }
+ }
+ } );
+ },
+
+ hasClass: function( selector ) {
+ var className, elem,
+ i = 0;
+
+ className = " " + selector + " ";
+ while ( ( elem = this[ i++ ] ) ) {
+ if ( elem.nodeType === 1 &&
+ ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+} );
+
+
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend( {
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[ 0 ];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] ||
+ jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks &&
+ "get" in hooks &&
+ ( ret = hooks.get( elem, "value" ) ) !== undefined
+ ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ // Handle most common string cases
+ if ( typeof ret === "string" ) {
+ return ret.replace( rreturn, "" );
+ }
+
+ // Handle cases where value is null/undef or number
+ return ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each( function( i ) {
+ var val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, jQuery( this ).val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+
+ } else if ( typeof val === "number" ) {
+ val += "";
+
+ } else if ( Array.isArray( val ) ) {
+ val = jQuery.map( val, function( value ) {
+ return value == null ? "" : value + "";
+ } );
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ } );
+ }
+} );
+
+jQuery.extend( {
+ valHooks: {
+ option: {
+ get: function( elem ) {
+
+ var val = jQuery.find.attr( elem, "value" );
+ return val != null ?
+ val :
+
+ // Support: IE <=10 - 11 only
+ // option.text throws exceptions (#14686, #14858)
+ // Strip and collapse whitespace
+ // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
+ stripAndCollapse( jQuery.text( elem ) );
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option, i,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one",
+ values = one ? null : [],
+ max = one ? index + 1 : options.length;
+
+ if ( index < 0 ) {
+ i = max;
+
+ } else {
+ i = one ? index : 0;
+ }
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Support: IE <=9 only
+ // IE8-9 doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+
+ // Don't return options that are disabled or in a disabled optgroup
+ !option.disabled &&
+ ( !option.parentNode.disabled ||
+ !nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var optionSet, option,
+ options = elem.options,
+ values = jQuery.makeArray( value ),
+ i = options.length;
+
+ while ( i-- ) {
+ option = options[ i ];
+
+ /* eslint-disable no-cond-assign */
+
+ if ( option.selected =
+ jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
+ ) {
+ optionSet = true;
+ }
+
+ /* eslint-enable no-cond-assign */
+ }
+
+ // Force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ }
+} );
+
+// Radios and checkboxes getter/setter
+jQuery.each( [ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ set: function( elem, value ) {
+ if ( Array.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
+ }
+ }
+ };
+ if ( !support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ return elem.getAttribute( "value" ) === null ? "on" : elem.value;
+ };
+ }
+} );
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
+
+jQuery.extend( jQuery.event, {
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+
+ var i, cur, tmp, bubbleType, ontype, handle, special,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "." ) > -1 ) {
+
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split( "." );
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf( ":" ) < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join( "." );
+ event.rnamespace = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === ( elem.ownerDocument || document ) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
+ dataPriv.get( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === false ) {
+ event.preventDefault();
+ }
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( ( !special._default ||
+ special._default.apply( eventPath.pop(), data ) === false ) &&
+ acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name as the event.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ // Piggyback on a donor event to simulate a different one
+ // Used only for `focus(in | out)` events
+ simulate: function( type, elem, event ) {
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true
+ }
+ );
+
+ jQuery.event.trigger( e, null, elem );
+ }
+
+} );
+
+jQuery.fn.extend( {
+
+ trigger: function( type, data ) {
+ return this.each( function() {
+ jQuery.event.trigger( type, data, this );
+ } );
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[ 0 ];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+} );
+
+
+jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup contextmenu" ).split( " " ),
+ function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+} );
+
+jQuery.fn.extend( {
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+} );
+
+
+
+
+support.focusin = "onfocusin" in window;
+
+
+// Support: Firefox <=44
+// Firefox doesn't have focus(in | out) events
+// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
+//
+// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
+// focus(in | out) events fire after focus & blur events,
+// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
+// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
+if ( !support.focusin ) {
+ jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler on the document while someone wants focusin/focusout
+ var handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix );
+
+ if ( !attaches ) {
+ doc.addEventListener( orig, handler, true );
+ }
+ dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
+ },
+ teardown: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix ) - 1;
+
+ if ( !attaches ) {
+ doc.removeEventListener( orig, handler, true );
+ dataPriv.remove( doc, fix );
+
+ } else {
+ dataPriv.access( doc, fix, attaches );
+ }
+ }
+ };
+ } );
+}
+var location = window.location;
+
+var nonce = jQuery.now();
+
+var rquery = ( /\?/ );
+
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+ var xml;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+
+ // Support: IE 9 - 11 only
+ // IE throws on parseFromString with invalid input.
+ try {
+ xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
+ } catch ( e ) {
+ xml = undefined;
+ }
+
+ if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+};
+
+
+var
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( Array.isArray( obj ) ) {
+
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams(
+ prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
+ v,
+ traditional,
+ add
+ );
+ }
+ } );
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, valueOrFunction ) {
+
+ // If value is a function, invoke it and use its return value
+ var value = jQuery.isFunction( valueOrFunction ) ?
+ valueOrFunction() :
+ valueOrFunction;
+
+ s[ s.length ] = encodeURIComponent( key ) + "=" +
+ encodeURIComponent( value == null ? "" : value );
+ };
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ } );
+
+ } else {
+
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" );
+};
+
+jQuery.fn.extend( {
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map( function() {
+
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ } )
+ .filter( function() {
+ var type = this.type;
+
+ // Use .is( ":disabled" ) so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !rcheckableType.test( type ) );
+ } )
+ .map( function( i, elem ) {
+ var val = jQuery( this ).val();
+
+ if ( val == null ) {
+ return null;
+ }
+
+ if ( Array.isArray( val ) ) {
+ return jQuery.map( val, function( val ) {
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } );
+ }
+
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } ).get();
+ }
+} );
+
+
+var
+ r20 = /%20/g,
+ rhash = /#.*$/,
+ rantiCache = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat( "*" ),
+
+ // Anchor tag for parsing the document origin
+ originAnchor = document.createElement( "a" );
+ originAnchor.href = location.href;
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+
+ // For each dataType in the dataTypeExpression
+ while ( ( dataType = dataTypes[ i++ ] ) ) {
+
+ // Prepend if requested
+ if ( dataType[ 0 ] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
+
+ // Otherwise append
+ } else {
+ ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if ( typeof dataTypeOrTransport === "string" &&
+ !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ } );
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var ct, type, finalDataType, firstDataType,
+ contents = s.contents,
+ dataTypes = s.dataTypes;
+
+ // Remove auto dataType and get content-type in the process
+ while ( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+ var conv2, current, conv, tmp, prev,
+ converters = {},
+
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice();
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ current = dataTypes.shift();
+
+ // Convert to each sequential dataType
+ while ( current ) {
+
+ if ( s.responseFields[ current ] ) {
+ jqXHR[ s.responseFields[ current ] ] = response;
+ }
+
+ // Apply the dataFilter if provided
+ if ( !prev && isSuccess && s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ prev = current;
+ current = dataTypes.shift();
+
+ if ( current ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current === "*" ) {
+
+ current = prev;
+
+ // Convert response if prev dataType is non-auto and differs from current
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split( " " );
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.unshift( tmp[ 1 ] );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s.throws ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return {
+ state: "parsererror",
+ error: conv ? e : "No conversion from " + prev + " to " + current
+ };
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { state: "success", data: response };
+}
+
+jQuery.extend( {
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: location.href,
+ type: "GET",
+ isLocal: rlocalProtocol.test( location.protocol ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /\bxml\b/,
+ html: /\bhtml/,
+ json: /\bjson\b/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText",
+ json: "responseJSON"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": JSON.parse,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var transport,
+
+ // URL without anti-cache param
+ cacheURL,
+
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+
+ // timeout handle
+ timeoutTimer,
+
+ // Url cleanup var
+ urlAnchor,
+
+ // Request state (becomes false upon send and true upon completion)
+ completed,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ // Loop variable
+ i,
+
+ // uncached part of the url
+ uncached,
+
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+
+ // Callbacks context
+ callbackContext = s.context || s,
+
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context &&
+ ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+
+ // Default abort message
+ strAbort = "canceled",
+
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( completed ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return completed ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ if ( completed == null ) {
+ name = requestHeadersNames[ name.toLowerCase() ] =
+ requestHeadersNames[ name.toLowerCase() ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( completed == null ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( completed ) {
+
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ } else {
+
+ // Lazy-add the new callbacks in a way that preserves old ones
+ for ( code in map ) {
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR );
+
+ // Add protocol if not provided (prefilters might expect it)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || location.href ) + "" )
+ .replace( rprotocol, location.protocol + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
+
+ // A cross-domain request is in order when the origin doesn't match the current origin.
+ if ( s.crossDomain == null ) {
+ urlAnchor = document.createElement( "a" );
+
+ // Support: IE <=8 - 11, Edge 12 - 13
+ // IE throws exception on accessing the href property if url is malformed,
+ // e.g. http://example.com:80x/
+ try {
+ urlAnchor.href = s.url;
+
+ // Support: IE <=8 - 11 only
+ // Anchor's host property isn't correctly set when s.url is relative
+ urlAnchor.href = urlAnchor.href;
+ s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
+ urlAnchor.protocol + "//" + urlAnchor.host;
+ } catch ( e ) {
+
+ // If there is an error parsing the URL, assume it is crossDomain,
+ // it can be rejected by the transport if it is invalid
+ s.crossDomain = true;
+ }
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( completed ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+ fireGlobals = jQuery.event && s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ // Remove hash to simplify url manipulation
+ cacheURL = s.url.replace( rhash, "" );
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // Remember the hash so we can put it back
+ uncached = s.url.slice( cacheURL.length );
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
+
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add or update anti-cache param if needed
+ if ( s.cache === false ) {
+ cacheURL = cacheURL.replace( rantiCache, "$1" );
+ uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
+ }
+
+ // Put hash and anti-cache on the URL that will be requested (gh-1732)
+ s.url = cacheURL + uncached;
+
+ // Change '%20' to '+' if this is encoded form body content (gh-2658)
+ } else if ( s.data && s.processData &&
+ ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
+ s.data = s.data.replace( r20, "+" );
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
+ s.accepts[ s.dataTypes[ 0 ] ] +
+ ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend &&
+ ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
+
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // Aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ completeDeferred.add( s.complete );
+ jqXHR.done( s.success );
+ jqXHR.fail( s.error );
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+
+ // If request was aborted inside ajaxSend, stop there
+ if ( completed ) {
+ return jqXHR;
+ }
+
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = window.setTimeout( function() {
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
+
+ try {
+ completed = false;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+
+ // Rethrow post-completion exceptions
+ if ( completed ) {
+ throw e;
+ }
+
+ // Propagate others as results
+ done( -1, e );
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Ignore repeat invocations
+ if ( completed ) {
+ return;
+ }
+
+ completed = true;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ window.clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Determine if successful
+ isSuccess = status >= 200 && status < 300 || status === 304;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // Convert no matter what (that way responseXXX fields are always set)
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+ // If successful, handle type chaining
+ if ( isSuccess ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader( "Last-Modified" );
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader( "etag" );
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 || s.type === "HEAD" ) {
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ statusText = response.state;
+ success = response.data;
+ error = response.error;
+ isSuccess = !error;
+ }
+ } else {
+
+ // Extract error from statusText and normalize for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ }
+} );
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+
+ // Shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ // The url can be an options object (which then must have .url)
+ return jQuery.ajax( jQuery.extend( {
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ }, jQuery.isPlainObject( url ) && url ) );
+ };
+} );
+
+
+jQuery._evalUrl = function( url ) {
+ return jQuery.ajax( {
+ url: url,
+
+ // Make this explicit, since user can override this through ajaxSetup (#11264)
+ type: "GET",
+ dataType: "script",
+ cache: true,
+ async: false,
+ global: false,
+ "throws": true
+ } );
+};
+
+
+jQuery.fn.extend( {
+ wrapAll: function( html ) {
+ var wrap;
+
+ if ( this[ 0 ] ) {
+ if ( jQuery.isFunction( html ) ) {
+ html = html.call( this[ 0 ] );
+ }
+
+ // The elements to wrap the target around
+ wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
+
+ if ( this[ 0 ].parentNode ) {
+ wrap.insertBefore( this[ 0 ] );
+ }
+
+ wrap.map( function() {
+ var elem = this;
+
+ while ( elem.firstElementChild ) {
+ elem = elem.firstElementChild;
+ }
+
+ return elem;
+ } ).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).wrapInner( html.call( this, i ) );
+ } );
+ }
+
+ return this.each( function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ } );
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each( function( i ) {
+ jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
+ } );
+ },
+
+ unwrap: function( selector ) {
+ this.parent( selector ).not( "body" ).each( function() {
+ jQuery( this ).replaceWith( this.childNodes );
+ } );
+ return this;
+ }
+} );
+
+
+jQuery.expr.pseudos.hidden = function( elem ) {
+ return !jQuery.expr.pseudos.visible( elem );
+};
+jQuery.expr.pseudos.visible = function( elem ) {
+ return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
+};
+
+
+
+
+jQuery.ajaxSettings.xhr = function() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch ( e ) {}
+};
+
+var xhrSuccessStatus = {
+
+ // File protocol always yields status code 0, assume 200
+ 0: 200,
+
+ // Support: IE <=9 only
+ // #1450: sometimes IE returns 1223 when it should be 204
+ 1223: 204
+ },
+ xhrSupported = jQuery.ajaxSettings.xhr();
+
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+support.ajax = xhrSupported = !!xhrSupported;
+
+jQuery.ajaxTransport( function( options ) {
+ var callback, errorCallback;
+
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( support.cors || xhrSupported && !options.crossDomain ) {
+ return {
+ send: function( headers, complete ) {
+ var i,
+ xhr = options.xhr();
+
+ xhr.open(
+ options.type,
+ options.url,
+ options.async,
+ options.username,
+ options.password
+ );
+
+ // Apply custom fields if provided
+ if ( options.xhrFields ) {
+ for ( i in options.xhrFields ) {
+ xhr[ i ] = options.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( options.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( options.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
+
+ // Set headers
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+
+ // Callback
+ callback = function( type ) {
+ return function() {
+ if ( callback ) {
+ callback = errorCallback = xhr.onload =
+ xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
+
+ if ( type === "abort" ) {
+ xhr.abort();
+ } else if ( type === "error" ) {
+
+ // Support: IE <=9 only
+ // On a manual native abort, IE9 throws
+ // errors on any property access that is not readyState
+ if ( typeof xhr.status !== "number" ) {
+ complete( 0, "error" );
+ } else {
+ complete(
+
+ // File: protocol always yields status 0; see #8605, #14207
+ xhr.status,
+ xhr.statusText
+ );
+ }
+ } else {
+ complete(
+ xhrSuccessStatus[ xhr.status ] || xhr.status,
+ xhr.statusText,
+
+ // Support: IE <=9 only
+ // IE9 has no XHR2 but throws on binary (trac-11426)
+ // For XHR2 non-text, let the caller handle it (gh-2498)
+ ( xhr.responseType || "text" ) !== "text" ||
+ typeof xhr.responseText !== "string" ?
+ { binary: xhr.response } :
+ { text: xhr.responseText },
+ xhr.getAllResponseHeaders()
+ );
+ }
+ }
+ };
+ };
+
+ // Listen to events
+ xhr.onload = callback();
+ errorCallback = xhr.onerror = callback( "error" );
+
+ // Support: IE 9 only
+ // Use onreadystatechange to replace onabort
+ // to handle uncaught aborts
+ if ( xhr.onabort !== undefined ) {
+ xhr.onabort = errorCallback;
+ } else {
+ xhr.onreadystatechange = function() {
+
+ // Check readyState before timeout as it changes
+ if ( xhr.readyState === 4 ) {
+
+ // Allow onerror to be called first,
+ // but that will not handle a native abort
+ // Also, save errorCallback to a variable
+ // as xhr.onerror cannot be accessed
+ window.setTimeout( function() {
+ if ( callback ) {
+ errorCallback();
+ }
+ } );
+ }
+ };
+ }
+
+ // Create the abort callback
+ callback = callback( "abort" );
+
+ try {
+
+ // Do send the request (this may raise an exception)
+ xhr.send( options.hasContent && options.data || null );
+ } catch ( e ) {
+
+ // #14683: Only rethrow if this hasn't been notified as an error yet
+ if ( callback ) {
+ throw e;
+ }
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+} );
+
+
+
+
+// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
+jQuery.ajaxPrefilter( function( s ) {
+ if ( s.crossDomain ) {
+ s.contents.script = false;
+ }
+} );
+
+// Install script dataType
+jQuery.ajaxSetup( {
+ accepts: {
+ script: "text/javascript, application/javascript, " +
+ "application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /\b(?:java|ecma)script\b/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+} );
+
+// Handle cache's special case and crossDomain
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ }
+} );
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function( s ) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+ var script, callback;
+ return {
+ send: function( _, complete ) {
+ script = jQuery( "<script>" ).prop( {
+ charset: s.scriptCharset,
+ src: s.url
+ } ).on(
+ "load error",
+ callback = function( evt ) {
+ script.remove();
+ callback = null;
+ if ( evt ) {
+ complete( evt.type === "error" ? 404 : 200, evt.type );
+ }
+ }
+ );
+
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ document.head.appendChild( script[ 0 ] );
+ },
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+} );
+
+
+
+
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup( {
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+} );
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" &&
+ ( s.contentType || "" )
+ .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
+ rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters[ "script json" ] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // Force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always( function() {
+
+ // If previous value didn't exist - remove it
+ if ( overwritten === undefined ) {
+ jQuery( window ).removeProp( callbackName );
+
+ // Otherwise restore preexisting value
+ } else {
+ window[ callbackName ] = overwritten;
+ }
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+
+ // Make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // Save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ } );
+
+ // Delegate to script
+ return "script";
+ }
+} );
+
+
+
+
+// Support: Safari 8 only
+// In Safari 8 documents created via document.implementation.createHTMLDocument
+// collapse sibling forms: the second one becomes a child of the first one.
+// Because of that, this security measure has to be disabled in Safari 8.
+// https://bugs.webkit.org/show_bug.cgi?id=137337
+support.createHTMLDocument = ( function() {
+ var body = document.implementation.createHTMLDocument( "" ).body;
+ body.innerHTML = "<form></form><form></form>";
+ return body.childNodes.length === 2;
+} )();
+
+
+// Argument "data" should be string of html
+// context (optional): If specified, the fragment will be created in this context,
+// defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+ if ( typeof data !== "string" ) {
+ return [];
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+
+ var base, parsed, scripts;
+
+ if ( !context ) {
+
+ // Stop scripts or inline event handlers from being executed immediately
+ // by using document.implementation
+ if ( support.createHTMLDocument ) {
+ context = document.implementation.createHTMLDocument( "" );
+
+ // Set the base href for the created document
+ // so any parsed elements with URLs
+ // are based on the document's URL (gh-2965)
+ base = context.createElement( "base" );
+ base.href = document.location.href;
+ context.head.appendChild( base );
+ } else {
+ context = document;
+ }
+ }
+
+ parsed = rsingleTag.exec( data );
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[ 1 ] ) ];
+ }
+
+ parsed = buildFragment( [ data ], context, scripts );
+
+ if ( scripts && scripts.length ) {
+ jQuery( scripts ).remove();
+ }
+
+ return jQuery.merge( [], parsed.childNodes );
+};
+
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+ var selector, type, response,
+ self = this,
+ off = url.indexOf( " " );
+
+ if ( off > -1 ) {
+ selector = stripAndCollapse( url.slice( off ) );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax( {
+ url: url,
+
+ // If "type" variable is undefined, then "GET" method will be used.
+ // Make value of this field explicit since
+ // user can override it through ajaxSetup method
+ type: type || "GET",
+ dataType: "html",
+ data: params
+ } ).done( function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ // If the request succeeds, this function gets "data", "status", "jqXHR"
+ // but they are ignored because response was set above.
+ // If it fails, this function gets "jqXHR", "status", "error"
+ } ).always( callback && function( jqXHR, status ) {
+ self.each( function() {
+ callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
+ } );
+ } );
+ }
+
+ return this;
+};
+
+
+
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [
+ "ajaxStart",
+ "ajaxStop",
+ "ajaxComplete",
+ "ajaxError",
+ "ajaxSuccess",
+ "ajaxSend"
+], function( i, type ) {
+ jQuery.fn[ type ] = function( fn ) {
+ return this.on( type, fn );
+ };
+} );
+
+
+
+
+jQuery.expr.pseudos.animated = function( elem ) {
+ return jQuery.grep( jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ } ).length;
+};
+
+
+
+
+jQuery.offset = {
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // Set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+ ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
+
+ // Need to be able to calculate position if either
+ // top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+
+ // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
+ options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+jQuery.fn.extend( {
+ offset: function( options ) {
+
+ // Preserve chaining for setter
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each( function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ } );
+ }
+
+ var doc, docElem, rect, win,
+ elem = this[ 0 ];
+
+ if ( !elem ) {
+ return;
+ }
+
+ // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a
+ // disconnected node in IE throws an error
+ if ( !elem.getClientRects().length ) {
+ return { top: 0, left: 0 };
+ }
+
+ rect = elem.getBoundingClientRect();
+
+ doc = elem.ownerDocument;
+ docElem = doc.documentElement;
+ win = doc.defaultView;
+
+ return {
+ top: rect.top + win.pageYOffset - docElem.clientTop,
+ left: rect.left + win.pageXOffset - docElem.clientLeft
+ };
+ },
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ elem = this[ 0 ],
+ parentOffset = { top: 0, left: 0 };
+
+ // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
+ // because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+
+ // Assume getBoundingClientRect is there when computed position is fixed
+ offset = elem.getBoundingClientRect();
+
+ } else {
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset = {
+ top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
+ left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
+ };
+ }
+
+ // Subtract parent offsets and element margins
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
+ };
+ },
+
+ // This method will return documentElement in the following cases:
+ // 1) For the element inside the iframe without offsetParent, this method will return
+ // documentElement of the parent window
+ // 2) For the hidden or detached element
+ // 3) For body or html element, i.e. in case of the html node - it will return itself
+ //
+ // but those exceptions were never presented as a real life use-cases
+ // and might be considered as more preferable results.
+ //
+ // This logic, however, is not guaranteed and can change at any point in the future
+ offsetParent: function() {
+ return this.map( function() {
+ var offsetParent = this.offsetParent;
+
+ while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || documentElement;
+ } );
+ }
+} );
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = "pageYOffset" === prop;
+
+ jQuery.fn[ method ] = function( val ) {
+ return access( this, function( elem, method, val ) {
+
+ // Coalesce documents and windows
+ var win;
+ if ( jQuery.isWindow( elem ) ) {
+ win = elem;
+ } else if ( elem.nodeType === 9 ) {
+ win = elem.defaultView;
+ }
+
+ if ( val === undefined ) {
+ return win ? win[ prop ] : elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : win.pageXOffset,
+ top ? val : win.pageYOffset
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length );
+ };
+} );
+
+// Support: Safari <=7 - 9.1, Chrome <=37 - 49
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
+// getComputedStyle returns percent when specified for top/left/bottom/right;
+// rather than make the css module depend on the offset module, just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+
+ // If curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ );
+} );
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
+ function( defaultExtra, funcName ) {
+
+ // Margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+
+ // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
+ return funcName.indexOf( "outer" ) === 0 ?
+ elem[ "inner" + name ] :
+ elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+ // whichever is greatest
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable );
+ };
+ } );
+} );
+
+
+jQuery.fn.extend( {
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ?
+ this.off( selector, "**" ) :
+ this.off( types, selector || "**", fn );
+ }
+} );
+
+jQuery.holdReady = function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+};
+jQuery.isArray = Array.isArray;
+jQuery.parseJSON = JSON.parse;
+jQuery.nodeName = nodeName;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( true ) {
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function() {
+ return jQuery;
+ }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+}
+
+
+
+
+var
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in AMD
+// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( !noGlobal ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+} );
+
+
+/***/ }),
+/* 2 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
+/* WEBPACK VAR INJECTION */(function(global) {/**!
+ * @fileOverview Kickass library to create and place poppers near their reference elements.
+ * @version 1.13.0
+ * @license
+ * Copyright (c) 2016 Federico Zivolo and contributors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+var isBrowser = typeof window !== 'undefined' && typeof document !== 'undefined';
+var longerTimeoutBrowsers = ['Edge', 'Trident', 'Firefox'];
+var timeoutDuration = 0;
+for (var i = 0; i < longerTimeoutBrowsers.length; i += 1) {
+ if (isBrowser && navigator.userAgent.indexOf(longerTimeoutBrowsers[i]) >= 0) {
+ timeoutDuration = 1;
+ break;
+ }
+}
+
+function microtaskDebounce(fn) {
+ var called = false;
+ return function () {
+ if (called) {
+ return;
+ }
+ called = true;
+ window.Promise.resolve().then(function () {
+ called = false;
+ fn();
+ });
+ };
+}
+
+function taskDebounce(fn) {
+ var scheduled = false;
+ return function () {
+ if (!scheduled) {
+ scheduled = true;
+ setTimeout(function () {
+ scheduled = false;
+ fn();
+ }, timeoutDuration);
+ }
+ };
+}
+
+var supportsMicroTasks = isBrowser && window.Promise;
+
+/**
+* Create a debounced version of a method, that's asynchronously deferred
+* but called in the minimum time possible.
+*
+* @method
+* @memberof Popper.Utils
+* @argument {Function} fn
+* @returns {Function}
+*/
+var debounce = supportsMicroTasks ? microtaskDebounce : taskDebounce;
+
+/**
+ * Check if the given variable is a function
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Any} functionToCheck - variable to check
+ * @returns {Boolean} answer to: is a function?
+ */
+function isFunction(functionToCheck) {
+ var getType = {};
+ return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
+}
+
+/**
+ * Get CSS computed property of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Eement} element
+ * @argument {String} property
+ */
+function getStyleComputedProperty(element, property) {
+ if (element.nodeType !== 1) {
+ return [];
+ }
+ // NOTE: 1 DOM access here
+ var css = getComputedStyle(element, null);
+ return property ? css[property] : css;
+}
+
+/**
+ * Returns the parentNode or the host of the element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} parent
+ */
+function getParentNode(element) {
+ if (element.nodeName === 'HTML') {
+ return element;
+ }
+ return element.parentNode || element.host;
+}
+
+/**
+ * Returns the scrolling parent of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} scroll parent
+ */
+function getScrollParent(element) {
+ // Return body, `getScroll` will take care to get the correct `scrollTop` from it
+ if (!element) {
+ return document.body;
+ }
+
+ switch (element.nodeName) {
+ case 'HTML':
+ case 'BODY':
+ return element.ownerDocument.body;
+ case '#document':
+ return element.body;
+ }
+
+ // Firefox want us to check `-x` and `-y` variations as well
+
+ var _getStyleComputedProp = getStyleComputedProperty(element),
+ overflow = _getStyleComputedProp.overflow,
+ overflowX = _getStyleComputedProp.overflowX,
+ overflowY = _getStyleComputedProp.overflowY;
+
+ if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {
+ return element;
+ }
+
+ return getScrollParent(getParentNode(element));
+}
+
+/**
+ * Returns the offset parent of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Element} offset parent
+ */
+function getOffsetParent(element) {
+ // NOTE: 1 DOM access here
+ var offsetParent = element && element.offsetParent;
+ var nodeName = offsetParent && offsetParent.nodeName;
+
+ if (!nodeName || nodeName === 'BODY' || nodeName === 'HTML') {
+ if (element) {
+ return element.ownerDocument.documentElement;
+ }
+
+ return document.documentElement;
+ }
+
+ // .offsetParent will return the closest TD or TABLE in case
+ // no offsetParent is present, I hate this job...
+ if (['TD', 'TABLE'].indexOf(offsetParent.nodeName) !== -1 && getStyleComputedProperty(offsetParent, 'position') === 'static') {
+ return getOffsetParent(offsetParent);
+ }
+
+ return offsetParent;
+}
+
+function isOffsetContainer(element) {
+ var nodeName = element.nodeName;
+
+ if (nodeName === 'BODY') {
+ return false;
+ }
+ return nodeName === 'HTML' || getOffsetParent(element.firstElementChild) === element;
+}
+
+/**
+ * Finds the root node (document, shadowDOM root) of the given element
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} node
+ * @returns {Element} root node
+ */
+function getRoot(node) {
+ if (node.parentNode !== null) {
+ return getRoot(node.parentNode);
+ }
+
+ return node;
+}
+
+/**
+ * Finds the offset parent common to the two provided nodes
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element1
+ * @argument {Element} element2
+ * @returns {Element} common offset parent
+ */
+function findCommonOffsetParent(element1, element2) {
+ // This check is needed to avoid errors in case one of the elements isn't defined for any reason
+ if (!element1 || !element1.nodeType || !element2 || !element2.nodeType) {
+ return document.documentElement;
+ }
+
+ // Here we make sure to give as "start" the element that comes first in the DOM
+ var order = element1.compareDocumentPosition(element2) & Node.DOCUMENT_POSITION_FOLLOWING;
+ var start = order ? element1 : element2;
+ var end = order ? element2 : element1;
+
+ // Get common ancestor container
+ var range = document.createRange();
+ range.setStart(start, 0);
+ range.setEnd(end, 0);
+ var commonAncestorContainer = range.commonAncestorContainer;
+
+ // Both nodes are inside #document
+
+ if (element1 !== commonAncestorContainer && element2 !== commonAncestorContainer || start.contains(end)) {
+ if (isOffsetContainer(commonAncestorContainer)) {
+ return commonAncestorContainer;
+ }
+
+ return getOffsetParent(commonAncestorContainer);
+ }
+
+ // one of the nodes is inside shadowDOM, find which one
+ var element1root = getRoot(element1);
+ if (element1root.host) {
+ return findCommonOffsetParent(element1root.host, element2);
+ } else {
+ return findCommonOffsetParent(element1, getRoot(element2).host);
+ }
+}
+
+/**
+ * Gets the scroll value of the given element in the given side (top and left)
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @argument {String} side `top` or `left`
+ * @returns {number} amount of scrolled pixels
+ */
+function getScroll(element) {
+ var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'top';
+
+ var upperSide = side === 'top' ? 'scrollTop' : 'scrollLeft';
+ var nodeName = element.nodeName;
+
+ if (nodeName === 'BODY' || nodeName === 'HTML') {
+ var html = element.ownerDocument.documentElement;
+ var scrollingElement = element.ownerDocument.scrollingElement || html;
+ return scrollingElement[upperSide];
+ }
+
+ return element[upperSide];
+}
+
+/*
+ * Sum or subtract the element scroll values (left and top) from a given rect object
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} rect - Rect object you want to change
+ * @param {HTMLElement} element - The element from the function reads the scroll values
+ * @param {Boolean} subtract - set to true if you want to subtract the scroll values
+ * @return {Object} rect - The modifier rect object
+ */
+function includeScroll(rect, element) {
+ var subtract = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+
+ var scrollTop = getScroll(element, 'top');
+ var scrollLeft = getScroll(element, 'left');
+ var modifier = subtract ? -1 : 1;
+ rect.top += scrollTop * modifier;
+ rect.bottom += scrollTop * modifier;
+ rect.left += scrollLeft * modifier;
+ rect.right += scrollLeft * modifier;
+ return rect;
+}
+
+/*
+ * Helper to detect borders of a given element
+ * @method
+ * @memberof Popper.Utils
+ * @param {CSSStyleDeclaration} styles
+ * Result of `getStyleComputedProperty` on the given element
+ * @param {String} axis - `x` or `y`
+ * @return {number} borders - The borders size of the given axis
+ */
+
+function getBordersSize(styles, axis) {
+ var sideA = axis === 'x' ? 'Left' : 'Top';
+ var sideB = sideA === 'Left' ? 'Right' : 'Bottom';
+
+ return parseFloat(styles['border' + sideA + 'Width'], 10) + parseFloat(styles['border' + sideB + 'Width'], 10);
+}
+
+/**
+ * Tells if you are running Internet Explorer 10
+ * @method
+ * @memberof Popper.Utils
+ * @returns {Boolean} isIE10
+ */
+var isIE10 = undefined;
+
+var isIE10$1 = function () {
+ if (isIE10 === undefined) {
+ isIE10 = navigator.appVersion.indexOf('MSIE 10') !== -1;
+ }
+ return isIE10;
+};
+
+function getSize(axis, body, html, computedStyle) {
+ return Math.max(body['offset' + axis], body['scroll' + axis], html['client' + axis], html['offset' + axis], html['scroll' + axis], isIE10$1() ? html['offset' + axis] + computedStyle['margin' + (axis === 'Height' ? 'Top' : 'Left')] + computedStyle['margin' + (axis === 'Height' ? 'Bottom' : 'Right')] : 0);
+}
+
+function getWindowSizes() {
+ var body = document.body;
+ var html = document.documentElement;
+ var computedStyle = isIE10$1() && getComputedStyle(html);
+
+ return {
+ height: getSize('Height', body, html, computedStyle),
+ width: getSize('Width', body, html, computedStyle)
+ };
+}
+
+var classCallCheck = function (instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+};
+
+var createClass = function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+}();
+
+
+
+
+
+var defineProperty = function (obj, key, value) {
+ if (key in obj) {
+ Object.defineProperty(obj, key, {
+ value: value,
+ enumerable: true,
+ configurable: true,
+ writable: true
+ });
+ } else {
+ obj[key] = value;
+ }
+
+ return obj;
+};
+
+var _extends = Object.assign || function (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+
+ for (var key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+
+ return target;
+};
+
+/**
+ * Given element offsets, generate an output similar to getBoundingClientRect
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Object} offsets
+ * @returns {Object} ClientRect like output
+ */
+function getClientRect(offsets) {
+ return _extends({}, offsets, {
+ right: offsets.left + offsets.width,
+ bottom: offsets.top + offsets.height
+ });
+}
+
+/**
+ * Get bounding client rect of given element
+ * @method
+ * @memberof Popper.Utils
+ * @param {HTMLElement} element
+ * @return {Object} client rect
+ */
+function getBoundingClientRect(element) {
+ var rect = {};
+
+ // IE10 10 FIX: Please, don't ask, the element isn't
+ // considered in DOM in some circumstances...
+ // This isn't reproducible in IE10 compatibility mode of IE11
+ if (isIE10$1()) {
+ try {
+ rect = element.getBoundingClientRect();
+ var scrollTop = getScroll(element, 'top');
+ var scrollLeft = getScroll(element, 'left');
+ rect.top += scrollTop;
+ rect.left += scrollLeft;
+ rect.bottom += scrollTop;
+ rect.right += scrollLeft;
+ } catch (err) {}
+ } else {
+ rect = element.getBoundingClientRect();
+ }
+
+ var result = {
+ left: rect.left,
+ top: rect.top,
+ width: rect.right - rect.left,
+ height: rect.bottom - rect.top
+ };
+
+ // subtract scrollbar size from sizes
+ var sizes = element.nodeName === 'HTML' ? getWindowSizes() : {};
+ var width = sizes.width || element.clientWidth || result.right - result.left;
+ var height = sizes.height || element.clientHeight || result.bottom - result.top;
+
+ var horizScrollbar = element.offsetWidth - width;
+ var vertScrollbar = element.offsetHeight - height;
+
+ // if an hypothetical scrollbar is detected, we must be sure it's not a `border`
+ // we make this check conditional for performance reasons
+ if (horizScrollbar || vertScrollbar) {
+ var styles = getStyleComputedProperty(element);
+ horizScrollbar -= getBordersSize(styles, 'x');
+ vertScrollbar -= getBordersSize(styles, 'y');
+
+ result.width -= horizScrollbar;
+ result.height -= vertScrollbar;
+ }
+
+ return getClientRect(result);
+}
+
+function getOffsetRectRelativeToArbitraryNode(children, parent) {
+ var isIE10 = isIE10$1();
+ var isHTML = parent.nodeName === 'HTML';
+ var childrenRect = getBoundingClientRect(children);
+ var parentRect = getBoundingClientRect(parent);
+ var scrollParent = getScrollParent(children);
+
+ var styles = getStyleComputedProperty(parent);
+ var borderTopWidth = parseFloat(styles.borderTopWidth, 10);
+ var borderLeftWidth = parseFloat(styles.borderLeftWidth, 10);
+
+ var offsets = getClientRect({
+ top: childrenRect.top - parentRect.top - borderTopWidth,
+ left: childrenRect.left - parentRect.left - borderLeftWidth,
+ width: childrenRect.width,
+ height: childrenRect.height
+ });
+ offsets.marginTop = 0;
+ offsets.marginLeft = 0;
+
+ // Subtract margins of documentElement in case it's being used as parent
+ // we do this only on HTML because it's the only element that behaves
+ // differently when margins are applied to it. The margins are included in
+ // the box of the documentElement, in the other cases not.
+ if (!isIE10 && isHTML) {
+ var marginTop = parseFloat(styles.marginTop, 10);
+ var marginLeft = parseFloat(styles.marginLeft, 10);
+
+ offsets.top -= borderTopWidth - marginTop;
+ offsets.bottom -= borderTopWidth - marginTop;
+ offsets.left -= borderLeftWidth - marginLeft;
+ offsets.right -= borderLeftWidth - marginLeft;
+
+ // Attach marginTop and marginLeft because in some circumstances we may need them
+ offsets.marginTop = marginTop;
+ offsets.marginLeft = marginLeft;
+ }
+
+ if (isIE10 ? parent.contains(scrollParent) : parent === scrollParent && scrollParent.nodeName !== 'BODY') {
+ offsets = includeScroll(offsets, parent);
+ }
+
+ return offsets;
+}
+
+function getViewportOffsetRectRelativeToArtbitraryNode(element) {
+ var html = element.ownerDocument.documentElement;
+ var relativeOffset = getOffsetRectRelativeToArbitraryNode(element, html);
+ var width = Math.max(html.clientWidth, window.innerWidth || 0);
+ var height = Math.max(html.clientHeight, window.innerHeight || 0);
+
+ var scrollTop = getScroll(html);
+ var scrollLeft = getScroll(html, 'left');
+
+ var offset = {
+ top: scrollTop - relativeOffset.top + relativeOffset.marginTop,
+ left: scrollLeft - relativeOffset.left + relativeOffset.marginLeft,
+ width: width,
+ height: height
+ };
+
+ return getClientRect(offset);
+}
+
+/**
+ * Check if the given element is fixed or is inside a fixed parent
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @argument {Element} customContainer
+ * @returns {Boolean} answer to "isFixed?"
+ */
+function isFixed(element) {
+ var nodeName = element.nodeName;
+ if (nodeName === 'BODY' || nodeName === 'HTML') {
+ return false;
+ }
+ if (getStyleComputedProperty(element, 'position') === 'fixed') {
+ return true;
+ }
+ return isFixed(getParentNode(element));
+}
+
+/**
+ * Computed the boundaries limits and return them
+ * @method
+ * @memberof Popper.Utils
+ * @param {HTMLElement} popper
+ * @param {HTMLElement} reference
+ * @param {number} padding
+ * @param {HTMLElement} boundariesElement - Element used to define the boundaries
+ * @returns {Object} Coordinates of the boundaries
+ */
+function getBoundaries(popper, reference, padding, boundariesElement) {
+ // NOTE: 1 DOM access here
+ var boundaries = { top: 0, left: 0 };
+ var offsetParent = findCommonOffsetParent(popper, reference);
+
+ // Handle viewport case
+ if (boundariesElement === 'viewport') {
+ boundaries = getViewportOffsetRectRelativeToArtbitraryNode(offsetParent);
+ } else {
+ // Handle other cases based on DOM element used as boundaries
+ var boundariesNode = void 0;
+ if (boundariesElement === 'scrollParent') {
+ boundariesNode = getScrollParent(getParentNode(reference));
+ if (boundariesNode.nodeName === 'BODY') {
+ boundariesNode = popper.ownerDocument.documentElement;
+ }
+ } else if (boundariesElement === 'window') {
+ boundariesNode = popper.ownerDocument.documentElement;
+ } else {
+ boundariesNode = boundariesElement;
+ }
+
+ var offsets = getOffsetRectRelativeToArbitraryNode(boundariesNode, offsetParent);
+
+ // In case of HTML, we need a different computation
+ if (boundariesNode.nodeName === 'HTML' && !isFixed(offsetParent)) {
+ var _getWindowSizes = getWindowSizes(),
+ height = _getWindowSizes.height,
+ width = _getWindowSizes.width;
+
+ boundaries.top += offsets.top - offsets.marginTop;
+ boundaries.bottom = height + offsets.top;
+ boundaries.left += offsets.left - offsets.marginLeft;
+ boundaries.right = width + offsets.left;
+ } else {
+ // for all the other DOM elements, this one is good
+ boundaries = offsets;
+ }
+ }
+
+ // Add paddings
+ boundaries.left += padding;
+ boundaries.top += padding;
+ boundaries.right -= padding;
+ boundaries.bottom -= padding;
+
+ return boundaries;
+}
+
+function getArea(_ref) {
+ var width = _ref.width,
+ height = _ref.height;
+
+ return width * height;
+}
+
+/**
+ * Utility used to transform the `auto` placement to the placement with more
+ * available space.
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function computeAutoPlacement(placement, refRect, popper, reference, boundariesElement) {
+ var padding = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 0;
+
+ if (placement.indexOf('auto') === -1) {
+ return placement;
+ }
+
+ var boundaries = getBoundaries(popper, reference, padding, boundariesElement);
+
+ var rects = {
+ top: {
+ width: boundaries.width,
+ height: refRect.top - boundaries.top
+ },
+ right: {
+ width: boundaries.right - refRect.right,
+ height: boundaries.height
+ },
+ bottom: {
+ width: boundaries.width,
+ height: boundaries.bottom - refRect.bottom
+ },
+ left: {
+ width: refRect.left - boundaries.left,
+ height: boundaries.height
+ }
+ };
+
+ var sortedAreas = Object.keys(rects).map(function (key) {
+ return _extends({
+ key: key
+ }, rects[key], {
+ area: getArea(rects[key])
+ });
+ }).sort(function (a, b) {
+ return b.area - a.area;
+ });
+
+ var filteredAreas = sortedAreas.filter(function (_ref2) {
+ var width = _ref2.width,
+ height = _ref2.height;
+ return width >= popper.clientWidth && height >= popper.clientHeight;
+ });
+
+ var computedPlacement = filteredAreas.length > 0 ? filteredAreas[0].key : sortedAreas[0].key;
+
+ var variation = placement.split('-')[1];
+
+ return computedPlacement + (variation ? '-' + variation : '');
+}
+
+/**
+ * Get offsets to the reference element
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} state
+ * @param {Element} popper - the popper element
+ * @param {Element} reference - the reference element (the popper will be relative to this)
+ * @returns {Object} An object containing the offsets which will be applied to the popper
+ */
+function getReferenceOffsets(state, popper, reference) {
+ var commonOffsetParent = findCommonOffsetParent(popper, reference);
+ return getOffsetRectRelativeToArbitraryNode(reference, commonOffsetParent);
+}
+
+/**
+ * Get the outer sizes of the given element (offset size + margins)
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element
+ * @returns {Object} object containing width and height properties
+ */
+function getOuterSizes(element) {
+ var styles = getComputedStyle(element);
+ var x = parseFloat(styles.marginTop) + parseFloat(styles.marginBottom);
+ var y = parseFloat(styles.marginLeft) + parseFloat(styles.marginRight);
+ var result = {
+ width: element.offsetWidth + y,
+ height: element.offsetHeight + x
+ };
+ return result;
+}
+
+/**
+ * Get the opposite placement of the given one
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} placement
+ * @returns {String} flipped placement
+ */
+function getOppositePlacement(placement) {
+ var hash = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' };
+ return placement.replace(/left|right|bottom|top/g, function (matched) {
+ return hash[matched];
+ });
+}
+
+/**
+ * Get offsets to the popper
+ * @method
+ * @memberof Popper.Utils
+ * @param {Object} position - CSS position the Popper will get applied
+ * @param {HTMLElement} popper - the popper element
+ * @param {Object} referenceOffsets - the reference offsets (the popper will be relative to this)
+ * @param {String} placement - one of the valid placement options
+ * @returns {Object} popperOffsets - An object containing the offsets which will be applied to the popper
+ */
+function getPopperOffsets(popper, referenceOffsets, placement) {
+ placement = placement.split('-')[0];
+
+ // Get popper node sizes
+ var popperRect = getOuterSizes(popper);
+
+ // Add position, width and height to our offsets object
+ var popperOffsets = {
+ width: popperRect.width,
+ height: popperRect.height
+ };
+
+ // depending by the popper placement we have to compute its offsets slightly differently
+ var isHoriz = ['right', 'left'].indexOf(placement) !== -1;
+ var mainSide = isHoriz ? 'top' : 'left';
+ var secondarySide = isHoriz ? 'left' : 'top';
+ var measurement = isHoriz ? 'height' : 'width';
+ var secondaryMeasurement = !isHoriz ? 'height' : 'width';
+
+ popperOffsets[mainSide] = referenceOffsets[mainSide] + referenceOffsets[measurement] / 2 - popperRect[measurement] / 2;
+ if (placement === secondarySide) {
+ popperOffsets[secondarySide] = referenceOffsets[secondarySide] - popperRect[secondaryMeasurement];
+ } else {
+ popperOffsets[secondarySide] = referenceOffsets[getOppositePlacement(secondarySide)];
+ }
+
+ return popperOffsets;
+}
+
+/**
+ * Mimics the `find` method of Array
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Array} arr
+ * @argument prop
+ * @argument value
+ * @returns index or -1
+ */
+function find(arr, check) {
+ // use native find if supported
+ if (Array.prototype.find) {
+ return arr.find(check);
+ }
+
+ // use `filter` to obtain the same behavior of `find`
+ return arr.filter(check)[0];
+}
+
+/**
+ * Return the index of the matching object
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Array} arr
+ * @argument prop
+ * @argument value
+ * @returns index or -1
+ */
+function findIndex(arr, prop, value) {
+ // use native findIndex if supported
+ if (Array.prototype.findIndex) {
+ return arr.findIndex(function (cur) {
+ return cur[prop] === value;
+ });
+ }
+
+ // use `find` + `indexOf` if `findIndex` isn't supported
+ var match = find(arr, function (obj) {
+ return obj[prop] === value;
+ });
+ return arr.indexOf(match);
+}
+
+/**
+ * Loop trough the list of modifiers and run them in order,
+ * each of them will then edit the data object.
+ * @method
+ * @memberof Popper.Utils
+ * @param {dataObject} data
+ * @param {Array} modifiers
+ * @param {String} ends - Optional modifier name used as stopper
+ * @returns {dataObject}
+ */
+function runModifiers(modifiers, data, ends) {
+ var modifiersToRun = ends === undefined ? modifiers : modifiers.slice(0, findIndex(modifiers, 'name', ends));
+
+ modifiersToRun.forEach(function (modifier) {
+ if (modifier['function']) {
+ // eslint-disable-line dot-notation
+ console.warn('`modifier.function` is deprecated, use `modifier.fn`!');
+ }
+ var fn = modifier['function'] || modifier.fn; // eslint-disable-line dot-notation
+ if (modifier.enabled && isFunction(fn)) {
+ // Add properties to offsets to make them a complete clientRect object
+ // we do this before each modifier to make sure the previous one doesn't
+ // mess with these values
+ data.offsets.popper = getClientRect(data.offsets.popper);
+ data.offsets.reference = getClientRect(data.offsets.reference);
+
+ data = fn(data, modifier);
+ }
+ });
+
+ return data;
+}
+
+/**
+ * Updates the position of the popper, computing the new offsets and applying
+ * the new style.<br />
+ * Prefer `scheduleUpdate` over `update` because of performance reasons.
+ * @method
+ * @memberof Popper
+ */
+function update() {
+ // if popper is destroyed, don't perform any further update
+ if (this.state.isDestroyed) {
+ return;
+ }
+
+ var data = {
+ instance: this,
+ styles: {},
+ arrowStyles: {},
+ attributes: {},
+ flipped: false,
+ offsets: {}
+ };
+
+ // compute reference element offsets
+ data.offsets.reference = getReferenceOffsets(this.state, this.popper, this.reference);
+
+ // compute auto placement, store placement inside the data object,
+ // modifiers will be able to edit `placement` if needed
+ // and refer to originalPlacement to know the original value
+ data.placement = computeAutoPlacement(this.options.placement, data.offsets.reference, this.popper, this.reference, this.options.modifiers.flip.boundariesElement, this.options.modifiers.flip.padding);
+
+ // store the computed placement inside `originalPlacement`
+ data.originalPlacement = data.placement;
+
+ // compute the popper offsets
+ data.offsets.popper = getPopperOffsets(this.popper, data.offsets.reference, data.placement);
+ data.offsets.popper.position = 'absolute';
+
+ // run the modifiers
+ data = runModifiers(this.modifiers, data);
+
+ // the first `update` will call `onCreate` callback
+ // the other ones will call `onUpdate` callback
+ if (!this.state.isCreated) {
+ this.state.isCreated = true;
+ this.options.onCreate(data);
+ } else {
+ this.options.onUpdate(data);
+ }
+}
+
+/**
+ * Helper used to know if the given modifier is enabled.
+ * @method
+ * @memberof Popper.Utils
+ * @returns {Boolean}
+ */
+function isModifierEnabled(modifiers, modifierName) {
+ return modifiers.some(function (_ref) {
+ var name = _ref.name,
+ enabled = _ref.enabled;
+ return enabled && name === modifierName;
+ });
+}
+
+/**
+ * Get the prefixed supported property name
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} property (camelCase)
+ * @returns {String} prefixed property (camelCase or PascalCase, depending on the vendor prefix)
+ */
+function getSupportedPropertyName(property) {
+ var prefixes = [false, 'ms', 'Webkit', 'Moz', 'O'];
+ var upperProp = property.charAt(0).toUpperCase() + property.slice(1);
+
+ for (var i = 0; i < prefixes.length - 1; i++) {
+ var prefix = prefixes[i];
+ var toCheck = prefix ? '' + prefix + upperProp : property;
+ if (typeof document.body.style[toCheck] !== 'undefined') {
+ return toCheck;
+ }
+ }
+ return null;
+}
+
+/**
+ * Destroy the popper
+ * @method
+ * @memberof Popper
+ */
+function destroy() {
+ this.state.isDestroyed = true;
+
+ // touch DOM only if `applyStyle` modifier is enabled
+ if (isModifierEnabled(this.modifiers, 'applyStyle')) {
+ this.popper.removeAttribute('x-placement');
+ this.popper.style.left = '';
+ this.popper.style.position = '';
+ this.popper.style.top = '';
+ this.popper.style[getSupportedPropertyName('transform')] = '';
+ }
+
+ this.disableEventListeners();
+
+ // remove the popper if user explicity asked for the deletion on destroy
+ // do not use `remove` because IE11 doesn't support it
+ if (this.options.removeOnDestroy) {
+ this.popper.parentNode.removeChild(this.popper);
+ }
+ return this;
+}
+
+/**
+ * Get the window associated with the element
+ * @argument {Element} element
+ * @returns {Window}
+ */
+function getWindow(element) {
+ var ownerDocument = element.ownerDocument;
+ return ownerDocument ? ownerDocument.defaultView : window;
+}
+
+function attachToScrollParents(scrollParent, event, callback, scrollParents) {
+ var isBody = scrollParent.nodeName === 'BODY';
+ var target = isBody ? scrollParent.ownerDocument.defaultView : scrollParent;
+ target.addEventListener(event, callback, { passive: true });
+
+ if (!isBody) {
+ attachToScrollParents(getScrollParent(target.parentNode), event, callback, scrollParents);
+ }
+ scrollParents.push(target);
+}
+
+/**
+ * Setup needed event listeners used to update the popper position
+ * @method
+ * @memberof Popper.Utils
+ * @private
+ */
+function setupEventListeners(reference, options, state, updateBound) {
+ // Resize event listener on window
+ state.updateBound = updateBound;
+ getWindow(reference).addEventListener('resize', state.updateBound, { passive: true });
+
+ // Scroll event listener on scroll parents
+ var scrollElement = getScrollParent(reference);
+ attachToScrollParents(scrollElement, 'scroll', state.updateBound, state.scrollParents);
+ state.scrollElement = scrollElement;
+ state.eventsEnabled = true;
+
+ return state;
+}
+
+/**
+ * It will add resize/scroll events and start recalculating
+ * position of the popper element when they are triggered.
+ * @method
+ * @memberof Popper
+ */
+function enableEventListeners() {
+ if (!this.state.eventsEnabled) {
+ this.state = setupEventListeners(this.reference, this.options, this.state, this.scheduleUpdate);
+ }
+}
+
+/**
+ * Remove event listeners used to update the popper position
+ * @method
+ * @memberof Popper.Utils
+ * @private
+ */
+function removeEventListeners(reference, state) {
+ // Remove resize event listener on window
+ getWindow(reference).removeEventListener('resize', state.updateBound);
+
+ // Remove scroll event listener on scroll parents
+ state.scrollParents.forEach(function (target) {
+ target.removeEventListener('scroll', state.updateBound);
+ });
+
+ // Reset state
+ state.updateBound = null;
+ state.scrollParents = [];
+ state.scrollElement = null;
+ state.eventsEnabled = false;
+ return state;
+}
+
+/**
+ * It will remove resize/scroll events and won't recalculate popper position
+ * when they are triggered. It also won't trigger onUpdate callback anymore,
+ * unless you call `update` method manually.
+ * @method
+ * @memberof Popper
+ */
+function disableEventListeners() {
+ if (this.state.eventsEnabled) {
+ cancelAnimationFrame(this.scheduleUpdate);
+ this.state = removeEventListeners(this.reference, this.state);
+ }
+}
+
+/**
+ * Tells if a given input is a number
+ * @method
+ * @memberof Popper.Utils
+ * @param {*} input to check
+ * @return {Boolean}
+ */
+function isNumeric(n) {
+ return n !== '' && !isNaN(parseFloat(n)) && isFinite(n);
+}
+
+/**
+ * Set the style to the given popper
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element - Element to apply the style to
+ * @argument {Object} styles
+ * Object with a list of properties and values which will be applied to the element
+ */
+function setStyles(element, styles) {
+ Object.keys(styles).forEach(function (prop) {
+ var unit = '';
+ // add unit if the value is numeric and is one of the following
+ if (['width', 'height', 'top', 'right', 'bottom', 'left'].indexOf(prop) !== -1 && isNumeric(styles[prop])) {
+ unit = 'px';
+ }
+ element.style[prop] = styles[prop] + unit;
+ });
+}
+
+/**
+ * Set the attributes to the given popper
+ * @method
+ * @memberof Popper.Utils
+ * @argument {Element} element - Element to apply the attributes to
+ * @argument {Object} styles
+ * Object with a list of properties and values which will be applied to the element
+ */
+function setAttributes(element, attributes) {
+ Object.keys(attributes).forEach(function (prop) {
+ var value = attributes[prop];
+ if (value !== false) {
+ element.setAttribute(prop, attributes[prop]);
+ } else {
+ element.removeAttribute(prop);
+ }
+ });
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} data.styles - List of style properties - values to apply to popper element
+ * @argument {Object} data.attributes - List of attribute properties - values to apply to popper element
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The same data object
+ */
+function applyStyle(data) {
+ // any property present in `data.styles` will be applied to the popper,
+ // in this way we can make the 3rd party modifiers add custom styles to it
+ // Be aware, modifiers could override the properties defined in the previous
+ // lines of this modifier!
+ setStyles(data.instance.popper, data.styles);
+
+ // any property present in `data.attributes` will be applied to the popper,
+ // they will be set as HTML attributes of the element
+ setAttributes(data.instance.popper, data.attributes);
+
+ // if arrowElement is defined and arrowStyles has some properties
+ if (data.arrowElement && Object.keys(data.arrowStyles).length) {
+ setStyles(data.arrowElement, data.arrowStyles);
+ }
+
+ return data;
+}
+
+/**
+ * Set the x-placement attribute before everything else because it could be used
+ * to add margins to the popper margins needs to be calculated to get the
+ * correct popper offsets.
+ * @method
+ * @memberof Popper.modifiers
+ * @param {HTMLElement} reference - The reference element used to position the popper
+ * @param {HTMLElement} popper - The HTML element used as popper.
+ * @param {Object} options - Popper.js options
+ */
+function applyStyleOnLoad(reference, popper, options, modifierOptions, state) {
+ // compute reference element offsets
+ var referenceOffsets = getReferenceOffsets(state, popper, reference);
+
+ // compute auto placement, store placement inside the data object,
+ // modifiers will be able to edit `placement` if needed
+ // and refer to originalPlacement to know the original value
+ var placement = computeAutoPlacement(options.placement, referenceOffsets, popper, reference, options.modifiers.flip.boundariesElement, options.modifiers.flip.padding);
+
+ popper.setAttribute('x-placement', placement);
+
+ // Apply `position` to popper before anything else because
+ // without the position applied we can't guarantee correct computations
+ setStyles(popper, { position: 'absolute' });
+
+ return options;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function computeStyle(data, options) {
+ var x = options.x,
+ y = options.y;
+ var popper = data.offsets.popper;
+
+ // Remove this legacy support in Popper.js v2
+
+ var legacyGpuAccelerationOption = find(data.instance.modifiers, function (modifier) {
+ return modifier.name === 'applyStyle';
+ }).gpuAcceleration;
+ if (legacyGpuAccelerationOption !== undefined) {
+ console.warn('WARNING: `gpuAcceleration` option moved to `computeStyle` modifier and will not be supported in future versions of Popper.js!');
+ }
+ var gpuAcceleration = legacyGpuAccelerationOption !== undefined ? legacyGpuAccelerationOption : options.gpuAcceleration;
+
+ var offsetParent = getOffsetParent(data.instance.popper);
+ var offsetParentRect = getBoundingClientRect(offsetParent);
+
+ // Styles
+ var styles = {
+ position: popper.position
+ };
+
+ // floor sides to avoid blurry text
+ var offsets = {
+ left: Math.floor(popper.left),
+ top: Math.floor(popper.top),
+ bottom: Math.floor(popper.bottom),
+ right: Math.floor(popper.right)
+ };
+
+ var sideA = x === 'bottom' ? 'top' : 'bottom';
+ var sideB = y === 'right' ? 'left' : 'right';
+
+ // if gpuAcceleration is set to `true` and transform is supported,
+ // we use `translate3d` to apply the position to the popper we
+ // automatically use the supported prefixed version if needed
+ var prefixedProperty = getSupportedPropertyName('transform');
+
+ // now, let's make a step back and look at this code closely (wtf?)
+ // If the content of the popper grows once it's been positioned, it
+ // may happen that the popper gets misplaced because of the new content
+ // overflowing its reference element
+ // To avoid this problem, we provide two options (x and y), which allow
+ // the consumer to define the offset origin.
+ // If we position a popper on top of a reference element, we can set
+ // `x` to `top` to make the popper grow towards its top instead of
+ // its bottom.
+ var left = void 0,
+ top = void 0;
+ if (sideA === 'bottom') {
+ top = -offsetParentRect.height + offsets.bottom;
+ } else {
+ top = offsets.top;
+ }
+ if (sideB === 'right') {
+ left = -offsetParentRect.width + offsets.right;
+ } else {
+ left = offsets.left;
+ }
+ if (gpuAcceleration && prefixedProperty) {
+ styles[prefixedProperty] = 'translate3d(' + left + 'px, ' + top + 'px, 0)';
+ styles[sideA] = 0;
+ styles[sideB] = 0;
+ styles.willChange = 'transform';
+ } else {
+ // othwerise, we use the standard `top`, `left`, `bottom` and `right` properties
+ var invertTop = sideA === 'bottom' ? -1 : 1;
+ var invertLeft = sideB === 'right' ? -1 : 1;
+ styles[sideA] = top * invertTop;
+ styles[sideB] = left * invertLeft;
+ styles.willChange = sideA + ', ' + sideB;
+ }
+
+ // Attributes
+ var attributes = {
+ 'x-placement': data.placement
+ };
+
+ // Update `data` attributes, styles and arrowStyles
+ data.attributes = _extends({}, attributes, data.attributes);
+ data.styles = _extends({}, styles, data.styles);
+ data.arrowStyles = _extends({}, data.offsets.arrow, data.arrowStyles);
+
+ return data;
+}
+
+/**
+ * Helper used to know if the given modifier depends from another one.<br />
+ * It checks if the needed modifier is listed and enabled.
+ * @method
+ * @memberof Popper.Utils
+ * @param {Array} modifiers - list of modifiers
+ * @param {String} requestingName - name of requesting modifier
+ * @param {String} requestedName - name of requested modifier
+ * @returns {Boolean}
+ */
+function isModifierRequired(modifiers, requestingName, requestedName) {
+ var requesting = find(modifiers, function (_ref) {
+ var name = _ref.name;
+ return name === requestingName;
+ });
+
+ var isRequired = !!requesting && modifiers.some(function (modifier) {
+ return modifier.name === requestedName && modifier.enabled && modifier.order < requesting.order;
+ });
+
+ if (!isRequired) {
+ var _requesting = '`' + requestingName + '`';
+ var requested = '`' + requestedName + '`';
+ console.warn(requested + ' modifier is required by ' + _requesting + ' modifier in order to work, be sure to include it before ' + _requesting + '!');
+ }
+ return isRequired;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function arrow(data, options) {
+ var _data$offsets$arrow;
+
+ // arrow depends on keepTogether in order to work
+ if (!isModifierRequired(data.instance.modifiers, 'arrow', 'keepTogether')) {
+ return data;
+ }
+
+ var arrowElement = options.element;
+
+ // if arrowElement is a string, suppose it's a CSS selector
+ if (typeof arrowElement === 'string') {
+ arrowElement = data.instance.popper.querySelector(arrowElement);
+
+ // if arrowElement is not found, don't run the modifier
+ if (!arrowElement) {
+ return data;
+ }
+ } else {
+ // if the arrowElement isn't a query selector we must check that the
+ // provided DOM node is child of its popper node
+ if (!data.instance.popper.contains(arrowElement)) {
+ console.warn('WARNING: `arrow.element` must be child of its popper element!');
+ return data;
+ }
+ }
+
+ var placement = data.placement.split('-')[0];
+ var _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
+
+ var isVertical = ['left', 'right'].indexOf(placement) !== -1;
+
+ var len = isVertical ? 'height' : 'width';
+ var sideCapitalized = isVertical ? 'Top' : 'Left';
+ var side = sideCapitalized.toLowerCase();
+ var altSide = isVertical ? 'left' : 'top';
+ var opSide = isVertical ? 'bottom' : 'right';
+ var arrowElementSize = getOuterSizes(arrowElement)[len];
+
+ //
+ // extends keepTogether behavior making sure the popper and its
+ // reference have enough pixels in conjuction
+ //
+
+ // top/left side
+ if (reference[opSide] - arrowElementSize < popper[side]) {
+ data.offsets.popper[side] -= popper[side] - (reference[opSide] - arrowElementSize);
+ }
+ // bottom/right side
+ if (reference[side] + arrowElementSize > popper[opSide]) {
+ data.offsets.popper[side] += reference[side] + arrowElementSize - popper[opSide];
+ }
+ data.offsets.popper = getClientRect(data.offsets.popper);
+
+ // compute center of the popper
+ var center = reference[side] + reference[len] / 2 - arrowElementSize / 2;
+
+ // Compute the sideValue using the updated popper offsets
+ // take popper margin in account because we don't have this info available
+ var css = getStyleComputedProperty(data.instance.popper);
+ var popperMarginSide = parseFloat(css['margin' + sideCapitalized], 10);
+ var popperBorderSide = parseFloat(css['border' + sideCapitalized + 'Width'], 10);
+ var sideValue = center - data.offsets.popper[side] - popperMarginSide - popperBorderSide;
+
+ // prevent arrowElement from being placed not contiguously to its popper
+ sideValue = Math.max(Math.min(popper[len] - arrowElementSize, sideValue), 0);
+
+ data.arrowElement = arrowElement;
+ data.offsets.arrow = (_data$offsets$arrow = {}, defineProperty(_data$offsets$arrow, side, Math.round(sideValue)), defineProperty(_data$offsets$arrow, altSide, ''), _data$offsets$arrow);
+
+ return data;
+}
+
+/**
+ * Get the opposite placement variation of the given one
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} placement variation
+ * @returns {String} flipped placement variation
+ */
+function getOppositeVariation(variation) {
+ if (variation === 'end') {
+ return 'start';
+ } else if (variation === 'start') {
+ return 'end';
+ }
+ return variation;
+}
+
+/**
+ * List of accepted placements to use as values of the `placement` option.<br />
+ * Valid placements are:
+ * - `auto`
+ * - `top`
+ * - `right`
+ * - `bottom`
+ * - `left`
+ *
+ * Each placement can have a variation from this list:
+ * - `-start`
+ * - `-end`
+ *
+ * Variations are interpreted easily if you think of them as the left to right
+ * written languages. Horizontally (`top` and `bottom`), `start` is left and `end`
+ * is right.<br />
+ * Vertically (`left` and `right`), `start` is top and `end` is bottom.
+ *
+ * Some valid examples are:
+ * - `top-end` (on top of reference, right aligned)
+ * - `right-start` (on right of reference, top aligned)
+ * - `bottom` (on bottom, centered)
+ * - `auto-right` (on the side with more space available, alignment depends by placement)
+ *
+ * @static
+ * @type {Array}
+ * @enum {String}
+ * @readonly
+ * @method placements
+ * @memberof Popper
+ */
+var placements = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-end', 'bottom', 'bottom-start', 'left-end', 'left', 'left-start'];
+
+// Get rid of `auto` `auto-start` and `auto-end`
+var validPlacements = placements.slice(3);
+
+/**
+ * Given an initial placement, returns all the subsequent placements
+ * clockwise (or counter-clockwise).
+ *
+ * @method
+ * @memberof Popper.Utils
+ * @argument {String} placement - A valid placement (it accepts variations)
+ * @argument {Boolean} counter - Set to true to walk the placements counterclockwise
+ * @returns {Array} placements including their variations
+ */
+function clockwise(placement) {
+ var counter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+
+ var index = validPlacements.indexOf(placement);
+ var arr = validPlacements.slice(index + 1).concat(validPlacements.slice(0, index));
+ return counter ? arr.reverse() : arr;
+}
+
+var BEHAVIORS = {
+ FLIP: 'flip',
+ CLOCKWISE: 'clockwise',
+ COUNTERCLOCKWISE: 'counterclockwise'
+};
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function flip(data, options) {
+ // if `inner` modifier is enabled, we can't use the `flip` modifier
+ if (isModifierEnabled(data.instance.modifiers, 'inner')) {
+ return data;
+ }
+
+ if (data.flipped && data.placement === data.originalPlacement) {
+ // seems like flip is trying to loop, probably there's not enough space on any of the flippable sides
+ return data;
+ }
+
+ var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, options.boundariesElement);
+
+ var placement = data.placement.split('-')[0];
+ var placementOpposite = getOppositePlacement(placement);
+ var variation = data.placement.split('-')[1] || '';
+
+ var flipOrder = [];
+
+ switch (options.behavior) {
+ case BEHAVIORS.FLIP:
+ flipOrder = [placement, placementOpposite];
+ break;
+ case BEHAVIORS.CLOCKWISE:
+ flipOrder = clockwise(placement);
+ break;
+ case BEHAVIORS.COUNTERCLOCKWISE:
+ flipOrder = clockwise(placement, true);
+ break;
+ default:
+ flipOrder = options.behavior;
+ }
+
+ flipOrder.forEach(function (step, index) {
+ if (placement !== step || flipOrder.length === index + 1) {
+ return data;
+ }
+
+ placement = data.placement.split('-')[0];
+ placementOpposite = getOppositePlacement(placement);
+
+ var popperOffsets = data.offsets.popper;
+ var refOffsets = data.offsets.reference;
+
+ // using floor because the reference offsets may contain decimals we are not going to consider here
+ var floor = Math.floor;
+ var overlapsRef = placement === 'left' && floor(popperOffsets.right) > floor(refOffsets.left) || placement === 'right' && floor(popperOffsets.left) < floor(refOffsets.right) || placement === 'top' && floor(popperOffsets.bottom) > floor(refOffsets.top) || placement === 'bottom' && floor(popperOffsets.top) < floor(refOffsets.bottom);
+
+ var overflowsLeft = floor(popperOffsets.left) < floor(boundaries.left);
+ var overflowsRight = floor(popperOffsets.right) > floor(boundaries.right);
+ var overflowsTop = floor(popperOffsets.top) < floor(boundaries.top);
+ var overflowsBottom = floor(popperOffsets.bottom) > floor(boundaries.bottom);
+
+ var overflowsBoundaries = placement === 'left' && overflowsLeft || placement === 'right' && overflowsRight || placement === 'top' && overflowsTop || placement === 'bottom' && overflowsBottom;
+
+ // flip the variation if required
+ var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
+ var flippedVariation = !!options.flipVariations && (isVertical && variation === 'start' && overflowsLeft || isVertical && variation === 'end' && overflowsRight || !isVertical && variation === 'start' && overflowsTop || !isVertical && variation === 'end' && overflowsBottom);
+
+ if (overlapsRef || overflowsBoundaries || flippedVariation) {
+ // this boolean to detect any flip loop
+ data.flipped = true;
+
+ if (overlapsRef || overflowsBoundaries) {
+ placement = flipOrder[index + 1];
+ }
+
+ if (flippedVariation) {
+ variation = getOppositeVariation(variation);
+ }
+
+ data.placement = placement + (variation ? '-' + variation : '');
+
+ // this object contains `position`, we want to preserve it along with
+ // any additional property we may add in the future
+ data.offsets.popper = _extends({}, data.offsets.popper, getPopperOffsets(data.instance.popper, data.offsets.reference, data.placement));
+
+ data = runModifiers(data.instance.modifiers, data, 'flip');
+ }
+ });
+ return data;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function keepTogether(data) {
+ var _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
+
+ var placement = data.placement.split('-')[0];
+ var floor = Math.floor;
+ var isVertical = ['top', 'bottom'].indexOf(placement) !== -1;
+ var side = isVertical ? 'right' : 'bottom';
+ var opSide = isVertical ? 'left' : 'top';
+ var measurement = isVertical ? 'width' : 'height';
+
+ if (popper[side] < floor(reference[opSide])) {
+ data.offsets.popper[opSide] = floor(reference[opSide]) - popper[measurement];
+ }
+ if (popper[opSide] > floor(reference[side])) {
+ data.offsets.popper[opSide] = floor(reference[side]);
+ }
+
+ return data;
+}
+
+/**
+ * Converts a string containing value + unit into a px value number
+ * @function
+ * @memberof {modifiers~offset}
+ * @private
+ * @argument {String} str - Value + unit string
+ * @argument {String} measurement - `height` or `width`
+ * @argument {Object} popperOffsets
+ * @argument {Object} referenceOffsets
+ * @returns {Number|String}
+ * Value in pixels, or original string if no values were extracted
+ */
+function toValue(str, measurement, popperOffsets, referenceOffsets) {
+ // separate value from unit
+ var split = str.match(/((?:\-|\+)?\d*\.?\d*)(.*)/);
+ var value = +split[1];
+ var unit = split[2];
+
+ // If it's not a number it's an operator, I guess
+ if (!value) {
+ return str;
+ }
+
+ if (unit.indexOf('%') === 0) {
+ var element = void 0;
+ switch (unit) {
+ case '%p':
+ element = popperOffsets;
+ break;
+ case '%':
+ case '%r':
+ default:
+ element = referenceOffsets;
+ }
+
+ var rect = getClientRect(element);
+ return rect[measurement] / 100 * value;
+ } else if (unit === 'vh' || unit === 'vw') {
+ // if is a vh or vw, we calculate the size based on the viewport
+ var size = void 0;
+ if (unit === 'vh') {
+ size = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
+ } else {
+ size = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
+ }
+ return size / 100 * value;
+ } else {
+ // if is an explicit pixel unit, we get rid of the unit and keep the value
+ // if is an implicit unit, it's px, and we return just the value
+ return value;
+ }
+}
+
+/**
+ * Parse an `offset` string to extrapolate `x` and `y` numeric offsets.
+ * @function
+ * @memberof {modifiers~offset}
+ * @private
+ * @argument {String} offset
+ * @argument {Object} popperOffsets
+ * @argument {Object} referenceOffsets
+ * @argument {String} basePlacement
+ * @returns {Array} a two cells array with x and y offsets in numbers
+ */
+function parseOffset(offset, popperOffsets, referenceOffsets, basePlacement) {
+ var offsets = [0, 0];
+
+ // Use height if placement is left or right and index is 0 otherwise use width
+ // in this way the first offset will use an axis and the second one
+ // will use the other one
+ var useHeight = ['right', 'left'].indexOf(basePlacement) !== -1;
+
+ // Split the offset string to obtain a list of values and operands
+ // The regex addresses values with the plus or minus sign in front (+10, -20, etc)
+ var fragments = offset.split(/(\+|\-)/).map(function (frag) {
+ return frag.trim();
+ });
+
+ // Detect if the offset string contains a pair of values or a single one
+ // they could be separated by comma or space
+ var divider = fragments.indexOf(find(fragments, function (frag) {
+ return frag.search(/,|\s/) !== -1;
+ }));
+
+ if (fragments[divider] && fragments[divider].indexOf(',') === -1) {
+ console.warn('Offsets separated by white space(s) are deprecated, use a comma (,) instead.');
+ }
+
+ // If divider is found, we divide the list of values and operands to divide
+ // them by ofset X and Y.
+ var splitRegex = /\s*,\s*|\s+/;
+ var ops = divider !== -1 ? [fragments.slice(0, divider).concat([fragments[divider].split(splitRegex)[0]]), [fragments[divider].split(splitRegex)[1]].concat(fragments.slice(divider + 1))] : [fragments];
+
+ // Convert the values with units to absolute pixels to allow our computations
+ ops = ops.map(function (op, index) {
+ // Most of the units rely on the orientation of the popper
+ var measurement = (index === 1 ? !useHeight : useHeight) ? 'height' : 'width';
+ var mergeWithPrevious = false;
+ return op
+ // This aggregates any `+` or `-` sign that aren't considered operators
+ // e.g.: 10 + +5 => [10, +, +5]
+ .reduce(function (a, b) {
+ if (a[a.length - 1] === '' && ['+', '-'].indexOf(b) !== -1) {
+ a[a.length - 1] = b;
+ mergeWithPrevious = true;
+ return a;
+ } else if (mergeWithPrevious) {
+ a[a.length - 1] += b;
+ mergeWithPrevious = false;
+ return a;
+ } else {
+ return a.concat(b);
+ }
+ }, [])
+ // Here we convert the string values into number values (in px)
+ .map(function (str) {
+ return toValue(str, measurement, popperOffsets, referenceOffsets);
+ });
+ });
+
+ // Loop trough the offsets arrays and execute the operations
+ ops.forEach(function (op, index) {
+ op.forEach(function (frag, index2) {
+ if (isNumeric(frag)) {
+ offsets[index] += frag * (op[index2 - 1] === '-' ? -1 : 1);
+ }
+ });
+ });
+ return offsets;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @argument {Number|String} options.offset=0
+ * The offset value as described in the modifier description
+ * @returns {Object} The data object, properly modified
+ */
+function offset(data, _ref) {
+ var offset = _ref.offset;
+ var placement = data.placement,
+ _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
+
+ var basePlacement = placement.split('-')[0];
+
+ var offsets = void 0;
+ if (isNumeric(+offset)) {
+ offsets = [+offset, 0];
+ } else {
+ offsets = parseOffset(offset, popper, reference, basePlacement);
+ }
+
+ if (basePlacement === 'left') {
+ popper.top += offsets[0];
+ popper.left -= offsets[1];
+ } else if (basePlacement === 'right') {
+ popper.top += offsets[0];
+ popper.left += offsets[1];
+ } else if (basePlacement === 'top') {
+ popper.left += offsets[0];
+ popper.top -= offsets[1];
+ } else if (basePlacement === 'bottom') {
+ popper.left += offsets[0];
+ popper.top += offsets[1];
+ }
+
+ data.popper = popper;
+ return data;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function preventOverflow(data, options) {
+ var boundariesElement = options.boundariesElement || getOffsetParent(data.instance.popper);
+
+ // If offsetParent is the reference element, we really want to
+ // go one step up and use the next offsetParent as reference to
+ // avoid to make this modifier completely useless and look like broken
+ if (data.instance.reference === boundariesElement) {
+ boundariesElement = getOffsetParent(boundariesElement);
+ }
+
+ var boundaries = getBoundaries(data.instance.popper, data.instance.reference, options.padding, boundariesElement);
+ options.boundaries = boundaries;
+
+ var order = options.priority;
+ var popper = data.offsets.popper;
+
+ var check = {
+ primary: function primary(placement) {
+ var value = popper[placement];
+ if (popper[placement] < boundaries[placement] && !options.escapeWithReference) {
+ value = Math.max(popper[placement], boundaries[placement]);
+ }
+ return defineProperty({}, placement, value);
+ },
+ secondary: function secondary(placement) {
+ var mainSide = placement === 'right' ? 'left' : 'top';
+ var value = popper[mainSide];
+ if (popper[placement] > boundaries[placement] && !options.escapeWithReference) {
+ value = Math.min(popper[mainSide], boundaries[placement] - (placement === 'right' ? popper.width : popper.height));
+ }
+ return defineProperty({}, mainSide, value);
+ }
+ };
+
+ order.forEach(function (placement) {
+ var side = ['left', 'top'].indexOf(placement) !== -1 ? 'primary' : 'secondary';
+ popper = _extends({}, popper, check[side](placement));
+ });
+
+ data.offsets.popper = popper;
+
+ return data;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function shift(data) {
+ var placement = data.placement;
+ var basePlacement = placement.split('-')[0];
+ var shiftvariation = placement.split('-')[1];
+
+ // if shift shiftvariation is specified, run the modifier
+ if (shiftvariation) {
+ var _data$offsets = data.offsets,
+ reference = _data$offsets.reference,
+ popper = _data$offsets.popper;
+
+ var isVertical = ['bottom', 'top'].indexOf(basePlacement) !== -1;
+ var side = isVertical ? 'left' : 'top';
+ var measurement = isVertical ? 'width' : 'height';
+
+ var shiftOffsets = {
+ start: defineProperty({}, side, reference[side]),
+ end: defineProperty({}, side, reference[side] + reference[measurement] - popper[measurement])
+ };
+
+ data.offsets.popper = _extends({}, popper, shiftOffsets[shiftvariation]);
+ }
+
+ return data;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by update method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function hide(data) {
+ if (!isModifierRequired(data.instance.modifiers, 'hide', 'preventOverflow')) {
+ return data;
+ }
+
+ var refRect = data.offsets.reference;
+ var bound = find(data.instance.modifiers, function (modifier) {
+ return modifier.name === 'preventOverflow';
+ }).boundaries;
+
+ if (refRect.bottom < bound.top || refRect.left > bound.right || refRect.top > bound.bottom || refRect.right < bound.left) {
+ // Avoid unnecessary DOM access if visibility hasn't changed
+ if (data.hide === true) {
+ return data;
+ }
+
+ data.hide = true;
+ data.attributes['x-out-of-boundaries'] = '';
+ } else {
+ // Avoid unnecessary DOM access if visibility hasn't changed
+ if (data.hide === false) {
+ return data;
+ }
+
+ data.hide = false;
+ data.attributes['x-out-of-boundaries'] = false;
+ }
+
+ return data;
+}
+
+/**
+ * @function
+ * @memberof Modifiers
+ * @argument {Object} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {Object} The data object, properly modified
+ */
+function inner(data) {
+ var placement = data.placement;
+ var basePlacement = placement.split('-')[0];
+ var _data$offsets = data.offsets,
+ popper = _data$offsets.popper,
+ reference = _data$offsets.reference;
+
+ var isHoriz = ['left', 'right'].indexOf(basePlacement) !== -1;
+
+ var subtractLength = ['top', 'left'].indexOf(basePlacement) === -1;
+
+ popper[isHoriz ? 'left' : 'top'] = reference[basePlacement] - (subtractLength ? popper[isHoriz ? 'width' : 'height'] : 0);
+
+ data.placement = getOppositePlacement(placement);
+ data.offsets.popper = getClientRect(popper);
+
+ return data;
+}
+
+/**
+ * Modifier function, each modifier can have a function of this type assigned
+ * to its `fn` property.<br />
+ * These functions will be called on each update, this means that you must
+ * make sure they are performant enough to avoid performance bottlenecks.
+ *
+ * @function ModifierFn
+ * @argument {dataObject} data - The data object generated by `update` method
+ * @argument {Object} options - Modifiers configuration and options
+ * @returns {dataObject} The data object, properly modified
+ */
+
+/**
+ * Modifiers are plugins used to alter the behavior of your poppers.<br />
+ * Popper.js uses a set of 9 modifiers to provide all the basic functionalities
+ * needed by the library.
+ *
+ * Usually you don't want to override the `order`, `fn` and `onLoad` props.
+ * All the other properties are configurations that could be tweaked.
+ * @namespace modifiers
+ */
+var modifiers = {
+ /**
+ * Modifier used to shift the popper on the start or end of its reference
+ * element.<br />
+ * It will read the variation of the `placement` property.<br />
+ * It can be one either `-end` or `-start`.
+ * @memberof modifiers
+ * @inner
+ */
+ shift: {
+ /** @prop {number} order=100 - Index used to define the order of execution */
+ order: 100,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: shift
+ },
+
+ /**
+ * The `offset` modifier can shift your popper on both its axis.
+ *
+ * It accepts the following units:
+ * - `px` or unitless, interpreted as pixels
+ * - `%` or `%r`, percentage relative to the length of the reference element
+ * - `%p`, percentage relative to the length of the popper element
+ * - `vw`, CSS viewport width unit
+ * - `vh`, CSS viewport height unit
+ *
+ * For length is intended the main axis relative to the placement of the popper.<br />
+ * This means that if the placement is `top` or `bottom`, the length will be the
+ * `width`. In case of `left` or `right`, it will be the height.
+ *
+ * You can provide a single value (as `Number` or `String`), or a pair of values
+ * as `String` divided by a comma or one (or more) white spaces.<br />
+ * The latter is a deprecated method because it leads to confusion and will be
+ * removed in v2.<br />
+ * Additionally, it accepts additions and subtractions between different units.
+ * Note that multiplications and divisions aren't supported.
+ *
+ * Valid examples are:
+ * ```
+ * 10
+ * '10%'
+ * '10, 10'
+ * '10%, 10'
+ * '10 + 10%'
+ * '10 - 5vh + 3%'
+ * '-10px + 5vh, 5px - 6%'
+ * ```
+ * > **NB**: If you desire to apply offsets to your poppers in a way that may make them overlap
+ * > with their reference element, unfortunately, you will have to disable the `flip` modifier.
+ * > More on this [reading this issue](https://github.com/FezVrasta/popper.js/issues/373)
+ *
+ * @memberof modifiers
+ * @inner
+ */
+ offset: {
+ /** @prop {number} order=200 - Index used to define the order of execution */
+ order: 200,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: offset,
+ /** @prop {Number|String} offset=0
+ * The offset value as described in the modifier description
+ */
+ offset: 0
+ },
+
+ /**
+ * Modifier used to prevent the popper from being positioned outside the boundary.
+ *
+ * An scenario exists where the reference itself is not within the boundaries.<br />
+ * We can say it has "escaped the boundaries" — or just "escaped".<br />
+ * In this case we need to decide whether the popper should either:
+ *
+ * - detach from the reference and remain "trapped" in the boundaries, or
+ * - if it should ignore the boundary and "escape with its reference"
+ *
+ * When `escapeWithReference` is set to`true` and reference is completely
+ * outside its boundaries, the popper will overflow (or completely leave)
+ * the boundaries in order to remain attached to the edge of the reference.
+ *
+ * @memberof modifiers
+ * @inner
+ */
+ preventOverflow: {
+ /** @prop {number} order=300 - Index used to define the order of execution */
+ order: 300,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: preventOverflow,
+ /**
+ * @prop {Array} [priority=['left','right','top','bottom']]
+ * Popper will try to prevent overflow following these priorities by default,
+ * then, it could overflow on the left and on top of the `boundariesElement`
+ */
+ priority: ['left', 'right', 'top', 'bottom'],
+ /**
+ * @prop {number} padding=5
+ * Amount of pixel used to define a minimum distance between the boundaries
+ * and the popper this makes sure the popper has always a little padding
+ * between the edges of its container
+ */
+ padding: 5,
+ /**
+ * @prop {String|HTMLElement} boundariesElement='scrollParent'
+ * Boundaries used by the modifier, can be `scrollParent`, `window`,
+ * `viewport` or any DOM element.
+ */
+ boundariesElement: 'scrollParent'
+ },
+
+ /**
+ * Modifier used to make sure the reference and its popper stay near eachothers
+ * without leaving any gap between the two. Expecially useful when the arrow is
+ * enabled and you want to assure it to point to its reference element.
+ * It cares only about the first axis, you can still have poppers with margin
+ * between the popper and its reference element.
+ * @memberof modifiers
+ * @inner
+ */
+ keepTogether: {
+ /** @prop {number} order=400 - Index used to define the order of execution */
+ order: 400,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: keepTogether
+ },
+
+ /**
+ * This modifier is used to move the `arrowElement` of the popper to make
+ * sure it is positioned between the reference element and its popper element.
+ * It will read the outer size of the `arrowElement` node to detect how many
+ * pixels of conjuction are needed.
+ *
+ * It has no effect if no `arrowElement` is provided.
+ * @memberof modifiers
+ * @inner
+ */
+ arrow: {
+ /** @prop {number} order=500 - Index used to define the order of execution */
+ order: 500,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: arrow,
+ /** @prop {String|HTMLElement} element='[x-arrow]' - Selector or node used as arrow */
+ element: '[x-arrow]'
+ },
+
+ /**
+ * Modifier used to flip the popper's placement when it starts to overlap its
+ * reference element.
+ *
+ * Requires the `preventOverflow` modifier before it in order to work.
+ *
+ * **NOTE:** this modifier will interrupt the current update cycle and will
+ * restart it if it detects the need to flip the placement.
+ * @memberof modifiers
+ * @inner
+ */
+ flip: {
+ /** @prop {number} order=600 - Index used to define the order of execution */
+ order: 600,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: flip,
+ /**
+ * @prop {String|Array} behavior='flip'
+ * The behavior used to change the popper's placement. It can be one of
+ * `flip`, `clockwise`, `counterclockwise` or an array with a list of valid
+ * placements (with optional variations).
+ */
+ behavior: 'flip',
+ /**
+ * @prop {number} padding=5
+ * The popper will flip if it hits the edges of the `boundariesElement`
+ */
+ padding: 5,
+ /**
+ * @prop {String|HTMLElement} boundariesElement='viewport'
+ * The element which will define the boundaries of the popper position,
+ * the popper will never be placed outside of the defined boundaries
+ * (except if keepTogether is enabled)
+ */
+ boundariesElement: 'viewport'
+ },
+
+ /**
+ * Modifier used to make the popper flow toward the inner of the reference element.
+ * By default, when this modifier is disabled, the popper will be placed outside
+ * the reference element.
+ * @memberof modifiers
+ * @inner
+ */
+ inner: {
+ /** @prop {number} order=700 - Index used to define the order of execution */
+ order: 700,
+ /** @prop {Boolean} enabled=false - Whether the modifier is enabled or not */
+ enabled: false,
+ /** @prop {ModifierFn} */
+ fn: inner
+ },
+
+ /**
+ * Modifier used to hide the popper when its reference element is outside of the
+ * popper boundaries. It will set a `x-out-of-boundaries` attribute which can
+ * be used to hide with a CSS selector the popper when its reference is
+ * out of boundaries.
+ *
+ * Requires the `preventOverflow` modifier before it in order to work.
+ * @memberof modifiers
+ * @inner
+ */
+ hide: {
+ /** @prop {number} order=800 - Index used to define the order of execution */
+ order: 800,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: hide
+ },
+
+ /**
+ * Computes the style that will be applied to the popper element to gets
+ * properly positioned.
+ *
+ * Note that this modifier will not touch the DOM, it just prepares the styles
+ * so that `applyStyle` modifier can apply it. This separation is useful
+ * in case you need to replace `applyStyle` with a custom implementation.
+ *
+ * This modifier has `850` as `order` value to maintain backward compatibility
+ * with previous versions of Popper.js. Expect the modifiers ordering method
+ * to change in future major versions of the library.
+ *
+ * @memberof modifiers
+ * @inner
+ */
+ computeStyle: {
+ /** @prop {number} order=850 - Index used to define the order of execution */
+ order: 850,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: computeStyle,
+ /**
+ * @prop {Boolean} gpuAcceleration=true
+ * If true, it uses the CSS 3d transformation to position the popper.
+ * Otherwise, it will use the `top` and `left` properties.
+ */
+ gpuAcceleration: true,
+ /**
+ * @prop {string} [x='bottom']
+ * Where to anchor the X axis (`bottom` or `top`). AKA X offset origin.
+ * Change this if your popper should grow in a direction different from `bottom`
+ */
+ x: 'bottom',
+ /**
+ * @prop {string} [x='left']
+ * Where to anchor the Y axis (`left` or `right`). AKA Y offset origin.
+ * Change this if your popper should grow in a direction different from `right`
+ */
+ y: 'right'
+ },
+
+ /**
+ * Applies the computed styles to the popper element.
+ *
+ * All the DOM manipulations are limited to this modifier. This is useful in case
+ * you want to integrate Popper.js inside a framework or view library and you
+ * want to delegate all the DOM manipulations to it.
+ *
+ * Note that if you disable this modifier, you must make sure the popper element
+ * has its position set to `absolute` before Popper.js can do its work!
+ *
+ * Just disable this modifier and define you own to achieve the desired effect.
+ *
+ * @memberof modifiers
+ * @inner
+ */
+ applyStyle: {
+ /** @prop {number} order=900 - Index used to define the order of execution */
+ order: 900,
+ /** @prop {Boolean} enabled=true - Whether the modifier is enabled or not */
+ enabled: true,
+ /** @prop {ModifierFn} */
+ fn: applyStyle,
+ /** @prop {Function} */
+ onLoad: applyStyleOnLoad,
+ /**
+ * @deprecated since version 1.10.0, the property moved to `computeStyle` modifier
+ * @prop {Boolean} gpuAcceleration=true
+ * If true, it uses the CSS 3d transformation to position the popper.
+ * Otherwise, it will use the `top` and `left` properties.
+ */
+ gpuAcceleration: undefined
+ }
+};
+
+/**
+ * The `dataObject` is an object containing all the informations used by Popper.js
+ * this object get passed to modifiers and to the `onCreate` and `onUpdate` callbacks.
+ * @name dataObject
+ * @property {Object} data.instance The Popper.js instance
+ * @property {String} data.placement Placement applied to popper
+ * @property {String} data.originalPlacement Placement originally defined on init
+ * @property {Boolean} data.flipped True if popper has been flipped by flip modifier
+ * @property {Boolean} data.hide True if the reference element is out of boundaries, useful to know when to hide the popper.
+ * @property {HTMLElement} data.arrowElement Node used as arrow by arrow modifier
+ * @property {Object} data.styles Any CSS property defined here will be applied to the popper, it expects the JavaScript nomenclature (eg. `marginBottom`)
+ * @property {Object} data.arrowStyles Any CSS property defined here will be applied to the popper arrow, it expects the JavaScript nomenclature (eg. `marginBottom`)
+ * @property {Object} data.boundaries Offsets of the popper boundaries
+ * @property {Object} data.offsets The measurements of popper, reference and arrow elements.
+ * @property {Object} data.offsets.popper `top`, `left`, `width`, `height` values
+ * @property {Object} data.offsets.reference `top`, `left`, `width`, `height` values
+ * @property {Object} data.offsets.arrow] `top` and `left` offsets, only one of them will be different from 0
+ */
+
+/**
+ * Default options provided to Popper.js constructor.<br />
+ * These can be overriden using the `options` argument of Popper.js.<br />
+ * To override an option, simply pass as 3rd argument an object with the same
+ * structure of this object, example:
+ * ```
+ * new Popper(ref, pop, {
+ * modifiers: {
+ * preventOverflow: { enabled: false }
+ * }
+ * })
+ * ```
+ * @type {Object}
+ * @static
+ * @memberof Popper
+ */
+var Defaults = {
+ /**
+ * Popper's placement
+ * @prop {Popper.placements} placement='bottom'
+ */
+ placement: 'bottom',
+
+ /**
+ * Whether events (resize, scroll) are initially enabled
+ * @prop {Boolean} eventsEnabled=true
+ */
+ eventsEnabled: true,
+
+ /**
+ * Set to true if you want to automatically remove the popper when
+ * you call the `destroy` method.
+ * @prop {Boolean} removeOnDestroy=false
+ */
+ removeOnDestroy: false,
+
+ /**
+ * Callback called when the popper is created.<br />
+ * By default, is set to no-op.<br />
+ * Access Popper.js instance with `data.instance`.
+ * @prop {onCreate}
+ */
+ onCreate: function onCreate() {},
+
+ /**
+ * Callback called when the popper is updated, this callback is not called
+ * on the initialization/creation of the popper, but only on subsequent
+ * updates.<br />
+ * By default, is set to no-op.<br />
+ * Access Popper.js instance with `data.instance`.
+ * @prop {onUpdate}
+ */
+ onUpdate: function onUpdate() {},
+
+ /**
+ * List of modifiers used to modify the offsets before they are applied to the popper.
+ * They provide most of the functionalities of Popper.js
+ * @prop {modifiers}
+ */
+ modifiers: modifiers
+};
+
+/**
+ * @callback onCreate
+ * @param {dataObject} data
+ */
+
+/**
+ * @callback onUpdate
+ * @param {dataObject} data
+ */
+
+// Utils
+// Methods
+var Popper = function () {
+ /**
+ * Create a new Popper.js instance
+ * @class Popper
+ * @param {HTMLElement|referenceObject} reference - The reference element used to position the popper
+ * @param {HTMLElement} popper - The HTML element used as popper.
+ * @param {Object} options - Your custom options to override the ones defined in [Defaults](#defaults)
+ * @return {Object} instance - The generated Popper.js instance
+ */
+ function Popper(reference, popper) {
+ var _this = this;
+
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
+ classCallCheck(this, Popper);
+
+ this.scheduleUpdate = function () {
+ return requestAnimationFrame(_this.update);
+ };
+
+ // make update() debounced, so that it only runs at most once-per-tick
+ this.update = debounce(this.update.bind(this));
+
+ // with {} we create a new object with the options inside it
+ this.options = _extends({}, Popper.Defaults, options);
+
+ // init state
+ this.state = {
+ isDestroyed: false,
+ isCreated: false,
+ scrollParents: []
+ };
+
+ // get reference and popper elements (allow jQuery wrappers)
+ this.reference = reference && reference.jquery ? reference[0] : reference;
+ this.popper = popper && popper.jquery ? popper[0] : popper;
+
+ // Deep merge modifiers options
+ this.options.modifiers = {};
+ Object.keys(_extends({}, Popper.Defaults.modifiers, options.modifiers)).forEach(function (name) {
+ _this.options.modifiers[name] = _extends({}, Popper.Defaults.modifiers[name] || {}, options.modifiers ? options.modifiers[name] : {});
+ });
+
+ // Refactoring modifiers' list (Object => Array)
+ this.modifiers = Object.keys(this.options.modifiers).map(function (name) {
+ return _extends({
+ name: name
+ }, _this.options.modifiers[name]);
+ })
+ // sort the modifiers by order
+ .sort(function (a, b) {
+ return a.order - b.order;
+ });
+
+ // modifiers have the ability to execute arbitrary code when Popper.js get inited
+ // such code is executed in the same order of its modifier
+ // they could add new properties to their options configuration
+ // BE AWARE: don't add options to `options.modifiers.name` but to `modifierOptions`!
+ this.modifiers.forEach(function (modifierOptions) {
+ if (modifierOptions.enabled && isFunction(modifierOptions.onLoad)) {
+ modifierOptions.onLoad(_this.reference, _this.popper, _this.options, modifierOptions, _this.state);
+ }
+ });
+
+ // fire the first update to position the popper in the right place
+ this.update();
+
+ var eventsEnabled = this.options.eventsEnabled;
+ if (eventsEnabled) {
+ // setup event listeners, they will take care of update the position in specific situations
+ this.enableEventListeners();
+ }
+
+ this.state.eventsEnabled = eventsEnabled;
+ }
+
+ // We can't use class properties because they don't get listed in the
+ // class prototype and break stuff like Sinon stubs
+
+
+ createClass(Popper, [{
+ key: 'update',
+ value: function update$$1() {
+ return update.call(this);
+ }
+ }, {
+ key: 'destroy',
+ value: function destroy$$1() {
+ return destroy.call(this);
+ }
+ }, {
+ key: 'enableEventListeners',
+ value: function enableEventListeners$$1() {
+ return enableEventListeners.call(this);
+ }
+ }, {
+ key: 'disableEventListeners',
+ value: function disableEventListeners$$1() {
+ return disableEventListeners.call(this);
+ }
+
+ /**
+ * Schedule an update, it will run on the next UI update available
+ * @method scheduleUpdate
+ * @memberof Popper
+ */
+
+
+ /**
+ * Collection of utilities useful when writing custom modifiers.
+ * Starting from version 1.7, this method is available only if you
+ * include `popper-utils.js` before `popper.js`.
+ *
+ * **DEPRECATION**: This way to access PopperUtils is deprecated
+ * and will be removed in v2! Use the PopperUtils module directly instead.
+ * Due to the high instability of the methods contained in Utils, we can't
+ * guarantee them to follow semver. Use them at your own risk!
+ * @static
+ * @private
+ * @type {Object}
+ * @deprecated since version 1.8
+ * @member Utils
+ * @memberof Popper
+ */
+
+ }]);
+ return Popper;
+}();
+
+/**
+ * The `referenceObject` is an object that provides an interface compatible with Popper.js
+ * and lets you use it as replacement of a real DOM node.<br />
+ * You can use this method to position a popper relatively to a set of coordinates
+ * in case you don't have a DOM node to use as reference.
+ *
+ * ```
+ * new Popper(referenceObject, popperNode);
+ * ```
+ *
+ * NB: This feature isn't supported in Internet Explorer 10
+ * @name referenceObject
+ * @property {Function} data.getBoundingClientRect
+ * A function that returns a set of coordinates compatible with the native `getBoundingClientRect` method.
+ * @property {number} data.clientWidth
+ * An ES6 getter that will return the width of the virtual reference element.
+ * @property {number} data.clientHeight
+ * An ES6 getter that will return the height of the virtual reference element.
+ */
+
+
+Popper.Utils = (typeof window !== 'undefined' ? window : global).PopperUtils;
+Popper.placements = placements;
+Popper.Defaults = Defaults;
+
+/* harmony default export */ __webpack_exports__["default"] = (Popper);
+//# sourceMappingURL=popper.js.map
+
+/* WEBPACK VAR INJECTION */}.call(__webpack_exports__, __webpack_require__(3)))
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports) {
+
+var g;
+
+// This works in non-strict mode
+g = (function() {
+ return this;
+})();
+
+try {
+ // This works if eval is allowed (see CSP)
+ g = g || Function("return this")() || (1,eval)("this");
+} catch(e) {
+ // This works if the window reference is available
+ if(typeof window === "object")
+ g = window;
+}
+
+// g can still be undefined, but nothing to do about it...
+// We return undefined, instead of nothing here, so it's
+// easier to handle this case. if(!global) { ...}
+
+module.exports = g;
+
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! DataTables 1.10.16
+ * ©2008-2017 SpryMedia Ltd - datatables.net/license
+ */
+
+/**
+ * @summary DataTables
+ * @description Paginate, search and order HTML tables
+ * @version 1.10.16
+ * @file jquery.dataTables.js
+ * @author SpryMedia Ltd
+ * @contact www.datatables.net
+ * @copyright Copyright 2008-2017 SpryMedia Ltd.
+ *
+ * This source file is free software, available under the following license:
+ * MIT license - http://datatables.net/license
+ *
+ * This source file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
+ *
+ * For details please refer to: http://www.datatables.net
+ */
+
+/*jslint evil: true, undef: true, browser: true */
+/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
+
+(function( factory ) {
+ "use strict";
+
+ if ( true ) {
+ // AMD
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {
+ return factory( $, window, document );
+ }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ }
+ else if ( typeof exports === 'object' ) {
+ // CommonJS
+ module.exports = function (root, $) {
+ if ( ! root ) {
+ // CommonJS environments without a window global must pass a
+ // root. This will give an error otherwise
+ root = window;
+ }
+
+ if ( ! $ ) {
+ $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
+ require('jquery') :
+ require('jquery')( root );
+ }
+
+ return factory( $, root, root.document );
+ };
+ }
+ else {
+ // Browser
+ factory( jQuery, window, document );
+ }
+}
+(function( $, window, document, undefined ) {
+ "use strict";
+
+ /**
+ * DataTables is a plug-in for the jQuery Javascript library. It is a highly
+ * flexible tool, based upon the foundations of progressive enhancement,
+ * which will add advanced interaction controls to any HTML table. For a
+ * full list of features please refer to
+ * [DataTables.net](href="http://datatables.net).
+ *
+ * Note that the `DataTable` object is not a global variable but is aliased
+ * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
+ * be accessed.
+ *
+ * @class
+ * @param {object} [init={}] Configuration object for DataTables. Options
+ * are defined by {@link DataTable.defaults}
+ * @requires jQuery 1.7+
+ *
+ * @example
+ * // Basic initialisation
+ * $(document).ready( function {
+ * $('#example').dataTable();
+ * } );
+ *
+ * @example
+ * // Initialisation with configuration options - in this case, disable
+ * // pagination and sorting.
+ * $(document).ready( function {
+ * $('#example').dataTable( {
+ * "paginate": false,
+ * "sort": false
+ * } );
+ * } );
+ */
+ var DataTable = function ( options )
+ {
+ /**
+ * Perform a jQuery selector action on the table's TR elements (from the tbody) and
+ * return the resulting jQuery object.
+ * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
+ * @param {object} [oOpts] Optional parameters for modifying the rows to be included
+ * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
+ * criterion ("applied") or all TR elements (i.e. no filter).
+ * @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
+ * Can be either 'current', whereby the current sorting of the table is used, or
+ * 'original' whereby the original order the data was read into the table is used.
+ * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
+ * ("current") or not ("all"). If 'current' is given, then order is assumed to be
+ * 'current' and filter is 'applied', regardless of what they might be given as.
+ * @returns {object} jQuery object, filtered by the given selector.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Highlight every second row
+ * oTable.$('tr:odd').css('backgroundColor', 'blue');
+ * } );
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Filter to rows with 'Webkit' in them, add a background colour and then
+ * // remove the filter, thus highlighting the 'Webkit' rows only.
+ * oTable.fnFilter('Webkit');
+ * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
+ * oTable.fnFilter('');
+ * } );
+ */
+ this.$ = function ( sSelector, oOpts )
+ {
+ return this.api(true).$( sSelector, oOpts );
+ };
+
+
+ /**
+ * Almost identical to $ in operation, but in this case returns the data for the matched
+ * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
+ * rather than any descendants, so the data can be obtained for the row/cell. If matching
+ * rows are found, the data returned is the original data array/object that was used to
+ * create the row (or a generated array if from a DOM source).
+ *
+ * This method is often useful in-combination with $ where both functions are given the
+ * same parameters and the array indexes will match identically.
+ * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
+ * @param {object} [oOpts] Optional parameters for modifying the rows to be included
+ * @param {string} [oOpts.filter=none] Select elements that meet the current filter
+ * criterion ("applied") or all elements (i.e. no filter).
+ * @param {string} [oOpts.order=current] Order of the data in the processed array.
+ * Can be either 'current', whereby the current sorting of the table is used, or
+ * 'original' whereby the original order the data was read into the table is used.
+ * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
+ * ("current") or not ("all"). If 'current' is given, then order is assumed to be
+ * 'current' and filter is 'applied', regardless of what they might be given as.
+ * @returns {array} Data for the matched elements. If any elements, as a result of the
+ * selector, were not TR, TD or TH elements in the DataTable, they will have a null
+ * entry in the array.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Get the data from the first row in the table
+ * var data = oTable._('tr:first');
+ *
+ * // Do something useful with the data
+ * alert( "First cell is: "+data[0] );
+ * } );
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Filter to 'Webkit' and get all data for
+ * oTable.fnFilter('Webkit');
+ * var data = oTable._('tr', {"search": "applied"});
+ *
+ * // Do something with the data
+ * alert( data.length+" rows matched the search" );
+ * } );
+ */
+ this._ = function ( sSelector, oOpts )
+ {
+ return this.api(true).rows( sSelector, oOpts ).data();
+ };
+
+
+ /**
+ * Create a DataTables Api instance, with the currently selected tables for
+ * the Api's context.
+ * @param {boolean} [traditional=false] Set the API instance's context to be
+ * only the table referred to by the `DataTable.ext.iApiIndex` option, as was
+ * used in the API presented by DataTables 1.9- (i.e. the traditional mode),
+ * or if all tables captured in the jQuery object should be used.
+ * @return {DataTables.Api}
+ */
+ this.api = function ( traditional )
+ {
+ return traditional ?
+ new _Api(
+ _fnSettingsFromNode( this[ _ext.iApiIndex ] )
+ ) :
+ new _Api( this );
+ };
+
+
+ /**
+ * Add a single new row or multiple rows of data to the table. Please note
+ * that this is suitable for client-side processing only - if you are using
+ * server-side processing (i.e. "bServerSide": true), then to add data, you
+ * must add it to the data source, i.e. the server-side, through an Ajax call.
+ * @param {array|object} data The data to be added to the table. This can be:
+ * <ul>
+ * <li>1D array of data - add a single row with the data provided</li>
+ * <li>2D array of arrays - add multiple rows in a single call</li>
+ * <li>object - data object when using <i>mData</i></li>
+ * <li>array of objects - multiple data objects when using <i>mData</i></li>
+ * </ul>
+ * @param {bool} [redraw=true] redraw the table or not
+ * @returns {array} An array of integers, representing the list of indexes in
+ * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
+ * the table.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * // Global var for counter
+ * var giCount = 2;
+ *
+ * $(document).ready(function() {
+ * $('#example').dataTable();
+ * } );
+ *
+ * function fnClickAddRow() {
+ * $('#example').dataTable().fnAddData( [
+ * giCount+".1",
+ * giCount+".2",
+ * giCount+".3",
+ * giCount+".4" ]
+ * );
+ *
+ * giCount++;
+ * }
+ */
+ this.fnAddData = function( data, redraw )
+ {
+ var api = this.api( true );
+
+ /* Check if we want to add multiple rows or not */
+ var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
+ api.rows.add( data ) :
+ api.row.add( data );
+
+ if ( redraw === undefined || redraw ) {
+ api.draw();
+ }
+
+ return rows.flatten().toArray();
+ };
+
+
+ /**
+ * This function will make DataTables recalculate the column sizes, based on the data
+ * contained in the table and the sizes applied to the columns (in the DOM, CSS or
+ * through the sWidth parameter). This can be useful when the width of the table's
+ * parent element changes (for example a window resize).
+ * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable( {
+ * "sScrollY": "200px",
+ * "bPaginate": false
+ * } );
+ *
+ * $(window).on('resize', function () {
+ * oTable.fnAdjustColumnSizing();
+ * } );
+ * } );
+ */
+ this.fnAdjustColumnSizing = function ( bRedraw )
+ {
+ var api = this.api( true ).columns.adjust();
+ var settings = api.settings()[0];
+ var scroll = settings.oScroll;
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.draw( false );
+ }
+ else if ( scroll.sX !== "" || scroll.sY !== "" ) {
+ /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
+ _fnScrollDraw( settings );
+ }
+ };
+
+
+ /**
+ * Quickly and simply clear a table
+ * @param {bool} [bRedraw=true] redraw the table or not
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
+ * oTable.fnClearTable();
+ * } );
+ */
+ this.fnClearTable = function( bRedraw )
+ {
+ var api = this.api( true ).clear();
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.draw();
+ }
+ };
+
+
+ /**
+ * The exact opposite of 'opening' a row, this function will close any rows which
+ * are currently 'open'.
+ * @param {node} nTr the table row to 'close'
+ * @returns {int} 0 on success, or 1 if failed (can't find the row)
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable;
+ *
+ * // 'open' an information row when a row is clicked on
+ * $('#example tbody tr').click( function () {
+ * if ( oTable.fnIsOpen(this) ) {
+ * oTable.fnClose( this );
+ * } else {
+ * oTable.fnOpen( this, "Temporary row opened", "info_row" );
+ * }
+ * } );
+ *
+ * oTable = $('#example').dataTable();
+ * } );
+ */
+ this.fnClose = function( nTr )
+ {
+ this.api( true ).row( nTr ).child.hide();
+ };
+
+
+ /**
+ * Remove a row for the table
+ * @param {mixed} target The index of the row from aoData to be deleted, or
+ * the TR element you want to delete
+ * @param {function|null} [callBack] Callback function
+ * @param {bool} [redraw=true] Redraw the table or not
+ * @returns {array} The row that was deleted
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Immediately remove the first row
+ * oTable.fnDeleteRow( 0 );
+ * } );
+ */
+ this.fnDeleteRow = function( target, callback, redraw )
+ {
+ var api = this.api( true );
+ var rows = api.rows( target );
+ var settings = rows.settings()[0];
+ var data = settings.aoData[ rows[0][0] ];
+
+ rows.remove();
+
+ if ( callback ) {
+ callback.call( this, settings, data );
+ }
+
+ if ( redraw === undefined || redraw ) {
+ api.draw();
+ }
+
+ return data;
+ };
+
+
+ /**
+ * Restore the table to it's original state in the DOM by removing all of DataTables
+ * enhancements, alterations to the DOM structure of the table and event listeners.
+ * @param {boolean} [remove=false] Completely remove the table from the DOM
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * // This example is fairly pointless in reality, but shows how fnDestroy can be used
+ * var oTable = $('#example').dataTable();
+ * oTable.fnDestroy();
+ * } );
+ */
+ this.fnDestroy = function ( remove )
+ {
+ this.api( true ).destroy( remove );
+ };
+
+
+ /**
+ * Redraw the table
+ * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
+ * oTable.fnDraw();
+ * } );
+ */
+ this.fnDraw = function( complete )
+ {
+ // Note that this isn't an exact match to the old call to _fnDraw - it takes
+ // into account the new data, but can hold position.
+ this.api( true ).draw( complete );
+ };
+
+
+ /**
+ * Filter the input based on data
+ * @param {string} sInput String to filter the table on
+ * @param {int|null} [iColumn] Column to limit filtering to
+ * @param {bool} [bRegex=false] Treat as regular expression or not
+ * @param {bool} [bSmart=true] Perform smart filtering or not
+ * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
+ * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Sometime later - filter...
+ * oTable.fnFilter( 'test string' );
+ * } );
+ */
+ this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
+ {
+ var api = this.api( true );
+
+ if ( iColumn === null || iColumn === undefined ) {
+ api.search( sInput, bRegex, bSmart, bCaseInsensitive );
+ }
+ else {
+ api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
+ }
+
+ api.draw();
+ };
+
+
+ /**
+ * Get the data for the whole table, an individual row or an individual cell based on the
+ * provided parameters.
+ * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
+ * a TR node then the data source for the whole row will be returned. If given as a
+ * TD/TH cell node then iCol will be automatically calculated and the data for the
+ * cell returned. If given as an integer, then this is treated as the aoData internal
+ * data index for the row (see fnGetPosition) and the data for that row used.
+ * @param {int} [col] Optional column index that you want the data of.
+ * @returns {array|object|string} If mRow is undefined, then the data for all rows is
+ * returned. If mRow is defined, just data for that row, and is iCol is
+ * defined, only data for the designated cell is returned.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * // Row data
+ * $(document).ready(function() {
+ * oTable = $('#example').dataTable();
+ *
+ * oTable.$('tr').click( function () {
+ * var data = oTable.fnGetData( this );
+ * // ... do something with the array / object of data for the row
+ * } );
+ * } );
+ *
+ * @example
+ * // Individual cell data
+ * $(document).ready(function() {
+ * oTable = $('#example').dataTable();
+ *
+ * oTable.$('td').click( function () {
+ * var sData = oTable.fnGetData( this );
+ * alert( 'The cell clicked on had the value of '+sData );
+ * } );
+ * } );
+ */
+ this.fnGetData = function( src, col )
+ {
+ var api = this.api( true );
+
+ if ( src !== undefined ) {
+ var type = src.nodeName ? src.nodeName.toLowerCase() : '';
+
+ return col !== undefined || type == 'td' || type == 'th' ?
+ api.cell( src, col ).data() :
+ api.row( src ).data() || null;
+ }
+
+ return api.data().toArray();
+ };
+
+
+ /**
+ * Get an array of the TR nodes that are used in the table's body. Note that you will
+ * typically want to use the '$' API method in preference to this as it is more
+ * flexible.
+ * @param {int} [iRow] Optional row index for the TR element you want
+ * @returns {array|node} If iRow is undefined, returns an array of all TR elements
+ * in the table's body, or iRow is defined, just the TR element requested.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Get the nodes from the table
+ * var nNodes = oTable.fnGetNodes( );
+ * } );
+ */
+ this.fnGetNodes = function( iRow )
+ {
+ var api = this.api( true );
+
+ return iRow !== undefined ?
+ api.row( iRow ).node() :
+ api.rows().nodes().flatten().toArray();
+ };
+
+
+ /**
+ * Get the array indexes of a particular cell from it's DOM element
+ * and column index including hidden columns
+ * @param {node} node this can either be a TR, TD or TH in the table's body
+ * @returns {int} If nNode is given as a TR, then a single index is returned, or
+ * if given as a cell, an array of [row index, column index (visible),
+ * column index (all)] is given.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * $('#example tbody td').click( function () {
+ * // Get the position of the current data from the node
+ * var aPos = oTable.fnGetPosition( this );
+ *
+ * // Get the data array for this row
+ * var aData = oTable.fnGetData( aPos[0] );
+ *
+ * // Update the data array and return the value
+ * aData[ aPos[1] ] = 'clicked';
+ * this.innerHTML = 'clicked';
+ * } );
+ *
+ * // Init DataTables
+ * oTable = $('#example').dataTable();
+ * } );
+ */
+ this.fnGetPosition = function( node )
+ {
+ var api = this.api( true );
+ var nodeName = node.nodeName.toUpperCase();
+
+ if ( nodeName == 'TR' ) {
+ return api.row( node ).index();
+ }
+ else if ( nodeName == 'TD' || nodeName == 'TH' ) {
+ var cell = api.cell( node ).index();
+
+ return [
+ cell.row,
+ cell.columnVisible,
+ cell.column
+ ];
+ }
+ return null;
+ };
+
+
+ /**
+ * Check to see if a row is 'open' or not.
+ * @param {node} nTr the table row to check
+ * @returns {boolean} true if the row is currently open, false otherwise
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable;
+ *
+ * // 'open' an information row when a row is clicked on
+ * $('#example tbody tr').click( function () {
+ * if ( oTable.fnIsOpen(this) ) {
+ * oTable.fnClose( this );
+ * } else {
+ * oTable.fnOpen( this, "Temporary row opened", "info_row" );
+ * }
+ * } );
+ *
+ * oTable = $('#example').dataTable();
+ * } );
+ */
+ this.fnIsOpen = function( nTr )
+ {
+ return this.api( true ).row( nTr ).child.isShown();
+ };
+
+
+ /**
+ * This function will place a new row directly after a row which is currently
+ * on display on the page, with the HTML contents that is passed into the
+ * function. This can be used, for example, to ask for confirmation that a
+ * particular record should be deleted.
+ * @param {node} nTr The table row to 'open'
+ * @param {string|node|jQuery} mHtml The HTML to put into the row
+ * @param {string} sClass Class to give the new TD cell
+ * @returns {node} The row opened. Note that if the table row passed in as the
+ * first parameter, is not found in the table, this method will silently
+ * return.
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable;
+ *
+ * // 'open' an information row when a row is clicked on
+ * $('#example tbody tr').click( function () {
+ * if ( oTable.fnIsOpen(this) ) {
+ * oTable.fnClose( this );
+ * } else {
+ * oTable.fnOpen( this, "Temporary row opened", "info_row" );
+ * }
+ * } );
+ *
+ * oTable = $('#example').dataTable();
+ * } );
+ */
+ this.fnOpen = function( nTr, mHtml, sClass )
+ {
+ return this.api( true )
+ .row( nTr )
+ .child( mHtml, sClass )
+ .show()
+ .child()[0];
+ };
+
+
+ /**
+ * Change the pagination - provides the internal logic for pagination in a simple API
+ * function. With this function you can have a DataTables table go to the next,
+ * previous, first or last pages.
+ * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
+ * or page number to jump to (integer), note that page 0 is the first page.
+ * @param {bool} [bRedraw=true] Redraw the table or not
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ * oTable.fnPageChange( 'next' );
+ * } );
+ */
+ this.fnPageChange = function ( mAction, bRedraw )
+ {
+ var api = this.api( true ).page( mAction );
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.draw(false);
+ }
+ };
+
+
+ /**
+ * Show a particular column
+ * @param {int} iCol The column whose display should be changed
+ * @param {bool} bShow Show (true) or hide (false) the column
+ * @param {bool} [bRedraw=true] Redraw the table or not
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Hide the second column after initialisation
+ * oTable.fnSetColumnVis( 1, false );
+ * } );
+ */
+ this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
+ {
+ var api = this.api( true ).column( iCol ).visible( bShow );
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.columns.adjust().draw();
+ }
+ };
+
+
+ /**
+ * Get the settings for a particular table for external manipulation
+ * @returns {object} DataTables settings object. See
+ * {@link DataTable.models.oSettings}
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ * var oSettings = oTable.fnSettings();
+ *
+ * // Show an example parameter from the settings
+ * alert( oSettings._iDisplayStart );
+ * } );
+ */
+ this.fnSettings = function()
+ {
+ return _fnSettingsFromNode( this[_ext.iApiIndex] );
+ };
+
+
+ /**
+ * Sort the table by a particular column
+ * @param {int} iCol the data index to sort on. Note that this will not match the
+ * 'display index' if you have hidden data entries
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Sort immediately with columns 0 and 1
+ * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
+ * } );
+ */
+ this.fnSort = function( aaSort )
+ {
+ this.api( true ).order( aaSort ).draw();
+ };
+
+
+ /**
+ * Attach a sort listener to an element for a given column
+ * @param {node} nNode the element to attach the sort listener to
+ * @param {int} iColumn the column that a click on this node will sort on
+ * @param {function} [fnCallback] callback function when sort is run
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ *
+ * // Sort on column 1, when 'sorter' is clicked on
+ * oTable.fnSortListener( document.getElementById('sorter'), 1 );
+ * } );
+ */
+ this.fnSortListener = function( nNode, iColumn, fnCallback )
+ {
+ this.api( true ).order.listener( nNode, iColumn, fnCallback );
+ };
+
+
+ /**
+ * Update a table cell or row - this method will accept either a single value to
+ * update the cell with, an array of values with one element for each column or
+ * an object in the same format as the original data source. The function is
+ * self-referencing in order to make the multi column updates easier.
+ * @param {object|array|string} mData Data to update the cell/row with
+ * @param {node|int} mRow TR element you want to update or the aoData index
+ * @param {int} [iColumn] The column to update, give as null or undefined to
+ * update a whole row.
+ * @param {bool} [bRedraw=true] Redraw the table or not
+ * @param {bool} [bAction=true] Perform pre-draw actions or not
+ * @returns {int} 0 on success, 1 on error
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
+ * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
+ * } );
+ */
+ this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
+ {
+ var api = this.api( true );
+
+ if ( iColumn === undefined || iColumn === null ) {
+ api.row( mRow ).data( mData );
+ }
+ else {
+ api.cell( mRow, iColumn ).data( mData );
+ }
+
+ if ( bAction === undefined || bAction ) {
+ api.columns.adjust();
+ }
+
+ if ( bRedraw === undefined || bRedraw ) {
+ api.draw();
+ }
+ return 0;
+ };
+
+
+ /**
+ * Provide a common method for plug-ins to check the version of DataTables being used, in order
+ * to ensure compatibility.
+ * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
+ * formats "X" and "X.Y" are also acceptable.
+ * @returns {boolean} true if this version of DataTables is greater or equal to the required
+ * version, or false if this version of DataTales is not suitable
+ * @method
+ * @dtopt API
+ * @deprecated Since v1.10
+ *
+ * @example
+ * $(document).ready(function() {
+ * var oTable = $('#example').dataTable();
+ * alert( oTable.fnVersionCheck( '1.9.0' ) );
+ * } );
+ */
+ this.fnVersionCheck = _ext.fnVersionCheck;
+
+
+ var _that = this;
+ var emptyInit = options === undefined;
+ var len = this.length;
+
+ if ( emptyInit ) {
+ options = {};
+ }
+
+ this.oApi = this.internal = _ext.internal;
+
+ // Extend with old style plug-in API methods
+ for ( var fn in DataTable.ext.internal ) {
+ if ( fn ) {
+ this[fn] = _fnExternApiFunc(fn);
+ }
+ }
+
+ this.each(function() {
+ // For each initialisation we want to give it a clean initialisation
+ // object that can be bashed around
+ var o = {};
+ var oInit = len > 1 ? // optimisation for single table case
+ _fnExtend( o, options, true ) :
+ options;
+
+ /*global oInit,_that,emptyInit*/
+ var i=0, iLen, j, jLen, k, kLen;
+ var sId = this.getAttribute( 'id' );
+ var bInitHandedOff = false;
+ var defaults = DataTable.defaults;
+ var $this = $(this);
+
+
+ /* Sanity check */
+ if ( this.nodeName.toLowerCase() != 'table' )
+ {
+ _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
+ return;
+ }
+
+ /* Backwards compatibility for the defaults */
+ _fnCompatOpts( defaults );
+ _fnCompatCols( defaults.column );
+
+ /* Convert the camel-case defaults to Hungarian */
+ _fnCamelToHungarian( defaults, defaults, true );
+ _fnCamelToHungarian( defaults.column, defaults.column, true );
+
+ /* Setting up the initialisation object */
+ _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
+
+
+
+ /* Check to see if we are re-initialising a table */
+ var allSettings = DataTable.settings;
+ for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
+ {
+ var s = allSettings[i];
+
+ /* Base check on table node */
+ if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
+ {
+ var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
+ var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
+
+ if ( emptyInit || bRetrieve )
+ {
+ return s.oInstance;
+ }
+ else if ( bDestroy )
+ {
+ s.oInstance.fnDestroy();
+ break;
+ }
+ else
+ {
+ _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
+ return;
+ }
+ }
+
+ /* If the element we are initialising has the same ID as a table which was previously
+ * initialised, but the table nodes don't match (from before) then we destroy the old
+ * instance by simply deleting it. This is under the assumption that the table has been
+ * destroyed by other methods. Anyone using non-id selectors will need to do this manually
+ */
+ if ( s.sTableId == this.id )
+ {
+ allSettings.splice( i, 1 );
+ break;
+ }
+ }
+
+ /* Ensure the table has an ID - required for accessibility */
+ if ( sId === null || sId === "" )
+ {
+ sId = "DataTables_Table_"+(DataTable.ext._unique++);
+ this.id = sId;
+ }
+
+ /* Create the settings object for this table and set some of the default parameters */
+ var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
+ "sDestroyWidth": $this[0].style.width,
+ "sInstance": sId,
+ "sTableId": sId
+ } );
+ oSettings.nTable = this;
+ oSettings.oApi = _that.internal;
+ oSettings.oInit = oInit;
+
+ allSettings.push( oSettings );
+
+ // Need to add the instance after the instance after the settings object has been added
+ // to the settings array, so we can self reference the table instance if more than one
+ oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
+
+ // Backwards compatibility, before we apply all the defaults
+ _fnCompatOpts( oInit );
+
+ if ( oInit.oLanguage )
+ {
+ _fnLanguageCompat( oInit.oLanguage );
+ }
+
+ // If the length menu is given, but the init display length is not, use the length menu
+ if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
+ {
+ oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
+ oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
+ }
+
+ // Apply the defaults and init options to make a single init object will all
+ // options defined from defaults and instance options.
+ oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
+
+
+ // Map the initialisation options onto the settings object
+ _fnMap( oSettings.oFeatures, oInit, [
+ "bPaginate",
+ "bLengthChange",
+ "bFilter",
+ "bSort",
+ "bSortMulti",
+ "bInfo",
+ "bProcessing",
+ "bAutoWidth",
+ "bSortClasses",
+ "bServerSide",
+ "bDeferRender"
+ ] );
+ _fnMap( oSettings, oInit, [
+ "asStripeClasses",
+ "ajax",
+ "fnServerData",
+ "fnFormatNumber",
+ "sServerMethod",
+ "aaSorting",
+ "aaSortingFixed",
+ "aLengthMenu",
+ "sPaginationType",
+ "sAjaxSource",
+ "sAjaxDataProp",
+ "iStateDuration",
+ "sDom",
+ "bSortCellsTop",
+ "iTabIndex",
+ "fnStateLoadCallback",
+ "fnStateSaveCallback",
+ "renderer",
+ "searchDelay",
+ "rowId",
+ [ "iCookieDuration", "iStateDuration" ], // backwards compat
+ [ "oSearch", "oPreviousSearch" ],
+ [ "aoSearchCols", "aoPreSearchCols" ],
+ [ "iDisplayLength", "_iDisplayLength" ]
+ ] );
+ _fnMap( oSettings.oScroll, oInit, [
+ [ "sScrollX", "sX" ],
+ [ "sScrollXInner", "sXInner" ],
+ [ "sScrollY", "sY" ],
+ [ "bScrollCollapse", "bCollapse" ]
+ ] );
+ _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
+
+ /* Callback functions which are array driven */
+ _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' );
+ _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' );
+ _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' );
+ _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' );
+ _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' );
+ _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' );
+ _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' );
+ _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' );
+ _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' );
+ _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' );
+ _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' );
+
+ oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
+
+ /* Browser support detection */
+ _fnBrowserDetect( oSettings );
+
+ var oClasses = oSettings.oClasses;
+
+ $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
+ $this.addClass( oClasses.sTable );
+
+
+ if ( oSettings.iInitDisplayStart === undefined )
+ {
+ /* Display start point, taking into account the save saving */
+ oSettings.iInitDisplayStart = oInit.iDisplayStart;
+ oSettings._iDisplayStart = oInit.iDisplayStart;
+ }
+
+ if ( oInit.iDeferLoading !== null )
+ {
+ oSettings.bDeferLoading = true;
+ var tmp = $.isArray( oInit.iDeferLoading );
+ oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
+ oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
+ }
+
+ /* Language definitions */
+ var oLanguage = oSettings.oLanguage;
+ $.extend( true, oLanguage, oInit.oLanguage );
+
+ if ( oLanguage.sUrl )
+ {
+ /* Get the language definitions from a file - because this Ajax call makes the language
+ * get async to the remainder of this function we use bInitHandedOff to indicate that
+ * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
+ */
+ $.ajax( {
+ dataType: 'json',
+ url: oLanguage.sUrl,
+ success: function ( json ) {
+ _fnLanguageCompat( json );
+ _fnCamelToHungarian( defaults.oLanguage, json );
+ $.extend( true, oLanguage, json );
+ _fnInitialise( oSettings );
+ },
+ error: function () {
+ // Error occurred loading language file, continue on as best we can
+ _fnInitialise( oSettings );
+ }
+ } );
+ bInitHandedOff = true;
+ }
+
+ /*
+ * Stripes
+ */
+ if ( oInit.asStripeClasses === null )
+ {
+ oSettings.asStripeClasses =[
+ oClasses.sStripeOdd,
+ oClasses.sStripeEven
+ ];
+ }
+
+ /* Remove row stripe classes if they are already on the table row */
+ var stripeClasses = oSettings.asStripeClasses;
+ var rowOne = $this.children('tbody').find('tr').eq(0);
+ if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
+ return rowOne.hasClass(el);
+ } ) ) !== -1 ) {
+ $('tbody tr', this).removeClass( stripeClasses.join(' ') );
+ oSettings.asDestroyStripes = stripeClasses.slice();
+ }
+
+ /*
+ * Columns
+ * See if we should load columns automatically or use defined ones
+ */
+ var anThs = [];
+ var aoColumnsInit;
+ var nThead = this.getElementsByTagName('thead');
+ if ( nThead.length !== 0 )
+ {
+ _fnDetectHeader( oSettings.aoHeader, nThead[0] );
+ anThs = _fnGetUniqueThs( oSettings );
+ }
+
+ /* If not given a column array, generate one with nulls */
+ if ( oInit.aoColumns === null )
+ {
+ aoColumnsInit = [];
+ for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
+ {
+ aoColumnsInit.push( null );
+ }
+ }
+ else
+ {
+ aoColumnsInit = oInit.aoColumns;
+ }
+
+ /* Add the columns */
+ for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
+ {
+ _fnAddColumn( oSettings, anThs ? anThs[i] : null );
+ }
+
+ /* Apply the column definitions */
+ _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
+ _fnColumnOptions( oSettings, iCol, oDef );
+ } );
+
+ /* HTML5 attribute detection - build an mData object automatically if the
+ * attributes are found
+ */
+ if ( rowOne.length ) {
+ var a = function ( cell, name ) {
+ return cell.getAttribute( 'data-'+name ) !== null ? name : null;
+ };
+
+ $( rowOne[0] ).children('th, td').each( function (i, cell) {
+ var col = oSettings.aoColumns[i];
+
+ if ( col.mData === i ) {
+ var sort = a( cell, 'sort' ) || a( cell, 'order' );
+ var filter = a( cell, 'filter' ) || a( cell, 'search' );
+
+ if ( sort !== null || filter !== null ) {
+ col.mData = {
+ _: i+'.display',
+ sort: sort !== null ? i+'.@data-'+sort : undefined,
+ type: sort !== null ? i+'.@data-'+sort : undefined,
+ filter: filter !== null ? i+'.@data-'+filter : undefined
+ };
+
+ _fnColumnOptions( oSettings, i );
+ }
+ }
+ } );
+ }
+
+ var features = oSettings.oFeatures;
+ var loadedInit = function () {
+ /*
+ * Sorting
+ * @todo For modularisation (1.11) this needs to do into a sort start up handler
+ */
+
+ // If aaSorting is not defined, then we use the first indicator in asSorting
+ // in case that has been altered, so the default sort reflects that option
+ if ( oInit.aaSorting === undefined ) {
+ var sorting = oSettings.aaSorting;
+ for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
+ sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
+ }
+ }
+
+ /* Do a first pass on the sorting classes (allows any size changes to be taken into
+ * account, and also will apply sorting disabled classes if disabled
+ */
+ _fnSortingClasses( oSettings );
+
+ if ( features.bSort ) {
+ _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
+ if ( oSettings.bSorted ) {
+ var aSort = _fnSortFlatten( oSettings );
+ var sortedColumns = {};
+
+ $.each( aSort, function (i, val) {
+ sortedColumns[ val.src ] = val.dir;
+ } );
+
+ _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
+ _fnSortAria( oSettings );
+ }
+ } );
+ }
+
+ _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
+ if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
+ _fnSortingClasses( oSettings );
+ }
+ }, 'sc' );
+
+
+ /*
+ * Final init
+ * Cache the header, body and footer as required, creating them if needed
+ */
+
+ // Work around for Webkit bug 83867 - store the caption-side before removing from doc
+ var captions = $this.children('caption').each( function () {
+ this._captionSide = $(this).css('caption-side');
+ } );
+
+ var thead = $this.children('thead');
+ if ( thead.length === 0 ) {
+ thead = $('<thead/>').appendTo($this);
+ }
+ oSettings.nTHead = thead[0];
+
+ var tbody = $this.children('tbody');
+ if ( tbody.length === 0 ) {
+ tbody = $('<tbody/>').appendTo($this);
+ }
+ oSettings.nTBody = tbody[0];
+
+ var tfoot = $this.children('tfoot');
+ if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
+ // If we are a scrolling table, and no footer has been given, then we need to create
+ // a tfoot element for the caption element to be appended to
+ tfoot = $('<tfoot/>').appendTo($this);
+ }
+
+ if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
+ $this.addClass( oClasses.sNoFooter );
+ }
+ else if ( tfoot.length > 0 ) {
+ oSettings.nTFoot = tfoot[0];
+ _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
+ }
+
+ /* Check if there is data passing into the constructor */
+ if ( oInit.aaData ) {
+ for ( i=0 ; i<oInit.aaData.length ; i++ ) {
+ _fnAddData( oSettings, oInit.aaData[ i ] );
+ }
+ }
+ else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
+ /* Grab the data from the page - only do this when deferred loading or no Ajax
+ * source since there is no point in reading the DOM data if we are then going
+ * to replace it with Ajax data
+ */
+ _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
+ }
+
+ /* Copy the data index array */
+ oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
+
+ /* Initialisation complete - table can be drawn */
+ oSettings.bInitialised = true;
+
+ /* Check if we need to initialise the table (it might not have been handed off to the
+ * language processor)
+ */
+ if ( bInitHandedOff === false ) {
+ _fnInitialise( oSettings );
+ }
+ };
+
+ /* Must be done after everything which can be overridden by the state saving! */
+ if ( oInit.bStateSave )
+ {
+ features.bStateSave = true;
+ _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
+ _fnLoadState( oSettings, oInit, loadedInit );
+ }
+ else {
+ loadedInit();
+ }
+
+ } );
+ _that = null;
+ return this;
+ };
+
+
+ /*
+ * It is useful to have variables which are scoped locally so only the
+ * DataTables functions can access them and they don't leak into global space.
+ * At the same time these functions are often useful over multiple files in the
+ * core and API, so we list, or at least document, all variables which are used
+ * by DataTables as private variables here. This also ensures that there is no
+ * clashing of variable names and that they can easily referenced for reuse.
+ */
+
+
+ // Defined else where
+ // _selector_run
+ // _selector_opts
+ // _selector_first
+ // _selector_row_indexes
+
+ var _ext; // DataTable.ext
+ var _Api; // DataTable.Api
+ var _api_register; // DataTable.Api.register
+ var _api_registerPlural; // DataTable.Api.registerPlural
+
+ var _re_dic = {};
+ var _re_new_lines = /[\r\n]/g;
+ var _re_html = /<.*?>/g;
+
+ // This is not strict ISO8601 - Date.parse() is quite lax, although
+ // implementations differ between browsers.
+ var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
+
+ // Escape regular expression special characters
+ var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
+
+ // http://en.wikipedia.org/wiki/Foreign_exchange_market
+ // - \u20BD - Russian ruble.
+ // - \u20a9 - South Korean Won
+ // - \u20BA - Turkish Lira
+ // - \u20B9 - Indian Rupee
+ // - R - Brazil (R$) and South Africa
+ // - fr - Swiss Franc
+ // - kr - Swedish krona, Norwegian krone and Danish krone
+ // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
+ // standards as thousands separators.
+ var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
+
+
+ var _empty = function ( d ) {
+ return !d || d === true || d === '-' ? true : false;
+ };
+
+
+ var _intVal = function ( s ) {
+ var integer = parseInt( s, 10 );
+ return !isNaN(integer) && isFinite(s) ? integer : null;
+ };
+
+ // Convert from a formatted number with characters other than `.` as the
+ // decimal place, to a Javascript number
+ var _numToDecimal = function ( num, decimalPoint ) {
+ // Cache created regular expressions for speed as this function is called often
+ if ( ! _re_dic[ decimalPoint ] ) {
+ _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
+ }
+ return typeof num === 'string' && decimalPoint !== '.' ?
+ num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
+ num;
+ };
+
+
+ var _isNumber = function ( d, decimalPoint, formatted ) {
+ var strType = typeof d === 'string';
+
+ // If empty return immediately so there must be a number if it is a
+ // formatted string (this stops the string "k", or "kr", etc being detected
+ // as a formatted number for currency
+ if ( _empty( d ) ) {
+ return true;
+ }
+
+ if ( decimalPoint && strType ) {
+ d = _numToDecimal( d, decimalPoint );
+ }
+
+ if ( formatted && strType ) {
+ d = d.replace( _re_formatted_numeric, '' );
+ }
+
+ return !isNaN( parseFloat(d) ) && isFinite( d );
+ };
+
+
+ // A string without HTML in it can be considered to be HTML still
+ var _isHtml = function ( d ) {
+ return _empty( d ) || typeof d === 'string';
+ };
+
+
+ var _htmlNumeric = function ( d, decimalPoint, formatted ) {
+ if ( _empty( d ) ) {
+ return true;
+ }
+
+ var html = _isHtml( d );
+ return ! html ?
+ null :
+ _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
+ true :
+ null;
+ };
+
+
+ var _pluck = function ( a, prop, prop2 ) {
+ var out = [];
+ var i=0, ien=a.length;
+
+ // Could have the test in the loop for slightly smaller code, but speed
+ // is essential here
+ if ( prop2 !== undefined ) {
+ for ( ; i<ien ; i++ ) {
+ if ( a[i] && a[i][ prop ] ) {
+ out.push( a[i][ prop ][ prop2 ] );
+ }
+ }
+ }
+ else {
+ for ( ; i<ien ; i++ ) {
+ if ( a[i] ) {
+ out.push( a[i][ prop ] );
+ }
+ }
+ }
+
+ return out;
+ };
+
+
+ // Basically the same as _pluck, but rather than looping over `a` we use `order`
+ // as the indexes to pick from `a`
+ var _pluck_order = function ( a, order, prop, prop2 )
+ {
+ var out = [];
+ var i=0, ien=order.length;
+
+ // Could have the test in the loop for slightly smaller code, but speed
+ // is essential here
+ if ( prop2 !== undefined ) {
+ for ( ; i<ien ; i++ ) {
+ if ( a[ order[i] ][ prop ] ) {
+ out.push( a[ order[i] ][ prop ][ prop2 ] );
+ }
+ }
+ }
+ else {
+ for ( ; i<ien ; i++ ) {
+ out.push( a[ order[i] ][ prop ] );
+ }
+ }
+
+ return out;
+ };
+
+
+ var _range = function ( len, start )
+ {
+ var out = [];
+ var end;
+
+ if ( start === undefined ) {
+ start = 0;
+ end = len;
+ }
+ else {
+ end = start;
+ start = len;
+ }
+
+ for ( var i=start ; i<end ; i++ ) {
+ out.push( i );
+ }
+
+ return out;
+ };
+
+
+ var _removeEmpty = function ( a )
+ {
+ var out = [];
+
+ for ( var i=0, ien=a.length ; i<ien ; i++ ) {
+ if ( a[i] ) { // careful - will remove all falsy values!
+ out.push( a[i] );
+ }
+ }
+
+ return out;
+ };
+
+
+ var _stripHtml = function ( d ) {
+ return d.replace( _re_html, '' );
+ };
+
+
+ /**
+ * Determine if all values in the array are unique. This means we can short
+ * cut the _unique method at the cost of a single loop. A sorted array is used
+ * to easily check the values.
+ *
+ * @param {array} src Source array
+ * @return {boolean} true if all unique, false otherwise
+ * @ignore
+ */
+ var _areAllUnique = function ( src ) {
+ if ( src.length < 2 ) {
+ return true;
+ }
+
+ var sorted = src.slice().sort();
+ var last = sorted[0];
+
+ for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
+ if ( sorted[i] === last ) {
+ return false;
+ }
+
+ last = sorted[i];
+ }
+
+ return true;
+ };
+
+
+ /**
+ * Find the unique elements in a source array.
+ *
+ * @param {array} src Source array
+ * @return {array} Array of unique items
+ * @ignore
+ */
+ var _unique = function ( src )
+ {
+ if ( _areAllUnique( src ) ) {
+ return src.slice();
+ }
+
+ // A faster unique method is to use object keys to identify used values,
+ // but this doesn't work with arrays or objects, which we must also
+ // consider. See jsperf.com/compare-array-unique-versions/4 for more
+ // information.
+ var
+ out = [],
+ val,
+ i, ien=src.length,
+ j, k=0;
+
+ again: for ( i=0 ; i<ien ; i++ ) {
+ val = src[i];
+
+ for ( j=0 ; j<k ; j++ ) {
+ if ( out[j] === val ) {
+ continue again;
+ }
+ }
+
+ out.push( val );
+ k++;
+ }
+
+ return out;
+ };
+
+
+ /**
+ * DataTables utility methods
+ *
+ * This namespace provides helper methods that DataTables uses internally to
+ * create a DataTable, but which are not exclusively used only for DataTables.
+ * These methods can be used by extension authors to save the duplication of
+ * code.
+ *
+ * @namespace
+ */
+ DataTable.util = {
+ /**
+ * Throttle the calls to a function. Arguments and context are maintained
+ * for the throttled function.
+ *
+ * @param {function} fn Function to be called
+ * @param {integer} freq Call frequency in mS
+ * @return {function} Wrapped function
+ */
+ throttle: function ( fn, freq ) {
+ var
+ frequency = freq !== undefined ? freq : 200,
+ last,
+ timer;
+
+ return function () {
+ var
+ that = this,
+ now = +new Date(),
+ args = arguments;
+
+ if ( last && now < last + frequency ) {
+ clearTimeout( timer );
+
+ timer = setTimeout( function () {
+ last = undefined;
+ fn.apply( that, args );
+ }, frequency );
+ }
+ else {
+ last = now;
+ fn.apply( that, args );
+ }
+ };
+ },
+
+
+ /**
+ * Escape a string such that it can be used in a regular expression
+ *
+ * @param {string} val string to escape
+ * @returns {string} escaped string
+ */
+ escapeRegex: function ( val ) {
+ return val.replace( _re_escape_regex, '\\$1' );
+ }
+ };
+
+
+
+ /**
+ * Create a mapping object that allows camel case parameters to be looked up
+ * for their Hungarian counterparts. The mapping is stored in a private
+ * parameter called `_hungarianMap` which can be accessed on the source object.
+ * @param {object} o
+ * @memberof DataTable#oApi
+ */
+ function _fnHungarianMap ( o )
+ {
+ var
+ hungarian = 'a aa ai ao as b fn i m o s ',
+ match,
+ newKey,
+ map = {};
+
+ $.each( o, function (key, val) {
+ match = key.match(/^([^A-Z]+?)([A-Z])/);
+
+ if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
+ {
+ newKey = key.replace( match[0], match[2].toLowerCase() );
+ map[ newKey ] = key;
+
+ if ( match[1] === 'o' )
+ {
+ _fnHungarianMap( o[key] );
+ }
+ }
+ } );
+
+ o._hungarianMap = map;
+ }
+
+
+ /**
+ * Convert from camel case parameters to Hungarian, based on a Hungarian map
+ * created by _fnHungarianMap.
+ * @param {object} src The model object which holds all parameters that can be
+ * mapped.
+ * @param {object} user The object to convert from camel case to Hungarian.
+ * @param {boolean} force When set to `true`, properties which already have a
+ * Hungarian value in the `user` object will be overwritten. Otherwise they
+ * won't be.
+ * @memberof DataTable#oApi
+ */
+ function _fnCamelToHungarian ( src, user, force )
+ {
+ if ( ! src._hungarianMap ) {
+ _fnHungarianMap( src );
+ }
+
+ var hungarianKey;
+
+ $.each( user, function (key, val) {
+ hungarianKey = src._hungarianMap[ key ];
+
+ if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
+ {
+ // For objects, we need to buzz down into the object to copy parameters
+ if ( hungarianKey.charAt(0) === 'o' )
+ {
+ // Copy the camelCase options over to the hungarian
+ if ( ! user[ hungarianKey ] ) {
+ user[ hungarianKey ] = {};
+ }
+ $.extend( true, user[hungarianKey], user[key] );
+
+ _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
+ }
+ else {
+ user[hungarianKey] = user[ key ];
+ }
+ }
+ } );
+ }
+
+
+ /**
+ * Language compatibility - when certain options are given, and others aren't, we
+ * need to duplicate the values over, in order to provide backwards compatibility
+ * with older language files.
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnLanguageCompat( lang )
+ {
+ var defaults = DataTable.defaults.oLanguage;
+ var zeroRecords = lang.sZeroRecords;
+
+ /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
+ * sZeroRecords - assuming that is given.
+ */
+ if ( ! lang.sEmptyTable && zeroRecords &&
+ defaults.sEmptyTable === "No data available in table" )
+ {
+ _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
+ }
+
+ /* Likewise with loading records */
+ if ( ! lang.sLoadingRecords && zeroRecords &&
+ defaults.sLoadingRecords === "Loading..." )
+ {
+ _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
+ }
+
+ // Old parameter name of the thousands separator mapped onto the new
+ if ( lang.sInfoThousands ) {
+ lang.sThousands = lang.sInfoThousands;
+ }
+
+ var decimal = lang.sDecimal;
+ if ( decimal ) {
+ _addNumericSort( decimal );
+ }
+ }
+
+
+ /**
+ * Map one parameter onto another
+ * @param {object} o Object to map
+ * @param {*} knew The new parameter name
+ * @param {*} old The old parameter name
+ */
+ var _fnCompatMap = function ( o, knew, old ) {
+ if ( o[ knew ] !== undefined ) {
+ o[ old ] = o[ knew ];
+ }
+ };
+
+
+ /**
+ * Provide backwards compatibility for the main DT options. Note that the new
+ * options are mapped onto the old parameters, so this is an external interface
+ * change only.
+ * @param {object} init Object to map
+ */
+ function _fnCompatOpts ( init )
+ {
+ _fnCompatMap( init, 'ordering', 'bSort' );
+ _fnCompatMap( init, 'orderMulti', 'bSortMulti' );
+ _fnCompatMap( init, 'orderClasses', 'bSortClasses' );
+ _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
+ _fnCompatMap( init, 'order', 'aaSorting' );
+ _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' );
+ _fnCompatMap( init, 'paging', 'bPaginate' );
+ _fnCompatMap( init, 'pagingType', 'sPaginationType' );
+ _fnCompatMap( init, 'pageLength', 'iDisplayLength' );
+ _fnCompatMap( init, 'searching', 'bFilter' );
+
+ // Boolean initialisation of x-scrolling
+ if ( typeof init.sScrollX === 'boolean' ) {
+ init.sScrollX = init.sScrollX ? '100%' : '';
+ }
+ if ( typeof init.scrollX === 'boolean' ) {
+ init.scrollX = init.scrollX ? '100%' : '';
+ }
+
+ // Column search objects are in an array, so it needs to be converted
+ // element by element
+ var searchCols = init.aoSearchCols;
+
+ if ( searchCols ) {
+ for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
+ if ( searchCols[i] ) {
+ _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Provide backwards compatibility for column options. Note that the new options
+ * are mapped onto the old parameters, so this is an external interface change
+ * only.
+ * @param {object} init Object to map
+ */
+ function _fnCompatCols ( init )
+ {
+ _fnCompatMap( init, 'orderable', 'bSortable' );
+ _fnCompatMap( init, 'orderData', 'aDataSort' );
+ _fnCompatMap( init, 'orderSequence', 'asSorting' );
+ _fnCompatMap( init, 'orderDataType', 'sortDataType' );
+
+ // orderData can be given as an integer
+ var dataSort = init.aDataSort;
+ if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) {
+ init.aDataSort = [ dataSort ];
+ }
+ }
+
+
+ /**
+ * Browser feature detection for capabilities, quirks
+ * @param {object} settings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnBrowserDetect( settings )
+ {
+ // We don't need to do this every time DataTables is constructed, the values
+ // calculated are specific to the browser and OS configuration which we
+ // don't expect to change between initialisations
+ if ( ! DataTable.__browser ) {
+ var browser = {};
+ DataTable.__browser = browser;
+
+ // Scrolling feature / quirks detection
+ var n = $('<div/>')
+ .css( {
+ position: 'fixed',
+ top: 0,
+ left: $(window).scrollLeft()*-1, // allow for scrolling
+ height: 1,
+ width: 1,
+ overflow: 'hidden'
+ } )
+ .append(
+ $('<div/>')
+ .css( {
+ position: 'absolute',
+ top: 1,
+ left: 1,
+ width: 100,
+ overflow: 'scroll'
+ } )
+ .append(
+ $('<div/>')
+ .css( {
+ width: '100%',
+ height: 10
+ } )
+ )
+ )
+ .appendTo( 'body' );
+
+ var outer = n.children();
+ var inner = outer.children();
+
+ // Numbers below, in order, are:
+ // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
+ //
+ // IE6 XP: 100 100 100 83
+ // IE7 Vista: 100 100 100 83
+ // IE 8+ Windows: 83 83 100 83
+ // Evergreen Windows: 83 83 100 83
+ // Evergreen Mac with scrollbars: 85 85 100 85
+ // Evergreen Mac without scrollbars: 100 100 100 100
+
+ // Get scrollbar width
+ browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
+
+ // IE6/7 will oversize a width 100% element inside a scrolling element, to
+ // include the width of the scrollbar, while other browsers ensure the inner
+ // element is contained without forcing scrolling
+ browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
+
+ // In rtl text layout, some browsers (most, but not all) will place the
+ // scrollbar on the left, rather than the right.
+ browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
+
+ // IE8- don't provide height and width for getBoundingClientRect
+ browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
+
+ n.remove();
+ }
+
+ $.extend( settings.oBrowser, DataTable.__browser );
+ settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
+ }
+
+
+ /**
+ * Array.prototype reduce[Right] method, used for browsers which don't support
+ * JS 1.6. Done this way to reduce code size, since we iterate either way
+ * @param {object} settings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnReduce ( that, fn, init, start, end, inc )
+ {
+ var
+ i = start,
+ value,
+ isSet = false;
+
+ if ( init !== undefined ) {
+ value = init;
+ isSet = true;
+ }
+
+ while ( i !== end ) {
+ if ( ! that.hasOwnProperty(i) ) {
+ continue;
+ }
+
+ value = isSet ?
+ fn( value, that[i], i, that ) :
+ that[i];
+
+ isSet = true;
+ i += inc;
+ }
+
+ return value;
+ }
+
+ /**
+ * Add a column to the list used for the table with default values
+ * @param {object} oSettings dataTables settings object
+ * @param {node} nTh The th element for this column
+ * @memberof DataTable#oApi
+ */
+ function _fnAddColumn( oSettings, nTh )
+ {
+ // Add column to aoColumns array
+ var oDefaults = DataTable.defaults.column;
+ var iCol = oSettings.aoColumns.length;
+ var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
+ "nTh": nTh ? nTh : document.createElement('th'),
+ "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '',
+ "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
+ "mData": oDefaults.mData ? oDefaults.mData : iCol,
+ idx: iCol
+ } );
+ oSettings.aoColumns.push( oCol );
+
+ // Add search object for column specific search. Note that the `searchCols[ iCol ]`
+ // passed into extend can be undefined. This allows the user to give a default
+ // with only some of the parameters defined, and also not give a default
+ var searchCols = oSettings.aoPreSearchCols;
+ searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
+
+ // Use the default column options function to initialise classes etc
+ _fnColumnOptions( oSettings, iCol, $(nTh).data() );
+ }
+
+
+ /**
+ * Apply options for a column
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iCol column index to consider
+ * @param {object} oOptions object with sType, bVisible and bSearchable etc
+ * @memberof DataTable#oApi
+ */
+ function _fnColumnOptions( oSettings, iCol, oOptions )
+ {
+ var oCol = oSettings.aoColumns[ iCol ];
+ var oClasses = oSettings.oClasses;
+ var th = $(oCol.nTh);
+
+ // Try to get width information from the DOM. We can't get it from CSS
+ // as we'd need to parse the CSS stylesheet. `width` option can override
+ if ( ! oCol.sWidthOrig ) {
+ // Width attribute
+ oCol.sWidthOrig = th.attr('width') || null;
+
+ // Style attribute
+ var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
+ if ( t ) {
+ oCol.sWidthOrig = t[1];
+ }
+ }
+
+ /* User specified column options */
+ if ( oOptions !== undefined && oOptions !== null )
+ {
+ // Backwards compatibility
+ _fnCompatCols( oOptions );
+
+ // Map camel case parameters to their Hungarian counterparts
+ _fnCamelToHungarian( DataTable.defaults.column, oOptions );
+
+ /* Backwards compatibility for mDataProp */
+ if ( oOptions.mDataProp !== undefined && !oOptions.mData )
+ {
+ oOptions.mData = oOptions.mDataProp;
+ }
+
+ if ( oOptions.sType )
+ {
+ oCol._sManualType = oOptions.sType;
+ }
+
+ // `class` is a reserved word in Javascript, so we need to provide
+ // the ability to use a valid name for the camel case input
+ if ( oOptions.className && ! oOptions.sClass )
+ {
+ oOptions.sClass = oOptions.className;
+ }
+ if ( oOptions.sClass ) {
+ th.addClass( oOptions.sClass );
+ }
+
+ $.extend( oCol, oOptions );
+ _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
+
+ /* iDataSort to be applied (backwards compatibility), but aDataSort will take
+ * priority if defined
+ */
+ if ( oOptions.iDataSort !== undefined )
+ {
+ oCol.aDataSort = [ oOptions.iDataSort ];
+ }
+ _fnMap( oCol, oOptions, "aDataSort" );
+ }
+
+ /* Cache the data get and set functions for speed */
+ var mDataSrc = oCol.mData;
+ var mData = _fnGetObjectDataFn( mDataSrc );
+ var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
+
+ var attrTest = function( src ) {
+ return typeof src === 'string' && src.indexOf('@') !== -1;
+ };
+ oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
+ attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
+ );
+ oCol._setter = null;
+
+ oCol.fnGetData = function (rowData, type, meta) {
+ var innerData = mData( rowData, type, undefined, meta );
+
+ return mRender && type ?
+ mRender( innerData, type, rowData, meta ) :
+ innerData;
+ };
+ oCol.fnSetData = function ( rowData, val, meta ) {
+ return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
+ };
+
+ // Indicate if DataTables should read DOM data as an object or array
+ // Used in _fnGetRowElements
+ if ( typeof mDataSrc !== 'number' ) {
+ oSettings._rowReadObject = true;
+ }
+
+ /* Feature sorting overrides column specific when off */
+ if ( !oSettings.oFeatures.bSort )
+ {
+ oCol.bSortable = false;
+ th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
+ }
+
+ /* Check that the class assignment is correct for sorting */
+ var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
+ var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
+ if ( !oCol.bSortable || (!bAsc && !bDesc) )
+ {
+ oCol.sSortingClass = oClasses.sSortableNone;
+ oCol.sSortingClassJUI = "";
+ }
+ else if ( bAsc && !bDesc )
+ {
+ oCol.sSortingClass = oClasses.sSortableAsc;
+ oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
+ }
+ else if ( !bAsc && bDesc )
+ {
+ oCol.sSortingClass = oClasses.sSortableDesc;
+ oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
+ }
+ else
+ {
+ oCol.sSortingClass = oClasses.sSortable;
+ oCol.sSortingClassJUI = oClasses.sSortJUI;
+ }
+ }
+
+
+ /**
+ * Adjust the table column widths for new data. Note: you would probably want to
+ * do a redraw after calling this function!
+ * @param {object} settings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnAdjustColumnSizing ( settings )
+ {
+ /* Not interested in doing column width calculation if auto-width is disabled */
+ if ( settings.oFeatures.bAutoWidth !== false )
+ {
+ var columns = settings.aoColumns;
+
+ _fnCalculateColumnWidths( settings );
+ for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
+ {
+ columns[i].nTh.style.width = columns[i].sWidth;
+ }
+ }
+
+ var scroll = settings.oScroll;
+ if ( scroll.sY !== '' || scroll.sX !== '')
+ {
+ _fnScrollDraw( settings );
+ }
+
+ _fnCallbackFire( settings, null, 'column-sizing', [settings] );
+ }
+
+
+ /**
+ * Covert the index of a visible column to the index in the data array (take account
+ * of hidden columns)
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iMatch Visible column index to lookup
+ * @returns {int} i the data index
+ * @memberof DataTable#oApi
+ */
+ function _fnVisibleToColumnIndex( oSettings, iMatch )
+ {
+ var aiVis = _fnGetColumns( oSettings, 'bVisible' );
+
+ return typeof aiVis[iMatch] === 'number' ?
+ aiVis[iMatch] :
+ null;
+ }
+
+
+ /**
+ * Covert the index of an index in the data array and convert it to the visible
+ * column index (take account of hidden columns)
+ * @param {int} iMatch Column index to lookup
+ * @param {object} oSettings dataTables settings object
+ * @returns {int} i the data index
+ * @memberof DataTable#oApi
+ */
+ function _fnColumnIndexToVisible( oSettings, iMatch )
+ {
+ var aiVis = _fnGetColumns( oSettings, 'bVisible' );
+ var iPos = $.inArray( iMatch, aiVis );
+
+ return iPos !== -1 ? iPos : null;
+ }
+
+
+ /**
+ * Get the number of visible columns
+ * @param {object} oSettings dataTables settings object
+ * @returns {int} i the number of visible columns
+ * @memberof DataTable#oApi
+ */
+ function _fnVisbleColumns( oSettings )
+ {
+ var vis = 0;
+
+ // No reduce in IE8, use a loop for now
+ $.each( oSettings.aoColumns, function ( i, col ) {
+ if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
+ vis++;
+ }
+ } );
+
+ return vis;
+ }
+
+
+ /**
+ * Get an array of column indexes that match a given property
+ * @param {object} oSettings dataTables settings object
+ * @param {string} sParam Parameter in aoColumns to look for - typically
+ * bVisible or bSearchable
+ * @returns {array} Array of indexes with matched properties
+ * @memberof DataTable#oApi
+ */
+ function _fnGetColumns( oSettings, sParam )
+ {
+ var a = [];
+
+ $.map( oSettings.aoColumns, function(val, i) {
+ if ( val[sParam] ) {
+ a.push( i );
+ }
+ } );
+
+ return a;
+ }
+
+
+ /**
+ * Calculate the 'type' of a column
+ * @param {object} settings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnColumnTypes ( settings )
+ {
+ var columns = settings.aoColumns;
+ var data = settings.aoData;
+ var types = DataTable.ext.type.detect;
+ var i, ien, j, jen, k, ken;
+ var col, cell, detectedType, cache;
+
+ // For each column, spin over the
+ for ( i=0, ien=columns.length ; i<ien ; i++ ) {
+ col = columns[i];
+ cache = [];
+
+ if ( ! col.sType && col._sManualType ) {
+ col.sType = col._sManualType;
+ }
+ else if ( ! col.sType ) {
+ for ( j=0, jen=types.length ; j<jen ; j++ ) {
+ for ( k=0, ken=data.length ; k<ken ; k++ ) {
+ // Use a cache array so we only need to get the type data
+ // from the formatter once (when using multiple detectors)
+ if ( cache[k] === undefined ) {
+ cache[k] = _fnGetCellData( settings, k, i, 'type' );
+ }
+
+ detectedType = types[j]( cache[k], settings );
+
+ // If null, then this type can't apply to this column, so
+ // rather than testing all cells, break out. There is an
+ // exception for the last type which is `html`. We need to
+ // scan all rows since it is possible to mix string and HTML
+ // types
+ if ( ! detectedType && j !== types.length-1 ) {
+ break;
+ }
+
+ // Only a single match is needed for html type since it is
+ // bottom of the pile and very similar to string
+ if ( detectedType === 'html' ) {
+ break;
+ }
+ }
+
+ // Type is valid for all data points in the column - use this
+ // type
+ if ( detectedType ) {
+ col.sType = detectedType;
+ break;
+ }
+ }
+
+ // Fall back - if no type was detected, always use string
+ if ( ! col.sType ) {
+ col.sType = 'string';
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Take the column definitions and static columns arrays and calculate how
+ * they relate to column indexes. The callback function will then apply the
+ * definition found for a column to a suitable configuration object.
+ * @param {object} oSettings dataTables settings object
+ * @param {array} aoColDefs The aoColumnDefs array that is to be applied
+ * @param {array} aoCols The aoColumns array that defines columns individually
+ * @param {function} fn Callback function - takes two parameters, the calculated
+ * column index and the definition for that column.
+ * @memberof DataTable#oApi
+ */
+ function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
+ {
+ var i, iLen, j, jLen, k, kLen, def;
+ var columns = oSettings.aoColumns;
+
+ // Column definitions with aTargets
+ if ( aoColDefs )
+ {
+ /* Loop over the definitions array - loop in reverse so first instance has priority */
+ for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
+ {
+ def = aoColDefs[i];
+
+ /* Each definition can target multiple columns, as it is an array */
+ var aTargets = def.targets !== undefined ?
+ def.targets :
+ def.aTargets;
+
+ if ( ! $.isArray( aTargets ) )
+ {
+ aTargets = [ aTargets ];
+ }
+
+ for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
+ {
+ if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
+ {
+ /* Add columns that we don't yet know about */
+ while( columns.length <= aTargets[j] )
+ {
+ _fnAddColumn( oSettings );
+ }
+
+ /* Integer, basic index */
+ fn( aTargets[j], def );
+ }
+ else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
+ {
+ /* Negative integer, right to left column counting */
+ fn( columns.length+aTargets[j], def );
+ }
+ else if ( typeof aTargets[j] === 'string' )
+ {
+ /* Class name matching on TH element */
+ for ( k=0, kLen=columns.length ; k<kLen ; k++ )
+ {
+ if ( aTargets[j] == "_all" ||
+ $(columns[k].nTh).hasClass( aTargets[j] ) )
+ {
+ fn( k, def );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Statically defined columns array
+ if ( aoCols )
+ {
+ for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
+ {
+ fn( i, aoCols[i] );
+ }
+ }
+ }
+
+ /**
+ * Add a data array to the table, creating DOM node etc. This is the parallel to
+ * _fnGatherData, but for adding rows from a Javascript source, rather than a
+ * DOM source.
+ * @param {object} oSettings dataTables settings object
+ * @param {array} aData data array to be added
+ * @param {node} [nTr] TR element to add to the table - optional. If not given,
+ * DataTables will create a row automatically
+ * @param {array} [anTds] Array of TD|TH elements for the row - must be given
+ * if nTr is.
+ * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
+ * @memberof DataTable#oApi
+ */
+ function _fnAddData ( oSettings, aDataIn, nTr, anTds )
+ {
+ /* Create the object for storing information about this new row */
+ var iRow = oSettings.aoData.length;
+ var oData = $.extend( true, {}, DataTable.models.oRow, {
+ src: nTr ? 'dom' : 'data',
+ idx: iRow
+ } );
+
+ oData._aData = aDataIn;
+ oSettings.aoData.push( oData );
+
+ /* Create the cells */
+ var nTd, sThisType;
+ var columns = oSettings.aoColumns;
+
+ // Invalidate the column types as the new data needs to be revalidated
+ for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
+ {
+ columns[i].sType = null;
+ }
+
+ /* Add to the display array */
+ oSettings.aiDisplayMaster.push( iRow );
+
+ var id = oSettings.rowIdFn( aDataIn );
+ if ( id !== undefined ) {
+ oSettings.aIds[ id ] = oData;
+ }
+
+ /* Create the DOM information, or register it if already present */
+ if ( nTr || ! oSettings.oFeatures.bDeferRender )
+ {
+ _fnCreateTr( oSettings, iRow, nTr, anTds );
+ }
+
+ return iRow;
+ }
+
+
+ /**
+ * Add one or more TR elements to the table. Generally we'd expect to
+ * use this for reading data from a DOM sourced table, but it could be
+ * used for an TR element. Note that if a TR is given, it is used (i.e.
+ * it is not cloned).
+ * @param {object} settings dataTables settings object
+ * @param {array|node|jQuery} trs The TR element(s) to add to the table
+ * @returns {array} Array of indexes for the added rows
+ * @memberof DataTable#oApi
+ */
+ function _fnAddTr( settings, trs )
+ {
+ var row;
+
+ // Allow an individual node to be passed in
+ if ( ! (trs instanceof $) ) {
+ trs = $(trs);
+ }
+
+ return trs.map( function (i, el) {
+ row = _fnGetRowElements( settings, el );
+ return _fnAddData( settings, row.data, el, row.cells );
+ } );
+ }
+
+
+ /**
+ * Take a TR element and convert it to an index in aoData
+ * @param {object} oSettings dataTables settings object
+ * @param {node} n the TR element to find
+ * @returns {int} index if the node is found, null if not
+ * @memberof DataTable#oApi
+ */
+ function _fnNodeToDataIndex( oSettings, n )
+ {
+ return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
+ }
+
+
+ /**
+ * Take a TD element and convert it into a column data index (not the visible index)
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iRow The row number the TD/TH can be found in
+ * @param {node} n The TD/TH element to find
+ * @returns {int} index if the node is found, -1 if not
+ * @memberof DataTable#oApi
+ */
+ function _fnNodeToColumnIndex( oSettings, iRow, n )
+ {
+ return $.inArray( n, oSettings.aoData[ iRow ].anCells );
+ }
+
+
+ /**
+ * Get the data for a given cell from the internal cache, taking into account data mapping
+ * @param {object} settings dataTables settings object
+ * @param {int} rowIdx aoData row id
+ * @param {int} colIdx Column index
+ * @param {string} type data get type ('display', 'type' 'filter' 'sort')
+ * @returns {*} Cell data
+ * @memberof DataTable#oApi
+ */
+ function _fnGetCellData( settings, rowIdx, colIdx, type )
+ {
+ var draw = settings.iDraw;
+ var col = settings.aoColumns[colIdx];
+ var rowData = settings.aoData[rowIdx]._aData;
+ var defaultContent = col.sDefaultContent;
+ var cellData = col.fnGetData( rowData, type, {
+ settings: settings,
+ row: rowIdx,
+ col: colIdx
+ } );
+
+ if ( cellData === undefined ) {
+ if ( settings.iDrawError != draw && defaultContent === null ) {
+ _fnLog( settings, 0, "Requested unknown parameter "+
+ (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
+ " for row "+rowIdx+", column "+colIdx, 4 );
+ settings.iDrawError = draw;
+ }
+ return defaultContent;
+ }
+
+ // When the data source is null and a specific data type is requested (i.e.
+ // not the original data), we can use default column data
+ if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
+ cellData = defaultContent;
+ }
+ else if ( typeof cellData === 'function' ) {
+ // If the data source is a function, then we run it and use the return,
+ // executing in the scope of the data object (for instances)
+ return cellData.call( rowData );
+ }
+
+ if ( cellData === null && type == 'display' ) {
+ return '';
+ }
+ return cellData;
+ }
+
+
+ /**
+ * Set the value for a specific cell, into the internal data cache
+ * @param {object} settings dataTables settings object
+ * @param {int} rowIdx aoData row id
+ * @param {int} colIdx Column index
+ * @param {*} val Value to set
+ * @memberof DataTable#oApi
+ */
+ function _fnSetCellData( settings, rowIdx, colIdx, val )
+ {
+ var col = settings.aoColumns[colIdx];
+ var rowData = settings.aoData[rowIdx]._aData;
+
+ col.fnSetData( rowData, val, {
+ settings: settings,
+ row: rowIdx,
+ col: colIdx
+ } );
+ }
+
+
+ // Private variable that is used to match action syntax in the data property object
+ var __reArray = /\[.*?\]$/;
+ var __reFn = /\(\)$/;
+
+ /**
+ * Split string on periods, taking into account escaped periods
+ * @param {string} str String to split
+ * @return {array} Split string
+ */
+ function _fnSplitObjNotation( str )
+ {
+ return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
+ return s.replace(/\\\./g, '.');
+ } );
+ }
+
+
+ /**
+ * Return a function that can be used to get data from a source object, taking
+ * into account the ability to use nested objects as a source
+ * @param {string|int|function} mSource The data source for the object
+ * @returns {function} Data get function
+ * @memberof DataTable#oApi
+ */
+ function _fnGetObjectDataFn( mSource )
+ {
+ if ( $.isPlainObject( mSource ) )
+ {
+ /* Build an object of get functions, and wrap them in a single call */
+ var o = {};
+ $.each( mSource, function (key, val) {
+ if ( val ) {
+ o[key] = _fnGetObjectDataFn( val );
+ }
+ } );
+
+ return function (data, type, row, meta) {
+ var t = o[type] || o._;
+ return t !== undefined ?
+ t(data, type, row, meta) :
+ data;
+ };
+ }
+ else if ( mSource === null )
+ {
+ /* Give an empty string for rendering / sorting etc */
+ return function (data) { // type, row and meta also passed, but not used
+ return data;
+ };
+ }
+ else if ( typeof mSource === 'function' )
+ {
+ return function (data, type, row, meta) {
+ return mSource( data, type, row, meta );
+ };
+ }
+ else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
+ mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
+ {
+ /* If there is a . in the source string then the data source is in a
+ * nested object so we loop over the data for each level to get the next
+ * level down. On each loop we test for undefined, and if found immediately
+ * return. This allows entire objects to be missing and sDefaultContent to
+ * be used if defined, rather than throwing an error
+ */
+ var fetchData = function (data, type, src) {
+ var arrayNotation, funcNotation, out, innerSrc;
+
+ if ( src !== "" )
+ {
+ var a = _fnSplitObjNotation( src );
+
+ for ( var i=0, iLen=a.length ; i<iLen ; i++ )
+ {
+ // Check if we are dealing with special notation
+ arrayNotation = a[i].match(__reArray);
+ funcNotation = a[i].match(__reFn);
+
+ if ( arrayNotation )
+ {
+ // Array notation
+ a[i] = a[i].replace(__reArray, '');
+
+ // Condition allows simply [] to be passed in
+ if ( a[i] !== "" ) {
+ data = data[ a[i] ];
+ }
+ out = [];
+
+ // Get the remainder of the nested object to get
+ a.splice( 0, i+1 );
+ innerSrc = a.join('.');
+
+ // Traverse each entry in the array getting the properties requested
+ if ( $.isArray( data ) ) {
+ for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
+ out.push( fetchData( data[j], type, innerSrc ) );
+ }
+ }
+
+ // If a string is given in between the array notation indicators, that
+ // is used to join the strings together, otherwise an array is returned
+ var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
+ data = (join==="") ? out : out.join(join);
+
+ // The inner call to fetchData has already traversed through the remainder
+ // of the source requested, so we exit from the loop
+ break;
+ }
+ else if ( funcNotation )
+ {
+ // Function call
+ a[i] = a[i].replace(__reFn, '');
+ data = data[ a[i] ]();
+ continue;
+ }
+
+ if ( data === null || data[ a[i] ] === undefined )
+ {
+ return undefined;
+ }
+ data = data[ a[i] ];
+ }
+ }
+
+ return data;
+ };
+
+ return function (data, type) { // row and meta also passed, but not used
+ return fetchData( data, type, mSource );
+ };
+ }
+ else
+ {
+ /* Array or flat object mapping */
+ return function (data, type) { // row and meta also passed, but not used
+ return data[mSource];
+ };
+ }
+ }
+
+
+ /**
+ * Return a function that can be used to set data from a source object, taking
+ * into account the ability to use nested objects as a source
+ * @param {string|int|function} mSource The data source for the object
+ * @returns {function} Data set function
+ * @memberof DataTable#oApi
+ */
+ function _fnSetObjectDataFn( mSource )
+ {
+ if ( $.isPlainObject( mSource ) )
+ {
+ /* Unlike get, only the underscore (global) option is used for for
+ * setting data since we don't know the type here. This is why an object
+ * option is not documented for `mData` (which is read/write), but it is
+ * for `mRender` which is read only.
+ */
+ return _fnSetObjectDataFn( mSource._ );
+ }
+ else if ( mSource === null )
+ {
+ /* Nothing to do when the data source is null */
+ return function () {};
+ }
+ else if ( typeof mSource === 'function' )
+ {
+ return function (data, val, meta) {
+ mSource( data, 'set', val, meta );
+ };
+ }
+ else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
+ mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
+ {
+ /* Like the get, we need to get data from a nested object */
+ var setData = function (data, val, src) {
+ var a = _fnSplitObjNotation( src ), b;
+ var aLast = a[a.length-1];
+ var arrayNotation, funcNotation, o, innerSrc;
+
+ for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
+ {
+ // Check if we are dealing with an array notation request
+ arrayNotation = a[i].match(__reArray);
+ funcNotation = a[i].match(__reFn);
+
+ if ( arrayNotation )
+ {
+ a[i] = a[i].replace(__reArray, '');
+ data[ a[i] ] = [];
+
+ // Get the remainder of the nested object to set so we can recurse
+ b = a.slice();
+ b.splice( 0, i+1 );
+ innerSrc = b.join('.');
+
+ // Traverse each entry in the array setting the properties requested
+ if ( $.isArray( val ) )
+ {
+ for ( var j=0, jLen=val.length ; j<jLen ; j++ )
+ {
+ o = {};
+ setData( o, val[j], innerSrc );
+ data[ a[i] ].push( o );
+ }
+ }
+ else
+ {
+ // We've been asked to save data to an array, but it
+ // isn't array data to be saved. Best that can be done
+ // is to just save the value.
+ data[ a[i] ] = val;
+ }
+
+ // The inner call to setData has already traversed through the remainder
+ // of the source and has set the data, thus we can exit here
+ return;
+ }
+ else if ( funcNotation )
+ {
+ // Function call
+ a[i] = a[i].replace(__reFn, '');
+ data = data[ a[i] ]( val );
+ }
+
+ // If the nested object doesn't currently exist - since we are
+ // trying to set the value - create it
+ if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
+ {
+ data[ a[i] ] = {};
+ }
+ data = data[ a[i] ];
+ }
+
+ // Last item in the input - i.e, the actual set
+ if ( aLast.match(__reFn ) )
+ {
+ // Function call
+ data = data[ aLast.replace(__reFn, '') ]( val );
+ }
+ else
+ {
+ // If array notation is used, we just want to strip it and use the property name
+ // and assign the value. If it isn't used, then we get the result we want anyway
+ data[ aLast.replace(__reArray, '') ] = val;
+ }
+ };
+
+ return function (data, val) { // meta is also passed in, but not used
+ return setData( data, val, mSource );
+ };
+ }
+ else
+ {
+ /* Array or flat object mapping */
+ return function (data, val) { // meta is also passed in, but not used
+ data[mSource] = val;
+ };
+ }
+ }
+
+
+ /**
+ * Return an array with the full table data
+ * @param {object} oSettings dataTables settings object
+ * @returns array {array} aData Master data array
+ * @memberof DataTable#oApi
+ */
+ function _fnGetDataMaster ( settings )
+ {
+ return _pluck( settings.aoData, '_aData' );
+ }
+
+
+ /**
+ * Nuke the table
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnClearTable( settings )
+ {
+ settings.aoData.length = 0;
+ settings.aiDisplayMaster.length = 0;
+ settings.aiDisplay.length = 0;
+ settings.aIds = {};
+ }
+
+
+ /**
+ * Take an array of integers (index array) and remove a target integer (value - not
+ * the key!)
+ * @param {array} a Index array to target
+ * @param {int} iTarget value to find
+ * @memberof DataTable#oApi
+ */
+ function _fnDeleteIndex( a, iTarget, splice )
+ {
+ var iTargetIndex = -1;
+
+ for ( var i=0, iLen=a.length ; i<iLen ; i++ )
+ {
+ if ( a[i] == iTarget )
+ {
+ iTargetIndex = i;
+ }
+ else if ( a[i] > iTarget )
+ {
+ a[i]--;
+ }
+ }
+
+ if ( iTargetIndex != -1 && splice === undefined )
+ {
+ a.splice( iTargetIndex, 1 );
+ }
+ }
+
+
+ /**
+ * Mark cached data as invalid such that a re-read of the data will occur when
+ * the cached data is next requested. Also update from the data source object.
+ *
+ * @param {object} settings DataTables settings object
+ * @param {int} rowIdx Row index to invalidate
+ * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom'
+ * or 'data'
+ * @param {int} [colIdx] Column index to invalidate. If undefined the whole
+ * row will be invalidated
+ * @memberof DataTable#oApi
+ *
+ * @todo For the modularisation of v1.11 this will need to become a callback, so
+ * the sort and filter methods can subscribe to it. That will required
+ * initialisation options for sorting, which is why it is not already baked in
+ */
+ function _fnInvalidate( settings, rowIdx, src, colIdx )
+ {
+ var row = settings.aoData[ rowIdx ];
+ var i, ien;
+ var cellWrite = function ( cell, col ) {
+ // This is very frustrating, but in IE if you just write directly
+ // to innerHTML, and elements that are overwritten are GC'ed,
+ // even if there is a reference to them elsewhere
+ while ( cell.childNodes.length ) {
+ cell.removeChild( cell.firstChild );
+ }
+
+ cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
+ };
+
+ // Are we reading last data from DOM or the data object?
+ if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
+ // Read the data from the DOM
+ row._aData = _fnGetRowElements(
+ settings, row, colIdx, colIdx === undefined ? undefined : row._aData
+ )
+ .data;
+ }
+ else {
+ // Reading from data object, update the DOM
+ var cells = row.anCells;
+
+ if ( cells ) {
+ if ( colIdx !== undefined ) {
+ cellWrite( cells[colIdx], colIdx );
+ }
+ else {
+ for ( i=0, ien=cells.length ; i<ien ; i++ ) {
+ cellWrite( cells[i], i );
+ }
+ }
+ }
+ }
+
+ // For both row and cell invalidation, the cached data for sorting and
+ // filtering is nulled out
+ row._aSortData = null;
+ row._aFilterData = null;
+
+ // Invalidate the type for a specific column (if given) or all columns since
+ // the data might have changed
+ var cols = settings.aoColumns;
+ if ( colIdx !== undefined ) {
+ cols[ colIdx ].sType = null;
+ }
+ else {
+ for ( i=0, ien=cols.length ; i<ien ; i++ ) {
+ cols[i].sType = null;
+ }
+
+ // Update DataTables special `DT_*` attributes for the row
+ _fnRowAttributes( settings, row );
+ }
+ }
+
+
+ /**
+ * Build a data source object from an HTML row, reading the contents of the
+ * cells that are in the row.
+ *
+ * @param {object} settings DataTables settings object
+ * @param {node|object} TR element from which to read data or existing row
+ * object from which to re-read the data from the cells
+ * @param {int} [colIdx] Optional column index
+ * @param {array|object} [d] Data source object. If `colIdx` is given then this
+ * parameter should also be given and will be used to write the data into.
+ * Only the column in question will be written
+ * @returns {object} Object with two parameters: `data` the data read, in
+ * document order, and `cells` and array of nodes (they can be useful to the
+ * caller, so rather than needing a second traversal to get them, just return
+ * them from here).
+ * @memberof DataTable#oApi
+ */
+ function _fnGetRowElements( settings, row, colIdx, d )
+ {
+ var
+ tds = [],
+ td = row.firstChild,
+ name, col, o, i=0, contents,
+ columns = settings.aoColumns,
+ objectRead = settings._rowReadObject;
+
+ // Allow the data object to be passed in, or construct
+ d = d !== undefined ?
+ d :
+ objectRead ?
+ {} :
+ [];
+
+ var attr = function ( str, td ) {
+ if ( typeof str === 'string' ) {
+ var idx = str.indexOf('@');
+
+ if ( idx !== -1 ) {
+ var attr = str.substring( idx+1 );
+ var setter = _fnSetObjectDataFn( str );
+ setter( d, td.getAttribute( attr ) );
+ }
+ }
+ };
+
+ // Read data from a cell and store into the data object
+ var cellProcess = function ( cell ) {
+ if ( colIdx === undefined || colIdx === i ) {
+ col = columns[i];
+ contents = $.trim(cell.innerHTML);
+
+ if ( col && col._bAttrSrc ) {
+ var setter = _fnSetObjectDataFn( col.mData._ );
+ setter( d, contents );
+
+ attr( col.mData.sort, cell );
+ attr( col.mData.type, cell );
+ attr( col.mData.filter, cell );
+ }
+ else {
+ // Depending on the `data` option for the columns the data can
+ // be read to either an object or an array.
+ if ( objectRead ) {
+ if ( ! col._setter ) {
+ // Cache the setter function
+ col._setter = _fnSetObjectDataFn( col.mData );
+ }
+ col._setter( d, contents );
+ }
+ else {
+ d[i] = contents;
+ }
+ }
+ }
+
+ i++;
+ };
+
+ if ( td ) {
+ // `tr` element was passed in
+ while ( td ) {
+ name = td.nodeName.toUpperCase();
+
+ if ( name == "TD" || name == "TH" ) {
+ cellProcess( td );
+ tds.push( td );
+ }
+
+ td = td.nextSibling;
+ }
+ }
+ else {
+ // Existing row object passed in
+ tds = row.anCells;
+
+ for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
+ cellProcess( tds[j] );
+ }
+ }
+
+ // Read the ID from the DOM if present
+ var rowNode = row.firstChild ? row : row.nTr;
+
+ if ( rowNode ) {
+ var id = rowNode.getAttribute( 'id' );
+
+ if ( id ) {
+ _fnSetObjectDataFn( settings.rowId )( d, id );
+ }
+ }
+
+ return {
+ data: d,
+ cells: tds
+ };
+ }
+ /**
+ * Create a new TR element (and it's TD children) for a row
+ * @param {object} oSettings dataTables settings object
+ * @param {int} iRow Row to consider
+ * @param {node} [nTrIn] TR element to add to the table - optional. If not given,
+ * DataTables will create a row automatically
+ * @param {array} [anTds] Array of TD|TH elements for the row - must be given
+ * if nTr is.
+ * @memberof DataTable#oApi
+ */
+ function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
+ {
+ var
+ row = oSettings.aoData[iRow],
+ rowData = row._aData,
+ cells = [],
+ nTr, nTd, oCol,
+ i, iLen;
+
+ if ( row.nTr === null )
+ {
+ nTr = nTrIn || document.createElement('tr');
+
+ row.nTr = nTr;
+ row.anCells = cells;
+
+ /* Use a private property on the node to allow reserve mapping from the node
+ * to the aoData array for fast look up
+ */
+ nTr._DT_RowIndex = iRow;
+
+ /* Special parameters can be given by the data source to be used on the row */
+ _fnRowAttributes( oSettings, row );
+
+ /* Process each column */
+ for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
+ {
+ oCol = oSettings.aoColumns[i];
+
+ nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
+ nTd._DT_CellIndex = {
+ row: iRow,
+ column: i
+ };
+
+ cells.push( nTd );
+
+ // Need to create the HTML if new, or if a rendering function is defined
+ if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
+ (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
+ ) {
+ nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
+ }
+
+ /* Add user defined class */
+ if ( oCol.sClass )
+ {
+ nTd.className += ' '+oCol.sClass;
+ }
+
+ // Visibility - add or remove as required
+ if ( oCol.bVisible && ! nTrIn )
+ {
+ nTr.appendChild( nTd );
+ }
+ else if ( ! oCol.bVisible && nTrIn )
+ {
+ nTd.parentNode.removeChild( nTd );
+ }
+
+ if ( oCol.fnCreatedCell )
+ {
+ oCol.fnCreatedCell.call( oSettings.oInstance,
+ nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
+ );
+ }
+ }
+
+ _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
+ }
+
+ // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
+ // and deployed
+ row.nTr.setAttribute( 'role', 'row' );
+ }
+
+
+ /**
+ * Add attributes to a row based on the special `DT_*` parameters in a data
+ * source object.
+ * @param {object} settings DataTables settings object
+ * @param {object} DataTables row object for the row to be modified
+ * @memberof DataTable#oApi
+ */
+ function _fnRowAttributes( settings, row )
+ {
+ var tr = row.nTr;
+ var data = row._aData;
+
+ if ( tr ) {
+ var id = settings.rowIdFn( data );
+
+ if ( id ) {
+ tr.id = id;
+ }
+
+ if ( data.DT_RowClass ) {
+ // Remove any classes added by DT_RowClass before
+ var a = data.DT_RowClass.split(' ');
+ row.__rowc = row.__rowc ?
+ _unique( row.__rowc.concat( a ) ) :
+ a;
+
+ $(tr)
+ .removeClass( row.__rowc.join(' ') )
+ .addClass( data.DT_RowClass );
+ }
+
+ if ( data.DT_RowAttr ) {
+ $(tr).attr( data.DT_RowAttr );
+ }
+
+ if ( data.DT_RowData ) {
+ $(tr).data( data.DT_RowData );
+ }
+ }
+ }
+
+
+ /**
+ * Create the HTML header for the table
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnBuildHead( oSettings )
+ {
+ var i, ien, cell, row, column;
+ var thead = oSettings.nTHead;
+ var tfoot = oSettings.nTFoot;
+ var createHeader = $('th, td', thead).length === 0;
+ var classes = oSettings.oClasses;
+ var columns = oSettings.aoColumns;
+
+ if ( createHeader ) {
+ row = $('<tr/>').appendTo( thead );
+ }
+
+ for ( i=0, ien=columns.length ; i<ien ; i++ ) {
+ column = columns[i];
+ cell = $( column.nTh ).addClass( column.sClass );
+
+ if ( createHeader ) {
+ cell.appendTo( row );
+ }
+
+ // 1.11 move into sorting
+ if ( oSettings.oFeatures.bSort ) {
+ cell.addClass( column.sSortingClass );
+
+ if ( column.bSortable !== false ) {
+ cell
+ .attr( 'tabindex', oSettings.iTabIndex )
+ .attr( 'aria-controls', oSettings.sTableId );
+
+ _fnSortAttachListener( oSettings, column.nTh, i );
+ }
+ }
+
+ if ( column.sTitle != cell[0].innerHTML ) {
+ cell.html( column.sTitle );
+ }
+
+ _fnRenderer( oSettings, 'header' )(
+ oSettings, cell, column, classes
+ );
+ }
+
+ if ( createHeader ) {
+ _fnDetectHeader( oSettings.aoHeader, thead );
+ }
+
+ /* ARIA role for the rows */
+ $(thead).find('>tr').attr('role', 'row');
+
+ /* Deal with the footer - add classes if required */
+ $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
+ $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
+
+ // Cache the footer cells. Note that we only take the cells from the first
+ // row in the footer. If there is more than one row the user wants to
+ // interact with, they need to use the table().foot() method. Note also this
+ // allows cells to be used for multiple columns using colspan
+ if ( tfoot !== null ) {
+ var cells = oSettings.aoFooter[0];
+
+ for ( i=0, ien=cells.length ; i<ien ; i++ ) {
+ column = columns[i];
+ column.nTf = cells[i].cell;
+
+ if ( column.sClass ) {
+ $(column.nTf).addClass( column.sClass );
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Draw the header (or footer) element based on the column visibility states. The
+ * methodology here is to use the layout array from _fnDetectHeader, modified for
+ * the instantaneous column visibility, to construct the new layout. The grid is
+ * traversed over cell at a time in a rows x columns grid fashion, although each
+ * cell insert can cover multiple elements in the grid - which is tracks using the
+ * aApplied array. Cell inserts in the grid will only occur where there isn't
+ * already a cell in that position.
+ * @param {object} oSettings dataTables settings object
+ * @param array {objects} aoSource Layout array from _fnDetectHeader
+ * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
+ * @memberof DataTable#oApi
+ */
+ function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
+ {
+ var i, iLen, j, jLen, k, kLen, n, nLocalTr;
+ var aoLocal = [];
+ var aApplied = [];
+ var iColumns = oSettings.aoColumns.length;
+ var iRowspan, iColspan;
+
+ if ( ! aoSource )
+ {
+ return;
+ }
+
+ if ( bIncludeHidden === undefined )
+ {
+ bIncludeHidden = false;
+ }
+
+ /* Make a copy of the master layout array, but without the visible columns in it */
+ for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
+ {
+ aoLocal[i] = aoSource[i].slice();
+ aoLocal[i].nTr = aoSource[i].nTr;
+
+ /* Remove any columns which are currently hidden */
+ for ( j=iColumns-1 ; j>=0 ; j-- )
+ {
+ if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
+ {
+ aoLocal[i].splice( j, 1 );
+ }
+ }
+
+ /* Prep the applied array - it needs an element for each row */
+ aApplied.push( [] );
+ }
+
+ for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
+ {
+ nLocalTr = aoLocal[i].nTr;
+
+ /* All cells are going to be replaced, so empty out the row */
+ if ( nLocalTr )
+ {
+ while( (n = nLocalTr.firstChild) )
+ {
+ nLocalTr.removeChild( n );
+ }
+ }
+
+ for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
+ {
+ iRowspan = 1;
+ iColspan = 1;
+
+ /* Check to see if there is already a cell (row/colspan) covering our target
+ * insert point. If there is, then there is nothing to do.
+ */
+ if ( aApplied[i][j] === undefined )
+ {
+ nLocalTr.appendChild( aoLocal[i][j].cell );
+ aApplied[i][j] = 1;
+
+ /* Expand the cell to cover as many rows as needed */
+ while ( aoLocal[i+iRowspan] !== undefined &&
+ aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
+ {
+ aApplied[i+iRowspan][j] = 1;
+ iRowspan++;
+ }
+
+ /* Expand the cell to cover as many columns as needed */
+ while ( aoLocal[i][j+iColspan] !== undefined &&
+ aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
+ {
+ /* Must update the applied array over the rows for the columns */
+ for ( k=0 ; k<iRowspan ; k++ )
+ {
+ aApplied[i+k][j+iColspan] = 1;
+ }
+ iColspan++;
+ }
+
+ /* Do the actual expansion in the DOM */
+ $(aoLocal[i][j].cell)
+ .attr('rowspan', iRowspan)
+ .attr('colspan', iColspan);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Insert the required TR nodes into the table for display
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnDraw( oSettings )
+ {
+ /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
+ var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
+ if ( $.inArray( false, aPreDraw ) !== -1 )
+ {
+ _fnProcessingDisplay( oSettings, false );
+ return;
+ }
+
+ var i, iLen, n;
+ var anRows = [];
+ var iRowCount = 0;
+ var asStripeClasses = oSettings.asStripeClasses;
+ var iStripes = asStripeClasses.length;
+ var iOpenRows = oSettings.aoOpenRows.length;
+ var oLang = oSettings.oLanguage;
+ var iInitDisplayStart = oSettings.iInitDisplayStart;
+ var bServerSide = _fnDataSource( oSettings ) == 'ssp';
+ var aiDisplay = oSettings.aiDisplay;
+
+ oSettings.bDrawing = true;
+
+ /* Check and see if we have an initial draw position from state saving */
+ if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
+ {
+ oSettings._iDisplayStart = bServerSide ?
+ iInitDisplayStart :
+ iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
+ 0 :
+ iInitDisplayStart;
+
+ oSettings.iInitDisplayStart = -1;
+ }
+
+ var iDisplayStart = oSettings._iDisplayStart;
+ var iDisplayEnd = oSettings.fnDisplayEnd();
+
+ /* Server-side processing draw intercept */
+ if ( oSettings.bDeferLoading )
+ {
+ oSettings.bDeferLoading = false;
+ oSettings.iDraw++;
+ _fnProcessingDisplay( oSettings, false );
+ }
+ else if ( !bServerSide )
+ {
+ oSettings.iDraw++;
+ }
+ else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
+ {
+ return;
+ }
+
+ if ( aiDisplay.length !== 0 )
+ {
+ var iStart = bServerSide ? 0 : iDisplayStart;
+ var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
+
+ for ( var j=iStart ; j<iEnd ; j++ )
+ {
+ var iDataIndex = aiDisplay[j];
+ var aoData = oSettings.aoData[ iDataIndex ];
+ if ( aoData.nTr === null )
+ {
+ _fnCreateTr( oSettings, iDataIndex );
+ }
+
+ var nRow = aoData.nTr;
+
+ /* Remove the old striping classes and then add the new one */
+ if ( iStripes !== 0 )
+ {
+ var sStripe = asStripeClasses[ iRowCount % iStripes ];
+ if ( aoData._sRowStripe != sStripe )
+ {
+ $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
+ aoData._sRowStripe = sStripe;
+ }
+ }
+
+ // Row callback functions - might want to manipulate the row
+ // iRowCount and j are not currently documented. Are they at all
+ // useful?
+ _fnCallbackFire( oSettings, 'aoRowCallback', null,
+ [nRow, aoData._aData, iRowCount, j] );
+
+ anRows.push( nRow );
+ iRowCount++;
+ }
+ }
+ else
+ {
+ /* Table is empty - create a row with an empty message in it */
+ var sZero = oLang.sZeroRecords;
+ if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' )
+ {
+ sZero = oLang.sLoadingRecords;
+ }
+ else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
+ {
+ sZero = oLang.sEmptyTable;
+ }
+
+ anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
+ .append( $('<td />', {
+ 'valign': 'top',
+ 'colSpan': _fnVisbleColumns( oSettings ),
+ 'class': oSettings.oClasses.sRowEmpty
+ } ).html( sZero ) )[0];
+ }
+
+ /* Header and footer callbacks */
+ _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
+ _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
+
+ _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
+ _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
+
+ var body = $(oSettings.nTBody);
+
+ body.children().detach();
+ body.append( $(anRows) );
+
+ /* Call all required callback functions for the end of a draw */
+ _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
+
+ /* Draw is complete, sorting and filtering must be as well */
+ oSettings.bSorted = false;
+ oSettings.bFiltered = false;
+ oSettings.bDrawing = false;
+ }
+
+
+ /**
+ * Redraw the table - taking account of the various features which are enabled
+ * @param {object} oSettings dataTables settings object
+ * @param {boolean} [holdPosition] Keep the current paging position. By default
+ * the paging is reset to the first page
+ * @memberof DataTable#oApi
+ */
+ function _fnReDraw( settings, holdPosition )
+ {
+ var
+ features = settings.oFeatures,
+ sort = features.bSort,
+ filter = features.bFilter;
+
+ if ( sort ) {
+ _fnSort( settings );
+ }
+
+ if ( filter ) {
+ _fnFilterComplete( settings, settings.oPreviousSearch );
+ }
+ else {
+ // No filtering, so we want to just use the display master
+ settings.aiDisplay = settings.aiDisplayMaster.slice();
+ }
+
+ if ( holdPosition !== true ) {
+ settings._iDisplayStart = 0;
+ }
+
+ // Let any modules know about the draw hold position state (used by
+ // scrolling internally)
+ settings._drawHold = holdPosition;
+
+ _fnDraw( settings );
+
+ settings._drawHold = false;
+ }
+
+
+ /**
+ * Add the options to the page HTML for the table
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnAddOptionsHtml ( oSettings )
+ {
+ var classes = oSettings.oClasses;
+ var table = $(oSettings.nTable);
+ var holding = $('<div/>').insertBefore( table ); // Holding element for speed
+ var features = oSettings.oFeatures;
+
+ // All DataTables are wrapped in a div
+ var insert = $('<div/>', {
+ id: oSettings.sTableId+'_wrapper',
+ 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
+ } );
+
+ oSettings.nHolding = holding[0];
+ oSettings.nTableWrapper = insert[0];
+ oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
+
+ /* Loop over the user set positioning and place the elements as needed */
+ var aDom = oSettings.sDom.split('');
+ var featureNode, cOption, nNewNode, cNext, sAttr, j;
+ for ( var i=0 ; i<aDom.length ; i++ )
+ {
+ featureNode = null;
+ cOption = aDom[i];
+
+ if ( cOption == '<' )
+ {
+ /* New container div */
+ nNewNode = $('<div/>')[0];
+
+ /* Check to see if we should append an id and/or a class name to the container */
+ cNext = aDom[i+1];
+ if ( cNext == "'" || cNext == '"' )
+ {
+ sAttr = "";
+ j = 2;
+ while ( aDom[i+j] != cNext )
+ {
+ sAttr += aDom[i+j];
+ j++;
+ }
+
+ /* Replace jQuery UI constants @todo depreciated */
+ if ( sAttr == "H" )
+ {
+ sAttr = classes.sJUIHeader;
+ }
+ else if ( sAttr == "F" )
+ {
+ sAttr = classes.sJUIFooter;
+ }
+
+ /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
+ * breaks the string into parts and applies them as needed
+ */
+ if ( sAttr.indexOf('.') != -1 )
+ {
+ var aSplit = sAttr.split('.');
+ nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
+ nNewNode.className = aSplit[1];
+ }
+ else if ( sAttr.charAt(0) == "#" )
+ {
+ nNewNode.id = sAttr.substr(1, sAttr.length-1);
+ }
+ else
+ {
+ nNewNode.className = sAttr;
+ }
+
+ i += j; /* Move along the position array */
+ }
+
+ insert.append( nNewNode );
+ insert = $(nNewNode);
+ }
+ else if ( cOption == '>' )
+ {
+ /* End container div */
+ insert = insert.parent();
+ }
+ // @todo Move options into their own plugins?
+ else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
+ {
+ /* Length */
+ featureNode = _fnFeatureHtmlLength( oSettings );
+ }
+ else if ( cOption == 'f' && features.bFilter )
+ {
+ /* Filter */
+ featureNode = _fnFeatureHtmlFilter( oSettings );
+ }
+ else if ( cOption == 'r' && features.bProcessing )
+ {
+ /* pRocessing */
+ featureNode = _fnFeatureHtmlProcessing( oSettings );
+ }
+ else if ( cOption == 't' )
+ {
+ /* Table */
+ featureNode = _fnFeatureHtmlTable( oSettings );
+ }
+ else if ( cOption == 'i' && features.bInfo )
+ {
+ /* Info */
+ featureNode = _fnFeatureHtmlInfo( oSettings );
+ }
+ else if ( cOption == 'p' && features.bPaginate )
+ {
+ /* Pagination */
+ featureNode = _fnFeatureHtmlPaginate( oSettings );
+ }
+ else if ( DataTable.ext.feature.length !== 0 )
+ {
+ /* Plug-in features */
+ var aoFeatures = DataTable.ext.feature;
+ for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
+ {
+ if ( cOption == aoFeatures[k].cFeature )
+ {
+ featureNode = aoFeatures[k].fnInit( oSettings );
+ break;
+ }
+ }
+ }
+
+ /* Add to the 2D features array */
+ if ( featureNode )
+ {
+ var aanFeatures = oSettings.aanFeatures;
+
+ if ( ! aanFeatures[cOption] )
+ {
+ aanFeatures[cOption] = [];
+ }
+
+ aanFeatures[cOption].push( featureNode );
+ insert.append( featureNode );
+ }
+ }
+
+ /* Built our DOM structure - replace the holding div with what we want */
+ holding.replaceWith( insert );
+ oSettings.nHolding = null;
+ }
+
+
+ /**
+ * Use the DOM source to create up an array of header cells. The idea here is to
+ * create a layout grid (array) of rows x columns, which contains a reference
+ * to the cell that that point in the grid (regardless of col/rowspan), such that
+ * any column / row could be removed and the new grid constructed
+ * @param array {object} aLayout Array to store the calculated layout in
+ * @param {node} nThead The header/footer element for the table
+ * @memberof DataTable#oApi
+ */
+ function _fnDetectHeader ( aLayout, nThead )
+ {
+ var nTrs = $(nThead).children('tr');
+ var nTr, nCell;
+ var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
+ var bUnique;
+ var fnShiftCol = function ( a, i, j ) {
+ var k = a[i];
+ while ( k[j] ) {
+ j++;
+ }
+ return j;
+ };
+
+ aLayout.splice( 0, aLayout.length );
+
+ /* We know how many rows there are in the layout - so prep it */
+ for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
+ {
+ aLayout.push( [] );
+ }
+
+ /* Calculate a layout array */
+ for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
+ {
+ nTr = nTrs[i];
+ iColumn = 0;
+
+ /* For every cell in the row... */
+ nCell = nTr.firstChild;
+ while ( nCell ) {
+ if ( nCell.nodeName.toUpperCase() == "TD" ||
+ nCell.nodeName.toUpperCase() == "TH" )
+ {
+ /* Get the col and rowspan attributes from the DOM and sanitise them */
+ iColspan = nCell.getAttribute('colspan') * 1;
+ iRowspan = nCell.getAttribute('rowspan') * 1;
+ iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
+ iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
+
+ /* There might be colspan cells already in this row, so shift our target
+ * accordingly
+ */
+ iColShifted = fnShiftCol( aLayout, i, iColumn );
+
+ /* Cache calculation for unique columns */
+ bUnique = iColspan === 1 ? true : false;
+
+ /* If there is col / rowspan, copy the information into the layout grid */
+ for ( l=0 ; l<iColspan ; l++ )
+ {
+ for ( k=0 ; k<iRowspan ; k++ )
+ {
+ aLayout[i+k][iColShifted+l] = {
+ "cell": nCell,
+ "unique": bUnique
+ };
+ aLayout[i+k].nTr = nTr;
+ }
+ }
+ }
+ nCell = nCell.nextSibling;
+ }
+ }
+ }
+
+
+ /**
+ * Get an array of unique th elements, one for each column
+ * @param {object} oSettings dataTables settings object
+ * @param {node} nHeader automatically detect the layout from this node - optional
+ * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
+ * @returns array {node} aReturn list of unique th's
+ * @memberof DataTable#oApi
+ */
+ function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
+ {
+ var aReturn = [];
+ if ( !aLayout )
+ {
+ aLayout = oSettings.aoHeader;
+ if ( nHeader )
+ {
+ aLayout = [];
+ _fnDetectHeader( aLayout, nHeader );
+ }
+ }
+
+ for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
+ {
+ for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
+ {
+ if ( aLayout[i][j].unique &&
+ (!aReturn[j] || !oSettings.bSortCellsTop) )
+ {
+ aReturn[j] = aLayout[i][j].cell;
+ }
+ }
+ }
+
+ return aReturn;
+ }
+
+ /**
+ * Create an Ajax call based on the table's settings, taking into account that
+ * parameters can have multiple forms, and backwards compatibility.
+ *
+ * @param {object} oSettings dataTables settings object
+ * @param {array} data Data to send to the server, required by
+ * DataTables - may be augmented by developer callbacks
+ * @param {function} fn Callback function to run when data is obtained
+ */
+ function _fnBuildAjax( oSettings, data, fn )
+ {
+ // Compatibility with 1.9-, allow fnServerData and event to manipulate
+ _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
+
+ // Convert to object based for 1.10+ if using the old array scheme which can
+ // come from server-side processing or serverParams
+ if ( data && $.isArray(data) ) {
+ var tmp = {};
+ var rbracket = /(.*?)\[\]$/;
+
+ $.each( data, function (key, val) {
+ var match = val.name.match(rbracket);
+
+ if ( match ) {
+ // Support for arrays
+ var name = match[0];
+
+ if ( ! tmp[ name ] ) {
+ tmp[ name ] = [];
+ }
+ tmp[ name ].push( val.value );
+ }
+ else {
+ tmp[val.name] = val.value;
+ }
+ } );
+ data = tmp;
+ }
+
+ var ajaxData;
+ var ajax = oSettings.ajax;
+ var instance = oSettings.oInstance;
+ var callback = function ( json ) {
+ _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
+ fn( json );
+ };
+
+ if ( $.isPlainObject( ajax ) && ajax.data )
+ {
+ ajaxData = ajax.data;
+
+ var newData = $.isFunction( ajaxData ) ?
+ ajaxData( data, oSettings ) : // fn can manipulate data or return
+ ajaxData; // an object object or array to merge
+
+ // If the function returned something, use that alone
+ data = $.isFunction( ajaxData ) && newData ?
+ newData :
+ $.extend( true, data, newData );
+
+ // Remove the data property as we've resolved it already and don't want
+ // jQuery to do it again (it is restored at the end of the function)
+ delete ajax.data;
+ }
+
+ var baseAjax = {
+ "data": data,
+ "success": function (json) {
+ var error = json.error || json.sError;
+ if ( error ) {
+ _fnLog( oSettings, 0, error );
+ }
+
+ oSettings.json = json;
+ callback( json );
+ },
+ "dataType": "json",
+ "cache": false,
+ "type": oSettings.sServerMethod,
+ "error": function (xhr, error, thrown) {
+ var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
+
+ if ( $.inArray( true, ret ) === -1 ) {
+ if ( error == "parsererror" ) {
+ _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
+ }
+ else if ( xhr.readyState === 4 ) {
+ _fnLog( oSettings, 0, 'Ajax error', 7 );
+ }
+ }
+
+ _fnProcessingDisplay( oSettings, false );
+ }
+ };
+
+ // Store the data submitted for the API
+ oSettings.oAjaxData = data;
+
+ // Allow plug-ins and external processes to modify the data
+ _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
+
+ if ( oSettings.fnServerData )
+ {
+ // DataTables 1.9- compatibility
+ oSettings.fnServerData.call( instance,
+ oSettings.sAjaxSource,
+ $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
+ return { name: key, value: val };
+ } ),
+ callback,
+ oSettings
+ );
+ }
+ else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
+ {
+ // DataTables 1.9- compatibility
+ oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
+ url: ajax || oSettings.sAjaxSource
+ } ) );
+ }
+ else if ( $.isFunction( ajax ) )
+ {
+ // Is a function - let the caller define what needs to be done
+ oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
+ }
+ else
+ {
+ // Object to extend the base settings
+ oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
+
+ // Restore for next time around
+ ajax.data = ajaxData;
+ }
+ }
+
+
+ /**
+ * Update the table using an Ajax call
+ * @param {object} settings dataTables settings object
+ * @returns {boolean} Block the table drawing or not
+ * @memberof DataTable#oApi
+ */
+ function _fnAjaxUpdate( settings )
+ {
+ if ( settings.bAjaxDataGet ) {
+ settings.iDraw++;
+ _fnProcessingDisplay( settings, true );
+
+ _fnBuildAjax(
+ settings,
+ _fnAjaxParameters( settings ),
+ function(json) {
+ _fnAjaxUpdateDraw( settings, json );
+ }
+ );
+
+ return false;
+ }
+ return true;
+ }
+
+
+ /**
+ * Build up the parameters in an object needed for a server-side processing
+ * request. Note that this is basically done twice, is different ways - a modern
+ * method which is used by default in DataTables 1.10 which uses objects and
+ * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
+ * the sAjaxSource option is used in the initialisation, or the legacyAjax
+ * option is set.
+ * @param {object} oSettings dataTables settings object
+ * @returns {bool} block the table drawing or not
+ * @memberof DataTable#oApi
+ */
+ function _fnAjaxParameters( settings )
+ {
+ var
+ columns = settings.aoColumns,
+ columnCount = columns.length,
+ features = settings.oFeatures,
+ preSearch = settings.oPreviousSearch,
+ preColSearch = settings.aoPreSearchCols,
+ i, data = [], dataProp, column, columnSearch,
+ sort = _fnSortFlatten( settings ),
+ displayStart = settings._iDisplayStart,
+ displayLength = features.bPaginate !== false ?
+ settings._iDisplayLength :
+ -1;
+
+ var param = function ( name, value ) {
+ data.push( { 'name': name, 'value': value } );
+ };
+
+ // DataTables 1.9- compatible method
+ param( 'sEcho', settings.iDraw );
+ param( 'iColumns', columnCount );
+ param( 'sColumns', _pluck( columns, 'sName' ).join(',') );
+ param( 'iDisplayStart', displayStart );
+ param( 'iDisplayLength', displayLength );
+
+ // DataTables 1.10+ method
+ var d = {
+ draw: settings.iDraw,
+ columns: [],
+ order: [],
+ start: displayStart,
+ length: displayLength,
+ search: {
+ value: preSearch.sSearch,
+ regex: preSearch.bRegex
+ }
+ };
+
+ for ( i=0 ; i<columnCount ; i++ ) {
+ column = columns[i];
+ columnSearch = preColSearch[i];
+ dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
+
+ d.columns.push( {
+ data: dataProp,
+ name: column.sName,
+ searchable: column.bSearchable,
+ orderable: column.bSortable,
+ search: {
+ value: columnSearch.sSearch,
+ regex: columnSearch.bRegex
+ }
+ } );
+
+ param( "mDataProp_"+i, dataProp );
+
+ if ( features.bFilter ) {
+ param( 'sSearch_'+i, columnSearch.sSearch );
+ param( 'bRegex_'+i, columnSearch.bRegex );
+ param( 'bSearchable_'+i, column.bSearchable );
+ }
+
+ if ( features.bSort ) {
+ param( 'bSortable_'+i, column.bSortable );
+ }
+ }
+
+ if ( features.bFilter ) {
+ param( 'sSearch', preSearch.sSearch );
+ param( 'bRegex', preSearch.bRegex );
+ }
+
+ if ( features.bSort ) {
+ $.each( sort, function ( i, val ) {
+ d.order.push( { column: val.col, dir: val.dir } );
+
+ param( 'iSortCol_'+i, val.col );
+ param( 'sSortDir_'+i, val.dir );
+ } );
+
+ param( 'iSortingCols', sort.length );
+ }
+
+ // If the legacy.ajax parameter is null, then we automatically decide which
+ // form to use, based on sAjaxSource
+ var legacy = DataTable.ext.legacy.ajax;
+ if ( legacy === null ) {
+ return settings.sAjaxSource ? data : d;
+ }
+
+ // Otherwise, if legacy has been specified then we use that to decide on the
+ // form
+ return legacy ? data : d;
+ }
+
+
+ /**
+ * Data the data from the server (nuking the old) and redraw the table
+ * @param {object} oSettings dataTables settings object
+ * @param {object} json json data return from the server.
+ * @param {string} json.sEcho Tracking flag for DataTables to match requests
+ * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
+ * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
+ * @param {array} json.aaData The data to display on this page
+ * @param {string} [json.sColumns] Column ordering (sName, comma separated)
+ * @memberof DataTable#oApi
+ */
+ function _fnAjaxUpdateDraw ( settings, json )
+ {
+ // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
+ // Support both
+ var compat = function ( old, modern ) {
+ return json[old] !== undefined ? json[old] : json[modern];
+ };
+
+ var data = _fnAjaxDataSrc( settings, json );
+ var draw = compat( 'sEcho', 'draw' );
+ var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' );
+ var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
+
+ if ( draw ) {
+ // Protect against out of sequence returns
+ if ( draw*1 < settings.iDraw ) {
+ return;
+ }
+ settings.iDraw = draw * 1;
+ }
+
+ _fnClearTable( settings );
+ settings._iRecordsTotal = parseInt(recordsTotal, 10);
+ settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
+
+ for ( var i=0, ien=data.length ; i<ien ; i++ ) {
+ _fnAddData( settings, data[i] );
+ }
+ settings.aiDisplay = settings.aiDisplayMaster.slice();
+
+ settings.bAjaxDataGet = false;
+ _fnDraw( settings );
+
+ if ( ! settings._bInitComplete ) {
+ _fnInitComplete( settings, json );
+ }
+
+ settings.bAjaxDataGet = true;
+ _fnProcessingDisplay( settings, false );
+ }
+
+
+ /**
+ * Get the data from the JSON data source to use for drawing a table. Using
+ * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
+ * source object, or from a processing function.
+ * @param {object} oSettings dataTables settings object
+ * @param {object} json Data source object / array from the server
+ * @return {array} Array of data to use
+ */
+ function _fnAjaxDataSrc ( oSettings, json )
+ {
+ var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
+ oSettings.ajax.dataSrc :
+ oSettings.sAjaxDataProp; // Compatibility with 1.9-.
+
+ // Compatibility with 1.9-. In order to read from aaData, check if the
+ // default has been changed, if not, check for aaData
+ if ( dataSrc === 'data' ) {
+ return json.aaData || json[dataSrc];
+ }
+
+ return dataSrc !== "" ?
+ _fnGetObjectDataFn( dataSrc )( json ) :
+ json;
+ }
+
+ /**
+ * Generate the node required for filtering text
+ * @returns {node} Filter control element
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlFilter ( settings )
+ {
+ var classes = settings.oClasses;
+ var tableId = settings.sTableId;
+ var language = settings.oLanguage;
+ var previousSearch = settings.oPreviousSearch;
+ var features = settings.aanFeatures;
+ var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
+
+ var str = language.sSearch;
+ str = str.match(/_INPUT_/) ?
+ str.replace('_INPUT_', input) :
+ str+input;
+
+ var filter = $('<div/>', {
+ 'id': ! features.f ? tableId+'_filter' : null,
+ 'class': classes.sFilter
+ } )
+ .append( $('<label/>' ).append( str ) );
+
+ var searchFn = function() {
+ /* Update all other filter input elements for the new display */
+ var n = features.f;
+ var val = !this.value ? "" : this.value; // mental IE8 fix :-(
+
+ /* Now do the filter */
+ if ( val != previousSearch.sSearch ) {
+ _fnFilterComplete( settings, {
+ "sSearch": val,
+ "bRegex": previousSearch.bRegex,
+ "bSmart": previousSearch.bSmart ,
+ "bCaseInsensitive": previousSearch.bCaseInsensitive
+ } );
+
+ // Need to redraw, without resorting
+ settings._iDisplayStart = 0;
+ _fnDraw( settings );
+ }
+ };
+
+ var searchDelay = settings.searchDelay !== null ?
+ settings.searchDelay :
+ _fnDataSource( settings ) === 'ssp' ?
+ 400 :
+ 0;
+
+ var jqFilter = $('input', filter)
+ .val( previousSearch.sSearch )
+ .attr( 'placeholder', language.sSearchPlaceholder )
+ .on(
+ 'keyup.DT search.DT input.DT paste.DT cut.DT',
+ searchDelay ?
+ _fnThrottle( searchFn, searchDelay ) :
+ searchFn
+ )
+ .on( 'keypress.DT', function(e) {
+ /* Prevent form submission */
+ if ( e.keyCode == 13 ) {
+ return false;
+ }
+ } )
+ .attr('aria-controls', tableId);
+
+ // Update the input elements whenever the table is filtered
+ $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
+ if ( settings === s ) {
+ // IE9 throws an 'unknown error' if document.activeElement is used
+ // inside an iframe or frame...
+ try {
+ if ( jqFilter[0] !== document.activeElement ) {
+ jqFilter.val( previousSearch.sSearch );
+ }
+ }
+ catch ( e ) {}
+ }
+ } );
+
+ return filter[0];
+ }
+
+
+ /**
+ * Filter the table using both the global filter and column based filtering
+ * @param {object} oSettings dataTables settings object
+ * @param {object} oSearch search information
+ * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
+ * @memberof DataTable#oApi
+ */
+ function _fnFilterComplete ( oSettings, oInput, iForce )
+ {
+ var oPrevSearch = oSettings.oPreviousSearch;
+ var aoPrevSearch = oSettings.aoPreSearchCols;
+ var fnSaveFilter = function ( oFilter ) {
+ /* Save the filtering values */
+ oPrevSearch.sSearch = oFilter.sSearch;
+ oPrevSearch.bRegex = oFilter.bRegex;
+ oPrevSearch.bSmart = oFilter.bSmart;
+ oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
+ };
+ var fnRegex = function ( o ) {
+ // Backwards compatibility with the bEscapeRegex option
+ return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
+ };
+
+ // Resolve any column types that are unknown due to addition or invalidation
+ // @todo As per sort - can this be moved into an event handler?
+ _fnColumnTypes( oSettings );
+
+ /* In server-side processing all filtering is done by the server, so no point hanging around here */
+ if ( _fnDataSource( oSettings ) != 'ssp' )
+ {
+ /* Global filter */
+ _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
+ fnSaveFilter( oInput );
+
+ /* Now do the individual column filter */
+ for ( var i=0 ; i<aoPrevSearch.length ; i++ )
+ {
+ _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
+ aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
+ }
+
+ /* Custom filtering */
+ _fnFilterCustom( oSettings );
+ }
+ else
+ {
+ fnSaveFilter( oInput );
+ }
+
+ /* Tell the draw function we have been filtering */
+ oSettings.bFiltered = true;
+ _fnCallbackFire( oSettings, null, 'search', [oSettings] );
+ }
+
+
+ /**
+ * Apply custom filtering functions
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnFilterCustom( settings )
+ {
+ var filters = DataTable.ext.search;
+ var displayRows = settings.aiDisplay;
+ var row, rowIdx;
+
+ for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
+ var rows = [];
+
+ // Loop over each row and see if it should be included
+ for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
+ rowIdx = displayRows[ j ];
+ row = settings.aoData[ rowIdx ];
+
+ if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
+ rows.push( rowIdx );
+ }
+ }
+
+ // So the array reference doesn't break set the results into the
+ // existing array
+ displayRows.length = 0;
+ $.merge( displayRows, rows );
+ }
+ }
+
+
+ /**
+ * Filter the table on a per-column basis
+ * @param {object} oSettings dataTables settings object
+ * @param {string} sInput string to filter on
+ * @param {int} iColumn column to filter
+ * @param {bool} bRegex treat search string as a regular expression or not
+ * @param {bool} bSmart use smart filtering or not
+ * @param {bool} bCaseInsensitive Do case insenstive matching or not
+ * @memberof DataTable#oApi
+ */
+ function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
+ {
+ if ( searchStr === '' ) {
+ return;
+ }
+
+ var data;
+ var out = [];
+ var display = settings.aiDisplay;
+ var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
+
+ for ( var i=0 ; i<display.length ; i++ ) {
+ data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
+
+ if ( rpSearch.test( data ) ) {
+ out.push( display[i] );
+ }
+ }
+
+ settings.aiDisplay = out;
+ }
+
+
+ /**
+ * Filter the data table based on user input and draw the table
+ * @param {object} settings dataTables settings object
+ * @param {string} input string to filter on
+ * @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
+ * @param {bool} regex treat as a regular expression or not
+ * @param {bool} smart perform smart filtering or not
+ * @param {bool} caseInsensitive Do case insenstive matching or not
+ * @memberof DataTable#oApi
+ */
+ function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
+ {
+ var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
+ var prevSearch = settings.oPreviousSearch.sSearch;
+ var displayMaster = settings.aiDisplayMaster;
+ var display, invalidated, i;
+ var filtered = [];
+
+ // Need to take account of custom filtering functions - always filter
+ if ( DataTable.ext.search.length !== 0 ) {
+ force = true;
+ }
+
+ // Check if any of the rows were invalidated
+ invalidated = _fnFilterData( settings );
+
+ // If the input is blank - we just want the full data set
+ if ( input.length <= 0 ) {
+ settings.aiDisplay = displayMaster.slice();
+ }
+ else {
+ // New search - start from the master array
+ if ( invalidated ||
+ force ||
+ prevSearch.length > input.length ||
+ input.indexOf(prevSearch) !== 0 ||
+ settings.bSorted // On resort, the display master needs to be
+ // re-filtered since indexes will have changed
+ ) {
+ settings.aiDisplay = displayMaster.slice();
+ }
+
+ // Search the display array
+ display = settings.aiDisplay;
+
+ for ( i=0 ; i<display.length ; i++ ) {
+ if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
+ filtered.push( display[i] );
+ }
+ }
+
+ settings.aiDisplay = filtered;
+ }
+ }
+
+
+ /**
+ * Build a regular expression object suitable for searching a table
+ * @param {string} sSearch string to search for
+ * @param {bool} bRegex treat as a regular expression or not
+ * @param {bool} bSmart perform smart filtering or not
+ * @param {bool} bCaseInsensitive Do case insensitive matching or not
+ * @returns {RegExp} constructed object
+ * @memberof DataTable#oApi
+ */
+ function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
+ {
+ search = regex ?
+ search :
+ _fnEscapeRegex( search );
+
+ if ( smart ) {
+ /* For smart filtering we want to allow the search to work regardless of
+ * word order. We also want double quoted text to be preserved, so word
+ * order is important - a la google. So this is what we want to
+ * generate:
+ *
+ * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
+ */
+ var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
+ if ( word.charAt(0) === '"' ) {
+ var m = word.match( /^"(.*)"$/ );
+ word = m ? m[1] : word;
+ }
+
+ return word.replace('"', '');
+ } );
+
+ search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
+ }
+
+ return new RegExp( search, caseInsensitive ? 'i' : '' );
+ }
+
+
+ /**
+ * Escape a string such that it can be used in a regular expression
+ * @param {string} sVal string to escape
+ * @returns {string} escaped string
+ * @memberof DataTable#oApi
+ */
+ var _fnEscapeRegex = DataTable.util.escapeRegex;
+
+ var __filter_div = $('<div>')[0];
+ var __filter_div_textContent = __filter_div.textContent !== undefined;
+
+ // Update the filtering data for each row if needed (by invalidation or first run)
+ function _fnFilterData ( settings )
+ {
+ var columns = settings.aoColumns;
+ var column;
+ var i, j, ien, jen, filterData, cellData, row;
+ var fomatters = DataTable.ext.type.search;
+ var wasInvalidated = false;
+
+ for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
+ row = settings.aoData[i];
+
+ if ( ! row._aFilterData ) {
+ filterData = [];
+
+ for ( j=0, jen=columns.length ; j<jen ; j++ ) {
+ column = columns[j];
+
+ if ( column.bSearchable ) {
+ cellData = _fnGetCellData( settings, i, j, 'filter' );
+
+ if ( fomatters[ column.sType ] ) {
+ cellData = fomatters[ column.sType ]( cellData );
+ }
+
+ // Search in DataTables 1.10 is string based. In 1.11 this
+ // should be altered to also allow strict type checking.
+ if ( cellData === null ) {
+ cellData = '';
+ }
+
+ if ( typeof cellData !== 'string' && cellData.toString ) {
+ cellData = cellData.toString();
+ }
+ }
+ else {
+ cellData = '';
+ }
+
+ // If it looks like there is an HTML entity in the string,
+ // attempt to decode it so sorting works as expected. Note that
+ // we could use a single line of jQuery to do this, but the DOM
+ // method used here is much faster http://jsperf.com/html-decode
+ if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
+ __filter_div.innerHTML = cellData;
+ cellData = __filter_div_textContent ?
+ __filter_div.textContent :
+ __filter_div.innerText;
+ }
+
+ if ( cellData.replace ) {
+ cellData = cellData.replace(/[\r\n]/g, '');
+ }
+
+ filterData.push( cellData );
+ }
+
+ row._aFilterData = filterData;
+ row._sFilterRow = filterData.join(' ');
+ wasInvalidated = true;
+ }
+ }
+
+ return wasInvalidated;
+ }
+
+
+ /**
+ * Convert from the internal Hungarian notation to camelCase for external
+ * interaction
+ * @param {object} obj Object to convert
+ * @returns {object} Inverted object
+ * @memberof DataTable#oApi
+ */
+ function _fnSearchToCamel ( obj )
+ {
+ return {
+ search: obj.sSearch,
+ smart: obj.bSmart,
+ regex: obj.bRegex,
+ caseInsensitive: obj.bCaseInsensitive
+ };
+ }
+
+
+
+ /**
+ * Convert from camelCase notation to the internal Hungarian. We could use the
+ * Hungarian convert function here, but this is cleaner
+ * @param {object} obj Object to convert
+ * @returns {object} Inverted object
+ * @memberof DataTable#oApi
+ */
+ function _fnSearchToHung ( obj )
+ {
+ return {
+ sSearch: obj.search,
+ bSmart: obj.smart,
+ bRegex: obj.regex,
+ bCaseInsensitive: obj.caseInsensitive
+ };
+ }
+
+ /**
+ * Generate the node required for the info display
+ * @param {object} oSettings dataTables settings object
+ * @returns {node} Information element
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlInfo ( settings )
+ {
+ var
+ tid = settings.sTableId,
+ nodes = settings.aanFeatures.i,
+ n = $('<div/>', {
+ 'class': settings.oClasses.sInfo,
+ 'id': ! nodes ? tid+'_info' : null
+ } );
+
+ if ( ! nodes ) {
+ // Update display on each draw
+ settings.aoDrawCallback.push( {
+ "fn": _fnUpdateInfo,
+ "sName": "information"
+ } );
+
+ n
+ .attr( 'role', 'status' )
+ .attr( 'aria-live', 'polite' );
+
+ // Table is described by our info div
+ $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
+ }
+
+ return n[0];
+ }
+
+
+ /**
+ * Update the information elements in the display
+ * @param {object} settings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnUpdateInfo ( settings )
+ {
+ /* Show information about the table */
+ var nodes = settings.aanFeatures.i;
+ if ( nodes.length === 0 ) {
+ return;
+ }
+
+ var
+ lang = settings.oLanguage,
+ start = settings._iDisplayStart+1,
+ end = settings.fnDisplayEnd(),
+ max = settings.fnRecordsTotal(),
+ total = settings.fnRecordsDisplay(),
+ out = total ?
+ lang.sInfo :
+ lang.sInfoEmpty;
+
+ if ( total !== max ) {
+ /* Record set after filtering */
+ out += ' ' + lang.sInfoFiltered;
+ }
+
+ // Convert the macros
+ out += lang.sInfoPostFix;
+ out = _fnInfoMacros( settings, out );
+
+ var callback = lang.fnInfoCallback;
+ if ( callback !== null ) {
+ out = callback.call( settings.oInstance,
+ settings, start, end, max, total, out
+ );
+ }
+
+ $(nodes).html( out );
+ }
+
+
+ function _fnInfoMacros ( settings, str )
+ {
+ // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
+ // internally
+ var
+ formatter = settings.fnFormatNumber,
+ start = settings._iDisplayStart+1,
+ len = settings._iDisplayLength,
+ vis = settings.fnRecordsDisplay(),
+ all = len === -1;
+
+ return str.
+ replace(/_START_/g, formatter.call( settings, start ) ).
+ replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ).
+ replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ).
+ replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
+ replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
+ replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
+ }
+
+
+
+ /**
+ * Draw the table for the first time, adding all required features
+ * @param {object} settings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnInitialise ( settings )
+ {
+ var i, iLen, iAjaxStart=settings.iInitDisplayStart;
+ var columns = settings.aoColumns, column;
+ var features = settings.oFeatures;
+ var deferLoading = settings.bDeferLoading; // value modified by the draw
+
+ /* Ensure that the table data is fully initialised */
+ if ( ! settings.bInitialised ) {
+ setTimeout( function(){ _fnInitialise( settings ); }, 200 );
+ return;
+ }
+
+ /* Show the display HTML options */
+ _fnAddOptionsHtml( settings );
+
+ /* Build and draw the header / footer for the table */
+ _fnBuildHead( settings );
+ _fnDrawHead( settings, settings.aoHeader );
+ _fnDrawHead( settings, settings.aoFooter );
+
+ /* Okay to show that something is going on now */
+ _fnProcessingDisplay( settings, true );
+
+ /* Calculate sizes for columns */
+ if ( features.bAutoWidth ) {
+ _fnCalculateColumnWidths( settings );
+ }
+
+ for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
+ column = columns[i];
+
+ if ( column.sWidth ) {
+ column.nTh.style.width = _fnStringToCss( column.sWidth );
+ }
+ }
+
+ _fnCallbackFire( settings, null, 'preInit', [settings] );
+
+ // If there is default sorting required - let's do it. The sort function
+ // will do the drawing for us. Otherwise we draw the table regardless of the
+ // Ajax source - this allows the table to look initialised for Ajax sourcing
+ // data (show 'loading' message possibly)
+ _fnReDraw( settings );
+
+ // Server-side processing init complete is done by _fnAjaxUpdateDraw
+ var dataSrc = _fnDataSource( settings );
+ if ( dataSrc != 'ssp' || deferLoading ) {
+ // if there is an ajax source load the data
+ if ( dataSrc == 'ajax' ) {
+ _fnBuildAjax( settings, [], function(json) {
+ var aData = _fnAjaxDataSrc( settings, json );
+
+ // Got the data - add it to the table
+ for ( i=0 ; i<aData.length ; i++ ) {
+ _fnAddData( settings, aData[i] );
+ }
+
+ // Reset the init display for cookie saving. We've already done
+ // a filter, and therefore cleared it before. So we need to make
+ // it appear 'fresh'
+ settings.iInitDisplayStart = iAjaxStart;
+
+ _fnReDraw( settings );
+
+ _fnProcessingDisplay( settings, false );
+ _fnInitComplete( settings, json );
+ }, settings );
+ }
+ else {
+ _fnProcessingDisplay( settings, false );
+ _fnInitComplete( settings );
+ }
+ }
+ }
+
+
+ /**
+ * Draw the table for the first time, adding all required features
+ * @param {object} oSettings dataTables settings object
+ * @param {object} [json] JSON from the server that completed the table, if using Ajax source
+ * with client-side processing (optional)
+ * @memberof DataTable#oApi
+ */
+ function _fnInitComplete ( settings, json )
+ {
+ settings._bInitComplete = true;
+
+ // When data was added after the initialisation (data or Ajax) we need to
+ // calculate the column sizing
+ if ( json || settings.oInit.aaData ) {
+ _fnAdjustColumnSizing( settings );
+ }
+
+ _fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
+ _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
+ }
+
+
+ function _fnLengthChange ( settings, val )
+ {
+ var len = parseInt( val, 10 );
+ settings._iDisplayLength = len;
+
+ _fnLengthOverflow( settings );
+
+ // Fire length change event
+ _fnCallbackFire( settings, null, 'length', [settings, len] );
+ }
+
+
+ /**
+ * Generate the node required for user display length changing
+ * @param {object} settings dataTables settings object
+ * @returns {node} Display length feature node
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlLength ( settings )
+ {
+ var
+ classes = settings.oClasses,
+ tableId = settings.sTableId,
+ menu = settings.aLengthMenu,
+ d2 = $.isArray( menu[0] ),
+ lengths = d2 ? menu[0] : menu,
+ language = d2 ? menu[1] : menu;
+
+ var select = $('<select/>', {
+ 'name': tableId+'_length',
+ 'aria-controls': tableId,
+ 'class': classes.sLengthSelect
+ } );
+
+ for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
+ select[0][ i ] = new Option(
+ typeof language[i] === 'number' ?
+ settings.fnFormatNumber( language[i] ) :
+ language[i],
+ lengths[i]
+ );
+ }
+
+ var div = $('<div><label/></div>').addClass( classes.sLength );
+ if ( ! settings.aanFeatures.l ) {
+ div[0].id = tableId+'_length';
+ }
+
+ div.children().append(
+ settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
+ );
+
+ // Can't use `select` variable as user might provide their own and the
+ // reference is broken by the use of outerHTML
+ $('select', div)
+ .val( settings._iDisplayLength )
+ .on( 'change.DT', function(e) {
+ _fnLengthChange( settings, $(this).val() );
+ _fnDraw( settings );
+ } );
+
+ // Update node value whenever anything changes the table's length
+ $(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
+ if ( settings === s ) {
+ $('select', div).val( len );
+ }
+ } );
+
+ return div[0];
+ }
+
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Note that most of the paging logic is done in
+ * DataTable.ext.pager
+ */
+
+ /**
+ * Generate the node required for default pagination
+ * @param {object} oSettings dataTables settings object
+ * @returns {node} Pagination feature node
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlPaginate ( settings )
+ {
+ var
+ type = settings.sPaginationType,
+ plugin = DataTable.ext.pager[ type ],
+ modern = typeof plugin === 'function',
+ redraw = function( settings ) {
+ _fnDraw( settings );
+ },
+ node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
+ features = settings.aanFeatures;
+
+ if ( ! modern ) {
+ plugin.fnInit( settings, node, redraw );
+ }
+
+ /* Add a draw callback for the pagination on first instance, to update the paging display */
+ if ( ! features.p )
+ {
+ node.id = settings.sTableId+'_paginate';
+
+ settings.aoDrawCallback.push( {
+ "fn": function( settings ) {
+ if ( modern ) {
+ var
+ start = settings._iDisplayStart,
+ len = settings._iDisplayLength,
+ visRecords = settings.fnRecordsDisplay(),
+ all = len === -1,
+ page = all ? 0 : Math.ceil( start / len ),
+ pages = all ? 1 : Math.ceil( visRecords / len ),
+ buttons = plugin(page, pages),
+ i, ien;
+
+ for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
+ _fnRenderer( settings, 'pageButton' )(
+ settings, features.p[i], i, buttons, page, pages
+ );
+ }
+ }
+ else {
+ plugin.fnUpdate( settings, redraw );
+ }
+ },
+ "sName": "pagination"
+ } );
+ }
+
+ return node;
+ }
+
+
+ /**
+ * Alter the display settings to change the page
+ * @param {object} settings DataTables settings object
+ * @param {string|int} action Paging action to take: "first", "previous",
+ * "next" or "last" or page number to jump to (integer)
+ * @param [bool] redraw Automatically draw the update or not
+ * @returns {bool} true page has changed, false - no change
+ * @memberof DataTable#oApi
+ */
+ function _fnPageChange ( settings, action, redraw )
+ {
+ var
+ start = settings._iDisplayStart,
+ len = settings._iDisplayLength,
+ records = settings.fnRecordsDisplay();
+
+ if ( records === 0 || len === -1 )
+ {
+ start = 0;
+ }
+ else if ( typeof action === "number" )
+ {
+ start = action * len;
+
+ if ( start > records )
+ {
+ start = 0;
+ }
+ }
+ else if ( action == "first" )
+ {
+ start = 0;
+ }
+ else if ( action == "previous" )
+ {
+ start = len >= 0 ?
+ start - len :
+ 0;
+
+ if ( start < 0 )
+ {
+ start = 0;
+ }
+ }
+ else if ( action == "next" )
+ {
+ if ( start + len < records )
+ {
+ start += len;
+ }
+ }
+ else if ( action == "last" )
+ {
+ start = Math.floor( (records-1) / len) * len;
+ }
+ else
+ {
+ _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
+ }
+
+ var changed = settings._iDisplayStart !== start;
+ settings._iDisplayStart = start;
+
+ if ( changed ) {
+ _fnCallbackFire( settings, null, 'page', [settings] );
+
+ if ( redraw ) {
+ _fnDraw( settings );
+ }
+ }
+
+ return changed;
+ }
+
+
+
+ /**
+ * Generate the node required for the processing node
+ * @param {object} settings dataTables settings object
+ * @returns {node} Processing element
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlProcessing ( settings )
+ {
+ return $('<div/>', {
+ 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
+ 'class': settings.oClasses.sProcessing
+ } )
+ .html( settings.oLanguage.sProcessing )
+ .insertBefore( settings.nTable )[0];
+ }
+
+
+ /**
+ * Display or hide the processing indicator
+ * @param {object} settings dataTables settings object
+ * @param {bool} show Show the processing indicator (true) or not (false)
+ * @memberof DataTable#oApi
+ */
+ function _fnProcessingDisplay ( settings, show )
+ {
+ if ( settings.oFeatures.bProcessing ) {
+ $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
+ }
+
+ _fnCallbackFire( settings, null, 'processing', [settings, show] );
+ }
+
+ /**
+ * Add any control elements for the table - specifically scrolling
+ * @param {object} settings dataTables settings object
+ * @returns {node} Node to add to the DOM
+ * @memberof DataTable#oApi
+ */
+ function _fnFeatureHtmlTable ( settings )
+ {
+ var table = $(settings.nTable);
+
+ // Add the ARIA grid role to the table
+ table.attr( 'role', 'grid' );
+
+ // Scrolling from here on in
+ var scroll = settings.oScroll;
+
+ if ( scroll.sX === '' && scroll.sY === '' ) {
+ return settings.nTable;
+ }
+
+ var scrollX = scroll.sX;
+ var scrollY = scroll.sY;
+ var classes = settings.oClasses;
+ var caption = table.children('caption');
+ var captionSide = caption.length ? caption[0]._captionSide : null;
+ var headerClone = $( table[0].cloneNode(false) );
+ var footerClone = $( table[0].cloneNode(false) );
+ var footer = table.children('tfoot');
+ var _div = '<div/>';
+ var size = function ( s ) {
+ return !s ? null : _fnStringToCss( s );
+ };
+
+ if ( ! footer.length ) {
+ footer = null;
+ }
+
+ /*
+ * The HTML structure that we want to generate in this function is:
+ * div - scroller
+ * div - scroll head
+ * div - scroll head inner
+ * table - scroll head table
+ * thead - thead
+ * div - scroll body
+ * table - table (master table)
+ * thead - thead clone for sizing
+ * tbody - tbody
+ * div - scroll foot
+ * div - scroll foot inner
+ * table - scroll foot table
+ * tfoot - tfoot
+ */
+ var scroller = $( _div, { 'class': classes.sScrollWrapper } )
+ .append(
+ $(_div, { 'class': classes.sScrollHead } )
+ .css( {
+ overflow: 'hidden',
+ position: 'relative',
+ border: 0,
+ width: scrollX ? size(scrollX) : '100%'
+ } )
+ .append(
+ $(_div, { 'class': classes.sScrollHeadInner } )
+ .css( {
+ 'box-sizing': 'content-box',
+ width: scroll.sXInner || '100%'
+ } )
+ .append(
+ headerClone
+ .removeAttr('id')
+ .css( 'margin-left', 0 )
+ .append( captionSide === 'top' ? caption : null )
+ .append(
+ table.children('thead')
+ )
+ )
+ )
+ )
+ .append(
+ $(_div, { 'class': classes.sScrollBody } )
+ .css( {
+ position: 'relative',
+ overflow: 'auto',
+ width: size( scrollX )
+ } )
+ .append( table )
+ );
+
+ if ( footer ) {
+ scroller.append(
+ $(_div, { 'class': classes.sScrollFoot } )
+ .css( {
+ overflow: 'hidden',
+ border: 0,
+ width: scrollX ? size(scrollX) : '100%'
+ } )
+ .append(
+ $(_div, { 'class': classes.sScrollFootInner } )
+ .append(
+ footerClone
+ .removeAttr('id')
+ .css( 'margin-left', 0 )
+ .append( captionSide === 'bottom' ? caption : null )
+ .append(
+ table.children('tfoot')
+ )
+ )
+ )
+ );
+ }
+
+ var children = scroller.children();
+ var scrollHead = children[0];
+ var scrollBody = children[1];
+ var scrollFoot = footer ? children[2] : null;
+
+ // When the body is scrolled, then we also want to scroll the headers
+ if ( scrollX ) {
+ $(scrollBody).on( 'scroll.DT', function (e) {
+ var scrollLeft = this.scrollLeft;
+
+ scrollHead.scrollLeft = scrollLeft;
+
+ if ( footer ) {
+ scrollFoot.scrollLeft = scrollLeft;
+ }
+ } );
+ }
+
+ $(scrollBody).css(
+ scrollY && scroll.bCollapse ? 'max-height' : 'height',
+ scrollY
+ );
+
+ settings.nScrollHead = scrollHead;
+ settings.nScrollBody = scrollBody;
+ settings.nScrollFoot = scrollFoot;
+
+ // On redraw - align columns
+ settings.aoDrawCallback.push( {
+ "fn": _fnScrollDraw,
+ "sName": "scrolling"
+ } );
+
+ return scroller[0];
+ }
+
+
+
+ /**
+ * Update the header, footer and body tables for resizing - i.e. column
+ * alignment.
+ *
+ * Welcome to the most horrible function DataTables. The process that this
+ * function follows is basically:
+ * 1. Re-create the table inside the scrolling div
+ * 2. Take live measurements from the DOM
+ * 3. Apply the measurements to align the columns
+ * 4. Clean up
+ *
+ * @param {object} settings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnScrollDraw ( settings )
+ {
+ // Given that this is such a monster function, a lot of variables are use
+ // to try and keep the minimised size as small as possible
+ var
+ scroll = settings.oScroll,
+ scrollX = scroll.sX,
+ scrollXInner = scroll.sXInner,
+ scrollY = scroll.sY,
+ barWidth = scroll.iBarWidth,
+ divHeader = $(settings.nScrollHead),
+ divHeaderStyle = divHeader[0].style,
+ divHeaderInner = divHeader.children('div'),
+ divHeaderInnerStyle = divHeaderInner[0].style,
+ divHeaderTable = divHeaderInner.children('table'),
+ divBodyEl = settings.nScrollBody,
+ divBody = $(divBodyEl),
+ divBodyStyle = divBodyEl.style,
+ divFooter = $(settings.nScrollFoot),
+ divFooterInner = divFooter.children('div'),
+ divFooterTable = divFooterInner.children('table'),
+ header = $(settings.nTHead),
+ table = $(settings.nTable),
+ tableEl = table[0],
+ tableStyle = tableEl.style,
+ footer = settings.nTFoot ? $(settings.nTFoot) : null,
+ browser = settings.oBrowser,
+ ie67 = browser.bScrollOversize,
+ dtHeaderCells = _pluck( settings.aoColumns, 'nTh' ),
+ headerTrgEls, footerTrgEls,
+ headerSrcEls, footerSrcEls,
+ headerCopy, footerCopy,
+ headerWidths=[], footerWidths=[],
+ headerContent=[], footerContent=[],
+ idx, correction, sanityWidth,
+ zeroOut = function(nSizer) {
+ var style = nSizer.style;
+ style.paddingTop = "0";
+ style.paddingBottom = "0";
+ style.borderTopWidth = "0";
+ style.borderBottomWidth = "0";
+ style.height = 0;
+ };
+
+ // If the scrollbar visibility has changed from the last draw, we need to
+ // adjust the column sizes as the table width will have changed to account
+ // for the scrollbar
+ var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
+
+ if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
+ settings.scrollBarVis = scrollBarVis;
+ _fnAdjustColumnSizing( settings );
+ return; // adjust column sizing will call this function again
+ }
+ else {
+ settings.scrollBarVis = scrollBarVis;
+ }
+
+ /*
+ * 1. Re-create the table inside the scrolling div
+ */
+
+ // Remove the old minimised thead and tfoot elements in the inner table
+ table.children('thead, tfoot').remove();
+
+ if ( footer ) {
+ footerCopy = footer.clone().prependTo( table );
+ footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
+ footerSrcEls = footerCopy.find('tr');
+ }
+
+ // Clone the current header and footer elements and then place it into the inner table
+ headerCopy = header.clone().prependTo( table );
+ headerTrgEls = header.find('tr'); // original header is in its own table
+ headerSrcEls = headerCopy.find('tr');
+ headerCopy.find('th, td').removeAttr('tabindex');
+
+
+ /*
+ * 2. Take live measurements from the DOM - do not alter the DOM itself!
+ */
+
+ // Remove old sizing and apply the calculated column widths
+ // Get the unique column headers in the newly created (cloned) header. We want to apply the
+ // calculated sizes to this header
+ if ( ! scrollX )
+ {
+ divBodyStyle.width = '100%';
+ divHeader[0].style.width = '100%';
+ }
+
+ $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
+ idx = _fnVisibleToColumnIndex( settings, i );
+ el.style.width = settings.aoColumns[idx].sWidth;
+ } );
+
+ if ( footer ) {
+ _fnApplyToChildren( function(n) {
+ n.style.width = "";
+ }, footerSrcEls );
+ }
+
+ // Size the table as a whole
+ sanityWidth = table.outerWidth();
+ if ( scrollX === "" ) {
+ // No x scrolling
+ tableStyle.width = "100%";
+
+ // IE7 will make the width of the table when 100% include the scrollbar
+ // - which is shouldn't. When there is a scrollbar we need to take this
+ // into account.
+ if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
+ divBody.css('overflow-y') == "scroll")
+ ) {
+ tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
+ }
+
+ // Recalculate the sanity width
+ sanityWidth = table.outerWidth();
+ }
+ else if ( scrollXInner !== "" ) {
+ // legacy x scroll inner has been given - use it
+ tableStyle.width = _fnStringToCss(scrollXInner);
+
+ // Recalculate the sanity width
+ sanityWidth = table.outerWidth();
+ }
+
+ // Hidden header should have zero height, so remove padding and borders. Then
+ // set the width based on the real headers
+
+ // Apply all styles in one pass
+ _fnApplyToChildren( zeroOut, headerSrcEls );
+
+ // Read all widths in next pass
+ _fnApplyToChildren( function(nSizer) {
+ headerContent.push( nSizer.innerHTML );
+ headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
+ }, headerSrcEls );
+
+ // Apply all widths in final pass
+ _fnApplyToChildren( function(nToSize, i) {
+ // Only apply widths to the DataTables detected header cells - this
+ // prevents complex headers from having contradictory sizes applied
+ if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
+ nToSize.style.width = headerWidths[i];
+ }
+ }, headerTrgEls );
+
+ $(headerSrcEls).height(0);
+
+ /* Same again with the footer if we have one */
+ if ( footer )
+ {
+ _fnApplyToChildren( zeroOut, footerSrcEls );
+
+ _fnApplyToChildren( function(nSizer) {
+ footerContent.push( nSizer.innerHTML );
+ footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
+ }, footerSrcEls );
+
+ _fnApplyToChildren( function(nToSize, i) {
+ nToSize.style.width = footerWidths[i];
+ }, footerTrgEls );
+
+ $(footerSrcEls).height(0);
+ }
+
+
+ /*
+ * 3. Apply the measurements
+ */
+
+ // "Hide" the header and footer that we used for the sizing. We need to keep
+ // the content of the cell so that the width applied to the header and body
+ // both match, but we want to hide it completely. We want to also fix their
+ // width to what they currently are
+ _fnApplyToChildren( function(nSizer, i) {
+ nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
+ nSizer.style.width = headerWidths[i];
+ }, headerSrcEls );
+
+ if ( footer )
+ {
+ _fnApplyToChildren( function(nSizer, i) {
+ nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>';
+ nSizer.style.width = footerWidths[i];
+ }, footerSrcEls );
+ }
+
+ // Sanity check that the table is of a sensible width. If not then we are going to get
+ // misalignment - try to prevent this by not allowing the table to shrink below its min width
+ if ( table.outerWidth() < sanityWidth )
+ {
+ // The min width depends upon if we have a vertical scrollbar visible or not */
+ correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
+ divBody.css('overflow-y') == "scroll")) ?
+ sanityWidth+barWidth :
+ sanityWidth;
+
+ // IE6/7 are a law unto themselves...
+ if ( ie67 && (divBodyEl.scrollHeight >
+ divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
+ ) {
+ tableStyle.width = _fnStringToCss( correction-barWidth );
+ }
+
+ // And give the user a warning that we've stopped the table getting too small
+ if ( scrollX === "" || scrollXInner !== "" ) {
+ _fnLog( settings, 1, 'Possible column misalignment', 6 );
+ }
+ }
+ else
+ {
+ correction = '100%';
+ }
+
+ // Apply to the container elements
+ divBodyStyle.width = _fnStringToCss( correction );
+ divHeaderStyle.width = _fnStringToCss( correction );
+
+ if ( footer ) {
+ settings.nScrollFoot.style.width = _fnStringToCss( correction );
+ }
+
+
+ /*
+ * 4. Clean up
+ */
+ if ( ! scrollY ) {
+ /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
+ * the scrollbar height from the visible display, rather than adding it on. We need to
+ * set the height in order to sort this. Don't want to do it in any other browsers.
+ */
+ if ( ie67 ) {
+ divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
+ }
+ }
+
+ /* Finally set the width's of the header and footer tables */
+ var iOuterWidth = table.outerWidth();
+ divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
+ divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
+
+ // Figure out if there are scrollbar present - if so then we need a the header and footer to
+ // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
+ var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
+ var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
+ divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
+
+ if ( footer ) {
+ divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
+ divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
+ divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
+ }
+
+ // Correct DOM ordering for colgroup - comes before the thead
+ table.children('colgroup').insertBefore( table.children('thead') );
+
+ /* Adjust the position of the header in case we loose the y-scrollbar */
+ divBody.scroll();
+
+ // If sorting or filtering has occurred, jump the scrolling back to the top
+ // only if we aren't holding the position
+ if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
+ divBodyEl.scrollTop = 0;
+ }
+ }
+
+
+
+ /**
+ * Apply a given function to the display child nodes of an element array (typically
+ * TD children of TR rows
+ * @param {function} fn Method to apply to the objects
+ * @param array {nodes} an1 List of elements to look through for display children
+ * @param array {nodes} an2 Another list (identical structure to the first) - optional
+ * @memberof DataTable#oApi
+ */
+ function _fnApplyToChildren( fn, an1, an2 )
+ {
+ var index=0, i=0, iLen=an1.length;
+ var nNode1, nNode2;
+
+ while ( i < iLen ) {
+ nNode1 = an1[i].firstChild;
+ nNode2 = an2 ? an2[i].firstChild : null;
+
+ while ( nNode1 ) {
+ if ( nNode1.nodeType === 1 ) {
+ if ( an2 ) {
+ fn( nNode1, nNode2, index );
+ }
+ else {
+ fn( nNode1, index );
+ }
+
+ index++;
+ }
+
+ nNode1 = nNode1.nextSibling;
+ nNode2 = an2 ? nNode2.nextSibling : null;
+ }
+
+ i++;
+ }
+ }
+
+
+
+ var __re_html_remove = /<.*?>/g;
+
+
+ /**
+ * Calculate the width of columns for the table
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnCalculateColumnWidths ( oSettings )
+ {
+ var
+ table = oSettings.nTable,
+ columns = oSettings.aoColumns,
+ scroll = oSettings.oScroll,
+ scrollY = scroll.sY,
+ scrollX = scroll.sX,
+ scrollXInner = scroll.sXInner,
+ columnCount = columns.length,
+ visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
+ headerCells = $('th', oSettings.nTHead),
+ tableWidthAttr = table.getAttribute('width'), // from DOM element
+ tableContainer = table.parentNode,
+ userInputs = false,
+ i, column, columnIdx, width, outerWidth,
+ browser = oSettings.oBrowser,
+ ie67 = browser.bScrollOversize;
+
+ var styleWidth = table.style.width;
+ if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
+ tableWidthAttr = styleWidth;
+ }
+
+ /* Convert any user input sizes into pixel sizes */
+ for ( i=0 ; i<visibleColumns.length ; i++ ) {
+ column = columns[ visibleColumns[i] ];
+
+ if ( column.sWidth !== null ) {
+ column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
+
+ userInputs = true;
+ }
+ }
+
+ /* If the number of columns in the DOM equals the number that we have to
+ * process in DataTables, then we can use the offsets that are created by
+ * the web- browser. No custom sizes can be set in order for this to happen,
+ * nor scrolling used
+ */
+ if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
+ columnCount == _fnVisbleColumns( oSettings ) &&
+ columnCount == headerCells.length
+ ) {
+ for ( i=0 ; i<columnCount ; i++ ) {
+ var colIdx = _fnVisibleToColumnIndex( oSettings, i );
+
+ if ( colIdx !== null ) {
+ columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
+ }
+ }
+ }
+ else
+ {
+ // Otherwise construct a single row, worst case, table with the widest
+ // node in the data, assign any user defined widths, then insert it into
+ // the DOM and allow the browser to do all the hard work of calculating
+ // table widths
+ var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
+ .css( 'visibility', 'hidden' )
+ .removeAttr( 'id' );
+
+ // Clean up the table body
+ tmpTable.find('tbody tr').remove();
+ var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
+
+ // Clone the table header and footer - we can't use the header / footer
+ // from the cloned table, since if scrolling is active, the table's
+ // real header and footer are contained in different table tags
+ tmpTable.find('thead, tfoot').remove();
+ tmpTable
+ .append( $(oSettings.nTHead).clone() )
+ .append( $(oSettings.nTFoot).clone() );
+
+ // Remove any assigned widths from the footer (from scrolling)
+ tmpTable.find('tfoot th, tfoot td').css('width', '');
+
+ // Apply custom sizing to the cloned header
+ headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
+
+ for ( i=0 ; i<visibleColumns.length ; i++ ) {
+ column = columns[ visibleColumns[i] ];
+
+ headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
+ _fnStringToCss( column.sWidthOrig ) :
+ '';
+
+ // For scrollX we need to force the column width otherwise the
+ // browser will collapse it. If this width is smaller than the
+ // width the column requires, then it will have no effect
+ if ( column.sWidthOrig && scrollX ) {
+ $( headerCells[i] ).append( $('<div/>').css( {
+ width: column.sWidthOrig,
+ margin: 0,
+ padding: 0,
+ border: 0,
+ height: 1
+ } ) );
+ }
+ }
+
+ // Find the widest cell for each column and put it into the table
+ if ( oSettings.aoData.length ) {
+ for ( i=0 ; i<visibleColumns.length ; i++ ) {
+ columnIdx = visibleColumns[i];
+ column = columns[ columnIdx ];
+
+ $( _fnGetWidestNode( oSettings, columnIdx ) )
+ .clone( false )
+ .append( column.sContentPadding )
+ .appendTo( tr );
+ }
+ }
+
+ // Tidy the temporary table - remove name attributes so there aren't
+ // duplicated in the dom (radio elements for example)
+ $('[name]', tmpTable).removeAttr('name');
+
+ // Table has been built, attach to the document so we can work with it.
+ // A holding element is used, positioned at the top of the container
+ // with minimal height, so it has no effect on if the container scrolls
+ // or not. Otherwise it might trigger scrolling when it actually isn't
+ // needed
+ var holder = $('<div/>').css( scrollX || scrollY ?
+ {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ height: 1,
+ right: 0,
+ overflow: 'hidden'
+ } :
+ {}
+ )
+ .append( tmpTable )
+ .appendTo( tableContainer );
+
+ // When scrolling (X or Y) we want to set the width of the table as
+ // appropriate. However, when not scrolling leave the table width as it
+ // is. This results in slightly different, but I think correct behaviour
+ if ( scrollX && scrollXInner ) {
+ tmpTable.width( scrollXInner );
+ }
+ else if ( scrollX ) {
+ tmpTable.css( 'width', 'auto' );
+ tmpTable.removeAttr('width');
+
+ // If there is no width attribute or style, then allow the table to
+ // collapse
+ if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
+ tmpTable.width( tableContainer.clientWidth );
+ }
+ }
+ else if ( scrollY ) {
+ tmpTable.width( tableContainer.clientWidth );
+ }
+ else if ( tableWidthAttr ) {
+ tmpTable.width( tableWidthAttr );
+ }
+
+ // Get the width of each column in the constructed table - we need to
+ // know the inner width (so it can be assigned to the other table's
+ // cells) and the outer width so we can calculate the full width of the
+ // table. This is safe since DataTables requires a unique cell for each
+ // column, but if ever a header can span multiple columns, this will
+ // need to be modified.
+ var total = 0;
+ for ( i=0 ; i<visibleColumns.length ; i++ ) {
+ var cell = $(headerCells[i]);
+ var border = cell.outerWidth() - cell.width();
+
+ // Use getBounding... where possible (not IE8-) because it can give
+ // sub-pixel accuracy, which we then want to round up!
+ var bounding = browser.bBounding ?
+ Math.ceil( headerCells[i].getBoundingClientRect().width ) :
+ cell.outerWidth();
+
+ // Total is tracked to remove any sub-pixel errors as the outerWidth
+ // of the table might not equal the total given here (IE!).
+ total += bounding;
+
+ // Width for each column to use
+ columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
+ }
+
+ table.style.width = _fnStringToCss( total );
+
+ // Finished with the table - ditch it
+ holder.remove();
+ }
+
+ // If there is a width attr, we want to attach an event listener which
+ // allows the table sizing to automatically adjust when the window is
+ // resized. Use the width attr rather than CSS, since we can't know if the
+ // CSS is a relative value or absolute - DOM read is always px.
+ if ( tableWidthAttr ) {
+ table.style.width = _fnStringToCss( tableWidthAttr );
+ }
+
+ if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
+ var bindResize = function () {
+ $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
+ _fnAdjustColumnSizing( oSettings );
+ } ) );
+ };
+
+ // IE6/7 will crash if we bind a resize event handler on page load.
+ // To be removed in 1.11 which drops IE6/7 support
+ if ( ie67 ) {
+ setTimeout( bindResize, 1000 );
+ }
+ else {
+ bindResize();
+ }
+
+ oSettings._reszEvt = true;
+ }
+ }
+
+
+ /**
+ * Throttle the calls to a function. Arguments and context are maintained for
+ * the throttled function
+ * @param {function} fn Function to be called
+ * @param {int} [freq=200] call frequency in mS
+ * @returns {function} wrapped function
+ * @memberof DataTable#oApi
+ */
+ var _fnThrottle = DataTable.util.throttle;
+
+
+ /**
+ * Convert a CSS unit width to pixels (e.g. 2em)
+ * @param {string} width width to be converted
+ * @param {node} parent parent to get the with for (required for relative widths) - optional
+ * @returns {int} width in pixels
+ * @memberof DataTable#oApi
+ */
+ function _fnConvertToWidth ( width, parent )
+ {
+ if ( ! width ) {
+ return 0;
+ }
+
+ var n = $('<div/>')
+ .css( 'width', _fnStringToCss( width ) )
+ .appendTo( parent || document.body );
+
+ var val = n[0].offsetWidth;
+ n.remove();
+
+ return val;
+ }
+
+
+ /**
+ * Get the widest node
+ * @param {object} settings dataTables settings object
+ * @param {int} colIdx column of interest
+ * @returns {node} widest table node
+ * @memberof DataTable#oApi
+ */
+ function _fnGetWidestNode( settings, colIdx )
+ {
+ var idx = _fnGetMaxLenString( settings, colIdx );
+ if ( idx < 0 ) {
+ return null;
+ }
+
+ var data = settings.aoData[ idx ];
+ return ! data.nTr ? // Might not have been created when deferred rendering
+ $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
+ data.anCells[ colIdx ];
+ }
+
+
+ /**
+ * Get the maximum strlen for each data column
+ * @param {object} settings dataTables settings object
+ * @param {int} colIdx column of interest
+ * @returns {string} max string length for each column
+ * @memberof DataTable#oApi
+ */
+ function _fnGetMaxLenString( settings, colIdx )
+ {
+ var s, max=-1, maxIdx = -1;
+
+ for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
+ s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
+ s = s.replace( __re_html_remove, '' );
+ s = s.replace( /&nbsp;/g, ' ' );
+
+ if ( s.length > max ) {
+ max = s.length;
+ maxIdx = i;
+ }
+ }
+
+ return maxIdx;
+ }
+
+
+ /**
+ * Append a CSS unit (only if required) to a string
+ * @param {string} value to css-ify
+ * @returns {string} value with css unit
+ * @memberof DataTable#oApi
+ */
+ function _fnStringToCss( s )
+ {
+ if ( s === null ) {
+ return '0px';
+ }
+
+ if ( typeof s == 'number' ) {
+ return s < 0 ?
+ '0px' :
+ s+'px';
+ }
+
+ // Check it has a unit character already
+ return s.match(/\d$/) ?
+ s+'px' :
+ s;
+ }
+
+
+
+ function _fnSortFlatten ( settings )
+ {
+ var
+ i, iLen, k, kLen,
+ aSort = [],
+ aiOrig = [],
+ aoColumns = settings.aoColumns,
+ aDataSort, iCol, sType, srcCol,
+ fixed = settings.aaSortingFixed,
+ fixedObj = $.isPlainObject( fixed ),
+ nestedSort = [],
+ add = function ( a ) {
+ if ( a.length && ! $.isArray( a[0] ) ) {
+ // 1D array
+ nestedSort.push( a );
+ }
+ else {
+ // 2D array
+ $.merge( nestedSort, a );
+ }
+ };
+
+ // Build the sort array, with pre-fix and post-fix options if they have been
+ // specified
+ if ( $.isArray( fixed ) ) {
+ add( fixed );
+ }
+
+ if ( fixedObj && fixed.pre ) {
+ add( fixed.pre );
+ }
+
+ add( settings.aaSorting );
+
+ if (fixedObj && fixed.post ) {
+ add( fixed.post );
+ }
+
+ for ( i=0 ; i<nestedSort.length ; i++ )
+ {
+ srcCol = nestedSort[i][0];
+ aDataSort = aoColumns[ srcCol ].aDataSort;
+
+ for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
+ {
+ iCol = aDataSort[k];
+ sType = aoColumns[ iCol ].sType || 'string';
+
+ if ( nestedSort[i]._idx === undefined ) {
+ nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
+ }
+
+ aSort.push( {
+ src: srcCol,
+ col: iCol,
+ dir: nestedSort[i][1],
+ index: nestedSort[i]._idx,
+ type: sType,
+ formatter: DataTable.ext.type.order[ sType+"-pre" ]
+ } );
+ }
+ }
+
+ return aSort;
+ }
+
+ /**
+ * Change the order of the table
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ * @todo This really needs split up!
+ */
+ function _fnSort ( oSettings )
+ {
+ var
+ i, ien, iLen, j, jLen, k, kLen,
+ sDataType, nTh,
+ aiOrig = [],
+ oExtSort = DataTable.ext.type.order,
+ aoData = oSettings.aoData,
+ aoColumns = oSettings.aoColumns,
+ aDataSort, data, iCol, sType, oSort,
+ formatters = 0,
+ sortCol,
+ displayMaster = oSettings.aiDisplayMaster,
+ aSort;
+
+ // Resolve any column types that are unknown due to addition or invalidation
+ // @todo Can this be moved into a 'data-ready' handler which is called when
+ // data is going to be used in the table?
+ _fnColumnTypes( oSettings );
+
+ aSort = _fnSortFlatten( oSettings );
+
+ for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
+ sortCol = aSort[i];
+
+ // Track if we can use the fast sort algorithm
+ if ( sortCol.formatter ) {
+ formatters++;
+ }
+
+ // Load the data needed for the sort, for each cell
+ _fnSortData( oSettings, sortCol.col );
+ }
+
+ /* No sorting required if server-side or no sorting array */
+ if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
+ {
+ // Create a value - key array of the current row positions such that we can use their
+ // current position during the sort, if values match, in order to perform stable sorting
+ for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
+ aiOrig[ displayMaster[i] ] = i;
+ }
+
+ /* Do the sort - here we want multi-column sorting based on a given data source (column)
+ * and sorting function (from oSort) in a certain direction. It's reasonably complex to
+ * follow on it's own, but this is what we want (example two column sorting):
+ * fnLocalSorting = function(a,b){
+ * var iTest;
+ * iTest = oSort['string-asc']('data11', 'data12');
+ * if (iTest !== 0)
+ * return iTest;
+ * iTest = oSort['numeric-desc']('data21', 'data22');
+ * if (iTest !== 0)
+ * return iTest;
+ * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
+ * }
+ * Basically we have a test for each sorting column, if the data in that column is equal,
+ * test the next column. If all columns match, then we use a numeric sort on the row
+ * positions in the original data array to provide a stable sort.
+ *
+ * Note - I know it seems excessive to have two sorting methods, but the first is around
+ * 15% faster, so the second is only maintained for backwards compatibility with sorting
+ * methods which do not have a pre-sort formatting function.
+ */
+ if ( formatters === aSort.length ) {
+ // All sort types have formatting functions
+ displayMaster.sort( function ( a, b ) {
+ var
+ x, y, k, test, sort,
+ len=aSort.length,
+ dataA = aoData[a]._aSortData,
+ dataB = aoData[b]._aSortData;
+
+ for ( k=0 ; k<len ; k++ ) {
+ sort = aSort[k];
+
+ x = dataA[ sort.col ];
+ y = dataB[ sort.col ];
+
+ test = x<y ? -1 : x>y ? 1 : 0;
+ if ( test !== 0 ) {
+ return sort.dir === 'asc' ? test : -test;
+ }
+ }
+
+ x = aiOrig[a];
+ y = aiOrig[b];
+ return x<y ? -1 : x>y ? 1 : 0;
+ } );
+ }
+ else {
+ // Depreciated - remove in 1.11 (providing a plug-in option)
+ // Not all sort types have formatting methods, so we have to call their sorting
+ // methods.
+ displayMaster.sort( function ( a, b ) {
+ var
+ x, y, k, l, test, sort, fn,
+ len=aSort.length,
+ dataA = aoData[a]._aSortData,
+ dataB = aoData[b]._aSortData;
+
+ for ( k=0 ; k<len ; k++ ) {
+ sort = aSort[k];
+
+ x = dataA[ sort.col ];
+ y = dataB[ sort.col ];
+
+ fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
+ test = fn( x, y );
+ if ( test !== 0 ) {
+ return test;
+ }
+ }
+
+ x = aiOrig[a];
+ y = aiOrig[b];
+ return x<y ? -1 : x>y ? 1 : 0;
+ } );
+ }
+ }
+
+ /* Tell the draw function that we have sorted the data */
+ oSettings.bSorted = true;
+ }
+
+
+ function _fnSortAria ( settings )
+ {
+ var label;
+ var nextSort;
+ var columns = settings.aoColumns;
+ var aSort = _fnSortFlatten( settings );
+ var oAria = settings.oLanguage.oAria;
+
+ // ARIA attributes - need to loop all columns, to update all (removing old
+ // attributes as needed)
+ for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
+ {
+ var col = columns[i];
+ var asSorting = col.asSorting;
+ var sTitle = col.sTitle.replace( /<.*?>/g, "" );
+ var th = col.nTh;
+
+ // IE7 is throwing an error when setting these properties with jQuery's
+ // attr() and removeAttr() methods...
+ th.removeAttribute('aria-sort');
+
+ /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
+ if ( col.bSortable ) {
+ if ( aSort.length > 0 && aSort[0].col == i ) {
+ th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
+ nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
+ }
+ else {
+ nextSort = asSorting[0];
+ }
+
+ label = sTitle + ( nextSort === "asc" ?
+ oAria.sSortAscending :
+ oAria.sSortDescending
+ );
+ }
+ else {
+ label = sTitle;
+ }
+
+ th.setAttribute('aria-label', label);
+ }
+ }
+
+
+ /**
+ * Function to run on user sort request
+ * @param {object} settings dataTables settings object
+ * @param {node} attachTo node to attach the handler to
+ * @param {int} colIdx column sorting index
+ * @param {boolean} [append=false] Append the requested sort to the existing
+ * sort if true (i.e. multi-column sort)
+ * @param {function} [callback] callback function
+ * @memberof DataTable#oApi
+ */
+ function _fnSortListener ( settings, colIdx, append, callback )
+ {
+ var col = settings.aoColumns[ colIdx ];
+ var sorting = settings.aaSorting;
+ var asSorting = col.asSorting;
+ var nextSortIdx;
+ var next = function ( a, overflow ) {
+ var idx = a._idx;
+ if ( idx === undefined ) {
+ idx = $.inArray( a[1], asSorting );
+ }
+
+ return idx+1 < asSorting.length ?
+ idx+1 :
+ overflow ?
+ null :
+ 0;
+ };
+
+ // Convert to 2D array if needed
+ if ( typeof sorting[0] === 'number' ) {
+ sorting = settings.aaSorting = [ sorting ];
+ }
+
+ // If appending the sort then we are multi-column sorting
+ if ( append && settings.oFeatures.bSortMulti ) {
+ // Are we already doing some kind of sort on this column?
+ var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
+
+ if ( sortIdx !== -1 ) {
+ // Yes, modify the sort
+ nextSortIdx = next( sorting[sortIdx], true );
+
+ if ( nextSortIdx === null && sorting.length === 1 ) {
+ nextSortIdx = 0; // can't remove sorting completely
+ }
+
+ if ( nextSortIdx === null ) {
+ sorting.splice( sortIdx, 1 );
+ }
+ else {
+ sorting[sortIdx][1] = asSorting[ nextSortIdx ];
+ sorting[sortIdx]._idx = nextSortIdx;
+ }
+ }
+ else {
+ // No sort on this column yet
+ sorting.push( [ colIdx, asSorting[0], 0 ] );
+ sorting[sorting.length-1]._idx = 0;
+ }
+ }
+ else if ( sorting.length && sorting[0][0] == colIdx ) {
+ // Single column - already sorting on this column, modify the sort
+ nextSortIdx = next( sorting[0] );
+
+ sorting.length = 1;
+ sorting[0][1] = asSorting[ nextSortIdx ];
+ sorting[0]._idx = nextSortIdx;
+ }
+ else {
+ // Single column - sort only on this column
+ sorting.length = 0;
+ sorting.push( [ colIdx, asSorting[0] ] );
+ sorting[0]._idx = 0;
+ }
+
+ // Run the sort by calling a full redraw
+ _fnReDraw( settings );
+
+ // callback used for async user interaction
+ if ( typeof callback == 'function' ) {
+ callback( settings );
+ }
+ }
+
+
+ /**
+ * Attach a sort handler (click) to a node
+ * @param {object} settings dataTables settings object
+ * @param {node} attachTo node to attach the handler to
+ * @param {int} colIdx column sorting index
+ * @param {function} [callback] callback function
+ * @memberof DataTable#oApi
+ */
+ function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
+ {
+ var col = settings.aoColumns[ colIdx ];
+
+ _fnBindAction( attachTo, {}, function (e) {
+ /* If the column is not sortable - don't to anything */
+ if ( col.bSortable === false ) {
+ return;
+ }
+
+ // If processing is enabled use a timeout to allow the processing
+ // display to be shown - otherwise to it synchronously
+ if ( settings.oFeatures.bProcessing ) {
+ _fnProcessingDisplay( settings, true );
+
+ setTimeout( function() {
+ _fnSortListener( settings, colIdx, e.shiftKey, callback );
+
+ // In server-side processing, the draw callback will remove the
+ // processing display
+ if ( _fnDataSource( settings ) !== 'ssp' ) {
+ _fnProcessingDisplay( settings, false );
+ }
+ }, 0 );
+ }
+ else {
+ _fnSortListener( settings, colIdx, e.shiftKey, callback );
+ }
+ } );
+ }
+
+
+ /**
+ * Set the sorting classes on table's body, Note: it is safe to call this function
+ * when bSort and bSortClasses are false
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnSortingClasses( settings )
+ {
+ var oldSort = settings.aLastSort;
+ var sortClass = settings.oClasses.sSortColumn;
+ var sort = _fnSortFlatten( settings );
+ var features = settings.oFeatures;
+ var i, ien, colIdx;
+
+ if ( features.bSort && features.bSortClasses ) {
+ // Remove old sorting classes
+ for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
+ colIdx = oldSort[i].src;
+
+ // Remove column sorting
+ $( _pluck( settings.aoData, 'anCells', colIdx ) )
+ .removeClass( sortClass + (i<2 ? i+1 : 3) );
+ }
+
+ // Add new column sorting
+ for ( i=0, ien=sort.length ; i<ien ; i++ ) {
+ colIdx = sort[i].src;
+
+ $( _pluck( settings.aoData, 'anCells', colIdx ) )
+ .addClass( sortClass + (i<2 ? i+1 : 3) );
+ }
+ }
+
+ settings.aLastSort = sort;
+ }
+
+
+ // Get the data to sort a column, be it from cache, fresh (populating the
+ // cache), or from a sort formatter
+ function _fnSortData( settings, idx )
+ {
+ // Custom sorting function - provided by the sort data type
+ var column = settings.aoColumns[ idx ];
+ var customSort = DataTable.ext.order[ column.sSortDataType ];
+ var customData;
+
+ if ( customSort ) {
+ customData = customSort.call( settings.oInstance, settings, idx,
+ _fnColumnIndexToVisible( settings, idx )
+ );
+ }
+
+ // Use / populate cache
+ var row, cellData;
+ var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
+
+ for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
+ row = settings.aoData[i];
+
+ if ( ! row._aSortData ) {
+ row._aSortData = [];
+ }
+
+ if ( ! row._aSortData[idx] || customSort ) {
+ cellData = customSort ?
+ customData[i] : // If there was a custom sort function, use data from there
+ _fnGetCellData( settings, i, idx, 'sort' );
+
+ row._aSortData[ idx ] = formatter ?
+ formatter( cellData ) :
+ cellData;
+ }
+ }
+ }
+
+
+
+ /**
+ * Save the state of a table
+ * @param {object} oSettings dataTables settings object
+ * @memberof DataTable#oApi
+ */
+ function _fnSaveState ( settings )
+ {
+ if ( !settings.oFeatures.bStateSave || settings.bDestroying )
+ {
+ return;
+ }
+
+ /* Store the interesting variables */
+ var state = {
+ time: +new Date(),
+ start: settings._iDisplayStart,
+ length: settings._iDisplayLength,
+ order: $.extend( true, [], settings.aaSorting ),
+ search: _fnSearchToCamel( settings.oPreviousSearch ),
+ columns: $.map( settings.aoColumns, function ( col, i ) {
+ return {
+ visible: col.bVisible,
+ search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
+ };
+ } )
+ };
+
+ _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
+
+ settings.oSavedState = state;
+ settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
+ }
+
+
+ /**
+ * Attempt to load a saved table state
+ * @param {object} oSettings dataTables settings object
+ * @param {object} oInit DataTables init object so we can override settings
+ * @param {function} callback Callback to execute when the state has been loaded
+ * @memberof DataTable#oApi
+ */
+ function _fnLoadState ( settings, oInit, callback )
+ {
+ var i, ien;
+ var columns = settings.aoColumns;
+ var loaded = function ( s ) {
+ if ( ! s || ! s.time ) {
+ callback();
+ return;
+ }
+
+ // Allow custom and plug-in manipulation functions to alter the saved data set and
+ // cancelling of loading by returning false
+ var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
+ if ( $.inArray( false, abStateLoad ) !== -1 ) {
+ callback();
+ return;
+ }
+
+ // Reject old data
+ var duration = settings.iStateDuration;
+ if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
+ callback();
+ return;
+ }
+
+ // Number of columns have changed - all bets are off, no restore of settings
+ if ( s.columns && columns.length !== s.columns.length ) {
+ callback();
+ return;
+ }
+
+ // Store the saved state so it might be accessed at any time
+ settings.oLoadedState = $.extend( true, {}, s );
+
+ // Restore key features - todo - for 1.11 this needs to be done by
+ // subscribed events
+ if ( s.start !== undefined ) {
+ settings._iDisplayStart = s.start;
+ settings.iInitDisplayStart = s.start;
+ }
+ if ( s.length !== undefined ) {
+ settings._iDisplayLength = s.length;
+ }
+
+ // Order
+ if ( s.order !== undefined ) {
+ settings.aaSorting = [];
+ $.each( s.order, function ( i, col ) {
+ settings.aaSorting.push( col[0] >= columns.length ?
+ [ 0, col[1] ] :
+ col
+ );
+ } );
+ }
+
+ // Search
+ if ( s.search !== undefined ) {
+ $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
+ }
+
+ // Columns
+ //
+ if ( s.columns ) {
+ for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
+ var col = s.columns[i];
+
+ // Visibility
+ if ( col.visible !== undefined ) {
+ columns[i].bVisible = col.visible;
+ }
+
+ // Search
+ if ( col.search !== undefined ) {
+ $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
+ }
+ }
+ }
+
+ _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
+ callback();
+ }
+
+ if ( ! settings.oFeatures.bStateSave ) {
+ callback();
+ return;
+ }
+
+ var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
+
+ if ( state !== undefined ) {
+ loaded( state );
+ }
+ // otherwise, wait for the loaded callback to be executed
+ }
+
+
+ /**
+ * Return the settings object for a particular table
+ * @param {node} table table we are using as a dataTable
+ * @returns {object} Settings object - or null if not found
+ * @memberof DataTable#oApi
+ */
+ function _fnSettingsFromNode ( table )
+ {
+ var settings = DataTable.settings;
+ var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
+
+ return idx !== -1 ?
+ settings[ idx ] :
+ null;
+ }
+
+
+ /**
+ * Log an error message
+ * @param {object} settings dataTables settings object
+ * @param {int} level log error messages, or display them to the user
+ * @param {string} msg error message
+ * @param {int} tn Technical note id to get more information about the error.
+ * @memberof DataTable#oApi
+ */
+ function _fnLog( settings, level, msg, tn )
+ {
+ msg = 'DataTables warning: '+
+ (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
+
+ if ( tn ) {
+ msg += '. For more information about this error, please see '+
+ 'http://datatables.net/tn/'+tn;
+ }
+
+ if ( ! level ) {
+ // Backwards compatibility pre 1.10
+ var ext = DataTable.ext;
+ var type = ext.sErrMode || ext.errMode;
+
+ if ( settings ) {
+ _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
+ }
+
+ if ( type == 'alert' ) {
+ alert( msg );
+ }
+ else if ( type == 'throw' ) {
+ throw new Error(msg);
+ }
+ else if ( typeof type == 'function' ) {
+ type( settings, tn, msg );
+ }
+ }
+ else if ( window.console && console.log ) {
+ console.log( msg );
+ }
+ }
+
+
+ /**
+ * See if a property is defined on one object, if so assign it to the other object
+ * @param {object} ret target object
+ * @param {object} src source object
+ * @param {string} name property
+ * @param {string} [mappedName] name to map too - optional, name used if not given
+ * @memberof DataTable#oApi
+ */
+ function _fnMap( ret, src, name, mappedName )
+ {
+ if ( $.isArray( name ) ) {
+ $.each( name, function (i, val) {
+ if ( $.isArray( val ) ) {
+ _fnMap( ret, src, val[0], val[1] );
+ }
+ else {
+ _fnMap( ret, src, val );
+ }
+ } );
+
+ return;
+ }
+
+ if ( mappedName === undefined ) {
+ mappedName = name;
+ }
+
+ if ( src[name] !== undefined ) {
+ ret[mappedName] = src[name];
+ }
+ }
+
+
+ /**
+ * Extend objects - very similar to jQuery.extend, but deep copy objects, and
+ * shallow copy arrays. The reason we need to do this, is that we don't want to
+ * deep copy array init values (such as aaSorting) since the dev wouldn't be
+ * able to override them, but we do want to deep copy arrays.
+ * @param {object} out Object to extend
+ * @param {object} extender Object from which the properties will be applied to
+ * out
+ * @param {boolean} breakRefs If true, then arrays will be sliced to take an
+ * independent copy with the exception of the `data` or `aaData` parameters
+ * if they are present. This is so you can pass in a collection to
+ * DataTables and have that used as your data source without breaking the
+ * references
+ * @returns {object} out Reference, just for convenience - out === the return.
+ * @memberof DataTable#oApi
+ * @todo This doesn't take account of arrays inside the deep copied objects.
+ */
+ function _fnExtend( out, extender, breakRefs )
+ {
+ var val;
+
+ for ( var prop in extender ) {
+ if ( extender.hasOwnProperty(prop) ) {
+ val = extender[prop];
+
+ if ( $.isPlainObject( val ) ) {
+ if ( ! $.isPlainObject( out[prop] ) ) {
+ out[prop] = {};
+ }
+ $.extend( true, out[prop], val );
+ }
+ else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
+ out[prop] = val.slice();
+ }
+ else {
+ out[prop] = val;
+ }
+ }
+ }
+
+ return out;
+ }
+
+
+ /**
+ * Bind an event handers to allow a click or return key to activate the callback.
+ * This is good for accessibility since a return on the keyboard will have the
+ * same effect as a click, if the element has focus.
+ * @param {element} n Element to bind the action to
+ * @param {object} oData Data object to pass to the triggered function
+ * @param {function} fn Callback function for when the event is triggered
+ * @memberof DataTable#oApi
+ */
+ function _fnBindAction( n, oData, fn )
+ {
+ $(n)
+ .on( 'click.DT', oData, function (e) {
+ n.blur(); // Remove focus outline for mouse users
+ fn(e);
+ } )
+ .on( 'keypress.DT', oData, function (e){
+ if ( e.which === 13 ) {
+ e.preventDefault();
+ fn(e);
+ }
+ } )
+ .on( 'selectstart.DT', function () {
+ /* Take the brutal approach to cancelling text selection */
+ return false;
+ } );
+ }
+
+
+ /**
+ * Register a callback function. Easily allows a callback function to be added to
+ * an array store of callback functions that can then all be called together.
+ * @param {object} oSettings dataTables settings object
+ * @param {string} sStore Name of the array storage for the callbacks in oSettings
+ * @param {function} fn Function to be called back
+ * @param {string} sName Identifying name for the callback (i.e. a label)
+ * @memberof DataTable#oApi
+ */
+ function _fnCallbackReg( oSettings, sStore, fn, sName )
+ {
+ if ( fn )
+ {
+ oSettings[sStore].push( {
+ "fn": fn,
+ "sName": sName
+ } );
+ }
+ }
+
+
+ /**
+ * Fire callback functions and trigger events. Note that the loop over the
+ * callback array store is done backwards! Further note that you do not want to
+ * fire off triggers in time sensitive applications (for example cell creation)
+ * as its slow.
+ * @param {object} settings dataTables settings object
+ * @param {string} callbackArr Name of the array storage for the callbacks in
+ * oSettings
+ * @param {string} eventName Name of the jQuery custom event to trigger. If
+ * null no trigger is fired
+ * @param {array} args Array of arguments to pass to the callback function /
+ * trigger
+ * @memberof DataTable#oApi
+ */
+ function _fnCallbackFire( settings, callbackArr, eventName, args )
+ {
+ var ret = [];
+
+ if ( callbackArr ) {
+ ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
+ return val.fn.apply( settings.oInstance, args );
+ } );
+ }
+
+ if ( eventName !== null ) {
+ var e = $.Event( eventName+'.dt' );
+
+ $(settings.nTable).trigger( e, args );
+
+ ret.push( e.result );
+ }
+
+ return ret;
+ }
+
+
+ function _fnLengthOverflow ( settings )
+ {
+ var
+ start = settings._iDisplayStart,
+ end = settings.fnDisplayEnd(),
+ len = settings._iDisplayLength;
+
+ /* If we have space to show extra rows (backing up from the end point - then do so */
+ if ( start >= end )
+ {
+ start = end - len;
+ }
+
+ // Keep the start record on the current page
+ start -= (start % len);
+
+ if ( len === -1 || start < 0 )
+ {
+ start = 0;
+ }
+
+ settings._iDisplayStart = start;
+ }
+
+
+ function _fnRenderer( settings, type )
+ {
+ var renderer = settings.renderer;
+ var host = DataTable.ext.renderer[type];
+
+ if ( $.isPlainObject( renderer ) && renderer[type] ) {
+ // Specific renderer for this type. If available use it, otherwise use
+ // the default.
+ return host[renderer[type]] || host._;
+ }
+ else if ( typeof renderer === 'string' ) {
+ // Common renderer - if there is one available for this type use it,
+ // otherwise use the default
+ return host[renderer] || host._;
+ }
+
+ // Use the default
+ return host._;
+ }
+
+
+ /**
+ * Detect the data source being used for the table. Used to simplify the code
+ * a little (ajax) and to make it compress a little smaller.
+ *
+ * @param {object} settings dataTables settings object
+ * @returns {string} Data source
+ * @memberof DataTable#oApi
+ */
+ function _fnDataSource ( settings )
+ {
+ if ( settings.oFeatures.bServerSide ) {
+ return 'ssp';
+ }
+ else if ( settings.ajax || settings.sAjaxSource ) {
+ return 'ajax';
+ }
+ return 'dom';
+ }
+
+
+
+
+ /**
+ * Computed structure of the DataTables API, defined by the options passed to
+ * `DataTable.Api.register()` when building the API.
+ *
+ * The structure is built in order to speed creation and extension of the Api
+ * objects since the extensions are effectively pre-parsed.
+ *
+ * The array is an array of objects with the following structure, where this
+ * base array represents the Api prototype base:
+ *
+ * [
+ * {
+ * name: 'data' -- string - Property name
+ * val: function () {}, -- function - Api method (or undefined if just an object
+ * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
+ * propExt: [ ... ] -- array - Array of Api object definitions to extend the property
+ * },
+ * {
+ * name: 'row'
+ * val: {},
+ * methodExt: [ ... ],
+ * propExt: [
+ * {
+ * name: 'data'
+ * val: function () {},
+ * methodExt: [ ... ],
+ * propExt: [ ... ]
+ * },
+ * ...
+ * ]
+ * }
+ * ]
+ *
+ * @type {Array}
+ * @ignore
+ */
+ var __apiStruct = [];
+
+
+ /**
+ * `Array.prototype` reference.
+ *
+ * @type object
+ * @ignore
+ */
+ var __arrayProto = Array.prototype;
+
+
+ /**
+ * Abstraction for `context` parameter of the `Api` constructor to allow it to
+ * take several different forms for ease of use.
+ *
+ * Each of the input parameter types will be converted to a DataTables settings
+ * object where possible.
+ *
+ * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one
+ * of:
+ *
+ * * `string` - jQuery selector. Any DataTables' matching the given selector
+ * with be found and used.
+ * * `node` - `TABLE` node which has already been formed into a DataTable.
+ * * `jQuery` - A jQuery object of `TABLE` nodes.
+ * * `object` - DataTables settings object
+ * * `DataTables.Api` - API instance
+ * @return {array|null} Matching DataTables settings objects. `null` or
+ * `undefined` is returned if no matching DataTable is found.
+ * @ignore
+ */
+ var _toSettings = function ( mixed )
+ {
+ var idx, jq;
+ var settings = DataTable.settings;
+ var tables = $.map( settings, function (el, i) {
+ return el.nTable;
+ } );
+
+ if ( ! mixed ) {
+ return [];
+ }
+ else if ( mixed.nTable && mixed.oApi ) {
+ // DataTables settings object
+ return [ mixed ];
+ }
+ else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
+ // Table node
+ idx = $.inArray( mixed, tables );
+ return idx !== -1 ? [ settings[idx] ] : null;
+ }
+ else if ( mixed && typeof mixed.settings === 'function' ) {
+ return mixed.settings().toArray();
+ }
+ else if ( typeof mixed === 'string' ) {
+ // jQuery selector
+ jq = $(mixed);
+ }
+ else if ( mixed instanceof $ ) {
+ // jQuery object (also DataTables instance)
+ jq = mixed;
+ }
+
+ if ( jq ) {
+ return jq.map( function(i) {
+ idx = $.inArray( this, tables );
+ return idx !== -1 ? settings[idx] : null;
+ } ).toArray();
+ }
+ };
+
+
+ /**
+ * DataTables API class - used to control and interface with one or more
+ * DataTables enhanced tables.
+ *
+ * The API class is heavily based on jQuery, presenting a chainable interface
+ * that you can use to interact with tables. Each instance of the API class has
+ * a "context" - i.e. the tables that it will operate on. This could be a single
+ * table, all tables on a page or a sub-set thereof.
+ *
+ * Additionally the API is designed to allow you to easily work with the data in
+ * the tables, retrieving and manipulating it as required. This is done by
+ * presenting the API class as an array like interface. The contents of the
+ * array depend upon the actions requested by each method (for example
+ * `rows().nodes()` will return an array of nodes, while `rows().data()` will
+ * return an array of objects or arrays depending upon your table's
+ * configuration). The API object has a number of array like methods (`push`,
+ * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
+ * `unique` etc) to assist your working with the data held in a table.
+ *
+ * Most methods (those which return an Api instance) are chainable, which means
+ * the return from a method call also has all of the methods available that the
+ * top level object had. For example, these two calls are equivalent:
+ *
+ * // Not chained
+ * api.row.add( {...} );
+ * api.draw();
+ *
+ * // Chained
+ * api.row.add( {...} ).draw();
+ *
+ * @class DataTable.Api
+ * @param {array|object|string|jQuery} context DataTable identifier. This is
+ * used to define which DataTables enhanced tables this API will operate on.
+ * Can be one of:
+ *
+ * * `string` - jQuery selector. Any DataTables' matching the given selector
+ * with be found and used.
+ * * `node` - `TABLE` node which has already been formed into a DataTable.
+ * * `jQuery` - A jQuery object of `TABLE` nodes.
+ * * `object` - DataTables settings object
+ * @param {array} [data] Data to initialise the Api instance with.
+ *
+ * @example
+ * // Direct initialisation during DataTables construction
+ * var api = $('#example').DataTable();
+ *
+ * @example
+ * // Initialisation using a DataTables jQuery object
+ * var api = $('#example').dataTable().api();
+ *
+ * @example
+ * // Initialisation as a constructor
+ * var api = new $.fn.DataTable.Api( 'table.dataTable' );
+ */
+ _Api = function ( context, data )
+ {
+ if ( ! (this instanceof _Api) ) {
+ return new _Api( context, data );
+ }
+
+ var settings = [];
+ var ctxSettings = function ( o ) {
+ var a = _toSettings( o );
+ if ( a ) {
+ settings = settings.concat( a );
+ }
+ };
+
+ if ( $.isArray( context ) ) {
+ for ( var i=0, ien=context.length ; i<ien ; i++ ) {
+ ctxSettings( context[i] );
+ }
+ }
+ else {
+ ctxSettings( context );
+ }
+
+ // Remove duplicates
+ this.context = _unique( settings );
+
+ // Initial data
+ if ( data ) {
+ $.merge( this, data );
+ }
+
+ // selector
+ this.selector = {
+ rows: null,
+ cols: null,
+ opts: null
+ };
+
+ _Api.extend( this, this, __apiStruct );
+ };
+
+ DataTable.Api = _Api;
+
+ // Don't destroy the existing prototype, just extend it. Required for jQuery 2's
+ // isPlainObject.
+ $.extend( _Api.prototype, {
+ any: function ()
+ {
+ return this.count() !== 0;
+ },
+
+
+ concat: __arrayProto.concat,
+
+
+ context: [], // array of table settings objects
+
+
+ count: function ()
+ {
+ return this.flatten().length;
+ },
+
+
+ each: function ( fn )
+ {
+ for ( var i=0, ien=this.length ; i<ien; i++ ) {
+ fn.call( this, this[i], i, this );
+ }
+
+ return this;
+ },
+
+
+ eq: function ( idx )
+ {
+ var ctx = this.context;
+
+ return ctx.length > idx ?
+ new _Api( ctx[idx], this[idx] ) :
+ null;
+ },
+
+
+ filter: function ( fn )
+ {
+ var a = [];
+
+ if ( __arrayProto.filter ) {
+ a = __arrayProto.filter.call( this, fn, this );
+ }
+ else {
+ // Compatibility for browsers without EMCA-252-5 (JS 1.6)
+ for ( var i=0, ien=this.length ; i<ien ; i++ ) {
+ if ( fn.call( this, this[i], i, this ) ) {
+ a.push( this[i] );
+ }
+ }
+ }
+
+ return new _Api( this.context, a );
+ },
+
+
+ flatten: function ()
+ {
+ var a = [];
+ return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
+ },
+
+
+ join: __arrayProto.join,
+
+
+ indexOf: __arrayProto.indexOf || function (obj, start)
+ {
+ for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
+ if ( this[i] === obj ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ iterator: function ( flatten, type, fn, alwaysNew ) {
+ var
+ a = [], ret,
+ i, ien, j, jen,
+ context = this.context,
+ rows, items, item,
+ selector = this.selector;
+
+ // Argument shifting
+ if ( typeof flatten === 'string' ) {
+ alwaysNew = fn;
+ fn = type;
+ type = flatten;
+ flatten = false;
+ }
+
+ for ( i=0, ien=context.length ; i<ien ; i++ ) {
+ var apiInst = new _Api( context[i] );
+
+ if ( type === 'table' ) {
+ ret = fn.call( apiInst, context[i], i );
+
+ if ( ret !== undefined ) {
+ a.push( ret );
+ }
+ }
+ else if ( type === 'columns' || type === 'rows' ) {
+ // this has same length as context - one entry for each table
+ ret = fn.call( apiInst, context[i], this[i], i );
+
+ if ( ret !== undefined ) {
+ a.push( ret );
+ }
+ }
+ else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
+ // columns and rows share the same structure.
+ // 'this' is an array of column indexes for each context
+ items = this[i];
+
+ if ( type === 'column-rows' ) {
+ rows = _selector_row_indexes( context[i], selector.opts );
+ }
+
+ for ( j=0, jen=items.length ; j<jen ; j++ ) {
+ item = items[j];
+
+ if ( type === 'cell' ) {
+ ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
+ }
+ else {
+ ret = fn.call( apiInst, context[i], item, i, j, rows );
+ }
+
+ if ( ret !== undefined ) {
+ a.push( ret );
+ }
+ }
+ }
+ }
+
+ if ( a.length || alwaysNew ) {
+ var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
+ var apiSelector = api.selector;
+ apiSelector.rows = selector.rows;
+ apiSelector.cols = selector.cols;
+ apiSelector.opts = selector.opts;
+ return api;
+ }
+ return this;
+ },
+
+
+ lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
+ {
+ // Bit cheeky...
+ return this.indexOf.apply( this.toArray.reverse(), arguments );
+ },
+
+
+ length: 0,
+
+
+ map: function ( fn )
+ {
+ var a = [];
+
+ if ( __arrayProto.map ) {
+ a = __arrayProto.map.call( this, fn, this );
+ }
+ else {
+ // Compatibility for browsers without EMCA-252-5 (JS 1.6)
+ for ( var i=0, ien=this.length ; i<ien ; i++ ) {
+ a.push( fn.call( this, this[i], i ) );
+ }
+ }
+
+ return new _Api( this.context, a );
+ },
+
+
+ pluck: function ( prop )
+ {
+ return this.map( function ( el ) {
+ return el[ prop ];
+ } );
+ },
+
+ pop: __arrayProto.pop,
+
+
+ push: __arrayProto.push,
+
+
+ // Does not return an API instance
+ reduce: __arrayProto.reduce || function ( fn, init )
+ {
+ return _fnReduce( this, fn, init, 0, this.length, 1 );
+ },
+
+
+ reduceRight: __arrayProto.reduceRight || function ( fn, init )
+ {
+ return _fnReduce( this, fn, init, this.length-1, -1, -1 );
+ },
+
+
+ reverse: __arrayProto.reverse,
+
+
+ // Object with rows, columns and opts
+ selector: null,
+
+
+ shift: __arrayProto.shift,
+
+
+ slice: function () {
+ return new _Api( this.context, this );
+ },
+
+
+ sort: __arrayProto.sort, // ? name - order?
+
+
+ splice: __arrayProto.splice,
+
+
+ toArray: function ()
+ {
+ return __arrayProto.slice.call( this );
+ },
+
+
+ to$: function ()
+ {
+ return $( this );
+ },
+
+
+ toJQuery: function ()
+ {
+ return $( this );
+ },
+
+
+ unique: function ()
+ {
+ return new _Api( this.context, _unique(this) );
+ },
+
+
+ unshift: __arrayProto.unshift
+ } );
+
+
+ _Api.extend = function ( scope, obj, ext )
+ {
+ // Only extend API instances and static properties of the API
+ if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
+ return;
+ }
+
+ var
+ i, ien,
+ j, jen,
+ struct, inner,
+ methodScoping = function ( scope, fn, struc ) {
+ return function () {
+ var ret = fn.apply( scope, arguments );
+
+ // Method extension
+ _Api.extend( ret, ret, struc.methodExt );
+ return ret;
+ };
+ };
+
+ for ( i=0, ien=ext.length ; i<ien ; i++ ) {
+ struct = ext[i];
+
+ // Value
+ obj[ struct.name ] = typeof struct.val === 'function' ?
+ methodScoping( scope, struct.val, struct ) :
+ $.isPlainObject( struct.val ) ?
+ {} :
+ struct.val;
+
+ obj[ struct.name ].__dt_wrapper = true;
+
+ // Property extension
+ _Api.extend( scope, obj[ struct.name ], struct.propExt );
+ }
+ };
+
+
+ // @todo - Is there need for an augment function?
+ // _Api.augment = function ( inst, name )
+ // {
+ // // Find src object in the structure from the name
+ // var parts = name.split('.');
+
+ // _Api.extend( inst, obj );
+ // };
+
+
+ // [
+ // {
+ // name: 'data' -- string - Property name
+ // val: function () {}, -- function - Api method (or undefined if just an object
+ // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result
+ // propExt: [ ... ] -- array - Array of Api object definitions to extend the property
+ // },
+ // {
+ // name: 'row'
+ // val: {},
+ // methodExt: [ ... ],
+ // propExt: [
+ // {
+ // name: 'data'
+ // val: function () {},
+ // methodExt: [ ... ],
+ // propExt: [ ... ]
+ // },
+ // ...
+ // ]
+ // }
+ // ]
+
+ _Api.register = _api_register = function ( name, val )
+ {
+ if ( $.isArray( name ) ) {
+ for ( var j=0, jen=name.length ; j<jen ; j++ ) {
+ _Api.register( name[j], val );
+ }
+ return;
+ }
+
+ var
+ i, ien,
+ heir = name.split('.'),
+ struct = __apiStruct,
+ key, method;
+
+ var find = function ( src, name ) {
+ for ( var i=0, ien=src.length ; i<ien ; i++ ) {
+ if ( src[i].name === name ) {
+ return src[i];
+ }
+ }
+ return null;
+ };
+
+ for ( i=0, ien=heir.length ; i<ien ; i++ ) {
+ method = heir[i].indexOf('()') !== -1;
+ key = method ?
+ heir[i].replace('()', '') :
+ heir[i];
+
+ var src = find( struct, key );
+ if ( ! src ) {
+ src = {
+ name: key,
+ val: {},
+ methodExt: [],
+ propExt: []
+ };
+ struct.push( src );
+ }
+
+ if ( i === ien-1 ) {
+ src.val = val;
+ }
+ else {
+ struct = method ?
+ src.methodExt :
+ src.propExt;
+ }
+ }
+ };
+
+
+ _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
+ _Api.register( pluralName, val );
+
+ _Api.register( singularName, function () {
+ var ret = val.apply( this, arguments );
+
+ if ( ret === this ) {
+ // Returned item is the API instance that was passed in, return it
+ return this;
+ }
+ else if ( ret instanceof _Api ) {
+ // New API instance returned, want the value from the first item
+ // in the returned array for the singular result.
+ return ret.length ?
+ $.isArray( ret[0] ) ?
+ new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
+ ret[0] :
+ undefined;
+ }
+
+ // Non-API return - just fire it back
+ return ret;
+ } );
+ };
+
+
+ /**
+ * Selector for HTML tables. Apply the given selector to the give array of
+ * DataTables settings objects.
+ *
+ * @param {string|integer} [selector] jQuery selector string or integer
+ * @param {array} Array of DataTables settings objects to be filtered
+ * @return {array}
+ * @ignore
+ */
+ var __table_selector = function ( selector, a )
+ {
+ // Integer is used to pick out a table by index
+ if ( typeof selector === 'number' ) {
+ return [ a[ selector ] ];
+ }
+
+ // Perform a jQuery selector on the table nodes
+ var nodes = $.map( a, function (el, i) {
+ return el.nTable;
+ } );
+
+ return $(nodes)
+ .filter( selector )
+ .map( function (i) {
+ // Need to translate back from the table node to the settings
+ var idx = $.inArray( this, nodes );
+ return a[ idx ];
+ } )
+ .toArray();
+ };
+
+
+
+ /**
+ * Context selector for the API's context (i.e. the tables the API instance
+ * refers to.
+ *
+ * @name DataTable.Api#tables
+ * @param {string|integer} [selector] Selector to pick which tables the iterator
+ * should operate on. If not given, all tables in the current context are
+ * used. This can be given as a jQuery selector (for example `':gt(0)'`) to
+ * select multiple tables or as an integer to select a single table.
+ * @returns {DataTable.Api} Returns a new API instance if a selector is given.
+ */
+ _api_register( 'tables()', function ( selector ) {
+ // A new instance is created if there was a selector specified
+ return selector ?
+ new _Api( __table_selector( selector, this.context ) ) :
+ this;
+ } );
+
+
+ _api_register( 'table()', function ( selector ) {
+ var tables = this.tables( selector );
+ var ctx = tables.context;
+
+ // Truncate to the first matched table
+ return ctx.length ?
+ new _Api( ctx[0] ) :
+ tables;
+ } );
+
+
+ _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
+ return this.iterator( 'table', function ( ctx ) {
+ return ctx.nTable;
+ }, 1 );
+ } );
+
+
+ _api_registerPlural( 'tables().body()', 'table().body()' , function () {
+ return this.iterator( 'table', function ( ctx ) {
+ return ctx.nTBody;
+ }, 1 );
+ } );
+
+
+ _api_registerPlural( 'tables().header()', 'table().header()' , function () {
+ return this.iterator( 'table', function ( ctx ) {
+ return ctx.nTHead;
+ }, 1 );
+ } );
+
+
+ _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
+ return this.iterator( 'table', function ( ctx ) {
+ return ctx.nTFoot;
+ }, 1 );
+ } );
+
+
+ _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
+ return this.iterator( 'table', function ( ctx ) {
+ return ctx.nTableWrapper;
+ }, 1 );
+ } );
+
+
+
+ /**
+ * Redraw the tables in the current context.
+ */
+ _api_register( 'draw()', function ( paging ) {
+ return this.iterator( 'table', function ( settings ) {
+ if ( paging === 'page' ) {
+ _fnDraw( settings );
+ }
+ else {
+ if ( typeof paging === 'string' ) {
+ paging = paging === 'full-hold' ?
+ false :
+ true;
+ }
+
+ _fnReDraw( settings, paging===false );
+ }
+ } );
+ } );
+
+
+
+ /**
+ * Get the current page index.
+ *
+ * @return {integer} Current page index (zero based)
+ *//**
+ * Set the current page.
+ *
+ * Note that if you attempt to show a page which does not exist, DataTables will
+ * not throw an error, but rather reset the paging.
+ *
+ * @param {integer|string} action The paging action to take. This can be one of:
+ * * `integer` - The page index to jump to
+ * * `string` - An action to take:
+ * * `first` - Jump to first page.
+ * * `next` - Jump to the next page
+ * * `previous` - Jump to previous page
+ * * `last` - Jump to the last page.
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'page()', function ( action ) {
+ if ( action === undefined ) {
+ return this.page.info().page; // not an expensive call
+ }
+
+ // else, have an action to take on all tables
+ return this.iterator( 'table', function ( settings ) {
+ _fnPageChange( settings, action );
+ } );
+ } );
+
+
+ /**
+ * Paging information for the first table in the current context.
+ *
+ * If you require paging information for another table, use the `table()` method
+ * with a suitable selector.
+ *
+ * @return {object} Object with the following properties set:
+ * * `page` - Current page index (zero based - i.e. the first page is `0`)
+ * * `pages` - Total number of pages
+ * * `start` - Display index for the first record shown on the current page
+ * * `end` - Display index for the last record shown on the current page
+ * * `length` - Display length (number of records). Note that generally `start
+ * + length = end`, but this is not always true, for example if there are
+ * only 2 records to show on the final page, with a length of 10.
+ * * `recordsTotal` - Full data set length
+ * * `recordsDisplay` - Data set length once the current filtering criterion
+ * are applied.
+ */
+ _api_register( 'page.info()', function ( action ) {
+ if ( this.context.length === 0 ) {
+ return undefined;
+ }
+
+ var
+ settings = this.context[0],
+ start = settings._iDisplayStart,
+ len = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
+ visRecords = settings.fnRecordsDisplay(),
+ all = len === -1;
+
+ return {
+ "page": all ? 0 : Math.floor( start / len ),
+ "pages": all ? 1 : Math.ceil( visRecords / len ),
+ "start": start,
+ "end": settings.fnDisplayEnd(),
+ "length": len,
+ "recordsTotal": settings.fnRecordsTotal(),
+ "recordsDisplay": visRecords,
+ "serverSide": _fnDataSource( settings ) === 'ssp'
+ };
+ } );
+
+
+ /**
+ * Get the current page length.
+ *
+ * @return {integer} Current page length. Note `-1` indicates that all records
+ * are to be shown.
+ *//**
+ * Set the current page length.
+ *
+ * @param {integer} Page length to set. Use `-1` to show all records.
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'page.len()', function ( len ) {
+ // Note that we can't call this function 'length()' because `length`
+ // is a Javascript property of functions which defines how many arguments
+ // the function expects.
+ if ( len === undefined ) {
+ return this.context.length !== 0 ?
+ this.context[0]._iDisplayLength :
+ undefined;
+ }
+
+ // else, set the page length
+ return this.iterator( 'table', function ( settings ) {
+ _fnLengthChange( settings, len );
+ } );
+ } );
+
+
+
+ var __reload = function ( settings, holdPosition, callback ) {
+ // Use the draw event to trigger a callback
+ if ( callback ) {
+ var api = new _Api( settings );
+
+ api.one( 'draw', function () {
+ callback( api.ajax.json() );
+ } );
+ }
+
+ if ( _fnDataSource( settings ) == 'ssp' ) {
+ _fnReDraw( settings, holdPosition );
+ }
+ else {
+ _fnProcessingDisplay( settings, true );
+
+ // Cancel an existing request
+ var xhr = settings.jqXHR;
+ if ( xhr && xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+
+ // Trigger xhr
+ _fnBuildAjax( settings, [], function( json ) {
+ _fnClearTable( settings );
+
+ var data = _fnAjaxDataSrc( settings, json );
+ for ( var i=0, ien=data.length ; i<ien ; i++ ) {
+ _fnAddData( settings, data[i] );
+ }
+
+ _fnReDraw( settings, holdPosition );
+ _fnProcessingDisplay( settings, false );
+ } );
+ }
+ };
+
+
+ /**
+ * Get the JSON response from the last Ajax request that DataTables made to the
+ * server. Note that this returns the JSON from the first table in the current
+ * context.
+ *
+ * @return {object} JSON received from the server.
+ */
+ _api_register( 'ajax.json()', function () {
+ var ctx = this.context;
+
+ if ( ctx.length > 0 ) {
+ return ctx[0].json;
+ }
+
+ // else return undefined;
+ } );
+
+
+ /**
+ * Get the data submitted in the last Ajax request
+ */
+ _api_register( 'ajax.params()', function () {
+ var ctx = this.context;
+
+ if ( ctx.length > 0 ) {
+ return ctx[0].oAjaxData;
+ }
+
+ // else return undefined;
+ } );
+
+
+ /**
+ * Reload tables from the Ajax data source. Note that this function will
+ * automatically re-draw the table when the remote data has been loaded.
+ *
+ * @param {boolean} [reset=true] Reset (default) or hold the current paging
+ * position. A full re-sort and re-filter is performed when this method is
+ * called, which is why the pagination reset is the default action.
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
+ return this.iterator( 'table', function (settings) {
+ __reload( settings, resetPaging===false, callback );
+ } );
+ } );
+
+
+ /**
+ * Get the current Ajax URL. Note that this returns the URL from the first
+ * table in the current context.
+ *
+ * @return {string} Current Ajax source URL
+ *//**
+ * Set the Ajax URL. Note that this will set the URL for all tables in the
+ * current context.
+ *
+ * @param {string} url URL to set.
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'ajax.url()', function ( url ) {
+ var ctx = this.context;
+
+ if ( url === undefined ) {
+ // get
+ if ( ctx.length === 0 ) {
+ return undefined;
+ }
+ ctx = ctx[0];
+
+ return ctx.ajax ?
+ $.isPlainObject( ctx.ajax ) ?
+ ctx.ajax.url :
+ ctx.ajax :
+ ctx.sAjaxSource;
+ }
+
+ // set
+ return this.iterator( 'table', function ( settings ) {
+ if ( $.isPlainObject( settings.ajax ) ) {
+ settings.ajax.url = url;
+ }
+ else {
+ settings.ajax = url;
+ }
+ // No need to consider sAjaxSource here since DataTables gives priority
+ // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
+ // value of `sAjaxSource` redundant.
+ } );
+ } );
+
+
+ /**
+ * Load data from the newly set Ajax URL. Note that this method is only
+ * available when `ajax.url()` is used to set a URL. Additionally, this method
+ * has the same effect as calling `ajax.reload()` but is provided for
+ * convenience when setting a new URL. Like `ajax.reload()` it will
+ * automatically redraw the table once the remote data has been loaded.
+ *
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
+ // Same as a reload, but makes sense to present it for easy access after a
+ // url change
+ return this.iterator( 'table', function ( ctx ) {
+ __reload( ctx, resetPaging===false, callback );
+ } );
+ } );
+
+
+
+
+ var _selector_run = function ( type, selector, selectFn, settings, opts )
+ {
+ var
+ out = [], res,
+ a, i, ien, j, jen,
+ selectorType = typeof selector;
+
+ // Can't just check for isArray here, as an API or jQuery instance might be
+ // given with their array like look
+ if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
+ selector = [ selector ];
+ }
+
+ for ( i=0, ien=selector.length ; i<ien ; i++ ) {
+ // Only split on simple strings - complex expressions will be jQuery selectors
+ a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
+ selector[i].split(',') :
+ [ selector[i] ];
+
+ for ( j=0, jen=a.length ; j<jen ; j++ ) {
+ res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
+
+ if ( res && res.length ) {
+ out = out.concat( res );
+ }
+ }
+ }
+
+ // selector extensions
+ var ext = _ext.selector[ type ];
+ if ( ext.length ) {
+ for ( i=0, ien=ext.length ; i<ien ; i++ ) {
+ out = ext[i]( settings, opts, out );
+ }
+ }
+
+ return _unique( out );
+ };
+
+
+ var _selector_opts = function ( opts )
+ {
+ if ( ! opts ) {
+ opts = {};
+ }
+
+ // Backwards compatibility for 1.9- which used the terminology filter rather
+ // than search
+ if ( opts.filter && opts.search === undefined ) {
+ opts.search = opts.filter;
+ }
+
+ return $.extend( {
+ search: 'none',
+ order: 'current',
+ page: 'all'
+ }, opts );
+ };
+
+
+ var _selector_first = function ( inst )
+ {
+ // Reduce the API instance to the first item found
+ for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
+ if ( inst[i].length > 0 ) {
+ // Assign the first element to the first item in the instance
+ // and truncate the instance and context
+ inst[0] = inst[i];
+ inst[0].length = 1;
+ inst.length = 1;
+ inst.context = [ inst.context[i] ];
+
+ return inst;
+ }
+ }
+
+ // Not found - return an empty instance
+ inst.length = 0;
+ return inst;
+ };
+
+
+ var _selector_row_indexes = function ( settings, opts )
+ {
+ var
+ i, ien, tmp, a=[],
+ displayFiltered = settings.aiDisplay,
+ displayMaster = settings.aiDisplayMaster;
+
+ var
+ search = opts.search, // none, applied, removed
+ order = opts.order, // applied, current, index (original - compatibility with 1.9)
+ page = opts.page; // all, current
+
+ if ( _fnDataSource( settings ) == 'ssp' ) {
+ // In server-side processing mode, most options are irrelevant since
+ // rows not shown don't exist and the index order is the applied order
+ // Removed is a special case - for consistency just return an empty
+ // array
+ return search === 'removed' ?
+ [] :
+ _range( 0, displayMaster.length );
+ }
+ else if ( page == 'current' ) {
+ // Current page implies that order=current and fitler=applied, since it is
+ // fairly senseless otherwise, regardless of what order and search actually
+ // are
+ for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
+ a.push( displayFiltered[i] );
+ }
+ }
+ else if ( order == 'current' || order == 'applied' ) {
+ a = search == 'none' ?
+ displayMaster.slice() : // no search
+ search == 'applied' ?
+ displayFiltered.slice() : // applied search
+ $.map( displayMaster, function (el, i) { // removed search
+ return $.inArray( el, displayFiltered ) === -1 ? el : null;
+ } );
+ }
+ else if ( order == 'index' || order == 'original' ) {
+ for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
+ if ( search == 'none' ) {
+ a.push( i );
+ }
+ else { // applied | removed
+ tmp = $.inArray( i, displayFiltered );
+
+ if ((tmp === -1 && search == 'removed') ||
+ (tmp >= 0 && search == 'applied') )
+ {
+ a.push( i );
+ }
+ }
+ }
+ }
+
+ return a;
+ };
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Rows
+ *
+ * {} - no selector - use all available rows
+ * {integer} - row aoData index
+ * {node} - TR node
+ * {string} - jQuery selector to apply to the TR elements
+ * {array} - jQuery array of nodes, or simply an array of TR nodes
+ *
+ */
+
+
+ var __row_selector = function ( settings, selector, opts )
+ {
+ var rows;
+ var run = function ( sel ) {
+ var selInt = _intVal( sel );
+ var i, ien;
+
+ // Short cut - selector is a number and no options provided (default is
+ // all records, so no need to check if the index is in there, since it
+ // must be - dev error if the index doesn't exist).
+ if ( selInt !== null && ! opts ) {
+ return [ selInt ];
+ }
+
+ if ( ! rows ) {
+ rows = _selector_row_indexes( settings, opts );
+ }
+
+ if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
+ // Selector - integer
+ return [ selInt ];
+ }
+ else if ( sel === null || sel === undefined || sel === '' ) {
+ // Selector - none
+ return rows;
+ }
+
+ // Selector - function
+ if ( typeof sel === 'function' ) {
+ return $.map( rows, function (idx) {
+ var row = settings.aoData[ idx ];
+ return sel( idx, row._aData, row.nTr ) ? idx : null;
+ } );
+ }
+
+ // Get nodes in the order from the `rows` array with null values removed
+ var nodes = _removeEmpty(
+ _pluck_order( settings.aoData, rows, 'nTr' )
+ );
+
+ // Selector - node
+ if ( sel.nodeName ) {
+ if ( sel._DT_RowIndex !== undefined ) {
+ return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup
+ }
+ else if ( sel._DT_CellIndex ) {
+ return [ sel._DT_CellIndex.row ];
+ }
+ else {
+ var host = $(sel).closest('*[data-dt-row]');
+ return host.length ?
+ [ host.data('dt-row') ] :
+ [];
+ }
+ }
+
+ // ID selector. Want to always be able to select rows by id, regardless
+ // of if the tr element has been created or not, so can't rely upon
+ // jQuery here - hence a custom implementation. This does not match
+ // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
+ // but to select it using a CSS selector engine (like Sizzle or
+ // querySelect) it would need to need to be escaped for some characters.
+ // DataTables simplifies this for row selectors since you can select
+ // only a row. A # indicates an id any anything that follows is the id -
+ // unescaped.
+ if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
+ // get row index from id
+ var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
+ if ( rowObj !== undefined ) {
+ return [ rowObj.idx ];
+ }
+
+ // need to fall through to jQuery in case there is DOM id that
+ // matches
+ }
+
+ // Selector - jQuery selector string, array of nodes or jQuery object/
+ // As jQuery's .filter() allows jQuery objects to be passed in filter,
+ // it also allows arrays, so this will cope with all three options
+ return $(nodes)
+ .filter( sel )
+ .map( function () {
+ return this._DT_RowIndex;
+ } )
+ .toArray();
+ };
+
+ return _selector_run( 'row', selector, run, settings, opts );
+ };
+
+
+ _api_register( 'rows()', function ( selector, opts ) {
+ // argument shifting
+ if ( selector === undefined ) {
+ selector = '';
+ }
+ else if ( $.isPlainObject( selector ) ) {
+ opts = selector;
+ selector = '';
+ }
+
+ opts = _selector_opts( opts );
+
+ var inst = this.iterator( 'table', function ( settings ) {
+ return __row_selector( settings, selector, opts );
+ }, 1 );
+
+ // Want argument shifting here and in __row_selector?
+ inst.selector.rows = selector;
+ inst.selector.opts = opts;
+
+ return inst;
+ } );
+
+ _api_register( 'rows().nodes()', function () {
+ return this.iterator( 'row', function ( settings, row ) {
+ return settings.aoData[ row ].nTr || undefined;
+ }, 1 );
+ } );
+
+ _api_register( 'rows().data()', function () {
+ return this.iterator( true, 'rows', function ( settings, rows ) {
+ return _pluck_order( settings.aoData, rows, '_aData' );
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
+ return this.iterator( 'row', function ( settings, row ) {
+ var r = settings.aoData[ row ];
+ return type === 'search' ? r._aFilterData : r._aSortData;
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
+ return this.iterator( 'row', function ( settings, row ) {
+ _fnInvalidate( settings, row, src );
+ } );
+ } );
+
+ _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
+ return this.iterator( 'row', function ( settings, row ) {
+ return row;
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
+ var a = [];
+ var context = this.context;
+
+ // `iterator` will drop undefined values, but in this case we want them
+ for ( var i=0, ien=context.length ; i<ien ; i++ ) {
+ for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
+ var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
+ a.push( (hash === true ? '#' : '' )+ id );
+ }
+ }
+
+ return new _Api( context, a );
+ } );
+
+ _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
+ var that = this;
+
+ this.iterator( 'row', function ( settings, row, thatIdx ) {
+ var data = settings.aoData;
+ var rowData = data[ row ];
+ var i, ien, j, jen;
+ var loopRow, loopCells;
+
+ data.splice( row, 1 );
+
+ // Update the cached indexes
+ for ( i=0, ien=data.length ; i<ien ; i++ ) {
+ loopRow = data[i];
+ loopCells = loopRow.anCells;
+
+ // Rows
+ if ( loopRow.nTr !== null ) {
+ loopRow.nTr._DT_RowIndex = i;
+ }
+
+ // Cells
+ if ( loopCells !== null ) {
+ for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
+ loopCells[j]._DT_CellIndex.row = i;
+ }
+ }
+ }
+
+ // Delete from the display arrays
+ _fnDeleteIndex( settings.aiDisplayMaster, row );
+ _fnDeleteIndex( settings.aiDisplay, row );
+ _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
+
+ // For server-side processing tables - subtract the deleted row from the count
+ if ( settings._iRecordsDisplay > 0 ) {
+ settings._iRecordsDisplay--;
+ }
+
+ // Check for an 'overflow' they case for displaying the table
+ _fnLengthOverflow( settings );
+
+ // Remove the row's ID reference if there is one
+ var id = settings.rowIdFn( rowData._aData );
+ if ( id !== undefined ) {
+ delete settings.aIds[ id ];
+ }
+ } );
+
+ this.iterator( 'table', function ( settings ) {
+ for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
+ settings.aoData[i].idx = i;
+ }
+ } );
+
+ return this;
+ } );
+
+
+ _api_register( 'rows.add()', function ( rows ) {
+ var newRows = this.iterator( 'table', function ( settings ) {
+ var row, i, ien;
+ var out = [];
+
+ for ( i=0, ien=rows.length ; i<ien ; i++ ) {
+ row = rows[i];
+
+ if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
+ out.push( _fnAddTr( settings, row )[0] );
+ }
+ else {
+ out.push( _fnAddData( settings, row ) );
+ }
+ }
+
+ return out;
+ }, 1 );
+
+ // Return an Api.rows() extended instance, so rows().nodes() etc can be used
+ var modRows = this.rows( -1 );
+ modRows.pop();
+ $.merge( modRows, newRows );
+
+ return modRows;
+ } );
+
+
+
+
+
+ /**
+ *
+ */
+ _api_register( 'row()', function ( selector, opts ) {
+ return _selector_first( this.rows( selector, opts ) );
+ } );
+
+
+ _api_register( 'row().data()', function ( data ) {
+ var ctx = this.context;
+
+ if ( data === undefined ) {
+ // Get
+ return ctx.length && this.length ?
+ ctx[0].aoData[ this[0] ]._aData :
+ undefined;
+ }
+
+ // Set
+ ctx[0].aoData[ this[0] ]._aData = data;
+
+ // Automatically invalidate
+ _fnInvalidate( ctx[0], this[0], 'data' );
+
+ return this;
+ } );
+
+
+ _api_register( 'row().node()', function () {
+ var ctx = this.context;
+
+ return ctx.length && this.length ?
+ ctx[0].aoData[ this[0] ].nTr || null :
+ null;
+ } );
+
+
+ _api_register( 'row.add()', function ( row ) {
+ // Allow a jQuery object to be passed in - only a single row is added from
+ // it though - the first element in the set
+ if ( row instanceof $ && row.length ) {
+ row = row[0];
+ }
+
+ var rows = this.iterator( 'table', function ( settings ) {
+ if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
+ return _fnAddTr( settings, row )[0];
+ }
+ return _fnAddData( settings, row );
+ } );
+
+ // Return an Api.rows() extended instance, with the newly added row selected
+ return this.row( rows[0] );
+ } );
+
+
+
+ var __details_add = function ( ctx, row, data, klass )
+ {
+ // Convert to array of TR elements
+ var rows = [];
+ var addRow = function ( r, k ) {
+ // Recursion to allow for arrays of jQuery objects
+ if ( $.isArray( r ) || r instanceof $ ) {
+ for ( var i=0, ien=r.length ; i<ien ; i++ ) {
+ addRow( r[i], k );
+ }
+ return;
+ }
+
+ // If we get a TR element, then just add it directly - up to the dev
+ // to add the correct number of columns etc
+ if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
+ rows.push( r );
+ }
+ else {
+ // Otherwise create a row with a wrapper
+ var created = $('<tr><td/></tr>').addClass( k );
+ $('td', created)
+ .addClass( k )
+ .html( r )
+ [0].colSpan = _fnVisbleColumns( ctx );
+
+ rows.push( created[0] );
+ }
+ };
+
+ addRow( data, klass );
+
+ if ( row._details ) {
+ row._details.detach();
+ }
+
+ row._details = $(rows);
+
+ // If the children were already shown, that state should be retained
+ if ( row._detailsShow ) {
+ row._details.insertAfter( row.nTr );
+ }
+ };
+
+
+ var __details_remove = function ( api, idx )
+ {
+ var ctx = api.context;
+
+ if ( ctx.length ) {
+ var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
+
+ if ( row && row._details ) {
+ row._details.remove();
+
+ row._detailsShow = undefined;
+ row._details = undefined;
+ }
+ }
+ };
+
+
+ var __details_display = function ( api, show ) {
+ var ctx = api.context;
+
+ if ( ctx.length && api.length ) {
+ var row = ctx[0].aoData[ api[0] ];
+
+ if ( row._details ) {
+ row._detailsShow = show;
+
+ if ( show ) {
+ row._details.insertAfter( row.nTr );
+ }
+ else {
+ row._details.detach();
+ }
+
+ __details_events( ctx[0] );
+ }
+ }
+ };
+
+
+ var __details_events = function ( settings )
+ {
+ var api = new _Api( settings );
+ var namespace = '.dt.DT_details';
+ var drawEvent = 'draw'+namespace;
+ var colvisEvent = 'column-visibility'+namespace;
+ var destroyEvent = 'destroy'+namespace;
+ var data = settings.aoData;
+
+ api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
+
+ if ( _pluck( data, '_details' ).length > 0 ) {
+ // On each draw, insert the required elements into the document
+ api.on( drawEvent, function ( e, ctx ) {
+ if ( settings !== ctx ) {
+ return;
+ }
+
+ api.rows( {page:'current'} ).eq(0).each( function (idx) {
+ // Internal data grab
+ var row = data[ idx ];
+
+ if ( row._detailsShow ) {
+ row._details.insertAfter( row.nTr );
+ }
+ } );
+ } );
+
+ // Column visibility change - update the colspan
+ api.on( colvisEvent, function ( e, ctx, idx, vis ) {
+ if ( settings !== ctx ) {
+ return;
+ }
+
+ // Update the colspan for the details rows (note, only if it already has
+ // a colspan)
+ var row, visible = _fnVisbleColumns( ctx );
+
+ for ( var i=0, ien=data.length ; i<ien ; i++ ) {
+ row = data[i];
+
+ if ( row._details ) {
+ row._details.children('td[colspan]').attr('colspan', visible );
+ }
+ }
+ } );
+
+ // Table destroyed - nuke any child rows
+ api.on( destroyEvent, function ( e, ctx ) {
+ if ( settings !== ctx ) {
+ return;
+ }
+
+ for ( var i=0, ien=data.length ; i<ien ; i++ ) {
+ if ( data[i]._details ) {
+ __details_remove( api, i );
+ }
+ }
+ } );
+ }
+ };
+
+ // Strings for the method names to help minification
+ var _emp = '';
+ var _child_obj = _emp+'row().child';
+ var _child_mth = _child_obj+'()';
+
+ // data can be:
+ // tr
+ // string
+ // jQuery or array of any of the above
+ _api_register( _child_mth, function ( data, klass ) {
+ var ctx = this.context;
+
+ if ( data === undefined ) {
+ // get
+ return ctx.length && this.length ?
+ ctx[0].aoData[ this[0] ]._details :
+ undefined;
+ }
+ else if ( data === true ) {
+ // show
+ this.child.show();
+ }
+ else if ( data === false ) {
+ // remove
+ __details_remove( this );
+ }
+ else if ( ctx.length && this.length ) {
+ // set
+ __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
+ }
+
+ return this;
+ } );
+
+
+ _api_register( [
+ _child_obj+'.show()',
+ _child_mth+'.show()' // only when `child()` was called with parameters (without
+ ], function ( show ) { // it returns an object and this method is not executed)
+ __details_display( this, true );
+ return this;
+ } );
+
+
+ _api_register( [
+ _child_obj+'.hide()',
+ _child_mth+'.hide()' // only when `child()` was called with parameters (without
+ ], function () { // it returns an object and this method is not executed)
+ __details_display( this, false );
+ return this;
+ } );
+
+
+ _api_register( [
+ _child_obj+'.remove()',
+ _child_mth+'.remove()' // only when `child()` was called with parameters (without
+ ], function () { // it returns an object and this method is not executed)
+ __details_remove( this );
+ return this;
+ } );
+
+
+ _api_register( _child_obj+'.isShown()', function () {
+ var ctx = this.context;
+
+ if ( ctx.length && this.length ) {
+ // _detailsShown as false or undefined will fall through to return false
+ return ctx[0].aoData[ this[0] ]._detailsShow || false;
+ }
+ return false;
+ } );
+
+
+
+ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Columns
+ *
+ * {integer} - column index (>=0 count from left, <0 count from right)
+ * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right)
+ * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right)
+ * "{string}:name" - column name
+ * "{string}" - jQuery selector on column header nodes
+ *
+ */
+
+ // can be an array of these items, comma separated list, or an array of comma
+ // separated lists
+
+ var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
+
+
+ // r1 and r2 are redundant - but it means that the parameters match for the
+ // iterator callback in columns().data()
+ var __columnData = function ( settings, column, r1, r2, rows ) {
+ var a = [];
+ for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
+ a.push( _fnGetCellData( settings, rows[row], column ) );
+ }
+ return a;
+ };
+
+
+ var __column_selector = function ( settings, selector, opts )
+ {
+ var
+ columns = settings.aoColumns,
+ names = _pluck( columns, 'sName' ),
+ nodes = _pluck( columns, 'nTh' );
+
+ var run = function ( s ) {
+ var selInt = _intVal( s );
+
+ // Selector - all
+ if ( s === '' ) {
+ return _range( columns.length );
+ }
+
+ // Selector - index
+ if ( selInt !== null ) {
+ return [ selInt >= 0 ?
+ selInt : // Count from left
+ columns.length + selInt // Count from right (+ because its a negative value)
+ ];
+ }
+
+ // Selector = function
+ if ( typeof s === 'function' ) {
+ var rows = _selector_row_indexes( settings, opts );
+
+ return $.map( columns, function (col, idx) {
+ return s(
+ idx,
+ __columnData( settings, idx, 0, 0, rows ),
+ nodes[ idx ]
+ ) ? idx : null;
+ } );
+ }
+
+ // jQuery or string selector
+ var match = typeof s === 'string' ?
+ s.match( __re_column_selector ) :
+ '';
+
+ if ( match ) {
+ switch( match[2] ) {
+ case 'visIdx':
+ case 'visible':
+ var idx = parseInt( match[1], 10 );
+ // Visible index given, convert to column index
+ if ( idx < 0 ) {
+ // Counting from the right
+ var visColumns = $.map( columns, function (col,i) {
+ return col.bVisible ? i : null;
+ } );
+ return [ visColumns[ visColumns.length + idx ] ];
+ }
+ // Counting from the left
+ return [ _fnVisibleToColumnIndex( settings, idx ) ];
+
+ case 'name':
+ // match by name. `names` is column index complete and in order
+ return $.map( names, function (name, i) {
+ return name === match[1] ? i : null;
+ } );
+
+ default:
+ return [];
+ }
+ }
+
+ // Cell in the table body
+ if ( s.nodeName && s._DT_CellIndex ) {
+ return [ s._DT_CellIndex.column ];
+ }
+
+ // jQuery selector on the TH elements for the columns
+ var jqResult = $( nodes )
+ .filter( s )
+ .map( function () {
+ return $.inArray( this, nodes ); // `nodes` is column index complete and in order
+ } )
+ .toArray();
+
+ if ( jqResult.length || ! s.nodeName ) {
+ return jqResult;
+ }
+
+ // Otherwise a node which might have a `dt-column` data attribute, or be
+ // a child or such an element
+ var host = $(s).closest('*[data-dt-column]');
+ return host.length ?
+ [ host.data('dt-column') ] :
+ [];
+ };
+
+ return _selector_run( 'column', selector, run, settings, opts );
+ };
+
+
+ var __setColumnVis = function ( settings, column, vis ) {
+ var
+ cols = settings.aoColumns,
+ col = cols[ column ],
+ data = settings.aoData,
+ row, cells, i, ien, tr;
+
+ // Get
+ if ( vis === undefined ) {
+ return col.bVisible;
+ }
+
+ // Set
+ // No change
+ if ( col.bVisible === vis ) {
+ return;
+ }
+
+ if ( vis ) {
+ // Insert column
+ // Need to decide if we should use appendChild or insertBefore
+ var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
+
+ for ( i=0, ien=data.length ; i<ien ; i++ ) {
+ tr = data[i].nTr;
+ cells = data[i].anCells;
+
+ if ( tr ) {
+ // insertBefore can act like appendChild if 2nd arg is null
+ tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
+ }
+ }
+ }
+ else {
+ // Remove column
+ $( _pluck( settings.aoData, 'anCells', column ) ).detach();
+ }
+
+ // Common actions
+ col.bVisible = vis;
+ _fnDrawHead( settings, settings.aoHeader );
+ _fnDrawHead( settings, settings.aoFooter );
+
+ _fnSaveState( settings );
+ };
+
+
+ _api_register( 'columns()', function ( selector, opts ) {
+ // argument shifting
+ if ( selector === undefined ) {
+ selector = '';
+ }
+ else if ( $.isPlainObject( selector ) ) {
+ opts = selector;
+ selector = '';
+ }
+
+ opts = _selector_opts( opts );
+
+ var inst = this.iterator( 'table', function ( settings ) {
+ return __column_selector( settings, selector, opts );
+ }, 1 );
+
+ // Want argument shifting here and in _row_selector?
+ inst.selector.cols = selector;
+ inst.selector.opts = opts;
+
+ return inst;
+ } );
+
+ _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
+ return this.iterator( 'column', function ( settings, column ) {
+ return settings.aoColumns[column].nTh;
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
+ return this.iterator( 'column', function ( settings, column ) {
+ return settings.aoColumns[column].nTf;
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'columns().data()', 'column().data()', function () {
+ return this.iterator( 'column-rows', __columnData, 1 );
+ } );
+
+ _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
+ return this.iterator( 'column', function ( settings, column ) {
+ return settings.aoColumns[column].mData;
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
+ return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
+ return _pluck_order( settings.aoData, rows,
+ type === 'search' ? '_aFilterData' : '_aSortData', column
+ );
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
+ return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
+ return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
+ }, 1 );
+ } );
+
+ _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
+ var ret = this.iterator( 'column', function ( settings, column ) {
+ if ( vis === undefined ) {
+ return settings.aoColumns[ column ].bVisible;
+ } // else
+ __setColumnVis( settings, column, vis );
+ } );
+
+ // Group the column visibility changes
+ if ( vis !== undefined ) {
+ // Second loop once the first is done for events
+ this.iterator( 'column', function ( settings, column ) {
+ _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
+ } );
+
+ if ( calc === undefined || calc ) {
+ this.columns.adjust();
+ }
+ }
+
+ return ret;
+ } );
+
+ _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
+ return this.iterator( 'column', function ( settings, column ) {
+ return type === 'visible' ?
+ _fnColumnIndexToVisible( settings, column ) :
+ column;
+ }, 1 );
+ } );
+
+ _api_register( 'columns.adjust()', function () {
+ return this.iterator( 'table', function ( settings ) {
+ _fnAdjustColumnSizing( settings );
+ }, 1 );
+ } );
+
+ _api_register( 'column.index()', function ( type, idx ) {
+ if ( this.context.length !== 0 ) {
+ var ctx = this.context[0];
+
+ if ( type === 'fromVisible' || type === 'toData' ) {
+ return _fnVisibleToColumnIndex( ctx, idx );
+ }
+ else if ( type === 'fromData' || type === 'toVisible' ) {
+ return _fnColumnIndexToVisible( ctx, idx );
+ }
+ }
+ } );
+
+ _api_register( 'column()', function ( selector, opts ) {
+ return _selector_first( this.columns( selector, opts ) );
+ } );
+
+
+
+ var __cell_selector = function ( settings, selector, opts )
+ {
+ var data = settings.aoData;
+ var rows = _selector_row_indexes( settings, opts );
+ var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
+ var allCells = $( [].concat.apply([], cells) );
+ var row;
+ var columns = settings.aoColumns.length;
+ var a, i, ien, j, o, host;
+
+ var run = function ( s ) {
+ var fnSelector = typeof s === 'function';
+
+ if ( s === null || s === undefined || fnSelector ) {
+ // All cells and function selectors
+ a = [];
+
+ for ( i=0, ien=rows.length ; i<ien ; i++ ) {
+ row = rows[i];
+
+ for ( j=0 ; j<columns ; j++ ) {
+ o = {
+ row: row,
+ column: j
+ };
+
+ if ( fnSelector ) {
+ // Selector - function
+ host = data[ row ];
+
+ if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
+ a.push( o );
+ }
+ }
+ else {
+ // Selector - all
+ a.push( o );
+ }
+ }
+ }
+
+ return a;
+ }
+
+ // Selector - index
+ if ( $.isPlainObject( s ) ) {
+ return [s];
+ }
+
+ // Selector - jQuery filtered cells
+ var jqResult = allCells
+ .filter( s )
+ .map( function (i, el) {
+ return { // use a new object, in case someone changes the values
+ row: el._DT_CellIndex.row,
+ column: el._DT_CellIndex.column
+ };
+ } )
+ .toArray();
+
+ if ( jqResult.length || ! s.nodeName ) {
+ return jqResult;
+ }
+
+ // Otherwise the selector is a node, and there is one last option - the
+ // element might be a child of an element which has dt-row and dt-column
+ // data attributes
+ host = $(s).closest('*[data-dt-row]');
+ return host.length ?
+ [ {
+ row: host.data('dt-row'),
+ column: host.data('dt-column')
+ } ] :
+ [];
+ };
+
+ return _selector_run( 'cell', selector, run, settings, opts );
+ };
+
+
+
+
+ _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
+ // Argument shifting
+ if ( $.isPlainObject( rowSelector ) ) {
+ // Indexes
+ if ( rowSelector.row === undefined ) {
+ // Selector options in first parameter
+ opts = rowSelector;
+ rowSelector = null;
+ }
+ else {
+ // Cell index objects in first parameter
+ opts = columnSelector;
+ columnSelector = null;
+ }
+ }
+ if ( $.isPlainObject( columnSelector ) ) {
+ opts = columnSelector;
+ columnSelector = null;
+ }
+
+ // Cell selector
+ if ( columnSelector === null || columnSelector === undefined ) {
+ return this.iterator( 'table', function ( settings ) {
+ return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
+ } );
+ }
+
+ // Row + column selector
+ var columns = this.columns( columnSelector, opts );
+ var rows = this.rows( rowSelector, opts );
+ var a, i, ien, j, jen;
+
+ var cells = this.iterator( 'table', function ( settings, idx ) {
+ a = [];
+
+ for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
+ for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
+ a.push( {
+ row: rows[idx][i],
+ column: columns[idx][j]
+ } );
+ }
+ }
+
+ return a;
+ }, 1 );
+
+ $.extend( cells.selector, {
+ cols: columnSelector,
+ rows: rowSelector,
+ opts: opts
+ } );
+
+ return cells;
+ } );
+
+
+ _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
+ return this.iterator( 'cell', function ( settings, row, column ) {
+ var data = settings.aoData[ row ];
+
+ return data && data.anCells ?
+ data.anCells[ column ] :
+ undefined;
+ }, 1 );
+ } );
+
+
+ _api_register( 'cells().data()', function () {
+ return this.iterator( 'cell', function ( settings, row, column ) {
+ return _fnGetCellData( settings, row, column );
+ }, 1 );
+ } );
+
+
+ _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
+ type = type === 'search' ? '_aFilterData' : '_aSortData';
+
+ return this.iterator( 'cell', function ( settings, row, column ) {
+ return settings.aoData[ row ][ type ][ column ];
+ }, 1 );
+ } );
+
+
+ _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
+ return this.iterator( 'cell', function ( settings, row, column ) {
+ return _fnGetCellData( settings, row, column, type );
+ }, 1 );
+ } );
+
+
+ _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
+ return this.iterator( 'cell', function ( settings, row, column ) {
+ return {
+ row: row,
+ column: column,
+ columnVisible: _fnColumnIndexToVisible( settings, column )
+ };
+ }, 1 );
+ } );
+
+
+ _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
+ return this.iterator( 'cell', function ( settings, row, column ) {
+ _fnInvalidate( settings, row, src, column );
+ } );
+ } );
+
+
+
+ _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
+ return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
+ } );
+
+
+ _api_register( 'cell().data()', function ( data ) {
+ var ctx = this.context;
+ var cell = this[0];
+
+ if ( data === undefined ) {
+ // Get
+ return ctx.length && cell.length ?
+ _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
+ undefined;
+ }
+
+ // Set
+ _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
+ _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
+
+ return this;
+ } );
+
+
+
+ /**
+ * Get current ordering (sorting) that has been applied to the table.
+ *
+ * @returns {array} 2D array containing the sorting information for the first
+ * table in the current context. Each element in the parent array represents
+ * a column being sorted upon (i.e. multi-sorting with two columns would have
+ * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
+ * the column index that the sorting condition applies to, the second is the
+ * direction of the sort (`desc` or `asc`) and, optionally, the third is the
+ * index of the sorting order from the `column.sorting` initialisation array.
+ *//**
+ * Set the ordering for the table.
+ *
+ * @param {integer} order Column index to sort upon.
+ * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
+ * @returns {DataTables.Api} this
+ *//**
+ * Set the ordering for the table.
+ *
+ * @param {array} order 1D array of sorting information to be applied.
+ * @param {array} [...] Optional additional sorting conditions
+ * @returns {DataTables.Api} this
+ *//**
+ * Set the ordering for the table.
+ *
+ * @param {array} order 2D array of sorting information to be applied.
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'order()', function ( order, dir ) {
+ var ctx = this.context;
+
+ if ( order === undefined ) {
+ // get
+ return ctx.length !== 0 ?
+ ctx[0].aaSorting :
+ undefined;
+ }
+
+ // set
+ if ( typeof order === 'number' ) {
+ // Simple column / direction passed in
+ order = [ [ order, dir ] ];
+ }
+ else if ( order.length && ! $.isArray( order[0] ) ) {
+ // Arguments passed in (list of 1D arrays)
+ order = Array.prototype.slice.call( arguments );
+ }
+ // otherwise a 2D array was passed in
+
+ return this.iterator( 'table', function ( settings ) {
+ settings.aaSorting = order.slice();
+ } );
+ } );
+
+
+ /**
+ * Attach a sort listener to an element for a given column
+ *
+ * @param {node|jQuery|string} node Identifier for the element(s) to attach the
+ * listener to. This can take the form of a single DOM node, a jQuery
+ * collection of nodes or a jQuery selector which will identify the node(s).
+ * @param {integer} column the column that a click on this node will sort on
+ * @param {function} [callback] callback function when sort is run
+ * @returns {DataTables.Api} this
+ */
+ _api_register( 'order.listener()', function ( node, column, callback ) {
+ return this.iterator( 'table', function ( settings ) {
+ _fnSortAttachListener( settings, node, column, callback );
+ } );
+ } );
+
+
+ _api_register( 'order.fixed()', function ( set ) {
+ if ( ! set ) {
+ var ctx = this.context;
+ var fixed = ctx.length ?
+ ctx[0].aaSortingFixed :
+ undefined;
+
+ return $.isArray( fixed ) ?
+ { pre: fixed } :
+ fixed;
+ }
+
+ return this.iterator( 'table', function ( settings ) {
+ settings.aaSortingFixed = $.extend( true, {}, set );
+ } );
+ } );
+
+
+ // Order by the selected column(s)
+ _api_register( [
+ 'columns().order()',
+ 'column().order()'
+ ], function ( dir ) {
+ var that = this;
+
+ return this.iterator( 'table', function ( settings, i ) {
+ var sort = [];
+
+ $.each( that[i], function (j, col) {
+ sort.push( [ col, dir ] );
+ } );
+
+ settings.aaSorting = sort;
+ } );
+ } );
+
+
+
+ _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
+ var ctx = this.context;
+
+ if ( input === undefined ) {
+ // get
+ return ctx.length !== 0 ?
+ ctx[0].oPreviousSearch.sSearch :
+ undefined;
+ }
+
+ // set
+ return this.iterator( 'table', function ( settings ) {
+ if ( ! settings.oFeatures.bFilter ) {
+ return;
+ }
+
+ _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
+ "sSearch": input+"",
+ "bRegex": regex === null ? false : regex,
+ "bSmart": smart === null ? true : smart,
+ "bCaseInsensitive": caseInsen === null ? true : caseInsen
+ } ), 1 );
+ } );
+ } );
+
+
+ _api_registerPlural(
+ 'columns().search()',
+ 'column().search()',
+ function ( input, regex, smart, caseInsen ) {
+ return this.iterator( 'column', function ( settings, column ) {
+ var preSearch = settings.aoPreSearchCols;
+
+ if ( input === undefined ) {
+ // get
+ return preSearch[ column ].sSearch;
+ }
+
+ // set
+ if ( ! settings.oFeatures.bFilter ) {
+ return;
+ }
+
+ $.extend( preSearch[ column ], {
+ "sSearch": input+"",
+ "bRegex": regex === null ? false : regex,
+ "bSmart": smart === null ? true : smart,
+ "bCaseInsensitive": caseInsen === null ? true : caseInsen
+ } );
+
+ _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
+ } );
+ }
+ );
+
+ /*
+ * State API methods
+ */
+
+ _api_register( 'state()', function () {
+ return this.context.length ?
+ this.context[0].oSavedState :
+ null;
+ } );
+
+
+ _api_register( 'state.clear()', function () {
+ return this.iterator( 'table', function ( settings ) {
+ // Save an empty object
+ settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
+ } );
+ } );
+
+
+ _api_register( 'state.loaded()', function () {
+ return this.context.length ?
+ this.context[0].oLoadedState :
+ null;
+ } );
+
+
+ _api_register( 'state.save()', function () {
+ return this.iterator( 'table', function ( settings ) {
+ _fnSaveState( settings );
+ } );
+ } );
+
+
+
+ /**
+ * Provide a common method for plug-ins to check the version of DataTables being
+ * used, in order to ensure compatibility.
+ *
+ * @param {string} version Version string to check for, in the format "X.Y.Z".
+ * Note that the formats "X" and "X.Y" are also acceptable.
+ * @returns {boolean} true if this version of DataTables is greater or equal to
+ * the required version, or false if this version of DataTales is not
+ * suitable
+ * @static
+ * @dtopt API-Static
+ *
+ * @example
+ * alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
+ */
+ DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
+ {
+ var aThis = DataTable.version.split('.');
+ var aThat = version.split('.');
+ var iThis, iThat;
+
+ for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
+ iThis = parseInt( aThis[i], 10 ) || 0;
+ iThat = parseInt( aThat[i], 10 ) || 0;
+
+ // Parts are the same, keep comparing
+ if (iThis === iThat) {
+ continue;
+ }
+
+ // Parts are different, return immediately
+ return iThis > iThat;
+ }
+
+ return true;
+ };
+
+
+ /**
+ * Check if a `<table>` node is a DataTable table already or not.
+ *
+ * @param {node|jquery|string} table Table node, jQuery object or jQuery
+ * selector for the table to test. Note that if more than more than one
+ * table is passed on, only the first will be checked
+ * @returns {boolean} true the table given is a DataTable, or false otherwise
+ * @static
+ * @dtopt API-Static
+ *
+ * @example
+ * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
+ * $('#example').dataTable();
+ * }
+ */
+ DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
+ {
+ var t = $(table).get(0);
+ var is = false;
+
+ if ( table instanceof DataTable.Api ) {
+ return true;
+ }
+
+ $.each( DataTable.settings, function (i, o) {
+ var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
+ var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
+
+ if ( o.nTable === t || head === t || foot === t ) {
+ is = true;
+ }
+ } );
+
+ return is;
+ };
+
+
+ /**
+ * Get all DataTable tables that have been initialised - optionally you can
+ * select to get only currently visible tables.
+ *
+ * @param {boolean} [visible=false] Flag to indicate if you want all (default)
+ * or visible tables only.
+ * @returns {array} Array of `table` nodes (not DataTable instances) which are
+ * DataTables
+ * @static
+ * @dtopt API-Static
+ *
+ * @example
+ * $.each( $.fn.dataTable.tables(true), function () {
+ * $(table).DataTable().columns.adjust();
+ * } );
+ */
+ DataTable.tables = DataTable.fnTables = function ( visible )
+ {
+ var api = false;
+
+ if ( $.isPlainObject( visible ) ) {
+ api = visible.api;
+ visible = visible.visible;
+ }
+
+ var a = $.map( DataTable.settings, function (o) {
+ if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
+ return o.nTable;
+ }
+ } );
+
+ return api ?
+ new _Api( a ) :
+ a;
+ };
+
+
+ /**
+ * Convert from camel case parameters to Hungarian notation. This is made public
+ * for the extensions to provide the same ability as DataTables core to accept
+ * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
+ * parameters.
+ *
+ * @param {object} src The model object which holds all parameters that can be
+ * mapped.
+ * @param {object} user The object to convert from camel case to Hungarian.
+ * @param {boolean} force When set to `true`, properties which already have a
+ * Hungarian value in the `user` object will be overwritten. Otherwise they
+ * won't be.
+ */
+ DataTable.camelToHungarian = _fnCamelToHungarian;
+
+
+
+ /**
+ *
+ */
+ _api_register( '$()', function ( selector, opts ) {
+ var
+ rows = this.rows( opts ).nodes(), // Get all rows
+ jqRows = $(rows);
+
+ return $( [].concat(
+ jqRows.filter( selector ).toArray(),
+ jqRows.find( selector ).toArray()
+ ) );
+ } );
+
+
+ // jQuery functions to operate on the tables
+ $.each( [ 'on', 'one', 'off' ], function (i, key) {
+ _api_register( key+'()', function ( /* event, handler */ ) {
+ var args = Array.prototype.slice.call(arguments);
+
+ // Add the `dt` namespace automatically if it isn't already present
+ args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
+ return ! e.match(/\.dt\b/) ?
+ e+'.dt' :
+ e;
+ } ).join( ' ' );
+
+ var inst = $( this.tables().nodes() );
+ inst[key].apply( inst, args );
+ return this;
+ } );
+ } );
+
+
+ _api_register( 'clear()', function () {
+ return this.iterator( 'table', function ( settings ) {
+ _fnClearTable( settings );
+ } );
+ } );
+
+
+ _api_register( 'settings()', function () {
+ return new _Api( this.context, this.context );
+ } );
+
+
+ _api_register( 'init()', function () {
+ var ctx = this.context;
+ return ctx.length ? ctx[0].oInit : null;
+ } );
+
+
+ _api_register( 'data()', function () {
+ return this.iterator( 'table', function ( settings ) {
+ return _pluck( settings.aoData, '_aData' );
+ } ).flatten();
+ } );
+
+
+ _api_register( 'destroy()', function ( remove ) {
+ remove = remove || false;
+
+ return this.iterator( 'table', function ( settings ) {
+ var orig = settings.nTableWrapper.parentNode;
+ var classes = settings.oClasses;
+ var table = settings.nTable;
+ var tbody = settings.nTBody;
+ var thead = settings.nTHead;
+ var tfoot = settings.nTFoot;
+ var jqTable = $(table);
+ var jqTbody = $(tbody);
+ var jqWrapper = $(settings.nTableWrapper);
+ var rows = $.map( settings.aoData, function (r) { return r.nTr; } );
+ var i, ien;
+
+ // Flag to note that the table is currently being destroyed - no action
+ // should be taken
+ settings.bDestroying = true;
+
+ // Fire off the destroy callbacks for plug-ins etc
+ _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
+
+ // If not being removed from the document, make all columns visible
+ if ( ! remove ) {
+ new _Api( settings ).columns().visible( true );
+ }
+
+ // Blitz all `DT` namespaced events (these are internal events, the
+ // lowercase, `dt` events are user subscribed and they are responsible
+ // for removing them
+ jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
+ $(window).off('.DT-'+settings.sInstance);
+
+ // When scrolling we had to break the table up - restore it
+ if ( table != thead.parentNode ) {
+ jqTable.children('thead').detach();
+ jqTable.append( thead );
+ }
+
+ if ( tfoot && table != tfoot.parentNode ) {
+ jqTable.children('tfoot').detach();
+ jqTable.append( tfoot );
+ }
+
+ settings.aaSorting = [];
+ settings.aaSortingFixed = [];
+ _fnSortingClasses( settings );
+
+ $( rows ).removeClass( settings.asStripeClasses.join(' ') );
+
+ $('th, td', thead).removeClass( classes.sSortable+' '+
+ classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
+ );
+
+ // Add the TR elements back into the table in their original order
+ jqTbody.children().detach();
+ jqTbody.append( rows );
+
+ // Remove the DataTables generated nodes, events and classes
+ var removedMethod = remove ? 'remove' : 'detach';
+ jqTable[ removedMethod ]();
+ jqWrapper[ removedMethod ]();
+
+ // If we need to reattach the table to the document
+ if ( ! remove && orig ) {
+ // insertBefore acts like appendChild if !arg[1]
+ orig.insertBefore( table, settings.nTableReinsertBefore );
+
+ // Restore the width of the original table - was read from the style property,
+ // so we can restore directly to that
+ jqTable
+ .css( 'width', settings.sDestroyWidth )
+ .removeClass( classes.sTable );
+
+ // If the were originally stripe classes - then we add them back here.
+ // Note this is not fool proof (for example if not all rows had stripe
+ // classes - but it's a good effort without getting carried away
+ ien = settings.asDestroyStripes.length;
+
+ if ( ien ) {
+ jqTbody.children().each( function (i) {
+ $(this).addClass( settings.asDestroyStripes[i % ien] );
+ } );
+ }
+ }
+
+ /* Remove the settings object from the settings array */
+ var idx = $.inArray( settings, DataTable.settings );
+ if ( idx !== -1 ) {
+ DataTable.settings.splice( idx, 1 );
+ }
+ } );
+ } );
+
+
+ // Add the `every()` method for rows, columns and cells in a compact form
+ $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
+ _api_register( type+'s().every()', function ( fn ) {
+ var opts = this.selector.opts;
+ var api = this;
+
+ return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
+ // Rows and columns:
+ // arg1 - index
+ // arg2 - table counter
+ // arg3 - loop counter
+ // arg4 - undefined
+ // Cells:
+ // arg1 - row index
+ // arg2 - column index
+ // arg3 - table counter
+ // arg4 - loop counter
+ fn.call(
+ api[ type ](
+ arg1,
+ type==='cell' ? arg2 : opts,
+ type==='cell' ? opts : undefined
+ ),
+ arg1, arg2, arg3, arg4
+ );
+ } );
+ } );
+ } );
+
+
+ // i18n method for extensions to be able to use the language object from the
+ // DataTable
+ _api_register( 'i18n()', function ( token, def, plural ) {
+ var ctx = this.context[0];
+ var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
+
+ if ( resolved === undefined ) {
+ resolved = def;
+ }
+
+ if ( plural !== undefined && $.isPlainObject( resolved ) ) {
+ resolved = resolved[ plural ] !== undefined ?
+ resolved[ plural ] :
+ resolved._;
+ }
+
+ return resolved.replace( '%d', plural ); // nb: plural might be undefined,
+ } );
+ /**
+ * Version string for plug-ins to check compatibility. Allowed format is
+ * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
+ * only for non-release builds. See http://semver.org/ for more information.
+ * @member
+ * @type string
+ * @default Version number
+ */
+ DataTable.version = "1.10.16";
+
+ /**
+ * Private data store, containing all of the settings objects that are
+ * created for the tables on a given page.
+ *
+ * Note that the `DataTable.settings` object is aliased to
+ * `jQuery.fn.dataTableExt` through which it may be accessed and
+ * manipulated, or `jQuery.fn.dataTable.settings`.
+ * @member
+ * @type array
+ * @default []
+ * @private
+ */
+ DataTable.settings = [];
+
+ /**
+ * Object models container, for the various models that DataTables has
+ * available to it. These models define the objects that are used to hold
+ * the active state and configuration of the table.
+ * @namespace
+ */
+ DataTable.models = {};
+
+
+
+ /**
+ * Template object for the way in which DataTables holds information about
+ * search information for the global filter and individual column filters.
+ * @namespace
+ */
+ DataTable.models.oSearch = {
+ /**
+ * Flag to indicate if the filtering should be case insensitive or not
+ * @type boolean
+ * @default true
+ */
+ "bCaseInsensitive": true,
+
+ /**
+ * Applied search term
+ * @type string
+ * @default <i>Empty string</i>
+ */
+ "sSearch": "",
+
+ /**
+ * Flag to indicate if the search term should be interpreted as a
+ * regular expression (true) or not (false) and therefore and special
+ * regex characters escaped.
+ * @type boolean
+ * @default false
+ */
+ "bRegex": false,
+
+ /**
+ * Flag to indicate if DataTables is to use its smart filtering or not.
+ * @type boolean
+ * @default true
+ */
+ "bSmart": true
+ };
+
+
+
+
+ /**
+ * Template object for the way in which DataTables holds information about
+ * each individual row. This is the object format used for the settings
+ * aoData array.
+ * @namespace
+ */
+ DataTable.models.oRow = {
+ /**
+ * TR element for the row
+ * @type node
+ * @default null
+ */
+ "nTr": null,
+
+ /**
+ * Array of TD elements for each row. This is null until the row has been
+ * created.
+ * @type array nodes
+ * @default []
+ */
+ "anCells": null,
+
+ /**
+ * Data object from the original data source for the row. This is either
+ * an array if using the traditional form of DataTables, or an object if
+ * using mData options. The exact type will depend on the passed in
+ * data from the data source, or will be an array if using DOM a data
+ * source.
+ * @type array|object
+ * @default []
+ */
+ "_aData": [],
+
+ /**
+ * Sorting data cache - this array is ostensibly the same length as the
+ * number of columns (although each index is generated only as it is
+ * needed), and holds the data that is used for sorting each column in the
+ * row. We do this cache generation at the start of the sort in order that
+ * the formatting of the sort data need be done only once for each cell
+ * per sort. This array should not be read from or written to by anything
+ * other than the master sorting methods.
+ * @type array
+ * @default null
+ * @private
+ */
+ "_aSortData": null,
+
+ /**
+ * Per cell filtering data cache. As per the sort data cache, used to
+ * increase the performance of the filtering in DataTables
+ * @type array
+ * @default null
+ * @private
+ */
+ "_aFilterData": null,
+
+ /**
+ * Filtering data cache. This is the same as the cell filtering cache, but
+ * in this case a string rather than an array. This is easily computed with
+ * a join on `_aFilterData`, but is provided as a cache so the join isn't
+ * needed on every search (memory traded for performance)
+ * @type array
+ * @default null
+ * @private
+ */
+ "_sFilterRow": null,
+
+ /**
+ * Cache of the class name that DataTables has applied to the row, so we
+ * can quickly look at this variable rather than needing to do a DOM check
+ * on className for the nTr property.
+ * @type string
+ * @default <i>Empty string</i>
+ * @private
+ */
+ "_sRowStripe": "",
+
+ /**
+ * Denote if the original data source was from the DOM, or the data source
+ * object. This is used for invalidating data, so DataTables can
+ * automatically read data from the original source, unless uninstructed
+ * otherwise.
+ * @type string
+ * @default null
+ * @private
+ */
+ "src": null,
+
+ /**
+ * Index in the aoData array. This saves an indexOf lookup when we have the
+ * object, but want to know the index
+ * @type integer
+ * @default -1
+ * @private
+ */
+ "idx": -1
+ };
+
+
+ /**
+ * Template object for the column information object in DataTables. This object
+ * is held in the settings aoColumns array and contains all the information that
+ * DataTables needs about each individual column.
+ *
+ * Note that this object is related to {@link DataTable.defaults.column}
+ * but this one is the internal data store for DataTables's cache of columns.
+ * It should NOT be manipulated outside of DataTables. Any configuration should
+ * be done through the initialisation options.
+ * @namespace
+ */
+ DataTable.models.oColumn = {
+ /**
+ * Column index. This could be worked out on-the-fly with $.inArray, but it
+ * is faster to just hold it as a variable
+ * @type integer
+ * @default null
+ */
+ "idx": null,
+
+ /**
+ * A list of the columns that sorting should occur on when this column
+ * is sorted. That this property is an array allows multi-column sorting
+ * to be defined for a column (for example first name / last name columns
+ * would benefit from this). The values are integers pointing to the
+ * columns to be sorted on (typically it will be a single integer pointing
+ * at itself, but that doesn't need to be the case).
+ * @type array
+ */
+ "aDataSort": null,
+
+ /**
+ * Define the sorting directions that are applied to the column, in sequence
+ * as the column is repeatedly sorted upon - i.e. the first value is used
+ * as the sorting direction when the column if first sorted (clicked on).
+ * Sort it again (click again) and it will move on to the next index.
+ * Repeat until loop.
+ * @type array
+ */
+ "asSorting": null,
+
+ /**
+ * Flag to indicate if the column is searchable, and thus should be included
+ * in the filtering or not.
+ * @type boolean
+ */
+ "bSearchable": null,
+
+ /**
+ * Flag to indicate if the column is sortable or not.
+ * @type boolean
+ */
+ "bSortable": null,
+
+ /**
+ * Flag to indicate if the column is currently visible in the table or not
+ * @type boolean
+ */
+ "bVisible": null,
+
+ /**
+ * Store for manual type assignment using the `column.type` option. This
+ * is held in store so we can manipulate the column's `sType` property.
+ * @type string
+ * @default null
+ * @private
+ */
+ "_sManualType": null,
+
+ /**
+ * Flag to indicate if HTML5 data attributes should be used as the data
+ * source for filtering or sorting. True is either are.
+ * @type boolean
+ * @default false
+ * @private
+ */
+ "_bAttrSrc": false,
+
+ /**
+ * Developer definable function that is called whenever a cell is created (Ajax source,
+ * etc) or processed for input (DOM source). This can be used as a compliment to mRender
+ * allowing you to modify the DOM element (add background colour for example) when the
+ * element is available.
+ * @type function
+ * @param {element} nTd The TD node that has been created
+ * @param {*} sData The Data for the cell
+ * @param {array|object} oData The data for the whole row
+ * @param {int} iRow The row index for the aoData data store
+ * @default null
+ */
+ "fnCreatedCell": null,
+
+ /**
+ * Function to get data from a cell in a column. You should <b>never</b>
+ * access data directly through _aData internally in DataTables - always use
+ * the method attached to this property. It allows mData to function as
+ * required. This function is automatically assigned by the column
+ * initialisation method
+ * @type function
+ * @param {array|object} oData The data array/object for the array
+ * (i.e. aoData[]._aData)
+ * @param {string} sSpecific The specific data type you want to get -
+ * 'display', 'type' 'filter' 'sort'
+ * @returns {*} The data for the cell from the given row's data
+ * @default null
+ */
+ "fnGetData": null,
+
+ /**
+ * Function to set data for a cell in the column. You should <b>never</b>
+ * set the data directly to _aData internally in DataTables - always use
+ * this method. It allows mData to function as required. This function
+ * is automatically assigned by the column initialisation method
+ * @type function
+ * @param {array|object} oData The data array/object for the array
+ * (i.e. aoData[]._aData)
+ * @param {*} sValue Value to set
+ * @default null
+ */
+ "fnSetData": null,
+
+ /**
+ * Property to read the value for the cells in the column from the data
+ * source array / object. If null, then the default content is used, if a
+ * function is given then the return from the function is used.
+ * @type function|int|string|null
+ * @default null
+ */
+ "mData": null,
+
+ /**
+ * Partner property to mData which is used (only when defined) to get
+ * the data - i.e. it is basically the same as mData, but without the
+ * 'set' option, and also the data fed to it is the result from mData.
+ * This is the rendering method to match the data method of mData.
+ * @type function|int|string|null
+ * @default null
+ */
+ "mRender": null,
+
+ /**
+ * Unique header TH/TD element for this column - this is what the sorting
+ * listener is attached to (if sorting is enabled.)
+ * @type node
+ * @default null
+ */
+ "nTh": null,
+
+ /**
+ * Unique footer TH/TD element for this column (if there is one). Not used
+ * in DataTables as such, but can be used for plug-ins to reference the
+ * footer for each column.
+ * @type node
+ * @default null
+ */
+ "nTf": null,
+
+ /**
+ * The class to apply to all TD elements in the table's TBODY for the column
+ * @type string
+ * @default null
+ */
+ "sClass": null,
+
+ /**
+ * When DataTables calculates the column widths to assign to each column,
+ * it finds the longest string in each column and then constructs a
+ * temporary table and reads the widths from that. The problem with this
+ * is that "mmm" is much wider then "iiii", but the latter is a longer
+ * string - thus the calculation can go wrong (doing it properly and putting
+ * it into an DOM object and measuring that is horribly(!) slow). Thus as
+ * a "work around" we provide this option. It will append its value to the
+ * text that is found to be the longest string for the column - i.e. padding.
+ * @type string
+ */
+ "sContentPadding": null,
+
+ /**
+ * Allows a default value to be given for a column's data, and will be used
+ * whenever a null data source is encountered (this can be because mData
+ * is set to null, or because the data source itself is null).
+ * @type string
+ * @default null
+ */
+ "sDefaultContent": null,
+
+ /**
+ * Name for the column, allowing reference to the column by name as well as
+ * by index (needs a lookup to work by name).
+ * @type string
+ */
+ "sName": null,
+
+ /**
+ * Custom sorting data type - defines which of the available plug-ins in
+ * afnSortData the custom sorting will use - if any is defined.
+ * @type string
+ * @default std
+ */
+ "sSortDataType": 'std',
+
+ /**
+ * Class to be applied to the header element when sorting on this column
+ * @type string
+ * @default null
+ */
+ "sSortingClass": null,
+
+ /**
+ * Class to be applied to the header element when sorting on this column -
+ * when jQuery UI theming is used.
+ * @type string
+ * @default null
+ */
+ "sSortingClassJUI": null,
+
+ /**
+ * Title of the column - what is seen in the TH element (nTh).
+ * @type string
+ */
+ "sTitle": null,
+
+ /**
+ * Column sorting and filtering type
+ * @type string
+ * @default null
+ */
+ "sType": null,
+
+ /**
+ * Width of the column
+ * @type string
+ * @default null
+ */
+ "sWidth": null,
+
+ /**
+ * Width of the column when it was first "encountered"
+ * @type string
+ * @default null
+ */
+ "sWidthOrig": null
+ };
+
+
+ /*
+ * Developer note: The properties of the object below are given in Hungarian
+ * notation, that was used as the interface for DataTables prior to v1.10, however
+ * from v1.10 onwards the primary interface is camel case. In order to avoid
+ * breaking backwards compatibility utterly with this change, the Hungarian
+ * version is still, internally the primary interface, but is is not documented
+ * - hence the @name tags in each doc comment. This allows a Javascript function
+ * to create a map from Hungarian notation to camel case (going the other direction
+ * would require each property to be listed, which would at around 3K to the size
+ * of DataTables, while this method is about a 0.5K hit.
+ *
+ * Ultimately this does pave the way for Hungarian notation to be dropped
+ * completely, but that is a massive amount of work and will break current
+ * installs (therefore is on-hold until v2).
+ */
+
+ /**
+ * Initialisation options that can be given to DataTables at initialisation
+ * time.
+ * @namespace
+ */
+ DataTable.defaults = {
+ /**
+ * An array of data to use for the table, passed in at initialisation which
+ * will be used in preference to any data which is already in the DOM. This is
+ * particularly useful for constructing tables purely in Javascript, for
+ * example with a custom Ajax call.
+ * @type array
+ * @default null
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.data
+ *
+ * @example
+ * // Using a 2D array data source
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "data": [
+ * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
+ * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
+ * ],
+ * "columns": [
+ * { "title": "Engine" },
+ * { "title": "Browser" },
+ * { "title": "Platform" },
+ * { "title": "Version" },
+ * { "title": "Grade" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using an array of objects as a data source (`data`)
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "data": [
+ * {
+ * "engine": "Trident",
+ * "browser": "Internet Explorer 4.0",
+ * "platform": "Win 95+",
+ * "version": 4,
+ * "grade": "X"
+ * },
+ * {
+ * "engine": "Trident",
+ * "browser": "Internet Explorer 5.0",
+ * "platform": "Win 95+",
+ * "version": 5,
+ * "grade": "C"
+ * }
+ * ],
+ * "columns": [
+ * { "title": "Engine", "data": "engine" },
+ * { "title": "Browser", "data": "browser" },
+ * { "title": "Platform", "data": "platform" },
+ * { "title": "Version", "data": "version" },
+ * { "title": "Grade", "data": "grade" }
+ * ]
+ * } );
+ * } );
+ */
+ "aaData": null,
+
+
+ /**
+ * If ordering is enabled, then DataTables will perform a first pass sort on
+ * initialisation. You can define which column(s) the sort is performed
+ * upon, and the sorting direction, with this variable. The `sorting` array
+ * should contain an array for each column to be sorted initially containing
+ * the column's index and a direction string ('asc' or 'desc').
+ * @type array
+ * @default [[0,'asc']]
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.order
+ *
+ * @example
+ * // Sort by 3rd column first, and then 4th column
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "order": [[2,'asc'], [3,'desc']]
+ * } );
+ * } );
+ *
+ * // No initial sorting
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "order": []
+ * } );
+ * } );
+ */
+ "aaSorting": [[0,'asc']],
+
+
+ /**
+ * This parameter is basically identical to the `sorting` parameter, but
+ * cannot be overridden by user interaction with the table. What this means
+ * is that you could have a column (visible or hidden) which the sorting
+ * will always be forced on first - any sorting after that (from the user)
+ * will then be performed as required. This can be useful for grouping rows
+ * together.
+ * @type array
+ * @default null
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.orderFixed
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "orderFixed": [[0,'asc']]
+ * } );
+ * } )
+ */
+ "aaSortingFixed": [],
+
+
+ /**
+ * DataTables can be instructed to load data to display in the table from a
+ * Ajax source. This option defines how that Ajax call is made and where to.
+ *
+ * The `ajax` property has three different modes of operation, depending on
+ * how it is defined. These are:
+ *
+ * * `string` - Set the URL from where the data should be loaded from.
+ * * `object` - Define properties for `jQuery.ajax`.
+ * * `function` - Custom data get function
+ *
+ * `string`
+ * --------
+ *
+ * As a string, the `ajax` property simply defines the URL from which
+ * DataTables will load data.
+ *
+ * `object`
+ * --------
+ *
+ * As an object, the parameters in the object are passed to
+ * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
+ * of the Ajax request. DataTables has a number of default parameters which
+ * you can override using this option. Please refer to the jQuery
+ * documentation for a full description of the options available, although
+ * the following parameters provide additional options in DataTables or
+ * require special consideration:
+ *
+ * * `data` - As with jQuery, `data` can be provided as an object, but it
+ * can also be used as a function to manipulate the data DataTables sends
+ * to the server. The function takes a single parameter, an object of
+ * parameters with the values that DataTables has readied for sending. An
+ * object may be returned which will be merged into the DataTables
+ * defaults, or you can add the items to the object that was passed in and
+ * not return anything from the function. This supersedes `fnServerParams`
+ * from DataTables 1.9-.
+ *
+ * * `dataSrc` - By default DataTables will look for the property `data` (or
+ * `aaData` for compatibility with DataTables 1.9-) when obtaining data
+ * from an Ajax source or for server-side processing - this parameter
+ * allows that property to be changed. You can use Javascript dotted
+ * object notation to get a data source for multiple levels of nesting, or
+ * it my be used as a function. As a function it takes a single parameter,
+ * the JSON returned from the server, which can be manipulated as
+ * required, with the returned value being that used by DataTables as the
+ * data source for the table. This supersedes `sAjaxDataProp` from
+ * DataTables 1.9-.
+ *
+ * * `success` - Should not be overridden it is used internally in
+ * DataTables. To manipulate / transform the data returned by the server
+ * use `ajax.dataSrc`, or use `ajax` as a function (see below).
+ *
+ * `function`
+ * ----------
+ *
+ * As a function, making the Ajax call is left up to yourself allowing
+ * complete control of the Ajax request. Indeed, if desired, a method other
+ * than Ajax could be used to obtain the required data, such as Web storage
+ * or an AIR database.
+ *
+ * The function is given four parameters and no return is required. The
+ * parameters are:
+ *
+ * 1. _object_ - Data to send to the server
+ * 2. _function_ - Callback function that must be executed when the required
+ * data has been obtained. That data should be passed into the callback
+ * as the only parameter
+ * 3. _object_ - DataTables settings object for the table
+ *
+ * Note that this supersedes `fnServerData` from DataTables 1.9-.
+ *
+ * @type string|object|function
+ * @default null
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.ajax
+ * @since 1.10.0
+ *
+ * @example
+ * // Get JSON data from a file via Ajax.
+ * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
+ * $('#example').dataTable( {
+ * "ajax": "data.json"
+ * } );
+ *
+ * @example
+ * // Get JSON data from a file via Ajax, using `dataSrc` to change
+ * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
+ * $('#example').dataTable( {
+ * "ajax": {
+ * "url": "data.json",
+ * "dataSrc": "tableData"
+ * }
+ * } );
+ *
+ * @example
+ * // Get JSON data from a file via Ajax, using `dataSrc` to read data
+ * // from a plain array rather than an array in an object
+ * $('#example').dataTable( {
+ * "ajax": {
+ * "url": "data.json",
+ * "dataSrc": ""
+ * }
+ * } );
+ *
+ * @example
+ * // Manipulate the data returned from the server - add a link to data
+ * // (note this can, should, be done using `render` for the column - this
+ * // is just a simple example of how the data can be manipulated).
+ * $('#example').dataTable( {
+ * "ajax": {
+ * "url": "data.json",
+ * "dataSrc": function ( json ) {
+ * for ( var i=0, ien=json.length ; i<ien ; i++ ) {
+ * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
+ * }
+ * return json;
+ * }
+ * }
+ * } );
+ *
+ * @example
+ * // Add data to the request
+ * $('#example').dataTable( {
+ * "ajax": {
+ * "url": "data.json",
+ * "data": function ( d ) {
+ * return {
+ * "extra_search": $('#extra').val()
+ * };
+ * }
+ * }
+ * } );
+ *
+ * @example
+ * // Send request as POST
+ * $('#example').dataTable( {
+ * "ajax": {
+ * "url": "data.json",
+ * "type": "POST"
+ * }
+ * } );
+ *
+ * @example
+ * // Get the data from localStorage (could interface with a form for
+ * // adding, editing and removing rows).
+ * $('#example').dataTable( {
+ * "ajax": function (data, callback, settings) {
+ * callback(
+ * JSON.parse( localStorage.getItem('dataTablesData') )
+ * );
+ * }
+ * } );
+ */
+ "ajax": null,
+
+
+ /**
+ * This parameter allows you to readily specify the entries in the length drop
+ * down menu that DataTables shows when pagination is enabled. It can be
+ * either a 1D array of options which will be used for both the displayed
+ * option and the value, or a 2D array which will use the array in the first
+ * position as the value, and the array in the second position as the
+ * displayed options (useful for language strings such as 'All').
+ *
+ * Note that the `pageLength` property will be automatically set to the
+ * first value given in this array, unless `pageLength` is also provided.
+ * @type array
+ * @default [ 10, 25, 50, 100 ]
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.lengthMenu
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
+ * } );
+ * } );
+ */
+ "aLengthMenu": [ 10, 25, 50, 100 ],
+
+
+ /**
+ * The `columns` option in the initialisation parameter allows you to define
+ * details about the way individual columns behave. For a full list of
+ * column options that can be set, please see
+ * {@link DataTable.defaults.column}. Note that if you use `columns` to
+ * define your columns, you must have an entry in the array for every single
+ * column that you have in your table (these can be null if you don't which
+ * to specify any options).
+ * @member
+ *
+ * @name DataTable.defaults.column
+ */
+ "aoColumns": null,
+
+ /**
+ * Very similar to `columns`, `columnDefs` allows you to target a specific
+ * column, multiple columns, or all columns, using the `targets` property of
+ * each object in the array. This allows great flexibility when creating
+ * tables, as the `columnDefs` arrays can be of any length, targeting the
+ * columns you specifically want. `columnDefs` may use any of the column
+ * options available: {@link DataTable.defaults.column}, but it _must_
+ * have `targets` defined in each object in the array. Values in the `targets`
+ * array may be:
+ * <ul>
+ * <li>a string - class name will be matched on the TH for the column</li>
+ * <li>0 or a positive integer - column index counting from the left</li>
+ * <li>a negative integer - column index counting from the right</li>
+ * <li>the string "_all" - all columns (i.e. assign a default)</li>
+ * </ul>
+ * @member
+ *
+ * @name DataTable.defaults.columnDefs
+ */
+ "aoColumnDefs": null,
+
+
+ /**
+ * Basically the same as `search`, this parameter defines the individual column
+ * filtering state at initialisation time. The array must be of the same size
+ * as the number of columns, and each element be an object with the parameters
+ * `search` and `escapeRegex` (the latter is optional). 'null' is also
+ * accepted and the default will be used.
+ * @type array
+ * @default []
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.searchCols
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "searchCols": [
+ * null,
+ * { "search": "My filter" },
+ * null,
+ * { "search": "^[0-9]", "escapeRegex": false }
+ * ]
+ * } );
+ * } )
+ */
+ "aoSearchCols": [],
+
+
+ /**
+ * An array of CSS classes that should be applied to displayed rows. This
+ * array may be of any length, and DataTables will apply each class
+ * sequentially, looping when required.
+ * @type array
+ * @default null <i>Will take the values determined by the `oClasses.stripe*`
+ * options</i>
+ *
+ * @dtopt Option
+ * @name DataTable.defaults.stripeClasses
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
+ * } );
+ * } )
+ */
+ "asStripeClasses": null,
+
+
+ /**
+ * Enable or disable automatic column width calculation. This can be disabled
+ * as an optimisation (it takes some time to calculate the widths) if the
+ * tables widths are passed in using `columns`.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.autoWidth
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "autoWidth": false
+ * } );
+ * } );
+ */
+ "bAutoWidth": true,
+
+
+ /**
+ * Deferred rendering can provide DataTables with a huge speed boost when you
+ * are using an Ajax or JS data source for the table. This option, when set to
+ * true, will cause DataTables to defer the creation of the table elements for
+ * each row until they are needed for a draw - saving a significant amount of
+ * time.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.deferRender
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "ajax": "sources/arrays.txt",
+ * "deferRender": true
+ * } );
+ * } );
+ */
+ "bDeferRender": false,
+
+
+ /**
+ * Replace a DataTable which matches the given selector and replace it with
+ * one which has the properties of the new initialisation object passed. If no
+ * table matches the selector, then the new DataTable will be constructed as
+ * per normal.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.destroy
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "srollY": "200px",
+ * "paginate": false
+ * } );
+ *
+ * // Some time later....
+ * $('#example').dataTable( {
+ * "filter": false,
+ * "destroy": true
+ * } );
+ * } );
+ */
+ "bDestroy": false,
+
+
+ /**
+ * Enable or disable filtering of data. Filtering in DataTables is "smart" in
+ * that it allows the end user to input multiple words (space separated) and
+ * will match a row containing those words, even if not in the order that was
+ * specified (this allow matching across multiple columns). Note that if you
+ * wish to use filtering in DataTables this must remain 'true' - to remove the
+ * default filtering input box and retain filtering abilities, please use
+ * {@link DataTable.defaults.dom}.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.searching
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "searching": false
+ * } );
+ * } );
+ */
+ "bFilter": true,
+
+
+ /**
+ * Enable or disable the table information display. This shows information
+ * about the data that is currently visible on the page, including information
+ * about filtered data if that action is being performed.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.info
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "info": false
+ * } );
+ * } );
+ */
+ "bInfo": true,
+
+
+ /**
+ * Allows the end user to select the size of a formatted page from a select
+ * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.lengthChange
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "lengthChange": false
+ * } );
+ * } );
+ */
+ "bLengthChange": true,
+
+
+ /**
+ * Enable or disable pagination.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.paging
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "paging": false
+ * } );
+ * } );
+ */
+ "bPaginate": true,
+
+
+ /**
+ * Enable or disable the display of a 'processing' indicator when the table is
+ * being processed (e.g. a sort). This is particularly useful for tables with
+ * large amounts of data where it can take a noticeable amount of time to sort
+ * the entries.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.processing
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "processing": true
+ * } );
+ * } );
+ */
+ "bProcessing": false,
+
+
+ /**
+ * Retrieve the DataTables object for the given selector. Note that if the
+ * table has already been initialised, this parameter will cause DataTables
+ * to simply return the object that has already been set up - it will not take
+ * account of any changes you might have made to the initialisation object
+ * passed to DataTables (setting this parameter to true is an acknowledgement
+ * that you understand this). `destroy` can be used to reinitialise a table if
+ * you need.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.retrieve
+ *
+ * @example
+ * $(document).ready( function() {
+ * initTable();
+ * tableActions();
+ * } );
+ *
+ * function initTable ()
+ * {
+ * return $('#example').dataTable( {
+ * "scrollY": "200px",
+ * "paginate": false,
+ * "retrieve": true
+ * } );
+ * }
+ *
+ * function tableActions ()
+ * {
+ * var table = initTable();
+ * // perform API operations with oTable
+ * }
+ */
+ "bRetrieve": false,
+
+
+ /**
+ * When vertical (y) scrolling is enabled, DataTables will force the height of
+ * the table's viewport to the given height at all times (useful for layout).
+ * However, this can look odd when filtering data down to a small data set,
+ * and the footer is left "floating" further down. This parameter (when
+ * enabled) will cause DataTables to collapse the table's viewport down when
+ * the result set will fit within the given Y height.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.scrollCollapse
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "scrollY": "200",
+ * "scrollCollapse": true
+ * } );
+ * } );
+ */
+ "bScrollCollapse": false,
+
+
+ /**
+ * Configure DataTables to use server-side processing. Note that the
+ * `ajax` parameter must also be given in order to give DataTables a
+ * source to obtain the required data for each draw.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @dtopt Server-side
+ * @name DataTable.defaults.serverSide
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "serverSide": true,
+ * "ajax": "xhr.php"
+ * } );
+ * } );
+ */
+ "bServerSide": false,
+
+
+ /**
+ * Enable or disable sorting of columns. Sorting of individual columns can be
+ * disabled by the `sortable` option for each column.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.ordering
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "ordering": false
+ * } );
+ * } );
+ */
+ "bSort": true,
+
+
+ /**
+ * Enable or display DataTables' ability to sort multiple columns at the
+ * same time (activated by shift-click by the user).
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.orderMulti
+ *
+ * @example
+ * // Disable multiple column sorting ability
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "orderMulti": false
+ * } );
+ * } );
+ */
+ "bSortMulti": true,
+
+
+ /**
+ * Allows control over whether DataTables should use the top (true) unique
+ * cell that is found for a single column, or the bottom (false - default).
+ * This is useful when using complex headers.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.orderCellsTop
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "orderCellsTop": true
+ * } );
+ * } );
+ */
+ "bSortCellsTop": false,
+
+
+ /**
+ * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
+ * `sorting\_3` to the columns which are currently being sorted on. This is
+ * presented as a feature switch as it can increase processing time (while
+ * classes are removed and added) so for large data sets you might want to
+ * turn this off.
+ * @type boolean
+ * @default true
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.orderClasses
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "orderClasses": false
+ * } );
+ * } );
+ */
+ "bSortClasses": true,
+
+
+ /**
+ * Enable or disable state saving. When enabled HTML5 `localStorage` will be
+ * used to save table display information such as pagination information,
+ * display length, filtering and sorting. As such when the end user reloads
+ * the page the display display will match what thy had previously set up.
+ *
+ * Due to the use of `localStorage` the default state saving is not supported
+ * in IE6 or 7. If state saving is required in those browsers, use
+ * `stateSaveCallback` to provide a storage solution such as cookies.
+ * @type boolean
+ * @default false
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.stateSave
+ *
+ * @example
+ * $(document).ready( function () {
+ * $('#example').dataTable( {
+ * "stateSave": true
+ * } );
+ * } );
+ */
+ "bStateSave": false,
+
+
+ /**
+ * This function is called when a TR element is created (and all TD child
+ * elements have been inserted), or registered if using a DOM source, allowing
+ * manipulation of the TR element (adding classes etc).
+ * @type function
+ * @param {node} row "TR" element for the current row
+ * @param {array} data Raw data array for this row
+ * @param {int} dataIndex The index of this row in the internal aoData array
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.createdRow
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "createdRow": function( row, data, dataIndex ) {
+ * // Bold the grade for all 'A' grade browsers
+ * if ( data[4] == "A" )
+ * {
+ * $('td:eq(4)', row).html( '<b>A</b>' );
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnCreatedRow": null,
+
+
+ /**
+ * This function is called on every 'draw' event, and allows you to
+ * dynamically modify any aspect you want about the created DOM.
+ * @type function
+ * @param {object} settings DataTables settings object
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.drawCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "drawCallback": function( settings ) {
+ * alert( 'DataTables has redrawn the table' );
+ * }
+ * } );
+ * } );
+ */
+ "fnDrawCallback": null,
+
+
+ /**
+ * Identical to fnHeaderCallback() but for the table footer this function
+ * allows you to modify the table footer on every 'draw' event.
+ * @type function
+ * @param {node} foot "TR" element for the footer
+ * @param {array} data Full table data (as derived from the original HTML)
+ * @param {int} start Index for the current display starting point in the
+ * display array
+ * @param {int} end Index for the current display ending point in the
+ * display array
+ * @param {array int} display Index array to translate the visual position
+ * to the full data array
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.footerCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "footerCallback": function( tfoot, data, start, end, display ) {
+ * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
+ * }
+ * } );
+ * } )
+ */
+ "fnFooterCallback": null,
+
+
+ /**
+ * When rendering large numbers in the information element for the table
+ * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
+ * to have a comma separator for the 'thousands' units (e.g. 1 million is
+ * rendered as "1,000,000") to help readability for the end user. This
+ * function will override the default method DataTables uses.
+ * @type function
+ * @member
+ * @param {int} toFormat number to be formatted
+ * @returns {string} formatted string for DataTables to show the number
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.formatNumber
+ *
+ * @example
+ * // Format a number using a single quote for the separator (note that
+ * // this can also be done with the language.thousands option)
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "formatNumber": function ( toFormat ) {
+ * return toFormat.toString().replace(
+ * /\B(?=(\d{3})+(?!\d))/g, "'"
+ * );
+ * };
+ * } );
+ * } );
+ */
+ "fnFormatNumber": function ( toFormat ) {
+ return toFormat.toString().replace(
+ /\B(?=(\d{3})+(?!\d))/g,
+ this.oLanguage.sThousands
+ );
+ },
+
+
+ /**
+ * This function is called on every 'draw' event, and allows you to
+ * dynamically modify the header row. This can be used to calculate and
+ * display useful information about the table.
+ * @type function
+ * @param {node} head "TR" element for the header
+ * @param {array} data Full table data (as derived from the original HTML)
+ * @param {int} start Index for the current display starting point in the
+ * display array
+ * @param {int} end Index for the current display ending point in the
+ * display array
+ * @param {array int} display Index array to translate the visual position
+ * to the full data array
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.headerCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "fheaderCallback": function( head, data, start, end, display ) {
+ * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
+ * }
+ * } );
+ * } )
+ */
+ "fnHeaderCallback": null,
+
+
+ /**
+ * The information element can be used to convey information about the current
+ * state of the table. Although the internationalisation options presented by
+ * DataTables are quite capable of dealing with most customisations, there may
+ * be times where you wish to customise the string further. This callback
+ * allows you to do exactly that.
+ * @type function
+ * @param {object} oSettings DataTables settings object
+ * @param {int} start Starting position in data for the draw
+ * @param {int} end End position in data for the draw
+ * @param {int} max Total number of rows in the table (regardless of
+ * filtering)
+ * @param {int} total Total number of rows in the data set, after filtering
+ * @param {string} pre The string that DataTables has formatted using it's
+ * own rules
+ * @returns {string} The string to be displayed in the information element.
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.infoCallback
+ *
+ * @example
+ * $('#example').dataTable( {
+ * "infoCallback": function( settings, start, end, max, total, pre ) {
+ * return start +" to "+ end;
+ * }
+ * } );
+ */
+ "fnInfoCallback": null,
+
+
+ /**
+ * Called when the table has been initialised. Normally DataTables will
+ * initialise sequentially and there will be no need for this function,
+ * however, this does not hold true when using external language information
+ * since that is obtained using an async XHR call.
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @param {object} json The JSON object request from the server - only
+ * present if client-side Ajax sourced data is used
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.initComplete
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "initComplete": function(settings, json) {
+ * alert( 'DataTables has finished its initialisation.' );
+ * }
+ * } );
+ * } )
+ */
+ "fnInitComplete": null,
+
+
+ /**
+ * Called at the very start of each table draw and can be used to cancel the
+ * draw by returning false, any other return (including undefined) results in
+ * the full draw occurring).
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @returns {boolean} False will cancel the draw, anything else (including no
+ * return) will allow it to complete.
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.preDrawCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "preDrawCallback": function( settings ) {
+ * if ( $('#test').val() == 1 ) {
+ * return false;
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnPreDrawCallback": null,
+
+
+ /**
+ * This function allows you to 'post process' each row after it have been
+ * generated for each table draw, but before it is rendered on screen. This
+ * function might be used for setting the row class name etc.
+ * @type function
+ * @param {node} row "TR" element for the current row
+ * @param {array} data Raw data array for this row
+ * @param {int} displayIndex The display index for the current table draw
+ * @param {int} displayIndexFull The index of the data in the full list of
+ * rows (after filtering)
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.rowCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
+ * // Bold the grade for all 'A' grade browsers
+ * if ( data[4] == "A" ) {
+ * $('td:eq(4)', row).html( '<b>A</b>' );
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "fnRowCallback": null,
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * This parameter allows you to override the default function which obtains
+ * the data from the server so something more suitable for your application.
+ * For example you could use POST data, or pull information from a Gears or
+ * AIR database.
+ * @type function
+ * @member
+ * @param {string} source HTTP source to obtain the data from (`ajax`)
+ * @param {array} data A key/value pair object containing the data to send
+ * to the server
+ * @param {function} callback to be called on completion of the data get
+ * process that will draw the data on the page.
+ * @param {object} settings DataTables settings object
+ *
+ * @dtopt Callbacks
+ * @dtopt Server-side
+ * @name DataTable.defaults.serverData
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "fnServerData": null,
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * It is often useful to send extra data to the server when making an Ajax
+ * request - for example custom filtering information, and this callback
+ * function makes it trivial to send extra information to the server. The
+ * passed in parameter is the data set that has been constructed by
+ * DataTables, and you can add to this or modify it as you require.
+ * @type function
+ * @param {array} data Data array (array of objects which are name/value
+ * pairs) that has been constructed by DataTables and will be sent to the
+ * server. In the case of Ajax sourced data with server-side processing
+ * this will be an empty array, for server-side processing there will be a
+ * significant number of parameters!
+ * @returns {undefined} Ensure that you modify the data array passed in,
+ * as this is passed by reference.
+ *
+ * @dtopt Callbacks
+ * @dtopt Server-side
+ * @name DataTable.defaults.serverParams
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "fnServerParams": null,
+
+
+ /**
+ * Load the table state. With this function you can define from where, and how, the
+ * state of a table is loaded. By default DataTables will load from `localStorage`
+ * but you might wish to use a server-side database or cookies.
+ * @type function
+ * @member
+ * @param {object} settings DataTables settings object
+ * @param {object} callback Callback that can be executed when done. It
+ * should be passed the loaded state object.
+ * @return {object} The DataTables state object to be loaded
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateLoadCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateLoadCallback": function (settings, callback) {
+ * $.ajax( {
+ * "url": "/state_load",
+ * "dataType": "json",
+ * "success": function (json) {
+ * callback( json );
+ * }
+ * } );
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoadCallback": function ( settings ) {
+ try {
+ return JSON.parse(
+ (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
+ 'DataTables_'+settings.sInstance+'_'+location.pathname
+ )
+ );
+ } catch (e) {}
+ },
+
+
+ /**
+ * Callback which allows modification of the saved state prior to loading that state.
+ * This callback is called when the table is loading state from the stored data, but
+ * prior to the settings object being modified by the saved state. Note that for
+ * plug-in authors, you should use the `stateLoadParams` event to load parameters for
+ * a plug-in.
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @param {object} data The state object that is to be loaded
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateLoadParams
+ *
+ * @example
+ * // Remove a saved filter, so filtering is never loaded
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateLoadParams": function (settings, data) {
+ * data.oSearch.sSearch = "";
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Disallow state loading by returning false
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateLoadParams": function (settings, data) {
+ * return false;
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoadParams": null,
+
+
+ /**
+ * Callback that is called when the state has been loaded from the state saving method
+ * and the DataTables settings object has been modified as a result of the loaded state.
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @param {object} data The state object that was loaded
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateLoaded
+ *
+ * @example
+ * // Show an alert with the filtering value that was saved
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateLoaded": function (settings, data) {
+ * alert( 'Saved filter was: '+data.oSearch.sSearch );
+ * }
+ * } );
+ * } );
+ */
+ "fnStateLoaded": null,
+
+
+ /**
+ * Save the table state. This function allows you to define where and how the state
+ * information for the table is stored By default DataTables will use `localStorage`
+ * but you might wish to use a server-side database or cookies.
+ * @type function
+ * @member
+ * @param {object} settings DataTables settings object
+ * @param {object} data The state object to be saved
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateSaveCallback
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateSaveCallback": function (settings, data) {
+ * // Send an Ajax request to the server with the state object
+ * $.ajax( {
+ * "url": "/state_save",
+ * "data": data,
+ * "dataType": "json",
+ * "method": "POST"
+ * "success": function () {}
+ * } );
+ * }
+ * } );
+ * } );
+ */
+ "fnStateSaveCallback": function ( settings, data ) {
+ try {
+ (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
+ 'DataTables_'+settings.sInstance+'_'+location.pathname,
+ JSON.stringify( data )
+ );
+ } catch (e) {}
+ },
+
+
+ /**
+ * Callback which allows modification of the state to be saved. Called when the table
+ * has changed state a new state save is required. This method allows modification of
+ * the state saving object prior to actually doing the save, including addition or
+ * other state properties or modification. Note that for plug-in authors, you should
+ * use the `stateSaveParams` event to save parameters for a plug-in.
+ * @type function
+ * @param {object} settings DataTables settings object
+ * @param {object} data The state object to be saved
+ *
+ * @dtopt Callbacks
+ * @name DataTable.defaults.stateSaveParams
+ *
+ * @example
+ * // Remove a saved filter, so filtering is never saved
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateSave": true,
+ * "stateSaveParams": function (settings, data) {
+ * data.oSearch.sSearch = "";
+ * }
+ * } );
+ * } );
+ */
+ "fnStateSaveParams": null,
+
+
+ /**
+ * Duration for which the saved state information is considered valid. After this period
+ * has elapsed the state will be returned to the default.
+ * Value is given in seconds.
+ * @type int
+ * @default 7200 <i>(2 hours)</i>
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.stateDuration
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "stateDuration": 60*60*24; // 1 day
+ * } );
+ * } )
+ */
+ "iStateDuration": 7200,
+
+
+ /**
+ * When enabled DataTables will not make a request to the server for the first
+ * page draw - rather it will use the data already on the page (no sorting etc
+ * will be applied to it), thus saving on an XHR at load time. `deferLoading`
+ * is used to indicate that deferred loading is required, but it is also used
+ * to tell DataTables how many records there are in the full table (allowing
+ * the information element and pagination to be displayed correctly). In the case
+ * where a filtering is applied to the table on initial load, this can be
+ * indicated by giving the parameter as an array, where the first element is
+ * the number of records available after filtering and the second element is the
+ * number of records without filtering (allowing the table information element
+ * to be shown correctly).
+ * @type int | array
+ * @default null
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.deferLoading
+ *
+ * @example
+ * // 57 records available in the table, no filtering applied
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "serverSide": true,
+ * "ajax": "scripts/server_processing.php",
+ * "deferLoading": 57
+ * } );
+ * } );
+ *
+ * @example
+ * // 57 records after filtering, 100 without filtering (an initial filter applied)
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "serverSide": true,
+ * "ajax": "scripts/server_processing.php",
+ * "deferLoading": [ 57, 100 ],
+ * "search": {
+ * "search": "my_filter"
+ * }
+ * } );
+ * } );
+ */
+ "iDeferLoading": null,
+
+
+ /**
+ * Number of rows to display on a single page when using pagination. If
+ * feature enabled (`lengthChange`) then the end user will be able to override
+ * this to a custom setting using a pop-up menu.
+ * @type int
+ * @default 10
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.pageLength
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "pageLength": 50
+ * } );
+ * } )
+ */
+ "iDisplayLength": 10,
+
+
+ /**
+ * Define the starting point for data display when using DataTables with
+ * pagination. Note that this parameter is the number of records, rather than
+ * the page number, so if you have 10 records per page and want to start on
+ * the third page, it should be "20".
+ * @type int
+ * @default 0
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.displayStart
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "displayStart": 20
+ * } );
+ * } )
+ */
+ "iDisplayStart": 0,
+
+
+ /**
+ * By default DataTables allows keyboard navigation of the table (sorting, paging,
+ * and filtering) by adding a `tabindex` attribute to the required elements. This
+ * allows you to tab through the controls and press the enter key to activate them.
+ * The tabindex is default 0, meaning that the tab follows the flow of the document.
+ * You can overrule this using this parameter if you wish. Use a value of -1 to
+ * disable built-in keyboard navigation.
+ * @type int
+ * @default 0
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.tabIndex
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "tabIndex": 1
+ * } );
+ * } );
+ */
+ "iTabIndex": 0,
+
+
+ /**
+ * Classes that DataTables assigns to the various components and features
+ * that it adds to the HTML table. This allows classes to be configured
+ * during initialisation in addition to through the static
+ * {@link DataTable.ext.oStdClasses} object).
+ * @namespace
+ * @name DataTable.defaults.classes
+ */
+ "oClasses": {},
+
+
+ /**
+ * All strings that DataTables uses in the user interface that it creates
+ * are defined in this object, allowing you to modified them individually or
+ * completely replace them all as required.
+ * @namespace
+ * @name DataTable.defaults.language
+ */
+ "oLanguage": {
+ /**
+ * Strings that are used for WAI-ARIA labels and controls only (these are not
+ * actually visible on the page, but will be read by screenreaders, and thus
+ * must be internationalised as well).
+ * @namespace
+ * @name DataTable.defaults.language.aria
+ */
+ "oAria": {
+ /**
+ * ARIA label that is added to the table headers when the column may be
+ * sorted ascending by activing the column (click or return when focused).
+ * Note that the column header is prefixed to this string.
+ * @type string
+ * @default : activate to sort column ascending
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.aria.sortAscending
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "aria": {
+ * "sortAscending": " - click/return to sort ascending"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sSortAscending": ": activate to sort column ascending",
+
+ /**
+ * ARIA label that is added to the table headers when the column may be
+ * sorted descending by activing the column (click or return when focused).
+ * Note that the column header is prefixed to this string.
+ * @type string
+ * @default : activate to sort column ascending
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.aria.sortDescending
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "aria": {
+ * "sortDescending": " - click/return to sort descending"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sSortDescending": ": activate to sort column descending"
+ },
+
+ /**
+ * Pagination string used by DataTables for the built-in pagination
+ * control types.
+ * @namespace
+ * @name DataTable.defaults.language.paginate
+ */
+ "oPaginate": {
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the first page.
+ * @type string
+ * @default First
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.paginate.first
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "paginate": {
+ * "first": "First page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sFirst": "First",
+
+
+ /**
+ * Text to use when using the 'full_numbers' type of pagination for the
+ * button to take the user to the last page.
+ * @type string
+ * @default Last
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.paginate.last
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "paginate": {
+ * "last": "Last page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sLast": "Last",
+
+
+ /**
+ * Text to use for the 'next' pagination button (to take the user to the
+ * next page).
+ * @type string
+ * @default Next
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.paginate.next
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "paginate": {
+ * "next": "Next page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sNext": "Next",
+
+
+ /**
+ * Text to use for the 'previous' pagination button (to take the user to
+ * the previous page).
+ * @type string
+ * @default Previous
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.paginate.previous
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "paginate": {
+ * "previous": "Previous page"
+ * }
+ * }
+ * } );
+ * } );
+ */
+ "sPrevious": "Previous"
+ },
+
+ /**
+ * This string is shown in preference to `zeroRecords` when the table is
+ * empty of data (regardless of filtering). Note that this is an optional
+ * parameter - if it is not given, the value of `zeroRecords` will be used
+ * instead (either the default or given value).
+ * @type string
+ * @default No data available in table
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.emptyTable
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "emptyTable": "No data available in table"
+ * }
+ * } );
+ * } );
+ */
+ "sEmptyTable": "No data available in table",
+
+
+ /**
+ * This string gives information to the end user about the information
+ * that is current on display on the page. The following tokens can be
+ * used in the string and will be dynamically replaced as the table
+ * display updates. This tokens can be placed anywhere in the string, or
+ * removed as needed by the language requires:
+ *
+ * * `\_START\_` - Display index of the first record on the current page
+ * * `\_END\_` - Display index of the last record on the current page
+ * * `\_TOTAL\_` - Number of records in the table after filtering
+ * * `\_MAX\_` - Number of records in the table without filtering
+ * * `\_PAGE\_` - Current page number
+ * * `\_PAGES\_` - Total number of pages of data in the table
+ *
+ * @type string
+ * @default Showing _START_ to _END_ of _TOTAL_ entries
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.info
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "info": "Showing page _PAGE_ of _PAGES_"
+ * }
+ * } );
+ * } );
+ */
+ "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
+
+
+ /**
+ * Display information string for when the table is empty. Typically the
+ * format of this string should match `info`.
+ * @type string
+ * @default Showing 0 to 0 of 0 entries
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.infoEmpty
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "infoEmpty": "No entries to show"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoEmpty": "Showing 0 to 0 of 0 entries",
+
+
+ /**
+ * When a user filters the information in a table, this string is appended
+ * to the information (`info`) to give an idea of how strong the filtering
+ * is. The variable _MAX_ is dynamically updated.
+ * @type string
+ * @default (filtered from _MAX_ total entries)
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.infoFiltered
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "infoFiltered": " - filtering from _MAX_ records"
+ * }
+ * } );
+ * } );
+ */
+ "sInfoFiltered": "(filtered from _MAX_ total entries)",
+
+
+ /**
+ * If can be useful to append extra information to the info string at times,
+ * and this variable does exactly that. This information will be appended to
+ * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
+ * being used) at all times.
+ * @type string
+ * @default <i>Empty string</i>
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.infoPostFix
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "infoPostFix": "All records shown are derived from real information."
+ * }
+ * } );
+ * } );
+ */
+ "sInfoPostFix": "",
+
+
+ /**
+ * This decimal place operator is a little different from the other
+ * language options since DataTables doesn't output floating point
+ * numbers, so it won't ever use this for display of a number. Rather,
+ * what this parameter does is modify the sort methods of the table so
+ * that numbers which are in a format which has a character other than
+ * a period (`.`) as a decimal place will be sorted numerically.
+ *
+ * Note that numbers with different decimal places cannot be shown in
+ * the same table and still be sortable, the table must be consistent.
+ * However, multiple different tables on the page can use different
+ * decimal place characters.
+ * @type string
+ * @default
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.decimal
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "decimal": ","
+ * "thousands": "."
+ * }
+ * } );
+ * } );
+ */
+ "sDecimal": "",
+
+
+ /**
+ * DataTables has a build in number formatter (`formatNumber`) which is
+ * used to format large numbers that are used in the table information.
+ * By default a comma is used, but this can be trivially changed to any
+ * character you wish with this parameter.
+ * @type string
+ * @default ,
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.thousands
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "thousands": "'"
+ * }
+ * } );
+ * } );
+ */
+ "sThousands": ",",
+
+
+ /**
+ * Detail the action that will be taken when the drop down menu for the
+ * pagination length option is changed. The '_MENU_' variable is replaced
+ * with a default select list of 10, 25, 50 and 100, and can be replaced
+ * with a custom select box if required.
+ * @type string
+ * @default Show _MENU_ entries
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.lengthMenu
+ *
+ * @example
+ * // Language change only
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "lengthMenu": "Display _MENU_ records"
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Language and options change
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "lengthMenu": 'Display <select>'+
+ * '<option value="10">10</option>'+
+ * '<option value="20">20</option>'+
+ * '<option value="30">30</option>'+
+ * '<option value="40">40</option>'+
+ * '<option value="50">50</option>'+
+ * '<option value="-1">All</option>'+
+ * '</select> records'
+ * }
+ * } );
+ * } );
+ */
+ "sLengthMenu": "Show _MENU_ entries",
+
+
+ /**
+ * When using Ajax sourced data and during the first draw when DataTables is
+ * gathering the data, this message is shown in an empty row in the table to
+ * indicate to the end user the the data is being loaded. Note that this
+ * parameter is not used when loading data by server-side processing, just
+ * Ajax sourced data with client-side processing.
+ * @type string
+ * @default Loading...
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.loadingRecords
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "loadingRecords": "Please wait - loading..."
+ * }
+ * } );
+ * } );
+ */
+ "sLoadingRecords": "Loading...",
+
+
+ /**
+ * Text which is displayed when the table is processing a user action
+ * (usually a sort command or similar).
+ * @type string
+ * @default Processing...
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.processing
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "processing": "DataTables is currently busy"
+ * }
+ * } );
+ * } );
+ */
+ "sProcessing": "Processing...",
+
+
+ /**
+ * Details the actions that will be taken when the user types into the
+ * filtering input text box. The variable "_INPUT_", if used in the string,
+ * is replaced with the HTML text box for the filtering input allowing
+ * control over where it appears in the string. If "_INPUT_" is not given
+ * then the input box is appended to the string automatically.
+ * @type string
+ * @default Search:
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.search
+ *
+ * @example
+ * // Input text box will be appended at the end automatically
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "search": "Filter records:"
+ * }
+ * } );
+ * } );
+ *
+ * @example
+ * // Specify where the filter should appear
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "search": "Apply filter _INPUT_ to table"
+ * }
+ * } );
+ * } );
+ */
+ "sSearch": "Search:",
+
+
+ /**
+ * Assign a `placeholder` attribute to the search `input` element
+ * @type string
+ * @default
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.searchPlaceholder
+ */
+ "sSearchPlaceholder": "",
+
+
+ /**
+ * All of the language information can be stored in a file on the
+ * server-side, which DataTables will look up if this parameter is passed.
+ * It must store the URL of the language file, which is in a JSON format,
+ * and the object has the same properties as the oLanguage object in the
+ * initialiser object (i.e. the above parameters). Please refer to one of
+ * the example language files to see how this works in action.
+ * @type string
+ * @default <i>Empty string - i.e. disabled</i>
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.url
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
+ * }
+ * } );
+ * } );
+ */
+ "sUrl": "",
+
+
+ /**
+ * Text shown inside the table records when the is no information to be
+ * displayed after filtering. `emptyTable` is shown when there is simply no
+ * information in the table at all (regardless of filtering).
+ * @type string
+ * @default No matching records found
+ *
+ * @dtopt Language
+ * @name DataTable.defaults.language.zeroRecords
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "language": {
+ * "zeroRecords": "No records to display"
+ * }
+ * } );
+ * } );
+ */
+ "sZeroRecords": "No matching records found"
+ },
+
+
+ /**
+ * This parameter allows you to have define the global filtering state at
+ * initialisation time. As an object the `search` parameter must be
+ * defined, but all other parameters are optional. When `regex` is true,
+ * the search string will be treated as a regular expression, when false
+ * (default) it will be treated as a straight string. When `smart`
+ * DataTables will use it's smart filtering methods (to word match at
+ * any point in the data), when false this will not be done.
+ * @namespace
+ * @extends DataTable.models.oSearch
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.search
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "search": {"search": "Initial search"}
+ * } );
+ * } )
+ */
+ "oSearch": $.extend( {}, DataTable.models.oSearch ),
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * By default DataTables will look for the property `data` (or `aaData` for
+ * compatibility with DataTables 1.9-) when obtaining data from an Ajax
+ * source or for server-side processing - this parameter allows that
+ * property to be changed. You can use Javascript dotted object notation to
+ * get a data source for multiple levels of nesting.
+ * @type string
+ * @default data
+ *
+ * @dtopt Options
+ * @dtopt Server-side
+ * @name DataTable.defaults.ajaxDataProp
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "sAjaxDataProp": "data",
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * You can instruct DataTables to load data from an external
+ * source using this parameter (use aData if you want to pass data in you
+ * already have). Simply provide a url a JSON object can be obtained from.
+ * @type string
+ * @default null
+ *
+ * @dtopt Options
+ * @dtopt Server-side
+ * @name DataTable.defaults.ajaxSource
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "sAjaxSource": null,
+
+
+ /**
+ * This initialisation variable allows you to specify exactly where in the
+ * DOM you want DataTables to inject the various controls it adds to the page
+ * (for example you might want the pagination controls at the top of the
+ * table). DIV elements (with or without a custom class) can also be added to
+ * aid styling. The follow syntax is used:
+ * <ul>
+ * <li>The following options are allowed:
+ * <ul>
+ * <li>'l' - Length changing</li>
+ * <li>'f' - Filtering input</li>
+ * <li>'t' - The table!</li>
+ * <li>'i' - Information</li>
+ * <li>'p' - Pagination</li>
+ * <li>'r' - pRocessing</li>
+ * </ul>
+ * </li>
+ * <li>The following constants are allowed:
+ * <ul>
+ * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
+ * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
+ * </ul>
+ * </li>
+ * <li>The following syntax is expected:
+ * <ul>
+ * <li>'&lt;' and '&gt;' - div elements</li>
+ * <li>'&lt;"class" and '&gt;' - div with a class</li>
+ * <li>'&lt;"#id" and '&gt;' - div with an ID</li>
+ * </ul>
+ * </li>
+ * <li>Examples:
+ * <ul>
+ * <li>'&lt;"wrapper"flipt&gt;'</li>
+ * <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * @type string
+ * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
+ * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.dom
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
+ * } );
+ * } );
+ */
+ "sDom": "lfrtip",
+
+
+ /**
+ * Search delay option. This will throttle full table searches that use the
+ * DataTables provided search input element (it does not effect calls to
+ * `dt-api search()`, providing a delay before the search is made.
+ * @type integer
+ * @default 0
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.searchDelay
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "searchDelay": 200
+ * } );
+ * } )
+ */
+ "searchDelay": null,
+
+
+ /**
+ * DataTables features six different built-in options for the buttons to
+ * display for pagination control:
+ *
+ * * `numbers` - Page number buttons only
+ * * `simple` - 'Previous' and 'Next' buttons only
+ * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
+ * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
+ * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
+ * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
+ *
+ * Further methods can be added using {@link DataTable.ext.oPagination}.
+ * @type string
+ * @default simple_numbers
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.pagingType
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "pagingType": "full_numbers"
+ * } );
+ * } )
+ */
+ "sPaginationType": "simple_numbers",
+
+
+ /**
+ * Enable horizontal scrolling. When a table is too wide to fit into a
+ * certain layout, or you have a large number of columns in the table, you
+ * can enable x-scrolling to show the table in a viewport, which can be
+ * scrolled. This property can be `true` which will allow the table to
+ * scroll horizontally when needed, or any CSS unit, or a number (in which
+ * case it will be treated as a pixel measurement). Setting as simply `true`
+ * is recommended.
+ * @type boolean|string
+ * @default <i>blank string - i.e. disabled</i>
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.scrollX
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "scrollX": true,
+ * "scrollCollapse": true
+ * } );
+ * } );
+ */
+ "sScrollX": "",
+
+
+ /**
+ * This property can be used to force a DataTable to use more width than it
+ * might otherwise do when x-scrolling is enabled. For example if you have a
+ * table which requires to be well spaced, this parameter is useful for
+ * "over-sizing" the table, and thus forcing scrolling. This property can by
+ * any CSS unit, or a number (in which case it will be treated as a pixel
+ * measurement).
+ * @type string
+ * @default <i>blank string - i.e. disabled</i>
+ *
+ * @dtopt Options
+ * @name DataTable.defaults.scrollXInner
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "scrollX": "100%",
+ * "scrollXInner": "110%"
+ * } );
+ * } );
+ */
+ "sScrollXInner": "",
+
+
+ /**
+ * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
+ * to the given height, and enable scrolling for any data which overflows the
+ * current viewport. This can be used as an alternative to paging to display
+ * a lot of data in a small area (although paging and scrolling can both be
+ * enabled at the same time). This property can be any CSS unit, or a number
+ * (in which case it will be treated as a pixel measurement).
+ * @type string
+ * @default <i>blank string - i.e. disabled</i>
+ *
+ * @dtopt Features
+ * @name DataTable.defaults.scrollY
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "scrollY": "200px",
+ * "paginate": false
+ * } );
+ * } );
+ */
+ "sScrollY": "",
+
+
+ /**
+ * __Deprecated__ The functionality provided by this parameter has now been
+ * superseded by that provided through `ajax`, which should be used instead.
+ *
+ * Set the HTTP method that is used to make the Ajax call for server-side
+ * processing or Ajax sourced data.
+ * @type string
+ * @default GET
+ *
+ * @dtopt Options
+ * @dtopt Server-side
+ * @name DataTable.defaults.serverMethod
+ *
+ * @deprecated 1.10. Please use `ajax` for this functionality now.
+ */
+ "sServerMethod": "GET",
+
+
+ /**
+ * DataTables makes use of renderers when displaying HTML elements for
+ * a table. These renderers can be added or modified by plug-ins to
+ * generate suitable mark-up for a site. For example the Bootstrap
+ * integration plug-in for DataTables uses a paging button renderer to
+ * display pagination buttons in the mark-up required by Bootstrap.
+ *
+ * For further information about the renderers available see
+ * DataTable.ext.renderer
+ * @type string|object
+ * @default null
+ *
+ * @name DataTable.defaults.renderer
+ *
+ */
+ "renderer": null,
+
+
+ /**
+ * Set the data property name that DataTables should use to get a row's id
+ * to set as the `id` property in the node.
+ * @type string
+ * @default DT_RowId
+ *
+ * @name DataTable.defaults.rowId
+ */
+ "rowId": "DT_RowId"
+ };
+
+ _fnHungarianMap( DataTable.defaults );
+
+
+
+ /*
+ * Developer note - See note in model.defaults.js about the use of Hungarian
+ * notation and camel case.
+ */
+
+ /**
+ * Column options that can be given to DataTables at initialisation time.
+ * @namespace
+ */
+ DataTable.defaults.column = {
+ /**
+ * Define which column(s) an order will occur on for this column. This
+ * allows a column's ordering to take multiple columns into account when
+ * doing a sort or use the data from a different column. For example first
+ * name / last name columns make sense to do a multi-column sort over the
+ * two columns.
+ * @type array|int
+ * @default null <i>Takes the value of the column index automatically</i>
+ *
+ * @name DataTable.defaults.column.orderData
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "orderData": [ 0, 1 ], "targets": [ 0 ] },
+ * { "orderData": [ 1, 0 ], "targets": [ 1 ] },
+ * { "orderData": 2, "targets": [ 2 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "orderData": [ 0, 1 ] },
+ * { "orderData": [ 1, 0 ] },
+ * { "orderData": 2 },
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "aDataSort": null,
+ "iDataSort": -1,
+
+
+ /**
+ * You can control the default ordering direction, and even alter the
+ * behaviour of the sort handler (i.e. only allow ascending ordering etc)
+ * using this parameter.
+ * @type array
+ * @default [ 'asc', 'desc' ]
+ *
+ * @name DataTable.defaults.column.orderSequence
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "orderSequence": [ "asc" ], "targets": [ 1 ] },
+ * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
+ * { "orderSequence": [ "desc" ], "targets": [ 3 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * null,
+ * { "orderSequence": [ "asc" ] },
+ * { "orderSequence": [ "desc", "asc", "asc" ] },
+ * { "orderSequence": [ "desc" ] },
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "asSorting": [ 'asc', 'desc' ],
+
+
+ /**
+ * Enable or disable filtering on the data in this column.
+ * @type boolean
+ * @default true
+ *
+ * @name DataTable.defaults.column.searchable
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "searchable": false, "targets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "searchable": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bSearchable": true,
+
+
+ /**
+ * Enable or disable ordering on this column.
+ * @type boolean
+ * @default true
+ *
+ * @name DataTable.defaults.column.orderable
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "orderable": false, "targets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "orderable": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bSortable": true,
+
+
+ /**
+ * Enable or disable the display of this column.
+ * @type boolean
+ * @default true
+ *
+ * @name DataTable.defaults.column.visible
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "visible": false, "targets": [ 0 ] }
+ * ] } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "visible": false },
+ * null,
+ * null,
+ * null,
+ * null
+ * ] } );
+ * } );
+ */
+ "bVisible": true,
+
+
+ /**
+ * Developer definable function that is called whenever a cell is created (Ajax source,
+ * etc) or processed for input (DOM source). This can be used as a compliment to mRender
+ * allowing you to modify the DOM element (add background colour for example) when the
+ * element is available.
+ * @type function
+ * @param {element} td The TD node that has been created
+ * @param {*} cellData The Data for the cell
+ * @param {array|object} rowData The data for the whole row
+ * @param {int} row The row index for the aoData data store
+ * @param {int} col The column index for aoColumns
+ *
+ * @name DataTable.defaults.column.createdCell
+ * @dtopt Columns
+ *
+ * @example
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [3],
+ * "createdCell": function (td, cellData, rowData, row, col) {
+ * if ( cellData == "1.7" ) {
+ * $(td).css('color', 'blue')
+ * }
+ * }
+ * } ]
+ * });
+ * } );
+ */
+ "fnCreatedCell": null,
+
+
+ /**
+ * This parameter has been replaced by `data` in DataTables to ensure naming
+ * consistency. `dataProp` can still be used, as there is backwards
+ * compatibility in DataTables for this option, but it is strongly
+ * recommended that you use `data` in preference to `dataProp`.
+ * @name DataTable.defaults.column.dataProp
+ */
+
+
+ /**
+ * This property can be used to read data from any data source property,
+ * including deeply nested objects / properties. `data` can be given in a
+ * number of different ways which effect its behaviour:
+ *
+ * * `integer` - treated as an array index for the data source. This is the
+ * default that DataTables uses (incrementally increased for each column).
+ * * `string` - read an object property from the data source. There are
+ * three 'special' options that can be used in the string to alter how
+ * DataTables reads the data from the source object:
+ * * `.` - Dotted Javascript notation. Just as you use a `.` in
+ * Javascript to read from nested objects, so to can the options
+ * specified in `data`. For example: `browser.version` or
+ * `browser.name`. If your object parameter name contains a period, use
+ * `\\` to escape it - i.e. `first\\.name`.
+ * * `[]` - Array notation. DataTables can automatically combine data
+ * from and array source, joining the data with the characters provided
+ * between the two brackets. For example: `name[, ]` would provide a
+ * comma-space separated list from the source array. If no characters
+ * are provided between the brackets, the original array source is
+ * returned.
+ * * `()` - Function notation. Adding `()` to the end of a parameter will
+ * execute a function of the name given. For example: `browser()` for a
+ * simple function on the data source, `browser.version()` for a
+ * function in a nested property or even `browser().version` to get an
+ * object property if the function called returns an object. Note that
+ * function notation is recommended for use in `render` rather than
+ * `data` as it is much simpler to use as a renderer.
+ * * `null` - use the original data source for the row rather than plucking
+ * data directly from it. This action has effects on two other
+ * initialisation options:
+ * * `defaultContent` - When null is given as the `data` option and
+ * `defaultContent` is specified for the column, the value defined by
+ * `defaultContent` will be used for the cell.
+ * * `render` - When null is used for the `data` option and the `render`
+ * option is specified for the column, the whole data source for the
+ * row is used for the renderer.
+ * * `function` - the function given will be executed whenever DataTables
+ * needs to set or get the data for a cell in the column. The function
+ * takes three parameters:
+ * * Parameters:
+ * * `{array|object}` The data source for the row
+ * * `{string}` The type call data requested - this will be 'set' when
+ * setting data or 'filter', 'display', 'type', 'sort' or undefined
+ * when gathering data. Note that when `undefined` is given for the
+ * type DataTables expects to get the raw data for the object back<
+ * * `{*}` Data to set when the second parameter is 'set'.
+ * * Return:
+ * * The return value from the function is not required when 'set' is
+ * the type of call, but otherwise the return is what will be used
+ * for the data requested.
+ *
+ * Note that `data` is a getter and setter option. If you just require
+ * formatting of data for output, you will likely want to use `render` which
+ * is simply a getter and thus simpler to use.
+ *
+ * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
+ * name change reflects the flexibility of this property and is consistent
+ * with the naming of mRender. If 'mDataProp' is given, then it will still
+ * be used by DataTables, as it automatically maps the old name to the new
+ * if required.
+ *
+ * @type string|int|function|null
+ * @default null <i>Use automatically calculated column index</i>
+ *
+ * @name DataTable.defaults.column.data
+ * @dtopt Columns
+ *
+ * @example
+ * // Read table data from objects
+ * // JSON structure for each row:
+ * // {
+ * // "engine": {value},
+ * // "browser": {value},
+ * // "platform": {value},
+ * // "version": {value},
+ * // "grade": {value}
+ * // }
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "ajaxSource": "sources/objects.txt",
+ * "columns": [
+ * { "data": "engine" },
+ * { "data": "browser" },
+ * { "data": "platform" },
+ * { "data": "version" },
+ * { "data": "grade" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Read information from deeply nested objects
+ * // JSON structure for each row:
+ * // {
+ * // "engine": {value},
+ * // "browser": {value},
+ * // "platform": {
+ * // "inner": {value}
+ * // },
+ * // "details": [
+ * // {value}, {value}
+ * // ]
+ * // }
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "ajaxSource": "sources/deep.txt",
+ * "columns": [
+ * { "data": "engine" },
+ * { "data": "browser" },
+ * { "data": "platform.inner" },
+ * { "data": "platform.details.0" },
+ * { "data": "platform.details.1" }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `data` as a function to provide different information for
+ * // sorting, filtering and display. In this case, currency (price)
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": function ( source, type, val ) {
+ * if (type === 'set') {
+ * source.price = val;
+ * // Store the computed dislay and filter values for efficiency
+ * source.price_display = val=="" ? "" : "$"+numberFormat(val);
+ * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val;
+ * return;
+ * }
+ * else if (type === 'display') {
+ * return source.price_display;
+ * }
+ * else if (type === 'filter') {
+ * return source.price_filter;
+ * }
+ * // 'sort', 'type' and undefined all just use the integer
+ * return source.price;
+ * }
+ * } ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using default content
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": null,
+ * "defaultContent": "Click to edit"
+ * } ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using array notation - outputting a list from an array
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": "name[, ]"
+ * } ]
+ * } );
+ * } );
+ *
+ */
+ "mData": null,
+
+
+ /**
+ * This property is the rendering partner to `data` and it is suggested that
+ * when you want to manipulate data for display (including filtering,
+ * sorting etc) without altering the underlying data for the table, use this
+ * property. `render` can be considered to be the the read only companion to
+ * `data` which is read / write (then as such more complex). Like `data`
+ * this option can be given in a number of different ways to effect its
+ * behaviour:
+ *
+ * * `integer` - treated as an array index for the data source. This is the
+ * default that DataTables uses (incrementally increased for each column).
+ * * `string` - read an object property from the data source. There are
+ * three 'special' options that can be used in the string to alter how
+ * DataTables reads the data from the source object:
+ * * `.` - Dotted Javascript notation. Just as you use a `.` in
+ * Javascript to read from nested objects, so to can the options
+ * specified in `data`. For example: `browser.version` or
+ * `browser.name`. If your object parameter name contains a period, use
+ * `\\` to escape it - i.e. `first\\.name`.
+ * * `[]` - Array notation. DataTables can automatically combine data
+ * from and array source, joining the data with the characters provided
+ * between the two brackets. For example: `name[, ]` would provide a
+ * comma-space separated list from the source array. If no characters
+ * are provided between the brackets, the original array source is
+ * returned.
+ * * `()` - Function notation. Adding `()` to the end of a parameter will
+ * execute a function of the name given. For example: `browser()` for a
+ * simple function on the data source, `browser.version()` for a
+ * function in a nested property or even `browser().version` to get an
+ * object property if the function called returns an object.
+ * * `object` - use different data for the different data types requested by
+ * DataTables ('filter', 'display', 'type' or 'sort'). The property names
+ * of the object is the data type the property refers to and the value can
+ * defined using an integer, string or function using the same rules as
+ * `render` normally does. Note that an `_` option _must_ be specified.
+ * This is the default value to use if you haven't specified a value for
+ * the data type requested by DataTables.
+ * * `function` - the function given will be executed whenever DataTables
+ * needs to set or get the data for a cell in the column. The function
+ * takes three parameters:
+ * * Parameters:
+ * * {array|object} The data source for the row (based on `data`)
+ * * {string} The type call data requested - this will be 'filter',
+ * 'display', 'type' or 'sort'.
+ * * {array|object} The full data source for the row (not based on
+ * `data`)
+ * * Return:
+ * * The return value from the function is what will be used for the
+ * data requested.
+ *
+ * @type string|int|function|object|null
+ * @default null Use the data source value.
+ *
+ * @name DataTable.defaults.column.render
+ * @dtopt Columns
+ *
+ * @example
+ * // Create a comma separated list from an array of objects
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "ajaxSource": "sources/deep.txt",
+ * "columns": [
+ * { "data": "engine" },
+ * { "data": "browser" },
+ * {
+ * "data": "platform",
+ * "render": "[, ].name"
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Execute a function to obtain data
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": null, // Use the full data source object for the renderer's source
+ * "render": "browserName()"
+ * } ]
+ * } );
+ * } );
+ *
+ * @example
+ * // As an object, extracting different data for the different types
+ * // This would be used with a data source such as:
+ * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
+ * // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
+ * // (which has both forms) is used for filtering for if a user inputs either format, while
+ * // the formatted phone number is the one that is shown in the table.
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": null, // Use the full data source object for the renderer's source
+ * "render": {
+ * "_": "phone",
+ * "filter": "phone_filter",
+ * "display": "phone_display"
+ * }
+ * } ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Use as a function to create a link from the data source
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "data": "download_link",
+ * "render": function ( data, type, full ) {
+ * return '<a href="'+data+'">Download</a>';
+ * }
+ * } ]
+ * } );
+ * } );
+ */
+ "mRender": null,
+
+
+ /**
+ * Change the cell type created for the column - either TD cells or TH cells. This
+ * can be useful as TH cells have semantic meaning in the table body, allowing them
+ * to act as a header for a row (you may wish to add scope='row' to the TH elements).
+ * @type string
+ * @default td
+ *
+ * @name DataTable.defaults.column.cellType
+ * @dtopt Columns
+ *
+ * @example
+ * // Make the first column use TH cells
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [ {
+ * "targets": [ 0 ],
+ * "cellType": "th"
+ * } ]
+ * } );
+ * } );
+ */
+ "sCellType": "td",
+
+
+ /**
+ * Class to give to each cell in this column.
+ * @type string
+ * @default <i>Empty string</i>
+ *
+ * @name DataTable.defaults.column.class
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "class": "my_class", "targets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "class": "my_class" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sClass": "",
+
+ /**
+ * When DataTables calculates the column widths to assign to each column,
+ * it finds the longest string in each column and then constructs a
+ * temporary table and reads the widths from that. The problem with this
+ * is that "mmm" is much wider then "iiii", but the latter is a longer
+ * string - thus the calculation can go wrong (doing it properly and putting
+ * it into an DOM object and measuring that is horribly(!) slow). Thus as
+ * a "work around" we provide this option. It will append its value to the
+ * text that is found to be the longest string for the column - i.e. padding.
+ * Generally you shouldn't need this!
+ * @type string
+ * @default <i>Empty string<i>
+ *
+ * @name DataTable.defaults.column.contentPadding
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * null,
+ * null,
+ * null,
+ * {
+ * "contentPadding": "mmm"
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "sContentPadding": "",
+
+
+ /**
+ * Allows a default value to be given for a column's data, and will be used
+ * whenever a null data source is encountered (this can be because `data`
+ * is set to null, or because the data source itself is null).
+ * @type string
+ * @default null
+ *
+ * @name DataTable.defaults.column.defaultContent
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * {
+ * "data": null,
+ * "defaultContent": "Edit",
+ * "targets": [ -1 ]
+ * }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * null,
+ * null,
+ * null,
+ * {
+ * "data": null,
+ * "defaultContent": "Edit"
+ * }
+ * ]
+ * } );
+ * } );
+ */
+ "sDefaultContent": null,
+
+
+ /**
+ * This parameter is only used in DataTables' server-side processing. It can
+ * be exceptionally useful to know what columns are being displayed on the
+ * client side, and to map these to database fields. When defined, the names
+ * also allow DataTables to reorder information from the server if it comes
+ * back in an unexpected order (i.e. if you switch your columns around on the
+ * client-side, your server-side code does not also need updating).
+ * @type string
+ * @default <i>Empty string</i>
+ *
+ * @name DataTable.defaults.column.name
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "name": "engine", "targets": [ 0 ] },
+ * { "name": "browser", "targets": [ 1 ] },
+ * { "name": "platform", "targets": [ 2 ] },
+ * { "name": "version", "targets": [ 3 ] },
+ * { "name": "grade", "targets": [ 4 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "name": "engine" },
+ * { "name": "browser" },
+ * { "name": "platform" },
+ * { "name": "version" },
+ * { "name": "grade" }
+ * ]
+ * } );
+ * } );
+ */
+ "sName": "",
+
+
+ /**
+ * Defines a data source type for the ordering which can be used to read
+ * real-time information from the table (updating the internally cached
+ * version) prior to ordering. This allows ordering to occur on user
+ * editable elements such as form inputs.
+ * @type string
+ * @default std
+ *
+ * @name DataTable.defaults.column.orderDataType
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
+ * { "type": "numeric", "targets": [ 3 ] },
+ * { "orderDataType": "dom-select", "targets": [ 4 ] },
+ * { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * null,
+ * null,
+ * { "orderDataType": "dom-text" },
+ * { "orderDataType": "dom-text", "type": "numeric" },
+ * { "orderDataType": "dom-select" },
+ * { "orderDataType": "dom-checkbox" }
+ * ]
+ * } );
+ * } );
+ */
+ "sSortDataType": "std",
+
+
+ /**
+ * The title of this column.
+ * @type string
+ * @default null <i>Derived from the 'TH' value for this column in the
+ * original HTML table.</i>
+ *
+ * @name DataTable.defaults.column.title
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "title": "My column title", "targets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "title": "My column title" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sTitle": null,
+
+
+ /**
+ * The type allows you to specify how the data for this column will be
+ * ordered. Four types (string, numeric, date and html (which will strip
+ * HTML tags before ordering)) are currently available. Note that only date
+ * formats understood by Javascript's Date() object will be accepted as type
+ * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
+ * 'numeric', 'date' or 'html' (by default). Further types can be adding
+ * through plug-ins.
+ * @type string
+ * @default null <i>Auto-detected from raw data</i>
+ *
+ * @name DataTable.defaults.column.type
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "type": "html", "targets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "type": "html" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sType": null,
+
+
+ /**
+ * Defining the width of the column, this parameter may take any CSS value
+ * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
+ * been given a specific width through this interface ensuring that the table
+ * remains readable.
+ * @type string
+ * @default null <i>Automatic</i>
+ *
+ * @name DataTable.defaults.column.width
+ * @dtopt Columns
+ *
+ * @example
+ * // Using `columnDefs`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columnDefs": [
+ * { "width": "20%", "targets": [ 0 ] }
+ * ]
+ * } );
+ * } );
+ *
+ * @example
+ * // Using `columns`
+ * $(document).ready( function() {
+ * $('#example').dataTable( {
+ * "columns": [
+ * { "width": "20%" },
+ * null,
+ * null,
+ * null,
+ * null
+ * ]
+ * } );
+ * } );
+ */
+ "sWidth": null
+ };
+
+ _fnHungarianMap( DataTable.defaults.column );
+
+
+
+ /**
+ * DataTables settings object - this holds all the information needed for a
+ * given table, including configuration, data and current application of the
+ * table options. DataTables does not have a single instance for each DataTable
+ * with the settings attached to that instance, but rather instances of the
+ * DataTable "class" are created on-the-fly as needed (typically by a
+ * $().dataTable() call) and the settings object is then applied to that
+ * instance.
+ *
+ * Note that this object is related to {@link DataTable.defaults} but this
+ * one is the internal data store for DataTables's cache of columns. It should
+ * NOT be manipulated outside of DataTables. Any configuration should be done
+ * through the initialisation options.
+ * @namespace
+ * @todo Really should attach the settings object to individual instances so we
+ * don't need to create new instances on each $().dataTable() call (if the
+ * table already exists). It would also save passing oSettings around and
+ * into every single function. However, this is a very significant
+ * architecture change for DataTables and will almost certainly break
+ * backwards compatibility with older installations. This is something that
+ * will be done in 2.0.
+ */
+ DataTable.models.oSettings = {
+ /**
+ * Primary features of DataTables and their enablement state.
+ * @namespace
+ */
+ "oFeatures": {
+
+ /**
+ * Flag to say if DataTables should automatically try to calculate the
+ * optimum table and columns widths (true) or not (false).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bAutoWidth": null,
+
+ /**
+ * Delay the creation of TR and TD elements until they are actually
+ * needed by a driven page draw. This can give a significant speed
+ * increase for Ajax source and Javascript source data, but makes no
+ * difference at all fro DOM and server-side processing tables.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bDeferRender": null,
+
+ /**
+ * Enable filtering on the table or not. Note that if this is disabled
+ * then there is no filtering at all on the table, including fnFilter.
+ * To just remove the filtering input use sDom and remove the 'f' option.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bFilter": null,
+
+ /**
+ * Table information element (the 'Showing x of y records' div) enable
+ * flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bInfo": null,
+
+ /**
+ * Present a user control allowing the end user to change the page size
+ * when pagination is enabled.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bLengthChange": null,
+
+ /**
+ * Pagination enabled or not. Note that if this is disabled then length
+ * changing must also be disabled.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bPaginate": null,
+
+ /**
+ * Processing indicator enable flag whenever DataTables is enacting a
+ * user request - typically an Ajax request for server-side processing.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bProcessing": null,
+
+ /**
+ * Server-side processing enabled flag - when enabled DataTables will
+ * get all data from the server for every draw - there is no filtering,
+ * sorting or paging done on the client-side.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bServerSide": null,
+
+ /**
+ * Sorting enablement flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSort": null,
+
+ /**
+ * Multi-column sorting
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortMulti": null,
+
+ /**
+ * Apply a class to the columns which are being sorted to provide a
+ * visual highlight or not. This can slow things down when enabled since
+ * there is a lot of DOM interaction.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortClasses": null,
+
+ /**
+ * State saving enablement flag.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bStateSave": null
+ },
+
+
+ /**
+ * Scrolling settings for a table.
+ * @namespace
+ */
+ "oScroll": {
+ /**
+ * When the table is shorter in height than sScrollY, collapse the
+ * table container down to the height of the table (when true).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bCollapse": null,
+
+ /**
+ * Width of the scrollbar for the web-browser's platform. Calculated
+ * during table initialisation.
+ * @type int
+ * @default 0
+ */
+ "iBarWidth": 0,
+
+ /**
+ * Viewport width for horizontal scrolling. Horizontal scrolling is
+ * disabled if an empty string.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sX": null,
+
+ /**
+ * Width to expand the table to when using x-scrolling. Typically you
+ * should not need to use this.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @deprecated
+ */
+ "sXInner": null,
+
+ /**
+ * Viewport height for vertical scrolling. Vertical scrolling is disabled
+ * if an empty string.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sY": null
+ },
+
+ /**
+ * Language information for the table.
+ * @namespace
+ * @extends DataTable.defaults.oLanguage
+ */
+ "oLanguage": {
+ /**
+ * Information callback function. See
+ * {@link DataTable.defaults.fnInfoCallback}
+ * @type function
+ * @default null
+ */
+ "fnInfoCallback": null
+ },
+
+ /**
+ * Browser support parameters
+ * @namespace
+ */
+ "oBrowser": {
+ /**
+ * Indicate if the browser incorrectly calculates width:100% inside a
+ * scrolling element (IE6/7)
+ * @type boolean
+ * @default false
+ */
+ "bScrollOversize": false,
+
+ /**
+ * Determine if the vertical scrollbar is on the right or left of the
+ * scrolling container - needed for rtl language layout, although not
+ * all browsers move the scrollbar (Safari).
+ * @type boolean
+ * @default false
+ */
+ "bScrollbarLeft": false,
+
+ /**
+ * Flag for if `getBoundingClientRect` is fully supported or not
+ * @type boolean
+ * @default false
+ */
+ "bBounding": false,
+
+ /**
+ * Browser scrollbar width
+ * @type integer
+ * @default 0
+ */
+ "barWidth": 0
+ },
+
+
+ "ajax": null,
+
+
+ /**
+ * Array referencing the nodes which are used for the features. The
+ * parameters of this object match what is allowed by sDom - i.e.
+ * <ul>
+ * <li>'l' - Length changing</li>
+ * <li>'f' - Filtering input</li>
+ * <li>'t' - The table!</li>
+ * <li>'i' - Information</li>
+ * <li>'p' - Pagination</li>
+ * <li>'r' - pRocessing</li>
+ * </ul>
+ * @type array
+ * @default []
+ */
+ "aanFeatures": [],
+
+ /**
+ * Store data information - see {@link DataTable.models.oRow} for detailed
+ * information.
+ * @type array
+ * @default []
+ */
+ "aoData": [],
+
+ /**
+ * Array of indexes which are in the current display (after filtering etc)
+ * @type array
+ * @default []
+ */
+ "aiDisplay": [],
+
+ /**
+ * Array of indexes for display - no filtering
+ * @type array
+ * @default []
+ */
+ "aiDisplayMaster": [],
+
+ /**
+ * Map of row ids to data indexes
+ * @type object
+ * @default {}
+ */
+ "aIds": {},
+
+ /**
+ * Store information about each column that is in use
+ * @type array
+ * @default []
+ */
+ "aoColumns": [],
+
+ /**
+ * Store information about the table's header
+ * @type array
+ * @default []
+ */
+ "aoHeader": [],
+
+ /**
+ * Store information about the table's footer
+ * @type array
+ * @default []
+ */
+ "aoFooter": [],
+
+ /**
+ * Store the applied global search information in case we want to force a
+ * research or compare the old search to a new one.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @namespace
+ * @extends DataTable.models.oSearch
+ */
+ "oPreviousSearch": {},
+
+ /**
+ * Store the applied search for each column - see
+ * {@link DataTable.models.oSearch} for the format that is used for the
+ * filtering information for each column.
+ * @type array
+ * @default []
+ */
+ "aoPreSearchCols": [],
+
+ /**
+ * Sorting that is applied to the table. Note that the inner arrays are
+ * used in the following manner:
+ * <ul>
+ * <li>Index 0 - column number</li>
+ * <li>Index 1 - current sorting direction</li>
+ * </ul>
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @todo These inner arrays should really be objects
+ */
+ "aaSorting": null,
+
+ /**
+ * Sorting that is always applied to the table (i.e. prefixed in front of
+ * aaSorting).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "aaSortingFixed": [],
+
+ /**
+ * Classes to use for the striping of a table.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "asStripeClasses": null,
+
+ /**
+ * If restoring a table - we should restore its striping classes as well
+ * @type array
+ * @default []
+ */
+ "asDestroyStripes": [],
+
+ /**
+ * If restoring a table - we should restore its width
+ * @type int
+ * @default 0
+ */
+ "sDestroyWidth": 0,
+
+ /**
+ * Callback functions array for every time a row is inserted (i.e. on a draw).
+ * @type array
+ * @default []
+ */
+ "aoRowCallback": [],
+
+ /**
+ * Callback functions for the header on each draw.
+ * @type array
+ * @default []
+ */
+ "aoHeaderCallback": [],
+
+ /**
+ * Callback function for the footer on each draw.
+ * @type array
+ * @default []
+ */
+ "aoFooterCallback": [],
+
+ /**
+ * Array of callback functions for draw callback functions
+ * @type array
+ * @default []
+ */
+ "aoDrawCallback": [],
+
+ /**
+ * Array of callback functions for row created function
+ * @type array
+ * @default []
+ */
+ "aoRowCreatedCallback": [],
+
+ /**
+ * Callback functions for just before the table is redrawn. A return of
+ * false will be used to cancel the draw.
+ * @type array
+ * @default []
+ */
+ "aoPreDrawCallback": [],
+
+ /**
+ * Callback functions for when the table has been initialised.
+ * @type array
+ * @default []
+ */
+ "aoInitComplete": [],
+
+
+ /**
+ * Callbacks for modifying the settings to be stored for state saving, prior to
+ * saving state.
+ * @type array
+ * @default []
+ */
+ "aoStateSaveParams": [],
+
+ /**
+ * Callbacks for modifying the settings that have been stored for state saving
+ * prior to using the stored values to restore the state.
+ * @type array
+ * @default []
+ */
+ "aoStateLoadParams": [],
+
+ /**
+ * Callbacks for operating on the settings object once the saved state has been
+ * loaded
+ * @type array
+ * @default []
+ */
+ "aoStateLoaded": [],
+
+ /**
+ * Cache the table ID for quick access
+ * @type string
+ * @default <i>Empty string</i>
+ */
+ "sTableId": "",
+
+ /**
+ * The TABLE node for the main table
+ * @type node
+ * @default null
+ */
+ "nTable": null,
+
+ /**
+ * Permanent ref to the thead element
+ * @type node
+ * @default null
+ */
+ "nTHead": null,
+
+ /**
+ * Permanent ref to the tfoot element - if it exists
+ * @type node
+ * @default null
+ */
+ "nTFoot": null,
+
+ /**
+ * Permanent ref to the tbody element
+ * @type node
+ * @default null
+ */
+ "nTBody": null,
+
+ /**
+ * Cache the wrapper node (contains all DataTables controlled elements)
+ * @type node
+ * @default null
+ */
+ "nTableWrapper": null,
+
+ /**
+ * Indicate if when using server-side processing the loading of data
+ * should be deferred until the second draw.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ * @default false
+ */
+ "bDeferLoading": false,
+
+ /**
+ * Indicate if all required information has been read in
+ * @type boolean
+ * @default false
+ */
+ "bInitialised": false,
+
+ /**
+ * Information about open rows. Each object in the array has the parameters
+ * 'nTr' and 'nParent'
+ * @type array
+ * @default []
+ */
+ "aoOpenRows": [],
+
+ /**
+ * Dictate the positioning of DataTables' control elements - see
+ * {@link DataTable.model.oInit.sDom}.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default null
+ */
+ "sDom": null,
+
+ /**
+ * Search delay (in mS)
+ * @type integer
+ * @default null
+ */
+ "searchDelay": null,
+
+ /**
+ * Which type of pagination should be used.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default two_button
+ */
+ "sPaginationType": "two_button",
+
+ /**
+ * The state duration (for `stateSave`) in seconds.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type int
+ * @default 0
+ */
+ "iStateDuration": 0,
+
+ /**
+ * Array of callback functions for state saving. Each array element is an
+ * object with the following parameters:
+ * <ul>
+ * <li>function:fn - function to call. Takes two parameters, oSettings
+ * and the JSON string to save that has been thus far created. Returns
+ * a JSON string to be inserted into a json object
+ * (i.e. '"param": [ 0, 1, 2]')</li>
+ * <li>string:sName - name of callback</li>
+ * </ul>
+ * @type array
+ * @default []
+ */
+ "aoStateSave": [],
+
+ /**
+ * Array of callback functions for state loading. Each array element is an
+ * object with the following parameters:
+ * <ul>
+ * <li>function:fn - function to call. Takes two parameters, oSettings
+ * and the object stored. May return false to cancel state loading</li>
+ * <li>string:sName - name of callback</li>
+ * </ul>
+ * @type array
+ * @default []
+ */
+ "aoStateLoad": [],
+
+ /**
+ * State that was saved. Useful for back reference
+ * @type object
+ * @default null
+ */
+ "oSavedState": null,
+
+ /**
+ * State that was loaded. Useful for back reference
+ * @type object
+ * @default null
+ */
+ "oLoadedState": null,
+
+ /**
+ * Source url for AJAX data for the table.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ * @default null
+ */
+ "sAjaxSource": null,
+
+ /**
+ * Property from a given object from which to read the table data from. This
+ * can be an empty string (when not server-side processing), in which case
+ * it is assumed an an array is given directly.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sAjaxDataProp": null,
+
+ /**
+ * Note if draw should be blocked while getting data
+ * @type boolean
+ * @default true
+ */
+ "bAjaxDataGet": true,
+
+ /**
+ * The last jQuery XHR object that was used for server-side data gathering.
+ * This can be used for working with the XHR information in one of the
+ * callbacks
+ * @type object
+ * @default null
+ */
+ "jqXHR": null,
+
+ /**
+ * JSON returned from the server in the last Ajax request
+ * @type object
+ * @default undefined
+ */
+ "json": undefined,
+
+ /**
+ * Data submitted as part of the last Ajax request
+ * @type object
+ * @default undefined
+ */
+ "oAjaxData": undefined,
+
+ /**
+ * Function to get the server-side data.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type function
+ */
+ "fnServerData": null,
+
+ /**
+ * Functions which are called prior to sending an Ajax request so extra
+ * parameters can easily be sent to the server
+ * @type array
+ * @default []
+ */
+ "aoServerParams": [],
+
+ /**
+ * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
+ * required).
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type string
+ */
+ "sServerMethod": null,
+
+ /**
+ * Format numbers for display.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type function
+ */
+ "fnFormatNumber": null,
+
+ /**
+ * List of options that can be used for the user selectable length menu.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type array
+ * @default []
+ */
+ "aLengthMenu": null,
+
+ /**
+ * Counter for the draws that the table does. Also used as a tracker for
+ * server-side processing
+ * @type int
+ * @default 0
+ */
+ "iDraw": 0,
+
+ /**
+ * Indicate if a redraw is being done - useful for Ajax
+ * @type boolean
+ * @default false
+ */
+ "bDrawing": false,
+
+ /**
+ * Draw index (iDraw) of the last error when parsing the returned data
+ * @type int
+ * @default -1
+ */
+ "iDrawError": -1,
+
+ /**
+ * Paging display length
+ * @type int
+ * @default 10
+ */
+ "_iDisplayLength": 10,
+
+ /**
+ * Paging start point - aiDisplay index
+ * @type int
+ * @default 0
+ */
+ "_iDisplayStart": 0,
+
+ /**
+ * Server-side processing - number of records in the result set
+ * (i.e. before filtering), Use fnRecordsTotal rather than
+ * this property to get the value of the number of records, regardless of
+ * the server-side processing setting.
+ * @type int
+ * @default 0
+ * @private
+ */
+ "_iRecordsTotal": 0,
+
+ /**
+ * Server-side processing - number of records in the current display set
+ * (i.e. after filtering). Use fnRecordsDisplay rather than
+ * this property to get the value of the number of records, regardless of
+ * the server-side processing setting.
+ * @type boolean
+ * @default 0
+ * @private
+ */
+ "_iRecordsDisplay": 0,
+
+ /**
+ * The classes to use for the table
+ * @type object
+ * @default {}
+ */
+ "oClasses": {},
+
+ /**
+ * Flag attached to the settings object so you can check in the draw
+ * callback if filtering has been done in the draw. Deprecated in favour of
+ * events.
+ * @type boolean
+ * @default false
+ * @deprecated
+ */
+ "bFiltered": false,
+
+ /**
+ * Flag attached to the settings object so you can check in the draw
+ * callback if sorting has been done in the draw. Deprecated in favour of
+ * events.
+ * @type boolean
+ * @default false
+ * @deprecated
+ */
+ "bSorted": false,
+
+ /**
+ * Indicate that if multiple rows are in the header and there is more than
+ * one unique cell per column, if the top one (true) or bottom one (false)
+ * should be used for sorting / title by DataTables.
+ * Note that this parameter will be set by the initialisation routine. To
+ * set a default use {@link DataTable.defaults}.
+ * @type boolean
+ */
+ "bSortCellsTop": null,
+
+ /**
+ * Initialisation object that is used for the table
+ * @type object
+ * @default null
+ */
+ "oInit": null,
+
+ /**
+ * Destroy callback functions - for plug-ins to attach themselves to the
+ * destroy so they can clean up markup and events.
+ * @type array
+ * @default []
+ */
+ "aoDestroyCallback": [],
+
+
+ /**
+ * Get the number of records in the current record set, before filtering
+ * @type function
+ */
+ "fnRecordsTotal": function ()
+ {
+ return _fnDataSource( this ) == 'ssp' ?
+ this._iRecordsTotal * 1 :
+ this.aiDisplayMaster.length;
+ },
+
+ /**
+ * Get the number of records in the current record set, after filtering
+ * @type function
+ */
+ "fnRecordsDisplay": function ()
+ {
+ return _fnDataSource( this ) == 'ssp' ?
+ this._iRecordsDisplay * 1 :
+ this.aiDisplay.length;
+ },
+
+ /**
+ * Get the display end point - aiDisplay index
+ * @type function
+ */
+ "fnDisplayEnd": function ()
+ {
+ var
+ len = this._iDisplayLength,
+ start = this._iDisplayStart,
+ calc = start + len,
+ records = this.aiDisplay.length,
+ features = this.oFeatures,
+ paginate = features.bPaginate;
+
+ if ( features.bServerSide ) {
+ return paginate === false || len === -1 ?
+ start + records :
+ Math.min( start+len, this._iRecordsDisplay );
+ }
+ else {
+ return ! paginate || calc>records || len===-1 ?
+ records :
+ calc;
+ }
+ },
+
+ /**
+ * The DataTables object for this table
+ * @type object
+ * @default null
+ */
+ "oInstance": null,
+
+ /**
+ * Unique identifier for each instance of the DataTables object. If there
+ * is an ID on the table node, then it takes that value, otherwise an
+ * incrementing internal counter is used.
+ * @type string
+ * @default null
+ */
+ "sInstance": null,
+
+ /**
+ * tabindex attribute value that is added to DataTables control elements, allowing
+ * keyboard navigation of the table and its controls.
+ */
+ "iTabIndex": 0,
+
+ /**
+ * DIV container for the footer scrolling table if scrolling
+ */
+ "nScrollHead": null,
+
+ /**
+ * DIV container for the footer scrolling table if scrolling
+ */
+ "nScrollFoot": null,
+
+ /**
+ * Last applied sort
+ * @type array
+ * @default []
+ */
+ "aLastSort": [],
+
+ /**
+ * Stored plug-in instances
+ * @type object
+ * @default {}
+ */
+ "oPlugins": {},
+
+ /**
+ * Function used to get a row's id from the row's data
+ * @type function
+ * @default null
+ */
+ "rowIdFn": null,
+
+ /**
+ * Data location where to store a row's id
+ * @type string
+ * @default null
+ */
+ "rowId": null
+ };
+
+ /**
+ * Extension object for DataTables that is used to provide all extension
+ * options.
+ *
+ * Note that the `DataTable.ext` object is available through
+ * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
+ * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
+ * @namespace
+ * @extends DataTable.models.ext
+ */
+
+
+ /**
+ * DataTables extensions
+ *
+ * This namespace acts as a collection area for plug-ins that can be used to
+ * extend DataTables capabilities. Indeed many of the build in methods
+ * use this method to provide their own capabilities (sorting methods for
+ * example).
+ *
+ * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
+ * reasons
+ *
+ * @namespace
+ */
+ DataTable.ext = _ext = {
+ /**
+ * Buttons. For use with the Buttons extension for DataTables. This is
+ * defined here so other extensions can define buttons regardless of load
+ * order. It is _not_ used by DataTables core.
+ *
+ * @type object
+ * @default {}
+ */
+ buttons: {},
+
+
+ /**
+ * Element class names
+ *
+ * @type object
+ * @default {}
+ */
+ classes: {},
+
+
+ /**
+ * DataTables build type (expanded by the download builder)
+ *
+ * @type string
+ */
+ builder: "-source-",
+
+
+ /**
+ * Error reporting.
+ *
+ * How should DataTables report an error. Can take the value 'alert',
+ * 'throw', 'none' or a function.
+ *
+ * @type string|function
+ * @default alert
+ */
+ errMode: "alert",
+
+
+ /**
+ * Feature plug-ins.
+ *
+ * This is an array of objects which describe the feature plug-ins that are
+ * available to DataTables. These feature plug-ins are then available for
+ * use through the `dom` initialisation option.
+ *
+ * Each feature plug-in is described by an object which must have the
+ * following properties:
+ *
+ * * `fnInit` - function that is used to initialise the plug-in,
+ * * `cFeature` - a character so the feature can be enabled by the `dom`
+ * instillation option. This is case sensitive.
+ *
+ * The `fnInit` function has the following input parameters:
+ *
+ * 1. `{object}` DataTables settings object: see
+ * {@link DataTable.models.oSettings}
+ *
+ * And the following return is expected:
+ *
+ * * {node|null} The element which contains your feature. Note that the
+ * return may also be void if your plug-in does not require to inject any
+ * DOM elements into DataTables control (`dom`) - for example this might
+ * be useful when developing a plug-in which allows table control via
+ * keyboard entry
+ *
+ * @type array
+ *
+ * @example
+ * $.fn.dataTable.ext.features.push( {
+ * "fnInit": function( oSettings ) {
+ * return new TableTools( { "oDTSettings": oSettings } );
+ * },
+ * "cFeature": "T"
+ * } );
+ */
+ feature: [],
+
+
+ /**
+ * Row searching.
+ *
+ * This method of searching is complimentary to the default type based
+ * searching, and a lot more comprehensive as it allows you complete control
+ * over the searching logic. Each element in this array is a function
+ * (parameters described below) that is called for every row in the table,
+ * and your logic decides if it should be included in the searching data set
+ * or not.
+ *
+ * Searching functions have the following input parameters:
+ *
+ * 1. `{object}` DataTables settings object: see
+ * {@link DataTable.models.oSettings}
+ * 2. `{array|object}` Data for the row to be processed (same as the
+ * original format that was passed in as the data source, or an array
+ * from a DOM data source
+ * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
+ * can be useful to retrieve the `TR` element if you need DOM interaction.
+ *
+ * And the following return is expected:
+ *
+ * * {boolean} Include the row in the searched result set (true) or not
+ * (false)
+ *
+ * Note that as with the main search ability in DataTables, technically this
+ * is "filtering", since it is subtractive. However, for consistency in
+ * naming we call it searching here.
+ *
+ * @type array
+ * @default []
+ *
+ * @example
+ * // The following example shows custom search being applied to the
+ * // fourth column (i.e. the data[3] index) based on two input values
+ * // from the end-user, matching the data in a certain range.
+ * $.fn.dataTable.ext.search.push(
+ * function( settings, data, dataIndex ) {
+ * var min = document.getElementById('min').value * 1;
+ * var max = document.getElementById('max').value * 1;
+ * var version = data[3] == "-" ? 0 : data[3]*1;
+ *
+ * if ( min == "" && max == "" ) {
+ * return true;
+ * }
+ * else if ( min == "" && version < max ) {
+ * return true;
+ * }
+ * else if ( min < version && "" == max ) {
+ * return true;
+ * }
+ * else if ( min < version && version < max ) {
+ * return true;
+ * }
+ * return false;
+ * }
+ * );
+ */
+ search: [],
+
+
+ /**
+ * Selector extensions
+ *
+ * The `selector` option can be used to extend the options available for the
+ * selector modifier options (`selector-modifier` object data type) that
+ * each of the three built in selector types offer (row, column and cell +
+ * their plural counterparts). For example the Select extension uses this
+ * mechanism to provide an option to select only rows, columns and cells
+ * that have been marked as selected by the end user (`{selected: true}`),
+ * which can be used in conjunction with the existing built in selector
+ * options.
+ *
+ * Each property is an array to which functions can be pushed. The functions
+ * take three attributes:
+ *
+ * * Settings object for the host table
+ * * Options object (`selector-modifier` object type)
+ * * Array of selected item indexes
+ *
+ * The return is an array of the resulting item indexes after the custom
+ * selector has been applied.
+ *
+ * @type object
+ */
+ selector: {
+ cell: [],
+ column: [],
+ row: []
+ },
+
+
+ /**
+ * Internal functions, exposed for used in plug-ins.
+ *
+ * Please note that you should not need to use the internal methods for
+ * anything other than a plug-in (and even then, try to avoid if possible).
+ * The internal function may change between releases.
+ *
+ * @type object
+ * @default {}
+ */
+ internal: {},
+
+
+ /**
+ * Legacy configuration options. Enable and disable legacy options that
+ * are available in DataTables.
+ *
+ * @type object
+ */
+ legacy: {
+ /**
+ * Enable / disable DataTables 1.9 compatible server-side processing
+ * requests
+ *
+ * @type boolean
+ * @default null
+ */
+ ajax: null
+ },
+
+
+ /**
+ * Pagination plug-in methods.
+ *
+ * Each entry in this object is a function and defines which buttons should
+ * be shown by the pagination rendering method that is used for the table:
+ * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
+ * buttons are displayed in the document, while the functions here tell it
+ * what buttons to display. This is done by returning an array of button
+ * descriptions (what each button will do).
+ *
+ * Pagination types (the four built in options and any additional plug-in
+ * options defined here) can be used through the `paginationType`
+ * initialisation parameter.
+ *
+ * The functions defined take two parameters:
+ *
+ * 1. `{int} page` The current page index
+ * 2. `{int} pages` The number of pages in the table
+ *
+ * Each function is expected to return an array where each element of the
+ * array can be one of:
+ *
+ * * `first` - Jump to first page when activated
+ * * `last` - Jump to last page when activated
+ * * `previous` - Show previous page when activated
+ * * `next` - Show next page when activated
+ * * `{int}` - Show page of the index given
+ * * `{array}` - A nested array containing the above elements to add a
+ * containing 'DIV' element (might be useful for styling).
+ *
+ * Note that DataTables v1.9- used this object slightly differently whereby
+ * an object with two functions would be defined for each plug-in. That
+ * ability is still supported by DataTables 1.10+ to provide backwards
+ * compatibility, but this option of use is now decremented and no longer
+ * documented in DataTables 1.10+.
+ *
+ * @type object
+ * @default {}
+ *
+ * @example
+ * // Show previous, next and current page buttons only
+ * $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
+ * return [ 'previous', page, 'next' ];
+ * };
+ */
+ pager: {},
+
+
+ renderer: {
+ pageButton: {},
+ header: {}
+ },
+
+
+ /**
+ * Ordering plug-ins - custom data source
+ *
+ * The extension options for ordering of data available here is complimentary
+ * to the default type based ordering that DataTables typically uses. It
+ * allows much greater control over the the data that is being used to
+ * order a column, but is necessarily therefore more complex.
+ *
+ * This type of ordering is useful if you want to do ordering based on data
+ * live from the DOM (for example the contents of an 'input' element) rather
+ * than just the static string that DataTables knows of.
+ *
+ * The way these plug-ins work is that you create an array of the values you
+ * wish to be ordering for the column in question and then return that
+ * array. The data in the array much be in the index order of the rows in
+ * the table (not the currently ordering order!). Which order data gathering
+ * function is run here depends on the `dt-init columns.orderDataType`
+ * parameter that is used for the column (if any).
+ *
+ * The functions defined take two parameters:
+ *
+ * 1. `{object}` DataTables settings object: see
+ * {@link DataTable.models.oSettings}
+ * 2. `{int}` Target column index
+ *
+ * Each function is expected to return an array:
+ *
+ * * `{array}` Data for the column to be ordering upon
+ *
+ * @type array
+ *
+ * @example
+ * // Ordering using `input` node values
+ * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col )
+ * {
+ * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
+ * return $('input', td).val();
+ * } );
+ * }
+ */
+ order: {},
+
+
+ /**
+ * Type based plug-ins.
+ *
+ * Each column in DataTables has a type assigned to it, either by automatic
+ * detection or by direct assignment using the `type` option for the column.
+ * The type of a column will effect how it is ordering and search (plug-ins
+ * can also make use of the column type if required).
+ *
+ * @namespace
+ */
+ type: {
+ /**
+ * Type detection functions.
+ *
+ * The functions defined in this object are used to automatically detect
+ * a column's type, making initialisation of DataTables super easy, even
+ * when complex data is in the table.
+ *
+ * The functions defined take two parameters:
+ *
+ * 1. `{*}` Data from the column cell to be analysed
+ * 2. `{settings}` DataTables settings object. This can be used to
+ * perform context specific type detection - for example detection
+ * based on language settings such as using a comma for a decimal
+ * place. Generally speaking the options from the settings will not
+ * be required
+ *
+ * Each function is expected to return:
+ *
+ * * `{string|null}` Data type detected, or null if unknown (and thus
+ * pass it on to the other type detection functions.
+ *
+ * @type array
+ *
+ * @example
+ * // Currency type detection plug-in:
+ * $.fn.dataTable.ext.type.detect.push(
+ * function ( data, settings ) {
+ * // Check the numeric part
+ * if ( ! $.isNumeric( data.substring(1) ) ) {
+ * return null;
+ * }
+ *
+ * // Check prefixed by currency
+ * if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
+ * return 'currency';
+ * }
+ * return null;
+ * }
+ * );
+ */
+ detect: [],
+
+
+ /**
+ * Type based search formatting.
+ *
+ * The type based searching functions can be used to pre-format the
+ * data to be search on. For example, it can be used to strip HTML
+ * tags or to de-format telephone numbers for numeric only searching.
+ *
+ * Note that is a search is not defined for a column of a given type,
+ * no search formatting will be performed.
+ *
+ * Pre-processing of searching data plug-ins - When you assign the sType
+ * for a column (or have it automatically detected for you by DataTables
+ * or a type detection plug-in), you will typically be using this for
+ * custom sorting, but it can also be used to provide custom searching
+ * by allowing you to pre-processing the data and returning the data in
+ * the format that should be searched upon. This is done by adding
+ * functions this object with a parameter name which matches the sType
+ * for that target column. This is the corollary of <i>afnSortData</i>
+ * for searching data.
+ *
+ * The functions defined take a single parameter:
+ *
+ * 1. `{*}` Data from the column cell to be prepared for searching
+ *
+ * Each function is expected to return:
+ *
+ * * `{string|null}` Formatted string that will be used for the searching.
+ *
+ * @type object
+ * @default {}
+ *
+ * @example
+ * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
+ * return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
+ * }
+ */
+ search: {},
+
+
+ /**
+ * Type based ordering.
+ *
+ * The column type tells DataTables what ordering to apply to the table
+ * when a column is sorted upon. The order for each type that is defined,
+ * is defined by the functions available in this object.
+ *
+ * Each ordering option can be described by three properties added to
+ * this object:
+ *
+ * * `{type}-pre` - Pre-formatting function
+ * * `{type}-asc` - Ascending order function
+ * * `{type}-desc` - Descending order function
+ *
+ * All three can be used together, only `{type}-pre` or only
+ * `{type}-asc` and `{type}-desc` together. It is generally recommended
+ * that only `{type}-pre` is used, as this provides the optimal
+ * implementation in terms of speed, although the others are provided
+ * for compatibility with existing Javascript sort functions.
+ *
+ * `{type}-pre`: Functions defined take a single parameter:
+ *
+ * 1. `{*}` Data from the column cell to be prepared for ordering
+ *
+ * And return:
+ *
+ * * `{*}` Data to be sorted upon
+ *
+ * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
+ * functions, taking two parameters:
+ *
+ * 1. `{*}` Data to compare to the second parameter
+ * 2. `{*}` Data to compare to the first parameter
+ *
+ * And returning:
+ *
+ * * `{*}` Ordering match: <0 if first parameter should be sorted lower
+ * than the second parameter, ===0 if the two parameters are equal and
+ * >0 if the first parameter should be sorted height than the second
+ * parameter.
+ *
+ * @type object
+ * @default {}
+ *
+ * @example
+ * // Numeric ordering of formatted numbers with a pre-formatter
+ * $.extend( $.fn.dataTable.ext.type.order, {
+ * "string-pre": function(x) {
+ * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
+ * return parseFloat( a );
+ * }
+ * } );
+ *
+ * @example
+ * // Case-sensitive string ordering, with no pre-formatting method
+ * $.extend( $.fn.dataTable.ext.order, {
+ * "string-case-asc": function(x,y) {
+ * return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ * },
+ * "string-case-desc": function(x,y) {
+ * return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ * }
+ * } );
+ */
+ order: {}
+ },
+
+ /**
+ * Unique DataTables instance counter
+ *
+ * @type int
+ * @private
+ */
+ _unique: 0,
+
+
+ //
+ // Depreciated
+ // The following properties are retained for backwards compatiblity only.
+ // The should not be used in new projects and will be removed in a future
+ // version
+ //
+
+ /**
+ * Version check function.
+ * @type function
+ * @depreciated Since 1.10
+ */
+ fnVersionCheck: DataTable.fnVersionCheck,
+
+
+ /**
+ * Index for what 'this' index API functions should use
+ * @type int
+ * @deprecated Since v1.10
+ */
+ iApiIndex: 0,
+
+
+ /**
+ * jQuery UI class container
+ * @type object
+ * @deprecated Since v1.10
+ */
+ oJUIClasses: {},
+
+
+ /**
+ * Software version
+ * @type string
+ * @deprecated Since v1.10
+ */
+ sVersion: DataTable.version
+ };
+
+
+ //
+ // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
+ //
+ $.extend( _ext, {
+ afnFiltering: _ext.search,
+ aTypes: _ext.type.detect,
+ ofnSearch: _ext.type.search,
+ oSort: _ext.type.order,
+ afnSortData: _ext.order,
+ aoFeatures: _ext.feature,
+ oApi: _ext.internal,
+ oStdClasses: _ext.classes,
+ oPagination: _ext.pager
+ } );
+
+
+ $.extend( DataTable.ext.classes, {
+ "sTable": "dataTable",
+ "sNoFooter": "no-footer",
+
+ /* Paging buttons */
+ "sPageButton": "paginate_button",
+ "sPageButtonActive": "current",
+ "sPageButtonDisabled": "disabled",
+
+ /* Striping classes */
+ "sStripeOdd": "odd",
+ "sStripeEven": "even",
+
+ /* Empty row */
+ "sRowEmpty": "dataTables_empty",
+
+ /* Features */
+ "sWrapper": "dataTables_wrapper",
+ "sFilter": "dataTables_filter",
+ "sInfo": "dataTables_info",
+ "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
+ "sLength": "dataTables_length",
+ "sProcessing": "dataTables_processing",
+
+ /* Sorting */
+ "sSortAsc": "sorting_asc",
+ "sSortDesc": "sorting_desc",
+ "sSortable": "sorting", /* Sortable in both directions */
+ "sSortableAsc": "sorting_asc_disabled",
+ "sSortableDesc": "sorting_desc_disabled",
+ "sSortableNone": "sorting_disabled",
+ "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
+
+ /* Filtering */
+ "sFilterInput": "",
+
+ /* Page length */
+ "sLengthSelect": "",
+
+ /* Scrolling */
+ "sScrollWrapper": "dataTables_scroll",
+ "sScrollHead": "dataTables_scrollHead",
+ "sScrollHeadInner": "dataTables_scrollHeadInner",
+ "sScrollBody": "dataTables_scrollBody",
+ "sScrollFoot": "dataTables_scrollFoot",
+ "sScrollFootInner": "dataTables_scrollFootInner",
+
+ /* Misc */
+ "sHeaderTH": "",
+ "sFooterTH": "",
+
+ // Deprecated
+ "sSortJUIAsc": "",
+ "sSortJUIDesc": "",
+ "sSortJUI": "",
+ "sSortJUIAscAllowed": "",
+ "sSortJUIDescAllowed": "",
+ "sSortJUIWrapper": "",
+ "sSortIcon": "",
+ "sJUIHeader": "",
+ "sJUIFooter": ""
+ } );
+
+
+ var extPagination = DataTable.ext.pager;
+
+ function _numbers ( page, pages ) {
+ var
+ numbers = [],
+ buttons = extPagination.numbers_length,
+ half = Math.floor( buttons / 2 ),
+ i = 1;
+
+ if ( pages <= buttons ) {
+ numbers = _range( 0, pages );
+ }
+ else if ( page <= half ) {
+ numbers = _range( 0, buttons-2 );
+ numbers.push( 'ellipsis' );
+ numbers.push( pages-1 );
+ }
+ else if ( page >= pages - 1 - half ) {
+ numbers = _range( pages-(buttons-2), pages );
+ numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
+ numbers.splice( 0, 0, 0 );
+ }
+ else {
+ numbers = _range( page-half+2, page+half-1 );
+ numbers.push( 'ellipsis' );
+ numbers.push( pages-1 );
+ numbers.splice( 0, 0, 'ellipsis' );
+ numbers.splice( 0, 0, 0 );
+ }
+
+ numbers.DT_el = 'span';
+ return numbers;
+ }
+
+
+ $.extend( extPagination, {
+ simple: function ( page, pages ) {
+ return [ 'previous', 'next' ];
+ },
+
+ full: function ( page, pages ) {
+ return [ 'first', 'previous', 'next', 'last' ];
+ },
+
+ numbers: function ( page, pages ) {
+ return [ _numbers(page, pages) ];
+ },
+
+ simple_numbers: function ( page, pages ) {
+ return [ 'previous', _numbers(page, pages), 'next' ];
+ },
+
+ full_numbers: function ( page, pages ) {
+ return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
+ },
+
+ first_last_numbers: function (page, pages) {
+ return ['first', _numbers(page, pages), 'last'];
+ },
+
+ // For testing and plug-ins to use
+ _numbers: _numbers,
+
+ // Number of number buttons (including ellipsis) to show. _Must be odd!_
+ numbers_length: 7
+ } );
+
+
+ $.extend( true, DataTable.ext.renderer, {
+ pageButton: {
+ _: function ( settings, host, idx, buttons, page, pages ) {
+ var classes = settings.oClasses;
+ var lang = settings.oLanguage.oPaginate;
+ var aria = settings.oLanguage.oAria.paginate || {};
+ var btnDisplay, btnClass, counter=0;
+
+ var attach = function( container, buttons ) {
+ var i, ien, node, button;
+ var clickHandler = function ( e ) {
+ _fnPageChange( settings, e.data.action, true );
+ };
+
+ for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
+ button = buttons[i];
+
+ if ( $.isArray( button ) ) {
+ var inner = $( '<'+(button.DT_el || 'div')+'/>' )
+ .appendTo( container );
+ attach( inner, button );
+ }
+ else {
+ btnDisplay = null;
+ btnClass = '';
+
+ switch ( button ) {
+ case 'ellipsis':
+ container.append('<span class="ellipsis">&#x2026;</span>');
+ break;
+
+ case 'first':
+ btnDisplay = lang.sFirst;
+ btnClass = button + (page > 0 ?
+ '' : ' '+classes.sPageButtonDisabled);
+ break;
+
+ case 'previous':
+ btnDisplay = lang.sPrevious;
+ btnClass = button + (page > 0 ?
+ '' : ' '+classes.sPageButtonDisabled);
+ break;
+
+ case 'next':
+ btnDisplay = lang.sNext;
+ btnClass = button + (page < pages-1 ?
+ '' : ' '+classes.sPageButtonDisabled);
+ break;
+
+ case 'last':
+ btnDisplay = lang.sLast;
+ btnClass = button + (page < pages-1 ?
+ '' : ' '+classes.sPageButtonDisabled);
+ break;
+
+ default:
+ btnDisplay = button + 1;
+ btnClass = page === button ?
+ classes.sPageButtonActive : '';
+ break;
+ }
+
+ if ( btnDisplay !== null ) {
+ node = $('<a>', {
+ 'class': classes.sPageButton+' '+btnClass,
+ 'aria-controls': settings.sTableId,
+ 'aria-label': aria[ button ],
+ 'data-dt-idx': counter,
+ 'tabindex': settings.iTabIndex,
+ 'id': idx === 0 && typeof button === 'string' ?
+ settings.sTableId +'_'+ button :
+ null
+ } )
+ .html( btnDisplay )
+ .appendTo( container );
+
+ _fnBindAction(
+ node, {action: button}, clickHandler
+ );
+
+ counter++;
+ }
+ }
+ }
+ };
+
+ // IE9 throws an 'unknown error' if document.activeElement is used
+ // inside an iframe or frame. Try / catch the error. Not good for
+ // accessibility, but neither are frames.
+ var activeEl;
+
+ try {
+ // Because this approach is destroying and recreating the paging
+ // elements, focus is lost on the select button which is bad for
+ // accessibility. So we want to restore focus once the draw has
+ // completed
+ activeEl = $(host).find(document.activeElement).data('dt-idx');
+ }
+ catch (e) {}
+
+ attach( $(host).empty(), buttons );
+
+ if ( activeEl !== undefined ) {
+ $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
+ }
+ }
+ }
+ } );
+
+
+
+ // Built in type detection. See model.ext.aTypes for information about
+ // what is required from this methods.
+ $.extend( DataTable.ext.type.detect, [
+ // Plain numbers - first since V8 detects some plain numbers as dates
+ // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
+ function ( d, settings )
+ {
+ var decimal = settings.oLanguage.sDecimal;
+ return _isNumber( d, decimal ) ? 'num'+decimal : null;
+ },
+
+ // Dates (only those recognised by the browser's Date.parse)
+ function ( d, settings )
+ {
+ // V8 tries _very_ hard to make a string passed into `Date.parse()`
+ // valid, so we need to use a regex to restrict date formats. Use a
+ // plug-in for anything other than ISO8601 style strings
+ if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
+ return null;
+ }
+ var parsed = Date.parse(d);
+ return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
+ },
+
+ // Formatted numbers
+ function ( d, settings )
+ {
+ var decimal = settings.oLanguage.sDecimal;
+ return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
+ },
+
+ // HTML numeric
+ function ( d, settings )
+ {
+ var decimal = settings.oLanguage.sDecimal;
+ return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
+ },
+
+ // HTML numeric, formatted
+ function ( d, settings )
+ {
+ var decimal = settings.oLanguage.sDecimal;
+ return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
+ },
+
+ // HTML (this is strict checking - there must be html)
+ function ( d, settings )
+ {
+ return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
+ 'html' : null;
+ }
+ ] );
+
+
+
+ // Filter formatting functions. See model.ext.ofnSearch for information about
+ // what is required from these methods.
+ //
+ // Note that additional search methods are added for the html numbers and
+ // html formatted numbers by `_addNumericSort()` when we know what the decimal
+ // place is
+
+
+ $.extend( DataTable.ext.type.search, {
+ html: function ( data ) {
+ return _empty(data) ?
+ data :
+ typeof data === 'string' ?
+ data
+ .replace( _re_new_lines, " " )
+ .replace( _re_html, "" ) :
+ '';
+ },
+
+ string: function ( data ) {
+ return _empty(data) ?
+ data :
+ typeof data === 'string' ?
+ data.replace( _re_new_lines, " " ) :
+ data;
+ }
+ } );
+
+
+
+ var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
+ if ( d !== 0 && (!d || d === '-') ) {
+ return -Infinity;
+ }
+
+ // If a decimal place other than `.` is used, it needs to be given to the
+ // function so we can detect it and replace with a `.` which is the only
+ // decimal place Javascript recognises - it is not locale aware.
+ if ( decimalPlace ) {
+ d = _numToDecimal( d, decimalPlace );
+ }
+
+ if ( d.replace ) {
+ if ( re1 ) {
+ d = d.replace( re1, '' );
+ }
+
+ if ( re2 ) {
+ d = d.replace( re2, '' );
+ }
+ }
+
+ return d * 1;
+ };
+
+
+ // Add the numeric 'deformatting' functions for sorting and search. This is done
+ // in a function to provide an easy ability for the language options to add
+ // additional methods if a non-period decimal place is used.
+ function _addNumericSort ( decimalPlace ) {
+ $.each(
+ {
+ // Plain numbers
+ "num": function ( d ) {
+ return __numericReplace( d, decimalPlace );
+ },
+
+ // Formatted numbers
+ "num-fmt": function ( d ) {
+ return __numericReplace( d, decimalPlace, _re_formatted_numeric );
+ },
+
+ // HTML numeric
+ "html-num": function ( d ) {
+ return __numericReplace( d, decimalPlace, _re_html );
+ },
+
+ // HTML numeric, formatted
+ "html-num-fmt": function ( d ) {
+ return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
+ }
+ },
+ function ( key, fn ) {
+ // Add the ordering method
+ _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
+
+ // For HTML types add a search formatter that will strip the HTML
+ if ( key.match(/^html\-/) ) {
+ _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
+ }
+ }
+ );
+ }
+
+
+ // Default sort methods
+ $.extend( _ext.type.order, {
+ // Dates
+ "date-pre": function ( d ) {
+ return Date.parse( d ) || -Infinity;
+ },
+
+ // html
+ "html-pre": function ( a ) {
+ return _empty(a) ?
+ '' :
+ a.replace ?
+ a.replace( /<.*?>/g, "" ).toLowerCase() :
+ a+'';
+ },
+
+ // string
+ "string-pre": function ( a ) {
+ // This is a little complex, but faster than always calling toString,
+ // http://jsperf.com/tostring-v-check
+ return _empty(a) ?
+ '' :
+ typeof a === 'string' ?
+ a.toLowerCase() :
+ ! a.toString ?
+ '' :
+ a.toString();
+ },
+
+ // string-asc and -desc are retained only for compatibility with the old
+ // sort methods
+ "string-asc": function ( x, y ) {
+ return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+ },
+
+ "string-desc": function ( x, y ) {
+ return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+ }
+ } );
+
+
+ // Numeric sorting types - order doesn't matter here
+ _addNumericSort( '' );
+
+
+ $.extend( true, DataTable.ext.renderer, {
+ header: {
+ _: function ( settings, cell, column, classes ) {
+ // No additional mark-up required
+ // Attach a sort listener to update on sort - note that using the
+ // `DT` namespace will allow the event to be removed automatically
+ // on destroy, while the `dt` namespaced event is the one we are
+ // listening for
+ $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
+ if ( settings !== ctx ) { // need to check this this is the host
+ return; // table, not a nested one
+ }
+
+ var colIdx = column.idx;
+
+ cell
+ .removeClass(
+ column.sSortingClass +' '+
+ classes.sSortAsc +' '+
+ classes.sSortDesc
+ )
+ .addClass( columns[ colIdx ] == 'asc' ?
+ classes.sSortAsc : columns[ colIdx ] == 'desc' ?
+ classes.sSortDesc :
+ column.sSortingClass
+ );
+ } );
+ },
+
+ jqueryui: function ( settings, cell, column, classes ) {
+ $('<div/>')
+ .addClass( classes.sSortJUIWrapper )
+ .append( cell.contents() )
+ .append( $('<span/>')
+ .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
+ )
+ .appendTo( cell );
+
+ // Attach a sort listener to update on sort
+ $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
+ if ( settings !== ctx ) {
+ return;
+ }
+
+ var colIdx = column.idx;
+
+ cell
+ .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
+ .addClass( columns[ colIdx ] == 'asc' ?
+ classes.sSortAsc : columns[ colIdx ] == 'desc' ?
+ classes.sSortDesc :
+ column.sSortingClass
+ );
+
+ cell
+ .find( 'span.'+classes.sSortIcon )
+ .removeClass(
+ classes.sSortJUIAsc +" "+
+ classes.sSortJUIDesc +" "+
+ classes.sSortJUI +" "+
+ classes.sSortJUIAscAllowed +" "+
+ classes.sSortJUIDescAllowed
+ )
+ .addClass( columns[ colIdx ] == 'asc' ?
+ classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
+ classes.sSortJUIDesc :
+ column.sSortingClassJUI
+ );
+ } );
+ }
+ }
+ } );
+
+ /*
+ * Public helper functions. These aren't used internally by DataTables, or
+ * called by any of the options passed into DataTables, but they can be used
+ * externally by developers working with DataTables. They are helper functions
+ * to make working with DataTables a little bit easier.
+ */
+
+ var __htmlEscapeEntities = function ( d ) {
+ return typeof d === 'string' ?
+ d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
+ d;
+ };
+
+ /**
+ * Helpers for `columns.render`.
+ *
+ * The options defined here can be used with the `columns.render` initialisation
+ * option to provide a display renderer. The following functions are defined:
+ *
+ * * `number` - Will format numeric data (defined by `columns.data`) for
+ * display, retaining the original unformatted data for sorting and filtering.
+ * It takes 5 parameters:
+ * * `string` - Thousands grouping separator
+ * * `string` - Decimal point indicator
+ * * `integer` - Number of decimal points to show
+ * * `string` (optional) - Prefix.
+ * * `string` (optional) - Postfix (/suffix).
+ * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
+ * parameters.
+ *
+ * @example
+ * // Column definition using the number renderer
+ * {
+ * data: "salary",
+ * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
+ * }
+ *
+ * @namespace
+ */
+ DataTable.render = {
+ number: function ( thousands, decimal, precision, prefix, postfix ) {
+ return {
+ display: function ( d ) {
+ if ( typeof d !== 'number' && typeof d !== 'string' ) {
+ return d;
+ }
+
+ var negative = d < 0 ? '-' : '';
+ var flo = parseFloat( d );
+
+ // If NaN then there isn't much formatting that we can do - just
+ // return immediately, escaping any HTML (this was supposed to
+ // be a number after all)
+ if ( isNaN( flo ) ) {
+ return __htmlEscapeEntities( d );
+ }
+
+ flo = flo.toFixed( precision );
+ d = Math.abs( flo );
+
+ var intPart = parseInt( d, 10 );
+ var floatPart = precision ?
+ decimal+(d - intPart).toFixed( precision ).substring( 2 ):
+ '';
+
+ return negative + (prefix||'') +
+ intPart.toString().replace(
+ /\B(?=(\d{3})+(?!\d))/g, thousands
+ ) +
+ floatPart +
+ (postfix||'');
+ }
+ };
+ },
+
+ text: function () {
+ return {
+ display: __htmlEscapeEntities
+ };
+ }
+ };
+
+
+ /*
+ * This is really a good bit rubbish this method of exposing the internal methods
+ * publicly... - To be fixed in 2.0 using methods on the prototype
+ */
+
+
+ /**
+ * Create a wrapper function for exporting an internal functions to an external API.
+ * @param {string} fn API function name
+ * @returns {function} wrapped function
+ * @memberof DataTable#internal
+ */
+ function _fnExternApiFunc (fn)
+ {
+ return function() {
+ var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
+ Array.prototype.slice.call(arguments)
+ );
+ return DataTable.ext.internal[fn].apply( this, args );
+ };
+ }
+
+
+ /**
+ * Reference to internal functions for use by plug-in developers. Note that
+ * these methods are references to internal functions and are considered to be
+ * private. If you use these methods, be aware that they are liable to change
+ * between versions.
+ * @namespace
+ */
+ $.extend( DataTable.ext.internal, {
+ _fnExternApiFunc: _fnExternApiFunc,
+ _fnBuildAjax: _fnBuildAjax,
+ _fnAjaxUpdate: _fnAjaxUpdate,
+ _fnAjaxParameters: _fnAjaxParameters,
+ _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
+ _fnAjaxDataSrc: _fnAjaxDataSrc,
+ _fnAddColumn: _fnAddColumn,
+ _fnColumnOptions: _fnColumnOptions,
+ _fnAdjustColumnSizing: _fnAdjustColumnSizing,
+ _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
+ _fnColumnIndexToVisible: _fnColumnIndexToVisible,
+ _fnVisbleColumns: _fnVisbleColumns,
+ _fnGetColumns: _fnGetColumns,
+ _fnColumnTypes: _fnColumnTypes,
+ _fnApplyColumnDefs: _fnApplyColumnDefs,
+ _fnHungarianMap: _fnHungarianMap,
+ _fnCamelToHungarian: _fnCamelToHungarian,
+ _fnLanguageCompat: _fnLanguageCompat,
+ _fnBrowserDetect: _fnBrowserDetect,
+ _fnAddData: _fnAddData,
+ _fnAddTr: _fnAddTr,
+ _fnNodeToDataIndex: _fnNodeToDataIndex,
+ _fnNodeToColumnIndex: _fnNodeToColumnIndex,
+ _fnGetCellData: _fnGetCellData,
+ _fnSetCellData: _fnSetCellData,
+ _fnSplitObjNotation: _fnSplitObjNotation,
+ _fnGetObjectDataFn: _fnGetObjectDataFn,
+ _fnSetObjectDataFn: _fnSetObjectDataFn,
+ _fnGetDataMaster: _fnGetDataMaster,
+ _fnClearTable: _fnClearTable,
+ _fnDeleteIndex: _fnDeleteIndex,
+ _fnInvalidate: _fnInvalidate,
+ _fnGetRowElements: _fnGetRowElements,
+ _fnCreateTr: _fnCreateTr,
+ _fnBuildHead: _fnBuildHead,
+ _fnDrawHead: _fnDrawHead,
+ _fnDraw: _fnDraw,
+ _fnReDraw: _fnReDraw,
+ _fnAddOptionsHtml: _fnAddOptionsHtml,
+ _fnDetectHeader: _fnDetectHeader,
+ _fnGetUniqueThs: _fnGetUniqueThs,
+ _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
+ _fnFilterComplete: _fnFilterComplete,
+ _fnFilterCustom: _fnFilterCustom,
+ _fnFilterColumn: _fnFilterColumn,
+ _fnFilter: _fnFilter,
+ _fnFilterCreateSearch: _fnFilterCreateSearch,
+ _fnEscapeRegex: _fnEscapeRegex,
+ _fnFilterData: _fnFilterData,
+ _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
+ _fnUpdateInfo: _fnUpdateInfo,
+ _fnInfoMacros: _fnInfoMacros,
+ _fnInitialise: _fnInitialise,
+ _fnInitComplete: _fnInitComplete,
+ _fnLengthChange: _fnLengthChange,
+ _fnFeatureHtmlLength: _fnFeatureHtmlLength,
+ _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
+ _fnPageChange: _fnPageChange,
+ _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
+ _fnProcessingDisplay: _fnProcessingDisplay,
+ _fnFeatureHtmlTable: _fnFeatureHtmlTable,
+ _fnScrollDraw: _fnScrollDraw,
+ _fnApplyToChildren: _fnApplyToChildren,
+ _fnCalculateColumnWidths: _fnCalculateColumnWidths,
+ _fnThrottle: _fnThrottle,
+ _fnConvertToWidth: _fnConvertToWidth,
+ _fnGetWidestNode: _fnGetWidestNode,
+ _fnGetMaxLenString: _fnGetMaxLenString,
+ _fnStringToCss: _fnStringToCss,
+ _fnSortFlatten: _fnSortFlatten,
+ _fnSort: _fnSort,
+ _fnSortAria: _fnSortAria,
+ _fnSortListener: _fnSortListener,
+ _fnSortAttachListener: _fnSortAttachListener,
+ _fnSortingClasses: _fnSortingClasses,
+ _fnSortData: _fnSortData,
+ _fnSaveState: _fnSaveState,
+ _fnLoadState: _fnLoadState,
+ _fnSettingsFromNode: _fnSettingsFromNode,
+ _fnLog: _fnLog,
+ _fnMap: _fnMap,
+ _fnBindAction: _fnBindAction,
+ _fnCallbackReg: _fnCallbackReg,
+ _fnCallbackFire: _fnCallbackFire,
+ _fnLengthOverflow: _fnLengthOverflow,
+ _fnRenderer: _fnRenderer,
+ _fnDataSource: _fnDataSource,
+ _fnRowAttributes: _fnRowAttributes,
+ _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
+ // in 1.10, so this dead-end function is
+ // added to prevent errors
+ } );
+
+
+ // jQuery access
+ $.fn.dataTable = DataTable;
+
+ // Provide access to the host jQuery object (circular reference)
+ DataTable.$ = $;
+
+ // Legacy aliases
+ $.fn.dataTableSettings = DataTable.settings;
+ $.fn.dataTableExt = DataTable.ext;
+
+ // With a capital `D` we return a DataTables API instance rather than a
+ // jQuery object
+ $.fn.DataTable = function ( opts ) {
+ return $(this).dataTable( opts ).api();
+ };
+
+ // All properties that are available to $.fn.dataTable should also be
+ // available on $.fn.DataTable
+ $.each( DataTable, function ( prop, val ) {
+ $.fn.DataTable[ prop ] = val;
+ } );
+
+
+ // Information about events fired by DataTables - for documentation.
+ /**
+ * Draw event, fired whenever the table is redrawn on the page, at the same
+ * point as fnDrawCallback. This may be useful for binding events or
+ * performing calculations when the table is altered at all.
+ * @name DataTable#draw.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Search event, fired when the searching applied to the table (using the
+ * built-in global search, or column filters) is altered.
+ * @name DataTable#search.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Page change event, fired when the paging of the table is altered.
+ * @name DataTable#page.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Order event, fired when the ordering applied to the table is altered.
+ * @name DataTable#order.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * DataTables initialisation complete event, fired when the table is fully
+ * drawn, including Ajax data loaded, if Ajax data is required.
+ * @name DataTable#init.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The JSON object request from the server - only
+ * present if client-side Ajax sourced data is used</li></ol>
+ */
+
+ /**
+ * State save event, fired when the table has changed state a new state save
+ * is required. This event allows modification of the state saving object
+ * prior to actually doing the save, including addition or other state
+ * properties (for plug-ins) or modification of a DataTables core property.
+ * @name DataTable#stateSaveParams.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The state information to be saved
+ */
+
+ /**
+ * State load event, fired when the table is loading state from the stored
+ * data, but prior to the settings object being modified by the saved state
+ * - allowing modification of the saved state is required or loading of
+ * state for a plug-in.
+ * @name DataTable#stateLoadParams.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The saved state information
+ */
+
+ /**
+ * State loaded event, fired when state has been loaded from stored data and
+ * the settings object has been modified by the loaded data.
+ * @name DataTable#stateLoaded.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {object} json The saved state information
+ */
+
+ /**
+ * Processing event, fired when DataTables is doing some kind of processing
+ * (be it, order, searcg or anything else). It can be used to indicate to
+ * the end user that there is something happening, or that something has
+ * finished.
+ * @name DataTable#processing.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} oSettings DataTables settings object
+ * @param {boolean} bShow Flag for if DataTables is doing processing or not
+ */
+
+ /**
+ * Ajax (XHR) event, fired whenever an Ajax request is completed from a
+ * request to made to the server for new data. This event is called before
+ * DataTables processed the returned data, so it can also be used to pre-
+ * process the data returned from the server, if needed.
+ *
+ * Note that this trigger is called in `fnServerData`, if you override
+ * `fnServerData` and which to use this event, you need to trigger it in you
+ * success function.
+ * @name DataTable#xhr.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ * @param {object} json JSON returned from the server
+ *
+ * @example
+ * // Use a custom property returned from the server in another DOM element
+ * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
+ * $('#status').html( json.status );
+ * } );
+ *
+ * @example
+ * // Pre-process the data returned from the server
+ * $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
+ * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
+ * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
+ * }
+ * // Note no return - manipulate the data directly in the JSON object.
+ * } );
+ */
+
+ /**
+ * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
+ * or passing the bDestroy:true parameter in the initialisation object. This
+ * can be used to remove bound events, added DOM nodes, etc.
+ * @name DataTable#destroy.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Page length change event, fired when number of records to show on each
+ * page (the length) is changed.
+ * @name DataTable#length.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ * @param {integer} len New length
+ */
+
+ /**
+ * Column sizing has changed.
+ * @name DataTable#column-sizing.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ */
+
+ /**
+ * Column visibility has changed.
+ * @name DataTable#column-visibility.dt
+ * @event
+ * @param {event} e jQuery event object
+ * @param {object} o DataTables settings object {@link DataTable.models.oSettings}
+ * @param {int} column Column index
+ * @param {bool} vis `false` if column now hidden, or `true` if visible
+ */
+
+ return $.fn.dataTable;
+}));
+
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Afrikaans [af]
+//! author : Werner Mollentze : https://github.com/wernerm
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var af = moment.defineLocale('af', {
+ months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
+ monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
+ weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
+ weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
+ weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
+ meridiemParse: /vm|nm/i,
+ isPM : function (input) {
+ return /^nm$/i.test(input);
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 12) {
+ return isLower ? 'vm' : 'VM';
+ } else {
+ return isLower ? 'nm' : 'NM';
+ }
+ },
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Vandag om] LT',
+ nextDay : '[Môre om] LT',
+ nextWeek : 'dddd [om] LT',
+ lastDay : '[Gister om] LT',
+ lastWeek : '[Laas] dddd [om] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'oor %s',
+ past : '%s gelede',
+ s : '\'n paar sekondes',
+ ss : '%d sekondes',
+ m : '\'n minuut',
+ mm : '%d minute',
+ h : '\'n uur',
+ hh : '%d ure',
+ d : '\'n dag',
+ dd : '%d dae',
+ M : '\'n maand',
+ MM : '%d maande',
+ y : '\'n jaar',
+ yy : '%d jaar'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
+ ordinal : function (number) {
+ return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
+ },
+ week : {
+ dow : 1, // Maandag is die eerste dag van die week.
+ doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
+ }
+});
+
+return af;
+
+})));
+
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Arabic [ar]
+//! author : Abdel Said: https://github.com/abdelsaid
+//! author : Ahmed Elkhatib
+//! author : forabi https://github.com/forabi
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '١',
+ '2': '٢',
+ '3': '٣',
+ '4': '٤',
+ '5': '٥',
+ '6': '٦',
+ '7': '٧',
+ '8': '٨',
+ '9': '٩',
+ '0': '٠'
+};
+var numberMap = {
+ '١': '1',
+ '٢': '2',
+ '٣': '3',
+ '٤': '4',
+ '٥': '5',
+ '٦': '6',
+ '٧': '7',
+ '٨': '8',
+ '٩': '9',
+ '٠': '0'
+};
+var pluralForm = function (n) {
+ return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
+};
+var plurals = {
+ s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
+ m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
+ h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
+ d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
+ M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
+ y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
+};
+var pluralize = function (u) {
+ return function (number, withoutSuffix, string, isFuture) {
+ var f = pluralForm(number),
+ str = plurals[u][pluralForm(number)];
+ if (f === 2) {
+ str = str[withoutSuffix ? 0 : 1];
+ }
+ return str.replace(/%d/i, number);
+ };
+};
+var months = [
+ 'يناير',
+ 'فبراير',
+ 'مارس',
+ 'أبريل',
+ 'مايو',
+ 'يونيو',
+ 'يوليو',
+ 'أغسطس',
+ 'سبتمبر',
+ 'أكتوبر',
+ 'نوفمبر',
+ 'ديسمبر'
+];
+
+var ar = moment.defineLocale('ar', {
+ months : months,
+ monthsShort : months,
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'D/\u200FM/\u200FYYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /ص|م/,
+ isPM : function (input) {
+ return 'م' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ص';
+ } else {
+ return 'م';
+ }
+ },
+ calendar : {
+ sameDay: '[اليوم عند الساعة] LT',
+ nextDay: '[غدًا عند الساعة] LT',
+ nextWeek: 'dddd [عند الساعة] LT',
+ lastDay: '[أمس عند الساعة] LT',
+ lastWeek: 'dddd [عند الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'بعد %s',
+ past : 'منذ %s',
+ s : pluralize('s'),
+ ss : pluralize('s'),
+ m : pluralize('m'),
+ mm : pluralize('m'),
+ h : pluralize('h'),
+ hh : pluralize('h'),
+ d : pluralize('d'),
+ dd : pluralize('d'),
+ M : pluralize('M'),
+ MM : pluralize('M'),
+ y : pluralize('y'),
+ yy : pluralize('y')
+ },
+ preparse: function (string) {
+ return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
+ return numberMap[match];
+ }).replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ }).replace(/,/g, '،');
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ar;
+
+})));
+
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Arabic (Algeria) [ar-dz]
+//! author : Noureddine LOUAHEDJ : https://github.com/noureddineme
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var arDz = moment.defineLocale('ar-dz', {
+ months : 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ monthsShort : 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'احد_اثنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'أح_إث_ثلا_أر_خم_جم_سب'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[اليوم على الساعة] LT',
+ nextDay: '[غدا على الساعة] LT',
+ nextWeek: 'dddd [على الساعة] LT',
+ lastDay: '[أمس على الساعة] LT',
+ lastWeek: 'dddd [على الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'في %s',
+ past : 'منذ %s',
+ s : 'ثوان',
+ ss : '%d ثانية',
+ m : 'دقيقة',
+ mm : '%d دقائق',
+ h : 'ساعة',
+ hh : '%d ساعات',
+ d : 'يوم',
+ dd : '%d أيام',
+ M : 'شهر',
+ MM : '%d أشهر',
+ y : 'سنة',
+ yy : '%d سنوات'
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 4 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return arDz;
+
+})));
+
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Arabic (Kuwait) [ar-kw]
+//! author : Nusret Parlak: https://github.com/nusretparlak
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var arKw = moment.defineLocale('ar-kw', {
+ months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+ monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+ weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[اليوم على الساعة] LT',
+ nextDay: '[غدا على الساعة] LT',
+ nextWeek: 'dddd [على الساعة] LT',
+ lastDay: '[أمس على الساعة] LT',
+ lastWeek: 'dddd [على الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'في %s',
+ past : 'منذ %s',
+ s : 'ثوان',
+ ss : '%d ثانية',
+ m : 'دقيقة',
+ mm : '%d دقائق',
+ h : 'ساعة',
+ hh : '%d ساعات',
+ d : 'يوم',
+ dd : '%d أيام',
+ M : 'شهر',
+ MM : '%d أشهر',
+ y : 'سنة',
+ yy : '%d سنوات'
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return arKw;
+
+})));
+
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Arabic (Lybia) [ar-ly]
+//! author : Ali Hmer: https://github.com/kikoanis
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '1',
+ '2': '2',
+ '3': '3',
+ '4': '4',
+ '5': '5',
+ '6': '6',
+ '7': '7',
+ '8': '8',
+ '9': '9',
+ '0': '0'
+};
+var pluralForm = function (n) {
+ return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
+};
+var plurals = {
+ s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
+ m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
+ h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
+ d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
+ M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
+ y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
+};
+var pluralize = function (u) {
+ return function (number, withoutSuffix, string, isFuture) {
+ var f = pluralForm(number),
+ str = plurals[u][pluralForm(number)];
+ if (f === 2) {
+ str = str[withoutSuffix ? 0 : 1];
+ }
+ return str.replace(/%d/i, number);
+ };
+};
+var months = [
+ 'يناير',
+ 'فبراير',
+ 'مارس',
+ 'أبريل',
+ 'مايو',
+ 'يونيو',
+ 'يوليو',
+ 'أغسطس',
+ 'سبتمبر',
+ 'أكتوبر',
+ 'نوفمبر',
+ 'ديسمبر'
+];
+
+var arLy = moment.defineLocale('ar-ly', {
+ months : months,
+ monthsShort : months,
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'D/\u200FM/\u200FYYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /ص|م/,
+ isPM : function (input) {
+ return 'م' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ص';
+ } else {
+ return 'م';
+ }
+ },
+ calendar : {
+ sameDay: '[اليوم عند الساعة] LT',
+ nextDay: '[غدًا عند الساعة] LT',
+ nextWeek: 'dddd [عند الساعة] LT',
+ lastDay: '[أمس عند الساعة] LT',
+ lastWeek: 'dddd [عند الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'بعد %s',
+ past : 'منذ %s',
+ s : pluralize('s'),
+ ss : pluralize('s'),
+ m : pluralize('m'),
+ mm : pluralize('m'),
+ h : pluralize('h'),
+ hh : pluralize('h'),
+ d : pluralize('d'),
+ dd : pluralize('d'),
+ M : pluralize('M'),
+ MM : pluralize('M'),
+ y : pluralize('y'),
+ yy : pluralize('y')
+ },
+ preparse: function (string) {
+ return string.replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ }).replace(/,/g, '،');
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return arLy;
+
+})));
+
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Arabic (Morocco) [ar-ma]
+//! author : ElFadili Yassine : https://github.com/ElFadiliY
+//! author : Abdel Said : https://github.com/abdelsaid
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var arMa = moment.defineLocale('ar-ma', {
+ months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+ monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+ weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[اليوم على الساعة] LT',
+ nextDay: '[غدا على الساعة] LT',
+ nextWeek: 'dddd [على الساعة] LT',
+ lastDay: '[أمس على الساعة] LT',
+ lastWeek: 'dddd [على الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'في %s',
+ past : 'منذ %s',
+ s : 'ثوان',
+ ss : '%d ثانية',
+ m : 'دقيقة',
+ mm : '%d دقائق',
+ h : 'ساعة',
+ hh : '%d ساعات',
+ d : 'يوم',
+ dd : '%d أيام',
+ M : 'شهر',
+ MM : '%d أشهر',
+ y : 'سنة',
+ yy : '%d سنوات'
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return arMa;
+
+})));
+
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Arabic (Saudi Arabia) [ar-sa]
+//! author : Suhail Alkowaileet : https://github.com/xsoh
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '١',
+ '2': '٢',
+ '3': '٣',
+ '4': '٤',
+ '5': '٥',
+ '6': '٦',
+ '7': '٧',
+ '8': '٨',
+ '9': '٩',
+ '0': '٠'
+};
+var numberMap = {
+ '١': '1',
+ '٢': '2',
+ '٣': '3',
+ '٤': '4',
+ '٥': '5',
+ '٦': '6',
+ '٧': '7',
+ '٨': '8',
+ '٩': '9',
+ '٠': '0'
+};
+
+var arSa = moment.defineLocale('ar-sa', {
+ months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /ص|م/,
+ isPM : function (input) {
+ return 'م' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ص';
+ } else {
+ return 'م';
+ }
+ },
+ calendar : {
+ sameDay: '[اليوم على الساعة] LT',
+ nextDay: '[غدا على الساعة] LT',
+ nextWeek: 'dddd [على الساعة] LT',
+ lastDay: '[أمس على الساعة] LT',
+ lastWeek: 'dddd [على الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'في %s',
+ past : 'منذ %s',
+ s : 'ثوان',
+ ss : '%d ثانية',
+ m : 'دقيقة',
+ mm : '%d دقائق',
+ h : 'ساعة',
+ hh : '%d ساعات',
+ d : 'يوم',
+ dd : '%d أيام',
+ M : 'شهر',
+ MM : '%d أشهر',
+ y : 'سنة',
+ yy : '%d سنوات'
+ },
+ preparse: function (string) {
+ return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
+ return numberMap[match];
+ }).replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ }).replace(/,/g, '،');
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return arSa;
+
+})));
+
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Arabic (Tunisia) [ar-tn]
+//! author : Nader Toukabri : https://github.com/naderio
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var arTn = moment.defineLocale('ar-tn', {
+ months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY HH:mm',
+ LLLL: 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar: {
+ sameDay: '[اليوم على الساعة] LT',
+ nextDay: '[غدا على الساعة] LT',
+ nextWeek: 'dddd [على الساعة] LT',
+ lastDay: '[أمس على الساعة] LT',
+ lastWeek: 'dddd [على الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: 'في %s',
+ past: 'منذ %s',
+ s: 'ثوان',
+ ss : '%d ثانية',
+ m: 'دقيقة',
+ mm: '%d دقائق',
+ h: 'ساعة',
+ hh: '%d ساعات',
+ d: 'يوم',
+ dd: '%d أيام',
+ M: 'شهر',
+ MM: '%d أشهر',
+ y: 'سنة',
+ yy: '%d سنوات'
+ },
+ week: {
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return arTn;
+
+})));
+
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Azerbaijani [az]
+//! author : topchiyev : https://github.com/topchiyev
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+ 1: '-inci',
+ 5: '-inci',
+ 8: '-inci',
+ 70: '-inci',
+ 80: '-inci',
+ 2: '-nci',
+ 7: '-nci',
+ 20: '-nci',
+ 50: '-nci',
+ 3: '-üncü',
+ 4: '-üncü',
+ 100: '-üncü',
+ 6: '-ncı',
+ 9: '-uncu',
+ 10: '-uncu',
+ 30: '-uncu',
+ 60: '-ıncı',
+ 90: '-ıncı'
+};
+
+var az = moment.defineLocale('az', {
+ months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
+ monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
+ weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
+ weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
+ weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[bugün saat] LT',
+ nextDay : '[sabah saat] LT',
+ nextWeek : '[gələn həftə] dddd [saat] LT',
+ lastDay : '[dünən] LT',
+ lastWeek : '[keçən həftə] dddd [saat] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s sonra',
+ past : '%s əvvəl',
+ s : 'birneçə saniyyə',
+ ss : '%d saniyə',
+ m : 'bir dəqiqə',
+ mm : '%d dəqiqə',
+ h : 'bir saat',
+ hh : '%d saat',
+ d : 'bir gün',
+ dd : '%d gün',
+ M : 'bir ay',
+ MM : '%d ay',
+ y : 'bir il',
+ yy : '%d il'
+ },
+ meridiemParse: /gecə|səhər|gündüz|axşam/,
+ isPM : function (input) {
+ return /^(gündüz|axşam)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'gecə';
+ } else if (hour < 12) {
+ return 'səhər';
+ } else if (hour < 17) {
+ return 'gündüz';
+ } else {
+ return 'axşam';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
+ ordinal : function (number) {
+ if (number === 0) { // special case for zero
+ return number + '-ıncı';
+ }
+ var a = number % 10,
+ b = number % 100 - a,
+ c = number >= 100 ? 100 : null;
+ return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return az;
+
+})));
+
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Belarusian [be]
+//! author : Dmitry Demidov : https://github.com/demidov91
+//! author: Praleska: http://praleska.pro/
+//! Author : Menelion Elensúle : https://github.com/Oire
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function plural(word, num) {
+ var forms = word.split('_');
+ return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ var format = {
+ 'ss': withoutSuffix ? 'секунда_секунды_секунд' : 'секунду_секунды_секунд',
+ 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
+ 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
+ 'dd': 'дзень_дні_дзён',
+ 'MM': 'месяц_месяцы_месяцаў',
+ 'yy': 'год_гады_гадоў'
+ };
+ if (key === 'm') {
+ return withoutSuffix ? 'хвіліна' : 'хвіліну';
+ }
+ else if (key === 'h') {
+ return withoutSuffix ? 'гадзіна' : 'гадзіну';
+ }
+ else {
+ return number + ' ' + plural(format[key], +number);
+ }
+}
+
+var be = moment.defineLocale('be', {
+ months : {
+ format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'),
+ standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_')
+ },
+ monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
+ weekdays : {
+ format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'),
+ standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
+ isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/
+ },
+ weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+ weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY г.',
+ LLL : 'D MMMM YYYY г., HH:mm',
+ LLLL : 'dddd, D MMMM YYYY г., HH:mm'
+ },
+ calendar : {
+ sameDay: '[Сёння ў] LT',
+ nextDay: '[Заўтра ў] LT',
+ lastDay: '[Учора ў] LT',
+ nextWeek: function () {
+ return '[У] dddd [ў] LT';
+ },
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ case 5:
+ case 6:
+ return '[У мінулую] dddd [ў] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[У мінулы] dddd [ў] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'праз %s',
+ past : '%s таму',
+ s : 'некалькі секунд',
+ m : relativeTimeWithPlural,
+ mm : relativeTimeWithPlural,
+ h : relativeTimeWithPlural,
+ hh : relativeTimeWithPlural,
+ d : 'дзень',
+ dd : relativeTimeWithPlural,
+ M : 'месяц',
+ MM : relativeTimeWithPlural,
+ y : 'год',
+ yy : relativeTimeWithPlural
+ },
+ meridiemParse: /ночы|раніцы|дня|вечара/,
+ isPM : function (input) {
+ return /^(дня|вечара)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ночы';
+ } else if (hour < 12) {
+ return 'раніцы';
+ } else if (hour < 17) {
+ return 'дня';
+ } else {
+ return 'вечара';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(і|ы|га)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ case 'w':
+ case 'W':
+ return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
+ case 'D':
+ return number + '-га';
+ default:
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return be;
+
+})));
+
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Bulgarian [bg]
+//! author : Krasen Borisov : https://github.com/kraz
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var bg = moment.defineLocale('bg', {
+ months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
+ monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
+ weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
+ weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
+ weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'D.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY H:mm',
+ LLLL : 'dddd, D MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[Днес в] LT',
+ nextDay : '[Утре в] LT',
+ nextWeek : 'dddd [в] LT',
+ lastDay : '[Вчера в] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ case 6:
+ return '[В изминалата] dddd [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[В изминалия] dddd [в] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'след %s',
+ past : 'преди %s',
+ s : 'няколко секунди',
+ ss : '%d секунди',
+ m : 'минута',
+ mm : '%d минути',
+ h : 'час',
+ hh : '%d часа',
+ d : 'ден',
+ dd : '%d дни',
+ M : 'месец',
+ MM : '%d месеца',
+ y : 'година',
+ yy : '%d години'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+ ordinal : function (number) {
+ var lastDigit = number % 10,
+ last2Digits = number % 100;
+ if (number === 0) {
+ return number + '-ев';
+ } else if (last2Digits === 0) {
+ return number + '-ен';
+ } else if (last2Digits > 10 && last2Digits < 20) {
+ return number + '-ти';
+ } else if (lastDigit === 1) {
+ return number + '-ви';
+ } else if (lastDigit === 2) {
+ return number + '-ри';
+ } else if (lastDigit === 7 || lastDigit === 8) {
+ return number + '-ми';
+ } else {
+ return number + '-ти';
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return bg;
+
+})));
+
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Bambara [bm]
+//! author : Estelle Comment : https://github.com/estellecomment
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+// Language contact person : Abdoufata Kane : https://github.com/abdoufata
+
+var bm = moment.defineLocale('bm', {
+ months : 'Zanwuyekalo_Fewuruyekalo_Marisikalo_Awirilikalo_Mɛkalo_Zuwɛnkalo_Zuluyekalo_Utikalo_Sɛtanburukalo_ɔkutɔburukalo_Nowanburukalo_Desanburukalo'.split('_'),
+ monthsShort : 'Zan_Few_Mar_Awi_Mɛ_Zuw_Zul_Uti_Sɛt_ɔku_Now_Des'.split('_'),
+ weekdays : 'Kari_Ntɛnɛn_Tarata_Araba_Alamisa_Juma_Sibiri'.split('_'),
+ weekdaysShort : 'Kar_Ntɛ_Tar_Ara_Ala_Jum_Sib'.split('_'),
+ weekdaysMin : 'Ka_Nt_Ta_Ar_Al_Ju_Si'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'MMMM [tile] D [san] YYYY',
+ LLL : 'MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
+ LLLL : 'dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm'
+ },
+ calendar : {
+ sameDay : '[Bi lɛrɛ] LT',
+ nextDay : '[Sini lɛrɛ] LT',
+ nextWeek : 'dddd [don lɛrɛ] LT',
+ lastDay : '[Kunu lɛrɛ] LT',
+ lastWeek : 'dddd [tɛmɛnen lɛrɛ] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s kɔnɔ',
+ past : 'a bɛ %s bɔ',
+ s : 'sanga dama dama',
+ ss : 'sekondi %d',
+ m : 'miniti kelen',
+ mm : 'miniti %d',
+ h : 'lɛrɛ kelen',
+ hh : 'lɛrɛ %d',
+ d : 'tile kelen',
+ dd : 'tile %d',
+ M : 'kalo kelen',
+ MM : 'kalo %d',
+ y : 'san kelen',
+ yy : 'san %d'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return bm;
+
+})));
+
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Bengali [bn]
+//! author : Kaushik Gandhi : https://github.com/kaushikgandhi
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '১',
+ '2': '২',
+ '3': '৩',
+ '4': '৪',
+ '5': '৫',
+ '6': '৬',
+ '7': '৭',
+ '8': '৮',
+ '9': '৯',
+ '0': '০'
+};
+var numberMap = {
+ '১': '1',
+ '২': '2',
+ '৩': '3',
+ '৪': '4',
+ '৫': '5',
+ '৬': '6',
+ '৭': '7',
+ '৮': '8',
+ '৯': '9',
+ '০': '0'
+};
+
+var bn = moment.defineLocale('bn', {
+ months : 'জানুয়ারী_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
+ monthsShort : 'জানু_ফেব_মার্চ_এপ্র_মে_জুন_জুল_আগ_সেপ্ট_অক্টো_নভে_ডিসে'.split('_'),
+ weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার'.split('_'),
+ weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি'.split('_'),
+ weekdaysMin : 'রবি_সোম_মঙ্গ_বুধ_বৃহঃ_শুক্র_শনি'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm সময়',
+ LTS : 'A h:mm:ss সময়',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm সময়',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm সময়'
+ },
+ calendar : {
+ sameDay : '[আজ] LT',
+ nextDay : '[আগামীকাল] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[গতকাল] LT',
+ lastWeek : '[গত] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s পরে',
+ past : '%s আগে',
+ s : 'কয়েক সেকেন্ড',
+ ss : '%d সেকেন্ড',
+ m : 'এক মিনিট',
+ mm : '%d মিনিট',
+ h : 'এক ঘন্টা',
+ hh : '%d ঘন্টা',
+ d : 'এক দিন',
+ dd : '%d দিন',
+ M : 'এক মাস',
+ MM : '%d মাস',
+ y : 'এক বছর',
+ yy : '%d বছর'
+ },
+ preparse: function (string) {
+ return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if ((meridiem === 'রাত' && hour >= 4) ||
+ (meridiem === 'দুপুর' && hour < 5) ||
+ meridiem === 'বিকাল') {
+ return hour + 12;
+ } else {
+ return hour;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'রাত';
+ } else if (hour < 10) {
+ return 'সকাল';
+ } else if (hour < 17) {
+ return 'দুপুর';
+ } else if (hour < 20) {
+ return 'বিকাল';
+ } else {
+ return 'রাত';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return bn;
+
+})));
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Tibetan [bo]
+//! author : Thupten N. Chakrishar : https://github.com/vajradog
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '༡',
+ '2': '༢',
+ '3': '༣',
+ '4': '༤',
+ '5': '༥',
+ '6': '༦',
+ '7': '༧',
+ '8': '༨',
+ '9': '༩',
+ '0': '༠'
+};
+var numberMap = {
+ '༡': '1',
+ '༢': '2',
+ '༣': '3',
+ '༤': '4',
+ '༥': '5',
+ '༦': '6',
+ '༧': '7',
+ '༨': '8',
+ '༩': '9',
+ '༠': '0'
+};
+
+var bo = moment.defineLocale('bo', {
+ months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+ monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+ weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
+ weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+ weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm',
+ LTS : 'A h:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm'
+ },
+ calendar : {
+ sameDay : '[དི་རིང] LT',
+ nextDay : '[སང་ཉིན] LT',
+ nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
+ lastDay : '[ཁ་སང] LT',
+ lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ལ་',
+ past : '%s སྔན་ལ',
+ s : 'ལམ་སང',
+ ss : '%d སྐར་ཆ།',
+ m : 'སྐར་མ་གཅིག',
+ mm : '%d སྐར་མ',
+ h : 'ཆུ་ཚོད་གཅིག',
+ hh : '%d ཆུ་ཚོད',
+ d : 'ཉིན་གཅིག',
+ dd : '%d ཉིན་',
+ M : 'ཟླ་བ་གཅིག',
+ MM : '%d ཟླ་བ',
+ y : 'ལོ་གཅིག',
+ yy : '%d ལོ'
+ },
+ preparse: function (string) {
+ return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if ((meridiem === 'མཚན་མོ' && hour >= 4) ||
+ (meridiem === 'ཉིན་གུང' && hour < 5) ||
+ meridiem === 'དགོང་དག') {
+ return hour + 12;
+ } else {
+ return hour;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'མཚན་མོ';
+ } else if (hour < 10) {
+ return 'ཞོགས་ཀས';
+ } else if (hour < 17) {
+ return 'ཉིན་གུང';
+ } else if (hour < 20) {
+ return 'དགོང་དག';
+ } else {
+ return 'མཚན་མོ';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return bo;
+
+})));
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Breton [br]
+//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function relativeTimeWithMutation(number, withoutSuffix, key) {
+ var format = {
+ 'mm': 'munutenn',
+ 'MM': 'miz',
+ 'dd': 'devezh'
+ };
+ return number + ' ' + mutation(format[key], number);
+}
+function specialMutationForYears(number) {
+ switch (lastNumber(number)) {
+ case 1:
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ return number + ' bloaz';
+ default:
+ return number + ' vloaz';
+ }
+}
+function lastNumber(number) {
+ if (number > 9) {
+ return lastNumber(number % 10);
+ }
+ return number;
+}
+function mutation(text, number) {
+ if (number === 2) {
+ return softMutation(text);
+ }
+ return text;
+}
+function softMutation(text) {
+ var mutationTable = {
+ 'm': 'v',
+ 'b': 'v',
+ 'd': 'z'
+ };
+ if (mutationTable[text.charAt(0)] === undefined) {
+ return text;
+ }
+ return mutationTable[text.charAt(0)] + text.substring(1);
+}
+
+var br = moment.defineLocale('br', {
+ months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
+ monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
+ weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
+ weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
+ weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'h[e]mm A',
+ LTS : 'h[e]mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D [a viz] MMMM YYYY',
+ LLL : 'D [a viz] MMMM YYYY h[e]mm A',
+ LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
+ },
+ calendar : {
+ sameDay : '[Hiziv da] LT',
+ nextDay : '[Warc\'hoazh da] LT',
+ nextWeek : 'dddd [da] LT',
+ lastDay : '[Dec\'h da] LT',
+ lastWeek : 'dddd [paset da] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'a-benn %s',
+ past : '%s \'zo',
+ s : 'un nebeud segondennoù',
+ ss : '%d eilenn',
+ m : 'ur vunutenn',
+ mm : relativeTimeWithMutation,
+ h : 'un eur',
+ hh : '%d eur',
+ d : 'un devezh',
+ dd : relativeTimeWithMutation,
+ M : 'ur miz',
+ MM : relativeTimeWithMutation,
+ y : 'ur bloaz',
+ yy : specialMutationForYears
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(añ|vet)/,
+ ordinal : function (number) {
+ var output = (number === 1) ? 'añ' : 'vet';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return br;
+
+})));
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Bosnian [bs]
+//! author : Nedim Cholich : https://github.com/frontyard
+//! based on (hr) translation by Bojan Marković
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function translate(number, withoutSuffix, key) {
+ var result = number + ' ';
+ switch (key) {
+ case 'ss':
+ if (number === 1) {
+ result += 'sekunda';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'sekunde';
+ } else {
+ result += 'sekundi';
+ }
+ return result;
+ case 'm':
+ return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+ case 'mm':
+ if (number === 1) {
+ result += 'minuta';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'minute';
+ } else {
+ result += 'minuta';
+ }
+ return result;
+ case 'h':
+ return withoutSuffix ? 'jedan sat' : 'jednog sata';
+ case 'hh':
+ if (number === 1) {
+ result += 'sat';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'sata';
+ } else {
+ result += 'sati';
+ }
+ return result;
+ case 'dd':
+ if (number === 1) {
+ result += 'dan';
+ } else {
+ result += 'dana';
+ }
+ return result;
+ case 'MM':
+ if (number === 1) {
+ result += 'mjesec';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'mjeseca';
+ } else {
+ result += 'mjeseci';
+ }
+ return result;
+ case 'yy':
+ if (number === 1) {
+ result += 'godina';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'godine';
+ } else {
+ result += 'godina';
+ }
+ return result;
+ }
+}
+
+var bs = moment.defineLocale('bs', {
+ months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
+ monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+ weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+ weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[danas u] LT',
+ nextDay : '[sutra u] LT',
+ nextWeek : function () {
+ switch (this.day()) {
+ case 0:
+ return '[u] [nedjelju] [u] LT';
+ case 3:
+ return '[u] [srijedu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[u] dddd [u] LT';
+ }
+ },
+ lastDay : '[jučer u] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ return '[prošlu] dddd [u] LT';
+ case 6:
+ return '[prošle] [subote] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[prošli] dddd [u] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'prije %s',
+ s : 'par sekundi',
+ ss : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : 'dan',
+ dd : translate,
+ M : 'mjesec',
+ MM : translate,
+ y : 'godinu',
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return bs;
+
+})));
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Catalan [ca]
+//! author : Juan G. Hurtado : https://github.com/juanghurtado
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ca = moment.defineLocale('ca', {
+ months : {
+ standalone: 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
+ format: 'de gener_de febrer_de març_d\'abril_de maig_de juny_de juliol_d\'agost_de setembre_d\'octubre_de novembre_de desembre'.split('_'),
+ isFormat: /D[oD]?(\s)+MMMM/
+ },
+ monthsShort : 'gen._febr._març_abr._maig_juny_jul._ag._set._oct._nov._des.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
+ weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
+ weekdaysMin : 'dg_dl_dt_dc_dj_dv_ds'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM [de] YYYY',
+ ll : 'D MMM YYYY',
+ LLL : 'D MMMM [de] YYYY [a les] H:mm',
+ lll : 'D MMM YYYY, H:mm',
+ LLLL : 'dddd D MMMM [de] YYYY [a les] H:mm',
+ llll : 'ddd D MMM YYYY, H:mm'
+ },
+ calendar : {
+ sameDay : function () {
+ return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ nextDay : function () {
+ return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ nextWeek : function () {
+ return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ lastDay : function () {
+ return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ lastWeek : function () {
+ return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'd\'aquí %s',
+ past : 'fa %s',
+ s : 'uns segons',
+ ss : '%d segons',
+ m : 'un minut',
+ mm : '%d minuts',
+ h : 'una hora',
+ hh : '%d hores',
+ d : 'un dia',
+ dd : '%d dies',
+ M : 'un mes',
+ MM : '%d mesos',
+ y : 'un any',
+ yy : '%d anys'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(r|n|t|è|a)/,
+ ordinal : function (number, period) {
+ var output = (number === 1) ? 'r' :
+ (number === 2) ? 'n' :
+ (number === 3) ? 'r' :
+ (number === 4) ? 't' : 'è';
+ if (period === 'w' || period === 'W') {
+ output = 'a';
+ }
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return ca;
+
+})));
+
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Czech [cs]
+//! author : petrbela : https://github.com/petrbela
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_');
+var monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_');
+function plural(n) {
+ return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
+}
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ switch (key) {
+ case 's': // a few seconds / in a few seconds / a few seconds ago
+ return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
+ case 'ss': // 9 seconds / in 9 seconds / 9 seconds ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'sekundy' : 'sekund');
+ } else {
+ return result + 'sekundami';
+ }
+ break;
+ case 'm': // a minute / in a minute / a minute ago
+ return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
+ case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'minuty' : 'minut');
+ } else {
+ return result + 'minutami';
+ }
+ break;
+ case 'h': // an hour / in an hour / an hour ago
+ return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+ case 'hh': // 9 hours / in 9 hours / 9 hours ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'hodiny' : 'hodin');
+ } else {
+ return result + 'hodinami';
+ }
+ break;
+ case 'd': // a day / in a day / a day ago
+ return (withoutSuffix || isFuture) ? 'den' : 'dnem';
+ case 'dd': // 9 days / in 9 days / 9 days ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'dny' : 'dní');
+ } else {
+ return result + 'dny';
+ }
+ break;
+ case 'M': // a month / in a month / a month ago
+ return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
+ case 'MM': // 9 months / in 9 months / 9 months ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'měsíce' : 'měsíců');
+ } else {
+ return result + 'měsíci';
+ }
+ break;
+ case 'y': // a year / in a year / a year ago
+ return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
+ case 'yy': // 9 years / in 9 years / 9 years ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'roky' : 'let');
+ } else {
+ return result + 'lety';
+ }
+ break;
+ }
+}
+
+var cs = moment.defineLocale('cs', {
+ months : months,
+ monthsShort : monthsShort,
+ monthsParse : (function (months, monthsShort) {
+ var i, _monthsParse = [];
+ for (i = 0; i < 12; i++) {
+ // use custom parser to solve problem with July (červenec)
+ _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
+ }
+ return _monthsParse;
+ }(months, monthsShort)),
+ shortMonthsParse : (function (monthsShort) {
+ var i, _shortMonthsParse = [];
+ for (i = 0; i < 12; i++) {
+ _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i');
+ }
+ return _shortMonthsParse;
+ }(monthsShort)),
+ longMonthsParse : (function (months) {
+ var i, _longMonthsParse = [];
+ for (i = 0; i < 12; i++) {
+ _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i');
+ }
+ return _longMonthsParse;
+ }(months)),
+ weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
+ weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'),
+ weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'),
+ longDateFormat : {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd D. MMMM YYYY H:mm',
+ l : 'D. M. YYYY'
+ },
+ calendar : {
+ sameDay: '[dnes v] LT',
+ nextDay: '[zítra v] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[v neděli v] LT';
+ case 1:
+ case 2:
+ return '[v] dddd [v] LT';
+ case 3:
+ return '[ve středu v] LT';
+ case 4:
+ return '[ve čtvrtek v] LT';
+ case 5:
+ return '[v pátek v] LT';
+ case 6:
+ return '[v sobotu v] LT';
+ }
+ },
+ lastDay: '[včera v] LT',
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[minulou neděli v] LT';
+ case 1:
+ case 2:
+ return '[minulé] dddd [v] LT';
+ case 3:
+ return '[minulou středu v] LT';
+ case 4:
+ case 5:
+ return '[minulý] dddd [v] LT';
+ case 6:
+ return '[minulou sobotu v] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'před %s',
+ s : translate,
+ ss : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return cs;
+
+})));
+
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Chuvash [cv]
+//! author : Anatoly Mironov : https://github.com/mirontoli
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var cv = moment.defineLocale('cv', {
+ months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'),
+ monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'),
+ weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'),
+ weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'),
+ weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD-MM-YYYY',
+ LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
+ LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
+ LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm'
+ },
+ calendar : {
+ sameDay: '[Паян] LT [сехетре]',
+ nextDay: '[Ыран] LT [сехетре]',
+ lastDay: '[Ӗнер] LT [сехетре]',
+ nextWeek: '[Ҫитес] dddd LT [сехетре]',
+ lastWeek: '[Иртнӗ] dddd LT [сехетре]',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : function (output) {
+ var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран';
+ return output + affix;
+ },
+ past : '%s каялла',
+ s : 'пӗр-ик ҫеккунт',
+ ss : '%d ҫеккунт',
+ m : 'пӗр минут',
+ mm : '%d минут',
+ h : 'пӗр сехет',
+ hh : '%d сехет',
+ d : 'пӗр кун',
+ dd : '%d кун',
+ M : 'пӗр уйӑх',
+ MM : '%d уйӑх',
+ y : 'пӗр ҫул',
+ yy : '%d ҫул'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-мӗш/,
+ ordinal : '%d-мӗш',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return cv;
+
+})));
+
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Welsh [cy]
+//! author : Robert Allen : https://github.com/robgallen
+//! author : https://github.com/ryangreaves
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var cy = moment.defineLocale('cy', {
+ months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'),
+ monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'),
+ weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'),
+ weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'),
+ weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'),
+ weekdaysParseExact : true,
+ // time formats are the same as en-gb
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY HH:mm',
+ LLLL: 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar: {
+ sameDay: '[Heddiw am] LT',
+ nextDay: '[Yfory am] LT',
+ nextWeek: 'dddd [am] LT',
+ lastDay: '[Ddoe am] LT',
+ lastWeek: 'dddd [diwethaf am] LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: 'mewn %s',
+ past: '%s yn ôl',
+ s: 'ychydig eiliadau',
+ ss: '%d eiliad',
+ m: 'munud',
+ mm: '%d munud',
+ h: 'awr',
+ hh: '%d awr',
+ d: 'diwrnod',
+ dd: '%d diwrnod',
+ M: 'mis',
+ MM: '%d mis',
+ y: 'blwyddyn',
+ yy: '%d flynedd'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,
+ // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
+ ordinal: function (number) {
+ var b = number,
+ output = '',
+ lookup = [
+ '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
+ 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
+ ];
+ if (b > 20) {
+ if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
+ output = 'fed'; // not 30ain, 70ain or 90ain
+ } else {
+ output = 'ain';
+ }
+ } else if (b > 0) {
+ output = lookup[b];
+ }
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return cy;
+
+})));
+
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Danish [da]
+//! author : Ulrik Nielsen : https://github.com/mrbase
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var da = moment.defineLocale('da', {
+ months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
+ weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
+ weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'),
+ weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY HH:mm',
+ LLLL : 'dddd [d.] D. MMMM YYYY [kl.] HH:mm'
+ },
+ calendar : {
+ sameDay : '[i dag kl.] LT',
+ nextDay : '[i morgen kl.] LT',
+ nextWeek : 'på dddd [kl.] LT',
+ lastDay : '[i går kl.] LT',
+ lastWeek : '[i] dddd[s kl.] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'om %s',
+ past : '%s siden',
+ s : 'få sekunder',
+ ss : '%d sekunder',
+ m : 'et minut',
+ mm : '%d minutter',
+ h : 'en time',
+ hh : '%d timer',
+ d : 'en dag',
+ dd : '%d dage',
+ M : 'en måned',
+ MM : '%d måneder',
+ y : 'et år',
+ yy : '%d år'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return da;
+
+})));
+
+
+/***/ }),
+/* 26 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : German [de]
+//! author : lluchs : https://github.com/lluchs
+//! author: Menelion Elensúle: https://github.com/Oire
+//! author : Mikolaj Dadela : https://github.com/mik01aj
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 'm': ['eine Minute', 'einer Minute'],
+ 'h': ['eine Stunde', 'einer Stunde'],
+ 'd': ['ein Tag', 'einem Tag'],
+ 'dd': [number + ' Tage', number + ' Tagen'],
+ 'M': ['ein Monat', 'einem Monat'],
+ 'MM': [number + ' Monate', number + ' Monaten'],
+ 'y': ['ein Jahr', 'einem Jahr'],
+ 'yy': [number + ' Jahre', number + ' Jahren']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+
+var de = moment.defineLocale('de', {
+ months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+ monthsShort : 'Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+ weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
+ weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY HH:mm',
+ LLLL : 'dddd, D. MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[heute um] LT [Uhr]',
+ sameElse: 'L',
+ nextDay: '[morgen um] LT [Uhr]',
+ nextWeek: 'dddd [um] LT [Uhr]',
+ lastDay: '[gestern um] LT [Uhr]',
+ lastWeek: '[letzten] dddd [um] LT [Uhr]'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : 'vor %s',
+ s : 'ein paar Sekunden',
+ ss : '%d Sekunden',
+ m : processRelativeTime,
+ mm : '%d Minuten',
+ h : processRelativeTime,
+ hh : '%d Stunden',
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return de;
+
+})));
+
+
+/***/ }),
+/* 27 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : German (Austria) [de-at]
+//! author : lluchs : https://github.com/lluchs
+//! author: Menelion Elensúle: https://github.com/Oire
+//! author : Martin Groller : https://github.com/MadMG
+//! author : Mikolaj Dadela : https://github.com/mik01aj
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 'm': ['eine Minute', 'einer Minute'],
+ 'h': ['eine Stunde', 'einer Stunde'],
+ 'd': ['ein Tag', 'einem Tag'],
+ 'dd': [number + ' Tage', number + ' Tagen'],
+ 'M': ['ein Monat', 'einem Monat'],
+ 'MM': [number + ' Monate', number + ' Monaten'],
+ 'y': ['ein Jahr', 'einem Jahr'],
+ 'yy': [number + ' Jahre', number + ' Jahren']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+
+var deAt = moment.defineLocale('de-at', {
+ months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+ monthsShort : 'Jän._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+ weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
+ weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY HH:mm',
+ LLLL : 'dddd, D. MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[heute um] LT [Uhr]',
+ sameElse: 'L',
+ nextDay: '[morgen um] LT [Uhr]',
+ nextWeek: 'dddd [um] LT [Uhr]',
+ lastDay: '[gestern um] LT [Uhr]',
+ lastWeek: '[letzten] dddd [um] LT [Uhr]'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : 'vor %s',
+ s : 'ein paar Sekunden',
+ ss : '%d Sekunden',
+ m : processRelativeTime,
+ mm : '%d Minuten',
+ h : processRelativeTime,
+ hh : '%d Stunden',
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return deAt;
+
+})));
+
+
+/***/ }),
+/* 28 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : German (Switzerland) [de-ch]
+//! author : sschueller : https://github.com/sschueller
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+// based on: https://www.bk.admin.ch/dokumentation/sprachen/04915/05016/index.html?lang=de#
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 'm': ['eine Minute', 'einer Minute'],
+ 'h': ['eine Stunde', 'einer Stunde'],
+ 'd': ['ein Tag', 'einem Tag'],
+ 'dd': [number + ' Tage', number + ' Tagen'],
+ 'M': ['ein Monat', 'einem Monat'],
+ 'MM': [number + ' Monate', number + ' Monaten'],
+ 'y': ['ein Jahr', 'einem Jahr'],
+ 'yy': [number + ' Jahre', number + ' Jahren']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+
+var deCh = moment.defineLocale('de-ch', {
+ months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+ monthsShort : 'Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+ weekdaysShort : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+ weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY HH:mm',
+ LLLL : 'dddd, D. MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[heute um] LT [Uhr]',
+ sameElse: 'L',
+ nextDay: '[morgen um] LT [Uhr]',
+ nextWeek: 'dddd [um] LT [Uhr]',
+ lastDay: '[gestern um] LT [Uhr]',
+ lastWeek: '[letzten] dddd [um] LT [Uhr]'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : 'vor %s',
+ s : 'ein paar Sekunden',
+ ss : '%d Sekunden',
+ m : processRelativeTime,
+ mm : '%d Minuten',
+ h : processRelativeTime,
+ hh : '%d Stunden',
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return deCh;
+
+})));
+
+
+/***/ }),
+/* 29 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Maldivian [dv]
+//! author : Jawish Hameed : https://github.com/jawish
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = [
+ 'ޖެނުއަރީ',
+ 'ފެބްރުއަރީ',
+ 'މާރިޗު',
+ 'އޭޕްރީލު',
+ 'މޭ',
+ 'ޖޫން',
+ 'ޖުލައި',
+ 'އޯގަސްޓު',
+ 'ސެޕްޓެމްބަރު',
+ 'އޮކްޓޯބަރު',
+ 'ނޮވެމްބަރު',
+ 'ޑިސެމްބަރު'
+];
+var weekdays = [
+ 'އާދިއްތަ',
+ 'ހޯމަ',
+ 'އަންގާރަ',
+ 'ބުދަ',
+ 'ބުރާސްފަތި',
+ 'ހުކުރު',
+ 'ހޮނިހިރު'
+];
+
+var dv = moment.defineLocale('dv', {
+ months : months,
+ monthsShort : months,
+ weekdays : weekdays,
+ weekdaysShort : weekdays,
+ weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'),
+ longDateFormat : {
+
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'D/M/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /މކ|މފ/,
+ isPM : function (input) {
+ return 'މފ' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'މކ';
+ } else {
+ return 'މފ';
+ }
+ },
+ calendar : {
+ sameDay : '[މިއަދު] LT',
+ nextDay : '[މާދަމާ] LT',
+ nextWeek : 'dddd LT',
+ lastDay : '[އިއްޔެ] LT',
+ lastWeek : '[ފާއިތުވި] dddd LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'ތެރޭގައި %s',
+ past : 'ކުރިން %s',
+ s : 'ސިކުންތުކޮޅެއް',
+ ss : 'd% ސިކުންތު',
+ m : 'މިނިޓެއް',
+ mm : 'މިނިޓު %d',
+ h : 'ގަޑިއިރެއް',
+ hh : 'ގަޑިއިރު %d',
+ d : 'ދުވަހެއް',
+ dd : 'ދުވަސް %d',
+ M : 'މަހެއް',
+ MM : 'މަސް %d',
+ y : 'އަހަރެއް',
+ yy : 'އަހަރު %d'
+ },
+ preparse: function (string) {
+ return string.replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/,/g, '،');
+ },
+ week : {
+ dow : 7, // Sunday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return dv;
+
+})));
+
+
+/***/ }),
+/* 30 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Greek [el]
+//! author : Aggelos Karalias : https://github.com/mehiel
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+function isFunction(input) {
+ return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
+}
+
+
+var el = moment.defineLocale('el', {
+ monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'),
+ monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'),
+ months : function (momentToFormat, format) {
+ if (!momentToFormat) {
+ return this._monthsNominativeEl;
+ } else if (typeof format === 'string' && /D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM'
+ return this._monthsGenitiveEl[momentToFormat.month()];
+ } else {
+ return this._monthsNominativeEl[momentToFormat.month()];
+ }
+ },
+ monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'),
+ weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'),
+ weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'),
+ weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'),
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'μμ' : 'ΜΜ';
+ } else {
+ return isLower ? 'πμ' : 'ΠΜ';
+ }
+ },
+ isPM : function (input) {
+ return ((input + '').toLowerCase()[0] === 'μ');
+ },
+ meridiemParse : /[ΠΜ]\.?Μ?\.?/i,
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendarEl : {
+ sameDay : '[Σήμερα {}] LT',
+ nextDay : '[Αύριο {}] LT',
+ nextWeek : 'dddd [{}] LT',
+ lastDay : '[Χθες {}] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 6:
+ return '[το προηγούμενο] dddd [{}] LT';
+ default:
+ return '[την προηγούμενη] dddd [{}] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ calendar : function (key, mom) {
+ var output = this._calendarEl[key],
+ hours = mom && mom.hours();
+ if (isFunction(output)) {
+ output = output.apply(mom);
+ }
+ return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις'));
+ },
+ relativeTime : {
+ future : 'σε %s',
+ past : '%s πριν',
+ s : 'λίγα δευτερόλεπτα',
+ ss : '%d δευτερόλεπτα',
+ m : 'ένα λεπτό',
+ mm : '%d λεπτά',
+ h : 'μία ώρα',
+ hh : '%d ώρες',
+ d : 'μία μέρα',
+ dd : '%d μέρες',
+ M : 'ένας μήνας',
+ MM : '%d μήνες',
+ y : 'ένας χρόνος',
+ yy : '%d χρόνια'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}η/,
+ ordinal: '%dη',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4st is the first week of the year.
+ }
+});
+
+return el;
+
+})));
+
+
+/***/ }),
+/* 31 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : English (Australia) [en-au]
+//! author : Jared Morse : https://github.com/jarcoal
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var enAu = moment.defineLocale('en-au', {
+ months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+ weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+ weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ ss : '%d seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return enAu;
+
+})));
+
+
+/***/ }),
+/* 32 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : English (Canada) [en-ca]
+//! author : Jonathan Abourbih : https://github.com/jonbca
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var enCa = moment.defineLocale('en-ca', {
+ months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+ weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+ weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'YYYY-MM-DD',
+ LL : 'MMMM D, YYYY',
+ LLL : 'MMMM D, YYYY h:mm A',
+ LLLL : 'dddd, MMMM D, YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ ss : '%d seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ }
+});
+
+return enCa;
+
+})));
+
+
+/***/ }),
+/* 33 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : English (United Kingdom) [en-gb]
+//! author : Chris Gedrim : https://github.com/chrisgedrim
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var enGb = moment.defineLocale('en-gb', {
+ months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+ weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+ weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ ss : '%d seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return enGb;
+
+})));
+
+
+/***/ }),
+/* 34 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : English (Ireland) [en-ie]
+//! author : Chris Cartlidge : https://github.com/chriscartlidge
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var enIe = moment.defineLocale('en-ie', {
+ months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+ weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+ weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD-MM-YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ ss : '%d seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return enIe;
+
+})));
+
+
+/***/ }),
+/* 35 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : English (New Zealand) [en-nz]
+//! author : Luke McGregor : https://github.com/lukemcgregor
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var enNz = moment.defineLocale('en-nz', {
+ months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+ weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+ weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ ss : '%d seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return enNz;
+
+})));
+
+
+/***/ }),
+/* 36 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Esperanto [eo]
+//! author : Colin Dean : https://github.com/colindean
+//! author : Mia Nordentoft Imperatori : https://github.com/miestasmia
+//! comment : miestasmia corrected the translation by colindean
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var eo = moment.defineLocale('eo', {
+ months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'),
+ weekdays : 'dimanĉo_lundo_mardo_merkredo_ĵaŭdo_vendredo_sabato'.split('_'),
+ weekdaysShort : 'dim_lun_mard_merk_ĵaŭ_ven_sab'.split('_'),
+ weekdaysMin : 'di_lu_ma_me_ĵa_ve_sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'D[-a de] MMMM, YYYY',
+ LLL : 'D[-a de] MMMM, YYYY HH:mm',
+ LLLL : 'dddd, [la] D[-a de] MMMM, YYYY HH:mm'
+ },
+ meridiemParse: /[ap]\.t\.m/i,
+ isPM: function (input) {
+ return input.charAt(0).toLowerCase() === 'p';
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'p.t.m.' : 'P.T.M.';
+ } else {
+ return isLower ? 'a.t.m.' : 'A.T.M.';
+ }
+ },
+ calendar : {
+ sameDay : '[Hodiaŭ je] LT',
+ nextDay : '[Morgaŭ je] LT',
+ nextWeek : 'dddd [je] LT',
+ lastDay : '[Hieraŭ je] LT',
+ lastWeek : '[pasinta] dddd [je] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'post %s',
+ past : 'antaŭ %s',
+ s : 'sekundoj',
+ ss : '%d sekundoj',
+ m : 'minuto',
+ mm : '%d minutoj',
+ h : 'horo',
+ hh : '%d horoj',
+ d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo
+ dd : '%d tagoj',
+ M : 'monato',
+ MM : '%d monatoj',
+ y : 'jaro',
+ yy : '%d jaroj'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}a/,
+ ordinal : '%da',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return eo;
+
+})));
+
+
+/***/ }),
+/* 37 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Spanish [es]
+//! author : Julio Napurí : https://github.com/julionc
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
+var monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
+
+var monthsParse = [/^ene/i, /^feb/i, /^mar/i, /^abr/i, /^may/i, /^jun/i, /^jul/i, /^ago/i, /^sep/i, /^oct/i, /^nov/i, /^dic/i];
+var monthsRegex = /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;
+
+var es = moment.defineLocale('es', {
+ months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortDot;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShort[m.month()];
+ } else {
+ return monthsShortDot[m.month()];
+ }
+ },
+ monthsRegex : monthsRegex,
+ monthsShortRegex : monthsRegex,
+ monthsStrictRegex : /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,
+ monthsShortStrictRegex : /^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,
+ monthsParse : monthsParse,
+ longMonthsParse : monthsParse,
+ shortMonthsParse : monthsParse,
+ weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
+ weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
+ weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY H:mm',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
+ },
+ calendar : {
+ sameDay : function () {
+ return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ nextDay : function () {
+ return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ nextWeek : function () {
+ return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ lastDay : function () {
+ return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ lastWeek : function () {
+ return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'en %s',
+ past : 'hace %s',
+ s : 'unos segundos',
+ ss : '%d segundos',
+ m : 'un minuto',
+ mm : '%d minutos',
+ h : 'una hora',
+ hh : '%d horas',
+ d : 'un día',
+ dd : '%d días',
+ M : 'un mes',
+ MM : '%d meses',
+ y : 'un año',
+ yy : '%d años'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal : '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return es;
+
+})));
+
+
+/***/ }),
+/* 38 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Spanish (Dominican Republic) [es-do]
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
+var monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
+
+var monthsParse = [/^ene/i, /^feb/i, /^mar/i, /^abr/i, /^may/i, /^jun/i, /^jul/i, /^ago/i, /^sep/i, /^oct/i, /^nov/i, /^dic/i];
+var monthsRegex = /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;
+
+var esDo = moment.defineLocale('es-do', {
+ months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortDot;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShort[m.month()];
+ } else {
+ return monthsShortDot[m.month()];
+ }
+ },
+ monthsRegex: monthsRegex,
+ monthsShortRegex: monthsRegex,
+ monthsStrictRegex: /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,
+ monthsShortStrictRegex: /^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,
+ monthsParse: monthsParse,
+ longMonthsParse: monthsParse,
+ shortMonthsParse: monthsParse,
+ weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
+ weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
+ weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY h:mm A',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : function () {
+ return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ nextDay : function () {
+ return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ nextWeek : function () {
+ return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ lastDay : function () {
+ return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ lastWeek : function () {
+ return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'en %s',
+ past : 'hace %s',
+ s : 'unos segundos',
+ ss : '%d segundos',
+ m : 'un minuto',
+ mm : '%d minutos',
+ h : 'una hora',
+ hh : '%d horas',
+ d : 'un día',
+ dd : '%d días',
+ M : 'un mes',
+ MM : '%d meses',
+ y : 'un año',
+ yy : '%d años'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal : '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return esDo;
+
+})));
+
+
+/***/ }),
+/* 39 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Spanish (United States) [es-us]
+//! author : bustta : https://github.com/bustta
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
+var monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
+
+var esUs = moment.defineLocale('es-us', {
+ months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortDot;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShort[m.month()];
+ } else {
+ return monthsShortDot[m.month()];
+ }
+ },
+ monthsParseExact : true,
+ weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
+ weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
+ weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'MM/DD/YYYY',
+ LL : 'MMMM [de] D [de] YYYY',
+ LLL : 'MMMM [de] D [de] YYYY h:mm A',
+ LLLL : 'dddd, MMMM [de] D [de] YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : function () {
+ return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ nextDay : function () {
+ return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ nextWeek : function () {
+ return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ lastDay : function () {
+ return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ lastWeek : function () {
+ return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'en %s',
+ past : 'hace %s',
+ s : 'unos segundos',
+ ss : '%d segundos',
+ m : 'un minuto',
+ mm : '%d minutos',
+ h : 'una hora',
+ hh : '%d horas',
+ d : 'un día',
+ dd : '%d días',
+ M : 'un mes',
+ MM : '%d meses',
+ y : 'un año',
+ yy : '%d años'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal : '%dº',
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return esUs;
+
+})));
+
+
+/***/ }),
+/* 40 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Estonian [et]
+//! author : Henry Kehlmann : https://github.com/madhenry
+//! improvements : Illimar Tambek : https://github.com/ragulka
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
+ 'ss': [number + 'sekundi', number + 'sekundit'],
+ 'm' : ['ühe minuti', 'üks minut'],
+ 'mm': [number + ' minuti', number + ' minutit'],
+ 'h' : ['ühe tunni', 'tund aega', 'üks tund'],
+ 'hh': [number + ' tunni', number + ' tundi'],
+ 'd' : ['ühe päeva', 'üks päev'],
+ 'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
+ 'MM': [number + ' kuu', number + ' kuud'],
+ 'y' : ['ühe aasta', 'aasta', 'üks aasta'],
+ 'yy': [number + ' aasta', number + ' aastat']
+ };
+ if (withoutSuffix) {
+ return format[key][2] ? format[key][2] : format[key][1];
+ }
+ return isFuture ? format[key][0] : format[key][1];
+}
+
+var et = moment.defineLocale('et', {
+ months : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'),
+ monthsShort : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'),
+ weekdays : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'),
+ weekdaysShort : 'P_E_T_K_N_R_L'.split('_'),
+ weekdaysMin : 'P_E_T_K_N_R_L'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[Täna,] LT',
+ nextDay : '[Homme,] LT',
+ nextWeek : '[Järgmine] dddd LT',
+ lastDay : '[Eile,] LT',
+ lastWeek : '[Eelmine] dddd LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s pärast',
+ past : '%s tagasi',
+ s : processRelativeTime,
+ ss : processRelativeTime,
+ m : processRelativeTime,
+ mm : processRelativeTime,
+ h : processRelativeTime,
+ hh : processRelativeTime,
+ d : processRelativeTime,
+ dd : '%d päeva',
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return et;
+
+})));
+
+
+/***/ }),
+/* 41 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Basque [eu]
+//! author : Eneko Illarramendi : https://github.com/eillarra
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var eu = moment.defineLocale('eu', {
+ months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'),
+ monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'),
+ weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'),
+ weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'YYYY[ko] MMMM[ren] D[a]',
+ LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm',
+ LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
+ l : 'YYYY-M-D',
+ ll : 'YYYY[ko] MMM D[a]',
+ lll : 'YYYY[ko] MMM D[a] HH:mm',
+ llll : 'ddd, YYYY[ko] MMM D[a] HH:mm'
+ },
+ calendar : {
+ sameDay : '[gaur] LT[etan]',
+ nextDay : '[bihar] LT[etan]',
+ nextWeek : 'dddd LT[etan]',
+ lastDay : '[atzo] LT[etan]',
+ lastWeek : '[aurreko] dddd LT[etan]',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s barru',
+ past : 'duela %s',
+ s : 'segundo batzuk',
+ ss : '%d segundo',
+ m : 'minutu bat',
+ mm : '%d minutu',
+ h : 'ordu bat',
+ hh : '%d ordu',
+ d : 'egun bat',
+ dd : '%d egun',
+ M : 'hilabete bat',
+ MM : '%d hilabete',
+ y : 'urte bat',
+ yy : '%d urte'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return eu;
+
+})));
+
+
+/***/ }),
+/* 42 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Persian [fa]
+//! author : Ebrahim Byagowi : https://github.com/ebraminio
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '۱',
+ '2': '۲',
+ '3': '۳',
+ '4': '۴',
+ '5': '۵',
+ '6': '۶',
+ '7': '۷',
+ '8': '۸',
+ '9': '۹',
+ '0': '۰'
+};
+var numberMap = {
+ '۱': '1',
+ '۲': '2',
+ '۳': '3',
+ '۴': '4',
+ '۵': '5',
+ '۶': '6',
+ '۷': '7',
+ '۸': '8',
+ '۹': '9',
+ '۰': '0'
+};
+
+var fa = moment.defineLocale('fa', {
+ months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+ monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+ weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+ weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+ weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /قبل از ظهر|بعد از ظهر/,
+ isPM: function (input) {
+ return /بعد از ظهر/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'قبل از ظهر';
+ } else {
+ return 'بعد از ظهر';
+ }
+ },
+ calendar : {
+ sameDay : '[امروز ساعت] LT',
+ nextDay : '[فردا ساعت] LT',
+ nextWeek : 'dddd [ساعت] LT',
+ lastDay : '[دیروز ساعت] LT',
+ lastWeek : 'dddd [پیش] [ساعت] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'در %s',
+ past : '%s پیش',
+ s : 'چند ثانیه',
+ ss : 'ثانیه d%',
+ m : 'یک دقیقه',
+ mm : '%d دقیقه',
+ h : 'یک ساعت',
+ hh : '%d ساعت',
+ d : 'یک روز',
+ dd : '%d روز',
+ M : 'یک ماه',
+ MM : '%d ماه',
+ y : 'یک سال',
+ yy : '%d سال'
+ },
+ preparse: function (string) {
+ return string.replace(/[۰-۹]/g, function (match) {
+ return numberMap[match];
+ }).replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ }).replace(/,/g, '،');
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}م/,
+ ordinal : '%dم',
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return fa;
+
+})));
+
+
+/***/ }),
+/* 43 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Finnish [fi]
+//! author : Tarmo Aidantausta : https://github.com/bleadof
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' ');
+var numbersFuture = [
+ 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
+ numbersPast[7], numbersPast[8], numbersPast[9]
+ ];
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = '';
+ switch (key) {
+ case 's':
+ return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
+ case 'ss':
+ return isFuture ? 'sekunnin' : 'sekuntia';
+ case 'm':
+ return isFuture ? 'minuutin' : 'minuutti';
+ case 'mm':
+ result = isFuture ? 'minuutin' : 'minuuttia';
+ break;
+ case 'h':
+ return isFuture ? 'tunnin' : 'tunti';
+ case 'hh':
+ result = isFuture ? 'tunnin' : 'tuntia';
+ break;
+ case 'd':
+ return isFuture ? 'päivän' : 'päivä';
+ case 'dd':
+ result = isFuture ? 'päivän' : 'päivää';
+ break;
+ case 'M':
+ return isFuture ? 'kuukauden' : 'kuukausi';
+ case 'MM':
+ result = isFuture ? 'kuukauden' : 'kuukautta';
+ break;
+ case 'y':
+ return isFuture ? 'vuoden' : 'vuosi';
+ case 'yy':
+ result = isFuture ? 'vuoden' : 'vuotta';
+ break;
+ }
+ result = verbalNumber(number, isFuture) + ' ' + result;
+ return result;
+}
+function verbalNumber(number, isFuture) {
+ return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number;
+}
+
+var fi = moment.defineLocale('fi', {
+ months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'),
+ monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'),
+ weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'),
+ weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'),
+ weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD.MM.YYYY',
+ LL : 'Do MMMM[ta] YYYY',
+ LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm',
+ LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm',
+ l : 'D.M.YYYY',
+ ll : 'Do MMM YYYY',
+ lll : 'Do MMM YYYY, [klo] HH.mm',
+ llll : 'ddd, Do MMM YYYY, [klo] HH.mm'
+ },
+ calendar : {
+ sameDay : '[tänään] [klo] LT',
+ nextDay : '[huomenna] [klo] LT',
+ nextWeek : 'dddd [klo] LT',
+ lastDay : '[eilen] [klo] LT',
+ lastWeek : '[viime] dddd[na] [klo] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s päästä',
+ past : '%s sitten',
+ s : translate,
+ ss : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return fi;
+
+})));
+
+
+/***/ }),
+/* 44 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Faroese [fo]
+//! author : Ragnar Johannesen : https://github.com/ragnar123
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var fo = moment.defineLocale('fo', {
+ months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+ weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'),
+ weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'),
+ weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D. MMMM, YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Í dag kl.] LT',
+ nextDay : '[Í morgin kl.] LT',
+ nextWeek : 'dddd [kl.] LT',
+ lastDay : '[Í gjár kl.] LT',
+ lastWeek : '[síðstu] dddd [kl] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'um %s',
+ past : '%s síðani',
+ s : 'fá sekund',
+ ss : '%d sekundir',
+ m : 'ein minutt',
+ mm : '%d minuttir',
+ h : 'ein tími',
+ hh : '%d tímar',
+ d : 'ein dagur',
+ dd : '%d dagar',
+ M : 'ein mánaði',
+ MM : '%d mánaðir',
+ y : 'eitt ár',
+ yy : '%d ár'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return fo;
+
+})));
+
+
+/***/ }),
+/* 45 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : French [fr]
+//! author : John Fischer : https://github.com/jfroffice
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var fr = moment.defineLocale('fr', {
+ months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+ monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+ weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+ weekdaysMin : 'di_lu_ma_me_je_ve_sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Aujourd’hui à] LT',
+ nextDay : '[Demain à] LT',
+ nextWeek : 'dddd [à] LT',
+ lastDay : '[Hier à] LT',
+ lastWeek : 'dddd [dernier à] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dans %s',
+ past : 'il y a %s',
+ s : 'quelques secondes',
+ ss : '%d secondes',
+ m : 'une minute',
+ mm : '%d minutes',
+ h : 'une heure',
+ hh : '%d heures',
+ d : 'un jour',
+ dd : '%d jours',
+ M : 'un mois',
+ MM : '%d mois',
+ y : 'un an',
+ yy : '%d ans'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(er|)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ // TODO: Return 'e' when day of month > 1. Move this case inside
+ // block for masculine words below.
+ // See https://github.com/moment/moment/issues/3375
+ case 'D':
+ return number + (number === 1 ? 'er' : '');
+
+ // Words with masculine grammatical gender: mois, trimestre, jour
+ default:
+ case 'M':
+ case 'Q':
+ case 'DDD':
+ case 'd':
+ return number + (number === 1 ? 'er' : 'e');
+
+ // Words with feminine grammatical gender: semaine
+ case 'w':
+ case 'W':
+ return number + (number === 1 ? 're' : 'e');
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return fr;
+
+})));
+
+
+/***/ }),
+/* 46 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : French (Canada) [fr-ca]
+//! author : Jonathan Abourbih : https://github.com/jonbca
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var frCa = moment.defineLocale('fr-ca', {
+ months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+ monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+ weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+ weekdaysMin : 'di_lu_ma_me_je_ve_sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Aujourd’hui à] LT',
+ nextDay : '[Demain à] LT',
+ nextWeek : 'dddd [à] LT',
+ lastDay : '[Hier à] LT',
+ lastWeek : 'dddd [dernier à] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dans %s',
+ past : 'il y a %s',
+ s : 'quelques secondes',
+ ss : '%d secondes',
+ m : 'une minute',
+ mm : '%d minutes',
+ h : 'une heure',
+ hh : '%d heures',
+ d : 'un jour',
+ dd : '%d jours',
+ M : 'un mois',
+ MM : '%d mois',
+ y : 'un an',
+ yy : '%d ans'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(er|e)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ // Words with masculine grammatical gender: mois, trimestre, jour
+ default:
+ case 'M':
+ case 'Q':
+ case 'D':
+ case 'DDD':
+ case 'd':
+ return number + (number === 1 ? 'er' : 'e');
+
+ // Words with feminine grammatical gender: semaine
+ case 'w':
+ case 'W':
+ return number + (number === 1 ? 're' : 'e');
+ }
+ }
+});
+
+return frCa;
+
+})));
+
+
+/***/ }),
+/* 47 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : French (Switzerland) [fr-ch]
+//! author : Gaspard Bucher : https://github.com/gaspard
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var frCh = moment.defineLocale('fr-ch', {
+ months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+ monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+ weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+ weekdaysMin : 'di_lu_ma_me_je_ve_sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Aujourd’hui à] LT',
+ nextDay : '[Demain à] LT',
+ nextWeek : 'dddd [à] LT',
+ lastDay : '[Hier à] LT',
+ lastWeek : 'dddd [dernier à] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dans %s',
+ past : 'il y a %s',
+ s : 'quelques secondes',
+ ss : '%d secondes',
+ m : 'une minute',
+ mm : '%d minutes',
+ h : 'une heure',
+ hh : '%d heures',
+ d : 'un jour',
+ dd : '%d jours',
+ M : 'un mois',
+ MM : '%d mois',
+ y : 'un an',
+ yy : '%d ans'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(er|e)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ // Words with masculine grammatical gender: mois, trimestre, jour
+ default:
+ case 'M':
+ case 'Q':
+ case 'D':
+ case 'DDD':
+ case 'd':
+ return number + (number === 1 ? 'er' : 'e');
+
+ // Words with feminine grammatical gender: semaine
+ case 'w':
+ case 'W':
+ return number + (number === 1 ? 're' : 'e');
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return frCh;
+
+})));
+
+
+/***/ }),
+/* 48 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Frisian [fy]
+//! author : Robin van der Vliet : https://github.com/robin0van0der0v
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_');
+var monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_');
+
+var fy = moment.defineLocale('fy', {
+ months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortWithDots;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShortWithoutDots[m.month()];
+ } else {
+ return monthsShortWithDots[m.month()];
+ }
+ },
+ monthsParseExact : true,
+ weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'),
+ weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'),
+ weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD-MM-YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[hjoed om] LT',
+ nextDay: '[moarn om] LT',
+ nextWeek: 'dddd [om] LT',
+ lastDay: '[juster om] LT',
+ lastWeek: '[ôfrûne] dddd [om] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'oer %s',
+ past : '%s lyn',
+ s : 'in pear sekonden',
+ ss : '%d sekonden',
+ m : 'ien minút',
+ mm : '%d minuten',
+ h : 'ien oere',
+ hh : '%d oeren',
+ d : 'ien dei',
+ dd : '%d dagen',
+ M : 'ien moanne',
+ MM : '%d moannen',
+ y : 'ien jier',
+ yy : '%d jierren'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
+ ordinal : function (number) {
+ return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return fy;
+
+})));
+
+
+/***/ }),
+/* 49 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Scottish Gaelic [gd]
+//! author : Jon Ashdown : https://github.com/jonashdown
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = [
+ 'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'
+];
+
+var monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'];
+
+var weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'];
+
+var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'];
+
+var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'];
+
+var gd = moment.defineLocale('gd', {
+ months : months,
+ monthsShort : monthsShort,
+ monthsParseExact : true,
+ weekdays : weekdays,
+ weekdaysShort : weekdaysShort,
+ weekdaysMin : weekdaysMin,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[An-diugh aig] LT',
+ nextDay : '[A-màireach aig] LT',
+ nextWeek : 'dddd [aig] LT',
+ lastDay : '[An-dè aig] LT',
+ lastWeek : 'dddd [seo chaidh] [aig] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'ann an %s',
+ past : 'bho chionn %s',
+ s : 'beagan diogan',
+ ss : '%d diogan',
+ m : 'mionaid',
+ mm : '%d mionaidean',
+ h : 'uair',
+ hh : '%d uairean',
+ d : 'latha',
+ dd : '%d latha',
+ M : 'mìos',
+ MM : '%d mìosan',
+ y : 'bliadhna',
+ yy : '%d bliadhna'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}(d|na|mh)/,
+ ordinal : function (number) {
+ var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return gd;
+
+})));
+
+
+/***/ }),
+/* 50 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Galician [gl]
+//! author : Juan G. Hurtado : https://github.com/juanghurtado
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var gl = moment.defineLocale('gl', {
+ months : 'xaneiro_febreiro_marzo_abril_maio_xuño_xullo_agosto_setembro_outubro_novembro_decembro'.split('_'),
+ monthsShort : 'xan._feb._mar._abr._mai._xuñ._xul._ago._set._out._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'domingo_luns_martes_mércores_xoves_venres_sábado'.split('_'),
+ weekdaysShort : 'dom._lun._mar._mér._xov._ven._sáb.'.split('_'),
+ weekdaysMin : 'do_lu_ma_mé_xo_ve_sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY H:mm',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
+ },
+ calendar : {
+ sameDay : function () {
+ return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+ },
+ nextDay : function () {
+ return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+ },
+ nextWeek : function () {
+ return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+ },
+ lastDay : function () {
+ return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
+ },
+ lastWeek : function () {
+ return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : function (str) {
+ if (str.indexOf('un') === 0) {
+ return 'n' + str;
+ }
+ return 'en ' + str;
+ },
+ past : 'hai %s',
+ s : 'uns segundos',
+ ss : '%d segundos',
+ m : 'un minuto',
+ mm : '%d minutos',
+ h : 'unha hora',
+ hh : '%d horas',
+ d : 'un día',
+ dd : '%d días',
+ M : 'un mes',
+ MM : '%d meses',
+ y : 'un ano',
+ yy : '%d anos'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal : '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return gl;
+
+})));
+
+
+/***/ }),
+/* 51 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Konkani Latin script [gom-latn]
+//! author : The Discoverer : https://github.com/WikiDiscoverer
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 's': ['thodde secondanim', 'thodde second'],
+ 'ss': [number + ' secondanim', number + ' second'],
+ 'm': ['eka mintan', 'ek minute'],
+ 'mm': [number + ' mintanim', number + ' mintam'],
+ 'h': ['eka horan', 'ek hor'],
+ 'hh': [number + ' horanim', number + ' hor'],
+ 'd': ['eka disan', 'ek dis'],
+ 'dd': [number + ' disanim', number + ' dis'],
+ 'M': ['eka mhoinean', 'ek mhoino'],
+ 'MM': [number + ' mhoineanim', number + ' mhoine'],
+ 'y': ['eka vorsan', 'ek voros'],
+ 'yy': [number + ' vorsanim', number + ' vorsam']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+
+var gomLatn = moment.defineLocale('gom-latn', {
+ months : 'Janer_Febrer_Mars_Abril_Mai_Jun_Julai_Agost_Setembr_Otubr_Novembr_Dezembr'.split('_'),
+ monthsShort : 'Jan._Feb._Mars_Abr._Mai_Jun_Jul._Ago._Set._Otu._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'Aitar_Somar_Mongllar_Budvar_Brestar_Sukrar_Son\'var'.split('_'),
+ weekdaysShort : 'Ait._Som._Mon._Bud._Bre._Suk._Son.'.split('_'),
+ weekdaysMin : 'Ai_Sm_Mo_Bu_Br_Su_Sn'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'A h:mm [vazta]',
+ LTS : 'A h:mm:ss [vazta]',
+ L : 'DD-MM-YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY A h:mm [vazta]',
+ LLLL : 'dddd, MMMM[achea] Do, YYYY, A h:mm [vazta]',
+ llll: 'ddd, D MMM YYYY, A h:mm [vazta]'
+ },
+ calendar : {
+ sameDay: '[Aiz] LT',
+ nextDay: '[Faleam] LT',
+ nextWeek: '[Ieta to] dddd[,] LT',
+ lastDay: '[Kal] LT',
+ lastWeek: '[Fatlo] dddd[,] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : '%s',
+ past : '%s adim',
+ s : processRelativeTime,
+ ss : processRelativeTime,
+ m : processRelativeTime,
+ mm : processRelativeTime,
+ h : processRelativeTime,
+ hh : processRelativeTime,
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}(er)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ // the ordinal 'er' only applies to day of the month
+ case 'D':
+ return number + 'er';
+ default:
+ case 'M':
+ case 'Q':
+ case 'DDD':
+ case 'd':
+ case 'w':
+ case 'W':
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ },
+ meridiemParse: /rati|sokalli|donparam|sanje/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'rati') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'sokalli') {
+ return hour;
+ } else if (meridiem === 'donparam') {
+ return hour > 12 ? hour : hour + 12;
+ } else if (meridiem === 'sanje') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'rati';
+ } else if (hour < 12) {
+ return 'sokalli';
+ } else if (hour < 16) {
+ return 'donparam';
+ } else if (hour < 20) {
+ return 'sanje';
+ } else {
+ return 'rati';
+ }
+ }
+});
+
+return gomLatn;
+
+})));
+
+
+/***/ }),
+/* 52 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Gujarati [gu]
+//! author : Kaushik Thanki : https://github.com/Kaushik1987
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '૧',
+ '2': '૨',
+ '3': '૩',
+ '4': '૪',
+ '5': '૫',
+ '6': '૬',
+ '7': '૭',
+ '8': '૮',
+ '9': '૯',
+ '0': '૦'
+ };
+var numberMap = {
+ '૧': '1',
+ '૨': '2',
+ '૩': '3',
+ '૪': '4',
+ '૫': '5',
+ '૬': '6',
+ '૭': '7',
+ '૮': '8',
+ '૯': '9',
+ '૦': '0'
+ };
+
+var gu = moment.defineLocale('gu', {
+ months: 'જાન્યુઆરી_ફેબ્રુઆરી_માર્ચ_એપ્રિલ_મે_જૂન_જુલાઈ_ઑગસ્ટ_સપ્ટેમ્બર_ઑક્ટ્બર_નવેમ્બર_ડિસેમ્બર'.split('_'),
+ monthsShort: 'જાન્યુ._ફેબ્રુ._માર્ચ_એપ્રિ._મે_જૂન_જુલા._ઑગ._સપ્ટે._ઑક્ટ્._નવે._ડિસે.'.split('_'),
+ monthsParseExact: true,
+ weekdays: 'રવિવાર_સોમવાર_મંગળવાર_બુધ્વાર_ગુરુવાર_શુક્રવાર_શનિવાર'.split('_'),
+ weekdaysShort: 'રવિ_સોમ_મંગળ_બુધ્_ગુરુ_શુક્ર_શનિ'.split('_'),
+ weekdaysMin: 'ર_સો_મં_બુ_ગુ_શુ_શ'.split('_'),
+ longDateFormat: {
+ LT: 'A h:mm વાગ્યે',
+ LTS: 'A h:mm:ss વાગ્યે',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY, A h:mm વાગ્યે',
+ LLLL: 'dddd, D MMMM YYYY, A h:mm વાગ્યે'
+ },
+ calendar: {
+ sameDay: '[આજ] LT',
+ nextDay: '[કાલે] LT',
+ nextWeek: 'dddd, LT',
+ lastDay: '[ગઇકાલે] LT',
+ lastWeek: '[પાછલા] dddd, LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: '%s મા',
+ past: '%s પેહલા',
+ s: 'અમુક પળો',
+ ss: '%d સેકંડ',
+ m: 'એક મિનિટ',
+ mm: '%d મિનિટ',
+ h: 'એક કલાક',
+ hh: '%d કલાક',
+ d: 'એક દિવસ',
+ dd: '%d દિવસ',
+ M: 'એક મહિનો',
+ MM: '%d મહિનો',
+ y: 'એક વર્ષ',
+ yy: '%d વર્ષ'
+ },
+ preparse: function (string) {
+ return string.replace(/[૧૨૩૪૫૬૭૮૯૦]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ // Gujarati notation for meridiems are quite fuzzy in practice. While there exists
+ // a rigid notion of a 'Pahar' it is not used as rigidly in modern Gujarati.
+ meridiemParse: /રાત|બપોર|સવાર|સાંજ/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'રાત') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'સવાર') {
+ return hour;
+ } else if (meridiem === 'બપોર') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'સાંજ') {
+ return hour + 12;
+ }
+ },
+ meridiem: function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'રાત';
+ } else if (hour < 10) {
+ return 'સવાર';
+ } else if (hour < 17) {
+ return 'બપોર';
+ } else if (hour < 20) {
+ return 'સાંજ';
+ } else {
+ return 'રાત';
+ }
+ },
+ week: {
+ dow: 0, // Sunday is the first day of the week.
+ doy: 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return gu;
+
+})));
+
+
+/***/ }),
+/* 53 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Hebrew [he]
+//! author : Tomer Cohen : https://github.com/tomer
+//! author : Moshe Simantov : https://github.com/DevelopmentIL
+//! author : Tal Ater : https://github.com/TalAter
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var he = moment.defineLocale('he', {
+ months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'),
+ monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'),
+ weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
+ weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'),
+ weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [ב]MMMM YYYY',
+ LLL : 'D [ב]MMMM YYYY HH:mm',
+ LLLL : 'dddd, D [ב]MMMM YYYY HH:mm',
+ l : 'D/M/YYYY',
+ ll : 'D MMM YYYY',
+ lll : 'D MMM YYYY HH:mm',
+ llll : 'ddd, D MMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[היום ב־]LT',
+ nextDay : '[מחר ב־]LT',
+ nextWeek : 'dddd [בשעה] LT',
+ lastDay : '[אתמול ב־]LT',
+ lastWeek : '[ביום] dddd [האחרון בשעה] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'בעוד %s',
+ past : 'לפני %s',
+ s : 'מספר שניות',
+ ss : '%d שניות',
+ m : 'דקה',
+ mm : '%d דקות',
+ h : 'שעה',
+ hh : function (number) {
+ if (number === 2) {
+ return 'שעתיים';
+ }
+ return number + ' שעות';
+ },
+ d : 'יום',
+ dd : function (number) {
+ if (number === 2) {
+ return 'יומיים';
+ }
+ return number + ' ימים';
+ },
+ M : 'חודש',
+ MM : function (number) {
+ if (number === 2) {
+ return 'חודשיים';
+ }
+ return number + ' חודשים';
+ },
+ y : 'שנה',
+ yy : function (number) {
+ if (number === 2) {
+ return 'שנתיים';
+ } else if (number % 10 === 0 && number !== 10) {
+ return number + ' שנה';
+ }
+ return number + ' שנים';
+ }
+ },
+ meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,
+ isPM : function (input) {
+ return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 5) {
+ return 'לפנות בוקר';
+ } else if (hour < 10) {
+ return 'בבוקר';
+ } else if (hour < 12) {
+ return isLower ? 'לפנה"צ' : 'לפני הצהריים';
+ } else if (hour < 18) {
+ return isLower ? 'אחה"צ' : 'אחרי הצהריים';
+ } else {
+ return 'בערב';
+ }
+ }
+});
+
+return he;
+
+})));
+
+
+/***/ }),
+/* 54 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Hindi [hi]
+//! author : Mayank Singhal : https://github.com/mayanksinghal
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '१',
+ '2': '२',
+ '3': '३',
+ '4': '४',
+ '5': '५',
+ '6': '६',
+ '7': '७',
+ '8': '८',
+ '9': '९',
+ '0': '०'
+};
+var numberMap = {
+ '१': '1',
+ '२': '2',
+ '३': '3',
+ '४': '4',
+ '५': '5',
+ '६': '6',
+ '७': '7',
+ '८': '8',
+ '९': '9',
+ '०': '0'
+};
+
+var hi = moment.defineLocale('hi', {
+ months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'),
+ monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
+ weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'),
+ weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm बजे',
+ LTS : 'A h:mm:ss बजे',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm बजे',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm बजे'
+ },
+ calendar : {
+ sameDay : '[आज] LT',
+ nextDay : '[कल] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[कल] LT',
+ lastWeek : '[पिछले] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s में',
+ past : '%s पहले',
+ s : 'कुछ ही क्षण',
+ ss : '%d सेकंड',
+ m : 'एक मिनट',
+ mm : '%d मिनट',
+ h : 'एक घंटा',
+ hh : '%d घंटे',
+ d : 'एक दिन',
+ dd : '%d दिन',
+ M : 'एक महीने',
+ MM : '%d महीने',
+ y : 'एक वर्ष',
+ yy : '%d वर्ष'
+ },
+ preparse: function (string) {
+ return string.replace(/[१२३४५६७८९०]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ // Hindi notation for meridiems are quite fuzzy in practice. While there exists
+ // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
+ meridiemParse: /रात|सुबह|दोपहर|शाम/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'रात') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'सुबह') {
+ return hour;
+ } else if (meridiem === 'दोपहर') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'शाम') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'रात';
+ } else if (hour < 10) {
+ return 'सुबह';
+ } else if (hour < 17) {
+ return 'दोपहर';
+ } else if (hour < 20) {
+ return 'शाम';
+ } else {
+ return 'रात';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return hi;
+
+})));
+
+
+/***/ }),
+/* 55 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Croatian [hr]
+//! author : Bojan Marković : https://github.com/bmarkovic
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function translate(number, withoutSuffix, key) {
+ var result = number + ' ';
+ switch (key) {
+ case 'ss':
+ if (number === 1) {
+ result += 'sekunda';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'sekunde';
+ } else {
+ result += 'sekundi';
+ }
+ return result;
+ case 'm':
+ return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+ case 'mm':
+ if (number === 1) {
+ result += 'minuta';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'minute';
+ } else {
+ result += 'minuta';
+ }
+ return result;
+ case 'h':
+ return withoutSuffix ? 'jedan sat' : 'jednog sata';
+ case 'hh':
+ if (number === 1) {
+ result += 'sat';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'sata';
+ } else {
+ result += 'sati';
+ }
+ return result;
+ case 'dd':
+ if (number === 1) {
+ result += 'dan';
+ } else {
+ result += 'dana';
+ }
+ return result;
+ case 'MM':
+ if (number === 1) {
+ result += 'mjesec';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'mjeseca';
+ } else {
+ result += 'mjeseci';
+ }
+ return result;
+ case 'yy':
+ if (number === 1) {
+ result += 'godina';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'godine';
+ } else {
+ result += 'godina';
+ }
+ return result;
+ }
+}
+
+var hr = moment.defineLocale('hr', {
+ months : {
+ format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'),
+ standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_')
+ },
+ monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+ weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+ weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[danas u] LT',
+ nextDay : '[sutra u] LT',
+ nextWeek : function () {
+ switch (this.day()) {
+ case 0:
+ return '[u] [nedjelju] [u] LT';
+ case 3:
+ return '[u] [srijedu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[u] dddd [u] LT';
+ }
+ },
+ lastDay : '[jučer u] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ return '[prošlu] dddd [u] LT';
+ case 6:
+ return '[prošle] [subote] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[prošli] dddd [u] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'prije %s',
+ s : 'par sekundi',
+ ss : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : 'dan',
+ dd : translate,
+ M : 'mjesec',
+ MM : translate,
+ y : 'godinu',
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return hr;
+
+})));
+
+
+/***/ }),
+/* 56 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Hungarian [hu]
+//! author : Adam Brunner : https://github.com/adambrunner
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
+function translate(number, withoutSuffix, key, isFuture) {
+ var num = number;
+ switch (key) {
+ case 's':
+ return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
+ case 'ss':
+ return num + (isFuture || withoutSuffix) ? ' másodperc' : ' másodperce';
+ case 'm':
+ return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
+ case 'mm':
+ return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
+ case 'h':
+ return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
+ case 'hh':
+ return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
+ case 'd':
+ return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
+ case 'dd':
+ return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
+ case 'M':
+ return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+ case 'MM':
+ return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+ case 'y':
+ return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
+ case 'yy':
+ return num + (isFuture || withoutSuffix ? ' év' : ' éve');
+ }
+ return '';
+}
+function week(isFuture) {
+ return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
+}
+
+var hu = moment.defineLocale('hu', {
+ months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'),
+ monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'),
+ weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'),
+ weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'),
+ weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'YYYY.MM.DD.',
+ LL : 'YYYY. MMMM D.',
+ LLL : 'YYYY. MMMM D. H:mm',
+ LLLL : 'YYYY. MMMM D., dddd H:mm'
+ },
+ meridiemParse: /de|du/i,
+ isPM: function (input) {
+ return input.charAt(1).toLowerCase() === 'u';
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 12) {
+ return isLower === true ? 'de' : 'DE';
+ } else {
+ return isLower === true ? 'du' : 'DU';
+ }
+ },
+ calendar : {
+ sameDay : '[ma] LT[-kor]',
+ nextDay : '[holnap] LT[-kor]',
+ nextWeek : function () {
+ return week.call(this, true);
+ },
+ lastDay : '[tegnap] LT[-kor]',
+ lastWeek : function () {
+ return week.call(this, false);
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s múlva',
+ past : '%s',
+ s : translate,
+ ss : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return hu;
+
+})));
+
+
+/***/ }),
+/* 57 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Armenian [hy-am]
+//! author : Armendarabyan : https://github.com/armendarabyan
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var hyAm = moment.defineLocale('hy-am', {
+ months : {
+ format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'),
+ standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_')
+ },
+ monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'),
+ weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'),
+ weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
+ weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY թ.',
+ LLL : 'D MMMM YYYY թ., HH:mm',
+ LLLL : 'dddd, D MMMM YYYY թ., HH:mm'
+ },
+ calendar : {
+ sameDay: '[այսօր] LT',
+ nextDay: '[վաղը] LT',
+ lastDay: '[երեկ] LT',
+ nextWeek: function () {
+ return 'dddd [օրը ժամը] LT';
+ },
+ lastWeek: function () {
+ return '[անցած] dddd [օրը ժամը] LT';
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : '%s հետո',
+ past : '%s առաջ',
+ s : 'մի քանի վայրկյան',
+ ss : '%d վայրկյան',
+ m : 'րոպե',
+ mm : '%d րոպե',
+ h : 'ժամ',
+ hh : '%d ժամ',
+ d : 'օր',
+ dd : '%d օր',
+ M : 'ամիս',
+ MM : '%d ամիս',
+ y : 'տարի',
+ yy : '%d տարի'
+ },
+ meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,
+ isPM: function (input) {
+ return /^(ցերեկվա|երեկոյան)$/.test(input);
+ },
+ meridiem : function (hour) {
+ if (hour < 4) {
+ return 'գիշերվա';
+ } else if (hour < 12) {
+ return 'առավոտվա';
+ } else if (hour < 17) {
+ return 'ցերեկվա';
+ } else {
+ return 'երեկոյան';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'DDD':
+ case 'w':
+ case 'W':
+ case 'DDDo':
+ if (number === 1) {
+ return number + '-ին';
+ }
+ return number + '-րդ';
+ default:
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return hyAm;
+
+})));
+
+
+/***/ }),
+/* 58 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Indonesian [id]
+//! author : Mohammad Satrio Utomo : https://github.com/tyok
+//! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var id = moment.defineLocale('id', {
+ months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'),
+ weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'),
+ weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'),
+ weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [pukul] HH.mm',
+ LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+ },
+ meridiemParse: /pagi|siang|sore|malam/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'pagi') {
+ return hour;
+ } else if (meridiem === 'siang') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'sore' || meridiem === 'malam') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'pagi';
+ } else if (hours < 15) {
+ return 'siang';
+ } else if (hours < 19) {
+ return 'sore';
+ } else {
+ return 'malam';
+ }
+ },
+ calendar : {
+ sameDay : '[Hari ini pukul] LT',
+ nextDay : '[Besok pukul] LT',
+ nextWeek : 'dddd [pukul] LT',
+ lastDay : '[Kemarin pukul] LT',
+ lastWeek : 'dddd [lalu pukul] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dalam %s',
+ past : '%s yang lalu',
+ s : 'beberapa detik',
+ ss : '%d detik',
+ m : 'semenit',
+ mm : '%d menit',
+ h : 'sejam',
+ hh : '%d jam',
+ d : 'sehari',
+ dd : '%d hari',
+ M : 'sebulan',
+ MM : '%d bulan',
+ y : 'setahun',
+ yy : '%d tahun'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return id;
+
+})));
+
+
+/***/ }),
+/* 59 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Icelandic [is]
+//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function plural(n) {
+ if (n % 100 === 11) {
+ return true;
+ } else if (n % 10 === 1) {
+ return false;
+ }
+ return true;
+}
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ switch (key) {
+ case 's':
+ return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
+ case 'ss':
+ if (plural(number)) {
+ return result + (withoutSuffix || isFuture ? 'sekúndur' : 'sekúndum');
+ }
+ return result + 'sekúnda';
+ case 'm':
+ return withoutSuffix ? 'mínúta' : 'mínútu';
+ case 'mm':
+ if (plural(number)) {
+ return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
+ } else if (withoutSuffix) {
+ return result + 'mínúta';
+ }
+ return result + 'mínútu';
+ case 'hh':
+ if (plural(number)) {
+ return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
+ }
+ return result + 'klukkustund';
+ case 'd':
+ if (withoutSuffix) {
+ return 'dagur';
+ }
+ return isFuture ? 'dag' : 'degi';
+ case 'dd':
+ if (plural(number)) {
+ if (withoutSuffix) {
+ return result + 'dagar';
+ }
+ return result + (isFuture ? 'daga' : 'dögum');
+ } else if (withoutSuffix) {
+ return result + 'dagur';
+ }
+ return result + (isFuture ? 'dag' : 'degi');
+ case 'M':
+ if (withoutSuffix) {
+ return 'mánuður';
+ }
+ return isFuture ? 'mánuð' : 'mánuði';
+ case 'MM':
+ if (plural(number)) {
+ if (withoutSuffix) {
+ return result + 'mánuðir';
+ }
+ return result + (isFuture ? 'mánuði' : 'mánuðum');
+ } else if (withoutSuffix) {
+ return result + 'mánuður';
+ }
+ return result + (isFuture ? 'mánuð' : 'mánuði');
+ case 'y':
+ return withoutSuffix || isFuture ? 'ár' : 'ári';
+ case 'yy':
+ if (plural(number)) {
+ return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
+ }
+ return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
+ }
+}
+
+var is = moment.defineLocale('is', {
+ months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'),
+ weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'),
+ weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'),
+ weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY [kl.] H:mm',
+ LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm'
+ },
+ calendar : {
+ sameDay : '[í dag kl.] LT',
+ nextDay : '[á morgun kl.] LT',
+ nextWeek : 'dddd [kl.] LT',
+ lastDay : '[í gær kl.] LT',
+ lastWeek : '[síðasta] dddd [kl.] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'eftir %s',
+ past : 'fyrir %s síðan',
+ s : translate,
+ ss : translate,
+ m : translate,
+ mm : translate,
+ h : 'klukkustund',
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return is;
+
+})));
+
+
+/***/ }),
+/* 60 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Italian [it]
+//! author : Lorenzo : https://github.com/aliem
+//! author: Mattia Larentis: https://github.com/nostalgiaz
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var it = moment.defineLocale('it', {
+ months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'),
+ monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
+ weekdays : 'domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato'.split('_'),
+ weekdaysShort : 'dom_lun_mar_mer_gio_ven_sab'.split('_'),
+ weekdaysMin : 'do_lu_ma_me_gi_ve_sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Oggi alle] LT',
+ nextDay: '[Domani alle] LT',
+ nextWeek: 'dddd [alle] LT',
+ lastDay: '[Ieri alle] LT',
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[la scorsa] dddd [alle] LT';
+ default:
+ return '[lo scorso] dddd [alle] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : function (s) {
+ return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s;
+ },
+ past : '%s fa',
+ s : 'alcuni secondi',
+ ss : '%d secondi',
+ m : 'un minuto',
+ mm : '%d minuti',
+ h : 'un\'ora',
+ hh : '%d ore',
+ d : 'un giorno',
+ dd : '%d giorni',
+ M : 'un mese',
+ MM : '%d mesi',
+ y : 'un anno',
+ yy : '%d anni'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal: '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return it;
+
+})));
+
+
+/***/ }),
+/* 61 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Japanese [ja]
+//! author : LI Long : https://github.com/baryon
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ja = moment.defineLocale('ja', {
+ months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
+ weekdaysShort : '日_月_火_水_木_金_土'.split('_'),
+ weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY/MM/DD',
+ LL : 'YYYY年M月D日',
+ LLL : 'YYYY年M月D日 HH:mm',
+ LLLL : 'YYYY年M月D日 HH:mm dddd',
+ l : 'YYYY/MM/DD',
+ ll : 'YYYY年M月D日',
+ lll : 'YYYY年M月D日 HH:mm',
+ llll : 'YYYY年M月D日 HH:mm dddd'
+ },
+ meridiemParse: /午前|午後/i,
+ isPM : function (input) {
+ return input === '午後';
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return '午前';
+ } else {
+ return '午後';
+ }
+ },
+ calendar : {
+ sameDay : '[今日] LT',
+ nextDay : '[明日] LT',
+ nextWeek : '[来週]dddd LT',
+ lastDay : '[昨日] LT',
+ lastWeek : '[前週]dddd LT',
+ sameElse : 'L'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}日/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return number + '日';
+ default:
+ return number;
+ }
+ },
+ relativeTime : {
+ future : '%s後',
+ past : '%s前',
+ s : '数秒',
+ ss : '%d秒',
+ m : '1分',
+ mm : '%d分',
+ h : '1時間',
+ hh : '%d時間',
+ d : '1日',
+ dd : '%d日',
+ M : '1ヶ月',
+ MM : '%dヶ月',
+ y : '1年',
+ yy : '%d年'
+ }
+});
+
+return ja;
+
+})));
+
+
+/***/ }),
+/* 62 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Javanese [jv]
+//! author : Rony Lantip : https://github.com/lantip
+//! reference: http://jv.wikipedia.org/wiki/Basa_Jawa
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var jv = moment.defineLocale('jv', {
+ months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'),
+ weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'),
+ weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'),
+ weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [pukul] HH.mm',
+ LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+ },
+ meridiemParse: /enjing|siyang|sonten|ndalu/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'enjing') {
+ return hour;
+ } else if (meridiem === 'siyang') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'sonten' || meridiem === 'ndalu') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'enjing';
+ } else if (hours < 15) {
+ return 'siyang';
+ } else if (hours < 19) {
+ return 'sonten';
+ } else {
+ return 'ndalu';
+ }
+ },
+ calendar : {
+ sameDay : '[Dinten puniko pukul] LT',
+ nextDay : '[Mbenjang pukul] LT',
+ nextWeek : 'dddd [pukul] LT',
+ lastDay : '[Kala wingi pukul] LT',
+ lastWeek : 'dddd [kepengker pukul] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'wonten ing %s',
+ past : '%s ingkang kepengker',
+ s : 'sawetawis detik',
+ ss : '%d detik',
+ m : 'setunggal menit',
+ mm : '%d menit',
+ h : 'setunggal jam',
+ hh : '%d jam',
+ d : 'sedinten',
+ dd : '%d dinten',
+ M : 'sewulan',
+ MM : '%d wulan',
+ y : 'setaun',
+ yy : '%d taun'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return jv;
+
+})));
+
+
+/***/ }),
+/* 63 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Georgian [ka]
+//! author : Irakli Janiashvili : https://github.com/irakli-janiashvili
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ka = moment.defineLocale('ka', {
+ months : {
+ standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
+ format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
+ },
+ monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'),
+ weekdays : {
+ standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
+ format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'),
+ isFormat: /(წინა|შემდეგ)/
+ },
+ weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'),
+ weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[დღეს] LT[-ზე]',
+ nextDay : '[ხვალ] LT[-ზე]',
+ lastDay : '[გუშინ] LT[-ზე]',
+ nextWeek : '[შემდეგ] dddd LT[-ზე]',
+ lastWeek : '[წინა] dddd LT-ზე',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : function (s) {
+ return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
+ s.replace(/ი$/, 'ში') :
+ s + 'ში';
+ },
+ past : function (s) {
+ if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
+ return s.replace(/(ი|ე)$/, 'ის უკან');
+ }
+ if ((/წელი/).test(s)) {
+ return s.replace(/წელი$/, 'წლის უკან');
+ }
+ },
+ s : 'რამდენიმე წამი',
+ ss : '%d წამი',
+ m : 'წუთი',
+ mm : '%d წუთი',
+ h : 'საათი',
+ hh : '%d საათი',
+ d : 'დღე',
+ dd : '%d დღე',
+ M : 'თვე',
+ MM : '%d თვე',
+ y : 'წელი',
+ yy : '%d წელი'
+ },
+ dayOfMonthOrdinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,
+ ordinal : function (number) {
+ if (number === 0) {
+ return number;
+ }
+ if (number === 1) {
+ return number + '-ლი';
+ }
+ if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
+ return 'მე-' + number;
+ }
+ return number + '-ე';
+ },
+ week : {
+ dow : 1,
+ doy : 7
+ }
+});
+
+return ka;
+
+})));
+
+
+/***/ }),
+/* 64 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Kazakh [kk]
+//! authors : Nurlan Rakhimzhanov : https://github.com/nurlan
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+ 0: '-ші',
+ 1: '-ші',
+ 2: '-ші',
+ 3: '-ші',
+ 4: '-ші',
+ 5: '-ші',
+ 6: '-шы',
+ 7: '-ші',
+ 8: '-ші',
+ 9: '-шы',
+ 10: '-шы',
+ 20: '-шы',
+ 30: '-шы',
+ 40: '-шы',
+ 50: '-ші',
+ 60: '-шы',
+ 70: '-ші',
+ 80: '-ші',
+ 90: '-шы',
+ 100: '-ші'
+};
+
+var kk = moment.defineLocale('kk', {
+ months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'),
+ monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'),
+ weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'),
+ weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'),
+ weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Бүгін сағат] LT',
+ nextDay : '[Ертең сағат] LT',
+ nextWeek : 'dddd [сағат] LT',
+ lastDay : '[Кеше сағат] LT',
+ lastWeek : '[Өткен аптаның] dddd [сағат] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ішінде',
+ past : '%s бұрын',
+ s : 'бірнеше секунд',
+ ss : '%d секунд',
+ m : 'бір минут',
+ mm : '%d минут',
+ h : 'бір сағат',
+ hh : '%d сағат',
+ d : 'бір күн',
+ dd : '%d күн',
+ M : 'бір ай',
+ MM : '%d ай',
+ y : 'бір жыл',
+ yy : '%d жыл'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(ші|шы)/,
+ ordinal : function (number) {
+ var a = number % 10,
+ b = number >= 100 ? 100 : null;
+ return number + (suffixes[number] || suffixes[a] || suffixes[b]);
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return kk;
+
+})));
+
+
+/***/ }),
+/* 65 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Cambodian [km]
+//! author : Kruy Vanna : https://github.com/kruyvanna
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var km = moment.defineLocale('km', {
+ months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
+ monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
+ weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+ weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+ weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY HH:mm',
+ LLLL: 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar: {
+ sameDay: '[ថ្ងៃនេះ ម៉ោង] LT',
+ nextDay: '[ស្អែក ម៉ោង] LT',
+ nextWeek: 'dddd [ម៉ោង] LT',
+ lastDay: '[ម្សិលមិញ ម៉ោង] LT',
+ lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: '%sទៀត',
+ past: '%sមុន',
+ s: 'ប៉ុន្មានវិនាទី',
+ ss: '%d វិនាទី',
+ m: 'មួយនាទី',
+ mm: '%d នាទី',
+ h: 'មួយម៉ោង',
+ hh: '%d ម៉ោង',
+ d: 'មួយថ្ងៃ',
+ dd: '%d ថ្ងៃ',
+ M: 'មួយខែ',
+ MM: '%d ខែ',
+ y: 'មួយឆ្នាំ',
+ yy: '%d ឆ្នាំ'
+ },
+ week: {
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return km;
+
+})));
+
+
+/***/ }),
+/* 66 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Kannada [kn]
+//! author : Rajeev Naik : https://github.com/rajeevnaikte
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '೧',
+ '2': '೨',
+ '3': '೩',
+ '4': '೪',
+ '5': '೫',
+ '6': '೬',
+ '7': '೭',
+ '8': '೮',
+ '9': '೯',
+ '0': '೦'
+};
+var numberMap = {
+ '೧': '1',
+ '೨': '2',
+ '೩': '3',
+ '೪': '4',
+ '೫': '5',
+ '೬': '6',
+ '೭': '7',
+ '೮': '8',
+ '೯': '9',
+ '೦': '0'
+};
+
+var kn = moment.defineLocale('kn', {
+ months : 'ಜನವರಿ_ಫೆಬ್ರವರಿ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬರ್_ಅಕ್ಟೋಬರ್_ನವೆಂಬರ್_ಡಿಸೆಂಬರ್'.split('_'),
+ monthsShort : 'ಜನ_ಫೆಬ್ರ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬ_ಅಕ್ಟೋಬ_ನವೆಂಬ_ಡಿಸೆಂಬ'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'ಭಾನುವಾರ_ಸೋಮವಾರ_ಮಂಗಳವಾರ_ಬುಧವಾರ_ಗುರುವಾರ_ಶುಕ್ರವಾರ_ಶನಿವಾರ'.split('_'),
+ weekdaysShort : 'ಭಾನು_ಸೋಮ_ಮಂಗಳ_ಬುಧ_ಗುರು_ಶುಕ್ರ_ಶನಿ'.split('_'),
+ weekdaysMin : 'ಭಾ_ಸೋ_ಮಂ_ಬು_ಗು_ಶು_ಶ'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm',
+ LTS : 'A h:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm'
+ },
+ calendar : {
+ sameDay : '[ಇಂದು] LT',
+ nextDay : '[ನಾಳೆ] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[ನಿನ್ನೆ] LT',
+ lastWeek : '[ಕೊನೆಯ] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ನಂತರ',
+ past : '%s ಹಿಂದೆ',
+ s : 'ಕೆಲವು ಕ್ಷಣಗಳು',
+ ss : '%d ಸೆಕೆಂಡುಗಳು',
+ m : 'ಒಂದು ನಿಮಿಷ',
+ mm : '%d ನಿಮಿಷ',
+ h : 'ಒಂದು ಗಂಟೆ',
+ hh : '%d ಗಂಟೆ',
+ d : 'ಒಂದು ದಿನ',
+ dd : '%d ದಿನ',
+ M : 'ಒಂದು ತಿಂಗಳು',
+ MM : '%d ತಿಂಗಳು',
+ y : 'ಒಂದು ವರ್ಷ',
+ yy : '%d ವರ್ಷ'
+ },
+ preparse: function (string) {
+ return string.replace(/[೧೨೩೪೫೬೭೮೯೦]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /ರಾತ್ರಿ|ಬೆಳಿಗ್ಗೆ|ಮಧ್ಯಾಹ್ನ|ಸಂಜೆ/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'ರಾತ್ರಿ') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'ಬೆಳಿಗ್ಗೆ') {
+ return hour;
+ } else if (meridiem === 'ಮಧ್ಯಾಹ್ನ') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'ಸಂಜೆ') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ರಾತ್ರಿ';
+ } else if (hour < 10) {
+ return 'ಬೆಳಿಗ್ಗೆ';
+ } else if (hour < 17) {
+ return 'ಮಧ್ಯಾಹ್ನ';
+ } else if (hour < 20) {
+ return 'ಸಂಜೆ';
+ } else {
+ return 'ರಾತ್ರಿ';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ನೇ)/,
+ ordinal : function (number) {
+ return number + 'ನೇ';
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return kn;
+
+})));
+
+
+/***/ }),
+/* 67 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Korean [ko]
+//! author : Kyungwook, Park : https://github.com/kyungw00k
+//! author : Jeeeyul Lee <jeeeyul@gmail.com>
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ko = moment.defineLocale('ko', {
+ months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
+ monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
+ weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'),
+ weekdaysShort : '일_월_화_수_목_금_토'.split('_'),
+ weekdaysMin : '일_월_화_수_목_금_토'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm',
+ LTS : 'A h:mm:ss',
+ L : 'YYYY.MM.DD',
+ LL : 'YYYY년 MMMM D일',
+ LLL : 'YYYY년 MMMM D일 A h:mm',
+ LLLL : 'YYYY년 MMMM D일 dddd A h:mm',
+ l : 'YYYY.MM.DD',
+ ll : 'YYYY년 MMMM D일',
+ lll : 'YYYY년 MMMM D일 A h:mm',
+ llll : 'YYYY년 MMMM D일 dddd A h:mm'
+ },
+ calendar : {
+ sameDay : '오늘 LT',
+ nextDay : '내일 LT',
+ nextWeek : 'dddd LT',
+ lastDay : '어제 LT',
+ lastWeek : '지난주 dddd LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s 후',
+ past : '%s 전',
+ s : '몇 초',
+ ss : '%d초',
+ m : '1분',
+ mm : '%d분',
+ h : '한 시간',
+ hh : '%d시간',
+ d : '하루',
+ dd : '%d일',
+ M : '한 달',
+ MM : '%d달',
+ y : '일 년',
+ yy : '%d년'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}(일|월|주)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return number + '일';
+ case 'M':
+ return number + '월';
+ case 'w':
+ case 'W':
+ return number + '주';
+ default:
+ return number;
+ }
+ },
+ meridiemParse : /오전|오후/,
+ isPM : function (token) {
+ return token === '오후';
+ },
+ meridiem : function (hour, minute, isUpper) {
+ return hour < 12 ? '오전' : '오후';
+ }
+});
+
+return ko;
+
+})));
+
+
+/***/ }),
+/* 68 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Kyrgyz [ky]
+//! author : Chyngyz Arystan uulu : https://github.com/chyngyz
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+
+var suffixes = {
+ 0: '-чү',
+ 1: '-чи',
+ 2: '-чи',
+ 3: '-чү',
+ 4: '-чү',
+ 5: '-чи',
+ 6: '-чы',
+ 7: '-чи',
+ 8: '-чи',
+ 9: '-чу',
+ 10: '-чу',
+ 20: '-чы',
+ 30: '-чу',
+ 40: '-чы',
+ 50: '-чү',
+ 60: '-чы',
+ 70: '-чи',
+ 80: '-чи',
+ 90: '-чу',
+ 100: '-чү'
+};
+
+var ky = moment.defineLocale('ky', {
+ months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
+ monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
+ weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'),
+ weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'),
+ weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Бүгүн саат] LT',
+ nextDay : '[Эртең саат] LT',
+ nextWeek : 'dddd [саат] LT',
+ lastDay : '[Кече саат] LT',
+ lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ичинде',
+ past : '%s мурун',
+ s : 'бирнече секунд',
+ ss : '%d секунд',
+ m : 'бир мүнөт',
+ mm : '%d мүнөт',
+ h : 'бир саат',
+ hh : '%d саат',
+ d : 'бир күн',
+ dd : '%d күн',
+ M : 'бир ай',
+ MM : '%d ай',
+ y : 'бир жыл',
+ yy : '%d жыл'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(чи|чы|чү|чу)/,
+ ordinal : function (number) {
+ var a = number % 10,
+ b = number >= 100 ? 100 : null;
+ return number + (suffixes[number] || suffixes[a] || suffixes[b]);
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ky;
+
+})));
+
+
+/***/ }),
+/* 69 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Luxembourgish [lb]
+//! author : mweimerskirch : https://github.com/mweimerskirch
+//! author : David Raison : https://github.com/kwisatz
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 'm': ['eng Minutt', 'enger Minutt'],
+ 'h': ['eng Stonn', 'enger Stonn'],
+ 'd': ['een Dag', 'engem Dag'],
+ 'M': ['ee Mount', 'engem Mount'],
+ 'y': ['ee Joer', 'engem Joer']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+function processFutureTime(string) {
+ var number = string.substr(0, string.indexOf(' '));
+ if (eifelerRegelAppliesToNumber(number)) {
+ return 'a ' + string;
+ }
+ return 'an ' + string;
+}
+function processPastTime(string) {
+ var number = string.substr(0, string.indexOf(' '));
+ if (eifelerRegelAppliesToNumber(number)) {
+ return 'viru ' + string;
+ }
+ return 'virun ' + string;
+}
+/**
+ * Returns true if the word before the given number loses the '-n' ending.
+ * e.g. 'an 10 Deeg' but 'a 5 Deeg'
+ *
+ * @param number {integer}
+ * @returns {boolean}
+ */
+function eifelerRegelAppliesToNumber(number) {
+ number = parseInt(number, 10);
+ if (isNaN(number)) {
+ return false;
+ }
+ if (number < 0) {
+ // Negative Number --> always true
+ return true;
+ } else if (number < 10) {
+ // Only 1 digit
+ if (4 <= number && number <= 7) {
+ return true;
+ }
+ return false;
+ } else if (number < 100) {
+ // 2 digits
+ var lastDigit = number % 10, firstDigit = number / 10;
+ if (lastDigit === 0) {
+ return eifelerRegelAppliesToNumber(firstDigit);
+ }
+ return eifelerRegelAppliesToNumber(lastDigit);
+ } else if (number < 10000) {
+ // 3 or 4 digits --> recursively check first digit
+ while (number >= 10) {
+ number = number / 10;
+ }
+ return eifelerRegelAppliesToNumber(number);
+ } else {
+ // Anything larger than 4 digits: recursively check first n-3 digits
+ number = number / 1000;
+ return eifelerRegelAppliesToNumber(number);
+ }
+}
+
+var lb = moment.defineLocale('lb', {
+ months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+ monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'),
+ weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'),
+ weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'H:mm [Auer]',
+ LTS: 'H:mm:ss [Auer]',
+ L: 'DD.MM.YYYY',
+ LL: 'D. MMMM YYYY',
+ LLL: 'D. MMMM YYYY H:mm [Auer]',
+ LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]'
+ },
+ calendar: {
+ sameDay: '[Haut um] LT',
+ sameElse: 'L',
+ nextDay: '[Muer um] LT',
+ nextWeek: 'dddd [um] LT',
+ lastDay: '[Gëschter um] LT',
+ lastWeek: function () {
+ // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
+ switch (this.day()) {
+ case 2:
+ case 4:
+ return '[Leschten] dddd [um] LT';
+ default:
+ return '[Leschte] dddd [um] LT';
+ }
+ }
+ },
+ relativeTime : {
+ future : processFutureTime,
+ past : processPastTime,
+ s : 'e puer Sekonnen',
+ ss : '%d Sekonnen',
+ m : processRelativeTime,
+ mm : '%d Minutten',
+ h : processRelativeTime,
+ hh : '%d Stonnen',
+ d : processRelativeTime,
+ dd : '%d Deeg',
+ M : processRelativeTime,
+ MM : '%d Méint',
+ y : processRelativeTime,
+ yy : '%d Joer'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal: '%d.',
+ week: {
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return lb;
+
+})));
+
+
+/***/ }),
+/* 70 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Lao [lo]
+//! author : Ryan Hart : https://github.com/ryanhart2
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var lo = moment.defineLocale('lo', {
+ months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
+ monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
+ weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
+ weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
+ weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'ວັນdddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/,
+ isPM: function (input) {
+ return input === 'ຕອນແລງ';
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ຕອນເຊົ້າ';
+ } else {
+ return 'ຕອນແລງ';
+ }
+ },
+ calendar : {
+ sameDay : '[ມື້ນີ້ເວລາ] LT',
+ nextDay : '[ມື້ອື່ນເວລາ] LT',
+ nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT',
+ lastDay : '[ມື້ວານນີ້ເວລາ] LT',
+ lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'ອີກ %s',
+ past : '%sຜ່ານມາ',
+ s : 'ບໍ່ເທົ່າໃດວິນາທີ',
+ ss : '%d ວິນາທີ' ,
+ m : '1 ນາທີ',
+ mm : '%d ນາທີ',
+ h : '1 ຊົ່ວໂມງ',
+ hh : '%d ຊົ່ວໂມງ',
+ d : '1 ມື້',
+ dd : '%d ມື້',
+ M : '1 ເດືອນ',
+ MM : '%d ເດືອນ',
+ y : '1 ປີ',
+ yy : '%d ປີ'
+ },
+ dayOfMonthOrdinalParse: /(ທີ່)\d{1,2}/,
+ ordinal : function (number) {
+ return 'ທີ່' + number;
+ }
+});
+
+return lo;
+
+})));
+
+
+/***/ }),
+/* 71 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Lithuanian [lt]
+//! author : Mindaugas Mozūras : https://github.com/mmozuras
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var units = {
+ 'ss' : 'sekundė_sekundžių_sekundes',
+ 'm' : 'minutė_minutės_minutę',
+ 'mm': 'minutės_minučių_minutes',
+ 'h' : 'valanda_valandos_valandą',
+ 'hh': 'valandos_valandų_valandas',
+ 'd' : 'diena_dienos_dieną',
+ 'dd': 'dienos_dienų_dienas',
+ 'M' : 'mėnuo_mėnesio_mėnesį',
+ 'MM': 'mėnesiai_mėnesių_mėnesius',
+ 'y' : 'metai_metų_metus',
+ 'yy': 'metai_metų_metus'
+};
+function translateSeconds(number, withoutSuffix, key, isFuture) {
+ if (withoutSuffix) {
+ return 'kelios sekundės';
+ } else {
+ return isFuture ? 'kelių sekundžių' : 'kelias sekundes';
+ }
+}
+function translateSingular(number, withoutSuffix, key, isFuture) {
+ return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
+}
+function special(number) {
+ return number % 10 === 0 || (number > 10 && number < 20);
+}
+function forms(key) {
+ return units[key].split('_');
+}
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ if (number === 1) {
+ return result + translateSingular(number, withoutSuffix, key[0], isFuture);
+ } else if (withoutSuffix) {
+ return result + (special(number) ? forms(key)[1] : forms(key)[0]);
+ } else {
+ if (isFuture) {
+ return result + forms(key)[1];
+ } else {
+ return result + (special(number) ? forms(key)[1] : forms(key)[2]);
+ }
+ }
+}
+var lt = moment.defineLocale('lt', {
+ months : {
+ format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'),
+ standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_'),
+ isFormat: /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/
+ },
+ monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'),
+ weekdays : {
+ format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'),
+ standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'),
+ isFormat: /dddd HH:mm/
+ },
+ weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'),
+ weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'YYYY [m.] MMMM D [d.]',
+ LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
+ LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]',
+ l : 'YYYY-MM-DD',
+ ll : 'YYYY [m.] MMMM D [d.]',
+ lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
+ llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]'
+ },
+ calendar : {
+ sameDay : '[Šiandien] LT',
+ nextDay : '[Rytoj] LT',
+ nextWeek : 'dddd LT',
+ lastDay : '[Vakar] LT',
+ lastWeek : '[Praėjusį] dddd LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'po %s',
+ past : 'prieš %s',
+ s : translateSeconds,
+ ss : translate,
+ m : translateSingular,
+ mm : translate,
+ h : translateSingular,
+ hh : translate,
+ d : translateSingular,
+ dd : translate,
+ M : translateSingular,
+ MM : translate,
+ y : translateSingular,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-oji/,
+ ordinal : function (number) {
+ return number + '-oji';
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return lt;
+
+})));
+
+
+/***/ }),
+/* 72 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Latvian [lv]
+//! author : Kristaps Karlsons : https://github.com/skakri
+//! author : Jānis Elmeris : https://github.com/JanisE
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var units = {
+ 'ss': 'sekundes_sekundēm_sekunde_sekundes'.split('_'),
+ 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
+ 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
+ 'h': 'stundas_stundām_stunda_stundas'.split('_'),
+ 'hh': 'stundas_stundām_stunda_stundas'.split('_'),
+ 'd': 'dienas_dienām_diena_dienas'.split('_'),
+ 'dd': 'dienas_dienām_diena_dienas'.split('_'),
+ 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
+ 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
+ 'y': 'gada_gadiem_gads_gadi'.split('_'),
+ 'yy': 'gada_gadiem_gads_gadi'.split('_')
+};
+/**
+ * @param withoutSuffix boolean true = a length of time; false = before/after a period of time.
+ */
+function format(forms, number, withoutSuffix) {
+ if (withoutSuffix) {
+ // E.g. "21 minūte", "3 minūtes".
+ return number % 10 === 1 && number % 100 !== 11 ? forms[2] : forms[3];
+ } else {
+ // E.g. "21 minūtes" as in "pēc 21 minūtes".
+ // E.g. "3 minūtēm" as in "pēc 3 minūtēm".
+ return number % 10 === 1 && number % 100 !== 11 ? forms[0] : forms[1];
+ }
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ return number + ' ' + format(units[key], number, withoutSuffix);
+}
+function relativeTimeWithSingular(number, withoutSuffix, key) {
+ return format(units[key], number, withoutSuffix);
+}
+function relativeSeconds(number, withoutSuffix) {
+ return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm';
+}
+
+var lv = moment.defineLocale('lv', {
+ months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'),
+ weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'),
+ weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'),
+ weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY.',
+ LL : 'YYYY. [gada] D. MMMM',
+ LLL : 'YYYY. [gada] D. MMMM, HH:mm',
+ LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm'
+ },
+ calendar : {
+ sameDay : '[Šodien pulksten] LT',
+ nextDay : '[Rīt pulksten] LT',
+ nextWeek : 'dddd [pulksten] LT',
+ lastDay : '[Vakar pulksten] LT',
+ lastWeek : '[Pagājušā] dddd [pulksten] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'pēc %s',
+ past : 'pirms %s',
+ s : relativeSeconds,
+ ss : relativeTimeWithPlural,
+ m : relativeTimeWithSingular,
+ mm : relativeTimeWithPlural,
+ h : relativeTimeWithSingular,
+ hh : relativeTimeWithPlural,
+ d : relativeTimeWithSingular,
+ dd : relativeTimeWithPlural,
+ M : relativeTimeWithSingular,
+ MM : relativeTimeWithPlural,
+ y : relativeTimeWithSingular,
+ yy : relativeTimeWithPlural
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return lv;
+
+})));
+
+
+/***/ }),
+/* 73 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Montenegrin [me]
+//! author : Miodrag Nikač <miodrag@restartit.me> : https://github.com/miodragnikac
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var translator = {
+ words: { //Different grammatical cases
+ ss: ['sekund', 'sekunda', 'sekundi'],
+ m: ['jedan minut', 'jednog minuta'],
+ mm: ['minut', 'minuta', 'minuta'],
+ h: ['jedan sat', 'jednog sata'],
+ hh: ['sat', 'sata', 'sati'],
+ dd: ['dan', 'dana', 'dana'],
+ MM: ['mjesec', 'mjeseca', 'mjeseci'],
+ yy: ['godina', 'godine', 'godina']
+ },
+ correctGrammaticalCase: function (number, wordKey) {
+ return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+ },
+ translate: function (number, withoutSuffix, key) {
+ var wordKey = translator.words[key];
+ if (key.length === 1) {
+ return withoutSuffix ? wordKey[0] : wordKey[1];
+ } else {
+ return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
+ }
+ }
+};
+
+var me = moment.defineLocale('me', {
+ months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
+ monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
+ monthsParseExact : true,
+ weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+ weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+ weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L: 'DD.MM.YYYY',
+ LL: 'D. MMMM YYYY',
+ LLL: 'D. MMMM YYYY H:mm',
+ LLLL: 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar: {
+ sameDay: '[danas u] LT',
+ nextDay: '[sjutra u] LT',
+
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[u] [nedjelju] [u] LT';
+ case 3:
+ return '[u] [srijedu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[u] dddd [u] LT';
+ }
+ },
+ lastDay : '[juče u] LT',
+ lastWeek : function () {
+ var lastWeekDays = [
+ '[prošle] [nedjelje] [u] LT',
+ '[prošlog] [ponedjeljka] [u] LT',
+ '[prošlog] [utorka] [u] LT',
+ '[prošle] [srijede] [u] LT',
+ '[prošlog] [četvrtka] [u] LT',
+ '[prošlog] [petka] [u] LT',
+ '[prošle] [subote] [u] LT'
+ ];
+ return lastWeekDays[this.day()];
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'prije %s',
+ s : 'nekoliko sekundi',
+ ss : translator.translate,
+ m : translator.translate,
+ mm : translator.translate,
+ h : translator.translate,
+ hh : translator.translate,
+ d : 'dan',
+ dd : translator.translate,
+ M : 'mjesec',
+ MM : translator.translate,
+ y : 'godinu',
+ yy : translator.translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return me;
+
+})));
+
+
+/***/ }),
+/* 74 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Maori [mi]
+//! author : John Corrigan <robbiecloset@gmail.com> : https://github.com/johnideal
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var mi = moment.defineLocale('mi', {
+ months: 'Kohi-tāte_Hui-tanguru_Poutū-te-rangi_Paenga-whāwhā_Haratua_Pipiri_Hōngoingoi_Here-turi-kōkā_Mahuru_Whiringa-ā-nuku_Whiringa-ā-rangi_Hakihea'.split('_'),
+ monthsShort: 'Kohi_Hui_Pou_Pae_Hara_Pipi_Hōngoi_Here_Mahu_Whi-nu_Whi-ra_Haki'.split('_'),
+ monthsRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
+ monthsStrictRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
+ monthsShortRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
+ monthsShortStrictRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,2}/i,
+ weekdays: 'Rātapu_Mane_Tūrei_Wenerei_Tāite_Paraire_Hātarei'.split('_'),
+ weekdaysShort: 'Ta_Ma_Tū_We_Tāi_Pa_Hā'.split('_'),
+ weekdaysMin: 'Ta_Ma_Tū_We_Tāi_Pa_Hā'.split('_'),
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY [i] HH:mm',
+ LLLL: 'dddd, D MMMM YYYY [i] HH:mm'
+ },
+ calendar: {
+ sameDay: '[i teie mahana, i] LT',
+ nextDay: '[apopo i] LT',
+ nextWeek: 'dddd [i] LT',
+ lastDay: '[inanahi i] LT',
+ lastWeek: 'dddd [whakamutunga i] LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: 'i roto i %s',
+ past: '%s i mua',
+ s: 'te hēkona ruarua',
+ ss: '%d hēkona',
+ m: 'he meneti',
+ mm: '%d meneti',
+ h: 'te haora',
+ hh: '%d haora',
+ d: 'he ra',
+ dd: '%d ra',
+ M: 'he marama',
+ MM: '%d marama',
+ y: 'he tau',
+ yy: '%d tau'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}º/,
+ ordinal: '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return mi;
+
+})));
+
+
+/***/ }),
+/* 75 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Macedonian [mk]
+//! author : Borislav Mickov : https://github.com/B0k0
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var mk = moment.defineLocale('mk', {
+ months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'),
+ monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'),
+ weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'),
+ weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'),
+ weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'D.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY H:mm',
+ LLLL : 'dddd, D MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[Денес во] LT',
+ nextDay : '[Утре во] LT',
+ nextWeek : '[Во] dddd [во] LT',
+ lastDay : '[Вчера во] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ case 6:
+ return '[Изминатата] dddd [во] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[Изминатиот] dddd [во] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'после %s',
+ past : 'пред %s',
+ s : 'неколку секунди',
+ ss : '%d секунди',
+ m : 'минута',
+ mm : '%d минути',
+ h : 'час',
+ hh : '%d часа',
+ d : 'ден',
+ dd : '%d дена',
+ M : 'месец',
+ MM : '%d месеци',
+ y : 'година',
+ yy : '%d години'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+ ordinal : function (number) {
+ var lastDigit = number % 10,
+ last2Digits = number % 100;
+ if (number === 0) {
+ return number + '-ев';
+ } else if (last2Digits === 0) {
+ return number + '-ен';
+ } else if (last2Digits > 10 && last2Digits < 20) {
+ return number + '-ти';
+ } else if (lastDigit === 1) {
+ return number + '-ви';
+ } else if (lastDigit === 2) {
+ return number + '-ри';
+ } else if (lastDigit === 7 || lastDigit === 8) {
+ return number + '-ми';
+ } else {
+ return number + '-ти';
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return mk;
+
+})));
+
+
+/***/ }),
+/* 76 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Malayalam [ml]
+//! author : Floyd Pink : https://github.com/floydpink
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ml = moment.defineLocale('ml', {
+ months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'),
+ monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'),
+ weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'),
+ weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm -നു',
+ LTS : 'A h:mm:ss -നു',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm -നു',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm -നു'
+ },
+ calendar : {
+ sameDay : '[ഇന്ന്] LT',
+ nextDay : '[നാളെ] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[ഇന്നലെ] LT',
+ lastWeek : '[കഴിഞ്ഞ] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s കഴിഞ്ഞ്',
+ past : '%s മുൻപ്',
+ s : 'അൽപ നിമിഷങ്ങൾ',
+ ss : '%d സെക്കൻഡ്',
+ m : 'ഒരു മിനിറ്റ്',
+ mm : '%d മിനിറ്റ്',
+ h : 'ഒരു മണിക്കൂർ',
+ hh : '%d മണിക്കൂർ',
+ d : 'ഒരു ദിവസം',
+ dd : '%d ദിവസം',
+ M : 'ഒരു മാസം',
+ MM : '%d മാസം',
+ y : 'ഒരു വർഷം',
+ yy : '%d വർഷം'
+ },
+ meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if ((meridiem === 'രാത്രി' && hour >= 4) ||
+ meridiem === 'ഉച്ച കഴിഞ്ഞ്' ||
+ meridiem === 'വൈകുന്നേരം') {
+ return hour + 12;
+ } else {
+ return hour;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'രാത്രി';
+ } else if (hour < 12) {
+ return 'രാവിലെ';
+ } else if (hour < 17) {
+ return 'ഉച്ച കഴിഞ്ഞ്';
+ } else if (hour < 20) {
+ return 'വൈകുന്നേരം';
+ } else {
+ return 'രാത്രി';
+ }
+ }
+});
+
+return ml;
+
+})));
+
+
+/***/ }),
+/* 77 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Marathi [mr]
+//! author : Harshad Kale : https://github.com/kalehv
+//! author : Vivek Athalye : https://github.com/vnathalye
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '१',
+ '2': '२',
+ '3': '३',
+ '4': '४',
+ '5': '५',
+ '6': '६',
+ '7': '७',
+ '8': '८',
+ '9': '९',
+ '0': '०'
+};
+var numberMap = {
+ '१': '1',
+ '२': '2',
+ '३': '3',
+ '४': '4',
+ '५': '5',
+ '६': '6',
+ '७': '7',
+ '८': '8',
+ '९': '9',
+ '०': '0'
+};
+
+function relativeTimeMr(number, withoutSuffix, string, isFuture)
+{
+ var output = '';
+ if (withoutSuffix) {
+ switch (string) {
+ case 's': output = 'काही सेकंद'; break;
+ case 'ss': output = '%d सेकंद'; break;
+ case 'm': output = 'एक मिनिट'; break;
+ case 'mm': output = '%d मिनिटे'; break;
+ case 'h': output = 'एक तास'; break;
+ case 'hh': output = '%d तास'; break;
+ case 'd': output = 'एक दिवस'; break;
+ case 'dd': output = '%d दिवस'; break;
+ case 'M': output = 'एक महिना'; break;
+ case 'MM': output = '%d महिने'; break;
+ case 'y': output = 'एक वर्ष'; break;
+ case 'yy': output = '%d वर्षे'; break;
+ }
+ }
+ else {
+ switch (string) {
+ case 's': output = 'काही सेकंदां'; break;
+ case 'ss': output = '%d सेकंदां'; break;
+ case 'm': output = 'एका मिनिटा'; break;
+ case 'mm': output = '%d मिनिटां'; break;
+ case 'h': output = 'एका तासा'; break;
+ case 'hh': output = '%d तासां'; break;
+ case 'd': output = 'एका दिवसा'; break;
+ case 'dd': output = '%d दिवसां'; break;
+ case 'M': output = 'एका महिन्या'; break;
+ case 'MM': output = '%d महिन्यां'; break;
+ case 'y': output = 'एका वर्षा'; break;
+ case 'yy': output = '%d वर्षां'; break;
+ }
+ }
+ return output.replace(/%d/i, number);
+}
+
+var mr = moment.defineLocale('mr', {
+ months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'),
+ monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
+ weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'),
+ weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm वाजता',
+ LTS : 'A h:mm:ss वाजता',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm वाजता',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता'
+ },
+ calendar : {
+ sameDay : '[आज] LT',
+ nextDay : '[उद्या] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[काल] LT',
+ lastWeek: '[मागील] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future: '%sमध्ये',
+ past: '%sपूर्वी',
+ s: relativeTimeMr,
+ ss: relativeTimeMr,
+ m: relativeTimeMr,
+ mm: relativeTimeMr,
+ h: relativeTimeMr,
+ hh: relativeTimeMr,
+ d: relativeTimeMr,
+ dd: relativeTimeMr,
+ M: relativeTimeMr,
+ MM: relativeTimeMr,
+ y: relativeTimeMr,
+ yy: relativeTimeMr
+ },
+ preparse: function (string) {
+ return string.replace(/[१२३४५६७८९०]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'रात्री') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'सकाळी') {
+ return hour;
+ } else if (meridiem === 'दुपारी') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'सायंकाळी') {
+ return hour + 12;
+ }
+ },
+ meridiem: function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'रात्री';
+ } else if (hour < 10) {
+ return 'सकाळी';
+ } else if (hour < 17) {
+ return 'दुपारी';
+ } else if (hour < 20) {
+ return 'सायंकाळी';
+ } else {
+ return 'रात्री';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return mr;
+
+})));
+
+
+/***/ }),
+/* 78 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Malay [ms]
+//! author : Weldan Jamili : https://github.com/weldan
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ms = moment.defineLocale('ms', {
+ months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
+ monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
+ weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+ weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
+ weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [pukul] HH.mm',
+ LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+ },
+ meridiemParse: /pagi|tengahari|petang|malam/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'pagi') {
+ return hour;
+ } else if (meridiem === 'tengahari') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'petang' || meridiem === 'malam') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'pagi';
+ } else if (hours < 15) {
+ return 'tengahari';
+ } else if (hours < 19) {
+ return 'petang';
+ } else {
+ return 'malam';
+ }
+ },
+ calendar : {
+ sameDay : '[Hari ini pukul] LT',
+ nextDay : '[Esok pukul] LT',
+ nextWeek : 'dddd [pukul] LT',
+ lastDay : '[Kelmarin pukul] LT',
+ lastWeek : 'dddd [lepas pukul] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dalam %s',
+ past : '%s yang lepas',
+ s : 'beberapa saat',
+ ss : '%d saat',
+ m : 'seminit',
+ mm : '%d minit',
+ h : 'sejam',
+ hh : '%d jam',
+ d : 'sehari',
+ dd : '%d hari',
+ M : 'sebulan',
+ MM : '%d bulan',
+ y : 'setahun',
+ yy : '%d tahun'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ms;
+
+})));
+
+
+/***/ }),
+/* 79 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Malay [ms-my]
+//! note : DEPRECATED, the correct one is [ms]
+//! author : Weldan Jamili : https://github.com/weldan
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var msMy = moment.defineLocale('ms-my', {
+ months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
+ monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
+ weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+ weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
+ weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [pukul] HH.mm',
+ LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+ },
+ meridiemParse: /pagi|tengahari|petang|malam/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'pagi') {
+ return hour;
+ } else if (meridiem === 'tengahari') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'petang' || meridiem === 'malam') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'pagi';
+ } else if (hours < 15) {
+ return 'tengahari';
+ } else if (hours < 19) {
+ return 'petang';
+ } else {
+ return 'malam';
+ }
+ },
+ calendar : {
+ sameDay : '[Hari ini pukul] LT',
+ nextDay : '[Esok pukul] LT',
+ nextWeek : 'dddd [pukul] LT',
+ lastDay : '[Kelmarin pukul] LT',
+ lastWeek : 'dddd [lepas pukul] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dalam %s',
+ past : '%s yang lepas',
+ s : 'beberapa saat',
+ ss : '%d saat',
+ m : 'seminit',
+ mm : '%d minit',
+ h : 'sejam',
+ hh : '%d jam',
+ d : 'sehari',
+ dd : '%d hari',
+ M : 'sebulan',
+ MM : '%d bulan',
+ y : 'setahun',
+ yy : '%d tahun'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return msMy;
+
+})));
+
+
+/***/ }),
+/* 80 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Maltese (Malta) [mt]
+//! author : Alessandro Maruccia : https://github.com/alesma
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var mt = moment.defineLocale('mt', {
+ months : 'Jannar_Frar_Marzu_April_Mejju_Ġunju_Lulju_Awwissu_Settembru_Ottubru_Novembru_Diċembru'.split('_'),
+ monthsShort : 'Jan_Fra_Mar_Apr_Mej_Ġun_Lul_Aww_Set_Ott_Nov_Diċ'.split('_'),
+ weekdays : 'Il-Ħadd_It-Tnejn_It-Tlieta_L-Erbgħa_Il-Ħamis_Il-Ġimgħa_Is-Sibt'.split('_'),
+ weekdaysShort : 'Ħad_Tne_Tli_Erb_Ħam_Ġim_Sib'.split('_'),
+ weekdaysMin : 'Ħa_Tn_Tl_Er_Ħa_Ġi_Si'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Illum fil-]LT',
+ nextDay : '[Għada fil-]LT',
+ nextWeek : 'dddd [fil-]LT',
+ lastDay : '[Il-bieraħ fil-]LT',
+ lastWeek : 'dddd [li għadda] [fil-]LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'f’ %s',
+ past : '%s ilu',
+ s : 'ftit sekondi',
+ ss : '%d sekondi',
+ m : 'minuta',
+ mm : '%d minuti',
+ h : 'siegħa',
+ hh : '%d siegħat',
+ d : 'ġurnata',
+ dd : '%d ġranet',
+ M : 'xahar',
+ MM : '%d xhur',
+ y : 'sena',
+ yy : '%d sni'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal: '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return mt;
+
+})));
+
+
+/***/ }),
+/* 81 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Burmese [my]
+//! author : Squar team, mysquar.com
+//! author : David Rossellat : https://github.com/gholadr
+//! author : Tin Aung Lin : https://github.com/thanyawzinmin
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '၁',
+ '2': '၂',
+ '3': '၃',
+ '4': '၄',
+ '5': '၅',
+ '6': '၆',
+ '7': '၇',
+ '8': '၈',
+ '9': '၉',
+ '0': '၀'
+};
+var numberMap = {
+ '၁': '1',
+ '၂': '2',
+ '၃': '3',
+ '၄': '4',
+ '၅': '5',
+ '၆': '6',
+ '၇': '7',
+ '၈': '8',
+ '၉': '9',
+ '၀': '0'
+};
+
+var my = moment.defineLocale('my', {
+ months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'),
+ monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'),
+ weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'),
+ weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
+ weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
+
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY HH:mm',
+ LLLL: 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar: {
+ sameDay: '[ယနေ.] LT [မှာ]',
+ nextDay: '[မနက်ဖြန်] LT [မှာ]',
+ nextWeek: 'dddd LT [မှာ]',
+ lastDay: '[မနေ.က] LT [မှာ]',
+ lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: 'လာမည့် %s မှာ',
+ past: 'လွန်ခဲ့သော %s က',
+ s: 'စက္ကန်.အနည်းငယ်',
+ ss : '%d စက္ကန့်',
+ m: 'တစ်မိနစ်',
+ mm: '%d မိနစ်',
+ h: 'တစ်နာရီ',
+ hh: '%d နာရီ',
+ d: 'တစ်ရက်',
+ dd: '%d ရက်',
+ M: 'တစ်လ',
+ MM: '%d လ',
+ y: 'တစ်နှစ်',
+ yy: '%d နှစ်'
+ },
+ preparse: function (string) {
+ return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ week: {
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return my;
+
+})));
+
+
+/***/ }),
+/* 82 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Norwegian Bokmål [nb]
+//! authors : Espen Hovlandsdal : https://github.com/rexxars
+//! Sigurd Gartmann : https://github.com/sigurdga
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var nb = moment.defineLocale('nb', {
+ months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+ monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
+ weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'),
+ weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY [kl.] HH:mm',
+ LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
+ },
+ calendar : {
+ sameDay: '[i dag kl.] LT',
+ nextDay: '[i morgen kl.] LT',
+ nextWeek: 'dddd [kl.] LT',
+ lastDay: '[i går kl.] LT',
+ lastWeek: '[forrige] dddd [kl.] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'om %s',
+ past : '%s siden',
+ s : 'noen sekunder',
+ ss : '%d sekunder',
+ m : 'ett minutt',
+ mm : '%d minutter',
+ h : 'en time',
+ hh : '%d timer',
+ d : 'en dag',
+ dd : '%d dager',
+ M : 'en måned',
+ MM : '%d måneder',
+ y : 'ett år',
+ yy : '%d år'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return nb;
+
+})));
+
+
+/***/ }),
+/* 83 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Nepalese [ne]
+//! author : suvash : https://github.com/suvash
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '१',
+ '2': '२',
+ '3': '३',
+ '4': '४',
+ '5': '५',
+ '6': '६',
+ '7': '७',
+ '8': '८',
+ '9': '९',
+ '0': '०'
+};
+var numberMap = {
+ '१': '1',
+ '२': '2',
+ '३': '3',
+ '४': '4',
+ '५': '5',
+ '६': '6',
+ '७': '7',
+ '८': '8',
+ '९': '9',
+ '०': '0'
+};
+
+var ne = moment.defineLocale('ne', {
+ months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'),
+ monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'),
+ weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'),
+ weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'Aको h:mm बजे',
+ LTS : 'Aको h:mm:ss बजे',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, Aको h:mm बजे',
+ LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे'
+ },
+ preparse: function (string) {
+ return string.replace(/[१२३४५६७८९०]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /राति|बिहान|दिउँसो|साँझ/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'राति') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'बिहान') {
+ return hour;
+ } else if (meridiem === 'दिउँसो') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'साँझ') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 3) {
+ return 'राति';
+ } else if (hour < 12) {
+ return 'बिहान';
+ } else if (hour < 16) {
+ return 'दिउँसो';
+ } else if (hour < 20) {
+ return 'साँझ';
+ } else {
+ return 'राति';
+ }
+ },
+ calendar : {
+ sameDay : '[आज] LT',
+ nextDay : '[भोलि] LT',
+ nextWeek : '[आउँदो] dddd[,] LT',
+ lastDay : '[हिजो] LT',
+ lastWeek : '[गएको] dddd[,] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%sमा',
+ past : '%s अगाडि',
+ s : 'केही क्षण',
+ ss : '%d सेकेण्ड',
+ m : 'एक मिनेट',
+ mm : '%d मिनेट',
+ h : 'एक घण्टा',
+ hh : '%d घण्टा',
+ d : 'एक दिन',
+ dd : '%d दिन',
+ M : 'एक महिना',
+ MM : '%d महिना',
+ y : 'एक बर्ष',
+ yy : '%d बर्ष'
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ne;
+
+})));
+
+
+/***/ }),
+/* 84 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Dutch [nl]
+//! author : Joris Röling : https://github.com/jorisroling
+//! author : Jacob Middag : https://github.com/middagj
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_');
+var monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
+
+var monthsParse = [/^jan/i, /^feb/i, /^maart|mrt.?$/i, /^apr/i, /^mei$/i, /^jun[i.]?$/i, /^jul[i.]?$/i, /^aug/i, /^sep/i, /^okt/i, /^nov/i, /^dec/i];
+var monthsRegex = /^(januari|februari|maart|april|mei|april|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;
+
+var nl = moment.defineLocale('nl', {
+ months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortWithDots;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShortWithoutDots[m.month()];
+ } else {
+ return monthsShortWithDots[m.month()];
+ }
+ },
+
+ monthsRegex: monthsRegex,
+ monthsShortRegex: monthsRegex,
+ monthsStrictRegex: /^(januari|februari|maart|mei|ju[nl]i|april|augustus|september|oktober|november|december)/i,
+ monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
+
+ monthsParse : monthsParse,
+ longMonthsParse : monthsParse,
+ shortMonthsParse : monthsParse,
+
+ weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
+ weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
+ weekdaysMin : 'zo_ma_di_wo_do_vr_za'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD-MM-YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[vandaag om] LT',
+ nextDay: '[morgen om] LT',
+ nextWeek: 'dddd [om] LT',
+ lastDay: '[gisteren om] LT',
+ lastWeek: '[afgelopen] dddd [om] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'over %s',
+ past : '%s geleden',
+ s : 'een paar seconden',
+ ss : '%d seconden',
+ m : 'één minuut',
+ mm : '%d minuten',
+ h : 'één uur',
+ hh : '%d uur',
+ d : 'één dag',
+ dd : '%d dagen',
+ M : 'één maand',
+ MM : '%d maanden',
+ y : 'één jaar',
+ yy : '%d jaar'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
+ ordinal : function (number) {
+ return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return nl;
+
+})));
+
+
+/***/ }),
+/* 85 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Dutch (Belgium) [nl-be]
+//! author : Joris Röling : https://github.com/jorisroling
+//! author : Jacob Middag : https://github.com/middagj
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_');
+var monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
+
+var monthsParse = [/^jan/i, /^feb/i, /^maart|mrt.?$/i, /^apr/i, /^mei$/i, /^jun[i.]?$/i, /^jul[i.]?$/i, /^aug/i, /^sep/i, /^okt/i, /^nov/i, /^dec/i];
+var monthsRegex = /^(januari|februari|maart|april|mei|april|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;
+
+var nlBe = moment.defineLocale('nl-be', {
+ months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortWithDots;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShortWithoutDots[m.month()];
+ } else {
+ return monthsShortWithDots[m.month()];
+ }
+ },
+
+ monthsRegex: monthsRegex,
+ monthsShortRegex: monthsRegex,
+ monthsStrictRegex: /^(januari|februari|maart|mei|ju[nl]i|april|augustus|september|oktober|november|december)/i,
+ monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
+
+ monthsParse : monthsParse,
+ longMonthsParse : monthsParse,
+ shortMonthsParse : monthsParse,
+
+ weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
+ weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
+ weekdaysMin : 'zo_ma_di_wo_do_vr_za'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[vandaag om] LT',
+ nextDay: '[morgen om] LT',
+ nextWeek: 'dddd [om] LT',
+ lastDay: '[gisteren om] LT',
+ lastWeek: '[afgelopen] dddd [om] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'over %s',
+ past : '%s geleden',
+ s : 'een paar seconden',
+ ss : '%d seconden',
+ m : 'één minuut',
+ mm : '%d minuten',
+ h : 'één uur',
+ hh : '%d uur',
+ d : 'één dag',
+ dd : '%d dagen',
+ M : 'één maand',
+ MM : '%d maanden',
+ y : 'één jaar',
+ yy : '%d jaar'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
+ ordinal : function (number) {
+ return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return nlBe;
+
+})));
+
+
+/***/ }),
+/* 86 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Nynorsk [nn]
+//! author : https://github.com/mechuwind
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var nn = moment.defineLocale('nn', {
+ months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+ weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'),
+ weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'),
+ weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY [kl.] H:mm',
+ LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
+ },
+ calendar : {
+ sameDay: '[I dag klokka] LT',
+ nextDay: '[I morgon klokka] LT',
+ nextWeek: 'dddd [klokka] LT',
+ lastDay: '[I går klokka] LT',
+ lastWeek: '[Føregåande] dddd [klokka] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'om %s',
+ past : '%s sidan',
+ s : 'nokre sekund',
+ ss : '%d sekund',
+ m : 'eit minutt',
+ mm : '%d minutt',
+ h : 'ein time',
+ hh : '%d timar',
+ d : 'ein dag',
+ dd : '%d dagar',
+ M : 'ein månad',
+ MM : '%d månader',
+ y : 'eit år',
+ yy : '%d år'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return nn;
+
+})));
+
+
+/***/ }),
+/* 87 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Punjabi (India) [pa-in]
+//! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '੧',
+ '2': '੨',
+ '3': '੩',
+ '4': '੪',
+ '5': '੫',
+ '6': '੬',
+ '7': '੭',
+ '8': '੮',
+ '9': '੯',
+ '0': '੦'
+};
+var numberMap = {
+ '੧': '1',
+ '੨': '2',
+ '੩': '3',
+ '੪': '4',
+ '੫': '5',
+ '੬': '6',
+ '੭': '7',
+ '੮': '8',
+ '੯': '9',
+ '੦': '0'
+};
+
+var paIn = moment.defineLocale('pa-in', {
+ // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi.
+ months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
+ monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
+ weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'),
+ weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
+ weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm ਵਜੇ',
+ LTS : 'A h:mm:ss ਵਜੇ',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm ਵਜੇ',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ'
+ },
+ calendar : {
+ sameDay : '[ਅਜ] LT',
+ nextDay : '[ਕਲ] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[ਕਲ] LT',
+ lastWeek : '[ਪਿਛਲੇ] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ਵਿੱਚ',
+ past : '%s ਪਿਛਲੇ',
+ s : 'ਕੁਝ ਸਕਿੰਟ',
+ ss : '%d ਸਕਿੰਟ',
+ m : 'ਇਕ ਮਿੰਟ',
+ mm : '%d ਮਿੰਟ',
+ h : 'ਇੱਕ ਘੰਟਾ',
+ hh : '%d ਘੰਟੇ',
+ d : 'ਇੱਕ ਦਿਨ',
+ dd : '%d ਦਿਨ',
+ M : 'ਇੱਕ ਮਹੀਨਾ',
+ MM : '%d ਮਹੀਨੇ',
+ y : 'ਇੱਕ ਸਾਲ',
+ yy : '%d ਸਾਲ'
+ },
+ preparse: function (string) {
+ return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ // Punjabi notation for meridiems are quite fuzzy in practice. While there exists
+ // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi.
+ meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'ਰਾਤ') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'ਸਵੇਰ') {
+ return hour;
+ } else if (meridiem === 'ਦੁਪਹਿਰ') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'ਸ਼ਾਮ') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ਰਾਤ';
+ } else if (hour < 10) {
+ return 'ਸਵੇਰ';
+ } else if (hour < 17) {
+ return 'ਦੁਪਹਿਰ';
+ } else if (hour < 20) {
+ return 'ਸ਼ਾਮ';
+ } else {
+ return 'ਰਾਤ';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return paIn;
+
+})));
+
+
+/***/ }),
+/* 88 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Polish [pl]
+//! author : Rafal Hirsz : https://github.com/evoL
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_');
+var monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_');
+function plural(n) {
+ return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
+}
+function translate(number, withoutSuffix, key) {
+ var result = number + ' ';
+ switch (key) {
+ case 'ss':
+ return result + (plural(number) ? 'sekundy' : 'sekund');
+ case 'm':
+ return withoutSuffix ? 'minuta' : 'minutę';
+ case 'mm':
+ return result + (plural(number) ? 'minuty' : 'minut');
+ case 'h':
+ return withoutSuffix ? 'godzina' : 'godzinę';
+ case 'hh':
+ return result + (plural(number) ? 'godziny' : 'godzin');
+ case 'MM':
+ return result + (plural(number) ? 'miesiące' : 'miesięcy');
+ case 'yy':
+ return result + (plural(number) ? 'lata' : 'lat');
+ }
+}
+
+var pl = moment.defineLocale('pl', {
+ months : function (momentToFormat, format) {
+ if (!momentToFormat) {
+ return monthsNominative;
+ } else if (format === '') {
+ // Hack: if format empty we know this is used to generate
+ // RegExp by moment. Give then back both valid forms of months
+ // in RegExp ready format.
+ return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')';
+ } else if (/D MMMM/.test(format)) {
+ return monthsSubjective[momentToFormat.month()];
+ } else {
+ return monthsNominative[momentToFormat.month()];
+ }
+ },
+ monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'),
+ weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'),
+ weekdaysShort : 'ndz_pon_wt_śr_czw_pt_sob'.split('_'),
+ weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Dziś o] LT',
+ nextDay: '[Jutro o] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[W niedzielę o] LT';
+
+ case 2:
+ return '[We wtorek o] LT';
+
+ case 3:
+ return '[W środę o] LT';
+
+ case 6:
+ return '[W sobotę o] LT';
+
+ default:
+ return '[W] dddd [o] LT';
+ }
+ },
+ lastDay: '[Wczoraj o] LT',
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[W zeszłą niedzielę o] LT';
+ case 3:
+ return '[W zeszłą środę o] LT';
+ case 6:
+ return '[W zeszłą sobotę o] LT';
+ default:
+ return '[W zeszły] dddd [o] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : '%s temu',
+ s : 'kilka sekund',
+ ss : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : '1 dzień',
+ dd : '%d dni',
+ M : 'miesiąc',
+ MM : translate,
+ y : 'rok',
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return pl;
+
+})));
+
+
+/***/ }),
+/* 89 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Portuguese [pt]
+//! author : Jefferson : https://github.com/jalex79
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var pt = moment.defineLocale('pt', {
+ months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'),
+ monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
+ weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
+ weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
+ weekdaysMin : 'Do_2ª_3ª_4ª_5ª_6ª_Sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY HH:mm',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Hoje às] LT',
+ nextDay: '[Amanhã às] LT',
+ nextWeek: 'dddd [às] LT',
+ lastDay: '[Ontem às] LT',
+ lastWeek: function () {
+ return (this.day() === 0 || this.day() === 6) ?
+ '[Último] dddd [às] LT' : // Saturday + Sunday
+ '[Última] dddd [às] LT'; // Monday - Friday
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'em %s',
+ past : 'há %s',
+ s : 'segundos',
+ ss : '%d segundos',
+ m : 'um minuto',
+ mm : '%d minutos',
+ h : 'uma hora',
+ hh : '%d horas',
+ d : 'um dia',
+ dd : '%d dias',
+ M : 'um mês',
+ MM : '%d meses',
+ y : 'um ano',
+ yy : '%d anos'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}º/,
+ ordinal : '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return pt;
+
+})));
+
+
+/***/ }),
+/* 90 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Portuguese (Brazil) [pt-br]
+//! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ptBr = moment.defineLocale('pt-br', {
+ months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'),
+ monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
+ weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
+ weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
+ weekdaysMin : 'Do_2ª_3ª_4ª_5ª_6ª_Sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY [às] HH:mm',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm'
+ },
+ calendar : {
+ sameDay: '[Hoje às] LT',
+ nextDay: '[Amanhã às] LT',
+ nextWeek: 'dddd [às] LT',
+ lastDay: '[Ontem às] LT',
+ lastWeek: function () {
+ return (this.day() === 0 || this.day() === 6) ?
+ '[Último] dddd [às] LT' : // Saturday + Sunday
+ '[Última] dddd [às] LT'; // Monday - Friday
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'em %s',
+ past : '%s atrás',
+ s : 'poucos segundos',
+ ss : '%d segundos',
+ m : 'um minuto',
+ mm : '%d minutos',
+ h : 'uma hora',
+ hh : '%d horas',
+ d : 'um dia',
+ dd : '%d dias',
+ M : 'um mês',
+ MM : '%d meses',
+ y : 'um ano',
+ yy : '%d anos'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}º/,
+ ordinal : '%dº'
+});
+
+return ptBr;
+
+})));
+
+
+/***/ }),
+/* 91 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Romanian [ro]
+//! author : Vlad Gurdiga : https://github.com/gurdiga
+//! author : Valentin Agachi : https://github.com/avaly
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ var format = {
+ 'ss': 'secunde',
+ 'mm': 'minute',
+ 'hh': 'ore',
+ 'dd': 'zile',
+ 'MM': 'luni',
+ 'yy': 'ani'
+ },
+ separator = ' ';
+ if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
+ separator = ' de ';
+ }
+ return number + separator + format[key];
+}
+
+var ro = moment.defineLocale('ro', {
+ months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'),
+ monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'),
+ weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'),
+ weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY H:mm',
+ LLLL : 'dddd, D MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay: '[azi la] LT',
+ nextDay: '[mâine la] LT',
+ nextWeek: 'dddd [la] LT',
+ lastDay: '[ieri la] LT',
+ lastWeek: '[fosta] dddd [la] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'peste %s',
+ past : '%s în urmă',
+ s : 'câteva secunde',
+ ss : relativeTimeWithPlural,
+ m : 'un minut',
+ mm : relativeTimeWithPlural,
+ h : 'o oră',
+ hh : relativeTimeWithPlural,
+ d : 'o zi',
+ dd : relativeTimeWithPlural,
+ M : 'o lună',
+ MM : relativeTimeWithPlural,
+ y : 'un an',
+ yy : relativeTimeWithPlural
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ro;
+
+})));
+
+
+/***/ }),
+/* 92 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Russian [ru]
+//! author : Viktorminator : https://github.com/Viktorminator
+//! Author : Menelion Elensúle : https://github.com/Oire
+//! author : Коренберг Марк : https://github.com/socketpair
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function plural(word, num) {
+ var forms = word.split('_');
+ return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ var format = {
+ 'ss': withoutSuffix ? 'секунда_секунды_секунд' : 'секунду_секунды_секунд',
+ 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
+ 'hh': 'час_часа_часов',
+ 'dd': 'день_дня_дней',
+ 'MM': 'месяц_месяца_месяцев',
+ 'yy': 'год_года_лет'
+ };
+ if (key === 'm') {
+ return withoutSuffix ? 'минута' : 'минуту';
+ }
+ else {
+ return number + ' ' + plural(format[key], +number);
+ }
+}
+var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i];
+
+// http://new.gramota.ru/spravka/rules/139-prop : § 103
+// Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637
+// CLDR data: http://www.unicode.org/cldr/charts/28/summary/ru.html#1753
+var ru = moment.defineLocale('ru', {
+ months : {
+ format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'),
+ standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_')
+ },
+ monthsShort : {
+ // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ?
+ format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'),
+ standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_')
+ },
+ weekdays : {
+ standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
+ format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'),
+ isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/
+ },
+ weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
+ weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
+ monthsParse : monthsParse,
+ longMonthsParse : monthsParse,
+ shortMonthsParse : monthsParse,
+
+ // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки
+ monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
+
+ // копия предыдущего
+ monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
+
+ // полные названия с падежами
+ monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,
+
+ // Выражение, которое соотвествует только сокращённым формам
+ monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY г.',
+ LLL : 'D MMMM YYYY г., H:mm',
+ LLLL : 'dddd, D MMMM YYYY г., H:mm'
+ },
+ calendar : {
+ sameDay: '[Сегодня в] LT',
+ nextDay: '[Завтра в] LT',
+ lastDay: '[Вчера в] LT',
+ nextWeek: function (now) {
+ if (now.week() !== this.week()) {
+ switch (this.day()) {
+ case 0:
+ return '[В следующее] dddd [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[В следующий] dddd [в] LT';
+ case 3:
+ case 5:
+ case 6:
+ return '[В следующую] dddd [в] LT';
+ }
+ } else {
+ if (this.day() === 2) {
+ return '[Во] dddd [в] LT';
+ } else {
+ return '[В] dddd [в] LT';
+ }
+ }
+ },
+ lastWeek: function (now) {
+ if (now.week() !== this.week()) {
+ switch (this.day()) {
+ case 0:
+ return '[В прошлое] dddd [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[В прошлый] dddd [в] LT';
+ case 3:
+ case 5:
+ case 6:
+ return '[В прошлую] dddd [в] LT';
+ }
+ } else {
+ if (this.day() === 2) {
+ return '[Во] dddd [в] LT';
+ } else {
+ return '[В] dddd [в] LT';
+ }
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'через %s',
+ past : '%s назад',
+ s : 'несколько секунд',
+ ss : relativeTimeWithPlural,
+ m : relativeTimeWithPlural,
+ mm : relativeTimeWithPlural,
+ h : 'час',
+ hh : relativeTimeWithPlural,
+ d : 'день',
+ dd : relativeTimeWithPlural,
+ M : 'месяц',
+ MM : relativeTimeWithPlural,
+ y : 'год',
+ yy : relativeTimeWithPlural
+ },
+ meridiemParse: /ночи|утра|дня|вечера/i,
+ isPM : function (input) {
+ return /^(дня|вечера)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ночи';
+ } else if (hour < 12) {
+ return 'утра';
+ } else if (hour < 17) {
+ return 'дня';
+ } else {
+ return 'вечера';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(й|го|я)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ return number + '-й';
+ case 'D':
+ return number + '-го';
+ case 'w':
+ case 'W':
+ return number + '-я';
+ default:
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return ru;
+
+})));
+
+
+/***/ }),
+/* 93 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Sindhi [sd]
+//! author : Narain Sagar : https://github.com/narainsagar
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = [
+ 'جنوري',
+ 'فيبروري',
+ 'مارچ',
+ 'اپريل',
+ 'مئي',
+ 'جون',
+ 'جولاءِ',
+ 'آگسٽ',
+ 'سيپٽمبر',
+ 'آڪٽوبر',
+ 'نومبر',
+ 'ڊسمبر'
+];
+var days = [
+ 'آچر',
+ 'سومر',
+ 'اڱارو',
+ 'اربع',
+ 'خميس',
+ 'جمع',
+ 'ڇنڇر'
+];
+
+var sd = moment.defineLocale('sd', {
+ months : months,
+ monthsShort : months,
+ weekdays : days,
+ weekdaysShort : days,
+ weekdaysMin : days,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd، D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /صبح|شام/,
+ isPM : function (input) {
+ return 'شام' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'صبح';
+ }
+ return 'شام';
+ },
+ calendar : {
+ sameDay : '[اڄ] LT',
+ nextDay : '[سڀاڻي] LT',
+ nextWeek : 'dddd [اڳين هفتي تي] LT',
+ lastDay : '[ڪالهه] LT',
+ lastWeek : '[گزريل هفتي] dddd [تي] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s پوء',
+ past : '%s اڳ',
+ s : 'چند سيڪنڊ',
+ ss : '%d سيڪنڊ',
+ m : 'هڪ منٽ',
+ mm : '%d منٽ',
+ h : 'هڪ ڪلاڪ',
+ hh : '%d ڪلاڪ',
+ d : 'هڪ ڏينهن',
+ dd : '%d ڏينهن',
+ M : 'هڪ مهينو',
+ MM : '%d مهينا',
+ y : 'هڪ سال',
+ yy : '%d سال'
+ },
+ preparse: function (string) {
+ return string.replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/,/g, '،');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return sd;
+
+})));
+
+
+/***/ }),
+/* 94 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Northern Sami [se]
+//! authors : Bård Rolstad Henriksen : https://github.com/karamell
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+
+var se = moment.defineLocale('se', {
+ months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'),
+ monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'),
+ weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'),
+ weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'),
+ weekdaysMin : 's_v_m_g_d_b_L'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'MMMM D. [b.] YYYY',
+ LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm',
+ LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm'
+ },
+ calendar : {
+ sameDay: '[otne ti] LT',
+ nextDay: '[ihttin ti] LT',
+ nextWeek: 'dddd [ti] LT',
+ lastDay: '[ikte ti] LT',
+ lastWeek: '[ovddit] dddd [ti] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : '%s geažes',
+ past : 'maŋit %s',
+ s : 'moadde sekunddat',
+ ss: '%d sekunddat',
+ m : 'okta minuhta',
+ mm : '%d minuhtat',
+ h : 'okta diimmu',
+ hh : '%d diimmut',
+ d : 'okta beaivi',
+ dd : '%d beaivvit',
+ M : 'okta mánnu',
+ MM : '%d mánut',
+ y : 'okta jahki',
+ yy : '%d jagit'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return se;
+
+})));
+
+
+/***/ }),
+/* 95 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Sinhalese [si]
+//! author : Sampath Sitinamaluwa : https://github.com/sampathsris
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+/*jshint -W100*/
+var si = moment.defineLocale('si', {
+ months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'),
+ monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'),
+ weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'),
+ weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන'.split('_'),
+ weekdaysMin : 'ඉ_ස_අ_බ_බ්‍ර_සි_සෙ'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'a h:mm',
+ LTS : 'a h:mm:ss',
+ L : 'YYYY/MM/DD',
+ LL : 'YYYY MMMM D',
+ LLL : 'YYYY MMMM D, a h:mm',
+ LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss'
+ },
+ calendar : {
+ sameDay : '[අද] LT[ට]',
+ nextDay : '[හෙට] LT[ට]',
+ nextWeek : 'dddd LT[ට]',
+ lastDay : '[ඊයේ] LT[ට]',
+ lastWeek : '[පසුගිය] dddd LT[ට]',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%sකින්',
+ past : '%sකට පෙර',
+ s : 'තත්පර කිහිපය',
+ ss : 'තත්පර %d',
+ m : 'මිනිත්තුව',
+ mm : 'මිනිත්තු %d',
+ h : 'පැය',
+ hh : 'පැය %d',
+ d : 'දිනය',
+ dd : 'දින %d',
+ M : 'මාසය',
+ MM : 'මාස %d',
+ y : 'වසර',
+ yy : 'වසර %d'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2} වැනි/,
+ ordinal : function (number) {
+ return number + ' වැනි';
+ },
+ meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,
+ isPM : function (input) {
+ return input === 'ප.ව.' || input === 'පස් වරු';
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'ප.ව.' : 'පස් වරු';
+ } else {
+ return isLower ? 'පෙ.ව.' : 'පෙර වරු';
+ }
+ }
+});
+
+return si;
+
+})));
+
+
+/***/ }),
+/* 96 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Slovak [sk]
+//! author : Martin Minka : https://github.com/k2s
+//! based on work of petrbela : https://github.com/petrbela
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_');
+var monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_');
+function plural(n) {
+ return (n > 1) && (n < 5);
+}
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ switch (key) {
+ case 's': // a few seconds / in a few seconds / a few seconds ago
+ return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
+ case 'ss': // 9 seconds / in 9 seconds / 9 seconds ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'sekundy' : 'sekúnd');
+ } else {
+ return result + 'sekundami';
+ }
+ break;
+ case 'm': // a minute / in a minute / a minute ago
+ return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
+ case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'minúty' : 'minút');
+ } else {
+ return result + 'minútami';
+ }
+ break;
+ case 'h': // an hour / in an hour / an hour ago
+ return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+ case 'hh': // 9 hours / in 9 hours / 9 hours ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'hodiny' : 'hodín');
+ } else {
+ return result + 'hodinami';
+ }
+ break;
+ case 'd': // a day / in a day / a day ago
+ return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
+ case 'dd': // 9 days / in 9 days / 9 days ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'dni' : 'dní');
+ } else {
+ return result + 'dňami';
+ }
+ break;
+ case 'M': // a month / in a month / a month ago
+ return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
+ case 'MM': // 9 months / in 9 months / 9 months ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'mesiace' : 'mesiacov');
+ } else {
+ return result + 'mesiacmi';
+ }
+ break;
+ case 'y': // a year / in a year / a year ago
+ return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
+ case 'yy': // 9 years / in 9 years / 9 years ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'roky' : 'rokov');
+ } else {
+ return result + 'rokmi';
+ }
+ break;
+ }
+}
+
+var sk = moment.defineLocale('sk', {
+ months : months,
+ monthsShort : monthsShort,
+ weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'),
+ weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'),
+ weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'),
+ longDateFormat : {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay: '[dnes o] LT',
+ nextDay: '[zajtra o] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[v nedeľu o] LT';
+ case 1:
+ case 2:
+ return '[v] dddd [o] LT';
+ case 3:
+ return '[v stredu o] LT';
+ case 4:
+ return '[vo štvrtok o] LT';
+ case 5:
+ return '[v piatok o] LT';
+ case 6:
+ return '[v sobotu o] LT';
+ }
+ },
+ lastDay: '[včera o] LT',
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[minulú nedeľu o] LT';
+ case 1:
+ case 2:
+ return '[minulý] dddd [o] LT';
+ case 3:
+ return '[minulú stredu o] LT';
+ case 4:
+ case 5:
+ return '[minulý] dddd [o] LT';
+ case 6:
+ return '[minulú sobotu o] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'pred %s',
+ s : translate,
+ ss : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return sk;
+
+})));
+
+
+/***/ }),
+/* 97 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Slovenian [sl]
+//! author : Robert Sedovšek : https://github.com/sedovsek
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ switch (key) {
+ case 's':
+ return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami';
+ case 'ss':
+ if (number === 1) {
+ result += withoutSuffix ? 'sekundo' : 'sekundi';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'sekundi' : 'sekundah';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'sekunde' : 'sekundah';
+ } else {
+ result += withoutSuffix || isFuture ? 'sekund' : 'sekund';
+ }
+ return result;
+ case 'm':
+ return withoutSuffix ? 'ena minuta' : 'eno minuto';
+ case 'mm':
+ if (number === 1) {
+ result += withoutSuffix ? 'minuta' : 'minuto';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'minuti' : 'minutama';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'minute' : 'minutami';
+ } else {
+ result += withoutSuffix || isFuture ? 'minut' : 'minutami';
+ }
+ return result;
+ case 'h':
+ return withoutSuffix ? 'ena ura' : 'eno uro';
+ case 'hh':
+ if (number === 1) {
+ result += withoutSuffix ? 'ura' : 'uro';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'uri' : 'urama';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'ure' : 'urami';
+ } else {
+ result += withoutSuffix || isFuture ? 'ur' : 'urami';
+ }
+ return result;
+ case 'd':
+ return withoutSuffix || isFuture ? 'en dan' : 'enim dnem';
+ case 'dd':
+ if (number === 1) {
+ result += withoutSuffix || isFuture ? 'dan' : 'dnem';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'dni' : 'dnevoma';
+ } else {
+ result += withoutSuffix || isFuture ? 'dni' : 'dnevi';
+ }
+ return result;
+ case 'M':
+ return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem';
+ case 'MM':
+ if (number === 1) {
+ result += withoutSuffix || isFuture ? 'mesec' : 'mesecem';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'meseca' : 'mesecema';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'mesece' : 'meseci';
+ } else {
+ result += withoutSuffix || isFuture ? 'mesecev' : 'meseci';
+ }
+ return result;
+ case 'y':
+ return withoutSuffix || isFuture ? 'eno leto' : 'enim letom';
+ case 'yy':
+ if (number === 1) {
+ result += withoutSuffix || isFuture ? 'leto' : 'letom';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'leti' : 'letoma';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'leta' : 'leti';
+ } else {
+ result += withoutSuffix || isFuture ? 'let' : 'leti';
+ }
+ return result;
+ }
+}
+
+var sl = moment.defineLocale('sl', {
+ months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'),
+ monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'),
+ weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'),
+ weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[danes ob] LT',
+ nextDay : '[jutri ob] LT',
+
+ nextWeek : function () {
+ switch (this.day()) {
+ case 0:
+ return '[v] [nedeljo] [ob] LT';
+ case 3:
+ return '[v] [sredo] [ob] LT';
+ case 6:
+ return '[v] [soboto] [ob] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[v] dddd [ob] LT';
+ }
+ },
+ lastDay : '[včeraj ob] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ return '[prejšnjo] [nedeljo] [ob] LT';
+ case 3:
+ return '[prejšnjo] [sredo] [ob] LT';
+ case 6:
+ return '[prejšnjo] [soboto] [ob] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[prejšnji] dddd [ob] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'čez %s',
+ past : 'pred %s',
+ s : processRelativeTime,
+ ss : processRelativeTime,
+ m : processRelativeTime,
+ mm : processRelativeTime,
+ h : processRelativeTime,
+ hh : processRelativeTime,
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return sl;
+
+})));
+
+
+/***/ }),
+/* 98 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Albanian [sq]
+//! author : Flakërim Ismani : https://github.com/flakerimi
+//! author : Menelion Elensúle : https://github.com/Oire
+//! author : Oerd Cukalla : https://github.com/oerd
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var sq = moment.defineLocale('sq', {
+ months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'),
+ monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'),
+ weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'),
+ weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'),
+ weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'),
+ weekdaysParseExact : true,
+ meridiemParse: /PD|MD/,
+ isPM: function (input) {
+ return input.charAt(0) === 'M';
+ },
+ meridiem : function (hours, minutes, isLower) {
+ return hours < 12 ? 'PD' : 'MD';
+ },
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Sot në] LT',
+ nextDay : '[Nesër në] LT',
+ nextWeek : 'dddd [në] LT',
+ lastDay : '[Dje në] LT',
+ lastWeek : 'dddd [e kaluar në] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'në %s',
+ past : '%s më parë',
+ s : 'disa sekonda',
+ ss : '%d sekonda',
+ m : 'një minutë',
+ mm : '%d minuta',
+ h : 'një orë',
+ hh : '%d orë',
+ d : 'një ditë',
+ dd : '%d ditë',
+ M : 'një muaj',
+ MM : '%d muaj',
+ y : 'një vit',
+ yy : '%d vite'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return sq;
+
+})));
+
+
+/***/ }),
+/* 99 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Serbian [sr]
+//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var translator = {
+ words: { //Different grammatical cases
+ ss: ['sekunda', 'sekunde', 'sekundi'],
+ m: ['jedan minut', 'jedne minute'],
+ mm: ['minut', 'minute', 'minuta'],
+ h: ['jedan sat', 'jednog sata'],
+ hh: ['sat', 'sata', 'sati'],
+ dd: ['dan', 'dana', 'dana'],
+ MM: ['mesec', 'meseca', 'meseci'],
+ yy: ['godina', 'godine', 'godina']
+ },
+ correctGrammaticalCase: function (number, wordKey) {
+ return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+ },
+ translate: function (number, withoutSuffix, key) {
+ var wordKey = translator.words[key];
+ if (key.length === 1) {
+ return withoutSuffix ? wordKey[0] : wordKey[1];
+ } else {
+ return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
+ }
+ }
+};
+
+var sr = moment.defineLocale('sr', {
+ months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
+ monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'),
+ weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'),
+ weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L: 'DD.MM.YYYY',
+ LL: 'D. MMMM YYYY',
+ LLL: 'D. MMMM YYYY H:mm',
+ LLLL: 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar: {
+ sameDay: '[danas u] LT',
+ nextDay: '[sutra u] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[u] [nedelju] [u] LT';
+ case 3:
+ return '[u] [sredu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[u] dddd [u] LT';
+ }
+ },
+ lastDay : '[juče u] LT',
+ lastWeek : function () {
+ var lastWeekDays = [
+ '[prošle] [nedelje] [u] LT',
+ '[prošlog] [ponedeljka] [u] LT',
+ '[prošlog] [utorka] [u] LT',
+ '[prošle] [srede] [u] LT',
+ '[prošlog] [četvrtka] [u] LT',
+ '[prošlog] [petka] [u] LT',
+ '[prošle] [subote] [u] LT'
+ ];
+ return lastWeekDays[this.day()];
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'pre %s',
+ s : 'nekoliko sekundi',
+ ss : translator.translate,
+ m : translator.translate,
+ mm : translator.translate,
+ h : translator.translate,
+ hh : translator.translate,
+ d : 'dan',
+ dd : translator.translate,
+ M : 'mesec',
+ MM : translator.translate,
+ y : 'godinu',
+ yy : translator.translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return sr;
+
+})));
+
+
+/***/ }),
+/* 100 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Serbian Cyrillic [sr-cyrl]
+//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var translator = {
+ words: { //Different grammatical cases
+ ss: ['секунда', 'секунде', 'секунди'],
+ m: ['један минут', 'једне минуте'],
+ mm: ['минут', 'минуте', 'минута'],
+ h: ['један сат', 'једног сата'],
+ hh: ['сат', 'сата', 'сати'],
+ dd: ['дан', 'дана', 'дана'],
+ MM: ['месец', 'месеца', 'месеци'],
+ yy: ['година', 'године', 'година']
+ },
+ correctGrammaticalCase: function (number, wordKey) {
+ return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+ },
+ translate: function (number, withoutSuffix, key) {
+ var wordKey = translator.words[key];
+ if (key.length === 1) {
+ return withoutSuffix ? wordKey[0] : wordKey[1];
+ } else {
+ return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
+ }
+ }
+};
+
+var srCyrl = moment.defineLocale('sr-cyrl', {
+ months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'),
+ monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'),
+ monthsParseExact: true,
+ weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'),
+ weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'),
+ weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L: 'DD.MM.YYYY',
+ LL: 'D. MMMM YYYY',
+ LLL: 'D. MMMM YYYY H:mm',
+ LLLL: 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar: {
+ sameDay: '[данас у] LT',
+ nextDay: '[сутра у] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[у] [недељу] [у] LT';
+ case 3:
+ return '[у] [среду] [у] LT';
+ case 6:
+ return '[у] [суботу] [у] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[у] dddd [у] LT';
+ }
+ },
+ lastDay : '[јуче у] LT',
+ lastWeek : function () {
+ var lastWeekDays = [
+ '[прошле] [недеље] [у] LT',
+ '[прошлог] [понедељка] [у] LT',
+ '[прошлог] [уторка] [у] LT',
+ '[прошле] [среде] [у] LT',
+ '[прошлог] [четвртка] [у] LT',
+ '[прошлог] [петка] [у] LT',
+ '[прошле] [суботе] [у] LT'
+ ];
+ return lastWeekDays[this.day()];
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'за %s',
+ past : 'пре %s',
+ s : 'неколико секунди',
+ ss : translator.translate,
+ m : translator.translate,
+ mm : translator.translate,
+ h : translator.translate,
+ hh : translator.translate,
+ d : 'дан',
+ dd : translator.translate,
+ M : 'месец',
+ MM : translator.translate,
+ y : 'годину',
+ yy : translator.translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return srCyrl;
+
+})));
+
+
+/***/ }),
+/* 101 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : siSwati [ss]
+//! author : Nicolai Davies<mail@nicolai.io> : https://github.com/nicolaidavies
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+
+var ss = moment.defineLocale('ss', {
+ months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'),
+ monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'),
+ weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'),
+ weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'),
+ weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Namuhla nga] LT',
+ nextDay : '[Kusasa nga] LT',
+ nextWeek : 'dddd [nga] LT',
+ lastDay : '[Itolo nga] LT',
+ lastWeek : 'dddd [leliphelile] [nga] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'nga %s',
+ past : 'wenteka nga %s',
+ s : 'emizuzwana lomcane',
+ ss : '%d mzuzwana',
+ m : 'umzuzu',
+ mm : '%d emizuzu',
+ h : 'lihora',
+ hh : '%d emahora',
+ d : 'lilanga',
+ dd : '%d emalanga',
+ M : 'inyanga',
+ MM : '%d tinyanga',
+ y : 'umnyaka',
+ yy : '%d iminyaka'
+ },
+ meridiemParse: /ekuseni|emini|entsambama|ebusuku/,
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'ekuseni';
+ } else if (hours < 15) {
+ return 'emini';
+ } else if (hours < 19) {
+ return 'entsambama';
+ } else {
+ return 'ebusuku';
+ }
+ },
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'ekuseni') {
+ return hour;
+ } else if (meridiem === 'emini') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') {
+ if (hour === 0) {
+ return 0;
+ }
+ return hour + 12;
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}/,
+ ordinal : '%d',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return ss;
+
+})));
+
+
+/***/ }),
+/* 102 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Swedish [sv]
+//! author : Jens Alm : https://github.com/ulmus
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var sv = moment.defineLocale('sv', {
+ months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
+ weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'),
+ weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'),
+ weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [kl.] HH:mm',
+ LLLL : 'dddd D MMMM YYYY [kl.] HH:mm',
+ lll : 'D MMM YYYY HH:mm',
+ llll : 'ddd D MMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Idag] LT',
+ nextDay: '[Imorgon] LT',
+ lastDay: '[Igår] LT',
+ nextWeek: '[På] dddd LT',
+ lastWeek: '[I] dddd[s] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'om %s',
+ past : 'för %s sedan',
+ s : 'några sekunder',
+ ss : '%d sekunder',
+ m : 'en minut',
+ mm : '%d minuter',
+ h : 'en timme',
+ hh : '%d timmar',
+ d : 'en dag',
+ dd : '%d dagar',
+ M : 'en månad',
+ MM : '%d månader',
+ y : 'ett år',
+ yy : '%d år'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(e|a)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'e' :
+ (b === 1) ? 'a' :
+ (b === 2) ? 'a' :
+ (b === 3) ? 'e' : 'e';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return sv;
+
+})));
+
+
+/***/ }),
+/* 103 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Swahili [sw]
+//! author : Fahad Kassim : https://github.com/fadsel
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var sw = moment.defineLocale('sw', {
+ months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'),
+ monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'),
+ weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'),
+ weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'),
+ weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[leo saa] LT',
+ nextDay : '[kesho saa] LT',
+ nextWeek : '[wiki ijayo] dddd [saat] LT',
+ lastDay : '[jana] LT',
+ lastWeek : '[wiki iliyopita] dddd [saat] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s baadaye',
+ past : 'tokea %s',
+ s : 'hivi punde',
+ ss : 'sekunde %d',
+ m : 'dakika moja',
+ mm : 'dakika %d',
+ h : 'saa limoja',
+ hh : 'masaa %d',
+ d : 'siku moja',
+ dd : 'masiku %d',
+ M : 'mwezi mmoja',
+ MM : 'miezi %d',
+ y : 'mwaka mmoja',
+ yy : 'miaka %d'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return sw;
+
+})));
+
+
+/***/ }),
+/* 104 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Tamil [ta]
+//! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '௧',
+ '2': '௨',
+ '3': '௩',
+ '4': '௪',
+ '5': '௫',
+ '6': '௬',
+ '7': '௭',
+ '8': '௮',
+ '9': '௯',
+ '0': '௦'
+};
+var numberMap = {
+ '௧': '1',
+ '௨': '2',
+ '௩': '3',
+ '௪': '4',
+ '௫': '5',
+ '௬': '6',
+ '௭': '7',
+ '௮': '8',
+ '௯': '9',
+ '௦': '0'
+};
+
+var ta = moment.defineLocale('ta', {
+ months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
+ monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
+ weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'),
+ weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'),
+ weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, HH:mm',
+ LLLL : 'dddd, D MMMM YYYY, HH:mm'
+ },
+ calendar : {
+ sameDay : '[இன்று] LT',
+ nextDay : '[நாளை] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[நேற்று] LT',
+ lastWeek : '[கடந்த வாரம்] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s இல்',
+ past : '%s முன்',
+ s : 'ஒரு சில விநாடிகள்',
+ ss : '%d விநாடிகள்',
+ m : 'ஒரு நிமிடம்',
+ mm : '%d நிமிடங்கள்',
+ h : 'ஒரு மணி நேரம்',
+ hh : '%d மணி நேரம்',
+ d : 'ஒரு நாள்',
+ dd : '%d நாட்கள்',
+ M : 'ஒரு மாதம்',
+ MM : '%d மாதங்கள்',
+ y : 'ஒரு வருடம்',
+ yy : '%d ஆண்டுகள்'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}வது/,
+ ordinal : function (number) {
+ return number + 'வது';
+ },
+ preparse: function (string) {
+ return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ // refer http://ta.wikipedia.org/s/1er1
+ meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 2) {
+ return ' யாமம்';
+ } else if (hour < 6) {
+ return ' வைகறை'; // வைகறை
+ } else if (hour < 10) {
+ return ' காலை'; // காலை
+ } else if (hour < 14) {
+ return ' நண்பகல்'; // நண்பகல்
+ } else if (hour < 18) {
+ return ' எற்பாடு'; // எற்பாடு
+ } else if (hour < 22) {
+ return ' மாலை'; // மாலை
+ } else {
+ return ' யாமம்';
+ }
+ },
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'யாமம்') {
+ return hour < 2 ? hour : hour + 12;
+ } else if (meridiem === 'வைகறை' || meridiem === 'காலை') {
+ return hour;
+ } else if (meridiem === 'நண்பகல்') {
+ return hour >= 10 ? hour : hour + 12;
+ } else {
+ return hour + 12;
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ta;
+
+})));
+
+
+/***/ }),
+/* 105 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Telugu [te]
+//! author : Krishna Chaitanya Thota : https://github.com/kcthota
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var te = moment.defineLocale('te', {
+ months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'),
+ monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'),
+ weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'),
+ weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm',
+ LTS : 'A h:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm'
+ },
+ calendar : {
+ sameDay : '[నేడు] LT',
+ nextDay : '[రేపు] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[నిన్న] LT',
+ lastWeek : '[గత] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s లో',
+ past : '%s క్రితం',
+ s : 'కొన్ని క్షణాలు',
+ ss : '%d సెకన్లు',
+ m : 'ఒక నిమిషం',
+ mm : '%d నిమిషాలు',
+ h : 'ఒక గంట',
+ hh : '%d గంటలు',
+ d : 'ఒక రోజు',
+ dd : '%d రోజులు',
+ M : 'ఒక నెల',
+ MM : '%d నెలలు',
+ y : 'ఒక సంవత్సరం',
+ yy : '%d సంవత్సరాలు'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}వ/,
+ ordinal : '%dవ',
+ meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'రాత్రి') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'ఉదయం') {
+ return hour;
+ } else if (meridiem === 'మధ్యాహ్నం') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'సాయంత్రం') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'రాత్రి';
+ } else if (hour < 10) {
+ return 'ఉదయం';
+ } else if (hour < 17) {
+ return 'మధ్యాహ్నం';
+ } else if (hour < 20) {
+ return 'సాయంత్రం';
+ } else {
+ return 'రాత్రి';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return te;
+
+})));
+
+
+/***/ }),
+/* 106 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Tetun Dili (East Timor) [tet]
+//! author : Joshua Brooks : https://github.com/joshbrooks
+//! author : Onorio De J. Afonso : https://github.com/marobo
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var tet = moment.defineLocale('tet', {
+ months : 'Janeiru_Fevereiru_Marsu_Abril_Maiu_Juniu_Juliu_Augustu_Setembru_Outubru_Novembru_Dezembru'.split('_'),
+ monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Aug_Set_Out_Nov_Dez'.split('_'),
+ weekdays : 'Domingu_Segunda_Tersa_Kuarta_Kinta_Sexta_Sabadu'.split('_'),
+ weekdaysShort : 'Dom_Seg_Ters_Kua_Kint_Sext_Sab'.split('_'),
+ weekdaysMin : 'Do_Seg_Te_Ku_Ki_Sex_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Ohin iha] LT',
+ nextDay: '[Aban iha] LT',
+ nextWeek: 'dddd [iha] LT',
+ lastDay: '[Horiseik iha] LT',
+ lastWeek: 'dddd [semana kotuk] [iha] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'iha %s',
+ past : '%s liuba',
+ s : 'minutu balun',
+ ss : 'minutu %d',
+ m : 'minutu ida',
+ mm : 'minutus %d',
+ h : 'horas ida',
+ hh : 'horas %d',
+ d : 'loron ida',
+ dd : 'loron %d',
+ M : 'fulan ida',
+ MM : 'fulan %d',
+ y : 'tinan ida',
+ yy : 'tinan %d'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return tet;
+
+})));
+
+
+/***/ }),
+/* 107 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Thai [th]
+//! author : Kridsada Thanabulpong : https://github.com/sirn
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var th = moment.defineLocale('th', {
+ months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'),
+ monthsShort : 'ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'),
+ weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference
+ weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY เวลา H:mm',
+ LLLL : 'วันddddที่ D MMMM YYYY เวลา H:mm'
+ },
+ meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/,
+ isPM: function (input) {
+ return input === 'หลังเที่ยง';
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ก่อนเที่ยง';
+ } else {
+ return 'หลังเที่ยง';
+ }
+ },
+ calendar : {
+ sameDay : '[วันนี้ เวลา] LT',
+ nextDay : '[พรุ่งนี้ เวลา] LT',
+ nextWeek : 'dddd[หน้า เวลา] LT',
+ lastDay : '[เมื่อวานนี้ เวลา] LT',
+ lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'อีก %s',
+ past : '%sที่แล้ว',
+ s : 'ไม่กี่วินาที',
+ ss : '%d วินาที',
+ m : '1 นาที',
+ mm : '%d นาที',
+ h : '1 ชั่วโมง',
+ hh : '%d ชั่วโมง',
+ d : '1 วัน',
+ dd : '%d วัน',
+ M : '1 เดือน',
+ MM : '%d เดือน',
+ y : '1 ปี',
+ yy : '%d ปี'
+ }
+});
+
+return th;
+
+})));
+
+
+/***/ }),
+/* 108 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Tagalog (Philippines) [tl-ph]
+//! author : Dan Hagman : https://github.com/hagmandan
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var tlPh = moment.defineLocale('tl-ph', {
+ months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'),
+ monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'),
+ weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'),
+ weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'),
+ weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'MM/D/YYYY',
+ LL : 'MMMM D, YYYY',
+ LLL : 'MMMM D, YYYY HH:mm',
+ LLLL : 'dddd, MMMM DD, YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: 'LT [ngayong araw]',
+ nextDay: '[Bukas ng] LT',
+ nextWeek: 'LT [sa susunod na] dddd',
+ lastDay: 'LT [kahapon]',
+ lastWeek: 'LT [noong nakaraang] dddd',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'sa loob ng %s',
+ past : '%s ang nakalipas',
+ s : 'ilang segundo',
+ ss : '%d segundo',
+ m : 'isang minuto',
+ mm : '%d minuto',
+ h : 'isang oras',
+ hh : '%d oras',
+ d : 'isang araw',
+ dd : '%d araw',
+ M : 'isang buwan',
+ MM : '%d buwan',
+ y : 'isang taon',
+ yy : '%d taon'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}/,
+ ordinal : function (number) {
+ return number;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return tlPh;
+
+})));
+
+
+/***/ }),
+/* 109 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Klingon [tlh]
+//! author : Dominika Kruk : https://github.com/amaranthrose
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_');
+
+function translateFuture(output) {
+ var time = output;
+ time = (output.indexOf('jaj') !== -1) ?
+ time.slice(0, -3) + 'leS' :
+ (output.indexOf('jar') !== -1) ?
+ time.slice(0, -3) + 'waQ' :
+ (output.indexOf('DIS') !== -1) ?
+ time.slice(0, -3) + 'nem' :
+ time + ' pIq';
+ return time;
+}
+
+function translatePast(output) {
+ var time = output;
+ time = (output.indexOf('jaj') !== -1) ?
+ time.slice(0, -3) + 'Hu’' :
+ (output.indexOf('jar') !== -1) ?
+ time.slice(0, -3) + 'wen' :
+ (output.indexOf('DIS') !== -1) ?
+ time.slice(0, -3) + 'ben' :
+ time + ' ret';
+ return time;
+}
+
+function translate(number, withoutSuffix, string, isFuture) {
+ var numberNoun = numberAsNoun(number);
+ switch (string) {
+ case 'ss':
+ return numberNoun + ' lup';
+ case 'mm':
+ return numberNoun + ' tup';
+ case 'hh':
+ return numberNoun + ' rep';
+ case 'dd':
+ return numberNoun + ' jaj';
+ case 'MM':
+ return numberNoun + ' jar';
+ case 'yy':
+ return numberNoun + ' DIS';
+ }
+}
+
+function numberAsNoun(number) {
+ var hundred = Math.floor((number % 1000) / 100),
+ ten = Math.floor((number % 100) / 10),
+ one = number % 10,
+ word = '';
+ if (hundred > 0) {
+ word += numbersNouns[hundred] + 'vatlh';
+ }
+ if (ten > 0) {
+ word += ((word !== '') ? ' ' : '') + numbersNouns[ten] + 'maH';
+ }
+ if (one > 0) {
+ word += ((word !== '') ? ' ' : '') + numbersNouns[one];
+ }
+ return (word === '') ? 'pagh' : word;
+}
+
+var tlh = moment.defineLocale('tlh', {
+ months : 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split('_'),
+ monthsShort : 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
+ weekdaysShort : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
+ weekdaysMin : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[DaHjaj] LT',
+ nextDay: '[wa’leS] LT',
+ nextWeek: 'LLL',
+ lastDay: '[wa’Hu’] LT',
+ lastWeek: 'LLL',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : translateFuture,
+ past : translatePast,
+ s : 'puS lup',
+ ss : translate,
+ m : 'wa’ tup',
+ mm : translate,
+ h : 'wa’ rep',
+ hh : translate,
+ d : 'wa’ jaj',
+ dd : translate,
+ M : 'wa’ jar',
+ MM : translate,
+ y : 'wa’ DIS',
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return tlh;
+
+})));
+
+
+/***/ }),
+/* 110 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Turkish [tr]
+//! authors : Erhan Gundogan : https://github.com/erhangundogan,
+//! Burak Yiğit Kaya: https://github.com/BYK
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+ 1: '\'inci',
+ 5: '\'inci',
+ 8: '\'inci',
+ 70: '\'inci',
+ 80: '\'inci',
+ 2: '\'nci',
+ 7: '\'nci',
+ 20: '\'nci',
+ 50: '\'nci',
+ 3: '\'üncü',
+ 4: '\'üncü',
+ 100: '\'üncü',
+ 6: '\'ncı',
+ 9: '\'uncu',
+ 10: '\'uncu',
+ 30: '\'uncu',
+ 60: '\'ıncı',
+ 90: '\'ıncı'
+};
+
+var tr = moment.defineLocale('tr', {
+ months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
+ monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
+ weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
+ weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
+ weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[bugün saat] LT',
+ nextDay : '[yarın saat] LT',
+ nextWeek : '[gelecek] dddd [saat] LT',
+ lastDay : '[dün] LT',
+ lastWeek : '[geçen] dddd [saat] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s sonra',
+ past : '%s önce',
+ s : 'birkaç saniye',
+ ss : '%d saniye',
+ m : 'bir dakika',
+ mm : '%d dakika',
+ h : 'bir saat',
+ hh : '%d saat',
+ d : 'bir gün',
+ dd : '%d gün',
+ M : 'bir ay',
+ MM : '%d ay',
+ y : 'bir yıl',
+ yy : '%d yıl'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
+ ordinal : function (number) {
+ if (number === 0) { // special case for zero
+ return number + '\'ıncı';
+ }
+ var a = number % 10,
+ b = number % 100 - a,
+ c = number >= 100 ? 100 : null;
+ return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return tr;
+
+})));
+
+
+/***/ }),
+/* 111 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Talossan [tzl]
+//! author : Robin van der Vliet : https://github.com/robin0van0der0v
+//! author : Iustì Canun
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+// After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals.
+// This is currently too difficult (maybe even impossible) to add.
+var tzl = moment.defineLocale('tzl', {
+ months : 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split('_'),
+ monthsShort : 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'),
+ weekdays : 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'),
+ weekdaysShort : 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'),
+ weekdaysMin : 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM [dallas] YYYY',
+ LLL : 'D. MMMM [dallas] YYYY HH.mm',
+ LLLL : 'dddd, [li] D. MMMM [dallas] YYYY HH.mm'
+ },
+ meridiemParse: /d\'o|d\'a/i,
+ isPM : function (input) {
+ return 'd\'o' === input.toLowerCase();
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'd\'o' : 'D\'O';
+ } else {
+ return isLower ? 'd\'a' : 'D\'A';
+ }
+ },
+ calendar : {
+ sameDay : '[oxhi à] LT',
+ nextDay : '[demà à] LT',
+ nextWeek : 'dddd [à] LT',
+ lastDay : '[ieiri à] LT',
+ lastWeek : '[sür el] dddd [lasteu à] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'osprei %s',
+ past : 'ja%s',
+ s : processRelativeTime,
+ ss : processRelativeTime,
+ m : processRelativeTime,
+ mm : processRelativeTime,
+ h : processRelativeTime,
+ hh : processRelativeTime,
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 's': ['viensas secunds', '\'iensas secunds'],
+ 'ss': [number + ' secunds', '' + number + ' secunds'],
+ 'm': ['\'n míut', '\'iens míut'],
+ 'mm': [number + ' míuts', '' + number + ' míuts'],
+ 'h': ['\'n þora', '\'iensa þora'],
+ 'hh': [number + ' þoras', '' + number + ' þoras'],
+ 'd': ['\'n ziua', '\'iensa ziua'],
+ 'dd': [number + ' ziuas', '' + number + ' ziuas'],
+ 'M': ['\'n mes', '\'iens mes'],
+ 'MM': [number + ' mesen', '' + number + ' mesen'],
+ 'y': ['\'n ar', '\'iens ar'],
+ 'yy': [number + ' ars', '' + number + ' ars']
+ };
+ return isFuture ? format[key][0] : (withoutSuffix ? format[key][0] : format[key][1]);
+}
+
+return tzl;
+
+})));
+
+
+/***/ }),
+/* 112 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Central Atlas Tamazight [tzm]
+//! author : Abdel Said : https://github.com/abdelsaid
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var tzm = moment.defineLocale('tzm', {
+ months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
+ monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
+ weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+ weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+ weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[ⴰⵙⴷⵅ ⴴ] LT',
+ nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
+ nextWeek: 'dddd [ⴴ] LT',
+ lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
+ lastWeek: 'dddd [ⴴ] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s',
+ past : 'ⵢⴰⵏ %s',
+ s : 'ⵉⵎⵉⴽ',
+ ss : '%d ⵉⵎⵉⴽ',
+ m : 'ⵎⵉⵏⵓⴺ',
+ mm : '%d ⵎⵉⵏⵓⴺ',
+ h : 'ⵙⴰⵄⴰ',
+ hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ',
+ d : 'ⴰⵙⵙ',
+ dd : '%d oⵙⵙⴰⵏ',
+ M : 'ⴰⵢoⵓⵔ',
+ MM : '%d ⵉⵢⵢⵉⵔⵏ',
+ y : 'ⴰⵙⴳⴰⵙ',
+ yy : '%d ⵉⵙⴳⴰⵙⵏ'
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return tzm;
+
+})));
+
+
+/***/ }),
+/* 113 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Central Atlas Tamazight Latin [tzm-latn]
+//! author : Abdel Said : https://github.com/abdelsaid
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var tzmLatn = moment.defineLocale('tzm-latn', {
+ months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
+ monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
+ weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+ weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+ weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[asdkh g] LT',
+ nextDay: '[aska g] LT',
+ nextWeek: 'dddd [g] LT',
+ lastDay: '[assant g] LT',
+ lastWeek: 'dddd [g] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'dadkh s yan %s',
+ past : 'yan %s',
+ s : 'imik',
+ ss : '%d imik',
+ m : 'minuḍ',
+ mm : '%d minuḍ',
+ h : 'saɛa',
+ hh : '%d tassaɛin',
+ d : 'ass',
+ dd : '%d ossan',
+ M : 'ayowr',
+ MM : '%d iyyirn',
+ y : 'asgas',
+ yy : '%d isgasn'
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return tzmLatn;
+
+})));
+
+
+/***/ }),
+/* 114 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Ukrainian [uk]
+//! author : zemlanin : https://github.com/zemlanin
+//! Author : Menelion Elensúle : https://github.com/Oire
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function plural(word, num) {
+ var forms = word.split('_');
+ return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ var format = {
+ 'ss': withoutSuffix ? 'секунда_секунди_секунд' : 'секунду_секунди_секунд',
+ 'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин',
+ 'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин',
+ 'dd': 'день_дні_днів',
+ 'MM': 'місяць_місяці_місяців',
+ 'yy': 'рік_роки_років'
+ };
+ if (key === 'm') {
+ return withoutSuffix ? 'хвилина' : 'хвилину';
+ }
+ else if (key === 'h') {
+ return withoutSuffix ? 'година' : 'годину';
+ }
+ else {
+ return number + ' ' + plural(format[key], +number);
+ }
+}
+function weekdaysCaseReplace(m, format) {
+ var weekdays = {
+ 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
+ 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
+ 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
+ };
+
+ if (!m) {
+ return weekdays['nominative'];
+ }
+
+ var nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
+ 'accusative' :
+ ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
+ 'genitive' :
+ 'nominative');
+ return weekdays[nounCase][m.day()];
+}
+function processHoursFunction(str) {
+ return function () {
+ return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
+ };
+}
+
+var uk = moment.defineLocale('uk', {
+ months : {
+ 'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'),
+ 'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_')
+ },
+ monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'),
+ weekdays : weekdaysCaseReplace,
+ weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+ weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY р.',
+ LLL : 'D MMMM YYYY р., HH:mm',
+ LLLL : 'dddd, D MMMM YYYY р., HH:mm'
+ },
+ calendar : {
+ sameDay: processHoursFunction('[Сьогодні '),
+ nextDay: processHoursFunction('[Завтра '),
+ lastDay: processHoursFunction('[Вчора '),
+ nextWeek: processHoursFunction('[У] dddd ['),
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ case 5:
+ case 6:
+ return processHoursFunction('[Минулої] dddd [').call(this);
+ case 1:
+ case 2:
+ case 4:
+ return processHoursFunction('[Минулого] dddd [').call(this);
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'за %s',
+ past : '%s тому',
+ s : 'декілька секунд',
+ ss : relativeTimeWithPlural,
+ m : relativeTimeWithPlural,
+ mm : relativeTimeWithPlural,
+ h : 'годину',
+ hh : relativeTimeWithPlural,
+ d : 'день',
+ dd : relativeTimeWithPlural,
+ M : 'місяць',
+ MM : relativeTimeWithPlural,
+ y : 'рік',
+ yy : relativeTimeWithPlural
+ },
+ // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
+ meridiemParse: /ночі|ранку|дня|вечора/,
+ isPM: function (input) {
+ return /^(дня|вечора)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ночі';
+ } else if (hour < 12) {
+ return 'ранку';
+ } else if (hour < 17) {
+ return 'дня';
+ } else {
+ return 'вечора';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(й|го)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ case 'w':
+ case 'W':
+ return number + '-й';
+ case 'D':
+ return number + '-го';
+ default:
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return uk;
+
+})));
+
+
+/***/ }),
+/* 115 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Urdu [ur]
+//! author : Sawood Alam : https://github.com/ibnesayeed
+//! author : Zack : https://github.com/ZackVision
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = [
+ 'جنوری',
+ 'فروری',
+ 'مارچ',
+ 'اپریل',
+ 'مئی',
+ 'جون',
+ 'جولائی',
+ 'اگست',
+ 'ستمبر',
+ 'اکتوبر',
+ 'نومبر',
+ 'دسمبر'
+];
+var days = [
+ 'اتوار',
+ 'پیر',
+ 'منگل',
+ 'بدھ',
+ 'جمعرات',
+ 'جمعہ',
+ 'ہفتہ'
+];
+
+var ur = moment.defineLocale('ur', {
+ months : months,
+ monthsShort : months,
+ weekdays : days,
+ weekdaysShort : days,
+ weekdaysMin : days,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd، D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /صبح|شام/,
+ isPM : function (input) {
+ return 'شام' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'صبح';
+ }
+ return 'شام';
+ },
+ calendar : {
+ sameDay : '[آج بوقت] LT',
+ nextDay : '[کل بوقت] LT',
+ nextWeek : 'dddd [بوقت] LT',
+ lastDay : '[گذشتہ روز بوقت] LT',
+ lastWeek : '[گذشتہ] dddd [بوقت] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s بعد',
+ past : '%s قبل',
+ s : 'چند سیکنڈ',
+ ss : '%d سیکنڈ',
+ m : 'ایک منٹ',
+ mm : '%d منٹ',
+ h : 'ایک گھنٹہ',
+ hh : '%d گھنٹے',
+ d : 'ایک دن',
+ dd : '%d دن',
+ M : 'ایک ماہ',
+ MM : '%d ماہ',
+ y : 'ایک سال',
+ yy : '%d سال'
+ },
+ preparse: function (string) {
+ return string.replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/,/g, '،');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return ur;
+
+})));
+
+
+/***/ }),
+/* 116 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Uzbek [uz]
+//! author : Sardor Muminov : https://github.com/muminoff
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var uz = moment.defineLocale('uz', {
+ months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'),
+ monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'),
+ weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'),
+ weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'),
+ weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'D MMMM YYYY, dddd HH:mm'
+ },
+ calendar : {
+ sameDay : '[Бугун соат] LT [да]',
+ nextDay : '[Эртага] LT [да]',
+ nextWeek : 'dddd [куни соат] LT [да]',
+ lastDay : '[Кеча соат] LT [да]',
+ lastWeek : '[Утган] dddd [куни соат] LT [да]',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'Якин %s ичида',
+ past : 'Бир неча %s олдин',
+ s : 'фурсат',
+ ss : '%d фурсат',
+ m : 'бир дакика',
+ mm : '%d дакика',
+ h : 'бир соат',
+ hh : '%d соат',
+ d : 'бир кун',
+ dd : '%d кун',
+ M : 'бир ой',
+ MM : '%d ой',
+ y : 'бир йил',
+ yy : '%d йил'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return uz;
+
+})));
+
+
+/***/ }),
+/* 117 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Uzbek Latin [uz-latn]
+//! author : Rasulbek Mirzayev : github.com/Rasulbeeek
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var uzLatn = moment.defineLocale('uz-latn', {
+ months : 'Yanvar_Fevral_Mart_Aprel_May_Iyun_Iyul_Avgust_Sentabr_Oktabr_Noyabr_Dekabr'.split('_'),
+ monthsShort : 'Yan_Fev_Mar_Apr_May_Iyun_Iyul_Avg_Sen_Okt_Noy_Dek'.split('_'),
+ weekdays : 'Yakshanba_Dushanba_Seshanba_Chorshanba_Payshanba_Juma_Shanba'.split('_'),
+ weekdaysShort : 'Yak_Dush_Sesh_Chor_Pay_Jum_Shan'.split('_'),
+ weekdaysMin : 'Ya_Du_Se_Cho_Pa_Ju_Sha'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'D MMMM YYYY, dddd HH:mm'
+ },
+ calendar : {
+ sameDay : '[Bugun soat] LT [da]',
+ nextDay : '[Ertaga] LT [da]',
+ nextWeek : 'dddd [kuni soat] LT [da]',
+ lastDay : '[Kecha soat] LT [da]',
+ lastWeek : '[O\'tgan] dddd [kuni soat] LT [da]',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'Yaqin %s ichida',
+ past : 'Bir necha %s oldin',
+ s : 'soniya',
+ ss : '%d soniya',
+ m : 'bir daqiqa',
+ mm : '%d daqiqa',
+ h : 'bir soat',
+ hh : '%d soat',
+ d : 'bir kun',
+ dd : '%d kun',
+ M : 'bir oy',
+ MM : '%d oy',
+ y : 'bir yil',
+ yy : '%d yil'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return uzLatn;
+
+})));
+
+
+/***/ }),
+/* 118 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Vietnamese [vi]
+//! author : Bang Nguyen : https://github.com/bangnk
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var vi = moment.defineLocale('vi', {
+ months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'),
+ monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'),
+ weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
+ weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
+ weekdaysParseExact : true,
+ meridiemParse: /sa|ch/i,
+ isPM : function (input) {
+ return /^ch$/i.test(input);
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 12) {
+ return isLower ? 'sa' : 'SA';
+ } else {
+ return isLower ? 'ch' : 'CH';
+ }
+ },
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM [năm] YYYY',
+ LLL : 'D MMMM [năm] YYYY HH:mm',
+ LLLL : 'dddd, D MMMM [năm] YYYY HH:mm',
+ l : 'DD/M/YYYY',
+ ll : 'D MMM YYYY',
+ lll : 'D MMM YYYY HH:mm',
+ llll : 'ddd, D MMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Hôm nay lúc] LT',
+ nextDay: '[Ngày mai lúc] LT',
+ nextWeek: 'dddd [tuần tới lúc] LT',
+ lastDay: '[Hôm qua lúc] LT',
+ lastWeek: 'dddd [tuần rồi lúc] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : '%s tới',
+ past : '%s trước',
+ s : 'vài giây',
+ ss : '%d giây' ,
+ m : 'một phút',
+ mm : '%d phút',
+ h : 'một giờ',
+ hh : '%d giờ',
+ d : 'một ngày',
+ dd : '%d ngày',
+ M : 'một tháng',
+ MM : '%d tháng',
+ y : 'một năm',
+ yy : '%d năm'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}/,
+ ordinal : function (number) {
+ return number;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return vi;
+
+})));
+
+
+/***/ }),
+/* 119 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Pseudo [x-pseudo]
+//! author : Andrew Hood : https://github.com/andrewhood125
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var xPseudo = moment.defineLocale('x-pseudo', {
+ months : 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split('_'),
+ monthsShort : 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split('_'),
+ weekdaysShort : 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'),
+ weekdaysMin : 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[T~ódá~ý át] LT',
+ nextDay : '[T~ómó~rró~w át] LT',
+ nextWeek : 'dddd [át] LT',
+ lastDay : '[Ý~ést~érdá~ý át] LT',
+ lastWeek : '[L~ást] dddd [át] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'í~ñ %s',
+ past : '%s á~gó',
+ s : 'á ~féw ~sécó~ñds',
+ ss : '%d s~écóñ~ds',
+ m : 'á ~míñ~úté',
+ mm : '%d m~íñú~tés',
+ h : 'á~ñ hó~úr',
+ hh : '%d h~óúrs',
+ d : 'á ~dáý',
+ dd : '%d d~áýs',
+ M : 'á ~móñ~th',
+ MM : '%d m~óñt~hs',
+ y : 'á ~ýéár',
+ yy : '%d ý~éárs'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return xPseudo;
+
+})));
+
+
+/***/ }),
+/* 120 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Yoruba Nigeria [yo]
+//! author : Atolagbe Abisoye : https://github.com/andela-batolagbe
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var yo = moment.defineLocale('yo', {
+ months : 'Sẹ́rẹ́_Èrèlè_Ẹrẹ̀nà_Ìgbé_Èbibi_Òkùdu_Agẹmo_Ògún_Owewe_Ọ̀wàrà_Bélú_Ọ̀pẹ̀̀'.split('_'),
+ monthsShort : 'Sẹ́r_Èrl_Ẹrn_Ìgb_Èbi_Òkù_Agẹ_Ògú_Owe_Ọ̀wà_Bél_Ọ̀pẹ̀̀'.split('_'),
+ weekdays : 'Àìkú_Ajé_Ìsẹ́gun_Ọjọ́rú_Ọjọ́bọ_Ẹtì_Àbámẹ́ta'.split('_'),
+ weekdaysShort : 'Àìk_Ajé_Ìsẹ́_Ọjr_Ọjb_Ẹtì_Àbá'.split('_'),
+ weekdaysMin : 'Àì_Aj_Ìs_Ọr_Ọb_Ẹt_Àb'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Ònì ni] LT',
+ nextDay : '[Ọ̀la ni] LT',
+ nextWeek : 'dddd [Ọsẹ̀ tón\'bọ] [ni] LT',
+ lastDay : '[Àna ni] LT',
+ lastWeek : 'dddd [Ọsẹ̀ tólọ́] [ni] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'ní %s',
+ past : '%s kọjá',
+ s : 'ìsẹjú aayá die',
+ ss :'aayá %d',
+ m : 'ìsẹjú kan',
+ mm : 'ìsẹjú %d',
+ h : 'wákati kan',
+ hh : 'wákati %d',
+ d : 'ọjọ́ kan',
+ dd : 'ọjọ́ %d',
+ M : 'osù kan',
+ MM : 'osù %d',
+ y : 'ọdún kan',
+ yy : 'ọdún %d'
+ },
+ dayOfMonthOrdinalParse : /ọjọ́\s\d{1,2}/,
+ ordinal : 'ọjọ́ %d',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return yo;
+
+})));
+
+
+/***/ }),
+/* 121 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Chinese (China) [zh-cn]
+//! author : suupic : https://github.com/suupic
+//! author : Zeno Zeng : https://github.com/zenozeng
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var zhCn = moment.defineLocale('zh-cn', {
+ months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+ monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+ weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'),
+ weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY/MM/DD',
+ LL : 'YYYY年M月D日',
+ LLL : 'YYYY年M月D日Ah点mm分',
+ LLLL : 'YYYY年M月D日ddddAh点mm分',
+ l : 'YYYY/M/D',
+ ll : 'YYYY年M月D日',
+ lll : 'YYYY年M月D日 HH:mm',
+ llll : 'YYYY年M月D日dddd HH:mm'
+ },
+ meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === '凌晨' || meridiem === '早上' ||
+ meridiem === '上午') {
+ return hour;
+ } else if (meridiem === '下午' || meridiem === '晚上') {
+ return hour + 12;
+ } else {
+ // '中午'
+ return hour >= 11 ? hour : hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ var hm = hour * 100 + minute;
+ if (hm < 600) {
+ return '凌晨';
+ } else if (hm < 900) {
+ return '早上';
+ } else if (hm < 1130) {
+ return '上午';
+ } else if (hm < 1230) {
+ return '中午';
+ } else if (hm < 1800) {
+ return '下午';
+ } else {
+ return '晚上';
+ }
+ },
+ calendar : {
+ sameDay : '[今天]LT',
+ nextDay : '[明天]LT',
+ nextWeek : '[下]ddddLT',
+ lastDay : '[昨天]LT',
+ lastWeek : '[上]ddddLT',
+ sameElse : 'L'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(日|月|周)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return number + '日';
+ case 'M':
+ return number + '月';
+ case 'w':
+ case 'W':
+ return number + '周';
+ default:
+ return number;
+ }
+ },
+ relativeTime : {
+ future : '%s内',
+ past : '%s前',
+ s : '几秒',
+ ss : '%d 秒',
+ m : '1 分钟',
+ mm : '%d 分钟',
+ h : '1 小时',
+ hh : '%d 小时',
+ d : '1 天',
+ dd : '%d 天',
+ M : '1 个月',
+ MM : '%d 个月',
+ y : '1 年',
+ yy : '%d 年'
+ },
+ week : {
+ // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return zhCn;
+
+})));
+
+
+/***/ }),
+/* 122 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Chinese (Hong Kong) [zh-hk]
+//! author : Ben : https://github.com/ben-lin
+//! author : Chris Lam : https://github.com/hehachris
+//! author : Konstantin : https://github.com/skfd
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var zhHk = moment.defineLocale('zh-hk', {
+ months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+ monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+ weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
+ weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY/MM/DD',
+ LL : 'YYYY年M月D日',
+ LLL : 'YYYY年M月D日 HH:mm',
+ LLLL : 'YYYY年M月D日dddd HH:mm',
+ l : 'YYYY/M/D',
+ ll : 'YYYY年M月D日',
+ lll : 'YYYY年M月D日 HH:mm',
+ llll : 'YYYY年M月D日dddd HH:mm'
+ },
+ meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
+ return hour;
+ } else if (meridiem === '中午') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === '下午' || meridiem === '晚上') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ var hm = hour * 100 + minute;
+ if (hm < 600) {
+ return '凌晨';
+ } else if (hm < 900) {
+ return '早上';
+ } else if (hm < 1130) {
+ return '上午';
+ } else if (hm < 1230) {
+ return '中午';
+ } else if (hm < 1800) {
+ return '下午';
+ } else {
+ return '晚上';
+ }
+ },
+ calendar : {
+ sameDay : '[今天]LT',
+ nextDay : '[明天]LT',
+ nextWeek : '[下]ddddLT',
+ lastDay : '[昨天]LT',
+ lastWeek : '[上]ddddLT',
+ sameElse : 'L'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(日|月|週)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd' :
+ case 'D' :
+ case 'DDD' :
+ return number + '日';
+ case 'M' :
+ return number + '月';
+ case 'w' :
+ case 'W' :
+ return number + '週';
+ default :
+ return number;
+ }
+ },
+ relativeTime : {
+ future : '%s內',
+ past : '%s前',
+ s : '幾秒',
+ ss : '%d 秒',
+ m : '1 分鐘',
+ mm : '%d 分鐘',
+ h : '1 小時',
+ hh : '%d 小時',
+ d : '1 天',
+ dd : '%d 天',
+ M : '1 個月',
+ MM : '%d 個月',
+ y : '1 年',
+ yy : '%d 年'
+ }
+});
+
+return zhHk;
+
+})));
+
+
+/***/ }),
+/* 123 */
+/***/ (function(module, exports, __webpack_require__) {
+
+//! moment.js locale configuration
+//! locale : Chinese (Taiwan) [zh-tw]
+//! author : Ben : https://github.com/ben-lin
+//! author : Chris Lam : https://github.com/hehachris
+
+;(function (global, factory) {
+ true ? factory(__webpack_require__(0)) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var zhTw = moment.defineLocale('zh-tw', {
+ months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+ monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+ weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
+ weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY/MM/DD',
+ LL : 'YYYY年M月D日',
+ LLL : 'YYYY年M月D日 HH:mm',
+ LLLL : 'YYYY年M月D日dddd HH:mm',
+ l : 'YYYY/M/D',
+ ll : 'YYYY年M月D日',
+ lll : 'YYYY年M月D日 HH:mm',
+ llll : 'YYYY年M月D日dddd HH:mm'
+ },
+ meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
+ return hour;
+ } else if (meridiem === '中午') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === '下午' || meridiem === '晚上') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ var hm = hour * 100 + minute;
+ if (hm < 600) {
+ return '凌晨';
+ } else if (hm < 900) {
+ return '早上';
+ } else if (hm < 1130) {
+ return '上午';
+ } else if (hm < 1230) {
+ return '中午';
+ } else if (hm < 1800) {
+ return '下午';
+ } else {
+ return '晚上';
+ }
+ },
+ calendar : {
+ sameDay : '[今天]LT',
+ nextDay : '[明天]LT',
+ nextWeek : '[下]ddddLT',
+ lastDay : '[昨天]LT',
+ lastWeek : '[上]ddddLT',
+ sameElse : 'L'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(日|月|週)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd' :
+ case 'D' :
+ case 'DDD' :
+ return number + '日';
+ case 'M' :
+ return number + '月';
+ case 'w' :
+ case 'W' :
+ return number + '週';
+ default :
+ return number;
+ }
+ },
+ relativeTime : {
+ future : '%s內',
+ past : '%s前',
+ s : '幾秒',
+ ss : '%d 秒',
+ m : '1 分鐘',
+ mm : '%d 分鐘',
+ h : '1 小時',
+ hh : '%d 小時',
+ d : '1 天',
+ dd : '%d 天',
+ M : '1 個月',
+ MM : '%d 個月',
+ y : '1 年',
+ yy : '%d 年'
+ }
+});
+
+return zhTw;
+
+})));
+
+
+/***/ }),
+/* 124 */
+/***/ (function(module, exports, __webpack_require__) {
+
+module.exports = __webpack_require__(125);
+
+
+/***/ }),
+/* 125 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_jquery__ = __webpack_require__(1);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_jquery___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_jquery__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_popper_js__ = __webpack_require__(2);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_bootstrap__ = __webpack_require__(126);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_bootstrap___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2_bootstrap__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_datatables_net__ = __webpack_require__(4);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_datatables_net___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_datatables_net__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_corejs_typeahead__ = __webpack_require__(127);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4_corejs_typeahead___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_4_corejs_typeahead__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_datatables_net_bs4__ = __webpack_require__(131);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_5_datatables_net_bs4___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_5_datatables_net_bs4__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_sortablejs__ = __webpack_require__(132);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_6_sortablejs___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_6_sortablejs__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_select2__ = __webpack_require__(133);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_7_select2___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_7_select2__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_moment__ = __webpack_require__(0);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_8_moment___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_8_moment__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9_eonasdan_bootstrap_datetimepicker__ = __webpack_require__(136);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_9_eonasdan_bootstrap_datetimepicker___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_9_eonasdan_bootstrap_datetimepicker__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10_jquery_colorbox__ = __webpack_require__(137);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_10_jquery_colorbox___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_10_jquery_colorbox__);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11_wheelzoom__ = __webpack_require__(138);
+/* harmony import */ var __WEBPACK_IMPORTED_MODULE_11_wheelzoom___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_11_wheelzoom__);
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2017 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+window.$ = window.jQuery = __WEBPACK_IMPORTED_MODULE_0_jquery___default.a;
+
+
+
+
+
+
+
+
+
+
+
+
+/***/ }),
+/* 126 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/*!
+ * Bootstrap v4.0.0-beta.3 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+(function (global, factory) {
+ true ? factory(exports, __webpack_require__(1), __webpack_require__(2)) :
+ typeof define === 'function' && define.amd ? define(['exports', 'jquery', 'popper.js'], factory) :
+ (factory((global.bootstrap = {}),global.jQuery,global.Popper));
+}(this, (function (exports,$,Popper) { 'use strict';
+
+$ = $ && $.hasOwnProperty('default') ? $['default'] : $;
+Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper;
+
+function _defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+}
+
+function _createClass(Constructor, protoProps, staticProps) {
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) _defineProperties(Constructor, staticProps);
+ return Constructor;
+}
+
+function _extends() {
+ _extends = Object.assign || function (target) {
+ for (var i = 1; i < arguments.length; i++) {
+ var source = arguments[i];
+
+ for (var key in source) {
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
+ target[key] = source[key];
+ }
+ }
+ }
+
+ return target;
+ };
+
+ return _extends.apply(this, arguments);
+}
+
+function _inheritsLoose(subClass, superClass) {
+ subClass.prototype = Object.create(superClass.prototype);
+ subClass.prototype.constructor = subClass;
+ subClass.__proto__ = superClass;
+}
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): util.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Util = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Private TransitionEnd Helpers
+ * ------------------------------------------------------------------------
+ */
+ var transition = false;
+ var MAX_UID = 1000000; // shoutout AngusCroll (https://goo.gl/pxwQGp)
+
+ function toType(obj) {
+ return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
+ }
+
+ function getSpecialTransitionEndEvent() {
+ return {
+ bindType: transition.end,
+ delegateType: transition.end,
+ handle: function handle(event) {
+ if ($$$1(event.target).is(this)) {
+ return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
+ }
+
+ return undefined; // eslint-disable-line no-undefined
+ }
+ };
+ }
+
+ function transitionEndTest() {
+ if (window.QUnit) {
+ return false;
+ }
+
+ return {
+ end: 'transitionend'
+ };
+ }
+
+ function transitionEndEmulator(duration) {
+ var _this = this;
+
+ var called = false;
+ $$$1(this).one(Util.TRANSITION_END, function () {
+ called = true;
+ });
+ setTimeout(function () {
+ if (!called) {
+ Util.triggerTransitionEnd(_this);
+ }
+ }, duration);
+ return this;
+ }
+
+ function setTransitionEndSupport() {
+ transition = transitionEndTest();
+ $$$1.fn.emulateTransitionEnd = transitionEndEmulator;
+
+ if (Util.supportsTransitionEnd()) {
+ $$$1.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
+ }
+ }
+
+ function escapeId(selector) {
+ // we escape IDs in case of special selectors (selector = '#myId:something')
+ // $.escapeSelector does not exist in jQuery < 3
+ selector = typeof $$$1.escapeSelector === 'function' ? $$$1.escapeSelector(selector).substr(1) : selector.replace(/(:|\.|\[|\]|,|=|@)/g, '\\$1');
+ return selector;
+ }
+ /**
+ * --------------------------------------------------------------------------
+ * Public Util Api
+ * --------------------------------------------------------------------------
+ */
+
+
+ var Util = {
+ TRANSITION_END: 'bsTransitionEnd',
+ getUID: function getUID(prefix) {
+ do {
+ // eslint-disable-next-line no-bitwise
+ prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
+ } while (document.getElementById(prefix));
+
+ return prefix;
+ },
+ getSelectorFromElement: function getSelectorFromElement(element) {
+ var selector = element.getAttribute('data-target');
+
+ if (!selector || selector === '#') {
+ selector = element.getAttribute('href') || '';
+ } // if it's an ID
+
+
+ if (selector.charAt(0) === '#') {
+ selector = escapeId(selector);
+ }
+
+ try {
+ var $selector = $$$1(document).find(selector);
+ return $selector.length > 0 ? selector : null;
+ } catch (error) {
+ return null;
+ }
+ },
+ reflow: function reflow(element) {
+ return element.offsetHeight;
+ },
+ triggerTransitionEnd: function triggerTransitionEnd(element) {
+ $$$1(element).trigger(transition.end);
+ },
+ supportsTransitionEnd: function supportsTransitionEnd() {
+ return Boolean(transition);
+ },
+ isElement: function isElement(obj) {
+ return (obj[0] || obj).nodeType;
+ },
+ typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
+ for (var property in configTypes) {
+ if (Object.prototype.hasOwnProperty.call(configTypes, property)) {
+ var expectedTypes = configTypes[property];
+ var value = config[property];
+ var valueType = value && Util.isElement(value) ? 'element' : toType(value);
+
+ if (!new RegExp(expectedTypes).test(valueType)) {
+ throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\"."));
+ }
+ }
+ }
+ }
+ };
+ setTransitionEndSupport();
+ return Util;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): alert.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Alert = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'alert';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.alert';
+ var EVENT_KEY = "." + DATA_KEY;
+ var DATA_API_KEY = '.data-api';
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var TRANSITION_DURATION = 150;
+ var Selector = {
+ DISMISS: '[data-dismiss="alert"]'
+ };
+ var Event = {
+ CLOSE: "close" + EVENT_KEY,
+ CLOSED: "closed" + EVENT_KEY,
+ CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
+ };
+ var ClassName = {
+ ALERT: 'alert',
+ FADE: 'fade',
+ SHOW: 'show'
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Alert =
+ /*#__PURE__*/
+ function () {
+ function Alert(element) {
+ this._element = element;
+ } // getters
+
+
+ var _proto = Alert.prototype;
+
+ // public
+ _proto.close = function close(element) {
+ element = element || this._element;
+
+ var rootElement = this._getRootElement(element);
+
+ var customEvent = this._triggerCloseEvent(rootElement);
+
+ if (customEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ this._removeElement(rootElement);
+ };
+
+ _proto.dispose = function dispose() {
+ $$$1.removeData(this._element, DATA_KEY);
+ this._element = null;
+ }; // private
+
+
+ _proto._getRootElement = function _getRootElement(element) {
+ var selector = Util.getSelectorFromElement(element);
+ var parent = false;
+
+ if (selector) {
+ parent = $$$1(selector)[0];
+ }
+
+ if (!parent) {
+ parent = $$$1(element).closest("." + ClassName.ALERT)[0];
+ }
+
+ return parent;
+ };
+
+ _proto._triggerCloseEvent = function _triggerCloseEvent(element) {
+ var closeEvent = $$$1.Event(Event.CLOSE);
+ $$$1(element).trigger(closeEvent);
+ return closeEvent;
+ };
+
+ _proto._removeElement = function _removeElement(element) {
+ var _this = this;
+
+ $$$1(element).removeClass(ClassName.SHOW);
+
+ if (!Util.supportsTransitionEnd() || !$$$1(element).hasClass(ClassName.FADE)) {
+ this._destroyElement(element);
+
+ return;
+ }
+
+ $$$1(element).one(Util.TRANSITION_END, function (event) {
+ return _this._destroyElement(element, event);
+ }).emulateTransitionEnd(TRANSITION_DURATION);
+ };
+
+ _proto._destroyElement = function _destroyElement(element) {
+ $$$1(element).detach().trigger(Event.CLOSED).remove();
+ }; // static
+
+
+ Alert._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var $element = $$$1(this);
+ var data = $element.data(DATA_KEY);
+
+ if (!data) {
+ data = new Alert(this);
+ $element.data(DATA_KEY, data);
+ }
+
+ if (config === 'close') {
+ data[config](this);
+ }
+ });
+ };
+
+ Alert._handleDismiss = function _handleDismiss(alertInstance) {
+ return function (event) {
+ if (event) {
+ event.preventDefault();
+ }
+
+ alertInstance.close(this);
+ };
+ };
+
+ _createClass(Alert, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }]);
+ return Alert;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $$$1.fn[NAME] = Alert._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Alert;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Alert._jQueryInterface;
+ };
+
+ return Alert;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): button.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Button = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'button';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.button';
+ var EVENT_KEY = "." + DATA_KEY;
+ var DATA_API_KEY = '.data-api';
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var ClassName = {
+ ACTIVE: 'active',
+ BUTTON: 'btn',
+ FOCUS: 'focus'
+ };
+ var Selector = {
+ DATA_TOGGLE_CARROT: '[data-toggle^="button"]',
+ DATA_TOGGLE: '[data-toggle="buttons"]',
+ INPUT: 'input',
+ ACTIVE: '.active',
+ BUTTON: '.btn'
+ };
+ var Event = {
+ CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY,
+ FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY + DATA_API_KEY + " " + ("blur" + EVENT_KEY + DATA_API_KEY)
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Button =
+ /*#__PURE__*/
+ function () {
+ function Button(element) {
+ this._element = element;
+ } // getters
+
+
+ var _proto = Button.prototype;
+
+ // public
+ _proto.toggle = function toggle() {
+ var triggerChangeEvent = true;
+ var addAriaPressed = true;
+ var rootElement = $$$1(this._element).closest(Selector.DATA_TOGGLE)[0];
+
+ if (rootElement) {
+ var input = $$$1(this._element).find(Selector.INPUT)[0];
+
+ if (input) {
+ if (input.type === 'radio') {
+ if (input.checked && $$$1(this._element).hasClass(ClassName.ACTIVE)) {
+ triggerChangeEvent = false;
+ } else {
+ var activeElement = $$$1(rootElement).find(Selector.ACTIVE)[0];
+
+ if (activeElement) {
+ $$$1(activeElement).removeClass(ClassName.ACTIVE);
+ }
+ }
+ }
+
+ if (triggerChangeEvent) {
+ if (input.hasAttribute('disabled') || rootElement.hasAttribute('disabled') || input.classList.contains('disabled') || rootElement.classList.contains('disabled')) {
+ return;
+ }
+
+ input.checked = !$$$1(this._element).hasClass(ClassName.ACTIVE);
+ $$$1(input).trigger('change');
+ }
+
+ input.focus();
+ addAriaPressed = false;
+ }
+ }
+
+ if (addAriaPressed) {
+ this._element.setAttribute('aria-pressed', !$$$1(this._element).hasClass(ClassName.ACTIVE));
+ }
+
+ if (triggerChangeEvent) {
+ $$$1(this._element).toggleClass(ClassName.ACTIVE);
+ }
+ };
+
+ _proto.dispose = function dispose() {
+ $$$1.removeData(this._element, DATA_KEY);
+ this._element = null;
+ }; // static
+
+
+ Button._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var data = $$$1(this).data(DATA_KEY);
+
+ if (!data) {
+ data = new Button(this);
+ $$$1(this).data(DATA_KEY, data);
+ }
+
+ if (config === 'toggle') {
+ data[config]();
+ }
+ });
+ };
+
+ _createClass(Button, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }]);
+ return Button;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+ event.preventDefault();
+ var button = event.target;
+
+ if (!$$$1(button).hasClass(ClassName.BUTTON)) {
+ button = $$$1(button).closest(Selector.BUTTON);
+ }
+
+ Button._jQueryInterface.call($$$1(button), 'toggle');
+ }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+ var button = $$$1(event.target).closest(Selector.BUTTON)[0];
+ $$$1(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));
+ });
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $$$1.fn[NAME] = Button._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Button;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Button._jQueryInterface;
+ };
+
+ return Button;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): carousel.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Carousel = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'carousel';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.carousel';
+ var EVENT_KEY = "." + DATA_KEY;
+ var DATA_API_KEY = '.data-api';
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var TRANSITION_DURATION = 600;
+ var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
+
+ var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
+
+ var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch
+
+ var Default = {
+ interval: 5000,
+ keyboard: true,
+ slide: false,
+ pause: 'hover',
+ wrap: true
+ };
+ var DefaultType = {
+ interval: '(number|boolean)',
+ keyboard: 'boolean',
+ slide: '(boolean|string)',
+ pause: '(string|boolean)',
+ wrap: 'boolean'
+ };
+ var Direction = {
+ NEXT: 'next',
+ PREV: 'prev',
+ LEFT: 'left',
+ RIGHT: 'right'
+ };
+ var Event = {
+ SLIDE: "slide" + EVENT_KEY,
+ SLID: "slid" + EVENT_KEY,
+ KEYDOWN: "keydown" + EVENT_KEY,
+ MOUSEENTER: "mouseenter" + EVENT_KEY,
+ MOUSELEAVE: "mouseleave" + EVENT_KEY,
+ TOUCHEND: "touchend" + EVENT_KEY,
+ LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY,
+ CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
+ };
+ var ClassName = {
+ CAROUSEL: 'carousel',
+ ACTIVE: 'active',
+ SLIDE: 'slide',
+ RIGHT: 'carousel-item-right',
+ LEFT: 'carousel-item-left',
+ NEXT: 'carousel-item-next',
+ PREV: 'carousel-item-prev',
+ ITEM: 'carousel-item'
+ };
+ var Selector = {
+ ACTIVE: '.active',
+ ACTIVE_ITEM: '.active.carousel-item',
+ ITEM: '.carousel-item',
+ NEXT_PREV: '.carousel-item-next, .carousel-item-prev',
+ INDICATORS: '.carousel-indicators',
+ DATA_SLIDE: '[data-slide], [data-slide-to]',
+ DATA_RIDE: '[data-ride="carousel"]'
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Carousel =
+ /*#__PURE__*/
+ function () {
+ function Carousel(element, config) {
+ this._items = null;
+ this._interval = null;
+ this._activeElement = null;
+ this._isPaused = false;
+ this._isSliding = false;
+ this.touchTimeout = null;
+ this._config = this._getConfig(config);
+ this._element = $$$1(element)[0];
+ this._indicatorsElement = $$$1(this._element).find(Selector.INDICATORS)[0];
+
+ this._addEventListeners();
+ } // getters
+
+
+ var _proto = Carousel.prototype;
+
+ // public
+ _proto.next = function next() {
+ if (!this._isSliding) {
+ this._slide(Direction.NEXT);
+ }
+ };
+
+ _proto.nextWhenVisible = function nextWhenVisible() {
+ // Don't call next when the page isn't visible
+ // or the carousel or its parent isn't visible
+ if (!document.hidden && $$$1(this._element).is(':visible') && $$$1(this._element).css('visibility') !== 'hidden') {
+ this.next();
+ }
+ };
+
+ _proto.prev = function prev() {
+ if (!this._isSliding) {
+ this._slide(Direction.PREV);
+ }
+ };
+
+ _proto.pause = function pause(event) {
+ if (!event) {
+ this._isPaused = true;
+ }
+
+ if ($$$1(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {
+ Util.triggerTransitionEnd(this._element);
+ this.cycle(true);
+ }
+
+ clearInterval(this._interval);
+ this._interval = null;
+ };
+
+ _proto.cycle = function cycle(event) {
+ if (!event) {
+ this._isPaused = false;
+ }
+
+ if (this._interval) {
+ clearInterval(this._interval);
+ this._interval = null;
+ }
+
+ if (this._config.interval && !this._isPaused) {
+ this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval);
+ }
+ };
+
+ _proto.to = function to(index) {
+ var _this = this;
+
+ this._activeElement = $$$1(this._element).find(Selector.ACTIVE_ITEM)[0];
+
+ var activeIndex = this._getItemIndex(this._activeElement);
+
+ if (index > this._items.length - 1 || index < 0) {
+ return;
+ }
+
+ if (this._isSliding) {
+ $$$1(this._element).one(Event.SLID, function () {
+ return _this.to(index);
+ });
+ return;
+ }
+
+ if (activeIndex === index) {
+ this.pause();
+ this.cycle();
+ return;
+ }
+
+ var direction = index > activeIndex ? Direction.NEXT : Direction.PREV;
+
+ this._slide(direction, this._items[index]);
+ };
+
+ _proto.dispose = function dispose() {
+ $$$1(this._element).off(EVENT_KEY);
+ $$$1.removeData(this._element, DATA_KEY);
+ this._items = null;
+ this._config = null;
+ this._element = null;
+ this._interval = null;
+ this._isPaused = null;
+ this._isSliding = null;
+ this._activeElement = null;
+ this._indicatorsElement = null;
+ }; // private
+
+
+ _proto._getConfig = function _getConfig(config) {
+ config = _extends({}, Default, config);
+ Util.typeCheckConfig(NAME, config, DefaultType);
+ return config;
+ };
+
+ _proto._addEventListeners = function _addEventListeners() {
+ var _this2 = this;
+
+ if (this._config.keyboard) {
+ $$$1(this._element).on(Event.KEYDOWN, function (event) {
+ return _this2._keydown(event);
+ });
+ }
+
+ if (this._config.pause === 'hover') {
+ $$$1(this._element).on(Event.MOUSEENTER, function (event) {
+ return _this2.pause(event);
+ }).on(Event.MOUSELEAVE, function (event) {
+ return _this2.cycle(event);
+ });
+
+ if ('ontouchstart' in document.documentElement) {
+ // if it's a touch-enabled device, mouseenter/leave are fired as
+ // part of the mouse compatibility events on first tap - the carousel
+ // would stop cycling until user tapped out of it;
+ // here, we listen for touchend, explicitly pause the carousel
+ // (as if it's the second time we tap on it, mouseenter compat event
+ // is NOT fired) and after a timeout (to allow for mouse compatibility
+ // events to fire) we explicitly restart cycling
+ $$$1(this._element).on(Event.TOUCHEND, function () {
+ _this2.pause();
+
+ if (_this2.touchTimeout) {
+ clearTimeout(_this2.touchTimeout);
+ }
+
+ _this2.touchTimeout = setTimeout(function (event) {
+ return _this2.cycle(event);
+ }, TOUCHEVENT_COMPAT_WAIT + _this2._config.interval);
+ });
+ }
+ }
+ };
+
+ _proto._keydown = function _keydown(event) {
+ if (/input|textarea/i.test(event.target.tagName)) {
+ return;
+ }
+
+ switch (event.which) {
+ case ARROW_LEFT_KEYCODE:
+ event.preventDefault();
+ this.prev();
+ break;
+
+ case ARROW_RIGHT_KEYCODE:
+ event.preventDefault();
+ this.next();
+ break;
+
+ default:
+ return;
+ }
+ };
+
+ _proto._getItemIndex = function _getItemIndex(element) {
+ this._items = $$$1.makeArray($$$1(element).parent().find(Selector.ITEM));
+ return this._items.indexOf(element);
+ };
+
+ _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) {
+ var isNextDirection = direction === Direction.NEXT;
+ var isPrevDirection = direction === Direction.PREV;
+
+ var activeIndex = this._getItemIndex(activeElement);
+
+ var lastItemIndex = this._items.length - 1;
+ var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
+
+ if (isGoingToWrap && !this._config.wrap) {
+ return activeElement;
+ }
+
+ var delta = direction === Direction.PREV ? -1 : 1;
+ var itemIndex = (activeIndex + delta) % this._items.length;
+ return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
+ };
+
+ _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) {
+ var targetIndex = this._getItemIndex(relatedTarget);
+
+ var fromIndex = this._getItemIndex($$$1(this._element).find(Selector.ACTIVE_ITEM)[0]);
+
+ var slideEvent = $$$1.Event(Event.SLIDE, {
+ relatedTarget: relatedTarget,
+ direction: eventDirectionName,
+ from: fromIndex,
+ to: targetIndex
+ });
+ $$$1(this._element).trigger(slideEvent);
+ return slideEvent;
+ };
+
+ _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
+ if (this._indicatorsElement) {
+ $$$1(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+
+ var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
+
+ if (nextIndicator) {
+ $$$1(nextIndicator).addClass(ClassName.ACTIVE);
+ }
+ }
+ };
+
+ _proto._slide = function _slide(direction, element) {
+ var _this3 = this;
+
+ var activeElement = $$$1(this._element).find(Selector.ACTIVE_ITEM)[0];
+
+ var activeElementIndex = this._getItemIndex(activeElement);
+
+ var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
+
+ var nextElementIndex = this._getItemIndex(nextElement);
+
+ var isCycling = Boolean(this._interval);
+ var directionalClassName;
+ var orderClassName;
+ var eventDirectionName;
+
+ if (direction === Direction.NEXT) {
+ directionalClassName = ClassName.LEFT;
+ orderClassName = ClassName.NEXT;
+ eventDirectionName = Direction.LEFT;
+ } else {
+ directionalClassName = ClassName.RIGHT;
+ orderClassName = ClassName.PREV;
+ eventDirectionName = Direction.RIGHT;
+ }
+
+ if (nextElement && $$$1(nextElement).hasClass(ClassName.ACTIVE)) {
+ this._isSliding = false;
+ return;
+ }
+
+ var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName);
+
+ if (slideEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ if (!activeElement || !nextElement) {
+ // some weirdness is happening, so we bail
+ return;
+ }
+
+ this._isSliding = true;
+
+ if (isCycling) {
+ this.pause();
+ }
+
+ this._setActiveIndicatorElement(nextElement);
+
+ var slidEvent = $$$1.Event(Event.SLID, {
+ relatedTarget: nextElement,
+ direction: eventDirectionName,
+ from: activeElementIndex,
+ to: nextElementIndex
+ });
+
+ if (Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.SLIDE)) {
+ $$$1(nextElement).addClass(orderClassName);
+ Util.reflow(nextElement);
+ $$$1(activeElement).addClass(directionalClassName);
+ $$$1(nextElement).addClass(directionalClassName);
+ $$$1(activeElement).one(Util.TRANSITION_END, function () {
+ $$$1(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName.ACTIVE);
+ $$$1(activeElement).removeClass(ClassName.ACTIVE + " " + orderClassName + " " + directionalClassName);
+ _this3._isSliding = false;
+ setTimeout(function () {
+ return $$$1(_this3._element).trigger(slidEvent);
+ }, 0);
+ }).emulateTransitionEnd(TRANSITION_DURATION);
+ } else {
+ $$$1(activeElement).removeClass(ClassName.ACTIVE);
+ $$$1(nextElement).addClass(ClassName.ACTIVE);
+ this._isSliding = false;
+ $$$1(this._element).trigger(slidEvent);
+ }
+
+ if (isCycling) {
+ this.cycle();
+ }
+ }; // static
+
+
+ Carousel._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var data = $$$1(this).data(DATA_KEY);
+
+ var _config = _extends({}, Default, $$$1(this).data());
+
+ if (typeof config === 'object') {
+ _config = _extends({}, _config, config);
+ }
+
+ var action = typeof config === 'string' ? config : _config.slide;
+
+ if (!data) {
+ data = new Carousel(this, _config);
+ $$$1(this).data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'number') {
+ data.to(config);
+ } else if (typeof action === 'string') {
+ if (typeof data[action] === 'undefined') {
+ throw new Error("No method named \"" + action + "\"");
+ }
+
+ data[action]();
+ } else if (_config.interval) {
+ data.pause();
+ data.cycle();
+ }
+ });
+ };
+
+ Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
+ var selector = Util.getSelectorFromElement(this);
+
+ if (!selector) {
+ return;
+ }
+
+ var target = $$$1(selector)[0];
+
+ if (!target || !$$$1(target).hasClass(ClassName.CAROUSEL)) {
+ return;
+ }
+
+ var config = _extends({}, $$$1(target).data(), $$$1(this).data());
+ var slideIndex = this.getAttribute('data-slide-to');
+
+ if (slideIndex) {
+ config.interval = false;
+ }
+
+ Carousel._jQueryInterface.call($$$1(target), config);
+
+ if (slideIndex) {
+ $$$1(target).data(DATA_KEY).to(slideIndex);
+ }
+
+ event.preventDefault();
+ };
+
+ _createClass(Carousel, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }, {
+ key: "Default",
+ get: function get() {
+ return Default;
+ }
+ }]);
+ return Carousel;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
+ $$$1(window).on(Event.LOAD_DATA_API, function () {
+ $$$1(Selector.DATA_RIDE).each(function () {
+ var $carousel = $$$1(this);
+
+ Carousel._jQueryInterface.call($carousel, $carousel.data());
+ });
+ });
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $$$1.fn[NAME] = Carousel._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Carousel;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Carousel._jQueryInterface;
+ };
+
+ return Carousel;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): collapse.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Collapse = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'collapse';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.collapse';
+ var EVENT_KEY = "." + DATA_KEY;
+ var DATA_API_KEY = '.data-api';
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var TRANSITION_DURATION = 600;
+ var Default = {
+ toggle: true,
+ parent: ''
+ };
+ var DefaultType = {
+ toggle: 'boolean',
+ parent: '(string|element)'
+ };
+ var Event = {
+ SHOW: "show" + EVENT_KEY,
+ SHOWN: "shown" + EVENT_KEY,
+ HIDE: "hide" + EVENT_KEY,
+ HIDDEN: "hidden" + EVENT_KEY,
+ CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
+ };
+ var ClassName = {
+ SHOW: 'show',
+ COLLAPSE: 'collapse',
+ COLLAPSING: 'collapsing',
+ COLLAPSED: 'collapsed'
+ };
+ var Dimension = {
+ WIDTH: 'width',
+ HEIGHT: 'height'
+ };
+ var Selector = {
+ ACTIVES: '.show, .collapsing',
+ DATA_TOGGLE: '[data-toggle="collapse"]'
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Collapse =
+ /*#__PURE__*/
+ function () {
+ function Collapse(element, config) {
+ this._isTransitioning = false;
+ this._element = element;
+ this._config = this._getConfig(config);
+ this._triggerArray = $$$1.makeArray($$$1("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]")));
+ var tabToggles = $$$1(Selector.DATA_TOGGLE);
+
+ for (var i = 0; i < tabToggles.length; i++) {
+ var elem = tabToggles[i];
+ var selector = Util.getSelectorFromElement(elem);
+
+ if (selector !== null && $$$1(selector).filter(element).length > 0) {
+ this._triggerArray.push(elem);
+ }
+ }
+
+ this._parent = this._config.parent ? this._getParent() : null;
+
+ if (!this._config.parent) {
+ this._addAriaAndCollapsedClass(this._element, this._triggerArray);
+ }
+
+ if (this._config.toggle) {
+ this.toggle();
+ }
+ } // getters
+
+
+ var _proto = Collapse.prototype;
+
+ // public
+ _proto.toggle = function toggle() {
+ if ($$$1(this._element).hasClass(ClassName.SHOW)) {
+ this.hide();
+ } else {
+ this.show();
+ }
+ };
+
+ _proto.show = function show() {
+ var _this = this;
+
+ if (this._isTransitioning || $$$1(this._element).hasClass(ClassName.SHOW)) {
+ return;
+ }
+
+ var actives;
+ var activesData;
+
+ if (this._parent) {
+ actives = $$$1.makeArray($$$1(this._parent).children().children(Selector.ACTIVES));
+
+ if (!actives.length) {
+ actives = null;
+ }
+ }
+
+ if (actives) {
+ activesData = $$$1(actives).data(DATA_KEY);
+
+ if (activesData && activesData._isTransitioning) {
+ return;
+ }
+ }
+
+ var startEvent = $$$1.Event(Event.SHOW);
+ $$$1(this._element).trigger(startEvent);
+
+ if (startEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ if (actives) {
+ Collapse._jQueryInterface.call($$$1(actives), 'hide');
+
+ if (!activesData) {
+ $$$1(actives).data(DATA_KEY, null);
+ }
+ }
+
+ var dimension = this._getDimension();
+
+ $$$1(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
+ this._element.style[dimension] = 0;
+
+ if (this._triggerArray.length) {
+ $$$1(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
+ }
+
+ this.setTransitioning(true);
+
+ var complete = function complete() {
+ $$$1(_this._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.SHOW);
+ _this._element.style[dimension] = '';
+
+ _this.setTransitioning(false);
+
+ $$$1(_this._element).trigger(Event.SHOWN);
+ };
+
+ if (!Util.supportsTransitionEnd()) {
+ complete();
+ return;
+ }
+
+ var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
+ var scrollSize = "scroll" + capitalizedDimension;
+ $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+ this._element.style[dimension] = this._element[scrollSize] + "px";
+ };
+
+ _proto.hide = function hide() {
+ var _this2 = this;
+
+ if (this._isTransitioning || !$$$1(this._element).hasClass(ClassName.SHOW)) {
+ return;
+ }
+
+ var startEvent = $$$1.Event(Event.HIDE);
+ $$$1(this._element).trigger(startEvent);
+
+ if (startEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ var dimension = this._getDimension();
+
+ this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px";
+ Util.reflow(this._element);
+ $$$1(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.SHOW);
+
+ if (this._triggerArray.length) {
+ for (var i = 0; i < this._triggerArray.length; i++) {
+ var trigger = this._triggerArray[i];
+ var selector = Util.getSelectorFromElement(trigger);
+
+ if (selector !== null) {
+ var $elem = $$$1(selector);
+
+ if (!$elem.hasClass(ClassName.SHOW)) {
+ $$$1(trigger).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
+ }
+ }
+ }
+ }
+
+ this.setTransitioning(true);
+
+ var complete = function complete() {
+ _this2.setTransitioning(false);
+
+ $$$1(_this2._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
+ };
+
+ this._element.style[dimension] = '';
+
+ if (!Util.supportsTransitionEnd()) {
+ complete();
+ return;
+ }
+
+ $$$1(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+ };
+
+ _proto.setTransitioning = function setTransitioning(isTransitioning) {
+ this._isTransitioning = isTransitioning;
+ };
+
+ _proto.dispose = function dispose() {
+ $$$1.removeData(this._element, DATA_KEY);
+ this._config = null;
+ this._parent = null;
+ this._element = null;
+ this._triggerArray = null;
+ this._isTransitioning = null;
+ }; // private
+
+
+ _proto._getConfig = function _getConfig(config) {
+ config = _extends({}, Default, config);
+ config.toggle = Boolean(config.toggle); // coerce string values
+
+ Util.typeCheckConfig(NAME, config, DefaultType);
+ return config;
+ };
+
+ _proto._getDimension = function _getDimension() {
+ var hasWidth = $$$1(this._element).hasClass(Dimension.WIDTH);
+ return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
+ };
+
+ _proto._getParent = function _getParent() {
+ var _this3 = this;
+
+ var parent = null;
+
+ if (Util.isElement(this._config.parent)) {
+ parent = this._config.parent; // it's a jQuery object
+
+ if (typeof this._config.parent.jquery !== 'undefined') {
+ parent = this._config.parent[0];
+ }
+ } else {
+ parent = $$$1(this._config.parent)[0];
+ }
+
+ var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]";
+ $$$1(parent).find(selector).each(function (i, element) {
+ _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
+ });
+ return parent;
+ };
+
+ _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
+ if (element) {
+ var isOpen = $$$1(element).hasClass(ClassName.SHOW);
+
+ if (triggerArray.length) {
+ $$$1(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
+ }
+ }
+ }; // static
+
+
+ Collapse._getTargetFromElement = function _getTargetFromElement(element) {
+ var selector = Util.getSelectorFromElement(element);
+ return selector ? $$$1(selector)[0] : null;
+ };
+
+ Collapse._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var $this = $$$1(this);
+ var data = $this.data(DATA_KEY);
+
+ var _config = _extends({}, Default, $this.data(), typeof config === 'object' && config);
+
+ if (!data && _config.toggle && /show|hide/.test(config)) {
+ _config.toggle = false;
+ }
+
+ if (!data) {
+ data = new Collapse(this, _config);
+ $this.data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'string') {
+ if (typeof data[config] === 'undefined') {
+ throw new Error("No method named \"" + config + "\"");
+ }
+
+ data[config]();
+ }
+ });
+ };
+
+ _createClass(Collapse, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }, {
+ key: "Default",
+ get: function get() {
+ return Default;
+ }
+ }]);
+ return Collapse;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+ // preventDefault only for <a> elements (which change the URL) not inside the collapsible element
+ if (event.currentTarget.tagName === 'A') {
+ event.preventDefault();
+ }
+
+ var $trigger = $$$1(this);
+ var selector = Util.getSelectorFromElement(this);
+ $$$1(selector).each(function () {
+ var $target = $$$1(this);
+ var data = $target.data(DATA_KEY);
+ var config = data ? 'toggle' : $trigger.data();
+
+ Collapse._jQueryInterface.call($target, config);
+ });
+ });
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $$$1.fn[NAME] = Collapse._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Collapse;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Collapse._jQueryInterface;
+ };
+
+ return Collapse;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): dropdown.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Dropdown = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'dropdown';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.dropdown';
+ var EVENT_KEY = "." + DATA_KEY;
+ var DATA_API_KEY = '.data-api';
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+
+ var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key
+
+ var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key
+
+ var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
+
+ var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
+
+ var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
+
+ var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE);
+ var Event = {
+ HIDE: "hide" + EVENT_KEY,
+ HIDDEN: "hidden" + EVENT_KEY,
+ SHOW: "show" + EVENT_KEY,
+ SHOWN: "shown" + EVENT_KEY,
+ CLICK: "click" + EVENT_KEY,
+ CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY,
+ KEYDOWN_DATA_API: "keydown" + EVENT_KEY + DATA_API_KEY,
+ KEYUP_DATA_API: "keyup" + EVENT_KEY + DATA_API_KEY
+ };
+ var ClassName = {
+ DISABLED: 'disabled',
+ SHOW: 'show',
+ DROPUP: 'dropup',
+ DROPRIGHT: 'dropright',
+ DROPLEFT: 'dropleft',
+ MENURIGHT: 'dropdown-menu-right',
+ MENULEFT: 'dropdown-menu-left',
+ POSITION_STATIC: 'position-static'
+ };
+ var Selector = {
+ DATA_TOGGLE: '[data-toggle="dropdown"]',
+ FORM_CHILD: '.dropdown form',
+ MENU: '.dropdown-menu',
+ NAVBAR_NAV: '.navbar-nav',
+ VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled)'
+ };
+ var AttachmentMap = {
+ TOP: 'top-start',
+ TOPEND: 'top-end',
+ BOTTOM: 'bottom-start',
+ BOTTOMEND: 'bottom-end',
+ RIGHT: 'right-start',
+ RIGHTEND: 'right-end',
+ LEFT: 'left-start',
+ LEFTEND: 'left-end'
+ };
+ var Default = {
+ offset: 0,
+ flip: true,
+ boundary: 'scrollParent'
+ };
+ var DefaultType = {
+ offset: '(number|string|function)',
+ flip: 'boolean',
+ boundary: '(string|element)'
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Dropdown =
+ /*#__PURE__*/
+ function () {
+ function Dropdown(element, config) {
+ this._element = element;
+ this._popper = null;
+ this._config = this._getConfig(config);
+ this._menu = this._getMenuElement();
+ this._inNavbar = this._detectNavbar();
+
+ this._addEventListeners();
+ } // getters
+
+
+ var _proto = Dropdown.prototype;
+
+ // public
+ _proto.toggle = function toggle() {
+ if (this._element.disabled || $$$1(this._element).hasClass(ClassName.DISABLED)) {
+ return;
+ }
+
+ var parent = Dropdown._getParentFromElement(this._element);
+
+ var isActive = $$$1(this._menu).hasClass(ClassName.SHOW);
+
+ Dropdown._clearMenus();
+
+ if (isActive) {
+ return;
+ }
+
+ var relatedTarget = {
+ relatedTarget: this._element
+ };
+ var showEvent = $$$1.Event(Event.SHOW, relatedTarget);
+ $$$1(parent).trigger(showEvent);
+
+ if (showEvent.isDefaultPrevented()) {
+ return;
+ } // Disable totally Popper.js for Dropdown in Navbar
+
+
+ if (!this._inNavbar) {
+ /**
+ * Check for Popper dependency
+ * Popper - https://popper.js.org
+ */
+ if (typeof Popper === 'undefined') {
+ throw new Error('Bootstrap dropdown require Popper.js (https://popper.js.org)');
+ }
+
+ var element = this._element; // for dropup with alignment we use the parent as popper container
+
+ if ($$$1(parent).hasClass(ClassName.DROPUP)) {
+ if ($$$1(this._menu).hasClass(ClassName.MENULEFT) || $$$1(this._menu).hasClass(ClassName.MENURIGHT)) {
+ element = parent;
+ }
+ } // If boundary is not `scrollParent`, then set position to `static`
+ // to allow the menu to "escape" the scroll parent's boundaries
+ // https://github.com/twbs/bootstrap/issues/24251
+
+
+ if (this._config.boundary !== 'scrollParent') {
+ $$$1(parent).addClass(ClassName.POSITION_STATIC);
+ }
+
+ this._popper = new Popper(element, this._menu, this._getPopperConfig());
+ } // if this is a touch-enabled device we add extra
+ // empty mouseover listeners to the body's immediate children;
+ // only needed because of broken event delegation on iOS
+ // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
+
+
+ if ('ontouchstart' in document.documentElement && !$$$1(parent).closest(Selector.NAVBAR_NAV).length) {
+ $$$1('body').children().on('mouseover', null, $$$1.noop);
+ }
+
+ this._element.focus();
+
+ this._element.setAttribute('aria-expanded', true);
+
+ $$$1(this._menu).toggleClass(ClassName.SHOW);
+ $$$1(parent).toggleClass(ClassName.SHOW).trigger($$$1.Event(Event.SHOWN, relatedTarget));
+ };
+
+ _proto.dispose = function dispose() {
+ $$$1.removeData(this._element, DATA_KEY);
+ $$$1(this._element).off(EVENT_KEY);
+ this._element = null;
+ this._menu = null;
+
+ if (this._popper !== null) {
+ this._popper.destroy();
+
+ this._popper = null;
+ }
+ };
+
+ _proto.update = function update() {
+ this._inNavbar = this._detectNavbar();
+
+ if (this._popper !== null) {
+ this._popper.scheduleUpdate();
+ }
+ }; // private
+
+
+ _proto._addEventListeners = function _addEventListeners() {
+ var _this = this;
+
+ $$$1(this._element).on(Event.CLICK, function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ _this.toggle();
+ });
+ };
+
+ _proto._getConfig = function _getConfig(config) {
+ config = _extends({}, this.constructor.Default, $$$1(this._element).data(), config);
+ Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
+ return config;
+ };
+
+ _proto._getMenuElement = function _getMenuElement() {
+ if (!this._menu) {
+ var parent = Dropdown._getParentFromElement(this._element);
+
+ this._menu = $$$1(parent).find(Selector.MENU)[0];
+ }
+
+ return this._menu;
+ };
+
+ _proto._getPlacement = function _getPlacement() {
+ var $parentDropdown = $$$1(this._element).parent();
+ var placement = AttachmentMap.BOTTOM; // Handle dropup
+
+ if ($parentDropdown.hasClass(ClassName.DROPUP)) {
+ placement = AttachmentMap.TOP;
+
+ if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) {
+ placement = AttachmentMap.TOPEND;
+ }
+ } else if ($parentDropdown.hasClass(ClassName.DROPRIGHT)) {
+ placement = AttachmentMap.RIGHT;
+ } else if ($parentDropdown.hasClass(ClassName.DROPLEFT)) {
+ placement = AttachmentMap.LEFT;
+ } else if ($$$1(this._menu).hasClass(ClassName.MENURIGHT)) {
+ placement = AttachmentMap.BOTTOMEND;
+ }
+
+ return placement;
+ };
+
+ _proto._detectNavbar = function _detectNavbar() {
+ return $$$1(this._element).closest('.navbar').length > 0;
+ };
+
+ _proto._getPopperConfig = function _getPopperConfig() {
+ var _this2 = this;
+
+ var offsetConf = {};
+
+ if (typeof this._config.offset === 'function') {
+ offsetConf.fn = function (data) {
+ data.offsets = _extends({}, data.offsets, _this2._config.offset(data.offsets) || {});
+ return data;
+ };
+ } else {
+ offsetConf.offset = this._config.offset;
+ }
+
+ var popperConfig = {
+ placement: this._getPlacement(),
+ modifiers: {
+ offset: offsetConf,
+ flip: {
+ enabled: this._config.flip
+ },
+ preventOverflow: {
+ boundariesElement: this._config.boundary
+ }
+ }
+ };
+ return popperConfig;
+ }; // static
+
+
+ Dropdown._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var data = $$$1(this).data(DATA_KEY);
+
+ var _config = typeof config === 'object' ? config : null;
+
+ if (!data) {
+ data = new Dropdown(this, _config);
+ $$$1(this).data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'string') {
+ if (typeof data[config] === 'undefined') {
+ throw new Error("No method named \"" + config + "\"");
+ }
+
+ data[config]();
+ }
+ });
+ };
+
+ Dropdown._clearMenus = function _clearMenus(event) {
+ if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) {
+ return;
+ }
+
+ var toggles = $$$1.makeArray($$$1(Selector.DATA_TOGGLE));
+
+ for (var i = 0; i < toggles.length; i++) {
+ var parent = Dropdown._getParentFromElement(toggles[i]);
+
+ var context = $$$1(toggles[i]).data(DATA_KEY);
+ var relatedTarget = {
+ relatedTarget: toggles[i]
+ };
+
+ if (!context) {
+ continue;
+ }
+
+ var dropdownMenu = context._menu;
+
+ if (!$$$1(parent).hasClass(ClassName.SHOW)) {
+ continue;
+ }
+
+ if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $$$1.contains(parent, event.target)) {
+ continue;
+ }
+
+ var hideEvent = $$$1.Event(Event.HIDE, relatedTarget);
+ $$$1(parent).trigger(hideEvent);
+
+ if (hideEvent.isDefaultPrevented()) {
+ continue;
+ } // if this is a touch-enabled device we remove the extra
+ // empty mouseover listeners we added for iOS support
+
+
+ if ('ontouchstart' in document.documentElement) {
+ $$$1('body').children().off('mouseover', null, $$$1.noop);
+ }
+
+ toggles[i].setAttribute('aria-expanded', 'false');
+ $$$1(dropdownMenu).removeClass(ClassName.SHOW);
+ $$$1(parent).removeClass(ClassName.SHOW).trigger($$$1.Event(Event.HIDDEN, relatedTarget));
+ }
+ };
+
+ Dropdown._getParentFromElement = function _getParentFromElement(element) {
+ var parent;
+ var selector = Util.getSelectorFromElement(element);
+
+ if (selector) {
+ parent = $$$1(selector)[0];
+ }
+
+ return parent || element.parentNode;
+ };
+
+ Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
+ // If not input/textarea:
+ // - And not a key in REGEXP_KEYDOWN => not a dropdown command
+ // If input/textarea:
+ // - If space key => not a dropdown command
+ // - If key is other than escape
+ // - If key is not up or down => not a dropdown command
+ // - If trigger inside the menu => not a dropdown command
+ if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $$$1(event.target).closest(Selector.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) {
+ return;
+ }
+
+ event.preventDefault();
+ event.stopPropagation();
+
+ if (this.disabled || $$$1(this).hasClass(ClassName.DISABLED)) {
+ return;
+ }
+
+ var parent = Dropdown._getParentFromElement(this);
+
+ var isActive = $$$1(parent).hasClass(ClassName.SHOW);
+
+ if (!isActive && (event.which !== ESCAPE_KEYCODE || event.which !== SPACE_KEYCODE) || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) {
+ if (event.which === ESCAPE_KEYCODE) {
+ var toggle = $$$1(parent).find(Selector.DATA_TOGGLE)[0];
+ $$$1(toggle).trigger('focus');
+ }
+
+ $$$1(this).trigger('click');
+ return;
+ }
+
+ var items = $$$1(parent).find(Selector.VISIBLE_ITEMS).get();
+
+ if (!items.length) {
+ return;
+ }
+
+ var index = items.indexOf(event.target);
+
+ if (event.which === ARROW_UP_KEYCODE && index > 0) {
+ // up
+ index--;
+ }
+
+ if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
+ // down
+ index++;
+ }
+
+ if (index < 0) {
+ index = 0;
+ }
+
+ items[index].focus();
+ };
+
+ _createClass(Dropdown, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }, {
+ key: "Default",
+ get: function get() {
+ return Default;
+ }
+ }, {
+ key: "DefaultType",
+ get: function get() {
+ return DefaultType;
+ }
+ }]);
+ return Dropdown;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.MENU, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API + " " + Event.KEYUP_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ Dropdown._jQueryInterface.call($$$1(this), 'toggle');
+ }).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
+ e.stopPropagation();
+ });
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $$$1.fn[NAME] = Dropdown._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Dropdown;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Dropdown._jQueryInterface;
+ };
+
+ return Dropdown;
+}($, Popper);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): modal.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Modal = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'modal';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.modal';
+ var EVENT_KEY = "." + DATA_KEY;
+ var DATA_API_KEY = '.data-api';
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var TRANSITION_DURATION = 300;
+ var BACKDROP_TRANSITION_DURATION = 150;
+ var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+
+ var Default = {
+ backdrop: true,
+ keyboard: true,
+ focus: true,
+ show: true
+ };
+ var DefaultType = {
+ backdrop: '(boolean|string)',
+ keyboard: 'boolean',
+ focus: 'boolean',
+ show: 'boolean'
+ };
+ var Event = {
+ HIDE: "hide" + EVENT_KEY,
+ HIDDEN: "hidden" + EVENT_KEY,
+ SHOW: "show" + EVENT_KEY,
+ SHOWN: "shown" + EVENT_KEY,
+ FOCUSIN: "focusin" + EVENT_KEY,
+ RESIZE: "resize" + EVENT_KEY,
+ CLICK_DISMISS: "click.dismiss" + EVENT_KEY,
+ KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY,
+ MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY,
+ MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY,
+ CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
+ };
+ var ClassName = {
+ SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
+ BACKDROP: 'modal-backdrop',
+ OPEN: 'modal-open',
+ FADE: 'fade',
+ SHOW: 'show'
+ };
+ var Selector = {
+ DIALOG: '.modal-dialog',
+ DATA_TOGGLE: '[data-toggle="modal"]',
+ DATA_DISMISS: '[data-dismiss="modal"]',
+ FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top',
+ STICKY_CONTENT: '.sticky-top',
+ NAVBAR_TOGGLER: '.navbar-toggler'
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Modal =
+ /*#__PURE__*/
+ function () {
+ function Modal(element, config) {
+ this._config = this._getConfig(config);
+ this._element = element;
+ this._dialog = $$$1(element).find(Selector.DIALOG)[0];
+ this._backdrop = null;
+ this._isShown = false;
+ this._isBodyOverflowing = false;
+ this._ignoreBackdropClick = false;
+ this._originalBodyPadding = 0;
+ this._scrollbarWidth = 0;
+ } // getters
+
+
+ var _proto = Modal.prototype;
+
+ // public
+ _proto.toggle = function toggle(relatedTarget) {
+ return this._isShown ? this.hide() : this.show(relatedTarget);
+ };
+
+ _proto.show = function show(relatedTarget) {
+ var _this = this;
+
+ if (this._isTransitioning || this._isShown) {
+ return;
+ }
+
+ if (Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.FADE)) {
+ this._isTransitioning = true;
+ }
+
+ var showEvent = $$$1.Event(Event.SHOW, {
+ relatedTarget: relatedTarget
+ });
+ $$$1(this._element).trigger(showEvent);
+
+ if (this._isShown || showEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ this._isShown = true;
+
+ this._checkScrollbar();
+
+ this._setScrollbar();
+
+ this._adjustDialog();
+
+ $$$1(document.body).addClass(ClassName.OPEN);
+
+ this._setEscapeEvent();
+
+ this._setResizeEvent();
+
+ $$$1(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, function (event) {
+ return _this.hide(event);
+ });
+ $$$1(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
+ $$$1(_this._element).one(Event.MOUSEUP_DISMISS, function (event) {
+ if ($$$1(event.target).is(_this._element)) {
+ _this._ignoreBackdropClick = true;
+ }
+ });
+ });
+
+ this._showBackdrop(function () {
+ return _this._showElement(relatedTarget);
+ });
+ };
+
+ _proto.hide = function hide(event) {
+ var _this2 = this;
+
+ if (event) {
+ event.preventDefault();
+ }
+
+ if (this._isTransitioning || !this._isShown) {
+ return;
+ }
+
+ var hideEvent = $$$1.Event(Event.HIDE);
+ $$$1(this._element).trigger(hideEvent);
+
+ if (!this._isShown || hideEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ this._isShown = false;
+ var transition = Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.FADE);
+
+ if (transition) {
+ this._isTransitioning = true;
+ }
+
+ this._setEscapeEvent();
+
+ this._setResizeEvent();
+
+ $$$1(document).off(Event.FOCUSIN);
+ $$$1(this._element).removeClass(ClassName.SHOW);
+ $$$1(this._element).off(Event.CLICK_DISMISS);
+ $$$1(this._dialog).off(Event.MOUSEDOWN_DISMISS);
+
+ if (transition) {
+ $$$1(this._element).one(Util.TRANSITION_END, function (event) {
+ return _this2._hideModal(event);
+ }).emulateTransitionEnd(TRANSITION_DURATION);
+ } else {
+ this._hideModal();
+ }
+ };
+
+ _proto.dispose = function dispose() {
+ $$$1.removeData(this._element, DATA_KEY);
+ $$$1(window, document, this._element, this._backdrop).off(EVENT_KEY);
+ this._config = null;
+ this._element = null;
+ this._dialog = null;
+ this._backdrop = null;
+ this._isShown = null;
+ this._isBodyOverflowing = null;
+ this._ignoreBackdropClick = null;
+ this._scrollbarWidth = null;
+ };
+
+ _proto.handleUpdate = function handleUpdate() {
+ this._adjustDialog();
+ }; // private
+
+
+ _proto._getConfig = function _getConfig(config) {
+ config = _extends({}, Default, config);
+ Util.typeCheckConfig(NAME, config, DefaultType);
+ return config;
+ };
+
+ _proto._showElement = function _showElement(relatedTarget) {
+ var _this3 = this;
+
+ var transition = Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.FADE);
+
+ if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
+ // don't move modals dom position
+ document.body.appendChild(this._element);
+ }
+
+ this._element.style.display = 'block';
+
+ this._element.removeAttribute('aria-hidden');
+
+ this._element.scrollTop = 0;
+
+ if (transition) {
+ Util.reflow(this._element);
+ }
+
+ $$$1(this._element).addClass(ClassName.SHOW);
+
+ if (this._config.focus) {
+ this._enforceFocus();
+ }
+
+ var shownEvent = $$$1.Event(Event.SHOWN, {
+ relatedTarget: relatedTarget
+ });
+
+ var transitionComplete = function transitionComplete() {
+ if (_this3._config.focus) {
+ _this3._element.focus();
+ }
+
+ _this3._isTransitioning = false;
+ $$$1(_this3._element).trigger(shownEvent);
+ };
+
+ if (transition) {
+ $$$1(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION);
+ } else {
+ transitionComplete();
+ }
+ };
+
+ _proto._enforceFocus = function _enforceFocus() {
+ var _this4 = this;
+
+ $$$1(document).off(Event.FOCUSIN) // guard against infinite focus loop
+ .on(Event.FOCUSIN, function (event) {
+ if (document !== event.target && _this4._element !== event.target && !$$$1(_this4._element).has(event.target).length) {
+ _this4._element.focus();
+ }
+ });
+ };
+
+ _proto._setEscapeEvent = function _setEscapeEvent() {
+ var _this5 = this;
+
+ if (this._isShown && this._config.keyboard) {
+ $$$1(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
+ if (event.which === ESCAPE_KEYCODE) {
+ event.preventDefault();
+
+ _this5.hide();
+ }
+ });
+ } else if (!this._isShown) {
+ $$$1(this._element).off(Event.KEYDOWN_DISMISS);
+ }
+ };
+
+ _proto._setResizeEvent = function _setResizeEvent() {
+ var _this6 = this;
+
+ if (this._isShown) {
+ $$$1(window).on(Event.RESIZE, function (event) {
+ return _this6.handleUpdate(event);
+ });
+ } else {
+ $$$1(window).off(Event.RESIZE);
+ }
+ };
+
+ _proto._hideModal = function _hideModal() {
+ var _this7 = this;
+
+ this._element.style.display = 'none';
+
+ this._element.setAttribute('aria-hidden', true);
+
+ this._isTransitioning = false;
+
+ this._showBackdrop(function () {
+ $$$1(document.body).removeClass(ClassName.OPEN);
+
+ _this7._resetAdjustments();
+
+ _this7._resetScrollbar();
+
+ $$$1(_this7._element).trigger(Event.HIDDEN);
+ });
+ };
+
+ _proto._removeBackdrop = function _removeBackdrop() {
+ if (this._backdrop) {
+ $$$1(this._backdrop).remove();
+ this._backdrop = null;
+ }
+ };
+
+ _proto._showBackdrop = function _showBackdrop(callback) {
+ var _this8 = this;
+
+ var animate = $$$1(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
+
+ if (this._isShown && this._config.backdrop) {
+ var doAnimate = Util.supportsTransitionEnd() && animate;
+ this._backdrop = document.createElement('div');
+ this._backdrop.className = ClassName.BACKDROP;
+
+ if (animate) {
+ $$$1(this._backdrop).addClass(animate);
+ }
+
+ $$$1(this._backdrop).appendTo(document.body);
+ $$$1(this._element).on(Event.CLICK_DISMISS, function (event) {
+ if (_this8._ignoreBackdropClick) {
+ _this8._ignoreBackdropClick = false;
+ return;
+ }
+
+ if (event.target !== event.currentTarget) {
+ return;
+ }
+
+ if (_this8._config.backdrop === 'static') {
+ _this8._element.focus();
+ } else {
+ _this8.hide();
+ }
+ });
+
+ if (doAnimate) {
+ Util.reflow(this._backdrop);
+ }
+
+ $$$1(this._backdrop).addClass(ClassName.SHOW);
+
+ if (!callback) {
+ return;
+ }
+
+ if (!doAnimate) {
+ callback();
+ return;
+ }
+
+ $$$1(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+ } else if (!this._isShown && this._backdrop) {
+ $$$1(this._backdrop).removeClass(ClassName.SHOW);
+
+ var callbackRemove = function callbackRemove() {
+ _this8._removeBackdrop();
+
+ if (callback) {
+ callback();
+ }
+ };
+
+ if (Util.supportsTransitionEnd() && $$$1(this._element).hasClass(ClassName.FADE)) {
+ $$$1(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+ } else {
+ callbackRemove();
+ }
+ } else if (callback) {
+ callback();
+ }
+ }; // ----------------------------------------------------------------------
+ // the following methods are used to handle overflowing modals
+ // todo (fat): these should probably be refactored out of modal.js
+ // ----------------------------------------------------------------------
+
+
+ _proto._adjustDialog = function _adjustDialog() {
+ var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
+
+ if (!this._isBodyOverflowing && isModalOverflowing) {
+ this._element.style.paddingLeft = this._scrollbarWidth + "px";
+ }
+
+ if (this._isBodyOverflowing && !isModalOverflowing) {
+ this._element.style.paddingRight = this._scrollbarWidth + "px";
+ }
+ };
+
+ _proto._resetAdjustments = function _resetAdjustments() {
+ this._element.style.paddingLeft = '';
+ this._element.style.paddingRight = '';
+ };
+
+ _proto._checkScrollbar = function _checkScrollbar() {
+ var rect = document.body.getBoundingClientRect();
+ this._isBodyOverflowing = rect.left + rect.right < window.innerWidth;
+ this._scrollbarWidth = this._getScrollbarWidth();
+ };
+
+ _proto._setScrollbar = function _setScrollbar() {
+ var _this9 = this;
+
+ if (this._isBodyOverflowing) {
+ // Note: DOMNode.style.paddingRight returns the actual value or '' if not set
+ // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set
+ // Adjust fixed content padding
+ $$$1(Selector.FIXED_CONTENT).each(function (index, element) {
+ var actualPadding = $$$1(element)[0].style.paddingRight;
+ var calculatedPadding = $$$1(element).css('padding-right');
+ $$$1(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this9._scrollbarWidth + "px");
+ }); // Adjust sticky content margin
+
+ $$$1(Selector.STICKY_CONTENT).each(function (index, element) {
+ var actualMargin = $$$1(element)[0].style.marginRight;
+ var calculatedMargin = $$$1(element).css('margin-right');
+ $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this9._scrollbarWidth + "px");
+ }); // Adjust navbar-toggler margin
+
+ $$$1(Selector.NAVBAR_TOGGLER).each(function (index, element) {
+ var actualMargin = $$$1(element)[0].style.marginRight;
+ var calculatedMargin = $$$1(element).css('margin-right');
+ $$$1(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) + _this9._scrollbarWidth + "px");
+ }); // Adjust body padding
+
+ var actualPadding = document.body.style.paddingRight;
+ var calculatedPadding = $$$1('body').css('padding-right');
+ $$$1('body').data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px");
+ }
+ };
+
+ _proto._resetScrollbar = function _resetScrollbar() {
+ // Restore fixed content padding
+ $$$1(Selector.FIXED_CONTENT).each(function (index, element) {
+ var padding = $$$1(element).data('padding-right');
+
+ if (typeof padding !== 'undefined') {
+ $$$1(element).css('padding-right', padding).removeData('padding-right');
+ }
+ }); // Restore sticky content and navbar-toggler margin
+
+ $$$1(Selector.STICKY_CONTENT + ", " + Selector.NAVBAR_TOGGLER).each(function (index, element) {
+ var margin = $$$1(element).data('margin-right');
+
+ if (typeof margin !== 'undefined') {
+ $$$1(element).css('margin-right', margin).removeData('margin-right');
+ }
+ }); // Restore body padding
+
+ var padding = $$$1('body').data('padding-right');
+
+ if (typeof padding !== 'undefined') {
+ $$$1('body').css('padding-right', padding).removeData('padding-right');
+ }
+ };
+
+ _proto._getScrollbarWidth = function _getScrollbarWidth() {
+ // thx d.walsh
+ var scrollDiv = document.createElement('div');
+ scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
+ document.body.appendChild(scrollDiv);
+ var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth;
+ document.body.removeChild(scrollDiv);
+ return scrollbarWidth;
+ }; // static
+
+
+ Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
+ return this.each(function () {
+ var data = $$$1(this).data(DATA_KEY);
+
+ var _config = _extends({}, Modal.Default, $$$1(this).data(), typeof config === 'object' && config);
+
+ if (!data) {
+ data = new Modal(this, _config);
+ $$$1(this).data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'string') {
+ if (typeof data[config] === 'undefined') {
+ throw new Error("No method named \"" + config + "\"");
+ }
+
+ data[config](relatedTarget);
+ } else if (_config.show) {
+ data.show(relatedTarget);
+ }
+ });
+ };
+
+ _createClass(Modal, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }, {
+ key: "Default",
+ get: function get() {
+ return Default;
+ }
+ }]);
+ return Modal;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+ var _this10 = this;
+
+ var target;
+ var selector = Util.getSelectorFromElement(this);
+
+ if (selector) {
+ target = $$$1(selector)[0];
+ }
+
+ var config = $$$1(target).data(DATA_KEY) ? 'toggle' : _extends({}, $$$1(target).data(), $$$1(this).data());
+
+ if (this.tagName === 'A' || this.tagName === 'AREA') {
+ event.preventDefault();
+ }
+
+ var $target = $$$1(target).one(Event.SHOW, function (showEvent) {
+ if (showEvent.isDefaultPrevented()) {
+ // only register focus restorer if modal will actually get shown
+ return;
+ }
+
+ $target.one(Event.HIDDEN, function () {
+ if ($$$1(_this10).is(':visible')) {
+ _this10.focus();
+ }
+ });
+ });
+
+ Modal._jQueryInterface.call($$$1(target), config, this);
+ });
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $$$1.fn[NAME] = Modal._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Modal;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Modal._jQueryInterface;
+ };
+
+ return Modal;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): tooltip.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tooltip = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'tooltip';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.tooltip';
+ var EVENT_KEY = "." + DATA_KEY;
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var TRANSITION_DURATION = 150;
+ var CLASS_PREFIX = 'bs-tooltip';
+ var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
+ var DefaultType = {
+ animation: 'boolean',
+ template: 'string',
+ title: '(string|element|function)',
+ trigger: 'string',
+ delay: '(number|object)',
+ html: 'boolean',
+ selector: '(string|boolean)',
+ placement: '(string|function)',
+ offset: '(number|string)',
+ container: '(string|element|boolean)',
+ fallbackPlacement: '(string|array)',
+ boundary: '(string|element)'
+ };
+ var AttachmentMap = {
+ AUTO: 'auto',
+ TOP: 'top',
+ RIGHT: 'right',
+ BOTTOM: 'bottom',
+ LEFT: 'left'
+ };
+ var Default = {
+ animation: true,
+ template: '<div class="tooltip" role="tooltip">' + '<div class="arrow"></div>' + '<div class="tooltip-inner"></div></div>',
+ trigger: 'hover focus',
+ title: '',
+ delay: 0,
+ html: false,
+ selector: false,
+ placement: 'top',
+ offset: 0,
+ container: false,
+ fallbackPlacement: 'flip',
+ boundary: 'scrollParent'
+ };
+ var HoverState = {
+ SHOW: 'show',
+ OUT: 'out'
+ };
+ var Event = {
+ HIDE: "hide" + EVENT_KEY,
+ HIDDEN: "hidden" + EVENT_KEY,
+ SHOW: "show" + EVENT_KEY,
+ SHOWN: "shown" + EVENT_KEY,
+ INSERTED: "inserted" + EVENT_KEY,
+ CLICK: "click" + EVENT_KEY,
+ FOCUSIN: "focusin" + EVENT_KEY,
+ FOCUSOUT: "focusout" + EVENT_KEY,
+ MOUSEENTER: "mouseenter" + EVENT_KEY,
+ MOUSELEAVE: "mouseleave" + EVENT_KEY
+ };
+ var ClassName = {
+ FADE: 'fade',
+ SHOW: 'show'
+ };
+ var Selector = {
+ TOOLTIP: '.tooltip',
+ TOOLTIP_INNER: '.tooltip-inner',
+ ARROW: '.arrow'
+ };
+ var Trigger = {
+ HOVER: 'hover',
+ FOCUS: 'focus',
+ CLICK: 'click',
+ MANUAL: 'manual'
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Tooltip =
+ /*#__PURE__*/
+ function () {
+ function Tooltip(element, config) {
+ /**
+ * Check for Popper dependency
+ * Popper - https://popper.js.org
+ */
+ if (typeof Popper === 'undefined') {
+ throw new Error('Bootstrap tooltips require Popper.js (https://popper.js.org)');
+ } // private
+
+
+ this._isEnabled = true;
+ this._timeout = 0;
+ this._hoverState = '';
+ this._activeTrigger = {};
+ this._popper = null; // protected
+
+ this.element = element;
+ this.config = this._getConfig(config);
+ this.tip = null;
+
+ this._setListeners();
+ } // getters
+
+
+ var _proto = Tooltip.prototype;
+
+ // public
+ _proto.enable = function enable() {
+ this._isEnabled = true;
+ };
+
+ _proto.disable = function disable() {
+ this._isEnabled = false;
+ };
+
+ _proto.toggleEnabled = function toggleEnabled() {
+ this._isEnabled = !this._isEnabled;
+ };
+
+ _proto.toggle = function toggle(event) {
+ if (!this._isEnabled) {
+ return;
+ }
+
+ if (event) {
+ var dataKey = this.constructor.DATA_KEY;
+ var context = $$$1(event.currentTarget).data(dataKey);
+
+ if (!context) {
+ context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+ $$$1(event.currentTarget).data(dataKey, context);
+ }
+
+ context._activeTrigger.click = !context._activeTrigger.click;
+
+ if (context._isWithActiveTrigger()) {
+ context._enter(null, context);
+ } else {
+ context._leave(null, context);
+ }
+ } else {
+ if ($$$1(this.getTipElement()).hasClass(ClassName.SHOW)) {
+ this._leave(null, this);
+
+ return;
+ }
+
+ this._enter(null, this);
+ }
+ };
+
+ _proto.dispose = function dispose() {
+ clearTimeout(this._timeout);
+ $$$1.removeData(this.element, this.constructor.DATA_KEY);
+ $$$1(this.element).off(this.constructor.EVENT_KEY);
+ $$$1(this.element).closest('.modal').off('hide.bs.modal');
+
+ if (this.tip) {
+ $$$1(this.tip).remove();
+ }
+
+ this._isEnabled = null;
+ this._timeout = null;
+ this._hoverState = null;
+ this._activeTrigger = null;
+
+ if (this._popper !== null) {
+ this._popper.destroy();
+ }
+
+ this._popper = null;
+ this.element = null;
+ this.config = null;
+ this.tip = null;
+ };
+
+ _proto.show = function show() {
+ var _this = this;
+
+ if ($$$1(this.element).css('display') === 'none') {
+ throw new Error('Please use show on visible elements');
+ }
+
+ var showEvent = $$$1.Event(this.constructor.Event.SHOW);
+
+ if (this.isWithContent() && this._isEnabled) {
+ $$$1(this.element).trigger(showEvent);
+ var isInTheDom = $$$1.contains(this.element.ownerDocument.documentElement, this.element);
+
+ if (showEvent.isDefaultPrevented() || !isInTheDom) {
+ return;
+ }
+
+ var tip = this.getTipElement();
+ var tipId = Util.getUID(this.constructor.NAME);
+ tip.setAttribute('id', tipId);
+ this.element.setAttribute('aria-describedby', tipId);
+ this.setContent();
+
+ if (this.config.animation) {
+ $$$1(tip).addClass(ClassName.FADE);
+ }
+
+ var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
+
+ var attachment = this._getAttachment(placement);
+
+ this.addAttachmentClass(attachment);
+ var container = this.config.container === false ? document.body : $$$1(this.config.container);
+ $$$1(tip).data(this.constructor.DATA_KEY, this);
+
+ if (!$$$1.contains(this.element.ownerDocument.documentElement, this.tip)) {
+ $$$1(tip).appendTo(container);
+ }
+
+ $$$1(this.element).trigger(this.constructor.Event.INSERTED);
+ this._popper = new Popper(this.element, tip, {
+ placement: attachment,
+ modifiers: {
+ offset: {
+ offset: this.config.offset
+ },
+ flip: {
+ behavior: this.config.fallbackPlacement
+ },
+ arrow: {
+ element: Selector.ARROW
+ },
+ preventOverflow: {
+ boundariesElement: this.config.boundary
+ }
+ },
+ onCreate: function onCreate(data) {
+ if (data.originalPlacement !== data.placement) {
+ _this._handlePopperPlacementChange(data);
+ }
+ },
+ onUpdate: function onUpdate(data) {
+ _this._handlePopperPlacementChange(data);
+ }
+ });
+ $$$1(tip).addClass(ClassName.SHOW); // if this is a touch-enabled device we add extra
+ // empty mouseover listeners to the body's immediate children;
+ // only needed because of broken event delegation on iOS
+ // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
+
+ if ('ontouchstart' in document.documentElement) {
+ $$$1('body').children().on('mouseover', null, $$$1.noop);
+ }
+
+ var complete = function complete() {
+ if (_this.config.animation) {
+ _this._fixTransition();
+ }
+
+ var prevHoverState = _this._hoverState;
+ _this._hoverState = null;
+ $$$1(_this.element).trigger(_this.constructor.Event.SHOWN);
+
+ if (prevHoverState === HoverState.OUT) {
+ _this._leave(null, _this);
+ }
+ };
+
+ if (Util.supportsTransitionEnd() && $$$1(this.tip).hasClass(ClassName.FADE)) {
+ $$$1(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);
+ } else {
+ complete();
+ }
+ }
+ };
+
+ _proto.hide = function hide(callback) {
+ var _this2 = this;
+
+ var tip = this.getTipElement();
+ var hideEvent = $$$1.Event(this.constructor.Event.HIDE);
+
+ var complete = function complete() {
+ if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) {
+ tip.parentNode.removeChild(tip);
+ }
+
+ _this2._cleanTipClass();
+
+ _this2.element.removeAttribute('aria-describedby');
+
+ $$$1(_this2.element).trigger(_this2.constructor.Event.HIDDEN);
+
+ if (_this2._popper !== null) {
+ _this2._popper.destroy();
+ }
+
+ if (callback) {
+ callback();
+ }
+ };
+
+ $$$1(this.element).trigger(hideEvent);
+
+ if (hideEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ $$$1(tip).removeClass(ClassName.SHOW); // if this is a touch-enabled device we remove the extra
+ // empty mouseover listeners we added for iOS support
+
+ if ('ontouchstart' in document.documentElement) {
+ $$$1('body').children().off('mouseover', null, $$$1.noop);
+ }
+
+ this._activeTrigger[Trigger.CLICK] = false;
+ this._activeTrigger[Trigger.FOCUS] = false;
+ this._activeTrigger[Trigger.HOVER] = false;
+
+ if (Util.supportsTransitionEnd() && $$$1(this.tip).hasClass(ClassName.FADE)) {
+ $$$1(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+ } else {
+ complete();
+ }
+
+ this._hoverState = '';
+ };
+
+ _proto.update = function update() {
+ if (this._popper !== null) {
+ this._popper.scheduleUpdate();
+ }
+ }; // protected
+
+
+ _proto.isWithContent = function isWithContent() {
+ return Boolean(this.getTitle());
+ };
+
+ _proto.addAttachmentClass = function addAttachmentClass(attachment) {
+ $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
+ };
+
+ _proto.getTipElement = function getTipElement() {
+ this.tip = this.tip || $$$1(this.config.template)[0];
+ return this.tip;
+ };
+
+ _proto.setContent = function setContent() {
+ var $tip = $$$1(this.getTipElement());
+ this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
+ $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW);
+ };
+
+ _proto.setElementContent = function setElementContent($element, content) {
+ var html = this.config.html;
+
+ if (typeof content === 'object' && (content.nodeType || content.jquery)) {
+ // content is a DOM node or a jQuery
+ if (html) {
+ if (!$$$1(content).parent().is($element)) {
+ $element.empty().append(content);
+ }
+ } else {
+ $element.text($$$1(content).text());
+ }
+ } else {
+ $element[html ? 'html' : 'text'](content);
+ }
+ };
+
+ _proto.getTitle = function getTitle() {
+ var title = this.element.getAttribute('data-original-title');
+
+ if (!title) {
+ title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
+ }
+
+ return title;
+ }; // private
+
+
+ _proto._getAttachment = function _getAttachment(placement) {
+ return AttachmentMap[placement.toUpperCase()];
+ };
+
+ _proto._setListeners = function _setListeners() {
+ var _this3 = this;
+
+ var triggers = this.config.trigger.split(' ');
+ triggers.forEach(function (trigger) {
+ if (trigger === 'click') {
+ $$$1(_this3.element).on(_this3.constructor.Event.CLICK, _this3.config.selector, function (event) {
+ return _this3.toggle(event);
+ });
+ } else if (trigger !== Trigger.MANUAL) {
+ var eventIn = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSEENTER : _this3.constructor.Event.FOCUSIN;
+ var eventOut = trigger === Trigger.HOVER ? _this3.constructor.Event.MOUSELEAVE : _this3.constructor.Event.FOCUSOUT;
+ $$$1(_this3.element).on(eventIn, _this3.config.selector, function (event) {
+ return _this3._enter(event);
+ }).on(eventOut, _this3.config.selector, function (event) {
+ return _this3._leave(event);
+ });
+ }
+
+ $$$1(_this3.element).closest('.modal').on('hide.bs.modal', function () {
+ return _this3.hide();
+ });
+ });
+
+ if (this.config.selector) {
+ this.config = _extends({}, this.config, {
+ trigger: 'manual',
+ selector: ''
+ });
+ } else {
+ this._fixTitle();
+ }
+ };
+
+ _proto._fixTitle = function _fixTitle() {
+ var titleType = typeof this.element.getAttribute('data-original-title');
+
+ if (this.element.getAttribute('title') || titleType !== 'string') {
+ this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
+ this.element.setAttribute('title', '');
+ }
+ };
+
+ _proto._enter = function _enter(event, context) {
+ var dataKey = this.constructor.DATA_KEY;
+ context = context || $$$1(event.currentTarget).data(dataKey);
+
+ if (!context) {
+ context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+ $$$1(event.currentTarget).data(dataKey, context);
+ }
+
+ if (event) {
+ context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
+ }
+
+ if ($$$1(context.getTipElement()).hasClass(ClassName.SHOW) || context._hoverState === HoverState.SHOW) {
+ context._hoverState = HoverState.SHOW;
+ return;
+ }
+
+ clearTimeout(context._timeout);
+ context._hoverState = HoverState.SHOW;
+
+ if (!context.config.delay || !context.config.delay.show) {
+ context.show();
+ return;
+ }
+
+ context._timeout = setTimeout(function () {
+ if (context._hoverState === HoverState.SHOW) {
+ context.show();
+ }
+ }, context.config.delay.show);
+ };
+
+ _proto._leave = function _leave(event, context) {
+ var dataKey = this.constructor.DATA_KEY;
+ context = context || $$$1(event.currentTarget).data(dataKey);
+
+ if (!context) {
+ context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+ $$$1(event.currentTarget).data(dataKey, context);
+ }
+
+ if (event) {
+ context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
+ }
+
+ if (context._isWithActiveTrigger()) {
+ return;
+ }
+
+ clearTimeout(context._timeout);
+ context._hoverState = HoverState.OUT;
+
+ if (!context.config.delay || !context.config.delay.hide) {
+ context.hide();
+ return;
+ }
+
+ context._timeout = setTimeout(function () {
+ if (context._hoverState === HoverState.OUT) {
+ context.hide();
+ }
+ }, context.config.delay.hide);
+ };
+
+ _proto._isWithActiveTrigger = function _isWithActiveTrigger() {
+ for (var trigger in this._activeTrigger) {
+ if (this._activeTrigger[trigger]) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+
+ _proto._getConfig = function _getConfig(config) {
+ config = _extends({}, this.constructor.Default, $$$1(this.element).data(), config);
+
+ if (typeof config.delay === 'number') {
+ config.delay = {
+ show: config.delay,
+ hide: config.delay
+ };
+ }
+
+ if (typeof config.title === 'number') {
+ config.title = config.title.toString();
+ }
+
+ if (typeof config.content === 'number') {
+ config.content = config.content.toString();
+ }
+
+ Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
+ return config;
+ };
+
+ _proto._getDelegateConfig = function _getDelegateConfig() {
+ var config = {};
+
+ if (this.config) {
+ for (var key in this.config) {
+ if (this.constructor.Default[key] !== this.config[key]) {
+ config[key] = this.config[key];
+ }
+ }
+ }
+
+ return config;
+ };
+
+ _proto._cleanTipClass = function _cleanTipClass() {
+ var $tip = $$$1(this.getTipElement());
+ var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
+
+ if (tabClass !== null && tabClass.length > 0) {
+ $tip.removeClass(tabClass.join(''));
+ }
+ };
+
+ _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(data) {
+ this._cleanTipClass();
+
+ this.addAttachmentClass(this._getAttachment(data.placement));
+ };
+
+ _proto._fixTransition = function _fixTransition() {
+ var tip = this.getTipElement();
+ var initConfigAnimation = this.config.animation;
+
+ if (tip.getAttribute('x-placement') !== null) {
+ return;
+ }
+
+ $$$1(tip).removeClass(ClassName.FADE);
+ this.config.animation = false;
+ this.hide();
+ this.show();
+ this.config.animation = initConfigAnimation;
+ }; // static
+
+
+ Tooltip._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var data = $$$1(this).data(DATA_KEY);
+
+ var _config = typeof config === 'object' && config;
+
+ if (!data && /dispose|hide/.test(config)) {
+ return;
+ }
+
+ if (!data) {
+ data = new Tooltip(this, _config);
+ $$$1(this).data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'string') {
+ if (typeof data[config] === 'undefined') {
+ throw new Error("No method named \"" + config + "\"");
+ }
+
+ data[config]();
+ }
+ });
+ };
+
+ _createClass(Tooltip, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }, {
+ key: "Default",
+ get: function get() {
+ return Default;
+ }
+ }, {
+ key: "NAME",
+ get: function get() {
+ return NAME;
+ }
+ }, {
+ key: "DATA_KEY",
+ get: function get() {
+ return DATA_KEY;
+ }
+ }, {
+ key: "Event",
+ get: function get() {
+ return Event;
+ }
+ }, {
+ key: "EVENT_KEY",
+ get: function get() {
+ return EVENT_KEY;
+ }
+ }, {
+ key: "DefaultType",
+ get: function get() {
+ return DefaultType;
+ }
+ }]);
+ return Tooltip;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1.fn[NAME] = Tooltip._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Tooltip;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Tooltip._jQueryInterface;
+ };
+
+ return Tooltip;
+}($, Popper);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): popover.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Popover = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'popover';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.popover';
+ var EVENT_KEY = "." + DATA_KEY;
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var CLASS_PREFIX = 'bs-popover';
+ var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g');
+ var Default = _extends({}, Tooltip.Default, {
+ placement: 'right',
+ trigger: 'click',
+ content: '',
+ template: '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-header"></h3>' + '<div class="popover-body"></div></div>'
+ });
+ var DefaultType = _extends({}, Tooltip.DefaultType, {
+ content: '(string|element|function)'
+ });
+ var ClassName = {
+ FADE: 'fade',
+ SHOW: 'show'
+ };
+ var Selector = {
+ TITLE: '.popover-header',
+ CONTENT: '.popover-body'
+ };
+ var Event = {
+ HIDE: "hide" + EVENT_KEY,
+ HIDDEN: "hidden" + EVENT_KEY,
+ SHOW: "show" + EVENT_KEY,
+ SHOWN: "shown" + EVENT_KEY,
+ INSERTED: "inserted" + EVENT_KEY,
+ CLICK: "click" + EVENT_KEY,
+ FOCUSIN: "focusin" + EVENT_KEY,
+ FOCUSOUT: "focusout" + EVENT_KEY,
+ MOUSEENTER: "mouseenter" + EVENT_KEY,
+ MOUSELEAVE: "mouseleave" + EVENT_KEY
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Popover =
+ /*#__PURE__*/
+ function (_Tooltip) {
+ _inheritsLoose(Popover, _Tooltip);
+
+ function Popover() {
+ return _Tooltip.apply(this, arguments) || this;
+ }
+
+ var _proto = Popover.prototype;
+
+ // overrides
+ _proto.isWithContent = function isWithContent() {
+ return this.getTitle() || this._getContent();
+ };
+
+ _proto.addAttachmentClass = function addAttachmentClass(attachment) {
+ $$$1(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment);
+ };
+
+ _proto.getTipElement = function getTipElement() {
+ this.tip = this.tip || $$$1(this.config.template)[0];
+ return this.tip;
+ };
+
+ _proto.setContent = function setContent() {
+ var $tip = $$$1(this.getTipElement()); // we use append for html objects to maintain js events
+
+ this.setElementContent($tip.find(Selector.TITLE), this.getTitle());
+
+ var content = this._getContent();
+
+ if (typeof content === 'function') {
+ content = content.call(this.element);
+ }
+
+ this.setElementContent($tip.find(Selector.CONTENT), content);
+ $tip.removeClass(ClassName.FADE + " " + ClassName.SHOW);
+ }; // private
+
+
+ _proto._getContent = function _getContent() {
+ return this.element.getAttribute('data-content') || this.config.content;
+ };
+
+ _proto._cleanTipClass = function _cleanTipClass() {
+ var $tip = $$$1(this.getTipElement());
+ var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX);
+
+ if (tabClass !== null && tabClass.length > 0) {
+ $tip.removeClass(tabClass.join(''));
+ }
+ }; // static
+
+
+ Popover._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var data = $$$1(this).data(DATA_KEY);
+
+ var _config = typeof config === 'object' ? config : null;
+
+ if (!data && /destroy|hide/.test(config)) {
+ return;
+ }
+
+ if (!data) {
+ data = new Popover(this, _config);
+ $$$1(this).data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'string') {
+ if (typeof data[config] === 'undefined') {
+ throw new Error("No method named \"" + config + "\"");
+ }
+
+ data[config]();
+ }
+ });
+ };
+
+ _createClass(Popover, null, [{
+ key: "VERSION",
+ // getters
+ get: function get() {
+ return VERSION;
+ }
+ }, {
+ key: "Default",
+ get: function get() {
+ return Default;
+ }
+ }, {
+ key: "NAME",
+ get: function get() {
+ return NAME;
+ }
+ }, {
+ key: "DATA_KEY",
+ get: function get() {
+ return DATA_KEY;
+ }
+ }, {
+ key: "Event",
+ get: function get() {
+ return Event;
+ }
+ }, {
+ key: "EVENT_KEY",
+ get: function get() {
+ return EVENT_KEY;
+ }
+ }, {
+ key: "DefaultType",
+ get: function get() {
+ return DefaultType;
+ }
+ }]);
+ return Popover;
+ }(Tooltip);
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1.fn[NAME] = Popover._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Popover;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Popover._jQueryInterface;
+ };
+
+ return Popover;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): scrollspy.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var ScrollSpy = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'scrollspy';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.scrollspy';
+ var EVENT_KEY = "." + DATA_KEY;
+ var DATA_API_KEY = '.data-api';
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var Default = {
+ offset: 10,
+ method: 'auto',
+ target: ''
+ };
+ var DefaultType = {
+ offset: 'number',
+ method: 'string',
+ target: '(string|element)'
+ };
+ var Event = {
+ ACTIVATE: "activate" + EVENT_KEY,
+ SCROLL: "scroll" + EVENT_KEY,
+ LOAD_DATA_API: "load" + EVENT_KEY + DATA_API_KEY
+ };
+ var ClassName = {
+ DROPDOWN_ITEM: 'dropdown-item',
+ DROPDOWN_MENU: 'dropdown-menu',
+ ACTIVE: 'active'
+ };
+ var Selector = {
+ DATA_SPY: '[data-spy="scroll"]',
+ ACTIVE: '.active',
+ NAV_LIST_GROUP: '.nav, .list-group',
+ NAV_LINKS: '.nav-link',
+ NAV_ITEMS: '.nav-item',
+ LIST_ITEMS: '.list-group-item',
+ DROPDOWN: '.dropdown',
+ DROPDOWN_ITEMS: '.dropdown-item',
+ DROPDOWN_TOGGLE: '.dropdown-toggle'
+ };
+ var OffsetMethod = {
+ OFFSET: 'offset',
+ POSITION: 'position'
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var ScrollSpy =
+ /*#__PURE__*/
+ function () {
+ function ScrollSpy(element, config) {
+ var _this = this;
+
+ this._element = element;
+ this._scrollElement = element.tagName === 'BODY' ? window : element;
+ this._config = this._getConfig(config);
+ this._selector = this._config.target + " " + Selector.NAV_LINKS + "," + (this._config.target + " " + Selector.LIST_ITEMS + ",") + (this._config.target + " " + Selector.DROPDOWN_ITEMS);
+ this._offsets = [];
+ this._targets = [];
+ this._activeTarget = null;
+ this._scrollHeight = 0;
+ $$$1(this._scrollElement).on(Event.SCROLL, function (event) {
+ return _this._process(event);
+ });
+ this.refresh();
+
+ this._process();
+ } // getters
+
+
+ var _proto = ScrollSpy.prototype;
+
+ // public
+ _proto.refresh = function refresh() {
+ var _this2 = this;
+
+ var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
+ var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
+ var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
+ this._offsets = [];
+ this._targets = [];
+ this._scrollHeight = this._getScrollHeight();
+ var targets = $$$1.makeArray($$$1(this._selector));
+ targets.map(function (element) {
+ var target;
+ var targetSelector = Util.getSelectorFromElement(element);
+
+ if (targetSelector) {
+ target = $$$1(targetSelector)[0];
+ }
+
+ if (target) {
+ var targetBCR = target.getBoundingClientRect();
+
+ if (targetBCR.width || targetBCR.height) {
+ // todo (fat): remove sketch reliance on jQuery position/offset
+ return [$$$1(target)[offsetMethod]().top + offsetBase, targetSelector];
+ }
+ }
+
+ return null;
+ }).filter(function (item) {
+ return item;
+ }).sort(function (a, b) {
+ return a[0] - b[0];
+ }).forEach(function (item) {
+ _this2._offsets.push(item[0]);
+
+ _this2._targets.push(item[1]);
+ });
+ };
+
+ _proto.dispose = function dispose() {
+ $$$1.removeData(this._element, DATA_KEY);
+ $$$1(this._scrollElement).off(EVENT_KEY);
+ this._element = null;
+ this._scrollElement = null;
+ this._config = null;
+ this._selector = null;
+ this._offsets = null;
+ this._targets = null;
+ this._activeTarget = null;
+ this._scrollHeight = null;
+ }; // private
+
+
+ _proto._getConfig = function _getConfig(config) {
+ config = _extends({}, Default, config);
+
+ if (typeof config.target !== 'string') {
+ var id = $$$1(config.target).attr('id');
+
+ if (!id) {
+ id = Util.getUID(NAME);
+ $$$1(config.target).attr('id', id);
+ }
+
+ config.target = "#" + id;
+ }
+
+ Util.typeCheckConfig(NAME, config, DefaultType);
+ return config;
+ };
+
+ _proto._getScrollTop = function _getScrollTop() {
+ return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop;
+ };
+
+ _proto._getScrollHeight = function _getScrollHeight() {
+ return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
+ };
+
+ _proto._getOffsetHeight = function _getOffsetHeight() {
+ return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height;
+ };
+
+ _proto._process = function _process() {
+ var scrollTop = this._getScrollTop() + this._config.offset;
+
+ var scrollHeight = this._getScrollHeight();
+
+ var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight();
+
+ if (this._scrollHeight !== scrollHeight) {
+ this.refresh();
+ }
+
+ if (scrollTop >= maxScroll) {
+ var target = this._targets[this._targets.length - 1];
+
+ if (this._activeTarget !== target) {
+ this._activate(target);
+ }
+
+ return;
+ }
+
+ if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) {
+ this._activeTarget = null;
+
+ this._clear();
+
+ return;
+ }
+
+ for (var i = this._offsets.length; i--;) {
+ var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]);
+
+ if (isActiveTarget) {
+ this._activate(this._targets[i]);
+ }
+ }
+ };
+
+ _proto._activate = function _activate(target) {
+ this._activeTarget = target;
+
+ this._clear();
+
+ var queries = this._selector.split(','); // eslint-disable-next-line arrow-body-style
+
+
+ queries = queries.map(function (selector) {
+ return selector + "[data-target=\"" + target + "\"]," + (selector + "[href=\"" + target + "\"]");
+ });
+ var $link = $$$1(queries.join(','));
+
+ if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
+ $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+ $link.addClass(ClassName.ACTIVE);
+ } else {
+ // Set triggered link as active
+ $link.addClass(ClassName.ACTIVE); // Set triggered links parents as active
+ // With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
+
+ $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_LINKS + ", " + Selector.LIST_ITEMS).addClass(ClassName.ACTIVE); // Handle special case when .nav-link is inside .nav-item
+
+ $link.parents(Selector.NAV_LIST_GROUP).prev(Selector.NAV_ITEMS).children(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
+ }
+
+ $$$1(this._scrollElement).trigger(Event.ACTIVATE, {
+ relatedTarget: target
+ });
+ };
+
+ _proto._clear = function _clear() {
+ $$$1(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+ }; // static
+
+
+ ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var data = $$$1(this).data(DATA_KEY);
+
+ var _config = typeof config === 'object' && config;
+
+ if (!data) {
+ data = new ScrollSpy(this, _config);
+ $$$1(this).data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'string') {
+ if (typeof data[config] === 'undefined') {
+ throw new Error("No method named \"" + config + "\"");
+ }
+
+ data[config]();
+ }
+ });
+ };
+
+ _createClass(ScrollSpy, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }, {
+ key: "Default",
+ get: function get() {
+ return Default;
+ }
+ }]);
+ return ScrollSpy;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1(window).on(Event.LOAD_DATA_API, function () {
+ var scrollSpys = $$$1.makeArray($$$1(Selector.DATA_SPY));
+
+ for (var i = scrollSpys.length; i--;) {
+ var $spy = $$$1(scrollSpys[i]);
+
+ ScrollSpy._jQueryInterface.call($spy, $spy.data());
+ }
+ });
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $$$1.fn[NAME] = ScrollSpy._jQueryInterface;
+ $$$1.fn[NAME].Constructor = ScrollSpy;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return ScrollSpy._jQueryInterface;
+ };
+
+ return ScrollSpy;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-beta.3): tab.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tab = function ($$$1) {
+ /**
+ * ------------------------------------------------------------------------
+ * Constants
+ * ------------------------------------------------------------------------
+ */
+ var NAME = 'tab';
+ var VERSION = '4.0.0-beta.3';
+ var DATA_KEY = 'bs.tab';
+ var EVENT_KEY = "." + DATA_KEY;
+ var DATA_API_KEY = '.data-api';
+ var JQUERY_NO_CONFLICT = $$$1.fn[NAME];
+ var TRANSITION_DURATION = 150;
+ var Event = {
+ HIDE: "hide" + EVENT_KEY,
+ HIDDEN: "hidden" + EVENT_KEY,
+ SHOW: "show" + EVENT_KEY,
+ SHOWN: "shown" + EVENT_KEY,
+ CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY
+ };
+ var ClassName = {
+ DROPDOWN_MENU: 'dropdown-menu',
+ ACTIVE: 'active',
+ DISABLED: 'disabled',
+ FADE: 'fade',
+ SHOW: 'show'
+ };
+ var Selector = {
+ DROPDOWN: '.dropdown',
+ NAV_LIST_GROUP: '.nav, .list-group',
+ ACTIVE: '.active',
+ ACTIVE_UL: '> li > .active',
+ DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"], [data-toggle="list"]',
+ DROPDOWN_TOGGLE: '.dropdown-toggle',
+ DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
+ /**
+ * ------------------------------------------------------------------------
+ * Class Definition
+ * ------------------------------------------------------------------------
+ */
+
+ };
+
+ var Tab =
+ /*#__PURE__*/
+ function () {
+ function Tab(element) {
+ this._element = element;
+ } // getters
+
+
+ var _proto = Tab.prototype;
+
+ // public
+ _proto.show = function show() {
+ var _this = this;
+
+ if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $$$1(this._element).hasClass(ClassName.ACTIVE) || $$$1(this._element).hasClass(ClassName.DISABLED)) {
+ return;
+ }
+
+ var target;
+ var previous;
+ var listElement = $$$1(this._element).closest(Selector.NAV_LIST_GROUP)[0];
+ var selector = Util.getSelectorFromElement(this._element);
+
+ if (listElement) {
+ var itemSelector = listElement.nodeName === 'UL' ? Selector.ACTIVE_UL : Selector.ACTIVE;
+ previous = $$$1.makeArray($$$1(listElement).find(itemSelector));
+ previous = previous[previous.length - 1];
+ }
+
+ var hideEvent = $$$1.Event(Event.HIDE, {
+ relatedTarget: this._element
+ });
+ var showEvent = $$$1.Event(Event.SHOW, {
+ relatedTarget: previous
+ });
+
+ if (previous) {
+ $$$1(previous).trigger(hideEvent);
+ }
+
+ $$$1(this._element).trigger(showEvent);
+
+ if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
+ return;
+ }
+
+ if (selector) {
+ target = $$$1(selector)[0];
+ }
+
+ this._activate(this._element, listElement);
+
+ var complete = function complete() {
+ var hiddenEvent = $$$1.Event(Event.HIDDEN, {
+ relatedTarget: _this._element
+ });
+ var shownEvent = $$$1.Event(Event.SHOWN, {
+ relatedTarget: previous
+ });
+ $$$1(previous).trigger(hiddenEvent);
+ $$$1(_this._element).trigger(shownEvent);
+ };
+
+ if (target) {
+ this._activate(target, target.parentNode, complete);
+ } else {
+ complete();
+ }
+ };
+
+ _proto.dispose = function dispose() {
+ $$$1.removeData(this._element, DATA_KEY);
+ this._element = null;
+ }; // private
+
+
+ _proto._activate = function _activate(element, container, callback) {
+ var _this2 = this;
+
+ var activeElements;
+
+ if (container.nodeName === 'UL') {
+ activeElements = $$$1(container).find(Selector.ACTIVE_UL);
+ } else {
+ activeElements = $$$1(container).children(Selector.ACTIVE);
+ }
+
+ var active = activeElements[0];
+ var isTransitioning = callback && Util.supportsTransitionEnd() && active && $$$1(active).hasClass(ClassName.FADE);
+
+ var complete = function complete() {
+ return _this2._transitionComplete(element, active, callback);
+ };
+
+ if (active && isTransitioning) {
+ $$$1(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+ } else {
+ complete();
+ }
+ };
+
+ _proto._transitionComplete = function _transitionComplete(element, active, callback) {
+ if (active) {
+ $$$1(active).removeClass(ClassName.SHOW + " " + ClassName.ACTIVE);
+ var dropdownChild = $$$1(active.parentNode).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
+
+ if (dropdownChild) {
+ $$$1(dropdownChild).removeClass(ClassName.ACTIVE);
+ }
+
+ if (active.getAttribute('role') === 'tab') {
+ active.setAttribute('aria-selected', false);
+ }
+ }
+
+ $$$1(element).addClass(ClassName.ACTIVE);
+
+ if (element.getAttribute('role') === 'tab') {
+ element.setAttribute('aria-selected', true);
+ }
+
+ Util.reflow(element);
+ $$$1(element).addClass(ClassName.SHOW);
+
+ if (element.parentNode && $$$1(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
+ var dropdownElement = $$$1(element).closest(Selector.DROPDOWN)[0];
+
+ if (dropdownElement) {
+ $$$1(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+ }
+
+ element.setAttribute('aria-expanded', true);
+ }
+
+ if (callback) {
+ callback();
+ }
+ }; // static
+
+
+ Tab._jQueryInterface = function _jQueryInterface(config) {
+ return this.each(function () {
+ var $this = $$$1(this);
+ var data = $this.data(DATA_KEY);
+
+ if (!data) {
+ data = new Tab(this);
+ $this.data(DATA_KEY, data);
+ }
+
+ if (typeof config === 'string') {
+ if (typeof data[config] === 'undefined') {
+ throw new Error("No method named \"" + config + "\"");
+ }
+
+ data[config]();
+ }
+ });
+ };
+
+ _createClass(Tab, null, [{
+ key: "VERSION",
+ get: function get() {
+ return VERSION;
+ }
+ }]);
+ return Tab;
+ }();
+ /**
+ * ------------------------------------------------------------------------
+ * Data Api implementation
+ * ------------------------------------------------------------------------
+ */
+
+
+ $$$1(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+ event.preventDefault();
+
+ Tab._jQueryInterface.call($$$1(this), 'show');
+ });
+ /**
+ * ------------------------------------------------------------------------
+ * jQuery
+ * ------------------------------------------------------------------------
+ */
+
+ $$$1.fn[NAME] = Tab._jQueryInterface;
+ $$$1.fn[NAME].Constructor = Tab;
+
+ $$$1.fn[NAME].noConflict = function () {
+ $$$1.fn[NAME] = JQUERY_NO_CONFLICT;
+ return Tab._jQueryInterface;
+ };
+
+ return Tab;
+}($);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.6): index.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+(function ($$$1) {
+ if (typeof $$$1 === 'undefined') {
+ throw new Error('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.');
+ }
+
+ var version = $$$1.fn.jquery.split(' ')[0].split('.');
+ var minMajor = 1;
+ var ltMajor = 2;
+ var minMinor = 9;
+ var minPatch = 1;
+ var maxMajor = 4;
+
+ if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) {
+ throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0');
+ }
+})($);
+
+exports.Util = Util;
+exports.Alert = Alert;
+exports.Button = Button;
+exports.Carousel = Carousel;
+exports.Collapse = Collapse;
+exports.Dropdown = Dropdown;
+exports.Modal = Modal;
+exports.Popover = Popover;
+exports.Scrollspy = ScrollSpy;
+exports.Tab = Tab;
+exports.Tooltip = Tooltip;
+
+Object.defineProperty(exports, '__esModule', { value: true });
+
+})));
+//# sourceMappingURL=bootstrap.js.map
+
+
+/***/ }),
+/* 127 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function(setImmediate) {var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*!
+ * typeahead.js 1.2.0
+ * https://github.com/twitter/typeahead.js
+ * Copyright 2013-2017 Twitter, Inc. and other contributors; Licensed MIT
+ */
+
+(function(root, factory) {
+ if (true) {
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(1) ], __WEBPACK_AMD_DEFINE_RESULT__ = (function(a0) {
+ return root["Bloodhound"] = factory(a0);
+ }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (typeof exports === "object") {
+ module.exports = factory(require("jquery"));
+ } else {
+ root["Bloodhound"] = factory(root["jQuery"]);
+ }
+})(this, function($) {
+ var _ = function() {
+ "use strict";
+ return {
+ isMsie: function() {
+ return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
+ },
+ isBlankString: function(str) {
+ return !str || /^\s*$/.test(str);
+ },
+ escapeRegExChars: function(str) {
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+ },
+ isString: function(obj) {
+ return typeof obj === "string";
+ },
+ isNumber: function(obj) {
+ return typeof obj === "number";
+ },
+ isArray: $.isArray,
+ isFunction: $.isFunction,
+ isObject: $.isPlainObject,
+ isUndefined: function(obj) {
+ return typeof obj === "undefined";
+ },
+ isElement: function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ },
+ isJQuery: function(obj) {
+ return obj instanceof $;
+ },
+ toStr: function toStr(s) {
+ return _.isUndefined(s) || s === null ? "" : s + "";
+ },
+ bind: $.proxy,
+ each: function(collection, cb) {
+ $.each(collection, reverseArgs);
+ function reverseArgs(index, value) {
+ return cb(value, index);
+ }
+ },
+ map: $.map,
+ filter: $.grep,
+ every: function(obj, test) {
+ var result = true;
+ if (!obj) {
+ return result;
+ }
+ $.each(obj, function(key, val) {
+ if (!(result = test.call(null, val, key, obj))) {
+ return false;
+ }
+ });
+ return !!result;
+ },
+ some: function(obj, test) {
+ var result = false;
+ if (!obj) {
+ return result;
+ }
+ $.each(obj, function(key, val) {
+ if (result = test.call(null, val, key, obj)) {
+ return false;
+ }
+ });
+ return !!result;
+ },
+ mixin: $.extend,
+ identity: function(x) {
+ return x;
+ },
+ clone: function(obj) {
+ return $.extend(true, {}, obj);
+ },
+ getIdGenerator: function() {
+ var counter = 0;
+ return function() {
+ return counter++;
+ };
+ },
+ templatify: function templatify(obj) {
+ return $.isFunction(obj) ? obj : template;
+ function template() {
+ return String(obj);
+ }
+ },
+ defer: function(fn) {
+ setTimeout(fn, 0);
+ },
+ debounce: function(func, wait, immediate) {
+ var timeout, result;
+ return function() {
+ var context = this, args = arguments, later, callNow;
+ later = function() {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ }
+ };
+ callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ }
+ return result;
+ };
+ },
+ throttle: function(func, wait) {
+ var context, args, timeout, result, previous, later;
+ previous = 0;
+ later = function() {
+ previous = new Date();
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function() {
+ var now = new Date(), remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ },
+ stringify: function(val) {
+ return _.isString(val) ? val : JSON.stringify(val);
+ },
+ guid: function() {
+ function _p8(s) {
+ var p = (Math.random().toString(16) + "000000000").substr(2, 8);
+ return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p;
+ }
+ return "tt-" + _p8() + _p8(true) + _p8(true) + _p8();
+ },
+ noop: function() {}
+ };
+ }();
+ var VERSION = "1.2.0";
+ var tokenizers = function() {
+ "use strict";
+ return {
+ nonword: nonword,
+ whitespace: whitespace,
+ ngram: ngram,
+ obj: {
+ nonword: getObjTokenizer(nonword),
+ whitespace: getObjTokenizer(whitespace),
+ ngram: getObjTokenizer(ngram)
+ }
+ };
+ function whitespace(str) {
+ str = _.toStr(str);
+ return str ? str.split(/\s+/) : [];
+ }
+ function nonword(str) {
+ str = _.toStr(str);
+ return str ? str.split(/\W+/) : [];
+ }
+ function ngram(str) {
+ str = _.toStr(str);
+ var tokens = [], word = "";
+ _.each(str.split(""), function(char) {
+ if (char.match(/\s+/)) {
+ word = "";
+ } else {
+ tokens.push(word + char);
+ word += char;
+ }
+ });
+ return tokens;
+ }
+ function getObjTokenizer(tokenizer) {
+ return function setKey(keys) {
+ keys = _.isArray(keys) ? keys : [].slice.call(arguments, 0);
+ return function tokenize(o) {
+ var tokens = [];
+ _.each(keys, function(k) {
+ tokens = tokens.concat(tokenizer(_.toStr(o[k])));
+ });
+ return tokens;
+ };
+ };
+ }
+ }();
+ var LruCache = function() {
+ "use strict";
+ function LruCache(maxSize) {
+ this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
+ this.reset();
+ if (this.maxSize <= 0) {
+ this.set = this.get = $.noop;
+ }
+ }
+ _.mixin(LruCache.prototype, {
+ set: function set(key, val) {
+ var tailItem = this.list.tail, node;
+ if (this.size >= this.maxSize) {
+ this.list.remove(tailItem);
+ delete this.hash[tailItem.key];
+ this.size--;
+ }
+ if (node = this.hash[key]) {
+ node.val = val;
+ this.list.moveToFront(node);
+ } else {
+ node = new Node(key, val);
+ this.list.add(node);
+ this.hash[key] = node;
+ this.size++;
+ }
+ },
+ get: function get(key) {
+ var node = this.hash[key];
+ if (node) {
+ this.list.moveToFront(node);
+ return node.val;
+ }
+ },
+ reset: function reset() {
+ this.size = 0;
+ this.hash = {};
+ this.list = new List();
+ }
+ });
+ function List() {
+ this.head = this.tail = null;
+ }
+ _.mixin(List.prototype, {
+ add: function add(node) {
+ if (this.head) {
+ node.next = this.head;
+ this.head.prev = node;
+ }
+ this.head = node;
+ this.tail = this.tail || node;
+ },
+ remove: function remove(node) {
+ node.prev ? node.prev.next = node.next : this.head = node.next;
+ node.next ? node.next.prev = node.prev : this.tail = node.prev;
+ },
+ moveToFront: function(node) {
+ this.remove(node);
+ this.add(node);
+ }
+ });
+ function Node(key, val) {
+ this.key = key;
+ this.val = val;
+ this.prev = this.next = null;
+ }
+ return LruCache;
+ }();
+ var PersistentStorage = function() {
+ "use strict";
+ var LOCAL_STORAGE;
+ try {
+ LOCAL_STORAGE = window.localStorage;
+ LOCAL_STORAGE.setItem("~~~", "!");
+ LOCAL_STORAGE.removeItem("~~~");
+ } catch (err) {
+ LOCAL_STORAGE = null;
+ }
+ function PersistentStorage(namespace, override) {
+ this.prefix = [ "__", namespace, "__" ].join("");
+ this.ttlKey = "__ttl__";
+ this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
+ this.ls = override || LOCAL_STORAGE;
+ !this.ls && this._noop();
+ }
+ _.mixin(PersistentStorage.prototype, {
+ _prefix: function(key) {
+ return this.prefix + key;
+ },
+ _ttlKey: function(key) {
+ return this._prefix(key) + this.ttlKey;
+ },
+ _noop: function() {
+ this.get = this.set = this.remove = this.clear = this.isExpired = _.noop;
+ },
+ _safeSet: function(key, val) {
+ try {
+ this.ls.setItem(key, val);
+ } catch (err) {
+ if (err.name === "QuotaExceededError") {
+ this.clear();
+ this._noop();
+ }
+ }
+ },
+ get: function(key) {
+ if (this.isExpired(key)) {
+ this.remove(key);
+ }
+ return decode(this.ls.getItem(this._prefix(key)));
+ },
+ set: function(key, val, ttl) {
+ if (_.isNumber(ttl)) {
+ this._safeSet(this._ttlKey(key), encode(now() + ttl));
+ } else {
+ this.ls.removeItem(this._ttlKey(key));
+ }
+ return this._safeSet(this._prefix(key), encode(val));
+ },
+ remove: function(key) {
+ this.ls.removeItem(this._ttlKey(key));
+ this.ls.removeItem(this._prefix(key));
+ return this;
+ },
+ clear: function() {
+ var i, keys = gatherMatchingKeys(this.keyMatcher);
+ for (i = keys.length; i--; ) {
+ this.remove(keys[i]);
+ }
+ return this;
+ },
+ isExpired: function(key) {
+ var ttl = decode(this.ls.getItem(this._ttlKey(key)));
+ return _.isNumber(ttl) && now() > ttl ? true : false;
+ }
+ });
+ return PersistentStorage;
+ function now() {
+ return new Date().getTime();
+ }
+ function encode(val) {
+ return JSON.stringify(_.isUndefined(val) ? null : val);
+ }
+ function decode(val) {
+ return $.parseJSON(val);
+ }
+ function gatherMatchingKeys(keyMatcher) {
+ var i, key, keys = [], len = LOCAL_STORAGE.length;
+ for (i = 0; i < len; i++) {
+ if ((key = LOCAL_STORAGE.key(i)).match(keyMatcher)) {
+ keys.push(key.replace(keyMatcher, ""));
+ }
+ }
+ return keys;
+ }
+ }();
+ var Transport = function() {
+ "use strict";
+ var pendingRequestsCount = 0, pendingRequests = {}, sharedCache = new LruCache(10);
+ function Transport(o) {
+ o = o || {};
+ this.maxPendingRequests = o.maxPendingRequests || 6;
+ this.cancelled = false;
+ this.lastReq = null;
+ this._send = o.transport;
+ this._get = o.limiter ? o.limiter(this._get) : this._get;
+ this._cache = o.cache === false ? new LruCache(0) : sharedCache;
+ }
+ Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
+ this.maxPendingRequests = num;
+ };
+ Transport.resetCache = function resetCache() {
+ sharedCache.reset();
+ };
+ _.mixin(Transport.prototype, {
+ _fingerprint: function fingerprint(o) {
+ o = o || {};
+ return o.url + o.type + $.param(o.data || {});
+ },
+ _get: function(o, cb) {
+ var that = this, fingerprint, jqXhr;
+ fingerprint = this._fingerprint(o);
+ if (this.cancelled || fingerprint !== this.lastReq) {
+ return;
+ }
+ if (jqXhr = pendingRequests[fingerprint]) {
+ jqXhr.done(done).fail(fail);
+ } else if (pendingRequestsCount < this.maxPendingRequests) {
+ pendingRequestsCount++;
+ pendingRequests[fingerprint] = this._send(o).done(done).fail(fail).always(always);
+ } else {
+ this.onDeckRequestArgs = [].slice.call(arguments, 0);
+ }
+ function done(resp) {
+ cb(null, resp);
+ that._cache.set(fingerprint, resp);
+ }
+ function fail() {
+ cb(true);
+ }
+ function always() {
+ pendingRequestsCount--;
+ delete pendingRequests[fingerprint];
+ if (that.onDeckRequestArgs) {
+ that._get.apply(that, that.onDeckRequestArgs);
+ that.onDeckRequestArgs = null;
+ }
+ }
+ },
+ get: function(o, cb) {
+ var resp, fingerprint;
+ cb = cb || $.noop;
+ o = _.isString(o) ? {
+ url: o
+ } : o || {};
+ fingerprint = this._fingerprint(o);
+ this.cancelled = false;
+ this.lastReq = fingerprint;
+ if (resp = this._cache.get(fingerprint)) {
+ cb(null, resp);
+ } else {
+ this._get(o, cb);
+ }
+ },
+ cancel: function() {
+ this.cancelled = true;
+ }
+ });
+ return Transport;
+ }();
+ var SearchIndex = window.SearchIndex = function() {
+ "use strict";
+ var CHILDREN = "c", IDS = "i";
+ function SearchIndex(o) {
+ o = o || {};
+ if (!o.datumTokenizer || !o.queryTokenizer) {
+ $.error("datumTokenizer and queryTokenizer are both required");
+ }
+ this.identify = o.identify || _.stringify;
+ this.datumTokenizer = o.datumTokenizer;
+ this.queryTokenizer = o.queryTokenizer;
+ this.matchAnyQueryToken = o.matchAnyQueryToken;
+ this.reset();
+ }
+ _.mixin(SearchIndex.prototype, {
+ bootstrap: function bootstrap(o) {
+ this.datums = o.datums;
+ this.trie = o.trie;
+ },
+ add: function(data) {
+ var that = this;
+ data = _.isArray(data) ? data : [ data ];
+ _.each(data, function(datum) {
+ var id, tokens;
+ that.datums[id = that.identify(datum)] = datum;
+ tokens = normalizeTokens(that.datumTokenizer(datum));
+ _.each(tokens, function(token) {
+ var node, chars, ch;
+ node = that.trie;
+ chars = token.split("");
+ while (ch = chars.shift()) {
+ node = node[CHILDREN][ch] || (node[CHILDREN][ch] = newNode());
+ node[IDS].push(id);
+ }
+ });
+ });
+ },
+ get: function get(ids) {
+ var that = this;
+ return _.map(ids, function(id) {
+ return that.datums[id];
+ });
+ },
+ search: function search(query) {
+ var that = this, tokens, matches;
+ tokens = normalizeTokens(this.queryTokenizer(query));
+ _.each(tokens, function(token) {
+ var node, chars, ch, ids;
+ if (matches && matches.length === 0 && !that.matchAnyQueryToken) {
+ return false;
+ }
+ node = that.trie;
+ chars = token.split("");
+ while (node && (ch = chars.shift())) {
+ node = node[CHILDREN][ch];
+ }
+ if (node && chars.length === 0) {
+ ids = node[IDS].slice(0);
+ matches = matches ? getIntersection(matches, ids) : ids;
+ } else {
+ if (!that.matchAnyQueryToken) {
+ matches = [];
+ return false;
+ }
+ }
+ });
+ return matches ? _.map(unique(matches), function(id) {
+ return that.datums[id];
+ }) : [];
+ },
+ all: function all() {
+ var values = [];
+ for (var key in this.datums) {
+ values.push(this.datums[key]);
+ }
+ return values;
+ },
+ reset: function reset() {
+ this.datums = {};
+ this.trie = newNode();
+ },
+ serialize: function serialize() {
+ return {
+ datums: this.datums,
+ trie: this.trie
+ };
+ }
+ });
+ return SearchIndex;
+ function normalizeTokens(tokens) {
+ tokens = _.filter(tokens, function(token) {
+ return !!token;
+ });
+ tokens = _.map(tokens, function(token) {
+ return token.toLowerCase();
+ });
+ return tokens;
+ }
+ function newNode() {
+ var node = {};
+ node[IDS] = [];
+ node[CHILDREN] = {};
+ return node;
+ }
+ function unique(array) {
+ var seen = {}, uniques = [];
+ for (var i = 0, len = array.length; i < len; i++) {
+ if (!seen[array[i]]) {
+ seen[array[i]] = true;
+ uniques.push(array[i]);
+ }
+ }
+ return uniques;
+ }
+ function getIntersection(arrayA, arrayB) {
+ var ai = 0, bi = 0, intersection = [];
+ arrayA = arrayA.sort();
+ arrayB = arrayB.sort();
+ var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
+ while (ai < lenArrayA && bi < lenArrayB) {
+ if (arrayA[ai] < arrayB[bi]) {
+ ai++;
+ } else if (arrayA[ai] > arrayB[bi]) {
+ bi++;
+ } else {
+ intersection.push(arrayA[ai]);
+ ai++;
+ bi++;
+ }
+ }
+ return intersection;
+ }
+ }();
+ var Prefetch = function() {
+ "use strict";
+ var keys;
+ keys = {
+ data: "data",
+ protocol: "protocol",
+ thumbprint: "thumbprint"
+ };
+ function Prefetch(o) {
+ this.url = o.url;
+ this.ttl = o.ttl;
+ this.cache = o.cache;
+ this.prepare = o.prepare;
+ this.transform = o.transform;
+ this.transport = o.transport;
+ this.thumbprint = o.thumbprint;
+ this.storage = new PersistentStorage(o.cacheKey);
+ }
+ _.mixin(Prefetch.prototype, {
+ _settings: function settings() {
+ return {
+ url: this.url,
+ type: "GET",
+ dataType: "json"
+ };
+ },
+ store: function store(data) {
+ if (!this.cache) {
+ return;
+ }
+ this.storage.set(keys.data, data, this.ttl);
+ this.storage.set(keys.protocol, location.protocol, this.ttl);
+ this.storage.set(keys.thumbprint, this.thumbprint, this.ttl);
+ },
+ fromCache: function fromCache() {
+ var stored = {}, isExpired;
+ if (!this.cache) {
+ return null;
+ }
+ stored.data = this.storage.get(keys.data);
+ stored.protocol = this.storage.get(keys.protocol);
+ stored.thumbprint = this.storage.get(keys.thumbprint);
+ isExpired = stored.thumbprint !== this.thumbprint || stored.protocol !== location.protocol;
+ return stored.data && !isExpired ? stored.data : null;
+ },
+ fromNetwork: function(cb) {
+ var that = this, settings;
+ if (!cb) {
+ return;
+ }
+ settings = this.prepare(this._settings());
+ this.transport(settings).fail(onError).done(onResponse);
+ function onError() {
+ cb(true);
+ }
+ function onResponse(resp) {
+ cb(null, that.transform(resp));
+ }
+ },
+ clear: function clear() {
+ this.storage.clear();
+ return this;
+ }
+ });
+ return Prefetch;
+ }();
+ var Remote = function() {
+ "use strict";
+ function Remote(o) {
+ this.url = o.url;
+ this.prepare = o.prepare;
+ this.transform = o.transform;
+ this.indexResponse = o.indexResponse;
+ this.transport = new Transport({
+ cache: o.cache,
+ limiter: o.limiter,
+ transport: o.transport,
+ maxPendingRequests: o.maxPendingRequests
+ });
+ }
+ _.mixin(Remote.prototype, {
+ _settings: function settings() {
+ return {
+ url: this.url,
+ type: "GET",
+ dataType: "json"
+ };
+ },
+ get: function get(query, cb) {
+ var that = this, settings;
+ if (!cb) {
+ return;
+ }
+ query = query || "";
+ settings = this.prepare(query, this._settings());
+ return this.transport.get(settings, onResponse);
+ function onResponse(err, resp) {
+ err ? cb([]) : cb(that.transform(resp));
+ }
+ },
+ cancelLastRequest: function cancelLastRequest() {
+ this.transport.cancel();
+ }
+ });
+ return Remote;
+ }();
+ var oParser = function() {
+ "use strict";
+ return function parse(o) {
+ var defaults, sorter;
+ defaults = {
+ initialize: true,
+ identify: _.stringify,
+ datumTokenizer: null,
+ queryTokenizer: null,
+ matchAnyQueryToken: false,
+ sufficient: 5,
+ indexRemote: false,
+ sorter: null,
+ local: [],
+ prefetch: null,
+ remote: null
+ };
+ o = _.mixin(defaults, o || {});
+ !o.datumTokenizer && $.error("datumTokenizer is required");
+ !o.queryTokenizer && $.error("queryTokenizer is required");
+ sorter = o.sorter;
+ o.sorter = sorter ? function(x) {
+ return x.sort(sorter);
+ } : _.identity;
+ o.local = _.isFunction(o.local) ? o.local() : o.local;
+ o.prefetch = parsePrefetch(o.prefetch);
+ o.remote = parseRemote(o.remote);
+ return o;
+ };
+ function parsePrefetch(o) {
+ var defaults;
+ if (!o) {
+ return null;
+ }
+ defaults = {
+ url: null,
+ ttl: 24 * 60 * 60 * 1e3,
+ cache: true,
+ cacheKey: null,
+ thumbprint: "",
+ prepare: _.identity,
+ transform: _.identity,
+ transport: null
+ };
+ o = _.isString(o) ? {
+ url: o
+ } : o;
+ o = _.mixin(defaults, o);
+ !o.url && $.error("prefetch requires url to be set");
+ o.transform = o.filter || o.transform;
+ o.cacheKey = o.cacheKey || o.url;
+ o.thumbprint = VERSION + o.thumbprint;
+ o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
+ return o;
+ }
+ function parseRemote(o) {
+ var defaults;
+ if (!o) {
+ return;
+ }
+ defaults = {
+ url: null,
+ cache: true,
+ prepare: null,
+ replace: null,
+ wildcard: null,
+ limiter: null,
+ rateLimitBy: "debounce",
+ rateLimitWait: 300,
+ transform: _.identity,
+ transport: null
+ };
+ o = _.isString(o) ? {
+ url: o
+ } : o;
+ o = _.mixin(defaults, o);
+ !o.url && $.error("remote requires url to be set");
+ o.transform = o.filter || o.transform;
+ o.prepare = toRemotePrepare(o);
+ o.limiter = toLimiter(o);
+ o.transport = o.transport ? callbackToDeferred(o.transport) : $.ajax;
+ delete o.replace;
+ delete o.wildcard;
+ delete o.rateLimitBy;
+ delete o.rateLimitWait;
+ return o;
+ }
+ function toRemotePrepare(o) {
+ var prepare, replace, wildcard;
+ prepare = o.prepare;
+ replace = o.replace;
+ wildcard = o.wildcard;
+ if (prepare) {
+ return prepare;
+ }
+ if (replace) {
+ prepare = prepareByReplace;
+ } else if (o.wildcard) {
+ prepare = prepareByWildcard;
+ } else {
+ prepare = identityPrepare;
+ }
+ return prepare;
+ function prepareByReplace(query, settings) {
+ settings.url = replace(settings.url, query);
+ return settings;
+ }
+ function prepareByWildcard(query, settings) {
+ settings.url = settings.url.replace(wildcard, encodeURIComponent(query));
+ return settings;
+ }
+ function identityPrepare(query, settings) {
+ return settings;
+ }
+ }
+ function toLimiter(o) {
+ var limiter, method, wait;
+ limiter = o.limiter;
+ method = o.rateLimitBy;
+ wait = o.rateLimitWait;
+ if (!limiter) {
+ limiter = /^throttle$/i.test(method) ? throttle(wait) : debounce(wait);
+ }
+ return limiter;
+ function debounce(wait) {
+ return function debounce(fn) {
+ return _.debounce(fn, wait);
+ };
+ }
+ function throttle(wait) {
+ return function throttle(fn) {
+ return _.throttle(fn, wait);
+ };
+ }
+ }
+ function callbackToDeferred(fn) {
+ return function wrapper(o) {
+ var deferred = $.Deferred();
+ fn(o, onSuccess, onError);
+ return deferred;
+ function onSuccess(resp) {
+ _.defer(function() {
+ deferred.resolve(resp);
+ });
+ }
+ function onError(err) {
+ _.defer(function() {
+ deferred.reject(err);
+ });
+ }
+ };
+ }
+ }();
+ var Bloodhound = function() {
+ "use strict";
+ var old;
+ old = window && window.Bloodhound;
+ function Bloodhound(o) {
+ o = oParser(o);
+ this.sorter = o.sorter;
+ this.identify = o.identify;
+ this.sufficient = o.sufficient;
+ this.indexRemote = o.indexRemote;
+ this.local = o.local;
+ this.remote = o.remote ? new Remote(o.remote) : null;
+ this.prefetch = o.prefetch ? new Prefetch(o.prefetch) : null;
+ this.index = new SearchIndex({
+ identify: this.identify,
+ datumTokenizer: o.datumTokenizer,
+ queryTokenizer: o.queryTokenizer
+ });
+ o.initialize !== false && this.initialize();
+ }
+ Bloodhound.noConflict = function noConflict() {
+ window && (window.Bloodhound = old);
+ return Bloodhound;
+ };
+ Bloodhound.tokenizers = tokenizers;
+ _.mixin(Bloodhound.prototype, {
+ __ttAdapter: function ttAdapter() {
+ var that = this;
+ return this.remote ? withAsync : withoutAsync;
+ function withAsync(query, sync, async) {
+ return that.search(query, sync, async);
+ }
+ function withoutAsync(query, sync) {
+ return that.search(query, sync);
+ }
+ },
+ _loadPrefetch: function loadPrefetch() {
+ var that = this, deferred, serialized;
+ deferred = $.Deferred();
+ if (!this.prefetch) {
+ deferred.resolve();
+ } else if (serialized = this.prefetch.fromCache()) {
+ this.index.bootstrap(serialized);
+ deferred.resolve();
+ } else {
+ this.prefetch.fromNetwork(done);
+ }
+ return deferred.promise();
+ function done(err, data) {
+ if (err) {
+ return deferred.reject();
+ }
+ that.add(data);
+ that.prefetch.store(that.index.serialize());
+ deferred.resolve();
+ }
+ },
+ _initialize: function initialize() {
+ var that = this, deferred;
+ this.clear();
+ (this.initPromise = this._loadPrefetch()).done(addLocalToIndex);
+ return this.initPromise;
+ function addLocalToIndex() {
+ that.add(that.local);
+ }
+ },
+ initialize: function initialize(force) {
+ return !this.initPromise || force ? this._initialize() : this.initPromise;
+ },
+ add: function add(data) {
+ this.index.add(data);
+ return this;
+ },
+ get: function get(ids) {
+ ids = _.isArray(ids) ? ids : [].slice.call(arguments);
+ return this.index.get(ids);
+ },
+ search: function search(query, sync, async) {
+ var that = this, local;
+ sync = sync || _.noop;
+ async = async || _.noop;
+ local = this.sorter(this.index.search(query));
+ sync(this.remote ? local.slice() : local);
+ if (this.remote && local.length < this.sufficient) {
+ this.remote.get(query, processRemote);
+ } else if (this.remote) {
+ this.remote.cancelLastRequest();
+ }
+ return this;
+ function processRemote(remote) {
+ var nonDuplicates = [];
+ _.each(remote, function(r) {
+ !_.some(local, function(l) {
+ return that.identify(r) === that.identify(l);
+ }) && nonDuplicates.push(r);
+ });
+ that.indexRemote && that.add(nonDuplicates);
+ async(nonDuplicates);
+ }
+ },
+ all: function all() {
+ return this.index.all();
+ },
+ clear: function clear() {
+ this.index.reset();
+ return this;
+ },
+ clearPrefetchCache: function clearPrefetchCache() {
+ this.prefetch && this.prefetch.clear();
+ return this;
+ },
+ clearRemoteCache: function clearRemoteCache() {
+ Transport.resetCache();
+ return this;
+ },
+ ttAdapter: function ttAdapter() {
+ return this.__ttAdapter();
+ }
+ });
+ return Bloodhound;
+ }();
+ return Bloodhound;
+});
+
+(function(root, factory) {
+ if (true) {
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [ __webpack_require__(1) ], __WEBPACK_AMD_DEFINE_RESULT__ = (function(a0) {
+ return factory(a0);
+ }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (typeof exports === "object") {
+ module.exports = factory(require("jquery"));
+ } else {
+ factory(root["jQuery"]);
+ }
+})(this, function($) {
+ var _ = function() {
+ "use strict";
+ return {
+ isMsie: function() {
+ return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
+ },
+ isBlankString: function(str) {
+ return !str || /^\s*$/.test(str);
+ },
+ escapeRegExChars: function(str) {
+ return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+ },
+ isString: function(obj) {
+ return typeof obj === "string";
+ },
+ isNumber: function(obj) {
+ return typeof obj === "number";
+ },
+ isArray: $.isArray,
+ isFunction: $.isFunction,
+ isObject: $.isPlainObject,
+ isUndefined: function(obj) {
+ return typeof obj === "undefined";
+ },
+ isElement: function(obj) {
+ return !!(obj && obj.nodeType === 1);
+ },
+ isJQuery: function(obj) {
+ return obj instanceof $;
+ },
+ toStr: function toStr(s) {
+ return _.isUndefined(s) || s === null ? "" : s + "";
+ },
+ bind: $.proxy,
+ each: function(collection, cb) {
+ $.each(collection, reverseArgs);
+ function reverseArgs(index, value) {
+ return cb(value, index);
+ }
+ },
+ map: $.map,
+ filter: $.grep,
+ every: function(obj, test) {
+ var result = true;
+ if (!obj) {
+ return result;
+ }
+ $.each(obj, function(key, val) {
+ if (!(result = test.call(null, val, key, obj))) {
+ return false;
+ }
+ });
+ return !!result;
+ },
+ some: function(obj, test) {
+ var result = false;
+ if (!obj) {
+ return result;
+ }
+ $.each(obj, function(key, val) {
+ if (result = test.call(null, val, key, obj)) {
+ return false;
+ }
+ });
+ return !!result;
+ },
+ mixin: $.extend,
+ identity: function(x) {
+ return x;
+ },
+ clone: function(obj) {
+ return $.extend(true, {}, obj);
+ },
+ getIdGenerator: function() {
+ var counter = 0;
+ return function() {
+ return counter++;
+ };
+ },
+ templatify: function templatify(obj) {
+ return $.isFunction(obj) ? obj : template;
+ function template() {
+ return String(obj);
+ }
+ },
+ defer: function(fn) {
+ setTimeout(fn, 0);
+ },
+ debounce: function(func, wait, immediate) {
+ var timeout, result;
+ return function() {
+ var context = this, args = arguments, later, callNow;
+ later = function() {
+ timeout = null;
+ if (!immediate) {
+ result = func.apply(context, args);
+ }
+ };
+ callNow = immediate && !timeout;
+ clearTimeout(timeout);
+ timeout = setTimeout(later, wait);
+ if (callNow) {
+ result = func.apply(context, args);
+ }
+ return result;
+ };
+ },
+ throttle: function(func, wait) {
+ var context, args, timeout, result, previous, later;
+ previous = 0;
+ later = function() {
+ previous = new Date();
+ timeout = null;
+ result = func.apply(context, args);
+ };
+ return function() {
+ var now = new Date(), remaining = wait - (now - previous);
+ context = this;
+ args = arguments;
+ if (remaining <= 0) {
+ clearTimeout(timeout);
+ timeout = null;
+ previous = now;
+ result = func.apply(context, args);
+ } else if (!timeout) {
+ timeout = setTimeout(later, remaining);
+ }
+ return result;
+ };
+ },
+ stringify: function(val) {
+ return _.isString(val) ? val : JSON.stringify(val);
+ },
+ guid: function() {
+ function _p8(s) {
+ var p = (Math.random().toString(16) + "000000000").substr(2, 8);
+ return s ? "-" + p.substr(0, 4) + "-" + p.substr(4, 4) : p;
+ }
+ return "tt-" + _p8() + _p8(true) + _p8(true) + _p8();
+ },
+ noop: function() {}
+ };
+ }();
+ var WWW = function() {
+ "use strict";
+ var defaultClassNames = {
+ wrapper: "twitter-typeahead",
+ input: "tt-input",
+ hint: "tt-hint",
+ menu: "tt-menu",
+ dataset: "tt-dataset",
+ suggestion: "tt-suggestion",
+ selectable: "tt-selectable",
+ empty: "tt-empty",
+ open: "tt-open",
+ cursor: "tt-cursor",
+ highlight: "tt-highlight"
+ };
+ return build;
+ function build(o) {
+ var www, classes;
+ classes = _.mixin({}, defaultClassNames, o);
+ www = {
+ css: buildCss(),
+ classes: classes,
+ html: buildHtml(classes),
+ selectors: buildSelectors(classes)
+ };
+ return {
+ css: www.css,
+ html: www.html,
+ classes: www.classes,
+ selectors: www.selectors,
+ mixin: function(o) {
+ _.mixin(o, www);
+ }
+ };
+ }
+ function buildHtml(c) {
+ return {
+ wrapper: '<span class="' + c.wrapper + '"></span>',
+ menu: '<div role="listbox" class="' + c.menu + '"></div>'
+ };
+ }
+ function buildSelectors(classes) {
+ var selectors = {};
+ _.each(classes, function(v, k) {
+ selectors[k] = "." + v;
+ });
+ return selectors;
+ }
+ function buildCss() {
+ var css = {
+ wrapper: {
+ position: "relative",
+ display: "inline-block"
+ },
+ hint: {
+ position: "absolute",
+ top: "0",
+ left: "0",
+ borderColor: "transparent",
+ boxShadow: "none",
+ opacity: "1"
+ },
+ input: {
+ position: "relative",
+ verticalAlign: "top",
+ backgroundColor: "transparent"
+ },
+ inputWithNoHint: {
+ position: "relative",
+ verticalAlign: "top"
+ },
+ menu: {
+ position: "absolute",
+ top: "100%",
+ left: "0",
+ zIndex: "100",
+ display: "none"
+ },
+ ltr: {
+ left: "0",
+ right: "auto"
+ },
+ rtl: {
+ left: "auto",
+ right: " 0"
+ }
+ };
+ if (_.isMsie()) {
+ _.mixin(css.input, {
+ backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
+ });
+ }
+ return css;
+ }
+ }();
+ var EventBus = function() {
+ "use strict";
+ var namespace, deprecationMap;
+ namespace = "typeahead:";
+ deprecationMap = {
+ render: "rendered",
+ cursorchange: "cursorchanged",
+ select: "selected",
+ autocomplete: "autocompleted"
+ };
+ function EventBus(o) {
+ if (!o || !o.el) {
+ $.error("EventBus initialized without el");
+ }
+ this.$el = $(o.el);
+ }
+ _.mixin(EventBus.prototype, {
+ _trigger: function(type, args) {
+ var $e = $.Event(namespace + type);
+ this.$el.trigger.call(this.$el, $e, args || []);
+ return $e;
+ },
+ before: function(type) {
+ var args, $e;
+ args = [].slice.call(arguments, 1);
+ $e = this._trigger("before" + type, args);
+ return $e.isDefaultPrevented();
+ },
+ trigger: function(type) {
+ var deprecatedType;
+ this._trigger(type, [].slice.call(arguments, 1));
+ if (deprecatedType = deprecationMap[type]) {
+ this._trigger(deprecatedType, [].slice.call(arguments, 1));
+ }
+ }
+ });
+ return EventBus;
+ }();
+ var EventEmitter = function() {
+ "use strict";
+ var splitter = /\s+/, nextTick = getNextTick();
+ return {
+ onSync: onSync,
+ onAsync: onAsync,
+ off: off,
+ trigger: trigger
+ };
+ function on(method, types, cb, context) {
+ var type;
+ if (!cb) {
+ return this;
+ }
+ types = types.split(splitter);
+ cb = context ? bindContext(cb, context) : cb;
+ this._callbacks = this._callbacks || {};
+ while (type = types.shift()) {
+ this._callbacks[type] = this._callbacks[type] || {
+ sync: [],
+ async: []
+ };
+ this._callbacks[type][method].push(cb);
+ }
+ return this;
+ }
+ function onAsync(types, cb, context) {
+ return on.call(this, "async", types, cb, context);
+ }
+ function onSync(types, cb, context) {
+ return on.call(this, "sync", types, cb, context);
+ }
+ function off(types) {
+ var type;
+ if (!this._callbacks) {
+ return this;
+ }
+ types = types.split(splitter);
+ while (type = types.shift()) {
+ delete this._callbacks[type];
+ }
+ return this;
+ }
+ function trigger(types) {
+ var type, callbacks, args, syncFlush, asyncFlush;
+ if (!this._callbacks) {
+ return this;
+ }
+ types = types.split(splitter);
+ args = [].slice.call(arguments, 1);
+ while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
+ syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
+ asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
+ syncFlush() && nextTick(asyncFlush);
+ }
+ return this;
+ }
+ function getFlush(callbacks, context, args) {
+ return flush;
+ function flush() {
+ var cancelled;
+ for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
+ cancelled = callbacks[i].apply(context, args) === false;
+ }
+ return !cancelled;
+ }
+ }
+ function getNextTick() {
+ var nextTickFn;
+ if (window.setImmediate) {
+ nextTickFn = function nextTickSetImmediate(fn) {
+ setImmediate(function() {
+ fn();
+ });
+ };
+ } else {
+ nextTickFn = function nextTickSetTimeout(fn) {
+ setTimeout(function() {
+ fn();
+ }, 0);
+ };
+ }
+ return nextTickFn;
+ }
+ function bindContext(fn, context) {
+ return fn.bind ? fn.bind(context) : function() {
+ fn.apply(context, [].slice.call(arguments, 0));
+ };
+ }
+ }();
+ var highlight = function(doc) {
+ "use strict";
+ var defaults = {
+ node: null,
+ pattern: null,
+ tagName: "strong",
+ className: null,
+ wordsOnly: false,
+ caseSensitive: false,
+ diacriticInsensitive: false
+ };
+ var accented = {
+ A: "[AaªÀ-Åà-åĀ-ąǍǎȀ-ȃȦȧᴬᵃḀḁẚẠ-ảₐ℀℁℻⒜Ⓐⓐ㍱-㍴㎀-㎄㎈㎉㎩-㎯㏂㏊㏟㏿Aa]",
+ B: "[BbᴮᵇḂ-ḇℬ⒝Ⓑⓑ㍴㎅-㎇㏃㏈㏔㏝Bb]",
+ C: "[CcÇçĆ-čᶜ℀ℂ℃℅℆ℭⅭⅽ⒞Ⓒⓒ㍶㎈㎉㎝㎠㎤㏄-㏇Cc]",
+ D: "[DdĎďDŽ-džDZ-dzᴰᵈḊ-ḓⅅⅆⅮⅾ⒟Ⓓⓓ㋏㍲㍷-㍹㎗㎭-㎯㏅㏈Dd]",
+ E: "[EeÈ-Ëè-ëĒ-ěȄ-ȇȨȩᴱᵉḘ-ḛẸ-ẽₑ℡ℯℰⅇ⒠Ⓔⓔ㉐㋍㋎Ee]",
+ F: "[FfᶠḞḟ℉ℱ℻⒡Ⓕⓕ㎊-㎌㎙ff-fflFf]",
+ G: "[GgĜ-ģǦǧǴǵᴳᵍḠḡℊ⒢Ⓖⓖ㋌㋍㎇㎍-㎏㎓㎬㏆㏉㏒㏿Gg]",
+ H: "[HhĤĥȞȟʰᴴḢ-ḫẖℋ-ℎ⒣Ⓗⓗ㋌㍱㎐-㎔㏊㏋㏗Hh]",
+ I: "[IiÌ-Ïì-ïĨ-İIJijǏǐȈ-ȋᴵᵢḬḭỈ-ịⁱℐℑℹⅈⅠ-ⅣⅥ-ⅨⅪⅫⅰ-ⅳⅵ-ⅸⅺⅻ⒤Ⓘⓘ㍺㏌㏕fiffiIi]",
+ J: "[JjIJ-ĵLJ-njǰʲᴶⅉ⒥ⒿⓙⱼJj]",
+ K: "[KkĶķǨǩᴷᵏḰ-ḵK⒦Ⓚⓚ㎄㎅㎉㎏㎑㎘㎞㎢㎦㎪㎸㎾㏀㏆㏍-㏏Kk]",
+ L: "[LlĹ-ŀLJ-ljˡᴸḶḷḺ-ḽℒℓ℡Ⅼⅼ⒧Ⓛⓛ㋏㎈㎉㏐-㏓㏕㏖㏿flfflLl]",
+ M: "[MmᴹᵐḾ-ṃ℠™ℳⅯⅿ⒨Ⓜⓜ㍷-㍹㎃㎆㎎㎒㎖㎙-㎨㎫㎳㎷㎹㎽㎿㏁㏂㏎㏐㏔-㏖㏘㏙㏞㏟Mm]",
+ N: "[NnÑñŃ-ʼnNJ-njǸǹᴺṄ-ṋⁿℕ№⒩Ⓝⓝ㎁㎋㎚㎱㎵㎻㏌㏑Nn]",
+ O: "[OoºÒ-Öò-öŌ-őƠơǑǒǪǫȌ-ȏȮȯᴼᵒỌ-ỏₒ℅№ℴ⒪Ⓞⓞ㍵㏇㏒㏖Oo]",
+ P: "[PpᴾᵖṔ-ṗℙ⒫Ⓟⓟ㉐㍱㍶㎀㎊㎩-㎬㎰㎴㎺㏋㏗-㏚Pp]",
+ Q: "[Qqℚ⒬Ⓠⓠ㏃Qq]",
+ R: "[RrŔ-řȐ-ȓʳᴿᵣṘ-ṛṞṟ₨ℛ-ℝ⒭Ⓡⓡ㋍㍴㎭-㎯㏚㏛Rr]",
+ S: "[SsŚ-šſȘșˢṠ-ṣ₨℁℠⒮Ⓢⓢ㎧㎨㎮-㎳㏛㏜stSs]",
+ T: "[TtŢ-ťȚțᵀᵗṪ-ṱẗ℡™⒯Ⓣⓣ㉐㋏㎔㏏ſtstTt]",
+ U: "[UuÙ-Üù-üŨ-ųƯưǓǔȔ-ȗᵁᵘᵤṲ-ṷỤ-ủ℆⒰Ⓤⓤ㍳㍺Uu]",
+ V: "[VvᵛᵥṼ-ṿⅣ-Ⅷⅳ-ⅷ⒱Ⓥⓥⱽ㋎㍵㎴-㎹㏜㏞Vv]",
+ W: "[WwŴŵʷᵂẀ-ẉẘ⒲Ⓦⓦ㎺-㎿㏝Ww]",
+ X: "[XxˣẊ-ẍₓ℻Ⅸ-Ⅻⅸ-ⅻ⒳Ⓧⓧ㏓Xx]",
+ Y: "[YyÝýÿŶ-ŸȲȳʸẎẏẙỲ-ỹ⒴Ⓨⓨ㏉Yy]",
+ Z: "[ZzŹ-žDZ-dzᶻẐ-ẕℤℨ⒵Ⓩⓩ㎐-㎔Zz]"
+ };
+ return function hightlight(o) {
+ var regex;
+ o = _.mixin({}, defaults, o);
+ if (!o.node || !o.pattern) {
+ return;
+ }
+ o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
+ regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly, o.diacriticInsensitive);
+ traverse(o.node, hightlightTextNode);
+ function hightlightTextNode(textNode) {
+ var match, patternNode, wrapperNode;
+ if (match = regex.exec(textNode.data)) {
+ wrapperNode = doc.createElement(o.tagName);
+ o.className && (wrapperNode.className = o.className);
+ patternNode = textNode.splitText(match.index);
+ patternNode.splitText(match[0].length);
+ wrapperNode.appendChild(patternNode.cloneNode(true));
+ textNode.parentNode.replaceChild(wrapperNode, patternNode);
+ }
+ return !!match;
+ }
+ function traverse(el, hightlightTextNode) {
+ var childNode, TEXT_NODE_TYPE = 3;
+ for (var i = 0; i < el.childNodes.length; i++) {
+ childNode = el.childNodes[i];
+ if (childNode.nodeType === TEXT_NODE_TYPE) {
+ i += hightlightTextNode(childNode) ? 1 : 0;
+ } else {
+ traverse(childNode, hightlightTextNode);
+ }
+ }
+ }
+ };
+ function accent_replacer(chr) {
+ return accented[chr.toUpperCase()] || chr;
+ }
+ function getRegex(patterns, caseSensitive, wordsOnly, diacriticInsensitive) {
+ var escapedPatterns = [], regexStr;
+ for (var i = 0, len = patterns.length; i < len; i++) {
+ var escapedWord = _.escapeRegExChars(patterns[i]);
+ if (diacriticInsensitive) {
+ escapedWord = escapedWord.replace(/\S/g, accent_replacer);
+ }
+ escapedPatterns.push(escapedWord);
+ }
+ regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
+ return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
+ }
+ }(window.document);
+ var Input = function() {
+ "use strict";
+ var specialKeyCodeMap;
+ specialKeyCodeMap = {
+ 9: "tab",
+ 27: "esc",
+ 37: "left",
+ 39: "right",
+ 13: "enter",
+ 38: "up",
+ 40: "down"
+ };
+ function Input(o, www) {
+ o = o || {};
+ if (!o.input) {
+ $.error("input is missing");
+ }
+ www.mixin(this);
+ this.$hint = $(o.hint);
+ this.$input = $(o.input);
+ this.$input.attr({
+ "aria-activedescendant": "",
+ "aria-owns": this.$input.attr("id") + "_listbox",
+ role: "combobox",
+ "aria-readonly": "true",
+ "aria-autocomplete": "list"
+ });
+ $(www.menu).attr("id", this.$input.attr("id") + "_listbox");
+ this.query = this.$input.val();
+ this.queryWhenFocused = this.hasFocus() ? this.query : null;
+ this.$overflowHelper = buildOverflowHelper(this.$input);
+ this._checkLanguageDirection();
+ if (this.$hint.length === 0) {
+ this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
+ }
+ this.onSync("cursorchange", this._updateDescendent);
+ }
+ Input.normalizeQuery = function(str) {
+ return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
+ };
+ _.mixin(Input.prototype, EventEmitter, {
+ _onBlur: function onBlur() {
+ this.resetInputValue();
+ this.trigger("blurred");
+ },
+ _onFocus: function onFocus() {
+ this.queryWhenFocused = this.query;
+ this.trigger("focused");
+ },
+ _onKeydown: function onKeydown($e) {
+ var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
+ this._managePreventDefault(keyName, $e);
+ if (keyName && this._shouldTrigger(keyName, $e)) {
+ this.trigger(keyName + "Keyed", $e);
+ }
+ },
+ _onInput: function onInput() {
+ this._setQuery(this.getInputValue());
+ this.clearHintIfInvalid();
+ this._checkLanguageDirection();
+ },
+ _managePreventDefault: function managePreventDefault(keyName, $e) {
+ var preventDefault;
+ switch (keyName) {
+ case "up":
+ case "down":
+ preventDefault = !withModifier($e);
+ break;
+
+ default:
+ preventDefault = false;
+ }
+ preventDefault && $e.preventDefault();
+ },
+ _shouldTrigger: function shouldTrigger(keyName, $e) {
+ var trigger;
+ switch (keyName) {
+ case "tab":
+ trigger = !withModifier($e);
+ break;
+
+ default:
+ trigger = true;
+ }
+ return trigger;
+ },
+ _checkLanguageDirection: function checkLanguageDirection() {
+ var dir = (this.$input.css("direction") || "ltr").toLowerCase();
+ if (this.dir !== dir) {
+ this.dir = dir;
+ this.$hint.attr("dir", dir);
+ this.trigger("langDirChanged", dir);
+ }
+ },
+ _setQuery: function setQuery(val, silent) {
+ var areEquivalent, hasDifferentWhitespace;
+ areEquivalent = areQueriesEquivalent(val, this.query);
+ hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
+ this.query = val;
+ if (!silent && !areEquivalent) {
+ this.trigger("queryChanged", this.query);
+ } else if (!silent && hasDifferentWhitespace) {
+ this.trigger("whitespaceChanged", this.query);
+ }
+ },
+ _updateDescendent: function updateDescendent(event, id) {
+ this.$input.attr("aria-activedescendant", id);
+ },
+ bind: function() {
+ var that = this, onBlur, onFocus, onKeydown, onInput;
+ onBlur = _.bind(this._onBlur, this);
+ onFocus = _.bind(this._onFocus, this);
+ onKeydown = _.bind(this._onKeydown, this);
+ onInput = _.bind(this._onInput, this);
+ this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
+ if (!_.isMsie() || _.isMsie() > 9) {
+ this.$input.on("input.tt", onInput);
+ } else {
+ this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
+ if (specialKeyCodeMap[$e.which || $e.keyCode]) {
+ return;
+ }
+ _.defer(_.bind(that._onInput, that, $e));
+ });
+ }
+ return this;
+ },
+ focus: function focus() {
+ this.$input.focus();
+ },
+ blur: function blur() {
+ this.$input.blur();
+ },
+ getLangDir: function getLangDir() {
+ return this.dir;
+ },
+ getQuery: function getQuery() {
+ return this.query || "";
+ },
+ setQuery: function setQuery(val, silent) {
+ this.setInputValue(val);
+ this._setQuery(val, silent);
+ },
+ hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
+ return this.query !== this.queryWhenFocused;
+ },
+ getInputValue: function getInputValue() {
+ return this.$input.val();
+ },
+ setInputValue: function setInputValue(value) {
+ this.$input.val(value);
+ this.clearHintIfInvalid();
+ this._checkLanguageDirection();
+ },
+ resetInputValue: function resetInputValue() {
+ this.setInputValue(this.query);
+ },
+ getHint: function getHint() {
+ return this.$hint.val();
+ },
+ setHint: function setHint(value) {
+ this.$hint.val(value);
+ },
+ clearHint: function clearHint() {
+ this.setHint("");
+ },
+ clearHintIfInvalid: function clearHintIfInvalid() {
+ var val, hint, valIsPrefixOfHint, isValid;
+ val = this.getInputValue();
+ hint = this.getHint();
+ valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
+ isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
+ !isValid && this.clearHint();
+ },
+ hasFocus: function hasFocus() {
+ return this.$input.is(":focus");
+ },
+ hasOverflow: function hasOverflow() {
+ var constraint = this.$input.width() - 2;
+ this.$overflowHelper.text(this.getInputValue());
+ return this.$overflowHelper.width() >= constraint;
+ },
+ isCursorAtEnd: function() {
+ var valueLength, selectionStart, range;
+ valueLength = this.$input.val().length;
+ selectionStart = this.$input[0].selectionStart;
+ if (_.isNumber(selectionStart)) {
+ return selectionStart === valueLength;
+ } else if (document.selection) {
+ range = document.selection.createRange();
+ range.moveStart("character", -valueLength);
+ return valueLength === range.text.length;
+ }
+ return true;
+ },
+ destroy: function destroy() {
+ this.$hint.off(".tt");
+ this.$input.off(".tt");
+ this.$overflowHelper.remove();
+ this.$hint = this.$input = this.$overflowHelper = $("<div>");
+ }
+ });
+ return Input;
+ function buildOverflowHelper($input) {
+ return $('<pre aria-hidden="true"></pre>').css({
+ position: "absolute",
+ visibility: "hidden",
+ whiteSpace: "pre",
+ fontFamily: $input.css("font-family"),
+ fontSize: $input.css("font-size"),
+ fontStyle: $input.css("font-style"),
+ fontVariant: $input.css("font-variant"),
+ fontWeight: $input.css("font-weight"),
+ wordSpacing: $input.css("word-spacing"),
+ letterSpacing: $input.css("letter-spacing"),
+ textIndent: $input.css("text-indent"),
+ textRendering: $input.css("text-rendering"),
+ textTransform: $input.css("text-transform")
+ }).insertAfter($input);
+ }
+ function areQueriesEquivalent(a, b) {
+ return Input.normalizeQuery(a) === Input.normalizeQuery(b);
+ }
+ function withModifier($e) {
+ return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
+ }
+ }();
+ var Dataset = function() {
+ "use strict";
+ var keys, nameGenerator;
+ keys = {
+ dataset: "tt-selectable-dataset",
+ val: "tt-selectable-display",
+ obj: "tt-selectable-object"
+ };
+ nameGenerator = _.getIdGenerator();
+ function Dataset(o, www) {
+ o = o || {};
+ o.templates = o.templates || {};
+ o.templates.notFound = o.templates.notFound || o.templates.empty;
+ if (!o.source) {
+ $.error("missing source");
+ }
+ if (!o.node) {
+ $.error("missing node");
+ }
+ if (o.name && !isValidName(o.name)) {
+ $.error("invalid dataset name: " + o.name);
+ }
+ www.mixin(this);
+ this.highlight = !!o.highlight;
+ this.name = _.toStr(o.name || nameGenerator());
+ this.limit = o.limit || 5;
+ this.displayFn = getDisplayFn(o.display || o.displayKey);
+ this.templates = getTemplates(o.templates, this.displayFn);
+ this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
+ this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
+ this._resetLastSuggestion();
+ this.$el = $(o.node).attr("role", "presentation").addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
+ }
+ Dataset.extractData = function extractData(el) {
+ var $el = $(el);
+ if ($el.data(keys.obj)) {
+ return {
+ dataset: $el.data(keys.dataset) || "",
+ val: $el.data(keys.val) || "",
+ obj: $el.data(keys.obj) || null
+ };
+ }
+ return null;
+ };
+ _.mixin(Dataset.prototype, EventEmitter, {
+ _overwrite: function overwrite(query, suggestions) {
+ suggestions = suggestions || [];
+ if (suggestions.length) {
+ this._renderSuggestions(query, suggestions);
+ } else if (this.async && this.templates.pending) {
+ this._renderPending(query);
+ } else if (!this.async && this.templates.notFound) {
+ this._renderNotFound(query);
+ } else {
+ this._empty();
+ }
+ this.trigger("rendered", suggestions, false, this.name);
+ },
+ _append: function append(query, suggestions) {
+ suggestions = suggestions || [];
+ if (suggestions.length && this.$lastSuggestion.length) {
+ this._appendSuggestions(query, suggestions);
+ } else if (suggestions.length) {
+ this._renderSuggestions(query, suggestions);
+ } else if (!this.$lastSuggestion.length && this.templates.notFound) {
+ this._renderNotFound(query);
+ }
+ this.trigger("rendered", suggestions, true, this.name);
+ },
+ _renderSuggestions: function renderSuggestions(query, suggestions) {
+ var $fragment;
+ $fragment = this._getSuggestionsFragment(query, suggestions);
+ this.$lastSuggestion = $fragment.children().last();
+ this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
+ },
+ _appendSuggestions: function appendSuggestions(query, suggestions) {
+ var $fragment, $lastSuggestion;
+ $fragment = this._getSuggestionsFragment(query, suggestions);
+ $lastSuggestion = $fragment.children().last();
+ this.$lastSuggestion.after($fragment);
+ this.$lastSuggestion = $lastSuggestion;
+ },
+ _renderPending: function renderPending(query) {
+ var template = this.templates.pending;
+ this._resetLastSuggestion();
+ template && this.$el.html(template({
+ query: query,
+ dataset: this.name
+ }));
+ },
+ _renderNotFound: function renderNotFound(query) {
+ var template = this.templates.notFound;
+ this._resetLastSuggestion();
+ template && this.$el.html(template({
+ query: query,
+ dataset: this.name
+ }));
+ },
+ _empty: function empty() {
+ this.$el.empty();
+ this._resetLastSuggestion();
+ },
+ _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
+ var that = this, fragment;
+ fragment = document.createDocumentFragment();
+ _.each(suggestions, function getSuggestionNode(suggestion) {
+ var $el, context;
+ context = that._injectQuery(query, suggestion);
+ $el = $(that.templates.suggestion(context)).data(keys.dataset, that.name).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
+ fragment.appendChild($el[0]);
+ });
+ this.highlight && highlight({
+ className: this.classes.highlight,
+ node: fragment,
+ pattern: query
+ });
+ return $(fragment);
+ },
+ _getFooter: function getFooter(query, suggestions) {
+ return this.templates.footer ? this.templates.footer({
+ query: query,
+ suggestions: suggestions,
+ dataset: this.name
+ }) : null;
+ },
+ _getHeader: function getHeader(query, suggestions) {
+ return this.templates.header ? this.templates.header({
+ query: query,
+ suggestions: suggestions,
+ dataset: this.name
+ }) : null;
+ },
+ _resetLastSuggestion: function resetLastSuggestion() {
+ this.$lastSuggestion = $();
+ },
+ _injectQuery: function injectQuery(query, obj) {
+ return _.isObject(obj) ? _.mixin({
+ _query: query
+ }, obj) : obj;
+ },
+ update: function update(query) {
+ var that = this, canceled = false, syncCalled = false, rendered = 0;
+ this.cancel();
+ this.cancel = function cancel() {
+ canceled = true;
+ that.cancel = $.noop;
+ that.async && that.trigger("asyncCanceled", query, that.name);
+ };
+ this.source(query, sync, async);
+ !syncCalled && sync([]);
+ function sync(suggestions) {
+ if (syncCalled) {
+ return;
+ }
+ syncCalled = true;
+ suggestions = (suggestions || []).slice(0, that.limit);
+ rendered = suggestions.length;
+ that._overwrite(query, suggestions);
+ if (rendered < that.limit && that.async) {
+ that.trigger("asyncRequested", query, that.name);
+ }
+ }
+ function async(suggestions) {
+ suggestions = suggestions || [];
+ if (!canceled && rendered < that.limit) {
+ that.cancel = $.noop;
+ var idx = Math.abs(rendered - that.limit);
+ rendered += idx;
+ that._append(query, suggestions.slice(0, idx));
+ that.async && that.trigger("asyncReceived", query, that.name);
+ }
+ }
+ },
+ cancel: $.noop,
+ clear: function clear() {
+ this._empty();
+ this.cancel();
+ this.trigger("cleared");
+ },
+ isEmpty: function isEmpty() {
+ return this.$el.is(":empty");
+ },
+ destroy: function destroy() {
+ this.$el = $("<div>");
+ }
+ });
+ return Dataset;
+ function getDisplayFn(display) {
+ display = display || _.stringify;
+ return _.isFunction(display) ? display : displayFn;
+ function displayFn(obj) {
+ return obj[display];
+ }
+ }
+ function getTemplates(templates, displayFn) {
+ return {
+ notFound: templates.notFound && _.templatify(templates.notFound),
+ pending: templates.pending && _.templatify(templates.pending),
+ header: templates.header && _.templatify(templates.header),
+ footer: templates.footer && _.templatify(templates.footer),
+ suggestion: templates.suggestion || suggestionTemplate
+ };
+ function suggestionTemplate(context) {
+ return $('<div role="option">').attr("id", _.guid()).text(displayFn(context));
+ }
+ }
+ function isValidName(str) {
+ return /^[_a-zA-Z0-9-]+$/.test(str);
+ }
+ }();
+ var Menu = function() {
+ "use strict";
+ function Menu(o, www) {
+ var that = this;
+ o = o || {};
+ if (!o.node) {
+ $.error("node is required");
+ }
+ www.mixin(this);
+ this.$node = $(o.node);
+ this.query = null;
+ this.datasets = _.map(o.datasets, initializeDataset);
+ function initializeDataset(oDataset) {
+ var node = that.$node.find(oDataset.node).first();
+ oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
+ return new Dataset(oDataset, www);
+ }
+ }
+ _.mixin(Menu.prototype, EventEmitter, {
+ _onSelectableClick: function onSelectableClick($e) {
+ this.trigger("selectableClicked", $($e.currentTarget));
+ },
+ _onRendered: function onRendered(type, dataset, suggestions, async) {
+ this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
+ this.trigger("datasetRendered", dataset, suggestions, async);
+ },
+ _onCleared: function onCleared() {
+ this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
+ this.trigger("datasetCleared");
+ },
+ _propagate: function propagate() {
+ this.trigger.apply(this, arguments);
+ },
+ _allDatasetsEmpty: function allDatasetsEmpty() {
+ return _.every(this.datasets, _.bind(function isDatasetEmpty(dataset) {
+ var isEmpty = dataset.isEmpty();
+ this.$node.attr("aria-expanded", !isEmpty);
+ return isEmpty;
+ }, this));
+ },
+ _getSelectables: function getSelectables() {
+ return this.$node.find(this.selectors.selectable);
+ },
+ _removeCursor: function _removeCursor() {
+ var $selectable = this.getActiveSelectable();
+ $selectable && $selectable.removeClass(this.classes.cursor);
+ },
+ _ensureVisible: function ensureVisible($el) {
+ var elTop, elBottom, nodeScrollTop, nodeHeight;
+ elTop = $el.position().top;
+ elBottom = elTop + $el.outerHeight(true);
+ nodeScrollTop = this.$node.scrollTop();
+ nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
+ if (elTop < 0) {
+ this.$node.scrollTop(nodeScrollTop + elTop);
+ } else if (nodeHeight < elBottom) {
+ this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
+ }
+ },
+ bind: function() {
+ var that = this, onSelectableClick;
+ onSelectableClick = _.bind(this._onSelectableClick, this);
+ this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
+ this.$node.on("mouseover", this.selectors.selectable, function() {
+ that.setCursor($(this));
+ });
+ this.$node.on("mouseleave", function() {
+ that._removeCursor();
+ });
+ _.each(this.datasets, function(dataset) {
+ dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that);
+ });
+ return this;
+ },
+ isOpen: function isOpen() {
+ return this.$node.hasClass(this.classes.open);
+ },
+ open: function open() {
+ this.$node.scrollTop(0);
+ this.$node.addClass(this.classes.open);
+ },
+ close: function close() {
+ this.$node.attr("aria-expanded", false);
+ this.$node.removeClass(this.classes.open);
+ this._removeCursor();
+ },
+ setLanguageDirection: function setLanguageDirection(dir) {
+ this.$node.attr("dir", dir);
+ },
+ selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
+ var $selectables, $oldCursor, oldIndex, newIndex;
+ $oldCursor = this.getActiveSelectable();
+ $selectables = this._getSelectables();
+ oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
+ newIndex = oldIndex + delta;
+ newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
+ newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
+ return newIndex === -1 ? null : $selectables.eq(newIndex);
+ },
+ setCursor: function setCursor($selectable) {
+ this._removeCursor();
+ if ($selectable = $selectable && $selectable.first()) {
+ $selectable.addClass(this.classes.cursor);
+ this._ensureVisible($selectable);
+ }
+ },
+ getSelectableData: function getSelectableData($el) {
+ return $el && $el.length ? Dataset.extractData($el) : null;
+ },
+ getActiveSelectable: function getActiveSelectable() {
+ var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
+ return $selectable.length ? $selectable : null;
+ },
+ getTopSelectable: function getTopSelectable() {
+ var $selectable = this._getSelectables().first();
+ return $selectable.length ? $selectable : null;
+ },
+ update: function update(query) {
+ var isValidUpdate = query !== this.query;
+ if (isValidUpdate) {
+ this.query = query;
+ _.each(this.datasets, updateDataset);
+ }
+ return isValidUpdate;
+ function updateDataset(dataset) {
+ dataset.update(query);
+ }
+ },
+ empty: function empty() {
+ _.each(this.datasets, clearDataset);
+ this.query = null;
+ this.$node.addClass(this.classes.empty);
+ function clearDataset(dataset) {
+ dataset.clear();
+ }
+ },
+ destroy: function destroy() {
+ this.$node.off(".tt");
+ this.$node = $("<div>");
+ _.each(this.datasets, destroyDataset);
+ function destroyDataset(dataset) {
+ dataset.destroy();
+ }
+ }
+ });
+ return Menu;
+ }();
+ var Status = function() {
+ "use strict";
+ function Status(options) {
+ this.$el = $("<span></span>", {
+ role: "status",
+ "aria-live": "polite"
+ }).css({
+ position: "absolute",
+ padding: "0",
+ border: "0",
+ height: "1px",
+ width: "1px",
+ "margin-bottom": "-1px",
+ "margin-right": "-1px",
+ overflow: "hidden",
+ clip: "rect(0 0 0 0)",
+ "white-space": "nowrap"
+ });
+ options.$input.after(this.$el);
+ _.each(options.menu.datasets, _.bind(function(dataset) {
+ if (dataset.onSync) {
+ dataset.onSync("rendered", _.bind(this.update, this));
+ dataset.onSync("cleared", _.bind(this.cleared, this));
+ }
+ }, this));
+ }
+ _.mixin(Status.prototype, {
+ update: function update(event, suggestions) {
+ var length = suggestions.length;
+ var words;
+ if (length === 1) {
+ words = {
+ result: "result",
+ is: "is"
+ };
+ } else {
+ words = {
+ result: "results",
+ is: "are"
+ };
+ }
+ this.$el.text(length + " " + words.result + " " + words.is + " available, use up and down arrow keys to navigate.");
+ },
+ cleared: function() {
+ this.$el.text("");
+ }
+ });
+ return Status;
+ }();
+ var DefaultMenu = function() {
+ "use strict";
+ var s = Menu.prototype;
+ function DefaultMenu() {
+ Menu.apply(this, [].slice.call(arguments, 0));
+ }
+ _.mixin(DefaultMenu.prototype, Menu.prototype, {
+ open: function open() {
+ !this._allDatasetsEmpty() && this._show();
+ return s.open.apply(this, [].slice.call(arguments, 0));
+ },
+ close: function close() {
+ this._hide();
+ return s.close.apply(this, [].slice.call(arguments, 0));
+ },
+ _onRendered: function onRendered() {
+ if (this._allDatasetsEmpty()) {
+ this._hide();
+ } else {
+ this.isOpen() && this._show();
+ }
+ return s._onRendered.apply(this, [].slice.call(arguments, 0));
+ },
+ _onCleared: function onCleared() {
+ if (this._allDatasetsEmpty()) {
+ this._hide();
+ } else {
+ this.isOpen() && this._show();
+ }
+ return s._onCleared.apply(this, [].slice.call(arguments, 0));
+ },
+ setLanguageDirection: function setLanguageDirection(dir) {
+ this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
+ return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
+ },
+ _hide: function hide() {
+ this.$node.hide();
+ },
+ _show: function show() {
+ this.$node.css("display", "block");
+ }
+ });
+ return DefaultMenu;
+ }();
+ var Typeahead = function() {
+ "use strict";
+ function Typeahead(o, www) {
+ var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
+ o = o || {};
+ if (!o.input) {
+ $.error("missing input");
+ }
+ if (!o.menu) {
+ $.error("missing menu");
+ }
+ if (!o.eventBus) {
+ $.error("missing event bus");
+ }
+ www.mixin(this);
+ this.eventBus = o.eventBus;
+ this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
+ this.input = o.input;
+ this.menu = o.menu;
+ this.enabled = true;
+ this.autoselect = !!o.autoselect;
+ this.active = false;
+ this.input.hasFocus() && this.activate();
+ this.dir = this.input.getLangDir();
+ this._hacks();
+ this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this);
+ onFocused = c(this, "activate", "open", "_onFocused");
+ onBlurred = c(this, "deactivate", "_onBlurred");
+ onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
+ onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
+ onEscKeyed = c(this, "isActive", "_onEscKeyed");
+ onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
+ onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
+ onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
+ onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
+ onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
+ onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
+ this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this._onLangDirChanged, this);
+ }
+ _.mixin(Typeahead.prototype, {
+ _hacks: function hacks() {
+ var $input, $menu;
+ $input = this.input.$input || $("<div>");
+ $menu = this.menu.$node || $("<div>");
+ $input.on("blur.tt", function($e) {
+ var active, isActive, hasActive;
+ active = document.activeElement;
+ isActive = $menu.is(active);
+ hasActive = $menu.has(active).length > 0;
+ if (_.isMsie() && (isActive || hasActive)) {
+ $e.preventDefault();
+ $e.stopImmediatePropagation();
+ _.defer(function() {
+ $input.focus();
+ });
+ }
+ });
+ $menu.on("mousedown.tt", function($e) {
+ $e.preventDefault();
+ });
+ },
+ _onSelectableClicked: function onSelectableClicked(type, $el) {
+ this.select($el);
+ },
+ _onDatasetCleared: function onDatasetCleared() {
+ this._updateHint();
+ },
+ _onDatasetRendered: function onDatasetRendered(type, suggestions, async, dataset) {
+ this._updateHint();
+ if (this.autoselect) {
+ var cursorClass = this.selectors.cursor.substr(1);
+ this.menu.$node.find(this.selectors.suggestion).first().addClass(cursorClass);
+ }
+ this.eventBus.trigger("render", suggestions, async, dataset);
+ },
+ _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
+ this.eventBus.trigger("asyncrequest", query, dataset);
+ },
+ _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
+ this.eventBus.trigger("asynccancel", query, dataset);
+ },
+ _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
+ this.eventBus.trigger("asyncreceive", query, dataset);
+ },
+ _onFocused: function onFocused() {
+ this._minLengthMet() && this.menu.update(this.input.getQuery());
+ },
+ _onBlurred: function onBlurred() {
+ if (this.input.hasQueryChangedSinceLastFocus()) {
+ this.eventBus.trigger("change", this.input.getQuery());
+ }
+ },
+ _onEnterKeyed: function onEnterKeyed(type, $e) {
+ var $selectable;
+ if ($selectable = this.menu.getActiveSelectable()) {
+ if (this.select($selectable)) {
+ $e.preventDefault();
+ $e.stopPropagation();
+ }
+ } else if (this.autoselect) {
+ if (this.select(this.menu.getTopSelectable())) {
+ $e.preventDefault();
+ $e.stopPropagation();
+ }
+ }
+ },
+ _onTabKeyed: function onTabKeyed(type, $e) {
+ var $selectable;
+ if ($selectable = this.menu.getActiveSelectable()) {
+ this.select($selectable) && $e.preventDefault();
+ } else if ($selectable = this.menu.getTopSelectable()) {
+ this.autocomplete($selectable) && $e.preventDefault();
+ }
+ },
+ _onEscKeyed: function onEscKeyed() {
+ this.close();
+ },
+ _onUpKeyed: function onUpKeyed() {
+ this.moveCursor(-1);
+ },
+ _onDownKeyed: function onDownKeyed() {
+ this.moveCursor(+1);
+ },
+ _onLeftKeyed: function onLeftKeyed() {
+ if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
+ this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable());
+ }
+ },
+ _onRightKeyed: function onRightKeyed() {
+ if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
+ this.autocomplete(this.menu.getActiveSelectable() || this.menu.getTopSelectable());
+ }
+ },
+ _onQueryChanged: function onQueryChanged(e, query) {
+ this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
+ },
+ _onWhitespaceChanged: function onWhitespaceChanged() {
+ this._updateHint();
+ },
+ _onLangDirChanged: function onLangDirChanged(e, dir) {
+ if (this.dir !== dir) {
+ this.dir = dir;
+ this.menu.setLanguageDirection(dir);
+ }
+ },
+ _openIfActive: function openIfActive() {
+ this.isActive() && this.open();
+ },
+ _minLengthMet: function minLengthMet(query) {
+ query = _.isString(query) ? query : this.input.getQuery() || "";
+ return query.length >= this.minLength;
+ },
+ _updateHint: function updateHint() {
+ var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
+ $selectable = this.menu.getTopSelectable();
+ data = this.menu.getSelectableData($selectable);
+ val = this.input.getInputValue();
+ if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
+ query = Input.normalizeQuery(val);
+ escapedQuery = _.escapeRegExChars(query);
+ frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
+ match = frontMatchRegEx.exec(data.val);
+ match && this.input.setHint(val + match[1]);
+ } else {
+ this.input.clearHint();
+ }
+ },
+ isEnabled: function isEnabled() {
+ return this.enabled;
+ },
+ enable: function enable() {
+ this.enabled = true;
+ },
+ disable: function disable() {
+ this.enabled = false;
+ },
+ isActive: function isActive() {
+ return this.active;
+ },
+ activate: function activate() {
+ if (this.isActive()) {
+ return true;
+ } else if (!this.isEnabled() || this.eventBus.before("active")) {
+ return false;
+ } else {
+ this.active = true;
+ this.eventBus.trigger("active");
+ return true;
+ }
+ },
+ deactivate: function deactivate() {
+ if (!this.isActive()) {
+ return true;
+ } else if (this.eventBus.before("idle")) {
+ return false;
+ } else {
+ this.active = false;
+ this.close();
+ this.eventBus.trigger("idle");
+ return true;
+ }
+ },
+ isOpen: function isOpen() {
+ return this.menu.isOpen();
+ },
+ open: function open() {
+ if (!this.isOpen() && !this.eventBus.before("open")) {
+ this.menu.open();
+ this._updateHint();
+ this.eventBus.trigger("open");
+ }
+ return this.isOpen();
+ },
+ close: function close() {
+ if (this.isOpen() && !this.eventBus.before("close")) {
+ this.menu.close();
+ this.input.clearHint();
+ this.input.resetInputValue();
+ this.eventBus.trigger("close");
+ }
+ return !this.isOpen();
+ },
+ setVal: function setVal(val) {
+ this.input.setQuery(_.toStr(val));
+ },
+ getVal: function getVal() {
+ return this.input.getQuery();
+ },
+ select: function select($selectable) {
+ var data = this.menu.getSelectableData($selectable);
+ if (data && !this.eventBus.before("select", data.obj, data.dataset)) {
+ this.input.setQuery(data.val, true);
+ this.eventBus.trigger("select", data.obj, data.dataset);
+ this.close();
+ return true;
+ }
+ return false;
+ },
+ autocomplete: function autocomplete($selectable) {
+ var query, data, isValid;
+ query = this.input.getQuery();
+ data = this.menu.getSelectableData($selectable);
+ isValid = data && query !== data.val;
+ if (isValid && !this.eventBus.before("autocomplete", data.obj, data.dataset)) {
+ this.input.setQuery(data.val);
+ this.eventBus.trigger("autocomplete", data.obj, data.dataset);
+ return true;
+ }
+ return false;
+ },
+ moveCursor: function moveCursor(delta) {
+ var query, $candidate, data, suggestion, datasetName, cancelMove, id;
+ query = this.input.getQuery();
+ $candidate = this.menu.selectableRelativeToCursor(delta);
+ data = this.menu.getSelectableData($candidate);
+ suggestion = data ? data.obj : null;
+ datasetName = data ? data.dataset : null;
+ id = $candidate ? $candidate.attr("id") : null;
+ this.input.trigger("cursorchange", id);
+ cancelMove = this._minLengthMet() && this.menu.update(query);
+ if (!cancelMove && !this.eventBus.before("cursorchange", suggestion, datasetName)) {
+ this.menu.setCursor($candidate);
+ if (data) {
+ this.input.setInputValue(data.val);
+ } else {
+ this.input.resetInputValue();
+ this._updateHint();
+ }
+ this.eventBus.trigger("cursorchange", suggestion, datasetName);
+ return true;
+ }
+ return false;
+ },
+ destroy: function destroy() {
+ this.input.destroy();
+ this.menu.destroy();
+ }
+ });
+ return Typeahead;
+ function c(ctx) {
+ var methods = [].slice.call(arguments, 1);
+ return function() {
+ var args = [].slice.call(arguments);
+ _.each(methods, function(method) {
+ return ctx[method].apply(ctx, args);
+ });
+ };
+ }
+ }();
+ (function() {
+ "use strict";
+ var old, keys, methods;
+ old = $.fn.typeahead;
+ keys = {
+ www: "tt-www",
+ attrs: "tt-attrs",
+ typeahead: "tt-typeahead"
+ };
+ methods = {
+ initialize: function initialize(o, datasets) {
+ var www;
+ datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
+ o = o || {};
+ www = WWW(o.classNames);
+ return this.each(attach);
+ function attach() {
+ var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, status, typeahead, MenuConstructor;
+ _.each(datasets, function(d) {
+ d.highlight = !!o.highlight;
+ });
+ $input = $(this);
+ $wrapper = $(www.html.wrapper);
+ $hint = $elOrNull(o.hint);
+ $menu = $elOrNull(o.menu);
+ defaultHint = o.hint !== false && !$hint;
+ defaultMenu = o.menu !== false && !$menu;
+ defaultHint && ($hint = buildHintFromInput($input, www));
+ defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
+ $hint && $hint.val("");
+ $input = prepInput($input, www);
+ if (defaultHint || defaultMenu) {
+ $wrapper.css(www.css.wrapper);
+ $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
+ $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
+ }
+ MenuConstructor = defaultMenu ? DefaultMenu : Menu;
+ eventBus = new EventBus({
+ el: $input
+ });
+ input = new Input({
+ hint: $hint,
+ input: $input
+ }, www);
+ menu = new MenuConstructor({
+ node: $menu,
+ datasets: datasets
+ }, www);
+ status = new Status({
+ $input: $input,
+ menu: menu
+ });
+ typeahead = new Typeahead({
+ input: input,
+ menu: menu,
+ eventBus: eventBus,
+ minLength: o.minLength,
+ autoselect: o.autoselect
+ }, www);
+ $input.data(keys.www, www);
+ $input.data(keys.typeahead, typeahead);
+ }
+ },
+ isEnabled: function isEnabled() {
+ var enabled;
+ ttEach(this.first(), function(t) {
+ enabled = t.isEnabled();
+ });
+ return enabled;
+ },
+ enable: function enable() {
+ ttEach(this, function(t) {
+ t.enable();
+ });
+ return this;
+ },
+ disable: function disable() {
+ ttEach(this, function(t) {
+ t.disable();
+ });
+ return this;
+ },
+ isActive: function isActive() {
+ var active;
+ ttEach(this.first(), function(t) {
+ active = t.isActive();
+ });
+ return active;
+ },
+ activate: function activate() {
+ ttEach(this, function(t) {
+ t.activate();
+ });
+ return this;
+ },
+ deactivate: function deactivate() {
+ ttEach(this, function(t) {
+ t.deactivate();
+ });
+ return this;
+ },
+ isOpen: function isOpen() {
+ var open;
+ ttEach(this.first(), function(t) {
+ open = t.isOpen();
+ });
+ return open;
+ },
+ open: function open() {
+ ttEach(this, function(t) {
+ t.open();
+ });
+ return this;
+ },
+ close: function close() {
+ ttEach(this, function(t) {
+ t.close();
+ });
+ return this;
+ },
+ select: function select(el) {
+ var success = false, $el = $(el);
+ ttEach(this.first(), function(t) {
+ success = t.select($el);
+ });
+ return success;
+ },
+ autocomplete: function autocomplete(el) {
+ var success = false, $el = $(el);
+ ttEach(this.first(), function(t) {
+ success = t.autocomplete($el);
+ });
+ return success;
+ },
+ moveCursor: function moveCursoe(delta) {
+ var success = false;
+ ttEach(this.first(), function(t) {
+ success = t.moveCursor(delta);
+ });
+ return success;
+ },
+ val: function val(newVal) {
+ var query;
+ if (!arguments.length) {
+ ttEach(this.first(), function(t) {
+ query = t.getVal();
+ });
+ return query;
+ } else {
+ ttEach(this, function(t) {
+ t.setVal(_.toStr(newVal));
+ });
+ return this;
+ }
+ },
+ destroy: function destroy() {
+ ttEach(this, function(typeahead, $input) {
+ revert($input);
+ typeahead.destroy();
+ });
+ return this;
+ }
+ };
+ $.fn.typeahead = function(method) {
+ if (methods[method]) {
+ return methods[method].apply(this, [].slice.call(arguments, 1));
+ } else {
+ return methods.initialize.apply(this, arguments);
+ }
+ };
+ $.fn.typeahead.noConflict = function noConflict() {
+ $.fn.typeahead = old;
+ return this;
+ };
+ function ttEach($els, fn) {
+ $els.each(function() {
+ var $input = $(this), typeahead;
+ (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
+ });
+ }
+ function buildHintFromInput($input, www) {
+ return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop({
+ readonly: true,
+ required: false
+ }).removeAttr("id name placeholder").removeClass("required").attr({
+ spellcheck: "false",
+ tabindex: -1
+ });
+ }
+ function prepInput($input, www) {
+ $input.data(keys.attrs, {
+ dir: $input.attr("dir"),
+ autocomplete: $input.attr("autocomplete"),
+ spellcheck: $input.attr("spellcheck"),
+ style: $input.attr("style")
+ });
+ $input.addClass(www.classes.input).attr({
+ spellcheck: false
+ });
+ try {
+ !$input.attr("dir") && $input.attr("dir", "auto");
+ } catch (e) {}
+ return $input;
+ }
+ function getBackgroundStyles($el) {
+ return {
+ backgroundAttachment: $el.css("background-attachment"),
+ backgroundClip: $el.css("background-clip"),
+ backgroundColor: $el.css("background-color"),
+ backgroundImage: $el.css("background-image"),
+ backgroundOrigin: $el.css("background-origin"),
+ backgroundPosition: $el.css("background-position"),
+ backgroundRepeat: $el.css("background-repeat"),
+ backgroundSize: $el.css("background-size")
+ };
+ }
+ function revert($input) {
+ var www, $wrapper;
+ www = $input.data(keys.www);
+ $wrapper = $input.parent().filter(www.selectors.wrapper);
+ _.each($input.data(keys.attrs), function(val, key) {
+ _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
+ });
+ $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
+ if ($wrapper.length) {
+ $input.detach().insertAfter($wrapper);
+ $wrapper.remove();
+ }
+ }
+ function $elOrNull(obj) {
+ var isValid, $el;
+ isValid = _.isJQuery(obj) || _.isElement(obj);
+ $el = isValid ? $(obj).first() : [];
+ return $el.length ? $el : null;
+ }
+ })();
+});
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(128).setImmediate))
+
+/***/ }),
+/* 128 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var apply = Function.prototype.apply;
+
+// DOM APIs, for completeness
+
+exports.setTimeout = function() {
+ return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout);
+};
+exports.setInterval = function() {
+ return new Timeout(apply.call(setInterval, window, arguments), clearInterval);
+};
+exports.clearTimeout =
+exports.clearInterval = function(timeout) {
+ if (timeout) {
+ timeout.close();
+ }
+};
+
+function Timeout(id, clearFn) {
+ this._id = id;
+ this._clearFn = clearFn;
+}
+Timeout.prototype.unref = Timeout.prototype.ref = function() {};
+Timeout.prototype.close = function() {
+ this._clearFn.call(window, this._id);
+};
+
+// Does not start the time, just sets up the members needed.
+exports.enroll = function(item, msecs) {
+ clearTimeout(item._idleTimeoutId);
+ item._idleTimeout = msecs;
+};
+
+exports.unenroll = function(item) {
+ clearTimeout(item._idleTimeoutId);
+ item._idleTimeout = -1;
+};
+
+exports._unrefActive = exports.active = function(item) {
+ clearTimeout(item._idleTimeoutId);
+
+ var msecs = item._idleTimeout;
+ if (msecs >= 0) {
+ item._idleTimeoutId = setTimeout(function onTimeout() {
+ if (item._onTimeout)
+ item._onTimeout();
+ }, msecs);
+ }
+};
+
+// setimmediate attaches itself to the global object
+__webpack_require__(129);
+exports.setImmediate = setImmediate;
+exports.clearImmediate = clearImmediate;
+
+
+/***/ }),
+/* 129 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function(global, process) {(function (global, undefined) {
+ "use strict";
+
+ if (global.setImmediate) {
+ return;
+ }
+
+ var nextHandle = 1; // Spec says greater than zero
+ var tasksByHandle = {};
+ var currentlyRunningATask = false;
+ var doc = global.document;
+ var registerImmediate;
+
+ function setImmediate(callback) {
+ // Callback can either be a function or a string
+ if (typeof callback !== "function") {
+ callback = new Function("" + callback);
+ }
+ // Copy function arguments
+ var args = new Array(arguments.length - 1);
+ for (var i = 0; i < args.length; i++) {
+ args[i] = arguments[i + 1];
+ }
+ // Store and register the task
+ var task = { callback: callback, args: args };
+ tasksByHandle[nextHandle] = task;
+ registerImmediate(nextHandle);
+ return nextHandle++;
+ }
+
+ function clearImmediate(handle) {
+ delete tasksByHandle[handle];
+ }
+
+ function run(task) {
+ var callback = task.callback;
+ var args = task.args;
+ switch (args.length) {
+ case 0:
+ callback();
+ break;
+ case 1:
+ callback(args[0]);
+ break;
+ case 2:
+ callback(args[0], args[1]);
+ break;
+ case 3:
+ callback(args[0], args[1], args[2]);
+ break;
+ default:
+ callback.apply(undefined, args);
+ break;
+ }
+ }
+
+ function runIfPresent(handle) {
+ // From the spec: "Wait until any invocations of this algorithm started before this one have completed."
+ // So if we're currently running a task, we'll need to delay this invocation.
+ if (currentlyRunningATask) {
+ // Delay by doing a setTimeout. setImmediate was tried instead, but in Firefox 7 it generated a
+ // "too much recursion" error.
+ setTimeout(runIfPresent, 0, handle);
+ } else {
+ var task = tasksByHandle[handle];
+ if (task) {
+ currentlyRunningATask = true;
+ try {
+ run(task);
+ } finally {
+ clearImmediate(handle);
+ currentlyRunningATask = false;
+ }
+ }
+ }
+ }
+
+ function installNextTickImplementation() {
+ registerImmediate = function(handle) {
+ process.nextTick(function () { runIfPresent(handle); });
+ };
+ }
+
+ function canUsePostMessage() {
+ // The test against `importScripts` prevents this implementation from being installed inside a web worker,
+ // where `global.postMessage` means something completely different and can't be used for this purpose.
+ if (global.postMessage && !global.importScripts) {
+ var postMessageIsAsynchronous = true;
+ var oldOnMessage = global.onmessage;
+ global.onmessage = function() {
+ postMessageIsAsynchronous = false;
+ };
+ global.postMessage("", "*");
+ global.onmessage = oldOnMessage;
+ return postMessageIsAsynchronous;
+ }
+ }
+
+ function installPostMessageImplementation() {
+ // Installs an event handler on `global` for the `message` event: see
+ // * https://developer.mozilla.org/en/DOM/window.postMessage
+ // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
+
+ var messagePrefix = "setImmediate$" + Math.random() + "$";
+ var onGlobalMessage = function(event) {
+ if (event.source === global &&
+ typeof event.data === "string" &&
+ event.data.indexOf(messagePrefix) === 0) {
+ runIfPresent(+event.data.slice(messagePrefix.length));
+ }
+ };
+
+ if (global.addEventListener) {
+ global.addEventListener("message", onGlobalMessage, false);
+ } else {
+ global.attachEvent("onmessage", onGlobalMessage);
+ }
+
+ registerImmediate = function(handle) {
+ global.postMessage(messagePrefix + handle, "*");
+ };
+ }
+
+ function installMessageChannelImplementation() {
+ var channel = new MessageChannel();
+ channel.port1.onmessage = function(event) {
+ var handle = event.data;
+ runIfPresent(handle);
+ };
+
+ registerImmediate = function(handle) {
+ channel.port2.postMessage(handle);
+ };
+ }
+
+ function installReadyStateChangeImplementation() {
+ var html = doc.documentElement;
+ registerImmediate = function(handle) {
+ // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
+ // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
+ var script = doc.createElement("script");
+ script.onreadystatechange = function () {
+ runIfPresent(handle);
+ script.onreadystatechange = null;
+ html.removeChild(script);
+ script = null;
+ };
+ html.appendChild(script);
+ };
+ }
+
+ function installSetTimeoutImplementation() {
+ registerImmediate = function(handle) {
+ setTimeout(runIfPresent, 0, handle);
+ };
+ }
+
+ // If supported, we should attach to the prototype of global, since that is where setTimeout et al. live.
+ var attachTo = Object.getPrototypeOf && Object.getPrototypeOf(global);
+ attachTo = attachTo && attachTo.setTimeout ? attachTo : global;
+
+ // Don't get fooled by e.g. browserify environments.
+ if ({}.toString.call(global.process) === "[object process]") {
+ // For Node.js before 0.9
+ installNextTickImplementation();
+
+ } else if (canUsePostMessage()) {
+ // For non-IE10 modern browsers
+ installPostMessageImplementation();
+
+ } else if (global.MessageChannel) {
+ // For web workers, where supported
+ installMessageChannelImplementation();
+
+ } else if (doc && "onreadystatechange" in doc.createElement("script")) {
+ // For IE 6–8
+ installReadyStateChangeImplementation();
+
+ } else {
+ // For older browsers
+ installSetTimeoutImplementation();
+ }
+
+ attachTo.setImmediate = setImmediate;
+ attachTo.clearImmediate = clearImmediate;
+}(typeof self === "undefined" ? typeof global === "undefined" ? this : global : self));
+
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(3), __webpack_require__(130)))
+
+/***/ }),
+/* 130 */
+/***/ (function(module, exports) {
+
+// shim for using process in browser
+var process = module.exports = {};
+
+// cached from whatever global is present so that test runners that stub it
+// don't break things. But we need to wrap it in a try catch in case it is
+// wrapped in strict mode code which doesn't define any globals. It's inside a
+// function because try/catches deoptimize in certain engines.
+
+var cachedSetTimeout;
+var cachedClearTimeout;
+
+function defaultSetTimout() {
+ throw new Error('setTimeout has not been defined');
+}
+function defaultClearTimeout () {
+ throw new Error('clearTimeout has not been defined');
+}
+(function () {
+ try {
+ if (typeof setTimeout === 'function') {
+ cachedSetTimeout = setTimeout;
+ } else {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ } catch (e) {
+ cachedSetTimeout = defaultSetTimout;
+ }
+ try {
+ if (typeof clearTimeout === 'function') {
+ cachedClearTimeout = clearTimeout;
+ } else {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+ } catch (e) {
+ cachedClearTimeout = defaultClearTimeout;
+ }
+} ())
+function runTimeout(fun) {
+ if (cachedSetTimeout === setTimeout) {
+ //normal enviroments in sane situations
+ return setTimeout(fun, 0);
+ }
+ // if setTimeout wasn't available but was latter defined
+ if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
+ cachedSetTimeout = setTimeout;
+ return setTimeout(fun, 0);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedSetTimeout(fun, 0);
+ } catch(e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedSetTimeout.call(null, fun, 0);
+ } catch(e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
+ return cachedSetTimeout.call(this, fun, 0);
+ }
+ }
+
+
+}
+function runClearTimeout(marker) {
+ if (cachedClearTimeout === clearTimeout) {
+ //normal enviroments in sane situations
+ return clearTimeout(marker);
+ }
+ // if clearTimeout wasn't available but was latter defined
+ if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
+ cachedClearTimeout = clearTimeout;
+ return clearTimeout(marker);
+ }
+ try {
+ // when when somebody has screwed with setTimeout but no I.E. maddness
+ return cachedClearTimeout(marker);
+ } catch (e){
+ try {
+ // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
+ return cachedClearTimeout.call(null, marker);
+ } catch (e){
+ // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
+ // Some versions of I.E. have different rules for clearTimeout vs setTimeout
+ return cachedClearTimeout.call(this, marker);
+ }
+ }
+
+
+
+}
+var queue = [];
+var draining = false;
+var currentQueue;
+var queueIndex = -1;
+
+function cleanUpNextTick() {
+ if (!draining || !currentQueue) {
+ return;
+ }
+ draining = false;
+ if (currentQueue.length) {
+ queue = currentQueue.concat(queue);
+ } else {
+ queueIndex = -1;
+ }
+ if (queue.length) {
+ drainQueue();
+ }
+}
+
+function drainQueue() {
+ if (draining) {
+ return;
+ }
+ var timeout = runTimeout(cleanUpNextTick);
+ draining = true;
+
+ var len = queue.length;
+ while(len) {
+ currentQueue = queue;
+ queue = [];
+ while (++queueIndex < len) {
+ if (currentQueue) {
+ currentQueue[queueIndex].run();
+ }
+ }
+ queueIndex = -1;
+ len = queue.length;
+ }
+ currentQueue = null;
+ draining = false;
+ runClearTimeout(timeout);
+}
+
+process.nextTick = function (fun) {
+ var args = new Array(arguments.length - 1);
+ if (arguments.length > 1) {
+ for (var i = 1; i < arguments.length; i++) {
+ args[i - 1] = arguments[i];
+ }
+ }
+ queue.push(new Item(fun, args));
+ if (queue.length === 1 && !draining) {
+ runTimeout(drainQueue);
+ }
+};
+
+// v8 likes predictible objects
+function Item(fun, array) {
+ this.fun = fun;
+ this.array = array;
+}
+Item.prototype.run = function () {
+ this.fun.apply(null, this.array);
+};
+process.title = 'browser';
+process.browser = true;
+process.env = {};
+process.argv = [];
+process.version = ''; // empty string to avoid regexp issues
+process.versions = {};
+
+function noop() {}
+
+process.on = noop;
+process.addListener = noop;
+process.once = noop;
+process.off = noop;
+process.removeListener = noop;
+process.removeAllListeners = noop;
+process.emit = noop;
+process.prependListener = noop;
+process.prependOnceListener = noop;
+
+process.listeners = function (name) { return [] }
+
+process.binding = function (name) {
+ throw new Error('process.binding is not supported');
+};
+
+process.cwd = function () { return '/' };
+process.chdir = function (dir) {
+ throw new Error('process.chdir is not supported');
+};
+process.umask = function() { return 0; };
+
+
+/***/ }),
+/* 131 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! DataTables Bootstrap 3 integration
+ * ©2011-2015 SpryMedia Ltd - datatables.net/license
+ */
+
+/**
+ * DataTables integration for Bootstrap 3. This requires Bootstrap 3 and
+ * DataTables 1.10 or newer.
+ *
+ * This file sets the defaults and adds options to DataTables to style its
+ * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
+ * for further information.
+ */
+(function( factory ){
+ if ( true ) {
+ // AMD
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1), __webpack_require__(4)], __WEBPACK_AMD_DEFINE_RESULT__ = (function ( $ ) {
+ return factory( $, window, document );
+ }).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ }
+ else if ( typeof exports === 'object' ) {
+ // CommonJS
+ module.exports = function (root, $) {
+ if ( ! root ) {
+ root = window;
+ }
+
+ if ( ! $ || ! $.fn.dataTable ) {
+ // Require DataTables, which attaches to jQuery, including
+ // jQuery if needed and have a $ property so we can access the
+ // jQuery object that is used
+ $ = require('datatables.net')(root, $).$;
+ }
+
+ return factory( $, root, root.document );
+ };
+ }
+ else {
+ // Browser
+ factory( jQuery, window, document );
+ }
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+
+/* Set the defaults for DataTables initialisation */
+$.extend( true, DataTable.defaults, {
+ dom:
+ "<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>" +
+ "<'row'<'col-sm-12'tr>>" +
+ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+ renderer: 'bootstrap'
+} );
+
+
+/* Default class modification */
+$.extend( DataTable.ext.classes, {
+ sWrapper: "dataTables_wrapper container-fluid dt-bootstrap4",
+ sFilterInput: "form-control form-control-sm",
+ sLengthSelect: "form-control form-control-sm",
+ sProcessing: "dataTables_processing card",
+ sPageButton: "paginate_button page-item"
+} );
+
+
+/* Bootstrap paging button renderer */
+DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
+ var api = new DataTable.Api( settings );
+ var classes = settings.oClasses;
+ var lang = settings.oLanguage.oPaginate;
+ var aria = settings.oLanguage.oAria.paginate || {};
+ var btnDisplay, btnClass, counter=0;
+
+ var attach = function( container, buttons ) {
+ var i, ien, node, button;
+ var clickHandler = function ( e ) {
+ e.preventDefault();
+ if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
+ api.page( e.data.action ).draw( 'page' );
+ }
+ };
+
+ for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
+ button = buttons[i];
+
+ if ( $.isArray( button ) ) {
+ attach( container, button );
+ }
+ else {
+ btnDisplay = '';
+ btnClass = '';
+
+ switch ( button ) {
+ case 'ellipsis':
+ btnDisplay = '&#x2026;';
+ btnClass = 'disabled';
+ break;
+
+ case 'first':
+ btnDisplay = lang.sFirst;
+ btnClass = button + (page > 0 ?
+ '' : ' disabled');
+ break;
+
+ case 'previous':
+ btnDisplay = lang.sPrevious;
+ btnClass = button + (page > 0 ?
+ '' : ' disabled');
+ break;
+
+ case 'next':
+ btnDisplay = lang.sNext;
+ btnClass = button + (page < pages-1 ?
+ '' : ' disabled');
+ break;
+
+ case 'last':
+ btnDisplay = lang.sLast;
+ btnClass = button + (page < pages-1 ?
+ '' : ' disabled');
+ break;
+
+ default:
+ btnDisplay = button + 1;
+ btnClass = page === button ?
+ 'active' : '';
+ break;
+ }
+
+ if ( btnDisplay ) {
+ node = $('<li>', {
+ 'class': classes.sPageButton+' '+btnClass,
+ 'id': idx === 0 && typeof button === 'string' ?
+ settings.sTableId +'_'+ button :
+ null
+ } )
+ .append( $('<a>', {
+ 'href': '#',
+ 'aria-controls': settings.sTableId,
+ 'aria-label': aria[ button ],
+ 'data-dt-idx': counter,
+ 'tabindex': settings.iTabIndex,
+ 'class': 'page-link'
+ } )
+ .html( btnDisplay )
+ )
+ .appendTo( container );
+
+ settings.oApi._fnBindAction(
+ node, {action: button}, clickHandler
+ );
+
+ counter++;
+ }
+ }
+ }
+ };
+
+ // IE9 throws an 'unknown error' if document.activeElement is used
+ // inside an iframe or frame.
+ var activeEl;
+
+ try {
+ // Because this approach is destroying and recreating the paging
+ // elements, focus is lost on the select button which is bad for
+ // accessibility. So we want to restore focus once the draw has
+ // completed
+ activeEl = $(host).find(document.activeElement).data('dt-idx');
+ }
+ catch (e) {}
+
+ attach(
+ $(host).empty().html('<ul class="pagination"/>').children('ul'),
+ buttons
+ );
+
+ if ( activeEl !== undefined ) {
+ $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
+ }
+};
+
+
+return DataTable;
+}));
+
+
+/***/ }),
+/* 132 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_RESULT__;/**!
+ * Sortable
+ * @author RubaXa <trash@rubaxa.org>
+ * @license MIT
+ */
+
+(function sortableModule(factory) {
+ "use strict";
+
+ if (true) {
+ !(__WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
+ __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
+ (__WEBPACK_AMD_DEFINE_FACTORY__.call(exports, __webpack_require__, exports, module)) :
+ __WEBPACK_AMD_DEFINE_FACTORY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ }
+ else if (typeof module != "undefined" && typeof module.exports != "undefined") {
+ module.exports = factory();
+ }
+ else {
+ /* jshint sub:true */
+ window["Sortable"] = factory();
+ }
+})(function sortableFactory() {
+ "use strict";
+
+ if (typeof window === "undefined" || !window.document) {
+ return function sortableError() {
+ throw new Error("Sortable.js requires a window with a document");
+ };
+ }
+
+ var dragEl,
+ parentEl,
+ ghostEl,
+ cloneEl,
+ rootEl,
+ nextEl,
+ lastDownEl,
+
+ scrollEl,
+ scrollParentEl,
+ scrollCustomFn,
+
+ lastEl,
+ lastCSS,
+ lastParentCSS,
+
+ oldIndex,
+ newIndex,
+
+ activeGroup,
+ putSortable,
+
+ autoScroll = {},
+
+ tapEvt,
+ touchEvt,
+
+ moved,
+
+ /** @const */
+ R_SPACE = /\s+/g,
+ R_FLOAT = /left|right|inline/,
+
+ expando = 'Sortable' + (new Date).getTime(),
+
+ win = window,
+ document = win.document,
+ parseInt = win.parseInt,
+ setTimeout = win.setTimeout,
+
+ $ = win.jQuery || win.Zepto,
+ Polymer = win.Polymer,
+
+ captureMode = false,
+ passiveMode = false,
+
+ supportDraggable = ('draggable' in document.createElement('div')),
+ supportCssPointerEvents = (function (el) {
+ // false when IE11
+ if (!!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\.|msie)/i)) {
+ return false;
+ }
+ el = document.createElement('x');
+ el.style.cssText = 'pointer-events:auto';
+ return el.style.pointerEvents === 'auto';
+ })(),
+
+ _silent = false,
+
+ abs = Math.abs,
+ min = Math.min,
+
+ savedInputChecked = [],
+ touchDragOverListeners = [],
+
+ _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {
+ // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
+ if (rootEl && options.scroll) {
+ var _this = rootEl[expando],
+ el,
+ rect,
+ sens = options.scrollSensitivity,
+ speed = options.scrollSpeed,
+
+ x = evt.clientX,
+ y = evt.clientY,
+
+ winWidth = window.innerWidth,
+ winHeight = window.innerHeight,
+
+ vx,
+ vy,
+
+ scrollOffsetX,
+ scrollOffsetY
+ ;
+
+ // Delect scrollEl
+ if (scrollParentEl !== rootEl) {
+ scrollEl = options.scroll;
+ scrollParentEl = rootEl;
+ scrollCustomFn = options.scrollFn;
+
+ if (scrollEl === true) {
+ scrollEl = rootEl;
+
+ do {
+ if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
+ (scrollEl.offsetHeight < scrollEl.scrollHeight)
+ ) {
+ break;
+ }
+ /* jshint boss:true */
+ } while (scrollEl = scrollEl.parentNode);
+ }
+ }
+
+ if (scrollEl) {
+ el = scrollEl;
+ rect = scrollEl.getBoundingClientRect();
+ vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
+ vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
+ }
+
+
+ if (!(vx || vy)) {
+ vx = (winWidth - x <= sens) - (x <= sens);
+ vy = (winHeight - y <= sens) - (y <= sens);
+
+ /* jshint expr:true */
+ (vx || vy) && (el = win);
+ }
+
+
+ if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
+ autoScroll.el = el;
+ autoScroll.vx = vx;
+ autoScroll.vy = vy;
+
+ clearInterval(autoScroll.pid);
+
+ if (el) {
+ autoScroll.pid = setInterval(function () {
+ scrollOffsetY = vy ? vy * speed : 0;
+ scrollOffsetX = vx ? vx * speed : 0;
+
+ if ('function' === typeof(scrollCustomFn)) {
+ return scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt);
+ }
+
+ if (el === win) {
+ win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY);
+ } else {
+ el.scrollTop += scrollOffsetY;
+ el.scrollLeft += scrollOffsetX;
+ }
+ }, 24);
+ }
+ }
+ }
+ }, 30),
+
+ _prepareGroup = function (options) {
+ function toFn(value, pull) {
+ if (value === void 0 || value === true) {
+ value = group.name;
+ }
+
+ if (typeof value === 'function') {
+ return value;
+ } else {
+ return function (to, from) {
+ var fromGroup = from.options.group.name;
+
+ return pull
+ ? value
+ : value && (value.join
+ ? value.indexOf(fromGroup) > -1
+ : (fromGroup == value)
+ );
+ };
+ }
+ }
+
+ var group = {};
+ var originalGroup = options.group;
+
+ if (!originalGroup || typeof originalGroup != 'object') {
+ originalGroup = {name: originalGroup};
+ }
+
+ group.name = originalGroup.name;
+ group.checkPull = toFn(originalGroup.pull, true);
+ group.checkPut = toFn(originalGroup.put);
+ group.revertClone = originalGroup.revertClone;
+
+ options.group = group;
+ }
+ ;
+
+ // Detect support a passive mode
+ try {
+ window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
+ get: function () {
+ // `false`, because everything starts to work incorrectly and instead of d'n'd,
+ // begins the page has scrolled.
+ passiveMode = false;
+ captureMode = {
+ capture: false,
+ passive: passiveMode
+ };
+ }
+ }));
+ } catch (err) {}
+
+ /**
+ * @class Sortable
+ * @param {HTMLElement} el
+ * @param {Object} [options]
+ */
+ function Sortable(el, options) {
+ if (!(el && el.nodeType && el.nodeType === 1)) {
+ throw 'Sortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);
+ }
+
+ this.el = el; // root element
+ this.options = options = _extend({}, options);
+
+
+ // Export instance
+ el[expando] = this;
+
+ // Default options
+ var defaults = {
+ group: Math.random(),
+ sort: true,
+ disabled: false,
+ store: null,
+ handle: null,
+ scroll: true,
+ scrollSensitivity: 30,
+ scrollSpeed: 10,
+ draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
+ ghostClass: 'sortable-ghost',
+ chosenClass: 'sortable-chosen',
+ dragClass: 'sortable-drag',
+ ignore: 'a, img',
+ filter: null,
+ preventOnFilter: true,
+ animation: 0,
+ setData: function (dataTransfer, dragEl) {
+ dataTransfer.setData('Text', dragEl.textContent);
+ },
+ dropBubble: false,
+ dragoverBubble: false,
+ dataIdAttr: 'data-id',
+ delay: 0,
+ forceFallback: false,
+ fallbackClass: 'sortable-fallback',
+ fallbackOnBody: false,
+ fallbackTolerance: 0,
+ fallbackOffset: {x: 0, y: 0},
+ supportPointer: Sortable.supportPointer !== false
+ };
+
+
+ // Set default options
+ for (var name in defaults) {
+ !(name in options) && (options[name] = defaults[name]);
+ }
+
+ _prepareGroup(options);
+
+ // Bind all private methods
+ for (var fn in this) {
+ if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
+ this[fn] = this[fn].bind(this);
+ }
+ }
+
+ // Setup drag mode
+ this.nativeDraggable = options.forceFallback ? false : supportDraggable;
+
+ // Bind events
+ _on(el, 'mousedown', this._onTapStart);
+ _on(el, 'touchstart', this._onTapStart);
+ options.supportPointer && _on(el, 'pointerdown', this._onTapStart);
+
+ if (this.nativeDraggable) {
+ _on(el, 'dragover', this);
+ _on(el, 'dragenter', this);
+ }
+
+ touchDragOverListeners.push(this._onDragOver);
+
+ // Restore sorting
+ options.store && this.sort(options.store.get(this));
+ }
+
+
+ Sortable.prototype = /** @lends Sortable.prototype */ {
+ constructor: Sortable,
+
+ _onTapStart: function (/** Event|TouchEvent */evt) {
+ var _this = this,
+ el = this.el,
+ options = this.options,
+ preventOnFilter = options.preventOnFilter,
+ type = evt.type,
+ touch = evt.touches && evt.touches[0],
+ target = (touch || evt).target,
+ originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0]) || target,
+ filter = options.filter,
+ startIndex;
+
+ _saveInputCheckedState(el);
+
+
+ // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
+ if (dragEl) {
+ return;
+ }
+
+ if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
+ return; // only left button or enabled
+ }
+
+ // cancel dnd if original target is content editable
+ if (originalTarget.isContentEditable) {
+ return;
+ }
+
+ target = _closest(target, options.draggable, el);
+
+ if (!target) {
+ return;
+ }
+
+ if (lastDownEl === target) {
+ // Ignoring duplicate `down`
+ return;
+ }
+
+ // Get the index of the dragged element within its parent
+ startIndex = _index(target, options.draggable);
+
+ // Check filter
+ if (typeof filter === 'function') {
+ if (filter.call(this, evt, target, this)) {
+ _dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex);
+ preventOnFilter && evt.preventDefault();
+ return; // cancel dnd
+ }
+ }
+ else if (filter) {
+ filter = filter.split(',').some(function (criteria) {
+ criteria = _closest(originalTarget, criteria.trim(), el);
+
+ if (criteria) {
+ _dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex);
+ return true;
+ }
+ });
+
+ if (filter) {
+ preventOnFilter && evt.preventDefault();
+ return; // cancel dnd
+ }
+ }
+
+ if (options.handle && !_closest(originalTarget, options.handle, el)) {
+ return;
+ }
+
+ // Prepare `dragstart`
+ this._prepareDragStart(evt, touch, target, startIndex);
+ },
+
+ _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {
+ var _this = this,
+ el = _this.el,
+ options = _this.options,
+ ownerDocument = el.ownerDocument,
+ dragStartFn;
+
+ if (target && !dragEl && (target.parentNode === el)) {
+ tapEvt = evt;
+
+ rootEl = el;
+ dragEl = target;
+ parentEl = dragEl.parentNode;
+ nextEl = dragEl.nextSibling;
+ lastDownEl = target;
+ activeGroup = options.group;
+ oldIndex = startIndex;
+
+ this._lastX = (touch || evt).clientX;
+ this._lastY = (touch || evt).clientY;
+
+ dragEl.style['will-change'] = 'all';
+
+ dragStartFn = function () {
+ // Delayed drag has been triggered
+ // we can re-enable the events: touchmove/mousemove
+ _this._disableDelayedDrag();
+
+ // Make the element draggable
+ dragEl.draggable = _this.nativeDraggable;
+
+ // Chosen item
+ _toggleClass(dragEl, options.chosenClass, true);
+
+ // Bind the events: dragstart/dragend
+ _this._triggerDragStart(evt, touch);
+
+ // Drag start event
+ _dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex);
+ };
+
+ // Disable "draggable"
+ options.ignore.split(',').forEach(function (criteria) {
+ _find(dragEl, criteria.trim(), _disableDraggable);
+ });
+
+ _on(ownerDocument, 'mouseup', _this._onDrop);
+ _on(ownerDocument, 'touchend', _this._onDrop);
+ _on(ownerDocument, 'touchcancel', _this._onDrop);
+ _on(ownerDocument, 'selectstart', _this);
+ options.supportPointer && _on(ownerDocument, 'pointercancel', _this._onDrop);
+
+ if (options.delay) {
+ // If the user moves the pointer or let go the click or touch
+ // before the delay has been reached:
+ // disable the delayed drag
+ _on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
+ _on(ownerDocument, 'touchend', _this._disableDelayedDrag);
+ _on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
+ _on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
+ _on(ownerDocument, 'touchmove', _this._disableDelayedDrag);
+ options.supportPointer && _on(ownerDocument, 'pointermove', _this._disableDelayedDrag);
+
+ _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
+ } else {
+ dragStartFn();
+ }
+
+
+ }
+ },
+
+ _disableDelayedDrag: function () {
+ var ownerDocument = this.el.ownerDocument;
+
+ clearTimeout(this._dragStartTimer);
+ _off(ownerDocument, 'mouseup', this._disableDelayedDrag);
+ _off(ownerDocument, 'touchend', this._disableDelayedDrag);
+ _off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
+ _off(ownerDocument, 'mousemove', this._disableDelayedDrag);
+ _off(ownerDocument, 'touchmove', this._disableDelayedDrag);
+ _off(ownerDocument, 'pointermove', this._disableDelayedDrag);
+ },
+
+ _triggerDragStart: function (/** Event */evt, /** Touch */touch) {
+ touch = touch || (evt.pointerType == 'touch' ? evt : null);
+
+ if (touch) {
+ // Touch device support
+ tapEvt = {
+ target: dragEl,
+ clientX: touch.clientX,
+ clientY: touch.clientY
+ };
+
+ this._onDragStart(tapEvt, 'touch');
+ }
+ else if (!this.nativeDraggable) {
+ this._onDragStart(tapEvt, true);
+ }
+ else {
+ _on(dragEl, 'dragend', this);
+ _on(rootEl, 'dragstart', this._onDragStart);
+ }
+
+ try {
+ if (document.selection) {
+ // Timeout neccessary for IE9
+ _nextTick(function () {
+ document.selection.empty();
+ });
+ } else {
+ window.getSelection().removeAllRanges();
+ }
+ } catch (err) {
+ }
+ },
+
+ _dragStarted: function () {
+ if (rootEl && dragEl) {
+ var options = this.options;
+
+ // Apply effect
+ _toggleClass(dragEl, options.ghostClass, true);
+ _toggleClass(dragEl, options.dragClass, false);
+
+ Sortable.active = this;
+
+ // Drag start event
+ _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex);
+ } else {
+ this._nulling();
+ }
+ },
+
+ _emulateDragOver: function () {
+ if (touchEvt) {
+ if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
+ return;
+ }
+
+ this._lastX = touchEvt.clientX;
+ this._lastY = touchEvt.clientY;
+
+ if (!supportCssPointerEvents) {
+ _css(ghostEl, 'display', 'none');
+ }
+
+ var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
+ var parent = target;
+ var i = touchDragOverListeners.length;
+
+ if (target && target.shadowRoot) {
+ target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
+ parent = target;
+ }
+
+ if (parent) {
+ do {
+ if (parent[expando]) {
+ while (i--) {
+ touchDragOverListeners[i]({
+ clientX: touchEvt.clientX,
+ clientY: touchEvt.clientY,
+ target: target,
+ rootEl: parent
+ });
+ }
+
+ break;
+ }
+
+ target = parent; // store last element
+ }
+ /* jshint boss:true */
+ while (parent = parent.parentNode);
+ }
+
+ if (!supportCssPointerEvents) {
+ _css(ghostEl, 'display', '');
+ }
+ }
+ },
+
+
+ _onTouchMove: function (/**TouchEvent*/evt) {
+ if (tapEvt) {
+ var options = this.options,
+ fallbackTolerance = options.fallbackTolerance,
+ fallbackOffset = options.fallbackOffset,
+ touch = evt.touches ? evt.touches[0] : evt,
+ dx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x,
+ dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y,
+ translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
+
+ // only set the status to dragging, when we are actually dragging
+ if (!Sortable.active) {
+ if (fallbackTolerance &&
+ min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance
+ ) {
+ return;
+ }
+
+ this._dragStarted();
+ }
+
+ // as well as creating the ghost element on the document body
+ this._appendGhost();
+
+ moved = true;
+ touchEvt = touch;
+
+ _css(ghostEl, 'webkitTransform', translate3d);
+ _css(ghostEl, 'mozTransform', translate3d);
+ _css(ghostEl, 'msTransform', translate3d);
+ _css(ghostEl, 'transform', translate3d);
+
+ evt.preventDefault();
+ }
+ },
+
+ _appendGhost: function () {
+ if (!ghostEl) {
+ var rect = dragEl.getBoundingClientRect(),
+ css = _css(dragEl),
+ options = this.options,
+ ghostRect;
+
+ ghostEl = dragEl.cloneNode(true);
+
+ _toggleClass(ghostEl, options.ghostClass, false);
+ _toggleClass(ghostEl, options.fallbackClass, true);
+ _toggleClass(ghostEl, options.dragClass, true);
+
+ _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
+ _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
+ _css(ghostEl, 'width', rect.width);
+ _css(ghostEl, 'height', rect.height);
+ _css(ghostEl, 'opacity', '0.8');
+ _css(ghostEl, 'position', 'fixed');
+ _css(ghostEl, 'zIndex', '100000');
+ _css(ghostEl, 'pointerEvents', 'none');
+
+ options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);
+
+ // Fixing dimensions.
+ ghostRect = ghostEl.getBoundingClientRect();
+ _css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
+ _css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
+ }
+ },
+
+ _onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
+ var _this = this;
+ var dataTransfer = evt.dataTransfer;
+ var options = _this.options;
+
+ _this._offUpEvents();
+
+ if (activeGroup.checkPull(_this, _this, dragEl, evt)) {
+ cloneEl = _clone(dragEl);
+
+ cloneEl.draggable = false;
+ cloneEl.style['will-change'] = '';
+
+ _css(cloneEl, 'display', 'none');
+ _toggleClass(cloneEl, _this.options.chosenClass, false);
+
+ // #1143: IFrame support workaround
+ _this._cloneId = _nextTick(function () {
+ rootEl.insertBefore(cloneEl, dragEl);
+ _dispatchEvent(_this, rootEl, 'clone', dragEl);
+ });
+ }
+
+ _toggleClass(dragEl, options.dragClass, true);
+
+ if (useFallback) {
+ if (useFallback === 'touch') {
+ // Bind touch events
+ _on(document, 'touchmove', _this._onTouchMove);
+ _on(document, 'touchend', _this._onDrop);
+ _on(document, 'touchcancel', _this._onDrop);
+
+ if (options.supportPointer) {
+ _on(document, 'pointermove', _this._onTouchMove);
+ _on(document, 'pointerup', _this._onDrop);
+ }
+ } else {
+ // Old brwoser
+ _on(document, 'mousemove', _this._onTouchMove);
+ _on(document, 'mouseup', _this._onDrop);
+ }
+
+ _this._loopId = setInterval(_this._emulateDragOver, 50);
+ }
+ else {
+ if (dataTransfer) {
+ dataTransfer.effectAllowed = 'move';
+ options.setData && options.setData.call(_this, dataTransfer, dragEl);
+ }
+
+ _on(document, 'drop', _this);
+
+ // #1143: Бывает элемент с IFrame внутри блокирует `drop`,
+ // поэтому если вызвался `mouseover`, значит надо отменять весь d'n'd.
+ // Breaking Chrome 62+
+ // _on(document, 'mouseover', _this);
+
+ _this._dragStartId = _nextTick(_this._dragStarted);
+ }
+ },
+
+ _onDragOver: function (/**Event*/evt) {
+ var el = this.el,
+ target,
+ dragRect,
+ targetRect,
+ revert,
+ options = this.options,
+ group = options.group,
+ activeSortable = Sortable.active,
+ isOwner = (activeGroup === group),
+ isMovingBetweenSortable = false,
+ canSort = options.sort;
+
+ if (evt.preventDefault !== void 0) {
+ evt.preventDefault();
+ !options.dragoverBubble && evt.stopPropagation();
+ }
+
+ if (dragEl.animated) {
+ return;
+ }
+
+ moved = true;
+
+ if (activeSortable && !options.disabled &&
+ (isOwner
+ ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
+ : (
+ putSortable === this ||
+ (
+ (activeSortable.lastPullMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) &&
+ group.checkPut(this, activeSortable, dragEl, evt)
+ )
+ )
+ ) &&
+ (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
+ ) {
+ // Smart auto-scrolling
+ _autoScroll(evt, options, this.el);
+
+ if (_silent) {
+ return;
+ }
+
+ target = _closest(evt.target, options.draggable, el);
+ dragRect = dragEl.getBoundingClientRect();
+
+ if (putSortable !== this) {
+ putSortable = this;
+ isMovingBetweenSortable = true;
+ }
+
+ if (revert) {
+ _cloneHide(activeSortable, true);
+ parentEl = rootEl; // actualization
+
+ if (cloneEl || nextEl) {
+ rootEl.insertBefore(dragEl, cloneEl || nextEl);
+ }
+ else if (!canSort) {
+ rootEl.appendChild(dragEl);
+ }
+
+ return;
+ }
+
+
+ if ((el.children.length === 0) || (el.children[0] === ghostEl) ||
+ (el === evt.target) && (_ghostIsLast(el, evt))
+ ) {
+ //assign target only if condition is true
+ if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) {
+ target = el.lastElementChild;
+ }
+
+ if (target) {
+ if (target.animated) {
+ return;
+ }
+
+ targetRect = target.getBoundingClientRect();
+ }
+
+ _cloneHide(activeSortable, isOwner);
+
+ if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
+ if (!dragEl.contains(el)) {
+ el.appendChild(dragEl);
+ parentEl = el; // actualization
+ }
+
+ this._animate(dragRect, dragEl);
+ target && this._animate(targetRect, target);
+ }
+ }
+ else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {
+ if (lastEl !== target) {
+ lastEl = target;
+ lastCSS = _css(target);
+ lastParentCSS = _css(target.parentNode);
+ }
+
+ targetRect = target.getBoundingClientRect();
+
+ var width = targetRect.right - targetRect.left,
+ height = targetRect.bottom - targetRect.top,
+ floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display)
+ || (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),
+ isWide = (target.offsetWidth > dragEl.offsetWidth),
+ isLong = (target.offsetHeight > dragEl.offsetHeight),
+ halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,
+ nextSibling = target.nextElementSibling,
+ after = false
+ ;
+
+ if (floating) {
+ var elTop = dragEl.offsetTop,
+ tgTop = target.offsetTop;
+
+ if (elTop === tgTop) {
+ after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;
+ }
+ else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) {
+ after = (evt.clientY - targetRect.top) / height > 0.5;
+ } else {
+ after = tgTop > elTop;
+ }
+ } else if (!isMovingBetweenSortable) {
+ after = (nextSibling !== dragEl) && !isLong || halfway && isLong;
+ }
+
+ var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
+
+ if (moveVector !== false) {
+ if (moveVector === 1 || moveVector === -1) {
+ after = (moveVector === 1);
+ }
+
+ _silent = true;
+ setTimeout(_unsilent, 30);
+
+ _cloneHide(activeSortable, isOwner);
+
+ if (!dragEl.contains(el)) {
+ if (after && !nextSibling) {
+ el.appendChild(dragEl);
+ } else {
+ target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
+ }
+ }
+
+ parentEl = dragEl.parentNode; // actualization
+
+ this._animate(dragRect, dragEl);
+ this._animate(targetRect, target);
+ }
+ }
+ }
+ },
+
+ _animate: function (prevRect, target) {
+ var ms = this.options.animation;
+
+ if (ms) {
+ var currentRect = target.getBoundingClientRect();
+
+ if (prevRect.nodeType === 1) {
+ prevRect = prevRect.getBoundingClientRect();
+ }
+
+ _css(target, 'transition', 'none');
+ _css(target, 'transform', 'translate3d('
+ + (prevRect.left - currentRect.left) + 'px,'
+ + (prevRect.top - currentRect.top) + 'px,0)'
+ );
+
+ target.offsetWidth; // repaint
+
+ _css(target, 'transition', 'all ' + ms + 'ms');
+ _css(target, 'transform', 'translate3d(0,0,0)');
+
+ clearTimeout(target.animated);
+ target.animated = setTimeout(function () {
+ _css(target, 'transition', '');
+ _css(target, 'transform', '');
+ target.animated = false;
+ }, ms);
+ }
+ },
+
+ _offUpEvents: function () {
+ var ownerDocument = this.el.ownerDocument;
+
+ _off(document, 'touchmove', this._onTouchMove);
+ _off(document, 'pointermove', this._onTouchMove);
+ _off(ownerDocument, 'mouseup', this._onDrop);
+ _off(ownerDocument, 'touchend', this._onDrop);
+ _off(ownerDocument, 'pointerup', this._onDrop);
+ _off(ownerDocument, 'touchcancel', this._onDrop);
+ _off(ownerDocument, 'pointercancel', this._onDrop);
+ _off(ownerDocument, 'selectstart', this);
+ },
+
+ _onDrop: function (/**Event*/evt) {
+ var el = this.el,
+ options = this.options;
+
+ clearInterval(this._loopId);
+ clearInterval(autoScroll.pid);
+ clearTimeout(this._dragStartTimer);
+
+ _cancelNextTick(this._cloneId);
+ _cancelNextTick(this._dragStartId);
+
+ // Unbind events
+ _off(document, 'mouseover', this);
+ _off(document, 'mousemove', this._onTouchMove);
+
+ if (this.nativeDraggable) {
+ _off(document, 'drop', this);
+ _off(el, 'dragstart', this._onDragStart);
+ }
+
+ this._offUpEvents();
+
+ if (evt) {
+ if (moved) {
+ evt.preventDefault();
+ !options.dropBubble && evt.stopPropagation();
+ }
+
+ ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
+
+ if (rootEl === parentEl || Sortable.active.lastPullMode !== 'clone') {
+ // Remove clone
+ cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
+ }
+
+ if (dragEl) {
+ if (this.nativeDraggable) {
+ _off(dragEl, 'dragend', this);
+ }
+
+ _disableDraggable(dragEl);
+ dragEl.style['will-change'] = '';
+
+ // Remove class's
+ _toggleClass(dragEl, this.options.ghostClass, false);
+ _toggleClass(dragEl, this.options.chosenClass, false);
+
+ // Drag stop event
+ _dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex);
+
+ if (rootEl !== parentEl) {
+ newIndex = _index(dragEl, options.draggable);
+
+ if (newIndex >= 0) {
+ // Add event
+ _dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex);
+
+ // Remove event
+ _dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex);
+
+ // drag from one list and drop into another
+ _dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
+ _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
+ }
+ }
+ else {
+ if (dragEl.nextSibling !== nextEl) {
+ // Get the index of the dragged element within its parent
+ newIndex = _index(dragEl, options.draggable);
+
+ if (newIndex >= 0) {
+ // drag & drop within the same list
+ _dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex);
+ _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
+ }
+ }
+ }
+
+ if (Sortable.active) {
+ /* jshint eqnull:true */
+ if (newIndex == null || newIndex === -1) {
+ newIndex = oldIndex;
+ }
+
+ _dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex);
+
+ // Save sorting
+ this.save();
+ }
+ }
+
+ }
+
+ this._nulling();
+ },
+
+ _nulling: function() {
+ rootEl =
+ dragEl =
+ parentEl =
+ ghostEl =
+ nextEl =
+ cloneEl =
+ lastDownEl =
+
+ scrollEl =
+ scrollParentEl =
+
+ tapEvt =
+ touchEvt =
+
+ moved =
+ newIndex =
+
+ lastEl =
+ lastCSS =
+
+ putSortable =
+ activeGroup =
+ Sortable.active = null;
+
+ savedInputChecked.forEach(function (el) {
+ el.checked = true;
+ });
+ savedInputChecked.length = 0;
+ },
+
+ handleEvent: function (/**Event*/evt) {
+ switch (evt.type) {
+ case 'drop':
+ case 'dragend':
+ this._onDrop(evt);
+ break;
+
+ case 'dragover':
+ case 'dragenter':
+ if (dragEl) {
+ this._onDragOver(evt);
+ _globalDragOver(evt);
+ }
+ break;
+
+ case 'mouseover':
+ this._onDrop(evt);
+ break;
+
+ case 'selectstart':
+ evt.preventDefault();
+ break;
+ }
+ },
+
+
+ /**
+ * Serializes the item into an array of string.
+ * @returns {String[]}
+ */
+ toArray: function () {
+ var order = [],
+ el,
+ children = this.el.children,
+ i = 0,
+ n = children.length,
+ options = this.options;
+
+ for (; i < n; i++) {
+ el = children[i];
+ if (_closest(el, options.draggable, this.el)) {
+ order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
+ }
+ }
+
+ return order;
+ },
+
+
+ /**
+ * Sorts the elements according to the array.
+ * @param {String[]} order order of the items
+ */
+ sort: function (order) {
+ var items = {}, rootEl = this.el;
+
+ this.toArray().forEach(function (id, i) {
+ var el = rootEl.children[i];
+
+ if (_closest(el, this.options.draggable, rootEl)) {
+ items[id] = el;
+ }
+ }, this);
+
+ order.forEach(function (id) {
+ if (items[id]) {
+ rootEl.removeChild(items[id]);
+ rootEl.appendChild(items[id]);
+ }
+ });
+ },
+
+
+ /**
+ * Save the current sorting
+ */
+ save: function () {
+ var store = this.options.store;
+ store && store.set(this);
+ },
+
+
+ /**
+ * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
+ * @param {HTMLElement} el
+ * @param {String} [selector] default: `options.draggable`
+ * @returns {HTMLElement|null}
+ */
+ closest: function (el, selector) {
+ return _closest(el, selector || this.options.draggable, this.el);
+ },
+
+
+ /**
+ * Set/get option
+ * @param {string} name
+ * @param {*} [value]
+ * @returns {*}
+ */
+ option: function (name, value) {
+ var options = this.options;
+
+ if (value === void 0) {
+ return options[name];
+ } else {
+ options[name] = value;
+
+ if (name === 'group') {
+ _prepareGroup(options);
+ }
+ }
+ },
+
+
+ /**
+ * Destroy
+ */
+ destroy: function () {
+ var el = this.el;
+
+ el[expando] = null;
+
+ _off(el, 'mousedown', this._onTapStart);
+ _off(el, 'touchstart', this._onTapStart);
+ _off(el, 'pointerdown', this._onTapStart);
+
+ if (this.nativeDraggable) {
+ _off(el, 'dragover', this);
+ _off(el, 'dragenter', this);
+ }
+
+ // Remove draggable attributes
+ Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
+ el.removeAttribute('draggable');
+ });
+
+ touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
+
+ this._onDrop();
+
+ this.el = el = null;
+ }
+ };
+
+
+ function _cloneHide(sortable, state) {
+ if (sortable.lastPullMode !== 'clone') {
+ state = true;
+ }
+
+ if (cloneEl && (cloneEl.state !== state)) {
+ _css(cloneEl, 'display', state ? 'none' : '');
+
+ if (!state) {
+ if (cloneEl.state) {
+ if (sortable.options.group.revertClone) {
+ rootEl.insertBefore(cloneEl, nextEl);
+ sortable._animate(dragEl, cloneEl);
+ } else {
+ rootEl.insertBefore(cloneEl, dragEl);
+ }
+ }
+ }
+
+ cloneEl.state = state;
+ }
+ }
+
+
+ function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
+ if (el) {
+ ctx = ctx || document;
+
+ do {
+ if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) {
+ return el;
+ }
+ /* jshint boss:true */
+ } while (el = _getParentOrHost(el));
+ }
+
+ return null;
+ }
+
+
+ function _getParentOrHost(el) {
+ var parent = el.host;
+
+ return (parent && parent.nodeType) ? parent : el.parentNode;
+ }
+
+
+ function _globalDragOver(/**Event*/evt) {
+ if (evt.dataTransfer) {
+ evt.dataTransfer.dropEffect = 'move';
+ }
+ evt.preventDefault();
+ }
+
+
+ function _on(el, event, fn) {
+ el.addEventListener(event, fn, captureMode);
+ }
+
+
+ function _off(el, event, fn) {
+ el.removeEventListener(event, fn, captureMode);
+ }
+
+
+ function _toggleClass(el, name, state) {
+ if (el) {
+ if (el.classList) {
+ el.classList[state ? 'add' : 'remove'](name);
+ }
+ else {
+ var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
+ el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
+ }
+ }
+ }
+
+
+ function _css(el, prop, val) {
+ var style = el && el.style;
+
+ if (style) {
+ if (val === void 0) {
+ if (document.defaultView && document.defaultView.getComputedStyle) {
+ val = document.defaultView.getComputedStyle(el, '');
+ }
+ else if (el.currentStyle) {
+ val = el.currentStyle;
+ }
+
+ return prop === void 0 ? val : val[prop];
+ }
+ else {
+ if (!(prop in style)) {
+ prop = '-webkit-' + prop;
+ }
+
+ style[prop] = val + (typeof val === 'string' ? '' : 'px');
+ }
+ }
+ }
+
+
+ function _find(ctx, tagName, iterator) {
+ if (ctx) {
+ var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
+
+ if (iterator) {
+ for (; i < n; i++) {
+ iterator(list[i], i);
+ }
+ }
+
+ return list;
+ }
+
+ return [];
+ }
+
+
+
+ function _dispatchEvent(sortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex) {
+ sortable = (sortable || rootEl[expando]);
+
+ var evt = document.createEvent('Event'),
+ options = sortable.options,
+ onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
+
+ evt.initEvent(name, true, true);
+
+ evt.to = toEl || rootEl;
+ evt.from = fromEl || rootEl;
+ evt.item = targetEl || rootEl;
+ evt.clone = cloneEl;
+
+ evt.oldIndex = startIndex;
+ evt.newIndex = newIndex;
+
+ rootEl.dispatchEvent(evt);
+
+ if (options[onName]) {
+ options[onName].call(sortable, evt);
+ }
+ }
+
+
+ function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) {
+ var evt,
+ sortable = fromEl[expando],
+ onMoveFn = sortable.options.onMove,
+ retVal;
+
+ evt = document.createEvent('Event');
+ evt.initEvent('move', true, true);
+
+ evt.to = toEl;
+ evt.from = fromEl;
+ evt.dragged = dragEl;
+ evt.draggedRect = dragRect;
+ evt.related = targetEl || toEl;
+ evt.relatedRect = targetRect || toEl.getBoundingClientRect();
+ evt.willInsertAfter = willInsertAfter;
+
+ fromEl.dispatchEvent(evt);
+
+ if (onMoveFn) {
+ retVal = onMoveFn.call(sortable, evt, originalEvt);
+ }
+
+ return retVal;
+ }
+
+
+ function _disableDraggable(el) {
+ el.draggable = false;
+ }
+
+
+ function _unsilent() {
+ _silent = false;
+ }
+
+
+ /** @returns {HTMLElement|false} */
+ function _ghostIsLast(el, evt) {
+ var lastEl = el.lastElementChild,
+ rect = lastEl.getBoundingClientRect();
+
+ // 5 — min delta
+ // abs — нельзя добавлять, а то глюки при наведении сверху
+ return (evt.clientY - (rect.top + rect.height) > 5) ||
+ (evt.clientX - (rect.left + rect.width) > 5);
+ }
+
+
+ /**
+ * Generate id
+ * @param {HTMLElement} el
+ * @returns {String}
+ * @private
+ */
+ function _generateId(el) {
+ var str = el.tagName + el.className + el.src + el.href + el.textContent,
+ i = str.length,
+ sum = 0;
+
+ while (i--) {
+ sum += str.charCodeAt(i);
+ }
+
+ return sum.toString(36);
+ }
+
+ /**
+ * Returns the index of an element within its parent for a selected set of
+ * elements
+ * @param {HTMLElement} el
+ * @param {selector} selector
+ * @return {number}
+ */
+ function _index(el, selector) {
+ var index = 0;
+
+ if (!el || !el.parentNode) {
+ return -1;
+ }
+
+ while (el && (el = el.previousElementSibling)) {
+ if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) {
+ index++;
+ }
+ }
+
+ return index;
+ }
+
+ function _matches(/**HTMLElement*/el, /**String*/selector) {
+ if (el) {
+ selector = selector.split('.');
+
+ var tag = selector.shift().toUpperCase(),
+ re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');
+
+ return (
+ (tag === '' || el.nodeName.toUpperCase() == tag) &&
+ (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
+ );
+ }
+
+ return false;
+ }
+
+ function _throttle(callback, ms) {
+ var args, _this;
+
+ return function () {
+ if (args === void 0) {
+ args = arguments;
+ _this = this;
+
+ setTimeout(function () {
+ if (args.length === 1) {
+ callback.call(_this, args[0]);
+ } else {
+ callback.apply(_this, args);
+ }
+
+ args = void 0;
+ }, ms);
+ }
+ };
+ }
+
+ function _extend(dst, src) {
+ if (dst && src) {
+ for (var key in src) {
+ if (src.hasOwnProperty(key)) {
+ dst[key] = src[key];
+ }
+ }
+ }
+
+ return dst;
+ }
+
+ function _clone(el) {
+ if (Polymer && Polymer.dom) {
+ return Polymer.dom(el).cloneNode(true);
+ }
+ else if ($) {
+ return $(el).clone(true)[0];
+ }
+ else {
+ return el.cloneNode(true);
+ }
+ }
+
+ function _saveInputCheckedState(root) {
+ var inputs = root.getElementsByTagName('input');
+ var idx = inputs.length;
+
+ while (idx--) {
+ var el = inputs[idx];
+ el.checked && savedInputChecked.push(el);
+ }
+ }
+
+ function _nextTick(fn) {
+ return setTimeout(fn, 0);
+ }
+
+ function _cancelNextTick(id) {
+ return clearTimeout(id);
+ }
+
+ // Fixed #973:
+ _on(document, 'touchmove', function (evt) {
+ if (Sortable.active) {
+ evt.preventDefault();
+ }
+ });
+
+ // Export utils
+ Sortable.utils = {
+ on: _on,
+ off: _off,
+ css: _css,
+ find: _find,
+ is: function (el, selector) {
+ return !!_closest(el, selector, el);
+ },
+ extend: _extend,
+ throttle: _throttle,
+ closest: _closest,
+ toggleClass: _toggleClass,
+ clone: _clone,
+ index: _index,
+ nextTick: _nextTick,
+ cancelNextTick: _cancelNextTick
+ };
+
+
+ /**
+ * Create sortable instance
+ * @param {HTMLElement} el
+ * @param {Object} [options]
+ */
+ Sortable.create = function (el, options) {
+ return new Sortable(el, options);
+ };
+
+
+ // Export
+ Sortable.version = '1.7.0';
+ return Sortable;
+});
+
+
+/***/ }),
+/* 133 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function($) {var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;var require;var require;/*!
+ * Select2 4.0.6-rc.1
+ * https://select2.github.io
+ *
+ * Released under the MIT license
+ * https://github.com/select2/select2/blob/master/LICENSE.md
+ */
+;(function (factory) {
+ if (true) {
+ // AMD. Register as an anonymous module.
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
+ __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
+ (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (typeof module === 'object' && module.exports) {
+ // Node/CommonJS
+ module.exports = function (root, jQuery) {
+ if (jQuery === undefined) {
+ // require('jQuery') returns a factory that requires window to
+ // build a jQuery instance, we normalize how we use modules
+ // that require this pattern but the window provided is a noop
+ // if it's defined (how jquery works)
+ if (typeof window !== 'undefined') {
+ jQuery = require('jquery');
+ }
+ else {
+ jQuery = require('jquery')(root);
+ }
+ }
+ factory(jQuery);
+ return jQuery;
+ };
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+} (function (jQuery) {
+ // This is needed so we can catch the AMD loader configuration and use it
+ // The inner file should be wrapped (by `banner.start.js`) in a function that
+ // returns the AMD loader references.
+ var S2 =(function () {
+ // Restore the Select2 AMD loader so it can be used
+ // Needed mostly in the language files, where the loader is not inserted
+ if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
+ var S2 = jQuery.fn.select2.amd;
+ }
+var S2;(function () { if (!S2 || !S2.requirejs) {
+if (!S2) { S2 = {}; } else { require = S2; }
+/**
+ * @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
+ * Released under MIT license, http://github.com/requirejs/almond/LICENSE
+ */
+//Going sloppy to avoid 'use strict' string cost, but strict practices should
+//be followed.
+/*global setTimeout: false */
+
+var requirejs, require, define;
+(function (undef) {
+ var main, req, makeMap, handlers,
+ defined = {},
+ waiting = {},
+ config = {},
+ defining = {},
+ hasOwn = Object.prototype.hasOwnProperty,
+ aps = [].slice,
+ jsSuffixRegExp = /\.js$/;
+
+ function hasProp(obj, prop) {
+ return hasOwn.call(obj, prop);
+ }
+
+ /**
+ * Given a relative module name, like ./something, normalize it to
+ * a real name that can be mapped to a path.
+ * @param {String} name the relative name
+ * @param {String} baseName a real name that the name arg is relative
+ * to.
+ * @returns {String} normalized name
+ */
+ function normalize(name, baseName) {
+ var nameParts, nameSegment, mapValue, foundMap, lastIndex,
+ foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
+ baseParts = baseName && baseName.split("/"),
+ map = config.map,
+ starMap = (map && map['*']) || {};
+
+ //Adjust any relative paths.
+ if (name) {
+ name = name.split('/');
+ lastIndex = name.length - 1;
+
+ // If wanting node ID compatibility, strip .js from end
+ // of IDs. Have to do this here, and not in nameToUrl
+ // because node allows either .js or non .js to map
+ // to same file.
+ if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
+ name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
+ }
+
+ // Starts with a '.' so need the baseName
+ if (name[0].charAt(0) === '.' && baseParts) {
+ //Convert baseName to array, and lop off the last part,
+ //so that . matches that 'directory' and not name of the baseName's
+ //module. For instance, baseName of 'one/two/three', maps to
+ //'one/two/three.js', but we want the directory, 'one/two' for
+ //this normalization.
+ normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
+ name = normalizedBaseParts.concat(name);
+ }
+
+ //start trimDots
+ for (i = 0; i < name.length; i++) {
+ part = name[i];
+ if (part === '.') {
+ name.splice(i, 1);
+ i -= 1;
+ } else if (part === '..') {
+ // If at the start, or previous value is still ..,
+ // keep them so that when converted to a path it may
+ // still work when converted to a path, even though
+ // as an ID it is less than ideal. In larger point
+ // releases, may be better to just kick out an error.
+ if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
+ continue;
+ } else if (i > 0) {
+ name.splice(i - 1, 2);
+ i -= 2;
+ }
+ }
+ }
+ //end trimDots
+
+ name = name.join('/');
+ }
+
+ //Apply map config if available.
+ if ((baseParts || starMap) && map) {
+ nameParts = name.split('/');
+
+ for (i = nameParts.length; i > 0; i -= 1) {
+ nameSegment = nameParts.slice(0, i).join("/");
+
+ if (baseParts) {
+ //Find the longest baseName segment match in the config.
+ //So, do joins on the biggest to smallest lengths of baseParts.
+ for (j = baseParts.length; j > 0; j -= 1) {
+ mapValue = map[baseParts.slice(0, j).join('/')];
+
+ //baseName segment has config, find if it has one for
+ //this name.
+ if (mapValue) {
+ mapValue = mapValue[nameSegment];
+ if (mapValue) {
+ //Match, update name to the new value.
+ foundMap = mapValue;
+ foundI = i;
+ break;
+ }
+ }
+ }
+ }
+
+ if (foundMap) {
+ break;
+ }
+
+ //Check for a star map match, but just hold on to it,
+ //if there is a shorter segment match later in a matching
+ //config, then favor over this star map.
+ if (!foundStarMap && starMap && starMap[nameSegment]) {
+ foundStarMap = starMap[nameSegment];
+ starI = i;
+ }
+ }
+
+ if (!foundMap && foundStarMap) {
+ foundMap = foundStarMap;
+ foundI = starI;
+ }
+
+ if (foundMap) {
+ nameParts.splice(0, foundI, foundMap);
+ name = nameParts.join('/');
+ }
+ }
+
+ return name;
+ }
+
+ function makeRequire(relName, forceSync) {
+ return function () {
+ //A version of a require function that passes a moduleName
+ //value for items that may need to
+ //look up paths relative to the moduleName
+ var args = aps.call(arguments, 0);
+
+ //If first arg is not require('string'), and there is only
+ //one arg, it is the array form without a callback. Insert
+ //a null so that the following concat is correct.
+ if (typeof args[0] !== 'string' && args.length === 1) {
+ args.push(null);
+ }
+ return req.apply(undef, args.concat([relName, forceSync]));
+ };
+ }
+
+ function makeNormalize(relName) {
+ return function (name) {
+ return normalize(name, relName);
+ };
+ }
+
+ function makeLoad(depName) {
+ return function (value) {
+ defined[depName] = value;
+ };
+ }
+
+ function callDep(name) {
+ if (hasProp(waiting, name)) {
+ var args = waiting[name];
+ delete waiting[name];
+ defining[name] = true;
+ main.apply(undef, args);
+ }
+
+ if (!hasProp(defined, name) && !hasProp(defining, name)) {
+ throw new Error('No ' + name);
+ }
+ return defined[name];
+ }
+
+ //Turns a plugin!resource to [plugin, resource]
+ //with the plugin being undefined if the name
+ //did not have a plugin prefix.
+ function splitPrefix(name) {
+ var prefix,
+ index = name ? name.indexOf('!') : -1;
+ if (index > -1) {
+ prefix = name.substring(0, index);
+ name = name.substring(index + 1, name.length);
+ }
+ return [prefix, name];
+ }
+
+ //Creates a parts array for a relName where first part is plugin ID,
+ //second part is resource ID. Assumes relName has already been normalized.
+ function makeRelParts(relName) {
+ return relName ? splitPrefix(relName) : [];
+ }
+
+ /**
+ * Makes a name map, normalizing the name, and using a plugin
+ * for normalization if necessary. Grabs a ref to plugin
+ * too, as an optimization.
+ */
+ makeMap = function (name, relParts) {
+ var plugin,
+ parts = splitPrefix(name),
+ prefix = parts[0],
+ relResourceName = relParts[1];
+
+ name = parts[1];
+
+ if (prefix) {
+ prefix = normalize(prefix, relResourceName);
+ plugin = callDep(prefix);
+ }
+
+ //Normalize according
+ if (prefix) {
+ if (plugin && plugin.normalize) {
+ name = plugin.normalize(name, makeNormalize(relResourceName));
+ } else {
+ name = normalize(name, relResourceName);
+ }
+ } else {
+ name = normalize(name, relResourceName);
+ parts = splitPrefix(name);
+ prefix = parts[0];
+ name = parts[1];
+ if (prefix) {
+ plugin = callDep(prefix);
+ }
+ }
+
+ //Using ridiculous property names for space reasons
+ return {
+ f: prefix ? prefix + '!' + name : name, //fullName
+ n: name,
+ pr: prefix,
+ p: plugin
+ };
+ };
+
+ function makeConfig(name) {
+ return function () {
+ return (config && config.config && config.config[name]) || {};
+ };
+ }
+
+ handlers = {
+ require: function (name) {
+ return makeRequire(name);
+ },
+ exports: function (name) {
+ var e = defined[name];
+ if (typeof e !== 'undefined') {
+ return e;
+ } else {
+ return (defined[name] = {});
+ }
+ },
+ module: function (name) {
+ return {
+ id: name,
+ uri: '',
+ exports: defined[name],
+ config: makeConfig(name)
+ };
+ }
+ };
+
+ main = function (name, deps, callback, relName) {
+ var cjsModule, depName, ret, map, i, relParts,
+ args = [],
+ callbackType = typeof callback,
+ usingExports;
+
+ //Use name if no relName
+ relName = relName || name;
+ relParts = makeRelParts(relName);
+
+ //Call the callback to define the module, if necessary.
+ if (callbackType === 'undefined' || callbackType === 'function') {
+ //Pull out the defined dependencies and pass the ordered
+ //values to the callback.
+ //Default to [require, exports, module] if no deps
+ deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
+ for (i = 0; i < deps.length; i += 1) {
+ map = makeMap(deps[i], relParts);
+ depName = map.f;
+
+ //Fast path CommonJS standard dependencies.
+ if (depName === "require") {
+ args[i] = handlers.require(name);
+ } else if (depName === "exports") {
+ //CommonJS module spec 1.1
+ args[i] = handlers.exports(name);
+ usingExports = true;
+ } else if (depName === "module") {
+ //CommonJS module spec 1.1
+ cjsModule = args[i] = handlers.module(name);
+ } else if (hasProp(defined, depName) ||
+ hasProp(waiting, depName) ||
+ hasProp(defining, depName)) {
+ args[i] = callDep(depName);
+ } else if (map.p) {
+ map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
+ args[i] = defined[depName];
+ } else {
+ throw new Error(name + ' missing ' + depName);
+ }
+ }
+
+ ret = callback ? callback.apply(defined[name], args) : undefined;
+
+ if (name) {
+ //If setting exports via "module" is in play,
+ //favor that over return value and exports. After that,
+ //favor a non-undefined return value over exports use.
+ if (cjsModule && cjsModule.exports !== undef &&
+ cjsModule.exports !== defined[name]) {
+ defined[name] = cjsModule.exports;
+ } else if (ret !== undef || !usingExports) {
+ //Use the return value from the function.
+ defined[name] = ret;
+ }
+ }
+ } else if (name) {
+ //May just be an object definition for the module. Only
+ //worry about defining if have a module name.
+ defined[name] = callback;
+ }
+ };
+
+ requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
+ if (typeof deps === "string") {
+ if (handlers[deps]) {
+ //callback in this case is really relName
+ return handlers[deps](callback);
+ }
+ //Just return the module wanted. In this scenario, the
+ //deps arg is the module name, and second arg (if passed)
+ //is just the relName.
+ //Normalize module name, if it contains . or ..
+ return callDep(makeMap(deps, makeRelParts(callback)).f);
+ } else if (!deps.splice) {
+ //deps is a config object, not an array.
+ config = deps;
+ if (config.deps) {
+ req(config.deps, config.callback);
+ }
+ if (!callback) {
+ return;
+ }
+
+ if (callback.splice) {
+ //callback is an array, which means it is a dependency list.
+ //Adjust args if there are dependencies
+ deps = callback;
+ callback = relName;
+ relName = null;
+ } else {
+ deps = undef;
+ }
+ }
+
+ //Support require(['a'])
+ callback = callback || function () {};
+
+ //If relName is a function, it is an errback handler,
+ //so remove it.
+ if (typeof relName === 'function') {
+ relName = forceSync;
+ forceSync = alt;
+ }
+
+ //Simulate async callback;
+ if (forceSync) {
+ main(undef, deps, callback, relName);
+ } else {
+ //Using a non-zero value because of concern for what old browsers
+ //do, and latest browsers "upgrade" to 4 if lower value is used:
+ //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
+ //If want a value immediately, use require('id') instead -- something
+ //that works in almond on the global level, but not guaranteed and
+ //unlikely to work in other AMD implementations.
+ setTimeout(function () {
+ main(undef, deps, callback, relName);
+ }, 4);
+ }
+
+ return req;
+ };
+
+ /**
+ * Just drops the config on the floor, but returns req in case
+ * the config return value is used.
+ */
+ req.config = function (cfg) {
+ return req(cfg);
+ };
+
+ /**
+ * Expose module registry for debugging and tooling
+ */
+ requirejs._defined = defined;
+
+ define = function (name, deps, callback) {
+ if (typeof name !== 'string') {
+ throw new Error('See almond README: incorrect module build, no module name');
+ }
+
+ //This module may not have dependencies
+ if (!deps.splice) {
+ //deps is not an array, so probably means
+ //an object literal or factory function for
+ //the value. Adjust args.
+ callback = deps;
+ deps = [];
+ }
+
+ if (!hasProp(defined, name) && !hasProp(waiting, name)) {
+ waiting[name] = [name, deps, callback];
+ }
+ };
+
+ define.amd = {
+ jQuery: true
+ };
+}());
+
+S2.requirejs = requirejs;S2.require = require;S2.define = define;
+}
+}());
+S2.define("almond", function(){});
+
+/* global jQuery:false, $:false */
+S2.define('jquery',[],function () {
+ var _$ = jQuery || $;
+
+ if (_$ == null && console && console.error) {
+ console.error(
+ 'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
+ 'found. Make sure that you are including jQuery before Select2 on your ' +
+ 'web page.'
+ );
+ }
+
+ return _$;
+});
+
+S2.define('select2/utils',[
+ 'jquery'
+], function ($) {
+ var Utils = {};
+
+ Utils.Extend = function (ChildClass, SuperClass) {
+ var __hasProp = {}.hasOwnProperty;
+
+ function BaseConstructor () {
+ this.constructor = ChildClass;
+ }
+
+ for (var key in SuperClass) {
+ if (__hasProp.call(SuperClass, key)) {
+ ChildClass[key] = SuperClass[key];
+ }
+ }
+
+ BaseConstructor.prototype = SuperClass.prototype;
+ ChildClass.prototype = new BaseConstructor();
+ ChildClass.__super__ = SuperClass.prototype;
+
+ return ChildClass;
+ };
+
+ function getMethods (theClass) {
+ var proto = theClass.prototype;
+
+ var methods = [];
+
+ for (var methodName in proto) {
+ var m = proto[methodName];
+
+ if (typeof m !== 'function') {
+ continue;
+ }
+
+ if (methodName === 'constructor') {
+ continue;
+ }
+
+ methods.push(methodName);
+ }
+
+ return methods;
+ }
+
+ Utils.Decorate = function (SuperClass, DecoratorClass) {
+ var decoratedMethods = getMethods(DecoratorClass);
+ var superMethods = getMethods(SuperClass);
+
+ function DecoratedClass () {
+ var unshift = Array.prototype.unshift;
+
+ var argCount = DecoratorClass.prototype.constructor.length;
+
+ var calledConstructor = SuperClass.prototype.constructor;
+
+ if (argCount > 0) {
+ unshift.call(arguments, SuperClass.prototype.constructor);
+
+ calledConstructor = DecoratorClass.prototype.constructor;
+ }
+
+ calledConstructor.apply(this, arguments);
+ }
+
+ DecoratorClass.displayName = SuperClass.displayName;
+
+ function ctr () {
+ this.constructor = DecoratedClass;
+ }
+
+ DecoratedClass.prototype = new ctr();
+
+ for (var m = 0; m < superMethods.length; m++) {
+ var superMethod = superMethods[m];
+
+ DecoratedClass.prototype[superMethod] =
+ SuperClass.prototype[superMethod];
+ }
+
+ var calledMethod = function (methodName) {
+ // Stub out the original method if it's not decorating an actual method
+ var originalMethod = function () {};
+
+ if (methodName in DecoratedClass.prototype) {
+ originalMethod = DecoratedClass.prototype[methodName];
+ }
+
+ var decoratedMethod = DecoratorClass.prototype[methodName];
+
+ return function () {
+ var unshift = Array.prototype.unshift;
+
+ unshift.call(arguments, originalMethod);
+
+ return decoratedMethod.apply(this, arguments);
+ };
+ };
+
+ for (var d = 0; d < decoratedMethods.length; d++) {
+ var decoratedMethod = decoratedMethods[d];
+
+ DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
+ }
+
+ return DecoratedClass;
+ };
+
+ var Observable = function () {
+ this.listeners = {};
+ };
+
+ Observable.prototype.on = function (event, callback) {
+ this.listeners = this.listeners || {};
+
+ if (event in this.listeners) {
+ this.listeners[event].push(callback);
+ } else {
+ this.listeners[event] = [callback];
+ }
+ };
+
+ Observable.prototype.trigger = function (event) {
+ var slice = Array.prototype.slice;
+ var params = slice.call(arguments, 1);
+
+ this.listeners = this.listeners || {};
+
+ // Params should always come in as an array
+ if (params == null) {
+ params = [];
+ }
+
+ // If there are no arguments to the event, use a temporary object
+ if (params.length === 0) {
+ params.push({});
+ }
+
+ // Set the `_type` of the first object to the event
+ params[0]._type = event;
+
+ if (event in this.listeners) {
+ this.invoke(this.listeners[event], slice.call(arguments, 1));
+ }
+
+ if ('*' in this.listeners) {
+ this.invoke(this.listeners['*'], arguments);
+ }
+ };
+
+ Observable.prototype.invoke = function (listeners, params) {
+ for (var i = 0, len = listeners.length; i < len; i++) {
+ listeners[i].apply(this, params);
+ }
+ };
+
+ Utils.Observable = Observable;
+
+ Utils.generateChars = function (length) {
+ var chars = '';
+
+ for (var i = 0; i < length; i++) {
+ var randomChar = Math.floor(Math.random() * 36);
+ chars += randomChar.toString(36);
+ }
+
+ return chars;
+ };
+
+ Utils.bind = function (func, context) {
+ return function () {
+ func.apply(context, arguments);
+ };
+ };
+
+ Utils._convertData = function (data) {
+ for (var originalKey in data) {
+ var keys = originalKey.split('-');
+
+ var dataLevel = data;
+
+ if (keys.length === 1) {
+ continue;
+ }
+
+ for (var k = 0; k < keys.length; k++) {
+ var key = keys[k];
+
+ // Lowercase the first letter
+ // By default, dash-separated becomes camelCase
+ key = key.substring(0, 1).toLowerCase() + key.substring(1);
+
+ if (!(key in dataLevel)) {
+ dataLevel[key] = {};
+ }
+
+ if (k == keys.length - 1) {
+ dataLevel[key] = data[originalKey];
+ }
+
+ dataLevel = dataLevel[key];
+ }
+
+ delete data[originalKey];
+ }
+
+ return data;
+ };
+
+ Utils.hasScroll = function (index, el) {
+ // Adapted from the function created by @ShadowScripter
+ // and adapted by @BillBarry on the Stack Exchange Code Review website.
+ // The original code can be found at
+ // http://codereview.stackexchange.com/q/13338
+ // and was designed to be used with the Sizzle selector engine.
+
+ var $el = $(el);
+ var overflowX = el.style.overflowX;
+ var overflowY = el.style.overflowY;
+
+ //Check both x and y declarations
+ if (overflowX === overflowY &&
+ (overflowY === 'hidden' || overflowY === 'visible')) {
+ return false;
+ }
+
+ if (overflowX === 'scroll' || overflowY === 'scroll') {
+ return true;
+ }
+
+ return ($el.innerHeight() < el.scrollHeight ||
+ $el.innerWidth() < el.scrollWidth);
+ };
+
+ Utils.escapeMarkup = function (markup) {
+ var replaceMap = {
+ '\\': '&#92;',
+ '&': '&amp;',
+ '<': '&lt;',
+ '>': '&gt;',
+ '"': '&quot;',
+ '\'': '&#39;',
+ '/': '&#47;'
+ };
+
+ // Do not try to escape the markup if it's not a string
+ if (typeof markup !== 'string') {
+ return markup;
+ }
+
+ return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
+ return replaceMap[match];
+ });
+ };
+
+ // Append an array of jQuery nodes to a given element.
+ Utils.appendMany = function ($element, $nodes) {
+ // jQuery 1.7.x does not support $.fn.append() with an array
+ // Fall back to a jQuery object collection using $.fn.add()
+ if ($.fn.jquery.substr(0, 3) === '1.7') {
+ var $jqNodes = $();
+
+ $.map($nodes, function (node) {
+ $jqNodes = $jqNodes.add(node);
+ });
+
+ $nodes = $jqNodes;
+ }
+
+ $element.append($nodes);
+ };
+
+ // Cache objects in Utils.__cache instead of $.data (see #4346)
+ Utils.__cache = {};
+
+ var id = 0;
+ Utils.GetUniqueElementId = function (element) {
+ // Get a unique element Id. If element has no id,
+ // creates a new unique number, stores it in the id
+ // attribute and returns the new id.
+ // If an id already exists, it simply returns it.
+
+ var select2Id = element.getAttribute('data-select2-id');
+ if (select2Id == null) {
+ // If element has id, use it.
+ if (element.id) {
+ select2Id = element.id;
+ element.setAttribute('data-select2-id', select2Id);
+ } else {
+ element.setAttribute('data-select2-id', ++id);
+ select2Id = id.toString();
+ }
+ }
+ return select2Id;
+ };
+
+ Utils.StoreData = function (element, name, value) {
+ // Stores an item in the cache for a specified element.
+ // name is the cache key.
+ var id = Utils.GetUniqueElementId(element);
+ if (!Utils.__cache[id]) {
+ Utils.__cache[id] = {};
+ }
+
+ Utils.__cache[id][name] = value;
+ };
+
+ Utils.GetData = function (element, name) {
+ // Retrieves a value from the cache by its key (name)
+ // name is optional. If no name specified, return
+ // all cache items for the specified element.
+ // and for a specified element.
+ var id = Utils.GetUniqueElementId(element);
+ if (name) {
+ if (Utils.__cache[id]) {
+ return Utils.__cache[id][name] != null ?
+ Utils.__cache[id][name]:
+ $(element).data(name); // Fallback to HTML5 data attribs.
+ }
+ return $(element).data(name); // Fallback to HTML5 data attribs.
+ } else {
+ return Utils.__cache[id];
+ }
+ };
+
+ Utils.RemoveData = function (element) {
+ // Removes all cached items for a specified element.
+ var id = Utils.GetUniqueElementId(element);
+ if (Utils.__cache[id] != null) {
+ delete Utils.__cache[id];
+ }
+ };
+
+ return Utils;
+});
+
+S2.define('select2/results',[
+ 'jquery',
+ './utils'
+], function ($, Utils) {
+ function Results ($element, options, dataAdapter) {
+ this.$element = $element;
+ this.data = dataAdapter;
+ this.options = options;
+
+ Results.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(Results, Utils.Observable);
+
+ Results.prototype.render = function () {
+ var $results = $(
+ '<ul class="select2-results__options" role="tree"></ul>'
+ );
+
+ if (this.options.get('multiple')) {
+ $results.attr('aria-multiselectable', 'true');
+ }
+
+ this.$results = $results;
+
+ return $results;
+ };
+
+ Results.prototype.clear = function () {
+ this.$results.empty();
+ };
+
+ Results.prototype.displayMessage = function (params) {
+ var escapeMarkup = this.options.get('escapeMarkup');
+
+ this.clear();
+ this.hideLoading();
+
+ var $message = $(
+ '<li role="treeitem" aria-live="assertive"' +
+ ' class="select2-results__option"></li>'
+ );
+
+ var message = this.options.get('translations').get(params.message);
+
+ $message.append(
+ escapeMarkup(
+ message(params.args)
+ )
+ );
+
+ $message[0].className += ' select2-results__message';
+
+ this.$results.append($message);
+ };
+
+ Results.prototype.hideMessages = function () {
+ this.$results.find('.select2-results__message').remove();
+ };
+
+ Results.prototype.append = function (data) {
+ this.hideLoading();
+
+ var $options = [];
+
+ if (data.results == null || data.results.length === 0) {
+ if (this.$results.children().length === 0) {
+ this.trigger('results:message', {
+ message: 'noResults'
+ });
+ }
+
+ return;
+ }
+
+ data.results = this.sort(data.results);
+
+ for (var d = 0; d < data.results.length; d++) {
+ var item = data.results[d];
+
+ var $option = this.option(item);
+
+ $options.push($option);
+ }
+
+ this.$results.append($options);
+ };
+
+ Results.prototype.position = function ($results, $dropdown) {
+ var $resultsContainer = $dropdown.find('.select2-results');
+ $resultsContainer.append($results);
+ };
+
+ Results.prototype.sort = function (data) {
+ var sorter = this.options.get('sorter');
+
+ return sorter(data);
+ };
+
+ Results.prototype.highlightFirstItem = function () {
+ var $options = this.$results
+ .find('.select2-results__option[aria-selected]');
+
+ var $selected = $options.filter('[aria-selected=true]');
+
+ // Check if there are any selected options
+ if ($selected.length > 0) {
+ // If there are selected options, highlight the first
+ $selected.first().trigger('mouseenter');
+ } else {
+ // If there are no selected options, highlight the first option
+ // in the dropdown
+ $options.first().trigger('mouseenter');
+ }
+
+ this.ensureHighlightVisible();
+ };
+
+ Results.prototype.setClasses = function () {
+ var self = this;
+
+ this.data.current(function (selected) {
+ var selectedIds = $.map(selected, function (s) {
+ return s.id.toString();
+ });
+
+ var $options = self.$results
+ .find('.select2-results__option[aria-selected]');
+
+ $options.each(function () {
+ var $option = $(this);
+
+ var item = Utils.GetData(this, 'data');
+
+ // id needs to be converted to a string when comparing
+ var id = '' + item.id;
+
+ if ((item.element != null && item.element.selected) ||
+ (item.element == null && $.inArray(id, selectedIds) > -1)) {
+ $option.attr('aria-selected', 'true');
+ } else {
+ $option.attr('aria-selected', 'false');
+ }
+ });
+
+ });
+ };
+
+ Results.prototype.showLoading = function (params) {
+ this.hideLoading();
+
+ var loadingMore = this.options.get('translations').get('searching');
+
+ var loading = {
+ disabled: true,
+ loading: true,
+ text: loadingMore(params)
+ };
+ var $loading = this.option(loading);
+ $loading.className += ' loading-results';
+
+ this.$results.prepend($loading);
+ };
+
+ Results.prototype.hideLoading = function () {
+ this.$results.find('.loading-results').remove();
+ };
+
+ Results.prototype.option = function (data) {
+ var option = document.createElement('li');
+ option.className = 'select2-results__option';
+
+ var attrs = {
+ 'role': 'treeitem',
+ 'aria-selected': 'false'
+ };
+
+ if (data.disabled) {
+ delete attrs['aria-selected'];
+ attrs['aria-disabled'] = 'true';
+ }
+
+ if (data.id == null) {
+ delete attrs['aria-selected'];
+ }
+
+ if (data._resultId != null) {
+ option.id = data._resultId;
+ }
+
+ if (data.title) {
+ option.title = data.title;
+ }
+
+ if (data.children) {
+ attrs.role = 'group';
+ attrs['aria-label'] = data.text;
+ delete attrs['aria-selected'];
+ }
+
+ for (var attr in attrs) {
+ var val = attrs[attr];
+
+ option.setAttribute(attr, val);
+ }
+
+ if (data.children) {
+ var $option = $(option);
+
+ var label = document.createElement('strong');
+ label.className = 'select2-results__group';
+
+ var $label = $(label);
+ this.template(data, label);
+
+ var $children = [];
+
+ for (var c = 0; c < data.children.length; c++) {
+ var child = data.children[c];
+
+ var $child = this.option(child);
+
+ $children.push($child);
+ }
+
+ var $childrenContainer = $('<ul></ul>', {
+ 'class': 'select2-results__options select2-results__options--nested'
+ });
+
+ $childrenContainer.append($children);
+
+ $option.append(label);
+ $option.append($childrenContainer);
+ } else {
+ this.template(data, option);
+ }
+
+ Utils.StoreData(option, 'data', data);
+
+ return option;
+ };
+
+ Results.prototype.bind = function (container, $container) {
+ var self = this;
+
+ var id = container.id + '-results';
+
+ this.$results.attr('id', id);
+
+ container.on('results:all', function (params) {
+ self.clear();
+ self.append(params.data);
+
+ if (container.isOpen()) {
+ self.setClasses();
+ self.highlightFirstItem();
+ }
+ });
+
+ container.on('results:append', function (params) {
+ self.append(params.data);
+
+ if (container.isOpen()) {
+ self.setClasses();
+ }
+ });
+
+ container.on('query', function (params) {
+ self.hideMessages();
+ self.showLoading(params);
+ });
+
+ container.on('select', function () {
+ if (!container.isOpen()) {
+ return;
+ }
+
+ self.setClasses();
+ self.highlightFirstItem();
+ });
+
+ container.on('unselect', function () {
+ if (!container.isOpen()) {
+ return;
+ }
+
+ self.setClasses();
+ self.highlightFirstItem();
+ });
+
+ container.on('open', function () {
+ // When the dropdown is open, aria-expended="true"
+ self.$results.attr('aria-expanded', 'true');
+ self.$results.attr('aria-hidden', 'false');
+
+ self.setClasses();
+ self.ensureHighlightVisible();
+ });
+
+ container.on('close', function () {
+ // When the dropdown is closed, aria-expended="false"
+ self.$results.attr('aria-expanded', 'false');
+ self.$results.attr('aria-hidden', 'true');
+ self.$results.removeAttr('aria-activedescendant');
+ });
+
+ container.on('results:toggle', function () {
+ var $highlighted = self.getHighlightedResults();
+
+ if ($highlighted.length === 0) {
+ return;
+ }
+
+ $highlighted.trigger('mouseup');
+ });
+
+ container.on('results:select', function () {
+ var $highlighted = self.getHighlightedResults();
+
+ if ($highlighted.length === 0) {
+ return;
+ }
+
+ var data = Utils.GetData($highlighted[0], 'data');
+
+ if ($highlighted.attr('aria-selected') == 'true') {
+ self.trigger('close', {});
+ } else {
+ self.trigger('select', {
+ data: data
+ });
+ }
+ });
+
+ container.on('results:previous', function () {
+ var $highlighted = self.getHighlightedResults();
+
+ var $options = self.$results.find('[aria-selected]');
+
+ var currentIndex = $options.index($highlighted);
+
+ // If we are already at te top, don't move further
+ // If no options, currentIndex will be -1
+ if (currentIndex <= 0) {
+ return;
+ }
+
+ var nextIndex = currentIndex - 1;
+
+ // If none are highlighted, highlight the first
+ if ($highlighted.length === 0) {
+ nextIndex = 0;
+ }
+
+ var $next = $options.eq(nextIndex);
+
+ $next.trigger('mouseenter');
+
+ var currentOffset = self.$results.offset().top;
+ var nextTop = $next.offset().top;
+ var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);
+
+ if (nextIndex === 0) {
+ self.$results.scrollTop(0);
+ } else if (nextTop - currentOffset < 0) {
+ self.$results.scrollTop(nextOffset);
+ }
+ });
+
+ container.on('results:next', function () {
+ var $highlighted = self.getHighlightedResults();
+
+ var $options = self.$results.find('[aria-selected]');
+
+ var currentIndex = $options.index($highlighted);
+
+ var nextIndex = currentIndex + 1;
+
+ // If we are at the last option, stay there
+ if (nextIndex >= $options.length) {
+ return;
+ }
+
+ var $next = $options.eq(nextIndex);
+
+ $next.trigger('mouseenter');
+
+ var currentOffset = self.$results.offset().top +
+ self.$results.outerHeight(false);
+ var nextBottom = $next.offset().top + $next.outerHeight(false);
+ var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;
+
+ if (nextIndex === 0) {
+ self.$results.scrollTop(0);
+ } else if (nextBottom > currentOffset) {
+ self.$results.scrollTop(nextOffset);
+ }
+ });
+
+ container.on('results:focus', function (params) {
+ params.element.addClass('select2-results__option--highlighted');
+ });
+
+ container.on('results:message', function (params) {
+ self.displayMessage(params);
+ });
+
+ if ($.fn.mousewheel) {
+ this.$results.on('mousewheel', function (e) {
+ var top = self.$results.scrollTop();
+
+ var bottom = self.$results.get(0).scrollHeight - top + e.deltaY;
+
+ var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
+ var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();
+
+ if (isAtTop) {
+ self.$results.scrollTop(0);
+
+ e.preventDefault();
+ e.stopPropagation();
+ } else if (isAtBottom) {
+ self.$results.scrollTop(
+ self.$results.get(0).scrollHeight - self.$results.height()
+ );
+
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+ }
+
+ this.$results.on('mouseup', '.select2-results__option[aria-selected]',
+ function (evt) {
+ var $this = $(this);
+
+ var data = Utils.GetData(this, 'data');
+
+ if ($this.attr('aria-selected') === 'true') {
+ if (self.options.get('multiple')) {
+ self.trigger('unselect', {
+ originalEvent: evt,
+ data: data
+ });
+ } else {
+ self.trigger('close', {});
+ }
+
+ return;
+ }
+
+ self.trigger('select', {
+ originalEvent: evt,
+ data: data
+ });
+ });
+
+ this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
+ function (evt) {
+ var data = Utils.GetData(this, 'data');
+
+ self.getHighlightedResults()
+ .removeClass('select2-results__option--highlighted');
+
+ self.trigger('results:focus', {
+ data: data,
+ element: $(this)
+ });
+ });
+ };
+
+ Results.prototype.getHighlightedResults = function () {
+ var $highlighted = this.$results
+ .find('.select2-results__option--highlighted');
+
+ return $highlighted;
+ };
+
+ Results.prototype.destroy = function () {
+ this.$results.remove();
+ };
+
+ Results.prototype.ensureHighlightVisible = function () {
+ var $highlighted = this.getHighlightedResults();
+
+ if ($highlighted.length === 0) {
+ return;
+ }
+
+ var $options = this.$results.find('[aria-selected]');
+
+ var currentIndex = $options.index($highlighted);
+
+ var currentOffset = this.$results.offset().top;
+ var nextTop = $highlighted.offset().top;
+ var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);
+
+ var offsetDelta = nextTop - currentOffset;
+ nextOffset -= $highlighted.outerHeight(false) * 2;
+
+ if (currentIndex <= 2) {
+ this.$results.scrollTop(0);
+ } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
+ this.$results.scrollTop(nextOffset);
+ }
+ };
+
+ Results.prototype.template = function (result, container) {
+ var template = this.options.get('templateResult');
+ var escapeMarkup = this.options.get('escapeMarkup');
+
+ var content = template(result, container);
+
+ if (content == null) {
+ container.style.display = 'none';
+ } else if (typeof content === 'string') {
+ container.innerHTML = escapeMarkup(content);
+ } else {
+ $(container).append(content);
+ }
+ };
+
+ return Results;
+});
+
+S2.define('select2/keys',[
+
+], function () {
+ var KEYS = {
+ BACKSPACE: 8,
+ TAB: 9,
+ ENTER: 13,
+ SHIFT: 16,
+ CTRL: 17,
+ ALT: 18,
+ ESC: 27,
+ SPACE: 32,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ DELETE: 46
+ };
+
+ return KEYS;
+});
+
+S2.define('select2/selection/base',[
+ 'jquery',
+ '../utils',
+ '../keys'
+], function ($, Utils, KEYS) {
+ function BaseSelection ($element, options) {
+ this.$element = $element;
+ this.options = options;
+
+ BaseSelection.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(BaseSelection, Utils.Observable);
+
+ BaseSelection.prototype.render = function () {
+ var $selection = $(
+ '<span class="select2-selection" role="combobox" ' +
+ ' aria-haspopup="true" aria-expanded="false">' +
+ '</span>'
+ );
+
+ this._tabindex = 0;
+
+ if (Utils.GetData(this.$element[0], 'old-tabindex') != null) {
+ this._tabindex = Utils.GetData(this.$element[0], 'old-tabindex');
+ } else if (this.$element.attr('tabindex') != null) {
+ this._tabindex = this.$element.attr('tabindex');
+ }
+
+ $selection.attr('title', this.$element.attr('title'));
+ $selection.attr('tabindex', this._tabindex);
+
+ this.$selection = $selection;
+
+ return $selection;
+ };
+
+ BaseSelection.prototype.bind = function (container, $container) {
+ var self = this;
+
+ var id = container.id + '-container';
+ var resultsId = container.id + '-results';
+
+ this.container = container;
+
+ this.$selection.on('focus', function (evt) {
+ self.trigger('focus', evt);
+ });
+
+ this.$selection.on('blur', function (evt) {
+ self._handleBlur(evt);
+ });
+
+ this.$selection.on('keydown', function (evt) {
+ self.trigger('keypress', evt);
+
+ if (evt.which === KEYS.SPACE) {
+ evt.preventDefault();
+ }
+ });
+
+ container.on('results:focus', function (params) {
+ self.$selection.attr('aria-activedescendant', params.data._resultId);
+ });
+
+ container.on('selection:update', function (params) {
+ self.update(params.data);
+ });
+
+ container.on('open', function () {
+ // When the dropdown is open, aria-expanded="true"
+ self.$selection.attr('aria-expanded', 'true');
+ self.$selection.attr('aria-owns', resultsId);
+
+ self._attachCloseHandler(container);
+ });
+
+ container.on('close', function () {
+ // When the dropdown is closed, aria-expanded="false"
+ self.$selection.attr('aria-expanded', 'false');
+ self.$selection.removeAttr('aria-activedescendant');
+ self.$selection.removeAttr('aria-owns');
+
+ self.$selection.focus();
+ window.setTimeout(function () {
+ self.$selection.focus();
+ }, 0);
+
+ self._detachCloseHandler(container);
+ });
+
+ container.on('enable', function () {
+ self.$selection.attr('tabindex', self._tabindex);
+ });
+
+ container.on('disable', function () {
+ self.$selection.attr('tabindex', '-1');
+ });
+ };
+
+ BaseSelection.prototype._handleBlur = function (evt) {
+ var self = this;
+
+ // This needs to be delayed as the active element is the body when the tab
+ // key is pressed, possibly along with others.
+ window.setTimeout(function () {
+ // Don't trigger `blur` if the focus is still in the selection
+ if (
+ (document.activeElement == self.$selection[0]) ||
+ ($.contains(self.$selection[0], document.activeElement))
+ ) {
+ return;
+ }
+
+ self.trigger('blur', evt);
+ }, 1);
+ };
+
+ BaseSelection.prototype._attachCloseHandler = function (container) {
+ var self = this;
+
+ $(document.body).on('mousedown.select2.' + container.id, function (e) {
+ var $target = $(e.target);
+
+ var $select = $target.closest('.select2');
+
+ var $all = $('.select2.select2-container--open');
+
+ $all.each(function () {
+ var $this = $(this);
+
+ if (this == $select[0]) {
+ return;
+ }
+
+ var $element = Utils.GetData(this, 'element');
+
+ $element.select2('close');
+ });
+ });
+ };
+
+ BaseSelection.prototype._detachCloseHandler = function (container) {
+ $(document.body).off('mousedown.select2.' + container.id);
+ };
+
+ BaseSelection.prototype.position = function ($selection, $container) {
+ var $selectionContainer = $container.find('.selection');
+ $selectionContainer.append($selection);
+ };
+
+ BaseSelection.prototype.destroy = function () {
+ this._detachCloseHandler(this.container);
+ };
+
+ BaseSelection.prototype.update = function (data) {
+ throw new Error('The `update` method must be defined in child classes.');
+ };
+
+ return BaseSelection;
+});
+
+S2.define('select2/selection/single',[
+ 'jquery',
+ './base',
+ '../utils',
+ '../keys'
+], function ($, BaseSelection, Utils, KEYS) {
+ function SingleSelection () {
+ SingleSelection.__super__.constructor.apply(this, arguments);
+ }
+
+ Utils.Extend(SingleSelection, BaseSelection);
+
+ SingleSelection.prototype.render = function () {
+ var $selection = SingleSelection.__super__.render.call(this);
+
+ $selection.addClass('select2-selection--single');
+
+ $selection.html(
+ '<span class="select2-selection__rendered"></span>' +
+ '<span class="select2-selection__arrow" role="presentation">' +
+ '<b role="presentation"></b>' +
+ '</span>'
+ );
+
+ return $selection;
+ };
+
+ SingleSelection.prototype.bind = function (container, $container) {
+ var self = this;
+
+ SingleSelection.__super__.bind.apply(this, arguments);
+
+ var id = container.id + '-container';
+
+ this.$selection.find('.select2-selection__rendered')
+ .attr('id', id)
+ .attr('role', 'textbox')
+ .attr('aria-readonly', 'true');
+ this.$selection.attr('aria-labelledby', id);
+
+ this.$selection.on('mousedown', function (evt) {
+ // Only respond to left clicks
+ if (evt.which !== 1) {
+ return;
+ }
+
+ self.trigger('toggle', {
+ originalEvent: evt
+ });
+ });
+
+ this.$selection.on('focus', function (evt) {
+ // User focuses on the container
+ });
+
+ this.$selection.on('blur', function (evt) {
+ // User exits the container
+ });
+
+ container.on('focus', function (evt) {
+ if (!container.isOpen()) {
+ self.$selection.focus();
+ }
+ });
+ };
+
+ SingleSelection.prototype.clear = function () {
+ var $rendered = this.$selection.find('.select2-selection__rendered');
+ $rendered.empty();
+ $rendered.removeAttr('title'); // clear tooltip on empty
+ };
+
+ SingleSelection.prototype.display = function (data, container) {
+ var template = this.options.get('templateSelection');
+ var escapeMarkup = this.options.get('escapeMarkup');
+
+ return escapeMarkup(template(data, container));
+ };
+
+ SingleSelection.prototype.selectionContainer = function () {
+ return $('<span></span>');
+ };
+
+ SingleSelection.prototype.update = function (data) {
+ if (data.length === 0) {
+ this.clear();
+ return;
+ }
+
+ var selection = data[0];
+
+ var $rendered = this.$selection.find('.select2-selection__rendered');
+ var formatted = this.display(selection, $rendered);
+
+ $rendered.empty().append(formatted);
+ $rendered.attr('title', selection.title || selection.text);
+ };
+
+ return SingleSelection;
+});
+
+S2.define('select2/selection/multiple',[
+ 'jquery',
+ './base',
+ '../utils'
+], function ($, BaseSelection, Utils) {
+ function MultipleSelection ($element, options) {
+ MultipleSelection.__super__.constructor.apply(this, arguments);
+ }
+
+ Utils.Extend(MultipleSelection, BaseSelection);
+
+ MultipleSelection.prototype.render = function () {
+ var $selection = MultipleSelection.__super__.render.call(this);
+
+ $selection.addClass('select2-selection--multiple');
+
+ $selection.html(
+ '<ul class="select2-selection__rendered"></ul>'
+ );
+
+ return $selection;
+ };
+
+ MultipleSelection.prototype.bind = function (container, $container) {
+ var self = this;
+
+ MultipleSelection.__super__.bind.apply(this, arguments);
+
+ this.$selection.on('click', function (evt) {
+ self.trigger('toggle', {
+ originalEvent: evt
+ });
+ });
+
+ this.$selection.on(
+ 'click',
+ '.select2-selection__choice__remove',
+ function (evt) {
+ // Ignore the event if it is disabled
+ if (self.options.get('disabled')) {
+ return;
+ }
+
+ var $remove = $(this);
+ var $selection = $remove.parent();
+
+ var data = Utils.GetData($selection[0], 'data');
+
+ self.trigger('unselect', {
+ originalEvent: evt,
+ data: data
+ });
+ }
+ );
+ };
+
+ MultipleSelection.prototype.clear = function () {
+ var $rendered = this.$selection.find('.select2-selection__rendered');
+ $rendered.empty();
+ $rendered.removeAttr('title');
+ };
+
+ MultipleSelection.prototype.display = function (data, container) {
+ var template = this.options.get('templateSelection');
+ var escapeMarkup = this.options.get('escapeMarkup');
+
+ return escapeMarkup(template(data, container));
+ };
+
+ MultipleSelection.prototype.selectionContainer = function () {
+ var $container = $(
+ '<li class="select2-selection__choice">' +
+ '<span class="select2-selection__choice__remove" role="presentation">' +
+ '&times;' +
+ '</span>' +
+ '</li>'
+ );
+
+ return $container;
+ };
+
+ MultipleSelection.prototype.update = function (data) {
+ this.clear();
+
+ if (data.length === 0) {
+ return;
+ }
+
+ var $selections = [];
+
+ for (var d = 0; d < data.length; d++) {
+ var selection = data[d];
+
+ var $selection = this.selectionContainer();
+ var formatted = this.display(selection, $selection);
+
+ $selection.append(formatted);
+ $selection.attr('title', selection.title || selection.text);
+
+ Utils.StoreData($selection[0], 'data', selection);
+
+ $selections.push($selection);
+ }
+
+ var $rendered = this.$selection.find('.select2-selection__rendered');
+
+ Utils.appendMany($rendered, $selections);
+ };
+
+ return MultipleSelection;
+});
+
+S2.define('select2/selection/placeholder',[
+ '../utils'
+], function (Utils) {
+ function Placeholder (decorated, $element, options) {
+ this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
+
+ decorated.call(this, $element, options);
+ }
+
+ Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
+ if (typeof placeholder === 'string') {
+ placeholder = {
+ id: '',
+ text: placeholder
+ };
+ }
+
+ return placeholder;
+ };
+
+ Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
+ var $placeholder = this.selectionContainer();
+
+ $placeholder.html(this.display(placeholder));
+ $placeholder.addClass('select2-selection__placeholder')
+ .removeClass('select2-selection__choice');
+
+ return $placeholder;
+ };
+
+ Placeholder.prototype.update = function (decorated, data) {
+ var singlePlaceholder = (
+ data.length == 1 && data[0].id != this.placeholder.id
+ );
+ var multipleSelections = data.length > 1;
+
+ if (multipleSelections || singlePlaceholder) {
+ return decorated.call(this, data);
+ }
+
+ this.clear();
+
+ var $placeholder = this.createPlaceholder(this.placeholder);
+
+ this.$selection.find('.select2-selection__rendered').append($placeholder);
+ };
+
+ return Placeholder;
+});
+
+S2.define('select2/selection/allowClear',[
+ 'jquery',
+ '../keys',
+ '../utils'
+], function ($, KEYS, Utils) {
+ function AllowClear () { }
+
+ AllowClear.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ if (this.placeholder == null) {
+ if (this.options.get('debug') && window.console && console.error) {
+ console.error(
+ 'Select2: The `allowClear` option should be used in combination ' +
+ 'with the `placeholder` option.'
+ );
+ }
+ }
+
+ this.$selection.on('mousedown', '.select2-selection__clear',
+ function (evt) {
+ self._handleClear(evt);
+ });
+
+ container.on('keypress', function (evt) {
+ self._handleKeyboardClear(evt, container);
+ });
+ };
+
+ AllowClear.prototype._handleClear = function (_, evt) {
+ // Ignore the event if it is disabled
+ if (this.options.get('disabled')) {
+ return;
+ }
+
+ var $clear = this.$selection.find('.select2-selection__clear');
+
+ // Ignore the event if nothing has been selected
+ if ($clear.length === 0) {
+ return;
+ }
+
+ evt.stopPropagation();
+
+ var data = Utils.GetData($clear[0], 'data');
+
+ var previousVal = this.$element.val();
+ this.$element.val(this.placeholder.id);
+
+ var unselectData = {
+ data: data
+ };
+ this.trigger('clear', unselectData);
+ if (unselectData.prevented) {
+ this.$element.val(previousVal);
+ return;
+ }
+
+ for (var d = 0; d < data.length; d++) {
+ unselectData = {
+ data: data[d]
+ };
+
+ // Trigger the `unselect` event, so people can prevent it from being
+ // cleared.
+ this.trigger('unselect', unselectData);
+
+ // If the event was prevented, don't clear it out.
+ if (unselectData.prevented) {
+ this.$element.val(previousVal);
+ return;
+ }
+ }
+
+ this.$element.trigger('change');
+
+ this.trigger('toggle', {});
+ };
+
+ AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
+ if (container.isOpen()) {
+ return;
+ }
+
+ if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
+ this._handleClear(evt);
+ }
+ };
+
+ AllowClear.prototype.update = function (decorated, data) {
+ decorated.call(this, data);
+
+ if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
+ data.length === 0) {
+ return;
+ }
+
+ var $remove = $(
+ '<span class="select2-selection__clear">' +
+ '&times;' +
+ '</span>'
+ );
+ Utils.StoreData($remove[0], 'data', data);
+
+ this.$selection.find('.select2-selection__rendered').prepend($remove);
+ };
+
+ return AllowClear;
+});
+
+S2.define('select2/selection/search',[
+ 'jquery',
+ '../utils',
+ '../keys'
+], function ($, Utils, KEYS) {
+ function Search (decorated, $element, options) {
+ decorated.call(this, $element, options);
+ }
+
+ Search.prototype.render = function (decorated) {
+ var $search = $(
+ '<li class="select2-search select2-search--inline">' +
+ '<input class="select2-search__field" type="search" tabindex="-1"' +
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
+ ' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
+ '</li>'
+ );
+
+ this.$searchContainer = $search;
+ this.$search = $search.find('input');
+
+ var $rendered = decorated.call(this);
+
+ this._transferTabIndex();
+
+ return $rendered;
+ };
+
+ Search.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ container.on('open', function () {
+ self.$search.trigger('focus');
+ });
+
+ container.on('close', function () {
+ self.$search.val('');
+ self.$search.removeAttr('aria-activedescendant');
+ self.$search.trigger('focus');
+ });
+
+ container.on('enable', function () {
+ self.$search.prop('disabled', false);
+
+ self._transferTabIndex();
+ });
+
+ container.on('disable', function () {
+ self.$search.prop('disabled', true);
+ });
+
+ container.on('focus', function (evt) {
+ self.$search.trigger('focus');
+ });
+
+ container.on('results:focus', function (params) {
+ self.$search.attr('aria-activedescendant', params.id);
+ });
+
+ this.$selection.on('focusin', '.select2-search--inline', function (evt) {
+ self.trigger('focus', evt);
+ });
+
+ this.$selection.on('focusout', '.select2-search--inline', function (evt) {
+ self._handleBlur(evt);
+ });
+
+ this.$selection.on('keydown', '.select2-search--inline', function (evt) {
+ evt.stopPropagation();
+
+ self.trigger('keypress', evt);
+
+ self._keyUpPrevented = evt.isDefaultPrevented();
+
+ var key = evt.which;
+
+ if (key === KEYS.BACKSPACE && self.$search.val() === '') {
+ var $previousChoice = self.$searchContainer
+ .prev('.select2-selection__choice');
+
+ if ($previousChoice.length > 0) {
+ var item = Utils.GetData($previousChoice[0], 'data');
+
+ self.searchRemoveChoice(item);
+
+ evt.preventDefault();
+ }
+ }
+ });
+
+ // Try to detect the IE version should the `documentMode` property that
+ // is stored on the document. This is only implemented in IE and is
+ // slightly cleaner than doing a user agent check.
+ // This property is not available in Edge, but Edge also doesn't have
+ // this bug.
+ var msie = document.documentMode;
+ var disableInputEvents = msie && msie <= 11;
+
+ // Workaround for browsers which do not support the `input` event
+ // This will prevent double-triggering of events for browsers which support
+ // both the `keyup` and `input` events.
+ this.$selection.on(
+ 'input.searchcheck',
+ '.select2-search--inline',
+ function (evt) {
+ // IE will trigger the `input` event when a placeholder is used on a
+ // search box. To get around this issue, we are forced to ignore all
+ // `input` events in IE and keep using `keyup`.
+ if (disableInputEvents) {
+ self.$selection.off('input.search input.searchcheck');
+ return;
+ }
+
+ // Unbind the duplicated `keyup` event
+ self.$selection.off('keyup.search');
+ }
+ );
+
+ this.$selection.on(
+ 'keyup.search input.search',
+ '.select2-search--inline',
+ function (evt) {
+ // IE will trigger the `input` event when a placeholder is used on a
+ // search box. To get around this issue, we are forced to ignore all
+ // `input` events in IE and keep using `keyup`.
+ if (disableInputEvents && evt.type === 'input') {
+ self.$selection.off('input.search input.searchcheck');
+ return;
+ }
+
+ var key = evt.which;
+
+ // We can freely ignore events from modifier keys
+ if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
+ return;
+ }
+
+ // Tabbing will be handled during the `keydown` phase
+ if (key == KEYS.TAB) {
+ return;
+ }
+
+ self.handleSearch(evt);
+ }
+ );
+ };
+
+ /**
+ * This method will transfer the tabindex attribute from the rendered
+ * selection to the search box. This allows for the search box to be used as
+ * the primary focus instead of the selection container.
+ *
+ * @private
+ */
+ Search.prototype._transferTabIndex = function (decorated) {
+ this.$search.attr('tabindex', this.$selection.attr('tabindex'));
+ this.$selection.attr('tabindex', '-1');
+ };
+
+ Search.prototype.createPlaceholder = function (decorated, placeholder) {
+ this.$search.attr('placeholder', placeholder.text);
+ };
+
+ Search.prototype.update = function (decorated, data) {
+ var searchHadFocus = this.$search[0] == document.activeElement;
+
+ this.$search.attr('placeholder', '');
+
+ decorated.call(this, data);
+
+ this.$selection.find('.select2-selection__rendered')
+ .append(this.$searchContainer);
+
+ this.resizeSearch();
+ if (searchHadFocus) {
+ var isTagInput = this.$element.find('[data-select2-tag]').length;
+ if (isTagInput) {
+ // fix IE11 bug where tag input lost focus
+ this.$element.focus();
+ } else {
+ this.$search.focus();
+ }
+ }
+ };
+
+ Search.prototype.handleSearch = function () {
+ this.resizeSearch();
+
+ if (!this._keyUpPrevented) {
+ var input = this.$search.val();
+
+ this.trigger('query', {
+ term: input
+ });
+ }
+
+ this._keyUpPrevented = false;
+ };
+
+ Search.prototype.searchRemoveChoice = function (decorated, item) {
+ this.trigger('unselect', {
+ data: item
+ });
+
+ this.$search.val(item.text);
+ this.handleSearch();
+ };
+
+ Search.prototype.resizeSearch = function () {
+ this.$search.css('width', '25px');
+
+ var width = '';
+
+ if (this.$search.attr('placeholder') !== '') {
+ width = this.$selection.find('.select2-selection__rendered').innerWidth();
+ } else {
+ var minimumWidth = this.$search.val().length + 1;
+
+ width = (minimumWidth * 0.75) + 'em';
+ }
+
+ this.$search.css('width', width);
+ };
+
+ return Search;
+});
+
+S2.define('select2/selection/eventRelay',[
+ 'jquery'
+], function ($) {
+ function EventRelay () { }
+
+ EventRelay.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+ var relayEvents = [
+ 'open', 'opening',
+ 'close', 'closing',
+ 'select', 'selecting',
+ 'unselect', 'unselecting',
+ 'clear', 'clearing'
+ ];
+
+ var preventableEvents = [
+ 'opening', 'closing', 'selecting', 'unselecting', 'clearing'
+ ];
+
+ decorated.call(this, container, $container);
+
+ container.on('*', function (name, params) {
+ // Ignore events that should not be relayed
+ if ($.inArray(name, relayEvents) === -1) {
+ return;
+ }
+
+ // The parameters should always be an object
+ params = params || {};
+
+ // Generate the jQuery event for the Select2 event
+ var evt = $.Event('select2:' + name, {
+ params: params
+ });
+
+ self.$element.trigger(evt);
+
+ // Only handle preventable events if it was one
+ if ($.inArray(name, preventableEvents) === -1) {
+ return;
+ }
+
+ params.prevented = evt.isDefaultPrevented();
+ });
+ };
+
+ return EventRelay;
+});
+
+S2.define('select2/translation',[
+ 'jquery',
+ 'require'
+], function ($, require) {
+ function Translation (dict) {
+ this.dict = dict || {};
+ }
+
+ Translation.prototype.all = function () {
+ return this.dict;
+ };
+
+ Translation.prototype.get = function (key) {
+ return this.dict[key];
+ };
+
+ Translation.prototype.extend = function (translation) {
+ this.dict = $.extend({}, translation.all(), this.dict);
+ };
+
+ // Static functions
+
+ Translation._cache = {};
+
+ Translation.loadPath = function (path) {
+ if (!(path in Translation._cache)) {
+ var translations = require(path);
+
+ Translation._cache[path] = translations;
+ }
+
+ return new Translation(Translation._cache[path]);
+ };
+
+ return Translation;
+});
+
+S2.define('select2/diacritics',[
+
+], function () {
+ var diacritics = {
+ '\u24B6': 'A',
+ '\uFF21': 'A',
+ '\u00C0': 'A',
+ '\u00C1': 'A',
+ '\u00C2': 'A',
+ '\u1EA6': 'A',
+ '\u1EA4': 'A',
+ '\u1EAA': 'A',
+ '\u1EA8': 'A',
+ '\u00C3': 'A',
+ '\u0100': 'A',
+ '\u0102': 'A',
+ '\u1EB0': 'A',
+ '\u1EAE': 'A',
+ '\u1EB4': 'A',
+ '\u1EB2': 'A',
+ '\u0226': 'A',
+ '\u01E0': 'A',
+ '\u00C4': 'A',
+ '\u01DE': 'A',
+ '\u1EA2': 'A',
+ '\u00C5': 'A',
+ '\u01FA': 'A',
+ '\u01CD': 'A',
+ '\u0200': 'A',
+ '\u0202': 'A',
+ '\u1EA0': 'A',
+ '\u1EAC': 'A',
+ '\u1EB6': 'A',
+ '\u1E00': 'A',
+ '\u0104': 'A',
+ '\u023A': 'A',
+ '\u2C6F': 'A',
+ '\uA732': 'AA',
+ '\u00C6': 'AE',
+ '\u01FC': 'AE',
+ '\u01E2': 'AE',
+ '\uA734': 'AO',
+ '\uA736': 'AU',
+ '\uA738': 'AV',
+ '\uA73A': 'AV',
+ '\uA73C': 'AY',
+ '\u24B7': 'B',
+ '\uFF22': 'B',
+ '\u1E02': 'B',
+ '\u1E04': 'B',
+ '\u1E06': 'B',
+ '\u0243': 'B',
+ '\u0182': 'B',
+ '\u0181': 'B',
+ '\u24B8': 'C',
+ '\uFF23': 'C',
+ '\u0106': 'C',
+ '\u0108': 'C',
+ '\u010A': 'C',
+ '\u010C': 'C',
+ '\u00C7': 'C',
+ '\u1E08': 'C',
+ '\u0187': 'C',
+ '\u023B': 'C',
+ '\uA73E': 'C',
+ '\u24B9': 'D',
+ '\uFF24': 'D',
+ '\u1E0A': 'D',
+ '\u010E': 'D',
+ '\u1E0C': 'D',
+ '\u1E10': 'D',
+ '\u1E12': 'D',
+ '\u1E0E': 'D',
+ '\u0110': 'D',
+ '\u018B': 'D',
+ '\u018A': 'D',
+ '\u0189': 'D',
+ '\uA779': 'D',
+ '\u01F1': 'DZ',
+ '\u01C4': 'DZ',
+ '\u01F2': 'Dz',
+ '\u01C5': 'Dz',
+ '\u24BA': 'E',
+ '\uFF25': 'E',
+ '\u00C8': 'E',
+ '\u00C9': 'E',
+ '\u00CA': 'E',
+ '\u1EC0': 'E',
+ '\u1EBE': 'E',
+ '\u1EC4': 'E',
+ '\u1EC2': 'E',
+ '\u1EBC': 'E',
+ '\u0112': 'E',
+ '\u1E14': 'E',
+ '\u1E16': 'E',
+ '\u0114': 'E',
+ '\u0116': 'E',
+ '\u00CB': 'E',
+ '\u1EBA': 'E',
+ '\u011A': 'E',
+ '\u0204': 'E',
+ '\u0206': 'E',
+ '\u1EB8': 'E',
+ '\u1EC6': 'E',
+ '\u0228': 'E',
+ '\u1E1C': 'E',
+ '\u0118': 'E',
+ '\u1E18': 'E',
+ '\u1E1A': 'E',
+ '\u0190': 'E',
+ '\u018E': 'E',
+ '\u24BB': 'F',
+ '\uFF26': 'F',
+ '\u1E1E': 'F',
+ '\u0191': 'F',
+ '\uA77B': 'F',
+ '\u24BC': 'G',
+ '\uFF27': 'G',
+ '\u01F4': 'G',
+ '\u011C': 'G',
+ '\u1E20': 'G',
+ '\u011E': 'G',
+ '\u0120': 'G',
+ '\u01E6': 'G',
+ '\u0122': 'G',
+ '\u01E4': 'G',
+ '\u0193': 'G',
+ '\uA7A0': 'G',
+ '\uA77D': 'G',
+ '\uA77E': 'G',
+ '\u24BD': 'H',
+ '\uFF28': 'H',
+ '\u0124': 'H',
+ '\u1E22': 'H',
+ '\u1E26': 'H',
+ '\u021E': 'H',
+ '\u1E24': 'H',
+ '\u1E28': 'H',
+ '\u1E2A': 'H',
+ '\u0126': 'H',
+ '\u2C67': 'H',
+ '\u2C75': 'H',
+ '\uA78D': 'H',
+ '\u24BE': 'I',
+ '\uFF29': 'I',
+ '\u00CC': 'I',
+ '\u00CD': 'I',
+ '\u00CE': 'I',
+ '\u0128': 'I',
+ '\u012A': 'I',
+ '\u012C': 'I',
+ '\u0130': 'I',
+ '\u00CF': 'I',
+ '\u1E2E': 'I',
+ '\u1EC8': 'I',
+ '\u01CF': 'I',
+ '\u0208': 'I',
+ '\u020A': 'I',
+ '\u1ECA': 'I',
+ '\u012E': 'I',
+ '\u1E2C': 'I',
+ '\u0197': 'I',
+ '\u24BF': 'J',
+ '\uFF2A': 'J',
+ '\u0134': 'J',
+ '\u0248': 'J',
+ '\u24C0': 'K',
+ '\uFF2B': 'K',
+ '\u1E30': 'K',
+ '\u01E8': 'K',
+ '\u1E32': 'K',
+ '\u0136': 'K',
+ '\u1E34': 'K',
+ '\u0198': 'K',
+ '\u2C69': 'K',
+ '\uA740': 'K',
+ '\uA742': 'K',
+ '\uA744': 'K',
+ '\uA7A2': 'K',
+ '\u24C1': 'L',
+ '\uFF2C': 'L',
+ '\u013F': 'L',
+ '\u0139': 'L',
+ '\u013D': 'L',
+ '\u1E36': 'L',
+ '\u1E38': 'L',
+ '\u013B': 'L',
+ '\u1E3C': 'L',
+ '\u1E3A': 'L',
+ '\u0141': 'L',
+ '\u023D': 'L',
+ '\u2C62': 'L',
+ '\u2C60': 'L',
+ '\uA748': 'L',
+ '\uA746': 'L',
+ '\uA780': 'L',
+ '\u01C7': 'LJ',
+ '\u01C8': 'Lj',
+ '\u24C2': 'M',
+ '\uFF2D': 'M',
+ '\u1E3E': 'M',
+ '\u1E40': 'M',
+ '\u1E42': 'M',
+ '\u2C6E': 'M',
+ '\u019C': 'M',
+ '\u24C3': 'N',
+ '\uFF2E': 'N',
+ '\u01F8': 'N',
+ '\u0143': 'N',
+ '\u00D1': 'N',
+ '\u1E44': 'N',
+ '\u0147': 'N',
+ '\u1E46': 'N',
+ '\u0145': 'N',
+ '\u1E4A': 'N',
+ '\u1E48': 'N',
+ '\u0220': 'N',
+ '\u019D': 'N',
+ '\uA790': 'N',
+ '\uA7A4': 'N',
+ '\u01CA': 'NJ',
+ '\u01CB': 'Nj',
+ '\u24C4': 'O',
+ '\uFF2F': 'O',
+ '\u00D2': 'O',
+ '\u00D3': 'O',
+ '\u00D4': 'O',
+ '\u1ED2': 'O',
+ '\u1ED0': 'O',
+ '\u1ED6': 'O',
+ '\u1ED4': 'O',
+ '\u00D5': 'O',
+ '\u1E4C': 'O',
+ '\u022C': 'O',
+ '\u1E4E': 'O',
+ '\u014C': 'O',
+ '\u1E50': 'O',
+ '\u1E52': 'O',
+ '\u014E': 'O',
+ '\u022E': 'O',
+ '\u0230': 'O',
+ '\u00D6': 'O',
+ '\u022A': 'O',
+ '\u1ECE': 'O',
+ '\u0150': 'O',
+ '\u01D1': 'O',
+ '\u020C': 'O',
+ '\u020E': 'O',
+ '\u01A0': 'O',
+ '\u1EDC': 'O',
+ '\u1EDA': 'O',
+ '\u1EE0': 'O',
+ '\u1EDE': 'O',
+ '\u1EE2': 'O',
+ '\u1ECC': 'O',
+ '\u1ED8': 'O',
+ '\u01EA': 'O',
+ '\u01EC': 'O',
+ '\u00D8': 'O',
+ '\u01FE': 'O',
+ '\u0186': 'O',
+ '\u019F': 'O',
+ '\uA74A': 'O',
+ '\uA74C': 'O',
+ '\u01A2': 'OI',
+ '\uA74E': 'OO',
+ '\u0222': 'OU',
+ '\u24C5': 'P',
+ '\uFF30': 'P',
+ '\u1E54': 'P',
+ '\u1E56': 'P',
+ '\u01A4': 'P',
+ '\u2C63': 'P',
+ '\uA750': 'P',
+ '\uA752': 'P',
+ '\uA754': 'P',
+ '\u24C6': 'Q',
+ '\uFF31': 'Q',
+ '\uA756': 'Q',
+ '\uA758': 'Q',
+ '\u024A': 'Q',
+ '\u24C7': 'R',
+ '\uFF32': 'R',
+ '\u0154': 'R',
+ '\u1E58': 'R',
+ '\u0158': 'R',
+ '\u0210': 'R',
+ '\u0212': 'R',
+ '\u1E5A': 'R',
+ '\u1E5C': 'R',
+ '\u0156': 'R',
+ '\u1E5E': 'R',
+ '\u024C': 'R',
+ '\u2C64': 'R',
+ '\uA75A': 'R',
+ '\uA7A6': 'R',
+ '\uA782': 'R',
+ '\u24C8': 'S',
+ '\uFF33': 'S',
+ '\u1E9E': 'S',
+ '\u015A': 'S',
+ '\u1E64': 'S',
+ '\u015C': 'S',
+ '\u1E60': 'S',
+ '\u0160': 'S',
+ '\u1E66': 'S',
+ '\u1E62': 'S',
+ '\u1E68': 'S',
+ '\u0218': 'S',
+ '\u015E': 'S',
+ '\u2C7E': 'S',
+ '\uA7A8': 'S',
+ '\uA784': 'S',
+ '\u24C9': 'T',
+ '\uFF34': 'T',
+ '\u1E6A': 'T',
+ '\u0164': 'T',
+ '\u1E6C': 'T',
+ '\u021A': 'T',
+ '\u0162': 'T',
+ '\u1E70': 'T',
+ '\u1E6E': 'T',
+ '\u0166': 'T',
+ '\u01AC': 'T',
+ '\u01AE': 'T',
+ '\u023E': 'T',
+ '\uA786': 'T',
+ '\uA728': 'TZ',
+ '\u24CA': 'U',
+ '\uFF35': 'U',
+ '\u00D9': 'U',
+ '\u00DA': 'U',
+ '\u00DB': 'U',
+ '\u0168': 'U',
+ '\u1E78': 'U',
+ '\u016A': 'U',
+ '\u1E7A': 'U',
+ '\u016C': 'U',
+ '\u00DC': 'U',
+ '\u01DB': 'U',
+ '\u01D7': 'U',
+ '\u01D5': 'U',
+ '\u01D9': 'U',
+ '\u1EE6': 'U',
+ '\u016E': 'U',
+ '\u0170': 'U',
+ '\u01D3': 'U',
+ '\u0214': 'U',
+ '\u0216': 'U',
+ '\u01AF': 'U',
+ '\u1EEA': 'U',
+ '\u1EE8': 'U',
+ '\u1EEE': 'U',
+ '\u1EEC': 'U',
+ '\u1EF0': 'U',
+ '\u1EE4': 'U',
+ '\u1E72': 'U',
+ '\u0172': 'U',
+ '\u1E76': 'U',
+ '\u1E74': 'U',
+ '\u0244': 'U',
+ '\u24CB': 'V',
+ '\uFF36': 'V',
+ '\u1E7C': 'V',
+ '\u1E7E': 'V',
+ '\u01B2': 'V',
+ '\uA75E': 'V',
+ '\u0245': 'V',
+ '\uA760': 'VY',
+ '\u24CC': 'W',
+ '\uFF37': 'W',
+ '\u1E80': 'W',
+ '\u1E82': 'W',
+ '\u0174': 'W',
+ '\u1E86': 'W',
+ '\u1E84': 'W',
+ '\u1E88': 'W',
+ '\u2C72': 'W',
+ '\u24CD': 'X',
+ '\uFF38': 'X',
+ '\u1E8A': 'X',
+ '\u1E8C': 'X',
+ '\u24CE': 'Y',
+ '\uFF39': 'Y',
+ '\u1EF2': 'Y',
+ '\u00DD': 'Y',
+ '\u0176': 'Y',
+ '\u1EF8': 'Y',
+ '\u0232': 'Y',
+ '\u1E8E': 'Y',
+ '\u0178': 'Y',
+ '\u1EF6': 'Y',
+ '\u1EF4': 'Y',
+ '\u01B3': 'Y',
+ '\u024E': 'Y',
+ '\u1EFE': 'Y',
+ '\u24CF': 'Z',
+ '\uFF3A': 'Z',
+ '\u0179': 'Z',
+ '\u1E90': 'Z',
+ '\u017B': 'Z',
+ '\u017D': 'Z',
+ '\u1E92': 'Z',
+ '\u1E94': 'Z',
+ '\u01B5': 'Z',
+ '\u0224': 'Z',
+ '\u2C7F': 'Z',
+ '\u2C6B': 'Z',
+ '\uA762': 'Z',
+ '\u24D0': 'a',
+ '\uFF41': 'a',
+ '\u1E9A': 'a',
+ '\u00E0': 'a',
+ '\u00E1': 'a',
+ '\u00E2': 'a',
+ '\u1EA7': 'a',
+ '\u1EA5': 'a',
+ '\u1EAB': 'a',
+ '\u1EA9': 'a',
+ '\u00E3': 'a',
+ '\u0101': 'a',
+ '\u0103': 'a',
+ '\u1EB1': 'a',
+ '\u1EAF': 'a',
+ '\u1EB5': 'a',
+ '\u1EB3': 'a',
+ '\u0227': 'a',
+ '\u01E1': 'a',
+ '\u00E4': 'a',
+ '\u01DF': 'a',
+ '\u1EA3': 'a',
+ '\u00E5': 'a',
+ '\u01FB': 'a',
+ '\u01CE': 'a',
+ '\u0201': 'a',
+ '\u0203': 'a',
+ '\u1EA1': 'a',
+ '\u1EAD': 'a',
+ '\u1EB7': 'a',
+ '\u1E01': 'a',
+ '\u0105': 'a',
+ '\u2C65': 'a',
+ '\u0250': 'a',
+ '\uA733': 'aa',
+ '\u00E6': 'ae',
+ '\u01FD': 'ae',
+ '\u01E3': 'ae',
+ '\uA735': 'ao',
+ '\uA737': 'au',
+ '\uA739': 'av',
+ '\uA73B': 'av',
+ '\uA73D': 'ay',
+ '\u24D1': 'b',
+ '\uFF42': 'b',
+ '\u1E03': 'b',
+ '\u1E05': 'b',
+ '\u1E07': 'b',
+ '\u0180': 'b',
+ '\u0183': 'b',
+ '\u0253': 'b',
+ '\u24D2': 'c',
+ '\uFF43': 'c',
+ '\u0107': 'c',
+ '\u0109': 'c',
+ '\u010B': 'c',
+ '\u010D': 'c',
+ '\u00E7': 'c',
+ '\u1E09': 'c',
+ '\u0188': 'c',
+ '\u023C': 'c',
+ '\uA73F': 'c',
+ '\u2184': 'c',
+ '\u24D3': 'd',
+ '\uFF44': 'd',
+ '\u1E0B': 'd',
+ '\u010F': 'd',
+ '\u1E0D': 'd',
+ '\u1E11': 'd',
+ '\u1E13': 'd',
+ '\u1E0F': 'd',
+ '\u0111': 'd',
+ '\u018C': 'd',
+ '\u0256': 'd',
+ '\u0257': 'd',
+ '\uA77A': 'd',
+ '\u01F3': 'dz',
+ '\u01C6': 'dz',
+ '\u24D4': 'e',
+ '\uFF45': 'e',
+ '\u00E8': 'e',
+ '\u00E9': 'e',
+ '\u00EA': 'e',
+ '\u1EC1': 'e',
+ '\u1EBF': 'e',
+ '\u1EC5': 'e',
+ '\u1EC3': 'e',
+ '\u1EBD': 'e',
+ '\u0113': 'e',
+ '\u1E15': 'e',
+ '\u1E17': 'e',
+ '\u0115': 'e',
+ '\u0117': 'e',
+ '\u00EB': 'e',
+ '\u1EBB': 'e',
+ '\u011B': 'e',
+ '\u0205': 'e',
+ '\u0207': 'e',
+ '\u1EB9': 'e',
+ '\u1EC7': 'e',
+ '\u0229': 'e',
+ '\u1E1D': 'e',
+ '\u0119': 'e',
+ '\u1E19': 'e',
+ '\u1E1B': 'e',
+ '\u0247': 'e',
+ '\u025B': 'e',
+ '\u01DD': 'e',
+ '\u24D5': 'f',
+ '\uFF46': 'f',
+ '\u1E1F': 'f',
+ '\u0192': 'f',
+ '\uA77C': 'f',
+ '\u24D6': 'g',
+ '\uFF47': 'g',
+ '\u01F5': 'g',
+ '\u011D': 'g',
+ '\u1E21': 'g',
+ '\u011F': 'g',
+ '\u0121': 'g',
+ '\u01E7': 'g',
+ '\u0123': 'g',
+ '\u01E5': 'g',
+ '\u0260': 'g',
+ '\uA7A1': 'g',
+ '\u1D79': 'g',
+ '\uA77F': 'g',
+ '\u24D7': 'h',
+ '\uFF48': 'h',
+ '\u0125': 'h',
+ '\u1E23': 'h',
+ '\u1E27': 'h',
+ '\u021F': 'h',
+ '\u1E25': 'h',
+ '\u1E29': 'h',
+ '\u1E2B': 'h',
+ '\u1E96': 'h',
+ '\u0127': 'h',
+ '\u2C68': 'h',
+ '\u2C76': 'h',
+ '\u0265': 'h',
+ '\u0195': 'hv',
+ '\u24D8': 'i',
+ '\uFF49': 'i',
+ '\u00EC': 'i',
+ '\u00ED': 'i',
+ '\u00EE': 'i',
+ '\u0129': 'i',
+ '\u012B': 'i',
+ '\u012D': 'i',
+ '\u00EF': 'i',
+ '\u1E2F': 'i',
+ '\u1EC9': 'i',
+ '\u01D0': 'i',
+ '\u0209': 'i',
+ '\u020B': 'i',
+ '\u1ECB': 'i',
+ '\u012F': 'i',
+ '\u1E2D': 'i',
+ '\u0268': 'i',
+ '\u0131': 'i',
+ '\u24D9': 'j',
+ '\uFF4A': 'j',
+ '\u0135': 'j',
+ '\u01F0': 'j',
+ '\u0249': 'j',
+ '\u24DA': 'k',
+ '\uFF4B': 'k',
+ '\u1E31': 'k',
+ '\u01E9': 'k',
+ '\u1E33': 'k',
+ '\u0137': 'k',
+ '\u1E35': 'k',
+ '\u0199': 'k',
+ '\u2C6A': 'k',
+ '\uA741': 'k',
+ '\uA743': 'k',
+ '\uA745': 'k',
+ '\uA7A3': 'k',
+ '\u24DB': 'l',
+ '\uFF4C': 'l',
+ '\u0140': 'l',
+ '\u013A': 'l',
+ '\u013E': 'l',
+ '\u1E37': 'l',
+ '\u1E39': 'l',
+ '\u013C': 'l',
+ '\u1E3D': 'l',
+ '\u1E3B': 'l',
+ '\u017F': 'l',
+ '\u0142': 'l',
+ '\u019A': 'l',
+ '\u026B': 'l',
+ '\u2C61': 'l',
+ '\uA749': 'l',
+ '\uA781': 'l',
+ '\uA747': 'l',
+ '\u01C9': 'lj',
+ '\u24DC': 'm',
+ '\uFF4D': 'm',
+ '\u1E3F': 'm',
+ '\u1E41': 'm',
+ '\u1E43': 'm',
+ '\u0271': 'm',
+ '\u026F': 'm',
+ '\u24DD': 'n',
+ '\uFF4E': 'n',
+ '\u01F9': 'n',
+ '\u0144': 'n',
+ '\u00F1': 'n',
+ '\u1E45': 'n',
+ '\u0148': 'n',
+ '\u1E47': 'n',
+ '\u0146': 'n',
+ '\u1E4B': 'n',
+ '\u1E49': 'n',
+ '\u019E': 'n',
+ '\u0272': 'n',
+ '\u0149': 'n',
+ '\uA791': 'n',
+ '\uA7A5': 'n',
+ '\u01CC': 'nj',
+ '\u24DE': 'o',
+ '\uFF4F': 'o',
+ '\u00F2': 'o',
+ '\u00F3': 'o',
+ '\u00F4': 'o',
+ '\u1ED3': 'o',
+ '\u1ED1': 'o',
+ '\u1ED7': 'o',
+ '\u1ED5': 'o',
+ '\u00F5': 'o',
+ '\u1E4D': 'o',
+ '\u022D': 'o',
+ '\u1E4F': 'o',
+ '\u014D': 'o',
+ '\u1E51': 'o',
+ '\u1E53': 'o',
+ '\u014F': 'o',
+ '\u022F': 'o',
+ '\u0231': 'o',
+ '\u00F6': 'o',
+ '\u022B': 'o',
+ '\u1ECF': 'o',
+ '\u0151': 'o',
+ '\u01D2': 'o',
+ '\u020D': 'o',
+ '\u020F': 'o',
+ '\u01A1': 'o',
+ '\u1EDD': 'o',
+ '\u1EDB': 'o',
+ '\u1EE1': 'o',
+ '\u1EDF': 'o',
+ '\u1EE3': 'o',
+ '\u1ECD': 'o',
+ '\u1ED9': 'o',
+ '\u01EB': 'o',
+ '\u01ED': 'o',
+ '\u00F8': 'o',
+ '\u01FF': 'o',
+ '\u0254': 'o',
+ '\uA74B': 'o',
+ '\uA74D': 'o',
+ '\u0275': 'o',
+ '\u01A3': 'oi',
+ '\u0223': 'ou',
+ '\uA74F': 'oo',
+ '\u24DF': 'p',
+ '\uFF50': 'p',
+ '\u1E55': 'p',
+ '\u1E57': 'p',
+ '\u01A5': 'p',
+ '\u1D7D': 'p',
+ '\uA751': 'p',
+ '\uA753': 'p',
+ '\uA755': 'p',
+ '\u24E0': 'q',
+ '\uFF51': 'q',
+ '\u024B': 'q',
+ '\uA757': 'q',
+ '\uA759': 'q',
+ '\u24E1': 'r',
+ '\uFF52': 'r',
+ '\u0155': 'r',
+ '\u1E59': 'r',
+ '\u0159': 'r',
+ '\u0211': 'r',
+ '\u0213': 'r',
+ '\u1E5B': 'r',
+ '\u1E5D': 'r',
+ '\u0157': 'r',
+ '\u1E5F': 'r',
+ '\u024D': 'r',
+ '\u027D': 'r',
+ '\uA75B': 'r',
+ '\uA7A7': 'r',
+ '\uA783': 'r',
+ '\u24E2': 's',
+ '\uFF53': 's',
+ '\u00DF': 's',
+ '\u015B': 's',
+ '\u1E65': 's',
+ '\u015D': 's',
+ '\u1E61': 's',
+ '\u0161': 's',
+ '\u1E67': 's',
+ '\u1E63': 's',
+ '\u1E69': 's',
+ '\u0219': 's',
+ '\u015F': 's',
+ '\u023F': 's',
+ '\uA7A9': 's',
+ '\uA785': 's',
+ '\u1E9B': 's',
+ '\u24E3': 't',
+ '\uFF54': 't',
+ '\u1E6B': 't',
+ '\u1E97': 't',
+ '\u0165': 't',
+ '\u1E6D': 't',
+ '\u021B': 't',
+ '\u0163': 't',
+ '\u1E71': 't',
+ '\u1E6F': 't',
+ '\u0167': 't',
+ '\u01AD': 't',
+ '\u0288': 't',
+ '\u2C66': 't',
+ '\uA787': 't',
+ '\uA729': 'tz',
+ '\u24E4': 'u',
+ '\uFF55': 'u',
+ '\u00F9': 'u',
+ '\u00FA': 'u',
+ '\u00FB': 'u',
+ '\u0169': 'u',
+ '\u1E79': 'u',
+ '\u016B': 'u',
+ '\u1E7B': 'u',
+ '\u016D': 'u',
+ '\u00FC': 'u',
+ '\u01DC': 'u',
+ '\u01D8': 'u',
+ '\u01D6': 'u',
+ '\u01DA': 'u',
+ '\u1EE7': 'u',
+ '\u016F': 'u',
+ '\u0171': 'u',
+ '\u01D4': 'u',
+ '\u0215': 'u',
+ '\u0217': 'u',
+ '\u01B0': 'u',
+ '\u1EEB': 'u',
+ '\u1EE9': 'u',
+ '\u1EEF': 'u',
+ '\u1EED': 'u',
+ '\u1EF1': 'u',
+ '\u1EE5': 'u',
+ '\u1E73': 'u',
+ '\u0173': 'u',
+ '\u1E77': 'u',
+ '\u1E75': 'u',
+ '\u0289': 'u',
+ '\u24E5': 'v',
+ '\uFF56': 'v',
+ '\u1E7D': 'v',
+ '\u1E7F': 'v',
+ '\u028B': 'v',
+ '\uA75F': 'v',
+ '\u028C': 'v',
+ '\uA761': 'vy',
+ '\u24E6': 'w',
+ '\uFF57': 'w',
+ '\u1E81': 'w',
+ '\u1E83': 'w',
+ '\u0175': 'w',
+ '\u1E87': 'w',
+ '\u1E85': 'w',
+ '\u1E98': 'w',
+ '\u1E89': 'w',
+ '\u2C73': 'w',
+ '\u24E7': 'x',
+ '\uFF58': 'x',
+ '\u1E8B': 'x',
+ '\u1E8D': 'x',
+ '\u24E8': 'y',
+ '\uFF59': 'y',
+ '\u1EF3': 'y',
+ '\u00FD': 'y',
+ '\u0177': 'y',
+ '\u1EF9': 'y',
+ '\u0233': 'y',
+ '\u1E8F': 'y',
+ '\u00FF': 'y',
+ '\u1EF7': 'y',
+ '\u1E99': 'y',
+ '\u1EF5': 'y',
+ '\u01B4': 'y',
+ '\u024F': 'y',
+ '\u1EFF': 'y',
+ '\u24E9': 'z',
+ '\uFF5A': 'z',
+ '\u017A': 'z',
+ '\u1E91': 'z',
+ '\u017C': 'z',
+ '\u017E': 'z',
+ '\u1E93': 'z',
+ '\u1E95': 'z',
+ '\u01B6': 'z',
+ '\u0225': 'z',
+ '\u0240': 'z',
+ '\u2C6C': 'z',
+ '\uA763': 'z',
+ '\u0386': '\u0391',
+ '\u0388': '\u0395',
+ '\u0389': '\u0397',
+ '\u038A': '\u0399',
+ '\u03AA': '\u0399',
+ '\u038C': '\u039F',
+ '\u038E': '\u03A5',
+ '\u03AB': '\u03A5',
+ '\u038F': '\u03A9',
+ '\u03AC': '\u03B1',
+ '\u03AD': '\u03B5',
+ '\u03AE': '\u03B7',
+ '\u03AF': '\u03B9',
+ '\u03CA': '\u03B9',
+ '\u0390': '\u03B9',
+ '\u03CC': '\u03BF',
+ '\u03CD': '\u03C5',
+ '\u03CB': '\u03C5',
+ '\u03B0': '\u03C5',
+ '\u03C9': '\u03C9',
+ '\u03C2': '\u03C3'
+ };
+
+ return diacritics;
+});
+
+S2.define('select2/data/base',[
+ '../utils'
+], function (Utils) {
+ function BaseAdapter ($element, options) {
+ BaseAdapter.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(BaseAdapter, Utils.Observable);
+
+ BaseAdapter.prototype.current = function (callback) {
+ throw new Error('The `current` method must be defined in child classes.');
+ };
+
+ BaseAdapter.prototype.query = function (params, callback) {
+ throw new Error('The `query` method must be defined in child classes.');
+ };
+
+ BaseAdapter.prototype.bind = function (container, $container) {
+ // Can be implemented in subclasses
+ };
+
+ BaseAdapter.prototype.destroy = function () {
+ // Can be implemented in subclasses
+ };
+
+ BaseAdapter.prototype.generateResultId = function (container, data) {
+ var id = container.id + '-result-';
+
+ id += Utils.generateChars(4);
+
+ if (data.id != null) {
+ id += '-' + data.id.toString();
+ } else {
+ id += '-' + Utils.generateChars(4);
+ }
+ return id;
+ };
+
+ return BaseAdapter;
+});
+
+S2.define('select2/data/select',[
+ './base',
+ '../utils',
+ 'jquery'
+], function (BaseAdapter, Utils, $) {
+ function SelectAdapter ($element, options) {
+ this.$element = $element;
+ this.options = options;
+
+ SelectAdapter.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(SelectAdapter, BaseAdapter);
+
+ SelectAdapter.prototype.current = function (callback) {
+ var data = [];
+ var self = this;
+
+ this.$element.find(':selected').each(function () {
+ var $option = $(this);
+
+ var option = self.item($option);
+
+ data.push(option);
+ });
+
+ callback(data);
+ };
+
+ SelectAdapter.prototype.select = function (data) {
+ var self = this;
+
+ data.selected = true;
+
+ // If data.element is a DOM node, use it instead
+ if ($(data.element).is('option')) {
+ data.element.selected = true;
+
+ this.$element.trigger('change');
+
+ return;
+ }
+
+ if (this.$element.prop('multiple')) {
+ this.current(function (currentData) {
+ var val = [];
+
+ data = [data];
+ data.push.apply(data, currentData);
+
+ for (var d = 0; d < data.length; d++) {
+ var id = data[d].id;
+
+ if ($.inArray(id, val) === -1) {
+ val.push(id);
+ }
+ }
+
+ self.$element.val(val);
+ self.$element.trigger('change');
+ });
+ } else {
+ var val = data.id;
+
+ this.$element.val(val);
+ this.$element.trigger('change');
+ }
+ };
+
+ SelectAdapter.prototype.unselect = function (data) {
+ var self = this;
+
+ if (!this.$element.prop('multiple')) {
+ return;
+ }
+
+ data.selected = false;
+
+ if ($(data.element).is('option')) {
+ data.element.selected = false;
+
+ this.$element.trigger('change');
+
+ return;
+ }
+
+ this.current(function (currentData) {
+ var val = [];
+
+ for (var d = 0; d < currentData.length; d++) {
+ var id = currentData[d].id;
+
+ if (id !== data.id && $.inArray(id, val) === -1) {
+ val.push(id);
+ }
+ }
+
+ self.$element.val(val);
+
+ self.$element.trigger('change');
+ });
+ };
+
+ SelectAdapter.prototype.bind = function (container, $container) {
+ var self = this;
+
+ this.container = container;
+
+ container.on('select', function (params) {
+ self.select(params.data);
+ });
+
+ container.on('unselect', function (params) {
+ self.unselect(params.data);
+ });
+ };
+
+ SelectAdapter.prototype.destroy = function () {
+ // Remove anything added to child elements
+ this.$element.find('*').each(function () {
+ // Remove any custom data set by Select2
+ Utils.RemoveData(this);
+ });
+ };
+
+ SelectAdapter.prototype.query = function (params, callback) {
+ var data = [];
+ var self = this;
+
+ var $options = this.$element.children();
+
+ $options.each(function () {
+ var $option = $(this);
+
+ if (!$option.is('option') && !$option.is('optgroup')) {
+ return;
+ }
+
+ var option = self.item($option);
+
+ var matches = self.matches(params, option);
+
+ if (matches !== null) {
+ data.push(matches);
+ }
+ });
+
+ callback({
+ results: data
+ });
+ };
+
+ SelectAdapter.prototype.addOptions = function ($options) {
+ Utils.appendMany(this.$element, $options);
+ };
+
+ SelectAdapter.prototype.option = function (data) {
+ var option;
+
+ if (data.children) {
+ option = document.createElement('optgroup');
+ option.label = data.text;
+ } else {
+ option = document.createElement('option');
+
+ if (option.textContent !== undefined) {
+ option.textContent = data.text;
+ } else {
+ option.innerText = data.text;
+ }
+ }
+
+ if (data.id !== undefined) {
+ option.value = data.id;
+ }
+
+ if (data.disabled) {
+ option.disabled = true;
+ }
+
+ if (data.selected) {
+ option.selected = true;
+ }
+
+ if (data.title) {
+ option.title = data.title;
+ }
+
+ var $option = $(option);
+
+ var normalizedData = this._normalizeItem(data);
+ normalizedData.element = option;
+
+ // Override the option's data with the combined data
+ Utils.StoreData(option, 'data', normalizedData);
+
+ return $option;
+ };
+
+ SelectAdapter.prototype.item = function ($option) {
+ var data = {};
+
+ data = Utils.GetData($option[0], 'data');
+
+ if (data != null) {
+ return data;
+ }
+
+ if ($option.is('option')) {
+ data = {
+ id: $option.val(),
+ text: $option.text(),
+ disabled: $option.prop('disabled'),
+ selected: $option.prop('selected'),
+ title: $option.prop('title')
+ };
+ } else if ($option.is('optgroup')) {
+ data = {
+ text: $option.prop('label'),
+ children: [],
+ title: $option.prop('title')
+ };
+
+ var $children = $option.children('option');
+ var children = [];
+
+ for (var c = 0; c < $children.length; c++) {
+ var $child = $($children[c]);
+
+ var child = this.item($child);
+
+ children.push(child);
+ }
+
+ data.children = children;
+ }
+
+ data = this._normalizeItem(data);
+ data.element = $option[0];
+
+ Utils.StoreData($option[0], 'data', data);
+
+ return data;
+ };
+
+ SelectAdapter.prototype._normalizeItem = function (item) {
+ if (item !== Object(item)) {
+ item = {
+ id: item,
+ text: item
+ };
+ }
+
+ item = $.extend({}, {
+ text: ''
+ }, item);
+
+ var defaults = {
+ selected: false,
+ disabled: false
+ };
+
+ if (item.id != null) {
+ item.id = item.id.toString();
+ }
+
+ if (item.text != null) {
+ item.text = item.text.toString();
+ }
+
+ if (item._resultId == null && item.id && this.container != null) {
+ item._resultId = this.generateResultId(this.container, item);
+ }
+
+ return $.extend({}, defaults, item);
+ };
+
+ SelectAdapter.prototype.matches = function (params, data) {
+ var matcher = this.options.get('matcher');
+
+ return matcher(params, data);
+ };
+
+ return SelectAdapter;
+});
+
+S2.define('select2/data/array',[
+ './select',
+ '../utils',
+ 'jquery'
+], function (SelectAdapter, Utils, $) {
+ function ArrayAdapter ($element, options) {
+ var data = options.get('data') || [];
+
+ ArrayAdapter.__super__.constructor.call(this, $element, options);
+
+ this.addOptions(this.convertToOptions(data));
+ }
+
+ Utils.Extend(ArrayAdapter, SelectAdapter);
+
+ ArrayAdapter.prototype.select = function (data) {
+ var $option = this.$element.find('option').filter(function (i, elm) {
+ return elm.value == data.id.toString();
+ });
+
+ if ($option.length === 0) {
+ $option = this.option(data);
+
+ this.addOptions($option);
+ }
+
+ ArrayAdapter.__super__.select.call(this, data);
+ };
+
+ ArrayAdapter.prototype.convertToOptions = function (data) {
+ var self = this;
+
+ var $existing = this.$element.find('option');
+ var existingIds = $existing.map(function () {
+ return self.item($(this)).id;
+ }).get();
+
+ var $options = [];
+
+ // Filter out all items except for the one passed in the argument
+ function onlyItem (item) {
+ return function () {
+ return $(this).val() == item.id;
+ };
+ }
+
+ for (var d = 0; d < data.length; d++) {
+ var item = this._normalizeItem(data[d]);
+
+ // Skip items which were pre-loaded, only merge the data
+ if ($.inArray(item.id, existingIds) >= 0) {
+ var $existingOption = $existing.filter(onlyItem(item));
+
+ var existingData = this.item($existingOption);
+ var newData = $.extend(true, {}, item, existingData);
+
+ var $newOption = this.option(newData);
+
+ $existingOption.replaceWith($newOption);
+
+ continue;
+ }
+
+ var $option = this.option(item);
+
+ if (item.children) {
+ var $children = this.convertToOptions(item.children);
+
+ Utils.appendMany($option, $children);
+ }
+
+ $options.push($option);
+ }
+
+ return $options;
+ };
+
+ return ArrayAdapter;
+});
+
+S2.define('select2/data/ajax',[
+ './array',
+ '../utils',
+ 'jquery'
+], function (ArrayAdapter, Utils, $) {
+ function AjaxAdapter ($element, options) {
+ this.ajaxOptions = this._applyDefaults(options.get('ajax'));
+
+ if (this.ajaxOptions.processResults != null) {
+ this.processResults = this.ajaxOptions.processResults;
+ }
+
+ AjaxAdapter.__super__.constructor.call(this, $element, options);
+ }
+
+ Utils.Extend(AjaxAdapter, ArrayAdapter);
+
+ AjaxAdapter.prototype._applyDefaults = function (options) {
+ var defaults = {
+ data: function (params) {
+ return $.extend({}, params, {
+ q: params.term
+ });
+ },
+ transport: function (params, success, failure) {
+ var $request = $.ajax(params);
+
+ $request.then(success);
+ $request.fail(failure);
+
+ return $request;
+ }
+ };
+
+ return $.extend({}, defaults, options, true);
+ };
+
+ AjaxAdapter.prototype.processResults = function (results) {
+ return results;
+ };
+
+ AjaxAdapter.prototype.query = function (params, callback) {
+ var matches = [];
+ var self = this;
+
+ if (this._request != null) {
+ // JSONP requests cannot always be aborted
+ if ($.isFunction(this._request.abort)) {
+ this._request.abort();
+ }
+
+ this._request = null;
+ }
+
+ var options = $.extend({
+ type: 'GET'
+ }, this.ajaxOptions);
+
+ if (typeof options.url === 'function') {
+ options.url = options.url.call(this.$element, params);
+ }
+
+ if (typeof options.data === 'function') {
+ options.data = options.data.call(this.$element, params);
+ }
+
+ function request () {
+ var $request = options.transport(options, function (data) {
+ var results = self.processResults(data, params);
+
+ if (self.options.get('debug') && window.console && console.error) {
+ // Check to make sure that the response included a `results` key.
+ if (!results || !results.results || !$.isArray(results.results)) {
+ console.error(
+ 'Select2: The AJAX results did not return an array in the ' +
+ '`results` key of the response.'
+ );
+ }
+ }
+
+ callback(results);
+ }, function () {
+ // Attempt to detect if a request was aborted
+ // Only works if the transport exposes a status property
+ if ('status' in $request &&
+ ($request.status === 0 || $request.status === '0')) {
+ return;
+ }
+
+ self.trigger('results:message', {
+ message: 'errorLoading'
+ });
+ });
+
+ self._request = $request;
+ }
+
+ if (this.ajaxOptions.delay && params.term != null) {
+ if (this._queryTimeout) {
+ window.clearTimeout(this._queryTimeout);
+ }
+
+ this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
+ } else {
+ request();
+ }
+ };
+
+ return AjaxAdapter;
+});
+
+S2.define('select2/data/tags',[
+ 'jquery'
+], function ($) {
+ function Tags (decorated, $element, options) {
+ var tags = options.get('tags');
+
+ var createTag = options.get('createTag');
+
+ if (createTag !== undefined) {
+ this.createTag = createTag;
+ }
+
+ var insertTag = options.get('insertTag');
+
+ if (insertTag !== undefined) {
+ this.insertTag = insertTag;
+ }
+
+ decorated.call(this, $element, options);
+
+ if ($.isArray(tags)) {
+ for (var t = 0; t < tags.length; t++) {
+ var tag = tags[t];
+ var item = this._normalizeItem(tag);
+
+ var $option = this.option(item);
+
+ this.$element.append($option);
+ }
+ }
+ }
+
+ Tags.prototype.query = function (decorated, params, callback) {
+ var self = this;
+
+ this._removeOldTags();
+
+ if (params.term == null || params.page != null) {
+ decorated.call(this, params, callback);
+ return;
+ }
+
+ function wrapper (obj, child) {
+ var data = obj.results;
+
+ for (var i = 0; i < data.length; i++) {
+ var option = data[i];
+
+ var checkChildren = (
+ option.children != null &&
+ !wrapper({
+ results: option.children
+ }, true)
+ );
+
+ var optionText = (option.text || '').toUpperCase();
+ var paramsTerm = (params.term || '').toUpperCase();
+
+ var checkText = optionText === paramsTerm;
+
+ if (checkText || checkChildren) {
+ if (child) {
+ return false;
+ }
+
+ obj.data = data;
+ callback(obj);
+
+ return;
+ }
+ }
+
+ if (child) {
+ return true;
+ }
+
+ var tag = self.createTag(params);
+
+ if (tag != null) {
+ var $option = self.option(tag);
+ $option.attr('data-select2-tag', true);
+
+ self.addOptions([$option]);
+
+ self.insertTag(data, tag);
+ }
+
+ obj.results = data;
+
+ callback(obj);
+ }
+
+ decorated.call(this, params, wrapper);
+ };
+
+ Tags.prototype.createTag = function (decorated, params) {
+ var term = $.trim(params.term);
+
+ if (term === '') {
+ return null;
+ }
+
+ return {
+ id: term,
+ text: term
+ };
+ };
+
+ Tags.prototype.insertTag = function (_, data, tag) {
+ data.unshift(tag);
+ };
+
+ Tags.prototype._removeOldTags = function (_) {
+ var tag = this._lastTag;
+
+ var $options = this.$element.find('option[data-select2-tag]');
+
+ $options.each(function () {
+ if (this.selected) {
+ return;
+ }
+
+ $(this).remove();
+ });
+ };
+
+ return Tags;
+});
+
+S2.define('select2/data/tokenizer',[
+ 'jquery'
+], function ($) {
+ function Tokenizer (decorated, $element, options) {
+ var tokenizer = options.get('tokenizer');
+
+ if (tokenizer !== undefined) {
+ this.tokenizer = tokenizer;
+ }
+
+ decorated.call(this, $element, options);
+ }
+
+ Tokenizer.prototype.bind = function (decorated, container, $container) {
+ decorated.call(this, container, $container);
+
+ this.$search = container.dropdown.$search || container.selection.$search ||
+ $container.find('.select2-search__field');
+ };
+
+ Tokenizer.prototype.query = function (decorated, params, callback) {
+ var self = this;
+
+ function createAndSelect (data) {
+ // Normalize the data object so we can use it for checks
+ var item = self._normalizeItem(data);
+
+ // Check if the data object already exists as a tag
+ // Select it if it doesn't
+ var $existingOptions = self.$element.find('option').filter(function () {
+ return $(this).val() === item.id;
+ });
+
+ // If an existing option wasn't found for it, create the option
+ if (!$existingOptions.length) {
+ var $option = self.option(item);
+ $option.attr('data-select2-tag', true);
+
+ self._removeOldTags();
+ self.addOptions([$option]);
+ }
+
+ // Select the item, now that we know there is an option for it
+ select(item);
+ }
+
+ function select (data) {
+ self.trigger('select', {
+ data: data
+ });
+ }
+
+ params.term = params.term || '';
+
+ var tokenData = this.tokenizer(params, this.options, createAndSelect);
+
+ if (tokenData.term !== params.term) {
+ // Replace the search term if we have the search box
+ if (this.$search.length) {
+ this.$search.val(tokenData.term);
+ this.$search.focus();
+ }
+
+ params.term = tokenData.term;
+ }
+
+ decorated.call(this, params, callback);
+ };
+
+ Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
+ var separators = options.get('tokenSeparators') || [];
+ var term = params.term;
+ var i = 0;
+
+ var createTag = this.createTag || function (params) {
+ return {
+ id: params.term,
+ text: params.term
+ };
+ };
+
+ while (i < term.length) {
+ var termChar = term[i];
+
+ if ($.inArray(termChar, separators) === -1) {
+ i++;
+
+ continue;
+ }
+
+ var part = term.substr(0, i);
+ var partParams = $.extend({}, params, {
+ term: part
+ });
+
+ var data = createTag(partParams);
+
+ if (data == null) {
+ i++;
+ continue;
+ }
+
+ callback(data);
+
+ // Reset the term to not include the tokenized portion
+ term = term.substr(i + 1) || '';
+ i = 0;
+ }
+
+ return {
+ term: term
+ };
+ };
+
+ return Tokenizer;
+});
+
+S2.define('select2/data/minimumInputLength',[
+
+], function () {
+ function MinimumInputLength (decorated, $e, options) {
+ this.minimumInputLength = options.get('minimumInputLength');
+
+ decorated.call(this, $e, options);
+ }
+
+ MinimumInputLength.prototype.query = function (decorated, params, callback) {
+ params.term = params.term || '';
+
+ if (params.term.length < this.minimumInputLength) {
+ this.trigger('results:message', {
+ message: 'inputTooShort',
+ args: {
+ minimum: this.minimumInputLength,
+ input: params.term,
+ params: params
+ }
+ });
+
+ return;
+ }
+
+ decorated.call(this, params, callback);
+ };
+
+ return MinimumInputLength;
+});
+
+S2.define('select2/data/maximumInputLength',[
+
+], function () {
+ function MaximumInputLength (decorated, $e, options) {
+ this.maximumInputLength = options.get('maximumInputLength');
+
+ decorated.call(this, $e, options);
+ }
+
+ MaximumInputLength.prototype.query = function (decorated, params, callback) {
+ params.term = params.term || '';
+
+ if (this.maximumInputLength > 0 &&
+ params.term.length > this.maximumInputLength) {
+ this.trigger('results:message', {
+ message: 'inputTooLong',
+ args: {
+ maximum: this.maximumInputLength,
+ input: params.term,
+ params: params
+ }
+ });
+
+ return;
+ }
+
+ decorated.call(this, params, callback);
+ };
+
+ return MaximumInputLength;
+});
+
+S2.define('select2/data/maximumSelectionLength',[
+
+], function (){
+ function MaximumSelectionLength (decorated, $e, options) {
+ this.maximumSelectionLength = options.get('maximumSelectionLength');
+
+ decorated.call(this, $e, options);
+ }
+
+ MaximumSelectionLength.prototype.query =
+ function (decorated, params, callback) {
+ var self = this;
+
+ this.current(function (currentData) {
+ var count = currentData != null ? currentData.length : 0;
+ if (self.maximumSelectionLength > 0 &&
+ count >= self.maximumSelectionLength) {
+ self.trigger('results:message', {
+ message: 'maximumSelected',
+ args: {
+ maximum: self.maximumSelectionLength
+ }
+ });
+ return;
+ }
+ decorated.call(self, params, callback);
+ });
+ };
+
+ return MaximumSelectionLength;
+});
+
+S2.define('select2/dropdown',[
+ 'jquery',
+ './utils'
+], function ($, Utils) {
+ function Dropdown ($element, options) {
+ this.$element = $element;
+ this.options = options;
+
+ Dropdown.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(Dropdown, Utils.Observable);
+
+ Dropdown.prototype.render = function () {
+ var $dropdown = $(
+ '<span class="select2-dropdown">' +
+ '<span class="select2-results"></span>' +
+ '</span>'
+ );
+
+ $dropdown.attr('dir', this.options.get('dir'));
+
+ this.$dropdown = $dropdown;
+
+ return $dropdown;
+ };
+
+ Dropdown.prototype.bind = function () {
+ // Should be implemented in subclasses
+ };
+
+ Dropdown.prototype.position = function ($dropdown, $container) {
+ // Should be implmented in subclasses
+ };
+
+ Dropdown.prototype.destroy = function () {
+ // Remove the dropdown from the DOM
+ this.$dropdown.remove();
+ };
+
+ return Dropdown;
+});
+
+S2.define('select2/dropdown/search',[
+ 'jquery',
+ '../utils'
+], function ($, Utils) {
+ function Search () { }
+
+ Search.prototype.render = function (decorated) {
+ var $rendered = decorated.call(this);
+
+ var $search = $(
+ '<span class="select2-search select2-search--dropdown">' +
+ '<input class="select2-search__field" type="search" tabindex="-1"' +
+ ' autocomplete="off" autocorrect="off" autocapitalize="none"' +
+ ' spellcheck="false" role="textbox" />' +
+ '</span>'
+ );
+
+ this.$searchContainer = $search;
+ this.$search = $search.find('input');
+
+ $rendered.prepend($search);
+
+ return $rendered;
+ };
+
+ Search.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ this.$search.on('keydown', function (evt) {
+ self.trigger('keypress', evt);
+
+ self._keyUpPrevented = evt.isDefaultPrevented();
+ });
+
+ // Workaround for browsers which do not support the `input` event
+ // This will prevent double-triggering of events for browsers which support
+ // both the `keyup` and `input` events.
+ this.$search.on('input', function (evt) {
+ // Unbind the duplicated `keyup` event
+ $(this).off('keyup');
+ });
+
+ this.$search.on('keyup input', function (evt) {
+ self.handleSearch(evt);
+ });
+
+ container.on('open', function () {
+ self.$search.attr('tabindex', 0);
+
+ self.$search.focus();
+
+ window.setTimeout(function () {
+ self.$search.focus();
+ }, 0);
+ });
+
+ container.on('close', function () {
+ self.$search.attr('tabindex', -1);
+
+ self.$search.val('');
+ self.$search.blur();
+ });
+
+ container.on('focus', function () {
+ if (!container.isOpen()) {
+ self.$search.focus();
+ }
+ });
+
+ container.on('results:all', function (params) {
+ if (params.query.term == null || params.query.term === '') {
+ var showSearch = self.showSearch(params);
+
+ if (showSearch) {
+ self.$searchContainer.removeClass('select2-search--hide');
+ } else {
+ self.$searchContainer.addClass('select2-search--hide');
+ }
+ }
+ });
+ };
+
+ Search.prototype.handleSearch = function (evt) {
+ if (!this._keyUpPrevented) {
+ var input = this.$search.val();
+
+ this.trigger('query', {
+ term: input
+ });
+ }
+
+ this._keyUpPrevented = false;
+ };
+
+ Search.prototype.showSearch = function (_, params) {
+ return true;
+ };
+
+ return Search;
+});
+
+S2.define('select2/dropdown/hidePlaceholder',[
+
+], function () {
+ function HidePlaceholder (decorated, $element, options, dataAdapter) {
+ this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
+
+ decorated.call(this, $element, options, dataAdapter);
+ }
+
+ HidePlaceholder.prototype.append = function (decorated, data) {
+ data.results = this.removePlaceholder(data.results);
+
+ decorated.call(this, data);
+ };
+
+ HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
+ if (typeof placeholder === 'string') {
+ placeholder = {
+ id: '',
+ text: placeholder
+ };
+ }
+
+ return placeholder;
+ };
+
+ HidePlaceholder.prototype.removePlaceholder = function (_, data) {
+ var modifiedData = data.slice(0);
+
+ for (var d = data.length - 1; d >= 0; d--) {
+ var item = data[d];
+
+ if (this.placeholder.id === item.id) {
+ modifiedData.splice(d, 1);
+ }
+ }
+
+ return modifiedData;
+ };
+
+ return HidePlaceholder;
+});
+
+S2.define('select2/dropdown/infiniteScroll',[
+ 'jquery'
+], function ($) {
+ function InfiniteScroll (decorated, $element, options, dataAdapter) {
+ this.lastParams = {};
+
+ decorated.call(this, $element, options, dataAdapter);
+
+ this.$loadingMore = this.createLoadingMore();
+ this.loading = false;
+ }
+
+ InfiniteScroll.prototype.append = function (decorated, data) {
+ this.$loadingMore.remove();
+ this.loading = false;
+
+ decorated.call(this, data);
+
+ if (this.showLoadingMore(data)) {
+ this.$results.append(this.$loadingMore);
+ }
+ };
+
+ InfiniteScroll.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ container.on('query', function (params) {
+ self.lastParams = params;
+ self.loading = true;
+ });
+
+ container.on('query:append', function (params) {
+ self.lastParams = params;
+ self.loading = true;
+ });
+
+ this.$results.on('scroll', function () {
+ var isLoadMoreVisible = $.contains(
+ document.documentElement,
+ self.$loadingMore[0]
+ );
+
+ if (self.loading || !isLoadMoreVisible) {
+ return;
+ }
+
+ var currentOffset = self.$results.offset().top +
+ self.$results.outerHeight(false);
+ var loadingMoreOffset = self.$loadingMore.offset().top +
+ self.$loadingMore.outerHeight(false);
+
+ if (currentOffset + 50 >= loadingMoreOffset) {
+ self.loadMore();
+ }
+ });
+ };
+
+ InfiniteScroll.prototype.loadMore = function () {
+ this.loading = true;
+
+ var params = $.extend({}, {page: 1}, this.lastParams);
+
+ params.page++;
+
+ this.trigger('query:append', params);
+ };
+
+ InfiniteScroll.prototype.showLoadingMore = function (_, data) {
+ return data.pagination && data.pagination.more;
+ };
+
+ InfiniteScroll.prototype.createLoadingMore = function () {
+ var $option = $(
+ '<li ' +
+ 'class="select2-results__option select2-results__option--load-more"' +
+ 'role="treeitem" aria-disabled="true"></li>'
+ );
+
+ var message = this.options.get('translations').get('loadingMore');
+
+ $option.html(message(this.lastParams));
+
+ return $option;
+ };
+
+ return InfiniteScroll;
+});
+
+S2.define('select2/dropdown/attachBody',[
+ 'jquery',
+ '../utils'
+], function ($, Utils) {
+ function AttachBody (decorated, $element, options) {
+ this.$dropdownParent = options.get('dropdownParent') || $(document.body);
+
+ decorated.call(this, $element, options);
+ }
+
+ AttachBody.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ var setupResultsEvents = false;
+
+ decorated.call(this, container, $container);
+
+ container.on('open', function () {
+ self._showDropdown();
+ self._attachPositioningHandler(container);
+
+ if (!setupResultsEvents) {
+ setupResultsEvents = true;
+
+ container.on('results:all', function () {
+ self._positionDropdown();
+ self._resizeDropdown();
+ });
+
+ container.on('results:append', function () {
+ self._positionDropdown();
+ self._resizeDropdown();
+ });
+ }
+ });
+
+ container.on('close', function () {
+ self._hideDropdown();
+ self._detachPositioningHandler(container);
+ });
+
+ this.$dropdownContainer.on('mousedown', function (evt) {
+ evt.stopPropagation();
+ });
+ };
+
+ AttachBody.prototype.destroy = function (decorated) {
+ decorated.call(this);
+
+ this.$dropdownContainer.remove();
+ };
+
+ AttachBody.prototype.position = function (decorated, $dropdown, $container) {
+ // Clone all of the container classes
+ $dropdown.attr('class', $container.attr('class'));
+
+ $dropdown.removeClass('select2');
+ $dropdown.addClass('select2-container--open');
+
+ $dropdown.css({
+ position: 'absolute',
+ top: -999999
+ });
+
+ this.$container = $container;
+ };
+
+ AttachBody.prototype.render = function (decorated) {
+ var $container = $('<span></span>');
+
+ var $dropdown = decorated.call(this);
+ $container.append($dropdown);
+
+ this.$dropdownContainer = $container;
+
+ return $container;
+ };
+
+ AttachBody.prototype._hideDropdown = function (decorated) {
+ this.$dropdownContainer.detach();
+ };
+
+ AttachBody.prototype._attachPositioningHandler =
+ function (decorated, container) {
+ var self = this;
+
+ var scrollEvent = 'scroll.select2.' + container.id;
+ var resizeEvent = 'resize.select2.' + container.id;
+ var orientationEvent = 'orientationchange.select2.' + container.id;
+
+ var $watchers = this.$container.parents().filter(Utils.hasScroll);
+ $watchers.each(function () {
+ Utils.StoreData(this, 'select2-scroll-position', {
+ x: $(this).scrollLeft(),
+ y: $(this).scrollTop()
+ });
+ });
+
+ $watchers.on(scrollEvent, function (ev) {
+ var position = Utils.GetData(this, 'select2-scroll-position');
+ $(this).scrollTop(position.y);
+ });
+
+ $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
+ function (e) {
+ self._positionDropdown();
+ self._resizeDropdown();
+ });
+ };
+
+ AttachBody.prototype._detachPositioningHandler =
+ function (decorated, container) {
+ var scrollEvent = 'scroll.select2.' + container.id;
+ var resizeEvent = 'resize.select2.' + container.id;
+ var orientationEvent = 'orientationchange.select2.' + container.id;
+
+ var $watchers = this.$container.parents().filter(Utils.hasScroll);
+ $watchers.off(scrollEvent);
+
+ $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
+ };
+
+ AttachBody.prototype._positionDropdown = function () {
+ var $window = $(window);
+
+ var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
+ var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
+
+ var newDirection = null;
+
+ var offset = this.$container.offset();
+
+ offset.bottom = offset.top + this.$container.outerHeight(false);
+
+ var container = {
+ height: this.$container.outerHeight(false)
+ };
+
+ container.top = offset.top;
+ container.bottom = offset.top + container.height;
+
+ var dropdown = {
+ height: this.$dropdown.outerHeight(false)
+ };
+
+ var viewport = {
+ top: $window.scrollTop(),
+ bottom: $window.scrollTop() + $window.height()
+ };
+
+ var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
+ var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
+
+ var css = {
+ left: offset.left,
+ top: container.bottom
+ };
+
+ // Determine what the parent element is to use for calciulating the offset
+ var $offsetParent = this.$dropdownParent;
+
+ // For statically positoned elements, we need to get the element
+ // that is determining the offset
+ if ($offsetParent.css('position') === 'static') {
+ $offsetParent = $offsetParent.offsetParent();
+ }
+
+ var parentOffset = $offsetParent.offset();
+
+ css.top -= parentOffset.top;
+ css.left -= parentOffset.left;
+
+ if (!isCurrentlyAbove && !isCurrentlyBelow) {
+ newDirection = 'below';
+ }
+
+ if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
+ newDirection = 'above';
+ } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
+ newDirection = 'below';
+ }
+
+ if (newDirection == 'above' ||
+ (isCurrentlyAbove && newDirection !== 'below')) {
+ css.top = container.top - parentOffset.top - dropdown.height;
+ }
+
+ if (newDirection != null) {
+ this.$dropdown
+ .removeClass('select2-dropdown--below select2-dropdown--above')
+ .addClass('select2-dropdown--' + newDirection);
+ this.$container
+ .removeClass('select2-container--below select2-container--above')
+ .addClass('select2-container--' + newDirection);
+ }
+
+ this.$dropdownContainer.css(css);
+ };
+
+ AttachBody.prototype._resizeDropdown = function () {
+ var css = {
+ width: this.$container.outerWidth(false) + 'px'
+ };
+
+ if (this.options.get('dropdownAutoWidth')) {
+ css.minWidth = css.width;
+ css.position = 'relative';
+ css.width = 'auto';
+ }
+
+ this.$dropdown.css(css);
+ };
+
+ AttachBody.prototype._showDropdown = function (decorated) {
+ this.$dropdownContainer.appendTo(this.$dropdownParent);
+
+ this._positionDropdown();
+ this._resizeDropdown();
+ };
+
+ return AttachBody;
+});
+
+S2.define('select2/dropdown/minimumResultsForSearch',[
+
+], function () {
+ function countResults (data) {
+ var count = 0;
+
+ for (var d = 0; d < data.length; d++) {
+ var item = data[d];
+
+ if (item.children) {
+ count += countResults(item.children);
+ } else {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {
+ this.minimumResultsForSearch = options.get('minimumResultsForSearch');
+
+ if (this.minimumResultsForSearch < 0) {
+ this.minimumResultsForSearch = Infinity;
+ }
+
+ decorated.call(this, $element, options, dataAdapter);
+ }
+
+ MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
+ if (countResults(params.data.results) < this.minimumResultsForSearch) {
+ return false;
+ }
+
+ return decorated.call(this, params);
+ };
+
+ return MinimumResultsForSearch;
+});
+
+S2.define('select2/dropdown/selectOnClose',[
+ '../utils'
+], function (Utils) {
+ function SelectOnClose () { }
+
+ SelectOnClose.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ container.on('close', function (params) {
+ self._handleSelectOnClose(params);
+ });
+ };
+
+ SelectOnClose.prototype._handleSelectOnClose = function (_, params) {
+ if (params && params.originalSelect2Event != null) {
+ var event = params.originalSelect2Event;
+
+ // Don't select an item if the close event was triggered from a select or
+ // unselect event
+ if (event._type === 'select' || event._type === 'unselect') {
+ return;
+ }
+ }
+
+ var $highlightedResults = this.getHighlightedResults();
+
+ // Only select highlighted results
+ if ($highlightedResults.length < 1) {
+ return;
+ }
+
+ var data = Utils.GetData($highlightedResults[0], 'data');
+
+ // Don't re-select already selected resulte
+ if (
+ (data.element != null && data.element.selected) ||
+ (data.element == null && data.selected)
+ ) {
+ return;
+ }
+
+ this.trigger('select', {
+ data: data
+ });
+ };
+
+ return SelectOnClose;
+});
+
+S2.define('select2/dropdown/closeOnSelect',[
+
+], function () {
+ function CloseOnSelect () { }
+
+ CloseOnSelect.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ container.on('select', function (evt) {
+ self._selectTriggered(evt);
+ });
+
+ container.on('unselect', function (evt) {
+ self._selectTriggered(evt);
+ });
+ };
+
+ CloseOnSelect.prototype._selectTriggered = function (_, evt) {
+ var originalEvent = evt.originalEvent;
+
+ // Don't close if the control key is being held
+ if (originalEvent && originalEvent.ctrlKey) {
+ return;
+ }
+
+ this.trigger('close', {
+ originalEvent: originalEvent,
+ originalSelect2Event: evt
+ });
+ };
+
+ return CloseOnSelect;
+});
+
+S2.define('select2/i18n/en',[],function () {
+ // English
+ return {
+ errorLoading: function () {
+ return 'The results could not be loaded.';
+ },
+ inputTooLong: function (args) {
+ var overChars = args.input.length - args.maximum;
+
+ var message = 'Please delete ' + overChars + ' character';
+
+ if (overChars != 1) {
+ message += 's';
+ }
+
+ return message;
+ },
+ inputTooShort: function (args) {
+ var remainingChars = args.minimum - args.input.length;
+
+ var message = 'Please enter ' + remainingChars + ' or more characters';
+
+ return message;
+ },
+ loadingMore: function () {
+ return 'Loading more results…';
+ },
+ maximumSelected: function (args) {
+ var message = 'You can only select ' + args.maximum + ' item';
+
+ if (args.maximum != 1) {
+ message += 's';
+ }
+
+ return message;
+ },
+ noResults: function () {
+ return 'No results found';
+ },
+ searching: function () {
+ return 'Searching…';
+ }
+ };
+});
+
+S2.define('select2/defaults',[
+ 'jquery',
+ 'require',
+
+ './results',
+
+ './selection/single',
+ './selection/multiple',
+ './selection/placeholder',
+ './selection/allowClear',
+ './selection/search',
+ './selection/eventRelay',
+
+ './utils',
+ './translation',
+ './diacritics',
+
+ './data/select',
+ './data/array',
+ './data/ajax',
+ './data/tags',
+ './data/tokenizer',
+ './data/minimumInputLength',
+ './data/maximumInputLength',
+ './data/maximumSelectionLength',
+
+ './dropdown',
+ './dropdown/search',
+ './dropdown/hidePlaceholder',
+ './dropdown/infiniteScroll',
+ './dropdown/attachBody',
+ './dropdown/minimumResultsForSearch',
+ './dropdown/selectOnClose',
+ './dropdown/closeOnSelect',
+
+ './i18n/en'
+], function ($, require,
+
+ ResultsList,
+
+ SingleSelection, MultipleSelection, Placeholder, AllowClear,
+ SelectionSearch, EventRelay,
+
+ Utils, Translation, DIACRITICS,
+
+ SelectData, ArrayData, AjaxData, Tags, Tokenizer,
+ MinimumInputLength, MaximumInputLength, MaximumSelectionLength,
+
+ Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
+ AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,
+
+ EnglishTranslation) {
+ function Defaults () {
+ this.reset();
+ }
+
+ Defaults.prototype.apply = function (options) {
+ options = $.extend(true, {}, this.defaults, options);
+
+ if (options.dataAdapter == null) {
+ if (options.ajax != null) {
+ options.dataAdapter = AjaxData;
+ } else if (options.data != null) {
+ options.dataAdapter = ArrayData;
+ } else {
+ options.dataAdapter = SelectData;
+ }
+
+ if (options.minimumInputLength > 0) {
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ MinimumInputLength
+ );
+ }
+
+ if (options.maximumInputLength > 0) {
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ MaximumInputLength
+ );
+ }
+
+ if (options.maximumSelectionLength > 0) {
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ MaximumSelectionLength
+ );
+ }
+
+ if (options.tags) {
+ options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
+ }
+
+ if (options.tokenSeparators != null || options.tokenizer != null) {
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ Tokenizer
+ );
+ }
+
+ if (options.query != null) {
+ var Query = require(options.amdBase + 'compat/query');
+
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ Query
+ );
+ }
+
+ if (options.initSelection != null) {
+ var InitSelection = require(options.amdBase + 'compat/initSelection');
+
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ InitSelection
+ );
+ }
+ }
+
+ if (options.resultsAdapter == null) {
+ options.resultsAdapter = ResultsList;
+
+ if (options.ajax != null) {
+ options.resultsAdapter = Utils.Decorate(
+ options.resultsAdapter,
+ InfiniteScroll
+ );
+ }
+
+ if (options.placeholder != null) {
+ options.resultsAdapter = Utils.Decorate(
+ options.resultsAdapter,
+ HidePlaceholder
+ );
+ }
+
+ if (options.selectOnClose) {
+ options.resultsAdapter = Utils.Decorate(
+ options.resultsAdapter,
+ SelectOnClose
+ );
+ }
+ }
+
+ if (options.dropdownAdapter == null) {
+ if (options.multiple) {
+ options.dropdownAdapter = Dropdown;
+ } else {
+ var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);
+
+ options.dropdownAdapter = SearchableDropdown;
+ }
+
+ if (options.minimumResultsForSearch !== 0) {
+ options.dropdownAdapter = Utils.Decorate(
+ options.dropdownAdapter,
+ MinimumResultsForSearch
+ );
+ }
+
+ if (options.closeOnSelect) {
+ options.dropdownAdapter = Utils.Decorate(
+ options.dropdownAdapter,
+ CloseOnSelect
+ );
+ }
+
+ if (
+ options.dropdownCssClass != null ||
+ options.dropdownCss != null ||
+ options.adaptDropdownCssClass != null
+ ) {
+ var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');
+
+ options.dropdownAdapter = Utils.Decorate(
+ options.dropdownAdapter,
+ DropdownCSS
+ );
+ }
+
+ options.dropdownAdapter = Utils.Decorate(
+ options.dropdownAdapter,
+ AttachBody
+ );
+ }
+
+ if (options.selectionAdapter == null) {
+ if (options.multiple) {
+ options.selectionAdapter = MultipleSelection;
+ } else {
+ options.selectionAdapter = SingleSelection;
+ }
+
+ // Add the placeholder mixin if a placeholder was specified
+ if (options.placeholder != null) {
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ Placeholder
+ );
+ }
+
+ if (options.allowClear) {
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ AllowClear
+ );
+ }
+
+ if (options.multiple) {
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ SelectionSearch
+ );
+ }
+
+ if (
+ options.containerCssClass != null ||
+ options.containerCss != null ||
+ options.adaptContainerCssClass != null
+ ) {
+ var ContainerCSS = require(options.amdBase + 'compat/containerCss');
+
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ ContainerCSS
+ );
+ }
+
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ EventRelay
+ );
+ }
+
+ if (typeof options.language === 'string') {
+ // Check if the language is specified with a region
+ if (options.language.indexOf('-') > 0) {
+ // Extract the region information if it is included
+ var languageParts = options.language.split('-');
+ var baseLanguage = languageParts[0];
+
+ options.language = [options.language, baseLanguage];
+ } else {
+ options.language = [options.language];
+ }
+ }
+
+ if ($.isArray(options.language)) {
+ var languages = new Translation();
+ options.language.push('en');
+
+ var languageNames = options.language;
+
+ for (var l = 0; l < languageNames.length; l++) {
+ var name = languageNames[l];
+ var language = {};
+
+ try {
+ // Try to load it with the original name
+ language = Translation.loadPath(name);
+ } catch (e) {
+ try {
+ // If we couldn't load it, check if it wasn't the full path
+ name = this.defaults.amdLanguageBase + name;
+ language = Translation.loadPath(name);
+ } catch (ex) {
+ // The translation could not be loaded at all. Sometimes this is
+ // because of a configuration problem, other times this can be
+ // because of how Select2 helps load all possible translation files.
+ if (options.debug && window.console && console.warn) {
+ console.warn(
+ 'Select2: The language file for "' + name + '" could not be ' +
+ 'automatically loaded. A fallback will be used instead.'
+ );
+ }
+
+ continue;
+ }
+ }
+
+ languages.extend(language);
+ }
+
+ options.translations = languages;
+ } else {
+ var baseTranslation = Translation.loadPath(
+ this.defaults.amdLanguageBase + 'en'
+ );
+ var customTranslation = new Translation(options.language);
+
+ customTranslation.extend(baseTranslation);
+
+ options.translations = customTranslation;
+ }
+
+ return options;
+ };
+
+ Defaults.prototype.reset = function () {
+ function stripDiacritics (text) {
+ // Used 'uni range + named function' from http://jsperf.com/diacritics/18
+ function match(a) {
+ return DIACRITICS[a] || a;
+ }
+
+ return text.replace(/[^\u0000-\u007E]/g, match);
+ }
+
+ function matcher (params, data) {
+ // Always return the object if there is nothing to compare
+ if ($.trim(params.term) === '') {
+ return data;
+ }
+
+ // Do a recursive check for options with children
+ if (data.children && data.children.length > 0) {
+ // Clone the data object if there are children
+ // This is required as we modify the object to remove any non-matches
+ var match = $.extend(true, {}, data);
+
+ // Check each child of the option
+ for (var c = data.children.length - 1; c >= 0; c--) {
+ var child = data.children[c];
+
+ var matches = matcher(params, child);
+
+ // If there wasn't a match, remove the object in the array
+ if (matches == null) {
+ match.children.splice(c, 1);
+ }
+ }
+
+ // If any children matched, return the new object
+ if (match.children.length > 0) {
+ return match;
+ }
+
+ // If there were no matching children, check just the plain object
+ return matcher(params, match);
+ }
+
+ var original = stripDiacritics(data.text).toUpperCase();
+ var term = stripDiacritics(params.term).toUpperCase();
+
+ // Check if the text contains the term
+ if (original.indexOf(term) > -1) {
+ return data;
+ }
+
+ // If it doesn't contain the term, don't return anything
+ return null;
+ }
+
+ this.defaults = {
+ amdBase: './',
+ amdLanguageBase: './i18n/',
+ closeOnSelect: true,
+ debug: false,
+ dropdownAutoWidth: false,
+ escapeMarkup: Utils.escapeMarkup,
+ language: EnglishTranslation,
+ matcher: matcher,
+ minimumInputLength: 0,
+ maximumInputLength: 0,
+ maximumSelectionLength: 0,
+ minimumResultsForSearch: 0,
+ selectOnClose: false,
+ sorter: function (data) {
+ return data;
+ },
+ templateResult: function (result) {
+ return result.text;
+ },
+ templateSelection: function (selection) {
+ return selection.text;
+ },
+ theme: 'default',
+ width: 'resolve'
+ };
+ };
+
+ Defaults.prototype.set = function (key, value) {
+ var camelKey = $.camelCase(key);
+
+ var data = {};
+ data[camelKey] = value;
+
+ var convertedData = Utils._convertData(data);
+
+ $.extend(true, this.defaults, convertedData);
+ };
+
+ var defaults = new Defaults();
+
+ return defaults;
+});
+
+S2.define('select2/options',[
+ 'require',
+ 'jquery',
+ './defaults',
+ './utils'
+], function (require, $, Defaults, Utils) {
+ function Options (options, $element) {
+ this.options = options;
+
+ if ($element != null) {
+ this.fromElement($element);
+ }
+
+ this.options = Defaults.apply(this.options);
+
+ if ($element && $element.is('input')) {
+ var InputCompat = require(this.get('amdBase') + 'compat/inputData');
+
+ this.options.dataAdapter = Utils.Decorate(
+ this.options.dataAdapter,
+ InputCompat
+ );
+ }
+ }
+
+ Options.prototype.fromElement = function ($e) {
+ var excludedData = ['select2'];
+
+ if (this.options.multiple == null) {
+ this.options.multiple = $e.prop('multiple');
+ }
+
+ if (this.options.disabled == null) {
+ this.options.disabled = $e.prop('disabled');
+ }
+
+ if (this.options.language == null) {
+ if ($e.prop('lang')) {
+ this.options.language = $e.prop('lang').toLowerCase();
+ } else if ($e.closest('[lang]').prop('lang')) {
+ this.options.language = $e.closest('[lang]').prop('lang');
+ }
+ }
+
+ if (this.options.dir == null) {
+ if ($e.prop('dir')) {
+ this.options.dir = $e.prop('dir');
+ } else if ($e.closest('[dir]').prop('dir')) {
+ this.options.dir = $e.closest('[dir]').prop('dir');
+ } else {
+ this.options.dir = 'ltr';
+ }
+ }
+
+ $e.prop('disabled', this.options.disabled);
+ $e.prop('multiple', this.options.multiple);
+
+ if (Utils.GetData($e[0], 'select2Tags')) {
+ if (this.options.debug && window.console && console.warn) {
+ console.warn(
+ 'Select2: The `data-select2-tags` attribute has been changed to ' +
+ 'use the `data-data` and `data-tags="true"` attributes and will be ' +
+ 'removed in future versions of Select2.'
+ );
+ }
+
+ Utils.StoreData($e[0], 'data', Utils.GetData($e[0], 'select2Tags'));
+ Utils.StoreData($e[0], 'tags', true);
+ }
+
+ if (Utils.GetData($e[0], 'ajaxUrl')) {
+ if (this.options.debug && window.console && console.warn) {
+ console.warn(
+ 'Select2: The `data-ajax-url` attribute has been changed to ' +
+ '`data-ajax--url` and support for the old attribute will be removed' +
+ ' in future versions of Select2.'
+ );
+ }
+
+ $e.attr('ajax--url', Utils.GetData($e[0], 'ajaxUrl'));
+ Utils.StoreData($e[0], 'ajax-Url', Utils.GetData($e[0], 'ajaxUrl'));
+
+ }
+
+ var dataset = {};
+
+ // Prefer the element's `dataset` attribute if it exists
+ // jQuery 1.x does not correctly handle data attributes with multiple dashes
+ if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
+ dataset = $.extend(true, {}, $e[0].dataset, Utils.GetData($e[0]));
+ } else {
+ dataset = Utils.GetData($e[0]);
+ }
+
+ var data = $.extend(true, {}, dataset);
+
+ data = Utils._convertData(data);
+
+ for (var key in data) {
+ if ($.inArray(key, excludedData) > -1) {
+ continue;
+ }
+
+ if ($.isPlainObject(this.options[key])) {
+ $.extend(this.options[key], data[key]);
+ } else {
+ this.options[key] = data[key];
+ }
+ }
+
+ return this;
+ };
+
+ Options.prototype.get = function (key) {
+ return this.options[key];
+ };
+
+ Options.prototype.set = function (key, val) {
+ this.options[key] = val;
+ };
+
+ return Options;
+});
+
+S2.define('select2/core',[
+ 'jquery',
+ './options',
+ './utils',
+ './keys'
+], function ($, Options, Utils, KEYS) {
+ var Select2 = function ($element, options) {
+ if (Utils.GetData($element[0], 'select2') != null) {
+ Utils.GetData($element[0], 'select2').destroy();
+ }
+
+ this.$element = $element;
+
+ this.id = this._generateId($element);
+
+ options = options || {};
+
+ this.options = new Options(options, $element);
+
+ Select2.__super__.constructor.call(this);
+
+ // Set up the tabindex
+
+ var tabindex = $element.attr('tabindex') || 0;
+ Utils.StoreData($element[0], 'old-tabindex', tabindex);
+ $element.attr('tabindex', '-1');
+
+ // Set up containers and adapters
+
+ var DataAdapter = this.options.get('dataAdapter');
+ this.dataAdapter = new DataAdapter($element, this.options);
+
+ var $container = this.render();
+
+ this._placeContainer($container);
+
+ var SelectionAdapter = this.options.get('selectionAdapter');
+ this.selection = new SelectionAdapter($element, this.options);
+ this.$selection = this.selection.render();
+
+ this.selection.position(this.$selection, $container);
+
+ var DropdownAdapter = this.options.get('dropdownAdapter');
+ this.dropdown = new DropdownAdapter($element, this.options);
+ this.$dropdown = this.dropdown.render();
+
+ this.dropdown.position(this.$dropdown, $container);
+
+ var ResultsAdapter = this.options.get('resultsAdapter');
+ this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
+ this.$results = this.results.render();
+
+ this.results.position(this.$results, this.$dropdown);
+
+ // Bind events
+
+ var self = this;
+
+ // Bind the container to all of the adapters
+ this._bindAdapters();
+
+ // Register any DOM event handlers
+ this._registerDomEvents();
+
+ // Register any internal event handlers
+ this._registerDataEvents();
+ this._registerSelectionEvents();
+ this._registerDropdownEvents();
+ this._registerResultsEvents();
+ this._registerEvents();
+
+ // Set the initial state
+ this.dataAdapter.current(function (initialData) {
+ self.trigger('selection:update', {
+ data: initialData
+ });
+ });
+
+ // Hide the original select
+ $element.addClass('select2-hidden-accessible');
+ $element.attr('aria-hidden', 'true');
+
+ // Synchronize any monitored attributes
+ this._syncAttributes();
+
+ Utils.StoreData($element[0], 'select2', this);
+
+ // Ensure backwards compatibility with $element.data('select2').
+ $element.data('select2', this);
+ };
+
+ Utils.Extend(Select2, Utils.Observable);
+
+ Select2.prototype._generateId = function ($element) {
+ var id = '';
+
+ if ($element.attr('id') != null) {
+ id = $element.attr('id');
+ } else if ($element.attr('name') != null) {
+ id = $element.attr('name') + '-' + Utils.generateChars(2);
+ } else {
+ id = Utils.generateChars(4);
+ }
+
+ id = id.replace(/(:|\.|\[|\]|,)/g, '');
+ id = 'select2-' + id;
+
+ return id;
+ };
+
+ Select2.prototype._placeContainer = function ($container) {
+ $container.insertAfter(this.$element);
+
+ var width = this._resolveWidth(this.$element, this.options.get('width'));
+
+ if (width != null) {
+ $container.css('width', width);
+ }
+ };
+
+ Select2.prototype._resolveWidth = function ($element, method) {
+ var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
+
+ if (method == 'resolve') {
+ var styleWidth = this._resolveWidth($element, 'style');
+
+ if (styleWidth != null) {
+ return styleWidth;
+ }
+
+ return this._resolveWidth($element, 'element');
+ }
+
+ if (method == 'element') {
+ var elementWidth = $element.outerWidth(false);
+
+ if (elementWidth <= 0) {
+ return 'auto';
+ }
+
+ return elementWidth + 'px';
+ }
+
+ if (method == 'style') {
+ var style = $element.attr('style');
+
+ if (typeof(style) !== 'string') {
+ return null;
+ }
+
+ var attrs = style.split(';');
+
+ for (var i = 0, l = attrs.length; i < l; i = i + 1) {
+ var attr = attrs[i].replace(/\s/g, '');
+ var matches = attr.match(WIDTH);
+
+ if (matches !== null && matches.length >= 1) {
+ return matches[1];
+ }
+ }
+
+ return null;
+ }
+
+ return method;
+ };
+
+ Select2.prototype._bindAdapters = function () {
+ this.dataAdapter.bind(this, this.$container);
+ this.selection.bind(this, this.$container);
+
+ this.dropdown.bind(this, this.$container);
+ this.results.bind(this, this.$container);
+ };
+
+ Select2.prototype._registerDomEvents = function () {
+ var self = this;
+
+ this.$element.on('change.select2', function () {
+ self.dataAdapter.current(function (data) {
+ self.trigger('selection:update', {
+ data: data
+ });
+ });
+ });
+
+ this.$element.on('focus.select2', function (evt) {
+ self.trigger('focus', evt);
+ });
+
+ this._syncA = Utils.bind(this._syncAttributes, this);
+ this._syncS = Utils.bind(this._syncSubtree, this);
+
+ if (this.$element[0].attachEvent) {
+ this.$element[0].attachEvent('onpropertychange', this._syncA);
+ }
+
+ var observer = window.MutationObserver ||
+ window.WebKitMutationObserver ||
+ window.MozMutationObserver
+ ;
+
+ if (observer != null) {
+ this._observer = new observer(function (mutations) {
+ $.each(mutations, self._syncA);
+ $.each(mutations, self._syncS);
+ });
+ this._observer.observe(this.$element[0], {
+ attributes: true,
+ childList: true,
+ subtree: false
+ });
+ } else if (this.$element[0].addEventListener) {
+ this.$element[0].addEventListener(
+ 'DOMAttrModified',
+ self._syncA,
+ false
+ );
+ this.$element[0].addEventListener(
+ 'DOMNodeInserted',
+ self._syncS,
+ false
+ );
+ this.$element[0].addEventListener(
+ 'DOMNodeRemoved',
+ self._syncS,
+ false
+ );
+ }
+ };
+
+ Select2.prototype._registerDataEvents = function () {
+ var self = this;
+
+ this.dataAdapter.on('*', function (name, params) {
+ self.trigger(name, params);
+ });
+ };
+
+ Select2.prototype._registerSelectionEvents = function () {
+ var self = this;
+ var nonRelayEvents = ['toggle', 'focus'];
+
+ this.selection.on('toggle', function () {
+ self.toggleDropdown();
+ });
+
+ this.selection.on('focus', function (params) {
+ self.focus(params);
+ });
+
+ this.selection.on('*', function (name, params) {
+ if ($.inArray(name, nonRelayEvents) !== -1) {
+ return;
+ }
+
+ self.trigger(name, params);
+ });
+ };
+
+ Select2.prototype._registerDropdownEvents = function () {
+ var self = this;
+
+ this.dropdown.on('*', function (name, params) {
+ self.trigger(name, params);
+ });
+ };
+
+ Select2.prototype._registerResultsEvents = function () {
+ var self = this;
+
+ this.results.on('*', function (name, params) {
+ self.trigger(name, params);
+ });
+ };
+
+ Select2.prototype._registerEvents = function () {
+ var self = this;
+
+ this.on('open', function () {
+ self.$container.addClass('select2-container--open');
+ });
+
+ this.on('close', function () {
+ self.$container.removeClass('select2-container--open');
+ });
+
+ this.on('enable', function () {
+ self.$container.removeClass('select2-container--disabled');
+ });
+
+ this.on('disable', function () {
+ self.$container.addClass('select2-container--disabled');
+ });
+
+ this.on('blur', function () {
+ self.$container.removeClass('select2-container--focus');
+ });
+
+ this.on('query', function (params) {
+ if (!self.isOpen()) {
+ self.trigger('open', {});
+ }
+
+ this.dataAdapter.query(params, function (data) {
+ self.trigger('results:all', {
+ data: data,
+ query: params
+ });
+ });
+ });
+
+ this.on('query:append', function (params) {
+ this.dataAdapter.query(params, function (data) {
+ self.trigger('results:append', {
+ data: data,
+ query: params
+ });
+ });
+ });
+
+ this.on('keypress', function (evt) {
+ var key = evt.which;
+
+ if (self.isOpen()) {
+ if (key === KEYS.ESC || key === KEYS.TAB ||
+ (key === KEYS.UP && evt.altKey)) {
+ self.close();
+
+ evt.preventDefault();
+ } else if (key === KEYS.ENTER) {
+ self.trigger('results:select', {});
+
+ evt.preventDefault();
+ } else if ((key === KEYS.SPACE && evt.ctrlKey)) {
+ self.trigger('results:toggle', {});
+
+ evt.preventDefault();
+ } else if (key === KEYS.UP) {
+ self.trigger('results:previous', {});
+
+ evt.preventDefault();
+ } else if (key === KEYS.DOWN) {
+ self.trigger('results:next', {});
+
+ evt.preventDefault();
+ }
+ } else {
+ if (key === KEYS.ENTER || key === KEYS.SPACE ||
+ (key === KEYS.DOWN && evt.altKey)) {
+ self.open();
+
+ evt.preventDefault();
+ }
+ }
+ });
+ };
+
+ Select2.prototype._syncAttributes = function () {
+ this.options.set('disabled', this.$element.prop('disabled'));
+
+ if (this.options.get('disabled')) {
+ if (this.isOpen()) {
+ this.close();
+ }
+
+ this.trigger('disable', {});
+ } else {
+ this.trigger('enable', {});
+ }
+ };
+
+ Select2.prototype._syncSubtree = function (evt, mutations) {
+ var changed = false;
+ var self = this;
+
+ // Ignore any mutation events raised for elements that aren't options or
+ // optgroups. This handles the case when the select element is destroyed
+ if (
+ evt && evt.target && (
+ evt.target.nodeName !== 'OPTION' && evt.target.nodeName !== 'OPTGROUP'
+ )
+ ) {
+ return;
+ }
+
+ if (!mutations) {
+ // If mutation events aren't supported, then we can only assume that the
+ // change affected the selections
+ changed = true;
+ } else if (mutations.addedNodes && mutations.addedNodes.length > 0) {
+ for (var n = 0; n < mutations.addedNodes.length; n++) {
+ var node = mutations.addedNodes[n];
+
+ if (node.selected) {
+ changed = true;
+ }
+ }
+ } else if (mutations.removedNodes && mutations.removedNodes.length > 0) {
+ changed = true;
+ }
+
+ // Only re-pull the data if we think there is a change
+ if (changed) {
+ this.dataAdapter.current(function (currentData) {
+ self.trigger('selection:update', {
+ data: currentData
+ });
+ });
+ }
+ };
+
+ /**
+ * Override the trigger method to automatically trigger pre-events when
+ * there are events that can be prevented.
+ */
+ Select2.prototype.trigger = function (name, args) {
+ var actualTrigger = Select2.__super__.trigger;
+ var preTriggerMap = {
+ 'open': 'opening',
+ 'close': 'closing',
+ 'select': 'selecting',
+ 'unselect': 'unselecting',
+ 'clear': 'clearing'
+ };
+
+ if (args === undefined) {
+ args = {};
+ }
+
+ if (name in preTriggerMap) {
+ var preTriggerName = preTriggerMap[name];
+ var preTriggerArgs = {
+ prevented: false,
+ name: name,
+ args: args
+ };
+
+ actualTrigger.call(this, preTriggerName, preTriggerArgs);
+
+ if (preTriggerArgs.prevented) {
+ args.prevented = true;
+
+ return;
+ }
+ }
+
+ actualTrigger.call(this, name, args);
+ };
+
+ Select2.prototype.toggleDropdown = function () {
+ if (this.options.get('disabled')) {
+ return;
+ }
+
+ if (this.isOpen()) {
+ this.close();
+ } else {
+ this.open();
+ }
+ };
+
+ Select2.prototype.open = function () {
+ if (this.isOpen()) {
+ return;
+ }
+
+ this.trigger('query', {});
+ };
+
+ Select2.prototype.close = function () {
+ if (!this.isOpen()) {
+ return;
+ }
+
+ this.trigger('close', {});
+ };
+
+ Select2.prototype.isOpen = function () {
+ return this.$container.hasClass('select2-container--open');
+ };
+
+ Select2.prototype.hasFocus = function () {
+ return this.$container.hasClass('select2-container--focus');
+ };
+
+ Select2.prototype.focus = function (data) {
+ // No need to re-trigger focus events if we are already focused
+ if (this.hasFocus()) {
+ return;
+ }
+
+ this.$container.addClass('select2-container--focus');
+ this.trigger('focus', {});
+ };
+
+ Select2.prototype.enable = function (args) {
+ if (this.options.get('debug') && window.console && console.warn) {
+ console.warn(
+ 'Select2: The `select2("enable")` method has been deprecated and will' +
+ ' be removed in later Select2 versions. Use $element.prop("disabled")' +
+ ' instead.'
+ );
+ }
+
+ if (args == null || args.length === 0) {
+ args = [true];
+ }
+
+ var disabled = !args[0];
+
+ this.$element.prop('disabled', disabled);
+ };
+
+ Select2.prototype.data = function () {
+ if (this.options.get('debug') &&
+ arguments.length > 0 && window.console && console.warn) {
+ console.warn(
+ 'Select2: Data can no longer be set using `select2("data")`. You ' +
+ 'should consider setting the value instead using `$element.val()`.'
+ );
+ }
+
+ var data = [];
+
+ this.dataAdapter.current(function (currentData) {
+ data = currentData;
+ });
+
+ return data;
+ };
+
+ Select2.prototype.val = function (args) {
+ if (this.options.get('debug') && window.console && console.warn) {
+ console.warn(
+ 'Select2: The `select2("val")` method has been deprecated and will be' +
+ ' removed in later Select2 versions. Use $element.val() instead.'
+ );
+ }
+
+ if (args == null || args.length === 0) {
+ return this.$element.val();
+ }
+
+ var newVal = args[0];
+
+ if ($.isArray(newVal)) {
+ newVal = $.map(newVal, function (obj) {
+ return obj.toString();
+ });
+ }
+
+ this.$element.val(newVal).trigger('change');
+ };
+
+ Select2.prototype.destroy = function () {
+ this.$container.remove();
+
+ if (this.$element[0].detachEvent) {
+ this.$element[0].detachEvent('onpropertychange', this._syncA);
+ }
+
+ if (this._observer != null) {
+ this._observer.disconnect();
+ this._observer = null;
+ } else if (this.$element[0].removeEventListener) {
+ this.$element[0]
+ .removeEventListener('DOMAttrModified', this._syncA, false);
+ this.$element[0]
+ .removeEventListener('DOMNodeInserted', this._syncS, false);
+ this.$element[0]
+ .removeEventListener('DOMNodeRemoved', this._syncS, false);
+ }
+
+ this._syncA = null;
+ this._syncS = null;
+
+ this.$element.off('.select2');
+ this.$element.attr('tabindex',
+ Utils.GetData(this.$element[0], 'old-tabindex'));
+
+ this.$element.removeClass('select2-hidden-accessible');
+ this.$element.attr('aria-hidden', 'false');
+ Utils.RemoveData(this.$element[0]);
+ this.$element.removeData('select2');
+
+ this.dataAdapter.destroy();
+ this.selection.destroy();
+ this.dropdown.destroy();
+ this.results.destroy();
+
+ this.dataAdapter = null;
+ this.selection = null;
+ this.dropdown = null;
+ this.results = null;
+ };
+
+ Select2.prototype.render = function () {
+ var $container = $(
+ '<span class="select2 select2-container">' +
+ '<span class="selection"></span>' +
+ '<span class="dropdown-wrapper" aria-hidden="true"></span>' +
+ '</span>'
+ );
+
+ $container.attr('dir', this.options.get('dir'));
+
+ this.$container = $container;
+
+ this.$container.addClass('select2-container--' + this.options.get('theme'));
+
+ Utils.StoreData($container[0], 'element', this.$element);
+
+ return $container;
+ };
+
+ return Select2;
+});
+
+S2.define('jquery-mousewheel',[
+ 'jquery'
+], function ($) {
+ // Used to shim jQuery.mousewheel for non-full builds.
+ return $;
+});
+
+S2.define('jquery.select2',[
+ 'jquery',
+ 'jquery-mousewheel',
+
+ './select2/core',
+ './select2/defaults',
+ './select2/utils'
+], function ($, _, Select2, Defaults, Utils) {
+ if ($.fn.select2 == null) {
+ // All methods that should return the element
+ var thisMethods = ['open', 'close', 'destroy'];
+
+ $.fn.select2 = function (options) {
+ options = options || {};
+
+ if (typeof options === 'object') {
+ this.each(function () {
+ var instanceOptions = $.extend(true, {}, options);
+
+ var instance = new Select2($(this), instanceOptions);
+ });
+
+ return this;
+ } else if (typeof options === 'string') {
+ var ret;
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ this.each(function () {
+ var instance = Utils.GetData(this, 'select2');
+
+ if (instance == null && window.console && console.error) {
+ console.error(
+ 'The select2(\'' + options + '\') method was called on an ' +
+ 'element that is not using Select2.'
+ );
+ }
+
+ ret = instance[options].apply(instance, args);
+ });
+
+ // Check if we should be returning `this`
+ if ($.inArray(options, thisMethods) > -1) {
+ return this;
+ }
+
+ return ret;
+ } else {
+ throw new Error('Invalid arguments for Select2: ' + options);
+ }
+ };
+ }
+
+ if ($.fn.select2.defaults == null) {
+ $.fn.select2.defaults = Defaults;
+ }
+
+ return Select2;
+});
+
+ // Return the AMD loader configuration so it can be used outside of this file
+ return {
+ define: S2.define,
+ require: S2.require
+ };
+}());
+
+ // Autoload the jQuery bindings
+ // We know that all of the modules exist above this, so we're safe
+ var select2 = S2.require('jquery.select2');
+
+ // Hold the AMD module references on the jQuery function that was just loaded
+ // This allows Select2 to use the internal loader outside of this file, such
+ // as in the language files.
+ jQuery.fn.select2.amd = S2;
+
+ // Return the Select2 instance for anyone who is importing it.
+ return select2;
+}));
+
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))
+
+/***/ }),
+/* 134 */
+/***/ (function(module, exports) {
+
+module.exports = function(module) {
+ if(!module.webpackPolyfill) {
+ module.deprecate = function() {};
+ module.paths = [];
+ // module.parent = undefined by default
+ if(!module.children) module.children = [];
+ Object.defineProperty(module, "loaded", {
+ enumerable: true,
+ get: function() {
+ return module.l;
+ }
+ });
+ Object.defineProperty(module, "id", {
+ enumerable: true,
+ get: function() {
+ return module.i;
+ }
+ });
+ module.webpackPolyfill = 1;
+ }
+ return module;
+};
+
+
+/***/ }),
+/* 135 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var map = {
+ "./af": 5,
+ "./af.js": 5,
+ "./ar": 6,
+ "./ar-dz": 7,
+ "./ar-dz.js": 7,
+ "./ar-kw": 8,
+ "./ar-kw.js": 8,
+ "./ar-ly": 9,
+ "./ar-ly.js": 9,
+ "./ar-ma": 10,
+ "./ar-ma.js": 10,
+ "./ar-sa": 11,
+ "./ar-sa.js": 11,
+ "./ar-tn": 12,
+ "./ar-tn.js": 12,
+ "./ar.js": 6,
+ "./az": 13,
+ "./az.js": 13,
+ "./be": 14,
+ "./be.js": 14,
+ "./bg": 15,
+ "./bg.js": 15,
+ "./bm": 16,
+ "./bm.js": 16,
+ "./bn": 17,
+ "./bn.js": 17,
+ "./bo": 18,
+ "./bo.js": 18,
+ "./br": 19,
+ "./br.js": 19,
+ "./bs": 20,
+ "./bs.js": 20,
+ "./ca": 21,
+ "./ca.js": 21,
+ "./cs": 22,
+ "./cs.js": 22,
+ "./cv": 23,
+ "./cv.js": 23,
+ "./cy": 24,
+ "./cy.js": 24,
+ "./da": 25,
+ "./da.js": 25,
+ "./de": 26,
+ "./de-at": 27,
+ "./de-at.js": 27,
+ "./de-ch": 28,
+ "./de-ch.js": 28,
+ "./de.js": 26,
+ "./dv": 29,
+ "./dv.js": 29,
+ "./el": 30,
+ "./el.js": 30,
+ "./en-au": 31,
+ "./en-au.js": 31,
+ "./en-ca": 32,
+ "./en-ca.js": 32,
+ "./en-gb": 33,
+ "./en-gb.js": 33,
+ "./en-ie": 34,
+ "./en-ie.js": 34,
+ "./en-nz": 35,
+ "./en-nz.js": 35,
+ "./eo": 36,
+ "./eo.js": 36,
+ "./es": 37,
+ "./es-do": 38,
+ "./es-do.js": 38,
+ "./es-us": 39,
+ "./es-us.js": 39,
+ "./es.js": 37,
+ "./et": 40,
+ "./et.js": 40,
+ "./eu": 41,
+ "./eu.js": 41,
+ "./fa": 42,
+ "./fa.js": 42,
+ "./fi": 43,
+ "./fi.js": 43,
+ "./fo": 44,
+ "./fo.js": 44,
+ "./fr": 45,
+ "./fr-ca": 46,
+ "./fr-ca.js": 46,
+ "./fr-ch": 47,
+ "./fr-ch.js": 47,
+ "./fr.js": 45,
+ "./fy": 48,
+ "./fy.js": 48,
+ "./gd": 49,
+ "./gd.js": 49,
+ "./gl": 50,
+ "./gl.js": 50,
+ "./gom-latn": 51,
+ "./gom-latn.js": 51,
+ "./gu": 52,
+ "./gu.js": 52,
+ "./he": 53,
+ "./he.js": 53,
+ "./hi": 54,
+ "./hi.js": 54,
+ "./hr": 55,
+ "./hr.js": 55,
+ "./hu": 56,
+ "./hu.js": 56,
+ "./hy-am": 57,
+ "./hy-am.js": 57,
+ "./id": 58,
+ "./id.js": 58,
+ "./is": 59,
+ "./is.js": 59,
+ "./it": 60,
+ "./it.js": 60,
+ "./ja": 61,
+ "./ja.js": 61,
+ "./jv": 62,
+ "./jv.js": 62,
+ "./ka": 63,
+ "./ka.js": 63,
+ "./kk": 64,
+ "./kk.js": 64,
+ "./km": 65,
+ "./km.js": 65,
+ "./kn": 66,
+ "./kn.js": 66,
+ "./ko": 67,
+ "./ko.js": 67,
+ "./ky": 68,
+ "./ky.js": 68,
+ "./lb": 69,
+ "./lb.js": 69,
+ "./lo": 70,
+ "./lo.js": 70,
+ "./lt": 71,
+ "./lt.js": 71,
+ "./lv": 72,
+ "./lv.js": 72,
+ "./me": 73,
+ "./me.js": 73,
+ "./mi": 74,
+ "./mi.js": 74,
+ "./mk": 75,
+ "./mk.js": 75,
+ "./ml": 76,
+ "./ml.js": 76,
+ "./mr": 77,
+ "./mr.js": 77,
+ "./ms": 78,
+ "./ms-my": 79,
+ "./ms-my.js": 79,
+ "./ms.js": 78,
+ "./mt": 80,
+ "./mt.js": 80,
+ "./my": 81,
+ "./my.js": 81,
+ "./nb": 82,
+ "./nb.js": 82,
+ "./ne": 83,
+ "./ne.js": 83,
+ "./nl": 84,
+ "./nl-be": 85,
+ "./nl-be.js": 85,
+ "./nl.js": 84,
+ "./nn": 86,
+ "./nn.js": 86,
+ "./pa-in": 87,
+ "./pa-in.js": 87,
+ "./pl": 88,
+ "./pl.js": 88,
+ "./pt": 89,
+ "./pt-br": 90,
+ "./pt-br.js": 90,
+ "./pt.js": 89,
+ "./ro": 91,
+ "./ro.js": 91,
+ "./ru": 92,
+ "./ru.js": 92,
+ "./sd": 93,
+ "./sd.js": 93,
+ "./se": 94,
+ "./se.js": 94,
+ "./si": 95,
+ "./si.js": 95,
+ "./sk": 96,
+ "./sk.js": 96,
+ "./sl": 97,
+ "./sl.js": 97,
+ "./sq": 98,
+ "./sq.js": 98,
+ "./sr": 99,
+ "./sr-cyrl": 100,
+ "./sr-cyrl.js": 100,
+ "./sr.js": 99,
+ "./ss": 101,
+ "./ss.js": 101,
+ "./sv": 102,
+ "./sv.js": 102,
+ "./sw": 103,
+ "./sw.js": 103,
+ "./ta": 104,
+ "./ta.js": 104,
+ "./te": 105,
+ "./te.js": 105,
+ "./tet": 106,
+ "./tet.js": 106,
+ "./th": 107,
+ "./th.js": 107,
+ "./tl-ph": 108,
+ "./tl-ph.js": 108,
+ "./tlh": 109,
+ "./tlh.js": 109,
+ "./tr": 110,
+ "./tr.js": 110,
+ "./tzl": 111,
+ "./tzl.js": 111,
+ "./tzm": 112,
+ "./tzm-latn": 113,
+ "./tzm-latn.js": 113,
+ "./tzm.js": 112,
+ "./uk": 114,
+ "./uk.js": 114,
+ "./ur": 115,
+ "./ur.js": 115,
+ "./uz": 116,
+ "./uz-latn": 117,
+ "./uz-latn.js": 117,
+ "./uz.js": 116,
+ "./vi": 118,
+ "./vi.js": 118,
+ "./x-pseudo": 119,
+ "./x-pseudo.js": 119,
+ "./yo": 120,
+ "./yo.js": 120,
+ "./zh-cn": 121,
+ "./zh-cn.js": 121,
+ "./zh-hk": 122,
+ "./zh-hk.js": 122,
+ "./zh-tw": 123,
+ "./zh-tw.js": 123
+};
+function webpackContext(req) {
+ return __webpack_require__(webpackContextResolve(req));
+};
+function webpackContextResolve(req) {
+ var id = map[req];
+ if(!(id + 1)) // check for number or string
+ throw new Error("Cannot find module '" + req + "'.");
+ return id;
+};
+webpackContext.keys = function webpackContextKeys() {
+ return Object.keys(map);
+};
+webpackContext.resolve = webpackContextResolve;
+module.exports = webpackContext;
+webpackContext.id = 135;
+
+/***/ }),
+/* 136 */
+/***/ (function(module, exports, __webpack_require__) {
+
+var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! version : 4.17.47
+ =========================================================
+ bootstrap-datetimejs
+ https://github.com/Eonasdan/bootstrap-datetimepicker
+ Copyright (c) 2015 Jonathan Peterson
+ =========================================================
+ */
+/*
+ The MIT License (MIT)
+
+ Copyright (c) 2015 Jonathan Peterson
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+/*global define:false */
+/*global exports:false */
+/*global require:false */
+/*global jQuery:false */
+/*global moment:false */
+(function (factory) {
+ 'use strict';
+ if (true) {
+ // AMD is used - Register as an anonymous module.
+ !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(1), __webpack_require__(0)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
+ __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
+ (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
+ __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
+ } else if (typeof exports === 'object') {
+ module.exports = factory(require('jquery'), require('moment'));
+ } else {
+ // Neither AMD nor CommonJS used. Use global variables.
+ if (typeof jQuery === 'undefined') {
+ throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
+ }
+ if (typeof moment === 'undefined') {
+ throw 'bootstrap-datetimepicker requires Moment.js to be loaded first';
+ }
+ factory(jQuery, moment);
+ }
+}(function ($, moment) {
+ 'use strict';
+ if (!moment) {
+ throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first');
+ }
+
+ var dateTimePicker = function (element, options) {
+ var picker = {},
+ date,
+ viewDate,
+ unset = true,
+ input,
+ component = false,
+ widget = false,
+ use24Hours,
+ minViewModeNumber = 0,
+ actualFormat,
+ parseFormats,
+ currentViewMode,
+ datePickerModes = [
+ {
+ clsName: 'days',
+ navFnc: 'M',
+ navStep: 1
+ },
+ {
+ clsName: 'months',
+ navFnc: 'y',
+ navStep: 1
+ },
+ {
+ clsName: 'years',
+ navFnc: 'y',
+ navStep: 10
+ },
+ {
+ clsName: 'decades',
+ navFnc: 'y',
+ navStep: 100
+ }
+ ],
+ viewModes = ['days', 'months', 'years', 'decades'],
+ verticalModes = ['top', 'bottom', 'auto'],
+ horizontalModes = ['left', 'right', 'auto'],
+ toolbarPlacements = ['default', 'top', 'bottom'],
+ keyMap = {
+ 'up': 38,
+ 38: 'up',
+ 'down': 40,
+ 40: 'down',
+ 'left': 37,
+ 37: 'left',
+ 'right': 39,
+ 39: 'right',
+ 'tab': 9,
+ 9: 'tab',
+ 'escape': 27,
+ 27: 'escape',
+ 'enter': 13,
+ 13: 'enter',
+ 'pageUp': 33,
+ 33: 'pageUp',
+ 'pageDown': 34,
+ 34: 'pageDown',
+ 'shift': 16,
+ 16: 'shift',
+ 'control': 17,
+ 17: 'control',
+ 'space': 32,
+ 32: 'space',
+ 't': 84,
+ 84: 't',
+ 'delete': 46,
+ 46: 'delete'
+ },
+ keyState = {},
+
+ /********************************************************************************
+ *
+ * Private functions
+ *
+ ********************************************************************************/
+
+ hasTimeZone = function () {
+ return moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '';
+ },
+
+ getMoment = function (d) {
+ var returnMoment;
+
+ if (d === undefined || d === null) {
+ returnMoment = moment(); //TODO should this use format? and locale?
+ } else if (moment.isDate(d) || moment.isMoment(d)) {
+ // If the date that is passed in is already a Date() or moment() object,
+ // pass it directly to moment.
+ returnMoment = moment(d);
+ } else if (hasTimeZone()) { // There is a string to parse and a default time zone
+ // parse with the tz function which takes a default time zone if it is not in the format string
+ returnMoment = moment.tz(d, parseFormats, options.useStrict, options.timeZone);
+ } else {
+ returnMoment = moment(d, parseFormats, options.useStrict);
+ }
+
+ if (hasTimeZone()) {
+ returnMoment.tz(options.timeZone);
+ }
+
+ return returnMoment;
+ },
+
+ isEnabled = function (granularity) {
+ if (typeof granularity !== 'string' || granularity.length > 1) {
+ throw new TypeError('isEnabled expects a single character string parameter');
+ }
+ switch (granularity) {
+ case 'y':
+ return actualFormat.indexOf('Y') !== -1;
+ case 'M':
+ return actualFormat.indexOf('M') !== -1;
+ case 'd':
+ return actualFormat.toLowerCase().indexOf('d') !== -1;
+ case 'h':
+ case 'H':
+ return actualFormat.toLowerCase().indexOf('h') !== -1;
+ case 'm':
+ return actualFormat.indexOf('m') !== -1;
+ case 's':
+ return actualFormat.indexOf('s') !== -1;
+ default:
+ return false;
+ }
+ },
+
+ hasTime = function () {
+ return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
+ },
+
+ hasDate = function () {
+ return (isEnabled('y') || isEnabled('M') || isEnabled('d'));
+ },
+
+ getDatePickerTemplate = function () {
+ var headTemplate = $('<thead>')
+ .append($('<tr>')
+ .append($('<th>').addClass('prev').attr('data-action', 'previous')
+ .append($('<span>').addClass(options.icons.previous))
+ )
+ .append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5')))
+ .append($('<th>').addClass('next').attr('data-action', 'next')
+ .append($('<span>').addClass(options.icons.next))
+ )
+ ),
+ contTemplate = $('<tbody>')
+ .append($('<tr>')
+ .append($('<td>').attr('colspan', (options.calendarWeeks ? '8' : '7')))
+ );
+
+ return [
+ $('<div>').addClass('datepicker-days')
+ .append($('<table>').addClass('table-condensed')
+ .append(headTemplate)
+ .append($('<tbody>'))
+ ),
+ $('<div>').addClass('datepicker-months')
+ .append($('<table>').addClass('table-condensed')
+ .append(headTemplate.clone())
+ .append(contTemplate.clone())
+ ),
+ $('<div>').addClass('datepicker-years')
+ .append($('<table>').addClass('table-condensed')
+ .append(headTemplate.clone())
+ .append(contTemplate.clone())
+ ),
+ $('<div>').addClass('datepicker-decades')
+ .append($('<table>').addClass('table-condensed')
+ .append(headTemplate.clone())
+ .append(contTemplate.clone())
+ )
+ ];
+ },
+
+ getTimePickerMainTemplate = function () {
+ var topRow = $('<tr>'),
+ middleRow = $('<tr>'),
+ bottomRow = $('<tr>');
+
+ if (isEnabled('h')) {
+ topRow.append($('<td>')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour }).addClass('btn').attr('data-action', 'incrementHours').append($('<span>').addClass(options.icons.up))));
+ middleRow.append($('<td>')
+ .append($('<span>').addClass('timepicker-hour').attr({ 'data-time-component': 'hours', 'title': options.tooltips.pickHour }).attr('data-action', 'showHours')));
+ bottomRow.append($('<td>')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour }).addClass('btn').attr('data-action', 'decrementHours').append($('<span>').addClass(options.icons.down))));
+ }
+ if (isEnabled('m')) {
+ if (isEnabled('h')) {
+ topRow.append($('<td>').addClass('separator'));
+ middleRow.append($('<td>').addClass('separator').html(':'));
+ bottomRow.append($('<td>').addClass('separator'));
+ }
+ topRow.append($('<td>')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute }).addClass('btn').attr('data-action', 'incrementMinutes')
+ .append($('<span>').addClass(options.icons.up))));
+ middleRow.append($('<td>')
+ .append($('<span>').addClass('timepicker-minute').attr({ 'data-time-component': 'minutes', 'title': options.tooltips.pickMinute }).attr('data-action', 'showMinutes')));
+ bottomRow.append($('<td>')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute }).addClass('btn').attr('data-action', 'decrementMinutes')
+ .append($('<span>').addClass(options.icons.down))));
+ }
+ if (isEnabled('s')) {
+ if (isEnabled('m')) {
+ topRow.append($('<td>').addClass('separator'));
+ middleRow.append($('<td>').addClass('separator').html(':'));
+ bottomRow.append($('<td>').addClass('separator'));
+ }
+ topRow.append($('<td>')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond }).addClass('btn').attr('data-action', 'incrementSeconds')
+ .append($('<span>').addClass(options.icons.up))));
+ middleRow.append($('<td>')
+ .append($('<span>').addClass('timepicker-second').attr({ 'data-time-component': 'seconds', 'title': options.tooltips.pickSecond }).attr('data-action', 'showSeconds')));
+ bottomRow.append($('<td>')
+ .append($('<a>').attr({ href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond }).addClass('btn').attr('data-action', 'decrementSeconds')
+ .append($('<span>').addClass(options.icons.down))));
+ }
+
+ if (!use24Hours) {
+ topRow.append($('<td>').addClass('separator'));
+ middleRow.append($('<td>')
+ .append($('<button>').addClass('btn btn-primary').attr({ 'data-action': 'togglePeriod', tabindex: '-1', 'title': options.tooltips.togglePeriod })));
+ bottomRow.append($('<td>').addClass('separator'));
+ }
+
+ return $('<div>').addClass('timepicker-picker')
+ .append($('<table>').addClass('table-condensed')
+ .append([topRow, middleRow, bottomRow]));
+ },
+
+ getTimePickerTemplate = function () {
+ var hoursView = $('<div>').addClass('timepicker-hours')
+ .append($('<table>').addClass('table-condensed')),
+ minutesView = $('<div>').addClass('timepicker-minutes')
+ .append($('<table>').addClass('table-condensed')),
+ secondsView = $('<div>').addClass('timepicker-seconds')
+ .append($('<table>').addClass('table-condensed')),
+ ret = [getTimePickerMainTemplate()];
+
+ if (isEnabled('h')) {
+ ret.push(hoursView);
+ }
+ if (isEnabled('m')) {
+ ret.push(minutesView);
+ }
+ if (isEnabled('s')) {
+ ret.push(secondsView);
+ }
+
+ return ret;
+ },
+
+ getToolbar = function () {
+ var row = [];
+ if (options.showTodayButton) {
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'today', 'title': options.tooltips.today }).append($('<span>').addClass(options.icons.today))));
+ }
+ if (!options.sideBySide && hasDate() && hasTime()) {
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'togglePicker', 'title': options.tooltips.selectTime }).append($('<span>').addClass(options.icons.time))));
+ }
+ if (options.showClear) {
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'clear', 'title': options.tooltips.clear }).append($('<span>').addClass(options.icons.clear))));
+ }
+ if (options.showClose) {
+ row.push($('<td>').append($('<a>').attr({ 'data-action': 'close', 'title': options.tooltips.close }).append($('<span>').addClass(options.icons.close))));
+ }
+ return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
+ },
+
+ getTemplate = function () {
+ var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'),
+ dateView = $('<div>').addClass('datepicker').append(getDatePickerTemplate()),
+ timeView = $('<div>').addClass('timepicker').append(getTimePickerTemplate()),
+ content = $('<ul>').addClass('list-unstyled'),
+ toolbar = $('<li>').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar());
+
+ if (options.inline) {
+ template.removeClass('dropdown-menu');
+ }
+
+ if (use24Hours) {
+ template.addClass('usetwentyfour');
+ }
+
+ if (isEnabled('s') && !use24Hours) {
+ template.addClass('wider');
+ }
+
+ if (options.sideBySide && hasDate() && hasTime()) {
+ template.addClass('timepicker-sbs');
+ if (options.toolbarPlacement === 'top') {
+ template.append(toolbar);
+ }
+ template.append(
+ $('<div>').addClass('row')
+ .append(dateView.addClass('col-md-6'))
+ .append(timeView.addClass('col-md-6'))
+ );
+ if (options.toolbarPlacement === 'bottom') {
+ template.append(toolbar);
+ }
+ return template;
+ }
+
+ if (options.toolbarPlacement === 'top') {
+ content.append(toolbar);
+ }
+ if (hasDate()) {
+ content.append($('<li>').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView));
+ }
+ if (options.toolbarPlacement === 'default') {
+ content.append(toolbar);
+ }
+ if (hasTime()) {
+ content.append($('<li>').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView));
+ }
+ if (options.toolbarPlacement === 'bottom') {
+ content.append(toolbar);
+ }
+ return template.append(content);
+ },
+
+ dataToOptions = function () {
+ var eData,
+ dataOptions = {};
+
+ if (element.is('input') || options.inline) {
+ eData = element.data();
+ } else {
+ eData = element.find('input').data();
+ }
+
+ if (eData.dateOptions && eData.dateOptions instanceof Object) {
+ dataOptions = $.extend(true, dataOptions, eData.dateOptions);
+ }
+
+ $.each(options, function (key) {
+ var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1);
+ if (eData[attributeName] !== undefined) {
+ dataOptions[key] = eData[attributeName];
+ }
+ });
+ return dataOptions;
+ },
+
+ place = function () {
+ var position = (component || element).position(),
+ offset = (component || element).offset(),
+ vertical = options.widgetPositioning.vertical,
+ horizontal = options.widgetPositioning.horizontal,
+ parent;
+
+ if (options.widgetParent) {
+ parent = options.widgetParent.append(widget);
+ } else if (element.is('input')) {
+ parent = element.after(widget).parent();
+ } else if (options.inline) {
+ parent = element.append(widget);
+ return;
+ } else {
+ parent = element;
+ element.children().first().after(widget);
+ }
+
+ // Top and bottom logic
+ if (vertical === 'auto') {
+ if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() &&
+ widget.height() + element.outerHeight() < offset.top) {
+ vertical = 'top';
+ } else {
+ vertical = 'bottom';
+ }
+ }
+
+ // Left and right logic
+ if (horizontal === 'auto') {
+ if (parent.width() < offset.left + widget.outerWidth() / 2 &&
+ offset.left + widget.outerWidth() > $(window).width()) {
+ horizontal = 'right';
+ } else {
+ horizontal = 'left';
+ }
+ }
+
+ if (vertical === 'top') {
+ widget.addClass('top').removeClass('bottom');
+ } else {
+ widget.addClass('bottom').removeClass('top');
+ }
+
+ if (horizontal === 'right') {
+ widget.addClass('pull-right');
+ } else {
+ widget.removeClass('pull-right');
+ }
+
+ // find the first parent element that has a non-static css positioning
+ if (parent.css('position') === 'static') {
+ parent = parent.parents().filter(function () {
+ return $(this).css('position') !== 'static';
+ }).first();
+ }
+
+ if (parent.length === 0) {
+ throw new Error('datetimepicker component should be placed within a non-static positioned container');
+ }
+
+ widget.css({
+ top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
+ bottom: vertical === 'top' ? parent.outerHeight() - (parent === element ? 0 : position.top) : 'auto',
+ left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
+ right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
+ });
+ },
+
+ notifyEvent = function (e) {
+ if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) {
+ return;
+ }
+ element.trigger(e);
+ },
+
+ viewUpdate = function (e) {
+ if (e === 'y') {
+ e = 'YYYY';
+ }
+ notifyEvent({
+ type: 'dp.update',
+ change: e,
+ viewDate: viewDate.clone()
+ });
+ },
+
+ showMode = function (dir) {
+ if (!widget) {
+ return;
+ }
+ if (dir) {
+ currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir));
+ }
+ widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show();
+ },
+
+ fillDow = function () {
+ var row = $('<tr>'),
+ currentDate = viewDate.clone().startOf('w').startOf('d');
+
+ if (options.calendarWeeks === true) {
+ row.append($('<th>').addClass('cw').text('#'));
+ }
+
+ while (currentDate.isBefore(viewDate.clone().endOf('w'))) {
+ row.append($('<th>').addClass('dow').text(currentDate.format('dd')));
+ currentDate.add(1, 'd');
+ }
+ widget.find('.datepicker-days thead').append(row);
+ },
+
+ isInDisabledDates = function (testDate) {
+ return options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
+ },
+
+ isInEnabledDates = function (testDate) {
+ return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
+ },
+
+ isInDisabledHours = function (testDate) {
+ return options.disabledHours[testDate.format('H')] === true;
+ },
+
+ isInEnabledHours = function (testDate) {
+ return options.enabledHours[testDate.format('H')] === true;
+ },
+
+ isValid = function (targetMoment, granularity) {
+ if (!targetMoment.isValid()) {
+ return false;
+ }
+ if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) {
+ return false;
+ }
+ if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) {
+ return false;
+ }
+ if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
+ return false;
+ }
+ if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
+ return false;
+ }
+ if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
+ return false;
+ }
+ if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) {
+ return false;
+ }
+ if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) {
+ return false;
+ }
+ if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
+ var found = false;
+ $.each(options.disabledTimeIntervals, function () {
+ if (targetMoment.isBetween(this[0], this[1])) {
+ found = true;
+ return false;
+ }
+ });
+ if (found) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ fillMonths = function () {
+ var spans = [],
+ monthsShort = viewDate.clone().startOf('y').startOf('d');
+ while (monthsShort.isSame(viewDate, 'y')) {
+ spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
+ monthsShort.add(1, 'M');
+ }
+ widget.find('.datepicker-months td').empty().append(spans);
+ },
+
+ updateMonths = function () {
+ var monthsView = widget.find('.datepicker-months'),
+ monthsViewHeader = monthsView.find('th'),
+ months = monthsView.find('tbody').find('span');
+
+ monthsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevYear);
+ monthsViewHeader.eq(1).attr('title', options.tooltips.selectYear);
+ monthsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextYear);
+
+ monthsView.find('.disabled').removeClass('disabled');
+
+ if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) {
+ monthsViewHeader.eq(0).addClass('disabled');
+ }
+
+ monthsViewHeader.eq(1).text(viewDate.year());
+
+ if (!isValid(viewDate.clone().add(1, 'y'), 'y')) {
+ monthsViewHeader.eq(2).addClass('disabled');
+ }
+
+ months.removeClass('active');
+ if (date.isSame(viewDate, 'y') && !unset) {
+ months.eq(date.month()).addClass('active');
+ }
+
+ months.each(function (index) {
+ if (!isValid(viewDate.clone().month(index), 'M')) {
+ $(this).addClass('disabled');
+ }
+ });
+ },
+
+ updateYears = function () {
+ var yearsView = widget.find('.datepicker-years'),
+ yearsViewHeader = yearsView.find('th'),
+ startYear = viewDate.clone().subtract(5, 'y'),
+ endYear = viewDate.clone().add(6, 'y'),
+ html = '';
+
+ yearsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevDecade);
+ yearsViewHeader.eq(1).attr('title', options.tooltips.selectDecade);
+ yearsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextDecade);
+
+ yearsView.find('.disabled').removeClass('disabled');
+
+ if (options.minDate && options.minDate.isAfter(startYear, 'y')) {
+ yearsViewHeader.eq(0).addClass('disabled');
+ }
+
+ yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year());
+
+ if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) {
+ yearsViewHeader.eq(2).addClass('disabled');
+ }
+
+ while (!startYear.isAfter(endYear, 'y')) {
+ html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
+ startYear.add(1, 'y');
+ }
+
+ yearsView.find('td').html(html);
+ },
+
+ updateDecades = function () {
+ var decadesView = widget.find('.datepicker-decades'),
+ decadesViewHeader = decadesView.find('th'),
+ startDecade = moment({ y: viewDate.year() - (viewDate.year() % 100) - 1 }),
+ endDecade = startDecade.clone().add(100, 'y'),
+ startedAt = startDecade.clone(),
+ minDateDecade = false,
+ maxDateDecade = false,
+ endDecadeYear,
+ html = '';
+
+ decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury);
+ decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury);
+
+ decadesView.find('.disabled').removeClass('disabled');
+
+ if (startDecade.isSame(moment({ y: 1900 })) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
+ decadesViewHeader.eq(0).addClass('disabled');
+ }
+
+ decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());
+
+ if (startDecade.isSame(moment({ y: 2000 })) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
+ decadesViewHeader.eq(2).addClass('disabled');
+ }
+
+ while (!startDecade.isAfter(endDecade, 'y')) {
+ endDecadeYear = startDecade.year() + 12;
+ minDateDecade = options.minDate && options.minDate.isAfter(startDecade, 'y') && options.minDate.year() <= endDecadeYear;
+ maxDateDecade = options.maxDate && options.maxDate.isAfter(startDecade, 'y') && options.maxDate.year() <= endDecadeYear;
+ html += '<span data-action="selectDecade" class="decade' + (date.isAfter(startDecade) && date.year() <= endDecadeYear ? ' active' : '') +
+ (!isValid(startDecade, 'y') && !minDateDecade && !maxDateDecade ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
+ startDecade.add(12, 'y');
+ }
+ html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even
+
+ decadesView.find('td').html(html);
+ decadesViewHeader.eq(1).text((startedAt.year() + 1) + '-' + (startDecade.year()));
+ },
+
+ fillDate = function () {
+ var daysView = widget.find('.datepicker-days'),
+ daysViewHeader = daysView.find('th'),
+ currentDate,
+ html = [],
+ row,
+ clsNames = [],
+ i;
+
+ if (!hasDate()) {
+ return;
+ }
+
+ daysViewHeader.eq(0).find('span').attr('title', options.tooltips.prevMonth);
+ daysViewHeader.eq(1).attr('title', options.tooltips.selectMonth);
+ daysViewHeader.eq(2).find('span').attr('title', options.tooltips.nextMonth);
+
+ daysView.find('.disabled').removeClass('disabled');
+ daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat));
+
+ if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) {
+ daysViewHeader.eq(0).addClass('disabled');
+ }
+ if (!isValid(viewDate.clone().add(1, 'M'), 'M')) {
+ daysViewHeader.eq(2).addClass('disabled');
+ }
+
+ currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d');
+
+ for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks)
+ if (currentDate.weekday() === 0) {
+ row = $('<tr>');
+ if (options.calendarWeeks) {
+ row.append('<td class="cw">' + currentDate.week() + '</td>');
+ }
+ html.push(row);
+ }
+ clsNames = ['day'];
+ if (currentDate.isBefore(viewDate, 'M')) {
+ clsNames.push('old');
+ }
+ if (currentDate.isAfter(viewDate, 'M')) {
+ clsNames.push('new');
+ }
+ if (currentDate.isSame(date, 'd') && !unset) {
+ clsNames.push('active');
+ }
+ if (!isValid(currentDate, 'd')) {
+ clsNames.push('disabled');
+ }
+ if (currentDate.isSame(getMoment(), 'd')) {
+ clsNames.push('today');
+ }
+ if (currentDate.day() === 0 || currentDate.day() === 6) {
+ clsNames.push('weekend');
+ }
+ notifyEvent({
+ type: 'dp.classify',
+ date: currentDate,
+ classNames: clsNames
+ });
+ row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="' + clsNames.join(' ') + '">' + currentDate.date() + '</td>');
+ currentDate.add(1, 'd');
+ }
+
+ daysView.find('tbody').empty().append(html);
+
+ updateMonths();
+
+ updateYears();
+
+ updateDecades();
+ },
+
+ fillHours = function () {
+ var table = widget.find('.timepicker-hours table'),
+ currentHour = viewDate.clone().startOf('d'),
+ html = [],
+ row = $('<tr>');
+
+ if (viewDate.hour() > 11 && !use24Hours) {
+ currentHour.hour(12);
+ }
+ while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) {
+ if (currentHour.hour() % 4 === 0) {
+ row = $('<tr>');
+ html.push(row);
+ }
+ row.append('<td data-action="selectHour" class="hour' + (!isValid(currentHour, 'h') ? ' disabled' : '') + '">' + currentHour.format(use24Hours ? 'HH' : 'hh') + '</td>');
+ currentHour.add(1, 'h');
+ }
+ table.empty().append(html);
+ },
+
+ fillMinutes = function () {
+ var table = widget.find('.timepicker-minutes table'),
+ currentMinute = viewDate.clone().startOf('h'),
+ html = [],
+ row = $('<tr>'),
+ step = options.stepping === 1 ? 5 : options.stepping;
+
+ while (viewDate.isSame(currentMinute, 'h')) {
+ if (currentMinute.minute() % (step * 4) === 0) {
+ row = $('<tr>');
+ html.push(row);
+ }
+ row.append('<td data-action="selectMinute" class="minute' + (!isValid(currentMinute, 'm') ? ' disabled' : '') + '">' + currentMinute.format('mm') + '</td>');
+ currentMinute.add(step, 'm');
+ }
+ table.empty().append(html);
+ },
+
+ fillSeconds = function () {
+ var table = widget.find('.timepicker-seconds table'),
+ currentSecond = viewDate.clone().startOf('m'),
+ html = [],
+ row = $('<tr>');
+
+ while (viewDate.isSame(currentSecond, 'm')) {
+ if (currentSecond.second() % 20 === 0) {
+ row = $('<tr>');
+ html.push(row);
+ }
+ row.append('<td data-action="selectSecond" class="second' + (!isValid(currentSecond, 's') ? ' disabled' : '') + '">' + currentSecond.format('ss') + '</td>');
+ currentSecond.add(5, 's');
+ }
+
+ table.empty().append(html);
+ },
+
+ fillTime = function () {
+ var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]');
+
+ if (!use24Hours) {
+ toggle = widget.find('.timepicker [data-action=togglePeriod]');
+ newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h');
+
+ toggle.text(date.format('A'));
+
+ if (isValid(newDate, 'h')) {
+ toggle.removeClass('disabled');
+ } else {
+ toggle.addClass('disabled');
+ }
+ }
+ timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh'));
+ timeComponents.filter('[data-time-component=minutes]').text(date.format('mm'));
+ timeComponents.filter('[data-time-component=seconds]').text(date.format('ss'));
+
+ fillHours();
+ fillMinutes();
+ fillSeconds();
+ },
+
+ update = function () {
+ if (!widget) {
+ return;
+ }
+ fillDate();
+ fillTime();
+ },
+
+ setValue = function (targetMoment) {
+ var oldDate = unset ? null : date;
+
+ // case of calling setValue(null or false)
+ if (!targetMoment) {
+ unset = true;
+ input.val('');
+ element.data('date', '');
+ notifyEvent({
+ type: 'dp.change',
+ date: false,
+ oldDate: oldDate
+ });
+ update();
+ return;
+ }
+
+ targetMoment = targetMoment.clone().locale(options.locale);
+
+ if (hasTimeZone()) {
+ targetMoment.tz(options.timeZone);
+ }
+
+ if (options.stepping !== 1) {
+ targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping)).seconds(0);
+
+ while (options.minDate && targetMoment.isBefore(options.minDate)) {
+ targetMoment.add(options.stepping, 'minutes');
+ }
+ }
+
+ if (isValid(targetMoment)) {
+ date = targetMoment;
+ viewDate = date.clone();
+ input.val(date.format(actualFormat));
+ element.data('date', date.format(actualFormat));
+ unset = false;
+ update();
+ notifyEvent({
+ type: 'dp.change',
+ date: date.clone(),
+ oldDate: oldDate
+ });
+ } else {
+ if (!options.keepInvalid) {
+ input.val(unset ? '' : date.format(actualFormat));
+ } else {
+ notifyEvent({
+ type: 'dp.change',
+ date: targetMoment,
+ oldDate: oldDate
+ });
+ }
+ notifyEvent({
+ type: 'dp.error',
+ date: targetMoment,
+ oldDate: oldDate
+ });
+ }
+ },
+
+ /**
+ * Hides the widget. Possibly will emit dp.hide
+ */
+ hide = function () {
+ var transitioning = false;
+ if (!widget) {
+ return picker;
+ }
+ // Ignore event if in the middle of a picker transition
+ widget.find('.collapse').each(function () {
+ var collapseData = $(this).data('collapse');
+ if (collapseData && collapseData.transitioning) {
+ transitioning = true;
+ return false;
+ }
+ return true;
+ });
+ if (transitioning) {
+ return picker;
+ }
+ if (component && component.hasClass('btn')) {
+ component.toggleClass('active');
+ }
+ widget.hide();
+
+ $(window).off('resize', place);
+ widget.off('click', '[data-action]');
+ widget.off('mousedown', false);
+
+ widget.remove();
+ widget = false;
+
+ notifyEvent({
+ type: 'dp.hide',
+ date: date.clone()
+ });
+
+ input.blur();
+
+ viewDate = date.clone();
+
+ return picker;
+ },
+
+ clear = function () {
+ setValue(null);
+ },
+
+ parseInputDate = function (inputDate) {
+ if (options.parseInputDate === undefined) {
+ if (!moment.isMoment(inputDate) || inputDate instanceof Date) {
+ inputDate = getMoment(inputDate);
+ }
+ } else {
+ inputDate = options.parseInputDate(inputDate);
+ }
+ //inputDate.locale(options.locale);
+ return inputDate;
+ },
+
+ /********************************************************************************
+ *
+ * Widget UI interaction functions
+ *
+ ********************************************************************************/
+ actions = {
+ next: function () {
+ var navFnc = datePickerModes[currentViewMode].navFnc;
+ viewDate.add(datePickerModes[currentViewMode].navStep, navFnc);
+ fillDate();
+ viewUpdate(navFnc);
+ },
+
+ previous: function () {
+ var navFnc = datePickerModes[currentViewMode].navFnc;
+ viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc);
+ fillDate();
+ viewUpdate(navFnc);
+ },
+
+ pickerSwitch: function () {
+ showMode(1);
+ },
+
+ selectMonth: function (e) {
+ var month = $(e.target).closest('tbody').find('span').index($(e.target));
+ viewDate.month(month);
+ if (currentViewMode === minViewModeNumber) {
+ setValue(date.clone().year(viewDate.year()).month(viewDate.month()));
+ if (!options.inline) {
+ hide();
+ }
+ } else {
+ showMode(-1);
+ fillDate();
+ }
+ viewUpdate('M');
+ },
+
+ selectYear: function (e) {
+ var year = parseInt($(e.target).text(), 10) || 0;
+ viewDate.year(year);
+ if (currentViewMode === minViewModeNumber) {
+ setValue(date.clone().year(viewDate.year()));
+ if (!options.inline) {
+ hide();
+ }
+ } else {
+ showMode(-1);
+ fillDate();
+ }
+ viewUpdate('YYYY');
+ },
+
+ selectDecade: function (e) {
+ var year = parseInt($(e.target).data('selection'), 10) || 0;
+ viewDate.year(year);
+ if (currentViewMode === minViewModeNumber) {
+ setValue(date.clone().year(viewDate.year()));
+ if (!options.inline) {
+ hide();
+ }
+ } else {
+ showMode(-1);
+ fillDate();
+ }
+ viewUpdate('YYYY');
+ },
+
+ selectDay: function (e) {
+ var day = viewDate.clone();
+ if ($(e.target).is('.old')) {
+ day.subtract(1, 'M');
+ }
+ if ($(e.target).is('.new')) {
+ day.add(1, 'M');
+ }
+ setValue(day.date(parseInt($(e.target).text(), 10)));
+ if (!hasTime() && !options.keepOpen && !options.inline) {
+ hide();
+ }
+ },
+
+ incrementHours: function () {
+ var newDate = date.clone().add(1, 'h');
+ if (isValid(newDate, 'h')) {
+ setValue(newDate);
+ }
+ },
+
+ incrementMinutes: function () {
+ var newDate = date.clone().add(options.stepping, 'm');
+ if (isValid(newDate, 'm')) {
+ setValue(newDate);
+ }
+ },
+
+ incrementSeconds: function () {
+ var newDate = date.clone().add(1, 's');
+ if (isValid(newDate, 's')) {
+ setValue(newDate);
+ }
+ },
+
+ decrementHours: function () {
+ var newDate = date.clone().subtract(1, 'h');
+ if (isValid(newDate, 'h')) {
+ setValue(newDate);
+ }
+ },
+
+ decrementMinutes: function () {
+ var newDate = date.clone().subtract(options.stepping, 'm');
+ if (isValid(newDate, 'm')) {
+ setValue(newDate);
+ }
+ },
+
+ decrementSeconds: function () {
+ var newDate = date.clone().subtract(1, 's');
+ if (isValid(newDate, 's')) {
+ setValue(newDate);
+ }
+ },
+
+ togglePeriod: function () {
+ setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'));
+ },
+
+ togglePicker: function (e) {
+ var $this = $(e.target),
+ $parent = $this.closest('ul'),
+ expanded = $parent.find('.in'),
+ closed = $parent.find('.collapse:not(.in)'),
+ collapseData;
+
+ if (expanded && expanded.length) {
+ collapseData = expanded.data('collapse');
+ if (collapseData && collapseData.transitioning) {
+ return;
+ }
+ if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it
+ expanded.collapse('hide');
+ closed.collapse('show');
+ } else { // otherwise just toggle in class on the two views
+ expanded.removeClass('in');
+ closed.addClass('in');
+ }
+ if ($this.is('span')) {
+ $this.toggleClass(options.icons.time + ' ' + options.icons.date);
+ } else {
+ $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
+ }
+
+ // NOTE: uncomment if toggled state will be restored in show()
+ //if (component) {
+ // component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
+ //}
+ }
+ },
+
+ showPicker: function () {
+ widget.find('.timepicker > div:not(.timepicker-picker)').hide();
+ widget.find('.timepicker .timepicker-picker').show();
+ },
+
+ showHours: function () {
+ widget.find('.timepicker .timepicker-picker').hide();
+ widget.find('.timepicker .timepicker-hours').show();
+ },
+
+ showMinutes: function () {
+ widget.find('.timepicker .timepicker-picker').hide();
+ widget.find('.timepicker .timepicker-minutes').show();
+ },
+
+ showSeconds: function () {
+ widget.find('.timepicker .timepicker-picker').hide();
+ widget.find('.timepicker .timepicker-seconds').show();
+ },
+
+ selectHour: function (e) {
+ var hour = parseInt($(e.target).text(), 10);
+
+ if (!use24Hours) {
+ if (date.hours() >= 12) {
+ if (hour !== 12) {
+ hour += 12;
+ }
+ } else {
+ if (hour === 12) {
+ hour = 0;
+ }
+ }
+ }
+ setValue(date.clone().hours(hour));
+ actions.showPicker.call(picker);
+ },
+
+ selectMinute: function (e) {
+ setValue(date.clone().minutes(parseInt($(e.target).text(), 10)));
+ actions.showPicker.call(picker);
+ },
+
+ selectSecond: function (e) {
+ setValue(date.clone().seconds(parseInt($(e.target).text(), 10)));
+ actions.showPicker.call(picker);
+ },
+
+ clear: clear,
+
+ today: function () {
+ var todaysDate = getMoment();
+ if (isValid(todaysDate, 'd')) {
+ setValue(todaysDate);
+ }
+ },
+
+ close: hide
+ },
+
+ doAction = function (e) {
+ if ($(e.currentTarget).is('.disabled')) {
+ return false;
+ }
+ actions[$(e.currentTarget).data('action')].apply(picker, arguments);
+ return false;
+ },
+
+ /**
+ * Shows the widget. Possibly will emit dp.show and dp.change
+ */
+ show = function () {
+ var currentMoment,
+ useCurrentGranularity = {
+ 'year': function (m) {
+ return m.month(0).date(1).hours(0).seconds(0).minutes(0);
+ },
+ 'month': function (m) {
+ return m.date(1).hours(0).seconds(0).minutes(0);
+ },
+ 'day': function (m) {
+ return m.hours(0).seconds(0).minutes(0);
+ },
+ 'hour': function (m) {
+ return m.seconds(0).minutes(0);
+ },
+ 'minute': function (m) {
+ return m.seconds(0);
+ }
+ };
+
+ if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
+ return picker;
+ }
+ if (input.val() !== undefined && input.val().trim().length !== 0) {
+ setValue(parseInputDate(input.val().trim()));
+ } else if (unset && options.useCurrent && (options.inline || (input.is('input') && input.val().trim().length === 0))) {
+ currentMoment = getMoment();
+ if (typeof options.useCurrent === 'string') {
+ currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
+ }
+ setValue(currentMoment);
+ }
+ widget = getTemplate();
+
+ fillDow();
+ fillMonths();
+
+ widget.find('.timepicker-hours').hide();
+ widget.find('.timepicker-minutes').hide();
+ widget.find('.timepicker-seconds').hide();
+
+ update();
+ showMode();
+
+ $(window).on('resize', place);
+ widget.on('click', '[data-action]', doAction); // this handles clicks on the widget
+ widget.on('mousedown', false);
+
+ if (component && component.hasClass('btn')) {
+ component.toggleClass('active');
+ }
+ place();
+ widget.show();
+ if (options.focusOnShow && !input.is(':focus')) {
+ input.focus();
+ }
+
+ notifyEvent({
+ type: 'dp.show'
+ });
+ return picker;
+ },
+
+ /**
+ * Shows or hides the widget
+ */
+ toggle = function () {
+ return (widget ? hide() : show());
+ },
+
+ keydown = function (e) {
+ var handler = null,
+ index,
+ index2,
+ pressedKeys = [],
+ pressedModifiers = {},
+ currentKey = e.which,
+ keyBindKeys,
+ allModifiersPressed,
+ pressed = 'p';
+
+ keyState[currentKey] = pressed;
+
+ for (index in keyState) {
+ if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
+ pressedKeys.push(index);
+ if (parseInt(index, 10) !== currentKey) {
+ pressedModifiers[index] = true;
+ }
+ }
+ }
+
+ for (index in options.keyBinds) {
+ if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') {
+ keyBindKeys = index.split(' ');
+ if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
+ allModifiersPressed = true;
+ for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
+ if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) {
+ allModifiersPressed = false;
+ break;
+ }
+ }
+ if (allModifiersPressed) {
+ handler = options.keyBinds[index];
+ break;
+ }
+ }
+ }
+ }
+
+ if (handler) {
+ handler.call(picker, widget);
+ e.stopPropagation();
+ e.preventDefault();
+ }
+ },
+
+ keyup = function (e) {
+ keyState[e.which] = 'r';
+ e.stopPropagation();
+ e.preventDefault();
+ },
+
+ change = function (e) {
+ var val = $(e.target).val().trim(),
+ parsedDate = val ? parseInputDate(val) : null;
+ setValue(parsedDate);
+ e.stopImmediatePropagation();
+ return false;
+ },
+
+ attachDatePickerElementEvents = function () {
+ input.on({
+ 'change': change,
+ 'blur': options.debug ? '' : hide,
+ 'keydown': keydown,
+ 'keyup': keyup,
+ 'focus': options.allowInputToggle ? show : ''
+ });
+
+ if (element.is('input')) {
+ input.on({
+ 'focus': show
+ });
+ } else if (component) {
+ component.on('click', toggle);
+ component.on('mousedown', false);
+ }
+ },
+
+ detachDatePickerElementEvents = function () {
+ input.off({
+ 'change': change,
+ 'blur': blur,
+ 'keydown': keydown,
+ 'keyup': keyup,
+ 'focus': options.allowInputToggle ? hide : ''
+ });
+
+ if (element.is('input')) {
+ input.off({
+ 'focus': show
+ });
+ } else if (component) {
+ component.off('click', toggle);
+ component.off('mousedown', false);
+ }
+ },
+
+ indexGivenDates = function (givenDatesArray) {
+ // Store given enabledDates and disabledDates as keys.
+ // This way we can check their existence in O(1) time instead of looping through whole array.
+ // (for example: options.enabledDates['2014-02-27'] === true)
+ var givenDatesIndexed = {};
+ $.each(givenDatesArray, function () {
+ var dDate = parseInputDate(this);
+ if (dDate.isValid()) {
+ givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
+ }
+ });
+ return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false;
+ },
+
+ indexGivenHours = function (givenHoursArray) {
+ // Store given enabledHours and disabledHours as keys.
+ // This way we can check their existence in O(1) time instead of looping through whole array.
+ // (for example: options.enabledHours['2014-02-27'] === true)
+ var givenHoursIndexed = {};
+ $.each(givenHoursArray, function () {
+ givenHoursIndexed[this] = true;
+ });
+ return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false;
+ },
+
+ initFormatting = function () {
+ var format = options.format || 'L LT';
+
+ actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
+ var newinput = date.localeData().longDateFormat(formatInput) || formatInput;
+ return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740
+ return date.localeData().longDateFormat(formatInput2) || formatInput2;
+ });
+ });
+
+
+ parseFormats = options.extraFormats ? options.extraFormats.slice() : [];
+ if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) {
+ parseFormats.push(actualFormat);
+ }
+
+ use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1);
+
+ if (isEnabled('y')) {
+ minViewModeNumber = 2;
+ }
+ if (isEnabled('M')) {
+ minViewModeNumber = 1;
+ }
+ if (isEnabled('d')) {
+ minViewModeNumber = 0;
+ }
+
+ currentViewMode = Math.max(minViewModeNumber, currentViewMode);
+
+ if (!unset) {
+ setValue(date);
+ }
+ };
+
+ /********************************************************************************
+ *
+ * Public API functions
+ * =====================
+ *
+ * Important: Do not expose direct references to private objects or the options
+ * object to the outer world. Always return a clone when returning values or make
+ * a clone when setting a private variable.
+ *
+ ********************************************************************************/
+ picker.destroy = function () {
+ ///<summary>Destroys the widget and removes all attached event listeners</summary>
+ hide();
+ detachDatePickerElementEvents();
+ element.removeData('DateTimePicker');
+ element.removeData('date');
+ };
+
+ picker.toggle = toggle;
+
+ picker.show = show;
+
+ picker.hide = hide;
+
+ picker.disable = function () {
+ ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it.
+ ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary>
+ hide();
+ if (component && component.hasClass('btn')) {
+ component.addClass('disabled');
+ }
+ input.prop('disabled', true);
+ return picker;
+ };
+
+ picker.enable = function () {
+ ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary>
+ if (component && component.hasClass('btn')) {
+ component.removeClass('disabled');
+ }
+ input.prop('disabled', false);
+ return picker;
+ };
+
+ picker.ignoreReadonly = function (ignoreReadonly) {
+ if (arguments.length === 0) {
+ return options.ignoreReadonly;
+ }
+ if (typeof ignoreReadonly !== 'boolean') {
+ throw new TypeError('ignoreReadonly () expects a boolean parameter');
+ }
+ options.ignoreReadonly = ignoreReadonly;
+ return picker;
+ };
+
+ picker.options = function (newOptions) {
+ if (arguments.length === 0) {
+ return $.extend(true, {}, options);
+ }
+
+ if (!(newOptions instanceof Object)) {
+ throw new TypeError('options() options parameter should be an object');
+ }
+ $.extend(true, options, newOptions);
+ $.each(options, function (key, value) {
+ if (picker[key] !== undefined) {
+ picker[key](value);
+ } else {
+ throw new TypeError('option ' + key + ' is not recognized!');
+ }
+ });
+ return picker;
+ };
+
+ picker.date = function (newDate) {
+ ///<signature helpKeyword="$.fn.datetimepicker.date">
+ ///<summary>Returns the component's model current date, a moment object or null if not set.</summary>
+ ///<returns type="Moment">date.clone()</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
+ ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ if (unset) {
+ return null;
+ }
+ return date.clone();
+ }
+
+ if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
+ throw new TypeError('date() parameter must be one of [null, string, moment or Date]');
+ }
+
+ setValue(newDate === null ? null : parseInputDate(newDate));
+ return picker;
+ };
+
+ picker.format = function (newFormat) {
+ ///<summary>test su</summary>
+ ///<param name="newFormat">info about para</param>
+ ///<returns type="string|boolean">returns foo</returns>
+ if (arguments.length === 0) {
+ return options.format;
+ }
+
+ if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
+ throw new TypeError('format() expects a string or boolean:false parameter ' + newFormat);
+ }
+
+ options.format = newFormat;
+ if (actualFormat) {
+ initFormatting(); // reinit formatting
+ }
+ return picker;
+ };
+
+ picker.timeZone = function (newZone) {
+ if (arguments.length === 0) {
+ return options.timeZone;
+ }
+
+ if (typeof newZone !== 'string') {
+ throw new TypeError('newZone() expects a string parameter');
+ }
+
+ options.timeZone = newZone;
+
+ return picker;
+ };
+
+ picker.dayViewHeaderFormat = function (newFormat) {
+ if (arguments.length === 0) {
+ return options.dayViewHeaderFormat;
+ }
+
+ if (typeof newFormat !== 'string') {
+ throw new TypeError('dayViewHeaderFormat() expects a string parameter');
+ }
+
+ options.dayViewHeaderFormat = newFormat;
+ return picker;
+ };
+
+ picker.extraFormats = function (formats) {
+ if (arguments.length === 0) {
+ return options.extraFormats;
+ }
+
+ if (formats !== false && !(formats instanceof Array)) {
+ throw new TypeError('extraFormats() expects an array or false parameter');
+ }
+
+ options.extraFormats = formats;
+ if (parseFormats) {
+ initFormatting(); // reinit formatting
+ }
+ return picker;
+ };
+
+ picker.disabledDates = function (dates) {
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledDates">
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
+ ///<returns type="array">options.disabledDates</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+ ///options.enabledDates if such exist.</summary>
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates);
+ }
+
+ if (!dates) {
+ options.disabledDates = false;
+ update();
+ return picker;
+ }
+ if (!(dates instanceof Array)) {
+ throw new TypeError('disabledDates() expects an array parameter');
+ }
+ options.disabledDates = indexGivenDates(dates);
+ options.enabledDates = false;
+ update();
+ return picker;
+ };
+
+ picker.enabledDates = function (dates) {
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledDates">
+ ///<summary>Returns an array with the currently set enabled dates on the component.</summary>
+ ///<returns type="array">options.enabledDates</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary>
+ ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates);
+ }
+
+ if (!dates) {
+ options.enabledDates = false;
+ update();
+ return picker;
+ }
+ if (!(dates instanceof Array)) {
+ throw new TypeError('enabledDates() expects an array parameter');
+ }
+ options.enabledDates = indexGivenDates(dates);
+ options.disabledDates = false;
+ update();
+ return picker;
+ };
+
+ picker.daysOfWeekDisabled = function (daysOfWeekDisabled) {
+ if (arguments.length === 0) {
+ return options.daysOfWeekDisabled.splice(0);
+ }
+
+ if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) {
+ options.daysOfWeekDisabled = false;
+ update();
+ return picker;
+ }
+
+ if (!(daysOfWeekDisabled instanceof Array)) {
+ throw new TypeError('daysOfWeekDisabled() expects an array parameter');
+ }
+ options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
+ currentValue = parseInt(currentValue, 10);
+ if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {
+ return previousValue;
+ }
+ if (previousValue.indexOf(currentValue) === -1) {
+ previousValue.push(currentValue);
+ }
+ return previousValue;
+ }, []).sort();
+ if (options.useCurrent && !options.keepInvalid) {
+ var tries = 0;
+ while (!isValid(date, 'd')) {
+ date.add(1, 'd');
+ if (tries === 31) {
+ throw 'Tried 31 times to find a valid date';
+ }
+ tries++;
+ }
+ setValue(date);
+ }
+ update();
+ return picker;
+ };
+
+ picker.maxDate = function (maxDate) {
+ if (arguments.length === 0) {
+ return options.maxDate ? options.maxDate.clone() : options.maxDate;
+ }
+
+ if ((typeof maxDate === 'boolean') && maxDate === false) {
+ options.maxDate = false;
+ update();
+ return picker;
+ }
+
+ if (typeof maxDate === 'string') {
+ if (maxDate === 'now' || maxDate === 'moment') {
+ maxDate = getMoment();
+ }
+ }
+
+ var parsedDate = parseInputDate(maxDate);
+
+ if (!parsedDate.isValid()) {
+ throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate);
+ }
+ if (options.minDate && parsedDate.isBefore(options.minDate)) {
+ throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
+ }
+ options.maxDate = parsedDate;
+ if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) {
+ setValue(options.maxDate);
+ }
+ if (viewDate.isAfter(parsedDate)) {
+ viewDate = parsedDate.clone().subtract(options.stepping, 'm');
+ }
+ update();
+ return picker;
+ };
+
+ picker.minDate = function (minDate) {
+ if (arguments.length === 0) {
+ return options.minDate ? options.minDate.clone() : options.minDate;
+ }
+
+ if ((typeof minDate === 'boolean') && minDate === false) {
+ options.minDate = false;
+ update();
+ return picker;
+ }
+
+ if (typeof minDate === 'string') {
+ if (minDate === 'now' || minDate === 'moment') {
+ minDate = getMoment();
+ }
+ }
+
+ var parsedDate = parseInputDate(minDate);
+
+ if (!parsedDate.isValid()) {
+ throw new TypeError('minDate() Could not parse date parameter: ' + minDate);
+ }
+ if (options.maxDate && parsedDate.isAfter(options.maxDate)) {
+ throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
+ }
+ options.minDate = parsedDate;
+ if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) {
+ setValue(options.minDate);
+ }
+ if (viewDate.isBefore(parsedDate)) {
+ viewDate = parsedDate.clone().add(options.stepping, 'm');
+ }
+ update();
+ return picker;
+ };
+
+ picker.defaultDate = function (defaultDate) {
+ ///<signature helpKeyword="$.fn.datetimepicker.defaultDate">
+ ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary>
+ ///<returns type="Moment">date.clone()</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary>
+ ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return options.defaultDate ? options.defaultDate.clone() : options.defaultDate;
+ }
+ if (!defaultDate) {
+ options.defaultDate = false;
+ return picker;
+ }
+
+ if (typeof defaultDate === 'string') {
+ if (defaultDate === 'now' || defaultDate === 'moment') {
+ defaultDate = getMoment();
+ } else {
+ defaultDate = getMoment(defaultDate);
+ }
+ }
+
+ var parsedDate = parseInputDate(defaultDate);
+ if (!parsedDate.isValid()) {
+ throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate);
+ }
+ if (!isValid(parsedDate)) {
+ throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
+ }
+
+ options.defaultDate = parsedDate;
+
+ if ((options.defaultDate && options.inline) || input.val().trim() === '') {
+ setValue(options.defaultDate);
+ }
+ return picker;
+ };
+
+ picker.locale = function (locale) {
+ if (arguments.length === 0) {
+ return options.locale;
+ }
+
+ if (!moment.localeData(locale)) {
+ throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!');
+ }
+
+ options.locale = locale;
+ date.locale(options.locale);
+ viewDate.locale(options.locale);
+
+ if (actualFormat) {
+ initFormatting(); // reinit formatting
+ }
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.stepping = function (stepping) {
+ if (arguments.length === 0) {
+ return options.stepping;
+ }
+
+ stepping = parseInt(stepping, 10);
+ if (isNaN(stepping) || stepping < 1) {
+ stepping = 1;
+ }
+ options.stepping = stepping;
+ return picker;
+ };
+
+ picker.useCurrent = function (useCurrent) {
+ var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];
+ if (arguments.length === 0) {
+ return options.useCurrent;
+ }
+
+ if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) {
+ throw new TypeError('useCurrent() expects a boolean or string parameter');
+ }
+ if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) {
+ throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', '));
+ }
+ options.useCurrent = useCurrent;
+ return picker;
+ };
+
+ picker.collapse = function (collapse) {
+ if (arguments.length === 0) {
+ return options.collapse;
+ }
+
+ if (typeof collapse !== 'boolean') {
+ throw new TypeError('collapse() expects a boolean parameter');
+ }
+ if (options.collapse === collapse) {
+ return picker;
+ }
+ options.collapse = collapse;
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.icons = function (icons) {
+ if (arguments.length === 0) {
+ return $.extend({}, options.icons);
+ }
+
+ if (!(icons instanceof Object)) {
+ throw new TypeError('icons() expects parameter to be an Object');
+ }
+ $.extend(options.icons, icons);
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.tooltips = function (tooltips) {
+ if (arguments.length === 0) {
+ return $.extend({}, options.tooltips);
+ }
+
+ if (!(tooltips instanceof Object)) {
+ throw new TypeError('tooltips() expects parameter to be an Object');
+ }
+ $.extend(options.tooltips, tooltips);
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.useStrict = function (useStrict) {
+ if (arguments.length === 0) {
+ return options.useStrict;
+ }
+
+ if (typeof useStrict !== 'boolean') {
+ throw new TypeError('useStrict() expects a boolean parameter');
+ }
+ options.useStrict = useStrict;
+ return picker;
+ };
+
+ picker.sideBySide = function (sideBySide) {
+ if (arguments.length === 0) {
+ return options.sideBySide;
+ }
+
+ if (typeof sideBySide !== 'boolean') {
+ throw new TypeError('sideBySide() expects a boolean parameter');
+ }
+ options.sideBySide = sideBySide;
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.viewMode = function (viewMode) {
+ if (arguments.length === 0) {
+ return options.viewMode;
+ }
+
+ if (typeof viewMode !== 'string') {
+ throw new TypeError('viewMode() expects a string parameter');
+ }
+
+ if (viewModes.indexOf(viewMode) === -1) {
+ throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value');
+ }
+
+ options.viewMode = viewMode;
+ currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber);
+
+ showMode();
+ return picker;
+ };
+
+ picker.toolbarPlacement = function (toolbarPlacement) {
+ if (arguments.length === 0) {
+ return options.toolbarPlacement;
+ }
+
+ if (typeof toolbarPlacement !== 'string') {
+ throw new TypeError('toolbarPlacement() expects a string parameter');
+ }
+ if (toolbarPlacements.indexOf(toolbarPlacement) === -1) {
+ throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value');
+ }
+ options.toolbarPlacement = toolbarPlacement;
+
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.widgetPositioning = function (widgetPositioning) {
+ if (arguments.length === 0) {
+ return $.extend({}, options.widgetPositioning);
+ }
+
+ if (({}).toString.call(widgetPositioning) !== '[object Object]') {
+ throw new TypeError('widgetPositioning() expects an object variable');
+ }
+ if (widgetPositioning.horizontal) {
+ if (typeof widgetPositioning.horizontal !== 'string') {
+ throw new TypeError('widgetPositioning() horizontal variable must be a string');
+ }
+ widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase();
+ if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) {
+ throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')');
+ }
+ options.widgetPositioning.horizontal = widgetPositioning.horizontal;
+ }
+ if (widgetPositioning.vertical) {
+ if (typeof widgetPositioning.vertical !== 'string') {
+ throw new TypeError('widgetPositioning() vertical variable must be a string');
+ }
+ widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase();
+ if (verticalModes.indexOf(widgetPositioning.vertical) === -1) {
+ throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')');
+ }
+ options.widgetPositioning.vertical = widgetPositioning.vertical;
+ }
+ update();
+ return picker;
+ };
+
+ picker.calendarWeeks = function (calendarWeeks) {
+ if (arguments.length === 0) {
+ return options.calendarWeeks;
+ }
+
+ if (typeof calendarWeeks !== 'boolean') {
+ throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
+ }
+
+ options.calendarWeeks = calendarWeeks;
+ update();
+ return picker;
+ };
+
+ picker.showTodayButton = function (showTodayButton) {
+ if (arguments.length === 0) {
+ return options.showTodayButton;
+ }
+
+ if (typeof showTodayButton !== 'boolean') {
+ throw new TypeError('showTodayButton() expects a boolean parameter');
+ }
+
+ options.showTodayButton = showTodayButton;
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.showClear = function (showClear) {
+ if (arguments.length === 0) {
+ return options.showClear;
+ }
+
+ if (typeof showClear !== 'boolean') {
+ throw new TypeError('showClear() expects a boolean parameter');
+ }
+
+ options.showClear = showClear;
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.widgetParent = function (widgetParent) {
+ if (arguments.length === 0) {
+ return options.widgetParent;
+ }
+
+ if (typeof widgetParent === 'string') {
+ widgetParent = $(widgetParent);
+ }
+
+ if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) {
+ throw new TypeError('widgetParent() expects a string or a jQuery object parameter');
+ }
+
+ options.widgetParent = widgetParent;
+ if (widget) {
+ hide();
+ show();
+ }
+ return picker;
+ };
+
+ picker.keepOpen = function (keepOpen) {
+ if (arguments.length === 0) {
+ return options.keepOpen;
+ }
+
+ if (typeof keepOpen !== 'boolean') {
+ throw new TypeError('keepOpen() expects a boolean parameter');
+ }
+
+ options.keepOpen = keepOpen;
+ return picker;
+ };
+
+ picker.focusOnShow = function (focusOnShow) {
+ if (arguments.length === 0) {
+ return options.focusOnShow;
+ }
+
+ if (typeof focusOnShow !== 'boolean') {
+ throw new TypeError('focusOnShow() expects a boolean parameter');
+ }
+
+ options.focusOnShow = focusOnShow;
+ return picker;
+ };
+
+ picker.inline = function (inline) {
+ if (arguments.length === 0) {
+ return options.inline;
+ }
+
+ if (typeof inline !== 'boolean') {
+ throw new TypeError('inline() expects a boolean parameter');
+ }
+
+ options.inline = inline;
+ return picker;
+ };
+
+ picker.clear = function () {
+ clear();
+ return picker;
+ };
+
+ picker.keyBinds = function (keyBinds) {
+ if (arguments.length === 0) {
+ return options.keyBinds;
+ }
+
+ options.keyBinds = keyBinds;
+ return picker;
+ };
+
+ picker.getMoment = function (d) {
+ return getMoment(d);
+ };
+
+ picker.debug = function (debug) {
+ if (typeof debug !== 'boolean') {
+ throw new TypeError('debug() expects a boolean parameter');
+ }
+
+ options.debug = debug;
+ return picker;
+ };
+
+ picker.allowInputToggle = function (allowInputToggle) {
+ if (arguments.length === 0) {
+ return options.allowInputToggle;
+ }
+
+ if (typeof allowInputToggle !== 'boolean') {
+ throw new TypeError('allowInputToggle() expects a boolean parameter');
+ }
+
+ options.allowInputToggle = allowInputToggle;
+ return picker;
+ };
+
+ picker.showClose = function (showClose) {
+ if (arguments.length === 0) {
+ return options.showClose;
+ }
+
+ if (typeof showClose !== 'boolean') {
+ throw new TypeError('showClose() expects a boolean parameter');
+ }
+
+ options.showClose = showClose;
+ return picker;
+ };
+
+ picker.keepInvalid = function (keepInvalid) {
+ if (arguments.length === 0) {
+ return options.keepInvalid;
+ }
+
+ if (typeof keepInvalid !== 'boolean') {
+ throw new TypeError('keepInvalid() expects a boolean parameter');
+ }
+ options.keepInvalid = keepInvalid;
+ return picker;
+ };
+
+ picker.datepickerInput = function (datepickerInput) {
+ if (arguments.length === 0) {
+ return options.datepickerInput;
+ }
+
+ if (typeof datepickerInput !== 'string') {
+ throw new TypeError('datepickerInput() expects a string parameter');
+ }
+
+ options.datepickerInput = datepickerInput;
+ return picker;
+ };
+
+ picker.parseInputDate = function (parseInputDate) {
+ if (arguments.length === 0) {
+ return options.parseInputDate;
+ }
+
+ if (typeof parseInputDate !== 'function') {
+ throw new TypeError('parseInputDate() sholud be as function');
+ }
+
+ options.parseInputDate = parseInputDate;
+
+ return picker;
+ };
+
+ picker.disabledTimeIntervals = function (disabledTimeIntervals) {
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals">
+ ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
+ ///<returns type="array">options.disabledTimeIntervals</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+ ///options.enabledDates if such exist.</summary>
+ ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals);
+ }
+
+ if (!disabledTimeIntervals) {
+ options.disabledTimeIntervals = false;
+ update();
+ return picker;
+ }
+ if (!(disabledTimeIntervals instanceof Array)) {
+ throw new TypeError('disabledTimeIntervals() expects an array parameter');
+ }
+ options.disabledTimeIntervals = disabledTimeIntervals;
+ update();
+ return picker;
+ };
+
+ picker.disabledHours = function (hours) {
+ ///<signature helpKeyword="$.fn.datetimepicker.disabledHours">
+ ///<summary>Returns an array with the currently set disabled hours on the component.</summary>
+ ///<returns type="array">options.disabledHours</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+ ///options.enabledHours if such exist.</summary>
+ ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours);
+ }
+
+ if (!hours) {
+ options.disabledHours = false;
+ update();
+ return picker;
+ }
+ if (!(hours instanceof Array)) {
+ throw new TypeError('disabledHours() expects an array parameter');
+ }
+ options.disabledHours = indexGivenHours(hours);
+ options.enabledHours = false;
+ if (options.useCurrent && !options.keepInvalid) {
+ var tries = 0;
+ while (!isValid(date, 'h')) {
+ date.add(1, 'h');
+ if (tries === 24) {
+ throw 'Tried 24 times to find a valid date';
+ }
+ tries++;
+ }
+ setValue(date);
+ }
+ update();
+ return picker;
+ };
+
+ picker.enabledHours = function (hours) {
+ ///<signature helpKeyword="$.fn.datetimepicker.enabledHours">
+ ///<summary>Returns an array with the currently set enabled hours on the component.</summary>
+ ///<returns type="array">options.enabledHours</returns>
+ ///</signature>
+ ///<signature>
+ ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary>
+ ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param>
+ ///</signature>
+ if (arguments.length === 0) {
+ return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours);
+ }
+
+ if (!hours) {
+ options.enabledHours = false;
+ update();
+ return picker;
+ }
+ if (!(hours instanceof Array)) {
+ throw new TypeError('enabledHours() expects an array parameter');
+ }
+ options.enabledHours = indexGivenHours(hours);
+ options.disabledHours = false;
+ if (options.useCurrent && !options.keepInvalid) {
+ var tries = 0;
+ while (!isValid(date, 'h')) {
+ date.add(1, 'h');
+ if (tries === 24) {
+ throw 'Tried 24 times to find a valid date';
+ }
+ tries++;
+ }
+ setValue(date);
+ }
+ update();
+ return picker;
+ };
+ /**
+ * Returns the component's model current viewDate, a moment object or null if not set. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.
+ * @param {Takes string, viewDate, moment, null parameter.} newDate
+ * @returns {viewDate.clone()}
+ */
+ picker.viewDate = function (newDate) {
+ if (arguments.length === 0) {
+ return viewDate.clone();
+ }
+
+ if (!newDate) {
+ viewDate = date.clone();
+ return picker;
+ }
+
+ if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
+ throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
+ }
+
+ viewDate = parseInputDate(newDate);
+ viewUpdate();
+ return picker;
+ };
+
+ // initializing element and component attributes
+ if (element.is('input')) {
+ input = element;
+ } else {
+ input = element.find(options.datepickerInput);
+ if (input.length === 0) {
+ input = element.find('input');
+ } else if (!input.is('input')) {
+ throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
+ }
+ }
+
+ if (element.hasClass('input-group')) {
+ // in case there is more then one 'input-group-addon' Issue #48
+ if (element.find('.datepickerbutton').length === 0) {
+ component = element.find('.input-group-addon');
+ } else {
+ component = element.find('.datepickerbutton');
+ }
+ }
+
+ if (!options.inline && !input.is('input')) {
+ throw new Error('Could not initialize DateTimePicker without an input element');
+ }
+
+ // Set defaults for date here now instead of in var declaration
+ date = getMoment();
+ viewDate = date.clone();
+
+ $.extend(true, options, dataToOptions());
+
+ picker.options(options);
+
+ initFormatting();
+
+ attachDatePickerElementEvents();
+
+ if (input.prop('disabled')) {
+ picker.disable();
+ }
+ if (input.is('input') && input.val().trim().length !== 0) {
+ setValue(parseInputDate(input.val().trim()));
+ }
+ else if (options.defaultDate && input.attr('placeholder') === undefined) {
+ setValue(options.defaultDate);
+ }
+ if (options.inline) {
+ show();
+ }
+ return picker;
+ };
+
+ /********************************************************************************
+ *
+ * jQuery plugin constructor and defaults object
+ *
+ ********************************************************************************/
+
+ /**
+ * See (http://jquery.com/).
+ * @name jQuery
+ * @class
+ * See the jQuery Library (http://jquery.com/) for full details. This just
+ * documents the function and classes that are added to jQuery by this plug-in.
+ */
+ /**
+ * See (http://jquery.com/)
+ * @name fn
+ * @class
+ * See the jQuery Library (http://jquery.com/) for full details. This just
+ * documents the function and classes that are added to jQuery by this plug-in.
+ * @memberOf jQuery
+ */
+ /**
+ * Show comments
+ * @class datetimepicker
+ * @memberOf jQuery.fn
+ */
+ $.fn.datetimepicker = function (options) {
+ options = options || {};
+
+ var args = Array.prototype.slice.call(arguments, 1),
+ isInstance = true,
+ thisMethods = ['destroy', 'hide', 'show', 'toggle'],
+ returnValue;
+
+ if (typeof options === 'object') {
+ return this.each(function () {
+ var $this = $(this),
+ _options;
+ if (!$this.data('DateTimePicker')) {
+ // create a private copy of the defaults object
+ _options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
+ $this.data('DateTimePicker', dateTimePicker($this, _options));
+ }
+ });
+ } else if (typeof options === 'string') {
+ this.each(function () {
+ var $this = $(this),
+ instance = $this.data('DateTimePicker');
+ if (!instance) {
+ throw new Error('bootstrap-datetimepicker("' + options + '") method was called on an element that is not using DateTimePicker');
+ }
+
+ returnValue = instance[options].apply(instance, args);
+ isInstance = returnValue === instance;
+ });
+
+ if (isInstance || $.inArray(options, thisMethods) > -1) {
+ return this;
+ }
+
+ return returnValue;
+ }
+
+ throw new TypeError('Invalid arguments for DateTimePicker: ' + options);
+ };
+
+ $.fn.datetimepicker.defaults = {
+ timeZone: '',
+ format: false,
+ dayViewHeaderFormat: 'MMMM YYYY',
+ extraFormats: false,
+ stepping: 1,
+ minDate: false,
+ maxDate: false,
+ useCurrent: true,
+ collapse: true,
+ locale: moment.locale(),
+ defaultDate: false,
+ disabledDates: false,
+ enabledDates: false,
+ icons: {
+ time: 'glyphicon glyphicon-time',
+ date: 'glyphicon glyphicon-calendar',
+ up: 'glyphicon glyphicon-chevron-up',
+ down: 'glyphicon glyphicon-chevron-down',
+ previous: 'glyphicon glyphicon-chevron-left',
+ next: 'glyphicon glyphicon-chevron-right',
+ today: 'glyphicon glyphicon-screenshot',
+ clear: 'glyphicon glyphicon-trash',
+ close: 'glyphicon glyphicon-remove'
+ },
+ tooltips: {
+ today: 'Go to today',
+ clear: 'Clear selection',
+ close: 'Close the picker',
+ selectMonth: 'Select Month',
+ prevMonth: 'Previous Month',
+ nextMonth: 'Next Month',
+ selectYear: 'Select Year',
+ prevYear: 'Previous Year',
+ nextYear: 'Next Year',
+ selectDecade: 'Select Decade',
+ prevDecade: 'Previous Decade',
+ nextDecade: 'Next Decade',
+ prevCentury: 'Previous Century',
+ nextCentury: 'Next Century',
+ pickHour: 'Pick Hour',
+ incrementHour: 'Increment Hour',
+ decrementHour: 'Decrement Hour',
+ pickMinute: 'Pick Minute',
+ incrementMinute: 'Increment Minute',
+ decrementMinute: 'Decrement Minute',
+ pickSecond: 'Pick Second',
+ incrementSecond: 'Increment Second',
+ decrementSecond: 'Decrement Second',
+ togglePeriod: 'Toggle Period',
+ selectTime: 'Select Time'
+ },
+ useStrict: false,
+ sideBySide: false,
+ daysOfWeekDisabled: false,
+ calendarWeeks: false,
+ viewMode: 'days',
+ toolbarPlacement: 'default',
+ showTodayButton: false,
+ showClear: false,
+ showClose: false,
+ widgetPositioning: {
+ horizontal: 'auto',
+ vertical: 'auto'
+ },
+ widgetParent: null,
+ ignoreReadonly: false,
+ keepOpen: false,
+ focusOnShow: true,
+ inline: false,
+ keepInvalid: false,
+ datepickerInput: '.datepickerinput',
+ keyBinds: {
+ up: function (widget) {
+ if (!widget) {
+ return;
+ }
+ var d = this.date() || this.getMoment();
+ if (widget.find('.datepicker').is(':visible')) {
+ this.date(d.clone().subtract(7, 'd'));
+ } else {
+ this.date(d.clone().add(this.stepping(), 'm'));
+ }
+ },
+ down: function (widget) {
+ if (!widget) {
+ this.show();
+ return;
+ }
+ var d = this.date() || this.getMoment();
+ if (widget.find('.datepicker').is(':visible')) {
+ this.date(d.clone().add(7, 'd'));
+ } else {
+ this.date(d.clone().subtract(this.stepping(), 'm'));
+ }
+ },
+ 'control up': function (widget) {
+ if (!widget) {
+ return;
+ }
+ var d = this.date() || this.getMoment();
+ if (widget.find('.datepicker').is(':visible')) {
+ this.date(d.clone().subtract(1, 'y'));
+ } else {
+ this.date(d.clone().add(1, 'h'));
+ }
+ },
+ 'control down': function (widget) {
+ if (!widget) {
+ return;
+ }
+ var d = this.date() || this.getMoment();
+ if (widget.find('.datepicker').is(':visible')) {
+ this.date(d.clone().add(1, 'y'));
+ } else {
+ this.date(d.clone().subtract(1, 'h'));
+ }
+ },
+ left: function (widget) {
+ if (!widget) {
+ return;
+ }
+ var d = this.date() || this.getMoment();
+ if (widget.find('.datepicker').is(':visible')) {
+ this.date(d.clone().subtract(1, 'd'));
+ }
+ },
+ right: function (widget) {
+ if (!widget) {
+ return;
+ }
+ var d = this.date() || this.getMoment();
+ if (widget.find('.datepicker').is(':visible')) {
+ this.date(d.clone().add(1, 'd'));
+ }
+ },
+ pageUp: function (widget) {
+ if (!widget) {
+ return;
+ }
+ var d = this.date() || this.getMoment();
+ if (widget.find('.datepicker').is(':visible')) {
+ this.date(d.clone().subtract(1, 'M'));
+ }
+ },
+ pageDown: function (widget) {
+ if (!widget) {
+ return;
+ }
+ var d = this.date() || this.getMoment();
+ if (widget.find('.datepicker').is(':visible')) {
+ this.date(d.clone().add(1, 'M'));
+ }
+ },
+ enter: function () {
+ this.hide();
+ },
+ escape: function () {
+ this.hide();
+ },
+ //tab: function (widget) { //this break the flow of the form. disabling for now
+ // var toggle = widget.find('.picker-switch a[data-action="togglePicker"]');
+ // if(toggle.length > 0) toggle.click();
+ //},
+ 'control space': function (widget) {
+ if (!widget) {
+ return;
+ }
+ if (widget.find('.timepicker').is(':visible')) {
+ widget.find('.btn[data-action="togglePeriod"]').click();
+ }
+ },
+ t: function () {
+ this.date(this.getMoment());
+ },
+ 'delete': function () {
+ this.clear();
+ }
+ },
+ debug: false,
+ allowInputToggle: false,
+ disabledTimeIntervals: false,
+ disabledHours: false,
+ enabledHours: false,
+ viewDate: false
+ };
+
+ return $.fn.datetimepicker;
+}));
+
+
+/***/ }),
+/* 137 */
+/***/ (function(module, exports, __webpack_require__) {
+
+/* WEBPACK VAR INJECTION */(function(jQuery) {/*!
+ Colorbox 1.6.4
+ license: MIT
+ http://www.jacklmoore.com/colorbox
+*/
+(function ($, document, window) {
+ var
+ // Default settings object.
+ // See http://jacklmoore.com/colorbox for details.
+ defaults = {
+ // data sources
+ html: false,
+ photo: false,
+ iframe: false,
+ inline: false,
+
+ // behavior and appearance
+ transition: "elastic",
+ speed: 300,
+ fadeOut: 300,
+ width: false,
+ initialWidth: "600",
+ innerWidth: false,
+ maxWidth: false,
+ height: false,
+ initialHeight: "450",
+ innerHeight: false,
+ maxHeight: false,
+ scalePhotos: true,
+ scrolling: true,
+ opacity: 0.9,
+ preloading: true,
+ className: false,
+ overlayClose: true,
+ escKey: true,
+ arrowKey: true,
+ top: false,
+ bottom: false,
+ left: false,
+ right: false,
+ fixed: false,
+ data: undefined,
+ closeButton: true,
+ fastIframe: true,
+ open: false,
+ reposition: true,
+ loop: true,
+ slideshow: false,
+ slideshowAuto: true,
+ slideshowSpeed: 2500,
+ slideshowStart: "start slideshow",
+ slideshowStop: "stop slideshow",
+ photoRegex: /\.(gif|png|jp(e|g|eg)|bmp|ico|webp|jxr|svg)((#|\?).*)?$/i,
+
+ // alternate image paths for high-res displays
+ retinaImage: false,
+ retinaUrl: false,
+ retinaSuffix: '@2x.$1',
+
+ // internationalization
+ current: "image {current} of {total}",
+ previous: "previous",
+ next: "next",
+ close: "close",
+ xhrError: "This content failed to load.",
+ imgError: "This image failed to load.",
+
+ // accessbility
+ returnFocus: true,
+ trapFocus: true,
+
+ // callbacks
+ onOpen: false,
+ onLoad: false,
+ onComplete: false,
+ onCleanup: false,
+ onClosed: false,
+
+ rel: function() {
+ return this.rel;
+ },
+ href: function() {
+ // using this.href would give the absolute url, when the href may have been inteded as a selector (e.g. '#container')
+ return $(this).attr('href');
+ },
+ title: function() {
+ return this.title;
+ },
+ createImg: function() {
+ var img = new Image();
+ var attrs = $(this).data('cbox-img-attrs');
+
+ if (typeof attrs === 'object') {
+ $.each(attrs, function(key, val){
+ img[key] = val;
+ });
+ }
+
+ return img;
+ },
+ createIframe: function() {
+ var iframe = document.createElement('iframe');
+ var attrs = $(this).data('cbox-iframe-attrs');
+
+ if (typeof attrs === 'object') {
+ $.each(attrs, function(key, val){
+ iframe[key] = val;
+ });
+ }
+
+ if ('frameBorder' in iframe) {
+ iframe.frameBorder = 0;
+ }
+ if ('allowTransparency' in iframe) {
+ iframe.allowTransparency = "true";
+ }
+ iframe.name = (new Date()).getTime(); // give the iframe a unique name to prevent caching
+ iframe.allowFullscreen = true;
+
+ return iframe;
+ }
+ },
+
+ // Abstracting the HTML and event identifiers for easy rebranding
+ colorbox = 'colorbox',
+ prefix = 'cbox',
+ boxElement = prefix + 'Element',
+
+ // Events
+ event_open = prefix + '_open',
+ event_load = prefix + '_load',
+ event_complete = prefix + '_complete',
+ event_cleanup = prefix + '_cleanup',
+ event_closed = prefix + '_closed',
+ event_purge = prefix + '_purge',
+
+ // Cached jQuery Object Variables
+ $overlay,
+ $box,
+ $wrap,
+ $content,
+ $topBorder,
+ $leftBorder,
+ $rightBorder,
+ $bottomBorder,
+ $related,
+ $window,
+ $loaded,
+ $loadingBay,
+ $loadingOverlay,
+ $title,
+ $current,
+ $slideshow,
+ $next,
+ $prev,
+ $close,
+ $groupControls,
+ $events = $('<a/>'), // $({}) would be prefered, but there is an issue with jQuery 1.4.2
+
+ // Variables for cached values or use across multiple functions
+ settings,
+ interfaceHeight,
+ interfaceWidth,
+ loadedHeight,
+ loadedWidth,
+ index,
+ photo,
+ open,
+ active,
+ closing,
+ loadingTimer,
+ publicMethod,
+ div = "div",
+ requests = 0,
+ previousCSS = {},
+ init;
+
+ // ****************
+ // HELPER FUNCTIONS
+ // ****************
+
+ // Convenience function for creating new jQuery objects
+ function $tag(tag, id, css) {
+ var element = document.createElement(tag);
+
+ if (id) {
+ element.id = prefix + id;
+ }
+
+ if (css) {
+ element.style.cssText = css;
+ }
+
+ return $(element);
+ }
+
+ // Get the window height using innerHeight when available to avoid an issue with iOS
+ // http://bugs.jquery.com/ticket/6724
+ function winheight() {
+ return window.innerHeight ? window.innerHeight : $(window).height();
+ }
+
+ function Settings(element, options) {
+ if (options !== Object(options)) {
+ options = {};
+ }
+
+ this.cache = {};
+ this.el = element;
+
+ this.value = function(key) {
+ var dataAttr;
+
+ if (this.cache[key] === undefined) {
+ dataAttr = $(this.el).attr('data-cbox-'+key);
+
+ if (dataAttr !== undefined) {
+ this.cache[key] = dataAttr;
+ } else if (options[key] !== undefined) {
+ this.cache[key] = options[key];
+ } else if (defaults[key] !== undefined) {
+ this.cache[key] = defaults[key];
+ }
+ }
+
+ return this.cache[key];
+ };
+
+ this.get = function(key) {
+ var value = this.value(key);
+ return $.isFunction(value) ? value.call(this.el, this) : value;
+ };
+ }
+
+ // Determine the next and previous members in a group.
+ function getIndex(increment) {
+ var
+ max = $related.length,
+ newIndex = (index + increment) % max;
+
+ return (newIndex < 0) ? max + newIndex : newIndex;
+ }
+
+ // Convert '%' and 'px' values to integers
+ function setSize(size, dimension) {
+ return Math.round((/%/.test(size) ? ((dimension === 'x' ? $window.width() : winheight()) / 100) : 1) * parseInt(size, 10));
+ }
+
+ // Checks an href to see if it is a photo.
+ // There is a force photo option (photo: true) for hrefs that cannot be matched by the regex.
+ function isImage(settings, url) {
+ return settings.get('photo') || settings.get('photoRegex').test(url);
+ }
+
+ function retinaUrl(settings, url) {
+ return settings.get('retinaUrl') && window.devicePixelRatio > 1 ? url.replace(settings.get('photoRegex'), settings.get('retinaSuffix')) : url;
+ }
+
+ function trapFocus(e) {
+ if ('contains' in $box[0] && !$box[0].contains(e.target) && e.target !== $overlay[0]) {
+ e.stopPropagation();
+ $box.focus();
+ }
+ }
+
+ function setClass(str) {
+ if (setClass.str !== str) {
+ $box.add($overlay).removeClass(setClass.str).addClass(str);
+ setClass.str = str;
+ }
+ }
+
+ function getRelated(rel) {
+ index = 0;
+
+ if (rel && rel !== false && rel !== 'nofollow') {
+ $related = $('.' + boxElement).filter(function () {
+ var options = $.data(this, colorbox);
+ var settings = new Settings(this, options);
+ return (settings.get('rel') === rel);
+ });
+ index = $related.index(settings.el);
+
+ // Check direct calls to Colorbox.
+ if (index === -1) {
+ $related = $related.add(settings.el);
+ index = $related.length - 1;
+ }
+ } else {
+ $related = $(settings.el);
+ }
+ }
+
+ function trigger(event) {
+ // for external use
+ $(document).trigger(event);
+ // for internal use
+ $events.triggerHandler(event);
+ }
+
+ var slideshow = (function(){
+ var active,
+ className = prefix + "Slideshow_",
+ click = "click." + prefix,
+ timeOut;
+
+ function clear () {
+ clearTimeout(timeOut);
+ }
+
+ function set() {
+ if (settings.get('loop') || $related[index + 1]) {
+ clear();
+ timeOut = setTimeout(publicMethod.next, settings.get('slideshowSpeed'));
+ }
+ }
+
+ function start() {
+ $slideshow
+ .html(settings.get('slideshowStop'))
+ .unbind(click)
+ .one(click, stop);
+
+ $events
+ .bind(event_complete, set)
+ .bind(event_load, clear);
+
+ $box.removeClass(className + "off").addClass(className + "on");
+ }
+
+ function stop() {
+ clear();
+
+ $events
+ .unbind(event_complete, set)
+ .unbind(event_load, clear);
+
+ $slideshow
+ .html(settings.get('slideshowStart'))
+ .unbind(click)
+ .one(click, function () {
+ publicMethod.next();
+ start();
+ });
+
+ $box.removeClass(className + "on").addClass(className + "off");
+ }
+
+ function reset() {
+ active = false;
+ $slideshow.hide();
+ clear();
+ $events
+ .unbind(event_complete, set)
+ .unbind(event_load, clear);
+ $box.removeClass(className + "off " + className + "on");
+ }
+
+ return function(){
+ if (active) {
+ if (!settings.get('slideshow')) {
+ $events.unbind(event_cleanup, reset);
+ reset();
+ }
+ } else {
+ if (settings.get('slideshow') && $related[1]) {
+ active = true;
+ $events.one(event_cleanup, reset);
+ if (settings.get('slideshowAuto')) {
+ start();
+ } else {
+ stop();
+ }
+ $slideshow.show();
+ }
+ }
+ };
+
+ }());
+
+
+ function launch(element) {
+ var options;
+
+ if (!closing) {
+
+ options = $(element).data(colorbox);
+
+ settings = new Settings(element, options);
+
+ getRelated(settings.get('rel'));
+
+ if (!open) {
+ open = active = true; // Prevents the page-change action from queuing up if the visitor holds down the left or right keys.
+
+ setClass(settings.get('className'));
+
+ // Show colorbox so the sizes can be calculated in older versions of jQuery
+ $box.css({visibility:'hidden', display:'block', opacity:''});
+
+ $loaded = $tag(div, 'LoadedContent', 'width:0; height:0; overflow:hidden; visibility:hidden');
+ $content.css({width:'', height:''}).append($loaded);
+
+ // Cache values needed for size calculations
+ interfaceHeight = $topBorder.height() + $bottomBorder.height() + $content.outerHeight(true) - $content.height();
+ interfaceWidth = $leftBorder.width() + $rightBorder.width() + $content.outerWidth(true) - $content.width();
+ loadedHeight = $loaded.outerHeight(true);
+ loadedWidth = $loaded.outerWidth(true);
+
+ // Opens inital empty Colorbox prior to content being loaded.
+ var initialWidth = setSize(settings.get('initialWidth'), 'x');
+ var initialHeight = setSize(settings.get('initialHeight'), 'y');
+ var maxWidth = settings.get('maxWidth');
+ var maxHeight = settings.get('maxHeight');
+
+ settings.w = Math.max((maxWidth !== false ? Math.min(initialWidth, setSize(maxWidth, 'x')) : initialWidth) - loadedWidth - interfaceWidth, 0);
+ settings.h = Math.max((maxHeight !== false ? Math.min(initialHeight, setSize(maxHeight, 'y')) : initialHeight) - loadedHeight - interfaceHeight, 0);
+
+ $loaded.css({width:'', height:settings.h});
+ publicMethod.position();
+
+ trigger(event_open);
+ settings.get('onOpen');
+
+ $groupControls.add($title).hide();
+
+ $box.focus();
+
+ if (settings.get('trapFocus')) {
+ // Confine focus to the modal
+ // Uses event capturing that is not supported in IE8-
+ if (document.addEventListener) {
+
+ document.addEventListener('focus', trapFocus, true);
+
+ $events.one(event_closed, function () {
+ document.removeEventListener('focus', trapFocus, true);
+ });
+ }
+ }
+
+ // Return focus on closing
+ if (settings.get('returnFocus')) {
+ $events.one(event_closed, function () {
+ $(settings.el).focus();
+ });
+ }
+ }
+
+ var opacity = parseFloat(settings.get('opacity'));
+ $overlay.css({
+ opacity: opacity === opacity ? opacity : '',
+ cursor: settings.get('overlayClose') ? 'pointer' : '',
+ visibility: 'visible'
+ }).show();
+
+ if (settings.get('closeButton')) {
+ $close.html(settings.get('close')).appendTo($content);
+ } else {
+ $close.appendTo('<div/>'); // replace with .detach() when dropping jQuery < 1.4
+ }
+
+ load();
+ }
+ }
+
+ // Colorbox's markup needs to be added to the DOM prior to being called
+ // so that the browser will go ahead and load the CSS background images.
+ function appendHTML() {
+ if (!$box) {
+ init = false;
+ $window = $(window);
+ $box = $tag(div).attr({
+ id: colorbox,
+ 'class': $.support.opacity === false ? prefix + 'IE' : '', // class for optional IE8 & lower targeted CSS.
+ role: 'dialog',
+ tabindex: '-1'
+ }).hide();
+ $overlay = $tag(div, "Overlay").hide();
+ $loadingOverlay = $([$tag(div, "LoadingOverlay")[0],$tag(div, "LoadingGraphic")[0]]);
+ $wrap = $tag(div, "Wrapper");
+ $content = $tag(div, "Content").append(
+ $title = $tag(div, "Title"),
+ $current = $tag(div, "Current"),
+ $prev = $('<button type="button"/>').attr({id:prefix+'Previous'}),
+ $next = $('<button type="button"/>').attr({id:prefix+'Next'}),
+ $slideshow = $('<button type="button"/>').attr({id:prefix+'Slideshow'}),
+ $loadingOverlay
+ );
+
+ $close = $('<button type="button"/>').attr({id:prefix+'Close'});
+
+ $wrap.append( // The 3x3 Grid that makes up Colorbox
+ $tag(div).append(
+ $tag(div, "TopLeft"),
+ $topBorder = $tag(div, "TopCenter"),
+ $tag(div, "TopRight")
+ ),
+ $tag(div, false, 'clear:left').append(
+ $leftBorder = $tag(div, "MiddleLeft"),
+ $content,
+ $rightBorder = $tag(div, "MiddleRight")
+ ),
+ $tag(div, false, 'clear:left').append(
+ $tag(div, "BottomLeft"),
+ $bottomBorder = $tag(div, "BottomCenter"),
+ $tag(div, "BottomRight")
+ )
+ ).find('div div').css({'float': 'left'});
+
+ $loadingBay = $tag(div, false, 'position:absolute; width:9999px; visibility:hidden; display:none; max-width:none;');
+
+ $groupControls = $next.add($prev).add($current).add($slideshow);
+ }
+ if (document.body && !$box.parent().length) {
+ $(document.body).append($overlay, $box.append($wrap, $loadingBay));
+ }
+ }
+
+ // Add Colorbox's event bindings
+ function addBindings() {
+ function clickHandler(e) {
+ // ignore non-left-mouse-clicks and clicks modified with ctrl / command, shift, or alt.
+ // See: http://jacklmoore.com/notes/click-events/
+ if (!(e.which > 1 || e.shiftKey || e.altKey || e.metaKey || e.ctrlKey)) {
+ e.preventDefault();
+ launch(this);
+ }
+ }
+
+ if ($box) {
+ if (!init) {
+ init = true;
+
+ // Anonymous functions here keep the public method from being cached, thereby allowing them to be redefined on the fly.
+ $next.click(function () {
+ publicMethod.next();
+ });
+ $prev.click(function () {
+ publicMethod.prev();
+ });
+ $close.click(function () {
+ publicMethod.close();
+ });
+ $overlay.click(function () {
+ if (settings.get('overlayClose')) {
+ publicMethod.close();
+ }
+ });
+
+ // Key Bindings
+ $(document).bind('keydown.' + prefix, function (e) {
+ var key = e.keyCode;
+ if (open && settings.get('escKey') && key === 27) {
+ e.preventDefault();
+ publicMethod.close();
+ }
+ if (open && settings.get('arrowKey') && $related[1] && !e.altKey) {
+ if (key === 37) {
+ e.preventDefault();
+ $prev.click();
+ } else if (key === 39) {
+ e.preventDefault();
+ $next.click();
+ }
+ }
+ });
+
+ if ($.isFunction($.fn.on)) {
+ // For jQuery 1.7+
+ $(document).on('click.'+prefix, '.'+boxElement, clickHandler);
+ } else {
+ // For jQuery 1.3.x -> 1.6.x
+ // This code is never reached in jQuery 1.9, so do not contact me about 'live' being removed.
+ // This is not here for jQuery 1.9, it's here for legacy users.
+ $('.'+boxElement).live('click.'+prefix, clickHandler);
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ // Don't do anything if Colorbox already exists.
+ if ($[colorbox]) {
+ return;
+ }
+
+ // Append the HTML when the DOM loads
+ $(appendHTML);
+
+
+ // ****************
+ // PUBLIC FUNCTIONS
+ // Usage format: $.colorbox.close();
+ // Usage from within an iframe: parent.jQuery.colorbox.close();
+ // ****************
+
+ publicMethod = $.fn[colorbox] = $[colorbox] = function (options, callback) {
+ var settings;
+ var $obj = this;
+
+ options = options || {};
+
+ if ($.isFunction($obj)) { // assume a call to $.colorbox
+ $obj = $('<a/>');
+ options.open = true;
+ }
+
+ if (!$obj[0]) { // colorbox being applied to empty collection
+ return $obj;
+ }
+
+ appendHTML();
+
+ if (addBindings()) {
+
+ if (callback) {
+ options.onComplete = callback;
+ }
+
+ $obj.each(function () {
+ var old = $.data(this, colorbox) || {};
+ $.data(this, colorbox, $.extend(old, options));
+ }).addClass(boxElement);
+
+ settings = new Settings($obj[0], options);
+
+ if (settings.get('open')) {
+ launch($obj[0]);
+ }
+ }
+
+ return $obj;
+ };
+
+ publicMethod.position = function (speed, loadedCallback) {
+ var
+ css,
+ top = 0,
+ left = 0,
+ offset = $box.offset(),
+ scrollTop,
+ scrollLeft;
+
+ $window.unbind('resize.' + prefix);
+
+ // remove the modal so that it doesn't influence the document width/height
+ $box.css({top: -9e4, left: -9e4});
+
+ scrollTop = $window.scrollTop();
+ scrollLeft = $window.scrollLeft();
+
+ if (settings.get('fixed')) {
+ offset.top -= scrollTop;
+ offset.left -= scrollLeft;
+ $box.css({position: 'fixed'});
+ } else {
+ top = scrollTop;
+ left = scrollLeft;
+ $box.css({position: 'absolute'});
+ }
+
+ // keeps the top and left positions within the browser's viewport.
+ if (settings.get('right') !== false) {
+ left += Math.max($window.width() - settings.w - loadedWidth - interfaceWidth - setSize(settings.get('right'), 'x'), 0);
+ } else if (settings.get('left') !== false) {
+ left += setSize(settings.get('left'), 'x');
+ } else {
+ left += Math.round(Math.max($window.width() - settings.w - loadedWidth - interfaceWidth, 0) / 2);
+ }
+
+ if (settings.get('bottom') !== false) {
+ top += Math.max(winheight() - settings.h - loadedHeight - interfaceHeight - setSize(settings.get('bottom'), 'y'), 0);
+ } else if (settings.get('top') !== false) {
+ top += setSize(settings.get('top'), 'y');
+ } else {
+ top += Math.round(Math.max(winheight() - settings.h - loadedHeight - interfaceHeight, 0) / 2);
+ }
+
+ $box.css({top: offset.top, left: offset.left, visibility:'visible'});
+
+ // this gives the wrapper plenty of breathing room so it's floated contents can move around smoothly,
+ // but it has to be shrank down around the size of div#colorbox when it's done. If not,
+ // it can invoke an obscure IE bug when using iframes.
+ $wrap[0].style.width = $wrap[0].style.height = "9999px";
+
+ function modalDimensions() {
+ $topBorder[0].style.width = $bottomBorder[0].style.width = $content[0].style.width = (parseInt($box[0].style.width,10) - interfaceWidth)+'px';
+ $content[0].style.height = $leftBorder[0].style.height = $rightBorder[0].style.height = (parseInt($box[0].style.height,10) - interfaceHeight)+'px';
+ }
+
+ css = {width: settings.w + loadedWidth + interfaceWidth, height: settings.h + loadedHeight + interfaceHeight, top: top, left: left};
+
+ // setting the speed to 0 if the content hasn't changed size or position
+ if (speed) {
+ var tempSpeed = 0;
+ $.each(css, function(i){
+ if (css[i] !== previousCSS[i]) {
+ tempSpeed = speed;
+ return;
+ }
+ });
+ speed = tempSpeed;
+ }
+
+ previousCSS = css;
+
+ if (!speed) {
+ $box.css(css);
+ }
+
+ $box.dequeue().animate(css, {
+ duration: speed || 0,
+ complete: function () {
+ modalDimensions();
+
+ active = false;
+
+ // shrink the wrapper down to exactly the size of colorbox to avoid a bug in IE's iframe implementation.
+ $wrap[0].style.width = (settings.w + loadedWidth + interfaceWidth) + "px";
+ $wrap[0].style.height = (settings.h + loadedHeight + interfaceHeight) + "px";
+
+ if (settings.get('reposition')) {
+ setTimeout(function () { // small delay before binding onresize due to an IE8 bug.
+ $window.bind('resize.' + prefix, publicMethod.position);
+ }, 1);
+ }
+
+ if ($.isFunction(loadedCallback)) {
+ loadedCallback();
+ }
+ },
+ step: modalDimensions
+ });
+ };
+
+ publicMethod.resize = function (options) {
+ var scrolltop;
+
+ if (open) {
+ options = options || {};
+
+ if (options.width) {
+ settings.w = setSize(options.width, 'x') - loadedWidth - interfaceWidth;
+ }
+
+ if (options.innerWidth) {
+ settings.w = setSize(options.innerWidth, 'x');
+ }
+
+ $loaded.css({width: settings.w});
+
+ if (options.height) {
+ settings.h = setSize(options.height, 'y') - loadedHeight - interfaceHeight;
+ }
+
+ if (options.innerHeight) {
+ settings.h = setSize(options.innerHeight, 'y');
+ }
+
+ if (!options.innerHeight && !options.height) {
+ scrolltop = $loaded.scrollTop();
+ $loaded.css({height: "auto"});
+ settings.h = $loaded.height();
+ }
+
+ $loaded.css({height: settings.h});
+
+ if(scrolltop) {
+ $loaded.scrollTop(scrolltop);
+ }
+
+ publicMethod.position(settings.get('transition') === "none" ? 0 : settings.get('speed'));
+ }
+ };
+
+ publicMethod.prep = function (object) {
+ if (!open) {
+ return;
+ }
+
+ var callback, speed = settings.get('transition') === "none" ? 0 : settings.get('speed');
+
+ $loaded.remove();
+
+ $loaded = $tag(div, 'LoadedContent').append(object);
+
+ function getWidth() {
+ settings.w = settings.w || $loaded.width();
+ settings.w = settings.mw && settings.mw < settings.w ? settings.mw : settings.w;
+ return settings.w;
+ }
+ function getHeight() {
+ settings.h = settings.h || $loaded.height();
+ settings.h = settings.mh && settings.mh < settings.h ? settings.mh : settings.h;
+ return settings.h;
+ }
+
+ $loaded.hide()
+ .appendTo($loadingBay.show())// content has to be appended to the DOM for accurate size calculations.
+ .css({width: getWidth(), overflow: settings.get('scrolling') ? 'auto' : 'hidden'})
+ .css({height: getHeight()})// sets the height independently from the width in case the new width influences the value of height.
+ .prependTo($content);
+
+ $loadingBay.hide();
+
+ // floating the IMG removes the bottom line-height and fixed a problem where IE miscalculates the width of the parent element as 100% of the document width.
+
+ $(photo).css({'float': 'none'});
+
+ setClass(settings.get('className'));
+
+ callback = function () {
+ var total = $related.length,
+ iframe,
+ complete;
+
+ if (!open) {
+ return;
+ }
+
+ function removeFilter() { // Needed for IE8 in versions of jQuery prior to 1.7.2
+ if ($.support.opacity === false) {
+ $box[0].style.removeAttribute('filter');
+ }
+ }
+
+ complete = function () {
+ clearTimeout(loadingTimer);
+ $loadingOverlay.hide();
+ trigger(event_complete);
+ settings.get('onComplete');
+ };
+
+
+ $title.html(settings.get('title')).show();
+ $loaded.show();
+
+ if (total > 1) { // handle grouping
+ if (typeof settings.get('current') === "string") {
+ $current.html(settings.get('current').replace('{current}', index + 1).replace('{total}', total)).show();
+ }
+
+ $next[(settings.get('loop') || index < total - 1) ? "show" : "hide"]().html(settings.get('next'));
+ $prev[(settings.get('loop') || index) ? "show" : "hide"]().html(settings.get('previous'));
+
+ slideshow();
+
+ // Preloads images within a rel group
+ if (settings.get('preloading')) {
+ $.each([getIndex(-1), getIndex(1)], function(){
+ var img,
+ i = $related[this],
+ settings = new Settings(i, $.data(i, colorbox)),
+ src = settings.get('href');
+
+ if (src && isImage(settings, src)) {
+ src = retinaUrl(settings, src);
+ img = document.createElement('img');
+ img.src = src;
+ }
+ });
+ }
+ } else {
+ $groupControls.hide();
+ }
+
+ if (settings.get('iframe')) {
+
+ iframe = settings.get('createIframe');
+
+ if (!settings.get('scrolling')) {
+ iframe.scrolling = "no";
+ }
+
+ $(iframe)
+ .attr({
+ src: settings.get('href'),
+ 'class': prefix + 'Iframe'
+ })
+ .one('load', complete)
+ .appendTo($loaded);
+
+ $events.one(event_purge, function () {
+ iframe.src = "//about:blank";
+ });
+
+ if (settings.get('fastIframe')) {
+ $(iframe).trigger('load');
+ }
+ } else {
+ complete();
+ }
+
+ if (settings.get('transition') === 'fade') {
+ $box.fadeTo(speed, 1, removeFilter);
+ } else {
+ removeFilter();
+ }
+ };
+
+ if (settings.get('transition') === 'fade') {
+ $box.fadeTo(speed, 0, function () {
+ publicMethod.position(0, callback);
+ });
+ } else {
+ publicMethod.position(speed, callback);
+ }
+ };
+
+ function load () {
+ var href, setResize, prep = publicMethod.prep, $inline, request = ++requests;
+
+ active = true;
+
+ photo = false;
+
+ trigger(event_purge);
+ trigger(event_load);
+ settings.get('onLoad');
+
+ settings.h = settings.get('height') ?
+ setSize(settings.get('height'), 'y') - loadedHeight - interfaceHeight :
+ settings.get('innerHeight') && setSize(settings.get('innerHeight'), 'y');
+
+ settings.w = settings.get('width') ?
+ setSize(settings.get('width'), 'x') - loadedWidth - interfaceWidth :
+ settings.get('innerWidth') && setSize(settings.get('innerWidth'), 'x');
+
+ // Sets the minimum dimensions for use in image scaling
+ settings.mw = settings.w;
+ settings.mh = settings.h;
+
+ // Re-evaluate the minimum width and height based on maxWidth and maxHeight values.
+ // If the width or height exceed the maxWidth or maxHeight, use the maximum values instead.
+ if (settings.get('maxWidth')) {
+ settings.mw = setSize(settings.get('maxWidth'), 'x') - loadedWidth - interfaceWidth;
+ settings.mw = settings.w && settings.w < settings.mw ? settings.w : settings.mw;
+ }
+ if (settings.get('maxHeight')) {
+ settings.mh = setSize(settings.get('maxHeight'), 'y') - loadedHeight - interfaceHeight;
+ settings.mh = settings.h && settings.h < settings.mh ? settings.h : settings.mh;
+ }
+
+ href = settings.get('href');
+
+ loadingTimer = setTimeout(function () {
+ $loadingOverlay.show();
+ }, 100);
+
+ if (settings.get('inline')) {
+ var $target = $(href).eq(0);
+ // Inserts an empty placeholder where inline content is being pulled from.
+ // An event is bound to put inline content back when Colorbox closes or loads new content.
+ $inline = $('<div>').hide().insertBefore($target);
+
+ $events.one(event_purge, function () {
+ $inline.replaceWith($target);
+ });
+
+ prep($target);
+ } else if (settings.get('iframe')) {
+ // IFrame element won't be added to the DOM until it is ready to be displayed,
+ // to avoid problems with DOM-ready JS that might be trying to run in that iframe.
+ prep(" ");
+ } else if (settings.get('html')) {
+ prep(settings.get('html'));
+ } else if (isImage(settings, href)) {
+
+ href = retinaUrl(settings, href);
+
+ photo = settings.get('createImg');
+
+ $(photo)
+ .addClass(prefix + 'Photo')
+ .bind('error.'+prefix,function () {
+ prep($tag(div, 'Error').html(settings.get('imgError')));
+ })
+ .one('load', function () {
+ if (request !== requests) {
+ return;
+ }
+
+ // A small pause because some browsers will occassionaly report a
+ // img.width and img.height of zero immediately after the img.onload fires
+ setTimeout(function(){
+ var percent;
+
+ if (settings.get('retinaImage') && window.devicePixelRatio > 1) {
+ photo.height = photo.height / window.devicePixelRatio;
+ photo.width = photo.width / window.devicePixelRatio;
+ }
+
+ if (settings.get('scalePhotos')) {
+ setResize = function () {
+ photo.height -= photo.height * percent;
+ photo.width -= photo.width * percent;
+ };
+ if (settings.mw && photo.width > settings.mw) {
+ percent = (photo.width - settings.mw) / photo.width;
+ setResize();
+ }
+ if (settings.mh && photo.height > settings.mh) {
+ percent = (photo.height - settings.mh) / photo.height;
+ setResize();
+ }
+ }
+
+ if (settings.h) {
+ photo.style.marginTop = Math.max(settings.mh - photo.height, 0) / 2 + 'px';
+ }
+
+ if ($related[1] && (settings.get('loop') || $related[index + 1])) {
+ photo.style.cursor = 'pointer';
+
+ $(photo).bind('click.'+prefix, function () {
+ publicMethod.next();
+ });
+ }
+
+ photo.style.width = photo.width + 'px';
+ photo.style.height = photo.height + 'px';
+ prep(photo);
+ }, 1);
+ });
+
+ photo.src = href;
+
+ } else if (href) {
+ $loadingBay.load(href, settings.get('data'), function (data, status) {
+ if (request === requests) {
+ prep(status === 'error' ? $tag(div, 'Error').html(settings.get('xhrError')) : $(this).contents());
+ }
+ });
+ }
+ }
+
+ // Navigates to the next page/image in a set.
+ publicMethod.next = function () {
+ if (!active && $related[1] && (settings.get('loop') || $related[index + 1])) {
+ index = getIndex(1);
+ launch($related[index]);
+ }
+ };
+
+ publicMethod.prev = function () {
+ if (!active && $related[1] && (settings.get('loop') || index)) {
+ index = getIndex(-1);
+ launch($related[index]);
+ }
+ };
+
+ // Note: to use this within an iframe use the following format: parent.jQuery.colorbox.close();
+ publicMethod.close = function () {
+ if (open && !closing) {
+
+ closing = true;
+ open = false;
+ trigger(event_cleanup);
+ settings.get('onCleanup');
+ $window.unbind('.' + prefix);
+ $overlay.fadeTo(settings.get('fadeOut') || 0, 0);
+
+ $box.stop().fadeTo(settings.get('fadeOut') || 0, 0, function () {
+ $box.hide();
+ $overlay.hide();
+ trigger(event_purge);
+ $loaded.remove();
+
+ setTimeout(function () {
+ closing = false;
+ trigger(event_closed);
+ settings.get('onClosed');
+ }, 1);
+ });
+ }
+ };
+
+ // Removes changes Colorbox made to the document, but does not remove the plugin.
+ publicMethod.remove = function () {
+ if (!$box) { return; }
+
+ $box.stop();
+ $[colorbox].close();
+ $box.stop(false, true).remove();
+ $overlay.remove();
+ closing = false;
+ $box = null;
+ $('.' + boxElement)
+ .removeData(colorbox)
+ .removeClass(boxElement);
+
+ $(document).unbind('click.'+prefix).unbind('keydown.'+prefix);
+ };
+
+ // A method for fetching the current element Colorbox is referencing.
+ // returns a jQuery object.
+ publicMethod.element = function () {
+ return $(settings.el);
+ };
+
+ publicMethod.settings = defaults;
+
+}(jQuery, document, window));
+
+/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))
+
+/***/ }),
+/* 138 */
+/***/ (function(module, exports) {
+
+/*!
+ Wheelzoom 3.1.2
+ license: MIT
+ http://www.jacklmoore.com/wheelzoom
+*/
+window.wheelzoom = (function(){
+ var defaults = {
+ zoom: 0.10,
+ maxZoom: false,
+ };
+
+ var canvas = document.createElement('canvas');
+
+ var main = function(img, options){
+ if (!img || !img.nodeName || img.nodeName !== 'IMG') { return; }
+
+ var settings = {};
+ var width;
+ var height;
+ var bgWidth;
+ var bgHeight;
+ var bgPosX;
+ var bgPosY;
+ var previousEvent;
+ var cachedDataUrl;
+
+ function setSrcToBackground(img) {
+ img.style.backgroundImage = 'url("'+img.src+'")';
+ img.style.backgroundRepeat = 'no-repeat';
+ canvas.width = img.naturalWidth;
+ canvas.height = img.naturalHeight;
+ cachedDataUrl = canvas.toDataURL();
+ img.src = cachedDataUrl;
+ }
+
+ function updateBgStyle() {
+ if (bgPosX > 0) {
+ bgPosX = 0;
+ } else if (bgPosX < width - bgWidth) {
+ bgPosX = width - bgWidth;
+ }
+
+ if (bgPosY > 0) {
+ bgPosY = 0;
+ } else if (bgPosY < height - bgHeight) {
+ bgPosY = height - bgHeight;
+ }
+
+ img.style.backgroundSize = bgWidth+'px '+bgHeight+'px';
+ img.style.backgroundPosition = bgPosX+'px '+bgPosY+'px';
+ }
+
+ function reset() {
+ bgWidth = width;
+ bgHeight = height;
+ bgPosX = bgPosY = 0;
+ updateBgStyle();
+ }
+
+ function onwheel(e) {
+ var deltaY = 0;
+
+ e.preventDefault();
+
+ if (e.deltaY) { // FireFox 17+ (IE9+, Chrome 31+?)
+ deltaY = e.deltaY;
+ } else if (e.wheelDelta) {
+ deltaY = -e.wheelDelta;
+ }
+
+ // As far as I know, there is no good cross-browser way to get the cursor position relative to the event target.
+ // We have to calculate the target element's position relative to the document, and subtrack that from the
+ // cursor's position relative to the document.
+ var rect = img.getBoundingClientRect();
+ var offsetX = e.pageX - rect.left - window.pageXOffset;
+ var offsetY = e.pageY - rect.top - window.pageYOffset;
+
+ // Record the offset between the bg edge and cursor:
+ var bgCursorX = offsetX - bgPosX;
+ var bgCursorY = offsetY - bgPosY;
+
+ // Use the previous offset to get the percent offset between the bg edge and cursor:
+ var bgRatioX = bgCursorX/bgWidth;
+ var bgRatioY = bgCursorY/bgHeight;
+
+ // Update the bg size:
+ if (deltaY < 0) {
+ bgWidth += bgWidth*settings.zoom;
+ bgHeight += bgHeight*settings.zoom;
+ } else {
+ bgWidth -= bgWidth*settings.zoom;
+ bgHeight -= bgHeight*settings.zoom;
+ }
+
+ if (settings.maxZoom) {
+ bgWidth = Math.min(width*settings.maxZoom, bgWidth);
+ bgHeight = Math.min(height*settings.maxZoom, bgHeight);
+ }
+
+ // Take the percent offset and apply it to the new size:
+ bgPosX = offsetX - (bgWidth * bgRatioX);
+ bgPosY = offsetY - (bgHeight * bgRatioY);
+
+ // Prevent zooming out beyond the starting size
+ if (bgWidth <= width || bgHeight <= height) {
+ reset();
+ } else {
+ updateBgStyle();
+ }
+ }
+
+ function drag(e) {
+ e.preventDefault();
+ bgPosX += (e.pageX - previousEvent.pageX);
+ bgPosY += (e.pageY - previousEvent.pageY);
+ previousEvent = e;
+ updateBgStyle();
+ }
+
+ function removeDrag() {
+ document.removeEventListener('mouseup', removeDrag);
+ document.removeEventListener('mousemove', drag);
+ }
+
+ // Make the background draggable
+ function draggable(e) {
+ e.preventDefault();
+ previousEvent = e;
+ document.addEventListener('mousemove', drag);
+ document.addEventListener('mouseup', removeDrag);
+ }
+
+ function load() {
+ if (img.src === cachedDataUrl) return;
+
+ var computedStyle = window.getComputedStyle(img, null);
+
+ width = parseInt(computedStyle.width, 10);
+ height = parseInt(computedStyle.height, 10);
+ bgWidth = width;
+ bgHeight = height;
+ bgPosX = 0;
+ bgPosY = 0;
+
+ setSrcToBackground(img);
+
+ img.style.backgroundSize = width+'px '+height+'px';
+ img.style.backgroundPosition = '0 0';
+ img.addEventListener('wheelzoom.reset', reset);
+
+ img.addEventListener('wheel', onwheel);
+ img.addEventListener('mousedown', draggable);
+ }
+
+ var destroy = function (originalProperties) {
+ img.removeEventListener('wheelzoom.destroy', destroy);
+ img.removeEventListener('wheelzoom.reset', reset);
+ img.removeEventListener('load', load);
+ img.removeEventListener('mouseup', removeDrag);
+ img.removeEventListener('mousemove', drag);
+ img.removeEventListener('mousedown', draggable);
+ img.removeEventListener('wheel', onwheel);
+
+ img.style.backgroundImage = originalProperties.backgroundImage;
+ img.style.backgroundRepeat = originalProperties.backgroundRepeat;
+ img.src = originalProperties.src;
+ }.bind(null, {
+ backgroundImage: img.style.backgroundImage,
+ backgroundRepeat: img.style.backgroundRepeat,
+ src: img.src
+ });
+
+ img.addEventListener('wheelzoom.destroy', destroy);
+
+ options = options || {};
+
+ Object.keys(defaults).forEach(function(key){
+ settings[key] = options[key] !== undefined ? options[key] : defaults[key];
+ });
+
+ if (img.complete) {
+ load();
+ }
+
+ img.addEventListener('load', load);
+ };
+
+ // Do nothing in IE8
+ if (typeof window.getComputedStyle !== 'function') {
+ return function(elements) {
+ return elements;
+ };
+ } else {
+ return function(elements, options) {
+ if (elements && elements.length) {
+ Array.prototype.forEach.call(elements, main, options);
+ } else if (elements && elements.nodeName) {
+ main(elements, options);
+ }
+ return elements;
+ };
+ }
+}());
+
+/***/ })
+/******/ ]);
+//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAgZmI0NGFlOTE4YWJhZjVlZmMyYTMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL21vbWVudC9tb21lbnQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2pxdWVyeS9kaXN0L2pxdWVyeS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvcG9wcGVyLmpzL2Rpc3QvZXNtL3BvcHBlci5qcyIsIndlYnBhY2s6Ly8vKHdlYnBhY2spL2J1aWxkaW4vZ2xvYmFsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9kYXRhdGFibGVzLm5ldC9qcy9qcXVlcnkuZGF0YVRhYmxlcy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hZi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci1kei5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci1rdy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci1seS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci1tYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci1zYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci10bi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hei5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9iZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9iZy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ibS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ibi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9iby5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ici5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9icy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9jYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9jcy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9jdi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9jeS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9kYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9kZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9kZS1hdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9kZS1jaC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9kdi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbi1hdS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbi1jYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbi1nYi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbi1pZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbi1uei5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lby5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lcy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lcy1kby5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lcy11cy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ldC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ldS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9mYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9maS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9mby5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9mci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9mci1jYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9mci1jaC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9meS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9nZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9nbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9nb20tbGF0bi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ndS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9oZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9oaS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9oci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9odS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9oeS1hbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9pZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9pcy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9pdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9qYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9qdi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9rYS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ray5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9rbS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9rbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9rby5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9reS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9sYi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9sby5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9sdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9sdi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9tZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9taS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9tay5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9tbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9tci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9tcy5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9tcy1teS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9tdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9teS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9uYi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9uZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ubC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ubC1iZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ubi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9wYS1pbi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9wbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9wdC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9wdC1ici5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9yby5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ydS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zZC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zZS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zaS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zay5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zbC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zcS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zci1jeXJsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3NzLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3N2LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3N3LmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3RhLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3RlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3RldC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS90aC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS90bC1waC5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS90bGguanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdHIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdHpsLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3R6bS5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS90em0tbGF0bi5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS91ay5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS91ci5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS91ei5qcyIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS91ei1sYXRuLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3ZpLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3gtcHNldWRvLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3lvLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3poLWNuLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3poLWhrLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3poLXR3LmpzIiwid2VicGFjazovLy8uL3Jlc291cmNlcy9hc3NldHMvanMvdmVuZG9yLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ib290c3RyYXAvZGlzdC9qcy9ib290c3RyYXAuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2NvcmVqcy10eXBlYWhlYWQvZGlzdC90eXBlYWhlYWQuYnVuZGxlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy90aW1lcnMtYnJvd3NlcmlmeS9tYWluLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9zZXRpbW1lZGlhdGUvc2V0SW1tZWRpYXRlLmpzIiwid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2RhdGF0YWJsZXMubmV0LWJzNC9qcy9kYXRhVGFibGVzLmJvb3RzdHJhcDQuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL3NvcnRhYmxlanMvU29ydGFibGUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL3NlbGVjdDIvZGlzdC9qcy9zZWxlY3QyLmpzIiwid2VicGFjazovLy8od2VicGFjaykvYnVpbGRpbi9tb2R1bGUuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUgXlxcLlxcLy4qJCIsIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvZW9uYXNkYW4tYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyL3NyYy9qcy9ib290c3RyYXAtZGF0ZXRpbWVwaWNrZXIuanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL2pxdWVyeS1jb2xvcmJveC9qcXVlcnkuY29sb3Jib3guanMiLCJ3ZWJwYWNrOi8vLy4vbm9kZV9tb2R1bGVzL3doZWVsem9vbS93aGVlbHpvb20uanMiXSwibmFtZXMiOlsid2luZG93IiwiJCIsImpRdWVyeSJdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxtQ0FBMkIsMEJBQTBCLEVBQUU7QUFDdkQseUNBQWlDLGVBQWU7QUFDaEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOERBQXNELCtEQUErRDs7QUFFckg7QUFDQTs7QUFFQTtBQUNBOzs7Ozs7OzhDQzdEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDLHFCQUFxQjs7QUFFdEI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZUFBZSxnQkFBZ0I7QUFDL0I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBOztBQUVBLHVCQUF1QixTQUFTO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG1CQUFtQiw2QkFBNkI7QUFDaEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxTQUFTO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLHNCQUFzQjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkM7QUFDM0MsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1QkFBdUIsSUFBSTtBQUMzQjs7QUFFQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHdDQUF3QyxJQUFJOztBQUU1QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDRCQUE0QjtBQUM1QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esb0JBQW9CLGlDQUFpQztBQUNyRDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx3TEFBd0wsSUFBSTs7QUFFNUwsaUVBQWlFLElBQUk7O0FBRXJFOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsc0NBQXNDLFlBQVk7QUFDbEQ7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQixZQUFZO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsMEJBQTBCO0FBQzFCLDRCQUE0QjtBQUM1Qix5QkFBeUIsRUFBRSxFQUFFO0FBQzdCLHlCQUF5QixFQUFFLEVBQUU7QUFDN0IsOEJBQThCLEVBQUUsRUFBRTtBQUNsQyw2QkFBNkI7QUFDN0IsaUNBQWlDO0FBQ2pDLHFDQUFxQztBQUNyQyx5QkFBeUIsSUFBSSxFQUFFO0FBQy9CLHlCQUF5QixJQUFJLEVBQUU7QUFDL0IsOEJBQThCLElBQUksRUFBRTs7QUFFcEMsMkJBQTJCO0FBQzNCLGdDQUFnQzs7QUFFaEMsMENBQTBDO0FBQzFDLGlEQUFpRDs7QUFFakQsb0NBQW9DLElBQUksSUFBSTs7QUFFNUM7QUFDQTtBQUNBLHVCQUF1QixNQUFNLHdFQUF3RSxNQUFNLG1CQUFtQixNQUFNLHFCQUFxQixNQUFNLEVBQUUsSUFBSTs7O0FBR3JLOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBLDBDQUEwQztBQUMxQzs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsa0JBQWtCO0FBQ2pDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHdCQUF3QjtBQUMvQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixpQkFBaUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixRQUFRO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBO0FBQ0E7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsT0FBTztBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZUFBZSxPQUFPO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLCtCQUErQjtBQUM5QztBQUNBOztBQUVBO0FBQ0EsVUFBVSxPQUFPO0FBQ2pCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVDQUF1QyxFQUFFLElBQUksRUFBRTtBQUMvQyxvQ0FBb0MsRUFBRSxJQUFJLEVBQUU7O0FBRTVDOztBQUVBO0FBQ0EsNkJBQTZCLEVBQUU7QUFDL0IsdUJBQXVCLEVBQUU7QUFDekIseUJBQXlCLEVBQUU7QUFDM0IsdUJBQXVCLEVBQUU7QUFDekIscUJBQXFCLEVBQUUsSUFBSSxFQUFFO0FBQzdCLG9CQUFvQixFQUFFO0FBQ3RCLDJCQUEyQixHQUFHO0FBQzlCLHFCQUFxQixFQUFFO0FBQ3ZCO0FBQ0EsdUJBQXVCLEVBQUUsSUFBSSxFQUFFO0FBQy9CLHNCQUFzQixFQUFFLElBQUksRUFBRTtBQUM5QixvQkFBb0IsRUFBRTtBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsd0NBQXdDLE9BQU87QUFDL0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDRDQUE0QyxPQUFPO0FBQ25EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMERBQTBELElBQUksMERBQTBELElBQUkscUVBQXFFLEVBQUU7O0FBRW5NO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLGVBQWUsbUJBQW1CO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZUFBZSxzQkFBc0I7QUFDckM7QUFDQSxrQ0FBa0M7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSw4QkFBOEIsZ0JBQWdCO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLG9CQUFvQjtBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIscUJBQXFCO0FBQ3hDO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSyw2QkFBNkI7QUFDbEM7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsZUFBZTs7QUFFZjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsY0FBYztBQUNwQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBLHlEQUF5RDtBQUN6RCxxREFBcUQ7QUFDckQsMkRBQTJEO0FBQzNELG9EQUFvRCxPQUFPO0FBQzNELG9EQUFvRCxPQUFPO0FBQzNELG1EQUFtRCxPQUFPO0FBQzFELCtEQUErRCxPQUFPO0FBQ3RFLGlFQUFpRSxPQUFPO0FBQ3hFO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLHFCQUFxQjtBQUNwRCxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQixxQkFBcUI7QUFDcEQsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esb0JBQW9CO0FBQ3BCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7O0FBR0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBLENBQUM7OztBQUdEOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLG9CQUFvQixtQkFBbUI7QUFDdkM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLG1CQUFtQjtBQUNwQztBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDOzs7Ozs7OztBQ3Q3SUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7OztBQUlBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsWUFBWTs7QUFFcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGLG9CQUFvQjs7QUFFcEI7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRixnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUyxTQUFTO0FBQ2xCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUyxZQUFZO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxZQUFZO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLFNBQVM7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQSxnQkFBZ0IsSUFBSTs7QUFFcEI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0Esd0NBQXdDLElBQUk7QUFDNUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNELFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQSxNQUFNOztBQUVOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSx5QkFBeUI7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsU0FBUztBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsUUFBUSw2QkFBNkI7QUFDaEQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGdCQUFnQjtBQUMzQixhQUFhLHVCQUF1QjtBQUNwQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGVBQWU7QUFDMUIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGVBQWU7QUFDMUIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLFVBQVU7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXLGNBQWM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLGdDQUFnQyxNQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBLGVBQWU7O0FBRWYsU0FBUzs7QUFFVDtBQUNBLFFBQVEsaUNBQWlDO0FBQ3pDLFFBQVEsb0JBQW9CO0FBQzVCLFFBQVEsc0NBQXNDO0FBQzlDLFFBQVE7QUFDUixFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsYUFBYSxFQUFFO0FBQy9CO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSw0REFBNEQ7O0FBRTVEO0FBQ0E7QUFDQTtBQUNBLHlDQUF5Qzs7QUFFekM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkRBQTZEOztBQUU3RDtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEM7O0FBRTFDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0VBQWdFOztBQUVoRTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7O0FBRTdDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFLFVBQVU7QUFDM0Usc0NBQXNDLDJCQUEyQjtBQUNqRTtBQUNBLGdDQUFnQyxNQUFNO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsWUFBWTtBQUN0QjtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxVQUFVLFlBQVk7QUFDdEI7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsVUFBVSxVQUFVO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBLFVBQVUsY0FBYztBQUN4QjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLFlBQVksdUVBQXVFO0FBQ25GO0FBQ0E7QUFDQSxZQUFZLDRCQUE0QjtBQUN4QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRLFNBQVM7QUFDakI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSwyREFBMkQ7O0FBRTNEO0FBQ0E7QUFDQSxvRkFBb0Y7O0FBRXBGO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBLG1DQUFtQztBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsUUFBUSxTQUFTO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVILFFBQVEsU0FBUztBQUNqQjtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsaURBQWlEO0FBQ3hGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaURBQWlEO0FBQ2pELFVBQVUsd0NBQXdDO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsTUFBTTtBQUNqQixXQUFXLE1BQU07QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7O0FBRUEsQ0FBQzs7OztBQUlEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBLFFBQVEsR0FBRztBQUNYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBOzs7O0FBSUE7O0FBRUE7O0FBRUE7QUFDQTs7OztBQUlBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCLFNBQVM7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7O0FBRUEsY0FBYyxTQUFTO0FBQ3ZCO0FBQ0E7O0FBRUE7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsVUFBVSxPQUFPO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxVQUFVLE9BQU87QUFDakIsMEJBQTBCLHdCQUF3Qjs7QUFFbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0EsMENBQTBDO0FBQzFDLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQjs7QUFFbkI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxjQUFjO0FBQ3hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTs7QUFFUjtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsTUFBTTs7QUFFTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsd0NBQXdDLHNDQUFzQztBQUM5RSxvQ0FBb0MsdUNBQXVDO0FBQzNFLG9DQUFvQyxzQ0FBc0M7QUFDMUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUixPQUFPO0FBQ1A7QUFDQSxNQUFNO0FBQ04sS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVTs7QUFFVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTOztBQUVUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07O0FBRU47QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQztBQUNwQyxxQ0FBcUM7QUFDckMsb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7Ozs7O0FBS0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVSxTQUFTO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCLGFBQWE7QUFDcEMsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0IsU0FBUztBQUM3Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDs7QUFFQTs7O0FBR0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsUUFBUSxnQkFBZ0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUJBQWlCLGdCQUFnQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQztBQUNEOztBQUVBOztBQUVBOzs7O0FBSUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7O0FBRUEsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFFBQVEsT0FBTztBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQSxzQkFBc0I7O0FBRXRCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLE9BQU87QUFDZjs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRSxnQkFBZ0I7QUFDbEI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFdBQVc7O0FBRVg7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSwyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esb0RBQW9EO0FBQ3BEOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyxzQkFBc0I7QUFDcEM7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLCtEQUErRDtBQUMvRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsY0FBYzs7QUFFeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixtQkFBbUI7QUFDcEM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQix1Q0FBdUM7QUFDakU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHVEQUF1RDtBQUM5RTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLGNBQWM7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMkNBQTJDLE9BQU87QUFDbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7O0FBRTlCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsT0FBTztBQUNqQjs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixnQkFBZ0I7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxRQUFRLCtCQUErQjtBQUN2QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUNBQXVDLE9BQU87QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsd0NBQXdDLE9BQU87QUFDL0M7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLHFDQUFxQztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBLFNBQVMsOEJBQThCO0FBQ3ZDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxZQUFZLE9BQU87QUFDbkI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLFdBQVc7QUFDcEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7O0FBSUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCO0FBQzFCLHNCQUFzQixjQUFjO0FBQ3BDLGdCQUFnQixXQUFXLFlBQVk7QUFDdkMsV0FBVztBQUNYO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLFVBQVUsU0FBUyxNQUFNLGFBQWE7QUFDM0UsYUFBYSxlQUFlO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0YsQ0FBQzs7O0FBR0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSwrREFBK0Q7QUFDM0U7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUEsUUFBUSxPQUFPOztBQUVmO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCLGdCQUFnQjtBQUNsQztBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQSxVQUFVLE9BQU87QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxXQUFXLFNBQVM7QUFDcEI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVzs7QUFFWDtBQUNBO0FBQ0E7QUFDQSxRQUFRLE9BQU87QUFDZjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsZ0JBQWdCO0FBQ3hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osaURBQWlELDBCQUEwQjtBQUMzRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVUsZ0JBQWdCO0FBQzFCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7QUFDQSxxQkFBcUI7QUFDckI7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsZ0JBQWdCO0FBQzNCO0FBQ0E7O0FBRUEsNkNBQTZDO0FBQzdDO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTs7QUFFQSxRQUFRLGdCQUFnQjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLFNBQVMsZ0JBQWdCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGlFQUFpRTtBQUNqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBOztBQUVBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0Esb0JBQW9CLGNBQWM7QUFDbEMsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaURBQWlEOztBQUVqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLCtCQUErQixTQUFTO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsZ0JBQWdCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxrQkFBa0I7QUFDNUIsV0FBVyxrQkFBa0I7QUFDN0IsY0FBYztBQUNkLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsUUFBUSxtQkFBbUI7QUFDM0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7O0FBR0Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7Ozs7O0FBS0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQSxpQ0FBaUM7QUFDakM7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEOzs7QUFHQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBOztBQUVBOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhDQUE4QztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDJDQUEyQztBQUMzQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsS0FBSztBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxxQ0FBcUM7O0FBRXBEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7O0FBRUE7O0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUgsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsS0FBSztBQUNMOztBQUVBLFdBQVc7QUFDWCxHQUFHO0FBQ0g7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEIsZ0RBQWdEO0FBQ2hEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsbUJBQW1CO0FBQ25COztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdEQUF3RDtBQUN4RDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUztBQUNUOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUI7QUFDakIsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDs7QUFFbEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkI7O0FBRTNCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxrQ0FBa0M7O0FBRWxDO0FBQ0Esc0JBQXNCO0FBQ3RCLDJCQUEyQjs7QUFFM0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzREFBc0Q7QUFDdEQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQSxtREFBbUQ7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLHVCQUF1QjtBQUNsQyxXQUFXLHlCQUF5QjtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7QUFLRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7QUFDRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7OztBQUtEO0FBQ0E7QUFDQTtBQUNBLEVBQUU7QUFDRjs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHFEQUFxRDtBQUNyRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQkFBbUI7O0FBRW5CLDREQUE0RCxlQUFlO0FBQzNFO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBLGNBQWMsc0RBQXNEO0FBQ3BFOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0EsY0FBYyxtQ0FBbUM7QUFDakQsZUFBZSw2REFBNkQ7QUFDNUU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBLEVBQUU7QUFDRixDQUFDOzs7QUFHRDs7QUFFQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQUE7QUFDRjs7Ozs7QUFLQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQ0EsQ0FBQzs7Ozs7Ozs7O0FDNWdVRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLGtDQUFrQztBQUNqRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxTQUFTO0FBQ3RCLFlBQVk7QUFDWjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxJQUFJO0FBQ2xCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLFFBQVE7QUFDdEIsY0FBYyxRQUFRO0FBQ3RCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLFlBQVk7QUFDdkIsV0FBVyxRQUFRO0FBQ25CLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxvQkFBb0I7QUFDL0I7QUFDQSxXQUFXLE9BQU87QUFDbEIsWUFBWSxPQUFPO0FBQ25COztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQixrQkFBa0I7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7Ozs7OztBQU1EO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUIsc0JBQXNCO0FBQ3ZDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0Esb0JBQW9CO0FBQ3BCO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFlBQVk7QUFDdkIsWUFBWSxPQUFPO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLFFBQVE7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFlBQVk7QUFDdkIsV0FBVyxZQUFZO0FBQ3ZCLFdBQVcsT0FBTztBQUNsQixXQUFXLFlBQVk7QUFDdkIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsWUFBWTtBQUN2QixXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFdBQVc7QUFDdEIsV0FBVyxNQUFNO0FBQ2pCLFdBQVcsT0FBTztBQUNsQixhQUFhO0FBQ2I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQ7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxjQUFjO0FBQ2QsbUJBQW1CO0FBQ25CLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUJBQWlCLHlCQUF5QjtBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEMsZ0JBQWdCOztBQUU1RDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSxnQkFBZ0I7O0FBRXRGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxFQUFFO0FBQ2IsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEdBQUc7QUFDSDs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsWUFBWTtBQUN2QixXQUFXLFlBQVk7QUFDdkIsV0FBVyxPQUFPO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxxQkFBcUIsdUJBQXVCOztBQUU1QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrQkFBK0I7QUFDL0IsMkJBQTJCO0FBQzNCLGdDQUFnQzs7QUFFaEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxNQUFNO0FBQ2pCLFdBQVcsT0FBTztBQUNsQixXQUFXLE9BQU87QUFDbEIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsZ0RBQWdEOztBQUVoRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVixVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLFFBQVE7QUFDdEIsYUFBYSxNQUFNO0FBQ25CO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLHVDQUF1Qzs7QUFFdkM7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE1BQU07QUFDbkI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsY0FBYztBQUM1QjtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsOEJBQThCO0FBQzlCLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7QUFDOUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esd0JBQXdCO0FBQ3hCLEdBQUc7O0FBRUg7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsOEJBQThCO0FBQzlCLDRCQUE0QjtBQUM1Qjs7QUFFQSxxQ0FBcUM7QUFDckM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsV0FBVztBQUN6QixjQUFjLE9BQU87QUFDckIsYUFBYSxXQUFXO0FBQ3hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQSxlQUFlLGNBQWM7QUFDN0I7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQTtBQUNBLGNBQWMsTUFBTTtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsbUJBQW1CO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBLGVBQWUsbUJBQW1CO0FBQ2xDO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQTtBQUNBLGNBQWMsYUFBYTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLG1CQUFtQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxPQUFPO0FBQ3RCO0FBQ0EsZUFBZSxRQUFRO0FBQ3ZCO0FBQ0EsZUFBZSxXQUFXO0FBQzFCO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBLGVBQWUsV0FBVztBQUMxQjtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQSxlQUFlLFdBQVc7QUFDMUI7QUFDQSxlQUFlLFNBQVM7QUFDeEI7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsUUFBUTtBQUN0QixjQUFjLFFBQVE7QUFDdEIsY0FBYyxZQUFZO0FBQzFCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksa0JBQWtCO0FBQzlCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFlBQVksUUFBUTtBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFlBQVksUUFBUTtBQUNwQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0Esa0NBQWtDOztBQUVsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQSxrQ0FBa0M7O0FBRWxDO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFdBQVcsV0FBVztBQUN0Qjs7QUFFQTtBQUNBO0FBQ0EsV0FBVyxXQUFXO0FBQ3RCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsNEJBQTRCO0FBQ3pDLGFBQWEsWUFBWTtBQUN6QixhQUFhLE9BQU87QUFDcEIsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWM7QUFDZCw4QkFBOEI7O0FBRTlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQixpREFBaUQsdUNBQXVDLGtEQUFrRDtBQUMxSSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsU0FBUztBQUN2QjtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7Ozs7QUNwNEVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0Q0FBNEM7O0FBRTVDOzs7Ozs7O0FDcEJBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3QjtBQUN4QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQUE7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU8sU0FBUztBQUM3Qix1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1YsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsbUJBQW1CO0FBQ2pDLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckI7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0EsZ0JBQWdCLE9BQU87QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEIsb0JBQW9CO0FBQzlDO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsbUJBQW1CO0FBQ2pDLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckI7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0EsZ0JBQWdCLE1BQU07QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxvQkFBb0I7QUFDekQ7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxhQUFhO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQixnQkFBZ0IsTUFBTTtBQUN0Qix3QkFBd0IsaUNBQWlDO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkIsZ0JBQWdCLElBQUk7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGNBQWMsTUFBTTtBQUNwQjtBQUNBLGNBQWMsY0FBYztBQUM1QixjQUFjLEtBQUs7QUFDbkIsZ0JBQWdCLE1BQU07QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxRQUFRO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxTQUFTO0FBQ3ZCLGNBQWMsS0FBSztBQUNuQixjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsU0FBUztBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsSUFBSTtBQUNsQixnQkFBZ0Isb0JBQW9CO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLElBQUk7QUFDbEIsZ0JBQWdCLFdBQVc7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQixnQkFBZ0IsSUFBSTtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQixnQkFBZ0IsUUFBUTtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CLGNBQWMsbUJBQW1CO0FBQ2pDLGNBQWMsT0FBTztBQUNyQixnQkFBZ0IsS0FBSztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsV0FBVztBQUN6QjtBQUNBLGNBQWMsS0FBSztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGNBQWMsSUFBSTtBQUNsQixjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGdCQUFnQixPQUFPO0FBQ3ZCLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsY0FBYyxJQUFJO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxjQUFjLEtBQUs7QUFDbkIsY0FBYyxJQUFJO0FBQ2xCLGNBQWMsU0FBUztBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsb0JBQW9CO0FBQ2xDLGNBQWMsU0FBUztBQUN2QixjQUFjLElBQUk7QUFDbEI7QUFDQSxjQUFjLEtBQUs7QUFDbkIsY0FBYyxLQUFLO0FBQ25CLGdCQUFnQixJQUFJO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9EQUFvRDtBQUNwRCx5RUFBeUU7QUFDekUsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCO0FBQ0EsZ0JBQWdCLFFBQVE7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7OztBQUlBO0FBQ0E7QUFDQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSx3Q0FBd0M7OztBQUd4QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQyxTQUFTO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx5Q0FBeUMsU0FBUztBQUNsRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDLFNBQVM7QUFDOUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFFBQVE7O0FBRVI7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQkFBZ0Isd0JBQXdCO0FBQ3hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFVBQVU7QUFDVixVQUFVO0FBQ1YsbUJBQW1CO0FBQ25CLHlCQUF5Qjs7QUFFekI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxxQkFBcUIsSUFBSSxXQUFXLElBQUksV0FBVyxJQUFJLE1BQU0sRUFBRSxHQUFHLElBQUksUUFBUSxFQUFFLFNBQVMsRUFBRTs7QUFFM0Y7QUFDQSxrR0FBa0csS0FBSzs7QUFFdkc7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsUUFBUTtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLFFBQVE7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsVUFBVSxRQUFRO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsUUFBUTtBQUNsQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQkFBcUIsUUFBUTtBQUM3QjtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQSwrQkFBK0IsUUFBUTtBQUN2QyxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsb0NBQW9DLFFBQVE7QUFDNUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsTUFBTTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0JBQW9CLFFBQVE7QUFDNUI7O0FBRUEsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFNBQVM7QUFDdEIsYUFBYSxRQUFRO0FBQ3JCLGNBQWMsU0FBUztBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsZ0JBQWdCLE9BQU87QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLEVBQUU7QUFDZixhQUFhLEVBQUU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHlDQUF5QyxRQUFRO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsS0FBSztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DOztBQUVuQztBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxJQUFJO0FBQ2pCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx3Q0FBd0MsU0FBUztBQUNqRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLElBQUk7QUFDakIsZUFBZSxJQUFJO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsSUFBSTtBQUNqQixhQUFhLE9BQU87QUFDcEIsZUFBZSxJQUFJO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsSUFBSTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0EsZUFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUNBQWlDLFFBQVE7QUFDekM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQyxRQUFRO0FBQ3pDLGlDQUFpQyxRQUFRO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsTUFBTTtBQUNuQixhQUFhLE1BQU07QUFDbkIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLE9BQU87QUFDdEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQyxTQUFTO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxNQUFNO0FBQ25CLGFBQWEsS0FBSztBQUNsQjtBQUNBLGFBQWEsTUFBTTtBQUNuQjtBQUNBLGVBQWUsSUFBSTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxrQkFBa0I7QUFDL0IsZUFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsS0FBSztBQUNsQixlQUFlLElBQUk7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsSUFBSTtBQUNqQixhQUFhLEtBQUs7QUFDbEIsZUFBZSxJQUFJO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLElBQUk7QUFDakIsYUFBYSxJQUFJO0FBQ2pCLGFBQWEsT0FBTztBQUNwQixlQUFlLEVBQUU7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxJQUFJO0FBQ2pCLGFBQWEsSUFBSTtBQUNqQixhQUFhLEVBQUU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsTUFBTTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLG9CQUFvQjtBQUNqQyxlQUFlLFNBQVM7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxtQ0FBbUMsU0FBUztBQUM1QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseUNBQXlDLFNBQVM7QUFDbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLG9CQUFvQjtBQUNqQyxlQUFlLFNBQVM7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQ0FBb0MsU0FBUztBQUM3QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx1Q0FBdUMsU0FBUztBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdDQUFnQztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIscUJBQXFCLE1BQU07QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsSUFBSTtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdDQUFnQyxTQUFTO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxPQUFPO0FBQ25CLFlBQVksSUFBSTtBQUNoQixZQUFZLE9BQU87QUFDbkI7QUFDQSxZQUFZLElBQUk7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDLFFBQVE7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQixRQUFRO0FBQ3ZDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxPQUFPO0FBQ25CLFlBQVksWUFBWTtBQUN4QjtBQUNBLFlBQVksSUFBSTtBQUNoQixZQUFZLGFBQWE7QUFDekI7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDLFFBQVE7QUFDMUM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLElBQUk7QUFDakIsYUFBYSxLQUFLO0FBQ2xCO0FBQ0EsYUFBYSxNQUFNO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLCtDQUErQyxTQUFTO0FBQ3hEO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxpQ0FBaUMsUUFBUTtBQUN6QztBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdDQUFnQyxRQUFRO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLG1CQUFtQixRQUFRO0FBQzNCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQ0FBbUMsU0FBUztBQUM1QztBQUNBO0FBQ0E7O0FBRUE7QUFDQSx1QkFBdUIsT0FBTztBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGtDQUFrQyxTQUFTO0FBQzNDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxzQ0FBc0MsU0FBUztBQUMvQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixhQUFhO0FBQzlCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx1QkFBdUIsU0FBUztBQUNoQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhCQUE4Qiw4Q0FBOEM7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxRQUFRO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtEQUFrRDtBQUNsRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQixnQkFBZ0I7QUFDakM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsWUFBWTtBQUNaOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkNBQTJDLFNBQVM7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixPQUFPO0FBQzFCLGFBQWEsS0FBSztBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSwrQkFBK0IsU0FBUztBQUN4QztBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrQkFBK0IsU0FBUztBQUN4QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCLGFBQWE7QUFDN0I7QUFDQSxpQkFBaUIsYUFBYTtBQUM5QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLEtBQUs7QUFDbEIsYUFBYSxNQUFNO0FBQ25CLHFCQUFxQixLQUFLO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0NBQXNDLFNBQVM7QUFDL0M7QUFDQSwwQ0FBMEMsU0FBUztBQUNuRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLE9BQU87QUFDbkIsWUFBWSxNQUFNO0FBQ2xCO0FBQ0EsWUFBWSxTQUFTO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNDQUFzQztBQUN0QyxhQUFhO0FBQ2IsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlLFFBQVE7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsS0FBSztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGVBQWUsK0JBQStCO0FBQzlDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsYUFBYSxnQkFBZ0I7QUFDN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsbUJBQW1CLGdDQUFnQzs7QUFFbkQ7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQixhQUFhLElBQUk7QUFDakIsYUFBYSxJQUFJO0FBQ2pCLGFBQWEsTUFBTTtBQUNuQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxrQ0FBa0MsUUFBUTtBQUMxQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixjQUFjLE9BQU87QUFDckIsY0FBYyxNQUFNO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7O0FBRTNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGVBQWUsS0FBSztBQUNwQixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQzs7QUFFM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsYUFBYSxJQUFJO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtCQUFrQix3QkFBd0I7QUFDMUM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDLFFBQVE7QUFDN0M7O0FBRUE7QUFDQSwwQ0FBMEMsUUFBUTtBQUNsRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsYUFBYSxJQUFJO0FBQ2pCLGFBQWEsS0FBSztBQUNsQixhQUFhLEtBQUs7QUFDbEIsYUFBYSxLQUFLO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGlCQUFpQixtQkFBbUI7QUFDcEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsYUFBYSxJQUFJO0FBQ2pCLGFBQWEsS0FBSztBQUNsQixhQUFhLEtBQUs7QUFDbEIsYUFBYSxLQUFLO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWMsbUJBQW1CO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLEtBQUs7QUFDbEIsYUFBYSxLQUFLO0FBQ2xCLGFBQWEsS0FBSztBQUNsQixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx5Q0FBeUMsUUFBUTtBQUNqRDs7QUFFQTtBQUNBOztBQUVBLG1DQUFtQyxRQUFRO0FBQzNDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlLEtBQUs7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEM7O0FBRTVDO0FBQ0E7QUFDQSwwQkFBMEIsMkJBQTJCLEVBQUU7QUFDdkQ7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDLFNBQVM7QUFDM0M7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGdCQUFnQixpQkFBaUI7QUFDakM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlLEtBQUs7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUgscUNBQXFDLFFBQVE7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlLEtBQUs7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHdDQUF3QyxRQUFRO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLFdBQVc7QUFDeEI7QUFDQTtBQUNBLGVBQWUsS0FBSztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7OztBQUlBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEIsZUFBZSxLQUFLO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLEtBQUs7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsS0FBSztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixrQ0FBa0M7QUFDN0Q7QUFDQSxhQUFhLCtCQUErQjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsZUFBZSxvQ0FBb0M7QUFDbkQ7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsK0JBQStCO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGFBQWEsK0JBQStCO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0EsZUFBZSxvQ0FBb0M7QUFDbkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG9DQUFvQztBQUNwQztBQUNBOztBQUVBO0FBQ0E7QUFDQSxtQ0FBbUM7QUFDbkM7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRSxnQkFBZ0I7QUFDdEY7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLHVFQUF1RSxnQkFBZ0I7QUFDdkY7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0EsYUFBYSxTQUFTO0FBQ3RCLG1CQUFtQixNQUFNO0FBQ3pCLG1CQUFtQixNQUFNO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7QUFJQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYSwwQkFBMEI7QUFDdkM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxnQkFBZ0I7QUFDOUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGNBQWMsMEJBQTBCO0FBQ3hDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxlQUFlLDBCQUEwQjtBQUN6QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsMEJBQTBCO0FBQ3hDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxTQUFTO0FBQ3RCLGFBQWEsSUFBSTtBQUNqQixlQUFlLFNBQVM7QUFDeEI7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsS0FBSztBQUNsQixlQUFlLElBQUk7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLElBQUk7QUFDakIsZUFBZSxLQUFLO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLElBQUk7QUFDakIsZUFBZSxPQUFPO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNkNBQTZDLFFBQVE7QUFDckQ7QUFDQTtBQUNBLHlCQUF5Qjs7QUFFekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGFBQWEsc0JBQXNCO0FBQ25DO0FBQ0E7QUFDQTs7QUFFQSxxQ0FBcUMsU0FBUztBQUM5QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsK0JBQStCLFFBQVE7QUFDdkM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUMsU0FBUztBQUNsRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCLFFBQVE7QUFDeEI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdCQUFnQixRQUFRO0FBQ3hCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHNDQUFzQyxTQUFTO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLEtBQUs7QUFDbEIsYUFBYSxJQUFJO0FBQ2pCLGFBQWEsUUFBUTtBQUNyQjtBQUNBLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EscUJBQXFCO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsS0FBSztBQUNsQixhQUFhLElBQUk7QUFDakIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNkJBQTZCO0FBQzdCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0NBQWtDLFFBQVE7QUFDMUM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrQkFBK0IsUUFBUTtBQUN2Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDZDQUE2QyxRQUFRO0FBQ3JEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw2Q0FBNkM7O0FBRTdDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQyxRQUFRO0FBQzdDOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsS0FBSztBQUNsQixlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsSUFBSTtBQUNqQixhQUFhLE9BQU87QUFDcEIsYUFBYSxJQUFJO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQjtBQUNBLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckIsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjO0FBQ2Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEIsYUFBYSxTQUFTO0FBQ3RCLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixhQUFhLE9BQU87QUFDcEI7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQSxhQUFhLE1BQU07QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGVBQWUsT0FBTztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsMEJBQTBCO0FBQ3ZDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFdBQVc7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixJQUFJO0FBQzFCO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQixJQUFJO0FBQzFCO0FBQ0E7QUFDQSxZQUFZLDJCQUEyQjtBQUN2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxNQUFNO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHNDQUFzQyxRQUFRO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIOzs7QUFHQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBLG1DQUFtQyxPQUFPO0FBQzFDO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0MsUUFBUTtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDs7O0FBR0E7QUFDQTtBQUNBLDhDQUE4QyxRQUFRO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGtDQUFrQyxRQUFRO0FBQzFDOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsa0NBQWtDLFFBQVE7QUFDMUM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQyxRQUFRO0FBQzVDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7O0FBRUg7OztBQUdBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIOzs7QUFHQTtBQUNBOzs7QUFHQTs7O0FBR0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIOzs7QUFHQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw2QkFBNkIsUUFBUTtBQUNyQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxxQ0FBcUM7QUFDckM7QUFDQTtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQW1DLFFBQVE7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQyxRQUFRO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw4QkFBOEIsUUFBUTtBQUN0QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGVBQWU7QUFDM0IsYUFBYSxNQUFNO0FBQ25CLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWSxlQUFlO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLGNBQWMsY0FBYztBQUM1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7Ozs7QUFJRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7OztBQUlGO0FBQ0E7QUFDQTtBQUNBLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLGVBQWU7QUFDM0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxlQUFlO0FBQzdCO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQztBQUNoQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEIsY0FBYyxlQUFlO0FBQzdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7O0FBSUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0Esb0NBQW9DLFFBQVE7QUFDNUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEI7QUFDQTtBQUNBLGNBQWMsZUFBZTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksT0FBTztBQUNuQixjQUFjLGVBQWU7QUFDN0I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsZUFBZTtBQUM3QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7Ozs7QUFLRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQ0FBa0MsUUFBUTtBQUMxQztBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEIsUUFBUTtBQUNwQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QixRQUFRO0FBQ3RDO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7OztBQUdBO0FBQ0E7QUFDQTtBQUNBLGtDQUFrQyxRQUFRO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQjs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpRUFBaUUsUUFBUTtBQUN6RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNkNBQTZDO0FBQzdDO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSwwQ0FBMEMsUUFBUTtBQUNsRDtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ04sS0FBSyxRQUFRO0FBQ2IsS0FBSyxLQUFLO0FBQ1YsS0FBSyxPQUFPO0FBQ1osS0FBSyxNQUFNO0FBQ1g7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHFDQUFxQyxRQUFRO0FBQzdDLHNDQUFzQyxRQUFRO0FBQzlDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSwrQkFBK0IsUUFBUTtBQUN2QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxzQ0FBc0MsUUFBUTtBQUM5QztBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxpREFBaUQ7O0FBRWpEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSw4Q0FBOEMsUUFBUTtBQUN0RDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdDQUFnQyxRQUFRO0FBQ3hDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7Ozs7OztBQU1GO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOzs7QUFHRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsRUFBRTs7OztBQUlGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDLFFBQVE7QUFDekM7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGVBQWUsZUFBZTtBQUM5QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLG9DQUFvQyxRQUFRO0FBQzVDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQyxRQUFRO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7Ozs7QUFJRjtBQUNBO0FBQ0E7QUFDQSxLQUFLLFFBQVE7QUFDYixNQUFNLFFBQVE7QUFDZCxNQUFNLFFBQVEsdUJBQXVCLFFBQVE7QUFDN0MsTUFBTSxPQUFPO0FBQ2IsTUFBTSxPQUFPO0FBQ2I7QUFDQTs7QUFFQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQyxVQUFVO0FBQzlDO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQyxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtCQUErQixRQUFRO0FBQ3ZDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7Ozs7QUFJRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsZ0NBQWdDLFFBQVE7QUFDeEM7O0FBRUEsZ0JBQWdCLFlBQVk7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLG9DQUFvQyxRQUFRO0FBQzVDLHdDQUF3QyxRQUFRO0FBQ2hEO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7QUFHRjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7O0FBSUY7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7OztBQUlGO0FBQ0E7QUFDQTtBQUNBLGNBQWMsTUFBTTtBQUNwQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLFFBQVE7QUFDcEIsWUFBWSxPQUFPO0FBQ25CLGNBQWMsZUFBZTtBQUM3QjtBQUNBO0FBQ0E7QUFDQSxZQUFZLE1BQU07QUFDbEIsWUFBWSxNQUFNO0FBQ2xCLGNBQWMsZUFBZTtBQUM3QjtBQUNBO0FBQ0E7QUFDQSxZQUFZLE1BQU07QUFDbEIsY0FBYyxlQUFlO0FBQzdCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQSxZQUFZLG1CQUFtQjtBQUMvQjtBQUNBO0FBQ0EsWUFBWSxRQUFRO0FBQ3BCLFlBQVksU0FBUztBQUNyQixjQUFjLGVBQWU7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSyxhQUFhO0FBQ2xCO0FBQ0E7O0FBRUE7QUFDQSwrQ0FBK0M7QUFDL0MsR0FBRztBQUNILEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0EsR0FBRztBQUNILEVBQUU7Ozs7QUFJRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDRDQUE0QztBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0gsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0Esc0VBQXNFO0FBQ3RFLEdBQUc7QUFDSCxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7O0FBSUY7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE9BQU87QUFDcEI7QUFDQSxlQUFlLFFBQVE7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsb0NBQW9DLFNBQVM7QUFDN0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxtQkFBbUI7QUFDaEM7QUFDQTtBQUNBLGVBQWUsUUFBUTtBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxRQUFRO0FBQ3JCO0FBQ0EsZUFBZSxNQUFNO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCO0FBQ0EsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsUUFBUTtBQUNyQjtBQUNBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7OztBQUdGO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOzs7QUFHRjtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7OztBQUdGO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5REFBeUQsY0FBYyxFQUFFO0FBQ3pFOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHO0FBQ0gsRUFBRTs7O0FBR0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSwwQ0FBMEM7QUFDMUMsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUM7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLEVBQUU7QUFDaEIsY0FBYyxhQUFhO0FBQzNCLGNBQWMsSUFBSTtBQUNsQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLGFBQWE7QUFDM0I7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQSxnQkFBZ0IsRUFBRTtBQUNsQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxhQUFhO0FBQzNCO0FBQ0EsY0FBYyxFQUFFO0FBQ2hCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLG9CQUFvQjtBQUNuQyxlQUFlLHFCQUFxQjtBQUNwQyxlQUFlLHNCQUFzQjtBQUNyQyxlQUFlLHFCQUFxQjtBQUNwQyxlQUFlO0FBQ2Y7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHdDQUF3QztBQUN2RCxlQUFlLHlDQUF5QztBQUN4RCxlQUFlLDBDQUEwQztBQUN6RCxlQUFlLHlDQUF5QztBQUN4RCxlQUFlO0FBQ2Y7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxREFBcUQsdUJBQXVCO0FBQzVFO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDLDRCQUE0QjtBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkMsUUFBUTtBQUNyRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsUUFBUTtBQUNSO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTSxnQ0FBZ0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIsZ0NBQWdDO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSx3QkFBd0I7QUFDdkM7QUFDQSxlQUFlO0FBQ2Y7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNLDZCQUE2QjtBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CLGNBQWMsTUFBTTtBQUNwQixjQUFjLElBQUk7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CLGNBQWMsTUFBTTtBQUNwQixjQUFjLElBQUk7QUFDbEI7QUFDQSxjQUFjLElBQUk7QUFDbEI7QUFDQSxjQUFjLFVBQVU7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsSUFBSTtBQUNsQixnQkFBZ0IsT0FBTztBQUN2QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCLEVBQUU7QUFDNUI7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsY0FBYyxFQUFFO0FBQ2hCO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxLQUFLO0FBQ25CLGNBQWMsTUFBTTtBQUNwQixjQUFjLElBQUk7QUFDbEI7QUFDQSxjQUFjLElBQUk7QUFDbEI7QUFDQSxjQUFjLFVBQVU7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxJQUFJO0FBQ2xCLGNBQWMsSUFBSTtBQUNsQixjQUFjLElBQUk7QUFDbEI7QUFDQSxjQUFjLElBQUk7QUFDbEIsY0FBYyxPQUFPO0FBQ3JCO0FBQ0EsZ0JBQWdCLE9BQU87QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixnQkFBZ0IsUUFBUTtBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsS0FBSztBQUNuQixjQUFjLE1BQU07QUFDcEIsY0FBYyxJQUFJO0FBQ2xCLGNBQWMsSUFBSTtBQUNsQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE1BQU07QUFDcEI7QUFDQSxjQUFjLFNBQVM7QUFDdkI7QUFDQSxjQUFjLE9BQU87QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE1BQU07QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsVUFBVTtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsT0FBTztBQUNyQixjQUFjLE9BQU87QUFDckI7QUFDQSxlQUFlLE9BQU87QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxPQUFPO0FBQ3JCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxjQUFjLE9BQU87QUFDckIsY0FBYyxPQUFPO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEMsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU0sZ0NBQWdDO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7O0FBR2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1g7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWDtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaLFVBQVU7QUFDVjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaLFVBQVU7QUFDVjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1osVUFBVTtBQUNWO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaLFVBQVU7QUFDVjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaLFVBQVU7QUFDVjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWixVQUFVO0FBQ1Y7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWixVQUFVO0FBQ1Y7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1osVUFBVTtBQUNWO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWixVQUFVO0FBQ1Y7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaLFVBQVU7QUFDVjtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWixVQUFVO0FBQ1Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWixVQUFVO0FBQ1Y7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWixVQUFVO0FBQ1Y7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZO0FBQ1osVUFBVTtBQUNWO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQSx5QkFBeUI7OztBQUd6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0IsV0FBVztBQUNqQyxzQkFBc0IsaUJBQWlCO0FBQ3ZDLHNCQUFzQixlQUFlO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0JBQXNCLGtCQUFrQjtBQUN4QyxzQkFBc0IsTUFBTSxLQUFLLE1BQU07QUFDdkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IsVUFBVSxNQUFNLGVBQWUsSUFBSSxXQUFXO0FBQ3RFLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxnQ0FBZ0M7QUFDekU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSwwQ0FBMEM7QUFDekQsZUFBZSwwQ0FBMEM7QUFDekQsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLHdCQUF3QjtBQUN2QyxlQUFlLHdCQUF3QjtBQUN2QyxlQUFlLGlCQUFpQjtBQUNoQztBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSwrQ0FBK0M7QUFDOUQsZUFBZSw4REFBOEQ7QUFDN0UsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsNkJBQTZCO0FBQzVDLGVBQWUsNENBQTRDO0FBQzNELGVBQWUsOEJBQThCO0FBQzdDO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGVBQWU7QUFDZixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxzQkFBc0I7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2YsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGVBQWU7QUFDZixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxxQkFBcUI7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2YsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmLGVBQWU7QUFDZixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxtQkFBbUI7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2YsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWMsUUFBUTtBQUN0QixjQUFjLEVBQUU7QUFDaEIsY0FBYyxhQUFhO0FBQzNCLGNBQWMsSUFBSTtBQUNsQixjQUFjLElBQUk7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYyxhQUFhO0FBQzNCLGNBQWMsT0FBTztBQUNyQjtBQUNBO0FBQ0E7QUFDQSxjQUFjLEVBQUU7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkIsTUFBTTtBQUNqQyw0QkFBNEIsTUFBTTtBQUNsQyw2QkFBNkIsTUFBTTtBQUNuQyw0QkFBNEIsTUFBTTtBQUNsQywwQkFBMEI7QUFDMUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsbUJBQW1CO0FBQ2xDLGVBQWUsb0JBQW9CO0FBQ25DLGVBQWUscUJBQXFCO0FBQ3BDLGVBQWUsb0JBQW9CO0FBQ25DLGVBQWU7QUFDZjtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQixNQUFNO0FBQ2pDLDRCQUE0QixNQUFNO0FBQ2xDO0FBQ0EsNkJBQTZCO0FBQzdCLGlCQUFpQjtBQUNqQjtBQUNBLG9CQUFvQixNQUFNLEdBQUc7QUFDN0I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxtQkFBbUI7QUFDbEMsZUFBZSxvQkFBb0I7QUFDbkMsZUFBZSwyQkFBMkI7QUFDMUMsZUFBZSwrQkFBK0I7QUFDOUMsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLGFBQWE7QUFDMUIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0EsYUFBYSxhQUFhO0FBQzFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLG1CQUFtQjtBQUNsQyxlQUFlLG9CQUFvQjtBQUNuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsc0JBQXNCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxxQ0FBcUM7QUFDcEQsZUFBZSxzQ0FBc0M7QUFDckQsZUFBZSx1Q0FBdUM7QUFDdEQsZUFBZSxzQ0FBc0M7QUFDckQsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLG1CQUFtQjtBQUNsQyxlQUFlLG9CQUFvQjtBQUNuQyxlQUFlLHFCQUFxQjtBQUNwQyxlQUFlLG9CQUFvQjtBQUNuQyxlQUFlO0FBQ2Y7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxtREFBbUQ7QUFDbEUsZUFBZSxzQ0FBc0M7QUFDckQsZUFBZSxrREFBa0Q7QUFDakUsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSw4QkFBOEI7QUFDN0MsZUFBZSxpREFBaUQ7QUFDaEUsZUFBZSxnQ0FBZ0M7QUFDL0MsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZTtBQUNmO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLDZCQUE2QjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZUFBZSxpQkFBaUI7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVc7QUFDWCxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsaUJBQWlCO0FBQ2hDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5Qyx5QkFBeUI7QUFDbEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHlCQUF5QjtBQUNsRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHlCQUF5QjtBQUNsRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix5QkFBeUI7QUFDbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHlCQUF5QjtBQUNsRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIseUJBQXlCO0FBQ2xEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix5QkFBeUI7QUFDbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHlCQUF5QjtBQUNsRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix5QkFBeUI7QUFDbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix5QkFBeUI7QUFDbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix5QkFBeUI7QUFDbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIseUJBQXlCO0FBQ2xEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIseUJBQXlCO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5Qix5QkFBeUI7QUFDbEQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHlCQUF5QjtBQUNsRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUIseUJBQXlCO0FBQ2xEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLHlCQUF5QjtBQUNsRDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsbUNBQW1DLDRCQUE0QjtBQUMvRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7O0FBRVo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IseUJBQXlCO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBLHVCQUF1Qjs7QUFFdkI7QUFDQTtBQUNBLE1BQU0sK0JBQStCO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qix5QkFBeUI7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IseUJBQXlCO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qix5QkFBeUI7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IseUJBQXlCO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTSxpQ0FBaUM7QUFDdkM7QUFDQSx3QkFBd0IseUJBQXlCO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IseUJBQXlCO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qix5QkFBeUI7QUFDakQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IseUJBQXlCO0FBQ2pEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBd0IseUJBQXlCO0FBQ2pEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qix5QkFBeUI7QUFDakQ7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHlCQUF5QjtBQUNqRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHlCQUF5QjtBQUNqRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHlCQUF5QjtBQUNqRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQjs7QUFFaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLHlCQUF5QjtBQUNqRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0I7O0FBRWhCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOzs7QUFHYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOzs7QUFHYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsT0FBTztBQUNqQixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsUUFBUSxVQUFVO0FBQ2xCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esb0NBQW9DLDJCQUEyQjtBQUMvRCxXQUFXO0FBQ1g7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxPQUFPO0FBQ2pCLFNBQVM7QUFDVCxVQUFVLGFBQWE7QUFDdkI7QUFDQTtBQUNBLFVBQVUsSUFBSSxjQUFjLHdDQUF3QztBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQVEsUUFBUTtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwREFBMEQsZUFBZTtBQUN6RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsY0FBYzs7O0FBR2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU0sd0NBQXdDO0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxJQUFJO0FBQ2QsVUFBVSxJQUFJO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVMsSUFBSTtBQUNiLFNBQVMsTUFBTTtBQUNmO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXOzs7QUFHWDtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLEdBQUc7OztBQUdIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVUsT0FBTztBQUNqQixTQUFTO0FBQ1QsVUFBVSxJQUFJO0FBQ2Q7QUFDQTtBQUNBO0FBQ0EsU0FBUyxNQUFNO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsY0FBYztBQUN4RDtBQUNBLFdBQVc7QUFDWDtBQUNBO0FBQ0EsV0FBVzs7O0FBR1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsRUFBRTtBQUNqQixlQUFlLFNBQVM7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxVQUFVLFlBQVk7QUFDdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFFQUFxRTtBQUNyRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxlQUFlLEVBQUU7QUFDakI7QUFDQTtBQUNBO0FBQ0EsVUFBVSxZQUFZO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7OztBQUdiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVSxLQUFLO0FBQ2YsVUFBVSxLQUFLO0FBQ2YsVUFBVSxLQUFLO0FBQ2Y7QUFDQSw2Q0FBNkMsS0FBSztBQUNsRCxRQUFRLEtBQUssWUFBWSxLQUFLO0FBQzlCLGtCQUFrQixLQUFLO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBLFFBQVEsS0FBSztBQUNiO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLFVBQVUsRUFBRTtBQUNaO0FBQ0EsUUFBUSxLQUFLLFlBQVksS0FBSztBQUM5QjtBQUNBO0FBQ0EsZUFBZSxFQUFFO0FBQ2pCLGVBQWUsRUFBRTtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxVQUFVLEVBQUU7QUFDWjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVk7QUFDWjtBQUNBO0FBQ0E7QUFDQSxVQUFVO0FBQ1Y7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7O0FBR2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQyxRQUFRO0FBQzVDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDBEQUEwRDtBQUMxRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFVBQVU7QUFDVjtBQUNBOztBQUVBO0FBQ0EsZ0JBQWdCLGVBQWU7QUFDL0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7O0FBSUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7Ozs7QUFJRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7OztBQUdGO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QjtBQUM5QixhQUFhO0FBQ2I7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJOztBQUVKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esd0JBQXdCLHNCQUFzQix3QkFBd0I7QUFDdEU7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCLEVBQUU7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGFBQWEsT0FBTztBQUNwQixlQUFlLFNBQVM7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOzs7QUFHRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLE9BQU8sK0JBQStCO0FBQ25EOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxPQUFPLCtCQUErQjtBQUNuRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLE9BQU8sK0JBQStCO0FBQ25EOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsT0FBTywrQkFBK0I7QUFDbkQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLE9BQU87QUFDcEIsYUFBYSxPQUFPO0FBQ3BCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxPQUFPO0FBQ3BCLGFBQWEsT0FBTztBQUNwQjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsTUFBTTtBQUNuQixhQUFhLE9BQU87QUFDcEIsYUFBYSxRQUFRO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxPQUFPLCtCQUErQjtBQUNuRCxhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlEQUFpRCxRQUFRO0FBQ3pEO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxPQUFPLCtCQUErQjtBQUNuRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsT0FBTywrQkFBK0I7QUFDbkQsYUFBYSxRQUFRO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSxNQUFNO0FBQ25CLGFBQWEsT0FBTywrQkFBK0I7QUFDbkQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLE1BQU07QUFDbkIsYUFBYSxPQUFPLCtCQUErQjtBQUNuRCxhQUFhLElBQUk7QUFDakIsYUFBYSxLQUFLO0FBQ2xCOztBQUVBO0FBQ0EsQ0FBQzs7Ozs7OztBQ3o0ZEQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBLHdGQUF3RjtBQUN4RixLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN6RUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzlJRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzNERDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzNERDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM5SEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzVERDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ3pHRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzNERDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN6R0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ3RJRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMxRkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOztBQUU1Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMzREQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN2SEQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN2SEQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDNUdEO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN4SkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDeEZEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxtQkFBbUIsUUFBUTtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsbUJBQW1CLFFBQVE7QUFDM0I7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxtQkFBbUIsUUFBUTtBQUMzQjtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsaUNBQWlDLElBQUk7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ25MRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDL0REO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtCQUErQjtBQUMvQixhQUFhO0FBQ2I7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUNqRkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM1REQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzlFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMvRUQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDOUVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDcEdEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7QUFFNUI7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLGdHQUFnRztBQUN6RztBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsNkJBQTZCO0FBQzdCLDRCQUE0QjtBQUM1Qiw0QkFBNEI7QUFDNUIsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLHFEQUFxRDtBQUNyRDtBQUNBLHNEQUFzRDtBQUN0RDtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakMsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDcEdEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ25FRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQy9ERDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUNuRUQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbkVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ25FRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDekVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxpQ0FBaUMsSUFBSTtBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDNUZEO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsaUNBQWlDLElBQUk7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzNGRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGlDQUFpQyxJQUFJO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUNuRkQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ2pGRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ2xFRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDM0dEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzdHRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzVERDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUNuRkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMxRUQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDOUVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzNFRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsaUNBQWlDLElBQUk7QUFDckM7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDNUVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsaUNBQWlDLElBQUk7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzdFRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxpQ0FBaUMsSUFBSTtBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMzSEQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzVIRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbkdEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM1SEQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzFKRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM5R0Q7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJLElBQUksSUFBSTtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQy9GRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbkZEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ3BJRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsaUNBQWlDLElBQUk7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ3RFRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxpQ0FBaUMsSUFBSTtBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUNoRkQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ25GRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCwwQ0FBMEMsSUFBSSxJQUFJLElBQUk7QUFDdEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ3pGRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN2RkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDMUREO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDOUhEO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsaUNBQWlDLElBQUk7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbEZEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7OztBQUk1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN4RkQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGtCQUFrQjtBQUNsQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN6SUQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLHFDQUFxQyxJQUFJO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ3RFRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN0SEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0RBQXdEO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbEdEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDaEhEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBLG1EQUFtRCxJQUFJO0FBQ3ZELHlEQUF5RCxJQUFJO0FBQzdELHdEQUF3RCxJQUFJO0FBQzVELDhEQUE4RCxJQUFJO0FBQ2xFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDaEVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzFGRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDakZEO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw0Q0FBNEM7QUFDNUMsMkNBQTJDO0FBQzNDLDBDQUEwQztBQUMxQyw0Q0FBNEM7QUFDNUMsd0NBQXdDO0FBQ3hDLHlDQUF5QztBQUN6Qyx5Q0FBeUM7QUFDekMsMENBQTBDO0FBQzFDLDBDQUEwQztBQUMxQywyQ0FBMkM7QUFDM0MseUNBQXlDO0FBQ3pDLDJDQUEyQztBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QztBQUM5Qyw2Q0FBNkM7QUFDN0MsNENBQTRDO0FBQzVDLDZDQUE2QztBQUM3QywwQ0FBMEM7QUFDMUMsMkNBQTJDO0FBQzNDLDJDQUEyQztBQUMzQyw0Q0FBNEM7QUFDNUMsNkNBQTZDO0FBQzdDLDhDQUE4QztBQUM5QywyQ0FBMkM7QUFDM0MsNENBQTRDO0FBQzVDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDaktEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbEZEO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUNuRkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGlDQUFpQyxJQUFJO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM1REQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ2hHRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQy9ERDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzNIRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDeEZEO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN4RkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM1REQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzVIRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM5SEQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0NBQXdDO0FBQ3hDLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ2pFRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEMsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzdERDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDNUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDeExEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ2xHRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7Ozs7QUFJNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM3REQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDdkVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUM3SkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDN0tEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDdEVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMvR0Q7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQSxZQUFZO0FBQ1o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQy9HRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7Ozs7QUFJNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDekZEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsZ0NBQWdDLElBQUk7QUFDcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUNyRUQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMzREQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULDRCQUE0QjtBQUM1QixTQUFTO0FBQ1QsMkJBQTJCO0FBQzNCLFNBQVM7QUFDVCw4QkFBOEI7QUFDOUIsU0FBUztBQUNULDhCQUE4QjtBQUM5QixTQUFTO0FBQ1QsMkJBQTJCO0FBQzNCLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbElEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGlDQUFpQyxJQUFJO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ3pGRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQ3BFRDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbkVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDOUREO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMxSEQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBLDJCQUEyQjtBQUMzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMxRkQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBLENBQUM7Ozs7Ozs7QUM1RkQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDMUREO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzFERDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDeEpEO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDbkdEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUEsQ0FBQzs7Ozs7OztBQzFERDtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMxREQ7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDL0VEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDcEVEO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCx1Q0FBdUMsSUFBSTtBQUMzQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7O0FDNUREO0FBQ0E7QUFDQTtBQUNBOztBQUVBLENBQUM7QUFDRCxRQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUMsMkJBQTJCOzs7QUFHNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUMvR0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxDQUFDO0FBQ0QsUUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLDJCQUEyQjs7O0FBRzVCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLGdDQUFnQyxJQUFJO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEOztBQUVBLENBQUM7Ozs7Ozs7QUN6R0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsQ0FBQztBQUNELFFBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQywyQkFBMkI7OztBQUc1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxnQ0FBZ0MsSUFBSTtBQUNwQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQSxDQUFDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDeEdEO0FBQUE7QUFBQTs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7QUFDQUEsT0FBT0MsQ0FBUCxHQUFXRCxPQUFPRSxNQUFQLEdBQWdCLDhDQUEzQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FDMUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEMsQ0FBQyxxQ0FBcUM7O0FBRXRDO0FBQ0E7O0FBRUE7QUFDQSxpQkFBaUIsa0JBQWtCO0FBQ25DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG1CQUFtQixzQkFBc0I7QUFDekM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCQUF3Qjs7QUFFeEI7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0VBQWdFO0FBQ2hFOztBQUVBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QztBQUM5QyxPQUFPOztBQUVQO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87OztBQUdQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7OztBQUdMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOzs7QUFHTjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOzs7QUFHTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07OztBQUdOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4QkFBOEI7O0FBRTlCLCtCQUErQjs7QUFFL0IsbUNBQW1DOztBQUVuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7O0FBR0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsV0FBVztBQUNYO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOzs7QUFHTjtBQUNBO0FBQ0E7O0FBRUEsaUNBQWlDOztBQUVqQztBQUNBLCtCQUErQjtBQUMvQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBLDhCQUE4QjtBQUM5Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTCxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHFCQUFxQix1QkFBdUI7QUFDNUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx1QkFBdUIsK0JBQStCO0FBQ3REO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQSwwQkFBMEI7QUFDMUIsNkNBQTZDOztBQUU3QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLHFDQUFxQzs7QUFFckM7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUNBQWlDOztBQUVqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7O0FBRTFCLHlCQUF5Qjs7QUFFekIsc0JBQXNCOztBQUV0Qiw0QkFBNEI7O0FBRTVCLDhCQUE4Qjs7QUFFOUIsbUNBQW1DOztBQUVuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOzs7QUFHTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG9DQUFvQzs7QUFFcEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDJDQUEyQzs7QUFFM0M7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxvQ0FBb0MseURBQXlEO0FBQzdGO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEscUJBQXFCLG9CQUFvQjtBQUN6Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCOztBQUUxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7O0FBR0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPOztBQUVQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQSwwQkFBMEI7QUFDMUI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxXQUFXO0FBQ1g7QUFDQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLEVBQUU7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLEVBQUU7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTLEVBQUU7O0FBRVg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLEVBQUU7O0FBRVQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLEVBQUU7O0FBRVQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07OztBQUdOO0FBQ0E7QUFDQTs7QUFFQSxpQ0FBaUM7O0FBRWpDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHFFQUFxRTs7QUFFckU7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPOzs7QUFHUDtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjs7QUFFMUI7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7O0FBR0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCwyQ0FBMkM7QUFDM0M7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSw0Q0FBNEM7QUFDNUM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07OztBQUdOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLE1BQU07OztBQUdOO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXO0FBQ1gsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0EsV0FBVztBQUNYOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTzs7QUFFUDtBQUNBLGlDQUFpQztBQUNqQztBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsMEJBQTBCOztBQUUxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILCtCQUErQjtBQUMvQjtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDRDQUE0Qzs7QUFFNUM7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxNQUFNOzs7QUFHTjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07OztBQUdOO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0EsS0FBSzs7O0FBR0w7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07OztBQUdOO0FBQ0EsMEJBQTBCOztBQUUxQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBLHdDQUF3QyxLQUFLO0FBQzdDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSw4Q0FBOEM7OztBQUc5QztBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLHlDQUF5QztBQUN6Qzs7QUFFQSxnSUFBZ0k7O0FBRWhJO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0EsTUFBTTs7O0FBR047QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBLG1DQUFtQyxLQUFLO0FBQ3hDOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7OztBQUdMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOzs7QUFHTjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxNQUFNOzs7QUFHTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDhDQUE4QyxjQUFjOztBQUU1RCxDQUFDO0FBQ0Q7Ozs7Ozs7b0hDbnpIQTtBQUNBO0FBQ0E7QUFDQSw0REFBNEQ7QUFDNUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQUE7QUFDVCxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSwrQ0FBK0MsRUFBRTtBQUNqRCxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLHdDQUF3QztBQUN4QyxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxxQ0FBcUMsS0FBSztBQUMxQztBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLFNBQVM7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSwwREFBMEQ7QUFDMUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsNERBQTREO0FBQzVELGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQixpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCLCtDQUErQyxTQUFTO0FBQ3hEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLCtCQUErQjtBQUMvQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUM7QUFDekM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekIscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBLEtBQUs7QUFDTDtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQUE7QUFDVCxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQSwrQ0FBK0MsRUFBRTtBQUNqRCxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBLHdDQUF3QztBQUN4QyxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQ0FBZ0M7QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlEQUF5RDtBQUN6RCxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdURBQXVELHVCQUF1QjtBQUM5RTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQjtBQUMxQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCLDBCQUEwQjtBQUN6RDtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxrREFBa0QsU0FBUztBQUMzRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUVBQWlFLEdBQUc7QUFDcEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQixhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxDQUFDLEU7Ozs7Ozs7QUM1akZEOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUNwREE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLGlCQUFpQjtBQUN0QztBQUNBO0FBQ0E7QUFDQSxrQkFBa0I7QUFDbEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsMENBQTBDLHNCQUFzQixFQUFFO0FBQ2xFO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxVQUFVO0FBQ1Y7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxDQUFDOzs7Ozs7OztBQ3pMRDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHNCQUFzQjtBQUM3QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEscUNBQXFDOztBQUVyQztBQUNBO0FBQ0E7O0FBRUEsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTtBQUNBLDRCQUE0QixVQUFVOzs7Ozs7O0FDdkx0QztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQUE7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOzs7QUFHRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7OztBQUdEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsaUNBQWlDLFFBQVE7QUFDekM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSw0QkFBNEI7QUFDNUI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYSxlQUFlO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0EsQ0FBQzs7Ozs7OztBQ3ZMRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnRUFBZ0U7QUFDaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBLGFBQWEsWUFBWTtBQUN6QixhQUFhLE9BQU87QUFDcEI7QUFDQTtBQUNBO0FBQ0EsNERBQTREO0FBQzVEOztBQUVBLGVBQWU7QUFDZixxQ0FBcUM7OztBQUdyQztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQixXQUFXO0FBQy9CO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFdBQVc7QUFDWDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsWUFBWTtBQUNaO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxZQUFZO0FBQ1o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7OztBQUdBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOLEtBQUs7QUFDTDtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUEsc0JBQXNCO0FBQ3RCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHVCQUF1Qjs7QUFFdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFFBQVE7QUFDUjtBQUNBO0FBQ0E7O0FBRUEsbUNBQW1DOztBQUVuQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsdUJBQXVCOztBQUV2QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxHQUFHOztBQUVIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBLGVBQWU7QUFDZjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLFNBQVMsT0FBTztBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBLGNBQWMsU0FBUztBQUN2QjtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSixHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0EsZUFBZSxZQUFZO0FBQzNCLGVBQWUsT0FBTztBQUN0QixlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QixlQUFlLEVBQUU7QUFDakIsZUFBZTtBQUNmO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRzs7O0FBR0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsVUFBVSxPQUFPO0FBQ2pCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7Ozs7QUFJQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBOzs7QUFHQSxlQUFlLGtCQUFrQjtBQUNqQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBLGNBQWMsWUFBWTtBQUMxQixjQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsWUFBWTtBQUN6QixhQUFhLFNBQVM7QUFDdEIsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0EsWUFBWSxZQUFZO0FBQ3hCLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7Ozs7OztxSkNuZ0REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPLGNBQWM7QUFDckIsVUFBVSxTQUFTLEVBQUUsT0FBTyxjQUFjO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQjtBQUNwQixvQkFBb0I7QUFDcEIsbUJBQW1CO0FBQ25CLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGVBQWUsT0FBTztBQUN0QixlQUFlLE9BQU87QUFDdEI7QUFDQSxpQkFBaUIsT0FBTztBQUN4QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLHVCQUF1QixpQkFBaUI7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHNDQUFzQyxPQUFPO0FBQzdDOztBQUVBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4QyxPQUFPO0FBQ3JEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLDBDQUEwQztBQUMxQztBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLGlCQUFpQjtBQUN4QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsdUZBQXVGO0FBQ3ZGO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVELHlCQUF5QixxQkFBcUI7QUFDOUM7QUFDQSxDQUFDO0FBQ0QsZ0NBQWdDOztBQUVoQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0Esc0JBQXNCOztBQUV0QjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQix5QkFBeUI7QUFDNUM7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsbUJBQW1CLDZCQUE2QjtBQUNoRDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyQ0FBMkMsU0FBUztBQUNwRDtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQSxtQkFBbUIsWUFBWTtBQUMvQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEscUJBQXFCLGlCQUFpQjtBQUN0Qzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCLGlCQUFpQjtBQUNqQixnQkFBZ0I7QUFDaEIsZ0JBQWdCO0FBQ2hCLGtCQUFrQjtBQUNsQixrQkFBa0I7QUFDbEIsaUJBQWlCO0FBQ2pCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPOztBQUVQO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7QUFDN0I7QUFDQSxtQ0FBbUM7QUFDbkMsS0FBSztBQUNMLCtCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUEsbUJBQW1CLHlCQUF5QjtBQUM1Qzs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBLE9BQU87O0FBRVAsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLHFCQUFxQiwwQkFBMEI7QUFDL0M7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsZ0NBQWdDO0FBQ2hDLE9BQU87QUFDUDtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVCxrQ0FBa0M7QUFDbEM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxPQUFPO0FBQ1AsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0Esa0NBQWtDO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBLG1CQUFtQixpQkFBaUI7QUFDcEM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCOztBQUUxQjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLG1CQUFtQixpQkFBaUI7QUFDcEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsNkJBQTZCO0FBQzdCOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSwwQkFBMEI7O0FBRTFCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwyQkFBMkI7QUFDM0I7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBLHVCQUF1QixpQkFBaUI7QUFDeEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEscUJBQXFCLHdCQUF3QjtBQUM3Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEscUJBQXFCLHNCQUFzQjtBQUMzQzs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLHNCQUFzQjtBQUN0QjtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsc0JBQXNCO0FBQ3RCOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsbUJBQW1CLGlCQUFpQjtBQUNwQzs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx1Q0FBdUM7O0FBRXZDOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsMEJBQTBCO0FBQzFCO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLHNCQUFzQjtBQUN0Qjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTzs7QUFFUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EscUJBQXFCLGlCQUFpQjtBQUN0QztBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxxQkFBcUIsaUJBQWlCO0FBQ3RDOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTzs7QUFFUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLGtDQUFrQztBQUNsQztBQUNBLE9BQU87O0FBRVA7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87O0FBRVA7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNCQUFzQjs7QUFFdEI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLENBQUM7O0FBRUQ7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQ0FBaUMsUUFBUTtBQUN6Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUEsNEJBQTRCLEdBQUcsUUFBUTs7QUFFdkM7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0E7QUFDQTs7QUFFQSxtQkFBbUIsaUJBQWlCO0FBQ3BDOztBQUVBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7O0FBRTdCO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQSxDQUFDOztBQUVEOztBQUVBO0FBQ0EsNkJBQTZCOztBQUU3QjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0JBQStCOztBQUUvQjtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxxQkFBcUIsMEJBQTBCO0FBQy9DO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQzs7QUFFckM7QUFDQSw4Q0FBOEMsUUFBUTtBQUN0RDs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDO0FBQ2pDLEtBQUs7QUFDTDtBQUNBOztBQUVBLGdDQUFnQzs7QUFFaEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBLGdDQUFnQzs7QUFFaEMsdUNBQXVDLE9BQU87QUFDOUM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUCxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxLQUFLO0FBQ0w7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSwrQkFBK0I7QUFDL0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1QsT0FBTztBQUNQLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxPQUFPO0FBQ1AsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsU0FBUztBQUNULDJDQUEyQzs7QUFFM0M7QUFDQSxTQUFTO0FBQ1QsMkNBQTJDOztBQUUzQztBQUNBLFNBQVM7QUFDVCw2Q0FBNkM7O0FBRTdDO0FBQ0EsU0FBUztBQUNULHlDQUF5Qzs7QUFFekM7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsZ0NBQWdDO0FBQ2hDLEtBQUs7QUFDTCwrQkFBK0I7QUFDL0I7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLHFCQUFxQixpQ0FBaUM7QUFDdEQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNULE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDRCQUE0QjtBQUM1Qjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSw0QkFBNEI7QUFDNUI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsNEJBQTRCO0FBQzVCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaURBQWlEOztBQUVqRDtBQUNBLFNBQVM7O0FBRVQ7QUFDQSxPQUFPO0FBQ1A7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFNBQVM7O0FBRVQ7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxPQUFPO0FBQ1A7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLENBQUM7Ozs7Ozs7O0FDdHRMRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdCOzs7Ozs7QUM5UEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSx1QkFBdUI7QUFDdkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLHlCQUF5Qjs7QUFFekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBOztBQUVBO0FBQ0EsNENBQTRDO0FBQzVDLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUIsMEJBQTBCO0FBQzNDO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsK0NBQStDLHFFQUFxRTtBQUNwSDtBQUNBLDhFQUE4RSxxRUFBcUU7QUFDbko7QUFDQSwrQ0FBK0MscUVBQXFFO0FBQ3BIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsdUVBQXVFO0FBQ3RIO0FBQ0E7QUFDQSxnRkFBZ0YseUVBQXlFO0FBQ3pKO0FBQ0EsK0NBQStDLHVFQUF1RTtBQUN0SDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwrQ0FBK0MsdUVBQXVFO0FBQ3RIO0FBQ0E7QUFDQSxnRkFBZ0YseUVBQXlFO0FBQ3pKO0FBQ0EsK0NBQStDLHVFQUF1RTtBQUN0SDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGdGQUFnRix3RkFBd0Y7QUFDeEs7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQSw2REFBNkQsMERBQTBEO0FBQ3ZIO0FBQ0E7QUFDQSw2REFBNkQsc0VBQXNFO0FBQ25JO0FBQ0E7QUFDQSw2REFBNkQsMERBQTBEO0FBQ3ZIO0FBQ0E7QUFDQSw2REFBNkQsMERBQTBEO0FBQ3ZIO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakIsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsbURBQW1EO0FBQzdGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBLCtDQUErQyxVQUFVO0FBQ3pEO0FBQ0E7O0FBRUE7O0FBRUEsK0NBQStDLFVBQVU7QUFDekQ7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esa0VBQWtFOztBQUVsRTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsMkJBQTJCLFFBQVEsT0FBTztBQUMxQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjs7QUFFQTs7QUFFQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFCQUFxQjtBQUNyQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdEQUFnRDtBQUNoRDtBQUNBO0FBQ0EseUJBQXlCLE9BQU87QUFDaEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7O0FBRWpCO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSw4REFBOEQ7QUFDOUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDO0FBQ3pDO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRSxhQUFhO0FBQzlFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTs7QUFFYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjs7QUFFakI7QUFDQTtBQUNBO0FBQ0EscUJBQXFCO0FBQ3JCLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckIsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBLGFBQWE7O0FBRWI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsYUFBYTs7QUFFYjtBQUNBOztBQUVBLG1GQUFtRixJQUFJO0FBQ3ZGO0FBQ0EsaUZBQWlGLElBQUksOEJBQThCO0FBQ25IO0FBQ0EscUJBQXFCO0FBQ3JCLGlCQUFpQjs7O0FBR2pCO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHdDQUF3QztBQUN4Qzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQ7QUFDM0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwREFBMEQ7QUFDMUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsaUNBQWlDO0FBQ2pDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxrQ0FBa0M7QUFDbEM7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGtDQUFrQztBQUNsQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGtDQUFrQztBQUNsQzs7QUFFQSxtQkFBbUI7QUFDbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1FQUFtRTtBQUNuRTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJEQUEyRDtBQUMzRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwREFBMEQ7QUFDMUQ7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG1CQUFtQixnREFBZ0Q7QUFDbkUscUJBQXFCO0FBQ3JCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnREFBZ0Q7QUFDaEQ7QUFDQTtBQUNBLGFBQWE7QUFDYixTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxhQUFhOztBQUViO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2Isc0NBQXNDO0FBQ3RDO0FBQ0E7QUFDQSxlQUFlO0FBQ2Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxDQUFDOzs7Ozs7O0FDM2tGRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxtQkFBbUIsUUFBUSxLQUFLLE1BQU07QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDs7QUFFQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHdDQUF3QztBQUN4Qzs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2QkFBNkI7O0FBRTdCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLEVBQUU7OztBQUdGO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQSx5QkFBeUI7O0FBRXpCOztBQUVBO0FBQ0EsY0FBYyxpREFBaUQ7O0FBRS9ELGtEQUFrRCxVQUFVLGlCQUFpQjtBQUM3RSxrQkFBa0Isb0JBQW9COztBQUV0QztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSxpQkFBaUIsNEJBQTRCO0FBQzdDOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7O0FBRUo7QUFDQTtBQUNBLElBQUk7QUFDSiw4QkFBOEI7QUFDOUI7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0NBQStDLHFCQUFxQjtBQUNwRSwrQ0FBK0MsaUJBQWlCO0FBQ2hFLG9EQUFvRCxzQkFBc0I7QUFDMUU7QUFDQTs7QUFFQSwrQ0FBK0Msa0JBQWtCOztBQUVqRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDBCQUEwQixnQkFBZ0I7O0FBRTFDLHFEQUFxRCxjQUFjLG1CQUFtQixjQUFjLGdCQUFnQjs7QUFFcEg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsMkJBQTJCO0FBQzNCO0FBQ0E7QUFDQTs7QUFFQSxpQkFBaUI7QUFDakI7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxZQUFZLHNCQUFzQjs7QUFFbEM7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLGtCQUFrQjtBQUMvQixHQUFHO0FBQ0g7QUFDQTtBQUNBLGFBQWEscUJBQXFCO0FBQ2xDOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQSxZQUFZLHlEQUF5RDs7QUFFckU7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUzs7QUFFVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDZCQUE2QjtBQUM3QjtBQUNBLE1BQU07QUFDTjs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQSxHQUFHO0FBQ0g7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsZ0JBQWdCLGtCQUFrQjs7QUFFbEM7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsaUJBQWlCLGVBQWU7QUFDaEM7QUFDQTs7QUFFQSxnQkFBZ0IsbUJBQW1COztBQUVuQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxRQUFRLDJFQUEyRTtBQUNuRixRQUFRLG9CQUFvQjtBQUM1Qjs7QUFFQTs7QUFFQTs7QUFFQSxnQkFBZ0IsZ0JBQWdCOztBQUVoQzs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQSxtQkFBbUI7QUFDbkI7QUFDQSxxREFBcUQsUUFBUSx3QkFBd0IsTUFBTTtBQUMzRjs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxNQUFNO0FBQ047QUFDQTs7QUFFQTtBQUNBO0FBQ0EsS0FBSzs7QUFFTDtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0osR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRzs7QUFFSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJOztBQUVKO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBLEdBQUc7O0FBRUg7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJOztBQUVKOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGNBQWMsUUFBUTs7QUFFdEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxDQUFDOzs7Ozs7OztBQ2hsQ0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSx3REFBd0QsUUFBUTs7QUFFaEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQSxrQkFBa0I7QUFDbEI7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIOztBQUVBOztBQUVBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDLEkiLCJmaWxlIjoiL3B1YmxpYy9hc3NldHMtMi4wLjAvanMvdmVuZG9yLmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cbiBcdC8vIExvYWQgZW50cnkgbW9kdWxlIGFuZCByZXR1cm4gZXhwb3J0c1xuIFx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18oX193ZWJwYWNrX3JlcXVpcmVfXy5zID0gMTI0KTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyB3ZWJwYWNrL2Jvb3RzdHJhcCBmYjQ0YWU5MThhYmFmNWVmYzJhMyIsIi8vISBtb21lbnQuanNcbi8vISB2ZXJzaW9uIDogMi4yMC4xXG4vLyEgYXV0aG9ycyA6IFRpbSBXb29kLCBJc2tyZW4gQ2hlcm5ldiwgTW9tZW50LmpzIGNvbnRyaWJ1dG9yc1xuLy8hIGxpY2Vuc2UgOiBNSVRcbi8vISBtb21lbnRqcy5jb21cblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KCkgOlxuICAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShmYWN0b3J5KSA6XG4gICAgZ2xvYmFsLm1vbWVudCA9IGZhY3RvcnkoKVxufSh0aGlzLCAoZnVuY3Rpb24gKCkgeyAndXNlIHN0cmljdCc7XG5cbnZhciBob29rQ2FsbGJhY2s7XG5cbmZ1bmN0aW9uIGhvb2tzICgpIHtcbiAgICByZXR1cm4gaG9va0NhbGxiYWNrLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG59XG5cbi8vIFRoaXMgaXMgZG9uZSB0byByZWdpc3RlciB0aGUgbWV0aG9kIGNhbGxlZCB3aXRoIG1vbWVudCgpXG4vLyB3aXRob3V0IGNyZWF0aW5nIGNpcmN1bGFyIGRlcGVuZGVuY2llcy5cbmZ1bmN0aW9uIHNldEhvb2tDYWxsYmFjayAoY2FsbGJhY2spIHtcbiAgICBob29rQ2FsbGJhY2sgPSBjYWxsYmFjaztcbn1cblxuZnVuY3Rpb24gaXNBcnJheShpbnB1dCkge1xuICAgIHJldHVybiBpbnB1dCBpbnN0YW5jZW9mIEFycmF5IHx8IE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IEFycmF5XSc7XG59XG5cbmZ1bmN0aW9uIGlzT2JqZWN0KGlucHV0KSB7XG4gICAgLy8gSUU4IHdpbGwgdHJlYXQgdW5kZWZpbmVkIGFuZCBudWxsIGFzIG9iamVjdCBpZiBpdCB3YXNuJ3QgZm9yXG4gICAgLy8gaW5wdXQgIT0gbnVsbFxuICAgIHJldHVybiBpbnB1dCAhPSBudWxsICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IE9iamVjdF0nO1xufVxuXG5mdW5jdGlvbiBpc09iamVjdEVtcHR5KG9iaikge1xuICAgIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcykge1xuICAgICAgICByZXR1cm4gKE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKG9iaikubGVuZ3RoID09PSAwKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaztcbiAgICAgICAgZm9yIChrIGluIG9iaikge1xuICAgICAgICAgICAgaWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGlucHV0KSB7XG4gICAgcmV0dXJuIGlucHV0ID09PSB2b2lkIDA7XG59XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGlucHV0KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBpbnB1dCA9PT0gJ251bWJlcicgfHwgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgTnVtYmVyXSc7XG59XG5cbmZ1bmN0aW9uIGlzRGF0ZShpbnB1dCkge1xuICAgIHJldHVybiBpbnB1dCBpbnN0YW5jZW9mIERhdGUgfHwgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuXG5mdW5jdGlvbiBtYXAoYXJyLCBmbikge1xuICAgIHZhciByZXMgPSBbXSwgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgYXJyLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHJlcy5wdXNoKGZuKGFycltpXSwgaSkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBoYXNPd25Qcm9wKGEsIGIpIHtcbiAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGEsIGIpO1xufVxuXG5mdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgIGZvciAodmFyIGkgaW4gYikge1xuICAgICAgICBpZiAoaGFzT3duUHJvcChiLCBpKSkge1xuICAgICAgICAgICAgYVtpXSA9IGJbaV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoaGFzT3duUHJvcChiLCAndG9TdHJpbmcnKSkge1xuICAgICAgICBhLnRvU3RyaW5nID0gYi50b1N0cmluZztcbiAgICB9XG5cbiAgICBpZiAoaGFzT3duUHJvcChiLCAndmFsdWVPZicpKSB7XG4gICAgICAgIGEudmFsdWVPZiA9IGIudmFsdWVPZjtcbiAgICB9XG5cbiAgICByZXR1cm4gYTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlVVRDIChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCkge1xuICAgIHJldHVybiBjcmVhdGVMb2NhbE9yVVRDKGlucHV0LCBmb3JtYXQsIGxvY2FsZSwgc3RyaWN0LCB0cnVlKS51dGMoKTtcbn1cblxuZnVuY3Rpb24gZGVmYXVsdFBhcnNpbmdGbGFncygpIHtcbiAgICAvLyBXZSBuZWVkIHRvIGRlZXAgY2xvbmUgdGhpcyBvYmplY3QuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgZW1wdHkgICAgICAgICAgIDogZmFsc2UsXG4gICAgICAgIHVudXNlZFRva2VucyAgICA6IFtdLFxuICAgICAgICB1bnVzZWRJbnB1dCAgICAgOiBbXSxcbiAgICAgICAgb3ZlcmZsb3cgICAgICAgIDogLTIsXG4gICAgICAgIGNoYXJzTGVmdE92ZXIgICA6IDAsXG4gICAgICAgIG51bGxJbnB1dCAgICAgICA6IGZhbHNlLFxuICAgICAgICBpbnZhbGlkTW9udGggICAgOiBudWxsLFxuICAgICAgICBpbnZhbGlkRm9ybWF0ICAgOiBmYWxzZSxcbiAgICAgICAgdXNlckludmFsaWRhdGVkIDogZmFsc2UsXG4gICAgICAgIGlzbyAgICAgICAgICAgICA6IGZhbHNlLFxuICAgICAgICBwYXJzZWREYXRlUGFydHMgOiBbXSxcbiAgICAgICAgbWVyaWRpZW0gICAgICAgIDogbnVsbCxcbiAgICAgICAgcmZjMjgyMiAgICAgICAgIDogZmFsc2UsXG4gICAgICAgIHdlZWtkYXlNaXNtYXRjaCA6IGZhbHNlXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0UGFyc2luZ0ZsYWdzKG0pIHtcbiAgICBpZiAobS5fcGYgPT0gbnVsbCkge1xuICAgICAgICBtLl9wZiA9IGRlZmF1bHRQYXJzaW5nRmxhZ3MoKTtcbiAgICB9XG4gICAgcmV0dXJuIG0uX3BmO1xufVxuXG52YXIgc29tZTtcbmlmIChBcnJheS5wcm90b3R5cGUuc29tZSkge1xuICAgIHNvbWUgPSBBcnJheS5wcm90b3R5cGUuc29tZTtcbn0gZWxzZSB7XG4gICAgc29tZSA9IGZ1bmN0aW9uIChmdW4pIHtcbiAgICAgICAgdmFyIHQgPSBPYmplY3QodGhpcyk7XG4gICAgICAgIHZhciBsZW4gPSB0Lmxlbmd0aCA+Pj4gMDtcblxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoaSBpbiB0ICYmIGZ1bi5jYWxsKHRoaXMsIHRbaV0sIGksIHQpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gaXNWYWxpZChtKSB7XG4gICAgaWYgKG0uX2lzVmFsaWQgPT0gbnVsbCkge1xuICAgICAgICB2YXIgZmxhZ3MgPSBnZXRQYXJzaW5nRmxhZ3MobSk7XG4gICAgICAgIHZhciBwYXJzZWRQYXJ0cyA9IHNvbWUuY2FsbChmbGFncy5wYXJzZWREYXRlUGFydHMsIGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICByZXR1cm4gaSAhPSBudWxsO1xuICAgICAgICB9KTtcbiAgICAgICAgdmFyIGlzTm93VmFsaWQgPSAhaXNOYU4obS5fZC5nZXRUaW1lKCkpICYmXG4gICAgICAgICAgICBmbGFncy5vdmVyZmxvdyA8IDAgJiZcbiAgICAgICAgICAgICFmbGFncy5lbXB0eSAmJlxuICAgICAgICAgICAgIWZsYWdzLmludmFsaWRNb250aCAmJlxuICAgICAgICAgICAgIWZsYWdzLmludmFsaWRXZWVrZGF5ICYmXG4gICAgICAgICAgICAhZmxhZ3Mud2Vla2RheU1pc21hdGNoICYmXG4gICAgICAgICAgICAhZmxhZ3MubnVsbElucHV0ICYmXG4gICAgICAgICAgICAhZmxhZ3MuaW52YWxpZEZvcm1hdCAmJlxuICAgICAgICAgICAgIWZsYWdzLnVzZXJJbnZhbGlkYXRlZCAmJlxuICAgICAgICAgICAgKCFmbGFncy5tZXJpZGllbSB8fCAoZmxhZ3MubWVyaWRpZW0gJiYgcGFyc2VkUGFydHMpKTtcblxuICAgICAgICBpZiAobS5fc3RyaWN0KSB7XG4gICAgICAgICAgICBpc05vd1ZhbGlkID0gaXNOb3dWYWxpZCAmJlxuICAgICAgICAgICAgICAgIGZsYWdzLmNoYXJzTGVmdE92ZXIgPT09IDAgJiZcbiAgICAgICAgICAgICAgICBmbGFncy51bnVzZWRUb2tlbnMubGVuZ3RoID09PSAwICYmXG4gICAgICAgICAgICAgICAgZmxhZ3MuYmlnSG91ciA9PT0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKE9iamVjdC5pc0Zyb3plbiA9PSBudWxsIHx8ICFPYmplY3QuaXNGcm96ZW4obSkpIHtcbiAgICAgICAgICAgIG0uX2lzVmFsaWQgPSBpc05vd1ZhbGlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGlzTm93VmFsaWQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG0uX2lzVmFsaWQ7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUludmFsaWQgKGZsYWdzKSB7XG4gICAgdmFyIG0gPSBjcmVhdGVVVEMoTmFOKTtcbiAgICBpZiAoZmxhZ3MgIT0gbnVsbCkge1xuICAgICAgICBleHRlbmQoZ2V0UGFyc2luZ0ZsYWdzKG0pLCBmbGFncyk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MobSkudXNlckludmFsaWRhdGVkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICByZXR1cm4gbTtcbn1cblxuLy8gUGx1Z2lucyB0aGF0IGFkZCBwcm9wZXJ0aWVzIHNob3VsZCBhbHNvIGFkZCB0aGUga2V5IGhlcmUgKG51bGwgdmFsdWUpLFxuLy8gc28gd2UgY2FuIHByb3Blcmx5IGNsb25lIG91cnNlbHZlcy5cbnZhciBtb21lbnRQcm9wZXJ0aWVzID0gaG9va3MubW9tZW50UHJvcGVydGllcyA9IFtdO1xuXG5mdW5jdGlvbiBjb3B5Q29uZmlnKHRvLCBmcm9tKSB7XG4gICAgdmFyIGksIHByb3AsIHZhbDtcblxuICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5faXNBTW9tZW50T2JqZWN0KSkge1xuICAgICAgICB0by5faXNBTW9tZW50T2JqZWN0ID0gZnJvbS5faXNBTW9tZW50T2JqZWN0O1xuICAgIH1cbiAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2kpKSB7XG4gICAgICAgIHRvLl9pID0gZnJvbS5faTtcbiAgICB9XG4gICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9mKSkge1xuICAgICAgICB0by5fZiA9IGZyb20uX2Y7XG4gICAgfVxuICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fbCkpIHtcbiAgICAgICAgdG8uX2wgPSBmcm9tLl9sO1xuICAgIH1cbiAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX3N0cmljdCkpIHtcbiAgICAgICAgdG8uX3N0cmljdCA9IGZyb20uX3N0cmljdDtcbiAgICB9XG4gICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl90em0pKSB7XG4gICAgICAgIHRvLl90em0gPSBmcm9tLl90em07XG4gICAgfVxuICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5faXNVVEMpKSB7XG4gICAgICAgIHRvLl9pc1VUQyA9IGZyb20uX2lzVVRDO1xuICAgIH1cbiAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX29mZnNldCkpIHtcbiAgICAgICAgdG8uX29mZnNldCA9IGZyb20uX29mZnNldDtcbiAgICB9XG4gICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9wZikpIHtcbiAgICAgICAgdG8uX3BmID0gZ2V0UGFyc2luZ0ZsYWdzKGZyb20pO1xuICAgIH1cbiAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2xvY2FsZSkpIHtcbiAgICAgICAgdG8uX2xvY2FsZSA9IGZyb20uX2xvY2FsZTtcbiAgICB9XG5cbiAgICBpZiAobW9tZW50UHJvcGVydGllcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBtb21lbnRQcm9wZXJ0aWVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBwcm9wID0gbW9tZW50UHJvcGVydGllc1tpXTtcbiAgICAgICAgICAgIHZhbCA9IGZyb21bcHJvcF07XG4gICAgICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKHZhbCkpIHtcbiAgICAgICAgICAgICAgICB0b1twcm9wXSA9IHZhbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0bztcbn1cblxudmFyIHVwZGF0ZUluUHJvZ3Jlc3MgPSBmYWxzZTtcblxuLy8gTW9tZW50IHByb3RvdHlwZSBvYmplY3RcbmZ1bmN0aW9uIE1vbWVudChjb25maWcpIHtcbiAgICBjb3B5Q29uZmlnKHRoaXMsIGNvbmZpZyk7XG4gICAgdGhpcy5fZCA9IG5ldyBEYXRlKGNvbmZpZy5fZCAhPSBudWxsID8gY29uZmlnLl9kLmdldFRpbWUoKSA6IE5hTik7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICB0aGlzLl9kID0gbmV3IERhdGUoTmFOKTtcbiAgICB9XG4gICAgLy8gUHJldmVudCBpbmZpbml0ZSBsb29wIGluIGNhc2UgdXBkYXRlT2Zmc2V0IGNyZWF0ZXMgbmV3IG1vbWVudFxuICAgIC8vIG9iamVjdHMuXG4gICAgaWYgKHVwZGF0ZUluUHJvZ3Jlc3MgPT09IGZhbHNlKSB7XG4gICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcyk7XG4gICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzTW9tZW50IChvYmopIHtcbiAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgTW9tZW50IHx8IChvYmogIT0gbnVsbCAmJiBvYmouX2lzQU1vbWVudE9iamVjdCAhPSBudWxsKTtcbn1cblxuZnVuY3Rpb24gYWJzRmxvb3IgKG51bWJlcikge1xuICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICAgIC8vIC0wIC0+IDBcbiAgICAgICAgcmV0dXJuIE1hdGguY2VpbChudW1iZXIpIHx8IDA7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IobnVtYmVyKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRvSW50KGFyZ3VtZW50Rm9yQ29lcmNpb24pIHtcbiAgICB2YXIgY29lcmNlZE51bWJlciA9ICthcmd1bWVudEZvckNvZXJjaW9uLFxuICAgICAgICB2YWx1ZSA9IDA7XG5cbiAgICBpZiAoY29lcmNlZE51bWJlciAhPT0gMCAmJiBpc0Zpbml0ZShjb2VyY2VkTnVtYmVyKSkge1xuICAgICAgICB2YWx1ZSA9IGFic0Zsb29yKGNvZXJjZWROdW1iZXIpO1xuICAgIH1cblxuICAgIHJldHVybiB2YWx1ZTtcbn1cblxuLy8gY29tcGFyZSB0d28gYXJyYXlzLCByZXR1cm4gdGhlIG51bWJlciBvZiBkaWZmZXJlbmNlc1xuZnVuY3Rpb24gY29tcGFyZUFycmF5cyhhcnJheTEsIGFycmF5MiwgZG9udENvbnZlcnQpIHtcbiAgICB2YXIgbGVuID0gTWF0aC5taW4oYXJyYXkxLmxlbmd0aCwgYXJyYXkyLmxlbmd0aCksXG4gICAgICAgIGxlbmd0aERpZmYgPSBNYXRoLmFicyhhcnJheTEubGVuZ3RoIC0gYXJyYXkyLmxlbmd0aCksXG4gICAgICAgIGRpZmZzID0gMCxcbiAgICAgICAgaTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgaWYgKChkb250Q29udmVydCAmJiBhcnJheTFbaV0gIT09IGFycmF5MltpXSkgfHxcbiAgICAgICAgICAgICghZG9udENvbnZlcnQgJiYgdG9JbnQoYXJyYXkxW2ldKSAhPT0gdG9JbnQoYXJyYXkyW2ldKSkpIHtcbiAgICAgICAgICAgIGRpZmZzKys7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRpZmZzICsgbGVuZ3RoRGlmZjtcbn1cblxuZnVuY3Rpb24gd2Fybihtc2cpIHtcbiAgICBpZiAoaG9va3Muc3VwcHJlc3NEZXByZWNhdGlvbldhcm5pbmdzID09PSBmYWxzZSAmJlxuICAgICAgICAgICAgKHR5cGVvZiBjb25zb2xlICE9PSAgJ3VuZGVmaW5lZCcpICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0RlcHJlY2F0aW9uIHdhcm5pbmc6ICcgKyBtc2cpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZGVwcmVjYXRlKG1zZywgZm4pIHtcbiAgICB2YXIgZmlyc3RUaW1lID0gdHJ1ZTtcblxuICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoaG9va3MuZGVwcmVjYXRpb25IYW5kbGVyICE9IG51bGwpIHtcbiAgICAgICAgICAgIGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlcihudWxsLCBtc2cpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmaXJzdFRpbWUpIHtcbiAgICAgICAgICAgIHZhciBhcmdzID0gW107XG4gICAgICAgICAgICB2YXIgYXJnO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBhcmcgPSAnJztcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGFyZ3VtZW50c1tpXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnICs9ICdcXG5bJyArIGkgKyAnXSAnO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBrZXkgaW4gYXJndW1lbnRzWzBdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgKz0ga2V5ICsgJzogJyArIGFyZ3VtZW50c1swXVtrZXldICsgJywgJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBhcmcgPSBhcmcuc2xpY2UoMCwgLTIpOyAvLyBSZW1vdmUgdHJhaWxpbmcgY29tbWEgYW5kIHNwYWNlXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhcmdzLnB1c2goYXJnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHdhcm4obXNnICsgJ1xcbkFyZ3VtZW50czogJyArIEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3MpLmpvaW4oJycpICsgJ1xcbicgKyAobmV3IEVycm9yKCkpLnN0YWNrKTtcbiAgICAgICAgICAgIGZpcnN0VGltZSA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH0sIGZuKTtcbn1cblxudmFyIGRlcHJlY2F0aW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBkZXByZWNhdGVTaW1wbGUobmFtZSwgbXNnKSB7XG4gICAgaWYgKGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciAhPSBudWxsKSB7XG4gICAgICAgIGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlcihuYW1lLCBtc2cpO1xuICAgIH1cbiAgICBpZiAoIWRlcHJlY2F0aW9uc1tuYW1lXSkge1xuICAgICAgICB3YXJuKG1zZyk7XG4gICAgICAgIGRlcHJlY2F0aW9uc1tuYW1lXSA9IHRydWU7XG4gICAgfVxufVxuXG5ob29rcy5zdXBwcmVzc0RlcHJlY2F0aW9uV2FybmluZ3MgPSBmYWxzZTtcbmhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciA9IG51bGw7XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oaW5wdXQpIHtcbiAgICByZXR1cm4gaW5wdXQgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaW5wdXQpID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5mdW5jdGlvbiBzZXQgKGNvbmZpZykge1xuICAgIHZhciBwcm9wLCBpO1xuICAgIGZvciAoaSBpbiBjb25maWcpIHtcbiAgICAgICAgcHJvcCA9IGNvbmZpZ1tpXTtcbiAgICAgICAgaWYgKGlzRnVuY3Rpb24ocHJvcCkpIHtcbiAgICAgICAgICAgIHRoaXNbaV0gPSBwcm9wO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpc1snXycgKyBpXSA9IHByb3A7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdGhpcy5fY29uZmlnID0gY29uZmlnO1xuICAgIC8vIExlbmllbnQgb3JkaW5hbCBwYXJzaW5nIGFjY2VwdHMganVzdCBhIG51bWJlciBpbiBhZGRpdGlvbiB0b1xuICAgIC8vIG51bWJlciArIChwb3NzaWJseSkgc3R1ZmYgY29taW5nIGZyb20gX2RheU9mTW9udGhPcmRpbmFsUGFyc2UuXG4gICAgLy8gVE9ETzogUmVtb3ZlIFwib3JkaW5hbFBhcnNlXCIgZmFsbGJhY2sgaW4gbmV4dCBtYWpvciByZWxlYXNlLlxuICAgIHRoaXMuX2RheU9mTW9udGhPcmRpbmFsUGFyc2VMZW5pZW50ID0gbmV3IFJlZ0V4cChcbiAgICAgICAgKHRoaXMuX2RheU9mTW9udGhPcmRpbmFsUGFyc2Uuc291cmNlIHx8IHRoaXMuX29yZGluYWxQYXJzZS5zb3VyY2UpICtcbiAgICAgICAgICAgICd8JyArICgvXFxkezEsMn0vKS5zb3VyY2UpO1xufVxuXG5mdW5jdGlvbiBtZXJnZUNvbmZpZ3MocGFyZW50Q29uZmlnLCBjaGlsZENvbmZpZykge1xuICAgIHZhciByZXMgPSBleHRlbmQoe30sIHBhcmVudENvbmZpZyksIHByb3A7XG4gICAgZm9yIChwcm9wIGluIGNoaWxkQ29uZmlnKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wKGNoaWxkQ29uZmlnLCBwcm9wKSkge1xuICAgICAgICAgICAgaWYgKGlzT2JqZWN0KHBhcmVudENvbmZpZ1twcm9wXSkgJiYgaXNPYmplY3QoY2hpbGRDb25maWdbcHJvcF0pKSB7XG4gICAgICAgICAgICAgICAgcmVzW3Byb3BdID0ge307XG4gICAgICAgICAgICAgICAgZXh0ZW5kKHJlc1twcm9wXSwgcGFyZW50Q29uZmlnW3Byb3BdKTtcbiAgICAgICAgICAgICAgICBleHRlbmQocmVzW3Byb3BdLCBjaGlsZENvbmZpZ1twcm9wXSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNoaWxkQ29uZmlnW3Byb3BdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICByZXNbcHJvcF0gPSBjaGlsZENvbmZpZ1twcm9wXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHJlc1twcm9wXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBmb3IgKHByb3AgaW4gcGFyZW50Q29uZmlnKSB7XG4gICAgICAgIGlmIChoYXNPd25Qcm9wKHBhcmVudENvbmZpZywgcHJvcCkgJiZcbiAgICAgICAgICAgICAgICAhaGFzT3duUHJvcChjaGlsZENvbmZpZywgcHJvcCkgJiZcbiAgICAgICAgICAgICAgICBpc09iamVjdChwYXJlbnRDb25maWdbcHJvcF0pKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHN1cmUgY2hhbmdlcyB0byBwcm9wZXJ0aWVzIGRvbid0IG1vZGlmeSBwYXJlbnQgY29uZmlnXG4gICAgICAgICAgICByZXNbcHJvcF0gPSBleHRlbmQoe30sIHJlc1twcm9wXSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cblxuZnVuY3Rpb24gTG9jYWxlKGNvbmZpZykge1xuICAgIGlmIChjb25maWcgIT0gbnVsbCkge1xuICAgICAgICB0aGlzLnNldChjb25maWcpO1xuICAgIH1cbn1cblxudmFyIGtleXM7XG5cbmlmIChPYmplY3Qua2V5cykge1xuICAgIGtleXMgPSBPYmplY3Qua2V5cztcbn0gZWxzZSB7XG4gICAga2V5cyA9IGZ1bmN0aW9uIChvYmopIHtcbiAgICAgICAgdmFyIGksIHJlcyA9IFtdO1xuICAgICAgICBmb3IgKGkgaW4gb2JqKSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcChvYmosIGkpKSB7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2goaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9O1xufVxuXG52YXIgZGVmYXVsdENhbGVuZGFyID0ge1xuICAgIHNhbWVEYXkgOiAnW1RvZGF5IGF0XSBMVCcsXG4gICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICBuZXh0V2VlayA6ICdkZGRkIFthdF0gTFQnLFxuICAgIGxhc3REYXkgOiAnW1llc3RlcmRheSBhdF0gTFQnLFxuICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgIHNhbWVFbHNlIDogJ0wnXG59O1xuXG5mdW5jdGlvbiBjYWxlbmRhciAoa2V5LCBtb20sIG5vdykge1xuICAgIHZhciBvdXRwdXQgPSB0aGlzLl9jYWxlbmRhcltrZXldIHx8IHRoaXMuX2NhbGVuZGFyWydzYW1lRWxzZSddO1xuICAgIHJldHVybiBpc0Z1bmN0aW9uKG91dHB1dCkgPyBvdXRwdXQuY2FsbChtb20sIG5vdykgOiBvdXRwdXQ7XG59XG5cbnZhciBkZWZhdWx0TG9uZ0RhdGVGb3JtYXQgPSB7XG4gICAgTFRTICA6ICdoOm1tOnNzIEEnLFxuICAgIExUICAgOiAnaDptbSBBJyxcbiAgICBMICAgIDogJ01NL0REL1lZWVknLFxuICAgIExMICAgOiAnTU1NTSBELCBZWVlZJyxcbiAgICBMTEwgIDogJ01NTU0gRCwgWVlZWSBoOm1tIEEnLFxuICAgIExMTEwgOiAnZGRkZCwgTU1NTSBELCBZWVlZIGg6bW0gQSdcbn07XG5cbmZ1bmN0aW9uIGxvbmdEYXRlRm9ybWF0IChrZXkpIHtcbiAgICB2YXIgZm9ybWF0ID0gdGhpcy5fbG9uZ0RhdGVGb3JtYXRba2V5XSxcbiAgICAgICAgZm9ybWF0VXBwZXIgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXkudG9VcHBlckNhc2UoKV07XG5cbiAgICBpZiAoZm9ybWF0IHx8ICFmb3JtYXRVcHBlcikge1xuICAgICAgICByZXR1cm4gZm9ybWF0O1xuICAgIH1cblxuICAgIHRoaXMuX2xvbmdEYXRlRm9ybWF0W2tleV0gPSBmb3JtYXRVcHBlci5yZXBsYWNlKC9NTU1NfE1NfEREfGRkZGQvZywgZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICByZXR1cm4gdmFsLnNsaWNlKDEpO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuX2xvbmdEYXRlRm9ybWF0W2tleV07XG59XG5cbnZhciBkZWZhdWx0SW52YWxpZERhdGUgPSAnSW52YWxpZCBkYXRlJztcblxuZnVuY3Rpb24gaW52YWxpZERhdGUgKCkge1xuICAgIHJldHVybiB0aGlzLl9pbnZhbGlkRGF0ZTtcbn1cblxudmFyIGRlZmF1bHRPcmRpbmFsID0gJyVkJztcbnZhciBkZWZhdWx0RGF5T2ZNb250aE9yZGluYWxQYXJzZSA9IC9cXGR7MSwyfS87XG5cbmZ1bmN0aW9uIG9yZGluYWwgKG51bWJlcikge1xuICAgIHJldHVybiB0aGlzLl9vcmRpbmFsLnJlcGxhY2UoJyVkJywgbnVtYmVyKTtcbn1cblxudmFyIGRlZmF1bHRSZWxhdGl2ZVRpbWUgPSB7XG4gICAgZnV0dXJlIDogJ2luICVzJyxcbiAgICBwYXN0ICAgOiAnJXMgYWdvJyxcbiAgICBzICA6ICdhIGZldyBzZWNvbmRzJyxcbiAgICBzcyA6ICclZCBzZWNvbmRzJyxcbiAgICBtICA6ICdhIG1pbnV0ZScsXG4gICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgaCAgOiAnYW4gaG91cicsXG4gICAgaGggOiAnJWQgaG91cnMnLFxuICAgIGQgIDogJ2EgZGF5JyxcbiAgICBkZCA6ICclZCBkYXlzJyxcbiAgICBNICA6ICdhIG1vbnRoJyxcbiAgICBNTSA6ICclZCBtb250aHMnLFxuICAgIHkgIDogJ2EgeWVhcicsXG4gICAgeXkgOiAnJWQgeWVhcnMnXG59O1xuXG5mdW5jdGlvbiByZWxhdGl2ZVRpbWUgKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgIHZhciBvdXRwdXQgPSB0aGlzLl9yZWxhdGl2ZVRpbWVbc3RyaW5nXTtcbiAgICByZXR1cm4gKGlzRnVuY3Rpb24ob3V0cHV0KSkgP1xuICAgICAgICBvdXRwdXQobnVtYmVyLCB3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKSA6XG4gICAgICAgIG91dHB1dC5yZXBsYWNlKC8lZC9pLCBudW1iZXIpO1xufVxuXG5mdW5jdGlvbiBwYXN0RnV0dXJlIChkaWZmLCBvdXRwdXQpIHtcbiAgICB2YXIgZm9ybWF0ID0gdGhpcy5fcmVsYXRpdmVUaW1lW2RpZmYgPiAwID8gJ2Z1dHVyZScgOiAncGFzdCddO1xuICAgIHJldHVybiBpc0Z1bmN0aW9uKGZvcm1hdCkgPyBmb3JtYXQob3V0cHV0KSA6IGZvcm1hdC5yZXBsYWNlKC8lcy9pLCBvdXRwdXQpO1xufVxuXG52YXIgYWxpYXNlcyA9IHt9O1xuXG5mdW5jdGlvbiBhZGRVbml0QWxpYXMgKHVuaXQsIHNob3J0aGFuZCkge1xuICAgIHZhciBsb3dlckNhc2UgPSB1bml0LnRvTG93ZXJDYXNlKCk7XG4gICAgYWxpYXNlc1tsb3dlckNhc2VdID0gYWxpYXNlc1tsb3dlckNhc2UgKyAncyddID0gYWxpYXNlc1tzaG9ydGhhbmRdID0gdW5pdDtcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplVW5pdHModW5pdHMpIHtcbiAgICByZXR1cm4gdHlwZW9mIHVuaXRzID09PSAnc3RyaW5nJyA/IGFsaWFzZXNbdW5pdHNdIHx8IGFsaWFzZXNbdW5pdHMudG9Mb3dlckNhc2UoKV0gOiB1bmRlZmluZWQ7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZU9iamVjdFVuaXRzKGlucHV0T2JqZWN0KSB7XG4gICAgdmFyIG5vcm1hbGl6ZWRJbnB1dCA9IHt9LFxuICAgICAgICBub3JtYWxpemVkUHJvcCxcbiAgICAgICAgcHJvcDtcblxuICAgIGZvciAocHJvcCBpbiBpbnB1dE9iamVjdCkge1xuICAgICAgICBpZiAoaGFzT3duUHJvcChpbnB1dE9iamVjdCwgcHJvcCkpIHtcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRQcm9wID0gbm9ybWFsaXplVW5pdHMocHJvcCk7XG4gICAgICAgICAgICBpZiAobm9ybWFsaXplZFByb3ApIHtcbiAgICAgICAgICAgICAgICBub3JtYWxpemVkSW5wdXRbbm9ybWFsaXplZFByb3BdID0gaW5wdXRPYmplY3RbcHJvcF07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbm9ybWFsaXplZElucHV0O1xufVxuXG52YXIgcHJpb3JpdGllcyA9IHt9O1xuXG5mdW5jdGlvbiBhZGRVbml0UHJpb3JpdHkodW5pdCwgcHJpb3JpdHkpIHtcbiAgICBwcmlvcml0aWVzW3VuaXRdID0gcHJpb3JpdHk7XG59XG5cbmZ1bmN0aW9uIGdldFByaW9yaXRpemVkVW5pdHModW5pdHNPYmopIHtcbiAgICB2YXIgdW5pdHMgPSBbXTtcbiAgICBmb3IgKHZhciB1IGluIHVuaXRzT2JqKSB7XG4gICAgICAgIHVuaXRzLnB1c2goe3VuaXQ6IHUsIHByaW9yaXR5OiBwcmlvcml0aWVzW3VdfSk7XG4gICAgfVxuICAgIHVuaXRzLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGEucHJpb3JpdHkgLSBiLnByaW9yaXR5O1xuICAgIH0pO1xuICAgIHJldHVybiB1bml0cztcbn1cblxuZnVuY3Rpb24gemVyb0ZpbGwobnVtYmVyLCB0YXJnZXRMZW5ndGgsIGZvcmNlU2lnbikge1xuICAgIHZhciBhYnNOdW1iZXIgPSAnJyArIE1hdGguYWJzKG51bWJlciksXG4gICAgICAgIHplcm9zVG9GaWxsID0gdGFyZ2V0TGVuZ3RoIC0gYWJzTnVtYmVyLmxlbmd0aCxcbiAgICAgICAgc2lnbiA9IG51bWJlciA+PSAwO1xuICAgIHJldHVybiAoc2lnbiA/IChmb3JjZVNpZ24gPyAnKycgOiAnJykgOiAnLScpICtcbiAgICAgICAgTWF0aC5wb3coMTAsIE1hdGgubWF4KDAsIHplcm9zVG9GaWxsKSkudG9TdHJpbmcoKS5zdWJzdHIoMSkgKyBhYnNOdW1iZXI7XG59XG5cbnZhciBmb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KFtIaF1tbShzcyk/fE1vfE1NP00/TT98RG98REREb3xERD9EP0Q/fGRkZD9kP3xkbz98d1tvfHddP3xXW298V10/fFFvP3xZWVlZWVl8WVlZWVl8WVlZWXxZWXxnZyhnZ2c/KT98R0coR0dHPyk/fGV8RXxhfEF8aGg/fEhIP3xraz98bW0/fHNzP3xTezEsOX18eHxYfHp6P3xaWj98LikvZztcblxudmFyIGxvY2FsRm9ybWF0dGluZ1Rva2VucyA9IC8oXFxbW15cXFtdKlxcXSl8KFxcXFwpPyhMVFN8TFR8TEw/TD9MP3xsezEsNH0pL2c7XG5cbnZhciBmb3JtYXRGdW5jdGlvbnMgPSB7fTtcblxudmFyIGZvcm1hdFRva2VuRnVuY3Rpb25zID0ge307XG5cbi8vIHRva2VuOiAgICAnTSdcbi8vIHBhZGRlZDogICBbJ01NJywgMl1cbi8vIG9yZGluYWw6ICAnTW8nXG4vLyBjYWxsYmFjazogZnVuY3Rpb24gKCkgeyB0aGlzLm1vbnRoKCkgKyAxIH1cbmZ1bmN0aW9uIGFkZEZvcm1hdFRva2VuICh0b2tlbiwgcGFkZGVkLCBvcmRpbmFsLCBjYWxsYmFjaykge1xuICAgIHZhciBmdW5jID0gY2FsbGJhY2s7XG4gICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgZnVuYyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW2NhbGxiYWNrXSgpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAodG9rZW4pIHtcbiAgICAgICAgZm9ybWF0VG9rZW5GdW5jdGlvbnNbdG9rZW5dID0gZnVuYztcbiAgICB9XG4gICAgaWYgKHBhZGRlZCkge1xuICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1twYWRkZWRbMF1dID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHplcm9GaWxsKGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKSwgcGFkZGVkWzFdLCBwYWRkZWRbMl0pO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAob3JkaW5hbCkge1xuICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1tvcmRpbmFsXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5vcmRpbmFsKGZ1bmMuYXBwbHkodGhpcywgYXJndW1lbnRzKSwgdG9rZW4pO1xuICAgICAgICB9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gcmVtb3ZlRm9ybWF0dGluZ1Rva2VucyhpbnB1dCkge1xuICAgIGlmIChpbnB1dC5tYXRjaCgvXFxbW1xcc1xcU10vKSkge1xuICAgICAgICByZXR1cm4gaW5wdXQucmVwbGFjZSgvXlxcW3xcXF0kL2csICcnKTtcbiAgICB9XG4gICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL1xcXFwvZywgJycpO1xufVxuXG5mdW5jdGlvbiBtYWtlRm9ybWF0RnVuY3Rpb24oZm9ybWF0KSB7XG4gICAgdmFyIGFycmF5ID0gZm9ybWF0Lm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpLCBpLCBsZW5ndGg7XG5cbiAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBhcnJheS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICBpZiAoZm9ybWF0VG9rZW5GdW5jdGlvbnNbYXJyYXlbaV1dKSB7XG4gICAgICAgICAgICBhcnJheVtpXSA9IGZvcm1hdFRva2VuRnVuY3Rpb25zW2FycmF5W2ldXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGFycmF5W2ldID0gcmVtb3ZlRm9ybWF0dGluZ1Rva2VucyhhcnJheVtpXSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gKG1vbSkge1xuICAgICAgICB2YXIgb3V0cHV0ID0gJycsIGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgb3V0cHV0ICs9IGlzRnVuY3Rpb24oYXJyYXlbaV0pID8gYXJyYXlbaV0uY2FsbChtb20sIGZvcm1hdCkgOiBhcnJheVtpXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gb3V0cHV0O1xuICAgIH07XG59XG5cbi8vIGZvcm1hdCBkYXRlIHVzaW5nIG5hdGl2ZSBkYXRlIG9iamVjdFxuZnVuY3Rpb24gZm9ybWF0TW9tZW50KG0sIGZvcm1hdCkge1xuICAgIGlmICghbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIG0ubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgfVxuXG4gICAgZm9ybWF0ID0gZXhwYW5kRm9ybWF0KGZvcm1hdCwgbS5sb2NhbGVEYXRhKCkpO1xuICAgIGZvcm1hdEZ1bmN0aW9uc1tmb3JtYXRdID0gZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0gfHwgbWFrZUZvcm1hdEZ1bmN0aW9uKGZvcm1hdCk7XG5cbiAgICByZXR1cm4gZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0obSk7XG59XG5cbmZ1bmN0aW9uIGV4cGFuZEZvcm1hdChmb3JtYXQsIGxvY2FsZSkge1xuICAgIHZhciBpID0gNTtcblxuICAgIGZ1bmN0aW9uIHJlcGxhY2VMb25nRGF0ZUZvcm1hdFRva2VucyhpbnB1dCkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLmxvbmdEYXRlRm9ybWF0KGlucHV0KSB8fCBpbnB1dDtcbiAgICB9XG5cbiAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcbiAgICB3aGlsZSAoaSA+PSAwICYmIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UobG9jYWxGb3JtYXR0aW5nVG9rZW5zLCByZXBsYWNlTG9uZ0RhdGVGb3JtYXRUb2tlbnMpO1xuICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcbiAgICAgICAgaSAtPSAxO1xuICAgIH1cblxuICAgIHJldHVybiBmb3JtYXQ7XG59XG5cbnZhciBtYXRjaDEgICAgICAgICA9IC9cXGQvOyAgICAgICAgICAgIC8vICAgICAgIDAgLSA5XG52YXIgbWF0Y2gyICAgICAgICAgPSAvXFxkXFxkLzsgICAgICAgICAgLy8gICAgICAwMCAtIDk5XG52YXIgbWF0Y2gzICAgICAgICAgPSAvXFxkezN9LzsgICAgICAgICAvLyAgICAgMDAwIC0gOTk5XG52YXIgbWF0Y2g0ICAgICAgICAgPSAvXFxkezR9LzsgICAgICAgICAvLyAgICAwMDAwIC0gOTk5OVxudmFyIG1hdGNoNiAgICAgICAgID0gL1srLV0/XFxkezZ9LzsgICAgLy8gLTk5OTk5OSAtIDk5OTk5OVxudmFyIG1hdGNoMXRvMiAgICAgID0gL1xcZFxcZD8vOyAgICAgICAgIC8vICAgICAgIDAgLSA5OVxudmFyIG1hdGNoM3RvNCAgICAgID0gL1xcZFxcZFxcZFxcZD8vOyAgICAgLy8gICAgIDk5OSAtIDk5OTlcbnZhciBtYXRjaDV0bzYgICAgICA9IC9cXGRcXGRcXGRcXGRcXGRcXGQ/LzsgLy8gICA5OTk5OSAtIDk5OTk5OVxudmFyIG1hdGNoMXRvMyAgICAgID0gL1xcZHsxLDN9LzsgICAgICAgLy8gICAgICAgMCAtIDk5OVxudmFyIG1hdGNoMXRvNCAgICAgID0gL1xcZHsxLDR9LzsgICAgICAgLy8gICAgICAgMCAtIDk5OTlcbnZhciBtYXRjaDF0bzYgICAgICA9IC9bKy1dP1xcZHsxLDZ9LzsgIC8vIC05OTk5OTkgLSA5OTk5OTlcblxudmFyIG1hdGNoVW5zaWduZWQgID0gL1xcZCsvOyAgICAgICAgICAgLy8gICAgICAgMCAtIGluZlxudmFyIG1hdGNoU2lnbmVkICAgID0gL1srLV0/XFxkKy87ICAgICAgLy8gICAgLWluZiAtIGluZlxuXG52YXIgbWF0Y2hPZmZzZXQgICAgPSAvWnxbKy1dXFxkXFxkOj9cXGRcXGQvZ2k7IC8vICswMDowMCAtMDA6MDAgKzAwMDAgLTAwMDAgb3IgWlxudmFyIG1hdGNoU2hvcnRPZmZzZXQgPSAvWnxbKy1dXFxkXFxkKD86Oj9cXGRcXGQpPy9naTsgLy8gKzAwIC0wMCArMDA6MDAgLTAwOjAwICswMDAwIC0wMDAwIG9yIFpcblxudmFyIG1hdGNoVGltZXN0YW1wID0gL1srLV0/XFxkKyhcXC5cXGR7MSwzfSk/LzsgLy8gMTIzNDU2Nzg5IDEyMzQ1Njc4OS4xMjNcblxuLy8gYW55IHdvcmQgKG9yIHR3bykgY2hhcmFjdGVycyBvciBudW1iZXJzIGluY2x1ZGluZyB0d28vdGhyZWUgd29yZCBtb250aCBpbiBhcmFiaWMuXG4vLyBpbmNsdWRlcyBzY290dGlzaCBnYWVsaWMgdHdvIHdvcmQgYW5kIGh5cGhlbmF0ZWQgbW9udGhzXG52YXIgbWF0Y2hXb3JkID0gL1swLTldezAsMjU2fVsnYS16XFx1MDBBMC1cXHUwNUZGXFx1MDcwMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRjA3XFx1RkYxMC1cXHVGRkVGXXsxLDI1Nn18W1xcdTA2MDAtXFx1MDZGRlxcL117MSwyNTZ9KFxccyo/W1xcdTA2MDAtXFx1MDZGRl17MSwyNTZ9KXsxLDJ9L2k7XG5cblxudmFyIHJlZ2V4ZXMgPSB7fTtcblxuZnVuY3Rpb24gYWRkUmVnZXhUb2tlbiAodG9rZW4sIHJlZ2V4LCBzdHJpY3RSZWdleCkge1xuICAgIHJlZ2V4ZXNbdG9rZW5dID0gaXNGdW5jdGlvbihyZWdleCkgPyByZWdleCA6IGZ1bmN0aW9uIChpc1N0cmljdCwgbG9jYWxlRGF0YSkge1xuICAgICAgICByZXR1cm4gKGlzU3RyaWN0ICYmIHN0cmljdFJlZ2V4KSA/IHN0cmljdFJlZ2V4IDogcmVnZXg7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0UGFyc2VSZWdleEZvclRva2VuICh0b2tlbiwgY29uZmlnKSB7XG4gICAgaWYgKCFoYXNPd25Qcm9wKHJlZ2V4ZXMsIHRva2VuKSkge1xuICAgICAgICByZXR1cm4gbmV3IFJlZ0V4cCh1bmVzY2FwZUZvcm1hdCh0b2tlbikpO1xuICAgIH1cblxuICAgIHJldHVybiByZWdleGVzW3Rva2VuXShjb25maWcuX3N0cmljdCwgY29uZmlnLl9sb2NhbGUpO1xufVxuXG4vLyBDb2RlIGZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8zNTYxNDkzL2lzLXRoZXJlLWEtcmVnZXhwLWVzY2FwZS1mdW5jdGlvbi1pbi1qYXZhc2NyaXB0XG5mdW5jdGlvbiB1bmVzY2FwZUZvcm1hdChzKSB7XG4gICAgcmV0dXJuIHJlZ2V4RXNjYXBlKHMucmVwbGFjZSgnXFxcXCcsICcnKS5yZXBsYWNlKC9cXFxcKFxcWyl8XFxcXChcXF0pfFxcWyhbXlxcXVxcW10qKVxcXXxcXFxcKC4pL2csIGZ1bmN0aW9uIChtYXRjaGVkLCBwMSwgcDIsIHAzLCBwNCkge1xuICAgICAgICByZXR1cm4gcDEgfHwgcDIgfHwgcDMgfHwgcDQ7XG4gICAgfSkpO1xufVxuXG5mdW5jdGlvbiByZWdleEVzY2FwZShzKSB7XG4gICAgcmV0dXJuIHMucmVwbGFjZSgvWy1cXC9cXFxcXiQqKz8uKCl8W1xcXXt9XS9nLCAnXFxcXCQmJyk7XG59XG5cbnZhciB0b2tlbnMgPSB7fTtcblxuZnVuY3Rpb24gYWRkUGFyc2VUb2tlbiAodG9rZW4sIGNhbGxiYWNrKSB7XG4gICAgdmFyIGksIGZ1bmMgPSBjYWxsYmFjaztcbiAgICBpZiAodHlwZW9mIHRva2VuID09PSAnc3RyaW5nJykge1xuICAgICAgICB0b2tlbiA9IFt0b2tlbl07XG4gICAgfVxuICAgIGlmIChpc051bWJlcihjYWxsYmFjaykpIHtcbiAgICAgICAgZnVuYyA9IGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgICAgIGFycmF5W2NhbGxiYWNrXSA9IHRvSW50KGlucHV0KTtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgZm9yIChpID0gMDsgaSA8IHRva2VuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHRva2Vuc1t0b2tlbltpXV0gPSBmdW5jO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gYWRkV2Vla1BhcnNlVG9rZW4gKHRva2VuLCBjYWxsYmFjaykge1xuICAgIGFkZFBhcnNlVG9rZW4odG9rZW4sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZywgdG9rZW4pIHtcbiAgICAgICAgY29uZmlnLl93ID0gY29uZmlnLl93IHx8IHt9O1xuICAgICAgICBjYWxsYmFjayhpbnB1dCwgY29uZmlnLl93LCBjb25maWcsIHRva2VuKTtcbiAgICB9KTtcbn1cblxuZnVuY3Rpb24gYWRkVGltZVRvQXJyYXlGcm9tVG9rZW4odG9rZW4sIGlucHV0LCBjb25maWcpIHtcbiAgICBpZiAoaW5wdXQgIT0gbnVsbCAmJiBoYXNPd25Qcm9wKHRva2VucywgdG9rZW4pKSB7XG4gICAgICAgIHRva2Vuc1t0b2tlbl0oaW5wdXQsIGNvbmZpZy5fYSwgY29uZmlnLCB0b2tlbik7XG4gICAgfVxufVxuXG52YXIgWUVBUiA9IDA7XG52YXIgTU9OVEggPSAxO1xudmFyIERBVEUgPSAyO1xudmFyIEhPVVIgPSAzO1xudmFyIE1JTlVURSA9IDQ7XG52YXIgU0VDT05EID0gNTtcbnZhciBNSUxMSVNFQ09ORCA9IDY7XG52YXIgV0VFSyA9IDc7XG52YXIgV0VFS0RBWSA9IDg7XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ1knLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHkgPSB0aGlzLnllYXIoKTtcbiAgICByZXR1cm4geSA8PSA5OTk5ID8gJycgKyB5IDogJysnICsgeTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbigwLCBbJ1lZJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy55ZWFyKCkgJSAxMDA7XG59KTtcblxuYWRkRm9ybWF0VG9rZW4oMCwgWydZWVlZJywgICA0XSwgICAgICAgMCwgJ3llYXInKTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnWVlZWVknLCAgNV0sICAgICAgIDAsICd5ZWFyJyk7XG5hZGRGb3JtYXRUb2tlbigwLCBbJ1lZWVlZWScsIDYsIHRydWVdLCAwLCAneWVhcicpO1xuXG4vLyBBTElBU0VTXG5cbmFkZFVuaXRBbGlhcygneWVhcicsICd5Jyk7XG5cbi8vIFBSSU9SSVRJRVNcblxuYWRkVW5pdFByaW9yaXR5KCd5ZWFyJywgMSk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbignWScsICAgICAgbWF0Y2hTaWduZWQpO1xuYWRkUmVnZXhUb2tlbignWVknLCAgICAgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignWVlZWScsICAgbWF0Y2gxdG80LCBtYXRjaDQpO1xuYWRkUmVnZXhUb2tlbignWVlZWVknLCAgbWF0Y2gxdG82LCBtYXRjaDYpO1xuYWRkUmVnZXhUb2tlbignWVlZWVlZJywgbWF0Y2gxdG82LCBtYXRjaDYpO1xuXG5hZGRQYXJzZVRva2VuKFsnWVlZWVknLCAnWVlZWVlZJ10sIFlFQVIpO1xuYWRkUGFyc2VUb2tlbignWVlZWScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICBhcnJheVtZRUFSXSA9IGlucHV0Lmxlbmd0aCA9PT0gMiA/IGhvb2tzLnBhcnNlVHdvRGlnaXRZZWFyKGlucHV0KSA6IHRvSW50KGlucHV0KTtcbn0pO1xuYWRkUGFyc2VUb2tlbignWVknLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgYXJyYXlbWUVBUl0gPSBob29rcy5wYXJzZVR3b0RpZ2l0WWVhcihpbnB1dCk7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ1knLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgYXJyYXlbWUVBUl0gPSBwYXJzZUludChpbnB1dCwgMTApO1xufSk7XG5cbi8vIEhFTFBFUlNcblxuZnVuY3Rpb24gZGF5c0luWWVhcih5ZWFyKSB7XG4gICAgcmV0dXJuIGlzTGVhcFllYXIoeWVhcikgPyAzNjYgOiAzNjU7XG59XG5cbmZ1bmN0aW9uIGlzTGVhcFllYXIoeWVhcikge1xuICAgIHJldHVybiAoeWVhciAlIDQgPT09IDAgJiYgeWVhciAlIDEwMCAhPT0gMCkgfHwgeWVhciAlIDQwMCA9PT0gMDtcbn1cblxuLy8gSE9PS1NcblxuaG9va3MucGFyc2VUd29EaWdpdFllYXIgPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICByZXR1cm4gdG9JbnQoaW5wdXQpICsgKHRvSW50KGlucHV0KSA+IDY4ID8gMTkwMCA6IDIwMDApO1xufTtcblxuLy8gTU9NRU5UU1xuXG52YXIgZ2V0U2V0WWVhciA9IG1ha2VHZXRTZXQoJ0Z1bGxZZWFyJywgdHJ1ZSk7XG5cbmZ1bmN0aW9uIGdldElzTGVhcFllYXIgKCkge1xuICAgIHJldHVybiBpc0xlYXBZZWFyKHRoaXMueWVhcigpKTtcbn1cblxuZnVuY3Rpb24gbWFrZUdldFNldCAodW5pdCwga2VlcFRpbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICh2YWx1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgICBzZXQkMSh0aGlzLCB1bml0LCB2YWx1ZSk7XG4gICAgICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywga2VlcFRpbWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0KHRoaXMsIHVuaXQpO1xuICAgICAgICB9XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZ2V0IChtb20sIHVuaXQpIHtcbiAgICByZXR1cm4gbW9tLmlzVmFsaWQoKSA/XG4gICAgICAgIG1vbS5fZFsnZ2V0JyArIChtb20uX2lzVVRDID8gJ1VUQycgOiAnJykgKyB1bml0XSgpIDogTmFOO1xufVxuXG5mdW5jdGlvbiBzZXQkMSAobW9tLCB1bml0LCB2YWx1ZSkge1xuICAgIGlmIChtb20uaXNWYWxpZCgpICYmICFpc05hTih2YWx1ZSkpIHtcbiAgICAgICAgaWYgKHVuaXQgPT09ICdGdWxsWWVhcicgJiYgaXNMZWFwWWVhcihtb20ueWVhcigpKSAmJiBtb20ubW9udGgoKSA9PT0gMSAmJiBtb20uZGF0ZSgpID09PSAyOSkge1xuICAgICAgICAgICAgbW9tLl9kWydzZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArIHVuaXRdKHZhbHVlLCBtb20ubW9udGgoKSwgZGF5c0luTW9udGgodmFsdWUsIG1vbS5tb250aCgpKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBtb20uX2RbJ3NldCcgKyAobW9tLl9pc1VUQyA/ICdVVEMnIDogJycpICsgdW5pdF0odmFsdWUpO1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vLyBNT01FTlRTXG5cbmZ1bmN0aW9uIHN0cmluZ0dldCAodW5pdHMpIHtcbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXNbdW5pdHNdKCk7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xufVxuXG5cbmZ1bmN0aW9uIHN0cmluZ1NldCAodW5pdHMsIHZhbHVlKSB7XG4gICAgaWYgKHR5cGVvZiB1bml0cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgdW5pdHMgPSBub3JtYWxpemVPYmplY3RVbml0cyh1bml0cyk7XG4gICAgICAgIHZhciBwcmlvcml0aXplZCA9IGdldFByaW9yaXRpemVkVW5pdHModW5pdHMpO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByaW9yaXRpemVkLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0aGlzW3ByaW9yaXRpemVkW2ldLnVuaXRdKHVuaXRzW3ByaW9yaXRpemVkW2ldLnVuaXRdKTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW3VuaXRzXSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRoaXM7XG59XG5cbmZ1bmN0aW9uIG1vZChuLCB4KSB7XG4gICAgcmV0dXJuICgobiAlIHgpICsgeCkgJSB4O1xufVxuXG52YXIgaW5kZXhPZjtcblxuaWYgKEFycmF5LnByb3RvdHlwZS5pbmRleE9mKSB7XG4gICAgaW5kZXhPZiA9IEFycmF5LnByb3RvdHlwZS5pbmRleE9mO1xufSBlbHNlIHtcbiAgICBpbmRleE9mID0gZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgLy8gSSBrbm93XG4gICAgICAgIHZhciBpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgaWYgKHRoaXNbaV0gPT09IG8pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gLTE7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gZGF5c0luTW9udGgoeWVhciwgbW9udGgpIHtcbiAgICBpZiAoaXNOYU4oeWVhcikgfHwgaXNOYU4obW9udGgpKSB7XG4gICAgICAgIHJldHVybiBOYU47XG4gICAgfVxuICAgIHZhciBtb2RNb250aCA9IG1vZChtb250aCwgMTIpO1xuICAgIHllYXIgKz0gKG1vbnRoIC0gbW9kTW9udGgpIC8gMTI7XG4gICAgcmV0dXJuIG1vZE1vbnRoID09PSAxID8gKGlzTGVhcFllYXIoeWVhcikgPyAyOSA6IDI4KSA6ICgzMSAtIG1vZE1vbnRoICUgNyAlIDIpO1xufVxuXG4vLyBGT1JNQVRUSU5HXG5cbmFkZEZvcm1hdFRva2VuKCdNJywgWydNTScsIDJdLCAnTW8nLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMubW9udGgoKSArIDE7XG59KTtcblxuYWRkRm9ybWF0VG9rZW4oJ01NTScsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzU2hvcnQodGhpcywgZm9ybWF0KTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignTU1NTScsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzKHRoaXMsIGZvcm1hdCk7XG59KTtcblxuLy8gQUxJQVNFU1xuXG5hZGRVbml0QWxpYXMoJ21vbnRoJywgJ00nKTtcblxuLy8gUFJJT1JJVFlcblxuYWRkVW5pdFByaW9yaXR5KCdtb250aCcsIDgpO1xuXG4vLyBQQVJTSU5HXG5cbmFkZFJlZ2V4VG9rZW4oJ00nLCAgICBtYXRjaDF0bzIpO1xuYWRkUmVnZXhUb2tlbignTU0nLCAgIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbmFkZFJlZ2V4VG9rZW4oJ01NTScsICBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgIHJldHVybiBsb2NhbGUubW9udGhzU2hvcnRSZWdleChpc1N0cmljdCk7XG59KTtcbmFkZFJlZ2V4VG9rZW4oJ01NTU0nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgIHJldHVybiBsb2NhbGUubW9udGhzUmVnZXgoaXNTdHJpY3QpO1xufSk7XG5cbmFkZFBhcnNlVG9rZW4oWydNJywgJ01NJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICBhcnJheVtNT05USF0gPSB0b0ludChpbnB1dCkgLSAxO1xufSk7XG5cbmFkZFBhcnNlVG9rZW4oWydNTU0nLCAnTU1NTSddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcsIHRva2VuKSB7XG4gICAgdmFyIG1vbnRoID0gY29uZmlnLl9sb2NhbGUubW9udGhzUGFyc2UoaW5wdXQsIHRva2VuLCBjb25maWcuX3N0cmljdCk7XG4gICAgLy8gaWYgd2UgZGlkbid0IGZpbmQgYSBtb250aCBuYW1lLCBtYXJrIHRoZSBkYXRlIGFzIGludmFsaWQuXG4gICAgaWYgKG1vbnRoICE9IG51bGwpIHtcbiAgICAgICAgYXJyYXlbTU9OVEhdID0gbW9udGg7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZE1vbnRoID0gaW5wdXQ7XG4gICAgfVxufSk7XG5cbi8vIExPQ0FMRVNcblxudmFyIE1PTlRIU19JTl9GT1JNQVQgPSAvRFtvRF0/KFxcW1teXFxbXFxdXSpcXF18XFxzKStNTU1NPy87XG52YXIgZGVmYXVsdExvY2FsZU1vbnRocyA9ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpO1xuZnVuY3Rpb24gbG9jYWxlTW9udGhzIChtLCBmb3JtYXQpIHtcbiAgICBpZiAoIW0pIHtcbiAgICAgICAgcmV0dXJuIGlzQXJyYXkodGhpcy5fbW9udGhzKSA/IHRoaXMuX21vbnRocyA6XG4gICAgICAgICAgICB0aGlzLl9tb250aHNbJ3N0YW5kYWxvbmUnXTtcbiAgICB9XG4gICAgcmV0dXJuIGlzQXJyYXkodGhpcy5fbW9udGhzKSA/IHRoaXMuX21vbnRoc1ttLm1vbnRoKCldIDpcbiAgICAgICAgdGhpcy5fbW9udGhzWyh0aGlzLl9tb250aHMuaXNGb3JtYXQgfHwgTU9OVEhTX0lOX0ZPUk1BVCkudGVzdChmb3JtYXQpID8gJ2Zvcm1hdCcgOiAnc3RhbmRhbG9uZSddW20ubW9udGgoKV07XG59XG5cbnZhciBkZWZhdWx0TG9jYWxlTW9udGhzU2hvcnQgPSAnSmFuX0ZlYl9NYXJfQXByX01heV9KdW5fSnVsX0F1Z19TZXBfT2N0X05vdl9EZWMnLnNwbGl0KCdfJyk7XG5mdW5jdGlvbiBsb2NhbGVNb250aHNTaG9ydCAobSwgZm9ybWF0KSB7XG4gICAgaWYgKCFtKSB7XG4gICAgICAgIHJldHVybiBpc0FycmF5KHRoaXMuX21vbnRoc1Nob3J0KSA/IHRoaXMuX21vbnRoc1Nob3J0IDpcbiAgICAgICAgICAgIHRoaXMuX21vbnRoc1Nob3J0WydzdGFuZGFsb25lJ107XG4gICAgfVxuICAgIHJldHVybiBpc0FycmF5KHRoaXMuX21vbnRoc1Nob3J0KSA/IHRoaXMuX21vbnRoc1Nob3J0W20ubW9udGgoKV0gOlxuICAgICAgICB0aGlzLl9tb250aHNTaG9ydFtNT05USFNfSU5fRk9STUFULnRlc3QoZm9ybWF0KSA/ICdmb3JtYXQnIDogJ3N0YW5kYWxvbmUnXVttLm1vbnRoKCldO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTdHJpY3RQYXJzZShtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgdmFyIGksIGlpLCBtb20sIGxsYyA9IG1vbnRoTmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgIGlmICghdGhpcy5fbW9udGhzUGFyc2UpIHtcbiAgICAgICAgLy8gdGhpcyBpcyBub3QgdXNlZFxuICAgICAgICB0aGlzLl9tb250aHNQYXJzZSA9IFtdO1xuICAgICAgICB0aGlzLl9sb25nTW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgdGhpcy5fc2hvcnRNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7ICsraSkge1xuICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCBpXSk7XG4gICAgICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlW2ldID0gdGhpcy5tb250aHNTaG9ydChtb20sICcnKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldID0gdGhpcy5tb250aHMobW9tLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdHJpY3QpIHtcbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ01NTScpIHtcbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0TW9udGhzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbG9uZ01vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChmb3JtYXQgPT09ICdNTU0nKSB7XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydE1vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX2xvbmdNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9sb25nTW9udGhzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxvY2FsZU1vbnRoc1BhcnNlIChtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgdmFyIGksIG1vbSwgcmVnZXg7XG5cbiAgICBpZiAodGhpcy5fbW9udGhzUGFyc2VFeGFjdCkge1xuICAgICAgICByZXR1cm4gaGFuZGxlU3RyaWN0UGFyc2UuY2FsbCh0aGlzLCBtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX21vbnRoc1BhcnNlKSB7XG4gICAgICAgIHRoaXMuX21vbnRoc1BhcnNlID0gW107XG4gICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlID0gW107XG4gICAgfVxuXG4gICAgLy8gVE9ETzogYWRkIHNvcnRpbmdcbiAgICAvLyBTb3J0aW5nIG1ha2VzIHN1cmUgaWYgb25lIG1vbnRoIChvciBhYmJyKSBpcyBhIHByZWZpeCBvZiBhbm90aGVyXG4gICAgLy8gc2VlIHNvcnRpbmcgaW4gY29tcHV0ZU1vbnRoc1BhcnNlXG4gICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgLy8gbWFrZSB0aGUgcmVnZXggaWYgd2UgZG9uJ3QgaGF2ZSBpdCBhbHJlYWR5XG4gICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgaV0pO1xuICAgICAgICBpZiAoc3RyaWN0ICYmICF0aGlzLl9sb25nTW9udGhzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZVtpXSA9IG5ldyBSZWdFeHAoJ14nICsgdGhpcy5tb250aHMobW9tLCAnJykucmVwbGFjZSgnLicsICcnKSArICckJywgJ2knKTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0TW9udGhzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKCdeJyArIHRoaXMubW9udGhzU2hvcnQobW9tLCAnJykucmVwbGFjZSgnLicsICcnKSArICckJywgJ2knKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXN0cmljdCAmJiAhdGhpcy5fbW9udGhzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgIHJlZ2V4ID0gJ14nICsgdGhpcy5tb250aHMobW9tLCAnJykgKyAnfF4nICsgdGhpcy5tb250aHNTaG9ydChtb20sICcnKTtcbiAgICAgICAgICAgIHRoaXMuX21vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChyZWdleC5yZXBsYWNlKCcuJywgJycpLCAnaScpO1xuICAgICAgICB9XG4gICAgICAgIC8vIHRlc3QgdGhlIHJlZ2V4XG4gICAgICAgIGlmIChzdHJpY3QgJiYgZm9ybWF0ID09PSAnTU1NTScgJiYgdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldLnRlc3QobW9udGhOYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH0gZWxzZSBpZiAoc3RyaWN0ICYmIGZvcm1hdCA9PT0gJ01NTScgJiYgdGhpcy5fc2hvcnRNb250aHNQYXJzZVtpXS50ZXN0KG1vbnRoTmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICB9IGVsc2UgaWYgKCFzdHJpY3QgJiYgdGhpcy5fbW9udGhzUGFyc2VbaV0udGVzdChtb250aE5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLy8gTU9NRU5UU1xuXG5mdW5jdGlvbiBzZXRNb250aCAobW9tLCB2YWx1ZSkge1xuICAgIHZhciBkYXlPZk1vbnRoO1xuXG4gICAgaWYgKCFtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgIC8vIE5vIG9wXG4gICAgICAgIHJldHVybiBtb207XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKC9eXFxkKyQvLnRlc3QodmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRvSW50KHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlID0gbW9tLmxvY2FsZURhdGEoKS5tb250aHNQYXJzZSh2YWx1ZSk7XG4gICAgICAgICAgICAvLyBUT0RPOiBBbm90aGVyIHNpbGVudCBmYWlsdXJlP1xuICAgICAgICAgICAgaWYgKCFpc051bWJlcih2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbW9tO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZGF5T2ZNb250aCA9IE1hdGgubWluKG1vbS5kYXRlKCksIGRheXNJbk1vbnRoKG1vbS55ZWFyKCksIHZhbHVlKSk7XG4gICAgbW9tLl9kWydzZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArICdNb250aCddKHZhbHVlLCBkYXlPZk1vbnRoKTtcbiAgICByZXR1cm4gbW9tO1xufVxuXG5mdW5jdGlvbiBnZXRTZXRNb250aCAodmFsdWUpIHtcbiAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICBzZXRNb250aCh0aGlzLCB2YWx1ZSk7XG4gICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGdldCh0aGlzLCAnTW9udGgnKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGdldERheXNJbk1vbnRoICgpIHtcbiAgICByZXR1cm4gZGF5c0luTW9udGgodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSk7XG59XG5cbnZhciBkZWZhdWx0TW9udGhzU2hvcnRSZWdleCA9IG1hdGNoV29yZDtcbmZ1bmN0aW9uIG1vbnRoc1Nob3J0UmVnZXggKGlzU3RyaWN0KSB7XG4gICAgaWYgKHRoaXMuX21vbnRoc1BhcnNlRXhhY3QpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfbW9udGhzUmVnZXgnKSkge1xuICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNTaG9ydFJlZ2V4O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfbW9udGhzU2hvcnRSZWdleCcpKSB7XG4gICAgICAgICAgICB0aGlzLl9tb250aHNTaG9ydFJlZ2V4ID0gZGVmYXVsdE1vbnRoc1Nob3J0UmVnZXg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX21vbnRoc1Nob3J0U3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleCA6IHRoaXMuX21vbnRoc1Nob3J0UmVnZXg7XG4gICAgfVxufVxuXG52YXIgZGVmYXVsdE1vbnRoc1JlZ2V4ID0gbWF0Y2hXb3JkO1xuZnVuY3Rpb24gbW9udGhzUmVnZXggKGlzU3RyaWN0KSB7XG4gICAgaWYgKHRoaXMuX21vbnRoc1BhcnNlRXhhY3QpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfbW9udGhzUmVnZXgnKSkge1xuICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzUmVnZXg7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNSZWdleCcpKSB7XG4gICAgICAgICAgICB0aGlzLl9tb250aHNSZWdleCA9IGRlZmF1bHRNb250aHNSZWdleDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgdGhpcy5fbW9udGhzU3RyaWN0UmVnZXggOiB0aGlzLl9tb250aHNSZWdleDtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVNb250aHNQYXJzZSAoKSB7XG4gICAgZnVuY3Rpb24gY21wTGVuUmV2KGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGIubGVuZ3RoIC0gYS5sZW5ndGg7XG4gICAgfVxuXG4gICAgdmFyIHNob3J0UGllY2VzID0gW10sIGxvbmdQaWVjZXMgPSBbXSwgbWl4ZWRQaWVjZXMgPSBbXSxcbiAgICAgICAgaSwgbW9tO1xuICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIGldKTtcbiAgICAgICAgc2hvcnRQaWVjZXMucHVzaCh0aGlzLm1vbnRoc1Nob3J0KG1vbSwgJycpKTtcbiAgICAgICAgbG9uZ1BpZWNlcy5wdXNoKHRoaXMubW9udGhzKG1vbSwgJycpKTtcbiAgICAgICAgbWl4ZWRQaWVjZXMucHVzaCh0aGlzLm1vbnRocyhtb20sICcnKSk7XG4gICAgICAgIG1peGVkUGllY2VzLnB1c2godGhpcy5tb250aHNTaG9ydChtb20sICcnKSk7XG4gICAgfVxuICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgbW9udGggKG9yIGFiYnIpIGlzIGEgcHJlZml4IG9mIGFub3RoZXIgaXRcbiAgICAvLyB3aWxsIG1hdGNoIHRoZSBsb25nZXIgcGllY2UuXG4gICAgc2hvcnRQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgIGxvbmdQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgIG1peGVkUGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICBzaG9ydFBpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKHNob3J0UGllY2VzW2ldKTtcbiAgICAgICAgbG9uZ1BpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKGxvbmdQaWVjZXNbaV0pO1xuICAgIH1cbiAgICBmb3IgKGkgPSAwOyBpIDwgMjQ7IGkrKykge1xuICAgICAgICBtaXhlZFBpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKG1peGVkUGllY2VzW2ldKTtcbiAgICB9XG5cbiAgICB0aGlzLl9tb250aHNSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIG1peGVkUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICB0aGlzLl9tb250aHNTaG9ydFJlZ2V4ID0gdGhpcy5fbW9udGhzUmVnZXg7XG4gICAgdGhpcy5fbW9udGhzU3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBsb25nUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICB0aGlzLl9tb250aHNTaG9ydFN0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgc2hvcnRQaWVjZXMuam9pbignfCcpICsgJyknLCAnaScpO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVEYXRlICh5LCBtLCBkLCBoLCBNLCBzLCBtcykge1xuICAgIC8vIGNhbid0IGp1c3QgYXBwbHkoKSB0byBjcmVhdGUgYSBkYXRlOlxuICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcS8xODEzNDhcbiAgICB2YXIgZGF0ZSA9IG5ldyBEYXRlKHksIG0sIGQsIGgsIE0sIHMsIG1zKTtcblxuICAgIC8vIHRoZSBkYXRlIGNvbnN0cnVjdG9yIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgIGlmICh5IDwgMTAwICYmIHkgPj0gMCAmJiBpc0Zpbml0ZShkYXRlLmdldEZ1bGxZZWFyKCkpKSB7XG4gICAgICAgIGRhdGUuc2V0RnVsbFllYXIoeSk7XG4gICAgfVxuICAgIHJldHVybiBkYXRlO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVVVENEYXRlICh5KSB7XG4gICAgdmFyIGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQy5hcHBseShudWxsLCBhcmd1bWVudHMpKTtcblxuICAgIC8vIHRoZSBEYXRlLlVUQyBmdW5jdGlvbiByZW1hcHMgeWVhcnMgMC05OSB0byAxOTAwLTE5OTlcbiAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDAgJiYgaXNGaW5pdGUoZGF0ZS5nZXRVVENGdWxsWWVhcigpKSkge1xuICAgICAgICBkYXRlLnNldFVUQ0Z1bGxZZWFyKHkpO1xuICAgIH1cbiAgICByZXR1cm4gZGF0ZTtcbn1cblxuLy8gc3RhcnQtb2YtZmlyc3Qtd2VlayAtIHN0YXJ0LW9mLXllYXJcbmZ1bmN0aW9uIGZpcnN0V2Vla09mZnNldCh5ZWFyLCBkb3csIGRveSkge1xuICAgIHZhciAvLyBmaXJzdC13ZWVrIGRheSAtLSB3aGljaCBqYW51YXJ5IGlzIGFsd2F5cyBpbiB0aGUgZmlyc3Qgd2VlayAoNCBmb3IgaXNvLCAxIGZvciBvdGhlcilcbiAgICAgICAgZndkID0gNyArIGRvdyAtIGRveSxcbiAgICAgICAgLy8gZmlyc3Qtd2VlayBkYXkgbG9jYWwgd2Vla2RheSAtLSB3aGljaCBsb2NhbCB3ZWVrZGF5IGlzIGZ3ZFxuICAgICAgICBmd2RsdyA9ICg3ICsgY3JlYXRlVVRDRGF0ZSh5ZWFyLCAwLCBmd2QpLmdldFVUQ0RheSgpIC0gZG93KSAlIDc7XG5cbiAgICByZXR1cm4gLWZ3ZGx3ICsgZndkIC0gMTtcbn1cblxuLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPX3dlZWtfZGF0ZSNDYWxjdWxhdGluZ19hX2RhdGVfZ2l2ZW5fdGhlX3llYXIuMkNfd2Vla19udW1iZXJfYW5kX3dlZWtkYXlcbmZ1bmN0aW9uIGRheU9mWWVhckZyb21XZWVrcyh5ZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgIHZhciBsb2NhbFdlZWtkYXkgPSAoNyArIHdlZWtkYXkgLSBkb3cpICUgNyxcbiAgICAgICAgd2Vla09mZnNldCA9IGZpcnN0V2Vla09mZnNldCh5ZWFyLCBkb3csIGRveSksXG4gICAgICAgIGRheU9mWWVhciA9IDEgKyA3ICogKHdlZWsgLSAxKSArIGxvY2FsV2Vla2RheSArIHdlZWtPZmZzZXQsXG4gICAgICAgIHJlc1llYXIsIHJlc0RheU9mWWVhcjtcblxuICAgIGlmIChkYXlPZlllYXIgPD0gMCkge1xuICAgICAgICByZXNZZWFyID0geWVhciAtIDE7XG4gICAgICAgIHJlc0RheU9mWWVhciA9IGRheXNJblllYXIocmVzWWVhcikgKyBkYXlPZlllYXI7XG4gICAgfSBlbHNlIGlmIChkYXlPZlllYXIgPiBkYXlzSW5ZZWFyKHllYXIpKSB7XG4gICAgICAgIHJlc1llYXIgPSB5ZWFyICsgMTtcbiAgICAgICAgcmVzRGF5T2ZZZWFyID0gZGF5T2ZZZWFyIC0gZGF5c0luWWVhcih5ZWFyKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXNZZWFyID0geWVhcjtcbiAgICAgICAgcmVzRGF5T2ZZZWFyID0gZGF5T2ZZZWFyO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHllYXI6IHJlc1llYXIsXG4gICAgICAgIGRheU9mWWVhcjogcmVzRGF5T2ZZZWFyXG4gICAgfTtcbn1cblxuZnVuY3Rpb24gd2Vla09mWWVhcihtb20sIGRvdywgZG95KSB7XG4gICAgdmFyIHdlZWtPZmZzZXQgPSBmaXJzdFdlZWtPZmZzZXQobW9tLnllYXIoKSwgZG93LCBkb3kpLFxuICAgICAgICB3ZWVrID0gTWF0aC5mbG9vcigobW9tLmRheU9mWWVhcigpIC0gd2Vla09mZnNldCAtIDEpIC8gNykgKyAxLFxuICAgICAgICByZXNXZWVrLCByZXNZZWFyO1xuXG4gICAgaWYgKHdlZWsgPCAxKSB7XG4gICAgICAgIHJlc1llYXIgPSBtb20ueWVhcigpIC0gMTtcbiAgICAgICAgcmVzV2VlayA9IHdlZWsgKyB3ZWVrc0luWWVhcihyZXNZZWFyLCBkb3csIGRveSk7XG4gICAgfSBlbHNlIGlmICh3ZWVrID4gd2Vla3NJblllYXIobW9tLnllYXIoKSwgZG93LCBkb3kpKSB7XG4gICAgICAgIHJlc1dlZWsgPSB3ZWVrIC0gd2Vla3NJblllYXIobW9tLnllYXIoKSwgZG93LCBkb3kpO1xuICAgICAgICByZXNZZWFyID0gbW9tLnllYXIoKSArIDE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmVzWWVhciA9IG1vbS55ZWFyKCk7XG4gICAgICAgIHJlc1dlZWsgPSB3ZWVrO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICAgIHdlZWs6IHJlc1dlZWssXG4gICAgICAgIHllYXI6IHJlc1llYXJcbiAgICB9O1xufVxuXG5mdW5jdGlvbiB3ZWVrc0luWWVhcih5ZWFyLCBkb3csIGRveSkge1xuICAgIHZhciB3ZWVrT2Zmc2V0ID0gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSxcbiAgICAgICAgd2Vla09mZnNldE5leHQgPSBmaXJzdFdlZWtPZmZzZXQoeWVhciArIDEsIGRvdywgZG95KTtcbiAgICByZXR1cm4gKGRheXNJblllYXIoeWVhcikgLSB3ZWVrT2Zmc2V0ICsgd2Vla09mZnNldE5leHQpIC8gNztcbn1cblxuLy8gRk9STUFUVElOR1xuXG5hZGRGb3JtYXRUb2tlbigndycsIFsnd3cnLCAyXSwgJ3dvJywgJ3dlZWsnKTtcbmFkZEZvcm1hdFRva2VuKCdXJywgWydXVycsIDJdLCAnV28nLCAnaXNvV2VlaycpO1xuXG4vLyBBTElBU0VTXG5cbmFkZFVuaXRBbGlhcygnd2VlaycsICd3Jyk7XG5hZGRVbml0QWxpYXMoJ2lzb1dlZWsnLCAnVycpO1xuXG4vLyBQUklPUklUSUVTXG5cbmFkZFVuaXRQcmlvcml0eSgnd2VlaycsIDUpO1xuYWRkVW5pdFByaW9yaXR5KCdpc29XZWVrJywgNSk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbigndycsICBtYXRjaDF0bzIpO1xuYWRkUmVnZXhUb2tlbignd3cnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG5hZGRSZWdleFRva2VuKCdXJywgIG1hdGNoMXRvMik7XG5hZGRSZWdleFRva2VuKCdXVycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcblxuYWRkV2Vla1BhcnNlVG9rZW4oWyd3JywgJ3d3JywgJ1cnLCAnV1cnXSwgZnVuY3Rpb24gKGlucHV0LCB3ZWVrLCBjb25maWcsIHRva2VuKSB7XG4gICAgd2Vla1t0b2tlbi5zdWJzdHIoMCwgMSldID0gdG9JbnQoaW5wdXQpO1xufSk7XG5cbi8vIEhFTFBFUlNcblxuLy8gTE9DQUxFU1xuXG5mdW5jdGlvbiBsb2NhbGVXZWVrIChtb20pIHtcbiAgICByZXR1cm4gd2Vla09mWWVhcihtb20sIHRoaXMuX3dlZWsuZG93LCB0aGlzLl93ZWVrLmRveSkud2Vlaztcbn1cblxudmFyIGRlZmF1bHRMb2NhbGVXZWVrID0ge1xuICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbn07XG5cbmZ1bmN0aW9uIGxvY2FsZUZpcnN0RGF5T2ZXZWVrICgpIHtcbiAgICByZXR1cm4gdGhpcy5fd2Vlay5kb3c7XG59XG5cbmZ1bmN0aW9uIGxvY2FsZUZpcnN0RGF5T2ZZZWFyICgpIHtcbiAgICByZXR1cm4gdGhpcy5fd2Vlay5kb3k7XG59XG5cbi8vIE1PTUVOVFNcblxuZnVuY3Rpb24gZ2V0U2V0V2VlayAoaW5wdXQpIHtcbiAgICB2YXIgd2VlayA9IHRoaXMubG9jYWxlRGF0YSgpLndlZWsodGhpcyk7XG4gICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB3ZWVrIDogdGhpcy5hZGQoKGlucHV0IC0gd2VlaykgKiA3LCAnZCcpO1xufVxuXG5mdW5jdGlvbiBnZXRTZXRJU09XZWVrIChpbnB1dCkge1xuICAgIHZhciB3ZWVrID0gd2Vla09mWWVhcih0aGlzLCAxLCA0KS53ZWVrO1xuICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2VlayA6IHRoaXMuYWRkKChpbnB1dCAtIHdlZWspICogNywgJ2QnKTtcbn1cblxuLy8gRk9STUFUVElOR1xuXG5hZGRGb3JtYXRUb2tlbignZCcsIDAsICdkbycsICdkYXknKTtcblxuYWRkRm9ybWF0VG9rZW4oJ2RkJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS53ZWVrZGF5c01pbih0aGlzLCBmb3JtYXQpO1xufSk7XG5cbmFkZEZvcm1hdFRva2VuKCdkZGQnLCAwLCAwLCBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLndlZWtkYXlzU2hvcnQodGhpcywgZm9ybWF0KTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignZGRkZCcsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkud2Vla2RheXModGhpcywgZm9ybWF0KTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignZScsIDAsIDAsICd3ZWVrZGF5Jyk7XG5hZGRGb3JtYXRUb2tlbignRScsIDAsIDAsICdpc29XZWVrZGF5Jyk7XG5cbi8vIEFMSUFTRVNcblxuYWRkVW5pdEFsaWFzKCdkYXknLCAnZCcpO1xuYWRkVW5pdEFsaWFzKCd3ZWVrZGF5JywgJ2UnKTtcbmFkZFVuaXRBbGlhcygnaXNvV2Vla2RheScsICdFJyk7XG5cbi8vIFBSSU9SSVRZXG5hZGRVbml0UHJpb3JpdHkoJ2RheScsIDExKTtcbmFkZFVuaXRQcmlvcml0eSgnd2Vla2RheScsIDExKTtcbmFkZFVuaXRQcmlvcml0eSgnaXNvV2Vla2RheScsIDExKTtcblxuLy8gUEFSU0lOR1xuXG5hZGRSZWdleFRva2VuKCdkJywgICAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ2UnLCAgICBtYXRjaDF0bzIpO1xuYWRkUmVnZXhUb2tlbignRScsICAgIG1hdGNoMXRvMik7XG5hZGRSZWdleFRva2VuKCdkZCcsICAgZnVuY3Rpb24gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICByZXR1cm4gbG9jYWxlLndlZWtkYXlzTWluUmVnZXgoaXNTdHJpY3QpO1xufSk7XG5hZGRSZWdleFRva2VuKCdkZGQnLCAgIGZ1bmN0aW9uIChpc1N0cmljdCwgbG9jYWxlKSB7XG4gICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c1Nob3J0UmVnZXgoaXNTdHJpY3QpO1xufSk7XG5hZGRSZWdleFRva2VuKCdkZGRkJywgICBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgIHJldHVybiBsb2NhbGUud2Vla2RheXNSZWdleChpc1N0cmljdCk7XG59KTtcblxuYWRkV2Vla1BhcnNlVG9rZW4oWydkZCcsICdkZGQnLCAnZGRkZCddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICB2YXIgd2Vla2RheSA9IGNvbmZpZy5fbG9jYWxlLndlZWtkYXlzUGFyc2UoaW5wdXQsIHRva2VuLCBjb25maWcuX3N0cmljdCk7XG4gICAgLy8gaWYgd2UgZGlkbid0IGdldCBhIHdlZWtkYXkgbmFtZSwgbWFyayB0aGUgZGF0ZSBhcyBpbnZhbGlkXG4gICAgaWYgKHdlZWtkYXkgIT0gbnVsbCkge1xuICAgICAgICB3ZWVrLmQgPSB3ZWVrZGF5O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmludmFsaWRXZWVrZGF5ID0gaW5wdXQ7XG4gICAgfVxufSk7XG5cbmFkZFdlZWtQYXJzZVRva2VuKFsnZCcsICdlJywgJ0UnXSwgZnVuY3Rpb24gKGlucHV0LCB3ZWVrLCBjb25maWcsIHRva2VuKSB7XG4gICAgd2Vla1t0b2tlbl0gPSB0b0ludChpbnB1dCk7XG59KTtcblxuLy8gSEVMUEVSU1xuXG5mdW5jdGlvbiBwYXJzZVdlZWtkYXkoaW5wdXQsIGxvY2FsZSkge1xuICAgIGlmICh0eXBlb2YgaW5wdXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG5cbiAgICBpZiAoIWlzTmFOKGlucHV0KSkge1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQoaW5wdXQsIDEwKTtcbiAgICB9XG5cbiAgICBpbnB1dCA9IGxvY2FsZS53ZWVrZGF5c1BhcnNlKGlucHV0KTtcbiAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gaW5wdXQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmZ1bmN0aW9uIHBhcnNlSXNvV2Vla2RheShpbnB1dCwgbG9jYWxlKSB7XG4gICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c1BhcnNlKGlucHV0KSAlIDcgfHwgNztcbiAgICB9XG4gICAgcmV0dXJuIGlzTmFOKGlucHV0KSA/IG51bGwgOiBpbnB1dDtcbn1cblxuLy8gTE9DQUxFU1xuXG52YXIgZGVmYXVsdExvY2FsZVdlZWtkYXlzID0gJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpO1xuZnVuY3Rpb24gbG9jYWxlV2Vla2RheXMgKG0sIGZvcm1hdCkge1xuICAgIGlmICghbSkge1xuICAgICAgICByZXR1cm4gaXNBcnJheSh0aGlzLl93ZWVrZGF5cykgPyB0aGlzLl93ZWVrZGF5cyA6XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1snc3RhbmRhbG9uZSddO1xuICAgIH1cbiAgICByZXR1cm4gaXNBcnJheSh0aGlzLl93ZWVrZGF5cykgPyB0aGlzLl93ZWVrZGF5c1ttLmRheSgpXSA6XG4gICAgICAgIHRoaXMuX3dlZWtkYXlzW3RoaXMuX3dlZWtkYXlzLmlzRm9ybWF0LnRlc3QoZm9ybWF0KSA/ICdmb3JtYXQnIDogJ3N0YW5kYWxvbmUnXVttLmRheSgpXTtcbn1cblxudmFyIGRlZmF1bHRMb2NhbGVXZWVrZGF5c1Nob3J0ID0gJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKTtcbmZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzU2hvcnQgKG0pIHtcbiAgICByZXR1cm4gKG0pID8gdGhpcy5fd2Vla2RheXNTaG9ydFttLmRheSgpXSA6IHRoaXMuX3dlZWtkYXlzU2hvcnQ7XG59XG5cbnZhciBkZWZhdWx0TG9jYWxlV2Vla2RheXNNaW4gPSAnU3VfTW9fVHVfV2VfVGhfRnJfU2EnLnNwbGl0KCdfJyk7XG5mdW5jdGlvbiBsb2NhbGVXZWVrZGF5c01pbiAobSkge1xuICAgIHJldHVybiAobSkgPyB0aGlzLl93ZWVrZGF5c01pblttLmRheSgpXSA6IHRoaXMuX3dlZWtkYXlzTWluO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVTdHJpY3RQYXJzZSQxKHdlZWtkYXlOYW1lLCBmb3JtYXQsIHN0cmljdCkge1xuICAgIHZhciBpLCBpaSwgbW9tLCBsbGMgPSB3ZWVrZGF5TmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgIGlmICghdGhpcy5fd2Vla2RheXNQYXJzZSkge1xuICAgICAgICB0aGlzLl93ZWVrZGF5c1BhcnNlID0gW107XG4gICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSA9IFtdO1xuICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlID0gW107XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDc7ICsraSkge1xuICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCAxXSkuZGF5KGkpO1xuICAgICAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXNNaW4obW9tLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXNTaG9ydChtb20sICcnKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXMobW9tLCAnJykudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChzdHJpY3QpIHtcbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ2RkZGQnKSB7XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICdkZGQnKSB7XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbWluV2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZm9ybWF0ID09PSAnZGRkZCcpIHtcbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3dlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKGZvcm1hdCA9PT0gJ2RkZCcpIHtcbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbWluV2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59XG5cbmZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzUGFyc2UgKHdlZWtkYXlOYW1lLCBmb3JtYXQsIHN0cmljdCkge1xuICAgIHZhciBpLCBtb20sIHJlZ2V4O1xuXG4gICAgaWYgKHRoaXMuX3dlZWtkYXlzUGFyc2VFeGFjdCkge1xuICAgICAgICByZXR1cm4gaGFuZGxlU3RyaWN0UGFyc2UkMS5jYWxsKHRoaXMsIHdlZWtkYXlOYW1lLCBmb3JtYXQsIHN0cmljdCk7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLl93ZWVrZGF5c1BhcnNlKSB7XG4gICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZSA9IFtdO1xuICAgICAgICB0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICB9XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuXG4gICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgMV0pLmRheShpKTtcbiAgICAgICAgaWYgKHN0cmljdCAmJiAhdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgIHRoaXMuX2Z1bGxXZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzKG1vbSwgJycpLnJlcGxhY2UoJy4nLCAnXFwuPycpICsgJyQnLCAnaScpO1xuICAgICAgICAgICAgdGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzU2hvcnQobW9tLCAnJykucmVwbGFjZSgnLicsICdcXC4/JykgKyAnJCcsICdpJyk7XG4gICAgICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpLnJlcGxhY2UoJy4nLCAnXFwuPycpICsgJyQnLCAnaScpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5fd2Vla2RheXNQYXJzZVtpXSkge1xuICAgICAgICAgICAgcmVnZXggPSAnXicgKyB0aGlzLndlZWtkYXlzKG1vbSwgJycpICsgJ3xeJyArIHRoaXMud2Vla2RheXNTaG9ydChtb20sICcnKSArICd8XicgKyB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpO1xuICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZVtpXSA9IG5ldyBSZWdFeHAocmVnZXgucmVwbGFjZSgnLicsICcnKSwgJ2knKTtcbiAgICAgICAgfVxuICAgICAgICAvLyB0ZXN0IHRoZSByZWdleFxuICAgICAgICBpZiAoc3RyaWN0ICYmIGZvcm1hdCA9PT0gJ2RkZGQnICYmIHRoaXMuX2Z1bGxXZWVrZGF5c1BhcnNlW2ldLnRlc3Qod2Vla2RheU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfSBlbHNlIGlmIChzdHJpY3QgJiYgZm9ybWF0ID09PSAnZGRkJyAmJiB0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2VbaV0udGVzdCh3ZWVrZGF5TmFtZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICB9IGVsc2UgaWYgKHN0cmljdCAmJiBmb3JtYXQgPT09ICdkZCcgJiYgdGhpcy5fbWluV2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKSkge1xuICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgIH0gZWxzZSBpZiAoIXN0cmljdCAmJiB0aGlzLl93ZWVrZGF5c1BhcnNlW2ldLnRlc3Qod2Vla2RheU5hbWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLy8gTU9NRU5UU1xuXG5mdW5jdGlvbiBnZXRTZXREYXlPZldlZWsgKGlucHV0KSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gaW5wdXQgIT0gbnVsbCA/IHRoaXMgOiBOYU47XG4gICAgfVxuICAgIHZhciBkYXkgPSB0aGlzLl9pc1VUQyA/IHRoaXMuX2QuZ2V0VVRDRGF5KCkgOiB0aGlzLl9kLmdldERheSgpO1xuICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgIGlucHV0ID0gcGFyc2VXZWVrZGF5KGlucHV0LCB0aGlzLmxvY2FsZURhdGEoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLmFkZChpbnB1dCAtIGRheSwgJ2QnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gZGF5O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0U2V0TG9jYWxlRGF5T2ZXZWVrIChpbnB1dCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ICE9IG51bGwgPyB0aGlzIDogTmFOO1xuICAgIH1cbiAgICB2YXIgd2Vla2RheSA9ICh0aGlzLmRheSgpICsgNyAtIHRoaXMubG9jYWxlRGF0YSgpLl93ZWVrLmRvdykgJSA3O1xuICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2Vla2RheSA6IHRoaXMuYWRkKGlucHV0IC0gd2Vla2RheSwgJ2QnKTtcbn1cblxuZnVuY3Rpb24gZ2V0U2V0SVNPRGF5T2ZXZWVrIChpbnB1dCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ICE9IG51bGwgPyB0aGlzIDogTmFOO1xuICAgIH1cblxuICAgIC8vIGJlaGF2ZXMgdGhlIHNhbWUgYXMgbW9tZW50I2RheSBleGNlcHRcbiAgICAvLyBhcyBhIGdldHRlciwgcmV0dXJucyA3IGluc3RlYWQgb2YgMCAoMS03IHJhbmdlIGluc3RlYWQgb2YgMC02KVxuICAgIC8vIGFzIGEgc2V0dGVyLCBzdW5kYXkgc2hvdWxkIGJlbG9uZyB0byB0aGUgcHJldmlvdXMgd2Vlay5cblxuICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgIHZhciB3ZWVrZGF5ID0gcGFyc2VJc29XZWVrZGF5KGlucHV0LCB0aGlzLmxvY2FsZURhdGEoKSk7XG4gICAgICAgIHJldHVybiB0aGlzLmRheSh0aGlzLmRheSgpICUgNyA/IHdlZWtkYXkgOiB3ZWVrZGF5IC0gNyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF5KCkgfHwgNztcbiAgICB9XG59XG5cbnZhciBkZWZhdWx0V2Vla2RheXNSZWdleCA9IG1hdGNoV29yZDtcbmZ1bmN0aW9uIHdlZWtkYXlzUmVnZXggKGlzU3RyaWN0KSB7XG4gICAgaWYgKHRoaXMuX3dlZWtkYXlzUGFyc2VFeGFjdCkge1xuICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgIGNvbXB1dGVXZWVrZGF5c1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1JlZ2V4O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNSZWdleCcpKSB7XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1JlZ2V4ID0gZGVmYXVsdFdlZWtkYXlzUmVnZXg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU3RyaWN0UmVnZXggJiYgaXNTdHJpY3QgP1xuICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleCA6IHRoaXMuX3dlZWtkYXlzUmVnZXg7XG4gICAgfVxufVxuXG52YXIgZGVmYXVsdFdlZWtkYXlzU2hvcnRSZWdleCA9IG1hdGNoV29yZDtcbmZ1bmN0aW9uIHdlZWtkYXlzU2hvcnRSZWdleCAoaXNTdHJpY3QpIHtcbiAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzUmVnZXgnKSkge1xuICAgICAgICAgICAgY29tcHV0ZVdlZWtkYXlzUGFyc2UuY2FsbCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4O1xuICAgICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNTaG9ydFJlZ2V4JykpIHtcbiAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzU2hvcnRSZWdleCA9IGRlZmF1bHRXZWVrZGF5c1Nob3J0UmVnZXg7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU2hvcnRTdHJpY3RSZWdleCAmJiBpc1N0cmljdCA/XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggOiB0aGlzLl93ZWVrZGF5c1Nob3J0UmVnZXg7XG4gICAgfVxufVxuXG52YXIgZGVmYXVsdFdlZWtkYXlzTWluUmVnZXggPSBtYXRjaFdvcmQ7XG5mdW5jdGlvbiB3ZWVrZGF5c01pblJlZ2V4IChpc1N0cmljdCkge1xuICAgIGlmICh0aGlzLl93ZWVrZGF5c1BhcnNlRXhhY3QpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNSZWdleCcpKSB7XG4gICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc1N0cmljdCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXg7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNNaW5SZWdleDtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzTWluUmVnZXgnKSkge1xuICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNNaW5SZWdleCA9IGRlZmF1bHRXZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c01pblN0cmljdFJlZ2V4ICYmIGlzU3RyaWN0ID9cbiAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXggOiB0aGlzLl93ZWVrZGF5c01pblJlZ2V4O1xuICAgIH1cbn1cblxuXG5mdW5jdGlvbiBjb21wdXRlV2Vla2RheXNQYXJzZSAoKSB7XG4gICAgZnVuY3Rpb24gY21wTGVuUmV2KGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGIubGVuZ3RoIC0gYS5sZW5ndGg7XG4gICAgfVxuXG4gICAgdmFyIG1pblBpZWNlcyA9IFtdLCBzaG9ydFBpZWNlcyA9IFtdLCBsb25nUGllY2VzID0gW10sIG1peGVkUGllY2VzID0gW10sXG4gICAgICAgIGksIG1vbSwgbWlucCwgc2hvcnRwLCBsb25ncDtcbiAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIDFdKS5kYXkoaSk7XG4gICAgICAgIG1pbnAgPSB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpO1xuICAgICAgICBzaG9ydHAgPSB0aGlzLndlZWtkYXlzU2hvcnQobW9tLCAnJyk7XG4gICAgICAgIGxvbmdwID0gdGhpcy53ZWVrZGF5cyhtb20sICcnKTtcbiAgICAgICAgbWluUGllY2VzLnB1c2gobWlucCk7XG4gICAgICAgIHNob3J0UGllY2VzLnB1c2goc2hvcnRwKTtcbiAgICAgICAgbG9uZ1BpZWNlcy5wdXNoKGxvbmdwKTtcbiAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChtaW5wKTtcbiAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChzaG9ydHApO1xuICAgICAgICBtaXhlZFBpZWNlcy5wdXNoKGxvbmdwKTtcbiAgICB9XG4gICAgLy8gU29ydGluZyBtYWtlcyBzdXJlIGlmIG9uZSB3ZWVrZGF5IChvciBhYmJyKSBpcyBhIHByZWZpeCBvZiBhbm90aGVyIGl0XG4gICAgLy8gd2lsbCBtYXRjaCB0aGUgbG9uZ2VyIHBpZWNlLlxuICAgIG1pblBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgc2hvcnRQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgIGxvbmdQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgIG1peGVkUGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgIHNob3J0UGllY2VzW2ldID0gcmVnZXhFc2NhcGUoc2hvcnRQaWVjZXNbaV0pO1xuICAgICAgICBsb25nUGllY2VzW2ldID0gcmVnZXhFc2NhcGUobG9uZ1BpZWNlc1tpXSk7XG4gICAgICAgIG1peGVkUGllY2VzW2ldID0gcmVnZXhFc2NhcGUobWl4ZWRQaWVjZXNbaV0pO1xuICAgIH1cblxuICAgIHRoaXMuX3dlZWtkYXlzUmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBtaXhlZFBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4ID0gdGhpcy5fd2Vla2RheXNSZWdleDtcbiAgICB0aGlzLl93ZWVrZGF5c01pblJlZ2V4ID0gdGhpcy5fd2Vla2RheXNSZWdleDtcblxuICAgIHRoaXMuX3dlZWtkYXlzU3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBsb25nUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKCdeKCcgKyBzaG9ydFBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgdGhpcy5fd2Vla2RheXNNaW5TdHJpY3RSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIG1pblBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG59XG5cbi8vIEZPUk1BVFRJTkdcblxuZnVuY3Rpb24gaEZvcm1hdCgpIHtcbiAgICByZXR1cm4gdGhpcy5ob3VycygpICUgMTIgfHwgMTI7XG59XG5cbmZ1bmN0aW9uIGtGb3JtYXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaG91cnMoKSB8fCAyNDtcbn1cblxuYWRkRm9ybWF0VG9rZW4oJ0gnLCBbJ0hIJywgMl0sIDAsICdob3VyJyk7XG5hZGRGb3JtYXRUb2tlbignaCcsIFsnaGgnLCAyXSwgMCwgaEZvcm1hdCk7XG5hZGRGb3JtYXRUb2tlbignaycsIFsna2snLCAyXSwgMCwga0Zvcm1hdCk7XG5cbmFkZEZvcm1hdFRva2VuKCdobW0nLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICcnICsgaEZvcm1hdC5hcHBseSh0aGlzKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignaG1tc3MnLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICcnICsgaEZvcm1hdC5hcHBseSh0aGlzKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKSArXG4gICAgICAgIHplcm9GaWxsKHRoaXMuc2Vjb25kcygpLCAyKTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignSG1tJywgMCwgMCwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAnJyArIHRoaXMuaG91cnMoKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbignSG1tc3MnLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuICcnICsgdGhpcy5ob3VycygpICsgemVyb0ZpbGwodGhpcy5taW51dGVzKCksIDIpICtcbiAgICAgICAgemVyb0ZpbGwodGhpcy5zZWNvbmRzKCksIDIpO1xufSk7XG5cbmZ1bmN0aW9uIG1lcmlkaWVtICh0b2tlbiwgbG93ZXJjYXNlKSB7XG4gICAgYWRkRm9ybWF0VG9rZW4odG9rZW4sIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLm1lcmlkaWVtKHRoaXMuaG91cnMoKSwgdGhpcy5taW51dGVzKCksIGxvd2VyY2FzZSk7XG4gICAgfSk7XG59XG5cbm1lcmlkaWVtKCdhJywgdHJ1ZSk7XG5tZXJpZGllbSgnQScsIGZhbHNlKTtcblxuLy8gQUxJQVNFU1xuXG5hZGRVbml0QWxpYXMoJ2hvdXInLCAnaCcpO1xuXG4vLyBQUklPUklUWVxuYWRkVW5pdFByaW9yaXR5KCdob3VyJywgMTMpO1xuXG4vLyBQQVJTSU5HXG5cbmZ1bmN0aW9uIG1hdGNoTWVyaWRpZW0gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICByZXR1cm4gbG9jYWxlLl9tZXJpZGllbVBhcnNlO1xufVxuXG5hZGRSZWdleFRva2VuKCdhJywgIG1hdGNoTWVyaWRpZW0pO1xuYWRkUmVnZXhUb2tlbignQScsICBtYXRjaE1lcmlkaWVtKTtcbmFkZFJlZ2V4VG9rZW4oJ0gnLCAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ2gnLCAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ2snLCAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ0hIJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignaGgnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG5hZGRSZWdleFRva2VuKCdraycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcblxuYWRkUmVnZXhUb2tlbignaG1tJywgbWF0Y2gzdG80KTtcbmFkZFJlZ2V4VG9rZW4oJ2htbXNzJywgbWF0Y2g1dG82KTtcbmFkZFJlZ2V4VG9rZW4oJ0htbScsIG1hdGNoM3RvNCk7XG5hZGRSZWdleFRva2VuKCdIbW1zcycsIG1hdGNoNXRvNik7XG5cbmFkZFBhcnNlVG9rZW4oWydIJywgJ0hIJ10sIEhPVVIpO1xuYWRkUGFyc2VUb2tlbihbJ2snLCAna2snXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgdmFyIGtJbnB1dCA9IHRvSW50KGlucHV0KTtcbiAgICBhcnJheVtIT1VSXSA9IGtJbnB1dCA9PT0gMjQgPyAwIDoga0lucHV0O1xufSk7XG5hZGRQYXJzZVRva2VuKFsnYScsICdBJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgIGNvbmZpZy5faXNQbSA9IGNvbmZpZy5fbG9jYWxlLmlzUE0oaW5wdXQpO1xuICAgIGNvbmZpZy5fbWVyaWRpZW0gPSBpbnB1dDtcbn0pO1xuYWRkUGFyc2VUb2tlbihbJ2gnLCAnaGgnXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgYXJyYXlbSE9VUl0gPSB0b0ludChpbnB1dCk7XG4gICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHRydWU7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ2htbScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgIHZhciBwb3MgPSBpbnB1dC5sZW5ndGggLSAyO1xuICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvcykpO1xuICAgIGFycmF5W01JTlVURV0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zKSk7XG4gICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHRydWU7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ2htbXNzJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgdmFyIHBvczEgPSBpbnB1dC5sZW5ndGggLSA0O1xuICAgIHZhciBwb3MyID0gaW5wdXQubGVuZ3RoIC0gMjtcbiAgICBhcnJheVtIT1VSXSA9IHRvSW50KGlucHV0LnN1YnN0cigwLCBwb3MxKSk7XG4gICAgYXJyYXlbTUlOVVRFXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MxLCAyKSk7XG4gICAgYXJyYXlbU0VDT05EXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MyKSk7XG4gICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHRydWU7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ0htbScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgIHZhciBwb3MgPSBpbnB1dC5sZW5ndGggLSAyO1xuICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvcykpO1xuICAgIGFycmF5W01JTlVURV0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zKSk7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ0htbXNzJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgdmFyIHBvczEgPSBpbnB1dC5sZW5ndGggLSA0O1xuICAgIHZhciBwb3MyID0gaW5wdXQubGVuZ3RoIC0gMjtcbiAgICBhcnJheVtIT1VSXSA9IHRvSW50KGlucHV0LnN1YnN0cigwLCBwb3MxKSk7XG4gICAgYXJyYXlbTUlOVVRFXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MxLCAyKSk7XG4gICAgYXJyYXlbU0VDT05EXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MyKSk7XG59KTtcblxuLy8gTE9DQUxFU1xuXG5mdW5jdGlvbiBsb2NhbGVJc1BNIChpbnB1dCkge1xuICAgIC8vIElFOCBRdWlya3MgTW9kZSAmIElFNyBTdGFuZGFyZHMgTW9kZSBkbyBub3QgYWxsb3cgYWNjZXNzaW5nIHN0cmluZ3MgbGlrZSBhcnJheXNcbiAgICAvLyBVc2luZyBjaGFyQXQgc2hvdWxkIGJlIG1vcmUgY29tcGF0aWJsZS5cbiAgICByZXR1cm4gKChpbnB1dCArICcnKS50b0xvd2VyQ2FzZSgpLmNoYXJBdCgwKSA9PT0gJ3AnKTtcbn1cblxudmFyIGRlZmF1bHRMb2NhbGVNZXJpZGllbVBhcnNlID0gL1thcF1cXC4/bT9cXC4/L2k7XG5mdW5jdGlvbiBsb2NhbGVNZXJpZGllbSAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdwbScgOiAnUE0nO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2FtJyA6ICdBTSc7XG4gICAgfVxufVxuXG5cbi8vIE1PTUVOVFNcblxuLy8gU2V0dGluZyB0aGUgaG91ciBzaG91bGQga2VlcCB0aGUgdGltZSwgYmVjYXVzZSB0aGUgdXNlciBleHBsaWNpdGx5XG4vLyBzcGVjaWZpZWQgd2hpY2ggaG91ciBoZSB3YW50cy4gU28gdHJ5aW5nIHRvIG1haW50YWluIHRoZSBzYW1lIGhvdXIgKGluXG4vLyBhIG5ldyB0aW1lem9uZSkgbWFrZXMgc2Vuc2UuIEFkZGluZy9zdWJ0cmFjdGluZyBob3VycyBkb2VzIG5vdCBmb2xsb3dcbi8vIHRoaXMgcnVsZS5cbnZhciBnZXRTZXRIb3VyID0gbWFrZUdldFNldCgnSG91cnMnLCB0cnVlKTtcblxuLy8gbW9udGhzXG4vLyB3ZWVrXG4vLyB3ZWVrZGF5c1xuLy8gbWVyaWRpZW1cbnZhciBiYXNlQ29uZmlnID0ge1xuICAgIGNhbGVuZGFyOiBkZWZhdWx0Q2FsZW5kYXIsXG4gICAgbG9uZ0RhdGVGb3JtYXQ6IGRlZmF1bHRMb25nRGF0ZUZvcm1hdCxcbiAgICBpbnZhbGlkRGF0ZTogZGVmYXVsdEludmFsaWREYXRlLFxuICAgIG9yZGluYWw6IGRlZmF1bHRPcmRpbmFsLFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IGRlZmF1bHREYXlPZk1vbnRoT3JkaW5hbFBhcnNlLFxuICAgIHJlbGF0aXZlVGltZTogZGVmYXVsdFJlbGF0aXZlVGltZSxcblxuICAgIG1vbnRoczogZGVmYXVsdExvY2FsZU1vbnRocyxcbiAgICBtb250aHNTaG9ydDogZGVmYXVsdExvY2FsZU1vbnRoc1Nob3J0LFxuXG4gICAgd2VlazogZGVmYXVsdExvY2FsZVdlZWssXG5cbiAgICB3ZWVrZGF5czogZGVmYXVsdExvY2FsZVdlZWtkYXlzLFxuICAgIHdlZWtkYXlzTWluOiBkZWZhdWx0TG9jYWxlV2Vla2RheXNNaW4sXG4gICAgd2Vla2RheXNTaG9ydDogZGVmYXVsdExvY2FsZVdlZWtkYXlzU2hvcnQsXG5cbiAgICBtZXJpZGllbVBhcnNlOiBkZWZhdWx0TG9jYWxlTWVyaWRpZW1QYXJzZVxufTtcblxuLy8gaW50ZXJuYWwgc3RvcmFnZSBmb3IgbG9jYWxlIGNvbmZpZyBmaWxlc1xudmFyIGxvY2FsZXMgPSB7fTtcbnZhciBsb2NhbGVGYW1pbGllcyA9IHt9O1xudmFyIGdsb2JhbExvY2FsZTtcblxuZnVuY3Rpb24gbm9ybWFsaXplTG9jYWxlKGtleSkge1xuICAgIHJldHVybiBrZXkgPyBrZXkudG9Mb3dlckNhc2UoKS5yZXBsYWNlKCdfJywgJy0nKSA6IGtleTtcbn1cblxuLy8gcGljayB0aGUgbG9jYWxlIGZyb20gdGhlIGFycmF5XG4vLyB0cnkgWydlbi1hdScsICdlbi1nYiddIGFzICdlbi1hdScsICdlbi1nYicsICdlbicsIGFzIGluIG1vdmUgdGhyb3VnaCB0aGUgbGlzdCB0cnlpbmcgZWFjaFxuLy8gc3Vic3RyaW5nIGZyb20gbW9zdCBzcGVjaWZpYyB0byBsZWFzdCwgYnV0IG1vdmUgdG8gdGhlIG5leHQgYXJyYXkgaXRlbSBpZiBpdCdzIGEgbW9yZSBzcGVjaWZpYyB2YXJpYW50IHRoYW4gdGhlIGN1cnJlbnQgcm9vdFxuZnVuY3Rpb24gY2hvb3NlTG9jYWxlKG5hbWVzKSB7XG4gICAgdmFyIGkgPSAwLCBqLCBuZXh0LCBsb2NhbGUsIHNwbGl0O1xuXG4gICAgd2hpbGUgKGkgPCBuYW1lcy5sZW5ndGgpIHtcbiAgICAgICAgc3BsaXQgPSBub3JtYWxpemVMb2NhbGUobmFtZXNbaV0pLnNwbGl0KCctJyk7XG4gICAgICAgIGogPSBzcGxpdC5sZW5ndGg7XG4gICAgICAgIG5leHQgPSBub3JtYWxpemVMb2NhbGUobmFtZXNbaSArIDFdKTtcbiAgICAgICAgbmV4dCA9IG5leHQgPyBuZXh0LnNwbGl0KCctJykgOiBudWxsO1xuICAgICAgICB3aGlsZSAoaiA+IDApIHtcbiAgICAgICAgICAgIGxvY2FsZSA9IGxvYWRMb2NhbGUoc3BsaXQuc2xpY2UoMCwgaikuam9pbignLScpKTtcbiAgICAgICAgICAgIGlmIChsb2NhbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9jYWxlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5leHQgJiYgbmV4dC5sZW5ndGggPj0gaiAmJiBjb21wYXJlQXJyYXlzKHNwbGl0LCBuZXh0LCB0cnVlKSA+PSBqIC0gMSkge1xuICAgICAgICAgICAgICAgIC8vdGhlIG5leHQgYXJyYXkgaXRlbSBpcyBiZXR0ZXIgdGhhbiBhIHNoYWxsb3dlciBzdWJzdHJpbmcgb2YgdGhpcyBvbmVcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGotLTtcbiAgICAgICAgfVxuICAgICAgICBpKys7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuXG5mdW5jdGlvbiBsb2FkTG9jYWxlKG5hbWUpIHtcbiAgICB2YXIgb2xkTG9jYWxlID0gbnVsbDtcbiAgICAvLyBUT0RPOiBGaW5kIGEgYmV0dGVyIHdheSB0byByZWdpc3RlciBhbmQgbG9hZCBhbGwgdGhlIGxvY2FsZXMgaW4gTm9kZVxuICAgIGlmICghbG9jYWxlc1tuYW1lXSAmJiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcpICYmXG4gICAgICAgICAgICBtb2R1bGUgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIG9sZExvY2FsZSA9IGdsb2JhbExvY2FsZS5fYWJicjtcbiAgICAgICAgICAgIHZhciBhbGlhc2VkUmVxdWlyZSA9IHJlcXVpcmU7XG4gICAgICAgICAgICBhbGlhc2VkUmVxdWlyZSgnLi9sb2NhbGUvJyArIG5hbWUpO1xuICAgICAgICAgICAgZ2V0U2V0R2xvYmFsTG9jYWxlKG9sZExvY2FsZSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgfVxuICAgIHJldHVybiBsb2NhbGVzW25hbWVdO1xufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIHdpbGwgbG9hZCBsb2NhbGUgYW5kIHRoZW4gc2V0IHRoZSBnbG9iYWwgbG9jYWxlLiAgSWZcbi8vIG5vIGFyZ3VtZW50cyBhcmUgcGFzc2VkIGluLCBpdCB3aWxsIHNpbXBseSByZXR1cm4gdGhlIGN1cnJlbnQgZ2xvYmFsXG4vLyBsb2NhbGUga2V5LlxuZnVuY3Rpb24gZ2V0U2V0R2xvYmFsTG9jYWxlIChrZXksIHZhbHVlcykge1xuICAgIHZhciBkYXRhO1xuICAgIGlmIChrZXkpIHtcbiAgICAgICAgaWYgKGlzVW5kZWZpbmVkKHZhbHVlcykpIHtcbiAgICAgICAgICAgIGRhdGEgPSBnZXRMb2NhbGUoa2V5KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGRhdGEgPSBkZWZpbmVMb2NhbGUoa2V5LCB2YWx1ZXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgIC8vIG1vbWVudC5kdXJhdGlvbi5fbG9jYWxlID0gbW9tZW50Ll9sb2NhbGUgPSBkYXRhO1xuICAgICAgICAgICAgZ2xvYmFsTG9jYWxlID0gZGF0YTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBnbG9iYWxMb2NhbGUuX2FiYnI7XG59XG5cbmZ1bmN0aW9uIGRlZmluZUxvY2FsZSAobmFtZSwgY29uZmlnKSB7XG4gICAgaWYgKGNvbmZpZyAhPT0gbnVsbCkge1xuICAgICAgICB2YXIgcGFyZW50Q29uZmlnID0gYmFzZUNvbmZpZztcbiAgICAgICAgY29uZmlnLmFiYnIgPSBuYW1lO1xuICAgICAgICBpZiAobG9jYWxlc1tuYW1lXSAhPSBudWxsKSB7XG4gICAgICAgICAgICBkZXByZWNhdGVTaW1wbGUoJ2RlZmluZUxvY2FsZU92ZXJyaWRlJyxcbiAgICAgICAgICAgICAgICAgICAgJ3VzZSBtb21lbnQudXBkYXRlTG9jYWxlKGxvY2FsZU5hbWUsIGNvbmZpZykgdG8gY2hhbmdlICcgK1xuICAgICAgICAgICAgICAgICAgICAnYW4gZXhpc3RpbmcgbG9jYWxlLiBtb21lbnQuZGVmaW5lTG9jYWxlKGxvY2FsZU5hbWUsICcgK1xuICAgICAgICAgICAgICAgICAgICAnY29uZmlnKSBzaG91bGQgb25seSBiZSB1c2VkIGZvciBjcmVhdGluZyBhIG5ldyBsb2NhbGUgJyArXG4gICAgICAgICAgICAgICAgICAgICdTZWUgaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9kZWZpbmUtbG9jYWxlLyBmb3IgbW9yZSBpbmZvLicpO1xuICAgICAgICAgICAgcGFyZW50Q29uZmlnID0gbG9jYWxlc1tuYW1lXS5fY29uZmlnO1xuICAgICAgICB9IGVsc2UgaWYgKGNvbmZpZy5wYXJlbnRMb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKGxvY2FsZXNbY29uZmlnLnBhcmVudExvY2FsZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHBhcmVudENvbmZpZyA9IGxvY2FsZXNbY29uZmlnLnBhcmVudExvY2FsZV0uX2NvbmZpZztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCFsb2NhbGVGYW1pbGllc1tjb25maWcucGFyZW50TG9jYWxlXSkge1xuICAgICAgICAgICAgICAgICAgICBsb2NhbGVGYW1pbGllc1tjb25maWcucGFyZW50TG9jYWxlXSA9IFtdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsb2NhbGVGYW1pbGllc1tjb25maWcucGFyZW50TG9jYWxlXS5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnOiBjb25maWdcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBsb2NhbGVzW25hbWVdID0gbmV3IExvY2FsZShtZXJnZUNvbmZpZ3MocGFyZW50Q29uZmlnLCBjb25maWcpKTtcblxuICAgICAgICBpZiAobG9jYWxlRmFtaWxpZXNbbmFtZV0pIHtcbiAgICAgICAgICAgIGxvY2FsZUZhbWlsaWVzW25hbWVdLmZvckVhY2goZnVuY3Rpb24gKHgpIHtcbiAgICAgICAgICAgICAgICBkZWZpbmVMb2NhbGUoeC5uYW1lLCB4LmNvbmZpZyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGJhY2t3YXJkcyBjb21wYXQgZm9yIG5vdzogYWxzbyBzZXQgdGhlIGxvY2FsZVxuICAgICAgICAvLyBtYWtlIHN1cmUgd2Ugc2V0IHRoZSBsb2NhbGUgQUZURVIgYWxsIGNoaWxkIGxvY2FsZXMgaGF2ZSBiZWVuXG4gICAgICAgIC8vIGNyZWF0ZWQsIHNvIHdlIHdvbid0IGVuZCB1cCB3aXRoIHRoZSBjaGlsZCBsb2NhbGUgc2V0LlxuICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG5cblxuICAgICAgICByZXR1cm4gbG9jYWxlc1tuYW1lXTtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB1c2VmdWwgZm9yIHRlc3RpbmdcbiAgICAgICAgZGVsZXRlIGxvY2FsZXNbbmFtZV07XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdXBkYXRlTG9jYWxlKG5hbWUsIGNvbmZpZykge1xuICAgIGlmIChjb25maWcgIT0gbnVsbCkge1xuICAgICAgICB2YXIgbG9jYWxlLCB0bXBMb2NhbGUsIHBhcmVudENvbmZpZyA9IGJhc2VDb25maWc7XG4gICAgICAgIC8vIE1FUkdFXG4gICAgICAgIHRtcExvY2FsZSA9IGxvYWRMb2NhbGUobmFtZSk7XG4gICAgICAgIGlmICh0bXBMb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgcGFyZW50Q29uZmlnID0gdG1wTG9jYWxlLl9jb25maWc7XG4gICAgICAgIH1cbiAgICAgICAgY29uZmlnID0gbWVyZ2VDb25maWdzKHBhcmVudENvbmZpZywgY29uZmlnKTtcbiAgICAgICAgbG9jYWxlID0gbmV3IExvY2FsZShjb25maWcpO1xuICAgICAgICBsb2NhbGUucGFyZW50TG9jYWxlID0gbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgbG9jYWxlc1tuYW1lXSA9IGxvY2FsZTtcblxuICAgICAgICAvLyBiYWNrd2FyZHMgY29tcGF0IGZvciBub3c6IGFsc28gc2V0IHRoZSBsb2NhbGVcbiAgICAgICAgZ2V0U2V0R2xvYmFsTG9jYWxlKG5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHBhc3MgbnVsbCBmb3IgY29uZmlnIHRvIHVudXBkYXRlLCB1c2VmdWwgZm9yIHRlc3RzXG4gICAgICAgIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlmIChsb2NhbGVzW25hbWVdLnBhcmVudExvY2FsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxlc1tuYW1lXSA9IGxvY2FsZXNbbmFtZV0ucGFyZW50TG9jYWxlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBkZWxldGUgbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbG9jYWxlc1tuYW1lXTtcbn1cblxuLy8gcmV0dXJucyBsb2NhbGUgZGF0YVxuZnVuY3Rpb24gZ2V0TG9jYWxlIChrZXkpIHtcbiAgICB2YXIgbG9jYWxlO1xuXG4gICAgaWYgKGtleSAmJiBrZXkuX2xvY2FsZSAmJiBrZXkuX2xvY2FsZS5fYWJicikge1xuICAgICAgICBrZXkgPSBrZXkuX2xvY2FsZS5fYWJicjtcbiAgICB9XG5cbiAgICBpZiAoIWtleSkge1xuICAgICAgICByZXR1cm4gZ2xvYmFsTG9jYWxlO1xuICAgIH1cblxuICAgIGlmICghaXNBcnJheShrZXkpKSB7XG4gICAgICAgIC8vc2hvcnQtY2lyY3VpdCBldmVyeXRoaW5nIGVsc2VcbiAgICAgICAgbG9jYWxlID0gbG9hZExvY2FsZShrZXkpO1xuICAgICAgICBpZiAobG9jYWxlKSB7XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxlO1xuICAgICAgICB9XG4gICAgICAgIGtleSA9IFtrZXldO1xuICAgIH1cblxuICAgIHJldHVybiBjaG9vc2VMb2NhbGUoa2V5KTtcbn1cblxuZnVuY3Rpb24gbGlzdExvY2FsZXMoKSB7XG4gICAgcmV0dXJuIGtleXMobG9jYWxlcyk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrT3ZlcmZsb3cgKG0pIHtcbiAgICB2YXIgb3ZlcmZsb3c7XG4gICAgdmFyIGEgPSBtLl9hO1xuXG4gICAgaWYgKGEgJiYgZ2V0UGFyc2luZ0ZsYWdzKG0pLm92ZXJmbG93ID09PSAtMikge1xuICAgICAgICBvdmVyZmxvdyA9XG4gICAgICAgICAgICBhW01PTlRIXSAgICAgICA8IDAgfHwgYVtNT05USF0gICAgICAgPiAxMSAgPyBNT05USCA6XG4gICAgICAgICAgICBhW0RBVEVdICAgICAgICA8IDEgfHwgYVtEQVRFXSAgICAgICAgPiBkYXlzSW5Nb250aChhW1lFQVJdLCBhW01PTlRIXSkgPyBEQVRFIDpcbiAgICAgICAgICAgIGFbSE9VUl0gICAgICAgIDwgMCB8fCBhW0hPVVJdICAgICAgICA+IDI0IHx8IChhW0hPVVJdID09PSAyNCAmJiAoYVtNSU5VVEVdICE9PSAwIHx8IGFbU0VDT05EXSAhPT0gMCB8fCBhW01JTExJU0VDT05EXSAhPT0gMCkpID8gSE9VUiA6XG4gICAgICAgICAgICBhW01JTlVURV0gICAgICA8IDAgfHwgYVtNSU5VVEVdICAgICAgPiA1OSAgPyBNSU5VVEUgOlxuICAgICAgICAgICAgYVtTRUNPTkRdICAgICAgPCAwIHx8IGFbU0VDT05EXSAgICAgID4gNTkgID8gU0VDT05EIDpcbiAgICAgICAgICAgIGFbTUlMTElTRUNPTkRdIDwgMCB8fCBhW01JTExJU0VDT05EXSA+IDk5OSA/IE1JTExJU0VDT05EIDpcbiAgICAgICAgICAgIC0xO1xuXG4gICAgICAgIGlmIChnZXRQYXJzaW5nRmxhZ3MobSkuX292ZXJmbG93RGF5T2ZZZWFyICYmIChvdmVyZmxvdyA8IFlFQVIgfHwgb3ZlcmZsb3cgPiBEQVRFKSkge1xuICAgICAgICAgICAgb3ZlcmZsb3cgPSBEQVRFO1xuICAgICAgICB9XG4gICAgICAgIGlmIChnZXRQYXJzaW5nRmxhZ3MobSkuX292ZXJmbG93V2Vla3MgJiYgb3ZlcmZsb3cgPT09IC0xKSB7XG4gICAgICAgICAgICBvdmVyZmxvdyA9IFdFRUs7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGdldFBhcnNpbmdGbGFncyhtKS5fb3ZlcmZsb3dXZWVrZGF5ICYmIG92ZXJmbG93ID09PSAtMSkge1xuICAgICAgICAgICAgb3ZlcmZsb3cgPSBXRUVLREFZO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKG0pLm92ZXJmbG93ID0gb3ZlcmZsb3c7XG4gICAgfVxuXG4gICAgcmV0dXJuIG07XG59XG5cbi8vIFBpY2sgdGhlIGZpcnN0IGRlZmluZWQgb2YgdHdvIG9yIHRocmVlIGFyZ3VtZW50cy5cbmZ1bmN0aW9uIGRlZmF1bHRzKGEsIGIsIGMpIHtcbiAgICBpZiAoYSAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBhO1xuICAgIH1cbiAgICBpZiAoYiAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBiO1xuICAgIH1cbiAgICByZXR1cm4gYztcbn1cblxuZnVuY3Rpb24gY3VycmVudERhdGVBcnJheShjb25maWcpIHtcbiAgICAvLyBob29rcyBpcyBhY3R1YWxseSB0aGUgZXhwb3J0ZWQgbW9tZW50IG9iamVjdFxuICAgIHZhciBub3dWYWx1ZSA9IG5ldyBEYXRlKGhvb2tzLm5vdygpKTtcbiAgICBpZiAoY29uZmlnLl91c2VVVEMpIHtcbiAgICAgICAgcmV0dXJuIFtub3dWYWx1ZS5nZXRVVENGdWxsWWVhcigpLCBub3dWYWx1ZS5nZXRVVENNb250aCgpLCBub3dWYWx1ZS5nZXRVVENEYXRlKCldO1xuICAgIH1cbiAgICByZXR1cm4gW25vd1ZhbHVlLmdldEZ1bGxZZWFyKCksIG5vd1ZhbHVlLmdldE1vbnRoKCksIG5vd1ZhbHVlLmdldERhdGUoKV07XG59XG5cbi8vIGNvbnZlcnQgYW4gYXJyYXkgdG8gYSBkYXRlLlxuLy8gdGhlIGFycmF5IHNob3VsZCBtaXJyb3IgdGhlIHBhcmFtZXRlcnMgYmVsb3dcbi8vIG5vdGU6IGFsbCB2YWx1ZXMgcGFzdCB0aGUgeWVhciBhcmUgb3B0aW9uYWwgYW5kIHdpbGwgZGVmYXVsdCB0byB0aGUgbG93ZXN0IHBvc3NpYmxlIHZhbHVlLlxuLy8gW3llYXIsIG1vbnRoLCBkYXkgLCBob3VyLCBtaW51dGUsIHNlY29uZCwgbWlsbGlzZWNvbmRdXG5mdW5jdGlvbiBjb25maWdGcm9tQXJyYXkgKGNvbmZpZykge1xuICAgIHZhciBpLCBkYXRlLCBpbnB1dCA9IFtdLCBjdXJyZW50RGF0ZSwgZXhwZWN0ZWRXZWVrZGF5LCB5ZWFyVG9Vc2U7XG5cbiAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjdXJyZW50RGF0ZSA9IGN1cnJlbnREYXRlQXJyYXkoY29uZmlnKTtcblxuICAgIC8vY29tcHV0ZSBkYXkgb2YgdGhlIHllYXIgZnJvbSB3ZWVrcyBhbmQgd2Vla2RheXNcbiAgICBpZiAoY29uZmlnLl93ICYmIGNvbmZpZy5fYVtEQVRFXSA9PSBudWxsICYmIGNvbmZpZy5fYVtNT05USF0gPT0gbnVsbCkge1xuICAgICAgICBkYXlPZlllYXJGcm9tV2Vla0luZm8oY29uZmlnKTtcbiAgICB9XG5cbiAgICAvL2lmIHRoZSBkYXkgb2YgdGhlIHllYXIgaXMgc2V0LCBmaWd1cmUgb3V0IHdoYXQgaXQgaXNcbiAgICBpZiAoY29uZmlnLl9kYXlPZlllYXIgIT0gbnVsbCkge1xuICAgICAgICB5ZWFyVG9Vc2UgPSBkZWZhdWx0cyhjb25maWcuX2FbWUVBUl0sIGN1cnJlbnREYXRlW1lFQVJdKTtcblxuICAgICAgICBpZiAoY29uZmlnLl9kYXlPZlllYXIgPiBkYXlzSW5ZZWFyKHllYXJUb1VzZSkgfHwgY29uZmlnLl9kYXlPZlllYXIgPT09IDApIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLl9vdmVyZmxvd0RheU9mWWVhciA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBkYXRlID0gY3JlYXRlVVRDRGF0ZSh5ZWFyVG9Vc2UsIDAsIGNvbmZpZy5fZGF5T2ZZZWFyKTtcbiAgICAgICAgY29uZmlnLl9hW01PTlRIXSA9IGRhdGUuZ2V0VVRDTW9udGgoKTtcbiAgICAgICAgY29uZmlnLl9hW0RBVEVdID0gZGF0ZS5nZXRVVENEYXRlKCk7XG4gICAgfVxuXG4gICAgLy8gRGVmYXVsdCB0byBjdXJyZW50IGRhdGUuXG4gICAgLy8gKiBpZiBubyB5ZWFyLCBtb250aCwgZGF5IG9mIG1vbnRoIGFyZSBnaXZlbiwgZGVmYXVsdCB0byB0b2RheVxuICAgIC8vICogaWYgZGF5IG9mIG1vbnRoIGlzIGdpdmVuLCBkZWZhdWx0IG1vbnRoIGFuZCB5ZWFyXG4gICAgLy8gKiBpZiBtb250aCBpcyBnaXZlbiwgZGVmYXVsdCBvbmx5IHllYXJcbiAgICAvLyAqIGlmIHllYXIgaXMgZ2l2ZW4sIGRvbid0IGRlZmF1bHQgYW55dGhpbmdcbiAgICBmb3IgKGkgPSAwOyBpIDwgMyAmJiBjb25maWcuX2FbaV0gPT0gbnVsbDsgKytpKSB7XG4gICAgICAgIGNvbmZpZy5fYVtpXSA9IGlucHV0W2ldID0gY3VycmVudERhdGVbaV07XG4gICAgfVxuXG4gICAgLy8gWmVybyBvdXQgd2hhdGV2ZXIgd2FzIG5vdCBkZWZhdWx0ZWQsIGluY2x1ZGluZyB0aW1lXG4gICAgZm9yICg7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgY29uZmlnLl9hW2ldID0gaW5wdXRbaV0gPSAoY29uZmlnLl9hW2ldID09IG51bGwpID8gKGkgPT09IDIgPyAxIDogMCkgOiBjb25maWcuX2FbaV07XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgZm9yIDI0OjAwOjAwLjAwMFxuICAgIGlmIChjb25maWcuX2FbSE9VUl0gPT09IDI0ICYmXG4gICAgICAgICAgICBjb25maWcuX2FbTUlOVVRFXSA9PT0gMCAmJlxuICAgICAgICAgICAgY29uZmlnLl9hW1NFQ09ORF0gPT09IDAgJiZcbiAgICAgICAgICAgIGNvbmZpZy5fYVtNSUxMSVNFQ09ORF0gPT09IDApIHtcbiAgICAgICAgY29uZmlnLl9uZXh0RGF5ID0gdHJ1ZTtcbiAgICAgICAgY29uZmlnLl9hW0hPVVJdID0gMDtcbiAgICB9XG5cbiAgICBjb25maWcuX2QgPSAoY29uZmlnLl91c2VVVEMgPyBjcmVhdGVVVENEYXRlIDogY3JlYXRlRGF0ZSkuYXBwbHkobnVsbCwgaW5wdXQpO1xuICAgIGV4cGVjdGVkV2Vla2RheSA9IGNvbmZpZy5fdXNlVVRDID8gY29uZmlnLl9kLmdldFVUQ0RheSgpIDogY29uZmlnLl9kLmdldERheSgpO1xuXG4gICAgLy8gQXBwbHkgdGltZXpvbmUgb2Zmc2V0IGZyb20gaW5wdXQuIFRoZSBhY3R1YWwgdXRjT2Zmc2V0IGNhbiBiZSBjaGFuZ2VkXG4gICAgLy8gd2l0aCBwYXJzZVpvbmUuXG4gICAgaWYgKGNvbmZpZy5fdHptICE9IG51bGwpIHtcbiAgICAgICAgY29uZmlnLl9kLnNldFVUQ01pbnV0ZXMoY29uZmlnLl9kLmdldFVUQ01pbnV0ZXMoKSAtIGNvbmZpZy5fdHptKTtcbiAgICB9XG5cbiAgICBpZiAoY29uZmlnLl9uZXh0RGF5KSB7XG4gICAgICAgIGNvbmZpZy5fYVtIT1VSXSA9IDI0O1xuICAgIH1cblxuICAgIC8vIGNoZWNrIGZvciBtaXNtYXRjaGluZyBkYXkgb2Ygd2Vla1xuICAgIGlmIChjb25maWcuX3cgJiYgdHlwZW9mIGNvbmZpZy5fdy5kICE9PSAndW5kZWZpbmVkJyAmJiBjb25maWcuX3cuZCAhPT0gZXhwZWN0ZWRXZWVrZGF5KSB7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLndlZWtkYXlNaXNtYXRjaCA9IHRydWU7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkYXlPZlllYXJGcm9tV2Vla0luZm8oY29uZmlnKSB7XG4gICAgdmFyIHcsIHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSwgdGVtcCwgd2Vla2RheU92ZXJmbG93O1xuXG4gICAgdyA9IGNvbmZpZy5fdztcbiAgICBpZiAody5HRyAhPSBudWxsIHx8IHcuVyAhPSBudWxsIHx8IHcuRSAhPSBudWxsKSB7XG4gICAgICAgIGRvdyA9IDE7XG4gICAgICAgIGRveSA9IDQ7XG5cbiAgICAgICAgLy8gVE9ETzogV2UgbmVlZCB0byB0YWtlIHRoZSBjdXJyZW50IGlzb1dlZWtZZWFyLCBidXQgdGhhdCBkZXBlbmRzIG9uXG4gICAgICAgIC8vIGhvdyB3ZSBpbnRlcnByZXQgbm93IChsb2NhbCwgdXRjLCBmaXhlZCBvZmZzZXQpLiBTbyBjcmVhdGVcbiAgICAgICAgLy8gYSBub3cgdmVyc2lvbiBvZiBjdXJyZW50IGNvbmZpZyAodGFrZSBsb2NhbC91dGMvb2Zmc2V0IGZsYWdzLCBhbmRcbiAgICAgICAgLy8gY3JlYXRlIG5vdykuXG4gICAgICAgIHdlZWtZZWFyID0gZGVmYXVsdHMody5HRywgY29uZmlnLl9hW1lFQVJdLCB3ZWVrT2ZZZWFyKGNyZWF0ZUxvY2FsKCksIDEsIDQpLnllYXIpO1xuICAgICAgICB3ZWVrID0gZGVmYXVsdHMody5XLCAxKTtcbiAgICAgICAgd2Vla2RheSA9IGRlZmF1bHRzKHcuRSwgMSk7XG4gICAgICAgIGlmICh3ZWVrZGF5IDwgMSB8fCB3ZWVrZGF5ID4gNykge1xuICAgICAgICAgICAgd2Vla2RheU92ZXJmbG93ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAgIGRvdyA9IGNvbmZpZy5fbG9jYWxlLl93ZWVrLmRvdztcbiAgICAgICAgZG95ID0gY29uZmlnLl9sb2NhbGUuX3dlZWsuZG95O1xuXG4gICAgICAgIHZhciBjdXJXZWVrID0gd2Vla09mWWVhcihjcmVhdGVMb2NhbCgpLCBkb3csIGRveSk7XG5cbiAgICAgICAgd2Vla1llYXIgPSBkZWZhdWx0cyh3LmdnLCBjb25maWcuX2FbWUVBUl0sIGN1cldlZWsueWVhcik7XG5cbiAgICAgICAgLy8gRGVmYXVsdCB0byBjdXJyZW50IHdlZWsuXG4gICAgICAgIHdlZWsgPSBkZWZhdWx0cyh3LncsIGN1cldlZWsud2Vlayk7XG5cbiAgICAgICAgaWYgKHcuZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAvLyB3ZWVrZGF5IC0tIGxvdyBkYXkgbnVtYmVycyBhcmUgY29uc2lkZXJlZCBuZXh0IHdlZWtcbiAgICAgICAgICAgIHdlZWtkYXkgPSB3LmQ7XG4gICAgICAgICAgICBpZiAod2Vla2RheSA8IDAgfHwgd2Vla2RheSA+IDYpIHtcbiAgICAgICAgICAgICAgICB3ZWVrZGF5T3ZlcmZsb3cgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHcuZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAvLyBsb2NhbCB3ZWVrZGF5IC0tIGNvdW50aW5nIHN0YXJ0cyBmcm9tIGJlZ2luaW5nIG9mIHdlZWtcbiAgICAgICAgICAgIHdlZWtkYXkgPSB3LmUgKyBkb3c7XG4gICAgICAgICAgICBpZiAody5lIDwgMCB8fCB3LmUgPiA2KSB7XG4gICAgICAgICAgICAgICAgd2Vla2RheU92ZXJmbG93ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIGRlZmF1bHQgdG8gYmVnaW5pbmcgb2Ygd2Vla1xuICAgICAgICAgICAgd2Vla2RheSA9IGRvdztcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAod2VlayA8IDEgfHwgd2VlayA+IHdlZWtzSW5ZZWFyKHdlZWtZZWFyLCBkb3csIGRveSkpIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuX292ZXJmbG93V2Vla3MgPSB0cnVlO1xuICAgIH0gZWxzZSBpZiAod2Vla2RheU92ZXJmbG93ICE9IG51bGwpIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuX292ZXJmbG93V2Vla2RheSA9IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgdGVtcCA9IGRheU9mWWVhckZyb21XZWVrcyh3ZWVrWWVhciwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpO1xuICAgICAgICBjb25maWcuX2FbWUVBUl0gPSB0ZW1wLnllYXI7XG4gICAgICAgIGNvbmZpZy5fZGF5T2ZZZWFyID0gdGVtcC5kYXlPZlllYXI7XG4gICAgfVxufVxuXG4vLyBpc28gODYwMSByZWdleFxuLy8gMDAwMC0wMC0wMCAwMDAwLVcwMCBvciAwMDAwLVcwMC0wICsgVCArIDAwIG9yIDAwOjAwIG9yIDAwOjAwOjAwIG9yIDAwOjAwOjAwLjAwMCArICswMDowMCBvciArMDAwMCBvciArMDApXG52YXIgZXh0ZW5kZWRJc29SZWdleCA9IC9eXFxzKigoPzpbKy1dXFxkezZ9fFxcZHs0fSktKD86XFxkXFxkLVxcZFxcZHxXXFxkXFxkLVxcZHxXXFxkXFxkfFxcZFxcZFxcZHxcXGRcXGQpKSg/OihUfCApKFxcZFxcZCg/OjpcXGRcXGQoPzo6XFxkXFxkKD86Wy4sXVxcZCspPyk/KT8pKFtcXCtcXC1dXFxkXFxkKD86Oj9cXGRcXGQpP3xcXHMqWik/KT8kLztcbnZhciBiYXNpY0lzb1JlZ2V4ID0gL15cXHMqKCg/OlsrLV1cXGR7Nn18XFxkezR9KSg/OlxcZFxcZFxcZFxcZHxXXFxkXFxkXFxkfFdcXGRcXGR8XFxkXFxkXFxkfFxcZFxcZCkpKD86KFR8ICkoXFxkXFxkKD86XFxkXFxkKD86XFxkXFxkKD86Wy4sXVxcZCspPyk/KT8pKFtcXCtcXC1dXFxkXFxkKD86Oj9cXGRcXGQpP3xcXHMqWik/KT8kLztcblxudmFyIHR6UmVnZXggPSAvWnxbKy1dXFxkXFxkKD86Oj9cXGRcXGQpPy87XG5cbnZhciBpc29EYXRlcyA9IFtcbiAgICBbJ1lZWVlZWS1NTS1ERCcsIC9bKy1dXFxkezZ9LVxcZFxcZC1cXGRcXGQvXSxcbiAgICBbJ1lZWVktTU0tREQnLCAvXFxkezR9LVxcZFxcZC1cXGRcXGQvXSxcbiAgICBbJ0dHR0ctW1ddV1ctRScsIC9cXGR7NH0tV1xcZFxcZC1cXGQvXSxcbiAgICBbJ0dHR0ctW1ddV1cnLCAvXFxkezR9LVdcXGRcXGQvLCBmYWxzZV0sXG4gICAgWydZWVlZLURERCcsIC9cXGR7NH0tXFxkezN9L10sXG4gICAgWydZWVlZLU1NJywgL1xcZHs0fS1cXGRcXGQvLCBmYWxzZV0sXG4gICAgWydZWVlZWVlNTUREJywgL1srLV1cXGR7MTB9L10sXG4gICAgWydZWVlZTU1ERCcsIC9cXGR7OH0vXSxcbiAgICAvLyBZWVlZTU0gaXMgTk9UIGFsbG93ZWQgYnkgdGhlIHN0YW5kYXJkXG4gICAgWydHR0dHW1ddV1dFJywgL1xcZHs0fVdcXGR7M30vXSxcbiAgICBbJ0dHR0dbV11XVycsIC9cXGR7NH1XXFxkezJ9LywgZmFsc2VdLFxuICAgIFsnWVlZWURERCcsIC9cXGR7N30vXVxuXTtcblxuLy8gaXNvIHRpbWUgZm9ybWF0cyBhbmQgcmVnZXhlc1xudmFyIGlzb1RpbWVzID0gW1xuICAgIFsnSEg6bW06c3MuU1NTUycsIC9cXGRcXGQ6XFxkXFxkOlxcZFxcZFxcLlxcZCsvXSxcbiAgICBbJ0hIOm1tOnNzLFNTU1MnLCAvXFxkXFxkOlxcZFxcZDpcXGRcXGQsXFxkKy9dLFxuICAgIFsnSEg6bW06c3MnLCAvXFxkXFxkOlxcZFxcZDpcXGRcXGQvXSxcbiAgICBbJ0hIOm1tJywgL1xcZFxcZDpcXGRcXGQvXSxcbiAgICBbJ0hIbW1zcy5TU1NTJywgL1xcZFxcZFxcZFxcZFxcZFxcZFxcLlxcZCsvXSxcbiAgICBbJ0hIbW1zcyxTU1NTJywgL1xcZFxcZFxcZFxcZFxcZFxcZCxcXGQrL10sXG4gICAgWydISG1tc3MnLCAvXFxkXFxkXFxkXFxkXFxkXFxkL10sXG4gICAgWydISG1tJywgL1xcZFxcZFxcZFxcZC9dLFxuICAgIFsnSEgnLCAvXFxkXFxkL11cbl07XG5cbnZhciBhc3BOZXRKc29uUmVnZXggPSAvXlxcLz9EYXRlXFwoKFxcLT9cXGQrKS9pO1xuXG4vLyBkYXRlIGZyb20gaXNvIGZvcm1hdFxuZnVuY3Rpb24gY29uZmlnRnJvbUlTTyhjb25maWcpIHtcbiAgICB2YXIgaSwgbCxcbiAgICAgICAgc3RyaW5nID0gY29uZmlnLl9pLFxuICAgICAgICBtYXRjaCA9IGV4dGVuZGVkSXNvUmVnZXguZXhlYyhzdHJpbmcpIHx8IGJhc2ljSXNvUmVnZXguZXhlYyhzdHJpbmcpLFxuICAgICAgICBhbGxvd1RpbWUsIGRhdGVGb3JtYXQsIHRpbWVGb3JtYXQsIHR6Rm9ybWF0O1xuXG4gICAgaWYgKG1hdGNoKSB7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmlzbyA9IHRydWU7XG5cbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGlzb0RhdGVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgaWYgKGlzb0RhdGVzW2ldWzFdLmV4ZWMobWF0Y2hbMV0pKSB7XG4gICAgICAgICAgICAgICAgZGF0ZUZvcm1hdCA9IGlzb0RhdGVzW2ldWzBdO1xuICAgICAgICAgICAgICAgIGFsbG93VGltZSA9IGlzb0RhdGVzW2ldWzJdICE9PSBmYWxzZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZGF0ZUZvcm1hdCA9PSBudWxsKSB7XG4gICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWF0Y2hbM10pIHtcbiAgICAgICAgICAgIGZvciAoaSA9IDAsIGwgPSBpc29UaW1lcy5sZW5ndGg7IGkgPCBsOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNvVGltZXNbaV1bMV0uZXhlYyhtYXRjaFszXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gbWF0Y2hbMl0gc2hvdWxkIGJlICdUJyBvciBzcGFjZVxuICAgICAgICAgICAgICAgICAgICB0aW1lRm9ybWF0ID0gKG1hdGNoWzJdIHx8ICcgJykgKyBpc29UaW1lc1tpXVswXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRpbWVGb3JtYXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWFsbG93VGltZSAmJiB0aW1lRm9ybWF0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtYXRjaFs0XSkge1xuICAgICAgICAgICAgaWYgKHR6UmVnZXguZXhlYyhtYXRjaFs0XSkpIHtcbiAgICAgICAgICAgICAgICB0ekZvcm1hdCA9ICdaJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbmZpZy5fZiA9IGRhdGVGb3JtYXQgKyAodGltZUZvcm1hdCB8fCAnJykgKyAodHpGb3JtYXQgfHwgJycpO1xuICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgfVxufVxuXG4vLyBSRkMgMjgyMiByZWdleDogRm9yIGRldGFpbHMgc2VlIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmMyODIyI3NlY3Rpb24tMy4zXG52YXIgcmZjMjgyMiA9IC9eKD86KE1vbnxUdWV8V2VkfFRodXxGcml8U2F0fFN1biksP1xccyk/KFxcZHsxLDJ9KVxccyhKYW58RmVifE1hcnxBcHJ8TWF5fEp1bnxKdWx8QXVnfFNlcHxPY3R8Tm92fERlYylcXHMoXFxkezIsNH0pXFxzKFxcZFxcZCk6KFxcZFxcZCkoPzo6KFxcZFxcZCkpP1xccyg/OihVVHxHTVR8W0VDTVBdW1NEXVQpfChbWnpdKXwoWystXVxcZHs0fSkpJC87XG5cbmZ1bmN0aW9uIGV4dHJhY3RGcm9tUkZDMjgyMlN0cmluZ3MoeWVhclN0ciwgbW9udGhTdHIsIGRheVN0ciwgaG91clN0ciwgbWludXRlU3RyLCBzZWNvbmRTdHIpIHtcbiAgICB2YXIgcmVzdWx0ID0gW1xuICAgICAgICB1bnRydW5jYXRlWWVhcih5ZWFyU3RyKSxcbiAgICAgICAgZGVmYXVsdExvY2FsZU1vbnRoc1Nob3J0LmluZGV4T2YobW9udGhTdHIpLFxuICAgICAgICBwYXJzZUludChkYXlTdHIsIDEwKSxcbiAgICAgICAgcGFyc2VJbnQoaG91clN0ciwgMTApLFxuICAgICAgICBwYXJzZUludChtaW51dGVTdHIsIDEwKVxuICAgIF07XG5cbiAgICBpZiAoc2Vjb25kU3RyKSB7XG4gICAgICAgIHJlc3VsdC5wdXNoKHBhcnNlSW50KHNlY29uZFN0ciwgMTApKTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiB1bnRydW5jYXRlWWVhcih5ZWFyU3RyKSB7XG4gICAgdmFyIHllYXIgPSBwYXJzZUludCh5ZWFyU3RyLCAxMCk7XG4gICAgaWYgKHllYXIgPD0gNDkpIHtcbiAgICAgICAgcmV0dXJuIDIwMDAgKyB5ZWFyO1xuICAgIH0gZWxzZSBpZiAoeWVhciA8PSA5OTkpIHtcbiAgICAgICAgcmV0dXJuIDE5MDAgKyB5ZWFyO1xuICAgIH1cbiAgICByZXR1cm4geWVhcjtcbn1cblxuZnVuY3Rpb24gcHJlcHJvY2Vzc1JGQzI4MjIocykge1xuICAgIC8vIFJlbW92ZSBjb21tZW50cyBhbmQgZm9sZGluZyB3aGl0ZXNwYWNlIGFuZCByZXBsYWNlIG11bHRpcGxlLXNwYWNlcyB3aXRoIGEgc2luZ2xlIHNwYWNlXG4gICAgcmV0dXJuIHMucmVwbGFjZSgvXFwoW14pXSpcXCl8W1xcblxcdF0vZywgJyAnKS5yZXBsYWNlKC8oXFxzXFxzKykvZywgJyAnKS50cmltKCk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrV2Vla2RheSh3ZWVrZGF5U3RyLCBwYXJzZWRJbnB1dCwgY29uZmlnKSB7XG4gICAgaWYgKHdlZWtkYXlTdHIpIHtcbiAgICAgICAgLy8gVE9ETzogUmVwbGFjZSB0aGUgdmFuaWxsYSBKUyBEYXRlIG9iamVjdCB3aXRoIGFuIGluZGVwZW50ZW50IGRheS1vZi13ZWVrIGNoZWNrLlxuICAgICAgICB2YXIgd2Vla2RheVByb3ZpZGVkID0gZGVmYXVsdExvY2FsZVdlZWtkYXlzU2hvcnQuaW5kZXhPZih3ZWVrZGF5U3RyKSxcbiAgICAgICAgICAgIHdlZWtkYXlBY3R1YWwgPSBuZXcgRGF0ZShwYXJzZWRJbnB1dFswXSwgcGFyc2VkSW5wdXRbMV0sIHBhcnNlZElucHV0WzJdKS5nZXREYXkoKTtcbiAgICAgICAgaWYgKHdlZWtkYXlQcm92aWRlZCAhPT0gd2Vla2RheUFjdHVhbCkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykud2Vla2RheU1pc21hdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufVxuXG52YXIgb2JzT2Zmc2V0cyA9IHtcbiAgICBVVDogMCxcbiAgICBHTVQ6IDAsXG4gICAgRURUOiAtNCAqIDYwLFxuICAgIEVTVDogLTUgKiA2MCxcbiAgICBDRFQ6IC01ICogNjAsXG4gICAgQ1NUOiAtNiAqIDYwLFxuICAgIE1EVDogLTYgKiA2MCxcbiAgICBNU1Q6IC03ICogNjAsXG4gICAgUERUOiAtNyAqIDYwLFxuICAgIFBTVDogLTggKiA2MFxufTtcblxuZnVuY3Rpb24gY2FsY3VsYXRlT2Zmc2V0KG9ic09mZnNldCwgbWlsaXRhcnlPZmZzZXQsIG51bU9mZnNldCkge1xuICAgIGlmIChvYnNPZmZzZXQpIHtcbiAgICAgICAgcmV0dXJuIG9ic09mZnNldHNbb2JzT2Zmc2V0XTtcbiAgICB9IGVsc2UgaWYgKG1pbGl0YXJ5T2Zmc2V0KSB7XG4gICAgICAgIC8vIHRoZSBvbmx5IGFsbG93ZWQgbWlsaXRhcnkgdHogaXMgWlxuICAgICAgICByZXR1cm4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgaG0gPSBwYXJzZUludChudW1PZmZzZXQsIDEwKTtcbiAgICAgICAgdmFyIG0gPSBobSAlIDEwMCwgaCA9IChobSAtIG0pIC8gMTAwO1xuICAgICAgICByZXR1cm4gaCAqIDYwICsgbTtcbiAgICB9XG59XG5cbi8vIGRhdGUgYW5kIHRpbWUgZnJvbSByZWYgMjgyMiBmb3JtYXRcbmZ1bmN0aW9uIGNvbmZpZ0Zyb21SRkMyODIyKGNvbmZpZykge1xuICAgIHZhciBtYXRjaCA9IHJmYzI4MjIuZXhlYyhwcmVwcm9jZXNzUkZDMjgyMihjb25maWcuX2kpKTtcbiAgICBpZiAobWF0Y2gpIHtcbiAgICAgICAgdmFyIHBhcnNlZEFycmF5ID0gZXh0cmFjdEZyb21SRkMyODIyU3RyaW5ncyhtYXRjaFs0XSwgbWF0Y2hbM10sIG1hdGNoWzJdLCBtYXRjaFs1XSwgbWF0Y2hbNl0sIG1hdGNoWzddKTtcbiAgICAgICAgaWYgKCFjaGVja1dlZWtkYXkobWF0Y2hbMV0sIHBhcnNlZEFycmF5LCBjb25maWcpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25maWcuX2EgPSBwYXJzZWRBcnJheTtcbiAgICAgICAgY29uZmlnLl90em0gPSBjYWxjdWxhdGVPZmZzZXQobWF0Y2hbOF0sIG1hdGNoWzldLCBtYXRjaFsxMF0pO1xuXG4gICAgICAgIGNvbmZpZy5fZCA9IGNyZWF0ZVVUQ0RhdGUuYXBwbHkobnVsbCwgY29uZmlnLl9hKTtcbiAgICAgICAgY29uZmlnLl9kLnNldFVUQ01pbnV0ZXMoY29uZmlnLl9kLmdldFVUQ01pbnV0ZXMoKSAtIGNvbmZpZy5fdHptKTtcblxuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5yZmMyODIyID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICB9XG59XG5cbi8vIGRhdGUgZnJvbSBpc28gZm9ybWF0IG9yIGZhbGxiYWNrXG5mdW5jdGlvbiBjb25maWdGcm9tU3RyaW5nKGNvbmZpZykge1xuICAgIHZhciBtYXRjaGVkID0gYXNwTmV0SnNvblJlZ2V4LmV4ZWMoY29uZmlnLl9pKTtcblxuICAgIGlmIChtYXRjaGVkICE9PSBudWxsKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKCttYXRjaGVkWzFdKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbmZpZ0Zyb21JU08oY29uZmlnKTtcbiAgICBpZiAoY29uZmlnLl9pc1ZhbGlkID09PSBmYWxzZSkge1xuICAgICAgICBkZWxldGUgY29uZmlnLl9pc1ZhbGlkO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25maWdGcm9tUkZDMjgyMihjb25maWcpO1xuICAgIGlmIChjb25maWcuX2lzVmFsaWQgPT09IGZhbHNlKSB7XG4gICAgICAgIGRlbGV0ZSBjb25maWcuX2lzVmFsaWQ7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEZpbmFsIGF0dGVtcHQsIHVzZSBJbnB1dCBGYWxsYmFja1xuICAgIGhvb2tzLmNyZWF0ZUZyb21JbnB1dEZhbGxiYWNrKGNvbmZpZyk7XG59XG5cbmhvb2tzLmNyZWF0ZUZyb21JbnB1dEZhbGxiYWNrID0gZGVwcmVjYXRlKFxuICAgICd2YWx1ZSBwcm92aWRlZCBpcyBub3QgaW4gYSByZWNvZ25pemVkIFJGQzI4MjIgb3IgSVNPIGZvcm1hdC4gbW9tZW50IGNvbnN0cnVjdGlvbiBmYWxscyBiYWNrIHRvIGpzIERhdGUoKSwgJyArXG4gICAgJ3doaWNoIGlzIG5vdCByZWxpYWJsZSBhY3Jvc3MgYWxsIGJyb3dzZXJzIGFuZCB2ZXJzaW9ucy4gTm9uIFJGQzI4MjIvSVNPIGRhdGUgZm9ybWF0cyBhcmUgJyArXG4gICAgJ2Rpc2NvdXJhZ2VkIGFuZCB3aWxsIGJlIHJlbW92ZWQgaW4gYW4gdXBjb21pbmcgbWFqb3IgcmVsZWFzZS4gUGxlYXNlIHJlZmVyIHRvICcgK1xuICAgICdodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL2pzLWRhdGUvIGZvciBtb3JlIGluZm8uJyxcbiAgICBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKGNvbmZpZy5faSArIChjb25maWcuX3VzZVVUQyA/ICcgVVRDJyA6ICcnKSk7XG4gICAgfVxuKTtcblxuLy8gY29uc3RhbnQgdGhhdCByZWZlcnMgdG8gdGhlIElTTyBzdGFuZGFyZFxuaG9va3MuSVNPXzg2MDEgPSBmdW5jdGlvbiAoKSB7fTtcblxuLy8gY29uc3RhbnQgdGhhdCByZWZlcnMgdG8gdGhlIFJGQyAyODIyIGZvcm1cbmhvb2tzLlJGQ18yODIyID0gZnVuY3Rpb24gKCkge307XG5cbi8vIGRhdGUgZnJvbSBzdHJpbmcgYW5kIGZvcm1hdCBzdHJpbmdcbmZ1bmN0aW9uIGNvbmZpZ0Zyb21TdHJpbmdBbmRGb3JtYXQoY29uZmlnKSB7XG4gICAgLy8gVE9ETzogTW92ZSB0aGlzIHRvIGFub3RoZXIgcGFydCBvZiB0aGUgY3JlYXRpb24gZmxvdyB0byBwcmV2ZW50IGNpcmN1bGFyIGRlcHNcbiAgICBpZiAoY29uZmlnLl9mID09PSBob29rcy5JU09fODYwMSkge1xuICAgICAgICBjb25maWdGcm9tSVNPKGNvbmZpZyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGNvbmZpZy5fZiA9PT0gaG9va3MuUkZDXzI4MjIpIHtcbiAgICAgICAgY29uZmlnRnJvbVJGQzI4MjIoY29uZmlnKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25maWcuX2EgPSBbXTtcbiAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5lbXB0eSA9IHRydWU7XG5cbiAgICAvLyBUaGlzIGFycmF5IGlzIHVzZWQgdG8gbWFrZSBhIERhdGUsIGVpdGhlciB3aXRoIGBuZXcgRGF0ZWAgb3IgYERhdGUuVVRDYFxuICAgIHZhciBzdHJpbmcgPSAnJyArIGNvbmZpZy5faSxcbiAgICAgICAgaSwgcGFyc2VkSW5wdXQsIHRva2VucywgdG9rZW4sIHNraXBwZWQsXG4gICAgICAgIHN0cmluZ0xlbmd0aCA9IHN0cmluZy5sZW5ndGgsXG4gICAgICAgIHRvdGFsUGFyc2VkSW5wdXRMZW5ndGggPSAwO1xuXG4gICAgdG9rZW5zID0gZXhwYW5kRm9ybWF0KGNvbmZpZy5fZiwgY29uZmlnLl9sb2NhbGUpLm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpIHx8IFtdO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IHRva2Vucy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0b2tlbiA9IHRva2Vuc1tpXTtcbiAgICAgICAgcGFyc2VkSW5wdXQgPSAoc3RyaW5nLm1hdGNoKGdldFBhcnNlUmVnZXhGb3JUb2tlbih0b2tlbiwgY29uZmlnKSkgfHwgW10pWzBdO1xuICAgICAgICAvLyBjb25zb2xlLmxvZygndG9rZW4nLCB0b2tlbiwgJ3BhcnNlZElucHV0JywgcGFyc2VkSW5wdXQsXG4gICAgICAgIC8vICAgICAgICAgJ3JlZ2V4JywgZ2V0UGFyc2VSZWdleEZvclRva2VuKHRva2VuLCBjb25maWcpKTtcbiAgICAgICAgaWYgKHBhcnNlZElucHV0KSB7XG4gICAgICAgICAgICBza2lwcGVkID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZihwYXJzZWRJbnB1dCkpO1xuICAgICAgICAgICAgaWYgKHNraXBwZWQubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZElucHV0LnB1c2goc2tpcHBlZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcuc2xpY2Uoc3RyaW5nLmluZGV4T2YocGFyc2VkSW5wdXQpICsgcGFyc2VkSW5wdXQubGVuZ3RoKTtcbiAgICAgICAgICAgIHRvdGFsUGFyc2VkSW5wdXRMZW5ndGggKz0gcGFyc2VkSW5wdXQubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIC8vIGRvbid0IHBhcnNlIGlmIGl0J3Mgbm90IGEga25vd24gdG9rZW5cbiAgICAgICAgaWYgKGZvcm1hdFRva2VuRnVuY3Rpb25zW3Rva2VuXSkge1xuICAgICAgICAgICAgaWYgKHBhcnNlZElucHV0KSB7XG4gICAgICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuZW1wdHkgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZFRva2Vucy5wdXNoKHRva2VuKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFkZFRpbWVUb0FycmF5RnJvbVRva2VuKHRva2VuLCBwYXJzZWRJbnB1dCwgY29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmIChjb25maWcuX3N0cmljdCAmJiAhcGFyc2VkSW5wdXQpIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZFRva2Vucy5wdXNoKHRva2VuKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFkZCByZW1haW5pbmcgdW5wYXJzZWQgaW5wdXQgbGVuZ3RoIHRvIHRoZSBzdHJpbmdcbiAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5jaGFyc0xlZnRPdmVyID0gc3RyaW5nTGVuZ3RoIC0gdG90YWxQYXJzZWRJbnB1dExlbmd0aDtcbiAgICBpZiAoc3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykudW51c2VkSW5wdXQucHVzaChzdHJpbmcpO1xuICAgIH1cblxuICAgIC8vIGNsZWFyIF8xMmggZmxhZyBpZiBob3VyIGlzIDw9IDEyXG4gICAgaWYgKGNvbmZpZy5fYVtIT1VSXSA8PSAxMiAmJlxuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID09PSB0cnVlICYmXG4gICAgICAgIGNvbmZpZy5fYVtIT1VSXSA+IDApIHtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5wYXJzZWREYXRlUGFydHMgPSBjb25maWcuX2Euc2xpY2UoMCk7XG4gICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykubWVyaWRpZW0gPSBjb25maWcuX21lcmlkaWVtO1xuICAgIC8vIGhhbmRsZSBtZXJpZGllbVxuICAgIGNvbmZpZy5fYVtIT1VSXSA9IG1lcmlkaWVtRml4V3JhcChjb25maWcuX2xvY2FsZSwgY29uZmlnLl9hW0hPVVJdLCBjb25maWcuX21lcmlkaWVtKTtcblxuICAgIGNvbmZpZ0Zyb21BcnJheShjb25maWcpO1xuICAgIGNoZWNrT3ZlcmZsb3coY29uZmlnKTtcbn1cblxuXG5mdW5jdGlvbiBtZXJpZGllbUZpeFdyYXAgKGxvY2FsZSwgaG91ciwgbWVyaWRpZW0pIHtcbiAgICB2YXIgaXNQbTtcblxuICAgIGlmIChtZXJpZGllbSA9PSBudWxsKSB7XG4gICAgICAgIC8vIG5vdGhpbmcgdG8gZG9cbiAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgfVxuICAgIGlmIChsb2NhbGUubWVyaWRpZW1Ib3VyICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS5tZXJpZGllbUhvdXIoaG91ciwgbWVyaWRpZW0pO1xuICAgIH0gZWxzZSBpZiAobG9jYWxlLmlzUE0gIT0gbnVsbCkge1xuICAgICAgICAvLyBGYWxsYmFja1xuICAgICAgICBpc1BtID0gbG9jYWxlLmlzUE0obWVyaWRpZW0pO1xuICAgICAgICBpZiAoaXNQbSAmJiBob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIGhvdXIgKz0gMTI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1BtICYmIGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaG91cjtcbiAgICB9IGVsc2Uge1xuICAgICAgICAvLyB0aGlzIGlzIG5vdCBzdXBwb3NlZCB0byBoYXBwZW5cbiAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgfVxufVxuXG4vLyBkYXRlIGZyb20gc3RyaW5nIGFuZCBhcnJheSBvZiBmb3JtYXQgc3RyaW5nc1xuZnVuY3Rpb24gY29uZmlnRnJvbVN0cmluZ0FuZEFycmF5KGNvbmZpZykge1xuICAgIHZhciB0ZW1wQ29uZmlnLFxuICAgICAgICBiZXN0TW9tZW50LFxuXG4gICAgICAgIHNjb3JlVG9CZWF0LFxuICAgICAgICBpLFxuICAgICAgICBjdXJyZW50U2NvcmU7XG5cbiAgICBpZiAoY29uZmlnLl9mLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5pbnZhbGlkRm9ybWF0ID0gdHJ1ZTtcbiAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoTmFOKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGZvciAoaSA9IDA7IGkgPCBjb25maWcuX2YubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY3VycmVudFNjb3JlID0gMDtcbiAgICAgICAgdGVtcENvbmZpZyA9IGNvcHlDb25maWcoe30sIGNvbmZpZyk7XG4gICAgICAgIGlmIChjb25maWcuX3VzZVVUQyAhPSBudWxsKSB7XG4gICAgICAgICAgICB0ZW1wQ29uZmlnLl91c2VVVEMgPSBjb25maWcuX3VzZVVUQztcbiAgICAgICAgfVxuICAgICAgICB0ZW1wQ29uZmlnLl9mID0gY29uZmlnLl9mW2ldO1xuICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KHRlbXBDb25maWcpO1xuXG4gICAgICAgIGlmICghaXNWYWxpZCh0ZW1wQ29uZmlnKSkge1xuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBpZiB0aGVyZSBpcyBhbnkgaW5wdXQgdGhhdCB3YXMgbm90IHBhcnNlZCBhZGQgYSBwZW5hbHR5IGZvciB0aGF0IGZvcm1hdFxuICAgICAgICBjdXJyZW50U2NvcmUgKz0gZ2V0UGFyc2luZ0ZsYWdzKHRlbXBDb25maWcpLmNoYXJzTGVmdE92ZXI7XG5cbiAgICAgICAgLy9vciB0b2tlbnNcbiAgICAgICAgY3VycmVudFNjb3JlICs9IGdldFBhcnNpbmdGbGFncyh0ZW1wQ29uZmlnKS51bnVzZWRUb2tlbnMubGVuZ3RoICogMTA7XG5cbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKHRlbXBDb25maWcpLnNjb3JlID0gY3VycmVudFNjb3JlO1xuXG4gICAgICAgIGlmIChzY29yZVRvQmVhdCA9PSBudWxsIHx8IGN1cnJlbnRTY29yZSA8IHNjb3JlVG9CZWF0KSB7XG4gICAgICAgICAgICBzY29yZVRvQmVhdCA9IGN1cnJlbnRTY29yZTtcbiAgICAgICAgICAgIGJlc3RNb21lbnQgPSB0ZW1wQ29uZmlnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXh0ZW5kKGNvbmZpZywgYmVzdE1vbWVudCB8fCB0ZW1wQ29uZmlnKTtcbn1cblxuZnVuY3Rpb24gY29uZmlnRnJvbU9iamVjdChjb25maWcpIHtcbiAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgaSA9IG5vcm1hbGl6ZU9iamVjdFVuaXRzKGNvbmZpZy5faSk7XG4gICAgY29uZmlnLl9hID0gbWFwKFtpLnllYXIsIGkubW9udGgsIGkuZGF5IHx8IGkuZGF0ZSwgaS5ob3VyLCBpLm1pbnV0ZSwgaS5zZWNvbmQsIGkubWlsbGlzZWNvbmRdLCBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogJiYgcGFyc2VJbnQob2JqLCAxMCk7XG4gICAgfSk7XG5cbiAgICBjb25maWdGcm9tQXJyYXkoY29uZmlnKTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlRnJvbUNvbmZpZyAoY29uZmlnKSB7XG4gICAgdmFyIHJlcyA9IG5ldyBNb21lbnQoY2hlY2tPdmVyZmxvdyhwcmVwYXJlQ29uZmlnKGNvbmZpZykpKTtcbiAgICBpZiAocmVzLl9uZXh0RGF5KSB7XG4gICAgICAgIC8vIEFkZGluZyBpcyBzbWFydCBlbm91Z2ggYXJvdW5kIERTVFxuICAgICAgICByZXMuYWRkKDEsICdkJyk7XG4gICAgICAgIHJlcy5fbmV4dERheSA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBwcmVwYXJlQ29uZmlnIChjb25maWcpIHtcbiAgICB2YXIgaW5wdXQgPSBjb25maWcuX2ksXG4gICAgICAgIGZvcm1hdCA9IGNvbmZpZy5fZjtcblxuICAgIGNvbmZpZy5fbG9jYWxlID0gY29uZmlnLl9sb2NhbGUgfHwgZ2V0TG9jYWxlKGNvbmZpZy5fbCk7XG5cbiAgICBpZiAoaW5wdXQgPT09IG51bGwgfHwgKGZvcm1hdCA9PT0gdW5kZWZpbmVkICYmIGlucHV0ID09PSAnJykpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUludmFsaWQoe251bGxJbnB1dDogdHJ1ZX0pO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbmZpZy5faSA9IGlucHV0ID0gY29uZmlnLl9sb2NhbGUucHJlcGFyc2UoaW5wdXQpO1xuICAgIH1cblxuICAgIGlmIChpc01vbWVudChpbnB1dCkpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBNb21lbnQoY2hlY2tPdmVyZmxvdyhpbnB1dCkpO1xuICAgIH0gZWxzZSBpZiAoaXNEYXRlKGlucHV0KSkge1xuICAgICAgICBjb25maWcuX2QgPSBpbnB1dDtcbiAgICB9IGVsc2UgaWYgKGlzQXJyYXkoZm9ybWF0KSkge1xuICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kQXJyYXkoY29uZmlnKTtcbiAgICB9IGVsc2UgaWYgKGZvcm1hdCkge1xuICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XG4gICAgfSAgZWxzZSB7XG4gICAgICAgIGNvbmZpZ0Zyb21JbnB1dChjb25maWcpO1xuICAgIH1cblxuICAgIGlmICghaXNWYWxpZChjb25maWcpKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG51bGw7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbmZpZztcbn1cblxuZnVuY3Rpb24gY29uZmlnRnJvbUlucHV0KGNvbmZpZykge1xuICAgIHZhciBpbnB1dCA9IGNvbmZpZy5faTtcbiAgICBpZiAoaXNVbmRlZmluZWQoaW5wdXQpKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKGhvb2tzLm5vdygpKTtcbiAgICB9IGVsc2UgaWYgKGlzRGF0ZShpbnB1dCkpIHtcbiAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoaW5wdXQudmFsdWVPZigpKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgY29uZmlnRnJvbVN0cmluZyhjb25maWcpO1xuICAgIH0gZWxzZSBpZiAoaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgY29uZmlnLl9hID0gbWFwKGlucHV0LnNsaWNlKDApLCBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQob2JqLCAxMCk7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25maWdGcm9tQXJyYXkoY29uZmlnKTtcbiAgICB9IGVsc2UgaWYgKGlzT2JqZWN0KGlucHV0KSkge1xuICAgICAgICBjb25maWdGcm9tT2JqZWN0KGNvbmZpZyk7XG4gICAgfSBlbHNlIGlmIChpc051bWJlcihpbnB1dCkpIHtcbiAgICAgICAgLy8gZnJvbSBtaWxsaXNlY29uZHNcbiAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoaW5wdXQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGhvb2tzLmNyZWF0ZUZyb21JbnB1dEZhbGxiYWNrKGNvbmZpZyk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVMb2NhbE9yVVRDIChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCwgaXNVVEMpIHtcbiAgICB2YXIgYyA9IHt9O1xuXG4gICAgaWYgKGxvY2FsZSA9PT0gdHJ1ZSB8fCBsb2NhbGUgPT09IGZhbHNlKSB7XG4gICAgICAgIHN0cmljdCA9IGxvY2FsZTtcbiAgICAgICAgbG9jYWxlID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmICgoaXNPYmplY3QoaW5wdXQpICYmIGlzT2JqZWN0RW1wdHkoaW5wdXQpKSB8fFxuICAgICAgICAgICAgKGlzQXJyYXkoaW5wdXQpICYmIGlucHV0Lmxlbmd0aCA9PT0gMCkpIHtcbiAgICAgICAgaW5wdXQgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIC8vIG9iamVjdCBjb25zdHJ1Y3Rpb24gbXVzdCBiZSBkb25lIHRoaXMgd2F5LlxuICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L2lzc3Vlcy8xNDIzXG4gICAgYy5faXNBTW9tZW50T2JqZWN0ID0gdHJ1ZTtcbiAgICBjLl91c2VVVEMgPSBjLl9pc1VUQyA9IGlzVVRDO1xuICAgIGMuX2wgPSBsb2NhbGU7XG4gICAgYy5faSA9IGlucHV0O1xuICAgIGMuX2YgPSBmb3JtYXQ7XG4gICAgYy5fc3RyaWN0ID0gc3RyaWN0O1xuXG4gICAgcmV0dXJuIGNyZWF0ZUZyb21Db25maWcoYyk7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUxvY2FsIChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCkge1xuICAgIHJldHVybiBjcmVhdGVMb2NhbE9yVVRDKGlucHV0LCBmb3JtYXQsIGxvY2FsZSwgc3RyaWN0LCBmYWxzZSk7XG59XG5cbnZhciBwcm90b3R5cGVNaW4gPSBkZXByZWNhdGUoXG4gICAgJ21vbWVudCgpLm1pbiBpcyBkZXByZWNhdGVkLCB1c2UgbW9tZW50Lm1heCBpbnN0ZWFkLiBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL21pbi1tYXgvJyxcbiAgICBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBvdGhlciA9IGNyZWF0ZUxvY2FsLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgIGlmICh0aGlzLmlzVmFsaWQoKSAmJiBvdGhlci5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBvdGhlciA8IHRoaXMgPyB0aGlzIDogb3RoZXI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlSW52YWxpZCgpO1xuICAgICAgICB9XG4gICAgfVxuKTtcblxudmFyIHByb3RvdHlwZU1heCA9IGRlcHJlY2F0ZShcbiAgICAnbW9tZW50KCkubWF4IGlzIGRlcHJlY2F0ZWQsIHVzZSBtb21lbnQubWluIGluc3RlYWQuIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvbWluLW1heC8nLFxuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG90aGVyID0gY3JlYXRlTG9jYWwuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgaWYgKHRoaXMuaXNWYWxpZCgpICYmIG90aGVyLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG90aGVyID4gdGhpcyA/IHRoaXMgOiBvdGhlcjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVJbnZhbGlkKCk7XG4gICAgICAgIH1cbiAgICB9XG4pO1xuXG4vLyBQaWNrIGEgbW9tZW50IG0gZnJvbSBtb21lbnRzIHNvIHRoYXQgbVtmbl0ob3RoZXIpIGlzIHRydWUgZm9yIGFsbFxuLy8gb3RoZXIuIFRoaXMgcmVsaWVzIG9uIHRoZSBmdW5jdGlvbiBmbiB0byBiZSB0cmFuc2l0aXZlLlxuLy9cbi8vIG1vbWVudHMgc2hvdWxkIGVpdGhlciBiZSBhbiBhcnJheSBvZiBtb21lbnQgb2JqZWN0cyBvciBhbiBhcnJheSwgd2hvc2Vcbi8vIGZpcnN0IGVsZW1lbnQgaXMgYW4gYXJyYXkgb2YgbW9tZW50IG9iamVjdHMuXG5mdW5jdGlvbiBwaWNrQnkoZm4sIG1vbWVudHMpIHtcbiAgICB2YXIgcmVzLCBpO1xuICAgIGlmIChtb21lbnRzLmxlbmd0aCA9PT0gMSAmJiBpc0FycmF5KG1vbWVudHNbMF0pKSB7XG4gICAgICAgIG1vbWVudHMgPSBtb21lbnRzWzBdO1xuICAgIH1cbiAgICBpZiAoIW1vbWVudHMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVMb2NhbCgpO1xuICAgIH1cbiAgICByZXMgPSBtb21lbnRzWzBdO1xuICAgIGZvciAoaSA9IDE7IGkgPCBtb21lbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmICghbW9tZW50c1tpXS5pc1ZhbGlkKCkgfHwgbW9tZW50c1tpXVtmbl0ocmVzKSkge1xuICAgICAgICAgICAgcmVzID0gbW9tZW50c1tpXTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuXG4vLyBUT0RPOiBVc2UgW10uc29ydCBpbnN0ZWFkP1xuZnVuY3Rpb24gbWluICgpIHtcbiAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcblxuICAgIHJldHVybiBwaWNrQnkoJ2lzQmVmb3JlJywgYXJncyk7XG59XG5cbmZ1bmN0aW9uIG1heCAoKSB7XG4gICAgdmFyIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCk7XG5cbiAgICByZXR1cm4gcGlja0J5KCdpc0FmdGVyJywgYXJncyk7XG59XG5cbnZhciBub3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIERhdGUubm93ID8gRGF0ZS5ub3coKSA6ICsobmV3IERhdGUoKSk7XG59O1xuXG52YXIgb3JkZXJpbmcgPSBbJ3llYXInLCAncXVhcnRlcicsICdtb250aCcsICd3ZWVrJywgJ2RheScsICdob3VyJywgJ21pbnV0ZScsICdzZWNvbmQnLCAnbWlsbGlzZWNvbmQnXTtcblxuZnVuY3Rpb24gaXNEdXJhdGlvblZhbGlkKG0pIHtcbiAgICBmb3IgKHZhciBrZXkgaW4gbSkge1xuICAgICAgICBpZiAoIShpbmRleE9mLmNhbGwob3JkZXJpbmcsIGtleSkgIT09IC0xICYmIChtW2tleV0gPT0gbnVsbCB8fCAhaXNOYU4obVtrZXldKSkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgdW5pdEhhc0RlY2ltYWwgPSBmYWxzZTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IG9yZGVyaW5nLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmIChtW29yZGVyaW5nW2ldXSkge1xuICAgICAgICAgICAgaWYgKHVuaXRIYXNEZWNpbWFsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBvbmx5IGFsbG93IG5vbi1pbnRlZ2VycyBmb3Igc21hbGxlc3QgdW5pdFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcnNlRmxvYXQobVtvcmRlcmluZ1tpXV0pICE9PSB0b0ludChtW29yZGVyaW5nW2ldXSkpIHtcbiAgICAgICAgICAgICAgICB1bml0SGFzRGVjaW1hbCA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaXNWYWxpZCQxKCkge1xuICAgIHJldHVybiB0aGlzLl9pc1ZhbGlkO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVJbnZhbGlkJDEoKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKE5hTik7XG59XG5cbmZ1bmN0aW9uIER1cmF0aW9uIChkdXJhdGlvbikge1xuICAgIHZhciBub3JtYWxpemVkSW5wdXQgPSBub3JtYWxpemVPYmplY3RVbml0cyhkdXJhdGlvbiksXG4gICAgICAgIHllYXJzID0gbm9ybWFsaXplZElucHV0LnllYXIgfHwgMCxcbiAgICAgICAgcXVhcnRlcnMgPSBub3JtYWxpemVkSW5wdXQucXVhcnRlciB8fCAwLFxuICAgICAgICBtb250aHMgPSBub3JtYWxpemVkSW5wdXQubW9udGggfHwgMCxcbiAgICAgICAgd2Vla3MgPSBub3JtYWxpemVkSW5wdXQud2VlayB8fCAwLFxuICAgICAgICBkYXlzID0gbm9ybWFsaXplZElucHV0LmRheSB8fCAwLFxuICAgICAgICBob3VycyA9IG5vcm1hbGl6ZWRJbnB1dC5ob3VyIHx8IDAsXG4gICAgICAgIG1pbnV0ZXMgPSBub3JtYWxpemVkSW5wdXQubWludXRlIHx8IDAsXG4gICAgICAgIHNlY29uZHMgPSBub3JtYWxpemVkSW5wdXQuc2Vjb25kIHx8IDAsXG4gICAgICAgIG1pbGxpc2Vjb25kcyA9IG5vcm1hbGl6ZWRJbnB1dC5taWxsaXNlY29uZCB8fCAwO1xuXG4gICAgdGhpcy5faXNWYWxpZCA9IGlzRHVyYXRpb25WYWxpZChub3JtYWxpemVkSW5wdXQpO1xuXG4gICAgLy8gcmVwcmVzZW50YXRpb24gZm9yIGRhdGVBZGRSZW1vdmVcbiAgICB0aGlzLl9taWxsaXNlY29uZHMgPSArbWlsbGlzZWNvbmRzICtcbiAgICAgICAgc2Vjb25kcyAqIDFlMyArIC8vIDEwMDBcbiAgICAgICAgbWludXRlcyAqIDZlNCArIC8vIDEwMDAgKiA2MFxuICAgICAgICBob3VycyAqIDEwMDAgKiA2MCAqIDYwOyAvL3VzaW5nIDEwMDAgKiA2MCAqIDYwIGluc3RlYWQgb2YgMzZlNSB0byBhdm9pZCBmbG9hdGluZyBwb2ludCByb3VuZGluZyBlcnJvcnMgaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvaXNzdWVzLzI5NzhcbiAgICAvLyBCZWNhdXNlIG9mIGRhdGVBZGRSZW1vdmUgdHJlYXRzIDI0IGhvdXJzIGFzIGRpZmZlcmVudCBmcm9tIGFcbiAgICAvLyBkYXkgd2hlbiB3b3JraW5nIGFyb3VuZCBEU1QsIHdlIG5lZWQgdG8gc3RvcmUgdGhlbSBzZXBhcmF0ZWx5XG4gICAgdGhpcy5fZGF5cyA9ICtkYXlzICtcbiAgICAgICAgd2Vla3MgKiA3O1xuICAgIC8vIEl0IGlzIGltcG9zc2libGUgdG8gdHJhbnNsYXRlIG1vbnRocyBpbnRvIGRheXMgd2l0aG91dCBrbm93aW5nXG4gICAgLy8gd2hpY2ggbW9udGhzIHlvdSBhcmUgYXJlIHRhbGtpbmcgYWJvdXQsIHNvIHdlIGhhdmUgdG8gc3RvcmVcbiAgICAvLyBpdCBzZXBhcmF0ZWx5LlxuICAgIHRoaXMuX21vbnRocyA9ICttb250aHMgK1xuICAgICAgICBxdWFydGVycyAqIDMgK1xuICAgICAgICB5ZWFycyAqIDEyO1xuXG4gICAgdGhpcy5fZGF0YSA9IHt9O1xuXG4gICAgdGhpcy5fbG9jYWxlID0gZ2V0TG9jYWxlKCk7XG5cbiAgICB0aGlzLl9idWJibGUoKTtcbn1cblxuZnVuY3Rpb24gaXNEdXJhdGlvbiAob2JqKSB7XG4gICAgcmV0dXJuIG9iaiBpbnN0YW5jZW9mIER1cmF0aW9uO1xufVxuXG5mdW5jdGlvbiBhYnNSb3VuZCAobnVtYmVyKSB7XG4gICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQoLTEgKiBudW1iZXIpICogLTE7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbiAgICB9XG59XG5cbi8vIEZPUk1BVFRJTkdcblxuZnVuY3Rpb24gb2Zmc2V0ICh0b2tlbiwgc2VwYXJhdG9yKSB7XG4gICAgYWRkRm9ybWF0VG9rZW4odG9rZW4sIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIG9mZnNldCA9IHRoaXMudXRjT2Zmc2V0KCk7XG4gICAgICAgIHZhciBzaWduID0gJysnO1xuICAgICAgICBpZiAob2Zmc2V0IDwgMCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gLW9mZnNldDtcbiAgICAgICAgICAgIHNpZ24gPSAnLSc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNpZ24gKyB6ZXJvRmlsbCh+fihvZmZzZXQgLyA2MCksIDIpICsgc2VwYXJhdG9yICsgemVyb0ZpbGwofn4ob2Zmc2V0KSAlIDYwLCAyKTtcbiAgICB9KTtcbn1cblxub2Zmc2V0KCdaJywgJzonKTtcbm9mZnNldCgnWlonLCAnJyk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbignWicsICBtYXRjaFNob3J0T2Zmc2V0KTtcbmFkZFJlZ2V4VG9rZW4oJ1paJywgbWF0Y2hTaG9ydE9mZnNldCk7XG5hZGRQYXJzZVRva2VuKFsnWicsICdaWiddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICBjb25maWcuX3VzZVVUQyA9IHRydWU7XG4gICAgY29uZmlnLl90em0gPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoU2hvcnRPZmZzZXQsIGlucHV0KTtcbn0pO1xuXG4vLyBIRUxQRVJTXG5cbi8vIHRpbWV6b25lIGNodW5rZXJcbi8vICcrMTA6MDAnID4gWycxMCcsICAnMDAnXVxuLy8gJy0xNTMwJyAgPiBbJy0xNScsICczMCddXG52YXIgY2h1bmtPZmZzZXQgPSAvKFtcXCtcXC1dfFxcZFxcZCkvZ2k7XG5cbmZ1bmN0aW9uIG9mZnNldEZyb21TdHJpbmcobWF0Y2hlciwgc3RyaW5nKSB7XG4gICAgdmFyIG1hdGNoZXMgPSAoc3RyaW5nIHx8ICcnKS5tYXRjaChtYXRjaGVyKTtcblxuICAgIGlmIChtYXRjaGVzID09PSBudWxsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHZhciBjaHVuayAgID0gbWF0Y2hlc1ttYXRjaGVzLmxlbmd0aCAtIDFdIHx8IFtdO1xuICAgIHZhciBwYXJ0cyAgID0gKGNodW5rICsgJycpLm1hdGNoKGNodW5rT2Zmc2V0KSB8fCBbJy0nLCAwLCAwXTtcbiAgICB2YXIgbWludXRlcyA9ICsocGFydHNbMV0gKiA2MCkgKyB0b0ludChwYXJ0c1syXSk7XG5cbiAgICByZXR1cm4gbWludXRlcyA9PT0gMCA/XG4gICAgICAwIDpcbiAgICAgIHBhcnRzWzBdID09PSAnKycgPyBtaW51dGVzIDogLW1pbnV0ZXM7XG59XG5cbi8vIFJldHVybiBhIG1vbWVudCBmcm9tIGlucHV0LCB0aGF0IGlzIGxvY2FsL3V0Yy96b25lIGVxdWl2YWxlbnQgdG8gbW9kZWwuXG5mdW5jdGlvbiBjbG9uZVdpdGhPZmZzZXQoaW5wdXQsIG1vZGVsKSB7XG4gICAgdmFyIHJlcywgZGlmZjtcbiAgICBpZiAobW9kZWwuX2lzVVRDKSB7XG4gICAgICAgIHJlcyA9IG1vZGVsLmNsb25lKCk7XG4gICAgICAgIGRpZmYgPSAoaXNNb21lbnQoaW5wdXQpIHx8IGlzRGF0ZShpbnB1dCkgPyBpbnB1dC52YWx1ZU9mKCkgOiBjcmVhdGVMb2NhbChpbnB1dCkudmFsdWVPZigpKSAtIHJlcy52YWx1ZU9mKCk7XG4gICAgICAgIC8vIFVzZSBsb3ctbGV2ZWwgYXBpLCBiZWNhdXNlIHRoaXMgZm4gaXMgbG93LWxldmVsIGFwaS5cbiAgICAgICAgcmVzLl9kLnNldFRpbWUocmVzLl9kLnZhbHVlT2YoKSArIGRpZmYpO1xuICAgICAgICBob29rcy51cGRhdGVPZmZzZXQocmVzLCBmYWxzZSk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsKGlucHV0KS5sb2NhbCgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0RGF0ZU9mZnNldCAobSkge1xuICAgIC8vIE9uIEZpcmVmb3guMjQgRGF0ZSNnZXRUaW1lem9uZU9mZnNldCByZXR1cm5zIGEgZmxvYXRpbmcgcG9pbnQuXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL21vbWVudC9tb21lbnQvcHVsbC8xODcxXG4gICAgcmV0dXJuIC1NYXRoLnJvdW5kKG0uX2QuZ2V0VGltZXpvbmVPZmZzZXQoKSAvIDE1KSAqIDE1O1xufVxuXG4vLyBIT09LU1xuXG4vLyBUaGlzIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkIHdoZW5ldmVyIGEgbW9tZW50IGlzIG11dGF0ZWQuXG4vLyBJdCBpcyBpbnRlbmRlZCB0byBrZWVwIHRoZSBvZmZzZXQgaW4gc3luYyB3aXRoIHRoZSB0aW1lem9uZS5cbmhvb2tzLnVwZGF0ZU9mZnNldCA9IGZ1bmN0aW9uICgpIHt9O1xuXG4vLyBNT01FTlRTXG5cbi8vIGtlZXBMb2NhbFRpbWUgPSB0cnVlIG1lYW5zIG9ubHkgY2hhbmdlIHRoZSB0aW1lem9uZSwgd2l0aG91dFxuLy8gYWZmZWN0aW5nIHRoZSBsb2NhbCBob3VyLiBTbyA1OjMxOjI2ICswMzAwIC0tW3V0Y09mZnNldCgyLCB0cnVlKV0tLT5cbi8vIDU6MzE6MjYgKzAyMDAgSXQgaXMgcG9zc2libGUgdGhhdCA1OjMxOjI2IGRvZXNuJ3QgZXhpc3Qgd2l0aCBvZmZzZXRcbi8vICswMjAwLCBzbyB3ZSBhZGp1c3QgdGhlIHRpbWUgYXMgbmVlZGVkLCB0byBiZSB2YWxpZC5cbi8vXG4vLyBLZWVwaW5nIHRoZSB0aW1lIGFjdHVhbGx5IGFkZHMvc3VidHJhY3RzIChvbmUgaG91cilcbi8vIGZyb20gdGhlIGFjdHVhbCByZXByZXNlbnRlZCB0aW1lLiBUaGF0IGlzIHdoeSB3ZSBjYWxsIHVwZGF0ZU9mZnNldFxuLy8gYSBzZWNvbmQgdGltZS4gSW4gY2FzZSBpdCB3YW50cyB1cyB0byBjaGFuZ2UgdGhlIG9mZnNldCBhZ2FpblxuLy8gX2NoYW5nZUluUHJvZ3Jlc3MgPT0gdHJ1ZSBjYXNlLCB0aGVuIHdlIGhhdmUgdG8gYWRqdXN0LCBiZWNhdXNlXG4vLyB0aGVyZSBpcyBubyBzdWNoIHRpbWUgaW4gdGhlIGdpdmVuIHRpbWV6b25lLlxuZnVuY3Rpb24gZ2V0U2V0T2Zmc2V0IChpbnB1dCwga2VlcExvY2FsVGltZSwga2VlcE1pbnV0ZXMpIHtcbiAgICB2YXIgb2Zmc2V0ID0gdGhpcy5fb2Zmc2V0IHx8IDAsXG4gICAgICAgIGxvY2FsQWRqdXN0O1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ICE9IG51bGwgPyB0aGlzIDogTmFOO1xuICAgIH1cbiAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaW5wdXQgPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoU2hvcnRPZmZzZXQsIGlucHV0KTtcbiAgICAgICAgICAgIGlmIChpbnB1dCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKE1hdGguYWJzKGlucHV0KSA8IDE2ICYmICFrZWVwTWludXRlcykge1xuICAgICAgICAgICAgaW5wdXQgPSBpbnB1dCAqIDYwO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5faXNVVEMgJiYga2VlcExvY2FsVGltZSkge1xuICAgICAgICAgICAgbG9jYWxBZGp1c3QgPSBnZXREYXRlT2Zmc2V0KHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX29mZnNldCA9IGlucHV0O1xuICAgICAgICB0aGlzLl9pc1VUQyA9IHRydWU7XG4gICAgICAgIGlmIChsb2NhbEFkanVzdCAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLmFkZChsb2NhbEFkanVzdCwgJ20nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAob2Zmc2V0ICE9PSBpbnB1dCkge1xuICAgICAgICAgICAgaWYgKCFrZWVwTG9jYWxUaW1lIHx8IHRoaXMuX2NoYW5nZUluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICBhZGRTdWJ0cmFjdCh0aGlzLCBjcmVhdGVEdXJhdGlvbihpbnB1dCAtIG9mZnNldCwgJ20nKSwgMSwgZmFsc2UpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5fY2hhbmdlSW5Qcm9ncmVzcykge1xuICAgICAgICAgICAgICAgIHRoaXMuX2NoYW5nZUluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9jaGFuZ2VJblByb2dyZXNzID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNVVEMgPyBvZmZzZXQgOiBnZXREYXRlT2Zmc2V0KHRoaXMpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZ2V0U2V0Wm9uZSAoaW5wdXQsIGtlZXBMb2NhbFRpbWUpIHtcbiAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgaW5wdXQgPSAtaW5wdXQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnV0Y09mZnNldChpbnB1dCwga2VlcExvY2FsVGltZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIC10aGlzLnV0Y09mZnNldCgpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gc2V0T2Zmc2V0VG9VVEMgKGtlZXBMb2NhbFRpbWUpIHtcbiAgICByZXR1cm4gdGhpcy51dGNPZmZzZXQoMCwga2VlcExvY2FsVGltZSk7XG59XG5cbmZ1bmN0aW9uIHNldE9mZnNldFRvTG9jYWwgKGtlZXBMb2NhbFRpbWUpIHtcbiAgICBpZiAodGhpcy5faXNVVEMpIHtcbiAgICAgICAgdGhpcy51dGNPZmZzZXQoMCwga2VlcExvY2FsVGltZSk7XG4gICAgICAgIHRoaXMuX2lzVVRDID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGtlZXBMb2NhbFRpbWUpIHtcbiAgICAgICAgICAgIHRoaXMuc3VidHJhY3QoZ2V0RGF0ZU9mZnNldCh0aGlzKSwgJ20nKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gc2V0T2Zmc2V0VG9QYXJzZWRPZmZzZXQgKCkge1xuICAgIGlmICh0aGlzLl90em0gIT0gbnVsbCkge1xuICAgICAgICB0aGlzLnV0Y09mZnNldCh0aGlzLl90em0sIGZhbHNlLCB0cnVlKTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLl9pID09PSAnc3RyaW5nJykge1xuICAgICAgICB2YXIgdFpvbmUgPSBvZmZzZXRGcm9tU3RyaW5nKG1hdGNoT2Zmc2V0LCB0aGlzLl9pKTtcbiAgICAgICAgaWYgKHRab25lICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMudXRjT2Zmc2V0KHRab25lKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMudXRjT2Zmc2V0KDAsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBoYXNBbGlnbmVkSG91ck9mZnNldCAoaW5wdXQpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaW5wdXQgPSBpbnB1dCA/IGNyZWF0ZUxvY2FsKGlucHV0KS51dGNPZmZzZXQoKSA6IDA7XG5cbiAgICByZXR1cm4gKHRoaXMudXRjT2Zmc2V0KCkgLSBpbnB1dCkgJSA2MCA9PT0gMDtcbn1cblxuZnVuY3Rpb24gaXNEYXlsaWdodFNhdmluZ1RpbWUgKCkge1xuICAgIHJldHVybiAoXG4gICAgICAgIHRoaXMudXRjT2Zmc2V0KCkgPiB0aGlzLmNsb25lKCkubW9udGgoMCkudXRjT2Zmc2V0KCkgfHxcbiAgICAgICAgdGhpcy51dGNPZmZzZXQoKSA+IHRoaXMuY2xvbmUoKS5tb250aCg1KS51dGNPZmZzZXQoKVxuICAgICk7XG59XG5cbmZ1bmN0aW9uIGlzRGF5bGlnaHRTYXZpbmdUaW1lU2hpZnRlZCAoKSB7XG4gICAgaWYgKCFpc1VuZGVmaW5lZCh0aGlzLl9pc0RTVFNoaWZ0ZWQpKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc0RTVFNoaWZ0ZWQ7XG4gICAgfVxuXG4gICAgdmFyIGMgPSB7fTtcblxuICAgIGNvcHlDb25maWcoYywgdGhpcyk7XG4gICAgYyA9IHByZXBhcmVDb25maWcoYyk7XG5cbiAgICBpZiAoYy5fYSkge1xuICAgICAgICB2YXIgb3RoZXIgPSBjLl9pc1VUQyA/IGNyZWF0ZVVUQyhjLl9hKSA6IGNyZWF0ZUxvY2FsKGMuX2EpO1xuICAgICAgICB0aGlzLl9pc0RTVFNoaWZ0ZWQgPSB0aGlzLmlzVmFsaWQoKSAmJlxuICAgICAgICAgICAgY29tcGFyZUFycmF5cyhjLl9hLCBvdGhlci50b0FycmF5KCkpID4gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9pc0RTVFNoaWZ0ZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5faXNEU1RTaGlmdGVkO1xufVxuXG5mdW5jdGlvbiBpc0xvY2FsICgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyAhdGhpcy5faXNVVEMgOiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaXNVdGNPZmZzZXQgKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMuX2lzVVRDIDogZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGlzVXRjICgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyB0aGlzLl9pc1VUQyAmJiB0aGlzLl9vZmZzZXQgPT09IDAgOiBmYWxzZTtcbn1cblxuLy8gQVNQLk5FVCBqc29uIGRhdGUgZm9ybWF0IHJlZ2V4XG52YXIgYXNwTmV0UmVnZXggPSAvXihcXC18XFwrKT8oPzooXFxkKilbLiBdKT8oXFxkKylcXDooXFxkKykoPzpcXDooXFxkKykoXFwuXFxkKik/KT8kLztcblxuLy8gZnJvbSBodHRwOi8vZG9jcy5jbG9zdXJlLWxpYnJhcnkuZ29vZ2xlY29kZS5jb20vZ2l0L2Nsb3N1cmVfZ29vZ19kYXRlX2RhdGUuanMuc291cmNlLmh0bWxcbi8vIHNvbWV3aGF0IG1vcmUgaW4gbGluZSB3aXRoIDQuNC4zLjIgMjAwNCBzcGVjLCBidXQgYWxsb3dzIGRlY2ltYWwgYW55d2hlcmVcbi8vIGFuZCBmdXJ0aGVyIG1vZGlmaWVkIHRvIGFsbG93IGZvciBzdHJpbmdzIGNvbnRhaW5pbmcgYm90aCB3ZWVrIGFuZCBkYXlcbnZhciBpc29SZWdleCA9IC9eKC18XFwrKT9QKD86KFstK10/WzAtOSwuXSopWSk/KD86KFstK10/WzAtOSwuXSopTSk/KD86KFstK10/WzAtOSwuXSopVyk/KD86KFstK10/WzAtOSwuXSopRCk/KD86VCg/OihbLStdP1swLTksLl0qKUgpPyg/OihbLStdP1swLTksLl0qKU0pPyg/OihbLStdP1swLTksLl0qKVMpPyk/JC87XG5cbmZ1bmN0aW9uIGNyZWF0ZUR1cmF0aW9uIChpbnB1dCwga2V5KSB7XG4gICAgdmFyIGR1cmF0aW9uID0gaW5wdXQsXG4gICAgICAgIC8vIG1hdGNoaW5nIGFnYWluc3QgcmVnZXhwIGlzIGV4cGVuc2l2ZSwgZG8gaXQgb24gZGVtYW5kXG4gICAgICAgIG1hdGNoID0gbnVsbCxcbiAgICAgICAgc2lnbixcbiAgICAgICAgcmV0LFxuICAgICAgICBkaWZmUmVzO1xuXG4gICAgaWYgKGlzRHVyYXRpb24oaW5wdXQpKSB7XG4gICAgICAgIGR1cmF0aW9uID0ge1xuICAgICAgICAgICAgbXMgOiBpbnB1dC5fbWlsbGlzZWNvbmRzLFxuICAgICAgICAgICAgZCAgOiBpbnB1dC5fZGF5cyxcbiAgICAgICAgICAgIE0gIDogaW5wdXQuX21vbnRoc1xuICAgICAgICB9O1xuICAgIH0gZWxzZSBpZiAoaXNOdW1iZXIoaW5wdXQpKSB7XG4gICAgICAgIGR1cmF0aW9uID0ge307XG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgIGR1cmF0aW9uW2tleV0gPSBpbnB1dDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGR1cmF0aW9uLm1pbGxpc2Vjb25kcyA9IGlucHV0O1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmICghIShtYXRjaCA9IGFzcE5ldFJlZ2V4LmV4ZWMoaW5wdXQpKSkge1xuICAgICAgICBzaWduID0gKG1hdGNoWzFdID09PSAnLScpID8gLTEgOiAxO1xuICAgICAgICBkdXJhdGlvbiA9IHtcbiAgICAgICAgICAgIHkgIDogMCxcbiAgICAgICAgICAgIGQgIDogdG9JbnQobWF0Y2hbREFURV0pICAgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgIGggIDogdG9JbnQobWF0Y2hbSE9VUl0pICAgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgIG0gIDogdG9JbnQobWF0Y2hbTUlOVVRFXSkgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgIHMgIDogdG9JbnQobWF0Y2hbU0VDT05EXSkgICAgICAgICAgICAgICAgICAgICAgICogc2lnbixcbiAgICAgICAgICAgIG1zIDogdG9JbnQoYWJzUm91bmQobWF0Y2hbTUlMTElTRUNPTkRdICogMTAwMCkpICogc2lnbiAvLyB0aGUgbWlsbGlzZWNvbmQgZGVjaW1hbCBwb2ludCBpcyBpbmNsdWRlZCBpbiB0aGUgbWF0Y2hcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKCEhKG1hdGNoID0gaXNvUmVnZXguZXhlYyhpbnB1dCkpKSB7XG4gICAgICAgIHNpZ24gPSAobWF0Y2hbMV0gPT09ICctJykgPyAtMSA6IChtYXRjaFsxXSA9PT0gJysnKSA/IDEgOiAxO1xuICAgICAgICBkdXJhdGlvbiA9IHtcbiAgICAgICAgICAgIHkgOiBwYXJzZUlzbyhtYXRjaFsyXSwgc2lnbiksXG4gICAgICAgICAgICBNIDogcGFyc2VJc28obWF0Y2hbM10sIHNpZ24pLFxuICAgICAgICAgICAgdyA6IHBhcnNlSXNvKG1hdGNoWzRdLCBzaWduKSxcbiAgICAgICAgICAgIGQgOiBwYXJzZUlzbyhtYXRjaFs1XSwgc2lnbiksXG4gICAgICAgICAgICBoIDogcGFyc2VJc28obWF0Y2hbNl0sIHNpZ24pLFxuICAgICAgICAgICAgbSA6IHBhcnNlSXNvKG1hdGNoWzddLCBzaWduKSxcbiAgICAgICAgICAgIHMgOiBwYXJzZUlzbyhtYXRjaFs4XSwgc2lnbilcbiAgICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKGR1cmF0aW9uID09IG51bGwpIHsvLyBjaGVja3MgZm9yIG51bGwgb3IgdW5kZWZpbmVkXG4gICAgICAgIGR1cmF0aW9uID0ge307XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZHVyYXRpb24gPT09ICdvYmplY3QnICYmICgnZnJvbScgaW4gZHVyYXRpb24gfHwgJ3RvJyBpbiBkdXJhdGlvbikpIHtcbiAgICAgICAgZGlmZlJlcyA9IG1vbWVudHNEaWZmZXJlbmNlKGNyZWF0ZUxvY2FsKGR1cmF0aW9uLmZyb20pLCBjcmVhdGVMb2NhbChkdXJhdGlvbi50bykpO1xuXG4gICAgICAgIGR1cmF0aW9uID0ge307XG4gICAgICAgIGR1cmF0aW9uLm1zID0gZGlmZlJlcy5taWxsaXNlY29uZHM7XG4gICAgICAgIGR1cmF0aW9uLk0gPSBkaWZmUmVzLm1vbnRocztcbiAgICB9XG5cbiAgICByZXQgPSBuZXcgRHVyYXRpb24oZHVyYXRpb24pO1xuXG4gICAgaWYgKGlzRHVyYXRpb24oaW5wdXQpICYmIGhhc093blByb3AoaW5wdXQsICdfbG9jYWxlJykpIHtcbiAgICAgICAgcmV0Ll9sb2NhbGUgPSBpbnB1dC5fbG9jYWxlO1xuICAgIH1cblxuICAgIHJldHVybiByZXQ7XG59XG5cbmNyZWF0ZUR1cmF0aW9uLmZuID0gRHVyYXRpb24ucHJvdG90eXBlO1xuY3JlYXRlRHVyYXRpb24uaW52YWxpZCA9IGNyZWF0ZUludmFsaWQkMTtcblxuZnVuY3Rpb24gcGFyc2VJc28gKGlucCwgc2lnbikge1xuICAgIC8vIFdlJ2Qgbm9ybWFsbHkgdXNlIH5+aW5wIGZvciB0aGlzLCBidXQgdW5mb3J0dW5hdGVseSBpdCBhbHNvXG4gICAgLy8gY29udmVydHMgZmxvYXRzIHRvIGludHMuXG4gICAgLy8gaW5wIG1heSBiZSB1bmRlZmluZWQsIHNvIGNhcmVmdWwgY2FsbGluZyByZXBsYWNlIG9uIGl0LlxuICAgIHZhciByZXMgPSBpbnAgJiYgcGFyc2VGbG9hdChpbnAucmVwbGFjZSgnLCcsICcuJykpO1xuICAgIC8vIGFwcGx5IHNpZ24gd2hpbGUgd2UncmUgYXQgaXRcbiAgICByZXR1cm4gKGlzTmFOKHJlcykgPyAwIDogcmVzKSAqIHNpZ247XG59XG5cbmZ1bmN0aW9uIHBvc2l0aXZlTW9tZW50c0RpZmZlcmVuY2UoYmFzZSwgb3RoZXIpIHtcbiAgICB2YXIgcmVzID0ge21pbGxpc2Vjb25kczogMCwgbW9udGhzOiAwfTtcblxuICAgIHJlcy5tb250aHMgPSBvdGhlci5tb250aCgpIC0gYmFzZS5tb250aCgpICtcbiAgICAgICAgKG90aGVyLnllYXIoKSAtIGJhc2UueWVhcigpKSAqIDEyO1xuICAgIGlmIChiYXNlLmNsb25lKCkuYWRkKHJlcy5tb250aHMsICdNJykuaXNBZnRlcihvdGhlcikpIHtcbiAgICAgICAgLS1yZXMubW9udGhzO1xuICAgIH1cblxuICAgIHJlcy5taWxsaXNlY29uZHMgPSArb3RoZXIgLSArKGJhc2UuY2xvbmUoKS5hZGQocmVzLm1vbnRocywgJ00nKSk7XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG5mdW5jdGlvbiBtb21lbnRzRGlmZmVyZW5jZShiYXNlLCBvdGhlcikge1xuICAgIHZhciByZXM7XG4gICAgaWYgKCEoYmFzZS5pc1ZhbGlkKCkgJiYgb3RoZXIuaXNWYWxpZCgpKSkge1xuICAgICAgICByZXR1cm4ge21pbGxpc2Vjb25kczogMCwgbW9udGhzOiAwfTtcbiAgICB9XG5cbiAgICBvdGhlciA9IGNsb25lV2l0aE9mZnNldChvdGhlciwgYmFzZSk7XG4gICAgaWYgKGJhc2UuaXNCZWZvcmUob3RoZXIpKSB7XG4gICAgICAgIHJlcyA9IHBvc2l0aXZlTW9tZW50c0RpZmZlcmVuY2UoYmFzZSwgb3RoZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJlcyA9IHBvc2l0aXZlTW9tZW50c0RpZmZlcmVuY2Uob3RoZXIsIGJhc2UpO1xuICAgICAgICByZXMubWlsbGlzZWNvbmRzID0gLXJlcy5taWxsaXNlY29uZHM7XG4gICAgICAgIHJlcy5tb250aHMgPSAtcmVzLm1vbnRocztcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzO1xufVxuXG4vLyBUT0RPOiByZW1vdmUgJ25hbWUnIGFyZyBhZnRlciBkZXByZWNhdGlvbiBpcyByZW1vdmVkXG5mdW5jdGlvbiBjcmVhdGVBZGRlcihkaXJlY3Rpb24sIG5hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKHZhbCwgcGVyaW9kKSB7XG4gICAgICAgIHZhciBkdXIsIHRtcDtcbiAgICAgICAgLy9pbnZlcnQgdGhlIGFyZ3VtZW50cywgYnV0IGNvbXBsYWluIGFib3V0IGl0XG4gICAgICAgIGlmIChwZXJpb2QgIT09IG51bGwgJiYgIWlzTmFOKCtwZXJpb2QpKSB7XG4gICAgICAgICAgICBkZXByZWNhdGVTaW1wbGUobmFtZSwgJ21vbWVudCgpLicgKyBuYW1lICArICcocGVyaW9kLCBudW1iZXIpIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgbW9tZW50KCkuJyArIG5hbWUgKyAnKG51bWJlciwgcGVyaW9kKS4gJyArXG4gICAgICAgICAgICAnU2VlIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvYWRkLWludmVydGVkLXBhcmFtLyBmb3IgbW9yZSBpbmZvLicpO1xuICAgICAgICAgICAgdG1wID0gdmFsOyB2YWwgPSBwZXJpb2Q7IHBlcmlvZCA9IHRtcDtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbCA9IHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnID8gK3ZhbCA6IHZhbDtcbiAgICAgICAgZHVyID0gY3JlYXRlRHVyYXRpb24odmFsLCBwZXJpb2QpO1xuICAgICAgICBhZGRTdWJ0cmFjdCh0aGlzLCBkdXIsIGRpcmVjdGlvbik7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG59XG5cbmZ1bmN0aW9uIGFkZFN1YnRyYWN0IChtb20sIGR1cmF0aW9uLCBpc0FkZGluZywgdXBkYXRlT2Zmc2V0KSB7XG4gICAgdmFyIG1pbGxpc2Vjb25kcyA9IGR1cmF0aW9uLl9taWxsaXNlY29uZHMsXG4gICAgICAgIGRheXMgPSBhYnNSb3VuZChkdXJhdGlvbi5fZGF5cyksXG4gICAgICAgIG1vbnRocyA9IGFic1JvdW5kKGR1cmF0aW9uLl9tb250aHMpO1xuXG4gICAgaWYgKCFtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgIC8vIE5vIG9wXG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB1cGRhdGVPZmZzZXQgPSB1cGRhdGVPZmZzZXQgPT0gbnVsbCA/IHRydWUgOiB1cGRhdGVPZmZzZXQ7XG5cbiAgICBpZiAobW9udGhzKSB7XG4gICAgICAgIHNldE1vbnRoKG1vbSwgZ2V0KG1vbSwgJ01vbnRoJykgKyBtb250aHMgKiBpc0FkZGluZyk7XG4gICAgfVxuICAgIGlmIChkYXlzKSB7XG4gICAgICAgIHNldCQxKG1vbSwgJ0RhdGUnLCBnZXQobW9tLCAnRGF0ZScpICsgZGF5cyAqIGlzQWRkaW5nKTtcbiAgICB9XG4gICAgaWYgKG1pbGxpc2Vjb25kcykge1xuICAgICAgICBtb20uX2Quc2V0VGltZShtb20uX2QudmFsdWVPZigpICsgbWlsbGlzZWNvbmRzICogaXNBZGRpbmcpO1xuICAgIH1cbiAgICBpZiAodXBkYXRlT2Zmc2V0KSB7XG4gICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldChtb20sIGRheXMgfHwgbW9udGhzKTtcbiAgICB9XG59XG5cbnZhciBhZGQgICAgICA9IGNyZWF0ZUFkZGVyKDEsICdhZGQnKTtcbnZhciBzdWJ0cmFjdCA9IGNyZWF0ZUFkZGVyKC0xLCAnc3VidHJhY3QnKTtcblxuZnVuY3Rpb24gZ2V0Q2FsZW5kYXJGb3JtYXQobXlNb21lbnQsIG5vdykge1xuICAgIHZhciBkaWZmID0gbXlNb21lbnQuZGlmZihub3csICdkYXlzJywgdHJ1ZSk7XG4gICAgcmV0dXJuIGRpZmYgPCAtNiA/ICdzYW1lRWxzZScgOlxuICAgICAgICAgICAgZGlmZiA8IC0xID8gJ2xhc3RXZWVrJyA6XG4gICAgICAgICAgICBkaWZmIDwgMCA/ICdsYXN0RGF5JyA6XG4gICAgICAgICAgICBkaWZmIDwgMSA/ICdzYW1lRGF5JyA6XG4gICAgICAgICAgICBkaWZmIDwgMiA/ICduZXh0RGF5JyA6XG4gICAgICAgICAgICBkaWZmIDwgNyA/ICduZXh0V2VlaycgOiAnc2FtZUVsc2UnO1xufVxuXG5mdW5jdGlvbiBjYWxlbmRhciQxICh0aW1lLCBmb3JtYXRzKSB7XG4gICAgLy8gV2Ugd2FudCB0byBjb21wYXJlIHRoZSBzdGFydCBvZiB0b2RheSwgdnMgdGhpcy5cbiAgICAvLyBHZXR0aW5nIHN0YXJ0LW9mLXRvZGF5IGRlcGVuZHMgb24gd2hldGhlciB3ZSdyZSBsb2NhbC91dGMvb2Zmc2V0IG9yIG5vdC5cbiAgICB2YXIgbm93ID0gdGltZSB8fCBjcmVhdGVMb2NhbCgpLFxuICAgICAgICBzb2QgPSBjbG9uZVdpdGhPZmZzZXQobm93LCB0aGlzKS5zdGFydE9mKCdkYXknKSxcbiAgICAgICAgZm9ybWF0ID0gaG9va3MuY2FsZW5kYXJGb3JtYXQodGhpcywgc29kKSB8fCAnc2FtZUVsc2UnO1xuXG4gICAgdmFyIG91dHB1dCA9IGZvcm1hdHMgJiYgKGlzRnVuY3Rpb24oZm9ybWF0c1tmb3JtYXRdKSA/IGZvcm1hdHNbZm9ybWF0XS5jYWxsKHRoaXMsIG5vdykgOiBmb3JtYXRzW2Zvcm1hdF0pO1xuXG4gICAgcmV0dXJuIHRoaXMuZm9ybWF0KG91dHB1dCB8fCB0aGlzLmxvY2FsZURhdGEoKS5jYWxlbmRhcihmb3JtYXQsIHRoaXMsIGNyZWF0ZUxvY2FsKG5vdykpKTtcbn1cblxuZnVuY3Rpb24gY2xvbmUgKCkge1xuICAgIHJldHVybiBuZXcgTW9tZW50KHRoaXMpO1xufVxuXG5mdW5jdGlvbiBpc0FmdGVyIChpbnB1dCwgdW5pdHMpIHtcbiAgICB2YXIgbG9jYWxJbnB1dCA9IGlzTW9tZW50KGlucHV0KSA/IGlucHV0IDogY3JlYXRlTG9jYWwoaW5wdXQpO1xuICAgIGlmICghKHRoaXMuaXNWYWxpZCgpICYmIGxvY2FsSW5wdXQuaXNWYWxpZCgpKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHMoIWlzVW5kZWZpbmVkKHVuaXRzKSA/IHVuaXRzIDogJ21pbGxpc2Vjb25kJyk7XG4gICAgaWYgKHVuaXRzID09PSAnbWlsbGlzZWNvbmQnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlT2YoKSA+IGxvY2FsSW5wdXQudmFsdWVPZigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBsb2NhbElucHV0LnZhbHVlT2YoKSA8IHRoaXMuY2xvbmUoKS5zdGFydE9mKHVuaXRzKS52YWx1ZU9mKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc0JlZm9yZSAoaW5wdXQsIHVuaXRzKSB7XG4gICAgdmFyIGxvY2FsSW5wdXQgPSBpc01vbWVudChpbnB1dCkgPyBpbnB1dCA6IGNyZWF0ZUxvY2FsKGlucHV0KTtcbiAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbElucHV0LmlzVmFsaWQoKSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKCFpc1VuZGVmaW5lZCh1bml0cykgPyB1bml0cyA6ICdtaWxsaXNlY29uZCcpO1xuICAgIGlmICh1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZU9mKCkgPCBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmVuZE9mKHVuaXRzKS52YWx1ZU9mKCkgPCBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGlzQmV0d2VlbiAoZnJvbSwgdG8sIHVuaXRzLCBpbmNsdXNpdml0eSkge1xuICAgIGluY2x1c2l2aXR5ID0gaW5jbHVzaXZpdHkgfHwgJygpJztcbiAgICByZXR1cm4gKGluY2x1c2l2aXR5WzBdID09PSAnKCcgPyB0aGlzLmlzQWZ0ZXIoZnJvbSwgdW5pdHMpIDogIXRoaXMuaXNCZWZvcmUoZnJvbSwgdW5pdHMpKSAmJlxuICAgICAgICAoaW5jbHVzaXZpdHlbMV0gPT09ICcpJyA/IHRoaXMuaXNCZWZvcmUodG8sIHVuaXRzKSA6ICF0aGlzLmlzQWZ0ZXIodG8sIHVuaXRzKSk7XG59XG5cbmZ1bmN0aW9uIGlzU2FtZSAoaW5wdXQsIHVuaXRzKSB7XG4gICAgdmFyIGxvY2FsSW5wdXQgPSBpc01vbWVudChpbnB1dCkgPyBpbnB1dCA6IGNyZWF0ZUxvY2FsKGlucHV0KSxcbiAgICAgICAgaW5wdXRNcztcbiAgICBpZiAoISh0aGlzLmlzVmFsaWQoKSAmJiBsb2NhbElucHV0LmlzVmFsaWQoKSkpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzIHx8ICdtaWxsaXNlY29uZCcpO1xuICAgIGlmICh1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZU9mKCkgPT09IGxvY2FsSW5wdXQudmFsdWVPZigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGlucHV0TXMgPSBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2xvbmUoKS5zdGFydE9mKHVuaXRzKS52YWx1ZU9mKCkgPD0gaW5wdXRNcyAmJiBpbnB1dE1zIDw9IHRoaXMuY2xvbmUoKS5lbmRPZih1bml0cykudmFsdWVPZigpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNTYW1lT3JBZnRlciAoaW5wdXQsIHVuaXRzKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNTYW1lKGlucHV0LCB1bml0cykgfHwgdGhpcy5pc0FmdGVyKGlucHV0LHVuaXRzKTtcbn1cblxuZnVuY3Rpb24gaXNTYW1lT3JCZWZvcmUgKGlucHV0LCB1bml0cykge1xuICAgIHJldHVybiB0aGlzLmlzU2FtZShpbnB1dCwgdW5pdHMpIHx8IHRoaXMuaXNCZWZvcmUoaW5wdXQsdW5pdHMpO1xufVxuXG5mdW5jdGlvbiBkaWZmIChpbnB1dCwgdW5pdHMsIGFzRmxvYXQpIHtcbiAgICB2YXIgdGhhdCxcbiAgICAgICAgem9uZURlbHRhLFxuICAgICAgICBkZWx0YSwgb3V0cHV0O1xuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gTmFOO1xuICAgIH1cblxuICAgIHRoYXQgPSBjbG9uZVdpdGhPZmZzZXQoaW5wdXQsIHRoaXMpO1xuXG4gICAgaWYgKCF0aGF0LmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gTmFOO1xuICAgIH1cblxuICAgIHpvbmVEZWx0YSA9ICh0aGF0LnV0Y09mZnNldCgpIC0gdGhpcy51dGNPZmZzZXQoKSkgKiA2ZTQ7XG5cbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcblxuICAgIHN3aXRjaCAodW5pdHMpIHtcbiAgICAgICAgY2FzZSAneWVhcic6IG91dHB1dCA9IG1vbnRoRGlmZih0aGlzLCB0aGF0KSAvIDEyOyBicmVhaztcbiAgICAgICAgY2FzZSAnbW9udGgnOiBvdXRwdXQgPSBtb250aERpZmYodGhpcywgdGhhdCk7IGJyZWFrO1xuICAgICAgICBjYXNlICdxdWFydGVyJzogb3V0cHV0ID0gbW9udGhEaWZmKHRoaXMsIHRoYXQpIC8gMzsgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3NlY29uZCc6IG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyAxZTM7IGJyZWFrOyAvLyAxMDAwXG4gICAgICAgIGNhc2UgJ21pbnV0ZSc6IG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyA2ZTQ7IGJyZWFrOyAvLyAxMDAwICogNjBcbiAgICAgICAgY2FzZSAnaG91cic6IG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyAzNmU1OyBicmVhazsgLy8gMTAwMCAqIDYwICogNjBcbiAgICAgICAgY2FzZSAnZGF5Jzogb3V0cHV0ID0gKHRoaXMgLSB0aGF0IC0gem9uZURlbHRhKSAvIDg2NGU1OyBicmVhazsgLy8gMTAwMCAqIDYwICogNjAgKiAyNCwgbmVnYXRlIGRzdFxuICAgICAgICBjYXNlICd3ZWVrJzogb3V0cHV0ID0gKHRoaXMgLSB0aGF0IC0gem9uZURlbHRhKSAvIDYwNDhlNTsgYnJlYWs7IC8vIDEwMDAgKiA2MCAqIDYwICogMjQgKiA3LCBuZWdhdGUgZHN0XG4gICAgICAgIGRlZmF1bHQ6IG91dHB1dCA9IHRoaXMgLSB0aGF0O1xuICAgIH1cblxuICAgIHJldHVybiBhc0Zsb2F0ID8gb3V0cHV0IDogYWJzRmxvb3Iob3V0cHV0KTtcbn1cblxuZnVuY3Rpb24gbW9udGhEaWZmIChhLCBiKSB7XG4gICAgLy8gZGlmZmVyZW5jZSBpbiBtb250aHNcbiAgICB2YXIgd2hvbGVNb250aERpZmYgPSAoKGIueWVhcigpIC0gYS55ZWFyKCkpICogMTIpICsgKGIubW9udGgoKSAtIGEubW9udGgoKSksXG4gICAgICAgIC8vIGIgaXMgaW4gKGFuY2hvciAtIDEgbW9udGgsIGFuY2hvciArIDEgbW9udGgpXG4gICAgICAgIGFuY2hvciA9IGEuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYsICdtb250aHMnKSxcbiAgICAgICAgYW5jaG9yMiwgYWRqdXN0O1xuXG4gICAgaWYgKGIgLSBhbmNob3IgPCAwKSB7XG4gICAgICAgIGFuY2hvcjIgPSBhLmNsb25lKCkuYWRkKHdob2xlTW9udGhEaWZmIC0gMSwgJ21vbnRocycpO1xuICAgICAgICAvLyBsaW5lYXIgYWNyb3NzIHRoZSBtb250aFxuICAgICAgICBhZGp1c3QgPSAoYiAtIGFuY2hvcikgLyAoYW5jaG9yIC0gYW5jaG9yMik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgYW5jaG9yMiA9IGEuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYgKyAxLCAnbW9udGhzJyk7XG4gICAgICAgIC8vIGxpbmVhciBhY3Jvc3MgdGhlIG1vbnRoXG4gICAgICAgIGFkanVzdCA9IChiIC0gYW5jaG9yKSAvIChhbmNob3IyIC0gYW5jaG9yKTtcbiAgICB9XG5cbiAgICAvL2NoZWNrIGZvciBuZWdhdGl2ZSB6ZXJvLCByZXR1cm4gemVybyBpZiBuZWdhdGl2ZSB6ZXJvXG4gICAgcmV0dXJuIC0od2hvbGVNb250aERpZmYgKyBhZGp1c3QpIHx8IDA7XG59XG5cbmhvb2tzLmRlZmF1bHRGb3JtYXQgPSAnWVlZWS1NTS1ERFRISDptbTpzc1onO1xuaG9va3MuZGVmYXVsdEZvcm1hdFV0YyA9ICdZWVlZLU1NLUREVEhIOm1tOnNzW1pdJztcblxuZnVuY3Rpb24gdG9TdHJpbmcgKCkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKCkubG9jYWxlKCdlbicpLmZvcm1hdCgnZGRkIE1NTSBERCBZWVlZIEhIOm1tOnNzIFtHTVRdWlonKTtcbn1cblxuZnVuY3Rpb24gdG9JU09TdHJpbmcoa2VlcE9mZnNldCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHZhciB1dGMgPSBrZWVwT2Zmc2V0ICE9PSB0cnVlO1xuICAgIHZhciBtID0gdXRjID8gdGhpcy5jbG9uZSgpLnV0YygpIDogdGhpcztcbiAgICBpZiAobS55ZWFyKCkgPCAwIHx8IG0ueWVhcigpID4gOTk5OSkge1xuICAgICAgICByZXR1cm4gZm9ybWF0TW9tZW50KG0sIHV0YyA/ICdZWVlZWVktTU0tRERbVF1ISDptbTpzcy5TU1NbWl0nIDogJ1lZWVlZWS1NTS1ERFtUXUhIOm1tOnNzLlNTU1onKTtcbiAgICB9XG4gICAgaWYgKGlzRnVuY3Rpb24oRGF0ZS5wcm90b3R5cGUudG9JU09TdHJpbmcpKSB7XG4gICAgICAgIC8vIG5hdGl2ZSBpbXBsZW1lbnRhdGlvbiBpcyB+NTB4IGZhc3RlciwgdXNlIGl0IHdoZW4gd2UgY2FuXG4gICAgICAgIGlmICh1dGMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUodGhpcy5fZC52YWx1ZU9mKCkpLnRvSVNPU3RyaW5nKCkucmVwbGFjZSgnWicsIGZvcm1hdE1vbWVudChtLCAnWicpKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZm9ybWF0TW9tZW50KG0sIHV0YyA/ICdZWVlZLU1NLUREW1RdSEg6bW06c3MuU1NTW1pdJyA6ICdZWVlZLU1NLUREW1RdSEg6bW06c3MuU1NTWicpO1xufVxuXG4vKipcbiAqIFJldHVybiBhIGh1bWFuIHJlYWRhYmxlIHJlcHJlc2VudGF0aW9uIG9mIGEgbW9tZW50IHRoYXQgY2FuXG4gKiBhbHNvIGJlIGV2YWx1YXRlZCB0byBnZXQgYSBuZXcgbW9tZW50IHdoaWNoIGlzIHRoZSBzYW1lXG4gKlxuICogQGxpbmsgaHR0cHM6Ly9ub2RlanMub3JnL2Rpc3QvbGF0ZXN0L2RvY3MvYXBpL3V0aWwuaHRtbCN1dGlsX2N1c3RvbV9pbnNwZWN0X2Z1bmN0aW9uX29uX29iamVjdHNcbiAqL1xuZnVuY3Rpb24gaW5zcGVjdCAoKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICByZXR1cm4gJ21vbWVudC5pbnZhbGlkKC8qICcgKyB0aGlzLl9pICsgJyAqLyknO1xuICAgIH1cbiAgICB2YXIgZnVuYyA9ICdtb21lbnQnO1xuICAgIHZhciB6b25lID0gJyc7XG4gICAgaWYgKCF0aGlzLmlzTG9jYWwoKSkge1xuICAgICAgICBmdW5jID0gdGhpcy51dGNPZmZzZXQoKSA9PT0gMCA/ICdtb21lbnQudXRjJyA6ICdtb21lbnQucGFyc2Vab25lJztcbiAgICAgICAgem9uZSA9ICdaJztcbiAgICB9XG4gICAgdmFyIHByZWZpeCA9ICdbJyArIGZ1bmMgKyAnKFwiXSc7XG4gICAgdmFyIHllYXIgPSAoMCA8PSB0aGlzLnllYXIoKSAmJiB0aGlzLnllYXIoKSA8PSA5OTk5KSA/ICdZWVlZJyA6ICdZWVlZWVknO1xuICAgIHZhciBkYXRldGltZSA9ICctTU0tRERbVF1ISDptbTpzcy5TU1MnO1xuICAgIHZhciBzdWZmaXggPSB6b25lICsgJ1tcIildJztcblxuICAgIHJldHVybiB0aGlzLmZvcm1hdChwcmVmaXggKyB5ZWFyICsgZGF0ZXRpbWUgKyBzdWZmaXgpO1xufVxuXG5mdW5jdGlvbiBmb3JtYXQgKGlucHV0U3RyaW5nKSB7XG4gICAgaWYgKCFpbnB1dFN0cmluZykge1xuICAgICAgICBpbnB1dFN0cmluZyA9IHRoaXMuaXNVdGMoKSA/IGhvb2tzLmRlZmF1bHRGb3JtYXRVdGMgOiBob29rcy5kZWZhdWx0Rm9ybWF0O1xuICAgIH1cbiAgICB2YXIgb3V0cHV0ID0gZm9ybWF0TW9tZW50KHRoaXMsIGlucHV0U3RyaW5nKTtcbiAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkucG9zdGZvcm1hdChvdXRwdXQpO1xufVxuXG5mdW5jdGlvbiBmcm9tICh0aW1lLCB3aXRob3V0U3VmZml4KSB7XG4gICAgaWYgKHRoaXMuaXNWYWxpZCgpICYmXG4gICAgICAgICAgICAoKGlzTW9tZW50KHRpbWUpICYmIHRpbWUuaXNWYWxpZCgpKSB8fFxuICAgICAgICAgICAgIGNyZWF0ZUxvY2FsKHRpbWUpLmlzVmFsaWQoKSkpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHt0bzogdGhpcywgZnJvbTogdGltZX0pLmxvY2FsZSh0aGlzLmxvY2FsZSgpKS5odW1hbml6ZSghd2l0aG91dFN1ZmZpeCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBmcm9tTm93ICh3aXRob3V0U3VmZml4KSB7XG4gICAgcmV0dXJuIHRoaXMuZnJvbShjcmVhdGVMb2NhbCgpLCB3aXRob3V0U3VmZml4KTtcbn1cblxuZnVuY3Rpb24gdG8gKHRpbWUsIHdpdGhvdXRTdWZmaXgpIHtcbiAgICBpZiAodGhpcy5pc1ZhbGlkKCkgJiZcbiAgICAgICAgICAgICgoaXNNb21lbnQodGltZSkgJiYgdGltZS5pc1ZhbGlkKCkpIHx8XG4gICAgICAgICAgICAgY3JlYXRlTG9jYWwodGltZSkuaXNWYWxpZCgpKSkge1xuICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oe2Zyb206IHRoaXMsIHRvOiB0aW1lfSkubG9jYWxlKHRoaXMubG9jYWxlKCkpLmh1bWFuaXplKCF3aXRob3V0U3VmZml4KTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkuaW52YWxpZERhdGUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIHRvTm93ICh3aXRob3V0U3VmZml4KSB7XG4gICAgcmV0dXJuIHRoaXMudG8oY3JlYXRlTG9jYWwoKSwgd2l0aG91dFN1ZmZpeCk7XG59XG5cbi8vIElmIHBhc3NlZCBhIGxvY2FsZSBrZXksIGl0IHdpbGwgc2V0IHRoZSBsb2NhbGUgZm9yIHRoaXNcbi8vIGluc3RhbmNlLiAgT3RoZXJ3aXNlLCBpdCB3aWxsIHJldHVybiB0aGUgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vIHZhcmlhYmxlcyBmb3IgdGhpcyBpbnN0YW5jZS5cbmZ1bmN0aW9uIGxvY2FsZSAoa2V5KSB7XG4gICAgdmFyIG5ld0xvY2FsZURhdGE7XG5cbiAgICBpZiAoa2V5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvY2FsZS5fYWJicjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBuZXdMb2NhbGVEYXRhID0gZ2V0TG9jYWxlKGtleSk7XG4gICAgICAgIGlmIChuZXdMb2NhbGVEYXRhICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMuX2xvY2FsZSA9IG5ld0xvY2FsZURhdGE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxufVxuXG52YXIgbGFuZyA9IGRlcHJlY2F0ZShcbiAgICAnbW9tZW50KCkubGFuZygpIGlzIGRlcHJlY2F0ZWQuIEluc3RlYWQsIHVzZSBtb21lbnQoKS5sb2NhbGVEYXRhKCkgdG8gZ2V0IHRoZSBsYW5ndWFnZSBjb25maWd1cmF0aW9uLiBVc2UgbW9tZW50KCkubG9jYWxlKCkgdG8gY2hhbmdlIGxhbmd1YWdlcy4nLFxuICAgIGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGUoa2V5KTtcbiAgICAgICAgfVxuICAgIH1cbik7XG5cbmZ1bmN0aW9uIGxvY2FsZURhdGEgKCkge1xuICAgIHJldHVybiB0aGlzLl9sb2NhbGU7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0T2YgKHVuaXRzKSB7XG4gICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG4gICAgLy8gdGhlIGZvbGxvd2luZyBzd2l0Y2ggaW50ZW50aW9uYWxseSBvbWl0cyBicmVhayBrZXl3b3Jkc1xuICAgIC8vIHRvIHV0aWxpemUgZmFsbGluZyB0aHJvdWdoIHRoZSBjYXNlcy5cbiAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgIGNhc2UgJ3llYXInOlxuICAgICAgICAgICAgdGhpcy5tb250aCgwKTtcbiAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgICAgY2FzZSAncXVhcnRlcic6XG4gICAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgICAgICAgIHRoaXMuZGF0ZSgxKTtcbiAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgICAgY2FzZSAnd2Vlayc6XG4gICAgICAgIGNhc2UgJ2lzb1dlZWsnOlxuICAgICAgICBjYXNlICdkYXknOlxuICAgICAgICBjYXNlICdkYXRlJzpcbiAgICAgICAgICAgIHRoaXMuaG91cnMoMCk7XG4gICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICAgIGNhc2UgJ2hvdXInOlxuICAgICAgICAgICAgdGhpcy5taW51dGVzKDApO1xuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICBjYXNlICdtaW51dGUnOlxuICAgICAgICAgICAgdGhpcy5zZWNvbmRzKDApO1xuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICBjYXNlICdzZWNvbmQnOlxuICAgICAgICAgICAgdGhpcy5taWxsaXNlY29uZHMoMCk7XG4gICAgfVxuXG4gICAgLy8gd2Vla3MgYXJlIGEgc3BlY2lhbCBjYXNlXG4gICAgaWYgKHVuaXRzID09PSAnd2VlaycpIHtcbiAgICAgICAgdGhpcy53ZWVrZGF5KDApO1xuICAgIH1cbiAgICBpZiAodW5pdHMgPT09ICdpc29XZWVrJykge1xuICAgICAgICB0aGlzLmlzb1dlZWtkYXkoMSk7XG4gICAgfVxuXG4gICAgLy8gcXVhcnRlcnMgYXJlIGFsc28gc3BlY2lhbFxuICAgIGlmICh1bml0cyA9PT0gJ3F1YXJ0ZXInKSB7XG4gICAgICAgIHRoaXMubW9udGgoTWF0aC5mbG9vcih0aGlzLm1vbnRoKCkgLyAzKSAqIDMpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBlbmRPZiAodW5pdHMpIHtcbiAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICBpZiAodW5pdHMgPT09IHVuZGVmaW5lZCB8fCB1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyAnZGF0ZScgaXMgYW4gYWxpYXMgZm9yICdkYXknLCBzbyBpdCBzaG91bGQgYmUgY29uc2lkZXJlZCBhcyBzdWNoLlxuICAgIGlmICh1bml0cyA9PT0gJ2RhdGUnKSB7XG4gICAgICAgIHVuaXRzID0gJ2RheSc7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuc3RhcnRPZih1bml0cykuYWRkKDEsICh1bml0cyA9PT0gJ2lzb1dlZWsnID8gJ3dlZWsnIDogdW5pdHMpKS5zdWJ0cmFjdCgxLCAnbXMnKTtcbn1cblxuZnVuY3Rpb24gdmFsdWVPZiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2QudmFsdWVPZigpIC0gKCh0aGlzLl9vZmZzZXQgfHwgMCkgKiA2MDAwMCk7XG59XG5cbmZ1bmN0aW9uIHVuaXggKCkge1xuICAgIHJldHVybiBNYXRoLmZsb29yKHRoaXMudmFsdWVPZigpIC8gMTAwMCk7XG59XG5cbmZ1bmN0aW9uIHRvRGF0ZSAoKSB7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHRoaXMudmFsdWVPZigpKTtcbn1cblxuZnVuY3Rpb24gdG9BcnJheSAoKSB7XG4gICAgdmFyIG0gPSB0aGlzO1xuICAgIHJldHVybiBbbS55ZWFyKCksIG0ubW9udGgoKSwgbS5kYXRlKCksIG0uaG91cigpLCBtLm1pbnV0ZSgpLCBtLnNlY29uZCgpLCBtLm1pbGxpc2Vjb25kKCldO1xufVxuXG5mdW5jdGlvbiB0b09iamVjdCAoKSB7XG4gICAgdmFyIG0gPSB0aGlzO1xuICAgIHJldHVybiB7XG4gICAgICAgIHllYXJzOiBtLnllYXIoKSxcbiAgICAgICAgbW9udGhzOiBtLm1vbnRoKCksXG4gICAgICAgIGRhdGU6IG0uZGF0ZSgpLFxuICAgICAgICBob3VyczogbS5ob3VycygpLFxuICAgICAgICBtaW51dGVzOiBtLm1pbnV0ZXMoKSxcbiAgICAgICAgc2Vjb25kczogbS5zZWNvbmRzKCksXG4gICAgICAgIG1pbGxpc2Vjb25kczogbS5taWxsaXNlY29uZHMoKVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIHRvSlNPTiAoKSB7XG4gICAgLy8gbmV3IERhdGUoTmFOKS50b0pTT04oKSA9PT0gbnVsbFxuICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMudG9JU09TdHJpbmcoKSA6IG51bGw7XG59XG5cbmZ1bmN0aW9uIGlzVmFsaWQkMiAoKSB7XG4gICAgcmV0dXJuIGlzVmFsaWQodGhpcyk7XG59XG5cbmZ1bmN0aW9uIHBhcnNpbmdGbGFncyAoKSB7XG4gICAgcmV0dXJuIGV4dGVuZCh7fSwgZ2V0UGFyc2luZ0ZsYWdzKHRoaXMpKTtcbn1cblxuZnVuY3Rpb24gaW52YWxpZEF0ICgpIHtcbiAgICByZXR1cm4gZ2V0UGFyc2luZ0ZsYWdzKHRoaXMpLm92ZXJmbG93O1xufVxuXG5mdW5jdGlvbiBjcmVhdGlvbkRhdGEoKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgaW5wdXQ6IHRoaXMuX2ksXG4gICAgICAgIGZvcm1hdDogdGhpcy5fZixcbiAgICAgICAgbG9jYWxlOiB0aGlzLl9sb2NhbGUsXG4gICAgICAgIGlzVVRDOiB0aGlzLl9pc1VUQyxcbiAgICAgICAgc3RyaWN0OiB0aGlzLl9zdHJpY3RcbiAgICB9O1xufVxuXG4vLyBGT1JNQVRUSU5HXG5cbmFkZEZvcm1hdFRva2VuKDAsIFsnZ2cnLCAyXSwgMCwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLndlZWtZZWFyKCkgJSAxMDA7XG59KTtcblxuYWRkRm9ybWF0VG9rZW4oMCwgWydHRycsIDJdLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNvV2Vla1llYXIoKSAlIDEwMDtcbn0pO1xuXG5mdW5jdGlvbiBhZGRXZWVrWWVhckZvcm1hdFRva2VuICh0b2tlbiwgZ2V0dGVyKSB7XG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgW3Rva2VuLCB0b2tlbi5sZW5ndGhdLCAwLCBnZXR0ZXIpO1xufVxuXG5hZGRXZWVrWWVhckZvcm1hdFRva2VuKCdnZ2dnJywgICAgICd3ZWVrWWVhcicpO1xuYWRkV2Vla1llYXJGb3JtYXRUb2tlbignZ2dnZ2cnLCAgICAnd2Vla1llYXInKTtcbmFkZFdlZWtZZWFyRm9ybWF0VG9rZW4oJ0dHR0cnLCAgJ2lzb1dlZWtZZWFyJyk7XG5hZGRXZWVrWWVhckZvcm1hdFRva2VuKCdHR0dHRycsICdpc29XZWVrWWVhcicpO1xuXG4vLyBBTElBU0VTXG5cbmFkZFVuaXRBbGlhcygnd2Vla1llYXInLCAnZ2cnKTtcbmFkZFVuaXRBbGlhcygnaXNvV2Vla1llYXInLCAnR0cnKTtcblxuLy8gUFJJT1JJVFlcblxuYWRkVW5pdFByaW9yaXR5KCd3ZWVrWWVhcicsIDEpO1xuYWRkVW5pdFByaW9yaXR5KCdpc29XZWVrWWVhcicsIDEpO1xuXG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbignRycsICAgICAgbWF0Y2hTaWduZWQpO1xuYWRkUmVnZXhUb2tlbignZycsICAgICAgbWF0Y2hTaWduZWQpO1xuYWRkUmVnZXhUb2tlbignR0cnLCAgICAgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignZ2cnLCAgICAgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignR0dHRycsICAgbWF0Y2gxdG80LCBtYXRjaDQpO1xuYWRkUmVnZXhUb2tlbignZ2dnZycsICAgbWF0Y2gxdG80LCBtYXRjaDQpO1xuYWRkUmVnZXhUb2tlbignR0dHR0cnLCAgbWF0Y2gxdG82LCBtYXRjaDYpO1xuYWRkUmVnZXhUb2tlbignZ2dnZ2cnLCAgbWF0Y2gxdG82LCBtYXRjaDYpO1xuXG5hZGRXZWVrUGFyc2VUb2tlbihbJ2dnZ2cnLCAnZ2dnZ2cnLCAnR0dHRycsICdHR0dHRyddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICB3ZWVrW3Rva2VuLnN1YnN0cigwLCAyKV0gPSB0b0ludChpbnB1dCk7XG59KTtcblxuYWRkV2Vla1BhcnNlVG9rZW4oWydnZycsICdHRyddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICB3ZWVrW3Rva2VuXSA9IGhvb2tzLnBhcnNlVHdvRGlnaXRZZWFyKGlucHV0KTtcbn0pO1xuXG4vLyBNT01FTlRTXG5cbmZ1bmN0aW9uIGdldFNldFdlZWtZZWFyIChpbnB1dCkge1xuICAgIHJldHVybiBnZXRTZXRXZWVrWWVhckhlbHBlci5jYWxsKHRoaXMsXG4gICAgICAgICAgICBpbnB1dCxcbiAgICAgICAgICAgIHRoaXMud2VlaygpLFxuICAgICAgICAgICAgdGhpcy53ZWVrZGF5KCksXG4gICAgICAgICAgICB0aGlzLmxvY2FsZURhdGEoKS5fd2Vlay5kb3csXG4gICAgICAgICAgICB0aGlzLmxvY2FsZURhdGEoKS5fd2Vlay5kb3kpO1xufVxuXG5mdW5jdGlvbiBnZXRTZXRJU09XZWVrWWVhciAoaW5wdXQpIHtcbiAgICByZXR1cm4gZ2V0U2V0V2Vla1llYXJIZWxwZXIuY2FsbCh0aGlzLFxuICAgICAgICAgICAgaW5wdXQsIHRoaXMuaXNvV2VlaygpLCB0aGlzLmlzb1dlZWtkYXkoKSwgMSwgNCk7XG59XG5cbmZ1bmN0aW9uIGdldElTT1dlZWtzSW5ZZWFyICgpIHtcbiAgICByZXR1cm4gd2Vla3NJblllYXIodGhpcy55ZWFyKCksIDEsIDQpO1xufVxuXG5mdW5jdGlvbiBnZXRXZWVrc0luWWVhciAoKSB7XG4gICAgdmFyIHdlZWtJbmZvID0gdGhpcy5sb2NhbGVEYXRhKCkuX3dlZWs7XG4gICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMueWVhcigpLCB3ZWVrSW5mby5kb3csIHdlZWtJbmZvLmRveSk7XG59XG5cbmZ1bmN0aW9uIGdldFNldFdlZWtZZWFySGVscGVyKGlucHV0LCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgIHZhciB3ZWVrc1RhcmdldDtcbiAgICBpZiAoaW5wdXQgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gd2Vla09mWWVhcih0aGlzLCBkb3csIGRveSkueWVhcjtcbiAgICB9IGVsc2Uge1xuICAgICAgICB3ZWVrc1RhcmdldCA9IHdlZWtzSW5ZZWFyKGlucHV0LCBkb3csIGRveSk7XG4gICAgICAgIGlmICh3ZWVrID4gd2Vla3NUYXJnZXQpIHtcbiAgICAgICAgICAgIHdlZWsgPSB3ZWVrc1RhcmdldDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2V0V2Vla0FsbC5jYWxsKHRoaXMsIGlucHV0LCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBzZXRXZWVrQWxsKHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSkge1xuICAgIHZhciBkYXlPZlllYXJEYXRhID0gZGF5T2ZZZWFyRnJvbVdlZWtzKHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSksXG4gICAgICAgIGRhdGUgPSBjcmVhdGVVVENEYXRlKGRheU9mWWVhckRhdGEueWVhciwgMCwgZGF5T2ZZZWFyRGF0YS5kYXlPZlllYXIpO1xuXG4gICAgdGhpcy55ZWFyKGRhdGUuZ2V0VVRDRnVsbFllYXIoKSk7XG4gICAgdGhpcy5tb250aChkYXRlLmdldFVUQ01vbnRoKCkpO1xuICAgIHRoaXMuZGF0ZShkYXRlLmdldFVUQ0RhdGUoKSk7XG4gICAgcmV0dXJuIHRoaXM7XG59XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ1EnLCAwLCAnUW8nLCAncXVhcnRlcicpO1xuXG4vLyBBTElBU0VTXG5cbmFkZFVuaXRBbGlhcygncXVhcnRlcicsICdRJyk7XG5cbi8vIFBSSU9SSVRZXG5cbmFkZFVuaXRQcmlvcml0eSgncXVhcnRlcicsIDcpO1xuXG4vLyBQQVJTSU5HXG5cbmFkZFJlZ2V4VG9rZW4oJ1EnLCBtYXRjaDEpO1xuYWRkUGFyc2VUb2tlbignUScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICBhcnJheVtNT05USF0gPSAodG9JbnQoaW5wdXQpIC0gMSkgKiAzO1xufSk7XG5cbi8vIE1PTUVOVFNcblxuZnVuY3Rpb24gZ2V0U2V0UXVhcnRlciAoaW5wdXQpIHtcbiAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IE1hdGguY2VpbCgodGhpcy5tb250aCgpICsgMSkgLyAzKSA6IHRoaXMubW9udGgoKGlucHV0IC0gMSkgKiAzICsgdGhpcy5tb250aCgpICUgMyk7XG59XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ0QnLCBbJ0REJywgMl0sICdEbycsICdkYXRlJyk7XG5cbi8vIEFMSUFTRVNcblxuYWRkVW5pdEFsaWFzKCdkYXRlJywgJ0QnKTtcblxuLy8gUFJJT1JPSVRZXG5hZGRVbml0UHJpb3JpdHkoJ2RhdGUnLCA5KTtcblxuLy8gUEFSU0lOR1xuXG5hZGRSZWdleFRva2VuKCdEJywgIG1hdGNoMXRvMik7XG5hZGRSZWdleFRva2VuKCdERCcsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbmFkZFJlZ2V4VG9rZW4oJ0RvJywgZnVuY3Rpb24gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICAvLyBUT0RPOiBSZW1vdmUgXCJvcmRpbmFsUGFyc2VcIiBmYWxsYmFjayBpbiBuZXh0IG1ham9yIHJlbGVhc2UuXG4gICAgcmV0dXJuIGlzU3RyaWN0ID9cbiAgICAgIChsb2NhbGUuX2RheU9mTW9udGhPcmRpbmFsUGFyc2UgfHwgbG9jYWxlLl9vcmRpbmFsUGFyc2UpIDpcbiAgICAgIGxvY2FsZS5fZGF5T2ZNb250aE9yZGluYWxQYXJzZUxlbmllbnQ7XG59KTtcblxuYWRkUGFyc2VUb2tlbihbJ0QnLCAnREQnXSwgREFURSk7XG5hZGRQYXJzZVRva2VuKCdEbycsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICBhcnJheVtEQVRFXSA9IHRvSW50KGlucHV0Lm1hdGNoKG1hdGNoMXRvMilbMF0pO1xufSk7XG5cbi8vIE1PTUVOVFNcblxudmFyIGdldFNldERheU9mTW9udGggPSBtYWtlR2V0U2V0KCdEYXRlJywgdHJ1ZSk7XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ0RERCcsIFsnRERERCcsIDNdLCAnREREbycsICdkYXlPZlllYXInKTtcblxuLy8gQUxJQVNFU1xuXG5hZGRVbml0QWxpYXMoJ2RheU9mWWVhcicsICdEREQnKTtcblxuLy8gUFJJT1JJVFlcbmFkZFVuaXRQcmlvcml0eSgnZGF5T2ZZZWFyJywgNCk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbignREREJywgIG1hdGNoMXRvMyk7XG5hZGRSZWdleFRva2VuKCdEREREJywgbWF0Y2gzKTtcbmFkZFBhcnNlVG9rZW4oWydEREQnLCAnRERERCddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICBjb25maWcuX2RheU9mWWVhciA9IHRvSW50KGlucHV0KTtcbn0pO1xuXG4vLyBIRUxQRVJTXG5cbi8vIE1PTUVOVFNcblxuZnVuY3Rpb24gZ2V0U2V0RGF5T2ZZZWFyIChpbnB1dCkge1xuICAgIHZhciBkYXlPZlllYXIgPSBNYXRoLnJvdW5kKCh0aGlzLmNsb25lKCkuc3RhcnRPZignZGF5JykgLSB0aGlzLmNsb25lKCkuc3RhcnRPZigneWVhcicpKSAvIDg2NGU1KSArIDE7XG4gICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyBkYXlPZlllYXIgOiB0aGlzLmFkZCgoaW5wdXQgLSBkYXlPZlllYXIpLCAnZCcpO1xufVxuXG4vLyBGT1JNQVRUSU5HXG5cbmFkZEZvcm1hdFRva2VuKCdtJywgWydtbScsIDJdLCAwLCAnbWludXRlJyk7XG5cbi8vIEFMSUFTRVNcblxuYWRkVW5pdEFsaWFzKCdtaW51dGUnLCAnbScpO1xuXG4vLyBQUklPUklUWVxuXG5hZGRVbml0UHJpb3JpdHkoJ21pbnV0ZScsIDE0KTtcblxuLy8gUEFSU0lOR1xuXG5hZGRSZWdleFRva2VuKCdtJywgIG1hdGNoMXRvMik7XG5hZGRSZWdleFRva2VuKCdtbScsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbmFkZFBhcnNlVG9rZW4oWydtJywgJ21tJ10sIE1JTlVURSk7XG5cbi8vIE1PTUVOVFNcblxudmFyIGdldFNldE1pbnV0ZSA9IG1ha2VHZXRTZXQoJ01pbnV0ZXMnLCBmYWxzZSk7XG5cbi8vIEZPUk1BVFRJTkdcblxuYWRkRm9ybWF0VG9rZW4oJ3MnLCBbJ3NzJywgMl0sIDAsICdzZWNvbmQnKTtcblxuLy8gQUxJQVNFU1xuXG5hZGRVbml0QWxpYXMoJ3NlY29uZCcsICdzJyk7XG5cbi8vIFBSSU9SSVRZXG5cbmFkZFVuaXRQcmlvcml0eSgnc2Vjb25kJywgMTUpO1xuXG4vLyBQQVJTSU5HXG5cbmFkZFJlZ2V4VG9rZW4oJ3MnLCAgbWF0Y2gxdG8yKTtcbmFkZFJlZ2V4VG9rZW4oJ3NzJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuYWRkUGFyc2VUb2tlbihbJ3MnLCAnc3MnXSwgU0VDT05EKTtcblxuLy8gTU9NRU5UU1xuXG52YXIgZ2V0U2V0U2Vjb25kID0gbWFrZUdldFNldCgnU2Vjb25kcycsIGZhbHNlKTtcblxuLy8gRk9STUFUVElOR1xuXG5hZGRGb3JtYXRUb2tlbignUycsIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gfn4odGhpcy5taWxsaXNlY29uZCgpIC8gMTAwKTtcbn0pO1xuXG5hZGRGb3JtYXRUb2tlbigwLCBbJ1NTJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gfn4odGhpcy5taWxsaXNlY29uZCgpIC8gMTApO1xufSk7XG5cbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTJywgM10sIDAsICdtaWxsaXNlY29uZCcpO1xuYWRkRm9ybWF0VG9rZW4oMCwgWydTU1NTJywgNF0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTA7XG59KTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1MnLCA1XSwgMCwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDA7XG59KTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTJywgNl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTAwMDtcbn0pO1xuYWRkRm9ybWF0VG9rZW4oMCwgWydTU1NTU1NTJywgN10sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTAwMDA7XG59KTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTU1MnLCA4XSwgMCwgZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLm1pbGxpc2Vjb25kKCkgKiAxMDAwMDA7XG59KTtcbmFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTU1NTJywgOV0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTAwMDAwMDtcbn0pO1xuXG5cbi8vIEFMSUFTRVNcblxuYWRkVW5pdEFsaWFzKCdtaWxsaXNlY29uZCcsICdtcycpO1xuXG4vLyBQUklPUklUWVxuXG5hZGRVbml0UHJpb3JpdHkoJ21pbGxpc2Vjb25kJywgMTYpO1xuXG4vLyBQQVJTSU5HXG5cbmFkZFJlZ2V4VG9rZW4oJ1MnLCAgICBtYXRjaDF0bzMsIG1hdGNoMSk7XG5hZGRSZWdleFRva2VuKCdTUycsICAgbWF0Y2gxdG8zLCBtYXRjaDIpO1xuYWRkUmVnZXhUb2tlbignU1NTJywgIG1hdGNoMXRvMywgbWF0Y2gzKTtcblxudmFyIHRva2VuO1xuZm9yICh0b2tlbiA9ICdTU1NTJzsgdG9rZW4ubGVuZ3RoIDw9IDk7IHRva2VuICs9ICdTJykge1xuICAgIGFkZFJlZ2V4VG9rZW4odG9rZW4sIG1hdGNoVW5zaWduZWQpO1xufVxuXG5mdW5jdGlvbiBwYXJzZU1zKGlucHV0LCBhcnJheSkge1xuICAgIGFycmF5W01JTExJU0VDT05EXSA9IHRvSW50KCgnMC4nICsgaW5wdXQpICogMTAwMCk7XG59XG5cbmZvciAodG9rZW4gPSAnUyc7IHRva2VuLmxlbmd0aCA8PSA5OyB0b2tlbiArPSAnUycpIHtcbiAgICBhZGRQYXJzZVRva2VuKHRva2VuLCBwYXJzZU1zKTtcbn1cbi8vIE1PTUVOVFNcblxudmFyIGdldFNldE1pbGxpc2Vjb25kID0gbWFrZUdldFNldCgnTWlsbGlzZWNvbmRzJywgZmFsc2UpO1xuXG4vLyBGT1JNQVRUSU5HXG5cbmFkZEZvcm1hdFRva2VuKCd6JywgIDAsIDAsICd6b25lQWJicicpO1xuYWRkRm9ybWF0VG9rZW4oJ3p6JywgMCwgMCwgJ3pvbmVOYW1lJyk7XG5cbi8vIE1PTUVOVFNcblxuZnVuY3Rpb24gZ2V0Wm9uZUFiYnIgKCkge1xuICAgIHJldHVybiB0aGlzLl9pc1VUQyA/ICdVVEMnIDogJyc7XG59XG5cbmZ1bmN0aW9uIGdldFpvbmVOYW1lICgpIHtcbiAgICByZXR1cm4gdGhpcy5faXNVVEMgPyAnQ29vcmRpbmF0ZWQgVW5pdmVyc2FsIFRpbWUnIDogJyc7XG59XG5cbnZhciBwcm90byA9IE1vbWVudC5wcm90b3R5cGU7XG5cbnByb3RvLmFkZCAgICAgICAgICAgICAgID0gYWRkO1xucHJvdG8uY2FsZW5kYXIgICAgICAgICAgPSBjYWxlbmRhciQxO1xucHJvdG8uY2xvbmUgICAgICAgICAgICAgPSBjbG9uZTtcbnByb3RvLmRpZmYgICAgICAgICAgICAgID0gZGlmZjtcbnByb3RvLmVuZE9mICAgICAgICAgICAgID0gZW5kT2Y7XG5wcm90by5mb3JtYXQgICAgICAgICAgICA9IGZvcm1hdDtcbnByb3RvLmZyb20gICAgICAgICAgICAgID0gZnJvbTtcbnByb3RvLmZyb21Ob3cgICAgICAgICAgID0gZnJvbU5vdztcbnByb3RvLnRvICAgICAgICAgICAgICAgID0gdG87XG5wcm90by50b05vdyAgICAgICAgICAgICA9IHRvTm93O1xucHJvdG8uZ2V0ICAgICAgICAgICAgICAgPSBzdHJpbmdHZXQ7XG5wcm90by5pbnZhbGlkQXQgICAgICAgICA9IGludmFsaWRBdDtcbnByb3RvLmlzQWZ0ZXIgICAgICAgICAgID0gaXNBZnRlcjtcbnByb3RvLmlzQmVmb3JlICAgICAgICAgID0gaXNCZWZvcmU7XG5wcm90by5pc0JldHdlZW4gICAgICAgICA9IGlzQmV0d2VlbjtcbnByb3RvLmlzU2FtZSAgICAgICAgICAgID0gaXNTYW1lO1xucHJvdG8uaXNTYW1lT3JBZnRlciAgICAgPSBpc1NhbWVPckFmdGVyO1xucHJvdG8uaXNTYW1lT3JCZWZvcmUgICAgPSBpc1NhbWVPckJlZm9yZTtcbnByb3RvLmlzVmFsaWQgICAgICAgICAgID0gaXNWYWxpZCQyO1xucHJvdG8ubGFuZyAgICAgICAgICAgICAgPSBsYW5nO1xucHJvdG8ubG9jYWxlICAgICAgICAgICAgPSBsb2NhbGU7XG5wcm90by5sb2NhbGVEYXRhICAgICAgICA9IGxvY2FsZURhdGE7XG5wcm90by5tYXggICAgICAgICAgICAgICA9IHByb3RvdHlwZU1heDtcbnByb3RvLm1pbiAgICAgICAgICAgICAgID0gcHJvdG90eXBlTWluO1xucHJvdG8ucGFyc2luZ0ZsYWdzICAgICAgPSBwYXJzaW5nRmxhZ3M7XG5wcm90by5zZXQgICAgICAgICAgICAgICA9IHN0cmluZ1NldDtcbnByb3RvLnN0YXJ0T2YgICAgICAgICAgID0gc3RhcnRPZjtcbnByb3RvLnN1YnRyYWN0ICAgICAgICAgID0gc3VidHJhY3Q7XG5wcm90by50b0FycmF5ICAgICAgICAgICA9IHRvQXJyYXk7XG5wcm90by50b09iamVjdCAgICAgICAgICA9IHRvT2JqZWN0O1xucHJvdG8udG9EYXRlICAgICAgICAgICAgPSB0b0RhdGU7XG5wcm90by50b0lTT1N0cmluZyAgICAgICA9IHRvSVNPU3RyaW5nO1xucHJvdG8uaW5zcGVjdCAgICAgICAgICAgPSBpbnNwZWN0O1xucHJvdG8udG9KU09OICAgICAgICAgICAgPSB0b0pTT047XG5wcm90by50b1N0cmluZyAgICAgICAgICA9IHRvU3RyaW5nO1xucHJvdG8udW5peCAgICAgICAgICAgICAgPSB1bml4O1xucHJvdG8udmFsdWVPZiAgICAgICAgICAgPSB2YWx1ZU9mO1xucHJvdG8uY3JlYXRpb25EYXRhICAgICAgPSBjcmVhdGlvbkRhdGE7XG5cbi8vIFllYXJcbnByb3RvLnllYXIgICAgICAgPSBnZXRTZXRZZWFyO1xucHJvdG8uaXNMZWFwWWVhciA9IGdldElzTGVhcFllYXI7XG5cbi8vIFdlZWsgWWVhclxucHJvdG8ud2Vla1llYXIgICAgPSBnZXRTZXRXZWVrWWVhcjtcbnByb3RvLmlzb1dlZWtZZWFyID0gZ2V0U2V0SVNPV2Vla1llYXI7XG5cbi8vIFF1YXJ0ZXJcbnByb3RvLnF1YXJ0ZXIgPSBwcm90by5xdWFydGVycyA9IGdldFNldFF1YXJ0ZXI7XG5cbi8vIE1vbnRoXG5wcm90by5tb250aCAgICAgICA9IGdldFNldE1vbnRoO1xucHJvdG8uZGF5c0luTW9udGggPSBnZXREYXlzSW5Nb250aDtcblxuLy8gV2Vla1xucHJvdG8ud2VlayAgICAgICAgICAgPSBwcm90by53ZWVrcyAgICAgICAgPSBnZXRTZXRXZWVrO1xucHJvdG8uaXNvV2VlayAgICAgICAgPSBwcm90by5pc29XZWVrcyAgICAgPSBnZXRTZXRJU09XZWVrO1xucHJvdG8ud2Vla3NJblllYXIgICAgPSBnZXRXZWVrc0luWWVhcjtcbnByb3RvLmlzb1dlZWtzSW5ZZWFyID0gZ2V0SVNPV2Vla3NJblllYXI7XG5cbi8vIERheVxucHJvdG8uZGF0ZSAgICAgICA9IGdldFNldERheU9mTW9udGg7XG5wcm90by5kYXkgICAgICAgID0gcHJvdG8uZGF5cyAgICAgICAgICAgICA9IGdldFNldERheU9mV2VlaztcbnByb3RvLndlZWtkYXkgICAgPSBnZXRTZXRMb2NhbGVEYXlPZldlZWs7XG5wcm90by5pc29XZWVrZGF5ID0gZ2V0U2V0SVNPRGF5T2ZXZWVrO1xucHJvdG8uZGF5T2ZZZWFyICA9IGdldFNldERheU9mWWVhcjtcblxuLy8gSG91clxucHJvdG8uaG91ciA9IHByb3RvLmhvdXJzID0gZ2V0U2V0SG91cjtcblxuLy8gTWludXRlXG5wcm90by5taW51dGUgPSBwcm90by5taW51dGVzID0gZ2V0U2V0TWludXRlO1xuXG4vLyBTZWNvbmRcbnByb3RvLnNlY29uZCA9IHByb3RvLnNlY29uZHMgPSBnZXRTZXRTZWNvbmQ7XG5cbi8vIE1pbGxpc2Vjb25kXG5wcm90by5taWxsaXNlY29uZCA9IHByb3RvLm1pbGxpc2Vjb25kcyA9IGdldFNldE1pbGxpc2Vjb25kO1xuXG4vLyBPZmZzZXRcbnByb3RvLnV0Y09mZnNldCAgICAgICAgICAgID0gZ2V0U2V0T2Zmc2V0O1xucHJvdG8udXRjICAgICAgICAgICAgICAgICAgPSBzZXRPZmZzZXRUb1VUQztcbnByb3RvLmxvY2FsICAgICAgICAgICAgICAgID0gc2V0T2Zmc2V0VG9Mb2NhbDtcbnByb3RvLnBhcnNlWm9uZSAgICAgICAgICAgID0gc2V0T2Zmc2V0VG9QYXJzZWRPZmZzZXQ7XG5wcm90by5oYXNBbGlnbmVkSG91ck9mZnNldCA9IGhhc0FsaWduZWRIb3VyT2Zmc2V0O1xucHJvdG8uaXNEU1QgICAgICAgICAgICAgICAgPSBpc0RheWxpZ2h0U2F2aW5nVGltZTtcbnByb3RvLmlzTG9jYWwgICAgICAgICAgICAgID0gaXNMb2NhbDtcbnByb3RvLmlzVXRjT2Zmc2V0ICAgICAgICAgID0gaXNVdGNPZmZzZXQ7XG5wcm90by5pc1V0YyAgICAgICAgICAgICAgICA9IGlzVXRjO1xucHJvdG8uaXNVVEMgICAgICAgICAgICAgICAgPSBpc1V0YztcblxuLy8gVGltZXpvbmVcbnByb3RvLnpvbmVBYmJyID0gZ2V0Wm9uZUFiYnI7XG5wcm90by56b25lTmFtZSA9IGdldFpvbmVOYW1lO1xuXG4vLyBEZXByZWNhdGlvbnNcbnByb3RvLmRhdGVzICA9IGRlcHJlY2F0ZSgnZGF0ZXMgYWNjZXNzb3IgaXMgZGVwcmVjYXRlZC4gVXNlIGRhdGUgaW5zdGVhZC4nLCBnZXRTZXREYXlPZk1vbnRoKTtcbnByb3RvLm1vbnRocyA9IGRlcHJlY2F0ZSgnbW9udGhzIGFjY2Vzc29yIGlzIGRlcHJlY2F0ZWQuIFVzZSBtb250aCBpbnN0ZWFkJywgZ2V0U2V0TW9udGgpO1xucHJvdG8ueWVhcnMgID0gZGVwcmVjYXRlKCd5ZWFycyBhY2Nlc3NvciBpcyBkZXByZWNhdGVkLiBVc2UgeWVhciBpbnN0ZWFkJywgZ2V0U2V0WWVhcik7XG5wcm90by56b25lICAgPSBkZXByZWNhdGUoJ21vbWVudCgpLnpvbmUgaXMgZGVwcmVjYXRlZCwgdXNlIG1vbWVudCgpLnV0Y09mZnNldCBpbnN0ZWFkLiBodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL3pvbmUvJywgZ2V0U2V0Wm9uZSk7XG5wcm90by5pc0RTVFNoaWZ0ZWQgPSBkZXByZWNhdGUoJ2lzRFNUU2hpZnRlZCBpcyBkZXByZWNhdGVkLiBTZWUgaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9kc3Qtc2hpZnRlZC8gZm9yIG1vcmUgaW5mb3JtYXRpb24nLCBpc0RheWxpZ2h0U2F2aW5nVGltZVNoaWZ0ZWQpO1xuXG5mdW5jdGlvbiBjcmVhdGVVbml4IChpbnB1dCkge1xuICAgIHJldHVybiBjcmVhdGVMb2NhbChpbnB1dCAqIDEwMDApO1xufVxuXG5mdW5jdGlvbiBjcmVhdGVJblpvbmUgKCkge1xuICAgIHJldHVybiBjcmVhdGVMb2NhbC5hcHBseShudWxsLCBhcmd1bWVudHMpLnBhcnNlWm9uZSgpO1xufVxuXG5mdW5jdGlvbiBwcmVQYXJzZVBvc3RGb3JtYXQgKHN0cmluZykge1xuICAgIHJldHVybiBzdHJpbmc7XG59XG5cbnZhciBwcm90byQxID0gTG9jYWxlLnByb3RvdHlwZTtcblxucHJvdG8kMS5jYWxlbmRhciAgICAgICAgPSBjYWxlbmRhcjtcbnByb3RvJDEubG9uZ0RhdGVGb3JtYXQgID0gbG9uZ0RhdGVGb3JtYXQ7XG5wcm90byQxLmludmFsaWREYXRlICAgICA9IGludmFsaWREYXRlO1xucHJvdG8kMS5vcmRpbmFsICAgICAgICAgPSBvcmRpbmFsO1xucHJvdG8kMS5wcmVwYXJzZSAgICAgICAgPSBwcmVQYXJzZVBvc3RGb3JtYXQ7XG5wcm90byQxLnBvc3Rmb3JtYXQgICAgICA9IHByZVBhcnNlUG9zdEZvcm1hdDtcbnByb3RvJDEucmVsYXRpdmVUaW1lICAgID0gcmVsYXRpdmVUaW1lO1xucHJvdG8kMS5wYXN0RnV0dXJlICAgICAgPSBwYXN0RnV0dXJlO1xucHJvdG8kMS5zZXQgICAgICAgICAgICAgPSBzZXQ7XG5cbi8vIE1vbnRoXG5wcm90byQxLm1vbnRocyAgICAgICAgICAgID0gICAgICAgIGxvY2FsZU1vbnRocztcbnByb3RvJDEubW9udGhzU2hvcnQgICAgICAgPSAgICAgICAgbG9jYWxlTW9udGhzU2hvcnQ7XG5wcm90byQxLm1vbnRoc1BhcnNlICAgICAgID0gICAgICAgIGxvY2FsZU1vbnRoc1BhcnNlO1xucHJvdG8kMS5tb250aHNSZWdleCAgICAgICA9IG1vbnRoc1JlZ2V4O1xucHJvdG8kMS5tb250aHNTaG9ydFJlZ2V4ICA9IG1vbnRoc1Nob3J0UmVnZXg7XG5cbi8vIFdlZWtcbnByb3RvJDEud2VlayA9IGxvY2FsZVdlZWs7XG5wcm90byQxLmZpcnN0RGF5T2ZZZWFyID0gbG9jYWxlRmlyc3REYXlPZlllYXI7XG5wcm90byQxLmZpcnN0RGF5T2ZXZWVrID0gbG9jYWxlRmlyc3REYXlPZldlZWs7XG5cbi8vIERheSBvZiBXZWVrXG5wcm90byQxLndlZWtkYXlzICAgICAgID0gICAgICAgIGxvY2FsZVdlZWtkYXlzO1xucHJvdG8kMS53ZWVrZGF5c01pbiAgICA9ICAgICAgICBsb2NhbGVXZWVrZGF5c01pbjtcbnByb3RvJDEud2Vla2RheXNTaG9ydCAgPSAgICAgICAgbG9jYWxlV2Vla2RheXNTaG9ydDtcbnByb3RvJDEud2Vla2RheXNQYXJzZSAgPSAgICAgICAgbG9jYWxlV2Vla2RheXNQYXJzZTtcblxucHJvdG8kMS53ZWVrZGF5c1JlZ2V4ICAgICAgID0gICAgICAgIHdlZWtkYXlzUmVnZXg7XG5wcm90byQxLndlZWtkYXlzU2hvcnRSZWdleCAgPSAgICAgICAgd2Vla2RheXNTaG9ydFJlZ2V4O1xucHJvdG8kMS53ZWVrZGF5c01pblJlZ2V4ICAgID0gICAgICAgIHdlZWtkYXlzTWluUmVnZXg7XG5cbi8vIEhvdXJzXG5wcm90byQxLmlzUE0gPSBsb2NhbGVJc1BNO1xucHJvdG8kMS5tZXJpZGllbSA9IGxvY2FsZU1lcmlkaWVtO1xuXG5mdW5jdGlvbiBnZXQkMSAoZm9ybWF0LCBpbmRleCwgZmllbGQsIHNldHRlcikge1xuICAgIHZhciBsb2NhbGUgPSBnZXRMb2NhbGUoKTtcbiAgICB2YXIgdXRjID0gY3JlYXRlVVRDKCkuc2V0KHNldHRlciwgaW5kZXgpO1xuICAgIHJldHVybiBsb2NhbGVbZmllbGRdKHV0YywgZm9ybWF0KTtcbn1cblxuZnVuY3Rpb24gbGlzdE1vbnRoc0ltcGwgKGZvcm1hdCwgaW5kZXgsIGZpZWxkKSB7XG4gICAgaWYgKGlzTnVtYmVyKGZvcm1hdCkpIHtcbiAgICAgICAgaW5kZXggPSBmb3JtYXQ7XG4gICAgICAgIGZvcm1hdCA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBmb3JtYXQgPSBmb3JtYXQgfHwgJyc7XG5cbiAgICBpZiAoaW5kZXggIT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZ2V0JDEoZm9ybWF0LCBpbmRleCwgZmllbGQsICdtb250aCcpO1xuICAgIH1cblxuICAgIHZhciBpO1xuICAgIHZhciBvdXQgPSBbXTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICBvdXRbaV0gPSBnZXQkMShmb3JtYXQsIGksIGZpZWxkLCAnbW9udGgnKTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbn1cblxuLy8gKClcbi8vICg1KVxuLy8gKGZtdCwgNSlcbi8vIChmbXQpXG4vLyAodHJ1ZSlcbi8vICh0cnVlLCA1KVxuLy8gKHRydWUsIGZtdCwgNSlcbi8vICh0cnVlLCBmbXQpXG5mdW5jdGlvbiBsaXN0V2Vla2RheXNJbXBsIChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgsIGZpZWxkKSB7XG4gICAgaWYgKHR5cGVvZiBsb2NhbGVTb3J0ZWQgPT09ICdib29sZWFuJykge1xuICAgICAgICBpZiAoaXNOdW1iZXIoZm9ybWF0KSkge1xuICAgICAgICAgICAgaW5kZXggPSBmb3JtYXQ7XG4gICAgICAgICAgICBmb3JtYXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBmb3JtYXQgPSBmb3JtYXQgfHwgJyc7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZm9ybWF0ID0gbG9jYWxlU29ydGVkO1xuICAgICAgICBpbmRleCA9IGZvcm1hdDtcbiAgICAgICAgbG9jYWxlU29ydGVkID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGlzTnVtYmVyKGZvcm1hdCkpIHtcbiAgICAgICAgICAgIGluZGV4ID0gZm9ybWF0O1xuICAgICAgICAgICAgZm9ybWF0ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9ybWF0ID0gZm9ybWF0IHx8ICcnO1xuICAgIH1cblxuICAgIHZhciBsb2NhbGUgPSBnZXRMb2NhbGUoKSxcbiAgICAgICAgc2hpZnQgPSBsb2NhbGVTb3J0ZWQgPyBsb2NhbGUuX3dlZWsuZG93IDogMDtcblxuICAgIGlmIChpbmRleCAhPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBnZXQkMShmb3JtYXQsIChpbmRleCArIHNoaWZ0KSAlIDcsIGZpZWxkLCAnZGF5Jyk7XG4gICAgfVxuXG4gICAgdmFyIGk7XG4gICAgdmFyIG91dCA9IFtdO1xuICAgIGZvciAoaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgb3V0W2ldID0gZ2V0JDEoZm9ybWF0LCAoaSArIHNoaWZ0KSAlIDcsIGZpZWxkLCAnZGF5Jyk7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIGxpc3RNb250aHMgKGZvcm1hdCwgaW5kZXgpIHtcbiAgICByZXR1cm4gbGlzdE1vbnRoc0ltcGwoZm9ybWF0LCBpbmRleCwgJ21vbnRocycpO1xufVxuXG5mdW5jdGlvbiBsaXN0TW9udGhzU2hvcnQgKGZvcm1hdCwgaW5kZXgpIHtcbiAgICByZXR1cm4gbGlzdE1vbnRoc0ltcGwoZm9ybWF0LCBpbmRleCwgJ21vbnRoc1Nob3J0Jyk7XG59XG5cbmZ1bmN0aW9uIGxpc3RXZWVrZGF5cyAobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4KSB7XG4gICAgcmV0dXJuIGxpc3RXZWVrZGF5c0ltcGwobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4LCAnd2Vla2RheXMnKTtcbn1cblxuZnVuY3Rpb24gbGlzdFdlZWtkYXlzU2hvcnQgKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCkge1xuICAgIHJldHVybiBsaXN0V2Vla2RheXNJbXBsKGxvY2FsZVNvcnRlZCwgZm9ybWF0LCBpbmRleCwgJ3dlZWtkYXlzU2hvcnQnKTtcbn1cblxuZnVuY3Rpb24gbGlzdFdlZWtkYXlzTWluIChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgpIHtcbiAgICByZXR1cm4gbGlzdFdlZWtkYXlzSW1wbChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgsICd3ZWVrZGF5c01pbicpO1xufVxuXG5nZXRTZXRHbG9iYWxMb2NhbGUoJ2VuJywge1xuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSh0aHxzdHxuZHxyZCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBvdXRwdXQgPSAodG9JbnQobnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgKGIgPT09IDEpID8gJ3N0JyA6XG4gICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgIH1cbn0pO1xuXG4vLyBTaWRlIGVmZmVjdCBpbXBvcnRzXG5ob29rcy5sYW5nID0gZGVwcmVjYXRlKCdtb21lbnQubGFuZyBpcyBkZXByZWNhdGVkLiBVc2UgbW9tZW50LmxvY2FsZSBpbnN0ZWFkLicsIGdldFNldEdsb2JhbExvY2FsZSk7XG5ob29rcy5sYW5nRGF0YSA9IGRlcHJlY2F0ZSgnbW9tZW50LmxhbmdEYXRhIGlzIGRlcHJlY2F0ZWQuIFVzZSBtb21lbnQubG9jYWxlRGF0YSBpbnN0ZWFkLicsIGdldExvY2FsZSk7XG5cbnZhciBtYXRoQWJzID0gTWF0aC5hYnM7XG5cbmZ1bmN0aW9uIGFicyAoKSB7XG4gICAgdmFyIGRhdGEgICAgICAgICAgID0gdGhpcy5fZGF0YTtcblxuICAgIHRoaXMuX21pbGxpc2Vjb25kcyA9IG1hdGhBYnModGhpcy5fbWlsbGlzZWNvbmRzKTtcbiAgICB0aGlzLl9kYXlzICAgICAgICAgPSBtYXRoQWJzKHRoaXMuX2RheXMpO1xuICAgIHRoaXMuX21vbnRocyAgICAgICA9IG1hdGhBYnModGhpcy5fbW9udGhzKTtcblxuICAgIGRhdGEubWlsbGlzZWNvbmRzICA9IG1hdGhBYnMoZGF0YS5taWxsaXNlY29uZHMpO1xuICAgIGRhdGEuc2Vjb25kcyAgICAgICA9IG1hdGhBYnMoZGF0YS5zZWNvbmRzKTtcbiAgICBkYXRhLm1pbnV0ZXMgICAgICAgPSBtYXRoQWJzKGRhdGEubWludXRlcyk7XG4gICAgZGF0YS5ob3VycyAgICAgICAgID0gbWF0aEFicyhkYXRhLmhvdXJzKTtcbiAgICBkYXRhLm1vbnRocyAgICAgICAgPSBtYXRoQWJzKGRhdGEubW9udGhzKTtcbiAgICBkYXRhLnllYXJzICAgICAgICAgPSBtYXRoQWJzKGRhdGEueWVhcnMpO1xuXG4gICAgcmV0dXJuIHRoaXM7XG59XG5cbmZ1bmN0aW9uIGFkZFN1YnRyYWN0JDEgKGR1cmF0aW9uLCBpbnB1dCwgdmFsdWUsIGRpcmVjdGlvbikge1xuICAgIHZhciBvdGhlciA9IGNyZWF0ZUR1cmF0aW9uKGlucHV0LCB2YWx1ZSk7XG5cbiAgICBkdXJhdGlvbi5fbWlsbGlzZWNvbmRzICs9IGRpcmVjdGlvbiAqIG90aGVyLl9taWxsaXNlY29uZHM7XG4gICAgZHVyYXRpb24uX2RheXMgICAgICAgICArPSBkaXJlY3Rpb24gKiBvdGhlci5fZGF5cztcbiAgICBkdXJhdGlvbi5fbW9udGhzICAgICAgICs9IGRpcmVjdGlvbiAqIG90aGVyLl9tb250aHM7XG5cbiAgICByZXR1cm4gZHVyYXRpb24uX2J1YmJsZSgpO1xufVxuXG4vLyBzdXBwb3J0cyBvbmx5IDIuMC1zdHlsZSBhZGQoMSwgJ3MnKSBvciBhZGQoZHVyYXRpb24pXG5mdW5jdGlvbiBhZGQkMSAoaW5wdXQsIHZhbHVlKSB7XG4gICAgcmV0dXJuIGFkZFN1YnRyYWN0JDEodGhpcywgaW5wdXQsIHZhbHVlLCAxKTtcbn1cblxuLy8gc3VwcG9ydHMgb25seSAyLjAtc3R5bGUgc3VidHJhY3QoMSwgJ3MnKSBvciBzdWJ0cmFjdChkdXJhdGlvbilcbmZ1bmN0aW9uIHN1YnRyYWN0JDEgKGlucHV0LCB2YWx1ZSkge1xuICAgIHJldHVybiBhZGRTdWJ0cmFjdCQxKHRoaXMsIGlucHV0LCB2YWx1ZSwgLTEpO1xufVxuXG5mdW5jdGlvbiBhYnNDZWlsIChudW1iZXIpIHtcbiAgICBpZiAobnVtYmVyIDwgMCkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcihudW1iZXIpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBNYXRoLmNlaWwobnVtYmVyKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGJ1YmJsZSAoKSB7XG4gICAgdmFyIG1pbGxpc2Vjb25kcyA9IHRoaXMuX21pbGxpc2Vjb25kcztcbiAgICB2YXIgZGF5cyAgICAgICAgID0gdGhpcy5fZGF5cztcbiAgICB2YXIgbW9udGhzICAgICAgID0gdGhpcy5fbW9udGhzO1xuICAgIHZhciBkYXRhICAgICAgICAgPSB0aGlzLl9kYXRhO1xuICAgIHZhciBzZWNvbmRzLCBtaW51dGVzLCBob3VycywgeWVhcnMsIG1vbnRoc0Zyb21EYXlzO1xuXG4gICAgLy8gaWYgd2UgaGF2ZSBhIG1peCBvZiBwb3NpdGl2ZSBhbmQgbmVnYXRpdmUgdmFsdWVzLCBidWJibGUgZG93biBmaXJzdFxuICAgIC8vIGNoZWNrOiBodHRwczovL2dpdGh1Yi5jb20vbW9tZW50L21vbWVudC9pc3N1ZXMvMjE2NlxuICAgIGlmICghKChtaWxsaXNlY29uZHMgPj0gMCAmJiBkYXlzID49IDAgJiYgbW9udGhzID49IDApIHx8XG4gICAgICAgICAgICAobWlsbGlzZWNvbmRzIDw9IDAgJiYgZGF5cyA8PSAwICYmIG1vbnRocyA8PSAwKSkpIHtcbiAgICAgICAgbWlsbGlzZWNvbmRzICs9IGFic0NlaWwobW9udGhzVG9EYXlzKG1vbnRocykgKyBkYXlzKSAqIDg2NGU1O1xuICAgICAgICBkYXlzID0gMDtcbiAgICAgICAgbW9udGhzID0gMDtcbiAgICB9XG5cbiAgICAvLyBUaGUgZm9sbG93aW5nIGNvZGUgYnViYmxlcyB1cCB2YWx1ZXMsIHNlZSB0aGUgdGVzdHMgZm9yXG4gICAgLy8gZXhhbXBsZXMgb2Ygd2hhdCB0aGF0IG1lYW5zLlxuICAgIGRhdGEubWlsbGlzZWNvbmRzID0gbWlsbGlzZWNvbmRzICUgMTAwMDtcblxuICAgIHNlY29uZHMgICAgICAgICAgID0gYWJzRmxvb3IobWlsbGlzZWNvbmRzIC8gMTAwMCk7XG4gICAgZGF0YS5zZWNvbmRzICAgICAgPSBzZWNvbmRzICUgNjA7XG5cbiAgICBtaW51dGVzICAgICAgICAgICA9IGFic0Zsb29yKHNlY29uZHMgLyA2MCk7XG4gICAgZGF0YS5taW51dGVzICAgICAgPSBtaW51dGVzICUgNjA7XG5cbiAgICBob3VycyAgICAgICAgICAgICA9IGFic0Zsb29yKG1pbnV0ZXMgLyA2MCk7XG4gICAgZGF0YS5ob3VycyAgICAgICAgPSBob3VycyAlIDI0O1xuXG4gICAgZGF5cyArPSBhYnNGbG9vcihob3VycyAvIDI0KTtcblxuICAgIC8vIGNvbnZlcnQgZGF5cyB0byBtb250aHNcbiAgICBtb250aHNGcm9tRGF5cyA9IGFic0Zsb29yKGRheXNUb01vbnRocyhkYXlzKSk7XG4gICAgbW9udGhzICs9IG1vbnRoc0Zyb21EYXlzO1xuICAgIGRheXMgLT0gYWJzQ2VpbChtb250aHNUb0RheXMobW9udGhzRnJvbURheXMpKTtcblxuICAgIC8vIDEyIG1vbnRocyAtPiAxIHllYXJcbiAgICB5ZWFycyA9IGFic0Zsb29yKG1vbnRocyAvIDEyKTtcbiAgICBtb250aHMgJT0gMTI7XG5cbiAgICBkYXRhLmRheXMgICA9IGRheXM7XG4gICAgZGF0YS5tb250aHMgPSBtb250aHM7XG4gICAgZGF0YS55ZWFycyAgPSB5ZWFycztcblxuICAgIHJldHVybiB0aGlzO1xufVxuXG5mdW5jdGlvbiBkYXlzVG9Nb250aHMgKGRheXMpIHtcbiAgICAvLyA0MDAgeWVhcnMgaGF2ZSAxNDYwOTcgZGF5cyAodGFraW5nIGludG8gYWNjb3VudCBsZWFwIHllYXIgcnVsZXMpXG4gICAgLy8gNDAwIHllYXJzIGhhdmUgMTIgbW9udGhzID09PSA0ODAwXG4gICAgcmV0dXJuIGRheXMgKiA0ODAwIC8gMTQ2MDk3O1xufVxuXG5mdW5jdGlvbiBtb250aHNUb0RheXMgKG1vbnRocykge1xuICAgIC8vIHRoZSByZXZlcnNlIG9mIGRheXNUb01vbnRoc1xuICAgIHJldHVybiBtb250aHMgKiAxNDYwOTcgLyA0ODAwO1xufVxuXG5mdW5jdGlvbiBhcyAodW5pdHMpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgIHJldHVybiBOYU47XG4gICAgfVxuICAgIHZhciBkYXlzO1xuICAgIHZhciBtb250aHM7XG4gICAgdmFyIG1pbGxpc2Vjb25kcyA9IHRoaXMuX21pbGxpc2Vjb25kcztcblxuICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuXG4gICAgaWYgKHVuaXRzID09PSAnbW9udGgnIHx8IHVuaXRzID09PSAneWVhcicpIHtcbiAgICAgICAgZGF5cyAgID0gdGhpcy5fZGF5cyAgICsgbWlsbGlzZWNvbmRzIC8gODY0ZTU7XG4gICAgICAgIG1vbnRocyA9IHRoaXMuX21vbnRocyArIGRheXNUb01vbnRocyhkYXlzKTtcbiAgICAgICAgcmV0dXJuIHVuaXRzID09PSAnbW9udGgnID8gbW9udGhzIDogbW9udGhzIC8gMTI7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaGFuZGxlIG1pbGxpc2Vjb25kcyBzZXBhcmF0ZWx5IGJlY2F1c2Ugb2YgZmxvYXRpbmcgcG9pbnQgbWF0aCBlcnJvcnMgKGlzc3VlICMxODY3KVxuICAgICAgICBkYXlzID0gdGhpcy5fZGF5cyArIE1hdGgucm91bmQobW9udGhzVG9EYXlzKHRoaXMuX21vbnRocykpO1xuICAgICAgICBzd2l0Y2ggKHVuaXRzKSB7XG4gICAgICAgICAgICBjYXNlICd3ZWVrJyAgIDogcmV0dXJuIGRheXMgLyA3ICAgICArIG1pbGxpc2Vjb25kcyAvIDYwNDhlNTtcbiAgICAgICAgICAgIGNhc2UgJ2RheScgICAgOiByZXR1cm4gZGF5cyAgICAgICAgICsgbWlsbGlzZWNvbmRzIC8gODY0ZTU7XG4gICAgICAgICAgICBjYXNlICdob3VyJyAgIDogcmV0dXJuIGRheXMgKiAyNCAgICArIG1pbGxpc2Vjb25kcyAvIDM2ZTU7XG4gICAgICAgICAgICBjYXNlICdtaW51dGUnIDogcmV0dXJuIGRheXMgKiAxNDQwICArIG1pbGxpc2Vjb25kcyAvIDZlNDtcbiAgICAgICAgICAgIGNhc2UgJ3NlY29uZCcgOiByZXR1cm4gZGF5cyAqIDg2NDAwICsgbWlsbGlzZWNvbmRzIC8gMTAwMDtcbiAgICAgICAgICAgIC8vIE1hdGguZmxvb3IgcHJldmVudHMgZmxvYXRpbmcgcG9pbnQgbWF0aCBlcnJvcnMgaGVyZVxuICAgICAgICAgICAgY2FzZSAnbWlsbGlzZWNvbmQnOiByZXR1cm4gTWF0aC5mbG9vcihkYXlzICogODY0ZTUpICsgbWlsbGlzZWNvbmRzO1xuICAgICAgICAgICAgZGVmYXVsdDogdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIHVuaXQgJyArIHVuaXRzKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLy8gVE9ETzogVXNlIHRoaXMuYXMoJ21zJyk/XG5mdW5jdGlvbiB2YWx1ZU9mJDEgKCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIE5hTjtcbiAgICB9XG4gICAgcmV0dXJuIChcbiAgICAgICAgdGhpcy5fbWlsbGlzZWNvbmRzICtcbiAgICAgICAgdGhpcy5fZGF5cyAqIDg2NGU1ICtcbiAgICAgICAgKHRoaXMuX21vbnRocyAlIDEyKSAqIDI1OTJlNiArXG4gICAgICAgIHRvSW50KHRoaXMuX21vbnRocyAvIDEyKSAqIDMxNTM2ZTZcbiAgICApO1xufVxuXG5mdW5jdGlvbiBtYWtlQXMgKGFsaWFzKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXMoYWxpYXMpO1xuICAgIH07XG59XG5cbnZhciBhc01pbGxpc2Vjb25kcyA9IG1ha2VBcygnbXMnKTtcbnZhciBhc1NlY29uZHMgICAgICA9IG1ha2VBcygncycpO1xudmFyIGFzTWludXRlcyAgICAgID0gbWFrZUFzKCdtJyk7XG52YXIgYXNIb3VycyAgICAgICAgPSBtYWtlQXMoJ2gnKTtcbnZhciBhc0RheXMgICAgICAgICA9IG1ha2VBcygnZCcpO1xudmFyIGFzV2Vla3MgICAgICAgID0gbWFrZUFzKCd3Jyk7XG52YXIgYXNNb250aHMgICAgICAgPSBtYWtlQXMoJ00nKTtcbnZhciBhc1llYXJzICAgICAgICA9IG1ha2VBcygneScpO1xuXG5mdW5jdGlvbiBjbG9uZSQxICgpIHtcbiAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24odGhpcyk7XG59XG5cbmZ1bmN0aW9uIGdldCQyICh1bml0cykge1xuICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXNbdW5pdHMgKyAncyddKCkgOiBOYU47XG59XG5cbmZ1bmN0aW9uIG1ha2VHZXR0ZXIobmFtZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMuX2RhdGFbbmFtZV0gOiBOYU47XG4gICAgfTtcbn1cblxudmFyIG1pbGxpc2Vjb25kcyA9IG1ha2VHZXR0ZXIoJ21pbGxpc2Vjb25kcycpO1xudmFyIHNlY29uZHMgICAgICA9IG1ha2VHZXR0ZXIoJ3NlY29uZHMnKTtcbnZhciBtaW51dGVzICAgICAgPSBtYWtlR2V0dGVyKCdtaW51dGVzJyk7XG52YXIgaG91cnMgICAgICAgID0gbWFrZUdldHRlcignaG91cnMnKTtcbnZhciBkYXlzICAgICAgICAgPSBtYWtlR2V0dGVyKCdkYXlzJyk7XG52YXIgbW9udGhzICAgICAgID0gbWFrZUdldHRlcignbW9udGhzJyk7XG52YXIgeWVhcnMgICAgICAgID0gbWFrZUdldHRlcigneWVhcnMnKTtcblxuZnVuY3Rpb24gd2Vla3MgKCkge1xuICAgIHJldHVybiBhYnNGbG9vcih0aGlzLmRheXMoKSAvIDcpO1xufVxuXG52YXIgcm91bmQgPSBNYXRoLnJvdW5kO1xudmFyIHRocmVzaG9sZHMgPSB7XG4gICAgc3M6IDQ0LCAgICAgICAgIC8vIGEgZmV3IHNlY29uZHMgdG8gc2Vjb25kc1xuICAgIHMgOiA0NSwgICAgICAgICAvLyBzZWNvbmRzIHRvIG1pbnV0ZVxuICAgIG0gOiA0NSwgICAgICAgICAvLyBtaW51dGVzIHRvIGhvdXJcbiAgICBoIDogMjIsICAgICAgICAgLy8gaG91cnMgdG8gZGF5XG4gICAgZCA6IDI2LCAgICAgICAgIC8vIGRheXMgdG8gbW9udGhcbiAgICBNIDogMTEgICAgICAgICAgLy8gbW9udGhzIHRvIHllYXJcbn07XG5cbi8vIGhlbHBlciBmdW5jdGlvbiBmb3IgbW9tZW50LmZuLmZyb20sIG1vbWVudC5mbi5mcm9tTm93LCBhbmQgbW9tZW50LmR1cmF0aW9uLmZuLmh1bWFuaXplXG5mdW5jdGlvbiBzdWJzdGl0dXRlVGltZUFnbyhzdHJpbmcsIG51bWJlciwgd2l0aG91dFN1ZmZpeCwgaXNGdXR1cmUsIGxvY2FsZSkge1xuICAgIHJldHVybiBsb2NhbGUucmVsYXRpdmVUaW1lKG51bWJlciB8fCAxLCAhIXdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpO1xufVxuXG5mdW5jdGlvbiByZWxhdGl2ZVRpbWUkMSAocG9zTmVnRHVyYXRpb24sIHdpdGhvdXRTdWZmaXgsIGxvY2FsZSkge1xuICAgIHZhciBkdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uKHBvc05lZ0R1cmF0aW9uKS5hYnMoKTtcbiAgICB2YXIgc2Vjb25kcyAgPSByb3VuZChkdXJhdGlvbi5hcygncycpKTtcbiAgICB2YXIgbWludXRlcyAgPSByb3VuZChkdXJhdGlvbi5hcygnbScpKTtcbiAgICB2YXIgaG91cnMgICAgPSByb3VuZChkdXJhdGlvbi5hcygnaCcpKTtcbiAgICB2YXIgZGF5cyAgICAgPSByb3VuZChkdXJhdGlvbi5hcygnZCcpKTtcbiAgICB2YXIgbW9udGhzICAgPSByb3VuZChkdXJhdGlvbi5hcygnTScpKTtcbiAgICB2YXIgeWVhcnMgICAgPSByb3VuZChkdXJhdGlvbi5hcygneScpKTtcblxuICAgIHZhciBhID0gc2Vjb25kcyA8PSB0aHJlc2hvbGRzLnNzICYmIFsncycsIHNlY29uZHNdICB8fFxuICAgICAgICAgICAgc2Vjb25kcyA8IHRocmVzaG9sZHMucyAgICYmIFsnc3MnLCBzZWNvbmRzXSB8fFxuICAgICAgICAgICAgbWludXRlcyA8PSAxICAgICAgICAgICAgICYmIFsnbSddICAgICAgICAgICB8fFxuICAgICAgICAgICAgbWludXRlcyA8IHRocmVzaG9sZHMubSAgICYmIFsnbW0nLCBtaW51dGVzXSB8fFxuICAgICAgICAgICAgaG91cnMgICA8PSAxICAgICAgICAgICAgICYmIFsnaCddICAgICAgICAgICB8fFxuICAgICAgICAgICAgaG91cnMgICA8IHRocmVzaG9sZHMuaCAgICYmIFsnaGgnLCBob3Vyc10gICB8fFxuICAgICAgICAgICAgZGF5cyAgICA8PSAxICAgICAgICAgICAgICYmIFsnZCddICAgICAgICAgICB8fFxuICAgICAgICAgICAgZGF5cyAgICA8IHRocmVzaG9sZHMuZCAgICYmIFsnZGQnLCBkYXlzXSAgICB8fFxuICAgICAgICAgICAgbW9udGhzICA8PSAxICAgICAgICAgICAgICYmIFsnTSddICAgICAgICAgICB8fFxuICAgICAgICAgICAgbW9udGhzICA8IHRocmVzaG9sZHMuTSAgICYmIFsnTU0nLCBtb250aHNdICB8fFxuICAgICAgICAgICAgeWVhcnMgICA8PSAxICAgICAgICAgICAgICYmIFsneSddICAgICAgICAgICB8fCBbJ3l5JywgeWVhcnNdO1xuXG4gICAgYVsyXSA9IHdpdGhvdXRTdWZmaXg7XG4gICAgYVszXSA9ICtwb3NOZWdEdXJhdGlvbiA+IDA7XG4gICAgYVs0XSA9IGxvY2FsZTtcbiAgICByZXR1cm4gc3Vic3RpdHV0ZVRpbWVBZ28uYXBwbHkobnVsbCwgYSk7XG59XG5cbi8vIFRoaXMgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byBzZXQgdGhlIHJvdW5kaW5nIGZ1bmN0aW9uIGZvciByZWxhdGl2ZSB0aW1lIHN0cmluZ3NcbmZ1bmN0aW9uIGdldFNldFJlbGF0aXZlVGltZVJvdW5kaW5nIChyb3VuZGluZ0Z1bmN0aW9uKSB7XG4gICAgaWYgKHJvdW5kaW5nRnVuY3Rpb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gcm91bmQ7XG4gICAgfVxuICAgIGlmICh0eXBlb2Yocm91bmRpbmdGdW5jdGlvbikgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcm91bmQgPSByb3VuZGluZ0Z1bmN0aW9uO1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG4vLyBUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gc2V0IGEgdGhyZXNob2xkIGZvciByZWxhdGl2ZSB0aW1lIHN0cmluZ3NcbmZ1bmN0aW9uIGdldFNldFJlbGF0aXZlVGltZVRocmVzaG9sZCAodGhyZXNob2xkLCBsaW1pdCkge1xuICAgIGlmICh0aHJlc2hvbGRzW3RocmVzaG9sZF0gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChsaW1pdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiB0aHJlc2hvbGRzW3RocmVzaG9sZF07XG4gICAgfVxuICAgIHRocmVzaG9sZHNbdGhyZXNob2xkXSA9IGxpbWl0O1xuICAgIGlmICh0aHJlc2hvbGQgPT09ICdzJykge1xuICAgICAgICB0aHJlc2hvbGRzLnNzID0gbGltaXQgLSAxO1xuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gaHVtYW5pemUgKHdpdGhTdWZmaXgpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5pbnZhbGlkRGF0ZSgpO1xuICAgIH1cblxuICAgIHZhciBsb2NhbGUgPSB0aGlzLmxvY2FsZURhdGEoKTtcbiAgICB2YXIgb3V0cHV0ID0gcmVsYXRpdmVUaW1lJDEodGhpcywgIXdpdGhTdWZmaXgsIGxvY2FsZSk7XG5cbiAgICBpZiAod2l0aFN1ZmZpeCkge1xuICAgICAgICBvdXRwdXQgPSBsb2NhbGUucGFzdEZ1dHVyZSgrdGhpcywgb3V0cHV0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gbG9jYWxlLnBvc3Rmb3JtYXQob3V0cHV0KTtcbn1cblxudmFyIGFicyQxID0gTWF0aC5hYnM7XG5cbmZ1bmN0aW9uIHNpZ24oeCkge1xuICAgIHJldHVybiAoKHggPiAwKSAtICh4IDwgMCkpIHx8ICt4O1xufVxuXG5mdW5jdGlvbiB0b0lTT1N0cmluZyQxKCkge1xuICAgIC8vIGZvciBJU08gc3RyaW5ncyB3ZSBkbyBub3QgdXNlIHRoZSBub3JtYWwgYnViYmxpbmcgcnVsZXM6XG4gICAgLy8gICogbWlsbGlzZWNvbmRzIGJ1YmJsZSB1cCB1bnRpbCB0aGV5IGJlY29tZSBob3Vyc1xuICAgIC8vICAqIGRheXMgZG8gbm90IGJ1YmJsZSBhdCBhbGxcbiAgICAvLyAgKiBtb250aHMgYnViYmxlIHVwIHVudGlsIHRoZXkgYmVjb21lIHllYXJzXG4gICAgLy8gVGhpcyBpcyBiZWNhdXNlIHRoZXJlIGlzIG5vIGNvbnRleHQtZnJlZSBjb252ZXJzaW9uIGJldHdlZW4gaG91cnMgYW5kIGRheXNcbiAgICAvLyAodGhpbmsgb2YgY2xvY2sgY2hhbmdlcylcbiAgICAvLyBhbmQgYWxzbyBub3QgYmV0d2VlbiBkYXlzIGFuZCBtb250aHMgKDI4LTMxIGRheXMgcGVyIG1vbnRoKVxuICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgfVxuXG4gICAgdmFyIHNlY29uZHMgPSBhYnMkMSh0aGlzLl9taWxsaXNlY29uZHMpIC8gMTAwMDtcbiAgICB2YXIgZGF5cyAgICAgICAgID0gYWJzJDEodGhpcy5fZGF5cyk7XG4gICAgdmFyIG1vbnRocyAgICAgICA9IGFicyQxKHRoaXMuX21vbnRocyk7XG4gICAgdmFyIG1pbnV0ZXMsIGhvdXJzLCB5ZWFycztcblxuICAgIC8vIDM2MDAgc2Vjb25kcyAtPiA2MCBtaW51dGVzIC0+IDEgaG91clxuICAgIG1pbnV0ZXMgICAgICAgICAgID0gYWJzRmxvb3Ioc2Vjb25kcyAvIDYwKTtcbiAgICBob3VycyAgICAgICAgICAgICA9IGFic0Zsb29yKG1pbnV0ZXMgLyA2MCk7XG4gICAgc2Vjb25kcyAlPSA2MDtcbiAgICBtaW51dGVzICU9IDYwO1xuXG4gICAgLy8gMTIgbW9udGhzIC0+IDEgeWVhclxuICAgIHllYXJzICA9IGFic0Zsb29yKG1vbnRocyAvIDEyKTtcbiAgICBtb250aHMgJT0gMTI7XG5cblxuICAgIC8vIGluc3BpcmVkIGJ5IGh0dHBzOi8vZ2l0aHViLmNvbS9kb3JkaWxsZS9tb21lbnQtaXNvZHVyYXRpb24vYmxvYi9tYXN0ZXIvbW9tZW50Lmlzb2R1cmF0aW9uLmpzXG4gICAgdmFyIFkgPSB5ZWFycztcbiAgICB2YXIgTSA9IG1vbnRocztcbiAgICB2YXIgRCA9IGRheXM7XG4gICAgdmFyIGggPSBob3VycztcbiAgICB2YXIgbSA9IG1pbnV0ZXM7XG4gICAgdmFyIHMgPSBzZWNvbmRzID8gc2Vjb25kcy50b0ZpeGVkKDMpLnJlcGxhY2UoL1xcLj8wKyQvLCAnJykgOiAnJztcbiAgICB2YXIgdG90YWwgPSB0aGlzLmFzU2Vjb25kcygpO1xuXG4gICAgaWYgKCF0b3RhbCkge1xuICAgICAgICAvLyB0aGlzIGlzIHRoZSBzYW1lIGFzIEMjJ3MgKE5vZGEpIGFuZCBweXRob24gKGlzb2RhdGUpLi4uXG4gICAgICAgIC8vIGJ1dCBub3Qgb3RoZXIgSlMgKGdvb2cuZGF0ZSlcbiAgICAgICAgcmV0dXJuICdQMEQnO1xuICAgIH1cblxuICAgIHZhciB0b3RhbFNpZ24gPSB0b3RhbCA8IDAgPyAnLScgOiAnJztcbiAgICB2YXIgeW1TaWduID0gc2lnbih0aGlzLl9tb250aHMpICE9PSBzaWduKHRvdGFsKSA/ICctJyA6ICcnO1xuICAgIHZhciBkYXlzU2lnbiA9IHNpZ24odGhpcy5fZGF5cykgIT09IHNpZ24odG90YWwpID8gJy0nIDogJyc7XG4gICAgdmFyIGhtc1NpZ24gPSBzaWduKHRoaXMuX21pbGxpc2Vjb25kcykgIT09IHNpZ24odG90YWwpID8gJy0nIDogJyc7XG5cbiAgICByZXR1cm4gdG90YWxTaWduICsgJ1AnICtcbiAgICAgICAgKFkgPyB5bVNpZ24gKyBZICsgJ1knIDogJycpICtcbiAgICAgICAgKE0gPyB5bVNpZ24gKyBNICsgJ00nIDogJycpICtcbiAgICAgICAgKEQgPyBkYXlzU2lnbiArIEQgKyAnRCcgOiAnJykgK1xuICAgICAgICAoKGggfHwgbSB8fCBzKSA/ICdUJyA6ICcnKSArXG4gICAgICAgIChoID8gaG1zU2lnbiArIGggKyAnSCcgOiAnJykgK1xuICAgICAgICAobSA/IGhtc1NpZ24gKyBtICsgJ00nIDogJycpICtcbiAgICAgICAgKHMgPyBobXNTaWduICsgcyArICdTJyA6ICcnKTtcbn1cblxudmFyIHByb3RvJDIgPSBEdXJhdGlvbi5wcm90b3R5cGU7XG5cbnByb3RvJDIuaXNWYWxpZCAgICAgICAgPSBpc1ZhbGlkJDE7XG5wcm90byQyLmFicyAgICAgICAgICAgID0gYWJzO1xucHJvdG8kMi5hZGQgICAgICAgICAgICA9IGFkZCQxO1xucHJvdG8kMi5zdWJ0cmFjdCAgICAgICA9IHN1YnRyYWN0JDE7XG5wcm90byQyLmFzICAgICAgICAgICAgID0gYXM7XG5wcm90byQyLmFzTWlsbGlzZWNvbmRzID0gYXNNaWxsaXNlY29uZHM7XG5wcm90byQyLmFzU2Vjb25kcyAgICAgID0gYXNTZWNvbmRzO1xucHJvdG8kMi5hc01pbnV0ZXMgICAgICA9IGFzTWludXRlcztcbnByb3RvJDIuYXNIb3VycyAgICAgICAgPSBhc0hvdXJzO1xucHJvdG8kMi5hc0RheXMgICAgICAgICA9IGFzRGF5cztcbnByb3RvJDIuYXNXZWVrcyAgICAgICAgPSBhc1dlZWtzO1xucHJvdG8kMi5hc01vbnRocyAgICAgICA9IGFzTW9udGhzO1xucHJvdG8kMi5hc1llYXJzICAgICAgICA9IGFzWWVhcnM7XG5wcm90byQyLnZhbHVlT2YgICAgICAgID0gdmFsdWVPZiQxO1xucHJvdG8kMi5fYnViYmxlICAgICAgICA9IGJ1YmJsZTtcbnByb3RvJDIuY2xvbmUgICAgICAgICAgPSBjbG9uZSQxO1xucHJvdG8kMi5nZXQgICAgICAgICAgICA9IGdldCQyO1xucHJvdG8kMi5taWxsaXNlY29uZHMgICA9IG1pbGxpc2Vjb25kcztcbnByb3RvJDIuc2Vjb25kcyAgICAgICAgPSBzZWNvbmRzO1xucHJvdG8kMi5taW51dGVzICAgICAgICA9IG1pbnV0ZXM7XG5wcm90byQyLmhvdXJzICAgICAgICAgID0gaG91cnM7XG5wcm90byQyLmRheXMgICAgICAgICAgID0gZGF5cztcbnByb3RvJDIud2Vla3MgICAgICAgICAgPSB3ZWVrcztcbnByb3RvJDIubW9udGhzICAgICAgICAgPSBtb250aHM7XG5wcm90byQyLnllYXJzICAgICAgICAgID0geWVhcnM7XG5wcm90byQyLmh1bWFuaXplICAgICAgID0gaHVtYW5pemU7XG5wcm90byQyLnRvSVNPU3RyaW5nICAgID0gdG9JU09TdHJpbmckMTtcbnByb3RvJDIudG9TdHJpbmcgICAgICAgPSB0b0lTT1N0cmluZyQxO1xucHJvdG8kMi50b0pTT04gICAgICAgICA9IHRvSVNPU3RyaW5nJDE7XG5wcm90byQyLmxvY2FsZSAgICAgICAgID0gbG9jYWxlO1xucHJvdG8kMi5sb2NhbGVEYXRhICAgICA9IGxvY2FsZURhdGE7XG5cbi8vIERlcHJlY2F0aW9uc1xucHJvdG8kMi50b0lzb1N0cmluZyA9IGRlcHJlY2F0ZSgndG9Jc29TdHJpbmcoKSBpcyBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIHRvSVNPU3RyaW5nKCkgaW5zdGVhZCAobm90aWNlIHRoZSBjYXBpdGFscyknLCB0b0lTT1N0cmluZyQxKTtcbnByb3RvJDIubGFuZyA9IGxhbmc7XG5cbi8vIFNpZGUgZWZmZWN0IGltcG9ydHNcblxuLy8gRk9STUFUVElOR1xuXG5hZGRGb3JtYXRUb2tlbignWCcsIDAsIDAsICd1bml4Jyk7XG5hZGRGb3JtYXRUb2tlbigneCcsIDAsIDAsICd2YWx1ZU9mJyk7XG5cbi8vIFBBUlNJTkdcblxuYWRkUmVnZXhUb2tlbigneCcsIG1hdGNoU2lnbmVkKTtcbmFkZFJlZ2V4VG9rZW4oJ1gnLCBtYXRjaFRpbWVzdGFtcCk7XG5hZGRQYXJzZVRva2VuKCdYJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgY29uZmlnLl9kID0gbmV3IERhdGUocGFyc2VGbG9hdChpbnB1dCwgMTApICogMTAwMCk7XG59KTtcbmFkZFBhcnNlVG9rZW4oJ3gnLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICBjb25maWcuX2QgPSBuZXcgRGF0ZSh0b0ludChpbnB1dCkpO1xufSk7XG5cbi8vIFNpZGUgZWZmZWN0IGltcG9ydHNcblxuXG5ob29rcy52ZXJzaW9uID0gJzIuMjAuMSc7XG5cbnNldEhvb2tDYWxsYmFjayhjcmVhdGVMb2NhbCk7XG5cbmhvb2tzLmZuICAgICAgICAgICAgICAgICAgICA9IHByb3RvO1xuaG9va3MubWluICAgICAgICAgICAgICAgICAgID0gbWluO1xuaG9va3MubWF4ICAgICAgICAgICAgICAgICAgID0gbWF4O1xuaG9va3Mubm93ICAgICAgICAgICAgICAgICAgID0gbm93O1xuaG9va3MudXRjICAgICAgICAgICAgICAgICAgID0gY3JlYXRlVVRDO1xuaG9va3MudW5peCAgICAgICAgICAgICAgICAgID0gY3JlYXRlVW5peDtcbmhvb2tzLm1vbnRocyAgICAgICAgICAgICAgICA9IGxpc3RNb250aHM7XG5ob29rcy5pc0RhdGUgICAgICAgICAgICAgICAgPSBpc0RhdGU7XG5ob29rcy5sb2NhbGUgICAgICAgICAgICAgICAgPSBnZXRTZXRHbG9iYWxMb2NhbGU7XG5ob29rcy5pbnZhbGlkICAgICAgICAgICAgICAgPSBjcmVhdGVJbnZhbGlkO1xuaG9va3MuZHVyYXRpb24gICAgICAgICAgICAgID0gY3JlYXRlRHVyYXRpb247XG5ob29rcy5pc01vbWVudCAgICAgICAgICAgICAgPSBpc01vbWVudDtcbmhvb2tzLndlZWtkYXlzICAgICAgICAgICAgICA9IGxpc3RXZWVrZGF5cztcbmhvb2tzLnBhcnNlWm9uZSAgICAgICAgICAgICA9IGNyZWF0ZUluWm9uZTtcbmhvb2tzLmxvY2FsZURhdGEgICAgICAgICAgICA9IGdldExvY2FsZTtcbmhvb2tzLmlzRHVyYXRpb24gICAgICAgICAgICA9IGlzRHVyYXRpb247XG5ob29rcy5tb250aHNTaG9ydCAgICAgICAgICAgPSBsaXN0TW9udGhzU2hvcnQ7XG5ob29rcy53ZWVrZGF5c01pbiAgICAgICAgICAgPSBsaXN0V2Vla2RheXNNaW47XG5ob29rcy5kZWZpbmVMb2NhbGUgICAgICAgICAgPSBkZWZpbmVMb2NhbGU7XG5ob29rcy51cGRhdGVMb2NhbGUgICAgICAgICAgPSB1cGRhdGVMb2NhbGU7XG5ob29rcy5sb2NhbGVzICAgICAgICAgICAgICAgPSBsaXN0TG9jYWxlcztcbmhvb2tzLndlZWtkYXlzU2hvcnQgICAgICAgICA9IGxpc3RXZWVrZGF5c1Nob3J0O1xuaG9va3Mubm9ybWFsaXplVW5pdHMgICAgICAgID0gbm9ybWFsaXplVW5pdHM7XG5ob29rcy5yZWxhdGl2ZVRpbWVSb3VuZGluZyAgPSBnZXRTZXRSZWxhdGl2ZVRpbWVSb3VuZGluZztcbmhvb2tzLnJlbGF0aXZlVGltZVRocmVzaG9sZCA9IGdldFNldFJlbGF0aXZlVGltZVRocmVzaG9sZDtcbmhvb2tzLmNhbGVuZGFyRm9ybWF0ICAgICAgICA9IGdldENhbGVuZGFyRm9ybWF0O1xuaG9va3MucHJvdG90eXBlICAgICAgICAgICAgID0gcHJvdG87XG5cbi8vIGN1cnJlbnRseSBIVE1MNSBpbnB1dCB0eXBlIG9ubHkgc3VwcG9ydHMgMjQtaG91ciBmb3JtYXRzXG5ob29rcy5IVE1MNV9GTVQgPSB7XG4gICAgREFURVRJTUVfTE9DQUw6ICdZWVlZLU1NLUREVEhIOm1tJywgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJkYXRldGltZS1sb2NhbFwiIC8+XG4gICAgREFURVRJTUVfTE9DQUxfU0VDT05EUzogJ1lZWVktTU0tRERUSEg6bW06c3MnLCAgLy8gPGlucHV0IHR5cGU9XCJkYXRldGltZS1sb2NhbFwiIHN0ZXA9XCIxXCIgLz5cbiAgICBEQVRFVElNRV9MT0NBTF9NUzogJ1lZWVktTU0tRERUSEg6bW06c3MuU1NTJywgICAvLyA8aW5wdXQgdHlwZT1cImRhdGV0aW1lLWxvY2FsXCIgc3RlcD1cIjAuMDAxXCIgLz5cbiAgICBEQVRFOiAnWVlZWS1NTS1ERCcsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8aW5wdXQgdHlwZT1cImRhdGVcIiAvPlxuICAgIFRJTUU6ICdISDptbScsICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDxpbnB1dCB0eXBlPVwidGltZVwiIC8+XG4gICAgVElNRV9TRUNPTkRTOiAnSEg6bW06c3MnLCAgICAgICAgICAgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJ0aW1lXCIgc3RlcD1cIjFcIiAvPlxuICAgIFRJTUVfTVM6ICdISDptbTpzcy5TU1MnLCAgICAgICAgICAgICAgICAgICAgICAgIC8vIDxpbnB1dCB0eXBlPVwidGltZVwiIHN0ZXA9XCIwLjAwMVwiIC8+XG4gICAgV0VFSzogJ1lZWVktW1ddV1cnLCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gPGlucHV0IHR5cGU9XCJ3ZWVrXCIgLz5cbiAgICBNT05USDogJ1lZWVktTU0nICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyA8aW5wdXQgdHlwZT1cIm1vbnRoXCIgLz5cbn07XG5cbnJldHVybiBob29rcztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9tb21lbnQuanNcbi8vIG1vZHVsZSBpZCA9IDBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyohXG4gKiBqUXVlcnkgSmF2YVNjcmlwdCBMaWJyYXJ5IHYzLjIuMVxuICogaHR0cHM6Ly9qcXVlcnkuY29tL1xuICpcbiAqIEluY2x1ZGVzIFNpenpsZS5qc1xuICogaHR0cHM6Ly9zaXp6bGVqcy5jb20vXG4gKlxuICogQ29weXJpZ2h0IEpTIEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9yc1xuICogUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBsaWNlbnNlXG4gKiBodHRwczovL2pxdWVyeS5vcmcvbGljZW5zZVxuICpcbiAqIERhdGU6IDIwMTctMDMtMjBUMTg6NTlaXG4gKi9cbiggZnVuY3Rpb24oIGdsb2JhbCwgZmFjdG9yeSApIHtcblxuXHRcInVzZSBzdHJpY3RcIjtcblxuXHRpZiAoIHR5cGVvZiBtb2R1bGUgPT09IFwib2JqZWN0XCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzID09PSBcIm9iamVjdFwiICkge1xuXG5cdFx0Ly8gRm9yIENvbW1vbkpTIGFuZCBDb21tb25KUy1saWtlIGVudmlyb25tZW50cyB3aGVyZSBhIHByb3BlciBgd2luZG93YFxuXHRcdC8vIGlzIHByZXNlbnQsIGV4ZWN1dGUgdGhlIGZhY3RvcnkgYW5kIGdldCBqUXVlcnkuXG5cdFx0Ly8gRm9yIGVudmlyb25tZW50cyB0aGF0IGRvIG5vdCBoYXZlIGEgYHdpbmRvd2Agd2l0aCBhIGBkb2N1bWVudGBcblx0XHQvLyAoc3VjaCBhcyBOb2RlLmpzKSwgZXhwb3NlIGEgZmFjdG9yeSBhcyBtb2R1bGUuZXhwb3J0cy5cblx0XHQvLyBUaGlzIGFjY2VudHVhdGVzIHRoZSBuZWVkIGZvciB0aGUgY3JlYXRpb24gb2YgYSByZWFsIGB3aW5kb3dgLlxuXHRcdC8vIGUuZy4gdmFyIGpRdWVyeSA9IHJlcXVpcmUoXCJqcXVlcnlcIikod2luZG93KTtcblx0XHQvLyBTZWUgdGlja2V0ICMxNDU0OSBmb3IgbW9yZSBpbmZvLlxuXHRcdG1vZHVsZS5leHBvcnRzID0gZ2xvYmFsLmRvY3VtZW50ID9cblx0XHRcdGZhY3RvcnkoIGdsb2JhbCwgdHJ1ZSApIDpcblx0XHRcdGZ1bmN0aW9uKCB3ICkge1xuXHRcdFx0XHRpZiAoICF3LmRvY3VtZW50ICkge1xuXHRcdFx0XHRcdHRocm93IG5ldyBFcnJvciggXCJqUXVlcnkgcmVxdWlyZXMgYSB3aW5kb3cgd2l0aCBhIGRvY3VtZW50XCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gZmFjdG9yeSggdyApO1xuXHRcdFx0fTtcblx0fSBlbHNlIHtcblx0XHRmYWN0b3J5KCBnbG9iYWwgKTtcblx0fVxuXG4vLyBQYXNzIHRoaXMgaWYgd2luZG93IGlzIG5vdCBkZWZpbmVkIHlldFxufSApKCB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdGhpcywgZnVuY3Rpb24oIHdpbmRvdywgbm9HbG9iYWwgKSB7XG5cbi8vIEVkZ2UgPD0gMTIgLSAxMyssIEZpcmVmb3ggPD0xOCAtIDQ1KywgSUUgMTAgLSAxMSwgU2FmYXJpIDUuMSAtIDkrLCBpT1MgNiAtIDkuMVxuLy8gdGhyb3cgZXhjZXB0aW9ucyB3aGVuIG5vbi1zdHJpY3QgY29kZSAoZS5nLiwgQVNQLk5FVCA0LjUpIGFjY2Vzc2VzIHN0cmljdCBtb2RlXG4vLyBhcmd1bWVudHMuY2FsbGVlLmNhbGxlciAodHJhYy0xMzMzNSkuIEJ1dCBhcyBvZiBqUXVlcnkgMy4wICgyMDE2KSwgc3RyaWN0IG1vZGUgc2hvdWxkIGJlIGNvbW1vblxuLy8gZW5vdWdoIHRoYXQgYWxsIHN1Y2ggYXR0ZW1wdHMgYXJlIGd1YXJkZWQgaW4gYSB0cnkgYmxvY2suXG5cInVzZSBzdHJpY3RcIjtcblxudmFyIGFyciA9IFtdO1xuXG52YXIgZG9jdW1lbnQgPSB3aW5kb3cuZG9jdW1lbnQ7XG5cbnZhciBnZXRQcm90byA9IE9iamVjdC5nZXRQcm90b3R5cGVPZjtcblxudmFyIHNsaWNlID0gYXJyLnNsaWNlO1xuXG52YXIgY29uY2F0ID0gYXJyLmNvbmNhdDtcblxudmFyIHB1c2ggPSBhcnIucHVzaDtcblxudmFyIGluZGV4T2YgPSBhcnIuaW5kZXhPZjtcblxudmFyIGNsYXNzMnR5cGUgPSB7fTtcblxudmFyIHRvU3RyaW5nID0gY2xhc3MydHlwZS50b1N0cmluZztcblxudmFyIGhhc093biA9IGNsYXNzMnR5cGUuaGFzT3duUHJvcGVydHk7XG5cbnZhciBmblRvU3RyaW5nID0gaGFzT3duLnRvU3RyaW5nO1xuXG52YXIgT2JqZWN0RnVuY3Rpb25TdHJpbmcgPSBmblRvU3RyaW5nLmNhbGwoIE9iamVjdCApO1xuXG52YXIgc3VwcG9ydCA9IHt9O1xuXG5cblxuXHRmdW5jdGlvbiBET01FdmFsKCBjb2RlLCBkb2MgKSB7XG5cdFx0ZG9jID0gZG9jIHx8IGRvY3VtZW50O1xuXG5cdFx0dmFyIHNjcmlwdCA9IGRvYy5jcmVhdGVFbGVtZW50KCBcInNjcmlwdFwiICk7XG5cblx0XHRzY3JpcHQudGV4dCA9IGNvZGU7XG5cdFx0ZG9jLmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdCApLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoIHNjcmlwdCApO1xuXHR9XG4vKiBnbG9iYWwgU3ltYm9sICovXG4vLyBEZWZpbmluZyB0aGlzIGdsb2JhbCBpbiAuZXNsaW50cmMuanNvbiB3b3VsZCBjcmVhdGUgYSBkYW5nZXIgb2YgdXNpbmcgdGhlIGdsb2JhbFxuLy8gdW5ndWFyZGVkIGluIGFub3RoZXIgcGxhY2UsIGl0IHNlZW1zIHNhZmVyIHRvIGRlZmluZSBnbG9iYWwgb25seSBmb3IgdGhpcyBtb2R1bGVcblxuXG5cbnZhclxuXHR2ZXJzaW9uID0gXCIzLjIuMVwiLFxuXG5cdC8vIERlZmluZSBhIGxvY2FsIGNvcHkgb2YgalF1ZXJ5XG5cdGpRdWVyeSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHtcblxuXHRcdC8vIFRoZSBqUXVlcnkgb2JqZWN0IGlzIGFjdHVhbGx5IGp1c3QgdGhlIGluaXQgY29uc3RydWN0b3IgJ2VuaGFuY2VkJ1xuXHRcdC8vIE5lZWQgaW5pdCBpZiBqUXVlcnkgaXMgY2FsbGVkIChqdXN0IGFsbG93IGVycm9yIHRvIGJlIHRocm93biBpZiBub3QgaW5jbHVkZWQpXG5cdFx0cmV0dXJuIG5ldyBqUXVlcnkuZm4uaW5pdCggc2VsZWN0b3IsIGNvbnRleHQgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHlcblx0Ly8gTWFrZSBzdXJlIHdlIHRyaW0gQk9NIGFuZCBOQlNQXG5cdHJ0cmltID0gL15bXFxzXFx1RkVGRlxceEEwXSt8W1xcc1xcdUZFRkZcXHhBMF0rJC9nLFxuXG5cdC8vIE1hdGNoZXMgZGFzaGVkIHN0cmluZyBmb3IgY2FtZWxpemluZ1xuXHRybXNQcmVmaXggPSAvXi1tcy0vLFxuXHRyZGFzaEFscGhhID0gLy0oW2Etel0pL2csXG5cblx0Ly8gVXNlZCBieSBqUXVlcnkuY2FtZWxDYXNlIGFzIGNhbGxiYWNrIHRvIHJlcGxhY2UoKVxuXHRmY2FtZWxDYXNlID0gZnVuY3Rpb24oIGFsbCwgbGV0dGVyICkge1xuXHRcdHJldHVybiBsZXR0ZXIudG9VcHBlckNhc2UoKTtcblx0fTtcblxualF1ZXJ5LmZuID0galF1ZXJ5LnByb3RvdHlwZSA9IHtcblxuXHQvLyBUaGUgY3VycmVudCB2ZXJzaW9uIG9mIGpRdWVyeSBiZWluZyB1c2VkXG5cdGpxdWVyeTogdmVyc2lvbixcblxuXHRjb25zdHJ1Y3RvcjogalF1ZXJ5LFxuXG5cdC8vIFRoZSBkZWZhdWx0IGxlbmd0aCBvZiBhIGpRdWVyeSBvYmplY3QgaXMgMFxuXHRsZW5ndGg6IDAsXG5cblx0dG9BcnJheTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0fSxcblxuXHQvLyBHZXQgdGhlIE50aCBlbGVtZW50IGluIHRoZSBtYXRjaGVkIGVsZW1lbnQgc2V0IE9SXG5cdC8vIEdldCB0aGUgd2hvbGUgbWF0Y2hlZCBlbGVtZW50IHNldCBhcyBhIGNsZWFuIGFycmF5XG5cdGdldDogZnVuY3Rpb24oIG51bSApIHtcblxuXHRcdC8vIFJldHVybiBhbGwgdGhlIGVsZW1lbnRzIGluIGEgY2xlYW4gYXJyYXlcblx0XHRpZiAoIG51bSA9PSBudWxsICkge1xuXHRcdFx0cmV0dXJuIHNsaWNlLmNhbGwoIHRoaXMgKTtcblx0XHR9XG5cblx0XHQvLyBSZXR1cm4ganVzdCB0aGUgb25lIGVsZW1lbnQgZnJvbSB0aGUgc2V0XG5cdFx0cmV0dXJuIG51bSA8IDAgPyB0aGlzWyBudW0gKyB0aGlzLmxlbmd0aCBdIDogdGhpc1sgbnVtIF07XG5cdH0sXG5cblx0Ly8gVGFrZSBhbiBhcnJheSBvZiBlbGVtZW50cyBhbmQgcHVzaCBpdCBvbnRvIHRoZSBzdGFja1xuXHQvLyAocmV0dXJuaW5nIHRoZSBuZXcgbWF0Y2hlZCBlbGVtZW50IHNldClcblx0cHVzaFN0YWNrOiBmdW5jdGlvbiggZWxlbXMgKSB7XG5cblx0XHQvLyBCdWlsZCBhIG5ldyBqUXVlcnkgbWF0Y2hlZCBlbGVtZW50IHNldFxuXHRcdHZhciByZXQgPSBqUXVlcnkubWVyZ2UoIHRoaXMuY29uc3RydWN0b3IoKSwgZWxlbXMgKTtcblxuXHRcdC8vIEFkZCB0aGUgb2xkIG9iamVjdCBvbnRvIHRoZSBzdGFjayAoYXMgYSByZWZlcmVuY2UpXG5cdFx0cmV0LnByZXZPYmplY3QgPSB0aGlzO1xuXG5cdFx0Ly8gUmV0dXJuIHRoZSBuZXdseS1mb3JtZWQgZWxlbWVudCBzZXRcblx0XHRyZXR1cm4gcmV0O1xuXHR9LFxuXG5cdC8vIEV4ZWN1dGUgYSBjYWxsYmFjayBmb3IgZXZlcnkgZWxlbWVudCBpbiB0aGUgbWF0Y2hlZCBzZXQuXG5cdGVhY2g6IGZ1bmN0aW9uKCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmVhY2goIHRoaXMsIGNhbGxiYWNrICk7XG5cdH0sXG5cblx0bWFwOiBmdW5jdGlvbiggY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqUXVlcnkubWFwKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiBjYWxsYmFjay5jYWxsKCBlbGVtLCBpLCBlbGVtICk7XG5cdFx0fSApICk7XG5cdH0sXG5cblx0c2xpY2U6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggc2xpY2UuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApICk7XG5cdH0sXG5cblx0Zmlyc3Q6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLmVxKCAwICk7XG5cdH0sXG5cblx0bGFzdDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMuZXEoIC0xICk7XG5cdH0sXG5cblx0ZXE6IGZ1bmN0aW9uKCBpICkge1xuXHRcdHZhciBsZW4gPSB0aGlzLmxlbmd0aCxcblx0XHRcdGogPSAraSArICggaSA8IDAgPyBsZW4gOiAwICk7XG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBqID49IDAgJiYgaiA8IGxlbiA/IFsgdGhpc1sgaiBdIF0gOiBbXSApO1xuXHR9LFxuXG5cdGVuZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMucHJldk9iamVjdCB8fCB0aGlzLmNvbnN0cnVjdG9yKCk7XG5cdH0sXG5cblx0Ly8gRm9yIGludGVybmFsIHVzZSBvbmx5LlxuXHQvLyBCZWhhdmVzIGxpa2UgYW4gQXJyYXkncyBtZXRob2QsIG5vdCBsaWtlIGEgalF1ZXJ5IG1ldGhvZC5cblx0cHVzaDogcHVzaCxcblx0c29ydDogYXJyLnNvcnQsXG5cdHNwbGljZTogYXJyLnNwbGljZVxufTtcblxualF1ZXJ5LmV4dGVuZCA9IGpRdWVyeS5mbi5leHRlbmQgPSBmdW5jdGlvbigpIHtcblx0dmFyIG9wdGlvbnMsIG5hbWUsIHNyYywgY29weSwgY29weUlzQXJyYXksIGNsb25lLFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1sgMCBdIHx8IHt9LFxuXHRcdGkgPSAxLFxuXHRcdGxlbmd0aCA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cdFx0ZGVlcCA9IGZhbHNlO1xuXG5cdC8vIEhhbmRsZSBhIGRlZXAgY29weSBzaXR1YXRpb25cblx0aWYgKCB0eXBlb2YgdGFyZ2V0ID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRkZWVwID0gdGFyZ2V0O1xuXG5cdFx0Ly8gU2tpcCB0aGUgYm9vbGVhbiBhbmQgdGhlIHRhcmdldFxuXHRcdHRhcmdldCA9IGFyZ3VtZW50c1sgaSBdIHx8IHt9O1xuXHRcdGkrKztcblx0fVxuXG5cdC8vIEhhbmRsZSBjYXNlIHdoZW4gdGFyZ2V0IGlzIGEgc3RyaW5nIG9yIHNvbWV0aGluZyAocG9zc2libGUgaW4gZGVlcCBjb3B5KVxuXHRpZiAoIHR5cGVvZiB0YXJnZXQgIT09IFwib2JqZWN0XCIgJiYgIWpRdWVyeS5pc0Z1bmN0aW9uKCB0YXJnZXQgKSApIHtcblx0XHR0YXJnZXQgPSB7fTtcblx0fVxuXG5cdC8vIEV4dGVuZCBqUXVlcnkgaXRzZWxmIGlmIG9ubHkgb25lIGFyZ3VtZW50IGlzIHBhc3NlZFxuXHRpZiAoIGkgPT09IGxlbmd0aCApIHtcblx0XHR0YXJnZXQgPSB0aGlzO1xuXHRcdGktLTtcblx0fVxuXG5cdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXG5cdFx0Ly8gT25seSBkZWFsIHdpdGggbm9uLW51bGwvdW5kZWZpbmVkIHZhbHVlc1xuXHRcdGlmICggKCBvcHRpb25zID0gYXJndW1lbnRzWyBpIF0gKSAhPSBudWxsICkge1xuXG5cdFx0XHQvLyBFeHRlbmQgdGhlIGJhc2Ugb2JqZWN0XG5cdFx0XHRmb3IgKCBuYW1lIGluIG9wdGlvbnMgKSB7XG5cdFx0XHRcdHNyYyA9IHRhcmdldFsgbmFtZSBdO1xuXHRcdFx0XHRjb3B5ID0gb3B0aW9uc1sgbmFtZSBdO1xuXG5cdFx0XHRcdC8vIFByZXZlbnQgbmV2ZXItZW5kaW5nIGxvb3Bcblx0XHRcdFx0aWYgKCB0YXJnZXQgPT09IGNvcHkgKSB7XG5cdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZWN1cnNlIGlmIHdlJ3JlIG1lcmdpbmcgcGxhaW4gb2JqZWN0cyBvciBhcnJheXNcblx0XHRcdFx0aWYgKCBkZWVwICYmIGNvcHkgJiYgKCBqUXVlcnkuaXNQbGFpbk9iamVjdCggY29weSApIHx8XG5cdFx0XHRcdFx0KCBjb3B5SXNBcnJheSA9IEFycmF5LmlzQXJyYXkoIGNvcHkgKSApICkgKSB7XG5cblx0XHRcdFx0XHRpZiAoIGNvcHlJc0FycmF5ICkge1xuXHRcdFx0XHRcdFx0Y29weUlzQXJyYXkgPSBmYWxzZTtcblx0XHRcdFx0XHRcdGNsb25lID0gc3JjICYmIEFycmF5LmlzQXJyYXkoIHNyYyApID8gc3JjIDogW107XG5cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0Y2xvbmUgPSBzcmMgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIHNyYyApID8gc3JjIDoge307XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gTmV2ZXIgbW92ZSBvcmlnaW5hbCBvYmplY3RzLCBjbG9uZSB0aGVtXG5cdFx0XHRcdFx0dGFyZ2V0WyBuYW1lIF0gPSBqUXVlcnkuZXh0ZW5kKCBkZWVwLCBjbG9uZSwgY29weSApO1xuXG5cdFx0XHRcdC8vIERvbid0IGJyaW5nIGluIHVuZGVmaW5lZCB2YWx1ZXNcblx0XHRcdFx0fSBlbHNlIGlmICggY29weSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdHRhcmdldFsgbmFtZSBdID0gY29weTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgbW9kaWZpZWQgb2JqZWN0XG5cdHJldHVybiB0YXJnZXQ7XG59O1xuXG5qUXVlcnkuZXh0ZW5kKCB7XG5cblx0Ly8gVW5pcXVlIGZvciBlYWNoIGNvcHkgb2YgalF1ZXJ5IG9uIHRoZSBwYWdlXG5cdGV4cGFuZG86IFwialF1ZXJ5XCIgKyAoIHZlcnNpb24gKyBNYXRoLnJhbmRvbSgpICkucmVwbGFjZSggL1xcRC9nLCBcIlwiICksXG5cblx0Ly8gQXNzdW1lIGpRdWVyeSBpcyByZWFkeSB3aXRob3V0IHRoZSByZWFkeSBtb2R1bGVcblx0aXNSZWFkeTogdHJ1ZSxcblxuXHRlcnJvcjogZnVuY3Rpb24oIG1zZyApIHtcblx0XHR0aHJvdyBuZXcgRXJyb3IoIG1zZyApO1xuXHR9LFxuXG5cdG5vb3A6IGZ1bmN0aW9uKCkge30sXG5cblx0aXNGdW5jdGlvbjogZnVuY3Rpb24oIG9iaiApIHtcblx0XHRyZXR1cm4galF1ZXJ5LnR5cGUoIG9iaiApID09PSBcImZ1bmN0aW9uXCI7XG5cdH0sXG5cblx0aXNXaW5kb3c6IGZ1bmN0aW9uKCBvYmogKSB7XG5cdFx0cmV0dXJuIG9iaiAhPSBudWxsICYmIG9iaiA9PT0gb2JqLndpbmRvdztcblx0fSxcblxuXHRpc051bWVyaWM6IGZ1bmN0aW9uKCBvYmogKSB7XG5cblx0XHQvLyBBcyBvZiBqUXVlcnkgMy4wLCBpc051bWVyaWMgaXMgbGltaXRlZCB0b1xuXHRcdC8vIHN0cmluZ3MgYW5kIG51bWJlcnMgKHByaW1pdGl2ZXMgb3Igb2JqZWN0cylcblx0XHQvLyB0aGF0IGNhbiBiZSBjb2VyY2VkIHRvIGZpbml0ZSBudW1iZXJzIChnaC0yNjYyKVxuXHRcdHZhciB0eXBlID0galF1ZXJ5LnR5cGUoIG9iaiApO1xuXHRcdHJldHVybiAoIHR5cGUgPT09IFwibnVtYmVyXCIgfHwgdHlwZSA9PT0gXCJzdHJpbmdcIiApICYmXG5cblx0XHRcdC8vIHBhcnNlRmxvYXQgTmFOcyBudW1lcmljLWNhc3QgZmFsc2UgcG9zaXRpdmVzIChcIlwiKVxuXHRcdFx0Ly8gLi4uYnV0IG1pc2ludGVycHJldHMgbGVhZGluZy1udW1iZXIgc3RyaW5ncywgcGFydGljdWxhcmx5IGhleCBsaXRlcmFscyAoXCIweC4uLlwiKVxuXHRcdFx0Ly8gc3VidHJhY3Rpb24gZm9yY2VzIGluZmluaXRpZXMgdG8gTmFOXG5cdFx0XHQhaXNOYU4oIG9iaiAtIHBhcnNlRmxvYXQoIG9iaiApICk7XG5cdH0sXG5cblx0aXNQbGFpbk9iamVjdDogZnVuY3Rpb24oIG9iaiApIHtcblx0XHR2YXIgcHJvdG8sIEN0b3I7XG5cblx0XHQvLyBEZXRlY3Qgb2J2aW91cyBuZWdhdGl2ZXNcblx0XHQvLyBVc2UgdG9TdHJpbmcgaW5zdGVhZCBvZiBqUXVlcnkudHlwZSB0byBjYXRjaCBob3N0IG9iamVjdHNcblx0XHRpZiAoICFvYmogfHwgdG9TdHJpbmcuY2FsbCggb2JqICkgIT09IFwiW29iamVjdCBPYmplY3RdXCIgKSB7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXG5cdFx0cHJvdG8gPSBnZXRQcm90byggb2JqICk7XG5cblx0XHQvLyBPYmplY3RzIHdpdGggbm8gcHJvdG90eXBlIChlLmcuLCBgT2JqZWN0LmNyZWF0ZSggbnVsbCApYCkgYXJlIHBsYWluXG5cdFx0aWYgKCAhcHJvdG8gKSB7XG5cdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHR9XG5cblx0XHQvLyBPYmplY3RzIHdpdGggcHJvdG90eXBlIGFyZSBwbGFpbiBpZmYgdGhleSB3ZXJlIGNvbnN0cnVjdGVkIGJ5IGEgZ2xvYmFsIE9iamVjdCBmdW5jdGlvblxuXHRcdEN0b3IgPSBoYXNPd24uY2FsbCggcHJvdG8sIFwiY29uc3RydWN0b3JcIiApICYmIHByb3RvLmNvbnN0cnVjdG9yO1xuXHRcdHJldHVybiB0eXBlb2YgQ3RvciA9PT0gXCJmdW5jdGlvblwiICYmIGZuVG9TdHJpbmcuY2FsbCggQ3RvciApID09PSBPYmplY3RGdW5jdGlvblN0cmluZztcblx0fSxcblxuXHRpc0VtcHR5T2JqZWN0OiBmdW5jdGlvbiggb2JqICkge1xuXG5cdFx0LyogZXNsaW50LWRpc2FibGUgbm8tdW51c2VkLXZhcnMgKi9cblx0XHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2VzbGludC9lc2xpbnQvaXNzdWVzLzYxMjVcblx0XHR2YXIgbmFtZTtcblxuXHRcdGZvciAoIG5hbWUgaW4gb2JqICkge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fSxcblxuXHR0eXBlOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdGlmICggb2JqID09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gb2JqICsgXCJcIjtcblx0XHR9XG5cblx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9Mi4zIG9ubHkgKGZ1bmN0aW9uaXNoIFJlZ0V4cClcblx0XHRyZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJvYmplY3RcIiB8fCB0eXBlb2Ygb2JqID09PSBcImZ1bmN0aW9uXCIgP1xuXHRcdFx0Y2xhc3MydHlwZVsgdG9TdHJpbmcuY2FsbCggb2JqICkgXSB8fCBcIm9iamVjdFwiIDpcblx0XHRcdHR5cGVvZiBvYmo7XG5cdH0sXG5cblx0Ly8gRXZhbHVhdGVzIGEgc2NyaXB0IGluIGEgZ2xvYmFsIGNvbnRleHRcblx0Z2xvYmFsRXZhbDogZnVuY3Rpb24oIGNvZGUgKSB7XG5cdFx0RE9NRXZhbCggY29kZSApO1xuXHR9LFxuXG5cdC8vIENvbnZlcnQgZGFzaGVkIHRvIGNhbWVsQ2FzZTsgdXNlZCBieSB0aGUgY3NzIGFuZCBkYXRhIG1vZHVsZXNcblx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHQvLyBNaWNyb3NvZnQgZm9yZ290IHRvIGh1bXAgdGhlaXIgdmVuZG9yIHByZWZpeCAoIzk1NzIpXG5cdGNhbWVsQ2FzZTogZnVuY3Rpb24oIHN0cmluZyApIHtcblx0XHRyZXR1cm4gc3RyaW5nLnJlcGxhY2UoIHJtc1ByZWZpeCwgXCJtcy1cIiApLnJlcGxhY2UoIHJkYXNoQWxwaGEsIGZjYW1lbENhc2UgKTtcblx0fSxcblxuXHRlYWNoOiBmdW5jdGlvbiggb2JqLCBjYWxsYmFjayApIHtcblx0XHR2YXIgbGVuZ3RoLCBpID0gMDtcblxuXHRcdGlmICggaXNBcnJheUxpa2UoIG9iaiApICkge1xuXHRcdFx0bGVuZ3RoID0gb2JqLmxlbmd0aDtcblx0XHRcdGZvciAoIDsgaSA8IGxlbmd0aDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrLmNhbGwoIG9ialsgaSBdLCBpLCBvYmpbIGkgXSApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRmb3IgKCBpIGluIG9iaiApIHtcblx0XHRcdFx0aWYgKCBjYWxsYmFjay5jYWxsKCBvYmpbIGkgXSwgaSwgb2JqWyBpIF0gKSA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gb2JqO1xuXHR9LFxuXG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seVxuXHR0cmltOiBmdW5jdGlvbiggdGV4dCApIHtcblx0XHRyZXR1cm4gdGV4dCA9PSBudWxsID9cblx0XHRcdFwiXCIgOlxuXHRcdFx0KCB0ZXh0ICsgXCJcIiApLnJlcGxhY2UoIHJ0cmltLCBcIlwiICk7XG5cdH0sXG5cblx0Ly8gcmVzdWx0cyBpcyBmb3IgaW50ZXJuYWwgdXNhZ2Ugb25seVxuXHRtYWtlQXJyYXk6IGZ1bmN0aW9uKCBhcnIsIHJlc3VsdHMgKSB7XG5cdFx0dmFyIHJldCA9IHJlc3VsdHMgfHwgW107XG5cblx0XHRpZiAoIGFyciAhPSBudWxsICkge1xuXHRcdFx0aWYgKCBpc0FycmF5TGlrZSggT2JqZWN0KCBhcnIgKSApICkge1xuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIHJldCxcblx0XHRcdFx0XHR0eXBlb2YgYXJyID09PSBcInN0cmluZ1wiID9cblx0XHRcdFx0XHRbIGFyciBdIDogYXJyXG5cdFx0XHRcdCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRwdXNoLmNhbGwoIHJldCwgYXJyICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJldDtcblx0fSxcblxuXHRpbkFycmF5OiBmdW5jdGlvbiggZWxlbSwgYXJyLCBpICkge1xuXHRcdHJldHVybiBhcnIgPT0gbnVsbCA/IC0xIDogaW5kZXhPZi5jYWxsKCBhcnIsIGVsZW0sIGkgKTtcblx0fSxcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRtZXJnZTogZnVuY3Rpb24oIGZpcnN0LCBzZWNvbmQgKSB7XG5cdFx0dmFyIGxlbiA9ICtzZWNvbmQubGVuZ3RoLFxuXHRcdFx0aiA9IDAsXG5cdFx0XHRpID0gZmlyc3QubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBqIDwgbGVuOyBqKysgKSB7XG5cdFx0XHRmaXJzdFsgaSsrIF0gPSBzZWNvbmRbIGogXTtcblx0XHR9XG5cblx0XHRmaXJzdC5sZW5ndGggPSBpO1xuXG5cdFx0cmV0dXJuIGZpcnN0O1xuXHR9LFxuXG5cdGdyZXA6IGZ1bmN0aW9uKCBlbGVtcywgY2FsbGJhY2ssIGludmVydCApIHtcblx0XHR2YXIgY2FsbGJhY2tJbnZlcnNlLFxuXHRcdFx0bWF0Y2hlcyA9IFtdLFxuXHRcdFx0aSA9IDAsXG5cdFx0XHRsZW5ndGggPSBlbGVtcy5sZW5ndGgsXG5cdFx0XHRjYWxsYmFja0V4cGVjdCA9ICFpbnZlcnQ7XG5cblx0XHQvLyBHbyB0aHJvdWdoIHRoZSBhcnJheSwgb25seSBzYXZpbmcgdGhlIGl0ZW1zXG5cdFx0Ly8gdGhhdCBwYXNzIHRoZSB2YWxpZGF0b3IgZnVuY3Rpb25cblx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkrKyApIHtcblx0XHRcdGNhbGxiYWNrSW52ZXJzZSA9ICFjYWxsYmFjayggZWxlbXNbIGkgXSwgaSApO1xuXHRcdFx0aWYgKCBjYWxsYmFja0ludmVyc2UgIT09IGNhbGxiYWNrRXhwZWN0ICkge1xuXHRcdFx0XHRtYXRjaGVzLnB1c2goIGVsZW1zWyBpIF0gKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gbWF0Y2hlcztcblx0fSxcblxuXHQvLyBhcmcgaXMgZm9yIGludGVybmFsIHVzYWdlIG9ubHlcblx0bWFwOiBmdW5jdGlvbiggZWxlbXMsIGNhbGxiYWNrLCBhcmcgKSB7XG5cdFx0dmFyIGxlbmd0aCwgdmFsdWUsXG5cdFx0XHRpID0gMCxcblx0XHRcdHJldCA9IFtdO1xuXG5cdFx0Ly8gR28gdGhyb3VnaCB0aGUgYXJyYXksIHRyYW5zbGF0aW5nIGVhY2ggb2YgdGhlIGl0ZW1zIHRvIHRoZWlyIG5ldyB2YWx1ZXNcblx0XHRpZiAoIGlzQXJyYXlMaWtlKCBlbGVtcyApICkge1xuXHRcdFx0bGVuZ3RoID0gZWxlbXMubGVuZ3RoO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpKysgKSB7XG5cdFx0XHRcdHZhbHVlID0gY2FsbGJhY2soIGVsZW1zWyBpIF0sIGksIGFyZyApO1xuXG5cdFx0XHRcdGlmICggdmFsdWUgIT0gbnVsbCApIHtcblx0XHRcdFx0XHRyZXQucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0Ly8gR28gdGhyb3VnaCBldmVyeSBrZXkgb24gdGhlIG9iamVjdCxcblx0XHR9IGVsc2Uge1xuXHRcdFx0Zm9yICggaSBpbiBlbGVtcyApIHtcblx0XHRcdFx0dmFsdWUgPSBjYWxsYmFjayggZWxlbXNbIGkgXSwgaSwgYXJnICk7XG5cblx0XHRcdFx0aWYgKCB2YWx1ZSAhPSBudWxsICkge1xuXHRcdFx0XHRcdHJldC5wdXNoKCB2YWx1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmxhdHRlbiBhbnkgbmVzdGVkIGFycmF5c1xuXHRcdHJldHVybiBjb25jYXQuYXBwbHkoIFtdLCByZXQgKTtcblx0fSxcblxuXHQvLyBBIGdsb2JhbCBHVUlEIGNvdW50ZXIgZm9yIG9iamVjdHNcblx0Z3VpZDogMSxcblxuXHQvLyBCaW5kIGEgZnVuY3Rpb24gdG8gYSBjb250ZXh0LCBvcHRpb25hbGx5IHBhcnRpYWxseSBhcHBseWluZyBhbnlcblx0Ly8gYXJndW1lbnRzLlxuXHRwcm94eTogZnVuY3Rpb24oIGZuLCBjb250ZXh0ICkge1xuXHRcdHZhciB0bXAsIGFyZ3MsIHByb3h5O1xuXG5cdFx0aWYgKCB0eXBlb2YgY29udGV4dCA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHRtcCA9IGZuWyBjb250ZXh0IF07XG5cdFx0XHRjb250ZXh0ID0gZm47XG5cdFx0XHRmbiA9IHRtcDtcblx0XHR9XG5cblx0XHQvLyBRdWljayBjaGVjayB0byBkZXRlcm1pbmUgaWYgdGFyZ2V0IGlzIGNhbGxhYmxlLCBpbiB0aGUgc3BlY1xuXHRcdC8vIHRoaXMgdGhyb3dzIGEgVHlwZUVycm9yLCBidXQgd2Ugd2lsbCBqdXN0IHJldHVybiB1bmRlZmluZWQuXG5cdFx0aWYgKCAhalF1ZXJ5LmlzRnVuY3Rpb24oIGZuICkgKSB7XG5cdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdH1cblxuXHRcdC8vIFNpbXVsYXRlZCBiaW5kXG5cdFx0YXJncyA9IHNsaWNlLmNhbGwoIGFyZ3VtZW50cywgMiApO1xuXHRcdHByb3h5ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gZm4uYXBwbHkoIGNvbnRleHQgfHwgdGhpcywgYXJncy5jb25jYXQoIHNsaWNlLmNhbGwoIGFyZ3VtZW50cyApICkgKTtcblx0XHR9O1xuXG5cdFx0Ly8gU2V0IHRoZSBndWlkIG9mIHVuaXF1ZSBoYW5kbGVyIHRvIHRoZSBzYW1lIG9mIG9yaWdpbmFsIGhhbmRsZXIsIHNvIGl0IGNhbiBiZSByZW1vdmVkXG5cdFx0cHJveHkuZ3VpZCA9IGZuLmd1aWQgPSBmbi5ndWlkIHx8IGpRdWVyeS5ndWlkKys7XG5cblx0XHRyZXR1cm4gcHJveHk7XG5cdH0sXG5cblx0bm93OiBEYXRlLm5vdyxcblxuXHQvLyBqUXVlcnkuc3VwcG9ydCBpcyBub3QgdXNlZCBpbiBDb3JlIGJ1dCBvdGhlciBwcm9qZWN0cyBhdHRhY2ggdGhlaXJcblx0Ly8gcHJvcGVydGllcyB0byBpdCBzbyBpdCBuZWVkcyB0byBleGlzdC5cblx0c3VwcG9ydDogc3VwcG9ydFxufSApO1xuXG5pZiAoIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiApIHtcblx0alF1ZXJ5LmZuWyBTeW1ib2wuaXRlcmF0b3IgXSA9IGFyclsgU3ltYm9sLml0ZXJhdG9yIF07XG59XG5cbi8vIFBvcHVsYXRlIHRoZSBjbGFzczJ0eXBlIG1hcFxualF1ZXJ5LmVhY2goIFwiQm9vbGVhbiBOdW1iZXIgU3RyaW5nIEZ1bmN0aW9uIEFycmF5IERhdGUgUmVnRXhwIE9iamVjdCBFcnJvciBTeW1ib2xcIi5zcGxpdCggXCIgXCIgKSxcbmZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHRjbGFzczJ0eXBlWyBcIltvYmplY3QgXCIgKyBuYW1lICsgXCJdXCIgXSA9IG5hbWUudG9Mb3dlckNhc2UoKTtcbn0gKTtcblxuZnVuY3Rpb24gaXNBcnJheUxpa2UoIG9iaiApIHtcblxuXHQvLyBTdXBwb3J0OiByZWFsIGlPUyA4LjIgb25seSAobm90IHJlcHJvZHVjaWJsZSBpbiBzaW11bGF0b3IpXG5cdC8vIGBpbmAgY2hlY2sgdXNlZCB0byBwcmV2ZW50IEpJVCBlcnJvciAoZ2gtMjE0NSlcblx0Ly8gaGFzT3duIGlzbid0IHVzZWQgaGVyZSBkdWUgdG8gZmFsc2UgbmVnYXRpdmVzXG5cdC8vIHJlZ2FyZGluZyBOb2RlbGlzdCBsZW5ndGggaW4gSUVcblx0dmFyIGxlbmd0aCA9ICEhb2JqICYmIFwibGVuZ3RoXCIgaW4gb2JqICYmIG9iai5sZW5ndGgsXG5cdFx0dHlwZSA9IGpRdWVyeS50eXBlKCBvYmogKTtcblxuXHRpZiAoIHR5cGUgPT09IFwiZnVuY3Rpb25cIiB8fCBqUXVlcnkuaXNXaW5kb3coIG9iaiApICkge1xuXHRcdHJldHVybiBmYWxzZTtcblx0fVxuXG5cdHJldHVybiB0eXBlID09PSBcImFycmF5XCIgfHwgbGVuZ3RoID09PSAwIHx8XG5cdFx0dHlwZW9mIGxlbmd0aCA9PT0gXCJudW1iZXJcIiAmJiBsZW5ndGggPiAwICYmICggbGVuZ3RoIC0gMSApIGluIG9iajtcbn1cbnZhciBTaXp6bGUgPVxuLyohXG4gKiBTaXp6bGUgQ1NTIFNlbGVjdG9yIEVuZ2luZSB2Mi4zLjNcbiAqIGh0dHBzOi8vc2l6emxlanMuY29tL1xuICpcbiAqIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzXG4gKiBSZWxlYXNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2VcbiAqIGh0dHA6Ly9qcXVlcnkub3JnL2xpY2Vuc2VcbiAqXG4gKiBEYXRlOiAyMDE2LTA4LTA4XG4gKi9cbihmdW5jdGlvbiggd2luZG93ICkge1xuXG52YXIgaSxcblx0c3VwcG9ydCxcblx0RXhwcixcblx0Z2V0VGV4dCxcblx0aXNYTUwsXG5cdHRva2VuaXplLFxuXHRjb21waWxlLFxuXHRzZWxlY3QsXG5cdG91dGVybW9zdENvbnRleHQsXG5cdHNvcnRJbnB1dCxcblx0aGFzRHVwbGljYXRlLFxuXG5cdC8vIExvY2FsIGRvY3VtZW50IHZhcnNcblx0c2V0RG9jdW1lbnQsXG5cdGRvY3VtZW50LFxuXHRkb2NFbGVtLFxuXHRkb2N1bWVudElzSFRNTCxcblx0cmJ1Z2d5UVNBLFxuXHRyYnVnZ3lNYXRjaGVzLFxuXHRtYXRjaGVzLFxuXHRjb250YWlucyxcblxuXHQvLyBJbnN0YW5jZS1zcGVjaWZpYyBkYXRhXG5cdGV4cGFuZG8gPSBcInNpenpsZVwiICsgMSAqIG5ldyBEYXRlKCksXG5cdHByZWZlcnJlZERvYyA9IHdpbmRvdy5kb2N1bWVudCxcblx0ZGlycnVucyA9IDAsXG5cdGRvbmUgPSAwLFxuXHRjbGFzc0NhY2hlID0gY3JlYXRlQ2FjaGUoKSxcblx0dG9rZW5DYWNoZSA9IGNyZWF0ZUNhY2hlKCksXG5cdGNvbXBpbGVyQ2FjaGUgPSBjcmVhdGVDYWNoZSgpLFxuXHRzb3J0T3JkZXIgPSBmdW5jdGlvbiggYSwgYiApIHtcblx0XHRpZiAoIGEgPT09IGIgKSB7XG5cdFx0XHRoYXNEdXBsaWNhdGUgPSB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gMDtcblx0fSxcblxuXHQvLyBJbnN0YW5jZSBtZXRob2RzXG5cdGhhc093biA9ICh7fSkuaGFzT3duUHJvcGVydHksXG5cdGFyciA9IFtdLFxuXHRwb3AgPSBhcnIucG9wLFxuXHRwdXNoX25hdGl2ZSA9IGFyci5wdXNoLFxuXHRwdXNoID0gYXJyLnB1c2gsXG5cdHNsaWNlID0gYXJyLnNsaWNlLFxuXHQvLyBVc2UgYSBzdHJpcHBlZC1kb3duIGluZGV4T2YgYXMgaXQncyBmYXN0ZXIgdGhhbiBuYXRpdmVcblx0Ly8gaHR0cHM6Ly9qc3BlcmYuY29tL3Rob3ItaW5kZXhvZi12cy1mb3IvNVxuXHRpbmRleE9mID0gZnVuY3Rpb24oIGxpc3QsIGVsZW0gKSB7XG5cdFx0dmFyIGkgPSAwLFxuXHRcdFx0bGVuID0gbGlzdC5sZW5ndGg7XG5cdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRpZiAoIGxpc3RbaV0gPT09IGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gLTE7XG5cdH0sXG5cblx0Ym9vbGVhbnMgPSBcImNoZWNrZWR8c2VsZWN0ZWR8YXN5bmN8YXV0b2ZvY3VzfGF1dG9wbGF5fGNvbnRyb2xzfGRlZmVyfGRpc2FibGVkfGhpZGRlbnxpc21hcHxsb29wfG11bHRpcGxlfG9wZW58cmVhZG9ubHl8cmVxdWlyZWR8c2NvcGVkXCIsXG5cblx0Ly8gUmVndWxhciBleHByZXNzaW9uc1xuXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL2NzczMtc2VsZWN0b3JzLyN3aGl0ZXNwYWNlXG5cdHdoaXRlc3BhY2UgPSBcIltcXFxceDIwXFxcXHRcXFxcclxcXFxuXFxcXGZdXCIsXG5cblx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvQ1NTMjEvc3luZGF0YS5odG1sI3ZhbHVlLWRlZi1pZGVudGlmaWVyXG5cdGlkZW50aWZpZXIgPSBcIig/OlxcXFxcXFxcLnxbXFxcXHctXXxbXlxcMC1cXFxceGEwXSkrXCIsXG5cblx0Ly8gQXR0cmlidXRlIHNlbGVjdG9yczogaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNhdHRyaWJ1dGUtc2VsZWN0b3JzXG5cdGF0dHJpYnV0ZXMgPSBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFwiICsgaWRlbnRpZmllciArIFwiKSg/OlwiICsgd2hpdGVzcGFjZSArXG5cdFx0Ly8gT3BlcmF0b3IgKGNhcHR1cmUgMilcblx0XHRcIiooWypeJHwhfl0/PSlcIiArIHdoaXRlc3BhY2UgK1xuXHRcdC8vIFwiQXR0cmlidXRlIHZhbHVlcyBtdXN0IGJlIENTUyBpZGVudGlmaWVycyBbY2FwdHVyZSA1XSBvciBzdHJpbmdzIFtjYXB0dXJlIDMgb3IgY2FwdHVyZSA0XVwiXG5cdFx0XCIqKD86JygoPzpcXFxcXFxcXC58W15cXFxcXFxcXCddKSopJ3xcXFwiKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcXFxcIl0pKilcXFwifChcIiArIGlkZW50aWZpZXIgKyBcIikpfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFwiKlxcXFxdXCIsXG5cblx0cHNldWRvcyA9IFwiOihcIiArIGlkZW50aWZpZXIgKyBcIikoPzpcXFxcKChcIiArXG5cdFx0Ly8gVG8gcmVkdWNlIHRoZSBudW1iZXIgb2Ygc2VsZWN0b3JzIG5lZWRpbmcgdG9rZW5pemUgaW4gdGhlIHByZUZpbHRlciwgcHJlZmVyIGFyZ3VtZW50czpcblx0XHQvLyAxLiBxdW90ZWQgKGNhcHR1cmUgMzsgY2FwdHVyZSA0IG9yIGNhcHR1cmUgNSlcblx0XHRcIignKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcJ10pKiknfFxcXCIoKD86XFxcXFxcXFwufFteXFxcXFxcXFxcXFwiXSkqKVxcXCIpfFwiICtcblx0XHQvLyAyLiBzaW1wbGUgKGNhcHR1cmUgNilcblx0XHRcIigoPzpcXFxcXFxcXC58W15cXFxcXFxcXCgpW1xcXFxdXXxcIiArIGF0dHJpYnV0ZXMgKyBcIikqKXxcIiArXG5cdFx0Ly8gMy4gYW55dGhpbmcgZWxzZSAoY2FwdHVyZSAyKVxuXHRcdFwiLipcIiArXG5cdFx0XCIpXFxcXCl8KVwiLFxuXG5cdC8vIExlYWRpbmcgYW5kIG5vbi1lc2NhcGVkIHRyYWlsaW5nIHdoaXRlc3BhY2UsIGNhcHR1cmluZyBzb21lIG5vbi13aGl0ZXNwYWNlIGNoYXJhY3RlcnMgcHJlY2VkaW5nIHRoZSBsYXR0ZXJcblx0cndoaXRlc3BhY2UgPSBuZXcgUmVnRXhwKCB3aGl0ZXNwYWNlICsgXCIrXCIsIFwiZ1wiICksXG5cdHJ0cmltID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIrfCgoPzpefFteXFxcXFxcXFxdKSg/OlxcXFxcXFxcLikqKVwiICsgd2hpdGVzcGFjZSArIFwiKyRcIiwgXCJnXCIgKSxcblxuXHRyY29tbWEgPSBuZXcgUmVnRXhwKCBcIl5cIiArIHdoaXRlc3BhY2UgKyBcIiosXCIgKyB3aGl0ZXNwYWNlICsgXCIqXCIgKSxcblx0cmNvbWJpbmF0b3JzID0gbmV3IFJlZ0V4cCggXCJeXCIgKyB3aGl0ZXNwYWNlICsgXCIqKFs+K35dfFwiICsgd2hpdGVzcGFjZSArIFwiKVwiICsgd2hpdGVzcGFjZSArIFwiKlwiICksXG5cblx0cmF0dHJpYnV0ZVF1b3RlcyA9IG5ldyBSZWdFeHAoIFwiPVwiICsgd2hpdGVzcGFjZSArIFwiKihbXlxcXFxdJ1xcXCJdKj8pXCIgKyB3aGl0ZXNwYWNlICsgXCIqXFxcXF1cIiwgXCJnXCIgKSxcblxuXHRycHNldWRvID0gbmV3IFJlZ0V4cCggcHNldWRvcyApLFxuXHRyaWRlbnRpZmllciA9IG5ldyBSZWdFeHAoIFwiXlwiICsgaWRlbnRpZmllciArIFwiJFwiICksXG5cblx0bWF0Y2hFeHByID0ge1xuXHRcdFwiSURcIjogbmV3IFJlZ0V4cCggXCJeIyhcIiArIGlkZW50aWZpZXIgKyBcIilcIiApLFxuXHRcdFwiQ0xBU1NcIjogbmV3IFJlZ0V4cCggXCJeXFxcXC4oXCIgKyBpZGVudGlmaWVyICsgXCIpXCIgKSxcblx0XHRcIlRBR1wiOiBuZXcgUmVnRXhwKCBcIl4oXCIgKyBpZGVudGlmaWVyICsgXCJ8WypdKVwiICksXG5cdFx0XCJBVFRSXCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgYXR0cmlidXRlcyApLFxuXHRcdFwiUFNFVURPXCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgcHNldWRvcyApLFxuXHRcdFwiQ0hJTERcIjogbmV3IFJlZ0V4cCggXCJeOihvbmx5fGZpcnN0fGxhc3R8bnRofG50aC1sYXN0KS0oY2hpbGR8b2YtdHlwZSkoPzpcXFxcKFwiICsgd2hpdGVzcGFjZSArXG5cdFx0XHRcIiooZXZlbnxvZGR8KChbKy1dfCkoXFxcXGQqKW58KVwiICsgd2hpdGVzcGFjZSArIFwiKig/OihbKy1dfClcIiArIHdoaXRlc3BhY2UgK1xuXHRcdFx0XCIqKFxcXFxkKyl8KSlcIiArIHdoaXRlc3BhY2UgKyBcIipcXFxcKXwpXCIsIFwiaVwiICksXG5cdFx0XCJib29sXCI6IG5ldyBSZWdFeHAoIFwiXig/OlwiICsgYm9vbGVhbnMgKyBcIikkXCIsIFwiaVwiICksXG5cdFx0Ly8gRm9yIHVzZSBpbiBsaWJyYXJpZXMgaW1wbGVtZW50aW5nIC5pcygpXG5cdFx0Ly8gV2UgdXNlIHRoaXMgZm9yIFBPUyBtYXRjaGluZyBpbiBgc2VsZWN0YFxuXHRcdFwibmVlZHNDb250ZXh0XCI6IG5ldyBSZWdFeHAoIFwiXlwiICsgd2hpdGVzcGFjZSArIFwiKls+K35dfDooZXZlbnxvZGR8ZXF8Z3R8bHR8bnRofGZpcnN0fGxhc3QpKD86XFxcXChcIiArXG5cdFx0XHR3aGl0ZXNwYWNlICsgXCIqKCg/Oi1cXFxcZCk/XFxcXGQqKVwiICsgd2hpdGVzcGFjZSArIFwiKlxcXFwpfCkoPz1bXi1dfCQpXCIsIFwiaVwiIClcblx0fSxcblxuXHRyaW5wdXRzID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8YnV0dG9uKSQvaSxcblx0cmhlYWRlciA9IC9eaFxcZCQvaSxcblxuXHRybmF0aXZlID0gL15bXntdK1xce1xccypcXFtuYXRpdmUgXFx3LyxcblxuXHQvLyBFYXNpbHktcGFyc2VhYmxlL3JldHJpZXZhYmxlIElEIG9yIFRBRyBvciBDTEFTUyBzZWxlY3RvcnNcblx0cnF1aWNrRXhwciA9IC9eKD86IyhbXFx3LV0rKXwoXFx3Kyl8XFwuKFtcXHctXSspKSQvLFxuXG5cdHJzaWJsaW5nID0gL1srfl0vLFxuXG5cdC8vIENTUyBlc2NhcGVzXG5cdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL0NTUzIxL3N5bmRhdGEuaHRtbCNlc2NhcGVkLWNoYXJhY3RlcnNcblx0cnVuZXNjYXBlID0gbmV3IFJlZ0V4cCggXCJcXFxcXFxcXChbXFxcXGRhLWZdezEsNn1cIiArIHdoaXRlc3BhY2UgKyBcIj98KFwiICsgd2hpdGVzcGFjZSArIFwiKXwuKVwiLCBcImlnXCIgKSxcblx0ZnVuZXNjYXBlID0gZnVuY3Rpb24oIF8sIGVzY2FwZWQsIGVzY2FwZWRXaGl0ZXNwYWNlICkge1xuXHRcdHZhciBoaWdoID0gXCIweFwiICsgZXNjYXBlZCAtIDB4MTAwMDA7XG5cdFx0Ly8gTmFOIG1lYW5zIG5vbi1jb2RlcG9pbnRcblx0XHQvLyBTdXBwb3J0OiBGaXJlZm94PDI0XG5cdFx0Ly8gV29ya2Fyb3VuZCBlcnJvbmVvdXMgbnVtZXJpYyBpbnRlcnByZXRhdGlvbiBvZiArXCIweFwiXG5cdFx0cmV0dXJuIGhpZ2ggIT09IGhpZ2ggfHwgZXNjYXBlZFdoaXRlc3BhY2UgP1xuXHRcdFx0ZXNjYXBlZCA6XG5cdFx0XHRoaWdoIDwgMCA/XG5cdFx0XHRcdC8vIEJNUCBjb2RlcG9pbnRcblx0XHRcdFx0U3RyaW5nLmZyb21DaGFyQ29kZSggaGlnaCArIDB4MTAwMDAgKSA6XG5cdFx0XHRcdC8vIFN1cHBsZW1lbnRhbCBQbGFuZSBjb2RlcG9pbnQgKHN1cnJvZ2F0ZSBwYWlyKVxuXHRcdFx0XHRTdHJpbmcuZnJvbUNoYXJDb2RlKCBoaWdoID4+IDEwIHwgMHhEODAwLCBoaWdoICYgMHgzRkYgfCAweERDMDAgKTtcblx0fSxcblxuXHQvLyBDU1Mgc3RyaW5nL2lkZW50aWZpZXIgc2VyaWFsaXphdGlvblxuXHQvLyBodHRwczovL2RyYWZ0cy5jc3N3Zy5vcmcvY3Nzb20vI2NvbW1vbi1zZXJpYWxpemluZy1pZGlvbXNcblx0cmNzc2VzY2FwZSA9IC8oW1xcMC1cXHgxZlxceDdmXXxeLT9cXGQpfF4tJHxbXlxcMC1cXHgxZlxceDdmLVxcdUZGRkZcXHctXS9nLFxuXHRmY3NzZXNjYXBlID0gZnVuY3Rpb24oIGNoLCBhc0NvZGVQb2ludCApIHtcblx0XHRpZiAoIGFzQ29kZVBvaW50ICkge1xuXG5cdFx0XHQvLyBVKzAwMDAgTlVMTCBiZWNvbWVzIFUrRkZGRCBSRVBMQUNFTUVOVCBDSEFSQUNURVJcblx0XHRcdGlmICggY2ggPT09IFwiXFwwXCIgKSB7XG5cdFx0XHRcdHJldHVybiBcIlxcdUZGRkRcIjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udHJvbCBjaGFyYWN0ZXJzIGFuZCAoZGVwZW5kZW50IHVwb24gcG9zaXRpb24pIG51bWJlcnMgZ2V0IGVzY2FwZWQgYXMgY29kZSBwb2ludHNcblx0XHRcdHJldHVybiBjaC5zbGljZSggMCwgLTEgKSArIFwiXFxcXFwiICsgY2guY2hhckNvZGVBdCggY2gubGVuZ3RoIC0gMSApLnRvU3RyaW5nKCAxNiApICsgXCIgXCI7XG5cdFx0fVxuXG5cdFx0Ly8gT3RoZXIgcG90ZW50aWFsbHktc3BlY2lhbCBBU0NJSSBjaGFyYWN0ZXJzIGdldCBiYWNrc2xhc2gtZXNjYXBlZFxuXHRcdHJldHVybiBcIlxcXFxcIiArIGNoO1xuXHR9LFxuXG5cdC8vIFVzZWQgZm9yIGlmcmFtZXNcblx0Ly8gU2VlIHNldERvY3VtZW50KClcblx0Ly8gUmVtb3ZpbmcgdGhlIGZ1bmN0aW9uIHdyYXBwZXIgY2F1c2VzIGEgXCJQZXJtaXNzaW9uIERlbmllZFwiXG5cdC8vIGVycm9yIGluIElFXG5cdHVubG9hZEhhbmRsZXIgPSBmdW5jdGlvbigpIHtcblx0XHRzZXREb2N1bWVudCgpO1xuXHR9LFxuXG5cdGRpc2FibGVkQW5jZXN0b3IgPSBhZGRDb21iaW5hdG9yKFxuXHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IHRydWUgJiYgKFwiZm9ybVwiIGluIGVsZW0gfHwgXCJsYWJlbFwiIGluIGVsZW0pO1xuXHRcdH0sXG5cdFx0eyBkaXI6IFwicGFyZW50Tm9kZVwiLCBuZXh0OiBcImxlZ2VuZFwiIH1cblx0KTtcblxuLy8gT3B0aW1pemUgZm9yIHB1c2guYXBwbHkoIF8sIE5vZGVMaXN0IClcbnRyeSB7XG5cdHB1c2guYXBwbHkoXG5cdFx0KGFyciA9IHNsaWNlLmNhbGwoIHByZWZlcnJlZERvYy5jaGlsZE5vZGVzICkpLFxuXHRcdHByZWZlcnJlZERvYy5jaGlsZE5vZGVzXG5cdCk7XG5cdC8vIFN1cHBvcnQ6IEFuZHJvaWQ8NC4wXG5cdC8vIERldGVjdCBzaWxlbnRseSBmYWlsaW5nIHB1c2guYXBwbHlcblx0YXJyWyBwcmVmZXJyZWREb2MuY2hpbGROb2Rlcy5sZW5ndGggXS5ub2RlVHlwZTtcbn0gY2F0Y2ggKCBlICkge1xuXHRwdXNoID0geyBhcHBseTogYXJyLmxlbmd0aCA/XG5cblx0XHQvLyBMZXZlcmFnZSBzbGljZSBpZiBwb3NzaWJsZVxuXHRcdGZ1bmN0aW9uKCB0YXJnZXQsIGVscyApIHtcblx0XHRcdHB1c2hfbmF0aXZlLmFwcGx5KCB0YXJnZXQsIHNsaWNlLmNhbGwoZWxzKSApO1xuXHRcdH0gOlxuXG5cdFx0Ly8gU3VwcG9ydDogSUU8OVxuXHRcdC8vIE90aGVyd2lzZSBhcHBlbmQgZGlyZWN0bHlcblx0XHRmdW5jdGlvbiggdGFyZ2V0LCBlbHMgKSB7XG5cdFx0XHR2YXIgaiA9IHRhcmdldC5sZW5ndGgsXG5cdFx0XHRcdGkgPSAwO1xuXHRcdFx0Ly8gQ2FuJ3QgdHJ1c3QgTm9kZUxpc3QubGVuZ3RoXG5cdFx0XHR3aGlsZSAoICh0YXJnZXRbaisrXSA9IGVsc1tpKytdKSApIHt9XG5cdFx0XHR0YXJnZXQubGVuZ3RoID0gaiAtIDE7XG5cdFx0fVxuXHR9O1xufVxuXG5mdW5jdGlvbiBTaXp6bGUoIHNlbGVjdG9yLCBjb250ZXh0LCByZXN1bHRzLCBzZWVkICkge1xuXHR2YXIgbSwgaSwgZWxlbSwgbmlkLCBtYXRjaCwgZ3JvdXBzLCBuZXdTZWxlY3Rvcixcblx0XHRuZXdDb250ZXh0ID0gY29udGV4dCAmJiBjb250ZXh0Lm93bmVyRG9jdW1lbnQsXG5cblx0XHQvLyBub2RlVHlwZSBkZWZhdWx0cyB0byA5LCBzaW5jZSBjb250ZXh0IGRlZmF1bHRzIHRvIGRvY3VtZW50XG5cdFx0bm9kZVR5cGUgPSBjb250ZXh0ID8gY29udGV4dC5ub2RlVHlwZSA6IDk7XG5cblx0cmVzdWx0cyA9IHJlc3VsdHMgfHwgW107XG5cblx0Ly8gUmV0dXJuIGVhcmx5IGZyb20gY2FsbHMgd2l0aCBpbnZhbGlkIHNlbGVjdG9yIG9yIGNvbnRleHRcblx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgfHwgIXNlbGVjdG9yIHx8XG5cdFx0bm9kZVR5cGUgIT09IDEgJiYgbm9kZVR5cGUgIT09IDkgJiYgbm9kZVR5cGUgIT09IDExICkge1xuXG5cdFx0cmV0dXJuIHJlc3VsdHM7XG5cdH1cblxuXHQvLyBUcnkgdG8gc2hvcnRjdXQgZmluZCBvcGVyYXRpb25zIChhcyBvcHBvc2VkIHRvIGZpbHRlcnMpIGluIEhUTUwgZG9jdW1lbnRzXG5cdGlmICggIXNlZWQgKSB7XG5cblx0XHRpZiAoICggY29udGV4dCA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogcHJlZmVycmVkRG9jICkgIT09IGRvY3VtZW50ICkge1xuXHRcdFx0c2V0RG9jdW1lbnQoIGNvbnRleHQgKTtcblx0XHR9XG5cdFx0Y29udGV4dCA9IGNvbnRleHQgfHwgZG9jdW1lbnQ7XG5cblx0XHRpZiAoIGRvY3VtZW50SXNIVE1MICkge1xuXG5cdFx0XHQvLyBJZiB0aGUgc2VsZWN0b3IgaXMgc3VmZmljaWVudGx5IHNpbXBsZSwgdHJ5IHVzaW5nIGEgXCJnZXQqQnkqXCIgRE9NIG1ldGhvZFxuXHRcdFx0Ly8gKGV4Y2VwdGluZyBEb2N1bWVudEZyYWdtZW50IGNvbnRleHQsIHdoZXJlIHRoZSBtZXRob2RzIGRvbid0IGV4aXN0KVxuXHRcdFx0aWYgKCBub2RlVHlwZSAhPT0gMTEgJiYgKG1hdGNoID0gcnF1aWNrRXhwci5leGVjKCBzZWxlY3RvciApKSApIHtcblxuXHRcdFx0XHQvLyBJRCBzZWxlY3RvclxuXHRcdFx0XHRpZiAoIChtID0gbWF0Y2hbMV0pICkge1xuXG5cdFx0XHRcdFx0Ly8gRG9jdW1lbnQgY29udGV4dFxuXHRcdFx0XHRcdGlmICggbm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIChlbGVtID0gY29udGV4dC5nZXRFbGVtZW50QnlJZCggbSApKSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSwgT3BlcmEsIFdlYmtpdFxuXHRcdFx0XHRcdFx0XHQvLyBUT0RPOiBpZGVudGlmeSB2ZXJzaW9uc1xuXHRcdFx0XHRcdFx0XHQvLyBnZXRFbGVtZW50QnlJZCBjYW4gbWF0Y2ggZWxlbWVudHMgYnkgbmFtZSBpbnN0ZWFkIG9mIElEXG5cdFx0XHRcdFx0XHRcdGlmICggZWxlbS5pZCA9PT0gbSApIHtcblx0XHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBFbGVtZW50IGNvbnRleHRcblx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSwgT3BlcmEsIFdlYmtpdFxuXHRcdFx0XHRcdFx0Ly8gVE9ETzogaWRlbnRpZnkgdmVyc2lvbnNcblx0XHRcdFx0XHRcdC8vIGdldEVsZW1lbnRCeUlkIGNhbiBtYXRjaCBlbGVtZW50cyBieSBuYW1lIGluc3RlYWQgb2YgSURcblx0XHRcdFx0XHRcdGlmICggbmV3Q29udGV4dCAmJiAoZWxlbSA9IG5ld0NvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIG0gKSkgJiZcblx0XHRcdFx0XHRcdFx0Y29udGFpbnMoIGNvbnRleHQsIGVsZW0gKSAmJlxuXHRcdFx0XHRcdFx0XHRlbGVtLmlkID09PSBtICkge1xuXG5cdFx0XHRcdFx0XHRcdHJlc3VsdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHlwZSBzZWxlY3RvclxuXHRcdFx0XHR9IGVsc2UgaWYgKCBtYXRjaFsyXSApIHtcblx0XHRcdFx0XHRwdXNoLmFwcGx5KCByZXN1bHRzLCBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCBzZWxlY3RvciApICk7XG5cdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cblx0XHRcdFx0Ly8gQ2xhc3Mgc2VsZWN0b3Jcblx0XHRcdFx0fSBlbHNlIGlmICggKG0gPSBtYXRjaFszXSkgJiYgc3VwcG9ydC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICYmXG5cdFx0XHRcdFx0Y29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lICkge1xuXG5cdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgY29udGV4dC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCBtICkgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmVzdWx0cztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBUYWtlIGFkdmFudGFnZSBvZiBxdWVyeVNlbGVjdG9yQWxsXG5cdFx0XHRpZiAoIHN1cHBvcnQucXNhICYmXG5cdFx0XHRcdCFjb21waWxlckNhY2hlWyBzZWxlY3RvciArIFwiIFwiIF0gJiZcblx0XHRcdFx0KCFyYnVnZ3lRU0EgfHwgIXJidWdneVFTQS50ZXN0KCBzZWxlY3RvciApKSApIHtcblxuXHRcdFx0XHRpZiAoIG5vZGVUeXBlICE9PSAxICkge1xuXHRcdFx0XHRcdG5ld0NvbnRleHQgPSBjb250ZXh0O1xuXHRcdFx0XHRcdG5ld1NlbGVjdG9yID0gc2VsZWN0b3I7XG5cblx0XHRcdFx0Ly8gcVNBIGxvb2tzIG91dHNpZGUgRWxlbWVudCBjb250ZXh0LCB3aGljaCBpcyBub3Qgd2hhdCB3ZSB3YW50XG5cdFx0XHRcdC8vIFRoYW5rcyB0byBBbmRyZXcgRHVwb250IGZvciB0aGlzIHdvcmthcm91bmQgdGVjaG5pcXVlXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OFxuXHRcdFx0XHQvLyBFeGNsdWRlIG9iamVjdCBlbGVtZW50c1xuXHRcdFx0XHR9IGVsc2UgaWYgKCBjb250ZXh0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHRcdFx0XHQvLyBDYXB0dXJlIHRoZSBjb250ZXh0IElELCBzZXR0aW5nIGl0IGZpcnN0IGlmIG5lY2Vzc2FyeVxuXHRcdFx0XHRcdGlmICggKG5pZCA9IGNvbnRleHQuZ2V0QXR0cmlidXRlKCBcImlkXCIgKSkgKSB7XG5cdFx0XHRcdFx0XHRuaWQgPSBuaWQucmVwbGFjZSggcmNzc2VzY2FwZSwgZmNzc2VzY2FwZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRjb250ZXh0LnNldEF0dHJpYnV0ZSggXCJpZFwiLCAobmlkID0gZXhwYW5kbykgKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBQcmVmaXggZXZlcnkgc2VsZWN0b3IgaW4gdGhlIGxpc3Rcblx0XHRcdFx0XHRncm91cHMgPSB0b2tlbml6ZSggc2VsZWN0b3IgKTtcblx0XHRcdFx0XHRpID0gZ3JvdXBzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0XHRcdGdyb3Vwc1tpXSA9IFwiI1wiICsgbmlkICsgXCIgXCIgKyB0b1NlbGVjdG9yKCBncm91cHNbaV0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bmV3U2VsZWN0b3IgPSBncm91cHMuam9pbiggXCIsXCIgKTtcblxuXHRcdFx0XHRcdC8vIEV4cGFuZCBjb250ZXh0IGZvciBzaWJsaW5nIHNlbGVjdG9yc1xuXHRcdFx0XHRcdG5ld0NvbnRleHQgPSByc2libGluZy50ZXN0KCBzZWxlY3RvciApICYmIHRlc3RDb250ZXh0KCBjb250ZXh0LnBhcmVudE5vZGUgKSB8fFxuXHRcdFx0XHRcdFx0Y29udGV4dDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICggbmV3U2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHB1c2guYXBwbHkoIHJlc3VsdHMsXG5cdFx0XHRcdFx0XHRcdG5ld0NvbnRleHQucXVlcnlTZWxlY3RvckFsbCggbmV3U2VsZWN0b3IgKVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKCBxc2FFcnJvciApIHtcblx0XHRcdFx0XHR9IGZpbmFsbHkge1xuXHRcdFx0XHRcdFx0aWYgKCBuaWQgPT09IGV4cGFuZG8gKSB7XG5cdFx0XHRcdFx0XHRcdGNvbnRleHQucmVtb3ZlQXR0cmlidXRlKCBcImlkXCIgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBBbGwgb3RoZXJzXG5cdHJldHVybiBzZWxlY3QoIHNlbGVjdG9yLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApO1xufVxuXG4vKipcbiAqIENyZWF0ZSBrZXktdmFsdWUgY2FjaGVzIG9mIGxpbWl0ZWQgc2l6ZVxuICogQHJldHVybnMge2Z1bmN0aW9uKHN0cmluZywgb2JqZWN0KX0gUmV0dXJucyB0aGUgT2JqZWN0IGRhdGEgYWZ0ZXIgc3RvcmluZyBpdCBvbiBpdHNlbGYgd2l0aFxuICpcdHByb3BlcnR5IG5hbWUgdGhlIChzcGFjZS1zdWZmaXhlZCkgc3RyaW5nIGFuZCAoaWYgdGhlIGNhY2hlIGlzIGxhcmdlciB0aGFuIEV4cHIuY2FjaGVMZW5ndGgpXG4gKlx0ZGVsZXRpbmcgdGhlIG9sZGVzdCBlbnRyeVxuICovXG5mdW5jdGlvbiBjcmVhdGVDYWNoZSgpIHtcblx0dmFyIGtleXMgPSBbXTtcblxuXHRmdW5jdGlvbiBjYWNoZSgga2V5LCB2YWx1ZSApIHtcblx0XHQvLyBVc2UgKGtleSArIFwiIFwiKSB0byBhdm9pZCBjb2xsaXNpb24gd2l0aCBuYXRpdmUgcHJvdG90eXBlIHByb3BlcnRpZXMgKHNlZSBJc3N1ZSAjMTU3KVxuXHRcdGlmICgga2V5cy5wdXNoKCBrZXkgKyBcIiBcIiApID4gRXhwci5jYWNoZUxlbmd0aCApIHtcblx0XHRcdC8vIE9ubHkga2VlcCB0aGUgbW9zdCByZWNlbnQgZW50cmllc1xuXHRcdFx0ZGVsZXRlIGNhY2hlWyBrZXlzLnNoaWZ0KCkgXTtcblx0XHR9XG5cdFx0cmV0dXJuIChjYWNoZVsga2V5ICsgXCIgXCIgXSA9IHZhbHVlKTtcblx0fVxuXHRyZXR1cm4gY2FjaGU7XG59XG5cbi8qKlxuICogTWFyayBhIGZ1bmN0aW9uIGZvciBzcGVjaWFsIHVzZSBieSBTaXp6bGVcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFRoZSBmdW5jdGlvbiB0byBtYXJrXG4gKi9cbmZ1bmN0aW9uIG1hcmtGdW5jdGlvbiggZm4gKSB7XG5cdGZuWyBleHBhbmRvIF0gPSB0cnVlO1xuXHRyZXR1cm4gZm47XG59XG5cbi8qKlxuICogU3VwcG9ydCB0ZXN0aW5nIHVzaW5nIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIFBhc3NlZCB0aGUgY3JlYXRlZCBlbGVtZW50IGFuZCByZXR1cm5zIGEgYm9vbGVhbiByZXN1bHRcbiAqL1xuZnVuY3Rpb24gYXNzZXJ0KCBmbiApIHtcblx0dmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImZpZWxkc2V0XCIpO1xuXG5cdHRyeSB7XG5cdFx0cmV0dXJuICEhZm4oIGVsICk7XG5cdH0gY2F0Y2ggKGUpIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH0gZmluYWxseSB7XG5cdFx0Ly8gUmVtb3ZlIGZyb20gaXRzIHBhcmVudCBieSBkZWZhdWx0XG5cdFx0aWYgKCBlbC5wYXJlbnROb2RlICkge1xuXHRcdFx0ZWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCggZWwgKTtcblx0XHR9XG5cdFx0Ly8gcmVsZWFzZSBtZW1vcnkgaW4gSUVcblx0XHRlbCA9IG51bGw7XG5cdH1cbn1cblxuLyoqXG4gKiBBZGRzIHRoZSBzYW1lIGhhbmRsZXIgZm9yIGFsbCBvZiB0aGUgc3BlY2lmaWVkIGF0dHJzXG4gKiBAcGFyYW0ge1N0cmluZ30gYXR0cnMgUGlwZS1zZXBhcmF0ZWQgbGlzdCBvZiBhdHRyaWJ1dGVzXG4gKiBAcGFyYW0ge0Z1bmN0aW9ufSBoYW5kbGVyIFRoZSBtZXRob2QgdGhhdCB3aWxsIGJlIGFwcGxpZWRcbiAqL1xuZnVuY3Rpb24gYWRkSGFuZGxlKCBhdHRycywgaGFuZGxlciApIHtcblx0dmFyIGFyciA9IGF0dHJzLnNwbGl0KFwifFwiKSxcblx0XHRpID0gYXJyLmxlbmd0aDtcblxuXHR3aGlsZSAoIGktLSApIHtcblx0XHRFeHByLmF0dHJIYW5kbGVbIGFycltpXSBdID0gaGFuZGxlcjtcblx0fVxufVxuXG4vKipcbiAqIENoZWNrcyBkb2N1bWVudCBvcmRlciBvZiB0d28gc2libGluZ3NcbiAqIEBwYXJhbSB7RWxlbWVudH0gYVxuICogQHBhcmFtIHtFbGVtZW50fSBiXG4gKiBAcmV0dXJucyB7TnVtYmVyfSBSZXR1cm5zIGxlc3MgdGhhbiAwIGlmIGEgcHJlY2VkZXMgYiwgZ3JlYXRlciB0aGFuIDAgaWYgYSBmb2xsb3dzIGJcbiAqL1xuZnVuY3Rpb24gc2libGluZ0NoZWNrKCBhLCBiICkge1xuXHR2YXIgY3VyID0gYiAmJiBhLFxuXHRcdGRpZmYgPSBjdXIgJiYgYS5ub2RlVHlwZSA9PT0gMSAmJiBiLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRhLnNvdXJjZUluZGV4IC0gYi5zb3VyY2VJbmRleDtcblxuXHQvLyBVc2UgSUUgc291cmNlSW5kZXggaWYgYXZhaWxhYmxlIG9uIGJvdGggbm9kZXNcblx0aWYgKCBkaWZmICkge1xuXHRcdHJldHVybiBkaWZmO1xuXHR9XG5cblx0Ly8gQ2hlY2sgaWYgYiBmb2xsb3dzIGFcblx0aWYgKCBjdXIgKSB7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLm5leHRTaWJsaW5nKSApIHtcblx0XHRcdGlmICggY3VyID09PSBiICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGEgPyAxIDogLTE7XG59XG5cbi8qKlxuICogUmV0dXJucyBhIGZ1bmN0aW9uIHRvIHVzZSBpbiBwc2V1ZG9zIGZvciBpbnB1dCB0eXBlc1xuICogQHBhcmFtIHtTdHJpbmd9IHR5cGVcbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5wdXRQc2V1ZG8oIHR5cGUgKSB7XG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHR2YXIgbmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIGJ1dHRvbnNcbiAqIEBwYXJhbSB7U3RyaW5nfSB0eXBlXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZUJ1dHRvblBzZXVkbyggdHlwZSApIHtcblx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBuYW1lID0gZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdHJldHVybiAobmFtZSA9PT0gXCJpbnB1dFwiIHx8IG5hbWUgPT09IFwiYnV0dG9uXCIpICYmIGVsZW0udHlwZSA9PT0gdHlwZTtcblx0fTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gdG8gdXNlIGluIHBzZXVkb3MgZm9yIDplbmFibGVkLzpkaXNhYmxlZFxuICogQHBhcmFtIHtCb29sZWFufSBkaXNhYmxlZCB0cnVlIGZvciA6ZGlzYWJsZWQ7IGZhbHNlIGZvciA6ZW5hYmxlZFxuICovXG5mdW5jdGlvbiBjcmVhdGVEaXNhYmxlZFBzZXVkbyggZGlzYWJsZWQgKSB7XG5cblx0Ly8gS25vd24gOmRpc2FibGVkIGZhbHNlIHBvc2l0aXZlczogZmllbGRzZXRbZGlzYWJsZWRdID4gbGVnZW5kOm50aC1vZi10eXBlKG4rMikgOmNhbi1kaXNhYmxlXG5cdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdC8vIE9ubHkgY2VydGFpbiBlbGVtZW50cyBjYW4gbWF0Y2ggOmVuYWJsZWQgb3IgOmRpc2FibGVkXG5cdFx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2Uvc2NyaXB0aW5nLmh0bWwjc2VsZWN0b3ItZW5hYmxlZFxuXHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3NjcmlwdGluZy5odG1sI3NlbGVjdG9yLWRpc2FibGVkXG5cdFx0aWYgKCBcImZvcm1cIiBpbiBlbGVtICkge1xuXG5cdFx0XHQvLyBDaGVjayBmb3IgaW5oZXJpdGVkIGRpc2FibGVkbmVzcyBvbiByZWxldmFudCBub24tZGlzYWJsZWQgZWxlbWVudHM6XG5cdFx0XHQvLyAqIGxpc3RlZCBmb3JtLWFzc29jaWF0ZWQgZWxlbWVudHMgaW4gYSBkaXNhYmxlZCBmaWVsZHNldFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NhdGVnb3J5LWxpc3RlZFxuXHRcdFx0Ly8gICBodHRwczovL2h0bWwuc3BlYy53aGF0d2cub3JnL211bHRpcGFnZS9mb3Jtcy5odG1sI2NvbmNlcHQtZmUtZGlzYWJsZWRcblx0XHRcdC8vICogb3B0aW9uIGVsZW1lbnRzIGluIGEgZGlzYWJsZWQgb3B0Z3JvdXBcblx0XHRcdC8vICAgaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvZm9ybXMuaHRtbCNjb25jZXB0LW9wdGlvbi1kaXNhYmxlZFxuXHRcdFx0Ly8gQWxsIHN1Y2ggZWxlbWVudHMgaGF2ZSBhIFwiZm9ybVwiIHByb3BlcnR5LlxuXHRcdFx0aWYgKCBlbGVtLnBhcmVudE5vZGUgJiYgZWxlbS5kaXNhYmxlZCA9PT0gZmFsc2UgKSB7XG5cblx0XHRcdFx0Ly8gT3B0aW9uIGVsZW1lbnRzIGRlZmVyIHRvIGEgcGFyZW50IG9wdGdyb3VwIGlmIHByZXNlbnRcblx0XHRcdFx0aWYgKCBcImxhYmVsXCIgaW4gZWxlbSApIHtcblx0XHRcdFx0XHRpZiAoIFwibGFiZWxcIiBpbiBlbGVtLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5wYXJlbnROb2RlLmRpc2FibGVkID09PSBkaXNhYmxlZDtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDYgLSAxMVxuXHRcdFx0XHQvLyBVc2UgdGhlIGlzRGlzYWJsZWQgc2hvcnRjdXQgcHJvcGVydHkgdG8gY2hlY2sgZm9yIGRpc2FibGVkIGZpZWxkc2V0IGFuY2VzdG9yc1xuXHRcdFx0XHRyZXR1cm4gZWxlbS5pc0Rpc2FibGVkID09PSBkaXNhYmxlZCB8fFxuXG5cdFx0XHRcdFx0Ly8gV2hlcmUgdGhlcmUgaXMgbm8gaXNEaXNhYmxlZCwgY2hlY2sgbWFudWFsbHlcblx0XHRcdFx0XHQvKiBqc2hpbnQgLVcwMTggKi9cblx0XHRcdFx0XHRlbGVtLmlzRGlzYWJsZWQgIT09ICFkaXNhYmxlZCAmJlxuXHRcdFx0XHRcdFx0ZGlzYWJsZWRBbmNlc3RvciggZWxlbSApID09PSBkaXNhYmxlZDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXG5cdFx0Ly8gVHJ5IHRvIHdpbm5vdyBvdXQgZWxlbWVudHMgdGhhdCBjYW4ndCBiZSBkaXNhYmxlZCBiZWZvcmUgdHJ1c3RpbmcgdGhlIGRpc2FibGVkIHByb3BlcnR5LlxuXHRcdC8vIFNvbWUgdmljdGltcyBnZXQgY2F1Z2h0IGluIG91ciBuZXQgKGxhYmVsLCBsZWdlbmQsIG1lbnUsIHRyYWNrKSwgYnV0IGl0IHNob3VsZG4ndFxuXHRcdC8vIGV2ZW4gZXhpc3Qgb24gdGhlbSwgbGV0IGFsb25lIGhhdmUgYSBib29sZWFuIHZhbHVlLlxuXHRcdH0gZWxzZSBpZiAoIFwibGFiZWxcIiBpbiBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZGlzYWJsZWQgPT09IGRpc2FibGVkO1xuXHRcdH1cblxuXHRcdC8vIFJlbWFpbmluZyBlbGVtZW50cyBhcmUgbmVpdGhlciA6ZW5hYmxlZCBub3IgOmRpc2FibGVkXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9O1xufVxuXG4vKipcbiAqIFJldHVybnMgYSBmdW5jdGlvbiB0byB1c2UgaW4gcHNldWRvcyBmb3IgcG9zaXRpb25hbHNcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oIGZuICkge1xuXHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBhcmd1bWVudCApIHtcblx0XHRhcmd1bWVudCA9ICthcmd1bWVudDtcblx0XHRyZXR1cm4gbWFya0Z1bmN0aW9uKGZ1bmN0aW9uKCBzZWVkLCBtYXRjaGVzICkge1xuXHRcdFx0dmFyIGosXG5cdFx0XHRcdG1hdGNoSW5kZXhlcyA9IGZuKCBbXSwgc2VlZC5sZW5ndGgsIGFyZ3VtZW50ICksXG5cdFx0XHRcdGkgPSBtYXRjaEluZGV4ZXMubGVuZ3RoO1xuXG5cdFx0XHQvLyBNYXRjaCBlbGVtZW50cyBmb3VuZCBhdCB0aGUgc3BlY2lmaWVkIGluZGV4ZXNcblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRpZiAoIHNlZWRbIChqID0gbWF0Y2hJbmRleGVzW2ldKSBdICkge1xuXHRcdFx0XHRcdHNlZWRbal0gPSAhKG1hdGNoZXNbal0gPSBzZWVkW2pdKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0pO1xuXHR9KTtcbn1cblxuLyoqXG4gKiBDaGVja3MgYSBub2RlIGZvciB2YWxpZGl0eSBhcyBhIFNpenpsZSBjb250ZXh0XG4gKiBAcGFyYW0ge0VsZW1lbnR8T2JqZWN0PX0gY29udGV4dFxuICogQHJldHVybnMge0VsZW1lbnR8T2JqZWN0fEJvb2xlYW59IFRoZSBpbnB1dCBub2RlIGlmIGFjY2VwdGFibGUsIG90aGVyd2lzZSBhIGZhbHN5IHZhbHVlXG4gKi9cbmZ1bmN0aW9uIHRlc3RDb250ZXh0KCBjb250ZXh0ICkge1xuXHRyZXR1cm4gY29udGV4dCAmJiB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBjb250ZXh0O1xufVxuXG4vLyBFeHBvc2Ugc3VwcG9ydCB2YXJzIGZvciBjb252ZW5pZW5jZVxuc3VwcG9ydCA9IFNpenpsZS5zdXBwb3J0ID0ge307XG5cbi8qKlxuICogRGV0ZWN0cyBYTUwgbm9kZXNcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IGVsZW0gQW4gZWxlbWVudCBvciBhIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gVHJ1ZSBpZmYgZWxlbSBpcyBhIG5vbi1IVE1MIFhNTCBub2RlXG4gKi9cbmlzWE1MID0gU2l6emxlLmlzWE1MID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdC8vIGRvY3VtZW50RWxlbWVudCBpcyB2ZXJpZmllZCBmb3IgY2FzZXMgd2hlcmUgaXQgZG9lc24ndCB5ZXQgZXhpc3Rcblx0Ly8gKHN1Y2ggYXMgbG9hZGluZyBpZnJhbWVzIGluIElFIC0gIzQ4MzMpXG5cdHZhciBkb2N1bWVudEVsZW1lbnQgPSBlbGVtICYmIChlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSkuZG9jdW1lbnRFbGVtZW50O1xuXHRyZXR1cm4gZG9jdW1lbnRFbGVtZW50ID8gZG9jdW1lbnRFbGVtZW50Lm5vZGVOYW1lICE9PSBcIkhUTUxcIiA6IGZhbHNlO1xufTtcblxuLyoqXG4gKiBTZXRzIGRvY3VtZW50LXJlbGF0ZWQgdmFyaWFibGVzIG9uY2UgYmFzZWQgb24gdGhlIGN1cnJlbnQgZG9jdW1lbnRcbiAqIEBwYXJhbSB7RWxlbWVudHxPYmplY3R9IFtkb2NdIEFuIGVsZW1lbnQgb3IgZG9jdW1lbnQgb2JqZWN0IHRvIHVzZSB0byBzZXQgdGhlIGRvY3VtZW50XG4gKiBAcmV0dXJucyB7T2JqZWN0fSBSZXR1cm5zIHRoZSBjdXJyZW50IGRvY3VtZW50XG4gKi9cbnNldERvY3VtZW50ID0gU2l6emxlLnNldERvY3VtZW50ID0gZnVuY3Rpb24oIG5vZGUgKSB7XG5cdHZhciBoYXNDb21wYXJlLCBzdWJXaW5kb3csXG5cdFx0ZG9jID0gbm9kZSA/IG5vZGUub3duZXJEb2N1bWVudCB8fCBub2RlIDogcHJlZmVycmVkRG9jO1xuXG5cdC8vIFJldHVybiBlYXJseSBpZiBkb2MgaXMgaW52YWxpZCBvciBhbHJlYWR5IHNlbGVjdGVkXG5cdGlmICggZG9jID09PSBkb2N1bWVudCB8fCBkb2Mubm9kZVR5cGUgIT09IDkgfHwgIWRvYy5kb2N1bWVudEVsZW1lbnQgKSB7XG5cdFx0cmV0dXJuIGRvY3VtZW50O1xuXHR9XG5cblx0Ly8gVXBkYXRlIGdsb2JhbCB2YXJpYWJsZXNcblx0ZG9jdW1lbnQgPSBkb2M7XG5cdGRvY0VsZW0gPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cdGRvY3VtZW50SXNIVE1MID0gIWlzWE1MKCBkb2N1bWVudCApO1xuXG5cdC8vIFN1cHBvcnQ6IElFIDktMTEsIEVkZ2Vcblx0Ly8gQWNjZXNzaW5nIGlmcmFtZSBkb2N1bWVudHMgYWZ0ZXIgdW5sb2FkIHRocm93cyBcInBlcm1pc3Npb24gZGVuaWVkXCIgZXJyb3JzIChqUXVlcnkgIzEzOTM2KVxuXHRpZiAoIHByZWZlcnJlZERvYyAhPT0gZG9jdW1lbnQgJiZcblx0XHQoc3ViV2luZG93ID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcpICYmIHN1YldpbmRvdy50b3AgIT09IHN1YldpbmRvdyApIHtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDExLCBFZGdlXG5cdFx0aWYgKCBzdWJXaW5kb3cuYWRkRXZlbnRMaXN0ZW5lciApIHtcblx0XHRcdHN1YldpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcInVubG9hZFwiLCB1bmxvYWRIYW5kbGVyLCBmYWxzZSApO1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgOSAtIDEwIG9ubHlcblx0XHR9IGVsc2UgaWYgKCBzdWJXaW5kb3cuYXR0YWNoRXZlbnQgKSB7XG5cdFx0XHRzdWJXaW5kb3cuYXR0YWNoRXZlbnQoIFwib251bmxvYWRcIiwgdW5sb2FkSGFuZGxlciApO1xuXHRcdH1cblx0fVxuXG5cdC8qIEF0dHJpYnV0ZXNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG5cdC8vIFN1cHBvcnQ6IElFPDhcblx0Ly8gVmVyaWZ5IHRoYXQgZ2V0QXR0cmlidXRlIHJlYWxseSByZXR1cm5zIGF0dHJpYnV0ZXMgYW5kIG5vdCBwcm9wZXJ0aWVzXG5cdC8vIChleGNlcHRpbmcgSUU4IGJvb2xlYW5zKVxuXHRzdXBwb3J0LmF0dHJpYnV0ZXMgPSBhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdGVsLmNsYXNzTmFtZSA9IFwiaVwiO1xuXHRcdHJldHVybiAhZWwuZ2V0QXR0cmlidXRlKFwiY2xhc3NOYW1lXCIpO1xuXHR9KTtcblxuXHQvKiBnZXRFbGVtZW50KHMpQnkqXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBDaGVjayBpZiBnZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikgcmV0dXJucyBvbmx5IGVsZW1lbnRzXG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgPSBhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdGVsLmFwcGVuZENoaWxkKCBkb2N1bWVudC5jcmVhdGVDb21tZW50KFwiXCIpICk7XG5cdFx0cmV0dXJuICFlbC5nZXRFbGVtZW50c0J5VGFnTmFtZShcIipcIikubGVuZ3RoO1xuXHR9KTtcblxuXHQvLyBTdXBwb3J0OiBJRTw5XG5cdHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSA9IHJuYXRpdmUudGVzdCggZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSApO1xuXG5cdC8vIFN1cHBvcnQ6IElFPDEwXG5cdC8vIENoZWNrIGlmIGdldEVsZW1lbnRCeUlkIHJldHVybnMgZWxlbWVudHMgYnkgbmFtZVxuXHQvLyBUaGUgYnJva2VuIGdldEVsZW1lbnRCeUlkIG1ldGhvZHMgZG9uJ3QgcGljayB1cCBwcm9ncmFtbWF0aWNhbGx5LXNldCBuYW1lcyxcblx0Ly8gc28gdXNlIGEgcm91bmRhYm91dCBnZXRFbGVtZW50c0J5TmFtZSB0ZXN0XG5cdHN1cHBvcnQuZ2V0QnlJZCA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5pZCA9IGV4cGFuZG87XG5cdFx0cmV0dXJuICFkb2N1bWVudC5nZXRFbGVtZW50c0J5TmFtZSB8fCAhZG9jdW1lbnQuZ2V0RWxlbWVudHNCeU5hbWUoIGV4cGFuZG8gKS5sZW5ndGg7XG5cdH0pO1xuXG5cdC8vIElEIGZpbHRlciBhbmQgZmluZFxuXHRpZiAoIHN1cHBvcnQuZ2V0QnlJZCApIHtcblx0XHRFeHByLmZpbHRlcltcIklEXCJdID0gZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0dmFyIGF0dHJJZCA9IGlkLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmdldEF0dHJpYnV0ZShcImlkXCIpID09PSBhdHRySWQ7XG5cdFx0XHR9O1xuXHRcdH07XG5cdFx0RXhwci5maW5kW1wiSURcIl0gPSBmdW5jdGlvbiggaWQsIGNvbnRleHQgKSB7XG5cdFx0XHRpZiAoIHR5cGVvZiBjb250ZXh0LmdldEVsZW1lbnRCeUlkICE9PSBcInVuZGVmaW5lZFwiICYmIGRvY3VtZW50SXNIVE1MICkge1xuXHRcdFx0XHR2YXIgZWxlbSA9IGNvbnRleHQuZ2V0RWxlbWVudEJ5SWQoIGlkICk7XG5cdFx0XHRcdHJldHVybiBlbGVtID8gWyBlbGVtIF0gOiBbXTtcblx0XHRcdH1cblx0XHR9O1xuXHR9IGVsc2Uge1xuXHRcdEV4cHIuZmlsdGVyW1wiSURcIl0gPSAgZnVuY3Rpb24oIGlkICkge1xuXHRcdFx0dmFyIGF0dHJJZCA9IGlkLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHZhciBub2RlID0gdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlTm9kZSAhPT0gXCJ1bmRlZmluZWRcIiAmJlxuXHRcdFx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRyZXR1cm4gbm9kZSAmJiBub2RlLnZhbHVlID09PSBhdHRySWQ7XG5cdFx0XHR9O1xuXHRcdH07XG5cblx0XHQvLyBTdXBwb3J0OiBJRSA2IC0gNyBvbmx5XG5cdFx0Ly8gZ2V0RWxlbWVudEJ5SWQgaXMgbm90IHJlbGlhYmxlIGFzIGEgZmluZCBzaG9ydGN1dFxuXHRcdEV4cHIuZmluZFtcIklEXCJdID0gZnVuY3Rpb24oIGlkLCBjb250ZXh0ICkge1xuXHRcdFx0aWYgKCB0eXBlb2YgY29udGV4dC5nZXRFbGVtZW50QnlJZCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdFx0dmFyIG5vZGUsIGksIGVsZW1zLFxuXHRcdFx0XHRcdGVsZW0gPSBjb250ZXh0LmdldEVsZW1lbnRCeUlkKCBpZCApO1xuXG5cdFx0XHRcdGlmICggZWxlbSApIHtcblxuXHRcdFx0XHRcdC8vIFZlcmlmeSB0aGUgaWQgYXR0cmlidXRlXG5cdFx0XHRcdFx0bm9kZSA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRcdGlmICggbm9kZSAmJiBub2RlLnZhbHVlID09PSBpZCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBbIGVsZW0gXTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBGYWxsIGJhY2sgb24gZ2V0RWxlbWVudHNCeU5hbWVcblx0XHRcdFx0XHRlbGVtcyA9IGNvbnRleHQuZ2V0RWxlbWVudHNCeU5hbWUoIGlkICk7XG5cdFx0XHRcdFx0aSA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1zW2krK10pICkge1xuXHRcdFx0XHRcdFx0bm9kZSA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShcImlkXCIpO1xuXHRcdFx0XHRcdFx0aWYgKCBub2RlICYmIG5vZGUudmFsdWUgPT09IGlkICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gWyBlbGVtIF07XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIFtdO1xuXHRcdFx0fVxuXHRcdH07XG5cdH1cblxuXHQvLyBUYWdcblx0RXhwci5maW5kW1wiVEFHXCJdID0gc3VwcG9ydC5nZXRFbGVtZW50c0J5VGFnTmFtZSA/XG5cdFx0ZnVuY3Rpb24oIHRhZywgY29udGV4dCApIHtcblx0XHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlUYWdOYW1lKCB0YWcgKTtcblxuXHRcdFx0Ly8gRG9jdW1lbnRGcmFnbWVudCBub2RlcyBkb24ndCBoYXZlIGdFQlROXG5cdFx0XHR9IGVsc2UgaWYgKCBzdXBwb3J0LnFzYSApIHtcblx0XHRcdFx0cmV0dXJuIGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCggdGFnICk7XG5cdFx0XHR9XG5cdFx0fSA6XG5cblx0XHRmdW5jdGlvbiggdGFnLCBjb250ZXh0ICkge1xuXHRcdFx0dmFyIGVsZW0sXG5cdFx0XHRcdHRtcCA9IFtdLFxuXHRcdFx0XHRpID0gMCxcblx0XHRcdFx0Ly8gQnkgaGFwcHkgY29pbmNpZGVuY2UsIGEgKGJyb2tlbikgZ0VCVE4gYXBwZWFycyBvbiBEb2N1bWVudEZyYWdtZW50IG5vZGVzIHRvb1xuXHRcdFx0XHRyZXN1bHRzID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnICk7XG5cblx0XHRcdC8vIEZpbHRlciBvdXQgcG9zc2libGUgY29tbWVudHNcblx0XHRcdGlmICggdGFnID09PSBcIipcIiApIHtcblx0XHRcdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0XHRcdFx0dG1wLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdG1wO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0fTtcblxuXHQvLyBDbGFzc1xuXHRFeHByLmZpbmRbXCJDTEFTU1wiXSA9IHN1cHBvcnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAmJiBmdW5jdGlvbiggY2xhc3NOYW1lLCBjb250ZXh0ICkge1xuXHRcdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkb2N1bWVudElzSFRNTCApIHtcblx0XHRcdHJldHVybiBjb250ZXh0LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoIGNsYXNzTmFtZSApO1xuXHRcdH1cblx0fTtcblxuXHQvKiBRU0EvbWF0Y2hlc1NlbGVjdG9yXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBRU0EgYW5kIG1hdGNoZXNTZWxlY3RvciBzdXBwb3J0XG5cblx0Ly8gbWF0Y2hlc1NlbGVjdG9yKDphY3RpdmUpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChJRTkvT3BlcmEgMTEuNSlcblx0cmJ1Z2d5TWF0Y2hlcyA9IFtdO1xuXG5cdC8vIHFTYSg6Zm9jdXMpIHJlcG9ydHMgZmFsc2Ugd2hlbiB0cnVlIChDaHJvbWUgMjEpXG5cdC8vIFdlIGFsbG93IHRoaXMgYmVjYXVzZSBvZiBhIGJ1ZyBpbiBJRTgvOSB0aGF0IHRocm93cyBhbiBlcnJvclxuXHQvLyB3aGVuZXZlciBgZG9jdW1lbnQuYWN0aXZlRWxlbWVudGAgaXMgYWNjZXNzZWQgb24gYW4gaWZyYW1lXG5cdC8vIFNvLCB3ZSBhbGxvdyA6Zm9jdXMgdG8gcGFzcyB0aHJvdWdoIFFTQSBhbGwgdGhlIHRpbWUgdG8gYXZvaWQgdGhlIElFIGVycm9yXG5cdC8vIFNlZSBodHRwczovL2J1Z3MuanF1ZXJ5LmNvbS90aWNrZXQvMTMzNzhcblx0cmJ1Z2d5UVNBID0gW107XG5cblx0aWYgKCAoc3VwcG9ydC5xc2EgPSBybmF0aXZlLnRlc3QoIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwgKSkgKSB7XG5cdFx0Ly8gQnVpbGQgUVNBIHJlZ2V4XG5cdFx0Ly8gUmVnZXggc3RyYXRlZ3kgYWRvcHRlZCBmcm9tIERpZWdvIFBlcmluaVxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHQvLyBTZWxlY3QgaXMgc2V0IHRvIGVtcHR5IHN0cmluZyBvbiBwdXJwb3NlXG5cdFx0XHQvLyBUaGlzIGlzIHRvIHRlc3QgSUUncyB0cmVhdG1lbnQgb2Ygbm90IGV4cGxpY2l0bHlcblx0XHRcdC8vIHNldHRpbmcgYSBib29sZWFuIGNvbnRlbnQgYXR0cmlidXRlLFxuXHRcdFx0Ly8gc2luY2UgaXRzIHByZXNlbmNlIHNob3VsZCBiZSBlbm91Z2hcblx0XHRcdC8vIGh0dHBzOi8vYnVncy5qcXVlcnkuY29tL3RpY2tldC8xMjM1OVxuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5pbm5lckhUTUwgPSBcIjxhIGlkPSdcIiArIGV4cGFuZG8gKyBcIic+PC9hPlwiICtcblx0XHRcdFx0XCI8c2VsZWN0IGlkPSdcIiArIGV4cGFuZG8gKyBcIi1cXHJcXFxcJyBtc2FsbG93Y2FwdHVyZT0nJz5cIiArXG5cdFx0XHRcdFwiPG9wdGlvbiBzZWxlY3RlZD0nJz48L29wdGlvbj48L3NlbGVjdD5cIjtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4LCBPcGVyYSAxMS0xMi4xNlxuXHRcdFx0Ly8gTm90aGluZyBzaG91bGQgYmUgc2VsZWN0ZWQgd2hlbiBlbXB0eSBzdHJpbmdzIGZvbGxvdyBePSBvciAkPSBvciAqPVxuXHRcdFx0Ly8gVGhlIHRlc3QgYXR0cmlidXRlIG11c3QgYmUgdW5rbm93biBpbiBPcGVyYSBidXQgXCJzYWZlXCIgZm9yIFdpblJUXG5cdFx0XHQvLyBodHRwczovL21zZG4ubWljcm9zb2Z0LmNvbS9lbi11cy9saWJyYXJ5L2llL2hoNDY1Mzg4LmFzcHgjYXR0cmlidXRlX3NlY3Rpb25cblx0XHRcdGlmICggZWwucXVlcnlTZWxlY3RvckFsbChcIlttc2FsbG93Y2FwdHVyZV49JyddXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goIFwiWypeJF09XCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86Jyd8XFxcIlxcXCIpXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogSUU4XG5cdFx0XHQvLyBCb29sZWFuIGF0dHJpYnV0ZXMgYW5kIFwidmFsdWVcIiBhcmUgbm90IHRyZWF0ZWQgY29ycmVjdGx5XG5cdFx0XHRpZiAoICFlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW3NlbGVjdGVkXVwiKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKCBcIlxcXFxbXCIgKyB3aGl0ZXNwYWNlICsgXCIqKD86dmFsdWV8XCIgKyBib29sZWFucyArIFwiKVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IENocm9tZTwyOSwgQW5kcm9pZDw0LjQsIFNhZmFyaTw3LjArLCBpT1M8Ny4wKywgUGhhbnRvbUpTPDEuOS44K1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbCggXCJbaWR+PVwiICsgZXhwYW5kbyArIFwiLV1cIiApLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCJ+PVwiKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gV2Via2l0L09wZXJhIC0gOmNoZWNrZWQgc2hvdWxkIHJldHVybiBzZWxlY3RlZCBvcHRpb24gZWxlbWVudHNcblx0XHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSLzIwMTEvUkVDLWNzczMtc2VsZWN0b3JzLTIwMTEwOTI5LyNjaGVja2VkXG5cdFx0XHQvLyBJRTggdGhyb3dzIGVycm9yIGhlcmUgYW5kIHdpbGwgbm90IHNlZSBsYXRlciB0ZXN0c1xuXHRcdFx0aWYgKCAhZWwucXVlcnlTZWxlY3RvckFsbChcIjpjaGVja2VkXCIpLmxlbmd0aCApIHtcblx0XHRcdFx0cmJ1Z2d5UVNBLnB1c2goXCI6Y2hlY2tlZFwiKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3VwcG9ydDogU2FmYXJpIDgrLCBpT1MgOCtcblx0XHRcdC8vIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzY4NTFcblx0XHRcdC8vIEluLXBhZ2UgYHNlbGVjdG9yI2lkIHNpYmxpbmctY29tYmluYXRvciBzZWxlY3RvcmAgZmFpbHNcblx0XHRcdGlmICggIWVsLnF1ZXJ5U2VsZWN0b3JBbGwoIFwiYSNcIiArIGV4cGFuZG8gKyBcIisqXCIgKS5sZW5ndGggKSB7XG5cdFx0XHRcdHJidWdneVFTQS5wdXNoKFwiLiMuK1srfl1cIik7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHRhc3NlcnQoZnVuY3Rpb24oIGVsICkge1xuXHRcdFx0ZWwuaW5uZXJIVE1MID0gXCI8YSBocmVmPScnIGRpc2FibGVkPSdkaXNhYmxlZCc+PC9hPlwiICtcblx0XHRcdFx0XCI8c2VsZWN0IGRpc2FibGVkPSdkaXNhYmxlZCc+PG9wdGlvbi8+PC9zZWxlY3Q+XCI7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IFdpbmRvd3MgOCBOYXRpdmUgQXBwc1xuXHRcdFx0Ly8gVGhlIHR5cGUgYW5kIG5hbWUgYXR0cmlidXRlcyBhcmUgcmVzdHJpY3RlZCBkdXJpbmcgLmlubmVySFRNTCBhc3NpZ25tZW50XG5cdFx0XHR2YXIgaW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiaW5wdXRcIik7XG5cdFx0XHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwidHlwZVwiLCBcImhpZGRlblwiICk7XG5cdFx0XHRlbC5hcHBlbmRDaGlsZCggaW5wdXQgKS5zZXRBdHRyaWJ1dGUoIFwibmFtZVwiLCBcIkRcIiApO1xuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRThcblx0XHRcdC8vIEVuZm9yY2UgY2FzZS1zZW5zaXRpdml0eSBvZiBuYW1lIGF0dHJpYnV0ZVxuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiW25hbWU9ZF1cIikubGVuZ3RoICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCJuYW1lXCIgKyB3aGl0ZXNwYWNlICsgXCIqWypeJHwhfl0/PVwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEZGIDMuNSAtIDplbmFibGVkLzpkaXNhYmxlZCBhbmQgaGlkZGVuIGVsZW1lbnRzIChoaWRkZW4gZWxlbWVudHMgYXJlIHN0aWxsIGVuYWJsZWQpXG5cdFx0XHQvLyBJRTggdGhyb3dzIGVycm9yIGhlcmUgYW5kIHdpbGwgbm90IHNlZSBsYXRlciB0ZXN0c1xuXHRcdFx0aWYgKCBlbC5xdWVyeVNlbGVjdG9yQWxsKFwiOmVuYWJsZWRcIikubGVuZ3RoICE9PSAyICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCI6ZW5hYmxlZFwiLCBcIjpkaXNhYmxlZFwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN1cHBvcnQ6IElFOS0xMStcblx0XHRcdC8vIElFJ3MgOmRpc2FibGVkIHNlbGVjdG9yIGRvZXMgbm90IHBpY2sgdXAgdGhlIGNoaWxkcmVuIG9mIGRpc2FibGVkIGZpZWxkc2V0c1xuXHRcdFx0ZG9jRWxlbS5hcHBlbmRDaGlsZCggZWwgKS5kaXNhYmxlZCA9IHRydWU7XG5cdFx0XHRpZiAoIGVsLnF1ZXJ5U2VsZWN0b3JBbGwoXCI6ZGlzYWJsZWRcIikubGVuZ3RoICE9PSAyICkge1xuXHRcdFx0XHRyYnVnZ3lRU0EucHVzaCggXCI6ZW5hYmxlZFwiLCBcIjpkaXNhYmxlZFwiICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIE9wZXJhIDEwLTExIGRvZXMgbm90IHRocm93IG9uIHBvc3QtY29tbWEgaW52YWxpZCBwc2V1ZG9zXG5cdFx0XHRlbC5xdWVyeVNlbGVjdG9yQWxsKFwiKiw6eFwiKTtcblx0XHRcdHJidWdneVFTQS5wdXNoKFwiLC4qOlwiKTtcblx0XHR9KTtcblx0fVxuXG5cdGlmICggKHN1cHBvcnQubWF0Y2hlc1NlbGVjdG9yID0gcm5hdGl2ZS50ZXN0KCAobWF0Y2hlcyA9IGRvY0VsZW0ubWF0Y2hlcyB8fFxuXHRcdGRvY0VsZW0ud2Via2l0TWF0Y2hlc1NlbGVjdG9yIHx8XG5cdFx0ZG9jRWxlbS5tb3pNYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm9NYXRjaGVzU2VsZWN0b3IgfHxcblx0XHRkb2NFbGVtLm1zTWF0Y2hlc1NlbGVjdG9yKSApKSApIHtcblxuXHRcdGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdFx0XHQvLyBDaGVjayB0byBzZWUgaWYgaXQncyBwb3NzaWJsZSB0byBkbyBtYXRjaGVzU2VsZWN0b3Jcblx0XHRcdC8vIG9uIGEgZGlzY29ubmVjdGVkIG5vZGUgKElFIDkpXG5cdFx0XHRzdXBwb3J0LmRpc2Nvbm5lY3RlZE1hdGNoID0gbWF0Y2hlcy5jYWxsKCBlbCwgXCIqXCIgKTtcblxuXHRcdFx0Ly8gVGhpcyBzaG91bGQgZmFpbCB3aXRoIGFuIGV4Y2VwdGlvblxuXHRcdFx0Ly8gR2Vja28gZG9lcyBub3QgZXJyb3IsIHJldHVybnMgZmFsc2UgaW5zdGVhZFxuXHRcdFx0bWF0Y2hlcy5jYWxsKCBlbCwgXCJbcyE9JyddOnhcIiApO1xuXHRcdFx0cmJ1Z2d5TWF0Y2hlcy5wdXNoKCBcIiE9XCIsIHBzZXVkb3MgKTtcblx0XHR9KTtcblx0fVxuXG5cdHJidWdneVFTQSA9IHJidWdneVFTQS5sZW5ndGggJiYgbmV3IFJlZ0V4cCggcmJ1Z2d5UVNBLmpvaW4oXCJ8XCIpICk7XG5cdHJidWdneU1hdGNoZXMgPSByYnVnZ3lNYXRjaGVzLmxlbmd0aCAmJiBuZXcgUmVnRXhwKCByYnVnZ3lNYXRjaGVzLmpvaW4oXCJ8XCIpICk7XG5cblx0LyogQ29udGFpbnNcblx0LS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXHRoYXNDb21wYXJlID0gcm5hdGl2ZS50ZXN0KCBkb2NFbGVtLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uICk7XG5cblx0Ly8gRWxlbWVudCBjb250YWlucyBhbm90aGVyXG5cdC8vIFB1cnBvc2VmdWxseSBzZWxmLWV4Y2x1c2l2ZVxuXHQvLyBBcyBpbiwgYW4gZWxlbWVudCBkb2VzIG5vdCBjb250YWluIGl0c2VsZlxuXHRjb250YWlucyA9IGhhc0NvbXBhcmUgfHwgcm5hdGl2ZS50ZXN0KCBkb2NFbGVtLmNvbnRhaW5zICkgP1xuXHRcdGZ1bmN0aW9uKCBhLCBiICkge1xuXHRcdFx0dmFyIGFkb3duID0gYS5ub2RlVHlwZSA9PT0gOSA/IGEuZG9jdW1lbnRFbGVtZW50IDogYSxcblx0XHRcdFx0YnVwID0gYiAmJiBiLnBhcmVudE5vZGU7XG5cdFx0XHRyZXR1cm4gYSA9PT0gYnVwIHx8ICEhKCBidXAgJiYgYnVwLm5vZGVUeXBlID09PSAxICYmIChcblx0XHRcdFx0YWRvd24uY29udGFpbnMgP1xuXHRcdFx0XHRcdGFkb3duLmNvbnRhaW5zKCBidXAgKSA6XG5cdFx0XHRcdFx0YS5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbiAmJiBhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBidXAgKSAmIDE2XG5cdFx0XHQpKTtcblx0XHR9IDpcblx0XHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHRcdGlmICggYiApIHtcblx0XHRcdFx0d2hpbGUgKCAoYiA9IGIucGFyZW50Tm9kZSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBiID09PSBhICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fTtcblxuXHQvKiBTb3J0aW5nXG5cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuXHQvLyBEb2N1bWVudCBvcmRlciBzb3J0aW5nXG5cdHNvcnRPcmRlciA9IGhhc0NvbXBhcmUgP1xuXHRmdW5jdGlvbiggYSwgYiApIHtcblxuXHRcdC8vIEZsYWcgZm9yIGR1cGxpY2F0ZSByZW1vdmFsXG5cdFx0aWYgKCBhID09PSBiICkge1xuXHRcdFx0aGFzRHVwbGljYXRlID0gdHJ1ZTtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdC8vIFNvcnQgb24gbWV0aG9kIGV4aXN0ZW5jZSBpZiBvbmx5IG9uZSBpbnB1dCBoYXMgY29tcGFyZURvY3VtZW50UG9zaXRpb25cblx0XHR2YXIgY29tcGFyZSA9ICFhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uIC0gIWIuY29tcGFyZURvY3VtZW50UG9zaXRpb247XG5cdFx0aWYgKCBjb21wYXJlICkge1xuXHRcdFx0cmV0dXJuIGNvbXBhcmU7XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsY3VsYXRlIHBvc2l0aW9uIGlmIGJvdGggaW5wdXRzIGJlbG9uZyB0byB0aGUgc2FtZSBkb2N1bWVudFxuXHRcdGNvbXBhcmUgPSAoIGEub3duZXJEb2N1bWVudCB8fCBhICkgPT09ICggYi5vd25lckRvY3VtZW50IHx8IGIgKSA/XG5cdFx0XHRhLmNvbXBhcmVEb2N1bWVudFBvc2l0aW9uKCBiICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugd2Uga25vdyB0aGV5IGFyZSBkaXNjb25uZWN0ZWRcblx0XHRcdDE7XG5cblx0XHQvLyBEaXNjb25uZWN0ZWQgbm9kZXNcblx0XHRpZiAoIGNvbXBhcmUgJiAxIHx8XG5cdFx0XHQoIXN1cHBvcnQuc29ydERldGFjaGVkICYmIGIuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGEgKSA9PT0gY29tcGFyZSkgKSB7XG5cblx0XHRcdC8vIENob29zZSB0aGUgZmlyc3QgZWxlbWVudCB0aGF0IGlzIHJlbGF0ZWQgdG8gb3VyIHByZWZlcnJlZCBkb2N1bWVudFxuXHRcdFx0aWYgKCBhID09PSBkb2N1bWVudCB8fCBhLm93bmVyRG9jdW1lbnQgPT09IHByZWZlcnJlZERvYyAmJiBjb250YWlucyhwcmVmZXJyZWREb2MsIGEpICkge1xuXHRcdFx0XHRyZXR1cm4gLTE7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGIgPT09IGRvY3VtZW50IHx8IGIub3duZXJEb2N1bWVudCA9PT0gcHJlZmVycmVkRG9jICYmIGNvbnRhaW5zKHByZWZlcnJlZERvYywgYikgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWludGFpbiBvcmlnaW5hbCBvcmRlclxuXHRcdFx0cmV0dXJuIHNvcnRJbnB1dCA/XG5cdFx0XHRcdCggaW5kZXhPZiggc29ydElucHV0LCBhICkgLSBpbmRleE9mKCBzb3J0SW5wdXQsIGIgKSApIDpcblx0XHRcdFx0MDtcblx0XHR9XG5cblx0XHRyZXR1cm4gY29tcGFyZSAmIDQgPyAtMSA6IDE7XG5cdH0gOlxuXHRmdW5jdGlvbiggYSwgYiApIHtcblx0XHQvLyBFeGl0IGVhcmx5IGlmIHRoZSBub2RlcyBhcmUgaWRlbnRpY2FsXG5cdFx0aWYgKCBhID09PSBiICkge1xuXHRcdFx0aGFzRHVwbGljYXRlID0gdHJ1ZTtcblx0XHRcdHJldHVybiAwO1xuXHRcdH1cblxuXHRcdHZhciBjdXIsXG5cdFx0XHRpID0gMCxcblx0XHRcdGF1cCA9IGEucGFyZW50Tm9kZSxcblx0XHRcdGJ1cCA9IGIucGFyZW50Tm9kZSxcblx0XHRcdGFwID0gWyBhIF0sXG5cdFx0XHRicCA9IFsgYiBdO1xuXG5cdFx0Ly8gUGFyZW50bGVzcyBub2RlcyBhcmUgZWl0aGVyIGRvY3VtZW50cyBvciBkaXNjb25uZWN0ZWRcblx0XHRpZiAoICFhdXAgfHwgIWJ1cCApIHtcblx0XHRcdHJldHVybiBhID09PSBkb2N1bWVudCA/IC0xIDpcblx0XHRcdFx0YiA9PT0gZG9jdW1lbnQgPyAxIDpcblx0XHRcdFx0YXVwID8gLTEgOlxuXHRcdFx0XHRidXAgPyAxIDpcblx0XHRcdFx0c29ydElucHV0ID9cblx0XHRcdFx0KCBpbmRleE9mKCBzb3J0SW5wdXQsIGEgKSAtIGluZGV4T2YoIHNvcnRJbnB1dCwgYiApICkgOlxuXHRcdFx0XHQwO1xuXG5cdFx0Ly8gSWYgdGhlIG5vZGVzIGFyZSBzaWJsaW5ncywgd2UgY2FuIGRvIGEgcXVpY2sgY2hlY2tcblx0XHR9IGVsc2UgaWYgKCBhdXAgPT09IGJ1cCApIHtcblx0XHRcdHJldHVybiBzaWJsaW5nQ2hlY2soIGEsIGIgKTtcblx0XHR9XG5cblx0XHQvLyBPdGhlcndpc2Ugd2UgbmVlZCBmdWxsIGxpc3RzIG9mIHRoZWlyIGFuY2VzdG9ycyBmb3IgY29tcGFyaXNvblxuXHRcdGN1ciA9IGE7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YXAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXHRcdGN1ciA9IGI7XG5cdFx0d2hpbGUgKCAoY3VyID0gY3VyLnBhcmVudE5vZGUpICkge1xuXHRcdFx0YnAudW5zaGlmdCggY3VyICk7XG5cdFx0fVxuXG5cdFx0Ly8gV2FsayBkb3duIHRoZSB0cmVlIGxvb2tpbmcgZm9yIGEgZGlzY3JlcGFuY3lcblx0XHR3aGlsZSAoIGFwW2ldID09PSBicFtpXSApIHtcblx0XHRcdGkrKztcblx0XHR9XG5cblx0XHRyZXR1cm4gaSA/XG5cdFx0XHQvLyBEbyBhIHNpYmxpbmcgY2hlY2sgaWYgdGhlIG5vZGVzIGhhdmUgYSBjb21tb24gYW5jZXN0b3Jcblx0XHRcdHNpYmxpbmdDaGVjayggYXBbaV0sIGJwW2ldICkgOlxuXG5cdFx0XHQvLyBPdGhlcndpc2Ugbm9kZXMgaW4gb3VyIGRvY3VtZW50IHNvcnQgZmlyc3Rcblx0XHRcdGFwW2ldID09PSBwcmVmZXJyZWREb2MgPyAtMSA6XG5cdFx0XHRicFtpXSA9PT0gcHJlZmVycmVkRG9jID8gMSA6XG5cdFx0XHQwO1xuXHR9O1xuXG5cdHJldHVybiBkb2N1bWVudDtcbn07XG5cblNpenpsZS5tYXRjaGVzID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1lbnRzICkge1xuXHRyZXR1cm4gU2l6emxlKCBleHByLCBudWxsLCBudWxsLCBlbGVtZW50cyApO1xufTtcblxuU2l6emxlLm1hdGNoZXNTZWxlY3RvciA9IGZ1bmN0aW9uKCBlbGVtLCBleHByICkge1xuXHQvLyBTZXQgZG9jdW1lbnQgdmFycyBpZiBuZWVkZWRcblx0aWYgKCAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBlbGVtICkgIT09IGRvY3VtZW50ICkge1xuXHRcdHNldERvY3VtZW50KCBlbGVtICk7XG5cdH1cblxuXHQvLyBNYWtlIHN1cmUgdGhhdCBhdHRyaWJ1dGUgc2VsZWN0b3JzIGFyZSBxdW90ZWRcblx0ZXhwciA9IGV4cHIucmVwbGFjZSggcmF0dHJpYnV0ZVF1b3RlcywgXCI9JyQxJ11cIiApO1xuXG5cdGlmICggc3VwcG9ydC5tYXRjaGVzU2VsZWN0b3IgJiYgZG9jdW1lbnRJc0hUTUwgJiZcblx0XHQhY29tcGlsZXJDYWNoZVsgZXhwciArIFwiIFwiIF0gJiZcblx0XHQoICFyYnVnZ3lNYXRjaGVzIHx8ICFyYnVnZ3lNYXRjaGVzLnRlc3QoIGV4cHIgKSApICYmXG5cdFx0KCAhcmJ1Z2d5UVNBICAgICB8fCAhcmJ1Z2d5UVNBLnRlc3QoIGV4cHIgKSApICkge1xuXG5cdFx0dHJ5IHtcblx0XHRcdHZhciByZXQgPSBtYXRjaGVzLmNhbGwoIGVsZW0sIGV4cHIgKTtcblxuXHRcdFx0Ly8gSUUgOSdzIG1hdGNoZXNTZWxlY3RvciByZXR1cm5zIGZhbHNlIG9uIGRpc2Nvbm5lY3RlZCBub2Rlc1xuXHRcdFx0aWYgKCByZXQgfHwgc3VwcG9ydC5kaXNjb25uZWN0ZWRNYXRjaCB8fFxuXHRcdFx0XHRcdC8vIEFzIHdlbGwsIGRpc2Nvbm5lY3RlZCBub2RlcyBhcmUgc2FpZCB0byBiZSBpbiBhIGRvY3VtZW50XG5cdFx0XHRcdFx0Ly8gZnJhZ21lbnQgaW4gSUUgOVxuXHRcdFx0XHRcdGVsZW0uZG9jdW1lbnQgJiYgZWxlbS5kb2N1bWVudC5ub2RlVHlwZSAhPT0gMTEgKSB7XG5cdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHR9XG5cdFx0fSBjYXRjaCAoZSkge31cblx0fVxuXG5cdHJldHVybiBTaXp6bGUoIGV4cHIsIGRvY3VtZW50LCBudWxsLCBbIGVsZW0gXSApLmxlbmd0aCA+IDA7XG59O1xuXG5TaXp6bGUuY29udGFpbnMgPSBmdW5jdGlvbiggY29udGV4dCwgZWxlbSApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBjb250ZXh0Lm93bmVyRG9jdW1lbnQgfHwgY29udGV4dCApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggY29udGV4dCApO1xuXHR9XG5cdHJldHVybiBjb250YWlucyggY29udGV4dCwgZWxlbSApO1xufTtcblxuU2l6emxlLmF0dHIgPSBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0Ly8gU2V0IGRvY3VtZW50IHZhcnMgaWYgbmVlZGVkXG5cdGlmICggKCBlbGVtLm93bmVyRG9jdW1lbnQgfHwgZWxlbSApICE9PSBkb2N1bWVudCApIHtcblx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHR9XG5cblx0dmFyIGZuID0gRXhwci5hdHRySGFuZGxlWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSxcblx0XHQvLyBEb24ndCBnZXQgZm9vbGVkIGJ5IE9iamVjdC5wcm90b3R5cGUgcHJvcGVydGllcyAoalF1ZXJ5ICMxMzgwNylcblx0XHR2YWwgPSBmbiAmJiBoYXNPd24uY2FsbCggRXhwci5hdHRySGFuZGxlLCBuYW1lLnRvTG93ZXJDYXNlKCkgKSA/XG5cdFx0XHRmbiggZWxlbSwgbmFtZSwgIWRvY3VtZW50SXNIVE1MICkgOlxuXHRcdFx0dW5kZWZpbmVkO1xuXG5cdHJldHVybiB2YWwgIT09IHVuZGVmaW5lZCA/XG5cdFx0dmFsIDpcblx0XHRzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWRvY3VtZW50SXNIVE1MID9cblx0XHRcdGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lICkgOlxuXHRcdFx0KHZhbCA9IGVsZW0uZ2V0QXR0cmlidXRlTm9kZShuYW1lKSkgJiYgdmFsLnNwZWNpZmllZCA/XG5cdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG59O1xuXG5TaXp6bGUuZXNjYXBlID0gZnVuY3Rpb24oIHNlbCApIHtcblx0cmV0dXJuIChzZWwgKyBcIlwiKS5yZXBsYWNlKCByY3NzZXNjYXBlLCBmY3NzZXNjYXBlICk7XG59O1xuXG5TaXp6bGUuZXJyb3IgPSBmdW5jdGlvbiggbXNnICkge1xuXHR0aHJvdyBuZXcgRXJyb3IoIFwiU3ludGF4IGVycm9yLCB1bnJlY29nbml6ZWQgZXhwcmVzc2lvbjogXCIgKyBtc2cgKTtcbn07XG5cbi8qKlxuICogRG9jdW1lbnQgc29ydGluZyBhbmQgcmVtb3ZpbmcgZHVwbGljYXRlc1xuICogQHBhcmFtIHtBcnJheUxpa2V9IHJlc3VsdHNcbiAqL1xuU2l6emxlLnVuaXF1ZVNvcnQgPSBmdW5jdGlvbiggcmVzdWx0cyApIHtcblx0dmFyIGVsZW0sXG5cdFx0ZHVwbGljYXRlcyA9IFtdLFxuXHRcdGogPSAwLFxuXHRcdGkgPSAwO1xuXG5cdC8vIFVubGVzcyB3ZSAqa25vdyogd2UgY2FuIGRldGVjdCBkdXBsaWNhdGVzLCBhc3N1bWUgdGhlaXIgcHJlc2VuY2Vcblx0aGFzRHVwbGljYXRlID0gIXN1cHBvcnQuZGV0ZWN0RHVwbGljYXRlcztcblx0c29ydElucHV0ID0gIXN1cHBvcnQuc29ydFN0YWJsZSAmJiByZXN1bHRzLnNsaWNlKCAwICk7XG5cdHJlc3VsdHMuc29ydCggc29ydE9yZGVyICk7XG5cblx0aWYgKCBoYXNEdXBsaWNhdGUgKSB7XG5cdFx0d2hpbGUgKCAoZWxlbSA9IHJlc3VsdHNbaSsrXSkgKSB7XG5cdFx0XHRpZiAoIGVsZW0gPT09IHJlc3VsdHNbIGkgXSApIHtcblx0XHRcdFx0aiA9IGR1cGxpY2F0ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdHJlc3VsdHMuc3BsaWNlKCBkdXBsaWNhdGVzWyBqIF0sIDEgKTtcblx0XHR9XG5cdH1cblxuXHQvLyBDbGVhciBpbnB1dCBhZnRlciBzb3J0aW5nIHRvIHJlbGVhc2Ugb2JqZWN0c1xuXHQvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9zaXp6bGUvcHVsbC8yMjVcblx0c29ydElucHV0ID0gbnVsbDtcblxuXHRyZXR1cm4gcmVzdWx0cztcbn07XG5cbi8qKlxuICogVXRpbGl0eSBmdW5jdGlvbiBmb3IgcmV0cmlldmluZyB0aGUgdGV4dCB2YWx1ZSBvZiBhbiBhcnJheSBvZiBET00gbm9kZXNcbiAqIEBwYXJhbSB7QXJyYXl8RWxlbWVudH0gZWxlbVxuICovXG5nZXRUZXh0ID0gU2l6emxlLmdldFRleHQgPSBmdW5jdGlvbiggZWxlbSApIHtcblx0dmFyIG5vZGUsXG5cdFx0cmV0ID0gXCJcIixcblx0XHRpID0gMCxcblx0XHRub2RlVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0aWYgKCAhbm9kZVR5cGUgKSB7XG5cdFx0Ly8gSWYgbm8gbm9kZVR5cGUsIHRoaXMgaXMgZXhwZWN0ZWQgdG8gYmUgYW4gYXJyYXlcblx0XHR3aGlsZSAoIChub2RlID0gZWxlbVtpKytdKSApIHtcblx0XHRcdC8vIERvIG5vdCB0cmF2ZXJzZSBjb21tZW50IG5vZGVzXG5cdFx0XHRyZXQgKz0gZ2V0VGV4dCggbm9kZSApO1xuXHRcdH1cblx0fSBlbHNlIGlmICggbm9kZVR5cGUgPT09IDEgfHwgbm9kZVR5cGUgPT09IDkgfHwgbm9kZVR5cGUgPT09IDExICkge1xuXHRcdC8vIFVzZSB0ZXh0Q29udGVudCBmb3IgZWxlbWVudHNcblx0XHQvLyBpbm5lclRleHQgdXNhZ2UgcmVtb3ZlZCBmb3IgY29uc2lzdGVuY3kgb2YgbmV3IGxpbmVzIChqUXVlcnkgIzExMTUzKVxuXHRcdGlmICggdHlwZW9mIGVsZW0udGV4dENvbnRlbnQgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS50ZXh0Q29udGVudDtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Ly8gVHJhdmVyc2UgaXRzIGNoaWxkcmVuXG5cdFx0XHRmb3IgKCBlbGVtID0gZWxlbS5maXJzdENoaWxkOyBlbGVtOyBlbGVtID0gZWxlbS5uZXh0U2libGluZyApIHtcblx0XHRcdFx0cmV0ICs9IGdldFRleHQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gZWxzZSBpZiAoIG5vZGVUeXBlID09PSAzIHx8IG5vZGVUeXBlID09PSA0ICkge1xuXHRcdHJldHVybiBlbGVtLm5vZGVWYWx1ZTtcblx0fVxuXHQvLyBEbyBub3QgaW5jbHVkZSBjb21tZW50IG9yIHByb2Nlc3NpbmcgaW5zdHJ1Y3Rpb24gbm9kZXNcblxuXHRyZXR1cm4gcmV0O1xufTtcblxuRXhwciA9IFNpenpsZS5zZWxlY3RvcnMgPSB7XG5cblx0Ly8gQ2FuIGJlIGFkanVzdGVkIGJ5IHRoZSB1c2VyXG5cdGNhY2hlTGVuZ3RoOiA1MCxcblxuXHRjcmVhdGVQc2V1ZG86IG1hcmtGdW5jdGlvbixcblxuXHRtYXRjaDogbWF0Y2hFeHByLFxuXG5cdGF0dHJIYW5kbGU6IHt9LFxuXG5cdGZpbmQ6IHt9LFxuXG5cdHJlbGF0aXZlOiB7XG5cdFx0XCI+XCI6IHsgZGlyOiBcInBhcmVudE5vZGVcIiwgZmlyc3Q6IHRydWUgfSxcblx0XHRcIiBcIjogeyBkaXI6IFwicGFyZW50Tm9kZVwiIH0sXG5cdFx0XCIrXCI6IHsgZGlyOiBcInByZXZpb3VzU2libGluZ1wiLCBmaXJzdDogdHJ1ZSB9LFxuXHRcdFwiflwiOiB7IGRpcjogXCJwcmV2aW91c1NpYmxpbmdcIiB9XG5cdH0sXG5cblx0cHJlRmlsdGVyOiB7XG5cdFx0XCJBVFRSXCI6IGZ1bmN0aW9uKCBtYXRjaCApIHtcblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0ucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0Ly8gTW92ZSB0aGUgZ2l2ZW4gdmFsdWUgdG8gbWF0Y2hbM10gd2hldGhlciBxdW90ZWQgb3IgdW5xdW90ZWRcblx0XHRcdG1hdGNoWzNdID0gKCBtYXRjaFszXSB8fCBtYXRjaFs0XSB8fCBtYXRjaFs1XSB8fCBcIlwiICkucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsyXSA9PT0gXCJ+PVwiICkge1xuXHRcdFx0XHRtYXRjaFszXSA9IFwiIFwiICsgbWF0Y2hbM10gKyBcIiBcIjtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCA0ICk7XG5cdFx0fSxcblxuXHRcdFwiQ0hJTERcIjogZnVuY3Rpb24oIG1hdGNoICkge1xuXHRcdFx0LyogbWF0Y2hlcyBmcm9tIG1hdGNoRXhwcltcIkNISUxEXCJdXG5cdFx0XHRcdDEgdHlwZSAob25seXxudGh8Li4uKVxuXHRcdFx0XHQyIHdoYXQgKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdDMgYXJndW1lbnQgKGV2ZW58b2RkfFxcZCp8XFxkKm4oWystXVxcZCspP3wuLi4pXG5cdFx0XHRcdDQgeG4tY29tcG9uZW50IG9mIHhuK3kgYXJndW1lbnQgKFsrLV0/XFxkKm58KVxuXHRcdFx0XHQ1IHNpZ24gb2YgeG4tY29tcG9uZW50XG5cdFx0XHRcdDYgeCBvZiB4bi1jb21wb25lbnRcblx0XHRcdFx0NyBzaWduIG9mIHktY29tcG9uZW50XG5cdFx0XHRcdDggeSBvZiB5LWNvbXBvbmVudFxuXHRcdFx0Ki9cblx0XHRcdG1hdGNoWzFdID0gbWF0Y2hbMV0udG9Mb3dlckNhc2UoKTtcblxuXHRcdFx0aWYgKCBtYXRjaFsxXS5zbGljZSggMCwgMyApID09PSBcIm50aFwiICkge1xuXHRcdFx0XHQvLyBudGgtKiByZXF1aXJlcyBhcmd1bWVudFxuXHRcdFx0XHRpZiAoICFtYXRjaFszXSApIHtcblx0XHRcdFx0XHRTaXp6bGUuZXJyb3IoIG1hdGNoWzBdICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBudW1lcmljIHggYW5kIHkgcGFyYW1ldGVycyBmb3IgRXhwci5maWx0ZXIuQ0hJTERcblx0XHRcdFx0Ly8gcmVtZW1iZXIgdGhhdCBmYWxzZS90cnVlIGNhc3QgcmVzcGVjdGl2ZWx5IHRvIDAvMVxuXHRcdFx0XHRtYXRjaFs0XSA9ICsoIG1hdGNoWzRdID8gbWF0Y2hbNV0gKyAobWF0Y2hbNl0gfHwgMSkgOiAyICogKCBtYXRjaFszXSA9PT0gXCJldmVuXCIgfHwgbWF0Y2hbM10gPT09IFwib2RkXCIgKSApO1xuXHRcdFx0XHRtYXRjaFs1XSA9ICsoICggbWF0Y2hbN10gKyBtYXRjaFs4XSApIHx8IG1hdGNoWzNdID09PSBcIm9kZFwiICk7XG5cblx0XHRcdC8vIG90aGVyIHR5cGVzIHByb2hpYml0IGFyZ3VtZW50c1xuXHRcdFx0fSBlbHNlIGlmICggbWF0Y2hbM10gKSB7XG5cdFx0XHRcdFNpenpsZS5lcnJvciggbWF0Y2hbMF0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG1hdGNoO1xuXHRcdH0sXG5cblx0XHRcIlBTRVVET1wiOiBmdW5jdGlvbiggbWF0Y2ggKSB7XG5cdFx0XHR2YXIgZXhjZXNzLFxuXHRcdFx0XHR1bnF1b3RlZCA9ICFtYXRjaFs2XSAmJiBtYXRjaFsyXTtcblxuXHRcdFx0aWYgKCBtYXRjaEV4cHJbXCJDSElMRFwiXS50ZXN0KCBtYXRjaFswXSApICkge1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWNjZXB0IHF1b3RlZCBhcmd1bWVudHMgYXMtaXNcblx0XHRcdGlmICggbWF0Y2hbM10gKSB7XG5cdFx0XHRcdG1hdGNoWzJdID0gbWF0Y2hbNF0gfHwgbWF0Y2hbNV0gfHwgXCJcIjtcblxuXHRcdFx0Ly8gU3RyaXAgZXhjZXNzIGNoYXJhY3RlcnMgZnJvbSB1bnF1b3RlZCBhcmd1bWVudHNcblx0XHRcdH0gZWxzZSBpZiAoIHVucXVvdGVkICYmIHJwc2V1ZG8udGVzdCggdW5xdW90ZWQgKSAmJlxuXHRcdFx0XHQvLyBHZXQgZXhjZXNzIGZyb20gdG9rZW5pemUgKHJlY3Vyc2l2ZWx5KVxuXHRcdFx0XHQoZXhjZXNzID0gdG9rZW5pemUoIHVucXVvdGVkLCB0cnVlICkpICYmXG5cdFx0XHRcdC8vIGFkdmFuY2UgdG8gdGhlIG5leHQgY2xvc2luZyBwYXJlbnRoZXNpc1xuXHRcdFx0XHQoZXhjZXNzID0gdW5xdW90ZWQuaW5kZXhPZiggXCIpXCIsIHVucXVvdGVkLmxlbmd0aCAtIGV4Y2VzcyApIC0gdW5xdW90ZWQubGVuZ3RoKSApIHtcblxuXHRcdFx0XHQvLyBleGNlc3MgaXMgYSBuZWdhdGl2ZSBpbmRleFxuXHRcdFx0XHRtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwLCBleGNlc3MgKTtcblx0XHRcdFx0bWF0Y2hbMl0gPSB1bnF1b3RlZC5zbGljZSggMCwgZXhjZXNzICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJldHVybiBvbmx5IGNhcHR1cmVzIG5lZWRlZCBieSB0aGUgcHNldWRvIGZpbHRlciBtZXRob2QgKHR5cGUgYW5kIGFyZ3VtZW50KVxuXHRcdFx0cmV0dXJuIG1hdGNoLnNsaWNlKCAwLCAzICk7XG5cdFx0fVxuXHR9LFxuXG5cdGZpbHRlcjoge1xuXG5cdFx0XCJUQUdcIjogZnVuY3Rpb24oIG5vZGVOYW1lU2VsZWN0b3IgKSB7XG5cdFx0XHR2YXIgbm9kZU5hbWUgPSBub2RlTmFtZVNlbGVjdG9yLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICkudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiBub2RlTmFtZVNlbGVjdG9yID09PSBcIipcIiA/XG5cdFx0XHRcdGZ1bmN0aW9uKCkgeyByZXR1cm4gdHJ1ZTsgfSA6XG5cdFx0XHRcdGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiBlbGVtLm5vZGVOYW1lICYmIGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbm9kZU5hbWU7XG5cdFx0XHRcdH07XG5cdFx0fSxcblxuXHRcdFwiQ0xBU1NcIjogZnVuY3Rpb24oIGNsYXNzTmFtZSApIHtcblx0XHRcdHZhciBwYXR0ZXJuID0gY2xhc3NDYWNoZVsgY2xhc3NOYW1lICsgXCIgXCIgXTtcblxuXHRcdFx0cmV0dXJuIHBhdHRlcm4gfHxcblx0XHRcdFx0KHBhdHRlcm4gPSBuZXcgUmVnRXhwKCBcIihefFwiICsgd2hpdGVzcGFjZSArIFwiKVwiICsgY2xhc3NOYW1lICsgXCIoXCIgKyB3aGl0ZXNwYWNlICsgXCJ8JClcIiApKSAmJlxuXHRcdFx0XHRjbGFzc0NhY2hlKCBjbGFzc05hbWUsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXR0ZXJuLnRlc3QoIHR5cGVvZiBlbGVtLmNsYXNzTmFtZSA9PT0gXCJzdHJpbmdcIiAmJiBlbGVtLmNsYXNzTmFtZSB8fCB0eXBlb2YgZWxlbS5nZXRBdHRyaWJ1dGUgIT09IFwidW5kZWZpbmVkXCIgJiYgZWxlbS5nZXRBdHRyaWJ1dGUoXCJjbGFzc1wiKSB8fCBcIlwiICk7XG5cdFx0XHRcdH0pO1xuXHRcdH0sXG5cblx0XHRcIkFUVFJcIjogZnVuY3Rpb24oIG5hbWUsIG9wZXJhdG9yLCBjaGVjayApIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdFx0dmFyIHJlc3VsdCA9IFNpenpsZS5hdHRyKCBlbGVtLCBuYW1lICk7XG5cblx0XHRcdFx0aWYgKCByZXN1bHQgPT0gbnVsbCApIHtcblx0XHRcdFx0XHRyZXR1cm4gb3BlcmF0b3IgPT09IFwiIT1cIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoICFvcGVyYXRvciApIHtcblx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJlc3VsdCArPSBcIlwiO1xuXG5cdFx0XHRcdHJldHVybiBvcGVyYXRvciA9PT0gXCI9XCIgPyByZXN1bHQgPT09IGNoZWNrIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIhPVwiID8gcmVzdWx0ICE9PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiXj1cIiA/IGNoZWNrICYmIHJlc3VsdC5pbmRleE9mKCBjaGVjayApID09PSAwIDpcblx0XHRcdFx0XHRvcGVyYXRvciA9PT0gXCIqPVwiID8gY2hlY2sgJiYgcmVzdWx0LmluZGV4T2YoIGNoZWNrICkgPiAtMSA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwiJD1cIiA/IGNoZWNrICYmIHJlc3VsdC5zbGljZSggLWNoZWNrLmxlbmd0aCApID09PSBjaGVjayA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwifj1cIiA/ICggXCIgXCIgKyByZXN1bHQucmVwbGFjZSggcndoaXRlc3BhY2UsIFwiIFwiICkgKyBcIiBcIiApLmluZGV4T2YoIGNoZWNrICkgPiAtMSA6XG5cdFx0XHRcdFx0b3BlcmF0b3IgPT09IFwifD1cIiA/IHJlc3VsdCA9PT0gY2hlY2sgfHwgcmVzdWx0LnNsaWNlKCAwLCBjaGVjay5sZW5ndGggKyAxICkgPT09IGNoZWNrICsgXCItXCIgOlxuXHRcdFx0XHRcdGZhbHNlO1xuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0XCJDSElMRFwiOiBmdW5jdGlvbiggdHlwZSwgd2hhdCwgYXJndW1lbnQsIGZpcnN0LCBsYXN0ICkge1xuXHRcdFx0dmFyIHNpbXBsZSA9IHR5cGUuc2xpY2UoIDAsIDMgKSAhPT0gXCJudGhcIixcblx0XHRcdFx0Zm9yd2FyZCA9IHR5cGUuc2xpY2UoIC00ICkgIT09IFwibGFzdFwiLFxuXHRcdFx0XHRvZlR5cGUgPSB3aGF0ID09PSBcIm9mLXR5cGVcIjtcblxuXHRcdFx0cmV0dXJuIGZpcnN0ID09PSAxICYmIGxhc3QgPT09IDAgP1xuXG5cdFx0XHRcdC8vIFNob3J0Y3V0IGZvciA6bnRoLSoobilcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0cmV0dXJuICEhZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0XHR9IDpcblxuXHRcdFx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdHZhciBjYWNoZSwgdW5pcXVlQ2FjaGUsIG91dGVyQ2FjaGUsIG5vZGUsIG5vZGVJbmRleCwgc3RhcnQsXG5cdFx0XHRcdFx0XHRkaXIgPSBzaW1wbGUgIT09IGZvcndhcmQgPyBcIm5leHRTaWJsaW5nXCIgOiBcInByZXZpb3VzU2libGluZ1wiLFxuXHRcdFx0XHRcdFx0cGFyZW50ID0gZWxlbS5wYXJlbnROb2RlLFxuXHRcdFx0XHRcdFx0bmFtZSA9IG9mVHlwZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCksXG5cdFx0XHRcdFx0XHR1c2VDYWNoZSA9ICF4bWwgJiYgIW9mVHlwZSxcblx0XHRcdFx0XHRcdGRpZmYgPSBmYWxzZTtcblxuXHRcdFx0XHRcdGlmICggcGFyZW50ICkge1xuXG5cdFx0XHRcdFx0XHQvLyA6KGZpcnN0fGxhc3R8b25seSktKGNoaWxkfG9mLXR5cGUpXG5cdFx0XHRcdFx0XHRpZiAoIHNpbXBsZSApIHtcblx0XHRcdFx0XHRcdFx0d2hpbGUgKCBkaXIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZSA9IGVsZW07XG5cdFx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9IG5vZGVbIGRpciBdKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggb2ZUeXBlID9cblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBuYW1lIDpcblx0XHRcdFx0XHRcdFx0XHRcdFx0bm9kZS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdC8vIFJldmVyc2UgZGlyZWN0aW9uIGZvciA6b25seS0qIChpZiB3ZSBoYXZlbid0IHlldCBkb25lIHNvKVxuXHRcdFx0XHRcdFx0XHRcdHN0YXJ0ID0gZGlyID0gdHlwZSA9PT0gXCJvbmx5XCIgJiYgIXN0YXJ0ICYmIFwibmV4dFNpYmxpbmdcIjtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0c3RhcnQgPSBbIGZvcndhcmQgPyBwYXJlbnQuZmlyc3RDaGlsZCA6IHBhcmVudC5sYXN0Q2hpbGQgXTtcblxuXHRcdFx0XHRcdFx0Ly8gbm9uLXhtbCA6bnRoLWNoaWxkKC4uLikgc3RvcmVzIGNhY2hlIGRhdGEgb24gYHBhcmVudGBcblx0XHRcdFx0XHRcdGlmICggZm9yd2FyZCAmJiB1c2VDYWNoZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBTZWVrIGBlbGVtYCBmcm9tIGEgcHJldmlvdXNseS1jYWNoZWQgaW5kZXhcblxuXHRcdFx0XHRcdFx0XHQvLyAuLi5pbiBhIGd6aXAtZnJpZW5kbHkgd2F5XG5cdFx0XHRcdFx0XHRcdG5vZGUgPSBwYXJlbnQ7XG5cdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8OSBvbmx5XG5cdFx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdChvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0Y2FjaGUgPSB1bmlxdWVDYWNoZVsgdHlwZSBdIHx8IFtdO1xuXHRcdFx0XHRcdFx0XHRub2RlSW5kZXggPSBjYWNoZVsgMCBdID09PSBkaXJydW5zICYmIGNhY2hlWyAxIF07XG5cdFx0XHRcdFx0XHRcdGRpZmYgPSBub2RlSW5kZXggJiYgY2FjaGVbIDIgXTtcblx0XHRcdFx0XHRcdFx0bm9kZSA9IG5vZGVJbmRleCAmJiBwYXJlbnQuY2hpbGROb2Rlc1sgbm9kZUluZGV4IF07XG5cblx0XHRcdFx0XHRcdFx0d2hpbGUgKCAobm9kZSA9ICsrbm9kZUluZGV4ICYmIG5vZGUgJiYgbm9kZVsgZGlyIF0gfHxcblxuXHRcdFx0XHRcdFx0XHRcdC8vIEZhbGxiYWNrIHRvIHNlZWtpbmcgYGVsZW1gIGZyb20gdGhlIHN0YXJ0XG5cdFx0XHRcdFx0XHRcdFx0KGRpZmYgPSBub2RlSW5kZXggPSAwKSB8fCBzdGFydC5wb3AoKSkgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBXaGVuIGZvdW5kLCBjYWNoZSBpbmRleGVzIG9uIGBwYXJlbnRgIGFuZCBicmVha1xuXHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZS5ub2RlVHlwZSA9PT0gMSAmJiArK2RpZmYgJiYgbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIG5vZGVJbmRleCwgZGlmZiBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdC8vIFVzZSBwcmV2aW91c2x5LWNhY2hlZCBlbGVtZW50IGluZGV4IGlmIGF2YWlsYWJsZVxuXHRcdFx0XHRcdFx0XHRpZiAoIHVzZUNhY2hlICkge1xuXHRcdFx0XHRcdFx0XHRcdC8vIC4uLmluIGEgZ3ppcC1mcmllbmRseSB3YXlcblx0XHRcdFx0XHRcdFx0XHRub2RlID0gZWxlbTtcblx0XHRcdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gbm9kZVsgZXhwYW5kbyBdIHx8IChub2RlWyBleHBhbmRvIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0Ly8gRGVmZW5kIGFnYWluc3QgY2xvbmVkIGF0dHJvcGVydGllcyAoalF1ZXJ5IGdoLTE3MDkpXG5cdFx0XHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGUgPSBvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRcdChvdXRlckNhY2hlWyBub2RlLnVuaXF1ZUlEIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdFx0XHRjYWNoZSA9IHVuaXF1ZUNhY2hlWyB0eXBlIF0gfHwgW107XG5cdFx0XHRcdFx0XHRcdFx0bm9kZUluZGV4ID0gY2FjaGVbIDAgXSA9PT0gZGlycnVucyAmJiBjYWNoZVsgMSBdO1xuXHRcdFx0XHRcdFx0XHRcdGRpZmYgPSBub2RlSW5kZXg7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHQvLyB4bWwgOm50aC1jaGlsZCguLi4pXG5cdFx0XHRcdFx0XHRcdC8vIG9yIDpudGgtbGFzdC1jaGlsZCguLi4pIG9yIDpudGgoLWxhc3QpPy1vZi10eXBlKC4uLilcblx0XHRcdFx0XHRcdFx0aWYgKCBkaWZmID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdFx0XHQvLyBVc2UgdGhlIHNhbWUgbG9vcCBhcyBhYm92ZSB0byBzZWVrIGBlbGVtYCBmcm9tIHRoZSBzdGFydFxuXHRcdFx0XHRcdFx0XHRcdHdoaWxlICggKG5vZGUgPSArK25vZGVJbmRleCAmJiBub2RlICYmIG5vZGVbIGRpciBdIHx8XG5cdFx0XHRcdFx0XHRcdFx0XHQoZGlmZiA9IG5vZGVJbmRleCA9IDApIHx8IHN0YXJ0LnBvcCgpKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCAoIG9mVHlwZSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5vZGUubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gbmFtZSA6XG5cdFx0XHRcdFx0XHRcdFx0XHRcdG5vZGUubm9kZVR5cGUgPT09IDEgKSAmJlxuXHRcdFx0XHRcdFx0XHRcdFx0XHQrK2RpZmYgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gQ2FjaGUgdGhlIGluZGV4IG9mIGVhY2ggZW5jb3VudGVyZWQgZWxlbWVudFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIHVzZUNhY2hlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG91dGVyQ2FjaGUgPSBub2RlWyBleHBhbmRvIF0gfHwgKG5vZGVbIGV4cGFuZG8gXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZlbmQgYWdhaW5zdCBjbG9uZWQgYXR0cm9wZXJ0aWVzIChqUXVlcnkgZ2gtMTcwOSlcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR1bmlxdWVDYWNoZSA9IG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0KG91dGVyQ2FjaGVbIG5vZGUudW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyB0eXBlIF0gPSBbIGRpcnJ1bnMsIGRpZmYgXTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggbm9kZSA9PT0gZWxlbSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHQvLyBJbmNvcnBvcmF0ZSB0aGUgb2Zmc2V0LCB0aGVuIGNoZWNrIGFnYWluc3QgY3ljbGUgc2l6ZVxuXHRcdFx0XHRcdFx0ZGlmZiAtPSBsYXN0O1xuXHRcdFx0XHRcdFx0cmV0dXJuIGRpZmYgPT09IGZpcnN0IHx8ICggZGlmZiAlIGZpcnN0ID09PSAwICYmIGRpZmYgLyBmaXJzdCA+PSAwICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdH0sXG5cblx0XHRcIlBTRVVET1wiOiBmdW5jdGlvbiggcHNldWRvLCBhcmd1bWVudCApIHtcblx0XHRcdC8vIHBzZXVkby1jbGFzcyBuYW1lcyBhcmUgY2FzZS1pbnNlbnNpdGl2ZVxuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvc2VsZWN0b3JzLyNwc2V1ZG8tY2xhc3Nlc1xuXHRcdFx0Ly8gUHJpb3JpdGl6ZSBieSBjYXNlIHNlbnNpdGl2aXR5IGluIGNhc2UgY3VzdG9tIHBzZXVkb3MgYXJlIGFkZGVkIHdpdGggdXBwZXJjYXNlIGxldHRlcnNcblx0XHRcdC8vIFJlbWVtYmVyIHRoYXQgc2V0RmlsdGVycyBpbmhlcml0cyBmcm9tIHBzZXVkb3Ncblx0XHRcdHZhciBhcmdzLFxuXHRcdFx0XHRmbiA9IEV4cHIucHNldWRvc1sgcHNldWRvIF0gfHwgRXhwci5zZXRGaWx0ZXJzWyBwc2V1ZG8udG9Mb3dlckNhc2UoKSBdIHx8XG5cdFx0XHRcdFx0U2l6emxlLmVycm9yKCBcInVuc3VwcG9ydGVkIHBzZXVkbzogXCIgKyBwc2V1ZG8gKTtcblxuXHRcdFx0Ly8gVGhlIHVzZXIgbWF5IHVzZSBjcmVhdGVQc2V1ZG8gdG8gaW5kaWNhdGUgdGhhdFxuXHRcdFx0Ly8gYXJndW1lbnRzIGFyZSBuZWVkZWQgdG8gY3JlYXRlIHRoZSBmaWx0ZXIgZnVuY3Rpb25cblx0XHRcdC8vIGp1c3QgYXMgU2l6emxlIGRvZXNcblx0XHRcdGlmICggZm5bIGV4cGFuZG8gXSApIHtcblx0XHRcdFx0cmV0dXJuIGZuKCBhcmd1bWVudCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBCdXQgbWFpbnRhaW4gc3VwcG9ydCBmb3Igb2xkIHNpZ25hdHVyZXNcblx0XHRcdGlmICggZm4ubGVuZ3RoID4gMSApIHtcblx0XHRcdFx0YXJncyA9IFsgcHNldWRvLCBwc2V1ZG8sIFwiXCIsIGFyZ3VtZW50IF07XG5cdFx0XHRcdHJldHVybiBFeHByLnNldEZpbHRlcnMuaGFzT3duUHJvcGVydHkoIHBzZXVkby50b0xvd2VyQ2FzZSgpICkgP1xuXHRcdFx0XHRcdG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcyApIHtcblx0XHRcdFx0XHRcdHZhciBpZHgsXG5cdFx0XHRcdFx0XHRcdG1hdGNoZWQgPSBmbiggc2VlZCwgYXJndW1lbnQgKSxcblx0XHRcdFx0XHRcdFx0aSA9IG1hdGNoZWQubGVuZ3RoO1xuXHRcdFx0XHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdFx0XHRcdGlkeCA9IGluZGV4T2YoIHNlZWQsIG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdFx0c2VlZFsgaWR4IF0gPSAhKCBtYXRjaGVzWyBpZHggXSA9IG1hdGNoZWRbaV0gKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KSA6XG5cdFx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZm4oIGVsZW0sIDAsIGFyZ3MgKTtcblx0XHRcdFx0XHR9O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZm47XG5cdFx0fVxuXHR9LFxuXG5cdHBzZXVkb3M6IHtcblx0XHQvLyBQb3RlbnRpYWxseSBjb21wbGV4IHBzZXVkb3Ncblx0XHRcIm5vdFwiOiBtYXJrRnVuY3Rpb24oZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdFx0Ly8gVHJpbSB0aGUgc2VsZWN0b3IgcGFzc2VkIHRvIGNvbXBpbGVcblx0XHRcdC8vIHRvIGF2b2lkIHRyZWF0aW5nIGxlYWRpbmcgYW5kIHRyYWlsaW5nXG5cdFx0XHQvLyBzcGFjZXMgYXMgY29tYmluYXRvcnNcblx0XHRcdHZhciBpbnB1dCA9IFtdLFxuXHRcdFx0XHRyZXN1bHRzID0gW10sXG5cdFx0XHRcdG1hdGNoZXIgPSBjb21waWxlKCBzZWxlY3Rvci5yZXBsYWNlKCBydHJpbSwgXCIkMVwiICkgKTtcblxuXHRcdFx0cmV0dXJuIG1hdGNoZXJbIGV4cGFuZG8gXSA/XG5cdFx0XHRcdG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgbWF0Y2hlcywgY29udGV4dCwgeG1sICkge1xuXHRcdFx0XHRcdHZhciBlbGVtLFxuXHRcdFx0XHRcdFx0dW5tYXRjaGVkID0gbWF0Y2hlciggc2VlZCwgbnVsbCwgeG1sLCBbXSApLFxuXHRcdFx0XHRcdFx0aSA9IHNlZWQubGVuZ3RoO1xuXG5cdFx0XHRcdFx0Ly8gTWF0Y2ggZWxlbWVudHMgdW5tYXRjaGVkIGJ5IGBtYXRjaGVyYFxuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRcdFx0XHRcdHNlZWRbaV0gPSAhKG1hdGNoZXNbaV0gPSBlbGVtKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pIDpcblx0XHRcdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdFx0XHRpbnB1dFswXSA9IGVsZW07XG5cdFx0XHRcdFx0bWF0Y2hlciggaW5wdXQsIG51bGwsIHhtbCwgcmVzdWx0cyApO1xuXHRcdFx0XHRcdC8vIERvbid0IGtlZXAgdGhlIGVsZW1lbnQgKGlzc3VlICMyOTkpXG5cdFx0XHRcdFx0aW5wdXRbMF0gPSBudWxsO1xuXHRcdFx0XHRcdHJldHVybiAhcmVzdWx0cy5wb3AoKTtcblx0XHRcdFx0fTtcblx0XHR9KSxcblxuXHRcdFwiaGFzXCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiBTaXp6bGUoIHNlbGVjdG9yLCBlbGVtICkubGVuZ3RoID4gMDtcblx0XHRcdH07XG5cdFx0fSksXG5cblx0XHRcImNvbnRhaW5zXCI6IG1hcmtGdW5jdGlvbihmdW5jdGlvbiggdGV4dCApIHtcblx0XHRcdHRleHQgPSB0ZXh0LnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICk7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRcdHJldHVybiAoIGVsZW0udGV4dENvbnRlbnQgfHwgZWxlbS5pbm5lclRleHQgfHwgZ2V0VGV4dCggZWxlbSApICkuaW5kZXhPZiggdGV4dCApID4gLTE7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0Ly8gXCJXaGV0aGVyIGFuIGVsZW1lbnQgaXMgcmVwcmVzZW50ZWQgYnkgYSA6bGFuZygpIHNlbGVjdG9yXG5cdFx0Ly8gaXMgYmFzZWQgc29sZWx5IG9uIHRoZSBlbGVtZW50J3MgbGFuZ3VhZ2UgdmFsdWVcblx0XHQvLyBiZWluZyBlcXVhbCB0byB0aGUgaWRlbnRpZmllciBDLFxuXHRcdC8vIG9yIGJlZ2lubmluZyB3aXRoIHRoZSBpZGVudGlmaWVyIEMgaW1tZWRpYXRlbHkgZm9sbG93ZWQgYnkgXCItXCIuXG5cdFx0Ly8gVGhlIG1hdGNoaW5nIG9mIEMgYWdhaW5zdCB0aGUgZWxlbWVudCdzIGxhbmd1YWdlIHZhbHVlIGlzIHBlcmZvcm1lZCBjYXNlLWluc2Vuc2l0aXZlbHkuXG5cdFx0Ly8gVGhlIGlkZW50aWZpZXIgQyBkb2VzIG5vdCBoYXZlIHRvIGJlIGEgdmFsaWQgbGFuZ3VhZ2UgbmFtZS5cIlxuXHRcdC8vIGh0dHA6Ly93d3cudzMub3JnL1RSL3NlbGVjdG9ycy8jbGFuZy1wc2V1ZG9cblx0XHRcImxhbmdcIjogbWFya0Z1bmN0aW9uKCBmdW5jdGlvbiggbGFuZyApIHtcblx0XHRcdC8vIGxhbmcgdmFsdWUgbXVzdCBiZSBhIHZhbGlkIGlkZW50aWZpZXJcblx0XHRcdGlmICggIXJpZGVudGlmaWVyLnRlc3QobGFuZyB8fCBcIlwiKSApIHtcblx0XHRcdFx0U2l6emxlLmVycm9yKCBcInVuc3VwcG9ydGVkIGxhbmc6IFwiICsgbGFuZyApO1xuXHRcdFx0fVxuXHRcdFx0bGFuZyA9IGxhbmcucmVwbGFjZSggcnVuZXNjYXBlLCBmdW5lc2NhcGUgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgZWxlbUxhbmc7XG5cdFx0XHRcdGRvIHtcblx0XHRcdFx0XHRpZiAoIChlbGVtTGFuZyA9IGRvY3VtZW50SXNIVE1MID9cblx0XHRcdFx0XHRcdGVsZW0ubGFuZyA6XG5cdFx0XHRcdFx0XHRlbGVtLmdldEF0dHJpYnV0ZShcInhtbDpsYW5nXCIpIHx8IGVsZW0uZ2V0QXR0cmlidXRlKFwibGFuZ1wiKSkgKSB7XG5cblx0XHRcdFx0XHRcdGVsZW1MYW5nID0gZWxlbUxhbmcudG9Mb3dlckNhc2UoKTtcblx0XHRcdFx0XHRcdHJldHVybiBlbGVtTGFuZyA9PT0gbGFuZyB8fCBlbGVtTGFuZy5pbmRleE9mKCBsYW5nICsgXCItXCIgKSA9PT0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gd2hpbGUgKCAoZWxlbSA9IGVsZW0ucGFyZW50Tm9kZSkgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9O1xuXHRcdH0pLFxuXG5cdFx0Ly8gTWlzY2VsbGFuZW91c1xuXHRcdFwidGFyZ2V0XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIGhhc2ggPSB3aW5kb3cubG9jYXRpb24gJiYgd2luZG93LmxvY2F0aW9uLmhhc2g7XG5cdFx0XHRyZXR1cm4gaGFzaCAmJiBoYXNoLnNsaWNlKCAxICkgPT09IGVsZW0uaWQ7XG5cdFx0fSxcblxuXHRcdFwicm9vdFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBkb2NFbGVtO1xuXHRcdH0sXG5cblx0XHRcImZvY3VzXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0gPT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgJiYgKCFkb2N1bWVudC5oYXNGb2N1cyB8fCBkb2N1bWVudC5oYXNGb2N1cygpKSAmJiAhIShlbGVtLnR5cGUgfHwgZWxlbS5ocmVmIHx8IH5lbGVtLnRhYkluZGV4KTtcblx0XHR9LFxuXG5cdFx0Ly8gQm9vbGVhbiBwcm9wZXJ0aWVzXG5cdFx0XCJlbmFibGVkXCI6IGNyZWF0ZURpc2FibGVkUHNldWRvKCBmYWxzZSApLFxuXHRcdFwiZGlzYWJsZWRcIjogY3JlYXRlRGlzYWJsZWRQc2V1ZG8oIHRydWUgKSxcblxuXHRcdFwiY2hlY2tlZFwiOiBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdC8vIEluIENTUzMsIDpjaGVja2VkIHNob3VsZCByZXR1cm4gYm90aCBjaGVja2VkIGFuZCBzZWxlY3RlZCBlbGVtZW50c1xuXHRcdFx0Ly8gaHR0cDovL3d3dy53My5vcmcvVFIvMjAxMS9SRUMtY3NzMy1zZWxlY3RvcnMtMjAxMTA5MjkvI2NoZWNrZWRcblx0XHRcdHZhciBub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRcdHJldHVybiAobm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiAhIWVsZW0uY2hlY2tlZCkgfHwgKG5vZGVOYW1lID09PSBcIm9wdGlvblwiICYmICEhZWxlbS5zZWxlY3RlZCk7XG5cdFx0fSxcblxuXHRcdFwic2VsZWN0ZWRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHQvLyBBY2Nlc3NpbmcgdGhpcyBwcm9wZXJ0eSBtYWtlcyBzZWxlY3RlZC1ieS1kZWZhdWx0XG5cdFx0XHQvLyBvcHRpb25zIGluIFNhZmFyaSB3b3JrIHByb3Blcmx5XG5cdFx0XHRpZiAoIGVsZW0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0ZWxlbS5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBlbGVtLnNlbGVjdGVkID09PSB0cnVlO1xuXHRcdH0sXG5cblx0XHQvLyBDb250ZW50c1xuXHRcdFwiZW1wdHlcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHQvLyBodHRwOi8vd3d3LnczLm9yZy9UUi9zZWxlY3RvcnMvI2VtcHR5LXBzZXVkb1xuXHRcdFx0Ly8gOmVtcHR5IGlzIG5lZ2F0ZWQgYnkgZWxlbWVudCAoMSkgb3IgY29udGVudCBub2RlcyAodGV4dDogMzsgY2RhdGE6IDQ7IGVudGl0eSByZWY6IDUpLFxuXHRcdFx0Ly8gICBidXQgbm90IGJ5IG90aGVycyAoY29tbWVudDogODsgcHJvY2Vzc2luZyBpbnN0cnVjdGlvbjogNzsgZXRjLilcblx0XHRcdC8vIG5vZGVUeXBlIDwgNiB3b3JrcyBiZWNhdXNlIGF0dHJpYnV0ZXMgKDIpIGRvIG5vdCBhcHBlYXIgYXMgY2hpbGRyZW5cblx0XHRcdGZvciAoIGVsZW0gPSBlbGVtLmZpcnN0Q2hpbGQ7IGVsZW07IGVsZW0gPSBlbGVtLm5leHRTaWJsaW5nICkge1xuXHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPCA2ICkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fSxcblxuXHRcdFwicGFyZW50XCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuICFFeHByLnBzZXVkb3NbXCJlbXB0eVwiXSggZWxlbSApO1xuXHRcdH0sXG5cblx0XHQvLyBFbGVtZW50L2lucHV0IHR5cGVzXG5cdFx0XCJoZWFkZXJcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gcmhlYWRlci50ZXN0KCBlbGVtLm5vZGVOYW1lICk7XG5cdFx0fSxcblxuXHRcdFwiaW5wdXRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gcmlucHV0cy50ZXN0KCBlbGVtLm5vZGVOYW1lICk7XG5cdFx0fSxcblxuXHRcdFwiYnV0dG9uXCI6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIG5hbWUgPSBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRyZXR1cm4gbmFtZSA9PT0gXCJpbnB1dFwiICYmIGVsZW0udHlwZSA9PT0gXCJidXR0b25cIiB8fCBuYW1lID09PSBcImJ1dHRvblwiO1xuXHRcdH0sXG5cblx0XHRcInRleHRcIjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHR2YXIgYXR0cjtcblx0XHRcdHJldHVybiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwiaW5wdXRcIiAmJlxuXHRcdFx0XHRlbGVtLnR5cGUgPT09IFwidGV4dFwiICYmXG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUU8OFxuXHRcdFx0XHQvLyBOZXcgSFRNTDUgYXR0cmlidXRlIHZhbHVlcyAoZS5nLiwgXCJzZWFyY2hcIikgYXBwZWFyIHdpdGggZWxlbS50eXBlID09PSBcInRleHRcIlxuXHRcdFx0XHQoIChhdHRyID0gZWxlbS5nZXRBdHRyaWJ1dGUoXCJ0eXBlXCIpKSA9PSBudWxsIHx8IGF0dHIudG9Mb3dlckNhc2UoKSA9PT0gXCJ0ZXh0XCIgKTtcblx0XHR9LFxuXG5cdFx0Ly8gUG9zaXRpb24taW4tY29sbGVjdGlvblxuXHRcdFwiZmlyc3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBbIDAgXTtcblx0XHR9KSxcblxuXHRcdFwibGFzdFwiOiBjcmVhdGVQb3NpdGlvbmFsUHNldWRvKGZ1bmN0aW9uKCBtYXRjaEluZGV4ZXMsIGxlbmd0aCApIHtcblx0XHRcdHJldHVybiBbIGxlbmd0aCAtIDEgXTtcblx0XHR9KSxcblxuXHRcdFwiZXFcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0cmV0dXJuIFsgYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudCBdO1xuXHRcdH0pLFxuXG5cdFx0XCJldmVuXCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoICkge1xuXHRcdFx0dmFyIGkgPSAwO1xuXHRcdFx0Zm9yICggOyBpIDwgbGVuZ3RoOyBpICs9IDIgKSB7XG5cdFx0XHRcdG1hdGNoSW5kZXhlcy5wdXNoKCBpICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbWF0Y2hJbmRleGVzO1xuXHRcdH0pLFxuXG5cdFx0XCJvZGRcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGggKSB7XG5cdFx0XHR2YXIgaSA9IDE7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW5ndGg7IGkgKz0gMiApIHtcblx0XHRcdFx0bWF0Y2hJbmRleGVzLnB1c2goIGkgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBtYXRjaEluZGV4ZXM7XG5cdFx0fSksXG5cblx0XHRcImx0XCI6IGNyZWF0ZVBvc2l0aW9uYWxQc2V1ZG8oZnVuY3Rpb24oIG1hdGNoSW5kZXhlcywgbGVuZ3RoLCBhcmd1bWVudCApIHtcblx0XHRcdHZhciBpID0gYXJndW1lbnQgPCAwID8gYXJndW1lbnQgKyBsZW5ndGggOiBhcmd1bWVudDtcblx0XHRcdGZvciAoIDsgLS1pID49IDA7ICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KSxcblxuXHRcdFwiZ3RcIjogY3JlYXRlUG9zaXRpb25hbFBzZXVkbyhmdW5jdGlvbiggbWF0Y2hJbmRleGVzLCBsZW5ndGgsIGFyZ3VtZW50ICkge1xuXHRcdFx0dmFyIGkgPSBhcmd1bWVudCA8IDAgPyBhcmd1bWVudCArIGxlbmd0aCA6IGFyZ3VtZW50O1xuXHRcdFx0Zm9yICggOyArK2kgPCBsZW5ndGg7ICkge1xuXHRcdFx0XHRtYXRjaEluZGV4ZXMucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG1hdGNoSW5kZXhlcztcblx0XHR9KVxuXHR9XG59O1xuXG5FeHByLnBzZXVkb3NbXCJudGhcIl0gPSBFeHByLnBzZXVkb3NbXCJlcVwiXTtcblxuLy8gQWRkIGJ1dHRvbi9pbnB1dCB0eXBlIHBzZXVkb3NcbmZvciAoIGkgaW4geyByYWRpbzogdHJ1ZSwgY2hlY2tib3g6IHRydWUsIGZpbGU6IHRydWUsIHBhc3N3b3JkOiB0cnVlLCBpbWFnZTogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUlucHV0UHNldWRvKCBpICk7XG59XG5mb3IgKCBpIGluIHsgc3VibWl0OiB0cnVlLCByZXNldDogdHJ1ZSB9ICkge1xuXHRFeHByLnBzZXVkb3NbIGkgXSA9IGNyZWF0ZUJ1dHRvblBzZXVkbyggaSApO1xufVxuXG4vLyBFYXN5IEFQSSBmb3IgY3JlYXRpbmcgbmV3IHNldEZpbHRlcnNcbmZ1bmN0aW9uIHNldEZpbHRlcnMoKSB7fVxuc2V0RmlsdGVycy5wcm90b3R5cGUgPSBFeHByLmZpbHRlcnMgPSBFeHByLnBzZXVkb3M7XG5FeHByLnNldEZpbHRlcnMgPSBuZXcgc2V0RmlsdGVycygpO1xuXG50b2tlbml6ZSA9IFNpenpsZS50b2tlbml6ZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgcGFyc2VPbmx5ICkge1xuXHR2YXIgbWF0Y2hlZCwgbWF0Y2gsIHRva2VucywgdHlwZSxcblx0XHRzb0ZhciwgZ3JvdXBzLCBwcmVGaWx0ZXJzLFxuXHRcdGNhY2hlZCA9IHRva2VuQ2FjaGVbIHNlbGVjdG9yICsgXCIgXCIgXTtcblxuXHRpZiAoIGNhY2hlZCApIHtcblx0XHRyZXR1cm4gcGFyc2VPbmx5ID8gMCA6IGNhY2hlZC5zbGljZSggMCApO1xuXHR9XG5cblx0c29GYXIgPSBzZWxlY3Rvcjtcblx0Z3JvdXBzID0gW107XG5cdHByZUZpbHRlcnMgPSBFeHByLnByZUZpbHRlcjtcblxuXHR3aGlsZSAoIHNvRmFyICkge1xuXG5cdFx0Ly8gQ29tbWEgYW5kIGZpcnN0IHJ1blxuXHRcdGlmICggIW1hdGNoZWQgfHwgKG1hdGNoID0gcmNvbW1hLmV4ZWMoIHNvRmFyICkpICkge1xuXHRcdFx0aWYgKCBtYXRjaCApIHtcblx0XHRcdFx0Ly8gRG9uJ3QgY29uc3VtZSB0cmFpbGluZyBjb21tYXMgYXMgdmFsaWRcblx0XHRcdFx0c29GYXIgPSBzb0Zhci5zbGljZSggbWF0Y2hbMF0ubGVuZ3RoICkgfHwgc29GYXI7XG5cdFx0XHR9XG5cdFx0XHRncm91cHMucHVzaCggKHRva2VucyA9IFtdKSApO1xuXHRcdH1cblxuXHRcdG1hdGNoZWQgPSBmYWxzZTtcblxuXHRcdC8vIENvbWJpbmF0b3JzXG5cdFx0aWYgKCAobWF0Y2ggPSByY29tYmluYXRvcnMuZXhlYyggc29GYXIgKSkgKSB7XG5cdFx0XHRtYXRjaGVkID0gbWF0Y2guc2hpZnQoKTtcblx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0dmFsdWU6IG1hdGNoZWQsXG5cdFx0XHRcdC8vIENhc3QgZGVzY2VuZGFudCBjb21iaW5hdG9ycyB0byBzcGFjZVxuXHRcdFx0XHR0eXBlOiBtYXRjaFswXS5yZXBsYWNlKCBydHJpbSwgXCIgXCIgKVxuXHRcdFx0fSk7XG5cdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdH1cblxuXHRcdC8vIEZpbHRlcnNcblx0XHRmb3IgKCB0eXBlIGluIEV4cHIuZmlsdGVyICkge1xuXHRcdFx0aWYgKCAobWF0Y2ggPSBtYXRjaEV4cHJbIHR5cGUgXS5leGVjKCBzb0ZhciApKSAmJiAoIXByZUZpbHRlcnNbIHR5cGUgXSB8fFxuXHRcdFx0XHQobWF0Y2ggPSBwcmVGaWx0ZXJzWyB0eXBlIF0oIG1hdGNoICkpKSApIHtcblx0XHRcdFx0bWF0Y2hlZCA9IG1hdGNoLnNoaWZ0KCk7XG5cdFx0XHRcdHRva2Vucy5wdXNoKHtcblx0XHRcdFx0XHR2YWx1ZTogbWF0Y2hlZCxcblx0XHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRcdG1hdGNoZXM6IG1hdGNoXG5cdFx0XHRcdH0pO1xuXHRcdFx0XHRzb0ZhciA9IHNvRmFyLnNsaWNlKCBtYXRjaGVkLmxlbmd0aCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggIW1hdGNoZWQgKSB7XG5cdFx0XHRicmVhaztcblx0XHR9XG5cdH1cblxuXHQvLyBSZXR1cm4gdGhlIGxlbmd0aCBvZiB0aGUgaW52YWxpZCBleGNlc3Ncblx0Ly8gaWYgd2UncmUganVzdCBwYXJzaW5nXG5cdC8vIE90aGVyd2lzZSwgdGhyb3cgYW4gZXJyb3Igb3IgcmV0dXJuIHRva2Vuc1xuXHRyZXR1cm4gcGFyc2VPbmx5ID9cblx0XHRzb0Zhci5sZW5ndGggOlxuXHRcdHNvRmFyID9cblx0XHRcdFNpenpsZS5lcnJvciggc2VsZWN0b3IgKSA6XG5cdFx0XHQvLyBDYWNoZSB0aGUgdG9rZW5zXG5cdFx0XHR0b2tlbkNhY2hlKCBzZWxlY3RvciwgZ3JvdXBzICkuc2xpY2UoIDAgKTtcbn07XG5cbmZ1bmN0aW9uIHRvU2VsZWN0b3IoIHRva2VucyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGxlbiA9IHRva2Vucy5sZW5ndGgsXG5cdFx0c2VsZWN0b3IgPSBcIlwiO1xuXHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRzZWxlY3RvciArPSB0b2tlbnNbaV0udmFsdWU7XG5cdH1cblx0cmV0dXJuIHNlbGVjdG9yO1xufVxuXG5mdW5jdGlvbiBhZGRDb21iaW5hdG9yKCBtYXRjaGVyLCBjb21iaW5hdG9yLCBiYXNlICkge1xuXHR2YXIgZGlyID0gY29tYmluYXRvci5kaXIsXG5cdFx0c2tpcCA9IGNvbWJpbmF0b3IubmV4dCxcblx0XHRrZXkgPSBza2lwIHx8IGRpcixcblx0XHRjaGVja05vbkVsZW1lbnRzID0gYmFzZSAmJiBrZXkgPT09IFwicGFyZW50Tm9kZVwiLFxuXHRcdGRvbmVOYW1lID0gZG9uZSsrO1xuXG5cdHJldHVybiBjb21iaW5hdG9yLmZpcnN0ID9cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGNsb3Nlc3QgYW5jZXN0b3IvcHJlY2VkaW5nIGVsZW1lbnRcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0d2hpbGUgKCAoZWxlbSA9IGVsZW1bIGRpciBdKSApIHtcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSA6XG5cblx0XHQvLyBDaGVjayBhZ2FpbnN0IGFsbCBhbmNlc3Rvci9wcmVjZWRpbmcgZWxlbWVudHNcblx0XHRmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIG9sZENhY2hlLCB1bmlxdWVDYWNoZSwgb3V0ZXJDYWNoZSxcblx0XHRcdFx0bmV3Q2FjaGUgPSBbIGRpcnJ1bnMsIGRvbmVOYW1lIF07XG5cblx0XHRcdC8vIFdlIGNhbid0IHNldCBhcmJpdHJhcnkgZGF0YSBvbiBYTUwgbm9kZXMsIHNvIHRoZXkgZG9uJ3QgYmVuZWZpdCBmcm9tIGNvbWJpbmF0b3IgY2FjaGluZ1xuXHRcdFx0aWYgKCB4bWwgKSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZXIoIGVsZW0sIGNvbnRleHQsIHhtbCApICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdoaWxlICggKGVsZW0gPSBlbGVtWyBkaXIgXSkgKSB7XG5cdFx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxIHx8IGNoZWNrTm9uRWxlbWVudHMgKSB7XG5cdFx0XHRcdFx0XHRvdXRlckNhY2hlID0gZWxlbVsgZXhwYW5kbyBdIHx8IChlbGVtWyBleHBhbmRvIF0gPSB7fSk7XG5cblx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw5IG9ubHlcblx0XHRcdFx0XHRcdC8vIERlZmVuZCBhZ2FpbnN0IGNsb25lZCBhdHRyb3BlcnRpZXMgKGpRdWVyeSBnaC0xNzA5KVxuXHRcdFx0XHRcdFx0dW5pcXVlQ2FjaGUgPSBvdXRlckNhY2hlWyBlbGVtLnVuaXF1ZUlEIF0gfHwgKG91dGVyQ2FjaGVbIGVsZW0udW5pcXVlSUQgXSA9IHt9KTtcblxuXHRcdFx0XHRcdFx0aWYgKCBza2lwICYmIHNraXAgPT09IGVsZW0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSApIHtcblx0XHRcdFx0XHRcdFx0ZWxlbSA9IGVsZW1bIGRpciBdIHx8IGVsZW07XG5cdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCAob2xkQ2FjaGUgPSB1bmlxdWVDYWNoZVsga2V5IF0pICYmXG5cdFx0XHRcdFx0XHRcdG9sZENhY2hlWyAwIF0gPT09IGRpcnJ1bnMgJiYgb2xkQ2FjaGVbIDEgXSA9PT0gZG9uZU5hbWUgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gQXNzaWduIHRvIG5ld0NhY2hlIHNvIHJlc3VsdHMgYmFjay1wcm9wYWdhdGUgdG8gcHJldmlvdXMgZWxlbWVudHNcblx0XHRcdFx0XHRcdFx0cmV0dXJuIChuZXdDYWNoZVsgMiBdID0gb2xkQ2FjaGVbIDIgXSk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXVzZSBuZXdjYWNoZSBzbyByZXN1bHRzIGJhY2stcHJvcGFnYXRlIHRvIHByZXZpb3VzIGVsZW1lbnRzXG5cdFx0XHRcdFx0XHRcdHVuaXF1ZUNhY2hlWyBrZXkgXSA9IG5ld0NhY2hlO1xuXG5cdFx0XHRcdFx0XHRcdC8vIEEgbWF0Y2ggbWVhbnMgd2UncmUgZG9uZTsgYSBmYWlsIG1lYW5zIHdlIGhhdmUgdG8ga2VlcCBjaGVja2luZ1xuXHRcdFx0XHRcdFx0XHRpZiAoIChuZXdDYWNoZVsgMiBdID0gbWF0Y2hlciggZWxlbSwgY29udGV4dCwgeG1sICkpICkge1xuXHRcdFx0XHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fTtcbn1cblxuZnVuY3Rpb24gZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICkge1xuXHRyZXR1cm4gbWF0Y2hlcnMubGVuZ3RoID4gMSA/XG5cdFx0ZnVuY3Rpb24oIGVsZW0sIGNvbnRleHQsIHhtbCApIHtcblx0XHRcdHZhciBpID0gbWF0Y2hlcnMubGVuZ3RoO1xuXHRcdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRcdGlmICggIW1hdGNoZXJzW2ldKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH0gOlxuXHRcdG1hdGNoZXJzWzBdO1xufVxuXG5mdW5jdGlvbiBtdWx0aXBsZUNvbnRleHRzKCBzZWxlY3RvciwgY29udGV4dHMsIHJlc3VsdHMgKSB7XG5cdHZhciBpID0gMCxcblx0XHRsZW4gPSBjb250ZXh0cy5sZW5ndGg7XG5cdGZvciAoIDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFNpenpsZSggc2VsZWN0b3IsIGNvbnRleHRzW2ldLCByZXN1bHRzICk7XG5cdH1cblx0cmV0dXJuIHJlc3VsdHM7XG59XG5cbmZ1bmN0aW9uIGNvbmRlbnNlKCB1bm1hdGNoZWQsIG1hcCwgZmlsdGVyLCBjb250ZXh0LCB4bWwgKSB7XG5cdHZhciBlbGVtLFxuXHRcdG5ld1VubWF0Y2hlZCA9IFtdLFxuXHRcdGkgPSAwLFxuXHRcdGxlbiA9IHVubWF0Y2hlZC5sZW5ndGgsXG5cdFx0bWFwcGVkID0gbWFwICE9IG51bGw7XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAoZWxlbSA9IHVubWF0Y2hlZFtpXSkgKSB7XG5cdFx0XHRpZiAoICFmaWx0ZXIgfHwgZmlsdGVyKCBlbGVtLCBjb250ZXh0LCB4bWwgKSApIHtcblx0XHRcdFx0bmV3VW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0aWYgKCBtYXBwZWQgKSB7XG5cdFx0XHRcdFx0bWFwLnB1c2goIGkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiBuZXdVbm1hdGNoZWQ7XG59XG5cbmZ1bmN0aW9uIHNldE1hdGNoZXIoIHByZUZpbHRlciwgc2VsZWN0b3IsIG1hdGNoZXIsIHBvc3RGaWx0ZXIsIHBvc3RGaW5kZXIsIHBvc3RTZWxlY3RvciApIHtcblx0aWYgKCBwb3N0RmlsdGVyICYmICFwb3N0RmlsdGVyWyBleHBhbmRvIF0gKSB7XG5cdFx0cG9zdEZpbHRlciA9IHNldE1hdGNoZXIoIHBvc3RGaWx0ZXIgKTtcblx0fVxuXHRpZiAoIHBvc3RGaW5kZXIgJiYgIXBvc3RGaW5kZXJbIGV4cGFuZG8gXSApIHtcblx0XHRwb3N0RmluZGVyID0gc2V0TWF0Y2hlciggcG9zdEZpbmRlciwgcG9zdFNlbGVjdG9yICk7XG5cdH1cblx0cmV0dXJuIG1hcmtGdW5jdGlvbihmdW5jdGlvbiggc2VlZCwgcmVzdWx0cywgY29udGV4dCwgeG1sICkge1xuXHRcdHZhciB0ZW1wLCBpLCBlbGVtLFxuXHRcdFx0cHJlTWFwID0gW10sXG5cdFx0XHRwb3N0TWFwID0gW10sXG5cdFx0XHRwcmVleGlzdGluZyA9IHJlc3VsdHMubGVuZ3RoLFxuXG5cdFx0XHQvLyBHZXQgaW5pdGlhbCBlbGVtZW50cyBmcm9tIHNlZWQgb3IgY29udGV4dFxuXHRcdFx0ZWxlbXMgPSBzZWVkIHx8IG11bHRpcGxlQ29udGV4dHMoIHNlbGVjdG9yIHx8IFwiKlwiLCBjb250ZXh0Lm5vZGVUeXBlID8gWyBjb250ZXh0IF0gOiBjb250ZXh0LCBbXSApLFxuXG5cdFx0XHQvLyBQcmVmaWx0ZXIgdG8gZ2V0IG1hdGNoZXIgaW5wdXQsIHByZXNlcnZpbmcgYSBtYXAgZm9yIHNlZWQtcmVzdWx0cyBzeW5jaHJvbml6YXRpb25cblx0XHRcdG1hdGNoZXJJbiA9IHByZUZpbHRlciAmJiAoIHNlZWQgfHwgIXNlbGVjdG9yICkgP1xuXHRcdFx0XHRjb25kZW5zZSggZWxlbXMsIHByZU1hcCwgcHJlRmlsdGVyLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdGVsZW1zLFxuXG5cdFx0XHRtYXRjaGVyT3V0ID0gbWF0Y2hlciA/XG5cdFx0XHRcdC8vIElmIHdlIGhhdmUgYSBwb3N0RmluZGVyLCBvciBmaWx0ZXJlZCBzZWVkLCBvciBub24tc2VlZCBwb3N0RmlsdGVyIG9yIHByZWV4aXN0aW5nIHJlc3VsdHMsXG5cdFx0XHRcdHBvc3RGaW5kZXIgfHwgKCBzZWVkID8gcHJlRmlsdGVyIDogcHJlZXhpc3RpbmcgfHwgcG9zdEZpbHRlciApID9cblxuXHRcdFx0XHRcdC8vIC4uLmludGVybWVkaWF0ZSBwcm9jZXNzaW5nIGlzIG5lY2Vzc2FyeVxuXHRcdFx0XHRcdFtdIDpcblxuXHRcdFx0XHRcdC8vIC4uLm90aGVyd2lzZSB1c2UgcmVzdWx0cyBkaXJlY3RseVxuXHRcdFx0XHRcdHJlc3VsdHMgOlxuXHRcdFx0XHRtYXRjaGVySW47XG5cblx0XHQvLyBGaW5kIHByaW1hcnkgbWF0Y2hlc1xuXHRcdGlmICggbWF0Y2hlciApIHtcblx0XHRcdG1hdGNoZXIoIG1hdGNoZXJJbiwgbWF0Y2hlck91dCwgY29udGV4dCwgeG1sICk7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgcG9zdEZpbHRlclxuXHRcdGlmICggcG9zdEZpbHRlciApIHtcblx0XHRcdHRlbXAgPSBjb25kZW5zZSggbWF0Y2hlck91dCwgcG9zdE1hcCApO1xuXHRcdFx0cG9zdEZpbHRlciggdGVtcCwgW10sIGNvbnRleHQsIHhtbCApO1xuXG5cdFx0XHQvLyBVbi1tYXRjaCBmYWlsaW5nIGVsZW1lbnRzIGJ5IG1vdmluZyB0aGVtIGJhY2sgdG8gbWF0Y2hlckluXG5cdFx0XHRpID0gdGVtcC5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdFx0aWYgKCAoZWxlbSA9IHRlbXBbaV0pICkge1xuXHRcdFx0XHRcdG1hdGNoZXJPdXRbIHBvc3RNYXBbaV0gXSA9ICEobWF0Y2hlckluWyBwb3N0TWFwW2ldIF0gPSBlbGVtKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggc2VlZCApIHtcblx0XHRcdGlmICggcG9zdEZpbmRlciB8fCBwcmVGaWx0ZXIgKSB7XG5cdFx0XHRcdGlmICggcG9zdEZpbmRlciApIHtcblx0XHRcdFx0XHQvLyBHZXQgdGhlIGZpbmFsIG1hdGNoZXJPdXQgYnkgY29uZGVuc2luZyB0aGlzIGludGVybWVkaWF0ZSBpbnRvIHBvc3RGaW5kZXIgY29udGV4dHNcblx0XHRcdFx0XHR0ZW1wID0gW107XG5cdFx0XHRcdFx0aSA9IG1hdGNoZXJPdXQubGVuZ3RoO1xuXHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoZWxlbSA9IG1hdGNoZXJPdXRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHQvLyBSZXN0b3JlIG1hdGNoZXJJbiBzaW5jZSBlbGVtIGlzIG5vdCB5ZXQgYSBmaW5hbCBtYXRjaFxuXHRcdFx0XHRcdFx0XHR0ZW1wLnB1c2goIChtYXRjaGVySW5baV0gPSBlbGVtKSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRwb3N0RmluZGVyKCBudWxsLCAobWF0Y2hlck91dCA9IFtdKSwgdGVtcCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBNb3ZlIG1hdGNoZWQgZWxlbWVudHMgZnJvbSBzZWVkIHRvIHJlc3VsdHMgdG8ga2VlcCB0aGVtIHN5bmNocm9uaXplZFxuXHRcdFx0XHRpID0gbWF0Y2hlck91dC5sZW5ndGg7XG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdGlmICggKGVsZW0gPSBtYXRjaGVyT3V0W2ldKSAmJlxuXHRcdFx0XHRcdFx0KHRlbXAgPSBwb3N0RmluZGVyID8gaW5kZXhPZiggc2VlZCwgZWxlbSApIDogcHJlTWFwW2ldKSA+IC0xICkge1xuXG5cdFx0XHRcdFx0XHRzZWVkW3RlbXBdID0gIShyZXN1bHRzW3RlbXBdID0gZWxlbSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBBZGQgZWxlbWVudHMgdG8gcmVzdWx0cywgdGhyb3VnaCBwb3N0RmluZGVyIGlmIGRlZmluZWRcblx0XHR9IGVsc2Uge1xuXHRcdFx0bWF0Y2hlck91dCA9IGNvbmRlbnNlKFxuXHRcdFx0XHRtYXRjaGVyT3V0ID09PSByZXN1bHRzID9cblx0XHRcdFx0XHRtYXRjaGVyT3V0LnNwbGljZSggcHJlZXhpc3RpbmcsIG1hdGNoZXJPdXQubGVuZ3RoICkgOlxuXHRcdFx0XHRcdG1hdGNoZXJPdXRcblx0XHRcdCk7XG5cdFx0XHRpZiAoIHBvc3RGaW5kZXIgKSB7XG5cdFx0XHRcdHBvc3RGaW5kZXIoIG51bGwsIHJlc3VsdHMsIG1hdGNoZXJPdXQsIHhtbCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgbWF0Y2hlck91dCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSk7XG59XG5cbmZ1bmN0aW9uIG1hdGNoZXJGcm9tVG9rZW5zKCB0b2tlbnMgKSB7XG5cdHZhciBjaGVja0NvbnRleHQsIG1hdGNoZXIsIGosXG5cdFx0bGVuID0gdG9rZW5zLmxlbmd0aCxcblx0XHRsZWFkaW5nUmVsYXRpdmUgPSBFeHByLnJlbGF0aXZlWyB0b2tlbnNbMF0udHlwZSBdLFxuXHRcdGltcGxpY2l0UmVsYXRpdmUgPSBsZWFkaW5nUmVsYXRpdmUgfHwgRXhwci5yZWxhdGl2ZVtcIiBcIl0sXG5cdFx0aSA9IGxlYWRpbmdSZWxhdGl2ZSA/IDEgOiAwLFxuXG5cdFx0Ly8gVGhlIGZvdW5kYXRpb25hbCBtYXRjaGVyIGVuc3VyZXMgdGhhdCBlbGVtZW50cyBhcmUgcmVhY2hhYmxlIGZyb20gdG9wLWxldmVsIGNvbnRleHQocylcblx0XHRtYXRjaENvbnRleHQgPSBhZGRDb21iaW5hdG9yKCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiBlbGVtID09PSBjaGVja0NvbnRleHQ7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoQW55Q29udGV4dCA9IGFkZENvbWJpbmF0b3IoIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YoIGNoZWNrQ29udGV4dCwgZWxlbSApID4gLTE7XG5cdFx0fSwgaW1wbGljaXRSZWxhdGl2ZSwgdHJ1ZSApLFxuXHRcdG1hdGNoZXJzID0gWyBmdW5jdGlvbiggZWxlbSwgY29udGV4dCwgeG1sICkge1xuXHRcdFx0dmFyIHJldCA9ICggIWxlYWRpbmdSZWxhdGl2ZSAmJiAoIHhtbCB8fCBjb250ZXh0ICE9PSBvdXRlcm1vc3RDb250ZXh0ICkgKSB8fCAoXG5cdFx0XHRcdChjaGVja0NvbnRleHQgPSBjb250ZXh0KS5ub2RlVHlwZSA/XG5cdFx0XHRcdFx0bWF0Y2hDb250ZXh0KCBlbGVtLCBjb250ZXh0LCB4bWwgKSA6XG5cdFx0XHRcdFx0bWF0Y2hBbnlDb250ZXh0KCBlbGVtLCBjb250ZXh0LCB4bWwgKSApO1xuXHRcdFx0Ly8gQXZvaWQgaGFuZ2luZyBvbnRvIGVsZW1lbnQgKGlzc3VlICMyOTkpXG5cdFx0XHRjaGVja0NvbnRleHQgPSBudWxsO1xuXHRcdFx0cmV0dXJuIHJldDtcblx0XHR9IF07XG5cblx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0aWYgKCAobWF0Y2hlciA9IEV4cHIucmVsYXRpdmVbIHRva2Vuc1tpXS50eXBlIF0pICkge1xuXHRcdFx0bWF0Y2hlcnMgPSBbIGFkZENvbWJpbmF0b3IoZWxlbWVudE1hdGNoZXIoIG1hdGNoZXJzICksIG1hdGNoZXIpIF07XG5cdFx0fSBlbHNlIHtcblx0XHRcdG1hdGNoZXIgPSBFeHByLmZpbHRlclsgdG9rZW5zW2ldLnR5cGUgXS5hcHBseSggbnVsbCwgdG9rZW5zW2ldLm1hdGNoZXMgKTtcblxuXHRcdFx0Ly8gUmV0dXJuIHNwZWNpYWwgdXBvbiBzZWVpbmcgYSBwb3NpdGlvbmFsIG1hdGNoZXJcblx0XHRcdGlmICggbWF0Y2hlclsgZXhwYW5kbyBdICkge1xuXHRcdFx0XHQvLyBGaW5kIHRoZSBuZXh0IHJlbGF0aXZlIG9wZXJhdG9yIChpZiBhbnkpIGZvciBwcm9wZXIgaGFuZGxpbmdcblx0XHRcdFx0aiA9ICsraTtcblx0XHRcdFx0Zm9yICggOyBqIDwgbGVuOyBqKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBFeHByLnJlbGF0aXZlWyB0b2tlbnNbal0udHlwZSBdICkge1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBzZXRNYXRjaGVyKFxuXHRcdFx0XHRcdGkgPiAxICYmIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApLFxuXHRcdFx0XHRcdGkgPiAxICYmIHRvU2VsZWN0b3IoXG5cdFx0XHRcdFx0XHQvLyBJZiB0aGUgcHJlY2VkaW5nIHRva2VuIHdhcyBhIGRlc2NlbmRhbnQgY29tYmluYXRvciwgaW5zZXJ0IGFuIGltcGxpY2l0IGFueS1lbGVtZW50IGAqYFxuXHRcdFx0XHRcdFx0dG9rZW5zLnNsaWNlKCAwLCBpIC0gMSApLmNvbmNhdCh7IHZhbHVlOiB0b2tlbnNbIGkgLSAyIF0udHlwZSA9PT0gXCIgXCIgPyBcIipcIiA6IFwiXCIgfSlcblx0XHRcdFx0XHQpLnJlcGxhY2UoIHJ0cmltLCBcIiQxXCIgKSxcblx0XHRcdFx0XHRtYXRjaGVyLFxuXHRcdFx0XHRcdGkgPCBqICYmIG1hdGNoZXJGcm9tVG9rZW5zKCB0b2tlbnMuc2xpY2UoIGksIGogKSApLFxuXHRcdFx0XHRcdGogPCBsZW4gJiYgbWF0Y2hlckZyb21Ub2tlbnMoICh0b2tlbnMgPSB0b2tlbnMuc2xpY2UoIGogKSkgKSxcblx0XHRcdFx0XHRqIDwgbGVuICYmIHRvU2VsZWN0b3IoIHRva2VucyApXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0XHRtYXRjaGVycy5wdXNoKCBtYXRjaGVyICk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW1lbnRNYXRjaGVyKCBtYXRjaGVycyApO1xufVxuXG5mdW5jdGlvbiBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSB7XG5cdHZhciBieVNldCA9IHNldE1hdGNoZXJzLmxlbmd0aCA+IDAsXG5cdFx0YnlFbGVtZW50ID0gZWxlbWVudE1hdGNoZXJzLmxlbmd0aCA+IDAsXG5cdFx0c3VwZXJNYXRjaGVyID0gZnVuY3Rpb24oIHNlZWQsIGNvbnRleHQsIHhtbCwgcmVzdWx0cywgb3V0ZXJtb3N0ICkge1xuXHRcdFx0dmFyIGVsZW0sIGosIG1hdGNoZXIsXG5cdFx0XHRcdG1hdGNoZWRDb3VudCA9IDAsXG5cdFx0XHRcdGkgPSBcIjBcIixcblx0XHRcdFx0dW5tYXRjaGVkID0gc2VlZCAmJiBbXSxcblx0XHRcdFx0c2V0TWF0Y2hlZCA9IFtdLFxuXHRcdFx0XHRjb250ZXh0QmFja3VwID0gb3V0ZXJtb3N0Q29udGV4dCxcblx0XHRcdFx0Ly8gV2UgbXVzdCBhbHdheXMgaGF2ZSBlaXRoZXIgc2VlZCBlbGVtZW50cyBvciBvdXRlcm1vc3QgY29udGV4dFxuXHRcdFx0XHRlbGVtcyA9IHNlZWQgfHwgYnlFbGVtZW50ICYmIEV4cHIuZmluZFtcIlRBR1wiXSggXCIqXCIsIG91dGVybW9zdCApLFxuXHRcdFx0XHQvLyBVc2UgaW50ZWdlciBkaXJydW5zIGlmZiB0aGlzIGlzIHRoZSBvdXRlcm1vc3QgbWF0Y2hlclxuXHRcdFx0XHRkaXJydW5zVW5pcXVlID0gKGRpcnJ1bnMgKz0gY29udGV4dEJhY2t1cCA9PSBudWxsID8gMSA6IE1hdGgucmFuZG9tKCkgfHwgMC4xKSxcblx0XHRcdFx0bGVuID0gZWxlbXMubGVuZ3RoO1xuXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0b3V0ZXJtb3N0Q29udGV4dCA9IGNvbnRleHQgPT09IGRvY3VtZW50IHx8IGNvbnRleHQgfHwgb3V0ZXJtb3N0O1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBZGQgZWxlbWVudHMgcGFzc2luZyBlbGVtZW50TWF0Y2hlcnMgZGlyZWN0bHkgdG8gcmVzdWx0c1xuXHRcdFx0Ly8gU3VwcG9ydDogSUU8OSwgU2FmYXJpXG5cdFx0XHQvLyBUb2xlcmF0ZSBOb2RlTGlzdCBwcm9wZXJ0aWVzIChJRTogXCJsZW5ndGhcIjsgU2FmYXJpOiA8bnVtYmVyPikgbWF0Y2hpbmcgZWxlbWVudHMgYnkgaWRcblx0XHRcdGZvciAoIDsgaSAhPT0gbGVuICYmIChlbGVtID0gZWxlbXNbaV0pICE9IG51bGw7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBieUVsZW1lbnQgJiYgZWxlbSApIHtcblx0XHRcdFx0XHRqID0gMDtcblx0XHRcdFx0XHRpZiAoICFjb250ZXh0ICYmIGVsZW0ub3duZXJEb2N1bWVudCAhPT0gZG9jdW1lbnQgKSB7XG5cdFx0XHRcdFx0XHRzZXREb2N1bWVudCggZWxlbSApO1xuXHRcdFx0XHRcdFx0eG1sID0gIWRvY3VtZW50SXNIVE1MO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR3aGlsZSAoIChtYXRjaGVyID0gZWxlbWVudE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVyKCBlbGVtLCBjb250ZXh0IHx8IGRvY3VtZW50LCB4bWwpICkge1xuXHRcdFx0XHRcdFx0XHRyZXN1bHRzLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggb3V0ZXJtb3N0ICkge1xuXHRcdFx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gVHJhY2sgdW5tYXRjaGVkIGVsZW1lbnRzIGZvciBzZXQgZmlsdGVyc1xuXHRcdFx0XHRpZiAoIGJ5U2V0ICkge1xuXHRcdFx0XHRcdC8vIFRoZXkgd2lsbCBoYXZlIGdvbmUgdGhyb3VnaCBhbGwgcG9zc2libGUgbWF0Y2hlcnNcblx0XHRcdFx0XHRpZiAoIChlbGVtID0gIW1hdGNoZXIgJiYgZWxlbSkgKSB7XG5cdFx0XHRcdFx0XHRtYXRjaGVkQ291bnQtLTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHQvLyBMZW5ndGhlbiB0aGUgYXJyYXkgZm9yIGV2ZXJ5IGVsZW1lbnQsIG1hdGNoZWQgb3Igbm90XG5cdFx0XHRcdFx0aWYgKCBzZWVkICkge1xuXHRcdFx0XHRcdFx0dW5tYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gYGlgIGlzIG5vdyB0aGUgY291bnQgb2YgZWxlbWVudHMgdmlzaXRlZCBhYm92ZSwgYW5kIGFkZGluZyBpdCB0byBgbWF0Y2hlZENvdW50YFxuXHRcdFx0Ly8gbWFrZXMgdGhlIGxhdHRlciBub25uZWdhdGl2ZS5cblx0XHRcdG1hdGNoZWRDb3VudCArPSBpO1xuXG5cdFx0XHQvLyBBcHBseSBzZXQgZmlsdGVycyB0byB1bm1hdGNoZWQgZWxlbWVudHNcblx0XHRcdC8vIE5PVEU6IFRoaXMgY2FuIGJlIHNraXBwZWQgaWYgdGhlcmUgYXJlIG5vIHVubWF0Y2hlZCBlbGVtZW50cyAoaS5lLiwgYG1hdGNoZWRDb3VudGBcblx0XHRcdC8vIGVxdWFscyBgaWApLCB1bmxlc3Mgd2UgZGlkbid0IHZpc2l0IF9hbnlfIGVsZW1lbnRzIGluIHRoZSBhYm92ZSBsb29wIGJlY2F1c2Ugd2UgaGF2ZVxuXHRcdFx0Ly8gbm8gZWxlbWVudCBtYXRjaGVycyBhbmQgbm8gc2VlZC5cblx0XHRcdC8vIEluY3JlbWVudGluZyBhbiBpbml0aWFsbHktc3RyaW5nIFwiMFwiIGBpYCBhbGxvd3MgYGlgIHRvIHJlbWFpbiBhIHN0cmluZyBvbmx5IGluIHRoYXRcblx0XHRcdC8vIGNhc2UsIHdoaWNoIHdpbGwgcmVzdWx0IGluIGEgXCIwMFwiIGBtYXRjaGVkQ291bnRgIHRoYXQgZGlmZmVycyBmcm9tIGBpYCBidXQgaXMgYWxzb1xuXHRcdFx0Ly8gbnVtZXJpY2FsbHkgemVyby5cblx0XHRcdGlmICggYnlTZXQgJiYgaSAhPT0gbWF0Y2hlZENvdW50ICkge1xuXHRcdFx0XHRqID0gMDtcblx0XHRcdFx0d2hpbGUgKCAobWF0Y2hlciA9IHNldE1hdGNoZXJzW2orK10pICkge1xuXHRcdFx0XHRcdG1hdGNoZXIoIHVubWF0Y2hlZCwgc2V0TWF0Y2hlZCwgY29udGV4dCwgeG1sICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIHNlZWQgKSB7XG5cdFx0XHRcdFx0Ly8gUmVpbnRlZ3JhdGUgZWxlbWVudCBtYXRjaGVzIHRvIGVsaW1pbmF0ZSB0aGUgbmVlZCBmb3Igc29ydGluZ1xuXHRcdFx0XHRcdGlmICggbWF0Y2hlZENvdW50ID4gMCApIHtcblx0XHRcdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdFx0XHRpZiAoICEodW5tYXRjaGVkW2ldIHx8IHNldE1hdGNoZWRbaV0pICkge1xuXHRcdFx0XHRcdFx0XHRcdHNldE1hdGNoZWRbaV0gPSBwb3AuY2FsbCggcmVzdWx0cyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gRGlzY2FyZCBpbmRleCBwbGFjZWhvbGRlciB2YWx1ZXMgdG8gZ2V0IG9ubHkgYWN0dWFsIG1hdGNoZXNcblx0XHRcdFx0XHRzZXRNYXRjaGVkID0gY29uZGVuc2UoIHNldE1hdGNoZWQgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFkZCBtYXRjaGVzIHRvIHJlc3VsdHNcblx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2V0TWF0Y2hlZCApO1xuXG5cdFx0XHRcdC8vIFNlZWRsZXNzIHNldCBtYXRjaGVzIHN1Y2NlZWRpbmcgbXVsdGlwbGUgc3VjY2Vzc2Z1bCBtYXRjaGVycyBzdGlwdWxhdGUgc29ydGluZ1xuXHRcdFx0XHRpZiAoIG91dGVybW9zdCAmJiAhc2VlZCAmJiBzZXRNYXRjaGVkLmxlbmd0aCA+IDAgJiZcblx0XHRcdFx0XHQoIG1hdGNoZWRDb3VudCArIHNldE1hdGNoZXJzLmxlbmd0aCApID4gMSApIHtcblxuXHRcdFx0XHRcdFNpenpsZS51bmlxdWVTb3J0KCByZXN1bHRzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gT3ZlcnJpZGUgbWFuaXB1bGF0aW9uIG9mIGdsb2JhbHMgYnkgbmVzdGVkIG1hdGNoZXJzXG5cdFx0XHRpZiAoIG91dGVybW9zdCApIHtcblx0XHRcdFx0ZGlycnVucyA9IGRpcnJ1bnNVbmlxdWU7XG5cdFx0XHRcdG91dGVybW9zdENvbnRleHQgPSBjb250ZXh0QmFja3VwO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdW5tYXRjaGVkO1xuXHRcdH07XG5cblx0cmV0dXJuIGJ5U2V0ID9cblx0XHRtYXJrRnVuY3Rpb24oIHN1cGVyTWF0Y2hlciApIDpcblx0XHRzdXBlck1hdGNoZXI7XG59XG5cbmNvbXBpbGUgPSBTaXp6bGUuY29tcGlsZSA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgbWF0Y2ggLyogSW50ZXJuYWwgVXNlIE9ubHkgKi8gKSB7XG5cdHZhciBpLFxuXHRcdHNldE1hdGNoZXJzID0gW10sXG5cdFx0ZWxlbWVudE1hdGNoZXJzID0gW10sXG5cdFx0Y2FjaGVkID0gY29tcGlsZXJDYWNoZVsgc2VsZWN0b3IgKyBcIiBcIiBdO1xuXG5cdGlmICggIWNhY2hlZCApIHtcblx0XHQvLyBHZW5lcmF0ZSBhIGZ1bmN0aW9uIG9mIHJlY3Vyc2l2ZSBmdW5jdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCB0byBjaGVjayBlYWNoIGVsZW1lbnRcblx0XHRpZiAoICFtYXRjaCApIHtcblx0XHRcdG1hdGNoID0gdG9rZW5pemUoIHNlbGVjdG9yICk7XG5cdFx0fVxuXHRcdGkgPSBtYXRjaC5sZW5ndGg7XG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRjYWNoZWQgPSBtYXRjaGVyRnJvbVRva2VucyggbWF0Y2hbaV0gKTtcblx0XHRcdGlmICggY2FjaGVkWyBleHBhbmRvIF0gKSB7XG5cdFx0XHRcdHNldE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZWxlbWVudE1hdGNoZXJzLnB1c2goIGNhY2hlZCApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIENhY2hlIHRoZSBjb21waWxlZCBmdW5jdGlvblxuXHRcdGNhY2hlZCA9IGNvbXBpbGVyQ2FjaGUoIHNlbGVjdG9yLCBtYXRjaGVyRnJvbUdyb3VwTWF0Y2hlcnMoIGVsZW1lbnRNYXRjaGVycywgc2V0TWF0Y2hlcnMgKSApO1xuXG5cdFx0Ly8gU2F2ZSBzZWxlY3RvciBhbmQgdG9rZW5pemF0aW9uXG5cdFx0Y2FjaGVkLnNlbGVjdG9yID0gc2VsZWN0b3I7XG5cdH1cblx0cmV0dXJuIGNhY2hlZDtcbn07XG5cbi8qKlxuICogQSBsb3ctbGV2ZWwgc2VsZWN0aW9uIGZ1bmN0aW9uIHRoYXQgd29ya3Mgd2l0aCBTaXp6bGUncyBjb21waWxlZFxuICogIHNlbGVjdG9yIGZ1bmN0aW9uc1xuICogQHBhcmFtIHtTdHJpbmd8RnVuY3Rpb259IHNlbGVjdG9yIEEgc2VsZWN0b3Igb3IgYSBwcmUtY29tcGlsZWRcbiAqICBzZWxlY3RvciBmdW5jdGlvbiBidWlsdCB3aXRoIFNpenpsZS5jb21waWxlXG4gKiBAcGFyYW0ge0VsZW1lbnR9IGNvbnRleHRcbiAqIEBwYXJhbSB7QXJyYXl9IFtyZXN1bHRzXVxuICogQHBhcmFtIHtBcnJheX0gW3NlZWRdIEEgc2V0IG9mIGVsZW1lbnRzIHRvIG1hdGNoIGFnYWluc3RcbiAqL1xuc2VsZWN0ID0gU2l6emxlLnNlbGVjdCA9IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCwgcmVzdWx0cywgc2VlZCApIHtcblx0dmFyIGksIHRva2VucywgdG9rZW4sIHR5cGUsIGZpbmQsXG5cdFx0Y29tcGlsZWQgPSB0eXBlb2Ygc2VsZWN0b3IgPT09IFwiZnVuY3Rpb25cIiAmJiBzZWxlY3Rvcixcblx0XHRtYXRjaCA9ICFzZWVkICYmIHRva2VuaXplKCAoc2VsZWN0b3IgPSBjb21waWxlZC5zZWxlY3RvciB8fCBzZWxlY3RvcikgKTtcblxuXHRyZXN1bHRzID0gcmVzdWx0cyB8fCBbXTtcblxuXHQvLyBUcnkgdG8gbWluaW1pemUgb3BlcmF0aW9ucyBpZiB0aGVyZSBpcyBvbmx5IG9uZSBzZWxlY3RvciBpbiB0aGUgbGlzdCBhbmQgbm8gc2VlZFxuXHQvLyAodGhlIGxhdHRlciBvZiB3aGljaCBndWFyYW50ZWVzIHVzIGNvbnRleHQpXG5cdGlmICggbWF0Y2gubGVuZ3RoID09PSAxICkge1xuXG5cdFx0Ly8gUmVkdWNlIGNvbnRleHQgaWYgdGhlIGxlYWRpbmcgY29tcG91bmQgc2VsZWN0b3IgaXMgYW4gSURcblx0XHR0b2tlbnMgPSBtYXRjaFswXSA9IG1hdGNoWzBdLnNsaWNlKCAwICk7XG5cdFx0aWYgKCB0b2tlbnMubGVuZ3RoID4gMiAmJiAodG9rZW4gPSB0b2tlbnNbMF0pLnR5cGUgPT09IFwiSURcIiAmJlxuXHRcdFx0XHRjb250ZXh0Lm5vZGVUeXBlID09PSA5ICYmIGRvY3VtZW50SXNIVE1MICYmIEV4cHIucmVsYXRpdmVbIHRva2Vuc1sxXS50eXBlIF0gKSB7XG5cblx0XHRcdGNvbnRleHQgPSAoIEV4cHIuZmluZFtcIklEXCJdKCB0b2tlbi5tYXRjaGVzWzBdLnJlcGxhY2UocnVuZXNjYXBlLCBmdW5lc2NhcGUpLCBjb250ZXh0ICkgfHwgW10gKVswXTtcblx0XHRcdGlmICggIWNvbnRleHQgKSB7XG5cdFx0XHRcdHJldHVybiByZXN1bHRzO1xuXG5cdFx0XHQvLyBQcmVjb21waWxlZCBtYXRjaGVycyB3aWxsIHN0aWxsIHZlcmlmeSBhbmNlc3RyeSwgc28gc3RlcCB1cCBhIGxldmVsXG5cdFx0XHR9IGVsc2UgaWYgKCBjb21waWxlZCApIHtcblx0XHRcdFx0Y29udGV4dCA9IGNvbnRleHQucGFyZW50Tm9kZTtcblx0XHRcdH1cblxuXHRcdFx0c2VsZWN0b3IgPSBzZWxlY3Rvci5zbGljZSggdG9rZW5zLnNoaWZ0KCkudmFsdWUubGVuZ3RoICk7XG5cdFx0fVxuXG5cdFx0Ly8gRmV0Y2ggYSBzZWVkIHNldCBmb3IgcmlnaHQtdG8tbGVmdCBtYXRjaGluZ1xuXHRcdGkgPSBtYXRjaEV4cHJbXCJuZWVkc0NvbnRleHRcIl0udGVzdCggc2VsZWN0b3IgKSA/IDAgOiB0b2tlbnMubGVuZ3RoO1xuXHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0dG9rZW4gPSB0b2tlbnNbaV07XG5cblx0XHRcdC8vIEFib3J0IGlmIHdlIGhpdCBhIGNvbWJpbmF0b3Jcblx0XHRcdGlmICggRXhwci5yZWxhdGl2ZVsgKHR5cGUgPSB0b2tlbi50eXBlKSBdICkge1xuXHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHRcdGlmICggKGZpbmQgPSBFeHByLmZpbmRbIHR5cGUgXSkgKSB7XG5cdFx0XHRcdC8vIFNlYXJjaCwgZXhwYW5kaW5nIGNvbnRleHQgZm9yIGxlYWRpbmcgc2libGluZyBjb21iaW5hdG9yc1xuXHRcdFx0XHRpZiAoIChzZWVkID0gZmluZChcblx0XHRcdFx0XHR0b2tlbi5tYXRjaGVzWzBdLnJlcGxhY2UoIHJ1bmVzY2FwZSwgZnVuZXNjYXBlICksXG5cdFx0XHRcdFx0cnNpYmxpbmcudGVzdCggdG9rZW5zWzBdLnR5cGUgKSAmJiB0ZXN0Q29udGV4dCggY29udGV4dC5wYXJlbnROb2RlICkgfHwgY29udGV4dFxuXHRcdFx0XHQpKSApIHtcblxuXHRcdFx0XHRcdC8vIElmIHNlZWQgaXMgZW1wdHkgb3Igbm8gdG9rZW5zIHJlbWFpbiwgd2UgY2FuIHJldHVybiBlYXJseVxuXHRcdFx0XHRcdHRva2Vucy5zcGxpY2UoIGksIDEgKTtcblx0XHRcdFx0XHRzZWxlY3RvciA9IHNlZWQubGVuZ3RoICYmIHRvU2VsZWN0b3IoIHRva2VucyApO1xuXHRcdFx0XHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0XHRcdFx0cHVzaC5hcHBseSggcmVzdWx0cywgc2VlZCApO1xuXHRcdFx0XHRcdFx0cmV0dXJuIHJlc3VsdHM7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblxuXHQvLyBDb21waWxlIGFuZCBleGVjdXRlIGEgZmlsdGVyaW5nIGZ1bmN0aW9uIGlmIG9uZSBpcyBub3QgcHJvdmlkZWRcblx0Ly8gUHJvdmlkZSBgbWF0Y2hgIHRvIGF2b2lkIHJldG9rZW5pemF0aW9uIGlmIHdlIG1vZGlmaWVkIHRoZSBzZWxlY3RvciBhYm92ZVxuXHQoIGNvbXBpbGVkIHx8IGNvbXBpbGUoIHNlbGVjdG9yLCBtYXRjaCApICkoXG5cdFx0c2VlZCxcblx0XHRjb250ZXh0LFxuXHRcdCFkb2N1bWVudElzSFRNTCxcblx0XHRyZXN1bHRzLFxuXHRcdCFjb250ZXh0IHx8IHJzaWJsaW5nLnRlc3QoIHNlbGVjdG9yICkgJiYgdGVzdENvbnRleHQoIGNvbnRleHQucGFyZW50Tm9kZSApIHx8IGNvbnRleHRcblx0KTtcblx0cmV0dXJuIHJlc3VsdHM7XG59O1xuXG4vLyBPbmUtdGltZSBhc3NpZ25tZW50c1xuXG4vLyBTb3J0IHN0YWJpbGl0eVxuc3VwcG9ydC5zb3J0U3RhYmxlID0gZXhwYW5kby5zcGxpdChcIlwiKS5zb3J0KCBzb3J0T3JkZXIgKS5qb2luKFwiXCIpID09PSBleHBhbmRvO1xuXG4vLyBTdXBwb3J0OiBDaHJvbWUgMTQtMzUrXG4vLyBBbHdheXMgYXNzdW1lIGR1cGxpY2F0ZXMgaWYgdGhleSBhcmVuJ3QgcGFzc2VkIHRvIHRoZSBjb21wYXJpc29uIGZ1bmN0aW9uXG5zdXBwb3J0LmRldGVjdER1cGxpY2F0ZXMgPSAhIWhhc0R1cGxpY2F0ZTtcblxuLy8gSW5pdGlhbGl6ZSBhZ2FpbnN0IHRoZSBkZWZhdWx0IGRvY3VtZW50XG5zZXREb2N1bWVudCgpO1xuXG4vLyBTdXBwb3J0OiBXZWJraXQ8NTM3LjMyIC0gU2FmYXJpIDYuMC4zL0Nocm9tZSAyNSAoZml4ZWQgaW4gQ2hyb21lIDI3KVxuLy8gRGV0YWNoZWQgbm9kZXMgY29uZm91bmRpbmdseSBmb2xsb3cgKmVhY2ggb3RoZXIqXG5zdXBwb3J0LnNvcnREZXRhY2hlZCA9IGFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdC8vIFNob3VsZCByZXR1cm4gMSwgYnV0IHJldHVybnMgNCAoZm9sbG93aW5nKVxuXHRyZXR1cm4gZWwuY29tcGFyZURvY3VtZW50UG9zaXRpb24oIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJmaWVsZHNldFwiKSApICYgMTtcbn0pO1xuXG4vLyBTdXBwb3J0OiBJRTw4XG4vLyBQcmV2ZW50IGF0dHJpYnV0ZS9wcm9wZXJ0eSBcImludGVycG9sYXRpb25cIlxuLy8gaHR0cHM6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9tczUzNjQyOSUyOFZTLjg1JTI5LmFzcHhcbmlmICggIWFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdGVsLmlubmVySFRNTCA9IFwiPGEgaHJlZj0nIyc+PC9hPlwiO1xuXHRyZXR1cm4gZWwuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoXCJocmVmXCIpID09PSBcIiNcIiA7XG59KSApIHtcblx0YWRkSGFuZGxlKCBcInR5cGV8aHJlZnxoZWlnaHR8d2lkdGhcIiwgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdGlmICggIWlzWE1MICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBuYW1lLCBuYW1lLnRvTG93ZXJDYXNlKCkgPT09IFwidHlwZVwiID8gMSA6IDIgKTtcblx0XHR9XG5cdH0pO1xufVxuXG4vLyBTdXBwb3J0OiBJRTw5XG4vLyBVc2UgZGVmYXVsdFZhbHVlIGluIHBsYWNlIG9mIGdldEF0dHJpYnV0ZShcInZhbHVlXCIpXG5pZiAoICFzdXBwb3J0LmF0dHJpYnV0ZXMgfHwgIWFzc2VydChmdW5jdGlvbiggZWwgKSB7XG5cdGVsLmlubmVySFRNTCA9IFwiPGlucHV0Lz5cIjtcblx0ZWwuZmlyc3RDaGlsZC5zZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiwgXCJcIiApO1xuXHRyZXR1cm4gZWwuZmlyc3RDaGlsZC5nZXRBdHRyaWJ1dGUoIFwidmFsdWVcIiApID09PSBcIlwiO1xufSkgKSB7XG5cdGFkZEhhbmRsZSggXCJ2YWx1ZVwiLCBmdW5jdGlvbiggZWxlbSwgbmFtZSwgaXNYTUwgKSB7XG5cdFx0aWYgKCAhaXNYTUwgJiYgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSBcImlucHV0XCIgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbS5kZWZhdWx0VmFsdWU7XG5cdFx0fVxuXHR9KTtcbn1cblxuLy8gU3VwcG9ydDogSUU8OVxuLy8gVXNlIGdldEF0dHJpYnV0ZU5vZGUgdG8gZmV0Y2ggYm9vbGVhbnMgd2hlbiBnZXRBdHRyaWJ1dGUgbGllc1xuaWYgKCAhYXNzZXJ0KGZ1bmN0aW9uKCBlbCApIHtcblx0cmV0dXJuIGVsLmdldEF0dHJpYnV0ZShcImRpc2FibGVkXCIpID09IG51bGw7XG59KSApIHtcblx0YWRkSGFuZGxlKCBib29sZWFucywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciB2YWw7XG5cdFx0aWYgKCAhaXNYTUwgKSB7XG5cdFx0XHRyZXR1cm4gZWxlbVsgbmFtZSBdID09PSB0cnVlID8gbmFtZS50b0xvd2VyQ2FzZSgpIDpcblx0XHRcdFx0XHQodmFsID0gZWxlbS5nZXRBdHRyaWJ1dGVOb2RlKCBuYW1lICkpICYmIHZhbC5zcGVjaWZpZWQgP1xuXHRcdFx0XHRcdHZhbC52YWx1ZSA6XG5cdFx0XHRcdG51bGw7XG5cdFx0fVxuXHR9KTtcbn1cblxucmV0dXJuIFNpenpsZTtcblxufSkoIHdpbmRvdyApO1xuXG5cblxualF1ZXJ5LmZpbmQgPSBTaXp6bGU7XG5qUXVlcnkuZXhwciA9IFNpenpsZS5zZWxlY3RvcnM7XG5cbi8vIERlcHJlY2F0ZWRcbmpRdWVyeS5leHByWyBcIjpcIiBdID0galF1ZXJ5LmV4cHIucHNldWRvcztcbmpRdWVyeS51bmlxdWVTb3J0ID0galF1ZXJ5LnVuaXF1ZSA9IFNpenpsZS51bmlxdWVTb3J0O1xualF1ZXJ5LnRleHQgPSBTaXp6bGUuZ2V0VGV4dDtcbmpRdWVyeS5pc1hNTERvYyA9IFNpenpsZS5pc1hNTDtcbmpRdWVyeS5jb250YWlucyA9IFNpenpsZS5jb250YWlucztcbmpRdWVyeS5lc2NhcGVTZWxlY3RvciA9IFNpenpsZS5lc2NhcGU7XG5cblxuXG5cbnZhciBkaXIgPSBmdW5jdGlvbiggZWxlbSwgZGlyLCB1bnRpbCApIHtcblx0dmFyIG1hdGNoZWQgPSBbXSxcblx0XHR0cnVuY2F0ZSA9IHVudGlsICE9PSB1bmRlZmluZWQ7XG5cblx0d2hpbGUgKCAoIGVsZW0gPSBlbGVtWyBkaXIgXSApICYmIGVsZW0ubm9kZVR5cGUgIT09IDkgKSB7XG5cdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICkge1xuXHRcdFx0aWYgKCB0cnVuY2F0ZSAmJiBqUXVlcnkoIGVsZW0gKS5pcyggdW50aWwgKSApIHtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRtYXRjaGVkLnB1c2goIGVsZW0gKTtcblx0XHR9XG5cdH1cblx0cmV0dXJuIG1hdGNoZWQ7XG59O1xuXG5cbnZhciBzaWJsaW5ncyA9IGZ1bmN0aW9uKCBuLCBlbGVtICkge1xuXHR2YXIgbWF0Y2hlZCA9IFtdO1xuXG5cdGZvciAoIDsgbjsgbiA9IG4ubmV4dFNpYmxpbmcgKSB7XG5cdFx0aWYgKCBuLm5vZGVUeXBlID09PSAxICYmIG4gIT09IGVsZW0gKSB7XG5cdFx0XHRtYXRjaGVkLnB1c2goIG4gKTtcblx0XHR9XG5cdH1cblxuXHRyZXR1cm4gbWF0Y2hlZDtcbn07XG5cblxudmFyIHJuZWVkc0NvbnRleHQgPSBqUXVlcnkuZXhwci5tYXRjaC5uZWVkc0NvbnRleHQ7XG5cblxuXG5mdW5jdGlvbiBub2RlTmFtZSggZWxlbSwgbmFtZSApIHtcblxuICByZXR1cm4gZWxlbS5ub2RlTmFtZSAmJiBlbGVtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09IG5hbWUudG9Mb3dlckNhc2UoKTtcblxufTtcbnZhciByc2luZ2xlVGFnID0gKCAvXjwoW2Etel1bXlxcL1xcMD46XFx4MjBcXHRcXHJcXG5cXGZdKilbXFx4MjBcXHRcXHJcXG5cXGZdKlxcLz8+KD86PFxcL1xcMT58KSQvaSApO1xuXG5cblxudmFyIHJpc1NpbXBsZSA9IC9eLlteOiNcXFtcXC4sXSokLztcblxuLy8gSW1wbGVtZW50IHRoZSBpZGVudGljYWwgZnVuY3Rpb25hbGl0eSBmb3IgZmlsdGVyIGFuZCBub3RcbmZ1bmN0aW9uIHdpbm5vdyggZWxlbWVudHMsIHF1YWxpZmllciwgbm90ICkge1xuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBxdWFsaWZpZXIgKSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSwgaSApIHtcblx0XHRcdHJldHVybiAhIXF1YWxpZmllci5jYWxsKCBlbGVtLCBpLCBlbGVtICkgIT09IG5vdDtcblx0XHR9ICk7XG5cdH1cblxuXHQvLyBTaW5nbGUgZWxlbWVudFxuXHRpZiAoIHF1YWxpZmllci5ub2RlVHlwZSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGVsZW0gPT09IHF1YWxpZmllciApICE9PSBub3Q7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gQXJyYXlsaWtlIG9mIGVsZW1lbnRzIChqUXVlcnksIGFyZ3VtZW50cywgQXJyYXkpXG5cdGlmICggdHlwZW9mIHF1YWxpZmllciAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdyZXAoIGVsZW1lbnRzLCBmdW5jdGlvbiggZWxlbSApIHtcblx0XHRcdHJldHVybiAoIGluZGV4T2YuY2FsbCggcXVhbGlmaWVyLCBlbGVtICkgPiAtMSApICE9PSBub3Q7XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gU2ltcGxlIHNlbGVjdG9yIHRoYXQgY2FuIGJlIGZpbHRlcmVkIGRpcmVjdGx5LCByZW1vdmluZyBub24tRWxlbWVudHNcblx0aWYgKCByaXNTaW1wbGUudGVzdCggcXVhbGlmaWVyICkgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5maWx0ZXIoIHF1YWxpZmllciwgZWxlbWVudHMsIG5vdCApO1xuXHR9XG5cblx0Ly8gQ29tcGxleCBzZWxlY3RvciwgY29tcGFyZSB0aGUgdHdvIHNldHMsIHJlbW92aW5nIG5vbi1FbGVtZW50c1xuXHRxdWFsaWZpZXIgPSBqUXVlcnkuZmlsdGVyKCBxdWFsaWZpZXIsIGVsZW1lbnRzICk7XG5cdHJldHVybiBqUXVlcnkuZ3JlcCggZWxlbWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiAoIGluZGV4T2YuY2FsbCggcXVhbGlmaWVyLCBlbGVtICkgPiAtMSApICE9PSBub3QgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMTtcblx0fSApO1xufVxuXG5qUXVlcnkuZmlsdGVyID0gZnVuY3Rpb24oIGV4cHIsIGVsZW1zLCBub3QgKSB7XG5cdHZhciBlbGVtID0gZWxlbXNbIDAgXTtcblxuXHRpZiAoIG5vdCApIHtcblx0XHRleHByID0gXCI6bm90KFwiICsgZXhwciArIFwiKVwiO1xuXHR9XG5cblx0aWYgKCBlbGVtcy5sZW5ndGggPT09IDEgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmZpbmQubWF0Y2hlc1NlbGVjdG9yKCBlbGVtLCBleHByICkgPyBbIGVsZW0gXSA6IFtdO1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeS5maW5kLm1hdGNoZXMoIGV4cHIsIGpRdWVyeS5ncmVwKCBlbGVtcywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGVsZW0ubm9kZVR5cGUgPT09IDE7XG5cdH0gKSApO1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRmaW5kOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0dmFyIGksIHJldCxcblx0XHRcdGxlbiA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0c2VsZiA9IHRoaXM7XG5cblx0XHRpZiAoIHR5cGVvZiBzZWxlY3RvciAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggalF1ZXJ5KCBzZWxlY3RvciApLmZpbHRlciggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBqUXVlcnkuY29udGFpbnMoIHNlbGZbIGkgXSwgdGhpcyApICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9ICkgKTtcblx0XHR9XG5cblx0XHRyZXQgPSB0aGlzLnB1c2hTdGFjayggW10gKTtcblxuXHRcdGZvciAoIGkgPSAwOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRqUXVlcnkuZmluZCggc2VsZWN0b3IsIHNlbGZbIGkgXSwgcmV0ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGxlbiA+IDEgPyBqUXVlcnkudW5pcXVlU29ydCggcmV0ICkgOiByZXQ7XG5cdH0sXG5cdGZpbHRlcjogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggd2lubm93KCB0aGlzLCBzZWxlY3RvciB8fCBbXSwgZmFsc2UgKSApO1xuXHR9LFxuXHRub3Q6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIHdpbm5vdyggdGhpcywgc2VsZWN0b3IgfHwgW10sIHRydWUgKSApO1xuXHR9LFxuXHRpczogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiAhIXdpbm5vdyhcblx0XHRcdHRoaXMsXG5cblx0XHRcdC8vIElmIHRoaXMgaXMgYSBwb3NpdGlvbmFsL3JlbGF0aXZlIHNlbGVjdG9yLCBjaGVjayBtZW1iZXJzaGlwIGluIHRoZSByZXR1cm5lZCBzZXRcblx0XHRcdC8vIHNvICQoXCJwOmZpcnN0XCIpLmlzKFwicDpsYXN0XCIpIHdvbid0IHJldHVybiB0cnVlIGZvciBhIGRvYyB3aXRoIHR3byBcInBcIi5cblx0XHRcdHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiAmJiBybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9yICkgP1xuXHRcdFx0XHRqUXVlcnkoIHNlbGVjdG9yICkgOlxuXHRcdFx0XHRzZWxlY3RvciB8fCBbXSxcblx0XHRcdGZhbHNlXG5cdFx0KS5sZW5ndGg7XG5cdH1cbn0gKTtcblxuXG4vLyBJbml0aWFsaXplIGEgalF1ZXJ5IG9iamVjdFxuXG5cbi8vIEEgY2VudHJhbCByZWZlcmVuY2UgdG8gdGhlIHJvb3QgalF1ZXJ5KGRvY3VtZW50KVxudmFyIHJvb3RqUXVlcnksXG5cblx0Ly8gQSBzaW1wbGUgd2F5IHRvIGNoZWNrIGZvciBIVE1MIHN0cmluZ3Ncblx0Ly8gUHJpb3JpdGl6ZSAjaWQgb3ZlciA8dGFnPiB0byBhdm9pZCBYU1MgdmlhIGxvY2F0aW9uLmhhc2ggKCM5NTIxKVxuXHQvLyBTdHJpY3QgSFRNTCByZWNvZ25pdGlvbiAoIzExMjkwOiBtdXN0IHN0YXJ0IHdpdGggPClcblx0Ly8gU2hvcnRjdXQgc2ltcGxlICNpZCBjYXNlIGZvciBzcGVlZFxuXHRycXVpY2tFeHByID0gL14oPzpcXHMqKDxbXFx3XFxXXSs+KVtePl0qfCMoW1xcdy1dKykpJC8sXG5cblx0aW5pdCA9IGpRdWVyeS5mbi5pbml0ID0gZnVuY3Rpb24oIHNlbGVjdG9yLCBjb250ZXh0LCByb290ICkge1xuXHRcdHZhciBtYXRjaCwgZWxlbTtcblxuXHRcdC8vIEhBTkRMRTogJChcIlwiKSwgJChudWxsKSwgJCh1bmRlZmluZWQpLCAkKGZhbHNlKVxuXHRcdGlmICggIXNlbGVjdG9yICkge1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXG5cdFx0Ly8gTWV0aG9kIGluaXQoKSBhY2NlcHRzIGFuIGFsdGVybmF0ZSByb290alF1ZXJ5XG5cdFx0Ly8gc28gbWlncmF0ZSBjYW4gc3VwcG9ydCBqUXVlcnkuc3ViIChnaC0yMTAxKVxuXHRcdHJvb3QgPSByb290IHx8IHJvb3RqUXVlcnk7XG5cblx0XHQvLyBIYW5kbGUgSFRNTCBzdHJpbmdzXG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRpZiAoIHNlbGVjdG9yWyAwIF0gPT09IFwiPFwiICYmXG5cdFx0XHRcdHNlbGVjdG9yWyBzZWxlY3Rvci5sZW5ndGggLSAxIF0gPT09IFwiPlwiICYmXG5cdFx0XHRcdHNlbGVjdG9yLmxlbmd0aCA+PSAzICkge1xuXG5cdFx0XHRcdC8vIEFzc3VtZSB0aGF0IHN0cmluZ3MgdGhhdCBzdGFydCBhbmQgZW5kIHdpdGggPD4gYXJlIEhUTUwgYW5kIHNraXAgdGhlIHJlZ2V4IGNoZWNrXG5cdFx0XHRcdG1hdGNoID0gWyBudWxsLCBzZWxlY3RvciwgbnVsbCBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRtYXRjaCA9IHJxdWlja0V4cHIuZXhlYyggc2VsZWN0b3IgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTWF0Y2ggaHRtbCBvciBtYWtlIHN1cmUgbm8gY29udGV4dCBpcyBzcGVjaWZpZWQgZm9yICNpZFxuXHRcdFx0aWYgKCBtYXRjaCAmJiAoIG1hdGNoWyAxIF0gfHwgIWNvbnRleHQgKSApIHtcblxuXHRcdFx0XHQvLyBIQU5ETEU6ICQoaHRtbCkgLT4gJChhcnJheSlcblx0XHRcdFx0aWYgKCBtYXRjaFsgMSBdICkge1xuXHRcdFx0XHRcdGNvbnRleHQgPSBjb250ZXh0IGluc3RhbmNlb2YgalF1ZXJ5ID8gY29udGV4dFsgMCBdIDogY29udGV4dDtcblxuXHRcdFx0XHRcdC8vIE9wdGlvbiB0byBydW4gc2NyaXB0cyBpcyB0cnVlIGZvciBiYWNrLWNvbXBhdFxuXHRcdFx0XHRcdC8vIEludGVudGlvbmFsbHkgbGV0IHRoZSBlcnJvciBiZSB0aHJvd24gaWYgcGFyc2VIVE1MIGlzIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCB0aGlzLCBqUXVlcnkucGFyc2VIVE1MKFxuXHRcdFx0XHRcdFx0bWF0Y2hbIDEgXSxcblx0XHRcdFx0XHRcdGNvbnRleHQgJiYgY29udGV4dC5ub2RlVHlwZSA/IGNvbnRleHQub3duZXJEb2N1bWVudCB8fCBjb250ZXh0IDogZG9jdW1lbnQsXG5cdFx0XHRcdFx0XHR0cnVlXG5cdFx0XHRcdFx0KSApO1xuXG5cdFx0XHRcdFx0Ly8gSEFORExFOiAkKGh0bWwsIHByb3BzKVxuXHRcdFx0XHRcdGlmICggcnNpbmdsZVRhZy50ZXN0KCBtYXRjaFsgMSBdICkgJiYgalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGNvbnRleHQgKSApIHtcblx0XHRcdFx0XHRcdGZvciAoIG1hdGNoIGluIGNvbnRleHQgKSB7XG5cblx0XHRcdFx0XHRcdFx0Ly8gUHJvcGVydGllcyBvZiBjb250ZXh0IGFyZSBjYWxsZWQgYXMgbWV0aG9kcyBpZiBwb3NzaWJsZVxuXHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB0aGlzWyBtYXRjaCBdICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0dGhpc1sgbWF0Y2ggXSggY29udGV4dFsgbWF0Y2ggXSApO1xuXG5cdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBvdGhlcndpc2Ugc2V0IGFzIGF0dHJpYnV0ZXNcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR0aGlzLmF0dHIoIG1hdGNoLCBjb250ZXh0WyBtYXRjaCBdICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblxuXHRcdFx0XHQvLyBIQU5ETEU6ICQoI2lkKVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGVsZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCggbWF0Y2hbIDIgXSApO1xuXG5cdFx0XHRcdFx0aWYgKCBlbGVtICkge1xuXG5cdFx0XHRcdFx0XHQvLyBJbmplY3QgdGhlIGVsZW1lbnQgZGlyZWN0bHkgaW50byB0aGUgalF1ZXJ5IG9iamVjdFxuXHRcdFx0XHRcdFx0dGhpc1sgMCBdID0gZWxlbTtcblx0XHRcdFx0XHRcdHRoaXMubGVuZ3RoID0gMTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH1cblxuXHRcdFx0Ly8gSEFORExFOiAkKGV4cHIsICQoLi4uKSlcblx0XHRcdH0gZWxzZSBpZiAoICFjb250ZXh0IHx8IGNvbnRleHQuanF1ZXJ5ICkge1xuXHRcdFx0XHRyZXR1cm4gKCBjb250ZXh0IHx8IHJvb3QgKS5maW5kKCBzZWxlY3RvciApO1xuXG5cdFx0XHQvLyBIQU5ETEU6ICQoZXhwciwgY29udGV4dClcblx0XHRcdC8vICh3aGljaCBpcyBqdXN0IGVxdWl2YWxlbnQgdG86ICQoY29udGV4dCkuZmluZChleHByKVxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIHRoaXMuY29uc3RydWN0b3IoIGNvbnRleHQgKS5maW5kKCBzZWxlY3RvciApO1xuXHRcdFx0fVxuXG5cdFx0Ly8gSEFORExFOiAkKERPTUVsZW1lbnQpXG5cdFx0fSBlbHNlIGlmICggc2VsZWN0b3Iubm9kZVR5cGUgKSB7XG5cdFx0XHR0aGlzWyAwIF0gPSBzZWxlY3Rvcjtcblx0XHRcdHRoaXMubGVuZ3RoID0gMTtcblx0XHRcdHJldHVybiB0aGlzO1xuXG5cdFx0Ly8gSEFORExFOiAkKGZ1bmN0aW9uKVxuXHRcdC8vIFNob3J0Y3V0IGZvciBkb2N1bWVudCByZWFkeVxuXHRcdH0gZWxzZSBpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBzZWxlY3RvciApICkge1xuXHRcdFx0cmV0dXJuIHJvb3QucmVhZHkgIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdHJvb3QucmVhZHkoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIEV4ZWN1dGUgaW1tZWRpYXRlbHkgaWYgcmVhZHkgaXMgbm90IHByZXNlbnRcblx0XHRcdFx0c2VsZWN0b3IoIGpRdWVyeSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBqUXVlcnkubWFrZUFycmF5KCBzZWxlY3RvciwgdGhpcyApO1xuXHR9O1xuXG4vLyBHaXZlIHRoZSBpbml0IGZ1bmN0aW9uIHRoZSBqUXVlcnkgcHJvdG90eXBlIGZvciBsYXRlciBpbnN0YW50aWF0aW9uXG5pbml0LnByb3RvdHlwZSA9IGpRdWVyeS5mbjtcblxuLy8gSW5pdGlhbGl6ZSBjZW50cmFsIHJlZmVyZW5jZVxucm9vdGpRdWVyeSA9IGpRdWVyeSggZG9jdW1lbnQgKTtcblxuXG52YXIgcnBhcmVudHNwcmV2ID0gL14oPzpwYXJlbnRzfHByZXYoPzpVbnRpbHxBbGwpKS8sXG5cblx0Ly8gTWV0aG9kcyBndWFyYW50ZWVkIHRvIHByb2R1Y2UgYSB1bmlxdWUgc2V0IHdoZW4gc3RhcnRpbmcgZnJvbSBhIHVuaXF1ZSBzZXRcblx0Z3VhcmFudGVlZFVuaXF1ZSA9IHtcblx0XHRjaGlsZHJlbjogdHJ1ZSxcblx0XHRjb250ZW50czogdHJ1ZSxcblx0XHRuZXh0OiB0cnVlLFxuXHRcdHByZXY6IHRydWVcblx0fTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRoYXM6IGZ1bmN0aW9uKCB0YXJnZXQgKSB7XG5cdFx0dmFyIHRhcmdldHMgPSBqUXVlcnkoIHRhcmdldCwgdGhpcyApLFxuXHRcdFx0bCA9IHRhcmdldHMubGVuZ3RoO1xuXG5cdFx0cmV0dXJuIHRoaXMuZmlsdGVyKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpID0gMDtcblx0XHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBqUXVlcnkuY29udGFpbnMoIHRoaXMsIHRhcmdldHNbIGkgXSApICkge1xuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9LFxuXG5cdGNsb3Nlc3Q6IGZ1bmN0aW9uKCBzZWxlY3RvcnMsIGNvbnRleHQgKSB7XG5cdFx0dmFyIGN1cixcblx0XHRcdGkgPSAwLFxuXHRcdFx0bCA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0bWF0Y2hlZCA9IFtdLFxuXHRcdFx0dGFyZ2V0cyA9IHR5cGVvZiBzZWxlY3RvcnMgIT09IFwic3RyaW5nXCIgJiYgalF1ZXJ5KCBzZWxlY3RvcnMgKTtcblxuXHRcdC8vIFBvc2l0aW9uYWwgc2VsZWN0b3JzIG5ldmVyIG1hdGNoLCBzaW5jZSB0aGVyZSdzIG5vIF9zZWxlY3Rpb25fIGNvbnRleHRcblx0XHRpZiAoICFybmVlZHNDb250ZXh0LnRlc3QoIHNlbGVjdG9ycyApICkge1xuXHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRmb3IgKCBjdXIgPSB0aGlzWyBpIF07IGN1ciAmJiBjdXIgIT09IGNvbnRleHQ7IGN1ciA9IGN1ci5wYXJlbnROb2RlICkge1xuXG5cdFx0XHRcdFx0Ly8gQWx3YXlzIHNraXAgZG9jdW1lbnQgZnJhZ21lbnRzXG5cdFx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPCAxMSAmJiAoIHRhcmdldHMgP1xuXHRcdFx0XHRcdFx0dGFyZ2V0cy5pbmRleCggY3VyICkgPiAtMSA6XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IHBhc3Mgbm9uLWVsZW1lbnRzIHRvIFNpenpsZVxuXHRcdFx0XHRcdFx0Y3VyLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kLm1hdGNoZXNTZWxlY3RvciggY3VyLCBzZWxlY3RvcnMgKSApICkge1xuXG5cdFx0XHRcdFx0XHRtYXRjaGVkLnB1c2goIGN1ciApO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMucHVzaFN0YWNrKCBtYXRjaGVkLmxlbmd0aCA+IDEgPyBqUXVlcnkudW5pcXVlU29ydCggbWF0Y2hlZCApIDogbWF0Y2hlZCApO1xuXHR9LFxuXG5cdC8vIERldGVybWluZSB0aGUgcG9zaXRpb24gb2YgYW4gZWxlbWVudCB3aXRoaW4gdGhlIHNldFxuXHRpbmRleDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHQvLyBObyBhcmd1bWVudCwgcmV0dXJuIGluZGV4IGluIHBhcmVudFxuXHRcdGlmICggIWVsZW0gKSB7XG5cdFx0XHRyZXR1cm4gKCB0aGlzWyAwIF0gJiYgdGhpc1sgMCBdLnBhcmVudE5vZGUgKSA/IHRoaXMuZmlyc3QoKS5wcmV2QWxsKCkubGVuZ3RoIDogLTE7XG5cdFx0fVxuXG5cdFx0Ly8gSW5kZXggaW4gc2VsZWN0b3Jcblx0XHRpZiAoIHR5cGVvZiBlbGVtID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIGluZGV4T2YuY2FsbCggalF1ZXJ5KCBlbGVtICksIHRoaXNbIDAgXSApO1xuXHRcdH1cblxuXHRcdC8vIExvY2F0ZSB0aGUgcG9zaXRpb24gb2YgdGhlIGRlc2lyZWQgZWxlbWVudFxuXHRcdHJldHVybiBpbmRleE9mLmNhbGwoIHRoaXMsXG5cblx0XHRcdC8vIElmIGl0IHJlY2VpdmVzIGEgalF1ZXJ5IG9iamVjdCwgdGhlIGZpcnN0IGVsZW1lbnQgaXMgdXNlZFxuXHRcdFx0ZWxlbS5qcXVlcnkgPyBlbGVtWyAwIF0gOiBlbGVtXG5cdFx0KTtcblx0fSxcblxuXHRhZGQ6IGZ1bmN0aW9uKCBzZWxlY3RvciwgY29udGV4dCApIHtcblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soXG5cdFx0XHRqUXVlcnkudW5pcXVlU29ydChcblx0XHRcdFx0alF1ZXJ5Lm1lcmdlKCB0aGlzLmdldCgpLCBqUXVlcnkoIHNlbGVjdG9yLCBjb250ZXh0ICkgKVxuXHRcdFx0KVxuXHRcdCk7XG5cdH0sXG5cblx0YWRkQmFjazogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiB0aGlzLmFkZCggc2VsZWN0b3IgPT0gbnVsbCA/XG5cdFx0XHR0aGlzLnByZXZPYmplY3QgOiB0aGlzLnByZXZPYmplY3QuZmlsdGVyKCBzZWxlY3RvciApXG5cdFx0KTtcblx0fVxufSApO1xuXG5mdW5jdGlvbiBzaWJsaW5nKCBjdXIsIGRpciApIHtcblx0d2hpbGUgKCAoIGN1ciA9IGN1clsgZGlyIF0gKSAmJiBjdXIubm9kZVR5cGUgIT09IDEgKSB7fVxuXHRyZXR1cm4gY3VyO1xufVxuXG5qUXVlcnkuZWFjaCgge1xuXHRwYXJlbnQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHZhciBwYXJlbnQgPSBlbGVtLnBhcmVudE5vZGU7XG5cdFx0cmV0dXJuIHBhcmVudCAmJiBwYXJlbnQubm9kZVR5cGUgIT09IDExID8gcGFyZW50IDogbnVsbDtcblx0fSxcblx0cGFyZW50czogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIgKTtcblx0fSxcblx0cGFyZW50c1VudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJwYXJlbnROb2RlXCIsIHVudGlsICk7XG5cdH0sXG5cdG5leHQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5nKCBlbGVtLCBcIm5leHRTaWJsaW5nXCIgKTtcblx0fSxcblx0cHJldjogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmcoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dEFsbDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJuZXh0U2libGluZ1wiICk7XG5cdH0sXG5cdHByZXZBbGw6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBkaXIoIGVsZW0sIFwicHJldmlvdXNTaWJsaW5nXCIgKTtcblx0fSxcblx0bmV4dFVudGlsOiBmdW5jdGlvbiggZWxlbSwgaSwgdW50aWwgKSB7XG5cdFx0cmV0dXJuIGRpciggZWxlbSwgXCJuZXh0U2libGluZ1wiLCB1bnRpbCApO1xuXHR9LFxuXHRwcmV2VW50aWw6IGZ1bmN0aW9uKCBlbGVtLCBpLCB1bnRpbCApIHtcblx0XHRyZXR1cm4gZGlyKCBlbGVtLCBcInByZXZpb3VzU2libGluZ1wiLCB1bnRpbCApO1xuXHR9LFxuXHRzaWJsaW5nczogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIHNpYmxpbmdzKCAoIGVsZW0ucGFyZW50Tm9kZSB8fCB7fSApLmZpcnN0Q2hpbGQsIGVsZW0gKTtcblx0fSxcblx0Y2hpbGRyZW46IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdHJldHVybiBzaWJsaW5ncyggZWxlbS5maXJzdENoaWxkICk7XG5cdH0sXG5cdGNvbnRlbnRzOiBmdW5jdGlvbiggZWxlbSApIHtcbiAgICAgICAgaWYgKCBub2RlTmFtZSggZWxlbSwgXCJpZnJhbWVcIiApICkge1xuICAgICAgICAgICAgcmV0dXJuIGVsZW0uY29udGVudERvY3VtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3VwcG9ydDogSUUgOSAtIDExIG9ubHksIGlPUyA3IG9ubHksIEFuZHJvaWQgQnJvd3NlciA8PTQuMyBvbmx5XG4gICAgICAgIC8vIFRyZWF0IHRoZSB0ZW1wbGF0ZSBlbGVtZW50IGFzIGEgcmVndWxhciBvbmUgaW4gYnJvd3NlcnMgdGhhdFxuICAgICAgICAvLyBkb24ndCBzdXBwb3J0IGl0LlxuICAgICAgICBpZiAoIG5vZGVOYW1lKCBlbGVtLCBcInRlbXBsYXRlXCIgKSApIHtcbiAgICAgICAgICAgIGVsZW0gPSBlbGVtLmNvbnRlbnQgfHwgZWxlbTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBqUXVlcnkubWVyZ2UoIFtdLCBlbGVtLmNoaWxkTm9kZXMgKTtcblx0fVxufSwgZnVuY3Rpb24oIG5hbWUsIGZuICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCB1bnRpbCwgc2VsZWN0b3IgKSB7XG5cdFx0dmFyIG1hdGNoZWQgPSBqUXVlcnkubWFwKCB0aGlzLCBmbiwgdW50aWwgKTtcblxuXHRcdGlmICggbmFtZS5zbGljZSggLTUgKSAhPT0gXCJVbnRpbFwiICkge1xuXHRcdFx0c2VsZWN0b3IgPSB1bnRpbDtcblx0XHR9XG5cblx0XHRpZiAoIHNlbGVjdG9yICYmIHR5cGVvZiBzZWxlY3RvciA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG1hdGNoZWQgPSBqUXVlcnkuZmlsdGVyKCBzZWxlY3RvciwgbWF0Y2hlZCApO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5sZW5ndGggPiAxICkge1xuXG5cdFx0XHQvLyBSZW1vdmUgZHVwbGljYXRlc1xuXHRcdFx0aWYgKCAhZ3VhcmFudGVlZFVuaXF1ZVsgbmFtZSBdICkge1xuXHRcdFx0XHRqUXVlcnkudW5pcXVlU29ydCggbWF0Y2hlZCApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZXZlcnNlIG9yZGVyIGZvciBwYXJlbnRzKiBhbmQgcHJldi1kZXJpdmF0aXZlc1xuXHRcdFx0aWYgKCBycGFyZW50c3ByZXYudGVzdCggbmFtZSApICkge1xuXHRcdFx0XHRtYXRjaGVkLnJldmVyc2UoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcy5wdXNoU3RhY2soIG1hdGNoZWQgKTtcblx0fTtcbn0gKTtcbnZhciBybm90aHRtbHdoaXRlID0gKCAvW15cXHgyMFxcdFxcclxcblxcZl0rL2cgKTtcblxuXG5cbi8vIENvbnZlcnQgU3RyaW5nLWZvcm1hdHRlZCBvcHRpb25zIGludG8gT2JqZWN0LWZvcm1hdHRlZCBvbmVzXG5mdW5jdGlvbiBjcmVhdGVPcHRpb25zKCBvcHRpb25zICkge1xuXHR2YXIgb2JqZWN0ID0ge307XG5cdGpRdWVyeS5lYWNoKCBvcHRpb25zLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW10sIGZ1bmN0aW9uKCBfLCBmbGFnICkge1xuXHRcdG9iamVjdFsgZmxhZyBdID0gdHJ1ZTtcblx0fSApO1xuXHRyZXR1cm4gb2JqZWN0O1xufVxuXG4vKlxuICogQ3JlYXRlIGEgY2FsbGJhY2sgbGlzdCB1c2luZyB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6XG4gKlxuICpcdG9wdGlvbnM6IGFuIG9wdGlvbmFsIGxpc3Qgb2Ygc3BhY2Utc2VwYXJhdGVkIG9wdGlvbnMgdGhhdCB3aWxsIGNoYW5nZSBob3dcbiAqXHRcdFx0dGhlIGNhbGxiYWNrIGxpc3QgYmVoYXZlcyBvciBhIG1vcmUgdHJhZGl0aW9uYWwgb3B0aW9uIG9iamVjdFxuICpcbiAqIEJ5IGRlZmF1bHQgYSBjYWxsYmFjayBsaXN0IHdpbGwgYWN0IGxpa2UgYW4gZXZlbnQgY2FsbGJhY2sgbGlzdCBhbmQgY2FuIGJlXG4gKiBcImZpcmVkXCIgbXVsdGlwbGUgdGltZXMuXG4gKlxuICogUG9zc2libGUgb3B0aW9uczpcbiAqXG4gKlx0b25jZTpcdFx0XHR3aWxsIGVuc3VyZSB0aGUgY2FsbGJhY2sgbGlzdCBjYW4gb25seSBiZSBmaXJlZCBvbmNlIChsaWtlIGEgRGVmZXJyZWQpXG4gKlxuICpcdG1lbW9yeTpcdFx0XHR3aWxsIGtlZXAgdHJhY2sgb2YgcHJldmlvdXMgdmFsdWVzIGFuZCB3aWxsIGNhbGwgYW55IGNhbGxiYWNrIGFkZGVkXG4gKlx0XHRcdFx0XHRhZnRlciB0aGUgbGlzdCBoYXMgYmVlbiBmaXJlZCByaWdodCBhd2F5IHdpdGggdGhlIGxhdGVzdCBcIm1lbW9yaXplZFwiXG4gKlx0XHRcdFx0XHR2YWx1ZXMgKGxpa2UgYSBEZWZlcnJlZClcbiAqXG4gKlx0dW5pcXVlOlx0XHRcdHdpbGwgZW5zdXJlIGEgY2FsbGJhY2sgY2FuIG9ubHkgYmUgYWRkZWQgb25jZSAobm8gZHVwbGljYXRlIGluIHRoZSBsaXN0KVxuICpcbiAqXHRzdG9wT25GYWxzZTpcdGludGVycnVwdCBjYWxsaW5ncyB3aGVuIGEgY2FsbGJhY2sgcmV0dXJucyBmYWxzZVxuICpcbiAqL1xualF1ZXJ5LkNhbGxiYWNrcyA9IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdC8vIENvbnZlcnQgb3B0aW9ucyBmcm9tIFN0cmluZy1mb3JtYXR0ZWQgdG8gT2JqZWN0LWZvcm1hdHRlZCBpZiBuZWVkZWRcblx0Ly8gKHdlIGNoZWNrIGluIGNhY2hlIGZpcnN0KVxuXHRvcHRpb25zID0gdHlwZW9mIG9wdGlvbnMgPT09IFwic3RyaW5nXCIgP1xuXHRcdGNyZWF0ZU9wdGlvbnMoIG9wdGlvbnMgKSA6XG5cdFx0alF1ZXJ5LmV4dGVuZCgge30sIG9wdGlvbnMgKTtcblxuXHR2YXIgLy8gRmxhZyB0byBrbm93IGlmIGxpc3QgaXMgY3VycmVudGx5IGZpcmluZ1xuXHRcdGZpcmluZyxcblxuXHRcdC8vIExhc3QgZmlyZSB2YWx1ZSBmb3Igbm9uLWZvcmdldHRhYmxlIGxpc3RzXG5cdFx0bWVtb3J5LFxuXG5cdFx0Ly8gRmxhZyB0byBrbm93IGlmIGxpc3Qgd2FzIGFscmVhZHkgZmlyZWRcblx0XHRmaXJlZCxcblxuXHRcdC8vIEZsYWcgdG8gcHJldmVudCBmaXJpbmdcblx0XHRsb2NrZWQsXG5cblx0XHQvLyBBY3R1YWwgY2FsbGJhY2sgbGlzdFxuXHRcdGxpc3QgPSBbXSxcblxuXHRcdC8vIFF1ZXVlIG9mIGV4ZWN1dGlvbiBkYXRhIGZvciByZXBlYXRhYmxlIGxpc3RzXG5cdFx0cXVldWUgPSBbXSxcblxuXHRcdC8vIEluZGV4IG9mIGN1cnJlbnRseSBmaXJpbmcgY2FsbGJhY2sgKG1vZGlmaWVkIGJ5IGFkZC9yZW1vdmUgYXMgbmVlZGVkKVxuXHRcdGZpcmluZ0luZGV4ID0gLTEsXG5cblx0XHQvLyBGaXJlIGNhbGxiYWNrc1xuXHRcdGZpcmUgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRW5mb3JjZSBzaW5nbGUtZmlyaW5nXG5cdFx0XHRsb2NrZWQgPSBsb2NrZWQgfHwgb3B0aW9ucy5vbmNlO1xuXG5cdFx0XHQvLyBFeGVjdXRlIGNhbGxiYWNrcyBmb3IgYWxsIHBlbmRpbmcgZXhlY3V0aW9ucyxcblx0XHRcdC8vIHJlc3BlY3RpbmcgZmlyaW5nSW5kZXggb3ZlcnJpZGVzIGFuZCBydW50aW1lIGNoYW5nZXNcblx0XHRcdGZpcmVkID0gZmlyaW5nID0gdHJ1ZTtcblx0XHRcdGZvciAoIDsgcXVldWUubGVuZ3RoOyBmaXJpbmdJbmRleCA9IC0xICkge1xuXHRcdFx0XHRtZW1vcnkgPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0XHR3aGlsZSAoICsrZmlyaW5nSW5kZXggPCBsaXN0Lmxlbmd0aCApIHtcblxuXHRcdFx0XHRcdC8vIFJ1biBjYWxsYmFjayBhbmQgY2hlY2sgZm9yIGVhcmx5IHRlcm1pbmF0aW9uXG5cdFx0XHRcdFx0aWYgKCBsaXN0WyBmaXJpbmdJbmRleCBdLmFwcGx5KCBtZW1vcnlbIDAgXSwgbWVtb3J5WyAxIF0gKSA9PT0gZmFsc2UgJiZcblx0XHRcdFx0XHRcdG9wdGlvbnMuc3RvcE9uRmFsc2UgKSB7XG5cblx0XHRcdFx0XHRcdC8vIEp1bXAgdG8gZW5kIGFuZCBmb3JnZXQgdGhlIGRhdGEgc28gLmFkZCBkb2Vzbid0IHJlLWZpcmVcblx0XHRcdFx0XHRcdGZpcmluZ0luZGV4ID0gbGlzdC5sZW5ndGg7XG5cdFx0XHRcdFx0XHRtZW1vcnkgPSBmYWxzZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gRm9yZ2V0IHRoZSBkYXRhIGlmIHdlJ3JlIGRvbmUgd2l0aCBpdFxuXHRcdFx0aWYgKCAhb3B0aW9ucy5tZW1vcnkgKSB7XG5cdFx0XHRcdG1lbW9yeSA9IGZhbHNlO1xuXHRcdFx0fVxuXG5cdFx0XHRmaXJpbmcgPSBmYWxzZTtcblxuXHRcdFx0Ly8gQ2xlYW4gdXAgaWYgd2UncmUgZG9uZSBmaXJpbmcgZm9yIGdvb2Rcblx0XHRcdGlmICggbG9ja2VkICkge1xuXG5cdFx0XHRcdC8vIEtlZXAgYW4gZW1wdHkgbGlzdCBpZiB3ZSBoYXZlIGRhdGEgZm9yIGZ1dHVyZSBhZGQgY2FsbHNcblx0XHRcdFx0aWYgKCBtZW1vcnkgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IFtdO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSwgdGhpcyBvYmplY3QgaXMgc3BlbnRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRsaXN0ID0gXCJcIjtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHQvLyBBY3R1YWwgQ2FsbGJhY2tzIG9iamVjdFxuXHRcdHNlbGYgPSB7XG5cblx0XHRcdC8vIEFkZCBhIGNhbGxiYWNrIG9yIGEgY29sbGVjdGlvbiBvZiBjYWxsYmFja3MgdG8gdGhlIGxpc3Rcblx0XHRcdGFkZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGlzdCApIHtcblxuXHRcdFx0XHRcdC8vIElmIHdlIGhhdmUgbWVtb3J5IGZyb20gYSBwYXN0IHJ1biwgd2Ugc2hvdWxkIGZpcmUgYWZ0ZXIgYWRkaW5nXG5cdFx0XHRcdFx0aWYgKCBtZW1vcnkgJiYgIWZpcmluZyApIHtcblx0XHRcdFx0XHRcdGZpcmluZ0luZGV4ID0gbGlzdC5sZW5ndGggLSAxO1xuXHRcdFx0XHRcdFx0cXVldWUucHVzaCggbWVtb3J5ICk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0KCBmdW5jdGlvbiBhZGQoIGFyZ3MgKSB7XG5cdFx0XHRcdFx0XHRqUXVlcnkuZWFjaCggYXJncywgZnVuY3Rpb24oIF8sIGFyZyApIHtcblx0XHRcdFx0XHRcdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggYXJnICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCAhb3B0aW9ucy51bmlxdWUgfHwgIXNlbGYuaGFzKCBhcmcgKSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGxpc3QucHVzaCggYXJnICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9IGVsc2UgaWYgKCBhcmcgJiYgYXJnLmxlbmd0aCAmJiBqUXVlcnkudHlwZSggYXJnICkgIT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBJbnNwZWN0IHJlY3Vyc2l2ZWx5XG5cdFx0XHRcdFx0XHRcdFx0YWRkKCBhcmcgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdH0gKSggYXJndW1lbnRzICk7XG5cblx0XHRcdFx0XHRpZiAoIG1lbW9yeSAmJiAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIFJlbW92ZSBhIGNhbGxiYWNrIGZyb20gdGhlIGxpc3Rcblx0XHRcdHJlbW92ZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5lYWNoKCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBfLCBhcmcgKSB7XG5cdFx0XHRcdFx0dmFyIGluZGV4O1xuXHRcdFx0XHRcdHdoaWxlICggKCBpbmRleCA9IGpRdWVyeS5pbkFycmF5KCBhcmcsIGxpc3QsIGluZGV4ICkgKSA+IC0xICkge1xuXHRcdFx0XHRcdFx0bGlzdC5zcGxpY2UoIGluZGV4LCAxICk7XG5cblx0XHRcdFx0XHRcdC8vIEhhbmRsZSBmaXJpbmcgaW5kZXhlc1xuXHRcdFx0XHRcdFx0aWYgKCBpbmRleCA8PSBmaXJpbmdJbmRleCApIHtcblx0XHRcdFx0XHRcdFx0ZmlyaW5nSW5kZXgtLTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBDaGVjayBpZiBhIGdpdmVuIGNhbGxiYWNrIGlzIGluIHRoZSBsaXN0LlxuXHRcdFx0Ly8gSWYgbm8gYXJndW1lbnQgaXMgZ2l2ZW4sIHJldHVybiB3aGV0aGVyIG9yIG5vdCBsaXN0IGhhcyBjYWxsYmFja3MgYXR0YWNoZWQuXG5cdFx0XHRoYXM6IGZ1bmN0aW9uKCBmbiApIHtcblx0XHRcdFx0cmV0dXJuIGZuID9cblx0XHRcdFx0XHRqUXVlcnkuaW5BcnJheSggZm4sIGxpc3QgKSA+IC0xIDpcblx0XHRcdFx0XHRsaXN0Lmxlbmd0aCA+IDA7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBSZW1vdmUgYWxsIGNhbGxiYWNrcyBmcm9tIHRoZSBsaXN0XG5cdFx0XHRlbXB0eTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggbGlzdCApIHtcblx0XHRcdFx0XHRsaXN0ID0gW107XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBEaXNhYmxlIC5maXJlIGFuZCAuYWRkXG5cdFx0XHQvLyBBYm9ydCBhbnkgY3VycmVudC9wZW5kaW5nIGV4ZWN1dGlvbnNcblx0XHRcdC8vIENsZWFyIGFsbCBjYWxsYmFja3MgYW5kIHZhbHVlc1xuXHRcdFx0ZGlzYWJsZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGxvY2tlZCA9IHF1ZXVlID0gW107XG5cdFx0XHRcdGxpc3QgPSBtZW1vcnkgPSBcIlwiO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cdFx0XHRkaXNhYmxlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhbGlzdDtcblx0XHRcdH0sXG5cblx0XHRcdC8vIERpc2FibGUgLmZpcmVcblx0XHRcdC8vIEFsc28gZGlzYWJsZSAuYWRkIHVubGVzcyB3ZSBoYXZlIG1lbW9yeSAoc2luY2UgaXQgd291bGQgaGF2ZSBubyBlZmZlY3QpXG5cdFx0XHQvLyBBYm9ydCBhbnkgcGVuZGluZyBleGVjdXRpb25zXG5cdFx0XHRsb2NrOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0bG9ja2VkID0gcXVldWUgPSBbXTtcblx0XHRcdFx0aWYgKCAhbWVtb3J5ICYmICFmaXJpbmcgKSB7XG5cdFx0XHRcdFx0bGlzdCA9IG1lbW9yeSA9IFwiXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9LFxuXHRcdFx0bG9ja2VkOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0cmV0dXJuICEhbG9ja2VkO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gQ2FsbCBhbGwgY2FsbGJhY2tzIHdpdGggdGhlIGdpdmVuIGNvbnRleHQgYW5kIGFyZ3VtZW50c1xuXHRcdFx0ZmlyZVdpdGg6IGZ1bmN0aW9uKCBjb250ZXh0LCBhcmdzICkge1xuXHRcdFx0XHRpZiAoICFsb2NrZWQgKSB7XG5cdFx0XHRcdFx0YXJncyA9IGFyZ3MgfHwgW107XG5cdFx0XHRcdFx0YXJncyA9IFsgY29udGV4dCwgYXJncy5zbGljZSA/IGFyZ3Muc2xpY2UoKSA6IGFyZ3MgXTtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBhcmdzICk7XG5cdFx0XHRcdFx0aWYgKCAhZmlyaW5nICkge1xuXHRcdFx0XHRcdFx0ZmlyZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH0sXG5cblx0XHRcdC8vIENhbGwgYWxsIHRoZSBjYWxsYmFja3Mgd2l0aCB0aGUgZ2l2ZW4gYXJndW1lbnRzXG5cdFx0XHRmaXJlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0c2VsZi5maXJlV2l0aCggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fSxcblxuXHRcdFx0Ly8gVG8ga25vdyBpZiB0aGUgY2FsbGJhY2tzIGhhdmUgYWxyZWFkeSBiZWVuIGNhbGxlZCBhdCBsZWFzdCBvbmNlXG5cdFx0XHRmaXJlZDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiAhIWZpcmVkO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0cmV0dXJuIHNlbGY7XG59O1xuXG5cbmZ1bmN0aW9uIElkZW50aXR5KCB2ICkge1xuXHRyZXR1cm4gdjtcbn1cbmZ1bmN0aW9uIFRocm93ZXIoIGV4ICkge1xuXHR0aHJvdyBleDtcbn1cblxuZnVuY3Rpb24gYWRvcHRWYWx1ZSggdmFsdWUsIHJlc29sdmUsIHJlamVjdCwgbm9WYWx1ZSApIHtcblx0dmFyIG1ldGhvZDtcblxuXHR0cnkge1xuXG5cdFx0Ly8gQ2hlY2sgZm9yIHByb21pc2UgYXNwZWN0IGZpcnN0IHRvIHByaXZpbGVnZSBzeW5jaHJvbm91cyBiZWhhdmlvclxuXHRcdGlmICggdmFsdWUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oICggbWV0aG9kID0gdmFsdWUucHJvbWlzZSApICkgKSB7XG5cdFx0XHRtZXRob2QuY2FsbCggdmFsdWUgKS5kb25lKCByZXNvbHZlICkuZmFpbCggcmVqZWN0ICk7XG5cblx0XHQvLyBPdGhlciB0aGVuYWJsZXNcblx0XHR9IGVsc2UgaWYgKCB2YWx1ZSAmJiBqUXVlcnkuaXNGdW5jdGlvbiggKCBtZXRob2QgPSB2YWx1ZS50aGVuICkgKSApIHtcblx0XHRcdG1ldGhvZC5jYWxsKCB2YWx1ZSwgcmVzb2x2ZSwgcmVqZWN0ICk7XG5cblx0XHQvLyBPdGhlciBub24tdGhlbmFibGVzXG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gQ29udHJvbCBgcmVzb2x2ZWAgYXJndW1lbnRzIGJ5IGxldHRpbmcgQXJyYXkjc2xpY2UgY2FzdCBib29sZWFuIGBub1ZhbHVlYCB0byBpbnRlZ2VyOlxuXHRcdFx0Ly8gKiBmYWxzZTogWyB2YWx1ZSBdLnNsaWNlKCAwICkgPT4gcmVzb2x2ZSggdmFsdWUgKVxuXHRcdFx0Ly8gKiB0cnVlOiBbIHZhbHVlIF0uc2xpY2UoIDEgKSA9PiByZXNvbHZlKClcblx0XHRcdHJlc29sdmUuYXBwbHkoIHVuZGVmaW5lZCwgWyB2YWx1ZSBdLnNsaWNlKCBub1ZhbHVlICkgKTtcblx0XHR9XG5cblx0Ly8gRm9yIFByb21pc2VzL0ErLCBjb252ZXJ0IGV4Y2VwdGlvbnMgaW50byByZWplY3Rpb25zXG5cdC8vIFNpbmNlIGpRdWVyeS53aGVuIGRvZXNuJ3QgdW53cmFwIHRoZW5hYmxlcywgd2UgY2FuIHNraXAgdGhlIGV4dHJhIGNoZWNrcyBhcHBlYXJpbmcgaW5cblx0Ly8gRGVmZXJyZWQjdGhlbiB0byBjb25kaXRpb25hbGx5IHN1cHByZXNzIHJlamVjdGlvbi5cblx0fSBjYXRjaCAoIHZhbHVlICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgb25seVxuXHRcdC8vIFN0cmljdCBtb2RlIGZ1bmN0aW9ucyBpbnZva2VkIHdpdGhvdXQgLmNhbGwvLmFwcGx5IGdldCBnbG9iYWwtb2JqZWN0IGNvbnRleHRcblx0XHRyZWplY3QuYXBwbHkoIHVuZGVmaW5lZCwgWyB2YWx1ZSBdICk7XG5cdH1cbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdERlZmVycmVkOiBmdW5jdGlvbiggZnVuYyApIHtcblx0XHR2YXIgdHVwbGVzID0gW1xuXG5cdFx0XHRcdC8vIGFjdGlvbiwgYWRkIGxpc3RlbmVyLCBjYWxsYmFja3MsXG5cdFx0XHRcdC8vIC4uLiAudGhlbiBoYW5kbGVycywgYXJndW1lbnQgaW5kZXgsIFtmaW5hbCBzdGF0ZV1cblx0XHRcdFx0WyBcIm5vdGlmeVwiLCBcInByb2dyZXNzXCIsIGpRdWVyeS5DYWxsYmFja3MoIFwibWVtb3J5XCIgKSxcblx0XHRcdFx0XHRqUXVlcnkuQ2FsbGJhY2tzKCBcIm1lbW9yeVwiICksIDIgXSxcblx0XHRcdFx0WyBcInJlc29sdmVcIiwgXCJkb25lXCIsIGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLFxuXHRcdFx0XHRcdGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLCAwLCBcInJlc29sdmVkXCIgXSxcblx0XHRcdFx0WyBcInJlamVjdFwiLCBcImZhaWxcIiwgalF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksXG5cdFx0XHRcdFx0alF1ZXJ5LkNhbGxiYWNrcyggXCJvbmNlIG1lbW9yeVwiICksIDEsIFwicmVqZWN0ZWRcIiBdXG5cdFx0XHRdLFxuXHRcdFx0c3RhdGUgPSBcInBlbmRpbmdcIixcblx0XHRcdHByb21pc2UgPSB7XG5cdFx0XHRcdHN0YXRlOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRyZXR1cm4gc3RhdGU7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdGFsd2F5czogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQuZG9uZSggYXJndW1lbnRzICkuZmFpbCggYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFwiY2F0Y2hcIjogZnVuY3Rpb24oIGZuICkge1xuXHRcdFx0XHRcdHJldHVybiBwcm9taXNlLnRoZW4oIG51bGwsIGZuICk7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gS2VlcCBwaXBlIGZvciBiYWNrLWNvbXBhdFxuXHRcdFx0XHRwaXBlOiBmdW5jdGlvbiggLyogZm5Eb25lLCBmbkZhaWwsIGZuUHJvZ3Jlc3MgKi8gKSB7XG5cdFx0XHRcdFx0dmFyIGZucyA9IGFyZ3VtZW50cztcblxuXHRcdFx0XHRcdHJldHVybiBqUXVlcnkuRGVmZXJyZWQoIGZ1bmN0aW9uKCBuZXdEZWZlciApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5lYWNoKCB0dXBsZXMsIGZ1bmN0aW9uKCBpLCB0dXBsZSApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBNYXAgdHVwbGVzIChwcm9ncmVzcywgZG9uZSwgZmFpbCkgdG8gYXJndW1lbnRzIChkb25lLCBmYWlsLCBwcm9ncmVzcylcblx0XHRcdFx0XHRcdFx0dmFyIGZuID0galF1ZXJ5LmlzRnVuY3Rpb24oIGZuc1sgdHVwbGVbIDQgXSBdICkgJiYgZm5zWyB0dXBsZVsgNCBdIF07XG5cblx0XHRcdFx0XHRcdFx0Ly8gZGVmZXJyZWQucHJvZ3Jlc3MoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIubm90aWZ5IH0pXG5cdFx0XHRcdFx0XHRcdC8vIGRlZmVycmVkLmRvbmUoZnVuY3Rpb24oKSB7IGJpbmQgdG8gbmV3RGVmZXIgb3IgbmV3RGVmZXIucmVzb2x2ZSB9KVxuXHRcdFx0XHRcdFx0XHQvLyBkZWZlcnJlZC5mYWlsKGZ1bmN0aW9uKCkgeyBiaW5kIHRvIG5ld0RlZmVyIG9yIG5ld0RlZmVyLnJlamVjdCB9KVxuXHRcdFx0XHRcdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDEgXSBdKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHR2YXIgcmV0dXJuZWQgPSBmbiAmJiBmbi5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdFx0XHRcdFx0aWYgKCByZXR1cm5lZCAmJiBqUXVlcnkuaXNGdW5jdGlvbiggcmV0dXJuZWQucHJvbWlzZSApICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQucHJvbWlzZSgpXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC5wcm9ncmVzcyggbmV3RGVmZXIubm90aWZ5IClcblx0XHRcdFx0XHRcdFx0XHRcdFx0LmRvbmUoIG5ld0RlZmVyLnJlc29sdmUgKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQuZmFpbCggbmV3RGVmZXIucmVqZWN0ICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyWyB0dXBsZVsgMCBdICsgXCJXaXRoXCIgXShcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGhpcyxcblx0XHRcdFx0XHRcdFx0XHRcdFx0Zm4gPyBbIHJldHVybmVkIF0gOiBhcmd1bWVudHNcblx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRmbnMgPSBudWxsO1xuXHRcdFx0XHRcdH0gKS5wcm9taXNlKCk7XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHRoZW46IGZ1bmN0aW9uKCBvbkZ1bGZpbGxlZCwgb25SZWplY3RlZCwgb25Qcm9ncmVzcyApIHtcblx0XHRcdFx0XHR2YXIgbWF4RGVwdGggPSAwO1xuXHRcdFx0XHRcdGZ1bmN0aW9uIHJlc29sdmUoIGRlcHRoLCBkZWZlcnJlZCwgaGFuZGxlciwgc3BlY2lhbCApIHtcblx0XHRcdFx0XHRcdHJldHVybiBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0dmFyIHRoYXQgPSB0aGlzLFxuXHRcdFx0XHRcdFx0XHRcdGFyZ3MgPSBhcmd1bWVudHMsXG5cdFx0XHRcdFx0XHRcdFx0bWlnaHRUaHJvdyA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0dmFyIHJldHVybmVkLCB0aGVuO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy4zLjMuM1xuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTlcblx0XHRcdFx0XHRcdFx0XHRcdC8vIElnbm9yZSBkb3VibGUtcmVzb2x1dGlvbiBhdHRlbXB0c1xuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCA8IG1heERlcHRoICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdHJldHVybmVkID0gaGFuZGxlci5hcHBseSggdGhhdCwgYXJncyApO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy4xXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC00OFxuXHRcdFx0XHRcdFx0XHRcdFx0aWYgKCByZXR1cm5lZCA9PT0gZGVmZXJyZWQucHJvbWlzZSgpICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKCBcIlRoZW5hYmxlIHNlbGYtcmVzb2x1dGlvblwiICk7XG5cdFx0XHRcdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb25zIDIuMy4zLjEsIDMuNVxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gaHR0cHM6Ly9wcm9taXNlc2FwbHVzLmNvbS8jcG9pbnQtNTRcblx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTc1XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBSZXRyaWV2ZSBgdGhlbmAgb25seSBvbmNlXG5cdFx0XHRcdFx0XHRcdFx0XHR0aGVuID0gcmV0dXJuZWQgJiZcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTdXBwb3J0OiBQcm9taXNlcy9BKyBzZWN0aW9uIDIuMy40XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTY0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIE9ubHkgY2hlY2sgb2JqZWN0cyBhbmQgZnVuY3Rpb25zIGZvciB0aGVuYWJpbGl0eVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoIHR5cGVvZiByZXR1cm5lZCA9PT0gXCJvYmplY3RcIiB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdHR5cGVvZiByZXR1cm5lZCA9PT0gXCJmdW5jdGlvblwiICkgJiZcblx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQudGhlbjtcblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGEgcmV0dXJuZWQgdGhlbmFibGVcblx0XHRcdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHRoZW4gKSApIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBTcGVjaWFsIHByb2Nlc3NvcnMgKG5vdGlmeSkganVzdCB3YWl0IGZvciByZXNvbHV0aW9uXG5cdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggc3BlY2lhbCApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGVuLmNhbGwoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXR1cm5lZCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgVGhyb3dlciwgc3BlY2lhbCApXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBOb3JtYWwgcHJvY2Vzc29ycyAocmVzb2x2ZSkgYWxzbyBob29rIGludG8gcHJvZ3Jlc3Ncblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIC4uLmFuZCBkaXNyZWdhcmQgb2xkZXIgcmVzb2x1dGlvbiB2YWx1ZXNcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRtYXhEZXB0aCsrO1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhlbi5jYWxsKFxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0cmV0dXJuZWQsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNvbHZlKCBtYXhEZXB0aCwgZGVmZXJyZWQsIElkZW50aXR5LCBzcGVjaWFsICksXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRyZXNvbHZlKCBtYXhEZXB0aCwgZGVmZXJyZWQsIFRocm93ZXIsIHNwZWNpYWwgKSxcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHJlc29sdmUoIG1heERlcHRoLCBkZWZlcnJlZCwgSWRlbnRpdHksXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGggKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0Ly8gSGFuZGxlIGFsbCBvdGhlciByZXR1cm5lZCB2YWx1ZXNcblx0XHRcdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0Ly8gT25seSBzdWJzdGl0dXRlIGhhbmRsZXJzIHBhc3Mgb24gY29udGV4dFxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhbmQgbXVsdGlwbGUgdmFsdWVzIChub24tc3BlYyBiZWhhdmlvcilcblx0XHRcdFx0XHRcdFx0XHRcdFx0aWYgKCBoYW5kbGVyICE9PSBJZGVudGl0eSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHR0aGF0ID0gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGFyZ3MgPSBbIHJldHVybmVkIF07XG5cdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBQcm9jZXNzIHRoZSB2YWx1ZShzKVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBEZWZhdWx0IHByb2Nlc3MgaXMgcmVzb2x2ZVxuXHRcdFx0XHRcdFx0XHRcdFx0XHQoIHNwZWNpYWwgfHwgZGVmZXJyZWQucmVzb2x2ZVdpdGggKSggdGhhdCwgYXJncyApO1xuXHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IG5vcm1hbCBwcm9jZXNzb3JzIChyZXNvbHZlKSBjYXRjaCBhbmQgcmVqZWN0IGV4Y2VwdGlvbnNcblx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzID0gc3BlY2lhbCA/XG5cdFx0XHRcdFx0XHRcdFx0XHRtaWdodFRocm93IDpcblx0XHRcdFx0XHRcdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG1pZ2h0VGhyb3coKTtcblx0XHRcdFx0XHRcdFx0XHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5EZWZlcnJlZC5leGNlcHRpb25Ib29rICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LkRlZmVycmVkLmV4Y2VwdGlvbkhvb2soIGUsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdHByb2Nlc3Muc3RhY2tUcmFjZSApO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy40LjFcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBodHRwczovL3Byb21pc2VzYXBsdXMuY29tLyNwb2ludC02MVxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdC8vIElnbm9yZSBwb3N0LXJlc29sdXRpb24gZXhjZXB0aW9uc1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggZGVwdGggKyAxID49IG1heERlcHRoICkge1xuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBPbmx5IHN1YnN0aXR1dGUgaGFuZGxlcnMgcGFzcyBvbiBjb250ZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHQvLyBhbmQgbXVsdGlwbGUgdmFsdWVzIChub24tc3BlYyBiZWhhdmlvcilcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdGlmICggaGFuZGxlciAhPT0gVGhyb3dlciApIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0dGhhdCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0YXJncyA9IFsgZSBdO1xuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRkZWZlcnJlZC5yZWplY3RXaXRoKCB0aGF0LCBhcmdzICk7XG5cdFx0XHRcdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IFByb21pc2VzL0ErIHNlY3Rpb24gMi4zLjMuMy4xXG5cdFx0XHRcdFx0XHRcdC8vIGh0dHBzOi8vcHJvbWlzZXNhcGx1cy5jb20vI3BvaW50LTU3XG5cdFx0XHRcdFx0XHRcdC8vIFJlLXJlc29sdmUgcHJvbWlzZXMgaW1tZWRpYXRlbHkgdG8gZG9kZ2UgZmFsc2UgcmVqZWN0aW9uIGZyb21cblx0XHRcdFx0XHRcdFx0Ly8gc3Vic2VxdWVudCBlcnJvcnNcblx0XHRcdFx0XHRcdFx0aWYgKCBkZXB0aCApIHtcblx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzKCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBDYWxsIGFuIG9wdGlvbmFsIGhvb2sgdG8gcmVjb3JkIHRoZSBzdGFjaywgaW4gY2FzZSBvZiBleGNlcHRpb25cblx0XHRcdFx0XHRcdFx0XHQvLyBzaW5jZSBpdCdzIG90aGVyd2lzZSBsb3N0IHdoZW4gZXhlY3V0aW9uIGdvZXMgYXN5bmNcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGpRdWVyeS5EZWZlcnJlZC5nZXRTdGFja0hvb2sgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRwcm9jZXNzLnN0YWNrVHJhY2UgPSBqUXVlcnkuRGVmZXJyZWQuZ2V0U3RhY2tIb29rKCk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBwcm9jZXNzICk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH07XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0cmV0dXJuIGpRdWVyeS5EZWZlcnJlZCggZnVuY3Rpb24oIG5ld0RlZmVyICkge1xuXG5cdFx0XHRcdFx0XHQvLyBwcm9ncmVzc19oYW5kbGVycy5hZGQoIC4uLiApXG5cdFx0XHRcdFx0XHR0dXBsZXNbIDAgXVsgMyBdLmFkZChcblx0XHRcdFx0XHRcdFx0cmVzb2x2ZShcblx0XHRcdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLFxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5pc0Z1bmN0aW9uKCBvblByb2dyZXNzICkgP1xuXHRcdFx0XHRcdFx0XHRcdFx0b25Qcm9ncmVzcyA6XG5cdFx0XHRcdFx0XHRcdFx0XHRJZGVudGl0eSxcblx0XHRcdFx0XHRcdFx0XHRuZXdEZWZlci5ub3RpZnlXaXRoXG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdC8vIGZ1bGZpbGxlZF9oYW5kbGVycy5hZGQoIC4uLiApXG5cdFx0XHRcdFx0XHR0dXBsZXNbIDEgXVsgMyBdLmFkZChcblx0XHRcdFx0XHRcdFx0cmVzb2x2ZShcblx0XHRcdFx0XHRcdFx0XHQwLFxuXHRcdFx0XHRcdFx0XHRcdG5ld0RlZmVyLFxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5pc0Z1bmN0aW9uKCBvbkZ1bGZpbGxlZCApID9cblx0XHRcdFx0XHRcdFx0XHRcdG9uRnVsZmlsbGVkIDpcblx0XHRcdFx0XHRcdFx0XHRcdElkZW50aXR5XG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdCk7XG5cblx0XHRcdFx0XHRcdC8vIHJlamVjdGVkX2hhbmRsZXJzLmFkZCggLi4uIClcblx0XHRcdFx0XHRcdHR1cGxlc1sgMiBdWyAzIF0uYWRkKFxuXHRcdFx0XHRcdFx0XHRyZXNvbHZlKFxuXHRcdFx0XHRcdFx0XHRcdDAsXG5cdFx0XHRcdFx0XHRcdFx0bmV3RGVmZXIsXG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIG9uUmVqZWN0ZWQgKSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRvblJlamVjdGVkIDpcblx0XHRcdFx0XHRcdFx0XHRcdFRocm93ZXJcblx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHR9ICkucHJvbWlzZSgpO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIEdldCBhIHByb21pc2UgZm9yIHRoaXMgZGVmZXJyZWRcblx0XHRcdFx0Ly8gSWYgb2JqIGlzIHByb3ZpZGVkLCB0aGUgcHJvbWlzZSBhc3BlY3QgaXMgYWRkZWQgdG8gdGhlIG9iamVjdFxuXHRcdFx0XHRwcm9taXNlOiBmdW5jdGlvbiggb2JqICkge1xuXHRcdFx0XHRcdHJldHVybiBvYmogIT0gbnVsbCA/IGpRdWVyeS5leHRlbmQoIG9iaiwgcHJvbWlzZSApIDogcHJvbWlzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGRlZmVycmVkID0ge307XG5cblx0XHQvLyBBZGQgbGlzdC1zcGVjaWZpYyBtZXRob2RzXG5cdFx0alF1ZXJ5LmVhY2goIHR1cGxlcywgZnVuY3Rpb24oIGksIHR1cGxlICkge1xuXHRcdFx0dmFyIGxpc3QgPSB0dXBsZVsgMiBdLFxuXHRcdFx0XHRzdGF0ZVN0cmluZyA9IHR1cGxlWyA1IF07XG5cblx0XHRcdC8vIHByb21pc2UucHJvZ3Jlc3MgPSBsaXN0LmFkZFxuXHRcdFx0Ly8gcHJvbWlzZS5kb25lID0gbGlzdC5hZGRcblx0XHRcdC8vIHByb21pc2UuZmFpbCA9IGxpc3QuYWRkXG5cdFx0XHRwcm9taXNlWyB0dXBsZVsgMSBdIF0gPSBsaXN0LmFkZDtcblxuXHRcdFx0Ly8gSGFuZGxlIHN0YXRlXG5cdFx0XHRpZiAoIHN0YXRlU3RyaW5nICkge1xuXHRcdFx0XHRsaXN0LmFkZChcblx0XHRcdFx0XHRmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0Ly8gc3RhdGUgPSBcInJlc29sdmVkXCIgKGkuZS4sIGZ1bGZpbGxlZClcblx0XHRcdFx0XHRcdC8vIHN0YXRlID0gXCJyZWplY3RlZFwiXG5cdFx0XHRcdFx0XHRzdGF0ZSA9IHN0YXRlU3RyaW5nO1xuXHRcdFx0XHRcdH0sXG5cblx0XHRcdFx0XHQvLyByZWplY3RlZF9jYWxsYmFja3MuZGlzYWJsZVxuXHRcdFx0XHRcdC8vIGZ1bGZpbGxlZF9jYWxsYmFja3MuZGlzYWJsZVxuXHRcdFx0XHRcdHR1cGxlc1sgMyAtIGkgXVsgMiBdLmRpc2FibGUsXG5cblx0XHRcdFx0XHQvLyBwcm9ncmVzc19jYWxsYmFja3MubG9ja1xuXHRcdFx0XHRcdHR1cGxlc1sgMCBdWyAyIF0ubG9ja1xuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBwcm9ncmVzc19oYW5kbGVycy5maXJlXG5cdFx0XHQvLyBmdWxmaWxsZWRfaGFuZGxlcnMuZmlyZVxuXHRcdFx0Ly8gcmVqZWN0ZWRfaGFuZGxlcnMuZmlyZVxuXHRcdFx0bGlzdC5hZGQoIHR1cGxlWyAzIF0uZmlyZSApO1xuXG5cdFx0XHQvLyBkZWZlcnJlZC5ub3RpZnkgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQubm90aWZ5V2l0aCguLi4pIH1cblx0XHRcdC8vIGRlZmVycmVkLnJlc29sdmUgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQucmVzb2x2ZVdpdGgoLi4uKSB9XG5cdFx0XHQvLyBkZWZlcnJlZC5yZWplY3QgPSBmdW5jdGlvbigpIHsgZGVmZXJyZWQucmVqZWN0V2l0aCguLi4pIH1cblx0XHRcdGRlZmVycmVkWyB0dXBsZVsgMCBdIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdFx0ZGVmZXJyZWRbIHR1cGxlWyAwIF0gKyBcIldpdGhcIiBdKCB0aGlzID09PSBkZWZlcnJlZCA/IHVuZGVmaW5lZCA6IHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdH07XG5cblx0XHRcdC8vIGRlZmVycmVkLm5vdGlmeVdpdGggPSBsaXN0LmZpcmVXaXRoXG5cdFx0XHQvLyBkZWZlcnJlZC5yZXNvbHZlV2l0aCA9IGxpc3QuZmlyZVdpdGhcblx0XHRcdC8vIGRlZmVycmVkLnJlamVjdFdpdGggPSBsaXN0LmZpcmVXaXRoXG5cdFx0XHRkZWZlcnJlZFsgdHVwbGVbIDAgXSArIFwiV2l0aFwiIF0gPSBsaXN0LmZpcmVXaXRoO1xuXHRcdH0gKTtcblxuXHRcdC8vIE1ha2UgdGhlIGRlZmVycmVkIGEgcHJvbWlzZVxuXHRcdHByb21pc2UucHJvbWlzZSggZGVmZXJyZWQgKTtcblxuXHRcdC8vIENhbGwgZ2l2ZW4gZnVuYyBpZiBhbnlcblx0XHRpZiAoIGZ1bmMgKSB7XG5cdFx0XHRmdW5jLmNhbGwoIGRlZmVycmVkLCBkZWZlcnJlZCApO1xuXHRcdH1cblxuXHRcdC8vIEFsbCBkb25lIVxuXHRcdHJldHVybiBkZWZlcnJlZDtcblx0fSxcblxuXHQvLyBEZWZlcnJlZCBoZWxwZXJcblx0d2hlbjogZnVuY3Rpb24oIHNpbmdsZVZhbHVlICkge1xuXHRcdHZhclxuXG5cdFx0XHQvLyBjb3VudCBvZiB1bmNvbXBsZXRlZCBzdWJvcmRpbmF0ZXNcblx0XHRcdHJlbWFpbmluZyA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cblx0XHRcdC8vIGNvdW50IG9mIHVucHJvY2Vzc2VkIGFyZ3VtZW50c1xuXHRcdFx0aSA9IHJlbWFpbmluZyxcblxuXHRcdFx0Ly8gc3Vib3JkaW5hdGUgZnVsZmlsbG1lbnQgZGF0YVxuXHRcdFx0cmVzb2x2ZUNvbnRleHRzID0gQXJyYXkoIGkgKSxcblx0XHRcdHJlc29sdmVWYWx1ZXMgPSBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSxcblxuXHRcdFx0Ly8gdGhlIG1hc3RlciBEZWZlcnJlZFxuXHRcdFx0bWFzdGVyID0galF1ZXJ5LkRlZmVycmVkKCksXG5cblx0XHRcdC8vIHN1Ym9yZGluYXRlIGNhbGxiYWNrIGZhY3Rvcnlcblx0XHRcdHVwZGF0ZUZ1bmMgPSBmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXNvbHZlQ29udGV4dHNbIGkgXSA9IHRoaXM7XG5cdFx0XHRcdFx0cmVzb2x2ZVZhbHVlc1sgaSBdID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgPyBzbGljZS5jYWxsKCBhcmd1bWVudHMgKSA6IHZhbHVlO1xuXHRcdFx0XHRcdGlmICggISggLS1yZW1haW5pbmcgKSApIHtcblx0XHRcdFx0XHRcdG1hc3Rlci5yZXNvbHZlV2l0aCggcmVzb2x2ZUNvbnRleHRzLCByZXNvbHZlVmFsdWVzICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdFx0fTtcblxuXHRcdC8vIFNpbmdsZS0gYW5kIGVtcHR5IGFyZ3VtZW50cyBhcmUgYWRvcHRlZCBsaWtlIFByb21pc2UucmVzb2x2ZVxuXHRcdGlmICggcmVtYWluaW5nIDw9IDEgKSB7XG5cdFx0XHRhZG9wdFZhbHVlKCBzaW5nbGVWYWx1ZSwgbWFzdGVyLmRvbmUoIHVwZGF0ZUZ1bmMoIGkgKSApLnJlc29sdmUsIG1hc3Rlci5yZWplY3QsXG5cdFx0XHRcdCFyZW1haW5pbmcgKTtcblxuXHRcdFx0Ly8gVXNlIC50aGVuKCkgdG8gdW53cmFwIHNlY29uZGFyeSB0aGVuYWJsZXMgKGNmLiBnaC0zMDAwKVxuXHRcdFx0aWYgKCBtYXN0ZXIuc3RhdGUoKSA9PT0gXCJwZW5kaW5nXCIgfHxcblx0XHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHJlc29sdmVWYWx1ZXNbIGkgXSAmJiByZXNvbHZlVmFsdWVzWyBpIF0udGhlbiApICkge1xuXG5cdFx0XHRcdHJldHVybiBtYXN0ZXIudGhlbigpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIE11bHRpcGxlIGFyZ3VtZW50cyBhcmUgYWdncmVnYXRlZCBsaWtlIFByb21pc2UuYWxsIGFycmF5IGVsZW1lbnRzXG5cdFx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0XHRhZG9wdFZhbHVlKCByZXNvbHZlVmFsdWVzWyBpIF0sIHVwZGF0ZUZ1bmMoIGkgKSwgbWFzdGVyLnJlamVjdCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBtYXN0ZXIucHJvbWlzZSgpO1xuXHR9XG59ICk7XG5cblxuLy8gVGhlc2UgdXN1YWxseSBpbmRpY2F0ZSBhIHByb2dyYW1tZXIgbWlzdGFrZSBkdXJpbmcgZGV2ZWxvcG1lbnQsXG4vLyB3YXJuIGFib3V0IHRoZW0gQVNBUCByYXRoZXIgdGhhbiBzd2FsbG93aW5nIHRoZW0gYnkgZGVmYXVsdC5cbnZhciByZXJyb3JOYW1lcyA9IC9eKEV2YWx8SW50ZXJuYWx8UmFuZ2V8UmVmZXJlbmNlfFN5bnRheHxUeXBlfFVSSSlFcnJvciQvO1xuXG5qUXVlcnkuRGVmZXJyZWQuZXhjZXB0aW9uSG9vayA9IGZ1bmN0aW9uKCBlcnJvciwgc3RhY2sgKSB7XG5cblx0Ly8gU3VwcG9ydDogSUUgOCAtIDkgb25seVxuXHQvLyBDb25zb2xlIGV4aXN0cyB3aGVuIGRldiB0b29scyBhcmUgb3Blbiwgd2hpY2ggY2FuIGhhcHBlbiBhdCBhbnkgdGltZVxuXHRpZiAoIHdpbmRvdy5jb25zb2xlICYmIHdpbmRvdy5jb25zb2xlLndhcm4gJiYgZXJyb3IgJiYgcmVycm9yTmFtZXMudGVzdCggZXJyb3IubmFtZSApICkge1xuXHRcdHdpbmRvdy5jb25zb2xlLndhcm4oIFwialF1ZXJ5LkRlZmVycmVkIGV4Y2VwdGlvbjogXCIgKyBlcnJvci5tZXNzYWdlLCBlcnJvci5zdGFjaywgc3RhY2sgKTtcblx0fVxufTtcblxuXG5cblxualF1ZXJ5LnJlYWR5RXhjZXB0aW9uID0gZnVuY3Rpb24oIGVycm9yICkge1xuXHR3aW5kb3cuc2V0VGltZW91dCggZnVuY3Rpb24oKSB7XG5cdFx0dGhyb3cgZXJyb3I7XG5cdH0gKTtcbn07XG5cblxuXG5cbi8vIFRoZSBkZWZlcnJlZCB1c2VkIG9uIERPTSByZWFkeVxudmFyIHJlYWR5TGlzdCA9IGpRdWVyeS5EZWZlcnJlZCgpO1xuXG5qUXVlcnkuZm4ucmVhZHkgPSBmdW5jdGlvbiggZm4gKSB7XG5cblx0cmVhZHlMaXN0XG5cdFx0LnRoZW4oIGZuIClcblxuXHRcdC8vIFdyYXAgalF1ZXJ5LnJlYWR5RXhjZXB0aW9uIGluIGEgZnVuY3Rpb24gc28gdGhhdCB0aGUgbG9va3VwXG5cdFx0Ly8gaGFwcGVucyBhdCB0aGUgdGltZSBvZiBlcnJvciBoYW5kbGluZyBpbnN0ZWFkIG9mIGNhbGxiYWNrXG5cdFx0Ly8gcmVnaXN0cmF0aW9uLlxuXHRcdC5jYXRjaCggZnVuY3Rpb24oIGVycm9yICkge1xuXHRcdFx0alF1ZXJ5LnJlYWR5RXhjZXB0aW9uKCBlcnJvciApO1xuXHRcdH0gKTtcblxuXHRyZXR1cm4gdGhpcztcbn07XG5cbmpRdWVyeS5leHRlbmQoIHtcblxuXHQvLyBJcyB0aGUgRE9NIHJlYWR5IHRvIGJlIHVzZWQ/IFNldCB0byB0cnVlIG9uY2UgaXQgb2NjdXJzLlxuXHRpc1JlYWR5OiBmYWxzZSxcblxuXHQvLyBBIGNvdW50ZXIgdG8gdHJhY2sgaG93IG1hbnkgaXRlbXMgdG8gd2FpdCBmb3IgYmVmb3JlXG5cdC8vIHRoZSByZWFkeSBldmVudCBmaXJlcy4gU2VlICM2NzgxXG5cdHJlYWR5V2FpdDogMSxcblxuXHQvLyBIYW5kbGUgd2hlbiB0aGUgRE9NIGlzIHJlYWR5XG5cdHJlYWR5OiBmdW5jdGlvbiggd2FpdCApIHtcblxuXHRcdC8vIEFib3J0IGlmIHRoZXJlIGFyZSBwZW5kaW5nIGhvbGRzIG9yIHdlJ3JlIGFscmVhZHkgcmVhZHlcblx0XHRpZiAoIHdhaXQgPT09IHRydWUgPyAtLWpRdWVyeS5yZWFkeVdhaXQgOiBqUXVlcnkuaXNSZWFkeSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBSZW1lbWJlciB0aGF0IHRoZSBET00gaXMgcmVhZHlcblx0XHRqUXVlcnkuaXNSZWFkeSA9IHRydWU7XG5cblx0XHQvLyBJZiBhIG5vcm1hbCBET00gUmVhZHkgZXZlbnQgZmlyZWQsIGRlY3JlbWVudCwgYW5kIHdhaXQgaWYgbmVlZCBiZVxuXHRcdGlmICggd2FpdCAhPT0gdHJ1ZSAmJiAtLWpRdWVyeS5yZWFkeVdhaXQgPiAwICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIElmIHRoZXJlIGFyZSBmdW5jdGlvbnMgYm91bmQsIHRvIGV4ZWN1dGVcblx0XHRyZWFkeUxpc3QucmVzb2x2ZVdpdGgoIGRvY3VtZW50LCBbIGpRdWVyeSBdICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LnJlYWR5LnRoZW4gPSByZWFkeUxpc3QudGhlbjtcblxuLy8gVGhlIHJlYWR5IGV2ZW50IGhhbmRsZXIgYW5kIHNlbGYgY2xlYW51cCBtZXRob2RcbmZ1bmN0aW9uIGNvbXBsZXRlZCgpIHtcblx0ZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCApO1xuXHR3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lciggXCJsb2FkXCIsIGNvbXBsZXRlZCApO1xuXHRqUXVlcnkucmVhZHkoKTtcbn1cblxuLy8gQ2F0Y2ggY2FzZXMgd2hlcmUgJChkb2N1bWVudCkucmVhZHkoKSBpcyBjYWxsZWRcbi8vIGFmdGVyIHRoZSBicm93c2VyIGV2ZW50IGhhcyBhbHJlYWR5IG9jY3VycmVkLlxuLy8gU3VwcG9ydDogSUUgPD05IC0gMTAgb25seVxuLy8gT2xkZXIgSUUgc29tZXRpbWVzIHNpZ25hbHMgXCJpbnRlcmFjdGl2ZVwiIHRvbyBzb29uXG5pZiAoIGRvY3VtZW50LnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIiB8fFxuXHQoIGRvY3VtZW50LnJlYWR5U3RhdGUgIT09IFwibG9hZGluZ1wiICYmICFkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuZG9TY3JvbGwgKSApIHtcblxuXHQvLyBIYW5kbGUgaXQgYXN5bmNocm9ub3VzbHkgdG8gYWxsb3cgc2NyaXB0cyB0aGUgb3Bwb3J0dW5pdHkgdG8gZGVsYXkgcmVhZHlcblx0d2luZG93LnNldFRpbWVvdXQoIGpRdWVyeS5yZWFkeSApO1xuXG59IGVsc2Uge1xuXG5cdC8vIFVzZSB0aGUgaGFuZHkgZXZlbnQgY2FsbGJhY2tcblx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lciggXCJET01Db250ZW50TG9hZGVkXCIsIGNvbXBsZXRlZCApO1xuXG5cdC8vIEEgZmFsbGJhY2sgdG8gd2luZG93Lm9ubG9hZCwgdGhhdCB3aWxsIGFsd2F5cyB3b3JrXG5cdHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCBcImxvYWRcIiwgY29tcGxldGVkICk7XG59XG5cblxuXG5cbi8vIE11bHRpZnVuY3Rpb25hbCBtZXRob2QgdG8gZ2V0IGFuZCBzZXQgdmFsdWVzIG9mIGEgY29sbGVjdGlvblxuLy8gVGhlIHZhbHVlL3MgY2FuIG9wdGlvbmFsbHkgYmUgZXhlY3V0ZWQgaWYgaXQncyBhIGZ1bmN0aW9uXG52YXIgYWNjZXNzID0gZnVuY3Rpb24oIGVsZW1zLCBmbiwga2V5LCB2YWx1ZSwgY2hhaW5hYmxlLCBlbXB0eUdldCwgcmF3ICkge1xuXHR2YXIgaSA9IDAsXG5cdFx0bGVuID0gZWxlbXMubGVuZ3RoLFxuXHRcdGJ1bGsgPSBrZXkgPT0gbnVsbDtcblxuXHQvLyBTZXRzIG1hbnkgdmFsdWVzXG5cdGlmICggalF1ZXJ5LnR5cGUoIGtleSApID09PSBcIm9iamVjdFwiICkge1xuXHRcdGNoYWluYWJsZSA9IHRydWU7XG5cdFx0Zm9yICggaSBpbiBrZXkgKSB7XG5cdFx0XHRhY2Nlc3MoIGVsZW1zLCBmbiwgaSwga2V5WyBpIF0sIHRydWUsIGVtcHR5R2V0LCByYXcgKTtcblx0XHR9XG5cblx0Ly8gU2V0cyBvbmUgdmFsdWVcblx0fSBlbHNlIGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRjaGFpbmFibGUgPSB0cnVlO1xuXG5cdFx0aWYgKCAhalF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICkgKSB7XG5cdFx0XHRyYXcgPSB0cnVlO1xuXHRcdH1cblxuXHRcdGlmICggYnVsayApIHtcblxuXHRcdFx0Ly8gQnVsayBvcGVyYXRpb25zIHJ1biBhZ2FpbnN0IHRoZSBlbnRpcmUgc2V0XG5cdFx0XHRpZiAoIHJhdyApIHtcblx0XHRcdFx0Zm4uY2FsbCggZWxlbXMsIHZhbHVlICk7XG5cdFx0XHRcdGZuID0gbnVsbDtcblxuXHRcdFx0Ly8gLi4uZXhjZXB0IHdoZW4gZXhlY3V0aW5nIGZ1bmN0aW9uIHZhbHVlc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YnVsayA9IGZuO1xuXHRcdFx0XHRmbiA9IGZ1bmN0aW9uKCBlbGVtLCBrZXksIHZhbHVlICkge1xuXHRcdFx0XHRcdHJldHVybiBidWxrLmNhbGwoIGpRdWVyeSggZWxlbSApLCB2YWx1ZSApO1xuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggZm4gKSB7XG5cdFx0XHRmb3IgKCA7IGkgPCBsZW47IGkrKyApIHtcblx0XHRcdFx0Zm4oXG5cdFx0XHRcdFx0ZWxlbXNbIGkgXSwga2V5LCByYXcgP1xuXHRcdFx0XHRcdHZhbHVlIDpcblx0XHRcdFx0XHR2YWx1ZS5jYWxsKCBlbGVtc1sgaSBdLCBpLCBmbiggZWxlbXNbIGkgXSwga2V5ICkgKVxuXHRcdFx0XHQpO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmICggY2hhaW5hYmxlICkge1xuXHRcdHJldHVybiBlbGVtcztcblx0fVxuXG5cdC8vIEdldHNcblx0aWYgKCBidWxrICkge1xuXHRcdHJldHVybiBmbi5jYWxsKCBlbGVtcyApO1xuXHR9XG5cblx0cmV0dXJuIGxlbiA/IGZuKCBlbGVtc1sgMCBdLCBrZXkgKSA6IGVtcHR5R2V0O1xufTtcbnZhciBhY2NlcHREYXRhID0gZnVuY3Rpb24oIG93bmVyICkge1xuXG5cdC8vIEFjY2VwdHMgb25seTpcblx0Ly8gIC0gTm9kZVxuXHQvLyAgICAtIE5vZGUuRUxFTUVOVF9OT0RFXG5cdC8vICAgIC0gTm9kZS5ET0NVTUVOVF9OT0RFXG5cdC8vICAtIE9iamVjdFxuXHQvLyAgICAtIEFueVxuXHRyZXR1cm4gb3duZXIubm9kZVR5cGUgPT09IDEgfHwgb3duZXIubm9kZVR5cGUgPT09IDkgfHwgISggK293bmVyLm5vZGVUeXBlICk7XG59O1xuXG5cblxuXG5mdW5jdGlvbiBEYXRhKCkge1xuXHR0aGlzLmV4cGFuZG8gPSBqUXVlcnkuZXhwYW5kbyArIERhdGEudWlkKys7XG59XG5cbkRhdGEudWlkID0gMTtcblxuRGF0YS5wcm90b3R5cGUgPSB7XG5cblx0Y2FjaGU6IGZ1bmN0aW9uKCBvd25lciApIHtcblxuXHRcdC8vIENoZWNrIGlmIHRoZSBvd25lciBvYmplY3QgYWxyZWFkeSBoYXMgYSBjYWNoZVxuXHRcdHZhciB2YWx1ZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblxuXHRcdC8vIElmIG5vdCwgY3JlYXRlIG9uZVxuXHRcdGlmICggIXZhbHVlICkge1xuXHRcdFx0dmFsdWUgPSB7fTtcblxuXHRcdFx0Ly8gV2UgY2FuIGFjY2VwdCBkYXRhIGZvciBub24tZWxlbWVudCBub2RlcyBpbiBtb2Rlcm4gYnJvd3NlcnMsXG5cdFx0XHQvLyBidXQgd2Ugc2hvdWxkIG5vdCwgc2VlICM4MzM1LlxuXHRcdFx0Ly8gQWx3YXlzIHJldHVybiBhbiBlbXB0eSBvYmplY3QuXG5cdFx0XHRpZiAoIGFjY2VwdERhdGEoIG93bmVyICkgKSB7XG5cblx0XHRcdFx0Ly8gSWYgaXQgaXMgYSBub2RlIHVubGlrZWx5IHRvIGJlIHN0cmluZ2lmeS1lZCBvciBsb29wZWQgb3ZlclxuXHRcdFx0XHQvLyB1c2UgcGxhaW4gYXNzaWdubWVudFxuXHRcdFx0XHRpZiAoIG93bmVyLm5vZGVUeXBlICkge1xuXHRcdFx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSA9IHZhbHVlO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBzZWN1cmUgaXQgaW4gYSBub24tZW51bWVyYWJsZSBwcm9wZXJ0eVxuXHRcdFx0XHQvLyBjb25maWd1cmFibGUgbXVzdCBiZSB0cnVlIHRvIGFsbG93IHRoZSBwcm9wZXJ0eSB0byBiZVxuXHRcdFx0XHQvLyBkZWxldGVkIHdoZW4gZGF0YSBpcyByZW1vdmVkXG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KCBvd25lciwgdGhpcy5leHBhbmRvLCB7XG5cdFx0XHRcdFx0XHR2YWx1ZTogdmFsdWUsXG5cdFx0XHRcdFx0XHRjb25maWd1cmFibGU6IHRydWVcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdmFsdWU7XG5cdH0sXG5cdHNldDogZnVuY3Rpb24oIG93bmVyLCBkYXRhLCB2YWx1ZSApIHtcblx0XHR2YXIgcHJvcCxcblx0XHRcdGNhY2hlID0gdGhpcy5jYWNoZSggb3duZXIgKTtcblxuXHRcdC8vIEhhbmRsZTogWyBvd25lciwga2V5LCB2YWx1ZSBdIGFyZ3Ncblx0XHQvLyBBbHdheXMgdXNlIGNhbWVsQ2FzZSBrZXkgKGdoLTIyNTcpXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGNhY2hlWyBqUXVlcnkuY2FtZWxDYXNlKCBkYXRhICkgXSA9IHZhbHVlO1xuXG5cdFx0Ly8gSGFuZGxlOiBbIG93bmVyLCB7IHByb3BlcnRpZXMgfSBdIGFyZ3Ncblx0XHR9IGVsc2Uge1xuXG5cdFx0XHQvLyBDb3B5IHRoZSBwcm9wZXJ0aWVzIG9uZS1ieS1vbmUgdG8gdGhlIGNhY2hlIG9iamVjdFxuXHRcdFx0Zm9yICggcHJvcCBpbiBkYXRhICkge1xuXHRcdFx0XHRjYWNoZVsgalF1ZXJ5LmNhbWVsQ2FzZSggcHJvcCApIF0gPSBkYXRhWyBwcm9wIF07XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBjYWNoZTtcblx0fSxcblx0Z2V0OiBmdW5jdGlvbiggb3duZXIsIGtleSApIHtcblx0XHRyZXR1cm4ga2V5ID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcy5jYWNoZSggb3duZXIgKSA6XG5cblx0XHRcdC8vIEFsd2F5cyB1c2UgY2FtZWxDYXNlIGtleSAoZ2gtMjI1Nylcblx0XHRcdG93bmVyWyB0aGlzLmV4cGFuZG8gXSAmJiBvd25lclsgdGhpcy5leHBhbmRvIF1bIGpRdWVyeS5jYW1lbENhc2UoIGtleSApIF07XG5cdH0sXG5cdGFjY2VzczogZnVuY3Rpb24oIG93bmVyLCBrZXksIHZhbHVlICkge1xuXG5cdFx0Ly8gSW4gY2FzZXMgd2hlcmUgZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBObyBrZXkgd2FzIHNwZWNpZmllZFxuXHRcdC8vICAgMi4gQSBzdHJpbmcga2V5IHdhcyBzcGVjaWZpZWQsIGJ1dCBubyB2YWx1ZSBwcm92aWRlZFxuXHRcdC8vXG5cdFx0Ly8gVGFrZSB0aGUgXCJyZWFkXCIgcGF0aCBhbmQgYWxsb3cgdGhlIGdldCBtZXRob2QgdG8gZGV0ZXJtaW5lXG5cdFx0Ly8gd2hpY2ggdmFsdWUgdG8gcmV0dXJuLCByZXNwZWN0aXZlbHkgZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBUaGUgZW50aXJlIGNhY2hlIG9iamVjdFxuXHRcdC8vICAgMi4gVGhlIGRhdGEgc3RvcmVkIGF0IHRoZSBrZXlcblx0XHQvL1xuXHRcdGlmICgga2V5ID09PSB1bmRlZmluZWQgfHxcblx0XHRcdFx0KCAoIGtleSAmJiB0eXBlb2Yga2V5ID09PSBcInN0cmluZ1wiICkgJiYgdmFsdWUgPT09IHVuZGVmaW5lZCApICkge1xuXG5cdFx0XHRyZXR1cm4gdGhpcy5nZXQoIG93bmVyLCBrZXkgKTtcblx0XHR9XG5cblx0XHQvLyBXaGVuIHRoZSBrZXkgaXMgbm90IGEgc3RyaW5nLCBvciBib3RoIGEga2V5IGFuZCB2YWx1ZVxuXHRcdC8vIGFyZSBzcGVjaWZpZWQsIHNldCBvciBleHRlbmQgKGV4aXN0aW5nIG9iamVjdHMpIHdpdGggZWl0aGVyOlxuXHRcdC8vXG5cdFx0Ly8gICAxLiBBbiBvYmplY3Qgb2YgcHJvcGVydGllc1xuXHRcdC8vICAgMi4gQSBrZXkgYW5kIHZhbHVlXG5cdFx0Ly9cblx0XHR0aGlzLnNldCggb3duZXIsIGtleSwgdmFsdWUgKTtcblxuXHRcdC8vIFNpbmNlIHRoZSBcInNldFwiIHBhdGggY2FuIGhhdmUgdHdvIHBvc3NpYmxlIGVudHJ5IHBvaW50c1xuXHRcdC8vIHJldHVybiB0aGUgZXhwZWN0ZWQgZGF0YSBiYXNlZCBvbiB3aGljaCBwYXRoIHdhcyB0YWtlblsqXVxuXHRcdHJldHVybiB2YWx1ZSAhPT0gdW5kZWZpbmVkID8gdmFsdWUgOiBrZXk7XG5cdH0sXG5cdHJlbW92ZTogZnVuY3Rpb24oIG93bmVyLCBrZXkgKSB7XG5cdFx0dmFyIGksXG5cdFx0XHRjYWNoZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblxuXHRcdGlmICggY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIGtleSAhPT0gdW5kZWZpbmVkICkge1xuXG5cdFx0XHQvLyBTdXBwb3J0IGFycmF5IG9yIHNwYWNlIHNlcGFyYXRlZCBzdHJpbmcgb2Yga2V5c1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCBrZXkgKSApIHtcblxuXHRcdFx0XHQvLyBJZiBrZXkgaXMgYW4gYXJyYXkgb2Yga2V5cy4uLlxuXHRcdFx0XHQvLyBXZSBhbHdheXMgc2V0IGNhbWVsQ2FzZSBrZXlzLCBzbyByZW1vdmUgdGhhdC5cblx0XHRcdFx0a2V5ID0ga2V5Lm1hcCggalF1ZXJ5LmNhbWVsQ2FzZSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0a2V5ID0galF1ZXJ5LmNhbWVsQ2FzZSgga2V5ICk7XG5cblx0XHRcdFx0Ly8gSWYgYSBrZXkgd2l0aCB0aGUgc3BhY2VzIGV4aXN0cywgdXNlIGl0LlxuXHRcdFx0XHQvLyBPdGhlcndpc2UsIGNyZWF0ZSBhbiBhcnJheSBieSBtYXRjaGluZyBub24td2hpdGVzcGFjZVxuXHRcdFx0XHRrZXkgPSBrZXkgaW4gY2FjaGUgP1xuXHRcdFx0XHRcdFsga2V5IF0gOlxuXHRcdFx0XHRcdCgga2V5Lm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW10gKTtcblx0XHRcdH1cblxuXHRcdFx0aSA9IGtleS5sZW5ndGg7XG5cblx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRkZWxldGUgY2FjaGVbIGtleVsgaSBdIF07XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gUmVtb3ZlIHRoZSBleHBhbmRvIGlmIHRoZXJlJ3Mgbm8gbW9yZSBkYXRhXG5cdFx0aWYgKCBrZXkgPT09IHVuZGVmaW5lZCB8fCBqUXVlcnkuaXNFbXB0eU9iamVjdCggY2FjaGUgKSApIHtcblxuXHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lIDw9MzUgLSA0NVxuXHRcdFx0Ly8gV2Via2l0ICYgQmxpbmsgcGVyZm9ybWFuY2Ugc3VmZmVycyB3aGVuIGRlbGV0aW5nIHByb3BlcnRpZXNcblx0XHRcdC8vIGZyb20gRE9NIG5vZGVzLCBzbyBzZXQgdG8gdW5kZWZpbmVkIGluc3RlYWRcblx0XHRcdC8vIGh0dHBzOi8vYnVncy5jaHJvbWl1bS5vcmcvcC9jaHJvbWl1bS9pc3N1ZXMvZGV0YWlsP2lkPTM3ODYwNyAoYnVnIHJlc3RyaWN0ZWQpXG5cdFx0XHRpZiAoIG93bmVyLm5vZGVUeXBlICkge1xuXHRcdFx0XHRvd25lclsgdGhpcy5leHBhbmRvIF0gPSB1bmRlZmluZWQ7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRkZWxldGUgb3duZXJbIHRoaXMuZXhwYW5kbyBdO1xuXHRcdFx0fVxuXHRcdH1cblx0fSxcblx0aGFzRGF0YTogZnVuY3Rpb24oIG93bmVyICkge1xuXHRcdHZhciBjYWNoZSA9IG93bmVyWyB0aGlzLmV4cGFuZG8gXTtcblx0XHRyZXR1cm4gY2FjaGUgIT09IHVuZGVmaW5lZCAmJiAhalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGNhY2hlICk7XG5cdH1cbn07XG52YXIgZGF0YVByaXYgPSBuZXcgRGF0YSgpO1xuXG52YXIgZGF0YVVzZXIgPSBuZXcgRGF0YSgpO1xuXG5cblxuLy9cdEltcGxlbWVudGF0aW9uIFN1bW1hcnlcbi8vXG4vL1x0MS4gRW5mb3JjZSBBUEkgc3VyZmFjZSBhbmQgc2VtYW50aWMgY29tcGF0aWJpbGl0eSB3aXRoIDEuOS54IGJyYW5jaFxuLy9cdDIuIEltcHJvdmUgdGhlIG1vZHVsZSdzIG1haW50YWluYWJpbGl0eSBieSByZWR1Y2luZyB0aGUgc3RvcmFnZVxuLy9cdFx0cGF0aHMgdG8gYSBzaW5nbGUgbWVjaGFuaXNtLlxuLy9cdDMuIFVzZSB0aGUgc2FtZSBzaW5nbGUgbWVjaGFuaXNtIHRvIHN1cHBvcnQgXCJwcml2YXRlXCIgYW5kIFwidXNlclwiIGRhdGEuXG4vL1x0NC4gX05ldmVyXyBleHBvc2UgXCJwcml2YXRlXCIgZGF0YSB0byB1c2VyIGNvZGUgKFRPRE86IERyb3AgX2RhdGEsIF9yZW1vdmVEYXRhKVxuLy9cdDUuIEF2b2lkIGV4cG9zaW5nIGltcGxlbWVudGF0aW9uIGRldGFpbHMgb24gdXNlciBvYmplY3RzIChlZy4gZXhwYW5kbyBwcm9wZXJ0aWVzKVxuLy9cdDYuIFByb3ZpZGUgYSBjbGVhciBwYXRoIGZvciBpbXBsZW1lbnRhdGlvbiB1cGdyYWRlIHRvIFdlYWtNYXAgaW4gMjAxNFxuXG52YXIgcmJyYWNlID0gL14oPzpcXHtbXFx3XFxXXSpcXH18XFxbW1xcd1xcV10qXFxdKSQvLFxuXHRybXVsdGlEYXNoID0gL1tBLVpdL2c7XG5cbmZ1bmN0aW9uIGdldERhdGEoIGRhdGEgKSB7XG5cdGlmICggZGF0YSA9PT0gXCJ0cnVlXCIgKSB7XG5cdFx0cmV0dXJuIHRydWU7XG5cdH1cblxuXHRpZiAoIGRhdGEgPT09IFwiZmFsc2VcIiApIHtcblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRpZiAoIGRhdGEgPT09IFwibnVsbFwiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gT25seSBjb252ZXJ0IHRvIGEgbnVtYmVyIGlmIGl0IGRvZXNuJ3QgY2hhbmdlIHRoZSBzdHJpbmdcblx0aWYgKCBkYXRhID09PSArZGF0YSArIFwiXCIgKSB7XG5cdFx0cmV0dXJuICtkYXRhO1xuXHR9XG5cblx0aWYgKCByYnJhY2UudGVzdCggZGF0YSApICkge1xuXHRcdHJldHVybiBKU09OLnBhcnNlKCBkYXRhICk7XG5cdH1cblxuXHRyZXR1cm4gZGF0YTtcbn1cblxuZnVuY3Rpb24gZGF0YUF0dHIoIGVsZW0sIGtleSwgZGF0YSApIHtcblx0dmFyIG5hbWU7XG5cblx0Ly8gSWYgbm90aGluZyB3YXMgZm91bmQgaW50ZXJuYWxseSwgdHJ5IHRvIGZldGNoIGFueVxuXHQvLyBkYXRhIGZyb20gdGhlIEhUTUw1IGRhdGEtKiBhdHRyaWJ1dGVcblx0aWYgKCBkYXRhID09PSB1bmRlZmluZWQgJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRuYW1lID0gXCJkYXRhLVwiICsga2V5LnJlcGxhY2UoIHJtdWx0aURhc2gsIFwiLSQmXCIgKS50b0xvd2VyQ2FzZSgpO1xuXHRcdGRhdGEgPSBlbGVtLmdldEF0dHJpYnV0ZSggbmFtZSApO1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YSA9PT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdGRhdGEgPSBnZXREYXRhKCBkYXRhICk7XG5cdFx0XHR9IGNhdGNoICggZSApIHt9XG5cblx0XHRcdC8vIE1ha2Ugc3VyZSB3ZSBzZXQgdGhlIGRhdGEgc28gaXQgaXNuJ3QgY2hhbmdlZCBsYXRlclxuXHRcdFx0ZGF0YVVzZXIuc2V0KCBlbGVtLCBrZXksIGRhdGEgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0ZGF0YSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdH1cblx0cmV0dXJuIGRhdGE7XG59XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0aGFzRGF0YTogZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0cmV0dXJuIGRhdGFVc2VyLmhhc0RhdGEoIGVsZW0gKSB8fCBkYXRhUHJpdi5oYXNEYXRhKCBlbGVtICk7XG5cdH0sXG5cblx0ZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFVc2VyLmFjY2VzcyggZWxlbSwgbmFtZSwgZGF0YSApO1xuXHR9LFxuXG5cdHJlbW92ZURhdGE6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lICkge1xuXHRcdGRhdGFVc2VyLnJlbW92ZSggZWxlbSwgbmFtZSApO1xuXHR9LFxuXG5cdC8vIFRPRE86IE5vdyB0aGF0IGFsbCBjYWxscyB0byBfZGF0YSBhbmQgX3JlbW92ZURhdGEgaGF2ZSBiZWVuIHJlcGxhY2VkXG5cdC8vIHdpdGggZGlyZWN0IGNhbGxzIHRvIGRhdGFQcml2IG1ldGhvZHMsIHRoZXNlIGNhbiBiZSBkZXByZWNhdGVkLlxuXHRfZGF0YTogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGRhdGEgKSB7XG5cdFx0cmV0dXJuIGRhdGFQcml2LmFjY2VzcyggZWxlbSwgbmFtZSwgZGF0YSApO1xuXHR9LFxuXG5cdF9yZW1vdmVEYXRhOiBmdW5jdGlvbiggZWxlbSwgbmFtZSApIHtcblx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIG5hbWUgKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGRhdGE6IGZ1bmN0aW9uKCBrZXksIHZhbHVlICkge1xuXHRcdHZhciBpLCBuYW1lLCBkYXRhLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXSxcblx0XHRcdGF0dHJzID0gZWxlbSAmJiBlbGVtLmF0dHJpYnV0ZXM7XG5cblx0XHQvLyBHZXRzIGFsbCB2YWx1ZXNcblx0XHRpZiAoIGtleSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0aWYgKCB0aGlzLmxlbmd0aCApIHtcblx0XHRcdFx0ZGF0YSA9IGRhdGFVc2VyLmdldCggZWxlbSApO1xuXG5cdFx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAhZGF0YVByaXYuZ2V0KCBlbGVtLCBcImhhc0RhdGFBdHRyc1wiICkgKSB7XG5cdFx0XHRcdFx0aSA9IGF0dHJzLmxlbmd0aDtcblx0XHRcdFx0XHR3aGlsZSAoIGktLSApIHtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgMTEgb25seVxuXHRcdFx0XHRcdFx0Ly8gVGhlIGF0dHJzIGVsZW1lbnRzIGNhbiBiZSBudWxsICgjMTQ4OTQpXG5cdFx0XHRcdFx0XHRpZiAoIGF0dHJzWyBpIF0gKSB7XG5cdFx0XHRcdFx0XHRcdG5hbWUgPSBhdHRyc1sgaSBdLm5hbWU7XG5cdFx0XHRcdFx0XHRcdGlmICggbmFtZS5pbmRleE9mKCBcImRhdGEtXCIgKSA9PT0gMCApIHtcblx0XHRcdFx0XHRcdFx0XHRuYW1lID0galF1ZXJ5LmNhbWVsQ2FzZSggbmFtZS5zbGljZSggNSApICk7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YUF0dHIoIGVsZW0sIG5hbWUsIGRhdGFbIG5hbWUgXSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGRhdGFQcml2LnNldCggZWxlbSwgXCJoYXNEYXRhQXR0cnNcIiwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBkYXRhO1xuXHRcdH1cblxuXHRcdC8vIFNldHMgbXVsdGlwbGUgdmFsdWVzXG5cdFx0aWYgKCB0eXBlb2Yga2V5ID09PSBcIm9iamVjdFwiICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRhdGFVc2VyLnNldCggdGhpcywga2V5ICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0dmFyIGRhdGE7XG5cblx0XHRcdC8vIFRoZSBjYWxsaW5nIGpRdWVyeSBvYmplY3QgKGVsZW1lbnQgbWF0Y2hlcykgaXMgbm90IGVtcHR5XG5cdFx0XHQvLyAoYW5kIHRoZXJlZm9yZSBoYXMgYW4gZWxlbWVudCBhcHBlYXJzIGF0IHRoaXNbIDAgXSkgYW5kIHRoZVxuXHRcdFx0Ly8gYHZhbHVlYCBwYXJhbWV0ZXIgd2FzIG5vdCB1bmRlZmluZWQuIEFuIGVtcHR5IGpRdWVyeSBvYmplY3Rcblx0XHRcdC8vIHdpbGwgcmVzdWx0IGluIGB1bmRlZmluZWRgIGZvciBlbGVtID0gdGhpc1sgMCBdIHdoaWNoIHdpbGxcblx0XHRcdC8vIHRocm93IGFuIGV4Y2VwdGlvbiBpZiBhbiBhdHRlbXB0IHRvIHJlYWQgYSBkYXRhIGNhY2hlIGlzIG1hZGUuXG5cdFx0XHRpZiAoIGVsZW0gJiYgdmFsdWUgPT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHQvLyBBdHRlbXB0IHRvIGdldCBkYXRhIGZyb20gdGhlIGNhY2hlXG5cdFx0XHRcdC8vIFRoZSBrZXkgd2lsbCBhbHdheXMgYmUgY2FtZWxDYXNlZCBpbiBEYXRhXG5cdFx0XHRcdGRhdGEgPSBkYXRhVXNlci5nZXQoIGVsZW0sIGtleSApO1xuXHRcdFx0XHRpZiAoIGRhdGEgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gZGF0YTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEF0dGVtcHQgdG8gXCJkaXNjb3ZlclwiIHRoZSBkYXRhIGluXG5cdFx0XHRcdC8vIEhUTUw1IGN1c3RvbSBkYXRhLSogYXR0cnNcblx0XHRcdFx0ZGF0YSA9IGRhdGFBdHRyKCBlbGVtLCBrZXkgKTtcblx0XHRcdFx0aWYgKCBkYXRhICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBXZSB0cmllZCByZWFsbHkgaGFyZCwgYnV0IHRoZSBkYXRhIGRvZXNuJ3QgZXhpc3QuXG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IHRoZSBkYXRhLi4uXG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXG5cdFx0XHRcdC8vIFdlIGFsd2F5cyBzdG9yZSB0aGUgY2FtZWxDYXNlZCBrZXlcblx0XHRcdFx0ZGF0YVVzZXIuc2V0KCB0aGlzLCBrZXksIHZhbHVlICk7XG5cdFx0XHR9ICk7XG5cdFx0fSwgbnVsbCwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxLCBudWxsLCB0cnVlICk7XG5cdH0sXG5cblx0cmVtb3ZlRGF0YTogZnVuY3Rpb24oIGtleSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGRhdGFVc2VyLnJlbW92ZSggdGhpcywga2V5ICk7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cblxualF1ZXJ5LmV4dGVuZCgge1xuXHRxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIHF1ZXVlO1xuXG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0dHlwZSA9ICggdHlwZSB8fCBcImZ4XCIgKSArIFwicXVldWVcIjtcblx0XHRcdHF1ZXVlID0gZGF0YVByaXYuZ2V0KCBlbGVtLCB0eXBlICk7XG5cblx0XHRcdC8vIFNwZWVkIHVwIGRlcXVldWUgYnkgZ2V0dGluZyBvdXQgcXVpY2tseSBpZiB0aGlzIGlzIGp1c3QgYSBsb29rdXBcblx0XHRcdGlmICggZGF0YSApIHtcblx0XHRcdFx0aWYgKCAhcXVldWUgfHwgQXJyYXkuaXNBcnJheSggZGF0YSApICkge1xuXHRcdFx0XHRcdHF1ZXVlID0gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCB0eXBlLCBqUXVlcnkubWFrZUFycmF5KCBkYXRhICkgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRxdWV1ZS5wdXNoKCBkYXRhICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBxdWV1ZSB8fCBbXTtcblx0XHR9XG5cdH0sXG5cblx0ZGVxdWV1ZTogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdFx0dmFyIHF1ZXVlID0galF1ZXJ5LnF1ZXVlKCBlbGVtLCB0eXBlICksXG5cdFx0XHRzdGFydExlbmd0aCA9IHF1ZXVlLmxlbmd0aCxcblx0XHRcdGZuID0gcXVldWUuc2hpZnQoKSxcblx0XHRcdGhvb2tzID0galF1ZXJ5Ll9xdWV1ZUhvb2tzKCBlbGVtLCB0eXBlICksXG5cdFx0XHRuZXh0ID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGpRdWVyeS5kZXF1ZXVlKCBlbGVtLCB0eXBlICk7XG5cdFx0XHR9O1xuXG5cdFx0Ly8gSWYgdGhlIGZ4IHF1ZXVlIGlzIGRlcXVldWVkLCBhbHdheXMgcmVtb3ZlIHRoZSBwcm9ncmVzcyBzZW50aW5lbFxuXHRcdGlmICggZm4gPT09IFwiaW5wcm9ncmVzc1wiICkge1xuXHRcdFx0Zm4gPSBxdWV1ZS5zaGlmdCgpO1xuXHRcdFx0c3RhcnRMZW5ndGgtLTtcblx0XHR9XG5cblx0XHRpZiAoIGZuICkge1xuXG5cdFx0XHQvLyBBZGQgYSBwcm9ncmVzcyBzZW50aW5lbCB0byBwcmV2ZW50IHRoZSBmeCBxdWV1ZSBmcm9tIGJlaW5nXG5cdFx0XHQvLyBhdXRvbWF0aWNhbGx5IGRlcXVldWVkXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiApIHtcblx0XHRcdFx0cXVldWUudW5zaGlmdCggXCJpbnByb2dyZXNzXCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ2xlYXIgdXAgdGhlIGxhc3QgcXVldWUgc3RvcCBmdW5jdGlvblxuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRmbi5jYWxsKCBlbGVtLCBuZXh0LCBob29rcyApO1xuXHRcdH1cblxuXHRcdGlmICggIXN0YXJ0TGVuZ3RoICYmIGhvb2tzICkge1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSgpO1xuXHRcdH1cblx0fSxcblxuXHQvLyBOb3QgcHVibGljIC0gZ2VuZXJhdGUgYSBxdWV1ZUhvb2tzIG9iamVjdCwgb3IgcmV0dXJuIHRoZSBjdXJyZW50IG9uZVxuXHRfcXVldWVIb29rczogZnVuY3Rpb24oIGVsZW0sIHR5cGUgKSB7XG5cdFx0dmFyIGtleSA9IHR5cGUgKyBcInF1ZXVlSG9va3NcIjtcblx0XHRyZXR1cm4gZGF0YVByaXYuZ2V0KCBlbGVtLCBrZXkgKSB8fCBkYXRhUHJpdi5hY2Nlc3MoIGVsZW0sIGtleSwge1xuXHRcdFx0ZW1wdHk6IGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLmFkZCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZWxlbSwgWyB0eXBlICsgXCJxdWV1ZVwiLCBrZXkgXSApO1xuXHRcdFx0fSApXG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0cXVldWU6IGZ1bmN0aW9uKCB0eXBlLCBkYXRhICkge1xuXHRcdHZhciBzZXR0ZXIgPSAyO1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdGRhdGEgPSB0eXBlO1xuXHRcdFx0dHlwZSA9IFwiZnhcIjtcblx0XHRcdHNldHRlci0tO1xuXHRcdH1cblxuXHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCA8IHNldHRlciApIHtcblx0XHRcdHJldHVybiBqUXVlcnkucXVldWUoIHRoaXNbIDAgXSwgdHlwZSApO1xuXHRcdH1cblxuXHRcdHJldHVybiBkYXRhID09PSB1bmRlZmluZWQgP1xuXHRcdFx0dGhpcyA6XG5cdFx0XHR0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHR2YXIgcXVldWUgPSBqUXVlcnkucXVldWUoIHRoaXMsIHR5cGUsIGRhdGEgKTtcblxuXHRcdFx0XHQvLyBFbnN1cmUgYSBob29rcyBmb3IgdGhpcyBxdWV1ZVxuXHRcdFx0XHRqUXVlcnkuX3F1ZXVlSG9va3MoIHRoaXMsIHR5cGUgKTtcblxuXHRcdFx0XHRpZiAoIHR5cGUgPT09IFwiZnhcIiAmJiBxdWV1ZVsgMCBdICE9PSBcImlucHJvZ3Jlc3NcIiApIHtcblx0XHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdH0sXG5cdGRlcXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIHR5cGUgKTtcblx0XHR9ICk7XG5cdH0sXG5cdGNsZWFyUXVldWU6IGZ1bmN0aW9uKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlIHx8IFwiZnhcIiwgW10gKTtcblx0fSxcblxuXHQvLyBHZXQgYSBwcm9taXNlIHJlc29sdmVkIHdoZW4gcXVldWVzIG9mIGEgY2VydGFpbiB0eXBlXG5cdC8vIGFyZSBlbXB0aWVkIChmeCBpcyB0aGUgdHlwZSBieSBkZWZhdWx0KVxuXHRwcm9taXNlOiBmdW5jdGlvbiggdHlwZSwgb2JqICkge1xuXHRcdHZhciB0bXAsXG5cdFx0XHRjb3VudCA9IDEsXG5cdFx0XHRkZWZlciA9IGpRdWVyeS5EZWZlcnJlZCgpLFxuXHRcdFx0ZWxlbWVudHMgPSB0aGlzLFxuXHRcdFx0aSA9IHRoaXMubGVuZ3RoLFxuXHRcdFx0cmVzb2x2ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICEoIC0tY291bnQgKSApIHtcblx0XHRcdFx0XHRkZWZlci5yZXNvbHZlV2l0aCggZWxlbWVudHMsIFsgZWxlbWVudHMgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXG5cdFx0aWYgKCB0eXBlb2YgdHlwZSAhPT0gXCJzdHJpbmdcIiApIHtcblx0XHRcdG9iaiA9IHR5cGU7XG5cdFx0XHR0eXBlID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0XHR0eXBlID0gdHlwZSB8fCBcImZ4XCI7XG5cblx0XHR3aGlsZSAoIGktLSApIHtcblx0XHRcdHRtcCA9IGRhdGFQcml2LmdldCggZWxlbWVudHNbIGkgXSwgdHlwZSArIFwicXVldWVIb29rc1wiICk7XG5cdFx0XHRpZiAoIHRtcCAmJiB0bXAuZW1wdHkgKSB7XG5cdFx0XHRcdGNvdW50Kys7XG5cdFx0XHRcdHRtcC5lbXB0eS5hZGQoIHJlc29sdmUgKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmVzb2x2ZSgpO1xuXHRcdHJldHVybiBkZWZlci5wcm9taXNlKCBvYmogKTtcblx0fVxufSApO1xudmFyIHBudW0gPSAoIC9bKy1dPyg/OlxcZCpcXC58KVxcZCsoPzpbZUVdWystXT9cXGQrfCkvICkuc291cmNlO1xuXG52YXIgcmNzc051bSA9IG5ldyBSZWdFeHAoIFwiXig/OihbKy1dKT18KShcIiArIHBudW0gKyBcIikoW2EteiVdKikkXCIsIFwiaVwiICk7XG5cblxudmFyIGNzc0V4cGFuZCA9IFsgXCJUb3BcIiwgXCJSaWdodFwiLCBcIkJvdHRvbVwiLCBcIkxlZnRcIiBdO1xuXG52YXIgaXNIaWRkZW5XaXRoaW5UcmVlID0gZnVuY3Rpb24oIGVsZW0sIGVsICkge1xuXG5cdFx0Ly8gaXNIaWRkZW5XaXRoaW5UcmVlIG1pZ2h0IGJlIGNhbGxlZCBmcm9tIGpRdWVyeSNmaWx0ZXIgZnVuY3Rpb247XG5cdFx0Ly8gaW4gdGhhdCBjYXNlLCBlbGVtZW50IHdpbGwgYmUgc2Vjb25kIGFyZ3VtZW50XG5cdFx0ZWxlbSA9IGVsIHx8IGVsZW07XG5cblx0XHQvLyBJbmxpbmUgc3R5bGUgdHJ1bXBzIGFsbFxuXHRcdHJldHVybiBlbGVtLnN0eWxlLmRpc3BsYXkgPT09IFwibm9uZVwiIHx8XG5cdFx0XHRlbGVtLnN0eWxlLmRpc3BsYXkgPT09IFwiXCIgJiZcblxuXHRcdFx0Ly8gT3RoZXJ3aXNlLCBjaGVjayBjb21wdXRlZCBzdHlsZVxuXHRcdFx0Ly8gU3VwcG9ydDogRmlyZWZveCA8PTQzIC0gNDVcblx0XHRcdC8vIERpc2Nvbm5lY3RlZCBlbGVtZW50cyBjYW4gaGF2ZSBjb21wdXRlZCBkaXNwbGF5OiBub25lLCBzbyBmaXJzdCBjb25maXJtIHRoYXQgZWxlbSBpc1xuXHRcdFx0Ly8gaW4gdGhlIGRvY3VtZW50LlxuXHRcdFx0alF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKSAmJlxuXG5cdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBcImRpc3BsYXlcIiApID09PSBcIm5vbmVcIjtcblx0fTtcblxudmFyIHN3YXAgPSBmdW5jdGlvbiggZWxlbSwgb3B0aW9ucywgY2FsbGJhY2ssIGFyZ3MgKSB7XG5cdHZhciByZXQsIG5hbWUsXG5cdFx0b2xkID0ge307XG5cblx0Ly8gUmVtZW1iZXIgdGhlIG9sZCB2YWx1ZXMsIGFuZCBpbnNlcnQgdGhlIG5ldyBvbmVzXG5cdGZvciAoIG5hbWUgaW4gb3B0aW9ucyApIHtcblx0XHRvbGRbIG5hbWUgXSA9IGVsZW0uc3R5bGVbIG5hbWUgXTtcblx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSBvcHRpb25zWyBuYW1lIF07XG5cdH1cblxuXHRyZXQgPSBjYWxsYmFjay5hcHBseSggZWxlbSwgYXJncyB8fCBbXSApO1xuXG5cdC8vIFJldmVydCB0aGUgb2xkIHZhbHVlc1xuXHRmb3IgKCBuYW1lIGluIG9wdGlvbnMgKSB7XG5cdFx0ZWxlbS5zdHlsZVsgbmFtZSBdID0gb2xkWyBuYW1lIF07XG5cdH1cblxuXHRyZXR1cm4gcmV0O1xufTtcblxuXG5cblxuZnVuY3Rpb24gYWRqdXN0Q1NTKCBlbGVtLCBwcm9wLCB2YWx1ZVBhcnRzLCB0d2VlbiApIHtcblx0dmFyIGFkanVzdGVkLFxuXHRcdHNjYWxlID0gMSxcblx0XHRtYXhJdGVyYXRpb25zID0gMjAsXG5cdFx0Y3VycmVudFZhbHVlID0gdHdlZW4gP1xuXHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiB0d2Vlbi5jdXIoKTtcblx0XHRcdH0gOlxuXHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkuY3NzKCBlbGVtLCBwcm9wLCBcIlwiICk7XG5cdFx0XHR9LFxuXHRcdGluaXRpYWwgPSBjdXJyZW50VmFsdWUoKSxcblx0XHR1bml0ID0gdmFsdWVQYXJ0cyAmJiB2YWx1ZVBhcnRzWyAzIF0gfHwgKCBqUXVlcnkuY3NzTnVtYmVyWyBwcm9wIF0gPyBcIlwiIDogXCJweFwiICksXG5cblx0XHQvLyBTdGFydGluZyB2YWx1ZSBjb21wdXRhdGlvbiBpcyByZXF1aXJlZCBmb3IgcG90ZW50aWFsIHVuaXQgbWlzbWF0Y2hlc1xuXHRcdGluaXRpYWxJblVuaXQgPSAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSB8fCB1bml0ICE9PSBcInB4XCIgJiYgK2luaXRpYWwgKSAmJlxuXHRcdFx0cmNzc051bS5leGVjKCBqUXVlcnkuY3NzKCBlbGVtLCBwcm9wICkgKTtcblxuXHRpZiAoIGluaXRpYWxJblVuaXQgJiYgaW5pdGlhbEluVW5pdFsgMyBdICE9PSB1bml0ICkge1xuXG5cdFx0Ly8gVHJ1c3QgdW5pdHMgcmVwb3J0ZWQgYnkgalF1ZXJ5LmNzc1xuXHRcdHVuaXQgPSB1bml0IHx8IGluaXRpYWxJblVuaXRbIDMgXTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB3ZSB1cGRhdGUgdGhlIHR3ZWVuIHByb3BlcnRpZXMgbGF0ZXIgb25cblx0XHR2YWx1ZVBhcnRzID0gdmFsdWVQYXJ0cyB8fCBbXTtcblxuXHRcdC8vIEl0ZXJhdGl2ZWx5IGFwcHJveGltYXRlIGZyb20gYSBub256ZXJvIHN0YXJ0aW5nIHBvaW50XG5cdFx0aW5pdGlhbEluVW5pdCA9ICtpbml0aWFsIHx8IDE7XG5cblx0XHRkbyB7XG5cblx0XHRcdC8vIElmIHByZXZpb3VzIGl0ZXJhdGlvbiB6ZXJvZWQgb3V0LCBkb3VibGUgdW50aWwgd2UgZ2V0ICpzb21ldGhpbmcqLlxuXHRcdFx0Ly8gVXNlIHN0cmluZyBmb3IgZG91Ymxpbmcgc28gd2UgZG9uJ3QgYWNjaWRlbnRhbGx5IHNlZSBzY2FsZSBhcyB1bmNoYW5nZWQgYmVsb3dcblx0XHRcdHNjYWxlID0gc2NhbGUgfHwgXCIuNVwiO1xuXG5cdFx0XHQvLyBBZGp1c3QgYW5kIGFwcGx5XG5cdFx0XHRpbml0aWFsSW5Vbml0ID0gaW5pdGlhbEluVW5pdCAvIHNjYWxlO1xuXHRcdFx0alF1ZXJ5LnN0eWxlKCBlbGVtLCBwcm9wLCBpbml0aWFsSW5Vbml0ICsgdW5pdCApO1xuXG5cdFx0Ly8gVXBkYXRlIHNjYWxlLCB0b2xlcmF0aW5nIHplcm8gb3IgTmFOIGZyb20gdHdlZW4uY3VyKClcblx0XHQvLyBCcmVhayB0aGUgbG9vcCBpZiBzY2FsZSBpcyB1bmNoYW5nZWQgb3IgcGVyZmVjdCwgb3IgaWYgd2UndmUganVzdCBoYWQgZW5vdWdoLlxuXHRcdH0gd2hpbGUgKFxuXHRcdFx0c2NhbGUgIT09ICggc2NhbGUgPSBjdXJyZW50VmFsdWUoKSAvIGluaXRpYWwgKSAmJiBzY2FsZSAhPT0gMSAmJiAtLW1heEl0ZXJhdGlvbnNcblx0XHQpO1xuXHR9XG5cblx0aWYgKCB2YWx1ZVBhcnRzICkge1xuXHRcdGluaXRpYWxJblVuaXQgPSAraW5pdGlhbEluVW5pdCB8fCAraW5pdGlhbCB8fCAwO1xuXG5cdFx0Ly8gQXBwbHkgcmVsYXRpdmUgb2Zmc2V0ICgrPS8tPSkgaWYgc3BlY2lmaWVkXG5cdFx0YWRqdXN0ZWQgPSB2YWx1ZVBhcnRzWyAxIF0gP1xuXHRcdFx0aW5pdGlhbEluVW5pdCArICggdmFsdWVQYXJ0c1sgMSBdICsgMSApICogdmFsdWVQYXJ0c1sgMiBdIDpcblx0XHRcdCt2YWx1ZVBhcnRzWyAyIF07XG5cdFx0aWYgKCB0d2VlbiApIHtcblx0XHRcdHR3ZWVuLnVuaXQgPSB1bml0O1xuXHRcdFx0dHdlZW4uc3RhcnQgPSBpbml0aWFsSW5Vbml0O1xuXHRcdFx0dHdlZW4uZW5kID0gYWRqdXN0ZWQ7XG5cdFx0fVxuXHR9XG5cdHJldHVybiBhZGp1c3RlZDtcbn1cblxuXG52YXIgZGVmYXVsdERpc3BsYXlNYXAgPSB7fTtcblxuZnVuY3Rpb24gZ2V0RGVmYXVsdERpc3BsYXkoIGVsZW0gKSB7XG5cdHZhciB0ZW1wLFxuXHRcdGRvYyA9IGVsZW0ub3duZXJEb2N1bWVudCxcblx0XHRub2RlTmFtZSA9IGVsZW0ubm9kZU5hbWUsXG5cdFx0ZGlzcGxheSA9IGRlZmF1bHREaXNwbGF5TWFwWyBub2RlTmFtZSBdO1xuXG5cdGlmICggZGlzcGxheSApIHtcblx0XHRyZXR1cm4gZGlzcGxheTtcblx0fVxuXG5cdHRlbXAgPSBkb2MuYm9keS5hcHBlbmRDaGlsZCggZG9jLmNyZWF0ZUVsZW1lbnQoIG5vZGVOYW1lICkgKTtcblx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIHRlbXAsIFwiZGlzcGxheVwiICk7XG5cblx0dGVtcC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCB0ZW1wICk7XG5cblx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRkaXNwbGF5ID0gXCJibG9ja1wiO1xuXHR9XG5cdGRlZmF1bHREaXNwbGF5TWFwWyBub2RlTmFtZSBdID0gZGlzcGxheTtcblxuXHRyZXR1cm4gZGlzcGxheTtcbn1cblxuZnVuY3Rpb24gc2hvd0hpZGUoIGVsZW1lbnRzLCBzaG93ICkge1xuXHR2YXIgZGlzcGxheSwgZWxlbSxcblx0XHR2YWx1ZXMgPSBbXSxcblx0XHRpbmRleCA9IDAsXG5cdFx0bGVuZ3RoID0gZWxlbWVudHMubGVuZ3RoO1xuXG5cdC8vIERldGVybWluZSBuZXcgZGlzcGxheSB2YWx1ZSBmb3IgZWxlbWVudHMgdGhhdCBuZWVkIHRvIGNoYW5nZVxuXHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGVsZW0gPSBlbGVtZW50c1sgaW5kZXggXTtcblx0XHRpZiAoICFlbGVtLnN0eWxlICkge1xuXHRcdFx0Y29udGludWU7XG5cdFx0fVxuXG5cdFx0ZGlzcGxheSA9IGVsZW0uc3R5bGUuZGlzcGxheTtcblx0XHRpZiAoIHNob3cgKSB7XG5cblx0XHRcdC8vIFNpbmNlIHdlIGZvcmNlIHZpc2liaWxpdHkgdXBvbiBjYXNjYWRlLWhpZGRlbiBlbGVtZW50cywgYW4gaW1tZWRpYXRlIChhbmQgc2xvdylcblx0XHRcdC8vIGNoZWNrIGlzIHJlcXVpcmVkIGluIHRoaXMgZmlyc3QgbG9vcCB1bmxlc3Mgd2UgaGF2ZSBhIG5vbmVtcHR5IGRpc3BsYXkgdmFsdWUgKGVpdGhlclxuXHRcdFx0Ly8gaW5saW5lIG9yIGFib3V0LXRvLWJlLXJlc3RvcmVkKVxuXHRcdFx0aWYgKCBkaXNwbGF5ID09PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImRpc3BsYXlcIiApIHx8IG51bGw7XG5cdFx0XHRcdGlmICggIXZhbHVlc1sgaW5kZXggXSApIHtcblx0XHRcdFx0XHRlbGVtLnN0eWxlLmRpc3BsYXkgPSBcIlwiO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAoIGVsZW0uc3R5bGUuZGlzcGxheSA9PT0gXCJcIiAmJiBpc0hpZGRlbldpdGhpblRyZWUoIGVsZW0gKSApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gZ2V0RGVmYXVsdERpc3BsYXkoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0aWYgKCBkaXNwbGF5ICE9PSBcIm5vbmVcIiApIHtcblx0XHRcdFx0dmFsdWVzWyBpbmRleCBdID0gXCJub25lXCI7XG5cblx0XHRcdFx0Ly8gUmVtZW1iZXIgd2hhdCB3ZSdyZSBvdmVyd3JpdGluZ1xuXHRcdFx0XHRkYXRhUHJpdi5zZXQoIGVsZW0sIFwiZGlzcGxheVwiLCBkaXNwbGF5ICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gU2V0IHRoZSBkaXNwbGF5IG9mIHRoZSBlbGVtZW50cyBpbiBhIHNlY29uZCBsb29wIHRvIGF2b2lkIGNvbnN0YW50IHJlZmxvd1xuXHRmb3IgKCBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdGlmICggdmFsdWVzWyBpbmRleCBdICE9IG51bGwgKSB7XG5cdFx0XHRlbGVtZW50c1sgaW5kZXggXS5zdHlsZS5kaXNwbGF5ID0gdmFsdWVzWyBpbmRleCBdO1xuXHRcdH1cblx0fVxuXG5cdHJldHVybiBlbGVtZW50cztcbn1cblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRzaG93OiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gc2hvd0hpZGUoIHRoaXMsIHRydWUgKTtcblx0fSxcblx0aGlkZTogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHNob3dIaWRlKCB0aGlzICk7XG5cdH0sXG5cdHRvZ2dsZTogZnVuY3Rpb24oIHN0YXRlICkge1xuXHRcdGlmICggdHlwZW9mIHN0YXRlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdHJldHVybiBzdGF0ZSA/IHRoaXMuc2hvdygpIDogdGhpcy5oaWRlKCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIGlzSGlkZGVuV2l0aGluVHJlZSggdGhpcyApICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5zaG93KCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5oaWRlKCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG59ICk7XG52YXIgcmNoZWNrYWJsZVR5cGUgPSAoIC9eKD86Y2hlY2tib3h8cmFkaW8pJC9pICk7XG5cbnZhciBydGFnTmFtZSA9ICggLzwoW2Etel1bXlxcL1xcMD5cXHgyMFxcdFxcclxcblxcZl0rKS9pICk7XG5cbnZhciByc2NyaXB0VHlwZSA9ICggL14kfFxcLyg/OmphdmF8ZWNtYSlzY3JpcHQvaSApO1xuXG5cblxuLy8gV2UgaGF2ZSB0byBjbG9zZSB0aGVzZSB0YWdzIHRvIHN1cHBvcnQgWEhUTUwgKCMxMzIwMClcbnZhciB3cmFwTWFwID0ge1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdG9wdGlvbjogWyAxLCBcIjxzZWxlY3QgbXVsdGlwbGU9J211bHRpcGxlJz5cIiwgXCI8L3NlbGVjdD5cIiBdLFxuXG5cdC8vIFhIVE1MIHBhcnNlcnMgZG8gbm90IG1hZ2ljYWxseSBpbnNlcnQgZWxlbWVudHMgaW4gdGhlXG5cdC8vIHNhbWUgd2F5IHRoYXQgdGFnIHNvdXAgcGFyc2VycyBkby4gU28gd2UgY2Fubm90IHNob3J0ZW5cblx0Ly8gdGhpcyBieSBvbWl0dGluZyA8dGJvZHk+IG9yIG90aGVyIHJlcXVpcmVkIGVsZW1lbnRzLlxuXHR0aGVhZDogWyAxLCBcIjx0YWJsZT5cIiwgXCI8L3RhYmxlPlwiIF0sXG5cdGNvbDogWyAyLCBcIjx0YWJsZT48Y29sZ3JvdXA+XCIsIFwiPC9jb2xncm91cD48L3RhYmxlPlwiIF0sXG5cdHRyOiBbIDIsIFwiPHRhYmxlPjx0Ym9keT5cIiwgXCI8L3Rib2R5PjwvdGFibGU+XCIgXSxcblx0dGQ6IFsgMywgXCI8dGFibGU+PHRib2R5Pjx0cj5cIiwgXCI8L3RyPjwvdGJvZHk+PC90YWJsZT5cIiBdLFxuXG5cdF9kZWZhdWx0OiBbIDAsIFwiXCIsIFwiXCIgXVxufTtcblxuLy8gU3VwcG9ydDogSUUgPD05IG9ubHlcbndyYXBNYXAub3B0Z3JvdXAgPSB3cmFwTWFwLm9wdGlvbjtcblxud3JhcE1hcC50Ym9keSA9IHdyYXBNYXAudGZvb3QgPSB3cmFwTWFwLmNvbGdyb3VwID0gd3JhcE1hcC5jYXB0aW9uID0gd3JhcE1hcC50aGVhZDtcbndyYXBNYXAudGggPSB3cmFwTWFwLnRkO1xuXG5cbmZ1bmN0aW9uIGdldEFsbCggY29udGV4dCwgdGFnICkge1xuXG5cdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0Ly8gVXNlIHR5cGVvZiB0byBhdm9pZCB6ZXJvLWFyZ3VtZW50IG1ldGhvZCBpbnZvY2F0aW9uIG9uIGhvc3Qgb2JqZWN0cyAoIzE1MTUxKVxuXHR2YXIgcmV0O1xuXG5cdGlmICggdHlwZW9mIGNvbnRleHQuZ2V0RWxlbWVudHNCeVRhZ05hbWUgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0cmV0ID0gY29udGV4dC5nZXRFbGVtZW50c0J5VGFnTmFtZSggdGFnIHx8IFwiKlwiICk7XG5cblx0fSBlbHNlIGlmICggdHlwZW9mIGNvbnRleHQucXVlcnlTZWxlY3RvckFsbCAhPT0gXCJ1bmRlZmluZWRcIiApIHtcblx0XHRyZXQgPSBjb250ZXh0LnF1ZXJ5U2VsZWN0b3JBbGwoIHRhZyB8fCBcIipcIiApO1xuXG5cdH0gZWxzZSB7XG5cdFx0cmV0ID0gW107XG5cdH1cblxuXHRpZiAoIHRhZyA9PT0gdW5kZWZpbmVkIHx8IHRhZyAmJiBub2RlTmFtZSggY29udGV4dCwgdGFnICkgKSB7XG5cdFx0cmV0dXJuIGpRdWVyeS5tZXJnZSggWyBjb250ZXh0IF0sIHJldCApO1xuXHR9XG5cblx0cmV0dXJuIHJldDtcbn1cblxuXG4vLyBNYXJrIHNjcmlwdHMgYXMgaGF2aW5nIGFscmVhZHkgYmVlbiBldmFsdWF0ZWRcbmZ1bmN0aW9uIHNldEdsb2JhbEV2YWwoIGVsZW1zLCByZWZFbGVtZW50cyApIHtcblx0dmFyIGkgPSAwLFxuXHRcdGwgPSBlbGVtcy5sZW5ndGg7XG5cblx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdGRhdGFQcml2LnNldChcblx0XHRcdGVsZW1zWyBpIF0sXG5cdFx0XHRcImdsb2JhbEV2YWxcIixcblx0XHRcdCFyZWZFbGVtZW50cyB8fCBkYXRhUHJpdi5nZXQoIHJlZkVsZW1lbnRzWyBpIF0sIFwiZ2xvYmFsRXZhbFwiIClcblx0XHQpO1xuXHR9XG59XG5cblxudmFyIHJodG1sID0gLzx8JiM/XFx3KzsvO1xuXG5mdW5jdGlvbiBidWlsZEZyYWdtZW50KCBlbGVtcywgY29udGV4dCwgc2NyaXB0cywgc2VsZWN0aW9uLCBpZ25vcmVkICkge1xuXHR2YXIgZWxlbSwgdG1wLCB0YWcsIHdyYXAsIGNvbnRhaW5zLCBqLFxuXHRcdGZyYWdtZW50ID0gY29udGV4dC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCksXG5cdFx0bm9kZXMgPSBbXSxcblx0XHRpID0gMCxcblx0XHRsID0gZWxlbXMubGVuZ3RoO1xuXG5cdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRlbGVtID0gZWxlbXNbIGkgXTtcblxuXHRcdGlmICggZWxlbSB8fCBlbGVtID09PSAwICkge1xuXG5cdFx0XHQvLyBBZGQgbm9kZXMgZGlyZWN0bHlcblx0XHRcdGlmICggalF1ZXJ5LnR5cGUoIGVsZW0gKSA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4wIG9ubHksIFBoYW50b21KUyAxIG9ubHlcblx0XHRcdFx0Ly8gcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0XHRqUXVlcnkubWVyZ2UoIG5vZGVzLCBlbGVtLm5vZGVUeXBlID8gWyBlbGVtIF0gOiBlbGVtICk7XG5cblx0XHRcdC8vIENvbnZlcnQgbm9uLWh0bWwgaW50byBhIHRleHQgbm9kZVxuXHRcdFx0fSBlbHNlIGlmICggIXJodG1sLnRlc3QoIGVsZW0gKSApIHtcblx0XHRcdFx0bm9kZXMucHVzaCggY29udGV4dC5jcmVhdGVUZXh0Tm9kZSggZWxlbSApICk7XG5cblx0XHRcdC8vIENvbnZlcnQgaHRtbCBpbnRvIERPTSBub2Rlc1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dG1wID0gdG1wIHx8IGZyYWdtZW50LmFwcGVuZENoaWxkKCBjb250ZXh0LmNyZWF0ZUVsZW1lbnQoIFwiZGl2XCIgKSApO1xuXG5cdFx0XHRcdC8vIERlc2VyaWFsaXplIGEgc3RhbmRhcmQgcmVwcmVzZW50YXRpb25cblx0XHRcdFx0dGFnID0gKCBydGFnTmFtZS5leGVjKCBlbGVtICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdHdyYXAgPSB3cmFwTWFwWyB0YWcgXSB8fCB3cmFwTWFwLl9kZWZhdWx0O1xuXHRcdFx0XHR0bXAuaW5uZXJIVE1MID0gd3JhcFsgMSBdICsgalF1ZXJ5Lmh0bWxQcmVmaWx0ZXIoIGVsZW0gKSArIHdyYXBbIDIgXTtcblxuXHRcdFx0XHQvLyBEZXNjZW5kIHRocm91Z2ggd3JhcHBlcnMgdG8gdGhlIHJpZ2h0IGNvbnRlbnRcblx0XHRcdFx0aiA9IHdyYXBbIDAgXTtcblx0XHRcdFx0d2hpbGUgKCBqLS0gKSB7XG5cdFx0XHRcdFx0dG1wID0gdG1wLmxhc3RDaGlsZDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdGpRdWVyeS5tZXJnZSggbm9kZXMsIHRtcC5jaGlsZE5vZGVzICk7XG5cblx0XHRcdFx0Ly8gUmVtZW1iZXIgdGhlIHRvcC1sZXZlbCBjb250YWluZXJcblx0XHRcdFx0dG1wID0gZnJhZ21lbnQuZmlyc3RDaGlsZDtcblxuXHRcdFx0XHQvLyBFbnN1cmUgdGhlIGNyZWF0ZWQgbm9kZXMgYXJlIG9ycGhhbmVkICgjMTIzOTIpXG5cdFx0XHRcdHRtcC50ZXh0Q29udGVudCA9IFwiXCI7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gUmVtb3ZlIHdyYXBwZXIgZnJvbSBmcmFnbWVudFxuXHRmcmFnbWVudC50ZXh0Q29udGVudCA9IFwiXCI7XG5cblx0aSA9IDA7XG5cdHdoaWxlICggKCBlbGVtID0gbm9kZXNbIGkrKyBdICkgKSB7XG5cblx0XHQvLyBTa2lwIGVsZW1lbnRzIGFscmVhZHkgaW4gdGhlIGNvbnRleHQgY29sbGVjdGlvbiAodHJhYy00MDg3KVxuXHRcdGlmICggc2VsZWN0aW9uICYmIGpRdWVyeS5pbkFycmF5KCBlbGVtLCBzZWxlY3Rpb24gKSA+IC0xICkge1xuXHRcdFx0aWYgKCBpZ25vcmVkICkge1xuXHRcdFx0XHRpZ25vcmVkLnB1c2goIGVsZW0gKTtcblx0XHRcdH1cblx0XHRcdGNvbnRpbnVlO1xuXHRcdH1cblxuXHRcdGNvbnRhaW5zID0galF1ZXJ5LmNvbnRhaW5zKCBlbGVtLm93bmVyRG9jdW1lbnQsIGVsZW0gKTtcblxuXHRcdC8vIEFwcGVuZCB0byBmcmFnbWVudFxuXHRcdHRtcCA9IGdldEFsbCggZnJhZ21lbnQuYXBwZW5kQ2hpbGQoIGVsZW0gKSwgXCJzY3JpcHRcIiApO1xuXG5cdFx0Ly8gUHJlc2VydmUgc2NyaXB0IGV2YWx1YXRpb24gaGlzdG9yeVxuXHRcdGlmICggY29udGFpbnMgKSB7XG5cdFx0XHRzZXRHbG9iYWxFdmFsKCB0bXAgKTtcblx0XHR9XG5cblx0XHQvLyBDYXB0dXJlIGV4ZWN1dGFibGVzXG5cdFx0aWYgKCBzY3JpcHRzICkge1xuXHRcdFx0aiA9IDA7XG5cdFx0XHR3aGlsZSAoICggZWxlbSA9IHRtcFsgaisrIF0gKSApIHtcblx0XHRcdFx0aWYgKCByc2NyaXB0VHlwZS50ZXN0KCBlbGVtLnR5cGUgfHwgXCJcIiApICkge1xuXHRcdFx0XHRcdHNjcmlwdHMucHVzaCggZWxlbSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGZyYWdtZW50O1xufVxuXG5cbiggZnVuY3Rpb24oKSB7XG5cdHZhciBmcmFnbWVudCA9IGRvY3VtZW50LmNyZWF0ZURvY3VtZW50RnJhZ21lbnQoKSxcblx0XHRkaXYgPSBmcmFnbWVudC5hcHBlbmRDaGlsZCggZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApICksXG5cdFx0aW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImlucHV0XCIgKTtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDQuMCAtIDQuMyBvbmx5XG5cdC8vIENoZWNrIHN0YXRlIGxvc3QgaWYgdGhlIG5hbWUgaXMgc2V0ICgjMTEyMTcpXG5cdC8vIFN1cHBvcnQ6IFdpbmRvd3MgV2ViIEFwcHMgKFdXQSlcblx0Ly8gYG5hbWVgIGFuZCBgdHlwZWAgbXVzdCB1c2UgLnNldEF0dHJpYnV0ZSBmb3IgV1dBICgjMTQ5MDEpXG5cdGlucHV0LnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIFwicmFkaW9cIiApO1xuXHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwiY2hlY2tlZFwiLCBcImNoZWNrZWRcIiApO1xuXHRpbnB1dC5zZXRBdHRyaWJ1dGUoIFwibmFtZVwiLCBcInRcIiApO1xuXG5cdGRpdi5hcHBlbmRDaGlsZCggaW5wdXQgKTtcblxuXHQvLyBTdXBwb3J0OiBBbmRyb2lkIDw9NC4xIG9ubHlcblx0Ly8gT2xkZXIgV2ViS2l0IGRvZXNuJ3QgY2xvbmUgY2hlY2tlZCBzdGF0ZSBjb3JyZWN0bHkgaW4gZnJhZ21lbnRzXG5cdHN1cHBvcnQuY2hlY2tDbG9uZSA9IGRpdi5jbG9uZU5vZGUoIHRydWUgKS5jbG9uZU5vZGUoIHRydWUgKS5sYXN0Q2hpbGQuY2hlY2tlZDtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gTWFrZSBzdXJlIHRleHRhcmVhIChhbmQgY2hlY2tib3gpIGRlZmF1bHRWYWx1ZSBpcyBwcm9wZXJseSBjbG9uZWRcblx0ZGl2LmlubmVySFRNTCA9IFwiPHRleHRhcmVhPng8L3RleHRhcmVhPlwiO1xuXHRzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkID0gISFkaXYuY2xvbmVOb2RlKCB0cnVlICkubGFzdENoaWxkLmRlZmF1bHRWYWx1ZTtcbn0gKSgpO1xudmFyIGRvY3VtZW50RWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcblxuXG5cbnZhclxuXHRya2V5RXZlbnQgPSAvXmtleS8sXG5cdHJtb3VzZUV2ZW50ID0gL14oPzptb3VzZXxwb2ludGVyfGNvbnRleHRtZW51fGRyYWd8ZHJvcCl8Y2xpY2svLFxuXHRydHlwZW5hbWVzcGFjZSA9IC9eKFteLl0qKSg/OlxcLiguKyl8KS87XG5cbmZ1bmN0aW9uIHJldHVyblRydWUoKSB7XG5cdHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiByZXR1cm5GYWxzZSgpIHtcblx0cmV0dXJuIGZhbHNlO1xufVxuXG4vLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuLy8gU2VlICMxMzM5MyBmb3IgbW9yZSBpbmZvXG5mdW5jdGlvbiBzYWZlQWN0aXZlRWxlbWVudCgpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gZG9jdW1lbnQuYWN0aXZlRWxlbWVudDtcblx0fSBjYXRjaCAoIGVyciApIHsgfVxufVxuXG5mdW5jdGlvbiBvbiggZWxlbSwgdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiwgb25lICkge1xuXHR2YXIgb3JpZ0ZuLCB0eXBlO1xuXG5cdC8vIFR5cGVzIGNhbiBiZSBhIG1hcCBvZiB0eXBlcy9oYW5kbGVyc1xuXHRpZiAoIHR5cGVvZiB0eXBlcyA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdC8vICggdHlwZXMtT2JqZWN0LCBzZWxlY3RvciwgZGF0YSApXG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgIT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMtT2JqZWN0LCBkYXRhIClcblx0XHRcdGRhdGEgPSBkYXRhIHx8IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRvbiggZWxlbSwgdHlwZSwgc2VsZWN0b3IsIGRhdGEsIHR5cGVzWyB0eXBlIF0sIG9uZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gZWxlbTtcblx0fVxuXG5cdGlmICggZGF0YSA9PSBudWxsICYmIGZuID09IG51bGwgKSB7XG5cblx0XHQvLyAoIHR5cGVzLCBmbiApXG5cdFx0Zm4gPSBzZWxlY3Rvcjtcblx0XHRkYXRhID0gc2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdH0gZWxzZSBpZiAoIGZuID09IG51bGwgKSB7XG5cdFx0aWYgKCB0eXBlb2Ygc2VsZWN0b3IgPT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdC8vICggdHlwZXMsIHNlbGVjdG9yLCBmbiApXG5cdFx0XHRmbiA9IGRhdGE7XG5cdFx0XHRkYXRhID0gdW5kZWZpbmVkO1xuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vICggdHlwZXMsIGRhdGEsIGZuIClcblx0XHRcdGZuID0gZGF0YTtcblx0XHRcdGRhdGEgPSBzZWxlY3Rvcjtcblx0XHRcdHNlbGVjdG9yID0gdW5kZWZpbmVkO1xuXHRcdH1cblx0fVxuXHRpZiAoIGZuID09PSBmYWxzZSApIHtcblx0XHRmbiA9IHJldHVybkZhbHNlO1xuXHR9IGVsc2UgaWYgKCAhZm4gKSB7XG5cdFx0cmV0dXJuIGVsZW07XG5cdH1cblxuXHRpZiAoIG9uZSA9PT0gMSApIHtcblx0XHRvcmlnRm4gPSBmbjtcblx0XHRmbiA9IGZ1bmN0aW9uKCBldmVudCApIHtcblxuXHRcdFx0Ly8gQ2FuIHVzZSBhbiBlbXB0eSBzZXQsIHNpbmNlIGV2ZW50IGNvbnRhaW5zIHRoZSBpbmZvXG5cdFx0XHRqUXVlcnkoKS5vZmYoIGV2ZW50ICk7XG5cdFx0XHRyZXR1cm4gb3JpZ0ZuLmFwcGx5KCB0aGlzLCBhcmd1bWVudHMgKTtcblx0XHR9O1xuXG5cdFx0Ly8gVXNlIHNhbWUgZ3VpZCBzbyBjYWxsZXIgY2FuIHJlbW92ZSB1c2luZyBvcmlnRm5cblx0XHRmbi5ndWlkID0gb3JpZ0ZuLmd1aWQgfHwgKCBvcmlnRm4uZ3VpZCA9IGpRdWVyeS5ndWlkKysgKTtcblx0fVxuXHRyZXR1cm4gZWxlbS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRqUXVlcnkuZXZlbnQuYWRkKCB0aGlzLCB0eXBlcywgZm4sIGRhdGEsIHNlbGVjdG9yICk7XG5cdH0gKTtcbn1cblxuLypcbiAqIEhlbHBlciBmdW5jdGlvbnMgZm9yIG1hbmFnaW5nIGV2ZW50cyAtLSBub3QgcGFydCBvZiB0aGUgcHVibGljIGludGVyZmFjZS5cbiAqIFByb3BzIHRvIERlYW4gRWR3YXJkcycgYWRkRXZlbnQgbGlicmFyeSBmb3IgbWFueSBvZiB0aGUgaWRlYXMuXG4gKi9cbmpRdWVyeS5ldmVudCA9IHtcblxuXHRnbG9iYWw6IHt9LFxuXG5cdGFkZDogZnVuY3Rpb24oIGVsZW0sIHR5cGVzLCBoYW5kbGVyLCBkYXRhLCBzZWxlY3RvciApIHtcblxuXHRcdHZhciBoYW5kbGVPYmpJbiwgZXZlbnRIYW5kbGUsIHRtcCxcblx0XHRcdGV2ZW50cywgdCwgaGFuZGxlT2JqLFxuXHRcdFx0c3BlY2lhbCwgaGFuZGxlcnMsIHR5cGUsIG5hbWVzcGFjZXMsIG9yaWdUeXBlLFxuXHRcdFx0ZWxlbURhdGEgPSBkYXRhUHJpdi5nZXQoIGVsZW0gKTtcblxuXHRcdC8vIERvbid0IGF0dGFjaCBldmVudHMgdG8gbm9EYXRhIG9yIHRleHQvY29tbWVudCBub2RlcyAoYnV0IGFsbG93IHBsYWluIG9iamVjdHMpXG5cdFx0aWYgKCAhZWxlbURhdGEgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGVyIGNhbiBwYXNzIGluIGFuIG9iamVjdCBvZiBjdXN0b20gZGF0YSBpbiBsaWV1IG9mIHRoZSBoYW5kbGVyXG5cdFx0aWYgKCBoYW5kbGVyLmhhbmRsZXIgKSB7XG5cdFx0XHRoYW5kbGVPYmpJbiA9IGhhbmRsZXI7XG5cdFx0XHRoYW5kbGVyID0gaGFuZGxlT2JqSW4uaGFuZGxlcjtcblx0XHRcdHNlbGVjdG9yID0gaGFuZGxlT2JqSW4uc2VsZWN0b3I7XG5cdFx0fVxuXG5cdFx0Ly8gRW5zdXJlIHRoYXQgaW52YWxpZCBzZWxlY3RvcnMgdGhyb3cgZXhjZXB0aW9ucyBhdCBhdHRhY2ggdGltZVxuXHRcdC8vIEV2YWx1YXRlIGFnYWluc3QgZG9jdW1lbnRFbGVtZW50IGluIGNhc2UgZWxlbSBpcyBhIG5vbi1lbGVtZW50IG5vZGUgKGUuZy4sIGRvY3VtZW50KVxuXHRcdGlmICggc2VsZWN0b3IgKSB7XG5cdFx0XHRqUXVlcnkuZmluZC5tYXRjaGVzU2VsZWN0b3IoIGRvY3VtZW50RWxlbWVudCwgc2VsZWN0b3IgKTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIHN1cmUgdGhhdCB0aGUgaGFuZGxlciBoYXMgYSB1bmlxdWUgSUQsIHVzZWQgdG8gZmluZC9yZW1vdmUgaXQgbGF0ZXJcblx0XHRpZiAoICFoYW5kbGVyLmd1aWQgKSB7XG5cdFx0XHRoYW5kbGVyLmd1aWQgPSBqUXVlcnkuZ3VpZCsrO1xuXHRcdH1cblxuXHRcdC8vIEluaXQgdGhlIGVsZW1lbnQncyBldmVudCBzdHJ1Y3R1cmUgYW5kIG1haW4gaGFuZGxlciwgaWYgdGhpcyBpcyB0aGUgZmlyc3Rcblx0XHRpZiAoICEoIGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyApICkge1xuXHRcdFx0ZXZlbnRzID0gZWxlbURhdGEuZXZlbnRzID0ge307XG5cdFx0fVxuXHRcdGlmICggISggZXZlbnRIYW5kbGUgPSBlbGVtRGF0YS5oYW5kbGUgKSApIHtcblx0XHRcdGV2ZW50SGFuZGxlID0gZWxlbURhdGEuaGFuZGxlID0gZnVuY3Rpb24oIGUgKSB7XG5cblx0XHRcdFx0Ly8gRGlzY2FyZCB0aGUgc2Vjb25kIGV2ZW50IG9mIGEgalF1ZXJ5LmV2ZW50LnRyaWdnZXIoKSBhbmRcblx0XHRcdFx0Ly8gd2hlbiBhbiBldmVudCBpcyBjYWxsZWQgYWZ0ZXIgYSBwYWdlIGhhcyB1bmxvYWRlZFxuXHRcdFx0XHRyZXR1cm4gdHlwZW9mIGpRdWVyeSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICE9PSBlLnR5cGUgP1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5kaXNwYXRjaC5hcHBseSggZWxlbSwgYXJndW1lbnRzICkgOiB1bmRlZmluZWQ7XG5cdFx0XHR9O1xuXHRcdH1cblxuXHRcdC8vIEhhbmRsZSBtdWx0aXBsZSBldmVudHMgc2VwYXJhdGVkIGJ5IGEgc3BhY2Vcblx0XHR0eXBlcyA9ICggdHlwZXMgfHwgXCJcIiApLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgWyBcIlwiIF07XG5cdFx0dCA9IHR5cGVzLmxlbmd0aDtcblx0XHR3aGlsZSAoIHQtLSApIHtcblx0XHRcdHRtcCA9IHJ0eXBlbmFtZXNwYWNlLmV4ZWMoIHR5cGVzWyB0IF0gKSB8fCBbXTtcblx0XHRcdHR5cGUgPSBvcmlnVHlwZSA9IHRtcFsgMSBdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWyAyIF0gfHwgXCJcIiApLnNwbGl0KCBcIi5cIiApLnNvcnQoKTtcblxuXHRcdFx0Ly8gVGhlcmUgKm11c3QqIGJlIGEgdHlwZSwgbm8gYXR0YWNoaW5nIG5hbWVzcGFjZS1vbmx5IGhhbmRsZXJzXG5cdFx0XHRpZiAoICF0eXBlICkge1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgZXZlbnQgY2hhbmdlcyBpdHMgdHlwZSwgdXNlIHRoZSBzcGVjaWFsIGV2ZW50IGhhbmRsZXJzIGZvciB0aGUgY2hhbmdlZCB0eXBlXG5cdFx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblxuXHRcdFx0Ly8gSWYgc2VsZWN0b3IgZGVmaW5lZCwgZGV0ZXJtaW5lIHNwZWNpYWwgZXZlbnQgYXBpIHR5cGUsIG90aGVyd2lzZSBnaXZlbiB0eXBlXG5cdFx0XHR0eXBlID0gKCBzZWxlY3RvciA/IHNwZWNpYWwuZGVsZWdhdGVUeXBlIDogc3BlY2lhbC5iaW5kVHlwZSApIHx8IHR5cGU7XG5cblx0XHRcdC8vIFVwZGF0ZSBzcGVjaWFsIGJhc2VkIG9uIG5ld2x5IHJlc2V0IHR5cGVcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgdHlwZSBdIHx8IHt9O1xuXG5cdFx0XHQvLyBoYW5kbGVPYmogaXMgcGFzc2VkIHRvIGFsbCBldmVudCBoYW5kbGVyc1xuXHRcdFx0aGFuZGxlT2JqID0galF1ZXJ5LmV4dGVuZCgge1xuXHRcdFx0XHR0eXBlOiB0eXBlLFxuXHRcdFx0XHRvcmlnVHlwZTogb3JpZ1R5cGUsXG5cdFx0XHRcdGRhdGE6IGRhdGEsXG5cdFx0XHRcdGhhbmRsZXI6IGhhbmRsZXIsXG5cdFx0XHRcdGd1aWQ6IGhhbmRsZXIuZ3VpZCxcblx0XHRcdFx0c2VsZWN0b3I6IHNlbGVjdG9yLFxuXHRcdFx0XHRuZWVkc0NvbnRleHQ6IHNlbGVjdG9yICYmIGpRdWVyeS5leHByLm1hdGNoLm5lZWRzQ29udGV4dC50ZXN0KCBzZWxlY3RvciApLFxuXHRcdFx0XHRuYW1lc3BhY2U6IG5hbWVzcGFjZXMuam9pbiggXCIuXCIgKVxuXHRcdFx0fSwgaGFuZGxlT2JqSW4gKTtcblxuXHRcdFx0Ly8gSW5pdCB0aGUgZXZlbnQgaGFuZGxlciBxdWV1ZSBpZiB3ZSdyZSB0aGUgZmlyc3Rcblx0XHRcdGlmICggISggaGFuZGxlcnMgPSBldmVudHNbIHR5cGUgXSApICkge1xuXHRcdFx0XHRoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdID0gW107XG5cdFx0XHRcdGhhbmRsZXJzLmRlbGVnYXRlQ291bnQgPSAwO1xuXG5cdFx0XHRcdC8vIE9ubHkgdXNlIGFkZEV2ZW50TGlzdGVuZXIgaWYgdGhlIHNwZWNpYWwgZXZlbnRzIGhhbmRsZXIgcmV0dXJucyBmYWxzZVxuXHRcdFx0XHRpZiAoICFzcGVjaWFsLnNldHVwIHx8XG5cdFx0XHRcdFx0c3BlY2lhbC5zZXR1cC5jYWxsKCBlbGVtLCBkYXRhLCBuYW1lc3BhY2VzLCBldmVudEhhbmRsZSApID09PSBmYWxzZSApIHtcblxuXHRcdFx0XHRcdGlmICggZWxlbS5hZGRFdmVudExpc3RlbmVyICkge1xuXHRcdFx0XHRcdFx0ZWxlbS5hZGRFdmVudExpc3RlbmVyKCB0eXBlLCBldmVudEhhbmRsZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHNwZWNpYWwuYWRkICkge1xuXHRcdFx0XHRzcGVjaWFsLmFkZC5jYWxsKCBlbGVtLCBoYW5kbGVPYmogKTtcblxuXHRcdFx0XHRpZiAoICFoYW5kbGVPYmouaGFuZGxlci5ndWlkICkge1xuXHRcdFx0XHRcdGhhbmRsZU9iai5oYW5kbGVyLmd1aWQgPSBoYW5kbGVyLmd1aWQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIHRvIHRoZSBlbGVtZW50J3MgaGFuZGxlciBsaXN0LCBkZWxlZ2F0ZXMgaW4gZnJvbnRcblx0XHRcdGlmICggc2VsZWN0b3IgKSB7XG5cdFx0XHRcdGhhbmRsZXJzLnNwbGljZSggaGFuZGxlcnMuZGVsZWdhdGVDb3VudCsrLCAwLCBoYW5kbGVPYmogKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGhhbmRsZXJzLnB1c2goIGhhbmRsZU9iaiApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBLZWVwIHRyYWNrIG9mIHdoaWNoIGV2ZW50cyBoYXZlIGV2ZXIgYmVlbiB1c2VkLCBmb3IgZXZlbnQgb3B0aW1pemF0aW9uXG5cdFx0XHRqUXVlcnkuZXZlbnQuZ2xvYmFsWyB0eXBlIF0gPSB0cnVlO1xuXHRcdH1cblxuXHR9LFxuXG5cdC8vIERldGFjaCBhbiBldmVudCBvciBzZXQgb2YgZXZlbnRzIGZyb20gYW4gZWxlbWVudFxuXHRyZW1vdmU6IGZ1bmN0aW9uKCBlbGVtLCB0eXBlcywgaGFuZGxlciwgc2VsZWN0b3IsIG1hcHBlZFR5cGVzICkge1xuXG5cdFx0dmFyIGosIG9yaWdDb3VudCwgdG1wLFxuXHRcdFx0ZXZlbnRzLCB0LCBoYW5kbGVPYmosXG5cdFx0XHRzcGVjaWFsLCBoYW5kbGVycywgdHlwZSwgbmFtZXNwYWNlcywgb3JpZ1R5cGUsXG5cdFx0XHRlbGVtRGF0YSA9IGRhdGFQcml2Lmhhc0RhdGEoIGVsZW0gKSAmJiBkYXRhUHJpdi5nZXQoIGVsZW0gKTtcblxuXHRcdGlmICggIWVsZW1EYXRhIHx8ICEoIGV2ZW50cyA9IGVsZW1EYXRhLmV2ZW50cyApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIE9uY2UgZm9yIGVhY2ggdHlwZS5uYW1lc3BhY2UgaW4gdHlwZXM7IHR5cGUgbWF5IGJlIG9taXR0ZWRcblx0XHR0eXBlcyA9ICggdHlwZXMgfHwgXCJcIiApLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgWyBcIlwiIF07XG5cdFx0dCA9IHR5cGVzLmxlbmd0aDtcblx0XHR3aGlsZSAoIHQtLSApIHtcblx0XHRcdHRtcCA9IHJ0eXBlbmFtZXNwYWNlLmV4ZWMoIHR5cGVzWyB0IF0gKSB8fCBbXTtcblx0XHRcdHR5cGUgPSBvcmlnVHlwZSA9IHRtcFsgMSBdO1xuXHRcdFx0bmFtZXNwYWNlcyA9ICggdG1wWyAyIF0gfHwgXCJcIiApLnNwbGl0KCBcIi5cIiApLnNvcnQoKTtcblxuXHRcdFx0Ly8gVW5iaW5kIGFsbCBldmVudHMgKG9uIHRoaXMgbmFtZXNwYWNlLCBpZiBwcm92aWRlZCkgZm9yIHRoZSBlbGVtZW50XG5cdFx0XHRpZiAoICF0eXBlICkge1xuXHRcdFx0XHRmb3IgKCB0eXBlIGluIGV2ZW50cyApIHtcblx0XHRcdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCBlbGVtLCB0eXBlICsgdHlwZXNbIHQgXSwgaGFuZGxlciwgc2VsZWN0b3IsIHRydWUgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0c3BlY2lhbCA9IGpRdWVyeS5ldmVudC5zcGVjaWFsWyB0eXBlIF0gfHwge307XG5cdFx0XHR0eXBlID0gKCBzZWxlY3RvciA/IHNwZWNpYWwuZGVsZWdhdGVUeXBlIDogc3BlY2lhbC5iaW5kVHlwZSApIHx8IHR5cGU7XG5cdFx0XHRoYW5kbGVycyA9IGV2ZW50c1sgdHlwZSBdIHx8IFtdO1xuXHRcdFx0dG1wID0gdG1wWyAyIF0gJiZcblx0XHRcdFx0bmV3IFJlZ0V4cCggXCIoXnxcXFxcLilcIiArIG5hbWVzcGFjZXMuam9pbiggXCJcXFxcLig/Oi4qXFxcXC58KVwiICkgKyBcIihcXFxcLnwkKVwiICk7XG5cblx0XHRcdC8vIFJlbW92ZSBtYXRjaGluZyBldmVudHNcblx0XHRcdG9yaWdDb3VudCA9IGogPSBoYW5kbGVycy5sZW5ndGg7XG5cdFx0XHR3aGlsZSAoIGotLSApIHtcblx0XHRcdFx0aGFuZGxlT2JqID0gaGFuZGxlcnNbIGogXTtcblxuXHRcdFx0XHRpZiAoICggbWFwcGVkVHlwZXMgfHwgb3JpZ1R5cGUgPT09IGhhbmRsZU9iai5vcmlnVHlwZSApICYmXG5cdFx0XHRcdFx0KCAhaGFuZGxlciB8fCBoYW5kbGVyLmd1aWQgPT09IGhhbmRsZU9iai5ndWlkICkgJiZcblx0XHRcdFx0XHQoICF0bXAgfHwgdG1wLnRlc3QoIGhhbmRsZU9iai5uYW1lc3BhY2UgKSApICYmXG5cdFx0XHRcdFx0KCAhc2VsZWN0b3IgfHwgc2VsZWN0b3IgPT09IGhhbmRsZU9iai5zZWxlY3RvciB8fFxuXHRcdFx0XHRcdFx0c2VsZWN0b3IgPT09IFwiKipcIiAmJiBoYW5kbGVPYmouc2VsZWN0b3IgKSApIHtcblx0XHRcdFx0XHRoYW5kbGVycy5zcGxpY2UoIGosIDEgKTtcblxuXHRcdFx0XHRcdGlmICggaGFuZGxlT2JqLnNlbGVjdG9yICkge1xuXHRcdFx0XHRcdFx0aGFuZGxlcnMuZGVsZWdhdGVDb3VudC0tO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRpZiAoIHNwZWNpYWwucmVtb3ZlICkge1xuXHRcdFx0XHRcdFx0c3BlY2lhbC5yZW1vdmUuY2FsbCggZWxlbSwgaGFuZGxlT2JqICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIFJlbW92ZSBnZW5lcmljIGV2ZW50IGhhbmRsZXIgaWYgd2UgcmVtb3ZlZCBzb21ldGhpbmcgYW5kIG5vIG1vcmUgaGFuZGxlcnMgZXhpc3Rcblx0XHRcdC8vIChhdm9pZHMgcG90ZW50aWFsIGZvciBlbmRsZXNzIHJlY3Vyc2lvbiBkdXJpbmcgcmVtb3ZhbCBvZiBzcGVjaWFsIGV2ZW50IGhhbmRsZXJzKVxuXHRcdFx0aWYgKCBvcmlnQ291bnQgJiYgIWhhbmRsZXJzLmxlbmd0aCApIHtcblx0XHRcdFx0aWYgKCAhc3BlY2lhbC50ZWFyZG93biB8fFxuXHRcdFx0XHRcdHNwZWNpYWwudGVhcmRvd24uY2FsbCggZWxlbSwgbmFtZXNwYWNlcywgZWxlbURhdGEuaGFuZGxlICkgPT09IGZhbHNlICkge1xuXG5cdFx0XHRcdFx0alF1ZXJ5LnJlbW92ZUV2ZW50KCBlbGVtLCB0eXBlLCBlbGVtRGF0YS5oYW5kbGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGRlbGV0ZSBldmVudHNbIHR5cGUgXTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBSZW1vdmUgZGF0YSBhbmQgdGhlIGV4cGFuZG8gaWYgaXQncyBubyBsb25nZXIgdXNlZFxuXHRcdGlmICggalF1ZXJ5LmlzRW1wdHlPYmplY3QoIGV2ZW50cyApICkge1xuXHRcdFx0ZGF0YVByaXYucmVtb3ZlKCBlbGVtLCBcImhhbmRsZSBldmVudHNcIiApO1xuXHRcdH1cblx0fSxcblxuXHRkaXNwYXRjaDogZnVuY3Rpb24oIG5hdGl2ZUV2ZW50ICkge1xuXG5cdFx0Ly8gTWFrZSBhIHdyaXRhYmxlIGpRdWVyeS5FdmVudCBmcm9tIHRoZSBuYXRpdmUgZXZlbnQgb2JqZWN0XG5cdFx0dmFyIGV2ZW50ID0galF1ZXJ5LmV2ZW50LmZpeCggbmF0aXZlRXZlbnQgKTtcblxuXHRcdHZhciBpLCBqLCByZXQsIG1hdGNoZWQsIGhhbmRsZU9iaiwgaGFuZGxlclF1ZXVlLFxuXHRcdFx0YXJncyA9IG5ldyBBcnJheSggYXJndW1lbnRzLmxlbmd0aCApLFxuXHRcdFx0aGFuZGxlcnMgPSAoIGRhdGFQcml2LmdldCggdGhpcywgXCJldmVudHNcIiApIHx8IHt9IClbIGV2ZW50LnR5cGUgXSB8fCBbXSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZXZlbnQudHlwZSBdIHx8IHt9O1xuXG5cdFx0Ly8gVXNlIHRoZSBmaXgtZWQgalF1ZXJ5LkV2ZW50IHJhdGhlciB0aGFuIHRoZSAocmVhZC1vbmx5KSBuYXRpdmUgZXZlbnRcblx0XHRhcmdzWyAwIF0gPSBldmVudDtcblxuXHRcdGZvciAoIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrICkge1xuXHRcdFx0YXJnc1sgaSBdID0gYXJndW1lbnRzWyBpIF07XG5cdFx0fVxuXG5cdFx0ZXZlbnQuZGVsZWdhdGVUYXJnZXQgPSB0aGlzO1xuXG5cdFx0Ly8gQ2FsbCB0aGUgcHJlRGlzcGF0Y2ggaG9vayBmb3IgdGhlIG1hcHBlZCB0eXBlLCBhbmQgbGV0IGl0IGJhaWwgaWYgZGVzaXJlZFxuXHRcdGlmICggc3BlY2lhbC5wcmVEaXNwYXRjaCAmJiBzcGVjaWFsLnByZURpc3BhdGNoLmNhbGwoIHRoaXMsIGV2ZW50ICkgPT09IGZhbHNlICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIERldGVybWluZSBoYW5kbGVyc1xuXHRcdGhhbmRsZXJRdWV1ZSA9IGpRdWVyeS5ldmVudC5oYW5kbGVycy5jYWxsKCB0aGlzLCBldmVudCwgaGFuZGxlcnMgKTtcblxuXHRcdC8vIFJ1biBkZWxlZ2F0ZXMgZmlyc3Q7IHRoZXkgbWF5IHdhbnQgdG8gc3RvcCBwcm9wYWdhdGlvbiBiZW5lYXRoIHVzXG5cdFx0aSA9IDA7XG5cdFx0d2hpbGUgKCAoIG1hdGNoZWQgPSBoYW5kbGVyUXVldWVbIGkrKyBdICkgJiYgIWV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cdFx0XHRldmVudC5jdXJyZW50VGFyZ2V0ID0gbWF0Y2hlZC5lbGVtO1xuXG5cdFx0XHRqID0gMDtcblx0XHRcdHdoaWxlICggKCBoYW5kbGVPYmogPSBtYXRjaGVkLmhhbmRsZXJzWyBqKysgXSApICYmXG5cdFx0XHRcdCFldmVudC5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCgpICkge1xuXG5cdFx0XHRcdC8vIFRyaWdnZXJlZCBldmVudCBtdXN0IGVpdGhlciAxKSBoYXZlIG5vIG5hbWVzcGFjZSwgb3IgMikgaGF2ZSBuYW1lc3BhY2Uocylcblx0XHRcdFx0Ly8gYSBzdWJzZXQgb3IgZXF1YWwgdG8gdGhvc2UgaW4gdGhlIGJvdW5kIGV2ZW50IChib3RoIGNhbiBoYXZlIG5vIG5hbWVzcGFjZSkuXG5cdFx0XHRcdGlmICggIWV2ZW50LnJuYW1lc3BhY2UgfHwgZXZlbnQucm5hbWVzcGFjZS50ZXN0KCBoYW5kbGVPYmoubmFtZXNwYWNlICkgKSB7XG5cblx0XHRcdFx0XHRldmVudC5oYW5kbGVPYmogPSBoYW5kbGVPYmo7XG5cdFx0XHRcdFx0ZXZlbnQuZGF0YSA9IGhhbmRsZU9iai5kYXRhO1xuXG5cdFx0XHRcdFx0cmV0ID0gKCAoIGpRdWVyeS5ldmVudC5zcGVjaWFsWyBoYW5kbGVPYmoub3JpZ1R5cGUgXSB8fCB7fSApLmhhbmRsZSB8fFxuXHRcdFx0XHRcdFx0aGFuZGxlT2JqLmhhbmRsZXIgKS5hcHBseSggbWF0Y2hlZC5lbGVtLCBhcmdzICk7XG5cblx0XHRcdFx0XHRpZiAoIHJldCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0aWYgKCAoIGV2ZW50LnJlc3VsdCA9IHJldCApID09PSBmYWxzZSApIHtcblx0XHRcdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdFx0ZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbCB0aGUgcG9zdERpc3BhdGNoIGhvb2sgZm9yIHRoZSBtYXBwZWQgdHlwZVxuXHRcdGlmICggc3BlY2lhbC5wb3N0RGlzcGF0Y2ggKSB7XG5cdFx0XHRzcGVjaWFsLnBvc3REaXNwYXRjaC5jYWxsKCB0aGlzLCBldmVudCApO1xuXHRcdH1cblxuXHRcdHJldHVybiBldmVudC5yZXN1bHQ7XG5cdH0sXG5cblx0aGFuZGxlcnM6IGZ1bmN0aW9uKCBldmVudCwgaGFuZGxlcnMgKSB7XG5cdFx0dmFyIGksIGhhbmRsZU9iaiwgc2VsLCBtYXRjaGVkSGFuZGxlcnMsIG1hdGNoZWRTZWxlY3RvcnMsXG5cdFx0XHRoYW5kbGVyUXVldWUgPSBbXSxcblx0XHRcdGRlbGVnYXRlQ291bnQgPSBoYW5kbGVycy5kZWxlZ2F0ZUNvdW50LFxuXHRcdFx0Y3VyID0gZXZlbnQudGFyZ2V0O1xuXG5cdFx0Ly8gRmluZCBkZWxlZ2F0ZSBoYW5kbGVyc1xuXHRcdGlmICggZGVsZWdhdGVDb3VudCAmJlxuXG5cdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTlcblx0XHRcdC8vIEJsYWNrLWhvbGUgU1ZHIDx1c2U+IGluc3RhbmNlIHRyZWVzICh0cmFjLTEzMTgwKVxuXHRcdFx0Y3VyLm5vZGVUeXBlICYmXG5cblx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggPD00MlxuXHRcdFx0Ly8gU3VwcHJlc3Mgc3BlYy12aW9sYXRpbmcgY2xpY2tzIGluZGljYXRpbmcgYSBub24tcHJpbWFyeSBwb2ludGVyIGJ1dHRvbiAodHJhYy0zODYxKVxuXHRcdFx0Ly8gaHR0cHM6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy8jZXZlbnQtdHlwZS1jbGlja1xuXHRcdFx0Ly8gU3VwcG9ydDogSUUgMTEgb25seVxuXHRcdFx0Ly8gLi4uYnV0IG5vdCBhcnJvdyBrZXkgXCJjbGlja3NcIiBvZiByYWRpbyBpbnB1dHMsIHdoaWNoIGNhbiBoYXZlIGBidXR0b25gIC0xIChnaC0yMzQzKVxuXHRcdFx0ISggZXZlbnQudHlwZSA9PT0gXCJjbGlja1wiICYmIGV2ZW50LmJ1dHRvbiA+PSAxICkgKSB7XG5cblx0XHRcdGZvciAoIDsgY3VyICE9PSB0aGlzOyBjdXIgPSBjdXIucGFyZW50Tm9kZSB8fCB0aGlzICkge1xuXG5cdFx0XHRcdC8vIERvbid0IGNoZWNrIG5vbi1lbGVtZW50cyAoIzEzMjA4KVxuXHRcdFx0XHQvLyBEb24ndCBwcm9jZXNzIGNsaWNrcyBvbiBkaXNhYmxlZCBlbGVtZW50cyAoIzY5MTEsICM4MTY1LCAjMTEzODIsICMxMTc2NClcblx0XHRcdFx0aWYgKCBjdXIubm9kZVR5cGUgPT09IDEgJiYgISggZXZlbnQudHlwZSA9PT0gXCJjbGlja1wiICYmIGN1ci5kaXNhYmxlZCA9PT0gdHJ1ZSApICkge1xuXHRcdFx0XHRcdG1hdGNoZWRIYW5kbGVycyA9IFtdO1xuXHRcdFx0XHRcdG1hdGNoZWRTZWxlY3RvcnMgPSB7fTtcblx0XHRcdFx0XHRmb3IgKCBpID0gMDsgaSA8IGRlbGVnYXRlQ291bnQ7IGkrKyApIHtcblx0XHRcdFx0XHRcdGhhbmRsZU9iaiA9IGhhbmRsZXJzWyBpIF07XG5cblx0XHRcdFx0XHRcdC8vIERvbid0IGNvbmZsaWN0IHdpdGggT2JqZWN0LnByb3RvdHlwZSBwcm9wZXJ0aWVzICgjMTMyMDMpXG5cdFx0XHRcdFx0XHRzZWwgPSBoYW5kbGVPYmouc2VsZWN0b3IgKyBcIiBcIjtcblxuXHRcdFx0XHRcdFx0aWYgKCBtYXRjaGVkU2VsZWN0b3JzWyBzZWwgXSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVkU2VsZWN0b3JzWyBzZWwgXSA9IGhhbmRsZU9iai5uZWVkc0NvbnRleHQgP1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeSggc2VsLCB0aGlzICkuaW5kZXgoIGN1ciApID4gLTEgOlxuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5maW5kKCBzZWwsIHRoaXMsIG51bGwsIFsgY3VyIF0gKS5sZW5ndGg7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRpZiAoIG1hdGNoZWRTZWxlY3RvcnNbIHNlbCBdICkge1xuXHRcdFx0XHRcdFx0XHRtYXRjaGVkSGFuZGxlcnMucHVzaCggaGFuZGxlT2JqICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmICggbWF0Y2hlZEhhbmRsZXJzLmxlbmd0aCApIHtcblx0XHRcdFx0XHRcdGhhbmRsZXJRdWV1ZS5wdXNoKCB7IGVsZW06IGN1ciwgaGFuZGxlcnM6IG1hdGNoZWRIYW5kbGVycyB9ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQWRkIHRoZSByZW1haW5pbmcgKGRpcmVjdGx5LWJvdW5kKSBoYW5kbGVyc1xuXHRcdGN1ciA9IHRoaXM7XG5cdFx0aWYgKCBkZWxlZ2F0ZUNvdW50IDwgaGFuZGxlcnMubGVuZ3RoICkge1xuXHRcdFx0aGFuZGxlclF1ZXVlLnB1c2goIHsgZWxlbTogY3VyLCBoYW5kbGVyczogaGFuZGxlcnMuc2xpY2UoIGRlbGVnYXRlQ291bnQgKSB9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGhhbmRsZXJRdWV1ZTtcblx0fSxcblxuXHRhZGRQcm9wOiBmdW5jdGlvbiggbmFtZSwgaG9vayApIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIGpRdWVyeS5FdmVudC5wcm90b3R5cGUsIG5hbWUsIHtcblx0XHRcdGVudW1lcmFibGU6IHRydWUsXG5cdFx0XHRjb25maWd1cmFibGU6IHRydWUsXG5cblx0XHRcdGdldDogalF1ZXJ5LmlzRnVuY3Rpb24oIGhvb2sgKSA/XG5cdFx0XHRcdGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5vcmlnaW5hbEV2ZW50ICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gaG9vayggdGhpcy5vcmlnaW5hbEV2ZW50ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IDpcblx0XHRcdFx0ZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0aWYgKCB0aGlzLm9yaWdpbmFsRXZlbnQgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0aGlzLm9yaWdpbmFsRXZlbnRbIG5hbWUgXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cblx0XHRcdHNldDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoIHRoaXMsIG5hbWUsIHtcblx0XHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuXHRcdFx0XHRcdGNvbmZpZ3VyYWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR3cml0YWJsZTogdHJ1ZSxcblx0XHRcdFx0XHR2YWx1ZTogdmFsdWVcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRmaXg6IGZ1bmN0aW9uKCBvcmlnaW5hbEV2ZW50ICkge1xuXHRcdHJldHVybiBvcmlnaW5hbEV2ZW50WyBqUXVlcnkuZXhwYW5kbyBdID9cblx0XHRcdG9yaWdpbmFsRXZlbnQgOlxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCggb3JpZ2luYWxFdmVudCApO1xuXHR9LFxuXG5cdHNwZWNpYWw6IHtcblx0XHRsb2FkOiB7XG5cblx0XHRcdC8vIFByZXZlbnQgdHJpZ2dlcmVkIGltYWdlLmxvYWQgZXZlbnRzIGZyb20gYnViYmxpbmcgdG8gd2luZG93LmxvYWRcblx0XHRcdG5vQnViYmxlOiB0cnVlXG5cdFx0fSxcblx0XHRmb2N1czoge1xuXG5cdFx0XHQvLyBGaXJlIG5hdGl2ZSBldmVudCBpZiBwb3NzaWJsZSBzbyBibHVyL2ZvY3VzIHNlcXVlbmNlIGlzIGNvcnJlY3Rcblx0XHRcdHRyaWdnZXI6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIHRoaXMgIT09IHNhZmVBY3RpdmVFbGVtZW50KCkgJiYgdGhpcy5mb2N1cyApIHtcblx0XHRcdFx0XHR0aGlzLmZvY3VzKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVsZWdhdGVUeXBlOiBcImZvY3VzaW5cIlxuXHRcdH0sXG5cdFx0Ymx1cjoge1xuXHRcdFx0dHJpZ2dlcjogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggdGhpcyA9PT0gc2FmZUFjdGl2ZUVsZW1lbnQoKSAmJiB0aGlzLmJsdXIgKSB7XG5cdFx0XHRcdFx0dGhpcy5ibHVyKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXHRcdFx0ZGVsZWdhdGVUeXBlOiBcImZvY3Vzb3V0XCJcblx0XHR9LFxuXHRcdGNsaWNrOiB7XG5cblx0XHRcdC8vIEZvciBjaGVja2JveCwgZmlyZSBuYXRpdmUgZXZlbnQgc28gY2hlY2tlZCBzdGF0ZSB3aWxsIGJlIHJpZ2h0XG5cdFx0XHR0cmlnZ2VyOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYgKCB0aGlzLnR5cGUgPT09IFwiY2hlY2tib3hcIiAmJiB0aGlzLmNsaWNrICYmIG5vZGVOYW1lKCB0aGlzLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR0aGlzLmNsaWNrKCk7XG5cdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHQvLyBGb3IgY3Jvc3MtYnJvd3NlciBjb25zaXN0ZW5jeSwgZG9uJ3QgZmlyZSBuYXRpdmUgLmNsaWNrKCkgb24gbGlua3Ncblx0XHRcdF9kZWZhdWx0OiBmdW5jdGlvbiggZXZlbnQgKSB7XG5cdFx0XHRcdHJldHVybiBub2RlTmFtZSggZXZlbnQudGFyZ2V0LCBcImFcIiApO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRiZWZvcmV1bmxvYWQ6IHtcblx0XHRcdHBvc3REaXNwYXRjaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXG5cdFx0XHRcdC8vIFN1cHBvcnQ6IEZpcmVmb3ggMjArXG5cdFx0XHRcdC8vIEZpcmVmb3ggZG9lc24ndCBhbGVydCBpZiB0aGUgcmV0dXJuVmFsdWUgZmllbGQgaXMgbm90IHNldC5cblx0XHRcdFx0aWYgKCBldmVudC5yZXN1bHQgIT09IHVuZGVmaW5lZCAmJiBldmVudC5vcmlnaW5hbEV2ZW50ICkge1xuXHRcdFx0XHRcdGV2ZW50Lm9yaWdpbmFsRXZlbnQucmV0dXJuVmFsdWUgPSBldmVudC5yZXN1bHQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cbn07XG5cbmpRdWVyeS5yZW1vdmVFdmVudCA9IGZ1bmN0aW9uKCBlbGVtLCB0eXBlLCBoYW5kbGUgKSB7XG5cblx0Ly8gVGhpcyBcImlmXCIgaXMgbmVlZGVkIGZvciBwbGFpbiBvYmplY3RzXG5cdGlmICggZWxlbS5yZW1vdmVFdmVudExpc3RlbmVyICkge1xuXHRcdGVsZW0ucmVtb3ZlRXZlbnRMaXN0ZW5lciggdHlwZSwgaGFuZGxlICk7XG5cdH1cbn07XG5cbmpRdWVyeS5FdmVudCA9IGZ1bmN0aW9uKCBzcmMsIHByb3BzICkge1xuXG5cdC8vIEFsbG93IGluc3RhbnRpYXRpb24gd2l0aG91dCB0aGUgJ25ldycga2V5d29yZFxuXHRpZiAoICEoIHRoaXMgaW5zdGFuY2VvZiBqUXVlcnkuRXZlbnQgKSApIHtcblx0XHRyZXR1cm4gbmV3IGpRdWVyeS5FdmVudCggc3JjLCBwcm9wcyApO1xuXHR9XG5cblx0Ly8gRXZlbnQgb2JqZWN0XG5cdGlmICggc3JjICYmIHNyYy50eXBlICkge1xuXHRcdHRoaXMub3JpZ2luYWxFdmVudCA9IHNyYztcblx0XHR0aGlzLnR5cGUgPSBzcmMudHlwZTtcblxuXHRcdC8vIEV2ZW50cyBidWJibGluZyB1cCB0aGUgZG9jdW1lbnQgbWF5IGhhdmUgYmVlbiBtYXJrZWQgYXMgcHJldmVudGVkXG5cdFx0Ly8gYnkgYSBoYW5kbGVyIGxvd2VyIGRvd24gdGhlIHRyZWU7IHJlZmxlY3QgdGhlIGNvcnJlY3QgdmFsdWUuXG5cdFx0dGhpcy5pc0RlZmF1bHRQcmV2ZW50ZWQgPSBzcmMuZGVmYXVsdFByZXZlbnRlZCB8fFxuXHRcdFx0XHRzcmMuZGVmYXVsdFByZXZlbnRlZCA9PT0gdW5kZWZpbmVkICYmXG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTIuMyBvbmx5XG5cdFx0XHRcdHNyYy5yZXR1cm5WYWx1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0cmV0dXJuVHJ1ZSA6XG5cdFx0XHRyZXR1cm5GYWxzZTtcblxuXHRcdC8vIENyZWF0ZSB0YXJnZXQgcHJvcGVydGllc1xuXHRcdC8vIFN1cHBvcnQ6IFNhZmFyaSA8PTYgLSA3IG9ubHlcblx0XHQvLyBUYXJnZXQgc2hvdWxkIG5vdCBiZSBhIHRleHQgbm9kZSAoIzUwNCwgIzEzMTQzKVxuXHRcdHRoaXMudGFyZ2V0ID0gKCBzcmMudGFyZ2V0ICYmIHNyYy50YXJnZXQubm9kZVR5cGUgPT09IDMgKSA/XG5cdFx0XHRzcmMudGFyZ2V0LnBhcmVudE5vZGUgOlxuXHRcdFx0c3JjLnRhcmdldDtcblxuXHRcdHRoaXMuY3VycmVudFRhcmdldCA9IHNyYy5jdXJyZW50VGFyZ2V0O1xuXHRcdHRoaXMucmVsYXRlZFRhcmdldCA9IHNyYy5yZWxhdGVkVGFyZ2V0O1xuXG5cdC8vIEV2ZW50IHR5cGVcblx0fSBlbHNlIHtcblx0XHR0aGlzLnR5cGUgPSBzcmM7XG5cdH1cblxuXHQvLyBQdXQgZXhwbGljaXRseSBwcm92aWRlZCBwcm9wZXJ0aWVzIG9udG8gdGhlIGV2ZW50IG9iamVjdFxuXHRpZiAoIHByb3BzICkge1xuXHRcdGpRdWVyeS5leHRlbmQoIHRoaXMsIHByb3BzICk7XG5cdH1cblxuXHQvLyBDcmVhdGUgYSB0aW1lc3RhbXAgaWYgaW5jb21pbmcgZXZlbnQgZG9lc24ndCBoYXZlIG9uZVxuXHR0aGlzLnRpbWVTdGFtcCA9IHNyYyAmJiBzcmMudGltZVN0YW1wIHx8IGpRdWVyeS5ub3coKTtcblxuXHQvLyBNYXJrIGl0IGFzIGZpeGVkXG5cdHRoaXNbIGpRdWVyeS5leHBhbmRvIF0gPSB0cnVlO1xufTtcblxuLy8galF1ZXJ5LkV2ZW50IGlzIGJhc2VkIG9uIERPTTMgRXZlbnRzIGFzIHNwZWNpZmllZCBieSB0aGUgRUNNQVNjcmlwdCBMYW5ndWFnZSBCaW5kaW5nXG4vLyBodHRwczovL3d3dy53My5vcmcvVFIvMjAwMy9XRC1ET00tTGV2ZWwtMy1FdmVudHMtMjAwMzAzMzEvZWNtYS1zY3JpcHQtYmluZGluZy5odG1sXG5qUXVlcnkuRXZlbnQucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogalF1ZXJ5LkV2ZW50LFxuXHRpc0RlZmF1bHRQcmV2ZW50ZWQ6IHJldHVybkZhbHNlLFxuXHRpc1Byb3BhZ2F0aW9uU3RvcHBlZDogcmV0dXJuRmFsc2UsXG5cdGlzSW1tZWRpYXRlUHJvcGFnYXRpb25TdG9wcGVkOiByZXR1cm5GYWxzZSxcblx0aXNTaW11bGF0ZWQ6IGZhbHNlLFxuXG5cdHByZXZlbnREZWZhdWx0OiBmdW5jdGlvbigpIHtcblx0XHR2YXIgZSA9IHRoaXMub3JpZ2luYWxFdmVudDtcblxuXHRcdHRoaXMuaXNEZWZhdWx0UHJldmVudGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH0sXG5cdHN0b3BQcm9wYWdhdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0dmFyIGUgPSB0aGlzLm9yaWdpbmFsRXZlbnQ7XG5cblx0XHR0aGlzLmlzUHJvcGFnYXRpb25TdG9wcGVkID0gcmV0dXJuVHJ1ZTtcblxuXHRcdGlmICggZSAmJiAhdGhpcy5pc1NpbXVsYXRlZCApIHtcblx0XHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0fVxuXHR9LFxuXHRzdG9wSW1tZWRpYXRlUHJvcGFnYXRpb246IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlID0gdGhpcy5vcmlnaW5hbEV2ZW50O1xuXG5cdFx0dGhpcy5pc0ltbWVkaWF0ZVByb3BhZ2F0aW9uU3RvcHBlZCA9IHJldHVyblRydWU7XG5cblx0XHRpZiAoIGUgJiYgIXRoaXMuaXNTaW11bGF0ZWQgKSB7XG5cdFx0XHRlLnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuXHRcdH1cblxuXHRcdHRoaXMuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdH1cbn07XG5cbi8vIEluY2x1ZGVzIGFsbCBjb21tb24gZXZlbnQgcHJvcHMgaW5jbHVkaW5nIEtleUV2ZW50IGFuZCBNb3VzZUV2ZW50IHNwZWNpZmljIHByb3BzXG5qUXVlcnkuZWFjaCgge1xuXHRhbHRLZXk6IHRydWUsXG5cdGJ1YmJsZXM6IHRydWUsXG5cdGNhbmNlbGFibGU6IHRydWUsXG5cdGNoYW5nZWRUb3VjaGVzOiB0cnVlLFxuXHRjdHJsS2V5OiB0cnVlLFxuXHRkZXRhaWw6IHRydWUsXG5cdGV2ZW50UGhhc2U6IHRydWUsXG5cdG1ldGFLZXk6IHRydWUsXG5cdHBhZ2VYOiB0cnVlLFxuXHRwYWdlWTogdHJ1ZSxcblx0c2hpZnRLZXk6IHRydWUsXG5cdHZpZXc6IHRydWUsXG5cdFwiY2hhclwiOiB0cnVlLFxuXHRjaGFyQ29kZTogdHJ1ZSxcblx0a2V5OiB0cnVlLFxuXHRrZXlDb2RlOiB0cnVlLFxuXHRidXR0b246IHRydWUsXG5cdGJ1dHRvbnM6IHRydWUsXG5cdGNsaWVudFg6IHRydWUsXG5cdGNsaWVudFk6IHRydWUsXG5cdG9mZnNldFg6IHRydWUsXG5cdG9mZnNldFk6IHRydWUsXG5cdHBvaW50ZXJJZDogdHJ1ZSxcblx0cG9pbnRlclR5cGU6IHRydWUsXG5cdHNjcmVlblg6IHRydWUsXG5cdHNjcmVlblk6IHRydWUsXG5cdHRhcmdldFRvdWNoZXM6IHRydWUsXG5cdHRvRWxlbWVudDogdHJ1ZSxcblx0dG91Y2hlczogdHJ1ZSxcblxuXHR3aGljaDogZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdHZhciBidXR0b24gPSBldmVudC5idXR0b247XG5cblx0XHQvLyBBZGQgd2hpY2ggZm9yIGtleSBldmVudHNcblx0XHRpZiAoIGV2ZW50LndoaWNoID09IG51bGwgJiYgcmtleUV2ZW50LnRlc3QoIGV2ZW50LnR5cGUgKSApIHtcblx0XHRcdHJldHVybiBldmVudC5jaGFyQ29kZSAhPSBudWxsID8gZXZlbnQuY2hhckNvZGUgOiBldmVudC5rZXlDb2RlO1xuXHRcdH1cblxuXHRcdC8vIEFkZCB3aGljaCBmb3IgY2xpY2s6IDEgPT09IGxlZnQ7IDIgPT09IG1pZGRsZTsgMyA9PT0gcmlnaHRcblx0XHRpZiAoICFldmVudC53aGljaCAmJiBidXR0b24gIT09IHVuZGVmaW5lZCAmJiBybW91c2VFdmVudC50ZXN0KCBldmVudC50eXBlICkgKSB7XG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDEgKSB7XG5cdFx0XHRcdHJldHVybiAxO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDIgKSB7XG5cdFx0XHRcdHJldHVybiAzO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGJ1dHRvbiAmIDQgKSB7XG5cdFx0XHRcdHJldHVybiAyO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gMDtcblx0XHR9XG5cblx0XHRyZXR1cm4gZXZlbnQud2hpY2g7XG5cdH1cbn0sIGpRdWVyeS5ldmVudC5hZGRQcm9wICk7XG5cbi8vIENyZWF0ZSBtb3VzZWVudGVyL2xlYXZlIGV2ZW50cyB1c2luZyBtb3VzZW92ZXIvb3V0IGFuZCBldmVudC10aW1lIGNoZWNrc1xuLy8gc28gdGhhdCBldmVudCBkZWxlZ2F0aW9uIHdvcmtzIGluIGpRdWVyeS5cbi8vIERvIHRoZSBzYW1lIGZvciBwb2ludGVyZW50ZXIvcG9pbnRlcmxlYXZlIGFuZCBwb2ludGVyb3Zlci9wb2ludGVyb3V0XG4vL1xuLy8gU3VwcG9ydDogU2FmYXJpIDcgb25seVxuLy8gU2FmYXJpIHNlbmRzIG1vdXNlZW50ZXIgdG9vIG9mdGVuOyBzZWU6XG4vLyBodHRwczovL2J1Z3MuY2hyb21pdW0ub3JnL3AvY2hyb21pdW0vaXNzdWVzL2RldGFpbD9pZD00NzAyNThcbi8vIGZvciB0aGUgZGVzY3JpcHRpb24gb2YgdGhlIGJ1ZyAoaXQgZXhpc3RlZCBpbiBvbGRlciBDaHJvbWUgdmVyc2lvbnMgYXMgd2VsbCkuXG5qUXVlcnkuZWFjaCgge1xuXHRtb3VzZWVudGVyOiBcIm1vdXNlb3ZlclwiLFxuXHRtb3VzZWxlYXZlOiBcIm1vdXNlb3V0XCIsXG5cdHBvaW50ZXJlbnRlcjogXCJwb2ludGVyb3ZlclwiLFxuXHRwb2ludGVybGVhdmU6IFwicG9pbnRlcm91dFwiXG59LCBmdW5jdGlvbiggb3JpZywgZml4ICkge1xuXHRqUXVlcnkuZXZlbnQuc3BlY2lhbFsgb3JpZyBdID0ge1xuXHRcdGRlbGVnYXRlVHlwZTogZml4LFxuXHRcdGJpbmRUeXBlOiBmaXgsXG5cblx0XHRoYW5kbGU6IGZ1bmN0aW9uKCBldmVudCApIHtcblx0XHRcdHZhciByZXQsXG5cdFx0XHRcdHRhcmdldCA9IHRoaXMsXG5cdFx0XHRcdHJlbGF0ZWQgPSBldmVudC5yZWxhdGVkVGFyZ2V0LFxuXHRcdFx0XHRoYW5kbGVPYmogPSBldmVudC5oYW5kbGVPYmo7XG5cblx0XHRcdC8vIEZvciBtb3VzZWVudGVyL2xlYXZlIGNhbGwgdGhlIGhhbmRsZXIgaWYgcmVsYXRlZCBpcyBvdXRzaWRlIHRoZSB0YXJnZXQuXG5cdFx0XHQvLyBOQjogTm8gcmVsYXRlZFRhcmdldCBpZiB0aGUgbW91c2UgbGVmdC9lbnRlcmVkIHRoZSBicm93c2VyIHdpbmRvd1xuXHRcdFx0aWYgKCAhcmVsYXRlZCB8fCAoIHJlbGF0ZWQgIT09IHRhcmdldCAmJiAhalF1ZXJ5LmNvbnRhaW5zKCB0YXJnZXQsIHJlbGF0ZWQgKSApICkge1xuXHRcdFx0XHRldmVudC50eXBlID0gaGFuZGxlT2JqLm9yaWdUeXBlO1xuXHRcdFx0XHRyZXQgPSBoYW5kbGVPYmouaGFuZGxlci5hcHBseSggdGhpcywgYXJndW1lbnRzICk7XG5cdFx0XHRcdGV2ZW50LnR5cGUgPSBmaXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblx0fTtcbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXG5cdG9uOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gb24oIHRoaXMsIHR5cGVzLCBzZWxlY3RvciwgZGF0YSwgZm4gKTtcblx0fSxcblx0b25lOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gb24oIHRoaXMsIHR5cGVzLCBzZWxlY3RvciwgZGF0YSwgZm4sIDEgKTtcblx0fSxcblx0b2ZmOiBmdW5jdGlvbiggdHlwZXMsIHNlbGVjdG9yLCBmbiApIHtcblx0XHR2YXIgaGFuZGxlT2JqLCB0eXBlO1xuXHRcdGlmICggdHlwZXMgJiYgdHlwZXMucHJldmVudERlZmF1bHQgJiYgdHlwZXMuaGFuZGxlT2JqICkge1xuXG5cdFx0XHQvLyAoIGV2ZW50ICkgIGRpc3BhdGNoZWQgalF1ZXJ5LkV2ZW50XG5cdFx0XHRoYW5kbGVPYmogPSB0eXBlcy5oYW5kbGVPYmo7XG5cdFx0XHRqUXVlcnkoIHR5cGVzLmRlbGVnYXRlVGFyZ2V0ICkub2ZmKFxuXHRcdFx0XHRoYW5kbGVPYmoubmFtZXNwYWNlID9cblx0XHRcdFx0XHRoYW5kbGVPYmoub3JpZ1R5cGUgKyBcIi5cIiArIGhhbmRsZU9iai5uYW1lc3BhY2UgOlxuXHRcdFx0XHRcdGhhbmRsZU9iai5vcmlnVHlwZSxcblx0XHRcdFx0aGFuZGxlT2JqLnNlbGVjdG9yLFxuXHRcdFx0XHRoYW5kbGVPYmouaGFuZGxlclxuXHRcdFx0KTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblx0XHRpZiAoIHR5cGVvZiB0eXBlcyA9PT0gXCJvYmplY3RcIiApIHtcblxuXHRcdFx0Ly8gKCB0eXBlcy1vYmplY3QgWywgc2VsZWN0b3JdIClcblx0XHRcdGZvciAoIHR5cGUgaW4gdHlwZXMgKSB7XG5cdFx0XHRcdHRoaXMub2ZmKCB0eXBlLCBzZWxlY3RvciwgdHlwZXNbIHR5cGUgXSApO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fVxuXHRcdGlmICggc2VsZWN0b3IgPT09IGZhbHNlIHx8IHR5cGVvZiBzZWxlY3RvciA9PT0gXCJmdW5jdGlvblwiICkge1xuXG5cdFx0XHQvLyAoIHR5cGVzIFssIGZuXSApXG5cdFx0XHRmbiA9IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcdGlmICggZm4gPT09IGZhbHNlICkge1xuXHRcdFx0Zm4gPSByZXR1cm5GYWxzZTtcblx0XHR9XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRqUXVlcnkuZXZlbnQucmVtb3ZlKCB0aGlzLCB0eXBlcywgZm4sIHNlbGVjdG9yICk7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cblxudmFyXG5cblx0LyogZXNsaW50LWRpc2FibGUgbWF4LWxlbiAqL1xuXG5cdC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZXNsaW50L2VzbGludC9pc3N1ZXMvMzIyOVxuXHRyeGh0bWxUYWcgPSAvPCg/IWFyZWF8YnJ8Y29sfGVtYmVkfGhyfGltZ3xpbnB1dHxsaW5rfG1ldGF8cGFyYW0pKChbYS16XVteXFwvXFwwPlxceDIwXFx0XFxyXFxuXFxmXSopW14+XSopXFwvPi9naSxcblxuXHQvKiBlc2xpbnQtZW5hYmxlICovXG5cblx0Ly8gU3VwcG9ydDogSUUgPD0xMCAtIDExLCBFZGdlIDEyIC0gMTNcblx0Ly8gSW4gSUUvRWRnZSB1c2luZyByZWdleCBncm91cHMgaGVyZSBjYXVzZXMgc2V2ZXJlIHNsb3dkb3ducy5cblx0Ly8gU2VlIGh0dHBzOi8vY29ubmVjdC5taWNyb3NvZnQuY29tL0lFL2ZlZWRiYWNrL2RldGFpbHMvMTczNjUxMi9cblx0cm5vSW5uZXJodG1sID0gLzxzY3JpcHR8PHN0eWxlfDxsaW5rL2ksXG5cblx0Ly8gY2hlY2tlZD1cImNoZWNrZWRcIiBvciBjaGVja2VkXG5cdHJjaGVja2VkID0gL2NoZWNrZWRcXHMqKD86W149XXw9XFxzKi5jaGVja2VkLikvaSxcblx0cnNjcmlwdFR5cGVNYXNrZWQgPSAvXnRydWVcXC8oLiopLyxcblx0cmNsZWFuU2NyaXB0ID0gL15cXHMqPCEoPzpcXFtDREFUQVxcW3wtLSl8KD86XFxdXFxdfC0tKT5cXHMqJC9nO1xuXG4vLyBQcmVmZXIgYSB0Ym9keSBvdmVyIGl0cyBwYXJlbnQgdGFibGUgZm9yIGNvbnRhaW5pbmcgbmV3IHJvd3NcbmZ1bmN0aW9uIG1hbmlwdWxhdGlvblRhcmdldCggZWxlbSwgY29udGVudCApIHtcblx0aWYgKCBub2RlTmFtZSggZWxlbSwgXCJ0YWJsZVwiICkgJiZcblx0XHRub2RlTmFtZSggY29udGVudC5ub2RlVHlwZSAhPT0gMTEgPyBjb250ZW50IDogY29udGVudC5maXJzdENoaWxkLCBcInRyXCIgKSApIHtcblxuXHRcdHJldHVybiBqUXVlcnkoIFwiPnRib2R5XCIsIGVsZW0gKVsgMCBdIHx8IGVsZW07XG5cdH1cblxuXHRyZXR1cm4gZWxlbTtcbn1cblxuLy8gUmVwbGFjZS9yZXN0b3JlIHRoZSB0eXBlIGF0dHJpYnV0ZSBvZiBzY3JpcHQgZWxlbWVudHMgZm9yIHNhZmUgRE9NIG1hbmlwdWxhdGlvblxuZnVuY3Rpb24gZGlzYWJsZVNjcmlwdCggZWxlbSApIHtcblx0ZWxlbS50eXBlID0gKCBlbGVtLmdldEF0dHJpYnV0ZSggXCJ0eXBlXCIgKSAhPT0gbnVsbCApICsgXCIvXCIgKyBlbGVtLnR5cGU7XG5cdHJldHVybiBlbGVtO1xufVxuZnVuY3Rpb24gcmVzdG9yZVNjcmlwdCggZWxlbSApIHtcblx0dmFyIG1hdGNoID0gcnNjcmlwdFR5cGVNYXNrZWQuZXhlYyggZWxlbS50eXBlICk7XG5cblx0aWYgKCBtYXRjaCApIHtcblx0XHRlbGVtLnR5cGUgPSBtYXRjaFsgMSBdO1xuXHR9IGVsc2Uge1xuXHRcdGVsZW0ucmVtb3ZlQXR0cmlidXRlKCBcInR5cGVcIiApO1xuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbmZ1bmN0aW9uIGNsb25lQ29weUV2ZW50KCBzcmMsIGRlc3QgKSB7XG5cdHZhciBpLCBsLCB0eXBlLCBwZGF0YU9sZCwgcGRhdGFDdXIsIHVkYXRhT2xkLCB1ZGF0YUN1ciwgZXZlbnRzO1xuXG5cdGlmICggZGVzdC5ub2RlVHlwZSAhPT0gMSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyAxLiBDb3B5IHByaXZhdGUgZGF0YTogZXZlbnRzLCBoYW5kbGVycywgZXRjLlxuXHRpZiAoIGRhdGFQcml2Lmhhc0RhdGEoIHNyYyApICkge1xuXHRcdHBkYXRhT2xkID0gZGF0YVByaXYuYWNjZXNzKCBzcmMgKTtcblx0XHRwZGF0YUN1ciA9IGRhdGFQcml2LnNldCggZGVzdCwgcGRhdGFPbGQgKTtcblx0XHRldmVudHMgPSBwZGF0YU9sZC5ldmVudHM7XG5cblx0XHRpZiAoIGV2ZW50cyApIHtcblx0XHRcdGRlbGV0ZSBwZGF0YUN1ci5oYW5kbGU7XG5cdFx0XHRwZGF0YUN1ci5ldmVudHMgPSB7fTtcblxuXHRcdFx0Zm9yICggdHlwZSBpbiBldmVudHMgKSB7XG5cdFx0XHRcdGZvciAoIGkgPSAwLCBsID0gZXZlbnRzWyB0eXBlIF0ubGVuZ3RoOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC5hZGQoIGRlc3QsIHR5cGUsIGV2ZW50c1sgdHlwZSBdWyBpIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIDIuIENvcHkgdXNlciBkYXRhXG5cdGlmICggZGF0YVVzZXIuaGFzRGF0YSggc3JjICkgKSB7XG5cdFx0dWRhdGFPbGQgPSBkYXRhVXNlci5hY2Nlc3MoIHNyYyApO1xuXHRcdHVkYXRhQ3VyID0galF1ZXJ5LmV4dGVuZCgge30sIHVkYXRhT2xkICk7XG5cblx0XHRkYXRhVXNlci5zZXQoIGRlc3QsIHVkYXRhQ3VyICk7XG5cdH1cbn1cblxuLy8gRml4IElFIGJ1Z3MsIHNlZSBzdXBwb3J0IHRlc3RzXG5mdW5jdGlvbiBmaXhJbnB1dCggc3JjLCBkZXN0ICkge1xuXHR2YXIgbm9kZU5hbWUgPSBkZXN0Lm5vZGVOYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0Ly8gRmFpbHMgdG8gcGVyc2lzdCB0aGUgY2hlY2tlZCBzdGF0ZSBvZiBhIGNsb25lZCBjaGVja2JveCBvciByYWRpbyBidXR0b24uXG5cdGlmICggbm9kZU5hbWUgPT09IFwiaW5wdXRcIiAmJiByY2hlY2thYmxlVHlwZS50ZXN0KCBzcmMudHlwZSApICkge1xuXHRcdGRlc3QuY2hlY2tlZCA9IHNyYy5jaGVja2VkO1xuXG5cdC8vIEZhaWxzIHRvIHJldHVybiB0aGUgc2VsZWN0ZWQgb3B0aW9uIHRvIHRoZSBkZWZhdWx0IHNlbGVjdGVkIHN0YXRlIHdoZW4gY2xvbmluZyBvcHRpb25zXG5cdH0gZWxzZSBpZiAoIG5vZGVOYW1lID09PSBcImlucHV0XCIgfHwgbm9kZU5hbWUgPT09IFwidGV4dGFyZWFcIiApIHtcblx0XHRkZXN0LmRlZmF1bHRWYWx1ZSA9IHNyYy5kZWZhdWx0VmFsdWU7XG5cdH1cbn1cblxuZnVuY3Rpb24gZG9tTWFuaXAoIGNvbGxlY3Rpb24sIGFyZ3MsIGNhbGxiYWNrLCBpZ25vcmVkICkge1xuXG5cdC8vIEZsYXR0ZW4gYW55IG5lc3RlZCBhcnJheXNcblx0YXJncyA9IGNvbmNhdC5hcHBseSggW10sIGFyZ3MgKTtcblxuXHR2YXIgZnJhZ21lbnQsIGZpcnN0LCBzY3JpcHRzLCBoYXNTY3JpcHRzLCBub2RlLCBkb2MsXG5cdFx0aSA9IDAsXG5cdFx0bCA9IGNvbGxlY3Rpb24ubGVuZ3RoLFxuXHRcdGlOb0Nsb25lID0gbCAtIDEsXG5cdFx0dmFsdWUgPSBhcmdzWyAwIF0sXG5cdFx0aXNGdW5jdGlvbiA9IGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApO1xuXG5cdC8vIFdlIGNhbid0IGNsb25lTm9kZSBmcmFnbWVudHMgdGhhdCBjb250YWluIGNoZWNrZWQsIGluIFdlYktpdFxuXHRpZiAoIGlzRnVuY3Rpb24gfHxcblx0XHRcdCggbCA+IDEgJiYgdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmXG5cdFx0XHRcdCFzdXBwb3J0LmNoZWNrQ2xvbmUgJiYgcmNoZWNrZWQudGVzdCggdmFsdWUgKSApICkge1xuXHRcdHJldHVybiBjb2xsZWN0aW9uLmVhY2goIGZ1bmN0aW9uKCBpbmRleCApIHtcblx0XHRcdHZhciBzZWxmID0gY29sbGVjdGlvbi5lcSggaW5kZXggKTtcblx0XHRcdGlmICggaXNGdW5jdGlvbiApIHtcblx0XHRcdFx0YXJnc1sgMCBdID0gdmFsdWUuY2FsbCggdGhpcywgaW5kZXgsIHNlbGYuaHRtbCgpICk7XG5cdFx0XHR9XG5cdFx0XHRkb21NYW5pcCggc2VsZiwgYXJncywgY2FsbGJhY2ssIGlnbm9yZWQgKTtcblx0XHR9ICk7XG5cdH1cblxuXHRpZiAoIGwgKSB7XG5cdFx0ZnJhZ21lbnQgPSBidWlsZEZyYWdtZW50KCBhcmdzLCBjb2xsZWN0aW9uWyAwIF0ub3duZXJEb2N1bWVudCwgZmFsc2UsIGNvbGxlY3Rpb24sIGlnbm9yZWQgKTtcblx0XHRmaXJzdCA9IGZyYWdtZW50LmZpcnN0Q2hpbGQ7XG5cblx0XHRpZiAoIGZyYWdtZW50LmNoaWxkTm9kZXMubGVuZ3RoID09PSAxICkge1xuXHRcdFx0ZnJhZ21lbnQgPSBmaXJzdDtcblx0XHR9XG5cblx0XHQvLyBSZXF1aXJlIGVpdGhlciBuZXcgY29udGVudCBvciBhbiBpbnRlcmVzdCBpbiBpZ25vcmVkIGVsZW1lbnRzIHRvIGludm9rZSB0aGUgY2FsbGJhY2tcblx0XHRpZiAoIGZpcnN0IHx8IGlnbm9yZWQgKSB7XG5cdFx0XHRzY3JpcHRzID0galF1ZXJ5Lm1hcCggZ2V0QWxsKCBmcmFnbWVudCwgXCJzY3JpcHRcIiApLCBkaXNhYmxlU2NyaXB0ICk7XG5cdFx0XHRoYXNTY3JpcHRzID0gc2NyaXB0cy5sZW5ndGg7XG5cblx0XHRcdC8vIFVzZSB0aGUgb3JpZ2luYWwgZnJhZ21lbnQgZm9yIHRoZSBsYXN0IGl0ZW1cblx0XHRcdC8vIGluc3RlYWQgb2YgdGhlIGZpcnN0IGJlY2F1c2UgaXQgY2FuIGVuZCB1cFxuXHRcdFx0Ly8gYmVpbmcgZW1wdGllZCBpbmNvcnJlY3RseSBpbiBjZXJ0YWluIHNpdHVhdGlvbnMgKCM4MDcwKS5cblx0XHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0bm9kZSA9IGZyYWdtZW50O1xuXG5cdFx0XHRcdGlmICggaSAhPT0gaU5vQ2xvbmUgKSB7XG5cdFx0XHRcdFx0bm9kZSA9IGpRdWVyeS5jbG9uZSggbm9kZSwgdHJ1ZSwgdHJ1ZSApO1xuXG5cdFx0XHRcdFx0Ly8gS2VlcCByZWZlcmVuY2VzIHRvIGNsb25lZCBzY3JpcHRzIGZvciBsYXRlciByZXN0b3JhdGlvblxuXHRcdFx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblxuXHRcdFx0XHRcdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMCBvbmx5LCBQaGFudG9tSlMgMSBvbmx5XG5cdFx0XHRcdFx0XHQvLyBwdXNoLmFwcGx5KF8sIGFycmF5bGlrZSkgdGhyb3dzIG9uIGFuY2llbnQgV2ViS2l0XG5cdFx0XHRcdFx0XHRqUXVlcnkubWVyZ2UoIHNjcmlwdHMsIGdldEFsbCggbm9kZSwgXCJzY3JpcHRcIiApICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Y2FsbGJhY2suY2FsbCggY29sbGVjdGlvblsgaSBdLCBub2RlLCBpICk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggaGFzU2NyaXB0cyApIHtcblx0XHRcdFx0ZG9jID0gc2NyaXB0c1sgc2NyaXB0cy5sZW5ndGggLSAxIF0ub3duZXJEb2N1bWVudDtcblxuXHRcdFx0XHQvLyBSZWVuYWJsZSBzY3JpcHRzXG5cdFx0XHRcdGpRdWVyeS5tYXAoIHNjcmlwdHMsIHJlc3RvcmVTY3JpcHQgKTtcblxuXHRcdFx0XHQvLyBFdmFsdWF0ZSBleGVjdXRhYmxlIHNjcmlwdHMgb24gZmlyc3QgZG9jdW1lbnQgaW5zZXJ0aW9uXG5cdFx0XHRcdGZvciAoIGkgPSAwOyBpIDwgaGFzU2NyaXB0czsgaSsrICkge1xuXHRcdFx0XHRcdG5vZGUgPSBzY3JpcHRzWyBpIF07XG5cdFx0XHRcdFx0aWYgKCByc2NyaXB0VHlwZS50ZXN0KCBub2RlLnR5cGUgfHwgXCJcIiApICYmXG5cdFx0XHRcdFx0XHQhZGF0YVByaXYuYWNjZXNzKCBub2RlLCBcImdsb2JhbEV2YWxcIiApICYmXG5cdFx0XHRcdFx0XHRqUXVlcnkuY29udGFpbnMoIGRvYywgbm9kZSApICkge1xuXG5cdFx0XHRcdFx0XHRpZiAoIG5vZGUuc3JjICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIE9wdGlvbmFsIEFKQVggZGVwZW5kZW5jeSwgYnV0IHdvbid0IHJ1biBzY3JpcHRzIGlmIG5vdCBwcmVzZW50XG5cdFx0XHRcdFx0XHRcdGlmICggalF1ZXJ5Ll9ldmFsVXJsICkge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5fZXZhbFVybCggbm9kZS5zcmMgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0RE9NRXZhbCggbm9kZS50ZXh0Q29udGVudC5yZXBsYWNlKCByY2xlYW5TY3JpcHQsIFwiXCIgKSwgZG9jICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGNvbGxlY3Rpb247XG59XG5cbmZ1bmN0aW9uIHJlbW92ZSggZWxlbSwgc2VsZWN0b3IsIGtlZXBEYXRhICkge1xuXHR2YXIgbm9kZSxcblx0XHRub2RlcyA9IHNlbGVjdG9yID8galF1ZXJ5LmZpbHRlciggc2VsZWN0b3IsIGVsZW0gKSA6IGVsZW0sXG5cdFx0aSA9IDA7XG5cblx0Zm9yICggOyAoIG5vZGUgPSBub2Rlc1sgaSBdICkgIT0gbnVsbDsgaSsrICkge1xuXHRcdGlmICggIWtlZXBEYXRhICYmIG5vZGUubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIG5vZGUgKSApO1xuXHRcdH1cblxuXHRcdGlmICggbm9kZS5wYXJlbnROb2RlICkge1xuXHRcdFx0aWYgKCBrZWVwRGF0YSAmJiBqUXVlcnkuY29udGFpbnMoIG5vZGUub3duZXJEb2N1bWVudCwgbm9kZSApICkge1xuXHRcdFx0XHRzZXRHbG9iYWxFdmFsKCBnZXRBbGwoIG5vZGUsIFwic2NyaXB0XCIgKSApO1xuXHRcdFx0fVxuXHRcdFx0bm9kZS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCBub2RlICk7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIGVsZW07XG59XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0aHRtbFByZWZpbHRlcjogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0cmV0dXJuIGh0bWwucmVwbGFjZSggcnhodG1sVGFnLCBcIjwkMT48LyQyPlwiICk7XG5cdH0sXG5cblx0Y2xvbmU6IGZ1bmN0aW9uKCBlbGVtLCBkYXRhQW5kRXZlbnRzLCBkZWVwRGF0YUFuZEV2ZW50cyApIHtcblx0XHR2YXIgaSwgbCwgc3JjRWxlbWVudHMsIGRlc3RFbGVtZW50cyxcblx0XHRcdGNsb25lID0gZWxlbS5jbG9uZU5vZGUoIHRydWUgKSxcblx0XHRcdGluUGFnZSA9IGpRdWVyeS5jb250YWlucyggZWxlbS5vd25lckRvY3VtZW50LCBlbGVtICk7XG5cblx0XHQvLyBGaXggSUUgY2xvbmluZyBpc3N1ZXNcblx0XHRpZiAoICFzdXBwb3J0Lm5vQ2xvbmVDaGVja2VkICYmICggZWxlbS5ub2RlVHlwZSA9PT0gMSB8fCBlbGVtLm5vZGVUeXBlID09PSAxMSApICYmXG5cdFx0XHRcdCFqUXVlcnkuaXNYTUxEb2MoIGVsZW0gKSApIHtcblxuXHRcdFx0Ly8gV2UgZXNjaGV3IFNpenpsZSBoZXJlIGZvciBwZXJmb3JtYW5jZSByZWFzb25zOiBodHRwczovL2pzcGVyZi5jb20vZ2V0YWxsLXZzLXNpenpsZS8yXG5cdFx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lICk7XG5cdFx0XHRzcmNFbGVtZW50cyA9IGdldEFsbCggZWxlbSApO1xuXG5cdFx0XHRmb3IgKCBpID0gMCwgbCA9IHNyY0VsZW1lbnRzLmxlbmd0aDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdFx0Zml4SW5wdXQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ29weSB0aGUgZXZlbnRzIGZyb20gdGhlIG9yaWdpbmFsIHRvIHRoZSBjbG9uZVxuXHRcdGlmICggZGF0YUFuZEV2ZW50cyApIHtcblx0XHRcdGlmICggZGVlcERhdGFBbmRFdmVudHMgKSB7XG5cdFx0XHRcdHNyY0VsZW1lbnRzID0gc3JjRWxlbWVudHMgfHwgZ2V0QWxsKCBlbGVtICk7XG5cdFx0XHRcdGRlc3RFbGVtZW50cyA9IGRlc3RFbGVtZW50cyB8fCBnZXRBbGwoIGNsb25lICk7XG5cblx0XHRcdFx0Zm9yICggaSA9IDAsIGwgPSBzcmNFbGVtZW50cy5sZW5ndGg7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRcdFx0Y2xvbmVDb3B5RXZlbnQoIHNyY0VsZW1lbnRzWyBpIF0sIGRlc3RFbGVtZW50c1sgaSBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGNsb25lQ29weUV2ZW50KCBlbGVtLCBjbG9uZSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFByZXNlcnZlIHNjcmlwdCBldmFsdWF0aW9uIGhpc3Rvcnlcblx0XHRkZXN0RWxlbWVudHMgPSBnZXRBbGwoIGNsb25lLCBcInNjcmlwdFwiICk7XG5cdFx0aWYgKCBkZXN0RWxlbWVudHMubGVuZ3RoID4gMCApIHtcblx0XHRcdHNldEdsb2JhbEV2YWwoIGRlc3RFbGVtZW50cywgIWluUGFnZSAmJiBnZXRBbGwoIGVsZW0sIFwic2NyaXB0XCIgKSApO1xuXHRcdH1cblxuXHRcdC8vIFJldHVybiB0aGUgY2xvbmVkIHNldFxuXHRcdHJldHVybiBjbG9uZTtcblx0fSxcblxuXHRjbGVhbkRhdGE6IGZ1bmN0aW9uKCBlbGVtcyApIHtcblx0XHR2YXIgZGF0YSwgZWxlbSwgdHlwZSxcblx0XHRcdHNwZWNpYWwgPSBqUXVlcnkuZXZlbnQuc3BlY2lhbCxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyAoIGVsZW0gPSBlbGVtc1sgaSBdICkgIT09IHVuZGVmaW5lZDsgaSsrICkge1xuXHRcdFx0aWYgKCBhY2NlcHREYXRhKCBlbGVtICkgKSB7XG5cdFx0XHRcdGlmICggKCBkYXRhID0gZWxlbVsgZGF0YVByaXYuZXhwYW5kbyBdICkgKSB7XG5cdFx0XHRcdFx0aWYgKCBkYXRhLmV2ZW50cyApIHtcblx0XHRcdFx0XHRcdGZvciAoIHR5cGUgaW4gZGF0YS5ldmVudHMgKSB7XG5cdFx0XHRcdFx0XHRcdGlmICggc3BlY2lhbFsgdHlwZSBdICkge1xuXHRcdFx0XHRcdFx0XHRcdGpRdWVyeS5ldmVudC5yZW1vdmUoIGVsZW0sIHR5cGUgKTtcblxuXHRcdFx0XHRcdFx0XHQvLyBUaGlzIGlzIGEgc2hvcnRjdXQgdG8gYXZvaWQgalF1ZXJ5LmV2ZW50LnJlbW92ZSdzIG92ZXJoZWFkXG5cdFx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdFx0alF1ZXJ5LnJlbW92ZUV2ZW50KCBlbGVtLCB0eXBlLCBkYXRhLmhhbmRsZSApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogQ2hyb21lIDw9MzUgLSA0NStcblx0XHRcdFx0XHQvLyBBc3NpZ24gdW5kZWZpbmVkIGluc3RlYWQgb2YgdXNpbmcgZGVsZXRlLCBzZWUgRGF0YSNyZW1vdmVcblx0XHRcdFx0XHRlbGVtWyBkYXRhUHJpdi5leHBhbmRvIF0gPSB1bmRlZmluZWQ7XG5cdFx0XHRcdH1cblx0XHRcdFx0aWYgKCBlbGVtWyBkYXRhVXNlci5leHBhbmRvIF0gKSB7XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBDaHJvbWUgPD0zNSAtIDQ1K1xuXHRcdFx0XHRcdC8vIEFzc2lnbiB1bmRlZmluZWQgaW5zdGVhZCBvZiB1c2luZyBkZWxldGUsIHNlZSBEYXRhI3JlbW92ZVxuXHRcdFx0XHRcdGVsZW1bIGRhdGFVc2VyLmV4cGFuZG8gXSA9IHVuZGVmaW5lZDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGRldGFjaDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHJldHVybiByZW1vdmUoIHRoaXMsIHNlbGVjdG9yLCB0cnVlICk7XG5cdH0sXG5cblx0cmVtb3ZlOiBmdW5jdGlvbiggc2VsZWN0b3IgKSB7XG5cdFx0cmV0dXJuIHJlbW92ZSggdGhpcywgc2VsZWN0b3IgKTtcblx0fSxcblxuXHR0ZXh0OiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0cmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRqUXVlcnkudGV4dCggdGhpcyApIDpcblx0XHRcdFx0dGhpcy5lbXB0eSgpLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSA9PT0gMSB8fCB0aGlzLm5vZGVUeXBlID09PSAxMSB8fCB0aGlzLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHRcdFx0dGhpcy50ZXh0Q29udGVudCA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdH0sIG51bGwsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH0sXG5cblx0YXBwZW5kOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMubm9kZVR5cGUgPT09IDEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gMTEgfHwgdGhpcy5ub2RlVHlwZSA9PT0gOSApIHtcblx0XHRcdFx0dmFyIHRhcmdldCA9IG1hbmlwdWxhdGlvblRhcmdldCggdGhpcywgZWxlbSApO1xuXHRcdFx0XHR0YXJnZXQuYXBwZW5kQ2hpbGQoIGVsZW0gKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0cHJlcGVuZDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLm5vZGVUeXBlID09PSAxIHx8IHRoaXMubm9kZVR5cGUgPT09IDExIHx8IHRoaXMubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHZhciB0YXJnZXQgPSBtYW5pcHVsYXRpb25UYXJnZXQoIHRoaXMsIGVsZW0gKTtcblx0XHRcdFx0dGFyZ2V0Lmluc2VydEJlZm9yZSggZWxlbSwgdGFyZ2V0LmZpcnN0Q2hpbGQgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0YmVmb3JlOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4gZG9tTWFuaXAoIHRoaXMsIGFyZ3VtZW50cywgZnVuY3Rpb24oIGVsZW0gKSB7XG5cdFx0XHRpZiAoIHRoaXMucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0dGhpcy5wYXJlbnROb2RlLmluc2VydEJlZm9yZSggZWxlbSwgdGhpcyApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblxuXHRhZnRlcjogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0aWYgKCB0aGlzLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHRoaXMucGFyZW50Tm9kZS5pbnNlcnRCZWZvcmUoIGVsZW0sIHRoaXMubmV4dFNpYmxpbmcgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0ZW1wdHk6IGZ1bmN0aW9uKCkge1xuXHRcdHZhciBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRmb3IgKCA7ICggZWxlbSA9IHRoaXNbIGkgXSApICE9IG51bGw7IGkrKyApIHtcblx0XHRcdGlmICggZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdFx0XHQvLyBQcmV2ZW50IG1lbW9yeSBsZWFrc1xuXHRcdFx0XHRqUXVlcnkuY2xlYW5EYXRhKCBnZXRBbGwoIGVsZW0sIGZhbHNlICkgKTtcblxuXHRcdFx0XHQvLyBSZW1vdmUgYW55IHJlbWFpbmluZyBub2Rlc1xuXHRcdFx0XHRlbGVtLnRleHRDb250ZW50ID0gXCJcIjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRjbG9uZTogZnVuY3Rpb24oIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICkge1xuXHRcdGRhdGFBbmRFdmVudHMgPSBkYXRhQW5kRXZlbnRzID09IG51bGwgPyBmYWxzZSA6IGRhdGFBbmRFdmVudHM7XG5cdFx0ZGVlcERhdGFBbmRFdmVudHMgPSBkZWVwRGF0YUFuZEV2ZW50cyA9PSBudWxsID8gZGF0YUFuZEV2ZW50cyA6IGRlZXBEYXRhQW5kRXZlbnRzO1xuXG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBqUXVlcnkuY2xvbmUoIHRoaXMsIGRhdGFBbmRFdmVudHMsIGRlZXBEYXRhQW5kRXZlbnRzICk7XG5cdFx0fSApO1xuXHR9LFxuXG5cdGh0bWw6IGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0XHR2YXIgZWxlbSA9IHRoaXNbIDAgXSB8fCB7fSxcblx0XHRcdFx0aSA9IDAsXG5cdFx0XHRcdGwgPSB0aGlzLmxlbmd0aDtcblxuXHRcdFx0aWYgKCB2YWx1ZSA9PT0gdW5kZWZpbmVkICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdHJldHVybiBlbGVtLmlubmVySFRNTDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2VlIGlmIHdlIGNhbiB0YWtlIGEgc2hvcnRjdXQgYW5kIGp1c3QgdXNlIGlubmVySFRNTFxuXHRcdFx0aWYgKCB0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIgJiYgIXJub0lubmVyaHRtbC50ZXN0KCB2YWx1ZSApICYmXG5cdFx0XHRcdCF3cmFwTWFwWyAoIHJ0YWdOYW1lLmV4ZWMoIHZhbHVlICkgfHwgWyBcIlwiLCBcIlwiIF0gKVsgMSBdLnRvTG93ZXJDYXNlKCkgXSApIHtcblxuXHRcdFx0XHR2YWx1ZSA9IGpRdWVyeS5odG1sUHJlZmlsdGVyKCB2YWx1ZSApO1xuXG5cdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdFx0ZWxlbSA9IHRoaXNbIGkgXSB8fCB7fTtcblxuXHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIGVsZW1lbnQgbm9kZXMgYW5kIHByZXZlbnQgbWVtb3J5IGxlYWtzXG5cdFx0XHRcdFx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHRcdFx0XHRcdGpRdWVyeS5jbGVhbkRhdGEoIGdldEFsbCggZWxlbSwgZmFsc2UgKSApO1xuXHRcdFx0XHRcdFx0XHRlbGVtLmlubmVySFRNTCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGVsZW0gPSAwO1xuXG5cdFx0XHRcdC8vIElmIHVzaW5nIGlubmVySFRNTCB0aHJvd3MgYW4gZXhjZXB0aW9uLCB1c2UgdGhlIGZhbGxiYWNrIG1ldGhvZFxuXHRcdFx0XHR9IGNhdGNoICggZSApIHt9XG5cdFx0XHR9XG5cblx0XHRcdGlmICggZWxlbSApIHtcblx0XHRcdFx0dGhpcy5lbXB0eSgpLmFwcGVuZCggdmFsdWUgKTtcblx0XHRcdH1cblx0XHR9LCBudWxsLCB2YWx1ZSwgYXJndW1lbnRzLmxlbmd0aCApO1xuXHR9LFxuXG5cdHJlcGxhY2VXaXRoOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgaWdub3JlZCA9IFtdO1xuXG5cdFx0Ly8gTWFrZSB0aGUgY2hhbmdlcywgcmVwbGFjaW5nIGVhY2ggbm9uLWlnbm9yZWQgY29udGV4dCBlbGVtZW50IHdpdGggdGhlIG5ldyBjb250ZW50XG5cdFx0cmV0dXJuIGRvbU1hbmlwKCB0aGlzLCBhcmd1bWVudHMsIGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0dmFyIHBhcmVudCA9IHRoaXMucGFyZW50Tm9kZTtcblxuXHRcdFx0aWYgKCBqUXVlcnkuaW5BcnJheSggdGhpcywgaWdub3JlZCApIDwgMCApIHtcblx0XHRcdFx0alF1ZXJ5LmNsZWFuRGF0YSggZ2V0QWxsKCB0aGlzICkgKTtcblx0XHRcdFx0aWYgKCBwYXJlbnQgKSB7XG5cdFx0XHRcdFx0cGFyZW50LnJlcGxhY2VDaGlsZCggZWxlbSwgdGhpcyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHQvLyBGb3JjZSBjYWxsYmFjayBpbnZvY2F0aW9uXG5cdFx0fSwgaWdub3JlZCApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5lYWNoKCB7XG5cdGFwcGVuZFRvOiBcImFwcGVuZFwiLFxuXHRwcmVwZW5kVG86IFwicHJlcGVuZFwiLFxuXHRpbnNlcnRCZWZvcmU6IFwiYmVmb3JlXCIsXG5cdGluc2VydEFmdGVyOiBcImFmdGVyXCIsXG5cdHJlcGxhY2VBbGw6IFwicmVwbGFjZVdpdGhcIlxufSwgZnVuY3Rpb24oIG5hbWUsIG9yaWdpbmFsICkge1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgZWxlbXMsXG5cdFx0XHRyZXQgPSBbXSxcblx0XHRcdGluc2VydCA9IGpRdWVyeSggc2VsZWN0b3IgKSxcblx0XHRcdGxhc3QgPSBpbnNlcnQubGVuZ3RoIC0gMSxcblx0XHRcdGkgPSAwO1xuXG5cdFx0Zm9yICggOyBpIDw9IGxhc3Q7IGkrKyApIHtcblx0XHRcdGVsZW1zID0gaSA9PT0gbGFzdCA/IHRoaXMgOiB0aGlzLmNsb25lKCB0cnVlICk7XG5cdFx0XHRqUXVlcnkoIGluc2VydFsgaSBdIClbIG9yaWdpbmFsIF0oIGVsZW1zICk7XG5cblx0XHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgPD00LjAgb25seSwgUGhhbnRvbUpTIDEgb25seVxuXHRcdFx0Ly8gLmdldCgpIGJlY2F1c2UgcHVzaC5hcHBseShfLCBhcnJheWxpa2UpIHRocm93cyBvbiBhbmNpZW50IFdlYktpdFxuXHRcdFx0cHVzaC5hcHBseSggcmV0LCBlbGVtcy5nZXQoKSApO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLnB1c2hTdGFjayggcmV0ICk7XG5cdH07XG59ICk7XG52YXIgcm1hcmdpbiA9ICggL15tYXJnaW4vICk7XG5cbnZhciBybnVtbm9ucHggPSBuZXcgUmVnRXhwKCBcIl4oXCIgKyBwbnVtICsgXCIpKD8hcHgpW2EteiVdKyRcIiwgXCJpXCIgKTtcblxudmFyIGdldFN0eWxlcyA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5LCBGaXJlZm94IDw9MzAgKCMxNTA5OCwgIzE0MTUwKVxuXHRcdC8vIElFIHRocm93cyBvbiBlbGVtZW50cyBjcmVhdGVkIGluIHBvcHVwc1xuXHRcdC8vIEZGIG1lYW53aGlsZSB0aHJvd3Mgb24gZnJhbWUgZWxlbWVudHMgdGhyb3VnaCBcImRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGVcIlxuXHRcdHZhciB2aWV3ID0gZWxlbS5vd25lckRvY3VtZW50LmRlZmF1bHRWaWV3O1xuXG5cdFx0aWYgKCAhdmlldyB8fCAhdmlldy5vcGVuZXIgKSB7XG5cdFx0XHR2aWV3ID0gd2luZG93O1xuXHRcdH1cblxuXHRcdHJldHVybiB2aWV3LmdldENvbXB1dGVkU3R5bGUoIGVsZW0gKTtcblx0fTtcblxuXG5cbiggZnVuY3Rpb24oKSB7XG5cblx0Ly8gRXhlY3V0aW5nIGJvdGggcGl4ZWxQb3NpdGlvbiAmIGJveFNpemluZ1JlbGlhYmxlIHRlc3RzIHJlcXVpcmUgb25seSBvbmUgbGF5b3V0XG5cdC8vIHNvIHRoZXkncmUgZXhlY3V0ZWQgYXQgdGhlIHNhbWUgdGltZSB0byBzYXZlIHRoZSBzZWNvbmQgY29tcHV0YXRpb24uXG5cdGZ1bmN0aW9uIGNvbXB1dGVTdHlsZVRlc3RzKCkge1xuXG5cdFx0Ly8gVGhpcyBpcyBhIHNpbmdsZXRvbiwgd2UgbmVlZCB0byBleGVjdXRlIGl0IG9ubHkgb25jZVxuXHRcdGlmICggIWRpdiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRkaXYuc3R5bGUuY3NzVGV4dCA9XG5cdFx0XHRcImJveC1zaXppbmc6Ym9yZGVyLWJveDtcIiArXG5cdFx0XHRcInBvc2l0aW9uOnJlbGF0aXZlO2Rpc3BsYXk6YmxvY2s7XCIgK1xuXHRcdFx0XCJtYXJnaW46YXV0bztib3JkZXI6MXB4O3BhZGRpbmc6MXB4O1wiICtcblx0XHRcdFwidG9wOjElO3dpZHRoOjUwJVwiO1xuXHRcdGRpdi5pbm5lckhUTUwgPSBcIlwiO1xuXHRcdGRvY3VtZW50RWxlbWVudC5hcHBlbmRDaGlsZCggY29udGFpbmVyICk7XG5cblx0XHR2YXIgZGl2U3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSggZGl2ICk7XG5cdFx0cGl4ZWxQb3NpdGlvblZhbCA9IGRpdlN0eWxlLnRvcCAhPT0gXCIxJVwiO1xuXG5cdFx0Ly8gU3VwcG9ydDogQW5kcm9pZCA0LjAgLSA0LjMgb25seSwgRmlyZWZveCA8PTMgLSA0NFxuXHRcdHJlbGlhYmxlTWFyZ2luTGVmdFZhbCA9IGRpdlN0eWxlLm1hcmdpbkxlZnQgPT09IFwiMnB4XCI7XG5cdFx0Ym94U2l6aW5nUmVsaWFibGVWYWwgPSBkaXZTdHlsZS53aWR0aCA9PT0gXCI0cHhcIjtcblxuXHRcdC8vIFN1cHBvcnQ6IEFuZHJvaWQgNC4wIC0gNC4zIG9ubHlcblx0XHQvLyBTb21lIHN0eWxlcyBjb21lIGJhY2sgd2l0aCBwZXJjZW50YWdlIHZhbHVlcywgZXZlbiB0aG91Z2ggdGhleSBzaG91bGRuJ3Rcblx0XHRkaXYuc3R5bGUubWFyZ2luUmlnaHQgPSBcIjUwJVwiO1xuXHRcdHBpeGVsTWFyZ2luUmlnaHRWYWwgPSBkaXZTdHlsZS5tYXJnaW5SaWdodCA9PT0gXCI0cHhcIjtcblxuXHRcdGRvY3VtZW50RWxlbWVudC5yZW1vdmVDaGlsZCggY29udGFpbmVyICk7XG5cblx0XHQvLyBOdWxsaWZ5IHRoZSBkaXYgc28gaXQgd291bGRuJ3QgYmUgc3RvcmVkIGluIHRoZSBtZW1vcnkgYW5kXG5cdFx0Ly8gaXQgd2lsbCBhbHNvIGJlIGEgc2lnbiB0aGF0IGNoZWNrcyBhbHJlYWR5IHBlcmZvcm1lZFxuXHRcdGRpdiA9IG51bGw7XG5cdH1cblxuXHR2YXIgcGl4ZWxQb3NpdGlvblZhbCwgYm94U2l6aW5nUmVsaWFibGVWYWwsIHBpeGVsTWFyZ2luUmlnaHRWYWwsIHJlbGlhYmxlTWFyZ2luTGVmdFZhbCxcblx0XHRjb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICksXG5cdFx0ZGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJkaXZcIiApO1xuXG5cdC8vIEZpbmlzaCBlYXJseSBpbiBsaW1pdGVkIChub24tYnJvd3NlcikgZW52aXJvbm1lbnRzXG5cdGlmICggIWRpdi5zdHlsZSApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHQvLyBTdXBwb3J0OiBJRSA8PTkgLSAxMSBvbmx5XG5cdC8vIFN0eWxlIG9mIGNsb25lZCBlbGVtZW50IGFmZmVjdHMgc291cmNlIGVsZW1lbnQgY2xvbmVkICgjODkwOClcblx0ZGl2LnN0eWxlLmJhY2tncm91bmRDbGlwID0gXCJjb250ZW50LWJveFwiO1xuXHRkaXYuY2xvbmVOb2RlKCB0cnVlICkuc3R5bGUuYmFja2dyb3VuZENsaXAgPSBcIlwiO1xuXHRzdXBwb3J0LmNsZWFyQ2xvbmVTdHlsZSA9IGRpdi5zdHlsZS5iYWNrZ3JvdW5kQ2xpcCA9PT0gXCJjb250ZW50LWJveFwiO1xuXG5cdGNvbnRhaW5lci5zdHlsZS5jc3NUZXh0ID0gXCJib3JkZXI6MDt3aWR0aDo4cHg7aGVpZ2h0OjA7dG9wOjA7bGVmdDotOTk5OXB4O1wiICtcblx0XHRcInBhZGRpbmc6MDttYXJnaW4tdG9wOjFweDtwb3NpdGlvbjphYnNvbHV0ZVwiO1xuXHRjb250YWluZXIuYXBwZW5kQ2hpbGQoIGRpdiApO1xuXG5cdGpRdWVyeS5leHRlbmQoIHN1cHBvcnQsIHtcblx0XHRwaXhlbFBvc2l0aW9uOiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcGl4ZWxQb3NpdGlvblZhbDtcblx0XHR9LFxuXHRcdGJveFNpemluZ1JlbGlhYmxlOiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gYm94U2l6aW5nUmVsaWFibGVWYWw7XG5cdFx0fSxcblx0XHRwaXhlbE1hcmdpblJpZ2h0OiBmdW5jdGlvbigpIHtcblx0XHRcdGNvbXB1dGVTdHlsZVRlc3RzKCk7XG5cdFx0XHRyZXR1cm4gcGl4ZWxNYXJnaW5SaWdodFZhbDtcblx0XHR9LFxuXHRcdHJlbGlhYmxlTWFyZ2luTGVmdDogZnVuY3Rpb24oKSB7XG5cdFx0XHRjb21wdXRlU3R5bGVUZXN0cygpO1xuXHRcdFx0cmV0dXJuIHJlbGlhYmxlTWFyZ2luTGVmdFZhbDtcblx0XHR9XG5cdH0gKTtcbn0gKSgpO1xuXG5cbmZ1bmN0aW9uIGN1ckNTUyggZWxlbSwgbmFtZSwgY29tcHV0ZWQgKSB7XG5cdHZhciB3aWR0aCwgbWluV2lkdGgsIG1heFdpZHRoLCByZXQsXG5cblx0XHQvLyBTdXBwb3J0OiBGaXJlZm94IDUxK1xuXHRcdC8vIFJldHJpZXZpbmcgc3R5bGUgYmVmb3JlIGNvbXB1dGVkIHNvbWVob3dcblx0XHQvLyBmaXhlcyBhbiBpc3N1ZSB3aXRoIGdldHRpbmcgd3JvbmcgdmFsdWVzXG5cdFx0Ly8gb24gZGV0YWNoZWQgZWxlbWVudHNcblx0XHRzdHlsZSA9IGVsZW0uc3R5bGU7XG5cblx0Y29tcHV0ZWQgPSBjb21wdXRlZCB8fCBnZXRTdHlsZXMoIGVsZW0gKTtcblxuXHQvLyBnZXRQcm9wZXJ0eVZhbHVlIGlzIG5lZWRlZCBmb3I6XG5cdC8vICAgLmNzcygnZmlsdGVyJykgKElFIDkgb25seSwgIzEyNTM3KVxuXHQvLyAgIC5jc3MoJy0tY3VzdG9tUHJvcGVydHkpICgjMzE0NClcblx0aWYgKCBjb21wdXRlZCApIHtcblx0XHRyZXQgPSBjb21wdXRlZC5nZXRQcm9wZXJ0eVZhbHVlKCBuYW1lICkgfHwgY29tcHV0ZWRbIG5hbWUgXTtcblxuXHRcdGlmICggcmV0ID09PSBcIlwiICYmICFqUXVlcnkuY29udGFpbnMoIGVsZW0ub3duZXJEb2N1bWVudCwgZWxlbSApICkge1xuXHRcdFx0cmV0ID0galF1ZXJ5LnN0eWxlKCBlbGVtLCBuYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gQSB0cmlidXRlIHRvIHRoZSBcImF3ZXNvbWUgaGFjayBieSBEZWFuIEVkd2FyZHNcIlxuXHRcdC8vIEFuZHJvaWQgQnJvd3NlciByZXR1cm5zIHBlcmNlbnRhZ2UgZm9yIHNvbWUgdmFsdWVzLFxuXHRcdC8vIGJ1dCB3aWR0aCBzZWVtcyB0byBiZSByZWxpYWJseSBwaXhlbHMuXG5cdFx0Ly8gVGhpcyBpcyBhZ2FpbnN0IHRoZSBDU1NPTSBkcmFmdCBzcGVjOlxuXHRcdC8vIGh0dHBzOi8vZHJhZnRzLmNzc3dnLm9yZy9jc3NvbS8jcmVzb2x2ZWQtdmFsdWVzXG5cdFx0aWYgKCAhc3VwcG9ydC5waXhlbE1hcmdpblJpZ2h0KCkgJiYgcm51bW5vbnB4LnRlc3QoIHJldCApICYmIHJtYXJnaW4udGVzdCggbmFtZSApICkge1xuXG5cdFx0XHQvLyBSZW1lbWJlciB0aGUgb3JpZ2luYWwgdmFsdWVzXG5cdFx0XHR3aWR0aCA9IHN0eWxlLndpZHRoO1xuXHRcdFx0bWluV2lkdGggPSBzdHlsZS5taW5XaWR0aDtcblx0XHRcdG1heFdpZHRoID0gc3R5bGUubWF4V2lkdGg7XG5cblx0XHRcdC8vIFB1dCBpbiB0aGUgbmV3IHZhbHVlcyB0byBnZXQgYSBjb21wdXRlZCB2YWx1ZSBvdXRcblx0XHRcdHN0eWxlLm1pbldpZHRoID0gc3R5bGUubWF4V2lkdGggPSBzdHlsZS53aWR0aCA9IHJldDtcblx0XHRcdHJldCA9IGNvbXB1dGVkLndpZHRoO1xuXG5cdFx0XHQvLyBSZXZlcnQgdGhlIGNoYW5nZWQgdmFsdWVzXG5cdFx0XHRzdHlsZS53aWR0aCA9IHdpZHRoO1xuXHRcdFx0c3R5bGUubWluV2lkdGggPSBtaW5XaWR0aDtcblx0XHRcdHN0eWxlLm1heFdpZHRoID0gbWF4V2lkdGg7XG5cdFx0fVxuXHR9XG5cblx0cmV0dXJuIHJldCAhPT0gdW5kZWZpbmVkID9cblxuXHRcdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExIG9ubHlcblx0XHQvLyBJRSByZXR1cm5zIHpJbmRleCB2YWx1ZSBhcyBhbiBpbnRlZ2VyLlxuXHRcdHJldCArIFwiXCIgOlxuXHRcdHJldDtcbn1cblxuXG5mdW5jdGlvbiBhZGRHZXRIb29rSWYoIGNvbmRpdGlvbkZuLCBob29rRm4gKSB7XG5cblx0Ly8gRGVmaW5lIHRoZSBob29rLCB3ZSdsbCBjaGVjayBvbiB0aGUgZmlyc3QgcnVuIGlmIGl0J3MgcmVhbGx5IG5lZWRlZC5cblx0cmV0dXJuIHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCBjb25kaXRpb25GbigpICkge1xuXG5cdFx0XHRcdC8vIEhvb2sgbm90IG5lZWRlZCAob3IgaXQncyBub3QgcG9zc2libGUgdG8gdXNlIGl0IGR1ZVxuXHRcdFx0XHQvLyB0byBtaXNzaW5nIGRlcGVuZGVuY3kpLCByZW1vdmUgaXQuXG5cdFx0XHRcdGRlbGV0ZSB0aGlzLmdldDtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBIb29rIG5lZWRlZDsgcmVkZWZpbmUgaXQgc28gdGhhdCB0aGUgc3VwcG9ydCB0ZXN0IGlzIG5vdCBleGVjdXRlZCBhZ2Fpbi5cblx0XHRcdHJldHVybiAoIHRoaXMuZ2V0ID0gaG9va0ZuICkuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcdH1cblx0fTtcbn1cblxuXG52YXJcblxuXHQvLyBTd2FwcGFibGUgaWYgZGlzcGxheSBpcyBub25lIG9yIHN0YXJ0cyB3aXRoIHRhYmxlXG5cdC8vIGV4Y2VwdCBcInRhYmxlXCIsIFwidGFibGUtY2VsbFwiLCBvciBcInRhYmxlLWNhcHRpb25cIlxuXHQvLyBTZWUgaGVyZSBmb3IgZGlzcGxheSB2YWx1ZXM6IGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvQ1NTL2Rpc3BsYXlcblx0cmRpc3BsYXlzd2FwID0gL14obm9uZXx0YWJsZSg/IS1jW2VhXSkuKykvLFxuXHRyY3VzdG9tUHJvcCA9IC9eLS0vLFxuXHRjc3NTaG93ID0geyBwb3NpdGlvbjogXCJhYnNvbHV0ZVwiLCB2aXNpYmlsaXR5OiBcImhpZGRlblwiLCBkaXNwbGF5OiBcImJsb2NrXCIgfSxcblx0Y3NzTm9ybWFsVHJhbnNmb3JtID0ge1xuXHRcdGxldHRlclNwYWNpbmc6IFwiMFwiLFxuXHRcdGZvbnRXZWlnaHQ6IFwiNDAwXCJcblx0fSxcblxuXHRjc3NQcmVmaXhlcyA9IFsgXCJXZWJraXRcIiwgXCJNb3pcIiwgXCJtc1wiIF0sXG5cdGVtcHR5U3R5bGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImRpdlwiICkuc3R5bGU7XG5cbi8vIFJldHVybiBhIGNzcyBwcm9wZXJ0eSBtYXBwZWQgdG8gYSBwb3RlbnRpYWxseSB2ZW5kb3IgcHJlZml4ZWQgcHJvcGVydHlcbmZ1bmN0aW9uIHZlbmRvclByb3BOYW1lKCBuYW1lICkge1xuXG5cdC8vIFNob3J0Y3V0IGZvciBuYW1lcyB0aGF0IGFyZSBub3QgdmVuZG9yIHByZWZpeGVkXG5cdGlmICggbmFtZSBpbiBlbXB0eVN0eWxlICkge1xuXHRcdHJldHVybiBuYW1lO1xuXHR9XG5cblx0Ly8gQ2hlY2sgZm9yIHZlbmRvciBwcmVmaXhlZCBuYW1lc1xuXHR2YXIgY2FwTmFtZSA9IG5hbWVbIDAgXS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zbGljZSggMSApLFxuXHRcdGkgPSBjc3NQcmVmaXhlcy5sZW5ndGg7XG5cblx0d2hpbGUgKCBpLS0gKSB7XG5cdFx0bmFtZSA9IGNzc1ByZWZpeGVzWyBpIF0gKyBjYXBOYW1lO1xuXHRcdGlmICggbmFtZSBpbiBlbXB0eVN0eWxlICkge1xuXHRcdFx0cmV0dXJuIG5hbWU7XG5cdFx0fVxuXHR9XG59XG5cbi8vIFJldHVybiBhIHByb3BlcnR5IG1hcHBlZCBhbG9uZyB3aGF0IGpRdWVyeS5jc3NQcm9wcyBzdWdnZXN0cyBvciB0b1xuLy8gYSB2ZW5kb3IgcHJlZml4ZWQgcHJvcGVydHkuXG5mdW5jdGlvbiBmaW5hbFByb3BOYW1lKCBuYW1lICkge1xuXHR2YXIgcmV0ID0galF1ZXJ5LmNzc1Byb3BzWyBuYW1lIF07XG5cdGlmICggIXJldCApIHtcblx0XHRyZXQgPSBqUXVlcnkuY3NzUHJvcHNbIG5hbWUgXSA9IHZlbmRvclByb3BOYW1lKCBuYW1lICkgfHwgbmFtZTtcblx0fVxuXHRyZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBzZXRQb3NpdGl2ZU51bWJlciggZWxlbSwgdmFsdWUsIHN1YnRyYWN0ICkge1xuXG5cdC8vIEFueSByZWxhdGl2ZSAoKy8tKSB2YWx1ZXMgaGF2ZSBhbHJlYWR5IGJlZW5cblx0Ly8gbm9ybWFsaXplZCBhdCB0aGlzIHBvaW50XG5cdHZhciBtYXRjaGVzID0gcmNzc051bS5leGVjKCB2YWx1ZSApO1xuXHRyZXR1cm4gbWF0Y2hlcyA/XG5cblx0XHQvLyBHdWFyZCBhZ2FpbnN0IHVuZGVmaW5lZCBcInN1YnRyYWN0XCIsIGUuZy4sIHdoZW4gdXNlZCBhcyBpbiBjc3NIb29rc1xuXHRcdE1hdGgubWF4KCAwLCBtYXRjaGVzWyAyIF0gLSAoIHN1YnRyYWN0IHx8IDAgKSApICsgKCBtYXRjaGVzWyAzIF0gfHwgXCJweFwiICkgOlxuXHRcdHZhbHVlO1xufVxuXG5mdW5jdGlvbiBhdWdtZW50V2lkdGhPckhlaWdodCggZWxlbSwgbmFtZSwgZXh0cmEsIGlzQm9yZGVyQm94LCBzdHlsZXMgKSB7XG5cdHZhciBpLFxuXHRcdHZhbCA9IDA7XG5cblx0Ly8gSWYgd2UgYWxyZWFkeSBoYXZlIHRoZSByaWdodCBtZWFzdXJlbWVudCwgYXZvaWQgYXVnbWVudGF0aW9uXG5cdGlmICggZXh0cmEgPT09ICggaXNCb3JkZXJCb3ggPyBcImJvcmRlclwiIDogXCJjb250ZW50XCIgKSApIHtcblx0XHRpID0gNDtcblxuXHQvLyBPdGhlcndpc2UgaW5pdGlhbGl6ZSBmb3IgaG9yaXpvbnRhbCBvciB2ZXJ0aWNhbCBwcm9wZXJ0aWVzXG5cdH0gZWxzZSB7XG5cdFx0aSA9IG5hbWUgPT09IFwid2lkdGhcIiA/IDEgOiAwO1xuXHR9XG5cblx0Zm9yICggOyBpIDwgNDsgaSArPSAyICkge1xuXG5cdFx0Ly8gQm90aCBib3ggbW9kZWxzIGV4Y2x1ZGUgbWFyZ2luLCBzbyBhZGQgaXQgaWYgd2Ugd2FudCBpdFxuXHRcdGlmICggZXh0cmEgPT09IFwibWFyZ2luXCIgKSB7XG5cdFx0XHR2YWwgKz0galF1ZXJ5LmNzcyggZWxlbSwgZXh0cmEgKyBjc3NFeHBhbmRbIGkgXSwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBpc0JvcmRlckJveCApIHtcblxuXHRcdFx0Ly8gYm9yZGVyLWJveCBpbmNsdWRlcyBwYWRkaW5nLCBzbyByZW1vdmUgaXQgaWYgd2Ugd2FudCBjb250ZW50XG5cdFx0XHRpZiAoIGV4dHJhID09PSBcImNvbnRlbnRcIiApIHtcblx0XHRcdFx0dmFsIC09IGpRdWVyeS5jc3MoIGVsZW0sIFwicGFkZGluZ1wiICsgY3NzRXhwYW5kWyBpIF0sIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBBdCB0aGlzIHBvaW50LCBleHRyYSBpc24ndCBib3JkZXIgbm9yIG1hcmdpbiwgc28gcmVtb3ZlIGJvcmRlclxuXHRcdFx0aWYgKCBleHRyYSAhPT0gXCJtYXJnaW5cIiApIHtcblx0XHRcdFx0dmFsIC09IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm9yZGVyXCIgKyBjc3NFeHBhbmRbIGkgXSArIFwiV2lkdGhcIiwgdHJ1ZSwgc3R5bGVzICk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgY29udGVudCwgc28gYWRkIHBhZGRpbmdcblx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBhZGRpbmdcIiArIGNzc0V4cGFuZFsgaSBdLCB0cnVlLCBzdHlsZXMgKTtcblxuXHRcdFx0Ly8gQXQgdGhpcyBwb2ludCwgZXh0cmEgaXNuJ3QgY29udGVudCBub3IgcGFkZGluZywgc28gYWRkIGJvcmRlclxuXHRcdFx0aWYgKCBleHRyYSAhPT0gXCJwYWRkaW5nXCIgKSB7XG5cdFx0XHRcdHZhbCArPSBqUXVlcnkuY3NzKCBlbGVtLCBcImJvcmRlclwiICsgY3NzRXhwYW5kWyBpIF0gKyBcIldpZHRoXCIsIHRydWUsIHN0eWxlcyApO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB2YWw7XG59XG5cbmZ1bmN0aW9uIGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICkge1xuXG5cdC8vIFN0YXJ0IHdpdGggY29tcHV0ZWQgc3R5bGVcblx0dmFyIHZhbHVlSXNCb3JkZXJCb3gsXG5cdFx0c3R5bGVzID0gZ2V0U3R5bGVzKCBlbGVtICksXG5cdFx0dmFsID0gY3VyQ1NTKCBlbGVtLCBuYW1lLCBzdHlsZXMgKSxcblx0XHRpc0JvcmRlckJveCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiYm94U2l6aW5nXCIsIGZhbHNlLCBzdHlsZXMgKSA9PT0gXCJib3JkZXItYm94XCI7XG5cblx0Ly8gQ29tcHV0ZWQgdW5pdCBpcyBub3QgcGl4ZWxzLiBTdG9wIGhlcmUgYW5kIHJldHVybi5cblx0aWYgKCBybnVtbm9ucHgudGVzdCggdmFsICkgKSB7XG5cdFx0cmV0dXJuIHZhbDtcblx0fVxuXG5cdC8vIENoZWNrIGZvciBzdHlsZSBpbiBjYXNlIGEgYnJvd3NlciB3aGljaCByZXR1cm5zIHVucmVsaWFibGUgdmFsdWVzXG5cdC8vIGZvciBnZXRDb21wdXRlZFN0eWxlIHNpbGVudGx5IGZhbGxzIGJhY2sgdG8gdGhlIHJlbGlhYmxlIGVsZW0uc3R5bGVcblx0dmFsdWVJc0JvcmRlckJveCA9IGlzQm9yZGVyQm94ICYmXG5cdFx0KCBzdXBwb3J0LmJveFNpemluZ1JlbGlhYmxlKCkgfHwgdmFsID09PSBlbGVtLnN0eWxlWyBuYW1lIF0gKTtcblxuXHQvLyBGYWxsIGJhY2sgdG8gb2Zmc2V0V2lkdGgvSGVpZ2h0IHdoZW4gdmFsdWUgaXMgXCJhdXRvXCJcblx0Ly8gVGhpcyBoYXBwZW5zIGZvciBpbmxpbmUgZWxlbWVudHMgd2l0aCBubyBleHBsaWNpdCBzZXR0aW5nIChnaC0zNTcxKVxuXHRpZiAoIHZhbCA9PT0gXCJhdXRvXCIgKSB7XG5cdFx0dmFsID0gZWxlbVsgXCJvZmZzZXRcIiArIG5hbWVbIDAgXS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zbGljZSggMSApIF07XG5cdH1cblxuXHQvLyBOb3JtYWxpemUgXCJcIiwgYXV0bywgYW5kIHByZXBhcmUgZm9yIGV4dHJhXG5cdHZhbCA9IHBhcnNlRmxvYXQoIHZhbCApIHx8IDA7XG5cblx0Ly8gVXNlIHRoZSBhY3RpdmUgYm94LXNpemluZyBtb2RlbCB0byBhZGQvc3VidHJhY3QgaXJyZWxldmFudCBzdHlsZXNcblx0cmV0dXJuICggdmFsICtcblx0XHRhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdGVsZW0sXG5cdFx0XHRuYW1lLFxuXHRcdFx0ZXh0cmEgfHwgKCBpc0JvcmRlckJveCA/IFwiYm9yZGVyXCIgOiBcImNvbnRlbnRcIiApLFxuXHRcdFx0dmFsdWVJc0JvcmRlckJveCxcblx0XHRcdHN0eWxlc1xuXHRcdClcblx0KSArIFwicHhcIjtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIEFkZCBpbiBzdHlsZSBwcm9wZXJ0eSBob29rcyBmb3Igb3ZlcnJpZGluZyB0aGUgZGVmYXVsdFxuXHQvLyBiZWhhdmlvciBvZiBnZXR0aW5nIGFuZCBzZXR0aW5nIGEgc3R5bGUgcHJvcGVydHlcblx0Y3NzSG9va3M6IHtcblx0XHRvcGFjaXR5OiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdFx0aWYgKCBjb21wdXRlZCApIHtcblxuXHRcdFx0XHRcdC8vIFdlIHNob3VsZCBhbHdheXMgZ2V0IGEgbnVtYmVyIGJhY2sgZnJvbSBvcGFjaXR5XG5cdFx0XHRcdFx0dmFyIHJldCA9IGN1ckNTUyggZWxlbSwgXCJvcGFjaXR5XCIgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmV0ID09PSBcIlwiID8gXCIxXCIgOiByZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0Ly8gRG9uJ3QgYXV0b21hdGljYWxseSBhZGQgXCJweFwiIHRvIHRoZXNlIHBvc3NpYmx5LXVuaXRsZXNzIHByb3BlcnRpZXNcblx0Y3NzTnVtYmVyOiB7XG5cdFx0XCJhbmltYXRpb25JdGVyYXRpb25Db3VudFwiOiB0cnVlLFxuXHRcdFwiY29sdW1uQ291bnRcIjogdHJ1ZSxcblx0XHRcImZpbGxPcGFjaXR5XCI6IHRydWUsXG5cdFx0XCJmbGV4R3Jvd1wiOiB0cnVlLFxuXHRcdFwiZmxleFNocmlua1wiOiB0cnVlLFxuXHRcdFwiZm9udFdlaWdodFwiOiB0cnVlLFxuXHRcdFwibGluZUhlaWdodFwiOiB0cnVlLFxuXHRcdFwib3BhY2l0eVwiOiB0cnVlLFxuXHRcdFwib3JkZXJcIjogdHJ1ZSxcblx0XHRcIm9ycGhhbnNcIjogdHJ1ZSxcblx0XHRcIndpZG93c1wiOiB0cnVlLFxuXHRcdFwiekluZGV4XCI6IHRydWUsXG5cdFx0XCJ6b29tXCI6IHRydWVcblx0fSxcblxuXHQvLyBBZGQgaW4gcHJvcGVydGllcyB3aG9zZSBuYW1lcyB5b3Ugd2lzaCB0byBmaXggYmVmb3JlXG5cdC8vIHNldHRpbmcgb3IgZ2V0dGluZyB0aGUgdmFsdWVcblx0Y3NzUHJvcHM6IHtcblx0XHRcImZsb2F0XCI6IFwiY3NzRmxvYXRcIlxuXHR9LFxuXG5cdC8vIEdldCBhbmQgc2V0IHRoZSBzdHlsZSBwcm9wZXJ0eSBvbiBhIERPTSBOb2RlXG5cdHN0eWxlOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUsIGV4dHJhICkge1xuXG5cdFx0Ly8gRG9uJ3Qgc2V0IHN0eWxlcyBvbiB0ZXh0IGFuZCBjb21tZW50IG5vZGVzXG5cdFx0aWYgKCAhZWxlbSB8fCBlbGVtLm5vZGVUeXBlID09PSAzIHx8IGVsZW0ubm9kZVR5cGUgPT09IDggfHwgIWVsZW0uc3R5bGUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gTWFrZSBzdXJlIHRoYXQgd2UncmUgd29ya2luZyB3aXRoIHRoZSByaWdodCBuYW1lXG5cdFx0dmFyIHJldCwgdHlwZSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdGlzQ3VzdG9tUHJvcCA9IHJjdXN0b21Qcm9wLnRlc3QoIG5hbWUgKSxcblx0XHRcdHN0eWxlID0gZWxlbS5zdHlsZTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHdlJ3JlIHdvcmtpbmcgd2l0aCB0aGUgcmlnaHQgbmFtZS4gV2UgZG9uJ3Rcblx0XHQvLyB3YW50IHRvIHF1ZXJ5IHRoZSB2YWx1ZSBpZiBpdCBpcyBhIENTUyBjdXN0b20gcHJvcGVydHlcblx0XHQvLyBzaW5jZSB0aGV5IGFyZSB1c2VyLWRlZmluZWQuXG5cdFx0aWYgKCAhaXNDdXN0b21Qcm9wICkge1xuXHRcdFx0bmFtZSA9IGZpbmFsUHJvcE5hbWUoIG9yaWdOYW1lICk7XG5cdFx0fVxuXG5cdFx0Ly8gR2V0cyBob29rIGZvciB0aGUgcHJlZml4ZWQgdmVyc2lvbiwgdGhlbiB1bnByZWZpeGVkIHZlcnNpb25cblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIENoZWNrIGlmIHdlJ3JlIHNldHRpbmcgYSB2YWx1ZVxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHR5cGUgPSB0eXBlb2YgdmFsdWU7XG5cblx0XHRcdC8vIENvbnZlcnQgXCIrPVwiIG9yIFwiLT1cIiB0byByZWxhdGl2ZSBudW1iZXJzICgjNzM0NSlcblx0XHRcdGlmICggdHlwZSA9PT0gXCJzdHJpbmdcIiAmJiAoIHJldCA9IHJjc3NOdW0uZXhlYyggdmFsdWUgKSApICYmIHJldFsgMSBdICkge1xuXHRcdFx0XHR2YWx1ZSA9IGFkanVzdENTUyggZWxlbSwgbmFtZSwgcmV0ICk7XG5cblx0XHRcdFx0Ly8gRml4ZXMgYnVnICM5MjM3XG5cdFx0XHRcdHR5cGUgPSBcIm51bWJlclwiO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBNYWtlIHN1cmUgdGhhdCBudWxsIGFuZCBOYU4gdmFsdWVzIGFyZW4ndCBzZXQgKCM3MTE2KVxuXHRcdFx0aWYgKCB2YWx1ZSA9PSBudWxsIHx8IHZhbHVlICE9PSB2YWx1ZSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBJZiBhIG51bWJlciB3YXMgcGFzc2VkIGluLCBhZGQgdGhlIHVuaXQgKGV4Y2VwdCBmb3IgY2VydGFpbiBDU1MgcHJvcGVydGllcylcblx0XHRcdGlmICggdHlwZSA9PT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0dmFsdWUgKz0gcmV0ICYmIHJldFsgMyBdIHx8ICggalF1ZXJ5LmNzc051bWJlclsgb3JpZ05hbWUgXSA/IFwiXCIgOiBcInB4XCIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gYmFja2dyb3VuZC0qIHByb3BzIGFmZmVjdCBvcmlnaW5hbCBjbG9uZSdzIHZhbHVlc1xuXHRcdFx0aWYgKCAhc3VwcG9ydC5jbGVhckNsb25lU3R5bGUgJiYgdmFsdWUgPT09IFwiXCIgJiYgbmFtZS5pbmRleE9mKCBcImJhY2tncm91bmRcIiApID09PSAwICkge1xuXHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gXCJpbmhlcml0XCI7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQsIHVzZSB0aGF0IHZhbHVlLCBvdGhlcndpc2UganVzdCBzZXQgdGhlIHNwZWNpZmllZCB2YWx1ZVxuXHRcdFx0aWYgKCAhaG9va3MgfHwgISggXCJzZXRcIiBpbiBob29rcyApIHx8XG5cdFx0XHRcdCggdmFsdWUgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBleHRyYSApICkgIT09IHVuZGVmaW5lZCApIHtcblxuXHRcdFx0XHRpZiAoIGlzQ3VzdG9tUHJvcCApIHtcblx0XHRcdFx0XHRzdHlsZS5zZXRQcm9wZXJ0eSggbmFtZSwgdmFsdWUgKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdHlsZVsgbmFtZSBdID0gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBub24tY29tcHV0ZWQgdmFsdWUgZnJvbSB0aGVyZVxuXHRcdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICYmXG5cdFx0XHRcdCggcmV0ID0gaG9va3MuZ2V0KCBlbGVtLCBmYWxzZSwgZXh0cmEgKSApICE9PSB1bmRlZmluZWQgKSB7XG5cblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gT3RoZXJ3aXNlIGp1c3QgZ2V0IHRoZSB2YWx1ZSBmcm9tIHRoZSBzdHlsZSBvYmplY3Rcblx0XHRcdHJldHVybiBzdHlsZVsgbmFtZSBdO1xuXHRcdH1cblx0fSxcblxuXHRjc3M6IGZ1bmN0aW9uKCBlbGVtLCBuYW1lLCBleHRyYSwgc3R5bGVzICkge1xuXHRcdHZhciB2YWwsIG51bSwgaG9va3MsXG5cdFx0XHRvcmlnTmFtZSA9IGpRdWVyeS5jYW1lbENhc2UoIG5hbWUgKSxcblx0XHRcdGlzQ3VzdG9tUHJvcCA9IHJjdXN0b21Qcm9wLnRlc3QoIG5hbWUgKTtcblxuXHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHdlJ3JlIHdvcmtpbmcgd2l0aCB0aGUgcmlnaHQgbmFtZS4gV2UgZG9uJ3Rcblx0XHQvLyB3YW50IHRvIG1vZGlmeSB0aGUgdmFsdWUgaWYgaXQgaXMgYSBDU1MgY3VzdG9tIHByb3BlcnR5XG5cdFx0Ly8gc2luY2UgdGhleSBhcmUgdXNlci1kZWZpbmVkLlxuXHRcdGlmICggIWlzQ3VzdG9tUHJvcCApIHtcblx0XHRcdG5hbWUgPSBmaW5hbFByb3BOYW1lKCBvcmlnTmFtZSApO1xuXHRcdH1cblxuXHRcdC8vIFRyeSBwcmVmaXhlZCBuYW1lIGZvbGxvd2VkIGJ5IHRoZSB1bnByZWZpeGVkIG5hbWVcblx0XHRob29rcyA9IGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdIHx8IGpRdWVyeS5jc3NIb29rc1sgb3JpZ05hbWUgXTtcblxuXHRcdC8vIElmIGEgaG9vayB3YXMgcHJvdmlkZWQgZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBmcm9tIHRoZXJlXG5cdFx0aWYgKCBob29rcyAmJiBcImdldFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsID0gaG9va3MuZ2V0KCBlbGVtLCB0cnVlLCBleHRyYSApO1xuXHRcdH1cblxuXHRcdC8vIE90aGVyd2lzZSwgaWYgYSB3YXkgdG8gZ2V0IHRoZSBjb21wdXRlZCB2YWx1ZSBleGlzdHMsIHVzZSB0aGF0XG5cdFx0aWYgKCB2YWwgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHZhbCA9IGN1ckNTUyggZWxlbSwgbmFtZSwgc3R5bGVzICk7XG5cdFx0fVxuXG5cdFx0Ly8gQ29udmVydCBcIm5vcm1hbFwiIHRvIGNvbXB1dGVkIHZhbHVlXG5cdFx0aWYgKCB2YWwgPT09IFwibm9ybWFsXCIgJiYgbmFtZSBpbiBjc3NOb3JtYWxUcmFuc2Zvcm0gKSB7XG5cdFx0XHR2YWwgPSBjc3NOb3JtYWxUcmFuc2Zvcm1bIG5hbWUgXTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIG51bWVyaWMgaWYgZm9yY2VkIG9yIGEgcXVhbGlmaWVyIHdhcyBwcm92aWRlZCBhbmQgdmFsIGxvb2tzIG51bWVyaWNcblx0XHRpZiAoIGV4dHJhID09PSBcIlwiIHx8IGV4dHJhICkge1xuXHRcdFx0bnVtID0gcGFyc2VGbG9hdCggdmFsICk7XG5cdFx0XHRyZXR1cm4gZXh0cmEgPT09IHRydWUgfHwgaXNGaW5pdGUoIG51bSApID8gbnVtIHx8IDAgOiB2YWw7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHZhbDtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcImhlaWdodFwiLCBcIndpZHRoXCIgXSwgZnVuY3Rpb24oIGksIG5hbWUgKSB7XG5cdGpRdWVyeS5jc3NIb29rc1sgbmFtZSBdID0ge1xuXHRcdGdldDogZnVuY3Rpb24oIGVsZW0sIGNvbXB1dGVkLCBleHRyYSApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cblx0XHRcdFx0Ly8gQ2VydGFpbiBlbGVtZW50cyBjYW4gaGF2ZSBkaW1lbnNpb24gaW5mbyBpZiB3ZSBpbnZpc2libHkgc2hvdyB0aGVtXG5cdFx0XHRcdC8vIGJ1dCBpdCBtdXN0IGhhdmUgYSBjdXJyZW50IGRpc3BsYXkgc3R5bGUgdGhhdCB3b3VsZCBiZW5lZml0XG5cdFx0XHRcdHJldHVybiByZGlzcGxheXN3YXAudGVzdCggalF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKSApICYmXG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBTYWZhcmkgOCtcblx0XHRcdFx0XHQvLyBUYWJsZSBjb2x1bW5zIGluIFNhZmFyaSBoYXZlIG5vbi16ZXJvIG9mZnNldFdpZHRoICYgemVyb1xuXHRcdFx0XHRcdC8vIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoIHVubGVzcyBkaXNwbGF5IGlzIGNoYW5nZWQuXG5cdFx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG5cdFx0XHRcdFx0Ly8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYSBkaXNjb25uZWN0ZWQgbm9kZVxuXHRcdFx0XHRcdC8vIGluIElFIHRocm93cyBhbiBlcnJvci5cblx0XHRcdFx0XHQoICFlbGVtLmdldENsaWVudFJlY3RzKCkubGVuZ3RoIHx8ICFlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoICkgP1xuXHRcdFx0XHRcdFx0c3dhcCggZWxlbSwgY3NzU2hvdywgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBnZXRXaWR0aE9ySGVpZ2h0KCBlbGVtLCBuYW1lLCBleHRyYSApO1xuXHRcdFx0XHRcdFx0fSApIDpcblx0XHRcdFx0XHRcdGdldFdpZHRoT3JIZWlnaHQoIGVsZW0sIG5hbWUsIGV4dHJhICk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlLCBleHRyYSApIHtcblx0XHRcdHZhciBtYXRjaGVzLFxuXHRcdFx0XHRzdHlsZXMgPSBleHRyYSAmJiBnZXRTdHlsZXMoIGVsZW0gKSxcblx0XHRcdFx0c3VidHJhY3QgPSBleHRyYSAmJiBhdWdtZW50V2lkdGhPckhlaWdodChcblx0XHRcdFx0XHRlbGVtLFxuXHRcdFx0XHRcdG5hbWUsXG5cdFx0XHRcdFx0ZXh0cmEsXG5cdFx0XHRcdFx0alF1ZXJ5LmNzcyggZWxlbSwgXCJib3hTaXppbmdcIiwgZmFsc2UsIHN0eWxlcyApID09PSBcImJvcmRlci1ib3hcIixcblx0XHRcdFx0XHRzdHlsZXNcblx0XHRcdFx0KTtcblxuXHRcdFx0Ly8gQ29udmVydCB0byBwaXhlbHMgaWYgdmFsdWUgYWRqdXN0bWVudCBpcyBuZWVkZWRcblx0XHRcdGlmICggc3VidHJhY3QgJiYgKCBtYXRjaGVzID0gcmNzc051bS5leGVjKCB2YWx1ZSApICkgJiZcblx0XHRcdFx0KCBtYXRjaGVzWyAzIF0gfHwgXCJweFwiICkgIT09IFwicHhcIiApIHtcblxuXHRcdFx0XHRlbGVtLnN0eWxlWyBuYW1lIF0gPSB2YWx1ZTtcblx0XHRcdFx0dmFsdWUgPSBqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICk7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBzZXRQb3NpdGl2ZU51bWJlciggZWxlbSwgdmFsdWUsIHN1YnRyYWN0ICk7XG5cdFx0fVxuXHR9O1xufSApO1xuXG5qUXVlcnkuY3NzSG9va3MubWFyZ2luTGVmdCA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5yZWxpYWJsZU1hcmdpbkxlZnQsXG5cdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRpZiAoIGNvbXB1dGVkICkge1xuXHRcdFx0cmV0dXJuICggcGFyc2VGbG9hdCggY3VyQ1NTKCBlbGVtLCBcIm1hcmdpbkxlZnRcIiApICkgfHxcblx0XHRcdFx0ZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0IC1cblx0XHRcdFx0XHRzd2FwKCBlbGVtLCB7IG1hcmdpbkxlZnQ6IDAgfSwgZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuXHRcdFx0XHRcdH0gKVxuXHRcdFx0XHQpICsgXCJweFwiO1xuXHRcdH1cblx0fVxuKTtcblxuLy8gVGhlc2UgaG9va3MgYXJlIHVzZWQgYnkgYW5pbWF0ZSB0byBleHBhbmQgcHJvcGVydGllc1xualF1ZXJ5LmVhY2goIHtcblx0bWFyZ2luOiBcIlwiLFxuXHRwYWRkaW5nOiBcIlwiLFxuXHRib3JkZXI6IFwiV2lkdGhcIlxufSwgZnVuY3Rpb24oIHByZWZpeCwgc3VmZml4ICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByZWZpeCArIHN1ZmZpeCBdID0ge1xuXHRcdGV4cGFuZDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdFx0dmFyIGkgPSAwLFxuXHRcdFx0XHRleHBhbmRlZCA9IHt9LFxuXG5cdFx0XHRcdC8vIEFzc3VtZXMgYSBzaW5nbGUgbnVtYmVyIGlmIG5vdCBhIHN0cmluZ1xuXHRcdFx0XHRwYXJ0cyA9IHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiA/IHZhbHVlLnNwbGl0KCBcIiBcIiApIDogWyB2YWx1ZSBdO1xuXG5cdFx0XHRmb3IgKCA7IGkgPCA0OyBpKysgKSB7XG5cdFx0XHRcdGV4cGFuZGVkWyBwcmVmaXggKyBjc3NFeHBhbmRbIGkgXSArIHN1ZmZpeCBdID1cblx0XHRcdFx0XHRwYXJ0c1sgaSBdIHx8IHBhcnRzWyBpIC0gMiBdIHx8IHBhcnRzWyAwIF07XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBleHBhbmRlZDtcblx0XHR9XG5cdH07XG5cblx0aWYgKCAhcm1hcmdpbi50ZXN0KCBwcmVmaXggKSApIHtcblx0XHRqUXVlcnkuY3NzSG9va3NbIHByZWZpeCArIHN1ZmZpeCBdLnNldCA9IHNldFBvc2l0aXZlTnVtYmVyO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0Y3NzOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0dmFyIHN0eWxlcywgbGVuLFxuXHRcdFx0XHRtYXAgPSB7fSxcblx0XHRcdFx0aSA9IDA7XG5cblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggbmFtZSApICkge1xuXHRcdFx0XHRzdHlsZXMgPSBnZXRTdHlsZXMoIGVsZW0gKTtcblx0XHRcdFx0bGVuID0gbmFtZS5sZW5ndGg7XG5cblx0XHRcdFx0Zm9yICggOyBpIDwgbGVuOyBpKysgKSB7XG5cdFx0XHRcdFx0bWFwWyBuYW1lWyBpIF0gXSA9IGpRdWVyeS5jc3MoIGVsZW0sIG5hbWVbIGkgXSwgZmFsc2UsIHN0eWxlcyApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIG1hcDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIHZhbHVlICE9PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRqUXVlcnkuc3R5bGUoIGVsZW0sIG5hbWUsIHZhbHVlICkgOlxuXHRcdFx0XHRqUXVlcnkuY3NzKCBlbGVtLCBuYW1lICk7XG5cdFx0fSwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH1cbn0gKTtcblxuXG5mdW5jdGlvbiBUd2VlbiggZWxlbSwgb3B0aW9ucywgcHJvcCwgZW5kLCBlYXNpbmcgKSB7XG5cdHJldHVybiBuZXcgVHdlZW4ucHJvdG90eXBlLmluaXQoIGVsZW0sIG9wdGlvbnMsIHByb3AsIGVuZCwgZWFzaW5nICk7XG59XG5qUXVlcnkuVHdlZW4gPSBUd2VlbjtcblxuVHdlZW4ucHJvdG90eXBlID0ge1xuXHRjb25zdHJ1Y3RvcjogVHdlZW4sXG5cdGluaXQ6IGZ1bmN0aW9uKCBlbGVtLCBvcHRpb25zLCBwcm9wLCBlbmQsIGVhc2luZywgdW5pdCApIHtcblx0XHR0aGlzLmVsZW0gPSBlbGVtO1xuXHRcdHRoaXMucHJvcCA9IHByb3A7XG5cdFx0dGhpcy5lYXNpbmcgPSBlYXNpbmcgfHwgalF1ZXJ5LmVhc2luZy5fZGVmYXVsdDtcblx0XHR0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXHRcdHRoaXMuc3RhcnQgPSB0aGlzLm5vdyA9IHRoaXMuY3VyKCk7XG5cdFx0dGhpcy5lbmQgPSBlbmQ7XG5cdFx0dGhpcy51bml0ID0gdW5pdCB8fCAoIGpRdWVyeS5jc3NOdW1iZXJbIHByb3AgXSA/IFwiXCIgOiBcInB4XCIgKTtcblx0fSxcblx0Y3VyOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgaG9va3MgPSBUd2Vlbi5wcm9wSG9va3NbIHRoaXMucHJvcCBdO1xuXG5cdFx0cmV0dXJuIGhvb2tzICYmIGhvb2tzLmdldCA/XG5cdFx0XHRob29rcy5nZXQoIHRoaXMgKSA6XG5cdFx0XHRUd2Vlbi5wcm9wSG9va3MuX2RlZmF1bHQuZ2V0KCB0aGlzICk7XG5cdH0sXG5cdHJ1bjogZnVuY3Rpb24oIHBlcmNlbnQgKSB7XG5cdFx0dmFyIGVhc2VkLFxuXHRcdFx0aG9va3MgPSBUd2Vlbi5wcm9wSG9va3NbIHRoaXMucHJvcCBdO1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuZHVyYXRpb24gKSB7XG5cdFx0XHR0aGlzLnBvcyA9IGVhc2VkID0galF1ZXJ5LmVhc2luZ1sgdGhpcy5lYXNpbmcgXShcblx0XHRcdFx0cGVyY2VudCwgdGhpcy5vcHRpb25zLmR1cmF0aW9uICogcGVyY2VudCwgMCwgMSwgdGhpcy5vcHRpb25zLmR1cmF0aW9uXG5cdFx0XHQpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLnBvcyA9IGVhc2VkID0gcGVyY2VudDtcblx0XHR9XG5cdFx0dGhpcy5ub3cgPSAoIHRoaXMuZW5kIC0gdGhpcy5zdGFydCApICogZWFzZWQgKyB0aGlzLnN0YXJ0O1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuc3RlcCApIHtcblx0XHRcdHRoaXMub3B0aW9ucy5zdGVwLmNhbGwoIHRoaXMuZWxlbSwgdGhpcy5ub3csIHRoaXMgKTtcblx0XHR9XG5cblx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnNldCApIHtcblx0XHRcdGhvb2tzLnNldCggdGhpcyApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRUd2Vlbi5wcm9wSG9va3MuX2RlZmF1bHQuc2V0KCB0aGlzICk7XG5cdFx0fVxuXHRcdHJldHVybiB0aGlzO1xuXHR9XG59O1xuXG5Ud2Vlbi5wcm90b3R5cGUuaW5pdC5wcm90b3R5cGUgPSBUd2Vlbi5wcm90b3R5cGU7XG5cblR3ZWVuLnByb3BIb29rcyA9IHtcblx0X2RlZmF1bHQ6IHtcblx0XHRnZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblx0XHRcdHZhciByZXN1bHQ7XG5cblx0XHRcdC8vIFVzZSBhIHByb3BlcnR5IG9uIHRoZSBlbGVtZW50IGRpcmVjdGx5IHdoZW4gaXQgaXMgbm90IGEgRE9NIGVsZW1lbnQsXG5cdFx0XHQvLyBvciB3aGVuIHRoZXJlIGlzIG5vIG1hdGNoaW5nIHN0eWxlIHByb3BlcnR5IHRoYXQgZXhpc3RzLlxuXHRcdFx0aWYgKCB0d2Vlbi5lbGVtLm5vZGVUeXBlICE9PSAxIHx8XG5cdFx0XHRcdHR3ZWVuLmVsZW1bIHR3ZWVuLnByb3AgXSAhPSBudWxsICYmIHR3ZWVuLmVsZW0uc3R5bGVbIHR3ZWVuLnByb3AgXSA9PSBudWxsICkge1xuXHRcdFx0XHRyZXR1cm4gdHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBQYXNzaW5nIGFuIGVtcHR5IHN0cmluZyBhcyBhIDNyZCBwYXJhbWV0ZXIgdG8gLmNzcyB3aWxsIGF1dG9tYXRpY2FsbHlcblx0XHRcdC8vIGF0dGVtcHQgYSBwYXJzZUZsb2F0IGFuZCBmYWxsYmFjayB0byBhIHN0cmluZyBpZiB0aGUgcGFyc2UgZmFpbHMuXG5cdFx0XHQvLyBTaW1wbGUgdmFsdWVzIHN1Y2ggYXMgXCIxMHB4XCIgYXJlIHBhcnNlZCB0byBGbG9hdDtcblx0XHRcdC8vIGNvbXBsZXggdmFsdWVzIHN1Y2ggYXMgXCJyb3RhdGUoMXJhZClcIiBhcmUgcmV0dXJuZWQgYXMtaXMuXG5cdFx0XHRyZXN1bHQgPSBqUXVlcnkuY3NzKCB0d2Vlbi5lbGVtLCB0d2Vlbi5wcm9wLCBcIlwiICk7XG5cblx0XHRcdC8vIEVtcHR5IHN0cmluZ3MsIG51bGwsIHVuZGVmaW5lZCBhbmQgXCJhdXRvXCIgYXJlIGNvbnZlcnRlZCB0byAwLlxuXHRcdFx0cmV0dXJuICFyZXN1bHQgfHwgcmVzdWx0ID09PSBcImF1dG9cIiA/IDAgOiByZXN1bHQ7XG5cdFx0fSxcblx0XHRzZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblxuXHRcdFx0Ly8gVXNlIHN0ZXAgaG9vayBmb3IgYmFjayBjb21wYXQuXG5cdFx0XHQvLyBVc2UgY3NzSG9vayBpZiBpdHMgdGhlcmUuXG5cdFx0XHQvLyBVc2UgLnN0eWxlIGlmIGF2YWlsYWJsZSBhbmQgdXNlIHBsYWluIHByb3BlcnRpZXMgd2hlcmUgYXZhaWxhYmxlLlxuXHRcdFx0aWYgKCBqUXVlcnkuZnguc3RlcFsgdHdlZW4ucHJvcCBdICkge1xuXHRcdFx0XHRqUXVlcnkuZnguc3RlcFsgdHdlZW4ucHJvcCBdKCB0d2VlbiApO1xuXHRcdFx0fSBlbHNlIGlmICggdHdlZW4uZWxlbS5ub2RlVHlwZSA9PT0gMSAmJlxuXHRcdFx0XHQoIHR3ZWVuLmVsZW0uc3R5bGVbIGpRdWVyeS5jc3NQcm9wc1sgdHdlZW4ucHJvcCBdIF0gIT0gbnVsbCB8fFxuXHRcdFx0XHRcdGpRdWVyeS5jc3NIb29rc1sgdHdlZW4ucHJvcCBdICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5zdHlsZSggdHdlZW4uZWxlbSwgdHdlZW4ucHJvcCwgdHdlZW4ubm93ICsgdHdlZW4udW5pdCApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufTtcblxuLy8gU3VwcG9ydDogSUUgPD05IG9ubHlcbi8vIFBhbmljIGJhc2VkIGFwcHJvYWNoIHRvIHNldHRpbmcgdGhpbmdzIG9uIGRpc2Nvbm5lY3RlZCBub2Rlc1xuVHdlZW4ucHJvcEhvb2tzLnNjcm9sbFRvcCA9IFR3ZWVuLnByb3BIb29rcy5zY3JvbGxMZWZ0ID0ge1xuXHRzZXQ6IGZ1bmN0aW9uKCB0d2VlbiApIHtcblx0XHRpZiAoIHR3ZWVuLmVsZW0ubm9kZVR5cGUgJiYgdHdlZW4uZWxlbS5wYXJlbnROb2RlICkge1xuXHRcdFx0dHdlZW4uZWxlbVsgdHdlZW4ucHJvcCBdID0gdHdlZW4ubm93O1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LmVhc2luZyA9IHtcblx0bGluZWFyOiBmdW5jdGlvbiggcCApIHtcblx0XHRyZXR1cm4gcDtcblx0fSxcblx0c3dpbmc6IGZ1bmN0aW9uKCBwICkge1xuXHRcdHJldHVybiAwLjUgLSBNYXRoLmNvcyggcCAqIE1hdGguUEkgKSAvIDI7XG5cdH0sXG5cdF9kZWZhdWx0OiBcInN3aW5nXCJcbn07XG5cbmpRdWVyeS5meCA9IFR3ZWVuLnByb3RvdHlwZS5pbml0O1xuXG4vLyBCYWNrIGNvbXBhdCA8MS44IGV4dGVuc2lvbiBwb2ludFxualF1ZXJ5LmZ4LnN0ZXAgPSB7fTtcblxuXG5cblxudmFyXG5cdGZ4Tm93LCBpblByb2dyZXNzLFxuXHRyZnh0eXBlcyA9IC9eKD86dG9nZ2xlfHNob3d8aGlkZSkkLyxcblx0cnJ1biA9IC9xdWV1ZUhvb2tzJC87XG5cbmZ1bmN0aW9uIHNjaGVkdWxlKCkge1xuXHRpZiAoIGluUHJvZ3Jlc3MgKSB7XG5cdFx0aWYgKCBkb2N1bWVudC5oaWRkZW4gPT09IGZhbHNlICYmIHdpbmRvdy5yZXF1ZXN0QW5pbWF0aW9uRnJhbWUgKSB7XG5cdFx0XHR3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lKCBzY2hlZHVsZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR3aW5kb3cuc2V0VGltZW91dCggc2NoZWR1bGUsIGpRdWVyeS5meC5pbnRlcnZhbCApO1xuXHRcdH1cblxuXHRcdGpRdWVyeS5meC50aWNrKCk7XG5cdH1cbn1cblxuLy8gQW5pbWF0aW9ucyBjcmVhdGVkIHN5bmNocm9ub3VzbHkgd2lsbCBydW4gc3luY2hyb25vdXNseVxuZnVuY3Rpb24gY3JlYXRlRnhOb3coKSB7XG5cdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRmeE5vdyA9IHVuZGVmaW5lZDtcblx0fSApO1xuXHRyZXR1cm4gKCBmeE5vdyA9IGpRdWVyeS5ub3coKSApO1xufVxuXG4vLyBHZW5lcmF0ZSBwYXJhbWV0ZXJzIHRvIGNyZWF0ZSBhIHN0YW5kYXJkIGFuaW1hdGlvblxuZnVuY3Rpb24gZ2VuRngoIHR5cGUsIGluY2x1ZGVXaWR0aCApIHtcblx0dmFyIHdoaWNoLFxuXHRcdGkgPSAwLFxuXHRcdGF0dHJzID0geyBoZWlnaHQ6IHR5cGUgfTtcblxuXHQvLyBJZiB3ZSBpbmNsdWRlIHdpZHRoLCBzdGVwIHZhbHVlIGlzIDEgdG8gZG8gYWxsIGNzc0V4cGFuZCB2YWx1ZXMsXG5cdC8vIG90aGVyd2lzZSBzdGVwIHZhbHVlIGlzIDIgdG8gc2tpcCBvdmVyIExlZnQgYW5kIFJpZ2h0XG5cdGluY2x1ZGVXaWR0aCA9IGluY2x1ZGVXaWR0aCA/IDEgOiAwO1xuXHRmb3IgKCA7IGkgPCA0OyBpICs9IDIgLSBpbmNsdWRlV2lkdGggKSB7XG5cdFx0d2hpY2ggPSBjc3NFeHBhbmRbIGkgXTtcblx0XHRhdHRyc1sgXCJtYXJnaW5cIiArIHdoaWNoIF0gPSBhdHRyc1sgXCJwYWRkaW5nXCIgKyB3aGljaCBdID0gdHlwZTtcblx0fVxuXG5cdGlmICggaW5jbHVkZVdpZHRoICkge1xuXHRcdGF0dHJzLm9wYWNpdHkgPSBhdHRycy53aWR0aCA9IHR5cGU7XG5cdH1cblxuXHRyZXR1cm4gYXR0cnM7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZVR3ZWVuKCB2YWx1ZSwgcHJvcCwgYW5pbWF0aW9uICkge1xuXHR2YXIgdHdlZW4sXG5cdFx0Y29sbGVjdGlvbiA9ICggQW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gfHwgW10gKS5jb25jYXQoIEFuaW1hdGlvbi50d2VlbmVyc1sgXCIqXCIgXSApLFxuXHRcdGluZGV4ID0gMCxcblx0XHRsZW5ndGggPSBjb2xsZWN0aW9uLmxlbmd0aDtcblx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRpZiAoICggdHdlZW4gPSBjb2xsZWN0aW9uWyBpbmRleCBdLmNhbGwoIGFuaW1hdGlvbiwgcHJvcCwgdmFsdWUgKSApICkge1xuXG5cdFx0XHQvLyBXZSdyZSBkb25lIHdpdGggdGhpcyBwcm9wZXJ0eVxuXHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBkZWZhdWx0UHJlZmlsdGVyKCBlbGVtLCBwcm9wcywgb3B0cyApIHtcblx0dmFyIHByb3AsIHZhbHVlLCB0b2dnbGUsIGhvb2tzLCBvbGRmaXJlLCBwcm9wVHdlZW4sIHJlc3RvcmVEaXNwbGF5LCBkaXNwbGF5LFxuXHRcdGlzQm94ID0gXCJ3aWR0aFwiIGluIHByb3BzIHx8IFwiaGVpZ2h0XCIgaW4gcHJvcHMsXG5cdFx0YW5pbSA9IHRoaXMsXG5cdFx0b3JpZyA9IHt9LFxuXHRcdHN0eWxlID0gZWxlbS5zdHlsZSxcblx0XHRoaWRkZW4gPSBlbGVtLm5vZGVUeXBlICYmIGlzSGlkZGVuV2l0aGluVHJlZSggZWxlbSApLFxuXHRcdGRhdGFTaG93ID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImZ4c2hvd1wiICk7XG5cblx0Ly8gUXVldWUtc2tpcHBpbmcgYW5pbWF0aW9ucyBoaWphY2sgdGhlIGZ4IGhvb2tzXG5cdGlmICggIW9wdHMucXVldWUgKSB7XG5cdFx0aG9va3MgPSBqUXVlcnkuX3F1ZXVlSG9va3MoIGVsZW0sIFwiZnhcIiApO1xuXHRcdGlmICggaG9va3MudW5xdWV1ZWQgPT0gbnVsbCApIHtcblx0XHRcdGhvb2tzLnVucXVldWVkID0gMDtcblx0XHRcdG9sZGZpcmUgPSBob29rcy5lbXB0eS5maXJlO1xuXHRcdFx0aG9va3MuZW1wdHkuZmlyZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoICFob29rcy51bnF1ZXVlZCApIHtcblx0XHRcdFx0XHRvbGRmaXJlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fVxuXHRcdGhvb2tzLnVucXVldWVkKys7XG5cblx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIEVuc3VyZSB0aGUgY29tcGxldGUgaGFuZGxlciBpcyBjYWxsZWQgYmVmb3JlIHRoaXMgY29tcGxldGVzXG5cdFx0XHRhbmltLmFsd2F5cyggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGhvb2tzLnVucXVldWVkLS07XG5cdFx0XHRcdGlmICggIWpRdWVyeS5xdWV1ZSggZWxlbSwgXCJmeFwiICkubGVuZ3RoICkge1xuXHRcdFx0XHRcdGhvb2tzLmVtcHR5LmZpcmUoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH0gKTtcblx0fVxuXG5cdC8vIERldGVjdCBzaG93L2hpZGUgYW5pbWF0aW9uc1xuXHRmb3IgKCBwcm9wIGluIHByb3BzICkge1xuXHRcdHZhbHVlID0gcHJvcHNbIHByb3AgXTtcblx0XHRpZiAoIHJmeHR5cGVzLnRlc3QoIHZhbHVlICkgKSB7XG5cdFx0XHRkZWxldGUgcHJvcHNbIHByb3AgXTtcblx0XHRcdHRvZ2dsZSA9IHRvZ2dsZSB8fCB2YWx1ZSA9PT0gXCJ0b2dnbGVcIjtcblx0XHRcdGlmICggdmFsdWUgPT09ICggaGlkZGVuID8gXCJoaWRlXCIgOiBcInNob3dcIiApICkge1xuXG5cdFx0XHRcdC8vIFByZXRlbmQgdG8gYmUgaGlkZGVuIGlmIHRoaXMgaXMgYSBcInNob3dcIiBhbmRcblx0XHRcdFx0Ly8gdGhlcmUgaXMgc3RpbGwgZGF0YSBmcm9tIGEgc3RvcHBlZCBzaG93L2hpZGVcblx0XHRcdFx0aWYgKCB2YWx1ZSA9PT0gXCJzaG93XCIgJiYgZGF0YVNob3cgJiYgZGF0YVNob3dbIHByb3AgXSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdGhpZGRlbiA9IHRydWU7XG5cblx0XHRcdFx0Ly8gSWdub3JlIGFsbCBvdGhlciBuby1vcCBzaG93L2hpZGUgZGF0YVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRvcmlnWyBwcm9wIF0gPSBkYXRhU2hvdyAmJiBkYXRhU2hvd1sgcHJvcCBdIHx8IGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIEJhaWwgb3V0IGlmIHRoaXMgaXMgYSBuby1vcCBsaWtlIC5oaWRlKCkuaGlkZSgpXG5cdHByb3BUd2VlbiA9ICFqUXVlcnkuaXNFbXB0eU9iamVjdCggcHJvcHMgKTtcblx0aWYgKCAhcHJvcFR3ZWVuICYmIGpRdWVyeS5pc0VtcHR5T2JqZWN0KCBvcmlnICkgKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Ly8gUmVzdHJpY3QgXCJvdmVyZmxvd1wiIGFuZCBcImRpc3BsYXlcIiBzdHlsZXMgZHVyaW5nIGJveCBhbmltYXRpb25zXG5cdGlmICggaXNCb3ggJiYgZWxlbS5ub2RlVHlwZSA9PT0gMSApIHtcblxuXHRcdC8vIFN1cHBvcnQ6IElFIDw9OSAtIDExLCBFZGdlIDEyIC0gMTNcblx0XHQvLyBSZWNvcmQgYWxsIDMgb3ZlcmZsb3cgYXR0cmlidXRlcyBiZWNhdXNlIElFIGRvZXMgbm90IGluZmVyIHRoZSBzaG9ydGhhbmRcblx0XHQvLyBmcm9tIGlkZW50aWNhbGx5LXZhbHVlZCBvdmVyZmxvd1ggYW5kIG92ZXJmbG93WVxuXHRcdG9wdHMub3ZlcmZsb3cgPSBbIHN0eWxlLm92ZXJmbG93LCBzdHlsZS5vdmVyZmxvd1gsIHN0eWxlLm92ZXJmbG93WSBdO1xuXG5cdFx0Ly8gSWRlbnRpZnkgYSBkaXNwbGF5IHR5cGUsIHByZWZlcnJpbmcgb2xkIHNob3cvaGlkZSBkYXRhIG92ZXIgdGhlIENTUyBjYXNjYWRlXG5cdFx0cmVzdG9yZURpc3BsYXkgPSBkYXRhU2hvdyAmJiBkYXRhU2hvdy5kaXNwbGF5O1xuXHRcdGlmICggcmVzdG9yZURpc3BsYXkgPT0gbnVsbCApIHtcblx0XHRcdHJlc3RvcmVEaXNwbGF5ID0gZGF0YVByaXYuZ2V0KCBlbGVtLCBcImRpc3BsYXlcIiApO1xuXHRcdH1cblx0XHRkaXNwbGF5ID0galF1ZXJ5LmNzcyggZWxlbSwgXCJkaXNwbGF5XCIgKTtcblx0XHRpZiAoIGRpc3BsYXkgPT09IFwibm9uZVwiICkge1xuXHRcdFx0aWYgKCByZXN0b3JlRGlzcGxheSApIHtcblx0XHRcdFx0ZGlzcGxheSA9IHJlc3RvcmVEaXNwbGF5O1xuXHRcdFx0fSBlbHNlIHtcblxuXHRcdFx0XHQvLyBHZXQgbm9uZW1wdHkgdmFsdWUocykgYnkgdGVtcG9yYXJpbHkgZm9yY2luZyB2aXNpYmlsaXR5XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSwgdHJ1ZSApO1xuXHRcdFx0XHRyZXN0b3JlRGlzcGxheSA9IGVsZW0uc3R5bGUuZGlzcGxheSB8fCByZXN0b3JlRGlzcGxheTtcblx0XHRcdFx0ZGlzcGxheSA9IGpRdWVyeS5jc3MoIGVsZW0sIFwiZGlzcGxheVwiICk7XG5cdFx0XHRcdHNob3dIaWRlKCBbIGVsZW0gXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIEFuaW1hdGUgaW5saW5lIGVsZW1lbnRzIGFzIGlubGluZS1ibG9ja1xuXHRcdGlmICggZGlzcGxheSA9PT0gXCJpbmxpbmVcIiB8fCBkaXNwbGF5ID09PSBcImlubGluZS1ibG9ja1wiICYmIHJlc3RvcmVEaXNwbGF5ICE9IG51bGwgKSB7XG5cdFx0XHRpZiAoIGpRdWVyeS5jc3MoIGVsZW0sIFwiZmxvYXRcIiApID09PSBcIm5vbmVcIiApIHtcblxuXHRcdFx0XHQvLyBSZXN0b3JlIHRoZSBvcmlnaW5hbCBkaXNwbGF5IHZhbHVlIGF0IHRoZSBlbmQgb2YgcHVyZSBzaG93L2hpZGUgYW5pbWF0aW9uc1xuXHRcdFx0XHRpZiAoICFwcm9wVHdlZW4gKSB7XG5cdFx0XHRcdFx0YW5pbS5kb25lKCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdHN0eWxlLmRpc3BsYXkgPSByZXN0b3JlRGlzcGxheTtcblx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0aWYgKCByZXN0b3JlRGlzcGxheSA9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0ZGlzcGxheSA9IHN0eWxlLmRpc3BsYXk7XG5cdFx0XHRcdFx0XHRyZXN0b3JlRGlzcGxheSA9IGRpc3BsYXkgPT09IFwibm9uZVwiID8gXCJcIiA6IGRpc3BsYXk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdHN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdGlmICggb3B0cy5vdmVyZmxvdyApIHtcblx0XHRzdHlsZS5vdmVyZmxvdyA9IFwiaGlkZGVuXCI7XG5cdFx0YW5pbS5hbHdheXMoIGZ1bmN0aW9uKCkge1xuXHRcdFx0c3R5bGUub3ZlcmZsb3cgPSBvcHRzLm92ZXJmbG93WyAwIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1ggPSBvcHRzLm92ZXJmbG93WyAxIF07XG5cdFx0XHRzdHlsZS5vdmVyZmxvd1kgPSBvcHRzLm92ZXJmbG93WyAyIF07XG5cdFx0fSApO1xuXHR9XG5cblx0Ly8gSW1wbGVtZW50IHNob3cvaGlkZSBhbmltYXRpb25zXG5cdHByb3BUd2VlbiA9IGZhbHNlO1xuXHRmb3IgKCBwcm9wIGluIG9yaWcgKSB7XG5cblx0XHQvLyBHZW5lcmFsIHNob3cvaGlkZSBzZXR1cCBmb3IgdGhpcyBlbGVtZW50IGFuaW1hdGlvblxuXHRcdGlmICggIXByb3BUd2VlbiApIHtcblx0XHRcdGlmICggZGF0YVNob3cgKSB7XG5cdFx0XHRcdGlmICggXCJoaWRkZW5cIiBpbiBkYXRhU2hvdyApIHtcblx0XHRcdFx0XHRoaWRkZW4gPSBkYXRhU2hvdy5oaWRkZW47XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGRhdGFTaG93ID0gZGF0YVByaXYuYWNjZXNzKCBlbGVtLCBcImZ4c2hvd1wiLCB7IGRpc3BsYXk6IHJlc3RvcmVEaXNwbGF5IH0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU3RvcmUgaGlkZGVuL3Zpc2libGUgZm9yIHRvZ2dsZSBzbyBgLnN0b3AoKS50b2dnbGUoKWAgXCJyZXZlcnNlc1wiXG5cdFx0XHRpZiAoIHRvZ2dsZSApIHtcblx0XHRcdFx0ZGF0YVNob3cuaGlkZGVuID0gIWhpZGRlbjtcblx0XHRcdH1cblxuXHRcdFx0Ly8gU2hvdyBlbGVtZW50cyBiZWZvcmUgYW5pbWF0aW5nIHRoZW1cblx0XHRcdGlmICggaGlkZGVuICkge1xuXHRcdFx0XHRzaG93SGlkZSggWyBlbGVtIF0sIHRydWUgKTtcblx0XHRcdH1cblxuXHRcdFx0LyogZXNsaW50LWRpc2FibGUgbm8tbG9vcC1mdW5jICovXG5cblx0XHRcdGFuaW0uZG9uZSggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8qIGVzbGludC1lbmFibGUgbm8tbG9vcC1mdW5jICovXG5cblx0XHRcdFx0Ly8gVGhlIGZpbmFsIHN0ZXAgb2YgYSBcImhpZGVcIiBhbmltYXRpb24gaXMgYWN0dWFsbHkgaGlkaW5nIHRoZSBlbGVtZW50XG5cdFx0XHRcdGlmICggIWhpZGRlbiApIHtcblx0XHRcdFx0XHRzaG93SGlkZSggWyBlbGVtIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRkYXRhUHJpdi5yZW1vdmUoIGVsZW0sIFwiZnhzaG93XCIgKTtcblx0XHRcdFx0Zm9yICggcHJvcCBpbiBvcmlnICkge1xuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgcHJvcCwgb3JpZ1sgcHJvcCBdICk7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHQvLyBQZXItcHJvcGVydHkgc2V0dXBcblx0XHRwcm9wVHdlZW4gPSBjcmVhdGVUd2VlbiggaGlkZGVuID8gZGF0YVNob3dbIHByb3AgXSA6IDAsIHByb3AsIGFuaW0gKTtcblx0XHRpZiAoICEoIHByb3AgaW4gZGF0YVNob3cgKSApIHtcblx0XHRcdGRhdGFTaG93WyBwcm9wIF0gPSBwcm9wVHdlZW4uc3RhcnQ7XG5cdFx0XHRpZiAoIGhpZGRlbiApIHtcblx0XHRcdFx0cHJvcFR3ZWVuLmVuZCA9IHByb3BUd2Vlbi5zdGFydDtcblx0XHRcdFx0cHJvcFR3ZWVuLnN0YXJ0ID0gMDtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn1cblxuZnVuY3Rpb24gcHJvcEZpbHRlciggcHJvcHMsIHNwZWNpYWxFYXNpbmcgKSB7XG5cdHZhciBpbmRleCwgbmFtZSwgZWFzaW5nLCB2YWx1ZSwgaG9va3M7XG5cblx0Ly8gY2FtZWxDYXNlLCBzcGVjaWFsRWFzaW5nIGFuZCBleHBhbmQgY3NzSG9vayBwYXNzXG5cdGZvciAoIGluZGV4IGluIHByb3BzICkge1xuXHRcdG5hbWUgPSBqUXVlcnkuY2FtZWxDYXNlKCBpbmRleCApO1xuXHRcdGVhc2luZyA9IHNwZWNpYWxFYXNpbmdbIG5hbWUgXTtcblx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdO1xuXHRcdGlmICggQXJyYXkuaXNBcnJheSggdmFsdWUgKSApIHtcblx0XHRcdGVhc2luZyA9IHZhbHVlWyAxIF07XG5cdFx0XHR2YWx1ZSA9IHByb3BzWyBpbmRleCBdID0gdmFsdWVbIDAgXTtcblx0XHR9XG5cblx0XHRpZiAoIGluZGV4ICE9PSBuYW1lICkge1xuXHRcdFx0cHJvcHNbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0ZGVsZXRlIHByb3BzWyBpbmRleCBdO1xuXHRcdH1cblxuXHRcdGhvb2tzID0galF1ZXJ5LmNzc0hvb2tzWyBuYW1lIF07XG5cdFx0aWYgKCBob29rcyAmJiBcImV4cGFuZFwiIGluIGhvb2tzICkge1xuXHRcdFx0dmFsdWUgPSBob29rcy5leHBhbmQoIHZhbHVlICk7XG5cdFx0XHRkZWxldGUgcHJvcHNbIG5hbWUgXTtcblxuXHRcdFx0Ly8gTm90IHF1aXRlICQuZXh0ZW5kLCB0aGlzIHdvbid0IG92ZXJ3cml0ZSBleGlzdGluZyBrZXlzLlxuXHRcdFx0Ly8gUmV1c2luZyAnaW5kZXgnIGJlY2F1c2Ugd2UgaGF2ZSB0aGUgY29ycmVjdCBcIm5hbWVcIlxuXHRcdFx0Zm9yICggaW5kZXggaW4gdmFsdWUgKSB7XG5cdFx0XHRcdGlmICggISggaW5kZXggaW4gcHJvcHMgKSApIHtcblx0XHRcdFx0XHRwcm9wc1sgaW5kZXggXSA9IHZhbHVlWyBpbmRleCBdO1xuXHRcdFx0XHRcdHNwZWNpYWxFYXNpbmdbIGluZGV4IF0gPSBlYXNpbmc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0c3BlY2lhbEVhc2luZ1sgbmFtZSBdID0gZWFzaW5nO1xuXHRcdH1cblx0fVxufVxuXG5mdW5jdGlvbiBBbmltYXRpb24oIGVsZW0sIHByb3BlcnRpZXMsIG9wdGlvbnMgKSB7XG5cdHZhciByZXN1bHQsXG5cdFx0c3RvcHBlZCxcblx0XHRpbmRleCA9IDAsXG5cdFx0bGVuZ3RoID0gQW5pbWF0aW9uLnByZWZpbHRlcnMubGVuZ3RoLFxuXHRcdGRlZmVycmVkID0galF1ZXJ5LkRlZmVycmVkKCkuYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gRG9uJ3QgbWF0Y2ggZWxlbSBpbiB0aGUgOmFuaW1hdGVkIHNlbGVjdG9yXG5cdFx0XHRkZWxldGUgdGljay5lbGVtO1xuXHRcdH0gKSxcblx0XHR0aWNrID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRpZiAoIHN0b3BwZWQgKSB7XG5cdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdH1cblx0XHRcdHZhciBjdXJyZW50VGltZSA9IGZ4Tm93IHx8IGNyZWF0ZUZ4Tm93KCksXG5cdFx0XHRcdHJlbWFpbmluZyA9IE1hdGgubWF4KCAwLCBhbmltYXRpb24uc3RhcnRUaW1lICsgYW5pbWF0aW9uLmR1cmF0aW9uIC0gY3VycmVudFRpbWUgKSxcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBBbmRyb2lkIDIuMyBvbmx5XG5cdFx0XHRcdC8vIEFyY2hhaWMgY3Jhc2ggYnVnIHdvbid0IGFsbG93IHVzIHRvIHVzZSBgMSAtICggMC41IHx8IDAgKWAgKCMxMjQ5Nylcblx0XHRcdFx0dGVtcCA9IHJlbWFpbmluZyAvIGFuaW1hdGlvbi5kdXJhdGlvbiB8fCAwLFxuXHRcdFx0XHRwZXJjZW50ID0gMSAtIHRlbXAsXG5cdFx0XHRcdGluZGV4ID0gMCxcblx0XHRcdFx0bGVuZ3RoID0gYW5pbWF0aW9uLnR3ZWVucy5sZW5ndGg7XG5cblx0XHRcdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCBwZXJjZW50ICk7XG5cdFx0XHR9XG5cblx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCBwZXJjZW50LCByZW1haW5pbmcgXSApO1xuXG5cdFx0XHQvLyBJZiB0aGVyZSdzIG1vcmUgdG8gZG8sIHlpZWxkXG5cdFx0XHRpZiAoIHBlcmNlbnQgPCAxICYmIGxlbmd0aCApIHtcblx0XHRcdFx0cmV0dXJuIHJlbWFpbmluZztcblx0XHRcdH1cblxuXHRcdFx0Ly8gSWYgdGhpcyB3YXMgYW4gZW1wdHkgYW5pbWF0aW9uLCBzeW50aGVzaXplIGEgZmluYWwgcHJvZ3Jlc3Mgbm90aWZpY2F0aW9uXG5cdFx0XHRpZiAoICFsZW5ndGggKSB7XG5cdFx0XHRcdGRlZmVycmVkLm5vdGlmeVdpdGgoIGVsZW0sIFsgYW5pbWF0aW9uLCAxLCAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUmVzb2x2ZSB0aGUgYW5pbWF0aW9uIGFuZCByZXBvcnQgaXRzIGNvbmNsdXNpb25cblx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiBdICk7XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fSxcblx0XHRhbmltYXRpb24gPSBkZWZlcnJlZC5wcm9taXNlKCB7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0cHJvcHM6IGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wZXJ0aWVzICksXG5cdFx0XHRvcHRzOiBqUXVlcnkuZXh0ZW5kKCB0cnVlLCB7XG5cdFx0XHRcdHNwZWNpYWxFYXNpbmc6IHt9LFxuXHRcdFx0XHRlYXNpbmc6IGpRdWVyeS5lYXNpbmcuX2RlZmF1bHRcblx0XHRcdH0sIG9wdGlvbnMgKSxcblx0XHRcdG9yaWdpbmFsUHJvcGVydGllczogcHJvcGVydGllcyxcblx0XHRcdG9yaWdpbmFsT3B0aW9uczogb3B0aW9ucyxcblx0XHRcdHN0YXJ0VGltZTogZnhOb3cgfHwgY3JlYXRlRnhOb3coKSxcblx0XHRcdGR1cmF0aW9uOiBvcHRpb25zLmR1cmF0aW9uLFxuXHRcdFx0dHdlZW5zOiBbXSxcblx0XHRcdGNyZWF0ZVR3ZWVuOiBmdW5jdGlvbiggcHJvcCwgZW5kICkge1xuXHRcdFx0XHR2YXIgdHdlZW4gPSBqUXVlcnkuVHdlZW4oIGVsZW0sIGFuaW1hdGlvbi5vcHRzLCBwcm9wLCBlbmQsXG5cdFx0XHRcdFx0XHRhbmltYXRpb24ub3B0cy5zcGVjaWFsRWFzaW5nWyBwcm9wIF0gfHwgYW5pbWF0aW9uLm9wdHMuZWFzaW5nICk7XG5cdFx0XHRcdGFuaW1hdGlvbi50d2VlbnMucHVzaCggdHdlZW4gKTtcblx0XHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdFx0fSxcblx0XHRcdHN0b3A6IGZ1bmN0aW9uKCBnb3RvRW5kICkge1xuXHRcdFx0XHR2YXIgaW5kZXggPSAwLFxuXG5cdFx0XHRcdFx0Ly8gSWYgd2UgYXJlIGdvaW5nIHRvIHRoZSBlbmQsIHdlIHdhbnQgdG8gcnVuIGFsbCB0aGUgdHdlZW5zXG5cdFx0XHRcdFx0Ly8gb3RoZXJ3aXNlIHdlIHNraXAgdGhpcyBwYXJ0XG5cdFx0XHRcdFx0bGVuZ3RoID0gZ290b0VuZCA/IGFuaW1hdGlvbi50d2VlbnMubGVuZ3RoIDogMDtcblx0XHRcdFx0aWYgKCBzdG9wcGVkICkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHN0b3BwZWQgPSB0cnVlO1xuXHRcdFx0XHRmb3IgKCA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrICkge1xuXHRcdFx0XHRcdGFuaW1hdGlvbi50d2VlbnNbIGluZGV4IF0ucnVuKCAxICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBSZXNvbHZlIHdoZW4gd2UgcGxheWVkIHRoZSBsYXN0IGZyYW1lOyBvdGhlcndpc2UsIHJlamVjdFxuXHRcdFx0XHRpZiAoIGdvdG9FbmQgKSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQubm90aWZ5V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIDEsIDAgXSApO1xuXHRcdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBlbGVtLCBbIGFuaW1hdGlvbiwgZ290b0VuZCBdICk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggZWxlbSwgWyBhbmltYXRpb24sIGdvdG9FbmQgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fVxuXHRcdH0gKSxcblx0XHRwcm9wcyA9IGFuaW1hdGlvbi5wcm9wcztcblxuXHRwcm9wRmlsdGVyKCBwcm9wcywgYW5pbWF0aW9uLm9wdHMuc3BlY2lhbEVhc2luZyApO1xuXG5cdGZvciAoIDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0cmVzdWx0ID0gQW5pbWF0aW9uLnByZWZpbHRlcnNbIGluZGV4IF0uY2FsbCggYW5pbWF0aW9uLCBlbGVtLCBwcm9wcywgYW5pbWF0aW9uLm9wdHMgKTtcblx0XHRpZiAoIHJlc3VsdCApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIHJlc3VsdC5zdG9wICkgKSB7XG5cdFx0XHRcdGpRdWVyeS5fcXVldWVIb29rcyggYW5pbWF0aW9uLmVsZW0sIGFuaW1hdGlvbi5vcHRzLnF1ZXVlICkuc3RvcCA9XG5cdFx0XHRcdFx0alF1ZXJ5LnByb3h5KCByZXN1bHQuc3RvcCwgcmVzdWx0ICk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gcmVzdWx0O1xuXHRcdH1cblx0fVxuXG5cdGpRdWVyeS5tYXAoIHByb3BzLCBjcmVhdGVUd2VlbiwgYW5pbWF0aW9uICk7XG5cblx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggYW5pbWF0aW9uLm9wdHMuc3RhcnQgKSApIHtcblx0XHRhbmltYXRpb24ub3B0cy5zdGFydC5jYWxsKCBlbGVtLCBhbmltYXRpb24gKTtcblx0fVxuXG5cdC8vIEF0dGFjaCBjYWxsYmFja3MgZnJvbSBvcHRpb25zXG5cdGFuaW1hdGlvblxuXHRcdC5wcm9ncmVzcyggYW5pbWF0aW9uLm9wdHMucHJvZ3Jlc3MgKVxuXHRcdC5kb25lKCBhbmltYXRpb24ub3B0cy5kb25lLCBhbmltYXRpb24ub3B0cy5jb21wbGV0ZSApXG5cdFx0LmZhaWwoIGFuaW1hdGlvbi5vcHRzLmZhaWwgKVxuXHRcdC5hbHdheXMoIGFuaW1hdGlvbi5vcHRzLmFsd2F5cyApO1xuXG5cdGpRdWVyeS5meC50aW1lcihcblx0XHRqUXVlcnkuZXh0ZW5kKCB0aWNrLCB7XG5cdFx0XHRlbGVtOiBlbGVtLFxuXHRcdFx0YW5pbTogYW5pbWF0aW9uLFxuXHRcdFx0cXVldWU6IGFuaW1hdGlvbi5vcHRzLnF1ZXVlXG5cdFx0fSApXG5cdCk7XG5cblx0cmV0dXJuIGFuaW1hdGlvbjtcbn1cblxualF1ZXJ5LkFuaW1hdGlvbiA9IGpRdWVyeS5leHRlbmQoIEFuaW1hdGlvbiwge1xuXG5cdHR3ZWVuZXJzOiB7XG5cdFx0XCIqXCI6IFsgZnVuY3Rpb24oIHByb3AsIHZhbHVlICkge1xuXHRcdFx0dmFyIHR3ZWVuID0gdGhpcy5jcmVhdGVUd2VlbiggcHJvcCwgdmFsdWUgKTtcblx0XHRcdGFkanVzdENTUyggdHdlZW4uZWxlbSwgcHJvcCwgcmNzc051bS5leGVjKCB2YWx1ZSApLCB0d2VlbiApO1xuXHRcdFx0cmV0dXJuIHR3ZWVuO1xuXHRcdH0gXVxuXHR9LFxuXG5cdHR3ZWVuZXI6IGZ1bmN0aW9uKCBwcm9wcywgY2FsbGJhY2sgKSB7XG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggcHJvcHMgKSApIHtcblx0XHRcdGNhbGxiYWNrID0gcHJvcHM7XG5cdFx0XHRwcm9wcyA9IFsgXCIqXCIgXTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0cHJvcHMgPSBwcm9wcy5tYXRjaCggcm5vdGh0bWx3aGl0ZSApO1xuXHRcdH1cblxuXHRcdHZhciBwcm9wLFxuXHRcdFx0aW5kZXggPSAwLFxuXHRcdFx0bGVuZ3RoID0gcHJvcHMubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKyApIHtcblx0XHRcdHByb3AgPSBwcm9wc1sgaW5kZXggXTtcblx0XHRcdEFuaW1hdGlvbi50d2VlbmVyc1sgcHJvcCBdID0gQW5pbWF0aW9uLnR3ZWVuZXJzWyBwcm9wIF0gfHwgW107XG5cdFx0XHRBbmltYXRpb24udHdlZW5lcnNbIHByb3AgXS51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH1cblx0fSxcblxuXHRwcmVmaWx0ZXJzOiBbIGRlZmF1bHRQcmVmaWx0ZXIgXSxcblxuXHRwcmVmaWx0ZXI6IGZ1bmN0aW9uKCBjYWxsYmFjaywgcHJlcGVuZCApIHtcblx0XHRpZiAoIHByZXBlbmQgKSB7XG5cdFx0XHRBbmltYXRpb24ucHJlZmlsdGVycy51bnNoaWZ0KCBjYWxsYmFjayApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRBbmltYXRpb24ucHJlZmlsdGVycy5wdXNoKCBjYWxsYmFjayApO1xuXHRcdH1cblx0fVxufSApO1xuXG5qUXVlcnkuc3BlZWQgPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgZm4gKSB7XG5cdHZhciBvcHQgPSBzcGVlZCAmJiB0eXBlb2Ygc3BlZWQgPT09IFwib2JqZWN0XCIgPyBqUXVlcnkuZXh0ZW5kKCB7fSwgc3BlZWQgKSA6IHtcblx0XHRjb21wbGV0ZTogZm4gfHwgIWZuICYmIGVhc2luZyB8fFxuXHRcdFx0alF1ZXJ5LmlzRnVuY3Rpb24oIHNwZWVkICkgJiYgc3BlZWQsXG5cdFx0ZHVyYXRpb246IHNwZWVkLFxuXHRcdGVhc2luZzogZm4gJiYgZWFzaW5nIHx8IGVhc2luZyAmJiAhalF1ZXJ5LmlzRnVuY3Rpb24oIGVhc2luZyApICYmIGVhc2luZ1xuXHR9O1xuXG5cdC8vIEdvIHRvIHRoZSBlbmQgc3RhdGUgaWYgZnggYXJlIG9mZlxuXHRpZiAoIGpRdWVyeS5meC5vZmYgKSB7XG5cdFx0b3B0LmR1cmF0aW9uID0gMDtcblxuXHR9IGVsc2Uge1xuXHRcdGlmICggdHlwZW9mIG9wdC5kdXJhdGlvbiAhPT0gXCJudW1iZXJcIiApIHtcblx0XHRcdGlmICggb3B0LmR1cmF0aW9uIGluIGpRdWVyeS5meC5zcGVlZHMgKSB7XG5cdFx0XHRcdG9wdC5kdXJhdGlvbiA9IGpRdWVyeS5meC5zcGVlZHNbIG9wdC5kdXJhdGlvbiBdO1xuXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvcHQuZHVyYXRpb24gPSBqUXVlcnkuZnguc3BlZWRzLl9kZWZhdWx0O1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdC8vIE5vcm1hbGl6ZSBvcHQucXVldWUgLSB0cnVlL3VuZGVmaW5lZC9udWxsIC0+IFwiZnhcIlxuXHRpZiAoIG9wdC5xdWV1ZSA9PSBudWxsIHx8IG9wdC5xdWV1ZSA9PT0gdHJ1ZSApIHtcblx0XHRvcHQucXVldWUgPSBcImZ4XCI7XG5cdH1cblxuXHQvLyBRdWV1ZWluZ1xuXHRvcHQub2xkID0gb3B0LmNvbXBsZXRlO1xuXG5cdG9wdC5jb21wbGV0ZSA9IGZ1bmN0aW9uKCkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIG9wdC5vbGQgKSApIHtcblx0XHRcdG9wdC5vbGQuY2FsbCggdGhpcyApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0LnF1ZXVlICkge1xuXHRcdFx0alF1ZXJ5LmRlcXVldWUoIHRoaXMsIG9wdC5xdWV1ZSApO1xuXHRcdH1cblx0fTtcblxuXHRyZXR1cm4gb3B0O1xufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRmYWRlVG86IGZ1bmN0aW9uKCBzcGVlZCwgdG8sIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cblx0XHQvLyBTaG93IGFueSBoaWRkZW4gZWxlbWVudHMgYWZ0ZXIgc2V0dGluZyBvcGFjaXR5IHRvIDBcblx0XHRyZXR1cm4gdGhpcy5maWx0ZXIoIGlzSGlkZGVuV2l0aGluVHJlZSApLmNzcyggXCJvcGFjaXR5XCIsIDAgKS5zaG93KClcblxuXHRcdFx0Ly8gQW5pbWF0ZSB0byB0aGUgdmFsdWUgc3BlY2lmaWVkXG5cdFx0XHQuZW5kKCkuYW5pbWF0ZSggeyBvcGFjaXR5OiB0byB9LCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9LFxuXHRhbmltYXRlOiBmdW5jdGlvbiggcHJvcCwgc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0dmFyIGVtcHR5ID0galF1ZXJ5LmlzRW1wdHlPYmplY3QoIHByb3AgKSxcblx0XHRcdG9wdGFsbCA9IGpRdWVyeS5zcGVlZCggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSxcblx0XHRcdGRvQW5pbWF0aW9uID0gZnVuY3Rpb24oKSB7XG5cblx0XHRcdFx0Ly8gT3BlcmF0ZSBvbiBhIGNvcHkgb2YgcHJvcCBzbyBwZXItcHJvcGVydHkgZWFzaW5nIHdvbid0IGJlIGxvc3Rcblx0XHRcdFx0dmFyIGFuaW0gPSBBbmltYXRpb24oIHRoaXMsIGpRdWVyeS5leHRlbmQoIHt9LCBwcm9wICksIG9wdGFsbCApO1xuXG5cdFx0XHRcdC8vIEVtcHR5IGFuaW1hdGlvbnMsIG9yIGZpbmlzaGluZyByZXNvbHZlcyBpbW1lZGlhdGVseVxuXHRcdFx0XHRpZiAoIGVtcHR5IHx8IGRhdGFQcml2LmdldCggdGhpcywgXCJmaW5pc2hcIiApICkge1xuXHRcdFx0XHRcdGFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0ZG9BbmltYXRpb24uZmluaXNoID0gZG9BbmltYXRpb247XG5cblx0XHRyZXR1cm4gZW1wdHkgfHwgb3B0YWxsLnF1ZXVlID09PSBmYWxzZSA/XG5cdFx0XHR0aGlzLmVhY2goIGRvQW5pbWF0aW9uICkgOlxuXHRcdFx0dGhpcy5xdWV1ZSggb3B0YWxsLnF1ZXVlLCBkb0FuaW1hdGlvbiApO1xuXHR9LFxuXHRzdG9wOiBmdW5jdGlvbiggdHlwZSwgY2xlYXJRdWV1ZSwgZ290b0VuZCApIHtcblx0XHR2YXIgc3RvcFF1ZXVlID0gZnVuY3Rpb24oIGhvb2tzICkge1xuXHRcdFx0dmFyIHN0b3AgPSBob29rcy5zdG9wO1xuXHRcdFx0ZGVsZXRlIGhvb2tzLnN0b3A7XG5cdFx0XHRzdG9wKCBnb3RvRW5kICk7XG5cdFx0fTtcblxuXHRcdGlmICggdHlwZW9mIHR5cGUgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRnb3RvRW5kID0gY2xlYXJRdWV1ZTtcblx0XHRcdGNsZWFyUXVldWUgPSB0eXBlO1xuXHRcdFx0dHlwZSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0aWYgKCBjbGVhclF1ZXVlICYmIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dGhpcy5xdWV1ZSggdHlwZSB8fCBcImZ4XCIsIFtdICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgZGVxdWV1ZSA9IHRydWUsXG5cdFx0XHRcdGluZGV4ID0gdHlwZSAhPSBudWxsICYmIHR5cGUgKyBcInF1ZXVlSG9va3NcIixcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0ZGF0YSA9IGRhdGFQcml2LmdldCggdGhpcyApO1xuXG5cdFx0XHRpZiAoIGluZGV4ICkge1xuXHRcdFx0XHRpZiAoIGRhdGFbIGluZGV4IF0gJiYgZGF0YVsgaW5kZXggXS5zdG9wICkge1xuXHRcdFx0XHRcdHN0b3BRdWV1ZSggZGF0YVsgaW5kZXggXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRmb3IgKCBpbmRleCBpbiBkYXRhICkge1xuXHRcdFx0XHRcdGlmICggZGF0YVsgaW5kZXggXSAmJiBkYXRhWyBpbmRleCBdLnN0b3AgJiYgcnJ1bi50ZXN0KCBpbmRleCApICkge1xuXHRcdFx0XHRcdFx0c3RvcFF1ZXVlKCBkYXRhWyBpbmRleCBdICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGZvciAoIGluZGV4ID0gdGltZXJzLmxlbmd0aDsgaW5kZXgtLTsgKSB7XG5cdFx0XHRcdGlmICggdGltZXJzWyBpbmRleCBdLmVsZW0gPT09IHRoaXMgJiZcblx0XHRcdFx0XHQoIHR5cGUgPT0gbnVsbCB8fCB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSApIHtcblxuXHRcdFx0XHRcdHRpbWVyc1sgaW5kZXggXS5hbmltLnN0b3AoIGdvdG9FbmQgKTtcblx0XHRcdFx0XHRkZXF1ZXVlID0gZmFsc2U7XG5cdFx0XHRcdFx0dGltZXJzLnNwbGljZSggaW5kZXgsIDEgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHQvLyBTdGFydCB0aGUgbmV4dCBpbiB0aGUgcXVldWUgaWYgdGhlIGxhc3Qgc3RlcCB3YXNuJ3QgZm9yY2VkLlxuXHRcdFx0Ly8gVGltZXJzIGN1cnJlbnRseSB3aWxsIGNhbGwgdGhlaXIgY29tcGxldGUgY2FsbGJhY2tzLCB3aGljaFxuXHRcdFx0Ly8gd2lsbCBkZXF1ZXVlIGJ1dCBvbmx5IGlmIHRoZXkgd2VyZSBnb3RvRW5kLlxuXHRcdFx0aWYgKCBkZXF1ZXVlIHx8ICFnb3RvRW5kICkge1xuXHRcdFx0XHRqUXVlcnkuZGVxdWV1ZSggdGhpcywgdHlwZSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSxcblx0ZmluaXNoOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRpZiAoIHR5cGUgIT09IGZhbHNlICkge1xuXHRcdFx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBpbmRleCxcblx0XHRcdFx0ZGF0YSA9IGRhdGFQcml2LmdldCggdGhpcyApLFxuXHRcdFx0XHRxdWV1ZSA9IGRhdGFbIHR5cGUgKyBcInF1ZXVlXCIgXSxcblx0XHRcdFx0aG9va3MgPSBkYXRhWyB0eXBlICsgXCJxdWV1ZUhvb2tzXCIgXSxcblx0XHRcdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycyxcblx0XHRcdFx0bGVuZ3RoID0gcXVldWUgPyBxdWV1ZS5sZW5ndGggOiAwO1xuXG5cdFx0XHQvLyBFbmFibGUgZmluaXNoaW5nIGZsYWcgb24gcHJpdmF0ZSBkYXRhXG5cdFx0XHRkYXRhLmZpbmlzaCA9IHRydWU7XG5cblx0XHRcdC8vIEVtcHR5IHRoZSBxdWV1ZSBmaXJzdFxuXHRcdFx0alF1ZXJ5LnF1ZXVlKCB0aGlzLCB0eXBlLCBbXSApO1xuXG5cdFx0XHRpZiAoIGhvb2tzICYmIGhvb2tzLnN0b3AgKSB7XG5cdFx0XHRcdGhvb2tzLnN0b3AuY2FsbCggdGhpcywgdHJ1ZSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBMb29rIGZvciBhbnkgYWN0aXZlIGFuaW1hdGlvbnMsIGFuZCBmaW5pc2ggdGhlbVxuXHRcdFx0Zm9yICggaW5kZXggPSB0aW1lcnMubGVuZ3RoOyBpbmRleC0tOyApIHtcblx0XHRcdFx0aWYgKCB0aW1lcnNbIGluZGV4IF0uZWxlbSA9PT0gdGhpcyAmJiB0aW1lcnNbIGluZGV4IF0ucXVldWUgPT09IHR5cGUgKSB7XG5cdFx0XHRcdFx0dGltZXJzWyBpbmRleCBdLmFuaW0uc3RvcCggdHJ1ZSApO1xuXHRcdFx0XHRcdHRpbWVycy5zcGxpY2UoIGluZGV4LCAxICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gTG9vayBmb3IgYW55IGFuaW1hdGlvbnMgaW4gdGhlIG9sZCBxdWV1ZSBhbmQgZmluaXNoIHRoZW1cblx0XHRcdGZvciAoIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KysgKSB7XG5cdFx0XHRcdGlmICggcXVldWVbIGluZGV4IF0gJiYgcXVldWVbIGluZGV4IF0uZmluaXNoICkge1xuXHRcdFx0XHRcdHF1ZXVlWyBpbmRleCBdLmZpbmlzaC5jYWxsKCB0aGlzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gVHVybiBvZmYgZmluaXNoaW5nIGZsYWdcblx0XHRcdGRlbGV0ZSBkYXRhLmZpbmlzaDtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmVhY2goIFsgXCJ0b2dnbGVcIiwgXCJzaG93XCIsIFwiaGlkZVwiIF0sIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgY3NzRm4gPSBqUXVlcnkuZm5bIG5hbWUgXTtcblx0alF1ZXJ5LmZuWyBuYW1lIF0gPSBmdW5jdGlvbiggc3BlZWQsIGVhc2luZywgY2FsbGJhY2sgKSB7XG5cdFx0cmV0dXJuIHNwZWVkID09IG51bGwgfHwgdHlwZW9mIHNwZWVkID09PSBcImJvb2xlYW5cIiA/XG5cdFx0XHRjc3NGbi5hcHBseSggdGhpcywgYXJndW1lbnRzICkgOlxuXHRcdFx0dGhpcy5hbmltYXRlKCBnZW5GeCggbmFtZSwgdHJ1ZSApLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSApO1xuXG4vLyBHZW5lcmF0ZSBzaG9ydGN1dHMgZm9yIGN1c3RvbSBhbmltYXRpb25zXG5qUXVlcnkuZWFjaCgge1xuXHRzbGlkZURvd246IGdlbkZ4KCBcInNob3dcIiApLFxuXHRzbGlkZVVwOiBnZW5GeCggXCJoaWRlXCIgKSxcblx0c2xpZGVUb2dnbGU6IGdlbkZ4KCBcInRvZ2dsZVwiICksXG5cdGZhZGVJbjogeyBvcGFjaXR5OiBcInNob3dcIiB9LFxuXHRmYWRlT3V0OiB7IG9wYWNpdHk6IFwiaGlkZVwiIH0sXG5cdGZhZGVUb2dnbGU6IHsgb3BhY2l0eTogXCJ0b2dnbGVcIiB9XG59LCBmdW5jdGlvbiggbmFtZSwgcHJvcHMgKSB7XG5cdGpRdWVyeS5mblsgbmFtZSBdID0gZnVuY3Rpb24oIHNwZWVkLCBlYXNpbmcsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiB0aGlzLmFuaW1hdGUoIHByb3BzLCBzcGVlZCwgZWFzaW5nLCBjYWxsYmFjayApO1xuXHR9O1xufSApO1xuXG5qUXVlcnkudGltZXJzID0gW107XG5qUXVlcnkuZngudGljayA9IGZ1bmN0aW9uKCkge1xuXHR2YXIgdGltZXIsXG5cdFx0aSA9IDAsXG5cdFx0dGltZXJzID0galF1ZXJ5LnRpbWVycztcblxuXHRmeE5vdyA9IGpRdWVyeS5ub3coKTtcblxuXHRmb3IgKCA7IGkgPCB0aW1lcnMubGVuZ3RoOyBpKysgKSB7XG5cdFx0dGltZXIgPSB0aW1lcnNbIGkgXTtcblxuXHRcdC8vIFJ1biB0aGUgdGltZXIgYW5kIHNhZmVseSByZW1vdmUgaXQgd2hlbiBkb25lIChhbGxvd2luZyBmb3IgZXh0ZXJuYWwgcmVtb3ZhbClcblx0XHRpZiAoICF0aW1lcigpICYmIHRpbWVyc1sgaSBdID09PSB0aW1lciApIHtcblx0XHRcdHRpbWVycy5zcGxpY2UoIGktLSwgMSApO1xuXHRcdH1cblx0fVxuXG5cdGlmICggIXRpbWVycy5sZW5ndGggKSB7XG5cdFx0alF1ZXJ5LmZ4LnN0b3AoKTtcblx0fVxuXHRmeE5vdyA9IHVuZGVmaW5lZDtcbn07XG5cbmpRdWVyeS5meC50aW1lciA9IGZ1bmN0aW9uKCB0aW1lciApIHtcblx0alF1ZXJ5LnRpbWVycy5wdXNoKCB0aW1lciApO1xuXHRqUXVlcnkuZnguc3RhcnQoKTtcbn07XG5cbmpRdWVyeS5meC5pbnRlcnZhbCA9IDEzO1xualF1ZXJ5LmZ4LnN0YXJ0ID0gZnVuY3Rpb24oKSB7XG5cdGlmICggaW5Qcm9ncmVzcyApIHtcblx0XHRyZXR1cm47XG5cdH1cblxuXHRpblByb2dyZXNzID0gdHJ1ZTtcblx0c2NoZWR1bGUoKTtcbn07XG5cbmpRdWVyeS5meC5zdG9wID0gZnVuY3Rpb24oKSB7XG5cdGluUHJvZ3Jlc3MgPSBudWxsO1xufTtcblxualF1ZXJ5LmZ4LnNwZWVkcyA9IHtcblx0c2xvdzogNjAwLFxuXHRmYXN0OiAyMDAsXG5cblx0Ly8gRGVmYXVsdCBzcGVlZFxuXHRfZGVmYXVsdDogNDAwXG59O1xuXG5cbi8vIEJhc2VkIG9mZiBvZiB0aGUgcGx1Z2luIGJ5IENsaW50IEhlbGZlcnMsIHdpdGggcGVybWlzc2lvbi5cbi8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDEwMDMyNDAxNDc0Ny9odHRwOi8vYmxpbmRzaWduYWxzLmNvbS9pbmRleC5waHAvMjAwOS8wNy9qcXVlcnktZGVsYXkvXG5qUXVlcnkuZm4uZGVsYXkgPSBmdW5jdGlvbiggdGltZSwgdHlwZSApIHtcblx0dGltZSA9IGpRdWVyeS5meCA/IGpRdWVyeS5meC5zcGVlZHNbIHRpbWUgXSB8fCB0aW1lIDogdGltZTtcblx0dHlwZSA9IHR5cGUgfHwgXCJmeFwiO1xuXG5cdHJldHVybiB0aGlzLnF1ZXVlKCB0eXBlLCBmdW5jdGlvbiggbmV4dCwgaG9va3MgKSB7XG5cdFx0dmFyIHRpbWVvdXQgPSB3aW5kb3cuc2V0VGltZW91dCggbmV4dCwgdGltZSApO1xuXHRcdGhvb2tzLnN0b3AgPSBmdW5jdGlvbigpIHtcblx0XHRcdHdpbmRvdy5jbGVhclRpbWVvdXQoIHRpbWVvdXQgKTtcblx0XHR9O1xuXHR9ICk7XG59O1xuXG5cbiggZnVuY3Rpb24oKSB7XG5cdHZhciBpbnB1dCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwiaW5wdXRcIiApLFxuXHRcdHNlbGVjdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwic2VsZWN0XCIgKSxcblx0XHRvcHQgPSBzZWxlY3QuYXBwZW5kQ2hpbGQoIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoIFwib3B0aW9uXCIgKSApO1xuXG5cdGlucHV0LnR5cGUgPSBcImNoZWNrYm94XCI7XG5cblx0Ly8gU3VwcG9ydDogQW5kcm9pZCA8PTQuMyBvbmx5XG5cdC8vIERlZmF1bHQgdmFsdWUgZm9yIGEgY2hlY2tib3ggc2hvdWxkIGJlIFwib25cIlxuXHRzdXBwb3J0LmNoZWNrT24gPSBpbnB1dC52YWx1ZSAhPT0gXCJcIjtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gTXVzdCBhY2Nlc3Mgc2VsZWN0ZWRJbmRleCB0byBtYWtlIGRlZmF1bHQgb3B0aW9ucyBzZWxlY3Rcblx0c3VwcG9ydC5vcHRTZWxlY3RlZCA9IG9wdC5zZWxlY3RlZDtcblxuXHQvLyBTdXBwb3J0OiBJRSA8PTExIG9ubHlcblx0Ly8gQW4gaW5wdXQgbG9zZXMgaXRzIHZhbHVlIGFmdGVyIGJlY29taW5nIGEgcmFkaW9cblx0aW5wdXQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBcImlucHV0XCIgKTtcblx0aW5wdXQudmFsdWUgPSBcInRcIjtcblx0aW5wdXQudHlwZSA9IFwicmFkaW9cIjtcblx0c3VwcG9ydC5yYWRpb1ZhbHVlID0gaW5wdXQudmFsdWUgPT09IFwidFwiO1xufSApKCk7XG5cblxudmFyIGJvb2xIb29rLFxuXHRhdHRySGFuZGxlID0galF1ZXJ5LmV4cHIuYXR0ckhhbmRsZTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRhdHRyOiBmdW5jdGlvbiggbmFtZSwgdmFsdWUgKSB7XG5cdFx0cmV0dXJuIGFjY2VzcyggdGhpcywgalF1ZXJ5LmF0dHIsIG5hbWUsIHZhbHVlLCBhcmd1bWVudHMubGVuZ3RoID4gMSApO1xuXHR9LFxuXG5cdHJlbW92ZUF0dHI6IGZ1bmN0aW9uKCBuYW1lICkge1xuXHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCkge1xuXHRcdFx0alF1ZXJ5LnJlbW92ZUF0dHIoIHRoaXMsIG5hbWUgKTtcblx0XHR9ICk7XG5cdH1cbn0gKTtcblxualF1ZXJ5LmV4dGVuZCgge1xuXHRhdHRyOiBmdW5jdGlvbiggZWxlbSwgbmFtZSwgdmFsdWUgKSB7XG5cdFx0dmFyIHJldCwgaG9va3MsXG5cdFx0XHRuVHlwZSA9IGVsZW0ubm9kZVR5cGU7XG5cblx0XHQvLyBEb24ndCBnZXQvc2V0IGF0dHJpYnV0ZXMgb24gdGV4dCwgY29tbWVudCBhbmQgYXR0cmlidXRlIG5vZGVzXG5cdFx0aWYgKCBuVHlwZSA9PT0gMyB8fCBuVHlwZSA9PT0gOCB8fCBuVHlwZSA9PT0gMiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBGYWxsYmFjayB0byBwcm9wIHdoZW4gYXR0cmlidXRlcyBhcmUgbm90IHN1cHBvcnRlZFxuXHRcdGlmICggdHlwZW9mIGVsZW0uZ2V0QXR0cmlidXRlID09PSBcInVuZGVmaW5lZFwiICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5wcm9wKCBlbGVtLCBuYW1lLCB2YWx1ZSApO1xuXHRcdH1cblxuXHRcdC8vIEF0dHJpYnV0ZSBob29rcyBhcmUgZGV0ZXJtaW5lZCBieSB0aGUgbG93ZXJjYXNlIHZlcnNpb25cblx0XHQvLyBHcmFiIG5lY2Vzc2FyeSBob29rIGlmIG9uZSBpcyBkZWZpbmVkXG5cdFx0aWYgKCBuVHlwZSAhPT0gMSB8fCAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5hdHRySG9va3NbIG5hbWUudG9Mb3dlckNhc2UoKSBdIHx8XG5cdFx0XHRcdCggalF1ZXJ5LmV4cHIubWF0Y2guYm9vbC50ZXN0KCBuYW1lICkgPyBib29sSG9vayA6IHVuZGVmaW5lZCApO1xuXHRcdH1cblxuXHRcdGlmICggdmFsdWUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGlmICggdmFsdWUgPT09IG51bGwgKSB7XG5cdFx0XHRcdGpRdWVyeS5yZW1vdmVBdHRyKCBlbGVtLCBuYW1lICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCBob29rcyAmJiBcInNldFwiIGluIGhvb2tzICYmXG5cdFx0XHRcdCggcmV0ID0gaG9va3Muc2V0KCBlbGVtLCB2YWx1ZSwgbmFtZSApICkgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0cmV0dXJuIHJldDtcblx0XHRcdH1cblxuXHRcdFx0ZWxlbS5zZXRBdHRyaWJ1dGUoIG5hbWUsIHZhbHVlICsgXCJcIiApO1xuXHRcdFx0cmV0dXJuIHZhbHVlO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApICkgIT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblxuXHRcdHJldCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIG5hbWUgKTtcblxuXHRcdC8vIE5vbi1leGlzdGVudCBhdHRyaWJ1dGVzIHJldHVybiBudWxsLCB3ZSBub3JtYWxpemUgdG8gdW5kZWZpbmVkXG5cdFx0cmV0dXJuIHJldCA9PSBudWxsID8gdW5kZWZpbmVkIDogcmV0O1xuXHR9LFxuXG5cdGF0dHJIb29rczoge1xuXHRcdHR5cGU6IHtcblx0XHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0XHRpZiAoICFzdXBwb3J0LnJhZGlvVmFsdWUgJiYgdmFsdWUgPT09IFwicmFkaW9cIiAmJlxuXHRcdFx0XHRcdG5vZGVOYW1lKCBlbGVtLCBcImlucHV0XCIgKSApIHtcblx0XHRcdFx0XHR2YXIgdmFsID0gZWxlbS52YWx1ZTtcblx0XHRcdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggXCJ0eXBlXCIsIHZhbHVlICk7XG5cdFx0XHRcdFx0aWYgKCB2YWwgKSB7XG5cdFx0XHRcdFx0XHRlbGVtLnZhbHVlID0gdmFsO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0cmVtb3ZlQXR0cjogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdHZhciBuYW1lLFxuXHRcdFx0aSA9IDAsXG5cblx0XHRcdC8vIEF0dHJpYnV0ZSBuYW1lcyBjYW4gY29udGFpbiBub24tSFRNTCB3aGl0ZXNwYWNlIGNoYXJhY3RlcnNcblx0XHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvbXVsdGlwYWdlL3N5bnRheC5odG1sI2F0dHJpYnV0ZXMtMlxuXHRcdFx0YXR0ck5hbWVzID0gdmFsdWUgJiYgdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKTtcblxuXHRcdGlmICggYXR0ck5hbWVzICYmIGVsZW0ubm9kZVR5cGUgPT09IDEgKSB7XG5cdFx0XHR3aGlsZSAoICggbmFtZSA9IGF0dHJOYW1lc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0ZWxlbS5yZW1vdmVBdHRyaWJ1dGUoIG5hbWUgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cbn0gKTtcblxuLy8gSG9va3MgZm9yIGJvb2xlYW4gYXR0cmlidXRlc1xuYm9vbEhvb2sgPSB7XG5cdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlLCBuYW1lICkge1xuXHRcdGlmICggdmFsdWUgPT09IGZhbHNlICkge1xuXG5cdFx0XHQvLyBSZW1vdmUgYm9vbGVhbiBhdHRyaWJ1dGVzIHdoZW4gc2V0IHRvIGZhbHNlXG5cdFx0XHRqUXVlcnkucmVtb3ZlQXR0ciggZWxlbSwgbmFtZSApO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRlbGVtLnNldEF0dHJpYnV0ZSggbmFtZSwgbmFtZSApO1xuXHRcdH1cblx0XHRyZXR1cm4gbmFtZTtcblx0fVxufTtcblxualF1ZXJ5LmVhY2goIGpRdWVyeS5leHByLm1hdGNoLmJvb2wuc291cmNlLm1hdGNoKCAvXFx3Ky9nICksIGZ1bmN0aW9uKCBpLCBuYW1lICkge1xuXHR2YXIgZ2V0dGVyID0gYXR0ckhhbmRsZVsgbmFtZSBdIHx8IGpRdWVyeS5maW5kLmF0dHI7XG5cblx0YXR0ckhhbmRsZVsgbmFtZSBdID0gZnVuY3Rpb24oIGVsZW0sIG5hbWUsIGlzWE1MICkge1xuXHRcdHZhciByZXQsIGhhbmRsZSxcblx0XHRcdGxvd2VyY2FzZU5hbWUgPSBuYW1lLnRvTG93ZXJDYXNlKCk7XG5cblx0XHRpZiAoICFpc1hNTCApIHtcblxuXHRcdFx0Ly8gQXZvaWQgYW4gaW5maW5pdGUgbG9vcCBieSB0ZW1wb3JhcmlseSByZW1vdmluZyB0aGlzIGZ1bmN0aW9uIGZyb20gdGhlIGdldHRlclxuXHRcdFx0aGFuZGxlID0gYXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdO1xuXHRcdFx0YXR0ckhhbmRsZVsgbG93ZXJjYXNlTmFtZSBdID0gcmV0O1xuXHRcdFx0cmV0ID0gZ2V0dGVyKCBlbGVtLCBuYW1lLCBpc1hNTCApICE9IG51bGwgP1xuXHRcdFx0XHRsb3dlcmNhc2VOYW1lIDpcblx0XHRcdFx0bnVsbDtcblx0XHRcdGF0dHJIYW5kbGVbIGxvd2VyY2FzZU5hbWUgXSA9IGhhbmRsZTtcblx0XHR9XG5cdFx0cmV0dXJuIHJldDtcblx0fTtcbn0gKTtcblxuXG5cblxudmFyIHJmb2N1c2FibGUgPSAvXig/OmlucHV0fHNlbGVjdHx0ZXh0YXJlYXxidXR0b24pJC9pLFxuXHRyY2xpY2thYmxlID0gL14oPzphfGFyZWEpJC9pO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHByb3A6IGZ1bmN0aW9uKCBuYW1lLCB2YWx1ZSApIHtcblx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBqUXVlcnkucHJvcCwgbmFtZSwgdmFsdWUsIGFyZ3VtZW50cy5sZW5ndGggPiAxICk7XG5cdH0sXG5cblx0cmVtb3ZlUHJvcDogZnVuY3Rpb24oIG5hbWUgKSB7XG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRkZWxldGUgdGhpc1sgalF1ZXJ5LnByb3BGaXhbIG5hbWUgXSB8fCBuYW1lIF07XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0cHJvcDogZnVuY3Rpb24oIGVsZW0sIG5hbWUsIHZhbHVlICkge1xuXHRcdHZhciByZXQsIGhvb2tzLFxuXHRcdFx0blR5cGUgPSBlbGVtLm5vZGVUeXBlO1xuXG5cdFx0Ly8gRG9uJ3QgZ2V0L3NldCBwcm9wZXJ0aWVzIG9uIHRleHQsIGNvbW1lbnQgYW5kIGF0dHJpYnV0ZSBub2Rlc1xuXHRcdGlmICggblR5cGUgPT09IDMgfHwgblR5cGUgPT09IDggfHwgblR5cGUgPT09IDIgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCBuVHlwZSAhPT0gMSB8fCAhalF1ZXJ5LmlzWE1MRG9jKCBlbGVtICkgKSB7XG5cblx0XHRcdC8vIEZpeCBuYW1lIGFuZCBhdHRhY2ggaG9va3Ncblx0XHRcdG5hbWUgPSBqUXVlcnkucHJvcEZpeFsgbmFtZSBdIHx8IG5hbWU7XG5cdFx0XHRob29rcyA9IGpRdWVyeS5wcm9wSG9va3NbIG5hbWUgXTtcblx0XHR9XG5cblx0XHRpZiAoIHZhbHVlICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRpZiAoIGhvb2tzICYmIFwic2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0KCByZXQgPSBob29rcy5zZXQoIGVsZW0sIHZhbHVlLCBuYW1lICkgKSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gKCBlbGVtWyBuYW1lIF0gPSB2YWx1ZSApO1xuXHRcdH1cblxuXHRcdGlmICggaG9va3MgJiYgXCJnZXRcIiBpbiBob29rcyAmJiAoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgbmFtZSApICkgIT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH1cblxuXHRcdHJldHVybiBlbGVtWyBuYW1lIF07XG5cdH0sXG5cblx0cHJvcEhvb2tzOiB7XG5cdFx0dGFiSW5kZXg6IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD05IC0gMTEgb25seVxuXHRcdFx0XHQvLyBlbGVtLnRhYkluZGV4IGRvZXNuJ3QgYWx3YXlzIHJldHVybiB0aGVcblx0XHRcdFx0Ly8gY29ycmVjdCB2YWx1ZSB3aGVuIGl0IGhhc24ndCBiZWVuIGV4cGxpY2l0bHkgc2V0XG5cdFx0XHRcdC8vIGh0dHBzOi8vd2ViLmFyY2hpdmUub3JnL3dlYi8yMDE0MTExNjIzMzM0Ny9odHRwOi8vZmx1aWRwcm9qZWN0Lm9yZy9ibG9nLzIwMDgvMDEvMDkvZ2V0dGluZy1zZXR0aW5nLWFuZC1yZW1vdmluZy10YWJpbmRleC12YWx1ZXMtd2l0aC1qYXZhc2NyaXB0L1xuXHRcdFx0XHQvLyBVc2UgcHJvcGVyIGF0dHJpYnV0ZSByZXRyaWV2YWwoIzEyMDcyKVxuXHRcdFx0XHR2YXIgdGFiaW5kZXggPSBqUXVlcnkuZmluZC5hdHRyKCBlbGVtLCBcInRhYmluZGV4XCIgKTtcblxuXHRcdFx0XHRpZiAoIHRhYmluZGV4ICkge1xuXHRcdFx0XHRcdHJldHVybiBwYXJzZUludCggdGFiaW5kZXgsIDEwICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoXG5cdFx0XHRcdFx0cmZvY3VzYWJsZS50ZXN0KCBlbGVtLm5vZGVOYW1lICkgfHxcblx0XHRcdFx0XHRyY2xpY2thYmxlLnRlc3QoIGVsZW0ubm9kZU5hbWUgKSAmJlxuXHRcdFx0XHRcdGVsZW0uaHJlZlxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHRyZXR1cm4gMDtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiAtMTtcblx0XHRcdH1cblx0XHR9XG5cdH0sXG5cblx0cHJvcEZpeDoge1xuXHRcdFwiZm9yXCI6IFwiaHRtbEZvclwiLFxuXHRcdFwiY2xhc3NcIjogXCJjbGFzc05hbWVcIlxuXHR9XG59ICk7XG5cbi8vIFN1cHBvcnQ6IElFIDw9MTEgb25seVxuLy8gQWNjZXNzaW5nIHRoZSBzZWxlY3RlZEluZGV4IHByb3BlcnR5XG4vLyBmb3JjZXMgdGhlIGJyb3dzZXIgdG8gcmVzcGVjdCBzZXR0aW5nIHNlbGVjdGVkXG4vLyBvbiB0aGUgb3B0aW9uXG4vLyBUaGUgZ2V0dGVyIGVuc3VyZXMgYSBkZWZhdWx0IG9wdGlvbiBpcyBzZWxlY3RlZFxuLy8gd2hlbiBpbiBhbiBvcHRncm91cFxuLy8gZXNsaW50IHJ1bGUgXCJuby11bnVzZWQtZXhwcmVzc2lvbnNcIiBpcyBkaXNhYmxlZCBmb3IgdGhpcyBjb2RlXG4vLyBzaW5jZSBpdCBjb25zaWRlcnMgc3VjaCBhY2Nlc3Npb25zIG5vb3BcbmlmICggIXN1cHBvcnQub3B0U2VsZWN0ZWQgKSB7XG5cdGpRdWVyeS5wcm9wSG9va3Muc2VsZWN0ZWQgPSB7XG5cdFx0Z2V0OiBmdW5jdGlvbiggZWxlbSApIHtcblxuXHRcdFx0LyogZXNsaW50IG5vLXVudXNlZC1leHByZXNzaW9uczogXCJvZmZcIiAqL1xuXG5cdFx0XHR2YXIgcGFyZW50ID0gZWxlbS5wYXJlbnROb2RlO1xuXHRcdFx0aWYgKCBwYXJlbnQgJiYgcGFyZW50LnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gbnVsbDtcblx0XHR9LFxuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdC8qIGVzbGludCBuby11bnVzZWQtZXhwcmVzc2lvbnM6IFwib2ZmXCIgKi9cblxuXHRcdFx0dmFyIHBhcmVudCA9IGVsZW0ucGFyZW50Tm9kZTtcblx0XHRcdGlmICggcGFyZW50ICkge1xuXHRcdFx0XHRwYXJlbnQuc2VsZWN0ZWRJbmRleDtcblxuXHRcdFx0XHRpZiAoIHBhcmVudC5wYXJlbnROb2RlICkge1xuXHRcdFx0XHRcdHBhcmVudC5wYXJlbnROb2RlLnNlbGVjdGVkSW5kZXg7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG59XG5cbmpRdWVyeS5lYWNoKCBbXG5cdFwidGFiSW5kZXhcIixcblx0XCJyZWFkT25seVwiLFxuXHRcIm1heExlbmd0aFwiLFxuXHRcImNlbGxTcGFjaW5nXCIsXG5cdFwiY2VsbFBhZGRpbmdcIixcblx0XCJyb3dTcGFuXCIsXG5cdFwiY29sU3BhblwiLFxuXHRcInVzZU1hcFwiLFxuXHRcImZyYW1lQm9yZGVyXCIsXG5cdFwiY29udGVudEVkaXRhYmxlXCJcbl0sIGZ1bmN0aW9uKCkge1xuXHRqUXVlcnkucHJvcEZpeFsgdGhpcy50b0xvd2VyQ2FzZSgpIF0gPSB0aGlzO1xufSApO1xuXG5cblxuXG5cdC8vIFN0cmlwIGFuZCBjb2xsYXBzZSB3aGl0ZXNwYWNlIGFjY29yZGluZyB0byBIVE1MIHNwZWNcblx0Ly8gaHR0cHM6Ly9odG1sLnNwZWMud2hhdHdnLm9yZy9tdWx0aXBhZ2UvaW5mcmFzdHJ1Y3R1cmUuaHRtbCNzdHJpcC1hbmQtY29sbGFwc2Utd2hpdGVzcGFjZVxuXHRmdW5jdGlvbiBzdHJpcEFuZENvbGxhcHNlKCB2YWx1ZSApIHtcblx0XHR2YXIgdG9rZW5zID0gdmFsdWUubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblx0XHRyZXR1cm4gdG9rZW5zLmpvaW4oIFwiIFwiICk7XG5cdH1cblxuXG5mdW5jdGlvbiBnZXRDbGFzcyggZWxlbSApIHtcblx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlICYmIGVsZW0uZ2V0QXR0cmlidXRlKCBcImNsYXNzXCIgKSB8fCBcIlwiO1xufVxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdGFkZENsYXNzOiBmdW5jdGlvbiggdmFsdWUgKSB7XG5cdFx0dmFyIGNsYXNzZXMsIGVsZW0sIGN1ciwgY3VyVmFsdWUsIGNsYXp6LCBqLCBmaW5hbFZhbHVlLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCB2YWx1ZSApICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGogKSB7XG5cdFx0XHRcdGpRdWVyeSggdGhpcyApLmFkZENsYXNzKCB2YWx1ZS5jYWxsKCB0aGlzLCBqLCBnZXRDbGFzcyggdGhpcyApICkgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cblx0XHRpZiAoIHR5cGVvZiB2YWx1ZSA9PT0gXCJzdHJpbmdcIiAmJiB2YWx1ZSApIHtcblx0XHRcdGNsYXNzZXMgPSB2YWx1ZS5tYXRjaCggcm5vdGh0bWx3aGl0ZSApIHx8IFtdO1xuXG5cdFx0XHR3aGlsZSAoICggZWxlbSA9IHRoaXNbIGkrKyBdICkgKSB7XG5cdFx0XHRcdGN1clZhbHVlID0gZ2V0Q2xhc3MoIGVsZW0gKTtcblx0XHRcdFx0Y3VyID0gZWxlbS5ub2RlVHlwZSA9PT0gMSAmJiAoIFwiIFwiICsgc3RyaXBBbmRDb2xsYXBzZSggY3VyVmFsdWUgKSArIFwiIFwiICk7XG5cblx0XHRcdFx0aWYgKCBjdXIgKSB7XG5cdFx0XHRcdFx0aiA9IDA7XG5cdFx0XHRcdFx0d2hpbGUgKCAoIGNsYXp6ID0gY2xhc3Nlc1sgaisrIF0gKSApIHtcblx0XHRcdFx0XHRcdGlmICggY3VyLmluZGV4T2YoIFwiIFwiICsgY2xhenogKyBcIiBcIiApIDwgMCApIHtcblx0XHRcdFx0XHRcdFx0Y3VyICs9IGNsYXp6ICsgXCIgXCI7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gT25seSBhc3NpZ24gaWYgZGlmZmVyZW50IHRvIGF2b2lkIHVubmVlZGVkIHJlbmRlcmluZy5cblx0XHRcdFx0XHRmaW5hbFZhbHVlID0gc3RyaXBBbmRDb2xsYXBzZSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBjdXJWYWx1ZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcImNsYXNzXCIsIGZpbmFsVmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHRyZW1vdmVDbGFzczogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBjbGFzc2VzLCBlbGVtLCBjdXIsIGN1clZhbHVlLCBjbGF6eiwgaiwgZmluYWxWYWx1ZSxcblx0XHRcdGkgPSAwO1xuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBqICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS5yZW1vdmVDbGFzcyggdmFsdWUuY2FsbCggdGhpcywgaiwgZ2V0Q2xhc3MoIHRoaXMgKSApICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0aWYgKCAhYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiB0aGlzLmF0dHIoIFwiY2xhc3NcIiwgXCJcIiApO1xuXHRcdH1cblxuXHRcdGlmICggdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiICYmIHZhbHVlICkge1xuXHRcdFx0Y2xhc3NlcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdHdoaWxlICggKCBlbGVtID0gdGhpc1sgaSsrIF0gKSApIHtcblx0XHRcdFx0Y3VyVmFsdWUgPSBnZXRDbGFzcyggZWxlbSApO1xuXG5cdFx0XHRcdC8vIFRoaXMgZXhwcmVzc2lvbiBpcyBoZXJlIGZvciBiZXR0ZXIgY29tcHJlc3NpYmlsaXR5IChzZWUgYWRkQ2xhc3MpXG5cdFx0XHRcdGN1ciA9IGVsZW0ubm9kZVR5cGUgPT09IDEgJiYgKCBcIiBcIiArIHN0cmlwQW5kQ29sbGFwc2UoIGN1clZhbHVlICkgKyBcIiBcIiApO1xuXG5cdFx0XHRcdGlmICggY3VyICkge1xuXHRcdFx0XHRcdGogPSAwO1xuXHRcdFx0XHRcdHdoaWxlICggKCBjbGF6eiA9IGNsYXNzZXNbIGorKyBdICkgKSB7XG5cblx0XHRcdFx0XHRcdC8vIFJlbW92ZSAqYWxsKiBpbnN0YW5jZXNcblx0XHRcdFx0XHRcdHdoaWxlICggY3VyLmluZGV4T2YoIFwiIFwiICsgY2xhenogKyBcIiBcIiApID4gLTEgKSB7XG5cdFx0XHRcdFx0XHRcdGN1ciA9IGN1ci5yZXBsYWNlKCBcIiBcIiArIGNsYXp6ICsgXCIgXCIsIFwiIFwiICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gT25seSBhc3NpZ24gaWYgZGlmZmVyZW50IHRvIGF2b2lkIHVubmVlZGVkIHJlbmRlcmluZy5cblx0XHRcdFx0XHRmaW5hbFZhbHVlID0gc3RyaXBBbmRDb2xsYXBzZSggY3VyICk7XG5cdFx0XHRcdFx0aWYgKCBjdXJWYWx1ZSAhPT0gZmluYWxWYWx1ZSApIHtcblx0XHRcdFx0XHRcdGVsZW0uc2V0QXR0cmlidXRlKCBcImNsYXNzXCIsIGZpbmFsVmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR0b2dnbGVDbGFzczogZnVuY3Rpb24oIHZhbHVlLCBzdGF0ZVZhbCApIHtcblx0XHR2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcblxuXHRcdGlmICggdHlwZW9mIHN0YXRlVmFsID09PSBcImJvb2xlYW5cIiAmJiB0eXBlID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0cmV0dXJuIHN0YXRlVmFsID8gdGhpcy5hZGRDbGFzcyggdmFsdWUgKSA6IHRoaXMucmVtb3ZlQ2xhc3MoIHZhbHVlICk7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWUgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS50b2dnbGVDbGFzcyhcblx0XHRcdFx0XHR2YWx1ZS5jYWxsKCB0aGlzLCBpLCBnZXRDbGFzcyggdGhpcyApLCBzdGF0ZVZhbCApLFxuXHRcdFx0XHRcdHN0YXRlVmFsXG5cdFx0XHRcdCk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgY2xhc3NOYW1lLCBpLCBzZWxmLCBjbGFzc05hbWVzO1xuXG5cdFx0XHRpZiAoIHR5cGUgPT09IFwic3RyaW5nXCIgKSB7XG5cblx0XHRcdFx0Ly8gVG9nZ2xlIGluZGl2aWR1YWwgY2xhc3MgbmFtZXNcblx0XHRcdFx0aSA9IDA7XG5cdFx0XHRcdHNlbGYgPSBqUXVlcnkoIHRoaXMgKTtcblx0XHRcdFx0Y2xhc3NOYW1lcyA9IHZhbHVlLm1hdGNoKCBybm90aHRtbHdoaXRlICkgfHwgW107XG5cblx0XHRcdFx0d2hpbGUgKCAoIGNsYXNzTmFtZSA9IGNsYXNzTmFtZXNbIGkrKyBdICkgKSB7XG5cblx0XHRcdFx0XHQvLyBDaGVjayBlYWNoIGNsYXNzTmFtZSBnaXZlbiwgc3BhY2Ugc2VwYXJhdGVkIGxpc3Rcblx0XHRcdFx0XHRpZiAoIHNlbGYuaGFzQ2xhc3MoIGNsYXNzTmFtZSApICkge1xuXHRcdFx0XHRcdFx0c2VsZi5yZW1vdmVDbGFzcyggY2xhc3NOYW1lICk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHNlbGYuYWRkQ2xhc3MoIGNsYXNzTmFtZSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHQvLyBUb2dnbGUgd2hvbGUgY2xhc3MgbmFtZVxuXHRcdFx0fSBlbHNlIGlmICggdmFsdWUgPT09IHVuZGVmaW5lZCB8fCB0eXBlID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRcdFx0Y2xhc3NOYW1lID0gZ2V0Q2xhc3MoIHRoaXMgKTtcblx0XHRcdFx0aWYgKCBjbGFzc05hbWUgKSB7XG5cblx0XHRcdFx0XHQvLyBTdG9yZSBjbGFzc05hbWUgaWYgc2V0XG5cdFx0XHRcdFx0ZGF0YVByaXYuc2V0KCB0aGlzLCBcIl9fY2xhc3NOYW1lX19cIiwgY2xhc3NOYW1lICk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBJZiB0aGUgZWxlbWVudCBoYXMgYSBjbGFzcyBuYW1lIG9yIGlmIHdlJ3JlIHBhc3NlZCBgZmFsc2VgLFxuXHRcdFx0XHQvLyB0aGVuIHJlbW92ZSB0aGUgd2hvbGUgY2xhc3NuYW1lIChpZiB0aGVyZSB3YXMgb25lLCB0aGUgYWJvdmUgc2F2ZWQgaXQpLlxuXHRcdFx0XHQvLyBPdGhlcndpc2UgYnJpbmcgYmFjayB3aGF0ZXZlciB3YXMgcHJldmlvdXNseSBzYXZlZCAoaWYgYW55dGhpbmcpLFxuXHRcdFx0XHQvLyBmYWxsaW5nIGJhY2sgdG8gdGhlIGVtcHR5IHN0cmluZyBpZiBub3RoaW5nIHdhcyBzdG9yZWQuXG5cdFx0XHRcdGlmICggdGhpcy5zZXRBdHRyaWJ1dGUgKSB7XG5cdFx0XHRcdFx0dGhpcy5zZXRBdHRyaWJ1dGUoIFwiY2xhc3NcIixcblx0XHRcdFx0XHRcdGNsYXNzTmFtZSB8fCB2YWx1ZSA9PT0gZmFsc2UgP1xuXHRcdFx0XHRcdFx0XCJcIiA6XG5cdFx0XHRcdFx0XHRkYXRhUHJpdi5nZXQoIHRoaXMsIFwiX19jbGFzc05hbWVfX1wiICkgfHwgXCJcIlxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0aGFzQ2xhc3M6IGZ1bmN0aW9uKCBzZWxlY3RvciApIHtcblx0XHR2YXIgY2xhc3NOYW1lLCBlbGVtLFxuXHRcdFx0aSA9IDA7XG5cblx0XHRjbGFzc05hbWUgPSBcIiBcIiArIHNlbGVjdG9yICsgXCIgXCI7XG5cdFx0d2hpbGUgKCAoIGVsZW0gPSB0aGlzWyBpKysgXSApICkge1xuXHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSAxICYmXG5cdFx0XHRcdCggXCIgXCIgKyBzdHJpcEFuZENvbGxhcHNlKCBnZXRDbGFzcyggZWxlbSApICkgKyBcIiBcIiApLmluZGV4T2YoIGNsYXNzTmFtZSApID4gLTEgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZhbHNlO1xuXHR9XG59ICk7XG5cblxuXG5cbnZhciBycmV0dXJuID0gL1xcci9nO1xuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cdHZhbDogZnVuY3Rpb24oIHZhbHVlICkge1xuXHRcdHZhciBob29rcywgcmV0LCBpc0Z1bmN0aW9uLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXTtcblxuXHRcdGlmICggIWFyZ3VtZW50cy5sZW5ndGggKSB7XG5cdFx0XHRpZiAoIGVsZW0gKSB7XG5cdFx0XHRcdGhvb2tzID0galF1ZXJ5LnZhbEhvb2tzWyBlbGVtLnR5cGUgXSB8fFxuXHRcdFx0XHRcdGpRdWVyeS52YWxIb29rc1sgZWxlbS5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpIF07XG5cblx0XHRcdFx0aWYgKCBob29rcyAmJlxuXHRcdFx0XHRcdFwiZ2V0XCIgaW4gaG9va3MgJiZcblx0XHRcdFx0XHQoIHJldCA9IGhvb2tzLmdldCggZWxlbSwgXCJ2YWx1ZVwiICkgKSAhPT0gdW5kZWZpbmVkXG5cdFx0XHRcdCkge1xuXHRcdFx0XHRcdHJldHVybiByZXQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXQgPSBlbGVtLnZhbHVlO1xuXG5cdFx0XHRcdC8vIEhhbmRsZSBtb3N0IGNvbW1vbiBzdHJpbmcgY2FzZXNcblx0XHRcdFx0aWYgKCB0eXBlb2YgcmV0ID09PSBcInN0cmluZ1wiICkge1xuXHRcdFx0XHRcdHJldHVybiByZXQucmVwbGFjZSggcnJldHVybiwgXCJcIiApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gSGFuZGxlIGNhc2VzIHdoZXJlIHZhbHVlIGlzIG51bGwvdW5kZWYgb3IgbnVtYmVyXG5cdFx0XHRcdHJldHVybiByZXQgPT0gbnVsbCA/IFwiXCIgOiByZXQ7XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpc0Z1bmN0aW9uID0galF1ZXJ5LmlzRnVuY3Rpb24oIHZhbHVlICk7XG5cblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdHZhciB2YWw7XG5cblx0XHRcdGlmICggdGhpcy5ub2RlVHlwZSAhPT0gMSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIGlzRnVuY3Rpb24gKSB7XG5cdFx0XHRcdHZhbCA9IHZhbHVlLmNhbGwoIHRoaXMsIGksIGpRdWVyeSggdGhpcyApLnZhbCgpICk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR2YWwgPSB2YWx1ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gVHJlYXQgbnVsbC91bmRlZmluZWQgYXMgXCJcIjsgY29udmVydCBudW1iZXJzIHRvIHN0cmluZ1xuXHRcdFx0aWYgKCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdFx0dmFsID0gXCJcIjtcblxuXHRcdFx0fSBlbHNlIGlmICggdHlwZW9mIHZhbCA9PT0gXCJudW1iZXJcIiApIHtcblx0XHRcdFx0dmFsICs9IFwiXCI7XG5cblx0XHRcdH0gZWxzZSBpZiAoIEFycmF5LmlzQXJyYXkoIHZhbCApICkge1xuXHRcdFx0XHR2YWwgPSBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWx1ZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSArIFwiXCI7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblxuXHRcdFx0aG9va3MgPSBqUXVlcnkudmFsSG9va3NbIHRoaXMudHlwZSBdIHx8IGpRdWVyeS52YWxIb29rc1sgdGhpcy5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpIF07XG5cblx0XHRcdC8vIElmIHNldCByZXR1cm5zIHVuZGVmaW5lZCwgZmFsbCBiYWNrIHRvIG5vcm1hbCBzZXR0aW5nXG5cdFx0XHRpZiAoICFob29rcyB8fCAhKCBcInNldFwiIGluIGhvb2tzICkgfHwgaG9va3Muc2V0KCB0aGlzLCB2YWwsIFwidmFsdWVcIiApID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHRoaXMudmFsdWUgPSB2YWw7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5leHRlbmQoIHtcblx0dmFsSG9va3M6IHtcblx0XHRvcHRpb246IHtcblx0XHRcdGdldDogZnVuY3Rpb24oIGVsZW0gKSB7XG5cblx0XHRcdFx0dmFyIHZhbCA9IGpRdWVyeS5maW5kLmF0dHIoIGVsZW0sIFwidmFsdWVcIiApO1xuXHRcdFx0XHRyZXR1cm4gdmFsICE9IG51bGwgP1xuXHRcdFx0XHRcdHZhbCA6XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTEwIC0gMTEgb25seVxuXHRcdFx0XHRcdC8vIG9wdGlvbi50ZXh0IHRocm93cyBleGNlcHRpb25zICgjMTQ2ODYsICMxNDg1OClcblx0XHRcdFx0XHQvLyBTdHJpcCBhbmQgY29sbGFwc2Ugd2hpdGVzcGFjZVxuXHRcdFx0XHRcdC8vIGh0dHBzOi8vaHRtbC5zcGVjLndoYXR3Zy5vcmcvI3N0cmlwLWFuZC1jb2xsYXBzZS13aGl0ZXNwYWNlXG5cdFx0XHRcdFx0c3RyaXBBbmRDb2xsYXBzZSggalF1ZXJ5LnRleHQoIGVsZW0gKSApO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0c2VsZWN0OiB7XG5cdFx0XHRnZXQ6IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0XHR2YXIgdmFsdWUsIG9wdGlvbiwgaSxcblx0XHRcdFx0XHRvcHRpb25zID0gZWxlbS5vcHRpb25zLFxuXHRcdFx0XHRcdGluZGV4ID0gZWxlbS5zZWxlY3RlZEluZGV4LFxuXHRcdFx0XHRcdG9uZSA9IGVsZW0udHlwZSA9PT0gXCJzZWxlY3Qtb25lXCIsXG5cdFx0XHRcdFx0dmFsdWVzID0gb25lID8gbnVsbCA6IFtdLFxuXHRcdFx0XHRcdG1heCA9IG9uZSA/IGluZGV4ICsgMSA6IG9wdGlvbnMubGVuZ3RoO1xuXG5cdFx0XHRcdGlmICggaW5kZXggPCAwICkge1xuXHRcdFx0XHRcdGkgPSBtYXg7XG5cblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRpID0gb25lID8gaW5kZXggOiAwO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gTG9vcCB0aHJvdWdoIGFsbCB0aGUgc2VsZWN0ZWQgb3B0aW9uc1xuXHRcdFx0XHRmb3IgKCA7IGkgPCBtYXg7IGkrKyApIHtcblx0XHRcdFx0XHRvcHRpb24gPSBvcHRpb25zWyBpIF07XG5cblx0XHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA8PTkgb25seVxuXHRcdFx0XHRcdC8vIElFOC05IGRvZXNuJ3QgdXBkYXRlIHNlbGVjdGVkIGFmdGVyIGZvcm0gcmVzZXQgKCMyNTUxKVxuXHRcdFx0XHRcdGlmICggKCBvcHRpb24uc2VsZWN0ZWQgfHwgaSA9PT0gaW5kZXggKSAmJlxuXG5cdFx0XHRcdFx0XHRcdC8vIERvbid0IHJldHVybiBvcHRpb25zIHRoYXQgYXJlIGRpc2FibGVkIG9yIGluIGEgZGlzYWJsZWQgb3B0Z3JvdXBcblx0XHRcdFx0XHRcdFx0IW9wdGlvbi5kaXNhYmxlZCAmJlxuXHRcdFx0XHRcdFx0XHQoICFvcHRpb24ucGFyZW50Tm9kZS5kaXNhYmxlZCB8fFxuXHRcdFx0XHRcdFx0XHRcdCFub2RlTmFtZSggb3B0aW9uLnBhcmVudE5vZGUsIFwib3B0Z3JvdXBcIiApICkgKSB7XG5cblx0XHRcdFx0XHRcdC8vIEdldCB0aGUgc3BlY2lmaWMgdmFsdWUgZm9yIHRoZSBvcHRpb25cblx0XHRcdFx0XHRcdHZhbHVlID0galF1ZXJ5KCBvcHRpb24gKS52YWwoKTtcblxuXHRcdFx0XHRcdFx0Ly8gV2UgZG9uJ3QgbmVlZCBhbiBhcnJheSBmb3Igb25lIHNlbGVjdHNcblx0XHRcdFx0XHRcdGlmICggb25lICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIE11bHRpLVNlbGVjdHMgcmV0dXJuIGFuIGFycmF5XG5cdFx0XHRcdFx0XHR2YWx1ZXMucHVzaCggdmFsdWUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fSxcblxuXHRcdFx0c2V0OiBmdW5jdGlvbiggZWxlbSwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBvcHRpb25TZXQsIG9wdGlvbixcblx0XHRcdFx0XHRvcHRpb25zID0gZWxlbS5vcHRpb25zLFxuXHRcdFx0XHRcdHZhbHVlcyA9IGpRdWVyeS5tYWtlQXJyYXkoIHZhbHVlICksXG5cdFx0XHRcdFx0aSA9IG9wdGlvbnMubGVuZ3RoO1xuXG5cdFx0XHRcdHdoaWxlICggaS0tICkge1xuXHRcdFx0XHRcdG9wdGlvbiA9IG9wdGlvbnNbIGkgXTtcblxuXHRcdFx0XHRcdC8qIGVzbGludC1kaXNhYmxlIG5vLWNvbmQtYXNzaWduICovXG5cblx0XHRcdFx0XHRpZiAoIG9wdGlvbi5zZWxlY3RlZCA9XG5cdFx0XHRcdFx0XHRqUXVlcnkuaW5BcnJheSggalF1ZXJ5LnZhbEhvb2tzLm9wdGlvbi5nZXQoIG9wdGlvbiApLCB2YWx1ZXMgKSA+IC0xXG5cdFx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0XHRvcHRpb25TZXQgPSB0cnVlO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8qIGVzbGludC1lbmFibGUgbm8tY29uZC1hc3NpZ24gKi9cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEZvcmNlIGJyb3dzZXJzIHRvIGJlaGF2ZSBjb25zaXN0ZW50bHkgd2hlbiBub24tbWF0Y2hpbmcgdmFsdWUgaXMgc2V0XG5cdFx0XHRcdGlmICggIW9wdGlvblNldCApIHtcblx0XHRcdFx0XHRlbGVtLnNlbGVjdGVkSW5kZXggPSAtMTtcblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gdmFsdWVzO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxufSApO1xuXG4vLyBSYWRpb3MgYW5kIGNoZWNrYm94ZXMgZ2V0dGVyL3NldHRlclxualF1ZXJ5LmVhY2goIFsgXCJyYWRpb1wiLCBcImNoZWNrYm94XCIgXSwgZnVuY3Rpb24oKSB7XG5cdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdID0ge1xuXHRcdHNldDogZnVuY3Rpb24oIGVsZW0sIHZhbHVlICkge1xuXHRcdFx0aWYgKCBBcnJheS5pc0FycmF5KCB2YWx1ZSApICkge1xuXHRcdFx0XHRyZXR1cm4gKCBlbGVtLmNoZWNrZWQgPSBqUXVlcnkuaW5BcnJheSggalF1ZXJ5KCBlbGVtICkudmFsKCksIHZhbHVlICkgPiAtMSApO1xuXHRcdFx0fVxuXHRcdH1cblx0fTtcblx0aWYgKCAhc3VwcG9ydC5jaGVja09uICkge1xuXHRcdGpRdWVyeS52YWxIb29rc1sgdGhpcyBdLmdldCA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGVsZW0uZ2V0QXR0cmlidXRlKCBcInZhbHVlXCIgKSA9PT0gbnVsbCA/IFwib25cIiA6IGVsZW0udmFsdWU7XG5cdFx0fTtcblx0fVxufSApO1xuXG5cblxuXG4vLyBSZXR1cm4galF1ZXJ5IGZvciBhdHRyaWJ1dGVzLW9ubHkgaW5jbHVzaW9uXG5cblxudmFyIHJmb2N1c01vcnBoID0gL14oPzpmb2N1c2luZm9jdXN8Zm9jdXNvdXRibHVyKSQvO1xuXG5qUXVlcnkuZXh0ZW5kKCBqUXVlcnkuZXZlbnQsIHtcblxuXHR0cmlnZ2VyOiBmdW5jdGlvbiggZXZlbnQsIGRhdGEsIGVsZW0sIG9ubHlIYW5kbGVycyApIHtcblxuXHRcdHZhciBpLCBjdXIsIHRtcCwgYnViYmxlVHlwZSwgb250eXBlLCBoYW5kbGUsIHNwZWNpYWwsXG5cdFx0XHRldmVudFBhdGggPSBbIGVsZW0gfHwgZG9jdW1lbnQgXSxcblx0XHRcdHR5cGUgPSBoYXNPd24uY2FsbCggZXZlbnQsIFwidHlwZVwiICkgPyBldmVudC50eXBlIDogZXZlbnQsXG5cdFx0XHRuYW1lc3BhY2VzID0gaGFzT3duLmNhbGwoIGV2ZW50LCBcIm5hbWVzcGFjZVwiICkgPyBldmVudC5uYW1lc3BhY2Uuc3BsaXQoIFwiLlwiICkgOiBbXTtcblxuXHRcdGN1ciA9IHRtcCA9IGVsZW0gPSBlbGVtIHx8IGRvY3VtZW50O1xuXG5cdFx0Ly8gRG9uJ3QgZG8gZXZlbnRzIG9uIHRleHQgYW5kIGNvbW1lbnQgbm9kZXNcblx0XHRpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDMgfHwgZWxlbS5ub2RlVHlwZSA9PT0gOCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBmb2N1cy9ibHVyIG1vcnBocyB0byBmb2N1c2luL291dDsgZW5zdXJlIHdlJ3JlIG5vdCBmaXJpbmcgdGhlbSByaWdodCBub3dcblx0XHRpZiAoIHJmb2N1c01vcnBoLnRlc3QoIHR5cGUgKyBqUXVlcnkuZXZlbnQudHJpZ2dlcmVkICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCB0eXBlLmluZGV4T2YoIFwiLlwiICkgPiAtMSApIHtcblxuXHRcdFx0Ly8gTmFtZXNwYWNlZCB0cmlnZ2VyOyBjcmVhdGUgYSByZWdleHAgdG8gbWF0Y2ggZXZlbnQgdHlwZSBpbiBoYW5kbGUoKVxuXHRcdFx0bmFtZXNwYWNlcyA9IHR5cGUuc3BsaXQoIFwiLlwiICk7XG5cdFx0XHR0eXBlID0gbmFtZXNwYWNlcy5zaGlmdCgpO1xuXHRcdFx0bmFtZXNwYWNlcy5zb3J0KCk7XG5cdFx0fVxuXHRcdG9udHlwZSA9IHR5cGUuaW5kZXhPZiggXCI6XCIgKSA8IDAgJiYgXCJvblwiICsgdHlwZTtcblxuXHRcdC8vIENhbGxlciBjYW4gcGFzcyBpbiBhIGpRdWVyeS5FdmVudCBvYmplY3QsIE9iamVjdCwgb3IganVzdCBhbiBldmVudCB0eXBlIHN0cmluZ1xuXHRcdGV2ZW50ID0gZXZlbnRbIGpRdWVyeS5leHBhbmRvIF0gP1xuXHRcdFx0ZXZlbnQgOlxuXHRcdFx0bmV3IGpRdWVyeS5FdmVudCggdHlwZSwgdHlwZW9mIGV2ZW50ID09PSBcIm9iamVjdFwiICYmIGV2ZW50ICk7XG5cblx0XHQvLyBUcmlnZ2VyIGJpdG1hc2s6ICYgMSBmb3IgbmF0aXZlIGhhbmRsZXJzOyAmIDIgZm9yIGpRdWVyeSAoYWx3YXlzIHRydWUpXG5cdFx0ZXZlbnQuaXNUcmlnZ2VyID0gb25seUhhbmRsZXJzID8gMiA6IDM7XG5cdFx0ZXZlbnQubmFtZXNwYWNlID0gbmFtZXNwYWNlcy5qb2luKCBcIi5cIiApO1xuXHRcdGV2ZW50LnJuYW1lc3BhY2UgPSBldmVudC5uYW1lc3BhY2UgP1xuXHRcdFx0bmV3IFJlZ0V4cCggXCIoXnxcXFxcLilcIiArIG5hbWVzcGFjZXMuam9pbiggXCJcXFxcLig/Oi4qXFxcXC58KVwiICkgKyBcIihcXFxcLnwkKVwiICkgOlxuXHRcdFx0bnVsbDtcblxuXHRcdC8vIENsZWFuIHVwIHRoZSBldmVudCBpbiBjYXNlIGl0IGlzIGJlaW5nIHJldXNlZFxuXHRcdGV2ZW50LnJlc3VsdCA9IHVuZGVmaW5lZDtcblx0XHRpZiAoICFldmVudC50YXJnZXQgKSB7XG5cdFx0XHRldmVudC50YXJnZXQgPSBlbGVtO1xuXHRcdH1cblxuXHRcdC8vIENsb25lIGFueSBpbmNvbWluZyBkYXRhIGFuZCBwcmVwZW5kIHRoZSBldmVudCwgY3JlYXRpbmcgdGhlIGhhbmRsZXIgYXJnIGxpc3Rcblx0XHRkYXRhID0gZGF0YSA9PSBudWxsID9cblx0XHRcdFsgZXZlbnQgXSA6XG5cdFx0XHRqUXVlcnkubWFrZUFycmF5KCBkYXRhLCBbIGV2ZW50IF0gKTtcblxuXHRcdC8vIEFsbG93IHNwZWNpYWwgZXZlbnRzIHRvIGRyYXcgb3V0c2lkZSB0aGUgbGluZXNcblx0XHRzcGVjaWFsID0galF1ZXJ5LmV2ZW50LnNwZWNpYWxbIHR5cGUgXSB8fCB7fTtcblx0XHRpZiAoICFvbmx5SGFuZGxlcnMgJiYgc3BlY2lhbC50cmlnZ2VyICYmIHNwZWNpYWwudHJpZ2dlci5hcHBseSggZWxlbSwgZGF0YSApID09PSBmYWxzZSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBEZXRlcm1pbmUgZXZlbnQgcHJvcGFnYXRpb24gcGF0aCBpbiBhZHZhbmNlLCBwZXIgVzNDIGV2ZW50cyBzcGVjICgjOTk1MSlcblx0XHQvLyBCdWJibGUgdXAgdG8gZG9jdW1lbnQsIHRoZW4gdG8gd2luZG93OyB3YXRjaCBmb3IgYSBnbG9iYWwgb3duZXJEb2N1bWVudCB2YXIgKCM5NzI0KVxuXHRcdGlmICggIW9ubHlIYW5kbGVycyAmJiAhc3BlY2lhbC5ub0J1YmJsZSAmJiAhalF1ZXJ5LmlzV2luZG93KCBlbGVtICkgKSB7XG5cblx0XHRcdGJ1YmJsZVR5cGUgPSBzcGVjaWFsLmRlbGVnYXRlVHlwZSB8fCB0eXBlO1xuXHRcdFx0aWYgKCAhcmZvY3VzTW9ycGgudGVzdCggYnViYmxlVHlwZSArIHR5cGUgKSApIHtcblx0XHRcdFx0Y3VyID0gY3VyLnBhcmVudE5vZGU7XG5cdFx0XHR9XG5cdFx0XHRmb3IgKCA7IGN1cjsgY3VyID0gY3VyLnBhcmVudE5vZGUgKSB7XG5cdFx0XHRcdGV2ZW50UGF0aC5wdXNoKCBjdXIgKTtcblx0XHRcdFx0dG1wID0gY3VyO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBPbmx5IGFkZCB3aW5kb3cgaWYgd2UgZ290IHRvIGRvY3VtZW50IChlLmcuLCBub3QgcGxhaW4gb2JqIG9yIGRldGFjaGVkIERPTSlcblx0XHRcdGlmICggdG1wID09PSAoIGVsZW0ub3duZXJEb2N1bWVudCB8fCBkb2N1bWVudCApICkge1xuXHRcdFx0XHRldmVudFBhdGgucHVzaCggdG1wLmRlZmF1bHRWaWV3IHx8IHRtcC5wYXJlbnRXaW5kb3cgfHwgd2luZG93ICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gRmlyZSBoYW5kbGVycyBvbiB0aGUgZXZlbnQgcGF0aFxuXHRcdGkgPSAwO1xuXHRcdHdoaWxlICggKCBjdXIgPSBldmVudFBhdGhbIGkrKyBdICkgJiYgIWV2ZW50LmlzUHJvcGFnYXRpb25TdG9wcGVkKCkgKSB7XG5cblx0XHRcdGV2ZW50LnR5cGUgPSBpID4gMSA/XG5cdFx0XHRcdGJ1YmJsZVR5cGUgOlxuXHRcdFx0XHRzcGVjaWFsLmJpbmRUeXBlIHx8IHR5cGU7XG5cblx0XHRcdC8vIGpRdWVyeSBoYW5kbGVyXG5cdFx0XHRoYW5kbGUgPSAoIGRhdGFQcml2LmdldCggY3VyLCBcImV2ZW50c1wiICkgfHwge30gKVsgZXZlbnQudHlwZSBdICYmXG5cdFx0XHRcdGRhdGFQcml2LmdldCggY3VyLCBcImhhbmRsZVwiICk7XG5cdFx0XHRpZiAoIGhhbmRsZSApIHtcblx0XHRcdFx0aGFuZGxlLmFwcGx5KCBjdXIsIGRhdGEgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gTmF0aXZlIGhhbmRsZXJcblx0XHRcdGhhbmRsZSA9IG9udHlwZSAmJiBjdXJbIG9udHlwZSBdO1xuXHRcdFx0aWYgKCBoYW5kbGUgJiYgaGFuZGxlLmFwcGx5ICYmIGFjY2VwdERhdGEoIGN1ciApICkge1xuXHRcdFx0XHRldmVudC5yZXN1bHQgPSBoYW5kbGUuYXBwbHkoIGN1ciwgZGF0YSApO1xuXHRcdFx0XHRpZiAoIGV2ZW50LnJlc3VsdCA9PT0gZmFsc2UgKSB7XG5cdFx0XHRcdFx0ZXZlbnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRldmVudC50eXBlID0gdHlwZTtcblxuXHRcdC8vIElmIG5vYm9keSBwcmV2ZW50ZWQgdGhlIGRlZmF1bHQgYWN0aW9uLCBkbyBpdCBub3dcblx0XHRpZiAoICFvbmx5SGFuZGxlcnMgJiYgIWV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpICkge1xuXG5cdFx0XHRpZiAoICggIXNwZWNpYWwuX2RlZmF1bHQgfHxcblx0XHRcdFx0c3BlY2lhbC5fZGVmYXVsdC5hcHBseSggZXZlbnRQYXRoLnBvcCgpLCBkYXRhICkgPT09IGZhbHNlICkgJiZcblx0XHRcdFx0YWNjZXB0RGF0YSggZWxlbSApICkge1xuXG5cdFx0XHRcdC8vIENhbGwgYSBuYXRpdmUgRE9NIG1ldGhvZCBvbiB0aGUgdGFyZ2V0IHdpdGggdGhlIHNhbWUgbmFtZSBhcyB0aGUgZXZlbnQuXG5cdFx0XHRcdC8vIERvbid0IGRvIGRlZmF1bHQgYWN0aW9ucyBvbiB3aW5kb3csIHRoYXQncyB3aGVyZSBnbG9iYWwgdmFyaWFibGVzIGJlICgjNjE3MClcblx0XHRcdFx0aWYgKCBvbnR5cGUgJiYgalF1ZXJ5LmlzRnVuY3Rpb24oIGVsZW1bIHR5cGUgXSApICYmICFqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vIERvbid0IHJlLXRyaWdnZXIgYW4gb25GT08gZXZlbnQgd2hlbiB3ZSBjYWxsIGl0cyBGT08oKSBtZXRob2Rcblx0XHRcdFx0XHR0bXAgPSBlbGVtWyBvbnR5cGUgXTtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSBudWxsO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIFByZXZlbnQgcmUtdHJpZ2dlcmluZyBvZiB0aGUgc2FtZSBldmVudCwgc2luY2Ugd2UgYWxyZWFkeSBidWJibGVkIGl0IGFib3ZlXG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHR5cGU7XG5cdFx0XHRcdFx0ZWxlbVsgdHlwZSBdKCk7XG5cdFx0XHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXJlZCA9IHVuZGVmaW5lZDtcblxuXHRcdFx0XHRcdGlmICggdG1wICkge1xuXHRcdFx0XHRcdFx0ZWxlbVsgb250eXBlIF0gPSB0bXA7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGV2ZW50LnJlc3VsdDtcblx0fSxcblxuXHQvLyBQaWdneWJhY2sgb24gYSBkb25vciBldmVudCB0byBzaW11bGF0ZSBhIGRpZmZlcmVudCBvbmVcblx0Ly8gVXNlZCBvbmx5IGZvciBgZm9jdXMoaW4gfCBvdXQpYCBldmVudHNcblx0c2ltdWxhdGU6IGZ1bmN0aW9uKCB0eXBlLCBlbGVtLCBldmVudCApIHtcblx0XHR2YXIgZSA9IGpRdWVyeS5leHRlbmQoXG5cdFx0XHRuZXcgalF1ZXJ5LkV2ZW50KCksXG5cdFx0XHRldmVudCxcblx0XHRcdHtcblx0XHRcdFx0dHlwZTogdHlwZSxcblx0XHRcdFx0aXNTaW11bGF0ZWQ6IHRydWVcblx0XHRcdH1cblx0XHQpO1xuXG5cdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIGUsIG51bGwsIGVsZW0gKTtcblx0fVxuXG59ICk7XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblxuXHR0cmlnZ2VyOiBmdW5jdGlvbiggdHlwZSwgZGF0YSApIHtcblx0XHRyZXR1cm4gdGhpcy5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCB0aGlzICk7XG5cdFx0fSApO1xuXHR9LFxuXHR0cmlnZ2VySGFuZGxlcjogZnVuY3Rpb24oIHR5cGUsIGRhdGEgKSB7XG5cdFx0dmFyIGVsZW0gPSB0aGlzWyAwIF07XG5cdFx0aWYgKCBlbGVtICkge1xuXHRcdFx0cmV0dXJuIGpRdWVyeS5ldmVudC50cmlnZ2VyKCB0eXBlLCBkYXRhLCBlbGVtLCB0cnVlICk7XG5cdFx0fVxuXHR9XG59ICk7XG5cblxualF1ZXJ5LmVhY2goICggXCJibHVyIGZvY3VzIGZvY3VzaW4gZm9jdXNvdXQgcmVzaXplIHNjcm9sbCBjbGljayBkYmxjbGljayBcIiArXG5cdFwibW91c2Vkb3duIG1vdXNldXAgbW91c2Vtb3ZlIG1vdXNlb3ZlciBtb3VzZW91dCBtb3VzZWVudGVyIG1vdXNlbGVhdmUgXCIgK1xuXHRcImNoYW5nZSBzZWxlY3Qgc3VibWl0IGtleWRvd24ga2V5cHJlc3Mga2V5dXAgY29udGV4dG1lbnVcIiApLnNwbGl0KCBcIiBcIiApLFxuXHRmdW5jdGlvbiggaSwgbmFtZSApIHtcblxuXHQvLyBIYW5kbGUgZXZlbnQgYmluZGluZ1xuXHRqUXVlcnkuZm5bIG5hbWUgXSA9IGZ1bmN0aW9uKCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA+IDAgP1xuXHRcdFx0dGhpcy5vbiggbmFtZSwgbnVsbCwgZGF0YSwgZm4gKSA6XG5cdFx0XHR0aGlzLnRyaWdnZXIoIG5hbWUgKTtcblx0fTtcbn0gKTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRob3ZlcjogZnVuY3Rpb24oIGZuT3ZlciwgZm5PdXQgKSB7XG5cdFx0cmV0dXJuIHRoaXMubW91c2VlbnRlciggZm5PdmVyICkubW91c2VsZWF2ZSggZm5PdXQgfHwgZm5PdmVyICk7XG5cdH1cbn0gKTtcblxuXG5cblxuc3VwcG9ydC5mb2N1c2luID0gXCJvbmZvY3VzaW5cIiBpbiB3aW5kb3c7XG5cblxuLy8gU3VwcG9ydDogRmlyZWZveCA8PTQ0XG4vLyBGaXJlZm94IGRvZXNuJ3QgaGF2ZSBmb2N1cyhpbiB8IG91dCkgZXZlbnRzXG4vLyBSZWxhdGVkIHRpY2tldCAtIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY4Nzc4N1xuLy9cbi8vIFN1cHBvcnQ6IENocm9tZSA8PTQ4IC0gNDksIFNhZmFyaSA8PTkuMCAtIDkuMVxuLy8gZm9jdXMoaW4gfCBvdXQpIGV2ZW50cyBmaXJlIGFmdGVyIGZvY3VzICYgYmx1ciBldmVudHMsXG4vLyB3aGljaCBpcyBzcGVjIHZpb2xhdGlvbiAtIGh0dHA6Ly93d3cudzMub3JnL1RSL0RPTS1MZXZlbC0zLUV2ZW50cy8jZXZlbnRzLWZvY3VzZXZlbnQtZXZlbnQtb3JkZXJcbi8vIFJlbGF0ZWQgdGlja2V0IC0gaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NDQ5ODU3XG5pZiAoICFzdXBwb3J0LmZvY3VzaW4gKSB7XG5cdGpRdWVyeS5lYWNoKCB7IGZvY3VzOiBcImZvY3VzaW5cIiwgYmx1cjogXCJmb2N1c291dFwiIH0sIGZ1bmN0aW9uKCBvcmlnLCBmaXggKSB7XG5cblx0XHQvLyBBdHRhY2ggYSBzaW5nbGUgY2FwdHVyaW5nIGhhbmRsZXIgb24gdGhlIGRvY3VtZW50IHdoaWxlIHNvbWVvbmUgd2FudHMgZm9jdXNpbi9mb2N1c291dFxuXHRcdHZhciBoYW5kbGVyID0gZnVuY3Rpb24oIGV2ZW50ICkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnNpbXVsYXRlKCBmaXgsIGV2ZW50LnRhcmdldCwgalF1ZXJ5LmV2ZW50LmZpeCggZXZlbnQgKSApO1xuXHRcdH07XG5cblx0XHRqUXVlcnkuZXZlbnQuc3BlY2lhbFsgZml4IF0gPSB7XG5cdFx0XHRzZXR1cDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBkb2MgPSB0aGlzLm93bmVyRG9jdW1lbnQgfHwgdGhpcyxcblx0XHRcdFx0XHRhdHRhY2hlcyA9IGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXggKTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MuYWRkRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXgsICggYXR0YWNoZXMgfHwgMCApICsgMSApO1xuXHRcdFx0fSxcblx0XHRcdHRlYXJkb3duOiBmdW5jdGlvbigpIHtcblx0XHRcdFx0dmFyIGRvYyA9IHRoaXMub3duZXJEb2N1bWVudCB8fCB0aGlzLFxuXHRcdFx0XHRcdGF0dGFjaGVzID0gZGF0YVByaXYuYWNjZXNzKCBkb2MsIGZpeCApIC0gMTtcblxuXHRcdFx0XHRpZiAoICFhdHRhY2hlcyApIHtcblx0XHRcdFx0XHRkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lciggb3JpZywgaGFuZGxlciwgdHJ1ZSApO1xuXHRcdFx0XHRcdGRhdGFQcml2LnJlbW92ZSggZG9jLCBmaXggKTtcblxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdGRhdGFQcml2LmFjY2VzcyggZG9jLCBmaXgsIGF0dGFjaGVzICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9ICk7XG59XG52YXIgbG9jYXRpb24gPSB3aW5kb3cubG9jYXRpb247XG5cbnZhciBub25jZSA9IGpRdWVyeS5ub3coKTtcblxudmFyIHJxdWVyeSA9ICggL1xcPy8gKTtcblxuXG5cbi8vIENyb3NzLWJyb3dzZXIgeG1sIHBhcnNpbmdcbmpRdWVyeS5wYXJzZVhNTCA9IGZ1bmN0aW9uKCBkYXRhICkge1xuXHR2YXIgeG1sO1xuXHRpZiAoICFkYXRhIHx8IHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBudWxsO1xuXHR9XG5cblx0Ly8gU3VwcG9ydDogSUUgOSAtIDExIG9ubHlcblx0Ly8gSUUgdGhyb3dzIG9uIHBhcnNlRnJvbVN0cmluZyB3aXRoIGludmFsaWQgaW5wdXQuXG5cdHRyeSB7XG5cdFx0eG1sID0gKCBuZXcgd2luZG93LkRPTVBhcnNlcigpICkucGFyc2VGcm9tU3RyaW5nKCBkYXRhLCBcInRleHQveG1sXCIgKTtcblx0fSBjYXRjaCAoIGUgKSB7XG5cdFx0eG1sID0gdW5kZWZpbmVkO1xuXHR9XG5cblx0aWYgKCAheG1sIHx8IHhtbC5nZXRFbGVtZW50c0J5VGFnTmFtZSggXCJwYXJzZXJlcnJvclwiICkubGVuZ3RoICkge1xuXHRcdGpRdWVyeS5lcnJvciggXCJJbnZhbGlkIFhNTDogXCIgKyBkYXRhICk7XG5cdH1cblx0cmV0dXJuIHhtbDtcbn07XG5cblxudmFyXG5cdHJicmFja2V0ID0gL1xcW1xcXSQvLFxuXHRyQ1JMRiA9IC9cXHI/XFxuL2csXG5cdHJzdWJtaXR0ZXJUeXBlcyA9IC9eKD86c3VibWl0fGJ1dHRvbnxpbWFnZXxyZXNldHxmaWxlKSQvaSxcblx0cnN1Ym1pdHRhYmxlID0gL14oPzppbnB1dHxzZWxlY3R8dGV4dGFyZWF8a2V5Z2VuKS9pO1xuXG5mdW5jdGlvbiBidWlsZFBhcmFtcyggcHJlZml4LCBvYmosIHRyYWRpdGlvbmFsLCBhZGQgKSB7XG5cdHZhciBuYW1lO1xuXG5cdGlmICggQXJyYXkuaXNBcnJheSggb2JqICkgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgYXJyYXkgaXRlbS5cblx0XHRqUXVlcnkuZWFjaCggb2JqLCBmdW5jdGlvbiggaSwgdiApIHtcblx0XHRcdGlmICggdHJhZGl0aW9uYWwgfHwgcmJyYWNrZXQudGVzdCggcHJlZml4ICkgKSB7XG5cblx0XHRcdFx0Ly8gVHJlYXQgZWFjaCBhcnJheSBpdGVtIGFzIGEgc2NhbGFyLlxuXHRcdFx0XHRhZGQoIHByZWZpeCwgdiApO1xuXG5cdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdC8vIEl0ZW0gaXMgbm9uLXNjYWxhciAoYXJyYXkgb3Igb2JqZWN0KSwgZW5jb2RlIGl0cyBudW1lcmljIGluZGV4LlxuXHRcdFx0XHRidWlsZFBhcmFtcyhcblx0XHRcdFx0XHRwcmVmaXggKyBcIltcIiArICggdHlwZW9mIHYgPT09IFwib2JqZWN0XCIgJiYgdiAhPSBudWxsID8gaSA6IFwiXCIgKSArIFwiXVwiLFxuXHRcdFx0XHRcdHYsXG5cdFx0XHRcdFx0dHJhZGl0aW9uYWwsXG5cdFx0XHRcdFx0YWRkXG5cdFx0XHRcdCk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXG5cdH0gZWxzZSBpZiAoICF0cmFkaXRpb25hbCAmJiBqUXVlcnkudHlwZSggb2JqICkgPT09IFwib2JqZWN0XCIgKSB7XG5cblx0XHQvLyBTZXJpYWxpemUgb2JqZWN0IGl0ZW0uXG5cdFx0Zm9yICggbmFtZSBpbiBvYmogKSB7XG5cdFx0XHRidWlsZFBhcmFtcyggcHJlZml4ICsgXCJbXCIgKyBuYW1lICsgXCJdXCIsIG9ialsgbmFtZSBdLCB0cmFkaXRpb25hbCwgYWRkICk7XG5cdFx0fVxuXG5cdH0gZWxzZSB7XG5cblx0XHQvLyBTZXJpYWxpemUgc2NhbGFyIGl0ZW0uXG5cdFx0YWRkKCBwcmVmaXgsIG9iaiApO1xuXHR9XG59XG5cbi8vIFNlcmlhbGl6ZSBhbiBhcnJheSBvZiBmb3JtIGVsZW1lbnRzIG9yIGEgc2V0IG9mXG4vLyBrZXkvdmFsdWVzIGludG8gYSBxdWVyeSBzdHJpbmdcbmpRdWVyeS5wYXJhbSA9IGZ1bmN0aW9uKCBhLCB0cmFkaXRpb25hbCApIHtcblx0dmFyIHByZWZpeCxcblx0XHRzID0gW10sXG5cdFx0YWRkID0gZnVuY3Rpb24oIGtleSwgdmFsdWVPckZ1bmN0aW9uICkge1xuXG5cdFx0XHQvLyBJZiB2YWx1ZSBpcyBhIGZ1bmN0aW9uLCBpbnZva2UgaXQgYW5kIHVzZSBpdHMgcmV0dXJuIHZhbHVlXG5cdFx0XHR2YXIgdmFsdWUgPSBqUXVlcnkuaXNGdW5jdGlvbiggdmFsdWVPckZ1bmN0aW9uICkgP1xuXHRcdFx0XHR2YWx1ZU9yRnVuY3Rpb24oKSA6XG5cdFx0XHRcdHZhbHVlT3JGdW5jdGlvbjtcblxuXHRcdFx0c1sgcy5sZW5ndGggXSA9IGVuY29kZVVSSUNvbXBvbmVudCgga2V5ICkgKyBcIj1cIiArXG5cdFx0XHRcdGVuY29kZVVSSUNvbXBvbmVudCggdmFsdWUgPT0gbnVsbCA/IFwiXCIgOiB2YWx1ZSApO1xuXHRcdH07XG5cblx0Ly8gSWYgYW4gYXJyYXkgd2FzIHBhc3NlZCBpbiwgYXNzdW1lIHRoYXQgaXQgaXMgYW4gYXJyYXkgb2YgZm9ybSBlbGVtZW50cy5cblx0aWYgKCBBcnJheS5pc0FycmF5KCBhICkgfHwgKCBhLmpxdWVyeSAmJiAhalF1ZXJ5LmlzUGxhaW5PYmplY3QoIGEgKSApICkge1xuXG5cdFx0Ly8gU2VyaWFsaXplIHRoZSBmb3JtIGVsZW1lbnRzXG5cdFx0alF1ZXJ5LmVhY2goIGEsIGZ1bmN0aW9uKCkge1xuXHRcdFx0YWRkKCB0aGlzLm5hbWUsIHRoaXMudmFsdWUgKTtcblx0XHR9ICk7XG5cblx0fSBlbHNlIHtcblxuXHRcdC8vIElmIHRyYWRpdGlvbmFsLCBlbmNvZGUgdGhlIFwib2xkXCIgd2F5ICh0aGUgd2F5IDEuMy4yIG9yIG9sZGVyXG5cdFx0Ly8gZGlkIGl0KSwgb3RoZXJ3aXNlIGVuY29kZSBwYXJhbXMgcmVjdXJzaXZlbHkuXG5cdFx0Zm9yICggcHJlZml4IGluIGEgKSB7XG5cdFx0XHRidWlsZFBhcmFtcyggcHJlZml4LCBhWyBwcmVmaXggXSwgdHJhZGl0aW9uYWwsIGFkZCApO1xuXHRcdH1cblx0fVxuXG5cdC8vIFJldHVybiB0aGUgcmVzdWx0aW5nIHNlcmlhbGl6YXRpb25cblx0cmV0dXJuIHMuam9pbiggXCImXCIgKTtcbn07XG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0c2VyaWFsaXplOiBmdW5jdGlvbigpIHtcblx0XHRyZXR1cm4galF1ZXJ5LnBhcmFtKCB0aGlzLnNlcmlhbGl6ZUFycmF5KCkgKTtcblx0fSxcblx0c2VyaWFsaXplQXJyYXk6IGZ1bmN0aW9uKCkge1xuXHRcdHJldHVybiB0aGlzLm1hcCggZnVuY3Rpb24oKSB7XG5cblx0XHRcdC8vIENhbiBhZGQgcHJvcEhvb2sgZm9yIFwiZWxlbWVudHNcIiB0byBmaWx0ZXIgb3IgYWRkIGZvcm0gZWxlbWVudHNcblx0XHRcdHZhciBlbGVtZW50cyA9IGpRdWVyeS5wcm9wKCB0aGlzLCBcImVsZW1lbnRzXCIgKTtcblx0XHRcdHJldHVybiBlbGVtZW50cyA/IGpRdWVyeS5tYWtlQXJyYXkoIGVsZW1lbnRzICkgOiB0aGlzO1xuXHRcdH0gKVxuXHRcdC5maWx0ZXIoIGZ1bmN0aW9uKCkge1xuXHRcdFx0dmFyIHR5cGUgPSB0aGlzLnR5cGU7XG5cblx0XHRcdC8vIFVzZSAuaXMoIFwiOmRpc2FibGVkXCIgKSBzbyB0aGF0IGZpZWxkc2V0W2Rpc2FibGVkXSB3b3Jrc1xuXHRcdFx0cmV0dXJuIHRoaXMubmFtZSAmJiAhalF1ZXJ5KCB0aGlzICkuaXMoIFwiOmRpc2FibGVkXCIgKSAmJlxuXHRcdFx0XHRyc3VibWl0dGFibGUudGVzdCggdGhpcy5ub2RlTmFtZSApICYmICFyc3VibWl0dGVyVHlwZXMudGVzdCggdHlwZSApICYmXG5cdFx0XHRcdCggdGhpcy5jaGVja2VkIHx8ICFyY2hlY2thYmxlVHlwZS50ZXN0KCB0eXBlICkgKTtcblx0XHR9IClcblx0XHQubWFwKCBmdW5jdGlvbiggaSwgZWxlbSApIHtcblx0XHRcdHZhciB2YWwgPSBqUXVlcnkoIHRoaXMgKS52YWwoKTtcblxuXHRcdFx0aWYgKCB2YWwgPT0gbnVsbCApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggQXJyYXkuaXNBcnJheSggdmFsICkgKSB7XG5cdFx0XHRcdHJldHVybiBqUXVlcnkubWFwKCB2YWwsIGZ1bmN0aW9uKCB2YWwgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIHsgbmFtZTogZWxlbS5uYW1lLCB2YWx1ZTogdmFsLnJlcGxhY2UoIHJDUkxGLCBcIlxcclxcblwiICkgfTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4geyBuYW1lOiBlbGVtLm5hbWUsIHZhbHVlOiB2YWwucmVwbGFjZSggckNSTEYsIFwiXFxyXFxuXCIgKSB9O1xuXHRcdH0gKS5nZXQoKTtcblx0fVxufSApO1xuXG5cbnZhclxuXHRyMjAgPSAvJTIwL2csXG5cdHJoYXNoID0gLyMuKiQvLFxuXHRyYW50aUNhY2hlID0gLyhbPyZdKV89W14mXSovLFxuXHRyaGVhZGVycyA9IC9eKC4qPyk6WyBcXHRdKihbXlxcclxcbl0qKSQvbWcsXG5cblx0Ly8gIzc2NTMsICM4MTI1LCAjODE1MjogbG9jYWwgcHJvdG9jb2wgZGV0ZWN0aW9uXG5cdHJsb2NhbFByb3RvY29sID0gL14oPzphYm91dHxhcHB8YXBwLXN0b3JhZ2V8ListZXh0ZW5zaW9ufGZpbGV8cmVzfHdpZGdldCk6JC8sXG5cdHJub0NvbnRlbnQgPSAvXig/OkdFVHxIRUFEKSQvLFxuXHRycHJvdG9jb2wgPSAvXlxcL1xcLy8sXG5cblx0LyogUHJlZmlsdGVyc1xuXHQgKiAxKSBUaGV5IGFyZSB1c2VmdWwgdG8gaW50cm9kdWNlIGN1c3RvbSBkYXRhVHlwZXMgKHNlZSBhamF4L2pzb25wLmpzIGZvciBhbiBleGFtcGxlKVxuXHQgKiAyKSBUaGVzZSBhcmUgY2FsbGVkOlxuXHQgKiAgICAtIEJFRk9SRSBhc2tpbmcgZm9yIGEgdHJhbnNwb3J0XG5cdCAqICAgIC0gQUZURVIgcGFyYW0gc2VyaWFsaXphdGlvbiAocy5kYXRhIGlzIGEgc3RyaW5nIGlmIHMucHJvY2Vzc0RhdGEgaXMgdHJ1ZSlcblx0ICogMykga2V5IGlzIHRoZSBkYXRhVHlwZVxuXHQgKiA0KSB0aGUgY2F0Y2hhbGwgc3ltYm9sIFwiKlwiIGNhbiBiZSB1c2VkXG5cdCAqIDUpIGV4ZWN1dGlvbiB3aWxsIHN0YXJ0IHdpdGggdHJhbnNwb3J0IGRhdGFUeXBlIGFuZCBUSEVOIGNvbnRpbnVlIGRvd24gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHRwcmVmaWx0ZXJzID0ge30sXG5cblx0LyogVHJhbnNwb3J0cyBiaW5kaW5nc1xuXHQgKiAxKSBrZXkgaXMgdGhlIGRhdGFUeXBlXG5cdCAqIDIpIHRoZSBjYXRjaGFsbCBzeW1ib2wgXCIqXCIgY2FuIGJlIHVzZWRcblx0ICogMykgc2VsZWN0aW9uIHdpbGwgc3RhcnQgd2l0aCB0cmFuc3BvcnQgZGF0YVR5cGUgYW5kIFRIRU4gZ28gdG8gXCIqXCIgaWYgbmVlZGVkXG5cdCAqL1xuXHR0cmFuc3BvcnRzID0ge30sXG5cblx0Ly8gQXZvaWQgY29tbWVudC1wcm9sb2cgY2hhciBzZXF1ZW5jZSAoIzEwMDk4KTsgbXVzdCBhcHBlYXNlIGxpbnQgYW5kIGV2YWRlIGNvbXByZXNzaW9uXG5cdGFsbFR5cGVzID0gXCIqL1wiLmNvbmNhdCggXCIqXCIgKSxcblxuXHQvLyBBbmNob3IgdGFnIGZvciBwYXJzaW5nIHRoZSBkb2N1bWVudCBvcmlnaW5cblx0b3JpZ2luQW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJhXCIgKTtcblx0b3JpZ2luQW5jaG9yLmhyZWYgPSBsb2NhdGlvbi5ocmVmO1xuXG4vLyBCYXNlIFwiY29uc3RydWN0b3JcIiBmb3IgalF1ZXJ5LmFqYXhQcmVmaWx0ZXIgYW5kIGpRdWVyeS5hamF4VHJhbnNwb3J0XG5mdW5jdGlvbiBhZGRUb1ByZWZpbHRlcnNPclRyYW5zcG9ydHMoIHN0cnVjdHVyZSApIHtcblxuXHQvLyBkYXRhVHlwZUV4cHJlc3Npb24gaXMgb3B0aW9uYWwgYW5kIGRlZmF1bHRzIHRvIFwiKlwiXG5cdHJldHVybiBmdW5jdGlvbiggZGF0YVR5cGVFeHByZXNzaW9uLCBmdW5jICkge1xuXG5cdFx0aWYgKCB0eXBlb2YgZGF0YVR5cGVFeHByZXNzaW9uICE9PSBcInN0cmluZ1wiICkge1xuXHRcdFx0ZnVuYyA9IGRhdGFUeXBlRXhwcmVzc2lvbjtcblx0XHRcdGRhdGFUeXBlRXhwcmVzc2lvbiA9IFwiKlwiO1xuXHRcdH1cblxuXHRcdHZhciBkYXRhVHlwZSxcblx0XHRcdGkgPSAwLFxuXHRcdFx0ZGF0YVR5cGVzID0gZGF0YVR5cGVFeHByZXNzaW9uLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbXTtcblxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGZ1bmMgKSApIHtcblxuXHRcdFx0Ly8gRm9yIGVhY2ggZGF0YVR5cGUgaW4gdGhlIGRhdGFUeXBlRXhwcmVzc2lvblxuXHRcdFx0d2hpbGUgKCAoIGRhdGFUeXBlID0gZGF0YVR5cGVzWyBpKysgXSApICkge1xuXG5cdFx0XHRcdC8vIFByZXBlbmQgaWYgcmVxdWVzdGVkXG5cdFx0XHRcdGlmICggZGF0YVR5cGVbIDAgXSA9PT0gXCIrXCIgKSB7XG5cdFx0XHRcdFx0ZGF0YVR5cGUgPSBkYXRhVHlwZS5zbGljZSggMSApIHx8IFwiKlwiO1xuXHRcdFx0XHRcdCggc3RydWN0dXJlWyBkYXRhVHlwZSBdID0gc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdICkudW5zaGlmdCggZnVuYyApO1xuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSBhcHBlbmRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQoIHN0cnVjdHVyZVsgZGF0YVR5cGUgXSA9IHN0cnVjdHVyZVsgZGF0YVR5cGUgXSB8fCBbXSApLnB1c2goIGZ1bmMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcbn1cblxuLy8gQmFzZSBpbnNwZWN0aW9uIGZ1bmN0aW9uIGZvciBwcmVmaWx0ZXJzIGFuZCB0cmFuc3BvcnRzXG5mdW5jdGlvbiBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggc3RydWN0dXJlLCBvcHRpb25zLCBvcmlnaW5hbE9wdGlvbnMsIGpxWEhSICkge1xuXG5cdHZhciBpbnNwZWN0ZWQgPSB7fSxcblx0XHRzZWVraW5nVHJhbnNwb3J0ID0gKCBzdHJ1Y3R1cmUgPT09IHRyYW5zcG9ydHMgKTtcblxuXHRmdW5jdGlvbiBpbnNwZWN0KCBkYXRhVHlwZSApIHtcblx0XHR2YXIgc2VsZWN0ZWQ7XG5cdFx0aW5zcGVjdGVkWyBkYXRhVHlwZSBdID0gdHJ1ZTtcblx0XHRqUXVlcnkuZWFjaCggc3RydWN0dXJlWyBkYXRhVHlwZSBdIHx8IFtdLCBmdW5jdGlvbiggXywgcHJlZmlsdGVyT3JGYWN0b3J5ICkge1xuXHRcdFx0dmFyIGRhdGFUeXBlT3JUcmFuc3BvcnQgPSBwcmVmaWx0ZXJPckZhY3RvcnkoIG9wdGlvbnMsIG9yaWdpbmFsT3B0aW9ucywganFYSFIgKTtcblx0XHRcdGlmICggdHlwZW9mIGRhdGFUeXBlT3JUcmFuc3BvcnQgPT09IFwic3RyaW5nXCIgJiZcblx0XHRcdFx0IXNlZWtpbmdUcmFuc3BvcnQgJiYgIWluc3BlY3RlZFsgZGF0YVR5cGVPclRyYW5zcG9ydCBdICkge1xuXG5cdFx0XHRcdG9wdGlvbnMuZGF0YVR5cGVzLnVuc2hpZnQoIGRhdGFUeXBlT3JUcmFuc3BvcnQgKTtcblx0XHRcdFx0aW5zcGVjdCggZGF0YVR5cGVPclRyYW5zcG9ydCApO1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9IGVsc2UgaWYgKCBzZWVraW5nVHJhbnNwb3J0ICkge1xuXHRcdFx0XHRyZXR1cm4gISggc2VsZWN0ZWQgPSBkYXRhVHlwZU9yVHJhbnNwb3J0ICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHRcdHJldHVybiBzZWxlY3RlZDtcblx0fVxuXG5cdHJldHVybiBpbnNwZWN0KCBvcHRpb25zLmRhdGFUeXBlc1sgMCBdICkgfHwgIWluc3BlY3RlZFsgXCIqXCIgXSAmJiBpbnNwZWN0KCBcIipcIiApO1xufVxuXG4vLyBBIHNwZWNpYWwgZXh0ZW5kIGZvciBhamF4IG9wdGlvbnNcbi8vIHRoYXQgdGFrZXMgXCJmbGF0XCIgb3B0aW9ucyAobm90IHRvIGJlIGRlZXAgZXh0ZW5kZWQpXG4vLyBGaXhlcyAjOTg4N1xuZnVuY3Rpb24gYWpheEV4dGVuZCggdGFyZ2V0LCBzcmMgKSB7XG5cdHZhciBrZXksIGRlZXAsXG5cdFx0ZmxhdE9wdGlvbnMgPSBqUXVlcnkuYWpheFNldHRpbmdzLmZsYXRPcHRpb25zIHx8IHt9O1xuXG5cdGZvciAoIGtleSBpbiBzcmMgKSB7XG5cdFx0aWYgKCBzcmNbIGtleSBdICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHQoIGZsYXRPcHRpb25zWyBrZXkgXSA/IHRhcmdldCA6ICggZGVlcCB8fCAoIGRlZXAgPSB7fSApICkgKVsga2V5IF0gPSBzcmNbIGtleSBdO1xuXHRcdH1cblx0fVxuXHRpZiAoIGRlZXAgKSB7XG5cdFx0alF1ZXJ5LmV4dGVuZCggdHJ1ZSwgdGFyZ2V0LCBkZWVwICk7XG5cdH1cblxuXHRyZXR1cm4gdGFyZ2V0O1xufVxuXG4vKiBIYW5kbGVzIHJlc3BvbnNlcyB0byBhbiBhamF4IHJlcXVlc3Q6XG4gKiAtIGZpbmRzIHRoZSByaWdodCBkYXRhVHlwZSAobWVkaWF0ZXMgYmV0d2VlbiBjb250ZW50LXR5cGUgYW5kIGV4cGVjdGVkIGRhdGFUeXBlKVxuICogLSByZXR1cm5zIHRoZSBjb3JyZXNwb25kaW5nIHJlc3BvbnNlXG4gKi9cbmZ1bmN0aW9uIGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKSB7XG5cblx0dmFyIGN0LCB0eXBlLCBmaW5hbERhdGFUeXBlLCBmaXJzdERhdGFUeXBlLFxuXHRcdGNvbnRlbnRzID0gcy5jb250ZW50cyxcblx0XHRkYXRhVHlwZXMgPSBzLmRhdGFUeXBlcztcblxuXHQvLyBSZW1vdmUgYXV0byBkYXRhVHlwZSBhbmQgZ2V0IGNvbnRlbnQtdHlwZSBpbiB0aGUgcHJvY2Vzc1xuXHR3aGlsZSAoIGRhdGFUeXBlc1sgMCBdID09PSBcIipcIiApIHtcblx0XHRkYXRhVHlwZXMuc2hpZnQoKTtcblx0XHRpZiAoIGN0ID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRjdCA9IHMubWltZVR5cGUgfHwganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoIFwiQ29udGVudC1UeXBlXCIgKTtcblx0XHR9XG5cdH1cblxuXHQvLyBDaGVjayBpZiB3ZSdyZSBkZWFsaW5nIHdpdGggYSBrbm93biBjb250ZW50LXR5cGVcblx0aWYgKCBjdCApIHtcblx0XHRmb3IgKCB0eXBlIGluIGNvbnRlbnRzICkge1xuXHRcdFx0aWYgKCBjb250ZW50c1sgdHlwZSBdICYmIGNvbnRlbnRzWyB0eXBlIF0udGVzdCggY3QgKSApIHtcblx0XHRcdFx0ZGF0YVR5cGVzLnVuc2hpZnQoIHR5cGUgKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblx0Ly8gQ2hlY2sgdG8gc2VlIGlmIHdlIGhhdmUgYSByZXNwb25zZSBmb3IgdGhlIGV4cGVjdGVkIGRhdGFUeXBlXG5cdGlmICggZGF0YVR5cGVzWyAwIF0gaW4gcmVzcG9uc2VzICkge1xuXHRcdGZpbmFsRGF0YVR5cGUgPSBkYXRhVHlwZXNbIDAgXTtcblx0fSBlbHNlIHtcblxuXHRcdC8vIFRyeSBjb252ZXJ0aWJsZSBkYXRhVHlwZXNcblx0XHRmb3IgKCB0eXBlIGluIHJlc3BvbnNlcyApIHtcblx0XHRcdGlmICggIWRhdGFUeXBlc1sgMCBdIHx8IHMuY29udmVydGVyc1sgdHlwZSArIFwiIFwiICsgZGF0YVR5cGVzWyAwIF0gXSApIHtcblx0XHRcdFx0ZmluYWxEYXRhVHlwZSA9IHR5cGU7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCAhZmlyc3REYXRhVHlwZSApIHtcblx0XHRcdFx0Zmlyc3REYXRhVHlwZSA9IHR5cGU7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gT3IganVzdCB1c2UgZmlyc3Qgb25lXG5cdFx0ZmluYWxEYXRhVHlwZSA9IGZpbmFsRGF0YVR5cGUgfHwgZmlyc3REYXRhVHlwZTtcblx0fVxuXG5cdC8vIElmIHdlIGZvdW5kIGEgZGF0YVR5cGVcblx0Ly8gV2UgYWRkIHRoZSBkYXRhVHlwZSB0byB0aGUgbGlzdCBpZiBuZWVkZWRcblx0Ly8gYW5kIHJldHVybiB0aGUgY29ycmVzcG9uZGluZyByZXNwb25zZVxuXHRpZiAoIGZpbmFsRGF0YVR5cGUgKSB7XG5cdFx0aWYgKCBmaW5hbERhdGFUeXBlICE9PSBkYXRhVHlwZXNbIDAgXSApIHtcblx0XHRcdGRhdGFUeXBlcy51bnNoaWZ0KCBmaW5hbERhdGFUeXBlICk7XG5cdFx0fVxuXHRcdHJldHVybiByZXNwb25zZXNbIGZpbmFsRGF0YVR5cGUgXTtcblx0fVxufVxuXG4vKiBDaGFpbiBjb252ZXJzaW9ucyBnaXZlbiB0aGUgcmVxdWVzdCBhbmQgdGhlIG9yaWdpbmFsIHJlc3BvbnNlXG4gKiBBbHNvIHNldHMgdGhlIHJlc3BvbnNlWFhYIGZpZWxkcyBvbiB0aGUganFYSFIgaW5zdGFuY2VcbiAqL1xuZnVuY3Rpb24gYWpheENvbnZlcnQoIHMsIHJlc3BvbnNlLCBqcVhIUiwgaXNTdWNjZXNzICkge1xuXHR2YXIgY29udjIsIGN1cnJlbnQsIGNvbnYsIHRtcCwgcHJldixcblx0XHRjb252ZXJ0ZXJzID0ge30sXG5cblx0XHQvLyBXb3JrIHdpdGggYSBjb3B5IG9mIGRhdGFUeXBlcyBpbiBjYXNlIHdlIG5lZWQgdG8gbW9kaWZ5IGl0IGZvciBjb252ZXJzaW9uXG5cdFx0ZGF0YVR5cGVzID0gcy5kYXRhVHlwZXMuc2xpY2UoKTtcblxuXHQvLyBDcmVhdGUgY29udmVydGVycyBtYXAgd2l0aCBsb3dlcmNhc2VkIGtleXNcblx0aWYgKCBkYXRhVHlwZXNbIDEgXSApIHtcblx0XHRmb3IgKCBjb252IGluIHMuY29udmVydGVycyApIHtcblx0XHRcdGNvbnZlcnRlcnNbIGNvbnYudG9Mb3dlckNhc2UoKSBdID0gcy5jb252ZXJ0ZXJzWyBjb252IF07XG5cdFx0fVxuXHR9XG5cblx0Y3VycmVudCA9IGRhdGFUeXBlcy5zaGlmdCgpO1xuXG5cdC8vIENvbnZlcnQgdG8gZWFjaCBzZXF1ZW50aWFsIGRhdGFUeXBlXG5cdHdoaWxlICggY3VycmVudCApIHtcblxuXHRcdGlmICggcy5yZXNwb25zZUZpZWxkc1sgY3VycmVudCBdICkge1xuXHRcdFx0anFYSFJbIHMucmVzcG9uc2VGaWVsZHNbIGN1cnJlbnQgXSBdID0gcmVzcG9uc2U7XG5cdFx0fVxuXG5cdFx0Ly8gQXBwbHkgdGhlIGRhdGFGaWx0ZXIgaWYgcHJvdmlkZWRcblx0XHRpZiAoICFwcmV2ICYmIGlzU3VjY2VzcyAmJiBzLmRhdGFGaWx0ZXIgKSB7XG5cdFx0XHRyZXNwb25zZSA9IHMuZGF0YUZpbHRlciggcmVzcG9uc2UsIHMuZGF0YVR5cGUgKTtcblx0XHR9XG5cblx0XHRwcmV2ID0gY3VycmVudDtcblx0XHRjdXJyZW50ID0gZGF0YVR5cGVzLnNoaWZ0KCk7XG5cblx0XHRpZiAoIGN1cnJlbnQgKSB7XG5cblx0XHRcdC8vIFRoZXJlJ3Mgb25seSB3b3JrIHRvIGRvIGlmIGN1cnJlbnQgZGF0YVR5cGUgaXMgbm9uLWF1dG9cblx0XHRcdGlmICggY3VycmVudCA9PT0gXCIqXCIgKSB7XG5cblx0XHRcdFx0Y3VycmVudCA9IHByZXY7XG5cblx0XHRcdC8vIENvbnZlcnQgcmVzcG9uc2UgaWYgcHJldiBkYXRhVHlwZSBpcyBub24tYXV0byBhbmQgZGlmZmVycyBmcm9tIGN1cnJlbnRcblx0XHRcdH0gZWxzZSBpZiAoIHByZXYgIT09IFwiKlwiICYmIHByZXYgIT09IGN1cnJlbnQgKSB7XG5cblx0XHRcdFx0Ly8gU2VlayBhIGRpcmVjdCBjb252ZXJ0ZXJcblx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIHByZXYgKyBcIiBcIiArIGN1cnJlbnQgXSB8fCBjb252ZXJ0ZXJzWyBcIiogXCIgKyBjdXJyZW50IF07XG5cblx0XHRcdFx0Ly8gSWYgbm9uZSBmb3VuZCwgc2VlayBhIHBhaXJcblx0XHRcdFx0aWYgKCAhY29udiApIHtcblx0XHRcdFx0XHRmb3IgKCBjb252MiBpbiBjb252ZXJ0ZXJzICkge1xuXG5cdFx0XHRcdFx0XHQvLyBJZiBjb252MiBvdXRwdXRzIGN1cnJlbnRcblx0XHRcdFx0XHRcdHRtcCA9IGNvbnYyLnNwbGl0KCBcIiBcIiApO1xuXHRcdFx0XHRcdFx0aWYgKCB0bXBbIDEgXSA9PT0gY3VycmVudCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBJZiBwcmV2IGNhbiBiZSBjb252ZXJ0ZWQgdG8gYWNjZXB0ZWQgaW5wdXRcblx0XHRcdFx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIHByZXYgKyBcIiBcIiArIHRtcFsgMCBdIF0gfHxcblx0XHRcdFx0XHRcdFx0XHRjb252ZXJ0ZXJzWyBcIiogXCIgKyB0bXBbIDAgXSBdO1xuXHRcdFx0XHRcdFx0XHRpZiAoIGNvbnYgKSB7XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBDb25kZW5zZSBlcXVpdmFsZW5jZSBjb252ZXJ0ZXJzXG5cdFx0XHRcdFx0XHRcdFx0aWYgKCBjb252ID09PSB0cnVlICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0Y29udiA9IGNvbnZlcnRlcnNbIGNvbnYyIF07XG5cblx0XHRcdFx0XHRcdFx0XHQvLyBPdGhlcndpc2UsIGluc2VydCB0aGUgaW50ZXJtZWRpYXRlIGRhdGFUeXBlXG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIGlmICggY29udmVydGVyc1sgY29udjIgXSAhPT0gdHJ1ZSApIHtcblx0XHRcdFx0XHRcdFx0XHRcdGN1cnJlbnQgPSB0bXBbIDAgXTtcblx0XHRcdFx0XHRcdFx0XHRcdGRhdGFUeXBlcy51bnNoaWZ0KCB0bXBbIDEgXSApO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFwcGx5IGNvbnZlcnRlciAoaWYgbm90IGFuIGVxdWl2YWxlbmNlKVxuXHRcdFx0XHRpZiAoIGNvbnYgIT09IHRydWUgKSB7XG5cblx0XHRcdFx0XHQvLyBVbmxlc3MgZXJyb3JzIGFyZSBhbGxvd2VkIHRvIGJ1YmJsZSwgY2F0Y2ggYW5kIHJldHVybiB0aGVtXG5cdFx0XHRcdFx0aWYgKCBjb252ICYmIHMudGhyb3dzICkge1xuXHRcdFx0XHRcdFx0cmVzcG9uc2UgPSBjb252KCByZXNwb25zZSApO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRyZXNwb25zZSA9IGNvbnYoIHJlc3BvbnNlICk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoICggZSApIHtcblx0XHRcdFx0XHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0XHRcdFx0XHRzdGF0ZTogXCJwYXJzZXJlcnJvclwiLFxuXHRcdFx0XHRcdFx0XHRcdGVycm9yOiBjb252ID8gZSA6IFwiTm8gY29udmVyc2lvbiBmcm9tIFwiICsgcHJldiArIFwiIHRvIFwiICsgY3VycmVudFxuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXG5cdHJldHVybiB7IHN0YXRlOiBcInN1Y2Nlc3NcIiwgZGF0YTogcmVzcG9uc2UgfTtcbn1cblxualF1ZXJ5LmV4dGVuZCgge1xuXG5cdC8vIENvdW50ZXIgZm9yIGhvbGRpbmcgdGhlIG51bWJlciBvZiBhY3RpdmUgcXVlcmllc1xuXHRhY3RpdmU6IDAsXG5cblx0Ly8gTGFzdC1Nb2RpZmllZCBoZWFkZXIgY2FjaGUgZm9yIG5leHQgcmVxdWVzdFxuXHRsYXN0TW9kaWZpZWQ6IHt9LFxuXHRldGFnOiB7fSxcblxuXHRhamF4U2V0dGluZ3M6IHtcblx0XHR1cmw6IGxvY2F0aW9uLmhyZWYsXG5cdFx0dHlwZTogXCJHRVRcIixcblx0XHRpc0xvY2FsOiBybG9jYWxQcm90b2NvbC50ZXN0KCBsb2NhdGlvbi5wcm90b2NvbCApLFxuXHRcdGdsb2JhbDogdHJ1ZSxcblx0XHRwcm9jZXNzRGF0YTogdHJ1ZSxcblx0XHRhc3luYzogdHJ1ZSxcblx0XHRjb250ZW50VHlwZTogXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQ7IGNoYXJzZXQ9VVRGLThcIixcblxuXHRcdC8qXG5cdFx0dGltZW91dDogMCxcblx0XHRkYXRhOiBudWxsLFxuXHRcdGRhdGFUeXBlOiBudWxsLFxuXHRcdHVzZXJuYW1lOiBudWxsLFxuXHRcdHBhc3N3b3JkOiBudWxsLFxuXHRcdGNhY2hlOiBudWxsLFxuXHRcdHRocm93czogZmFsc2UsXG5cdFx0dHJhZGl0aW9uYWw6IGZhbHNlLFxuXHRcdGhlYWRlcnM6IHt9LFxuXHRcdCovXG5cblx0XHRhY2NlcHRzOiB7XG5cdFx0XHRcIipcIjogYWxsVHlwZXMsXG5cdFx0XHR0ZXh0OiBcInRleHQvcGxhaW5cIixcblx0XHRcdGh0bWw6IFwidGV4dC9odG1sXCIsXG5cdFx0XHR4bWw6IFwiYXBwbGljYXRpb24veG1sLCB0ZXh0L3htbFwiLFxuXHRcdFx0anNvbjogXCJhcHBsaWNhdGlvbi9qc29uLCB0ZXh0L2phdmFzY3JpcHRcIlxuXHRcdH0sXG5cblx0XHRjb250ZW50czoge1xuXHRcdFx0eG1sOiAvXFxieG1sXFxiLyxcblx0XHRcdGh0bWw6IC9cXGJodG1sLyxcblx0XHRcdGpzb246IC9cXGJqc29uXFxiL1xuXHRcdH0sXG5cblx0XHRyZXNwb25zZUZpZWxkczoge1xuXHRcdFx0eG1sOiBcInJlc3BvbnNlWE1MXCIsXG5cdFx0XHR0ZXh0OiBcInJlc3BvbnNlVGV4dFwiLFxuXHRcdFx0anNvbjogXCJyZXNwb25zZUpTT05cIlxuXHRcdH0sXG5cblx0XHQvLyBEYXRhIGNvbnZlcnRlcnNcblx0XHQvLyBLZXlzIHNlcGFyYXRlIHNvdXJjZSAob3IgY2F0Y2hhbGwgXCIqXCIpIGFuZCBkZXN0aW5hdGlvbiB0eXBlcyB3aXRoIGEgc2luZ2xlIHNwYWNlXG5cdFx0Y29udmVydGVyczoge1xuXG5cdFx0XHQvLyBDb252ZXJ0IGFueXRoaW5nIHRvIHRleHRcblx0XHRcdFwiKiB0ZXh0XCI6IFN0cmluZyxcblxuXHRcdFx0Ly8gVGV4dCB0byBodG1sICh0cnVlID0gbm8gdHJhbnNmb3JtYXRpb24pXG5cdFx0XHRcInRleHQgaHRtbFwiOiB0cnVlLFxuXG5cdFx0XHQvLyBFdmFsdWF0ZSB0ZXh0IGFzIGEganNvbiBleHByZXNzaW9uXG5cdFx0XHRcInRleHQganNvblwiOiBKU09OLnBhcnNlLFxuXG5cdFx0XHQvLyBQYXJzZSB0ZXh0IGFzIHhtbFxuXHRcdFx0XCJ0ZXh0IHhtbFwiOiBqUXVlcnkucGFyc2VYTUxcblx0XHR9LFxuXG5cdFx0Ly8gRm9yIG9wdGlvbnMgdGhhdCBzaG91bGRuJ3QgYmUgZGVlcCBleHRlbmRlZDpcblx0XHQvLyB5b3UgY2FuIGFkZCB5b3VyIG93biBjdXN0b20gb3B0aW9ucyBoZXJlIGlmXG5cdFx0Ly8gYW5kIHdoZW4geW91IGNyZWF0ZSBvbmUgdGhhdCBzaG91bGRuJ3QgYmVcblx0XHQvLyBkZWVwIGV4dGVuZGVkIChzZWUgYWpheEV4dGVuZClcblx0XHRmbGF0T3B0aW9uczoge1xuXHRcdFx0dXJsOiB0cnVlLFxuXHRcdFx0Y29udGV4dDogdHJ1ZVxuXHRcdH1cblx0fSxcblxuXHQvLyBDcmVhdGVzIGEgZnVsbCBmbGVkZ2VkIHNldHRpbmdzIG9iamVjdCBpbnRvIHRhcmdldFxuXHQvLyB3aXRoIGJvdGggYWpheFNldHRpbmdzIGFuZCBzZXR0aW5ncyBmaWVsZHMuXG5cdC8vIElmIHRhcmdldCBpcyBvbWl0dGVkLCB3cml0ZXMgaW50byBhamF4U2V0dGluZ3MuXG5cdGFqYXhTZXR1cDogZnVuY3Rpb24oIHRhcmdldCwgc2V0dGluZ3MgKSB7XG5cdFx0cmV0dXJuIHNldHRpbmdzID9cblxuXHRcdFx0Ly8gQnVpbGRpbmcgYSBzZXR0aW5ncyBvYmplY3Rcblx0XHRcdGFqYXhFeHRlbmQoIGFqYXhFeHRlbmQoIHRhcmdldCwgalF1ZXJ5LmFqYXhTZXR0aW5ncyApLCBzZXR0aW5ncyApIDpcblxuXHRcdFx0Ly8gRXh0ZW5kaW5nIGFqYXhTZXR0aW5nc1xuXHRcdFx0YWpheEV4dGVuZCggalF1ZXJ5LmFqYXhTZXR0aW5ncywgdGFyZ2V0ICk7XG5cdH0sXG5cblx0YWpheFByZWZpbHRlcjogYWRkVG9QcmVmaWx0ZXJzT3JUcmFuc3BvcnRzKCBwcmVmaWx0ZXJzICksXG5cdGFqYXhUcmFuc3BvcnQ6IGFkZFRvUHJlZmlsdGVyc09yVHJhbnNwb3J0cyggdHJhbnNwb3J0cyApLFxuXG5cdC8vIE1haW4gbWV0aG9kXG5cdGFqYXg6IGZ1bmN0aW9uKCB1cmwsIG9wdGlvbnMgKSB7XG5cblx0XHQvLyBJZiB1cmwgaXMgYW4gb2JqZWN0LCBzaW11bGF0ZSBwcmUtMS41IHNpZ25hdHVyZVxuXHRcdGlmICggdHlwZW9mIHVybCA9PT0gXCJvYmplY3RcIiApIHtcblx0XHRcdG9wdGlvbnMgPSB1cmw7XG5cdFx0XHR1cmwgPSB1bmRlZmluZWQ7XG5cdFx0fVxuXG5cdFx0Ly8gRm9yY2Ugb3B0aW9ucyB0byBiZSBhbiBvYmplY3Rcblx0XHRvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuXHRcdHZhciB0cmFuc3BvcnQsXG5cblx0XHRcdC8vIFVSTCB3aXRob3V0IGFudGktY2FjaGUgcGFyYW1cblx0XHRcdGNhY2hlVVJMLFxuXG5cdFx0XHQvLyBSZXNwb25zZSBoZWFkZXJzXG5cdFx0XHRyZXNwb25zZUhlYWRlcnNTdHJpbmcsXG5cdFx0XHRyZXNwb25zZUhlYWRlcnMsXG5cblx0XHRcdC8vIHRpbWVvdXQgaGFuZGxlXG5cdFx0XHR0aW1lb3V0VGltZXIsXG5cblx0XHRcdC8vIFVybCBjbGVhbnVwIHZhclxuXHRcdFx0dXJsQW5jaG9yLFxuXG5cdFx0XHQvLyBSZXF1ZXN0IHN0YXRlIChiZWNvbWVzIGZhbHNlIHVwb24gc2VuZCBhbmQgdHJ1ZSB1cG9uIGNvbXBsZXRpb24pXG5cdFx0XHRjb21wbGV0ZWQsXG5cblx0XHRcdC8vIFRvIGtub3cgaWYgZ2xvYmFsIGV2ZW50cyBhcmUgdG8gYmUgZGlzcGF0Y2hlZFxuXHRcdFx0ZmlyZUdsb2JhbHMsXG5cblx0XHRcdC8vIExvb3AgdmFyaWFibGVcblx0XHRcdGksXG5cblx0XHRcdC8vIHVuY2FjaGVkIHBhcnQgb2YgdGhlIHVybFxuXHRcdFx0dW5jYWNoZWQsXG5cblx0XHRcdC8vIENyZWF0ZSB0aGUgZmluYWwgb3B0aW9ucyBvYmplY3Rcblx0XHRcdHMgPSBqUXVlcnkuYWpheFNldHVwKCB7fSwgb3B0aW9ucyApLFxuXG5cdFx0XHQvLyBDYWxsYmFja3MgY29udGV4dFxuXHRcdFx0Y2FsbGJhY2tDb250ZXh0ID0gcy5jb250ZXh0IHx8IHMsXG5cblx0XHRcdC8vIENvbnRleHQgZm9yIGdsb2JhbCBldmVudHMgaXMgY2FsbGJhY2tDb250ZXh0IGlmIGl0IGlzIGEgRE9NIG5vZGUgb3IgalF1ZXJ5IGNvbGxlY3Rpb25cblx0XHRcdGdsb2JhbEV2ZW50Q29udGV4dCA9IHMuY29udGV4dCAmJlxuXHRcdFx0XHQoIGNhbGxiYWNrQ29udGV4dC5ub2RlVHlwZSB8fCBjYWxsYmFja0NvbnRleHQuanF1ZXJ5ICkgP1xuXHRcdFx0XHRcdGpRdWVyeSggY2FsbGJhY2tDb250ZXh0ICkgOlxuXHRcdFx0XHRcdGpRdWVyeS5ldmVudCxcblxuXHRcdFx0Ly8gRGVmZXJyZWRzXG5cdFx0XHRkZWZlcnJlZCA9IGpRdWVyeS5EZWZlcnJlZCgpLFxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZCA9IGpRdWVyeS5DYWxsYmFja3MoIFwib25jZSBtZW1vcnlcIiApLFxuXG5cdFx0XHQvLyBTdGF0dXMtZGVwZW5kZW50IGNhbGxiYWNrc1xuXHRcdFx0c3RhdHVzQ29kZSA9IHMuc3RhdHVzQ29kZSB8fCB7fSxcblxuXHRcdFx0Ly8gSGVhZGVycyAodGhleSBhcmUgc2VudCBhbGwgYXQgb25jZSlcblx0XHRcdHJlcXVlc3RIZWFkZXJzID0ge30sXG5cdFx0XHRyZXF1ZXN0SGVhZGVyc05hbWVzID0ge30sXG5cblx0XHRcdC8vIERlZmF1bHQgYWJvcnQgbWVzc2FnZVxuXHRcdFx0c3RyQWJvcnQgPSBcImNhbmNlbGVkXCIsXG5cblx0XHRcdC8vIEZha2UgeGhyXG5cdFx0XHRqcVhIUiA9IHtcblx0XHRcdFx0cmVhZHlTdGF0ZTogMCxcblxuXHRcdFx0XHQvLyBCdWlsZHMgaGVhZGVycyBoYXNodGFibGUgaWYgbmVlZGVkXG5cdFx0XHRcdGdldFJlc3BvbnNlSGVhZGVyOiBmdW5jdGlvbigga2V5ICkge1xuXHRcdFx0XHRcdHZhciBtYXRjaDtcblx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0XHRcdGlmICggIXJlc3BvbnNlSGVhZGVycyApIHtcblx0XHRcdFx0XHRcdFx0cmVzcG9uc2VIZWFkZXJzID0ge307XG5cdFx0XHRcdFx0XHRcdHdoaWxlICggKCBtYXRjaCA9IHJoZWFkZXJzLmV4ZWMoIHJlc3BvbnNlSGVhZGVyc1N0cmluZyApICkgKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmVzcG9uc2VIZWFkZXJzWyBtYXRjaFsgMSBdLnRvTG93ZXJDYXNlKCkgXSA9IG1hdGNoWyAyIF07XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdG1hdGNoID0gcmVzcG9uc2VIZWFkZXJzWyBrZXkudG9Mb3dlckNhc2UoKSBdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gbWF0Y2ggPT0gbnVsbCA/IG51bGwgOiBtYXRjaDtcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBSYXcgc3RyaW5nXG5cdFx0XHRcdGdldEFsbFJlc3BvbnNlSGVhZGVyczogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGNvbXBsZXRlZCA/IHJlc3BvbnNlSGVhZGVyc1N0cmluZyA6IG51bGw7XG5cdFx0XHRcdH0sXG5cblx0XHRcdFx0Ly8gQ2FjaGVzIHRoZSBoZWFkZXJcblx0XHRcdFx0c2V0UmVxdWVzdEhlYWRlcjogZnVuY3Rpb24oIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0XHRcdGlmICggY29tcGxldGVkID09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRuYW1lID0gcmVxdWVzdEhlYWRlcnNOYW1lc1sgbmFtZS50b0xvd2VyQ2FzZSgpIF0gPVxuXHRcdFx0XHRcdFx0XHRyZXF1ZXN0SGVhZGVyc05hbWVzWyBuYW1lLnRvTG93ZXJDYXNlKCkgXSB8fCBuYW1lO1xuXHRcdFx0XHRcdFx0cmVxdWVzdEhlYWRlcnNbIG5hbWUgXSA9IHZhbHVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fSxcblxuXHRcdFx0XHQvLyBPdmVycmlkZXMgcmVzcG9uc2UgY29udGVudC10eXBlIGhlYWRlclxuXHRcdFx0XHRvdmVycmlkZU1pbWVUeXBlOiBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCA9PSBudWxsICkge1xuXHRcdFx0XHRcdFx0cy5taW1lVHlwZSA9IHR5cGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRcdHN0YXR1c0NvZGU6IGZ1bmN0aW9uKCBtYXAgKSB7XG5cdFx0XHRcdFx0dmFyIGNvZGU7XG5cdFx0XHRcdFx0aWYgKCBtYXAgKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblxuXHRcdFx0XHRcdFx0XHQvLyBFeGVjdXRlIHRoZSBhcHByb3ByaWF0ZSBjYWxsYmFja3Ncblx0XHRcdFx0XHRcdFx0anFYSFIuYWx3YXlzKCBtYXBbIGpxWEhSLnN0YXR1cyBdICk7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXG5cdFx0XHRcdFx0XHRcdC8vIExhenktYWRkIHRoZSBuZXcgY2FsbGJhY2tzIGluIGEgd2F5IHRoYXQgcHJlc2VydmVzIG9sZCBvbmVzXG5cdFx0XHRcdFx0XHRcdGZvciAoIGNvZGUgaW4gbWFwICkge1xuXHRcdFx0XHRcdFx0XHRcdHN0YXR1c0NvZGVbIGNvZGUgXSA9IFsgc3RhdHVzQ29kZVsgY29kZSBdLCBtYXBbIGNvZGUgXSBdO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0XHR9LFxuXG5cdFx0XHRcdC8vIENhbmNlbCB0aGUgcmVxdWVzdFxuXHRcdFx0XHRhYm9ydDogZnVuY3Rpb24oIHN0YXR1c1RleHQgKSB7XG5cdFx0XHRcdFx0dmFyIGZpbmFsVGV4dCA9IHN0YXR1c1RleHQgfHwgc3RyQWJvcnQ7XG5cdFx0XHRcdFx0aWYgKCB0cmFuc3BvcnQgKSB7XG5cdFx0XHRcdFx0XHR0cmFuc3BvcnQuYWJvcnQoIGZpbmFsVGV4dCApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRkb25lKCAwLCBmaW5hbFRleHQgKTtcblx0XHRcdFx0XHRyZXR1cm4gdGhpcztcblx0XHRcdFx0fVxuXHRcdFx0fTtcblxuXHRcdC8vIEF0dGFjaCBkZWZlcnJlZHNcblx0XHRkZWZlcnJlZC5wcm9taXNlKCBqcVhIUiApO1xuXG5cdFx0Ly8gQWRkIHByb3RvY29sIGlmIG5vdCBwcm92aWRlZCAocHJlZmlsdGVycyBtaWdodCBleHBlY3QgaXQpXG5cdFx0Ly8gSGFuZGxlIGZhbHN5IHVybCBpbiB0aGUgc2V0dGluZ3Mgb2JqZWN0ICgjMTAwOTM6IGNvbnNpc3RlbmN5IHdpdGggb2xkIHNpZ25hdHVyZSlcblx0XHQvLyBXZSBhbHNvIHVzZSB0aGUgdXJsIHBhcmFtZXRlciBpZiBhdmFpbGFibGVcblx0XHRzLnVybCA9ICggKCB1cmwgfHwgcy51cmwgfHwgbG9jYXRpb24uaHJlZiApICsgXCJcIiApXG5cdFx0XHQucmVwbGFjZSggcnByb3RvY29sLCBsb2NhdGlvbi5wcm90b2NvbCArIFwiLy9cIiApO1xuXG5cdFx0Ly8gQWxpYXMgbWV0aG9kIG9wdGlvbiB0byB0eXBlIGFzIHBlciB0aWNrZXQgIzEyMDA0XG5cdFx0cy50eXBlID0gb3B0aW9ucy5tZXRob2QgfHwgb3B0aW9ucy50eXBlIHx8IHMubWV0aG9kIHx8IHMudHlwZTtcblxuXHRcdC8vIEV4dHJhY3QgZGF0YVR5cGVzIGxpc3Rcblx0XHRzLmRhdGFUeXBlcyA9ICggcy5kYXRhVHlwZSB8fCBcIipcIiApLnRvTG93ZXJDYXNlKCkubWF0Y2goIHJub3RodG1sd2hpdGUgKSB8fCBbIFwiXCIgXTtcblxuXHRcdC8vIEEgY3Jvc3MtZG9tYWluIHJlcXVlc3QgaXMgaW4gb3JkZXIgd2hlbiB0aGUgb3JpZ2luIGRvZXNuJ3QgbWF0Y2ggdGhlIGN1cnJlbnQgb3JpZ2luLlxuXHRcdGlmICggcy5jcm9zc0RvbWFpbiA9PSBudWxsICkge1xuXHRcdFx0dXJsQW5jaG9yID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCggXCJhXCIgKTtcblxuXHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04IC0gMTEsIEVkZ2UgMTIgLSAxM1xuXHRcdFx0Ly8gSUUgdGhyb3dzIGV4Y2VwdGlvbiBvbiBhY2Nlc3NpbmcgdGhlIGhyZWYgcHJvcGVydHkgaWYgdXJsIGlzIG1hbGZvcm1lZCxcblx0XHRcdC8vIGUuZy4gaHR0cDovL2V4YW1wbGUuY29tOjgweC9cblx0XHRcdHRyeSB7XG5cdFx0XHRcdHVybEFuY2hvci5ocmVmID0gcy51cmw7XG5cblx0XHRcdFx0Ly8gU3VwcG9ydDogSUUgPD04IC0gMTEgb25seVxuXHRcdFx0XHQvLyBBbmNob3IncyBob3N0IHByb3BlcnR5IGlzbid0IGNvcnJlY3RseSBzZXQgd2hlbiBzLnVybCBpcyByZWxhdGl2ZVxuXHRcdFx0XHR1cmxBbmNob3IuaHJlZiA9IHVybEFuY2hvci5ocmVmO1xuXHRcdFx0XHRzLmNyb3NzRG9tYWluID0gb3JpZ2luQW5jaG9yLnByb3RvY29sICsgXCIvL1wiICsgb3JpZ2luQW5jaG9yLmhvc3QgIT09XG5cdFx0XHRcdFx0dXJsQW5jaG9yLnByb3RvY29sICsgXCIvL1wiICsgdXJsQW5jaG9yLmhvc3Q7XG5cdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHQvLyBJZiB0aGVyZSBpcyBhbiBlcnJvciBwYXJzaW5nIHRoZSBVUkwsIGFzc3VtZSBpdCBpcyBjcm9zc0RvbWFpbixcblx0XHRcdFx0Ly8gaXQgY2FuIGJlIHJlamVjdGVkIGJ5IHRoZSB0cmFuc3BvcnQgaWYgaXQgaXMgaW52YWxpZFxuXHRcdFx0XHRzLmNyb3NzRG9tYWluID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHQvLyBDb252ZXJ0IGRhdGEgaWYgbm90IGFscmVhZHkgYSBzdHJpbmdcblx0XHRpZiAoIHMuZGF0YSAmJiBzLnByb2Nlc3NEYXRhICYmIHR5cGVvZiBzLmRhdGEgIT09IFwic3RyaW5nXCIgKSB7XG5cdFx0XHRzLmRhdGEgPSBqUXVlcnkucGFyYW0oIHMuZGF0YSwgcy50cmFkaXRpb25hbCApO1xuXHRcdH1cblxuXHRcdC8vIEFwcGx5IHByZWZpbHRlcnNcblx0XHRpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggcHJlZmlsdGVycywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGEgcHJlZmlsdGVyLCBzdG9wIHRoZXJlXG5cdFx0aWYgKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRyZXR1cm4ganFYSFI7XG5cdFx0fVxuXG5cdFx0Ly8gV2UgY2FuIGZpcmUgZ2xvYmFsIGV2ZW50cyBhcyBvZiBub3cgaWYgYXNrZWQgdG9cblx0XHQvLyBEb24ndCBmaXJlIGV2ZW50cyBpZiBqUXVlcnkuZXZlbnQgaXMgdW5kZWZpbmVkIGluIGFuIEFNRC11c2FnZSBzY2VuYXJpbyAoIzE1MTE4KVxuXHRcdGZpcmVHbG9iYWxzID0galF1ZXJ5LmV2ZW50ICYmIHMuZ2xvYmFsO1xuXG5cdFx0Ly8gV2F0Y2ggZm9yIGEgbmV3IHNldCBvZiByZXF1ZXN0c1xuXHRcdGlmICggZmlyZUdsb2JhbHMgJiYgalF1ZXJ5LmFjdGl2ZSsrID09PSAwICkge1xuXHRcdFx0alF1ZXJ5LmV2ZW50LnRyaWdnZXIoIFwiYWpheFN0YXJ0XCIgKTtcblx0XHR9XG5cblx0XHQvLyBVcHBlcmNhc2UgdGhlIHR5cGVcblx0XHRzLnR5cGUgPSBzLnR5cGUudG9VcHBlckNhc2UoKTtcblxuXHRcdC8vIERldGVybWluZSBpZiByZXF1ZXN0IGhhcyBjb250ZW50XG5cdFx0cy5oYXNDb250ZW50ID0gIXJub0NvbnRlbnQudGVzdCggcy50eXBlICk7XG5cblx0XHQvLyBTYXZlIHRoZSBVUkwgaW4gY2FzZSB3ZSdyZSB0b3lpbmcgd2l0aCB0aGUgSWYtTW9kaWZpZWQtU2luY2Vcblx0XHQvLyBhbmQvb3IgSWYtTm9uZS1NYXRjaCBoZWFkZXIgbGF0ZXIgb25cblx0XHQvLyBSZW1vdmUgaGFzaCB0byBzaW1wbGlmeSB1cmwgbWFuaXB1bGF0aW9uXG5cdFx0Y2FjaGVVUkwgPSBzLnVybC5yZXBsYWNlKCByaGFzaCwgXCJcIiApO1xuXG5cdFx0Ly8gTW9yZSBvcHRpb25zIGhhbmRsaW5nIGZvciByZXF1ZXN0cyB3aXRoIG5vIGNvbnRlbnRcblx0XHRpZiAoICFzLmhhc0NvbnRlbnQgKSB7XG5cblx0XHRcdC8vIFJlbWVtYmVyIHRoZSBoYXNoIHNvIHdlIGNhbiBwdXQgaXQgYmFja1xuXHRcdFx0dW5jYWNoZWQgPSBzLnVybC5zbGljZSggY2FjaGVVUkwubGVuZ3RoICk7XG5cblx0XHRcdC8vIElmIGRhdGEgaXMgYXZhaWxhYmxlLCBhcHBlbmQgZGF0YSB0byB1cmxcblx0XHRcdGlmICggcy5kYXRhICkge1xuXHRcdFx0XHRjYWNoZVVSTCArPSAoIHJxdWVyeS50ZXN0KCBjYWNoZVVSTCApID8gXCImXCIgOiBcIj9cIiApICsgcy5kYXRhO1xuXG5cdFx0XHRcdC8vICM5NjgyOiByZW1vdmUgZGF0YSBzbyB0aGF0IGl0J3Mgbm90IHVzZWQgaW4gYW4gZXZlbnR1YWwgcmV0cnlcblx0XHRcdFx0ZGVsZXRlIHMuZGF0YTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQWRkIG9yIHVwZGF0ZSBhbnRpLWNhY2hlIHBhcmFtIGlmIG5lZWRlZFxuXHRcdFx0aWYgKCBzLmNhY2hlID09PSBmYWxzZSApIHtcblx0XHRcdFx0Y2FjaGVVUkwgPSBjYWNoZVVSTC5yZXBsYWNlKCByYW50aUNhY2hlLCBcIiQxXCIgKTtcblx0XHRcdFx0dW5jYWNoZWQgPSAoIHJxdWVyeS50ZXN0KCBjYWNoZVVSTCApID8gXCImXCIgOiBcIj9cIiApICsgXCJfPVwiICsgKCBub25jZSsrICkgKyB1bmNhY2hlZDtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUHV0IGhhc2ggYW5kIGFudGktY2FjaGUgb24gdGhlIFVSTCB0aGF0IHdpbGwgYmUgcmVxdWVzdGVkIChnaC0xNzMyKVxuXHRcdFx0cy51cmwgPSBjYWNoZVVSTCArIHVuY2FjaGVkO1xuXG5cdFx0Ly8gQ2hhbmdlICclMjAnIHRvICcrJyBpZiB0aGlzIGlzIGVuY29kZWQgZm9ybSBib2R5IGNvbnRlbnQgKGdoLTI2NTgpXG5cdFx0fSBlbHNlIGlmICggcy5kYXRhICYmIHMucHJvY2Vzc0RhdGEgJiZcblx0XHRcdCggcy5jb250ZW50VHlwZSB8fCBcIlwiICkuaW5kZXhPZiggXCJhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWRcIiApID09PSAwICkge1xuXHRcdFx0cy5kYXRhID0gcy5kYXRhLnJlcGxhY2UoIHIyMCwgXCIrXCIgKTtcblx0XHR9XG5cblx0XHQvLyBTZXQgdGhlIElmLU1vZGlmaWVkLVNpbmNlIGFuZC9vciBJZi1Ob25lLU1hdGNoIGhlYWRlciwgaWYgaW4gaWZNb2RpZmllZCBtb2RlLlxuXHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0aWYgKCBqUXVlcnkubGFzdE1vZGlmaWVkWyBjYWNoZVVSTCBdICkge1xuXHRcdFx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKCBcIklmLU1vZGlmaWVkLVNpbmNlXCIsIGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gKTtcblx0XHRcdH1cblx0XHRcdGlmICggalF1ZXJ5LmV0YWdbIGNhY2hlVVJMIF0gKSB7XG5cdFx0XHRcdGpxWEhSLnNldFJlcXVlc3RIZWFkZXIoIFwiSWYtTm9uZS1NYXRjaFwiLCBqUXVlcnkuZXRhZ1sgY2FjaGVVUkwgXSApO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgY29ycmVjdCBoZWFkZXIsIGlmIGRhdGEgaXMgYmVpbmcgc2VudFxuXHRcdGlmICggcy5kYXRhICYmIHMuaGFzQ29udGVudCAmJiBzLmNvbnRlbnRUeXBlICE9PSBmYWxzZSB8fCBvcHRpb25zLmNvbnRlbnRUeXBlICkge1xuXHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggXCJDb250ZW50LVR5cGVcIiwgcy5jb250ZW50VHlwZSApO1xuXHRcdH1cblxuXHRcdC8vIFNldCB0aGUgQWNjZXB0cyBoZWFkZXIgZm9yIHRoZSBzZXJ2ZXIsIGRlcGVuZGluZyBvbiB0aGUgZGF0YVR5cGVcblx0XHRqcVhIUi5zZXRSZXF1ZXN0SGVhZGVyKFxuXHRcdFx0XCJBY2NlcHRcIixcblx0XHRcdHMuZGF0YVR5cGVzWyAwIF0gJiYgcy5hY2NlcHRzWyBzLmRhdGFUeXBlc1sgMCBdIF0gP1xuXHRcdFx0XHRzLmFjY2VwdHNbIHMuZGF0YVR5cGVzWyAwIF0gXSArXG5cdFx0XHRcdFx0KCBzLmRhdGFUeXBlc1sgMCBdICE9PSBcIipcIiA/IFwiLCBcIiArIGFsbFR5cGVzICsgXCI7IHE9MC4wMVwiIDogXCJcIiApIDpcblx0XHRcdFx0cy5hY2NlcHRzWyBcIipcIiBdXG5cdFx0KTtcblxuXHRcdC8vIENoZWNrIGZvciBoZWFkZXJzIG9wdGlvblxuXHRcdGZvciAoIGkgaW4gcy5oZWFkZXJzICkge1xuXHRcdFx0anFYSFIuc2V0UmVxdWVzdEhlYWRlciggaSwgcy5oZWFkZXJzWyBpIF0gKTtcblx0XHR9XG5cblx0XHQvLyBBbGxvdyBjdXN0b20gaGVhZGVycy9taW1ldHlwZXMgYW5kIGVhcmx5IGFib3J0XG5cdFx0aWYgKCBzLmJlZm9yZVNlbmQgJiZcblx0XHRcdCggcy5iZWZvcmVTZW5kLmNhbGwoIGNhbGxiYWNrQ29udGV4dCwganFYSFIsIHMgKSA9PT0gZmFsc2UgfHwgY29tcGxldGVkICkgKSB7XG5cblx0XHRcdC8vIEFib3J0IGlmIG5vdCBkb25lIGFscmVhZHkgYW5kIHJldHVyblxuXHRcdFx0cmV0dXJuIGpxWEhSLmFib3J0KCk7XG5cdFx0fVxuXG5cdFx0Ly8gQWJvcnRpbmcgaXMgbm8gbG9uZ2VyIGEgY2FuY2VsbGF0aW9uXG5cdFx0c3RyQWJvcnQgPSBcImFib3J0XCI7XG5cblx0XHQvLyBJbnN0YWxsIGNhbGxiYWNrcyBvbiBkZWZlcnJlZHNcblx0XHRjb21wbGV0ZURlZmVycmVkLmFkZCggcy5jb21wbGV0ZSApO1xuXHRcdGpxWEhSLmRvbmUoIHMuc3VjY2VzcyApO1xuXHRcdGpxWEhSLmZhaWwoIHMuZXJyb3IgKTtcblxuXHRcdC8vIEdldCB0cmFuc3BvcnRcblx0XHR0cmFuc3BvcnQgPSBpbnNwZWN0UHJlZmlsdGVyc09yVHJhbnNwb3J0cyggdHJhbnNwb3J0cywgcywgb3B0aW9ucywganFYSFIgKTtcblxuXHRcdC8vIElmIG5vIHRyYW5zcG9ydCwgd2UgYXV0by1hYm9ydFxuXHRcdGlmICggIXRyYW5zcG9ydCApIHtcblx0XHRcdGRvbmUoIC0xLCBcIk5vIFRyYW5zcG9ydFwiICk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSAxO1xuXG5cdFx0XHQvLyBTZW5kIGdsb2JhbCBldmVudFxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheFNlbmRcIiwgWyBqcVhIUiwgcyBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIElmIHJlcXVlc3Qgd2FzIGFib3J0ZWQgaW5zaWRlIGFqYXhTZW5kLCBzdG9wIHRoZXJlXG5cdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0cmV0dXJuIGpxWEhSO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUaW1lb3V0XG5cdFx0XHRpZiAoIHMuYXN5bmMgJiYgcy50aW1lb3V0ID4gMCApIHtcblx0XHRcdFx0dGltZW91dFRpbWVyID0gd2luZG93LnNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGpxWEhSLmFib3J0KCBcInRpbWVvdXRcIiApO1xuXHRcdFx0XHR9LCBzLnRpbWVvdXQgKTtcblx0XHRcdH1cblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0Y29tcGxldGVkID0gZmFsc2U7XG5cdFx0XHRcdHRyYW5zcG9ydC5zZW5kKCByZXF1ZXN0SGVhZGVycywgZG9uZSApO1xuXHRcdFx0fSBjYXRjaCAoIGUgKSB7XG5cblx0XHRcdFx0Ly8gUmV0aHJvdyBwb3N0LWNvbXBsZXRpb24gZXhjZXB0aW9uc1xuXHRcdFx0XHRpZiAoIGNvbXBsZXRlZCApIHtcblx0XHRcdFx0XHR0aHJvdyBlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gUHJvcGFnYXRlIG90aGVycyBhcyByZXN1bHRzXG5cdFx0XHRcdGRvbmUoIC0xLCBlICk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gQ2FsbGJhY2sgZm9yIHdoZW4gZXZlcnl0aGluZyBpcyBkb25lXG5cdFx0ZnVuY3Rpb24gZG9uZSggc3RhdHVzLCBuYXRpdmVTdGF0dXNUZXh0LCByZXNwb25zZXMsIGhlYWRlcnMgKSB7XG5cdFx0XHR2YXIgaXNTdWNjZXNzLCBzdWNjZXNzLCBlcnJvciwgcmVzcG9uc2UsIG1vZGlmaWVkLFxuXHRcdFx0XHRzdGF0dXNUZXh0ID0gbmF0aXZlU3RhdHVzVGV4dDtcblxuXHRcdFx0Ly8gSWdub3JlIHJlcGVhdCBpbnZvY2F0aW9uc1xuXHRcdFx0aWYgKCBjb21wbGV0ZWQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0Y29tcGxldGVkID0gdHJ1ZTtcblxuXHRcdFx0Ly8gQ2xlYXIgdGltZW91dCBpZiBpdCBleGlzdHNcblx0XHRcdGlmICggdGltZW91dFRpbWVyICkge1xuXHRcdFx0XHR3aW5kb3cuY2xlYXJUaW1lb3V0KCB0aW1lb3V0VGltZXIgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gRGVyZWZlcmVuY2UgdHJhbnNwb3J0IGZvciBlYXJseSBnYXJiYWdlIGNvbGxlY3Rpb25cblx0XHRcdC8vIChubyBtYXR0ZXIgaG93IGxvbmcgdGhlIGpxWEhSIG9iamVjdCB3aWxsIGJlIHVzZWQpXG5cdFx0XHR0cmFuc3BvcnQgPSB1bmRlZmluZWQ7XG5cblx0XHRcdC8vIENhY2hlIHJlc3BvbnNlIGhlYWRlcnNcblx0XHRcdHJlc3BvbnNlSGVhZGVyc1N0cmluZyA9IGhlYWRlcnMgfHwgXCJcIjtcblxuXHRcdFx0Ly8gU2V0IHJlYWR5U3RhdGVcblx0XHRcdGpxWEhSLnJlYWR5U3RhdGUgPSBzdGF0dXMgPiAwID8gNCA6IDA7XG5cblx0XHRcdC8vIERldGVybWluZSBpZiBzdWNjZXNzZnVsXG5cdFx0XHRpc1N1Y2Nlc3MgPSBzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCB8fCBzdGF0dXMgPT09IDMwNDtcblxuXHRcdFx0Ly8gR2V0IHJlc3BvbnNlIGRhdGFcblx0XHRcdGlmICggcmVzcG9uc2VzICkge1xuXHRcdFx0XHRyZXNwb25zZSA9IGFqYXhIYW5kbGVSZXNwb25zZXMoIHMsIGpxWEhSLCByZXNwb25zZXMgKTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ29udmVydCBubyBtYXR0ZXIgd2hhdCAodGhhdCB3YXkgcmVzcG9uc2VYWFggZmllbGRzIGFyZSBhbHdheXMgc2V0KVxuXHRcdFx0cmVzcG9uc2UgPSBhamF4Q29udmVydCggcywgcmVzcG9uc2UsIGpxWEhSLCBpc1N1Y2Nlc3MgKTtcblxuXHRcdFx0Ly8gSWYgc3VjY2Vzc2Z1bCwgaGFuZGxlIHR5cGUgY2hhaW5pbmdcblx0XHRcdGlmICggaXNTdWNjZXNzICkge1xuXG5cdFx0XHRcdC8vIFNldCB0aGUgSWYtTW9kaWZpZWQtU2luY2UgYW5kL29yIElmLU5vbmUtTWF0Y2ggaGVhZGVyLCBpZiBpbiBpZk1vZGlmaWVkIG1vZGUuXG5cdFx0XHRcdGlmICggcy5pZk1vZGlmaWVkICkge1xuXHRcdFx0XHRcdG1vZGlmaWVkID0ganFYSFIuZ2V0UmVzcG9uc2VIZWFkZXIoIFwiTGFzdC1Nb2RpZmllZFwiICk7XG5cdFx0XHRcdFx0aWYgKCBtb2RpZmllZCApIHtcblx0XHRcdFx0XHRcdGpRdWVyeS5sYXN0TW9kaWZpZWRbIGNhY2hlVVJMIF0gPSBtb2RpZmllZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0bW9kaWZpZWQgPSBqcVhIUi5nZXRSZXNwb25zZUhlYWRlciggXCJldGFnXCIgKTtcblx0XHRcdFx0XHRpZiAoIG1vZGlmaWVkICkge1xuXHRcdFx0XHRcdFx0alF1ZXJ5LmV0YWdbIGNhY2hlVVJMIF0gPSBtb2RpZmllZDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBpZiBubyBjb250ZW50XG5cdFx0XHRcdGlmICggc3RhdHVzID09PSAyMDQgfHwgcy50eXBlID09PSBcIkhFQURcIiApIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gXCJub2NvbnRlbnRcIjtcblxuXHRcdFx0XHQvLyBpZiBub3QgbW9kaWZpZWRcblx0XHRcdFx0fSBlbHNlIGlmICggc3RhdHVzID09PSAzMDQgKSB7XG5cdFx0XHRcdFx0c3RhdHVzVGV4dCA9IFwibm90bW9kaWZpZWRcIjtcblxuXHRcdFx0XHQvLyBJZiB3ZSBoYXZlIGRhdGEsIGxldCdzIGNvbnZlcnQgaXRcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRzdGF0dXNUZXh0ID0gcmVzcG9uc2Uuc3RhdGU7XG5cdFx0XHRcdFx0c3VjY2VzcyA9IHJlc3BvbnNlLmRhdGE7XG5cdFx0XHRcdFx0ZXJyb3IgPSByZXNwb25zZS5lcnJvcjtcblx0XHRcdFx0XHRpc1N1Y2Nlc3MgPSAhZXJyb3I7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cblx0XHRcdFx0Ly8gRXh0cmFjdCBlcnJvciBmcm9tIHN0YXR1c1RleHQgYW5kIG5vcm1hbGl6ZSBmb3Igbm9uLWFib3J0c1xuXHRcdFx0XHRlcnJvciA9IHN0YXR1c1RleHQ7XG5cdFx0XHRcdGlmICggc3RhdHVzIHx8ICFzdGF0dXNUZXh0ICkge1xuXHRcdFx0XHRcdHN0YXR1c1RleHQgPSBcImVycm9yXCI7XG5cdFx0XHRcdFx0aWYgKCBzdGF0dXMgPCAwICkge1xuXHRcdFx0XHRcdFx0c3RhdHVzID0gMDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Ly8gU2V0IGRhdGEgZm9yIHRoZSBmYWtlIHhociBvYmplY3Rcblx0XHRcdGpxWEhSLnN0YXR1cyA9IHN0YXR1cztcblx0XHRcdGpxWEhSLnN0YXR1c1RleHQgPSAoIG5hdGl2ZVN0YXR1c1RleHQgfHwgc3RhdHVzVGV4dCApICsgXCJcIjtcblxuXHRcdFx0Ly8gU3VjY2Vzcy9FcnJvclxuXHRcdFx0aWYgKCBpc1N1Y2Nlc3MgKSB7XG5cdFx0XHRcdGRlZmVycmVkLnJlc29sdmVXaXRoKCBjYWxsYmFja0NvbnRleHQsIFsgc3VjY2Vzcywgc3RhdHVzVGV4dCwganFYSFIgXSApO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0ZGVmZXJyZWQucmVqZWN0V2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0LCBlcnJvciBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFN0YXR1cy1kZXBlbmRlbnQgY2FsbGJhY2tzXG5cdFx0XHRqcVhIUi5zdGF0dXNDb2RlKCBzdGF0dXNDb2RlICk7XG5cdFx0XHRzdGF0dXNDb2RlID0gdW5kZWZpbmVkO1xuXG5cdFx0XHRpZiAoIGZpcmVHbG9iYWxzICkge1xuXHRcdFx0XHRnbG9iYWxFdmVudENvbnRleHQudHJpZ2dlciggaXNTdWNjZXNzID8gXCJhamF4U3VjY2Vzc1wiIDogXCJhamF4RXJyb3JcIixcblx0XHRcdFx0XHRbIGpxWEhSLCBzLCBpc1N1Y2Nlc3MgPyBzdWNjZXNzIDogZXJyb3IgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBDb21wbGV0ZVxuXHRcdFx0Y29tcGxldGVEZWZlcnJlZC5maXJlV2l0aCggY2FsbGJhY2tDb250ZXh0LCBbIGpxWEhSLCBzdGF0dXNUZXh0IF0gKTtcblxuXHRcdFx0aWYgKCBmaXJlR2xvYmFscyApIHtcblx0XHRcdFx0Z2xvYmFsRXZlbnRDb250ZXh0LnRyaWdnZXIoIFwiYWpheENvbXBsZXRlXCIsIFsganFYSFIsIHMgXSApO1xuXG5cdFx0XHRcdC8vIEhhbmRsZSB0aGUgZ2xvYmFsIEFKQVggY291bnRlclxuXHRcdFx0XHRpZiAoICEoIC0talF1ZXJ5LmFjdGl2ZSApICkge1xuXHRcdFx0XHRcdGpRdWVyeS5ldmVudC50cmlnZ2VyKCBcImFqYXhTdG9wXCIgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBqcVhIUjtcblx0fSxcblxuXHRnZXRKU09OOiBmdW5jdGlvbiggdXJsLCBkYXRhLCBjYWxsYmFjayApIHtcblx0XHRyZXR1cm4galF1ZXJ5LmdldCggdXJsLCBkYXRhLCBjYWxsYmFjaywgXCJqc29uXCIgKTtcblx0fSxcblxuXHRnZXRTY3JpcHQ6IGZ1bmN0aW9uKCB1cmwsIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiBqUXVlcnkuZ2V0KCB1cmwsIHVuZGVmaW5lZCwgY2FsbGJhY2ssIFwic2NyaXB0XCIgKTtcblx0fVxufSApO1xuXG5qUXVlcnkuZWFjaCggWyBcImdldFwiLCBcInBvc3RcIiBdLCBmdW5jdGlvbiggaSwgbWV0aG9kICkge1xuXHRqUXVlcnlbIG1ldGhvZCBdID0gZnVuY3Rpb24oIHVybCwgZGF0YSwgY2FsbGJhY2ssIHR5cGUgKSB7XG5cblx0XHQvLyBTaGlmdCBhcmd1bWVudHMgaWYgZGF0YSBhcmd1bWVudCB3YXMgb21pdHRlZFxuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGRhdGEgKSApIHtcblx0XHRcdHR5cGUgPSB0eXBlIHx8IGNhbGxiYWNrO1xuXHRcdFx0Y2FsbGJhY2sgPSBkYXRhO1xuXHRcdFx0ZGF0YSA9IHVuZGVmaW5lZDtcblx0XHR9XG5cblx0XHQvLyBUaGUgdXJsIGNhbiBiZSBhbiBvcHRpb25zIG9iamVjdCAod2hpY2ggdGhlbiBtdXN0IGhhdmUgLnVybClcblx0XHRyZXR1cm4galF1ZXJ5LmFqYXgoIGpRdWVyeS5leHRlbmQoIHtcblx0XHRcdHVybDogdXJsLFxuXHRcdFx0dHlwZTogbWV0aG9kLFxuXHRcdFx0ZGF0YVR5cGU6IHR5cGUsXG5cdFx0XHRkYXRhOiBkYXRhLFxuXHRcdFx0c3VjY2VzczogY2FsbGJhY2tcblx0XHR9LCBqUXVlcnkuaXNQbGFpbk9iamVjdCggdXJsICkgJiYgdXJsICkgKTtcblx0fTtcbn0gKTtcblxuXG5qUXVlcnkuX2V2YWxVcmwgPSBmdW5jdGlvbiggdXJsICkge1xuXHRyZXR1cm4galF1ZXJ5LmFqYXgoIHtcblx0XHR1cmw6IHVybCxcblxuXHRcdC8vIE1ha2UgdGhpcyBleHBsaWNpdCwgc2luY2UgdXNlciBjYW4gb3ZlcnJpZGUgdGhpcyB0aHJvdWdoIGFqYXhTZXR1cCAoIzExMjY0KVxuXHRcdHR5cGU6IFwiR0VUXCIsXG5cdFx0ZGF0YVR5cGU6IFwic2NyaXB0XCIsXG5cdFx0Y2FjaGU6IHRydWUsXG5cdFx0YXN5bmM6IGZhbHNlLFxuXHRcdGdsb2JhbDogZmFsc2UsXG5cdFx0XCJ0aHJvd3NcIjogdHJ1ZVxuXHR9ICk7XG59O1xuXG5cbmpRdWVyeS5mbi5leHRlbmQoIHtcblx0d3JhcEFsbDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIHdyYXA7XG5cblx0XHRpZiAoIHRoaXNbIDAgXSApIHtcblx0XHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdFx0aHRtbCA9IGh0bWwuY2FsbCggdGhpc1sgMCBdICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIFRoZSBlbGVtZW50cyB0byB3cmFwIHRoZSB0YXJnZXQgYXJvdW5kXG5cdFx0XHR3cmFwID0galF1ZXJ5KCBodG1sLCB0aGlzWyAwIF0ub3duZXJEb2N1bWVudCApLmVxKCAwICkuY2xvbmUoIHRydWUgKTtcblxuXHRcdFx0aWYgKCB0aGlzWyAwIF0ucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0d3JhcC5pbnNlcnRCZWZvcmUoIHRoaXNbIDAgXSApO1xuXHRcdFx0fVxuXG5cdFx0XHR3cmFwLm1hcCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHZhciBlbGVtID0gdGhpcztcblxuXHRcdFx0XHR3aGlsZSAoIGVsZW0uZmlyc3RFbGVtZW50Q2hpbGQgKSB7XG5cdFx0XHRcdFx0ZWxlbSA9IGVsZW0uZmlyc3RFbGVtZW50Q2hpbGQ7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm4gZWxlbTtcblx0XHRcdH0gKS5hcHBlbmQoIHRoaXMgKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gdGhpcztcblx0fSxcblxuXHR3cmFwSW5uZXI6IGZ1bmN0aW9uKCBodG1sICkge1xuXHRcdGlmICggalF1ZXJ5LmlzRnVuY3Rpb24oIGh0bWwgKSApIHtcblx0XHRcdHJldHVybiB0aGlzLmVhY2goIGZ1bmN0aW9uKCBpICkge1xuXHRcdFx0XHRqUXVlcnkoIHRoaXMgKS53cmFwSW5uZXIoIGh0bWwuY2FsbCggdGhpcywgaSApICk7XG5cdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgc2VsZiA9IGpRdWVyeSggdGhpcyApLFxuXHRcdFx0XHRjb250ZW50cyA9IHNlbGYuY29udGVudHMoKTtcblxuXHRcdFx0aWYgKCBjb250ZW50cy5sZW5ndGggKSB7XG5cdFx0XHRcdGNvbnRlbnRzLndyYXBBbGwoIGh0bWwgKTtcblxuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0c2VsZi5hcHBlbmQoIGh0bWwgKTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdH0sXG5cblx0d3JhcDogZnVuY3Rpb24oIGh0bWwgKSB7XG5cdFx0dmFyIGlzRnVuY3Rpb24gPSBqUXVlcnkuaXNGdW5jdGlvbiggaHRtbCApO1xuXG5cdFx0cmV0dXJuIHRoaXMuZWFjaCggZnVuY3Rpb24oIGkgKSB7XG5cdFx0XHRqUXVlcnkoIHRoaXMgKS53cmFwQWxsKCBpc0Z1bmN0aW9uID8gaHRtbC5jYWxsKCB0aGlzLCBpICkgOiBodG1sICk7XG5cdFx0fSApO1xuXHR9LFxuXG5cdHVud3JhcDogZnVuY3Rpb24oIHNlbGVjdG9yICkge1xuXHRcdHRoaXMucGFyZW50KCBzZWxlY3RvciApLm5vdCggXCJib2R5XCIgKS5lYWNoKCBmdW5jdGlvbigpIHtcblx0XHRcdGpRdWVyeSggdGhpcyApLnJlcGxhY2VXaXRoKCB0aGlzLmNoaWxkTm9kZXMgKTtcblx0XHR9ICk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH1cbn0gKTtcblxuXG5qUXVlcnkuZXhwci5wc2V1ZG9zLmhpZGRlbiA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gIWpRdWVyeS5leHByLnBzZXVkb3MudmlzaWJsZSggZWxlbSApO1xufTtcbmpRdWVyeS5leHByLnBzZXVkb3MudmlzaWJsZSA9IGZ1bmN0aW9uKCBlbGVtICkge1xuXHRyZXR1cm4gISEoIGVsZW0ub2Zmc2V0V2lkdGggfHwgZWxlbS5vZmZzZXRIZWlnaHQgfHwgZWxlbS5nZXRDbGllbnRSZWN0cygpLmxlbmd0aCApO1xufTtcblxuXG5cblxualF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIgPSBmdW5jdGlvbigpIHtcblx0dHJ5IHtcblx0XHRyZXR1cm4gbmV3IHdpbmRvdy5YTUxIdHRwUmVxdWVzdCgpO1xuXHR9IGNhdGNoICggZSApIHt9XG59O1xuXG52YXIgeGhyU3VjY2Vzc1N0YXR1cyA9IHtcblxuXHRcdC8vIEZpbGUgcHJvdG9jb2wgYWx3YXlzIHlpZWxkcyBzdGF0dXMgY29kZSAwLCBhc3N1bWUgMjAwXG5cdFx0MDogMjAwLFxuXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD05IG9ubHlcblx0XHQvLyAjMTQ1MDogc29tZXRpbWVzIElFIHJldHVybnMgMTIyMyB3aGVuIGl0IHNob3VsZCBiZSAyMDRcblx0XHQxMjIzOiAyMDRcblx0fSxcblx0eGhyU3VwcG9ydGVkID0galF1ZXJ5LmFqYXhTZXR0aW5ncy54aHIoKTtcblxuc3VwcG9ydC5jb3JzID0gISF4aHJTdXBwb3J0ZWQgJiYgKCBcIndpdGhDcmVkZW50aWFsc1wiIGluIHhoclN1cHBvcnRlZCApO1xuc3VwcG9ydC5hamF4ID0geGhyU3VwcG9ydGVkID0gISF4aHJTdXBwb3J0ZWQ7XG5cbmpRdWVyeS5hamF4VHJhbnNwb3J0KCBmdW5jdGlvbiggb3B0aW9ucyApIHtcblx0dmFyIGNhbGxiYWNrLCBlcnJvckNhbGxiYWNrO1xuXG5cdC8vIENyb3NzIGRvbWFpbiBvbmx5IGFsbG93ZWQgaWYgc3VwcG9ydGVkIHRocm91Z2ggWE1MSHR0cFJlcXVlc3Rcblx0aWYgKCBzdXBwb3J0LmNvcnMgfHwgeGhyU3VwcG9ydGVkICYmICFvcHRpb25zLmNyb3NzRG9tYWluICkge1xuXHRcdHJldHVybiB7XG5cdFx0XHRzZW5kOiBmdW5jdGlvbiggaGVhZGVycywgY29tcGxldGUgKSB7XG5cdFx0XHRcdHZhciBpLFxuXHRcdFx0XHRcdHhociA9IG9wdGlvbnMueGhyKCk7XG5cblx0XHRcdFx0eGhyLm9wZW4oXG5cdFx0XHRcdFx0b3B0aW9ucy50eXBlLFxuXHRcdFx0XHRcdG9wdGlvbnMudXJsLFxuXHRcdFx0XHRcdG9wdGlvbnMuYXN5bmMsXG5cdFx0XHRcdFx0b3B0aW9ucy51c2VybmFtZSxcblx0XHRcdFx0XHRvcHRpb25zLnBhc3N3b3JkXG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gQXBwbHkgY3VzdG9tIGZpZWxkcyBpZiBwcm92aWRlZFxuXHRcdFx0XHRpZiAoIG9wdGlvbnMueGhyRmllbGRzICkge1xuXHRcdFx0XHRcdGZvciAoIGkgaW4gb3B0aW9ucy54aHJGaWVsZHMgKSB7XG5cdFx0XHRcdFx0XHR4aHJbIGkgXSA9IG9wdGlvbnMueGhyRmllbGRzWyBpIF07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gT3ZlcnJpZGUgbWltZSB0eXBlIGlmIG5lZWRlZFxuXHRcdFx0XHRpZiAoIG9wdGlvbnMubWltZVR5cGUgJiYgeGhyLm92ZXJyaWRlTWltZVR5cGUgKSB7XG5cdFx0XHRcdFx0eGhyLm92ZXJyaWRlTWltZVR5cGUoIG9wdGlvbnMubWltZVR5cGUgKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIFgtUmVxdWVzdGVkLVdpdGggaGVhZGVyXG5cdFx0XHRcdC8vIEZvciBjcm9zcy1kb21haW4gcmVxdWVzdHMsIHNlZWluZyBhcyBjb25kaXRpb25zIGZvciBhIHByZWZsaWdodCBhcmVcblx0XHRcdFx0Ly8gYWtpbiB0byBhIGppZ3NhdyBwdXp6bGUsIHdlIHNpbXBseSBuZXZlciBzZXQgaXQgdG8gYmUgc3VyZS5cblx0XHRcdFx0Ly8gKGl0IGNhbiBhbHdheXMgYmUgc2V0IG9uIGEgcGVyLXJlcXVlc3QgYmFzaXMgb3IgZXZlbiB1c2luZyBhamF4U2V0dXApXG5cdFx0XHRcdC8vIEZvciBzYW1lLWRvbWFpbiByZXF1ZXN0cywgd29uJ3QgY2hhbmdlIGhlYWRlciBpZiBhbHJlYWR5IHByb3ZpZGVkLlxuXHRcdFx0XHRpZiAoICFvcHRpb25zLmNyb3NzRG9tYWluICYmICFoZWFkZXJzWyBcIlgtUmVxdWVzdGVkLVdpdGhcIiBdICkge1xuXHRcdFx0XHRcdGhlYWRlcnNbIFwiWC1SZXF1ZXN0ZWQtV2l0aFwiIF0gPSBcIlhNTEh0dHBSZXF1ZXN0XCI7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBTZXQgaGVhZGVyc1xuXHRcdFx0XHRmb3IgKCBpIGluIGhlYWRlcnMgKSB7XG5cdFx0XHRcdFx0eGhyLnNldFJlcXVlc3RIZWFkZXIoIGksIGhlYWRlcnNbIGkgXSApO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gQ2FsbGJhY2tcblx0XHRcdFx0Y2FsbGJhY2sgPSBmdW5jdGlvbiggdHlwZSApIHtcblx0XHRcdFx0XHRyZXR1cm4gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0XHRjYWxsYmFjayA9IGVycm9yQ2FsbGJhY2sgPSB4aHIub25sb2FkID1cblx0XHRcdFx0XHRcdFx0XHR4aHIub25lcnJvciA9IHhoci5vbmFib3J0ID0geGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG5cblx0XHRcdFx0XHRcdFx0aWYgKCB0eXBlID09PSBcImFib3J0XCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0eGhyLmFib3J0KCk7XG5cdFx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIHR5cGUgPT09IFwiZXJyb3JcIiApIHtcblxuXHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0Ly8gT24gYSBtYW51YWwgbmF0aXZlIGFib3J0LCBJRTkgdGhyb3dzXG5cdFx0XHRcdFx0XHRcdFx0Ly8gZXJyb3JzIG9uIGFueSBwcm9wZXJ0eSBhY2Nlc3MgdGhhdCBpcyBub3QgcmVhZHlTdGF0ZVxuXHRcdFx0XHRcdFx0XHRcdGlmICggdHlwZW9mIHhoci5zdGF0dXMgIT09IFwibnVtYmVyXCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZSggMCwgXCJlcnJvclwiICk7XG5cdFx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRcdGNvbXBsZXRlKFxuXG5cdFx0XHRcdFx0XHRcdFx0XHRcdC8vIEZpbGU6IHByb3RvY29sIGFsd2F5cyB5aWVsZHMgc3RhdHVzIDA7IHNlZSAjODYwNSwgIzE0MjA3XG5cdFx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXMsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHhoci5zdGF0dXNUZXh0XG5cdFx0XHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHRjb21wbGV0ZShcblx0XHRcdFx0XHRcdFx0XHRcdHhoclN1Y2Nlc3NTdGF0dXNbIHhoci5zdGF0dXMgXSB8fCB4aHIuc3RhdHVzLFxuXHRcdFx0XHRcdFx0XHRcdFx0eGhyLnN0YXR1c1RleHQsXG5cblx0XHRcdFx0XHRcdFx0XHRcdC8vIFN1cHBvcnQ6IElFIDw9OSBvbmx5XG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBJRTkgaGFzIG5vIFhIUjIgYnV0IHRocm93cyBvbiBiaW5hcnkgKHRyYWMtMTE0MjYpXG5cdFx0XHRcdFx0XHRcdFx0XHQvLyBGb3IgWEhSMiBub24tdGV4dCwgbGV0IHRoZSBjYWxsZXIgaGFuZGxlIGl0IChnaC0yNDk4KVxuXHRcdFx0XHRcdFx0XHRcdFx0KCB4aHIucmVzcG9uc2VUeXBlIHx8IFwidGV4dFwiICkgIT09IFwidGV4dFwiICB8fFxuXHRcdFx0XHRcdFx0XHRcdFx0dHlwZW9mIHhoci5yZXNwb25zZVRleHQgIT09IFwic3RyaW5nXCIgP1xuXHRcdFx0XHRcdFx0XHRcdFx0XHR7IGJpbmFyeTogeGhyLnJlc3BvbnNlIH0gOlxuXHRcdFx0XHRcdFx0XHRcdFx0XHR7IHRleHQ6IHhoci5yZXNwb25zZVRleHQgfSxcblx0XHRcdFx0XHRcdFx0XHRcdHhoci5nZXRBbGxSZXNwb25zZUhlYWRlcnMoKVxuXHRcdFx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9O1xuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdC8vIExpc3RlbiB0byBldmVudHNcblx0XHRcdFx0eGhyLm9ubG9hZCA9IGNhbGxiYWNrKCk7XG5cdFx0XHRcdGVycm9yQ2FsbGJhY2sgPSB4aHIub25lcnJvciA9IGNhbGxiYWNrKCBcImVycm9yXCIgKTtcblxuXHRcdFx0XHQvLyBTdXBwb3J0OiBJRSA5IG9ubHlcblx0XHRcdFx0Ly8gVXNlIG9ucmVhZHlzdGF0ZWNoYW5nZSB0byByZXBsYWNlIG9uYWJvcnRcblx0XHRcdFx0Ly8gdG8gaGFuZGxlIHVuY2F1Z2h0IGFib3J0c1xuXHRcdFx0XHRpZiAoIHhoci5vbmFib3J0ICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0eGhyLm9uYWJvcnQgPSBlcnJvckNhbGxiYWNrO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHhoci5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbigpIHtcblxuXHRcdFx0XHRcdFx0Ly8gQ2hlY2sgcmVhZHlTdGF0ZSBiZWZvcmUgdGltZW91dCBhcyBpdCBjaGFuZ2VzXG5cdFx0XHRcdFx0XHRpZiAoIHhoci5yZWFkeVN0YXRlID09PSA0ICkge1xuXG5cdFx0XHRcdFx0XHRcdC8vIEFsbG93IG9uZXJyb3IgdG8gYmUgY2FsbGVkIGZpcnN0LFxuXHRcdFx0XHRcdFx0XHQvLyBidXQgdGhhdCB3aWxsIG5vdCBoYW5kbGUgYSBuYXRpdmUgYWJvcnRcblx0XHRcdFx0XHRcdFx0Ly8gQWxzbywgc2F2ZSBlcnJvckNhbGxiYWNrIHRvIGEgdmFyaWFibGVcblx0XHRcdFx0XHRcdFx0Ly8gYXMgeGhyLm9uZXJyb3IgY2Fubm90IGJlIGFjY2Vzc2VkXG5cdFx0XHRcdFx0XHRcdHdpbmRvdy5zZXRUaW1lb3V0KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0XHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdFx0XHRcdFx0ZXJyb3JDYWxsYmFjaygpO1xuXHRcdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdFx0fSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblxuXHRcdFx0XHQvLyBDcmVhdGUgdGhlIGFib3J0IGNhbGxiYWNrXG5cdFx0XHRcdGNhbGxiYWNrID0gY2FsbGJhY2soIFwiYWJvcnRcIiApO1xuXG5cdFx0XHRcdHRyeSB7XG5cblx0XHRcdFx0XHQvLyBEbyBzZW5kIHRoZSByZXF1ZXN0ICh0aGlzIG1heSByYWlzZSBhbiBleGNlcHRpb24pXG5cdFx0XHRcdFx0eGhyLnNlbmQoIG9wdGlvbnMuaGFzQ29udGVudCAmJiBvcHRpb25zLmRhdGEgfHwgbnVsbCApO1xuXHRcdFx0XHR9IGNhdGNoICggZSApIHtcblxuXHRcdFx0XHRcdC8vICMxNDY4MzogT25seSByZXRocm93IGlmIHRoaXMgaGFzbid0IGJlZW4gbm90aWZpZWQgYXMgYW4gZXJyb3IgeWV0XG5cdFx0XHRcdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdFx0XHRcdHRocm93IGU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9LFxuXG5cdFx0XHRhYm9ydDogZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmICggY2FsbGJhY2sgKSB7XG5cdFx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdH1cbn0gKTtcblxuXG5cblxuLy8gUHJldmVudCBhdXRvLWV4ZWN1dGlvbiBvZiBzY3JpcHRzIHdoZW4gbm8gZXhwbGljaXQgZGF0YVR5cGUgd2FzIHByb3ZpZGVkIChTZWUgZ2gtMjQzMilcbmpRdWVyeS5hamF4UHJlZmlsdGVyKCBmdW5jdGlvbiggcyApIHtcblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMuY29udGVudHMuc2NyaXB0ID0gZmFsc2U7XG5cdH1cbn0gKTtcblxuLy8gSW5zdGFsbCBzY3JpcHQgZGF0YVR5cGVcbmpRdWVyeS5hamF4U2V0dXAoIHtcblx0YWNjZXB0czoge1xuXHRcdHNjcmlwdDogXCJ0ZXh0L2phdmFzY3JpcHQsIGFwcGxpY2F0aW9uL2phdmFzY3JpcHQsIFwiICtcblx0XHRcdFwiYXBwbGljYXRpb24vZWNtYXNjcmlwdCwgYXBwbGljYXRpb24veC1lY21hc2NyaXB0XCJcblx0fSxcblx0Y29udGVudHM6IHtcblx0XHRzY3JpcHQ6IC9cXGIoPzpqYXZhfGVjbWEpc2NyaXB0XFxiL1xuXHR9LFxuXHRjb252ZXJ0ZXJzOiB7XG5cdFx0XCJ0ZXh0IHNjcmlwdFwiOiBmdW5jdGlvbiggdGV4dCApIHtcblx0XHRcdGpRdWVyeS5nbG9iYWxFdmFsKCB0ZXh0ICk7XG5cdFx0XHRyZXR1cm4gdGV4dDtcblx0XHR9XG5cdH1cbn0gKTtcblxuLy8gSGFuZGxlIGNhY2hlJ3Mgc3BlY2lhbCBjYXNlIGFuZCBjcm9zc0RvbWFpblxualF1ZXJ5LmFqYXhQcmVmaWx0ZXIoIFwic2NyaXB0XCIsIGZ1bmN0aW9uKCBzICkge1xuXHRpZiAoIHMuY2FjaGUgPT09IHVuZGVmaW5lZCApIHtcblx0XHRzLmNhY2hlID0gZmFsc2U7XG5cdH1cblx0aWYgKCBzLmNyb3NzRG9tYWluICkge1xuXHRcdHMudHlwZSA9IFwiR0VUXCI7XG5cdH1cbn0gKTtcblxuLy8gQmluZCBzY3JpcHQgdGFnIGhhY2sgdHJhbnNwb3J0XG5qUXVlcnkuYWpheFRyYW5zcG9ydCggXCJzY3JpcHRcIiwgZnVuY3Rpb24oIHMgKSB7XG5cblx0Ly8gVGhpcyB0cmFuc3BvcnQgb25seSBkZWFscyB3aXRoIGNyb3NzIGRvbWFpbiByZXF1ZXN0c1xuXHRpZiAoIHMuY3Jvc3NEb21haW4gKSB7XG5cdFx0dmFyIHNjcmlwdCwgY2FsbGJhY2s7XG5cdFx0cmV0dXJuIHtcblx0XHRcdHNlbmQ6IGZ1bmN0aW9uKCBfLCBjb21wbGV0ZSApIHtcblx0XHRcdFx0c2NyaXB0ID0galF1ZXJ5KCBcIjxzY3JpcHQ+XCIgKS5wcm9wKCB7XG5cdFx0XHRcdFx0Y2hhcnNldDogcy5zY3JpcHRDaGFyc2V0LFxuXHRcdFx0XHRcdHNyYzogcy51cmxcblx0XHRcdFx0fSApLm9uKFxuXHRcdFx0XHRcdFwibG9hZCBlcnJvclwiLFxuXHRcdFx0XHRcdGNhbGxiYWNrID0gZnVuY3Rpb24oIGV2dCApIHtcblx0XHRcdFx0XHRcdHNjcmlwdC5yZW1vdmUoKTtcblx0XHRcdFx0XHRcdGNhbGxiYWNrID0gbnVsbDtcblx0XHRcdFx0XHRcdGlmICggZXZ0ICkge1xuXHRcdFx0XHRcdFx0XHRjb21wbGV0ZSggZXZ0LnR5cGUgPT09IFwiZXJyb3JcIiA/IDQwNCA6IDIwMCwgZXZ0LnR5cGUgKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdCk7XG5cblx0XHRcdFx0Ly8gVXNlIG5hdGl2ZSBET00gbWFuaXB1bGF0aW9uIHRvIGF2b2lkIG91ciBkb21NYW5pcCBBSkFYIHRyaWNrZXJ5XG5cdFx0XHRcdGRvY3VtZW50LmhlYWQuYXBwZW5kQ2hpbGQoIHNjcmlwdFsgMCBdICk7XG5cdFx0XHR9LFxuXHRcdFx0YWJvcnQ6IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRpZiAoIGNhbGxiYWNrICkge1xuXHRcdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9O1xuXHR9XG59ICk7XG5cblxuXG5cbnZhciBvbGRDYWxsYmFja3MgPSBbXSxcblx0cmpzb25wID0gLyg9KVxcPyg/PSZ8JCl8XFw/XFw/LztcblxuLy8gRGVmYXVsdCBqc29ucCBzZXR0aW5nc1xualF1ZXJ5LmFqYXhTZXR1cCgge1xuXHRqc29ucDogXCJjYWxsYmFja1wiLFxuXHRqc29ucENhbGxiYWNrOiBmdW5jdGlvbigpIHtcblx0XHR2YXIgY2FsbGJhY2sgPSBvbGRDYWxsYmFja3MucG9wKCkgfHwgKCBqUXVlcnkuZXhwYW5kbyArIFwiX1wiICsgKCBub25jZSsrICkgKTtcblx0XHR0aGlzWyBjYWxsYmFjayBdID0gdHJ1ZTtcblx0XHRyZXR1cm4gY2FsbGJhY2s7XG5cdH1cbn0gKTtcblxuLy8gRGV0ZWN0LCBub3JtYWxpemUgb3B0aW9ucyBhbmQgaW5zdGFsbCBjYWxsYmFja3MgZm9yIGpzb25wIHJlcXVlc3RzXG5qUXVlcnkuYWpheFByZWZpbHRlciggXCJqc29uIGpzb25wXCIsIGZ1bmN0aW9uKCBzLCBvcmlnaW5hbFNldHRpbmdzLCBqcVhIUiApIHtcblxuXHR2YXIgY2FsbGJhY2tOYW1lLCBvdmVyd3JpdHRlbiwgcmVzcG9uc2VDb250YWluZXIsXG5cdFx0anNvblByb3AgPSBzLmpzb25wICE9PSBmYWxzZSAmJiAoIHJqc29ucC50ZXN0KCBzLnVybCApID9cblx0XHRcdFwidXJsXCIgOlxuXHRcdFx0dHlwZW9mIHMuZGF0YSA9PT0gXCJzdHJpbmdcIiAmJlxuXHRcdFx0XHQoIHMuY29udGVudFR5cGUgfHwgXCJcIiApXG5cdFx0XHRcdFx0LmluZGV4T2YoIFwiYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkXCIgKSA9PT0gMCAmJlxuXHRcdFx0XHRyanNvbnAudGVzdCggcy5kYXRhICkgJiYgXCJkYXRhXCJcblx0XHQpO1xuXG5cdC8vIEhhbmRsZSBpZmYgdGhlIGV4cGVjdGVkIGRhdGEgdHlwZSBpcyBcImpzb25wXCIgb3Igd2UgaGF2ZSBhIHBhcmFtZXRlciB0byBzZXRcblx0aWYgKCBqc29uUHJvcCB8fCBzLmRhdGFUeXBlc1sgMCBdID09PSBcImpzb25wXCIgKSB7XG5cblx0XHQvLyBHZXQgY2FsbGJhY2sgbmFtZSwgcmVtZW1iZXJpbmcgcHJlZXhpc3RpbmcgdmFsdWUgYXNzb2NpYXRlZCB3aXRoIGl0XG5cdFx0Y2FsbGJhY2tOYW1lID0gcy5qc29ucENhbGxiYWNrID0galF1ZXJ5LmlzRnVuY3Rpb24oIHMuanNvbnBDYWxsYmFjayApID9cblx0XHRcdHMuanNvbnBDYWxsYmFjaygpIDpcblx0XHRcdHMuanNvbnBDYWxsYmFjaztcblxuXHRcdC8vIEluc2VydCBjYWxsYmFjayBpbnRvIHVybCBvciBmb3JtIGRhdGFcblx0XHRpZiAoIGpzb25Qcm9wICkge1xuXHRcdFx0c1sganNvblByb3AgXSA9IHNbIGpzb25Qcm9wIF0ucmVwbGFjZSggcmpzb25wLCBcIiQxXCIgKyBjYWxsYmFja05hbWUgKTtcblx0XHR9IGVsc2UgaWYgKCBzLmpzb25wICE9PSBmYWxzZSApIHtcblx0XHRcdHMudXJsICs9ICggcnF1ZXJ5LnRlc3QoIHMudXJsICkgPyBcIiZcIiA6IFwiP1wiICkgKyBzLmpzb25wICsgXCI9XCIgKyBjYWxsYmFja05hbWU7XG5cdFx0fVxuXG5cdFx0Ly8gVXNlIGRhdGEgY29udmVydGVyIHRvIHJldHJpZXZlIGpzb24gYWZ0ZXIgc2NyaXB0IGV4ZWN1dGlvblxuXHRcdHMuY29udmVydGVyc1sgXCJzY3JpcHQganNvblwiIF0gPSBmdW5jdGlvbigpIHtcblx0XHRcdGlmICggIXJlc3BvbnNlQ29udGFpbmVyICkge1xuXHRcdFx0XHRqUXVlcnkuZXJyb3IoIGNhbGxiYWNrTmFtZSArIFwiIHdhcyBub3QgY2FsbGVkXCIgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiByZXNwb25zZUNvbnRhaW5lclsgMCBdO1xuXHRcdH07XG5cblx0XHQvLyBGb3JjZSBqc29uIGRhdGFUeXBlXG5cdFx0cy5kYXRhVHlwZXNbIDAgXSA9IFwianNvblwiO1xuXG5cdFx0Ly8gSW5zdGFsbCBjYWxsYmFja1xuXHRcdG92ZXJ3cml0dGVuID0gd2luZG93WyBjYWxsYmFja05hbWUgXTtcblx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXNwb25zZUNvbnRhaW5lciA9IGFyZ3VtZW50cztcblx0XHR9O1xuXG5cdFx0Ly8gQ2xlYW4tdXAgZnVuY3Rpb24gKGZpcmVzIGFmdGVyIGNvbnZlcnRlcnMpXG5cdFx0anFYSFIuYWx3YXlzKCBmdW5jdGlvbigpIHtcblxuXHRcdFx0Ly8gSWYgcHJldmlvdXMgdmFsdWUgZGlkbid0IGV4aXN0IC0gcmVtb3ZlIGl0XG5cdFx0XHRpZiAoIG92ZXJ3cml0dGVuID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdGpRdWVyeSggd2luZG93ICkucmVtb3ZlUHJvcCggY2FsbGJhY2tOYW1lICk7XG5cblx0XHRcdC8vIE90aGVyd2lzZSByZXN0b3JlIHByZWV4aXN0aW5nIHZhbHVlXG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR3aW5kb3dbIGNhbGxiYWNrTmFtZSBdID0gb3ZlcndyaXR0ZW47XG5cdFx0XHR9XG5cblx0XHRcdC8vIFNhdmUgYmFjayBhcyBmcmVlXG5cdFx0XHRpZiAoIHNbIGNhbGxiYWNrTmFtZSBdICkge1xuXG5cdFx0XHRcdC8vIE1ha2Ugc3VyZSB0aGF0IHJlLXVzaW5nIHRoZSBvcHRpb25zIGRvZXNuJ3Qgc2NyZXcgdGhpbmdzIGFyb3VuZFxuXHRcdFx0XHRzLmpzb25wQ2FsbGJhY2sgPSBvcmlnaW5hbFNldHRpbmdzLmpzb25wQ2FsbGJhY2s7XG5cblx0XHRcdFx0Ly8gU2F2ZSB0aGUgY2FsbGJhY2sgbmFtZSBmb3IgZnV0dXJlIHVzZVxuXHRcdFx0XHRvbGRDYWxsYmFja3MucHVzaCggY2FsbGJhY2tOYW1lICk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIENhbGwgaWYgaXQgd2FzIGEgZnVuY3Rpb24gYW5kIHdlIGhhdmUgYSByZXNwb25zZVxuXHRcdFx0aWYgKCByZXNwb25zZUNvbnRhaW5lciAmJiBqUXVlcnkuaXNGdW5jdGlvbiggb3ZlcndyaXR0ZW4gKSApIHtcblx0XHRcdFx0b3ZlcndyaXR0ZW4oIHJlc3BvbnNlQ29udGFpbmVyWyAwIF0gKTtcblx0XHRcdH1cblxuXHRcdFx0cmVzcG9uc2VDb250YWluZXIgPSBvdmVyd3JpdHRlbiA9IHVuZGVmaW5lZDtcblx0XHR9ICk7XG5cblx0XHQvLyBEZWxlZ2F0ZSB0byBzY3JpcHRcblx0XHRyZXR1cm4gXCJzY3JpcHRcIjtcblx0fVxufSApO1xuXG5cblxuXG4vLyBTdXBwb3J0OiBTYWZhcmkgOCBvbmx5XG4vLyBJbiBTYWZhcmkgOCBkb2N1bWVudHMgY3JlYXRlZCB2aWEgZG9jdW1lbnQuaW1wbGVtZW50YXRpb24uY3JlYXRlSFRNTERvY3VtZW50XG4vLyBjb2xsYXBzZSBzaWJsaW5nIGZvcm1zOiB0aGUgc2Vjb25kIG9uZSBiZWNvbWVzIGEgY2hpbGQgb2YgdGhlIGZpcnN0IG9uZS5cbi8vIEJlY2F1c2Ugb2YgdGhhdCwgdGhpcyBzZWN1cml0eSBtZWFzdXJlIGhhcyB0byBiZSBkaXNhYmxlZCBpbiBTYWZhcmkgOC5cbi8vIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xMzczMzdcbnN1cHBvcnQuY3JlYXRlSFRNTERvY3VtZW50ID0gKCBmdW5jdGlvbigpIHtcblx0dmFyIGJvZHkgPSBkb2N1bWVudC5pbXBsZW1lbnRhdGlvbi5jcmVhdGVIVE1MRG9jdW1lbnQoIFwiXCIgKS5ib2R5O1xuXHRib2R5LmlubmVySFRNTCA9IFwiPGZvcm0+PC9mb3JtPjxmb3JtPjwvZm9ybT5cIjtcblx0cmV0dXJuIGJvZHkuY2hpbGROb2Rlcy5sZW5ndGggPT09IDI7XG59ICkoKTtcblxuXG4vLyBBcmd1bWVudCBcImRhdGFcIiBzaG91bGQgYmUgc3RyaW5nIG9mIGh0bWxcbi8vIGNvbnRleHQgKG9wdGlvbmFsKTogSWYgc3BlY2lmaWVkLCB0aGUgZnJhZ21lbnQgd2lsbCBiZSBjcmVhdGVkIGluIHRoaXMgY29udGV4dCxcbi8vIGRlZmF1bHRzIHRvIGRvY3VtZW50XG4vLyBrZWVwU2NyaXB0cyAob3B0aW9uYWwpOiBJZiB0cnVlLCB3aWxsIGluY2x1ZGUgc2NyaXB0cyBwYXNzZWQgaW4gdGhlIGh0bWwgc3RyaW5nXG5qUXVlcnkucGFyc2VIVE1MID0gZnVuY3Rpb24oIGRhdGEsIGNvbnRleHQsIGtlZXBTY3JpcHRzICkge1xuXHRpZiAoIHR5cGVvZiBkYXRhICE9PSBcInN0cmluZ1wiICkge1xuXHRcdHJldHVybiBbXTtcblx0fVxuXHRpZiAoIHR5cGVvZiBjb250ZXh0ID09PSBcImJvb2xlYW5cIiApIHtcblx0XHRrZWVwU2NyaXB0cyA9IGNvbnRleHQ7XG5cdFx0Y29udGV4dCA9IGZhbHNlO1xuXHR9XG5cblx0dmFyIGJhc2UsIHBhcnNlZCwgc2NyaXB0cztcblxuXHRpZiAoICFjb250ZXh0ICkge1xuXG5cdFx0Ly8gU3RvcCBzY3JpcHRzIG9yIGlubGluZSBldmVudCBoYW5kbGVycyBmcm9tIGJlaW5nIGV4ZWN1dGVkIGltbWVkaWF0ZWx5XG5cdFx0Ly8gYnkgdXNpbmcgZG9jdW1lbnQuaW1wbGVtZW50YXRpb25cblx0XHRpZiAoIHN1cHBvcnQuY3JlYXRlSFRNTERvY3VtZW50ICkge1xuXHRcdFx0Y29udGV4dCA9IGRvY3VtZW50LmltcGxlbWVudGF0aW9uLmNyZWF0ZUhUTUxEb2N1bWVudCggXCJcIiApO1xuXG5cdFx0XHQvLyBTZXQgdGhlIGJhc2UgaHJlZiBmb3IgdGhlIGNyZWF0ZWQgZG9jdW1lbnRcblx0XHRcdC8vIHNvIGFueSBwYXJzZWQgZWxlbWVudHMgd2l0aCBVUkxzXG5cdFx0XHQvLyBhcmUgYmFzZWQgb24gdGhlIGRvY3VtZW50J3MgVVJMIChnaC0yOTY1KVxuXHRcdFx0YmFzZSA9IGNvbnRleHQuY3JlYXRlRWxlbWVudCggXCJiYXNlXCIgKTtcblx0XHRcdGJhc2UuaHJlZiA9IGRvY3VtZW50LmxvY2F0aW9uLmhyZWY7XG5cdFx0XHRjb250ZXh0LmhlYWQuYXBwZW5kQ2hpbGQoIGJhc2UgKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29udGV4dCA9IGRvY3VtZW50O1xuXHRcdH1cblx0fVxuXG5cdHBhcnNlZCA9IHJzaW5nbGVUYWcuZXhlYyggZGF0YSApO1xuXHRzY3JpcHRzID0gIWtlZXBTY3JpcHRzICYmIFtdO1xuXG5cdC8vIFNpbmdsZSB0YWdcblx0aWYgKCBwYXJzZWQgKSB7XG5cdFx0cmV0dXJuIFsgY29udGV4dC5jcmVhdGVFbGVtZW50KCBwYXJzZWRbIDEgXSApIF07XG5cdH1cblxuXHRwYXJzZWQgPSBidWlsZEZyYWdtZW50KCBbIGRhdGEgXSwgY29udGV4dCwgc2NyaXB0cyApO1xuXG5cdGlmICggc2NyaXB0cyAmJiBzY3JpcHRzLmxlbmd0aCApIHtcblx0XHRqUXVlcnkoIHNjcmlwdHMgKS5yZW1vdmUoKTtcblx0fVxuXG5cdHJldHVybiBqUXVlcnkubWVyZ2UoIFtdLCBwYXJzZWQuY2hpbGROb2RlcyApO1xufTtcblxuXG4vKipcbiAqIExvYWQgYSB1cmwgaW50byBhIHBhZ2VcbiAqL1xualF1ZXJ5LmZuLmxvYWQgPSBmdW5jdGlvbiggdXJsLCBwYXJhbXMsIGNhbGxiYWNrICkge1xuXHR2YXIgc2VsZWN0b3IsIHR5cGUsIHJlc3BvbnNlLFxuXHRcdHNlbGYgPSB0aGlzLFxuXHRcdG9mZiA9IHVybC5pbmRleE9mKCBcIiBcIiApO1xuXG5cdGlmICggb2ZmID4gLTEgKSB7XG5cdFx0c2VsZWN0b3IgPSBzdHJpcEFuZENvbGxhcHNlKCB1cmwuc2xpY2UoIG9mZiApICk7XG5cdFx0dXJsID0gdXJsLnNsaWNlKCAwLCBvZmYgKTtcblx0fVxuXG5cdC8vIElmIGl0J3MgYSBmdW5jdGlvblxuXHRpZiAoIGpRdWVyeS5pc0Z1bmN0aW9uKCBwYXJhbXMgKSApIHtcblxuXHRcdC8vIFdlIGFzc3VtZSB0aGF0IGl0J3MgdGhlIGNhbGxiYWNrXG5cdFx0Y2FsbGJhY2sgPSBwYXJhbXM7XG5cdFx0cGFyYW1zID0gdW5kZWZpbmVkO1xuXG5cdC8vIE90aGVyd2lzZSwgYnVpbGQgYSBwYXJhbSBzdHJpbmdcblx0fSBlbHNlIGlmICggcGFyYW1zICYmIHR5cGVvZiBwYXJhbXMgPT09IFwib2JqZWN0XCIgKSB7XG5cdFx0dHlwZSA9IFwiUE9TVFwiO1xuXHR9XG5cblx0Ly8gSWYgd2UgaGF2ZSBlbGVtZW50cyB0byBtb2RpZnksIG1ha2UgdGhlIHJlcXVlc3Rcblx0aWYgKCBzZWxmLmxlbmd0aCA+IDAgKSB7XG5cdFx0alF1ZXJ5LmFqYXgoIHtcblx0XHRcdHVybDogdXJsLFxuXG5cdFx0XHQvLyBJZiBcInR5cGVcIiB2YXJpYWJsZSBpcyB1bmRlZmluZWQsIHRoZW4gXCJHRVRcIiBtZXRob2Qgd2lsbCBiZSB1c2VkLlxuXHRcdFx0Ly8gTWFrZSB2YWx1ZSBvZiB0aGlzIGZpZWxkIGV4cGxpY2l0IHNpbmNlXG5cdFx0XHQvLyB1c2VyIGNhbiBvdmVycmlkZSBpdCB0aHJvdWdoIGFqYXhTZXR1cCBtZXRob2Rcblx0XHRcdHR5cGU6IHR5cGUgfHwgXCJHRVRcIixcblx0XHRcdGRhdGFUeXBlOiBcImh0bWxcIixcblx0XHRcdGRhdGE6IHBhcmFtc1xuXHRcdH0gKS5kb25lKCBmdW5jdGlvbiggcmVzcG9uc2VUZXh0ICkge1xuXG5cdFx0XHQvLyBTYXZlIHJlc3BvbnNlIGZvciB1c2UgaW4gY29tcGxldGUgY2FsbGJhY2tcblx0XHRcdHJlc3BvbnNlID0gYXJndW1lbnRzO1xuXG5cdFx0XHRzZWxmLmh0bWwoIHNlbGVjdG9yID9cblxuXHRcdFx0XHQvLyBJZiBhIHNlbGVjdG9yIHdhcyBzcGVjaWZpZWQsIGxvY2F0ZSB0aGUgcmlnaHQgZWxlbWVudHMgaW4gYSBkdW1teSBkaXZcblx0XHRcdFx0Ly8gRXhjbHVkZSBzY3JpcHRzIHRvIGF2b2lkIElFICdQZXJtaXNzaW9uIERlbmllZCcgZXJyb3JzXG5cdFx0XHRcdGpRdWVyeSggXCI8ZGl2PlwiICkuYXBwZW5kKCBqUXVlcnkucGFyc2VIVE1MKCByZXNwb25zZVRleHQgKSApLmZpbmQoIHNlbGVjdG9yICkgOlxuXG5cdFx0XHRcdC8vIE90aGVyd2lzZSB1c2UgdGhlIGZ1bGwgcmVzdWx0XG5cdFx0XHRcdHJlc3BvbnNlVGV4dCApO1xuXG5cdFx0Ly8gSWYgdGhlIHJlcXVlc3Qgc3VjY2VlZHMsIHRoaXMgZnVuY3Rpb24gZ2V0cyBcImRhdGFcIiwgXCJzdGF0dXNcIiwgXCJqcVhIUlwiXG5cdFx0Ly8gYnV0IHRoZXkgYXJlIGlnbm9yZWQgYmVjYXVzZSByZXNwb25zZSB3YXMgc2V0IGFib3ZlLlxuXHRcdC8vIElmIGl0IGZhaWxzLCB0aGlzIGZ1bmN0aW9uIGdldHMgXCJqcVhIUlwiLCBcInN0YXR1c1wiLCBcImVycm9yXCJcblx0XHR9ICkuYWx3YXlzKCBjYWxsYmFjayAmJiBmdW5jdGlvbigganFYSFIsIHN0YXR1cyApIHtcblx0XHRcdHNlbGYuZWFjaCggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGNhbGxiYWNrLmFwcGx5KCB0aGlzLCByZXNwb25zZSB8fCBbIGpxWEhSLnJlc3BvbnNlVGV4dCwgc3RhdHVzLCBqcVhIUiBdICk7XG5cdFx0XHR9ICk7XG5cdFx0fSApO1xuXHR9XG5cblx0cmV0dXJuIHRoaXM7XG59O1xuXG5cblxuXG4vLyBBdHRhY2ggYSBidW5jaCBvZiBmdW5jdGlvbnMgZm9yIGhhbmRsaW5nIGNvbW1vbiBBSkFYIGV2ZW50c1xualF1ZXJ5LmVhY2goIFtcblx0XCJhamF4U3RhcnRcIixcblx0XCJhamF4U3RvcFwiLFxuXHRcImFqYXhDb21wbGV0ZVwiLFxuXHRcImFqYXhFcnJvclwiLFxuXHRcImFqYXhTdWNjZXNzXCIsXG5cdFwiYWpheFNlbmRcIlxuXSwgZnVuY3Rpb24oIGksIHR5cGUgKSB7XG5cdGpRdWVyeS5mblsgdHlwZSBdID0gZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiB0aGlzLm9uKCB0eXBlLCBmbiApO1xuXHR9O1xufSApO1xuXG5cblxuXG5qUXVlcnkuZXhwci5wc2V1ZG9zLmFuaW1hdGVkID0gZnVuY3Rpb24oIGVsZW0gKSB7XG5cdHJldHVybiBqUXVlcnkuZ3JlcCggalF1ZXJ5LnRpbWVycywgZnVuY3Rpb24oIGZuICkge1xuXHRcdHJldHVybiBlbGVtID09PSBmbi5lbGVtO1xuXHR9ICkubGVuZ3RoO1xufTtcblxuXG5cblxualF1ZXJ5Lm9mZnNldCA9IHtcblx0c2V0T2Zmc2V0OiBmdW5jdGlvbiggZWxlbSwgb3B0aW9ucywgaSApIHtcblx0XHR2YXIgY3VyUG9zaXRpb24sIGN1ckxlZnQsIGN1ckNTU1RvcCwgY3VyVG9wLCBjdXJPZmZzZXQsIGN1ckNTU0xlZnQsIGNhbGN1bGF0ZVBvc2l0aW9uLFxuXHRcdFx0cG9zaXRpb24gPSBqUXVlcnkuY3NzKCBlbGVtLCBcInBvc2l0aW9uXCIgKSxcblx0XHRcdGN1ckVsZW0gPSBqUXVlcnkoIGVsZW0gKSxcblx0XHRcdHByb3BzID0ge307XG5cblx0XHQvLyBTZXQgcG9zaXRpb24gZmlyc3QsIGluLWNhc2UgdG9wL2xlZnQgYXJlIHNldCBldmVuIG9uIHN0YXRpYyBlbGVtXG5cdFx0aWYgKCBwb3NpdGlvbiA9PT0gXCJzdGF0aWNcIiApIHtcblx0XHRcdGVsZW0uc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG5cdFx0fVxuXG5cdFx0Y3VyT2Zmc2V0ID0gY3VyRWxlbS5vZmZzZXQoKTtcblx0XHRjdXJDU1NUb3AgPSBqUXVlcnkuY3NzKCBlbGVtLCBcInRvcFwiICk7XG5cdFx0Y3VyQ1NTTGVmdCA9IGpRdWVyeS5jc3MoIGVsZW0sIFwibGVmdFwiICk7XG5cdFx0Y2FsY3VsYXRlUG9zaXRpb24gPSAoIHBvc2l0aW9uID09PSBcImFic29sdXRlXCIgfHwgcG9zaXRpb24gPT09IFwiZml4ZWRcIiApICYmXG5cdFx0XHQoIGN1ckNTU1RvcCArIGN1ckNTU0xlZnQgKS5pbmRleE9mKCBcImF1dG9cIiApID4gLTE7XG5cblx0XHQvLyBOZWVkIHRvIGJlIGFibGUgdG8gY2FsY3VsYXRlIHBvc2l0aW9uIGlmIGVpdGhlclxuXHRcdC8vIHRvcCBvciBsZWZ0IGlzIGF1dG8gYW5kIHBvc2l0aW9uIGlzIGVpdGhlciBhYnNvbHV0ZSBvciBmaXhlZFxuXHRcdGlmICggY2FsY3VsYXRlUG9zaXRpb24gKSB7XG5cdFx0XHRjdXJQb3NpdGlvbiA9IGN1ckVsZW0ucG9zaXRpb24oKTtcblx0XHRcdGN1clRvcCA9IGN1clBvc2l0aW9uLnRvcDtcblx0XHRcdGN1ckxlZnQgPSBjdXJQb3NpdGlvbi5sZWZ0O1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1clRvcCA9IHBhcnNlRmxvYXQoIGN1ckNTU1RvcCApIHx8IDA7XG5cdFx0XHRjdXJMZWZ0ID0gcGFyc2VGbG9hdCggY3VyQ1NTTGVmdCApIHx8IDA7XG5cdFx0fVxuXG5cdFx0aWYgKCBqUXVlcnkuaXNGdW5jdGlvbiggb3B0aW9ucyApICkge1xuXG5cdFx0XHQvLyBVc2UgalF1ZXJ5LmV4dGVuZCBoZXJlIHRvIGFsbG93IG1vZGlmaWNhdGlvbiBvZiBjb29yZGluYXRlcyBhcmd1bWVudCAoZ2gtMTg0OClcblx0XHRcdG9wdGlvbnMgPSBvcHRpb25zLmNhbGwoIGVsZW0sIGksIGpRdWVyeS5leHRlbmQoIHt9LCBjdXJPZmZzZXQgKSApO1xuXHRcdH1cblxuXHRcdGlmICggb3B0aW9ucy50b3AgIT0gbnVsbCApIHtcblx0XHRcdHByb3BzLnRvcCA9ICggb3B0aW9ucy50b3AgLSBjdXJPZmZzZXQudG9wICkgKyBjdXJUb3A7XG5cdFx0fVxuXHRcdGlmICggb3B0aW9ucy5sZWZ0ICE9IG51bGwgKSB7XG5cdFx0XHRwcm9wcy5sZWZ0ID0gKCBvcHRpb25zLmxlZnQgLSBjdXJPZmZzZXQubGVmdCApICsgY3VyTGVmdDtcblx0XHR9XG5cblx0XHRpZiAoIFwidXNpbmdcIiBpbiBvcHRpb25zICkge1xuXHRcdFx0b3B0aW9ucy51c2luZy5jYWxsKCBlbGVtLCBwcm9wcyApO1xuXG5cdFx0fSBlbHNlIHtcblx0XHRcdGN1ckVsZW0uY3NzKCBwcm9wcyApO1xuXHRcdH1cblx0fVxufTtcblxualF1ZXJ5LmZuLmV4dGVuZCgge1xuXHRvZmZzZXQ6IGZ1bmN0aW9uKCBvcHRpb25zICkge1xuXG5cdFx0Ly8gUHJlc2VydmUgY2hhaW5pbmcgZm9yIHNldHRlclxuXHRcdGlmICggYXJndW1lbnRzLmxlbmd0aCApIHtcblx0XHRcdHJldHVybiBvcHRpb25zID09PSB1bmRlZmluZWQgP1xuXHRcdFx0XHR0aGlzIDpcblx0XHRcdFx0dGhpcy5lYWNoKCBmdW5jdGlvbiggaSApIHtcblx0XHRcdFx0XHRqUXVlcnkub2Zmc2V0LnNldE9mZnNldCggdGhpcywgb3B0aW9ucywgaSApO1xuXHRcdFx0XHR9ICk7XG5cdFx0fVxuXG5cdFx0dmFyIGRvYywgZG9jRWxlbSwgcmVjdCwgd2luLFxuXHRcdFx0ZWxlbSA9IHRoaXNbIDAgXTtcblxuXHRcdGlmICggIWVsZW0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Ly8gUmV0dXJuIHplcm9zIGZvciBkaXNjb25uZWN0ZWQgYW5kIGhpZGRlbiAoZGlzcGxheTogbm9uZSkgZWxlbWVudHMgKGdoLTIzMTApXG5cdFx0Ly8gU3VwcG9ydDogSUUgPD0xMSBvbmx5XG5cdFx0Ly8gUnVubmluZyBnZXRCb3VuZGluZ0NsaWVudFJlY3Qgb24gYVxuXHRcdC8vIGRpc2Nvbm5lY3RlZCBub2RlIGluIElFIHRocm93cyBhbiBlcnJvclxuXHRcdGlmICggIWVsZW0uZ2V0Q2xpZW50UmVjdHMoKS5sZW5ndGggKSB7XG5cdFx0XHRyZXR1cm4geyB0b3A6IDAsIGxlZnQ6IDAgfTtcblx0XHR9XG5cblx0XHRyZWN0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdGRvYyA9IGVsZW0ub3duZXJEb2N1bWVudDtcblx0XHRkb2NFbGVtID0gZG9jLmRvY3VtZW50RWxlbWVudDtcblx0XHR3aW4gPSBkb2MuZGVmYXVsdFZpZXc7XG5cblx0XHRyZXR1cm4ge1xuXHRcdFx0dG9wOiByZWN0LnRvcCArIHdpbi5wYWdlWU9mZnNldCAtIGRvY0VsZW0uY2xpZW50VG9wLFxuXHRcdFx0bGVmdDogcmVjdC5sZWZ0ICsgd2luLnBhZ2VYT2Zmc2V0IC0gZG9jRWxlbS5jbGllbnRMZWZ0XG5cdFx0fTtcblx0fSxcblxuXHRwb3NpdGlvbjogZnVuY3Rpb24oKSB7XG5cdFx0aWYgKCAhdGhpc1sgMCBdICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHZhciBvZmZzZXRQYXJlbnQsIG9mZnNldCxcblx0XHRcdGVsZW0gPSB0aGlzWyAwIF0sXG5cdFx0XHRwYXJlbnRPZmZzZXQgPSB7IHRvcDogMCwgbGVmdDogMCB9O1xuXG5cdFx0Ly8gRml4ZWQgZWxlbWVudHMgYXJlIG9mZnNldCBmcm9tIHdpbmRvdyAocGFyZW50T2Zmc2V0ID0ge3RvcDowLCBsZWZ0OiAwfSxcblx0XHQvLyBiZWNhdXNlIGl0IGlzIGl0cyBvbmx5IG9mZnNldCBwYXJlbnRcblx0XHRpZiAoIGpRdWVyeS5jc3MoIGVsZW0sIFwicG9zaXRpb25cIiApID09PSBcImZpeGVkXCIgKSB7XG5cblx0XHRcdC8vIEFzc3VtZSBnZXRCb3VuZGluZ0NsaWVudFJlY3QgaXMgdGhlcmUgd2hlbiBjb21wdXRlZCBwb3NpdGlvbiBpcyBmaXhlZFxuXHRcdFx0b2Zmc2V0ID0gZWxlbS5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdH0gZWxzZSB7XG5cblx0XHRcdC8vIEdldCAqcmVhbCogb2Zmc2V0UGFyZW50XG5cdFx0XHRvZmZzZXRQYXJlbnQgPSB0aGlzLm9mZnNldFBhcmVudCgpO1xuXG5cdFx0XHQvLyBHZXQgY29ycmVjdCBvZmZzZXRzXG5cdFx0XHRvZmZzZXQgPSB0aGlzLm9mZnNldCgpO1xuXHRcdFx0aWYgKCAhbm9kZU5hbWUoIG9mZnNldFBhcmVudFsgMCBdLCBcImh0bWxcIiApICkge1xuXHRcdFx0XHRwYXJlbnRPZmZzZXQgPSBvZmZzZXRQYXJlbnQub2Zmc2V0KCk7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEFkZCBvZmZzZXRQYXJlbnQgYm9yZGVyc1xuXHRcdFx0cGFyZW50T2Zmc2V0ID0ge1xuXHRcdFx0XHR0b3A6IHBhcmVudE9mZnNldC50b3AgKyBqUXVlcnkuY3NzKCBvZmZzZXRQYXJlbnRbIDAgXSwgXCJib3JkZXJUb3BXaWR0aFwiLCB0cnVlICksXG5cdFx0XHRcdGxlZnQ6IHBhcmVudE9mZnNldC5sZWZ0ICsgalF1ZXJ5LmNzcyggb2Zmc2V0UGFyZW50WyAwIF0sIFwiYm9yZGVyTGVmdFdpZHRoXCIsIHRydWUgKVxuXHRcdFx0fTtcblx0XHR9XG5cblx0XHQvLyBTdWJ0cmFjdCBwYXJlbnQgb2Zmc2V0cyBhbmQgZWxlbWVudCBtYXJnaW5zXG5cdFx0cmV0dXJuIHtcblx0XHRcdHRvcDogb2Zmc2V0LnRvcCAtIHBhcmVudE9mZnNldC50b3AgLSBqUXVlcnkuY3NzKCBlbGVtLCBcIm1hcmdpblRvcFwiLCB0cnVlICksXG5cdFx0XHRsZWZ0OiBvZmZzZXQubGVmdCAtIHBhcmVudE9mZnNldC5sZWZ0IC0galF1ZXJ5LmNzcyggZWxlbSwgXCJtYXJnaW5MZWZ0XCIsIHRydWUgKVxuXHRcdH07XG5cdH0sXG5cblx0Ly8gVGhpcyBtZXRob2Qgd2lsbCByZXR1cm4gZG9jdW1lbnRFbGVtZW50IGluIHRoZSBmb2xsb3dpbmcgY2FzZXM6XG5cdC8vIDEpIEZvciB0aGUgZWxlbWVudCBpbnNpZGUgdGhlIGlmcmFtZSB3aXRob3V0IG9mZnNldFBhcmVudCwgdGhpcyBtZXRob2Qgd2lsbCByZXR1cm5cblx0Ly8gICAgZG9jdW1lbnRFbGVtZW50IG9mIHRoZSBwYXJlbnQgd2luZG93XG5cdC8vIDIpIEZvciB0aGUgaGlkZGVuIG9yIGRldGFjaGVkIGVsZW1lbnRcblx0Ly8gMykgRm9yIGJvZHkgb3IgaHRtbCBlbGVtZW50LCBpLmUuIGluIGNhc2Ugb2YgdGhlIGh0bWwgbm9kZSAtIGl0IHdpbGwgcmV0dXJuIGl0c2VsZlxuXHQvL1xuXHQvLyBidXQgdGhvc2UgZXhjZXB0aW9ucyB3ZXJlIG5ldmVyIHByZXNlbnRlZCBhcyBhIHJlYWwgbGlmZSB1c2UtY2FzZXNcblx0Ly8gYW5kIG1pZ2h0IGJlIGNvbnNpZGVyZWQgYXMgbW9yZSBwcmVmZXJhYmxlIHJlc3VsdHMuXG5cdC8vXG5cdC8vIFRoaXMgbG9naWMsIGhvd2V2ZXIsIGlzIG5vdCBndWFyYW50ZWVkIGFuZCBjYW4gY2hhbmdlIGF0IGFueSBwb2ludCBpbiB0aGUgZnV0dXJlXG5cdG9mZnNldFBhcmVudDogZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbigpIHtcblx0XHRcdHZhciBvZmZzZXRQYXJlbnQgPSB0aGlzLm9mZnNldFBhcmVudDtcblxuXHRcdFx0d2hpbGUgKCBvZmZzZXRQYXJlbnQgJiYgalF1ZXJ5LmNzcyggb2Zmc2V0UGFyZW50LCBcInBvc2l0aW9uXCIgKSA9PT0gXCJzdGF0aWNcIiApIHtcblx0XHRcdFx0b2Zmc2V0UGFyZW50ID0gb2Zmc2V0UGFyZW50Lm9mZnNldFBhcmVudDtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIG9mZnNldFBhcmVudCB8fCBkb2N1bWVudEVsZW1lbnQ7XG5cdFx0fSApO1xuXHR9XG59ICk7XG5cbi8vIENyZWF0ZSBzY3JvbGxMZWZ0IGFuZCBzY3JvbGxUb3AgbWV0aG9kc1xualF1ZXJ5LmVhY2goIHsgc2Nyb2xsTGVmdDogXCJwYWdlWE9mZnNldFwiLCBzY3JvbGxUb3A6IFwicGFnZVlPZmZzZXRcIiB9LCBmdW5jdGlvbiggbWV0aG9kLCBwcm9wICkge1xuXHR2YXIgdG9wID0gXCJwYWdlWU9mZnNldFwiID09PSBwcm9wO1xuXG5cdGpRdWVyeS5mblsgbWV0aG9kIF0gPSBmdW5jdGlvbiggdmFsICkge1xuXHRcdHJldHVybiBhY2Nlc3MoIHRoaXMsIGZ1bmN0aW9uKCBlbGVtLCBtZXRob2QsIHZhbCApIHtcblxuXHRcdFx0Ly8gQ29hbGVzY2UgZG9jdW1lbnRzIGFuZCB3aW5kb3dzXG5cdFx0XHR2YXIgd2luO1xuXHRcdFx0aWYgKCBqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblx0XHRcdFx0d2luID0gZWxlbTtcblx0XHRcdH0gZWxzZSBpZiAoIGVsZW0ubm9kZVR5cGUgPT09IDkgKSB7XG5cdFx0XHRcdHdpbiA9IGVsZW0uZGVmYXVsdFZpZXc7XG5cdFx0XHR9XG5cblx0XHRcdGlmICggdmFsID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHJldHVybiB3aW4gPyB3aW5bIHByb3AgXSA6IGVsZW1bIG1ldGhvZCBdO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHdpbiApIHtcblx0XHRcdFx0d2luLnNjcm9sbFRvKFxuXHRcdFx0XHRcdCF0b3AgPyB2YWwgOiB3aW4ucGFnZVhPZmZzZXQsXG5cdFx0XHRcdFx0dG9wID8gdmFsIDogd2luLnBhZ2VZT2Zmc2V0XG5cdFx0XHRcdCk7XG5cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGVsZW1bIG1ldGhvZCBdID0gdmFsO1xuXHRcdFx0fVxuXHRcdH0sIG1ldGhvZCwgdmFsLCBhcmd1bWVudHMubGVuZ3RoICk7XG5cdH07XG59ICk7XG5cbi8vIFN1cHBvcnQ6IFNhZmFyaSA8PTcgLSA5LjEsIENocm9tZSA8PTM3IC0gNDlcbi8vIEFkZCB0aGUgdG9wL2xlZnQgY3NzSG9va3MgdXNpbmcgalF1ZXJ5LmZuLnBvc2l0aW9uXG4vLyBXZWJraXQgYnVnOiBodHRwczovL2J1Z3Mud2Via2l0Lm9yZy9zaG93X2J1Zy5jZ2k/aWQ9MjkwODRcbi8vIEJsaW5rIGJ1ZzogaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9NTg5MzQ3XG4vLyBnZXRDb21wdXRlZFN0eWxlIHJldHVybnMgcGVyY2VudCB3aGVuIHNwZWNpZmllZCBmb3IgdG9wL2xlZnQvYm90dG9tL3JpZ2h0O1xuLy8gcmF0aGVyIHRoYW4gbWFrZSB0aGUgY3NzIG1vZHVsZSBkZXBlbmQgb24gdGhlIG9mZnNldCBtb2R1bGUsIGp1c3QgY2hlY2sgZm9yIGl0IGhlcmVcbmpRdWVyeS5lYWNoKCBbIFwidG9wXCIsIFwibGVmdFwiIF0sIGZ1bmN0aW9uKCBpLCBwcm9wICkge1xuXHRqUXVlcnkuY3NzSG9va3NbIHByb3AgXSA9IGFkZEdldEhvb2tJZiggc3VwcG9ydC5waXhlbFBvc2l0aW9uLFxuXHRcdGZ1bmN0aW9uKCBlbGVtLCBjb21wdXRlZCApIHtcblx0XHRcdGlmICggY29tcHV0ZWQgKSB7XG5cdFx0XHRcdGNvbXB1dGVkID0gY3VyQ1NTKCBlbGVtLCBwcm9wICk7XG5cblx0XHRcdFx0Ly8gSWYgY3VyQ1NTIHJldHVybnMgcGVyY2VudGFnZSwgZmFsbGJhY2sgdG8gb2Zmc2V0XG5cdFx0XHRcdHJldHVybiBybnVtbm9ucHgudGVzdCggY29tcHV0ZWQgKSA/XG5cdFx0XHRcdFx0alF1ZXJ5KCBlbGVtICkucG9zaXRpb24oKVsgcHJvcCBdICsgXCJweFwiIDpcblx0XHRcdFx0XHRjb21wdXRlZDtcblx0XHRcdH1cblx0XHR9XG5cdCk7XG59ICk7XG5cblxuLy8gQ3JlYXRlIGlubmVySGVpZ2h0LCBpbm5lcldpZHRoLCBoZWlnaHQsIHdpZHRoLCBvdXRlckhlaWdodCBhbmQgb3V0ZXJXaWR0aCBtZXRob2RzXG5qUXVlcnkuZWFjaCggeyBIZWlnaHQ6IFwiaGVpZ2h0XCIsIFdpZHRoOiBcIndpZHRoXCIgfSwgZnVuY3Rpb24oIG5hbWUsIHR5cGUgKSB7XG5cdGpRdWVyeS5lYWNoKCB7IHBhZGRpbmc6IFwiaW5uZXJcIiArIG5hbWUsIGNvbnRlbnQ6IHR5cGUsIFwiXCI6IFwib3V0ZXJcIiArIG5hbWUgfSxcblx0XHRmdW5jdGlvbiggZGVmYXVsdEV4dHJhLCBmdW5jTmFtZSApIHtcblxuXHRcdC8vIE1hcmdpbiBpcyBvbmx5IGZvciBvdXRlckhlaWdodCwgb3V0ZXJXaWR0aFxuXHRcdGpRdWVyeS5mblsgZnVuY05hbWUgXSA9IGZ1bmN0aW9uKCBtYXJnaW4sIHZhbHVlICkge1xuXHRcdFx0dmFyIGNoYWluYWJsZSA9IGFyZ3VtZW50cy5sZW5ndGggJiYgKCBkZWZhdWx0RXh0cmEgfHwgdHlwZW9mIG1hcmdpbiAhPT0gXCJib29sZWFuXCIgKSxcblx0XHRcdFx0ZXh0cmEgPSBkZWZhdWx0RXh0cmEgfHwgKCBtYXJnaW4gPT09IHRydWUgfHwgdmFsdWUgPT09IHRydWUgPyBcIm1hcmdpblwiIDogXCJib3JkZXJcIiApO1xuXG5cdFx0XHRyZXR1cm4gYWNjZXNzKCB0aGlzLCBmdW5jdGlvbiggZWxlbSwgdHlwZSwgdmFsdWUgKSB7XG5cdFx0XHRcdHZhciBkb2M7XG5cblx0XHRcdFx0aWYgKCBqUXVlcnkuaXNXaW5kb3coIGVsZW0gKSApIHtcblxuXHRcdFx0XHRcdC8vICQoIHdpbmRvdyApLm91dGVyV2lkdGgvSGVpZ2h0IHJldHVybiB3L2ggaW5jbHVkaW5nIHNjcm9sbGJhcnMgKGdoLTE3MjkpXG5cdFx0XHRcdFx0cmV0dXJuIGZ1bmNOYW1lLmluZGV4T2YoIFwib3V0ZXJcIiApID09PSAwID9cblx0XHRcdFx0XHRcdGVsZW1bIFwiaW5uZXJcIiArIG5hbWUgXSA6XG5cdFx0XHRcdFx0XHRlbGVtLmRvY3VtZW50LmRvY3VtZW50RWxlbWVudFsgXCJjbGllbnRcIiArIG5hbWUgXTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEdldCBkb2N1bWVudCB3aWR0aCBvciBoZWlnaHRcblx0XHRcdFx0aWYgKCBlbGVtLm5vZGVUeXBlID09PSA5ICkge1xuXHRcdFx0XHRcdGRvYyA9IGVsZW0uZG9jdW1lbnRFbGVtZW50O1xuXG5cdFx0XHRcdFx0Ly8gRWl0aGVyIHNjcm9sbFtXaWR0aC9IZWlnaHRdIG9yIG9mZnNldFtXaWR0aC9IZWlnaHRdIG9yIGNsaWVudFtXaWR0aC9IZWlnaHRdLFxuXHRcdFx0XHRcdC8vIHdoaWNoZXZlciBpcyBncmVhdGVzdFxuXHRcdFx0XHRcdHJldHVybiBNYXRoLm1heChcblx0XHRcdFx0XHRcdGVsZW0uYm9keVsgXCJzY3JvbGxcIiArIG5hbWUgXSwgZG9jWyBcInNjcm9sbFwiICsgbmFtZSBdLFxuXHRcdFx0XHRcdFx0ZWxlbS5ib2R5WyBcIm9mZnNldFwiICsgbmFtZSBdLCBkb2NbIFwib2Zmc2V0XCIgKyBuYW1lIF0sXG5cdFx0XHRcdFx0XHRkb2NbIFwiY2xpZW50XCIgKyBuYW1lIF1cblx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0cmV0dXJuIHZhbHVlID09PSB1bmRlZmluZWQgP1xuXG5cdFx0XHRcdFx0Ly8gR2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudCwgcmVxdWVzdGluZyBidXQgbm90IGZvcmNpbmcgcGFyc2VGbG9hdFxuXHRcdFx0XHRcdGpRdWVyeS5jc3MoIGVsZW0sIHR5cGUsIGV4dHJhICkgOlxuXG5cdFx0XHRcdFx0Ly8gU2V0IHdpZHRoIG9yIGhlaWdodCBvbiB0aGUgZWxlbWVudFxuXHRcdFx0XHRcdGpRdWVyeS5zdHlsZSggZWxlbSwgdHlwZSwgdmFsdWUsIGV4dHJhICk7XG5cdFx0XHR9LCB0eXBlLCBjaGFpbmFibGUgPyBtYXJnaW4gOiB1bmRlZmluZWQsIGNoYWluYWJsZSApO1xuXHRcdH07XG5cdH0gKTtcbn0gKTtcblxuXG5qUXVlcnkuZm4uZXh0ZW5kKCB7XG5cblx0YmluZDogZnVuY3Rpb24oIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIG51bGwsIGRhdGEsIGZuICk7XG5cdH0sXG5cdHVuYmluZDogZnVuY3Rpb24oIHR5cGVzLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vZmYoIHR5cGVzLCBudWxsLCBmbiApO1xuXHR9LFxuXG5cdGRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBkYXRhLCBmbiApIHtcblx0XHRyZXR1cm4gdGhpcy5vbiggdHlwZXMsIHNlbGVjdG9yLCBkYXRhLCBmbiApO1xuXHR9LFxuXHR1bmRlbGVnYXRlOiBmdW5jdGlvbiggc2VsZWN0b3IsIHR5cGVzLCBmbiApIHtcblxuXHRcdC8vICggbmFtZXNwYWNlICkgb3IgKCBzZWxlY3RvciwgdHlwZXMgWywgZm5dIClcblx0XHRyZXR1cm4gYXJndW1lbnRzLmxlbmd0aCA9PT0gMSA/XG5cdFx0XHR0aGlzLm9mZiggc2VsZWN0b3IsIFwiKipcIiApIDpcblx0XHRcdHRoaXMub2ZmKCB0eXBlcywgc2VsZWN0b3IgfHwgXCIqKlwiLCBmbiApO1xuXHR9XG59ICk7XG5cbmpRdWVyeS5ob2xkUmVhZHkgPSBmdW5jdGlvbiggaG9sZCApIHtcblx0aWYgKCBob2xkICkge1xuXHRcdGpRdWVyeS5yZWFkeVdhaXQrKztcblx0fSBlbHNlIHtcblx0XHRqUXVlcnkucmVhZHkoIHRydWUgKTtcblx0fVxufTtcbmpRdWVyeS5pc0FycmF5ID0gQXJyYXkuaXNBcnJheTtcbmpRdWVyeS5wYXJzZUpTT04gPSBKU09OLnBhcnNlO1xualF1ZXJ5Lm5vZGVOYW1lID0gbm9kZU5hbWU7XG5cblxuXG5cbi8vIFJlZ2lzdGVyIGFzIGEgbmFtZWQgQU1EIG1vZHVsZSwgc2luY2UgalF1ZXJ5IGNhbiBiZSBjb25jYXRlbmF0ZWQgd2l0aCBvdGhlclxuLy8gZmlsZXMgdGhhdCBtYXkgdXNlIGRlZmluZSwgYnV0IG5vdCB2aWEgYSBwcm9wZXIgY29uY2F0ZW5hdGlvbiBzY3JpcHQgdGhhdFxuLy8gdW5kZXJzdGFuZHMgYW5vbnltb3VzIEFNRCBtb2R1bGVzLiBBIG5hbWVkIEFNRCBpcyBzYWZlc3QgYW5kIG1vc3Qgcm9idXN0XG4vLyB3YXkgdG8gcmVnaXN0ZXIuIExvd2VyY2FzZSBqcXVlcnkgaXMgdXNlZCBiZWNhdXNlIEFNRCBtb2R1bGUgbmFtZXMgYXJlXG4vLyBkZXJpdmVkIGZyb20gZmlsZSBuYW1lcywgYW5kIGpRdWVyeSBpcyBub3JtYWxseSBkZWxpdmVyZWQgaW4gYSBsb3dlcmNhc2Vcbi8vIGZpbGUgbmFtZS4gRG8gdGhpcyBhZnRlciBjcmVhdGluZyB0aGUgZ2xvYmFsIHNvIHRoYXQgaWYgYW4gQU1EIG1vZHVsZSB3YW50c1xuLy8gdG8gY2FsbCBub0NvbmZsaWN0IHRvIGhpZGUgdGhpcyB2ZXJzaW9uIG9mIGpRdWVyeSwgaXQgd2lsbCB3b3JrLlxuXG4vLyBOb3RlIHRoYXQgZm9yIG1heGltdW0gcG9ydGFiaWxpdHksIGxpYnJhcmllcyB0aGF0IGFyZSBub3QgalF1ZXJ5IHNob3VsZFxuLy8gZGVjbGFyZSB0aGVtc2VsdmVzIGFzIGFub255bW91cyBtb2R1bGVzLCBhbmQgYXZvaWQgc2V0dGluZyBhIGdsb2JhbCBpZiBhblxuLy8gQU1EIGxvYWRlciBpcyBwcmVzZW50LiBqUXVlcnkgaXMgYSBzcGVjaWFsIGNhc2UuIEZvciBtb3JlIGluZm9ybWF0aW9uLCBzZWVcbi8vIGh0dHBzOi8vZ2l0aHViLmNvbS9qcmJ1cmtlL3JlcXVpcmVqcy93aWtpL1VwZGF0aW5nLWV4aXN0aW5nLWxpYnJhcmllcyN3aWtpLWFub25cblxuaWYgKCB0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCApIHtcblx0ZGVmaW5lKCBcImpxdWVyeVwiLCBbXSwgZnVuY3Rpb24oKSB7XG5cdFx0cmV0dXJuIGpRdWVyeTtcblx0fSApO1xufVxuXG5cblxuXG52YXJcblxuXHQvLyBNYXAgb3ZlciBqUXVlcnkgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0X2pRdWVyeSA9IHdpbmRvdy5qUXVlcnksXG5cblx0Ly8gTWFwIG92ZXIgdGhlICQgaW4gY2FzZSBvZiBvdmVyd3JpdGVcblx0XyQgPSB3aW5kb3cuJDtcblxualF1ZXJ5Lm5vQ29uZmxpY3QgPSBmdW5jdGlvbiggZGVlcCApIHtcblx0aWYgKCB3aW5kb3cuJCA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy4kID0gXyQ7XG5cdH1cblxuXHRpZiAoIGRlZXAgJiYgd2luZG93LmpRdWVyeSA9PT0galF1ZXJ5ICkge1xuXHRcdHdpbmRvdy5qUXVlcnkgPSBfalF1ZXJ5O1xuXHR9XG5cblx0cmV0dXJuIGpRdWVyeTtcbn07XG5cbi8vIEV4cG9zZSBqUXVlcnkgYW5kICQgaWRlbnRpZmllcnMsIGV2ZW4gaW4gQU1EXG4vLyAoIzcxMDIjY29tbWVudDoxMCwgaHR0cHM6Ly9naXRodWIuY29tL2pxdWVyeS9qcXVlcnkvcHVsbC81NTcpXG4vLyBhbmQgQ29tbW9uSlMgZm9yIGJyb3dzZXIgZW11bGF0b3JzICgjMTM1NjYpXG5pZiAoICFub0dsb2JhbCApIHtcblx0d2luZG93LmpRdWVyeSA9IHdpbmRvdy4kID0galF1ZXJ5O1xufVxuXG5cblxuXG5yZXR1cm4galF1ZXJ5O1xufSApO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvanF1ZXJ5L2Rpc3QvanF1ZXJ5LmpzXG4vLyBtb2R1bGUgaWQgPSAxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qKiFcbiAqIEBmaWxlT3ZlcnZpZXcgS2lja2FzcyBsaWJyYXJ5IHRvIGNyZWF0ZSBhbmQgcGxhY2UgcG9wcGVycyBuZWFyIHRoZWlyIHJlZmVyZW5jZSBlbGVtZW50cy5cbiAqIEB2ZXJzaW9uIDEuMTMuMFxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAoYykgMjAxNiBGZWRlcmljbyBaaXZvbG8gYW5kIGNvbnRyaWJ1dG9yc1xuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbiAqIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbiAqIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbiAqIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuICogZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbiBhbGxcbiAqIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuICogSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4gKiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbiAqIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcbiAqIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXG4gKiBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRVxuICogU09GVFdBUkUuXG4gKi9cbnZhciBpc0Jyb3dzZXIgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xudmFyIGxvbmdlclRpbWVvdXRCcm93c2VycyA9IFsnRWRnZScsICdUcmlkZW50JywgJ0ZpcmVmb3gnXTtcbnZhciB0aW1lb3V0RHVyYXRpb24gPSAwO1xuZm9yICh2YXIgaSA9IDA7IGkgPCBsb25nZXJUaW1lb3V0QnJvd3NlcnMubGVuZ3RoOyBpICs9IDEpIHtcbiAgaWYgKGlzQnJvd3NlciAmJiBuYXZpZ2F0b3IudXNlckFnZW50LmluZGV4T2YobG9uZ2VyVGltZW91dEJyb3dzZXJzW2ldKSA+PSAwKSB7XG4gICAgdGltZW91dER1cmF0aW9uID0gMTtcbiAgICBicmVhaztcbiAgfVxufVxuXG5mdW5jdGlvbiBtaWNyb3Rhc2tEZWJvdW5jZShmbikge1xuICB2YXIgY2FsbGVkID0gZmFsc2U7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKGNhbGxlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjYWxsZWQgPSB0cnVlO1xuICAgIHdpbmRvdy5Qcm9taXNlLnJlc29sdmUoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxlZCA9IGZhbHNlO1xuICAgICAgZm4oKTtcbiAgICB9KTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdGFza0RlYm91bmNlKGZuKSB7XG4gIHZhciBzY2hlZHVsZWQgPSBmYWxzZTtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXNjaGVkdWxlZCkge1xuICAgICAgc2NoZWR1bGVkID0gdHJ1ZTtcbiAgICAgIHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBzY2hlZHVsZWQgPSBmYWxzZTtcbiAgICAgICAgZm4oKTtcbiAgICAgIH0sIHRpbWVvdXREdXJhdGlvbik7XG4gICAgfVxuICB9O1xufVxuXG52YXIgc3VwcG9ydHNNaWNyb1Rhc2tzID0gaXNCcm93c2VyICYmIHdpbmRvdy5Qcm9taXNlO1xuXG4vKipcbiogQ3JlYXRlIGEgZGVib3VuY2VkIHZlcnNpb24gb2YgYSBtZXRob2QsIHRoYXQncyBhc3luY2hyb25vdXNseSBkZWZlcnJlZFxuKiBidXQgY2FsbGVkIGluIHRoZSBtaW5pbXVtIHRpbWUgcG9zc2libGUuXG4qXG4qIEBtZXRob2RcbiogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuKiBAYXJndW1lbnQge0Z1bmN0aW9ufSBmblxuKiBAcmV0dXJucyB7RnVuY3Rpb259XG4qL1xudmFyIGRlYm91bmNlID0gc3VwcG9ydHNNaWNyb1Rhc2tzID8gbWljcm90YXNrRGVib3VuY2UgOiB0YXNrRGVib3VuY2U7XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIGdpdmVuIHZhcmlhYmxlIGlzIGEgZnVuY3Rpb25cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7QW55fSBmdW5jdGlvblRvQ2hlY2sgLSB2YXJpYWJsZSB0byBjaGVja1xuICogQHJldHVybnMge0Jvb2xlYW59IGFuc3dlciB0bzogaXMgYSBmdW5jdGlvbj9cbiAqL1xuZnVuY3Rpb24gaXNGdW5jdGlvbihmdW5jdGlvblRvQ2hlY2spIHtcbiAgdmFyIGdldFR5cGUgPSB7fTtcbiAgcmV0dXJuIGZ1bmN0aW9uVG9DaGVjayAmJiBnZXRUeXBlLnRvU3RyaW5nLmNhbGwoZnVuY3Rpb25Ub0NoZWNrKSA9PT0gJ1tvYmplY3QgRnVuY3Rpb25dJztcbn1cblxuLyoqXG4gKiBHZXQgQ1NTIGNvbXB1dGVkIHByb3BlcnR5IG9mIHRoZSBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VlbWVudH0gZWxlbWVudFxuICogQGFyZ3VtZW50IHtTdHJpbmd9IHByb3BlcnR5XG4gKi9cbmZ1bmN0aW9uIGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eShlbGVtZW50LCBwcm9wZXJ0eSkge1xuICBpZiAoZWxlbWVudC5ub2RlVHlwZSAhPT0gMSkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICAvLyBOT1RFOiAxIERPTSBhY2Nlc3MgaGVyZVxuICB2YXIgY3NzID0gZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50LCBudWxsKTtcbiAgcmV0dXJuIHByb3BlcnR5ID8gY3NzW3Byb3BlcnR5XSA6IGNzcztcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBwYXJlbnROb2RlIG9yIHRoZSBob3N0IG9mIHRoZSBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBwYXJlbnRcbiAqL1xuZnVuY3Rpb24gZ2V0UGFyZW50Tm9kZShlbGVtZW50KSB7XG4gIGlmIChlbGVtZW50Lm5vZGVOYW1lID09PSAnSFRNTCcpIHtcbiAgICByZXR1cm4gZWxlbWVudDtcbiAgfVxuICByZXR1cm4gZWxlbWVudC5wYXJlbnROb2RlIHx8IGVsZW1lbnQuaG9zdDtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzY3JvbGxpbmcgcGFyZW50IG9mIHRoZSBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBzY3JvbGwgcGFyZW50XG4gKi9cbmZ1bmN0aW9uIGdldFNjcm9sbFBhcmVudChlbGVtZW50KSB7XG4gIC8vIFJldHVybiBib2R5LCBgZ2V0U2Nyb2xsYCB3aWxsIHRha2UgY2FyZSB0byBnZXQgdGhlIGNvcnJlY3QgYHNjcm9sbFRvcGAgZnJvbSBpdFxuICBpZiAoIWVsZW1lbnQpIHtcbiAgICByZXR1cm4gZG9jdW1lbnQuYm9keTtcbiAgfVxuXG4gIHN3aXRjaCAoZWxlbWVudC5ub2RlTmFtZSkge1xuICAgIGNhc2UgJ0hUTUwnOlxuICAgIGNhc2UgJ0JPRFknOlxuICAgICAgcmV0dXJuIGVsZW1lbnQub3duZXJEb2N1bWVudC5ib2R5O1xuICAgIGNhc2UgJyNkb2N1bWVudCc6XG4gICAgICByZXR1cm4gZWxlbWVudC5ib2R5O1xuICB9XG5cbiAgLy8gRmlyZWZveCB3YW50IHVzIHRvIGNoZWNrIGAteGAgYW5kIGAteWAgdmFyaWF0aW9ucyBhcyB3ZWxsXG5cbiAgdmFyIF9nZXRTdHlsZUNvbXB1dGVkUHJvcCA9IGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eShlbGVtZW50KSxcbiAgICAgIG92ZXJmbG93ID0gX2dldFN0eWxlQ29tcHV0ZWRQcm9wLm92ZXJmbG93LFxuICAgICAgb3ZlcmZsb3dYID0gX2dldFN0eWxlQ29tcHV0ZWRQcm9wLm92ZXJmbG93WCxcbiAgICAgIG92ZXJmbG93WSA9IF9nZXRTdHlsZUNvbXB1dGVkUHJvcC5vdmVyZmxvd1k7XG5cbiAgaWYgKC8oYXV0b3xzY3JvbGwpLy50ZXN0KG92ZXJmbG93ICsgb3ZlcmZsb3dZICsgb3ZlcmZsb3dYKSkge1xuICAgIHJldHVybiBlbGVtZW50O1xuICB9XG5cbiAgcmV0dXJuIGdldFNjcm9sbFBhcmVudChnZXRQYXJlbnROb2RlKGVsZW1lbnQpKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBvZmZzZXQgcGFyZW50IG9mIHRoZSBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBvZmZzZXQgcGFyZW50XG4gKi9cbmZ1bmN0aW9uIGdldE9mZnNldFBhcmVudChlbGVtZW50KSB7XG4gIC8vIE5PVEU6IDEgRE9NIGFjY2VzcyBoZXJlXG4gIHZhciBvZmZzZXRQYXJlbnQgPSBlbGVtZW50ICYmIGVsZW1lbnQub2Zmc2V0UGFyZW50O1xuICB2YXIgbm9kZU5hbWUgPSBvZmZzZXRQYXJlbnQgJiYgb2Zmc2V0UGFyZW50Lm5vZGVOYW1lO1xuXG4gIGlmICghbm9kZU5hbWUgfHwgbm9kZU5hbWUgPT09ICdCT0RZJyB8fCBub2RlTmFtZSA9PT0gJ0hUTUwnKSB7XG4gICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgIHJldHVybiBlbGVtZW50Lm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICAgIH1cblxuICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIH1cblxuICAvLyAub2Zmc2V0UGFyZW50IHdpbGwgcmV0dXJuIHRoZSBjbG9zZXN0IFREIG9yIFRBQkxFIGluIGNhc2VcbiAgLy8gbm8gb2Zmc2V0UGFyZW50IGlzIHByZXNlbnQsIEkgaGF0ZSB0aGlzIGpvYi4uLlxuICBpZiAoWydURCcsICdUQUJMRSddLmluZGV4T2Yob2Zmc2V0UGFyZW50Lm5vZGVOYW1lKSAhPT0gLTEgJiYgZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KG9mZnNldFBhcmVudCwgJ3Bvc2l0aW9uJykgPT09ICdzdGF0aWMnKSB7XG4gICAgcmV0dXJuIGdldE9mZnNldFBhcmVudChvZmZzZXRQYXJlbnQpO1xuICB9XG5cbiAgcmV0dXJuIG9mZnNldFBhcmVudDtcbn1cblxuZnVuY3Rpb24gaXNPZmZzZXRDb250YWluZXIoZWxlbWVudCkge1xuICB2YXIgbm9kZU5hbWUgPSBlbGVtZW50Lm5vZGVOYW1lO1xuXG4gIGlmIChub2RlTmFtZSA9PT0gJ0JPRFknKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiBub2RlTmFtZSA9PT0gJ0hUTUwnIHx8IGdldE9mZnNldFBhcmVudChlbGVtZW50LmZpcnN0RWxlbWVudENoaWxkKSA9PT0gZWxlbWVudDtcbn1cblxuLyoqXG4gKiBGaW5kcyB0aGUgcm9vdCBub2RlIChkb2N1bWVudCwgc2hhZG93RE9NIHJvb3QpIG9mIHRoZSBnaXZlbiBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IG5vZGVcbiAqIEByZXR1cm5zIHtFbGVtZW50fSByb290IG5vZGVcbiAqL1xuZnVuY3Rpb24gZ2V0Um9vdChub2RlKSB7XG4gIGlmIChub2RlLnBhcmVudE5vZGUgIT09IG51bGwpIHtcbiAgICByZXR1cm4gZ2V0Um9vdChub2RlLnBhcmVudE5vZGUpO1xuICB9XG5cbiAgcmV0dXJuIG5vZGU7XG59XG5cbi8qKlxuICogRmluZHMgdGhlIG9mZnNldCBwYXJlbnQgY29tbW9uIHRvIHRoZSB0d28gcHJvdmlkZWQgbm9kZXNcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudDFcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudDJcbiAqIEByZXR1cm5zIHtFbGVtZW50fSBjb21tb24gb2Zmc2V0IHBhcmVudFxuICovXG5mdW5jdGlvbiBmaW5kQ29tbW9uT2Zmc2V0UGFyZW50KGVsZW1lbnQxLCBlbGVtZW50Mikge1xuICAvLyBUaGlzIGNoZWNrIGlzIG5lZWRlZCB0byBhdm9pZCBlcnJvcnMgaW4gY2FzZSBvbmUgb2YgdGhlIGVsZW1lbnRzIGlzbid0IGRlZmluZWQgZm9yIGFueSByZWFzb25cbiAgaWYgKCFlbGVtZW50MSB8fCAhZWxlbWVudDEubm9kZVR5cGUgfHwgIWVsZW1lbnQyIHx8ICFlbGVtZW50Mi5ub2RlVHlwZSkge1xuICAgIHJldHVybiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIH1cblxuICAvLyBIZXJlIHdlIG1ha2Ugc3VyZSB0byBnaXZlIGFzIFwic3RhcnRcIiB0aGUgZWxlbWVudCB0aGF0IGNvbWVzIGZpcnN0IGluIHRoZSBET01cbiAgdmFyIG9yZGVyID0gZWxlbWVudDEuY29tcGFyZURvY3VtZW50UG9zaXRpb24oZWxlbWVudDIpICYgTm9kZS5ET0NVTUVOVF9QT1NJVElPTl9GT0xMT1dJTkc7XG4gIHZhciBzdGFydCA9IG9yZGVyID8gZWxlbWVudDEgOiBlbGVtZW50MjtcbiAgdmFyIGVuZCA9IG9yZGVyID8gZWxlbWVudDIgOiBlbGVtZW50MTtcblxuICAvLyBHZXQgY29tbW9uIGFuY2VzdG9yIGNvbnRhaW5lclxuICB2YXIgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICByYW5nZS5zZXRTdGFydChzdGFydCwgMCk7XG4gIHJhbmdlLnNldEVuZChlbmQsIDApO1xuICB2YXIgY29tbW9uQW5jZXN0b3JDb250YWluZXIgPSByYW5nZS5jb21tb25BbmNlc3RvckNvbnRhaW5lcjtcblxuICAvLyBCb3RoIG5vZGVzIGFyZSBpbnNpZGUgI2RvY3VtZW50XG5cbiAgaWYgKGVsZW1lbnQxICE9PSBjb21tb25BbmNlc3RvckNvbnRhaW5lciAmJiBlbGVtZW50MiAhPT0gY29tbW9uQW5jZXN0b3JDb250YWluZXIgfHwgc3RhcnQuY29udGFpbnMoZW5kKSkge1xuICAgIGlmIChpc09mZnNldENvbnRhaW5lcihjb21tb25BbmNlc3RvckNvbnRhaW5lcikpIHtcbiAgICAgIHJldHVybiBjb21tb25BbmNlc3RvckNvbnRhaW5lcjtcbiAgICB9XG5cbiAgICByZXR1cm4gZ2V0T2Zmc2V0UGFyZW50KGNvbW1vbkFuY2VzdG9yQ29udGFpbmVyKTtcbiAgfVxuXG4gIC8vIG9uZSBvZiB0aGUgbm9kZXMgaXMgaW5zaWRlIHNoYWRvd0RPTSwgZmluZCB3aGljaCBvbmVcbiAgdmFyIGVsZW1lbnQxcm9vdCA9IGdldFJvb3QoZWxlbWVudDEpO1xuICBpZiAoZWxlbWVudDFyb290Lmhvc3QpIHtcbiAgICByZXR1cm4gZmluZENvbW1vbk9mZnNldFBhcmVudChlbGVtZW50MXJvb3QuaG9zdCwgZWxlbWVudDIpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBmaW5kQ29tbW9uT2Zmc2V0UGFyZW50KGVsZW1lbnQxLCBnZXRSb290KGVsZW1lbnQyKS5ob3N0KTtcbiAgfVxufVxuXG4vKipcbiAqIEdldHMgdGhlIHNjcm9sbCB2YWx1ZSBvZiB0aGUgZ2l2ZW4gZWxlbWVudCBpbiB0aGUgZ2l2ZW4gc2lkZSAodG9wIGFuZCBsZWZ0KVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtFbGVtZW50fSBlbGVtZW50XG4gKiBAYXJndW1lbnQge1N0cmluZ30gc2lkZSBgdG9wYCBvciBgbGVmdGBcbiAqIEByZXR1cm5zIHtudW1iZXJ9IGFtb3VudCBvZiBzY3JvbGxlZCBwaXhlbHNcbiAqL1xuZnVuY3Rpb24gZ2V0U2Nyb2xsKGVsZW1lbnQpIHtcbiAgdmFyIHNpZGUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6ICd0b3AnO1xuXG4gIHZhciB1cHBlclNpZGUgPSBzaWRlID09PSAndG9wJyA/ICdzY3JvbGxUb3AnIDogJ3Njcm9sbExlZnQnO1xuICB2YXIgbm9kZU5hbWUgPSBlbGVtZW50Lm5vZGVOYW1lO1xuXG4gIGlmIChub2RlTmFtZSA9PT0gJ0JPRFknIHx8IG5vZGVOYW1lID09PSAnSFRNTCcpIHtcbiAgICB2YXIgaHRtbCA9IGVsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgdmFyIHNjcm9sbGluZ0VsZW1lbnQgPSBlbGVtZW50Lm93bmVyRG9jdW1lbnQuc2Nyb2xsaW5nRWxlbWVudCB8fCBodG1sO1xuICAgIHJldHVybiBzY3JvbGxpbmdFbGVtZW50W3VwcGVyU2lkZV07XG4gIH1cblxuICByZXR1cm4gZWxlbWVudFt1cHBlclNpZGVdO1xufVxuXG4vKlxuICogU3VtIG9yIHN1YnRyYWN0IHRoZSBlbGVtZW50IHNjcm9sbCB2YWx1ZXMgKGxlZnQgYW5kIHRvcCkgZnJvbSBhIGdpdmVuIHJlY3Qgb2JqZWN0XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge09iamVjdH0gcmVjdCAtIFJlY3Qgb2JqZWN0IHlvdSB3YW50IHRvIGNoYW5nZVxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudCAtIFRoZSBlbGVtZW50IGZyb20gdGhlIGZ1bmN0aW9uIHJlYWRzIHRoZSBzY3JvbGwgdmFsdWVzXG4gKiBAcGFyYW0ge0Jvb2xlYW59IHN1YnRyYWN0IC0gc2V0IHRvIHRydWUgaWYgeW91IHdhbnQgdG8gc3VidHJhY3QgdGhlIHNjcm9sbCB2YWx1ZXNcbiAqIEByZXR1cm4ge09iamVjdH0gcmVjdCAtIFRoZSBtb2RpZmllciByZWN0IG9iamVjdFxuICovXG5mdW5jdGlvbiBpbmNsdWRlU2Nyb2xsKHJlY3QsIGVsZW1lbnQpIHtcbiAgdmFyIHN1YnRyYWN0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTtcblxuICB2YXIgc2Nyb2xsVG9wID0gZ2V0U2Nyb2xsKGVsZW1lbnQsICd0b3AnKTtcbiAgdmFyIHNjcm9sbExlZnQgPSBnZXRTY3JvbGwoZWxlbWVudCwgJ2xlZnQnKTtcbiAgdmFyIG1vZGlmaWVyID0gc3VidHJhY3QgPyAtMSA6IDE7XG4gIHJlY3QudG9wICs9IHNjcm9sbFRvcCAqIG1vZGlmaWVyO1xuICByZWN0LmJvdHRvbSArPSBzY3JvbGxUb3AgKiBtb2RpZmllcjtcbiAgcmVjdC5sZWZ0ICs9IHNjcm9sbExlZnQgKiBtb2RpZmllcjtcbiAgcmVjdC5yaWdodCArPSBzY3JvbGxMZWZ0ICogbW9kaWZpZXI7XG4gIHJldHVybiByZWN0O1xufVxuXG4vKlxuICogSGVscGVyIHRvIGRldGVjdCBib3JkZXJzIG9mIGEgZ2l2ZW4gZWxlbWVudFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtDU1NTdHlsZURlY2xhcmF0aW9ufSBzdHlsZXNcbiAqIFJlc3VsdCBvZiBgZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5YCBvbiB0aGUgZ2l2ZW4gZWxlbWVudFxuICogQHBhcmFtIHtTdHJpbmd9IGF4aXMgLSBgeGAgb3IgYHlgXG4gKiBAcmV0dXJuIHtudW1iZXJ9IGJvcmRlcnMgLSBUaGUgYm9yZGVycyBzaXplIG9mIHRoZSBnaXZlbiBheGlzXG4gKi9cblxuZnVuY3Rpb24gZ2V0Qm9yZGVyc1NpemUoc3R5bGVzLCBheGlzKSB7XG4gIHZhciBzaWRlQSA9IGF4aXMgPT09ICd4JyA/ICdMZWZ0JyA6ICdUb3AnO1xuICB2YXIgc2lkZUIgPSBzaWRlQSA9PT0gJ0xlZnQnID8gJ1JpZ2h0JyA6ICdCb3R0b20nO1xuXG4gIHJldHVybiBwYXJzZUZsb2F0KHN0eWxlc1snYm9yZGVyJyArIHNpZGVBICsgJ1dpZHRoJ10sIDEwKSArIHBhcnNlRmxvYXQoc3R5bGVzWydib3JkZXInICsgc2lkZUIgKyAnV2lkdGgnXSwgMTApO1xufVxuXG4vKipcbiAqIFRlbGxzIGlmIHlvdSBhcmUgcnVubmluZyBJbnRlcm5ldCBFeHBsb3JlciAxMFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHJldHVybnMge0Jvb2xlYW59IGlzSUUxMFxuICovXG52YXIgaXNJRTEwID0gdW5kZWZpbmVkO1xuXG52YXIgaXNJRTEwJDEgPSBmdW5jdGlvbiAoKSB7XG4gIGlmIChpc0lFMTAgPT09IHVuZGVmaW5lZCkge1xuICAgIGlzSUUxMCA9IG5hdmlnYXRvci5hcHBWZXJzaW9uLmluZGV4T2YoJ01TSUUgMTAnKSAhPT0gLTE7XG4gIH1cbiAgcmV0dXJuIGlzSUUxMDtcbn07XG5cbmZ1bmN0aW9uIGdldFNpemUoYXhpcywgYm9keSwgaHRtbCwgY29tcHV0ZWRTdHlsZSkge1xuICByZXR1cm4gTWF0aC5tYXgoYm9keVsnb2Zmc2V0JyArIGF4aXNdLCBib2R5WydzY3JvbGwnICsgYXhpc10sIGh0bWxbJ2NsaWVudCcgKyBheGlzXSwgaHRtbFsnb2Zmc2V0JyArIGF4aXNdLCBodG1sWydzY3JvbGwnICsgYXhpc10sIGlzSUUxMCQxKCkgPyBodG1sWydvZmZzZXQnICsgYXhpc10gKyBjb21wdXRlZFN0eWxlWydtYXJnaW4nICsgKGF4aXMgPT09ICdIZWlnaHQnID8gJ1RvcCcgOiAnTGVmdCcpXSArIGNvbXB1dGVkU3R5bGVbJ21hcmdpbicgKyAoYXhpcyA9PT0gJ0hlaWdodCcgPyAnQm90dG9tJyA6ICdSaWdodCcpXSA6IDApO1xufVxuXG5mdW5jdGlvbiBnZXRXaW5kb3dTaXplcygpIHtcbiAgdmFyIGJvZHkgPSBkb2N1bWVudC5ib2R5O1xuICB2YXIgaHRtbCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgdmFyIGNvbXB1dGVkU3R5bGUgPSBpc0lFMTAkMSgpICYmIGdldENvbXB1dGVkU3R5bGUoaHRtbCk7XG5cbiAgcmV0dXJuIHtcbiAgICBoZWlnaHQ6IGdldFNpemUoJ0hlaWdodCcsIGJvZHksIGh0bWwsIGNvbXB1dGVkU3R5bGUpLFxuICAgIHdpZHRoOiBnZXRTaXplKCdXaWR0aCcsIGJvZHksIGh0bWwsIGNvbXB1dGVkU3R5bGUpXG4gIH07XG59XG5cbnZhciBjbGFzc0NhbGxDaGVjayA9IGZ1bmN0aW9uIChpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHtcbiAgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpO1xuICB9XG59O1xuXG52YXIgY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07XG4gICAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7XG4gICAgICBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7XG4gICAgICBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlO1xuICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7XG4gICAgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTtcbiAgICBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgICByZXR1cm4gQ29uc3RydWN0b3I7XG4gIH07XG59KCk7XG5cblxuXG5cblxudmFyIGRlZmluZVByb3BlcnR5ID0gZnVuY3Rpb24gKG9iaiwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG9iaikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwge1xuICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgb2JqW2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIHJldHVybiBvYmo7XG59O1xuXG52YXIgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldO1xuXG4gICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHtcbiAgICAgICAgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufTtcblxuLyoqXG4gKiBHaXZlbiBlbGVtZW50IG9mZnNldHMsIGdlbmVyYXRlIGFuIG91dHB1dCBzaW1pbGFyIHRvIGdldEJvdW5kaW5nQ2xpZW50UmVjdFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IG9mZnNldHNcbiAqIEByZXR1cm5zIHtPYmplY3R9IENsaWVudFJlY3QgbGlrZSBvdXRwdXRcbiAqL1xuZnVuY3Rpb24gZ2V0Q2xpZW50UmVjdChvZmZzZXRzKSB7XG4gIHJldHVybiBfZXh0ZW5kcyh7fSwgb2Zmc2V0cywge1xuICAgIHJpZ2h0OiBvZmZzZXRzLmxlZnQgKyBvZmZzZXRzLndpZHRoLFxuICAgIGJvdHRvbTogb2Zmc2V0cy50b3AgKyBvZmZzZXRzLmhlaWdodFxuICB9KTtcbn1cblxuLyoqXG4gKiBHZXQgYm91bmRpbmcgY2xpZW50IHJlY3Qgb2YgZ2l2ZW4gZWxlbWVudFxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybiB7T2JqZWN0fSBjbGllbnQgcmVjdFxuICovXG5mdW5jdGlvbiBnZXRCb3VuZGluZ0NsaWVudFJlY3QoZWxlbWVudCkge1xuICB2YXIgcmVjdCA9IHt9O1xuXG4gIC8vIElFMTAgMTAgRklYOiBQbGVhc2UsIGRvbid0IGFzaywgdGhlIGVsZW1lbnQgaXNuJ3RcbiAgLy8gY29uc2lkZXJlZCBpbiBET00gaW4gc29tZSBjaXJjdW1zdGFuY2VzLi4uXG4gIC8vIFRoaXMgaXNuJ3QgcmVwcm9kdWNpYmxlIGluIElFMTAgY29tcGF0aWJpbGl0eSBtb2RlIG9mIElFMTFcbiAgaWYgKGlzSUUxMCQxKCkpIHtcbiAgICB0cnkge1xuICAgICAgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICB2YXIgc2Nyb2xsVG9wID0gZ2V0U2Nyb2xsKGVsZW1lbnQsICd0b3AnKTtcbiAgICAgIHZhciBzY3JvbGxMZWZ0ID0gZ2V0U2Nyb2xsKGVsZW1lbnQsICdsZWZ0Jyk7XG4gICAgICByZWN0LnRvcCArPSBzY3JvbGxUb3A7XG4gICAgICByZWN0LmxlZnQgKz0gc2Nyb2xsTGVmdDtcbiAgICAgIHJlY3QuYm90dG9tICs9IHNjcm9sbFRvcDtcbiAgICAgIHJlY3QucmlnaHQgKz0gc2Nyb2xsTGVmdDtcbiAgICB9IGNhdGNoIChlcnIpIHt9XG4gIH0gZWxzZSB7XG4gICAgcmVjdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gIH1cblxuICB2YXIgcmVzdWx0ID0ge1xuICAgIGxlZnQ6IHJlY3QubGVmdCxcbiAgICB0b3A6IHJlY3QudG9wLFxuICAgIHdpZHRoOiByZWN0LnJpZ2h0IC0gcmVjdC5sZWZ0LFxuICAgIGhlaWdodDogcmVjdC5ib3R0b20gLSByZWN0LnRvcFxuICB9O1xuXG4gIC8vIHN1YnRyYWN0IHNjcm9sbGJhciBzaXplIGZyb20gc2l6ZXNcbiAgdmFyIHNpemVzID0gZWxlbWVudC5ub2RlTmFtZSA9PT0gJ0hUTUwnID8gZ2V0V2luZG93U2l6ZXMoKSA6IHt9O1xuICB2YXIgd2lkdGggPSBzaXplcy53aWR0aCB8fCBlbGVtZW50LmNsaWVudFdpZHRoIHx8IHJlc3VsdC5yaWdodCAtIHJlc3VsdC5sZWZ0O1xuICB2YXIgaGVpZ2h0ID0gc2l6ZXMuaGVpZ2h0IHx8IGVsZW1lbnQuY2xpZW50SGVpZ2h0IHx8IHJlc3VsdC5ib3R0b20gLSByZXN1bHQudG9wO1xuXG4gIHZhciBob3JpelNjcm9sbGJhciA9IGVsZW1lbnQub2Zmc2V0V2lkdGggLSB3aWR0aDtcbiAgdmFyIHZlcnRTY3JvbGxiYXIgPSBlbGVtZW50Lm9mZnNldEhlaWdodCAtIGhlaWdodDtcblxuICAvLyBpZiBhbiBoeXBvdGhldGljYWwgc2Nyb2xsYmFyIGlzIGRldGVjdGVkLCB3ZSBtdXN0IGJlIHN1cmUgaXQncyBub3QgYSBgYm9yZGVyYFxuICAvLyB3ZSBtYWtlIHRoaXMgY2hlY2sgY29uZGl0aW9uYWwgZm9yIHBlcmZvcm1hbmNlIHJlYXNvbnNcbiAgaWYgKGhvcml6U2Nyb2xsYmFyIHx8IHZlcnRTY3JvbGxiYXIpIHtcbiAgICB2YXIgc3R5bGVzID0gZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KGVsZW1lbnQpO1xuICAgIGhvcml6U2Nyb2xsYmFyIC09IGdldEJvcmRlcnNTaXplKHN0eWxlcywgJ3gnKTtcbiAgICB2ZXJ0U2Nyb2xsYmFyIC09IGdldEJvcmRlcnNTaXplKHN0eWxlcywgJ3knKTtcblxuICAgIHJlc3VsdC53aWR0aCAtPSBob3JpelNjcm9sbGJhcjtcbiAgICByZXN1bHQuaGVpZ2h0IC09IHZlcnRTY3JvbGxiYXI7XG4gIH1cblxuICByZXR1cm4gZ2V0Q2xpZW50UmVjdChyZXN1bHQpO1xufVxuXG5mdW5jdGlvbiBnZXRPZmZzZXRSZWN0UmVsYXRpdmVUb0FyYml0cmFyeU5vZGUoY2hpbGRyZW4sIHBhcmVudCkge1xuICB2YXIgaXNJRTEwID0gaXNJRTEwJDEoKTtcbiAgdmFyIGlzSFRNTCA9IHBhcmVudC5ub2RlTmFtZSA9PT0gJ0hUTUwnO1xuICB2YXIgY2hpbGRyZW5SZWN0ID0gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KGNoaWxkcmVuKTtcbiAgdmFyIHBhcmVudFJlY3QgPSBnZXRCb3VuZGluZ0NsaWVudFJlY3QocGFyZW50KTtcbiAgdmFyIHNjcm9sbFBhcmVudCA9IGdldFNjcm9sbFBhcmVudChjaGlsZHJlbik7XG5cbiAgdmFyIHN0eWxlcyA9IGdldFN0eWxlQ29tcHV0ZWRQcm9wZXJ0eShwYXJlbnQpO1xuICB2YXIgYm9yZGVyVG9wV2lkdGggPSBwYXJzZUZsb2F0KHN0eWxlcy5ib3JkZXJUb3BXaWR0aCwgMTApO1xuICB2YXIgYm9yZGVyTGVmdFdpZHRoID0gcGFyc2VGbG9hdChzdHlsZXMuYm9yZGVyTGVmdFdpZHRoLCAxMCk7XG5cbiAgdmFyIG9mZnNldHMgPSBnZXRDbGllbnRSZWN0KHtcbiAgICB0b3A6IGNoaWxkcmVuUmVjdC50b3AgLSBwYXJlbnRSZWN0LnRvcCAtIGJvcmRlclRvcFdpZHRoLFxuICAgIGxlZnQ6IGNoaWxkcmVuUmVjdC5sZWZ0IC0gcGFyZW50UmVjdC5sZWZ0IC0gYm9yZGVyTGVmdFdpZHRoLFxuICAgIHdpZHRoOiBjaGlsZHJlblJlY3Qud2lkdGgsXG4gICAgaGVpZ2h0OiBjaGlsZHJlblJlY3QuaGVpZ2h0XG4gIH0pO1xuICBvZmZzZXRzLm1hcmdpblRvcCA9IDA7XG4gIG9mZnNldHMubWFyZ2luTGVmdCA9IDA7XG5cbiAgLy8gU3VidHJhY3QgbWFyZ2lucyBvZiBkb2N1bWVudEVsZW1lbnQgaW4gY2FzZSBpdCdzIGJlaW5nIHVzZWQgYXMgcGFyZW50XG4gIC8vIHdlIGRvIHRoaXMgb25seSBvbiBIVE1MIGJlY2F1c2UgaXQncyB0aGUgb25seSBlbGVtZW50IHRoYXQgYmVoYXZlc1xuICAvLyBkaWZmZXJlbnRseSB3aGVuIG1hcmdpbnMgYXJlIGFwcGxpZWQgdG8gaXQuIFRoZSBtYXJnaW5zIGFyZSBpbmNsdWRlZCBpblxuICAvLyB0aGUgYm94IG9mIHRoZSBkb2N1bWVudEVsZW1lbnQsIGluIHRoZSBvdGhlciBjYXNlcyBub3QuXG4gIGlmICghaXNJRTEwICYmIGlzSFRNTCkge1xuICAgIHZhciBtYXJnaW5Ub3AgPSBwYXJzZUZsb2F0KHN0eWxlcy5tYXJnaW5Ub3AsIDEwKTtcbiAgICB2YXIgbWFyZ2luTGVmdCA9IHBhcnNlRmxvYXQoc3R5bGVzLm1hcmdpbkxlZnQsIDEwKTtcblxuICAgIG9mZnNldHMudG9wIC09IGJvcmRlclRvcFdpZHRoIC0gbWFyZ2luVG9wO1xuICAgIG9mZnNldHMuYm90dG9tIC09IGJvcmRlclRvcFdpZHRoIC0gbWFyZ2luVG9wO1xuICAgIG9mZnNldHMubGVmdCAtPSBib3JkZXJMZWZ0V2lkdGggLSBtYXJnaW5MZWZ0O1xuICAgIG9mZnNldHMucmlnaHQgLT0gYm9yZGVyTGVmdFdpZHRoIC0gbWFyZ2luTGVmdDtcblxuICAgIC8vIEF0dGFjaCBtYXJnaW5Ub3AgYW5kIG1hcmdpbkxlZnQgYmVjYXVzZSBpbiBzb21lIGNpcmN1bXN0YW5jZXMgd2UgbWF5IG5lZWQgdGhlbVxuICAgIG9mZnNldHMubWFyZ2luVG9wID0gbWFyZ2luVG9wO1xuICAgIG9mZnNldHMubWFyZ2luTGVmdCA9IG1hcmdpbkxlZnQ7XG4gIH1cblxuICBpZiAoaXNJRTEwID8gcGFyZW50LmNvbnRhaW5zKHNjcm9sbFBhcmVudCkgOiBwYXJlbnQgPT09IHNjcm9sbFBhcmVudCAmJiBzY3JvbGxQYXJlbnQubm9kZU5hbWUgIT09ICdCT0RZJykge1xuICAgIG9mZnNldHMgPSBpbmNsdWRlU2Nyb2xsKG9mZnNldHMsIHBhcmVudCk7XG4gIH1cblxuICByZXR1cm4gb2Zmc2V0cztcbn1cblxuZnVuY3Rpb24gZ2V0Vmlld3BvcnRPZmZzZXRSZWN0UmVsYXRpdmVUb0FydGJpdHJhcnlOb2RlKGVsZW1lbnQpIHtcbiAgdmFyIGh0bWwgPSBlbGVtZW50Lm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50O1xuICB2YXIgcmVsYXRpdmVPZmZzZXQgPSBnZXRPZmZzZXRSZWN0UmVsYXRpdmVUb0FyYml0cmFyeU5vZGUoZWxlbWVudCwgaHRtbCk7XG4gIHZhciB3aWR0aCA9IE1hdGgubWF4KGh0bWwuY2xpZW50V2lkdGgsIHdpbmRvdy5pbm5lcldpZHRoIHx8IDApO1xuICB2YXIgaGVpZ2h0ID0gTWF0aC5tYXgoaHRtbC5jbGllbnRIZWlnaHQsIHdpbmRvdy5pbm5lckhlaWdodCB8fCAwKTtcblxuICB2YXIgc2Nyb2xsVG9wID0gZ2V0U2Nyb2xsKGh0bWwpO1xuICB2YXIgc2Nyb2xsTGVmdCA9IGdldFNjcm9sbChodG1sLCAnbGVmdCcpO1xuXG4gIHZhciBvZmZzZXQgPSB7XG4gICAgdG9wOiBzY3JvbGxUb3AgLSByZWxhdGl2ZU9mZnNldC50b3AgKyByZWxhdGl2ZU9mZnNldC5tYXJnaW5Ub3AsXG4gICAgbGVmdDogc2Nyb2xsTGVmdCAtIHJlbGF0aXZlT2Zmc2V0LmxlZnQgKyByZWxhdGl2ZU9mZnNldC5tYXJnaW5MZWZ0LFxuICAgIHdpZHRoOiB3aWR0aCxcbiAgICBoZWlnaHQ6IGhlaWdodFxuICB9O1xuXG4gIHJldHVybiBnZXRDbGllbnRSZWN0KG9mZnNldCk7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIGdpdmVuIGVsZW1lbnQgaXMgZml4ZWQgb3IgaXMgaW5zaWRlIGEgZml4ZWQgcGFyZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge0VsZW1lbnR9IGVsZW1lbnRcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gY3VzdG9tQ29udGFpbmVyXG4gKiBAcmV0dXJucyB7Qm9vbGVhbn0gYW5zd2VyIHRvIFwiaXNGaXhlZD9cIlxuICovXG5mdW5jdGlvbiBpc0ZpeGVkKGVsZW1lbnQpIHtcbiAgdmFyIG5vZGVOYW1lID0gZWxlbWVudC5ub2RlTmFtZTtcbiAgaWYgKG5vZGVOYW1lID09PSAnQk9EWScgfHwgbm9kZU5hbWUgPT09ICdIVE1MJykge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBpZiAoZ2V0U3R5bGVDb21wdXRlZFByb3BlcnR5KGVsZW1lbnQsICdwb3NpdGlvbicpID09PSAnZml4ZWQnKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgcmV0dXJuIGlzRml4ZWQoZ2V0UGFyZW50Tm9kZShlbGVtZW50KSk7XG59XG5cbi8qKlxuICogQ29tcHV0ZWQgdGhlIGJvdW5kYXJpZXMgbGltaXRzIGFuZCByZXR1cm4gdGhlbVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcG9wcGVyXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSByZWZlcmVuY2VcbiAqIEBwYXJhbSB7bnVtYmVyfSBwYWRkaW5nXG4gKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBib3VuZGFyaWVzRWxlbWVudCAtIEVsZW1lbnQgdXNlZCB0byBkZWZpbmUgdGhlIGJvdW5kYXJpZXNcbiAqIEByZXR1cm5zIHtPYmplY3R9IENvb3JkaW5hdGVzIG9mIHRoZSBib3VuZGFyaWVzXG4gKi9cbmZ1bmN0aW9uIGdldEJvdW5kYXJpZXMocG9wcGVyLCByZWZlcmVuY2UsIHBhZGRpbmcsIGJvdW5kYXJpZXNFbGVtZW50KSB7XG4gIC8vIE5PVEU6IDEgRE9NIGFjY2VzcyBoZXJlXG4gIHZhciBib3VuZGFyaWVzID0geyB0b3A6IDAsIGxlZnQ6IDAgfTtcbiAgdmFyIG9mZnNldFBhcmVudCA9IGZpbmRDb21tb25PZmZzZXRQYXJlbnQocG9wcGVyLCByZWZlcmVuY2UpO1xuXG4gIC8vIEhhbmRsZSB2aWV3cG9ydCBjYXNlXG4gIGlmIChib3VuZGFyaWVzRWxlbWVudCA9PT0gJ3ZpZXdwb3J0Jykge1xuICAgIGJvdW5kYXJpZXMgPSBnZXRWaWV3cG9ydE9mZnNldFJlY3RSZWxhdGl2ZVRvQXJ0Yml0cmFyeU5vZGUob2Zmc2V0UGFyZW50KTtcbiAgfSBlbHNlIHtcbiAgICAvLyBIYW5kbGUgb3RoZXIgY2FzZXMgYmFzZWQgb24gRE9NIGVsZW1lbnQgdXNlZCBhcyBib3VuZGFyaWVzXG4gICAgdmFyIGJvdW5kYXJpZXNOb2RlID0gdm9pZCAwO1xuICAgIGlmIChib3VuZGFyaWVzRWxlbWVudCA9PT0gJ3Njcm9sbFBhcmVudCcpIHtcbiAgICAgIGJvdW5kYXJpZXNOb2RlID0gZ2V0U2Nyb2xsUGFyZW50KGdldFBhcmVudE5vZGUocmVmZXJlbmNlKSk7XG4gICAgICBpZiAoYm91bmRhcmllc05vZGUubm9kZU5hbWUgPT09ICdCT0RZJykge1xuICAgICAgICBib3VuZGFyaWVzTm9kZSA9IHBvcHBlci5vd25lckRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGJvdW5kYXJpZXNFbGVtZW50ID09PSAnd2luZG93Jykge1xuICAgICAgYm91bmRhcmllc05vZGUgPSBwb3BwZXIub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIGJvdW5kYXJpZXNOb2RlID0gYm91bmRhcmllc0VsZW1lbnQ7XG4gICAgfVxuXG4gICAgdmFyIG9mZnNldHMgPSBnZXRPZmZzZXRSZWN0UmVsYXRpdmVUb0FyYml0cmFyeU5vZGUoYm91bmRhcmllc05vZGUsIG9mZnNldFBhcmVudCk7XG5cbiAgICAvLyBJbiBjYXNlIG9mIEhUTUwsIHdlIG5lZWQgYSBkaWZmZXJlbnQgY29tcHV0YXRpb25cbiAgICBpZiAoYm91bmRhcmllc05vZGUubm9kZU5hbWUgPT09ICdIVE1MJyAmJiAhaXNGaXhlZChvZmZzZXRQYXJlbnQpKSB7XG4gICAgICB2YXIgX2dldFdpbmRvd1NpemVzID0gZ2V0V2luZG93U2l6ZXMoKSxcbiAgICAgICAgICBoZWlnaHQgPSBfZ2V0V2luZG93U2l6ZXMuaGVpZ2h0LFxuICAgICAgICAgIHdpZHRoID0gX2dldFdpbmRvd1NpemVzLndpZHRoO1xuXG4gICAgICBib3VuZGFyaWVzLnRvcCArPSBvZmZzZXRzLnRvcCAtIG9mZnNldHMubWFyZ2luVG9wO1xuICAgICAgYm91bmRhcmllcy5ib3R0b20gPSBoZWlnaHQgKyBvZmZzZXRzLnRvcDtcbiAgICAgIGJvdW5kYXJpZXMubGVmdCArPSBvZmZzZXRzLmxlZnQgLSBvZmZzZXRzLm1hcmdpbkxlZnQ7XG4gICAgICBib3VuZGFyaWVzLnJpZ2h0ID0gd2lkdGggKyBvZmZzZXRzLmxlZnQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGZvciBhbGwgdGhlIG90aGVyIERPTSBlbGVtZW50cywgdGhpcyBvbmUgaXMgZ29vZFxuICAgICAgYm91bmRhcmllcyA9IG9mZnNldHM7XG4gICAgfVxuICB9XG5cbiAgLy8gQWRkIHBhZGRpbmdzXG4gIGJvdW5kYXJpZXMubGVmdCArPSBwYWRkaW5nO1xuICBib3VuZGFyaWVzLnRvcCArPSBwYWRkaW5nO1xuICBib3VuZGFyaWVzLnJpZ2h0IC09IHBhZGRpbmc7XG4gIGJvdW5kYXJpZXMuYm90dG9tIC09IHBhZGRpbmc7XG5cbiAgcmV0dXJuIGJvdW5kYXJpZXM7XG59XG5cbmZ1bmN0aW9uIGdldEFyZWEoX3JlZikge1xuICB2YXIgd2lkdGggPSBfcmVmLndpZHRoLFxuICAgICAgaGVpZ2h0ID0gX3JlZi5oZWlnaHQ7XG5cbiAgcmV0dXJuIHdpZHRoICogaGVpZ2h0O1xufVxuXG4vKipcbiAqIFV0aWxpdHkgdXNlZCB0byB0cmFuc2Zvcm0gdGhlIGBhdXRvYCBwbGFjZW1lbnQgdG8gdGhlIHBsYWNlbWVudCB3aXRoIG1vcmVcbiAqIGF2YWlsYWJsZSBzcGFjZS5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSB1cGRhdGUgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIGNvbXB1dGVBdXRvUGxhY2VtZW50KHBsYWNlbWVudCwgcmVmUmVjdCwgcG9wcGVyLCByZWZlcmVuY2UsIGJvdW5kYXJpZXNFbGVtZW50KSB7XG4gIHZhciBwYWRkaW5nID0gYXJndW1lbnRzLmxlbmd0aCA+IDUgJiYgYXJndW1lbnRzWzVdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNV0gOiAwO1xuXG4gIGlmIChwbGFjZW1lbnQuaW5kZXhPZignYXV0bycpID09PSAtMSkge1xuICAgIHJldHVybiBwbGFjZW1lbnQ7XG4gIH1cblxuICB2YXIgYm91bmRhcmllcyA9IGdldEJvdW5kYXJpZXMocG9wcGVyLCByZWZlcmVuY2UsIHBhZGRpbmcsIGJvdW5kYXJpZXNFbGVtZW50KTtcblxuICB2YXIgcmVjdHMgPSB7XG4gICAgdG9wOiB7XG4gICAgICB3aWR0aDogYm91bmRhcmllcy53aWR0aCxcbiAgICAgIGhlaWdodDogcmVmUmVjdC50b3AgLSBib3VuZGFyaWVzLnRvcFxuICAgIH0sXG4gICAgcmlnaHQ6IHtcbiAgICAgIHdpZHRoOiBib3VuZGFyaWVzLnJpZ2h0IC0gcmVmUmVjdC5yaWdodCxcbiAgICAgIGhlaWdodDogYm91bmRhcmllcy5oZWlnaHRcbiAgICB9LFxuICAgIGJvdHRvbToge1xuICAgICAgd2lkdGg6IGJvdW5kYXJpZXMud2lkdGgsXG4gICAgICBoZWlnaHQ6IGJvdW5kYXJpZXMuYm90dG9tIC0gcmVmUmVjdC5ib3R0b21cbiAgICB9LFxuICAgIGxlZnQ6IHtcbiAgICAgIHdpZHRoOiByZWZSZWN0LmxlZnQgLSBib3VuZGFyaWVzLmxlZnQsXG4gICAgICBoZWlnaHQ6IGJvdW5kYXJpZXMuaGVpZ2h0XG4gICAgfVxuICB9O1xuXG4gIHZhciBzb3J0ZWRBcmVhcyA9IE9iamVjdC5rZXlzKHJlY3RzKS5tYXAoZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiBfZXh0ZW5kcyh7XG4gICAgICBrZXk6IGtleVxuICAgIH0sIHJlY3RzW2tleV0sIHtcbiAgICAgIGFyZWE6IGdldEFyZWEocmVjdHNba2V5XSlcbiAgICB9KTtcbiAgfSkuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgIHJldHVybiBiLmFyZWEgLSBhLmFyZWE7XG4gIH0pO1xuXG4gIHZhciBmaWx0ZXJlZEFyZWFzID0gc29ydGVkQXJlYXMuZmlsdGVyKGZ1bmN0aW9uIChfcmVmMikge1xuICAgIHZhciB3aWR0aCA9IF9yZWYyLndpZHRoLFxuICAgICAgICBoZWlnaHQgPSBfcmVmMi5oZWlnaHQ7XG4gICAgcmV0dXJuIHdpZHRoID49IHBvcHBlci5jbGllbnRXaWR0aCAmJiBoZWlnaHQgPj0gcG9wcGVyLmNsaWVudEhlaWdodDtcbiAgfSk7XG5cbiAgdmFyIGNvbXB1dGVkUGxhY2VtZW50ID0gZmlsdGVyZWRBcmVhcy5sZW5ndGggPiAwID8gZmlsdGVyZWRBcmVhc1swXS5rZXkgOiBzb3J0ZWRBcmVhc1swXS5rZXk7XG5cbiAgdmFyIHZhcmlhdGlvbiA9IHBsYWNlbWVudC5zcGxpdCgnLScpWzFdO1xuXG4gIHJldHVybiBjb21wdXRlZFBsYWNlbWVudCArICh2YXJpYXRpb24gPyAnLScgKyB2YXJpYXRpb24gOiAnJyk7XG59XG5cbi8qKlxuICogR2V0IG9mZnNldHMgdG8gdGhlIHJlZmVyZW5jZSBlbGVtZW50XG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0ge09iamVjdH0gc3RhdGVcbiAqIEBwYXJhbSB7RWxlbWVudH0gcG9wcGVyIC0gdGhlIHBvcHBlciBlbGVtZW50XG4gKiBAcGFyYW0ge0VsZW1lbnR9IHJlZmVyZW5jZSAtIHRoZSByZWZlcmVuY2UgZWxlbWVudCAodGhlIHBvcHBlciB3aWxsIGJlIHJlbGF0aXZlIHRvIHRoaXMpXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBBbiBvYmplY3QgY29udGFpbmluZyB0aGUgb2Zmc2V0cyB3aGljaCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIHBvcHBlclxuICovXG5mdW5jdGlvbiBnZXRSZWZlcmVuY2VPZmZzZXRzKHN0YXRlLCBwb3BwZXIsIHJlZmVyZW5jZSkge1xuICB2YXIgY29tbW9uT2Zmc2V0UGFyZW50ID0gZmluZENvbW1vbk9mZnNldFBhcmVudChwb3BwZXIsIHJlZmVyZW5jZSk7XG4gIHJldHVybiBnZXRPZmZzZXRSZWN0UmVsYXRpdmVUb0FyYml0cmFyeU5vZGUocmVmZXJlbmNlLCBjb21tb25PZmZzZXRQYXJlbnQpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgb3V0ZXIgc2l6ZXMgb2YgdGhlIGdpdmVuIGVsZW1lbnQgKG9mZnNldCBzaXplICsgbWFyZ2lucylcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudFxuICogQHJldHVybnMge09iamVjdH0gb2JqZWN0IGNvbnRhaW5pbmcgd2lkdGggYW5kIGhlaWdodCBwcm9wZXJ0aWVzXG4gKi9cbmZ1bmN0aW9uIGdldE91dGVyU2l6ZXMoZWxlbWVudCkge1xuICB2YXIgc3R5bGVzID0gZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KTtcbiAgdmFyIHggPSBwYXJzZUZsb2F0KHN0eWxlcy5tYXJnaW5Ub3ApICsgcGFyc2VGbG9hdChzdHlsZXMubWFyZ2luQm90dG9tKTtcbiAgdmFyIHkgPSBwYXJzZUZsb2F0KHN0eWxlcy5tYXJnaW5MZWZ0KSArIHBhcnNlRmxvYXQoc3R5bGVzLm1hcmdpblJpZ2h0KTtcbiAgdmFyIHJlc3VsdCA9IHtcbiAgICB3aWR0aDogZWxlbWVudC5vZmZzZXRXaWR0aCArIHksXG4gICAgaGVpZ2h0OiBlbGVtZW50Lm9mZnNldEhlaWdodCArIHhcbiAgfTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIG9wcG9zaXRlIHBsYWNlbWVudCBvZiB0aGUgZ2l2ZW4gb25lXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAYXJndW1lbnQge1N0cmluZ30gcGxhY2VtZW50XG4gKiBAcmV0dXJucyB7U3RyaW5nfSBmbGlwcGVkIHBsYWNlbWVudFxuICovXG5mdW5jdGlvbiBnZXRPcHBvc2l0ZVBsYWNlbWVudChwbGFjZW1lbnQpIHtcbiAgdmFyIGhhc2ggPSB7IGxlZnQ6ICdyaWdodCcsIHJpZ2h0OiAnbGVmdCcsIGJvdHRvbTogJ3RvcCcsIHRvcDogJ2JvdHRvbScgfTtcbiAgcmV0dXJuIHBsYWNlbWVudC5yZXBsYWNlKC9sZWZ0fHJpZ2h0fGJvdHRvbXx0b3AvZywgZnVuY3Rpb24gKG1hdGNoZWQpIHtcbiAgICByZXR1cm4gaGFzaFttYXRjaGVkXTtcbiAgfSk7XG59XG5cbi8qKlxuICogR2V0IG9mZnNldHMgdG8gdGhlIHBvcHBlclxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHBhcmFtIHtPYmplY3R9IHBvc2l0aW9uIC0gQ1NTIHBvc2l0aW9uIHRoZSBQb3BwZXIgd2lsbCBnZXQgYXBwbGllZFxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcG9wcGVyIC0gdGhlIHBvcHBlciBlbGVtZW50XG4gKiBAcGFyYW0ge09iamVjdH0gcmVmZXJlbmNlT2Zmc2V0cyAtIHRoZSByZWZlcmVuY2Ugb2Zmc2V0cyAodGhlIHBvcHBlciB3aWxsIGJlIHJlbGF0aXZlIHRvIHRoaXMpXG4gKiBAcGFyYW0ge1N0cmluZ30gcGxhY2VtZW50IC0gb25lIG9mIHRoZSB2YWxpZCBwbGFjZW1lbnQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gcG9wcGVyT2Zmc2V0cyAtIEFuIG9iamVjdCBjb250YWluaW5nIHRoZSBvZmZzZXRzIHdoaWNoIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgcG9wcGVyXG4gKi9cbmZ1bmN0aW9uIGdldFBvcHBlck9mZnNldHMocG9wcGVyLCByZWZlcmVuY2VPZmZzZXRzLCBwbGFjZW1lbnQpIHtcbiAgcGxhY2VtZW50ID0gcGxhY2VtZW50LnNwbGl0KCctJylbMF07XG5cbiAgLy8gR2V0IHBvcHBlciBub2RlIHNpemVzXG4gIHZhciBwb3BwZXJSZWN0ID0gZ2V0T3V0ZXJTaXplcyhwb3BwZXIpO1xuXG4gIC8vIEFkZCBwb3NpdGlvbiwgd2lkdGggYW5kIGhlaWdodCB0byBvdXIgb2Zmc2V0cyBvYmplY3RcbiAgdmFyIHBvcHBlck9mZnNldHMgPSB7XG4gICAgd2lkdGg6IHBvcHBlclJlY3Qud2lkdGgsXG4gICAgaGVpZ2h0OiBwb3BwZXJSZWN0LmhlaWdodFxuICB9O1xuXG4gIC8vIGRlcGVuZGluZyBieSB0aGUgcG9wcGVyIHBsYWNlbWVudCB3ZSBoYXZlIHRvIGNvbXB1dGUgaXRzIG9mZnNldHMgc2xpZ2h0bHkgZGlmZmVyZW50bHlcbiAgdmFyIGlzSG9yaXogPSBbJ3JpZ2h0JywgJ2xlZnQnXS5pbmRleE9mKHBsYWNlbWVudCkgIT09IC0xO1xuICB2YXIgbWFpblNpZGUgPSBpc0hvcml6ID8gJ3RvcCcgOiAnbGVmdCc7XG4gIHZhciBzZWNvbmRhcnlTaWRlID0gaXNIb3JpeiA/ICdsZWZ0JyA6ICd0b3AnO1xuICB2YXIgbWVhc3VyZW1lbnQgPSBpc0hvcml6ID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xuICB2YXIgc2Vjb25kYXJ5TWVhc3VyZW1lbnQgPSAhaXNIb3JpeiA/ICdoZWlnaHQnIDogJ3dpZHRoJztcblxuICBwb3BwZXJPZmZzZXRzW21haW5TaWRlXSA9IHJlZmVyZW5jZU9mZnNldHNbbWFpblNpZGVdICsgcmVmZXJlbmNlT2Zmc2V0c1ttZWFzdXJlbWVudF0gLyAyIC0gcG9wcGVyUmVjdFttZWFzdXJlbWVudF0gLyAyO1xuICBpZiAocGxhY2VtZW50ID09PSBzZWNvbmRhcnlTaWRlKSB7XG4gICAgcG9wcGVyT2Zmc2V0c1tzZWNvbmRhcnlTaWRlXSA9IHJlZmVyZW5jZU9mZnNldHNbc2Vjb25kYXJ5U2lkZV0gLSBwb3BwZXJSZWN0W3NlY29uZGFyeU1lYXN1cmVtZW50XTtcbiAgfSBlbHNlIHtcbiAgICBwb3BwZXJPZmZzZXRzW3NlY29uZGFyeVNpZGVdID0gcmVmZXJlbmNlT2Zmc2V0c1tnZXRPcHBvc2l0ZVBsYWNlbWVudChzZWNvbmRhcnlTaWRlKV07XG4gIH1cblxuICByZXR1cm4gcG9wcGVyT2Zmc2V0cztcbn1cblxuLyoqXG4gKiBNaW1pY3MgdGhlIGBmaW5kYCBtZXRob2Qgb2YgQXJyYXlcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7QXJyYXl9IGFyclxuICogQGFyZ3VtZW50IHByb3BcbiAqIEBhcmd1bWVudCB2YWx1ZVxuICogQHJldHVybnMgaW5kZXggb3IgLTFcbiAqL1xuZnVuY3Rpb24gZmluZChhcnIsIGNoZWNrKSB7XG4gIC8vIHVzZSBuYXRpdmUgZmluZCBpZiBzdXBwb3J0ZWRcbiAgaWYgKEFycmF5LnByb3RvdHlwZS5maW5kKSB7XG4gICAgcmV0dXJuIGFyci5maW5kKGNoZWNrKTtcbiAgfVxuXG4gIC8vIHVzZSBgZmlsdGVyYCB0byBvYnRhaW4gdGhlIHNhbWUgYmVoYXZpb3Igb2YgYGZpbmRgXG4gIHJldHVybiBhcnIuZmlsdGVyKGNoZWNrKVswXTtcbn1cblxuLyoqXG4gKiBSZXR1cm4gdGhlIGluZGV4IG9mIHRoZSBtYXRjaGluZyBvYmplY3RcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7QXJyYXl9IGFyclxuICogQGFyZ3VtZW50IHByb3BcbiAqIEBhcmd1bWVudCB2YWx1ZVxuICogQHJldHVybnMgaW5kZXggb3IgLTFcbiAqL1xuZnVuY3Rpb24gZmluZEluZGV4KGFyciwgcHJvcCwgdmFsdWUpIHtcbiAgLy8gdXNlIG5hdGl2ZSBmaW5kSW5kZXggaWYgc3VwcG9ydGVkXG4gIGlmIChBcnJheS5wcm90b3R5cGUuZmluZEluZGV4KSB7XG4gICAgcmV0dXJuIGFyci5maW5kSW5kZXgoZnVuY3Rpb24gKGN1cikge1xuICAgICAgcmV0dXJuIGN1cltwcm9wXSA9PT0gdmFsdWU7XG4gICAgfSk7XG4gIH1cblxuICAvLyB1c2UgYGZpbmRgICsgYGluZGV4T2ZgIGlmIGBmaW5kSW5kZXhgIGlzbid0IHN1cHBvcnRlZFxuICB2YXIgbWF0Y2ggPSBmaW5kKGFyciwgZnVuY3Rpb24gKG9iaikge1xuICAgIHJldHVybiBvYmpbcHJvcF0gPT09IHZhbHVlO1xuICB9KTtcbiAgcmV0dXJuIGFyci5pbmRleE9mKG1hdGNoKTtcbn1cblxuLyoqXG4gKiBMb29wIHRyb3VnaCB0aGUgbGlzdCBvZiBtb2RpZmllcnMgYW5kIHJ1biB0aGVtIGluIG9yZGVyLFxuICogZWFjaCBvZiB0aGVtIHdpbGwgdGhlbiBlZGl0IHRoZSBkYXRhIG9iamVjdC5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwYXJhbSB7ZGF0YU9iamVjdH0gZGF0YVxuICogQHBhcmFtIHtBcnJheX0gbW9kaWZpZXJzXG4gKiBAcGFyYW0ge1N0cmluZ30gZW5kcyAtIE9wdGlvbmFsIG1vZGlmaWVyIG5hbWUgdXNlZCBhcyBzdG9wcGVyXG4gKiBAcmV0dXJucyB7ZGF0YU9iamVjdH1cbiAqL1xuZnVuY3Rpb24gcnVuTW9kaWZpZXJzKG1vZGlmaWVycywgZGF0YSwgZW5kcykge1xuICB2YXIgbW9kaWZpZXJzVG9SdW4gPSBlbmRzID09PSB1bmRlZmluZWQgPyBtb2RpZmllcnMgOiBtb2RpZmllcnMuc2xpY2UoMCwgZmluZEluZGV4KG1vZGlmaWVycywgJ25hbWUnLCBlbmRzKSk7XG5cbiAgbW9kaWZpZXJzVG9SdW4uZm9yRWFjaChmdW5jdGlvbiAobW9kaWZpZXIpIHtcbiAgICBpZiAobW9kaWZpZXJbJ2Z1bmN0aW9uJ10pIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgZG90LW5vdGF0aW9uXG4gICAgICBjb25zb2xlLndhcm4oJ2Btb2RpZmllci5mdW5jdGlvbmAgaXMgZGVwcmVjYXRlZCwgdXNlIGBtb2RpZmllci5mbmAhJyk7XG4gICAgfVxuICAgIHZhciBmbiA9IG1vZGlmaWVyWydmdW5jdGlvbiddIHx8IG1vZGlmaWVyLmZuOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGRvdC1ub3RhdGlvblxuICAgIGlmIChtb2RpZmllci5lbmFibGVkICYmIGlzRnVuY3Rpb24oZm4pKSB7XG4gICAgICAvLyBBZGQgcHJvcGVydGllcyB0byBvZmZzZXRzIHRvIG1ha2UgdGhlbSBhIGNvbXBsZXRlIGNsaWVudFJlY3Qgb2JqZWN0XG4gICAgICAvLyB3ZSBkbyB0aGlzIGJlZm9yZSBlYWNoIG1vZGlmaWVyIHRvIG1ha2Ugc3VyZSB0aGUgcHJldmlvdXMgb25lIGRvZXNuJ3RcbiAgICAgIC8vIG1lc3Mgd2l0aCB0aGVzZSB2YWx1ZXNcbiAgICAgIGRhdGEub2Zmc2V0cy5wb3BwZXIgPSBnZXRDbGllbnRSZWN0KGRhdGEub2Zmc2V0cy5wb3BwZXIpO1xuICAgICAgZGF0YS5vZmZzZXRzLnJlZmVyZW5jZSA9IGdldENsaWVudFJlY3QoZGF0YS5vZmZzZXRzLnJlZmVyZW5jZSk7XG5cbiAgICAgIGRhdGEgPSBmbihkYXRhLCBtb2RpZmllcik7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBVcGRhdGVzIHRoZSBwb3NpdGlvbiBvZiB0aGUgcG9wcGVyLCBjb21wdXRpbmcgdGhlIG5ldyBvZmZzZXRzIGFuZCBhcHBseWluZ1xuICogdGhlIG5ldyBzdHlsZS48YnIgLz5cbiAqIFByZWZlciBgc2NoZWR1bGVVcGRhdGVgIG92ZXIgYHVwZGF0ZWAgYmVjYXVzZSBvZiBwZXJmb3JtYW5jZSByZWFzb25zLlxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlclxuICovXG5mdW5jdGlvbiB1cGRhdGUoKSB7XG4gIC8vIGlmIHBvcHBlciBpcyBkZXN0cm95ZWQsIGRvbid0IHBlcmZvcm0gYW55IGZ1cnRoZXIgdXBkYXRlXG4gIGlmICh0aGlzLnN0YXRlLmlzRGVzdHJveWVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIGRhdGEgPSB7XG4gICAgaW5zdGFuY2U6IHRoaXMsXG4gICAgc3R5bGVzOiB7fSxcbiAgICBhcnJvd1N0eWxlczoge30sXG4gICAgYXR0cmlidXRlczoge30sXG4gICAgZmxpcHBlZDogZmFsc2UsXG4gICAgb2Zmc2V0czoge31cbiAgfTtcblxuICAvLyBjb21wdXRlIHJlZmVyZW5jZSBlbGVtZW50IG9mZnNldHNcbiAgZGF0YS5vZmZzZXRzLnJlZmVyZW5jZSA9IGdldFJlZmVyZW5jZU9mZnNldHModGhpcy5zdGF0ZSwgdGhpcy5wb3BwZXIsIHRoaXMucmVmZXJlbmNlKTtcblxuICAvLyBjb21wdXRlIGF1dG8gcGxhY2VtZW50LCBzdG9yZSBwbGFjZW1lbnQgaW5zaWRlIHRoZSBkYXRhIG9iamVjdCxcbiAgLy8gbW9kaWZpZXJzIHdpbGwgYmUgYWJsZSB0byBlZGl0IGBwbGFjZW1lbnRgIGlmIG5lZWRlZFxuICAvLyBhbmQgcmVmZXIgdG8gb3JpZ2luYWxQbGFjZW1lbnQgdG8ga25vdyB0aGUgb3JpZ2luYWwgdmFsdWVcbiAgZGF0YS5wbGFjZW1lbnQgPSBjb21wdXRlQXV0b1BsYWNlbWVudCh0aGlzLm9wdGlvbnMucGxhY2VtZW50LCBkYXRhLm9mZnNldHMucmVmZXJlbmNlLCB0aGlzLnBvcHBlciwgdGhpcy5yZWZlcmVuY2UsIHRoaXMub3B0aW9ucy5tb2RpZmllcnMuZmxpcC5ib3VuZGFyaWVzRWxlbWVudCwgdGhpcy5vcHRpb25zLm1vZGlmaWVycy5mbGlwLnBhZGRpbmcpO1xuXG4gIC8vIHN0b3JlIHRoZSBjb21wdXRlZCBwbGFjZW1lbnQgaW5zaWRlIGBvcmlnaW5hbFBsYWNlbWVudGBcbiAgZGF0YS5vcmlnaW5hbFBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50O1xuXG4gIC8vIGNvbXB1dGUgdGhlIHBvcHBlciBvZmZzZXRzXG4gIGRhdGEub2Zmc2V0cy5wb3BwZXIgPSBnZXRQb3BwZXJPZmZzZXRzKHRoaXMucG9wcGVyLCBkYXRhLm9mZnNldHMucmVmZXJlbmNlLCBkYXRhLnBsYWNlbWVudCk7XG4gIGRhdGEub2Zmc2V0cy5wb3BwZXIucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuXG4gIC8vIHJ1biB0aGUgbW9kaWZpZXJzXG4gIGRhdGEgPSBydW5Nb2RpZmllcnModGhpcy5tb2RpZmllcnMsIGRhdGEpO1xuXG4gIC8vIHRoZSBmaXJzdCBgdXBkYXRlYCB3aWxsIGNhbGwgYG9uQ3JlYXRlYCBjYWxsYmFja1xuICAvLyB0aGUgb3RoZXIgb25lcyB3aWxsIGNhbGwgYG9uVXBkYXRlYCBjYWxsYmFja1xuICBpZiAoIXRoaXMuc3RhdGUuaXNDcmVhdGVkKSB7XG4gICAgdGhpcy5zdGF0ZS5pc0NyZWF0ZWQgPSB0cnVlO1xuICAgIHRoaXMub3B0aW9ucy5vbkNyZWF0ZShkYXRhKTtcbiAgfSBlbHNlIHtcbiAgICB0aGlzLm9wdGlvbnMub25VcGRhdGUoZGF0YSk7XG4gIH1cbn1cblxuLyoqXG4gKiBIZWxwZXIgdXNlZCB0byBrbm93IGlmIHRoZSBnaXZlbiBtb2RpZmllciBpcyBlbmFibGVkLlxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQHJldHVybnMge0Jvb2xlYW59XG4gKi9cbmZ1bmN0aW9uIGlzTW9kaWZpZXJFbmFibGVkKG1vZGlmaWVycywgbW9kaWZpZXJOYW1lKSB7XG4gIHJldHVybiBtb2RpZmllcnMuc29tZShmdW5jdGlvbiAoX3JlZikge1xuICAgIHZhciBuYW1lID0gX3JlZi5uYW1lLFxuICAgICAgICBlbmFibGVkID0gX3JlZi5lbmFibGVkO1xuICAgIHJldHVybiBlbmFibGVkICYmIG5hbWUgPT09IG1vZGlmaWVyTmFtZTtcbiAgfSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBwcmVmaXhlZCBzdXBwb3J0ZWQgcHJvcGVydHkgbmFtZVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtTdHJpbmd9IHByb3BlcnR5IChjYW1lbENhc2UpXG4gKiBAcmV0dXJucyB7U3RyaW5nfSBwcmVmaXhlZCBwcm9wZXJ0eSAoY2FtZWxDYXNlIG9yIFBhc2NhbENhc2UsIGRlcGVuZGluZyBvbiB0aGUgdmVuZG9yIHByZWZpeClcbiAqL1xuZnVuY3Rpb24gZ2V0U3VwcG9ydGVkUHJvcGVydHlOYW1lKHByb3BlcnR5KSB7XG4gIHZhciBwcmVmaXhlcyA9IFtmYWxzZSwgJ21zJywgJ1dlYmtpdCcsICdNb3onLCAnTyddO1xuICB2YXIgdXBwZXJQcm9wID0gcHJvcGVydHkuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBwcm9wZXJ0eS5zbGljZSgxKTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHByZWZpeGVzLmxlbmd0aCAtIDE7IGkrKykge1xuICAgIHZhciBwcmVmaXggPSBwcmVmaXhlc1tpXTtcbiAgICB2YXIgdG9DaGVjayA9IHByZWZpeCA/ICcnICsgcHJlZml4ICsgdXBwZXJQcm9wIDogcHJvcGVydHk7XG4gICAgaWYgKHR5cGVvZiBkb2N1bWVudC5ib2R5LnN0eWxlW3RvQ2hlY2tdICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIHRvQ2hlY2s7XG4gICAgfVxuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG4vKipcbiAqIERlc3Ryb3kgdGhlIHBvcHBlclxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlclxuICovXG5mdW5jdGlvbiBkZXN0cm95KCkge1xuICB0aGlzLnN0YXRlLmlzRGVzdHJveWVkID0gdHJ1ZTtcblxuICAvLyB0b3VjaCBET00gb25seSBpZiBgYXBwbHlTdHlsZWAgbW9kaWZpZXIgaXMgZW5hYmxlZFxuICBpZiAoaXNNb2RpZmllckVuYWJsZWQodGhpcy5tb2RpZmllcnMsICdhcHBseVN0eWxlJykpIHtcbiAgICB0aGlzLnBvcHBlci5yZW1vdmVBdHRyaWJ1dGUoJ3gtcGxhY2VtZW50Jyk7XG4gICAgdGhpcy5wb3BwZXIuc3R5bGUubGVmdCA9ICcnO1xuICAgIHRoaXMucG9wcGVyLnN0eWxlLnBvc2l0aW9uID0gJyc7XG4gICAgdGhpcy5wb3BwZXIuc3R5bGUudG9wID0gJyc7XG4gICAgdGhpcy5wb3BwZXIuc3R5bGVbZ2V0U3VwcG9ydGVkUHJvcGVydHlOYW1lKCd0cmFuc2Zvcm0nKV0gPSAnJztcbiAgfVxuXG4gIHRoaXMuZGlzYWJsZUV2ZW50TGlzdGVuZXJzKCk7XG5cbiAgLy8gcmVtb3ZlIHRoZSBwb3BwZXIgaWYgdXNlciBleHBsaWNpdHkgYXNrZWQgZm9yIHRoZSBkZWxldGlvbiBvbiBkZXN0cm95XG4gIC8vIGRvIG5vdCB1c2UgYHJlbW92ZWAgYmVjYXVzZSBJRTExIGRvZXNuJ3Qgc3VwcG9ydCBpdFxuICBpZiAodGhpcy5vcHRpb25zLnJlbW92ZU9uRGVzdHJveSkge1xuICAgIHRoaXMucG9wcGVyLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5wb3BwZXIpO1xuICB9XG4gIHJldHVybiB0aGlzO1xufVxuXG4vKipcbiAqIEdldCB0aGUgd2luZG93IGFzc29jaWF0ZWQgd2l0aCB0aGUgZWxlbWVudFxuICogQGFyZ3VtZW50IHtFbGVtZW50fSBlbGVtZW50XG4gKiBAcmV0dXJucyB7V2luZG93fVxuICovXG5mdW5jdGlvbiBnZXRXaW5kb3coZWxlbWVudCkge1xuICB2YXIgb3duZXJEb2N1bWVudCA9IGVsZW1lbnQub3duZXJEb2N1bWVudDtcbiAgcmV0dXJuIG93bmVyRG9jdW1lbnQgPyBvd25lckRvY3VtZW50LmRlZmF1bHRWaWV3IDogd2luZG93O1xufVxuXG5mdW5jdGlvbiBhdHRhY2hUb1Njcm9sbFBhcmVudHMoc2Nyb2xsUGFyZW50LCBldmVudCwgY2FsbGJhY2ssIHNjcm9sbFBhcmVudHMpIHtcbiAgdmFyIGlzQm9keSA9IHNjcm9sbFBhcmVudC5ub2RlTmFtZSA9PT0gJ0JPRFknO1xuICB2YXIgdGFyZ2V0ID0gaXNCb2R5ID8gc2Nyb2xsUGFyZW50Lm93bmVyRG9jdW1lbnQuZGVmYXVsdFZpZXcgOiBzY3JvbGxQYXJlbnQ7XG4gIHRhcmdldC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBjYWxsYmFjaywgeyBwYXNzaXZlOiB0cnVlIH0pO1xuXG4gIGlmICghaXNCb2R5KSB7XG4gICAgYXR0YWNoVG9TY3JvbGxQYXJlbnRzKGdldFNjcm9sbFBhcmVudCh0YXJnZXQucGFyZW50Tm9kZSksIGV2ZW50LCBjYWxsYmFjaywgc2Nyb2xsUGFyZW50cyk7XG4gIH1cbiAgc2Nyb2xsUGFyZW50cy5wdXNoKHRhcmdldCk7XG59XG5cbi8qKlxuICogU2V0dXAgbmVlZGVkIGV2ZW50IGxpc3RlbmVycyB1c2VkIHRvIHVwZGF0ZSB0aGUgcG9wcGVyIHBvc2l0aW9uXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcHJpdmF0ZVxuICovXG5mdW5jdGlvbiBzZXR1cEV2ZW50TGlzdGVuZXJzKHJlZmVyZW5jZSwgb3B0aW9ucywgc3RhdGUsIHVwZGF0ZUJvdW5kKSB7XG4gIC8vIFJlc2l6ZSBldmVudCBsaXN0ZW5lciBvbiB3aW5kb3dcbiAgc3RhdGUudXBkYXRlQm91bmQgPSB1cGRhdGVCb3VuZDtcbiAgZ2V0V2luZG93KHJlZmVyZW5jZSkuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgc3RhdGUudXBkYXRlQm91bmQsIHsgcGFzc2l2ZTogdHJ1ZSB9KTtcblxuICAvLyBTY3JvbGwgZXZlbnQgbGlzdGVuZXIgb24gc2Nyb2xsIHBhcmVudHNcbiAgdmFyIHNjcm9sbEVsZW1lbnQgPSBnZXRTY3JvbGxQYXJlbnQocmVmZXJlbmNlKTtcbiAgYXR0YWNoVG9TY3JvbGxQYXJlbnRzKHNjcm9sbEVsZW1lbnQsICdzY3JvbGwnLCBzdGF0ZS51cGRhdGVCb3VuZCwgc3RhdGUuc2Nyb2xsUGFyZW50cyk7XG4gIHN0YXRlLnNjcm9sbEVsZW1lbnQgPSBzY3JvbGxFbGVtZW50O1xuICBzdGF0ZS5ldmVudHNFbmFibGVkID0gdHJ1ZTtcblxuICByZXR1cm4gc3RhdGU7XG59XG5cbi8qKlxuICogSXQgd2lsbCBhZGQgcmVzaXplL3Njcm9sbCBldmVudHMgYW5kIHN0YXJ0IHJlY2FsY3VsYXRpbmdcbiAqIHBvc2l0aW9uIG9mIHRoZSBwb3BwZXIgZWxlbWVudCB3aGVuIHRoZXkgYXJlIHRyaWdnZXJlZC5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXJcbiAqL1xuZnVuY3Rpb24gZW5hYmxlRXZlbnRMaXN0ZW5lcnMoKSB7XG4gIGlmICghdGhpcy5zdGF0ZS5ldmVudHNFbmFibGVkKSB7XG4gICAgdGhpcy5zdGF0ZSA9IHNldHVwRXZlbnRMaXN0ZW5lcnModGhpcy5yZWZlcmVuY2UsIHRoaXMub3B0aW9ucywgdGhpcy5zdGF0ZSwgdGhpcy5zY2hlZHVsZVVwZGF0ZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZW1vdmUgZXZlbnQgbGlzdGVuZXJzIHVzZWQgdG8gdXBkYXRlIHRoZSBwb3BwZXIgcG9zaXRpb25cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwcml2YXRlXG4gKi9cbmZ1bmN0aW9uIHJlbW92ZUV2ZW50TGlzdGVuZXJzKHJlZmVyZW5jZSwgc3RhdGUpIHtcbiAgLy8gUmVtb3ZlIHJlc2l6ZSBldmVudCBsaXN0ZW5lciBvbiB3aW5kb3dcbiAgZ2V0V2luZG93KHJlZmVyZW5jZSkucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgc3RhdGUudXBkYXRlQm91bmQpO1xuXG4gIC8vIFJlbW92ZSBzY3JvbGwgZXZlbnQgbGlzdGVuZXIgb24gc2Nyb2xsIHBhcmVudHNcbiAgc3RhdGUuc2Nyb2xsUGFyZW50cy5mb3JFYWNoKGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICB0YXJnZXQucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgc3RhdGUudXBkYXRlQm91bmQpO1xuICB9KTtcblxuICAvLyBSZXNldCBzdGF0ZVxuICBzdGF0ZS51cGRhdGVCb3VuZCA9IG51bGw7XG4gIHN0YXRlLnNjcm9sbFBhcmVudHMgPSBbXTtcbiAgc3RhdGUuc2Nyb2xsRWxlbWVudCA9IG51bGw7XG4gIHN0YXRlLmV2ZW50c0VuYWJsZWQgPSBmYWxzZTtcbiAgcmV0dXJuIHN0YXRlO1xufVxuXG4vKipcbiAqIEl0IHdpbGwgcmVtb3ZlIHJlc2l6ZS9zY3JvbGwgZXZlbnRzIGFuZCB3b24ndCByZWNhbGN1bGF0ZSBwb3BwZXIgcG9zaXRpb25cbiAqIHdoZW4gdGhleSBhcmUgdHJpZ2dlcmVkLiBJdCBhbHNvIHdvbid0IHRyaWdnZXIgb25VcGRhdGUgY2FsbGJhY2sgYW55bW9yZSxcbiAqIHVubGVzcyB5b3UgY2FsbCBgdXBkYXRlYCBtZXRob2QgbWFudWFsbHkuXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyXG4gKi9cbmZ1bmN0aW9uIGRpc2FibGVFdmVudExpc3RlbmVycygpIHtcbiAgaWYgKHRoaXMuc3RhdGUuZXZlbnRzRW5hYmxlZCkge1xuICAgIGNhbmNlbEFuaW1hdGlvbkZyYW1lKHRoaXMuc2NoZWR1bGVVcGRhdGUpO1xuICAgIHRoaXMuc3RhdGUgPSByZW1vdmVFdmVudExpc3RlbmVycyh0aGlzLnJlZmVyZW5jZSwgdGhpcy5zdGF0ZSk7XG4gIH1cbn1cblxuLyoqXG4gKiBUZWxscyBpZiBhIGdpdmVuIGlucHV0IGlzIGEgbnVtYmVyXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLlV0aWxzXG4gKiBAcGFyYW0geyp9IGlucHV0IHRvIGNoZWNrXG4gKiBAcmV0dXJuIHtCb29sZWFufVxuICovXG5mdW5jdGlvbiBpc051bWVyaWMobikge1xuICByZXR1cm4gbiAhPT0gJycgJiYgIWlzTmFOKHBhcnNlRmxvYXQobikpICYmIGlzRmluaXRlKG4pO1xufVxuXG4vKipcbiAqIFNldCB0aGUgc3R5bGUgdG8gdGhlIGdpdmVuIHBvcHBlclxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtFbGVtZW50fSBlbGVtZW50IC0gRWxlbWVudCB0byBhcHBseSB0aGUgc3R5bGUgdG9cbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBzdHlsZXNcbiAqIE9iamVjdCB3aXRoIGEgbGlzdCBvZiBwcm9wZXJ0aWVzIGFuZCB2YWx1ZXMgd2hpY2ggd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBlbGVtZW50XG4gKi9cbmZ1bmN0aW9uIHNldFN0eWxlcyhlbGVtZW50LCBzdHlsZXMpIHtcbiAgT2JqZWN0LmtleXMoc3R5bGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgdmFyIHVuaXQgPSAnJztcbiAgICAvLyBhZGQgdW5pdCBpZiB0aGUgdmFsdWUgaXMgbnVtZXJpYyBhbmQgaXMgb25lIG9mIHRoZSBmb2xsb3dpbmdcbiAgICBpZiAoWyd3aWR0aCcsICdoZWlnaHQnLCAndG9wJywgJ3JpZ2h0JywgJ2JvdHRvbScsICdsZWZ0J10uaW5kZXhPZihwcm9wKSAhPT0gLTEgJiYgaXNOdW1lcmljKHN0eWxlc1twcm9wXSkpIHtcbiAgICAgIHVuaXQgPSAncHgnO1xuICAgIH1cbiAgICBlbGVtZW50LnN0eWxlW3Byb3BdID0gc3R5bGVzW3Byb3BdICsgdW5pdDtcbiAgfSk7XG59XG5cbi8qKlxuICogU2V0IHRoZSBhdHRyaWJ1dGVzIHRvIHRoZSBnaXZlbiBwb3BwZXJcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7RWxlbWVudH0gZWxlbWVudCAtIEVsZW1lbnQgdG8gYXBwbHkgdGhlIGF0dHJpYnV0ZXMgdG9cbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBzdHlsZXNcbiAqIE9iamVjdCB3aXRoIGEgbGlzdCBvZiBwcm9wZXJ0aWVzIGFuZCB2YWx1ZXMgd2hpY2ggd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBlbGVtZW50XG4gKi9cbmZ1bmN0aW9uIHNldEF0dHJpYnV0ZXMoZWxlbWVudCwgYXR0cmlidXRlcykge1xuICBPYmplY3Qua2V5cyhhdHRyaWJ1dGVzKS5mb3JFYWNoKGZ1bmN0aW9uIChwcm9wKSB7XG4gICAgdmFyIHZhbHVlID0gYXR0cmlidXRlc1twcm9wXTtcbiAgICBpZiAodmFsdWUgIT09IGZhbHNlKSB7XG4gICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZShwcm9wLCBhdHRyaWJ1dGVzW3Byb3BdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUocHJvcCk7XG4gICAgfVxuICB9KTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSBgdXBkYXRlYCBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhLnN0eWxlcyAtIExpc3Qgb2Ygc3R5bGUgcHJvcGVydGllcyAtIHZhbHVlcyB0byBhcHBseSB0byBwb3BwZXIgZWxlbWVudFxuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEuYXR0cmlidXRlcyAtIExpc3Qgb2YgYXR0cmlidXRlIHByb3BlcnRpZXMgLSB2YWx1ZXMgdG8gYXBwbHkgdG8gcG9wcGVyIGVsZW1lbnRcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBzYW1lIGRhdGEgb2JqZWN0XG4gKi9cbmZ1bmN0aW9uIGFwcGx5U3R5bGUoZGF0YSkge1xuICAvLyBhbnkgcHJvcGVydHkgcHJlc2VudCBpbiBgZGF0YS5zdHlsZXNgIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgcG9wcGVyLFxuICAvLyBpbiB0aGlzIHdheSB3ZSBjYW4gbWFrZSB0aGUgM3JkIHBhcnR5IG1vZGlmaWVycyBhZGQgY3VzdG9tIHN0eWxlcyB0byBpdFxuICAvLyBCZSBhd2FyZSwgbW9kaWZpZXJzIGNvdWxkIG92ZXJyaWRlIHRoZSBwcm9wZXJ0aWVzIGRlZmluZWQgaW4gdGhlIHByZXZpb3VzXG4gIC8vIGxpbmVzIG9mIHRoaXMgbW9kaWZpZXIhXG4gIHNldFN0eWxlcyhkYXRhLmluc3RhbmNlLnBvcHBlciwgZGF0YS5zdHlsZXMpO1xuXG4gIC8vIGFueSBwcm9wZXJ0eSBwcmVzZW50IGluIGBkYXRhLmF0dHJpYnV0ZXNgIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgcG9wcGVyLFxuICAvLyB0aGV5IHdpbGwgYmUgc2V0IGFzIEhUTUwgYXR0cmlidXRlcyBvZiB0aGUgZWxlbWVudFxuICBzZXRBdHRyaWJ1dGVzKGRhdGEuaW5zdGFuY2UucG9wcGVyLCBkYXRhLmF0dHJpYnV0ZXMpO1xuXG4gIC8vIGlmIGFycm93RWxlbWVudCBpcyBkZWZpbmVkIGFuZCBhcnJvd1N0eWxlcyBoYXMgc29tZSBwcm9wZXJ0aWVzXG4gIGlmIChkYXRhLmFycm93RWxlbWVudCAmJiBPYmplY3Qua2V5cyhkYXRhLmFycm93U3R5bGVzKS5sZW5ndGgpIHtcbiAgICBzZXRTdHlsZXMoZGF0YS5hcnJvd0VsZW1lbnQsIGRhdGEuYXJyb3dTdHlsZXMpO1xuICB9XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogU2V0IHRoZSB4LXBsYWNlbWVudCBhdHRyaWJ1dGUgYmVmb3JlIGV2ZXJ5dGhpbmcgZWxzZSBiZWNhdXNlIGl0IGNvdWxkIGJlIHVzZWRcbiAqIHRvIGFkZCBtYXJnaW5zIHRvIHRoZSBwb3BwZXIgbWFyZ2lucyBuZWVkcyB0byBiZSBjYWxjdWxhdGVkIHRvIGdldCB0aGVcbiAqIGNvcnJlY3QgcG9wcGVyIG9mZnNldHMuXG4gKiBAbWV0aG9kXG4gKiBAbWVtYmVyb2YgUG9wcGVyLm1vZGlmaWVyc1xuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcmVmZXJlbmNlIC0gVGhlIHJlZmVyZW5jZSBlbGVtZW50IHVzZWQgdG8gcG9zaXRpb24gdGhlIHBvcHBlclxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcG9wcGVyIC0gVGhlIEhUTUwgZWxlbWVudCB1c2VkIGFzIHBvcHBlci5cbiAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gUG9wcGVyLmpzIG9wdGlvbnNcbiAqL1xuZnVuY3Rpb24gYXBwbHlTdHlsZU9uTG9hZChyZWZlcmVuY2UsIHBvcHBlciwgb3B0aW9ucywgbW9kaWZpZXJPcHRpb25zLCBzdGF0ZSkge1xuICAvLyBjb21wdXRlIHJlZmVyZW5jZSBlbGVtZW50IG9mZnNldHNcbiAgdmFyIHJlZmVyZW5jZU9mZnNldHMgPSBnZXRSZWZlcmVuY2VPZmZzZXRzKHN0YXRlLCBwb3BwZXIsIHJlZmVyZW5jZSk7XG5cbiAgLy8gY29tcHV0ZSBhdXRvIHBsYWNlbWVudCwgc3RvcmUgcGxhY2VtZW50IGluc2lkZSB0aGUgZGF0YSBvYmplY3QsXG4gIC8vIG1vZGlmaWVycyB3aWxsIGJlIGFibGUgdG8gZWRpdCBgcGxhY2VtZW50YCBpZiBuZWVkZWRcbiAgLy8gYW5kIHJlZmVyIHRvIG9yaWdpbmFsUGxhY2VtZW50IHRvIGtub3cgdGhlIG9yaWdpbmFsIHZhbHVlXG4gIHZhciBwbGFjZW1lbnQgPSBjb21wdXRlQXV0b1BsYWNlbWVudChvcHRpb25zLnBsYWNlbWVudCwgcmVmZXJlbmNlT2Zmc2V0cywgcG9wcGVyLCByZWZlcmVuY2UsIG9wdGlvbnMubW9kaWZpZXJzLmZsaXAuYm91bmRhcmllc0VsZW1lbnQsIG9wdGlvbnMubW9kaWZpZXJzLmZsaXAucGFkZGluZyk7XG5cbiAgcG9wcGVyLnNldEF0dHJpYnV0ZSgneC1wbGFjZW1lbnQnLCBwbGFjZW1lbnQpO1xuXG4gIC8vIEFwcGx5IGBwb3NpdGlvbmAgdG8gcG9wcGVyIGJlZm9yZSBhbnl0aGluZyBlbHNlIGJlY2F1c2VcbiAgLy8gd2l0aG91dCB0aGUgcG9zaXRpb24gYXBwbGllZCB3ZSBjYW4ndCBndWFyYW50ZWUgY29ycmVjdCBjb21wdXRhdGlvbnNcbiAgc2V0U3R5bGVzKHBvcHBlciwgeyBwb3NpdGlvbjogJ2Fic29sdXRlJyB9KTtcblxuICByZXR1cm4gb3B0aW9ucztcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSBgdXBkYXRlYCBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBkYXRhIG9iamVjdCwgcHJvcGVybHkgbW9kaWZpZWRcbiAqL1xuZnVuY3Rpb24gY29tcHV0ZVN0eWxlKGRhdGEsIG9wdGlvbnMpIHtcbiAgdmFyIHggPSBvcHRpb25zLngsXG4gICAgICB5ID0gb3B0aW9ucy55O1xuICB2YXIgcG9wcGVyID0gZGF0YS5vZmZzZXRzLnBvcHBlcjtcblxuICAvLyBSZW1vdmUgdGhpcyBsZWdhY3kgc3VwcG9ydCBpbiBQb3BwZXIuanMgdjJcblxuICB2YXIgbGVnYWN5R3B1QWNjZWxlcmF0aW9uT3B0aW9uID0gZmluZChkYXRhLmluc3RhbmNlLm1vZGlmaWVycywgZnVuY3Rpb24gKG1vZGlmaWVyKSB7XG4gICAgcmV0dXJuIG1vZGlmaWVyLm5hbWUgPT09ICdhcHBseVN0eWxlJztcbiAgfSkuZ3B1QWNjZWxlcmF0aW9uO1xuICBpZiAobGVnYWN5R3B1QWNjZWxlcmF0aW9uT3B0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICBjb25zb2xlLndhcm4oJ1dBUk5JTkc6IGBncHVBY2NlbGVyYXRpb25gIG9wdGlvbiBtb3ZlZCB0byBgY29tcHV0ZVN0eWxlYCBtb2RpZmllciBhbmQgd2lsbCBub3QgYmUgc3VwcG9ydGVkIGluIGZ1dHVyZSB2ZXJzaW9ucyBvZiBQb3BwZXIuanMhJyk7XG4gIH1cbiAgdmFyIGdwdUFjY2VsZXJhdGlvbiA9IGxlZ2FjeUdwdUFjY2VsZXJhdGlvbk9wdGlvbiAhPT0gdW5kZWZpbmVkID8gbGVnYWN5R3B1QWNjZWxlcmF0aW9uT3B0aW9uIDogb3B0aW9ucy5ncHVBY2NlbGVyYXRpb247XG5cbiAgdmFyIG9mZnNldFBhcmVudCA9IGdldE9mZnNldFBhcmVudChkYXRhLmluc3RhbmNlLnBvcHBlcik7XG4gIHZhciBvZmZzZXRQYXJlbnRSZWN0ID0gZ2V0Qm91bmRpbmdDbGllbnRSZWN0KG9mZnNldFBhcmVudCk7XG5cbiAgLy8gU3R5bGVzXG4gIHZhciBzdHlsZXMgPSB7XG4gICAgcG9zaXRpb246IHBvcHBlci5wb3NpdGlvblxuICB9O1xuXG4gIC8vIGZsb29yIHNpZGVzIHRvIGF2b2lkIGJsdXJyeSB0ZXh0XG4gIHZhciBvZmZzZXRzID0ge1xuICAgIGxlZnQ6IE1hdGguZmxvb3IocG9wcGVyLmxlZnQpLFxuICAgIHRvcDogTWF0aC5mbG9vcihwb3BwZXIudG9wKSxcbiAgICBib3R0b206IE1hdGguZmxvb3IocG9wcGVyLmJvdHRvbSksXG4gICAgcmlnaHQ6IE1hdGguZmxvb3IocG9wcGVyLnJpZ2h0KVxuICB9O1xuXG4gIHZhciBzaWRlQSA9IHggPT09ICdib3R0b20nID8gJ3RvcCcgOiAnYm90dG9tJztcbiAgdmFyIHNpZGVCID0geSA9PT0gJ3JpZ2h0JyA/ICdsZWZ0JyA6ICdyaWdodCc7XG5cbiAgLy8gaWYgZ3B1QWNjZWxlcmF0aW9uIGlzIHNldCB0byBgdHJ1ZWAgYW5kIHRyYW5zZm9ybSBpcyBzdXBwb3J0ZWQsXG4gIC8vICB3ZSB1c2UgYHRyYW5zbGF0ZTNkYCB0byBhcHBseSB0aGUgcG9zaXRpb24gdG8gdGhlIHBvcHBlciB3ZVxuICAvLyBhdXRvbWF0aWNhbGx5IHVzZSB0aGUgc3VwcG9ydGVkIHByZWZpeGVkIHZlcnNpb24gaWYgbmVlZGVkXG4gIHZhciBwcmVmaXhlZFByb3BlcnR5ID0gZ2V0U3VwcG9ydGVkUHJvcGVydHlOYW1lKCd0cmFuc2Zvcm0nKTtcblxuICAvLyBub3csIGxldCdzIG1ha2UgYSBzdGVwIGJhY2sgYW5kIGxvb2sgYXQgdGhpcyBjb2RlIGNsb3NlbHkgKHd0Zj8pXG4gIC8vIElmIHRoZSBjb250ZW50IG9mIHRoZSBwb3BwZXIgZ3Jvd3Mgb25jZSBpdCdzIGJlZW4gcG9zaXRpb25lZCwgaXRcbiAgLy8gbWF5IGhhcHBlbiB0aGF0IHRoZSBwb3BwZXIgZ2V0cyBtaXNwbGFjZWQgYmVjYXVzZSBvZiB0aGUgbmV3IGNvbnRlbnRcbiAgLy8gb3ZlcmZsb3dpbmcgaXRzIHJlZmVyZW5jZSBlbGVtZW50XG4gIC8vIFRvIGF2b2lkIHRoaXMgcHJvYmxlbSwgd2UgcHJvdmlkZSB0d28gb3B0aW9ucyAoeCBhbmQgeSksIHdoaWNoIGFsbG93XG4gIC8vIHRoZSBjb25zdW1lciB0byBkZWZpbmUgdGhlIG9mZnNldCBvcmlnaW4uXG4gIC8vIElmIHdlIHBvc2l0aW9uIGEgcG9wcGVyIG9uIHRvcCBvZiBhIHJlZmVyZW5jZSBlbGVtZW50LCB3ZSBjYW4gc2V0XG4gIC8vIGB4YCB0byBgdG9wYCB0byBtYWtlIHRoZSBwb3BwZXIgZ3JvdyB0b3dhcmRzIGl0cyB0b3AgaW5zdGVhZCBvZlxuICAvLyBpdHMgYm90dG9tLlxuICB2YXIgbGVmdCA9IHZvaWQgMCxcbiAgICAgIHRvcCA9IHZvaWQgMDtcbiAgaWYgKHNpZGVBID09PSAnYm90dG9tJykge1xuICAgIHRvcCA9IC1vZmZzZXRQYXJlbnRSZWN0LmhlaWdodCArIG9mZnNldHMuYm90dG9tO1xuICB9IGVsc2Uge1xuICAgIHRvcCA9IG9mZnNldHMudG9wO1xuICB9XG4gIGlmIChzaWRlQiA9PT0gJ3JpZ2h0Jykge1xuICAgIGxlZnQgPSAtb2Zmc2V0UGFyZW50UmVjdC53aWR0aCArIG9mZnNldHMucmlnaHQ7XG4gIH0gZWxzZSB7XG4gICAgbGVmdCA9IG9mZnNldHMubGVmdDtcbiAgfVxuICBpZiAoZ3B1QWNjZWxlcmF0aW9uICYmIHByZWZpeGVkUHJvcGVydHkpIHtcbiAgICBzdHlsZXNbcHJlZml4ZWRQcm9wZXJ0eV0gPSAndHJhbnNsYXRlM2QoJyArIGxlZnQgKyAncHgsICcgKyB0b3AgKyAncHgsIDApJztcbiAgICBzdHlsZXNbc2lkZUFdID0gMDtcbiAgICBzdHlsZXNbc2lkZUJdID0gMDtcbiAgICBzdHlsZXMud2lsbENoYW5nZSA9ICd0cmFuc2Zvcm0nO1xuICB9IGVsc2Uge1xuICAgIC8vIG90aHdlcmlzZSwgd2UgdXNlIHRoZSBzdGFuZGFyZCBgdG9wYCwgYGxlZnRgLCBgYm90dG9tYCBhbmQgYHJpZ2h0YCBwcm9wZXJ0aWVzXG4gICAgdmFyIGludmVydFRvcCA9IHNpZGVBID09PSAnYm90dG9tJyA/IC0xIDogMTtcbiAgICB2YXIgaW52ZXJ0TGVmdCA9IHNpZGVCID09PSAncmlnaHQnID8gLTEgOiAxO1xuICAgIHN0eWxlc1tzaWRlQV0gPSB0b3AgKiBpbnZlcnRUb3A7XG4gICAgc3R5bGVzW3NpZGVCXSA9IGxlZnQgKiBpbnZlcnRMZWZ0O1xuICAgIHN0eWxlcy53aWxsQ2hhbmdlID0gc2lkZUEgKyAnLCAnICsgc2lkZUI7XG4gIH1cblxuICAvLyBBdHRyaWJ1dGVzXG4gIHZhciBhdHRyaWJ1dGVzID0ge1xuICAgICd4LXBsYWNlbWVudCc6IGRhdGEucGxhY2VtZW50XG4gIH07XG5cbiAgLy8gVXBkYXRlIGBkYXRhYCBhdHRyaWJ1dGVzLCBzdHlsZXMgYW5kIGFycm93U3R5bGVzXG4gIGRhdGEuYXR0cmlidXRlcyA9IF9leHRlbmRzKHt9LCBhdHRyaWJ1dGVzLCBkYXRhLmF0dHJpYnV0ZXMpO1xuICBkYXRhLnN0eWxlcyA9IF9leHRlbmRzKHt9LCBzdHlsZXMsIGRhdGEuc3R5bGVzKTtcbiAgZGF0YS5hcnJvd1N0eWxlcyA9IF9leHRlbmRzKHt9LCBkYXRhLm9mZnNldHMuYXJyb3csIGRhdGEuYXJyb3dTdHlsZXMpO1xuXG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIEhlbHBlciB1c2VkIHRvIGtub3cgaWYgdGhlIGdpdmVuIG1vZGlmaWVyIGRlcGVuZHMgZnJvbSBhbm90aGVyIG9uZS48YnIgLz5cbiAqIEl0IGNoZWNrcyBpZiB0aGUgbmVlZGVkIG1vZGlmaWVyIGlzIGxpc3RlZCBhbmQgZW5hYmxlZC5cbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBwYXJhbSB7QXJyYXl9IG1vZGlmaWVycyAtIGxpc3Qgb2YgbW9kaWZpZXJzXG4gKiBAcGFyYW0ge1N0cmluZ30gcmVxdWVzdGluZ05hbWUgLSBuYW1lIG9mIHJlcXVlc3RpbmcgbW9kaWZpZXJcbiAqIEBwYXJhbSB7U3RyaW5nfSByZXF1ZXN0ZWROYW1lIC0gbmFtZSBvZiByZXF1ZXN0ZWQgbW9kaWZpZXJcbiAqIEByZXR1cm5zIHtCb29sZWFufVxuICovXG5mdW5jdGlvbiBpc01vZGlmaWVyUmVxdWlyZWQobW9kaWZpZXJzLCByZXF1ZXN0aW5nTmFtZSwgcmVxdWVzdGVkTmFtZSkge1xuICB2YXIgcmVxdWVzdGluZyA9IGZpbmQobW9kaWZpZXJzLCBmdW5jdGlvbiAoX3JlZikge1xuICAgIHZhciBuYW1lID0gX3JlZi5uYW1lO1xuICAgIHJldHVybiBuYW1lID09PSByZXF1ZXN0aW5nTmFtZTtcbiAgfSk7XG5cbiAgdmFyIGlzUmVxdWlyZWQgPSAhIXJlcXVlc3RpbmcgJiYgbW9kaWZpZXJzLnNvbWUoZnVuY3Rpb24gKG1vZGlmaWVyKSB7XG4gICAgcmV0dXJuIG1vZGlmaWVyLm5hbWUgPT09IHJlcXVlc3RlZE5hbWUgJiYgbW9kaWZpZXIuZW5hYmxlZCAmJiBtb2RpZmllci5vcmRlciA8IHJlcXVlc3Rpbmcub3JkZXI7XG4gIH0pO1xuXG4gIGlmICghaXNSZXF1aXJlZCkge1xuICAgIHZhciBfcmVxdWVzdGluZyA9ICdgJyArIHJlcXVlc3RpbmdOYW1lICsgJ2AnO1xuICAgIHZhciByZXF1ZXN0ZWQgPSAnYCcgKyByZXF1ZXN0ZWROYW1lICsgJ2AnO1xuICAgIGNvbnNvbGUud2FybihyZXF1ZXN0ZWQgKyAnIG1vZGlmaWVyIGlzIHJlcXVpcmVkIGJ5ICcgKyBfcmVxdWVzdGluZyArICcgbW9kaWZpZXIgaW4gb3JkZXIgdG8gd29yaywgYmUgc3VyZSB0byBpbmNsdWRlIGl0IGJlZm9yZSAnICsgX3JlcXVlc3RpbmcgKyAnIScpO1xuICB9XG4gIHJldHVybiBpc1JlcXVpcmVkO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQG1lbWJlcm9mIE1vZGlmaWVyc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IHVwZGF0ZSBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBkYXRhIG9iamVjdCwgcHJvcGVybHkgbW9kaWZpZWRcbiAqL1xuZnVuY3Rpb24gYXJyb3coZGF0YSwgb3B0aW9ucykge1xuICB2YXIgX2RhdGEkb2Zmc2V0cyRhcnJvdztcblxuICAvLyBhcnJvdyBkZXBlbmRzIG9uIGtlZXBUb2dldGhlciBpbiBvcmRlciB0byB3b3JrXG4gIGlmICghaXNNb2RpZmllclJlcXVpcmVkKGRhdGEuaW5zdGFuY2UubW9kaWZpZXJzLCAnYXJyb3cnLCAna2VlcFRvZ2V0aGVyJykpIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIHZhciBhcnJvd0VsZW1lbnQgPSBvcHRpb25zLmVsZW1lbnQ7XG5cbiAgLy8gaWYgYXJyb3dFbGVtZW50IGlzIGEgc3RyaW5nLCBzdXBwb3NlIGl0J3MgYSBDU1Mgc2VsZWN0b3JcbiAgaWYgKHR5cGVvZiBhcnJvd0VsZW1lbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgYXJyb3dFbGVtZW50ID0gZGF0YS5pbnN0YW5jZS5wb3BwZXIucXVlcnlTZWxlY3RvcihhcnJvd0VsZW1lbnQpO1xuXG4gICAgLy8gaWYgYXJyb3dFbGVtZW50IGlzIG5vdCBmb3VuZCwgZG9uJ3QgcnVuIHRoZSBtb2RpZmllclxuICAgIGlmICghYXJyb3dFbGVtZW50KSB7XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgLy8gaWYgdGhlIGFycm93RWxlbWVudCBpc24ndCBhIHF1ZXJ5IHNlbGVjdG9yIHdlIG11c3QgY2hlY2sgdGhhdCB0aGVcbiAgICAvLyBwcm92aWRlZCBET00gbm9kZSBpcyBjaGlsZCBvZiBpdHMgcG9wcGVyIG5vZGVcbiAgICBpZiAoIWRhdGEuaW5zdGFuY2UucG9wcGVyLmNvbnRhaW5zKGFycm93RWxlbWVudCkpIHtcbiAgICAgIGNvbnNvbGUud2FybignV0FSTklORzogYGFycm93LmVsZW1lbnRgIG11c3QgYmUgY2hpbGQgb2YgaXRzIHBvcHBlciBlbGVtZW50IScpO1xuICAgICAgcmV0dXJuIGRhdGE7XG4gICAgfVxuICB9XG5cbiAgdmFyIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50LnNwbGl0KCctJylbMF07XG4gIHZhciBfZGF0YSRvZmZzZXRzID0gZGF0YS5vZmZzZXRzLFxuICAgICAgcG9wcGVyID0gX2RhdGEkb2Zmc2V0cy5wb3BwZXIsXG4gICAgICByZWZlcmVuY2UgPSBfZGF0YSRvZmZzZXRzLnJlZmVyZW5jZTtcblxuICB2YXIgaXNWZXJ0aWNhbCA9IFsnbGVmdCcsICdyaWdodCddLmluZGV4T2YocGxhY2VtZW50KSAhPT0gLTE7XG5cbiAgdmFyIGxlbiA9IGlzVmVydGljYWwgPyAnaGVpZ2h0JyA6ICd3aWR0aCc7XG4gIHZhciBzaWRlQ2FwaXRhbGl6ZWQgPSBpc1ZlcnRpY2FsID8gJ1RvcCcgOiAnTGVmdCc7XG4gIHZhciBzaWRlID0gc2lkZUNhcGl0YWxpemVkLnRvTG93ZXJDYXNlKCk7XG4gIHZhciBhbHRTaWRlID0gaXNWZXJ0aWNhbCA/ICdsZWZ0JyA6ICd0b3AnO1xuICB2YXIgb3BTaWRlID0gaXNWZXJ0aWNhbCA/ICdib3R0b20nIDogJ3JpZ2h0JztcbiAgdmFyIGFycm93RWxlbWVudFNpemUgPSBnZXRPdXRlclNpemVzKGFycm93RWxlbWVudClbbGVuXTtcblxuICAvL1xuICAvLyBleHRlbmRzIGtlZXBUb2dldGhlciBiZWhhdmlvciBtYWtpbmcgc3VyZSB0aGUgcG9wcGVyIGFuZCBpdHNcbiAgLy8gcmVmZXJlbmNlIGhhdmUgZW5vdWdoIHBpeGVscyBpbiBjb25qdWN0aW9uXG4gIC8vXG5cbiAgLy8gdG9wL2xlZnQgc2lkZVxuICBpZiAocmVmZXJlbmNlW29wU2lkZV0gLSBhcnJvd0VsZW1lbnRTaXplIDwgcG9wcGVyW3NpZGVdKSB7XG4gICAgZGF0YS5vZmZzZXRzLnBvcHBlcltzaWRlXSAtPSBwb3BwZXJbc2lkZV0gLSAocmVmZXJlbmNlW29wU2lkZV0gLSBhcnJvd0VsZW1lbnRTaXplKTtcbiAgfVxuICAvLyBib3R0b20vcmlnaHQgc2lkZVxuICBpZiAocmVmZXJlbmNlW3NpZGVdICsgYXJyb3dFbGVtZW50U2l6ZSA+IHBvcHBlcltvcFNpZGVdKSB7XG4gICAgZGF0YS5vZmZzZXRzLnBvcHBlcltzaWRlXSArPSByZWZlcmVuY2Vbc2lkZV0gKyBhcnJvd0VsZW1lbnRTaXplIC0gcG9wcGVyW29wU2lkZV07XG4gIH1cbiAgZGF0YS5vZmZzZXRzLnBvcHBlciA9IGdldENsaWVudFJlY3QoZGF0YS5vZmZzZXRzLnBvcHBlcik7XG5cbiAgLy8gY29tcHV0ZSBjZW50ZXIgb2YgdGhlIHBvcHBlclxuICB2YXIgY2VudGVyID0gcmVmZXJlbmNlW3NpZGVdICsgcmVmZXJlbmNlW2xlbl0gLyAyIC0gYXJyb3dFbGVtZW50U2l6ZSAvIDI7XG5cbiAgLy8gQ29tcHV0ZSB0aGUgc2lkZVZhbHVlIHVzaW5nIHRoZSB1cGRhdGVkIHBvcHBlciBvZmZzZXRzXG4gIC8vIHRha2UgcG9wcGVyIG1hcmdpbiBpbiBhY2NvdW50IGJlY2F1c2Ugd2UgZG9uJ3QgaGF2ZSB0aGlzIGluZm8gYXZhaWxhYmxlXG4gIHZhciBjc3MgPSBnZXRTdHlsZUNvbXB1dGVkUHJvcGVydHkoZGF0YS5pbnN0YW5jZS5wb3BwZXIpO1xuICB2YXIgcG9wcGVyTWFyZ2luU2lkZSA9IHBhcnNlRmxvYXQoY3NzWydtYXJnaW4nICsgc2lkZUNhcGl0YWxpemVkXSwgMTApO1xuICB2YXIgcG9wcGVyQm9yZGVyU2lkZSA9IHBhcnNlRmxvYXQoY3NzWydib3JkZXInICsgc2lkZUNhcGl0YWxpemVkICsgJ1dpZHRoJ10sIDEwKTtcbiAgdmFyIHNpZGVWYWx1ZSA9IGNlbnRlciAtIGRhdGEub2Zmc2V0cy5wb3BwZXJbc2lkZV0gLSBwb3BwZXJNYXJnaW5TaWRlIC0gcG9wcGVyQm9yZGVyU2lkZTtcblxuICAvLyBwcmV2ZW50IGFycm93RWxlbWVudCBmcm9tIGJlaW5nIHBsYWNlZCBub3QgY29udGlndW91c2x5IHRvIGl0cyBwb3BwZXJcbiAgc2lkZVZhbHVlID0gTWF0aC5tYXgoTWF0aC5taW4ocG9wcGVyW2xlbl0gLSBhcnJvd0VsZW1lbnRTaXplLCBzaWRlVmFsdWUpLCAwKTtcblxuICBkYXRhLmFycm93RWxlbWVudCA9IGFycm93RWxlbWVudDtcbiAgZGF0YS5vZmZzZXRzLmFycm93ID0gKF9kYXRhJG9mZnNldHMkYXJyb3cgPSB7fSwgZGVmaW5lUHJvcGVydHkoX2RhdGEkb2Zmc2V0cyRhcnJvdywgc2lkZSwgTWF0aC5yb3VuZChzaWRlVmFsdWUpKSwgZGVmaW5lUHJvcGVydHkoX2RhdGEkb2Zmc2V0cyRhcnJvdywgYWx0U2lkZSwgJycpLCBfZGF0YSRvZmZzZXRzJGFycm93KTtcblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBHZXQgdGhlIG9wcG9zaXRlIHBsYWNlbWVudCB2YXJpYXRpb24gb2YgdGhlIGdpdmVuIG9uZVxuICogQG1ldGhvZFxuICogQG1lbWJlcm9mIFBvcHBlci5VdGlsc1xuICogQGFyZ3VtZW50IHtTdHJpbmd9IHBsYWNlbWVudCB2YXJpYXRpb25cbiAqIEByZXR1cm5zIHtTdHJpbmd9IGZsaXBwZWQgcGxhY2VtZW50IHZhcmlhdGlvblxuICovXG5mdW5jdGlvbiBnZXRPcHBvc2l0ZVZhcmlhdGlvbih2YXJpYXRpb24pIHtcbiAgaWYgKHZhcmlhdGlvbiA9PT0gJ2VuZCcpIHtcbiAgICByZXR1cm4gJ3N0YXJ0JztcbiAgfSBlbHNlIGlmICh2YXJpYXRpb24gPT09ICdzdGFydCcpIHtcbiAgICByZXR1cm4gJ2VuZCc7XG4gIH1cbiAgcmV0dXJuIHZhcmlhdGlvbjtcbn1cblxuLyoqXG4gKiBMaXN0IG9mIGFjY2VwdGVkIHBsYWNlbWVudHMgdG8gdXNlIGFzIHZhbHVlcyBvZiB0aGUgYHBsYWNlbWVudGAgb3B0aW9uLjxiciAvPlxuICogVmFsaWQgcGxhY2VtZW50cyBhcmU6XG4gKiAtIGBhdXRvYFxuICogLSBgdG9wYFxuICogLSBgcmlnaHRgXG4gKiAtIGBib3R0b21gXG4gKiAtIGBsZWZ0YFxuICpcbiAqIEVhY2ggcGxhY2VtZW50IGNhbiBoYXZlIGEgdmFyaWF0aW9uIGZyb20gdGhpcyBsaXN0OlxuICogLSBgLXN0YXJ0YFxuICogLSBgLWVuZGBcbiAqXG4gKiBWYXJpYXRpb25zIGFyZSBpbnRlcnByZXRlZCBlYXNpbHkgaWYgeW91IHRoaW5rIG9mIHRoZW0gYXMgdGhlIGxlZnQgdG8gcmlnaHRcbiAqIHdyaXR0ZW4gbGFuZ3VhZ2VzLiBIb3Jpem9udGFsbHkgKGB0b3BgIGFuZCBgYm90dG9tYCksIGBzdGFydGAgaXMgbGVmdCBhbmQgYGVuZGBcbiAqIGlzIHJpZ2h0LjxiciAvPlxuICogVmVydGljYWxseSAoYGxlZnRgIGFuZCBgcmlnaHRgKSwgYHN0YXJ0YCBpcyB0b3AgYW5kIGBlbmRgIGlzIGJvdHRvbS5cbiAqXG4gKiBTb21lIHZhbGlkIGV4YW1wbGVzIGFyZTpcbiAqIC0gYHRvcC1lbmRgIChvbiB0b3Agb2YgcmVmZXJlbmNlLCByaWdodCBhbGlnbmVkKVxuICogLSBgcmlnaHQtc3RhcnRgIChvbiByaWdodCBvZiByZWZlcmVuY2UsIHRvcCBhbGlnbmVkKVxuICogLSBgYm90dG9tYCAob24gYm90dG9tLCBjZW50ZXJlZClcbiAqIC0gYGF1dG8tcmlnaHRgIChvbiB0aGUgc2lkZSB3aXRoIG1vcmUgc3BhY2UgYXZhaWxhYmxlLCBhbGlnbm1lbnQgZGVwZW5kcyBieSBwbGFjZW1lbnQpXG4gKlxuICogQHN0YXRpY1xuICogQHR5cGUge0FycmF5fVxuICogQGVudW0ge1N0cmluZ31cbiAqIEByZWFkb25seVxuICogQG1ldGhvZCBwbGFjZW1lbnRzXG4gKiBAbWVtYmVyb2YgUG9wcGVyXG4gKi9cbnZhciBwbGFjZW1lbnRzID0gWydhdXRvLXN0YXJ0JywgJ2F1dG8nLCAnYXV0by1lbmQnLCAndG9wLXN0YXJ0JywgJ3RvcCcsICd0b3AtZW5kJywgJ3JpZ2h0LXN0YXJ0JywgJ3JpZ2h0JywgJ3JpZ2h0LWVuZCcsICdib3R0b20tZW5kJywgJ2JvdHRvbScsICdib3R0b20tc3RhcnQnLCAnbGVmdC1lbmQnLCAnbGVmdCcsICdsZWZ0LXN0YXJ0J107XG5cbi8vIEdldCByaWQgb2YgYGF1dG9gIGBhdXRvLXN0YXJ0YCBhbmQgYGF1dG8tZW5kYFxudmFyIHZhbGlkUGxhY2VtZW50cyA9IHBsYWNlbWVudHMuc2xpY2UoMyk7XG5cbi8qKlxuICogR2l2ZW4gYW4gaW5pdGlhbCBwbGFjZW1lbnQsIHJldHVybnMgYWxsIHRoZSBzdWJzZXF1ZW50IHBsYWNlbWVudHNcbiAqIGNsb2Nrd2lzZSAob3IgY291bnRlci1jbG9ja3dpc2UpLlxuICpcbiAqIEBtZXRob2RcbiAqIEBtZW1iZXJvZiBQb3BwZXIuVXRpbHNcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBwbGFjZW1lbnQgLSBBIHZhbGlkIHBsYWNlbWVudCAoaXQgYWNjZXB0cyB2YXJpYXRpb25zKVxuICogQGFyZ3VtZW50IHtCb29sZWFufSBjb3VudGVyIC0gU2V0IHRvIHRydWUgdG8gd2FsayB0aGUgcGxhY2VtZW50cyBjb3VudGVyY2xvY2t3aXNlXG4gKiBAcmV0dXJucyB7QXJyYXl9IHBsYWNlbWVudHMgaW5jbHVkaW5nIHRoZWlyIHZhcmlhdGlvbnNcbiAqL1xuZnVuY3Rpb24gY2xvY2t3aXNlKHBsYWNlbWVudCkge1xuICB2YXIgY291bnRlciA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogZmFsc2U7XG5cbiAgdmFyIGluZGV4ID0gdmFsaWRQbGFjZW1lbnRzLmluZGV4T2YocGxhY2VtZW50KTtcbiAgdmFyIGFyciA9IHZhbGlkUGxhY2VtZW50cy5zbGljZShpbmRleCArIDEpLmNvbmNhdCh2YWxpZFBsYWNlbWVudHMuc2xpY2UoMCwgaW5kZXgpKTtcbiAgcmV0dXJuIGNvdW50ZXIgPyBhcnIucmV2ZXJzZSgpIDogYXJyO1xufVxuXG52YXIgQkVIQVZJT1JTID0ge1xuICBGTElQOiAnZmxpcCcsXG4gIENMT0NLV0lTRTogJ2Nsb2Nrd2lzZScsXG4gIENPVU5URVJDTE9DS1dJU0U6ICdjb3VudGVyY2xvY2t3aXNlJ1xufTtcblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSB1cGRhdGUgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIGZsaXAoZGF0YSwgb3B0aW9ucykge1xuICAvLyBpZiBgaW5uZXJgIG1vZGlmaWVyIGlzIGVuYWJsZWQsIHdlIGNhbid0IHVzZSB0aGUgYGZsaXBgIG1vZGlmaWVyXG4gIGlmIChpc01vZGlmaWVyRW5hYmxlZChkYXRhLmluc3RhbmNlLm1vZGlmaWVycywgJ2lubmVyJykpIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuXG4gIGlmIChkYXRhLmZsaXBwZWQgJiYgZGF0YS5wbGFjZW1lbnQgPT09IGRhdGEub3JpZ2luYWxQbGFjZW1lbnQpIHtcbiAgICAvLyBzZWVtcyBsaWtlIGZsaXAgaXMgdHJ5aW5nIHRvIGxvb3AsIHByb2JhYmx5IHRoZXJlJ3Mgbm90IGVub3VnaCBzcGFjZSBvbiBhbnkgb2YgdGhlIGZsaXBwYWJsZSBzaWRlc1xuICAgIHJldHVybiBkYXRhO1xuICB9XG5cbiAgdmFyIGJvdW5kYXJpZXMgPSBnZXRCb3VuZGFyaWVzKGRhdGEuaW5zdGFuY2UucG9wcGVyLCBkYXRhLmluc3RhbmNlLnJlZmVyZW5jZSwgb3B0aW9ucy5wYWRkaW5nLCBvcHRpb25zLmJvdW5kYXJpZXNFbGVtZW50KTtcblxuICB2YXIgcGxhY2VtZW50ID0gZGF0YS5wbGFjZW1lbnQuc3BsaXQoJy0nKVswXTtcbiAgdmFyIHBsYWNlbWVudE9wcG9zaXRlID0gZ2V0T3Bwb3NpdGVQbGFjZW1lbnQocGxhY2VtZW50KTtcbiAgdmFyIHZhcmlhdGlvbiA9IGRhdGEucGxhY2VtZW50LnNwbGl0KCctJylbMV0gfHwgJyc7XG5cbiAgdmFyIGZsaXBPcmRlciA9IFtdO1xuXG4gIHN3aXRjaCAob3B0aW9ucy5iZWhhdmlvcikge1xuICAgIGNhc2UgQkVIQVZJT1JTLkZMSVA6XG4gICAgICBmbGlwT3JkZXIgPSBbcGxhY2VtZW50LCBwbGFjZW1lbnRPcHBvc2l0ZV07XG4gICAgICBicmVhaztcbiAgICBjYXNlIEJFSEFWSU9SUy5DTE9DS1dJU0U6XG4gICAgICBmbGlwT3JkZXIgPSBjbG9ja3dpc2UocGxhY2VtZW50KTtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgQkVIQVZJT1JTLkNPVU5URVJDTE9DS1dJU0U6XG4gICAgICBmbGlwT3JkZXIgPSBjbG9ja3dpc2UocGxhY2VtZW50LCB0cnVlKTtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBmbGlwT3JkZXIgPSBvcHRpb25zLmJlaGF2aW9yO1xuICB9XG5cbiAgZmxpcE9yZGVyLmZvckVhY2goZnVuY3Rpb24gKHN0ZXAsIGluZGV4KSB7XG4gICAgaWYgKHBsYWNlbWVudCAhPT0gc3RlcCB8fCBmbGlwT3JkZXIubGVuZ3RoID09PSBpbmRleCArIDEpIHtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50LnNwbGl0KCctJylbMF07XG4gICAgcGxhY2VtZW50T3Bwb3NpdGUgPSBnZXRPcHBvc2l0ZVBsYWNlbWVudChwbGFjZW1lbnQpO1xuXG4gICAgdmFyIHBvcHBlck9mZnNldHMgPSBkYXRhLm9mZnNldHMucG9wcGVyO1xuICAgIHZhciByZWZPZmZzZXRzID0gZGF0YS5vZmZzZXRzLnJlZmVyZW5jZTtcblxuICAgIC8vIHVzaW5nIGZsb29yIGJlY2F1c2UgdGhlIHJlZmVyZW5jZSBvZmZzZXRzIG1heSBjb250YWluIGRlY2ltYWxzIHdlIGFyZSBub3QgZ29pbmcgdG8gY29uc2lkZXIgaGVyZVxuICAgIHZhciBmbG9vciA9IE1hdGguZmxvb3I7XG4gICAgdmFyIG92ZXJsYXBzUmVmID0gcGxhY2VtZW50ID09PSAnbGVmdCcgJiYgZmxvb3IocG9wcGVyT2Zmc2V0cy5yaWdodCkgPiBmbG9vcihyZWZPZmZzZXRzLmxlZnQpIHx8IHBsYWNlbWVudCA9PT0gJ3JpZ2h0JyAmJiBmbG9vcihwb3BwZXJPZmZzZXRzLmxlZnQpIDwgZmxvb3IocmVmT2Zmc2V0cy5yaWdodCkgfHwgcGxhY2VtZW50ID09PSAndG9wJyAmJiBmbG9vcihwb3BwZXJPZmZzZXRzLmJvdHRvbSkgPiBmbG9vcihyZWZPZmZzZXRzLnRvcCkgfHwgcGxhY2VtZW50ID09PSAnYm90dG9tJyAmJiBmbG9vcihwb3BwZXJPZmZzZXRzLnRvcCkgPCBmbG9vcihyZWZPZmZzZXRzLmJvdHRvbSk7XG5cbiAgICB2YXIgb3ZlcmZsb3dzTGVmdCA9IGZsb29yKHBvcHBlck9mZnNldHMubGVmdCkgPCBmbG9vcihib3VuZGFyaWVzLmxlZnQpO1xuICAgIHZhciBvdmVyZmxvd3NSaWdodCA9IGZsb29yKHBvcHBlck9mZnNldHMucmlnaHQpID4gZmxvb3IoYm91bmRhcmllcy5yaWdodCk7XG4gICAgdmFyIG92ZXJmbG93c1RvcCA9IGZsb29yKHBvcHBlck9mZnNldHMudG9wKSA8IGZsb29yKGJvdW5kYXJpZXMudG9wKTtcbiAgICB2YXIgb3ZlcmZsb3dzQm90dG9tID0gZmxvb3IocG9wcGVyT2Zmc2V0cy5ib3R0b20pID4gZmxvb3IoYm91bmRhcmllcy5ib3R0b20pO1xuXG4gICAgdmFyIG92ZXJmbG93c0JvdW5kYXJpZXMgPSBwbGFjZW1lbnQgPT09ICdsZWZ0JyAmJiBvdmVyZmxvd3NMZWZ0IHx8IHBsYWNlbWVudCA9PT0gJ3JpZ2h0JyAmJiBvdmVyZmxvd3NSaWdodCB8fCBwbGFjZW1lbnQgPT09ICd0b3AnICYmIG92ZXJmbG93c1RvcCB8fCBwbGFjZW1lbnQgPT09ICdib3R0b20nICYmIG92ZXJmbG93c0JvdHRvbTtcblxuICAgIC8vIGZsaXAgdGhlIHZhcmlhdGlvbiBpZiByZXF1aXJlZFxuICAgIHZhciBpc1ZlcnRpY2FsID0gWyd0b3AnLCAnYm90dG9tJ10uaW5kZXhPZihwbGFjZW1lbnQpICE9PSAtMTtcbiAgICB2YXIgZmxpcHBlZFZhcmlhdGlvbiA9ICEhb3B0aW9ucy5mbGlwVmFyaWF0aW9ucyAmJiAoaXNWZXJ0aWNhbCAmJiB2YXJpYXRpb24gPT09ICdzdGFydCcgJiYgb3ZlcmZsb3dzTGVmdCB8fCBpc1ZlcnRpY2FsICYmIHZhcmlhdGlvbiA9PT0gJ2VuZCcgJiYgb3ZlcmZsb3dzUmlnaHQgfHwgIWlzVmVydGljYWwgJiYgdmFyaWF0aW9uID09PSAnc3RhcnQnICYmIG92ZXJmbG93c1RvcCB8fCAhaXNWZXJ0aWNhbCAmJiB2YXJpYXRpb24gPT09ICdlbmQnICYmIG92ZXJmbG93c0JvdHRvbSk7XG5cbiAgICBpZiAob3ZlcmxhcHNSZWYgfHwgb3ZlcmZsb3dzQm91bmRhcmllcyB8fCBmbGlwcGVkVmFyaWF0aW9uKSB7XG4gICAgICAvLyB0aGlzIGJvb2xlYW4gdG8gZGV0ZWN0IGFueSBmbGlwIGxvb3BcbiAgICAgIGRhdGEuZmxpcHBlZCA9IHRydWU7XG5cbiAgICAgIGlmIChvdmVybGFwc1JlZiB8fCBvdmVyZmxvd3NCb3VuZGFyaWVzKSB7XG4gICAgICAgIHBsYWNlbWVudCA9IGZsaXBPcmRlcltpbmRleCArIDFdO1xuICAgICAgfVxuXG4gICAgICBpZiAoZmxpcHBlZFZhcmlhdGlvbikge1xuICAgICAgICB2YXJpYXRpb24gPSBnZXRPcHBvc2l0ZVZhcmlhdGlvbih2YXJpYXRpb24pO1xuICAgICAgfVxuXG4gICAgICBkYXRhLnBsYWNlbWVudCA9IHBsYWNlbWVudCArICh2YXJpYXRpb24gPyAnLScgKyB2YXJpYXRpb24gOiAnJyk7XG5cbiAgICAgIC8vIHRoaXMgb2JqZWN0IGNvbnRhaW5zIGBwb3NpdGlvbmAsIHdlIHdhbnQgdG8gcHJlc2VydmUgaXQgYWxvbmcgd2l0aFxuICAgICAgLy8gYW55IGFkZGl0aW9uYWwgcHJvcGVydHkgd2UgbWF5IGFkZCBpbiB0aGUgZnV0dXJlXG4gICAgICBkYXRhLm9mZnNldHMucG9wcGVyID0gX2V4dGVuZHMoe30sIGRhdGEub2Zmc2V0cy5wb3BwZXIsIGdldFBvcHBlck9mZnNldHMoZGF0YS5pbnN0YW5jZS5wb3BwZXIsIGRhdGEub2Zmc2V0cy5yZWZlcmVuY2UsIGRhdGEucGxhY2VtZW50KSk7XG5cbiAgICAgIGRhdGEgPSBydW5Nb2RpZmllcnMoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsIGRhdGEsICdmbGlwJyk7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgdXBkYXRlIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBrZWVwVG9nZXRoZXIoZGF0YSkge1xuICB2YXIgX2RhdGEkb2Zmc2V0cyA9IGRhdGEub2Zmc2V0cyxcbiAgICAgIHBvcHBlciA9IF9kYXRhJG9mZnNldHMucG9wcGVyLFxuICAgICAgcmVmZXJlbmNlID0gX2RhdGEkb2Zmc2V0cy5yZWZlcmVuY2U7XG5cbiAgdmFyIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50LnNwbGl0KCctJylbMF07XG4gIHZhciBmbG9vciA9IE1hdGguZmxvb3I7XG4gIHZhciBpc1ZlcnRpY2FsID0gWyd0b3AnLCAnYm90dG9tJ10uaW5kZXhPZihwbGFjZW1lbnQpICE9PSAtMTtcbiAgdmFyIHNpZGUgPSBpc1ZlcnRpY2FsID8gJ3JpZ2h0JyA6ICdib3R0b20nO1xuICB2YXIgb3BTaWRlID0gaXNWZXJ0aWNhbCA/ICdsZWZ0JyA6ICd0b3AnO1xuICB2YXIgbWVhc3VyZW1lbnQgPSBpc1ZlcnRpY2FsID8gJ3dpZHRoJyA6ICdoZWlnaHQnO1xuXG4gIGlmIChwb3BwZXJbc2lkZV0gPCBmbG9vcihyZWZlcmVuY2Vbb3BTaWRlXSkpIHtcbiAgICBkYXRhLm9mZnNldHMucG9wcGVyW29wU2lkZV0gPSBmbG9vcihyZWZlcmVuY2Vbb3BTaWRlXSkgLSBwb3BwZXJbbWVhc3VyZW1lbnRdO1xuICB9XG4gIGlmIChwb3BwZXJbb3BTaWRlXSA+IGZsb29yKHJlZmVyZW5jZVtzaWRlXSkpIHtcbiAgICBkYXRhLm9mZnNldHMucG9wcGVyW29wU2lkZV0gPSBmbG9vcihyZWZlcmVuY2Vbc2lkZV0pO1xuICB9XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQ29udmVydHMgYSBzdHJpbmcgY29udGFpbmluZyB2YWx1ZSArIHVuaXQgaW50byBhIHB4IHZhbHVlIG51bWJlclxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2Yge21vZGlmaWVyc35vZmZzZXR9XG4gKiBAcHJpdmF0ZVxuICogQGFyZ3VtZW50IHtTdHJpbmd9IHN0ciAtIFZhbHVlICsgdW5pdCBzdHJpbmdcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBtZWFzdXJlbWVudCAtIGBoZWlnaHRgIG9yIGB3aWR0aGBcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBwb3BwZXJPZmZzZXRzXG4gKiBAYXJndW1lbnQge09iamVjdH0gcmVmZXJlbmNlT2Zmc2V0c1xuICogQHJldHVybnMge051bWJlcnxTdHJpbmd9XG4gKiBWYWx1ZSBpbiBwaXhlbHMsIG9yIG9yaWdpbmFsIHN0cmluZyBpZiBubyB2YWx1ZXMgd2VyZSBleHRyYWN0ZWRcbiAqL1xuZnVuY3Rpb24gdG9WYWx1ZShzdHIsIG1lYXN1cmVtZW50LCBwb3BwZXJPZmZzZXRzLCByZWZlcmVuY2VPZmZzZXRzKSB7XG4gIC8vIHNlcGFyYXRlIHZhbHVlIGZyb20gdW5pdFxuICB2YXIgc3BsaXQgPSBzdHIubWF0Y2goLygoPzpcXC18XFwrKT9cXGQqXFwuP1xcZCopKC4qKS8pO1xuICB2YXIgdmFsdWUgPSArc3BsaXRbMV07XG4gIHZhciB1bml0ID0gc3BsaXRbMl07XG5cbiAgLy8gSWYgaXQncyBub3QgYSBudW1iZXIgaXQncyBhbiBvcGVyYXRvciwgSSBndWVzc1xuICBpZiAoIXZhbHVlKSB7XG4gICAgcmV0dXJuIHN0cjtcbiAgfVxuXG4gIGlmICh1bml0LmluZGV4T2YoJyUnKSA9PT0gMCkge1xuICAgIHZhciBlbGVtZW50ID0gdm9pZCAwO1xuICAgIHN3aXRjaCAodW5pdCkge1xuICAgICAgY2FzZSAnJXAnOlxuICAgICAgICBlbGVtZW50ID0gcG9wcGVyT2Zmc2V0cztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICclJzpcbiAgICAgIGNhc2UgJyVyJzpcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGVsZW1lbnQgPSByZWZlcmVuY2VPZmZzZXRzO1xuICAgIH1cblxuICAgIHZhciByZWN0ID0gZ2V0Q2xpZW50UmVjdChlbGVtZW50KTtcbiAgICByZXR1cm4gcmVjdFttZWFzdXJlbWVudF0gLyAxMDAgKiB2YWx1ZTtcbiAgfSBlbHNlIGlmICh1bml0ID09PSAndmgnIHx8IHVuaXQgPT09ICd2dycpIHtcbiAgICAvLyBpZiBpcyBhIHZoIG9yIHZ3LCB3ZSBjYWxjdWxhdGUgdGhlIHNpemUgYmFzZWQgb24gdGhlIHZpZXdwb3J0XG4gICAgdmFyIHNpemUgPSB2b2lkIDA7XG4gICAgaWYgKHVuaXQgPT09ICd2aCcpIHtcbiAgICAgIHNpemUgPSBNYXRoLm1heChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0LCB3aW5kb3cuaW5uZXJIZWlnaHQgfHwgMCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNpemUgPSBNYXRoLm1heChkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50V2lkdGgsIHdpbmRvdy5pbm5lcldpZHRoIHx8IDApO1xuICAgIH1cbiAgICByZXR1cm4gc2l6ZSAvIDEwMCAqIHZhbHVlO1xuICB9IGVsc2Uge1xuICAgIC8vIGlmIGlzIGFuIGV4cGxpY2l0IHBpeGVsIHVuaXQsIHdlIGdldCByaWQgb2YgdGhlIHVuaXQgYW5kIGtlZXAgdGhlIHZhbHVlXG4gICAgLy8gaWYgaXMgYW4gaW1wbGljaXQgdW5pdCwgaXQncyBweCwgYW5kIHdlIHJldHVybiBqdXN0IHRoZSB2YWx1ZVxuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxufVxuXG4vKipcbiAqIFBhcnNlIGFuIGBvZmZzZXRgIHN0cmluZyB0byBleHRyYXBvbGF0ZSBgeGAgYW5kIGB5YCBudW1lcmljIG9mZnNldHMuXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiB7bW9kaWZpZXJzfm9mZnNldH1cbiAqIEBwcml2YXRlXG4gKiBAYXJndW1lbnQge1N0cmluZ30gb2Zmc2V0XG4gKiBAYXJndW1lbnQge09iamVjdH0gcG9wcGVyT2Zmc2V0c1xuICogQGFyZ3VtZW50IHtPYmplY3R9IHJlZmVyZW5jZU9mZnNldHNcbiAqIEBhcmd1bWVudCB7U3RyaW5nfSBiYXNlUGxhY2VtZW50XG4gKiBAcmV0dXJucyB7QXJyYXl9IGEgdHdvIGNlbGxzIGFycmF5IHdpdGggeCBhbmQgeSBvZmZzZXRzIGluIG51bWJlcnNcbiAqL1xuZnVuY3Rpb24gcGFyc2VPZmZzZXQob2Zmc2V0LCBwb3BwZXJPZmZzZXRzLCByZWZlcmVuY2VPZmZzZXRzLCBiYXNlUGxhY2VtZW50KSB7XG4gIHZhciBvZmZzZXRzID0gWzAsIDBdO1xuXG4gIC8vIFVzZSBoZWlnaHQgaWYgcGxhY2VtZW50IGlzIGxlZnQgb3IgcmlnaHQgYW5kIGluZGV4IGlzIDAgb3RoZXJ3aXNlIHVzZSB3aWR0aFxuICAvLyBpbiB0aGlzIHdheSB0aGUgZmlyc3Qgb2Zmc2V0IHdpbGwgdXNlIGFuIGF4aXMgYW5kIHRoZSBzZWNvbmQgb25lXG4gIC8vIHdpbGwgdXNlIHRoZSBvdGhlciBvbmVcbiAgdmFyIHVzZUhlaWdodCA9IFsncmlnaHQnLCAnbGVmdCddLmluZGV4T2YoYmFzZVBsYWNlbWVudCkgIT09IC0xO1xuXG4gIC8vIFNwbGl0IHRoZSBvZmZzZXQgc3RyaW5nIHRvIG9idGFpbiBhIGxpc3Qgb2YgdmFsdWVzIGFuZCBvcGVyYW5kc1xuICAvLyBUaGUgcmVnZXggYWRkcmVzc2VzIHZhbHVlcyB3aXRoIHRoZSBwbHVzIG9yIG1pbnVzIHNpZ24gaW4gZnJvbnQgKCsxMCwgLTIwLCBldGMpXG4gIHZhciBmcmFnbWVudHMgPSBvZmZzZXQuc3BsaXQoLyhcXCt8XFwtKS8pLm1hcChmdW5jdGlvbiAoZnJhZykge1xuICAgIHJldHVybiBmcmFnLnRyaW0oKTtcbiAgfSk7XG5cbiAgLy8gRGV0ZWN0IGlmIHRoZSBvZmZzZXQgc3RyaW5nIGNvbnRhaW5zIGEgcGFpciBvZiB2YWx1ZXMgb3IgYSBzaW5nbGUgb25lXG4gIC8vIHRoZXkgY291bGQgYmUgc2VwYXJhdGVkIGJ5IGNvbW1hIG9yIHNwYWNlXG4gIHZhciBkaXZpZGVyID0gZnJhZ21lbnRzLmluZGV4T2YoZmluZChmcmFnbWVudHMsIGZ1bmN0aW9uIChmcmFnKSB7XG4gICAgcmV0dXJuIGZyYWcuc2VhcmNoKC8sfFxccy8pICE9PSAtMTtcbiAgfSkpO1xuXG4gIGlmIChmcmFnbWVudHNbZGl2aWRlcl0gJiYgZnJhZ21lbnRzW2RpdmlkZXJdLmluZGV4T2YoJywnKSA9PT0gLTEpIHtcbiAgICBjb25zb2xlLndhcm4oJ09mZnNldHMgc2VwYXJhdGVkIGJ5IHdoaXRlIHNwYWNlKHMpIGFyZSBkZXByZWNhdGVkLCB1c2UgYSBjb21tYSAoLCkgaW5zdGVhZC4nKTtcbiAgfVxuXG4gIC8vIElmIGRpdmlkZXIgaXMgZm91bmQsIHdlIGRpdmlkZSB0aGUgbGlzdCBvZiB2YWx1ZXMgYW5kIG9wZXJhbmRzIHRvIGRpdmlkZVxuICAvLyB0aGVtIGJ5IG9mc2V0IFggYW5kIFkuXG4gIHZhciBzcGxpdFJlZ2V4ID0gL1xccyosXFxzKnxcXHMrLztcbiAgdmFyIG9wcyA9IGRpdmlkZXIgIT09IC0xID8gW2ZyYWdtZW50cy5zbGljZSgwLCBkaXZpZGVyKS5jb25jYXQoW2ZyYWdtZW50c1tkaXZpZGVyXS5zcGxpdChzcGxpdFJlZ2V4KVswXV0pLCBbZnJhZ21lbnRzW2RpdmlkZXJdLnNwbGl0KHNwbGl0UmVnZXgpWzFdXS5jb25jYXQoZnJhZ21lbnRzLnNsaWNlKGRpdmlkZXIgKyAxKSldIDogW2ZyYWdtZW50c107XG5cbiAgLy8gQ29udmVydCB0aGUgdmFsdWVzIHdpdGggdW5pdHMgdG8gYWJzb2x1dGUgcGl4ZWxzIHRvIGFsbG93IG91ciBjb21wdXRhdGlvbnNcbiAgb3BzID0gb3BzLm1hcChmdW5jdGlvbiAob3AsIGluZGV4KSB7XG4gICAgLy8gTW9zdCBvZiB0aGUgdW5pdHMgcmVseSBvbiB0aGUgb3JpZW50YXRpb24gb2YgdGhlIHBvcHBlclxuICAgIHZhciBtZWFzdXJlbWVudCA9IChpbmRleCA9PT0gMSA/ICF1c2VIZWlnaHQgOiB1c2VIZWlnaHQpID8gJ2hlaWdodCcgOiAnd2lkdGgnO1xuICAgIHZhciBtZXJnZVdpdGhQcmV2aW91cyA9IGZhbHNlO1xuICAgIHJldHVybiBvcFxuICAgIC8vIFRoaXMgYWdncmVnYXRlcyBhbnkgYCtgIG9yIGAtYCBzaWduIHRoYXQgYXJlbid0IGNvbnNpZGVyZWQgb3BlcmF0b3JzXG4gICAgLy8gZS5nLjogMTAgKyArNSA9PiBbMTAsICssICs1XVxuICAgIC5yZWR1Y2UoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIGlmIChhW2EubGVuZ3RoIC0gMV0gPT09ICcnICYmIFsnKycsICctJ10uaW5kZXhPZihiKSAhPT0gLTEpIHtcbiAgICAgICAgYVthLmxlbmd0aCAtIDFdID0gYjtcbiAgICAgICAgbWVyZ2VXaXRoUHJldmlvdXMgPSB0cnVlO1xuICAgICAgICByZXR1cm4gYTtcbiAgICAgIH0gZWxzZSBpZiAobWVyZ2VXaXRoUHJldmlvdXMpIHtcbiAgICAgICAgYVthLmxlbmd0aCAtIDFdICs9IGI7XG4gICAgICAgIG1lcmdlV2l0aFByZXZpb3VzID0gZmFsc2U7XG4gICAgICAgIHJldHVybiBhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGEuY29uY2F0KGIpO1xuICAgICAgfVxuICAgIH0sIFtdKVxuICAgIC8vIEhlcmUgd2UgY29udmVydCB0aGUgc3RyaW5nIHZhbHVlcyBpbnRvIG51bWJlciB2YWx1ZXMgKGluIHB4KVxuICAgIC5tYXAoZnVuY3Rpb24gKHN0cikge1xuICAgICAgcmV0dXJuIHRvVmFsdWUoc3RyLCBtZWFzdXJlbWVudCwgcG9wcGVyT2Zmc2V0cywgcmVmZXJlbmNlT2Zmc2V0cyk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIC8vIExvb3AgdHJvdWdoIHRoZSBvZmZzZXRzIGFycmF5cyBhbmQgZXhlY3V0ZSB0aGUgb3BlcmF0aW9uc1xuICBvcHMuZm9yRWFjaChmdW5jdGlvbiAob3AsIGluZGV4KSB7XG4gICAgb3AuZm9yRWFjaChmdW5jdGlvbiAoZnJhZywgaW5kZXgyKSB7XG4gICAgICBpZiAoaXNOdW1lcmljKGZyYWcpKSB7XG4gICAgICAgIG9mZnNldHNbaW5kZXhdICs9IGZyYWcgKiAob3BbaW5kZXgyIC0gMV0gPT09ICctJyA/IC0xIDogMSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0pO1xuICByZXR1cm4gb2Zmc2V0cztcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSB1cGRhdGUgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAYXJndW1lbnQge051bWJlcnxTdHJpbmd9IG9wdGlvbnMub2Zmc2V0PTBcbiAqIFRoZSBvZmZzZXQgdmFsdWUgYXMgZGVzY3JpYmVkIGluIHRoZSBtb2RpZmllciBkZXNjcmlwdGlvblxuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBvZmZzZXQoZGF0YSwgX3JlZikge1xuICB2YXIgb2Zmc2V0ID0gX3JlZi5vZmZzZXQ7XG4gIHZhciBwbGFjZW1lbnQgPSBkYXRhLnBsYWNlbWVudCxcbiAgICAgIF9kYXRhJG9mZnNldHMgPSBkYXRhLm9mZnNldHMsXG4gICAgICBwb3BwZXIgPSBfZGF0YSRvZmZzZXRzLnBvcHBlcixcbiAgICAgIHJlZmVyZW5jZSA9IF9kYXRhJG9mZnNldHMucmVmZXJlbmNlO1xuXG4gIHZhciBiYXNlUGxhY2VtZW50ID0gcGxhY2VtZW50LnNwbGl0KCctJylbMF07XG5cbiAgdmFyIG9mZnNldHMgPSB2b2lkIDA7XG4gIGlmIChpc051bWVyaWMoK29mZnNldCkpIHtcbiAgICBvZmZzZXRzID0gWytvZmZzZXQsIDBdO1xuICB9IGVsc2Uge1xuICAgIG9mZnNldHMgPSBwYXJzZU9mZnNldChvZmZzZXQsIHBvcHBlciwgcmVmZXJlbmNlLCBiYXNlUGxhY2VtZW50KTtcbiAgfVxuXG4gIGlmIChiYXNlUGxhY2VtZW50ID09PSAnbGVmdCcpIHtcbiAgICBwb3BwZXIudG9wICs9IG9mZnNldHNbMF07XG4gICAgcG9wcGVyLmxlZnQgLT0gb2Zmc2V0c1sxXTtcbiAgfSBlbHNlIGlmIChiYXNlUGxhY2VtZW50ID09PSAncmlnaHQnKSB7XG4gICAgcG9wcGVyLnRvcCArPSBvZmZzZXRzWzBdO1xuICAgIHBvcHBlci5sZWZ0ICs9IG9mZnNldHNbMV07XG4gIH0gZWxzZSBpZiAoYmFzZVBsYWNlbWVudCA9PT0gJ3RvcCcpIHtcbiAgICBwb3BwZXIubGVmdCArPSBvZmZzZXRzWzBdO1xuICAgIHBvcHBlci50b3AgLT0gb2Zmc2V0c1sxXTtcbiAgfSBlbHNlIGlmIChiYXNlUGxhY2VtZW50ID09PSAnYm90dG9tJykge1xuICAgIHBvcHBlci5sZWZ0ICs9IG9mZnNldHNbMF07XG4gICAgcG9wcGVyLnRvcCArPSBvZmZzZXRzWzFdO1xuICB9XG5cbiAgZGF0YS5wb3BwZXIgPSBwb3BwZXI7XG4gIHJldHVybiBkYXRhO1xufVxuXG4vKipcbiAqIEBmdW5jdGlvblxuICogQG1lbWJlcm9mIE1vZGlmaWVyc1xuICogQGFyZ3VtZW50IHtPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IGB1cGRhdGVgIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBwcmV2ZW50T3ZlcmZsb3coZGF0YSwgb3B0aW9ucykge1xuICB2YXIgYm91bmRhcmllc0VsZW1lbnQgPSBvcHRpb25zLmJvdW5kYXJpZXNFbGVtZW50IHx8IGdldE9mZnNldFBhcmVudChkYXRhLmluc3RhbmNlLnBvcHBlcik7XG5cbiAgLy8gSWYgb2Zmc2V0UGFyZW50IGlzIHRoZSByZWZlcmVuY2UgZWxlbWVudCwgd2UgcmVhbGx5IHdhbnQgdG9cbiAgLy8gZ28gb25lIHN0ZXAgdXAgYW5kIHVzZSB0aGUgbmV4dCBvZmZzZXRQYXJlbnQgYXMgcmVmZXJlbmNlIHRvXG4gIC8vIGF2b2lkIHRvIG1ha2UgdGhpcyBtb2RpZmllciBjb21wbGV0ZWx5IHVzZWxlc3MgYW5kIGxvb2sgbGlrZSBicm9rZW5cbiAgaWYgKGRhdGEuaW5zdGFuY2UucmVmZXJlbmNlID09PSBib3VuZGFyaWVzRWxlbWVudCkge1xuICAgIGJvdW5kYXJpZXNFbGVtZW50ID0gZ2V0T2Zmc2V0UGFyZW50KGJvdW5kYXJpZXNFbGVtZW50KTtcbiAgfVxuXG4gIHZhciBib3VuZGFyaWVzID0gZ2V0Qm91bmRhcmllcyhkYXRhLmluc3RhbmNlLnBvcHBlciwgZGF0YS5pbnN0YW5jZS5yZWZlcmVuY2UsIG9wdGlvbnMucGFkZGluZywgYm91bmRhcmllc0VsZW1lbnQpO1xuICBvcHRpb25zLmJvdW5kYXJpZXMgPSBib3VuZGFyaWVzO1xuXG4gIHZhciBvcmRlciA9IG9wdGlvbnMucHJpb3JpdHk7XG4gIHZhciBwb3BwZXIgPSBkYXRhLm9mZnNldHMucG9wcGVyO1xuXG4gIHZhciBjaGVjayA9IHtcbiAgICBwcmltYXJ5OiBmdW5jdGlvbiBwcmltYXJ5KHBsYWNlbWVudCkge1xuICAgICAgdmFyIHZhbHVlID0gcG9wcGVyW3BsYWNlbWVudF07XG4gICAgICBpZiAocG9wcGVyW3BsYWNlbWVudF0gPCBib3VuZGFyaWVzW3BsYWNlbWVudF0gJiYgIW9wdGlvbnMuZXNjYXBlV2l0aFJlZmVyZW5jZSkge1xuICAgICAgICB2YWx1ZSA9IE1hdGgubWF4KHBvcHBlcltwbGFjZW1lbnRdLCBib3VuZGFyaWVzW3BsYWNlbWVudF0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRlZmluZVByb3BlcnR5KHt9LCBwbGFjZW1lbnQsIHZhbHVlKTtcbiAgICB9LFxuICAgIHNlY29uZGFyeTogZnVuY3Rpb24gc2Vjb25kYXJ5KHBsYWNlbWVudCkge1xuICAgICAgdmFyIG1haW5TaWRlID0gcGxhY2VtZW50ID09PSAncmlnaHQnID8gJ2xlZnQnIDogJ3RvcCc7XG4gICAgICB2YXIgdmFsdWUgPSBwb3BwZXJbbWFpblNpZGVdO1xuICAgICAgaWYgKHBvcHBlcltwbGFjZW1lbnRdID4gYm91bmRhcmllc1twbGFjZW1lbnRdICYmICFvcHRpb25zLmVzY2FwZVdpdGhSZWZlcmVuY2UpIHtcbiAgICAgICAgdmFsdWUgPSBNYXRoLm1pbihwb3BwZXJbbWFpblNpZGVdLCBib3VuZGFyaWVzW3BsYWNlbWVudF0gLSAocGxhY2VtZW50ID09PSAncmlnaHQnID8gcG9wcGVyLndpZHRoIDogcG9wcGVyLmhlaWdodCkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGRlZmluZVByb3BlcnR5KHt9LCBtYWluU2lkZSwgdmFsdWUpO1xuICAgIH1cbiAgfTtcblxuICBvcmRlci5mb3JFYWNoKGZ1bmN0aW9uIChwbGFjZW1lbnQpIHtcbiAgICB2YXIgc2lkZSA9IFsnbGVmdCcsICd0b3AnXS5pbmRleE9mKHBsYWNlbWVudCkgIT09IC0xID8gJ3ByaW1hcnknIDogJ3NlY29uZGFyeSc7XG4gICAgcG9wcGVyID0gX2V4dGVuZHMoe30sIHBvcHBlciwgY2hlY2tbc2lkZV0ocGxhY2VtZW50KSk7XG4gIH0pO1xuXG4gIGRhdGEub2Zmc2V0cy5wb3BwZXIgPSBwb3BwZXI7XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgYHVwZGF0ZWAgbWV0aG9kXG4gKiBAYXJndW1lbnQge09iamVjdH0gb3B0aW9ucyAtIE1vZGlmaWVycyBjb25maWd1cmF0aW9uIGFuZCBvcHRpb25zXG4gKiBAcmV0dXJucyB7T2JqZWN0fSBUaGUgZGF0YSBvYmplY3QsIHByb3Blcmx5IG1vZGlmaWVkXG4gKi9cbmZ1bmN0aW9uIHNoaWZ0KGRhdGEpIHtcbiAgdmFyIHBsYWNlbWVudCA9IGRhdGEucGxhY2VtZW50O1xuICB2YXIgYmFzZVBsYWNlbWVudCA9IHBsYWNlbWVudC5zcGxpdCgnLScpWzBdO1xuICB2YXIgc2hpZnR2YXJpYXRpb24gPSBwbGFjZW1lbnQuc3BsaXQoJy0nKVsxXTtcblxuICAvLyBpZiBzaGlmdCBzaGlmdHZhcmlhdGlvbiBpcyBzcGVjaWZpZWQsIHJ1biB0aGUgbW9kaWZpZXJcbiAgaWYgKHNoaWZ0dmFyaWF0aW9uKSB7XG4gICAgdmFyIF9kYXRhJG9mZnNldHMgPSBkYXRhLm9mZnNldHMsXG4gICAgICAgIHJlZmVyZW5jZSA9IF9kYXRhJG9mZnNldHMucmVmZXJlbmNlLFxuICAgICAgICBwb3BwZXIgPSBfZGF0YSRvZmZzZXRzLnBvcHBlcjtcblxuICAgIHZhciBpc1ZlcnRpY2FsID0gWydib3R0b20nLCAndG9wJ10uaW5kZXhPZihiYXNlUGxhY2VtZW50KSAhPT0gLTE7XG4gICAgdmFyIHNpZGUgPSBpc1ZlcnRpY2FsID8gJ2xlZnQnIDogJ3RvcCc7XG4gICAgdmFyIG1lYXN1cmVtZW50ID0gaXNWZXJ0aWNhbCA/ICd3aWR0aCcgOiAnaGVpZ2h0JztcblxuICAgIHZhciBzaGlmdE9mZnNldHMgPSB7XG4gICAgICBzdGFydDogZGVmaW5lUHJvcGVydHkoe30sIHNpZGUsIHJlZmVyZW5jZVtzaWRlXSksXG4gICAgICBlbmQ6IGRlZmluZVByb3BlcnR5KHt9LCBzaWRlLCByZWZlcmVuY2Vbc2lkZV0gKyByZWZlcmVuY2VbbWVhc3VyZW1lbnRdIC0gcG9wcGVyW21lYXN1cmVtZW50XSlcbiAgICB9O1xuXG4gICAgZGF0YS5vZmZzZXRzLnBvcHBlciA9IF9leHRlbmRzKHt9LCBwb3BwZXIsIHNoaWZ0T2Zmc2V0c1tzaGlmdHZhcmlhdGlvbl0pO1xuICB9XG5cbiAgcmV0dXJuIGRhdGE7XG59XG5cbi8qKlxuICogQGZ1bmN0aW9uXG4gKiBAbWVtYmVyb2YgTW9kaWZpZXJzXG4gKiBAYXJndW1lbnQge09iamVjdH0gZGF0YSAtIFRoZSBkYXRhIG9iamVjdCBnZW5lcmF0ZWQgYnkgdXBkYXRlIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge09iamVjdH0gVGhlIGRhdGEgb2JqZWN0LCBwcm9wZXJseSBtb2RpZmllZFxuICovXG5mdW5jdGlvbiBoaWRlKGRhdGEpIHtcbiAgaWYgKCFpc01vZGlmaWVyUmVxdWlyZWQoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsICdoaWRlJywgJ3ByZXZlbnRPdmVyZmxvdycpKSB7XG4gICAgcmV0dXJuIGRhdGE7XG4gIH1cblxuICB2YXIgcmVmUmVjdCA9IGRhdGEub2Zmc2V0cy5yZWZlcmVuY2U7XG4gIHZhciBib3VuZCA9IGZpbmQoZGF0YS5pbnN0YW5jZS5tb2RpZmllcnMsIGZ1bmN0aW9uIChtb2RpZmllcikge1xuICAgIHJldHVybiBtb2RpZmllci5uYW1lID09PSAncHJldmVudE92ZXJmbG93JztcbiAgfSkuYm91bmRhcmllcztcblxuICBpZiAocmVmUmVjdC5ib3R0b20gPCBib3VuZC50b3AgfHwgcmVmUmVjdC5sZWZ0ID4gYm91bmQucmlnaHQgfHwgcmVmUmVjdC50b3AgPiBib3VuZC5ib3R0b20gfHwgcmVmUmVjdC5yaWdodCA8IGJvdW5kLmxlZnQpIHtcbiAgICAvLyBBdm9pZCB1bm5lY2Vzc2FyeSBET00gYWNjZXNzIGlmIHZpc2liaWxpdHkgaGFzbid0IGNoYW5nZWRcbiAgICBpZiAoZGF0YS5oaWRlID09PSB0cnVlKSB7XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG5cbiAgICBkYXRhLmhpZGUgPSB0cnVlO1xuICAgIGRhdGEuYXR0cmlidXRlc1sneC1vdXQtb2YtYm91bmRhcmllcyddID0gJyc7XG4gIH0gZWxzZSB7XG4gICAgLy8gQXZvaWQgdW5uZWNlc3NhcnkgRE9NIGFjY2VzcyBpZiB2aXNpYmlsaXR5IGhhc24ndCBjaGFuZ2VkXG4gICAgaWYgKGRhdGEuaGlkZSA9PT0gZmFsc2UpIHtcbiAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cblxuICAgIGRhdGEuaGlkZSA9IGZhbHNlO1xuICAgIGRhdGEuYXR0cmlidXRlc1sneC1vdXQtb2YtYm91bmRhcmllcyddID0gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBAZnVuY3Rpb25cbiAqIEBtZW1iZXJvZiBNb2RpZmllcnNcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBkYXRhIC0gVGhlIGRhdGEgb2JqZWN0IGdlbmVyYXRlZCBieSBgdXBkYXRlYCBtZXRob2RcbiAqIEBhcmd1bWVudCB7T2JqZWN0fSBvcHRpb25zIC0gTW9kaWZpZXJzIGNvbmZpZ3VyYXRpb24gYW5kIG9wdGlvbnNcbiAqIEByZXR1cm5zIHtPYmplY3R9IFRoZSBkYXRhIG9iamVjdCwgcHJvcGVybHkgbW9kaWZpZWRcbiAqL1xuZnVuY3Rpb24gaW5uZXIoZGF0YSkge1xuICB2YXIgcGxhY2VtZW50ID0gZGF0YS5wbGFjZW1lbnQ7XG4gIHZhciBiYXNlUGxhY2VtZW50ID0gcGxhY2VtZW50LnNwbGl0KCctJylbMF07XG4gIHZhciBfZGF0YSRvZmZzZXRzID0gZGF0YS5vZmZzZXRzLFxuICAgICAgcG9wcGVyID0gX2RhdGEkb2Zmc2V0cy5wb3BwZXIsXG4gICAgICByZWZlcmVuY2UgPSBfZGF0YSRvZmZzZXRzLnJlZmVyZW5jZTtcblxuICB2YXIgaXNIb3JpeiA9IFsnbGVmdCcsICdyaWdodCddLmluZGV4T2YoYmFzZVBsYWNlbWVudCkgIT09IC0xO1xuXG4gIHZhciBzdWJ0cmFjdExlbmd0aCA9IFsndG9wJywgJ2xlZnQnXS5pbmRleE9mKGJhc2VQbGFjZW1lbnQpID09PSAtMTtcblxuICBwb3BwZXJbaXNIb3JpeiA/ICdsZWZ0JyA6ICd0b3AnXSA9IHJlZmVyZW5jZVtiYXNlUGxhY2VtZW50XSAtIChzdWJ0cmFjdExlbmd0aCA/IHBvcHBlcltpc0hvcml6ID8gJ3dpZHRoJyA6ICdoZWlnaHQnXSA6IDApO1xuXG4gIGRhdGEucGxhY2VtZW50ID0gZ2V0T3Bwb3NpdGVQbGFjZW1lbnQocGxhY2VtZW50KTtcbiAgZGF0YS5vZmZzZXRzLnBvcHBlciA9IGdldENsaWVudFJlY3QocG9wcGVyKTtcblxuICByZXR1cm4gZGF0YTtcbn1cblxuLyoqXG4gKiBNb2RpZmllciBmdW5jdGlvbiwgZWFjaCBtb2RpZmllciBjYW4gaGF2ZSBhIGZ1bmN0aW9uIG9mIHRoaXMgdHlwZSBhc3NpZ25lZFxuICogdG8gaXRzIGBmbmAgcHJvcGVydHkuPGJyIC8+XG4gKiBUaGVzZSBmdW5jdGlvbnMgd2lsbCBiZSBjYWxsZWQgb24gZWFjaCB1cGRhdGUsIHRoaXMgbWVhbnMgdGhhdCB5b3UgbXVzdFxuICogbWFrZSBzdXJlIHRoZXkgYXJlIHBlcmZvcm1hbnQgZW5vdWdoIHRvIGF2b2lkIHBlcmZvcm1hbmNlIGJvdHRsZW5lY2tzLlxuICpcbiAqIEBmdW5jdGlvbiBNb2RpZmllckZuXG4gKiBAYXJndW1lbnQge2RhdGFPYmplY3R9IGRhdGEgLSBUaGUgZGF0YSBvYmplY3QgZ2VuZXJhdGVkIGJ5IGB1cGRhdGVgIG1ldGhvZFxuICogQGFyZ3VtZW50IHtPYmplY3R9IG9wdGlvbnMgLSBNb2RpZmllcnMgY29uZmlndXJhdGlvbiBhbmQgb3B0aW9uc1xuICogQHJldHVybnMge2RhdGFPYmplY3R9IFRoZSBkYXRhIG9iamVjdCwgcHJvcGVybHkgbW9kaWZpZWRcbiAqL1xuXG4vKipcbiAqIE1vZGlmaWVycyBhcmUgcGx1Z2lucyB1c2VkIHRvIGFsdGVyIHRoZSBiZWhhdmlvciBvZiB5b3VyIHBvcHBlcnMuPGJyIC8+XG4gKiBQb3BwZXIuanMgdXNlcyBhIHNldCBvZiA5IG1vZGlmaWVycyB0byBwcm92aWRlIGFsbCB0aGUgYmFzaWMgZnVuY3Rpb25hbGl0aWVzXG4gKiBuZWVkZWQgYnkgdGhlIGxpYnJhcnkuXG4gKlxuICogVXN1YWxseSB5b3UgZG9uJ3Qgd2FudCB0byBvdmVycmlkZSB0aGUgYG9yZGVyYCwgYGZuYCBhbmQgYG9uTG9hZGAgcHJvcHMuXG4gKiBBbGwgdGhlIG90aGVyIHByb3BlcnRpZXMgYXJlIGNvbmZpZ3VyYXRpb25zIHRoYXQgY291bGQgYmUgdHdlYWtlZC5cbiAqIEBuYW1lc3BhY2UgbW9kaWZpZXJzXG4gKi9cbnZhciBtb2RpZmllcnMgPSB7XG4gIC8qKlxuICAgKiBNb2RpZmllciB1c2VkIHRvIHNoaWZ0IHRoZSBwb3BwZXIgb24gdGhlIHN0YXJ0IG9yIGVuZCBvZiBpdHMgcmVmZXJlbmNlXG4gICAqIGVsZW1lbnQuPGJyIC8+XG4gICAqIEl0IHdpbGwgcmVhZCB0aGUgdmFyaWF0aW9uIG9mIHRoZSBgcGxhY2VtZW50YCBwcm9wZXJ0eS48YnIgLz5cbiAgICogSXQgY2FuIGJlIG9uZSBlaXRoZXIgYC1lbmRgIG9yIGAtc3RhcnRgLlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgc2hpZnQ6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9MTAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiAxMDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBzaGlmdFxuICB9LFxuXG4gIC8qKlxuICAgKiBUaGUgYG9mZnNldGAgbW9kaWZpZXIgY2FuIHNoaWZ0IHlvdXIgcG9wcGVyIG9uIGJvdGggaXRzIGF4aXMuXG4gICAqXG4gICAqIEl0IGFjY2VwdHMgdGhlIGZvbGxvd2luZyB1bml0czpcbiAgICogLSBgcHhgIG9yIHVuaXRsZXNzLCBpbnRlcnByZXRlZCBhcyBwaXhlbHNcbiAgICogLSBgJWAgb3IgYCVyYCwgcGVyY2VudGFnZSByZWxhdGl2ZSB0byB0aGUgbGVuZ3RoIG9mIHRoZSByZWZlcmVuY2UgZWxlbWVudFxuICAgKiAtIGAlcGAsIHBlcmNlbnRhZ2UgcmVsYXRpdmUgdG8gdGhlIGxlbmd0aCBvZiB0aGUgcG9wcGVyIGVsZW1lbnRcbiAgICogLSBgdndgLCBDU1Mgdmlld3BvcnQgd2lkdGggdW5pdFxuICAgKiAtIGB2aGAsIENTUyB2aWV3cG9ydCBoZWlnaHQgdW5pdFxuICAgKlxuICAgKiBGb3IgbGVuZ3RoIGlzIGludGVuZGVkIHRoZSBtYWluIGF4aXMgcmVsYXRpdmUgdG8gdGhlIHBsYWNlbWVudCBvZiB0aGUgcG9wcGVyLjxiciAvPlxuICAgKiBUaGlzIG1lYW5zIHRoYXQgaWYgdGhlIHBsYWNlbWVudCBpcyBgdG9wYCBvciBgYm90dG9tYCwgdGhlIGxlbmd0aCB3aWxsIGJlIHRoZVxuICAgKiBgd2lkdGhgLiBJbiBjYXNlIG9mIGBsZWZ0YCBvciBgcmlnaHRgLCBpdCB3aWxsIGJlIHRoZSBoZWlnaHQuXG4gICAqXG4gICAqIFlvdSBjYW4gcHJvdmlkZSBhIHNpbmdsZSB2YWx1ZSAoYXMgYE51bWJlcmAgb3IgYFN0cmluZ2ApLCBvciBhIHBhaXIgb2YgdmFsdWVzXG4gICAqIGFzIGBTdHJpbmdgIGRpdmlkZWQgYnkgYSBjb21tYSBvciBvbmUgKG9yIG1vcmUpIHdoaXRlIHNwYWNlcy48YnIgLz5cbiAgICogVGhlIGxhdHRlciBpcyBhIGRlcHJlY2F0ZWQgbWV0aG9kIGJlY2F1c2UgaXQgbGVhZHMgdG8gY29uZnVzaW9uIGFuZCB3aWxsIGJlXG4gICAqIHJlbW92ZWQgaW4gdjIuPGJyIC8+XG4gICAqIEFkZGl0aW9uYWxseSwgaXQgYWNjZXB0cyBhZGRpdGlvbnMgYW5kIHN1YnRyYWN0aW9ucyBiZXR3ZWVuIGRpZmZlcmVudCB1bml0cy5cbiAgICogTm90ZSB0aGF0IG11bHRpcGxpY2F0aW9ucyBhbmQgZGl2aXNpb25zIGFyZW4ndCBzdXBwb3J0ZWQuXG4gICAqXG4gICAqIFZhbGlkIGV4YW1wbGVzIGFyZTpcbiAgICogYGBgXG4gICAqIDEwXG4gICAqICcxMCUnXG4gICAqICcxMCwgMTAnXG4gICAqICcxMCUsIDEwJ1xuICAgKiAnMTAgKyAxMCUnXG4gICAqICcxMCAtIDV2aCArIDMlJ1xuICAgKiAnLTEwcHggKyA1dmgsIDVweCAtIDYlJ1xuICAgKiBgYGBcbiAgICogPiAqKk5CKio6IElmIHlvdSBkZXNpcmUgdG8gYXBwbHkgb2Zmc2V0cyB0byB5b3VyIHBvcHBlcnMgaW4gYSB3YXkgdGhhdCBtYXkgbWFrZSB0aGVtIG92ZXJsYXBcbiAgICogPiB3aXRoIHRoZWlyIHJlZmVyZW5jZSBlbGVtZW50LCB1bmZvcnR1bmF0ZWx5LCB5b3Ugd2lsbCBoYXZlIHRvIGRpc2FibGUgdGhlIGBmbGlwYCBtb2RpZmllci5cbiAgICogPiBNb3JlIG9uIHRoaXMgW3JlYWRpbmcgdGhpcyBpc3N1ZV0oaHR0cHM6Ly9naXRodWIuY29tL0ZlelZyYXN0YS9wb3BwZXIuanMvaXNzdWVzLzM3MylcbiAgICpcbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIG9mZnNldDoge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj0yMDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDIwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IG9mZnNldCxcbiAgICAvKiogQHByb3Age051bWJlcnxTdHJpbmd9IG9mZnNldD0wXG4gICAgICogVGhlIG9mZnNldCB2YWx1ZSBhcyBkZXNjcmliZWQgaW4gdGhlIG1vZGlmaWVyIGRlc2NyaXB0aW9uXG4gICAgICovXG4gICAgb2Zmc2V0OiAwXG4gIH0sXG5cbiAgLyoqXG4gICAqIE1vZGlmaWVyIHVzZWQgdG8gcHJldmVudCB0aGUgcG9wcGVyIGZyb20gYmVpbmcgcG9zaXRpb25lZCBvdXRzaWRlIHRoZSBib3VuZGFyeS5cbiAgICpcbiAgICogQW4gc2NlbmFyaW8gZXhpc3RzIHdoZXJlIHRoZSByZWZlcmVuY2UgaXRzZWxmIGlzIG5vdCB3aXRoaW4gdGhlIGJvdW5kYXJpZXMuPGJyIC8+XG4gICAqIFdlIGNhbiBzYXkgaXQgaGFzIFwiZXNjYXBlZCB0aGUgYm91bmRhcmllc1wiIOKAlCBvciBqdXN0IFwiZXNjYXBlZFwiLjxiciAvPlxuICAgKiBJbiB0aGlzIGNhc2Ugd2UgbmVlZCB0byBkZWNpZGUgd2hldGhlciB0aGUgcG9wcGVyIHNob3VsZCBlaXRoZXI6XG4gICAqXG4gICAqIC0gZGV0YWNoIGZyb20gdGhlIHJlZmVyZW5jZSBhbmQgcmVtYWluIFwidHJhcHBlZFwiIGluIHRoZSBib3VuZGFyaWVzLCBvclxuICAgKiAtIGlmIGl0IHNob3VsZCBpZ25vcmUgdGhlIGJvdW5kYXJ5IGFuZCBcImVzY2FwZSB3aXRoIGl0cyByZWZlcmVuY2VcIlxuICAgKlxuICAgKiBXaGVuIGBlc2NhcGVXaXRoUmVmZXJlbmNlYCBpcyBzZXQgdG9gdHJ1ZWAgYW5kIHJlZmVyZW5jZSBpcyBjb21wbGV0ZWx5XG4gICAqIG91dHNpZGUgaXRzIGJvdW5kYXJpZXMsIHRoZSBwb3BwZXIgd2lsbCBvdmVyZmxvdyAob3IgY29tcGxldGVseSBsZWF2ZSlcbiAgICogdGhlIGJvdW5kYXJpZXMgaW4gb3JkZXIgdG8gcmVtYWluIGF0dGFjaGVkIHRvIHRoZSBlZGdlIG9mIHRoZSByZWZlcmVuY2UuXG4gICAqXG4gICAqIEBtZW1iZXJvZiBtb2RpZmllcnNcbiAgICogQGlubmVyXG4gICAqL1xuICBwcmV2ZW50T3ZlcmZsb3c6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9MzAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiAzMDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBwcmV2ZW50T3ZlcmZsb3csXG4gICAgLyoqXG4gICAgICogQHByb3Age0FycmF5fSBbcHJpb3JpdHk9WydsZWZ0JywncmlnaHQnLCd0b3AnLCdib3R0b20nXV1cbiAgICAgKiBQb3BwZXIgd2lsbCB0cnkgdG8gcHJldmVudCBvdmVyZmxvdyBmb2xsb3dpbmcgdGhlc2UgcHJpb3JpdGllcyBieSBkZWZhdWx0LFxuICAgICAqIHRoZW4sIGl0IGNvdWxkIG92ZXJmbG93IG9uIHRoZSBsZWZ0IGFuZCBvbiB0b3Agb2YgdGhlIGBib3VuZGFyaWVzRWxlbWVudGBcbiAgICAgKi9cbiAgICBwcmlvcml0eTogWydsZWZ0JywgJ3JpZ2h0JywgJ3RvcCcsICdib3R0b20nXSxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7bnVtYmVyfSBwYWRkaW5nPTVcbiAgICAgKiBBbW91bnQgb2YgcGl4ZWwgdXNlZCB0byBkZWZpbmUgYSBtaW5pbXVtIGRpc3RhbmNlIGJldHdlZW4gdGhlIGJvdW5kYXJpZXNcbiAgICAgKiBhbmQgdGhlIHBvcHBlciB0aGlzIG1ha2VzIHN1cmUgdGhlIHBvcHBlciBoYXMgYWx3YXlzIGEgbGl0dGxlIHBhZGRpbmdcbiAgICAgKiBiZXR3ZWVuIHRoZSBlZGdlcyBvZiBpdHMgY29udGFpbmVyXG4gICAgICovXG4gICAgcGFkZGluZzogNSxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7U3RyaW5nfEhUTUxFbGVtZW50fSBib3VuZGFyaWVzRWxlbWVudD0nc2Nyb2xsUGFyZW50J1xuICAgICAqIEJvdW5kYXJpZXMgdXNlZCBieSB0aGUgbW9kaWZpZXIsIGNhbiBiZSBgc2Nyb2xsUGFyZW50YCwgYHdpbmRvd2AsXG4gICAgICogYHZpZXdwb3J0YCBvciBhbnkgRE9NIGVsZW1lbnQuXG4gICAgICovXG4gICAgYm91bmRhcmllc0VsZW1lbnQ6ICdzY3JvbGxQYXJlbnQnXG4gIH0sXG5cbiAgLyoqXG4gICAqIE1vZGlmaWVyIHVzZWQgdG8gbWFrZSBzdXJlIHRoZSByZWZlcmVuY2UgYW5kIGl0cyBwb3BwZXIgc3RheSBuZWFyIGVhY2hvdGhlcnNcbiAgICogd2l0aG91dCBsZWF2aW5nIGFueSBnYXAgYmV0d2VlbiB0aGUgdHdvLiBFeHBlY2lhbGx5IHVzZWZ1bCB3aGVuIHRoZSBhcnJvdyBpc1xuICAgKiBlbmFibGVkIGFuZCB5b3Ugd2FudCB0byBhc3N1cmUgaXQgdG8gcG9pbnQgdG8gaXRzIHJlZmVyZW5jZSBlbGVtZW50LlxuICAgKiBJdCBjYXJlcyBvbmx5IGFib3V0IHRoZSBmaXJzdCBheGlzLCB5b3UgY2FuIHN0aWxsIGhhdmUgcG9wcGVycyB3aXRoIG1hcmdpblxuICAgKiBiZXR3ZWVuIHRoZSBwb3BwZXIgYW5kIGl0cyByZWZlcmVuY2UgZWxlbWVudC5cbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIGtlZXBUb2dldGhlcjoge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj00MDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDQwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IGtlZXBUb2dldGhlclxuICB9LFxuXG4gIC8qKlxuICAgKiBUaGlzIG1vZGlmaWVyIGlzIHVzZWQgdG8gbW92ZSB0aGUgYGFycm93RWxlbWVudGAgb2YgdGhlIHBvcHBlciB0byBtYWtlXG4gICAqIHN1cmUgaXQgaXMgcG9zaXRpb25lZCBiZXR3ZWVuIHRoZSByZWZlcmVuY2UgZWxlbWVudCBhbmQgaXRzIHBvcHBlciBlbGVtZW50LlxuICAgKiBJdCB3aWxsIHJlYWQgdGhlIG91dGVyIHNpemUgb2YgdGhlIGBhcnJvd0VsZW1lbnRgIG5vZGUgdG8gZGV0ZWN0IGhvdyBtYW55XG4gICAqIHBpeGVscyBvZiBjb25qdWN0aW9uIGFyZSBuZWVkZWQuXG4gICAqXG4gICAqIEl0IGhhcyBubyBlZmZlY3QgaWYgbm8gYGFycm93RWxlbWVudGAgaXMgcHJvdmlkZWQuXG4gICAqIEBtZW1iZXJvZiBtb2RpZmllcnNcbiAgICogQGlubmVyXG4gICAqL1xuICBhcnJvdzoge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj01MDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDUwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IGFycm93LFxuICAgIC8qKiBAcHJvcCB7U3RyaW5nfEhUTUxFbGVtZW50fSBlbGVtZW50PSdbeC1hcnJvd10nIC0gU2VsZWN0b3Igb3Igbm9kZSB1c2VkIGFzIGFycm93ICovXG4gICAgZWxlbWVudDogJ1t4LWFycm93XSdcbiAgfSxcblxuICAvKipcbiAgICogTW9kaWZpZXIgdXNlZCB0byBmbGlwIHRoZSBwb3BwZXIncyBwbGFjZW1lbnQgd2hlbiBpdCBzdGFydHMgdG8gb3ZlcmxhcCBpdHNcbiAgICogcmVmZXJlbmNlIGVsZW1lbnQuXG4gICAqXG4gICAqIFJlcXVpcmVzIHRoZSBgcHJldmVudE92ZXJmbG93YCBtb2RpZmllciBiZWZvcmUgaXQgaW4gb3JkZXIgdG8gd29yay5cbiAgICpcbiAgICogKipOT1RFOioqIHRoaXMgbW9kaWZpZXIgd2lsbCBpbnRlcnJ1cHQgdGhlIGN1cnJlbnQgdXBkYXRlIGN5Y2xlIGFuZCB3aWxsXG4gICAqIHJlc3RhcnQgaXQgaWYgaXQgZGV0ZWN0cyB0aGUgbmVlZCB0byBmbGlwIHRoZSBwbGFjZW1lbnQuXG4gICAqIEBtZW1iZXJvZiBtb2RpZmllcnNcbiAgICogQGlubmVyXG4gICAqL1xuICBmbGlwOiB7XG4gICAgLyoqIEBwcm9wIHtudW1iZXJ9IG9yZGVyPTYwMCAtIEluZGV4IHVzZWQgdG8gZGVmaW5lIHRoZSBvcmRlciBvZiBleGVjdXRpb24gKi9cbiAgICBvcmRlcjogNjAwLFxuICAgIC8qKiBAcHJvcCB7Qm9vbGVhbn0gZW5hYmxlZD10cnVlIC0gV2hldGhlciB0aGUgbW9kaWZpZXIgaXMgZW5hYmxlZCBvciBub3QgKi9cbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIC8qKiBAcHJvcCB7TW9kaWZpZXJGbn0gKi9cbiAgICBmbjogZmxpcCxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7U3RyaW5nfEFycmF5fSBiZWhhdmlvcj0nZmxpcCdcbiAgICAgKiBUaGUgYmVoYXZpb3IgdXNlZCB0byBjaGFuZ2UgdGhlIHBvcHBlcidzIHBsYWNlbWVudC4gSXQgY2FuIGJlIG9uZSBvZlxuICAgICAqIGBmbGlwYCwgYGNsb2Nrd2lzZWAsIGBjb3VudGVyY2xvY2t3aXNlYCBvciBhbiBhcnJheSB3aXRoIGEgbGlzdCBvZiB2YWxpZFxuICAgICAqIHBsYWNlbWVudHMgKHdpdGggb3B0aW9uYWwgdmFyaWF0aW9ucykuXG4gICAgICovXG4gICAgYmVoYXZpb3I6ICdmbGlwJyxcbiAgICAvKipcbiAgICAgKiBAcHJvcCB7bnVtYmVyfSBwYWRkaW5nPTVcbiAgICAgKiBUaGUgcG9wcGVyIHdpbGwgZmxpcCBpZiBpdCBoaXRzIHRoZSBlZGdlcyBvZiB0aGUgYGJvdW5kYXJpZXNFbGVtZW50YFxuICAgICAqL1xuICAgIHBhZGRpbmc6IDUsXG4gICAgLyoqXG4gICAgICogQHByb3Age1N0cmluZ3xIVE1MRWxlbWVudH0gYm91bmRhcmllc0VsZW1lbnQ9J3ZpZXdwb3J0J1xuICAgICAqIFRoZSBlbGVtZW50IHdoaWNoIHdpbGwgZGVmaW5lIHRoZSBib3VuZGFyaWVzIG9mIHRoZSBwb3BwZXIgcG9zaXRpb24sXG4gICAgICogdGhlIHBvcHBlciB3aWxsIG5ldmVyIGJlIHBsYWNlZCBvdXRzaWRlIG9mIHRoZSBkZWZpbmVkIGJvdW5kYXJpZXNcbiAgICAgKiAoZXhjZXB0IGlmIGtlZXBUb2dldGhlciBpcyBlbmFibGVkKVxuICAgICAqL1xuICAgIGJvdW5kYXJpZXNFbGVtZW50OiAndmlld3BvcnQnXG4gIH0sXG5cbiAgLyoqXG4gICAqIE1vZGlmaWVyIHVzZWQgdG8gbWFrZSB0aGUgcG9wcGVyIGZsb3cgdG93YXJkIHRoZSBpbm5lciBvZiB0aGUgcmVmZXJlbmNlIGVsZW1lbnQuXG4gICAqIEJ5IGRlZmF1bHQsIHdoZW4gdGhpcyBtb2RpZmllciBpcyBkaXNhYmxlZCwgdGhlIHBvcHBlciB3aWxsIGJlIHBsYWNlZCBvdXRzaWRlXG4gICAqIHRoZSByZWZlcmVuY2UgZWxlbWVudC5cbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIGlubmVyOiB7XG4gICAgLyoqIEBwcm9wIHtudW1iZXJ9IG9yZGVyPTcwMCAtIEluZGV4IHVzZWQgdG8gZGVmaW5lIHRoZSBvcmRlciBvZiBleGVjdXRpb24gKi9cbiAgICBvcmRlcjogNzAwLFxuICAgIC8qKiBAcHJvcCB7Qm9vbGVhbn0gZW5hYmxlZD1mYWxzZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogZmFsc2UsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBpbm5lclxuICB9LFxuXG4gIC8qKlxuICAgKiBNb2RpZmllciB1c2VkIHRvIGhpZGUgdGhlIHBvcHBlciB3aGVuIGl0cyByZWZlcmVuY2UgZWxlbWVudCBpcyBvdXRzaWRlIG9mIHRoZVxuICAgKiBwb3BwZXIgYm91bmRhcmllcy4gSXQgd2lsbCBzZXQgYSBgeC1vdXQtb2YtYm91bmRhcmllc2AgYXR0cmlidXRlIHdoaWNoIGNhblxuICAgKiBiZSB1c2VkIHRvIGhpZGUgd2l0aCBhIENTUyBzZWxlY3RvciB0aGUgcG9wcGVyIHdoZW4gaXRzIHJlZmVyZW5jZSBpc1xuICAgKiBvdXQgb2YgYm91bmRhcmllcy5cbiAgICpcbiAgICogUmVxdWlyZXMgdGhlIGBwcmV2ZW50T3ZlcmZsb3dgIG1vZGlmaWVyIGJlZm9yZSBpdCBpbiBvcmRlciB0byB3b3JrLlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgaGlkZToge1xuICAgIC8qKiBAcHJvcCB7bnVtYmVyfSBvcmRlcj04MDAgLSBJbmRleCB1c2VkIHRvIGRlZmluZSB0aGUgb3JkZXIgb2YgZXhlY3V0aW9uICovXG4gICAgb3JkZXI6IDgwMCxcbiAgICAvKiogQHByb3Age0Jvb2xlYW59IGVuYWJsZWQ9dHJ1ZSAtIFdoZXRoZXIgdGhlIG1vZGlmaWVyIGlzIGVuYWJsZWQgb3Igbm90ICovXG4gICAgZW5hYmxlZDogdHJ1ZSxcbiAgICAvKiogQHByb3Age01vZGlmaWVyRm59ICovXG4gICAgZm46IGhpZGVcbiAgfSxcblxuICAvKipcbiAgICogQ29tcHV0ZXMgdGhlIHN0eWxlIHRoYXQgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXIgZWxlbWVudCB0byBnZXRzXG4gICAqIHByb3Blcmx5IHBvc2l0aW9uZWQuXG4gICAqXG4gICAqIE5vdGUgdGhhdCB0aGlzIG1vZGlmaWVyIHdpbGwgbm90IHRvdWNoIHRoZSBET00sIGl0IGp1c3QgcHJlcGFyZXMgdGhlIHN0eWxlc1xuICAgKiBzbyB0aGF0IGBhcHBseVN0eWxlYCBtb2RpZmllciBjYW4gYXBwbHkgaXQuIFRoaXMgc2VwYXJhdGlvbiBpcyB1c2VmdWxcbiAgICogaW4gY2FzZSB5b3UgbmVlZCB0byByZXBsYWNlIGBhcHBseVN0eWxlYCB3aXRoIGEgY3VzdG9tIGltcGxlbWVudGF0aW9uLlxuICAgKlxuICAgKiBUaGlzIG1vZGlmaWVyIGhhcyBgODUwYCBhcyBgb3JkZXJgIHZhbHVlIHRvIG1haW50YWluIGJhY2t3YXJkIGNvbXBhdGliaWxpdHlcbiAgICogd2l0aCBwcmV2aW91cyB2ZXJzaW9ucyBvZiBQb3BwZXIuanMuIEV4cGVjdCB0aGUgbW9kaWZpZXJzIG9yZGVyaW5nIG1ldGhvZFxuICAgKiB0byBjaGFuZ2UgaW4gZnV0dXJlIG1ham9yIHZlcnNpb25zIG9mIHRoZSBsaWJyYXJ5LlxuICAgKlxuICAgKiBAbWVtYmVyb2YgbW9kaWZpZXJzXG4gICAqIEBpbm5lclxuICAgKi9cbiAgY29tcHV0ZVN0eWxlOiB7XG4gICAgLyoqIEBwcm9wIHtudW1iZXJ9IG9yZGVyPTg1MCAtIEluZGV4IHVzZWQgdG8gZGVmaW5lIHRoZSBvcmRlciBvZiBleGVjdXRpb24gKi9cbiAgICBvcmRlcjogODUwLFxuICAgIC8qKiBAcHJvcCB7Qm9vbGVhbn0gZW5hYmxlZD10cnVlIC0gV2hldGhlciB0aGUgbW9kaWZpZXIgaXMgZW5hYmxlZCBvciBub3QgKi9cbiAgICBlbmFibGVkOiB0cnVlLFxuICAgIC8qKiBAcHJvcCB7TW9kaWZpZXJGbn0gKi9cbiAgICBmbjogY29tcHV0ZVN0eWxlLFxuICAgIC8qKlxuICAgICAqIEBwcm9wIHtCb29sZWFufSBncHVBY2NlbGVyYXRpb249dHJ1ZVxuICAgICAqIElmIHRydWUsIGl0IHVzZXMgdGhlIENTUyAzZCB0cmFuc2Zvcm1hdGlvbiB0byBwb3NpdGlvbiB0aGUgcG9wcGVyLlxuICAgICAqIE90aGVyd2lzZSwgaXQgd2lsbCB1c2UgdGhlIGB0b3BgIGFuZCBgbGVmdGAgcHJvcGVydGllcy5cbiAgICAgKi9cbiAgICBncHVBY2NlbGVyYXRpb246IHRydWUsXG4gICAgLyoqXG4gICAgICogQHByb3Age3N0cmluZ30gW3g9J2JvdHRvbSddXG4gICAgICogV2hlcmUgdG8gYW5jaG9yIHRoZSBYIGF4aXMgKGBib3R0b21gIG9yIGB0b3BgKS4gQUtBIFggb2Zmc2V0IG9yaWdpbi5cbiAgICAgKiBDaGFuZ2UgdGhpcyBpZiB5b3VyIHBvcHBlciBzaG91bGQgZ3JvdyBpbiBhIGRpcmVjdGlvbiBkaWZmZXJlbnQgZnJvbSBgYm90dG9tYFxuICAgICAqL1xuICAgIHg6ICdib3R0b20nLFxuICAgIC8qKlxuICAgICAqIEBwcm9wIHtzdHJpbmd9IFt4PSdsZWZ0J11cbiAgICAgKiBXaGVyZSB0byBhbmNob3IgdGhlIFkgYXhpcyAoYGxlZnRgIG9yIGByaWdodGApLiBBS0EgWSBvZmZzZXQgb3JpZ2luLlxuICAgICAqIENoYW5nZSB0aGlzIGlmIHlvdXIgcG9wcGVyIHNob3VsZCBncm93IGluIGEgZGlyZWN0aW9uIGRpZmZlcmVudCBmcm9tIGByaWdodGBcbiAgICAgKi9cbiAgICB5OiAncmlnaHQnXG4gIH0sXG5cbiAgLyoqXG4gICAqIEFwcGxpZXMgdGhlIGNvbXB1dGVkIHN0eWxlcyB0byB0aGUgcG9wcGVyIGVsZW1lbnQuXG4gICAqXG4gICAqIEFsbCB0aGUgRE9NIG1hbmlwdWxhdGlvbnMgYXJlIGxpbWl0ZWQgdG8gdGhpcyBtb2RpZmllci4gVGhpcyBpcyB1c2VmdWwgaW4gY2FzZVxuICAgKiB5b3Ugd2FudCB0byBpbnRlZ3JhdGUgUG9wcGVyLmpzIGluc2lkZSBhIGZyYW1ld29yayBvciB2aWV3IGxpYnJhcnkgYW5kIHlvdVxuICAgKiB3YW50IHRvIGRlbGVnYXRlIGFsbCB0aGUgRE9NIG1hbmlwdWxhdGlvbnMgdG8gaXQuXG4gICAqXG4gICAqIE5vdGUgdGhhdCBpZiB5b3UgZGlzYWJsZSB0aGlzIG1vZGlmaWVyLCB5b3UgbXVzdCBtYWtlIHN1cmUgdGhlIHBvcHBlciBlbGVtZW50XG4gICAqIGhhcyBpdHMgcG9zaXRpb24gc2V0IHRvIGBhYnNvbHV0ZWAgYmVmb3JlIFBvcHBlci5qcyBjYW4gZG8gaXRzIHdvcmshXG4gICAqXG4gICAqIEp1c3QgZGlzYWJsZSB0aGlzIG1vZGlmaWVyIGFuZCBkZWZpbmUgeW91IG93biB0byBhY2hpZXZlIHRoZSBkZXNpcmVkIGVmZmVjdC5cbiAgICpcbiAgICogQG1lbWJlcm9mIG1vZGlmaWVyc1xuICAgKiBAaW5uZXJcbiAgICovXG4gIGFwcGx5U3R5bGU6IHtcbiAgICAvKiogQHByb3Age251bWJlcn0gb3JkZXI9OTAwIC0gSW5kZXggdXNlZCB0byBkZWZpbmUgdGhlIG9yZGVyIG9mIGV4ZWN1dGlvbiAqL1xuICAgIG9yZGVyOiA5MDAsXG4gICAgLyoqIEBwcm9wIHtCb29sZWFufSBlbmFibGVkPXRydWUgLSBXaGV0aGVyIHRoZSBtb2RpZmllciBpcyBlbmFibGVkIG9yIG5vdCAqL1xuICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgLyoqIEBwcm9wIHtNb2RpZmllckZufSAqL1xuICAgIGZuOiBhcHBseVN0eWxlLFxuICAgIC8qKiBAcHJvcCB7RnVuY3Rpb259ICovXG4gICAgb25Mb2FkOiBhcHBseVN0eWxlT25Mb2FkLFxuICAgIC8qKlxuICAgICAqIEBkZXByZWNhdGVkIHNpbmNlIHZlcnNpb24gMS4xMC4wLCB0aGUgcHJvcGVydHkgbW92ZWQgdG8gYGNvbXB1dGVTdHlsZWAgbW9kaWZpZXJcbiAgICAgKiBAcHJvcCB7Qm9vbGVhbn0gZ3B1QWNjZWxlcmF0aW9uPXRydWVcbiAgICAgKiBJZiB0cnVlLCBpdCB1c2VzIHRoZSBDU1MgM2QgdHJhbnNmb3JtYXRpb24gdG8gcG9zaXRpb24gdGhlIHBvcHBlci5cbiAgICAgKiBPdGhlcndpc2UsIGl0IHdpbGwgdXNlIHRoZSBgdG9wYCBhbmQgYGxlZnRgIHByb3BlcnRpZXMuXG4gICAgICovXG4gICAgZ3B1QWNjZWxlcmF0aW9uOiB1bmRlZmluZWRcbiAgfVxufTtcblxuLyoqXG4gKiBUaGUgYGRhdGFPYmplY3RgIGlzIGFuIG9iamVjdCBjb250YWluaW5nIGFsbCB0aGUgaW5mb3JtYXRpb25zIHVzZWQgYnkgUG9wcGVyLmpzXG4gKiB0aGlzIG9iamVjdCBnZXQgcGFzc2VkIHRvIG1vZGlmaWVycyBhbmQgdG8gdGhlIGBvbkNyZWF0ZWAgYW5kIGBvblVwZGF0ZWAgY2FsbGJhY2tzLlxuICogQG5hbWUgZGF0YU9iamVjdFxuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEuaW5zdGFuY2UgVGhlIFBvcHBlci5qcyBpbnN0YW5jZVxuICogQHByb3BlcnR5IHtTdHJpbmd9IGRhdGEucGxhY2VtZW50IFBsYWNlbWVudCBhcHBsaWVkIHRvIHBvcHBlclxuICogQHByb3BlcnR5IHtTdHJpbmd9IGRhdGEub3JpZ2luYWxQbGFjZW1lbnQgUGxhY2VtZW50IG9yaWdpbmFsbHkgZGVmaW5lZCBvbiBpbml0XG4gKiBAcHJvcGVydHkge0Jvb2xlYW59IGRhdGEuZmxpcHBlZCBUcnVlIGlmIHBvcHBlciBoYXMgYmVlbiBmbGlwcGVkIGJ5IGZsaXAgbW9kaWZpZXJcbiAqIEBwcm9wZXJ0eSB7Qm9vbGVhbn0gZGF0YS5oaWRlIFRydWUgaWYgdGhlIHJlZmVyZW5jZSBlbGVtZW50IGlzIG91dCBvZiBib3VuZGFyaWVzLCB1c2VmdWwgdG8ga25vdyB3aGVuIHRvIGhpZGUgdGhlIHBvcHBlci5cbiAqIEBwcm9wZXJ0eSB7SFRNTEVsZW1lbnR9IGRhdGEuYXJyb3dFbGVtZW50IE5vZGUgdXNlZCBhcyBhcnJvdyBieSBhcnJvdyBtb2RpZmllclxuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEuc3R5bGVzIEFueSBDU1MgcHJvcGVydHkgZGVmaW5lZCBoZXJlIHdpbGwgYmUgYXBwbGllZCB0byB0aGUgcG9wcGVyLCBpdCBleHBlY3RzIHRoZSBKYXZhU2NyaXB0IG5vbWVuY2xhdHVyZSAoZWcuIGBtYXJnaW5Cb3R0b21gKVxuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEuYXJyb3dTdHlsZXMgQW55IENTUyBwcm9wZXJ0eSBkZWZpbmVkIGhlcmUgd2lsbCBiZSBhcHBsaWVkIHRvIHRoZSBwb3BwZXIgYXJyb3csIGl0IGV4cGVjdHMgdGhlIEphdmFTY3JpcHQgbm9tZW5jbGF0dXJlIChlZy4gYG1hcmdpbkJvdHRvbWApXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5ib3VuZGFyaWVzIE9mZnNldHMgb2YgdGhlIHBvcHBlciBib3VuZGFyaWVzXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5vZmZzZXRzIFRoZSBtZWFzdXJlbWVudHMgb2YgcG9wcGVyLCByZWZlcmVuY2UgYW5kIGFycm93IGVsZW1lbnRzLlxuICogQHByb3BlcnR5IHtPYmplY3R9IGRhdGEub2Zmc2V0cy5wb3BwZXIgYHRvcGAsIGBsZWZ0YCwgYHdpZHRoYCwgYGhlaWdodGAgdmFsdWVzXG4gKiBAcHJvcGVydHkge09iamVjdH0gZGF0YS5vZmZzZXRzLnJlZmVyZW5jZSBgdG9wYCwgYGxlZnRgLCBgd2lkdGhgLCBgaGVpZ2h0YCB2YWx1ZXNcbiAqIEBwcm9wZXJ0eSB7T2JqZWN0fSBkYXRhLm9mZnNldHMuYXJyb3ddIGB0b3BgIGFuZCBgbGVmdGAgb2Zmc2V0cywgb25seSBvbmUgb2YgdGhlbSB3aWxsIGJlIGRpZmZlcmVudCBmcm9tIDBcbiAqL1xuXG4vKipcbiAqIERlZmF1bHQgb3B0aW9ucyBwcm92aWRlZCB0byBQb3BwZXIuanMgY29uc3RydWN0b3IuPGJyIC8+XG4gKiBUaGVzZSBjYW4gYmUgb3ZlcnJpZGVuIHVzaW5nIHRoZSBgb3B0aW9uc2AgYXJndW1lbnQgb2YgUG9wcGVyLmpzLjxiciAvPlxuICogVG8gb3ZlcnJpZGUgYW4gb3B0aW9uLCBzaW1wbHkgcGFzcyBhcyAzcmQgYXJndW1lbnQgYW4gb2JqZWN0IHdpdGggdGhlIHNhbWVcbiAqIHN0cnVjdHVyZSBvZiB0aGlzIG9iamVjdCwgZXhhbXBsZTpcbiAqIGBgYFxuICogbmV3IFBvcHBlcihyZWYsIHBvcCwge1xuICogICBtb2RpZmllcnM6IHtcbiAqICAgICBwcmV2ZW50T3ZlcmZsb3c6IHsgZW5hYmxlZDogZmFsc2UgfVxuICogICB9XG4gKiB9KVxuICogYGBgXG4gKiBAdHlwZSB7T2JqZWN0fVxuICogQHN0YXRpY1xuICogQG1lbWJlcm9mIFBvcHBlclxuICovXG52YXIgRGVmYXVsdHMgPSB7XG4gIC8qKlxuICAgKiBQb3BwZXIncyBwbGFjZW1lbnRcbiAgICogQHByb3Age1BvcHBlci5wbGFjZW1lbnRzfSBwbGFjZW1lbnQ9J2JvdHRvbSdcbiAgICovXG4gIHBsYWNlbWVudDogJ2JvdHRvbScsXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgZXZlbnRzIChyZXNpemUsIHNjcm9sbCkgYXJlIGluaXRpYWxseSBlbmFibGVkXG4gICAqIEBwcm9wIHtCb29sZWFufSBldmVudHNFbmFibGVkPXRydWVcbiAgICovXG4gIGV2ZW50c0VuYWJsZWQ6IHRydWUsXG5cbiAgLyoqXG4gICAqIFNldCB0byB0cnVlIGlmIHlvdSB3YW50IHRvIGF1dG9tYXRpY2FsbHkgcmVtb3ZlIHRoZSBwb3BwZXIgd2hlblxuICAgKiB5b3UgY2FsbCB0aGUgYGRlc3Ryb3lgIG1ldGhvZC5cbiAgICogQHByb3Age0Jvb2xlYW59IHJlbW92ZU9uRGVzdHJveT1mYWxzZVxuICAgKi9cbiAgcmVtb3ZlT25EZXN0cm95OiBmYWxzZSxcblxuICAvKipcbiAgICogQ2FsbGJhY2sgY2FsbGVkIHdoZW4gdGhlIHBvcHBlciBpcyBjcmVhdGVkLjxiciAvPlxuICAgKiBCeSBkZWZhdWx0LCBpcyBzZXQgdG8gbm8tb3AuPGJyIC8+XG4gICAqIEFjY2VzcyBQb3BwZXIuanMgaW5zdGFuY2Ugd2l0aCBgZGF0YS5pbnN0YW5jZWAuXG4gICAqIEBwcm9wIHtvbkNyZWF0ZX1cbiAgICovXG4gIG9uQ3JlYXRlOiBmdW5jdGlvbiBvbkNyZWF0ZSgpIHt9LFxuXG4gIC8qKlxuICAgKiBDYWxsYmFjayBjYWxsZWQgd2hlbiB0aGUgcG9wcGVyIGlzIHVwZGF0ZWQsIHRoaXMgY2FsbGJhY2sgaXMgbm90IGNhbGxlZFxuICAgKiBvbiB0aGUgaW5pdGlhbGl6YXRpb24vY3JlYXRpb24gb2YgdGhlIHBvcHBlciwgYnV0IG9ubHkgb24gc3Vic2VxdWVudFxuICAgKiB1cGRhdGVzLjxiciAvPlxuICAgKiBCeSBkZWZhdWx0LCBpcyBzZXQgdG8gbm8tb3AuPGJyIC8+XG4gICAqIEFjY2VzcyBQb3BwZXIuanMgaW5zdGFuY2Ugd2l0aCBgZGF0YS5pbnN0YW5jZWAuXG4gICAqIEBwcm9wIHtvblVwZGF0ZX1cbiAgICovXG4gIG9uVXBkYXRlOiBmdW5jdGlvbiBvblVwZGF0ZSgpIHt9LFxuXG4gIC8qKlxuICAgKiBMaXN0IG9mIG1vZGlmaWVycyB1c2VkIHRvIG1vZGlmeSB0aGUgb2Zmc2V0cyBiZWZvcmUgdGhleSBhcmUgYXBwbGllZCB0byB0aGUgcG9wcGVyLlxuICAgKiBUaGV5IHByb3ZpZGUgbW9zdCBvZiB0aGUgZnVuY3Rpb25hbGl0aWVzIG9mIFBvcHBlci5qc1xuICAgKiBAcHJvcCB7bW9kaWZpZXJzfVxuICAgKi9cbiAgbW9kaWZpZXJzOiBtb2RpZmllcnNcbn07XG5cbi8qKlxuICogQGNhbGxiYWNrIG9uQ3JlYXRlXG4gKiBAcGFyYW0ge2RhdGFPYmplY3R9IGRhdGFcbiAqL1xuXG4vKipcbiAqIEBjYWxsYmFjayBvblVwZGF0ZVxuICogQHBhcmFtIHtkYXRhT2JqZWN0fSBkYXRhXG4gKi9cblxuLy8gVXRpbHNcbi8vIE1ldGhvZHNcbnZhciBQb3BwZXIgPSBmdW5jdGlvbiAoKSB7XG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgUG9wcGVyLmpzIGluc3RhbmNlXG4gICAqIEBjbGFzcyBQb3BwZXJcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxyZWZlcmVuY2VPYmplY3R9IHJlZmVyZW5jZSAtIFRoZSByZWZlcmVuY2UgZWxlbWVudCB1c2VkIHRvIHBvc2l0aW9uIHRoZSBwb3BwZXJcbiAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gcG9wcGVyIC0gVGhlIEhUTUwgZWxlbWVudCB1c2VkIGFzIHBvcHBlci5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBZb3VyIGN1c3RvbSBvcHRpb25zIHRvIG92ZXJyaWRlIHRoZSBvbmVzIGRlZmluZWQgaW4gW0RlZmF1bHRzXSgjZGVmYXVsdHMpXG4gICAqIEByZXR1cm4ge09iamVjdH0gaW5zdGFuY2UgLSBUaGUgZ2VuZXJhdGVkIFBvcHBlci5qcyBpbnN0YW5jZVxuICAgKi9cbiAgZnVuY3Rpb24gUG9wcGVyKHJlZmVyZW5jZSwgcG9wcGVyKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHZhciBvcHRpb25zID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiB7fTtcbiAgICBjbGFzc0NhbGxDaGVjayh0aGlzLCBQb3BwZXIpO1xuXG4gICAgdGhpcy5zY2hlZHVsZVVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoX3RoaXMudXBkYXRlKTtcbiAgICB9O1xuXG4gICAgLy8gbWFrZSB1cGRhdGUoKSBkZWJvdW5jZWQsIHNvIHRoYXQgaXQgb25seSBydW5zIGF0IG1vc3Qgb25jZS1wZXItdGlja1xuICAgIHRoaXMudXBkYXRlID0gZGVib3VuY2UodGhpcy51cGRhdGUuYmluZCh0aGlzKSk7XG5cbiAgICAvLyB3aXRoIHt9IHdlIGNyZWF0ZSBhIG5ldyBvYmplY3Qgd2l0aCB0aGUgb3B0aW9ucyBpbnNpZGUgaXRcbiAgICB0aGlzLm9wdGlvbnMgPSBfZXh0ZW5kcyh7fSwgUG9wcGVyLkRlZmF1bHRzLCBvcHRpb25zKTtcblxuICAgIC8vIGluaXQgc3RhdGVcbiAgICB0aGlzLnN0YXRlID0ge1xuICAgICAgaXNEZXN0cm95ZWQ6IGZhbHNlLFxuICAgICAgaXNDcmVhdGVkOiBmYWxzZSxcbiAgICAgIHNjcm9sbFBhcmVudHM6IFtdXG4gICAgfTtcblxuICAgIC8vIGdldCByZWZlcmVuY2UgYW5kIHBvcHBlciBlbGVtZW50cyAoYWxsb3cgalF1ZXJ5IHdyYXBwZXJzKVxuICAgIHRoaXMucmVmZXJlbmNlID0gcmVmZXJlbmNlICYmIHJlZmVyZW5jZS5qcXVlcnkgPyByZWZlcmVuY2VbMF0gOiByZWZlcmVuY2U7XG4gICAgdGhpcy5wb3BwZXIgPSBwb3BwZXIgJiYgcG9wcGVyLmpxdWVyeSA/IHBvcHBlclswXSA6IHBvcHBlcjtcblxuICAgIC8vIERlZXAgbWVyZ2UgbW9kaWZpZXJzIG9wdGlvbnNcbiAgICB0aGlzLm9wdGlvbnMubW9kaWZpZXJzID0ge307XG4gICAgT2JqZWN0LmtleXMoX2V4dGVuZHMoe30sIFBvcHBlci5EZWZhdWx0cy5tb2RpZmllcnMsIG9wdGlvbnMubW9kaWZpZXJzKSkuZm9yRWFjaChmdW5jdGlvbiAobmFtZSkge1xuICAgICAgX3RoaXMub3B0aW9ucy5tb2RpZmllcnNbbmFtZV0gPSBfZXh0ZW5kcyh7fSwgUG9wcGVyLkRlZmF1bHRzLm1vZGlmaWVyc1tuYW1lXSB8fCB7fSwgb3B0aW9ucy5tb2RpZmllcnMgPyBvcHRpb25zLm1vZGlmaWVyc1tuYW1lXSA6IHt9KTtcbiAgICB9KTtcblxuICAgIC8vIFJlZmFjdG9yaW5nIG1vZGlmaWVycycgbGlzdCAoT2JqZWN0ID0+IEFycmF5KVxuICAgIHRoaXMubW9kaWZpZXJzID0gT2JqZWN0LmtleXModGhpcy5vcHRpb25zLm1vZGlmaWVycykubWFwKGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICByZXR1cm4gX2V4dGVuZHMoe1xuICAgICAgICBuYW1lOiBuYW1lXG4gICAgICB9LCBfdGhpcy5vcHRpb25zLm1vZGlmaWVyc1tuYW1lXSk7XG4gICAgfSlcbiAgICAvLyBzb3J0IHRoZSBtb2RpZmllcnMgYnkgb3JkZXJcbiAgICAuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGEub3JkZXIgLSBiLm9yZGVyO1xuICAgIH0pO1xuXG4gICAgLy8gbW9kaWZpZXJzIGhhdmUgdGhlIGFiaWxpdHkgdG8gZXhlY3V0ZSBhcmJpdHJhcnkgY29kZSB3aGVuIFBvcHBlci5qcyBnZXQgaW5pdGVkXG4gICAgLy8gc3VjaCBjb2RlIGlzIGV4ZWN1dGVkIGluIHRoZSBzYW1lIG9yZGVyIG9mIGl0cyBtb2RpZmllclxuICAgIC8vIHRoZXkgY291bGQgYWRkIG5ldyBwcm9wZXJ0aWVzIHRvIHRoZWlyIG9wdGlvbnMgY29uZmlndXJhdGlvblxuICAgIC8vIEJFIEFXQVJFOiBkb24ndCBhZGQgb3B0aW9ucyB0byBgb3B0aW9ucy5tb2RpZmllcnMubmFtZWAgYnV0IHRvIGBtb2RpZmllck9wdGlvbnNgIVxuICAgIHRoaXMubW9kaWZpZXJzLmZvckVhY2goZnVuY3Rpb24gKG1vZGlmaWVyT3B0aW9ucykge1xuICAgICAgaWYgKG1vZGlmaWVyT3B0aW9ucy5lbmFibGVkICYmIGlzRnVuY3Rpb24obW9kaWZpZXJPcHRpb25zLm9uTG9hZCkpIHtcbiAgICAgICAgbW9kaWZpZXJPcHRpb25zLm9uTG9hZChfdGhpcy5yZWZlcmVuY2UsIF90aGlzLnBvcHBlciwgX3RoaXMub3B0aW9ucywgbW9kaWZpZXJPcHRpb25zLCBfdGhpcy5zdGF0ZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBmaXJlIHRoZSBmaXJzdCB1cGRhdGUgdG8gcG9zaXRpb24gdGhlIHBvcHBlciBpbiB0aGUgcmlnaHQgcGxhY2VcbiAgICB0aGlzLnVwZGF0ZSgpO1xuXG4gICAgdmFyIGV2ZW50c0VuYWJsZWQgPSB0aGlzLm9wdGlvbnMuZXZlbnRzRW5hYmxlZDtcbiAgICBpZiAoZXZlbnRzRW5hYmxlZCkge1xuICAgICAgLy8gc2V0dXAgZXZlbnQgbGlzdGVuZXJzLCB0aGV5IHdpbGwgdGFrZSBjYXJlIG9mIHVwZGF0ZSB0aGUgcG9zaXRpb24gaW4gc3BlY2lmaWMgc2l0dWF0aW9uc1xuICAgICAgdGhpcy5lbmFibGVFdmVudExpc3RlbmVycygpO1xuICAgIH1cblxuICAgIHRoaXMuc3RhdGUuZXZlbnRzRW5hYmxlZCA9IGV2ZW50c0VuYWJsZWQ7XG4gIH1cblxuICAvLyBXZSBjYW4ndCB1c2UgY2xhc3MgcHJvcGVydGllcyBiZWNhdXNlIHRoZXkgZG9uJ3QgZ2V0IGxpc3RlZCBpbiB0aGVcbiAgLy8gY2xhc3MgcHJvdG90eXBlIGFuZCBicmVhayBzdHVmZiBsaWtlIFNpbm9uIHN0dWJzXG5cblxuICBjcmVhdGVDbGFzcyhQb3BwZXIsIFt7XG4gICAga2V5OiAndXBkYXRlJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gdXBkYXRlJCQxKCkge1xuICAgICAgcmV0dXJuIHVwZGF0ZS5jYWxsKHRoaXMpO1xuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2Rlc3Ryb3knLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBkZXN0cm95JCQxKCkge1xuICAgICAgcmV0dXJuIGRlc3Ryb3kuY2FsbCh0aGlzKTtcbiAgICB9XG4gIH0sIHtcbiAgICBrZXk6ICdlbmFibGVFdmVudExpc3RlbmVycycsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIGVuYWJsZUV2ZW50TGlzdGVuZXJzJCQxKCkge1xuICAgICAgcmV0dXJuIGVuYWJsZUV2ZW50TGlzdGVuZXJzLmNhbGwodGhpcyk7XG4gICAgfVxuICB9LCB7XG4gICAga2V5OiAnZGlzYWJsZUV2ZW50TGlzdGVuZXJzJyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gZGlzYWJsZUV2ZW50TGlzdGVuZXJzJCQxKCkge1xuICAgICAgcmV0dXJuIGRpc2FibGVFdmVudExpc3RlbmVycy5jYWxsKHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNjaGVkdWxlIGFuIHVwZGF0ZSwgaXQgd2lsbCBydW4gb24gdGhlIG5leHQgVUkgdXBkYXRlIGF2YWlsYWJsZVxuICAgICAqIEBtZXRob2Qgc2NoZWR1bGVVcGRhdGVcbiAgICAgKiBAbWVtYmVyb2YgUG9wcGVyXG4gICAgICovXG5cblxuICAgIC8qKlxuICAgICAqIENvbGxlY3Rpb24gb2YgdXRpbGl0aWVzIHVzZWZ1bCB3aGVuIHdyaXRpbmcgY3VzdG9tIG1vZGlmaWVycy5cbiAgICAgKiBTdGFydGluZyBmcm9tIHZlcnNpb24gMS43LCB0aGlzIG1ldGhvZCBpcyBhdmFpbGFibGUgb25seSBpZiB5b3VcbiAgICAgKiBpbmNsdWRlIGBwb3BwZXItdXRpbHMuanNgIGJlZm9yZSBgcG9wcGVyLmpzYC5cbiAgICAgKlxuICAgICAqICoqREVQUkVDQVRJT04qKjogVGhpcyB3YXkgdG8gYWNjZXNzIFBvcHBlclV0aWxzIGlzIGRlcHJlY2F0ZWRcbiAgICAgKiBhbmQgd2lsbCBiZSByZW1vdmVkIGluIHYyISBVc2UgdGhlIFBvcHBlclV0aWxzIG1vZHVsZSBkaXJlY3RseSBpbnN0ZWFkLlxuICAgICAqIER1ZSB0byB0aGUgaGlnaCBpbnN0YWJpbGl0eSBvZiB0aGUgbWV0aG9kcyBjb250YWluZWQgaW4gVXRpbHMsIHdlIGNhbid0XG4gICAgICogZ3VhcmFudGVlIHRoZW0gdG8gZm9sbG93IHNlbXZlci4gVXNlIHRoZW0gYXQgeW91ciBvd24gcmlzayFcbiAgICAgKiBAc3RhdGljXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgICAqIEBkZXByZWNhdGVkIHNpbmNlIHZlcnNpb24gMS44XG4gICAgICogQG1lbWJlciBVdGlsc1xuICAgICAqIEBtZW1iZXJvZiBQb3BwZXJcbiAgICAgKi9cblxuICB9XSk7XG4gIHJldHVybiBQb3BwZXI7XG59KCk7XG5cbi8qKlxuICogVGhlIGByZWZlcmVuY2VPYmplY3RgIGlzIGFuIG9iamVjdCB0aGF0IHByb3ZpZGVzIGFuIGludGVyZmFjZSBjb21wYXRpYmxlIHdpdGggUG9wcGVyLmpzXG4gKiBhbmQgbGV0cyB5b3UgdXNlIGl0IGFzIHJlcGxhY2VtZW50IG9mIGEgcmVhbCBET00gbm9kZS48YnIgLz5cbiAqIFlvdSBjYW4gdXNlIHRoaXMgbWV0aG9kIHRvIHBvc2l0aW9uIGEgcG9wcGVyIHJlbGF0aXZlbHkgdG8gYSBzZXQgb2YgY29vcmRpbmF0ZXNcbiAqIGluIGNhc2UgeW91IGRvbid0IGhhdmUgYSBET00gbm9kZSB0byB1c2UgYXMgcmVmZXJlbmNlLlxuICpcbiAqIGBgYFxuICogbmV3IFBvcHBlcihyZWZlcmVuY2VPYmplY3QsIHBvcHBlck5vZGUpO1xuICogYGBgXG4gKlxuICogTkI6IFRoaXMgZmVhdHVyZSBpc24ndCBzdXBwb3J0ZWQgaW4gSW50ZXJuZXQgRXhwbG9yZXIgMTBcbiAqIEBuYW1lIHJlZmVyZW5jZU9iamVjdFxuICogQHByb3BlcnR5IHtGdW5jdGlvbn0gZGF0YS5nZXRCb3VuZGluZ0NsaWVudFJlY3RcbiAqIEEgZnVuY3Rpb24gdGhhdCByZXR1cm5zIGEgc2V0IG9mIGNvb3JkaW5hdGVzIGNvbXBhdGlibGUgd2l0aCB0aGUgbmF0aXZlIGBnZXRCb3VuZGluZ0NsaWVudFJlY3RgIG1ldGhvZC5cbiAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBkYXRhLmNsaWVudFdpZHRoXG4gKiBBbiBFUzYgZ2V0dGVyIHRoYXQgd2lsbCByZXR1cm4gdGhlIHdpZHRoIG9mIHRoZSB2aXJ0dWFsIHJlZmVyZW5jZSBlbGVtZW50LlxuICogQHByb3BlcnR5IHtudW1iZXJ9IGRhdGEuY2xpZW50SGVpZ2h0XG4gKiBBbiBFUzYgZ2V0dGVyIHRoYXQgd2lsbCByZXR1cm4gdGhlIGhlaWdodCBvZiB0aGUgdmlydHVhbCByZWZlcmVuY2UgZWxlbWVudC5cbiAqL1xuXG5cblBvcHBlci5VdGlscyA9ICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IHdpbmRvdyA6IGdsb2JhbCkuUG9wcGVyVXRpbHM7XG5Qb3BwZXIucGxhY2VtZW50cyA9IHBsYWNlbWVudHM7XG5Qb3BwZXIuRGVmYXVsdHMgPSBEZWZhdWx0cztcblxuZXhwb3J0IGRlZmF1bHQgUG9wcGVyO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cG9wcGVyLmpzLm1hcFxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvcG9wcGVyLmpzL2Rpc3QvZXNtL3BvcHBlci5qc1xuLy8gbW9kdWxlIGlkID0gMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgZztcclxuXHJcbi8vIFRoaXMgd29ya3MgaW4gbm9uLXN0cmljdCBtb2RlXHJcbmcgPSAoZnVuY3Rpb24oKSB7XHJcblx0cmV0dXJuIHRoaXM7XHJcbn0pKCk7XHJcblxyXG50cnkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgZXZhbCBpcyBhbGxvd2VkIChzZWUgQ1NQKVxyXG5cdGcgPSBnIHx8IEZ1bmN0aW9uKFwicmV0dXJuIHRoaXNcIikoKSB8fCAoMSxldmFsKShcInRoaXNcIik7XHJcbn0gY2F0Y2goZSkge1xyXG5cdC8vIFRoaXMgd29ya3MgaWYgdGhlIHdpbmRvdyByZWZlcmVuY2UgaXMgYXZhaWxhYmxlXHJcblx0aWYodHlwZW9mIHdpbmRvdyA9PT0gXCJvYmplY3RcIilcclxuXHRcdGcgPSB3aW5kb3c7XHJcbn1cclxuXHJcbi8vIGcgY2FuIHN0aWxsIGJlIHVuZGVmaW5lZCwgYnV0IG5vdGhpbmcgdG8gZG8gYWJvdXQgaXQuLi5cclxuLy8gV2UgcmV0dXJuIHVuZGVmaW5lZCwgaW5zdGVhZCBvZiBub3RoaW5nIGhlcmUsIHNvIGl0J3NcclxuLy8gZWFzaWVyIHRvIGhhbmRsZSB0aGlzIGNhc2UuIGlmKCFnbG9iYWwpIHsgLi4ufVxyXG5cclxubW9kdWxlLmV4cG9ydHMgPSBnO1xyXG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAod2VicGFjaykvYnVpbGRpbi9nbG9iYWwuanNcbi8vIG1vZHVsZSBpZCA9IDNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyohIERhdGFUYWJsZXMgMS4xMC4xNlxuICogwqkyMDA4LTIwMTcgU3ByeU1lZGlhIEx0ZCAtIGRhdGF0YWJsZXMubmV0L2xpY2Vuc2VcbiAqL1xuXG4vKipcbiAqIEBzdW1tYXJ5ICAgICBEYXRhVGFibGVzXG4gKiBAZGVzY3JpcHRpb24gUGFnaW5hdGUsIHNlYXJjaCBhbmQgb3JkZXIgSFRNTCB0YWJsZXNcbiAqIEB2ZXJzaW9uICAgICAxLjEwLjE2XG4gKiBAZmlsZSAgICAgICAganF1ZXJ5LmRhdGFUYWJsZXMuanNcbiAqIEBhdXRob3IgICAgICBTcHJ5TWVkaWEgTHRkXG4gKiBAY29udGFjdCAgICAgd3d3LmRhdGF0YWJsZXMubmV0XG4gKiBAY29weXJpZ2h0ICAgQ29weXJpZ2h0IDIwMDgtMjAxNyBTcHJ5TWVkaWEgTHRkLlxuICpcbiAqIFRoaXMgc291cmNlIGZpbGUgaXMgZnJlZSBzb2Z0d2FyZSwgYXZhaWxhYmxlIHVuZGVyIHRoZSBmb2xsb3dpbmcgbGljZW5zZTpcbiAqICAgTUlUIGxpY2Vuc2UgLSBodHRwOi8vZGF0YXRhYmxlcy5uZXQvbGljZW5zZVxuICpcbiAqIFRoaXMgc291cmNlIGZpbGUgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCwgYnV0XG4gKiBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mIE1FUkNIQU5UQUJJTElUWVxuICogb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuIFNlZSB0aGUgbGljZW5zZSBmaWxlcyBmb3IgZGV0YWlscy5cbiAqXG4gKiBGb3IgZGV0YWlscyBwbGVhc2UgcmVmZXIgdG86IGh0dHA6Ly93d3cuZGF0YXRhYmxlcy5uZXRcbiAqL1xuXG4vKmpzbGludCBldmlsOiB0cnVlLCB1bmRlZjogdHJ1ZSwgYnJvd3NlcjogdHJ1ZSAqL1xuLypnbG9iYWxzICQscmVxdWlyZSxqUXVlcnksZGVmaW5lLF9zZWxlY3Rvcl9ydW4sX3NlbGVjdG9yX29wdHMsX3NlbGVjdG9yX2ZpcnN0LF9zZWxlY3Rvcl9yb3dfaW5kZXhlcyxfZXh0LF9BcGksX2FwaV9yZWdpc3RlcixfYXBpX3JlZ2lzdGVyUGx1cmFsLF9yZV9uZXdfbGluZXMsX3JlX2h0bWwsX3JlX2Zvcm1hdHRlZF9udW1lcmljLF9yZV9lc2NhcGVfcmVnZXgsX2VtcHR5LF9pbnRWYWwsX251bVRvRGVjaW1hbCxfaXNOdW1iZXIsX2lzSHRtbCxfaHRtbE51bWVyaWMsX3BsdWNrLF9wbHVja19vcmRlcixfcmFuZ2UsX3N0cmlwSHRtbCxfdW5pcXVlLF9mbkJ1aWxkQWpheCxfZm5BamF4VXBkYXRlLF9mbkFqYXhQYXJhbWV0ZXJzLF9mbkFqYXhVcGRhdGVEcmF3LF9mbkFqYXhEYXRhU3JjLF9mbkFkZENvbHVtbixfZm5Db2x1bW5PcHRpb25zLF9mbkFkanVzdENvbHVtblNpemluZyxfZm5WaXNpYmxlVG9Db2x1bW5JbmRleCxfZm5Db2x1bW5JbmRleFRvVmlzaWJsZSxfZm5WaXNibGVDb2x1bW5zLF9mbkdldENvbHVtbnMsX2ZuQ29sdW1uVHlwZXMsX2ZuQXBwbHlDb2x1bW5EZWZzLF9mbkh1bmdhcmlhbk1hcCxfZm5DYW1lbFRvSHVuZ2FyaWFuLF9mbkxhbmd1YWdlQ29tcGF0LF9mbkJyb3dzZXJEZXRlY3QsX2ZuQWRkRGF0YSxfZm5BZGRUcixfZm5Ob2RlVG9EYXRhSW5kZXgsX2ZuTm9kZVRvQ29sdW1uSW5kZXgsX2ZuR2V0Q2VsbERhdGEsX2ZuU2V0Q2VsbERhdGEsX2ZuU3BsaXRPYmpOb3RhdGlvbixfZm5HZXRPYmplY3REYXRhRm4sX2ZuU2V0T2JqZWN0RGF0YUZuLF9mbkdldERhdGFNYXN0ZXIsX2ZuQ2xlYXJUYWJsZSxfZm5EZWxldGVJbmRleCxfZm5JbnZhbGlkYXRlLF9mbkdldFJvd0VsZW1lbnRzLF9mbkNyZWF0ZVRyLF9mbkJ1aWxkSGVhZCxfZm5EcmF3SGVhZCxfZm5EcmF3LF9mblJlRHJhdyxfZm5BZGRPcHRpb25zSHRtbCxfZm5EZXRlY3RIZWFkZXIsX2ZuR2V0VW5pcXVlVGhzLF9mbkZlYXR1cmVIdG1sRmlsdGVyLF9mbkZpbHRlckNvbXBsZXRlLF9mbkZpbHRlckN1c3RvbSxfZm5GaWx0ZXJDb2x1bW4sX2ZuRmlsdGVyLF9mbkZpbHRlckNyZWF0ZVNlYXJjaCxfZm5Fc2NhcGVSZWdleCxfZm5GaWx0ZXJEYXRhLF9mbkZlYXR1cmVIdG1sSW5mbyxfZm5VcGRhdGVJbmZvLF9mbkluZm9NYWNyb3MsX2ZuSW5pdGlhbGlzZSxfZm5Jbml0Q29tcGxldGUsX2ZuTGVuZ3RoQ2hhbmdlLF9mbkZlYXR1cmVIdG1sTGVuZ3RoLF9mbkZlYXR1cmVIdG1sUGFnaW5hdGUsX2ZuUGFnZUNoYW5nZSxfZm5GZWF0dXJlSHRtbFByb2Nlc3NpbmcsX2ZuUHJvY2Vzc2luZ0Rpc3BsYXksX2ZuRmVhdHVyZUh0bWxUYWJsZSxfZm5TY3JvbGxEcmF3LF9mbkFwcGx5VG9DaGlsZHJlbixfZm5DYWxjdWxhdGVDb2x1bW5XaWR0aHMsX2ZuVGhyb3R0bGUsX2ZuQ29udmVydFRvV2lkdGgsX2ZuR2V0V2lkZXN0Tm9kZSxfZm5HZXRNYXhMZW5TdHJpbmcsX2ZuU3RyaW5nVG9Dc3MsX2ZuU29ydEZsYXR0ZW4sX2ZuU29ydCxfZm5Tb3J0QXJpYSxfZm5Tb3J0TGlzdGVuZXIsX2ZuU29ydEF0dGFjaExpc3RlbmVyLF9mblNvcnRpbmdDbGFzc2VzLF9mblNvcnREYXRhLF9mblNhdmVTdGF0ZSxfZm5Mb2FkU3RhdGUsX2ZuU2V0dGluZ3NGcm9tTm9kZSxfZm5Mb2csX2ZuTWFwLF9mbkJpbmRBY3Rpb24sX2ZuQ2FsbGJhY2tSZWcsX2ZuQ2FsbGJhY2tGaXJlLF9mbkxlbmd0aE92ZXJmbG93LF9mblJlbmRlcmVyLF9mbkRhdGFTb3VyY2UsX2ZuUm93QXR0cmlidXRlcyovXG5cbihmdW5jdGlvbiggZmFjdG9yeSApIHtcblx0XCJ1c2Ugc3RyaWN0XCI7XG5cblx0aWYgKCB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKCBbJ2pxdWVyeSddLCBmdW5jdGlvbiAoICQgKSB7XG5cdFx0XHRyZXR1cm4gZmFjdG9yeSggJCwgd2luZG93LCBkb2N1bWVudCApO1xuXHRcdH0gKTtcblx0fVxuXHRlbHNlIGlmICggdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICkge1xuXHRcdC8vIENvbW1vbkpTXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocm9vdCwgJCkge1xuXHRcdFx0aWYgKCAhIHJvb3QgKSB7XG5cdFx0XHRcdC8vIENvbW1vbkpTIGVudmlyb25tZW50cyB3aXRob3V0IGEgd2luZG93IGdsb2JhbCBtdXN0IHBhc3MgYVxuXHRcdFx0XHQvLyByb290LiBUaGlzIHdpbGwgZ2l2ZSBhbiBlcnJvciBvdGhlcndpc2Vcblx0XHRcdFx0cm9vdCA9IHdpbmRvdztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhICQgKSB7XG5cdFx0XHRcdCQgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IC8vIGpRdWVyeSdzIGZhY3RvcnkgY2hlY2tzIGZvciBhIGdsb2JhbCB3aW5kb3dcblx0XHRcdFx0XHRyZXF1aXJlKCdqcXVlcnknKSA6XG5cdFx0XHRcdFx0cmVxdWlyZSgnanF1ZXJ5JykoIHJvb3QgKTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGZhY3RvcnkoICQsIHJvb3QsIHJvb3QuZG9jdW1lbnQgKTtcblx0XHR9O1xuXHR9XG5cdGVsc2Uge1xuXHRcdC8vIEJyb3dzZXJcblx0XHRmYWN0b3J5KCBqUXVlcnksIHdpbmRvdywgZG9jdW1lbnQgKTtcblx0fVxufVxuKGZ1bmN0aW9uKCAkLCB3aW5kb3csIGRvY3VtZW50LCB1bmRlZmluZWQgKSB7XG5cdFwidXNlIHN0cmljdFwiO1xuXG5cdC8qKlxuXHQgKiBEYXRhVGFibGVzIGlzIGEgcGx1Zy1pbiBmb3IgdGhlIGpRdWVyeSBKYXZhc2NyaXB0IGxpYnJhcnkuIEl0IGlzIGEgaGlnaGx5XG5cdCAqIGZsZXhpYmxlIHRvb2wsIGJhc2VkIHVwb24gdGhlIGZvdW5kYXRpb25zIG9mIHByb2dyZXNzaXZlIGVuaGFuY2VtZW50LFxuXHQgKiB3aGljaCB3aWxsIGFkZCBhZHZhbmNlZCBpbnRlcmFjdGlvbiBjb250cm9scyB0byBhbnkgSFRNTCB0YWJsZS4gRm9yIGFcblx0ICogZnVsbCBsaXN0IG9mIGZlYXR1cmVzIHBsZWFzZSByZWZlciB0b1xuXHQgKiBbRGF0YVRhYmxlcy5uZXRdKGhyZWY9XCJodHRwOi8vZGF0YXRhYmxlcy5uZXQpLlxuXHQgKlxuXHQgKiBOb3RlIHRoYXQgdGhlIGBEYXRhVGFibGVgIG9iamVjdCBpcyBub3QgYSBnbG9iYWwgdmFyaWFibGUgYnV0IGlzIGFsaWFzZWRcblx0ICogdG8gYGpRdWVyeS5mbi5EYXRhVGFibGVgIGFuZCBgalF1ZXJ5LmZuLmRhdGFUYWJsZWAgdGhyb3VnaCB3aGljaCBpdCBtYXlcblx0ICogYmUgIGFjY2Vzc2VkLlxuXHQgKlxuXHQgKiAgQGNsYXNzXG5cdCAqICBAcGFyYW0ge29iamVjdH0gW2luaXQ9e31dIENvbmZpZ3VyYXRpb24gb2JqZWN0IGZvciBEYXRhVGFibGVzLiBPcHRpb25zXG5cdCAqICAgIGFyZSBkZWZpbmVkIGJ5IHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9XG5cdCAqICBAcmVxdWlyZXMgalF1ZXJ5IDEuNytcblx0ICpcblx0ICogIEBleGFtcGxlXG5cdCAqICAgIC8vIEJhc2ljIGluaXRpYWxpc2F0aW9uXG5cdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiB7XG5cdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0ICogICAgfSApO1xuXHQgKlxuXHQgKiAgQGV4YW1wbGVcblx0ICogICAgLy8gSW5pdGlhbGlzYXRpb24gd2l0aCBjb25maWd1cmF0aW9uIG9wdGlvbnMgLSBpbiB0aGlzIGNhc2UsIGRpc2FibGVcblx0ICogICAgLy8gcGFnaW5hdGlvbiBhbmQgc29ydGluZy5cblx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uIHtcblx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHQgKiAgICAgICAgXCJwYWdpbmF0ZVwiOiBmYWxzZSxcblx0ICogICAgICAgIFwic29ydFwiOiBmYWxzZVxuXHQgKiAgICAgIH0gKTtcblx0ICogICAgfSApO1xuXHQgKi9cblx0dmFyIERhdGFUYWJsZSA9IGZ1bmN0aW9uICggb3B0aW9ucyApXG5cdHtcblx0XHQvKipcblx0XHQgKiBQZXJmb3JtIGEgalF1ZXJ5IHNlbGVjdG9yIGFjdGlvbiBvbiB0aGUgdGFibGUncyBUUiBlbGVtZW50cyAoZnJvbSB0aGUgdGJvZHkpIGFuZFxuXHRcdCAqIHJldHVybiB0aGUgcmVzdWx0aW5nIGpRdWVyeSBvYmplY3QuXG5cdFx0ICogIEBwYXJhbSB7c3RyaW5nfG5vZGV8alF1ZXJ5fSBzU2VsZWN0b3IgalF1ZXJ5IHNlbGVjdG9yIG9yIG5vZGUgY29sbGVjdGlvbiB0byBhY3Qgb25cblx0XHQgKiAgQHBhcmFtIHtvYmplY3R9IFtvT3B0c10gT3B0aW9uYWwgcGFyYW1ldGVycyBmb3IgbW9kaWZ5aW5nIHRoZSByb3dzIHRvIGJlIGluY2x1ZGVkXG5cdFx0ICogIEBwYXJhbSB7c3RyaW5nfSBbb09wdHMuZmlsdGVyPW5vbmVdIFNlbGVjdCBUUiBlbGVtZW50cyB0aGF0IG1lZXQgdGhlIGN1cnJlbnQgZmlsdGVyXG5cdFx0ICogICAgY3JpdGVyaW9uIChcImFwcGxpZWRcIikgb3IgYWxsIFRSIGVsZW1lbnRzIChpLmUuIG5vIGZpbHRlcikuXG5cdFx0ICogIEBwYXJhbSB7c3RyaW5nfSBbb09wdHMub3JkZXI9Y3VycmVudF0gT3JkZXIgb2YgdGhlIFRSIGVsZW1lbnRzIGluIHRoZSBwcm9jZXNzZWQgYXJyYXkuXG5cdFx0ICogICAgQ2FuIGJlIGVpdGhlciAnY3VycmVudCcsIHdoZXJlYnkgdGhlIGN1cnJlbnQgc29ydGluZyBvZiB0aGUgdGFibGUgaXMgdXNlZCwgb3Jcblx0XHQgKiAgICAnb3JpZ2luYWwnIHdoZXJlYnkgdGhlIG9yaWdpbmFsIG9yZGVyIHRoZSBkYXRhIHdhcyByZWFkIGludG8gdGhlIHRhYmxlIGlzIHVzZWQuXG5cdFx0ICogIEBwYXJhbSB7c3RyaW5nfSBbb09wdHMucGFnZT1hbGxdIExpbWl0IHRoZSBzZWxlY3Rpb24gdG8gdGhlIGN1cnJlbnRseSBkaXNwbGF5ZWQgcGFnZVxuXHRcdCAqICAgIChcImN1cnJlbnRcIikgb3Igbm90IChcImFsbFwiKS4gSWYgJ2N1cnJlbnQnIGlzIGdpdmVuLCB0aGVuIG9yZGVyIGlzIGFzc3VtZWQgdG8gYmVcblx0XHQgKiAgICAnY3VycmVudCcgYW5kIGZpbHRlciBpcyAnYXBwbGllZCcsIHJlZ2FyZGxlc3Mgb2Ygd2hhdCB0aGV5IG1pZ2h0IGJlIGdpdmVuIGFzLlxuXHRcdCAqICBAcmV0dXJucyB7b2JqZWN0fSBqUXVlcnkgb2JqZWN0LCBmaWx0ZXJlZCBieSB0aGUgZ2l2ZW4gc2VsZWN0b3IuXG5cdFx0ICogIEBkdG9wdCBBUElcblx0XHQgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTBcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vIEhpZ2hsaWdodCBldmVyeSBzZWNvbmQgcm93XG5cdFx0ICogICAgICBvVGFibGUuJCgndHI6b2RkJykuY3NzKCdiYWNrZ3JvdW5kQ29sb3InLCAnYmx1ZScpO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vIEZpbHRlciB0byByb3dzIHdpdGggJ1dlYmtpdCcgaW4gdGhlbSwgYWRkIGEgYmFja2dyb3VuZCBjb2xvdXIgYW5kIHRoZW5cblx0XHQgKiAgICAgIC8vIHJlbW92ZSB0aGUgZmlsdGVyLCB0aHVzIGhpZ2hsaWdodGluZyB0aGUgJ1dlYmtpdCcgcm93cyBvbmx5LlxuXHRcdCAqICAgICAgb1RhYmxlLmZuRmlsdGVyKCdXZWJraXQnKTtcblx0XHQgKiAgICAgIG9UYWJsZS4kKCd0cicsIHtcInNlYXJjaFwiOiBcImFwcGxpZWRcIn0pLmNzcygnYmFja2dyb3VuZENvbG9yJywgJ2JsdWUnKTtcblx0XHQgKiAgICAgIG9UYWJsZS5mbkZpbHRlcignJyk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdHRoaXMuJCA9IGZ1bmN0aW9uICggc1NlbGVjdG9yLCBvT3B0cyApXG5cdFx0e1xuXHRcdFx0cmV0dXJuIHRoaXMuYXBpKHRydWUpLiQoIHNTZWxlY3Rvciwgb09wdHMgKTtcblx0XHR9O1xuXHRcdFxuXHRcdFxuXHRcdC8qKlxuXHRcdCAqIEFsbW9zdCBpZGVudGljYWwgdG8gJCBpbiBvcGVyYXRpb24sIGJ1dCBpbiB0aGlzIGNhc2UgcmV0dXJucyB0aGUgZGF0YSBmb3IgdGhlIG1hdGNoZWRcblx0XHQgKiByb3dzIC0gYXMgc3VjaCwgdGhlIGpRdWVyeSBzZWxlY3RvciB1c2VkIHNob3VsZCBtYXRjaCBUUiByb3cgbm9kZXMgb3IgVEQvVEggY2VsbCBub2Rlc1xuXHRcdCAqIHJhdGhlciB0aGFuIGFueSBkZXNjZW5kYW50cywgc28gdGhlIGRhdGEgY2FuIGJlIG9idGFpbmVkIGZvciB0aGUgcm93L2NlbGwuIElmIG1hdGNoaW5nXG5cdFx0ICogcm93cyBhcmUgZm91bmQsIHRoZSBkYXRhIHJldHVybmVkIGlzIHRoZSBvcmlnaW5hbCBkYXRhIGFycmF5L29iamVjdCB0aGF0IHdhcyB1c2VkIHRvXG5cdFx0ICogY3JlYXRlIHRoZSByb3cgKG9yIGEgZ2VuZXJhdGVkIGFycmF5IGlmIGZyb20gYSBET00gc291cmNlKS5cblx0XHQgKlxuXHRcdCAqIFRoaXMgbWV0aG9kIGlzIG9mdGVuIHVzZWZ1bCBpbi1jb21iaW5hdGlvbiB3aXRoICQgd2hlcmUgYm90aCBmdW5jdGlvbnMgYXJlIGdpdmVuIHRoZVxuXHRcdCAqIHNhbWUgcGFyYW1ldGVycyBhbmQgdGhlIGFycmF5IGluZGV4ZXMgd2lsbCBtYXRjaCBpZGVudGljYWxseS5cblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd8bm9kZXxqUXVlcnl9IHNTZWxlY3RvciBqUXVlcnkgc2VsZWN0b3Igb3Igbm9kZSBjb2xsZWN0aW9uIHRvIGFjdCBvblxuXHRcdCAqICBAcGFyYW0ge29iamVjdH0gW29PcHRzXSBPcHRpb25hbCBwYXJhbWV0ZXJzIGZvciBtb2RpZnlpbmcgdGhlIHJvd3MgdG8gYmUgaW5jbHVkZWRcblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd9IFtvT3B0cy5maWx0ZXI9bm9uZV0gU2VsZWN0IGVsZW1lbnRzIHRoYXQgbWVldCB0aGUgY3VycmVudCBmaWx0ZXJcblx0XHQgKiAgICBjcml0ZXJpb24gKFwiYXBwbGllZFwiKSBvciBhbGwgZWxlbWVudHMgKGkuZS4gbm8gZmlsdGVyKS5cblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd9IFtvT3B0cy5vcmRlcj1jdXJyZW50XSBPcmRlciBvZiB0aGUgZGF0YSBpbiB0aGUgcHJvY2Vzc2VkIGFycmF5LlxuXHRcdCAqICAgIENhbiBiZSBlaXRoZXIgJ2N1cnJlbnQnLCB3aGVyZWJ5IHRoZSBjdXJyZW50IHNvcnRpbmcgb2YgdGhlIHRhYmxlIGlzIHVzZWQsIG9yXG5cdFx0ICogICAgJ29yaWdpbmFsJyB3aGVyZWJ5IHRoZSBvcmlnaW5hbCBvcmRlciB0aGUgZGF0YSB3YXMgcmVhZCBpbnRvIHRoZSB0YWJsZSBpcyB1c2VkLlxuXHRcdCAqICBAcGFyYW0ge3N0cmluZ30gW29PcHRzLnBhZ2U9YWxsXSBMaW1pdCB0aGUgc2VsZWN0aW9uIHRvIHRoZSBjdXJyZW50bHkgZGlzcGxheWVkIHBhZ2Vcblx0XHQgKiAgICAoXCJjdXJyZW50XCIpIG9yIG5vdCAoXCJhbGxcIikuIElmICdjdXJyZW50JyBpcyBnaXZlbiwgdGhlbiBvcmRlciBpcyBhc3N1bWVkIHRvIGJlXG5cdFx0ICogICAgJ2N1cnJlbnQnIGFuZCBmaWx0ZXIgaXMgJ2FwcGxpZWQnLCByZWdhcmRsZXNzIG9mIHdoYXQgdGhleSBtaWdodCBiZSBnaXZlbiBhcy5cblx0XHQgKiAgQHJldHVybnMge2FycmF5fSBEYXRhIGZvciB0aGUgbWF0Y2hlZCBlbGVtZW50cy4gSWYgYW55IGVsZW1lbnRzLCBhcyBhIHJlc3VsdCBvZiB0aGVcblx0XHQgKiAgICBzZWxlY3Rvciwgd2VyZSBub3QgVFIsIFREIG9yIFRIIGVsZW1lbnRzIGluIHRoZSBEYXRhVGFibGUsIHRoZXkgd2lsbCBoYXZlIGEgbnVsbFxuXHRcdCAqICAgIGVudHJ5IGluIHRoZSBhcnJheS5cblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0XHQgKlxuXHRcdCAqICAgICAgLy8gR2V0IHRoZSBkYXRhIGZyb20gdGhlIGZpcnN0IHJvdyBpbiB0aGUgdGFibGVcblx0XHQgKiAgICAgIHZhciBkYXRhID0gb1RhYmxlLl8oJ3RyOmZpcnN0Jyk7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vIERvIHNvbWV0aGluZyB1c2VmdWwgd2l0aCB0aGUgZGF0YVxuXHRcdCAqICAgICAgYWxlcnQoIFwiRmlyc3QgY2VsbCBpczogXCIrZGF0YVswXSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vIEZpbHRlciB0byAnV2Via2l0JyBhbmQgZ2V0IGFsbCBkYXRhIGZvclxuXHRcdCAqICAgICAgb1RhYmxlLmZuRmlsdGVyKCdXZWJraXQnKTtcblx0XHQgKiAgICAgIHZhciBkYXRhID0gb1RhYmxlLl8oJ3RyJywge1wic2VhcmNoXCI6IFwiYXBwbGllZFwifSk7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vIERvIHNvbWV0aGluZyB3aXRoIHRoZSBkYXRhXG5cdFx0ICogICAgICBhbGVydCggZGF0YS5sZW5ndGgrXCIgcm93cyBtYXRjaGVkIHRoZSBzZWFyY2hcIiApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHR0aGlzLl8gPSBmdW5jdGlvbiAoIHNTZWxlY3Rvciwgb09wdHMgKVxuXHRcdHtcblx0XHRcdHJldHVybiB0aGlzLmFwaSh0cnVlKS5yb3dzKCBzU2VsZWN0b3IsIG9PcHRzICkuZGF0YSgpO1xuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogQ3JlYXRlIGEgRGF0YVRhYmxlcyBBcGkgaW5zdGFuY2UsIHdpdGggdGhlIGN1cnJlbnRseSBzZWxlY3RlZCB0YWJsZXMgZm9yXG5cdFx0ICogdGhlIEFwaSdzIGNvbnRleHQuXG5cdFx0ICogQHBhcmFtIHtib29sZWFufSBbdHJhZGl0aW9uYWw9ZmFsc2VdIFNldCB0aGUgQVBJIGluc3RhbmNlJ3MgY29udGV4dCB0byBiZVxuXHRcdCAqICAgb25seSB0aGUgdGFibGUgcmVmZXJyZWQgdG8gYnkgdGhlIGBEYXRhVGFibGUuZXh0LmlBcGlJbmRleGAgb3B0aW9uLCBhcyB3YXNcblx0XHQgKiAgIHVzZWQgaW4gdGhlIEFQSSBwcmVzZW50ZWQgYnkgRGF0YVRhYmxlcyAxLjktIChpLmUuIHRoZSB0cmFkaXRpb25hbCBtb2RlKSxcblx0XHQgKiAgIG9yIGlmIGFsbCB0YWJsZXMgY2FwdHVyZWQgaW4gdGhlIGpRdWVyeSBvYmplY3Qgc2hvdWxkIGJlIHVzZWQuXG5cdFx0ICogQHJldHVybiB7RGF0YVRhYmxlcy5BcGl9XG5cdFx0ICovXG5cdFx0dGhpcy5hcGkgPSBmdW5jdGlvbiAoIHRyYWRpdGlvbmFsIClcblx0XHR7XG5cdFx0XHRyZXR1cm4gdHJhZGl0aW9uYWwgP1xuXHRcdFx0XHRuZXcgX0FwaShcblx0XHRcdFx0XHRfZm5TZXR0aW5nc0Zyb21Ob2RlKCB0aGlzWyBfZXh0LmlBcGlJbmRleCBdIClcblx0XHRcdFx0KSA6XG5cdFx0XHRcdG5ldyBfQXBpKCB0aGlzICk7XG5cdFx0fTtcblx0XHRcblx0XHRcblx0XHQvKipcblx0XHQgKiBBZGQgYSBzaW5nbGUgbmV3IHJvdyBvciBtdWx0aXBsZSByb3dzIG9mIGRhdGEgdG8gdGhlIHRhYmxlLiBQbGVhc2Ugbm90ZVxuXHRcdCAqIHRoYXQgdGhpcyBpcyBzdWl0YWJsZSBmb3IgY2xpZW50LXNpZGUgcHJvY2Vzc2luZyBvbmx5IC0gaWYgeW91IGFyZSB1c2luZ1xuXHRcdCAqIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcgKGkuZS4gXCJiU2VydmVyU2lkZVwiOiB0cnVlKSwgdGhlbiB0byBhZGQgZGF0YSwgeW91XG5cdFx0ICogbXVzdCBhZGQgaXQgdG8gdGhlIGRhdGEgc291cmNlLCBpLmUuIHRoZSBzZXJ2ZXItc2lkZSwgdGhyb3VnaCBhbiBBamF4IGNhbGwuXG5cdFx0ICogIEBwYXJhbSB7YXJyYXl8b2JqZWN0fSBkYXRhIFRoZSBkYXRhIHRvIGJlIGFkZGVkIHRvIHRoZSB0YWJsZS4gVGhpcyBjYW4gYmU6XG5cdFx0ICogICAgPHVsPlxuXHRcdCAqICAgICAgPGxpPjFEIGFycmF5IG9mIGRhdGEgLSBhZGQgYSBzaW5nbGUgcm93IHdpdGggdGhlIGRhdGEgcHJvdmlkZWQ8L2xpPlxuXHRcdCAqICAgICAgPGxpPjJEIGFycmF5IG9mIGFycmF5cyAtIGFkZCBtdWx0aXBsZSByb3dzIGluIGEgc2luZ2xlIGNhbGw8L2xpPlxuXHRcdCAqICAgICAgPGxpPm9iamVjdCAtIGRhdGEgb2JqZWN0IHdoZW4gdXNpbmcgPGk+bURhdGE8L2k+PC9saT5cblx0XHQgKiAgICAgIDxsaT5hcnJheSBvZiBvYmplY3RzIC0gbXVsdGlwbGUgZGF0YSBvYmplY3RzIHdoZW4gdXNpbmcgPGk+bURhdGE8L2k+PC9saT5cblx0XHQgKiAgICA8L3VsPlxuXHRcdCAqICBAcGFyYW0ge2Jvb2x9IFtyZWRyYXc9dHJ1ZV0gcmVkcmF3IHRoZSB0YWJsZSBvciBub3Rcblx0XHQgKiAgQHJldHVybnMge2FycmF5fSBBbiBhcnJheSBvZiBpbnRlZ2VycywgcmVwcmVzZW50aW5nIHRoZSBsaXN0IG9mIGluZGV4ZXMgaW5cblx0XHQgKiAgICA8aT5hb0RhdGE8L2k+ICh7QGxpbmsgRGF0YVRhYmxlLm1vZGVscy5vU2V0dGluZ3N9KSB0aGF0IGhhdmUgYmVlbiBhZGRlZCB0b1xuXHRcdCAqICAgIHRoZSB0YWJsZS5cblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gR2xvYmFsIHZhciBmb3IgY291bnRlclxuXHRcdCAqICAgIHZhciBnaUNvdW50ID0gMjtcblx0XHQgKlxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgICBmdW5jdGlvbiBmbkNsaWNrQWRkUm93KCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKS5mbkFkZERhdGEoIFtcblx0XHQgKiAgICAgICAgZ2lDb3VudCtcIi4xXCIsXG5cdFx0ICogICAgICAgIGdpQ291bnQrXCIuMlwiLFxuXHRcdCAqICAgICAgICBnaUNvdW50K1wiLjNcIixcblx0XHQgKiAgICAgICAgZ2lDb3VudCtcIi40XCIgXVxuXHRcdCAqICAgICAgKTtcblx0XHQgKlxuXHRcdCAqICAgICAgZ2lDb3VudCsrO1xuXHRcdCAqICAgIH1cblx0XHQgKi9cblx0XHR0aGlzLmZuQWRkRGF0YSA9IGZ1bmN0aW9uKCBkYXRhLCByZWRyYXcgKVxuXHRcdHtcblx0XHRcdHZhciBhcGkgPSB0aGlzLmFwaSggdHJ1ZSApO1xuXHRcdFxuXHRcdFx0LyogQ2hlY2sgaWYgd2Ugd2FudCB0byBhZGQgbXVsdGlwbGUgcm93cyBvciBub3QgKi9cblx0XHRcdHZhciByb3dzID0gJC5pc0FycmF5KGRhdGEpICYmICggJC5pc0FycmF5KGRhdGFbMF0pIHx8ICQuaXNQbGFpbk9iamVjdChkYXRhWzBdKSApID9cblx0XHRcdFx0YXBpLnJvd3MuYWRkKCBkYXRhICkgOlxuXHRcdFx0XHRhcGkucm93LmFkZCggZGF0YSApO1xuXHRcdFxuXHRcdFx0aWYgKCByZWRyYXcgPT09IHVuZGVmaW5lZCB8fCByZWRyYXcgKSB7XG5cdFx0XHRcdGFwaS5kcmF3KCk7XG5cdFx0XHR9XG5cdFx0XG5cdFx0XHRyZXR1cm4gcm93cy5mbGF0dGVuKCkudG9BcnJheSgpO1xuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogVGhpcyBmdW5jdGlvbiB3aWxsIG1ha2UgRGF0YVRhYmxlcyByZWNhbGN1bGF0ZSB0aGUgY29sdW1uIHNpemVzLCBiYXNlZCBvbiB0aGUgZGF0YVxuXHRcdCAqIGNvbnRhaW5lZCBpbiB0aGUgdGFibGUgYW5kIHRoZSBzaXplcyBhcHBsaWVkIHRvIHRoZSBjb2x1bW5zIChpbiB0aGUgRE9NLCBDU1Mgb3Jcblx0XHQgKiB0aHJvdWdoIHRoZSBzV2lkdGggcGFyYW1ldGVyKS4gVGhpcyBjYW4gYmUgdXNlZnVsIHdoZW4gdGhlIHdpZHRoIG9mIHRoZSB0YWJsZSdzXG5cdFx0ICogcGFyZW50IGVsZW1lbnQgY2hhbmdlcyAoZm9yIGV4YW1wbGUgYSB3aW5kb3cgcmVzaXplKS5cblx0XHQgKiAgQHBhcmFtIHtib29sZWFufSBbYlJlZHJhdz10cnVlXSBSZWRyYXcgdGhlIHRhYmxlIG9yIG5vdCwgeW91IHdpbGwgdHlwaWNhbGx5IHdhbnQgdG9cblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJzU2Nyb2xsWVwiOiBcIjIwMHB4XCIsXG5cdFx0ICogICAgICAgIFwiYlBhZ2luYXRlXCI6IGZhbHNlXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgICAgICQod2luZG93KS5vbigncmVzaXplJywgZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgICBvVGFibGUuZm5BZGp1c3RDb2x1bW5TaXppbmcoKTtcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0dGhpcy5mbkFkanVzdENvbHVtblNpemluZyA9IGZ1bmN0aW9uICggYlJlZHJhdyApXG5cdFx0e1xuXHRcdFx0dmFyIGFwaSA9IHRoaXMuYXBpKCB0cnVlICkuY29sdW1ucy5hZGp1c3QoKTtcblx0XHRcdHZhciBzZXR0aW5ncyA9IGFwaS5zZXR0aW5ncygpWzBdO1xuXHRcdFx0dmFyIHNjcm9sbCA9IHNldHRpbmdzLm9TY3JvbGw7XG5cdFx0XG5cdFx0XHRpZiAoIGJSZWRyYXcgPT09IHVuZGVmaW5lZCB8fCBiUmVkcmF3ICkge1xuXHRcdFx0XHRhcGkuZHJhdyggZmFsc2UgKTtcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKCBzY3JvbGwuc1ggIT09IFwiXCIgfHwgc2Nyb2xsLnNZICE9PSBcIlwiICkge1xuXHRcdFx0XHQvKiBJZiBub3QgcmVkcmF3aW5nLCBidXQgc2Nyb2xsaW5nLCB3ZSB3YW50IHRvIGFwcGx5IHRoZSBuZXcgY29sdW1uIHNpemVzIGFueXdheSAqL1xuXHRcdFx0XHRfZm5TY3JvbGxEcmF3KCBzZXR0aW5ncyApO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogUXVpY2tseSBhbmQgc2ltcGx5IGNsZWFyIGEgdGFibGVcblx0XHQgKiAgQHBhcmFtIHtib29sfSBbYlJlZHJhdz10cnVlXSByZWRyYXcgdGhlIHRhYmxlIG9yIG5vdFxuXHRcdCAqICBAZHRvcHQgQVBJXG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHRcdCAqXG5cdFx0ICogICAgICAvLyBJbW1lZGlhdGVseSAnbnVrZScgdGhlIGN1cnJlbnQgcm93cyAocGVyaGFwcyB3YWl0aW5nIGZvciBhbiBBamF4IGNhbGxiYWNrLi4uKVxuXHRcdCAqICAgICAgb1RhYmxlLmZuQ2xlYXJUYWJsZSgpO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHR0aGlzLmZuQ2xlYXJUYWJsZSA9IGZ1bmN0aW9uKCBiUmVkcmF3IClcblx0XHR7XG5cdFx0XHR2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKS5jbGVhcigpO1xuXHRcdFxuXHRcdFx0aWYgKCBiUmVkcmF3ID09PSB1bmRlZmluZWQgfHwgYlJlZHJhdyApIHtcblx0XHRcdFx0YXBpLmRyYXcoKTtcblx0XHRcdH1cblx0XHR9O1xuXHRcdFxuXHRcdFxuXHRcdC8qKlxuXHRcdCAqIFRoZSBleGFjdCBvcHBvc2l0ZSBvZiAnb3BlbmluZycgYSByb3csIHRoaXMgZnVuY3Rpb24gd2lsbCBjbG9zZSBhbnkgcm93cyB3aGljaFxuXHRcdCAqIGFyZSBjdXJyZW50bHkgJ29wZW4nLlxuXHRcdCAqICBAcGFyYW0ge25vZGV9IG5UciB0aGUgdGFibGUgcm93IHRvICdjbG9zZSdcblx0XHQgKiAgQHJldHVybnMge2ludH0gMCBvbiBzdWNjZXNzLCBvciAxIGlmIGZhaWxlZCAoY2FuJ3QgZmluZCB0aGUgcm93KVxuXHRcdCAqICBAZHRvcHQgQVBJXG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgIHZhciBvVGFibGU7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vICdvcGVuJyBhbiBpbmZvcm1hdGlvbiByb3cgd2hlbiBhIHJvdyBpcyBjbGlja2VkIG9uXG5cdFx0ICogICAgICAkKCcjZXhhbXBsZSB0Ym9keSB0cicpLmNsaWNrKCBmdW5jdGlvbiAoKSB7XG5cdFx0ICogICAgICAgIGlmICggb1RhYmxlLmZuSXNPcGVuKHRoaXMpICkge1xuXHRcdCAqICAgICAgICAgIG9UYWJsZS5mbkNsb3NlKCB0aGlzICk7XG5cdFx0ICogICAgICAgIH0gZWxzZSB7XG5cdFx0ICogICAgICAgICAgb1RhYmxlLmZuT3BlbiggdGhpcywgXCJUZW1wb3Jhcnkgcm93IG9wZW5lZFwiLCBcImluZm9fcm93XCIgKTtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqXG5cdFx0ICogICAgICBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHR0aGlzLmZuQ2xvc2UgPSBmdW5jdGlvbiggblRyIClcblx0XHR7XG5cdFx0XHR0aGlzLmFwaSggdHJ1ZSApLnJvdyggblRyICkuY2hpbGQuaGlkZSgpO1xuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogUmVtb3ZlIGEgcm93IGZvciB0aGUgdGFibGVcblx0XHQgKiAgQHBhcmFtIHttaXhlZH0gdGFyZ2V0IFRoZSBpbmRleCBvZiB0aGUgcm93IGZyb20gYW9EYXRhIHRvIGJlIGRlbGV0ZWQsIG9yXG5cdFx0ICogICAgdGhlIFRSIGVsZW1lbnQgeW91IHdhbnQgdG8gZGVsZXRlXG5cdFx0ICogIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gW2NhbGxCYWNrXSBDYWxsYmFjayBmdW5jdGlvblxuXHRcdCAqICBAcGFyYW0ge2Jvb2x9IFtyZWRyYXc9dHJ1ZV0gUmVkcmF3IHRoZSB0YWJsZSBvciBub3Rcblx0XHQgKiAgQHJldHVybnMge2FycmF5fSBUaGUgcm93IHRoYXQgd2FzIGRlbGV0ZWRcblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0XHQgKlxuXHRcdCAqICAgICAgLy8gSW1tZWRpYXRlbHkgcmVtb3ZlIHRoZSBmaXJzdCByb3dcblx0XHQgKiAgICAgIG9UYWJsZS5mbkRlbGV0ZVJvdyggMCApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHR0aGlzLmZuRGVsZXRlUm93ID0gZnVuY3Rpb24oIHRhcmdldCwgY2FsbGJhY2ssIHJlZHJhdyApXG5cdFx0e1xuXHRcdFx0dmFyIGFwaSA9IHRoaXMuYXBpKCB0cnVlICk7XG5cdFx0XHR2YXIgcm93cyA9IGFwaS5yb3dzKCB0YXJnZXQgKTtcblx0XHRcdHZhciBzZXR0aW5ncyA9IHJvd3Muc2V0dGluZ3MoKVswXTtcblx0XHRcdHZhciBkYXRhID0gc2V0dGluZ3MuYW9EYXRhWyByb3dzWzBdWzBdIF07XG5cdFx0XG5cdFx0XHRyb3dzLnJlbW92ZSgpO1xuXHRcdFxuXHRcdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdFx0Y2FsbGJhY2suY2FsbCggdGhpcywgc2V0dGluZ3MsIGRhdGEgKTtcblx0XHRcdH1cblx0XHRcblx0XHRcdGlmICggcmVkcmF3ID09PSB1bmRlZmluZWQgfHwgcmVkcmF3ICkge1xuXHRcdFx0XHRhcGkuZHJhdygpO1xuXHRcdFx0fVxuXHRcdFxuXHRcdFx0cmV0dXJuIGRhdGE7XG5cdFx0fTtcblx0XHRcblx0XHRcblx0XHQvKipcblx0XHQgKiBSZXN0b3JlIHRoZSB0YWJsZSB0byBpdCdzIG9yaWdpbmFsIHN0YXRlIGluIHRoZSBET00gYnkgcmVtb3ZpbmcgYWxsIG9mIERhdGFUYWJsZXNcblx0XHQgKiBlbmhhbmNlbWVudHMsIGFsdGVyYXRpb25zIHRvIHRoZSBET00gc3RydWN0dXJlIG9mIHRoZSB0YWJsZSBhbmQgZXZlbnQgbGlzdGVuZXJzLlxuXHRcdCAqICBAcGFyYW0ge2Jvb2xlYW59IFtyZW1vdmU9ZmFsc2VdIENvbXBsZXRlbHkgcmVtb3ZlIHRoZSB0YWJsZSBmcm9tIHRoZSBET01cblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAvLyBUaGlzIGV4YW1wbGUgaXMgZmFpcmx5IHBvaW50bGVzcyBpbiByZWFsaXR5LCBidXQgc2hvd3MgaG93IGZuRGVzdHJveSBjYW4gYmUgdXNlZFxuXHRcdCAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7XG5cdFx0ICogICAgICBvVGFibGUuZm5EZXN0cm95KCk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdHRoaXMuZm5EZXN0cm95ID0gZnVuY3Rpb24gKCByZW1vdmUgKVxuXHRcdHtcblx0XHRcdHRoaXMuYXBpKCB0cnVlICkuZGVzdHJveSggcmVtb3ZlICk7XG5cdFx0fTtcblx0XHRcblx0XHRcblx0XHQvKipcblx0XHQgKiBSZWRyYXcgdGhlIHRhYmxlXG5cdFx0ICogIEBwYXJhbSB7Ym9vbH0gW2NvbXBsZXRlPXRydWVdIFJlLWZpbHRlciBhbmQgcmVzb3J0IChpZiBlbmFibGVkKSB0aGUgdGFibGUgYmVmb3JlIHRoZSBkcmF3LlxuXHRcdCAqICBAZHRvcHQgQVBJXG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHRcdCAqXG5cdFx0ICogICAgICAvLyBSZS1kcmF3IHRoZSB0YWJsZSAtIHlvdSB3b3VsZG4ndCB3YW50IHRvIGRvIGl0IGhlcmUsIGJ1dCBpdCdzIGFuIGV4YW1wbGUgOi0pXG5cdFx0ICogICAgICBvVGFibGUuZm5EcmF3KCk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdHRoaXMuZm5EcmF3ID0gZnVuY3Rpb24oIGNvbXBsZXRlIClcblx0XHR7XG5cdFx0XHQvLyBOb3RlIHRoYXQgdGhpcyBpc24ndCBhbiBleGFjdCBtYXRjaCB0byB0aGUgb2xkIGNhbGwgdG8gX2ZuRHJhdyAtIGl0IHRha2VzXG5cdFx0XHQvLyBpbnRvIGFjY291bnQgdGhlIG5ldyBkYXRhLCBidXQgY2FuIGhvbGQgcG9zaXRpb24uXG5cdFx0XHR0aGlzLmFwaSggdHJ1ZSApLmRyYXcoIGNvbXBsZXRlICk7XG5cdFx0fTtcblx0XHRcblx0XHRcblx0XHQvKipcblx0XHQgKiBGaWx0ZXIgdGhlIGlucHV0IGJhc2VkIG9uIGRhdGFcblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd9IHNJbnB1dCBTdHJpbmcgdG8gZmlsdGVyIHRoZSB0YWJsZSBvblxuXHRcdCAqICBAcGFyYW0ge2ludHxudWxsfSBbaUNvbHVtbl0gQ29sdW1uIHRvIGxpbWl0IGZpbHRlcmluZyB0b1xuXHRcdCAqICBAcGFyYW0ge2Jvb2x9IFtiUmVnZXg9ZmFsc2VdIFRyZWF0IGFzIHJlZ3VsYXIgZXhwcmVzc2lvbiBvciBub3Rcblx0XHQgKiAgQHBhcmFtIHtib29sfSBbYlNtYXJ0PXRydWVdIFBlcmZvcm0gc21hcnQgZmlsdGVyaW5nIG9yIG5vdFxuXHRcdCAqICBAcGFyYW0ge2Jvb2x9IFtiU2hvd0dsb2JhbD10cnVlXSBTaG93IHRoZSBpbnB1dCBnbG9iYWwgZmlsdGVyIGluIGl0J3MgaW5wdXQgYm94KGVzKVxuXHRcdCAqICBAcGFyYW0ge2Jvb2x9IFtiQ2FzZUluc2Vuc2l0aXZlPXRydWVdIERvIGNhc2UtaW5zZW5zaXRpdmUgbWF0Y2hpbmcgKHRydWUpIG9yIG5vdCAoZmFsc2UpXG5cdFx0ICogIEBkdG9wdCBBUElcblx0XHQgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTBcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vIFNvbWV0aW1lIGxhdGVyIC0gZmlsdGVyLi4uXG5cdFx0ICogICAgICBvVGFibGUuZm5GaWx0ZXIoICd0ZXN0IHN0cmluZycgKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0dGhpcy5mbkZpbHRlciA9IGZ1bmN0aW9uKCBzSW5wdXQsIGlDb2x1bW4sIGJSZWdleCwgYlNtYXJ0LCBiU2hvd0dsb2JhbCwgYkNhc2VJbnNlbnNpdGl2ZSApXG5cdFx0e1xuXHRcdFx0dmFyIGFwaSA9IHRoaXMuYXBpKCB0cnVlICk7XG5cdFx0XG5cdFx0XHRpZiAoIGlDb2x1bW4gPT09IG51bGwgfHwgaUNvbHVtbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRhcGkuc2VhcmNoKCBzSW5wdXQsIGJSZWdleCwgYlNtYXJ0LCBiQ2FzZUluc2Vuc2l0aXZlICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0YXBpLmNvbHVtbiggaUNvbHVtbiApLnNlYXJjaCggc0lucHV0LCBiUmVnZXgsIGJTbWFydCwgYkNhc2VJbnNlbnNpdGl2ZSApO1xuXHRcdFx0fVxuXHRcdFxuXHRcdFx0YXBpLmRyYXcoKTtcblx0XHR9O1xuXHRcdFxuXHRcdFxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgZGF0YSBmb3IgdGhlIHdob2xlIHRhYmxlLCBhbiBpbmRpdmlkdWFsIHJvdyBvciBhbiBpbmRpdmlkdWFsIGNlbGwgYmFzZWQgb24gdGhlXG5cdFx0ICogcHJvdmlkZWQgcGFyYW1ldGVycy5cblx0XHQgKiAgQHBhcmFtIHtpbnR8bm9kZX0gW3NyY10gQSBUUiByb3cgbm9kZSwgVEQvVEggY2VsbCBub2RlIG9yIGFuIGludGVnZXIuIElmIGdpdmVuIGFzXG5cdFx0ICogICAgYSBUUiBub2RlIHRoZW4gdGhlIGRhdGEgc291cmNlIGZvciB0aGUgd2hvbGUgcm93IHdpbGwgYmUgcmV0dXJuZWQuIElmIGdpdmVuIGFzIGFcblx0XHQgKiAgICBURC9USCBjZWxsIG5vZGUgdGhlbiBpQ29sIHdpbGwgYmUgYXV0b21hdGljYWxseSBjYWxjdWxhdGVkIGFuZCB0aGUgZGF0YSBmb3IgdGhlXG5cdFx0ICogICAgY2VsbCByZXR1cm5lZC4gSWYgZ2l2ZW4gYXMgYW4gaW50ZWdlciwgdGhlbiB0aGlzIGlzIHRyZWF0ZWQgYXMgdGhlIGFvRGF0YSBpbnRlcm5hbFxuXHRcdCAqICAgIGRhdGEgaW5kZXggZm9yIHRoZSByb3cgKHNlZSBmbkdldFBvc2l0aW9uKSBhbmQgdGhlIGRhdGEgZm9yIHRoYXQgcm93IHVzZWQuXG5cdFx0ICogIEBwYXJhbSB7aW50fSBbY29sXSBPcHRpb25hbCBjb2x1bW4gaW5kZXggdGhhdCB5b3Ugd2FudCB0aGUgZGF0YSBvZi5cblx0XHQgKiAgQHJldHVybnMge2FycmF5fG9iamVjdHxzdHJpbmd9IElmIG1Sb3cgaXMgdW5kZWZpbmVkLCB0aGVuIHRoZSBkYXRhIGZvciBhbGwgcm93cyBpc1xuXHRcdCAqICAgIHJldHVybmVkLiBJZiBtUm93IGlzIGRlZmluZWQsIGp1c3QgZGF0YSBmb3IgdGhhdCByb3csIGFuZCBpcyBpQ29sIGlzXG5cdFx0ICogICAgZGVmaW5lZCwgb25seSBkYXRhIGZvciB0aGUgZGVzaWduYXRlZCBjZWxsIGlzIHJldHVybmVkLlxuXHRcdCAqICBAZHRvcHQgQVBJXG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBSb3cgZGF0YVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0XHQgKlxuXHRcdCAqICAgICAgb1RhYmxlLiQoJ3RyJykuY2xpY2soIGZ1bmN0aW9uICgpIHtcblx0XHQgKiAgICAgICAgdmFyIGRhdGEgPSBvVGFibGUuZm5HZXREYXRhKCB0aGlzICk7XG5cdFx0ICogICAgICAgIC8vIC4uLiBkbyBzb21ldGhpbmcgd2l0aCB0aGUgYXJyYXkgLyBvYmplY3Qgb2YgZGF0YSBmb3IgdGhlIHJvd1xuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIEluZGl2aWR1YWwgY2VsbCBkYXRhXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHRcdCAqXG5cdFx0ICogICAgICBvVGFibGUuJCgndGQnKS5jbGljayggZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgICB2YXIgc0RhdGEgPSBvVGFibGUuZm5HZXREYXRhKCB0aGlzICk7XG5cdFx0ICogICAgICAgIGFsZXJ0KCAnVGhlIGNlbGwgY2xpY2tlZCBvbiBoYWQgdGhlIHZhbHVlIG9mICcrc0RhdGEgKTtcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0dGhpcy5mbkdldERhdGEgPSBmdW5jdGlvbiggc3JjLCBjb2wgKVxuXHRcdHtcblx0XHRcdHZhciBhcGkgPSB0aGlzLmFwaSggdHJ1ZSApO1xuXHRcdFxuXHRcdFx0aWYgKCBzcmMgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0dmFyIHR5cGUgPSBzcmMubm9kZU5hbWUgPyBzcmMubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA6ICcnO1xuXHRcdFxuXHRcdFx0XHRyZXR1cm4gY29sICE9PSB1bmRlZmluZWQgfHwgdHlwZSA9PSAndGQnIHx8IHR5cGUgPT0gJ3RoJyA/XG5cdFx0XHRcdFx0YXBpLmNlbGwoIHNyYywgY29sICkuZGF0YSgpIDpcblx0XHRcdFx0XHRhcGkucm93KCBzcmMgKS5kYXRhKCkgfHwgbnVsbDtcblx0XHRcdH1cblx0XHRcblx0XHRcdHJldHVybiBhcGkuZGF0YSgpLnRvQXJyYXkoKTtcblx0XHR9O1xuXHRcdFxuXHRcdFxuXHRcdC8qKlxuXHRcdCAqIEdldCBhbiBhcnJheSBvZiB0aGUgVFIgbm9kZXMgdGhhdCBhcmUgdXNlZCBpbiB0aGUgdGFibGUncyBib2R5LiBOb3RlIHRoYXQgeW91IHdpbGxcblx0XHQgKiB0eXBpY2FsbHkgd2FudCB0byB1c2UgdGhlICckJyBBUEkgbWV0aG9kIGluIHByZWZlcmVuY2UgdG8gdGhpcyBhcyBpdCBpcyBtb3JlXG5cdFx0ICogZmxleGlibGUuXG5cdFx0ICogIEBwYXJhbSB7aW50fSBbaVJvd10gT3B0aW9uYWwgcm93IGluZGV4IGZvciB0aGUgVFIgZWxlbWVudCB5b3Ugd2FudFxuXHRcdCAqICBAcmV0dXJucyB7YXJyYXl8bm9kZX0gSWYgaVJvdyBpcyB1bmRlZmluZWQsIHJldHVybnMgYW4gYXJyYXkgb2YgYWxsIFRSIGVsZW1lbnRzXG5cdFx0ICogICAgaW4gdGhlIHRhYmxlJ3MgYm9keSwgb3IgaVJvdyBpcyBkZWZpbmVkLCBqdXN0IHRoZSBUUiBlbGVtZW50IHJlcXVlc3RlZC5cblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0XHQgKlxuXHRcdCAqICAgICAgLy8gR2V0IHRoZSBub2RlcyBmcm9tIHRoZSB0YWJsZVxuXHRcdCAqICAgICAgdmFyIG5Ob2RlcyA9IG9UYWJsZS5mbkdldE5vZGVzKCApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHR0aGlzLmZuR2V0Tm9kZXMgPSBmdW5jdGlvbiggaVJvdyApXG5cdFx0e1xuXHRcdFx0dmFyIGFwaSA9IHRoaXMuYXBpKCB0cnVlICk7XG5cdFx0XG5cdFx0XHRyZXR1cm4gaVJvdyAhPT0gdW5kZWZpbmVkID9cblx0XHRcdFx0YXBpLnJvdyggaVJvdyApLm5vZGUoKSA6XG5cdFx0XHRcdGFwaS5yb3dzKCkubm9kZXMoKS5mbGF0dGVuKCkudG9BcnJheSgpO1xuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSBhcnJheSBpbmRleGVzIG9mIGEgcGFydGljdWxhciBjZWxsIGZyb20gaXQncyBET00gZWxlbWVudFxuXHRcdCAqIGFuZCBjb2x1bW4gaW5kZXggaW5jbHVkaW5nIGhpZGRlbiBjb2x1bW5zXG5cdFx0ICogIEBwYXJhbSB7bm9kZX0gbm9kZSB0aGlzIGNhbiBlaXRoZXIgYmUgYSBUUiwgVEQgb3IgVEggaW4gdGhlIHRhYmxlJ3MgYm9keVxuXHRcdCAqICBAcmV0dXJucyB7aW50fSBJZiBuTm9kZSBpcyBnaXZlbiBhcyBhIFRSLCB0aGVuIGEgc2luZ2xlIGluZGV4IGlzIHJldHVybmVkLCBvclxuXHRcdCAqICAgIGlmIGdpdmVuIGFzIGEgY2VsbCwgYW4gYXJyYXkgb2YgW3JvdyBpbmRleCwgY29sdW1uIGluZGV4ICh2aXNpYmxlKSxcblx0XHQgKiAgICBjb2x1bW4gaW5kZXggKGFsbCldIGlzIGdpdmVuLlxuXHRcdCAqICBAZHRvcHQgQVBJXG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlIHRib2R5IHRkJykuY2xpY2soIGZ1bmN0aW9uICgpIHtcblx0XHQgKiAgICAgICAgLy8gR2V0IHRoZSBwb3NpdGlvbiBvZiB0aGUgY3VycmVudCBkYXRhIGZyb20gdGhlIG5vZGVcblx0XHQgKiAgICAgICAgdmFyIGFQb3MgPSBvVGFibGUuZm5HZXRQb3NpdGlvbiggdGhpcyApO1xuXHRcdCAqXG5cdFx0ICogICAgICAgIC8vIEdldCB0aGUgZGF0YSBhcnJheSBmb3IgdGhpcyByb3dcblx0XHQgKiAgICAgICAgdmFyIGFEYXRhID0gb1RhYmxlLmZuR2V0RGF0YSggYVBvc1swXSApO1xuXHRcdCAqXG5cdFx0ICogICAgICAgIC8vIFVwZGF0ZSB0aGUgZGF0YSBhcnJheSBhbmQgcmV0dXJuIHRoZSB2YWx1ZVxuXHRcdCAqICAgICAgICBhRGF0YVsgYVBvc1sxXSBdID0gJ2NsaWNrZWQnO1xuXHRcdCAqICAgICAgICB0aGlzLmlubmVySFRNTCA9ICdjbGlja2VkJztcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICAgICAgLy8gSW5pdCBEYXRhVGFibGVzXG5cdFx0ICogICAgICBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHR0aGlzLmZuR2V0UG9zaXRpb24gPSBmdW5jdGlvbiggbm9kZSApXG5cdFx0e1xuXHRcdFx0dmFyIGFwaSA9IHRoaXMuYXBpKCB0cnVlICk7XG5cdFx0XHR2YXIgbm9kZU5hbWUgPSBub2RlLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCk7XG5cdFx0XG5cdFx0XHRpZiAoIG5vZGVOYW1lID09ICdUUicgKSB7XG5cdFx0XHRcdHJldHVybiBhcGkucm93KCBub2RlICkuaW5kZXgoKTtcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKCBub2RlTmFtZSA9PSAnVEQnIHx8IG5vZGVOYW1lID09ICdUSCcgKSB7XG5cdFx0XHRcdHZhciBjZWxsID0gYXBpLmNlbGwoIG5vZGUgKS5pbmRleCgpO1xuXHRcdFxuXHRcdFx0XHRyZXR1cm4gW1xuXHRcdFx0XHRcdGNlbGwucm93LFxuXHRcdFx0XHRcdGNlbGwuY29sdW1uVmlzaWJsZSxcblx0XHRcdFx0XHRjZWxsLmNvbHVtblxuXHRcdFx0XHRdO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fTtcblx0XHRcblx0XHRcblx0XHQvKipcblx0XHQgKiBDaGVjayB0byBzZWUgaWYgYSByb3cgaXMgJ29wZW4nIG9yIG5vdC5cblx0XHQgKiAgQHBhcmFtIHtub2RlfSBuVHIgdGhlIHRhYmxlIHJvdyB0byBjaGVja1xuXHRcdCAqICBAcmV0dXJucyB7Ym9vbGVhbn0gdHJ1ZSBpZiB0aGUgcm93IGlzIGN1cnJlbnRseSBvcGVuLCBmYWxzZSBvdGhlcndpc2Vcblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICB2YXIgb1RhYmxlO1xuXHRcdCAqXG5cdFx0ICogICAgICAvLyAnb3BlbicgYW4gaW5mb3JtYXRpb24gcm93IHdoZW4gYSByb3cgaXMgY2xpY2tlZCBvblxuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUgdGJvZHkgdHInKS5jbGljayggZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgICBpZiAoIG9UYWJsZS5mbklzT3Blbih0aGlzKSApIHtcblx0XHQgKiAgICAgICAgICBvVGFibGUuZm5DbG9zZSggdGhpcyApO1xuXHRcdCAqICAgICAgICB9IGVsc2Uge1xuXHRcdCAqICAgICAgICAgIG9UYWJsZS5mbk9wZW4oIHRoaXMsIFwiVGVtcG9yYXJ5IHJvdyBvcGVuZWRcIiwgXCJpbmZvX3Jvd1wiICk7XG5cdFx0ICogICAgICAgIH1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICAgICAgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0dGhpcy5mbklzT3BlbiA9IGZ1bmN0aW9uKCBuVHIgKVxuXHRcdHtcblx0XHRcdHJldHVybiB0aGlzLmFwaSggdHJ1ZSApLnJvdyggblRyICkuY2hpbGQuaXNTaG93bigpO1xuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogVGhpcyBmdW5jdGlvbiB3aWxsIHBsYWNlIGEgbmV3IHJvdyBkaXJlY3RseSBhZnRlciBhIHJvdyB3aGljaCBpcyBjdXJyZW50bHlcblx0XHQgKiBvbiBkaXNwbGF5IG9uIHRoZSBwYWdlLCB3aXRoIHRoZSBIVE1MIGNvbnRlbnRzIHRoYXQgaXMgcGFzc2VkIGludG8gdGhlXG5cdFx0ICogZnVuY3Rpb24uIFRoaXMgY2FuIGJlIHVzZWQsIGZvciBleGFtcGxlLCB0byBhc2sgZm9yIGNvbmZpcm1hdGlvbiB0aGF0IGFcblx0XHQgKiBwYXJ0aWN1bGFyIHJlY29yZCBzaG91bGQgYmUgZGVsZXRlZC5cblx0XHQgKiAgQHBhcmFtIHtub2RlfSBuVHIgVGhlIHRhYmxlIHJvdyB0byAnb3Blbidcblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd8bm9kZXxqUXVlcnl9IG1IdG1sIFRoZSBIVE1MIHRvIHB1dCBpbnRvIHRoZSByb3dcblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd9IHNDbGFzcyBDbGFzcyB0byBnaXZlIHRoZSBuZXcgVEQgY2VsbFxuXHRcdCAqICBAcmV0dXJucyB7bm9kZX0gVGhlIHJvdyBvcGVuZWQuIE5vdGUgdGhhdCBpZiB0aGUgdGFibGUgcm93IHBhc3NlZCBpbiBhcyB0aGVcblx0XHQgKiAgICBmaXJzdCBwYXJhbWV0ZXIsIGlzIG5vdCBmb3VuZCBpbiB0aGUgdGFibGUsIHRoaXMgbWV0aG9kIHdpbGwgc2lsZW50bHlcblx0XHQgKiAgICByZXR1cm4uXG5cdFx0ICogIEBkdG9wdCBBUElcblx0XHQgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTBcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgdmFyIG9UYWJsZTtcblx0XHQgKlxuXHRcdCAqICAgICAgLy8gJ29wZW4nIGFuIGluZm9ybWF0aW9uIHJvdyB3aGVuIGEgcm93IGlzIGNsaWNrZWQgb25cblx0XHQgKiAgICAgICQoJyNleGFtcGxlIHRib2R5IHRyJykuY2xpY2soIGZ1bmN0aW9uICgpIHtcblx0XHQgKiAgICAgICAgaWYgKCBvVGFibGUuZm5Jc09wZW4odGhpcykgKSB7XG5cdFx0ICogICAgICAgICAgb1RhYmxlLmZuQ2xvc2UoIHRoaXMgKTtcblx0XHQgKiAgICAgICAgfSBlbHNlIHtcblx0XHQgKiAgICAgICAgICBvVGFibGUuZm5PcGVuKCB0aGlzLCBcIlRlbXBvcmFyeSByb3cgb3BlbmVkXCIsIFwiaW5mb19yb3dcIiApO1xuXHRcdCAqICAgICAgICB9XG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgICAgIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdHRoaXMuZm5PcGVuID0gZnVuY3Rpb24oIG5UciwgbUh0bWwsIHNDbGFzcyApXG5cdFx0e1xuXHRcdFx0cmV0dXJuIHRoaXMuYXBpKCB0cnVlIClcblx0XHRcdFx0LnJvdyggblRyIClcblx0XHRcdFx0LmNoaWxkKCBtSHRtbCwgc0NsYXNzIClcblx0XHRcdFx0LnNob3coKVxuXHRcdFx0XHQuY2hpbGQoKVswXTtcblx0XHR9O1xuXHRcdFxuXHRcdFxuXHRcdC8qKlxuXHRcdCAqIENoYW5nZSB0aGUgcGFnaW5hdGlvbiAtIHByb3ZpZGVzIHRoZSBpbnRlcm5hbCBsb2dpYyBmb3IgcGFnaW5hdGlvbiBpbiBhIHNpbXBsZSBBUElcblx0XHQgKiBmdW5jdGlvbi4gV2l0aCB0aGlzIGZ1bmN0aW9uIHlvdSBjYW4gaGF2ZSBhIERhdGFUYWJsZXMgdGFibGUgZ28gdG8gdGhlIG5leHQsXG5cdFx0ICogcHJldmlvdXMsIGZpcnN0IG9yIGxhc3QgcGFnZXMuXG5cdFx0ICogIEBwYXJhbSB7c3RyaW5nfGludH0gbUFjdGlvbiBQYWdpbmcgYWN0aW9uIHRvIHRha2U6IFwiZmlyc3RcIiwgXCJwcmV2aW91c1wiLCBcIm5leHRcIiBvciBcImxhc3RcIlxuXHRcdCAqICAgIG9yIHBhZ2UgbnVtYmVyIHRvIGp1bXAgdG8gKGludGVnZXIpLCBub3RlIHRoYXQgcGFnZSAwIGlzIHRoZSBmaXJzdCBwYWdlLlxuXHRcdCAqICBAcGFyYW0ge2Jvb2x9IFtiUmVkcmF3PXRydWVdIFJlZHJhdyB0aGUgdGFibGUgb3Igbm90XG5cdFx0ICogIEBkdG9wdCBBUElcblx0XHQgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTBcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7XG5cdFx0ICogICAgICBvVGFibGUuZm5QYWdlQ2hhbmdlKCAnbmV4dCcgKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0dGhpcy5mblBhZ2VDaGFuZ2UgPSBmdW5jdGlvbiAoIG1BY3Rpb24sIGJSZWRyYXcgKVxuXHRcdHtcblx0XHRcdHZhciBhcGkgPSB0aGlzLmFwaSggdHJ1ZSApLnBhZ2UoIG1BY3Rpb24gKTtcblx0XHRcblx0XHRcdGlmICggYlJlZHJhdyA9PT0gdW5kZWZpbmVkIHx8IGJSZWRyYXcgKSB7XG5cdFx0XHRcdGFwaS5kcmF3KGZhbHNlKTtcblx0XHRcdH1cblx0XHR9O1xuXHRcdFxuXHRcdFxuXHRcdC8qKlxuXHRcdCAqIFNob3cgYSBwYXJ0aWN1bGFyIGNvbHVtblxuXHRcdCAqICBAcGFyYW0ge2ludH0gaUNvbCBUaGUgY29sdW1uIHdob3NlIGRpc3BsYXkgc2hvdWxkIGJlIGNoYW5nZWRcblx0XHQgKiAgQHBhcmFtIHtib29sfSBiU2hvdyBTaG93ICh0cnVlKSBvciBoaWRlIChmYWxzZSkgdGhlIGNvbHVtblxuXHRcdCAqICBAcGFyYW0ge2Jvb2x9IFtiUmVkcmF3PXRydWVdIFJlZHJhdyB0aGUgdGFibGUgb3Igbm90XG5cdFx0ICogIEBkdG9wdCBBUElcblx0XHQgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTBcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgdmFyIG9UYWJsZSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCk7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vIEhpZGUgdGhlIHNlY29uZCBjb2x1bW4gYWZ0ZXIgaW5pdGlhbGlzYXRpb25cblx0XHQgKiAgICAgIG9UYWJsZS5mblNldENvbHVtblZpcyggMSwgZmFsc2UgKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0dGhpcy5mblNldENvbHVtblZpcyA9IGZ1bmN0aW9uICggaUNvbCwgYlNob3csIGJSZWRyYXcgKVxuXHRcdHtcblx0XHRcdHZhciBhcGkgPSB0aGlzLmFwaSggdHJ1ZSApLmNvbHVtbiggaUNvbCApLnZpc2libGUoIGJTaG93ICk7XG5cdFx0XG5cdFx0XHRpZiAoIGJSZWRyYXcgPT09IHVuZGVmaW5lZCB8fCBiUmVkcmF3ICkge1xuXHRcdFx0XHRhcGkuY29sdW1ucy5hZGp1c3QoKS5kcmF3KCk7XG5cdFx0XHR9XG5cdFx0fTtcblx0XHRcblx0XHRcblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIHNldHRpbmdzIGZvciBhIHBhcnRpY3VsYXIgdGFibGUgZm9yIGV4dGVybmFsIG1hbmlwdWxhdGlvblxuXHRcdCAqICBAcmV0dXJucyB7b2JqZWN0fSBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdC4gU2VlXG5cdFx0ICogICAge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfVxuXHRcdCAqICBAZHRvcHQgQVBJXG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHRcdCAqICAgICAgdmFyIG9TZXR0aW5ncyA9IG9UYWJsZS5mblNldHRpbmdzKCk7XG5cdFx0ICpcblx0XHQgKiAgICAgIC8vIFNob3cgYW4gZXhhbXBsZSBwYXJhbWV0ZXIgZnJvbSB0aGUgc2V0dGluZ3Ncblx0XHQgKiAgICAgIGFsZXJ0KCBvU2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0dGhpcy5mblNldHRpbmdzID0gZnVuY3Rpb24oKVxuXHRcdHtcblx0XHRcdHJldHVybiBfZm5TZXR0aW5nc0Zyb21Ob2RlKCB0aGlzW19leHQuaUFwaUluZGV4XSApO1xuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogU29ydCB0aGUgdGFibGUgYnkgYSBwYXJ0aWN1bGFyIGNvbHVtblxuXHRcdCAqICBAcGFyYW0ge2ludH0gaUNvbCB0aGUgZGF0YSBpbmRleCB0byBzb3J0IG9uLiBOb3RlIHRoYXQgdGhpcyB3aWxsIG5vdCBtYXRjaCB0aGVcblx0XHQgKiAgICAnZGlzcGxheSBpbmRleCcgaWYgeW91IGhhdmUgaGlkZGVuIGRhdGEgZW50cmllc1xuXHRcdCAqICBAZHRvcHQgQVBJXG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHRcdCAqXG5cdFx0ICogICAgICAvLyBTb3J0IGltbWVkaWF0ZWx5IHdpdGggY29sdW1ucyAwIGFuZCAxXG5cdFx0ICogICAgICBvVGFibGUuZm5Tb3J0KCBbIFswLCdhc2MnXSwgWzEsJ2FzYyddIF0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0dGhpcy5mblNvcnQgPSBmdW5jdGlvbiggYWFTb3J0IClcblx0XHR7XG5cdFx0XHR0aGlzLmFwaSggdHJ1ZSApLm9yZGVyKCBhYVNvcnQgKS5kcmF3KCk7XG5cdFx0fTtcblx0XHRcblx0XHRcblx0XHQvKipcblx0XHQgKiBBdHRhY2ggYSBzb3J0IGxpc3RlbmVyIHRvIGFuIGVsZW1lbnQgZm9yIGEgZ2l2ZW4gY29sdW1uXG5cdFx0ICogIEBwYXJhbSB7bm9kZX0gbk5vZGUgdGhlIGVsZW1lbnQgdG8gYXR0YWNoIHRoZSBzb3J0IGxpc3RlbmVyIHRvXG5cdFx0ICogIEBwYXJhbSB7aW50fSBpQ29sdW1uIHRoZSBjb2x1bW4gdGhhdCBhIGNsaWNrIG9uIHRoaXMgbm9kZSB3aWxsIHNvcnQgb25cblx0XHQgKiAgQHBhcmFtIHtmdW5jdGlvbn0gW2ZuQ2FsbGJhY2tdIGNhbGxiYWNrIGZ1bmN0aW9uIHdoZW4gc29ydCBpcyBydW5cblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0XHQgKlxuXHRcdCAqICAgICAgLy8gU29ydCBvbiBjb2x1bW4gMSwgd2hlbiAnc29ydGVyJyBpcyBjbGlja2VkIG9uXG5cdFx0ICogICAgICBvVGFibGUuZm5Tb3J0TGlzdGVuZXIoIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdzb3J0ZXInKSwgMSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHR0aGlzLmZuU29ydExpc3RlbmVyID0gZnVuY3Rpb24oIG5Ob2RlLCBpQ29sdW1uLCBmbkNhbGxiYWNrIClcblx0XHR7XG5cdFx0XHR0aGlzLmFwaSggdHJ1ZSApLm9yZGVyLmxpc3RlbmVyKCBuTm9kZSwgaUNvbHVtbiwgZm5DYWxsYmFjayApO1xuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogVXBkYXRlIGEgdGFibGUgY2VsbCBvciByb3cgLSB0aGlzIG1ldGhvZCB3aWxsIGFjY2VwdCBlaXRoZXIgYSBzaW5nbGUgdmFsdWUgdG9cblx0XHQgKiB1cGRhdGUgdGhlIGNlbGwgd2l0aCwgYW4gYXJyYXkgb2YgdmFsdWVzIHdpdGggb25lIGVsZW1lbnQgZm9yIGVhY2ggY29sdW1uIG9yXG5cdFx0ICogYW4gb2JqZWN0IGluIHRoZSBzYW1lIGZvcm1hdCBhcyB0aGUgb3JpZ2luYWwgZGF0YSBzb3VyY2UuIFRoZSBmdW5jdGlvbiBpc1xuXHRcdCAqIHNlbGYtcmVmZXJlbmNpbmcgaW4gb3JkZXIgdG8gbWFrZSB0aGUgbXVsdGkgY29sdW1uIHVwZGF0ZXMgZWFzaWVyLlxuXHRcdCAqICBAcGFyYW0ge29iamVjdHxhcnJheXxzdHJpbmd9IG1EYXRhIERhdGEgdG8gdXBkYXRlIHRoZSBjZWxsL3JvdyB3aXRoXG5cdFx0ICogIEBwYXJhbSB7bm9kZXxpbnR9IG1Sb3cgVFIgZWxlbWVudCB5b3Ugd2FudCB0byB1cGRhdGUgb3IgdGhlIGFvRGF0YSBpbmRleFxuXHRcdCAqICBAcGFyYW0ge2ludH0gW2lDb2x1bW5dIFRoZSBjb2x1bW4gdG8gdXBkYXRlLCBnaXZlIGFzIG51bGwgb3IgdW5kZWZpbmVkIHRvXG5cdFx0ICogICAgdXBkYXRlIGEgd2hvbGUgcm93LlxuXHRcdCAqICBAcGFyYW0ge2Jvb2x9IFtiUmVkcmF3PXRydWVdIFJlZHJhdyB0aGUgdGFibGUgb3Igbm90XG5cdFx0ICogIEBwYXJhbSB7Ym9vbH0gW2JBY3Rpb249dHJ1ZV0gUGVyZm9ybSBwcmUtZHJhdyBhY3Rpb25zIG9yIG5vdFxuXHRcdCAqICBAcmV0dXJucyB7aW50fSAwIG9uIHN1Y2Nlc3MsIDEgb24gZXJyb3Jcblx0XHQgKiAgQGR0b3B0IEFQSVxuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICB2YXIgb1RhYmxlID0gJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoKTtcblx0XHQgKiAgICAgIG9UYWJsZS5mblVwZGF0ZSggJ0V4YW1wbGUgdXBkYXRlJywgMCwgMCApOyAvLyBTaW5nbGUgY2VsbFxuXHRcdCAqICAgICAgb1RhYmxlLmZuVXBkYXRlKCBbJ2EnLCAnYicsICdjJywgJ2QnLCAnZSddLCAkKCd0Ym9keSB0cicpWzBdICk7IC8vIFJvd1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHR0aGlzLmZuVXBkYXRlID0gZnVuY3Rpb24oIG1EYXRhLCBtUm93LCBpQ29sdW1uLCBiUmVkcmF3LCBiQWN0aW9uIClcblx0XHR7XG5cdFx0XHR2YXIgYXBpID0gdGhpcy5hcGkoIHRydWUgKTtcblx0XHRcblx0XHRcdGlmICggaUNvbHVtbiA9PT0gdW5kZWZpbmVkIHx8IGlDb2x1bW4gPT09IG51bGwgKSB7XG5cdFx0XHRcdGFwaS5yb3coIG1Sb3cgKS5kYXRhKCBtRGF0YSApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGFwaS5jZWxsKCBtUm93LCBpQ29sdW1uICkuZGF0YSggbURhdGEgKTtcblx0XHRcdH1cblx0XHRcblx0XHRcdGlmICggYkFjdGlvbiA9PT0gdW5kZWZpbmVkIHx8IGJBY3Rpb24gKSB7XG5cdFx0XHRcdGFwaS5jb2x1bW5zLmFkanVzdCgpO1xuXHRcdFx0fVxuXHRcdFxuXHRcdFx0aWYgKCBiUmVkcmF3ID09PSB1bmRlZmluZWQgfHwgYlJlZHJhdyApIHtcblx0XHRcdFx0YXBpLmRyYXcoKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiAwO1xuXHRcdH07XG5cdFx0XG5cdFx0XG5cdFx0LyoqXG5cdFx0ICogUHJvdmlkZSBhIGNvbW1vbiBtZXRob2QgZm9yIHBsdWctaW5zIHRvIGNoZWNrIHRoZSB2ZXJzaW9uIG9mIERhdGFUYWJsZXMgYmVpbmcgdXNlZCwgaW4gb3JkZXJcblx0XHQgKiB0byBlbnN1cmUgY29tcGF0aWJpbGl0eS5cblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd9IHNWZXJzaW9uIFZlcnNpb24gc3RyaW5nIHRvIGNoZWNrIGZvciwgaW4gdGhlIGZvcm1hdCBcIlguWS5aXCIuIE5vdGUgdGhhdCB0aGVcblx0XHQgKiAgICBmb3JtYXRzIFwiWFwiIGFuZCBcIlguWVwiIGFyZSBhbHNvIGFjY2VwdGFibGUuXG5cdFx0ICogIEByZXR1cm5zIHtib29sZWFufSB0cnVlIGlmIHRoaXMgdmVyc2lvbiBvZiBEYXRhVGFibGVzIGlzIGdyZWF0ZXIgb3IgZXF1YWwgdG8gdGhlIHJlcXVpcmVkXG5cdFx0ICogICAgdmVyc2lvbiwgb3IgZmFsc2UgaWYgdGhpcyB2ZXJzaW9uIG9mIERhdGFUYWxlcyBpcyBub3Qgc3VpdGFibGVcblx0XHQgKiAgQG1ldGhvZFxuXHRcdCAqICBAZHRvcHQgQVBJXG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeShmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgIHZhciBvVGFibGUgPSAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHRcdCAqICAgICAgYWxlcnQoIG9UYWJsZS5mblZlcnNpb25DaGVjayggJzEuOS4wJyApICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdHRoaXMuZm5WZXJzaW9uQ2hlY2sgPSBfZXh0LmZuVmVyc2lvbkNoZWNrO1xuXHRcdFxuXG5cdFx0dmFyIF90aGF0ID0gdGhpcztcblx0XHR2YXIgZW1wdHlJbml0ID0gb3B0aW9ucyA9PT0gdW5kZWZpbmVkO1xuXHRcdHZhciBsZW4gPSB0aGlzLmxlbmd0aDtcblxuXHRcdGlmICggZW1wdHlJbml0ICkge1xuXHRcdFx0b3B0aW9ucyA9IHt9O1xuXHRcdH1cblxuXHRcdHRoaXMub0FwaSA9IHRoaXMuaW50ZXJuYWwgPSBfZXh0LmludGVybmFsO1xuXG5cdFx0Ly8gRXh0ZW5kIHdpdGggb2xkIHN0eWxlIHBsdWctaW4gQVBJIG1ldGhvZHNcblx0XHRmb3IgKCB2YXIgZm4gaW4gRGF0YVRhYmxlLmV4dC5pbnRlcm5hbCApIHtcblx0XHRcdGlmICggZm4gKSB7XG5cdFx0XHRcdHRoaXNbZm5dID0gX2ZuRXh0ZXJuQXBpRnVuYyhmbik7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5lYWNoKGZ1bmN0aW9uKCkge1xuXHRcdFx0Ly8gRm9yIGVhY2ggaW5pdGlhbGlzYXRpb24gd2Ugd2FudCB0byBnaXZlIGl0IGEgY2xlYW4gaW5pdGlhbGlzYXRpb25cblx0XHRcdC8vIG9iamVjdCB0aGF0IGNhbiBiZSBiYXNoZWQgYXJvdW5kXG5cdFx0XHR2YXIgbyA9IHt9O1xuXHRcdFx0dmFyIG9Jbml0ID0gbGVuID4gMSA/IC8vIG9wdGltaXNhdGlvbiBmb3Igc2luZ2xlIHRhYmxlIGNhc2Vcblx0XHRcdFx0X2ZuRXh0ZW5kKCBvLCBvcHRpb25zLCB0cnVlICkgOlxuXHRcdFx0XHRvcHRpb25zO1xuXG5cdFx0XHQvKmdsb2JhbCBvSW5pdCxfdGhhdCxlbXB0eUluaXQqL1xuXHRcdFx0dmFyIGk9MCwgaUxlbiwgaiwgakxlbiwgaywga0xlbjtcblx0XHRcdHZhciBzSWQgPSB0aGlzLmdldEF0dHJpYnV0ZSggJ2lkJyApO1xuXHRcdFx0dmFyIGJJbml0SGFuZGVkT2ZmID0gZmFsc2U7XG5cdFx0XHR2YXIgZGVmYXVsdHMgPSBEYXRhVGFibGUuZGVmYXVsdHM7XG5cdFx0XHR2YXIgJHRoaXMgPSAkKHRoaXMpO1xuXHRcdFx0XG5cdFx0XHRcblx0XHRcdC8qIFNhbml0eSBjaGVjayAqL1xuXHRcdFx0aWYgKCB0aGlzLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgIT0gJ3RhYmxlJyApXG5cdFx0XHR7XG5cdFx0XHRcdF9mbkxvZyggbnVsbCwgMCwgJ05vbi10YWJsZSBub2RlIGluaXRpYWxpc2F0aW9uICgnK3RoaXMubm9kZU5hbWUrJyknLCAyICk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0LyogQmFja3dhcmRzIGNvbXBhdGliaWxpdHkgZm9yIHRoZSBkZWZhdWx0cyAqL1xuXHRcdFx0X2ZuQ29tcGF0T3B0cyggZGVmYXVsdHMgKTtcblx0XHRcdF9mbkNvbXBhdENvbHMoIGRlZmF1bHRzLmNvbHVtbiApO1xuXHRcdFx0XG5cdFx0XHQvKiBDb252ZXJ0IHRoZSBjYW1lbC1jYXNlIGRlZmF1bHRzIHRvIEh1bmdhcmlhbiAqL1xuXHRcdFx0X2ZuQ2FtZWxUb0h1bmdhcmlhbiggZGVmYXVsdHMsIGRlZmF1bHRzLCB0cnVlICk7XG5cdFx0XHRfZm5DYW1lbFRvSHVuZ2FyaWFuKCBkZWZhdWx0cy5jb2x1bW4sIGRlZmF1bHRzLmNvbHVtbiwgdHJ1ZSApO1xuXHRcdFx0XG5cdFx0XHQvKiBTZXR0aW5nIHVwIHRoZSBpbml0aWFsaXNhdGlvbiBvYmplY3QgKi9cblx0XHRcdF9mbkNhbWVsVG9IdW5nYXJpYW4oIGRlZmF1bHRzLCAkLmV4dGVuZCggb0luaXQsICR0aGlzLmRhdGEoKSApICk7XG5cdFx0XHRcblx0XHRcdFxuXHRcdFx0XG5cdFx0XHQvKiBDaGVjayB0byBzZWUgaWYgd2UgYXJlIHJlLWluaXRpYWxpc2luZyBhIHRhYmxlICovXG5cdFx0XHR2YXIgYWxsU2V0dGluZ3MgPSBEYXRhVGFibGUuc2V0dGluZ3M7XG5cdFx0XHRmb3IgKCBpPTAsIGlMZW49YWxsU2V0dGluZ3MubGVuZ3RoIDsgaTxpTGVuIDsgaSsrIClcblx0XHRcdHtcblx0XHRcdFx0dmFyIHMgPSBhbGxTZXR0aW5nc1tpXTtcblx0XHRcdFxuXHRcdFx0XHQvKiBCYXNlIGNoZWNrIG9uIHRhYmxlIG5vZGUgKi9cblx0XHRcdFx0aWYgKCBzLm5UYWJsZSA9PSB0aGlzIHx8IHMublRIZWFkLnBhcmVudE5vZGUgPT0gdGhpcyB8fCAocy5uVEZvb3QgJiYgcy5uVEZvb3QucGFyZW50Tm9kZSA9PSB0aGlzKSApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR2YXIgYlJldHJpZXZlID0gb0luaXQuYlJldHJpZXZlICE9PSB1bmRlZmluZWQgPyBvSW5pdC5iUmV0cmlldmUgOiBkZWZhdWx0cy5iUmV0cmlldmU7XG5cdFx0XHRcdFx0dmFyIGJEZXN0cm95ID0gb0luaXQuYkRlc3Ryb3kgIT09IHVuZGVmaW5lZCA/IG9Jbml0LmJEZXN0cm95IDogZGVmYXVsdHMuYkRlc3Ryb3k7XG5cdFx0XHRcblx0XHRcdFx0XHRpZiAoIGVtcHR5SW5pdCB8fCBiUmV0cmlldmUgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHJldHVybiBzLm9JbnN0YW5jZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZiAoIGJEZXN0cm95IClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRzLm9JbnN0YW5jZS5mbkRlc3Ryb3koKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0X2ZuTG9nKCBzLCAwLCAnQ2Fubm90IHJlaW5pdGlhbGlzZSBEYXRhVGFibGUnLCAzICk7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcblx0XHRcdFx0LyogSWYgdGhlIGVsZW1lbnQgd2UgYXJlIGluaXRpYWxpc2luZyBoYXMgdGhlIHNhbWUgSUQgYXMgYSB0YWJsZSB3aGljaCB3YXMgcHJldmlvdXNseVxuXHRcdFx0XHQgKiBpbml0aWFsaXNlZCwgYnV0IHRoZSB0YWJsZSBub2RlcyBkb24ndCBtYXRjaCAoZnJvbSBiZWZvcmUpIHRoZW4gd2UgZGVzdHJveSB0aGUgb2xkXG5cdFx0XHRcdCAqIGluc3RhbmNlIGJ5IHNpbXBseSBkZWxldGluZyBpdC4gVGhpcyBpcyB1bmRlciB0aGUgYXNzdW1wdGlvbiB0aGF0IHRoZSB0YWJsZSBoYXMgYmVlblxuXHRcdFx0XHQgKiBkZXN0cm95ZWQgYnkgb3RoZXIgbWV0aG9kcy4gQW55b25lIHVzaW5nIG5vbi1pZCBzZWxlY3RvcnMgd2lsbCBuZWVkIHRvIGRvIHRoaXMgbWFudWFsbHlcblx0XHRcdFx0ICovXG5cdFx0XHRcdGlmICggcy5zVGFibGVJZCA9PSB0aGlzLmlkIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGFsbFNldHRpbmdzLnNwbGljZSggaSwgMSApO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdC8qIEVuc3VyZSB0aGUgdGFibGUgaGFzIGFuIElEIC0gcmVxdWlyZWQgZm9yIGFjY2Vzc2liaWxpdHkgKi9cblx0XHRcdGlmICggc0lkID09PSBudWxsIHx8IHNJZCA9PT0gXCJcIiApXG5cdFx0XHR7XG5cdFx0XHRcdHNJZCA9IFwiRGF0YVRhYmxlc19UYWJsZV9cIisoRGF0YVRhYmxlLmV4dC5fdW5pcXVlKyspO1xuXHRcdFx0XHR0aGlzLmlkID0gc0lkO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQvKiBDcmVhdGUgdGhlIHNldHRpbmdzIG9iamVjdCBmb3IgdGhpcyB0YWJsZSBhbmQgc2V0IHNvbWUgb2YgdGhlIGRlZmF1bHQgcGFyYW1ldGVycyAqL1xuXHRcdFx0dmFyIG9TZXR0aW5ncyA9ICQuZXh0ZW5kKCB0cnVlLCB7fSwgRGF0YVRhYmxlLm1vZGVscy5vU2V0dGluZ3MsIHtcblx0XHRcdFx0XCJzRGVzdHJveVdpZHRoXCI6ICR0aGlzWzBdLnN0eWxlLndpZHRoLFxuXHRcdFx0XHRcInNJbnN0YW5jZVwiOiAgICAgc0lkLFxuXHRcdFx0XHRcInNUYWJsZUlkXCI6ICAgICAgc0lkXG5cdFx0XHR9ICk7XG5cdFx0XHRvU2V0dGluZ3MublRhYmxlID0gdGhpcztcblx0XHRcdG9TZXR0aW5ncy5vQXBpICAgPSBfdGhhdC5pbnRlcm5hbDtcblx0XHRcdG9TZXR0aW5ncy5vSW5pdCAgPSBvSW5pdDtcblx0XHRcdFxuXHRcdFx0YWxsU2V0dGluZ3MucHVzaCggb1NldHRpbmdzICk7XG5cdFx0XHRcblx0XHRcdC8vIE5lZWQgdG8gYWRkIHRoZSBpbnN0YW5jZSBhZnRlciB0aGUgaW5zdGFuY2UgYWZ0ZXIgdGhlIHNldHRpbmdzIG9iamVjdCBoYXMgYmVlbiBhZGRlZFxuXHRcdFx0Ly8gdG8gdGhlIHNldHRpbmdzIGFycmF5LCBzbyB3ZSBjYW4gc2VsZiByZWZlcmVuY2UgdGhlIHRhYmxlIGluc3RhbmNlIGlmIG1vcmUgdGhhbiBvbmVcblx0XHRcdG9TZXR0aW5ncy5vSW5zdGFuY2UgPSAoX3RoYXQubGVuZ3RoPT09MSkgPyBfdGhhdCA6ICR0aGlzLmRhdGFUYWJsZSgpO1xuXHRcdFx0XG5cdFx0XHQvLyBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSwgYmVmb3JlIHdlIGFwcGx5IGFsbCB0aGUgZGVmYXVsdHNcblx0XHRcdF9mbkNvbXBhdE9wdHMoIG9Jbml0ICk7XG5cdFx0XHRcblx0XHRcdGlmICggb0luaXQub0xhbmd1YWdlIClcblx0XHRcdHtcblx0XHRcdFx0X2ZuTGFuZ3VhZ2VDb21wYXQoIG9Jbml0Lm9MYW5ndWFnZSApO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQvLyBJZiB0aGUgbGVuZ3RoIG1lbnUgaXMgZ2l2ZW4sIGJ1dCB0aGUgaW5pdCBkaXNwbGF5IGxlbmd0aCBpcyBub3QsIHVzZSB0aGUgbGVuZ3RoIG1lbnVcblx0XHRcdGlmICggb0luaXQuYUxlbmd0aE1lbnUgJiYgISBvSW5pdC5pRGlzcGxheUxlbmd0aCApXG5cdFx0XHR7XG5cdFx0XHRcdG9Jbml0LmlEaXNwbGF5TGVuZ3RoID0gJC5pc0FycmF5KCBvSW5pdC5hTGVuZ3RoTWVudVswXSApID9cblx0XHRcdFx0XHRvSW5pdC5hTGVuZ3RoTWVudVswXVswXSA6IG9Jbml0LmFMZW5ndGhNZW51WzBdO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQvLyBBcHBseSB0aGUgZGVmYXVsdHMgYW5kIGluaXQgb3B0aW9ucyB0byBtYWtlIGEgc2luZ2xlIGluaXQgb2JqZWN0IHdpbGwgYWxsXG5cdFx0XHQvLyBvcHRpb25zIGRlZmluZWQgZnJvbSBkZWZhdWx0cyBhbmQgaW5zdGFuY2Ugb3B0aW9ucy5cblx0XHRcdG9Jbml0ID0gX2ZuRXh0ZW5kKCAkLmV4dGVuZCggdHJ1ZSwge30sIGRlZmF1bHRzICksIG9Jbml0ICk7XG5cdFx0XHRcblx0XHRcdFxuXHRcdFx0Ly8gTWFwIHRoZSBpbml0aWFsaXNhdGlvbiBvcHRpb25zIG9udG8gdGhlIHNldHRpbmdzIG9iamVjdFxuXHRcdFx0X2ZuTWFwKCBvU2V0dGluZ3Mub0ZlYXR1cmVzLCBvSW5pdCwgW1xuXHRcdFx0XHRcImJQYWdpbmF0ZVwiLFxuXHRcdFx0XHRcImJMZW5ndGhDaGFuZ2VcIixcblx0XHRcdFx0XCJiRmlsdGVyXCIsXG5cdFx0XHRcdFwiYlNvcnRcIixcblx0XHRcdFx0XCJiU29ydE11bHRpXCIsXG5cdFx0XHRcdFwiYkluZm9cIixcblx0XHRcdFx0XCJiUHJvY2Vzc2luZ1wiLFxuXHRcdFx0XHRcImJBdXRvV2lkdGhcIixcblx0XHRcdFx0XCJiU29ydENsYXNzZXNcIixcblx0XHRcdFx0XCJiU2VydmVyU2lkZVwiLFxuXHRcdFx0XHRcImJEZWZlclJlbmRlclwiXG5cdFx0XHRdICk7XG5cdFx0XHRfZm5NYXAoIG9TZXR0aW5ncywgb0luaXQsIFtcblx0XHRcdFx0XCJhc1N0cmlwZUNsYXNzZXNcIixcblx0XHRcdFx0XCJhamF4XCIsXG5cdFx0XHRcdFwiZm5TZXJ2ZXJEYXRhXCIsXG5cdFx0XHRcdFwiZm5Gb3JtYXROdW1iZXJcIixcblx0XHRcdFx0XCJzU2VydmVyTWV0aG9kXCIsXG5cdFx0XHRcdFwiYWFTb3J0aW5nXCIsXG5cdFx0XHRcdFwiYWFTb3J0aW5nRml4ZWRcIixcblx0XHRcdFx0XCJhTGVuZ3RoTWVudVwiLFxuXHRcdFx0XHRcInNQYWdpbmF0aW9uVHlwZVwiLFxuXHRcdFx0XHRcInNBamF4U291cmNlXCIsXG5cdFx0XHRcdFwic0FqYXhEYXRhUHJvcFwiLFxuXHRcdFx0XHRcImlTdGF0ZUR1cmF0aW9uXCIsXG5cdFx0XHRcdFwic0RvbVwiLFxuXHRcdFx0XHRcImJTb3J0Q2VsbHNUb3BcIixcblx0XHRcdFx0XCJpVGFiSW5kZXhcIixcblx0XHRcdFx0XCJmblN0YXRlTG9hZENhbGxiYWNrXCIsXG5cdFx0XHRcdFwiZm5TdGF0ZVNhdmVDYWxsYmFja1wiLFxuXHRcdFx0XHRcInJlbmRlcmVyXCIsXG5cdFx0XHRcdFwic2VhcmNoRGVsYXlcIixcblx0XHRcdFx0XCJyb3dJZFwiLFxuXHRcdFx0XHRbIFwiaUNvb2tpZUR1cmF0aW9uXCIsIFwiaVN0YXRlRHVyYXRpb25cIiBdLCAvLyBiYWNrd2FyZHMgY29tcGF0XG5cdFx0XHRcdFsgXCJvU2VhcmNoXCIsIFwib1ByZXZpb3VzU2VhcmNoXCIgXSxcblx0XHRcdFx0WyBcImFvU2VhcmNoQ29sc1wiLCBcImFvUHJlU2VhcmNoQ29sc1wiIF0sXG5cdFx0XHRcdFsgXCJpRGlzcGxheUxlbmd0aFwiLCBcIl9pRGlzcGxheUxlbmd0aFwiIF1cblx0XHRcdF0gKTtcblx0XHRcdF9mbk1hcCggb1NldHRpbmdzLm9TY3JvbGwsIG9Jbml0LCBbXG5cdFx0XHRcdFsgXCJzU2Nyb2xsWFwiLCBcInNYXCIgXSxcblx0XHRcdFx0WyBcInNTY3JvbGxYSW5uZXJcIiwgXCJzWElubmVyXCIgXSxcblx0XHRcdFx0WyBcInNTY3JvbGxZXCIsIFwic1lcIiBdLFxuXHRcdFx0XHRbIFwiYlNjcm9sbENvbGxhcHNlXCIsIFwiYkNvbGxhcHNlXCIgXVxuXHRcdFx0XSApO1xuXHRcdFx0X2ZuTWFwKCBvU2V0dGluZ3Mub0xhbmd1YWdlLCBvSW5pdCwgXCJmbkluZm9DYWxsYmFja1wiICk7XG5cdFx0XHRcblx0XHRcdC8qIENhbGxiYWNrIGZ1bmN0aW9ucyB3aGljaCBhcmUgYXJyYXkgZHJpdmVuICovXG5cdFx0XHRfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCAnYW9EcmF3Q2FsbGJhY2snLCAgICAgICBvSW5pdC5mbkRyYXdDYWxsYmFjaywgICAgICAndXNlcicgKTtcblx0XHRcdF9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb1NlcnZlclBhcmFtcycsICAgICAgIG9Jbml0LmZuU2VydmVyUGFyYW1zLCAgICAgICd1c2VyJyApO1xuXHRcdFx0X2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvU3RhdGVTYXZlUGFyYW1zJywgICAgb0luaXQuZm5TdGF0ZVNhdmVQYXJhbXMsICAgJ3VzZXInICk7XG5cdFx0XHRfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCAnYW9TdGF0ZUxvYWRQYXJhbXMnLCAgICBvSW5pdC5mblN0YXRlTG9hZFBhcmFtcywgICAndXNlcicgKTtcblx0XHRcdF9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb1N0YXRlTG9hZGVkJywgICAgICAgIG9Jbml0LmZuU3RhdGVMb2FkZWQsICAgICAgICd1c2VyJyApO1xuXHRcdFx0X2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvUm93Q2FsbGJhY2snLCAgICAgICAgb0luaXQuZm5Sb3dDYWxsYmFjaywgICAgICAgJ3VzZXInICk7XG5cdFx0XHRfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCAnYW9Sb3dDcmVhdGVkQ2FsbGJhY2snLCBvSW5pdC5mbkNyZWF0ZWRSb3csICAgICAgICAndXNlcicgKTtcblx0XHRcdF9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb0hlYWRlckNhbGxiYWNrJywgICAgIG9Jbml0LmZuSGVhZGVyQ2FsbGJhY2ssICAgICd1c2VyJyApO1xuXHRcdFx0X2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvRm9vdGVyQ2FsbGJhY2snLCAgICAgb0luaXQuZm5Gb290ZXJDYWxsYmFjaywgICAgJ3VzZXInICk7XG5cdFx0XHRfZm5DYWxsYmFja1JlZyggb1NldHRpbmdzLCAnYW9Jbml0Q29tcGxldGUnLCAgICAgICBvSW5pdC5mbkluaXRDb21wbGV0ZSwgICAgICAndXNlcicgKTtcblx0XHRcdF9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb1ByZURyYXdDYWxsYmFjaycsICAgIG9Jbml0LmZuUHJlRHJhd0NhbGxiYWNrLCAgICd1c2VyJyApO1xuXHRcdFx0XG5cdFx0XHRvU2V0dGluZ3Mucm93SWRGbiA9IF9mbkdldE9iamVjdERhdGFGbiggb0luaXQucm93SWQgKTtcblx0XHRcdFxuXHRcdFx0LyogQnJvd3NlciBzdXBwb3J0IGRldGVjdGlvbiAqL1xuXHRcdFx0X2ZuQnJvd3NlckRldGVjdCggb1NldHRpbmdzICk7XG5cdFx0XHRcblx0XHRcdHZhciBvQ2xhc3NlcyA9IG9TZXR0aW5ncy5vQ2xhc3Nlcztcblx0XHRcdFxuXHRcdFx0JC5leHRlbmQoIG9DbGFzc2VzLCBEYXRhVGFibGUuZXh0LmNsYXNzZXMsIG9Jbml0Lm9DbGFzc2VzICk7XG5cdFx0XHQkdGhpcy5hZGRDbGFzcyggb0NsYXNzZXMuc1RhYmxlICk7XG5cdFx0XHRcblx0XHRcdFxuXHRcdFx0aWYgKCBvU2V0dGluZ3MuaUluaXREaXNwbGF5U3RhcnQgPT09IHVuZGVmaW5lZCApXG5cdFx0XHR7XG5cdFx0XHRcdC8qIERpc3BsYXkgc3RhcnQgcG9pbnQsIHRha2luZyBpbnRvIGFjY291bnQgdGhlIHNhdmUgc2F2aW5nICovXG5cdFx0XHRcdG9TZXR0aW5ncy5pSW5pdERpc3BsYXlTdGFydCA9IG9Jbml0LmlEaXNwbGF5U3RhcnQ7XG5cdFx0XHRcdG9TZXR0aW5ncy5faURpc3BsYXlTdGFydCA9IG9Jbml0LmlEaXNwbGF5U3RhcnQ7XG5cdFx0XHR9XG5cdFx0XHRcblx0XHRcdGlmICggb0luaXQuaURlZmVyTG9hZGluZyAhPT0gbnVsbCApXG5cdFx0XHR7XG5cdFx0XHRcdG9TZXR0aW5ncy5iRGVmZXJMb2FkaW5nID0gdHJ1ZTtcblx0XHRcdFx0dmFyIHRtcCA9ICQuaXNBcnJheSggb0luaXQuaURlZmVyTG9hZGluZyApO1xuXHRcdFx0XHRvU2V0dGluZ3MuX2lSZWNvcmRzRGlzcGxheSA9IHRtcCA/IG9Jbml0LmlEZWZlckxvYWRpbmdbMF0gOiBvSW5pdC5pRGVmZXJMb2FkaW5nO1xuXHRcdFx0XHRvU2V0dGluZ3MuX2lSZWNvcmRzVG90YWwgPSB0bXAgPyBvSW5pdC5pRGVmZXJMb2FkaW5nWzFdIDogb0luaXQuaURlZmVyTG9hZGluZztcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0LyogTGFuZ3VhZ2UgZGVmaW5pdGlvbnMgKi9cblx0XHRcdHZhciBvTGFuZ3VhZ2UgPSBvU2V0dGluZ3Mub0xhbmd1YWdlO1xuXHRcdFx0JC5leHRlbmQoIHRydWUsIG9MYW5ndWFnZSwgb0luaXQub0xhbmd1YWdlICk7XG5cdFx0XHRcblx0XHRcdGlmICggb0xhbmd1YWdlLnNVcmwgKVxuXHRcdFx0e1xuXHRcdFx0XHQvKiBHZXQgdGhlIGxhbmd1YWdlIGRlZmluaXRpb25zIGZyb20gYSBmaWxlIC0gYmVjYXVzZSB0aGlzIEFqYXggY2FsbCBtYWtlcyB0aGUgbGFuZ3VhZ2Vcblx0XHRcdFx0ICogZ2V0IGFzeW5jIHRvIHRoZSByZW1haW5kZXIgb2YgdGhpcyBmdW5jdGlvbiB3ZSB1c2UgYkluaXRIYW5kZWRPZmYgdG8gaW5kaWNhdGUgdGhhdFxuXHRcdFx0XHQgKiBfZm5Jbml0aWFsaXNlIHdpbGwgYmUgZmlyZWQgYnkgdGhlIHJldHVybmVkIEFqYXggaGFuZGxlciwgcmF0aGVyIHRoYW4gdGhlIGNvbnN0cnVjdG9yXG5cdFx0XHRcdCAqL1xuXHRcdFx0XHQkLmFqYXgoIHtcblx0XHRcdFx0XHRkYXRhVHlwZTogJ2pzb24nLFxuXHRcdFx0XHRcdHVybDogb0xhbmd1YWdlLnNVcmwsXG5cdFx0XHRcdFx0c3VjY2VzczogZnVuY3Rpb24gKCBqc29uICkge1xuXHRcdFx0XHRcdFx0X2ZuTGFuZ3VhZ2VDb21wYXQoIGpzb24gKTtcblx0XHRcdFx0XHRcdF9mbkNhbWVsVG9IdW5nYXJpYW4oIGRlZmF1bHRzLm9MYW5ndWFnZSwganNvbiApO1xuXHRcdFx0XHRcdFx0JC5leHRlbmQoIHRydWUsIG9MYW5ndWFnZSwganNvbiApO1xuXHRcdFx0XHRcdFx0X2ZuSW5pdGlhbGlzZSggb1NldHRpbmdzICk7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRlcnJvcjogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0Ly8gRXJyb3Igb2NjdXJyZWQgbG9hZGluZyBsYW5ndWFnZSBmaWxlLCBjb250aW51ZSBvbiBhcyBiZXN0IHdlIGNhblxuXHRcdFx0XHRcdFx0X2ZuSW5pdGlhbGlzZSggb1NldHRpbmdzICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9ICk7XG5cdFx0XHRcdGJJbml0SGFuZGVkT2ZmID0gdHJ1ZTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0Lypcblx0XHRcdCAqIFN0cmlwZXNcblx0XHRcdCAqL1xuXHRcdFx0aWYgKCBvSW5pdC5hc1N0cmlwZUNsYXNzZXMgPT09IG51bGwgKVxuXHRcdFx0e1xuXHRcdFx0XHRvU2V0dGluZ3MuYXNTdHJpcGVDbGFzc2VzID1bXG5cdFx0XHRcdFx0b0NsYXNzZXMuc1N0cmlwZU9kZCxcblx0XHRcdFx0XHRvQ2xhc3Nlcy5zU3RyaXBlRXZlblxuXHRcdFx0XHRdO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHQvKiBSZW1vdmUgcm93IHN0cmlwZSBjbGFzc2VzIGlmIHRoZXkgYXJlIGFscmVhZHkgb24gdGhlIHRhYmxlIHJvdyAqL1xuXHRcdFx0dmFyIHN0cmlwZUNsYXNzZXMgPSBvU2V0dGluZ3MuYXNTdHJpcGVDbGFzc2VzO1xuXHRcdFx0dmFyIHJvd09uZSA9ICR0aGlzLmNoaWxkcmVuKCd0Ym9keScpLmZpbmQoJ3RyJykuZXEoMCk7XG5cdFx0XHRpZiAoICQuaW5BcnJheSggdHJ1ZSwgJC5tYXAoIHN0cmlwZUNsYXNzZXMsIGZ1bmN0aW9uKGVsLCBpKSB7XG5cdFx0XHRcdHJldHVybiByb3dPbmUuaGFzQ2xhc3MoZWwpO1xuXHRcdFx0fSApICkgIT09IC0xICkge1xuXHRcdFx0XHQkKCd0Ym9keSB0cicsIHRoaXMpLnJlbW92ZUNsYXNzKCBzdHJpcGVDbGFzc2VzLmpvaW4oJyAnKSApO1xuXHRcdFx0XHRvU2V0dGluZ3MuYXNEZXN0cm95U3RyaXBlcyA9IHN0cmlwZUNsYXNzZXMuc2xpY2UoKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0Lypcblx0XHRcdCAqIENvbHVtbnNcblx0XHRcdCAqIFNlZSBpZiB3ZSBzaG91bGQgbG9hZCBjb2x1bW5zIGF1dG9tYXRpY2FsbHkgb3IgdXNlIGRlZmluZWQgb25lc1xuXHRcdFx0ICovXG5cdFx0XHR2YXIgYW5UaHMgPSBbXTtcblx0XHRcdHZhciBhb0NvbHVtbnNJbml0O1xuXHRcdFx0dmFyIG5UaGVhZCA9IHRoaXMuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3RoZWFkJyk7XG5cdFx0XHRpZiAoIG5UaGVhZC5sZW5ndGggIT09IDAgKVxuXHRcdFx0e1xuXHRcdFx0XHRfZm5EZXRlY3RIZWFkZXIoIG9TZXR0aW5ncy5hb0hlYWRlciwgblRoZWFkWzBdICk7XG5cdFx0XHRcdGFuVGhzID0gX2ZuR2V0VW5pcXVlVGhzKCBvU2V0dGluZ3MgKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0LyogSWYgbm90IGdpdmVuIGEgY29sdW1uIGFycmF5LCBnZW5lcmF0ZSBvbmUgd2l0aCBudWxscyAqL1xuXHRcdFx0aWYgKCBvSW5pdC5hb0NvbHVtbnMgPT09IG51bGwgKVxuXHRcdFx0e1xuXHRcdFx0XHRhb0NvbHVtbnNJbml0ID0gW107XG5cdFx0XHRcdGZvciAoIGk9MCwgaUxlbj1hblRocy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YW9Db2x1bW5zSW5pdC5wdXNoKCBudWxsICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2Vcblx0XHRcdHtcblx0XHRcdFx0YW9Db2x1bW5zSW5pdCA9IG9Jbml0LmFvQ29sdW1ucztcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0LyogQWRkIHRoZSBjb2x1bW5zICovXG5cdFx0XHRmb3IgKCBpPTAsIGlMZW49YW9Db2x1bW5zSW5pdC5sZW5ndGggOyBpPGlMZW4gOyBpKysgKVxuXHRcdFx0e1xuXHRcdFx0XHRfZm5BZGRDb2x1bW4oIG9TZXR0aW5ncywgYW5UaHMgPyBhblRoc1tpXSA6IG51bGwgKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0LyogQXBwbHkgdGhlIGNvbHVtbiBkZWZpbml0aW9ucyAqL1xuXHRcdFx0X2ZuQXBwbHlDb2x1bW5EZWZzKCBvU2V0dGluZ3MsIG9Jbml0LmFvQ29sdW1uRGVmcywgYW9Db2x1bW5zSW5pdCwgZnVuY3Rpb24gKGlDb2wsIG9EZWYpIHtcblx0XHRcdFx0X2ZuQ29sdW1uT3B0aW9ucyggb1NldHRpbmdzLCBpQ29sLCBvRGVmICk7XG5cdFx0XHR9ICk7XG5cdFx0XHRcblx0XHRcdC8qIEhUTUw1IGF0dHJpYnV0ZSBkZXRlY3Rpb24gLSBidWlsZCBhbiBtRGF0YSBvYmplY3QgYXV0b21hdGljYWxseSBpZiB0aGVcblx0XHRcdCAqIGF0dHJpYnV0ZXMgYXJlIGZvdW5kXG5cdFx0XHQgKi9cblx0XHRcdGlmICggcm93T25lLmxlbmd0aCApIHtcblx0XHRcdFx0dmFyIGEgPSBmdW5jdGlvbiAoIGNlbGwsIG5hbWUgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGNlbGwuZ2V0QXR0cmlidXRlKCAnZGF0YS0nK25hbWUgKSAhPT0gbnVsbCA/IG5hbWUgOiBudWxsO1xuXHRcdFx0XHR9O1xuXHRcdFx0XG5cdFx0XHRcdCQoIHJvd09uZVswXSApLmNoaWxkcmVuKCd0aCwgdGQnKS5lYWNoKCBmdW5jdGlvbiAoaSwgY2VsbCkge1xuXHRcdFx0XHRcdHZhciBjb2wgPSBvU2V0dGluZ3MuYW9Db2x1bW5zW2ldO1xuXHRcdFx0XG5cdFx0XHRcdFx0aWYgKCBjb2wubURhdGEgPT09IGkgKSB7XG5cdFx0XHRcdFx0XHR2YXIgc29ydCA9IGEoIGNlbGwsICdzb3J0JyApIHx8IGEoIGNlbGwsICdvcmRlcicgKTtcblx0XHRcdFx0XHRcdHZhciBmaWx0ZXIgPSBhKCBjZWxsLCAnZmlsdGVyJyApIHx8IGEoIGNlbGwsICdzZWFyY2gnICk7XG5cdFx0XHRcblx0XHRcdFx0XHRcdGlmICggc29ydCAhPT0gbnVsbCB8fCBmaWx0ZXIgIT09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRcdGNvbC5tRGF0YSA9IHtcblx0XHRcdFx0XHRcdFx0XHRfOiAgICAgIGkrJy5kaXNwbGF5Jyxcblx0XHRcdFx0XHRcdFx0XHRzb3J0OiAgIHNvcnQgIT09IG51bGwgICA/IGkrJy5AZGF0YS0nK3NvcnQgICA6IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRcdFx0XHR0eXBlOiAgIHNvcnQgIT09IG51bGwgICA/IGkrJy5AZGF0YS0nK3NvcnQgICA6IHVuZGVmaW5lZCxcblx0XHRcdFx0XHRcdFx0XHRmaWx0ZXI6IGZpbHRlciAhPT0gbnVsbCA/IGkrJy5AZGF0YS0nK2ZpbHRlciA6IHVuZGVmaW5lZFxuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XG5cdFx0XHRcdFx0XHRcdF9mbkNvbHVtbk9wdGlvbnMoIG9TZXR0aW5ncywgaSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHR2YXIgZmVhdHVyZXMgPSBvU2V0dGluZ3Mub0ZlYXR1cmVzO1xuXHRcdFx0dmFyIGxvYWRlZEluaXQgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdC8qXG5cdFx0XHRcdCAqIFNvcnRpbmdcblx0XHRcdFx0ICogQHRvZG8gRm9yIG1vZHVsYXJpc2F0aW9uICgxLjExKSB0aGlzIG5lZWRzIHRvIGRvIGludG8gYSBzb3J0IHN0YXJ0IHVwIGhhbmRsZXJcblx0XHRcdFx0ICovXG5cdFx0XHRcblx0XHRcdFx0Ly8gSWYgYWFTb3J0aW5nIGlzIG5vdCBkZWZpbmVkLCB0aGVuIHdlIHVzZSB0aGUgZmlyc3QgaW5kaWNhdG9yIGluIGFzU29ydGluZ1xuXHRcdFx0XHQvLyBpbiBjYXNlIHRoYXQgaGFzIGJlZW4gYWx0ZXJlZCwgc28gdGhlIGRlZmF1bHQgc29ydCByZWZsZWN0cyB0aGF0IG9wdGlvblxuXHRcdFx0XHRpZiAoIG9Jbml0LmFhU29ydGluZyA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdHZhciBzb3J0aW5nID0gb1NldHRpbmdzLmFhU29ydGluZztcblx0XHRcdFx0XHRmb3IgKCBpPTAsIGlMZW49c29ydGluZy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0XHRzb3J0aW5nW2ldWzFdID0gb1NldHRpbmdzLmFvQ29sdW1uc1sgaSBdLmFzU29ydGluZ1swXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFxuXHRcdFx0XHQvKiBEbyBhIGZpcnN0IHBhc3Mgb24gdGhlIHNvcnRpbmcgY2xhc3NlcyAoYWxsb3dzIGFueSBzaXplIGNoYW5nZXMgdG8gYmUgdGFrZW4gaW50b1xuXHRcdFx0XHQgKiBhY2NvdW50LCBhbmQgYWxzbyB3aWxsIGFwcGx5IHNvcnRpbmcgZGlzYWJsZWQgY2xhc3NlcyBpZiBkaXNhYmxlZFxuXHRcdFx0XHQgKi9cblx0XHRcdFx0X2ZuU29ydGluZ0NsYXNzZXMoIG9TZXR0aW5ncyApO1xuXHRcdFx0XG5cdFx0XHRcdGlmICggZmVhdHVyZXMuYlNvcnQgKSB7XG5cdFx0XHRcdFx0X2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvRHJhd0NhbGxiYWNrJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0aWYgKCBvU2V0dGluZ3MuYlNvcnRlZCApIHtcblx0XHRcdFx0XHRcdFx0dmFyIGFTb3J0ID0gX2ZuU29ydEZsYXR0ZW4oIG9TZXR0aW5ncyApO1xuXHRcdFx0XHRcdFx0XHR2YXIgc29ydGVkQ29sdW1ucyA9IHt9O1xuXHRcdFx0XG5cdFx0XHRcdFx0XHRcdCQuZWFjaCggYVNvcnQsIGZ1bmN0aW9uIChpLCB2YWwpIHtcblx0XHRcdFx0XHRcdFx0XHRzb3J0ZWRDb2x1bW5zWyB2YWwuc3JjIF0gPSB2YWwuZGlyO1xuXHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcblx0XHRcdFx0XHRcdFx0X2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsIG51bGwsICdvcmRlcicsIFtvU2V0dGluZ3MsIGFTb3J0LCBzb3J0ZWRDb2x1bW5zXSApO1xuXHRcdFx0XHRcdFx0XHRfZm5Tb3J0QXJpYSggb1NldHRpbmdzICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcblx0XHRcdFx0X2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgJ2FvRHJhd0NhbGxiYWNrJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdGlmICggb1NldHRpbmdzLmJTb3J0ZWQgfHwgX2ZuRGF0YVNvdXJjZSggb1NldHRpbmdzICkgPT09ICdzc3AnIHx8IGZlYXR1cmVzLmJEZWZlclJlbmRlciApIHtcblx0XHRcdFx0XHRcdF9mblNvcnRpbmdDbGFzc2VzKCBvU2V0dGluZ3MgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sICdzYycgKTtcblx0XHRcdFxuXHRcdFx0XG5cdFx0XHRcdC8qXG5cdFx0XHRcdCAqIEZpbmFsIGluaXRcblx0XHRcdFx0ICogQ2FjaGUgdGhlIGhlYWRlciwgYm9keSBhbmQgZm9vdGVyIGFzIHJlcXVpcmVkLCBjcmVhdGluZyB0aGVtIGlmIG5lZWRlZFxuXHRcdFx0XHQgKi9cblx0XHRcdFxuXHRcdFx0XHQvLyBXb3JrIGFyb3VuZCBmb3IgV2Via2l0IGJ1ZyA4Mzg2NyAtIHN0b3JlIHRoZSBjYXB0aW9uLXNpZGUgYmVmb3JlIHJlbW92aW5nIGZyb20gZG9jXG5cdFx0XHRcdHZhciBjYXB0aW9ucyA9ICR0aGlzLmNoaWxkcmVuKCdjYXB0aW9uJykuZWFjaCggZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHRoaXMuX2NhcHRpb25TaWRlID0gJCh0aGlzKS5jc3MoJ2NhcHRpb24tc2lkZScpO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHRcblx0XHRcdFx0dmFyIHRoZWFkID0gJHRoaXMuY2hpbGRyZW4oJ3RoZWFkJyk7XG5cdFx0XHRcdGlmICggdGhlYWQubGVuZ3RoID09PSAwICkge1xuXHRcdFx0XHRcdHRoZWFkID0gJCgnPHRoZWFkLz4nKS5hcHBlbmRUbygkdGhpcyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0b1NldHRpbmdzLm5USGVhZCA9IHRoZWFkWzBdO1xuXHRcdFx0XG5cdFx0XHRcdHZhciB0Ym9keSA9ICR0aGlzLmNoaWxkcmVuKCd0Ym9keScpO1xuXHRcdFx0XHRpZiAoIHRib2R5Lmxlbmd0aCA9PT0gMCApIHtcblx0XHRcdFx0XHR0Ym9keSA9ICQoJzx0Ym9keS8+JykuYXBwZW5kVG8oJHRoaXMpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdG9TZXR0aW5ncy5uVEJvZHkgPSB0Ym9keVswXTtcblx0XHRcdFxuXHRcdFx0XHR2YXIgdGZvb3QgPSAkdGhpcy5jaGlsZHJlbigndGZvb3QnKTtcblx0XHRcdFx0aWYgKCB0Zm9vdC5sZW5ndGggPT09IDAgJiYgY2FwdGlvbnMubGVuZ3RoID4gMCAmJiAob1NldHRpbmdzLm9TY3JvbGwuc1ggIT09IFwiXCIgfHwgb1NldHRpbmdzLm9TY3JvbGwuc1kgIT09IFwiXCIpICkge1xuXHRcdFx0XHRcdC8vIElmIHdlIGFyZSBhIHNjcm9sbGluZyB0YWJsZSwgYW5kIG5vIGZvb3RlciBoYXMgYmVlbiBnaXZlbiwgdGhlbiB3ZSBuZWVkIHRvIGNyZWF0ZVxuXHRcdFx0XHRcdC8vIGEgdGZvb3QgZWxlbWVudCBmb3IgdGhlIGNhcHRpb24gZWxlbWVudCB0byBiZSBhcHBlbmRlZCB0b1xuXHRcdFx0XHRcdHRmb290ID0gJCgnPHRmb290Lz4nKS5hcHBlbmRUbygkdGhpcyk7XG5cdFx0XHRcdH1cblx0XHRcdFxuXHRcdFx0XHRpZiAoIHRmb290Lmxlbmd0aCA9PT0gMCB8fCB0Zm9vdC5jaGlsZHJlbigpLmxlbmd0aCA9PT0gMCApIHtcblx0XHRcdFx0XHQkdGhpcy5hZGRDbGFzcyggb0NsYXNzZXMuc05vRm9vdGVyICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSBpZiAoIHRmb290Lmxlbmd0aCA+IDAgKSB7XG5cdFx0XHRcdFx0b1NldHRpbmdzLm5URm9vdCA9IHRmb290WzBdO1xuXHRcdFx0XHRcdF9mbkRldGVjdEhlYWRlciggb1NldHRpbmdzLmFvRm9vdGVyLCBvU2V0dGluZ3MublRGb290ICk7XG5cdFx0XHRcdH1cblx0XHRcdFxuXHRcdFx0XHQvKiBDaGVjayBpZiB0aGVyZSBpcyBkYXRhIHBhc3NpbmcgaW50byB0aGUgY29uc3RydWN0b3IgKi9cblx0XHRcdFx0aWYgKCBvSW5pdC5hYURhdGEgKSB7XG5cdFx0XHRcdFx0Zm9yICggaT0wIDsgaTxvSW5pdC5hYURhdGEubGVuZ3RoIDsgaSsrICkge1xuXHRcdFx0XHRcdFx0X2ZuQWRkRGF0YSggb1NldHRpbmdzLCBvSW5pdC5hYURhdGFbIGkgXSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIGlmICggb1NldHRpbmdzLmJEZWZlckxvYWRpbmcgfHwgX2ZuRGF0YVNvdXJjZSggb1NldHRpbmdzICkgPT0gJ2RvbScgKSB7XG5cdFx0XHRcdFx0LyogR3JhYiB0aGUgZGF0YSBmcm9tIHRoZSBwYWdlIC0gb25seSBkbyB0aGlzIHdoZW4gZGVmZXJyZWQgbG9hZGluZyBvciBubyBBamF4XG5cdFx0XHRcdFx0ICogc291cmNlIHNpbmNlIHRoZXJlIGlzIG5vIHBvaW50IGluIHJlYWRpbmcgdGhlIERPTSBkYXRhIGlmIHdlIGFyZSB0aGVuIGdvaW5nXG5cdFx0XHRcdFx0ICogdG8gcmVwbGFjZSBpdCB3aXRoIEFqYXggZGF0YVxuXHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdF9mbkFkZFRyKCBvU2V0dGluZ3MsICQob1NldHRpbmdzLm5UQm9keSkuY2hpbGRyZW4oJ3RyJykgKTtcblx0XHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRcdC8qIENvcHkgdGhlIGRhdGEgaW5kZXggYXJyYXkgKi9cblx0XHRcdFx0b1NldHRpbmdzLmFpRGlzcGxheSA9IG9TZXR0aW5ncy5haURpc3BsYXlNYXN0ZXIuc2xpY2UoKTtcblx0XHRcdFxuXHRcdFx0XHQvKiBJbml0aWFsaXNhdGlvbiBjb21wbGV0ZSAtIHRhYmxlIGNhbiBiZSBkcmF3biAqL1xuXHRcdFx0XHRvU2V0dGluZ3MuYkluaXRpYWxpc2VkID0gdHJ1ZTtcblx0XHRcdFxuXHRcdFx0XHQvKiBDaGVjayBpZiB3ZSBuZWVkIHRvIGluaXRpYWxpc2UgdGhlIHRhYmxlIChpdCBtaWdodCBub3QgaGF2ZSBiZWVuIGhhbmRlZCBvZmYgdG8gdGhlXG5cdFx0XHRcdCAqIGxhbmd1YWdlIHByb2Nlc3Nvcilcblx0XHRcdFx0ICovXG5cdFx0XHRcdGlmICggYkluaXRIYW5kZWRPZmYgPT09IGZhbHNlICkge1xuXHRcdFx0XHRcdF9mbkluaXRpYWxpc2UoIG9TZXR0aW5ncyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdFx0XG5cdFx0XHQvKiBNdXN0IGJlIGRvbmUgYWZ0ZXIgZXZlcnl0aGluZyB3aGljaCBjYW4gYmUgb3ZlcnJpZGRlbiBieSB0aGUgc3RhdGUgc2F2aW5nISAqL1xuXHRcdFx0aWYgKCBvSW5pdC5iU3RhdGVTYXZlIClcblx0XHRcdHtcblx0XHRcdFx0ZmVhdHVyZXMuYlN0YXRlU2F2ZSA9IHRydWU7XG5cdFx0XHRcdF9mbkNhbGxiYWNrUmVnKCBvU2V0dGluZ3MsICdhb0RyYXdDYWxsYmFjaycsIF9mblNhdmVTdGF0ZSwgJ3N0YXRlX3NhdmUnICk7XG5cdFx0XHRcdF9mbkxvYWRTdGF0ZSggb1NldHRpbmdzLCBvSW5pdCwgbG9hZGVkSW5pdCApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGxvYWRlZEluaXQoKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdH0gKTtcblx0XHRfdGhhdCA9IG51bGw7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH07XG5cblx0XG5cdC8qXG5cdCAqIEl0IGlzIHVzZWZ1bCB0byBoYXZlIHZhcmlhYmxlcyB3aGljaCBhcmUgc2NvcGVkIGxvY2FsbHkgc28gb25seSB0aGVcblx0ICogRGF0YVRhYmxlcyBmdW5jdGlvbnMgY2FuIGFjY2VzcyB0aGVtIGFuZCB0aGV5IGRvbid0IGxlYWsgaW50byBnbG9iYWwgc3BhY2UuXG5cdCAqIEF0IHRoZSBzYW1lIHRpbWUgdGhlc2UgZnVuY3Rpb25zIGFyZSBvZnRlbiB1c2VmdWwgb3ZlciBtdWx0aXBsZSBmaWxlcyBpbiB0aGVcblx0ICogY29yZSBhbmQgQVBJLCBzbyB3ZSBsaXN0LCBvciBhdCBsZWFzdCBkb2N1bWVudCwgYWxsIHZhcmlhYmxlcyB3aGljaCBhcmUgdXNlZFxuXHQgKiBieSBEYXRhVGFibGVzIGFzIHByaXZhdGUgdmFyaWFibGVzIGhlcmUuIFRoaXMgYWxzbyBlbnN1cmVzIHRoYXQgdGhlcmUgaXMgbm9cblx0ICogY2xhc2hpbmcgb2YgdmFyaWFibGUgbmFtZXMgYW5kIHRoYXQgdGhleSBjYW4gZWFzaWx5IHJlZmVyZW5jZWQgZm9yIHJldXNlLlxuXHQgKi9cblx0XG5cdFxuXHQvLyBEZWZpbmVkIGVsc2Ugd2hlcmVcblx0Ly8gIF9zZWxlY3Rvcl9ydW5cblx0Ly8gIF9zZWxlY3Rvcl9vcHRzXG5cdC8vICBfc2VsZWN0b3JfZmlyc3Rcblx0Ly8gIF9zZWxlY3Rvcl9yb3dfaW5kZXhlc1xuXHRcblx0dmFyIF9leHQ7IC8vIERhdGFUYWJsZS5leHRcblx0dmFyIF9BcGk7IC8vIERhdGFUYWJsZS5BcGlcblx0dmFyIF9hcGlfcmVnaXN0ZXI7IC8vIERhdGFUYWJsZS5BcGkucmVnaXN0ZXJcblx0dmFyIF9hcGlfcmVnaXN0ZXJQbHVyYWw7IC8vIERhdGFUYWJsZS5BcGkucmVnaXN0ZXJQbHVyYWxcblx0XG5cdHZhciBfcmVfZGljID0ge307XG5cdHZhciBfcmVfbmV3X2xpbmVzID0gL1tcXHJcXG5dL2c7XG5cdHZhciBfcmVfaHRtbCA9IC88Lio/Pi9nO1xuXHRcblx0Ly8gVGhpcyBpcyBub3Qgc3RyaWN0IElTTzg2MDEgLSBEYXRlLnBhcnNlKCkgaXMgcXVpdGUgbGF4LCBhbHRob3VnaFxuXHQvLyBpbXBsZW1lbnRhdGlvbnMgZGlmZmVyIGJldHdlZW4gYnJvd3NlcnMuXG5cdHZhciBfcmVfZGF0ZSA9IC9eXFxkezIsNH1bXFwuXFwvXFwtXVxcZHsxLDJ9W1xcLlxcL1xcLV1cXGR7MSwyfShbVCBdezF9XFxkezEsMn1bOlxcLl1cXGR7Mn0oW1xcLjpdXFxkezJ9KT8pPyQvO1xuXHRcblx0Ly8gRXNjYXBlIHJlZ3VsYXIgZXhwcmVzc2lvbiBzcGVjaWFsIGNoYXJhY3RlcnNcblx0dmFyIF9yZV9lc2NhcGVfcmVnZXggPSBuZXcgUmVnRXhwKCAnKFxcXFwnICsgWyAnLycsICcuJywgJyonLCAnKycsICc/JywgJ3wnLCAnKCcsICcpJywgJ1snLCAnXScsICd7JywgJ30nLCAnXFxcXCcsICckJywgJ14nLCAnLScgXS5qb2luKCd8XFxcXCcpICsgJyknLCAnZycgKTtcblx0XG5cdC8vIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvRm9yZWlnbl9leGNoYW5nZV9tYXJrZXRcblx0Ly8gLSBcXHUyMEJEIC0gUnVzc2lhbiBydWJsZS5cblx0Ly8gLSBcXHUyMGE5IC0gU291dGggS29yZWFuIFdvblxuXHQvLyAtIFxcdTIwQkEgLSBUdXJraXNoIExpcmFcblx0Ly8gLSBcXHUyMEI5IC0gSW5kaWFuIFJ1cGVlXG5cdC8vIC0gUiAtIEJyYXppbCAoUiQpIGFuZCBTb3V0aCBBZnJpY2Fcblx0Ly8gLSBmciAtIFN3aXNzIEZyYW5jXG5cdC8vIC0ga3IgLSBTd2VkaXNoIGtyb25hLCBOb3J3ZWdpYW4ga3JvbmUgYW5kIERhbmlzaCBrcm9uZVxuXHQvLyAtIFxcdTIwMDkgaXMgdGhpbiBzcGFjZSBhbmQgXFx1MjAyRiBpcyBuYXJyb3cgbm8tYnJlYWsgc3BhY2UsIGJvdGggdXNlZCBpbiBtYW55XG5cdC8vICAgc3RhbmRhcmRzIGFzIHRob3VzYW5kcyBzZXBhcmF0b3JzLlxuXHR2YXIgX3JlX2Zvcm1hdHRlZF9udW1lcmljID0gL1snLCTCo+KCrMKlJVxcdTIwMDlcXHUyMDJGXFx1MjBCRFxcdTIwYTlcXHUyMEJBcmZrXS9naTtcblx0XG5cdFxuXHR2YXIgX2VtcHR5ID0gZnVuY3Rpb24gKCBkICkge1xuXHRcdHJldHVybiAhZCB8fCBkID09PSB0cnVlIHx8IGQgPT09ICctJyA/IHRydWUgOiBmYWxzZTtcblx0fTtcblx0XG5cdFxuXHR2YXIgX2ludFZhbCA9IGZ1bmN0aW9uICggcyApIHtcblx0XHR2YXIgaW50ZWdlciA9IHBhcnNlSW50KCBzLCAxMCApO1xuXHRcdHJldHVybiAhaXNOYU4oaW50ZWdlcikgJiYgaXNGaW5pdGUocykgPyBpbnRlZ2VyIDogbnVsbDtcblx0fTtcblx0XG5cdC8vIENvbnZlcnQgZnJvbSBhIGZvcm1hdHRlZCBudW1iZXIgd2l0aCBjaGFyYWN0ZXJzIG90aGVyIHRoYW4gYC5gIGFzIHRoZVxuXHQvLyBkZWNpbWFsIHBsYWNlLCB0byBhIEphdmFzY3JpcHQgbnVtYmVyXG5cdHZhciBfbnVtVG9EZWNpbWFsID0gZnVuY3Rpb24gKCBudW0sIGRlY2ltYWxQb2ludCApIHtcblx0XHQvLyBDYWNoZSBjcmVhdGVkIHJlZ3VsYXIgZXhwcmVzc2lvbnMgZm9yIHNwZWVkIGFzIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIG9mdGVuXG5cdFx0aWYgKCAhIF9yZV9kaWNbIGRlY2ltYWxQb2ludCBdICkge1xuXHRcdFx0X3JlX2RpY1sgZGVjaW1hbFBvaW50IF0gPSBuZXcgUmVnRXhwKCBfZm5Fc2NhcGVSZWdleCggZGVjaW1hbFBvaW50ICksICdnJyApO1xuXHRcdH1cblx0XHRyZXR1cm4gdHlwZW9mIG51bSA9PT0gJ3N0cmluZycgJiYgZGVjaW1hbFBvaW50ICE9PSAnLicgP1xuXHRcdFx0bnVtLnJlcGxhY2UoIC9cXC4vZywgJycgKS5yZXBsYWNlKCBfcmVfZGljWyBkZWNpbWFsUG9pbnQgXSwgJy4nICkgOlxuXHRcdFx0bnVtO1xuXHR9O1xuXHRcblx0XG5cdHZhciBfaXNOdW1iZXIgPSBmdW5jdGlvbiAoIGQsIGRlY2ltYWxQb2ludCwgZm9ybWF0dGVkICkge1xuXHRcdHZhciBzdHJUeXBlID0gdHlwZW9mIGQgPT09ICdzdHJpbmcnO1xuXHRcblx0XHQvLyBJZiBlbXB0eSByZXR1cm4gaW1tZWRpYXRlbHkgc28gdGhlcmUgbXVzdCBiZSBhIG51bWJlciBpZiBpdCBpcyBhXG5cdFx0Ly8gZm9ybWF0dGVkIHN0cmluZyAodGhpcyBzdG9wcyB0aGUgc3RyaW5nIFwia1wiLCBvciBcImtyXCIsIGV0YyBiZWluZyBkZXRlY3RlZFxuXHRcdC8vIGFzIGEgZm9ybWF0dGVkIG51bWJlciBmb3IgY3VycmVuY3lcblx0XHRpZiAoIF9lbXB0eSggZCApICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcblx0XHRpZiAoIGRlY2ltYWxQb2ludCAmJiBzdHJUeXBlICkge1xuXHRcdFx0ZCA9IF9udW1Ub0RlY2ltYWwoIGQsIGRlY2ltYWxQb2ludCApO1xuXHRcdH1cblx0XG5cdFx0aWYgKCBmb3JtYXR0ZWQgJiYgc3RyVHlwZSApIHtcblx0XHRcdGQgPSBkLnJlcGxhY2UoIF9yZV9mb3JtYXR0ZWRfbnVtZXJpYywgJycgKTtcblx0XHR9XG5cdFxuXHRcdHJldHVybiAhaXNOYU4oIHBhcnNlRmxvYXQoZCkgKSAmJiBpc0Zpbml0ZSggZCApO1xuXHR9O1xuXHRcblx0XG5cdC8vIEEgc3RyaW5nIHdpdGhvdXQgSFRNTCBpbiBpdCBjYW4gYmUgY29uc2lkZXJlZCB0byBiZSBIVE1MIHN0aWxsXG5cdHZhciBfaXNIdG1sID0gZnVuY3Rpb24gKCBkICkge1xuXHRcdHJldHVybiBfZW1wdHkoIGQgKSB8fCB0eXBlb2YgZCA9PT0gJ3N0cmluZyc7XG5cdH07XG5cdFxuXHRcblx0dmFyIF9odG1sTnVtZXJpYyA9IGZ1bmN0aW9uICggZCwgZGVjaW1hbFBvaW50LCBmb3JtYXR0ZWQgKSB7XG5cdFx0aWYgKCBfZW1wdHkoIGQgKSApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XG5cdFx0dmFyIGh0bWwgPSBfaXNIdG1sKCBkICk7XG5cdFx0cmV0dXJuICEgaHRtbCA/XG5cdFx0XHRudWxsIDpcblx0XHRcdF9pc051bWJlciggX3N0cmlwSHRtbCggZCApLCBkZWNpbWFsUG9pbnQsIGZvcm1hdHRlZCApID9cblx0XHRcdFx0dHJ1ZSA6XG5cdFx0XHRcdG51bGw7XG5cdH07XG5cdFxuXHRcblx0dmFyIF9wbHVjayA9IGZ1bmN0aW9uICggYSwgcHJvcCwgcHJvcDIgKSB7XG5cdFx0dmFyIG91dCA9IFtdO1xuXHRcdHZhciBpPTAsIGllbj1hLmxlbmd0aDtcblx0XG5cdFx0Ly8gQ291bGQgaGF2ZSB0aGUgdGVzdCBpbiB0aGUgbG9vcCBmb3Igc2xpZ2h0bHkgc21hbGxlciBjb2RlLCBidXQgc3BlZWRcblx0XHQvLyBpcyBlc3NlbnRpYWwgaGVyZVxuXHRcdGlmICggcHJvcDIgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGZvciAoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdGlmICggYVtpXSAmJiBhW2ldWyBwcm9wIF0gKSB7XG5cdFx0XHRcdFx0b3V0LnB1c2goIGFbaV1bIHByb3AgXVsgcHJvcDIgXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0Zm9yICggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBhW2ldICkge1xuXHRcdFx0XHRcdG91dC5wdXNoKCBhW2ldWyBwcm9wIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0cmV0dXJuIG91dDtcblx0fTtcblx0XG5cdFxuXHQvLyBCYXNpY2FsbHkgdGhlIHNhbWUgYXMgX3BsdWNrLCBidXQgcmF0aGVyIHRoYW4gbG9vcGluZyBvdmVyIGBhYCB3ZSB1c2UgYG9yZGVyYFxuXHQvLyBhcyB0aGUgaW5kZXhlcyB0byBwaWNrIGZyb20gYGFgXG5cdHZhciBfcGx1Y2tfb3JkZXIgPSBmdW5jdGlvbiAoIGEsIG9yZGVyLCBwcm9wLCBwcm9wMiApXG5cdHtcblx0XHR2YXIgb3V0ID0gW107XG5cdFx0dmFyIGk9MCwgaWVuPW9yZGVyLmxlbmd0aDtcblx0XG5cdFx0Ly8gQ291bGQgaGF2ZSB0aGUgdGVzdCBpbiB0aGUgbG9vcCBmb3Igc2xpZ2h0bHkgc21hbGxlciBjb2RlLCBidXQgc3BlZWRcblx0XHQvLyBpcyBlc3NlbnRpYWwgaGVyZVxuXHRcdGlmICggcHJvcDIgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGZvciAoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdGlmICggYVsgb3JkZXJbaV0gXVsgcHJvcCBdICkge1xuXHRcdFx0XHRcdG91dC5wdXNoKCBhWyBvcmRlcltpXSBdWyBwcm9wIF1bIHByb3AyIF0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGZvciAoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdG91dC5wdXNoKCBhWyBvcmRlcltpXSBdWyBwcm9wIF0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFxuXHRcdHJldHVybiBvdXQ7XG5cdH07XG5cdFxuXHRcblx0dmFyIF9yYW5nZSA9IGZ1bmN0aW9uICggbGVuLCBzdGFydCApXG5cdHtcblx0XHR2YXIgb3V0ID0gW107XG5cdFx0dmFyIGVuZDtcblx0XG5cdFx0aWYgKCBzdGFydCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0c3RhcnQgPSAwO1xuXHRcdFx0ZW5kID0gbGVuO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGVuZCA9IHN0YXJ0O1xuXHRcdFx0c3RhcnQgPSBsZW47XG5cdFx0fVxuXHRcblx0XHRmb3IgKCB2YXIgaT1zdGFydCA7IGk8ZW5kIDsgaSsrICkge1xuXHRcdFx0b3V0LnB1c2goIGkgKTtcblx0XHR9XG5cdFxuXHRcdHJldHVybiBvdXQ7XG5cdH07XG5cdFxuXHRcblx0dmFyIF9yZW1vdmVFbXB0eSA9IGZ1bmN0aW9uICggYSApXG5cdHtcblx0XHR2YXIgb3V0ID0gW107XG5cdFxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1hLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0aWYgKCBhW2ldICkgeyAvLyBjYXJlZnVsIC0gd2lsbCByZW1vdmUgYWxsIGZhbHN5IHZhbHVlcyFcblx0XHRcdFx0b3V0LnB1c2goIGFbaV0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFxuXHRcdHJldHVybiBvdXQ7XG5cdH07XG5cdFxuXHRcblx0dmFyIF9zdHJpcEh0bWwgPSBmdW5jdGlvbiAoIGQgKSB7XG5cdFx0cmV0dXJuIGQucmVwbGFjZSggX3JlX2h0bWwsICcnICk7XG5cdH07XG5cdFxuXHRcblx0LyoqXG5cdCAqIERldGVybWluZSBpZiBhbGwgdmFsdWVzIGluIHRoZSBhcnJheSBhcmUgdW5pcXVlLiBUaGlzIG1lYW5zIHdlIGNhbiBzaG9ydFxuXHQgKiBjdXQgdGhlIF91bmlxdWUgbWV0aG9kIGF0IHRoZSBjb3N0IG9mIGEgc2luZ2xlIGxvb3AuIEEgc29ydGVkIGFycmF5IGlzIHVzZWRcblx0ICogdG8gZWFzaWx5IGNoZWNrIHRoZSB2YWx1ZXMuXG5cdCAqXG5cdCAqIEBwYXJhbSAge2FycmF5fSBzcmMgU291cmNlIGFycmF5XG5cdCAqIEByZXR1cm4ge2Jvb2xlYW59IHRydWUgaWYgYWxsIHVuaXF1ZSwgZmFsc2Ugb3RoZXJ3aXNlXG5cdCAqIEBpZ25vcmVcblx0ICovXG5cdHZhciBfYXJlQWxsVW5pcXVlID0gZnVuY3Rpb24gKCBzcmMgKSB7XG5cdFx0aWYgKCBzcmMubGVuZ3RoIDwgMiApIHtcblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XG5cdFx0dmFyIHNvcnRlZCA9IHNyYy5zbGljZSgpLnNvcnQoKTtcblx0XHR2YXIgbGFzdCA9IHNvcnRlZFswXTtcblx0XG5cdFx0Zm9yICggdmFyIGk9MSwgaWVuPXNvcnRlZC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGlmICggc29ydGVkW2ldID09PSBsYXN0ICkge1xuXHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHR9XG5cdFxuXHRcdFx0bGFzdCA9IHNvcnRlZFtpXTtcblx0XHR9XG5cdFxuXHRcdHJldHVybiB0cnVlO1xuXHR9O1xuXHRcblx0XG5cdC8qKlxuXHQgKiBGaW5kIHRoZSB1bmlxdWUgZWxlbWVudHMgaW4gYSBzb3VyY2UgYXJyYXkuXG5cdCAqXG5cdCAqIEBwYXJhbSAge2FycmF5fSBzcmMgU291cmNlIGFycmF5XG5cdCAqIEByZXR1cm4ge2FycmF5fSBBcnJheSBvZiB1bmlxdWUgaXRlbXNcblx0ICogQGlnbm9yZVxuXHQgKi9cblx0dmFyIF91bmlxdWUgPSBmdW5jdGlvbiAoIHNyYyApXG5cdHtcblx0XHRpZiAoIF9hcmVBbGxVbmlxdWUoIHNyYyApICkge1xuXHRcdFx0cmV0dXJuIHNyYy5zbGljZSgpO1xuXHRcdH1cblx0XG5cdFx0Ly8gQSBmYXN0ZXIgdW5pcXVlIG1ldGhvZCBpcyB0byB1c2Ugb2JqZWN0IGtleXMgdG8gaWRlbnRpZnkgdXNlZCB2YWx1ZXMsXG5cdFx0Ly8gYnV0IHRoaXMgZG9lc24ndCB3b3JrIHdpdGggYXJyYXlzIG9yIG9iamVjdHMsIHdoaWNoIHdlIG11c3QgYWxzb1xuXHRcdC8vIGNvbnNpZGVyLiBTZWUganNwZXJmLmNvbS9jb21wYXJlLWFycmF5LXVuaXF1ZS12ZXJzaW9ucy80IGZvciBtb3JlXG5cdFx0Ly8gaW5mb3JtYXRpb24uXG5cdFx0dmFyXG5cdFx0XHRvdXQgPSBbXSxcblx0XHRcdHZhbCxcblx0XHRcdGksIGllbj1zcmMubGVuZ3RoLFxuXHRcdFx0aiwgaz0wO1xuXHRcblx0XHRhZ2FpbjogZm9yICggaT0wIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHR2YWwgPSBzcmNbaV07XG5cdFxuXHRcdFx0Zm9yICggaj0wIDsgajxrIDsgaisrICkge1xuXHRcdFx0XHRpZiAoIG91dFtqXSA9PT0gdmFsICkge1xuXHRcdFx0XHRcdGNvbnRpbnVlIGFnYWluO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFxuXHRcdFx0b3V0LnB1c2goIHZhbCApO1xuXHRcdFx0aysrO1xuXHRcdH1cblx0XG5cdFx0cmV0dXJuIG91dDtcblx0fTtcblx0XG5cdFxuXHQvKipcblx0ICogRGF0YVRhYmxlcyB1dGlsaXR5IG1ldGhvZHNcblx0ICogXG5cdCAqIFRoaXMgbmFtZXNwYWNlIHByb3ZpZGVzIGhlbHBlciBtZXRob2RzIHRoYXQgRGF0YVRhYmxlcyB1c2VzIGludGVybmFsbHkgdG9cblx0ICogY3JlYXRlIGEgRGF0YVRhYmxlLCBidXQgd2hpY2ggYXJlIG5vdCBleGNsdXNpdmVseSB1c2VkIG9ubHkgZm9yIERhdGFUYWJsZXMuXG5cdCAqIFRoZXNlIG1ldGhvZHMgY2FuIGJlIHVzZWQgYnkgZXh0ZW5zaW9uIGF1dGhvcnMgdG8gc2F2ZSB0aGUgZHVwbGljYXRpb24gb2Zcblx0ICogY29kZS5cblx0ICpcblx0ICogIEBuYW1lc3BhY2Vcblx0ICovXG5cdERhdGFUYWJsZS51dGlsID0ge1xuXHRcdC8qKlxuXHRcdCAqIFRocm90dGxlIHRoZSBjYWxscyB0byBhIGZ1bmN0aW9uLiBBcmd1bWVudHMgYW5kIGNvbnRleHQgYXJlIG1haW50YWluZWRcblx0XHQgKiBmb3IgdGhlIHRocm90dGxlZCBmdW5jdGlvbi5cblx0XHQgKlxuXHRcdCAqIEBwYXJhbSB7ZnVuY3Rpb259IGZuIEZ1bmN0aW9uIHRvIGJlIGNhbGxlZFxuXHRcdCAqIEBwYXJhbSB7aW50ZWdlcn0gZnJlcSBDYWxsIGZyZXF1ZW5jeSBpbiBtU1xuXHRcdCAqIEByZXR1cm4ge2Z1bmN0aW9ufSBXcmFwcGVkIGZ1bmN0aW9uXG5cdFx0ICovXG5cdFx0dGhyb3R0bGU6IGZ1bmN0aW9uICggZm4sIGZyZXEgKSB7XG5cdFx0XHR2YXJcblx0XHRcdFx0ZnJlcXVlbmN5ID0gZnJlcSAhPT0gdW5kZWZpbmVkID8gZnJlcSA6IDIwMCxcblx0XHRcdFx0bGFzdCxcblx0XHRcdFx0dGltZXI7XG5cdFxuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0dmFyXG5cdFx0XHRcdFx0dGhhdCA9IHRoaXMsXG5cdFx0XHRcdFx0bm93ICA9ICtuZXcgRGF0ZSgpLFxuXHRcdFx0XHRcdGFyZ3MgPSBhcmd1bWVudHM7XG5cdFxuXHRcdFx0XHRpZiAoIGxhc3QgJiYgbm93IDwgbGFzdCArIGZyZXF1ZW5jeSApIHtcblx0XHRcdFx0XHRjbGVhclRpbWVvdXQoIHRpbWVyICk7XG5cdFxuXHRcdFx0XHRcdHRpbWVyID0gc2V0VGltZW91dCggZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0bGFzdCA9IHVuZGVmaW5lZDtcblx0XHRcdFx0XHRcdGZuLmFwcGx5KCB0aGF0LCBhcmdzICk7XG5cdFx0XHRcdFx0fSwgZnJlcXVlbmN5ICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0bGFzdCA9IG5vdztcblx0XHRcdFx0XHRmbi5hcHBseSggdGhhdCwgYXJncyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdH0sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBFc2NhcGUgYSBzdHJpbmcgc3VjaCB0aGF0IGl0IGNhbiBiZSB1c2VkIGluIGEgcmVndWxhciBleHByZXNzaW9uXG5cdFx0ICpcblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd9IHZhbCBzdHJpbmcgdG8gZXNjYXBlXG5cdFx0ICogIEByZXR1cm5zIHtzdHJpbmd9IGVzY2FwZWQgc3RyaW5nXG5cdFx0ICovXG5cdFx0ZXNjYXBlUmVnZXg6IGZ1bmN0aW9uICggdmFsICkge1xuXHRcdFx0cmV0dXJuIHZhbC5yZXBsYWNlKCBfcmVfZXNjYXBlX3JlZ2V4LCAnXFxcXCQxJyApO1xuXHRcdH1cblx0fTtcblx0XG5cdFxuXHRcblx0LyoqXG5cdCAqIENyZWF0ZSBhIG1hcHBpbmcgb2JqZWN0IHRoYXQgYWxsb3dzIGNhbWVsIGNhc2UgcGFyYW1ldGVycyB0byBiZSBsb29rZWQgdXBcblx0ICogZm9yIHRoZWlyIEh1bmdhcmlhbiBjb3VudGVycGFydHMuIFRoZSBtYXBwaW5nIGlzIHN0b3JlZCBpbiBhIHByaXZhdGVcblx0ICogcGFyYW1ldGVyIGNhbGxlZCBgX2h1bmdhcmlhbk1hcGAgd2hpY2ggY2FuIGJlIGFjY2Vzc2VkIG9uIHRoZSBzb3VyY2Ugb2JqZWN0LlxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9cblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuSHVuZ2FyaWFuTWFwICggbyApXG5cdHtcblx0XHR2YXJcblx0XHRcdGh1bmdhcmlhbiA9ICdhIGFhIGFpIGFvIGFzIGIgZm4gaSBtIG8gcyAnLFxuXHRcdFx0bWF0Y2gsXG5cdFx0XHRuZXdLZXksXG5cdFx0XHRtYXAgPSB7fTtcblx0XG5cdFx0JC5lYWNoKCBvLCBmdW5jdGlvbiAoa2V5LCB2YWwpIHtcblx0XHRcdG1hdGNoID0ga2V5Lm1hdGNoKC9eKFteQS1aXSs/KShbQS1aXSkvKTtcblx0XG5cdFx0XHRpZiAoIG1hdGNoICYmIGh1bmdhcmlhbi5pbmRleE9mKG1hdGNoWzFdKycgJykgIT09IC0xIClcblx0XHRcdHtcblx0XHRcdFx0bmV3S2V5ID0ga2V5LnJlcGxhY2UoIG1hdGNoWzBdLCBtYXRjaFsyXS50b0xvd2VyQ2FzZSgpICk7XG5cdFx0XHRcdG1hcFsgbmV3S2V5IF0gPSBrZXk7XG5cdFxuXHRcdFx0XHRpZiAoIG1hdGNoWzFdID09PSAnbycgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0X2ZuSHVuZ2FyaWFuTWFwKCBvW2tleV0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0gKTtcblx0XG5cdFx0by5faHVuZ2FyaWFuTWFwID0gbWFwO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIENvbnZlcnQgZnJvbSBjYW1lbCBjYXNlIHBhcmFtZXRlcnMgdG8gSHVuZ2FyaWFuLCBiYXNlZCBvbiBhIEh1bmdhcmlhbiBtYXBcblx0ICogY3JlYXRlZCBieSBfZm5IdW5nYXJpYW5NYXAuXG5cdCAqICBAcGFyYW0ge29iamVjdH0gc3JjIFRoZSBtb2RlbCBvYmplY3Qgd2hpY2ggaG9sZHMgYWxsIHBhcmFtZXRlcnMgdGhhdCBjYW4gYmVcblx0ICogICAgbWFwcGVkLlxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHVzZXIgVGhlIG9iamVjdCB0byBjb252ZXJ0IGZyb20gY2FtZWwgY2FzZSB0byBIdW5nYXJpYW4uXG5cdCAqICBAcGFyYW0ge2Jvb2xlYW59IGZvcmNlIFdoZW4gc2V0IHRvIGB0cnVlYCwgcHJvcGVydGllcyB3aGljaCBhbHJlYWR5IGhhdmUgYVxuXHQgKiAgICBIdW5nYXJpYW4gdmFsdWUgaW4gdGhlIGB1c2VyYCBvYmplY3Qgd2lsbCBiZSBvdmVyd3JpdHRlbi4gT3RoZXJ3aXNlIHRoZXlcblx0ICogICAgd29uJ3QgYmUuXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkNhbWVsVG9IdW5nYXJpYW4gKCBzcmMsIHVzZXIsIGZvcmNlIClcblx0e1xuXHRcdGlmICggISBzcmMuX2h1bmdhcmlhbk1hcCApIHtcblx0XHRcdF9mbkh1bmdhcmlhbk1hcCggc3JjICk7XG5cdFx0fVxuXHRcblx0XHR2YXIgaHVuZ2FyaWFuS2V5O1xuXHRcblx0XHQkLmVhY2goIHVzZXIsIGZ1bmN0aW9uIChrZXksIHZhbCkge1xuXHRcdFx0aHVuZ2FyaWFuS2V5ID0gc3JjLl9odW5nYXJpYW5NYXBbIGtleSBdO1xuXHRcblx0XHRcdGlmICggaHVuZ2FyaWFuS2V5ICE9PSB1bmRlZmluZWQgJiYgKGZvcmNlIHx8IHVzZXJbaHVuZ2FyaWFuS2V5XSA9PT0gdW5kZWZpbmVkKSApXG5cdFx0XHR7XG5cdFx0XHRcdC8vIEZvciBvYmplY3RzLCB3ZSBuZWVkIHRvIGJ1enogZG93biBpbnRvIHRoZSBvYmplY3QgdG8gY29weSBwYXJhbWV0ZXJzXG5cdFx0XHRcdGlmICggaHVuZ2FyaWFuS2V5LmNoYXJBdCgwKSA9PT0gJ28nIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdC8vIENvcHkgdGhlIGNhbWVsQ2FzZSBvcHRpb25zIG92ZXIgdG8gdGhlIGh1bmdhcmlhblxuXHRcdFx0XHRcdGlmICggISB1c2VyWyBodW5nYXJpYW5LZXkgXSApIHtcblx0XHRcdFx0XHRcdHVzZXJbIGh1bmdhcmlhbktleSBdID0ge307XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdCQuZXh0ZW5kKCB0cnVlLCB1c2VyW2h1bmdhcmlhbktleV0sIHVzZXJba2V5XSApO1xuXHRcblx0XHRcdFx0XHRfZm5DYW1lbFRvSHVuZ2FyaWFuKCBzcmNbaHVuZ2FyaWFuS2V5XSwgdXNlcltodW5nYXJpYW5LZXldLCBmb3JjZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdHVzZXJbaHVuZ2FyaWFuS2V5XSA9IHVzZXJbIGtleSBdO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIExhbmd1YWdlIGNvbXBhdGliaWxpdHkgLSB3aGVuIGNlcnRhaW4gb3B0aW9ucyBhcmUgZ2l2ZW4sIGFuZCBvdGhlcnMgYXJlbid0LCB3ZVxuXHQgKiBuZWVkIHRvIGR1cGxpY2F0ZSB0aGUgdmFsdWVzIG92ZXIsIGluIG9yZGVyIHRvIHByb3ZpZGUgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcblx0ICogd2l0aCBvbGRlciBsYW5ndWFnZSBmaWxlcy5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuTGFuZ3VhZ2VDb21wYXQoIGxhbmcgKVxuXHR7XG5cdFx0dmFyIGRlZmF1bHRzID0gRGF0YVRhYmxlLmRlZmF1bHRzLm9MYW5ndWFnZTtcblx0XHR2YXIgemVyb1JlY29yZHMgPSBsYW5nLnNaZXJvUmVjb3Jkcztcblx0XG5cdFx0LyogQmFja3dhcmRzIGNvbXBhdGliaWxpdHkgLSBpZiB0aGVyZSBpcyBubyBzRW1wdHlUYWJsZSBnaXZlbiwgdGhlbiB1c2UgdGhlIHNhbWUgYXNcblx0XHQgKiBzWmVyb1JlY29yZHMgLSBhc3N1bWluZyB0aGF0IGlzIGdpdmVuLlxuXHRcdCAqL1xuXHRcdGlmICggISBsYW5nLnNFbXB0eVRhYmxlICYmIHplcm9SZWNvcmRzICYmXG5cdFx0XHRkZWZhdWx0cy5zRW1wdHlUYWJsZSA9PT0gXCJObyBkYXRhIGF2YWlsYWJsZSBpbiB0YWJsZVwiIClcblx0XHR7XG5cdFx0XHRfZm5NYXAoIGxhbmcsIGxhbmcsICdzWmVyb1JlY29yZHMnLCAnc0VtcHR5VGFibGUnICk7XG5cdFx0fVxuXHRcblx0XHQvKiBMaWtld2lzZSB3aXRoIGxvYWRpbmcgcmVjb3JkcyAqL1xuXHRcdGlmICggISBsYW5nLnNMb2FkaW5nUmVjb3JkcyAmJiB6ZXJvUmVjb3JkcyAmJlxuXHRcdFx0ZGVmYXVsdHMuc0xvYWRpbmdSZWNvcmRzID09PSBcIkxvYWRpbmcuLi5cIiApXG5cdFx0e1xuXHRcdFx0X2ZuTWFwKCBsYW5nLCBsYW5nLCAnc1plcm9SZWNvcmRzJywgJ3NMb2FkaW5nUmVjb3JkcycgKTtcblx0XHR9XG5cdFxuXHRcdC8vIE9sZCBwYXJhbWV0ZXIgbmFtZSBvZiB0aGUgdGhvdXNhbmRzIHNlcGFyYXRvciBtYXBwZWQgb250byB0aGUgbmV3XG5cdFx0aWYgKCBsYW5nLnNJbmZvVGhvdXNhbmRzICkge1xuXHRcdFx0bGFuZy5zVGhvdXNhbmRzID0gbGFuZy5zSW5mb1Rob3VzYW5kcztcblx0XHR9XG5cdFxuXHRcdHZhciBkZWNpbWFsID0gbGFuZy5zRGVjaW1hbDtcblx0XHRpZiAoIGRlY2ltYWwgKSB7XG5cdFx0XHRfYWRkTnVtZXJpY1NvcnQoIGRlY2ltYWwgKTtcblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogTWFwIG9uZSBwYXJhbWV0ZXIgb250byBhbm90aGVyXG5cdCAqICBAcGFyYW0ge29iamVjdH0gbyBPYmplY3QgdG8gbWFwXG5cdCAqICBAcGFyYW0geyp9IGtuZXcgVGhlIG5ldyBwYXJhbWV0ZXIgbmFtZVxuXHQgKiAgQHBhcmFtIHsqfSBvbGQgVGhlIG9sZCBwYXJhbWV0ZXIgbmFtZVxuXHQgKi9cblx0dmFyIF9mbkNvbXBhdE1hcCA9IGZ1bmN0aW9uICggbywga25ldywgb2xkICkge1xuXHRcdGlmICggb1sga25ldyBdICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRvWyBvbGQgXSA9IG9bIGtuZXcgXTtcblx0XHR9XG5cdH07XG5cdFxuXHRcblx0LyoqXG5cdCAqIFByb3ZpZGUgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgZm9yIHRoZSBtYWluIERUIG9wdGlvbnMuIE5vdGUgdGhhdCB0aGUgbmV3XG5cdCAqIG9wdGlvbnMgYXJlIG1hcHBlZCBvbnRvIHRoZSBvbGQgcGFyYW1ldGVycywgc28gdGhpcyBpcyBhbiBleHRlcm5hbCBpbnRlcmZhY2Vcblx0ICogY2hhbmdlIG9ubHkuXG5cdCAqICBAcGFyYW0ge29iamVjdH0gaW5pdCBPYmplY3QgdG8gbWFwXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5Db21wYXRPcHRzICggaW5pdCApXG5cdHtcblx0XHRfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlcmluZycsICAgICAgJ2JTb3J0JyApO1xuXHRcdF9mbkNvbXBhdE1hcCggaW5pdCwgJ29yZGVyTXVsdGknLCAgICAnYlNvcnRNdWx0aScgKTtcblx0XHRfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlckNsYXNzZXMnLCAgJ2JTb3J0Q2xhc3NlcycgKTtcblx0XHRfZm5Db21wYXRNYXAoIGluaXQsICdvcmRlckNlbGxzVG9wJywgJ2JTb3J0Q2VsbHNUb3AnICk7XG5cdFx0X2ZuQ29tcGF0TWFwKCBpbml0LCAnb3JkZXInLCAgICAgICAgICdhYVNvcnRpbmcnICk7XG5cdFx0X2ZuQ29tcGF0TWFwKCBpbml0LCAnb3JkZXJGaXhlZCcsICAgICdhYVNvcnRpbmdGaXhlZCcgKTtcblx0XHRfZm5Db21wYXRNYXAoIGluaXQsICdwYWdpbmcnLCAgICAgICAgJ2JQYWdpbmF0ZScgKTtcblx0XHRfZm5Db21wYXRNYXAoIGluaXQsICdwYWdpbmdUeXBlJywgICAgJ3NQYWdpbmF0aW9uVHlwZScgKTtcblx0XHRfZm5Db21wYXRNYXAoIGluaXQsICdwYWdlTGVuZ3RoJywgICAgJ2lEaXNwbGF5TGVuZ3RoJyApO1xuXHRcdF9mbkNvbXBhdE1hcCggaW5pdCwgJ3NlYXJjaGluZycsICAgICAnYkZpbHRlcicgKTtcblx0XG5cdFx0Ly8gQm9vbGVhbiBpbml0aWFsaXNhdGlvbiBvZiB4LXNjcm9sbGluZ1xuXHRcdGlmICggdHlwZW9mIGluaXQuc1Njcm9sbFggPT09ICdib29sZWFuJyApIHtcblx0XHRcdGluaXQuc1Njcm9sbFggPSBpbml0LnNTY3JvbGxYID8gJzEwMCUnIDogJyc7XG5cdFx0fVxuXHRcdGlmICggdHlwZW9mIGluaXQuc2Nyb2xsWCA9PT0gJ2Jvb2xlYW4nICkge1xuXHRcdFx0aW5pdC5zY3JvbGxYID0gaW5pdC5zY3JvbGxYID8gJzEwMCUnIDogJyc7XG5cdFx0fVxuXHRcblx0XHQvLyBDb2x1bW4gc2VhcmNoIG9iamVjdHMgYXJlIGluIGFuIGFycmF5LCBzbyBpdCBuZWVkcyB0byBiZSBjb252ZXJ0ZWRcblx0XHQvLyBlbGVtZW50IGJ5IGVsZW1lbnRcblx0XHR2YXIgc2VhcmNoQ29scyA9IGluaXQuYW9TZWFyY2hDb2xzO1xuXHRcblx0XHRpZiAoIHNlYXJjaENvbHMgKSB7XG5cdFx0XHRmb3IgKCB2YXIgaT0wLCBpZW49c2VhcmNoQ29scy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBzZWFyY2hDb2xzW2ldICkge1xuXHRcdFx0XHRcdF9mbkNhbWVsVG9IdW5nYXJpYW4oIERhdGFUYWJsZS5tb2RlbHMub1NlYXJjaCwgc2VhcmNoQ29sc1tpXSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFByb3ZpZGUgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgZm9yIGNvbHVtbiBvcHRpb25zLiBOb3RlIHRoYXQgdGhlIG5ldyBvcHRpb25zXG5cdCAqIGFyZSBtYXBwZWQgb250byB0aGUgb2xkIHBhcmFtZXRlcnMsIHNvIHRoaXMgaXMgYW4gZXh0ZXJuYWwgaW50ZXJmYWNlIGNoYW5nZVxuXHQgKiBvbmx5LlxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IGluaXQgT2JqZWN0IHRvIG1hcFxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQ29tcGF0Q29scyAoIGluaXQgKVxuXHR7XG5cdFx0X2ZuQ29tcGF0TWFwKCBpbml0LCAnb3JkZXJhYmxlJywgICAgICdiU29ydGFibGUnICk7XG5cdFx0X2ZuQ29tcGF0TWFwKCBpbml0LCAnb3JkZXJEYXRhJywgICAgICdhRGF0YVNvcnQnICk7XG5cdFx0X2ZuQ29tcGF0TWFwKCBpbml0LCAnb3JkZXJTZXF1ZW5jZScsICdhc1NvcnRpbmcnICk7XG5cdFx0X2ZuQ29tcGF0TWFwKCBpbml0LCAnb3JkZXJEYXRhVHlwZScsICdzb3J0RGF0YVR5cGUnICk7XG5cdFxuXHRcdC8vIG9yZGVyRGF0YSBjYW4gYmUgZ2l2ZW4gYXMgYW4gaW50ZWdlclxuXHRcdHZhciBkYXRhU29ydCA9IGluaXQuYURhdGFTb3J0O1xuXHRcdGlmICggdHlwZW9mIGRhdGFTb3J0ID09PSAnbnVtYmVyJyAmJiAhICQuaXNBcnJheSggZGF0YVNvcnQgKSApIHtcblx0XHRcdGluaXQuYURhdGFTb3J0ID0gWyBkYXRhU29ydCBdO1xuXHRcdH1cblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBCcm93c2VyIGZlYXR1cmUgZGV0ZWN0aW9uIGZvciBjYXBhYmlsaXRpZXMsIHF1aXJrc1xuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkJyb3dzZXJEZXRlY3QoIHNldHRpbmdzIClcblx0e1xuXHRcdC8vIFdlIGRvbid0IG5lZWQgdG8gZG8gdGhpcyBldmVyeSB0aW1lIERhdGFUYWJsZXMgaXMgY29uc3RydWN0ZWQsIHRoZSB2YWx1ZXNcblx0XHQvLyBjYWxjdWxhdGVkIGFyZSBzcGVjaWZpYyB0byB0aGUgYnJvd3NlciBhbmQgT1MgY29uZmlndXJhdGlvbiB3aGljaCB3ZVxuXHRcdC8vIGRvbid0IGV4cGVjdCB0byBjaGFuZ2UgYmV0d2VlbiBpbml0aWFsaXNhdGlvbnNcblx0XHRpZiAoICEgRGF0YVRhYmxlLl9fYnJvd3NlciApIHtcblx0XHRcdHZhciBicm93c2VyID0ge307XG5cdFx0XHREYXRhVGFibGUuX19icm93c2VyID0gYnJvd3Nlcjtcblx0XG5cdFx0XHQvLyBTY3JvbGxpbmcgZmVhdHVyZSAvIHF1aXJrcyBkZXRlY3Rpb25cblx0XHRcdHZhciBuID0gJCgnPGRpdi8+Jylcblx0XHRcdFx0LmNzcygge1xuXHRcdFx0XHRcdHBvc2l0aW9uOiAnZml4ZWQnLFxuXHRcdFx0XHRcdHRvcDogMCxcblx0XHRcdFx0XHRsZWZ0OiAkKHdpbmRvdykuc2Nyb2xsTGVmdCgpKi0xLCAvLyBhbGxvdyBmb3Igc2Nyb2xsaW5nXG5cdFx0XHRcdFx0aGVpZ2h0OiAxLFxuXHRcdFx0XHRcdHdpZHRoOiAxLFxuXHRcdFx0XHRcdG92ZXJmbG93OiAnaGlkZGVuJ1xuXHRcdFx0XHR9IClcblx0XHRcdFx0LmFwcGVuZChcblx0XHRcdFx0XHQkKCc8ZGl2Lz4nKVxuXHRcdFx0XHRcdFx0LmNzcygge1xuXHRcdFx0XHRcdFx0XHRwb3NpdGlvbjogJ2Fic29sdXRlJyxcblx0XHRcdFx0XHRcdFx0dG9wOiAxLFxuXHRcdFx0XHRcdFx0XHRsZWZ0OiAxLFxuXHRcdFx0XHRcdFx0XHR3aWR0aDogMTAwLFxuXHRcdFx0XHRcdFx0XHRvdmVyZmxvdzogJ3Njcm9sbCdcblx0XHRcdFx0XHRcdH0gKVxuXHRcdFx0XHRcdFx0LmFwcGVuZChcblx0XHRcdFx0XHRcdFx0JCgnPGRpdi8+Jylcblx0XHRcdFx0XHRcdFx0XHQuY3NzKCB7XG5cdFx0XHRcdFx0XHRcdFx0XHR3aWR0aDogJzEwMCUnLFxuXHRcdFx0XHRcdFx0XHRcdFx0aGVpZ2h0OiAxMFxuXHRcdFx0XHRcdFx0XHRcdH0gKVxuXHRcdFx0XHRcdFx0KVxuXHRcdFx0XHQpXG5cdFx0XHRcdC5hcHBlbmRUbyggJ2JvZHknICk7XG5cdFxuXHRcdFx0dmFyIG91dGVyID0gbi5jaGlsZHJlbigpO1xuXHRcdFx0dmFyIGlubmVyID0gb3V0ZXIuY2hpbGRyZW4oKTtcblx0XG5cdFx0XHQvLyBOdW1iZXJzIGJlbG93LCBpbiBvcmRlciwgYXJlOlxuXHRcdFx0Ly8gaW5uZXIub2Zmc2V0V2lkdGgsIGlubmVyLmNsaWVudFdpZHRoLCBvdXRlci5vZmZzZXRXaWR0aCwgb3V0ZXIuY2xpZW50V2lkdGhcblx0XHRcdC8vXG5cdFx0XHQvLyBJRTYgWFA6ICAgICAgICAgICAgICAgICAgICAgICAgICAgMTAwIDEwMCAxMDAgIDgzXG5cdFx0XHQvLyBJRTcgVmlzdGE6ICAgICAgICAgICAgICAgICAgICAgICAgMTAwIDEwMCAxMDAgIDgzXG5cdFx0XHQvLyBJRSA4KyBXaW5kb3dzOiAgICAgICAgICAgICAgICAgICAgIDgzICA4MyAxMDAgIDgzXG5cdFx0XHQvLyBFdmVyZ3JlZW4gV2luZG93czogICAgICAgICAgICAgICAgIDgzICA4MyAxMDAgIDgzXG5cdFx0XHQvLyBFdmVyZ3JlZW4gTWFjIHdpdGggc2Nyb2xsYmFyczogICAgIDg1ICA4NSAxMDAgIDg1XG5cdFx0XHQvLyBFdmVyZ3JlZW4gTWFjIHdpdGhvdXQgc2Nyb2xsYmFyczogMTAwIDEwMCAxMDAgMTAwXG5cdFxuXHRcdFx0Ly8gR2V0IHNjcm9sbGJhciB3aWR0aFxuXHRcdFx0YnJvd3Nlci5iYXJXaWR0aCA9IG91dGVyWzBdLm9mZnNldFdpZHRoIC0gb3V0ZXJbMF0uY2xpZW50V2lkdGg7XG5cdFxuXHRcdFx0Ly8gSUU2Lzcgd2lsbCBvdmVyc2l6ZSBhIHdpZHRoIDEwMCUgZWxlbWVudCBpbnNpZGUgYSBzY3JvbGxpbmcgZWxlbWVudCwgdG9cblx0XHRcdC8vIGluY2x1ZGUgdGhlIHdpZHRoIG9mIHRoZSBzY3JvbGxiYXIsIHdoaWxlIG90aGVyIGJyb3dzZXJzIGVuc3VyZSB0aGUgaW5uZXJcblx0XHRcdC8vIGVsZW1lbnQgaXMgY29udGFpbmVkIHdpdGhvdXQgZm9yY2luZyBzY3JvbGxpbmdcblx0XHRcdGJyb3dzZXIuYlNjcm9sbE92ZXJzaXplID0gaW5uZXJbMF0ub2Zmc2V0V2lkdGggPT09IDEwMCAmJiBvdXRlclswXS5jbGllbnRXaWR0aCAhPT0gMTAwO1xuXHRcblx0XHRcdC8vIEluIHJ0bCB0ZXh0IGxheW91dCwgc29tZSBicm93c2VycyAobW9zdCwgYnV0IG5vdCBhbGwpIHdpbGwgcGxhY2UgdGhlXG5cdFx0XHQvLyBzY3JvbGxiYXIgb24gdGhlIGxlZnQsIHJhdGhlciB0aGFuIHRoZSByaWdodC5cblx0XHRcdGJyb3dzZXIuYlNjcm9sbGJhckxlZnQgPSBNYXRoLnJvdW5kKCBpbm5lci5vZmZzZXQoKS5sZWZ0ICkgIT09IDE7XG5cdFxuXHRcdFx0Ly8gSUU4LSBkb24ndCBwcm92aWRlIGhlaWdodCBhbmQgd2lkdGggZm9yIGdldEJvdW5kaW5nQ2xpZW50UmVjdFxuXHRcdFx0YnJvd3Nlci5iQm91bmRpbmcgPSBuWzBdLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoID8gdHJ1ZSA6IGZhbHNlO1xuXHRcblx0XHRcdG4ucmVtb3ZlKCk7XG5cdFx0fVxuXHRcblx0XHQkLmV4dGVuZCggc2V0dGluZ3Mub0Jyb3dzZXIsIERhdGFUYWJsZS5fX2Jyb3dzZXIgKTtcblx0XHRzZXR0aW5ncy5vU2Nyb2xsLmlCYXJXaWR0aCA9IERhdGFUYWJsZS5fX2Jyb3dzZXIuYmFyV2lkdGg7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQXJyYXkucHJvdG90eXBlIHJlZHVjZVtSaWdodF0gbWV0aG9kLCB1c2VkIGZvciBicm93c2VycyB3aGljaCBkb24ndCBzdXBwb3J0XG5cdCAqIEpTIDEuNi4gRG9uZSB0aGlzIHdheSB0byByZWR1Y2UgY29kZSBzaXplLCBzaW5jZSB3ZSBpdGVyYXRlIGVpdGhlciB3YXlcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5SZWR1Y2UgKCB0aGF0LCBmbiwgaW5pdCwgc3RhcnQsIGVuZCwgaW5jIClcblx0e1xuXHRcdHZhclxuXHRcdFx0aSA9IHN0YXJ0LFxuXHRcdFx0dmFsdWUsXG5cdFx0XHRpc1NldCA9IGZhbHNlO1xuXHRcblx0XHRpZiAoIGluaXQgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHZhbHVlID0gaW5pdDtcblx0XHRcdGlzU2V0ID0gdHJ1ZTtcblx0XHR9XG5cdFxuXHRcdHdoaWxlICggaSAhPT0gZW5kICkge1xuXHRcdFx0aWYgKCAhIHRoYXQuaGFzT3duUHJvcGVydHkoaSkgKSB7XG5cdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0fVxuXHRcblx0XHRcdHZhbHVlID0gaXNTZXQgP1xuXHRcdFx0XHRmbiggdmFsdWUsIHRoYXRbaV0sIGksIHRoYXQgKSA6XG5cdFx0XHRcdHRoYXRbaV07XG5cdFxuXHRcdFx0aXNTZXQgPSB0cnVlO1xuXHRcdFx0aSArPSBpbmM7XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gdmFsdWU7XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBBZGQgYSBjb2x1bW4gdG8gdGhlIGxpc3QgdXNlZCBmb3IgdGhlIHRhYmxlIHdpdGggZGVmYXVsdCB2YWx1ZXNcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7bm9kZX0gblRoIFRoZSB0aCBlbGVtZW50IGZvciB0aGlzIGNvbHVtblxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5BZGRDb2x1bW4oIG9TZXR0aW5ncywgblRoIClcblx0e1xuXHRcdC8vIEFkZCBjb2x1bW4gdG8gYW9Db2x1bW5zIGFycmF5XG5cdFx0dmFyIG9EZWZhdWx0cyA9IERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW47XG5cdFx0dmFyIGlDb2wgPSBvU2V0dGluZ3MuYW9Db2x1bW5zLmxlbmd0aDtcblx0XHR2YXIgb0NvbCA9ICQuZXh0ZW5kKCB7fSwgRGF0YVRhYmxlLm1vZGVscy5vQ29sdW1uLCBvRGVmYXVsdHMsIHtcblx0XHRcdFwiblRoXCI6IG5UaCA/IG5UaCA6IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RoJyksXG5cdFx0XHRcInNUaXRsZVwiOiAgICBvRGVmYXVsdHMuc1RpdGxlICAgID8gb0RlZmF1bHRzLnNUaXRsZSAgICA6IG5UaCA/IG5UaC5pbm5lckhUTUwgOiAnJyxcblx0XHRcdFwiYURhdGFTb3J0XCI6IG9EZWZhdWx0cy5hRGF0YVNvcnQgPyBvRGVmYXVsdHMuYURhdGFTb3J0IDogW2lDb2xdLFxuXHRcdFx0XCJtRGF0YVwiOiBvRGVmYXVsdHMubURhdGEgPyBvRGVmYXVsdHMubURhdGEgOiBpQ29sLFxuXHRcdFx0aWR4OiBpQ29sXG5cdFx0fSApO1xuXHRcdG9TZXR0aW5ncy5hb0NvbHVtbnMucHVzaCggb0NvbCApO1xuXHRcblx0XHQvLyBBZGQgc2VhcmNoIG9iamVjdCBmb3IgY29sdW1uIHNwZWNpZmljIHNlYXJjaC4gTm90ZSB0aGF0IHRoZSBgc2VhcmNoQ29sc1sgaUNvbCBdYFxuXHRcdC8vIHBhc3NlZCBpbnRvIGV4dGVuZCBjYW4gYmUgdW5kZWZpbmVkLiBUaGlzIGFsbG93cyB0aGUgdXNlciB0byBnaXZlIGEgZGVmYXVsdFxuXHRcdC8vIHdpdGggb25seSBzb21lIG9mIHRoZSBwYXJhbWV0ZXJzIGRlZmluZWQsIGFuZCBhbHNvIG5vdCBnaXZlIGEgZGVmYXVsdFxuXHRcdHZhciBzZWFyY2hDb2xzID0gb1NldHRpbmdzLmFvUHJlU2VhcmNoQ29scztcblx0XHRzZWFyY2hDb2xzWyBpQ29sIF0gPSAkLmV4dGVuZCgge30sIERhdGFUYWJsZS5tb2RlbHMub1NlYXJjaCwgc2VhcmNoQ29sc1sgaUNvbCBdICk7XG5cdFxuXHRcdC8vIFVzZSB0aGUgZGVmYXVsdCBjb2x1bW4gb3B0aW9ucyBmdW5jdGlvbiB0byBpbml0aWFsaXNlIGNsYXNzZXMgZXRjXG5cdFx0X2ZuQ29sdW1uT3B0aW9ucyggb1NldHRpbmdzLCBpQ29sLCAkKG5UaCkuZGF0YSgpICk7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQXBwbHkgb3B0aW9ucyBmb3IgYSBjb2x1bW5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7aW50fSBpQ29sIGNvbHVtbiBpbmRleCB0byBjb25zaWRlclxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9PcHRpb25zIG9iamVjdCB3aXRoIHNUeXBlLCBiVmlzaWJsZSBhbmQgYlNlYXJjaGFibGUgZXRjXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkNvbHVtbk9wdGlvbnMoIG9TZXR0aW5ncywgaUNvbCwgb09wdGlvbnMgKVxuXHR7XG5cdFx0dmFyIG9Db2wgPSBvU2V0dGluZ3MuYW9Db2x1bW5zWyBpQ29sIF07XG5cdFx0dmFyIG9DbGFzc2VzID0gb1NldHRpbmdzLm9DbGFzc2VzO1xuXHRcdHZhciB0aCA9ICQob0NvbC5uVGgpO1xuXHRcblx0XHQvLyBUcnkgdG8gZ2V0IHdpZHRoIGluZm9ybWF0aW9uIGZyb20gdGhlIERPTS4gV2UgY2FuJ3QgZ2V0IGl0IGZyb20gQ1NTXG5cdFx0Ly8gYXMgd2UnZCBuZWVkIHRvIHBhcnNlIHRoZSBDU1Mgc3R5bGVzaGVldC4gYHdpZHRoYCBvcHRpb24gY2FuIG92ZXJyaWRlXG5cdFx0aWYgKCAhIG9Db2wuc1dpZHRoT3JpZyApIHtcblx0XHRcdC8vIFdpZHRoIGF0dHJpYnV0ZVxuXHRcdFx0b0NvbC5zV2lkdGhPcmlnID0gdGguYXR0cignd2lkdGgnKSB8fCBudWxsO1xuXHRcblx0XHRcdC8vIFN0eWxlIGF0dHJpYnV0ZVxuXHRcdFx0dmFyIHQgPSAodGguYXR0cignc3R5bGUnKSB8fCAnJykubWF0Y2goL3dpZHRoOlxccyooXFxkK1tweGVtJV0rKS8pO1xuXHRcdFx0aWYgKCB0ICkge1xuXHRcdFx0XHRvQ29sLnNXaWR0aE9yaWcgPSB0WzFdO1xuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0LyogVXNlciBzcGVjaWZpZWQgY29sdW1uIG9wdGlvbnMgKi9cblx0XHRpZiAoIG9PcHRpb25zICE9PSB1bmRlZmluZWQgJiYgb09wdGlvbnMgIT09IG51bGwgKVxuXHRcdHtcblx0XHRcdC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5XG5cdFx0XHRfZm5Db21wYXRDb2xzKCBvT3B0aW9ucyApO1xuXHRcblx0XHRcdC8vIE1hcCBjYW1lbCBjYXNlIHBhcmFtZXRlcnMgdG8gdGhlaXIgSHVuZ2FyaWFuIGNvdW50ZXJwYXJ0c1xuXHRcdFx0X2ZuQ2FtZWxUb0h1bmdhcmlhbiggRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbiwgb09wdGlvbnMgKTtcblx0XG5cdFx0XHQvKiBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBmb3IgbURhdGFQcm9wICovXG5cdFx0XHRpZiAoIG9PcHRpb25zLm1EYXRhUHJvcCAhPT0gdW5kZWZpbmVkICYmICFvT3B0aW9ucy5tRGF0YSApXG5cdFx0XHR7XG5cdFx0XHRcdG9PcHRpb25zLm1EYXRhID0gb09wdGlvbnMubURhdGFQcm9wO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggb09wdGlvbnMuc1R5cGUgKVxuXHRcdFx0e1xuXHRcdFx0XHRvQ29sLl9zTWFudWFsVHlwZSA9IG9PcHRpb25zLnNUeXBlO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIGBjbGFzc2AgaXMgYSByZXNlcnZlZCB3b3JkIGluIEphdmFzY3JpcHQsIHNvIHdlIG5lZWQgdG8gcHJvdmlkZVxuXHRcdFx0Ly8gdGhlIGFiaWxpdHkgdG8gdXNlIGEgdmFsaWQgbmFtZSBmb3IgdGhlIGNhbWVsIGNhc2UgaW5wdXRcblx0XHRcdGlmICggb09wdGlvbnMuY2xhc3NOYW1lICYmICEgb09wdGlvbnMuc0NsYXNzIClcblx0XHRcdHtcblx0XHRcdFx0b09wdGlvbnMuc0NsYXNzID0gb09wdGlvbnMuY2xhc3NOYW1lO1xuXHRcdFx0fVxuXHRcdFx0aWYgKCBvT3B0aW9ucy5zQ2xhc3MgKSB7XG5cdFx0XHRcdHRoLmFkZENsYXNzKCBvT3B0aW9ucy5zQ2xhc3MgKTtcblx0XHRcdH1cblx0XG5cdFx0XHQkLmV4dGVuZCggb0NvbCwgb09wdGlvbnMgKTtcblx0XHRcdF9mbk1hcCggb0NvbCwgb09wdGlvbnMsIFwic1dpZHRoXCIsIFwic1dpZHRoT3JpZ1wiICk7XG5cdFxuXHRcdFx0LyogaURhdGFTb3J0IHRvIGJlIGFwcGxpZWQgKGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5KSwgYnV0IGFEYXRhU29ydCB3aWxsIHRha2Vcblx0XHRcdCAqIHByaW9yaXR5IGlmIGRlZmluZWRcblx0XHRcdCAqL1xuXHRcdFx0aWYgKCBvT3B0aW9ucy5pRGF0YVNvcnQgIT09IHVuZGVmaW5lZCApXG5cdFx0XHR7XG5cdFx0XHRcdG9Db2wuYURhdGFTb3J0ID0gWyBvT3B0aW9ucy5pRGF0YVNvcnQgXTtcblx0XHRcdH1cblx0XHRcdF9mbk1hcCggb0NvbCwgb09wdGlvbnMsIFwiYURhdGFTb3J0XCIgKTtcblx0XHR9XG5cdFxuXHRcdC8qIENhY2hlIHRoZSBkYXRhIGdldCBhbmQgc2V0IGZ1bmN0aW9ucyBmb3Igc3BlZWQgKi9cblx0XHR2YXIgbURhdGFTcmMgPSBvQ29sLm1EYXRhO1xuXHRcdHZhciBtRGF0YSA9IF9mbkdldE9iamVjdERhdGFGbiggbURhdGFTcmMgKTtcblx0XHR2YXIgbVJlbmRlciA9IG9Db2wubVJlbmRlciA/IF9mbkdldE9iamVjdERhdGFGbiggb0NvbC5tUmVuZGVyICkgOiBudWxsO1xuXHRcblx0XHR2YXIgYXR0clRlc3QgPSBmdW5jdGlvbiggc3JjICkge1xuXHRcdFx0cmV0dXJuIHR5cGVvZiBzcmMgPT09ICdzdHJpbmcnICYmIHNyYy5pbmRleE9mKCdAJykgIT09IC0xO1xuXHRcdH07XG5cdFx0b0NvbC5fYkF0dHJTcmMgPSAkLmlzUGxhaW5PYmplY3QoIG1EYXRhU3JjICkgJiYgKFxuXHRcdFx0YXR0clRlc3QobURhdGFTcmMuc29ydCkgfHwgYXR0clRlc3QobURhdGFTcmMudHlwZSkgfHwgYXR0clRlc3QobURhdGFTcmMuZmlsdGVyKVxuXHRcdCk7XG5cdFx0b0NvbC5fc2V0dGVyID0gbnVsbDtcblx0XG5cdFx0b0NvbC5mbkdldERhdGEgPSBmdW5jdGlvbiAocm93RGF0YSwgdHlwZSwgbWV0YSkge1xuXHRcdFx0dmFyIGlubmVyRGF0YSA9IG1EYXRhKCByb3dEYXRhLCB0eXBlLCB1bmRlZmluZWQsIG1ldGEgKTtcblx0XG5cdFx0XHRyZXR1cm4gbVJlbmRlciAmJiB0eXBlID9cblx0XHRcdFx0bVJlbmRlciggaW5uZXJEYXRhLCB0eXBlLCByb3dEYXRhLCBtZXRhICkgOlxuXHRcdFx0XHRpbm5lckRhdGE7XG5cdFx0fTtcblx0XHRvQ29sLmZuU2V0RGF0YSA9IGZ1bmN0aW9uICggcm93RGF0YSwgdmFsLCBtZXRhICkge1xuXHRcdFx0cmV0dXJuIF9mblNldE9iamVjdERhdGFGbiggbURhdGFTcmMgKSggcm93RGF0YSwgdmFsLCBtZXRhICk7XG5cdFx0fTtcblx0XG5cdFx0Ly8gSW5kaWNhdGUgaWYgRGF0YVRhYmxlcyBzaG91bGQgcmVhZCBET00gZGF0YSBhcyBhbiBvYmplY3Qgb3IgYXJyYXlcblx0XHQvLyBVc2VkIGluIF9mbkdldFJvd0VsZW1lbnRzXG5cdFx0aWYgKCB0eXBlb2YgbURhdGFTcmMgIT09ICdudW1iZXInICkge1xuXHRcdFx0b1NldHRpbmdzLl9yb3dSZWFkT2JqZWN0ID0gdHJ1ZTtcblx0XHR9XG5cdFxuXHRcdC8qIEZlYXR1cmUgc29ydGluZyBvdmVycmlkZXMgY29sdW1uIHNwZWNpZmljIHdoZW4gb2ZmICovXG5cdFx0aWYgKCAhb1NldHRpbmdzLm9GZWF0dXJlcy5iU29ydCApXG5cdFx0e1xuXHRcdFx0b0NvbC5iU29ydGFibGUgPSBmYWxzZTtcblx0XHRcdHRoLmFkZENsYXNzKCBvQ2xhc3Nlcy5zU29ydGFibGVOb25lICk7IC8vIEhhdmUgdG8gYWRkIGNsYXNzIGhlcmUgYXMgb3JkZXIgZXZlbnQgaXNuJ3QgY2FsbGVkXG5cdFx0fVxuXHRcblx0XHQvKiBDaGVjayB0aGF0IHRoZSBjbGFzcyBhc3NpZ25tZW50IGlzIGNvcnJlY3QgZm9yIHNvcnRpbmcgKi9cblx0XHR2YXIgYkFzYyA9ICQuaW5BcnJheSgnYXNjJywgb0NvbC5hc1NvcnRpbmcpICE9PSAtMTtcblx0XHR2YXIgYkRlc2MgPSAkLmluQXJyYXkoJ2Rlc2MnLCBvQ29sLmFzU29ydGluZykgIT09IC0xO1xuXHRcdGlmICggIW9Db2wuYlNvcnRhYmxlIHx8ICghYkFzYyAmJiAhYkRlc2MpIClcblx0XHR7XG5cdFx0XHRvQ29sLnNTb3J0aW5nQ2xhc3MgPSBvQ2xhc3Nlcy5zU29ydGFibGVOb25lO1xuXHRcdFx0b0NvbC5zU29ydGluZ0NsYXNzSlVJID0gXCJcIjtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIGJBc2MgJiYgIWJEZXNjIClcblx0XHR7XG5cdFx0XHRvQ29sLnNTb3J0aW5nQ2xhc3MgPSBvQ2xhc3Nlcy5zU29ydGFibGVBc2M7XG5cdFx0XHRvQ29sLnNTb3J0aW5nQ2xhc3NKVUkgPSBvQ2xhc3Nlcy5zU29ydEpVSUFzY0FsbG93ZWQ7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCAhYkFzYyAmJiBiRGVzYyApXG5cdFx0e1xuXHRcdFx0b0NvbC5zU29ydGluZ0NsYXNzID0gb0NsYXNzZXMuc1NvcnRhYmxlRGVzYztcblx0XHRcdG9Db2wuc1NvcnRpbmdDbGFzc0pVSSA9IG9DbGFzc2VzLnNTb3J0SlVJRGVzY0FsbG93ZWQ7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHRvQ29sLnNTb3J0aW5nQ2xhc3MgPSBvQ2xhc3Nlcy5zU29ydGFibGU7XG5cdFx0XHRvQ29sLnNTb3J0aW5nQ2xhc3NKVUkgPSBvQ2xhc3Nlcy5zU29ydEpVSTtcblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQWRqdXN0IHRoZSB0YWJsZSBjb2x1bW4gd2lkdGhzIGZvciBuZXcgZGF0YS4gTm90ZTogeW91IHdvdWxkIHByb2JhYmx5IHdhbnQgdG9cblx0ICogZG8gYSByZWRyYXcgYWZ0ZXIgY2FsbGluZyB0aGlzIGZ1bmN0aW9uIVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkFkanVzdENvbHVtblNpemluZyAoIHNldHRpbmdzIClcblx0e1xuXHRcdC8qIE5vdCBpbnRlcmVzdGVkIGluIGRvaW5nIGNvbHVtbiB3aWR0aCBjYWxjdWxhdGlvbiBpZiBhdXRvLXdpZHRoIGlzIGRpc2FibGVkICovXG5cdFx0aWYgKCBzZXR0aW5ncy5vRmVhdHVyZXMuYkF1dG9XaWR0aCAhPT0gZmFsc2UgKVxuXHRcdHtcblx0XHRcdHZhciBjb2x1bW5zID0gc2V0dGluZ3MuYW9Db2x1bW5zO1xuXHRcblx0XHRcdF9mbkNhbGN1bGF0ZUNvbHVtbldpZHRocyggc2V0dGluZ3MgKTtcblx0XHRcdGZvciAoIHZhciBpPTAgLCBpTGVuPWNvbHVtbnMubGVuZ3RoIDsgaTxpTGVuIDsgaSsrIClcblx0XHRcdHtcblx0XHRcdFx0Y29sdW1uc1tpXS5uVGguc3R5bGUud2lkdGggPSBjb2x1bW5zW2ldLnNXaWR0aDtcblx0XHRcdH1cblx0XHR9XG5cdFxuXHRcdHZhciBzY3JvbGwgPSBzZXR0aW5ncy5vU2Nyb2xsO1xuXHRcdGlmICggc2Nyb2xsLnNZICE9PSAnJyB8fCBzY3JvbGwuc1ggIT09ICcnKVxuXHRcdHtcblx0XHRcdF9mblNjcm9sbERyYXcoIHNldHRpbmdzICk7XG5cdFx0fVxuXHRcblx0XHRfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCBudWxsLCAnY29sdW1uLXNpemluZycsIFtzZXR0aW5nc10gKTtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBDb3ZlcnQgdGhlIGluZGV4IG9mIGEgdmlzaWJsZSBjb2x1bW4gdG8gdGhlIGluZGV4IGluIHRoZSBkYXRhIGFycmF5ICh0YWtlIGFjY291bnRcblx0ICogb2YgaGlkZGVuIGNvbHVtbnMpXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge2ludH0gaU1hdGNoIFZpc2libGUgY29sdW1uIGluZGV4IHRvIGxvb2t1cFxuXHQgKiAgQHJldHVybnMge2ludH0gaSB0aGUgZGF0YSBpbmRleFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5WaXNpYmxlVG9Db2x1bW5JbmRleCggb1NldHRpbmdzLCBpTWF0Y2ggKVxuXHR7XG5cdFx0dmFyIGFpVmlzID0gX2ZuR2V0Q29sdW1ucyggb1NldHRpbmdzLCAnYlZpc2libGUnICk7XG5cdFxuXHRcdHJldHVybiB0eXBlb2YgYWlWaXNbaU1hdGNoXSA9PT0gJ251bWJlcicgP1xuXHRcdFx0YWlWaXNbaU1hdGNoXSA6XG5cdFx0XHRudWxsO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIENvdmVydCB0aGUgaW5kZXggb2YgYW4gaW5kZXggaW4gdGhlIGRhdGEgYXJyYXkgYW5kIGNvbnZlcnQgaXQgdG8gdGhlIHZpc2libGVcblx0ICogICBjb2x1bW4gaW5kZXggKHRha2UgYWNjb3VudCBvZiBoaWRkZW4gY29sdW1ucylcblx0ICogIEBwYXJhbSB7aW50fSBpTWF0Y2ggQ29sdW1uIGluZGV4IHRvIGxvb2t1cFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHJldHVybnMge2ludH0gaSB0aGUgZGF0YSBpbmRleFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5Db2x1bW5JbmRleFRvVmlzaWJsZSggb1NldHRpbmdzLCBpTWF0Y2ggKVxuXHR7XG5cdFx0dmFyIGFpVmlzID0gX2ZuR2V0Q29sdW1ucyggb1NldHRpbmdzLCAnYlZpc2libGUnICk7XG5cdFx0dmFyIGlQb3MgPSAkLmluQXJyYXkoIGlNYXRjaCwgYWlWaXMgKTtcblx0XG5cdFx0cmV0dXJuIGlQb3MgIT09IC0xID8gaVBvcyA6IG51bGw7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogR2V0IHRoZSBudW1iZXIgb2YgdmlzaWJsZSBjb2x1bW5zXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcmV0dXJucyB7aW50fSBpIHRoZSBudW1iZXIgb2YgdmlzaWJsZSBjb2x1bW5zXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mblZpc2JsZUNvbHVtbnMoIG9TZXR0aW5ncyApXG5cdHtcblx0XHR2YXIgdmlzID0gMDtcblx0XG5cdFx0Ly8gTm8gcmVkdWNlIGluIElFOCwgdXNlIGEgbG9vcCBmb3Igbm93XG5cdFx0JC5lYWNoKCBvU2V0dGluZ3MuYW9Db2x1bW5zLCBmdW5jdGlvbiAoIGksIGNvbCApIHtcblx0XHRcdGlmICggY29sLmJWaXNpYmxlICYmICQoY29sLm5UaCkuY3NzKCdkaXNwbGF5JykgIT09ICdub25lJyApIHtcblx0XHRcdFx0dmlzKys7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHRcblx0XHRyZXR1cm4gdmlzO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEdldCBhbiBhcnJheSBvZiBjb2x1bW4gaW5kZXhlcyB0aGF0IG1hdGNoIGEgZ2l2ZW4gcHJvcGVydHlcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7c3RyaW5nfSBzUGFyYW0gUGFyYW1ldGVyIGluIGFvQ29sdW1ucyB0byBsb29rIGZvciAtIHR5cGljYWxseVxuXHQgKiAgICBiVmlzaWJsZSBvciBiU2VhcmNoYWJsZVxuXHQgKiAgQHJldHVybnMge2FycmF5fSBBcnJheSBvZiBpbmRleGVzIHdpdGggbWF0Y2hlZCBwcm9wZXJ0aWVzXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkdldENvbHVtbnMoIG9TZXR0aW5ncywgc1BhcmFtIClcblx0e1xuXHRcdHZhciBhID0gW107XG5cdFxuXHRcdCQubWFwKCBvU2V0dGluZ3MuYW9Db2x1bW5zLCBmdW5jdGlvbih2YWwsIGkpIHtcblx0XHRcdGlmICggdmFsW3NQYXJhbV0gKSB7XG5cdFx0XHRcdGEucHVzaCggaSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0XG5cdFx0cmV0dXJuIGE7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQ2FsY3VsYXRlIHRoZSAndHlwZScgb2YgYSBjb2x1bW5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5Db2x1bW5UeXBlcyAoIHNldHRpbmdzIClcblx0e1xuXHRcdHZhciBjb2x1bW5zID0gc2V0dGluZ3MuYW9Db2x1bW5zO1xuXHRcdHZhciBkYXRhID0gc2V0dGluZ3MuYW9EYXRhO1xuXHRcdHZhciB0eXBlcyA9IERhdGFUYWJsZS5leHQudHlwZS5kZXRlY3Q7XG5cdFx0dmFyIGksIGllbiwgaiwgamVuLCBrLCBrZW47XG5cdFx0dmFyIGNvbCwgY2VsbCwgZGV0ZWN0ZWRUeXBlLCBjYWNoZTtcblx0XG5cdFx0Ly8gRm9yIGVhY2ggY29sdW1uLCBzcGluIG92ZXIgdGhlIFxuXHRcdGZvciAoIGk9MCwgaWVuPWNvbHVtbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRjb2wgPSBjb2x1bW5zW2ldO1xuXHRcdFx0Y2FjaGUgPSBbXTtcblx0XG5cdFx0XHRpZiAoICEgY29sLnNUeXBlICYmIGNvbC5fc01hbnVhbFR5cGUgKSB7XG5cdFx0XHRcdGNvbC5zVHlwZSA9IGNvbC5fc01hbnVhbFR5cGU7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggISBjb2wuc1R5cGUgKSB7XG5cdFx0XHRcdGZvciAoIGo9MCwgamVuPXR5cGVzLmxlbmd0aCA7IGo8amVuIDsgaisrICkge1xuXHRcdFx0XHRcdGZvciAoIGs9MCwga2VuPWRhdGEubGVuZ3RoIDsgazxrZW4gOyBrKysgKSB7XG5cdFx0XHRcdFx0XHQvLyBVc2UgYSBjYWNoZSBhcnJheSBzbyB3ZSBvbmx5IG5lZWQgdG8gZ2V0IHRoZSB0eXBlIGRhdGFcblx0XHRcdFx0XHRcdC8vIGZyb20gdGhlIGZvcm1hdHRlciBvbmNlICh3aGVuIHVzaW5nIG11bHRpcGxlIGRldGVjdG9ycylcblx0XHRcdFx0XHRcdGlmICggY2FjaGVba10gPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRcdFx0Y2FjaGVba10gPSBfZm5HZXRDZWxsRGF0YSggc2V0dGluZ3MsIGssIGksICd0eXBlJyApO1xuXHRcdFx0XHRcdFx0fVxuXHRcblx0XHRcdFx0XHRcdGRldGVjdGVkVHlwZSA9IHR5cGVzW2pdKCBjYWNoZVtrXSwgc2V0dGluZ3MgKTtcblx0XG5cdFx0XHRcdFx0XHQvLyBJZiBudWxsLCB0aGVuIHRoaXMgdHlwZSBjYW4ndCBhcHBseSB0byB0aGlzIGNvbHVtbiwgc29cblx0XHRcdFx0XHRcdC8vIHJhdGhlciB0aGFuIHRlc3RpbmcgYWxsIGNlbGxzLCBicmVhayBvdXQuIFRoZXJlIGlzIGFuXG5cdFx0XHRcdFx0XHQvLyBleGNlcHRpb24gZm9yIHRoZSBsYXN0IHR5cGUgd2hpY2ggaXMgYGh0bWxgLiBXZSBuZWVkIHRvXG5cdFx0XHRcdFx0XHQvLyBzY2FuIGFsbCByb3dzIHNpbmNlIGl0IGlzIHBvc3NpYmxlIHRvIG1peCBzdHJpbmcgYW5kIEhUTUxcblx0XHRcdFx0XHRcdC8vIHR5cGVzXG5cdFx0XHRcdFx0XHRpZiAoICEgZGV0ZWN0ZWRUeXBlICYmIGogIT09IHR5cGVzLmxlbmd0aC0xICkge1xuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0XHQvLyBPbmx5IGEgc2luZ2xlIG1hdGNoIGlzIG5lZWRlZCBmb3IgaHRtbCB0eXBlIHNpbmNlIGl0IGlzXG5cdFx0XHRcdFx0XHQvLyBib3R0b20gb2YgdGhlIHBpbGUgYW5kIHZlcnkgc2ltaWxhciB0byBzdHJpbmdcblx0XHRcdFx0XHRcdGlmICggZGV0ZWN0ZWRUeXBlID09PSAnaHRtbCcgKSB7XG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0Ly8gVHlwZSBpcyB2YWxpZCBmb3IgYWxsIGRhdGEgcG9pbnRzIGluIHRoZSBjb2x1bW4gLSB1c2UgdGhpc1xuXHRcdFx0XHRcdC8vIHR5cGVcblx0XHRcdFx0XHRpZiAoIGRldGVjdGVkVHlwZSApIHtcblx0XHRcdFx0XHRcdGNvbC5zVHlwZSA9IGRldGVjdGVkVHlwZTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0Ly8gRmFsbCBiYWNrIC0gaWYgbm8gdHlwZSB3YXMgZGV0ZWN0ZWQsIGFsd2F5cyB1c2Ugc3RyaW5nXG5cdFx0XHRcdGlmICggISBjb2wuc1R5cGUgKSB7XG5cdFx0XHRcdFx0Y29sLnNUeXBlID0gJ3N0cmluZyc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogVGFrZSB0aGUgY29sdW1uIGRlZmluaXRpb25zIGFuZCBzdGF0aWMgY29sdW1ucyBhcnJheXMgYW5kIGNhbGN1bGF0ZSBob3dcblx0ICogdGhleSByZWxhdGUgdG8gY29sdW1uIGluZGV4ZXMuIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB3aWxsIHRoZW4gYXBwbHkgdGhlXG5cdCAqIGRlZmluaXRpb24gZm91bmQgZm9yIGEgY29sdW1uIHRvIGEgc3VpdGFibGUgY29uZmlndXJhdGlvbiBvYmplY3QuXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge2FycmF5fSBhb0NvbERlZnMgVGhlIGFvQ29sdW1uRGVmcyBhcnJheSB0aGF0IGlzIHRvIGJlIGFwcGxpZWRcblx0ICogIEBwYXJhbSB7YXJyYXl9IGFvQ29scyBUaGUgYW9Db2x1bW5zIGFycmF5IHRoYXQgZGVmaW5lcyBjb2x1bW5zIGluZGl2aWR1YWxseVxuXHQgKiAgQHBhcmFtIHtmdW5jdGlvbn0gZm4gQ2FsbGJhY2sgZnVuY3Rpb24gLSB0YWtlcyB0d28gcGFyYW1ldGVycywgdGhlIGNhbGN1bGF0ZWRcblx0ICogICAgY29sdW1uIGluZGV4IGFuZCB0aGUgZGVmaW5pdGlvbiBmb3IgdGhhdCBjb2x1bW4uXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkFwcGx5Q29sdW1uRGVmcyggb1NldHRpbmdzLCBhb0NvbERlZnMsIGFvQ29scywgZm4gKVxuXHR7XG5cdFx0dmFyIGksIGlMZW4sIGosIGpMZW4sIGssIGtMZW4sIGRlZjtcblx0XHR2YXIgY29sdW1ucyA9IG9TZXR0aW5ncy5hb0NvbHVtbnM7XG5cdFxuXHRcdC8vIENvbHVtbiBkZWZpbml0aW9ucyB3aXRoIGFUYXJnZXRzXG5cdFx0aWYgKCBhb0NvbERlZnMgKVxuXHRcdHtcblx0XHRcdC8qIExvb3Agb3ZlciB0aGUgZGVmaW5pdGlvbnMgYXJyYXkgLSBsb29wIGluIHJldmVyc2Ugc28gZmlyc3QgaW5zdGFuY2UgaGFzIHByaW9yaXR5ICovXG5cdFx0XHRmb3IgKCBpPWFvQ29sRGVmcy5sZW5ndGgtMSA7IGk+PTAgOyBpLS0gKVxuXHRcdFx0e1xuXHRcdFx0XHRkZWYgPSBhb0NvbERlZnNbaV07XG5cdFxuXHRcdFx0XHQvKiBFYWNoIGRlZmluaXRpb24gY2FuIHRhcmdldCBtdWx0aXBsZSBjb2x1bW5zLCBhcyBpdCBpcyBhbiBhcnJheSAqL1xuXHRcdFx0XHR2YXIgYVRhcmdldHMgPSBkZWYudGFyZ2V0cyAhPT0gdW5kZWZpbmVkID9cblx0XHRcdFx0XHRkZWYudGFyZ2V0cyA6XG5cdFx0XHRcdFx0ZGVmLmFUYXJnZXRzO1xuXHRcblx0XHRcdFx0aWYgKCAhICQuaXNBcnJheSggYVRhcmdldHMgKSApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRhVGFyZ2V0cyA9IFsgYVRhcmdldHMgXTtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0Zm9yICggaj0wLCBqTGVuPWFUYXJnZXRzLmxlbmd0aCA7IGo8akxlbiA7IGorKyApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZiAoIHR5cGVvZiBhVGFyZ2V0c1tqXSA9PT0gJ251bWJlcicgJiYgYVRhcmdldHNbal0gPj0gMCApXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0LyogQWRkIGNvbHVtbnMgdGhhdCB3ZSBkb24ndCB5ZXQga25vdyBhYm91dCAqL1xuXHRcdFx0XHRcdFx0d2hpbGUoIGNvbHVtbnMubGVuZ3RoIDw9IGFUYXJnZXRzW2pdIClcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0X2ZuQWRkQ29sdW1uKCBvU2V0dGluZ3MgKTtcblx0XHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0XHQvKiBJbnRlZ2VyLCBiYXNpYyBpbmRleCAqL1xuXHRcdFx0XHRcdFx0Zm4oIGFUYXJnZXRzW2pdLCBkZWYgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZiAoIHR5cGVvZiBhVGFyZ2V0c1tqXSA9PT0gJ251bWJlcicgJiYgYVRhcmdldHNbal0gPCAwIClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHQvKiBOZWdhdGl2ZSBpbnRlZ2VyLCByaWdodCB0byBsZWZ0IGNvbHVtbiBjb3VudGluZyAqL1xuXHRcdFx0XHRcdFx0Zm4oIGNvbHVtbnMubGVuZ3RoK2FUYXJnZXRzW2pdLCBkZWYgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZiAoIHR5cGVvZiBhVGFyZ2V0c1tqXSA9PT0gJ3N0cmluZycgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdC8qIENsYXNzIG5hbWUgbWF0Y2hpbmcgb24gVEggZWxlbWVudCAqL1xuXHRcdFx0XHRcdFx0Zm9yICggaz0wLCBrTGVuPWNvbHVtbnMubGVuZ3RoIDsgazxrTGVuIDsgaysrIClcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0aWYgKCBhVGFyZ2V0c1tqXSA9PSBcIl9hbGxcIiB8fFxuXHRcdFx0XHRcdFx0XHQgICAgICQoY29sdW1uc1trXS5uVGgpLmhhc0NsYXNzKCBhVGFyZ2V0c1tqXSApIClcblx0XHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRcdGZuKCBrLCBkZWYgKTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0Ly8gU3RhdGljYWxseSBkZWZpbmVkIGNvbHVtbnMgYXJyYXlcblx0XHRpZiAoIGFvQ29scyApXG5cdFx0e1xuXHRcdFx0Zm9yICggaT0wLCBpTGVuPWFvQ29scy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKVxuXHRcdFx0e1xuXHRcdFx0XHRmbiggaSwgYW9Db2xzW2ldICk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cdFxuXHQvKipcblx0ICogQWRkIGEgZGF0YSBhcnJheSB0byB0aGUgdGFibGUsIGNyZWF0aW5nIERPTSBub2RlIGV0Yy4gVGhpcyBpcyB0aGUgcGFyYWxsZWwgdG9cblx0ICogX2ZuR2F0aGVyRGF0YSwgYnV0IGZvciBhZGRpbmcgcm93cyBmcm9tIGEgSmF2YXNjcmlwdCBzb3VyY2UsIHJhdGhlciB0aGFuIGFcblx0ICogRE9NIHNvdXJjZS5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7YXJyYXl9IGFEYXRhIGRhdGEgYXJyYXkgdG8gYmUgYWRkZWRcblx0ICogIEBwYXJhbSB7bm9kZX0gW25Ucl0gVFIgZWxlbWVudCB0byBhZGQgdG8gdGhlIHRhYmxlIC0gb3B0aW9uYWwuIElmIG5vdCBnaXZlbixcblx0ICogICAgRGF0YVRhYmxlcyB3aWxsIGNyZWF0ZSBhIHJvdyBhdXRvbWF0aWNhbGx5XG5cdCAqICBAcGFyYW0ge2FycmF5fSBbYW5UZHNdIEFycmF5IG9mIFREfFRIIGVsZW1lbnRzIGZvciB0aGUgcm93IC0gbXVzdCBiZSBnaXZlblxuXHQgKiAgICBpZiBuVHIgaXMuXG5cdCAqICBAcmV0dXJucyB7aW50fSA+PTAgaWYgc3VjY2Vzc2Z1bCAoaW5kZXggb2YgbmV3IGFvRGF0YSBlbnRyeSksIC0xIGlmIGZhaWxlZFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5BZGREYXRhICggb1NldHRpbmdzLCBhRGF0YUluLCBuVHIsIGFuVGRzIClcblx0e1xuXHRcdC8qIENyZWF0ZSB0aGUgb2JqZWN0IGZvciBzdG9yaW5nIGluZm9ybWF0aW9uIGFib3V0IHRoaXMgbmV3IHJvdyAqL1xuXHRcdHZhciBpUm93ID0gb1NldHRpbmdzLmFvRGF0YS5sZW5ndGg7XG5cdFx0dmFyIG9EYXRhID0gJC5leHRlbmQoIHRydWUsIHt9LCBEYXRhVGFibGUubW9kZWxzLm9Sb3csIHtcblx0XHRcdHNyYzogblRyID8gJ2RvbScgOiAnZGF0YScsXG5cdFx0XHRpZHg6IGlSb3dcblx0XHR9ICk7XG5cdFxuXHRcdG9EYXRhLl9hRGF0YSA9IGFEYXRhSW47XG5cdFx0b1NldHRpbmdzLmFvRGF0YS5wdXNoKCBvRGF0YSApO1xuXHRcblx0XHQvKiBDcmVhdGUgdGhlIGNlbGxzICovXG5cdFx0dmFyIG5UZCwgc1RoaXNUeXBlO1xuXHRcdHZhciBjb2x1bW5zID0gb1NldHRpbmdzLmFvQ29sdW1ucztcblx0XG5cdFx0Ly8gSW52YWxpZGF0ZSB0aGUgY29sdW1uIHR5cGVzIGFzIHRoZSBuZXcgZGF0YSBuZWVkcyB0byBiZSByZXZhbGlkYXRlZFxuXHRcdGZvciAoIHZhciBpPTAsIGlMZW49Y29sdW1ucy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKVxuXHRcdHtcblx0XHRcdGNvbHVtbnNbaV0uc1R5cGUgPSBudWxsO1xuXHRcdH1cblx0XG5cdFx0LyogQWRkIHRvIHRoZSBkaXNwbGF5IGFycmF5ICovXG5cdFx0b1NldHRpbmdzLmFpRGlzcGxheU1hc3Rlci5wdXNoKCBpUm93ICk7XG5cdFxuXHRcdHZhciBpZCA9IG9TZXR0aW5ncy5yb3dJZEZuKCBhRGF0YUluICk7XG5cdFx0aWYgKCBpZCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0b1NldHRpbmdzLmFJZHNbIGlkIF0gPSBvRGF0YTtcblx0XHR9XG5cdFxuXHRcdC8qIENyZWF0ZSB0aGUgRE9NIGluZm9ybWF0aW9uLCBvciByZWdpc3RlciBpdCBpZiBhbHJlYWR5IHByZXNlbnQgKi9cblx0XHRpZiAoIG5UciB8fCAhIG9TZXR0aW5ncy5vRmVhdHVyZXMuYkRlZmVyUmVuZGVyIClcblx0XHR7XG5cdFx0XHRfZm5DcmVhdGVUciggb1NldHRpbmdzLCBpUm93LCBuVHIsIGFuVGRzICk7XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gaVJvdztcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBBZGQgb25lIG9yIG1vcmUgVFIgZWxlbWVudHMgdG8gdGhlIHRhYmxlLiBHZW5lcmFsbHkgd2UnZCBleHBlY3QgdG9cblx0ICogdXNlIHRoaXMgZm9yIHJlYWRpbmcgZGF0YSBmcm9tIGEgRE9NIHNvdXJjZWQgdGFibGUsIGJ1dCBpdCBjb3VsZCBiZVxuXHQgKiB1c2VkIGZvciBhbiBUUiBlbGVtZW50LiBOb3RlIHRoYXQgaWYgYSBUUiBpcyBnaXZlbiwgaXQgaXMgdXNlZCAoaS5lLlxuXHQgKiBpdCBpcyBub3QgY2xvbmVkKS5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHthcnJheXxub2RlfGpRdWVyeX0gdHJzIFRoZSBUUiBlbGVtZW50KHMpIHRvIGFkZCB0byB0aGUgdGFibGVcblx0ICogIEByZXR1cm5zIHthcnJheX0gQXJyYXkgb2YgaW5kZXhlcyBmb3IgdGhlIGFkZGVkIHJvd3Ncblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQWRkVHIoIHNldHRpbmdzLCB0cnMgKVxuXHR7XG5cdFx0dmFyIHJvdztcblx0XG5cdFx0Ly8gQWxsb3cgYW4gaW5kaXZpZHVhbCBub2RlIHRvIGJlIHBhc3NlZCBpblxuXHRcdGlmICggISAodHJzIGluc3RhbmNlb2YgJCkgKSB7XG5cdFx0XHR0cnMgPSAkKHRycyk7XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gdHJzLm1hcCggZnVuY3Rpb24gKGksIGVsKSB7XG5cdFx0XHRyb3cgPSBfZm5HZXRSb3dFbGVtZW50cyggc2V0dGluZ3MsIGVsICk7XG5cdFx0XHRyZXR1cm4gX2ZuQWRkRGF0YSggc2V0dGluZ3MsIHJvdy5kYXRhLCBlbCwgcm93LmNlbGxzICk7XG5cdFx0fSApO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFRha2UgYSBUUiBlbGVtZW50IGFuZCBjb252ZXJ0IGl0IHRvIGFuIGluZGV4IGluIGFvRGF0YVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtub2RlfSBuIHRoZSBUUiBlbGVtZW50IHRvIGZpbmRcblx0ICogIEByZXR1cm5zIHtpbnR9IGluZGV4IGlmIHRoZSBub2RlIGlzIGZvdW5kLCBudWxsIGlmIG5vdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5Ob2RlVG9EYXRhSW5kZXgoIG9TZXR0aW5ncywgbiApXG5cdHtcblx0XHRyZXR1cm4gKG4uX0RUX1Jvd0luZGV4IT09dW5kZWZpbmVkKSA/IG4uX0RUX1Jvd0luZGV4IDogbnVsbDtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBUYWtlIGEgVEQgZWxlbWVudCBhbmQgY29udmVydCBpdCBpbnRvIGEgY29sdW1uIGRhdGEgaW5kZXggKG5vdCB0aGUgdmlzaWJsZSBpbmRleClcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7aW50fSBpUm93IFRoZSByb3cgbnVtYmVyIHRoZSBURC9USCBjYW4gYmUgZm91bmQgaW5cblx0ICogIEBwYXJhbSB7bm9kZX0gbiBUaGUgVEQvVEggZWxlbWVudCB0byBmaW5kXG5cdCAqICBAcmV0dXJucyB7aW50fSBpbmRleCBpZiB0aGUgbm9kZSBpcyBmb3VuZCwgLTEgaWYgbm90XG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbk5vZGVUb0NvbHVtbkluZGV4KCBvU2V0dGluZ3MsIGlSb3csIG4gKVxuXHR7XG5cdFx0cmV0dXJuICQuaW5BcnJheSggbiwgb1NldHRpbmdzLmFvRGF0YVsgaVJvdyBdLmFuQ2VsbHMgKTtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBHZXQgdGhlIGRhdGEgZm9yIGEgZ2l2ZW4gY2VsbCBmcm9tIHRoZSBpbnRlcm5hbCBjYWNoZSwgdGFraW5nIGludG8gYWNjb3VudCBkYXRhIG1hcHBpbmdcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtpbnR9IHJvd0lkeCBhb0RhdGEgcm93IGlkXG5cdCAqICBAcGFyYW0ge2ludH0gY29sSWR4IENvbHVtbiBpbmRleFxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IHR5cGUgZGF0YSBnZXQgdHlwZSAoJ2Rpc3BsYXknLCAndHlwZScgJ2ZpbHRlcicgJ3NvcnQnKVxuXHQgKiAgQHJldHVybnMgeyp9IENlbGwgZGF0YVxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5HZXRDZWxsRGF0YSggc2V0dGluZ3MsIHJvd0lkeCwgY29sSWR4LCB0eXBlIClcblx0e1xuXHRcdHZhciBkcmF3ICAgICAgICAgICA9IHNldHRpbmdzLmlEcmF3O1xuXHRcdHZhciBjb2wgICAgICAgICAgICA9IHNldHRpbmdzLmFvQ29sdW1uc1tjb2xJZHhdO1xuXHRcdHZhciByb3dEYXRhICAgICAgICA9IHNldHRpbmdzLmFvRGF0YVtyb3dJZHhdLl9hRGF0YTtcblx0XHR2YXIgZGVmYXVsdENvbnRlbnQgPSBjb2wuc0RlZmF1bHRDb250ZW50O1xuXHRcdHZhciBjZWxsRGF0YSAgICAgICA9IGNvbC5mbkdldERhdGEoIHJvd0RhdGEsIHR5cGUsIHtcblx0XHRcdHNldHRpbmdzOiBzZXR0aW5ncyxcblx0XHRcdHJvdzogICAgICByb3dJZHgsXG5cdFx0XHRjb2w6ICAgICAgY29sSWR4XG5cdFx0fSApO1xuXHRcblx0XHRpZiAoIGNlbGxEYXRhID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRpZiAoIHNldHRpbmdzLmlEcmF3RXJyb3IgIT0gZHJhdyAmJiBkZWZhdWx0Q29udGVudCA9PT0gbnVsbCApIHtcblx0XHRcdFx0X2ZuTG9nKCBzZXR0aW5ncywgMCwgXCJSZXF1ZXN0ZWQgdW5rbm93biBwYXJhbWV0ZXIgXCIrXG5cdFx0XHRcdFx0KHR5cGVvZiBjb2wubURhdGE9PSdmdW5jdGlvbicgPyAne2Z1bmN0aW9ufScgOiBcIidcIitjb2wubURhdGErXCInXCIpK1xuXHRcdFx0XHRcdFwiIGZvciByb3cgXCIrcm93SWR4K1wiLCBjb2x1bW4gXCIrY29sSWR4LCA0ICk7XG5cdFx0XHRcdHNldHRpbmdzLmlEcmF3RXJyb3IgPSBkcmF3O1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGRlZmF1bHRDb250ZW50O1xuXHRcdH1cblx0XG5cdFx0Ly8gV2hlbiB0aGUgZGF0YSBzb3VyY2UgaXMgbnVsbCBhbmQgYSBzcGVjaWZpYyBkYXRhIHR5cGUgaXMgcmVxdWVzdGVkIChpLmUuXG5cdFx0Ly8gbm90IHRoZSBvcmlnaW5hbCBkYXRhKSwgd2UgY2FuIHVzZSBkZWZhdWx0IGNvbHVtbiBkYXRhXG5cdFx0aWYgKCAoY2VsbERhdGEgPT09IHJvd0RhdGEgfHwgY2VsbERhdGEgPT09IG51bGwpICYmIGRlZmF1bHRDb250ZW50ICE9PSBudWxsICYmIHR5cGUgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdGNlbGxEYXRhID0gZGVmYXVsdENvbnRlbnQ7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCB0eXBlb2YgY2VsbERhdGEgPT09ICdmdW5jdGlvbicgKSB7XG5cdFx0XHQvLyBJZiB0aGUgZGF0YSBzb3VyY2UgaXMgYSBmdW5jdGlvbiwgdGhlbiB3ZSBydW4gaXQgYW5kIHVzZSB0aGUgcmV0dXJuLFxuXHRcdFx0Ly8gZXhlY3V0aW5nIGluIHRoZSBzY29wZSBvZiB0aGUgZGF0YSBvYmplY3QgKGZvciBpbnN0YW5jZXMpXG5cdFx0XHRyZXR1cm4gY2VsbERhdGEuY2FsbCggcm93RGF0YSApO1xuXHRcdH1cblx0XG5cdFx0aWYgKCBjZWxsRGF0YSA9PT0gbnVsbCAmJiB0eXBlID09ICdkaXNwbGF5JyApIHtcblx0XHRcdHJldHVybiAnJztcblx0XHR9XG5cdFx0cmV0dXJuIGNlbGxEYXRhO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFNldCB0aGUgdmFsdWUgZm9yIGEgc3BlY2lmaWMgY2VsbCwgaW50byB0aGUgaW50ZXJuYWwgZGF0YSBjYWNoZVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge2ludH0gcm93SWR4IGFvRGF0YSByb3cgaWRcblx0ICogIEBwYXJhbSB7aW50fSBjb2xJZHggQ29sdW1uIGluZGV4XG5cdCAqICBAcGFyYW0geyp9IHZhbCBWYWx1ZSB0byBzZXRcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuU2V0Q2VsbERhdGEoIHNldHRpbmdzLCByb3dJZHgsIGNvbElkeCwgdmFsIClcblx0e1xuXHRcdHZhciBjb2wgICAgID0gc2V0dGluZ3MuYW9Db2x1bW5zW2NvbElkeF07XG5cdFx0dmFyIHJvd0RhdGEgPSBzZXR0aW5ncy5hb0RhdGFbcm93SWR4XS5fYURhdGE7XG5cdFxuXHRcdGNvbC5mblNldERhdGEoIHJvd0RhdGEsIHZhbCwge1xuXHRcdFx0c2V0dGluZ3M6IHNldHRpbmdzLFxuXHRcdFx0cm93OiAgICAgIHJvd0lkeCxcblx0XHRcdGNvbDogICAgICBjb2xJZHhcblx0XHR9ICApO1xuXHR9XG5cdFxuXHRcblx0Ly8gUHJpdmF0ZSB2YXJpYWJsZSB0aGF0IGlzIHVzZWQgdG8gbWF0Y2ggYWN0aW9uIHN5bnRheCBpbiB0aGUgZGF0YSBwcm9wZXJ0eSBvYmplY3Rcblx0dmFyIF9fcmVBcnJheSA9IC9cXFsuKj9cXF0kLztcblx0dmFyIF9fcmVGbiA9IC9cXChcXCkkLztcblx0XG5cdC8qKlxuXHQgKiBTcGxpdCBzdHJpbmcgb24gcGVyaW9kcywgdGFraW5nIGludG8gYWNjb3VudCBlc2NhcGVkIHBlcmlvZHNcblx0ICogQHBhcmFtICB7c3RyaW5nfSBzdHIgU3RyaW5nIHRvIHNwbGl0XG5cdCAqIEByZXR1cm4ge2FycmF5fSBTcGxpdCBzdHJpbmdcblx0ICovXG5cdGZ1bmN0aW9uIF9mblNwbGl0T2JqTm90YXRpb24oIHN0ciApXG5cdHtcblx0XHRyZXR1cm4gJC5tYXAoIHN0ci5tYXRjaCgvKFxcXFwufFteXFwuXSkrL2cpIHx8IFsnJ10sIGZ1bmN0aW9uICggcyApIHtcblx0XHRcdHJldHVybiBzLnJlcGxhY2UoL1xcXFxcXC4vZywgJy4nKTtcblx0XHR9ICk7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogUmV0dXJuIGEgZnVuY3Rpb24gdGhhdCBjYW4gYmUgdXNlZCB0byBnZXQgZGF0YSBmcm9tIGEgc291cmNlIG9iamVjdCwgdGFraW5nXG5cdCAqIGludG8gYWNjb3VudCB0aGUgYWJpbGl0eSB0byB1c2UgbmVzdGVkIG9iamVjdHMgYXMgYSBzb3VyY2Vcblx0ICogIEBwYXJhbSB7c3RyaW5nfGludHxmdW5jdGlvbn0gbVNvdXJjZSBUaGUgZGF0YSBzb3VyY2UgZm9yIHRoZSBvYmplY3Rcblx0ICogIEByZXR1cm5zIHtmdW5jdGlvbn0gRGF0YSBnZXQgZnVuY3Rpb25cblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuR2V0T2JqZWN0RGF0YUZuKCBtU291cmNlIClcblx0e1xuXHRcdGlmICggJC5pc1BsYWluT2JqZWN0KCBtU291cmNlICkgKVxuXHRcdHtcblx0XHRcdC8qIEJ1aWxkIGFuIG9iamVjdCBvZiBnZXQgZnVuY3Rpb25zLCBhbmQgd3JhcCB0aGVtIGluIGEgc2luZ2xlIGNhbGwgKi9cblx0XHRcdHZhciBvID0ge307XG5cdFx0XHQkLmVhY2goIG1Tb3VyY2UsIGZ1bmN0aW9uIChrZXksIHZhbCkge1xuXHRcdFx0XHRpZiAoIHZhbCApIHtcblx0XHRcdFx0XHRvW2tleV0gPSBfZm5HZXRPYmplY3REYXRhRm4oIHZhbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFxuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uIChkYXRhLCB0eXBlLCByb3csIG1ldGEpIHtcblx0XHRcdFx0dmFyIHQgPSBvW3R5cGVdIHx8IG8uXztcblx0XHRcdFx0cmV0dXJuIHQgIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRcdFx0dChkYXRhLCB0eXBlLCByb3csIG1ldGEpIDpcblx0XHRcdFx0XHRkYXRhO1xuXHRcdFx0fTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIG1Tb3VyY2UgPT09IG51bGwgKVxuXHRcdHtcblx0XHRcdC8qIEdpdmUgYW4gZW1wdHkgc3RyaW5nIGZvciByZW5kZXJpbmcgLyBzb3J0aW5nIGV0YyAqL1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uIChkYXRhKSB7IC8vIHR5cGUsIHJvdyBhbmQgbWV0YSBhbHNvIHBhc3NlZCwgYnV0IG5vdCB1c2VkXG5cdFx0XHRcdHJldHVybiBkYXRhO1xuXHRcdFx0fTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIHR5cGVvZiBtU291cmNlID09PSAnZnVuY3Rpb24nIClcblx0XHR7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKGRhdGEsIHR5cGUsIHJvdywgbWV0YSkge1xuXHRcdFx0XHRyZXR1cm4gbVNvdXJjZSggZGF0YSwgdHlwZSwgcm93LCBtZXRhICk7XG5cdFx0XHR9O1xuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIG1Tb3VyY2UgPT09ICdzdHJpbmcnICYmIChtU291cmNlLmluZGV4T2YoJy4nKSAhPT0gLTEgfHxcblx0XHRcdCAgICAgIG1Tb3VyY2UuaW5kZXhPZignWycpICE9PSAtMSB8fCBtU291cmNlLmluZGV4T2YoJygnKSAhPT0gLTEpIClcblx0XHR7XG5cdFx0XHQvKiBJZiB0aGVyZSBpcyBhIC4gaW4gdGhlIHNvdXJjZSBzdHJpbmcgdGhlbiB0aGUgZGF0YSBzb3VyY2UgaXMgaW4gYVxuXHRcdFx0ICogbmVzdGVkIG9iamVjdCBzbyB3ZSBsb29wIG92ZXIgdGhlIGRhdGEgZm9yIGVhY2ggbGV2ZWwgdG8gZ2V0IHRoZSBuZXh0XG5cdFx0XHQgKiBsZXZlbCBkb3duLiBPbiBlYWNoIGxvb3Agd2UgdGVzdCBmb3IgdW5kZWZpbmVkLCBhbmQgaWYgZm91bmQgaW1tZWRpYXRlbHlcblx0XHRcdCAqIHJldHVybi4gVGhpcyBhbGxvd3MgZW50aXJlIG9iamVjdHMgdG8gYmUgbWlzc2luZyBhbmQgc0RlZmF1bHRDb250ZW50IHRvXG5cdFx0XHQgKiBiZSB1c2VkIGlmIGRlZmluZWQsIHJhdGhlciB0aGFuIHRocm93aW5nIGFuIGVycm9yXG5cdFx0XHQgKi9cblx0XHRcdHZhciBmZXRjaERhdGEgPSBmdW5jdGlvbiAoZGF0YSwgdHlwZSwgc3JjKSB7XG5cdFx0XHRcdHZhciBhcnJheU5vdGF0aW9uLCBmdW5jTm90YXRpb24sIG91dCwgaW5uZXJTcmM7XG5cdFxuXHRcdFx0XHRpZiAoIHNyYyAhPT0gXCJcIiApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHR2YXIgYSA9IF9mblNwbGl0T2JqTm90YXRpb24oIHNyYyApO1xuXHRcblx0XHRcdFx0XHRmb3IgKCB2YXIgaT0wLCBpTGVuPWEubGVuZ3RoIDsgaTxpTGVuIDsgaSsrIClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHQvLyBDaGVjayBpZiB3ZSBhcmUgZGVhbGluZyB3aXRoIHNwZWNpYWwgbm90YXRpb25cblx0XHRcdFx0XHRcdGFycmF5Tm90YXRpb24gPSBhW2ldLm1hdGNoKF9fcmVBcnJheSk7XG5cdFx0XHRcdFx0XHRmdW5jTm90YXRpb24gPSBhW2ldLm1hdGNoKF9fcmVGbik7XG5cdFxuXHRcdFx0XHRcdFx0aWYgKCBhcnJheU5vdGF0aW9uIClcblx0XHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdFx0Ly8gQXJyYXkgbm90YXRpb25cblx0XHRcdFx0XHRcdFx0YVtpXSA9IGFbaV0ucmVwbGFjZShfX3JlQXJyYXksICcnKTtcblx0XG5cdFx0XHRcdFx0XHRcdC8vIENvbmRpdGlvbiBhbGxvd3Mgc2ltcGx5IFtdIHRvIGJlIHBhc3NlZCBpblxuXHRcdFx0XHRcdFx0XHRpZiAoIGFbaV0gIT09IFwiXCIgKSB7XG5cdFx0XHRcdFx0XHRcdFx0ZGF0YSA9IGRhdGFbIGFbaV0gXTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHRvdXQgPSBbXTtcblx0XG5cdFx0XHRcdFx0XHRcdC8vIEdldCB0aGUgcmVtYWluZGVyIG9mIHRoZSBuZXN0ZWQgb2JqZWN0IHRvIGdldFxuXHRcdFx0XHRcdFx0XHRhLnNwbGljZSggMCwgaSsxICk7XG5cdFx0XHRcdFx0XHRcdGlubmVyU3JjID0gYS5qb2luKCcuJyk7XG5cdFxuXHRcdFx0XHRcdFx0XHQvLyBUcmF2ZXJzZSBlYWNoIGVudHJ5IGluIHRoZSBhcnJheSBnZXR0aW5nIHRoZSBwcm9wZXJ0aWVzIHJlcXVlc3RlZFxuXHRcdFx0XHRcdFx0XHRpZiAoICQuaXNBcnJheSggZGF0YSApICkge1xuXHRcdFx0XHRcdFx0XHRcdGZvciAoIHZhciBqPTAsIGpMZW49ZGF0YS5sZW5ndGggOyBqPGpMZW4gOyBqKysgKSB7XG5cdFx0XHRcdFx0XHRcdFx0XHRvdXQucHVzaCggZmV0Y2hEYXRhKCBkYXRhW2pdLCB0eXBlLCBpbm5lclNyYyApICk7XG5cdFx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdFx0XHQvLyBJZiBhIHN0cmluZyBpcyBnaXZlbiBpbiBiZXR3ZWVuIHRoZSBhcnJheSBub3RhdGlvbiBpbmRpY2F0b3JzLCB0aGF0XG5cdFx0XHRcdFx0XHRcdC8vIGlzIHVzZWQgdG8gam9pbiB0aGUgc3RyaW5ncyB0b2dldGhlciwgb3RoZXJ3aXNlIGFuIGFycmF5IGlzIHJldHVybmVkXG5cdFx0XHRcdFx0XHRcdHZhciBqb2luID0gYXJyYXlOb3RhdGlvblswXS5zdWJzdHJpbmcoMSwgYXJyYXlOb3RhdGlvblswXS5sZW5ndGgtMSk7XG5cdFx0XHRcdFx0XHRcdGRhdGEgPSAoam9pbj09PVwiXCIpID8gb3V0IDogb3V0LmpvaW4oam9pbik7XG5cdFxuXHRcdFx0XHRcdFx0XHQvLyBUaGUgaW5uZXIgY2FsbCB0byBmZXRjaERhdGEgaGFzIGFscmVhZHkgdHJhdmVyc2VkIHRocm91Z2ggdGhlIHJlbWFpbmRlclxuXHRcdFx0XHRcdFx0XHQvLyBvZiB0aGUgc291cmNlIHJlcXVlc3RlZCwgc28gd2UgZXhpdCBmcm9tIHRoZSBsb29wXG5cdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZSBpZiAoIGZ1bmNOb3RhdGlvbiApXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdC8vIEZ1bmN0aW9uIGNhbGxcblx0XHRcdFx0XHRcdFx0YVtpXSA9IGFbaV0ucmVwbGFjZShfX3JlRm4sICcnKTtcblx0XHRcdFx0XHRcdFx0ZGF0YSA9IGRhdGFbIGFbaV0gXSgpO1xuXHRcdFx0XHRcdFx0XHRjb250aW51ZTtcblx0XHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0XHRpZiAoIGRhdGEgPT09IG51bGwgfHwgZGF0YVsgYVtpXSBdID09PSB1bmRlZmluZWQgKVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZGF0YSA9IGRhdGFbIGFbaV0gXTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdHJldHVybiBkYXRhO1xuXHRcdFx0fTtcblx0XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKGRhdGEsIHR5cGUpIHsgLy8gcm93IGFuZCBtZXRhIGFsc28gcGFzc2VkLCBidXQgbm90IHVzZWRcblx0XHRcdFx0cmV0dXJuIGZldGNoRGF0YSggZGF0YSwgdHlwZSwgbVNvdXJjZSApO1xuXHRcdFx0fTtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdC8qIEFycmF5IG9yIGZsYXQgb2JqZWN0IG1hcHBpbmcgKi9cblx0XHRcdHJldHVybiBmdW5jdGlvbiAoZGF0YSwgdHlwZSkgeyAvLyByb3cgYW5kIG1ldGEgYWxzbyBwYXNzZWQsIGJ1dCBub3QgdXNlZFxuXHRcdFx0XHRyZXR1cm4gZGF0YVttU291cmNlXTtcblx0XHRcdH07XG5cdFx0fVxuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFJldHVybiBhIGZ1bmN0aW9uIHRoYXQgY2FuIGJlIHVzZWQgdG8gc2V0IGRhdGEgZnJvbSBhIHNvdXJjZSBvYmplY3QsIHRha2luZ1xuXHQgKiBpbnRvIGFjY291bnQgdGhlIGFiaWxpdHkgdG8gdXNlIG5lc3RlZCBvYmplY3RzIGFzIGEgc291cmNlXG5cdCAqICBAcGFyYW0ge3N0cmluZ3xpbnR8ZnVuY3Rpb259IG1Tb3VyY2UgVGhlIGRhdGEgc291cmNlIGZvciB0aGUgb2JqZWN0XG5cdCAqICBAcmV0dXJucyB7ZnVuY3Rpb259IERhdGEgc2V0IGZ1bmN0aW9uXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mblNldE9iamVjdERhdGFGbiggbVNvdXJjZSApXG5cdHtcblx0XHRpZiAoICQuaXNQbGFpbk9iamVjdCggbVNvdXJjZSApIClcblx0XHR7XG5cdFx0XHQvKiBVbmxpa2UgZ2V0LCBvbmx5IHRoZSB1bmRlcnNjb3JlIChnbG9iYWwpIG9wdGlvbiBpcyB1c2VkIGZvciBmb3Jcblx0XHRcdCAqIHNldHRpbmcgZGF0YSBzaW5jZSB3ZSBkb24ndCBrbm93IHRoZSB0eXBlIGhlcmUuIFRoaXMgaXMgd2h5IGFuIG9iamVjdFxuXHRcdFx0ICogb3B0aW9uIGlzIG5vdCBkb2N1bWVudGVkIGZvciBgbURhdGFgICh3aGljaCBpcyByZWFkL3dyaXRlKSwgYnV0IGl0IGlzXG5cdFx0XHQgKiBmb3IgYG1SZW5kZXJgIHdoaWNoIGlzIHJlYWQgb25seS5cblx0XHRcdCAqL1xuXHRcdFx0cmV0dXJuIF9mblNldE9iamVjdERhdGFGbiggbVNvdXJjZS5fICk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCBtU291cmNlID09PSBudWxsIClcblx0XHR7XG5cdFx0XHQvKiBOb3RoaW5nIHRvIGRvIHdoZW4gdGhlIGRhdGEgc291cmNlIGlzIG51bGwgKi9cblx0XHRcdHJldHVybiBmdW5jdGlvbiAoKSB7fTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIHR5cGVvZiBtU291cmNlID09PSAnZnVuY3Rpb24nIClcblx0XHR7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKGRhdGEsIHZhbCwgbWV0YSkge1xuXHRcdFx0XHRtU291cmNlKCBkYXRhLCAnc2V0JywgdmFsLCBtZXRhICk7XG5cdFx0XHR9O1xuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIG1Tb3VyY2UgPT09ICdzdHJpbmcnICYmIChtU291cmNlLmluZGV4T2YoJy4nKSAhPT0gLTEgfHxcblx0XHRcdCAgICAgIG1Tb3VyY2UuaW5kZXhPZignWycpICE9PSAtMSB8fCBtU291cmNlLmluZGV4T2YoJygnKSAhPT0gLTEpIClcblx0XHR7XG5cdFx0XHQvKiBMaWtlIHRoZSBnZXQsIHdlIG5lZWQgdG8gZ2V0IGRhdGEgZnJvbSBhIG5lc3RlZCBvYmplY3QgKi9cblx0XHRcdHZhciBzZXREYXRhID0gZnVuY3Rpb24gKGRhdGEsIHZhbCwgc3JjKSB7XG5cdFx0XHRcdHZhciBhID0gX2ZuU3BsaXRPYmpOb3RhdGlvbiggc3JjICksIGI7XG5cdFx0XHRcdHZhciBhTGFzdCA9IGFbYS5sZW5ndGgtMV07XG5cdFx0XHRcdHZhciBhcnJheU5vdGF0aW9uLCBmdW5jTm90YXRpb24sIG8sIGlubmVyU3JjO1xuXHRcblx0XHRcdFx0Zm9yICggdmFyIGk9MCwgaUxlbj1hLmxlbmd0aC0xIDsgaTxpTGVuIDsgaSsrIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdC8vIENoZWNrIGlmIHdlIGFyZSBkZWFsaW5nIHdpdGggYW4gYXJyYXkgbm90YXRpb24gcmVxdWVzdFxuXHRcdFx0XHRcdGFycmF5Tm90YXRpb24gPSBhW2ldLm1hdGNoKF9fcmVBcnJheSk7XG5cdFx0XHRcdFx0ZnVuY05vdGF0aW9uID0gYVtpXS5tYXRjaChfX3JlRm4pO1xuXHRcblx0XHRcdFx0XHRpZiAoIGFycmF5Tm90YXRpb24gKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGFbaV0gPSBhW2ldLnJlcGxhY2UoX19yZUFycmF5LCAnJyk7XG5cdFx0XHRcdFx0XHRkYXRhWyBhW2ldIF0gPSBbXTtcblx0XG5cdFx0XHRcdFx0XHQvLyBHZXQgdGhlIHJlbWFpbmRlciBvZiB0aGUgbmVzdGVkIG9iamVjdCB0byBzZXQgc28gd2UgY2FuIHJlY3Vyc2Vcblx0XHRcdFx0XHRcdGIgPSBhLnNsaWNlKCk7XG5cdFx0XHRcdFx0XHRiLnNwbGljZSggMCwgaSsxICk7XG5cdFx0XHRcdFx0XHRpbm5lclNyYyA9IGIuam9pbignLicpO1xuXHRcblx0XHRcdFx0XHRcdC8vIFRyYXZlcnNlIGVhY2ggZW50cnkgaW4gdGhlIGFycmF5IHNldHRpbmcgdGhlIHByb3BlcnRpZXMgcmVxdWVzdGVkXG5cdFx0XHRcdFx0XHRpZiAoICQuaXNBcnJheSggdmFsICkgKVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRmb3IgKCB2YXIgaj0wLCBqTGVuPXZhbC5sZW5ndGggOyBqPGpMZW4gOyBqKysgKVxuXHRcdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdFx0byA9IHt9O1xuXHRcdFx0XHRcdFx0XHRcdHNldERhdGEoIG8sIHZhbFtqXSwgaW5uZXJTcmMgKTtcblx0XHRcdFx0XHRcdFx0XHRkYXRhWyBhW2ldIF0ucHVzaCggbyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRlbHNlXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdC8vIFdlJ3ZlIGJlZW4gYXNrZWQgdG8gc2F2ZSBkYXRhIHRvIGFuIGFycmF5LCBidXQgaXRcblx0XHRcdFx0XHRcdFx0Ly8gaXNuJ3QgYXJyYXkgZGF0YSB0byBiZSBzYXZlZC4gQmVzdCB0aGF0IGNhbiBiZSBkb25lXG5cdFx0XHRcdFx0XHRcdC8vIGlzIHRvIGp1c3Qgc2F2ZSB0aGUgdmFsdWUuXG5cdFx0XHRcdFx0XHRcdGRhdGFbIGFbaV0gXSA9IHZhbDtcblx0XHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0XHQvLyBUaGUgaW5uZXIgY2FsbCB0byBzZXREYXRhIGhhcyBhbHJlYWR5IHRyYXZlcnNlZCB0aHJvdWdoIHRoZSByZW1haW5kZXJcblx0XHRcdFx0XHRcdC8vIG9mIHRoZSBzb3VyY2UgYW5kIGhhcyBzZXQgdGhlIGRhdGEsIHRodXMgd2UgY2FuIGV4aXQgaGVyZVxuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIGlmICggZnVuY05vdGF0aW9uIClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHQvLyBGdW5jdGlvbiBjYWxsXG5cdFx0XHRcdFx0XHRhW2ldID0gYVtpXS5yZXBsYWNlKF9fcmVGbiwgJycpO1xuXHRcdFx0XHRcdFx0ZGF0YSA9IGRhdGFbIGFbaV0gXSggdmFsICk7XG5cdFx0XHRcdFx0fVxuXHRcblx0XHRcdFx0XHQvLyBJZiB0aGUgbmVzdGVkIG9iamVjdCBkb2Vzbid0IGN1cnJlbnRseSBleGlzdCAtIHNpbmNlIHdlIGFyZVxuXHRcdFx0XHRcdC8vIHRyeWluZyB0byBzZXQgdGhlIHZhbHVlIC0gY3JlYXRlIGl0XG5cdFx0XHRcdFx0aWYgKCBkYXRhWyBhW2ldIF0gPT09IG51bGwgfHwgZGF0YVsgYVtpXSBdID09PSB1bmRlZmluZWQgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGRhdGFbIGFbaV0gXSA9IHt9O1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRkYXRhID0gZGF0YVsgYVtpXSBdO1xuXHRcdFx0XHR9XG5cdFxuXHRcdFx0XHQvLyBMYXN0IGl0ZW0gaW4gdGhlIGlucHV0IC0gaS5lLCB0aGUgYWN0dWFsIHNldFxuXHRcdFx0XHRpZiAoIGFMYXN0Lm1hdGNoKF9fcmVGbiApIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdC8vIEZ1bmN0aW9uIGNhbGxcblx0XHRcdFx0XHRkYXRhID0gZGF0YVsgYUxhc3QucmVwbGFjZShfX3JlRm4sICcnKSBdKCB2YWwgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlXG5cdFx0XHRcdHtcblx0XHRcdFx0XHQvLyBJZiBhcnJheSBub3RhdGlvbiBpcyB1c2VkLCB3ZSBqdXN0IHdhbnQgdG8gc3RyaXAgaXQgYW5kIHVzZSB0aGUgcHJvcGVydHkgbmFtZVxuXHRcdFx0XHRcdC8vIGFuZCBhc3NpZ24gdGhlIHZhbHVlLiBJZiBpdCBpc24ndCB1c2VkLCB0aGVuIHdlIGdldCB0aGUgcmVzdWx0IHdlIHdhbnQgYW55d2F5XG5cdFx0XHRcdFx0ZGF0YVsgYUxhc3QucmVwbGFjZShfX3JlQXJyYXksICcnKSBdID0gdmFsO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcblx0XHRcdHJldHVybiBmdW5jdGlvbiAoZGF0YSwgdmFsKSB7IC8vIG1ldGEgaXMgYWxzbyBwYXNzZWQgaW4sIGJ1dCBub3QgdXNlZFxuXHRcdFx0XHRyZXR1cm4gc2V0RGF0YSggZGF0YSwgdmFsLCBtU291cmNlICk7XG5cdFx0XHR9O1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0e1xuXHRcdFx0LyogQXJyYXkgb3IgZmxhdCBvYmplY3QgbWFwcGluZyAqL1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uIChkYXRhLCB2YWwpIHsgLy8gbWV0YSBpcyBhbHNvIHBhc3NlZCBpbiwgYnV0IG5vdCB1c2VkXG5cdFx0XHRcdGRhdGFbbVNvdXJjZV0gPSB2YWw7XG5cdFx0XHR9O1xuXHRcdH1cblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBSZXR1cm4gYW4gYXJyYXkgd2l0aCB0aGUgZnVsbCB0YWJsZSBkYXRhXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcmV0dXJucyBhcnJheSB7YXJyYXl9IGFEYXRhIE1hc3RlciBkYXRhIGFycmF5XG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkdldERhdGFNYXN0ZXIgKCBzZXR0aW5ncyApXG5cdHtcblx0XHRyZXR1cm4gX3BsdWNrKCBzZXR0aW5ncy5hb0RhdGEsICdfYURhdGEnICk7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogTnVrZSB0aGUgdGFibGVcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQ2xlYXJUYWJsZSggc2V0dGluZ3MgKVxuXHR7XG5cdFx0c2V0dGluZ3MuYW9EYXRhLmxlbmd0aCA9IDA7XG5cdFx0c2V0dGluZ3MuYWlEaXNwbGF5TWFzdGVyLmxlbmd0aCA9IDA7XG5cdFx0c2V0dGluZ3MuYWlEaXNwbGF5Lmxlbmd0aCA9IDA7XG5cdFx0c2V0dGluZ3MuYUlkcyA9IHt9O1xuXHR9XG5cdFxuXHRcblx0IC8qKlxuXHQgKiBUYWtlIGFuIGFycmF5IG9mIGludGVnZXJzIChpbmRleCBhcnJheSkgYW5kIHJlbW92ZSBhIHRhcmdldCBpbnRlZ2VyICh2YWx1ZSAtIG5vdFxuXHQgKiB0aGUga2V5ISlcblx0ICogIEBwYXJhbSB7YXJyYXl9IGEgSW5kZXggYXJyYXkgdG8gdGFyZ2V0XG5cdCAqICBAcGFyYW0ge2ludH0gaVRhcmdldCB2YWx1ZSB0byBmaW5kXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkRlbGV0ZUluZGV4KCBhLCBpVGFyZ2V0LCBzcGxpY2UgKVxuXHR7XG5cdFx0dmFyIGlUYXJnZXRJbmRleCA9IC0xO1xuXHRcblx0XHRmb3IgKCB2YXIgaT0wLCBpTGVuPWEubGVuZ3RoIDsgaTxpTGVuIDsgaSsrIClcblx0XHR7XG5cdFx0XHRpZiAoIGFbaV0gPT0gaVRhcmdldCApXG5cdFx0XHR7XG5cdFx0XHRcdGlUYXJnZXRJbmRleCA9IGk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggYVtpXSA+IGlUYXJnZXQgKVxuXHRcdFx0e1xuXHRcdFx0XHRhW2ldLS07XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHRpZiAoIGlUYXJnZXRJbmRleCAhPSAtMSAmJiBzcGxpY2UgPT09IHVuZGVmaW5lZCApXG5cdFx0e1xuXHRcdFx0YS5zcGxpY2UoIGlUYXJnZXRJbmRleCwgMSApO1xuXHRcdH1cblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBNYXJrIGNhY2hlZCBkYXRhIGFzIGludmFsaWQgc3VjaCB0aGF0IGEgcmUtcmVhZCBvZiB0aGUgZGF0YSB3aWxsIG9jY3VyIHdoZW5cblx0ICogdGhlIGNhY2hlZCBkYXRhIGlzIG5leHQgcmVxdWVzdGVkLiBBbHNvIHVwZGF0ZSBmcm9tIHRoZSBkYXRhIHNvdXJjZSBvYmplY3QuXG5cdCAqXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiBAcGFyYW0ge2ludH0gICAgcm93SWR4ICAgUm93IGluZGV4IHRvIGludmFsaWRhdGVcblx0ICogQHBhcmFtIHtzdHJpbmd9IFtzcmNdICAgIFNvdXJjZSB0byBpbnZhbGlkYXRlIGZyb206IHVuZGVmaW5lZCwgJ2F1dG8nLCAnZG9tJ1xuXHQgKiAgICAgb3IgJ2RhdGEnXG5cdCAqIEBwYXJhbSB7aW50fSAgICBbY29sSWR4XSBDb2x1bW4gaW5kZXggdG8gaW52YWxpZGF0ZS4gSWYgdW5kZWZpbmVkIHRoZSB3aG9sZVxuXHQgKiAgICAgcm93IHdpbGwgYmUgaW52YWxpZGF0ZWRcblx0ICogQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqXG5cdCAqIEB0b2RvIEZvciB0aGUgbW9kdWxhcmlzYXRpb24gb2YgdjEuMTEgdGhpcyB3aWxsIG5lZWQgdG8gYmVjb21lIGEgY2FsbGJhY2ssIHNvXG5cdCAqICAgdGhlIHNvcnQgYW5kIGZpbHRlciBtZXRob2RzIGNhbiBzdWJzY3JpYmUgdG8gaXQuIFRoYXQgd2lsbCByZXF1aXJlZFxuXHQgKiAgIGluaXRpYWxpc2F0aW9uIG9wdGlvbnMgZm9yIHNvcnRpbmcsIHdoaWNoIGlzIHdoeSBpdCBpcyBub3QgYWxyZWFkeSBiYWtlZCBpblxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuSW52YWxpZGF0ZSggc2V0dGluZ3MsIHJvd0lkeCwgc3JjLCBjb2xJZHggKVxuXHR7XG5cdFx0dmFyIHJvdyA9IHNldHRpbmdzLmFvRGF0YVsgcm93SWR4IF07XG5cdFx0dmFyIGksIGllbjtcblx0XHR2YXIgY2VsbFdyaXRlID0gZnVuY3Rpb24gKCBjZWxsLCBjb2wgKSB7XG5cdFx0XHQvLyBUaGlzIGlzIHZlcnkgZnJ1c3RyYXRpbmcsIGJ1dCBpbiBJRSBpZiB5b3UganVzdCB3cml0ZSBkaXJlY3RseVxuXHRcdFx0Ly8gdG8gaW5uZXJIVE1MLCBhbmQgZWxlbWVudHMgdGhhdCBhcmUgb3ZlcndyaXR0ZW4gYXJlIEdDJ2VkLFxuXHRcdFx0Ly8gZXZlbiBpZiB0aGVyZSBpcyBhIHJlZmVyZW5jZSB0byB0aGVtIGVsc2V3aGVyZVxuXHRcdFx0d2hpbGUgKCBjZWxsLmNoaWxkTm9kZXMubGVuZ3RoICkge1xuXHRcdFx0XHRjZWxsLnJlbW92ZUNoaWxkKCBjZWxsLmZpcnN0Q2hpbGQgKTtcblx0XHRcdH1cblx0XG5cdFx0XHRjZWxsLmlubmVySFRNTCA9IF9mbkdldENlbGxEYXRhKCBzZXR0aW5ncywgcm93SWR4LCBjb2wsICdkaXNwbGF5JyApO1xuXHRcdH07XG5cdFxuXHRcdC8vIEFyZSB3ZSByZWFkaW5nIGxhc3QgZGF0YSBmcm9tIERPTSBvciB0aGUgZGF0YSBvYmplY3Q/XG5cdFx0aWYgKCBzcmMgPT09ICdkb20nIHx8ICgoISBzcmMgfHwgc3JjID09PSAnYXV0bycpICYmIHJvdy5zcmMgPT09ICdkb20nKSApIHtcblx0XHRcdC8vIFJlYWQgdGhlIGRhdGEgZnJvbSB0aGUgRE9NXG5cdFx0XHRyb3cuX2FEYXRhID0gX2ZuR2V0Um93RWxlbWVudHMoXG5cdFx0XHRcdFx0c2V0dGluZ3MsIHJvdywgY29sSWR4LCBjb2xJZHggPT09IHVuZGVmaW5lZCA/IHVuZGVmaW5lZCA6IHJvdy5fYURhdGFcblx0XHRcdFx0KVxuXHRcdFx0XHQuZGF0YTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHQvLyBSZWFkaW5nIGZyb20gZGF0YSBvYmplY3QsIHVwZGF0ZSB0aGUgRE9NXG5cdFx0XHR2YXIgY2VsbHMgPSByb3cuYW5DZWxscztcblx0XG5cdFx0XHRpZiAoIGNlbGxzICkge1xuXHRcdFx0XHRpZiAoIGNvbElkeCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdGNlbGxXcml0ZSggY2VsbHNbY29sSWR4XSwgY29sSWR4ICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0Zm9yICggaT0wLCBpZW49Y2VsbHMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0XHRjZWxsV3JpdGUoIGNlbGxzW2ldLCBpICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHQvLyBGb3IgYm90aCByb3cgYW5kIGNlbGwgaW52YWxpZGF0aW9uLCB0aGUgY2FjaGVkIGRhdGEgZm9yIHNvcnRpbmcgYW5kXG5cdFx0Ly8gZmlsdGVyaW5nIGlzIG51bGxlZCBvdXRcblx0XHRyb3cuX2FTb3J0RGF0YSA9IG51bGw7XG5cdFx0cm93Ll9hRmlsdGVyRGF0YSA9IG51bGw7XG5cdFxuXHRcdC8vIEludmFsaWRhdGUgdGhlIHR5cGUgZm9yIGEgc3BlY2lmaWMgY29sdW1uIChpZiBnaXZlbikgb3IgYWxsIGNvbHVtbnMgc2luY2Vcblx0XHQvLyB0aGUgZGF0YSBtaWdodCBoYXZlIGNoYW5nZWRcblx0XHR2YXIgY29scyA9IHNldHRpbmdzLmFvQ29sdW1ucztcblx0XHRpZiAoIGNvbElkeCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0Y29sc1sgY29sSWR4IF0uc1R5cGUgPSBudWxsO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdGZvciAoIGk9MCwgaWVuPWNvbHMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdGNvbHNbaV0uc1R5cGUgPSBudWxsO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIFVwZGF0ZSBEYXRhVGFibGVzIHNwZWNpYWwgYERUXypgIGF0dHJpYnV0ZXMgZm9yIHRoZSByb3dcblx0XHRcdF9mblJvd0F0dHJpYnV0ZXMoIHNldHRpbmdzLCByb3cgKTtcblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQnVpbGQgYSBkYXRhIHNvdXJjZSBvYmplY3QgZnJvbSBhbiBIVE1MIHJvdywgcmVhZGluZyB0aGUgY29udGVudHMgb2YgdGhlXG5cdCAqIGNlbGxzIHRoYXQgYXJlIGluIHRoZSByb3cuXG5cdCAqXG5cdCAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiBAcGFyYW0ge25vZGV8b2JqZWN0fSBUUiBlbGVtZW50IGZyb20gd2hpY2ggdG8gcmVhZCBkYXRhIG9yIGV4aXN0aW5nIHJvd1xuXHQgKiAgIG9iamVjdCBmcm9tIHdoaWNoIHRvIHJlLXJlYWQgdGhlIGRhdGEgZnJvbSB0aGUgY2VsbHNcblx0ICogQHBhcmFtIHtpbnR9IFtjb2xJZHhdIE9wdGlvbmFsIGNvbHVtbiBpbmRleFxuXHQgKiBAcGFyYW0ge2FycmF5fG9iamVjdH0gW2RdIERhdGEgc291cmNlIG9iamVjdC4gSWYgYGNvbElkeGAgaXMgZ2l2ZW4gdGhlbiB0aGlzXG5cdCAqICAgcGFyYW1ldGVyIHNob3VsZCBhbHNvIGJlIGdpdmVuIGFuZCB3aWxsIGJlIHVzZWQgdG8gd3JpdGUgdGhlIGRhdGEgaW50by5cblx0ICogICBPbmx5IHRoZSBjb2x1bW4gaW4gcXVlc3Rpb24gd2lsbCBiZSB3cml0dGVuXG5cdCAqIEByZXR1cm5zIHtvYmplY3R9IE9iamVjdCB3aXRoIHR3byBwYXJhbWV0ZXJzOiBgZGF0YWAgdGhlIGRhdGEgcmVhZCwgaW5cblx0ICogICBkb2N1bWVudCBvcmRlciwgYW5kIGBjZWxsc2AgYW5kIGFycmF5IG9mIG5vZGVzICh0aGV5IGNhbiBiZSB1c2VmdWwgdG8gdGhlXG5cdCAqICAgY2FsbGVyLCBzbyByYXRoZXIgdGhhbiBuZWVkaW5nIGEgc2Vjb25kIHRyYXZlcnNhbCB0byBnZXQgdGhlbSwganVzdCByZXR1cm5cblx0ICogICB0aGVtIGZyb20gaGVyZSkuXG5cdCAqIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuR2V0Um93RWxlbWVudHMoIHNldHRpbmdzLCByb3csIGNvbElkeCwgZCApXG5cdHtcblx0XHR2YXJcblx0XHRcdHRkcyA9IFtdLFxuXHRcdFx0dGQgPSByb3cuZmlyc3RDaGlsZCxcblx0XHRcdG5hbWUsIGNvbCwgbywgaT0wLCBjb250ZW50cyxcblx0XHRcdGNvbHVtbnMgPSBzZXR0aW5ncy5hb0NvbHVtbnMsXG5cdFx0XHRvYmplY3RSZWFkID0gc2V0dGluZ3MuX3Jvd1JlYWRPYmplY3Q7XG5cdFxuXHRcdC8vIEFsbG93IHRoZSBkYXRhIG9iamVjdCB0byBiZSBwYXNzZWQgaW4sIG9yIGNvbnN0cnVjdFxuXHRcdGQgPSBkICE9PSB1bmRlZmluZWQgP1xuXHRcdFx0ZCA6XG5cdFx0XHRvYmplY3RSZWFkID9cblx0XHRcdFx0e30gOlxuXHRcdFx0XHRbXTtcblx0XG5cdFx0dmFyIGF0dHIgPSBmdW5jdGlvbiAoIHN0ciwgdGQgICkge1xuXHRcdFx0aWYgKCB0eXBlb2Ygc3RyID09PSAnc3RyaW5nJyApIHtcblx0XHRcdFx0dmFyIGlkeCA9IHN0ci5pbmRleE9mKCdAJyk7XG5cdFxuXHRcdFx0XHRpZiAoIGlkeCAhPT0gLTEgKSB7XG5cdFx0XHRcdFx0dmFyIGF0dHIgPSBzdHIuc3Vic3RyaW5nKCBpZHgrMSApO1xuXHRcdFx0XHRcdHZhciBzZXR0ZXIgPSBfZm5TZXRPYmplY3REYXRhRm4oIHN0ciApO1xuXHRcdFx0XHRcdHNldHRlciggZCwgdGQuZ2V0QXR0cmlidXRlKCBhdHRyICkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cdFxuXHRcdC8vIFJlYWQgZGF0YSBmcm9tIGEgY2VsbCBhbmQgc3RvcmUgaW50byB0aGUgZGF0YSBvYmplY3Rcblx0XHR2YXIgY2VsbFByb2Nlc3MgPSBmdW5jdGlvbiAoIGNlbGwgKSB7XG5cdFx0XHRpZiAoIGNvbElkeCA9PT0gdW5kZWZpbmVkIHx8IGNvbElkeCA9PT0gaSApIHtcblx0XHRcdFx0Y29sID0gY29sdW1uc1tpXTtcblx0XHRcdFx0Y29udGVudHMgPSAkLnRyaW0oY2VsbC5pbm5lckhUTUwpO1xuXHRcblx0XHRcdFx0aWYgKCBjb2wgJiYgY29sLl9iQXR0clNyYyApIHtcblx0XHRcdFx0XHR2YXIgc2V0dGVyID0gX2ZuU2V0T2JqZWN0RGF0YUZuKCBjb2wubURhdGEuXyApO1xuXHRcdFx0XHRcdHNldHRlciggZCwgY29udGVudHMgKTtcblx0XG5cdFx0XHRcdFx0YXR0ciggY29sLm1EYXRhLnNvcnQsIGNlbGwgKTtcblx0XHRcdFx0XHRhdHRyKCBjb2wubURhdGEudHlwZSwgY2VsbCApO1xuXHRcdFx0XHRcdGF0dHIoIGNvbC5tRGF0YS5maWx0ZXIsIGNlbGwgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHQvLyBEZXBlbmRpbmcgb24gdGhlIGBkYXRhYCBvcHRpb24gZm9yIHRoZSBjb2x1bW5zIHRoZSBkYXRhIGNhblxuXHRcdFx0XHRcdC8vIGJlIHJlYWQgdG8gZWl0aGVyIGFuIG9iamVjdCBvciBhbiBhcnJheS5cblx0XHRcdFx0XHRpZiAoIG9iamVjdFJlYWQgKSB7XG5cdFx0XHRcdFx0XHRpZiAoICEgY29sLl9zZXR0ZXIgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIENhY2hlIHRoZSBzZXR0ZXIgZnVuY3Rpb25cblx0XHRcdFx0XHRcdFx0Y29sLl9zZXR0ZXIgPSBfZm5TZXRPYmplY3REYXRhRm4oIGNvbC5tRGF0YSApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0Y29sLl9zZXR0ZXIoIGQsIGNvbnRlbnRzICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0ZFtpXSA9IGNvbnRlbnRzO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcblx0XHRcdGkrKztcblx0XHR9O1xuXHRcblx0XHRpZiAoIHRkICkge1xuXHRcdFx0Ly8gYHRyYCBlbGVtZW50IHdhcyBwYXNzZWQgaW5cblx0XHRcdHdoaWxlICggdGQgKSB7XG5cdFx0XHRcdG5hbWUgPSB0ZC5ub2RlTmFtZS50b1VwcGVyQ2FzZSgpO1xuXHRcblx0XHRcdFx0aWYgKCBuYW1lID09IFwiVERcIiB8fCBuYW1lID09IFwiVEhcIiApIHtcblx0XHRcdFx0XHRjZWxsUHJvY2VzcyggdGQgKTtcblx0XHRcdFx0XHR0ZHMucHVzaCggdGQgKTtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0dGQgPSB0ZC5uZXh0U2libGluZztcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHQvLyBFeGlzdGluZyByb3cgb2JqZWN0IHBhc3NlZCBpblxuXHRcdFx0dGRzID0gcm93LmFuQ2VsbHM7XG5cdFxuXHRcdFx0Zm9yICggdmFyIGo9MCwgamVuPXRkcy5sZW5ndGggOyBqPGplbiA7IGorKyApIHtcblx0XHRcdFx0Y2VsbFByb2Nlc3MoIHRkc1tqXSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0Ly8gUmVhZCB0aGUgSUQgZnJvbSB0aGUgRE9NIGlmIHByZXNlbnRcblx0XHR2YXIgcm93Tm9kZSA9IHJvdy5maXJzdENoaWxkID8gcm93IDogcm93Lm5Ucjtcblx0XG5cdFx0aWYgKCByb3dOb2RlICkge1xuXHRcdFx0dmFyIGlkID0gcm93Tm9kZS5nZXRBdHRyaWJ1dGUoICdpZCcgKTtcblx0XG5cdFx0XHRpZiAoIGlkICkge1xuXHRcdFx0XHRfZm5TZXRPYmplY3REYXRhRm4oIHNldHRpbmdzLnJvd0lkICkoIGQsIGlkICk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4ge1xuXHRcdFx0ZGF0YTogZCxcblx0XHRcdGNlbGxzOiB0ZHNcblx0XHR9O1xuXHR9XG5cdC8qKlxuXHQgKiBDcmVhdGUgYSBuZXcgVFIgZWxlbWVudCAoYW5kIGl0J3MgVEQgY2hpbGRyZW4pIGZvciBhIHJvd1xuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtpbnR9IGlSb3cgUm93IHRvIGNvbnNpZGVyXG5cdCAqICBAcGFyYW0ge25vZGV9IFtuVHJJbl0gVFIgZWxlbWVudCB0byBhZGQgdG8gdGhlIHRhYmxlIC0gb3B0aW9uYWwuIElmIG5vdCBnaXZlbixcblx0ICogICAgRGF0YVRhYmxlcyB3aWxsIGNyZWF0ZSBhIHJvdyBhdXRvbWF0aWNhbGx5XG5cdCAqICBAcGFyYW0ge2FycmF5fSBbYW5UZHNdIEFycmF5IG9mIFREfFRIIGVsZW1lbnRzIGZvciB0aGUgcm93IC0gbXVzdCBiZSBnaXZlblxuXHQgKiAgICBpZiBuVHIgaXMuXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkNyZWF0ZVRyICggb1NldHRpbmdzLCBpUm93LCBuVHJJbiwgYW5UZHMgKVxuXHR7XG5cdFx0dmFyXG5cdFx0XHRyb3cgPSBvU2V0dGluZ3MuYW9EYXRhW2lSb3ddLFxuXHRcdFx0cm93RGF0YSA9IHJvdy5fYURhdGEsXG5cdFx0XHRjZWxscyA9IFtdLFxuXHRcdFx0blRyLCBuVGQsIG9Db2wsXG5cdFx0XHRpLCBpTGVuO1xuXHRcblx0XHRpZiAoIHJvdy5uVHIgPT09IG51bGwgKVxuXHRcdHtcblx0XHRcdG5UciA9IG5UckluIHx8IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3RyJyk7XG5cdFxuXHRcdFx0cm93Lm5UciA9IG5Ucjtcblx0XHRcdHJvdy5hbkNlbGxzID0gY2VsbHM7XG5cdFxuXHRcdFx0LyogVXNlIGEgcHJpdmF0ZSBwcm9wZXJ0eSBvbiB0aGUgbm9kZSB0byBhbGxvdyByZXNlcnZlIG1hcHBpbmcgZnJvbSB0aGUgbm9kZVxuXHRcdFx0ICogdG8gdGhlIGFvRGF0YSBhcnJheSBmb3IgZmFzdCBsb29rIHVwXG5cdFx0XHQgKi9cblx0XHRcdG5Uci5fRFRfUm93SW5kZXggPSBpUm93O1xuXHRcblx0XHRcdC8qIFNwZWNpYWwgcGFyYW1ldGVycyBjYW4gYmUgZ2l2ZW4gYnkgdGhlIGRhdGEgc291cmNlIHRvIGJlIHVzZWQgb24gdGhlIHJvdyAqL1xuXHRcdFx0X2ZuUm93QXR0cmlidXRlcyggb1NldHRpbmdzLCByb3cgKTtcblx0XG5cdFx0XHQvKiBQcm9jZXNzIGVhY2ggY29sdW1uICovXG5cdFx0XHRmb3IgKCBpPTAsIGlMZW49b1NldHRpbmdzLmFvQ29sdW1ucy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKVxuXHRcdFx0e1xuXHRcdFx0XHRvQ29sID0gb1NldHRpbmdzLmFvQ29sdW1uc1tpXTtcblx0XG5cdFx0XHRcdG5UZCA9IG5UckluID8gYW5UZHNbaV0gOiBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCBvQ29sLnNDZWxsVHlwZSApO1xuXHRcdFx0XHRuVGQuX0RUX0NlbGxJbmRleCA9IHtcblx0XHRcdFx0XHRyb3c6IGlSb3csXG5cdFx0XHRcdFx0Y29sdW1uOiBpXG5cdFx0XHRcdH07XG5cdFx0XHRcdFxuXHRcdFx0XHRjZWxscy5wdXNoKCBuVGQgKTtcblx0XG5cdFx0XHRcdC8vIE5lZWQgdG8gY3JlYXRlIHRoZSBIVE1MIGlmIG5ldywgb3IgaWYgYSByZW5kZXJpbmcgZnVuY3Rpb24gaXMgZGVmaW5lZFxuXHRcdFx0XHRpZiAoICghblRySW4gfHwgb0NvbC5tUmVuZGVyIHx8IG9Db2wubURhdGEgIT09IGkpICYmXG5cdFx0XHRcdFx0ICghJC5pc1BsYWluT2JqZWN0KG9Db2wubURhdGEpIHx8IG9Db2wubURhdGEuXyAhPT0gaSsnLmRpc3BsYXknKVxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHRuVGQuaW5uZXJIVE1MID0gX2ZuR2V0Q2VsbERhdGEoIG9TZXR0aW5ncywgaVJvdywgaSwgJ2Rpc3BsYXknICk7XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdC8qIEFkZCB1c2VyIGRlZmluZWQgY2xhc3MgKi9cblx0XHRcdFx0aWYgKCBvQ29sLnNDbGFzcyApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRuVGQuY2xhc3NOYW1lICs9ICcgJytvQ29sLnNDbGFzcztcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0Ly8gVmlzaWJpbGl0eSAtIGFkZCBvciByZW1vdmUgYXMgcmVxdWlyZWRcblx0XHRcdFx0aWYgKCBvQ29sLmJWaXNpYmxlICYmICEgblRySW4gKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0blRyLmFwcGVuZENoaWxkKCBuVGQgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIGlmICggISBvQ29sLmJWaXNpYmxlICYmIG5UckluIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdG5UZC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKCBuVGQgKTtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0aWYgKCBvQ29sLmZuQ3JlYXRlZENlbGwgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0b0NvbC5mbkNyZWF0ZWRDZWxsLmNhbGwoIG9TZXR0aW5ncy5vSW5zdGFuY2UsXG5cdFx0XHRcdFx0XHRuVGQsIF9mbkdldENlbGxEYXRhKCBvU2V0dGluZ3MsIGlSb3csIGkgKSwgcm93RGF0YSwgaVJvdywgaVxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XG5cdFx0XHRfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgJ2FvUm93Q3JlYXRlZENhbGxiYWNrJywgbnVsbCwgW25Uciwgcm93RGF0YSwgaVJvd10gKTtcblx0XHR9XG5cdFxuXHRcdC8vIFJlbW92ZSBvbmNlIHdlYmtpdCBidWcgMTMxODE5IGFuZCBDaHJvbWl1bSBidWcgMzY1NjE5IGhhdmUgYmVlbiByZXNvbHZlZFxuXHRcdC8vIGFuZCBkZXBsb3llZFxuXHRcdHJvdy5uVHIuc2V0QXR0cmlidXRlKCAncm9sZScsICdyb3cnICk7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQWRkIGF0dHJpYnV0ZXMgdG8gYSByb3cgYmFzZWQgb24gdGhlIHNwZWNpYWwgYERUXypgIHBhcmFtZXRlcnMgaW4gYSBkYXRhXG5cdCAqIHNvdXJjZSBvYmplY3QuXG5cdCAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBEYXRhVGFibGVzIHJvdyBvYmplY3QgZm9yIHRoZSByb3cgdG8gYmUgbW9kaWZpZWRcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuUm93QXR0cmlidXRlcyggc2V0dGluZ3MsIHJvdyApXG5cdHtcblx0XHR2YXIgdHIgPSByb3cublRyO1xuXHRcdHZhciBkYXRhID0gcm93Ll9hRGF0YTtcblx0XG5cdFx0aWYgKCB0ciApIHtcblx0XHRcdHZhciBpZCA9IHNldHRpbmdzLnJvd0lkRm4oIGRhdGEgKTtcblx0XG5cdFx0XHRpZiAoIGlkICkge1xuXHRcdFx0XHR0ci5pZCA9IGlkO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggZGF0YS5EVF9Sb3dDbGFzcyApIHtcblx0XHRcdFx0Ly8gUmVtb3ZlIGFueSBjbGFzc2VzIGFkZGVkIGJ5IERUX1Jvd0NsYXNzIGJlZm9yZVxuXHRcdFx0XHR2YXIgYSA9IGRhdGEuRFRfUm93Q2xhc3Muc3BsaXQoJyAnKTtcblx0XHRcdFx0cm93Ll9fcm93YyA9IHJvdy5fX3Jvd2MgP1xuXHRcdFx0XHRcdF91bmlxdWUoIHJvdy5fX3Jvd2MuY29uY2F0KCBhICkgKSA6XG5cdFx0XHRcdFx0YTtcblx0XG5cdFx0XHRcdCQodHIpXG5cdFx0XHRcdFx0LnJlbW92ZUNsYXNzKCByb3cuX19yb3djLmpvaW4oJyAnKSApXG5cdFx0XHRcdFx0LmFkZENsYXNzKCBkYXRhLkRUX1Jvd0NsYXNzICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0aWYgKCBkYXRhLkRUX1Jvd0F0dHIgKSB7XG5cdFx0XHRcdCQodHIpLmF0dHIoIGRhdGEuRFRfUm93QXR0ciApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggZGF0YS5EVF9Sb3dEYXRhICkge1xuXHRcdFx0XHQkKHRyKS5kYXRhKCBkYXRhLkRUX1Jvd0RhdGEgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQ3JlYXRlIHRoZSBIVE1MIGhlYWRlciBmb3IgdGhlIHRhYmxlXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkJ1aWxkSGVhZCggb1NldHRpbmdzIClcblx0e1xuXHRcdHZhciBpLCBpZW4sIGNlbGwsIHJvdywgY29sdW1uO1xuXHRcdHZhciB0aGVhZCA9IG9TZXR0aW5ncy5uVEhlYWQ7XG5cdFx0dmFyIHRmb290ID0gb1NldHRpbmdzLm5URm9vdDtcblx0XHR2YXIgY3JlYXRlSGVhZGVyID0gJCgndGgsIHRkJywgdGhlYWQpLmxlbmd0aCA9PT0gMDtcblx0XHR2YXIgY2xhc3NlcyA9IG9TZXR0aW5ncy5vQ2xhc3Nlcztcblx0XHR2YXIgY29sdW1ucyA9IG9TZXR0aW5ncy5hb0NvbHVtbnM7XG5cdFxuXHRcdGlmICggY3JlYXRlSGVhZGVyICkge1xuXHRcdFx0cm93ID0gJCgnPHRyLz4nKS5hcHBlbmRUbyggdGhlYWQgKTtcblx0XHR9XG5cdFxuXHRcdGZvciAoIGk9MCwgaWVuPWNvbHVtbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRjb2x1bW4gPSBjb2x1bW5zW2ldO1xuXHRcdFx0Y2VsbCA9ICQoIGNvbHVtbi5uVGggKS5hZGRDbGFzcyggY29sdW1uLnNDbGFzcyApO1xuXHRcblx0XHRcdGlmICggY3JlYXRlSGVhZGVyICkge1xuXHRcdFx0XHRjZWxsLmFwcGVuZFRvKCByb3cgKTtcblx0XHRcdH1cblx0XG5cdFx0XHQvLyAxLjExIG1vdmUgaW50byBzb3J0aW5nXG5cdFx0XHRpZiAoIG9TZXR0aW5ncy5vRmVhdHVyZXMuYlNvcnQgKSB7XG5cdFx0XHRcdGNlbGwuYWRkQ2xhc3MoIGNvbHVtbi5zU29ydGluZ0NsYXNzICk7XG5cdFxuXHRcdFx0XHRpZiAoIGNvbHVtbi5iU29ydGFibGUgIT09IGZhbHNlICkge1xuXHRcdFx0XHRcdGNlbGxcblx0XHRcdFx0XHRcdC5hdHRyKCAndGFiaW5kZXgnLCBvU2V0dGluZ3MuaVRhYkluZGV4IClcblx0XHRcdFx0XHRcdC5hdHRyKCAnYXJpYS1jb250cm9scycsIG9TZXR0aW5ncy5zVGFibGVJZCApO1xuXHRcblx0XHRcdFx0XHRfZm5Tb3J0QXR0YWNoTGlzdGVuZXIoIG9TZXR0aW5ncywgY29sdW1uLm5UaCwgaSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFxuXHRcdFx0aWYgKCBjb2x1bW4uc1RpdGxlICE9IGNlbGxbMF0uaW5uZXJIVE1MICkge1xuXHRcdFx0XHRjZWxsLmh0bWwoIGNvbHVtbi5zVGl0bGUgKTtcblx0XHRcdH1cblx0XG5cdFx0XHRfZm5SZW5kZXJlciggb1NldHRpbmdzLCAnaGVhZGVyJyApKFxuXHRcdFx0XHRvU2V0dGluZ3MsIGNlbGwsIGNvbHVtbiwgY2xhc3Nlc1xuXHRcdFx0KTtcblx0XHR9XG5cdFxuXHRcdGlmICggY3JlYXRlSGVhZGVyICkge1xuXHRcdFx0X2ZuRGV0ZWN0SGVhZGVyKCBvU2V0dGluZ3MuYW9IZWFkZXIsIHRoZWFkICk7XG5cdFx0fVxuXHRcdFxuXHRcdC8qIEFSSUEgcm9sZSBmb3IgdGhlIHJvd3MgKi9cblx0IFx0JCh0aGVhZCkuZmluZCgnPnRyJykuYXR0cigncm9sZScsICdyb3cnKTtcblx0XG5cdFx0LyogRGVhbCB3aXRoIHRoZSBmb290ZXIgLSBhZGQgY2xhc3NlcyBpZiByZXF1aXJlZCAqL1xuXHRcdCQodGhlYWQpLmZpbmQoJz50cj50aCwgPnRyPnRkJykuYWRkQ2xhc3MoIGNsYXNzZXMuc0hlYWRlclRIICk7XG5cdFx0JCh0Zm9vdCkuZmluZCgnPnRyPnRoLCA+dHI+dGQnKS5hZGRDbGFzcyggY2xhc3Nlcy5zRm9vdGVyVEggKTtcblx0XG5cdFx0Ly8gQ2FjaGUgdGhlIGZvb3RlciBjZWxscy4gTm90ZSB0aGF0IHdlIG9ubHkgdGFrZSB0aGUgY2VsbHMgZnJvbSB0aGUgZmlyc3Rcblx0XHQvLyByb3cgaW4gdGhlIGZvb3Rlci4gSWYgdGhlcmUgaXMgbW9yZSB0aGFuIG9uZSByb3cgdGhlIHVzZXIgd2FudHMgdG9cblx0XHQvLyBpbnRlcmFjdCB3aXRoLCB0aGV5IG5lZWQgdG8gdXNlIHRoZSB0YWJsZSgpLmZvb3QoKSBtZXRob2QuIE5vdGUgYWxzbyB0aGlzXG5cdFx0Ly8gYWxsb3dzIGNlbGxzIHRvIGJlIHVzZWQgZm9yIG11bHRpcGxlIGNvbHVtbnMgdXNpbmcgY29sc3BhblxuXHRcdGlmICggdGZvb3QgIT09IG51bGwgKSB7XG5cdFx0XHR2YXIgY2VsbHMgPSBvU2V0dGluZ3MuYW9Gb290ZXJbMF07XG5cdFxuXHRcdFx0Zm9yICggaT0wLCBpZW49Y2VsbHMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdGNvbHVtbiA9IGNvbHVtbnNbaV07XG5cdFx0XHRcdGNvbHVtbi5uVGYgPSBjZWxsc1tpXS5jZWxsO1xuXHRcblx0XHRcdFx0aWYgKCBjb2x1bW4uc0NsYXNzICkge1xuXHRcdFx0XHRcdCQoY29sdW1uLm5UZikuYWRkQ2xhc3MoIGNvbHVtbi5zQ2xhc3MgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBEcmF3IHRoZSBoZWFkZXIgKG9yIGZvb3RlcikgZWxlbWVudCBiYXNlZCBvbiB0aGUgY29sdW1uIHZpc2liaWxpdHkgc3RhdGVzLiBUaGVcblx0ICogbWV0aG9kb2xvZ3kgaGVyZSBpcyB0byB1c2UgdGhlIGxheW91dCBhcnJheSBmcm9tIF9mbkRldGVjdEhlYWRlciwgbW9kaWZpZWQgZm9yXG5cdCAqIHRoZSBpbnN0YW50YW5lb3VzIGNvbHVtbiB2aXNpYmlsaXR5LCB0byBjb25zdHJ1Y3QgdGhlIG5ldyBsYXlvdXQuIFRoZSBncmlkIGlzXG5cdCAqIHRyYXZlcnNlZCBvdmVyIGNlbGwgYXQgYSB0aW1lIGluIGEgcm93cyB4IGNvbHVtbnMgZ3JpZCBmYXNoaW9uLCBhbHRob3VnaCBlYWNoXG5cdCAqIGNlbGwgaW5zZXJ0IGNhbiBjb3ZlciBtdWx0aXBsZSBlbGVtZW50cyBpbiB0aGUgZ3JpZCAtIHdoaWNoIGlzIHRyYWNrcyB1c2luZyB0aGVcblx0ICogYUFwcGxpZWQgYXJyYXkuIENlbGwgaW5zZXJ0cyBpbiB0aGUgZ3JpZCB3aWxsIG9ubHkgb2NjdXIgd2hlcmUgdGhlcmUgaXNuJ3Rcblx0ICogYWxyZWFkeSBhIGNlbGwgaW4gdGhhdCBwb3NpdGlvbi5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSBhcnJheSB7b2JqZWN0c30gYW9Tb3VyY2UgTGF5b3V0IGFycmF5IGZyb20gX2ZuRGV0ZWN0SGVhZGVyXG5cdCAqICBAcGFyYW0ge2Jvb2xlYW59IFtiSW5jbHVkZUhpZGRlbj1mYWxzZV0gSWYgdHJ1ZSB0aGVuIGluY2x1ZGUgdGhlIGhpZGRlbiBjb2x1bW5zIGluIHRoZSBjYWxjLFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5EcmF3SGVhZCggb1NldHRpbmdzLCBhb1NvdXJjZSwgYkluY2x1ZGVIaWRkZW4gKVxuXHR7XG5cdFx0dmFyIGksIGlMZW4sIGosIGpMZW4sIGssIGtMZW4sIG4sIG5Mb2NhbFRyO1xuXHRcdHZhciBhb0xvY2FsID0gW107XG5cdFx0dmFyIGFBcHBsaWVkID0gW107XG5cdFx0dmFyIGlDb2x1bW5zID0gb1NldHRpbmdzLmFvQ29sdW1ucy5sZW5ndGg7XG5cdFx0dmFyIGlSb3dzcGFuLCBpQ29sc3Bhbjtcblx0XG5cdFx0aWYgKCAhIGFvU291cmNlIClcblx0XHR7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcblx0XHRpZiAoICBiSW5jbHVkZUhpZGRlbiA9PT0gdW5kZWZpbmVkIClcblx0XHR7XG5cdFx0XHRiSW5jbHVkZUhpZGRlbiA9IGZhbHNlO1xuXHRcdH1cblx0XG5cdFx0LyogTWFrZSBhIGNvcHkgb2YgdGhlIG1hc3RlciBsYXlvdXQgYXJyYXksIGJ1dCB3aXRob3V0IHRoZSB2aXNpYmxlIGNvbHVtbnMgaW4gaXQgKi9cblx0XHRmb3IgKCBpPTAsIGlMZW49YW9Tb3VyY2UubGVuZ3RoIDsgaTxpTGVuIDsgaSsrIClcblx0XHR7XG5cdFx0XHRhb0xvY2FsW2ldID0gYW9Tb3VyY2VbaV0uc2xpY2UoKTtcblx0XHRcdGFvTG9jYWxbaV0ublRyID0gYW9Tb3VyY2VbaV0ublRyO1xuXHRcblx0XHRcdC8qIFJlbW92ZSBhbnkgY29sdW1ucyB3aGljaCBhcmUgY3VycmVudGx5IGhpZGRlbiAqL1xuXHRcdFx0Zm9yICggaj1pQ29sdW1ucy0xIDsgaj49MCA7IGotLSApXG5cdFx0XHR7XG5cdFx0XHRcdGlmICggIW9TZXR0aW5ncy5hb0NvbHVtbnNbal0uYlZpc2libGUgJiYgIWJJbmNsdWRlSGlkZGVuIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGFvTG9jYWxbaV0uc3BsaWNlKCBqLCAxICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XG5cdFx0XHQvKiBQcmVwIHRoZSBhcHBsaWVkIGFycmF5IC0gaXQgbmVlZHMgYW4gZWxlbWVudCBmb3IgZWFjaCByb3cgKi9cblx0XHRcdGFBcHBsaWVkLnB1c2goIFtdICk7XG5cdFx0fVxuXHRcblx0XHRmb3IgKCBpPTAsIGlMZW49YW9Mb2NhbC5sZW5ndGggOyBpPGlMZW4gOyBpKysgKVxuXHRcdHtcblx0XHRcdG5Mb2NhbFRyID0gYW9Mb2NhbFtpXS5uVHI7XG5cdFxuXHRcdFx0LyogQWxsIGNlbGxzIGFyZSBnb2luZyB0byBiZSByZXBsYWNlZCwgc28gZW1wdHkgb3V0IHRoZSByb3cgKi9cblx0XHRcdGlmICggbkxvY2FsVHIgKVxuXHRcdFx0e1xuXHRcdFx0XHR3aGlsZSggKG4gPSBuTG9jYWxUci5maXJzdENoaWxkKSApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRuTG9jYWxUci5yZW1vdmVDaGlsZCggbiApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFxuXHRcdFx0Zm9yICggaj0wLCBqTGVuPWFvTG9jYWxbaV0ubGVuZ3RoIDsgajxqTGVuIDsgaisrIClcblx0XHRcdHtcblx0XHRcdFx0aVJvd3NwYW4gPSAxO1xuXHRcdFx0XHRpQ29sc3BhbiA9IDE7XG5cdFxuXHRcdFx0XHQvKiBDaGVjayB0byBzZWUgaWYgdGhlcmUgaXMgYWxyZWFkeSBhIGNlbGwgKHJvdy9jb2xzcGFuKSBjb3ZlcmluZyBvdXIgdGFyZ2V0XG5cdFx0XHRcdCAqIGluc2VydCBwb2ludC4gSWYgdGhlcmUgaXMsIHRoZW4gdGhlcmUgaXMgbm90aGluZyB0byBkby5cblx0XHRcdFx0ICovXG5cdFx0XHRcdGlmICggYUFwcGxpZWRbaV1bal0gPT09IHVuZGVmaW5lZCApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRuTG9jYWxUci5hcHBlbmRDaGlsZCggYW9Mb2NhbFtpXVtqXS5jZWxsICk7XG5cdFx0XHRcdFx0YUFwcGxpZWRbaV1bal0gPSAxO1xuXHRcblx0XHRcdFx0XHQvKiBFeHBhbmQgdGhlIGNlbGwgdG8gY292ZXIgYXMgbWFueSByb3dzIGFzIG5lZWRlZCAqL1xuXHRcdFx0XHRcdHdoaWxlICggYW9Mb2NhbFtpK2lSb3dzcGFuXSAhPT0gdW5kZWZpbmVkICYmXG5cdFx0XHRcdFx0ICAgICAgICBhb0xvY2FsW2ldW2pdLmNlbGwgPT0gYW9Mb2NhbFtpK2lSb3dzcGFuXVtqXS5jZWxsIClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRhQXBwbGllZFtpK2lSb3dzcGFuXVtqXSA9IDE7XG5cdFx0XHRcdFx0XHRpUm93c3BhbisrO1xuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0LyogRXhwYW5kIHRoZSBjZWxsIHRvIGNvdmVyIGFzIG1hbnkgY29sdW1ucyBhcyBuZWVkZWQgKi9cblx0XHRcdFx0XHR3aGlsZSAoIGFvTG9jYWxbaV1baitpQ29sc3Bhbl0gIT09IHVuZGVmaW5lZCAmJlxuXHRcdFx0XHRcdCAgICAgICAgYW9Mb2NhbFtpXVtqXS5jZWxsID09IGFvTG9jYWxbaV1baitpQ29sc3Bhbl0uY2VsbCApXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0LyogTXVzdCB1cGRhdGUgdGhlIGFwcGxpZWQgYXJyYXkgb3ZlciB0aGUgcm93cyBmb3IgdGhlIGNvbHVtbnMgKi9cblx0XHRcdFx0XHRcdGZvciAoIGs9MCA7IGs8aVJvd3NwYW4gOyBrKysgKVxuXHRcdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0XHRhQXBwbGllZFtpK2tdW2oraUNvbHNwYW5dID0gMTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlDb2xzcGFuKys7XG5cdFx0XHRcdFx0fVxuXHRcblx0XHRcdFx0XHQvKiBEbyB0aGUgYWN0dWFsIGV4cGFuc2lvbiBpbiB0aGUgRE9NICovXG5cdFx0XHRcdFx0JChhb0xvY2FsW2ldW2pdLmNlbGwpXG5cdFx0XHRcdFx0XHQuYXR0cigncm93c3BhbicsIGlSb3dzcGFuKVxuXHRcdFx0XHRcdFx0LmF0dHIoJ2NvbHNwYW4nLCBpQ29sc3Bhbik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogSW5zZXJ0IHRoZSByZXF1aXJlZCBUUiBub2RlcyBpbnRvIHRoZSB0YWJsZSBmb3IgZGlzcGxheVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5EcmF3KCBvU2V0dGluZ3MgKVxuXHR7XG5cdFx0LyogUHJvdmlkZSBhIHByZS1jYWxsYmFjayBmdW5jdGlvbiB3aGljaCBjYW4gYmUgdXNlZCB0byBjYW5jZWwgdGhlIGRyYXcgaXMgZmFsc2UgaXMgcmV0dXJuZWQgKi9cblx0XHR2YXIgYVByZURyYXcgPSBfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgJ2FvUHJlRHJhd0NhbGxiYWNrJywgJ3ByZURyYXcnLCBbb1NldHRpbmdzXSApO1xuXHRcdGlmICggJC5pbkFycmF5KCBmYWxzZSwgYVByZURyYXcgKSAhPT0gLTEgKVxuXHRcdHtcblx0XHRcdF9mblByb2Nlc3NpbmdEaXNwbGF5KCBvU2V0dGluZ3MsIGZhbHNlICk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcblx0XHR2YXIgaSwgaUxlbiwgbjtcblx0XHR2YXIgYW5Sb3dzID0gW107XG5cdFx0dmFyIGlSb3dDb3VudCA9IDA7XG5cdFx0dmFyIGFzU3RyaXBlQ2xhc3NlcyA9IG9TZXR0aW5ncy5hc1N0cmlwZUNsYXNzZXM7XG5cdFx0dmFyIGlTdHJpcGVzID0gYXNTdHJpcGVDbGFzc2VzLmxlbmd0aDtcblx0XHR2YXIgaU9wZW5Sb3dzID0gb1NldHRpbmdzLmFvT3BlblJvd3MubGVuZ3RoO1xuXHRcdHZhciBvTGFuZyA9IG9TZXR0aW5ncy5vTGFuZ3VhZ2U7XG5cdFx0dmFyIGlJbml0RGlzcGxheVN0YXJ0ID0gb1NldHRpbmdzLmlJbml0RGlzcGxheVN0YXJ0O1xuXHRcdHZhciBiU2VydmVyU2lkZSA9IF9mbkRhdGFTb3VyY2UoIG9TZXR0aW5ncyApID09ICdzc3AnO1xuXHRcdHZhciBhaURpc3BsYXkgPSBvU2V0dGluZ3MuYWlEaXNwbGF5O1xuXHRcblx0XHRvU2V0dGluZ3MuYkRyYXdpbmcgPSB0cnVlO1xuXHRcblx0XHQvKiBDaGVjayBhbmQgc2VlIGlmIHdlIGhhdmUgYW4gaW5pdGlhbCBkcmF3IHBvc2l0aW9uIGZyb20gc3RhdGUgc2F2aW5nICovXG5cdFx0aWYgKCBpSW5pdERpc3BsYXlTdGFydCAhPT0gdW5kZWZpbmVkICYmIGlJbml0RGlzcGxheVN0YXJ0ICE9PSAtMSApXG5cdFx0e1xuXHRcdFx0b1NldHRpbmdzLl9pRGlzcGxheVN0YXJ0ID0gYlNlcnZlclNpZGUgP1xuXHRcdFx0XHRpSW5pdERpc3BsYXlTdGFydCA6XG5cdFx0XHRcdGlJbml0RGlzcGxheVN0YXJ0ID49IG9TZXR0aW5ncy5mblJlY29yZHNEaXNwbGF5KCkgP1xuXHRcdFx0XHRcdDAgOlxuXHRcdFx0XHRcdGlJbml0RGlzcGxheVN0YXJ0O1xuXHRcblx0XHRcdG9TZXR0aW5ncy5pSW5pdERpc3BsYXlTdGFydCA9IC0xO1xuXHRcdH1cblx0XG5cdFx0dmFyIGlEaXNwbGF5U3RhcnQgPSBvU2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQ7XG5cdFx0dmFyIGlEaXNwbGF5RW5kID0gb1NldHRpbmdzLmZuRGlzcGxheUVuZCgpO1xuXHRcblx0XHQvKiBTZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIGRyYXcgaW50ZXJjZXB0ICovXG5cdFx0aWYgKCBvU2V0dGluZ3MuYkRlZmVyTG9hZGluZyApXG5cdFx0e1xuXHRcdFx0b1NldHRpbmdzLmJEZWZlckxvYWRpbmcgPSBmYWxzZTtcblx0XHRcdG9TZXR0aW5ncy5pRHJhdysrO1xuXHRcdFx0X2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIG9TZXR0aW5ncywgZmFsc2UgKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoICFiU2VydmVyU2lkZSApXG5cdFx0e1xuXHRcdFx0b1NldHRpbmdzLmlEcmF3Kys7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCAhb1NldHRpbmdzLmJEZXN0cm95aW5nICYmICFfZm5BamF4VXBkYXRlKCBvU2V0dGluZ3MgKSApXG5cdFx0e1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XG5cdFx0aWYgKCBhaURpc3BsYXkubGVuZ3RoICE9PSAwIClcblx0XHR7XG5cdFx0XHR2YXIgaVN0YXJ0ID0gYlNlcnZlclNpZGUgPyAwIDogaURpc3BsYXlTdGFydDtcblx0XHRcdHZhciBpRW5kID0gYlNlcnZlclNpZGUgPyBvU2V0dGluZ3MuYW9EYXRhLmxlbmd0aCA6IGlEaXNwbGF5RW5kO1xuXHRcblx0XHRcdGZvciAoIHZhciBqPWlTdGFydCA7IGo8aUVuZCA7IGorKyApXG5cdFx0XHR7XG5cdFx0XHRcdHZhciBpRGF0YUluZGV4ID0gYWlEaXNwbGF5W2pdO1xuXHRcdFx0XHR2YXIgYW9EYXRhID0gb1NldHRpbmdzLmFvRGF0YVsgaURhdGFJbmRleCBdO1xuXHRcdFx0XHRpZiAoIGFvRGF0YS5uVHIgPT09IG51bGwgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0X2ZuQ3JlYXRlVHIoIG9TZXR0aW5ncywgaURhdGFJbmRleCApO1xuXHRcdFx0XHR9XG5cdFxuXHRcdFx0XHR2YXIgblJvdyA9IGFvRGF0YS5uVHI7XG5cdFxuXHRcdFx0XHQvKiBSZW1vdmUgdGhlIG9sZCBzdHJpcGluZyBjbGFzc2VzIGFuZCB0aGVuIGFkZCB0aGUgbmV3IG9uZSAqL1xuXHRcdFx0XHRpZiAoIGlTdHJpcGVzICE9PSAwIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdHZhciBzU3RyaXBlID0gYXNTdHJpcGVDbGFzc2VzWyBpUm93Q291bnQgJSBpU3RyaXBlcyBdO1xuXHRcdFx0XHRcdGlmICggYW9EYXRhLl9zUm93U3RyaXBlICE9IHNTdHJpcGUgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdCQoblJvdykucmVtb3ZlQ2xhc3MoIGFvRGF0YS5fc1Jvd1N0cmlwZSApLmFkZENsYXNzKCBzU3RyaXBlICk7XG5cdFx0XHRcdFx0XHRhb0RhdGEuX3NSb3dTdHJpcGUgPSBzU3RyaXBlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0Ly8gUm93IGNhbGxiYWNrIGZ1bmN0aW9ucyAtIG1pZ2h0IHdhbnQgdG8gbWFuaXB1bGF0ZSB0aGUgcm93XG5cdFx0XHRcdC8vIGlSb3dDb3VudCBhbmQgaiBhcmUgbm90IGN1cnJlbnRseSBkb2N1bWVudGVkLiBBcmUgdGhleSBhdCBhbGxcblx0XHRcdFx0Ly8gdXNlZnVsP1xuXHRcdFx0XHRfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgJ2FvUm93Q2FsbGJhY2snLCBudWxsLFxuXHRcdFx0XHRcdFtuUm93LCBhb0RhdGEuX2FEYXRhLCBpUm93Q291bnQsIGpdICk7XG5cdFxuXHRcdFx0XHRhblJvd3MucHVzaCggblJvdyApO1xuXHRcdFx0XHRpUm93Q291bnQrKztcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdC8qIFRhYmxlIGlzIGVtcHR5IC0gY3JlYXRlIGEgcm93IHdpdGggYW4gZW1wdHkgbWVzc2FnZSBpbiBpdCAqL1xuXHRcdFx0dmFyIHNaZXJvID0gb0xhbmcuc1plcm9SZWNvcmRzO1xuXHRcdFx0aWYgKCBvU2V0dGluZ3MuaURyYXcgPT0gMSAmJiAgX2ZuRGF0YVNvdXJjZSggb1NldHRpbmdzICkgPT0gJ2FqYXgnIClcblx0XHRcdHtcblx0XHRcdFx0c1plcm8gPSBvTGFuZy5zTG9hZGluZ1JlY29yZHM7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggb0xhbmcuc0VtcHR5VGFibGUgJiYgb1NldHRpbmdzLmZuUmVjb3Jkc1RvdGFsKCkgPT09IDAgKVxuXHRcdFx0e1xuXHRcdFx0XHRzWmVybyA9IG9MYW5nLnNFbXB0eVRhYmxlO1xuXHRcdFx0fVxuXHRcblx0XHRcdGFuUm93c1sgMCBdID0gJCggJzx0ci8+JywgeyAnY2xhc3MnOiBpU3RyaXBlcyA/IGFzU3RyaXBlQ2xhc3Nlc1swXSA6ICcnIH0gKVxuXHRcdFx0XHQuYXBwZW5kKCAkKCc8dGQgLz4nLCB7XG5cdFx0XHRcdFx0J3ZhbGlnbic6ICAndG9wJyxcblx0XHRcdFx0XHQnY29sU3Bhbic6IF9mblZpc2JsZUNvbHVtbnMoIG9TZXR0aW5ncyApLFxuXHRcdFx0XHRcdCdjbGFzcyc6ICAgb1NldHRpbmdzLm9DbGFzc2VzLnNSb3dFbXB0eVxuXHRcdFx0XHR9ICkuaHRtbCggc1plcm8gKSApWzBdO1xuXHRcdH1cblx0XG5cdFx0LyogSGVhZGVyIGFuZCBmb290ZXIgY2FsbGJhY2tzICovXG5cdFx0X2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsICdhb0hlYWRlckNhbGxiYWNrJywgJ2hlYWRlcicsIFsgJChvU2V0dGluZ3MublRIZWFkKS5jaGlsZHJlbigndHInKVswXSxcblx0XHRcdF9mbkdldERhdGFNYXN0ZXIoIG9TZXR0aW5ncyApLCBpRGlzcGxheVN0YXJ0LCBpRGlzcGxheUVuZCwgYWlEaXNwbGF5IF0gKTtcblx0XG5cdFx0X2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsICdhb0Zvb3RlckNhbGxiYWNrJywgJ2Zvb3RlcicsIFsgJChvU2V0dGluZ3MublRGb290KS5jaGlsZHJlbigndHInKVswXSxcblx0XHRcdF9mbkdldERhdGFNYXN0ZXIoIG9TZXR0aW5ncyApLCBpRGlzcGxheVN0YXJ0LCBpRGlzcGxheUVuZCwgYWlEaXNwbGF5IF0gKTtcblx0XG5cdFx0dmFyIGJvZHkgPSAkKG9TZXR0aW5ncy5uVEJvZHkpO1xuXHRcblx0XHRib2R5LmNoaWxkcmVuKCkuZGV0YWNoKCk7XG5cdFx0Ym9keS5hcHBlbmQoICQoYW5Sb3dzKSApO1xuXHRcblx0XHQvKiBDYWxsIGFsbCByZXF1aXJlZCBjYWxsYmFjayBmdW5jdGlvbnMgZm9yIHRoZSBlbmQgb2YgYSBkcmF3ICovXG5cdFx0X2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsICdhb0RyYXdDYWxsYmFjaycsICdkcmF3JywgW29TZXR0aW5nc10gKTtcblx0XG5cdFx0LyogRHJhdyBpcyBjb21wbGV0ZSwgc29ydGluZyBhbmQgZmlsdGVyaW5nIG11c3QgYmUgYXMgd2VsbCAqL1xuXHRcdG9TZXR0aW5ncy5iU29ydGVkID0gZmFsc2U7XG5cdFx0b1NldHRpbmdzLmJGaWx0ZXJlZCA9IGZhbHNlO1xuXHRcdG9TZXR0aW5ncy5iRHJhd2luZyA9IGZhbHNlO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFJlZHJhdyB0aGUgdGFibGUgLSB0YWtpbmcgYWNjb3VudCBvZiB0aGUgdmFyaW91cyBmZWF0dXJlcyB3aGljaCBhcmUgZW5hYmxlZFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtib29sZWFufSBbaG9sZFBvc2l0aW9uXSBLZWVwIHRoZSBjdXJyZW50IHBhZ2luZyBwb3NpdGlvbi4gQnkgZGVmYXVsdFxuXHQgKiAgICB0aGUgcGFnaW5nIGlzIHJlc2V0IHRvIHRoZSBmaXJzdCBwYWdlXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mblJlRHJhdyggc2V0dGluZ3MsIGhvbGRQb3NpdGlvbiApXG5cdHtcblx0XHR2YXJcblx0XHRcdGZlYXR1cmVzID0gc2V0dGluZ3Mub0ZlYXR1cmVzLFxuXHRcdFx0c29ydCAgICAgPSBmZWF0dXJlcy5iU29ydCxcblx0XHRcdGZpbHRlciAgID0gZmVhdHVyZXMuYkZpbHRlcjtcblx0XG5cdFx0aWYgKCBzb3J0ICkge1xuXHRcdFx0X2ZuU29ydCggc2V0dGluZ3MgKTtcblx0XHR9XG5cdFxuXHRcdGlmICggZmlsdGVyICkge1xuXHRcdFx0X2ZuRmlsdGVyQ29tcGxldGUoIHNldHRpbmdzLCBzZXR0aW5ncy5vUHJldmlvdXNTZWFyY2ggKTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHQvLyBObyBmaWx0ZXJpbmcsIHNvIHdlIHdhbnQgdG8ganVzdCB1c2UgdGhlIGRpc3BsYXkgbWFzdGVyXG5cdFx0XHRzZXR0aW5ncy5haURpc3BsYXkgPSBzZXR0aW5ncy5haURpc3BsYXlNYXN0ZXIuc2xpY2UoKTtcblx0XHR9XG5cdFxuXHRcdGlmICggaG9sZFBvc2l0aW9uICE9PSB0cnVlICkge1xuXHRcdFx0c2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgPSAwO1xuXHRcdH1cblx0XG5cdFx0Ly8gTGV0IGFueSBtb2R1bGVzIGtub3cgYWJvdXQgdGhlIGRyYXcgaG9sZCBwb3NpdGlvbiBzdGF0ZSAodXNlZCBieVxuXHRcdC8vIHNjcm9sbGluZyBpbnRlcm5hbGx5KVxuXHRcdHNldHRpbmdzLl9kcmF3SG9sZCA9IGhvbGRQb3NpdGlvbjtcblx0XG5cdFx0X2ZuRHJhdyggc2V0dGluZ3MgKTtcblx0XG5cdFx0c2V0dGluZ3MuX2RyYXdIb2xkID0gZmFsc2U7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQWRkIHRoZSBvcHRpb25zIHRvIHRoZSBwYWdlIEhUTUwgZm9yIHRoZSB0YWJsZVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5BZGRPcHRpb25zSHRtbCAoIG9TZXR0aW5ncyApXG5cdHtcblx0XHR2YXIgY2xhc3NlcyA9IG9TZXR0aW5ncy5vQ2xhc3Nlcztcblx0XHR2YXIgdGFibGUgPSAkKG9TZXR0aW5ncy5uVGFibGUpO1xuXHRcdHZhciBob2xkaW5nID0gJCgnPGRpdi8+JykuaW5zZXJ0QmVmb3JlKCB0YWJsZSApOyAvLyBIb2xkaW5nIGVsZW1lbnQgZm9yIHNwZWVkXG5cdFx0dmFyIGZlYXR1cmVzID0gb1NldHRpbmdzLm9GZWF0dXJlcztcblx0XG5cdFx0Ly8gQWxsIERhdGFUYWJsZXMgYXJlIHdyYXBwZWQgaW4gYSBkaXZcblx0XHR2YXIgaW5zZXJ0ID0gJCgnPGRpdi8+Jywge1xuXHRcdFx0aWQ6ICAgICAgb1NldHRpbmdzLnNUYWJsZUlkKydfd3JhcHBlcicsXG5cdFx0XHQnY2xhc3MnOiBjbGFzc2VzLnNXcmFwcGVyICsgKG9TZXR0aW5ncy5uVEZvb3QgPyAnJyA6ICcgJytjbGFzc2VzLnNOb0Zvb3Rlcilcblx0XHR9ICk7XG5cdFxuXHRcdG9TZXR0aW5ncy5uSG9sZGluZyA9IGhvbGRpbmdbMF07XG5cdFx0b1NldHRpbmdzLm5UYWJsZVdyYXBwZXIgPSBpbnNlcnRbMF07XG5cdFx0b1NldHRpbmdzLm5UYWJsZVJlaW5zZXJ0QmVmb3JlID0gb1NldHRpbmdzLm5UYWJsZS5uZXh0U2libGluZztcblx0XG5cdFx0LyogTG9vcCBvdmVyIHRoZSB1c2VyIHNldCBwb3NpdGlvbmluZyBhbmQgcGxhY2UgdGhlIGVsZW1lbnRzIGFzIG5lZWRlZCAqL1xuXHRcdHZhciBhRG9tID0gb1NldHRpbmdzLnNEb20uc3BsaXQoJycpO1xuXHRcdHZhciBmZWF0dXJlTm9kZSwgY09wdGlvbiwgbk5ld05vZGUsIGNOZXh0LCBzQXR0ciwgajtcblx0XHRmb3IgKCB2YXIgaT0wIDsgaTxhRG9tLmxlbmd0aCA7IGkrKyApXG5cdFx0e1xuXHRcdFx0ZmVhdHVyZU5vZGUgPSBudWxsO1xuXHRcdFx0Y09wdGlvbiA9IGFEb21baV07XG5cdFxuXHRcdFx0aWYgKCBjT3B0aW9uID09ICc8JyApXG5cdFx0XHR7XG5cdFx0XHRcdC8qIE5ldyBjb250YWluZXIgZGl2ICovXG5cdFx0XHRcdG5OZXdOb2RlID0gJCgnPGRpdi8+JylbMF07XG5cdFxuXHRcdFx0XHQvKiBDaGVjayB0byBzZWUgaWYgd2Ugc2hvdWxkIGFwcGVuZCBhbiBpZCBhbmQvb3IgYSBjbGFzcyBuYW1lIHRvIHRoZSBjb250YWluZXIgKi9cblx0XHRcdFx0Y05leHQgPSBhRG9tW2krMV07XG5cdFx0XHRcdGlmICggY05leHQgPT0gXCInXCIgfHwgY05leHQgPT0gJ1wiJyApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRzQXR0ciA9IFwiXCI7XG5cdFx0XHRcdFx0aiA9IDI7XG5cdFx0XHRcdFx0d2hpbGUgKCBhRG9tW2kral0gIT0gY05leHQgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHNBdHRyICs9IGFEb21baStqXTtcblx0XHRcdFx0XHRcdGorKztcblx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdC8qIFJlcGxhY2UgalF1ZXJ5IFVJIGNvbnN0YW50cyBAdG9kbyBkZXByZWNpYXRlZCAqL1xuXHRcdFx0XHRcdGlmICggc0F0dHIgPT0gXCJIXCIgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHNBdHRyID0gY2xhc3Nlcy5zSlVJSGVhZGVyO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIGlmICggc0F0dHIgPT0gXCJGXCIgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdHNBdHRyID0gY2xhc3Nlcy5zSlVJRm9vdGVyO1xuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0LyogVGhlIGF0dHJpYnV0ZSBjYW4gYmUgaW4gdGhlIGZvcm1hdCBvZiBcIiNpZC5jbGFzc1wiLCBcIiNpZFwiIG9yIFwiY2xhc3NcIiBUaGlzIGxvZ2ljXG5cdFx0XHRcdFx0ICogYnJlYWtzIHRoZSBzdHJpbmcgaW50byBwYXJ0cyBhbmQgYXBwbGllcyB0aGVtIGFzIG5lZWRlZFxuXHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdGlmICggc0F0dHIuaW5kZXhPZignLicpICE9IC0xIClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHR2YXIgYVNwbGl0ID0gc0F0dHIuc3BsaXQoJy4nKTtcblx0XHRcdFx0XHRcdG5OZXdOb2RlLmlkID0gYVNwbGl0WzBdLnN1YnN0cigxLCBhU3BsaXRbMF0ubGVuZ3RoLTEpO1xuXHRcdFx0XHRcdFx0bk5ld05vZGUuY2xhc3NOYW1lID0gYVNwbGl0WzFdO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIGlmICggc0F0dHIuY2hhckF0KDApID09IFwiI1wiIClcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRuTmV3Tm9kZS5pZCA9IHNBdHRyLnN1YnN0cigxLCBzQXR0ci5sZW5ndGgtMSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Vcblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRuTmV3Tm9kZS5jbGFzc05hbWUgPSBzQXR0cjtcblx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdGkgKz0gajsgLyogTW92ZSBhbG9uZyB0aGUgcG9zaXRpb24gYXJyYXkgKi9cblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0aW5zZXJ0LmFwcGVuZCggbk5ld05vZGUgKTtcblx0XHRcdFx0aW5zZXJ0ID0gJChuTmV3Tm9kZSk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggY09wdGlvbiA9PSAnPicgKVxuXHRcdFx0e1xuXHRcdFx0XHQvKiBFbmQgY29udGFpbmVyIGRpdiAqL1xuXHRcdFx0XHRpbnNlcnQgPSBpbnNlcnQucGFyZW50KCk7XG5cdFx0XHR9XG5cdFx0XHQvLyBAdG9kbyBNb3ZlIG9wdGlvbnMgaW50byB0aGVpciBvd24gcGx1Z2lucz9cblx0XHRcdGVsc2UgaWYgKCBjT3B0aW9uID09ICdsJyAmJiBmZWF0dXJlcy5iUGFnaW5hdGUgJiYgZmVhdHVyZXMuYkxlbmd0aENoYW5nZSApXG5cdFx0XHR7XG5cdFx0XHRcdC8qIExlbmd0aCAqL1xuXHRcdFx0XHRmZWF0dXJlTm9kZSA9IF9mbkZlYXR1cmVIdG1sTGVuZ3RoKCBvU2V0dGluZ3MgKTtcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKCBjT3B0aW9uID09ICdmJyAmJiBmZWF0dXJlcy5iRmlsdGVyIClcblx0XHRcdHtcblx0XHRcdFx0LyogRmlsdGVyICovXG5cdFx0XHRcdGZlYXR1cmVOb2RlID0gX2ZuRmVhdHVyZUh0bWxGaWx0ZXIoIG9TZXR0aW5ncyApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoIGNPcHRpb24gPT0gJ3InICYmIGZlYXR1cmVzLmJQcm9jZXNzaW5nIClcblx0XHRcdHtcblx0XHRcdFx0LyogcFJvY2Vzc2luZyAqL1xuXHRcdFx0XHRmZWF0dXJlTm9kZSA9IF9mbkZlYXR1cmVIdG1sUHJvY2Vzc2luZyggb1NldHRpbmdzICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggY09wdGlvbiA9PSAndCcgKVxuXHRcdFx0e1xuXHRcdFx0XHQvKiBUYWJsZSAqL1xuXHRcdFx0XHRmZWF0dXJlTm9kZSA9IF9mbkZlYXR1cmVIdG1sVGFibGUoIG9TZXR0aW5ncyApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoIGNPcHRpb24gPT0gICdpJyAmJiBmZWF0dXJlcy5iSW5mbyApXG5cdFx0XHR7XG5cdFx0XHRcdC8qIEluZm8gKi9cblx0XHRcdFx0ZmVhdHVyZU5vZGUgPSBfZm5GZWF0dXJlSHRtbEluZm8oIG9TZXR0aW5ncyApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoIGNPcHRpb24gPT0gJ3AnICYmIGZlYXR1cmVzLmJQYWdpbmF0ZSApXG5cdFx0XHR7XG5cdFx0XHRcdC8qIFBhZ2luYXRpb24gKi9cblx0XHRcdFx0ZmVhdHVyZU5vZGUgPSBfZm5GZWF0dXJlSHRtbFBhZ2luYXRlKCBvU2V0dGluZ3MgKTtcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKCBEYXRhVGFibGUuZXh0LmZlYXR1cmUubGVuZ3RoICE9PSAwIClcblx0XHRcdHtcblx0XHRcdFx0LyogUGx1Zy1pbiBmZWF0dXJlcyAqL1xuXHRcdFx0XHR2YXIgYW9GZWF0dXJlcyA9IERhdGFUYWJsZS5leHQuZmVhdHVyZTtcblx0XHRcdFx0Zm9yICggdmFyIGs9MCwga0xlbj1hb0ZlYXR1cmVzLmxlbmd0aCA7IGs8a0xlbiA7IGsrKyApXG5cdFx0XHRcdHtcblx0XHRcdFx0XHRpZiAoIGNPcHRpb24gPT0gYW9GZWF0dXJlc1trXS5jRmVhdHVyZSApXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0ZmVhdHVyZU5vZGUgPSBhb0ZlYXR1cmVzW2tdLmZuSW5pdCggb1NldHRpbmdzICk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XG5cdFx0XHQvKiBBZGQgdG8gdGhlIDJEIGZlYXR1cmVzIGFycmF5ICovXG5cdFx0XHRpZiAoIGZlYXR1cmVOb2RlIClcblx0XHRcdHtcblx0XHRcdFx0dmFyIGFhbkZlYXR1cmVzID0gb1NldHRpbmdzLmFhbkZlYXR1cmVzO1xuXHRcblx0XHRcdFx0aWYgKCAhIGFhbkZlYXR1cmVzW2NPcHRpb25dIClcblx0XHRcdFx0e1xuXHRcdFx0XHRcdGFhbkZlYXR1cmVzW2NPcHRpb25dID0gW107XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdGFhbkZlYXR1cmVzW2NPcHRpb25dLnB1c2goIGZlYXR1cmVOb2RlICk7XG5cdFx0XHRcdGluc2VydC5hcHBlbmQoIGZlYXR1cmVOb2RlICk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHQvKiBCdWlsdCBvdXIgRE9NIHN0cnVjdHVyZSAtIHJlcGxhY2UgdGhlIGhvbGRpbmcgZGl2IHdpdGggd2hhdCB3ZSB3YW50ICovXG5cdFx0aG9sZGluZy5yZXBsYWNlV2l0aCggaW5zZXJ0ICk7XG5cdFx0b1NldHRpbmdzLm5Ib2xkaW5nID0gbnVsbDtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBVc2UgdGhlIERPTSBzb3VyY2UgdG8gY3JlYXRlIHVwIGFuIGFycmF5IG9mIGhlYWRlciBjZWxscy4gVGhlIGlkZWEgaGVyZSBpcyB0b1xuXHQgKiBjcmVhdGUgYSBsYXlvdXQgZ3JpZCAoYXJyYXkpIG9mIHJvd3MgeCBjb2x1bW5zLCB3aGljaCBjb250YWlucyBhIHJlZmVyZW5jZVxuXHQgKiB0byB0aGUgY2VsbCB0aGF0IHRoYXQgcG9pbnQgaW4gdGhlIGdyaWQgKHJlZ2FyZGxlc3Mgb2YgY29sL3Jvd3NwYW4pLCBzdWNoIHRoYXRcblx0ICogYW55IGNvbHVtbiAvIHJvdyBjb3VsZCBiZSByZW1vdmVkIGFuZCB0aGUgbmV3IGdyaWQgY29uc3RydWN0ZWRcblx0ICogIEBwYXJhbSBhcnJheSB7b2JqZWN0fSBhTGF5b3V0IEFycmF5IHRvIHN0b3JlIHRoZSBjYWxjdWxhdGVkIGxheW91dCBpblxuXHQgKiAgQHBhcmFtIHtub2RlfSBuVGhlYWQgVGhlIGhlYWRlci9mb290ZXIgZWxlbWVudCBmb3IgdGhlIHRhYmxlXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkRldGVjdEhlYWRlciAoIGFMYXlvdXQsIG5UaGVhZCApXG5cdHtcblx0XHR2YXIgblRycyA9ICQoblRoZWFkKS5jaGlsZHJlbigndHInKTtcblx0XHR2YXIgblRyLCBuQ2VsbDtcblx0XHR2YXIgaSwgaywgbCwgaUxlbiwgakxlbiwgaUNvbFNoaWZ0ZWQsIGlDb2x1bW4sIGlDb2xzcGFuLCBpUm93c3Bhbjtcblx0XHR2YXIgYlVuaXF1ZTtcblx0XHR2YXIgZm5TaGlmdENvbCA9IGZ1bmN0aW9uICggYSwgaSwgaiApIHtcblx0XHRcdHZhciBrID0gYVtpXTtcblx0ICAgICAgICAgICAgICAgIHdoaWxlICgga1tqXSApIHtcblx0XHRcdFx0aisrO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGo7XG5cdFx0fTtcblx0XG5cdFx0YUxheW91dC5zcGxpY2UoIDAsIGFMYXlvdXQubGVuZ3RoICk7XG5cdFxuXHRcdC8qIFdlIGtub3cgaG93IG1hbnkgcm93cyB0aGVyZSBhcmUgaW4gdGhlIGxheW91dCAtIHNvIHByZXAgaXQgKi9cblx0XHRmb3IgKCBpPTAsIGlMZW49blRycy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKVxuXHRcdHtcblx0XHRcdGFMYXlvdXQucHVzaCggW10gKTtcblx0XHR9XG5cdFxuXHRcdC8qIENhbGN1bGF0ZSBhIGxheW91dCBhcnJheSAqL1xuXHRcdGZvciAoIGk9MCwgaUxlbj1uVHJzLmxlbmd0aCA7IGk8aUxlbiA7IGkrKyApXG5cdFx0e1xuXHRcdFx0blRyID0gblRyc1tpXTtcblx0XHRcdGlDb2x1bW4gPSAwO1xuXHRcblx0XHRcdC8qIEZvciBldmVyeSBjZWxsIGluIHRoZSByb3cuLi4gKi9cblx0XHRcdG5DZWxsID0gblRyLmZpcnN0Q2hpbGQ7XG5cdFx0XHR3aGlsZSAoIG5DZWxsICkge1xuXHRcdFx0XHRpZiAoIG5DZWxsLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgPT0gXCJURFwiIHx8XG5cdFx0XHRcdCAgICAgbkNlbGwubm9kZU5hbWUudG9VcHBlckNhc2UoKSA9PSBcIlRIXCIgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0LyogR2V0IHRoZSBjb2wgYW5kIHJvd3NwYW4gYXR0cmlidXRlcyBmcm9tIHRoZSBET00gYW5kIHNhbml0aXNlIHRoZW0gKi9cblx0XHRcdFx0XHRpQ29sc3BhbiA9IG5DZWxsLmdldEF0dHJpYnV0ZSgnY29sc3BhbicpICogMTtcblx0XHRcdFx0XHRpUm93c3BhbiA9IG5DZWxsLmdldEF0dHJpYnV0ZSgncm93c3BhbicpICogMTtcblx0XHRcdFx0XHRpQ29sc3BhbiA9ICghaUNvbHNwYW4gfHwgaUNvbHNwYW49PT0wIHx8IGlDb2xzcGFuPT09MSkgPyAxIDogaUNvbHNwYW47XG5cdFx0XHRcdFx0aVJvd3NwYW4gPSAoIWlSb3dzcGFuIHx8IGlSb3dzcGFuPT09MCB8fCBpUm93c3Bhbj09PTEpID8gMSA6IGlSb3dzcGFuO1xuXHRcblx0XHRcdFx0XHQvKiBUaGVyZSBtaWdodCBiZSBjb2xzcGFuIGNlbGxzIGFscmVhZHkgaW4gdGhpcyByb3csIHNvIHNoaWZ0IG91ciB0YXJnZXRcblx0XHRcdFx0XHQgKiBhY2NvcmRpbmdseVxuXHRcdFx0XHRcdCAqL1xuXHRcdFx0XHRcdGlDb2xTaGlmdGVkID0gZm5TaGlmdENvbCggYUxheW91dCwgaSwgaUNvbHVtbiApO1xuXHRcblx0XHRcdFx0XHQvKiBDYWNoZSBjYWxjdWxhdGlvbiBmb3IgdW5pcXVlIGNvbHVtbnMgKi9cblx0XHRcdFx0XHRiVW5pcXVlID0gaUNvbHNwYW4gPT09IDEgPyB0cnVlIDogZmFsc2U7XG5cdFxuXHRcdFx0XHRcdC8qIElmIHRoZXJlIGlzIGNvbCAvIHJvd3NwYW4sIGNvcHkgdGhlIGluZm9ybWF0aW9uIGludG8gdGhlIGxheW91dCBncmlkICovXG5cdFx0XHRcdFx0Zm9yICggbD0wIDsgbDxpQ29sc3BhbiA7IGwrKyApXG5cdFx0XHRcdFx0e1xuXHRcdFx0XHRcdFx0Zm9yICggaz0wIDsgazxpUm93c3BhbiA7IGsrKyApXG5cdFx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRcdGFMYXlvdXRbaStrXVtpQ29sU2hpZnRlZCtsXSA9IHtcblx0XHRcdFx0XHRcdFx0XHRcImNlbGxcIjogbkNlbGwsXG5cdFx0XHRcdFx0XHRcdFx0XCJ1bmlxdWVcIjogYlVuaXF1ZVxuXHRcdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0XHRhTGF5b3V0W2kra10ublRyID0gblRyO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRuQ2VsbCA9IG5DZWxsLm5leHRTaWJsaW5nO1xuXHRcdFx0fVxuXHRcdH1cblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBHZXQgYW4gYXJyYXkgb2YgdW5pcXVlIHRoIGVsZW1lbnRzLCBvbmUgZm9yIGVhY2ggY29sdW1uXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge25vZGV9IG5IZWFkZXIgYXV0b21hdGljYWxseSBkZXRlY3QgdGhlIGxheW91dCBmcm9tIHRoaXMgbm9kZSAtIG9wdGlvbmFsXG5cdCAqICBAcGFyYW0ge2FycmF5fSBhTGF5b3V0IHRoZWFkL3Rmb290IGxheW91dCBmcm9tIF9mbkRldGVjdEhlYWRlciAtIG9wdGlvbmFsXG5cdCAqICBAcmV0dXJucyBhcnJheSB7bm9kZX0gYVJldHVybiBsaXN0IG9mIHVuaXF1ZSB0aCdzXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkdldFVuaXF1ZVRocyAoIG9TZXR0aW5ncywgbkhlYWRlciwgYUxheW91dCApXG5cdHtcblx0XHR2YXIgYVJldHVybiA9IFtdO1xuXHRcdGlmICggIWFMYXlvdXQgKVxuXHRcdHtcblx0XHRcdGFMYXlvdXQgPSBvU2V0dGluZ3MuYW9IZWFkZXI7XG5cdFx0XHRpZiAoIG5IZWFkZXIgKVxuXHRcdFx0e1xuXHRcdFx0XHRhTGF5b3V0ID0gW107XG5cdFx0XHRcdF9mbkRldGVjdEhlYWRlciggYUxheW91dCwgbkhlYWRlciApO1xuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0Zm9yICggdmFyIGk9MCwgaUxlbj1hTGF5b3V0Lmxlbmd0aCA7IGk8aUxlbiA7IGkrKyApXG5cdFx0e1xuXHRcdFx0Zm9yICggdmFyIGo9MCwgakxlbj1hTGF5b3V0W2ldLmxlbmd0aCA7IGo8akxlbiA7IGorKyApXG5cdFx0XHR7XG5cdFx0XHRcdGlmICggYUxheW91dFtpXVtqXS51bmlxdWUgJiZcblx0XHRcdFx0XHQgKCFhUmV0dXJuW2pdIHx8ICFvU2V0dGluZ3MuYlNvcnRDZWxsc1RvcCkgKVxuXHRcdFx0XHR7XG5cdFx0XHRcdFx0YVJldHVybltqXSA9IGFMYXlvdXRbaV1bal0uY2VsbDtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0cmV0dXJuIGFSZXR1cm47XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBDcmVhdGUgYW4gQWpheCBjYWxsIGJhc2VkIG9uIHRoZSB0YWJsZSdzIHNldHRpbmdzLCB0YWtpbmcgaW50byBhY2NvdW50IHRoYXRcblx0ICogcGFyYW1ldGVycyBjYW4gaGF2ZSBtdWx0aXBsZSBmb3JtcywgYW5kIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LlxuXHQgKlxuXHQgKiBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqIEBwYXJhbSB7YXJyYXl9IGRhdGEgRGF0YSB0byBzZW5kIHRvIHRoZSBzZXJ2ZXIsIHJlcXVpcmVkIGJ5XG5cdCAqICAgICBEYXRhVGFibGVzIC0gbWF5IGJlIGF1Z21lbnRlZCBieSBkZXZlbG9wZXIgY2FsbGJhY2tzXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb259IGZuIENhbGxiYWNrIGZ1bmN0aW9uIHRvIHJ1biB3aGVuIGRhdGEgaXMgb2J0YWluZWRcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkJ1aWxkQWpheCggb1NldHRpbmdzLCBkYXRhLCBmbiApXG5cdHtcblx0XHQvLyBDb21wYXRpYmlsaXR5IHdpdGggMS45LSwgYWxsb3cgZm5TZXJ2ZXJEYXRhIGFuZCBldmVudCB0byBtYW5pcHVsYXRlXG5cdFx0X2ZuQ2FsbGJhY2tGaXJlKCBvU2V0dGluZ3MsICdhb1NlcnZlclBhcmFtcycsICdzZXJ2ZXJQYXJhbXMnLCBbZGF0YV0gKTtcblx0XG5cdFx0Ly8gQ29udmVydCB0byBvYmplY3QgYmFzZWQgZm9yIDEuMTArIGlmIHVzaW5nIHRoZSBvbGQgYXJyYXkgc2NoZW1lIHdoaWNoIGNhblxuXHRcdC8vIGNvbWUgZnJvbSBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIG9yIHNlcnZlclBhcmFtc1xuXHRcdGlmICggZGF0YSAmJiAkLmlzQXJyYXkoZGF0YSkgKSB7XG5cdFx0XHR2YXIgdG1wID0ge307XG5cdFx0XHR2YXIgcmJyYWNrZXQgPSAvKC4qPylcXFtcXF0kLztcblx0XG5cdFx0XHQkLmVhY2goIGRhdGEsIGZ1bmN0aW9uIChrZXksIHZhbCkge1xuXHRcdFx0XHR2YXIgbWF0Y2ggPSB2YWwubmFtZS5tYXRjaChyYnJhY2tldCk7XG5cdFxuXHRcdFx0XHRpZiAoIG1hdGNoICkge1xuXHRcdFx0XHRcdC8vIFN1cHBvcnQgZm9yIGFycmF5c1xuXHRcdFx0XHRcdHZhciBuYW1lID0gbWF0Y2hbMF07XG5cdFxuXHRcdFx0XHRcdGlmICggISB0bXBbIG5hbWUgXSApIHtcblx0XHRcdFx0XHRcdHRtcFsgbmFtZSBdID0gW107XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHRtcFsgbmFtZSBdLnB1c2goIHZhbC52YWx1ZSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdHRtcFt2YWwubmFtZV0gPSB2YWwudmFsdWU7XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XHRcdGRhdGEgPSB0bXA7XG5cdFx0fVxuXHRcblx0XHR2YXIgYWpheERhdGE7XG5cdFx0dmFyIGFqYXggPSBvU2V0dGluZ3MuYWpheDtcblx0XHR2YXIgaW5zdGFuY2UgPSBvU2V0dGluZ3Mub0luc3RhbmNlO1xuXHRcdHZhciBjYWxsYmFjayA9IGZ1bmN0aW9uICgganNvbiApIHtcblx0XHRcdF9mbkNhbGxiYWNrRmlyZSggb1NldHRpbmdzLCBudWxsLCAneGhyJywgW29TZXR0aW5ncywganNvbiwgb1NldHRpbmdzLmpxWEhSXSApO1xuXHRcdFx0Zm4oIGpzb24gKTtcblx0XHR9O1xuXHRcblx0XHRpZiAoICQuaXNQbGFpbk9iamVjdCggYWpheCApICYmIGFqYXguZGF0YSApXG5cdFx0e1xuXHRcdFx0YWpheERhdGEgPSBhamF4LmRhdGE7XG5cdFxuXHRcdFx0dmFyIG5ld0RhdGEgPSAkLmlzRnVuY3Rpb24oIGFqYXhEYXRhICkgP1xuXHRcdFx0XHRhamF4RGF0YSggZGF0YSwgb1NldHRpbmdzICkgOiAgLy8gZm4gY2FuIG1hbmlwdWxhdGUgZGF0YSBvciByZXR1cm5cblx0XHRcdFx0YWpheERhdGE7ICAgICAgICAgICAgICAgICAgICAgIC8vIGFuIG9iamVjdCBvYmplY3Qgb3IgYXJyYXkgdG8gbWVyZ2Vcblx0XG5cdFx0XHQvLyBJZiB0aGUgZnVuY3Rpb24gcmV0dXJuZWQgc29tZXRoaW5nLCB1c2UgdGhhdCBhbG9uZVxuXHRcdFx0ZGF0YSA9ICQuaXNGdW5jdGlvbiggYWpheERhdGEgKSAmJiBuZXdEYXRhID9cblx0XHRcdFx0bmV3RGF0YSA6XG5cdFx0XHRcdCQuZXh0ZW5kKCB0cnVlLCBkYXRhLCBuZXdEYXRhICk7XG5cdFxuXHRcdFx0Ly8gUmVtb3ZlIHRoZSBkYXRhIHByb3BlcnR5IGFzIHdlJ3ZlIHJlc29sdmVkIGl0IGFscmVhZHkgYW5kIGRvbid0IHdhbnRcblx0XHRcdC8vIGpRdWVyeSB0byBkbyBpdCBhZ2FpbiAoaXQgaXMgcmVzdG9yZWQgYXQgdGhlIGVuZCBvZiB0aGUgZnVuY3Rpb24pXG5cdFx0XHRkZWxldGUgYWpheC5kYXRhO1xuXHRcdH1cblx0XG5cdFx0dmFyIGJhc2VBamF4ID0ge1xuXHRcdFx0XCJkYXRhXCI6IGRhdGEsXG5cdFx0XHRcInN1Y2Nlc3NcIjogZnVuY3Rpb24gKGpzb24pIHtcblx0XHRcdFx0dmFyIGVycm9yID0ganNvbi5lcnJvciB8fCBqc29uLnNFcnJvcjtcblx0XHRcdFx0aWYgKCBlcnJvciApIHtcblx0XHRcdFx0XHRfZm5Mb2coIG9TZXR0aW5ncywgMCwgZXJyb3IgKTtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0b1NldHRpbmdzLmpzb24gPSBqc29uO1xuXHRcdFx0XHRjYWxsYmFjaygganNvbiApO1xuXHRcdFx0fSxcblx0XHRcdFwiZGF0YVR5cGVcIjogXCJqc29uXCIsXG5cdFx0XHRcImNhY2hlXCI6IGZhbHNlLFxuXHRcdFx0XCJ0eXBlXCI6IG9TZXR0aW5ncy5zU2VydmVyTWV0aG9kLFxuXHRcdFx0XCJlcnJvclwiOiBmdW5jdGlvbiAoeGhyLCBlcnJvciwgdGhyb3duKSB7XG5cdFx0XHRcdHZhciByZXQgPSBfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgbnVsbCwgJ3hocicsIFtvU2V0dGluZ3MsIG51bGwsIG9TZXR0aW5ncy5qcVhIUl0gKTtcblx0XG5cdFx0XHRcdGlmICggJC5pbkFycmF5KCB0cnVlLCByZXQgKSA9PT0gLTEgKSB7XG5cdFx0XHRcdFx0aWYgKCBlcnJvciA9PSBcInBhcnNlcmVycm9yXCIgKSB7XG5cdFx0XHRcdFx0XHRfZm5Mb2coIG9TZXR0aW5ncywgMCwgJ0ludmFsaWQgSlNPTiByZXNwb25zZScsIDEgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSBpZiAoIHhoci5yZWFkeVN0YXRlID09PSA0ICkge1xuXHRcdFx0XHRcdFx0X2ZuTG9nKCBvU2V0dGluZ3MsIDAsICdBamF4IGVycm9yJywgNyApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0X2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIG9TZXR0aW5ncywgZmFsc2UgKTtcblx0XHRcdH1cblx0XHR9O1xuXHRcblx0XHQvLyBTdG9yZSB0aGUgZGF0YSBzdWJtaXR0ZWQgZm9yIHRoZSBBUElcblx0XHRvU2V0dGluZ3Mub0FqYXhEYXRhID0gZGF0YTtcblx0XG5cdFx0Ly8gQWxsb3cgcGx1Zy1pbnMgYW5kIGV4dGVybmFsIHByb2Nlc3NlcyB0byBtb2RpZnkgdGhlIGRhdGFcblx0XHRfZm5DYWxsYmFja0ZpcmUoIG9TZXR0aW5ncywgbnVsbCwgJ3ByZVhocicsIFtvU2V0dGluZ3MsIGRhdGFdICk7XG5cdFxuXHRcdGlmICggb1NldHRpbmdzLmZuU2VydmVyRGF0YSApXG5cdFx0e1xuXHRcdFx0Ly8gRGF0YVRhYmxlcyAxLjktIGNvbXBhdGliaWxpdHlcblx0XHRcdG9TZXR0aW5ncy5mblNlcnZlckRhdGEuY2FsbCggaW5zdGFuY2UsXG5cdFx0XHRcdG9TZXR0aW5ncy5zQWpheFNvdXJjZSxcblx0XHRcdFx0JC5tYXAoIGRhdGEsIGZ1bmN0aW9uICh2YWwsIGtleSkgeyAvLyBOZWVkIHRvIGNvbnZlcnQgYmFjayB0byAxLjkgdHJhZCBmb3JtYXRcblx0XHRcdFx0XHRyZXR1cm4geyBuYW1lOiBrZXksIHZhbHVlOiB2YWwgfTtcblx0XHRcdFx0fSApLFxuXHRcdFx0XHRjYWxsYmFjayxcblx0XHRcdFx0b1NldHRpbmdzXG5cdFx0XHQpO1xuXHRcdH1cblx0XHRlbHNlIGlmICggb1NldHRpbmdzLnNBamF4U291cmNlIHx8IHR5cGVvZiBhamF4ID09PSAnc3RyaW5nJyApXG5cdFx0e1xuXHRcdFx0Ly8gRGF0YVRhYmxlcyAxLjktIGNvbXBhdGliaWxpdHlcblx0XHRcdG9TZXR0aW5ncy5qcVhIUiA9ICQuYWpheCggJC5leHRlbmQoIGJhc2VBamF4LCB7XG5cdFx0XHRcdHVybDogYWpheCB8fCBvU2V0dGluZ3Muc0FqYXhTb3VyY2Vcblx0XHRcdH0gKSApO1xuXHRcdH1cblx0XHRlbHNlIGlmICggJC5pc0Z1bmN0aW9uKCBhamF4ICkgKVxuXHRcdHtcblx0XHRcdC8vIElzIGEgZnVuY3Rpb24gLSBsZXQgdGhlIGNhbGxlciBkZWZpbmUgd2hhdCBuZWVkcyB0byBiZSBkb25lXG5cdFx0XHRvU2V0dGluZ3MuanFYSFIgPSBhamF4LmNhbGwoIGluc3RhbmNlLCBkYXRhLCBjYWxsYmFjaywgb1NldHRpbmdzICk7XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHQvLyBPYmplY3QgdG8gZXh0ZW5kIHRoZSBiYXNlIHNldHRpbmdzXG5cdFx0XHRvU2V0dGluZ3MuanFYSFIgPSAkLmFqYXgoICQuZXh0ZW5kKCBiYXNlQWpheCwgYWpheCApICk7XG5cdFxuXHRcdFx0Ly8gUmVzdG9yZSBmb3IgbmV4dCB0aW1lIGFyb3VuZFxuXHRcdFx0YWpheC5kYXRhID0gYWpheERhdGE7XG5cdFx0fVxuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFVwZGF0ZSB0aGUgdGFibGUgdXNpbmcgYW4gQWpheCBjYWxsXG5cdCAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEByZXR1cm5zIHtib29sZWFufSBCbG9jayB0aGUgdGFibGUgZHJhd2luZyBvciBub3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQWpheFVwZGF0ZSggc2V0dGluZ3MgKVxuXHR7XG5cdFx0aWYgKCBzZXR0aW5ncy5iQWpheERhdGFHZXQgKSB7XG5cdFx0XHRzZXR0aW5ncy5pRHJhdysrO1xuXHRcdFx0X2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIHNldHRpbmdzLCB0cnVlICk7XG5cdFxuXHRcdFx0X2ZuQnVpbGRBamF4KFxuXHRcdFx0XHRzZXR0aW5ncyxcblx0XHRcdFx0X2ZuQWpheFBhcmFtZXRlcnMoIHNldHRpbmdzICksXG5cdFx0XHRcdGZ1bmN0aW9uKGpzb24pIHtcblx0XHRcdFx0XHRfZm5BamF4VXBkYXRlRHJhdyggc2V0dGluZ3MsIGpzb24gKTtcblx0XHRcdFx0fVxuXHRcdFx0KTtcblx0XG5cdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0fVxuXHRcdHJldHVybiB0cnVlO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEJ1aWxkIHVwIHRoZSBwYXJhbWV0ZXJzIGluIGFuIG9iamVjdCBuZWVkZWQgZm9yIGEgc2VydmVyLXNpZGUgcHJvY2Vzc2luZ1xuXHQgKiByZXF1ZXN0LiBOb3RlIHRoYXQgdGhpcyBpcyBiYXNpY2FsbHkgZG9uZSB0d2ljZSwgaXMgZGlmZmVyZW50IHdheXMgLSBhIG1vZGVyblxuXHQgKiBtZXRob2Qgd2hpY2ggaXMgdXNlZCBieSBkZWZhdWx0IGluIERhdGFUYWJsZXMgMS4xMCB3aGljaCB1c2VzIG9iamVjdHMgYW5kXG5cdCAqIGFycmF5cywgb3IgdGhlIDEuOS0gbWV0aG9kIHdpdGggaXMgbmFtZSAvIHZhbHVlIHBhaXJzLiAxLjkgbWV0aG9kIGlzIHVzZWQgaWZcblx0ICogdGhlIHNBamF4U291cmNlIG9wdGlvbiBpcyB1c2VkIGluIHRoZSBpbml0aWFsaXNhdGlvbiwgb3IgdGhlIGxlZ2FjeUFqYXhcblx0ICogb3B0aW9uIGlzIHNldC5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEByZXR1cm5zIHtib29sfSBibG9jayB0aGUgdGFibGUgZHJhd2luZyBvciBub3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQWpheFBhcmFtZXRlcnMoIHNldHRpbmdzIClcblx0e1xuXHRcdHZhclxuXHRcdFx0Y29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1ucyxcblx0XHRcdGNvbHVtbkNvdW50ID0gY29sdW1ucy5sZW5ndGgsXG5cdFx0XHRmZWF0dXJlcyA9IHNldHRpbmdzLm9GZWF0dXJlcyxcblx0XHRcdHByZVNlYXJjaCA9IHNldHRpbmdzLm9QcmV2aW91c1NlYXJjaCxcblx0XHRcdHByZUNvbFNlYXJjaCA9IHNldHRpbmdzLmFvUHJlU2VhcmNoQ29scyxcblx0XHRcdGksIGRhdGEgPSBbXSwgZGF0YVByb3AsIGNvbHVtbiwgY29sdW1uU2VhcmNoLFxuXHRcdFx0c29ydCA9IF9mblNvcnRGbGF0dGVuKCBzZXR0aW5ncyApLFxuXHRcdFx0ZGlzcGxheVN0YXJ0ID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsXG5cdFx0XHRkaXNwbGF5TGVuZ3RoID0gZmVhdHVyZXMuYlBhZ2luYXRlICE9PSBmYWxzZSA/XG5cdFx0XHRcdHNldHRpbmdzLl9pRGlzcGxheUxlbmd0aCA6XG5cdFx0XHRcdC0xO1xuXHRcblx0XHR2YXIgcGFyYW0gPSBmdW5jdGlvbiAoIG5hbWUsIHZhbHVlICkge1xuXHRcdFx0ZGF0YS5wdXNoKCB7ICduYW1lJzogbmFtZSwgJ3ZhbHVlJzogdmFsdWUgfSApO1xuXHRcdH07XG5cdFxuXHRcdC8vIERhdGFUYWJsZXMgMS45LSBjb21wYXRpYmxlIG1ldGhvZFxuXHRcdHBhcmFtKCAnc0VjaG8nLCAgICAgICAgICBzZXR0aW5ncy5pRHJhdyApO1xuXHRcdHBhcmFtKCAnaUNvbHVtbnMnLCAgICAgICBjb2x1bW5Db3VudCApO1xuXHRcdHBhcmFtKCAnc0NvbHVtbnMnLCAgICAgICBfcGx1Y2soIGNvbHVtbnMsICdzTmFtZScgKS5qb2luKCcsJykgKTtcblx0XHRwYXJhbSggJ2lEaXNwbGF5U3RhcnQnLCAgZGlzcGxheVN0YXJ0ICk7XG5cdFx0cGFyYW0oICdpRGlzcGxheUxlbmd0aCcsIGRpc3BsYXlMZW5ndGggKTtcblx0XG5cdFx0Ly8gRGF0YVRhYmxlcyAxLjEwKyBtZXRob2Rcblx0XHR2YXIgZCA9IHtcblx0XHRcdGRyYXc6ICAgIHNldHRpbmdzLmlEcmF3LFxuXHRcdFx0Y29sdW1uczogW10sXG5cdFx0XHRvcmRlcjogICBbXSxcblx0XHRcdHN0YXJ0OiAgIGRpc3BsYXlTdGFydCxcblx0XHRcdGxlbmd0aDogIGRpc3BsYXlMZW5ndGgsXG5cdFx0XHRzZWFyY2g6ICB7XG5cdFx0XHRcdHZhbHVlOiBwcmVTZWFyY2guc1NlYXJjaCxcblx0XHRcdFx0cmVnZXg6IHByZVNlYXJjaC5iUmVnZXhcblx0XHRcdH1cblx0XHR9O1xuXHRcblx0XHRmb3IgKCBpPTAgOyBpPGNvbHVtbkNvdW50IDsgaSsrICkge1xuXHRcdFx0Y29sdW1uID0gY29sdW1uc1tpXTtcblx0XHRcdGNvbHVtblNlYXJjaCA9IHByZUNvbFNlYXJjaFtpXTtcblx0XHRcdGRhdGFQcm9wID0gdHlwZW9mIGNvbHVtbi5tRGF0YT09XCJmdW5jdGlvblwiID8gJ2Z1bmN0aW9uJyA6IGNvbHVtbi5tRGF0YSA7XG5cdFxuXHRcdFx0ZC5jb2x1bW5zLnB1c2goIHtcblx0XHRcdFx0ZGF0YTogICAgICAgZGF0YVByb3AsXG5cdFx0XHRcdG5hbWU6ICAgICAgIGNvbHVtbi5zTmFtZSxcblx0XHRcdFx0c2VhcmNoYWJsZTogY29sdW1uLmJTZWFyY2hhYmxlLFxuXHRcdFx0XHRvcmRlcmFibGU6ICBjb2x1bW4uYlNvcnRhYmxlLFxuXHRcdFx0XHRzZWFyY2g6ICAgICB7XG5cdFx0XHRcdFx0dmFsdWU6IGNvbHVtblNlYXJjaC5zU2VhcmNoLFxuXHRcdFx0XHRcdHJlZ2V4OiBjb2x1bW5TZWFyY2guYlJlZ2V4XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XG5cdFx0XHRwYXJhbSggXCJtRGF0YVByb3BfXCIraSwgZGF0YVByb3AgKTtcblx0XG5cdFx0XHRpZiAoIGZlYXR1cmVzLmJGaWx0ZXIgKSB7XG5cdFx0XHRcdHBhcmFtKCAnc1NlYXJjaF8nK2ksICAgICBjb2x1bW5TZWFyY2guc1NlYXJjaCApO1xuXHRcdFx0XHRwYXJhbSggJ2JSZWdleF8nK2ksICAgICAgY29sdW1uU2VhcmNoLmJSZWdleCApO1xuXHRcdFx0XHRwYXJhbSggJ2JTZWFyY2hhYmxlXycraSwgY29sdW1uLmJTZWFyY2hhYmxlICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0aWYgKCBmZWF0dXJlcy5iU29ydCApIHtcblx0XHRcdFx0cGFyYW0oICdiU29ydGFibGVfJytpLCBjb2x1bW4uYlNvcnRhYmxlICk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHRpZiAoIGZlYXR1cmVzLmJGaWx0ZXIgKSB7XG5cdFx0XHRwYXJhbSggJ3NTZWFyY2gnLCBwcmVTZWFyY2guc1NlYXJjaCApO1xuXHRcdFx0cGFyYW0oICdiUmVnZXgnLCBwcmVTZWFyY2guYlJlZ2V4ICk7XG5cdFx0fVxuXHRcblx0XHRpZiAoIGZlYXR1cmVzLmJTb3J0ICkge1xuXHRcdFx0JC5lYWNoKCBzb3J0LCBmdW5jdGlvbiAoIGksIHZhbCApIHtcblx0XHRcdFx0ZC5vcmRlci5wdXNoKCB7IGNvbHVtbjogdmFsLmNvbCwgZGlyOiB2YWwuZGlyIH0gKTtcblx0XG5cdFx0XHRcdHBhcmFtKCAnaVNvcnRDb2xfJytpLCB2YWwuY29sICk7XG5cdFx0XHRcdHBhcmFtKCAnc1NvcnREaXJfJytpLCB2YWwuZGlyICk7XG5cdFx0XHR9ICk7XG5cdFxuXHRcdFx0cGFyYW0oICdpU29ydGluZ0NvbHMnLCBzb3J0Lmxlbmd0aCApO1xuXHRcdH1cblx0XG5cdFx0Ly8gSWYgdGhlIGxlZ2FjeS5hamF4IHBhcmFtZXRlciBpcyBudWxsLCB0aGVuIHdlIGF1dG9tYXRpY2FsbHkgZGVjaWRlIHdoaWNoXG5cdFx0Ly8gZm9ybSB0byB1c2UsIGJhc2VkIG9uIHNBamF4U291cmNlXG5cdFx0dmFyIGxlZ2FjeSA9IERhdGFUYWJsZS5leHQubGVnYWN5LmFqYXg7XG5cdFx0aWYgKCBsZWdhY3kgPT09IG51bGwgKSB7XG5cdFx0XHRyZXR1cm4gc2V0dGluZ3Muc0FqYXhTb3VyY2UgPyBkYXRhIDogZDtcblx0XHR9XG5cdFxuXHRcdC8vIE90aGVyd2lzZSwgaWYgbGVnYWN5IGhhcyBiZWVuIHNwZWNpZmllZCB0aGVuIHdlIHVzZSB0aGF0IHRvIGRlY2lkZSBvbiB0aGVcblx0XHQvLyBmb3JtXG5cdFx0cmV0dXJuIGxlZ2FjeSA/IGRhdGEgOiBkO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIERhdGEgdGhlIGRhdGEgZnJvbSB0aGUgc2VydmVyIChudWtpbmcgdGhlIG9sZCkgYW5kIHJlZHJhdyB0aGUgdGFibGVcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBqc29uIGpzb24gZGF0YSByZXR1cm4gZnJvbSB0aGUgc2VydmVyLlxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IGpzb24uc0VjaG8gVHJhY2tpbmcgZmxhZyBmb3IgRGF0YVRhYmxlcyB0byBtYXRjaCByZXF1ZXN0c1xuXHQgKiAgQHBhcmFtIHtpbnR9IGpzb24uaVRvdGFsUmVjb3JkcyBOdW1iZXIgb2YgcmVjb3JkcyBpbiB0aGUgZGF0YSBzZXQsIG5vdCBhY2NvdW50aW5nIGZvciBmaWx0ZXJpbmdcblx0ICogIEBwYXJhbSB7aW50fSBqc29uLmlUb3RhbERpc3BsYXlSZWNvcmRzIE51bWJlciBvZiByZWNvcmRzIGluIHRoZSBkYXRhIHNldCwgYWNjb3VudGluZyBmb3IgZmlsdGVyaW5nXG5cdCAqICBAcGFyYW0ge2FycmF5fSBqc29uLmFhRGF0YSBUaGUgZGF0YSB0byBkaXNwbGF5IG9uIHRoaXMgcGFnZVxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IFtqc29uLnNDb2x1bW5zXSBDb2x1bW4gb3JkZXJpbmcgKHNOYW1lLCBjb21tYSBzZXBhcmF0ZWQpXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkFqYXhVcGRhdGVEcmF3ICggc2V0dGluZ3MsIGpzb24gKVxuXHR7XG5cdFx0Ly8gdjEuMTAgdXNlcyBjYW1lbENhc2UgdmFyaWFibGVzLCB3aGlsZSAxLjkgdXNlcyBIdW5nYXJpYW4gbm90YXRpb24uXG5cdFx0Ly8gU3VwcG9ydCBib3RoXG5cdFx0dmFyIGNvbXBhdCA9IGZ1bmN0aW9uICggb2xkLCBtb2Rlcm4gKSB7XG5cdFx0XHRyZXR1cm4ganNvbltvbGRdICE9PSB1bmRlZmluZWQgPyBqc29uW29sZF0gOiBqc29uW21vZGVybl07XG5cdFx0fTtcblx0XG5cdFx0dmFyIGRhdGEgPSBfZm5BamF4RGF0YVNyYyggc2V0dGluZ3MsIGpzb24gKTtcblx0XHR2YXIgZHJhdyAgICAgICAgICAgID0gY29tcGF0KCAnc0VjaG8nLCAgICAgICAgICAgICAgICAnZHJhdycgKTtcblx0XHR2YXIgcmVjb3Jkc1RvdGFsICAgID0gY29tcGF0KCAnaVRvdGFsUmVjb3JkcycsICAgICAgICAncmVjb3Jkc1RvdGFsJyApO1xuXHRcdHZhciByZWNvcmRzRmlsdGVyZWQgPSBjb21wYXQoICdpVG90YWxEaXNwbGF5UmVjb3JkcycsICdyZWNvcmRzRmlsdGVyZWQnICk7XG5cdFxuXHRcdGlmICggZHJhdyApIHtcblx0XHRcdC8vIFByb3RlY3QgYWdhaW5zdCBvdXQgb2Ygc2VxdWVuY2UgcmV0dXJuc1xuXHRcdFx0aWYgKCBkcmF3KjEgPCBzZXR0aW5ncy5pRHJhdyApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcdFx0c2V0dGluZ3MuaURyYXcgPSBkcmF3ICogMTtcblx0XHR9XG5cdFxuXHRcdF9mbkNsZWFyVGFibGUoIHNldHRpbmdzICk7XG5cdFx0c2V0dGluZ3MuX2lSZWNvcmRzVG90YWwgICA9IHBhcnNlSW50KHJlY29yZHNUb3RhbCwgMTApO1xuXHRcdHNldHRpbmdzLl9pUmVjb3Jkc0Rpc3BsYXkgPSBwYXJzZUludChyZWNvcmRzRmlsdGVyZWQsIDEwKTtcblx0XG5cdFx0Zm9yICggdmFyIGk9MCwgaWVuPWRhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRfZm5BZGREYXRhKCBzZXR0aW5ncywgZGF0YVtpXSApO1xuXHRcdH1cblx0XHRzZXR0aW5ncy5haURpc3BsYXkgPSBzZXR0aW5ncy5haURpc3BsYXlNYXN0ZXIuc2xpY2UoKTtcblx0XG5cdFx0c2V0dGluZ3MuYkFqYXhEYXRhR2V0ID0gZmFsc2U7XG5cdFx0X2ZuRHJhdyggc2V0dGluZ3MgKTtcblx0XG5cdFx0aWYgKCAhIHNldHRpbmdzLl9iSW5pdENvbXBsZXRlICkge1xuXHRcdFx0X2ZuSW5pdENvbXBsZXRlKCBzZXR0aW5ncywganNvbiApO1xuXHRcdH1cblx0XG5cdFx0c2V0dGluZ3MuYkFqYXhEYXRhR2V0ID0gdHJ1ZTtcblx0XHRfZm5Qcm9jZXNzaW5nRGlzcGxheSggc2V0dGluZ3MsIGZhbHNlICk7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogR2V0IHRoZSBkYXRhIGZyb20gdGhlIEpTT04gZGF0YSBzb3VyY2UgdG8gdXNlIGZvciBkcmF3aW5nIGEgdGFibGUuIFVzaW5nXG5cdCAqIGBfZm5HZXRPYmplY3REYXRhRm5gIGFsbG93cyB0aGUgZGF0YSB0byBiZSBzb3VyY2VkIGZyb20gYSBwcm9wZXJ0eSBvZiB0aGVcblx0ICogc291cmNlIG9iamVjdCwgb3IgZnJvbSBhIHByb2Nlc3NpbmcgZnVuY3Rpb24uXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0gIHtvYmplY3R9IGpzb24gRGF0YSBzb3VyY2Ugb2JqZWN0IC8gYXJyYXkgZnJvbSB0aGUgc2VydmVyXG5cdCAqICBAcmV0dXJuIHthcnJheX0gQXJyYXkgb2YgZGF0YSB0byB1c2Vcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkFqYXhEYXRhU3JjICggb1NldHRpbmdzLCBqc29uIClcblx0e1xuXHRcdHZhciBkYXRhU3JjID0gJC5pc1BsYWluT2JqZWN0KCBvU2V0dGluZ3MuYWpheCApICYmIG9TZXR0aW5ncy5hamF4LmRhdGFTcmMgIT09IHVuZGVmaW5lZCA/XG5cdFx0XHRvU2V0dGluZ3MuYWpheC5kYXRhU3JjIDpcblx0XHRcdG9TZXR0aW5ncy5zQWpheERhdGFQcm9wOyAvLyBDb21wYXRpYmlsaXR5IHdpdGggMS45LS5cblx0XG5cdFx0Ly8gQ29tcGF0aWJpbGl0eSB3aXRoIDEuOS0uIEluIG9yZGVyIHRvIHJlYWQgZnJvbSBhYURhdGEsIGNoZWNrIGlmIHRoZVxuXHRcdC8vIGRlZmF1bHQgaGFzIGJlZW4gY2hhbmdlZCwgaWYgbm90LCBjaGVjayBmb3IgYWFEYXRhXG5cdFx0aWYgKCBkYXRhU3JjID09PSAnZGF0YScgKSB7XG5cdFx0XHRyZXR1cm4ganNvbi5hYURhdGEgfHwganNvbltkYXRhU3JjXTtcblx0XHR9XG5cdFxuXHRcdHJldHVybiBkYXRhU3JjICE9PSBcIlwiID9cblx0XHRcdF9mbkdldE9iamVjdERhdGFGbiggZGF0YVNyYyApKCBqc29uICkgOlxuXHRcdFx0anNvbjtcblx0fVxuXHRcblx0LyoqXG5cdCAqIEdlbmVyYXRlIHRoZSBub2RlIHJlcXVpcmVkIGZvciBmaWx0ZXJpbmcgdGV4dFxuXHQgKiAgQHJldHVybnMge25vZGV9IEZpbHRlciBjb250cm9sIGVsZW1lbnRcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuRmVhdHVyZUh0bWxGaWx0ZXIgKCBzZXR0aW5ncyApXG5cdHtcblx0XHR2YXIgY2xhc3NlcyA9IHNldHRpbmdzLm9DbGFzc2VzO1xuXHRcdHZhciB0YWJsZUlkID0gc2V0dGluZ3Muc1RhYmxlSWQ7XG5cdFx0dmFyIGxhbmd1YWdlID0gc2V0dGluZ3Mub0xhbmd1YWdlO1xuXHRcdHZhciBwcmV2aW91c1NlYXJjaCA9IHNldHRpbmdzLm9QcmV2aW91c1NlYXJjaDtcblx0XHR2YXIgZmVhdHVyZXMgPSBzZXR0aW5ncy5hYW5GZWF0dXJlcztcblx0XHR2YXIgaW5wdXQgPSAnPGlucHV0IHR5cGU9XCJzZWFyY2hcIiBjbGFzcz1cIicrY2xhc3Nlcy5zRmlsdGVySW5wdXQrJ1wiLz4nO1xuXHRcblx0XHR2YXIgc3RyID0gbGFuZ3VhZ2Uuc1NlYXJjaDtcblx0XHRzdHIgPSBzdHIubWF0Y2goL19JTlBVVF8vKSA/XG5cdFx0XHRzdHIucmVwbGFjZSgnX0lOUFVUXycsIGlucHV0KSA6XG5cdFx0XHRzdHIraW5wdXQ7XG5cdFxuXHRcdHZhciBmaWx0ZXIgPSAkKCc8ZGl2Lz4nLCB7XG5cdFx0XHRcdCdpZCc6ICEgZmVhdHVyZXMuZiA/IHRhYmxlSWQrJ19maWx0ZXInIDogbnVsbCxcblx0XHRcdFx0J2NsYXNzJzogY2xhc3Nlcy5zRmlsdGVyXG5cdFx0XHR9IClcblx0XHRcdC5hcHBlbmQoICQoJzxsYWJlbC8+JyApLmFwcGVuZCggc3RyICkgKTtcblx0XG5cdFx0dmFyIHNlYXJjaEZuID0gZnVuY3Rpb24oKSB7XG5cdFx0XHQvKiBVcGRhdGUgYWxsIG90aGVyIGZpbHRlciBpbnB1dCBlbGVtZW50cyBmb3IgdGhlIG5ldyBkaXNwbGF5ICovXG5cdFx0XHR2YXIgbiA9IGZlYXR1cmVzLmY7XG5cdFx0XHR2YXIgdmFsID0gIXRoaXMudmFsdWUgPyBcIlwiIDogdGhpcy52YWx1ZTsgLy8gbWVudGFsIElFOCBmaXggOi0oXG5cdFxuXHRcdFx0LyogTm93IGRvIHRoZSBmaWx0ZXIgKi9cblx0XHRcdGlmICggdmFsICE9IHByZXZpb3VzU2VhcmNoLnNTZWFyY2ggKSB7XG5cdFx0XHRcdF9mbkZpbHRlckNvbXBsZXRlKCBzZXR0aW5ncywge1xuXHRcdFx0XHRcdFwic1NlYXJjaFwiOiB2YWwsXG5cdFx0XHRcdFx0XCJiUmVnZXhcIjogcHJldmlvdXNTZWFyY2guYlJlZ2V4LFxuXHRcdFx0XHRcdFwiYlNtYXJ0XCI6IHByZXZpb3VzU2VhcmNoLmJTbWFydCAsXG5cdFx0XHRcdFx0XCJiQ2FzZUluc2Vuc2l0aXZlXCI6IHByZXZpb3VzU2VhcmNoLmJDYXNlSW5zZW5zaXRpdmVcblx0XHRcdFx0fSApO1xuXHRcblx0XHRcdFx0Ly8gTmVlZCB0byByZWRyYXcsIHdpdGhvdXQgcmVzb3J0aW5nXG5cdFx0XHRcdHNldHRpbmdzLl9pRGlzcGxheVN0YXJ0ID0gMDtcblx0XHRcdFx0X2ZuRHJhdyggc2V0dGluZ3MgKTtcblx0XHRcdH1cblx0XHR9O1xuXHRcblx0XHR2YXIgc2VhcmNoRGVsYXkgPSBzZXR0aW5ncy5zZWFyY2hEZWxheSAhPT0gbnVsbCA/XG5cdFx0XHRzZXR0aW5ncy5zZWFyY2hEZWxheSA6XG5cdFx0XHRfZm5EYXRhU291cmNlKCBzZXR0aW5ncyApID09PSAnc3NwJyA/XG5cdFx0XHRcdDQwMCA6XG5cdFx0XHRcdDA7XG5cdFxuXHRcdHZhciBqcUZpbHRlciA9ICQoJ2lucHV0JywgZmlsdGVyKVxuXHRcdFx0LnZhbCggcHJldmlvdXNTZWFyY2guc1NlYXJjaCApXG5cdFx0XHQuYXR0ciggJ3BsYWNlaG9sZGVyJywgbGFuZ3VhZ2Uuc1NlYXJjaFBsYWNlaG9sZGVyIClcblx0XHRcdC5vbihcblx0XHRcdFx0J2tleXVwLkRUIHNlYXJjaC5EVCBpbnB1dC5EVCBwYXN0ZS5EVCBjdXQuRFQnLFxuXHRcdFx0XHRzZWFyY2hEZWxheSA/XG5cdFx0XHRcdFx0X2ZuVGhyb3R0bGUoIHNlYXJjaEZuLCBzZWFyY2hEZWxheSApIDpcblx0XHRcdFx0XHRzZWFyY2hGblxuXHRcdFx0KVxuXHRcdFx0Lm9uKCAna2V5cHJlc3MuRFQnLCBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdC8qIFByZXZlbnQgZm9ybSBzdWJtaXNzaW9uICovXG5cdFx0XHRcdGlmICggZS5rZXlDb2RlID09IDEzICkge1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fVxuXHRcdFx0fSApXG5cdFx0XHQuYXR0cignYXJpYS1jb250cm9scycsIHRhYmxlSWQpO1xuXHRcblx0XHQvLyBVcGRhdGUgdGhlIGlucHV0IGVsZW1lbnRzIHdoZW5ldmVyIHRoZSB0YWJsZSBpcyBmaWx0ZXJlZFxuXHRcdCQoc2V0dGluZ3MublRhYmxlKS5vbiggJ3NlYXJjaC5kdC5EVCcsIGZ1bmN0aW9uICggZXYsIHMgKSB7XG5cdFx0XHRpZiAoIHNldHRpbmdzID09PSBzICkge1xuXHRcdFx0XHQvLyBJRTkgdGhyb3dzIGFuICd1bmtub3duIGVycm9yJyBpZiBkb2N1bWVudC5hY3RpdmVFbGVtZW50IGlzIHVzZWRcblx0XHRcdFx0Ly8gaW5zaWRlIGFuIGlmcmFtZSBvciBmcmFtZS4uLlxuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdGlmICgganFGaWx0ZXJbMF0gIT09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgKSB7XG5cdFx0XHRcdFx0XHRqcUZpbHRlci52YWwoIHByZXZpb3VzU2VhcmNoLnNTZWFyY2ggKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0Y2F0Y2ggKCBlICkge31cblx0XHRcdH1cblx0XHR9ICk7XG5cdFxuXHRcdHJldHVybiBmaWx0ZXJbMF07XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogRmlsdGVyIHRoZSB0YWJsZSB1c2luZyBib3RoIHRoZSBnbG9iYWwgZmlsdGVyIGFuZCBjb2x1bW4gYmFzZWQgZmlsdGVyaW5nXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NlYXJjaCBzZWFyY2ggaW5mb3JtYXRpb25cblx0ICogIEBwYXJhbSB7aW50fSBbaUZvcmNlXSBmb3JjZSBhIHJlc2VhcmNoIG9mIHRoZSBtYXN0ZXIgYXJyYXkgKDEpIG9yIG5vdCAodW5kZWZpbmVkIG9yIDApXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkZpbHRlckNvbXBsZXRlICggb1NldHRpbmdzLCBvSW5wdXQsIGlGb3JjZSApXG5cdHtcblx0XHR2YXIgb1ByZXZTZWFyY2ggPSBvU2V0dGluZ3Mub1ByZXZpb3VzU2VhcmNoO1xuXHRcdHZhciBhb1ByZXZTZWFyY2ggPSBvU2V0dGluZ3MuYW9QcmVTZWFyY2hDb2xzO1xuXHRcdHZhciBmblNhdmVGaWx0ZXIgPSBmdW5jdGlvbiAoIG9GaWx0ZXIgKSB7XG5cdFx0XHQvKiBTYXZlIHRoZSBmaWx0ZXJpbmcgdmFsdWVzICovXG5cdFx0XHRvUHJldlNlYXJjaC5zU2VhcmNoID0gb0ZpbHRlci5zU2VhcmNoO1xuXHRcdFx0b1ByZXZTZWFyY2guYlJlZ2V4ID0gb0ZpbHRlci5iUmVnZXg7XG5cdFx0XHRvUHJldlNlYXJjaC5iU21hcnQgPSBvRmlsdGVyLmJTbWFydDtcblx0XHRcdG9QcmV2U2VhcmNoLmJDYXNlSW5zZW5zaXRpdmUgPSBvRmlsdGVyLmJDYXNlSW5zZW5zaXRpdmU7XG5cdFx0fTtcblx0XHR2YXIgZm5SZWdleCA9IGZ1bmN0aW9uICggbyApIHtcblx0XHRcdC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggdGhlIGJFc2NhcGVSZWdleCBvcHRpb25cblx0XHRcdHJldHVybiBvLmJFc2NhcGVSZWdleCAhPT0gdW5kZWZpbmVkID8gIW8uYkVzY2FwZVJlZ2V4IDogby5iUmVnZXg7XG5cdFx0fTtcblx0XG5cdFx0Ly8gUmVzb2x2ZSBhbnkgY29sdW1uIHR5cGVzIHRoYXQgYXJlIHVua25vd24gZHVlIHRvIGFkZGl0aW9uIG9yIGludmFsaWRhdGlvblxuXHRcdC8vIEB0b2RvIEFzIHBlciBzb3J0IC0gY2FuIHRoaXMgYmUgbW92ZWQgaW50byBhbiBldmVudCBoYW5kbGVyP1xuXHRcdF9mbkNvbHVtblR5cGVzKCBvU2V0dGluZ3MgKTtcblx0XG5cdFx0LyogSW4gc2VydmVyLXNpZGUgcHJvY2Vzc2luZyBhbGwgZmlsdGVyaW5nIGlzIGRvbmUgYnkgdGhlIHNlcnZlciwgc28gbm8gcG9pbnQgaGFuZ2luZyBhcm91bmQgaGVyZSAqL1xuXHRcdGlmICggX2ZuRGF0YVNvdXJjZSggb1NldHRpbmdzICkgIT0gJ3NzcCcgKVxuXHRcdHtcblx0XHRcdC8qIEdsb2JhbCBmaWx0ZXIgKi9cblx0XHRcdF9mbkZpbHRlciggb1NldHRpbmdzLCBvSW5wdXQuc1NlYXJjaCwgaUZvcmNlLCBmblJlZ2V4KG9JbnB1dCksIG9JbnB1dC5iU21hcnQsIG9JbnB1dC5iQ2FzZUluc2Vuc2l0aXZlICk7XG5cdFx0XHRmblNhdmVGaWx0ZXIoIG9JbnB1dCApO1xuXHRcblx0XHRcdC8qIE5vdyBkbyB0aGUgaW5kaXZpZHVhbCBjb2x1bW4gZmlsdGVyICovXG5cdFx0XHRmb3IgKCB2YXIgaT0wIDsgaTxhb1ByZXZTZWFyY2gubGVuZ3RoIDsgaSsrIClcblx0XHRcdHtcblx0XHRcdFx0X2ZuRmlsdGVyQ29sdW1uKCBvU2V0dGluZ3MsIGFvUHJldlNlYXJjaFtpXS5zU2VhcmNoLCBpLCBmblJlZ2V4KGFvUHJldlNlYXJjaFtpXSksXG5cdFx0XHRcdFx0YW9QcmV2U2VhcmNoW2ldLmJTbWFydCwgYW9QcmV2U2VhcmNoW2ldLmJDYXNlSW5zZW5zaXRpdmUgKTtcblx0XHRcdH1cblx0XG5cdFx0XHQvKiBDdXN0b20gZmlsdGVyaW5nICovXG5cdFx0XHRfZm5GaWx0ZXJDdXN0b20oIG9TZXR0aW5ncyApO1xuXHRcdH1cblx0XHRlbHNlXG5cdFx0e1xuXHRcdFx0Zm5TYXZlRmlsdGVyKCBvSW5wdXQgKTtcblx0XHR9XG5cdFxuXHRcdC8qIFRlbGwgdGhlIGRyYXcgZnVuY3Rpb24gd2UgaGF2ZSBiZWVuIGZpbHRlcmluZyAqL1xuXHRcdG9TZXR0aW5ncy5iRmlsdGVyZWQgPSB0cnVlO1xuXHRcdF9mbkNhbGxiYWNrRmlyZSggb1NldHRpbmdzLCBudWxsLCAnc2VhcmNoJywgW29TZXR0aW5nc10gKTtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBBcHBseSBjdXN0b20gZmlsdGVyaW5nIGZ1bmN0aW9uc1xuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5GaWx0ZXJDdXN0b20oIHNldHRpbmdzIClcblx0e1xuXHRcdHZhciBmaWx0ZXJzID0gRGF0YVRhYmxlLmV4dC5zZWFyY2g7XG5cdFx0dmFyIGRpc3BsYXlSb3dzID0gc2V0dGluZ3MuYWlEaXNwbGF5O1xuXHRcdHZhciByb3csIHJvd0lkeDtcblx0XG5cdFx0Zm9yICggdmFyIGk9MCwgaWVuPWZpbHRlcnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHR2YXIgcm93cyA9IFtdO1xuXHRcblx0XHRcdC8vIExvb3Agb3ZlciBlYWNoIHJvdyBhbmQgc2VlIGlmIGl0IHNob3VsZCBiZSBpbmNsdWRlZFxuXHRcdFx0Zm9yICggdmFyIGo9MCwgamVuPWRpc3BsYXlSb3dzLmxlbmd0aCA7IGo8amVuIDsgaisrICkge1xuXHRcdFx0XHRyb3dJZHggPSBkaXNwbGF5Um93c1sgaiBdO1xuXHRcdFx0XHRyb3cgPSBzZXR0aW5ncy5hb0RhdGFbIHJvd0lkeCBdO1xuXHRcblx0XHRcdFx0aWYgKCBmaWx0ZXJzW2ldKCBzZXR0aW5ncywgcm93Ll9hRmlsdGVyRGF0YSwgcm93SWR4LCByb3cuX2FEYXRhLCBqICkgKSB7XG5cdFx0XHRcdFx0cm93cy5wdXNoKCByb3dJZHggKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcblx0XHRcdC8vIFNvIHRoZSBhcnJheSByZWZlcmVuY2UgZG9lc24ndCBicmVhayBzZXQgdGhlIHJlc3VsdHMgaW50byB0aGVcblx0XHRcdC8vIGV4aXN0aW5nIGFycmF5XG5cdFx0XHRkaXNwbGF5Um93cy5sZW5ndGggPSAwO1xuXHRcdFx0JC5tZXJnZSggZGlzcGxheVJvd3MsIHJvd3MgKTtcblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogRmlsdGVyIHRoZSB0YWJsZSBvbiBhIHBlci1jb2x1bW4gYmFzaXNcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7c3RyaW5nfSBzSW5wdXQgc3RyaW5nIHRvIGZpbHRlciBvblxuXHQgKiAgQHBhcmFtIHtpbnR9IGlDb2x1bW4gY29sdW1uIHRvIGZpbHRlclxuXHQgKiAgQHBhcmFtIHtib29sfSBiUmVnZXggdHJlYXQgc2VhcmNoIHN0cmluZyBhcyBhIHJlZ3VsYXIgZXhwcmVzc2lvbiBvciBub3Rcblx0ICogIEBwYXJhbSB7Ym9vbH0gYlNtYXJ0IHVzZSBzbWFydCBmaWx0ZXJpbmcgb3Igbm90XG5cdCAqICBAcGFyYW0ge2Jvb2x9IGJDYXNlSW5zZW5zaXRpdmUgRG8gY2FzZSBpbnNlbnN0aXZlIG1hdGNoaW5nIG9yIG5vdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5GaWx0ZXJDb2x1bW4gKCBzZXR0aW5ncywgc2VhcmNoU3RyLCBjb2xJZHgsIHJlZ2V4LCBzbWFydCwgY2FzZUluc2Vuc2l0aXZlIClcblx0e1xuXHRcdGlmICggc2VhcmNoU3RyID09PSAnJyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFxuXHRcdHZhciBkYXRhO1xuXHRcdHZhciBvdXQgPSBbXTtcblx0XHR2YXIgZGlzcGxheSA9IHNldHRpbmdzLmFpRGlzcGxheTtcblx0XHR2YXIgcnBTZWFyY2ggPSBfZm5GaWx0ZXJDcmVhdGVTZWFyY2goIHNlYXJjaFN0ciwgcmVnZXgsIHNtYXJ0LCBjYXNlSW5zZW5zaXRpdmUgKTtcblx0XG5cdFx0Zm9yICggdmFyIGk9MCA7IGk8ZGlzcGxheS5sZW5ndGggOyBpKysgKSB7XG5cdFx0XHRkYXRhID0gc2V0dGluZ3MuYW9EYXRhWyBkaXNwbGF5W2ldIF0uX2FGaWx0ZXJEYXRhWyBjb2xJZHggXTtcblx0XG5cdFx0XHRpZiAoIHJwU2VhcmNoLnRlc3QoIGRhdGEgKSApIHtcblx0XHRcdFx0b3V0LnB1c2goIGRpc3BsYXlbaV0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFxuXHRcdHNldHRpbmdzLmFpRGlzcGxheSA9IG91dDtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBGaWx0ZXIgdGhlIGRhdGEgdGFibGUgYmFzZWQgb24gdXNlciBpbnB1dCBhbmQgZHJhdyB0aGUgdGFibGVcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IGlucHV0IHN0cmluZyB0byBmaWx0ZXIgb25cblx0ICogIEBwYXJhbSB7aW50fSBmb3JjZSBvcHRpb25hbCAtIGZvcmNlIGEgcmVzZWFyY2ggb2YgdGhlIG1hc3RlciBhcnJheSAoMSkgb3Igbm90ICh1bmRlZmluZWQgb3IgMClcblx0ICogIEBwYXJhbSB7Ym9vbH0gcmVnZXggdHJlYXQgYXMgYSByZWd1bGFyIGV4cHJlc3Npb24gb3Igbm90XG5cdCAqICBAcGFyYW0ge2Jvb2x9IHNtYXJ0IHBlcmZvcm0gc21hcnQgZmlsdGVyaW5nIG9yIG5vdFxuXHQgKiAgQHBhcmFtIHtib29sfSBjYXNlSW5zZW5zaXRpdmUgRG8gY2FzZSBpbnNlbnN0aXZlIG1hdGNoaW5nIG9yIG5vdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5GaWx0ZXIoIHNldHRpbmdzLCBpbnB1dCwgZm9yY2UsIHJlZ2V4LCBzbWFydCwgY2FzZUluc2Vuc2l0aXZlIClcblx0e1xuXHRcdHZhciBycFNlYXJjaCA9IF9mbkZpbHRlckNyZWF0ZVNlYXJjaCggaW5wdXQsIHJlZ2V4LCBzbWFydCwgY2FzZUluc2Vuc2l0aXZlICk7XG5cdFx0dmFyIHByZXZTZWFyY2ggPSBzZXR0aW5ncy5vUHJldmlvdXNTZWFyY2guc1NlYXJjaDtcblx0XHR2YXIgZGlzcGxheU1hc3RlciA9IHNldHRpbmdzLmFpRGlzcGxheU1hc3Rlcjtcblx0XHR2YXIgZGlzcGxheSwgaW52YWxpZGF0ZWQsIGk7XG5cdFx0dmFyIGZpbHRlcmVkID0gW107XG5cdFxuXHRcdC8vIE5lZWQgdG8gdGFrZSBhY2NvdW50IG9mIGN1c3RvbSBmaWx0ZXJpbmcgZnVuY3Rpb25zIC0gYWx3YXlzIGZpbHRlclxuXHRcdGlmICggRGF0YVRhYmxlLmV4dC5zZWFyY2gubGVuZ3RoICE9PSAwICkge1xuXHRcdFx0Zm9yY2UgPSB0cnVlO1xuXHRcdH1cblx0XG5cdFx0Ly8gQ2hlY2sgaWYgYW55IG9mIHRoZSByb3dzIHdlcmUgaW52YWxpZGF0ZWRcblx0XHRpbnZhbGlkYXRlZCA9IF9mbkZpbHRlckRhdGEoIHNldHRpbmdzICk7XG5cdFxuXHRcdC8vIElmIHRoZSBpbnB1dCBpcyBibGFuayAtIHdlIGp1c3Qgd2FudCB0aGUgZnVsbCBkYXRhIHNldFxuXHRcdGlmICggaW5wdXQubGVuZ3RoIDw9IDAgKSB7XG5cdFx0XHRzZXR0aW5ncy5haURpc3BsYXkgPSBkaXNwbGF5TWFzdGVyLnNsaWNlKCk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0Ly8gTmV3IHNlYXJjaCAtIHN0YXJ0IGZyb20gdGhlIG1hc3RlciBhcnJheVxuXHRcdFx0aWYgKCBpbnZhbGlkYXRlZCB8fFxuXHRcdFx0XHQgZm9yY2UgfHxcblx0XHRcdFx0IHByZXZTZWFyY2gubGVuZ3RoID4gaW5wdXQubGVuZ3RoIHx8XG5cdFx0XHRcdCBpbnB1dC5pbmRleE9mKHByZXZTZWFyY2gpICE9PSAwIHx8XG5cdFx0XHRcdCBzZXR0aW5ncy5iU29ydGVkIC8vIE9uIHJlc29ydCwgdGhlIGRpc3BsYXkgbWFzdGVyIG5lZWRzIHRvIGJlXG5cdFx0XHRcdCAgICAgICAgICAgICAgICAgIC8vIHJlLWZpbHRlcmVkIHNpbmNlIGluZGV4ZXMgd2lsbCBoYXZlIGNoYW5nZWRcblx0XHRcdCkge1xuXHRcdFx0XHRzZXR0aW5ncy5haURpc3BsYXkgPSBkaXNwbGF5TWFzdGVyLnNsaWNlKCk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gU2VhcmNoIHRoZSBkaXNwbGF5IGFycmF5XG5cdFx0XHRkaXNwbGF5ID0gc2V0dGluZ3MuYWlEaXNwbGF5O1xuXHRcblx0XHRcdGZvciAoIGk9MCA7IGk8ZGlzcGxheS5sZW5ndGggOyBpKysgKSB7XG5cdFx0XHRcdGlmICggcnBTZWFyY2gudGVzdCggc2V0dGluZ3MuYW9EYXRhWyBkaXNwbGF5W2ldIF0uX3NGaWx0ZXJSb3cgKSApIHtcblx0XHRcdFx0XHRmaWx0ZXJlZC5wdXNoKCBkaXNwbGF5W2ldICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XG5cdFx0XHRzZXR0aW5ncy5haURpc3BsYXkgPSBmaWx0ZXJlZDtcblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogQnVpbGQgYSByZWd1bGFyIGV4cHJlc3Npb24gb2JqZWN0IHN1aXRhYmxlIGZvciBzZWFyY2hpbmcgYSB0YWJsZVxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IHNTZWFyY2ggc3RyaW5nIHRvIHNlYXJjaCBmb3Jcblx0ICogIEBwYXJhbSB7Ym9vbH0gYlJlZ2V4IHRyZWF0IGFzIGEgcmVndWxhciBleHByZXNzaW9uIG9yIG5vdFxuXHQgKiAgQHBhcmFtIHtib29sfSBiU21hcnQgcGVyZm9ybSBzbWFydCBmaWx0ZXJpbmcgb3Igbm90XG5cdCAqICBAcGFyYW0ge2Jvb2x9IGJDYXNlSW5zZW5zaXRpdmUgRG8gY2FzZSBpbnNlbnNpdGl2ZSBtYXRjaGluZyBvciBub3Rcblx0ICogIEByZXR1cm5zIHtSZWdFeHB9IGNvbnN0cnVjdGVkIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5GaWx0ZXJDcmVhdGVTZWFyY2goIHNlYXJjaCwgcmVnZXgsIHNtYXJ0LCBjYXNlSW5zZW5zaXRpdmUgKVxuXHR7XG5cdFx0c2VhcmNoID0gcmVnZXggP1xuXHRcdFx0c2VhcmNoIDpcblx0XHRcdF9mbkVzY2FwZVJlZ2V4KCBzZWFyY2ggKTtcblx0XHRcblx0XHRpZiAoIHNtYXJ0ICkge1xuXHRcdFx0LyogRm9yIHNtYXJ0IGZpbHRlcmluZyB3ZSB3YW50IHRvIGFsbG93IHRoZSBzZWFyY2ggdG8gd29yayByZWdhcmRsZXNzIG9mXG5cdFx0XHQgKiB3b3JkIG9yZGVyLiBXZSBhbHNvIHdhbnQgZG91YmxlIHF1b3RlZCB0ZXh0IHRvIGJlIHByZXNlcnZlZCwgc28gd29yZFxuXHRcdFx0ICogb3JkZXIgaXMgaW1wb3J0YW50IC0gYSBsYSBnb29nbGUuIFNvIHRoaXMgaXMgd2hhdCB3ZSB3YW50IHRvXG5cdFx0XHQgKiBnZW5lcmF0ZTpcblx0XHRcdCAqIFxuXHRcdFx0ICogXig/PS4qP1xcYm9uZVxcYikoPz0uKj9cXGJ0d28gdGhyZWVcXGIpKD89Lio/XFxiZm91clxcYikuKiRcblx0XHRcdCAqL1xuXHRcdFx0dmFyIGEgPSAkLm1hcCggc2VhcmNoLm1hdGNoKCAvXCJbXlwiXStcInxbXiBdKy9nICkgfHwgWycnXSwgZnVuY3Rpb24gKCB3b3JkICkge1xuXHRcdFx0XHRpZiAoIHdvcmQuY2hhckF0KDApID09PSAnXCInICkge1xuXHRcdFx0XHRcdHZhciBtID0gd29yZC5tYXRjaCggL15cIiguKilcIiQvICk7XG5cdFx0XHRcdFx0d29yZCA9IG0gPyBtWzFdIDogd29yZDtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0cmV0dXJuIHdvcmQucmVwbGFjZSgnXCInLCAnJyk7XG5cdFx0XHR9ICk7XG5cdFxuXHRcdFx0c2VhcmNoID0gJ14oPz0uKj8nK2Euam9pbiggJykoPz0uKj8nICkrJykuKiQnO1xuXHRcdH1cblx0XG5cdFx0cmV0dXJuIG5ldyBSZWdFeHAoIHNlYXJjaCwgY2FzZUluc2Vuc2l0aXZlID8gJ2knIDogJycgKTtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBFc2NhcGUgYSBzdHJpbmcgc3VjaCB0aGF0IGl0IGNhbiBiZSB1c2VkIGluIGEgcmVndWxhciBleHByZXNzaW9uXG5cdCAqICBAcGFyYW0ge3N0cmluZ30gc1ZhbCBzdHJpbmcgdG8gZXNjYXBlXG5cdCAqICBAcmV0dXJucyB7c3RyaW5nfSBlc2NhcGVkIHN0cmluZ1xuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHR2YXIgX2ZuRXNjYXBlUmVnZXggPSBEYXRhVGFibGUudXRpbC5lc2NhcGVSZWdleDtcblx0XG5cdHZhciBfX2ZpbHRlcl9kaXYgPSAkKCc8ZGl2PicpWzBdO1xuXHR2YXIgX19maWx0ZXJfZGl2X3RleHRDb250ZW50ID0gX19maWx0ZXJfZGl2LnRleHRDb250ZW50ICE9PSB1bmRlZmluZWQ7XG5cdFxuXHQvLyBVcGRhdGUgdGhlIGZpbHRlcmluZyBkYXRhIGZvciBlYWNoIHJvdyBpZiBuZWVkZWQgKGJ5IGludmFsaWRhdGlvbiBvciBmaXJzdCBydW4pXG5cdGZ1bmN0aW9uIF9mbkZpbHRlckRhdGEgKCBzZXR0aW5ncyApXG5cdHtcblx0XHR2YXIgY29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1ucztcblx0XHR2YXIgY29sdW1uO1xuXHRcdHZhciBpLCBqLCBpZW4sIGplbiwgZmlsdGVyRGF0YSwgY2VsbERhdGEsIHJvdztcblx0XHR2YXIgZm9tYXR0ZXJzID0gRGF0YVRhYmxlLmV4dC50eXBlLnNlYXJjaDtcblx0XHR2YXIgd2FzSW52YWxpZGF0ZWQgPSBmYWxzZTtcblx0XG5cdFx0Zm9yICggaT0wLCBpZW49c2V0dGluZ3MuYW9EYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0cm93ID0gc2V0dGluZ3MuYW9EYXRhW2ldO1xuXHRcblx0XHRcdGlmICggISByb3cuX2FGaWx0ZXJEYXRhICkge1xuXHRcdFx0XHRmaWx0ZXJEYXRhID0gW107XG5cdFxuXHRcdFx0XHRmb3IgKCBqPTAsIGplbj1jb2x1bW5zLmxlbmd0aCA7IGo8amVuIDsgaisrICkge1xuXHRcdFx0XHRcdGNvbHVtbiA9IGNvbHVtbnNbal07XG5cdFxuXHRcdFx0XHRcdGlmICggY29sdW1uLmJTZWFyY2hhYmxlICkge1xuXHRcdFx0XHRcdFx0Y2VsbERhdGEgPSBfZm5HZXRDZWxsRGF0YSggc2V0dGluZ3MsIGksIGosICdmaWx0ZXInICk7XG5cdFxuXHRcdFx0XHRcdFx0aWYgKCBmb21hdHRlcnNbIGNvbHVtbi5zVHlwZSBdICkge1xuXHRcdFx0XHRcdFx0XHRjZWxsRGF0YSA9IGZvbWF0dGVyc1sgY29sdW1uLnNUeXBlIF0oIGNlbGxEYXRhICk7XG5cdFx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdFx0Ly8gU2VhcmNoIGluIERhdGFUYWJsZXMgMS4xMCBpcyBzdHJpbmcgYmFzZWQuIEluIDEuMTEgdGhpc1xuXHRcdFx0XHRcdFx0Ly8gc2hvdWxkIGJlIGFsdGVyZWQgdG8gYWxzbyBhbGxvdyBzdHJpY3QgdHlwZSBjaGVja2luZy5cblx0XHRcdFx0XHRcdGlmICggY2VsbERhdGEgPT09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRcdGNlbGxEYXRhID0gJyc7XG5cdFx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdFx0aWYgKCB0eXBlb2YgY2VsbERhdGEgIT09ICdzdHJpbmcnICYmIGNlbGxEYXRhLnRvU3RyaW5nICkge1xuXHRcdFx0XHRcdFx0XHRjZWxsRGF0YSA9IGNlbGxEYXRhLnRvU3RyaW5nKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdFx0Y2VsbERhdGEgPSAnJztcblx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdC8vIElmIGl0IGxvb2tzIGxpa2UgdGhlcmUgaXMgYW4gSFRNTCBlbnRpdHkgaW4gdGhlIHN0cmluZyxcblx0XHRcdFx0XHQvLyBhdHRlbXB0IHRvIGRlY29kZSBpdCBzbyBzb3J0aW5nIHdvcmtzIGFzIGV4cGVjdGVkLiBOb3RlIHRoYXRcblx0XHRcdFx0XHQvLyB3ZSBjb3VsZCB1c2UgYSBzaW5nbGUgbGluZSBvZiBqUXVlcnkgdG8gZG8gdGhpcywgYnV0IHRoZSBET01cblx0XHRcdFx0XHQvLyBtZXRob2QgdXNlZCBoZXJlIGlzIG11Y2ggZmFzdGVyIGh0dHA6Ly9qc3BlcmYuY29tL2h0bWwtZGVjb2RlXG5cdFx0XHRcdFx0aWYgKCBjZWxsRGF0YS5pbmRleE9mICYmIGNlbGxEYXRhLmluZGV4T2YoJyYnKSAhPT0gLTEgKSB7XG5cdFx0XHRcdFx0XHRfX2ZpbHRlcl9kaXYuaW5uZXJIVE1MID0gY2VsbERhdGE7XG5cdFx0XHRcdFx0XHRjZWxsRGF0YSA9IF9fZmlsdGVyX2Rpdl90ZXh0Q29udGVudCA/XG5cdFx0XHRcdFx0XHRcdF9fZmlsdGVyX2Rpdi50ZXh0Q29udGVudCA6XG5cdFx0XHRcdFx0XHRcdF9fZmlsdGVyX2Rpdi5pbm5lclRleHQ7XG5cdFx0XHRcdFx0fVxuXHRcblx0XHRcdFx0XHRpZiAoIGNlbGxEYXRhLnJlcGxhY2UgKSB7XG5cdFx0XHRcdFx0XHRjZWxsRGF0YSA9IGNlbGxEYXRhLnJlcGxhY2UoL1tcXHJcXG5dL2csICcnKTtcblx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdGZpbHRlckRhdGEucHVzaCggY2VsbERhdGEgKTtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0cm93Ll9hRmlsdGVyRGF0YSA9IGZpbHRlckRhdGE7XG5cdFx0XHRcdHJvdy5fc0ZpbHRlclJvdyA9IGZpbHRlckRhdGEuam9pbignICAnKTtcblx0XHRcdFx0d2FzSW52YWxpZGF0ZWQgPSB0cnVlO1xuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0cmV0dXJuIHdhc0ludmFsaWRhdGVkO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIENvbnZlcnQgZnJvbSB0aGUgaW50ZXJuYWwgSHVuZ2FyaWFuIG5vdGF0aW9uIHRvIGNhbWVsQ2FzZSBmb3IgZXh0ZXJuYWxcblx0ICogaW50ZXJhY3Rpb25cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvYmogT2JqZWN0IHRvIGNvbnZlcnRcblx0ICogIEByZXR1cm5zIHtvYmplY3R9IEludmVydGVkIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5TZWFyY2hUb0NhbWVsICggb2JqIClcblx0e1xuXHRcdHJldHVybiB7XG5cdFx0XHRzZWFyY2g6ICAgICAgICAgIG9iai5zU2VhcmNoLFxuXHRcdFx0c21hcnQ6ICAgICAgICAgICBvYmouYlNtYXJ0LFxuXHRcdFx0cmVnZXg6ICAgICAgICAgICBvYmouYlJlZ2V4LFxuXHRcdFx0Y2FzZUluc2Vuc2l0aXZlOiBvYmouYkNhc2VJbnNlbnNpdGl2ZVxuXHRcdH07XG5cdH1cblx0XG5cdFxuXHRcblx0LyoqXG5cdCAqIENvbnZlcnQgZnJvbSBjYW1lbENhc2Ugbm90YXRpb24gdG8gdGhlIGludGVybmFsIEh1bmdhcmlhbi4gV2UgY291bGQgdXNlIHRoZVxuXHQgKiBIdW5nYXJpYW4gY29udmVydCBmdW5jdGlvbiBoZXJlLCBidXQgdGhpcyBpcyBjbGVhbmVyXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb2JqIE9iamVjdCB0byBjb252ZXJ0XG5cdCAqICBAcmV0dXJucyB7b2JqZWN0fSBJbnZlcnRlZCBvYmplY3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuU2VhcmNoVG9IdW5nICggb2JqIClcblx0e1xuXHRcdHJldHVybiB7XG5cdFx0XHRzU2VhcmNoOiAgICAgICAgICBvYmouc2VhcmNoLFxuXHRcdFx0YlNtYXJ0OiAgICAgICAgICAgb2JqLnNtYXJ0LFxuXHRcdFx0YlJlZ2V4OiAgICAgICAgICAgb2JqLnJlZ2V4LFxuXHRcdFx0YkNhc2VJbnNlbnNpdGl2ZTogb2JqLmNhc2VJbnNlbnNpdGl2ZVxuXHRcdH07XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBHZW5lcmF0ZSB0aGUgbm9kZSByZXF1aXJlZCBmb3IgdGhlIGluZm8gZGlzcGxheVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHJldHVybnMge25vZGV9IEluZm9ybWF0aW9uIGVsZW1lbnRcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuRmVhdHVyZUh0bWxJbmZvICggc2V0dGluZ3MgKVxuXHR7XG5cdFx0dmFyXG5cdFx0XHR0aWQgPSBzZXR0aW5ncy5zVGFibGVJZCxcblx0XHRcdG5vZGVzID0gc2V0dGluZ3MuYWFuRmVhdHVyZXMuaSxcblx0XHRcdG4gPSAkKCc8ZGl2Lz4nLCB7XG5cdFx0XHRcdCdjbGFzcyc6IHNldHRpbmdzLm9DbGFzc2VzLnNJbmZvLFxuXHRcdFx0XHQnaWQnOiAhIG5vZGVzID8gdGlkKydfaW5mbycgOiBudWxsXG5cdFx0XHR9ICk7XG5cdFxuXHRcdGlmICggISBub2RlcyApIHtcblx0XHRcdC8vIFVwZGF0ZSBkaXNwbGF5IG9uIGVhY2ggZHJhd1xuXHRcdFx0c2V0dGluZ3MuYW9EcmF3Q2FsbGJhY2sucHVzaCgge1xuXHRcdFx0XHRcImZuXCI6IF9mblVwZGF0ZUluZm8sXG5cdFx0XHRcdFwic05hbWVcIjogXCJpbmZvcm1hdGlvblwiXG5cdFx0XHR9ICk7XG5cdFxuXHRcdFx0blxuXHRcdFx0XHQuYXR0ciggJ3JvbGUnLCAnc3RhdHVzJyApXG5cdFx0XHRcdC5hdHRyKCAnYXJpYS1saXZlJywgJ3BvbGl0ZScgKTtcblx0XG5cdFx0XHQvLyBUYWJsZSBpcyBkZXNjcmliZWQgYnkgb3VyIGluZm8gZGl2XG5cdFx0XHQkKHNldHRpbmdzLm5UYWJsZSkuYXR0ciggJ2FyaWEtZGVzY3JpYmVkYnknLCB0aWQrJ19pbmZvJyApO1xuXHRcdH1cblx0XG5cdFx0cmV0dXJuIG5bMF07XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogVXBkYXRlIHRoZSBpbmZvcm1hdGlvbiBlbGVtZW50cyBpbiB0aGUgZGlzcGxheVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mblVwZGF0ZUluZm8gKCBzZXR0aW5ncyApXG5cdHtcblx0XHQvKiBTaG93IGluZm9ybWF0aW9uIGFib3V0IHRoZSB0YWJsZSAqL1xuXHRcdHZhciBub2RlcyA9IHNldHRpbmdzLmFhbkZlYXR1cmVzLmk7XG5cdFx0aWYgKCBub2Rlcy5sZW5ndGggPT09IDAgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcblx0XHR2YXJcblx0XHRcdGxhbmcgID0gc2V0dGluZ3Mub0xhbmd1YWdlLFxuXHRcdFx0c3RhcnQgPSBzZXR0aW5ncy5faURpc3BsYXlTdGFydCsxLFxuXHRcdFx0ZW5kICAgPSBzZXR0aW5ncy5mbkRpc3BsYXlFbmQoKSxcblx0XHRcdG1heCAgID0gc2V0dGluZ3MuZm5SZWNvcmRzVG90YWwoKSxcblx0XHRcdHRvdGFsID0gc2V0dGluZ3MuZm5SZWNvcmRzRGlzcGxheSgpLFxuXHRcdFx0b3V0ICAgPSB0b3RhbCA/XG5cdFx0XHRcdGxhbmcuc0luZm8gOlxuXHRcdFx0XHRsYW5nLnNJbmZvRW1wdHk7XG5cdFxuXHRcdGlmICggdG90YWwgIT09IG1heCApIHtcblx0XHRcdC8qIFJlY29yZCBzZXQgYWZ0ZXIgZmlsdGVyaW5nICovXG5cdFx0XHRvdXQgKz0gJyAnICsgbGFuZy5zSW5mb0ZpbHRlcmVkO1xuXHRcdH1cblx0XG5cdFx0Ly8gQ29udmVydCB0aGUgbWFjcm9zXG5cdFx0b3V0ICs9IGxhbmcuc0luZm9Qb3N0Rml4O1xuXHRcdG91dCA9IF9mbkluZm9NYWNyb3MoIHNldHRpbmdzLCBvdXQgKTtcblx0XG5cdFx0dmFyIGNhbGxiYWNrID0gbGFuZy5mbkluZm9DYWxsYmFjaztcblx0XHRpZiAoIGNhbGxiYWNrICE9PSBudWxsICkge1xuXHRcdFx0b3V0ID0gY2FsbGJhY2suY2FsbCggc2V0dGluZ3Mub0luc3RhbmNlLFxuXHRcdFx0XHRzZXR0aW5ncywgc3RhcnQsIGVuZCwgbWF4LCB0b3RhbCwgb3V0XG5cdFx0XHQpO1xuXHRcdH1cblx0XG5cdFx0JChub2RlcykuaHRtbCggb3V0ICk7XG5cdH1cblx0XG5cdFxuXHRmdW5jdGlvbiBfZm5JbmZvTWFjcm9zICggc2V0dGluZ3MsIHN0ciApXG5cdHtcblx0XHQvLyBXaGVuIGluZmluaXRlIHNjcm9sbGluZywgd2UgYXJlIGFsd2F5cyBzdGFydGluZyBhdCAxLiBfaURpc3BsYXlTdGFydCBpcyB1c2VkIG9ubHlcblx0XHQvLyBpbnRlcm5hbGx5XG5cdFx0dmFyXG5cdFx0XHRmb3JtYXR0ZXIgID0gc2V0dGluZ3MuZm5Gb3JtYXROdW1iZXIsXG5cdFx0XHRzdGFydCAgICAgID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQrMSxcblx0XHRcdGxlbiAgICAgICAgPSBzZXR0aW5ncy5faURpc3BsYXlMZW5ndGgsXG5cdFx0XHR2aXMgICAgICAgID0gc2V0dGluZ3MuZm5SZWNvcmRzRGlzcGxheSgpLFxuXHRcdFx0YWxsICAgICAgICA9IGxlbiA9PT0gLTE7XG5cdFxuXHRcdHJldHVybiBzdHIuXG5cdFx0XHRyZXBsYWNlKC9fU1RBUlRfL2csIGZvcm1hdHRlci5jYWxsKCBzZXR0aW5ncywgc3RhcnQgKSApLlxuXHRcdFx0cmVwbGFjZSgvX0VORF8vZywgICBmb3JtYXR0ZXIuY2FsbCggc2V0dGluZ3MsIHNldHRpbmdzLmZuRGlzcGxheUVuZCgpICkgKS5cblx0XHRcdHJlcGxhY2UoL19NQVhfL2csICAgZm9ybWF0dGVyLmNhbGwoIHNldHRpbmdzLCBzZXR0aW5ncy5mblJlY29yZHNUb3RhbCgpICkgKS5cblx0XHRcdHJlcGxhY2UoL19UT1RBTF8vZywgZm9ybWF0dGVyLmNhbGwoIHNldHRpbmdzLCB2aXMgKSApLlxuXHRcdFx0cmVwbGFjZSgvX1BBR0VfL2csICBmb3JtYXR0ZXIuY2FsbCggc2V0dGluZ3MsIGFsbCA/IDEgOiBNYXRoLmNlaWwoIHN0YXJ0IC8gbGVuICkgKSApLlxuXHRcdFx0cmVwbGFjZSgvX1BBR0VTXy9nLCBmb3JtYXR0ZXIuY2FsbCggc2V0dGluZ3MsIGFsbCA/IDEgOiBNYXRoLmNlaWwoIHZpcyAvIGxlbiApICkgKTtcblx0fVxuXHRcblx0XG5cdFxuXHQvKipcblx0ICogRHJhdyB0aGUgdGFibGUgZm9yIHRoZSBmaXJzdCB0aW1lLCBhZGRpbmcgYWxsIHJlcXVpcmVkIGZlYXR1cmVzXG5cdCAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuSW5pdGlhbGlzZSAoIHNldHRpbmdzIClcblx0e1xuXHRcdHZhciBpLCBpTGVuLCBpQWpheFN0YXJ0PXNldHRpbmdzLmlJbml0RGlzcGxheVN0YXJ0O1xuXHRcdHZhciBjb2x1bW5zID0gc2V0dGluZ3MuYW9Db2x1bW5zLCBjb2x1bW47XG5cdFx0dmFyIGZlYXR1cmVzID0gc2V0dGluZ3Mub0ZlYXR1cmVzO1xuXHRcdHZhciBkZWZlckxvYWRpbmcgPSBzZXR0aW5ncy5iRGVmZXJMb2FkaW5nOyAvLyB2YWx1ZSBtb2RpZmllZCBieSB0aGUgZHJhd1xuXHRcblx0XHQvKiBFbnN1cmUgdGhhdCB0aGUgdGFibGUgZGF0YSBpcyBmdWxseSBpbml0aWFsaXNlZCAqL1xuXHRcdGlmICggISBzZXR0aW5ncy5iSW5pdGlhbGlzZWQgKSB7XG5cdFx0XHRzZXRUaW1lb3V0KCBmdW5jdGlvbigpeyBfZm5Jbml0aWFsaXNlKCBzZXR0aW5ncyApOyB9LCAyMDAgKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFxuXHRcdC8qIFNob3cgdGhlIGRpc3BsYXkgSFRNTCBvcHRpb25zICovXG5cdFx0X2ZuQWRkT3B0aW9uc0h0bWwoIHNldHRpbmdzICk7XG5cdFxuXHRcdC8qIEJ1aWxkIGFuZCBkcmF3IHRoZSBoZWFkZXIgLyBmb290ZXIgZm9yIHRoZSB0YWJsZSAqL1xuXHRcdF9mbkJ1aWxkSGVhZCggc2V0dGluZ3MgKTtcblx0XHRfZm5EcmF3SGVhZCggc2V0dGluZ3MsIHNldHRpbmdzLmFvSGVhZGVyICk7XG5cdFx0X2ZuRHJhd0hlYWQoIHNldHRpbmdzLCBzZXR0aW5ncy5hb0Zvb3RlciApO1xuXHRcblx0XHQvKiBPa2F5IHRvIHNob3cgdGhhdCBzb21ldGhpbmcgaXMgZ29pbmcgb24gbm93ICovXG5cdFx0X2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIHNldHRpbmdzLCB0cnVlICk7XG5cdFxuXHRcdC8qIENhbGN1bGF0ZSBzaXplcyBmb3IgY29sdW1ucyAqL1xuXHRcdGlmICggZmVhdHVyZXMuYkF1dG9XaWR0aCApIHtcblx0XHRcdF9mbkNhbGN1bGF0ZUNvbHVtbldpZHRocyggc2V0dGluZ3MgKTtcblx0XHR9XG5cdFxuXHRcdGZvciAoIGk9MCwgaUxlbj1jb2x1bW5zLmxlbmd0aCA7IGk8aUxlbiA7IGkrKyApIHtcblx0XHRcdGNvbHVtbiA9IGNvbHVtbnNbaV07XG5cdFxuXHRcdFx0aWYgKCBjb2x1bW4uc1dpZHRoICkge1xuXHRcdFx0XHRjb2x1bW4ublRoLnN0eWxlLndpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIGNvbHVtbi5zV2lkdGggKTtcblx0XHRcdH1cblx0XHR9XG5cdFxuXHRcdF9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsIG51bGwsICdwcmVJbml0JywgW3NldHRpbmdzXSApO1xuXHRcblx0XHQvLyBJZiB0aGVyZSBpcyBkZWZhdWx0IHNvcnRpbmcgcmVxdWlyZWQgLSBsZXQncyBkbyBpdC4gVGhlIHNvcnQgZnVuY3Rpb25cblx0XHQvLyB3aWxsIGRvIHRoZSBkcmF3aW5nIGZvciB1cy4gT3RoZXJ3aXNlIHdlIGRyYXcgdGhlIHRhYmxlIHJlZ2FyZGxlc3Mgb2YgdGhlXG5cdFx0Ly8gQWpheCBzb3VyY2UgLSB0aGlzIGFsbG93cyB0aGUgdGFibGUgdG8gbG9vayBpbml0aWFsaXNlZCBmb3IgQWpheCBzb3VyY2luZ1xuXHRcdC8vIGRhdGEgKHNob3cgJ2xvYWRpbmcnIG1lc3NhZ2UgcG9zc2libHkpXG5cdFx0X2ZuUmVEcmF3KCBzZXR0aW5ncyApO1xuXHRcblx0XHQvLyBTZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIGluaXQgY29tcGxldGUgaXMgZG9uZSBieSBfZm5BamF4VXBkYXRlRHJhd1xuXHRcdHZhciBkYXRhU3JjID0gX2ZuRGF0YVNvdXJjZSggc2V0dGluZ3MgKTtcblx0XHRpZiAoIGRhdGFTcmMgIT0gJ3NzcCcgfHwgZGVmZXJMb2FkaW5nICkge1xuXHRcdFx0Ly8gaWYgdGhlcmUgaXMgYW4gYWpheCBzb3VyY2UgbG9hZCB0aGUgZGF0YVxuXHRcdFx0aWYgKCBkYXRhU3JjID09ICdhamF4JyApIHtcblx0XHRcdFx0X2ZuQnVpbGRBamF4KCBzZXR0aW5ncywgW10sIGZ1bmN0aW9uKGpzb24pIHtcblx0XHRcdFx0XHR2YXIgYURhdGEgPSBfZm5BamF4RGF0YVNyYyggc2V0dGluZ3MsIGpzb24gKTtcblx0XG5cdFx0XHRcdFx0Ly8gR290IHRoZSBkYXRhIC0gYWRkIGl0IHRvIHRoZSB0YWJsZVxuXHRcdFx0XHRcdGZvciAoIGk9MCA7IGk8YURhdGEubGVuZ3RoIDsgaSsrICkge1xuXHRcdFx0XHRcdFx0X2ZuQWRkRGF0YSggc2V0dGluZ3MsIGFEYXRhW2ldICk7XG5cdFx0XHRcdFx0fVxuXHRcblx0XHRcdFx0XHQvLyBSZXNldCB0aGUgaW5pdCBkaXNwbGF5IGZvciBjb29raWUgc2F2aW5nLiBXZSd2ZSBhbHJlYWR5IGRvbmVcblx0XHRcdFx0XHQvLyBhIGZpbHRlciwgYW5kIHRoZXJlZm9yZSBjbGVhcmVkIGl0IGJlZm9yZS4gU28gd2UgbmVlZCB0byBtYWtlXG5cdFx0XHRcdFx0Ly8gaXQgYXBwZWFyICdmcmVzaCdcblx0XHRcdFx0XHRzZXR0aW5ncy5pSW5pdERpc3BsYXlTdGFydCA9IGlBamF4U3RhcnQ7XG5cdFxuXHRcdFx0XHRcdF9mblJlRHJhdyggc2V0dGluZ3MgKTtcblx0XG5cdFx0XHRcdFx0X2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIHNldHRpbmdzLCBmYWxzZSApO1xuXHRcdFx0XHRcdF9mbkluaXRDb21wbGV0ZSggc2V0dGluZ3MsIGpzb24gKTtcblx0XHRcdFx0fSwgc2V0dGluZ3MgKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRfZm5Qcm9jZXNzaW5nRGlzcGxheSggc2V0dGluZ3MsIGZhbHNlICk7XG5cdFx0XHRcdF9mbkluaXRDb21wbGV0ZSggc2V0dGluZ3MgKTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogRHJhdyB0aGUgdGFibGUgZm9yIHRoZSBmaXJzdCB0aW1lLCBhZGRpbmcgYWxsIHJlcXVpcmVkIGZlYXR1cmVzXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge29iamVjdH0gW2pzb25dIEpTT04gZnJvbSB0aGUgc2VydmVyIHRoYXQgY29tcGxldGVkIHRoZSB0YWJsZSwgaWYgdXNpbmcgQWpheCBzb3VyY2Vcblx0ICogICAgd2l0aCBjbGllbnQtc2lkZSBwcm9jZXNzaW5nIChvcHRpb25hbClcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuSW5pdENvbXBsZXRlICggc2V0dGluZ3MsIGpzb24gKVxuXHR7XG5cdFx0c2V0dGluZ3MuX2JJbml0Q29tcGxldGUgPSB0cnVlO1xuXHRcblx0XHQvLyBXaGVuIGRhdGEgd2FzIGFkZGVkIGFmdGVyIHRoZSBpbml0aWFsaXNhdGlvbiAoZGF0YSBvciBBamF4KSB3ZSBuZWVkIHRvXG5cdFx0Ly8gY2FsY3VsYXRlIHRoZSBjb2x1bW4gc2l6aW5nXG5cdFx0aWYgKCBqc29uIHx8IHNldHRpbmdzLm9Jbml0LmFhRGF0YSApIHtcblx0XHRcdF9mbkFkanVzdENvbHVtblNpemluZyggc2V0dGluZ3MgKTtcblx0XHR9XG5cdFxuXHRcdF9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsIG51bGwsICdwbHVnaW4taW5pdCcsIFtzZXR0aW5ncywganNvbl0gKTtcblx0XHRfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCAnYW9Jbml0Q29tcGxldGUnLCAnaW5pdCcsIFtzZXR0aW5ncywganNvbl0gKTtcblx0fVxuXHRcblx0XG5cdGZ1bmN0aW9uIF9mbkxlbmd0aENoYW5nZSAoIHNldHRpbmdzLCB2YWwgKVxuXHR7XG5cdFx0dmFyIGxlbiA9IHBhcnNlSW50KCB2YWwsIDEwICk7XG5cdFx0c2V0dGluZ3MuX2lEaXNwbGF5TGVuZ3RoID0gbGVuO1xuXHRcblx0XHRfZm5MZW5ndGhPdmVyZmxvdyggc2V0dGluZ3MgKTtcblx0XG5cdFx0Ly8gRmlyZSBsZW5ndGggY2hhbmdlIGV2ZW50XG5cdFx0X2ZuQ2FsbGJhY2tGaXJlKCBzZXR0aW5ncywgbnVsbCwgJ2xlbmd0aCcsIFtzZXR0aW5ncywgbGVuXSApO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEdlbmVyYXRlIHRoZSBub2RlIHJlcXVpcmVkIGZvciB1c2VyIGRpc3BsYXkgbGVuZ3RoIGNoYW5naW5nXG5cdCAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEByZXR1cm5zIHtub2RlfSBEaXNwbGF5IGxlbmd0aCBmZWF0dXJlIG5vZGVcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuRmVhdHVyZUh0bWxMZW5ndGggKCBzZXR0aW5ncyApXG5cdHtcblx0XHR2YXJcblx0XHRcdGNsYXNzZXMgID0gc2V0dGluZ3Mub0NsYXNzZXMsXG5cdFx0XHR0YWJsZUlkICA9IHNldHRpbmdzLnNUYWJsZUlkLFxuXHRcdFx0bWVudSAgICAgPSBzZXR0aW5ncy5hTGVuZ3RoTWVudSxcblx0XHRcdGQyICAgICAgID0gJC5pc0FycmF5KCBtZW51WzBdICksXG5cdFx0XHRsZW5ndGhzICA9IGQyID8gbWVudVswXSA6IG1lbnUsXG5cdFx0XHRsYW5ndWFnZSA9IGQyID8gbWVudVsxXSA6IG1lbnU7XG5cdFxuXHRcdHZhciBzZWxlY3QgPSAkKCc8c2VsZWN0Lz4nLCB7XG5cdFx0XHQnbmFtZSc6ICAgICAgICAgIHRhYmxlSWQrJ19sZW5ndGgnLFxuXHRcdFx0J2FyaWEtY29udHJvbHMnOiB0YWJsZUlkLFxuXHRcdFx0J2NsYXNzJzogICAgICAgICBjbGFzc2VzLnNMZW5ndGhTZWxlY3Rcblx0XHR9ICk7XG5cdFxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1sZW5ndGhzLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0c2VsZWN0WzBdWyBpIF0gPSBuZXcgT3B0aW9uKFxuXHRcdFx0XHR0eXBlb2YgbGFuZ3VhZ2VbaV0gPT09ICdudW1iZXInID9cblx0XHRcdFx0XHRzZXR0aW5ncy5mbkZvcm1hdE51bWJlciggbGFuZ3VhZ2VbaV0gKSA6XG5cdFx0XHRcdFx0bGFuZ3VhZ2VbaV0sXG5cdFx0XHRcdGxlbmd0aHNbaV1cblx0XHRcdCk7XG5cdFx0fVxuXHRcblx0XHR2YXIgZGl2ID0gJCgnPGRpdj48bGFiZWwvPjwvZGl2PicpLmFkZENsYXNzKCBjbGFzc2VzLnNMZW5ndGggKTtcblx0XHRpZiAoICEgc2V0dGluZ3MuYWFuRmVhdHVyZXMubCApIHtcblx0XHRcdGRpdlswXS5pZCA9IHRhYmxlSWQrJ19sZW5ndGgnO1xuXHRcdH1cblx0XG5cdFx0ZGl2LmNoaWxkcmVuKCkuYXBwZW5kKFxuXHRcdFx0c2V0dGluZ3Mub0xhbmd1YWdlLnNMZW5ndGhNZW51LnJlcGxhY2UoICdfTUVOVV8nLCBzZWxlY3RbMF0ub3V0ZXJIVE1MIClcblx0XHQpO1xuXHRcblx0XHQvLyBDYW4ndCB1c2UgYHNlbGVjdGAgdmFyaWFibGUgYXMgdXNlciBtaWdodCBwcm92aWRlIHRoZWlyIG93biBhbmQgdGhlXG5cdFx0Ly8gcmVmZXJlbmNlIGlzIGJyb2tlbiBieSB0aGUgdXNlIG9mIG91dGVySFRNTFxuXHRcdCQoJ3NlbGVjdCcsIGRpdilcblx0XHRcdC52YWwoIHNldHRpbmdzLl9pRGlzcGxheUxlbmd0aCApXG5cdFx0XHQub24oICdjaGFuZ2UuRFQnLCBmdW5jdGlvbihlKSB7XG5cdFx0XHRcdF9mbkxlbmd0aENoYW5nZSggc2V0dGluZ3MsICQodGhpcykudmFsKCkgKTtcblx0XHRcdFx0X2ZuRHJhdyggc2V0dGluZ3MgKTtcblx0XHRcdH0gKTtcblx0XG5cdFx0Ly8gVXBkYXRlIG5vZGUgdmFsdWUgd2hlbmV2ZXIgYW55dGhpbmcgY2hhbmdlcyB0aGUgdGFibGUncyBsZW5ndGhcblx0XHQkKHNldHRpbmdzLm5UYWJsZSkub24oICdsZW5ndGguZHQuRFQnLCBmdW5jdGlvbiAoZSwgcywgbGVuKSB7XG5cdFx0XHRpZiAoIHNldHRpbmdzID09PSBzICkge1xuXHRcdFx0XHQkKCdzZWxlY3QnLCBkaXYpLnZhbCggbGVuICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHRcblx0XHRyZXR1cm4gZGl2WzBdO1xuXHR9XG5cdFxuXHRcblx0XG5cdC8qICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG5cdCAqIE5vdGUgdGhhdCBtb3N0IG9mIHRoZSBwYWdpbmcgbG9naWMgaXMgZG9uZSBpblxuXHQgKiBEYXRhVGFibGUuZXh0LnBhZ2VyXG5cdCAqL1xuXHRcblx0LyoqXG5cdCAqIEdlbmVyYXRlIHRoZSBub2RlIHJlcXVpcmVkIGZvciBkZWZhdWx0IHBhZ2luYXRpb25cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEByZXR1cm5zIHtub2RlfSBQYWdpbmF0aW9uIGZlYXR1cmUgbm9kZVxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5GZWF0dXJlSHRtbFBhZ2luYXRlICggc2V0dGluZ3MgKVxuXHR7XG5cdFx0dmFyXG5cdFx0XHR0eXBlICAgPSBzZXR0aW5ncy5zUGFnaW5hdGlvblR5cGUsXG5cdFx0XHRwbHVnaW4gPSBEYXRhVGFibGUuZXh0LnBhZ2VyWyB0eXBlIF0sXG5cdFx0XHRtb2Rlcm4gPSB0eXBlb2YgcGx1Z2luID09PSAnZnVuY3Rpb24nLFxuXHRcdFx0cmVkcmF3ID0gZnVuY3Rpb24oIHNldHRpbmdzICkge1xuXHRcdFx0XHRfZm5EcmF3KCBzZXR0aW5ncyApO1xuXHRcdFx0fSxcblx0XHRcdG5vZGUgPSAkKCc8ZGl2Lz4nKS5hZGRDbGFzcyggc2V0dGluZ3Mub0NsYXNzZXMuc1BhZ2luZyArIHR5cGUgKVswXSxcblx0XHRcdGZlYXR1cmVzID0gc2V0dGluZ3MuYWFuRmVhdHVyZXM7XG5cdFxuXHRcdGlmICggISBtb2Rlcm4gKSB7XG5cdFx0XHRwbHVnaW4uZm5Jbml0KCBzZXR0aW5ncywgbm9kZSwgcmVkcmF3ICk7XG5cdFx0fVxuXHRcblx0XHQvKiBBZGQgYSBkcmF3IGNhbGxiYWNrIGZvciB0aGUgcGFnaW5hdGlvbiBvbiBmaXJzdCBpbnN0YW5jZSwgdG8gdXBkYXRlIHRoZSBwYWdpbmcgZGlzcGxheSAqL1xuXHRcdGlmICggISBmZWF0dXJlcy5wIClcblx0XHR7XG5cdFx0XHRub2RlLmlkID0gc2V0dGluZ3Muc1RhYmxlSWQrJ19wYWdpbmF0ZSc7XG5cdFxuXHRcdFx0c2V0dGluZ3MuYW9EcmF3Q2FsbGJhY2sucHVzaCgge1xuXHRcdFx0XHRcImZuXCI6IGZ1bmN0aW9uKCBzZXR0aW5ncyApIHtcblx0XHRcdFx0XHRpZiAoIG1vZGVybiApIHtcblx0XHRcdFx0XHRcdHZhclxuXHRcdFx0XHRcdFx0XHRzdGFydCAgICAgID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsXG5cdFx0XHRcdFx0XHRcdGxlbiAgICAgICAgPSBzZXR0aW5ncy5faURpc3BsYXlMZW5ndGgsXG5cdFx0XHRcdFx0XHRcdHZpc1JlY29yZHMgPSBzZXR0aW5ncy5mblJlY29yZHNEaXNwbGF5KCksXG5cdFx0XHRcdFx0XHRcdGFsbCAgICAgICAgPSBsZW4gPT09IC0xLFxuXHRcdFx0XHRcdFx0XHRwYWdlID0gYWxsID8gMCA6IE1hdGguY2VpbCggc3RhcnQgLyBsZW4gKSxcblx0XHRcdFx0XHRcdFx0cGFnZXMgPSBhbGwgPyAxIDogTWF0aC5jZWlsKCB2aXNSZWNvcmRzIC8gbGVuICksXG5cdFx0XHRcdFx0XHRcdGJ1dHRvbnMgPSBwbHVnaW4ocGFnZSwgcGFnZXMpLFxuXHRcdFx0XHRcdFx0XHRpLCBpZW47XG5cdFxuXHRcdFx0XHRcdFx0Zm9yICggaT0wLCBpZW49ZmVhdHVyZXMucC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0XHRcdFx0X2ZuUmVuZGVyZXIoIHNldHRpbmdzLCAncGFnZUJ1dHRvbicgKShcblx0XHRcdFx0XHRcdFx0XHRzZXR0aW5ncywgZmVhdHVyZXMucFtpXSwgaSwgYnV0dG9ucywgcGFnZSwgcGFnZXNcblx0XHRcdFx0XHRcdFx0KTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRwbHVnaW4uZm5VcGRhdGUoIHNldHRpbmdzLCByZWRyYXcgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdFwic05hbWVcIjogXCJwYWdpbmF0aW9uXCJcblx0XHRcdH0gKTtcblx0XHR9XG5cdFxuXHRcdHJldHVybiBub2RlO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEFsdGVyIHRoZSBkaXNwbGF5IHNldHRpbmdzIHRvIGNoYW5nZSB0aGUgcGFnZVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge3N0cmluZ3xpbnR9IGFjdGlvbiBQYWdpbmcgYWN0aW9uIHRvIHRha2U6IFwiZmlyc3RcIiwgXCJwcmV2aW91c1wiLFxuXHQgKiAgICBcIm5leHRcIiBvciBcImxhc3RcIiBvciBwYWdlIG51bWJlciB0byBqdW1wIHRvIChpbnRlZ2VyKVxuXHQgKiAgQHBhcmFtIFtib29sXSByZWRyYXcgQXV0b21hdGljYWxseSBkcmF3IHRoZSB1cGRhdGUgb3Igbm90XG5cdCAqICBAcmV0dXJucyB7Ym9vbH0gdHJ1ZSBwYWdlIGhhcyBjaGFuZ2VkLCBmYWxzZSAtIG5vIGNoYW5nZVxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5QYWdlQ2hhbmdlICggc2V0dGluZ3MsIGFjdGlvbiwgcmVkcmF3IClcblx0e1xuXHRcdHZhclxuXHRcdFx0c3RhcnQgICAgID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsXG5cdFx0XHRsZW4gICAgICAgPSBzZXR0aW5ncy5faURpc3BsYXlMZW5ndGgsXG5cdFx0XHRyZWNvcmRzICAgPSBzZXR0aW5ncy5mblJlY29yZHNEaXNwbGF5KCk7XG5cdFxuXHRcdGlmICggcmVjb3JkcyA9PT0gMCB8fCBsZW4gPT09IC0xIClcblx0XHR7XG5cdFx0XHRzdGFydCA9IDA7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCB0eXBlb2YgYWN0aW9uID09PSBcIm51bWJlclwiIClcblx0XHR7XG5cdFx0XHRzdGFydCA9IGFjdGlvbiAqIGxlbjtcblx0XG5cdFx0XHRpZiAoIHN0YXJ0ID4gcmVjb3JkcyApXG5cdFx0XHR7XG5cdFx0XHRcdHN0YXJ0ID0gMDtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZSBpZiAoIGFjdGlvbiA9PSBcImZpcnN0XCIgKVxuXHRcdHtcblx0XHRcdHN0YXJ0ID0gMDtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIGFjdGlvbiA9PSBcInByZXZpb3VzXCIgKVxuXHRcdHtcblx0XHRcdHN0YXJ0ID0gbGVuID49IDAgP1xuXHRcdFx0XHRzdGFydCAtIGxlbiA6XG5cdFx0XHRcdDA7XG5cdFxuXHRcdFx0aWYgKCBzdGFydCA8IDAgKVxuXHRcdFx0e1xuXHRcdFx0ICBzdGFydCA9IDA7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCBhY3Rpb24gPT0gXCJuZXh0XCIgKVxuXHRcdHtcblx0XHRcdGlmICggc3RhcnQgKyBsZW4gPCByZWNvcmRzIClcblx0XHRcdHtcblx0XHRcdFx0c3RhcnQgKz0gbGVuO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggYWN0aW9uID09IFwibGFzdFwiIClcblx0XHR7XG5cdFx0XHRzdGFydCA9IE1hdGguZmxvb3IoIChyZWNvcmRzLTEpIC8gbGVuKSAqIGxlbjtcblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdF9mbkxvZyggc2V0dGluZ3MsIDAsIFwiVW5rbm93biBwYWdpbmcgYWN0aW9uOiBcIithY3Rpb24sIDUgKTtcblx0XHR9XG5cdFxuXHRcdHZhciBjaGFuZ2VkID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgIT09IHN0YXJ0O1xuXHRcdHNldHRpbmdzLl9pRGlzcGxheVN0YXJ0ID0gc3RhcnQ7XG5cdFxuXHRcdGlmICggY2hhbmdlZCApIHtcblx0XHRcdF9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsIG51bGwsICdwYWdlJywgW3NldHRpbmdzXSApO1xuXHRcblx0XHRcdGlmICggcmVkcmF3ICkge1xuXHRcdFx0XHRfZm5EcmF3KCBzZXR0aW5ncyApO1xuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0cmV0dXJuIGNoYW5nZWQ7XG5cdH1cblx0XG5cdFxuXHRcblx0LyoqXG5cdCAqIEdlbmVyYXRlIHRoZSBub2RlIHJlcXVpcmVkIGZvciB0aGUgcHJvY2Vzc2luZyBub2RlXG5cdCAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEByZXR1cm5zIHtub2RlfSBQcm9jZXNzaW5nIGVsZW1lbnRcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuRmVhdHVyZUh0bWxQcm9jZXNzaW5nICggc2V0dGluZ3MgKVxuXHR7XG5cdFx0cmV0dXJuICQoJzxkaXYvPicsIHtcblx0XHRcdFx0J2lkJzogISBzZXR0aW5ncy5hYW5GZWF0dXJlcy5yID8gc2V0dGluZ3Muc1RhYmxlSWQrJ19wcm9jZXNzaW5nJyA6IG51bGwsXG5cdFx0XHRcdCdjbGFzcyc6IHNldHRpbmdzLm9DbGFzc2VzLnNQcm9jZXNzaW5nXG5cdFx0XHR9IClcblx0XHRcdC5odG1sKCBzZXR0aW5ncy5vTGFuZ3VhZ2Uuc1Byb2Nlc3NpbmcgKVxuXHRcdFx0Lmluc2VydEJlZm9yZSggc2V0dGluZ3MublRhYmxlIClbMF07XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogRGlzcGxheSBvciBoaWRlIHRoZSBwcm9jZXNzaW5nIGluZGljYXRvclxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge2Jvb2x9IHNob3cgU2hvdyB0aGUgcHJvY2Vzc2luZyBpbmRpY2F0b3IgKHRydWUpIG9yIG5vdCAoZmFsc2UpXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mblByb2Nlc3NpbmdEaXNwbGF5ICggc2V0dGluZ3MsIHNob3cgKVxuXHR7XG5cdFx0aWYgKCBzZXR0aW5ncy5vRmVhdHVyZXMuYlByb2Nlc3NpbmcgKSB7XG5cdFx0XHQkKHNldHRpbmdzLmFhbkZlYXR1cmVzLnIpLmNzcyggJ2Rpc3BsYXknLCBzaG93ID8gJ2Jsb2NrJyA6ICdub25lJyApO1xuXHRcdH1cblx0XG5cdFx0X2ZuQ2FsbGJhY2tGaXJlKCBzZXR0aW5ncywgbnVsbCwgJ3Byb2Nlc3NpbmcnLCBbc2V0dGluZ3MsIHNob3ddICk7XG5cdH1cblx0XG5cdC8qKlxuXHQgKiBBZGQgYW55IGNvbnRyb2wgZWxlbWVudHMgZm9yIHRoZSB0YWJsZSAtIHNwZWNpZmljYWxseSBzY3JvbGxpbmdcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHJldHVybnMge25vZGV9IE5vZGUgdG8gYWRkIHRvIHRoZSBET01cblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuRmVhdHVyZUh0bWxUYWJsZSAoIHNldHRpbmdzIClcblx0e1xuXHRcdHZhciB0YWJsZSA9ICQoc2V0dGluZ3MublRhYmxlKTtcblx0XG5cdFx0Ly8gQWRkIHRoZSBBUklBIGdyaWQgcm9sZSB0byB0aGUgdGFibGVcblx0XHR0YWJsZS5hdHRyKCAncm9sZScsICdncmlkJyApO1xuXHRcblx0XHQvLyBTY3JvbGxpbmcgZnJvbSBoZXJlIG9uIGluXG5cdFx0dmFyIHNjcm9sbCA9IHNldHRpbmdzLm9TY3JvbGw7XG5cdFxuXHRcdGlmICggc2Nyb2xsLnNYID09PSAnJyAmJiBzY3JvbGwuc1kgPT09ICcnICkge1xuXHRcdFx0cmV0dXJuIHNldHRpbmdzLm5UYWJsZTtcblx0XHR9XG5cdFxuXHRcdHZhciBzY3JvbGxYID0gc2Nyb2xsLnNYO1xuXHRcdHZhciBzY3JvbGxZID0gc2Nyb2xsLnNZO1xuXHRcdHZhciBjbGFzc2VzID0gc2V0dGluZ3Mub0NsYXNzZXM7XG5cdFx0dmFyIGNhcHRpb24gPSB0YWJsZS5jaGlsZHJlbignY2FwdGlvbicpO1xuXHRcdHZhciBjYXB0aW9uU2lkZSA9IGNhcHRpb24ubGVuZ3RoID8gY2FwdGlvblswXS5fY2FwdGlvblNpZGUgOiBudWxsO1xuXHRcdHZhciBoZWFkZXJDbG9uZSA9ICQoIHRhYmxlWzBdLmNsb25lTm9kZShmYWxzZSkgKTtcblx0XHR2YXIgZm9vdGVyQ2xvbmUgPSAkKCB0YWJsZVswXS5jbG9uZU5vZGUoZmFsc2UpICk7XG5cdFx0dmFyIGZvb3RlciA9IHRhYmxlLmNoaWxkcmVuKCd0Zm9vdCcpO1xuXHRcdHZhciBfZGl2ID0gJzxkaXYvPic7XG5cdFx0dmFyIHNpemUgPSBmdW5jdGlvbiAoIHMgKSB7XG5cdFx0XHRyZXR1cm4gIXMgPyBudWxsIDogX2ZuU3RyaW5nVG9Dc3MoIHMgKTtcblx0XHR9O1xuXHRcblx0XHRpZiAoICEgZm9vdGVyLmxlbmd0aCApIHtcblx0XHRcdGZvb3RlciA9IG51bGw7XG5cdFx0fVxuXHRcblx0XHQvKlxuXHRcdCAqIFRoZSBIVE1MIHN0cnVjdHVyZSB0aGF0IHdlIHdhbnQgdG8gZ2VuZXJhdGUgaW4gdGhpcyBmdW5jdGlvbiBpczpcblx0XHQgKiAgZGl2IC0gc2Nyb2xsZXJcblx0XHQgKiAgICBkaXYgLSBzY3JvbGwgaGVhZFxuXHRcdCAqICAgICAgZGl2IC0gc2Nyb2xsIGhlYWQgaW5uZXJcblx0XHQgKiAgICAgICAgdGFibGUgLSBzY3JvbGwgaGVhZCB0YWJsZVxuXHRcdCAqICAgICAgICAgIHRoZWFkIC0gdGhlYWRcblx0XHQgKiAgICBkaXYgLSBzY3JvbGwgYm9keVxuXHRcdCAqICAgICAgdGFibGUgLSB0YWJsZSAobWFzdGVyIHRhYmxlKVxuXHRcdCAqICAgICAgICB0aGVhZCAtIHRoZWFkIGNsb25lIGZvciBzaXppbmdcblx0XHQgKiAgICAgICAgdGJvZHkgLSB0Ym9keVxuXHRcdCAqICAgIGRpdiAtIHNjcm9sbCBmb290XG5cdFx0ICogICAgICBkaXYgLSBzY3JvbGwgZm9vdCBpbm5lclxuXHRcdCAqICAgICAgICB0YWJsZSAtIHNjcm9sbCBmb290IHRhYmxlXG5cdFx0ICogICAgICAgICAgdGZvb3QgLSB0Zm9vdFxuXHRcdCAqL1xuXHRcdHZhciBzY3JvbGxlciA9ICQoIF9kaXYsIHsgJ2NsYXNzJzogY2xhc3Nlcy5zU2Nyb2xsV3JhcHBlciB9IClcblx0XHRcdC5hcHBlbmQoXG5cdFx0XHRcdCQoX2RpdiwgeyAnY2xhc3MnOiBjbGFzc2VzLnNTY3JvbGxIZWFkIH0gKVxuXHRcdFx0XHRcdC5jc3MoIHtcblx0XHRcdFx0XHRcdG92ZXJmbG93OiAnaGlkZGVuJyxcblx0XHRcdFx0XHRcdHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuXHRcdFx0XHRcdFx0Ym9yZGVyOiAwLFxuXHRcdFx0XHRcdFx0d2lkdGg6IHNjcm9sbFggPyBzaXplKHNjcm9sbFgpIDogJzEwMCUnXG5cdFx0XHRcdFx0fSApXG5cdFx0XHRcdFx0LmFwcGVuZChcblx0XHRcdFx0XHRcdCQoX2RpdiwgeyAnY2xhc3MnOiBjbGFzc2VzLnNTY3JvbGxIZWFkSW5uZXIgfSApXG5cdFx0XHRcdFx0XHRcdC5jc3MoIHtcblx0XHRcdFx0XHRcdFx0XHQnYm94LXNpemluZyc6ICdjb250ZW50LWJveCcsXG5cdFx0XHRcdFx0XHRcdFx0d2lkdGg6IHNjcm9sbC5zWElubmVyIHx8ICcxMDAlJ1xuXHRcdFx0XHRcdFx0XHR9IClcblx0XHRcdFx0XHRcdFx0LmFwcGVuZChcblx0XHRcdFx0XHRcdFx0XHRoZWFkZXJDbG9uZVxuXHRcdFx0XHRcdFx0XHRcdFx0LnJlbW92ZUF0dHIoJ2lkJylcblx0XHRcdFx0XHRcdFx0XHRcdC5jc3MoICdtYXJnaW4tbGVmdCcsIDAgKVxuXHRcdFx0XHRcdFx0XHRcdFx0LmFwcGVuZCggY2FwdGlvblNpZGUgPT09ICd0b3AnID8gY2FwdGlvbiA6IG51bGwgKVxuXHRcdFx0XHRcdFx0XHRcdFx0LmFwcGVuZChcblx0XHRcdFx0XHRcdFx0XHRcdFx0dGFibGUuY2hpbGRyZW4oJ3RoZWFkJylcblx0XHRcdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdFx0KVxuXHRcdFx0XHRcdClcblx0XHRcdClcblx0XHRcdC5hcHBlbmQoXG5cdFx0XHRcdCQoX2RpdiwgeyAnY2xhc3MnOiBjbGFzc2VzLnNTY3JvbGxCb2R5IH0gKVxuXHRcdFx0XHRcdC5jc3MoIHtcblx0XHRcdFx0XHRcdHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuXHRcdFx0XHRcdFx0b3ZlcmZsb3c6ICdhdXRvJyxcblx0XHRcdFx0XHRcdHdpZHRoOiBzaXplKCBzY3JvbGxYIClcblx0XHRcdFx0XHR9IClcblx0XHRcdFx0XHQuYXBwZW5kKCB0YWJsZSApXG5cdFx0XHQpO1xuXHRcblx0XHRpZiAoIGZvb3RlciApIHtcblx0XHRcdHNjcm9sbGVyLmFwcGVuZChcblx0XHRcdFx0JChfZGl2LCB7ICdjbGFzcyc6IGNsYXNzZXMuc1Njcm9sbEZvb3QgfSApXG5cdFx0XHRcdFx0LmNzcygge1xuXHRcdFx0XHRcdFx0b3ZlcmZsb3c6ICdoaWRkZW4nLFxuXHRcdFx0XHRcdFx0Ym9yZGVyOiAwLFxuXHRcdFx0XHRcdFx0d2lkdGg6IHNjcm9sbFggPyBzaXplKHNjcm9sbFgpIDogJzEwMCUnXG5cdFx0XHRcdFx0fSApXG5cdFx0XHRcdFx0LmFwcGVuZChcblx0XHRcdFx0XHRcdCQoX2RpdiwgeyAnY2xhc3MnOiBjbGFzc2VzLnNTY3JvbGxGb290SW5uZXIgfSApXG5cdFx0XHRcdFx0XHRcdC5hcHBlbmQoXG5cdFx0XHRcdFx0XHRcdFx0Zm9vdGVyQ2xvbmVcblx0XHRcdFx0XHRcdFx0XHRcdC5yZW1vdmVBdHRyKCdpZCcpXG5cdFx0XHRcdFx0XHRcdFx0XHQuY3NzKCAnbWFyZ2luLWxlZnQnLCAwIClcblx0XHRcdFx0XHRcdFx0XHRcdC5hcHBlbmQoIGNhcHRpb25TaWRlID09PSAnYm90dG9tJyA/IGNhcHRpb24gOiBudWxsIClcblx0XHRcdFx0XHRcdFx0XHRcdC5hcHBlbmQoXG5cdFx0XHRcdFx0XHRcdFx0XHRcdHRhYmxlLmNoaWxkcmVuKCd0Zm9vdCcpXG5cdFx0XHRcdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHQpXG5cdFx0XHQpO1xuXHRcdH1cblx0XG5cdFx0dmFyIGNoaWxkcmVuID0gc2Nyb2xsZXIuY2hpbGRyZW4oKTtcblx0XHR2YXIgc2Nyb2xsSGVhZCA9IGNoaWxkcmVuWzBdO1xuXHRcdHZhciBzY3JvbGxCb2R5ID0gY2hpbGRyZW5bMV07XG5cdFx0dmFyIHNjcm9sbEZvb3QgPSBmb290ZXIgPyBjaGlsZHJlblsyXSA6IG51bGw7XG5cdFxuXHRcdC8vIFdoZW4gdGhlIGJvZHkgaXMgc2Nyb2xsZWQsIHRoZW4gd2UgYWxzbyB3YW50IHRvIHNjcm9sbCB0aGUgaGVhZGVyc1xuXHRcdGlmICggc2Nyb2xsWCApIHtcblx0XHRcdCQoc2Nyb2xsQm9keSkub24oICdzY3JvbGwuRFQnLCBmdW5jdGlvbiAoZSkge1xuXHRcdFx0XHR2YXIgc2Nyb2xsTGVmdCA9IHRoaXMuc2Nyb2xsTGVmdDtcblx0XG5cdFx0XHRcdHNjcm9sbEhlYWQuc2Nyb2xsTGVmdCA9IHNjcm9sbExlZnQ7XG5cdFxuXHRcdFx0XHRpZiAoIGZvb3RlciApIHtcblx0XHRcdFx0XHRzY3JvbGxGb290LnNjcm9sbExlZnQgPSBzY3JvbGxMZWZ0O1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFx0fVxuXHRcblx0XHQkKHNjcm9sbEJvZHkpLmNzcyhcblx0XHRcdHNjcm9sbFkgJiYgc2Nyb2xsLmJDb2xsYXBzZSA/ICdtYXgtaGVpZ2h0JyA6ICdoZWlnaHQnLCBcblx0XHRcdHNjcm9sbFlcblx0XHQpO1xuXHRcblx0XHRzZXR0aW5ncy5uU2Nyb2xsSGVhZCA9IHNjcm9sbEhlYWQ7XG5cdFx0c2V0dGluZ3MublNjcm9sbEJvZHkgPSBzY3JvbGxCb2R5O1xuXHRcdHNldHRpbmdzLm5TY3JvbGxGb290ID0gc2Nyb2xsRm9vdDtcblx0XG5cdFx0Ly8gT24gcmVkcmF3IC0gYWxpZ24gY29sdW1uc1xuXHRcdHNldHRpbmdzLmFvRHJhd0NhbGxiYWNrLnB1c2goIHtcblx0XHRcdFwiZm5cIjogX2ZuU2Nyb2xsRHJhdyxcblx0XHRcdFwic05hbWVcIjogXCJzY3JvbGxpbmdcIlxuXHRcdH0gKTtcblx0XG5cdFx0cmV0dXJuIHNjcm9sbGVyWzBdO1xuXHR9XG5cdFxuXHRcblx0XG5cdC8qKlxuXHQgKiBVcGRhdGUgdGhlIGhlYWRlciwgZm9vdGVyIGFuZCBib2R5IHRhYmxlcyBmb3IgcmVzaXppbmcgLSBpLmUuIGNvbHVtblxuXHQgKiBhbGlnbm1lbnQuXG5cdCAqXG5cdCAqIFdlbGNvbWUgdG8gdGhlIG1vc3QgaG9ycmlibGUgZnVuY3Rpb24gRGF0YVRhYmxlcy4gVGhlIHByb2Nlc3MgdGhhdCB0aGlzXG5cdCAqIGZ1bmN0aW9uIGZvbGxvd3MgaXMgYmFzaWNhbGx5OlxuXHQgKiAgIDEuIFJlLWNyZWF0ZSB0aGUgdGFibGUgaW5zaWRlIHRoZSBzY3JvbGxpbmcgZGl2XG5cdCAqICAgMi4gVGFrZSBsaXZlIG1lYXN1cmVtZW50cyBmcm9tIHRoZSBET01cblx0ICogICAzLiBBcHBseSB0aGUgbWVhc3VyZW1lbnRzIHRvIGFsaWduIHRoZSBjb2x1bW5zXG5cdCAqICAgNC4gQ2xlYW4gdXBcblx0ICpcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5TY3JvbGxEcmF3ICggc2V0dGluZ3MgKVxuXHR7XG5cdFx0Ly8gR2l2ZW4gdGhhdCB0aGlzIGlzIHN1Y2ggYSBtb25zdGVyIGZ1bmN0aW9uLCBhIGxvdCBvZiB2YXJpYWJsZXMgYXJlIHVzZVxuXHRcdC8vIHRvIHRyeSBhbmQga2VlcCB0aGUgbWluaW1pc2VkIHNpemUgYXMgc21hbGwgYXMgcG9zc2libGVcblx0XHR2YXJcblx0XHRcdHNjcm9sbCAgICAgICAgID0gc2V0dGluZ3Mub1Njcm9sbCxcblx0XHRcdHNjcm9sbFggICAgICAgID0gc2Nyb2xsLnNYLFxuXHRcdFx0c2Nyb2xsWElubmVyICAgPSBzY3JvbGwuc1hJbm5lcixcblx0XHRcdHNjcm9sbFkgICAgICAgID0gc2Nyb2xsLnNZLFxuXHRcdFx0YmFyV2lkdGggICAgICAgPSBzY3JvbGwuaUJhcldpZHRoLFxuXHRcdFx0ZGl2SGVhZGVyICAgICAgPSAkKHNldHRpbmdzLm5TY3JvbGxIZWFkKSxcblx0XHRcdGRpdkhlYWRlclN0eWxlID0gZGl2SGVhZGVyWzBdLnN0eWxlLFxuXHRcdFx0ZGl2SGVhZGVySW5uZXIgPSBkaXZIZWFkZXIuY2hpbGRyZW4oJ2RpdicpLFxuXHRcdFx0ZGl2SGVhZGVySW5uZXJTdHlsZSA9IGRpdkhlYWRlcklubmVyWzBdLnN0eWxlLFxuXHRcdFx0ZGl2SGVhZGVyVGFibGUgPSBkaXZIZWFkZXJJbm5lci5jaGlsZHJlbigndGFibGUnKSxcblx0XHRcdGRpdkJvZHlFbCAgICAgID0gc2V0dGluZ3MublNjcm9sbEJvZHksXG5cdFx0XHRkaXZCb2R5ICAgICAgICA9ICQoZGl2Qm9keUVsKSxcblx0XHRcdGRpdkJvZHlTdHlsZSAgID0gZGl2Qm9keUVsLnN0eWxlLFxuXHRcdFx0ZGl2Rm9vdGVyICAgICAgPSAkKHNldHRpbmdzLm5TY3JvbGxGb290KSxcblx0XHRcdGRpdkZvb3RlcklubmVyID0gZGl2Rm9vdGVyLmNoaWxkcmVuKCdkaXYnKSxcblx0XHRcdGRpdkZvb3RlclRhYmxlID0gZGl2Rm9vdGVySW5uZXIuY2hpbGRyZW4oJ3RhYmxlJyksXG5cdFx0XHRoZWFkZXIgICAgICAgICA9ICQoc2V0dGluZ3MublRIZWFkKSxcblx0XHRcdHRhYmxlICAgICAgICAgID0gJChzZXR0aW5ncy5uVGFibGUpLFxuXHRcdFx0dGFibGVFbCAgICAgICAgPSB0YWJsZVswXSxcblx0XHRcdHRhYmxlU3R5bGUgICAgID0gdGFibGVFbC5zdHlsZSxcblx0XHRcdGZvb3RlciAgICAgICAgID0gc2V0dGluZ3MublRGb290ID8gJChzZXR0aW5ncy5uVEZvb3QpIDogbnVsbCxcblx0XHRcdGJyb3dzZXIgICAgICAgID0gc2V0dGluZ3Mub0Jyb3dzZXIsXG5cdFx0XHRpZTY3ICAgICAgICAgICA9IGJyb3dzZXIuYlNjcm9sbE92ZXJzaXplLFxuXHRcdFx0ZHRIZWFkZXJDZWxscyAgPSBfcGx1Y2soIHNldHRpbmdzLmFvQ29sdW1ucywgJ25UaCcgKSxcblx0XHRcdGhlYWRlclRyZ0VscywgZm9vdGVyVHJnRWxzLFxuXHRcdFx0aGVhZGVyU3JjRWxzLCBmb290ZXJTcmNFbHMsXG5cdFx0XHRoZWFkZXJDb3B5LCBmb290ZXJDb3B5LFxuXHRcdFx0aGVhZGVyV2lkdGhzPVtdLCBmb290ZXJXaWR0aHM9W10sXG5cdFx0XHRoZWFkZXJDb250ZW50PVtdLCBmb290ZXJDb250ZW50PVtdLFxuXHRcdFx0aWR4LCBjb3JyZWN0aW9uLCBzYW5pdHlXaWR0aCxcblx0XHRcdHplcm9PdXQgPSBmdW5jdGlvbihuU2l6ZXIpIHtcblx0XHRcdFx0dmFyIHN0eWxlID0gblNpemVyLnN0eWxlO1xuXHRcdFx0XHRzdHlsZS5wYWRkaW5nVG9wID0gXCIwXCI7XG5cdFx0XHRcdHN0eWxlLnBhZGRpbmdCb3R0b20gPSBcIjBcIjtcblx0XHRcdFx0c3R5bGUuYm9yZGVyVG9wV2lkdGggPSBcIjBcIjtcblx0XHRcdFx0c3R5bGUuYm9yZGVyQm90dG9tV2lkdGggPSBcIjBcIjtcblx0XHRcdFx0c3R5bGUuaGVpZ2h0ID0gMDtcblx0XHRcdH07XG5cdFxuXHRcdC8vIElmIHRoZSBzY3JvbGxiYXIgdmlzaWJpbGl0eSBoYXMgY2hhbmdlZCBmcm9tIHRoZSBsYXN0IGRyYXcsIHdlIG5lZWQgdG9cblx0XHQvLyBhZGp1c3QgdGhlIGNvbHVtbiBzaXplcyBhcyB0aGUgdGFibGUgd2lkdGggd2lsbCBoYXZlIGNoYW5nZWQgdG8gYWNjb3VudFxuXHRcdC8vIGZvciB0aGUgc2Nyb2xsYmFyXG5cdFx0dmFyIHNjcm9sbEJhclZpcyA9IGRpdkJvZHlFbC5zY3JvbGxIZWlnaHQgPiBkaXZCb2R5RWwuY2xpZW50SGVpZ2h0O1xuXHRcdFxuXHRcdGlmICggc2V0dGluZ3Muc2Nyb2xsQmFyVmlzICE9PSBzY3JvbGxCYXJWaXMgJiYgc2V0dGluZ3Muc2Nyb2xsQmFyVmlzICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRzZXR0aW5ncy5zY3JvbGxCYXJWaXMgPSBzY3JvbGxCYXJWaXM7XG5cdFx0XHRfZm5BZGp1c3RDb2x1bW5TaXppbmcoIHNldHRpbmdzICk7XG5cdFx0XHRyZXR1cm47IC8vIGFkanVzdCBjb2x1bW4gc2l6aW5nIHdpbGwgY2FsbCB0aGlzIGZ1bmN0aW9uIGFnYWluXG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0c2V0dGluZ3Muc2Nyb2xsQmFyVmlzID0gc2Nyb2xsQmFyVmlzO1xuXHRcdH1cblx0XG5cdFx0Lypcblx0XHQgKiAxLiBSZS1jcmVhdGUgdGhlIHRhYmxlIGluc2lkZSB0aGUgc2Nyb2xsaW5nIGRpdlxuXHRcdCAqL1xuXHRcblx0XHQvLyBSZW1vdmUgdGhlIG9sZCBtaW5pbWlzZWQgdGhlYWQgYW5kIHRmb290IGVsZW1lbnRzIGluIHRoZSBpbm5lciB0YWJsZVxuXHRcdHRhYmxlLmNoaWxkcmVuKCd0aGVhZCwgdGZvb3QnKS5yZW1vdmUoKTtcblx0XG5cdFx0aWYgKCBmb290ZXIgKSB7XG5cdFx0XHRmb290ZXJDb3B5ID0gZm9vdGVyLmNsb25lKCkucHJlcGVuZFRvKCB0YWJsZSApO1xuXHRcdFx0Zm9vdGVyVHJnRWxzID0gZm9vdGVyLmZpbmQoJ3RyJyk7IC8vIHRoZSBvcmlnaW5hbCB0Zm9vdCBpcyBpbiBpdHMgb3duIHRhYmxlIGFuZCBtdXN0IGJlIHNpemVkXG5cdFx0XHRmb290ZXJTcmNFbHMgPSBmb290ZXJDb3B5LmZpbmQoJ3RyJyk7XG5cdFx0fVxuXHRcblx0XHQvLyBDbG9uZSB0aGUgY3VycmVudCBoZWFkZXIgYW5kIGZvb3RlciBlbGVtZW50cyBhbmQgdGhlbiBwbGFjZSBpdCBpbnRvIHRoZSBpbm5lciB0YWJsZVxuXHRcdGhlYWRlckNvcHkgPSBoZWFkZXIuY2xvbmUoKS5wcmVwZW5kVG8oIHRhYmxlICk7XG5cdFx0aGVhZGVyVHJnRWxzID0gaGVhZGVyLmZpbmQoJ3RyJyk7IC8vIG9yaWdpbmFsIGhlYWRlciBpcyBpbiBpdHMgb3duIHRhYmxlXG5cdFx0aGVhZGVyU3JjRWxzID0gaGVhZGVyQ29weS5maW5kKCd0cicpO1xuXHRcdGhlYWRlckNvcHkuZmluZCgndGgsIHRkJykucmVtb3ZlQXR0cigndGFiaW5kZXgnKTtcblx0XG5cdFxuXHRcdC8qXG5cdFx0ICogMi4gVGFrZSBsaXZlIG1lYXN1cmVtZW50cyBmcm9tIHRoZSBET00gLSBkbyBub3QgYWx0ZXIgdGhlIERPTSBpdHNlbGYhXG5cdFx0ICovXG5cdFxuXHRcdC8vIFJlbW92ZSBvbGQgc2l6aW5nIGFuZCBhcHBseSB0aGUgY2FsY3VsYXRlZCBjb2x1bW4gd2lkdGhzXG5cdFx0Ly8gR2V0IHRoZSB1bmlxdWUgY29sdW1uIGhlYWRlcnMgaW4gdGhlIG5ld2x5IGNyZWF0ZWQgKGNsb25lZCkgaGVhZGVyLiBXZSB3YW50IHRvIGFwcGx5IHRoZVxuXHRcdC8vIGNhbGN1bGF0ZWQgc2l6ZXMgdG8gdGhpcyBoZWFkZXJcblx0XHRpZiAoICEgc2Nyb2xsWCApXG5cdFx0e1xuXHRcdFx0ZGl2Qm9keVN0eWxlLndpZHRoID0gJzEwMCUnO1xuXHRcdFx0ZGl2SGVhZGVyWzBdLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuXHRcdH1cblx0XG5cdFx0JC5lYWNoKCBfZm5HZXRVbmlxdWVUaHMoIHNldHRpbmdzLCBoZWFkZXJDb3B5ICksIGZ1bmN0aW9uICggaSwgZWwgKSB7XG5cdFx0XHRpZHggPSBfZm5WaXNpYmxlVG9Db2x1bW5JbmRleCggc2V0dGluZ3MsIGkgKTtcblx0XHRcdGVsLnN0eWxlLndpZHRoID0gc2V0dGluZ3MuYW9Db2x1bW5zW2lkeF0uc1dpZHRoO1xuXHRcdH0gKTtcblx0XG5cdFx0aWYgKCBmb290ZXIgKSB7XG5cdFx0XHRfZm5BcHBseVRvQ2hpbGRyZW4oIGZ1bmN0aW9uKG4pIHtcblx0XHRcdFx0bi5zdHlsZS53aWR0aCA9IFwiXCI7XG5cdFx0XHR9LCBmb290ZXJTcmNFbHMgKTtcblx0XHR9XG5cdFxuXHRcdC8vIFNpemUgdGhlIHRhYmxlIGFzIGEgd2hvbGVcblx0XHRzYW5pdHlXaWR0aCA9IHRhYmxlLm91dGVyV2lkdGgoKTtcblx0XHRpZiAoIHNjcm9sbFggPT09IFwiXCIgKSB7XG5cdFx0XHQvLyBObyB4IHNjcm9sbGluZ1xuXHRcdFx0dGFibGVTdHlsZS53aWR0aCA9IFwiMTAwJVwiO1xuXHRcblx0XHRcdC8vIElFNyB3aWxsIG1ha2UgdGhlIHdpZHRoIG9mIHRoZSB0YWJsZSB3aGVuIDEwMCUgaW5jbHVkZSB0aGUgc2Nyb2xsYmFyXG5cdFx0XHQvLyAtIHdoaWNoIGlzIHNob3VsZG4ndC4gV2hlbiB0aGVyZSBpcyBhIHNjcm9sbGJhciB3ZSBuZWVkIHRvIHRha2UgdGhpc1xuXHRcdFx0Ly8gaW50byBhY2NvdW50LlxuXHRcdFx0aWYgKCBpZTY3ICYmICh0YWJsZS5maW5kKCd0Ym9keScpLmhlaWdodCgpID4gZGl2Qm9keUVsLm9mZnNldEhlaWdodCB8fFxuXHRcdFx0XHRkaXZCb2R5LmNzcygnb3ZlcmZsb3cteScpID09IFwic2Nyb2xsXCIpXG5cdFx0XHQpIHtcblx0XHRcdFx0dGFibGVTdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCB0YWJsZS5vdXRlcldpZHRoKCkgLSBiYXJXaWR0aCk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gUmVjYWxjdWxhdGUgdGhlIHNhbml0eSB3aWR0aFxuXHRcdFx0c2FuaXR5V2lkdGggPSB0YWJsZS5vdXRlcldpZHRoKCk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCBzY3JvbGxYSW5uZXIgIT09IFwiXCIgKSB7XG5cdFx0XHQvLyBsZWdhY3kgeCBzY3JvbGwgaW5uZXIgaGFzIGJlZW4gZ2l2ZW4gLSB1c2UgaXRcblx0XHRcdHRhYmxlU3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyhzY3JvbGxYSW5uZXIpO1xuXHRcblx0XHRcdC8vIFJlY2FsY3VsYXRlIHRoZSBzYW5pdHkgd2lkdGhcblx0XHRcdHNhbml0eVdpZHRoID0gdGFibGUub3V0ZXJXaWR0aCgpO1xuXHRcdH1cblx0XG5cdFx0Ly8gSGlkZGVuIGhlYWRlciBzaG91bGQgaGF2ZSB6ZXJvIGhlaWdodCwgc28gcmVtb3ZlIHBhZGRpbmcgYW5kIGJvcmRlcnMuIFRoZW5cblx0XHQvLyBzZXQgdGhlIHdpZHRoIGJhc2VkIG9uIHRoZSByZWFsIGhlYWRlcnNcblx0XG5cdFx0Ly8gQXBwbHkgYWxsIHN0eWxlcyBpbiBvbmUgcGFzc1xuXHRcdF9mbkFwcGx5VG9DaGlsZHJlbiggemVyb091dCwgaGVhZGVyU3JjRWxzICk7XG5cdFxuXHRcdC8vIFJlYWQgYWxsIHdpZHRocyBpbiBuZXh0IHBhc3Ncblx0XHRfZm5BcHBseVRvQ2hpbGRyZW4oIGZ1bmN0aW9uKG5TaXplcikge1xuXHRcdFx0aGVhZGVyQ29udGVudC5wdXNoKCBuU2l6ZXIuaW5uZXJIVE1MICk7XG5cdFx0XHRoZWFkZXJXaWR0aHMucHVzaCggX2ZuU3RyaW5nVG9Dc3MoICQoblNpemVyKS5jc3MoJ3dpZHRoJykgKSApO1xuXHRcdH0sIGhlYWRlclNyY0VscyApO1xuXHRcblx0XHQvLyBBcHBseSBhbGwgd2lkdGhzIGluIGZpbmFsIHBhc3Ncblx0XHRfZm5BcHBseVRvQ2hpbGRyZW4oIGZ1bmN0aW9uKG5Ub1NpemUsIGkpIHtcblx0XHRcdC8vIE9ubHkgYXBwbHkgd2lkdGhzIHRvIHRoZSBEYXRhVGFibGVzIGRldGVjdGVkIGhlYWRlciBjZWxscyAtIHRoaXNcblx0XHRcdC8vIHByZXZlbnRzIGNvbXBsZXggaGVhZGVycyBmcm9tIGhhdmluZyBjb250cmFkaWN0b3J5IHNpemVzIGFwcGxpZWRcblx0XHRcdGlmICggJC5pbkFycmF5KCBuVG9TaXplLCBkdEhlYWRlckNlbGxzICkgIT09IC0xICkge1xuXHRcdFx0XHRuVG9TaXplLnN0eWxlLndpZHRoID0gaGVhZGVyV2lkdGhzW2ldO1xuXHRcdFx0fVxuXHRcdH0sIGhlYWRlclRyZ0VscyApO1xuXHRcblx0XHQkKGhlYWRlclNyY0VscykuaGVpZ2h0KDApO1xuXHRcblx0XHQvKiBTYW1lIGFnYWluIHdpdGggdGhlIGZvb3RlciBpZiB3ZSBoYXZlIG9uZSAqL1xuXHRcdGlmICggZm9vdGVyIClcblx0XHR7XG5cdFx0XHRfZm5BcHBseVRvQ2hpbGRyZW4oIHplcm9PdXQsIGZvb3RlclNyY0VscyApO1xuXHRcblx0XHRcdF9mbkFwcGx5VG9DaGlsZHJlbiggZnVuY3Rpb24oblNpemVyKSB7XG5cdFx0XHRcdGZvb3RlckNvbnRlbnQucHVzaCggblNpemVyLmlubmVySFRNTCApO1xuXHRcdFx0XHRmb290ZXJXaWR0aHMucHVzaCggX2ZuU3RyaW5nVG9Dc3MoICQoblNpemVyKS5jc3MoJ3dpZHRoJykgKSApO1xuXHRcdFx0fSwgZm9vdGVyU3JjRWxzICk7XG5cdFxuXHRcdFx0X2ZuQXBwbHlUb0NoaWxkcmVuKCBmdW5jdGlvbihuVG9TaXplLCBpKSB7XG5cdFx0XHRcdG5Ub1NpemUuc3R5bGUud2lkdGggPSBmb290ZXJXaWR0aHNbaV07XG5cdFx0XHR9LCBmb290ZXJUcmdFbHMgKTtcblx0XG5cdFx0XHQkKGZvb3RlclNyY0VscykuaGVpZ2h0KDApO1xuXHRcdH1cblx0XG5cdFxuXHRcdC8qXG5cdFx0ICogMy4gQXBwbHkgdGhlIG1lYXN1cmVtZW50c1xuXHRcdCAqL1xuXHRcblx0XHQvLyBcIkhpZGVcIiB0aGUgaGVhZGVyIGFuZCBmb290ZXIgdGhhdCB3ZSB1c2VkIGZvciB0aGUgc2l6aW5nLiBXZSBuZWVkIHRvIGtlZXBcblx0XHQvLyB0aGUgY29udGVudCBvZiB0aGUgY2VsbCBzbyB0aGF0IHRoZSB3aWR0aCBhcHBsaWVkIHRvIHRoZSBoZWFkZXIgYW5kIGJvZHlcblx0XHQvLyBib3RoIG1hdGNoLCBidXQgd2Ugd2FudCB0byBoaWRlIGl0IGNvbXBsZXRlbHkuIFdlIHdhbnQgdG8gYWxzbyBmaXggdGhlaXJcblx0XHQvLyB3aWR0aCB0byB3aGF0IHRoZXkgY3VycmVudGx5IGFyZVxuXHRcdF9mbkFwcGx5VG9DaGlsZHJlbiggZnVuY3Rpb24oblNpemVyLCBpKSB7XG5cdFx0XHRuU2l6ZXIuaW5uZXJIVE1MID0gJzxkaXYgY2xhc3M9XCJkYXRhVGFibGVzX3NpemluZ1wiIHN0eWxlPVwiaGVpZ2h0OjA7b3ZlcmZsb3c6aGlkZGVuO1wiPicraGVhZGVyQ29udGVudFtpXSsnPC9kaXY+Jztcblx0XHRcdG5TaXplci5zdHlsZS53aWR0aCA9IGhlYWRlcldpZHRoc1tpXTtcblx0XHR9LCBoZWFkZXJTcmNFbHMgKTtcblx0XG5cdFx0aWYgKCBmb290ZXIgKVxuXHRcdHtcblx0XHRcdF9mbkFwcGx5VG9DaGlsZHJlbiggZnVuY3Rpb24oblNpemVyLCBpKSB7XG5cdFx0XHRcdG5TaXplci5pbm5lckhUTUwgPSAnPGRpdiBjbGFzcz1cImRhdGFUYWJsZXNfc2l6aW5nXCIgc3R5bGU9XCJoZWlnaHQ6MDtvdmVyZmxvdzpoaWRkZW47XCI+Jytmb290ZXJDb250ZW50W2ldKyc8L2Rpdj4nO1xuXHRcdFx0XHRuU2l6ZXIuc3R5bGUud2lkdGggPSBmb290ZXJXaWR0aHNbaV07XG5cdFx0XHR9LCBmb290ZXJTcmNFbHMgKTtcblx0XHR9XG5cdFxuXHRcdC8vIFNhbml0eSBjaGVjayB0aGF0IHRoZSB0YWJsZSBpcyBvZiBhIHNlbnNpYmxlIHdpZHRoLiBJZiBub3QgdGhlbiB3ZSBhcmUgZ29pbmcgdG8gZ2V0XG5cdFx0Ly8gbWlzYWxpZ25tZW50IC0gdHJ5IHRvIHByZXZlbnQgdGhpcyBieSBub3QgYWxsb3dpbmcgdGhlIHRhYmxlIHRvIHNocmluayBiZWxvdyBpdHMgbWluIHdpZHRoXG5cdFx0aWYgKCB0YWJsZS5vdXRlcldpZHRoKCkgPCBzYW5pdHlXaWR0aCApXG5cdFx0e1xuXHRcdFx0Ly8gVGhlIG1pbiB3aWR0aCBkZXBlbmRzIHVwb24gaWYgd2UgaGF2ZSBhIHZlcnRpY2FsIHNjcm9sbGJhciB2aXNpYmxlIG9yIG5vdCAqL1xuXHRcdFx0Y29ycmVjdGlvbiA9ICgoZGl2Qm9keUVsLnNjcm9sbEhlaWdodCA+IGRpdkJvZHlFbC5vZmZzZXRIZWlnaHQgfHxcblx0XHRcdFx0ZGl2Qm9keS5jc3MoJ292ZXJmbG93LXknKSA9PSBcInNjcm9sbFwiKSkgP1xuXHRcdFx0XHRcdHNhbml0eVdpZHRoK2JhcldpZHRoIDpcblx0XHRcdFx0XHRzYW5pdHlXaWR0aDtcblx0XG5cdFx0XHQvLyBJRTYvNyBhcmUgYSBsYXcgdW50byB0aGVtc2VsdmVzLi4uXG5cdFx0XHRpZiAoIGllNjcgJiYgKGRpdkJvZHlFbC5zY3JvbGxIZWlnaHQgPlxuXHRcdFx0XHRkaXZCb2R5RWwub2Zmc2V0SGVpZ2h0IHx8IGRpdkJvZHkuY3NzKCdvdmVyZmxvdy15JykgPT0gXCJzY3JvbGxcIilcblx0XHRcdCkge1xuXHRcdFx0XHR0YWJsZVN0eWxlLndpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIGNvcnJlY3Rpb24tYmFyV2lkdGggKTtcblx0XHRcdH1cblx0XG5cdFx0XHQvLyBBbmQgZ2l2ZSB0aGUgdXNlciBhIHdhcm5pbmcgdGhhdCB3ZSd2ZSBzdG9wcGVkIHRoZSB0YWJsZSBnZXR0aW5nIHRvbyBzbWFsbFxuXHRcdFx0aWYgKCBzY3JvbGxYID09PSBcIlwiIHx8IHNjcm9sbFhJbm5lciAhPT0gXCJcIiApIHtcblx0XHRcdFx0X2ZuTG9nKCBzZXR0aW5ncywgMSwgJ1Bvc3NpYmxlIGNvbHVtbiBtaXNhbGlnbm1lbnQnLCA2ICk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGVsc2Vcblx0XHR7XG5cdFx0XHRjb3JyZWN0aW9uID0gJzEwMCUnO1xuXHRcdH1cblx0XG5cdFx0Ly8gQXBwbHkgdG8gdGhlIGNvbnRhaW5lciBlbGVtZW50c1xuXHRcdGRpdkJvZHlTdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBjb3JyZWN0aW9uICk7XG5cdFx0ZGl2SGVhZGVyU3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyggY29ycmVjdGlvbiApO1xuXHRcblx0XHRpZiAoIGZvb3RlciApIHtcblx0XHRcdHNldHRpbmdzLm5TY3JvbGxGb290LnN0eWxlLndpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIGNvcnJlY3Rpb24gKTtcblx0XHR9XG5cdFxuXHRcblx0XHQvKlxuXHRcdCAqIDQuIENsZWFuIHVwXG5cdFx0ICovXG5cdFx0aWYgKCAhIHNjcm9sbFkgKSB7XG5cdFx0XHQvKiBJRTc8IHB1dHMgYSB2ZXJ0aWNhbCBzY3JvbGxiYXIgaW4gcGxhY2UgKHdoZW4gaXQgc2hvdWxkbid0IGJlKSBkdWUgdG8gc3VidHJhY3Rpbmdcblx0XHRcdCAqIHRoZSBzY3JvbGxiYXIgaGVpZ2h0IGZyb20gdGhlIHZpc2libGUgZGlzcGxheSwgcmF0aGVyIHRoYW4gYWRkaW5nIGl0IG9uLiBXZSBuZWVkIHRvXG5cdFx0XHQgKiBzZXQgdGhlIGhlaWdodCBpbiBvcmRlciB0byBzb3J0IHRoaXMuIERvbid0IHdhbnQgdG8gZG8gaXQgaW4gYW55IG90aGVyIGJyb3dzZXJzLlxuXHRcdFx0ICovXG5cdFx0XHRpZiAoIGllNjcgKSB7XG5cdFx0XHRcdGRpdkJvZHlTdHlsZS5oZWlnaHQgPSBfZm5TdHJpbmdUb0NzcyggdGFibGVFbC5vZmZzZXRIZWlnaHQrYmFyV2lkdGggKTtcblx0XHRcdH1cblx0XHR9XG5cdFxuXHRcdC8qIEZpbmFsbHkgc2V0IHRoZSB3aWR0aCdzIG9mIHRoZSBoZWFkZXIgYW5kIGZvb3RlciB0YWJsZXMgKi9cblx0XHR2YXIgaU91dGVyV2lkdGggPSB0YWJsZS5vdXRlcldpZHRoKCk7XG5cdFx0ZGl2SGVhZGVyVGFibGVbMF0uc3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyggaU91dGVyV2lkdGggKTtcblx0XHRkaXZIZWFkZXJJbm5lclN0eWxlLndpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIGlPdXRlcldpZHRoICk7XG5cdFxuXHRcdC8vIEZpZ3VyZSBvdXQgaWYgdGhlcmUgYXJlIHNjcm9sbGJhciBwcmVzZW50IC0gaWYgc28gdGhlbiB3ZSBuZWVkIGEgdGhlIGhlYWRlciBhbmQgZm9vdGVyIHRvXG5cdFx0Ly8gcHJvdmlkZSBhIGJpdCBtb3JlIHNwYWNlIHRvIGFsbG93IFwib3ZlcmZsb3dcIiBzY3JvbGxpbmcgKGkuZS4gcGFzdCB0aGUgc2Nyb2xsYmFyKVxuXHRcdHZhciBiU2Nyb2xsaW5nID0gdGFibGUuaGVpZ2h0KCkgPiBkaXZCb2R5RWwuY2xpZW50SGVpZ2h0IHx8IGRpdkJvZHkuY3NzKCdvdmVyZmxvdy15JykgPT0gXCJzY3JvbGxcIjtcblx0XHR2YXIgcGFkZGluZyA9ICdwYWRkaW5nJyArIChicm93c2VyLmJTY3JvbGxiYXJMZWZ0ID8gJ0xlZnQnIDogJ1JpZ2h0JyApO1xuXHRcdGRpdkhlYWRlcklubmVyU3R5bGVbIHBhZGRpbmcgXSA9IGJTY3JvbGxpbmcgPyBiYXJXaWR0aCtcInB4XCIgOiBcIjBweFwiO1xuXHRcblx0XHRpZiAoIGZvb3RlciApIHtcblx0XHRcdGRpdkZvb3RlclRhYmxlWzBdLnN0eWxlLndpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIGlPdXRlcldpZHRoICk7XG5cdFx0XHRkaXZGb290ZXJJbm5lclswXS5zdHlsZS53aWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBpT3V0ZXJXaWR0aCApO1xuXHRcdFx0ZGl2Rm9vdGVySW5uZXJbMF0uc3R5bGVbcGFkZGluZ10gPSBiU2Nyb2xsaW5nID8gYmFyV2lkdGgrXCJweFwiIDogXCIwcHhcIjtcblx0XHR9XG5cdFxuXHRcdC8vIENvcnJlY3QgRE9NIG9yZGVyaW5nIGZvciBjb2xncm91cCAtIGNvbWVzIGJlZm9yZSB0aGUgdGhlYWRcblx0XHR0YWJsZS5jaGlsZHJlbignY29sZ3JvdXAnKS5pbnNlcnRCZWZvcmUoIHRhYmxlLmNoaWxkcmVuKCd0aGVhZCcpICk7XG5cdFxuXHRcdC8qIEFkanVzdCB0aGUgcG9zaXRpb24gb2YgdGhlIGhlYWRlciBpbiBjYXNlIHdlIGxvb3NlIHRoZSB5LXNjcm9sbGJhciAqL1xuXHRcdGRpdkJvZHkuc2Nyb2xsKCk7XG5cdFxuXHRcdC8vIElmIHNvcnRpbmcgb3IgZmlsdGVyaW5nIGhhcyBvY2N1cnJlZCwganVtcCB0aGUgc2Nyb2xsaW5nIGJhY2sgdG8gdGhlIHRvcFxuXHRcdC8vIG9ubHkgaWYgd2UgYXJlbid0IGhvbGRpbmcgdGhlIHBvc2l0aW9uXG5cdFx0aWYgKCAoc2V0dGluZ3MuYlNvcnRlZCB8fCBzZXR0aW5ncy5iRmlsdGVyZWQpICYmICEgc2V0dGluZ3MuX2RyYXdIb2xkICkge1xuXHRcdFx0ZGl2Qm9keUVsLnNjcm9sbFRvcCA9IDA7XG5cdFx0fVxuXHR9XG5cdFxuXHRcblx0XG5cdC8qKlxuXHQgKiBBcHBseSBhIGdpdmVuIGZ1bmN0aW9uIHRvIHRoZSBkaXNwbGF5IGNoaWxkIG5vZGVzIG9mIGFuIGVsZW1lbnQgYXJyYXkgKHR5cGljYWxseVxuXHQgKiBURCBjaGlsZHJlbiBvZiBUUiByb3dzXG5cdCAqICBAcGFyYW0ge2Z1bmN0aW9ufSBmbiBNZXRob2QgdG8gYXBwbHkgdG8gdGhlIG9iamVjdHNcblx0ICogIEBwYXJhbSBhcnJheSB7bm9kZXN9IGFuMSBMaXN0IG9mIGVsZW1lbnRzIHRvIGxvb2sgdGhyb3VnaCBmb3IgZGlzcGxheSBjaGlsZHJlblxuXHQgKiAgQHBhcmFtIGFycmF5IHtub2Rlc30gYW4yIEFub3RoZXIgbGlzdCAoaWRlbnRpY2FsIHN0cnVjdHVyZSB0byB0aGUgZmlyc3QpIC0gb3B0aW9uYWxcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQXBwbHlUb0NoaWxkcmVuKCBmbiwgYW4xLCBhbjIgKVxuXHR7XG5cdFx0dmFyIGluZGV4PTAsIGk9MCwgaUxlbj1hbjEubGVuZ3RoO1xuXHRcdHZhciBuTm9kZTEsIG5Ob2RlMjtcblx0XG5cdFx0d2hpbGUgKCBpIDwgaUxlbiApIHtcblx0XHRcdG5Ob2RlMSA9IGFuMVtpXS5maXJzdENoaWxkO1xuXHRcdFx0bk5vZGUyID0gYW4yID8gYW4yW2ldLmZpcnN0Q2hpbGQgOiBudWxsO1xuXHRcblx0XHRcdHdoaWxlICggbk5vZGUxICkge1xuXHRcdFx0XHRpZiAoIG5Ob2RlMS5ub2RlVHlwZSA9PT0gMSApIHtcblx0XHRcdFx0XHRpZiAoIGFuMiApIHtcblx0XHRcdFx0XHRcdGZuKCBuTm9kZTEsIG5Ob2RlMiwgaW5kZXggKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRmbiggbk5vZGUxLCBpbmRleCApO1xuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0aW5kZXgrKztcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0bk5vZGUxID0gbk5vZGUxLm5leHRTaWJsaW5nO1xuXHRcdFx0XHRuTm9kZTIgPSBhbjIgPyBuTm9kZTIubmV4dFNpYmxpbmcgOiBudWxsO1xuXHRcdFx0fVxuXHRcblx0XHRcdGkrKztcblx0XHR9XG5cdH1cblx0XG5cdFxuXHRcblx0dmFyIF9fcmVfaHRtbF9yZW1vdmUgPSAvPC4qPz4vZztcblx0XG5cdFxuXHQvKipcblx0ICogQ2FsY3VsYXRlIHRoZSB3aWR0aCBvZiBjb2x1bW5zIGZvciB0aGUgdGFibGVcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQ2FsY3VsYXRlQ29sdW1uV2lkdGhzICggb1NldHRpbmdzIClcblx0e1xuXHRcdHZhclxuXHRcdFx0dGFibGUgPSBvU2V0dGluZ3MublRhYmxlLFxuXHRcdFx0Y29sdW1ucyA9IG9TZXR0aW5ncy5hb0NvbHVtbnMsXG5cdFx0XHRzY3JvbGwgPSBvU2V0dGluZ3Mub1Njcm9sbCxcblx0XHRcdHNjcm9sbFkgPSBzY3JvbGwuc1ksXG5cdFx0XHRzY3JvbGxYID0gc2Nyb2xsLnNYLFxuXHRcdFx0c2Nyb2xsWElubmVyID0gc2Nyb2xsLnNYSW5uZXIsXG5cdFx0XHRjb2x1bW5Db3VudCA9IGNvbHVtbnMubGVuZ3RoLFxuXHRcdFx0dmlzaWJsZUNvbHVtbnMgPSBfZm5HZXRDb2x1bW5zKCBvU2V0dGluZ3MsICdiVmlzaWJsZScgKSxcblx0XHRcdGhlYWRlckNlbGxzID0gJCgndGgnLCBvU2V0dGluZ3MublRIZWFkKSxcblx0XHRcdHRhYmxlV2lkdGhBdHRyID0gdGFibGUuZ2V0QXR0cmlidXRlKCd3aWR0aCcpLCAvLyBmcm9tIERPTSBlbGVtZW50XG5cdFx0XHR0YWJsZUNvbnRhaW5lciA9IHRhYmxlLnBhcmVudE5vZGUsXG5cdFx0XHR1c2VySW5wdXRzID0gZmFsc2UsXG5cdFx0XHRpLCBjb2x1bW4sIGNvbHVtbklkeCwgd2lkdGgsIG91dGVyV2lkdGgsXG5cdFx0XHRicm93c2VyID0gb1NldHRpbmdzLm9Ccm93c2VyLFxuXHRcdFx0aWU2NyA9IGJyb3dzZXIuYlNjcm9sbE92ZXJzaXplO1xuXHRcblx0XHR2YXIgc3R5bGVXaWR0aCA9IHRhYmxlLnN0eWxlLndpZHRoO1xuXHRcdGlmICggc3R5bGVXaWR0aCAmJiBzdHlsZVdpZHRoLmluZGV4T2YoJyUnKSAhPT0gLTEgKSB7XG5cdFx0XHR0YWJsZVdpZHRoQXR0ciA9IHN0eWxlV2lkdGg7XG5cdFx0fVxuXHRcblx0XHQvKiBDb252ZXJ0IGFueSB1c2VyIGlucHV0IHNpemVzIGludG8gcGl4ZWwgc2l6ZXMgKi9cblx0XHRmb3IgKCBpPTAgOyBpPHZpc2libGVDb2x1bW5zLmxlbmd0aCA7IGkrKyApIHtcblx0XHRcdGNvbHVtbiA9IGNvbHVtbnNbIHZpc2libGVDb2x1bW5zW2ldIF07XG5cdFxuXHRcdFx0aWYgKCBjb2x1bW4uc1dpZHRoICE9PSBudWxsICkge1xuXHRcdFx0XHRjb2x1bW4uc1dpZHRoID0gX2ZuQ29udmVydFRvV2lkdGgoIGNvbHVtbi5zV2lkdGhPcmlnLCB0YWJsZUNvbnRhaW5lciApO1xuXHRcblx0XHRcdFx0dXNlcklucHV0cyA9IHRydWU7XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHQvKiBJZiB0aGUgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIERPTSBlcXVhbHMgdGhlIG51bWJlciB0aGF0IHdlIGhhdmUgdG9cblx0XHQgKiBwcm9jZXNzIGluIERhdGFUYWJsZXMsIHRoZW4gd2UgY2FuIHVzZSB0aGUgb2Zmc2V0cyB0aGF0IGFyZSBjcmVhdGVkIGJ5XG5cdFx0ICogdGhlIHdlYi0gYnJvd3Nlci4gTm8gY3VzdG9tIHNpemVzIGNhbiBiZSBzZXQgaW4gb3JkZXIgZm9yIHRoaXMgdG8gaGFwcGVuLFxuXHRcdCAqIG5vciBzY3JvbGxpbmcgdXNlZFxuXHRcdCAqL1xuXHRcdGlmICggaWU2NyB8fCAhIHVzZXJJbnB1dHMgJiYgISBzY3JvbGxYICYmICEgc2Nyb2xsWSAmJlxuXHRcdCAgICAgY29sdW1uQ291bnQgPT0gX2ZuVmlzYmxlQ29sdW1ucyggb1NldHRpbmdzICkgJiZcblx0XHQgICAgIGNvbHVtbkNvdW50ID09IGhlYWRlckNlbGxzLmxlbmd0aFxuXHRcdCkge1xuXHRcdFx0Zm9yICggaT0wIDsgaTxjb2x1bW5Db3VudCA7IGkrKyApIHtcblx0XHRcdFx0dmFyIGNvbElkeCA9IF9mblZpc2libGVUb0NvbHVtbkluZGV4KCBvU2V0dGluZ3MsIGkgKTtcblx0XG5cdFx0XHRcdGlmICggY29sSWR4ICE9PSBudWxsICkge1xuXHRcdFx0XHRcdGNvbHVtbnNbIGNvbElkeCBdLnNXaWR0aCA9IF9mblN0cmluZ1RvQ3NzKCBoZWFkZXJDZWxscy5lcShpKS53aWR0aCgpICk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZVxuXHRcdHtcblx0XHRcdC8vIE90aGVyd2lzZSBjb25zdHJ1Y3QgYSBzaW5nbGUgcm93LCB3b3JzdCBjYXNlLCB0YWJsZSB3aXRoIHRoZSB3aWRlc3Rcblx0XHRcdC8vIG5vZGUgaW4gdGhlIGRhdGEsIGFzc2lnbiBhbnkgdXNlciBkZWZpbmVkIHdpZHRocywgdGhlbiBpbnNlcnQgaXQgaW50b1xuXHRcdFx0Ly8gdGhlIERPTSBhbmQgYWxsb3cgdGhlIGJyb3dzZXIgdG8gZG8gYWxsIHRoZSBoYXJkIHdvcmsgb2YgY2FsY3VsYXRpbmdcblx0XHRcdC8vIHRhYmxlIHdpZHRoc1xuXHRcdFx0dmFyIHRtcFRhYmxlID0gJCh0YWJsZSkuY2xvbmUoKSAvLyBkb24ndCB1c2UgY2xvbmVOb2RlIC0gSUU4IHdpbGwgcmVtb3ZlIGV2ZW50cyBvbiB0aGUgbWFpbiB0YWJsZVxuXHRcdFx0XHQuY3NzKCAndmlzaWJpbGl0eScsICdoaWRkZW4nIClcblx0XHRcdFx0LnJlbW92ZUF0dHIoICdpZCcgKTtcblx0XG5cdFx0XHQvLyBDbGVhbiB1cCB0aGUgdGFibGUgYm9keVxuXHRcdFx0dG1wVGFibGUuZmluZCgndGJvZHkgdHInKS5yZW1vdmUoKTtcblx0XHRcdHZhciB0ciA9ICQoJzx0ci8+JykuYXBwZW5kVG8oIHRtcFRhYmxlLmZpbmQoJ3Rib2R5JykgKTtcblx0XG5cdFx0XHQvLyBDbG9uZSB0aGUgdGFibGUgaGVhZGVyIGFuZCBmb290ZXIgLSB3ZSBjYW4ndCB1c2UgdGhlIGhlYWRlciAvIGZvb3RlclxuXHRcdFx0Ly8gZnJvbSB0aGUgY2xvbmVkIHRhYmxlLCBzaW5jZSBpZiBzY3JvbGxpbmcgaXMgYWN0aXZlLCB0aGUgdGFibGUnc1xuXHRcdFx0Ly8gcmVhbCBoZWFkZXIgYW5kIGZvb3RlciBhcmUgY29udGFpbmVkIGluIGRpZmZlcmVudCB0YWJsZSB0YWdzXG5cdFx0XHR0bXBUYWJsZS5maW5kKCd0aGVhZCwgdGZvb3QnKS5yZW1vdmUoKTtcblx0XHRcdHRtcFRhYmxlXG5cdFx0XHRcdC5hcHBlbmQoICQob1NldHRpbmdzLm5USGVhZCkuY2xvbmUoKSApXG5cdFx0XHRcdC5hcHBlbmQoICQob1NldHRpbmdzLm5URm9vdCkuY2xvbmUoKSApO1xuXHRcblx0XHRcdC8vIFJlbW92ZSBhbnkgYXNzaWduZWQgd2lkdGhzIGZyb20gdGhlIGZvb3RlciAoZnJvbSBzY3JvbGxpbmcpXG5cdFx0XHR0bXBUYWJsZS5maW5kKCd0Zm9vdCB0aCwgdGZvb3QgdGQnKS5jc3MoJ3dpZHRoJywgJycpO1xuXHRcblx0XHRcdC8vIEFwcGx5IGN1c3RvbSBzaXppbmcgdG8gdGhlIGNsb25lZCBoZWFkZXJcblx0XHRcdGhlYWRlckNlbGxzID0gX2ZuR2V0VW5pcXVlVGhzKCBvU2V0dGluZ3MsIHRtcFRhYmxlLmZpbmQoJ3RoZWFkJylbMF0gKTtcblx0XG5cdFx0XHRmb3IgKCBpPTAgOyBpPHZpc2libGVDb2x1bW5zLmxlbmd0aCA7IGkrKyApIHtcblx0XHRcdFx0Y29sdW1uID0gY29sdW1uc1sgdmlzaWJsZUNvbHVtbnNbaV0gXTtcblx0XG5cdFx0XHRcdGhlYWRlckNlbGxzW2ldLnN0eWxlLndpZHRoID0gY29sdW1uLnNXaWR0aE9yaWcgIT09IG51bGwgJiYgY29sdW1uLnNXaWR0aE9yaWcgIT09ICcnID9cblx0XHRcdFx0XHRfZm5TdHJpbmdUb0NzcyggY29sdW1uLnNXaWR0aE9yaWcgKSA6XG5cdFx0XHRcdFx0Jyc7XG5cdFxuXHRcdFx0XHQvLyBGb3Igc2Nyb2xsWCB3ZSBuZWVkIHRvIGZvcmNlIHRoZSBjb2x1bW4gd2lkdGggb3RoZXJ3aXNlIHRoZVxuXHRcdFx0XHQvLyBicm93c2VyIHdpbGwgY29sbGFwc2UgaXQuIElmIHRoaXMgd2lkdGggaXMgc21hbGxlciB0aGFuIHRoZVxuXHRcdFx0XHQvLyB3aWR0aCB0aGUgY29sdW1uIHJlcXVpcmVzLCB0aGVuIGl0IHdpbGwgaGF2ZSBubyBlZmZlY3Rcblx0XHRcdFx0aWYgKCBjb2x1bW4uc1dpZHRoT3JpZyAmJiBzY3JvbGxYICkge1xuXHRcdFx0XHRcdCQoIGhlYWRlckNlbGxzW2ldICkuYXBwZW5kKCAkKCc8ZGl2Lz4nKS5jc3MoIHtcblx0XHRcdFx0XHRcdHdpZHRoOiBjb2x1bW4uc1dpZHRoT3JpZyxcblx0XHRcdFx0XHRcdG1hcmdpbjogMCxcblx0XHRcdFx0XHRcdHBhZGRpbmc6IDAsXG5cdFx0XHRcdFx0XHRib3JkZXI6IDAsXG5cdFx0XHRcdFx0XHRoZWlnaHQ6IDFcblx0XHRcdFx0XHR9ICkgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcblx0XHRcdC8vIEZpbmQgdGhlIHdpZGVzdCBjZWxsIGZvciBlYWNoIGNvbHVtbiBhbmQgcHV0IGl0IGludG8gdGhlIHRhYmxlXG5cdFx0XHRpZiAoIG9TZXR0aW5ncy5hb0RhdGEubGVuZ3RoICkge1xuXHRcdFx0XHRmb3IgKCBpPTAgOyBpPHZpc2libGVDb2x1bW5zLmxlbmd0aCA7IGkrKyApIHtcblx0XHRcdFx0XHRjb2x1bW5JZHggPSB2aXNpYmxlQ29sdW1uc1tpXTtcblx0XHRcdFx0XHRjb2x1bW4gPSBjb2x1bW5zWyBjb2x1bW5JZHggXTtcblx0XG5cdFx0XHRcdFx0JCggX2ZuR2V0V2lkZXN0Tm9kZSggb1NldHRpbmdzLCBjb2x1bW5JZHggKSApXG5cdFx0XHRcdFx0XHQuY2xvbmUoIGZhbHNlIClcblx0XHRcdFx0XHRcdC5hcHBlbmQoIGNvbHVtbi5zQ29udGVudFBhZGRpbmcgKVxuXHRcdFx0XHRcdFx0LmFwcGVuZFRvKCB0ciApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gVGlkeSB0aGUgdGVtcG9yYXJ5IHRhYmxlIC0gcmVtb3ZlIG5hbWUgYXR0cmlidXRlcyBzbyB0aGVyZSBhcmVuJ3Rcblx0XHRcdC8vIGR1cGxpY2F0ZWQgaW4gdGhlIGRvbSAocmFkaW8gZWxlbWVudHMgZm9yIGV4YW1wbGUpXG5cdFx0XHQkKCdbbmFtZV0nLCB0bXBUYWJsZSkucmVtb3ZlQXR0cignbmFtZScpO1xuXHRcblx0XHRcdC8vIFRhYmxlIGhhcyBiZWVuIGJ1aWx0LCBhdHRhY2ggdG8gdGhlIGRvY3VtZW50IHNvIHdlIGNhbiB3b3JrIHdpdGggaXQuXG5cdFx0XHQvLyBBIGhvbGRpbmcgZWxlbWVudCBpcyB1c2VkLCBwb3NpdGlvbmVkIGF0IHRoZSB0b3Agb2YgdGhlIGNvbnRhaW5lclxuXHRcdFx0Ly8gd2l0aCBtaW5pbWFsIGhlaWdodCwgc28gaXQgaGFzIG5vIGVmZmVjdCBvbiBpZiB0aGUgY29udGFpbmVyIHNjcm9sbHNcblx0XHRcdC8vIG9yIG5vdC4gT3RoZXJ3aXNlIGl0IG1pZ2h0IHRyaWdnZXIgc2Nyb2xsaW5nIHdoZW4gaXQgYWN0dWFsbHkgaXNuJ3Rcblx0XHRcdC8vIG5lZWRlZFxuXHRcdFx0dmFyIGhvbGRlciA9ICQoJzxkaXYvPicpLmNzcyggc2Nyb2xsWCB8fCBzY3JvbGxZID9cblx0XHRcdFx0XHR7XG5cdFx0XHRcdFx0XHRwb3NpdGlvbjogJ2Fic29sdXRlJyxcblx0XHRcdFx0XHRcdHRvcDogMCxcblx0XHRcdFx0XHRcdGxlZnQ6IDAsXG5cdFx0XHRcdFx0XHRoZWlnaHQ6IDEsXG5cdFx0XHRcdFx0XHRyaWdodDogMCxcblx0XHRcdFx0XHRcdG92ZXJmbG93OiAnaGlkZGVuJ1xuXHRcdFx0XHRcdH0gOlxuXHRcdFx0XHRcdHt9XG5cdFx0XHRcdClcblx0XHRcdFx0LmFwcGVuZCggdG1wVGFibGUgKVxuXHRcdFx0XHQuYXBwZW5kVG8oIHRhYmxlQ29udGFpbmVyICk7XG5cdFxuXHRcdFx0Ly8gV2hlbiBzY3JvbGxpbmcgKFggb3IgWSkgd2Ugd2FudCB0byBzZXQgdGhlIHdpZHRoIG9mIHRoZSB0YWJsZSBhcyBcblx0XHRcdC8vIGFwcHJvcHJpYXRlLiBIb3dldmVyLCB3aGVuIG5vdCBzY3JvbGxpbmcgbGVhdmUgdGhlIHRhYmxlIHdpZHRoIGFzIGl0XG5cdFx0XHQvLyBpcy4gVGhpcyByZXN1bHRzIGluIHNsaWdodGx5IGRpZmZlcmVudCwgYnV0IEkgdGhpbmsgY29ycmVjdCBiZWhhdmlvdXJcblx0XHRcdGlmICggc2Nyb2xsWCAmJiBzY3JvbGxYSW5uZXIgKSB7XG5cdFx0XHRcdHRtcFRhYmxlLndpZHRoKCBzY3JvbGxYSW5uZXIgKTtcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKCBzY3JvbGxYICkge1xuXHRcdFx0XHR0bXBUYWJsZS5jc3MoICd3aWR0aCcsICdhdXRvJyApO1xuXHRcdFx0XHR0bXBUYWJsZS5yZW1vdmVBdHRyKCd3aWR0aCcpO1xuXHRcblx0XHRcdFx0Ly8gSWYgdGhlcmUgaXMgbm8gd2lkdGggYXR0cmlidXRlIG9yIHN0eWxlLCB0aGVuIGFsbG93IHRoZSB0YWJsZSB0b1xuXHRcdFx0XHQvLyBjb2xsYXBzZVxuXHRcdFx0XHRpZiAoIHRtcFRhYmxlLndpZHRoKCkgPCB0YWJsZUNvbnRhaW5lci5jbGllbnRXaWR0aCAmJiB0YWJsZVdpZHRoQXR0ciApIHtcblx0XHRcdFx0XHR0bXBUYWJsZS53aWR0aCggdGFibGVDb250YWluZXIuY2xpZW50V2lkdGggKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoIHNjcm9sbFkgKSB7XG5cdFx0XHRcdHRtcFRhYmxlLndpZHRoKCB0YWJsZUNvbnRhaW5lci5jbGllbnRXaWR0aCApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoIHRhYmxlV2lkdGhBdHRyICkge1xuXHRcdFx0XHR0bXBUYWJsZS53aWR0aCggdGFibGVXaWR0aEF0dHIgKTtcblx0XHRcdH1cblx0XG5cdFx0XHQvLyBHZXQgdGhlIHdpZHRoIG9mIGVhY2ggY29sdW1uIGluIHRoZSBjb25zdHJ1Y3RlZCB0YWJsZSAtIHdlIG5lZWQgdG9cblx0XHRcdC8vIGtub3cgdGhlIGlubmVyIHdpZHRoIChzbyBpdCBjYW4gYmUgYXNzaWduZWQgdG8gdGhlIG90aGVyIHRhYmxlJ3Ncblx0XHRcdC8vIGNlbGxzKSBhbmQgdGhlIG91dGVyIHdpZHRoIHNvIHdlIGNhbiBjYWxjdWxhdGUgdGhlIGZ1bGwgd2lkdGggb2YgdGhlXG5cdFx0XHQvLyB0YWJsZS4gVGhpcyBpcyBzYWZlIHNpbmNlIERhdGFUYWJsZXMgcmVxdWlyZXMgYSB1bmlxdWUgY2VsbCBmb3IgZWFjaFxuXHRcdFx0Ly8gY29sdW1uLCBidXQgaWYgZXZlciBhIGhlYWRlciBjYW4gc3BhbiBtdWx0aXBsZSBjb2x1bW5zLCB0aGlzIHdpbGxcblx0XHRcdC8vIG5lZWQgdG8gYmUgbW9kaWZpZWQuXG5cdFx0XHR2YXIgdG90YWwgPSAwO1xuXHRcdFx0Zm9yICggaT0wIDsgaTx2aXNpYmxlQ29sdW1ucy5sZW5ndGggOyBpKysgKSB7XG5cdFx0XHRcdHZhciBjZWxsID0gJChoZWFkZXJDZWxsc1tpXSk7XG5cdFx0XHRcdHZhciBib3JkZXIgPSBjZWxsLm91dGVyV2lkdGgoKSAtIGNlbGwud2lkdGgoKTtcblx0XG5cdFx0XHRcdC8vIFVzZSBnZXRCb3VuZGluZy4uLiB3aGVyZSBwb3NzaWJsZSAobm90IElFOC0pIGJlY2F1c2UgaXQgY2FuIGdpdmVcblx0XHRcdFx0Ly8gc3ViLXBpeGVsIGFjY3VyYWN5LCB3aGljaCB3ZSB0aGVuIHdhbnQgdG8gcm91bmQgdXAhXG5cdFx0XHRcdHZhciBib3VuZGluZyA9IGJyb3dzZXIuYkJvdW5kaW5nID9cblx0XHRcdFx0XHRNYXRoLmNlaWwoIGhlYWRlckNlbGxzW2ldLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoICkgOlxuXHRcdFx0XHRcdGNlbGwub3V0ZXJXaWR0aCgpO1xuXHRcblx0XHRcdFx0Ly8gVG90YWwgaXMgdHJhY2tlZCB0byByZW1vdmUgYW55IHN1Yi1waXhlbCBlcnJvcnMgYXMgdGhlIG91dGVyV2lkdGhcblx0XHRcdFx0Ly8gb2YgdGhlIHRhYmxlIG1pZ2h0IG5vdCBlcXVhbCB0aGUgdG90YWwgZ2l2ZW4gaGVyZSAoSUUhKS5cblx0XHRcdFx0dG90YWwgKz0gYm91bmRpbmc7XG5cdFxuXHRcdFx0XHQvLyBXaWR0aCBmb3IgZWFjaCBjb2x1bW4gdG8gdXNlXG5cdFx0XHRcdGNvbHVtbnNbIHZpc2libGVDb2x1bW5zW2ldIF0uc1dpZHRoID0gX2ZuU3RyaW5nVG9Dc3MoIGJvdW5kaW5nIC0gYm9yZGVyICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0dGFibGUuc3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyggdG90YWwgKTtcblx0XG5cdFx0XHQvLyBGaW5pc2hlZCB3aXRoIHRoZSB0YWJsZSAtIGRpdGNoIGl0XG5cdFx0XHRob2xkZXIucmVtb3ZlKCk7XG5cdFx0fVxuXHRcblx0XHQvLyBJZiB0aGVyZSBpcyBhIHdpZHRoIGF0dHIsIHdlIHdhbnQgdG8gYXR0YWNoIGFuIGV2ZW50IGxpc3RlbmVyIHdoaWNoXG5cdFx0Ly8gYWxsb3dzIHRoZSB0YWJsZSBzaXppbmcgdG8gYXV0b21hdGljYWxseSBhZGp1c3Qgd2hlbiB0aGUgd2luZG93IGlzXG5cdFx0Ly8gcmVzaXplZC4gVXNlIHRoZSB3aWR0aCBhdHRyIHJhdGhlciB0aGFuIENTUywgc2luY2Ugd2UgY2FuJ3Qga25vdyBpZiB0aGVcblx0XHQvLyBDU1MgaXMgYSByZWxhdGl2ZSB2YWx1ZSBvciBhYnNvbHV0ZSAtIERPTSByZWFkIGlzIGFsd2F5cyBweC5cblx0XHRpZiAoIHRhYmxlV2lkdGhBdHRyICkge1xuXHRcdFx0dGFibGUuc3R5bGUud2lkdGggPSBfZm5TdHJpbmdUb0NzcyggdGFibGVXaWR0aEF0dHIgKTtcblx0XHR9XG5cdFxuXHRcdGlmICggKHRhYmxlV2lkdGhBdHRyIHx8IHNjcm9sbFgpICYmICEgb1NldHRpbmdzLl9yZXN6RXZ0ICkge1xuXHRcdFx0dmFyIGJpbmRSZXNpemUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdCQod2luZG93KS5vbigncmVzaXplLkRULScrb1NldHRpbmdzLnNJbnN0YW5jZSwgX2ZuVGhyb3R0bGUoIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRfZm5BZGp1c3RDb2x1bW5TaXppbmcoIG9TZXR0aW5ncyApO1xuXHRcdFx0XHR9ICkgKTtcblx0XHRcdH07XG5cdFxuXHRcdFx0Ly8gSUU2Lzcgd2lsbCBjcmFzaCBpZiB3ZSBiaW5kIGEgcmVzaXplIGV2ZW50IGhhbmRsZXIgb24gcGFnZSBsb2FkLlxuXHRcdFx0Ly8gVG8gYmUgcmVtb3ZlZCBpbiAxLjExIHdoaWNoIGRyb3BzIElFNi83IHN1cHBvcnRcblx0XHRcdGlmICggaWU2NyApIHtcblx0XHRcdFx0c2V0VGltZW91dCggYmluZFJlc2l6ZSwgMTAwMCApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGJpbmRSZXNpemUoKTtcblx0XHRcdH1cblx0XG5cdFx0XHRvU2V0dGluZ3MuX3Jlc3pFdnQgPSB0cnVlO1xuXHRcdH1cblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBUaHJvdHRsZSB0aGUgY2FsbHMgdG8gYSBmdW5jdGlvbi4gQXJndW1lbnRzIGFuZCBjb250ZXh0IGFyZSBtYWludGFpbmVkIGZvclxuXHQgKiB0aGUgdGhyb3R0bGVkIGZ1bmN0aW9uXG5cdCAqICBAcGFyYW0ge2Z1bmN0aW9ufSBmbiBGdW5jdGlvbiB0byBiZSBjYWxsZWRcblx0ICogIEBwYXJhbSB7aW50fSBbZnJlcT0yMDBdIGNhbGwgZnJlcXVlbmN5IGluIG1TXG5cdCAqICBAcmV0dXJucyB7ZnVuY3Rpb259IHdyYXBwZWQgZnVuY3Rpb25cblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0dmFyIF9mblRocm90dGxlID0gRGF0YVRhYmxlLnV0aWwudGhyb3R0bGU7XG5cdFxuXHRcblx0LyoqXG5cdCAqIENvbnZlcnQgYSBDU1MgdW5pdCB3aWR0aCB0byBwaXhlbHMgKGUuZy4gMmVtKVxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IHdpZHRoIHdpZHRoIHRvIGJlIGNvbnZlcnRlZFxuXHQgKiAgQHBhcmFtIHtub2RlfSBwYXJlbnQgcGFyZW50IHRvIGdldCB0aGUgd2l0aCBmb3IgKHJlcXVpcmVkIGZvciByZWxhdGl2ZSB3aWR0aHMpIC0gb3B0aW9uYWxcblx0ICogIEByZXR1cm5zIHtpbnR9IHdpZHRoIGluIHBpeGVsc1xuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5Db252ZXJ0VG9XaWR0aCAoIHdpZHRoLCBwYXJlbnQgKVxuXHR7XG5cdFx0aWYgKCAhIHdpZHRoICkge1xuXHRcdFx0cmV0dXJuIDA7XG5cdFx0fVxuXHRcblx0XHR2YXIgbiA9ICQoJzxkaXYvPicpXG5cdFx0XHQuY3NzKCAnd2lkdGgnLCBfZm5TdHJpbmdUb0Nzcyggd2lkdGggKSApXG5cdFx0XHQuYXBwZW5kVG8oIHBhcmVudCB8fCBkb2N1bWVudC5ib2R5ICk7XG5cdFxuXHRcdHZhciB2YWwgPSBuWzBdLm9mZnNldFdpZHRoO1xuXHRcdG4ucmVtb3ZlKCk7XG5cdFxuXHRcdHJldHVybiB2YWw7XG5cdH1cblx0XG5cdFxuXHQvKipcblx0ICogR2V0IHRoZSB3aWRlc3Qgbm9kZVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge2ludH0gY29sSWR4IGNvbHVtbiBvZiBpbnRlcmVzdFxuXHQgKiAgQHJldHVybnMge25vZGV9IHdpZGVzdCB0YWJsZSBub2RlXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkdldFdpZGVzdE5vZGUoIHNldHRpbmdzLCBjb2xJZHggKVxuXHR7XG5cdFx0dmFyIGlkeCA9IF9mbkdldE1heExlblN0cmluZyggc2V0dGluZ3MsIGNvbElkeCApO1xuXHRcdGlmICggaWR4IDwgMCApIHtcblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH1cblx0XG5cdFx0dmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGFbIGlkeCBdO1xuXHRcdHJldHVybiAhIGRhdGEublRyID8gLy8gTWlnaHQgbm90IGhhdmUgYmVlbiBjcmVhdGVkIHdoZW4gZGVmZXJyZWQgcmVuZGVyaW5nXG5cdFx0XHQkKCc8dGQvPicpLmh0bWwoIF9mbkdldENlbGxEYXRhKCBzZXR0aW5ncywgaWR4LCBjb2xJZHgsICdkaXNwbGF5JyApIClbMF0gOlxuXHRcdFx0ZGF0YS5hbkNlbGxzWyBjb2xJZHggXTtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBHZXQgdGhlIG1heGltdW0gc3RybGVuIGZvciBlYWNoIGRhdGEgY29sdW1uXG5cdCAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7aW50fSBjb2xJZHggY29sdW1uIG9mIGludGVyZXN0XG5cdCAqICBAcmV0dXJucyB7c3RyaW5nfSBtYXggc3RyaW5nIGxlbmd0aCBmb3IgZWFjaCBjb2x1bW5cblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuR2V0TWF4TGVuU3RyaW5nKCBzZXR0aW5ncywgY29sSWR4IClcblx0e1xuXHRcdHZhciBzLCBtYXg9LTEsIG1heElkeCA9IC0xO1xuXHRcblx0XHRmb3IgKCB2YXIgaT0wLCBpZW49c2V0dGluZ3MuYW9EYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0cyA9IF9mbkdldENlbGxEYXRhKCBzZXR0aW5ncywgaSwgY29sSWR4LCAnZGlzcGxheScgKSsnJztcblx0XHRcdHMgPSBzLnJlcGxhY2UoIF9fcmVfaHRtbF9yZW1vdmUsICcnICk7XG5cdFx0XHRzID0gcy5yZXBsYWNlKCAvJm5ic3A7L2csICcgJyApO1xuXHRcblx0XHRcdGlmICggcy5sZW5ndGggPiBtYXggKSB7XG5cdFx0XHRcdG1heCA9IHMubGVuZ3RoO1xuXHRcdFx0XHRtYXhJZHggPSBpO1xuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0cmV0dXJuIG1heElkeDtcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBBcHBlbmQgYSBDU1MgdW5pdCAob25seSBpZiByZXF1aXJlZCkgdG8gYSBzdHJpbmdcblx0ICogIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZSB0byBjc3MtaWZ5XG5cdCAqICBAcmV0dXJucyB7c3RyaW5nfSB2YWx1ZSB3aXRoIGNzcyB1bml0XG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mblN0cmluZ1RvQ3NzKCBzIClcblx0e1xuXHRcdGlmICggcyA9PT0gbnVsbCApIHtcblx0XHRcdHJldHVybiAnMHB4Jztcblx0XHR9XG5cdFxuXHRcdGlmICggdHlwZW9mIHMgPT0gJ251bWJlcicgKSB7XG5cdFx0XHRyZXR1cm4gcyA8IDAgP1xuXHRcdFx0XHQnMHB4JyA6XG5cdFx0XHRcdHMrJ3B4Jztcblx0XHR9XG5cdFxuXHRcdC8vIENoZWNrIGl0IGhhcyBhIHVuaXQgY2hhcmFjdGVyIGFscmVhZHlcblx0XHRyZXR1cm4gcy5tYXRjaCgvXFxkJC8pID9cblx0XHRcdHMrJ3B4JyA6XG5cdFx0XHRzO1xuXHR9XG5cdFxuXHRcblx0XG5cdGZ1bmN0aW9uIF9mblNvcnRGbGF0dGVuICggc2V0dGluZ3MgKVxuXHR7XG5cdFx0dmFyXG5cdFx0XHRpLCBpTGVuLCBrLCBrTGVuLFxuXHRcdFx0YVNvcnQgPSBbXSxcblx0XHRcdGFpT3JpZyA9IFtdLFxuXHRcdFx0YW9Db2x1bW5zID0gc2V0dGluZ3MuYW9Db2x1bW5zLFxuXHRcdFx0YURhdGFTb3J0LCBpQ29sLCBzVHlwZSwgc3JjQ29sLFxuXHRcdFx0Zml4ZWQgPSBzZXR0aW5ncy5hYVNvcnRpbmdGaXhlZCxcblx0XHRcdGZpeGVkT2JqID0gJC5pc1BsYWluT2JqZWN0KCBmaXhlZCApLFxuXHRcdFx0bmVzdGVkU29ydCA9IFtdLFxuXHRcdFx0YWRkID0gZnVuY3Rpb24gKCBhICkge1xuXHRcdFx0XHRpZiAoIGEubGVuZ3RoICYmICEgJC5pc0FycmF5KCBhWzBdICkgKSB7XG5cdFx0XHRcdFx0Ly8gMUQgYXJyYXlcblx0XHRcdFx0XHRuZXN0ZWRTb3J0LnB1c2goIGEgKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHQvLyAyRCBhcnJheVxuXHRcdFx0XHRcdCQubWVyZ2UoIG5lc3RlZFNvcnQsIGEgKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XG5cdFx0Ly8gQnVpbGQgdGhlIHNvcnQgYXJyYXksIHdpdGggcHJlLWZpeCBhbmQgcG9zdC1maXggb3B0aW9ucyBpZiB0aGV5IGhhdmUgYmVlblxuXHRcdC8vIHNwZWNpZmllZFxuXHRcdGlmICggJC5pc0FycmF5KCBmaXhlZCApICkge1xuXHRcdFx0YWRkKCBmaXhlZCApO1xuXHRcdH1cblx0XG5cdFx0aWYgKCBmaXhlZE9iaiAmJiBmaXhlZC5wcmUgKSB7XG5cdFx0XHRhZGQoIGZpeGVkLnByZSApO1xuXHRcdH1cblx0XG5cdFx0YWRkKCBzZXR0aW5ncy5hYVNvcnRpbmcgKTtcblx0XG5cdFx0aWYgKGZpeGVkT2JqICYmIGZpeGVkLnBvc3QgKSB7XG5cdFx0XHRhZGQoIGZpeGVkLnBvc3QgKTtcblx0XHR9XG5cdFxuXHRcdGZvciAoIGk9MCA7IGk8bmVzdGVkU29ydC5sZW5ndGggOyBpKysgKVxuXHRcdHtcblx0XHRcdHNyY0NvbCA9IG5lc3RlZFNvcnRbaV1bMF07XG5cdFx0XHRhRGF0YVNvcnQgPSBhb0NvbHVtbnNbIHNyY0NvbCBdLmFEYXRhU29ydDtcblx0XG5cdFx0XHRmb3IgKCBrPTAsIGtMZW49YURhdGFTb3J0Lmxlbmd0aCA7IGs8a0xlbiA7IGsrKyApXG5cdFx0XHR7XG5cdFx0XHRcdGlDb2wgPSBhRGF0YVNvcnRba107XG5cdFx0XHRcdHNUeXBlID0gYW9Db2x1bW5zWyBpQ29sIF0uc1R5cGUgfHwgJ3N0cmluZyc7XG5cdFxuXHRcdFx0XHRpZiAoIG5lc3RlZFNvcnRbaV0uX2lkeCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdG5lc3RlZFNvcnRbaV0uX2lkeCA9ICQuaW5BcnJheSggbmVzdGVkU29ydFtpXVsxXSwgYW9Db2x1bW5zW2lDb2xdLmFzU29ydGluZyApO1xuXHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRhU29ydC5wdXNoKCB7XG5cdFx0XHRcdFx0c3JjOiAgICAgICBzcmNDb2wsXG5cdFx0XHRcdFx0Y29sOiAgICAgICBpQ29sLFxuXHRcdFx0XHRcdGRpcjogICAgICAgbmVzdGVkU29ydFtpXVsxXSxcblx0XHRcdFx0XHRpbmRleDogICAgIG5lc3RlZFNvcnRbaV0uX2lkeCxcblx0XHRcdFx0XHR0eXBlOiAgICAgIHNUeXBlLFxuXHRcdFx0XHRcdGZvcm1hdHRlcjogRGF0YVRhYmxlLmV4dC50eXBlLm9yZGVyWyBzVHlwZStcIi1wcmVcIiBdXG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFxuXHRcdHJldHVybiBhU29ydDtcblx0fVxuXHRcblx0LyoqXG5cdCAqIENoYW5nZSB0aGUgb3JkZXIgb2YgdGhlIHRhYmxlXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICogIEB0b2RvIFRoaXMgcmVhbGx5IG5lZWRzIHNwbGl0IHVwIVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuU29ydCAoIG9TZXR0aW5ncyApXG5cdHtcblx0XHR2YXJcblx0XHRcdGksIGllbiwgaUxlbiwgaiwgakxlbiwgaywga0xlbixcblx0XHRcdHNEYXRhVHlwZSwgblRoLFxuXHRcdFx0YWlPcmlnID0gW10sXG5cdFx0XHRvRXh0U29ydCA9IERhdGFUYWJsZS5leHQudHlwZS5vcmRlcixcblx0XHRcdGFvRGF0YSA9IG9TZXR0aW5ncy5hb0RhdGEsXG5cdFx0XHRhb0NvbHVtbnMgPSBvU2V0dGluZ3MuYW9Db2x1bW5zLFxuXHRcdFx0YURhdGFTb3J0LCBkYXRhLCBpQ29sLCBzVHlwZSwgb1NvcnQsXG5cdFx0XHRmb3JtYXR0ZXJzID0gMCxcblx0XHRcdHNvcnRDb2wsXG5cdFx0XHRkaXNwbGF5TWFzdGVyID0gb1NldHRpbmdzLmFpRGlzcGxheU1hc3Rlcixcblx0XHRcdGFTb3J0O1xuXHRcblx0XHQvLyBSZXNvbHZlIGFueSBjb2x1bW4gdHlwZXMgdGhhdCBhcmUgdW5rbm93biBkdWUgdG8gYWRkaXRpb24gb3IgaW52YWxpZGF0aW9uXG5cdFx0Ly8gQHRvZG8gQ2FuIHRoaXMgYmUgbW92ZWQgaW50byBhICdkYXRhLXJlYWR5JyBoYW5kbGVyIHdoaWNoIGlzIGNhbGxlZCB3aGVuXG5cdFx0Ly8gICBkYXRhIGlzIGdvaW5nIHRvIGJlIHVzZWQgaW4gdGhlIHRhYmxlP1xuXHRcdF9mbkNvbHVtblR5cGVzKCBvU2V0dGluZ3MgKTtcblx0XG5cdFx0YVNvcnQgPSBfZm5Tb3J0RmxhdHRlbiggb1NldHRpbmdzICk7XG5cdFxuXHRcdGZvciAoIGk9MCwgaWVuPWFTb3J0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0c29ydENvbCA9IGFTb3J0W2ldO1xuXHRcblx0XHRcdC8vIFRyYWNrIGlmIHdlIGNhbiB1c2UgdGhlIGZhc3Qgc29ydCBhbGdvcml0aG1cblx0XHRcdGlmICggc29ydENvbC5mb3JtYXR0ZXIgKSB7XG5cdFx0XHRcdGZvcm1hdHRlcnMrKztcblx0XHRcdH1cblx0XG5cdFx0XHQvLyBMb2FkIHRoZSBkYXRhIG5lZWRlZCBmb3IgdGhlIHNvcnQsIGZvciBlYWNoIGNlbGxcblx0XHRcdF9mblNvcnREYXRhKCBvU2V0dGluZ3MsIHNvcnRDb2wuY29sICk7XG5cdFx0fVxuXHRcblx0XHQvKiBObyBzb3J0aW5nIHJlcXVpcmVkIGlmIHNlcnZlci1zaWRlIG9yIG5vIHNvcnRpbmcgYXJyYXkgKi9cblx0XHRpZiAoIF9mbkRhdGFTb3VyY2UoIG9TZXR0aW5ncyApICE9ICdzc3AnICYmIGFTb3J0Lmxlbmd0aCAhPT0gMCApXG5cdFx0e1xuXHRcdFx0Ly8gQ3JlYXRlIGEgdmFsdWUgLSBrZXkgYXJyYXkgb2YgdGhlIGN1cnJlbnQgcm93IHBvc2l0aW9ucyBzdWNoIHRoYXQgd2UgY2FuIHVzZSB0aGVpclxuXHRcdFx0Ly8gY3VycmVudCBwb3NpdGlvbiBkdXJpbmcgdGhlIHNvcnQsIGlmIHZhbHVlcyBtYXRjaCwgaW4gb3JkZXIgdG8gcGVyZm9ybSBzdGFibGUgc29ydGluZ1xuXHRcdFx0Zm9yICggaT0wLCBpTGVuPWRpc3BsYXlNYXN0ZXIubGVuZ3RoIDsgaTxpTGVuIDsgaSsrICkge1xuXHRcdFx0XHRhaU9yaWdbIGRpc3BsYXlNYXN0ZXJbaV0gXSA9IGk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0LyogRG8gdGhlIHNvcnQgLSBoZXJlIHdlIHdhbnQgbXVsdGktY29sdW1uIHNvcnRpbmcgYmFzZWQgb24gYSBnaXZlbiBkYXRhIHNvdXJjZSAoY29sdW1uKVxuXHRcdFx0ICogYW5kIHNvcnRpbmcgZnVuY3Rpb24gKGZyb20gb1NvcnQpIGluIGEgY2VydGFpbiBkaXJlY3Rpb24uIEl0J3MgcmVhc29uYWJseSBjb21wbGV4IHRvXG5cdFx0XHQgKiBmb2xsb3cgb24gaXQncyBvd24sIGJ1dCB0aGlzIGlzIHdoYXQgd2Ugd2FudCAoZXhhbXBsZSB0d28gY29sdW1uIHNvcnRpbmcpOlxuXHRcdFx0ICogIGZuTG9jYWxTb3J0aW5nID0gZnVuY3Rpb24oYSxiKXtcblx0XHRcdCAqICAgIHZhciBpVGVzdDtcblx0XHRcdCAqICAgIGlUZXN0ID0gb1NvcnRbJ3N0cmluZy1hc2MnXSgnZGF0YTExJywgJ2RhdGExMicpO1xuXHRcdFx0ICogICAgICBpZiAoaVRlc3QgIT09IDApXG5cdFx0XHQgKiAgICAgICAgcmV0dXJuIGlUZXN0O1xuXHRcdFx0ICogICAgaVRlc3QgPSBvU29ydFsnbnVtZXJpYy1kZXNjJ10oJ2RhdGEyMScsICdkYXRhMjInKTtcblx0XHRcdCAqICAgIGlmIChpVGVzdCAhPT0gMClcblx0XHRcdCAqICAgICAgcmV0dXJuIGlUZXN0O1xuXHRcdFx0ICogICAgcmV0dXJuIG9Tb3J0WydudW1lcmljLWFzYyddKCBhaU9yaWdbYV0sIGFpT3JpZ1tiXSApO1xuXHRcdFx0ICogIH1cblx0XHRcdCAqIEJhc2ljYWxseSB3ZSBoYXZlIGEgdGVzdCBmb3IgZWFjaCBzb3J0aW5nIGNvbHVtbiwgaWYgdGhlIGRhdGEgaW4gdGhhdCBjb2x1bW4gaXMgZXF1YWwsXG5cdFx0XHQgKiB0ZXN0IHRoZSBuZXh0IGNvbHVtbi4gSWYgYWxsIGNvbHVtbnMgbWF0Y2gsIHRoZW4gd2UgdXNlIGEgbnVtZXJpYyBzb3J0IG9uIHRoZSByb3dcblx0XHRcdCAqIHBvc2l0aW9ucyBpbiB0aGUgb3JpZ2luYWwgZGF0YSBhcnJheSB0byBwcm92aWRlIGEgc3RhYmxlIHNvcnQuXG5cdFx0XHQgKlxuXHRcdFx0ICogTm90ZSAtIEkga25vdyBpdCBzZWVtcyBleGNlc3NpdmUgdG8gaGF2ZSB0d28gc29ydGluZyBtZXRob2RzLCBidXQgdGhlIGZpcnN0IGlzIGFyb3VuZFxuXHRcdFx0ICogMTUlIGZhc3Rlciwgc28gdGhlIHNlY29uZCBpcyBvbmx5IG1haW50YWluZWQgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHdpdGggc29ydGluZ1xuXHRcdFx0ICogbWV0aG9kcyB3aGljaCBkbyBub3QgaGF2ZSBhIHByZS1zb3J0IGZvcm1hdHRpbmcgZnVuY3Rpb24uXG5cdFx0XHQgKi9cblx0XHRcdGlmICggZm9ybWF0dGVycyA9PT0gYVNvcnQubGVuZ3RoICkge1xuXHRcdFx0XHQvLyBBbGwgc29ydCB0eXBlcyBoYXZlIGZvcm1hdHRpbmcgZnVuY3Rpb25zXG5cdFx0XHRcdGRpc3BsYXlNYXN0ZXIuc29ydCggZnVuY3Rpb24gKCBhLCBiICkge1xuXHRcdFx0XHRcdHZhclxuXHRcdFx0XHRcdFx0eCwgeSwgaywgdGVzdCwgc29ydCxcblx0XHRcdFx0XHRcdGxlbj1hU29ydC5sZW5ndGgsXG5cdFx0XHRcdFx0XHRkYXRhQSA9IGFvRGF0YVthXS5fYVNvcnREYXRhLFxuXHRcdFx0XHRcdFx0ZGF0YUIgPSBhb0RhdGFbYl0uX2FTb3J0RGF0YTtcblx0XG5cdFx0XHRcdFx0Zm9yICggaz0wIDsgazxsZW4gOyBrKysgKSB7XG5cdFx0XHRcdFx0XHRzb3J0ID0gYVNvcnRba107XG5cdFxuXHRcdFx0XHRcdFx0eCA9IGRhdGFBWyBzb3J0LmNvbCBdO1xuXHRcdFx0XHRcdFx0eSA9IGRhdGFCWyBzb3J0LmNvbCBdO1xuXHRcblx0XHRcdFx0XHRcdHRlc3QgPSB4PHkgPyAtMSA6IHg+eSA/IDEgOiAwO1xuXHRcdFx0XHRcdFx0aWYgKCB0ZXN0ICE9PSAwICkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm4gc29ydC5kaXIgPT09ICdhc2MnID8gdGVzdCA6IC10ZXN0O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0eCA9IGFpT3JpZ1thXTtcblx0XHRcdFx0XHR5ID0gYWlPcmlnW2JdO1xuXHRcdFx0XHRcdHJldHVybiB4PHkgPyAtMSA6IHg+eSA/IDEgOiAwO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0Ly8gRGVwcmVjaWF0ZWQgLSByZW1vdmUgaW4gMS4xMSAocHJvdmlkaW5nIGEgcGx1Zy1pbiBvcHRpb24pXG5cdFx0XHRcdC8vIE5vdCBhbGwgc29ydCB0eXBlcyBoYXZlIGZvcm1hdHRpbmcgbWV0aG9kcywgc28gd2UgaGF2ZSB0byBjYWxsIHRoZWlyIHNvcnRpbmdcblx0XHRcdFx0Ly8gbWV0aG9kcy5cblx0XHRcdFx0ZGlzcGxheU1hc3Rlci5zb3J0KCBmdW5jdGlvbiAoIGEsIGIgKSB7XG5cdFx0XHRcdFx0dmFyXG5cdFx0XHRcdFx0XHR4LCB5LCBrLCBsLCB0ZXN0LCBzb3J0LCBmbixcblx0XHRcdFx0XHRcdGxlbj1hU29ydC5sZW5ndGgsXG5cdFx0XHRcdFx0XHRkYXRhQSA9IGFvRGF0YVthXS5fYVNvcnREYXRhLFxuXHRcdFx0XHRcdFx0ZGF0YUIgPSBhb0RhdGFbYl0uX2FTb3J0RGF0YTtcblx0XG5cdFx0XHRcdFx0Zm9yICggaz0wIDsgazxsZW4gOyBrKysgKSB7XG5cdFx0XHRcdFx0XHRzb3J0ID0gYVNvcnRba107XG5cdFxuXHRcdFx0XHRcdFx0eCA9IGRhdGFBWyBzb3J0LmNvbCBdO1xuXHRcdFx0XHRcdFx0eSA9IGRhdGFCWyBzb3J0LmNvbCBdO1xuXHRcblx0XHRcdFx0XHRcdGZuID0gb0V4dFNvcnRbIHNvcnQudHlwZStcIi1cIitzb3J0LmRpciBdIHx8IG9FeHRTb3J0WyBcInN0cmluZy1cIitzb3J0LmRpciBdO1xuXHRcdFx0XHRcdFx0dGVzdCA9IGZuKCB4LCB5ICk7XG5cdFx0XHRcdFx0XHRpZiAoIHRlc3QgIT09IDAgKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiB0ZXN0O1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0eCA9IGFpT3JpZ1thXTtcblx0XHRcdFx0XHR5ID0gYWlPcmlnW2JdO1xuXHRcdFx0XHRcdHJldHVybiB4PHkgPyAtMSA6IHg+eSA/IDEgOiAwO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHQvKiBUZWxsIHRoZSBkcmF3IGZ1bmN0aW9uIHRoYXQgd2UgaGF2ZSBzb3J0ZWQgdGhlIGRhdGEgKi9cblx0XHRvU2V0dGluZ3MuYlNvcnRlZCA9IHRydWU7XG5cdH1cblx0XG5cdFxuXHRmdW5jdGlvbiBfZm5Tb3J0QXJpYSAoIHNldHRpbmdzIClcblx0e1xuXHRcdHZhciBsYWJlbDtcblx0XHR2YXIgbmV4dFNvcnQ7XG5cdFx0dmFyIGNvbHVtbnMgPSBzZXR0aW5ncy5hb0NvbHVtbnM7XG5cdFx0dmFyIGFTb3J0ID0gX2ZuU29ydEZsYXR0ZW4oIHNldHRpbmdzICk7XG5cdFx0dmFyIG9BcmlhID0gc2V0dGluZ3Mub0xhbmd1YWdlLm9BcmlhO1xuXHRcblx0XHQvLyBBUklBIGF0dHJpYnV0ZXMgLSBuZWVkIHRvIGxvb3AgYWxsIGNvbHVtbnMsIHRvIHVwZGF0ZSBhbGwgKHJlbW92aW5nIG9sZFxuXHRcdC8vIGF0dHJpYnV0ZXMgYXMgbmVlZGVkKVxuXHRcdGZvciAoIHZhciBpPTAsIGlMZW49Y29sdW1ucy5sZW5ndGggOyBpPGlMZW4gOyBpKysgKVxuXHRcdHtcblx0XHRcdHZhciBjb2wgPSBjb2x1bW5zW2ldO1xuXHRcdFx0dmFyIGFzU29ydGluZyA9IGNvbC5hc1NvcnRpbmc7XG5cdFx0XHR2YXIgc1RpdGxlID0gY29sLnNUaXRsZS5yZXBsYWNlKCAvPC4qPz4vZywgXCJcIiApO1xuXHRcdFx0dmFyIHRoID0gY29sLm5UaDtcblx0XG5cdFx0XHQvLyBJRTcgaXMgdGhyb3dpbmcgYW4gZXJyb3Igd2hlbiBzZXR0aW5nIHRoZXNlIHByb3BlcnRpZXMgd2l0aCBqUXVlcnknc1xuXHRcdFx0Ly8gYXR0cigpIGFuZCByZW1vdmVBdHRyKCkgbWV0aG9kcy4uLlxuXHRcdFx0dGgucmVtb3ZlQXR0cmlidXRlKCdhcmlhLXNvcnQnKTtcblx0XG5cdFx0XHQvKiBJbiBBUklBIG9ubHkgdGhlIGZpcnN0IHNvcnRpbmcgY29sdW1uIGNhbiBiZSBtYXJrZWQgYXMgc29ydGluZyAtIG5vIG11bHRpLXNvcnQgb3B0aW9uICovXG5cdFx0XHRpZiAoIGNvbC5iU29ydGFibGUgKSB7XG5cdFx0XHRcdGlmICggYVNvcnQubGVuZ3RoID4gMCAmJiBhU29ydFswXS5jb2wgPT0gaSApIHtcblx0XHRcdFx0XHR0aC5zZXRBdHRyaWJ1dGUoJ2FyaWEtc29ydCcsIGFTb3J0WzBdLmRpcj09XCJhc2NcIiA/IFwiYXNjZW5kaW5nXCIgOiBcImRlc2NlbmRpbmdcIiApO1xuXHRcdFx0XHRcdG5leHRTb3J0ID0gYXNTb3J0aW5nWyBhU29ydFswXS5pbmRleCsxIF0gfHwgYXNTb3J0aW5nWzBdO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdG5leHRTb3J0ID0gYXNTb3J0aW5nWzBdO1xuXHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRsYWJlbCA9IHNUaXRsZSArICggbmV4dFNvcnQgPT09IFwiYXNjXCIgP1xuXHRcdFx0XHRcdG9BcmlhLnNTb3J0QXNjZW5kaW5nIDpcblx0XHRcdFx0XHRvQXJpYS5zU29ydERlc2NlbmRpbmdcblx0XHRcdFx0KTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRsYWJlbCA9IHNUaXRsZTtcblx0XHRcdH1cblx0XG5cdFx0XHR0aC5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCBsYWJlbCk7XG5cdFx0fVxuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEZ1bmN0aW9uIHRvIHJ1biBvbiB1c2VyIHNvcnQgcmVxdWVzdFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge25vZGV9IGF0dGFjaFRvIG5vZGUgdG8gYXR0YWNoIHRoZSBoYW5kbGVyIHRvXG5cdCAqICBAcGFyYW0ge2ludH0gY29sSWR4IGNvbHVtbiBzb3J0aW5nIGluZGV4XG5cdCAqICBAcGFyYW0ge2Jvb2xlYW59IFthcHBlbmQ9ZmFsc2VdIEFwcGVuZCB0aGUgcmVxdWVzdGVkIHNvcnQgdG8gdGhlIGV4aXN0aW5nXG5cdCAqICAgIHNvcnQgaWYgdHJ1ZSAoaS5lLiBtdWx0aS1jb2x1bW4gc29ydClcblx0ICogIEBwYXJhbSB7ZnVuY3Rpb259IFtjYWxsYmFja10gY2FsbGJhY2sgZnVuY3Rpb25cblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuU29ydExpc3RlbmVyICggc2V0dGluZ3MsIGNvbElkeCwgYXBwZW5kLCBjYWxsYmFjayApXG5cdHtcblx0XHR2YXIgY29sID0gc2V0dGluZ3MuYW9Db2x1bW5zWyBjb2xJZHggXTtcblx0XHR2YXIgc29ydGluZyA9IHNldHRpbmdzLmFhU29ydGluZztcblx0XHR2YXIgYXNTb3J0aW5nID0gY29sLmFzU29ydGluZztcblx0XHR2YXIgbmV4dFNvcnRJZHg7XG5cdFx0dmFyIG5leHQgPSBmdW5jdGlvbiAoIGEsIG92ZXJmbG93ICkge1xuXHRcdFx0dmFyIGlkeCA9IGEuX2lkeDtcblx0XHRcdGlmICggaWR4ID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdGlkeCA9ICQuaW5BcnJheSggYVsxXSwgYXNTb3J0aW5nICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0cmV0dXJuIGlkeCsxIDwgYXNTb3J0aW5nLmxlbmd0aCA/XG5cdFx0XHRcdGlkeCsxIDpcblx0XHRcdFx0b3ZlcmZsb3cgP1xuXHRcdFx0XHRcdG51bGwgOlxuXHRcdFx0XHRcdDA7XG5cdFx0fTtcblx0XG5cdFx0Ly8gQ29udmVydCB0byAyRCBhcnJheSBpZiBuZWVkZWRcblx0XHRpZiAoIHR5cGVvZiBzb3J0aW5nWzBdID09PSAnbnVtYmVyJyApIHtcblx0XHRcdHNvcnRpbmcgPSBzZXR0aW5ncy5hYVNvcnRpbmcgPSBbIHNvcnRpbmcgXTtcblx0XHR9XG5cdFxuXHRcdC8vIElmIGFwcGVuZGluZyB0aGUgc29ydCB0aGVuIHdlIGFyZSBtdWx0aS1jb2x1bW4gc29ydGluZ1xuXHRcdGlmICggYXBwZW5kICYmIHNldHRpbmdzLm9GZWF0dXJlcy5iU29ydE11bHRpICkge1xuXHRcdFx0Ly8gQXJlIHdlIGFscmVhZHkgZG9pbmcgc29tZSBraW5kIG9mIHNvcnQgb24gdGhpcyBjb2x1bW4/XG5cdFx0XHR2YXIgc29ydElkeCA9ICQuaW5BcnJheSggY29sSWR4LCBfcGx1Y2soc29ydGluZywgJzAnKSApO1xuXHRcblx0XHRcdGlmICggc29ydElkeCAhPT0gLTEgKSB7XG5cdFx0XHRcdC8vIFllcywgbW9kaWZ5IHRoZSBzb3J0XG5cdFx0XHRcdG5leHRTb3J0SWR4ID0gbmV4dCggc29ydGluZ1tzb3J0SWR4XSwgdHJ1ZSApO1xuXHRcblx0XHRcdFx0aWYgKCBuZXh0U29ydElkeCA9PT0gbnVsbCAmJiBzb3J0aW5nLmxlbmd0aCA9PT0gMSApIHtcblx0XHRcdFx0XHRuZXh0U29ydElkeCA9IDA7IC8vIGNhbid0IHJlbW92ZSBzb3J0aW5nIGNvbXBsZXRlbHlcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0aWYgKCBuZXh0U29ydElkeCA9PT0gbnVsbCApIHtcblx0XHRcdFx0XHRzb3J0aW5nLnNwbGljZSggc29ydElkeCwgMSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdHNvcnRpbmdbc29ydElkeF1bMV0gPSBhc1NvcnRpbmdbIG5leHRTb3J0SWR4IF07XG5cdFx0XHRcdFx0c29ydGluZ1tzb3J0SWR4XS5faWR4ID0gbmV4dFNvcnRJZHg7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHQvLyBObyBzb3J0IG9uIHRoaXMgY29sdW1uIHlldFxuXHRcdFx0XHRzb3J0aW5nLnB1c2goIFsgY29sSWR4LCBhc1NvcnRpbmdbMF0sIDAgXSApO1xuXHRcdFx0XHRzb3J0aW5nW3NvcnRpbmcubGVuZ3RoLTFdLl9pZHggPSAwO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggc29ydGluZy5sZW5ndGggJiYgc29ydGluZ1swXVswXSA9PSBjb2xJZHggKSB7XG5cdFx0XHQvLyBTaW5nbGUgY29sdW1uIC0gYWxyZWFkeSBzb3J0aW5nIG9uIHRoaXMgY29sdW1uLCBtb2RpZnkgdGhlIHNvcnRcblx0XHRcdG5leHRTb3J0SWR4ID0gbmV4dCggc29ydGluZ1swXSApO1xuXHRcblx0XHRcdHNvcnRpbmcubGVuZ3RoID0gMTtcblx0XHRcdHNvcnRpbmdbMF1bMV0gPSBhc1NvcnRpbmdbIG5leHRTb3J0SWR4IF07XG5cdFx0XHRzb3J0aW5nWzBdLl9pZHggPSBuZXh0U29ydElkeDtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHQvLyBTaW5nbGUgY29sdW1uIC0gc29ydCBvbmx5IG9uIHRoaXMgY29sdW1uXG5cdFx0XHRzb3J0aW5nLmxlbmd0aCA9IDA7XG5cdFx0XHRzb3J0aW5nLnB1c2goIFsgY29sSWR4LCBhc1NvcnRpbmdbMF0gXSApO1xuXHRcdFx0c29ydGluZ1swXS5faWR4ID0gMDtcblx0XHR9XG5cdFxuXHRcdC8vIFJ1biB0aGUgc29ydCBieSBjYWxsaW5nIGEgZnVsbCByZWRyYXdcblx0XHRfZm5SZURyYXcoIHNldHRpbmdzICk7XG5cdFxuXHRcdC8vIGNhbGxiYWNrIHVzZWQgZm9yIGFzeW5jIHVzZXIgaW50ZXJhY3Rpb25cblx0XHRpZiAoIHR5cGVvZiBjYWxsYmFjayA9PSAnZnVuY3Rpb24nICkge1xuXHRcdFx0Y2FsbGJhY2soIHNldHRpbmdzICk7XG5cdFx0fVxuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEF0dGFjaCBhIHNvcnQgaGFuZGxlciAoY2xpY2spIHRvIGEgbm9kZVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge25vZGV9IGF0dGFjaFRvIG5vZGUgdG8gYXR0YWNoIHRoZSBoYW5kbGVyIHRvXG5cdCAqICBAcGFyYW0ge2ludH0gY29sSWR4IGNvbHVtbiBzb3J0aW5nIGluZGV4XG5cdCAqICBAcGFyYW0ge2Z1bmN0aW9ufSBbY2FsbGJhY2tdIGNhbGxiYWNrIGZ1bmN0aW9uXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mblNvcnRBdHRhY2hMaXN0ZW5lciAoIHNldHRpbmdzLCBhdHRhY2hUbywgY29sSWR4LCBjYWxsYmFjayApXG5cdHtcblx0XHR2YXIgY29sID0gc2V0dGluZ3MuYW9Db2x1bW5zWyBjb2xJZHggXTtcblx0XG5cdFx0X2ZuQmluZEFjdGlvbiggYXR0YWNoVG8sIHt9LCBmdW5jdGlvbiAoZSkge1xuXHRcdFx0LyogSWYgdGhlIGNvbHVtbiBpcyBub3Qgc29ydGFibGUgLSBkb24ndCB0byBhbnl0aGluZyAqL1xuXHRcdFx0aWYgKCBjb2wuYlNvcnRhYmxlID09PSBmYWxzZSApIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIElmIHByb2Nlc3NpbmcgaXMgZW5hYmxlZCB1c2UgYSB0aW1lb3V0IHRvIGFsbG93IHRoZSBwcm9jZXNzaW5nXG5cdFx0XHQvLyBkaXNwbGF5IHRvIGJlIHNob3duIC0gb3RoZXJ3aXNlIHRvIGl0IHN5bmNocm9ub3VzbHlcblx0XHRcdGlmICggc2V0dGluZ3Mub0ZlYXR1cmVzLmJQcm9jZXNzaW5nICkge1xuXHRcdFx0XHRfZm5Qcm9jZXNzaW5nRGlzcGxheSggc2V0dGluZ3MsIHRydWUgKTtcblx0XG5cdFx0XHRcdHNldFRpbWVvdXQoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdF9mblNvcnRMaXN0ZW5lciggc2V0dGluZ3MsIGNvbElkeCwgZS5zaGlmdEtleSwgY2FsbGJhY2sgKTtcblx0XG5cdFx0XHRcdFx0Ly8gSW4gc2VydmVyLXNpZGUgcHJvY2Vzc2luZywgdGhlIGRyYXcgY2FsbGJhY2sgd2lsbCByZW1vdmUgdGhlXG5cdFx0XHRcdFx0Ly8gcHJvY2Vzc2luZyBkaXNwbGF5XG5cdFx0XHRcdFx0aWYgKCBfZm5EYXRhU291cmNlKCBzZXR0aW5ncyApICE9PSAnc3NwJyApIHtcblx0XHRcdFx0XHRcdF9mblByb2Nlc3NpbmdEaXNwbGF5KCBzZXR0aW5ncywgZmFsc2UgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sIDAgKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHRfZm5Tb3J0TGlzdGVuZXIoIHNldHRpbmdzLCBjb2xJZHgsIGUuc2hpZnRLZXksIGNhbGxiYWNrICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFNldCB0aGUgc29ydGluZyBjbGFzc2VzIG9uIHRhYmxlJ3MgYm9keSwgTm90ZTogaXQgaXMgc2FmZSB0byBjYWxsIHRoaXMgZnVuY3Rpb25cblx0ICogd2hlbiBiU29ydCBhbmQgYlNvcnRDbGFzc2VzIGFyZSBmYWxzZVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5Tb3J0aW5nQ2xhc3Nlcyggc2V0dGluZ3MgKVxuXHR7XG5cdFx0dmFyIG9sZFNvcnQgPSBzZXR0aW5ncy5hTGFzdFNvcnQ7XG5cdFx0dmFyIHNvcnRDbGFzcyA9IHNldHRpbmdzLm9DbGFzc2VzLnNTb3J0Q29sdW1uO1xuXHRcdHZhciBzb3J0ID0gX2ZuU29ydEZsYXR0ZW4oIHNldHRpbmdzICk7XG5cdFx0dmFyIGZlYXR1cmVzID0gc2V0dGluZ3Mub0ZlYXR1cmVzO1xuXHRcdHZhciBpLCBpZW4sIGNvbElkeDtcblx0XG5cdFx0aWYgKCBmZWF0dXJlcy5iU29ydCAmJiBmZWF0dXJlcy5iU29ydENsYXNzZXMgKSB7XG5cdFx0XHQvLyBSZW1vdmUgb2xkIHNvcnRpbmcgY2xhc3Nlc1xuXHRcdFx0Zm9yICggaT0wLCBpZW49b2xkU29ydC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0Y29sSWR4ID0gb2xkU29ydFtpXS5zcmM7XG5cdFxuXHRcdFx0XHQvLyBSZW1vdmUgY29sdW1uIHNvcnRpbmdcblx0XHRcdFx0JCggX3BsdWNrKCBzZXR0aW5ncy5hb0RhdGEsICdhbkNlbGxzJywgY29sSWR4ICkgKVxuXHRcdFx0XHRcdC5yZW1vdmVDbGFzcyggc29ydENsYXNzICsgKGk8MiA/IGkrMSA6IDMpICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gQWRkIG5ldyBjb2x1bW4gc29ydGluZ1xuXHRcdFx0Zm9yICggaT0wLCBpZW49c29ydC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0Y29sSWR4ID0gc29ydFtpXS5zcmM7XG5cdFxuXHRcdFx0XHQkKCBfcGx1Y2soIHNldHRpbmdzLmFvRGF0YSwgJ2FuQ2VsbHMnLCBjb2xJZHggKSApXG5cdFx0XHRcdFx0LmFkZENsYXNzKCBzb3J0Q2xhc3MgKyAoaTwyID8gaSsxIDogMykgKTtcblx0XHRcdH1cblx0XHR9XG5cdFxuXHRcdHNldHRpbmdzLmFMYXN0U29ydCA9IHNvcnQ7XG5cdH1cblx0XG5cdFxuXHQvLyBHZXQgdGhlIGRhdGEgdG8gc29ydCBhIGNvbHVtbiwgYmUgaXQgZnJvbSBjYWNoZSwgZnJlc2ggKHBvcHVsYXRpbmcgdGhlXG5cdC8vIGNhY2hlKSwgb3IgZnJvbSBhIHNvcnQgZm9ybWF0dGVyXG5cdGZ1bmN0aW9uIF9mblNvcnREYXRhKCBzZXR0aW5ncywgaWR4IClcblx0e1xuXHRcdC8vIEN1c3RvbSBzb3J0aW5nIGZ1bmN0aW9uIC0gcHJvdmlkZWQgYnkgdGhlIHNvcnQgZGF0YSB0eXBlXG5cdFx0dmFyIGNvbHVtbiA9IHNldHRpbmdzLmFvQ29sdW1uc1sgaWR4IF07XG5cdFx0dmFyIGN1c3RvbVNvcnQgPSBEYXRhVGFibGUuZXh0Lm9yZGVyWyBjb2x1bW4uc1NvcnREYXRhVHlwZSBdO1xuXHRcdHZhciBjdXN0b21EYXRhO1xuXHRcblx0XHRpZiAoIGN1c3RvbVNvcnQgKSB7XG5cdFx0XHRjdXN0b21EYXRhID0gY3VzdG9tU29ydC5jYWxsKCBzZXR0aW5ncy5vSW5zdGFuY2UsIHNldHRpbmdzLCBpZHgsXG5cdFx0XHRcdF9mbkNvbHVtbkluZGV4VG9WaXNpYmxlKCBzZXR0aW5ncywgaWR4IClcblx0XHRcdCk7XG5cdFx0fVxuXHRcblx0XHQvLyBVc2UgLyBwb3B1bGF0ZSBjYWNoZVxuXHRcdHZhciByb3csIGNlbGxEYXRhO1xuXHRcdHZhciBmb3JtYXR0ZXIgPSBEYXRhVGFibGUuZXh0LnR5cGUub3JkZXJbIGNvbHVtbi5zVHlwZStcIi1wcmVcIiBdO1xuXHRcblx0XHRmb3IgKCB2YXIgaT0wLCBpZW49c2V0dGluZ3MuYW9EYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0cm93ID0gc2V0dGluZ3MuYW9EYXRhW2ldO1xuXHRcblx0XHRcdGlmICggISByb3cuX2FTb3J0RGF0YSApIHtcblx0XHRcdFx0cm93Ll9hU29ydERhdGEgPSBbXTtcblx0XHRcdH1cblx0XG5cdFx0XHRpZiAoICEgcm93Ll9hU29ydERhdGFbaWR4XSB8fCBjdXN0b21Tb3J0ICkge1xuXHRcdFx0XHRjZWxsRGF0YSA9IGN1c3RvbVNvcnQgP1xuXHRcdFx0XHRcdGN1c3RvbURhdGFbaV0gOiAvLyBJZiB0aGVyZSB3YXMgYSBjdXN0b20gc29ydCBmdW5jdGlvbiwgdXNlIGRhdGEgZnJvbSB0aGVyZVxuXHRcdFx0XHRcdF9mbkdldENlbGxEYXRhKCBzZXR0aW5ncywgaSwgaWR4LCAnc29ydCcgKTtcblx0XG5cdFx0XHRcdHJvdy5fYVNvcnREYXRhWyBpZHggXSA9IGZvcm1hdHRlciA/XG5cdFx0XHRcdFx0Zm9ybWF0dGVyKCBjZWxsRGF0YSApIDpcblx0XHRcdFx0XHRjZWxsRGF0YTtcblx0XHRcdH1cblx0XHR9XG5cdH1cblx0XG5cdFxuXHRcblx0LyoqXG5cdCAqIFNhdmUgdGhlIHN0YXRlIG9mIGEgdGFibGVcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuU2F2ZVN0YXRlICggc2V0dGluZ3MgKVxuXHR7XG5cdFx0aWYgKCAhc2V0dGluZ3Mub0ZlYXR1cmVzLmJTdGF0ZVNhdmUgfHwgc2V0dGluZ3MuYkRlc3Ryb3lpbmcgKVxuXHRcdHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFxuXHRcdC8qIFN0b3JlIHRoZSBpbnRlcmVzdGluZyB2YXJpYWJsZXMgKi9cblx0XHR2YXIgc3RhdGUgPSB7XG5cdFx0XHR0aW1lOiAgICArbmV3IERhdGUoKSxcblx0XHRcdHN0YXJ0OiAgIHNldHRpbmdzLl9pRGlzcGxheVN0YXJ0LFxuXHRcdFx0bGVuZ3RoOiAgc2V0dGluZ3MuX2lEaXNwbGF5TGVuZ3RoLFxuXHRcdFx0b3JkZXI6ICAgJC5leHRlbmQoIHRydWUsIFtdLCBzZXR0aW5ncy5hYVNvcnRpbmcgKSxcblx0XHRcdHNlYXJjaDogIF9mblNlYXJjaFRvQ2FtZWwoIHNldHRpbmdzLm9QcmV2aW91c1NlYXJjaCApLFxuXHRcdFx0Y29sdW1uczogJC5tYXAoIHNldHRpbmdzLmFvQ29sdW1ucywgZnVuY3Rpb24gKCBjb2wsIGkgKSB7XG5cdFx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFx0dmlzaWJsZTogY29sLmJWaXNpYmxlLFxuXHRcdFx0XHRcdHNlYXJjaDogX2ZuU2VhcmNoVG9DYW1lbCggc2V0dGluZ3MuYW9QcmVTZWFyY2hDb2xzW2ldIClcblx0XHRcdFx0fTtcblx0XHRcdH0gKVxuXHRcdH07XG5cdFxuXHRcdF9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsIFwiYW9TdGF0ZVNhdmVQYXJhbXNcIiwgJ3N0YXRlU2F2ZVBhcmFtcycsIFtzZXR0aW5ncywgc3RhdGVdICk7XG5cdFxuXHRcdHNldHRpbmdzLm9TYXZlZFN0YXRlID0gc3RhdGU7XG5cdFx0c2V0dGluZ3MuZm5TdGF0ZVNhdmVDYWxsYmFjay5jYWxsKCBzZXR0aW5ncy5vSW5zdGFuY2UsIHNldHRpbmdzLCBzdGF0ZSApO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEF0dGVtcHQgdG8gbG9hZCBhIHNhdmVkIHRhYmxlIHN0YXRlXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIGRhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge29iamVjdH0gb0luaXQgRGF0YVRhYmxlcyBpbml0IG9iamVjdCBzbyB3ZSBjYW4gb3ZlcnJpZGUgc2V0dGluZ3Ncblx0ICogIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrIENhbGxiYWNrIHRvIGV4ZWN1dGUgd2hlbiB0aGUgc3RhdGUgaGFzIGJlZW4gbG9hZGVkXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkxvYWRTdGF0ZSAoIHNldHRpbmdzLCBvSW5pdCwgY2FsbGJhY2sgKVxuXHR7XG5cdFx0dmFyIGksIGllbjtcblx0XHR2YXIgY29sdW1ucyA9IHNldHRpbmdzLmFvQ29sdW1ucztcblx0XHR2YXIgbG9hZGVkID0gZnVuY3Rpb24gKCBzICkge1xuXHRcdFx0aWYgKCAhIHMgfHwgISBzLnRpbWUgKSB7XG5cdFx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XG5cdFx0XHQvLyBBbGxvdyBjdXN0b20gYW5kIHBsdWctaW4gbWFuaXB1bGF0aW9uIGZ1bmN0aW9ucyB0byBhbHRlciB0aGUgc2F2ZWQgZGF0YSBzZXQgYW5kXG5cdFx0XHQvLyBjYW5jZWxsaW5nIG9mIGxvYWRpbmcgYnkgcmV0dXJuaW5nIGZhbHNlXG5cdFx0XHR2YXIgYWJTdGF0ZUxvYWQgPSBfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCAnYW9TdGF0ZUxvYWRQYXJhbXMnLCAnc3RhdGVMb2FkUGFyYW1zJywgW3NldHRpbmdzLCBzXSApO1xuXHRcdFx0aWYgKCAkLmluQXJyYXkoIGZhbHNlLCBhYlN0YXRlTG9hZCApICE9PSAtMSApIHtcblx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIFJlamVjdCBvbGQgZGF0YVxuXHRcdFx0dmFyIGR1cmF0aW9uID0gc2V0dGluZ3MuaVN0YXRlRHVyYXRpb247XG5cdFx0XHRpZiAoIGR1cmF0aW9uID4gMCAmJiBzLnRpbWUgPCArbmV3IERhdGUoKSAtIChkdXJhdGlvbioxMDAwKSApIHtcblx0XHRcdFx0Y2FsbGJhY2soKTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIE51bWJlciBvZiBjb2x1bW5zIGhhdmUgY2hhbmdlZCAtIGFsbCBiZXRzIGFyZSBvZmYsIG5vIHJlc3RvcmUgb2Ygc2V0dGluZ3Ncblx0XHRcdGlmICggcy5jb2x1bW5zICYmIGNvbHVtbnMubGVuZ3RoICE9PSBzLmNvbHVtbnMubGVuZ3RoICkge1xuXHRcdFx0XHRjYWxsYmFjaygpO1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gU3RvcmUgdGhlIHNhdmVkIHN0YXRlIHNvIGl0IG1pZ2h0IGJlIGFjY2Vzc2VkIGF0IGFueSB0aW1lXG5cdFx0XHRzZXR0aW5ncy5vTG9hZGVkU3RhdGUgPSAkLmV4dGVuZCggdHJ1ZSwge30sIHMgKTtcblx0XG5cdFx0XHQvLyBSZXN0b3JlIGtleSBmZWF0dXJlcyAtIHRvZG8gLSBmb3IgMS4xMSB0aGlzIG5lZWRzIHRvIGJlIGRvbmUgYnlcblx0XHRcdC8vIHN1YnNjcmliZWQgZXZlbnRzXG5cdFx0XHRpZiAoIHMuc3RhcnQgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0c2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgICAgPSBzLnN0YXJ0O1xuXHRcdFx0XHRzZXR0aW5ncy5pSW5pdERpc3BsYXlTdGFydCA9IHMuc3RhcnQ7XG5cdFx0XHR9XG5cdFx0XHRpZiAoIHMubGVuZ3RoICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdHNldHRpbmdzLl9pRGlzcGxheUxlbmd0aCAgID0gcy5sZW5ndGg7XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gT3JkZXJcblx0XHRcdGlmICggcy5vcmRlciAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRzZXR0aW5ncy5hYVNvcnRpbmcgPSBbXTtcblx0XHRcdFx0JC5lYWNoKCBzLm9yZGVyLCBmdW5jdGlvbiAoIGksIGNvbCApIHtcblx0XHRcdFx0XHRzZXR0aW5ncy5hYVNvcnRpbmcucHVzaCggY29sWzBdID49IGNvbHVtbnMubGVuZ3RoID9cblx0XHRcdFx0XHRcdFsgMCwgY29sWzFdIF0gOlxuXHRcdFx0XHRcdFx0Y29sXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIFNlYXJjaFxuXHRcdFx0aWYgKCBzLnNlYXJjaCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHQkLmV4dGVuZCggc2V0dGluZ3Mub1ByZXZpb3VzU2VhcmNoLCBfZm5TZWFyY2hUb0h1bmcoIHMuc2VhcmNoICkgKTtcblx0XHRcdH1cblx0XG5cdFx0XHQvLyBDb2x1bW5zXG5cdFx0XHQvL1xuXHRcdFx0aWYgKCBzLmNvbHVtbnMgKSB7XG5cdFx0XHRcdGZvciAoIGk9MCwgaWVuPXMuY29sdW1ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0XHR2YXIgY29sID0gcy5jb2x1bW5zW2ldO1xuXHRcblx0XHRcdFx0XHQvLyBWaXNpYmlsaXR5XG5cdFx0XHRcdFx0aWYgKCBjb2wudmlzaWJsZSAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0Y29sdW1uc1tpXS5iVmlzaWJsZSA9IGNvbC52aXNpYmxlO1xuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0Ly8gU2VhcmNoXG5cdFx0XHRcdFx0aWYgKCBjb2wuc2VhcmNoICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0XHQkLmV4dGVuZCggc2V0dGluZ3MuYW9QcmVTZWFyY2hDb2xzW2ldLCBfZm5TZWFyY2hUb0h1bmcoIGNvbC5zZWFyY2ggKSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcblx0XHRcdF9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsICdhb1N0YXRlTG9hZGVkJywgJ3N0YXRlTG9hZGVkJywgW3NldHRpbmdzLCBzXSApO1xuXHRcdFx0Y2FsbGJhY2soKTtcblx0XHR9XG5cdFxuXHRcdGlmICggISBzZXR0aW5ncy5vRmVhdHVyZXMuYlN0YXRlU2F2ZSApIHtcblx0XHRcdGNhbGxiYWNrKCk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcblx0XHR2YXIgc3RhdGUgPSBzZXR0aW5ncy5mblN0YXRlTG9hZENhbGxiYWNrLmNhbGwoIHNldHRpbmdzLm9JbnN0YW5jZSwgc2V0dGluZ3MsIGxvYWRlZCApO1xuXHRcblx0XHRpZiAoIHN0YXRlICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRsb2FkZWQoIHN0YXRlICk7XG5cdFx0fVxuXHRcdC8vIG90aGVyd2lzZSwgd2FpdCBmb3IgdGhlIGxvYWRlZCBjYWxsYmFjayB0byBiZSBleGVjdXRlZFxuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFJldHVybiB0aGUgc2V0dGluZ3Mgb2JqZWN0IGZvciBhIHBhcnRpY3VsYXIgdGFibGVcblx0ICogIEBwYXJhbSB7bm9kZX0gdGFibGUgdGFibGUgd2UgYXJlIHVzaW5nIGFzIGEgZGF0YVRhYmxlXG5cdCAqICBAcmV0dXJucyB7b2JqZWN0fSBTZXR0aW5ncyBvYmplY3QgLSBvciBudWxsIGlmIG5vdCBmb3VuZFxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5TZXR0aW5nc0Zyb21Ob2RlICggdGFibGUgKVxuXHR7XG5cdFx0dmFyIHNldHRpbmdzID0gRGF0YVRhYmxlLnNldHRpbmdzO1xuXHRcdHZhciBpZHggPSAkLmluQXJyYXkoIHRhYmxlLCBfcGx1Y2soIHNldHRpbmdzLCAnblRhYmxlJyApICk7XG5cdFxuXHRcdHJldHVybiBpZHggIT09IC0xID9cblx0XHRcdHNldHRpbmdzWyBpZHggXSA6XG5cdFx0XHRudWxsO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIExvZyBhbiBlcnJvciBtZXNzYWdlXG5cdCAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgZGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7aW50fSBsZXZlbCBsb2cgZXJyb3IgbWVzc2FnZXMsIG9yIGRpc3BsYXkgdGhlbSB0byB0aGUgdXNlclxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IG1zZyBlcnJvciBtZXNzYWdlXG5cdCAqICBAcGFyYW0ge2ludH0gdG4gVGVjaG5pY2FsIG5vdGUgaWQgdG8gZ2V0IG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGVycm9yLlxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNvQXBpXG5cdCAqL1xuXHRmdW5jdGlvbiBfZm5Mb2coIHNldHRpbmdzLCBsZXZlbCwgbXNnLCB0biApXG5cdHtcblx0XHRtc2cgPSAnRGF0YVRhYmxlcyB3YXJuaW5nOiAnK1xuXHRcdFx0KHNldHRpbmdzID8gJ3RhYmxlIGlkPScrc2V0dGluZ3Muc1RhYmxlSWQrJyAtICcgOiAnJykrbXNnO1xuXHRcblx0XHRpZiAoIHRuICkge1xuXHRcdFx0bXNnICs9ICcuIEZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IHRoaXMgZXJyb3IsIHBsZWFzZSBzZWUgJytcblx0XHRcdCdodHRwOi8vZGF0YXRhYmxlcy5uZXQvdG4vJyt0bjtcblx0XHR9XG5cdFxuXHRcdGlmICggISBsZXZlbCAgKSB7XG5cdFx0XHQvLyBCYWNrd2FyZHMgY29tcGF0aWJpbGl0eSBwcmUgMS4xMFxuXHRcdFx0dmFyIGV4dCA9IERhdGFUYWJsZS5leHQ7XG5cdFx0XHR2YXIgdHlwZSA9IGV4dC5zRXJyTW9kZSB8fCBleHQuZXJyTW9kZTtcblx0XG5cdFx0XHRpZiAoIHNldHRpbmdzICkge1xuXHRcdFx0XHRfZm5DYWxsYmFja0ZpcmUoIHNldHRpbmdzLCBudWxsLCAnZXJyb3InLCBbIHNldHRpbmdzLCB0biwgbXNnIF0gKTtcblx0XHRcdH1cblx0XG5cdFx0XHRpZiAoIHR5cGUgPT0gJ2FsZXJ0JyApIHtcblx0XHRcdFx0YWxlcnQoIG1zZyApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoIHR5cGUgPT0gJ3Rocm93JyApIHtcblx0XHRcdFx0dGhyb3cgbmV3IEVycm9yKG1zZyk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggdHlwZW9mIHR5cGUgPT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdFx0dHlwZSggc2V0dGluZ3MsIHRuLCBtc2cgKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZSBpZiAoIHdpbmRvdy5jb25zb2xlICYmIGNvbnNvbGUubG9nICkge1xuXHRcdFx0Y29uc29sZS5sb2coIG1zZyApO1xuXHRcdH1cblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBTZWUgaWYgYSBwcm9wZXJ0eSBpcyBkZWZpbmVkIG9uIG9uZSBvYmplY3QsIGlmIHNvIGFzc2lnbiBpdCB0byB0aGUgb3RoZXIgb2JqZWN0XG5cdCAqICBAcGFyYW0ge29iamVjdH0gcmV0IHRhcmdldCBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzcmMgc291cmNlIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IG5hbWUgcHJvcGVydHlcblx0ICogIEBwYXJhbSB7c3RyaW5nfSBbbWFwcGVkTmFtZV0gbmFtZSB0byBtYXAgdG9vIC0gb3B0aW9uYWwsIG5hbWUgdXNlZCBpZiBub3QgZ2l2ZW5cblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuTWFwKCByZXQsIHNyYywgbmFtZSwgbWFwcGVkTmFtZSApXG5cdHtcblx0XHRpZiAoICQuaXNBcnJheSggbmFtZSApICkge1xuXHRcdFx0JC5lYWNoKCBuYW1lLCBmdW5jdGlvbiAoaSwgdmFsKSB7XG5cdFx0XHRcdGlmICggJC5pc0FycmF5KCB2YWwgKSApIHtcblx0XHRcdFx0XHRfZm5NYXAoIHJldCwgc3JjLCB2YWxbMF0sIHZhbFsxXSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdF9mbk1hcCggcmV0LCBzcmMsIHZhbCApO1xuXHRcdFx0XHR9XG5cdFx0XHR9ICk7XG5cdFxuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblx0XG5cdFx0aWYgKCBtYXBwZWROYW1lID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRtYXBwZWROYW1lID0gbmFtZTtcblx0XHR9XG5cdFxuXHRcdGlmICggc3JjW25hbWVdICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRyZXRbbWFwcGVkTmFtZV0gPSBzcmNbbmFtZV07XG5cdFx0fVxuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEV4dGVuZCBvYmplY3RzIC0gdmVyeSBzaW1pbGFyIHRvIGpRdWVyeS5leHRlbmQsIGJ1dCBkZWVwIGNvcHkgb2JqZWN0cywgYW5kXG5cdCAqIHNoYWxsb3cgY29weSBhcnJheXMuIFRoZSByZWFzb24gd2UgbmVlZCB0byBkbyB0aGlzLCBpcyB0aGF0IHdlIGRvbid0IHdhbnQgdG9cblx0ICogZGVlcCBjb3B5IGFycmF5IGluaXQgdmFsdWVzIChzdWNoIGFzIGFhU29ydGluZykgc2luY2UgdGhlIGRldiB3b3VsZG4ndCBiZVxuXHQgKiBhYmxlIHRvIG92ZXJyaWRlIHRoZW0sIGJ1dCB3ZSBkbyB3YW50IHRvIGRlZXAgY29weSBhcnJheXMuXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb3V0IE9iamVjdCB0byBleHRlbmRcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBleHRlbmRlciBPYmplY3QgZnJvbSB3aGljaCB0aGUgcHJvcGVydGllcyB3aWxsIGJlIGFwcGxpZWQgdG9cblx0ICogICAgICBvdXRcblx0ICogIEBwYXJhbSB7Ym9vbGVhbn0gYnJlYWtSZWZzIElmIHRydWUsIHRoZW4gYXJyYXlzIHdpbGwgYmUgc2xpY2VkIHRvIHRha2UgYW5cblx0ICogICAgICBpbmRlcGVuZGVudCBjb3B5IHdpdGggdGhlIGV4Y2VwdGlvbiBvZiB0aGUgYGRhdGFgIG9yIGBhYURhdGFgIHBhcmFtZXRlcnNcblx0ICogICAgICBpZiB0aGV5IGFyZSBwcmVzZW50LiBUaGlzIGlzIHNvIHlvdSBjYW4gcGFzcyBpbiBhIGNvbGxlY3Rpb24gdG9cblx0ICogICAgICBEYXRhVGFibGVzIGFuZCBoYXZlIHRoYXQgdXNlZCBhcyB5b3VyIGRhdGEgc291cmNlIHdpdGhvdXQgYnJlYWtpbmcgdGhlXG5cdCAqICAgICAgcmVmZXJlbmNlc1xuXHQgKiAgQHJldHVybnMge29iamVjdH0gb3V0IFJlZmVyZW5jZSwganVzdCBmb3IgY29udmVuaWVuY2UgLSBvdXQgPT09IHRoZSByZXR1cm4uXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICogIEB0b2RvIFRoaXMgZG9lc24ndCB0YWtlIGFjY291bnQgb2YgYXJyYXlzIGluc2lkZSB0aGUgZGVlcCBjb3BpZWQgb2JqZWN0cy5cblx0ICovXG5cdGZ1bmN0aW9uIF9mbkV4dGVuZCggb3V0LCBleHRlbmRlciwgYnJlYWtSZWZzIClcblx0e1xuXHRcdHZhciB2YWw7XG5cdFxuXHRcdGZvciAoIHZhciBwcm9wIGluIGV4dGVuZGVyICkge1xuXHRcdFx0aWYgKCBleHRlbmRlci5oYXNPd25Qcm9wZXJ0eShwcm9wKSApIHtcblx0XHRcdFx0dmFsID0gZXh0ZW5kZXJbcHJvcF07XG5cdFxuXHRcdFx0XHRpZiAoICQuaXNQbGFpbk9iamVjdCggdmFsICkgKSB7XG5cdFx0XHRcdFx0aWYgKCAhICQuaXNQbGFpbk9iamVjdCggb3V0W3Byb3BdICkgKSB7XG5cdFx0XHRcdFx0XHRvdXRbcHJvcF0gPSB7fTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0JC5leHRlbmQoIHRydWUsIG91dFtwcm9wXSwgdmFsICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSBpZiAoIGJyZWFrUmVmcyAmJiBwcm9wICE9PSAnZGF0YScgJiYgcHJvcCAhPT0gJ2FhRGF0YScgJiYgJC5pc0FycmF5KHZhbCkgKSB7XG5cdFx0XHRcdFx0b3V0W3Byb3BdID0gdmFsLnNsaWNlKCk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0b3V0W3Byb3BdID0gdmFsO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gb3V0O1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEJpbmQgYW4gZXZlbnQgaGFuZGVycyB0byBhbGxvdyBhIGNsaWNrIG9yIHJldHVybiBrZXkgdG8gYWN0aXZhdGUgdGhlIGNhbGxiYWNrLlxuXHQgKiBUaGlzIGlzIGdvb2QgZm9yIGFjY2Vzc2liaWxpdHkgc2luY2UgYSByZXR1cm4gb24gdGhlIGtleWJvYXJkIHdpbGwgaGF2ZSB0aGVcblx0ICogc2FtZSBlZmZlY3QgYXMgYSBjbGljaywgaWYgdGhlIGVsZW1lbnQgaGFzIGZvY3VzLlxuXHQgKiAgQHBhcmFtIHtlbGVtZW50fSBuIEVsZW1lbnQgdG8gYmluZCB0aGUgYWN0aW9uIHRvXG5cdCAqICBAcGFyYW0ge29iamVjdH0gb0RhdGEgRGF0YSBvYmplY3QgdG8gcGFzcyB0byB0aGUgdHJpZ2dlcmVkIGZ1bmN0aW9uXG5cdCAqICBAcGFyYW0ge2Z1bmN0aW9ufSBmbiBDYWxsYmFjayBmdW5jdGlvbiBmb3Igd2hlbiB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkXG5cdCAqICBAbWVtYmVyb2YgRGF0YVRhYmxlI29BcGlcblx0ICovXG5cdGZ1bmN0aW9uIF9mbkJpbmRBY3Rpb24oIG4sIG9EYXRhLCBmbiApXG5cdHtcblx0XHQkKG4pXG5cdFx0XHQub24oICdjbGljay5EVCcsIG9EYXRhLCBmdW5jdGlvbiAoZSkge1xuXHRcdFx0XHRcdG4uYmx1cigpOyAvLyBSZW1vdmUgZm9jdXMgb3V0bGluZSBmb3IgbW91c2UgdXNlcnNcblx0XHRcdFx0XHRmbihlKTtcblx0XHRcdFx0fSApXG5cdFx0XHQub24oICdrZXlwcmVzcy5EVCcsIG9EYXRhLCBmdW5jdGlvbiAoZSl7XG5cdFx0XHRcdFx0aWYgKCBlLndoaWNoID09PSAxMyApIHtcblx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdGZuKGUpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSApXG5cdFx0XHQub24oICdzZWxlY3RzdGFydC5EVCcsIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHQvKiBUYWtlIHRoZSBicnV0YWwgYXBwcm9hY2ggdG8gY2FuY2VsbGluZyB0ZXh0IHNlbGVjdGlvbiAqL1xuXHRcdFx0XHRcdHJldHVybiBmYWxzZTtcblx0XHRcdFx0fSApO1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24uIEVhc2lseSBhbGxvd3MgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBhZGRlZCB0b1xuXHQgKiBhbiBhcnJheSBzdG9yZSBvZiBjYWxsYmFjayBmdW5jdGlvbnMgdGhhdCBjYW4gdGhlbiBhbGwgYmUgY2FsbGVkIHRvZ2V0aGVyLlxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IHNTdG9yZSBOYW1lIG9mIHRoZSBhcnJheSBzdG9yYWdlIGZvciB0aGUgY2FsbGJhY2tzIGluIG9TZXR0aW5nc1xuXHQgKiAgQHBhcmFtIHtmdW5jdGlvbn0gZm4gRnVuY3Rpb24gdG8gYmUgY2FsbGVkIGJhY2tcblx0ICogIEBwYXJhbSB7c3RyaW5nfSBzTmFtZSBJZGVudGlmeWluZyBuYW1lIGZvciB0aGUgY2FsbGJhY2sgKGkuZS4gYSBsYWJlbClcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQ2FsbGJhY2tSZWcoIG9TZXR0aW5ncywgc1N0b3JlLCBmbiwgc05hbWUgKVxuXHR7XG5cdFx0aWYgKCBmbiApXG5cdFx0e1xuXHRcdFx0b1NldHRpbmdzW3NTdG9yZV0ucHVzaCgge1xuXHRcdFx0XHRcImZuXCI6IGZuLFxuXHRcdFx0XHRcInNOYW1lXCI6IHNOYW1lXG5cdFx0XHR9ICk7XG5cdFx0fVxuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIEZpcmUgY2FsbGJhY2sgZnVuY3Rpb25zIGFuZCB0cmlnZ2VyIGV2ZW50cy4gTm90ZSB0aGF0IHRoZSBsb29wIG92ZXIgdGhlXG5cdCAqIGNhbGxiYWNrIGFycmF5IHN0b3JlIGlzIGRvbmUgYmFja3dhcmRzISBGdXJ0aGVyIG5vdGUgdGhhdCB5b3UgZG8gbm90IHdhbnQgdG9cblx0ICogZmlyZSBvZmYgdHJpZ2dlcnMgaW4gdGltZSBzZW5zaXRpdmUgYXBwbGljYXRpb25zIChmb3IgZXhhbXBsZSBjZWxsIGNyZWF0aW9uKVxuXHQgKiBhcyBpdHMgc2xvdy5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtzdHJpbmd9IGNhbGxiYWNrQXJyIE5hbWUgb2YgdGhlIGFycmF5IHN0b3JhZ2UgZm9yIHRoZSBjYWxsYmFja3MgaW5cblx0ICogICAgICBvU2V0dGluZ3Ncblx0ICogIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWUgTmFtZSBvZiB0aGUgalF1ZXJ5IGN1c3RvbSBldmVudCB0byB0cmlnZ2VyLiBJZlxuXHQgKiAgICAgIG51bGwgbm8gdHJpZ2dlciBpcyBmaXJlZFxuXHQgKiAgQHBhcmFtIHthcnJheX0gYXJncyBBcnJheSBvZiBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgY2FsbGJhY2sgZnVuY3Rpb24gL1xuXHQgKiAgICAgIHRyaWdnZXJcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuQ2FsbGJhY2tGaXJlKCBzZXR0aW5ncywgY2FsbGJhY2tBcnIsIGV2ZW50TmFtZSwgYXJncyApXG5cdHtcblx0XHR2YXIgcmV0ID0gW107XG5cdFxuXHRcdGlmICggY2FsbGJhY2tBcnIgKSB7XG5cdFx0XHRyZXQgPSAkLm1hcCggc2V0dGluZ3NbY2FsbGJhY2tBcnJdLnNsaWNlKCkucmV2ZXJzZSgpLCBmdW5jdGlvbiAodmFsLCBpKSB7XG5cdFx0XHRcdHJldHVybiB2YWwuZm4uYXBwbHkoIHNldHRpbmdzLm9JbnN0YW5jZSwgYXJncyApO1xuXHRcdFx0fSApO1xuXHRcdH1cblx0XG5cdFx0aWYgKCBldmVudE5hbWUgIT09IG51bGwgKSB7XG5cdFx0XHR2YXIgZSA9ICQuRXZlbnQoIGV2ZW50TmFtZSsnLmR0JyApO1xuXHRcblx0XHRcdCQoc2V0dGluZ3MublRhYmxlKS50cmlnZ2VyKCBlLCBhcmdzICk7XG5cdFxuXHRcdFx0cmV0LnB1c2goIGUucmVzdWx0ICk7XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gcmV0O1xuXHR9XG5cdFxuXHRcblx0ZnVuY3Rpb24gX2ZuTGVuZ3RoT3ZlcmZsb3cgKCBzZXR0aW5ncyApXG5cdHtcblx0XHR2YXJcblx0XHRcdHN0YXJ0ID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsXG5cdFx0XHRlbmQgPSBzZXR0aW5ncy5mbkRpc3BsYXlFbmQoKSxcblx0XHRcdGxlbiA9IHNldHRpbmdzLl9pRGlzcGxheUxlbmd0aDtcblx0XG5cdFx0LyogSWYgd2UgaGF2ZSBzcGFjZSB0byBzaG93IGV4dHJhIHJvd3MgKGJhY2tpbmcgdXAgZnJvbSB0aGUgZW5kIHBvaW50IC0gdGhlbiBkbyBzbyAqL1xuXHRcdGlmICggc3RhcnQgPj0gZW5kIClcblx0XHR7XG5cdFx0XHRzdGFydCA9IGVuZCAtIGxlbjtcblx0XHR9XG5cdFxuXHRcdC8vIEtlZXAgdGhlIHN0YXJ0IHJlY29yZCBvbiB0aGUgY3VycmVudCBwYWdlXG5cdFx0c3RhcnQgLT0gKHN0YXJ0ICUgbGVuKTtcblx0XG5cdFx0aWYgKCBsZW4gPT09IC0xIHx8IHN0YXJ0IDwgMCApXG5cdFx0e1xuXHRcdFx0c3RhcnQgPSAwO1xuXHRcdH1cblx0XG5cdFx0c2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQgPSBzdGFydDtcblx0fVxuXHRcblx0XG5cdGZ1bmN0aW9uIF9mblJlbmRlcmVyKCBzZXR0aW5ncywgdHlwZSApXG5cdHtcblx0XHR2YXIgcmVuZGVyZXIgPSBzZXR0aW5ncy5yZW5kZXJlcjtcblx0XHR2YXIgaG9zdCA9IERhdGFUYWJsZS5leHQucmVuZGVyZXJbdHlwZV07XG5cdFxuXHRcdGlmICggJC5pc1BsYWluT2JqZWN0KCByZW5kZXJlciApICYmIHJlbmRlcmVyW3R5cGVdICkge1xuXHRcdFx0Ly8gU3BlY2lmaWMgcmVuZGVyZXIgZm9yIHRoaXMgdHlwZS4gSWYgYXZhaWxhYmxlIHVzZSBpdCwgb3RoZXJ3aXNlIHVzZVxuXHRcdFx0Ly8gdGhlIGRlZmF1bHQuXG5cdFx0XHRyZXR1cm4gaG9zdFtyZW5kZXJlclt0eXBlXV0gfHwgaG9zdC5fO1xuXHRcdH1cblx0XHRlbHNlIGlmICggdHlwZW9mIHJlbmRlcmVyID09PSAnc3RyaW5nJyApIHtcblx0XHRcdC8vIENvbW1vbiByZW5kZXJlciAtIGlmIHRoZXJlIGlzIG9uZSBhdmFpbGFibGUgZm9yIHRoaXMgdHlwZSB1c2UgaXQsXG5cdFx0XHQvLyBvdGhlcndpc2UgdXNlIHRoZSBkZWZhdWx0XG5cdFx0XHRyZXR1cm4gaG9zdFtyZW5kZXJlcl0gfHwgaG9zdC5fO1xuXHRcdH1cblx0XG5cdFx0Ly8gVXNlIHRoZSBkZWZhdWx0XG5cdFx0cmV0dXJuIGhvc3QuXztcblx0fVxuXHRcblx0XG5cdC8qKlxuXHQgKiBEZXRlY3QgdGhlIGRhdGEgc291cmNlIGJlaW5nIHVzZWQgZm9yIHRoZSB0YWJsZS4gVXNlZCB0byBzaW1wbGlmeSB0aGUgY29kZVxuXHQgKiBhIGxpdHRsZSAoYWpheCkgYW5kIHRvIG1ha2UgaXQgY29tcHJlc3MgYSBsaXR0bGUgc21hbGxlci5cblx0ICpcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBkYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHJldHVybnMge3N0cmluZ30gRGF0YSBzb3VyY2Vcblx0ICogIEBtZW1iZXJvZiBEYXRhVGFibGUjb0FwaVxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuRGF0YVNvdXJjZSAoIHNldHRpbmdzIClcblx0e1xuXHRcdGlmICggc2V0dGluZ3Mub0ZlYXR1cmVzLmJTZXJ2ZXJTaWRlICkge1xuXHRcdFx0cmV0dXJuICdzc3AnO1xuXHRcdH1cblx0XHRlbHNlIGlmICggc2V0dGluZ3MuYWpheCB8fCBzZXR0aW5ncy5zQWpheFNvdXJjZSApIHtcblx0XHRcdHJldHVybiAnYWpheCc7XG5cdFx0fVxuXHRcdHJldHVybiAnZG9tJztcblx0fVxuXHRcblxuXHRcblx0XG5cdC8qKlxuXHQgKiBDb21wdXRlZCBzdHJ1Y3R1cmUgb2YgdGhlIERhdGFUYWJsZXMgQVBJLCBkZWZpbmVkIGJ5IHRoZSBvcHRpb25zIHBhc3NlZCB0b1xuXHQgKiBgRGF0YVRhYmxlLkFwaS5yZWdpc3RlcigpYCB3aGVuIGJ1aWxkaW5nIHRoZSBBUEkuXG5cdCAqXG5cdCAqIFRoZSBzdHJ1Y3R1cmUgaXMgYnVpbHQgaW4gb3JkZXIgdG8gc3BlZWQgY3JlYXRpb24gYW5kIGV4dGVuc2lvbiBvZiB0aGUgQXBpXG5cdCAqIG9iamVjdHMgc2luY2UgdGhlIGV4dGVuc2lvbnMgYXJlIGVmZmVjdGl2ZWx5IHByZS1wYXJzZWQuXG5cdCAqXG5cdCAqIFRoZSBhcnJheSBpcyBhbiBhcnJheSBvZiBvYmplY3RzIHdpdGggdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmUsIHdoZXJlIHRoaXNcblx0ICogYmFzZSBhcnJheSByZXByZXNlbnRzIHRoZSBBcGkgcHJvdG90eXBlIGJhc2U6XG5cdCAqXG5cdCAqICAgICBbXG5cdCAqICAgICAgIHtcblx0ICogICAgICAgICBuYW1lOiAgICAgICdkYXRhJyAgICAgICAgICAgICAgICAtLSBzdHJpbmcgICAtIFByb3BlcnR5IG5hbWVcblx0ICogICAgICAgICB2YWw6ICAgICAgIGZ1bmN0aW9uICgpIHt9LCAgICAgICAtLSBmdW5jdGlvbiAtIEFwaSBtZXRob2QgKG9yIHVuZGVmaW5lZCBpZiBqdXN0IGFuIG9iamVjdFxuXHQgKiAgICAgICAgIG1ldGhvZEV4dDogWyAuLi4gXSwgICAgICAgICAgICAgIC0tIGFycmF5ICAgIC0gQXJyYXkgb2YgQXBpIG9iamVjdCBkZWZpbml0aW9ucyB0byBleHRlbmQgdGhlIG1ldGhvZCByZXN1bHRcblx0ICogICAgICAgICBwcm9wRXh0OiAgIFsgLi4uIF0gICAgICAgICAgICAgICAtLSBhcnJheSAgICAtIEFycmF5IG9mIEFwaSBvYmplY3QgZGVmaW5pdGlvbnMgdG8gZXh0ZW5kIHRoZSBwcm9wZXJ0eVxuXHQgKiAgICAgICB9LFxuXHQgKiAgICAgICB7XG5cdCAqICAgICAgICAgbmFtZTogICAgICdyb3cnXG5cdCAqICAgICAgICAgdmFsOiAgICAgICB7fSxcblx0ICogICAgICAgICBtZXRob2RFeHQ6IFsgLi4uIF0sXG5cdCAqICAgICAgICAgcHJvcEV4dDogICBbXG5cdCAqICAgICAgICAgICB7XG5cdCAqICAgICAgICAgICAgIG5hbWU6ICAgICAgJ2RhdGEnXG5cdCAqICAgICAgICAgICAgIHZhbDogICAgICAgZnVuY3Rpb24gKCkge30sXG5cdCAqICAgICAgICAgICAgIG1ldGhvZEV4dDogWyAuLi4gXSxcblx0ICogICAgICAgICAgICAgcHJvcEV4dDogICBbIC4uLiBdXG5cdCAqICAgICAgICAgICB9LFxuXHQgKiAgICAgICAgICAgLi4uXG5cdCAqICAgICAgICAgXVxuXHQgKiAgICAgICB9XG5cdCAqICAgICBdXG5cdCAqXG5cdCAqIEB0eXBlIHtBcnJheX1cblx0ICogQGlnbm9yZVxuXHQgKi9cblx0dmFyIF9fYXBpU3RydWN0ID0gW107XG5cdFxuXHRcblx0LyoqXG5cdCAqIGBBcnJheS5wcm90b3R5cGVgIHJlZmVyZW5jZS5cblx0ICpcblx0ICogQHR5cGUgb2JqZWN0XG5cdCAqIEBpZ25vcmVcblx0ICovXG5cdHZhciBfX2FycmF5UHJvdG8gPSBBcnJheS5wcm90b3R5cGU7XG5cdFxuXHRcblx0LyoqXG5cdCAqIEFic3RyYWN0aW9uIGZvciBgY29udGV4dGAgcGFyYW1ldGVyIG9mIHRoZSBgQXBpYCBjb25zdHJ1Y3RvciB0byBhbGxvdyBpdCB0b1xuXHQgKiB0YWtlIHNldmVyYWwgZGlmZmVyZW50IGZvcm1zIGZvciBlYXNlIG9mIHVzZS5cblx0ICpcblx0ICogRWFjaCBvZiB0aGUgaW5wdXQgcGFyYW1ldGVyIHR5cGVzIHdpbGwgYmUgY29udmVydGVkIHRvIGEgRGF0YVRhYmxlcyBzZXR0aW5nc1xuXHQgKiBvYmplY3Qgd2hlcmUgcG9zc2libGUuXG5cdCAqXG5cdCAqIEBwYXJhbSAge3N0cmluZ3xub2RlfGpRdWVyeXxvYmplY3R9IG1peGVkIERhdGFUYWJsZSBpZGVudGlmaWVyLiBDYW4gYmUgb25lXG5cdCAqICAgb2Y6XG5cdCAqXG5cdCAqICAgKiBgc3RyaW5nYCAtIGpRdWVyeSBzZWxlY3Rvci4gQW55IERhdGFUYWJsZXMnIG1hdGNoaW5nIHRoZSBnaXZlbiBzZWxlY3RvclxuXHQgKiAgICAgd2l0aCBiZSBmb3VuZCBhbmQgdXNlZC5cblx0ICogICAqIGBub2RlYCAtIGBUQUJMRWAgbm9kZSB3aGljaCBoYXMgYWxyZWFkeSBiZWVuIGZvcm1lZCBpbnRvIGEgRGF0YVRhYmxlLlxuXHQgKiAgICogYGpRdWVyeWAgLSBBIGpRdWVyeSBvYmplY3Qgb2YgYFRBQkxFYCBub2Rlcy5cblx0ICogICAqIGBvYmplY3RgIC0gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogICAqIGBEYXRhVGFibGVzLkFwaWAgLSBBUEkgaW5zdGFuY2Vcblx0ICogQHJldHVybiB7YXJyYXl8bnVsbH0gTWF0Y2hpbmcgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3RzLiBgbnVsbGAgb3Jcblx0ICogICBgdW5kZWZpbmVkYCBpcyByZXR1cm5lZCBpZiBubyBtYXRjaGluZyBEYXRhVGFibGUgaXMgZm91bmQuXG5cdCAqIEBpZ25vcmVcblx0ICovXG5cdHZhciBfdG9TZXR0aW5ncyA9IGZ1bmN0aW9uICggbWl4ZWQgKVxuXHR7XG5cdFx0dmFyIGlkeCwganE7XG5cdFx0dmFyIHNldHRpbmdzID0gRGF0YVRhYmxlLnNldHRpbmdzO1xuXHRcdHZhciB0YWJsZXMgPSAkLm1hcCggc2V0dGluZ3MsIGZ1bmN0aW9uIChlbCwgaSkge1xuXHRcdFx0cmV0dXJuIGVsLm5UYWJsZTtcblx0XHR9ICk7XG5cdFxuXHRcdGlmICggISBtaXhlZCApIHtcblx0XHRcdHJldHVybiBbXTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIG1peGVkLm5UYWJsZSAmJiBtaXhlZC5vQXBpICkge1xuXHRcdFx0Ly8gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0XHRcdHJldHVybiBbIG1peGVkIF07XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCBtaXhlZC5ub2RlTmFtZSAmJiBtaXhlZC5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSAndGFibGUnICkge1xuXHRcdFx0Ly8gVGFibGUgbm9kZVxuXHRcdFx0aWR4ID0gJC5pbkFycmF5KCBtaXhlZCwgdGFibGVzICk7XG5cdFx0XHRyZXR1cm4gaWR4ICE9PSAtMSA/IFsgc2V0dGluZ3NbaWR4XSBdIDogbnVsbDtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIG1peGVkICYmIHR5cGVvZiBtaXhlZC5zZXR0aW5ncyA9PT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdHJldHVybiBtaXhlZC5zZXR0aW5ncygpLnRvQXJyYXkoKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIHR5cGVvZiBtaXhlZCA9PT0gJ3N0cmluZycgKSB7XG5cdFx0XHQvLyBqUXVlcnkgc2VsZWN0b3Jcblx0XHRcdGpxID0gJChtaXhlZCk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCBtaXhlZCBpbnN0YW5jZW9mICQgKSB7XG5cdFx0XHQvLyBqUXVlcnkgb2JqZWN0IChhbHNvIERhdGFUYWJsZXMgaW5zdGFuY2UpXG5cdFx0XHRqcSA9IG1peGVkO1xuXHRcdH1cblx0XG5cdFx0aWYgKCBqcSApIHtcblx0XHRcdHJldHVybiBqcS5tYXAoIGZ1bmN0aW9uKGkpIHtcblx0XHRcdFx0aWR4ID0gJC5pbkFycmF5KCB0aGlzLCB0YWJsZXMgKTtcblx0XHRcdFx0cmV0dXJuIGlkeCAhPT0gLTEgPyBzZXR0aW5nc1tpZHhdIDogbnVsbDtcblx0XHRcdH0gKS50b0FycmF5KCk7XG5cdFx0fVxuXHR9O1xuXHRcblx0XG5cdC8qKlxuXHQgKiBEYXRhVGFibGVzIEFQSSBjbGFzcyAtIHVzZWQgdG8gY29udHJvbCBhbmQgaW50ZXJmYWNlIHdpdGggIG9uZSBvciBtb3JlXG5cdCAqIERhdGFUYWJsZXMgZW5oYW5jZWQgdGFibGVzLlxuXHQgKlxuXHQgKiBUaGUgQVBJIGNsYXNzIGlzIGhlYXZpbHkgYmFzZWQgb24galF1ZXJ5LCBwcmVzZW50aW5nIGEgY2hhaW5hYmxlIGludGVyZmFjZVxuXHQgKiB0aGF0IHlvdSBjYW4gdXNlIHRvIGludGVyYWN0IHdpdGggdGFibGVzLiBFYWNoIGluc3RhbmNlIG9mIHRoZSBBUEkgY2xhc3MgaGFzXG5cdCAqIGEgXCJjb250ZXh0XCIgLSBpLmUuIHRoZSB0YWJsZXMgdGhhdCBpdCB3aWxsIG9wZXJhdGUgb24uIFRoaXMgY291bGQgYmUgYSBzaW5nbGVcblx0ICogdGFibGUsIGFsbCB0YWJsZXMgb24gYSBwYWdlIG9yIGEgc3ViLXNldCB0aGVyZW9mLlxuXHQgKlxuXHQgKiBBZGRpdGlvbmFsbHkgdGhlIEFQSSBpcyBkZXNpZ25lZCB0byBhbGxvdyB5b3UgdG8gZWFzaWx5IHdvcmsgd2l0aCB0aGUgZGF0YSBpblxuXHQgKiB0aGUgdGFibGVzLCByZXRyaWV2aW5nIGFuZCBtYW5pcHVsYXRpbmcgaXQgYXMgcmVxdWlyZWQuIFRoaXMgaXMgZG9uZSBieVxuXHQgKiBwcmVzZW50aW5nIHRoZSBBUEkgY2xhc3MgYXMgYW4gYXJyYXkgbGlrZSBpbnRlcmZhY2UuIFRoZSBjb250ZW50cyBvZiB0aGVcblx0ICogYXJyYXkgZGVwZW5kIHVwb24gdGhlIGFjdGlvbnMgcmVxdWVzdGVkIGJ5IGVhY2ggbWV0aG9kIChmb3IgZXhhbXBsZVxuXHQgKiBgcm93cygpLm5vZGVzKClgIHdpbGwgcmV0dXJuIGFuIGFycmF5IG9mIG5vZGVzLCB3aGlsZSBgcm93cygpLmRhdGEoKWAgd2lsbFxuXHQgKiByZXR1cm4gYW4gYXJyYXkgb2Ygb2JqZWN0cyBvciBhcnJheXMgZGVwZW5kaW5nIHVwb24geW91ciB0YWJsZSdzXG5cdCAqIGNvbmZpZ3VyYXRpb24pLiBUaGUgQVBJIG9iamVjdCBoYXMgYSBudW1iZXIgb2YgYXJyYXkgbGlrZSBtZXRob2RzIChgcHVzaGAsXG5cdCAqIGBwb3BgLCBgcmV2ZXJzZWAgZXRjKSBhcyB3ZWxsIGFzIGFkZGl0aW9uYWwgaGVscGVyIG1ldGhvZHMgKGBlYWNoYCwgYHBsdWNrYCxcblx0ICogYHVuaXF1ZWAgZXRjKSB0byBhc3Npc3QgeW91ciB3b3JraW5nIHdpdGggdGhlIGRhdGEgaGVsZCBpbiBhIHRhYmxlLlxuXHQgKlxuXHQgKiBNb3N0IG1ldGhvZHMgKHRob3NlIHdoaWNoIHJldHVybiBhbiBBcGkgaW5zdGFuY2UpIGFyZSBjaGFpbmFibGUsIHdoaWNoIG1lYW5zXG5cdCAqIHRoZSByZXR1cm4gZnJvbSBhIG1ldGhvZCBjYWxsIGFsc28gaGFzIGFsbCBvZiB0aGUgbWV0aG9kcyBhdmFpbGFibGUgdGhhdCB0aGVcblx0ICogdG9wIGxldmVsIG9iamVjdCBoYWQuIEZvciBleGFtcGxlLCB0aGVzZSB0d28gY2FsbHMgYXJlIGVxdWl2YWxlbnQ6XG5cdCAqXG5cdCAqICAgICAvLyBOb3QgY2hhaW5lZFxuXHQgKiAgICAgYXBpLnJvdy5hZGQoIHsuLi59ICk7XG5cdCAqICAgICBhcGkuZHJhdygpO1xuXHQgKlxuXHQgKiAgICAgLy8gQ2hhaW5lZFxuXHQgKiAgICAgYXBpLnJvdy5hZGQoIHsuLi59ICkuZHJhdygpO1xuXHQgKlxuXHQgKiBAY2xhc3MgRGF0YVRhYmxlLkFwaVxuXHQgKiBAcGFyYW0ge2FycmF5fG9iamVjdHxzdHJpbmd8alF1ZXJ5fSBjb250ZXh0IERhdGFUYWJsZSBpZGVudGlmaWVyLiBUaGlzIGlzXG5cdCAqICAgdXNlZCB0byBkZWZpbmUgd2hpY2ggRGF0YVRhYmxlcyBlbmhhbmNlZCB0YWJsZXMgdGhpcyBBUEkgd2lsbCBvcGVyYXRlIG9uLlxuXHQgKiAgIENhbiBiZSBvbmUgb2Y6XG5cdCAqXG5cdCAqICAgKiBgc3RyaW5nYCAtIGpRdWVyeSBzZWxlY3Rvci4gQW55IERhdGFUYWJsZXMnIG1hdGNoaW5nIHRoZSBnaXZlbiBzZWxlY3RvclxuXHQgKiAgICAgd2l0aCBiZSBmb3VuZCBhbmQgdXNlZC5cblx0ICogICAqIGBub2RlYCAtIGBUQUJMRWAgbm9kZSB3aGljaCBoYXMgYWxyZWFkeSBiZWVuIGZvcm1lZCBpbnRvIGEgRGF0YVRhYmxlLlxuXHQgKiAgICogYGpRdWVyeWAgLSBBIGpRdWVyeSBvYmplY3Qgb2YgYFRBQkxFYCBub2Rlcy5cblx0ICogICAqIGBvYmplY3RgIC0gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogQHBhcmFtIHthcnJheX0gW2RhdGFdIERhdGEgdG8gaW5pdGlhbGlzZSB0aGUgQXBpIGluc3RhbmNlIHdpdGguXG5cdCAqXG5cdCAqIEBleGFtcGxlXG5cdCAqICAgLy8gRGlyZWN0IGluaXRpYWxpc2F0aW9uIGR1cmluZyBEYXRhVGFibGVzIGNvbnN0cnVjdGlvblxuXHQgKiAgIHZhciBhcGkgPSAkKCcjZXhhbXBsZScpLkRhdGFUYWJsZSgpO1xuXHQgKlxuXHQgKiBAZXhhbXBsZVxuXHQgKiAgIC8vIEluaXRpYWxpc2F0aW9uIHVzaW5nIGEgRGF0YVRhYmxlcyBqUXVlcnkgb2JqZWN0XG5cdCAqICAgdmFyIGFwaSA9ICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCkuYXBpKCk7XG5cdCAqXG5cdCAqIEBleGFtcGxlXG5cdCAqICAgLy8gSW5pdGlhbGlzYXRpb24gYXMgYSBjb25zdHJ1Y3RvclxuXHQgKiAgIHZhciBhcGkgPSBuZXcgJC5mbi5EYXRhVGFibGUuQXBpKCAndGFibGUuZGF0YVRhYmxlJyApO1xuXHQgKi9cblx0X0FwaSA9IGZ1bmN0aW9uICggY29udGV4dCwgZGF0YSApXG5cdHtcblx0XHRpZiAoICEgKHRoaXMgaW5zdGFuY2VvZiBfQXBpKSApIHtcblx0XHRcdHJldHVybiBuZXcgX0FwaSggY29udGV4dCwgZGF0YSApO1xuXHRcdH1cblx0XG5cdFx0dmFyIHNldHRpbmdzID0gW107XG5cdFx0dmFyIGN0eFNldHRpbmdzID0gZnVuY3Rpb24gKCBvICkge1xuXHRcdFx0dmFyIGEgPSBfdG9TZXR0aW5ncyggbyApO1xuXHRcdFx0aWYgKCBhICkge1xuXHRcdFx0XHRzZXR0aW5ncyA9IHNldHRpbmdzLmNvbmNhdCggYSApO1xuXHRcdFx0fVxuXHRcdH07XG5cdFxuXHRcdGlmICggJC5pc0FycmF5KCBjb250ZXh0ICkgKSB7XG5cdFx0XHRmb3IgKCB2YXIgaT0wLCBpZW49Y29udGV4dC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0Y3R4U2V0dGluZ3MoIGNvbnRleHRbaV0gKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRjdHhTZXR0aW5ncyggY29udGV4dCApO1xuXHRcdH1cblx0XG5cdFx0Ly8gUmVtb3ZlIGR1cGxpY2F0ZXNcblx0XHR0aGlzLmNvbnRleHQgPSBfdW5pcXVlKCBzZXR0aW5ncyApO1xuXHRcblx0XHQvLyBJbml0aWFsIGRhdGFcblx0XHRpZiAoIGRhdGEgKSB7XG5cdFx0XHQkLm1lcmdlKCB0aGlzLCBkYXRhICk7XG5cdFx0fVxuXHRcblx0XHQvLyBzZWxlY3RvclxuXHRcdHRoaXMuc2VsZWN0b3IgPSB7XG5cdFx0XHRyb3dzOiBudWxsLFxuXHRcdFx0Y29sczogbnVsbCxcblx0XHRcdG9wdHM6IG51bGxcblx0XHR9O1xuXHRcblx0XHRfQXBpLmV4dGVuZCggdGhpcywgdGhpcywgX19hcGlTdHJ1Y3QgKTtcblx0fTtcblx0XG5cdERhdGFUYWJsZS5BcGkgPSBfQXBpO1xuXHRcblx0Ly8gRG9uJ3QgZGVzdHJveSB0aGUgZXhpc3RpbmcgcHJvdG90eXBlLCBqdXN0IGV4dGVuZCBpdC4gUmVxdWlyZWQgZm9yIGpRdWVyeSAyJ3Ncblx0Ly8gaXNQbGFpbk9iamVjdC5cblx0JC5leHRlbmQoIF9BcGkucHJvdG90eXBlLCB7XG5cdFx0YW55OiBmdW5jdGlvbiAoKVxuXHRcdHtcblx0XHRcdHJldHVybiB0aGlzLmNvdW50KCkgIT09IDA7XG5cdFx0fSxcblx0XG5cdFxuXHRcdGNvbmNhdDogIF9fYXJyYXlQcm90by5jb25jYXQsXG5cdFxuXHRcblx0XHRjb250ZXh0OiBbXSwgLy8gYXJyYXkgb2YgdGFibGUgc2V0dGluZ3Mgb2JqZWN0c1xuXHRcblx0XG5cdFx0Y291bnQ6IGZ1bmN0aW9uICgpXG5cdFx0e1xuXHRcdFx0cmV0dXJuIHRoaXMuZmxhdHRlbigpLmxlbmd0aDtcblx0XHR9LFxuXHRcblx0XG5cdFx0ZWFjaDogZnVuY3Rpb24gKCBmbiApXG5cdFx0e1xuXHRcdFx0Zm9yICggdmFyIGk9MCwgaWVuPXRoaXMubGVuZ3RoIDsgaTxpZW47IGkrKyApIHtcblx0XHRcdFx0Zm4uY2FsbCggdGhpcywgdGhpc1tpXSwgaSwgdGhpcyApO1xuXHRcdFx0fVxuXHRcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH0sXG5cdFxuXHRcblx0XHRlcTogZnVuY3Rpb24gKCBpZHggKVxuXHRcdHtcblx0XHRcdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cdFxuXHRcdFx0cmV0dXJuIGN0eC5sZW5ndGggPiBpZHggP1xuXHRcdFx0XHRuZXcgX0FwaSggY3R4W2lkeF0sIHRoaXNbaWR4XSApIDpcblx0XHRcdFx0bnVsbDtcblx0XHR9LFxuXHRcblx0XG5cdFx0ZmlsdGVyOiBmdW5jdGlvbiAoIGZuIClcblx0XHR7XG5cdFx0XHR2YXIgYSA9IFtdO1xuXHRcblx0XHRcdGlmICggX19hcnJheVByb3RvLmZpbHRlciApIHtcblx0XHRcdFx0YSA9IF9fYXJyYXlQcm90by5maWx0ZXIuY2FsbCggdGhpcywgZm4sIHRoaXMgKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHQvLyBDb21wYXRpYmlsaXR5IGZvciBicm93c2VycyB3aXRob3V0IEVNQ0EtMjUyLTUgKEpTIDEuNilcblx0XHRcdFx0Zm9yICggdmFyIGk9MCwgaWVuPXRoaXMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0aWYgKCBmbi5jYWxsKCB0aGlzLCB0aGlzW2ldLCBpLCB0aGlzICkgKSB7XG5cdFx0XHRcdFx0XHRhLnB1c2goIHRoaXNbaV0gKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XG5cdFx0XHRyZXR1cm4gbmV3IF9BcGkoIHRoaXMuY29udGV4dCwgYSApO1xuXHRcdH0sXG5cdFxuXHRcblx0XHRmbGF0dGVuOiBmdW5jdGlvbiAoKVxuXHRcdHtcblx0XHRcdHZhciBhID0gW107XG5cdFx0XHRyZXR1cm4gbmV3IF9BcGkoIHRoaXMuY29udGV4dCwgYS5jb25jYXQuYXBwbHkoIGEsIHRoaXMudG9BcnJheSgpICkgKTtcblx0XHR9LFxuXHRcblx0XG5cdFx0am9pbjogICAgX19hcnJheVByb3RvLmpvaW4sXG5cdFxuXHRcblx0XHRpbmRleE9mOiBfX2FycmF5UHJvdG8uaW5kZXhPZiB8fCBmdW5jdGlvbiAob2JqLCBzdGFydClcblx0XHR7XG5cdFx0XHRmb3IgKCB2YXIgaT0oc3RhcnQgfHwgMCksIGllbj10aGlzLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIHRoaXNbaV0gPT09IG9iaiApIHtcblx0XHRcdFx0XHRyZXR1cm4gaTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIC0xO1xuXHRcdH0sXG5cdFxuXHRcdGl0ZXJhdG9yOiBmdW5jdGlvbiAoIGZsYXR0ZW4sIHR5cGUsIGZuLCBhbHdheXNOZXcgKSB7XG5cdFx0XHR2YXJcblx0XHRcdFx0YSA9IFtdLCByZXQsXG5cdFx0XHRcdGksIGllbiwgaiwgamVuLFxuXHRcdFx0XHRjb250ZXh0ID0gdGhpcy5jb250ZXh0LFxuXHRcdFx0XHRyb3dzLCBpdGVtcywgaXRlbSxcblx0XHRcdFx0c2VsZWN0b3IgPSB0aGlzLnNlbGVjdG9yO1xuXHRcblx0XHRcdC8vIEFyZ3VtZW50IHNoaWZ0aW5nXG5cdFx0XHRpZiAoIHR5cGVvZiBmbGF0dGVuID09PSAnc3RyaW5nJyApIHtcblx0XHRcdFx0YWx3YXlzTmV3ID0gZm47XG5cdFx0XHRcdGZuID0gdHlwZTtcblx0XHRcdFx0dHlwZSA9IGZsYXR0ZW47XG5cdFx0XHRcdGZsYXR0ZW4gPSBmYWxzZTtcblx0XHRcdH1cblx0XG5cdFx0XHRmb3IgKCBpPTAsIGllbj1jb250ZXh0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHR2YXIgYXBpSW5zdCA9IG5ldyBfQXBpKCBjb250ZXh0W2ldICk7XG5cdFxuXHRcdFx0XHRpZiAoIHR5cGUgPT09ICd0YWJsZScgKSB7XG5cdFx0XHRcdFx0cmV0ID0gZm4uY2FsbCggYXBpSW5zdCwgY29udGV4dFtpXSwgaSApO1xuXHRcblx0XHRcdFx0XHRpZiAoIHJldCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0YS5wdXNoKCByZXQgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSBpZiAoIHR5cGUgPT09ICdjb2x1bW5zJyB8fCB0eXBlID09PSAncm93cycgKSB7XG5cdFx0XHRcdFx0Ly8gdGhpcyBoYXMgc2FtZSBsZW5ndGggYXMgY29udGV4dCAtIG9uZSBlbnRyeSBmb3IgZWFjaCB0YWJsZVxuXHRcdFx0XHRcdHJldCA9IGZuLmNhbGwoIGFwaUluc3QsIGNvbnRleHRbaV0sIHRoaXNbaV0sIGkgKTtcblx0XG5cdFx0XHRcdFx0aWYgKCByZXQgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0XHRcdGEucHVzaCggcmV0ICk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKCB0eXBlID09PSAnY29sdW1uJyB8fCB0eXBlID09PSAnY29sdW1uLXJvd3MnIHx8IHR5cGUgPT09ICdyb3cnIHx8IHR5cGUgPT09ICdjZWxsJyApIHtcblx0XHRcdFx0XHQvLyBjb2x1bW5zIGFuZCByb3dzIHNoYXJlIHRoZSBzYW1lIHN0cnVjdHVyZS5cblx0XHRcdFx0XHQvLyAndGhpcycgaXMgYW4gYXJyYXkgb2YgY29sdW1uIGluZGV4ZXMgZm9yIGVhY2ggY29udGV4dFxuXHRcdFx0XHRcdGl0ZW1zID0gdGhpc1tpXTtcblx0XG5cdFx0XHRcdFx0aWYgKCB0eXBlID09PSAnY29sdW1uLXJvd3MnICkge1xuXHRcdFx0XHRcdFx0cm93cyA9IF9zZWxlY3Rvcl9yb3dfaW5kZXhlcyggY29udGV4dFtpXSwgc2VsZWN0b3Iub3B0cyApO1xuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0Zm9yICggaj0wLCBqZW49aXRlbXMubGVuZ3RoIDsgajxqZW4gOyBqKysgKSB7XG5cdFx0XHRcdFx0XHRpdGVtID0gaXRlbXNbal07XG5cdFxuXHRcdFx0XHRcdFx0aWYgKCB0eXBlID09PSAnY2VsbCcgKSB7XG5cdFx0XHRcdFx0XHRcdHJldCA9IGZuLmNhbGwoIGFwaUluc3QsIGNvbnRleHRbaV0sIGl0ZW0ucm93LCBpdGVtLmNvbHVtbiwgaSwgaiApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHJldCA9IGZuLmNhbGwoIGFwaUluc3QsIGNvbnRleHRbaV0sIGl0ZW0sIGksIGosIHJvd3MgKTtcblx0XHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0XHRpZiAoIHJldCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdFx0XHRhLnB1c2goIHJldCApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggYS5sZW5ndGggfHwgYWx3YXlzTmV3ICkge1xuXHRcdFx0XHR2YXIgYXBpID0gbmV3IF9BcGkoIGNvbnRleHQsIGZsYXR0ZW4gPyBhLmNvbmNhdC5hcHBseSggW10sIGEgKSA6IGEgKTtcblx0XHRcdFx0dmFyIGFwaVNlbGVjdG9yID0gYXBpLnNlbGVjdG9yO1xuXHRcdFx0XHRhcGlTZWxlY3Rvci5yb3dzID0gc2VsZWN0b3Iucm93cztcblx0XHRcdFx0YXBpU2VsZWN0b3IuY29scyA9IHNlbGVjdG9yLmNvbHM7XG5cdFx0XHRcdGFwaVNlbGVjdG9yLm9wdHMgPSBzZWxlY3Rvci5vcHRzO1xuXHRcdFx0XHRyZXR1cm4gYXBpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblx0XG5cdFxuXHRcdGxhc3RJbmRleE9mOiBfX2FycmF5UHJvdG8ubGFzdEluZGV4T2YgfHwgZnVuY3Rpb24gKG9iaiwgc3RhcnQpXG5cdFx0e1xuXHRcdFx0Ly8gQml0IGNoZWVreS4uLlxuXHRcdFx0cmV0dXJuIHRoaXMuaW5kZXhPZi5hcHBseSggdGhpcy50b0FycmF5LnJldmVyc2UoKSwgYXJndW1lbnRzICk7XG5cdFx0fSxcblx0XG5cdFxuXHRcdGxlbmd0aDogIDAsXG5cdFxuXHRcblx0XHRtYXA6IGZ1bmN0aW9uICggZm4gKVxuXHRcdHtcblx0XHRcdHZhciBhID0gW107XG5cdFxuXHRcdFx0aWYgKCBfX2FycmF5UHJvdG8ubWFwICkge1xuXHRcdFx0XHRhID0gX19hcnJheVByb3RvLm1hcC5jYWxsKCB0aGlzLCBmbiwgdGhpcyApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdC8vIENvbXBhdGliaWxpdHkgZm9yIGJyb3dzZXJzIHdpdGhvdXQgRU1DQS0yNTItNSAoSlMgMS42KVxuXHRcdFx0XHRmb3IgKCB2YXIgaT0wLCBpZW49dGhpcy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0XHRhLnB1c2goIGZuLmNhbGwoIHRoaXMsIHRoaXNbaV0sIGkgKSApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFxuXHRcdFx0cmV0dXJuIG5ldyBfQXBpKCB0aGlzLmNvbnRleHQsIGEgKTtcblx0XHR9LFxuXHRcblx0XG5cdFx0cGx1Y2s6IGZ1bmN0aW9uICggcHJvcCApXG5cdFx0e1xuXHRcdFx0cmV0dXJuIHRoaXMubWFwKCBmdW5jdGlvbiAoIGVsICkge1xuXHRcdFx0XHRyZXR1cm4gZWxbIHByb3AgXTtcblx0XHRcdH0gKTtcblx0XHR9LFxuXHRcblx0XHRwb3A6ICAgICBfX2FycmF5UHJvdG8ucG9wLFxuXHRcblx0XG5cdFx0cHVzaDogICAgX19hcnJheVByb3RvLnB1c2gsXG5cdFxuXHRcblx0XHQvLyBEb2VzIG5vdCByZXR1cm4gYW4gQVBJIGluc3RhbmNlXG5cdFx0cmVkdWNlOiBfX2FycmF5UHJvdG8ucmVkdWNlIHx8IGZ1bmN0aW9uICggZm4sIGluaXQgKVxuXHRcdHtcblx0XHRcdHJldHVybiBfZm5SZWR1Y2UoIHRoaXMsIGZuLCBpbml0LCAwLCB0aGlzLmxlbmd0aCwgMSApO1xuXHRcdH0sXG5cdFxuXHRcblx0XHRyZWR1Y2VSaWdodDogX19hcnJheVByb3RvLnJlZHVjZVJpZ2h0IHx8IGZ1bmN0aW9uICggZm4sIGluaXQgKVxuXHRcdHtcblx0XHRcdHJldHVybiBfZm5SZWR1Y2UoIHRoaXMsIGZuLCBpbml0LCB0aGlzLmxlbmd0aC0xLCAtMSwgLTEgKTtcblx0XHR9LFxuXHRcblx0XG5cdFx0cmV2ZXJzZTogX19hcnJheVByb3RvLnJldmVyc2UsXG5cdFxuXHRcblx0XHQvLyBPYmplY3Qgd2l0aCByb3dzLCBjb2x1bW5zIGFuZCBvcHRzXG5cdFx0c2VsZWN0b3I6IG51bGwsXG5cdFxuXHRcblx0XHRzaGlmdDogICBfX2FycmF5UHJvdG8uc2hpZnQsXG5cdFxuXHRcblx0XHRzbGljZTogZnVuY3Rpb24gKCkge1xuXHRcdFx0cmV0dXJuIG5ldyBfQXBpKCB0aGlzLmNvbnRleHQsIHRoaXMgKTtcblx0XHR9LFxuXHRcblx0XG5cdFx0c29ydDogICAgX19hcnJheVByb3RvLnNvcnQsIC8vID8gbmFtZSAtIG9yZGVyP1xuXHRcblx0XG5cdFx0c3BsaWNlOiAgX19hcnJheVByb3RvLnNwbGljZSxcblx0XG5cdFxuXHRcdHRvQXJyYXk6IGZ1bmN0aW9uICgpXG5cdFx0e1xuXHRcdFx0cmV0dXJuIF9fYXJyYXlQcm90by5zbGljZS5jYWxsKCB0aGlzICk7XG5cdFx0fSxcblx0XG5cdFxuXHRcdHRvJDogZnVuY3Rpb24gKClcblx0XHR7XG5cdFx0XHRyZXR1cm4gJCggdGhpcyApO1xuXHRcdH0sXG5cdFxuXHRcblx0XHR0b0pRdWVyeTogZnVuY3Rpb24gKClcblx0XHR7XG5cdFx0XHRyZXR1cm4gJCggdGhpcyApO1xuXHRcdH0sXG5cdFxuXHRcblx0XHR1bmlxdWU6IGZ1bmN0aW9uICgpXG5cdFx0e1xuXHRcdFx0cmV0dXJuIG5ldyBfQXBpKCB0aGlzLmNvbnRleHQsIF91bmlxdWUodGhpcykgKTtcblx0XHR9LFxuXHRcblx0XG5cdFx0dW5zaGlmdDogX19hcnJheVByb3RvLnVuc2hpZnRcblx0fSApO1xuXHRcblx0XG5cdF9BcGkuZXh0ZW5kID0gZnVuY3Rpb24gKCBzY29wZSwgb2JqLCBleHQgKVxuXHR7XG5cdFx0Ly8gT25seSBleHRlbmQgQVBJIGluc3RhbmNlcyBhbmQgc3RhdGljIHByb3BlcnRpZXMgb2YgdGhlIEFQSVxuXHRcdGlmICggISBleHQubGVuZ3RoIHx8ICEgb2JqIHx8ICggISAob2JqIGluc3RhbmNlb2YgX0FwaSkgJiYgISBvYmouX19kdF93cmFwcGVyICkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXHRcblx0XHR2YXJcblx0XHRcdGksIGllbixcblx0XHRcdGosIGplbixcblx0XHRcdHN0cnVjdCwgaW5uZXIsXG5cdFx0XHRtZXRob2RTY29waW5nID0gZnVuY3Rpb24gKCBzY29wZSwgZm4sIHN0cnVjICkge1xuXHRcdFx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHZhciByZXQgPSBmbi5hcHBseSggc2NvcGUsIGFyZ3VtZW50cyApO1xuXHRcblx0XHRcdFx0XHQvLyBNZXRob2QgZXh0ZW5zaW9uXG5cdFx0XHRcdFx0X0FwaS5leHRlbmQoIHJldCwgcmV0LCBzdHJ1Yy5tZXRob2RFeHQgKTtcblx0XHRcdFx0XHRyZXR1cm4gcmV0O1xuXHRcdFx0XHR9O1xuXHRcdFx0fTtcblx0XG5cdFx0Zm9yICggaT0wLCBpZW49ZXh0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0c3RydWN0ID0gZXh0W2ldO1xuXHRcblx0XHRcdC8vIFZhbHVlXG5cdFx0XHRvYmpbIHN0cnVjdC5uYW1lIF0gPSB0eXBlb2Ygc3RydWN0LnZhbCA9PT0gJ2Z1bmN0aW9uJyA/XG5cdFx0XHRcdG1ldGhvZFNjb3BpbmcoIHNjb3BlLCBzdHJ1Y3QudmFsLCBzdHJ1Y3QgKSA6XG5cdFx0XHRcdCQuaXNQbGFpbk9iamVjdCggc3RydWN0LnZhbCApID9cblx0XHRcdFx0XHR7fSA6XG5cdFx0XHRcdFx0c3RydWN0LnZhbDtcblx0XG5cdFx0XHRvYmpbIHN0cnVjdC5uYW1lIF0uX19kdF93cmFwcGVyID0gdHJ1ZTtcblx0XG5cdFx0XHQvLyBQcm9wZXJ0eSBleHRlbnNpb25cblx0XHRcdF9BcGkuZXh0ZW5kKCBzY29wZSwgb2JqWyBzdHJ1Y3QubmFtZSBdLCBzdHJ1Y3QucHJvcEV4dCApO1xuXHRcdH1cblx0fTtcblx0XG5cdFxuXHQvLyBAdG9kbyAtIElzIHRoZXJlIG5lZWQgZm9yIGFuIGF1Z21lbnQgZnVuY3Rpb24/XG5cdC8vIF9BcGkuYXVnbWVudCA9IGZ1bmN0aW9uICggaW5zdCwgbmFtZSApXG5cdC8vIHtcblx0Ly8gXHQvLyBGaW5kIHNyYyBvYmplY3QgaW4gdGhlIHN0cnVjdHVyZSBmcm9tIHRoZSBuYW1lXG5cdC8vIFx0dmFyIHBhcnRzID0gbmFtZS5zcGxpdCgnLicpO1xuXHRcblx0Ly8gXHRfQXBpLmV4dGVuZCggaW5zdCwgb2JqICk7XG5cdC8vIH07XG5cdFxuXHRcblx0Ly8gICAgIFtcblx0Ly8gICAgICAge1xuXHQvLyAgICAgICAgIG5hbWU6ICAgICAgJ2RhdGEnICAgICAgICAgICAgICAgIC0tIHN0cmluZyAgIC0gUHJvcGVydHkgbmFtZVxuXHQvLyAgICAgICAgIHZhbDogICAgICAgZnVuY3Rpb24gKCkge30sICAgICAgIC0tIGZ1bmN0aW9uIC0gQXBpIG1ldGhvZCAob3IgdW5kZWZpbmVkIGlmIGp1c3QgYW4gb2JqZWN0XG5cdC8vICAgICAgICAgbWV0aG9kRXh0OiBbIC4uLiBdLCAgICAgICAgICAgICAgLS0gYXJyYXkgICAgLSBBcnJheSBvZiBBcGkgb2JqZWN0IGRlZmluaXRpb25zIHRvIGV4dGVuZCB0aGUgbWV0aG9kIHJlc3VsdFxuXHQvLyAgICAgICAgIHByb3BFeHQ6ICAgWyAuLi4gXSAgICAgICAgICAgICAgIC0tIGFycmF5ICAgIC0gQXJyYXkgb2YgQXBpIG9iamVjdCBkZWZpbml0aW9ucyB0byBleHRlbmQgdGhlIHByb3BlcnR5XG5cdC8vICAgICAgIH0sXG5cdC8vICAgICAgIHtcblx0Ly8gICAgICAgICBuYW1lOiAgICAgJ3Jvdydcblx0Ly8gICAgICAgICB2YWw6ICAgICAgIHt9LFxuXHQvLyAgICAgICAgIG1ldGhvZEV4dDogWyAuLi4gXSxcblx0Ly8gICAgICAgICBwcm9wRXh0OiAgIFtcblx0Ly8gICAgICAgICAgIHtcblx0Ly8gICAgICAgICAgICAgbmFtZTogICAgICAnZGF0YSdcblx0Ly8gICAgICAgICAgICAgdmFsOiAgICAgICBmdW5jdGlvbiAoKSB7fSxcblx0Ly8gICAgICAgICAgICAgbWV0aG9kRXh0OiBbIC4uLiBdLFxuXHQvLyAgICAgICAgICAgICBwcm9wRXh0OiAgIFsgLi4uIF1cblx0Ly8gICAgICAgICAgIH0sXG5cdC8vICAgICAgICAgICAuLi5cblx0Ly8gICAgICAgICBdXG5cdC8vICAgICAgIH1cblx0Ly8gICAgIF1cblx0XG5cdF9BcGkucmVnaXN0ZXIgPSBfYXBpX3JlZ2lzdGVyID0gZnVuY3Rpb24gKCBuYW1lLCB2YWwgKVxuXHR7XG5cdFx0aWYgKCAkLmlzQXJyYXkoIG5hbWUgKSApIHtcblx0XHRcdGZvciAoIHZhciBqPTAsIGplbj1uYW1lLmxlbmd0aCA7IGo8amVuIDsgaisrICkge1xuXHRcdFx0XHRfQXBpLnJlZ2lzdGVyKCBuYW1lW2pdLCB2YWwgKTtcblx0XHRcdH1cblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFxuXHRcdHZhclxuXHRcdFx0aSwgaWVuLFxuXHRcdFx0aGVpciA9IG5hbWUuc3BsaXQoJy4nKSxcblx0XHRcdHN0cnVjdCA9IF9fYXBpU3RydWN0LFxuXHRcdFx0a2V5LCBtZXRob2Q7XG5cdFxuXHRcdHZhciBmaW5kID0gZnVuY3Rpb24gKCBzcmMsIG5hbWUgKSB7XG5cdFx0XHRmb3IgKCB2YXIgaT0wLCBpZW49c3JjLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHRpZiAoIHNyY1tpXS5uYW1lID09PSBuYW1lICkge1xuXHRcdFx0XHRcdHJldHVybiBzcmNbaV07XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiBudWxsO1xuXHRcdH07XG5cdFxuXHRcdGZvciAoIGk9MCwgaWVuPWhlaXIubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRtZXRob2QgPSBoZWlyW2ldLmluZGV4T2YoJygpJykgIT09IC0xO1xuXHRcdFx0a2V5ID0gbWV0aG9kID9cblx0XHRcdFx0aGVpcltpXS5yZXBsYWNlKCcoKScsICcnKSA6XG5cdFx0XHRcdGhlaXJbaV07XG5cdFxuXHRcdFx0dmFyIHNyYyA9IGZpbmQoIHN0cnVjdCwga2V5ICk7XG5cdFx0XHRpZiAoICEgc3JjICkge1xuXHRcdFx0XHRzcmMgPSB7XG5cdFx0XHRcdFx0bmFtZTogICAgICBrZXksXG5cdFx0XHRcdFx0dmFsOiAgICAgICB7fSxcblx0XHRcdFx0XHRtZXRob2RFeHQ6IFtdLFxuXHRcdFx0XHRcdHByb3BFeHQ6ICAgW11cblx0XHRcdFx0fTtcblx0XHRcdFx0c3RydWN0LnB1c2goIHNyYyApO1xuXHRcdFx0fVxuXHRcblx0XHRcdGlmICggaSA9PT0gaWVuLTEgKSB7XG5cdFx0XHRcdHNyYy52YWwgPSB2YWw7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0c3RydWN0ID0gbWV0aG9kID9cblx0XHRcdFx0XHRzcmMubWV0aG9kRXh0IDpcblx0XHRcdFx0XHRzcmMucHJvcEV4dDtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cdFxuXHRcblx0X0FwaS5yZWdpc3RlclBsdXJhbCA9IF9hcGlfcmVnaXN0ZXJQbHVyYWwgPSBmdW5jdGlvbiAoIHBsdXJhbE5hbWUsIHNpbmd1bGFyTmFtZSwgdmFsICkge1xuXHRcdF9BcGkucmVnaXN0ZXIoIHBsdXJhbE5hbWUsIHZhbCApO1xuXHRcblx0XHRfQXBpLnJlZ2lzdGVyKCBzaW5ndWxhck5hbWUsIGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciByZXQgPSB2YWwuYXBwbHkoIHRoaXMsIGFyZ3VtZW50cyApO1xuXHRcblx0XHRcdGlmICggcmV0ID09PSB0aGlzICkge1xuXHRcdFx0XHQvLyBSZXR1cm5lZCBpdGVtIGlzIHRoZSBBUEkgaW5zdGFuY2UgdGhhdCB3YXMgcGFzc2VkIGluLCByZXR1cm4gaXRcblx0XHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggcmV0IGluc3RhbmNlb2YgX0FwaSApIHtcblx0XHRcdFx0Ly8gTmV3IEFQSSBpbnN0YW5jZSByZXR1cm5lZCwgd2FudCB0aGUgdmFsdWUgZnJvbSB0aGUgZmlyc3QgaXRlbVxuXHRcdFx0XHQvLyBpbiB0aGUgcmV0dXJuZWQgYXJyYXkgZm9yIHRoZSBzaW5ndWxhciByZXN1bHQuXG5cdFx0XHRcdHJldHVybiByZXQubGVuZ3RoID9cblx0XHRcdFx0XHQkLmlzQXJyYXkoIHJldFswXSApID9cblx0XHRcdFx0XHRcdG5ldyBfQXBpKCByZXQuY29udGV4dCwgcmV0WzBdICkgOiAvLyBBcnJheSByZXN1bHRzIGFyZSAnZW5oYW5jZWQnXG5cdFx0XHRcdFx0XHRyZXRbMF0gOlxuXHRcdFx0XHRcdHVuZGVmaW5lZDtcblx0XHRcdH1cblx0XG5cdFx0XHQvLyBOb24tQVBJIHJldHVybiAtIGp1c3QgZmlyZSBpdCBiYWNrXG5cdFx0XHRyZXR1cm4gcmV0O1xuXHRcdH0gKTtcblx0fTtcblx0XG5cdFxuXHQvKipcblx0ICogU2VsZWN0b3IgZm9yIEhUTUwgdGFibGVzLiBBcHBseSB0aGUgZ2l2ZW4gc2VsZWN0b3IgdG8gdGhlIGdpdmUgYXJyYXkgb2Zcblx0ICogRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3RzLlxuXHQgKlxuXHQgKiBAcGFyYW0ge3N0cmluZ3xpbnRlZ2VyfSBbc2VsZWN0b3JdIGpRdWVyeSBzZWxlY3RvciBzdHJpbmcgb3IgaW50ZWdlclxuXHQgKiBAcGFyYW0gIHthcnJheX0gQXJyYXkgb2YgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3RzIHRvIGJlIGZpbHRlcmVkXG5cdCAqIEByZXR1cm4ge2FycmF5fVxuXHQgKiBAaWdub3JlXG5cdCAqL1xuXHR2YXIgX190YWJsZV9zZWxlY3RvciA9IGZ1bmN0aW9uICggc2VsZWN0b3IsIGEgKVxuXHR7XG5cdFx0Ly8gSW50ZWdlciBpcyB1c2VkIHRvIHBpY2sgb3V0IGEgdGFibGUgYnkgaW5kZXhcblx0XHRpZiAoIHR5cGVvZiBzZWxlY3RvciA9PT0gJ251bWJlcicgKSB7XG5cdFx0XHRyZXR1cm4gWyBhWyBzZWxlY3RvciBdIF07XG5cdFx0fVxuXHRcblx0XHQvLyBQZXJmb3JtIGEgalF1ZXJ5IHNlbGVjdG9yIG9uIHRoZSB0YWJsZSBub2Rlc1xuXHRcdHZhciBub2RlcyA9ICQubWFwKCBhLCBmdW5jdGlvbiAoZWwsIGkpIHtcblx0XHRcdHJldHVybiBlbC5uVGFibGU7XG5cdFx0fSApO1xuXHRcblx0XHRyZXR1cm4gJChub2Rlcylcblx0XHRcdC5maWx0ZXIoIHNlbGVjdG9yIClcblx0XHRcdC5tYXAoIGZ1bmN0aW9uIChpKSB7XG5cdFx0XHRcdC8vIE5lZWQgdG8gdHJhbnNsYXRlIGJhY2sgZnJvbSB0aGUgdGFibGUgbm9kZSB0byB0aGUgc2V0dGluZ3Ncblx0XHRcdFx0dmFyIGlkeCA9ICQuaW5BcnJheSggdGhpcywgbm9kZXMgKTtcblx0XHRcdFx0cmV0dXJuIGFbIGlkeCBdO1xuXHRcdFx0fSApXG5cdFx0XHQudG9BcnJheSgpO1xuXHR9O1xuXHRcblx0XG5cdFxuXHQvKipcblx0ICogQ29udGV4dCBzZWxlY3RvciBmb3IgdGhlIEFQSSdzIGNvbnRleHQgKGkuZS4gdGhlIHRhYmxlcyB0aGUgQVBJIGluc3RhbmNlXG5cdCAqIHJlZmVycyB0by5cblx0ICpcblx0ICogQG5hbWUgICAgRGF0YVRhYmxlLkFwaSN0YWJsZXNcblx0ICogQHBhcmFtIHtzdHJpbmd8aW50ZWdlcn0gW3NlbGVjdG9yXSBTZWxlY3RvciB0byBwaWNrIHdoaWNoIHRhYmxlcyB0aGUgaXRlcmF0b3Jcblx0ICogICBzaG91bGQgb3BlcmF0ZSBvbi4gSWYgbm90IGdpdmVuLCBhbGwgdGFibGVzIGluIHRoZSBjdXJyZW50IGNvbnRleHQgYXJlXG5cdCAqICAgdXNlZC4gVGhpcyBjYW4gYmUgZ2l2ZW4gYXMgYSBqUXVlcnkgc2VsZWN0b3IgKGZvciBleGFtcGxlIGAnOmd0KDApJ2ApIHRvXG5cdCAqICAgc2VsZWN0IG11bHRpcGxlIHRhYmxlcyBvciBhcyBhbiBpbnRlZ2VyIHRvIHNlbGVjdCBhIHNpbmdsZSB0YWJsZS5cblx0ICogQHJldHVybnMge0RhdGFUYWJsZS5BcGl9IFJldHVybnMgYSBuZXcgQVBJIGluc3RhbmNlIGlmIGEgc2VsZWN0b3IgaXMgZ2l2ZW4uXG5cdCAqL1xuXHRfYXBpX3JlZ2lzdGVyKCAndGFibGVzKCknLCBmdW5jdGlvbiAoIHNlbGVjdG9yICkge1xuXHRcdC8vIEEgbmV3IGluc3RhbmNlIGlzIGNyZWF0ZWQgaWYgdGhlcmUgd2FzIGEgc2VsZWN0b3Igc3BlY2lmaWVkXG5cdFx0cmV0dXJuIHNlbGVjdG9yID9cblx0XHRcdG5ldyBfQXBpKCBfX3RhYmxlX3NlbGVjdG9yKCBzZWxlY3RvciwgdGhpcy5jb250ZXh0ICkgKSA6XG5cdFx0XHR0aGlzO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ3RhYmxlKCknLCBmdW5jdGlvbiAoIHNlbGVjdG9yICkge1xuXHRcdHZhciB0YWJsZXMgPSB0aGlzLnRhYmxlcyggc2VsZWN0b3IgKTtcblx0XHR2YXIgY3R4ID0gdGFibGVzLmNvbnRleHQ7XG5cdFxuXHRcdC8vIFRydW5jYXRlIHRvIHRoZSBmaXJzdCBtYXRjaGVkIHRhYmxlXG5cdFx0cmV0dXJuIGN0eC5sZW5ndGggP1xuXHRcdFx0bmV3IF9BcGkoIGN0eFswXSApIDpcblx0XHRcdHRhYmxlcztcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXJQbHVyYWwoICd0YWJsZXMoKS5ub2RlcygpJywgJ3RhYmxlKCkubm9kZSgpJyAsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBjdHggKSB7XG5cdFx0XHRyZXR1cm4gY3R4Lm5UYWJsZTtcblx0XHR9LCAxICk7XG5cdH0gKTtcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAndGFibGVzKCkuYm9keSgpJywgJ3RhYmxlKCkuYm9keSgpJyAsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBjdHggKSB7XG5cdFx0XHRyZXR1cm4gY3R4Lm5UQm9keTtcblx0XHR9LCAxICk7XG5cdH0gKTtcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAndGFibGVzKCkuaGVhZGVyKCknLCAndGFibGUoKS5oZWFkZXIoKScgLCBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggY3R4ICkge1xuXHRcdFx0cmV0dXJuIGN0eC5uVEhlYWQ7XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlclBsdXJhbCggJ3RhYmxlcygpLmZvb3RlcigpJywgJ3RhYmxlKCkuZm9vdGVyKCknICwgZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHtcblx0XHRcdHJldHVybiBjdHgublRGb290O1xuXHRcdH0sIDEgKTtcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXJQbHVyYWwoICd0YWJsZXMoKS5jb250YWluZXJzKCknLCAndGFibGUoKS5jb250YWluZXIoKScgLCBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggY3R4ICkge1xuXHRcdFx0cmV0dXJuIGN0eC5uVGFibGVXcmFwcGVyO1xuXHRcdH0sIDEgKTtcblx0fSApO1xuXHRcblx0XG5cdFxuXHQvKipcblx0ICogUmVkcmF3IHRoZSB0YWJsZXMgaW4gdGhlIGN1cnJlbnQgY29udGV4dC5cblx0ICovXG5cdF9hcGlfcmVnaXN0ZXIoICdkcmF3KCknLCBmdW5jdGlvbiAoIHBhZ2luZyApIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHtcblx0XHRcdGlmICggcGFnaW5nID09PSAncGFnZScgKSB7XG5cdFx0XHRcdF9mbkRyYXcoIHNldHRpbmdzICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0aWYgKCB0eXBlb2YgcGFnaW5nID09PSAnc3RyaW5nJyApIHtcblx0XHRcdFx0XHRwYWdpbmcgPSBwYWdpbmcgPT09ICdmdWxsLWhvbGQnID9cblx0XHRcdFx0XHRcdGZhbHNlIDpcblx0XHRcdFx0XHRcdHRydWU7XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdF9mblJlRHJhdyggc2V0dGluZ3MsIHBhZ2luZz09PWZhbHNlICk7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHR9ICk7XG5cdFxuXHRcblx0XG5cdC8qKlxuXHQgKiBHZXQgdGhlIGN1cnJlbnQgcGFnZSBpbmRleC5cblx0ICpcblx0ICogQHJldHVybiB7aW50ZWdlcn0gQ3VycmVudCBwYWdlIGluZGV4ICh6ZXJvIGJhc2VkKVxuXHQgKi8vKipcblx0ICogU2V0IHRoZSBjdXJyZW50IHBhZ2UuXG5cdCAqXG5cdCAqIE5vdGUgdGhhdCBpZiB5b3UgYXR0ZW1wdCB0byBzaG93IGEgcGFnZSB3aGljaCBkb2VzIG5vdCBleGlzdCwgRGF0YVRhYmxlcyB3aWxsXG5cdCAqIG5vdCB0aHJvdyBhbiBlcnJvciwgYnV0IHJhdGhlciByZXNldCB0aGUgcGFnaW5nLlxuXHQgKlxuXHQgKiBAcGFyYW0ge2ludGVnZXJ8c3RyaW5nfSBhY3Rpb24gVGhlIHBhZ2luZyBhY3Rpb24gdG8gdGFrZS4gVGhpcyBjYW4gYmUgb25lIG9mOlxuXHQgKiAgKiBgaW50ZWdlcmAgLSBUaGUgcGFnZSBpbmRleCB0byBqdW1wIHRvXG5cdCAqICAqIGBzdHJpbmdgIC0gQW4gYWN0aW9uIHRvIHRha2U6XG5cdCAqICAgICogYGZpcnN0YCAtIEp1bXAgdG8gZmlyc3QgcGFnZS5cblx0ICogICAgKiBgbmV4dGAgLSBKdW1wIHRvIHRoZSBuZXh0IHBhZ2Vcblx0ICogICAgKiBgcHJldmlvdXNgIC0gSnVtcCB0byBwcmV2aW91cyBwYWdlXG5cdCAqICAgICogYGxhc3RgIC0gSnVtcCB0byB0aGUgbGFzdCBwYWdlLlxuXHQgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXNcblx0ICovXG5cdF9hcGlfcmVnaXN0ZXIoICdwYWdlKCknLCBmdW5jdGlvbiAoIGFjdGlvbiApIHtcblx0XHRpZiAoIGFjdGlvbiA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmV0dXJuIHRoaXMucGFnZS5pbmZvKCkucGFnZTsgLy8gbm90IGFuIGV4cGVuc2l2ZSBjYWxsXG5cdFx0fVxuXHRcblx0XHQvLyBlbHNlLCBoYXZlIGFuIGFjdGlvbiB0byB0YWtlIG9uIGFsbCB0YWJsZXNcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHtcblx0XHRcdF9mblBhZ2VDaGFuZ2UoIHNldHRpbmdzLCBhY3Rpb24gKTtcblx0XHR9ICk7XG5cdH0gKTtcblx0XG5cdFxuXHQvKipcblx0ICogUGFnaW5nIGluZm9ybWF0aW9uIGZvciB0aGUgZmlyc3QgdGFibGUgaW4gdGhlIGN1cnJlbnQgY29udGV4dC5cblx0ICpcblx0ICogSWYgeW91IHJlcXVpcmUgcGFnaW5nIGluZm9ybWF0aW9uIGZvciBhbm90aGVyIHRhYmxlLCB1c2UgdGhlIGB0YWJsZSgpYCBtZXRob2Rcblx0ICogd2l0aCBhIHN1aXRhYmxlIHNlbGVjdG9yLlxuXHQgKlxuXHQgKiBAcmV0dXJuIHtvYmplY3R9IE9iamVjdCB3aXRoIHRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyBzZXQ6XG5cdCAqICAqIGBwYWdlYCAtIEN1cnJlbnQgcGFnZSBpbmRleCAoemVybyBiYXNlZCAtIGkuZS4gdGhlIGZpcnN0IHBhZ2UgaXMgYDBgKVxuXHQgKiAgKiBgcGFnZXNgIC0gVG90YWwgbnVtYmVyIG9mIHBhZ2VzXG5cdCAqICAqIGBzdGFydGAgLSBEaXNwbGF5IGluZGV4IGZvciB0aGUgZmlyc3QgcmVjb3JkIHNob3duIG9uIHRoZSBjdXJyZW50IHBhZ2Vcblx0ICogICogYGVuZGAgLSBEaXNwbGF5IGluZGV4IGZvciB0aGUgbGFzdCByZWNvcmQgc2hvd24gb24gdGhlIGN1cnJlbnQgcGFnZVxuXHQgKiAgKiBgbGVuZ3RoYCAtIERpc3BsYXkgbGVuZ3RoIChudW1iZXIgb2YgcmVjb3JkcykuIE5vdGUgdGhhdCBnZW5lcmFsbHkgYHN0YXJ0XG5cdCAqICAgICsgbGVuZ3RoID0gZW5kYCwgYnV0IHRoaXMgaXMgbm90IGFsd2F5cyB0cnVlLCBmb3IgZXhhbXBsZSBpZiB0aGVyZSBhcmVcblx0ICogICAgb25seSAyIHJlY29yZHMgdG8gc2hvdyBvbiB0aGUgZmluYWwgcGFnZSwgd2l0aCBhIGxlbmd0aCBvZiAxMC5cblx0ICogICogYHJlY29yZHNUb3RhbGAgLSBGdWxsIGRhdGEgc2V0IGxlbmd0aFxuXHQgKiAgKiBgcmVjb3Jkc0Rpc3BsYXlgIC0gRGF0YSBzZXQgbGVuZ3RoIG9uY2UgdGhlIGN1cnJlbnQgZmlsdGVyaW5nIGNyaXRlcmlvblxuXHQgKiAgICBhcmUgYXBwbGllZC5cblx0ICovXG5cdF9hcGlfcmVnaXN0ZXIoICdwYWdlLmluZm8oKScsIGZ1bmN0aW9uICggYWN0aW9uICkge1xuXHRcdGlmICggdGhpcy5jb250ZXh0Lmxlbmd0aCA9PT0gMCApIHtcblx0XHRcdHJldHVybiB1bmRlZmluZWQ7XG5cdFx0fVxuXHRcblx0XHR2YXJcblx0XHRcdHNldHRpbmdzICAgPSB0aGlzLmNvbnRleHRbMF0sXG5cdFx0XHRzdGFydCAgICAgID0gc2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsXG5cdFx0XHRsZW4gICAgICAgID0gc2V0dGluZ3Mub0ZlYXR1cmVzLmJQYWdpbmF0ZSA/IHNldHRpbmdzLl9pRGlzcGxheUxlbmd0aCA6IC0xLFxuXHRcdFx0dmlzUmVjb3JkcyA9IHNldHRpbmdzLmZuUmVjb3Jkc0Rpc3BsYXkoKSxcblx0XHRcdGFsbCAgICAgICAgPSBsZW4gPT09IC0xO1xuXHRcblx0XHRyZXR1cm4ge1xuXHRcdFx0XCJwYWdlXCI6ICAgICAgICAgICBhbGwgPyAwIDogTWF0aC5mbG9vciggc3RhcnQgLyBsZW4gKSxcblx0XHRcdFwicGFnZXNcIjogICAgICAgICAgYWxsID8gMSA6IE1hdGguY2VpbCggdmlzUmVjb3JkcyAvIGxlbiApLFxuXHRcdFx0XCJzdGFydFwiOiAgICAgICAgICBzdGFydCxcblx0XHRcdFwiZW5kXCI6ICAgICAgICAgICAgc2V0dGluZ3MuZm5EaXNwbGF5RW5kKCksXG5cdFx0XHRcImxlbmd0aFwiOiAgICAgICAgIGxlbixcblx0XHRcdFwicmVjb3Jkc1RvdGFsXCI6ICAgc2V0dGluZ3MuZm5SZWNvcmRzVG90YWwoKSxcblx0XHRcdFwicmVjb3Jkc0Rpc3BsYXlcIjogdmlzUmVjb3Jkcyxcblx0XHRcdFwic2VydmVyU2lkZVwiOiAgICAgX2ZuRGF0YVNvdXJjZSggc2V0dGluZ3MgKSA9PT0gJ3NzcCdcblx0XHR9O1xuXHR9ICk7XG5cdFxuXHRcblx0LyoqXG5cdCAqIEdldCB0aGUgY3VycmVudCBwYWdlIGxlbmd0aC5cblx0ICpcblx0ICogQHJldHVybiB7aW50ZWdlcn0gQ3VycmVudCBwYWdlIGxlbmd0aC4gTm90ZSBgLTFgIGluZGljYXRlcyB0aGF0IGFsbCByZWNvcmRzXG5cdCAqICAgYXJlIHRvIGJlIHNob3duLlxuXHQgKi8vKipcblx0ICogU2V0IHRoZSBjdXJyZW50IHBhZ2UgbGVuZ3RoLlxuXHQgKlxuXHQgKiBAcGFyYW0ge2ludGVnZXJ9IFBhZ2UgbGVuZ3RoIHRvIHNldC4gVXNlIGAtMWAgdG8gc2hvdyBhbGwgcmVjb3Jkcy5cblx0ICogQHJldHVybnMge0RhdGFUYWJsZXMuQXBpfSB0aGlzXG5cdCAqL1xuXHRfYXBpX3JlZ2lzdGVyKCAncGFnZS5sZW4oKScsIGZ1bmN0aW9uICggbGVuICkge1xuXHRcdC8vIE5vdGUgdGhhdCB3ZSBjYW4ndCBjYWxsIHRoaXMgZnVuY3Rpb24gJ2xlbmd0aCgpJyBiZWNhdXNlIGBsZW5ndGhgXG5cdFx0Ly8gaXMgYSBKYXZhc2NyaXB0IHByb3BlcnR5IG9mIGZ1bmN0aW9ucyB3aGljaCBkZWZpbmVzIGhvdyBtYW55IGFyZ3VtZW50c1xuXHRcdC8vIHRoZSBmdW5jdGlvbiBleHBlY3RzLlxuXHRcdGlmICggbGVuID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5jb250ZXh0Lmxlbmd0aCAhPT0gMCA/XG5cdFx0XHRcdHRoaXMuY29udGV4dFswXS5faURpc3BsYXlMZW5ndGggOlxuXHRcdFx0XHR1bmRlZmluZWQ7XG5cdFx0fVxuXHRcblx0XHQvLyBlbHNlLCBzZXQgdGhlIHBhZ2UgbGVuZ3RoXG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7XG5cdFx0XHRfZm5MZW5ndGhDaGFuZ2UoIHNldHRpbmdzLCBsZW4gKTtcblx0XHR9ICk7XG5cdH0gKTtcblx0XG5cdFxuXHRcblx0dmFyIF9fcmVsb2FkID0gZnVuY3Rpb24gKCBzZXR0aW5ncywgaG9sZFBvc2l0aW9uLCBjYWxsYmFjayApIHtcblx0XHQvLyBVc2UgdGhlIGRyYXcgZXZlbnQgdG8gdHJpZ2dlciBhIGNhbGxiYWNrXG5cdFx0aWYgKCBjYWxsYmFjayApIHtcblx0XHRcdHZhciBhcGkgPSBuZXcgX0FwaSggc2V0dGluZ3MgKTtcblx0XG5cdFx0XHRhcGkub25lKCAnZHJhdycsIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0Y2FsbGJhY2soIGFwaS5hamF4Lmpzb24oKSApO1xuXHRcdFx0fSApO1xuXHRcdH1cblx0XG5cdFx0aWYgKCBfZm5EYXRhU291cmNlKCBzZXR0aW5ncyApID09ICdzc3AnICkge1xuXHRcdFx0X2ZuUmVEcmF3KCBzZXR0aW5ncywgaG9sZFBvc2l0aW9uICk7XG5cdFx0fVxuXHRcdGVsc2Uge1xuXHRcdFx0X2ZuUHJvY2Vzc2luZ0Rpc3BsYXkoIHNldHRpbmdzLCB0cnVlICk7XG5cdFxuXHRcdFx0Ly8gQ2FuY2VsIGFuIGV4aXN0aW5nIHJlcXVlc3Rcblx0XHRcdHZhciB4aHIgPSBzZXR0aW5ncy5qcVhIUjtcblx0XHRcdGlmICggeGhyICYmIHhoci5yZWFkeVN0YXRlICE9PSA0ICkge1xuXHRcdFx0XHR4aHIuYWJvcnQoKTtcblx0XHRcdH1cblx0XG5cdFx0XHQvLyBUcmlnZ2VyIHhoclxuXHRcdFx0X2ZuQnVpbGRBamF4KCBzZXR0aW5ncywgW10sIGZ1bmN0aW9uKCBqc29uICkge1xuXHRcdFx0XHRfZm5DbGVhclRhYmxlKCBzZXR0aW5ncyApO1xuXHRcblx0XHRcdFx0dmFyIGRhdGEgPSBfZm5BamF4RGF0YVNyYyggc2V0dGluZ3MsIGpzb24gKTtcblx0XHRcdFx0Zm9yICggdmFyIGk9MCwgaWVuPWRhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0X2ZuQWRkRGF0YSggc2V0dGluZ3MsIGRhdGFbaV0gKTtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0X2ZuUmVEcmF3KCBzZXR0aW5ncywgaG9sZFBvc2l0aW9uICk7XG5cdFx0XHRcdF9mblByb2Nlc3NpbmdEaXNwbGF5KCBzZXR0aW5ncywgZmFsc2UgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cdH07XG5cdFxuXHRcblx0LyoqXG5cdCAqIEdldCB0aGUgSlNPTiByZXNwb25zZSBmcm9tIHRoZSBsYXN0IEFqYXggcmVxdWVzdCB0aGF0IERhdGFUYWJsZXMgbWFkZSB0byB0aGVcblx0ICogc2VydmVyLiBOb3RlIHRoYXQgdGhpcyByZXR1cm5zIHRoZSBKU09OIGZyb20gdGhlIGZpcnN0IHRhYmxlIGluIHRoZSBjdXJyZW50XG5cdCAqIGNvbnRleHQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge29iamVjdH0gSlNPTiByZWNlaXZlZCBmcm9tIHRoZSBzZXJ2ZXIuXG5cdCAqL1xuXHRfYXBpX3JlZ2lzdGVyKCAnYWpheC5qc29uKCknLCBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGN0eCA9IHRoaXMuY29udGV4dDtcblx0XG5cdFx0aWYgKCBjdHgubGVuZ3RoID4gMCApIHtcblx0XHRcdHJldHVybiBjdHhbMF0uanNvbjtcblx0XHR9XG5cdFxuXHRcdC8vIGVsc2UgcmV0dXJuIHVuZGVmaW5lZDtcblx0fSApO1xuXHRcblx0XG5cdC8qKlxuXHQgKiBHZXQgdGhlIGRhdGEgc3VibWl0dGVkIGluIHRoZSBsYXN0IEFqYXggcmVxdWVzdFxuXHQgKi9cblx0X2FwaV9yZWdpc3RlciggJ2FqYXgucGFyYW1zKCknLCBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIGN0eCA9IHRoaXMuY29udGV4dDtcblx0XG5cdFx0aWYgKCBjdHgubGVuZ3RoID4gMCApIHtcblx0XHRcdHJldHVybiBjdHhbMF0ub0FqYXhEYXRhO1xuXHRcdH1cblx0XG5cdFx0Ly8gZWxzZSByZXR1cm4gdW5kZWZpbmVkO1xuXHR9ICk7XG5cdFxuXHRcblx0LyoqXG5cdCAqIFJlbG9hZCB0YWJsZXMgZnJvbSB0aGUgQWpheCBkYXRhIHNvdXJjZS4gTm90ZSB0aGF0IHRoaXMgZnVuY3Rpb24gd2lsbFxuXHQgKiBhdXRvbWF0aWNhbGx5IHJlLWRyYXcgdGhlIHRhYmxlIHdoZW4gdGhlIHJlbW90ZSBkYXRhIGhhcyBiZWVuIGxvYWRlZC5cblx0ICpcblx0ICogQHBhcmFtIHtib29sZWFufSBbcmVzZXQ9dHJ1ZV0gUmVzZXQgKGRlZmF1bHQpIG9yIGhvbGQgdGhlIGN1cnJlbnQgcGFnaW5nXG5cdCAqICAgcG9zaXRpb24uIEEgZnVsbCByZS1zb3J0IGFuZCByZS1maWx0ZXIgaXMgcGVyZm9ybWVkIHdoZW4gdGhpcyBtZXRob2QgaXNcblx0ICogICBjYWxsZWQsIHdoaWNoIGlzIHdoeSB0aGUgcGFnaW5hdGlvbiByZXNldCBpcyB0aGUgZGVmYXVsdCBhY3Rpb24uXG5cdCAqIEByZXR1cm5zIHtEYXRhVGFibGVzLkFwaX0gdGhpc1xuXHQgKi9cblx0X2FwaV9yZWdpc3RlciggJ2FqYXgucmVsb2FkKCknLCBmdW5jdGlvbiAoIGNhbGxiYWNrLCByZXNldFBhZ2luZyApIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKHNldHRpbmdzKSB7XG5cdFx0XHRfX3JlbG9hZCggc2V0dGluZ3MsIHJlc2V0UGFnaW5nPT09ZmFsc2UsIGNhbGxiYWNrICk7XG5cdFx0fSApO1xuXHR9ICk7XG5cdFxuXHRcblx0LyoqXG5cdCAqIEdldCB0aGUgY3VycmVudCBBamF4IFVSTC4gTm90ZSB0aGF0IHRoaXMgcmV0dXJucyB0aGUgVVJMIGZyb20gdGhlIGZpcnN0XG5cdCAqIHRhYmxlIGluIHRoZSBjdXJyZW50IGNvbnRleHQuXG5cdCAqXG5cdCAqIEByZXR1cm4ge3N0cmluZ30gQ3VycmVudCBBamF4IHNvdXJjZSBVUkxcblx0ICovLyoqXG5cdCAqIFNldCB0aGUgQWpheCBVUkwuIE5vdGUgdGhhdCB0aGlzIHdpbGwgc2V0IHRoZSBVUkwgZm9yIGFsbCB0YWJsZXMgaW4gdGhlXG5cdCAqIGN1cnJlbnQgY29udGV4dC5cblx0ICpcblx0ICogQHBhcmFtIHtzdHJpbmd9IHVybCBVUkwgdG8gc2V0LlxuXHQgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXNcblx0ICovXG5cdF9hcGlfcmVnaXN0ZXIoICdhamF4LnVybCgpJywgZnVuY3Rpb24gKCB1cmwgKSB7XG5cdFx0dmFyIGN0eCA9IHRoaXMuY29udGV4dDtcblx0XG5cdFx0aWYgKCB1cmwgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdC8vIGdldFxuXHRcdFx0aWYgKCBjdHgubGVuZ3RoID09PSAwICkge1xuXHRcdFx0XHRyZXR1cm4gdW5kZWZpbmVkO1xuXHRcdFx0fVxuXHRcdFx0Y3R4ID0gY3R4WzBdO1xuXHRcblx0XHRcdHJldHVybiBjdHguYWpheCA/XG5cdFx0XHRcdCQuaXNQbGFpbk9iamVjdCggY3R4LmFqYXggKSA/XG5cdFx0XHRcdFx0Y3R4LmFqYXgudXJsIDpcblx0XHRcdFx0XHRjdHguYWpheCA6XG5cdFx0XHRcdGN0eC5zQWpheFNvdXJjZTtcblx0XHR9XG5cdFxuXHRcdC8vIHNldFxuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0aWYgKCAkLmlzUGxhaW5PYmplY3QoIHNldHRpbmdzLmFqYXggKSApIHtcblx0XHRcdFx0c2V0dGluZ3MuYWpheC51cmwgPSB1cmw7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0c2V0dGluZ3MuYWpheCA9IHVybDtcblx0XHRcdH1cblx0XHRcdC8vIE5vIG5lZWQgdG8gY29uc2lkZXIgc0FqYXhTb3VyY2UgaGVyZSBzaW5jZSBEYXRhVGFibGVzIGdpdmVzIHByaW9yaXR5XG5cdFx0XHQvLyB0byBgYWpheGAgb3ZlciBgc0FqYXhTb3VyY2VgLiBTbyBzZXR0aW5nIGBhamF4YCBoZXJlLCByZW5kZXJzIGFueVxuXHRcdFx0Ly8gdmFsdWUgb2YgYHNBamF4U291cmNlYCByZWR1bmRhbnQuXG5cdFx0fSApO1xuXHR9ICk7XG5cdFxuXHRcblx0LyoqXG5cdCAqIExvYWQgZGF0YSBmcm9tIHRoZSBuZXdseSBzZXQgQWpheCBVUkwuIE5vdGUgdGhhdCB0aGlzIG1ldGhvZCBpcyBvbmx5XG5cdCAqIGF2YWlsYWJsZSB3aGVuIGBhamF4LnVybCgpYCBpcyB1c2VkIHRvIHNldCBhIFVSTC4gQWRkaXRpb25hbGx5LCB0aGlzIG1ldGhvZFxuXHQgKiBoYXMgdGhlIHNhbWUgZWZmZWN0IGFzIGNhbGxpbmcgYGFqYXgucmVsb2FkKClgIGJ1dCBpcyBwcm92aWRlZCBmb3Jcblx0ICogY29udmVuaWVuY2Ugd2hlbiBzZXR0aW5nIGEgbmV3IFVSTC4gTGlrZSBgYWpheC5yZWxvYWQoKWAgaXQgd2lsbFxuXHQgKiBhdXRvbWF0aWNhbGx5IHJlZHJhdyB0aGUgdGFibGUgb25jZSB0aGUgcmVtb3RlIGRhdGEgaGFzIGJlZW4gbG9hZGVkLlxuXHQgKlxuXHQgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXNcblx0ICovXG5cdF9hcGlfcmVnaXN0ZXIoICdhamF4LnVybCgpLmxvYWQoKScsIGZ1bmN0aW9uICggY2FsbGJhY2ssIHJlc2V0UGFnaW5nICkge1xuXHRcdC8vIFNhbWUgYXMgYSByZWxvYWQsIGJ1dCBtYWtlcyBzZW5zZSB0byBwcmVzZW50IGl0IGZvciBlYXN5IGFjY2VzcyBhZnRlciBhXG5cdFx0Ly8gdXJsIGNoYW5nZVxuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIGN0eCApIHtcblx0XHRcdF9fcmVsb2FkKCBjdHgsIHJlc2V0UGFnaW5nPT09ZmFsc2UsIGNhbGxiYWNrICk7XG5cdFx0fSApO1xuXHR9ICk7XG5cdFxuXHRcblx0XG5cdFxuXHR2YXIgX3NlbGVjdG9yX3J1biA9IGZ1bmN0aW9uICggdHlwZSwgc2VsZWN0b3IsIHNlbGVjdEZuLCBzZXR0aW5ncywgb3B0cyApXG5cdHtcblx0XHR2YXJcblx0XHRcdG91dCA9IFtdLCByZXMsXG5cdFx0XHRhLCBpLCBpZW4sIGosIGplbixcblx0XHRcdHNlbGVjdG9yVHlwZSA9IHR5cGVvZiBzZWxlY3Rvcjtcblx0XG5cdFx0Ly8gQ2FuJ3QganVzdCBjaGVjayBmb3IgaXNBcnJheSBoZXJlLCBhcyBhbiBBUEkgb3IgalF1ZXJ5IGluc3RhbmNlIG1pZ2h0IGJlXG5cdFx0Ly8gZ2l2ZW4gd2l0aCB0aGVpciBhcnJheSBsaWtlIGxvb2tcblx0XHRpZiAoICEgc2VsZWN0b3IgfHwgc2VsZWN0b3JUeXBlID09PSAnc3RyaW5nJyB8fCBzZWxlY3RvclR5cGUgPT09ICdmdW5jdGlvbicgfHwgc2VsZWN0b3IubGVuZ3RoID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRzZWxlY3RvciA9IFsgc2VsZWN0b3IgXTtcblx0XHR9XG5cdFxuXHRcdGZvciAoIGk9MCwgaWVuPXNlbGVjdG9yLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0Ly8gT25seSBzcGxpdCBvbiBzaW1wbGUgc3RyaW5ncyAtIGNvbXBsZXggZXhwcmVzc2lvbnMgd2lsbCBiZSBqUXVlcnkgc2VsZWN0b3JzXG5cdFx0XHRhID0gc2VsZWN0b3JbaV0gJiYgc2VsZWN0b3JbaV0uc3BsaXQgJiYgISBzZWxlY3RvcltpXS5tYXRjaCgvW1xcW1xcKDpdLykgP1xuXHRcdFx0XHRzZWxlY3RvcltpXS5zcGxpdCgnLCcpIDpcblx0XHRcdFx0WyBzZWxlY3RvcltpXSBdO1xuXHRcblx0XHRcdGZvciAoIGo9MCwgamVuPWEubGVuZ3RoIDsgajxqZW4gOyBqKysgKSB7XG5cdFx0XHRcdHJlcyA9IHNlbGVjdEZuKCB0eXBlb2YgYVtqXSA9PT0gJ3N0cmluZycgPyAkLnRyaW0oYVtqXSkgOiBhW2pdICk7XG5cdFxuXHRcdFx0XHRpZiAoIHJlcyAmJiByZXMubGVuZ3RoICkge1xuXHRcdFx0XHRcdG91dCA9IG91dC5jb25jYXQoIHJlcyApO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHQvLyBzZWxlY3RvciBleHRlbnNpb25zXG5cdFx0dmFyIGV4dCA9IF9leHQuc2VsZWN0b3JbIHR5cGUgXTtcblx0XHRpZiAoIGV4dC5sZW5ndGggKSB7XG5cdFx0XHRmb3IgKCBpPTAsIGllbj1leHQubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdG91dCA9IGV4dFtpXSggc2V0dGluZ3MsIG9wdHMsIG91dCApO1xuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0cmV0dXJuIF91bmlxdWUoIG91dCApO1xuXHR9O1xuXHRcblx0XG5cdHZhciBfc2VsZWN0b3Jfb3B0cyA9IGZ1bmN0aW9uICggb3B0cyApXG5cdHtcblx0XHRpZiAoICEgb3B0cyApIHtcblx0XHRcdG9wdHMgPSB7fTtcblx0XHR9XG5cdFxuXHRcdC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IGZvciAxLjktIHdoaWNoIHVzZWQgdGhlIHRlcm1pbm9sb2d5IGZpbHRlciByYXRoZXJcblx0XHQvLyB0aGFuIHNlYXJjaFxuXHRcdGlmICggb3B0cy5maWx0ZXIgJiYgb3B0cy5zZWFyY2ggPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdG9wdHMuc2VhcmNoID0gb3B0cy5maWx0ZXI7XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gJC5leHRlbmQoIHtcblx0XHRcdHNlYXJjaDogJ25vbmUnLFxuXHRcdFx0b3JkZXI6ICdjdXJyZW50Jyxcblx0XHRcdHBhZ2U6ICdhbGwnXG5cdFx0fSwgb3B0cyApO1xuXHR9O1xuXHRcblx0XG5cdHZhciBfc2VsZWN0b3JfZmlyc3QgPSBmdW5jdGlvbiAoIGluc3QgKVxuXHR7XG5cdFx0Ly8gUmVkdWNlIHRoZSBBUEkgaW5zdGFuY2UgdG8gdGhlIGZpcnN0IGl0ZW0gZm91bmRcblx0XHRmb3IgKCB2YXIgaT0wLCBpZW49aW5zdC5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGlmICggaW5zdFtpXS5sZW5ndGggPiAwICkge1xuXHRcdFx0XHQvLyBBc3NpZ24gdGhlIGZpcnN0IGVsZW1lbnQgdG8gdGhlIGZpcnN0IGl0ZW0gaW4gdGhlIGluc3RhbmNlXG5cdFx0XHRcdC8vIGFuZCB0cnVuY2F0ZSB0aGUgaW5zdGFuY2UgYW5kIGNvbnRleHRcblx0XHRcdFx0aW5zdFswXSA9IGluc3RbaV07XG5cdFx0XHRcdGluc3RbMF0ubGVuZ3RoID0gMTtcblx0XHRcdFx0aW5zdC5sZW5ndGggPSAxO1xuXHRcdFx0XHRpbnN0LmNvbnRleHQgPSBbIGluc3QuY29udGV4dFtpXSBdO1xuXHRcblx0XHRcdFx0cmV0dXJuIGluc3Q7XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHQvLyBOb3QgZm91bmQgLSByZXR1cm4gYW4gZW1wdHkgaW5zdGFuY2Vcblx0XHRpbnN0Lmxlbmd0aCA9IDA7XG5cdFx0cmV0dXJuIGluc3Q7XG5cdH07XG5cdFxuXHRcblx0dmFyIF9zZWxlY3Rvcl9yb3dfaW5kZXhlcyA9IGZ1bmN0aW9uICggc2V0dGluZ3MsIG9wdHMgKVxuXHR7XG5cdFx0dmFyXG5cdFx0XHRpLCBpZW4sIHRtcCwgYT1bXSxcblx0XHRcdGRpc3BsYXlGaWx0ZXJlZCA9IHNldHRpbmdzLmFpRGlzcGxheSxcblx0XHRcdGRpc3BsYXlNYXN0ZXIgPSBzZXR0aW5ncy5haURpc3BsYXlNYXN0ZXI7XG5cdFxuXHRcdHZhclxuXHRcdFx0c2VhcmNoID0gb3B0cy5zZWFyY2gsICAvLyBub25lLCBhcHBsaWVkLCByZW1vdmVkXG5cdFx0XHRvcmRlciAgPSBvcHRzLm9yZGVyLCAgIC8vIGFwcGxpZWQsIGN1cnJlbnQsIGluZGV4IChvcmlnaW5hbCAtIGNvbXBhdGliaWxpdHkgd2l0aCAxLjkpXG5cdFx0XHRwYWdlICAgPSBvcHRzLnBhZ2U7ICAgIC8vIGFsbCwgY3VycmVudFxuXHRcblx0XHRpZiAoIF9mbkRhdGFTb3VyY2UoIHNldHRpbmdzICkgPT0gJ3NzcCcgKSB7XG5cdFx0XHQvLyBJbiBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIG1vZGUsIG1vc3Qgb3B0aW9ucyBhcmUgaXJyZWxldmFudCBzaW5jZVxuXHRcdFx0Ly8gcm93cyBub3Qgc2hvd24gZG9uJ3QgZXhpc3QgYW5kIHRoZSBpbmRleCBvcmRlciBpcyB0aGUgYXBwbGllZCBvcmRlclxuXHRcdFx0Ly8gUmVtb3ZlZCBpcyBhIHNwZWNpYWwgY2FzZSAtIGZvciBjb25zaXN0ZW5jeSBqdXN0IHJldHVybiBhbiBlbXB0eVxuXHRcdFx0Ly8gYXJyYXlcblx0XHRcdHJldHVybiBzZWFyY2ggPT09ICdyZW1vdmVkJyA/XG5cdFx0XHRcdFtdIDpcblx0XHRcdFx0X3JhbmdlKCAwLCBkaXNwbGF5TWFzdGVyLmxlbmd0aCApO1xuXHRcdH1cblx0XHRlbHNlIGlmICggcGFnZSA9PSAnY3VycmVudCcgKSB7XG5cdFx0XHQvLyBDdXJyZW50IHBhZ2UgaW1wbGllcyB0aGF0IG9yZGVyPWN1cnJlbnQgYW5kIGZpdGxlcj1hcHBsaWVkLCBzaW5jZSBpdCBpc1xuXHRcdFx0Ly8gZmFpcmx5IHNlbnNlbGVzcyBvdGhlcndpc2UsIHJlZ2FyZGxlc3Mgb2Ygd2hhdCBvcmRlciBhbmQgc2VhcmNoIGFjdHVhbGx5XG5cdFx0XHQvLyBhcmVcblx0XHRcdGZvciAoIGk9c2V0dGluZ3MuX2lEaXNwbGF5U3RhcnQsIGllbj1zZXR0aW5ncy5mbkRpc3BsYXlFbmQoKSA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHRhLnB1c2goIGRpc3BsYXlGaWx0ZXJlZFtpXSApO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIGlmICggb3JkZXIgPT0gJ2N1cnJlbnQnIHx8IG9yZGVyID09ICdhcHBsaWVkJyApIHtcblx0XHRcdGEgPSBzZWFyY2ggPT0gJ25vbmUnID9cblx0XHRcdFx0ZGlzcGxheU1hc3Rlci5zbGljZSgpIDogICAgICAgICAgICAgICAgICAgICAgLy8gbm8gc2VhcmNoXG5cdFx0XHRcdHNlYXJjaCA9PSAnYXBwbGllZCcgP1xuXHRcdFx0XHRcdGRpc3BsYXlGaWx0ZXJlZC5zbGljZSgpIDogICAgICAgICAgICAgICAgLy8gYXBwbGllZCBzZWFyY2hcblx0XHRcdFx0XHQkLm1hcCggZGlzcGxheU1hc3RlciwgZnVuY3Rpb24gKGVsLCBpKSB7IC8vIHJlbW92ZWQgc2VhcmNoXG5cdFx0XHRcdFx0XHRyZXR1cm4gJC5pbkFycmF5KCBlbCwgZGlzcGxheUZpbHRlcmVkICkgPT09IC0xID8gZWwgOiBudWxsO1xuXHRcdFx0XHRcdH0gKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIG9yZGVyID09ICdpbmRleCcgfHwgb3JkZXIgPT0gJ29yaWdpbmFsJyApIHtcblx0XHRcdGZvciAoIGk9MCwgaWVuPXNldHRpbmdzLmFvRGF0YS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0aWYgKCBzZWFyY2ggPT0gJ25vbmUnICkge1xuXHRcdFx0XHRcdGEucHVzaCggaSApO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgeyAvLyBhcHBsaWVkIHwgcmVtb3ZlZFxuXHRcdFx0XHRcdHRtcCA9ICQuaW5BcnJheSggaSwgZGlzcGxheUZpbHRlcmVkICk7XG5cdFxuXHRcdFx0XHRcdGlmICgodG1wID09PSAtMSAmJiBzZWFyY2ggPT0gJ3JlbW92ZWQnKSB8fFxuXHRcdFx0XHRcdFx0KHRtcCA+PSAwICAgJiYgc2VhcmNoID09ICdhcHBsaWVkJykgKVxuXHRcdFx0XHRcdHtcblx0XHRcdFx0XHRcdGEucHVzaCggaSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0cmV0dXJuIGE7XG5cdH07XG5cdFxuXHRcblx0LyogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG5cdCAqIFJvd3Ncblx0ICpcblx0ICoge30gICAgICAgICAgLSBubyBzZWxlY3RvciAtIHVzZSBhbGwgYXZhaWxhYmxlIHJvd3Ncblx0ICoge2ludGVnZXJ9ICAgLSByb3cgYW9EYXRhIGluZGV4XG5cdCAqIHtub2RlfSAgICAgIC0gVFIgbm9kZVxuXHQgKiB7c3RyaW5nfSAgICAtIGpRdWVyeSBzZWxlY3RvciB0byBhcHBseSB0byB0aGUgVFIgZWxlbWVudHNcblx0ICoge2FycmF5fSAgICAgLSBqUXVlcnkgYXJyYXkgb2Ygbm9kZXMsIG9yIHNpbXBseSBhbiBhcnJheSBvZiBUUiBub2Rlc1xuXHQgKlxuXHQgKi9cblx0XG5cdFxuXHR2YXIgX19yb3dfc2VsZWN0b3IgPSBmdW5jdGlvbiAoIHNldHRpbmdzLCBzZWxlY3Rvciwgb3B0cyApXG5cdHtcblx0XHR2YXIgcm93cztcblx0XHR2YXIgcnVuID0gZnVuY3Rpb24gKCBzZWwgKSB7XG5cdFx0XHR2YXIgc2VsSW50ID0gX2ludFZhbCggc2VsICk7XG5cdFx0XHR2YXIgaSwgaWVuO1xuXHRcblx0XHRcdC8vIFNob3J0IGN1dCAtIHNlbGVjdG9yIGlzIGEgbnVtYmVyIGFuZCBubyBvcHRpb25zIHByb3ZpZGVkIChkZWZhdWx0IGlzXG5cdFx0XHQvLyBhbGwgcmVjb3Jkcywgc28gbm8gbmVlZCB0byBjaGVjayBpZiB0aGUgaW5kZXggaXMgaW4gdGhlcmUsIHNpbmNlIGl0XG5cdFx0XHQvLyBtdXN0IGJlIC0gZGV2IGVycm9yIGlmIHRoZSBpbmRleCBkb2Vzbid0IGV4aXN0KS5cblx0XHRcdGlmICggc2VsSW50ICE9PSBudWxsICYmICEgb3B0cyApIHtcblx0XHRcdFx0cmV0dXJuIFsgc2VsSW50IF07XG5cdFx0XHR9XG5cdFxuXHRcdFx0aWYgKCAhIHJvd3MgKSB7XG5cdFx0XHRcdHJvd3MgPSBfc2VsZWN0b3Jfcm93X2luZGV4ZXMoIHNldHRpbmdzLCBvcHRzICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0aWYgKCBzZWxJbnQgIT09IG51bGwgJiYgJC5pbkFycmF5KCBzZWxJbnQsIHJvd3MgKSAhPT0gLTEgKSB7XG5cdFx0XHRcdC8vIFNlbGVjdG9yIC0gaW50ZWdlclxuXHRcdFx0XHRyZXR1cm4gWyBzZWxJbnQgXTtcblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKCBzZWwgPT09IG51bGwgfHwgc2VsID09PSB1bmRlZmluZWQgfHwgc2VsID09PSAnJyApIHtcblx0XHRcdFx0Ly8gU2VsZWN0b3IgLSBub25lXG5cdFx0XHRcdHJldHVybiByb3dzO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIFNlbGVjdG9yIC0gZnVuY3Rpb25cblx0XHRcdGlmICggdHlwZW9mIHNlbCA9PT0gJ2Z1bmN0aW9uJyApIHtcblx0XHRcdFx0cmV0dXJuICQubWFwKCByb3dzLCBmdW5jdGlvbiAoaWR4KSB7XG5cdFx0XHRcdFx0dmFyIHJvdyA9IHNldHRpbmdzLmFvRGF0YVsgaWR4IF07XG5cdFx0XHRcdFx0cmV0dXJuIHNlbCggaWR4LCByb3cuX2FEYXRhLCByb3cublRyICkgPyBpZHggOiBudWxsO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gR2V0IG5vZGVzIGluIHRoZSBvcmRlciBmcm9tIHRoZSBgcm93c2AgYXJyYXkgd2l0aCBudWxsIHZhbHVlcyByZW1vdmVkXG5cdFx0XHR2YXIgbm9kZXMgPSBfcmVtb3ZlRW1wdHkoXG5cdFx0XHRcdF9wbHVja19vcmRlciggc2V0dGluZ3MuYW9EYXRhLCByb3dzLCAnblRyJyApXG5cdFx0XHQpO1xuXHRcblx0XHRcdC8vIFNlbGVjdG9yIC0gbm9kZVxuXHRcdFx0aWYgKCBzZWwubm9kZU5hbWUgKSB7XG5cdFx0XHRcdGlmICggc2VsLl9EVF9Sb3dJbmRleCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdHJldHVybiBbIHNlbC5fRFRfUm93SW5kZXggXTsgLy8gUHJvcGVydHkgYWRkZWQgYnkgRFQgZm9yIGZhc3QgbG9va3VwXG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSBpZiAoIHNlbC5fRFRfQ2VsbEluZGV4ICkge1xuXHRcdFx0XHRcdHJldHVybiBbIHNlbC5fRFRfQ2VsbEluZGV4LnJvdyBdO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2Uge1xuXHRcdFx0XHRcdHZhciBob3N0ID0gJChzZWwpLmNsb3Nlc3QoJypbZGF0YS1kdC1yb3ddJyk7XG5cdFx0XHRcdFx0cmV0dXJuIGhvc3QubGVuZ3RoID9cblx0XHRcdFx0XHRcdFsgaG9zdC5kYXRhKCdkdC1yb3cnKSBdIDpcblx0XHRcdFx0XHRcdFtdO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gSUQgc2VsZWN0b3IuIFdhbnQgdG8gYWx3YXlzIGJlIGFibGUgdG8gc2VsZWN0IHJvd3MgYnkgaWQsIHJlZ2FyZGxlc3Ncblx0XHRcdC8vIG9mIGlmIHRoZSB0ciBlbGVtZW50IGhhcyBiZWVuIGNyZWF0ZWQgb3Igbm90LCBzbyBjYW4ndCByZWx5IHVwb25cblx0XHRcdC8vIGpRdWVyeSBoZXJlIC0gaGVuY2UgYSBjdXN0b20gaW1wbGVtZW50YXRpb24uIFRoaXMgZG9lcyBub3QgbWF0Y2hcblx0XHRcdC8vIFNpenpsZSdzIGZhc3Qgc2VsZWN0b3Igb3IgSFRNTDQgLSBpbiBIVE1MNSB0aGUgSUQgY2FuIGJlIGFueXRoaW5nLFxuXHRcdFx0Ly8gYnV0IHRvIHNlbGVjdCBpdCB1c2luZyBhIENTUyBzZWxlY3RvciBlbmdpbmUgKGxpa2UgU2l6emxlIG9yXG5cdFx0XHQvLyBxdWVyeVNlbGVjdCkgaXQgd291bGQgbmVlZCB0byBuZWVkIHRvIGJlIGVzY2FwZWQgZm9yIHNvbWUgY2hhcmFjdGVycy5cblx0XHRcdC8vIERhdGFUYWJsZXMgc2ltcGxpZmllcyB0aGlzIGZvciByb3cgc2VsZWN0b3JzIHNpbmNlIHlvdSBjYW4gc2VsZWN0XG5cdFx0XHQvLyBvbmx5IGEgcm93LiBBICMgaW5kaWNhdGVzIGFuIGlkIGFueSBhbnl0aGluZyB0aGF0IGZvbGxvd3MgaXMgdGhlIGlkIC1cblx0XHRcdC8vIHVuZXNjYXBlZC5cblx0XHRcdGlmICggdHlwZW9mIHNlbCA9PT0gJ3N0cmluZycgJiYgc2VsLmNoYXJBdCgwKSA9PT0gJyMnICkge1xuXHRcdFx0XHQvLyBnZXQgcm93IGluZGV4IGZyb20gaWRcblx0XHRcdFx0dmFyIHJvd09iaiA9IHNldHRpbmdzLmFJZHNbIHNlbC5yZXBsYWNlKCAvXiMvLCAnJyApIF07XG5cdFx0XHRcdGlmICggcm93T2JqICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIFsgcm93T2JqLmlkeCBdO1xuXHRcdFx0XHR9XG5cdFxuXHRcdFx0XHQvLyBuZWVkIHRvIGZhbGwgdGhyb3VnaCB0byBqUXVlcnkgaW4gY2FzZSB0aGVyZSBpcyBET00gaWQgdGhhdFxuXHRcdFx0XHQvLyBtYXRjaGVzXG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gU2VsZWN0b3IgLSBqUXVlcnkgc2VsZWN0b3Igc3RyaW5nLCBhcnJheSBvZiBub2RlcyBvciBqUXVlcnkgb2JqZWN0L1xuXHRcdFx0Ly8gQXMgalF1ZXJ5J3MgLmZpbHRlcigpIGFsbG93cyBqUXVlcnkgb2JqZWN0cyB0byBiZSBwYXNzZWQgaW4gZmlsdGVyLFxuXHRcdFx0Ly8gaXQgYWxzbyBhbGxvd3MgYXJyYXlzLCBzbyB0aGlzIHdpbGwgY29wZSB3aXRoIGFsbCB0aHJlZSBvcHRpb25zXG5cdFx0XHRyZXR1cm4gJChub2Rlcylcblx0XHRcdFx0LmZpbHRlciggc2VsIClcblx0XHRcdFx0Lm1hcCggZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLl9EVF9Sb3dJbmRleDtcblx0XHRcdFx0fSApXG5cdFx0XHRcdC50b0FycmF5KCk7XG5cdFx0fTtcblx0XG5cdFx0cmV0dXJuIF9zZWxlY3Rvcl9ydW4oICdyb3cnLCBzZWxlY3RvciwgcnVuLCBzZXR0aW5ncywgb3B0cyApO1xuXHR9O1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXIoICdyb3dzKCknLCBmdW5jdGlvbiAoIHNlbGVjdG9yLCBvcHRzICkge1xuXHRcdC8vIGFyZ3VtZW50IHNoaWZ0aW5nXG5cdFx0aWYgKCBzZWxlY3RvciA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0c2VsZWN0b3IgPSAnJztcblx0XHR9XG5cdFx0ZWxzZSBpZiAoICQuaXNQbGFpbk9iamVjdCggc2VsZWN0b3IgKSApIHtcblx0XHRcdG9wdHMgPSBzZWxlY3Rvcjtcblx0XHRcdHNlbGVjdG9yID0gJyc7XG5cdFx0fVxuXHRcblx0XHRvcHRzID0gX3NlbGVjdG9yX29wdHMoIG9wdHMgKTtcblx0XG5cdFx0dmFyIGluc3QgPSB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0cmV0dXJuIF9fcm93X3NlbGVjdG9yKCBzZXR0aW5ncywgc2VsZWN0b3IsIG9wdHMgKTtcblx0XHR9LCAxICk7XG5cdFxuXHRcdC8vIFdhbnQgYXJndW1lbnQgc2hpZnRpbmcgaGVyZSBhbmQgaW4gX19yb3dfc2VsZWN0b3I/XG5cdFx0aW5zdC5zZWxlY3Rvci5yb3dzID0gc2VsZWN0b3I7XG5cdFx0aW5zdC5zZWxlY3Rvci5vcHRzID0gb3B0cztcblx0XG5cdFx0cmV0dXJuIGluc3Q7XG5cdH0gKTtcblx0XG5cdF9hcGlfcmVnaXN0ZXIoICdyb3dzKCkubm9kZXMoKScsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3JvdycsIGZ1bmN0aW9uICggc2V0dGluZ3MsIHJvdyApIHtcblx0XHRcdHJldHVybiBzZXR0aW5ncy5hb0RhdGFbIHJvdyBdLm5UciB8fCB1bmRlZmluZWQ7XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyKCAncm93cygpLmRhdGEoKScsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggdHJ1ZSwgJ3Jvd3MnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCByb3dzICkge1xuXHRcdFx0cmV0dXJuIF9wbHVja19vcmRlciggc2V0dGluZ3MuYW9EYXRhLCByb3dzLCAnX2FEYXRhJyApO1xuXHRcdH0sIDEgKTtcblx0fSApO1xuXHRcblx0X2FwaV9yZWdpc3RlclBsdXJhbCggJ3Jvd3MoKS5jYWNoZSgpJywgJ3JvdygpLmNhY2hlKCknLCBmdW5jdGlvbiAoIHR5cGUgKSB7XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICdyb3cnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCByb3cgKSB7XG5cdFx0XHR2YXIgciA9IHNldHRpbmdzLmFvRGF0YVsgcm93IF07XG5cdFx0XHRyZXR1cm4gdHlwZSA9PT0gJ3NlYXJjaCcgPyByLl9hRmlsdGVyRGF0YSA6IHIuX2FTb3J0RGF0YTtcblx0XHR9LCAxICk7XG5cdH0gKTtcblx0XG5cdF9hcGlfcmVnaXN0ZXJQbHVyYWwoICdyb3dzKCkuaW52YWxpZGF0ZSgpJywgJ3JvdygpLmludmFsaWRhdGUoKScsIGZ1bmN0aW9uICggc3JjICkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAncm93JywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93ICkge1xuXHRcdFx0X2ZuSW52YWxpZGF0ZSggc2V0dGluZ3MsIHJvdywgc3JjICk7XG5cdFx0fSApO1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAncm93cygpLmluZGV4ZXMoKScsICdyb3coKS5pbmRleCgpJywgZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAncm93JywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93ICkge1xuXHRcdFx0cmV0dXJuIHJvdztcblx0XHR9LCAxICk7XG5cdH0gKTtcblx0XG5cdF9hcGlfcmVnaXN0ZXJQbHVyYWwoICdyb3dzKCkuaWRzKCknLCAncm93KCkuaWQoKScsIGZ1bmN0aW9uICggaGFzaCApIHtcblx0XHR2YXIgYSA9IFtdO1xuXHRcdHZhciBjb250ZXh0ID0gdGhpcy5jb250ZXh0O1xuXHRcblx0XHQvLyBgaXRlcmF0b3JgIHdpbGwgZHJvcCB1bmRlZmluZWQgdmFsdWVzLCBidXQgaW4gdGhpcyBjYXNlIHdlIHdhbnQgdGhlbVxuXHRcdGZvciAoIHZhciBpPTAsIGllbj1jb250ZXh0Lmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0Zm9yICggdmFyIGo9MCwgamVuPXRoaXNbaV0ubGVuZ3RoIDsgajxqZW4gOyBqKysgKSB7XG5cdFx0XHRcdHZhciBpZCA9IGNvbnRleHRbaV0ucm93SWRGbiggY29udGV4dFtpXS5hb0RhdGFbIHRoaXNbaV1bal0gXS5fYURhdGEgKTtcblx0XHRcdFx0YS5wdXNoKCAoaGFzaCA9PT0gdHJ1ZSA/ICcjJyA6ICcnICkrIGlkICk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gbmV3IF9BcGkoIGNvbnRleHQsIGEgKTtcblx0fSApO1xuXHRcblx0X2FwaV9yZWdpc3RlclBsdXJhbCggJ3Jvd3MoKS5yZW1vdmUoKScsICdyb3coKS5yZW1vdmUoKScsIGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgdGhhdCA9IHRoaXM7XG5cdFxuXHRcdHRoaXMuaXRlcmF0b3IoICdyb3cnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCByb3csIHRoYXRJZHggKSB7XG5cdFx0XHR2YXIgZGF0YSA9IHNldHRpbmdzLmFvRGF0YTtcblx0XHRcdHZhciByb3dEYXRhID0gZGF0YVsgcm93IF07XG5cdFx0XHR2YXIgaSwgaWVuLCBqLCBqZW47XG5cdFx0XHR2YXIgbG9vcFJvdywgbG9vcENlbGxzO1xuXHRcblx0XHRcdGRhdGEuc3BsaWNlKCByb3csIDEgKTtcblx0XG5cdFx0XHQvLyBVcGRhdGUgdGhlIGNhY2hlZCBpbmRleGVzXG5cdFx0XHRmb3IgKCBpPTAsIGllbj1kYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHRsb29wUm93ID0gZGF0YVtpXTtcblx0XHRcdFx0bG9vcENlbGxzID0gbG9vcFJvdy5hbkNlbGxzO1xuXHRcblx0XHRcdFx0Ly8gUm93c1xuXHRcdFx0XHRpZiAoIGxvb3BSb3cublRyICE9PSBudWxsICkge1xuXHRcdFx0XHRcdGxvb3BSb3cublRyLl9EVF9Sb3dJbmRleCA9IGk7XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdC8vIENlbGxzXG5cdFx0XHRcdGlmICggbG9vcENlbGxzICE9PSBudWxsICkge1xuXHRcdFx0XHRcdGZvciAoIGo9MCwgamVuPWxvb3BDZWxscy5sZW5ndGggOyBqPGplbiA7IGorKyApIHtcblx0XHRcdFx0XHRcdGxvb3BDZWxsc1tqXS5fRFRfQ2VsbEluZGV4LnJvdyA9IGk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gRGVsZXRlIGZyb20gdGhlIGRpc3BsYXkgYXJyYXlzXG5cdFx0XHRfZm5EZWxldGVJbmRleCggc2V0dGluZ3MuYWlEaXNwbGF5TWFzdGVyLCByb3cgKTtcblx0XHRcdF9mbkRlbGV0ZUluZGV4KCBzZXR0aW5ncy5haURpc3BsYXksIHJvdyApO1xuXHRcdFx0X2ZuRGVsZXRlSW5kZXgoIHRoYXRbIHRoYXRJZHggXSwgcm93LCBmYWxzZSApOyAvLyBtYWludGFpbiBsb2NhbCBpbmRleGVzXG5cdFxuXHRcdFx0Ly8gRm9yIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcgdGFibGVzIC0gc3VidHJhY3QgdGhlIGRlbGV0ZWQgcm93IGZyb20gdGhlIGNvdW50XG5cdFx0XHRpZiAoIHNldHRpbmdzLl9pUmVjb3Jkc0Rpc3BsYXkgPiAwICkge1xuXHRcdFx0XHRzZXR0aW5ncy5faVJlY29yZHNEaXNwbGF5LS07XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gQ2hlY2sgZm9yIGFuICdvdmVyZmxvdycgdGhleSBjYXNlIGZvciBkaXNwbGF5aW5nIHRoZSB0YWJsZVxuXHRcdFx0X2ZuTGVuZ3RoT3ZlcmZsb3coIHNldHRpbmdzICk7XG5cdFxuXHRcdFx0Ly8gUmVtb3ZlIHRoZSByb3cncyBJRCByZWZlcmVuY2UgaWYgdGhlcmUgaXMgb25lXG5cdFx0XHR2YXIgaWQgPSBzZXR0aW5ncy5yb3dJZEZuKCByb3dEYXRhLl9hRGF0YSApO1xuXHRcdFx0aWYgKCBpZCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRkZWxldGUgc2V0dGluZ3MuYUlkc1sgaWQgXTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdFxuXHRcdHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7XG5cdFx0XHRmb3IgKCB2YXIgaT0wLCBpZW49c2V0dGluZ3MuYW9EYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHRzZXR0aW5ncy5hb0RhdGFbaV0uaWR4ID0gaTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdFxuXHRcdHJldHVybiB0aGlzO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ3Jvd3MuYWRkKCknLCBmdW5jdGlvbiAoIHJvd3MgKSB7XG5cdFx0dmFyIG5ld1Jvd3MgPSB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0XHR2YXIgcm93LCBpLCBpZW47XG5cdFx0XHRcdHZhciBvdXQgPSBbXTtcblx0XG5cdFx0XHRcdGZvciAoIGk9MCwgaWVuPXJvd3MubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0cm93ID0gcm93c1tpXTtcblx0XG5cdFx0XHRcdFx0aWYgKCByb3cubm9kZU5hbWUgJiYgcm93Lm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdUUicgKSB7XG5cdFx0XHRcdFx0XHRvdXQucHVzaCggX2ZuQWRkVHIoIHNldHRpbmdzLCByb3cgKVswXSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdG91dC5wdXNoKCBfZm5BZGREYXRhKCBzZXR0aW5ncywgcm93ICkgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdHJldHVybiBvdXQ7XG5cdFx0XHR9LCAxICk7XG5cdFxuXHRcdC8vIFJldHVybiBhbiBBcGkucm93cygpIGV4dGVuZGVkIGluc3RhbmNlLCBzbyByb3dzKCkubm9kZXMoKSBldGMgY2FuIGJlIHVzZWRcblx0XHR2YXIgbW9kUm93cyA9IHRoaXMucm93cyggLTEgKTtcblx0XHRtb2RSb3dzLnBvcCgpO1xuXHRcdCQubWVyZ2UoIG1vZFJvd3MsIG5ld1Jvd3MgKTtcblx0XG5cdFx0cmV0dXJuIG1vZFJvd3M7XG5cdH0gKTtcblx0XG5cdFxuXHRcblx0XG5cdFxuXHQvKipcblx0ICpcblx0ICovXG5cdF9hcGlfcmVnaXN0ZXIoICdyb3coKScsIGZ1bmN0aW9uICggc2VsZWN0b3IsIG9wdHMgKSB7XG5cdFx0cmV0dXJuIF9zZWxlY3Rvcl9maXJzdCggdGhpcy5yb3dzKCBzZWxlY3Rvciwgb3B0cyApICk7XG5cdH0gKTtcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyKCAncm93KCkuZGF0YSgpJywgZnVuY3Rpb24gKCBkYXRhICkge1xuXHRcdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cdFxuXHRcdGlmICggZGF0YSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0Ly8gR2V0XG5cdFx0XHRyZXR1cm4gY3R4Lmxlbmd0aCAmJiB0aGlzLmxlbmd0aCA/XG5cdFx0XHRcdGN0eFswXS5hb0RhdGFbIHRoaXNbMF0gXS5fYURhdGEgOlxuXHRcdFx0XHR1bmRlZmluZWQ7XG5cdFx0fVxuXHRcblx0XHQvLyBTZXRcblx0XHRjdHhbMF0uYW9EYXRhWyB0aGlzWzBdIF0uX2FEYXRhID0gZGF0YTtcblx0XG5cdFx0Ly8gQXV0b21hdGljYWxseSBpbnZhbGlkYXRlXG5cdFx0X2ZuSW52YWxpZGF0ZSggY3R4WzBdLCB0aGlzWzBdLCAnZGF0YScgKTtcblx0XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0gKTtcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyKCAncm93KCkubm9kZSgpJywgZnVuY3Rpb24gKCkge1xuXHRcdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cdFxuXHRcdHJldHVybiBjdHgubGVuZ3RoICYmIHRoaXMubGVuZ3RoID9cblx0XHRcdGN0eFswXS5hb0RhdGFbIHRoaXNbMF0gXS5uVHIgfHwgbnVsbCA6XG5cdFx0XHRudWxsO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ3Jvdy5hZGQoKScsIGZ1bmN0aW9uICggcm93ICkge1xuXHRcdC8vIEFsbG93IGEgalF1ZXJ5IG9iamVjdCB0byBiZSBwYXNzZWQgaW4gLSBvbmx5IGEgc2luZ2xlIHJvdyBpcyBhZGRlZCBmcm9tXG5cdFx0Ly8gaXQgdGhvdWdoIC0gdGhlIGZpcnN0IGVsZW1lbnQgaW4gdGhlIHNldFxuXHRcdGlmICggcm93IGluc3RhbmNlb2YgJCAmJiByb3cubGVuZ3RoICkge1xuXHRcdFx0cm93ID0gcm93WzBdO1xuXHRcdH1cblx0XG5cdFx0dmFyIHJvd3MgPSB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0aWYgKCByb3cubm9kZU5hbWUgJiYgcm93Lm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgPT09ICdUUicgKSB7XG5cdFx0XHRcdHJldHVybiBfZm5BZGRUciggc2V0dGluZ3MsIHJvdyApWzBdO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIF9mbkFkZERhdGEoIHNldHRpbmdzLCByb3cgKTtcblx0XHR9ICk7XG5cdFxuXHRcdC8vIFJldHVybiBhbiBBcGkucm93cygpIGV4dGVuZGVkIGluc3RhbmNlLCB3aXRoIHRoZSBuZXdseSBhZGRlZCByb3cgc2VsZWN0ZWRcblx0XHRyZXR1cm4gdGhpcy5yb3coIHJvd3NbMF0gKTtcblx0fSApO1xuXHRcblx0XG5cdFxuXHR2YXIgX19kZXRhaWxzX2FkZCA9IGZ1bmN0aW9uICggY3R4LCByb3csIGRhdGEsIGtsYXNzIClcblx0e1xuXHRcdC8vIENvbnZlcnQgdG8gYXJyYXkgb2YgVFIgZWxlbWVudHNcblx0XHR2YXIgcm93cyA9IFtdO1xuXHRcdHZhciBhZGRSb3cgPSBmdW5jdGlvbiAoIHIsIGsgKSB7XG5cdFx0XHQvLyBSZWN1cnNpb24gdG8gYWxsb3cgZm9yIGFycmF5cyBvZiBqUXVlcnkgb2JqZWN0c1xuXHRcdFx0aWYgKCAkLmlzQXJyYXkoIHIgKSB8fCByIGluc3RhbmNlb2YgJCApIHtcblx0XHRcdFx0Zm9yICggdmFyIGk9MCwgaWVuPXIubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0YWRkUm93KCByW2ldLCBrICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIElmIHdlIGdldCBhIFRSIGVsZW1lbnQsIHRoZW4ganVzdCBhZGQgaXQgZGlyZWN0bHkgLSB1cCB0byB0aGUgZGV2XG5cdFx0XHQvLyB0byBhZGQgdGhlIGNvcnJlY3QgbnVtYmVyIG9mIGNvbHVtbnMgZXRjXG5cdFx0XHRpZiAoIHIubm9kZU5hbWUgJiYgci5ub2RlTmFtZS50b0xvd2VyQ2FzZSgpID09PSAndHInICkge1xuXHRcdFx0XHRyb3dzLnB1c2goIHIgKTtcblx0XHRcdH1cblx0XHRcdGVsc2Uge1xuXHRcdFx0XHQvLyBPdGhlcndpc2UgY3JlYXRlIGEgcm93IHdpdGggYSB3cmFwcGVyXG5cdFx0XHRcdHZhciBjcmVhdGVkID0gJCgnPHRyPjx0ZC8+PC90cj4nKS5hZGRDbGFzcyggayApO1xuXHRcdFx0XHQkKCd0ZCcsIGNyZWF0ZWQpXG5cdFx0XHRcdFx0LmFkZENsYXNzKCBrIClcblx0XHRcdFx0XHQuaHRtbCggciApXG5cdFx0XHRcdFx0WzBdLmNvbFNwYW4gPSBfZm5WaXNibGVDb2x1bW5zKCBjdHggKTtcblx0XG5cdFx0XHRcdHJvd3MucHVzaCggY3JlYXRlZFswXSApO1xuXHRcdFx0fVxuXHRcdH07XG5cdFxuXHRcdGFkZFJvdyggZGF0YSwga2xhc3MgKTtcblx0XG5cdFx0aWYgKCByb3cuX2RldGFpbHMgKSB7XG5cdFx0XHRyb3cuX2RldGFpbHMuZGV0YWNoKCk7XG5cdFx0fVxuXHRcblx0XHRyb3cuX2RldGFpbHMgPSAkKHJvd3MpO1xuXHRcblx0XHQvLyBJZiB0aGUgY2hpbGRyZW4gd2VyZSBhbHJlYWR5IHNob3duLCB0aGF0IHN0YXRlIHNob3VsZCBiZSByZXRhaW5lZFxuXHRcdGlmICggcm93Ll9kZXRhaWxzU2hvdyApIHtcblx0XHRcdHJvdy5fZGV0YWlscy5pbnNlcnRBZnRlciggcm93Lm5UciApO1xuXHRcdH1cblx0fTtcblx0XG5cdFxuXHR2YXIgX19kZXRhaWxzX3JlbW92ZSA9IGZ1bmN0aW9uICggYXBpLCBpZHggKVxuXHR7XG5cdFx0dmFyIGN0eCA9IGFwaS5jb250ZXh0O1xuXHRcblx0XHRpZiAoIGN0eC5sZW5ndGggKSB7XG5cdFx0XHR2YXIgcm93ID0gY3R4WzBdLmFvRGF0YVsgaWR4ICE9PSB1bmRlZmluZWQgPyBpZHggOiBhcGlbMF0gXTtcblx0XG5cdFx0XHRpZiAoIHJvdyAmJiByb3cuX2RldGFpbHMgKSB7XG5cdFx0XHRcdHJvdy5fZGV0YWlscy5yZW1vdmUoKTtcblx0XG5cdFx0XHRcdHJvdy5fZGV0YWlsc1Nob3cgPSB1bmRlZmluZWQ7XG5cdFx0XHRcdHJvdy5fZGV0YWlscyA9IHVuZGVmaW5lZDtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cdFxuXHRcblx0dmFyIF9fZGV0YWlsc19kaXNwbGF5ID0gZnVuY3Rpb24gKCBhcGksIHNob3cgKSB7XG5cdFx0dmFyIGN0eCA9IGFwaS5jb250ZXh0O1xuXHRcblx0XHRpZiAoIGN0eC5sZW5ndGggJiYgYXBpLmxlbmd0aCApIHtcblx0XHRcdHZhciByb3cgPSBjdHhbMF0uYW9EYXRhWyBhcGlbMF0gXTtcblx0XG5cdFx0XHRpZiAoIHJvdy5fZGV0YWlscyApIHtcblx0XHRcdFx0cm93Ll9kZXRhaWxzU2hvdyA9IHNob3c7XG5cdFxuXHRcdFx0XHRpZiAoIHNob3cgKSB7XG5cdFx0XHRcdFx0cm93Ll9kZXRhaWxzLmluc2VydEFmdGVyKCByb3cublRyICk7XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0cm93Ll9kZXRhaWxzLmRldGFjaCgpO1xuXHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRfX2RldGFpbHNfZXZlbnRzKCBjdHhbMF0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cdFxuXHRcblx0dmFyIF9fZGV0YWlsc19ldmVudHMgPSBmdW5jdGlvbiAoIHNldHRpbmdzIClcblx0e1xuXHRcdHZhciBhcGkgPSBuZXcgX0FwaSggc2V0dGluZ3MgKTtcblx0XHR2YXIgbmFtZXNwYWNlID0gJy5kdC5EVF9kZXRhaWxzJztcblx0XHR2YXIgZHJhd0V2ZW50ID0gJ2RyYXcnK25hbWVzcGFjZTtcblx0XHR2YXIgY29sdmlzRXZlbnQgPSAnY29sdW1uLXZpc2liaWxpdHknK25hbWVzcGFjZTtcblx0XHR2YXIgZGVzdHJveUV2ZW50ID0gJ2Rlc3Ryb3knK25hbWVzcGFjZTtcblx0XHR2YXIgZGF0YSA9IHNldHRpbmdzLmFvRGF0YTtcblx0XG5cdFx0YXBpLm9mZiggZHJhd0V2ZW50ICsnICcrIGNvbHZpc0V2ZW50ICsnICcrIGRlc3Ryb3lFdmVudCApO1xuXHRcblx0XHRpZiAoIF9wbHVjayggZGF0YSwgJ19kZXRhaWxzJyApLmxlbmd0aCA+IDAgKSB7XG5cdFx0XHQvLyBPbiBlYWNoIGRyYXcsIGluc2VydCB0aGUgcmVxdWlyZWQgZWxlbWVudHMgaW50byB0aGUgZG9jdW1lbnRcblx0XHRcdGFwaS5vbiggZHJhd0V2ZW50LCBmdW5jdGlvbiAoIGUsIGN0eCApIHtcblx0XHRcdFx0aWYgKCBzZXR0aW5ncyAhPT0gY3R4ICkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0YXBpLnJvd3MoIHtwYWdlOidjdXJyZW50J30gKS5lcSgwKS5lYWNoKCBmdW5jdGlvbiAoaWR4KSB7XG5cdFx0XHRcdFx0Ly8gSW50ZXJuYWwgZGF0YSBncmFiXG5cdFx0XHRcdFx0dmFyIHJvdyA9IGRhdGFbIGlkeCBdO1xuXHRcblx0XHRcdFx0XHRpZiAoIHJvdy5fZGV0YWlsc1Nob3cgKSB7XG5cdFx0XHRcdFx0XHRyb3cuX2RldGFpbHMuaW5zZXJ0QWZ0ZXIoIHJvdy5uVHIgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0gKTtcblx0XHRcdH0gKTtcblx0XG5cdFx0XHQvLyBDb2x1bW4gdmlzaWJpbGl0eSBjaGFuZ2UgLSB1cGRhdGUgdGhlIGNvbHNwYW5cblx0XHRcdGFwaS5vbiggY29sdmlzRXZlbnQsIGZ1bmN0aW9uICggZSwgY3R4LCBpZHgsIHZpcyApIHtcblx0XHRcdFx0aWYgKCBzZXR0aW5ncyAhPT0gY3R4ICkge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXHRcblx0XHRcdFx0Ly8gVXBkYXRlIHRoZSBjb2xzcGFuIGZvciB0aGUgZGV0YWlscyByb3dzIChub3RlLCBvbmx5IGlmIGl0IGFscmVhZHkgaGFzXG5cdFx0XHRcdC8vIGEgY29sc3Bhbilcblx0XHRcdFx0dmFyIHJvdywgdmlzaWJsZSA9IF9mblZpc2JsZUNvbHVtbnMoIGN0eCApO1xuXHRcblx0XHRcdFx0Zm9yICggdmFyIGk9MCwgaWVuPWRhdGEubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0cm93ID0gZGF0YVtpXTtcblx0XG5cdFx0XHRcdFx0aWYgKCByb3cuX2RldGFpbHMgKSB7XG5cdFx0XHRcdFx0XHRyb3cuX2RldGFpbHMuY2hpbGRyZW4oJ3RkW2NvbHNwYW5dJykuYXR0cignY29sc3BhbicsIHZpc2libGUgKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gKTtcblx0XG5cdFx0XHQvLyBUYWJsZSBkZXN0cm95ZWQgLSBudWtlIGFueSBjaGlsZCByb3dzXG5cdFx0XHRhcGkub24oIGRlc3Ryb3lFdmVudCwgZnVuY3Rpb24gKCBlLCBjdHggKSB7XG5cdFx0XHRcdGlmICggc2V0dGluZ3MgIT09IGN0eCApIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdGZvciAoIHZhciBpPTAsIGllbj1kYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHRcdGlmICggZGF0YVtpXS5fZGV0YWlscyApIHtcblx0XHRcdFx0XHRcdF9fZGV0YWlsc19yZW1vdmUoIGFwaSwgaSApO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fSApO1xuXHRcdH1cblx0fTtcblx0XG5cdC8vIFN0cmluZ3MgZm9yIHRoZSBtZXRob2QgbmFtZXMgdG8gaGVscCBtaW5pZmljYXRpb25cblx0dmFyIF9lbXAgPSAnJztcblx0dmFyIF9jaGlsZF9vYmogPSBfZW1wKydyb3coKS5jaGlsZCc7XG5cdHZhciBfY2hpbGRfbXRoID0gX2NoaWxkX29iaisnKCknO1xuXHRcblx0Ly8gZGF0YSBjYW4gYmU6XG5cdC8vICB0clxuXHQvLyAgc3RyaW5nXG5cdC8vICBqUXVlcnkgb3IgYXJyYXkgb2YgYW55IG9mIHRoZSBhYm92ZVxuXHRfYXBpX3JlZ2lzdGVyKCBfY2hpbGRfbXRoLCBmdW5jdGlvbiAoIGRhdGEsIGtsYXNzICkge1xuXHRcdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cdFxuXHRcdGlmICggZGF0YSA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0Ly8gZ2V0XG5cdFx0XHRyZXR1cm4gY3R4Lmxlbmd0aCAmJiB0aGlzLmxlbmd0aCA/XG5cdFx0XHRcdGN0eFswXS5hb0RhdGFbIHRoaXNbMF0gXS5fZGV0YWlscyA6XG5cdFx0XHRcdHVuZGVmaW5lZDtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIGRhdGEgPT09IHRydWUgKSB7XG5cdFx0XHQvLyBzaG93XG5cdFx0XHR0aGlzLmNoaWxkLnNob3coKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoIGRhdGEgPT09IGZhbHNlICkge1xuXHRcdFx0Ly8gcmVtb3ZlXG5cdFx0XHRfX2RldGFpbHNfcmVtb3ZlKCB0aGlzICk7XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCBjdHgubGVuZ3RoICYmIHRoaXMubGVuZ3RoICkge1xuXHRcdFx0Ly8gc2V0XG5cdFx0XHRfX2RldGFpbHNfYWRkKCBjdHhbMF0sIGN0eFswXS5hb0RhdGFbIHRoaXNbMF0gXSwgZGF0YSwga2xhc3MgKTtcblx0XHR9XG5cdFxuXHRcdHJldHVybiB0aGlzO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggW1xuXHRcdF9jaGlsZF9vYmorJy5zaG93KCknLFxuXHRcdF9jaGlsZF9tdGgrJy5zaG93KCknIC8vIG9ubHkgd2hlbiBgY2hpbGQoKWAgd2FzIGNhbGxlZCB3aXRoIHBhcmFtZXRlcnMgKHdpdGhvdXRcblx0XSwgZnVuY3Rpb24gKCBzaG93ICkgeyAgIC8vIGl0IHJldHVybnMgYW4gb2JqZWN0IGFuZCB0aGlzIG1ldGhvZCBpcyBub3QgZXhlY3V0ZWQpXG5cdFx0X19kZXRhaWxzX2Rpc3BsYXkoIHRoaXMsIHRydWUgKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXIoIFtcblx0XHRfY2hpbGRfb2JqKycuaGlkZSgpJyxcblx0XHRfY2hpbGRfbXRoKycuaGlkZSgpJyAvLyBvbmx5IHdoZW4gYGNoaWxkKClgIHdhcyBjYWxsZWQgd2l0aCBwYXJhbWV0ZXJzICh3aXRob3V0XG5cdF0sIGZ1bmN0aW9uICgpIHsgICAgICAgICAvLyBpdCByZXR1cm5zIGFuIG9iamVjdCBhbmQgdGhpcyBtZXRob2QgaXMgbm90IGV4ZWN1dGVkKVxuXHRcdF9fZGV0YWlsc19kaXNwbGF5KCB0aGlzLCBmYWxzZSApO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggW1xuXHRcdF9jaGlsZF9vYmorJy5yZW1vdmUoKScsXG5cdFx0X2NoaWxkX210aCsnLnJlbW92ZSgpJyAvLyBvbmx5IHdoZW4gYGNoaWxkKClgIHdhcyBjYWxsZWQgd2l0aCBwYXJhbWV0ZXJzICh3aXRob3V0XG5cdF0sIGZ1bmN0aW9uICgpIHsgICAgICAgICAgIC8vIGl0IHJldHVybnMgYW4gb2JqZWN0IGFuZCB0aGlzIG1ldGhvZCBpcyBub3QgZXhlY3V0ZWQpXG5cdFx0X19kZXRhaWxzX3JlbW92ZSggdGhpcyApO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggX2NoaWxkX29iaisnLmlzU2hvd24oKScsIGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgY3R4ID0gdGhpcy5jb250ZXh0O1xuXHRcblx0XHRpZiAoIGN0eC5sZW5ndGggJiYgdGhpcy5sZW5ndGggKSB7XG5cdFx0XHQvLyBfZGV0YWlsc1Nob3duIGFzIGZhbHNlIG9yIHVuZGVmaW5lZCB3aWxsIGZhbGwgdGhyb3VnaCB0byByZXR1cm4gZmFsc2Vcblx0XHRcdHJldHVybiBjdHhbMF0uYW9EYXRhWyB0aGlzWzBdIF0uX2RldGFpbHNTaG93IHx8IGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH0gKTtcblx0XG5cdFxuXHRcblx0LyogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqICogKiAqXG5cdCAqIENvbHVtbnNcblx0ICpcblx0ICoge2ludGVnZXJ9ICAgICAgICAgICAtIGNvbHVtbiBpbmRleCAoPj0wIGNvdW50IGZyb20gbGVmdCwgPDAgY291bnQgZnJvbSByaWdodClcblx0ICogXCJ7aW50ZWdlcn06dmlzSWR4XCIgIC0gdmlzaWJsZSBjb2x1bW4gaW5kZXggKGkuZS4gdHJhbnNsYXRlIHRvIGNvbHVtbiBpbmRleCkgICg+PTAgY291bnQgZnJvbSBsZWZ0LCA8MCBjb3VudCBmcm9tIHJpZ2h0KVxuXHQgKiBcIntpbnRlZ2VyfTp2aXNpYmxlXCIgLSBhbGlhcyBmb3Ige2ludGVnZXJ9OnZpc0lkeCAgKD49MCBjb3VudCBmcm9tIGxlZnQsIDwwIGNvdW50IGZyb20gcmlnaHQpXG5cdCAqIFwie3N0cmluZ306bmFtZVwiICAgICAtIGNvbHVtbiBuYW1lXG5cdCAqIFwie3N0cmluZ31cIiAgICAgICAgICAtIGpRdWVyeSBzZWxlY3RvciBvbiBjb2x1bW4gaGVhZGVyIG5vZGVzXG5cdCAqXG5cdCAqL1xuXHRcblx0Ly8gY2FuIGJlIGFuIGFycmF5IG9mIHRoZXNlIGl0ZW1zLCBjb21tYSBzZXBhcmF0ZWQgbGlzdCwgb3IgYW4gYXJyYXkgb2YgY29tbWFcblx0Ly8gc2VwYXJhdGVkIGxpc3RzXG5cdFxuXHR2YXIgX19yZV9jb2x1bW5fc2VsZWN0b3IgPSAvXihbXjpdKyk6KG5hbWV8dmlzSWR4fHZpc2libGUpJC87XG5cdFxuXHRcblx0Ly8gcjEgYW5kIHIyIGFyZSByZWR1bmRhbnQgLSBidXQgaXQgbWVhbnMgdGhhdCB0aGUgcGFyYW1ldGVycyBtYXRjaCBmb3IgdGhlXG5cdC8vIGl0ZXJhdG9yIGNhbGxiYWNrIGluIGNvbHVtbnMoKS5kYXRhKClcblx0dmFyIF9fY29sdW1uRGF0YSA9IGZ1bmN0aW9uICggc2V0dGluZ3MsIGNvbHVtbiwgcjEsIHIyLCByb3dzICkge1xuXHRcdHZhciBhID0gW107XG5cdFx0Zm9yICggdmFyIHJvdz0wLCBpZW49cm93cy5sZW5ndGggOyByb3c8aWVuIDsgcm93KysgKSB7XG5cdFx0XHRhLnB1c2goIF9mbkdldENlbGxEYXRhKCBzZXR0aW5ncywgcm93c1tyb3ddLCBjb2x1bW4gKSApO1xuXHRcdH1cblx0XHRyZXR1cm4gYTtcblx0fTtcblx0XG5cdFxuXHR2YXIgX19jb2x1bW5fc2VsZWN0b3IgPSBmdW5jdGlvbiAoIHNldHRpbmdzLCBzZWxlY3Rvciwgb3B0cyApXG5cdHtcblx0XHR2YXJcblx0XHRcdGNvbHVtbnMgPSBzZXR0aW5ncy5hb0NvbHVtbnMsXG5cdFx0XHRuYW1lcyA9IF9wbHVjayggY29sdW1ucywgJ3NOYW1lJyApLFxuXHRcdFx0bm9kZXMgPSBfcGx1Y2soIGNvbHVtbnMsICduVGgnICk7XG5cdFxuXHRcdHZhciBydW4gPSBmdW5jdGlvbiAoIHMgKSB7XG5cdFx0XHR2YXIgc2VsSW50ID0gX2ludFZhbCggcyApO1xuXHRcblx0XHRcdC8vIFNlbGVjdG9yIC0gYWxsXG5cdFx0XHRpZiAoIHMgPT09ICcnICkge1xuXHRcdFx0XHRyZXR1cm4gX3JhbmdlKCBjb2x1bW5zLmxlbmd0aCApO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIFNlbGVjdG9yIC0gaW5kZXhcblx0XHRcdGlmICggc2VsSW50ICE9PSBudWxsICkge1xuXHRcdFx0XHRyZXR1cm4gWyBzZWxJbnQgPj0gMCA/XG5cdFx0XHRcdFx0c2VsSW50IDogLy8gQ291bnQgZnJvbSBsZWZ0XG5cdFx0XHRcdFx0Y29sdW1ucy5sZW5ndGggKyBzZWxJbnQgLy8gQ291bnQgZnJvbSByaWdodCAoKyBiZWNhdXNlIGl0cyBhIG5lZ2F0aXZlIHZhbHVlKVxuXHRcdFx0XHRdO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIFNlbGVjdG9yID0gZnVuY3Rpb25cblx0XHRcdGlmICggdHlwZW9mIHMgPT09ICdmdW5jdGlvbicgKSB7XG5cdFx0XHRcdHZhciByb3dzID0gX3NlbGVjdG9yX3Jvd19pbmRleGVzKCBzZXR0aW5ncywgb3B0cyApO1xuXHRcblx0XHRcdFx0cmV0dXJuICQubWFwKCBjb2x1bW5zLCBmdW5jdGlvbiAoY29sLCBpZHgpIHtcblx0XHRcdFx0XHRyZXR1cm4gcyhcblx0XHRcdFx0XHRcdFx0aWR4LFxuXHRcdFx0XHRcdFx0XHRfX2NvbHVtbkRhdGEoIHNldHRpbmdzLCBpZHgsIDAsIDAsIHJvd3MgKSxcblx0XHRcdFx0XHRcdFx0bm9kZXNbIGlkeCBdXG5cdFx0XHRcdFx0XHQpID8gaWR4IDogbnVsbDtcblx0XHRcdFx0fSApO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIGpRdWVyeSBvciBzdHJpbmcgc2VsZWN0b3Jcblx0XHRcdHZhciBtYXRjaCA9IHR5cGVvZiBzID09PSAnc3RyaW5nJyA/XG5cdFx0XHRcdHMubWF0Y2goIF9fcmVfY29sdW1uX3NlbGVjdG9yICkgOlxuXHRcdFx0XHQnJztcblx0XG5cdFx0XHRpZiAoIG1hdGNoICkge1xuXHRcdFx0XHRzd2l0Y2goIG1hdGNoWzJdICkge1xuXHRcdFx0XHRcdGNhc2UgJ3Zpc0lkeCc6XG5cdFx0XHRcdFx0Y2FzZSAndmlzaWJsZSc6XG5cdFx0XHRcdFx0XHR2YXIgaWR4ID0gcGFyc2VJbnQoIG1hdGNoWzFdLCAxMCApO1xuXHRcdFx0XHRcdFx0Ly8gVmlzaWJsZSBpbmRleCBnaXZlbiwgY29udmVydCB0byBjb2x1bW4gaW5kZXhcblx0XHRcdFx0XHRcdGlmICggaWR4IDwgMCApIHtcblx0XHRcdFx0XHRcdFx0Ly8gQ291bnRpbmcgZnJvbSB0aGUgcmlnaHRcblx0XHRcdFx0XHRcdFx0dmFyIHZpc0NvbHVtbnMgPSAkLm1hcCggY29sdW1ucywgZnVuY3Rpb24gKGNvbCxpKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuIGNvbC5iVmlzaWJsZSA/IGkgOiBudWxsO1xuXHRcdFx0XHRcdFx0XHR9ICk7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBbIHZpc0NvbHVtbnNbIHZpc0NvbHVtbnMubGVuZ3RoICsgaWR4IF0gXTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdC8vIENvdW50aW5nIGZyb20gdGhlIGxlZnRcblx0XHRcdFx0XHRcdHJldHVybiBbIF9mblZpc2libGVUb0NvbHVtbkluZGV4KCBzZXR0aW5ncywgaWR4ICkgXTtcblx0XG5cdFx0XHRcdFx0Y2FzZSAnbmFtZSc6XG5cdFx0XHRcdFx0XHQvLyBtYXRjaCBieSBuYW1lLiBgbmFtZXNgIGlzIGNvbHVtbiBpbmRleCBjb21wbGV0ZSBhbmQgaW4gb3JkZXJcblx0XHRcdFx0XHRcdHJldHVybiAkLm1hcCggbmFtZXMsIGZ1bmN0aW9uIChuYW1lLCBpKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBuYW1lID09PSBtYXRjaFsxXSA/IGkgOiBudWxsO1xuXHRcdFx0XHRcdFx0fSApO1xuXHRcblx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0cmV0dXJuIFtdO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gQ2VsbCBpbiB0aGUgdGFibGUgYm9keVxuXHRcdFx0aWYgKCBzLm5vZGVOYW1lICYmIHMuX0RUX0NlbGxJbmRleCApIHtcblx0XHRcdFx0cmV0dXJuIFsgcy5fRFRfQ2VsbEluZGV4LmNvbHVtbiBdO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIGpRdWVyeSBzZWxlY3RvciBvbiB0aGUgVEggZWxlbWVudHMgZm9yIHRoZSBjb2x1bW5zXG5cdFx0XHR2YXIganFSZXN1bHQgPSAkKCBub2RlcyApXG5cdFx0XHRcdC5maWx0ZXIoIHMgKVxuXHRcdFx0XHQubWFwKCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0cmV0dXJuICQuaW5BcnJheSggdGhpcywgbm9kZXMgKTsgLy8gYG5vZGVzYCBpcyBjb2x1bW4gaW5kZXggY29tcGxldGUgYW5kIGluIG9yZGVyXG5cdFx0XHRcdH0gKVxuXHRcdFx0XHQudG9BcnJheSgpO1xuXHRcblx0XHRcdGlmICgganFSZXN1bHQubGVuZ3RoIHx8ICEgcy5ub2RlTmFtZSApIHtcblx0XHRcdFx0cmV0dXJuIGpxUmVzdWx0O1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIE90aGVyd2lzZSBhIG5vZGUgd2hpY2ggbWlnaHQgaGF2ZSBhIGBkdC1jb2x1bW5gIGRhdGEgYXR0cmlidXRlLCBvciBiZVxuXHRcdFx0Ly8gYSBjaGlsZCBvciBzdWNoIGFuIGVsZW1lbnRcblx0XHRcdHZhciBob3N0ID0gJChzKS5jbG9zZXN0KCcqW2RhdGEtZHQtY29sdW1uXScpO1xuXHRcdFx0cmV0dXJuIGhvc3QubGVuZ3RoID9cblx0XHRcdFx0WyBob3N0LmRhdGEoJ2R0LWNvbHVtbicpIF0gOlxuXHRcdFx0XHRbXTtcblx0XHR9O1xuXHRcblx0XHRyZXR1cm4gX3NlbGVjdG9yX3J1biggJ2NvbHVtbicsIHNlbGVjdG9yLCBydW4sIHNldHRpbmdzLCBvcHRzICk7XG5cdH07XG5cdFxuXHRcblx0dmFyIF9fc2V0Q29sdW1uVmlzID0gZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uLCB2aXMgKSB7XG5cdFx0dmFyXG5cdFx0XHRjb2xzID0gc2V0dGluZ3MuYW9Db2x1bW5zLFxuXHRcdFx0Y29sICA9IGNvbHNbIGNvbHVtbiBdLFxuXHRcdFx0ZGF0YSA9IHNldHRpbmdzLmFvRGF0YSxcblx0XHRcdHJvdywgY2VsbHMsIGksIGllbiwgdHI7XG5cdFxuXHRcdC8vIEdldFxuXHRcdGlmICggdmlzID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRyZXR1cm4gY29sLmJWaXNpYmxlO1xuXHRcdH1cblx0XG5cdFx0Ly8gU2V0XG5cdFx0Ly8gTm8gY2hhbmdlXG5cdFx0aWYgKCBjb2wuYlZpc2libGUgPT09IHZpcyApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cdFxuXHRcdGlmICggdmlzICkge1xuXHRcdFx0Ly8gSW5zZXJ0IGNvbHVtblxuXHRcdFx0Ly8gTmVlZCB0byBkZWNpZGUgaWYgd2Ugc2hvdWxkIHVzZSBhcHBlbmRDaGlsZCBvciBpbnNlcnRCZWZvcmVcblx0XHRcdHZhciBpbnNlcnRCZWZvcmUgPSAkLmluQXJyYXkoIHRydWUsIF9wbHVjayhjb2xzLCAnYlZpc2libGUnKSwgY29sdW1uKzEgKTtcblx0XG5cdFx0XHRmb3IgKCBpPTAsIGllbj1kYXRhLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdFx0XHR0ciA9IGRhdGFbaV0ublRyO1xuXHRcdFx0XHRjZWxscyA9IGRhdGFbaV0uYW5DZWxscztcblx0XG5cdFx0XHRcdGlmICggdHIgKSB7XG5cdFx0XHRcdFx0Ly8gaW5zZXJ0QmVmb3JlIGNhbiBhY3QgbGlrZSBhcHBlbmRDaGlsZCBpZiAybmQgYXJnIGlzIG51bGxcblx0XHRcdFx0XHR0ci5pbnNlcnRCZWZvcmUoIGNlbGxzWyBjb2x1bW4gXSwgY2VsbHNbIGluc2VydEJlZm9yZSBdIHx8IG51bGwgKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdC8vIFJlbW92ZSBjb2x1bW5cblx0XHRcdCQoIF9wbHVjayggc2V0dGluZ3MuYW9EYXRhLCAnYW5DZWxscycsIGNvbHVtbiApICkuZGV0YWNoKCk7XG5cdFx0fVxuXHRcblx0XHQvLyBDb21tb24gYWN0aW9uc1xuXHRcdGNvbC5iVmlzaWJsZSA9IHZpcztcblx0XHRfZm5EcmF3SGVhZCggc2V0dGluZ3MsIHNldHRpbmdzLmFvSGVhZGVyICk7XG5cdFx0X2ZuRHJhd0hlYWQoIHNldHRpbmdzLCBzZXR0aW5ncy5hb0Zvb3RlciApO1xuXHRcblx0XHRfZm5TYXZlU3RhdGUoIHNldHRpbmdzICk7XG5cdH07XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ2NvbHVtbnMoKScsIGZ1bmN0aW9uICggc2VsZWN0b3IsIG9wdHMgKSB7XG5cdFx0Ly8gYXJndW1lbnQgc2hpZnRpbmdcblx0XHRpZiAoIHNlbGVjdG9yID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRzZWxlY3RvciA9ICcnO1xuXHRcdH1cblx0XHRlbHNlIGlmICggJC5pc1BsYWluT2JqZWN0KCBzZWxlY3RvciApICkge1xuXHRcdFx0b3B0cyA9IHNlbGVjdG9yO1xuXHRcdFx0c2VsZWN0b3IgPSAnJztcblx0XHR9XG5cdFxuXHRcdG9wdHMgPSBfc2VsZWN0b3Jfb3B0cyggb3B0cyApO1xuXHRcblx0XHR2YXIgaW5zdCA9IHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7XG5cdFx0XHRyZXR1cm4gX19jb2x1bW5fc2VsZWN0b3IoIHNldHRpbmdzLCBzZWxlY3Rvciwgb3B0cyApO1xuXHRcdH0sIDEgKTtcblx0XG5cdFx0Ly8gV2FudCBhcmd1bWVudCBzaGlmdGluZyBoZXJlIGFuZCBpbiBfcm93X3NlbGVjdG9yP1xuXHRcdGluc3Quc2VsZWN0b3IuY29scyA9IHNlbGVjdG9yO1xuXHRcdGluc3Quc2VsZWN0b3Iub3B0cyA9IG9wdHM7XG5cdFxuXHRcdHJldHVybiBpbnN0O1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmhlYWRlcigpJywgJ2NvbHVtbigpLmhlYWRlcigpJywgZnVuY3Rpb24gKCBzZWxlY3Rvciwgb3B0cyApIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ2NvbHVtbicsIGZ1bmN0aW9uICggc2V0dGluZ3MsIGNvbHVtbiApIHtcblx0XHRcdHJldHVybiBzZXR0aW5ncy5hb0NvbHVtbnNbY29sdW1uXS5uVGg7XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmZvb3RlcigpJywgJ2NvbHVtbigpLmZvb3RlcigpJywgZnVuY3Rpb24gKCBzZWxlY3Rvciwgb3B0cyApIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ2NvbHVtbicsIGZ1bmN0aW9uICggc2V0dGluZ3MsIGNvbHVtbiApIHtcblx0XHRcdHJldHVybiBzZXR0aW5ncy5hb0NvbHVtbnNbY29sdW1uXS5uVGY7XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmRhdGEoKScsICdjb2x1bW4oKS5kYXRhKCknLCBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjb2x1bW4tcm93cycsIF9fY29sdW1uRGF0YSwgMSApO1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmRhdGFTcmMoKScsICdjb2x1bW4oKS5kYXRhU3JjKCknLCBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjb2x1bW4nLCBmdW5jdGlvbiAoIHNldHRpbmdzLCBjb2x1bW4gKSB7XG5cdFx0XHRyZXR1cm4gc2V0dGluZ3MuYW9Db2x1bW5zW2NvbHVtbl0ubURhdGE7XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmNhY2hlKCknLCAnY29sdW1uKCkuY2FjaGUoKScsIGZ1bmN0aW9uICggdHlwZSApIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ2NvbHVtbi1yb3dzJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uLCBpLCBqLCByb3dzICkge1xuXHRcdFx0cmV0dXJuIF9wbHVja19vcmRlciggc2V0dGluZ3MuYW9EYXRhLCByb3dzLFxuXHRcdFx0XHR0eXBlID09PSAnc2VhcmNoJyA/ICdfYUZpbHRlckRhdGEnIDogJ19hU29ydERhdGEnLCBjb2x1bW5cblx0XHRcdCk7XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLm5vZGVzKCknLCAnY29sdW1uKCkubm9kZXMoKScsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ2NvbHVtbi1yb3dzJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uLCBpLCBqLCByb3dzICkge1xuXHRcdFx0cmV0dXJuIF9wbHVja19vcmRlciggc2V0dGluZ3MuYW9EYXRhLCByb3dzLCAnYW5DZWxscycsIGNvbHVtbiApIDtcblx0XHR9LCAxICk7XG5cdH0gKTtcblx0XG5cdF9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjb2x1bW5zKCkudmlzaWJsZSgpJywgJ2NvbHVtbigpLnZpc2libGUoKScsIGZ1bmN0aW9uICggdmlzLCBjYWxjICkge1xuXHRcdHZhciByZXQgPSB0aGlzLml0ZXJhdG9yKCAnY29sdW1uJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uICkge1xuXHRcdFx0aWYgKCB2aXMgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdFx0cmV0dXJuIHNldHRpbmdzLmFvQ29sdW1uc1sgY29sdW1uIF0uYlZpc2libGU7XG5cdFx0XHR9IC8vIGVsc2Vcblx0XHRcdF9fc2V0Q29sdW1uVmlzKCBzZXR0aW5ncywgY29sdW1uLCB2aXMgKTtcblx0XHR9ICk7XG5cdFxuXHRcdC8vIEdyb3VwIHRoZSBjb2x1bW4gdmlzaWJpbGl0eSBjaGFuZ2VzXG5cdFx0aWYgKCB2aXMgIT09IHVuZGVmaW5lZCApIHtcblx0XHRcdC8vIFNlY29uZCBsb29wIG9uY2UgdGhlIGZpcnN0IGlzIGRvbmUgZm9yIGV2ZW50c1xuXHRcdFx0dGhpcy5pdGVyYXRvciggJ2NvbHVtbicsIGZ1bmN0aW9uICggc2V0dGluZ3MsIGNvbHVtbiApIHtcblx0XHRcdFx0X2ZuQ2FsbGJhY2tGaXJlKCBzZXR0aW5ncywgbnVsbCwgJ2NvbHVtbi12aXNpYmlsaXR5JywgW3NldHRpbmdzLCBjb2x1bW4sIHZpcywgY2FsY10gKTtcblx0XHRcdH0gKTtcblx0XG5cdFx0XHRpZiAoIGNhbGMgPT09IHVuZGVmaW5lZCB8fCBjYWxjICkge1xuXHRcdFx0XHR0aGlzLmNvbHVtbnMuYWRqdXN0KCk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcblx0XHRyZXR1cm4gcmV0O1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY29sdW1ucygpLmluZGV4ZXMoKScsICdjb2x1bW4oKS5pbmRleCgpJywgZnVuY3Rpb24gKCB0eXBlICkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAnY29sdW1uJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uICkge1xuXHRcdFx0cmV0dXJuIHR5cGUgPT09ICd2aXNpYmxlJyA/XG5cdFx0XHRcdF9mbkNvbHVtbkluZGV4VG9WaXNpYmxlKCBzZXR0aW5ncywgY29sdW1uICkgOlxuXHRcdFx0XHRjb2x1bW47XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRfYXBpX3JlZ2lzdGVyKCAnY29sdW1ucy5hZGp1c3QoKScsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHtcblx0XHRcdF9mbkFkanVzdENvbHVtblNpemluZyggc2V0dGluZ3MgKTtcblx0XHR9LCAxICk7XG5cdH0gKTtcblx0XG5cdF9hcGlfcmVnaXN0ZXIoICdjb2x1bW4uaW5kZXgoKScsIGZ1bmN0aW9uICggdHlwZSwgaWR4ICkge1xuXHRcdGlmICggdGhpcy5jb250ZXh0Lmxlbmd0aCAhPT0gMCApIHtcblx0XHRcdHZhciBjdHggPSB0aGlzLmNvbnRleHRbMF07XG5cdFxuXHRcdFx0aWYgKCB0eXBlID09PSAnZnJvbVZpc2libGUnIHx8IHR5cGUgPT09ICd0b0RhdGEnICkge1xuXHRcdFx0XHRyZXR1cm4gX2ZuVmlzaWJsZVRvQ29sdW1uSW5kZXgoIGN0eCwgaWR4ICk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIGlmICggdHlwZSA9PT0gJ2Zyb21EYXRhJyB8fCB0eXBlID09PSAndG9WaXNpYmxlJyApIHtcblx0XHRcdFx0cmV0dXJuIF9mbkNvbHVtbkluZGV4VG9WaXNpYmxlKCBjdHgsIGlkeCApO1xuXHRcdFx0fVxuXHRcdH1cblx0fSApO1xuXHRcblx0X2FwaV9yZWdpc3RlciggJ2NvbHVtbigpJywgZnVuY3Rpb24gKCBzZWxlY3Rvciwgb3B0cyApIHtcblx0XHRyZXR1cm4gX3NlbGVjdG9yX2ZpcnN0KCB0aGlzLmNvbHVtbnMoIHNlbGVjdG9yLCBvcHRzICkgKTtcblx0fSApO1xuXHRcblx0XG5cdFxuXHR2YXIgX19jZWxsX3NlbGVjdG9yID0gZnVuY3Rpb24gKCBzZXR0aW5ncywgc2VsZWN0b3IsIG9wdHMgKVxuXHR7XG5cdFx0dmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGE7XG5cdFx0dmFyIHJvd3MgPSBfc2VsZWN0b3Jfcm93X2luZGV4ZXMoIHNldHRpbmdzLCBvcHRzICk7XG5cdFx0dmFyIGNlbGxzID0gX3JlbW92ZUVtcHR5KCBfcGx1Y2tfb3JkZXIoIGRhdGEsIHJvd3MsICdhbkNlbGxzJyApICk7XG5cdFx0dmFyIGFsbENlbGxzID0gJCggW10uY29uY2F0LmFwcGx5KFtdLCBjZWxscykgKTtcblx0XHR2YXIgcm93O1xuXHRcdHZhciBjb2x1bW5zID0gc2V0dGluZ3MuYW9Db2x1bW5zLmxlbmd0aDtcblx0XHR2YXIgYSwgaSwgaWVuLCBqLCBvLCBob3N0O1xuXHRcblx0XHR2YXIgcnVuID0gZnVuY3Rpb24gKCBzICkge1xuXHRcdFx0dmFyIGZuU2VsZWN0b3IgPSB0eXBlb2YgcyA9PT0gJ2Z1bmN0aW9uJztcblx0XG5cdFx0XHRpZiAoIHMgPT09IG51bGwgfHwgcyA9PT0gdW5kZWZpbmVkIHx8IGZuU2VsZWN0b3IgKSB7XG5cdFx0XHRcdC8vIEFsbCBjZWxscyBhbmQgZnVuY3Rpb24gc2VsZWN0b3JzXG5cdFx0XHRcdGEgPSBbXTtcblx0XG5cdFx0XHRcdGZvciAoIGk9MCwgaWVuPXJvd3MubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0cm93ID0gcm93c1tpXTtcblx0XG5cdFx0XHRcdFx0Zm9yICggaj0wIDsgajxjb2x1bW5zIDsgaisrICkge1xuXHRcdFx0XHRcdFx0byA9IHtcblx0XHRcdFx0XHRcdFx0cm93OiByb3csXG5cdFx0XHRcdFx0XHRcdGNvbHVtbjogalxuXHRcdFx0XHRcdFx0fTtcblx0XG5cdFx0XHRcdFx0XHRpZiAoIGZuU2VsZWN0b3IgKSB7XG5cdFx0XHRcdFx0XHRcdC8vIFNlbGVjdG9yIC0gZnVuY3Rpb25cblx0XHRcdFx0XHRcdFx0aG9zdCA9IGRhdGFbIHJvdyBdO1xuXHRcblx0XHRcdFx0XHRcdFx0aWYgKCBzKCBvLCBfZm5HZXRDZWxsRGF0YShzZXR0aW5ncywgcm93LCBqKSwgaG9zdC5hbkNlbGxzID8gaG9zdC5hbkNlbGxzW2pdIDogbnVsbCApICkge1xuXHRcdFx0XHRcdFx0XHRcdGEucHVzaCggbyApO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRlbHNlIHtcblx0XHRcdFx0XHRcdFx0Ly8gU2VsZWN0b3IgLSBhbGxcblx0XHRcdFx0XHRcdFx0YS5wdXNoKCBvICk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRyZXR1cm4gYTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0Ly8gU2VsZWN0b3IgLSBpbmRleFxuXHRcdFx0aWYgKCAkLmlzUGxhaW5PYmplY3QoIHMgKSApIHtcblx0XHRcdFx0cmV0dXJuIFtzXTtcblx0XHRcdH1cblx0XG5cdFx0XHQvLyBTZWxlY3RvciAtIGpRdWVyeSBmaWx0ZXJlZCBjZWxsc1xuXHRcdFx0dmFyIGpxUmVzdWx0ID0gYWxsQ2VsbHNcblx0XHRcdFx0LmZpbHRlciggcyApXG5cdFx0XHRcdC5tYXAoIGZ1bmN0aW9uIChpLCBlbCkge1xuXHRcdFx0XHRcdHJldHVybiB7IC8vIHVzZSBhIG5ldyBvYmplY3QsIGluIGNhc2Ugc29tZW9uZSBjaGFuZ2VzIHRoZSB2YWx1ZXNcblx0XHRcdFx0XHRcdHJvdzogICAgZWwuX0RUX0NlbGxJbmRleC5yb3csXG5cdFx0XHRcdFx0XHRjb2x1bW46IGVsLl9EVF9DZWxsSW5kZXguY29sdW1uXG5cdCBcdFx0XHRcdH07XG5cdFx0XHRcdH0gKVxuXHRcdFx0XHQudG9BcnJheSgpO1xuXHRcblx0XHRcdGlmICgganFSZXN1bHQubGVuZ3RoIHx8ICEgcy5ub2RlTmFtZSApIHtcblx0XHRcdFx0cmV0dXJuIGpxUmVzdWx0O1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIE90aGVyd2lzZSB0aGUgc2VsZWN0b3IgaXMgYSBub2RlLCBhbmQgdGhlcmUgaXMgb25lIGxhc3Qgb3B0aW9uIC0gdGhlXG5cdFx0XHQvLyBlbGVtZW50IG1pZ2h0IGJlIGEgY2hpbGQgb2YgYW4gZWxlbWVudCB3aGljaCBoYXMgZHQtcm93IGFuZCBkdC1jb2x1bW5cblx0XHRcdC8vIGRhdGEgYXR0cmlidXRlc1xuXHRcdFx0aG9zdCA9ICQocykuY2xvc2VzdCgnKltkYXRhLWR0LXJvd10nKTtcblx0XHRcdHJldHVybiBob3N0Lmxlbmd0aCA/XG5cdFx0XHRcdFsge1xuXHRcdFx0XHRcdHJvdzogaG9zdC5kYXRhKCdkdC1yb3cnKSxcblx0XHRcdFx0XHRjb2x1bW46IGhvc3QuZGF0YSgnZHQtY29sdW1uJylcblx0XHRcdFx0fSBdIDpcblx0XHRcdFx0W107XG5cdFx0fTtcblx0XG5cdFx0cmV0dXJuIF9zZWxlY3Rvcl9ydW4oICdjZWxsJywgc2VsZWN0b3IsIHJ1biwgc2V0dGluZ3MsIG9wdHMgKTtcblx0fTtcblx0XG5cdFxuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXIoICdjZWxscygpJywgZnVuY3Rpb24gKCByb3dTZWxlY3RvciwgY29sdW1uU2VsZWN0b3IsIG9wdHMgKSB7XG5cdFx0Ly8gQXJndW1lbnQgc2hpZnRpbmdcblx0XHRpZiAoICQuaXNQbGFpbk9iamVjdCggcm93U2VsZWN0b3IgKSApIHtcblx0XHRcdC8vIEluZGV4ZXNcblx0XHRcdGlmICggcm93U2VsZWN0b3Iucm93ID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHRcdC8vIFNlbGVjdG9yIG9wdGlvbnMgaW4gZmlyc3QgcGFyYW1ldGVyXG5cdFx0XHRcdG9wdHMgPSByb3dTZWxlY3Rvcjtcblx0XHRcdFx0cm93U2VsZWN0b3IgPSBudWxsO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdC8vIENlbGwgaW5kZXggb2JqZWN0cyBpbiBmaXJzdCBwYXJhbWV0ZXJcblx0XHRcdFx0b3B0cyA9IGNvbHVtblNlbGVjdG9yO1xuXHRcdFx0XHRjb2x1bW5TZWxlY3RvciA9IG51bGw7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICggJC5pc1BsYWluT2JqZWN0KCBjb2x1bW5TZWxlY3RvciApICkge1xuXHRcdFx0b3B0cyA9IGNvbHVtblNlbGVjdG9yO1xuXHRcdFx0Y29sdW1uU2VsZWN0b3IgPSBudWxsO1xuXHRcdH1cblx0XG5cdFx0Ly8gQ2VsbCBzZWxlY3RvclxuXHRcdGlmICggY29sdW1uU2VsZWN0b3IgPT09IG51bGwgfHwgY29sdW1uU2VsZWN0b3IgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0XHRyZXR1cm4gX19jZWxsX3NlbGVjdG9yKCBzZXR0aW5ncywgcm93U2VsZWN0b3IsIF9zZWxlY3Rvcl9vcHRzKCBvcHRzICkgKTtcblx0XHRcdH0gKTtcblx0XHR9XG5cdFxuXHRcdC8vIFJvdyArIGNvbHVtbiBzZWxlY3RvclxuXHRcdHZhciBjb2x1bW5zID0gdGhpcy5jb2x1bW5zKCBjb2x1bW5TZWxlY3Rvciwgb3B0cyApO1xuXHRcdHZhciByb3dzID0gdGhpcy5yb3dzKCByb3dTZWxlY3Rvciwgb3B0cyApO1xuXHRcdHZhciBhLCBpLCBpZW4sIGosIGplbjtcblx0XG5cdFx0dmFyIGNlbGxzID0gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgaWR4ICkge1xuXHRcdFx0YSA9IFtdO1xuXHRcblx0XHRcdGZvciAoIGk9MCwgaWVuPXJvd3NbaWR4XS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdFx0Zm9yICggaj0wLCBqZW49Y29sdW1uc1tpZHhdLmxlbmd0aCA7IGo8amVuIDsgaisrICkge1xuXHRcdFx0XHRcdGEucHVzaCgge1xuXHRcdFx0XHRcdFx0cm93OiAgICByb3dzW2lkeF1baV0sXG5cdFx0XHRcdFx0XHRjb2x1bW46IGNvbHVtbnNbaWR4XVtqXVxuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcblx0XHRcdHJldHVybiBhO1xuXHRcdH0sIDEgKTtcblx0XG5cdFx0JC5leHRlbmQoIGNlbGxzLnNlbGVjdG9yLCB7XG5cdFx0XHRjb2xzOiBjb2x1bW5TZWxlY3Rvcixcblx0XHRcdHJvd3M6IHJvd1NlbGVjdG9yLFxuXHRcdFx0b3B0czogb3B0c1xuXHRcdH0gKTtcblx0XG5cdFx0cmV0dXJuIGNlbGxzO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlclBsdXJhbCggJ2NlbGxzKCkubm9kZXMoKScsICdjZWxsKCkubm9kZSgpJywgZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAnY2VsbCcsIGZ1bmN0aW9uICggc2V0dGluZ3MsIHJvdywgY29sdW1uICkge1xuXHRcdFx0dmFyIGRhdGEgPSBzZXR0aW5ncy5hb0RhdGFbIHJvdyBdO1xuXHRcblx0XHRcdHJldHVybiBkYXRhICYmIGRhdGEuYW5DZWxscyA/XG5cdFx0XHRcdGRhdGEuYW5DZWxsc1sgY29sdW1uIF0gOlxuXHRcdFx0XHR1bmRlZmluZWQ7XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ2NlbGxzKCkuZGF0YSgpJywgZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAnY2VsbCcsIGZ1bmN0aW9uICggc2V0dGluZ3MsIHJvdywgY29sdW1uICkge1xuXHRcdFx0cmV0dXJuIF9mbkdldENlbGxEYXRhKCBzZXR0aW5ncywgcm93LCBjb2x1bW4gKTtcblx0XHR9LCAxICk7XG5cdH0gKTtcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyUGx1cmFsKCAnY2VsbHMoKS5jYWNoZSgpJywgJ2NlbGwoKS5jYWNoZSgpJywgZnVuY3Rpb24gKCB0eXBlICkge1xuXHRcdHR5cGUgPSB0eXBlID09PSAnc2VhcmNoJyA/ICdfYUZpbHRlckRhdGEnIDogJ19hU29ydERhdGEnO1xuXHRcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ2NlbGwnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCByb3csIGNvbHVtbiApIHtcblx0XHRcdHJldHVybiBzZXR0aW5ncy5hb0RhdGFbIHJvdyBdWyB0eXBlIF1bIGNvbHVtbiBdO1xuXHRcdH0sIDEgKTtcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjZWxscygpLnJlbmRlcigpJywgJ2NlbGwoKS5yZW5kZXIoKScsIGZ1bmN0aW9uICggdHlwZSApIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ2NlbGwnLCBmdW5jdGlvbiAoIHNldHRpbmdzLCByb3csIGNvbHVtbiApIHtcblx0XHRcdHJldHVybiBfZm5HZXRDZWxsRGF0YSggc2V0dGluZ3MsIHJvdywgY29sdW1uLCB0eXBlICk7XG5cdFx0fSwgMSApO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlclBsdXJhbCggJ2NlbGxzKCkuaW5kZXhlcygpJywgJ2NlbGwoKS5pbmRleCgpJywgZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAnY2VsbCcsIGZ1bmN0aW9uICggc2V0dGluZ3MsIHJvdywgY29sdW1uICkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0cm93OiByb3csXG5cdFx0XHRcdGNvbHVtbjogY29sdW1uLFxuXHRcdFx0XHRjb2x1bW5WaXNpYmxlOiBfZm5Db2x1bW5JbmRleFRvVmlzaWJsZSggc2V0dGluZ3MsIGNvbHVtbiApXG5cdFx0XHR9O1xuXHRcdH0sIDEgKTtcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXJQbHVyYWwoICdjZWxscygpLmludmFsaWRhdGUoKScsICdjZWxsKCkuaW52YWxpZGF0ZSgpJywgZnVuY3Rpb24gKCBzcmMgKSB7XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICdjZWxsJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgcm93LCBjb2x1bW4gKSB7XG5cdFx0XHRfZm5JbnZhbGlkYXRlKCBzZXR0aW5ncywgcm93LCBzcmMsIGNvbHVtbiApO1xuXHRcdH0gKTtcblx0fSApO1xuXHRcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyKCAnY2VsbCgpJywgZnVuY3Rpb24gKCByb3dTZWxlY3RvciwgY29sdW1uU2VsZWN0b3IsIG9wdHMgKSB7XG5cdFx0cmV0dXJuIF9zZWxlY3Rvcl9maXJzdCggdGhpcy5jZWxscyggcm93U2VsZWN0b3IsIGNvbHVtblNlbGVjdG9yLCBvcHRzICkgKTtcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXIoICdjZWxsKCkuZGF0YSgpJywgZnVuY3Rpb24gKCBkYXRhICkge1xuXHRcdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cdFx0dmFyIGNlbGwgPSB0aGlzWzBdO1xuXHRcblx0XHRpZiAoIGRhdGEgPT09IHVuZGVmaW5lZCApIHtcblx0XHRcdC8vIEdldFxuXHRcdFx0cmV0dXJuIGN0eC5sZW5ndGggJiYgY2VsbC5sZW5ndGggP1xuXHRcdFx0XHRfZm5HZXRDZWxsRGF0YSggY3R4WzBdLCBjZWxsWzBdLnJvdywgY2VsbFswXS5jb2x1bW4gKSA6XG5cdFx0XHRcdHVuZGVmaW5lZDtcblx0XHR9XG5cdFxuXHRcdC8vIFNldFxuXHRcdF9mblNldENlbGxEYXRhKCBjdHhbMF0sIGNlbGxbMF0ucm93LCBjZWxsWzBdLmNvbHVtbiwgZGF0YSApO1xuXHRcdF9mbkludmFsaWRhdGUoIGN0eFswXSwgY2VsbFswXS5yb3csICdkYXRhJywgY2VsbFswXS5jb2x1bW4gKTtcblx0XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH0gKTtcblx0XG5cdFxuXHRcblx0LyoqXG5cdCAqIEdldCBjdXJyZW50IG9yZGVyaW5nIChzb3J0aW5nKSB0aGF0IGhhcyBiZWVuIGFwcGxpZWQgdG8gdGhlIHRhYmxlLlxuXHQgKlxuXHQgKiBAcmV0dXJucyB7YXJyYXl9IDJEIGFycmF5IGNvbnRhaW5pbmcgdGhlIHNvcnRpbmcgaW5mb3JtYXRpb24gZm9yIHRoZSBmaXJzdFxuXHQgKiAgIHRhYmxlIGluIHRoZSBjdXJyZW50IGNvbnRleHQuIEVhY2ggZWxlbWVudCBpbiB0aGUgcGFyZW50IGFycmF5IHJlcHJlc2VudHNcblx0ICogICBhIGNvbHVtbiBiZWluZyBzb3J0ZWQgdXBvbiAoaS5lLiBtdWx0aS1zb3J0aW5nIHdpdGggdHdvIGNvbHVtbnMgd291bGQgaGF2ZVxuXHQgKiAgIDIgaW5uZXIgYXJyYXlzKS4gVGhlIGlubmVyIGFycmF5cyBtYXkgaGF2ZSAyIG9yIDMgZWxlbWVudHMuIFRoZSBmaXJzdCBpc1xuXHQgKiAgIHRoZSBjb2x1bW4gaW5kZXggdGhhdCB0aGUgc29ydGluZyBjb25kaXRpb24gYXBwbGllcyB0bywgdGhlIHNlY29uZCBpcyB0aGVcblx0ICogICBkaXJlY3Rpb24gb2YgdGhlIHNvcnQgKGBkZXNjYCBvciBgYXNjYCkgYW5kLCBvcHRpb25hbGx5LCB0aGUgdGhpcmQgaXMgdGhlXG5cdCAqICAgaW5kZXggb2YgdGhlIHNvcnRpbmcgb3JkZXIgZnJvbSB0aGUgYGNvbHVtbi5zb3J0aW5nYCBpbml0aWFsaXNhdGlvbiBhcnJheS5cblx0ICovLyoqXG5cdCAqIFNldCB0aGUgb3JkZXJpbmcgZm9yIHRoZSB0YWJsZS5cblx0ICpcblx0ICogQHBhcmFtIHtpbnRlZ2VyfSBvcmRlciBDb2x1bW4gaW5kZXggdG8gc29ydCB1cG9uLlxuXHQgKiBAcGFyYW0ge3N0cmluZ30gZGlyZWN0aW9uIERpcmVjdGlvbiBvZiB0aGUgc29ydCB0byBiZSBhcHBsaWVkIChgYXNjYCBvciBgZGVzY2ApXG5cdCAqIEByZXR1cm5zIHtEYXRhVGFibGVzLkFwaX0gdGhpc1xuXHQgKi8vKipcblx0ICogU2V0IHRoZSBvcmRlcmluZyBmb3IgdGhlIHRhYmxlLlxuXHQgKlxuXHQgKiBAcGFyYW0ge2FycmF5fSBvcmRlciAxRCBhcnJheSBvZiBzb3J0aW5nIGluZm9ybWF0aW9uIHRvIGJlIGFwcGxpZWQuXG5cdCAqIEBwYXJhbSB7YXJyYXl9IFsuLi5dIE9wdGlvbmFsIGFkZGl0aW9uYWwgc29ydGluZyBjb25kaXRpb25zXG5cdCAqIEByZXR1cm5zIHtEYXRhVGFibGVzLkFwaX0gdGhpc1xuXHQgKi8vKipcblx0ICogU2V0IHRoZSBvcmRlcmluZyBmb3IgdGhlIHRhYmxlLlxuXHQgKlxuXHQgKiBAcGFyYW0ge2FycmF5fSBvcmRlciAyRCBhcnJheSBvZiBzb3J0aW5nIGluZm9ybWF0aW9uIHRvIGJlIGFwcGxpZWQuXG5cdCAqIEByZXR1cm5zIHtEYXRhVGFibGVzLkFwaX0gdGhpc1xuXHQgKi9cblx0X2FwaV9yZWdpc3RlciggJ29yZGVyKCknLCBmdW5jdGlvbiAoIG9yZGVyLCBkaXIgKSB7XG5cdFx0dmFyIGN0eCA9IHRoaXMuY29udGV4dDtcblx0XG5cdFx0aWYgKCBvcmRlciA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0Ly8gZ2V0XG5cdFx0XHRyZXR1cm4gY3R4Lmxlbmd0aCAhPT0gMCA/XG5cdFx0XHRcdGN0eFswXS5hYVNvcnRpbmcgOlxuXHRcdFx0XHR1bmRlZmluZWQ7XG5cdFx0fVxuXHRcblx0XHQvLyBzZXRcblx0XHRpZiAoIHR5cGVvZiBvcmRlciA9PT0gJ251bWJlcicgKSB7XG5cdFx0XHQvLyBTaW1wbGUgY29sdW1uIC8gZGlyZWN0aW9uIHBhc3NlZCBpblxuXHRcdFx0b3JkZXIgPSBbIFsgb3JkZXIsIGRpciBdIF07XG5cdFx0fVxuXHRcdGVsc2UgaWYgKCBvcmRlci5sZW5ndGggJiYgISAkLmlzQXJyYXkoIG9yZGVyWzBdICkgKSB7XG5cdFx0XHQvLyBBcmd1bWVudHMgcGFzc2VkIGluIChsaXN0IG9mIDFEIGFycmF5cylcblx0XHRcdG9yZGVyID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoIGFyZ3VtZW50cyApO1xuXHRcdH1cblx0XHQvLyBvdGhlcndpc2UgYSAyRCBhcnJheSB3YXMgcGFzc2VkIGluXG5cdFxuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0c2V0dGluZ3MuYWFTb3J0aW5nID0gb3JkZXIuc2xpY2UoKTtcblx0XHR9ICk7XG5cdH0gKTtcblx0XG5cdFxuXHQvKipcblx0ICogQXR0YWNoIGEgc29ydCBsaXN0ZW5lciB0byBhbiBlbGVtZW50IGZvciBhIGdpdmVuIGNvbHVtblxuXHQgKlxuXHQgKiBAcGFyYW0ge25vZGV8alF1ZXJ5fHN0cmluZ30gbm9kZSBJZGVudGlmaWVyIGZvciB0aGUgZWxlbWVudChzKSB0byBhdHRhY2ggdGhlXG5cdCAqICAgbGlzdGVuZXIgdG8uIFRoaXMgY2FuIHRha2UgdGhlIGZvcm0gb2YgYSBzaW5nbGUgRE9NIG5vZGUsIGEgalF1ZXJ5XG5cdCAqICAgY29sbGVjdGlvbiBvZiBub2RlcyBvciBhIGpRdWVyeSBzZWxlY3RvciB3aGljaCB3aWxsIGlkZW50aWZ5IHRoZSBub2RlKHMpLlxuXHQgKiBAcGFyYW0ge2ludGVnZXJ9IGNvbHVtbiB0aGUgY29sdW1uIHRoYXQgYSBjbGljayBvbiB0aGlzIG5vZGUgd2lsbCBzb3J0IG9uXG5cdCAqIEBwYXJhbSB7ZnVuY3Rpb259IFtjYWxsYmFja10gY2FsbGJhY2sgZnVuY3Rpb24gd2hlbiBzb3J0IGlzIHJ1blxuXHQgKiBAcmV0dXJucyB7RGF0YVRhYmxlcy5BcGl9IHRoaXNcblx0ICovXG5cdF9hcGlfcmVnaXN0ZXIoICdvcmRlci5saXN0ZW5lcigpJywgZnVuY3Rpb24gKCBub2RlLCBjb2x1bW4sIGNhbGxiYWNrICkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0X2ZuU29ydEF0dGFjaExpc3RlbmVyKCBzZXR0aW5ncywgbm9kZSwgY29sdW1uLCBjYWxsYmFjayApO1xuXHRcdH0gKTtcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXIoICdvcmRlci5maXhlZCgpJywgZnVuY3Rpb24gKCBzZXQgKSB7XG5cdFx0aWYgKCAhIHNldCApIHtcblx0XHRcdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cdFx0XHR2YXIgZml4ZWQgPSBjdHgubGVuZ3RoID9cblx0XHRcdFx0Y3R4WzBdLmFhU29ydGluZ0ZpeGVkIDpcblx0XHRcdFx0dW5kZWZpbmVkO1xuXHRcblx0XHRcdHJldHVybiAkLmlzQXJyYXkoIGZpeGVkICkgP1xuXHRcdFx0XHR7IHByZTogZml4ZWQgfSA6XG5cdFx0XHRcdGZpeGVkO1xuXHRcdH1cblx0XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7XG5cdFx0XHRzZXR0aW5ncy5hYVNvcnRpbmdGaXhlZCA9ICQuZXh0ZW5kKCB0cnVlLCB7fSwgc2V0ICk7XG5cdFx0fSApO1xuXHR9ICk7XG5cdFxuXHRcblx0Ly8gT3JkZXIgYnkgdGhlIHNlbGVjdGVkIGNvbHVtbihzKVxuXHRfYXBpX3JlZ2lzdGVyKCBbXG5cdFx0J2NvbHVtbnMoKS5vcmRlcigpJyxcblx0XHQnY29sdW1uKCkub3JkZXIoKSdcblx0XSwgZnVuY3Rpb24gKCBkaXIgKSB7XG5cdFx0dmFyIHRoYXQgPSB0aGlzO1xuXHRcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgaSApIHtcblx0XHRcdHZhciBzb3J0ID0gW107XG5cdFxuXHRcdFx0JC5lYWNoKCB0aGF0W2ldLCBmdW5jdGlvbiAoaiwgY29sKSB7XG5cdFx0XHRcdHNvcnQucHVzaCggWyBjb2wsIGRpciBdICk7XG5cdFx0XHR9ICk7XG5cdFxuXHRcdFx0c2V0dGluZ3MuYWFTb3J0aW5nID0gc29ydDtcblx0XHR9ICk7XG5cdH0gKTtcblx0XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ3NlYXJjaCgpJywgZnVuY3Rpb24gKCBpbnB1dCwgcmVnZXgsIHNtYXJ0LCBjYXNlSW5zZW4gKSB7XG5cdFx0dmFyIGN0eCA9IHRoaXMuY29udGV4dDtcblx0XG5cdFx0aWYgKCBpbnB1dCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0Ly8gZ2V0XG5cdFx0XHRyZXR1cm4gY3R4Lmxlbmd0aCAhPT0gMCA/XG5cdFx0XHRcdGN0eFswXS5vUHJldmlvdXNTZWFyY2guc1NlYXJjaCA6XG5cdFx0XHRcdHVuZGVmaW5lZDtcblx0XHR9XG5cdFxuXHRcdC8vIHNldFxuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0aWYgKCAhIHNldHRpbmdzLm9GZWF0dXJlcy5iRmlsdGVyICkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cdFxuXHRcdFx0X2ZuRmlsdGVyQ29tcGxldGUoIHNldHRpbmdzLCAkLmV4dGVuZCgge30sIHNldHRpbmdzLm9QcmV2aW91c1NlYXJjaCwge1xuXHRcdFx0XHRcInNTZWFyY2hcIjogaW5wdXQrXCJcIixcblx0XHRcdFx0XCJiUmVnZXhcIjogIHJlZ2V4ID09PSBudWxsID8gZmFsc2UgOiByZWdleCxcblx0XHRcdFx0XCJiU21hcnRcIjogIHNtYXJ0ID09PSBudWxsID8gdHJ1ZSAgOiBzbWFydCxcblx0XHRcdFx0XCJiQ2FzZUluc2Vuc2l0aXZlXCI6IGNhc2VJbnNlbiA9PT0gbnVsbCA/IHRydWUgOiBjYXNlSW5zZW5cblx0XHRcdH0gKSwgMSApO1xuXHRcdH0gKTtcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXJQbHVyYWwoXG5cdFx0J2NvbHVtbnMoKS5zZWFyY2goKScsXG5cdFx0J2NvbHVtbigpLnNlYXJjaCgpJyxcblx0XHRmdW5jdGlvbiAoIGlucHV0LCByZWdleCwgc21hcnQsIGNhc2VJbnNlbiApIHtcblx0XHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAnY29sdW1uJywgZnVuY3Rpb24gKCBzZXR0aW5ncywgY29sdW1uICkge1xuXHRcdFx0XHR2YXIgcHJlU2VhcmNoID0gc2V0dGluZ3MuYW9QcmVTZWFyY2hDb2xzO1xuXHRcblx0XHRcdFx0aWYgKCBpbnB1dCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdC8vIGdldFxuXHRcdFx0XHRcdHJldHVybiBwcmVTZWFyY2hbIGNvbHVtbiBdLnNTZWFyY2g7XG5cdFx0XHRcdH1cblx0XG5cdFx0XHRcdC8vIHNldFxuXHRcdFx0XHRpZiAoICEgc2V0dGluZ3Mub0ZlYXR1cmVzLmJGaWx0ZXIgKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFxuXHRcdFx0XHQkLmV4dGVuZCggcHJlU2VhcmNoWyBjb2x1bW4gXSwge1xuXHRcdFx0XHRcdFwic1NlYXJjaFwiOiBpbnB1dCtcIlwiLFxuXHRcdFx0XHRcdFwiYlJlZ2V4XCI6ICByZWdleCA9PT0gbnVsbCA/IGZhbHNlIDogcmVnZXgsXG5cdFx0XHRcdFx0XCJiU21hcnRcIjogIHNtYXJ0ID09PSBudWxsID8gdHJ1ZSAgOiBzbWFydCxcblx0XHRcdFx0XHRcImJDYXNlSW5zZW5zaXRpdmVcIjogY2FzZUluc2VuID09PSBudWxsID8gdHJ1ZSA6IGNhc2VJbnNlblxuXHRcdFx0XHR9ICk7XG5cdFxuXHRcdFx0XHRfZm5GaWx0ZXJDb21wbGV0ZSggc2V0dGluZ3MsIHNldHRpbmdzLm9QcmV2aW91c1NlYXJjaCwgMSApO1xuXHRcdFx0fSApO1xuXHRcdH1cblx0KTtcblx0XG5cdC8qXG5cdCAqIFN0YXRlIEFQSSBtZXRob2RzXG5cdCAqL1xuXHRcblx0X2FwaV9yZWdpc3RlciggJ3N0YXRlKCknLCBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuY29udGV4dC5sZW5ndGggP1xuXHRcdFx0dGhpcy5jb250ZXh0WzBdLm9TYXZlZFN0YXRlIDpcblx0XHRcdG51bGw7XG5cdH0gKTtcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyKCAnc3RhdGUuY2xlYXIoKScsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHtcblx0XHRcdC8vIFNhdmUgYW4gZW1wdHkgb2JqZWN0XG5cdFx0XHRzZXR0aW5ncy5mblN0YXRlU2F2ZUNhbGxiYWNrLmNhbGwoIHNldHRpbmdzLm9JbnN0YW5jZSwgc2V0dGluZ3MsIHt9ICk7XG5cdFx0fSApO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ3N0YXRlLmxvYWRlZCgpJywgZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLmNvbnRleHQubGVuZ3RoID9cblx0XHRcdHRoaXMuY29udGV4dFswXS5vTG9hZGVkU3RhdGUgOlxuXHRcdFx0bnVsbDtcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXIoICdzdGF0ZS5zYXZlKCknLCBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7XG5cdFx0XHRfZm5TYXZlU3RhdGUoIHNldHRpbmdzICk7XG5cdFx0fSApO1xuXHR9ICk7XG5cdFxuXHRcblx0XG5cdC8qKlxuXHQgKiBQcm92aWRlIGEgY29tbW9uIG1ldGhvZCBmb3IgcGx1Zy1pbnMgdG8gY2hlY2sgdGhlIHZlcnNpb24gb2YgRGF0YVRhYmxlcyBiZWluZ1xuXHQgKiB1c2VkLCBpbiBvcmRlciB0byBlbnN1cmUgY29tcGF0aWJpbGl0eS5cblx0ICpcblx0ICogIEBwYXJhbSB7c3RyaW5nfSB2ZXJzaW9uIFZlcnNpb24gc3RyaW5nIHRvIGNoZWNrIGZvciwgaW4gdGhlIGZvcm1hdCBcIlguWS5aXCIuXG5cdCAqICAgIE5vdGUgdGhhdCB0aGUgZm9ybWF0cyBcIlhcIiBhbmQgXCJYLllcIiBhcmUgYWxzbyBhY2NlcHRhYmxlLlxuXHQgKiAgQHJldHVybnMge2Jvb2xlYW59IHRydWUgaWYgdGhpcyB2ZXJzaW9uIG9mIERhdGFUYWJsZXMgaXMgZ3JlYXRlciBvciBlcXVhbCB0b1xuXHQgKiAgICB0aGUgcmVxdWlyZWQgdmVyc2lvbiwgb3IgZmFsc2UgaWYgdGhpcyB2ZXJzaW9uIG9mIERhdGFUYWxlcyBpcyBub3Rcblx0ICogICAgc3VpdGFibGVcblx0ICogIEBzdGF0aWNcblx0ICogIEBkdG9wdCBBUEktU3RhdGljXG5cdCAqXG5cdCAqICBAZXhhbXBsZVxuXHQgKiAgICBhbGVydCggJC5mbi5kYXRhVGFibGUudmVyc2lvbkNoZWNrKCAnMS45LjAnICkgKTtcblx0ICovXG5cdERhdGFUYWJsZS52ZXJzaW9uQ2hlY2sgPSBEYXRhVGFibGUuZm5WZXJzaW9uQ2hlY2sgPSBmdW5jdGlvbiggdmVyc2lvbiApXG5cdHtcblx0XHR2YXIgYVRoaXMgPSBEYXRhVGFibGUudmVyc2lvbi5zcGxpdCgnLicpO1xuXHRcdHZhciBhVGhhdCA9IHZlcnNpb24uc3BsaXQoJy4nKTtcblx0XHR2YXIgaVRoaXMsIGlUaGF0O1xuXHRcblx0XHRmb3IgKCB2YXIgaT0wLCBpTGVuPWFUaGF0Lmxlbmd0aCA7IGk8aUxlbiA7IGkrKyApIHtcblx0XHRcdGlUaGlzID0gcGFyc2VJbnQoIGFUaGlzW2ldLCAxMCApIHx8IDA7XG5cdFx0XHRpVGhhdCA9IHBhcnNlSW50KCBhVGhhdFtpXSwgMTAgKSB8fCAwO1xuXHRcblx0XHRcdC8vIFBhcnRzIGFyZSB0aGUgc2FtZSwga2VlcCBjb21wYXJpbmdcblx0XHRcdGlmIChpVGhpcyA9PT0gaVRoYXQpIHtcblx0XHRcdFx0Y29udGludWU7XG5cdFx0XHR9XG5cdFxuXHRcdFx0Ly8gUGFydHMgYXJlIGRpZmZlcmVudCwgcmV0dXJuIGltbWVkaWF0ZWx5XG5cdFx0XHRyZXR1cm4gaVRoaXMgPiBpVGhhdDtcblx0XHR9XG5cdFxuXHRcdHJldHVybiB0cnVlO1xuXHR9O1xuXHRcblx0XG5cdC8qKlxuXHQgKiBDaGVjayBpZiBhIGA8dGFibGU+YCBub2RlIGlzIGEgRGF0YVRhYmxlIHRhYmxlIGFscmVhZHkgb3Igbm90LlxuXHQgKlxuXHQgKiAgQHBhcmFtIHtub2RlfGpxdWVyeXxzdHJpbmd9IHRhYmxlIFRhYmxlIG5vZGUsIGpRdWVyeSBvYmplY3Qgb3IgalF1ZXJ5XG5cdCAqICAgICAgc2VsZWN0b3IgZm9yIHRoZSB0YWJsZSB0byB0ZXN0LiBOb3RlIHRoYXQgaWYgbW9yZSB0aGFuIG1vcmUgdGhhbiBvbmVcblx0ICogICAgICB0YWJsZSBpcyBwYXNzZWQgb24sIG9ubHkgdGhlIGZpcnN0IHdpbGwgYmUgY2hlY2tlZFxuXHQgKiAgQHJldHVybnMge2Jvb2xlYW59IHRydWUgdGhlIHRhYmxlIGdpdmVuIGlzIGEgRGF0YVRhYmxlLCBvciBmYWxzZSBvdGhlcndpc2Vcblx0ICogIEBzdGF0aWNcblx0ICogIEBkdG9wdCBBUEktU3RhdGljXG5cdCAqXG5cdCAqICBAZXhhbXBsZVxuXHQgKiAgICBpZiAoICEgJC5mbi5EYXRhVGFibGUuaXNEYXRhVGFibGUoICcjZXhhbXBsZScgKSApIHtcblx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgpO1xuXHQgKiAgICB9XG5cdCAqL1xuXHREYXRhVGFibGUuaXNEYXRhVGFibGUgPSBEYXRhVGFibGUuZm5Jc0RhdGFUYWJsZSA9IGZ1bmN0aW9uICggdGFibGUgKVxuXHR7XG5cdFx0dmFyIHQgPSAkKHRhYmxlKS5nZXQoMCk7XG5cdFx0dmFyIGlzID0gZmFsc2U7XG5cdFxuXHRcdGlmICggdGFibGUgaW5zdGFuY2VvZiBEYXRhVGFibGUuQXBpICkge1xuXHRcdFx0cmV0dXJuIHRydWU7XG5cdFx0fVxuXHRcblx0XHQkLmVhY2goIERhdGFUYWJsZS5zZXR0aW5ncywgZnVuY3Rpb24gKGksIG8pIHtcblx0XHRcdHZhciBoZWFkID0gby5uU2Nyb2xsSGVhZCA/ICQoJ3RhYmxlJywgby5uU2Nyb2xsSGVhZClbMF0gOiBudWxsO1xuXHRcdFx0dmFyIGZvb3QgPSBvLm5TY3JvbGxGb290ID8gJCgndGFibGUnLCBvLm5TY3JvbGxGb290KVswXSA6IG51bGw7XG5cdFxuXHRcdFx0aWYgKCBvLm5UYWJsZSA9PT0gdCB8fCBoZWFkID09PSB0IHx8IGZvb3QgPT09IHQgKSB7XG5cdFx0XHRcdGlzID0gdHJ1ZTtcblx0XHRcdH1cblx0XHR9ICk7XG5cdFxuXHRcdHJldHVybiBpcztcblx0fTtcblx0XG5cdFxuXHQvKipcblx0ICogR2V0IGFsbCBEYXRhVGFibGUgdGFibGVzIHRoYXQgaGF2ZSBiZWVuIGluaXRpYWxpc2VkIC0gb3B0aW9uYWxseSB5b3UgY2FuXG5cdCAqIHNlbGVjdCB0byBnZXQgb25seSBjdXJyZW50bHkgdmlzaWJsZSB0YWJsZXMuXG5cdCAqXG5cdCAqICBAcGFyYW0ge2Jvb2xlYW59IFt2aXNpYmxlPWZhbHNlXSBGbGFnIHRvIGluZGljYXRlIGlmIHlvdSB3YW50IGFsbCAoZGVmYXVsdClcblx0ICogICAgb3IgdmlzaWJsZSB0YWJsZXMgb25seS5cblx0ICogIEByZXR1cm5zIHthcnJheX0gQXJyYXkgb2YgYHRhYmxlYCBub2RlcyAobm90IERhdGFUYWJsZSBpbnN0YW5jZXMpIHdoaWNoIGFyZVxuXHQgKiAgICBEYXRhVGFibGVzXG5cdCAqICBAc3RhdGljXG5cdCAqICBAZHRvcHQgQVBJLVN0YXRpY1xuXHQgKlxuXHQgKiAgQGV4YW1wbGVcblx0ICogICAgJC5lYWNoKCAkLmZuLmRhdGFUYWJsZS50YWJsZXModHJ1ZSksIGZ1bmN0aW9uICgpIHtcblx0ICogICAgICAkKHRhYmxlKS5EYXRhVGFibGUoKS5jb2x1bW5zLmFkanVzdCgpO1xuXHQgKiAgICB9ICk7XG5cdCAqL1xuXHREYXRhVGFibGUudGFibGVzID0gRGF0YVRhYmxlLmZuVGFibGVzID0gZnVuY3Rpb24gKCB2aXNpYmxlIClcblx0e1xuXHRcdHZhciBhcGkgPSBmYWxzZTtcblx0XG5cdFx0aWYgKCAkLmlzUGxhaW5PYmplY3QoIHZpc2libGUgKSApIHtcblx0XHRcdGFwaSA9IHZpc2libGUuYXBpO1xuXHRcdFx0dmlzaWJsZSA9IHZpc2libGUudmlzaWJsZTtcblx0XHR9XG5cdFxuXHRcdHZhciBhID0gJC5tYXAoIERhdGFUYWJsZS5zZXR0aW5ncywgZnVuY3Rpb24gKG8pIHtcblx0XHRcdGlmICggIXZpc2libGUgfHwgKHZpc2libGUgJiYgJChvLm5UYWJsZSkuaXMoJzp2aXNpYmxlJykpICkge1xuXHRcdFx0XHRyZXR1cm4gby5uVGFibGU7XG5cdFx0XHR9XG5cdFx0fSApO1xuXHRcblx0XHRyZXR1cm4gYXBpID9cblx0XHRcdG5ldyBfQXBpKCBhICkgOlxuXHRcdFx0YTtcblx0fTtcblx0XG5cdFxuXHQvKipcblx0ICogQ29udmVydCBmcm9tIGNhbWVsIGNhc2UgcGFyYW1ldGVycyB0byBIdW5nYXJpYW4gbm90YXRpb24uIFRoaXMgaXMgbWFkZSBwdWJsaWNcblx0ICogZm9yIHRoZSBleHRlbnNpb25zIHRvIHByb3ZpZGUgdGhlIHNhbWUgYWJpbGl0eSBhcyBEYXRhVGFibGVzIGNvcmUgdG8gYWNjZXB0XG5cdCAqIGVpdGhlciB0aGUgMS45IHN0eWxlIEh1bmdhcmlhbiBub3RhdGlvbiwgb3IgdGhlIDEuMTArIHN0eWxlIGNhbWVsQ2FzZVxuXHQgKiBwYXJhbWV0ZXJzLlxuXHQgKlxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IHNyYyBUaGUgbW9kZWwgb2JqZWN0IHdoaWNoIGhvbGRzIGFsbCBwYXJhbWV0ZXJzIHRoYXQgY2FuIGJlXG5cdCAqICAgIG1hcHBlZC5cblx0ICogIEBwYXJhbSB7b2JqZWN0fSB1c2VyIFRoZSBvYmplY3QgdG8gY29udmVydCBmcm9tIGNhbWVsIGNhc2UgdG8gSHVuZ2FyaWFuLlxuXHQgKiAgQHBhcmFtIHtib29sZWFufSBmb3JjZSBXaGVuIHNldCB0byBgdHJ1ZWAsIHByb3BlcnRpZXMgd2hpY2ggYWxyZWFkeSBoYXZlIGFcblx0ICogICAgSHVuZ2FyaWFuIHZhbHVlIGluIHRoZSBgdXNlcmAgb2JqZWN0IHdpbGwgYmUgb3ZlcndyaXR0ZW4uIE90aGVyd2lzZSB0aGV5XG5cdCAqICAgIHdvbid0IGJlLlxuXHQgKi9cblx0RGF0YVRhYmxlLmNhbWVsVG9IdW5nYXJpYW4gPSBfZm5DYW1lbFRvSHVuZ2FyaWFuO1xuXHRcblx0XG5cdFxuXHQvKipcblx0ICpcblx0ICovXG5cdF9hcGlfcmVnaXN0ZXIoICckKCknLCBmdW5jdGlvbiAoIHNlbGVjdG9yLCBvcHRzICkge1xuXHRcdHZhclxuXHRcdFx0cm93cyAgID0gdGhpcy5yb3dzKCBvcHRzICkubm9kZXMoKSwgLy8gR2V0IGFsbCByb3dzXG5cdFx0XHRqcVJvd3MgPSAkKHJvd3MpO1xuXHRcblx0XHRyZXR1cm4gJCggW10uY29uY2F0KFxuXHRcdFx0anFSb3dzLmZpbHRlciggc2VsZWN0b3IgKS50b0FycmF5KCksXG5cdFx0XHRqcVJvd3MuZmluZCggc2VsZWN0b3IgKS50b0FycmF5KClcblx0XHQpICk7XG5cdH0gKTtcblx0XG5cdFxuXHQvLyBqUXVlcnkgZnVuY3Rpb25zIHRvIG9wZXJhdGUgb24gdGhlIHRhYmxlc1xuXHQkLmVhY2goIFsgJ29uJywgJ29uZScsICdvZmYnIF0sIGZ1bmN0aW9uIChpLCBrZXkpIHtcblx0XHRfYXBpX3JlZ2lzdGVyKCBrZXkrJygpJywgZnVuY3Rpb24gKCAvKiBldmVudCwgaGFuZGxlciAqLyApIHtcblx0XHRcdHZhciBhcmdzID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcblx0XG5cdFx0XHQvLyBBZGQgdGhlIGBkdGAgbmFtZXNwYWNlIGF1dG9tYXRpY2FsbHkgaWYgaXQgaXNuJ3QgYWxyZWFkeSBwcmVzZW50XG5cdFx0XHRhcmdzWzBdID0gJC5tYXAoIGFyZ3NbMF0uc3BsaXQoIC9cXHMvICksIGZ1bmN0aW9uICggZSApIHtcblx0XHRcdFx0cmV0dXJuICEgZS5tYXRjaCgvXFwuZHRcXGIvKSA/XG5cdFx0XHRcdFx0ZSsnLmR0JyA6XG5cdFx0XHRcdFx0ZTtcblx0XHRcdFx0fSApLmpvaW4oICcgJyApO1xuXHRcblx0XHRcdHZhciBpbnN0ID0gJCggdGhpcy50YWJsZXMoKS5ub2RlcygpICk7XG5cdFx0XHRpbnN0W2tleV0uYXBwbHkoIGluc3QsIGFyZ3MgKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH0gKTtcblx0fSApO1xuXHRcblx0XG5cdF9hcGlfcmVnaXN0ZXIoICdjbGVhcigpJywgZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCAndGFibGUnLCBmdW5jdGlvbiAoIHNldHRpbmdzICkge1xuXHRcdFx0X2ZuQ2xlYXJUYWJsZSggc2V0dGluZ3MgKTtcblx0XHR9ICk7XG5cdH0gKTtcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyKCAnc2V0dGluZ3MoKScsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gbmV3IF9BcGkoIHRoaXMuY29udGV4dCwgdGhpcy5jb250ZXh0ICk7XG5cdH0gKTtcblx0XG5cdFxuXHRfYXBpX3JlZ2lzdGVyKCAnaW5pdCgpJywgZnVuY3Rpb24gKCkge1xuXHRcdHZhciBjdHggPSB0aGlzLmNvbnRleHQ7XG5cdFx0cmV0dXJuIGN0eC5sZW5ndGggPyBjdHhbMF0ub0luaXQgOiBudWxsO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ2RhdGEoKScsIGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gdGhpcy5pdGVyYXRvciggJ3RhYmxlJywgZnVuY3Rpb24gKCBzZXR0aW5ncyApIHtcblx0XHRcdHJldHVybiBfcGx1Y2soIHNldHRpbmdzLmFvRGF0YSwgJ19hRGF0YScgKTtcblx0XHR9ICkuZmxhdHRlbigpO1xuXHR9ICk7XG5cdFxuXHRcblx0X2FwaV9yZWdpc3RlciggJ2Rlc3Ryb3koKScsIGZ1bmN0aW9uICggcmVtb3ZlICkge1xuXHRcdHJlbW92ZSA9IHJlbW92ZSB8fCBmYWxzZTtcblx0XG5cdFx0cmV0dXJuIHRoaXMuaXRlcmF0b3IoICd0YWJsZScsIGZ1bmN0aW9uICggc2V0dGluZ3MgKSB7XG5cdFx0XHR2YXIgb3JpZyAgICAgID0gc2V0dGluZ3MublRhYmxlV3JhcHBlci5wYXJlbnROb2RlO1xuXHRcdFx0dmFyIGNsYXNzZXMgICA9IHNldHRpbmdzLm9DbGFzc2VzO1xuXHRcdFx0dmFyIHRhYmxlICAgICA9IHNldHRpbmdzLm5UYWJsZTtcblx0XHRcdHZhciB0Ym9keSAgICAgPSBzZXR0aW5ncy5uVEJvZHk7XG5cdFx0XHR2YXIgdGhlYWQgICAgID0gc2V0dGluZ3MublRIZWFkO1xuXHRcdFx0dmFyIHRmb290ICAgICA9IHNldHRpbmdzLm5URm9vdDtcblx0XHRcdHZhciBqcVRhYmxlICAgPSAkKHRhYmxlKTtcblx0XHRcdHZhciBqcVRib2R5ICAgPSAkKHRib2R5KTtcblx0XHRcdHZhciBqcVdyYXBwZXIgPSAkKHNldHRpbmdzLm5UYWJsZVdyYXBwZXIpO1xuXHRcdFx0dmFyIHJvd3MgICAgICA9ICQubWFwKCBzZXR0aW5ncy5hb0RhdGEsIGZ1bmN0aW9uIChyKSB7IHJldHVybiByLm5UcjsgfSApO1xuXHRcdFx0dmFyIGksIGllbjtcblx0XG5cdFx0XHQvLyBGbGFnIHRvIG5vdGUgdGhhdCB0aGUgdGFibGUgaXMgY3VycmVudGx5IGJlaW5nIGRlc3Ryb3llZCAtIG5vIGFjdGlvblxuXHRcdFx0Ly8gc2hvdWxkIGJlIHRha2VuXG5cdFx0XHRzZXR0aW5ncy5iRGVzdHJveWluZyA9IHRydWU7XG5cdFxuXHRcdFx0Ly8gRmlyZSBvZmYgdGhlIGRlc3Ryb3kgY2FsbGJhY2tzIGZvciBwbHVnLWlucyBldGNcblx0XHRcdF9mbkNhbGxiYWNrRmlyZSggc2V0dGluZ3MsIFwiYW9EZXN0cm95Q2FsbGJhY2tcIiwgXCJkZXN0cm95XCIsIFtzZXR0aW5nc10gKTtcblx0XG5cdFx0XHQvLyBJZiBub3QgYmVpbmcgcmVtb3ZlZCBmcm9tIHRoZSBkb2N1bWVudCwgbWFrZSBhbGwgY29sdW1ucyB2aXNpYmxlXG5cdFx0XHRpZiAoICEgcmVtb3ZlICkge1xuXHRcdFx0XHRuZXcgX0FwaSggc2V0dGluZ3MgKS5jb2x1bW5zKCkudmlzaWJsZSggdHJ1ZSApO1xuXHRcdFx0fVxuXHRcblx0XHRcdC8vIEJsaXR6IGFsbCBgRFRgIG5hbWVzcGFjZWQgZXZlbnRzICh0aGVzZSBhcmUgaW50ZXJuYWwgZXZlbnRzLCB0aGVcblx0XHRcdC8vIGxvd2VyY2FzZSwgYGR0YCBldmVudHMgYXJlIHVzZXIgc3Vic2NyaWJlZCBhbmQgdGhleSBhcmUgcmVzcG9uc2libGVcblx0XHRcdC8vIGZvciByZW1vdmluZyB0aGVtXG5cdFx0XHRqcVdyYXBwZXIub2ZmKCcuRFQnKS5maW5kKCc6bm90KHRib2R5ICopJykub2ZmKCcuRFQnKTtcblx0XHRcdCQod2luZG93KS5vZmYoJy5EVC0nK3NldHRpbmdzLnNJbnN0YW5jZSk7XG5cdFxuXHRcdFx0Ly8gV2hlbiBzY3JvbGxpbmcgd2UgaGFkIHRvIGJyZWFrIHRoZSB0YWJsZSB1cCAtIHJlc3RvcmUgaXRcblx0XHRcdGlmICggdGFibGUgIT0gdGhlYWQucGFyZW50Tm9kZSApIHtcblx0XHRcdFx0anFUYWJsZS5jaGlsZHJlbigndGhlYWQnKS5kZXRhY2goKTtcblx0XHRcdFx0anFUYWJsZS5hcHBlbmQoIHRoZWFkICk7XG5cdFx0XHR9XG5cdFxuXHRcdFx0aWYgKCB0Zm9vdCAmJiB0YWJsZSAhPSB0Zm9vdC5wYXJlbnROb2RlICkge1xuXHRcdFx0XHRqcVRhYmxlLmNoaWxkcmVuKCd0Zm9vdCcpLmRldGFjaCgpO1xuXHRcdFx0XHRqcVRhYmxlLmFwcGVuZCggdGZvb3QgKTtcblx0XHRcdH1cblx0XG5cdFx0XHRzZXR0aW5ncy5hYVNvcnRpbmcgPSBbXTtcblx0XHRcdHNldHRpbmdzLmFhU29ydGluZ0ZpeGVkID0gW107XG5cdFx0XHRfZm5Tb3J0aW5nQ2xhc3Nlcyggc2V0dGluZ3MgKTtcblx0XG5cdFx0XHQkKCByb3dzICkucmVtb3ZlQ2xhc3MoIHNldHRpbmdzLmFzU3RyaXBlQ2xhc3Nlcy5qb2luKCcgJykgKTtcblx0XG5cdFx0XHQkKCd0aCwgdGQnLCB0aGVhZCkucmVtb3ZlQ2xhc3MoIGNsYXNzZXMuc1NvcnRhYmxlKycgJytcblx0XHRcdFx0Y2xhc3Nlcy5zU29ydGFibGVBc2MrJyAnK2NsYXNzZXMuc1NvcnRhYmxlRGVzYysnICcrY2xhc3Nlcy5zU29ydGFibGVOb25lXG5cdFx0XHQpO1xuXHRcblx0XHRcdC8vIEFkZCB0aGUgVFIgZWxlbWVudHMgYmFjayBpbnRvIHRoZSB0YWJsZSBpbiB0aGVpciBvcmlnaW5hbCBvcmRlclxuXHRcdFx0anFUYm9keS5jaGlsZHJlbigpLmRldGFjaCgpO1xuXHRcdFx0anFUYm9keS5hcHBlbmQoIHJvd3MgKTtcblx0XG5cdFx0XHQvLyBSZW1vdmUgdGhlIERhdGFUYWJsZXMgZ2VuZXJhdGVkIG5vZGVzLCBldmVudHMgYW5kIGNsYXNzZXNcblx0XHRcdHZhciByZW1vdmVkTWV0aG9kID0gcmVtb3ZlID8gJ3JlbW92ZScgOiAnZGV0YWNoJztcblx0XHRcdGpxVGFibGVbIHJlbW92ZWRNZXRob2QgXSgpO1xuXHRcdFx0anFXcmFwcGVyWyByZW1vdmVkTWV0aG9kIF0oKTtcblx0XG5cdFx0XHQvLyBJZiB3ZSBuZWVkIHRvIHJlYXR0YWNoIHRoZSB0YWJsZSB0byB0aGUgZG9jdW1lbnRcblx0XHRcdGlmICggISByZW1vdmUgJiYgb3JpZyApIHtcblx0XHRcdFx0Ly8gaW5zZXJ0QmVmb3JlIGFjdHMgbGlrZSBhcHBlbmRDaGlsZCBpZiAhYXJnWzFdXG5cdFx0XHRcdG9yaWcuaW5zZXJ0QmVmb3JlKCB0YWJsZSwgc2V0dGluZ3MublRhYmxlUmVpbnNlcnRCZWZvcmUgKTtcblx0XG5cdFx0XHRcdC8vIFJlc3RvcmUgdGhlIHdpZHRoIG9mIHRoZSBvcmlnaW5hbCB0YWJsZSAtIHdhcyByZWFkIGZyb20gdGhlIHN0eWxlIHByb3BlcnR5LFxuXHRcdFx0XHQvLyBzbyB3ZSBjYW4gcmVzdG9yZSBkaXJlY3RseSB0byB0aGF0XG5cdFx0XHRcdGpxVGFibGVcblx0XHRcdFx0XHQuY3NzKCAnd2lkdGgnLCBzZXR0aW5ncy5zRGVzdHJveVdpZHRoIClcblx0XHRcdFx0XHQucmVtb3ZlQ2xhc3MoIGNsYXNzZXMuc1RhYmxlICk7XG5cdFxuXHRcdFx0XHQvLyBJZiB0aGUgd2VyZSBvcmlnaW5hbGx5IHN0cmlwZSBjbGFzc2VzIC0gdGhlbiB3ZSBhZGQgdGhlbSBiYWNrIGhlcmUuXG5cdFx0XHRcdC8vIE5vdGUgdGhpcyBpcyBub3QgZm9vbCBwcm9vZiAoZm9yIGV4YW1wbGUgaWYgbm90IGFsbCByb3dzIGhhZCBzdHJpcGVcblx0XHRcdFx0Ly8gY2xhc3NlcyAtIGJ1dCBpdCdzIGEgZ29vZCBlZmZvcnQgd2l0aG91dCBnZXR0aW5nIGNhcnJpZWQgYXdheVxuXHRcdFx0XHRpZW4gPSBzZXR0aW5ncy5hc0Rlc3Ryb3lTdHJpcGVzLmxlbmd0aDtcblx0XG5cdFx0XHRcdGlmICggaWVuICkge1xuXHRcdFx0XHRcdGpxVGJvZHkuY2hpbGRyZW4oKS5lYWNoKCBmdW5jdGlvbiAoaSkge1xuXHRcdFx0XHRcdFx0JCh0aGlzKS5hZGRDbGFzcyggc2V0dGluZ3MuYXNEZXN0cm95U3RyaXBlc1tpICUgaWVuXSApO1xuXHRcdFx0XHRcdH0gKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcblx0XHRcdC8qIFJlbW92ZSB0aGUgc2V0dGluZ3Mgb2JqZWN0IGZyb20gdGhlIHNldHRpbmdzIGFycmF5ICovXG5cdFx0XHR2YXIgaWR4ID0gJC5pbkFycmF5KCBzZXR0aW5ncywgRGF0YVRhYmxlLnNldHRpbmdzICk7XG5cdFx0XHRpZiAoIGlkeCAhPT0gLTEgKSB7XG5cdFx0XHRcdERhdGFUYWJsZS5zZXR0aW5ncy5zcGxpY2UoIGlkeCwgMSApO1xuXHRcdFx0fVxuXHRcdH0gKTtcblx0fSApO1xuXHRcblx0XG5cdC8vIEFkZCB0aGUgYGV2ZXJ5KClgIG1ldGhvZCBmb3Igcm93cywgY29sdW1ucyBhbmQgY2VsbHMgaW4gYSBjb21wYWN0IGZvcm1cblx0JC5lYWNoKCBbICdjb2x1bW4nLCAncm93JywgJ2NlbGwnIF0sIGZ1bmN0aW9uICggaSwgdHlwZSApIHtcblx0XHRfYXBpX3JlZ2lzdGVyKCB0eXBlKydzKCkuZXZlcnkoKScsIGZ1bmN0aW9uICggZm4gKSB7XG5cdFx0XHR2YXIgb3B0cyA9IHRoaXMuc2VsZWN0b3Iub3B0cztcblx0XHRcdHZhciBhcGkgPSB0aGlzO1xuXHRcblx0XHRcdHJldHVybiB0aGlzLml0ZXJhdG9yKCB0eXBlLCBmdW5jdGlvbiAoIHNldHRpbmdzLCBhcmcxLCBhcmcyLCBhcmczLCBhcmc0ICkge1xuXHRcdFx0XHQvLyBSb3dzIGFuZCBjb2x1bW5zOlxuXHRcdFx0XHQvLyAgYXJnMSAtIGluZGV4XG5cdFx0XHRcdC8vICBhcmcyIC0gdGFibGUgY291bnRlclxuXHRcdFx0XHQvLyAgYXJnMyAtIGxvb3AgY291bnRlclxuXHRcdFx0XHQvLyAgYXJnNCAtIHVuZGVmaW5lZFxuXHRcdFx0XHQvLyBDZWxsczpcblx0XHRcdFx0Ly8gIGFyZzEgLSByb3cgaW5kZXhcblx0XHRcdFx0Ly8gIGFyZzIgLSBjb2x1bW4gaW5kZXhcblx0XHRcdFx0Ly8gIGFyZzMgLSB0YWJsZSBjb3VudGVyXG5cdFx0XHRcdC8vICBhcmc0IC0gbG9vcCBjb3VudGVyXG5cdFx0XHRcdGZuLmNhbGwoXG5cdFx0XHRcdFx0YXBpWyB0eXBlIF0oXG5cdFx0XHRcdFx0XHRhcmcxLFxuXHRcdFx0XHRcdFx0dHlwZT09PSdjZWxsJyA/IGFyZzIgOiBvcHRzLFxuXHRcdFx0XHRcdFx0dHlwZT09PSdjZWxsJyA/IG9wdHMgOiB1bmRlZmluZWRcblx0XHRcdFx0XHQpLFxuXHRcdFx0XHRcdGFyZzEsIGFyZzIsIGFyZzMsIGFyZzRcblx0XHRcdFx0KTtcblx0XHRcdH0gKTtcblx0XHR9ICk7XG5cdH0gKTtcblx0XG5cdFxuXHQvLyBpMThuIG1ldGhvZCBmb3IgZXh0ZW5zaW9ucyB0byBiZSBhYmxlIHRvIHVzZSB0aGUgbGFuZ3VhZ2Ugb2JqZWN0IGZyb20gdGhlXG5cdC8vIERhdGFUYWJsZVxuXHRfYXBpX3JlZ2lzdGVyKCAnaTE4bigpJywgZnVuY3Rpb24gKCB0b2tlbiwgZGVmLCBwbHVyYWwgKSB7XG5cdFx0dmFyIGN0eCA9IHRoaXMuY29udGV4dFswXTtcblx0XHR2YXIgcmVzb2x2ZWQgPSBfZm5HZXRPYmplY3REYXRhRm4oIHRva2VuICkoIGN0eC5vTGFuZ3VhZ2UgKTtcblx0XG5cdFx0aWYgKCByZXNvbHZlZCA9PT0gdW5kZWZpbmVkICkge1xuXHRcdFx0cmVzb2x2ZWQgPSBkZWY7XG5cdFx0fVxuXHRcblx0XHRpZiAoIHBsdXJhbCAhPT0gdW5kZWZpbmVkICYmICQuaXNQbGFpbk9iamVjdCggcmVzb2x2ZWQgKSApIHtcblx0XHRcdHJlc29sdmVkID0gcmVzb2x2ZWRbIHBsdXJhbCBdICE9PSB1bmRlZmluZWQgP1xuXHRcdFx0XHRyZXNvbHZlZFsgcGx1cmFsIF0gOlxuXHRcdFx0XHRyZXNvbHZlZC5fO1xuXHRcdH1cblx0XG5cdFx0cmV0dXJuIHJlc29sdmVkLnJlcGxhY2UoICclZCcsIHBsdXJhbCApOyAvLyBuYjogcGx1cmFsIG1pZ2h0IGJlIHVuZGVmaW5lZCxcblx0fSApO1xuXHQvKipcblx0ICogVmVyc2lvbiBzdHJpbmcgZm9yIHBsdWctaW5zIHRvIGNoZWNrIGNvbXBhdGliaWxpdHkuIEFsbG93ZWQgZm9ybWF0IGlzXG5cdCAqIGBhLmIuYy1kYCB3aGVyZTogYTppbnQsIGI6aW50LCBjOmludCwgZDpzdHJpbmcoZGV2fGJldGF8YWxwaGEpLiBgZGAgaXMgdXNlZFxuXHQgKiBvbmx5IGZvciBub24tcmVsZWFzZSBidWlsZHMuIFNlZSBodHRwOi8vc2VtdmVyLm9yZy8gZm9yIG1vcmUgaW5mb3JtYXRpb24uXG5cdCAqICBAbWVtYmVyXG5cdCAqICBAdHlwZSBzdHJpbmdcblx0ICogIEBkZWZhdWx0IFZlcnNpb24gbnVtYmVyXG5cdCAqL1xuXHREYXRhVGFibGUudmVyc2lvbiA9IFwiMS4xMC4xNlwiO1xuXG5cdC8qKlxuXHQgKiBQcml2YXRlIGRhdGEgc3RvcmUsIGNvbnRhaW5pbmcgYWxsIG9mIHRoZSBzZXR0aW5ncyBvYmplY3RzIHRoYXQgYXJlXG5cdCAqIGNyZWF0ZWQgZm9yIHRoZSB0YWJsZXMgb24gYSBnaXZlbiBwYWdlLlxuXHQgKlxuXHQgKiBOb3RlIHRoYXQgdGhlIGBEYXRhVGFibGUuc2V0dGluZ3NgIG9iamVjdCBpcyBhbGlhc2VkIHRvXG5cdCAqIGBqUXVlcnkuZm4uZGF0YVRhYmxlRXh0YCB0aHJvdWdoIHdoaWNoIGl0IG1heSBiZSBhY2Nlc3NlZCBhbmRcblx0ICogbWFuaXB1bGF0ZWQsIG9yIGBqUXVlcnkuZm4uZGF0YVRhYmxlLnNldHRpbmdzYC5cblx0ICogIEBtZW1iZXJcblx0ICogIEB0eXBlIGFycmF5XG5cdCAqICBAZGVmYXVsdCBbXVxuXHQgKiAgQHByaXZhdGVcblx0ICovXG5cdERhdGFUYWJsZS5zZXR0aW5ncyA9IFtdO1xuXG5cdC8qKlxuXHQgKiBPYmplY3QgbW9kZWxzIGNvbnRhaW5lciwgZm9yIHRoZSB2YXJpb3VzIG1vZGVscyB0aGF0IERhdGFUYWJsZXMgaGFzXG5cdCAqIGF2YWlsYWJsZSB0byBpdC4gVGhlc2UgbW9kZWxzIGRlZmluZSB0aGUgb2JqZWN0cyB0aGF0IGFyZSB1c2VkIHRvIGhvbGRcblx0ICogdGhlIGFjdGl2ZSBzdGF0ZSBhbmQgY29uZmlndXJhdGlvbiBvZiB0aGUgdGFibGUuXG5cdCAqICBAbmFtZXNwYWNlXG5cdCAqL1xuXHREYXRhVGFibGUubW9kZWxzID0ge307XG5cdFxuXHRcblx0XG5cdC8qKlxuXHQgKiBUZW1wbGF0ZSBvYmplY3QgZm9yIHRoZSB3YXkgaW4gd2hpY2ggRGF0YVRhYmxlcyBob2xkcyBpbmZvcm1hdGlvbiBhYm91dFxuXHQgKiBzZWFyY2ggaW5mb3JtYXRpb24gZm9yIHRoZSBnbG9iYWwgZmlsdGVyIGFuZCBpbmRpdmlkdWFsIGNvbHVtbiBmaWx0ZXJzLlxuXHQgKiAgQG5hbWVzcGFjZVxuXHQgKi9cblx0RGF0YVRhYmxlLm1vZGVscy5vU2VhcmNoID0ge1xuXHRcdC8qKlxuXHRcdCAqIEZsYWcgdG8gaW5kaWNhdGUgaWYgdGhlIGZpbHRlcmluZyBzaG91bGQgYmUgY2FzZSBpbnNlbnNpdGl2ZSBvciBub3Rcblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqICBAZGVmYXVsdCB0cnVlXG5cdFx0ICovXG5cdFx0XCJiQ2FzZUluc2Vuc2l0aXZlXCI6IHRydWUsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFwcGxpZWQgc2VhcmNoIHRlcm1cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IDxpPkVtcHR5IHN0cmluZzwvaT5cblx0XHQgKi9cblx0XHRcInNTZWFyY2hcIjogXCJcIixcblx0XG5cdFx0LyoqXG5cdFx0ICogRmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgc2VhcmNoIHRlcm0gc2hvdWxkIGJlIGludGVycHJldGVkIGFzIGFcblx0XHQgKiByZWd1bGFyIGV4cHJlc3Npb24gKHRydWUpIG9yIG5vdCAoZmFsc2UpIGFuZCB0aGVyZWZvcmUgYW5kIHNwZWNpYWxcblx0XHQgKiByZWdleCBjaGFyYWN0ZXJzIGVzY2FwZWQuXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHQgKi9cblx0XHRcImJSZWdleFwiOiBmYWxzZSxcblx0XG5cdFx0LyoqXG5cdFx0ICogRmxhZyB0byBpbmRpY2F0ZSBpZiBEYXRhVGFibGVzIGlzIHRvIHVzZSBpdHMgc21hcnQgZmlsdGVyaW5nIG9yIG5vdC5cblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqICBAZGVmYXVsdCB0cnVlXG5cdFx0ICovXG5cdFx0XCJiU21hcnRcIjogdHJ1ZVxuXHR9O1xuXHRcblx0XG5cdFxuXHRcblx0LyoqXG5cdCAqIFRlbXBsYXRlIG9iamVjdCBmb3IgdGhlIHdheSBpbiB3aGljaCBEYXRhVGFibGVzIGhvbGRzIGluZm9ybWF0aW9uIGFib3V0XG5cdCAqIGVhY2ggaW5kaXZpZHVhbCByb3cuIFRoaXMgaXMgdGhlIG9iamVjdCBmb3JtYXQgdXNlZCBmb3IgdGhlIHNldHRpbmdzXG5cdCAqIGFvRGF0YSBhcnJheS5cblx0ICogIEBuYW1lc3BhY2Vcblx0ICovXG5cdERhdGFUYWJsZS5tb2RlbHMub1JvdyA9IHtcblx0XHQvKipcblx0XHQgKiBUUiBlbGVtZW50IGZvciB0aGUgcm93XG5cdFx0ICogIEB0eXBlIG5vZGVcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwiblRyXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFycmF5IG9mIFREIGVsZW1lbnRzIGZvciBlYWNoIHJvdy4gVGhpcyBpcyBudWxsIHVudGlsIHRoZSByb3cgaGFzIGJlZW5cblx0XHQgKiBjcmVhdGVkLlxuXHRcdCAqICBAdHlwZSBhcnJheSBub2Rlc1xuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYW5DZWxsc1wiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBEYXRhIG9iamVjdCBmcm9tIHRoZSBvcmlnaW5hbCBkYXRhIHNvdXJjZSBmb3IgdGhlIHJvdy4gVGhpcyBpcyBlaXRoZXJcblx0XHQgKiBhbiBhcnJheSBpZiB1c2luZyB0aGUgdHJhZGl0aW9uYWwgZm9ybSBvZiBEYXRhVGFibGVzLCBvciBhbiBvYmplY3QgaWZcblx0XHQgKiB1c2luZyBtRGF0YSBvcHRpb25zLiBUaGUgZXhhY3QgdHlwZSB3aWxsIGRlcGVuZCBvbiB0aGUgcGFzc2VkIGluXG5cdFx0ICogZGF0YSBmcm9tIHRoZSBkYXRhIHNvdXJjZSwgb3Igd2lsbCBiZSBhbiBhcnJheSBpZiB1c2luZyBET00gYSBkYXRhXG5cdFx0ICogc291cmNlLlxuXHRcdCAqICBAdHlwZSBhcnJheXxvYmplY3Rcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcIl9hRGF0YVwiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU29ydGluZyBkYXRhIGNhY2hlIC0gdGhpcyBhcnJheSBpcyBvc3RlbnNpYmx5IHRoZSBzYW1lIGxlbmd0aCBhcyB0aGVcblx0XHQgKiBudW1iZXIgb2YgY29sdW1ucyAoYWx0aG91Z2ggZWFjaCBpbmRleCBpcyBnZW5lcmF0ZWQgb25seSBhcyBpdCBpc1xuXHRcdCAqIG5lZWRlZCksIGFuZCBob2xkcyB0aGUgZGF0YSB0aGF0IGlzIHVzZWQgZm9yIHNvcnRpbmcgZWFjaCBjb2x1bW4gaW4gdGhlXG5cdFx0ICogcm93LiBXZSBkbyB0aGlzIGNhY2hlIGdlbmVyYXRpb24gYXQgdGhlIHN0YXJ0IG9mIHRoZSBzb3J0IGluIG9yZGVyIHRoYXRcblx0XHQgKiB0aGUgZm9ybWF0dGluZyBvZiB0aGUgc29ydCBkYXRhIG5lZWQgYmUgZG9uZSBvbmx5IG9uY2UgZm9yIGVhY2ggY2VsbFxuXHRcdCAqIHBlciBzb3J0LiBUaGlzIGFycmF5IHNob3VsZCBub3QgYmUgcmVhZCBmcm9tIG9yIHdyaXR0ZW4gdG8gYnkgYW55dGhpbmdcblx0XHQgKiBvdGhlciB0aGFuIHRoZSBtYXN0ZXIgc29ydGluZyBtZXRob2RzLlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICogIEBwcml2YXRlXG5cdFx0ICovXG5cdFx0XCJfYVNvcnREYXRhXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFBlciBjZWxsIGZpbHRlcmluZyBkYXRhIGNhY2hlLiBBcyBwZXIgdGhlIHNvcnQgZGF0YSBjYWNoZSwgdXNlZCB0b1xuXHRcdCAqIGluY3JlYXNlIHRoZSBwZXJmb3JtYW5jZSBvZiB0aGUgZmlsdGVyaW5nIGluIERhdGFUYWJsZXNcblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqICBAcHJpdmF0ZVxuXHRcdCAqL1xuXHRcdFwiX2FGaWx0ZXJEYXRhXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEZpbHRlcmluZyBkYXRhIGNhY2hlLiBUaGlzIGlzIHRoZSBzYW1lIGFzIHRoZSBjZWxsIGZpbHRlcmluZyBjYWNoZSwgYnV0XG5cdFx0ICogaW4gdGhpcyBjYXNlIGEgc3RyaW5nIHJhdGhlciB0aGFuIGFuIGFycmF5LiBUaGlzIGlzIGVhc2lseSBjb21wdXRlZCB3aXRoXG5cdFx0ICogYSBqb2luIG9uIGBfYUZpbHRlckRhdGFgLCBidXQgaXMgcHJvdmlkZWQgYXMgYSBjYWNoZSBzbyB0aGUgam9pbiBpc24ndFxuXHRcdCAqIG5lZWRlZCBvbiBldmVyeSBzZWFyY2ggKG1lbW9yeSB0cmFkZWQgZm9yIHBlcmZvcm1hbmNlKVxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICogIEBwcml2YXRlXG5cdFx0ICovXG5cdFx0XCJfc0ZpbHRlclJvd1wiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBDYWNoZSBvZiB0aGUgY2xhc3MgbmFtZSB0aGF0IERhdGFUYWJsZXMgaGFzIGFwcGxpZWQgdG8gdGhlIHJvdywgc28gd2Vcblx0XHQgKiBjYW4gcXVpY2tseSBsb29rIGF0IHRoaXMgdmFyaWFibGUgcmF0aGVyIHRoYW4gbmVlZGluZyB0byBkbyBhIERPTSBjaGVja1xuXHRcdCAqIG9uIGNsYXNzTmFtZSBmb3IgdGhlIG5UciBwcm9wZXJ0eS5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IDxpPkVtcHR5IHN0cmluZzwvaT5cblx0XHQgKiAgQHByaXZhdGVcblx0XHQgKi9cblx0XHRcIl9zUm93U3RyaXBlXCI6IFwiXCIsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIERlbm90ZSBpZiB0aGUgb3JpZ2luYWwgZGF0YSBzb3VyY2Ugd2FzIGZyb20gdGhlIERPTSwgb3IgdGhlIGRhdGEgc291cmNlXG5cdFx0ICogb2JqZWN0LiBUaGlzIGlzIHVzZWQgZm9yIGludmFsaWRhdGluZyBkYXRhLCBzbyBEYXRhVGFibGVzIGNhblxuXHRcdCAqIGF1dG9tYXRpY2FsbHkgcmVhZCBkYXRhIGZyb20gdGhlIG9yaWdpbmFsIHNvdXJjZSwgdW5sZXNzIHVuaW5zdHJ1Y3RlZFxuXHRcdCAqIG90aGVyd2lzZS5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKiAgQHByaXZhdGVcblx0XHQgKi9cblx0XHRcInNyY1wiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBJbmRleCBpbiB0aGUgYW9EYXRhIGFycmF5LiBUaGlzIHNhdmVzIGFuIGluZGV4T2YgbG9va3VwIHdoZW4gd2UgaGF2ZSB0aGVcblx0XHQgKiBvYmplY3QsIGJ1dCB3YW50IHRvIGtub3cgdGhlIGluZGV4XG5cdFx0ICogIEB0eXBlIGludGVnZXJcblx0XHQgKiAgQGRlZmF1bHQgLTFcblx0XHQgKiAgQHByaXZhdGVcblx0XHQgKi9cblx0XHRcImlkeFwiOiAtMVxuXHR9O1xuXHRcblx0XG5cdC8qKlxuXHQgKiBUZW1wbGF0ZSBvYmplY3QgZm9yIHRoZSBjb2x1bW4gaW5mb3JtYXRpb24gb2JqZWN0IGluIERhdGFUYWJsZXMuIFRoaXMgb2JqZWN0XG5cdCAqIGlzIGhlbGQgaW4gdGhlIHNldHRpbmdzIGFvQ29sdW1ucyBhcnJheSBhbmQgY29udGFpbnMgYWxsIHRoZSBpbmZvcm1hdGlvbiB0aGF0XG5cdCAqIERhdGFUYWJsZXMgbmVlZHMgYWJvdXQgZWFjaCBpbmRpdmlkdWFsIGNvbHVtbi5cblx0ICpcblx0ICogTm90ZSB0aGF0IHRoaXMgb2JqZWN0IGlzIHJlbGF0ZWQgdG8ge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW59XG5cdCAqIGJ1dCB0aGlzIG9uZSBpcyB0aGUgaW50ZXJuYWwgZGF0YSBzdG9yZSBmb3IgRGF0YVRhYmxlcydzIGNhY2hlIG9mIGNvbHVtbnMuXG5cdCAqIEl0IHNob3VsZCBOT1QgYmUgbWFuaXB1bGF0ZWQgb3V0c2lkZSBvZiBEYXRhVGFibGVzLiBBbnkgY29uZmlndXJhdGlvbiBzaG91bGRcblx0ICogYmUgZG9uZSB0aHJvdWdoIHRoZSBpbml0aWFsaXNhdGlvbiBvcHRpb25zLlxuXHQgKiAgQG5hbWVzcGFjZVxuXHQgKi9cblx0RGF0YVRhYmxlLm1vZGVscy5vQ29sdW1uID0ge1xuXHRcdC8qKlxuXHRcdCAqIENvbHVtbiBpbmRleC4gVGhpcyBjb3VsZCBiZSB3b3JrZWQgb3V0IG9uLXRoZS1mbHkgd2l0aCAkLmluQXJyYXksIGJ1dCBpdFxuXHRcdCAqIGlzIGZhc3RlciB0byBqdXN0IGhvbGQgaXQgYXMgYSB2YXJpYWJsZVxuXHRcdCAqICBAdHlwZSBpbnRlZ2VyXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcImlkeFwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBBIGxpc3Qgb2YgdGhlIGNvbHVtbnMgdGhhdCBzb3J0aW5nIHNob3VsZCBvY2N1ciBvbiB3aGVuIHRoaXMgY29sdW1uXG5cdFx0ICogaXMgc29ydGVkLiBUaGF0IHRoaXMgcHJvcGVydHkgaXMgYW4gYXJyYXkgYWxsb3dzIG11bHRpLWNvbHVtbiBzb3J0aW5nXG5cdFx0ICogdG8gYmUgZGVmaW5lZCBmb3IgYSBjb2x1bW4gKGZvciBleGFtcGxlIGZpcnN0IG5hbWUgLyBsYXN0IG5hbWUgY29sdW1uc1xuXHRcdCAqIHdvdWxkIGJlbmVmaXQgZnJvbSB0aGlzKS4gVGhlIHZhbHVlcyBhcmUgaW50ZWdlcnMgcG9pbnRpbmcgdG8gdGhlXG5cdFx0ICogY29sdW1ucyB0byBiZSBzb3J0ZWQgb24gKHR5cGljYWxseSBpdCB3aWxsIGJlIGEgc2luZ2xlIGludGVnZXIgcG9pbnRpbmdcblx0XHQgKiBhdCBpdHNlbGYsIGJ1dCB0aGF0IGRvZXNuJ3QgbmVlZCB0byBiZSB0aGUgY2FzZSkuXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICovXG5cdFx0XCJhRGF0YVNvcnRcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogRGVmaW5lIHRoZSBzb3J0aW5nIGRpcmVjdGlvbnMgdGhhdCBhcmUgYXBwbGllZCB0byB0aGUgY29sdW1uLCBpbiBzZXF1ZW5jZVxuXHRcdCAqIGFzIHRoZSBjb2x1bW4gaXMgcmVwZWF0ZWRseSBzb3J0ZWQgdXBvbiAtIGkuZS4gdGhlIGZpcnN0IHZhbHVlIGlzIHVzZWRcblx0XHQgKiBhcyB0aGUgc29ydGluZyBkaXJlY3Rpb24gd2hlbiB0aGUgY29sdW1uIGlmIGZpcnN0IHNvcnRlZCAoY2xpY2tlZCBvbikuXG5cdFx0ICogU29ydCBpdCBhZ2FpbiAoY2xpY2sgYWdhaW4pIGFuZCBpdCB3aWxsIG1vdmUgb24gdG8gdGhlIG5leHQgaW5kZXguXG5cdFx0ICogUmVwZWF0IHVudGlsIGxvb3AuXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICovXG5cdFx0XCJhc1NvcnRpbmdcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogRmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgY29sdW1uIGlzIHNlYXJjaGFibGUsIGFuZCB0aHVzIHNob3VsZCBiZSBpbmNsdWRlZFxuXHRcdCAqIGluIHRoZSBmaWx0ZXJpbmcgb3Igbm90LlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICovXG5cdFx0XCJiU2VhcmNoYWJsZVwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBGbGFnIHRvIGluZGljYXRlIGlmIHRoZSBjb2x1bW4gaXMgc29ydGFibGUgb3Igbm90LlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICovXG5cdFx0XCJiU29ydGFibGVcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogRmxhZyB0byBpbmRpY2F0ZSBpZiB0aGUgY29sdW1uIGlzIGN1cnJlbnRseSB2aXNpYmxlIGluIHRoZSB0YWJsZSBvciBub3Rcblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqL1xuXHRcdFwiYlZpc2libGVcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogU3RvcmUgZm9yIG1hbnVhbCB0eXBlIGFzc2lnbm1lbnQgdXNpbmcgdGhlIGBjb2x1bW4udHlwZWAgb3B0aW9uLiBUaGlzXG5cdFx0ICogaXMgaGVsZCBpbiBzdG9yZSBzbyB3ZSBjYW4gbWFuaXB1bGF0ZSB0aGUgY29sdW1uJ3MgYHNUeXBlYCBwcm9wZXJ0eS5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKiAgQHByaXZhdGVcblx0XHQgKi9cblx0XHRcIl9zTWFudWFsVHlwZVwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBGbGFnIHRvIGluZGljYXRlIGlmIEhUTUw1IGRhdGEgYXR0cmlidXRlcyBzaG91bGQgYmUgdXNlZCBhcyB0aGUgZGF0YVxuXHRcdCAqIHNvdXJjZSBmb3IgZmlsdGVyaW5nIG9yIHNvcnRpbmcuIFRydWUgaXMgZWl0aGVyIGFyZS5cblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqICBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqICBAcHJpdmF0ZVxuXHRcdCAqL1xuXHRcdFwiX2JBdHRyU3JjXCI6IGZhbHNlLFxuXHRcblx0XHQvKipcblx0XHQgKiBEZXZlbG9wZXIgZGVmaW5hYmxlIGZ1bmN0aW9uIHRoYXQgaXMgY2FsbGVkIHdoZW5ldmVyIGEgY2VsbCBpcyBjcmVhdGVkIChBamF4IHNvdXJjZSxcblx0XHQgKiBldGMpIG9yIHByb2Nlc3NlZCBmb3IgaW5wdXQgKERPTSBzb3VyY2UpLiBUaGlzIGNhbiBiZSB1c2VkIGFzIGEgY29tcGxpbWVudCB0byBtUmVuZGVyXG5cdFx0ICogYWxsb3dpbmcgeW91IHRvIG1vZGlmeSB0aGUgRE9NIGVsZW1lbnQgKGFkZCBiYWNrZ3JvdW5kIGNvbG91ciBmb3IgZXhhbXBsZSkgd2hlbiB0aGVcblx0XHQgKiBlbGVtZW50IGlzIGF2YWlsYWJsZS5cblx0XHQgKiAgQHR5cGUgZnVuY3Rpb25cblx0XHQgKiAgQHBhcmFtIHtlbGVtZW50fSBuVGQgVGhlIFREIG5vZGUgdGhhdCBoYXMgYmVlbiBjcmVhdGVkXG5cdFx0ICogIEBwYXJhbSB7Kn0gc0RhdGEgVGhlIERhdGEgZm9yIHRoZSBjZWxsXG5cdFx0ICogIEBwYXJhbSB7YXJyYXl8b2JqZWN0fSBvRGF0YSBUaGUgZGF0YSBmb3IgdGhlIHdob2xlIHJvd1xuXHRcdCAqICBAcGFyYW0ge2ludH0gaVJvdyBUaGUgcm93IGluZGV4IGZvciB0aGUgYW9EYXRhIGRhdGEgc3RvcmVcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwiZm5DcmVhdGVkQ2VsbFwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBGdW5jdGlvbiB0byBnZXQgZGF0YSBmcm9tIGEgY2VsbCBpbiBhIGNvbHVtbi4gWW91IHNob3VsZCA8Yj5uZXZlcjwvYj5cblx0XHQgKiBhY2Nlc3MgZGF0YSBkaXJlY3RseSB0aHJvdWdoIF9hRGF0YSBpbnRlcm5hbGx5IGluIERhdGFUYWJsZXMgLSBhbHdheXMgdXNlXG5cdFx0ICogdGhlIG1ldGhvZCBhdHRhY2hlZCB0byB0aGlzIHByb3BlcnR5LiBJdCBhbGxvd3MgbURhdGEgdG8gZnVuY3Rpb24gYXNcblx0XHQgKiByZXF1aXJlZC4gVGhpcyBmdW5jdGlvbiBpcyBhdXRvbWF0aWNhbGx5IGFzc2lnbmVkIGJ5IHRoZSBjb2x1bW5cblx0XHQgKiBpbml0aWFsaXNhdGlvbiBtZXRob2Rcblx0XHQgKiAgQHR5cGUgZnVuY3Rpb25cblx0XHQgKiAgQHBhcmFtIHthcnJheXxvYmplY3R9IG9EYXRhIFRoZSBkYXRhIGFycmF5L29iamVjdCBmb3IgdGhlIGFycmF5XG5cdFx0ICogICAgKGkuZS4gYW9EYXRhW10uX2FEYXRhKVxuXHRcdCAqICBAcGFyYW0ge3N0cmluZ30gc1NwZWNpZmljIFRoZSBzcGVjaWZpYyBkYXRhIHR5cGUgeW91IHdhbnQgdG8gZ2V0IC1cblx0XHQgKiAgICAnZGlzcGxheScsICd0eXBlJyAnZmlsdGVyJyAnc29ydCdcblx0XHQgKiAgQHJldHVybnMgeyp9IFRoZSBkYXRhIGZvciB0aGUgY2VsbCBmcm9tIHRoZSBnaXZlbiByb3cncyBkYXRhXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcImZuR2V0RGF0YVwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBGdW5jdGlvbiB0byBzZXQgZGF0YSBmb3IgYSBjZWxsIGluIHRoZSBjb2x1bW4uIFlvdSBzaG91bGQgPGI+bmV2ZXI8L2I+XG5cdFx0ICogc2V0IHRoZSBkYXRhIGRpcmVjdGx5IHRvIF9hRGF0YSBpbnRlcm5hbGx5IGluIERhdGFUYWJsZXMgLSBhbHdheXMgdXNlXG5cdFx0ICogdGhpcyBtZXRob2QuIEl0IGFsbG93cyBtRGF0YSB0byBmdW5jdGlvbiBhcyByZXF1aXJlZC4gVGhpcyBmdW5jdGlvblxuXHRcdCAqIGlzIGF1dG9tYXRpY2FsbHkgYXNzaWduZWQgYnkgdGhlIGNvbHVtbiBpbml0aWFsaXNhdGlvbiBtZXRob2Rcblx0XHQgKiAgQHR5cGUgZnVuY3Rpb25cblx0XHQgKiAgQHBhcmFtIHthcnJheXxvYmplY3R9IG9EYXRhIFRoZSBkYXRhIGFycmF5L29iamVjdCBmb3IgdGhlIGFycmF5XG5cdFx0ICogICAgKGkuZS4gYW9EYXRhW10uX2FEYXRhKVxuXHRcdCAqICBAcGFyYW0geyp9IHNWYWx1ZSBWYWx1ZSB0byBzZXRcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwiZm5TZXREYXRhXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFByb3BlcnR5IHRvIHJlYWQgdGhlIHZhbHVlIGZvciB0aGUgY2VsbHMgaW4gdGhlIGNvbHVtbiBmcm9tIHRoZSBkYXRhXG5cdFx0ICogc291cmNlIGFycmF5IC8gb2JqZWN0LiBJZiBudWxsLCB0aGVuIHRoZSBkZWZhdWx0IGNvbnRlbnQgaXMgdXNlZCwgaWYgYVxuXHRcdCAqIGZ1bmN0aW9uIGlzIGdpdmVuIHRoZW4gdGhlIHJldHVybiBmcm9tIHRoZSBmdW5jdGlvbiBpcyB1c2VkLlxuXHRcdCAqICBAdHlwZSBmdW5jdGlvbnxpbnR8c3RyaW5nfG51bGxcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwibURhdGFcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogUGFydG5lciBwcm9wZXJ0eSB0byBtRGF0YSB3aGljaCBpcyB1c2VkIChvbmx5IHdoZW4gZGVmaW5lZCkgdG8gZ2V0XG5cdFx0ICogdGhlIGRhdGEgLSBpLmUuIGl0IGlzIGJhc2ljYWxseSB0aGUgc2FtZSBhcyBtRGF0YSwgYnV0IHdpdGhvdXQgdGhlXG5cdFx0ICogJ3NldCcgb3B0aW9uLCBhbmQgYWxzbyB0aGUgZGF0YSBmZWQgdG8gaXQgaXMgdGhlIHJlc3VsdCBmcm9tIG1EYXRhLlxuXHRcdCAqIFRoaXMgaXMgdGhlIHJlbmRlcmluZyBtZXRob2QgdG8gbWF0Y2ggdGhlIGRhdGEgbWV0aG9kIG9mIG1EYXRhLlxuXHRcdCAqICBAdHlwZSBmdW5jdGlvbnxpbnR8c3RyaW5nfG51bGxcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwibVJlbmRlclwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBVbmlxdWUgaGVhZGVyIFRIL1REIGVsZW1lbnQgZm9yIHRoaXMgY29sdW1uIC0gdGhpcyBpcyB3aGF0IHRoZSBzb3J0aW5nXG5cdFx0ICogbGlzdGVuZXIgaXMgYXR0YWNoZWQgdG8gKGlmIHNvcnRpbmcgaXMgZW5hYmxlZC4pXG5cdFx0ICogIEB0eXBlIG5vZGVcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwiblRoXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFVuaXF1ZSBmb290ZXIgVEgvVEQgZWxlbWVudCBmb3IgdGhpcyBjb2x1bW4gKGlmIHRoZXJlIGlzIG9uZSkuIE5vdCB1c2VkXG5cdFx0ICogaW4gRGF0YVRhYmxlcyBhcyBzdWNoLCBidXQgY2FuIGJlIHVzZWQgZm9yIHBsdWctaW5zIHRvIHJlZmVyZW5jZSB0aGVcblx0XHQgKiBmb290ZXIgZm9yIGVhY2ggY29sdW1uLlxuXHRcdCAqICBAdHlwZSBub2RlXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcIm5UZlwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBUaGUgY2xhc3MgdG8gYXBwbHkgdG8gYWxsIFREIGVsZW1lbnRzIGluIHRoZSB0YWJsZSdzIFRCT0RZIGZvciB0aGUgY29sdW1uXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJzQ2xhc3NcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogV2hlbiBEYXRhVGFibGVzIGNhbGN1bGF0ZXMgdGhlIGNvbHVtbiB3aWR0aHMgdG8gYXNzaWduIHRvIGVhY2ggY29sdW1uLFxuXHRcdCAqIGl0IGZpbmRzIHRoZSBsb25nZXN0IHN0cmluZyBpbiBlYWNoIGNvbHVtbiBhbmQgdGhlbiBjb25zdHJ1Y3RzIGFcblx0XHQgKiB0ZW1wb3JhcnkgdGFibGUgYW5kIHJlYWRzIHRoZSB3aWR0aHMgZnJvbSB0aGF0LiBUaGUgcHJvYmxlbSB3aXRoIHRoaXNcblx0XHQgKiBpcyB0aGF0IFwibW1tXCIgaXMgbXVjaCB3aWRlciB0aGVuIFwiaWlpaVwiLCBidXQgdGhlIGxhdHRlciBpcyBhIGxvbmdlclxuXHRcdCAqIHN0cmluZyAtIHRodXMgdGhlIGNhbGN1bGF0aW9uIGNhbiBnbyB3cm9uZyAoZG9pbmcgaXQgcHJvcGVybHkgYW5kIHB1dHRpbmdcblx0XHQgKiBpdCBpbnRvIGFuIERPTSBvYmplY3QgYW5kIG1lYXN1cmluZyB0aGF0IGlzIGhvcnJpYmx5KCEpIHNsb3cpLiBUaHVzIGFzXG5cdFx0ICogYSBcIndvcmsgYXJvdW5kXCIgd2UgcHJvdmlkZSB0aGlzIG9wdGlvbi4gSXQgd2lsbCBhcHBlbmQgaXRzIHZhbHVlIHRvIHRoZVxuXHRcdCAqIHRleHQgdGhhdCBpcyBmb3VuZCB0byBiZSB0aGUgbG9uZ2VzdCBzdHJpbmcgZm9yIHRoZSBjb2x1bW4gLSBpLmUuIHBhZGRpbmcuXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqL1xuXHRcdFwic0NvbnRlbnRQYWRkaW5nXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFsbG93cyBhIGRlZmF1bHQgdmFsdWUgdG8gYmUgZ2l2ZW4gZm9yIGEgY29sdW1uJ3MgZGF0YSwgYW5kIHdpbGwgYmUgdXNlZFxuXHRcdCAqIHdoZW5ldmVyIGEgbnVsbCBkYXRhIHNvdXJjZSBpcyBlbmNvdW50ZXJlZCAodGhpcyBjYW4gYmUgYmVjYXVzZSBtRGF0YVxuXHRcdCAqIGlzIHNldCB0byBudWxsLCBvciBiZWNhdXNlIHRoZSBkYXRhIHNvdXJjZSBpdHNlbGYgaXMgbnVsbCkuXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJzRGVmYXVsdENvbnRlbnRcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogTmFtZSBmb3IgdGhlIGNvbHVtbiwgYWxsb3dpbmcgcmVmZXJlbmNlIHRvIHRoZSBjb2x1bW4gYnkgbmFtZSBhcyB3ZWxsIGFzXG5cdFx0ICogYnkgaW5kZXggKG5lZWRzIGEgbG9va3VwIHRvIHdvcmsgYnkgbmFtZSkuXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqL1xuXHRcdFwic05hbWVcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogQ3VzdG9tIHNvcnRpbmcgZGF0YSB0eXBlIC0gZGVmaW5lcyB3aGljaCBvZiB0aGUgYXZhaWxhYmxlIHBsdWctaW5zIGluXG5cdFx0ICogYWZuU29ydERhdGEgdGhlIGN1c3RvbSBzb3J0aW5nIHdpbGwgdXNlIC0gaWYgYW55IGlzIGRlZmluZWQuXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCBzdGRcblx0XHQgKi9cblx0XHRcInNTb3J0RGF0YVR5cGVcIjogJ3N0ZCcsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIENsYXNzIHRvIGJlIGFwcGxpZWQgdG8gdGhlIGhlYWRlciBlbGVtZW50IHdoZW4gc29ydGluZyBvbiB0aGlzIGNvbHVtblxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwic1NvcnRpbmdDbGFzc1wiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBDbGFzcyB0byBiZSBhcHBsaWVkIHRvIHRoZSBoZWFkZXIgZWxlbWVudCB3aGVuIHNvcnRpbmcgb24gdGhpcyBjb2x1bW4gLVxuXHRcdCAqIHdoZW4galF1ZXJ5IFVJIHRoZW1pbmcgaXMgdXNlZC5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcInNTb3J0aW5nQ2xhc3NKVUlcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogVGl0bGUgb2YgdGhlIGNvbHVtbiAtIHdoYXQgaXMgc2VlbiBpbiB0aGUgVEggZWxlbWVudCAoblRoKS5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICovXG5cdFx0XCJzVGl0bGVcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogQ29sdW1uIHNvcnRpbmcgYW5kIGZpbHRlcmluZyB0eXBlXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJzVHlwZVwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBXaWR0aCBvZiB0aGUgY29sdW1uXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJzV2lkdGhcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogV2lkdGggb2YgdGhlIGNvbHVtbiB3aGVuIGl0IHdhcyBmaXJzdCBcImVuY291bnRlcmVkXCJcblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcInNXaWR0aE9yaWdcIjogbnVsbFxuXHR9O1xuXHRcblx0XG5cdC8qXG5cdCAqIERldmVsb3BlciBub3RlOiBUaGUgcHJvcGVydGllcyBvZiB0aGUgb2JqZWN0IGJlbG93IGFyZSBnaXZlbiBpbiBIdW5nYXJpYW5cblx0ICogbm90YXRpb24sIHRoYXQgd2FzIHVzZWQgYXMgdGhlIGludGVyZmFjZSBmb3IgRGF0YVRhYmxlcyBwcmlvciB0byB2MS4xMCwgaG93ZXZlclxuXHQgKiBmcm9tIHYxLjEwIG9ud2FyZHMgdGhlIHByaW1hcnkgaW50ZXJmYWNlIGlzIGNhbWVsIGNhc2UuIEluIG9yZGVyIHRvIGF2b2lkXG5cdCAqIGJyZWFraW5nIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5IHV0dGVybHkgd2l0aCB0aGlzIGNoYW5nZSwgdGhlIEh1bmdhcmlhblxuXHQgKiB2ZXJzaW9uIGlzIHN0aWxsLCBpbnRlcm5hbGx5IHRoZSBwcmltYXJ5IGludGVyZmFjZSwgYnV0IGlzIGlzIG5vdCBkb2N1bWVudGVkXG5cdCAqIC0gaGVuY2UgdGhlIEBuYW1lIHRhZ3MgaW4gZWFjaCBkb2MgY29tbWVudC4gVGhpcyBhbGxvd3MgYSBKYXZhc2NyaXB0IGZ1bmN0aW9uXG5cdCAqIHRvIGNyZWF0ZSBhIG1hcCBmcm9tIEh1bmdhcmlhbiBub3RhdGlvbiB0byBjYW1lbCBjYXNlIChnb2luZyB0aGUgb3RoZXIgZGlyZWN0aW9uXG5cdCAqIHdvdWxkIHJlcXVpcmUgZWFjaCBwcm9wZXJ0eSB0byBiZSBsaXN0ZWQsIHdoaWNoIHdvdWxkIGF0IGFyb3VuZCAzSyB0byB0aGUgc2l6ZVxuXHQgKiBvZiBEYXRhVGFibGVzLCB3aGlsZSB0aGlzIG1ldGhvZCBpcyBhYm91dCBhIDAuNUsgaGl0LlxuXHQgKlxuXHQgKiBVbHRpbWF0ZWx5IHRoaXMgZG9lcyBwYXZlIHRoZSB3YXkgZm9yIEh1bmdhcmlhbiBub3RhdGlvbiB0byBiZSBkcm9wcGVkXG5cdCAqIGNvbXBsZXRlbHksIGJ1dCB0aGF0IGlzIGEgbWFzc2l2ZSBhbW91bnQgb2Ygd29yayBhbmQgd2lsbCBicmVhayBjdXJyZW50XG5cdCAqIGluc3RhbGxzICh0aGVyZWZvcmUgaXMgb24taG9sZCB1bnRpbCB2MikuXG5cdCAqL1xuXHRcblx0LyoqXG5cdCAqIEluaXRpYWxpc2F0aW9uIG9wdGlvbnMgdGhhdCBjYW4gYmUgZ2l2ZW4gdG8gRGF0YVRhYmxlcyBhdCBpbml0aWFsaXNhdGlvblxuXHQgKiB0aW1lLlxuXHQgKiAgQG5hbWVzcGFjZVxuXHQgKi9cblx0RGF0YVRhYmxlLmRlZmF1bHRzID0ge1xuXHRcdC8qKlxuXHRcdCAqIEFuIGFycmF5IG9mIGRhdGEgdG8gdXNlIGZvciB0aGUgdGFibGUsIHBhc3NlZCBpbiBhdCBpbml0aWFsaXNhdGlvbiB3aGljaFxuXHRcdCAqIHdpbGwgYmUgdXNlZCBpbiBwcmVmZXJlbmNlIHRvIGFueSBkYXRhIHdoaWNoIGlzIGFscmVhZHkgaW4gdGhlIERPTS4gVGhpcyBpc1xuXHRcdCAqIHBhcnRpY3VsYXJseSB1c2VmdWwgZm9yIGNvbnN0cnVjdGluZyB0YWJsZXMgcHVyZWx5IGluIEphdmFzY3JpcHQsIGZvclxuXHRcdCAqIGV4YW1wbGUgd2l0aCBhIGN1c3RvbSBBamF4IGNhbGwuXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgT3B0aW9uXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5kYXRhXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2luZyBhIDJEIGFycmF5IGRhdGEgc291cmNlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiZGF0YVwiOiBbXG5cdFx0ICogICAgICAgICAgWydUcmlkZW50JywgJ0ludGVybmV0IEV4cGxvcmVyIDQuMCcsICdXaW4gOTUrJywgNCwgJ1gnXSxcblx0XHQgKiAgICAgICAgICBbJ1RyaWRlbnQnLCAnSW50ZXJuZXQgRXhwbG9yZXIgNS4wJywgJ1dpbiA5NSsnLCA1LCAnQyddLFxuXHRcdCAqICAgICAgICBdLFxuXHRcdCAqICAgICAgICBcImNvbHVtbnNcIjogW1xuXHRcdCAqICAgICAgICAgIHsgXCJ0aXRsZVwiOiBcIkVuZ2luZVwiIH0sXG5cdFx0ICogICAgICAgICAgeyBcInRpdGxlXCI6IFwiQnJvd3NlclwiIH0sXG5cdFx0ICogICAgICAgICAgeyBcInRpdGxlXCI6IFwiUGxhdGZvcm1cIiB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJ0aXRsZVwiOiBcIlZlcnNpb25cIiB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJ0aXRsZVwiOiBcIkdyYWRlXCIgfVxuXHRcdCAqICAgICAgICBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYW4gYXJyYXkgb2Ygb2JqZWN0cyBhcyBhIGRhdGEgc291cmNlIChgZGF0YWApXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiZGF0YVwiOiBbXG5cdFx0ICogICAgICAgICAge1xuXHRcdCAqICAgICAgICAgICAgXCJlbmdpbmVcIjogICBcIlRyaWRlbnRcIixcblx0XHQgKiAgICAgICAgICAgIFwiYnJvd3NlclwiOiAgXCJJbnRlcm5ldCBFeHBsb3JlciA0LjBcIixcblx0XHQgKiAgICAgICAgICAgIFwicGxhdGZvcm1cIjogXCJXaW4gOTUrXCIsXG5cdFx0ICogICAgICAgICAgICBcInZlcnNpb25cIjogIDQsXG5cdFx0ICogICAgICAgICAgICBcImdyYWRlXCI6ICAgIFwiWFwiXG5cdFx0ICogICAgICAgICAgfSxcblx0XHQgKiAgICAgICAgICB7XG5cdFx0ICogICAgICAgICAgICBcImVuZ2luZVwiOiAgIFwiVHJpZGVudFwiLFxuXHRcdCAqICAgICAgICAgICAgXCJicm93c2VyXCI6ICBcIkludGVybmV0IEV4cGxvcmVyIDUuMFwiLFxuXHRcdCAqICAgICAgICAgICAgXCJwbGF0Zm9ybVwiOiBcIldpbiA5NStcIixcblx0XHQgKiAgICAgICAgICAgIFwidmVyc2lvblwiOiAgNSxcblx0XHQgKiAgICAgICAgICAgIFwiZ3JhZGVcIjogICAgXCJDXCJcblx0XHQgKiAgICAgICAgICB9XG5cdFx0ICogICAgICAgIF0sXG5cdFx0ICogICAgICAgIFwiY29sdW1uc1wiOiBbXG5cdFx0ICogICAgICAgICAgeyBcInRpdGxlXCI6IFwiRW5naW5lXCIsICAgXCJkYXRhXCI6IFwiZW5naW5lXCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwidGl0bGVcIjogXCJCcm93c2VyXCIsICBcImRhdGFcIjogXCJicm93c2VyXCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwidGl0bGVcIjogXCJQbGF0Zm9ybVwiLCBcImRhdGFcIjogXCJwbGF0Zm9ybVwiIH0sXG5cdFx0ICogICAgICAgICAgeyBcInRpdGxlXCI6IFwiVmVyc2lvblwiLCAgXCJkYXRhXCI6IFwidmVyc2lvblwiIH0sXG5cdFx0ICogICAgICAgICAgeyBcInRpdGxlXCI6IFwiR3JhZGVcIiwgICAgXCJkYXRhXCI6IFwiZ3JhZGVcIiB9XG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJhYURhdGFcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIElmIG9yZGVyaW5nIGlzIGVuYWJsZWQsIHRoZW4gRGF0YVRhYmxlcyB3aWxsIHBlcmZvcm0gYSBmaXJzdCBwYXNzIHNvcnQgb25cblx0XHQgKiBpbml0aWFsaXNhdGlvbi4gWW91IGNhbiBkZWZpbmUgd2hpY2ggY29sdW1uKHMpIHRoZSBzb3J0IGlzIHBlcmZvcm1lZFxuXHRcdCAqIHVwb24sIGFuZCB0aGUgc29ydGluZyBkaXJlY3Rpb24sIHdpdGggdGhpcyB2YXJpYWJsZS4gVGhlIGBzb3J0aW5nYCBhcnJheVxuXHRcdCAqIHNob3VsZCBjb250YWluIGFuIGFycmF5IGZvciBlYWNoIGNvbHVtbiB0byBiZSBzb3J0ZWQgaW5pdGlhbGx5IGNvbnRhaW5pbmdcblx0XHQgKiB0aGUgY29sdW1uJ3MgaW5kZXggYW5kIGEgZGlyZWN0aW9uIHN0cmluZyAoJ2FzYycgb3IgJ2Rlc2MnKS5cblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW1swLCdhc2MnXV1cblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgT3B0aW9uXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5vcmRlclxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gU29ydCBieSAzcmQgY29sdW1uIGZpcnN0LCBhbmQgdGhlbiA0dGggY29sdW1uXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJvcmRlclwiOiBbWzIsJ2FzYyddLCBbMywnZGVzYyddXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICAgIC8vIE5vIGluaXRpYWwgc29ydGluZ1xuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwib3JkZXJcIjogW11cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJhYVNvcnRpbmdcIjogW1swLCdhc2MnXV0sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBUaGlzIHBhcmFtZXRlciBpcyBiYXNpY2FsbHkgaWRlbnRpY2FsIHRvIHRoZSBgc29ydGluZ2AgcGFyYW1ldGVyLCBidXRcblx0XHQgKiBjYW5ub3QgYmUgb3ZlcnJpZGRlbiBieSB1c2VyIGludGVyYWN0aW9uIHdpdGggdGhlIHRhYmxlLiBXaGF0IHRoaXMgbWVhbnNcblx0XHQgKiBpcyB0aGF0IHlvdSBjb3VsZCBoYXZlIGEgY29sdW1uICh2aXNpYmxlIG9yIGhpZGRlbikgd2hpY2ggdGhlIHNvcnRpbmdcblx0XHQgKiB3aWxsIGFsd2F5cyBiZSBmb3JjZWQgb24gZmlyc3QgLSBhbnkgc29ydGluZyBhZnRlciB0aGF0IChmcm9tIHRoZSB1c2VyKVxuXHRcdCAqIHdpbGwgdGhlbiBiZSBwZXJmb3JtZWQgYXMgcmVxdWlyZWQuIFRoaXMgY2FuIGJlIHVzZWZ1bCBmb3IgZ3JvdXBpbmcgcm93c1xuXHRcdCAqIHRvZ2V0aGVyLlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvblxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMub3JkZXJGaXhlZFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJvcmRlckZpeGVkXCI6IFtbMCwnYXNjJ11dXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApXG5cdFx0ICovXG5cdFx0XCJhYVNvcnRpbmdGaXhlZFwiOiBbXSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIERhdGFUYWJsZXMgY2FuIGJlIGluc3RydWN0ZWQgdG8gbG9hZCBkYXRhIHRvIGRpc3BsYXkgaW4gdGhlIHRhYmxlIGZyb20gYVxuXHRcdCAqIEFqYXggc291cmNlLiBUaGlzIG9wdGlvbiBkZWZpbmVzIGhvdyB0aGF0IEFqYXggY2FsbCBpcyBtYWRlIGFuZCB3aGVyZSB0by5cblx0XHQgKlxuXHRcdCAqIFRoZSBgYWpheGAgcHJvcGVydHkgaGFzIHRocmVlIGRpZmZlcmVudCBtb2RlcyBvZiBvcGVyYXRpb24sIGRlcGVuZGluZyBvblxuXHRcdCAqIGhvdyBpdCBpcyBkZWZpbmVkLiBUaGVzZSBhcmU6XG5cdFx0ICpcblx0XHQgKiAqIGBzdHJpbmdgIC0gU2V0IHRoZSBVUkwgZnJvbSB3aGVyZSB0aGUgZGF0YSBzaG91bGQgYmUgbG9hZGVkIGZyb20uXG5cdFx0ICogKiBgb2JqZWN0YCAtIERlZmluZSBwcm9wZXJ0aWVzIGZvciBgalF1ZXJ5LmFqYXhgLlxuXHRcdCAqICogYGZ1bmN0aW9uYCAtIEN1c3RvbSBkYXRhIGdldCBmdW5jdGlvblxuXHRcdCAqXG5cdFx0ICogYHN0cmluZ2Bcblx0XHQgKiAtLS0tLS0tLVxuXHRcdCAqXG5cdFx0ICogQXMgYSBzdHJpbmcsIHRoZSBgYWpheGAgcHJvcGVydHkgc2ltcGx5IGRlZmluZXMgdGhlIFVSTCBmcm9tIHdoaWNoXG5cdFx0ICogRGF0YVRhYmxlcyB3aWxsIGxvYWQgZGF0YS5cblx0XHQgKlxuXHRcdCAqIGBvYmplY3RgXG5cdFx0ICogLS0tLS0tLS1cblx0XHQgKlxuXHRcdCAqIEFzIGFuIG9iamVjdCwgdGhlIHBhcmFtZXRlcnMgaW4gdGhlIG9iamVjdCBhcmUgcGFzc2VkIHRvXG5cdFx0ICogW2pRdWVyeS5hamF4XShodHRwOi8vYXBpLmpxdWVyeS5jb20valF1ZXJ5LmFqYXgvKSBhbGxvd2luZyBmaW5lIGNvbnRyb2xcblx0XHQgKiBvZiB0aGUgQWpheCByZXF1ZXN0LiBEYXRhVGFibGVzIGhhcyBhIG51bWJlciBvZiBkZWZhdWx0IHBhcmFtZXRlcnMgd2hpY2hcblx0XHQgKiB5b3UgY2FuIG92ZXJyaWRlIHVzaW5nIHRoaXMgb3B0aW9uLiBQbGVhc2UgcmVmZXIgdG8gdGhlIGpRdWVyeVxuXHRcdCAqIGRvY3VtZW50YXRpb24gZm9yIGEgZnVsbCBkZXNjcmlwdGlvbiBvZiB0aGUgb3B0aW9ucyBhdmFpbGFibGUsIGFsdGhvdWdoXG5cdFx0ICogdGhlIGZvbGxvd2luZyBwYXJhbWV0ZXJzIHByb3ZpZGUgYWRkaXRpb25hbCBvcHRpb25zIGluIERhdGFUYWJsZXMgb3Jcblx0XHQgKiByZXF1aXJlIHNwZWNpYWwgY29uc2lkZXJhdGlvbjpcblx0XHQgKlxuXHRcdCAqICogYGRhdGFgIC0gQXMgd2l0aCBqUXVlcnksIGBkYXRhYCBjYW4gYmUgcHJvdmlkZWQgYXMgYW4gb2JqZWN0LCBidXQgaXRcblx0XHQgKiAgIGNhbiBhbHNvIGJlIHVzZWQgYXMgYSBmdW5jdGlvbiB0byBtYW5pcHVsYXRlIHRoZSBkYXRhIERhdGFUYWJsZXMgc2VuZHNcblx0XHQgKiAgIHRvIHRoZSBzZXJ2ZXIuIFRoZSBmdW5jdGlvbiB0YWtlcyBhIHNpbmdsZSBwYXJhbWV0ZXIsIGFuIG9iamVjdCBvZlxuXHRcdCAqICAgcGFyYW1ldGVycyB3aXRoIHRoZSB2YWx1ZXMgdGhhdCBEYXRhVGFibGVzIGhhcyByZWFkaWVkIGZvciBzZW5kaW5nLiBBblxuXHRcdCAqICAgb2JqZWN0IG1heSBiZSByZXR1cm5lZCB3aGljaCB3aWxsIGJlIG1lcmdlZCBpbnRvIHRoZSBEYXRhVGFibGVzXG5cdFx0ICogICBkZWZhdWx0cywgb3IgeW91IGNhbiBhZGQgdGhlIGl0ZW1zIHRvIHRoZSBvYmplY3QgdGhhdCB3YXMgcGFzc2VkIGluIGFuZFxuXHRcdCAqICAgbm90IHJldHVybiBhbnl0aGluZyBmcm9tIHRoZSBmdW5jdGlvbi4gVGhpcyBzdXBlcnNlZGVzIGBmblNlcnZlclBhcmFtc2Bcblx0XHQgKiAgIGZyb20gRGF0YVRhYmxlcyAxLjktLlxuXHRcdCAqXG5cdFx0ICogKiBgZGF0YVNyY2AgLSBCeSBkZWZhdWx0IERhdGFUYWJsZXMgd2lsbCBsb29rIGZvciB0aGUgcHJvcGVydHkgYGRhdGFgIChvclxuXHRcdCAqICAgYGFhRGF0YWAgZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBEYXRhVGFibGVzIDEuOS0pIHdoZW4gb2J0YWluaW5nIGRhdGFcblx0XHQgKiAgIGZyb20gYW4gQWpheCBzb3VyY2Ugb3IgZm9yIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcgLSB0aGlzIHBhcmFtZXRlclxuXHRcdCAqICAgYWxsb3dzIHRoYXQgcHJvcGVydHkgdG8gYmUgY2hhbmdlZC4gWW91IGNhbiB1c2UgSmF2YXNjcmlwdCBkb3R0ZWRcblx0XHQgKiAgIG9iamVjdCBub3RhdGlvbiB0byBnZXQgYSBkYXRhIHNvdXJjZSBmb3IgbXVsdGlwbGUgbGV2ZWxzIG9mIG5lc3RpbmcsIG9yXG5cdFx0ICogICBpdCBteSBiZSB1c2VkIGFzIGEgZnVuY3Rpb24uIEFzIGEgZnVuY3Rpb24gaXQgdGFrZXMgYSBzaW5nbGUgcGFyYW1ldGVyLFxuXHRcdCAqICAgdGhlIEpTT04gcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyLCB3aGljaCBjYW4gYmUgbWFuaXB1bGF0ZWQgYXNcblx0XHQgKiAgIHJlcXVpcmVkLCB3aXRoIHRoZSByZXR1cm5lZCB2YWx1ZSBiZWluZyB0aGF0IHVzZWQgYnkgRGF0YVRhYmxlcyBhcyB0aGVcblx0XHQgKiAgIGRhdGEgc291cmNlIGZvciB0aGUgdGFibGUuIFRoaXMgc3VwZXJzZWRlcyBgc0FqYXhEYXRhUHJvcGAgZnJvbVxuXHRcdCAqICAgRGF0YVRhYmxlcyAxLjktLlxuXHRcdCAqXG5cdFx0ICogKiBgc3VjY2Vzc2AgLSBTaG91bGQgbm90IGJlIG92ZXJyaWRkZW4gaXQgaXMgdXNlZCBpbnRlcm5hbGx5IGluXG5cdFx0ICogICBEYXRhVGFibGVzLiBUbyBtYW5pcHVsYXRlIC8gdHJhbnNmb3JtIHRoZSBkYXRhIHJldHVybmVkIGJ5IHRoZSBzZXJ2ZXJcblx0XHQgKiAgIHVzZSBgYWpheC5kYXRhU3JjYCwgb3IgdXNlIGBhamF4YCBhcyBhIGZ1bmN0aW9uIChzZWUgYmVsb3cpLlxuXHRcdCAqXG5cdFx0ICogYGZ1bmN0aW9uYFxuXHRcdCAqIC0tLS0tLS0tLS1cblx0XHQgKlxuXHRcdCAqIEFzIGEgZnVuY3Rpb24sIG1ha2luZyB0aGUgQWpheCBjYWxsIGlzIGxlZnQgdXAgdG8geW91cnNlbGYgYWxsb3dpbmdcblx0XHQgKiBjb21wbGV0ZSBjb250cm9sIG9mIHRoZSBBamF4IHJlcXVlc3QuIEluZGVlZCwgaWYgZGVzaXJlZCwgYSBtZXRob2Qgb3RoZXJcblx0XHQgKiB0aGFuIEFqYXggY291bGQgYmUgdXNlZCB0byBvYnRhaW4gdGhlIHJlcXVpcmVkIGRhdGEsIHN1Y2ggYXMgV2ViIHN0b3JhZ2Vcblx0XHQgKiBvciBhbiBBSVIgZGF0YWJhc2UuXG5cdFx0ICpcblx0XHQgKiBUaGUgZnVuY3Rpb24gaXMgZ2l2ZW4gZm91ciBwYXJhbWV0ZXJzIGFuZCBubyByZXR1cm4gaXMgcmVxdWlyZWQuIFRoZVxuXHRcdCAqIHBhcmFtZXRlcnMgYXJlOlxuXHRcdCAqXG5cdFx0ICogMS4gX29iamVjdF8gLSBEYXRhIHRvIHNlbmQgdG8gdGhlIHNlcnZlclxuXHRcdCAqIDIuIF9mdW5jdGlvbl8gLSBDYWxsYmFjayBmdW5jdGlvbiB0aGF0IG11c3QgYmUgZXhlY3V0ZWQgd2hlbiB0aGUgcmVxdWlyZWRcblx0XHQgKiAgICBkYXRhIGhhcyBiZWVuIG9idGFpbmVkLiBUaGF0IGRhdGEgc2hvdWxkIGJlIHBhc3NlZCBpbnRvIHRoZSBjYWxsYmFja1xuXHRcdCAqICAgIGFzIHRoZSBvbmx5IHBhcmFtZXRlclxuXHRcdCAqIDMuIF9vYmplY3RfIC0gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QgZm9yIHRoZSB0YWJsZVxuXHRcdCAqXG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgc3VwZXJzZWRlcyBgZm5TZXJ2ZXJEYXRhYCBmcm9tIERhdGFUYWJsZXMgMS45LS5cblx0XHQgKlxuXHRcdCAqICBAdHlwZSBzdHJpbmd8b2JqZWN0fGZ1bmN0aW9uXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgT3B0aW9uXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5hamF4XG5cdFx0ICogIEBzaW5jZSAxLjEwLjBcblx0XHQgKlxuXHRcdCAqIEBleGFtcGxlXG5cdFx0ICogICAvLyBHZXQgSlNPTiBkYXRhIGZyb20gYSBmaWxlIHZpYSBBamF4LlxuXHRcdCAqICAgLy8gTm90ZSBEYXRhVGFibGVzIGV4cGVjdHMgZGF0YSBpbiB0aGUgZm9ybSBgeyBkYXRhOiBbIC4uLmRhdGEuLi4gXSB9YCBieSBkZWZhdWx0KS5cblx0XHQgKiAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgIFwiYWpheFwiOiBcImRhdGEuanNvblwiXG5cdFx0ICogICB9ICk7XG5cdFx0ICpcblx0XHQgKiBAZXhhbXBsZVxuXHRcdCAqICAgLy8gR2V0IEpTT04gZGF0YSBmcm9tIGEgZmlsZSB2aWEgQWpheCwgdXNpbmcgYGRhdGFTcmNgIHRvIGNoYW5nZVxuXHRcdCAqICAgLy8gYGRhdGFgIHRvIGB0YWJsZURhdGFgIChpLmUuIGB7IHRhYmxlRGF0YTogWyAuLi5kYXRhLi4uIF0gfWApXG5cdFx0ICogICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICBcImFqYXhcIjoge1xuXHRcdCAqICAgICAgIFwidXJsXCI6IFwiZGF0YS5qc29uXCIsXG5cdFx0ICogICAgICAgXCJkYXRhU3JjXCI6IFwidGFibGVEYXRhXCJcblx0XHQgKiAgICAgfVxuXHRcdCAqICAgfSApO1xuXHRcdCAqXG5cdFx0ICogQGV4YW1wbGVcblx0XHQgKiAgIC8vIEdldCBKU09OIGRhdGEgZnJvbSBhIGZpbGUgdmlhIEFqYXgsIHVzaW5nIGBkYXRhU3JjYCB0byByZWFkIGRhdGFcblx0XHQgKiAgIC8vIGZyb20gYSBwbGFpbiBhcnJheSByYXRoZXIgdGhhbiBhbiBhcnJheSBpbiBhbiBvYmplY3Rcblx0XHQgKiAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgIFwiYWpheFwiOiB7XG5cdFx0ICogICAgICAgXCJ1cmxcIjogXCJkYXRhLmpzb25cIixcblx0XHQgKiAgICAgICBcImRhdGFTcmNcIjogXCJcIlxuXHRcdCAqICAgICB9XG5cdFx0ICogICB9ICk7XG5cdFx0ICpcblx0XHQgKiBAZXhhbXBsZVxuXHRcdCAqICAgLy8gTWFuaXB1bGF0ZSB0aGUgZGF0YSByZXR1cm5lZCBmcm9tIHRoZSBzZXJ2ZXIgLSBhZGQgYSBsaW5rIHRvIGRhdGFcblx0XHQgKiAgIC8vIChub3RlIHRoaXMgY2FuLCBzaG91bGQsIGJlIGRvbmUgdXNpbmcgYHJlbmRlcmAgZm9yIHRoZSBjb2x1bW4gLSB0aGlzXG5cdFx0ICogICAvLyBpcyBqdXN0IGEgc2ltcGxlIGV4YW1wbGUgb2YgaG93IHRoZSBkYXRhIGNhbiBiZSBtYW5pcHVsYXRlZCkuXG5cdFx0ICogICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICBcImFqYXhcIjoge1xuXHRcdCAqICAgICAgIFwidXJsXCI6IFwiZGF0YS5qc29uXCIsXG5cdFx0ICogICAgICAgXCJkYXRhU3JjXCI6IGZ1bmN0aW9uICgganNvbiApIHtcblx0XHQgKiAgICAgICAgIGZvciAoIHZhciBpPTAsIGllbj1qc29uLmxlbmd0aCA7IGk8aWVuIDsgaSsrICkge1xuXHRcdCAqICAgICAgICAgICBqc29uW2ldWzBdID0gJzxhIGhyZWY9XCIvbWVzc2FnZS8nK2pzb25baV1bMF0rJz5WaWV3IG1lc3NhZ2U8L2E+Jztcblx0XHQgKiAgICAgICAgIH1cblx0XHQgKiAgICAgICAgIHJldHVybiBqc29uO1xuXHRcdCAqICAgICAgIH1cblx0XHQgKiAgICAgfVxuXHRcdCAqICAgfSApO1xuXHRcdCAqXG5cdFx0ICogQGV4YW1wbGVcblx0XHQgKiAgIC8vIEFkZCBkYXRhIHRvIHRoZSByZXF1ZXN0XG5cdFx0ICogICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICBcImFqYXhcIjoge1xuXHRcdCAqICAgICAgIFwidXJsXCI6IFwiZGF0YS5qc29uXCIsXG5cdFx0ICogICAgICAgXCJkYXRhXCI6IGZ1bmN0aW9uICggZCApIHtcblx0XHQgKiAgICAgICAgIHJldHVybiB7XG5cdFx0ICogICAgICAgICAgIFwiZXh0cmFfc2VhcmNoXCI6ICQoJyNleHRyYScpLnZhbCgpXG5cdFx0ICogICAgICAgICB9O1xuXHRcdCAqICAgICAgIH1cblx0XHQgKiAgICAgfVxuXHRcdCAqICAgfSApO1xuXHRcdCAqXG5cdFx0ICogQGV4YW1wbGVcblx0XHQgKiAgIC8vIFNlbmQgcmVxdWVzdCBhcyBQT1NUXG5cdFx0ICogICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICBcImFqYXhcIjoge1xuXHRcdCAqICAgICAgIFwidXJsXCI6IFwiZGF0YS5qc29uXCIsXG5cdFx0ICogICAgICAgXCJ0eXBlXCI6IFwiUE9TVFwiXG5cdFx0ICogICAgIH1cblx0XHQgKiAgIH0gKTtcblx0XHQgKlxuXHRcdCAqIEBleGFtcGxlXG5cdFx0ICogICAvLyBHZXQgdGhlIGRhdGEgZnJvbSBsb2NhbFN0b3JhZ2UgKGNvdWxkIGludGVyZmFjZSB3aXRoIGEgZm9ybSBmb3Jcblx0XHQgKiAgIC8vIGFkZGluZywgZWRpdGluZyBhbmQgcmVtb3Zpbmcgcm93cykuXG5cdFx0ICogICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICBcImFqYXhcIjogZnVuY3Rpb24gKGRhdGEsIGNhbGxiYWNrLCBzZXR0aW5ncykge1xuXHRcdCAqICAgICAgIGNhbGxiYWNrKFxuXHRcdCAqICAgICAgICAgSlNPTi5wYXJzZSggbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ2RhdGFUYWJsZXNEYXRhJykgKVxuXHRcdCAqICAgICAgICk7XG5cdFx0ICogICAgIH1cblx0XHQgKiAgIH0gKTtcblx0XHQgKi9cblx0XHRcImFqYXhcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoaXMgcGFyYW1ldGVyIGFsbG93cyB5b3UgdG8gcmVhZGlseSBzcGVjaWZ5IHRoZSBlbnRyaWVzIGluIHRoZSBsZW5ndGggZHJvcFxuXHRcdCAqIGRvd24gbWVudSB0aGF0IERhdGFUYWJsZXMgc2hvd3Mgd2hlbiBwYWdpbmF0aW9uIGlzIGVuYWJsZWQuIEl0IGNhbiBiZVxuXHRcdCAqIGVpdGhlciBhIDFEIGFycmF5IG9mIG9wdGlvbnMgd2hpY2ggd2lsbCBiZSB1c2VkIGZvciBib3RoIHRoZSBkaXNwbGF5ZWRcblx0XHQgKiBvcHRpb24gYW5kIHRoZSB2YWx1ZSwgb3IgYSAyRCBhcnJheSB3aGljaCB3aWxsIHVzZSB0aGUgYXJyYXkgaW4gdGhlIGZpcnN0XG5cdFx0ICogcG9zaXRpb24gYXMgdGhlIHZhbHVlLCBhbmQgdGhlIGFycmF5IGluIHRoZSBzZWNvbmQgcG9zaXRpb24gYXMgdGhlXG5cdFx0ICogZGlzcGxheWVkIG9wdGlvbnMgKHVzZWZ1bCBmb3IgbGFuZ3VhZ2Ugc3RyaW5ncyBzdWNoIGFzICdBbGwnKS5cblx0XHQgKlxuXHRcdCAqIE5vdGUgdGhhdCB0aGUgYHBhZ2VMZW5ndGhgIHByb3BlcnR5IHdpbGwgYmUgYXV0b21hdGljYWxseSBzZXQgdG8gdGhlXG5cdFx0ICogZmlyc3QgdmFsdWUgZ2l2ZW4gaW4gdGhpcyBhcnJheSwgdW5sZXNzIGBwYWdlTGVuZ3RoYCBpcyBhbHNvIHByb3ZpZGVkLlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbIDEwLCAyNSwgNTAsIDEwMCBdXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvblxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGVuZ3RoTWVudVxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJsZW5ndGhNZW51XCI6IFtbMTAsIDI1LCA1MCwgLTFdLCBbMTAsIDI1LCA1MCwgXCJBbGxcIl1dXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiYUxlbmd0aE1lbnVcIjogWyAxMCwgMjUsIDUwLCAxMDAgXSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoZSBgY29sdW1uc2Agb3B0aW9uIGluIHRoZSBpbml0aWFsaXNhdGlvbiBwYXJhbWV0ZXIgYWxsb3dzIHlvdSB0byBkZWZpbmVcblx0XHQgKiBkZXRhaWxzIGFib3V0IHRoZSB3YXkgaW5kaXZpZHVhbCBjb2x1bW5zIGJlaGF2ZS4gRm9yIGEgZnVsbCBsaXN0IG9mXG5cdFx0ICogY29sdW1uIG9wdGlvbnMgdGhhdCBjYW4gYmUgc2V0LCBwbGVhc2Ugc2VlXG5cdFx0ICoge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW59LiBOb3RlIHRoYXQgaWYgeW91IHVzZSBgY29sdW1uc2AgdG9cblx0XHQgKiBkZWZpbmUgeW91ciBjb2x1bW5zLCB5b3UgbXVzdCBoYXZlIGFuIGVudHJ5IGluIHRoZSBhcnJheSBmb3IgZXZlcnkgc2luZ2xlXG5cdFx0ICogY29sdW1uIHRoYXQgeW91IGhhdmUgaW4geW91ciB0YWJsZSAodGhlc2UgY2FuIGJlIG51bGwgaWYgeW91IGRvbid0IHdoaWNoXG5cdFx0ICogdG8gc3BlY2lmeSBhbnkgb3B0aW9ucykuXG5cdFx0ICogIEBtZW1iZXJcblx0XHQgKlxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uXG5cdFx0ICovXG5cdFx0XCJhb0NvbHVtbnNcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogVmVyeSBzaW1pbGFyIHRvIGBjb2x1bW5zYCwgYGNvbHVtbkRlZnNgIGFsbG93cyB5b3UgdG8gdGFyZ2V0IGEgc3BlY2lmaWNcblx0XHQgKiBjb2x1bW4sIG11bHRpcGxlIGNvbHVtbnMsIG9yIGFsbCBjb2x1bW5zLCB1c2luZyB0aGUgYHRhcmdldHNgIHByb3BlcnR5IG9mXG5cdFx0ICogZWFjaCBvYmplY3QgaW4gdGhlIGFycmF5LiBUaGlzIGFsbG93cyBncmVhdCBmbGV4aWJpbGl0eSB3aGVuIGNyZWF0aW5nXG5cdFx0ICogdGFibGVzLCBhcyB0aGUgYGNvbHVtbkRlZnNgIGFycmF5cyBjYW4gYmUgb2YgYW55IGxlbmd0aCwgdGFyZ2V0aW5nIHRoZVxuXHRcdCAqIGNvbHVtbnMgeW91IHNwZWNpZmljYWxseSB3YW50LiBgY29sdW1uRGVmc2AgbWF5IHVzZSBhbnkgb2YgdGhlIGNvbHVtblxuXHRcdCAqIG9wdGlvbnMgYXZhaWxhYmxlOiB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbn0sIGJ1dCBpdCBfbXVzdF9cblx0XHQgKiBoYXZlIGB0YXJnZXRzYCBkZWZpbmVkIGluIGVhY2ggb2JqZWN0IGluIHRoZSBhcnJheS4gVmFsdWVzIGluIHRoZSBgdGFyZ2V0c2Bcblx0XHQgKiBhcnJheSBtYXkgYmU6XG5cdFx0ICogICA8dWw+XG5cdFx0ICogICAgIDxsaT5hIHN0cmluZyAtIGNsYXNzIG5hbWUgd2lsbCBiZSBtYXRjaGVkIG9uIHRoZSBUSCBmb3IgdGhlIGNvbHVtbjwvbGk+XG5cdFx0ICogICAgIDxsaT4wIG9yIGEgcG9zaXRpdmUgaW50ZWdlciAtIGNvbHVtbiBpbmRleCBjb3VudGluZyBmcm9tIHRoZSBsZWZ0PC9saT5cblx0XHQgKiAgICAgPGxpPmEgbmVnYXRpdmUgaW50ZWdlciAtIGNvbHVtbiBpbmRleCBjb3VudGluZyBmcm9tIHRoZSByaWdodDwvbGk+XG5cdFx0ICogICAgIDxsaT50aGUgc3RyaW5nIFwiX2FsbFwiIC0gYWxsIGNvbHVtbnMgKGkuZS4gYXNzaWduIGEgZGVmYXVsdCk8L2xpPlxuXHRcdCAqICAgPC91bD5cblx0XHQgKiAgQG1lbWJlclxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW5EZWZzXG5cdFx0ICovXG5cdFx0XCJhb0NvbHVtbkRlZnNcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEJhc2ljYWxseSB0aGUgc2FtZSBhcyBgc2VhcmNoYCwgdGhpcyBwYXJhbWV0ZXIgZGVmaW5lcyB0aGUgaW5kaXZpZHVhbCBjb2x1bW5cblx0XHQgKiBmaWx0ZXJpbmcgc3RhdGUgYXQgaW5pdGlhbGlzYXRpb24gdGltZS4gVGhlIGFycmF5IG11c3QgYmUgb2YgdGhlIHNhbWUgc2l6ZVxuXHRcdCAqIGFzIHRoZSBudW1iZXIgb2YgY29sdW1ucywgYW5kIGVhY2ggZWxlbWVudCBiZSBhbiBvYmplY3Qgd2l0aCB0aGUgcGFyYW1ldGVyc1xuXHRcdCAqIGBzZWFyY2hgIGFuZCBgZXNjYXBlUmVnZXhgICh0aGUgbGF0dGVyIGlzIG9wdGlvbmFsKS4gJ251bGwnIGlzIGFsc29cblx0XHQgKiBhY2NlcHRlZCBhbmQgdGhlIGRlZmF1bHQgd2lsbCBiZSB1c2VkLlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBPcHRpb25cblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNlYXJjaENvbHNcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwic2VhcmNoQ29sc1wiOiBbXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICB7IFwic2VhcmNoXCI6IFwiTXkgZmlsdGVyXCIgfSxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIHsgXCJzZWFyY2hcIjogXCJeWzAtOV1cIiwgXCJlc2NhcGVSZWdleFwiOiBmYWxzZSB9XG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9IClcblx0XHQgKi9cblx0XHRcImFvU2VhcmNoQ29sc1wiOiBbXSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFuIGFycmF5IG9mIENTUyBjbGFzc2VzIHRoYXQgc2hvdWxkIGJlIGFwcGxpZWQgdG8gZGlzcGxheWVkIHJvd3MuIFRoaXNcblx0XHQgKiBhcnJheSBtYXkgYmUgb2YgYW55IGxlbmd0aCwgYW5kIERhdGFUYWJsZXMgd2lsbCBhcHBseSBlYWNoIGNsYXNzXG5cdFx0ICogc2VxdWVudGlhbGx5LCBsb29waW5nIHdoZW4gcmVxdWlyZWQuXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IG51bGwgPGk+V2lsbCB0YWtlIHRoZSB2YWx1ZXMgZGV0ZXJtaW5lZCBieSB0aGUgYG9DbGFzc2VzLnN0cmlwZSpgXG5cdFx0ICogICAgb3B0aW9uczwvaT5cblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgT3B0aW9uXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zdHJpcGVDbGFzc2VzXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcInN0cmlwZUNsYXNzZXNcIjogWyAnc3RyaXAxJywgJ3N0cmlwMicsICdzdHJpcDMnIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9IClcblx0XHQgKi9cblx0XHRcImFzU3RyaXBlQ2xhc3Nlc1wiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogRW5hYmxlIG9yIGRpc2FibGUgYXV0b21hdGljIGNvbHVtbiB3aWR0aCBjYWxjdWxhdGlvbi4gVGhpcyBjYW4gYmUgZGlzYWJsZWRcblx0XHQgKiBhcyBhbiBvcHRpbWlzYXRpb24gKGl0IHRha2VzIHNvbWUgdGltZSB0byBjYWxjdWxhdGUgdGhlIHdpZHRocykgaWYgdGhlXG5cdFx0ICogdGFibGVzIHdpZHRocyBhcmUgcGFzc2VkIGluIHVzaW5nIGBjb2x1bW5zYC5cblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqICBAZGVmYXVsdCB0cnVlXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IEZlYXR1cmVzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5hdXRvV2lkdGhcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiAoKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImF1dG9XaWR0aFwiOiBmYWxzZVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJBdXRvV2lkdGhcIjogdHJ1ZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIERlZmVycmVkIHJlbmRlcmluZyBjYW4gcHJvdmlkZSBEYXRhVGFibGVzIHdpdGggYSBodWdlIHNwZWVkIGJvb3N0IHdoZW4geW91XG5cdFx0ICogYXJlIHVzaW5nIGFuIEFqYXggb3IgSlMgZGF0YSBzb3VyY2UgZm9yIHRoZSB0YWJsZS4gVGhpcyBvcHRpb24sIHdoZW4gc2V0IHRvXG5cdFx0ICogdHJ1ZSwgd2lsbCBjYXVzZSBEYXRhVGFibGVzIHRvIGRlZmVyIHRoZSBjcmVhdGlvbiBvZiB0aGUgdGFibGUgZWxlbWVudHMgZm9yXG5cdFx0ICogZWFjaCByb3cgdW50aWwgdGhleSBhcmUgbmVlZGVkIGZvciBhIGRyYXcgLSBzYXZpbmcgYSBzaWduaWZpY2FudCBhbW91bnQgb2Zcblx0XHQgKiB0aW1lLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IEZlYXR1cmVzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5kZWZlclJlbmRlclxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJhamF4XCI6IFwic291cmNlcy9hcnJheXMudHh0XCIsXG5cdFx0ICogICAgICAgIFwiZGVmZXJSZW5kZXJcIjogdHJ1ZVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJEZWZlclJlbmRlclwiOiBmYWxzZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFJlcGxhY2UgYSBEYXRhVGFibGUgd2hpY2ggbWF0Y2hlcyB0aGUgZ2l2ZW4gc2VsZWN0b3IgYW5kIHJlcGxhY2UgaXQgd2l0aFxuXHRcdCAqIG9uZSB3aGljaCBoYXMgdGhlIHByb3BlcnRpZXMgb2YgdGhlIG5ldyBpbml0aWFsaXNhdGlvbiBvYmplY3QgcGFzc2VkLiBJZiBub1xuXHRcdCAqIHRhYmxlIG1hdGNoZXMgdGhlIHNlbGVjdG9yLCB0aGVuIHRoZSBuZXcgRGF0YVRhYmxlIHdpbGwgYmUgY29uc3RydWN0ZWQgYXNcblx0XHQgKiBwZXIgbm9ybWFsLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvbnNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmRlc3Ryb3lcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwic3JvbGxZXCI6IFwiMjAwcHhcIixcblx0XHQgKiAgICAgICAgXCJwYWdpbmF0ZVwiOiBmYWxzZVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqXG5cdFx0ICogICAgICAvLyBTb21lIHRpbWUgbGF0ZXIuLi4uXG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImZpbHRlclwiOiBmYWxzZSxcblx0XHQgKiAgICAgICAgXCJkZXN0cm95XCI6IHRydWVcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJiRGVzdHJveVwiOiBmYWxzZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEVuYWJsZSBvciBkaXNhYmxlIGZpbHRlcmluZyBvZiBkYXRhLiBGaWx0ZXJpbmcgaW4gRGF0YVRhYmxlcyBpcyBcInNtYXJ0XCIgaW5cblx0XHQgKiB0aGF0IGl0IGFsbG93cyB0aGUgZW5kIHVzZXIgdG8gaW5wdXQgbXVsdGlwbGUgd29yZHMgKHNwYWNlIHNlcGFyYXRlZCkgYW5kXG5cdFx0ICogd2lsbCBtYXRjaCBhIHJvdyBjb250YWluaW5nIHRob3NlIHdvcmRzLCBldmVuIGlmIG5vdCBpbiB0aGUgb3JkZXIgdGhhdCB3YXNcblx0XHQgKiBzcGVjaWZpZWQgKHRoaXMgYWxsb3cgbWF0Y2hpbmcgYWNyb3NzIG11bHRpcGxlIGNvbHVtbnMpLiBOb3RlIHRoYXQgaWYgeW91XG5cdFx0ICogd2lzaCB0byB1c2UgZmlsdGVyaW5nIGluIERhdGFUYWJsZXMgdGhpcyBtdXN0IHJlbWFpbiAndHJ1ZScgLSB0byByZW1vdmUgdGhlXG5cdFx0ICogZGVmYXVsdCBmaWx0ZXJpbmcgaW5wdXQgYm94IGFuZCByZXRhaW4gZmlsdGVyaW5nIGFiaWxpdGllcywgcGxlYXNlIHVzZVxuXHRcdCAqIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHMuZG9tfS5cblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqICBAZGVmYXVsdCB0cnVlXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IEZlYXR1cmVzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zZWFyY2hpbmdcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbiAoKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcInNlYXJjaGluZ1wiOiBmYWxzZVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJGaWx0ZXJcIjogdHJ1ZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEVuYWJsZSBvciBkaXNhYmxlIHRoZSB0YWJsZSBpbmZvcm1hdGlvbiBkaXNwbGF5LiBUaGlzIHNob3dzIGluZm9ybWF0aW9uXG5cdFx0ICogYWJvdXQgdGhlIGRhdGEgdGhhdCBpcyBjdXJyZW50bHkgdmlzaWJsZSBvbiB0aGUgcGFnZSwgaW5jbHVkaW5nIGluZm9ybWF0aW9uXG5cdFx0ICogYWJvdXQgZmlsdGVyZWQgZGF0YSBpZiB0aGF0IGFjdGlvbiBpcyBiZWluZyBwZXJmb3JtZWQuXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgdHJ1ZVxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBGZWF0dXJlc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuaW5mb1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiaW5mb1wiOiBmYWxzZVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJJbmZvXCI6IHRydWUsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBBbGxvd3MgdGhlIGVuZCB1c2VyIHRvIHNlbGVjdCB0aGUgc2l6ZSBvZiBhIGZvcm1hdHRlZCBwYWdlIGZyb20gYSBzZWxlY3Rcblx0XHQgKiBtZW51IChzaXplcyBhcmUgMTAsIDI1LCA1MCBhbmQgMTAwKS4gUmVxdWlyZXMgcGFnaW5hdGlvbiAoYHBhZ2luYXRlYCkuXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgdHJ1ZVxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBGZWF0dXJlc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGVuZ3RoQ2hhbmdlXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJsZW5ndGhDaGFuZ2VcIjogZmFsc2Vcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJiTGVuZ3RoQ2hhbmdlXCI6IHRydWUsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBFbmFibGUgb3IgZGlzYWJsZSBwYWdpbmF0aW9uLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IHRydWVcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgRmVhdHVyZXNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnBhZ2luZ1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwicGFnaW5nXCI6IGZhbHNlXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiYlBhZ2luYXRlXCI6IHRydWUsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBFbmFibGUgb3IgZGlzYWJsZSB0aGUgZGlzcGxheSBvZiBhICdwcm9jZXNzaW5nJyBpbmRpY2F0b3Igd2hlbiB0aGUgdGFibGUgaXNcblx0XHQgKiBiZWluZyBwcm9jZXNzZWQgKGUuZy4gYSBzb3J0KS4gVGhpcyBpcyBwYXJ0aWN1bGFybHkgdXNlZnVsIGZvciB0YWJsZXMgd2l0aFxuXHRcdCAqIGxhcmdlIGFtb3VudHMgb2YgZGF0YSB3aGVyZSBpdCBjYW4gdGFrZSBhIG5vdGljZWFibGUgYW1vdW50IG9mIHRpbWUgdG8gc29ydFxuXHRcdCAqIHRoZSBlbnRyaWVzLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IEZlYXR1cmVzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5wcm9jZXNzaW5nXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJwcm9jZXNzaW5nXCI6IHRydWVcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJiUHJvY2Vzc2luZ1wiOiBmYWxzZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFJldHJpZXZlIHRoZSBEYXRhVGFibGVzIG9iamVjdCBmb3IgdGhlIGdpdmVuIHNlbGVjdG9yLiBOb3RlIHRoYXQgaWYgdGhlXG5cdFx0ICogdGFibGUgaGFzIGFscmVhZHkgYmVlbiBpbml0aWFsaXNlZCwgdGhpcyBwYXJhbWV0ZXIgd2lsbCBjYXVzZSBEYXRhVGFibGVzXG5cdFx0ICogdG8gc2ltcGx5IHJldHVybiB0aGUgb2JqZWN0IHRoYXQgaGFzIGFscmVhZHkgYmVlbiBzZXQgdXAgLSBpdCB3aWxsIG5vdCB0YWtlXG5cdFx0ICogYWNjb3VudCBvZiBhbnkgY2hhbmdlcyB5b3UgbWlnaHQgaGF2ZSBtYWRlIHRvIHRoZSBpbml0aWFsaXNhdGlvbiBvYmplY3Rcblx0XHQgKiBwYXNzZWQgdG8gRGF0YVRhYmxlcyAoc2V0dGluZyB0aGlzIHBhcmFtZXRlciB0byB0cnVlIGlzIGFuIGFja25vd2xlZGdlbWVudFxuXHRcdCAqIHRoYXQgeW91IHVuZGVyc3RhbmQgdGhpcykuIGBkZXN0cm95YCBjYW4gYmUgdXNlZCB0byByZWluaXRpYWxpc2UgYSB0YWJsZSBpZlxuXHRcdCAqIHlvdSBuZWVkLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvbnNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnJldHJpZXZlXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICBpbml0VGFibGUoKTtcblx0XHQgKiAgICAgIHRhYmxlQWN0aW9ucygpO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICAgIGZ1bmN0aW9uIGluaXRUYWJsZSAoKVxuXHRcdCAqICAgIHtcblx0XHQgKiAgICAgIHJldHVybiAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcInNjcm9sbFlcIjogXCIyMDBweFwiLFxuXHRcdCAqICAgICAgICBcInBhZ2luYXRlXCI6IGZhbHNlLFxuXHRcdCAqICAgICAgICBcInJldHJpZXZlXCI6IHRydWVcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9XG5cdFx0ICpcblx0XHQgKiAgICBmdW5jdGlvbiB0YWJsZUFjdGlvbnMgKClcblx0XHQgKiAgICB7XG5cdFx0ICogICAgICB2YXIgdGFibGUgPSBpbml0VGFibGUoKTtcblx0XHQgKiAgICAgIC8vIHBlcmZvcm0gQVBJIG9wZXJhdGlvbnMgd2l0aCBvVGFibGVcblx0XHQgKiAgICB9XG5cdFx0ICovXG5cdFx0XCJiUmV0cmlldmVcIjogZmFsc2UsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBXaGVuIHZlcnRpY2FsICh5KSBzY3JvbGxpbmcgaXMgZW5hYmxlZCwgRGF0YVRhYmxlcyB3aWxsIGZvcmNlIHRoZSBoZWlnaHQgb2Zcblx0XHQgKiB0aGUgdGFibGUncyB2aWV3cG9ydCB0byB0aGUgZ2l2ZW4gaGVpZ2h0IGF0IGFsbCB0aW1lcyAodXNlZnVsIGZvciBsYXlvdXQpLlxuXHRcdCAqIEhvd2V2ZXIsIHRoaXMgY2FuIGxvb2sgb2RkIHdoZW4gZmlsdGVyaW5nIGRhdGEgZG93biB0byBhIHNtYWxsIGRhdGEgc2V0LFxuXHRcdCAqIGFuZCB0aGUgZm9vdGVyIGlzIGxlZnQgXCJmbG9hdGluZ1wiIGZ1cnRoZXIgZG93bi4gVGhpcyBwYXJhbWV0ZXIgKHdoZW5cblx0XHQgKiBlbmFibGVkKSB3aWxsIGNhdXNlIERhdGFUYWJsZXMgdG8gY29sbGFwc2UgdGhlIHRhYmxlJ3Mgdmlld3BvcnQgZG93biB3aGVuXG5cdFx0ICogdGhlIHJlc3VsdCBzZXQgd2lsbCBmaXQgd2l0aGluIHRoZSBnaXZlbiBZIGhlaWdodC5cblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqICBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBPcHRpb25zXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zY3JvbGxDb2xsYXBzZVxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJzY3JvbGxZXCI6IFwiMjAwXCIsXG5cdFx0ICogICAgICAgIFwic2Nyb2xsQ29sbGFwc2VcIjogdHJ1ZVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJTY3JvbGxDb2xsYXBzZVwiOiBmYWxzZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIENvbmZpZ3VyZSBEYXRhVGFibGVzIHRvIHVzZSBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nLiBOb3RlIHRoYXQgdGhlXG5cdFx0ICogYGFqYXhgIHBhcmFtZXRlciBtdXN0IGFsc28gYmUgZ2l2ZW4gaW4gb3JkZXIgdG8gZ2l2ZSBEYXRhVGFibGVzIGFcblx0XHQgKiBzb3VyY2UgdG8gb2J0YWluIHRoZSByZXF1aXJlZCBkYXRhIGZvciBlYWNoIGRyYXcuXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgRmVhdHVyZXNcblx0XHQgKiAgQGR0b3B0IFNlcnZlci1zaWRlXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zZXJ2ZXJTaWRlXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJzZXJ2ZXJTaWRlXCI6IHRydWUsXG5cdFx0ICogICAgICAgIFwiYWpheFwiOiBcInhoci5waHBcIlxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJTZXJ2ZXJTaWRlXCI6IGZhbHNlLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogRW5hYmxlIG9yIGRpc2FibGUgc29ydGluZyBvZiBjb2x1bW5zLiBTb3J0aW5nIG9mIGluZGl2aWR1YWwgY29sdW1ucyBjYW4gYmVcblx0XHQgKiBkaXNhYmxlZCBieSB0aGUgYHNvcnRhYmxlYCBvcHRpb24gZm9yIGVhY2ggY29sdW1uLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IHRydWVcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgRmVhdHVyZXNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLm9yZGVyaW5nXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJvcmRlcmluZ1wiOiBmYWxzZVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJTb3J0XCI6IHRydWUsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBFbmFibGUgb3IgZGlzcGxheSBEYXRhVGFibGVzJyBhYmlsaXR5IHRvIHNvcnQgbXVsdGlwbGUgY29sdW1ucyBhdCB0aGVcblx0XHQgKiBzYW1lIHRpbWUgKGFjdGl2YXRlZCBieSBzaGlmdC1jbGljayBieSB0aGUgdXNlcikuXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgdHJ1ZVxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBPcHRpb25zXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5vcmRlck11bHRpXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBEaXNhYmxlIG11bHRpcGxlIGNvbHVtbiBzb3J0aW5nIGFiaWxpdHlcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJvcmRlck11bHRpXCI6IGZhbHNlXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiYlNvcnRNdWx0aVwiOiB0cnVlLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogQWxsb3dzIGNvbnRyb2wgb3ZlciB3aGV0aGVyIERhdGFUYWJsZXMgc2hvdWxkIHVzZSB0aGUgdG9wICh0cnVlKSB1bmlxdWVcblx0XHQgKiBjZWxsIHRoYXQgaXMgZm91bmQgZm9yIGEgc2luZ2xlIGNvbHVtbiwgb3IgdGhlIGJvdHRvbSAoZmFsc2UgLSBkZWZhdWx0KS5cblx0XHQgKiBUaGlzIGlzIHVzZWZ1bCB3aGVuIHVzaW5nIGNvbXBsZXggaGVhZGVycy5cblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqICBAZGVmYXVsdCBmYWxzZVxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBPcHRpb25zXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5vcmRlckNlbGxzVG9wXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcIm9yZGVyQ2VsbHNUb3BcIjogdHJ1ZVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJTb3J0Q2VsbHNUb3BcIjogZmFsc2UsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBFbmFibGUgb3IgZGlzYWJsZSB0aGUgYWRkaXRpb24gb2YgdGhlIGNsYXNzZXMgYHNvcnRpbmdcXF8xYCwgYHNvcnRpbmdcXF8yYCBhbmRcblx0XHQgKiBgc29ydGluZ1xcXzNgIHRvIHRoZSBjb2x1bW5zIHdoaWNoIGFyZSBjdXJyZW50bHkgYmVpbmcgc29ydGVkIG9uLiBUaGlzIGlzXG5cdFx0ICogcHJlc2VudGVkIGFzIGEgZmVhdHVyZSBzd2l0Y2ggYXMgaXQgY2FuIGluY3JlYXNlIHByb2Nlc3NpbmcgdGltZSAod2hpbGVcblx0XHQgKiBjbGFzc2VzIGFyZSByZW1vdmVkIGFuZCBhZGRlZCkgc28gZm9yIGxhcmdlIGRhdGEgc2V0cyB5b3UgbWlnaHQgd2FudCB0b1xuXHRcdCAqIHR1cm4gdGhpcyBvZmYuXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgdHJ1ZVxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBGZWF0dXJlc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMub3JkZXJDbGFzc2VzXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24gKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJvcmRlckNsYXNzZXNcIjogZmFsc2Vcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJiU29ydENsYXNzZXNcIjogdHJ1ZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEVuYWJsZSBvciBkaXNhYmxlIHN0YXRlIHNhdmluZy4gV2hlbiBlbmFibGVkIEhUTUw1IGBsb2NhbFN0b3JhZ2VgIHdpbGwgYmVcblx0XHQgKiB1c2VkIHRvIHNhdmUgdGFibGUgZGlzcGxheSBpbmZvcm1hdGlvbiBzdWNoIGFzIHBhZ2luYXRpb24gaW5mb3JtYXRpb24sXG5cdFx0ICogZGlzcGxheSBsZW5ndGgsIGZpbHRlcmluZyBhbmQgc29ydGluZy4gQXMgc3VjaCB3aGVuIHRoZSBlbmQgdXNlciByZWxvYWRzXG5cdFx0ICogdGhlIHBhZ2UgdGhlIGRpc3BsYXkgZGlzcGxheSB3aWxsIG1hdGNoIHdoYXQgdGh5IGhhZCBwcmV2aW91c2x5IHNldCB1cC5cblx0XHQgKlxuXHRcdCAqIER1ZSB0byB0aGUgdXNlIG9mIGBsb2NhbFN0b3JhZ2VgIHRoZSBkZWZhdWx0IHN0YXRlIHNhdmluZyBpcyBub3Qgc3VwcG9ydGVkXG5cdFx0ICogaW4gSUU2IG9yIDcuIElmIHN0YXRlIHNhdmluZyBpcyByZXF1aXJlZCBpbiB0aG9zZSBicm93c2VycywgdXNlXG5cdFx0ICogYHN0YXRlU2F2ZUNhbGxiYWNrYCB0byBwcm92aWRlIGEgc3RvcmFnZSBzb2x1dGlvbiBzdWNoIGFzIGNvb2tpZXMuXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgRmVhdHVyZXNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnN0YXRlU2F2ZVxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uICgpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwic3RhdGVTYXZlXCI6IHRydWVcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJiU3RhdGVTYXZlXCI6IGZhbHNlLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgd2hlbiBhIFRSIGVsZW1lbnQgaXMgY3JlYXRlZCAoYW5kIGFsbCBURCBjaGlsZFxuXHRcdCAqIGVsZW1lbnRzIGhhdmUgYmVlbiBpbnNlcnRlZCksIG9yIHJlZ2lzdGVyZWQgaWYgdXNpbmcgYSBET00gc291cmNlLCBhbGxvd2luZ1xuXHRcdCAqIG1hbmlwdWxhdGlvbiBvZiB0aGUgVFIgZWxlbWVudCAoYWRkaW5nIGNsYXNzZXMgZXRjKS5cblx0XHQgKiAgQHR5cGUgZnVuY3Rpb25cblx0XHQgKiAgQHBhcmFtIHtub2RlfSByb3cgXCJUUlwiIGVsZW1lbnQgZm9yIHRoZSBjdXJyZW50IHJvd1xuXHRcdCAqICBAcGFyYW0ge2FycmF5fSBkYXRhIFJhdyBkYXRhIGFycmF5IGZvciB0aGlzIHJvd1xuXHRcdCAqICBAcGFyYW0ge2ludH0gZGF0YUluZGV4IFRoZSBpbmRleCBvZiB0aGlzIHJvdyBpbiB0aGUgaW50ZXJuYWwgYW9EYXRhIGFycmF5XG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IENhbGxiYWNrc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY3JlYXRlZFJvd1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjcmVhdGVkUm93XCI6IGZ1bmN0aW9uKCByb3csIGRhdGEsIGRhdGFJbmRleCApIHtcblx0XHQgKiAgICAgICAgICAvLyBCb2xkIHRoZSBncmFkZSBmb3IgYWxsICdBJyBncmFkZSBicm93c2Vyc1xuXHRcdCAqICAgICAgICAgIGlmICggZGF0YVs0XSA9PSBcIkFcIiApXG5cdFx0ICogICAgICAgICAge1xuXHRcdCAqICAgICAgICAgICAgJCgndGQ6ZXEoNCknLCByb3cpLmh0bWwoICc8Yj5BPC9iPicgKTtcblx0XHQgKiAgICAgICAgICB9XG5cdFx0ICogICAgICAgIH1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJmbkNyZWF0ZWRSb3dcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIG9uIGV2ZXJ5ICdkcmF3JyBldmVudCwgYW5kIGFsbG93cyB5b3UgdG9cblx0XHQgKiBkeW5hbWljYWxseSBtb2RpZnkgYW55IGFzcGVjdCB5b3Ugd2FudCBhYm91dCB0aGUgY3JlYXRlZCBET00uXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBDYWxsYmFja3Ncblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmRyYXdDYWxsYmFja1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJkcmF3Q2FsbGJhY2tcIjogZnVuY3Rpb24oIHNldHRpbmdzICkge1xuXHRcdCAqICAgICAgICAgIGFsZXJ0KCAnRGF0YVRhYmxlcyBoYXMgcmVkcmF3biB0aGUgdGFibGUnICk7XG5cdFx0ICogICAgICAgIH1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJmbkRyYXdDYWxsYmFja1wiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogSWRlbnRpY2FsIHRvIGZuSGVhZGVyQ2FsbGJhY2soKSBidXQgZm9yIHRoZSB0YWJsZSBmb290ZXIgdGhpcyBmdW5jdGlvblxuXHRcdCAqIGFsbG93cyB5b3UgdG8gbW9kaWZ5IHRoZSB0YWJsZSBmb290ZXIgb24gZXZlcnkgJ2RyYXcnIGV2ZW50LlxuXHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdCAqICBAcGFyYW0ge25vZGV9IGZvb3QgXCJUUlwiIGVsZW1lbnQgZm9yIHRoZSBmb290ZXJcblx0XHQgKiAgQHBhcmFtIHthcnJheX0gZGF0YSBGdWxsIHRhYmxlIGRhdGEgKGFzIGRlcml2ZWQgZnJvbSB0aGUgb3JpZ2luYWwgSFRNTClcblx0XHQgKiAgQHBhcmFtIHtpbnR9IHN0YXJ0IEluZGV4IGZvciB0aGUgY3VycmVudCBkaXNwbGF5IHN0YXJ0aW5nIHBvaW50IGluIHRoZVxuXHRcdCAqICAgIGRpc3BsYXkgYXJyYXlcblx0XHQgKiAgQHBhcmFtIHtpbnR9IGVuZCBJbmRleCBmb3IgdGhlIGN1cnJlbnQgZGlzcGxheSBlbmRpbmcgcG9pbnQgaW4gdGhlXG5cdFx0ICogICAgZGlzcGxheSBhcnJheVxuXHRcdCAqICBAcGFyYW0ge2FycmF5IGludH0gZGlzcGxheSBJbmRleCBhcnJheSB0byB0cmFuc2xhdGUgdGhlIHZpc3VhbCBwb3NpdGlvblxuXHRcdCAqICAgIHRvIHRoZSBmdWxsIGRhdGEgYXJyYXlcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgQ2FsbGJhY2tzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5mb290ZXJDYWxsYmFja1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJmb290ZXJDYWxsYmFja1wiOiBmdW5jdGlvbiggdGZvb3QsIGRhdGEsIHN0YXJ0LCBlbmQsIGRpc3BsYXkgKSB7XG5cdFx0ICogICAgICAgICAgdGZvb3QuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ3RoJylbMF0uaW5uZXJIVE1MID0gXCJTdGFydGluZyBpbmRleCBpcyBcIitzdGFydDtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKVxuXHRcdCAqL1xuXHRcdFwiZm5Gb290ZXJDYWxsYmFja1wiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogV2hlbiByZW5kZXJpbmcgbGFyZ2UgbnVtYmVycyBpbiB0aGUgaW5mb3JtYXRpb24gZWxlbWVudCBmb3IgdGhlIHRhYmxlXG5cdFx0ICogKGkuZS4gXCJTaG93aW5nIDEgdG8gMTAgb2YgNTcgZW50cmllc1wiKSBEYXRhVGFibGVzIHdpbGwgcmVuZGVyIGxhcmdlIG51bWJlcnNcblx0XHQgKiB0byBoYXZlIGEgY29tbWEgc2VwYXJhdG9yIGZvciB0aGUgJ3Rob3VzYW5kcycgdW5pdHMgKGUuZy4gMSBtaWxsaW9uIGlzXG5cdFx0ICogcmVuZGVyZWQgYXMgXCIxLDAwMCwwMDBcIikgdG8gaGVscCByZWFkYWJpbGl0eSBmb3IgdGhlIGVuZCB1c2VyLiBUaGlzXG5cdFx0ICogZnVuY3Rpb24gd2lsbCBvdmVycmlkZSB0aGUgZGVmYXVsdCBtZXRob2QgRGF0YVRhYmxlcyB1c2VzLlxuXHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdCAqICBAbWVtYmVyXG5cdFx0ICogIEBwYXJhbSB7aW50fSB0b0Zvcm1hdCBudW1iZXIgdG8gYmUgZm9ybWF0dGVkXG5cdFx0ICogIEByZXR1cm5zIHtzdHJpbmd9IGZvcm1hdHRlZCBzdHJpbmcgZm9yIERhdGFUYWJsZXMgdG8gc2hvdyB0aGUgbnVtYmVyXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IENhbGxiYWNrc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuZm9ybWF0TnVtYmVyXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBGb3JtYXQgYSBudW1iZXIgdXNpbmcgYSBzaW5nbGUgcXVvdGUgZm9yIHRoZSBzZXBhcmF0b3IgKG5vdGUgdGhhdFxuXHRcdCAqICAgIC8vIHRoaXMgY2FuIGFsc28gYmUgZG9uZSB3aXRoIHRoZSBsYW5ndWFnZS50aG91c2FuZHMgb3B0aW9uKVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiZm9ybWF0TnVtYmVyXCI6IGZ1bmN0aW9uICggdG9Gb3JtYXQgKSB7XG5cdFx0ICogICAgICAgICAgcmV0dXJuIHRvRm9ybWF0LnRvU3RyaW5nKCkucmVwbGFjZShcblx0XHQgKiAgICAgICAgICAgIC9cXEIoPz0oXFxkezN9KSsoPyFcXGQpKS9nLCBcIidcIlxuXHRcdCAqICAgICAgICAgICk7XG5cdFx0ICogICAgICAgIH07XG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiZm5Gb3JtYXROdW1iZXJcIjogZnVuY3Rpb24gKCB0b0Zvcm1hdCApIHtcblx0XHRcdHJldHVybiB0b0Zvcm1hdC50b1N0cmluZygpLnJlcGxhY2UoXG5cdFx0XHRcdC9cXEIoPz0oXFxkezN9KSsoPyFcXGQpKS9nLFxuXHRcdFx0XHR0aGlzLm9MYW5ndWFnZS5zVGhvdXNhbmRzXG5cdFx0XHQpO1xuXHRcdH0sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBvbiBldmVyeSAnZHJhdycgZXZlbnQsIGFuZCBhbGxvd3MgeW91IHRvXG5cdFx0ICogZHluYW1pY2FsbHkgbW9kaWZ5IHRoZSBoZWFkZXIgcm93LiBUaGlzIGNhbiBiZSB1c2VkIHRvIGNhbGN1bGF0ZSBhbmRcblx0XHQgKiBkaXNwbGF5IHVzZWZ1bCBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdGFibGUuXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBwYXJhbSB7bm9kZX0gaGVhZCBcIlRSXCIgZWxlbWVudCBmb3IgdGhlIGhlYWRlclxuXHRcdCAqICBAcGFyYW0ge2FycmF5fSBkYXRhIEZ1bGwgdGFibGUgZGF0YSAoYXMgZGVyaXZlZCBmcm9tIHRoZSBvcmlnaW5hbCBIVE1MKVxuXHRcdCAqICBAcGFyYW0ge2ludH0gc3RhcnQgSW5kZXggZm9yIHRoZSBjdXJyZW50IGRpc3BsYXkgc3RhcnRpbmcgcG9pbnQgaW4gdGhlXG5cdFx0ICogICAgZGlzcGxheSBhcnJheVxuXHRcdCAqICBAcGFyYW0ge2ludH0gZW5kIEluZGV4IGZvciB0aGUgY3VycmVudCBkaXNwbGF5IGVuZGluZyBwb2ludCBpbiB0aGVcblx0XHQgKiAgICBkaXNwbGF5IGFycmF5XG5cdFx0ICogIEBwYXJhbSB7YXJyYXkgaW50fSBkaXNwbGF5IEluZGV4IGFycmF5IHRvIHRyYW5zbGF0ZSB0aGUgdmlzdWFsIHBvc2l0aW9uXG5cdFx0ICogICAgdG8gdGhlIGZ1bGwgZGF0YSBhcnJheVxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBDYWxsYmFja3Ncblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmhlYWRlckNhbGxiYWNrXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImZoZWFkZXJDYWxsYmFja1wiOiBmdW5jdGlvbiggaGVhZCwgZGF0YSwgc3RhcnQsIGVuZCwgZGlzcGxheSApIHtcblx0XHQgKiAgICAgICAgICBoZWFkLmdldEVsZW1lbnRzQnlUYWdOYW1lKCd0aCcpWzBdLmlubmVySFRNTCA9IFwiRGlzcGxheWluZyBcIisoZW5kLXN0YXJ0KStcIiByZWNvcmRzXCI7XG5cdFx0ICogICAgICAgIH1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9IClcblx0XHQgKi9cblx0XHRcImZuSGVhZGVyQ2FsbGJhY2tcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoZSBpbmZvcm1hdGlvbiBlbGVtZW50IGNhbiBiZSB1c2VkIHRvIGNvbnZleSBpbmZvcm1hdGlvbiBhYm91dCB0aGUgY3VycmVudFxuXHRcdCAqIHN0YXRlIG9mIHRoZSB0YWJsZS4gQWx0aG91Z2ggdGhlIGludGVybmF0aW9uYWxpc2F0aW9uIG9wdGlvbnMgcHJlc2VudGVkIGJ5XG5cdFx0ICogRGF0YVRhYmxlcyBhcmUgcXVpdGUgY2FwYWJsZSBvZiBkZWFsaW5nIHdpdGggbW9zdCBjdXN0b21pc2F0aW9ucywgdGhlcmUgbWF5XG5cdFx0ICogYmUgdGltZXMgd2hlcmUgeW91IHdpc2ggdG8gY3VzdG9taXNlIHRoZSBzdHJpbmcgZnVydGhlci4gVGhpcyBjYWxsYmFja1xuXHRcdCAqIGFsbG93cyB5b3UgdG8gZG8gZXhhY3RseSB0aGF0LlxuXHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0ICogIEBwYXJhbSB7aW50fSBzdGFydCBTdGFydGluZyBwb3NpdGlvbiBpbiBkYXRhIGZvciB0aGUgZHJhd1xuXHRcdCAqICBAcGFyYW0ge2ludH0gZW5kIEVuZCBwb3NpdGlvbiBpbiBkYXRhIGZvciB0aGUgZHJhd1xuXHRcdCAqICBAcGFyYW0ge2ludH0gbWF4IFRvdGFsIG51bWJlciBvZiByb3dzIGluIHRoZSB0YWJsZSAocmVnYXJkbGVzcyBvZlxuXHRcdCAqICAgIGZpbHRlcmluZylcblx0XHQgKiAgQHBhcmFtIHtpbnR9IHRvdGFsIFRvdGFsIG51bWJlciBvZiByb3dzIGluIHRoZSBkYXRhIHNldCwgYWZ0ZXIgZmlsdGVyaW5nXG5cdFx0ICogIEBwYXJhbSB7c3RyaW5nfSBwcmUgVGhlIHN0cmluZyB0aGF0IERhdGFUYWJsZXMgaGFzIGZvcm1hdHRlZCB1c2luZyBpdCdzXG5cdFx0ICogICAgb3duIHJ1bGVzXG5cdFx0ICogIEByZXR1cm5zIHtzdHJpbmd9IFRoZSBzdHJpbmcgdG8gYmUgZGlzcGxheWVkIGluIHRoZSBpbmZvcm1hdGlvbiBlbGVtZW50LlxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBDYWxsYmFja3Ncblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmluZm9DYWxsYmFja1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgIFwiaW5mb0NhbGxiYWNrXCI6IGZ1bmN0aW9uKCBzZXR0aW5ncywgc3RhcnQsIGVuZCwgbWF4LCB0b3RhbCwgcHJlICkge1xuXHRcdCAqICAgICAgICByZXR1cm4gc3RhcnQgK1wiIHRvIFwiKyBlbmQ7XG5cdFx0ICogICAgICB9XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiZm5JbmZvQ2FsbGJhY2tcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIENhbGxlZCB3aGVuIHRoZSB0YWJsZSBoYXMgYmVlbiBpbml0aWFsaXNlZC4gTm9ybWFsbHkgRGF0YVRhYmxlcyB3aWxsXG5cdFx0ICogaW5pdGlhbGlzZSBzZXF1ZW50aWFsbHkgYW5kIHRoZXJlIHdpbGwgYmUgbm8gbmVlZCBmb3IgdGhpcyBmdW5jdGlvbixcblx0XHQgKiBob3dldmVyLCB0aGlzIGRvZXMgbm90IGhvbGQgdHJ1ZSB3aGVuIHVzaW5nIGV4dGVybmFsIGxhbmd1YWdlIGluZm9ybWF0aW9uXG5cdFx0ICogc2luY2UgdGhhdCBpcyBvYnRhaW5lZCB1c2luZyBhbiBhc3luYyBYSFIgY2FsbC5cblx0XHQgKiAgQHR5cGUgZnVuY3Rpb25cblx0XHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0ICogIEBwYXJhbSB7b2JqZWN0fSBqc29uIFRoZSBKU09OIG9iamVjdCByZXF1ZXN0IGZyb20gdGhlIHNlcnZlciAtIG9ubHlcblx0XHQgKiAgICBwcmVzZW50IGlmIGNsaWVudC1zaWRlIEFqYXggc291cmNlZCBkYXRhIGlzIHVzZWRcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgQ2FsbGJhY2tzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5pbml0Q29tcGxldGVcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiaW5pdENvbXBsZXRlXCI6IGZ1bmN0aW9uKHNldHRpbmdzLCBqc29uKSB7XG5cdFx0ICogICAgICAgICAgYWxlcnQoICdEYXRhVGFibGVzIGhhcyBmaW5pc2hlZCBpdHMgaW5pdGlhbGlzYXRpb24uJyApO1xuXHRcdCAqICAgICAgICB9XG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApXG5cdFx0ICovXG5cdFx0XCJmbkluaXRDb21wbGV0ZVwiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogQ2FsbGVkIGF0IHRoZSB2ZXJ5IHN0YXJ0IG9mIGVhY2ggdGFibGUgZHJhdyBhbmQgY2FuIGJlIHVzZWQgdG8gY2FuY2VsIHRoZVxuXHRcdCAqIGRyYXcgYnkgcmV0dXJuaW5nIGZhbHNlLCBhbnkgb3RoZXIgcmV0dXJuIChpbmNsdWRpbmcgdW5kZWZpbmVkKSByZXN1bHRzIGluXG5cdFx0ICogdGhlIGZ1bGwgZHJhdyBvY2N1cnJpbmcpLlxuXHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdCAqICBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0XHQgKiAgQHJldHVybnMge2Jvb2xlYW59IEZhbHNlIHdpbGwgY2FuY2VsIHRoZSBkcmF3LCBhbnl0aGluZyBlbHNlIChpbmNsdWRpbmcgbm9cblx0XHQgKiAgICByZXR1cm4pIHdpbGwgYWxsb3cgaXQgdG8gY29tcGxldGUuXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IENhbGxiYWNrc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMucHJlRHJhd0NhbGxiYWNrXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcInByZURyYXdDYWxsYmFja1wiOiBmdW5jdGlvbiggc2V0dGluZ3MgKSB7XG5cdFx0ICogICAgICAgICAgaWYgKCAkKCcjdGVzdCcpLnZhbCgpID09IDEgKSB7XG5cdFx0ICogICAgICAgICAgICByZXR1cm4gZmFsc2U7XG5cdFx0ICogICAgICAgICAgfVxuXHRcdCAqICAgICAgICB9XG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiZm5QcmVEcmF3Q2FsbGJhY2tcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoaXMgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byAncG9zdCBwcm9jZXNzJyBlYWNoIHJvdyBhZnRlciBpdCBoYXZlIGJlZW5cblx0XHQgKiBnZW5lcmF0ZWQgZm9yIGVhY2ggdGFibGUgZHJhdywgYnV0IGJlZm9yZSBpdCBpcyByZW5kZXJlZCBvbiBzY3JlZW4uIFRoaXNcblx0XHQgKiBmdW5jdGlvbiBtaWdodCBiZSB1c2VkIGZvciBzZXR0aW5nIHRoZSByb3cgY2xhc3MgbmFtZSBldGMuXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBwYXJhbSB7bm9kZX0gcm93IFwiVFJcIiBlbGVtZW50IGZvciB0aGUgY3VycmVudCByb3dcblx0XHQgKiAgQHBhcmFtIHthcnJheX0gZGF0YSBSYXcgZGF0YSBhcnJheSBmb3IgdGhpcyByb3dcblx0XHQgKiAgQHBhcmFtIHtpbnR9IGRpc3BsYXlJbmRleCBUaGUgZGlzcGxheSBpbmRleCBmb3IgdGhlIGN1cnJlbnQgdGFibGUgZHJhd1xuXHRcdCAqICBAcGFyYW0ge2ludH0gZGlzcGxheUluZGV4RnVsbCBUaGUgaW5kZXggb2YgdGhlIGRhdGEgaW4gdGhlIGZ1bGwgbGlzdCBvZlxuXHRcdCAqICAgIHJvd3MgKGFmdGVyIGZpbHRlcmluZylcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgQ2FsbGJhY2tzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5yb3dDYWxsYmFja1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJyb3dDYWxsYmFja1wiOiBmdW5jdGlvbiggcm93LCBkYXRhLCBkaXNwbGF5SW5kZXgsIGRpc3BsYXlJbmRleEZ1bGwgKSB7XG5cdFx0ICogICAgICAgICAgLy8gQm9sZCB0aGUgZ3JhZGUgZm9yIGFsbCAnQScgZ3JhZGUgYnJvd3NlcnNcblx0XHQgKiAgICAgICAgICBpZiAoIGRhdGFbNF0gPT0gXCJBXCIgKSB7XG5cdFx0ICogICAgICAgICAgICAkKCd0ZDplcSg0KScsIHJvdykuaHRtbCggJzxiPkE8L2I+JyApO1xuXHRcdCAqICAgICAgICAgIH1cblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImZuUm93Q2FsbGJhY2tcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIF9fRGVwcmVjYXRlZF9fIFRoZSBmdW5jdGlvbmFsaXR5IHByb3ZpZGVkIGJ5IHRoaXMgcGFyYW1ldGVyIGhhcyBub3cgYmVlblxuXHRcdCAqIHN1cGVyc2VkZWQgYnkgdGhhdCBwcm92aWRlZCB0aHJvdWdoIGBhamF4YCwgd2hpY2ggc2hvdWxkIGJlIHVzZWQgaW5zdGVhZC5cblx0XHQgKlxuXHRcdCAqIFRoaXMgcGFyYW1ldGVyIGFsbG93cyB5b3UgdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgZnVuY3Rpb24gd2hpY2ggb2J0YWluc1xuXHRcdCAqIHRoZSBkYXRhIGZyb20gdGhlIHNlcnZlciBzbyBzb21ldGhpbmcgbW9yZSBzdWl0YWJsZSBmb3IgeW91ciBhcHBsaWNhdGlvbi5cblx0XHQgKiBGb3IgZXhhbXBsZSB5b3UgY291bGQgdXNlIFBPU1QgZGF0YSwgb3IgcHVsbCBpbmZvcm1hdGlvbiBmcm9tIGEgR2VhcnMgb3Jcblx0XHQgKiBBSVIgZGF0YWJhc2UuXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBtZW1iZXJcblx0XHQgKiAgQHBhcmFtIHtzdHJpbmd9IHNvdXJjZSBIVFRQIHNvdXJjZSB0byBvYnRhaW4gdGhlIGRhdGEgZnJvbSAoYGFqYXhgKVxuXHRcdCAqICBAcGFyYW0ge2FycmF5fSBkYXRhIEEga2V5L3ZhbHVlIHBhaXIgb2JqZWN0IGNvbnRhaW5pbmcgdGhlIGRhdGEgdG8gc2VuZFxuXHRcdCAqICAgIHRvIHRoZSBzZXJ2ZXJcblx0XHQgKiAgQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2sgdG8gYmUgY2FsbGVkIG9uIGNvbXBsZXRpb24gb2YgdGhlIGRhdGEgZ2V0XG5cdFx0ICogICAgcHJvY2VzcyB0aGF0IHdpbGwgZHJhdyB0aGUgZGF0YSBvbiB0aGUgcGFnZS5cblx0XHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IENhbGxiYWNrc1xuXHRcdCAqICBAZHRvcHQgU2VydmVyLXNpZGVcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNlcnZlckRhdGFcblx0XHQgKlxuXHRcdCAqICBAZGVwcmVjYXRlZCAxLjEwLiBQbGVhc2UgdXNlIGBhamF4YCBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5IG5vdy5cblx0XHQgKi9cblx0XHRcImZuU2VydmVyRGF0YVwiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogX19EZXByZWNhdGVkX18gVGhlIGZ1bmN0aW9uYWxpdHkgcHJvdmlkZWQgYnkgdGhpcyBwYXJhbWV0ZXIgaGFzIG5vdyBiZWVuXG5cdFx0ICogc3VwZXJzZWRlZCBieSB0aGF0IHByb3ZpZGVkIHRocm91Z2ggYGFqYXhgLCB3aGljaCBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkLlxuXHRcdCAqXG5cdFx0ICogIEl0IGlzIG9mdGVuIHVzZWZ1bCB0byBzZW5kIGV4dHJhIGRhdGEgdG8gdGhlIHNlcnZlciB3aGVuIG1ha2luZyBhbiBBamF4XG5cdFx0ICogcmVxdWVzdCAtIGZvciBleGFtcGxlIGN1c3RvbSBmaWx0ZXJpbmcgaW5mb3JtYXRpb24sIGFuZCB0aGlzIGNhbGxiYWNrXG5cdFx0ICogZnVuY3Rpb24gbWFrZXMgaXQgdHJpdmlhbCB0byBzZW5kIGV4dHJhIGluZm9ybWF0aW9uIHRvIHRoZSBzZXJ2ZXIuIFRoZVxuXHRcdCAqIHBhc3NlZCBpbiBwYXJhbWV0ZXIgaXMgdGhlIGRhdGEgc2V0IHRoYXQgaGFzIGJlZW4gY29uc3RydWN0ZWQgYnlcblx0XHQgKiBEYXRhVGFibGVzLCBhbmQgeW91IGNhbiBhZGQgdG8gdGhpcyBvciBtb2RpZnkgaXQgYXMgeW91IHJlcXVpcmUuXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBwYXJhbSB7YXJyYXl9IGRhdGEgRGF0YSBhcnJheSAoYXJyYXkgb2Ygb2JqZWN0cyB3aGljaCBhcmUgbmFtZS92YWx1ZVxuXHRcdCAqICAgIHBhaXJzKSB0aGF0IGhhcyBiZWVuIGNvbnN0cnVjdGVkIGJ5IERhdGFUYWJsZXMgYW5kIHdpbGwgYmUgc2VudCB0byB0aGVcblx0XHQgKiAgICBzZXJ2ZXIuIEluIHRoZSBjYXNlIG9mIEFqYXggc291cmNlZCBkYXRhIHdpdGggc2VydmVyLXNpZGUgcHJvY2Vzc2luZ1xuXHRcdCAqICAgIHRoaXMgd2lsbCBiZSBhbiBlbXB0eSBhcnJheSwgZm9yIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcgdGhlcmUgd2lsbCBiZSBhXG5cdFx0ICogICAgc2lnbmlmaWNhbnQgbnVtYmVyIG9mIHBhcmFtZXRlcnMhXG5cdFx0ICogIEByZXR1cm5zIHt1bmRlZmluZWR9IEVuc3VyZSB0aGF0IHlvdSBtb2RpZnkgdGhlIGRhdGEgYXJyYXkgcGFzc2VkIGluLFxuXHRcdCAqICAgIGFzIHRoaXMgaXMgcGFzc2VkIGJ5IHJlZmVyZW5jZS5cblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgQ2FsbGJhY2tzXG5cdFx0ICogIEBkdG9wdCBTZXJ2ZXItc2lkZVxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc2VydmVyUGFyYW1zXG5cdFx0ICpcblx0XHQgKiAgQGRlcHJlY2F0ZWQgMS4xMC4gUGxlYXNlIHVzZSBgYWpheGAgZm9yIHRoaXMgZnVuY3Rpb25hbGl0eSBub3cuXG5cdFx0ICovXG5cdFx0XCJmblNlcnZlclBhcmFtc1wiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogTG9hZCB0aGUgdGFibGUgc3RhdGUuIFdpdGggdGhpcyBmdW5jdGlvbiB5b3UgY2FuIGRlZmluZSBmcm9tIHdoZXJlLCBhbmQgaG93LCB0aGVcblx0XHQgKiBzdGF0ZSBvZiBhIHRhYmxlIGlzIGxvYWRlZC4gQnkgZGVmYXVsdCBEYXRhVGFibGVzIHdpbGwgbG9hZCBmcm9tIGBsb2NhbFN0b3JhZ2VgXG5cdFx0ICogYnV0IHlvdSBtaWdodCB3aXNoIHRvIHVzZSBhIHNlcnZlci1zaWRlIGRhdGFiYXNlIG9yIGNvb2tpZXMuXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBtZW1iZXJcblx0XHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0ICogIEBwYXJhbSB7b2JqZWN0fSBjYWxsYmFjayBDYWxsYmFjayB0aGF0IGNhbiBiZSBleGVjdXRlZCB3aGVuIGRvbmUuIEl0XG5cdFx0ICogICAgc2hvdWxkIGJlIHBhc3NlZCB0aGUgbG9hZGVkIHN0YXRlIG9iamVjdC5cblx0XHQgKiAgQHJldHVybiB7b2JqZWN0fSBUaGUgRGF0YVRhYmxlcyBzdGF0ZSBvYmplY3QgdG8gYmUgbG9hZGVkXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IENhbGxiYWNrc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc3RhdGVMb2FkQ2FsbGJhY2tcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwic3RhdGVTYXZlXCI6IHRydWUsXG5cdFx0ICogICAgICAgIFwic3RhdGVMb2FkQ2FsbGJhY2tcIjogZnVuY3Rpb24gKHNldHRpbmdzLCBjYWxsYmFjaykge1xuXHRcdCAqICAgICAgICAgICQuYWpheCgge1xuXHRcdCAqICAgICAgICAgICAgXCJ1cmxcIjogXCIvc3RhdGVfbG9hZFwiLFxuXHRcdCAqICAgICAgICAgICAgXCJkYXRhVHlwZVwiOiBcImpzb25cIixcblx0XHQgKiAgICAgICAgICAgIFwic3VjY2Vzc1wiOiBmdW5jdGlvbiAoanNvbikge1xuXHRcdCAqICAgICAgICAgICAgICBjYWxsYmFjaygganNvbiApO1xuXHRcdCAqICAgICAgICAgICAgfVxuXHRcdCAqICAgICAgICAgIH0gKTtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImZuU3RhdGVMb2FkQ2FsbGJhY2tcIjogZnVuY3Rpb24gKCBzZXR0aW5ncyApIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdHJldHVybiBKU09OLnBhcnNlKFxuXHRcdFx0XHRcdChzZXR0aW5ncy5pU3RhdGVEdXJhdGlvbiA9PT0gLTEgPyBzZXNzaW9uU3RvcmFnZSA6IGxvY2FsU3RvcmFnZSkuZ2V0SXRlbShcblx0XHRcdFx0XHRcdCdEYXRhVGFibGVzXycrc2V0dGluZ3Muc0luc3RhbmNlKydfJytsb2NhdGlvbi5wYXRobmFtZVxuXHRcdFx0XHRcdClcblx0XHRcdFx0KTtcblx0XHRcdH0gY2F0Y2ggKGUpIHt9XG5cdFx0fSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIENhbGxiYWNrIHdoaWNoIGFsbG93cyBtb2RpZmljYXRpb24gb2YgdGhlIHNhdmVkIHN0YXRlIHByaW9yIHRvIGxvYWRpbmcgdGhhdCBzdGF0ZS5cblx0XHQgKiBUaGlzIGNhbGxiYWNrIGlzIGNhbGxlZCB3aGVuIHRoZSB0YWJsZSBpcyBsb2FkaW5nIHN0YXRlIGZyb20gdGhlIHN0b3JlZCBkYXRhLCBidXRcblx0XHQgKiBwcmlvciB0byB0aGUgc2V0dGluZ3Mgb2JqZWN0IGJlaW5nIG1vZGlmaWVkIGJ5IHRoZSBzYXZlZCBzdGF0ZS4gTm90ZSB0aGF0IGZvclxuXHRcdCAqIHBsdWctaW4gYXV0aG9ycywgeW91IHNob3VsZCB1c2UgdGhlIGBzdGF0ZUxvYWRQYXJhbXNgIGV2ZW50IHRvIGxvYWQgcGFyYW1ldGVycyBmb3Jcblx0XHQgKiBhIHBsdWctaW4uXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHRcdCAqICBAcGFyYW0ge29iamVjdH0gZGF0YSBUaGUgc3RhdGUgb2JqZWN0IHRoYXQgaXMgdG8gYmUgbG9hZGVkXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IENhbGxiYWNrc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc3RhdGVMb2FkUGFyYW1zXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBSZW1vdmUgYSBzYXZlZCBmaWx0ZXIsIHNvIGZpbHRlcmluZyBpcyBuZXZlciBsb2FkZWRcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcInN0YXRlU2F2ZVwiOiB0cnVlLFxuXHRcdCAqICAgICAgICBcInN0YXRlTG9hZFBhcmFtc1wiOiBmdW5jdGlvbiAoc2V0dGluZ3MsIGRhdGEpIHtcblx0XHQgKiAgICAgICAgICBkYXRhLm9TZWFyY2guc1NlYXJjaCA9IFwiXCI7XG5cdFx0ICogICAgICAgIH1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBEaXNhbGxvdyBzdGF0ZSBsb2FkaW5nIGJ5IHJldHVybmluZyBmYWxzZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwic3RhdGVTYXZlXCI6IHRydWUsXG5cdFx0ICogICAgICAgIFwic3RhdGVMb2FkUGFyYW1zXCI6IGZ1bmN0aW9uIChzZXR0aW5ncywgZGF0YSkge1xuXHRcdCAqICAgICAgICAgIHJldHVybiBmYWxzZTtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImZuU3RhdGVMb2FkUGFyYW1zXCI6IG51bGwsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBDYWxsYmFjayB0aGF0IGlzIGNhbGxlZCB3aGVuIHRoZSBzdGF0ZSBoYXMgYmVlbiBsb2FkZWQgZnJvbSB0aGUgc3RhdGUgc2F2aW5nIG1ldGhvZFxuXHRcdCAqIGFuZCB0aGUgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3QgaGFzIGJlZW4gbW9kaWZpZWQgYXMgYSByZXN1bHQgb2YgdGhlIGxvYWRlZCBzdGF0ZS5cblx0XHQgKiAgQHR5cGUgZnVuY3Rpb25cblx0XHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0ICogIEBwYXJhbSB7b2JqZWN0fSBkYXRhIFRoZSBzdGF0ZSBvYmplY3QgdGhhdCB3YXMgbG9hZGVkXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IENhbGxiYWNrc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc3RhdGVMb2FkZWRcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFNob3cgYW4gYWxlcnQgd2l0aCB0aGUgZmlsdGVyaW5nIHZhbHVlIHRoYXQgd2FzIHNhdmVkXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJzdGF0ZVNhdmVcIjogdHJ1ZSxcblx0XHQgKiAgICAgICAgXCJzdGF0ZUxvYWRlZFwiOiBmdW5jdGlvbiAoc2V0dGluZ3MsIGRhdGEpIHtcblx0XHQgKiAgICAgICAgICBhbGVydCggJ1NhdmVkIGZpbHRlciB3YXM6ICcrZGF0YS5vU2VhcmNoLnNTZWFyY2ggKTtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImZuU3RhdGVMb2FkZWRcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFNhdmUgdGhlIHRhYmxlIHN0YXRlLiBUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gZGVmaW5lIHdoZXJlIGFuZCBob3cgdGhlIHN0YXRlXG5cdFx0ICogaW5mb3JtYXRpb24gZm9yIHRoZSB0YWJsZSBpcyBzdG9yZWQgQnkgZGVmYXVsdCBEYXRhVGFibGVzIHdpbGwgdXNlIGBsb2NhbFN0b3JhZ2VgXG5cdFx0ICogYnV0IHlvdSBtaWdodCB3aXNoIHRvIHVzZSBhIHNlcnZlci1zaWRlIGRhdGFiYXNlIG9yIGNvb2tpZXMuXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBtZW1iZXJcblx0XHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0ICogIEBwYXJhbSB7b2JqZWN0fSBkYXRhIFRoZSBzdGF0ZSBvYmplY3QgdG8gYmUgc2F2ZWRcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgQ2FsbGJhY2tzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zdGF0ZVNhdmVDYWxsYmFja1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJzdGF0ZVNhdmVcIjogdHJ1ZSxcblx0XHQgKiAgICAgICAgXCJzdGF0ZVNhdmVDYWxsYmFja1wiOiBmdW5jdGlvbiAoc2V0dGluZ3MsIGRhdGEpIHtcblx0XHQgKiAgICAgICAgICAvLyBTZW5kIGFuIEFqYXggcmVxdWVzdCB0byB0aGUgc2VydmVyIHdpdGggdGhlIHN0YXRlIG9iamVjdFxuXHRcdCAqICAgICAgICAgICQuYWpheCgge1xuXHRcdCAqICAgICAgICAgICAgXCJ1cmxcIjogXCIvc3RhdGVfc2F2ZVwiLFxuXHRcdCAqICAgICAgICAgICAgXCJkYXRhXCI6IGRhdGEsXG5cdFx0ICogICAgICAgICAgICBcImRhdGFUeXBlXCI6IFwianNvblwiLFxuXHRcdCAqICAgICAgICAgICAgXCJtZXRob2RcIjogXCJQT1NUXCJcblx0XHQgKiAgICAgICAgICAgIFwic3VjY2Vzc1wiOiBmdW5jdGlvbiAoKSB7fVxuXHRcdCAqICAgICAgICAgIH0gKTtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImZuU3RhdGVTYXZlQ2FsbGJhY2tcIjogZnVuY3Rpb24gKCBzZXR0aW5ncywgZGF0YSApIHtcblx0XHRcdHRyeSB7XG5cdFx0XHRcdChzZXR0aW5ncy5pU3RhdGVEdXJhdGlvbiA9PT0gLTEgPyBzZXNzaW9uU3RvcmFnZSA6IGxvY2FsU3RvcmFnZSkuc2V0SXRlbShcblx0XHRcdFx0XHQnRGF0YVRhYmxlc18nK3NldHRpbmdzLnNJbnN0YW5jZSsnXycrbG9jYXRpb24ucGF0aG5hbWUsXG5cdFx0XHRcdFx0SlNPTi5zdHJpbmdpZnkoIGRhdGEgKVxuXHRcdFx0XHQpO1xuXHRcdFx0fSBjYXRjaCAoZSkge31cblx0XHR9LFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogQ2FsbGJhY2sgd2hpY2ggYWxsb3dzIG1vZGlmaWNhdGlvbiBvZiB0aGUgc3RhdGUgdG8gYmUgc2F2ZWQuIENhbGxlZCB3aGVuIHRoZSB0YWJsZVxuXHRcdCAqIGhhcyBjaGFuZ2VkIHN0YXRlIGEgbmV3IHN0YXRlIHNhdmUgaXMgcmVxdWlyZWQuIFRoaXMgbWV0aG9kIGFsbG93cyBtb2RpZmljYXRpb24gb2Zcblx0XHQgKiB0aGUgc3RhdGUgc2F2aW5nIG9iamVjdCBwcmlvciB0byBhY3R1YWxseSBkb2luZyB0aGUgc2F2ZSwgaW5jbHVkaW5nIGFkZGl0aW9uIG9yXG5cdFx0ICogb3RoZXIgc3RhdGUgcHJvcGVydGllcyBvciBtb2RpZmljYXRpb24uIE5vdGUgdGhhdCBmb3IgcGx1Zy1pbiBhdXRob3JzLCB5b3Ugc2hvdWxkXG5cdFx0ICogdXNlIHRoZSBgc3RhdGVTYXZlUGFyYW1zYCBldmVudCB0byBzYXZlIHBhcmFtZXRlcnMgZm9yIGEgcGx1Zy1pbi5cblx0XHQgKiAgQHR5cGUgZnVuY3Rpb25cblx0XHQgKiAgQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdFx0ICogIEBwYXJhbSB7b2JqZWN0fSBkYXRhIFRoZSBzdGF0ZSBvYmplY3QgdG8gYmUgc2F2ZWRcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgQ2FsbGJhY2tzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zdGF0ZVNhdmVQYXJhbXNcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFJlbW92ZSBhIHNhdmVkIGZpbHRlciwgc28gZmlsdGVyaW5nIGlzIG5ldmVyIHNhdmVkXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJzdGF0ZVNhdmVcIjogdHJ1ZSxcblx0XHQgKiAgICAgICAgXCJzdGF0ZVNhdmVQYXJhbXNcIjogZnVuY3Rpb24gKHNldHRpbmdzLCBkYXRhKSB7XG5cdFx0ICogICAgICAgICAgZGF0YS5vU2VhcmNoLnNTZWFyY2ggPSBcIlwiO1xuXHRcdCAqICAgICAgICB9XG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiZm5TdGF0ZVNhdmVQYXJhbXNcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIER1cmF0aW9uIGZvciB3aGljaCB0aGUgc2F2ZWQgc3RhdGUgaW5mb3JtYXRpb24gaXMgY29uc2lkZXJlZCB2YWxpZC4gQWZ0ZXIgdGhpcyBwZXJpb2Rcblx0XHQgKiBoYXMgZWxhcHNlZCB0aGUgc3RhdGUgd2lsbCBiZSByZXR1cm5lZCB0byB0aGUgZGVmYXVsdC5cblx0XHQgKiBWYWx1ZSBpcyBnaXZlbiBpbiBzZWNvbmRzLlxuXHRcdCAqICBAdHlwZSBpbnRcblx0XHQgKiAgQGRlZmF1bHQgNzIwMCA8aT4oMiBob3Vycyk8L2k+XG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvbnNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnN0YXRlRHVyYXRpb25cblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwic3RhdGVEdXJhdGlvblwiOiA2MCo2MCoyNDsgLy8gMSBkYXlcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9IClcblx0XHQgKi9cblx0XHRcImlTdGF0ZUR1cmF0aW9uXCI6IDcyMDAsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBXaGVuIGVuYWJsZWQgRGF0YVRhYmxlcyB3aWxsIG5vdCBtYWtlIGEgcmVxdWVzdCB0byB0aGUgc2VydmVyIGZvciB0aGUgZmlyc3Rcblx0XHQgKiBwYWdlIGRyYXcgLSByYXRoZXIgaXQgd2lsbCB1c2UgdGhlIGRhdGEgYWxyZWFkeSBvbiB0aGUgcGFnZSAobm8gc29ydGluZyBldGNcblx0XHQgKiB3aWxsIGJlIGFwcGxpZWQgdG8gaXQpLCB0aHVzIHNhdmluZyBvbiBhbiBYSFIgYXQgbG9hZCB0aW1lLiBgZGVmZXJMb2FkaW5nYFxuXHRcdCAqIGlzIHVzZWQgdG8gaW5kaWNhdGUgdGhhdCBkZWZlcnJlZCBsb2FkaW5nIGlzIHJlcXVpcmVkLCBidXQgaXQgaXMgYWxzbyB1c2VkXG5cdFx0ICogdG8gdGVsbCBEYXRhVGFibGVzIGhvdyBtYW55IHJlY29yZHMgdGhlcmUgYXJlIGluIHRoZSBmdWxsIHRhYmxlIChhbGxvd2luZ1xuXHRcdCAqIHRoZSBpbmZvcm1hdGlvbiBlbGVtZW50IGFuZCBwYWdpbmF0aW9uIHRvIGJlIGRpc3BsYXllZCBjb3JyZWN0bHkpLiBJbiB0aGUgY2FzZVxuXHRcdCAqIHdoZXJlIGEgZmlsdGVyaW5nIGlzIGFwcGxpZWQgdG8gdGhlIHRhYmxlIG9uIGluaXRpYWwgbG9hZCwgdGhpcyBjYW4gYmVcblx0XHQgKiBpbmRpY2F0ZWQgYnkgZ2l2aW5nIHRoZSBwYXJhbWV0ZXIgYXMgYW4gYXJyYXksIHdoZXJlIHRoZSBmaXJzdCBlbGVtZW50IGlzXG5cdFx0ICogdGhlIG51bWJlciBvZiByZWNvcmRzIGF2YWlsYWJsZSBhZnRlciBmaWx0ZXJpbmcgYW5kIHRoZSBzZWNvbmQgZWxlbWVudCBpcyB0aGVcblx0XHQgKiBudW1iZXIgb2YgcmVjb3JkcyB3aXRob3V0IGZpbHRlcmluZyAoYWxsb3dpbmcgdGhlIHRhYmxlIGluZm9ybWF0aW9uIGVsZW1lbnRcblx0XHQgKiB0byBiZSBzaG93biBjb3JyZWN0bHkpLlxuXHRcdCAqICBAdHlwZSBpbnQgfCBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvbnNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmRlZmVyTG9hZGluZ1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gNTcgcmVjb3JkcyBhdmFpbGFibGUgaW4gdGhlIHRhYmxlLCBubyBmaWx0ZXJpbmcgYXBwbGllZFxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwic2VydmVyU2lkZVwiOiB0cnVlLFxuXHRcdCAqICAgICAgICBcImFqYXhcIjogXCJzY3JpcHRzL3NlcnZlcl9wcm9jZXNzaW5nLnBocFwiLFxuXHRcdCAqICAgICAgICBcImRlZmVyTG9hZGluZ1wiOiA1N1xuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIDU3IHJlY29yZHMgYWZ0ZXIgZmlsdGVyaW5nLCAxMDAgd2l0aG91dCBmaWx0ZXJpbmcgKGFuIGluaXRpYWwgZmlsdGVyIGFwcGxpZWQpXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJzZXJ2ZXJTaWRlXCI6IHRydWUsXG5cdFx0ICogICAgICAgIFwiYWpheFwiOiBcInNjcmlwdHMvc2VydmVyX3Byb2Nlc3NpbmcucGhwXCIsXG5cdFx0ICogICAgICAgIFwiZGVmZXJMb2FkaW5nXCI6IFsgNTcsIDEwMCBdLFxuXHRcdCAqICAgICAgICBcInNlYXJjaFwiOiB7XG5cdFx0ICogICAgICAgICAgXCJzZWFyY2hcIjogXCJteV9maWx0ZXJcIlxuXHRcdCAqICAgICAgICB9XG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiaURlZmVyTG9hZGluZ1wiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogTnVtYmVyIG9mIHJvd3MgdG8gZGlzcGxheSBvbiBhIHNpbmdsZSBwYWdlIHdoZW4gdXNpbmcgcGFnaW5hdGlvbi4gSWZcblx0XHQgKiBmZWF0dXJlIGVuYWJsZWQgKGBsZW5ndGhDaGFuZ2VgKSB0aGVuIHRoZSBlbmQgdXNlciB3aWxsIGJlIGFibGUgdG8gb3ZlcnJpZGVcblx0XHQgKiB0aGlzIHRvIGEgY3VzdG9tIHNldHRpbmcgdXNpbmcgYSBwb3AtdXAgbWVudS5cblx0XHQgKiAgQHR5cGUgaW50XG5cdFx0ICogIEBkZWZhdWx0IDEwXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvbnNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnBhZ2VMZW5ndGhcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwicGFnZUxlbmd0aFwiOiA1MFxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKVxuXHRcdCAqL1xuXHRcdFwiaURpc3BsYXlMZW5ndGhcIjogMTAsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBEZWZpbmUgdGhlIHN0YXJ0aW5nIHBvaW50IGZvciBkYXRhIGRpc3BsYXkgd2hlbiB1c2luZyBEYXRhVGFibGVzIHdpdGhcblx0XHQgKiBwYWdpbmF0aW9uLiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgaXMgdGhlIG51bWJlciBvZiByZWNvcmRzLCByYXRoZXIgdGhhblxuXHRcdCAqIHRoZSBwYWdlIG51bWJlciwgc28gaWYgeW91IGhhdmUgMTAgcmVjb3JkcyBwZXIgcGFnZSBhbmQgd2FudCB0byBzdGFydCBvblxuXHRcdCAqIHRoZSB0aGlyZCBwYWdlLCBpdCBzaG91bGQgYmUgXCIyMFwiLlxuXHRcdCAqICBAdHlwZSBpbnRcblx0XHQgKiAgQGRlZmF1bHQgMFxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBPcHRpb25zXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5kaXNwbGF5U3RhcnRcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiZGlzcGxheVN0YXJ0XCI6IDIwXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApXG5cdFx0ICovXG5cdFx0XCJpRGlzcGxheVN0YXJ0XCI6IDAsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBCeSBkZWZhdWx0IERhdGFUYWJsZXMgYWxsb3dzIGtleWJvYXJkIG5hdmlnYXRpb24gb2YgdGhlIHRhYmxlIChzb3J0aW5nLCBwYWdpbmcsXG5cdFx0ICogYW5kIGZpbHRlcmluZykgYnkgYWRkaW5nIGEgYHRhYmluZGV4YCBhdHRyaWJ1dGUgdG8gdGhlIHJlcXVpcmVkIGVsZW1lbnRzLiBUaGlzXG5cdFx0ICogYWxsb3dzIHlvdSB0byB0YWIgdGhyb3VnaCB0aGUgY29udHJvbHMgYW5kIHByZXNzIHRoZSBlbnRlciBrZXkgdG8gYWN0aXZhdGUgdGhlbS5cblx0XHQgKiBUaGUgdGFiaW5kZXggaXMgZGVmYXVsdCAwLCBtZWFuaW5nIHRoYXQgdGhlIHRhYiBmb2xsb3dzIHRoZSBmbG93IG9mIHRoZSBkb2N1bWVudC5cblx0XHQgKiBZb3UgY2FuIG92ZXJydWxlIHRoaXMgdXNpbmcgdGhpcyBwYXJhbWV0ZXIgaWYgeW91IHdpc2guIFVzZSBhIHZhbHVlIG9mIC0xIHRvXG5cdFx0ICogZGlzYWJsZSBidWlsdC1pbiBrZXlib2FyZCBuYXZpZ2F0aW9uLlxuXHRcdCAqICBAdHlwZSBpbnRcblx0XHQgKiAgQGRlZmF1bHQgMFxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBPcHRpb25zXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy50YWJJbmRleFxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJ0YWJJbmRleFwiOiAxXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiaVRhYkluZGV4XCI6IDAsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBDbGFzc2VzIHRoYXQgRGF0YVRhYmxlcyBhc3NpZ25zIHRvIHRoZSB2YXJpb3VzIGNvbXBvbmVudHMgYW5kIGZlYXR1cmVzXG5cdFx0ICogdGhhdCBpdCBhZGRzIHRvIHRoZSBIVE1MIHRhYmxlLiBUaGlzIGFsbG93cyBjbGFzc2VzIHRvIGJlIGNvbmZpZ3VyZWRcblx0XHQgKiBkdXJpbmcgaW5pdGlhbGlzYXRpb24gaW4gYWRkaXRpb24gdG8gdGhyb3VnaCB0aGUgc3RhdGljXG5cdFx0ICoge0BsaW5rIERhdGFUYWJsZS5leHQub1N0ZENsYXNzZXN9IG9iamVjdCkuXG5cdFx0ICogIEBuYW1lc3BhY2Vcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNsYXNzZXNcblx0XHQgKi9cblx0XHRcIm9DbGFzc2VzXCI6IHt9LFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogQWxsIHN0cmluZ3MgdGhhdCBEYXRhVGFibGVzIHVzZXMgaW4gdGhlIHVzZXIgaW50ZXJmYWNlIHRoYXQgaXQgY3JlYXRlc1xuXHRcdCAqIGFyZSBkZWZpbmVkIGluIHRoaXMgb2JqZWN0LCBhbGxvd2luZyB5b3UgdG8gbW9kaWZpZWQgdGhlbSBpbmRpdmlkdWFsbHkgb3Jcblx0XHQgKiBjb21wbGV0ZWx5IHJlcGxhY2UgdGhlbSBhbGwgYXMgcmVxdWlyZWQuXG5cdFx0ICogIEBuYW1lc3BhY2Vcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlXG5cdFx0ICovXG5cdFx0XCJvTGFuZ3VhZ2VcIjoge1xuXHRcdFx0LyoqXG5cdFx0XHQgKiBTdHJpbmdzIHRoYXQgYXJlIHVzZWQgZm9yIFdBSS1BUklBIGxhYmVscyBhbmQgY29udHJvbHMgb25seSAodGhlc2UgYXJlIG5vdFxuXHRcdFx0ICogYWN0dWFsbHkgdmlzaWJsZSBvbiB0aGUgcGFnZSwgYnV0IHdpbGwgYmUgcmVhZCBieSBzY3JlZW5yZWFkZXJzLCBhbmQgdGh1c1xuXHRcdFx0ICogbXVzdCBiZSBpbnRlcm5hdGlvbmFsaXNlZCBhcyB3ZWxsKS5cblx0XHRcdCAqICBAbmFtZXNwYWNlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLmFyaWFcblx0XHRcdCAqL1xuXHRcdFx0XCJvQXJpYVwiOiB7XG5cdFx0XHRcdC8qKlxuXHRcdFx0XHQgKiBBUklBIGxhYmVsIHRoYXQgaXMgYWRkZWQgdG8gdGhlIHRhYmxlIGhlYWRlcnMgd2hlbiB0aGUgY29sdW1uIG1heSBiZVxuXHRcdFx0XHQgKiBzb3J0ZWQgYXNjZW5kaW5nIGJ5IGFjdGl2aW5nIHRoZSBjb2x1bW4gKGNsaWNrIG9yIHJldHVybiB3aGVuIGZvY3VzZWQpLlxuXHRcdFx0XHQgKiBOb3RlIHRoYXQgdGhlIGNvbHVtbiBoZWFkZXIgaXMgcHJlZml4ZWQgdG8gdGhpcyBzdHJpbmcuXG5cdFx0XHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHRcdFx0ICogIEBkZWZhdWx0IDogYWN0aXZhdGUgdG8gc29ydCBjb2x1bW4gYXNjZW5kaW5nXG5cdFx0XHRcdCAqXG5cdFx0XHRcdCAqICBAZHRvcHQgTGFuZ3VhZ2Vcblx0XHRcdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5hcmlhLnNvcnRBc2NlbmRpbmdcblx0XHRcdFx0ICpcblx0XHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0XHQgKiAgICAgICAgXCJsYW5ndWFnZVwiOiB7XG5cdFx0XHRcdCAqICAgICAgICAgIFwiYXJpYVwiOiB7XG5cdFx0XHRcdCAqICAgICAgICAgICAgXCJzb3J0QXNjZW5kaW5nXCI6IFwiIC0gY2xpY2svcmV0dXJuIHRvIHNvcnQgYXNjZW5kaW5nXCJcblx0XHRcdFx0ICogICAgICAgICAgfVxuXHRcdFx0XHQgKiAgICAgICAgfVxuXHRcdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdFx0ICogICAgfSApO1xuXHRcdFx0XHQgKi9cblx0XHRcdFx0XCJzU29ydEFzY2VuZGluZ1wiOiBcIjogYWN0aXZhdGUgdG8gc29ydCBjb2x1bW4gYXNjZW5kaW5nXCIsXG5cdFxuXHRcdFx0XHQvKipcblx0XHRcdFx0ICogQVJJQSBsYWJlbCB0aGF0IGlzIGFkZGVkIHRvIHRoZSB0YWJsZSBoZWFkZXJzIHdoZW4gdGhlIGNvbHVtbiBtYXkgYmVcblx0XHRcdFx0ICogc29ydGVkIGRlc2NlbmRpbmcgYnkgYWN0aXZpbmcgdGhlIGNvbHVtbiAoY2xpY2sgb3IgcmV0dXJuIHdoZW4gZm9jdXNlZCkuXG5cdFx0XHRcdCAqIE5vdGUgdGhhdCB0aGUgY29sdW1uIGhlYWRlciBpcyBwcmVmaXhlZCB0byB0aGlzIHN0cmluZy5cblx0XHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0XHQgKiAgQGRlZmF1bHQgOiBhY3RpdmF0ZSB0byBzb3J0IGNvbHVtbiBhc2NlbmRpbmdcblx0XHRcdFx0ICpcblx0XHRcdFx0ICogIEBkdG9wdCBMYW5ndWFnZVxuXHRcdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLmFyaWEuc29ydERlc2NlbmRpbmdcblx0XHRcdFx0ICpcblx0XHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0XHQgKiAgICAgICAgXCJsYW5ndWFnZVwiOiB7XG5cdFx0XHRcdCAqICAgICAgICAgIFwiYXJpYVwiOiB7XG5cdFx0XHRcdCAqICAgICAgICAgICAgXCJzb3J0RGVzY2VuZGluZ1wiOiBcIiAtIGNsaWNrL3JldHVybiB0byBzb3J0IGRlc2NlbmRpbmdcIlxuXHRcdFx0XHQgKiAgICAgICAgICB9XG5cdFx0XHRcdCAqICAgICAgICB9XG5cdFx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0XHQgKiAgICB9ICk7XG5cdFx0XHRcdCAqL1xuXHRcdFx0XHRcInNTb3J0RGVzY2VuZGluZ1wiOiBcIjogYWN0aXZhdGUgdG8gc29ydCBjb2x1bW4gZGVzY2VuZGluZ1wiXG5cdFx0XHR9LFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogUGFnaW5hdGlvbiBzdHJpbmcgdXNlZCBieSBEYXRhVGFibGVzIGZvciB0aGUgYnVpbHQtaW4gcGFnaW5hdGlvblxuXHRcdFx0ICogY29udHJvbCB0eXBlcy5cblx0XHRcdCAqICBAbmFtZXNwYWNlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLnBhZ2luYXRlXG5cdFx0XHQgKi9cblx0XHRcdFwib1BhZ2luYXRlXCI6IHtcblx0XHRcdFx0LyoqXG5cdFx0XHRcdCAqIFRleHQgdG8gdXNlIHdoZW4gdXNpbmcgdGhlICdmdWxsX251bWJlcnMnIHR5cGUgb2YgcGFnaW5hdGlvbiBmb3IgdGhlXG5cdFx0XHRcdCAqIGJ1dHRvbiB0byB0YWtlIHRoZSB1c2VyIHRvIHRoZSBmaXJzdCBwYWdlLlxuXHRcdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHRcdCAqICBAZGVmYXVsdCBGaXJzdFxuXHRcdFx0XHQgKlxuXHRcdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UucGFnaW5hdGUuZmlyc3Rcblx0XHRcdFx0ICpcblx0XHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0XHQgKiAgICAgICAgXCJsYW5ndWFnZVwiOiB7XG5cdFx0XHRcdCAqICAgICAgICAgIFwicGFnaW5hdGVcIjoge1xuXHRcdFx0XHQgKiAgICAgICAgICAgIFwiZmlyc3RcIjogXCJGaXJzdCBwYWdlXCJcblx0XHRcdFx0ICogICAgICAgICAgfVxuXHRcdFx0XHQgKiAgICAgICAgfVxuXHRcdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdFx0ICogICAgfSApO1xuXHRcdFx0XHQgKi9cblx0XHRcdFx0XCJzRmlyc3RcIjogXCJGaXJzdFwiLFxuXHRcblx0XG5cdFx0XHRcdC8qKlxuXHRcdFx0XHQgKiBUZXh0IHRvIHVzZSB3aGVuIHVzaW5nIHRoZSAnZnVsbF9udW1iZXJzJyB0eXBlIG9mIHBhZ2luYXRpb24gZm9yIHRoZVxuXHRcdFx0XHQgKiBidXR0b24gdG8gdGFrZSB0aGUgdXNlciB0byB0aGUgbGFzdCBwYWdlLlxuXHRcdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHRcdCAqICBAZGVmYXVsdCBMYXN0XG5cdFx0XHRcdCAqXG5cdFx0XHRcdCAqICBAZHRvcHQgTGFuZ3VhZ2Vcblx0XHRcdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5wYWdpbmF0ZS5sYXN0XG5cdFx0XHRcdCAqXG5cdFx0XHRcdCAqICBAZXhhbXBsZVxuXHRcdFx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHRcdFx0ICogICAgICAgIFwibGFuZ3VhZ2VcIjoge1xuXHRcdFx0XHQgKiAgICAgICAgICBcInBhZ2luYXRlXCI6IHtcblx0XHRcdFx0ICogICAgICAgICAgICBcImxhc3RcIjogXCJMYXN0IHBhZ2VcIlxuXHRcdFx0XHQgKiAgICAgICAgICB9XG5cdFx0XHRcdCAqICAgICAgICB9XG5cdFx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0XHQgKiAgICB9ICk7XG5cdFx0XHRcdCAqL1xuXHRcdFx0XHRcInNMYXN0XCI6IFwiTGFzdFwiLFxuXHRcblx0XG5cdFx0XHRcdC8qKlxuXHRcdFx0XHQgKiBUZXh0IHRvIHVzZSBmb3IgdGhlICduZXh0JyBwYWdpbmF0aW9uIGJ1dHRvbiAodG8gdGFrZSB0aGUgdXNlciB0byB0aGVcblx0XHRcdFx0ICogbmV4dCBwYWdlKS5cblx0XHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0XHQgKiAgQGRlZmF1bHQgTmV4dFxuXHRcdFx0XHQgKlxuXHRcdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UucGFnaW5hdGUubmV4dFxuXHRcdFx0XHQgKlxuXHRcdFx0XHQgKiAgQGV4YW1wbGVcblx0XHRcdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdFx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0XHRcdCAqICAgICAgICBcImxhbmd1YWdlXCI6IHtcblx0XHRcdFx0ICogICAgICAgICAgXCJwYWdpbmF0ZVwiOiB7XG5cdFx0XHRcdCAqICAgICAgICAgICAgXCJuZXh0XCI6IFwiTmV4dCBwYWdlXCJcblx0XHRcdFx0ICogICAgICAgICAgfVxuXHRcdFx0XHQgKiAgICAgICAgfVxuXHRcdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdFx0ICogICAgfSApO1xuXHRcdFx0XHQgKi9cblx0XHRcdFx0XCJzTmV4dFwiOiBcIk5leHRcIixcblx0XG5cdFxuXHRcdFx0XHQvKipcblx0XHRcdFx0ICogVGV4dCB0byB1c2UgZm9yIHRoZSAncHJldmlvdXMnIHBhZ2luYXRpb24gYnV0dG9uICh0byB0YWtlIHRoZSB1c2VyIHRvXG5cdFx0XHRcdCAqIHRoZSBwcmV2aW91cyBwYWdlKS5cblx0XHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0XHQgKiAgQGRlZmF1bHQgUHJldmlvdXNcblx0XHRcdFx0ICpcblx0XHRcdFx0ICogIEBkdG9wdCBMYW5ndWFnZVxuXHRcdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLnBhZ2luYXRlLnByZXZpb3VzXG5cdFx0XHRcdCAqXG5cdFx0XHRcdCAqICBAZXhhbXBsZVxuXHRcdFx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0XHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHRcdFx0ICogICAgICAgIFwibGFuZ3VhZ2VcIjoge1xuXHRcdFx0XHQgKiAgICAgICAgICBcInBhZ2luYXRlXCI6IHtcblx0XHRcdFx0ICogICAgICAgICAgICBcInByZXZpb3VzXCI6IFwiUHJldmlvdXMgcGFnZVwiXG5cdFx0XHRcdCAqICAgICAgICAgIH1cblx0XHRcdFx0ICogICAgICAgIH1cblx0XHRcdFx0ICogICAgICB9ICk7XG5cdFx0XHRcdCAqICAgIH0gKTtcblx0XHRcdFx0ICovXG5cdFx0XHRcdFwic1ByZXZpb3VzXCI6IFwiUHJldmlvdXNcIlxuXHRcdFx0fSxcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIFRoaXMgc3RyaW5nIGlzIHNob3duIGluIHByZWZlcmVuY2UgdG8gYHplcm9SZWNvcmRzYCB3aGVuIHRoZSB0YWJsZSBpc1xuXHRcdFx0ICogZW1wdHkgb2YgZGF0YSAocmVnYXJkbGVzcyBvZiBmaWx0ZXJpbmcpLiBOb3RlIHRoYXQgdGhpcyBpcyBhbiBvcHRpb25hbFxuXHRcdFx0ICogcGFyYW1ldGVyIC0gaWYgaXQgaXMgbm90IGdpdmVuLCB0aGUgdmFsdWUgb2YgYHplcm9SZWNvcmRzYCB3aWxsIGJlIHVzZWRcblx0XHRcdCAqIGluc3RlYWQgKGVpdGhlciB0aGUgZGVmYXVsdCBvciBnaXZlbiB2YWx1ZSkuXG5cdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHQgKiAgQGRlZmF1bHQgTm8gZGF0YSBhdmFpbGFibGUgaW4gdGFibGVcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLmVtcHR5VGFibGVcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGV4YW1wbGVcblx0XHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHRcdCAqICAgICAgICBcImxhbmd1YWdlXCI6IHtcblx0XHRcdCAqICAgICAgICAgIFwiZW1wdHlUYWJsZVwiOiBcIk5vIGRhdGEgYXZhaWxhYmxlIGluIHRhYmxlXCJcblx0XHRcdCAqICAgICAgICB9XG5cdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdCAqICAgIH0gKTtcblx0XHRcdCAqL1xuXHRcdFx0XCJzRW1wdHlUYWJsZVwiOiBcIk5vIGRhdGEgYXZhaWxhYmxlIGluIHRhYmxlXCIsXG5cdFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogVGhpcyBzdHJpbmcgZ2l2ZXMgaW5mb3JtYXRpb24gdG8gdGhlIGVuZCB1c2VyIGFib3V0IHRoZSBpbmZvcm1hdGlvblxuXHRcdFx0ICogdGhhdCBpcyBjdXJyZW50IG9uIGRpc3BsYXkgb24gdGhlIHBhZ2UuIFRoZSBmb2xsb3dpbmcgdG9rZW5zIGNhbiBiZVxuXHRcdFx0ICogdXNlZCBpbiB0aGUgc3RyaW5nIGFuZCB3aWxsIGJlIGR5bmFtaWNhbGx5IHJlcGxhY2VkIGFzIHRoZSB0YWJsZVxuXHRcdFx0ICogZGlzcGxheSB1cGRhdGVzLiBUaGlzIHRva2VucyBjYW4gYmUgcGxhY2VkIGFueXdoZXJlIGluIHRoZSBzdHJpbmcsIG9yXG5cdFx0XHQgKiByZW1vdmVkIGFzIG5lZWRlZCBieSB0aGUgbGFuZ3VhZ2UgcmVxdWlyZXM6XG5cdFx0XHQgKlxuXHRcdFx0ICogKiBgXFxfU1RBUlRcXF9gIC0gRGlzcGxheSBpbmRleCBvZiB0aGUgZmlyc3QgcmVjb3JkIG9uIHRoZSBjdXJyZW50IHBhZ2Vcblx0XHRcdCAqICogYFxcX0VORFxcX2AgLSBEaXNwbGF5IGluZGV4IG9mIHRoZSBsYXN0IHJlY29yZCBvbiB0aGUgY3VycmVudCBwYWdlXG5cdFx0XHQgKiAqIGBcXF9UT1RBTFxcX2AgLSBOdW1iZXIgb2YgcmVjb3JkcyBpbiB0aGUgdGFibGUgYWZ0ZXIgZmlsdGVyaW5nXG5cdFx0XHQgKiAqIGBcXF9NQVhcXF9gIC0gTnVtYmVyIG9mIHJlY29yZHMgaW4gdGhlIHRhYmxlIHdpdGhvdXQgZmlsdGVyaW5nXG5cdFx0XHQgKiAqIGBcXF9QQUdFXFxfYCAtIEN1cnJlbnQgcGFnZSBudW1iZXJcblx0XHRcdCAqICogYFxcX1BBR0VTXFxfYCAtIFRvdGFsIG51bWJlciBvZiBwYWdlcyBvZiBkYXRhIGluIHRoZSB0YWJsZVxuXHRcdFx0ICpcblx0XHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHRcdCAqICBAZGVmYXVsdCBTaG93aW5nIF9TVEFSVF8gdG8gX0VORF8gb2YgX1RPVEFMXyBlbnRyaWVzXG5cdFx0XHQgKlxuXHRcdFx0ICogIEBkdG9wdCBMYW5ndWFnZVxuXHRcdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5pbmZvXG5cdFx0XHQgKlxuXHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0XHQgKiAgICAgICAgXCJsYW5ndWFnZVwiOiB7XG5cdFx0XHQgKiAgICAgICAgICBcImluZm9cIjogXCJTaG93aW5nIHBhZ2UgX1BBR0VfIG9mIF9QQUdFU19cIlxuXHRcdFx0ICogICAgICAgIH1cblx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0ICogICAgfSApO1xuXHRcdFx0ICovXG5cdFx0XHRcInNJbmZvXCI6IFwiU2hvd2luZyBfU1RBUlRfIHRvIF9FTkRfIG9mIF9UT1RBTF8gZW50cmllc1wiLFxuXHRcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIERpc3BsYXkgaW5mb3JtYXRpb24gc3RyaW5nIGZvciB3aGVuIHRoZSB0YWJsZSBpcyBlbXB0eS4gVHlwaWNhbGx5IHRoZVxuXHRcdFx0ICogZm9ybWF0IG9mIHRoaXMgc3RyaW5nIHNob3VsZCBtYXRjaCBgaW5mb2AuXG5cdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHQgKiAgQGRlZmF1bHQgU2hvd2luZyAwIHRvIDAgb2YgMCBlbnRyaWVzXG5cdFx0XHQgKlxuXHRcdFx0ICogIEBkdG9wdCBMYW5ndWFnZVxuXHRcdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5pbmZvRW1wdHlcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGV4YW1wbGVcblx0XHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHRcdCAqICAgICAgICBcImxhbmd1YWdlXCI6IHtcblx0XHRcdCAqICAgICAgICAgIFwiaW5mb0VtcHR5XCI6IFwiTm8gZW50cmllcyB0byBzaG93XCJcblx0XHRcdCAqICAgICAgICB9XG5cdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdCAqICAgIH0gKTtcblx0XHRcdCAqL1xuXHRcdFx0XCJzSW5mb0VtcHR5XCI6IFwiU2hvd2luZyAwIHRvIDAgb2YgMCBlbnRyaWVzXCIsXG5cdFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogV2hlbiBhIHVzZXIgZmlsdGVycyB0aGUgaW5mb3JtYXRpb24gaW4gYSB0YWJsZSwgdGhpcyBzdHJpbmcgaXMgYXBwZW5kZWRcblx0XHRcdCAqIHRvIHRoZSBpbmZvcm1hdGlvbiAoYGluZm9gKSB0byBnaXZlIGFuIGlkZWEgb2YgaG93IHN0cm9uZyB0aGUgZmlsdGVyaW5nXG5cdFx0XHQgKiBpcy4gVGhlIHZhcmlhYmxlIF9NQVhfIGlzIGR5bmFtaWNhbGx5IHVwZGF0ZWQuXG5cdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHQgKiAgQGRlZmF1bHQgKGZpbHRlcmVkIGZyb20gX01BWF8gdG90YWwgZW50cmllcylcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLmluZm9GaWx0ZXJlZFxuXHRcdFx0ICpcblx0XHRcdCAqICBAZXhhbXBsZVxuXHRcdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0ICogICAgICAgIFwibGFuZ3VhZ2VcIjoge1xuXHRcdFx0ICogICAgICAgICAgXCJpbmZvRmlsdGVyZWRcIjogXCIgLSBmaWx0ZXJpbmcgZnJvbSBfTUFYXyByZWNvcmRzXCJcblx0XHRcdCAqICAgICAgICB9XG5cdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdCAqICAgIH0gKTtcblx0XHRcdCAqL1xuXHRcdFx0XCJzSW5mb0ZpbHRlcmVkXCI6IFwiKGZpbHRlcmVkIGZyb20gX01BWF8gdG90YWwgZW50cmllcylcIixcblx0XG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBJZiBjYW4gYmUgdXNlZnVsIHRvIGFwcGVuZCBleHRyYSBpbmZvcm1hdGlvbiB0byB0aGUgaW5mbyBzdHJpbmcgYXQgdGltZXMsXG5cdFx0XHQgKiBhbmQgdGhpcyB2YXJpYWJsZSBkb2VzIGV4YWN0bHkgdGhhdC4gVGhpcyBpbmZvcm1hdGlvbiB3aWxsIGJlIGFwcGVuZGVkIHRvXG5cdFx0XHQgKiB0aGUgYGluZm9gIChgaW5mb0VtcHR5YCBhbmQgYGluZm9GaWx0ZXJlZGAgaW4gd2hhdGV2ZXIgY29tYmluYXRpb24gdGhleSBhcmVcblx0XHRcdCAqIGJlaW5nIHVzZWQpIGF0IGFsbCB0aW1lcy5cblx0XHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHRcdCAqICBAZGVmYXVsdCA8aT5FbXB0eSBzdHJpbmc8L2k+XG5cdFx0XHQgKlxuXHRcdFx0ICogIEBkdG9wdCBMYW5ndWFnZVxuXHRcdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5sYW5ndWFnZS5pbmZvUG9zdEZpeFxuXHRcdFx0ICpcblx0XHRcdCAqICBAZXhhbXBsZVxuXHRcdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0ICogICAgICAgIFwibGFuZ3VhZ2VcIjoge1xuXHRcdFx0ICogICAgICAgICAgXCJpbmZvUG9zdEZpeFwiOiBcIkFsbCByZWNvcmRzIHNob3duIGFyZSBkZXJpdmVkIGZyb20gcmVhbCBpbmZvcm1hdGlvbi5cIlxuXHRcdFx0ICogICAgICAgIH1cblx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0ICogICAgfSApO1xuXHRcdFx0ICovXG5cdFx0XHRcInNJbmZvUG9zdEZpeFwiOiBcIlwiLFxuXHRcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIFRoaXMgZGVjaW1hbCBwbGFjZSBvcGVyYXRvciBpcyBhIGxpdHRsZSBkaWZmZXJlbnQgZnJvbSB0aGUgb3RoZXJcblx0XHRcdCAqIGxhbmd1YWdlIG9wdGlvbnMgc2luY2UgRGF0YVRhYmxlcyBkb2Vzbid0IG91dHB1dCBmbG9hdGluZyBwb2ludFxuXHRcdFx0ICogbnVtYmVycywgc28gaXQgd29uJ3QgZXZlciB1c2UgdGhpcyBmb3IgZGlzcGxheSBvZiBhIG51bWJlci4gUmF0aGVyLFxuXHRcdFx0ICogd2hhdCB0aGlzIHBhcmFtZXRlciBkb2VzIGlzIG1vZGlmeSB0aGUgc29ydCBtZXRob2RzIG9mIHRoZSB0YWJsZSBzb1xuXHRcdFx0ICogdGhhdCBudW1iZXJzIHdoaWNoIGFyZSBpbiBhIGZvcm1hdCB3aGljaCBoYXMgYSBjaGFyYWN0ZXIgb3RoZXIgdGhhblxuXHRcdFx0ICogYSBwZXJpb2QgKGAuYCkgYXMgYSBkZWNpbWFsIHBsYWNlIHdpbGwgYmUgc29ydGVkIG51bWVyaWNhbGx5LlxuXHRcdFx0ICpcblx0XHRcdCAqIE5vdGUgdGhhdCBudW1iZXJzIHdpdGggZGlmZmVyZW50IGRlY2ltYWwgcGxhY2VzIGNhbm5vdCBiZSBzaG93biBpblxuXHRcdFx0ICogdGhlIHNhbWUgdGFibGUgYW5kIHN0aWxsIGJlIHNvcnRhYmxlLCB0aGUgdGFibGUgbXVzdCBiZSBjb25zaXN0ZW50LlxuXHRcdFx0ICogSG93ZXZlciwgbXVsdGlwbGUgZGlmZmVyZW50IHRhYmxlcyBvbiB0aGUgcGFnZSBjYW4gdXNlIGRpZmZlcmVudFxuXHRcdFx0ICogZGVjaW1hbCBwbGFjZSBjaGFyYWN0ZXJzLlxuXHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0ICogIEBkZWZhdWx0IFxuXHRcdFx0ICpcblx0XHRcdCAqICBAZHRvcHQgTGFuZ3VhZ2Vcblx0XHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UuZGVjaW1hbFxuXHRcdFx0ICpcblx0XHRcdCAqICBAZXhhbXBsZVxuXHRcdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0ICogICAgICAgIFwibGFuZ3VhZ2VcIjoge1xuXHRcdFx0ICogICAgICAgICAgXCJkZWNpbWFsXCI6IFwiLFwiXG5cdFx0XHQgKiAgICAgICAgICBcInRob3VzYW5kc1wiOiBcIi5cIlxuXHRcdFx0ICogICAgICAgIH1cblx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0ICogICAgfSApO1xuXHRcdFx0ICovXG5cdFx0XHRcInNEZWNpbWFsXCI6IFwiXCIsXG5cdFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogRGF0YVRhYmxlcyBoYXMgYSBidWlsZCBpbiBudW1iZXIgZm9ybWF0dGVyIChgZm9ybWF0TnVtYmVyYCkgd2hpY2ggaXNcblx0XHRcdCAqIHVzZWQgdG8gZm9ybWF0IGxhcmdlIG51bWJlcnMgdGhhdCBhcmUgdXNlZCBpbiB0aGUgdGFibGUgaW5mb3JtYXRpb24uXG5cdFx0XHQgKiBCeSBkZWZhdWx0IGEgY29tbWEgaXMgdXNlZCwgYnV0IHRoaXMgY2FuIGJlIHRyaXZpYWxseSBjaGFuZ2VkIHRvIGFueVxuXHRcdFx0ICogY2hhcmFjdGVyIHlvdSB3aXNoIHdpdGggdGhpcyBwYXJhbWV0ZXIuXG5cdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHQgKiAgQGRlZmF1bHQgLFxuXHRcdFx0ICpcblx0XHRcdCAqICBAZHRvcHQgTGFuZ3VhZ2Vcblx0XHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UudGhvdXNhbmRzXG5cdFx0XHQgKlxuXHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0XHQgKiAgICAgICAgXCJsYW5ndWFnZVwiOiB7XG5cdFx0XHQgKiAgICAgICAgICBcInRob3VzYW5kc1wiOiBcIidcIlxuXHRcdFx0ICogICAgICAgIH1cblx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0ICogICAgfSApO1xuXHRcdFx0ICovXG5cdFx0XHRcInNUaG91c2FuZHNcIjogXCIsXCIsXG5cdFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogRGV0YWlsIHRoZSBhY3Rpb24gdGhhdCB3aWxsIGJlIHRha2VuIHdoZW4gdGhlIGRyb3AgZG93biBtZW51IGZvciB0aGVcblx0XHRcdCAqIHBhZ2luYXRpb24gbGVuZ3RoIG9wdGlvbiBpcyBjaGFuZ2VkLiBUaGUgJ19NRU5VXycgdmFyaWFibGUgaXMgcmVwbGFjZWRcblx0XHRcdCAqIHdpdGggYSBkZWZhdWx0IHNlbGVjdCBsaXN0IG9mIDEwLCAyNSwgNTAgYW5kIDEwMCwgYW5kIGNhbiBiZSByZXBsYWNlZFxuXHRcdFx0ICogd2l0aCBhIGN1c3RvbSBzZWxlY3QgYm94IGlmIHJlcXVpcmVkLlxuXHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0ICogIEBkZWZhdWx0IFNob3cgX01FTlVfIGVudHJpZXNcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLmxlbmd0aE1lbnVcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGV4YW1wbGVcblx0XHRcdCAqICAgIC8vIExhbmd1YWdlIGNoYW5nZSBvbmx5XG5cdFx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0XHQgKiAgICAgICAgXCJsYW5ndWFnZVwiOiB7XG5cdFx0XHQgKiAgICAgICAgICBcImxlbmd0aE1lbnVcIjogXCJEaXNwbGF5IF9NRU5VXyByZWNvcmRzXCJcblx0XHRcdCAqICAgICAgICB9XG5cdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdCAqICAgIH0gKTtcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGV4YW1wbGVcblx0XHRcdCAqICAgIC8vIExhbmd1YWdlIGFuZCBvcHRpb25zIGNoYW5nZVxuXHRcdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0ICogICAgICAgIFwibGFuZ3VhZ2VcIjoge1xuXHRcdFx0ICogICAgICAgICAgXCJsZW5ndGhNZW51XCI6ICdEaXNwbGF5IDxzZWxlY3Q+Jytcblx0XHRcdCAqICAgICAgICAgICAgJzxvcHRpb24gdmFsdWU9XCIxMFwiPjEwPC9vcHRpb24+Jytcblx0XHRcdCAqICAgICAgICAgICAgJzxvcHRpb24gdmFsdWU9XCIyMFwiPjIwPC9vcHRpb24+Jytcblx0XHRcdCAqICAgICAgICAgICAgJzxvcHRpb24gdmFsdWU9XCIzMFwiPjMwPC9vcHRpb24+Jytcblx0XHRcdCAqICAgICAgICAgICAgJzxvcHRpb24gdmFsdWU9XCI0MFwiPjQwPC9vcHRpb24+Jytcblx0XHRcdCAqICAgICAgICAgICAgJzxvcHRpb24gdmFsdWU9XCI1MFwiPjUwPC9vcHRpb24+Jytcblx0XHRcdCAqICAgICAgICAgICAgJzxvcHRpb24gdmFsdWU9XCItMVwiPkFsbDwvb3B0aW9uPicrXG5cdFx0XHQgKiAgICAgICAgICAgICc8L3NlbGVjdD4gcmVjb3Jkcydcblx0XHRcdCAqICAgICAgICB9XG5cdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdCAqICAgIH0gKTtcblx0XHRcdCAqL1xuXHRcdFx0XCJzTGVuZ3RoTWVudVwiOiBcIlNob3cgX01FTlVfIGVudHJpZXNcIixcblx0XG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBXaGVuIHVzaW5nIEFqYXggc291cmNlZCBkYXRhIGFuZCBkdXJpbmcgdGhlIGZpcnN0IGRyYXcgd2hlbiBEYXRhVGFibGVzIGlzXG5cdFx0XHQgKiBnYXRoZXJpbmcgdGhlIGRhdGEsIHRoaXMgbWVzc2FnZSBpcyBzaG93biBpbiBhbiBlbXB0eSByb3cgaW4gdGhlIHRhYmxlIHRvXG5cdFx0XHQgKiBpbmRpY2F0ZSB0byB0aGUgZW5kIHVzZXIgdGhlIHRoZSBkYXRhIGlzIGJlaW5nIGxvYWRlZC4gTm90ZSB0aGF0IHRoaXNcblx0XHRcdCAqIHBhcmFtZXRlciBpcyBub3QgdXNlZCB3aGVuIGxvYWRpbmcgZGF0YSBieSBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nLCBqdXN0XG5cdFx0XHQgKiBBamF4IHNvdXJjZWQgZGF0YSB3aXRoIGNsaWVudC1zaWRlIHByb2Nlc3NpbmcuXG5cdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHQgKiAgQGRlZmF1bHQgTG9hZGluZy4uLlxuXHRcdFx0ICpcblx0XHRcdCAqICBAZHRvcHQgTGFuZ3VhZ2Vcblx0XHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2UubG9hZGluZ1JlY29yZHNcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGV4YW1wbGVcblx0XHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHRcdCAqICAgICAgICBcImxhbmd1YWdlXCI6IHtcblx0XHRcdCAqICAgICAgICAgIFwibG9hZGluZ1JlY29yZHNcIjogXCJQbGVhc2Ugd2FpdCAtIGxvYWRpbmcuLi5cIlxuXHRcdFx0ICogICAgICAgIH1cblx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0ICogICAgfSApO1xuXHRcdFx0ICovXG5cdFx0XHRcInNMb2FkaW5nUmVjb3Jkc1wiOiBcIkxvYWRpbmcuLi5cIixcblx0XG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBUZXh0IHdoaWNoIGlzIGRpc3BsYXllZCB3aGVuIHRoZSB0YWJsZSBpcyBwcm9jZXNzaW5nIGEgdXNlciBhY3Rpb25cblx0XHRcdCAqICh1c3VhbGx5IGEgc29ydCBjb21tYW5kIG9yIHNpbWlsYXIpLlxuXHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0ICogIEBkZWZhdWx0IFByb2Nlc3NpbmcuLi5cblx0XHRcdCAqXG5cdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLnByb2Nlc3Npbmdcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGV4YW1wbGVcblx0XHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHRcdCAqICAgICAgICBcImxhbmd1YWdlXCI6IHtcblx0XHRcdCAqICAgICAgICAgIFwicHJvY2Vzc2luZ1wiOiBcIkRhdGFUYWJsZXMgaXMgY3VycmVudGx5IGJ1c3lcIlxuXHRcdFx0ICogICAgICAgIH1cblx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0ICogICAgfSApO1xuXHRcdFx0ICovXG5cdFx0XHRcInNQcm9jZXNzaW5nXCI6IFwiUHJvY2Vzc2luZy4uLlwiLFxuXHRcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIERldGFpbHMgdGhlIGFjdGlvbnMgdGhhdCB3aWxsIGJlIHRha2VuIHdoZW4gdGhlIHVzZXIgdHlwZXMgaW50byB0aGVcblx0XHRcdCAqIGZpbHRlcmluZyBpbnB1dCB0ZXh0IGJveC4gVGhlIHZhcmlhYmxlIFwiX0lOUFVUX1wiLCBpZiB1c2VkIGluIHRoZSBzdHJpbmcsXG5cdFx0XHQgKiBpcyByZXBsYWNlZCB3aXRoIHRoZSBIVE1MIHRleHQgYm94IGZvciB0aGUgZmlsdGVyaW5nIGlucHV0IGFsbG93aW5nXG5cdFx0XHQgKiBjb250cm9sIG92ZXIgd2hlcmUgaXQgYXBwZWFycyBpbiB0aGUgc3RyaW5nLiBJZiBcIl9JTlBVVF9cIiBpcyBub3QgZ2l2ZW5cblx0XHRcdCAqIHRoZW4gdGhlIGlucHV0IGJveCBpcyBhcHBlbmRlZCB0byB0aGUgc3RyaW5nIGF1dG9tYXRpY2FsbHkuXG5cdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHQgKiAgQGRlZmF1bHQgU2VhcmNoOlxuXHRcdFx0ICpcblx0XHRcdCAqICBAZHRvcHQgTGFuZ3VhZ2Vcblx0XHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMubGFuZ3VhZ2Uuc2VhcmNoXG5cdFx0XHQgKlxuXHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHQgKiAgICAvLyBJbnB1dCB0ZXh0IGJveCB3aWxsIGJlIGFwcGVuZGVkIGF0IHRoZSBlbmQgYXV0b21hdGljYWxseVxuXHRcdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0ICogICAgICAgIFwibGFuZ3VhZ2VcIjoge1xuXHRcdFx0ICogICAgICAgICAgXCJzZWFyY2hcIjogXCJGaWx0ZXIgcmVjb3JkczpcIlxuXHRcdFx0ICogICAgICAgIH1cblx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0ICogICAgfSApO1xuXHRcdFx0ICpcblx0XHRcdCAqICBAZXhhbXBsZVxuXHRcdFx0ICogICAgLy8gU3BlY2lmeSB3aGVyZSB0aGUgZmlsdGVyIHNob3VsZCBhcHBlYXJcblx0XHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHRcdCAqICAgICAgICBcImxhbmd1YWdlXCI6IHtcblx0XHRcdCAqICAgICAgICAgIFwic2VhcmNoXCI6IFwiQXBwbHkgZmlsdGVyIF9JTlBVVF8gdG8gdGFibGVcIlxuXHRcdFx0ICogICAgICAgIH1cblx0XHRcdCAqICAgICAgfSApO1xuXHRcdFx0ICogICAgfSApO1xuXHRcdFx0ICovXG5cdFx0XHRcInNTZWFyY2hcIjogXCJTZWFyY2g6XCIsXG5cdFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogQXNzaWduIGEgYHBsYWNlaG9sZGVyYCBhdHRyaWJ1dGUgdG8gdGhlIHNlYXJjaCBgaW5wdXRgIGVsZW1lbnRcblx0XHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHRcdCAqICBAZGVmYXVsdCBcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLnNlYXJjaFBsYWNlaG9sZGVyXG5cdFx0XHQgKi9cblx0XHRcdFwic1NlYXJjaFBsYWNlaG9sZGVyXCI6IFwiXCIsXG5cdFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogQWxsIG9mIHRoZSBsYW5ndWFnZSBpbmZvcm1hdGlvbiBjYW4gYmUgc3RvcmVkIGluIGEgZmlsZSBvbiB0aGVcblx0XHRcdCAqIHNlcnZlci1zaWRlLCB3aGljaCBEYXRhVGFibGVzIHdpbGwgbG9vayB1cCBpZiB0aGlzIHBhcmFtZXRlciBpcyBwYXNzZWQuXG5cdFx0XHQgKiBJdCBtdXN0IHN0b3JlIHRoZSBVUkwgb2YgdGhlIGxhbmd1YWdlIGZpbGUsIHdoaWNoIGlzIGluIGEgSlNPTiBmb3JtYXQsXG5cdFx0XHQgKiBhbmQgdGhlIG9iamVjdCBoYXMgdGhlIHNhbWUgcHJvcGVydGllcyBhcyB0aGUgb0xhbmd1YWdlIG9iamVjdCBpbiB0aGVcblx0XHRcdCAqIGluaXRpYWxpc2VyIG9iamVjdCAoaS5lLiB0aGUgYWJvdmUgcGFyYW1ldGVycykuIFBsZWFzZSByZWZlciB0byBvbmUgb2Zcblx0XHRcdCAqIHRoZSBleGFtcGxlIGxhbmd1YWdlIGZpbGVzIHRvIHNlZSBob3cgdGhpcyB3b3JrcyBpbiBhY3Rpb24uXG5cdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHQgKiAgQGRlZmF1bHQgPGk+RW1wdHkgc3RyaW5nIC0gaS5lLiBkaXNhYmxlZDwvaT5cblx0XHRcdCAqXG5cdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLnVybFxuXHRcdFx0ICpcblx0XHRcdCAqICBAZXhhbXBsZVxuXHRcdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdFx0ICogICAgICAgIFwibGFuZ3VhZ2VcIjoge1xuXHRcdFx0ICogICAgICAgICAgXCJ1cmxcIjogXCJodHRwOi8vd3d3LnNwcnltZWRpYS5jby51ay9kYXRhVGFibGVzL2xhbmcudHh0XCJcblx0XHRcdCAqICAgICAgICB9XG5cdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdCAqICAgIH0gKTtcblx0XHRcdCAqL1xuXHRcdFx0XCJzVXJsXCI6IFwiXCIsXG5cdFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogVGV4dCBzaG93biBpbnNpZGUgdGhlIHRhYmxlIHJlY29yZHMgd2hlbiB0aGUgaXMgbm8gaW5mb3JtYXRpb24gdG8gYmVcblx0XHRcdCAqIGRpc3BsYXllZCBhZnRlciBmaWx0ZXJpbmcuIGBlbXB0eVRhYmxlYCBpcyBzaG93biB3aGVuIHRoZXJlIGlzIHNpbXBseSBub1xuXHRcdFx0ICogaW5mb3JtYXRpb24gaW4gdGhlIHRhYmxlIGF0IGFsbCAocmVnYXJkbGVzcyBvZiBmaWx0ZXJpbmcpLlxuXHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0ICogIEBkZWZhdWx0IE5vIG1hdGNoaW5nIHJlY29yZHMgZm91bmRcblx0XHRcdCAqXG5cdFx0XHQgKiAgQGR0b3B0IExhbmd1YWdlXG5cdFx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmxhbmd1YWdlLnplcm9SZWNvcmRzXG5cdFx0XHQgKlxuXHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0XHQgKiAgICAgICAgXCJsYW5ndWFnZVwiOiB7XG5cdFx0XHQgKiAgICAgICAgICBcInplcm9SZWNvcmRzXCI6IFwiTm8gcmVjb3JkcyB0byBkaXNwbGF5XCJcblx0XHRcdCAqICAgICAgICB9XG5cdFx0XHQgKiAgICAgIH0gKTtcblx0XHRcdCAqICAgIH0gKTtcblx0XHRcdCAqL1xuXHRcdFx0XCJzWmVyb1JlY29yZHNcIjogXCJObyBtYXRjaGluZyByZWNvcmRzIGZvdW5kXCJcblx0XHR9LFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogVGhpcyBwYXJhbWV0ZXIgYWxsb3dzIHlvdSB0byBoYXZlIGRlZmluZSB0aGUgZ2xvYmFsIGZpbHRlcmluZyBzdGF0ZSBhdFxuXHRcdCAqIGluaXRpYWxpc2F0aW9uIHRpbWUuIEFzIGFuIG9iamVjdCB0aGUgYHNlYXJjaGAgcGFyYW1ldGVyIG11c3QgYmVcblx0XHQgKiBkZWZpbmVkLCBidXQgYWxsIG90aGVyIHBhcmFtZXRlcnMgYXJlIG9wdGlvbmFsLiBXaGVuIGByZWdleGAgaXMgdHJ1ZSxcblx0XHQgKiB0aGUgc2VhcmNoIHN0cmluZyB3aWxsIGJlIHRyZWF0ZWQgYXMgYSByZWd1bGFyIGV4cHJlc3Npb24sIHdoZW4gZmFsc2Vcblx0XHQgKiAoZGVmYXVsdCkgaXQgd2lsbCBiZSB0cmVhdGVkIGFzIGEgc3RyYWlnaHQgc3RyaW5nLiBXaGVuIGBzbWFydGBcblx0XHQgKiBEYXRhVGFibGVzIHdpbGwgdXNlIGl0J3Mgc21hcnQgZmlsdGVyaW5nIG1ldGhvZHMgKHRvIHdvcmQgbWF0Y2ggYXRcblx0XHQgKiBhbnkgcG9pbnQgaW4gdGhlIGRhdGEpLCB3aGVuIGZhbHNlIHRoaXMgd2lsbCBub3QgYmUgZG9uZS5cblx0XHQgKiAgQG5hbWVzcGFjZVxuXHRcdCAqICBAZXh0ZW5kcyBEYXRhVGFibGUubW9kZWxzLm9TZWFyY2hcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgT3B0aW9uc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuc2VhcmNoXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcInNlYXJjaFwiOiB7XCJzZWFyY2hcIjogXCJJbml0aWFsIHNlYXJjaFwifVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKVxuXHRcdCAqL1xuXHRcdFwib1NlYXJjaFwiOiAkLmV4dGVuZCgge30sIERhdGFUYWJsZS5tb2RlbHMub1NlYXJjaCApLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogX19EZXByZWNhdGVkX18gVGhlIGZ1bmN0aW9uYWxpdHkgcHJvdmlkZWQgYnkgdGhpcyBwYXJhbWV0ZXIgaGFzIG5vdyBiZWVuXG5cdFx0ICogc3VwZXJzZWRlZCBieSB0aGF0IHByb3ZpZGVkIHRocm91Z2ggYGFqYXhgLCB3aGljaCBzaG91bGQgYmUgdXNlZCBpbnN0ZWFkLlxuXHRcdCAqXG5cdFx0ICogQnkgZGVmYXVsdCBEYXRhVGFibGVzIHdpbGwgbG9vayBmb3IgdGhlIHByb3BlcnR5IGBkYXRhYCAob3IgYGFhRGF0YWAgZm9yXG5cdFx0ICogY29tcGF0aWJpbGl0eSB3aXRoIERhdGFUYWJsZXMgMS45LSkgd2hlbiBvYnRhaW5pbmcgZGF0YSBmcm9tIGFuIEFqYXhcblx0XHQgKiBzb3VyY2Ugb3IgZm9yIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcgLSB0aGlzIHBhcmFtZXRlciBhbGxvd3MgdGhhdFxuXHRcdCAqIHByb3BlcnR5IHRvIGJlIGNoYW5nZWQuIFlvdSBjYW4gdXNlIEphdmFzY3JpcHQgZG90dGVkIG9iamVjdCBub3RhdGlvbiB0b1xuXHRcdCAqIGdldCBhIGRhdGEgc291cmNlIGZvciBtdWx0aXBsZSBsZXZlbHMgb2YgbmVzdGluZy5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IGRhdGFcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgT3B0aW9uc1xuXHRcdCAqICBAZHRvcHQgU2VydmVyLXNpZGVcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmFqYXhEYXRhUHJvcFxuXHRcdCAqXG5cdFx0ICogIEBkZXByZWNhdGVkIDEuMTAuIFBsZWFzZSB1c2UgYGFqYXhgIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHkgbm93LlxuXHRcdCAqL1xuXHRcdFwic0FqYXhEYXRhUHJvcFwiOiBcImRhdGFcIixcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIF9fRGVwcmVjYXRlZF9fIFRoZSBmdW5jdGlvbmFsaXR5IHByb3ZpZGVkIGJ5IHRoaXMgcGFyYW1ldGVyIGhhcyBub3cgYmVlblxuXHRcdCAqIHN1cGVyc2VkZWQgYnkgdGhhdCBwcm92aWRlZCB0aHJvdWdoIGBhamF4YCwgd2hpY2ggc2hvdWxkIGJlIHVzZWQgaW5zdGVhZC5cblx0XHQgKlxuXHRcdCAqIFlvdSBjYW4gaW5zdHJ1Y3QgRGF0YVRhYmxlcyB0byBsb2FkIGRhdGEgZnJvbSBhbiBleHRlcm5hbFxuXHRcdCAqIHNvdXJjZSB1c2luZyB0aGlzIHBhcmFtZXRlciAodXNlIGFEYXRhIGlmIHlvdSB3YW50IHRvIHBhc3MgZGF0YSBpbiB5b3Vcblx0XHQgKiBhbHJlYWR5IGhhdmUpLiBTaW1wbHkgcHJvdmlkZSBhIHVybCBhIEpTT04gb2JqZWN0IGNhbiBiZSBvYnRhaW5lZCBmcm9tLlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBPcHRpb25zXG5cdFx0ICogIEBkdG9wdCBTZXJ2ZXItc2lkZVxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuYWpheFNvdXJjZVxuXHRcdCAqXG5cdFx0ICogIEBkZXByZWNhdGVkIDEuMTAuIFBsZWFzZSB1c2UgYGFqYXhgIGZvciB0aGlzIGZ1bmN0aW9uYWxpdHkgbm93LlxuXHRcdCAqL1xuXHRcdFwic0FqYXhTb3VyY2VcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoaXMgaW5pdGlhbGlzYXRpb24gdmFyaWFibGUgYWxsb3dzIHlvdSB0byBzcGVjaWZ5IGV4YWN0bHkgd2hlcmUgaW4gdGhlXG5cdFx0ICogRE9NIHlvdSB3YW50IERhdGFUYWJsZXMgdG8gaW5qZWN0IHRoZSB2YXJpb3VzIGNvbnRyb2xzIGl0IGFkZHMgdG8gdGhlIHBhZ2Vcblx0XHQgKiAoZm9yIGV4YW1wbGUgeW91IG1pZ2h0IHdhbnQgdGhlIHBhZ2luYXRpb24gY29udHJvbHMgYXQgdGhlIHRvcCBvZiB0aGVcblx0XHQgKiB0YWJsZSkuIERJViBlbGVtZW50cyAod2l0aCBvciB3aXRob3V0IGEgY3VzdG9tIGNsYXNzKSBjYW4gYWxzbyBiZSBhZGRlZCB0b1xuXHRcdCAqIGFpZCBzdHlsaW5nLiBUaGUgZm9sbG93IHN5bnRheCBpcyB1c2VkOlxuXHRcdCAqICAgPHVsPlxuXHRcdCAqICAgICA8bGk+VGhlIGZvbGxvd2luZyBvcHRpb25zIGFyZSBhbGxvd2VkOlxuXHRcdCAqICAgICAgIDx1bD5cblx0XHQgKiAgICAgICAgIDxsaT4nbCcgLSBMZW5ndGggY2hhbmdpbmc8L2xpPlxuXHRcdCAqICAgICAgICAgPGxpPidmJyAtIEZpbHRlcmluZyBpbnB1dDwvbGk+XG5cdFx0ICogICAgICAgICA8bGk+J3QnIC0gVGhlIHRhYmxlITwvbGk+XG5cdFx0ICogICAgICAgICA8bGk+J2knIC0gSW5mb3JtYXRpb248L2xpPlxuXHRcdCAqICAgICAgICAgPGxpPidwJyAtIFBhZ2luYXRpb248L2xpPlxuXHRcdCAqICAgICAgICAgPGxpPidyJyAtIHBSb2Nlc3Npbmc8L2xpPlxuXHRcdCAqICAgICAgIDwvdWw+XG5cdFx0ICogICAgIDwvbGk+XG5cdFx0ICogICAgIDxsaT5UaGUgZm9sbG93aW5nIGNvbnN0YW50cyBhcmUgYWxsb3dlZDpcblx0XHQgKiAgICAgICA8dWw+XG5cdFx0ICogICAgICAgICA8bGk+J0gnIC0galF1ZXJ5VUkgdGhlbWUgXCJoZWFkZXJcIiBjbGFzc2VzICgnZmctdG9vbGJhciB1aS13aWRnZXQtaGVhZGVyIHVpLWNvcm5lci10bCB1aS1jb3JuZXItdHIgdWktaGVscGVyLWNsZWFyZml4Jyk8L2xpPlxuXHRcdCAqICAgICAgICAgPGxpPidGJyAtIGpRdWVyeVVJIHRoZW1lIFwiZm9vdGVyXCIgY2xhc3NlcyAoJ2ZnLXRvb2xiYXIgdWktd2lkZ2V0LWhlYWRlciB1aS1jb3JuZXItYmwgdWktY29ybmVyLWJyIHVpLWhlbHBlci1jbGVhcmZpeCcpPC9saT5cblx0XHQgKiAgICAgICA8L3VsPlxuXHRcdCAqICAgICA8L2xpPlxuXHRcdCAqICAgICA8bGk+VGhlIGZvbGxvd2luZyBzeW50YXggaXMgZXhwZWN0ZWQ6XG5cdFx0ICogICAgICAgPHVsPlxuXHRcdCAqICAgICAgICAgPGxpPicmbHQ7JyBhbmQgJyZndDsnIC0gZGl2IGVsZW1lbnRzPC9saT5cblx0XHQgKiAgICAgICAgIDxsaT4nJmx0O1wiY2xhc3NcIiBhbmQgJyZndDsnIC0gZGl2IHdpdGggYSBjbGFzczwvbGk+XG5cdFx0ICogICAgICAgICA8bGk+JyZsdDtcIiNpZFwiIGFuZCAnJmd0OycgLSBkaXYgd2l0aCBhbiBJRDwvbGk+XG5cdFx0ICogICAgICAgPC91bD5cblx0XHQgKiAgICAgPC9saT5cblx0XHQgKiAgICAgPGxpPkV4YW1wbGVzOlxuXHRcdCAqICAgICAgIDx1bD5cblx0XHQgKiAgICAgICAgIDxsaT4nJmx0O1wid3JhcHBlclwiZmxpcHQmZ3Q7JzwvbGk+XG5cdFx0ICogICAgICAgICA8bGk+JyZsdDtsZiZsdDt0Jmd0O2lwJmd0Oyc8L2xpPlxuXHRcdCAqICAgICAgIDwvdWw+XG5cdFx0ICogICAgIDwvbGk+XG5cdFx0ICogICA8L3VsPlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgbGZydGlwIDxpPih3aGVuIGBqUXVlcnlVSWAgaXMgZmFsc2UpPC9pPiA8Yj5vcjwvYj5cblx0XHQgKiAgICA8XCJIXCJsZnI+dDxcIkZcImlwPiA8aT4od2hlbiBgalF1ZXJ5VUlgIGlzIHRydWUpPC9pPlxuXHRcdCAqXG5cdFx0ICogIEBkdG9wdCBPcHRpb25zXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5kb21cblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiZG9tXCI6ICcmbHQ7XCJ0b3BcImkmZ3Q7cnQmbHQ7XCJib3R0b21cImZscCZndDsmbHQ7XCJjbGVhclwiJmd0Oydcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJzRG9tXCI6IFwibGZydGlwXCIsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBTZWFyY2ggZGVsYXkgb3B0aW9uLiBUaGlzIHdpbGwgdGhyb3R0bGUgZnVsbCB0YWJsZSBzZWFyY2hlcyB0aGF0IHVzZSB0aGVcblx0XHQgKiBEYXRhVGFibGVzIHByb3ZpZGVkIHNlYXJjaCBpbnB1dCBlbGVtZW50IChpdCBkb2VzIG5vdCBlZmZlY3QgY2FsbHMgdG9cblx0XHQgKiBgZHQtYXBpIHNlYXJjaCgpYCwgcHJvdmlkaW5nIGEgZGVsYXkgYmVmb3JlIHRoZSBzZWFyY2ggaXMgbWFkZS5cblx0XHQgKiAgQHR5cGUgaW50ZWdlclxuXHRcdCAqICBAZGVmYXVsdCAwXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvbnNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNlYXJjaERlbGF5XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcInNlYXJjaERlbGF5XCI6IDIwMFxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKVxuXHRcdCAqL1xuXHRcdFwic2VhcmNoRGVsYXlcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIERhdGFUYWJsZXMgZmVhdHVyZXMgc2l4IGRpZmZlcmVudCBidWlsdC1pbiBvcHRpb25zIGZvciB0aGUgYnV0dG9ucyB0b1xuXHRcdCAqIGRpc3BsYXkgZm9yIHBhZ2luYXRpb24gY29udHJvbDpcblx0XHQgKlxuXHRcdCAqICogYG51bWJlcnNgIC0gUGFnZSBudW1iZXIgYnV0dG9ucyBvbmx5XG5cdFx0ICogKiBgc2ltcGxlYCAtICdQcmV2aW91cycgYW5kICdOZXh0JyBidXR0b25zIG9ubHlcblx0XHQgKiAqICdzaW1wbGVfbnVtYmVyc2AgLSAnUHJldmlvdXMnIGFuZCAnTmV4dCcgYnV0dG9ucywgcGx1cyBwYWdlIG51bWJlcnNcblx0XHQgKiAqIGBmdWxsYCAtICdGaXJzdCcsICdQcmV2aW91cycsICdOZXh0JyBhbmQgJ0xhc3QnIGJ1dHRvbnNcblx0XHQgKiAqIGBmdWxsX251bWJlcnNgIC0gJ0ZpcnN0JywgJ1ByZXZpb3VzJywgJ05leHQnIGFuZCAnTGFzdCcgYnV0dG9ucywgcGx1cyBwYWdlIG51bWJlcnNcblx0XHQgKiAqIGBmaXJzdF9sYXN0X251bWJlcnNgIC0gJ0ZpcnN0JyBhbmQgJ0xhc3QnIGJ1dHRvbnMsIHBsdXMgcGFnZSBudW1iZXJzXG5cdFx0ICogIFxuXHRcdCAqIEZ1cnRoZXIgbWV0aG9kcyBjYW4gYmUgYWRkZWQgdXNpbmcge0BsaW5rIERhdGFUYWJsZS5leHQub1BhZ2luYXRpb259LlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgc2ltcGxlX251bWJlcnNcblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgT3B0aW9uc1xuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMucGFnaW5nVHlwZVxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJwYWdpbmdUeXBlXCI6IFwiZnVsbF9udW1iZXJzXCJcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9IClcblx0XHQgKi9cblx0XHRcInNQYWdpbmF0aW9uVHlwZVwiOiBcInNpbXBsZV9udW1iZXJzXCIsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBFbmFibGUgaG9yaXpvbnRhbCBzY3JvbGxpbmcuIFdoZW4gYSB0YWJsZSBpcyB0b28gd2lkZSB0byBmaXQgaW50byBhXG5cdFx0ICogY2VydGFpbiBsYXlvdXQsIG9yIHlvdSBoYXZlIGEgbGFyZ2UgbnVtYmVyIG9mIGNvbHVtbnMgaW4gdGhlIHRhYmxlLCB5b3Vcblx0XHQgKiBjYW4gZW5hYmxlIHgtc2Nyb2xsaW5nIHRvIHNob3cgdGhlIHRhYmxlIGluIGEgdmlld3BvcnQsIHdoaWNoIGNhbiBiZVxuXHRcdCAqIHNjcm9sbGVkLiBUaGlzIHByb3BlcnR5IGNhbiBiZSBgdHJ1ZWAgd2hpY2ggd2lsbCBhbGxvdyB0aGUgdGFibGUgdG9cblx0XHQgKiBzY3JvbGwgaG9yaXpvbnRhbGx5IHdoZW4gbmVlZGVkLCBvciBhbnkgQ1NTIHVuaXQsIG9yIGEgbnVtYmVyIChpbiB3aGljaFxuXHRcdCAqIGNhc2UgaXQgd2lsbCBiZSB0cmVhdGVkIGFzIGEgcGl4ZWwgbWVhc3VyZW1lbnQpLiBTZXR0aW5nIGFzIHNpbXBseSBgdHJ1ZWBcblx0XHQgKiBpcyByZWNvbW1lbmRlZC5cblx0XHQgKiAgQHR5cGUgYm9vbGVhbnxzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgPGk+Ymxhbmsgc3RyaW5nIC0gaS5lLiBkaXNhYmxlZDwvaT5cblx0XHQgKlxuXHRcdCAqICBAZHRvcHQgRmVhdHVyZXNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNjcm9sbFhcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwic2Nyb2xsWFwiOiB0cnVlLFxuXHRcdCAqICAgICAgICBcInNjcm9sbENvbGxhcHNlXCI6IHRydWVcblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJzU2Nyb2xsWFwiOiBcIlwiLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogVGhpcyBwcm9wZXJ0eSBjYW4gYmUgdXNlZCB0byBmb3JjZSBhIERhdGFUYWJsZSB0byB1c2UgbW9yZSB3aWR0aCB0aGFuIGl0XG5cdFx0ICogbWlnaHQgb3RoZXJ3aXNlIGRvIHdoZW4geC1zY3JvbGxpbmcgaXMgZW5hYmxlZC4gRm9yIGV4YW1wbGUgaWYgeW91IGhhdmUgYVxuXHRcdCAqIHRhYmxlIHdoaWNoIHJlcXVpcmVzIHRvIGJlIHdlbGwgc3BhY2VkLCB0aGlzIHBhcmFtZXRlciBpcyB1c2VmdWwgZm9yXG5cdFx0ICogXCJvdmVyLXNpemluZ1wiIHRoZSB0YWJsZSwgYW5kIHRodXMgZm9yY2luZyBzY3JvbGxpbmcuIFRoaXMgcHJvcGVydHkgY2FuIGJ5XG5cdFx0ICogYW55IENTUyB1bml0LCBvciBhIG51bWJlciAoaW4gd2hpY2ggY2FzZSBpdCB3aWxsIGJlIHRyZWF0ZWQgYXMgYSBwaXhlbFxuXHRcdCAqIG1lYXN1cmVtZW50KS5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IDxpPmJsYW5rIHN0cmluZyAtIGkuZS4gZGlzYWJsZWQ8L2k+XG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvbnNcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnNjcm9sbFhJbm5lclxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJzY3JvbGxYXCI6IFwiMTAwJVwiLFxuXHRcdCAqICAgICAgICBcInNjcm9sbFhJbm5lclwiOiBcIjExMCVcIlxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcInNTY3JvbGxYSW5uZXJcIjogXCJcIixcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEVuYWJsZSB2ZXJ0aWNhbCBzY3JvbGxpbmcuIFZlcnRpY2FsIHNjcm9sbGluZyB3aWxsIGNvbnN0cmFpbiB0aGUgRGF0YVRhYmxlXG5cdFx0ICogdG8gdGhlIGdpdmVuIGhlaWdodCwgYW5kIGVuYWJsZSBzY3JvbGxpbmcgZm9yIGFueSBkYXRhIHdoaWNoIG92ZXJmbG93cyB0aGVcblx0XHQgKiBjdXJyZW50IHZpZXdwb3J0LiBUaGlzIGNhbiBiZSB1c2VkIGFzIGFuIGFsdGVybmF0aXZlIHRvIHBhZ2luZyB0byBkaXNwbGF5XG5cdFx0ICogYSBsb3Qgb2YgZGF0YSBpbiBhIHNtYWxsIGFyZWEgKGFsdGhvdWdoIHBhZ2luZyBhbmQgc2Nyb2xsaW5nIGNhbiBib3RoIGJlXG5cdFx0ICogZW5hYmxlZCBhdCB0aGUgc2FtZSB0aW1lKS4gVGhpcyBwcm9wZXJ0eSBjYW4gYmUgYW55IENTUyB1bml0LCBvciBhIG51bWJlclxuXHRcdCAqIChpbiB3aGljaCBjYXNlIGl0IHdpbGwgYmUgdHJlYXRlZCBhcyBhIHBpeGVsIG1lYXN1cmVtZW50KS5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IDxpPmJsYW5rIHN0cmluZyAtIGkuZS4gZGlzYWJsZWQ8L2k+XG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IEZlYXR1cmVzXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zY3JvbGxZXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcInNjcm9sbFlcIjogXCIyMDBweFwiLFxuXHRcdCAqICAgICAgICBcInBhZ2luYXRlXCI6IGZhbHNlXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwic1Njcm9sbFlcIjogXCJcIixcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIF9fRGVwcmVjYXRlZF9fIFRoZSBmdW5jdGlvbmFsaXR5IHByb3ZpZGVkIGJ5IHRoaXMgcGFyYW1ldGVyIGhhcyBub3cgYmVlblxuXHRcdCAqIHN1cGVyc2VkZWQgYnkgdGhhdCBwcm92aWRlZCB0aHJvdWdoIGBhamF4YCwgd2hpY2ggc2hvdWxkIGJlIHVzZWQgaW5zdGVhZC5cblx0XHQgKlxuXHRcdCAqIFNldCB0aGUgSFRUUCBtZXRob2QgdGhhdCBpcyB1c2VkIHRvIG1ha2UgdGhlIEFqYXggY2FsbCBmb3Igc2VydmVyLXNpZGVcblx0XHQgKiBwcm9jZXNzaW5nIG9yIEFqYXggc291cmNlZCBkYXRhLlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgR0VUXG5cdFx0ICpcblx0XHQgKiAgQGR0b3B0IE9wdGlvbnNcblx0XHQgKiAgQGR0b3B0IFNlcnZlci1zaWRlXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5zZXJ2ZXJNZXRob2Rcblx0XHQgKlxuXHRcdCAqICBAZGVwcmVjYXRlZCAxLjEwLiBQbGVhc2UgdXNlIGBhamF4YCBmb3IgdGhpcyBmdW5jdGlvbmFsaXR5IG5vdy5cblx0XHQgKi9cblx0XHRcInNTZXJ2ZXJNZXRob2RcIjogXCJHRVRcIixcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIERhdGFUYWJsZXMgbWFrZXMgdXNlIG9mIHJlbmRlcmVycyB3aGVuIGRpc3BsYXlpbmcgSFRNTCBlbGVtZW50cyBmb3Jcblx0XHQgKiBhIHRhYmxlLiBUaGVzZSByZW5kZXJlcnMgY2FuIGJlIGFkZGVkIG9yIG1vZGlmaWVkIGJ5IHBsdWctaW5zIHRvXG5cdFx0ICogZ2VuZXJhdGUgc3VpdGFibGUgbWFyay11cCBmb3IgYSBzaXRlLiBGb3IgZXhhbXBsZSB0aGUgQm9vdHN0cmFwXG5cdFx0ICogaW50ZWdyYXRpb24gcGx1Zy1pbiBmb3IgRGF0YVRhYmxlcyB1c2VzIGEgcGFnaW5nIGJ1dHRvbiByZW5kZXJlciB0b1xuXHRcdCAqIGRpc3BsYXkgcGFnaW5hdGlvbiBidXR0b25zIGluIHRoZSBtYXJrLXVwIHJlcXVpcmVkIGJ5IEJvb3RzdHJhcC5cblx0XHQgKlxuXHRcdCAqIEZvciBmdXJ0aGVyIGluZm9ybWF0aW9uIGFib3V0IHRoZSByZW5kZXJlcnMgYXZhaWxhYmxlIHNlZVxuXHRcdCAqIERhdGFUYWJsZS5leHQucmVuZGVyZXJcblx0XHQgKiAgQHR5cGUgc3RyaW5nfG9iamVjdFxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICpcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnJlbmRlcmVyXG5cdFx0ICpcblx0XHQgKi9cblx0XHRcInJlbmRlcmVyXCI6IG51bGwsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBTZXQgdGhlIGRhdGEgcHJvcGVydHkgbmFtZSB0aGF0IERhdGFUYWJsZXMgc2hvdWxkIHVzZSB0byBnZXQgYSByb3cncyBpZFxuXHRcdCAqIHRvIHNldCBhcyB0aGUgYGlkYCBwcm9wZXJ0eSBpbiB0aGUgbm9kZS5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IERUX1Jvd0lkXG5cdFx0ICpcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLnJvd0lkXG5cdFx0ICovXG5cdFx0XCJyb3dJZFwiOiBcIkRUX1Jvd0lkXCJcblx0fTtcblx0XG5cdF9mbkh1bmdhcmlhbk1hcCggRGF0YVRhYmxlLmRlZmF1bHRzICk7XG5cdFxuXHRcblx0XG5cdC8qXG5cdCAqIERldmVsb3BlciBub3RlIC0gU2VlIG5vdGUgaW4gbW9kZWwuZGVmYXVsdHMuanMgYWJvdXQgdGhlIHVzZSBvZiBIdW5nYXJpYW5cblx0ICogbm90YXRpb24gYW5kIGNhbWVsIGNhc2UuXG5cdCAqL1xuXHRcblx0LyoqXG5cdCAqIENvbHVtbiBvcHRpb25zIHRoYXQgY2FuIGJlIGdpdmVuIHRvIERhdGFUYWJsZXMgYXQgaW5pdGlhbGlzYXRpb24gdGltZS5cblx0ICogIEBuYW1lc3BhY2Vcblx0ICovXG5cdERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4gPSB7XG5cdFx0LyoqXG5cdFx0ICogRGVmaW5lIHdoaWNoIGNvbHVtbihzKSBhbiBvcmRlciB3aWxsIG9jY3VyIG9uIGZvciB0aGlzIGNvbHVtbi4gVGhpc1xuXHRcdCAqIGFsbG93cyBhIGNvbHVtbidzIG9yZGVyaW5nIHRvIHRha2UgbXVsdGlwbGUgY29sdW1ucyBpbnRvIGFjY291bnQgd2hlblxuXHRcdCAqIGRvaW5nIGEgc29ydCBvciB1c2UgdGhlIGRhdGEgZnJvbSBhIGRpZmZlcmVudCBjb2x1bW4uIEZvciBleGFtcGxlIGZpcnN0XG5cdFx0ICogbmFtZSAvIGxhc3QgbmFtZSBjb2x1bW5zIG1ha2Ugc2Vuc2UgdG8gZG8gYSBtdWx0aS1jb2x1bW4gc29ydCBvdmVyIHRoZVxuXHRcdCAqIHR3byBjb2x1bW5zLlxuXHRcdCAqICBAdHlwZSBhcnJheXxpbnRcblx0XHQgKiAgQGRlZmF1bHQgbnVsbCA8aT5UYWtlcyB0aGUgdmFsdWUgb2YgdGhlIGNvbHVtbiBpbmRleCBhdXRvbWF0aWNhbGx5PC9pPlxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4ub3JkZXJEYXRhXG5cdFx0ICogIEBkdG9wdCBDb2x1bW5zXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2luZyBgY29sdW1uRGVmc2Bcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImNvbHVtbkRlZnNcIjogW1xuXHRcdCAqICAgICAgICAgIHsgXCJvcmRlckRhdGFcIjogWyAwLCAxIF0sIFwidGFyZ2V0c1wiOiBbIDAgXSB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJvcmRlckRhdGFcIjogWyAxLCAwIF0sIFwidGFyZ2V0c1wiOiBbIDEgXSB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJvcmRlckRhdGFcIjogMiwgXCJ0YXJnZXRzXCI6IFsgMiBdIH1cblx0XHQgKiAgICAgICAgXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFVzaW5nIGBjb2x1bW5zYFxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiY29sdW1uc1wiOiBbXG5cdFx0ICogICAgICAgICAgeyBcIm9yZGVyRGF0YVwiOiBbIDAsIDEgXSB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJvcmRlckRhdGFcIjogWyAxLCAwIF0gfSxcblx0XHQgKiAgICAgICAgICB7IFwib3JkZXJEYXRhXCI6IDIgfSxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGxcblx0XHQgKiAgICAgICAgXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImFEYXRhU29ydFwiOiBudWxsLFxuXHRcdFwiaURhdGFTb3J0XCI6IC0xLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogWW91IGNhbiBjb250cm9sIHRoZSBkZWZhdWx0IG9yZGVyaW5nIGRpcmVjdGlvbiwgYW5kIGV2ZW4gYWx0ZXIgdGhlXG5cdFx0ICogYmVoYXZpb3VyIG9mIHRoZSBzb3J0IGhhbmRsZXIgKGkuZS4gb25seSBhbGxvdyBhc2NlbmRpbmcgb3JkZXJpbmcgZXRjKVxuXHRcdCAqIHVzaW5nIHRoaXMgcGFyYW1ldGVyLlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbICdhc2MnLCAnZGVzYycgXVxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4ub3JkZXJTZXF1ZW5jZVxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwib3JkZXJTZXF1ZW5jZVwiOiBbIFwiYXNjXCIgXSwgXCJ0YXJnZXRzXCI6IFsgMSBdIH0sXG5cdFx0ICogICAgICAgICAgeyBcIm9yZGVyU2VxdWVuY2VcIjogWyBcImRlc2NcIiwgXCJhc2NcIiwgXCJhc2NcIiBdLCBcInRhcmdldHNcIjogWyAyIF0gfSxcblx0XHQgKiAgICAgICAgICB7IFwib3JkZXJTZXF1ZW5jZVwiOiBbIFwiZGVzY1wiIF0sIFwidGFyZ2V0c1wiOiBbIDMgXSB9XG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2luZyBgY29sdW1uc2Bcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImNvbHVtbnNcIjogW1xuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgeyBcIm9yZGVyU2VxdWVuY2VcIjogWyBcImFzY1wiIF0gfSxcblx0XHQgKiAgICAgICAgICB7IFwib3JkZXJTZXF1ZW5jZVwiOiBbIFwiZGVzY1wiLCBcImFzY1wiLCBcImFzY1wiIF0gfSxcblx0XHQgKiAgICAgICAgICB7IFwib3JkZXJTZXF1ZW5jZVwiOiBbIFwiZGVzY1wiIF0gfSxcblx0XHQgKiAgICAgICAgICBudWxsXG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJhc1NvcnRpbmdcIjogWyAnYXNjJywgJ2Rlc2MnIF0sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBFbmFibGUgb3IgZGlzYWJsZSBmaWx0ZXJpbmcgb24gdGhlIGRhdGEgaW4gdGhpcyBjb2x1bW4uXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgdHJ1ZVxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4uc2VhcmNoYWJsZVxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwic2VhcmNoYWJsZVwiOiBmYWxzZSwgXCJ0YXJnZXRzXCI6IFsgMCBdIH1cblx0XHQgKiAgICAgICAgXSB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5zXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwic2VhcmNoYWJsZVwiOiBmYWxzZSB9LFxuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGxcblx0XHQgKiAgICAgICAgXSB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiYlNlYXJjaGFibGVcIjogdHJ1ZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEVuYWJsZSBvciBkaXNhYmxlIG9yZGVyaW5nIG9uIHRoaXMgY29sdW1uLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IHRydWVcblx0XHQgKlxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLm9yZGVyYWJsZVxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwib3JkZXJhYmxlXCI6IGZhbHNlLCBcInRhcmdldHNcIjogWyAwIF0gfVxuXHRcdCAqICAgICAgICBdIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2luZyBgY29sdW1uc2Bcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImNvbHVtbnNcIjogW1xuXHRcdCAqICAgICAgICAgIHsgXCJvcmRlcmFibGVcIjogZmFsc2UgfSxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsXG5cdFx0ICogICAgICAgIF0gfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcImJTb3J0YWJsZVwiOiB0cnVlLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogRW5hYmxlIG9yIGRpc2FibGUgdGhlIGRpc3BsYXkgb2YgdGhpcyBjb2x1bW4uXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgdHJ1ZVxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4udmlzaWJsZVxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwidmlzaWJsZVwiOiBmYWxzZSwgXCJ0YXJnZXRzXCI6IFsgMCBdIH1cblx0XHQgKiAgICAgICAgXSB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5zXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwidmlzaWJsZVwiOiBmYWxzZSB9LFxuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGxcblx0XHQgKiAgICAgICAgXSB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiYlZpc2libGVcIjogdHJ1ZSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIERldmVsb3BlciBkZWZpbmFibGUgZnVuY3Rpb24gdGhhdCBpcyBjYWxsZWQgd2hlbmV2ZXIgYSBjZWxsIGlzIGNyZWF0ZWQgKEFqYXggc291cmNlLFxuXHRcdCAqIGV0Yykgb3IgcHJvY2Vzc2VkIGZvciBpbnB1dCAoRE9NIHNvdXJjZSkuIFRoaXMgY2FuIGJlIHVzZWQgYXMgYSBjb21wbGltZW50IHRvIG1SZW5kZXJcblx0XHQgKiBhbGxvd2luZyB5b3UgdG8gbW9kaWZ5IHRoZSBET00gZWxlbWVudCAoYWRkIGJhY2tncm91bmQgY29sb3VyIGZvciBleGFtcGxlKSB3aGVuIHRoZVxuXHRcdCAqIGVsZW1lbnQgaXMgYXZhaWxhYmxlLlxuXHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdCAqICBAcGFyYW0ge2VsZW1lbnR9IHRkIFRoZSBURCBub2RlIHRoYXQgaGFzIGJlZW4gY3JlYXRlZFxuXHRcdCAqICBAcGFyYW0geyp9IGNlbGxEYXRhIFRoZSBEYXRhIGZvciB0aGUgY2VsbFxuXHRcdCAqICBAcGFyYW0ge2FycmF5fG9iamVjdH0gcm93RGF0YSBUaGUgZGF0YSBmb3IgdGhlIHdob2xlIHJvd1xuXHRcdCAqICBAcGFyYW0ge2ludH0gcm93IFRoZSByb3cgaW5kZXggZm9yIHRoZSBhb0RhdGEgZGF0YSBzdG9yZVxuXHRcdCAqICBAcGFyYW0ge2ludH0gY29sIFRoZSBjb2x1bW4gaW5kZXggZm9yIGFvQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4uY3JlYXRlZENlbGxcblx0XHQgKiAgQGR0b3B0IENvbHVtbnNcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiY29sdW1uRGVmc1wiOiBbIHtcblx0XHQgKiAgICAgICAgICBcInRhcmdldHNcIjogWzNdLFxuXHRcdCAqICAgICAgICAgIFwiY3JlYXRlZENlbGxcIjogZnVuY3Rpb24gKHRkLCBjZWxsRGF0YSwgcm93RGF0YSwgcm93LCBjb2wpIHtcblx0XHQgKiAgICAgICAgICAgIGlmICggY2VsbERhdGEgPT0gXCIxLjdcIiApIHtcblx0XHQgKiAgICAgICAgICAgICAgJCh0ZCkuY3NzKCdjb2xvcicsICdibHVlJylcblx0XHQgKiAgICAgICAgICAgIH1cblx0XHQgKiAgICAgICAgICB9XG5cdFx0ICogICAgICAgIH0gXVxuXHRcdCAqICAgICAgfSk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwiZm5DcmVhdGVkQ2VsbFwiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogVGhpcyBwYXJhbWV0ZXIgaGFzIGJlZW4gcmVwbGFjZWQgYnkgYGRhdGFgIGluIERhdGFUYWJsZXMgdG8gZW5zdXJlIG5hbWluZ1xuXHRcdCAqIGNvbnNpc3RlbmN5LiBgZGF0YVByb3BgIGNhbiBzdGlsbCBiZSB1c2VkLCBhcyB0aGVyZSBpcyBiYWNrd2FyZHNcblx0XHQgKiBjb21wYXRpYmlsaXR5IGluIERhdGFUYWJsZXMgZm9yIHRoaXMgb3B0aW9uLCBidXQgaXQgaXMgc3Ryb25nbHlcblx0XHQgKiByZWNvbW1lbmRlZCB0aGF0IHlvdSB1c2UgYGRhdGFgIGluIHByZWZlcmVuY2UgdG8gYGRhdGFQcm9wYC5cblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbi5kYXRhUHJvcFxuXHRcdCAqL1xuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogVGhpcyBwcm9wZXJ0eSBjYW4gYmUgdXNlZCB0byByZWFkIGRhdGEgZnJvbSBhbnkgZGF0YSBzb3VyY2UgcHJvcGVydHksXG5cdFx0ICogaW5jbHVkaW5nIGRlZXBseSBuZXN0ZWQgb2JqZWN0cyAvIHByb3BlcnRpZXMuIGBkYXRhYCBjYW4gYmUgZ2l2ZW4gaW4gYVxuXHRcdCAqIG51bWJlciBvZiBkaWZmZXJlbnQgd2F5cyB3aGljaCBlZmZlY3QgaXRzIGJlaGF2aW91cjpcblx0XHQgKlxuXHRcdCAqICogYGludGVnZXJgIC0gdHJlYXRlZCBhcyBhbiBhcnJheSBpbmRleCBmb3IgdGhlIGRhdGEgc291cmNlLiBUaGlzIGlzIHRoZVxuXHRcdCAqICAgZGVmYXVsdCB0aGF0IERhdGFUYWJsZXMgdXNlcyAoaW5jcmVtZW50YWxseSBpbmNyZWFzZWQgZm9yIGVhY2ggY29sdW1uKS5cblx0XHQgKiAqIGBzdHJpbmdgIC0gcmVhZCBhbiBvYmplY3QgcHJvcGVydHkgZnJvbSB0aGUgZGF0YSBzb3VyY2UuIFRoZXJlIGFyZVxuXHRcdCAqICAgdGhyZWUgJ3NwZWNpYWwnIG9wdGlvbnMgdGhhdCBjYW4gYmUgdXNlZCBpbiB0aGUgc3RyaW5nIHRvIGFsdGVyIGhvd1xuXHRcdCAqICAgRGF0YVRhYmxlcyByZWFkcyB0aGUgZGF0YSBmcm9tIHRoZSBzb3VyY2Ugb2JqZWN0OlxuXHRcdCAqICAgICogYC5gIC0gRG90dGVkIEphdmFzY3JpcHQgbm90YXRpb24uIEp1c3QgYXMgeW91IHVzZSBhIGAuYCBpblxuXHRcdCAqICAgICAgSmF2YXNjcmlwdCB0byByZWFkIGZyb20gbmVzdGVkIG9iamVjdHMsIHNvIHRvIGNhbiB0aGUgb3B0aW9uc1xuXHRcdCAqICAgICAgc3BlY2lmaWVkIGluIGBkYXRhYC4gRm9yIGV4YW1wbGU6IGBicm93c2VyLnZlcnNpb25gIG9yXG5cdFx0ICogICAgICBgYnJvd3Nlci5uYW1lYC4gSWYgeW91ciBvYmplY3QgcGFyYW1ldGVyIG5hbWUgY29udGFpbnMgYSBwZXJpb2QsIHVzZVxuXHRcdCAqICAgICAgYFxcXFxgIHRvIGVzY2FwZSBpdCAtIGkuZS4gYGZpcnN0XFxcXC5uYW1lYC5cblx0XHQgKiAgICAqIGBbXWAgLSBBcnJheSBub3RhdGlvbi4gRGF0YVRhYmxlcyBjYW4gYXV0b21hdGljYWxseSBjb21iaW5lIGRhdGFcblx0XHQgKiAgICAgIGZyb20gYW5kIGFycmF5IHNvdXJjZSwgam9pbmluZyB0aGUgZGF0YSB3aXRoIHRoZSBjaGFyYWN0ZXJzIHByb3ZpZGVkXG5cdFx0ICogICAgICBiZXR3ZWVuIHRoZSB0d28gYnJhY2tldHMuIEZvciBleGFtcGxlOiBgbmFtZVssIF1gIHdvdWxkIHByb3ZpZGUgYVxuXHRcdCAqICAgICAgY29tbWEtc3BhY2Ugc2VwYXJhdGVkIGxpc3QgZnJvbSB0aGUgc291cmNlIGFycmF5LiBJZiBubyBjaGFyYWN0ZXJzXG5cdFx0ICogICAgICBhcmUgcHJvdmlkZWQgYmV0d2VlbiB0aGUgYnJhY2tldHMsIHRoZSBvcmlnaW5hbCBhcnJheSBzb3VyY2UgaXNcblx0XHQgKiAgICAgIHJldHVybmVkLlxuXHRcdCAqICAgICogYCgpYCAtIEZ1bmN0aW9uIG5vdGF0aW9uLiBBZGRpbmcgYCgpYCB0byB0aGUgZW5kIG9mIGEgcGFyYW1ldGVyIHdpbGxcblx0XHQgKiAgICAgIGV4ZWN1dGUgYSBmdW5jdGlvbiBvZiB0aGUgbmFtZSBnaXZlbi4gRm9yIGV4YW1wbGU6IGBicm93c2VyKClgIGZvciBhXG5cdFx0ICogICAgICBzaW1wbGUgZnVuY3Rpb24gb24gdGhlIGRhdGEgc291cmNlLCBgYnJvd3Nlci52ZXJzaW9uKClgIGZvciBhXG5cdFx0ICogICAgICBmdW5jdGlvbiBpbiBhIG5lc3RlZCBwcm9wZXJ0eSBvciBldmVuIGBicm93c2VyKCkudmVyc2lvbmAgdG8gZ2V0IGFuXG5cdFx0ICogICAgICBvYmplY3QgcHJvcGVydHkgaWYgdGhlIGZ1bmN0aW9uIGNhbGxlZCByZXR1cm5zIGFuIG9iamVjdC4gTm90ZSB0aGF0XG5cdFx0ICogICAgICBmdW5jdGlvbiBub3RhdGlvbiBpcyByZWNvbW1lbmRlZCBmb3IgdXNlIGluIGByZW5kZXJgIHJhdGhlciB0aGFuXG5cdFx0ICogICAgICBgZGF0YWAgYXMgaXQgaXMgbXVjaCBzaW1wbGVyIHRvIHVzZSBhcyBhIHJlbmRlcmVyLlxuXHRcdCAqICogYG51bGxgIC0gdXNlIHRoZSBvcmlnaW5hbCBkYXRhIHNvdXJjZSBmb3IgdGhlIHJvdyByYXRoZXIgdGhhbiBwbHVja2luZ1xuXHRcdCAqICAgZGF0YSBkaXJlY3RseSBmcm9tIGl0LiBUaGlzIGFjdGlvbiBoYXMgZWZmZWN0cyBvbiB0d28gb3RoZXJcblx0XHQgKiAgIGluaXRpYWxpc2F0aW9uIG9wdGlvbnM6XG5cdFx0ICogICAgKiBgZGVmYXVsdENvbnRlbnRgIC0gV2hlbiBudWxsIGlzIGdpdmVuIGFzIHRoZSBgZGF0YWAgb3B0aW9uIGFuZFxuXHRcdCAqICAgICAgYGRlZmF1bHRDb250ZW50YCBpcyBzcGVjaWZpZWQgZm9yIHRoZSBjb2x1bW4sIHRoZSB2YWx1ZSBkZWZpbmVkIGJ5XG5cdFx0ICogICAgICBgZGVmYXVsdENvbnRlbnRgIHdpbGwgYmUgdXNlZCBmb3IgdGhlIGNlbGwuXG5cdFx0ICogICAgKiBgcmVuZGVyYCAtIFdoZW4gbnVsbCBpcyB1c2VkIGZvciB0aGUgYGRhdGFgIG9wdGlvbiBhbmQgdGhlIGByZW5kZXJgXG5cdFx0ICogICAgICBvcHRpb24gaXMgc3BlY2lmaWVkIGZvciB0aGUgY29sdW1uLCB0aGUgd2hvbGUgZGF0YSBzb3VyY2UgZm9yIHRoZVxuXHRcdCAqICAgICAgcm93IGlzIHVzZWQgZm9yIHRoZSByZW5kZXJlci5cblx0XHQgKiAqIGBmdW5jdGlvbmAgLSB0aGUgZnVuY3Rpb24gZ2l2ZW4gd2lsbCBiZSBleGVjdXRlZCB3aGVuZXZlciBEYXRhVGFibGVzXG5cdFx0ICogICBuZWVkcyB0byBzZXQgb3IgZ2V0IHRoZSBkYXRhIGZvciBhIGNlbGwgaW4gdGhlIGNvbHVtbi4gVGhlIGZ1bmN0aW9uXG5cdFx0ICogICB0YWtlcyB0aHJlZSBwYXJhbWV0ZXJzOlxuXHRcdCAqICAgICogUGFyYW1ldGVyczpcblx0XHQgKiAgICAgICogYHthcnJheXxvYmplY3R9YCBUaGUgZGF0YSBzb3VyY2UgZm9yIHRoZSByb3dcblx0XHQgKiAgICAgICogYHtzdHJpbmd9YCBUaGUgdHlwZSBjYWxsIGRhdGEgcmVxdWVzdGVkIC0gdGhpcyB3aWxsIGJlICdzZXQnIHdoZW5cblx0XHQgKiAgICAgICAgc2V0dGluZyBkYXRhIG9yICdmaWx0ZXInLCAnZGlzcGxheScsICd0eXBlJywgJ3NvcnQnIG9yIHVuZGVmaW5lZFxuXHRcdCAqICAgICAgICB3aGVuIGdhdGhlcmluZyBkYXRhLiBOb3RlIHRoYXQgd2hlbiBgdW5kZWZpbmVkYCBpcyBnaXZlbiBmb3IgdGhlXG5cdFx0ICogICAgICAgIHR5cGUgRGF0YVRhYmxlcyBleHBlY3RzIHRvIGdldCB0aGUgcmF3IGRhdGEgZm9yIHRoZSBvYmplY3QgYmFjazxcblx0XHQgKiAgICAgICogYHsqfWAgRGF0YSB0byBzZXQgd2hlbiB0aGUgc2Vjb25kIHBhcmFtZXRlciBpcyAnc2V0Jy5cblx0XHQgKiAgICAqIFJldHVybjpcblx0XHQgKiAgICAgICogVGhlIHJldHVybiB2YWx1ZSBmcm9tIHRoZSBmdW5jdGlvbiBpcyBub3QgcmVxdWlyZWQgd2hlbiAnc2V0JyBpc1xuXHRcdCAqICAgICAgICB0aGUgdHlwZSBvZiBjYWxsLCBidXQgb3RoZXJ3aXNlIHRoZSByZXR1cm4gaXMgd2hhdCB3aWxsIGJlIHVzZWRcblx0XHQgKiAgICAgICAgZm9yIHRoZSBkYXRhIHJlcXVlc3RlZC5cblx0XHQgKlxuXHRcdCAqIE5vdGUgdGhhdCBgZGF0YWAgaXMgYSBnZXR0ZXIgYW5kIHNldHRlciBvcHRpb24uIElmIHlvdSBqdXN0IHJlcXVpcmVcblx0XHQgKiBmb3JtYXR0aW5nIG9mIGRhdGEgZm9yIG91dHB1dCwgeW91IHdpbGwgbGlrZWx5IHdhbnQgdG8gdXNlIGByZW5kZXJgIHdoaWNoXG5cdFx0ICogaXMgc2ltcGx5IGEgZ2V0dGVyIGFuZCB0aHVzIHNpbXBsZXIgdG8gdXNlLlxuXHRcdCAqXG5cdFx0ICogTm90ZSB0aGF0IHByaW9yIHRvIERhdGFUYWJsZXMgMS45LjIgYGRhdGFgIHdhcyBjYWxsZWQgYG1EYXRhUHJvcGAuIFRoZVxuXHRcdCAqIG5hbWUgY2hhbmdlIHJlZmxlY3RzIHRoZSBmbGV4aWJpbGl0eSBvZiB0aGlzIHByb3BlcnR5IGFuZCBpcyBjb25zaXN0ZW50XG5cdFx0ICogd2l0aCB0aGUgbmFtaW5nIG9mIG1SZW5kZXIuIElmICdtRGF0YVByb3AnIGlzIGdpdmVuLCB0aGVuIGl0IHdpbGwgc3RpbGxcblx0XHQgKiBiZSB1c2VkIGJ5IERhdGFUYWJsZXMsIGFzIGl0IGF1dG9tYXRpY2FsbHkgbWFwcyB0aGUgb2xkIG5hbWUgdG8gdGhlIG5ld1xuXHRcdCAqIGlmIHJlcXVpcmVkLlxuXHRcdCAqXG5cdFx0ICogIEB0eXBlIHN0cmluZ3xpbnR8ZnVuY3Rpb258bnVsbFxuXHRcdCAqICBAZGVmYXVsdCBudWxsIDxpPlVzZSBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQgY29sdW1uIGluZGV4PC9pPlxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4uZGF0YVxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gUmVhZCB0YWJsZSBkYXRhIGZyb20gb2JqZWN0c1xuXHRcdCAqICAgIC8vIEpTT04gc3RydWN0dXJlIGZvciBlYWNoIHJvdzpcblx0XHQgKiAgICAvLyAgIHtcblx0XHQgKiAgICAvLyAgICAgIFwiZW5naW5lXCI6IHt2YWx1ZX0sXG5cdFx0ICogICAgLy8gICAgICBcImJyb3dzZXJcIjoge3ZhbHVlfSxcblx0XHQgKiAgICAvLyAgICAgIFwicGxhdGZvcm1cIjoge3ZhbHVlfSxcblx0XHQgKiAgICAvLyAgICAgIFwidmVyc2lvblwiOiB7dmFsdWV9LFxuXHRcdCAqICAgIC8vICAgICAgXCJncmFkZVwiOiB7dmFsdWV9XG5cdFx0ICogICAgLy8gICB9XG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJhamF4U291cmNlXCI6IFwic291cmNlcy9vYmplY3RzLnR4dFwiLFxuXHRcdCAqICAgICAgICBcImNvbHVtbnNcIjogW1xuXHRcdCAqICAgICAgICAgIHsgXCJkYXRhXCI6IFwiZW5naW5lXCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwiZGF0YVwiOiBcImJyb3dzZXJcIiB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJkYXRhXCI6IFwicGxhdGZvcm1cIiB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJkYXRhXCI6IFwidmVyc2lvblwiIH0sXG5cdFx0ICogICAgICAgICAgeyBcImRhdGFcIjogXCJncmFkZVwiIH1cblx0XHQgKiAgICAgICAgXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFJlYWQgaW5mb3JtYXRpb24gZnJvbSBkZWVwbHkgbmVzdGVkIG9iamVjdHNcblx0XHQgKiAgICAvLyBKU09OIHN0cnVjdHVyZSBmb3IgZWFjaCByb3c6XG5cdFx0ICogICAgLy8gICB7XG5cdFx0ICogICAgLy8gICAgICBcImVuZ2luZVwiOiB7dmFsdWV9LFxuXHRcdCAqICAgIC8vICAgICAgXCJicm93c2VyXCI6IHt2YWx1ZX0sXG5cdFx0ICogICAgLy8gICAgICBcInBsYXRmb3JtXCI6IHtcblx0XHQgKiAgICAvLyAgICAgICAgIFwiaW5uZXJcIjoge3ZhbHVlfVxuXHRcdCAqICAgIC8vICAgICAgfSxcblx0XHQgKiAgICAvLyAgICAgIFwiZGV0YWlsc1wiOiBbXG5cdFx0ICogICAgLy8gICAgICAgICB7dmFsdWV9LCB7dmFsdWV9XG5cdFx0ICogICAgLy8gICAgICBdXG5cdFx0ICogICAgLy8gICB9XG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJhamF4U291cmNlXCI6IFwic291cmNlcy9kZWVwLnR4dFwiLFxuXHRcdCAqICAgICAgICBcImNvbHVtbnNcIjogW1xuXHRcdCAqICAgICAgICAgIHsgXCJkYXRhXCI6IFwiZW5naW5lXCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwiZGF0YVwiOiBcImJyb3dzZXJcIiB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJkYXRhXCI6IFwicGxhdGZvcm0uaW5uZXJcIiB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJkYXRhXCI6IFwicGxhdGZvcm0uZGV0YWlscy4wXCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwiZGF0YVwiOiBcInBsYXRmb3JtLmRldGFpbHMuMVwiIH1cblx0XHQgKiAgICAgICAgXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFVzaW5nIGBkYXRhYCBhcyBhIGZ1bmN0aW9uIHRvIHByb3ZpZGUgZGlmZmVyZW50IGluZm9ybWF0aW9uIGZvclxuXHRcdCAqICAgIC8vIHNvcnRpbmcsIGZpbHRlcmluZyBhbmQgZGlzcGxheS4gSW4gdGhpcyBjYXNlLCBjdXJyZW5jeSAocHJpY2UpXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFsge1xuXHRcdCAqICAgICAgICAgIFwidGFyZ2V0c1wiOiBbIDAgXSxcblx0XHQgKiAgICAgICAgICBcImRhdGFcIjogZnVuY3Rpb24gKCBzb3VyY2UsIHR5cGUsIHZhbCApIHtcblx0XHQgKiAgICAgICAgICAgIGlmICh0eXBlID09PSAnc2V0Jykge1xuXHRcdCAqICAgICAgICAgICAgICBzb3VyY2UucHJpY2UgPSB2YWw7XG5cdFx0ICogICAgICAgICAgICAgIC8vIFN0b3JlIHRoZSBjb21wdXRlZCBkaXNsYXkgYW5kIGZpbHRlciB2YWx1ZXMgZm9yIGVmZmljaWVuY3lcblx0XHQgKiAgICAgICAgICAgICAgc291cmNlLnByaWNlX2Rpc3BsYXkgPSB2YWw9PVwiXCIgPyBcIlwiIDogXCIkXCIrbnVtYmVyRm9ybWF0KHZhbCk7XG5cdFx0ICogICAgICAgICAgICAgIHNvdXJjZS5wcmljZV9maWx0ZXIgID0gdmFsPT1cIlwiID8gXCJcIiA6IFwiJFwiK251bWJlckZvcm1hdCh2YWwpK1wiIFwiK3ZhbDtcblx0XHQgKiAgICAgICAgICAgICAgcmV0dXJuO1xuXHRcdCAqICAgICAgICAgICAgfVxuXHRcdCAqICAgICAgICAgICAgZWxzZSBpZiAodHlwZSA9PT0gJ2Rpc3BsYXknKSB7XG5cdFx0ICogICAgICAgICAgICAgIHJldHVybiBzb3VyY2UucHJpY2VfZGlzcGxheTtcblx0XHQgKiAgICAgICAgICAgIH1cblx0XHQgKiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGUgPT09ICdmaWx0ZXInKSB7XG5cdFx0ICogICAgICAgICAgICAgIHJldHVybiBzb3VyY2UucHJpY2VfZmlsdGVyO1xuXHRcdCAqICAgICAgICAgICAgfVxuXHRcdCAqICAgICAgICAgICAgLy8gJ3NvcnQnLCAndHlwZScgYW5kIHVuZGVmaW5lZCBhbGwganVzdCB1c2UgdGhlIGludGVnZXJcblx0XHQgKiAgICAgICAgICAgIHJldHVybiBzb3VyY2UucHJpY2U7XG5cdFx0ICogICAgICAgICAgfVxuXHRcdCAqICAgICAgICB9IF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2luZyBkZWZhdWx0IGNvbnRlbnRcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImNvbHVtbkRlZnNcIjogWyB7XG5cdFx0ICogICAgICAgICAgXCJ0YXJnZXRzXCI6IFsgMCBdLFxuXHRcdCAqICAgICAgICAgIFwiZGF0YVwiOiBudWxsLFxuXHRcdCAqICAgICAgICAgIFwiZGVmYXVsdENvbnRlbnRcIjogXCJDbGljayB0byBlZGl0XCJcblx0XHQgKiAgICAgICAgfSBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYXJyYXkgbm90YXRpb24gLSBvdXRwdXR0aW5nIGEgbGlzdCBmcm9tIGFuIGFycmF5XG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFsge1xuXHRcdCAqICAgICAgICAgIFwidGFyZ2V0c1wiOiBbIDAgXSxcblx0XHQgKiAgICAgICAgICBcImRhdGFcIjogXCJuYW1lWywgXVwiXG5cdFx0ICogICAgICAgIH0gXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqL1xuXHRcdFwibURhdGFcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoaXMgcHJvcGVydHkgaXMgdGhlIHJlbmRlcmluZyBwYXJ0bmVyIHRvIGBkYXRhYCBhbmQgaXQgaXMgc3VnZ2VzdGVkIHRoYXRcblx0XHQgKiB3aGVuIHlvdSB3YW50IHRvIG1hbmlwdWxhdGUgZGF0YSBmb3IgZGlzcGxheSAoaW5jbHVkaW5nIGZpbHRlcmluZyxcblx0XHQgKiBzb3J0aW5nIGV0Yykgd2l0aG91dCBhbHRlcmluZyB0aGUgdW5kZXJseWluZyBkYXRhIGZvciB0aGUgdGFibGUsIHVzZSB0aGlzXG5cdFx0ICogcHJvcGVydHkuIGByZW5kZXJgIGNhbiBiZSBjb25zaWRlcmVkIHRvIGJlIHRoZSB0aGUgcmVhZCBvbmx5IGNvbXBhbmlvbiB0b1xuXHRcdCAqIGBkYXRhYCB3aGljaCBpcyByZWFkIC8gd3JpdGUgKHRoZW4gYXMgc3VjaCBtb3JlIGNvbXBsZXgpLiBMaWtlIGBkYXRhYFxuXHRcdCAqIHRoaXMgb3B0aW9uIGNhbiBiZSBnaXZlbiBpbiBhIG51bWJlciBvZiBkaWZmZXJlbnQgd2F5cyB0byBlZmZlY3QgaXRzXG5cdFx0ICogYmVoYXZpb3VyOlxuXHRcdCAqXG5cdFx0ICogKiBgaW50ZWdlcmAgLSB0cmVhdGVkIGFzIGFuIGFycmF5IGluZGV4IGZvciB0aGUgZGF0YSBzb3VyY2UuIFRoaXMgaXMgdGhlXG5cdFx0ICogICBkZWZhdWx0IHRoYXQgRGF0YVRhYmxlcyB1c2VzIChpbmNyZW1lbnRhbGx5IGluY3JlYXNlZCBmb3IgZWFjaCBjb2x1bW4pLlxuXHRcdCAqICogYHN0cmluZ2AgLSByZWFkIGFuIG9iamVjdCBwcm9wZXJ0eSBmcm9tIHRoZSBkYXRhIHNvdXJjZS4gVGhlcmUgYXJlXG5cdFx0ICogICB0aHJlZSAnc3BlY2lhbCcgb3B0aW9ucyB0aGF0IGNhbiBiZSB1c2VkIGluIHRoZSBzdHJpbmcgdG8gYWx0ZXIgaG93XG5cdFx0ICogICBEYXRhVGFibGVzIHJlYWRzIHRoZSBkYXRhIGZyb20gdGhlIHNvdXJjZSBvYmplY3Q6XG5cdFx0ICogICAgKiBgLmAgLSBEb3R0ZWQgSmF2YXNjcmlwdCBub3RhdGlvbi4gSnVzdCBhcyB5b3UgdXNlIGEgYC5gIGluXG5cdFx0ICogICAgICBKYXZhc2NyaXB0IHRvIHJlYWQgZnJvbSBuZXN0ZWQgb2JqZWN0cywgc28gdG8gY2FuIHRoZSBvcHRpb25zXG5cdFx0ICogICAgICBzcGVjaWZpZWQgaW4gYGRhdGFgLiBGb3IgZXhhbXBsZTogYGJyb3dzZXIudmVyc2lvbmAgb3Jcblx0XHQgKiAgICAgIGBicm93c2VyLm5hbWVgLiBJZiB5b3VyIG9iamVjdCBwYXJhbWV0ZXIgbmFtZSBjb250YWlucyBhIHBlcmlvZCwgdXNlXG5cdFx0ICogICAgICBgXFxcXGAgdG8gZXNjYXBlIGl0IC0gaS5lLiBgZmlyc3RcXFxcLm5hbWVgLlxuXHRcdCAqICAgICogYFtdYCAtIEFycmF5IG5vdGF0aW9uLiBEYXRhVGFibGVzIGNhbiBhdXRvbWF0aWNhbGx5IGNvbWJpbmUgZGF0YVxuXHRcdCAqICAgICAgZnJvbSBhbmQgYXJyYXkgc291cmNlLCBqb2luaW5nIHRoZSBkYXRhIHdpdGggdGhlIGNoYXJhY3RlcnMgcHJvdmlkZWRcblx0XHQgKiAgICAgIGJldHdlZW4gdGhlIHR3byBicmFja2V0cy4gRm9yIGV4YW1wbGU6IGBuYW1lWywgXWAgd291bGQgcHJvdmlkZSBhXG5cdFx0ICogICAgICBjb21tYS1zcGFjZSBzZXBhcmF0ZWQgbGlzdCBmcm9tIHRoZSBzb3VyY2UgYXJyYXkuIElmIG5vIGNoYXJhY3RlcnNcblx0XHQgKiAgICAgIGFyZSBwcm92aWRlZCBiZXR3ZWVuIHRoZSBicmFja2V0cywgdGhlIG9yaWdpbmFsIGFycmF5IHNvdXJjZSBpc1xuXHRcdCAqICAgICAgcmV0dXJuZWQuXG5cdFx0ICogICAgKiBgKClgIC0gRnVuY3Rpb24gbm90YXRpb24uIEFkZGluZyBgKClgIHRvIHRoZSBlbmQgb2YgYSBwYXJhbWV0ZXIgd2lsbFxuXHRcdCAqICAgICAgZXhlY3V0ZSBhIGZ1bmN0aW9uIG9mIHRoZSBuYW1lIGdpdmVuLiBGb3IgZXhhbXBsZTogYGJyb3dzZXIoKWAgZm9yIGFcblx0XHQgKiAgICAgIHNpbXBsZSBmdW5jdGlvbiBvbiB0aGUgZGF0YSBzb3VyY2UsIGBicm93c2VyLnZlcnNpb24oKWAgZm9yIGFcblx0XHQgKiAgICAgIGZ1bmN0aW9uIGluIGEgbmVzdGVkIHByb3BlcnR5IG9yIGV2ZW4gYGJyb3dzZXIoKS52ZXJzaW9uYCB0byBnZXQgYW5cblx0XHQgKiAgICAgIG9iamVjdCBwcm9wZXJ0eSBpZiB0aGUgZnVuY3Rpb24gY2FsbGVkIHJldHVybnMgYW4gb2JqZWN0LlxuXHRcdCAqICogYG9iamVjdGAgLSB1c2UgZGlmZmVyZW50IGRhdGEgZm9yIHRoZSBkaWZmZXJlbnQgZGF0YSB0eXBlcyByZXF1ZXN0ZWQgYnlcblx0XHQgKiAgIERhdGFUYWJsZXMgKCdmaWx0ZXInLCAnZGlzcGxheScsICd0eXBlJyBvciAnc29ydCcpLiBUaGUgcHJvcGVydHkgbmFtZXNcblx0XHQgKiAgIG9mIHRoZSBvYmplY3QgaXMgdGhlIGRhdGEgdHlwZSB0aGUgcHJvcGVydHkgcmVmZXJzIHRvIGFuZCB0aGUgdmFsdWUgY2FuXG5cdFx0ICogICBkZWZpbmVkIHVzaW5nIGFuIGludGVnZXIsIHN0cmluZyBvciBmdW5jdGlvbiB1c2luZyB0aGUgc2FtZSBydWxlcyBhc1xuXHRcdCAqICAgYHJlbmRlcmAgbm9ybWFsbHkgZG9lcy4gTm90ZSB0aGF0IGFuIGBfYCBvcHRpb24gX211c3RfIGJlIHNwZWNpZmllZC5cblx0XHQgKiAgIFRoaXMgaXMgdGhlIGRlZmF1bHQgdmFsdWUgdG8gdXNlIGlmIHlvdSBoYXZlbid0IHNwZWNpZmllZCBhIHZhbHVlIGZvclxuXHRcdCAqICAgdGhlIGRhdGEgdHlwZSByZXF1ZXN0ZWQgYnkgRGF0YVRhYmxlcy5cblx0XHQgKiAqIGBmdW5jdGlvbmAgLSB0aGUgZnVuY3Rpb24gZ2l2ZW4gd2lsbCBiZSBleGVjdXRlZCB3aGVuZXZlciBEYXRhVGFibGVzXG5cdFx0ICogICBuZWVkcyB0byBzZXQgb3IgZ2V0IHRoZSBkYXRhIGZvciBhIGNlbGwgaW4gdGhlIGNvbHVtbi4gVGhlIGZ1bmN0aW9uXG5cdFx0ICogICB0YWtlcyB0aHJlZSBwYXJhbWV0ZXJzOlxuXHRcdCAqICAgICogUGFyYW1ldGVyczpcblx0XHQgKiAgICAgICoge2FycmF5fG9iamVjdH0gVGhlIGRhdGEgc291cmNlIGZvciB0aGUgcm93IChiYXNlZCBvbiBgZGF0YWApXG5cdFx0ICogICAgICAqIHtzdHJpbmd9IFRoZSB0eXBlIGNhbGwgZGF0YSByZXF1ZXN0ZWQgLSB0aGlzIHdpbGwgYmUgJ2ZpbHRlcicsXG5cdFx0ICogICAgICAgICdkaXNwbGF5JywgJ3R5cGUnIG9yICdzb3J0Jy5cblx0XHQgKiAgICAgICoge2FycmF5fG9iamVjdH0gVGhlIGZ1bGwgZGF0YSBzb3VyY2UgZm9yIHRoZSByb3cgKG5vdCBiYXNlZCBvblxuXHRcdCAqICAgICAgICBgZGF0YWApXG5cdFx0ICogICAgKiBSZXR1cm46XG5cdFx0ICogICAgICAqIFRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgZnVuY3Rpb24gaXMgd2hhdCB3aWxsIGJlIHVzZWQgZm9yIHRoZVxuXHRcdCAqICAgICAgICBkYXRhIHJlcXVlc3RlZC5cblx0XHQgKlxuXHRcdCAqICBAdHlwZSBzdHJpbmd8aW50fGZ1bmN0aW9ufG9iamVjdHxudWxsXG5cdFx0ICogIEBkZWZhdWx0IG51bGwgVXNlIHRoZSBkYXRhIHNvdXJjZSB2YWx1ZS5cblx0XHQgKlxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLnJlbmRlclxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gQ3JlYXRlIGEgY29tbWEgc2VwYXJhdGVkIGxpc3QgZnJvbSBhbiBhcnJheSBvZiBvYmplY3RzXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJhamF4U291cmNlXCI6IFwic291cmNlcy9kZWVwLnR4dFwiLFxuXHRcdCAqICAgICAgICBcImNvbHVtbnNcIjogW1xuXHRcdCAqICAgICAgICAgIHsgXCJkYXRhXCI6IFwiZW5naW5lXCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwiZGF0YVwiOiBcImJyb3dzZXJcIiB9LFxuXHRcdCAqICAgICAgICAgIHtcblx0XHQgKiAgICAgICAgICAgIFwiZGF0YVwiOiBcInBsYXRmb3JtXCIsXG5cdFx0ICogICAgICAgICAgICBcInJlbmRlclwiOiBcIlssIF0ubmFtZVwiXG5cdFx0ICogICAgICAgICAgfVxuXHRcdCAqICAgICAgICBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gRXhlY3V0ZSBhIGZ1bmN0aW9uIHRvIG9idGFpbiBkYXRhXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFsge1xuXHRcdCAqICAgICAgICAgIFwidGFyZ2V0c1wiOiBbIDAgXSxcblx0XHQgKiAgICAgICAgICBcImRhdGFcIjogbnVsbCwgLy8gVXNlIHRoZSBmdWxsIGRhdGEgc291cmNlIG9iamVjdCBmb3IgdGhlIHJlbmRlcmVyJ3Mgc291cmNlXG5cdFx0ICogICAgICAgICAgXCJyZW5kZXJcIjogXCJicm93c2VyTmFtZSgpXCJcblx0XHQgKiAgICAgICAgfSBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gQXMgYW4gb2JqZWN0LCBleHRyYWN0aW5nIGRpZmZlcmVudCBkYXRhIGZvciB0aGUgZGlmZmVyZW50IHR5cGVzXG5cdFx0ICogICAgLy8gVGhpcyB3b3VsZCBiZSB1c2VkIHdpdGggYSBkYXRhIHNvdXJjZSBzdWNoIGFzOlxuXHRcdCAqICAgIC8vICAgeyBcInBob25lXCI6IDU1NTIzNjgsIFwicGhvbmVfZmlsdGVyXCI6IFwiNTU1MjM2OCA1NTUtMjM2OFwiLCBcInBob25lX2Rpc3BsYXlcIjogXCI1NTUtMjM2OFwiIH1cblx0XHQgKiAgICAvLyBIZXJlIHRoZSBgcGhvbmVgIGludGVnZXIgaXMgdXNlZCBmb3Igc29ydGluZyBhbmQgdHlwZSBkZXRlY3Rpb24sIHdoaWxlIGBwaG9uZV9maWx0ZXJgXG5cdFx0ICogICAgLy8gKHdoaWNoIGhhcyBib3RoIGZvcm1zKSBpcyB1c2VkIGZvciBmaWx0ZXJpbmcgZm9yIGlmIGEgdXNlciBpbnB1dHMgZWl0aGVyIGZvcm1hdCwgd2hpbGVcblx0XHQgKiAgICAvLyB0aGUgZm9ybWF0dGVkIHBob25lIG51bWJlciBpcyB0aGUgb25lIHRoYXQgaXMgc2hvd24gaW4gdGhlIHRhYmxlLlxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiY29sdW1uRGVmc1wiOiBbIHtcblx0XHQgKiAgICAgICAgICBcInRhcmdldHNcIjogWyAwIF0sXG5cdFx0ICogICAgICAgICAgXCJkYXRhXCI6IG51bGwsIC8vIFVzZSB0aGUgZnVsbCBkYXRhIHNvdXJjZSBvYmplY3QgZm9yIHRoZSByZW5kZXJlcidzIHNvdXJjZVxuXHRcdCAqICAgICAgICAgIFwicmVuZGVyXCI6IHtcblx0XHQgKiAgICAgICAgICAgIFwiX1wiOiBcInBob25lXCIsXG5cdFx0ICogICAgICAgICAgICBcImZpbHRlclwiOiBcInBob25lX2ZpbHRlclwiLFxuXHRcdCAqICAgICAgICAgICAgXCJkaXNwbGF5XCI6IFwicGhvbmVfZGlzcGxheVwiXG5cdFx0ICogICAgICAgICAgfVxuXHRcdCAqICAgICAgICB9IF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2UgYXMgYSBmdW5jdGlvbiB0byBjcmVhdGUgYSBsaW5rIGZyb20gdGhlIGRhdGEgc291cmNlXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFsge1xuXHRcdCAqICAgICAgICAgIFwidGFyZ2V0c1wiOiBbIDAgXSxcblx0XHQgKiAgICAgICAgICBcImRhdGFcIjogXCJkb3dubG9hZF9saW5rXCIsXG5cdFx0ICogICAgICAgICAgXCJyZW5kZXJcIjogZnVuY3Rpb24gKCBkYXRhLCB0eXBlLCBmdWxsICkge1xuXHRcdCAqICAgICAgICAgICAgcmV0dXJuICc8YSBocmVmPVwiJytkYXRhKydcIj5Eb3dubG9hZDwvYT4nO1xuXHRcdCAqICAgICAgICAgIH1cblx0XHQgKiAgICAgICAgfSBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwibVJlbmRlclwiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogQ2hhbmdlIHRoZSBjZWxsIHR5cGUgY3JlYXRlZCBmb3IgdGhlIGNvbHVtbiAtIGVpdGhlciBURCBjZWxscyBvciBUSCBjZWxscy4gVGhpc1xuXHRcdCAqIGNhbiBiZSB1c2VmdWwgYXMgVEggY2VsbHMgaGF2ZSBzZW1hbnRpYyBtZWFuaW5nIGluIHRoZSB0YWJsZSBib2R5LCBhbGxvd2luZyB0aGVtXG5cdFx0ICogdG8gYWN0IGFzIGEgaGVhZGVyIGZvciBhIHJvdyAoeW91IG1heSB3aXNoIHRvIGFkZCBzY29wZT0ncm93JyB0byB0aGUgVEggZWxlbWVudHMpLlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgdGRcblx0XHQgKlxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLmNlbGxUeXBlXG5cdFx0ICogIEBkdG9wdCBDb2x1bW5zXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBNYWtlIHRoZSBmaXJzdCBjb2x1bW4gdXNlIFRIIGNlbGxzXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFsge1xuXHRcdCAqICAgICAgICAgIFwidGFyZ2V0c1wiOiBbIDAgXSxcblx0XHQgKiAgICAgICAgICBcImNlbGxUeXBlXCI6IFwidGhcIlxuXHRcdCAqICAgICAgICB9IF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJzQ2VsbFR5cGVcIjogXCJ0ZFwiLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogQ2xhc3MgdG8gZ2l2ZSB0byBlYWNoIGNlbGwgaW4gdGhpcyBjb2x1bW4uXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCA8aT5FbXB0eSBzdHJpbmc8L2k+XG5cdFx0ICpcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbi5jbGFzc1xuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwiY2xhc3NcIjogXCJteV9jbGFzc1wiLCBcInRhcmdldHNcIjogWyAwIF0gfVxuXHRcdCAqICAgICAgICBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5zXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwiY2xhc3NcIjogXCJteV9jbGFzc1wiIH0sXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbFxuXHRcdCAqICAgICAgICBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwic0NsYXNzXCI6IFwiXCIsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFdoZW4gRGF0YVRhYmxlcyBjYWxjdWxhdGVzIHRoZSBjb2x1bW4gd2lkdGhzIHRvIGFzc2lnbiB0byBlYWNoIGNvbHVtbixcblx0XHQgKiBpdCBmaW5kcyB0aGUgbG9uZ2VzdCBzdHJpbmcgaW4gZWFjaCBjb2x1bW4gYW5kIHRoZW4gY29uc3RydWN0cyBhXG5cdFx0ICogdGVtcG9yYXJ5IHRhYmxlIGFuZCByZWFkcyB0aGUgd2lkdGhzIGZyb20gdGhhdC4gVGhlIHByb2JsZW0gd2l0aCB0aGlzXG5cdFx0ICogaXMgdGhhdCBcIm1tbVwiIGlzIG11Y2ggd2lkZXIgdGhlbiBcImlpaWlcIiwgYnV0IHRoZSBsYXR0ZXIgaXMgYSBsb25nZXJcblx0XHQgKiBzdHJpbmcgLSB0aHVzIHRoZSBjYWxjdWxhdGlvbiBjYW4gZ28gd3JvbmcgKGRvaW5nIGl0IHByb3Blcmx5IGFuZCBwdXR0aW5nXG5cdFx0ICogaXQgaW50byBhbiBET00gb2JqZWN0IGFuZCBtZWFzdXJpbmcgdGhhdCBpcyBob3JyaWJseSghKSBzbG93KS4gVGh1cyBhc1xuXHRcdCAqIGEgXCJ3b3JrIGFyb3VuZFwiIHdlIHByb3ZpZGUgdGhpcyBvcHRpb24uIEl0IHdpbGwgYXBwZW5kIGl0cyB2YWx1ZSB0byB0aGVcblx0XHQgKiB0ZXh0IHRoYXQgaXMgZm91bmQgdG8gYmUgdGhlIGxvbmdlc3Qgc3RyaW5nIGZvciB0aGUgY29sdW1uIC0gaS5lLiBwYWRkaW5nLlxuXHRcdCAqIEdlbmVyYWxseSB5b3Ugc2hvdWxkbid0IG5lZWQgdGhpcyFcblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IDxpPkVtcHR5IHN0cmluZzxpPlxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4uY29udGVudFBhZGRpbmdcblx0XHQgKiAgQGR0b3B0IENvbHVtbnNcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFVzaW5nIGBjb2x1bW5zYFxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiY29sdW1uc1wiOiBbXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAge1xuXHRcdCAqICAgICAgICAgICAgXCJjb250ZW50UGFkZGluZ1wiOiBcIm1tbVwiXG5cdFx0ICogICAgICAgICAgfVxuXHRcdCAqICAgICAgICBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqL1xuXHRcdFwic0NvbnRlbnRQYWRkaW5nXCI6IFwiXCIsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBBbGxvd3MgYSBkZWZhdWx0IHZhbHVlIHRvIGJlIGdpdmVuIGZvciBhIGNvbHVtbidzIGRhdGEsIGFuZCB3aWxsIGJlIHVzZWRcblx0XHQgKiB3aGVuZXZlciBhIG51bGwgZGF0YSBzb3VyY2UgaXMgZW5jb3VudGVyZWQgKHRoaXMgY2FuIGJlIGJlY2F1c2UgYGRhdGFgXG5cdFx0ICogaXMgc2V0IHRvIG51bGwsIG9yIGJlY2F1c2UgdGhlIGRhdGEgc291cmNlIGl0c2VsZiBpcyBudWxsKS5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKlxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLmRlZmF1bHRDb250ZW50XG5cdFx0ICogIEBkdG9wdCBDb2x1bW5zXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2luZyBgY29sdW1uRGVmc2Bcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImNvbHVtbkRlZnNcIjogW1xuXHRcdCAqICAgICAgICAgIHtcblx0XHQgKiAgICAgICAgICAgIFwiZGF0YVwiOiBudWxsLFxuXHRcdCAqICAgICAgICAgICAgXCJkZWZhdWx0Q29udGVudFwiOiBcIkVkaXRcIixcblx0XHQgKiAgICAgICAgICAgIFwidGFyZ2V0c1wiOiBbIC0xIF1cblx0XHQgKiAgICAgICAgICB9XG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2luZyBgY29sdW1uc2Bcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImNvbHVtbnNcIjogW1xuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIHtcblx0XHQgKiAgICAgICAgICAgIFwiZGF0YVwiOiBudWxsLFxuXHRcdCAqICAgICAgICAgICAgXCJkZWZhdWx0Q29udGVudFwiOiBcIkVkaXRcIlxuXHRcdCAqICAgICAgICAgIH1cblx0XHQgKiAgICAgICAgXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRcInNEZWZhdWx0Q29udGVudFwiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogVGhpcyBwYXJhbWV0ZXIgaXMgb25seSB1c2VkIGluIERhdGFUYWJsZXMnIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcuIEl0IGNhblxuXHRcdCAqIGJlIGV4Y2VwdGlvbmFsbHkgdXNlZnVsIHRvIGtub3cgd2hhdCBjb2x1bW5zIGFyZSBiZWluZyBkaXNwbGF5ZWQgb24gdGhlXG5cdFx0ICogY2xpZW50IHNpZGUsIGFuZCB0byBtYXAgdGhlc2UgdG8gZGF0YWJhc2UgZmllbGRzLiBXaGVuIGRlZmluZWQsIHRoZSBuYW1lc1xuXHRcdCAqIGFsc28gYWxsb3cgRGF0YVRhYmxlcyB0byByZW9yZGVyIGluZm9ybWF0aW9uIGZyb20gdGhlIHNlcnZlciBpZiBpdCBjb21lc1xuXHRcdCAqIGJhY2sgaW4gYW4gdW5leHBlY3RlZCBvcmRlciAoaS5lLiBpZiB5b3Ugc3dpdGNoIHlvdXIgY29sdW1ucyBhcm91bmQgb24gdGhlXG5cdFx0ICogY2xpZW50LXNpZGUsIHlvdXIgc2VydmVyLXNpZGUgY29kZSBkb2VzIG5vdCBhbHNvIG5lZWQgdXBkYXRpbmcpLlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgPGk+RW1wdHkgc3RyaW5nPC9pPlxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4ubmFtZVxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwibmFtZVwiOiBcImVuZ2luZVwiLCBcInRhcmdldHNcIjogWyAwIF0gfSxcblx0XHQgKiAgICAgICAgICB7IFwibmFtZVwiOiBcImJyb3dzZXJcIiwgXCJ0YXJnZXRzXCI6IFsgMSBdIH0sXG5cdFx0ICogICAgICAgICAgeyBcIm5hbWVcIjogXCJwbGF0Zm9ybVwiLCBcInRhcmdldHNcIjogWyAyIF0gfSxcblx0XHQgKiAgICAgICAgICB7IFwibmFtZVwiOiBcInZlcnNpb25cIiwgXCJ0YXJnZXRzXCI6IFsgMyBdIH0sXG5cdFx0ICogICAgICAgICAgeyBcIm5hbWVcIjogXCJncmFkZVwiLCBcInRhcmdldHNcIjogWyA0IF0gfVxuXHRcdCAqICAgICAgICBdXG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfSApO1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5zXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwibmFtZVwiOiBcImVuZ2luZVwiIH0sXG5cdFx0ICogICAgICAgICAgeyBcIm5hbWVcIjogXCJicm93c2VyXCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwibmFtZVwiOiBcInBsYXRmb3JtXCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwibmFtZVwiOiBcInZlcnNpb25cIiB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJuYW1lXCI6IFwiZ3JhZGVcIiB9XG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJzTmFtZVwiOiBcIlwiLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogRGVmaW5lcyBhIGRhdGEgc291cmNlIHR5cGUgZm9yIHRoZSBvcmRlcmluZyB3aGljaCBjYW4gYmUgdXNlZCB0byByZWFkXG5cdFx0ICogcmVhbC10aW1lIGluZm9ybWF0aW9uIGZyb20gdGhlIHRhYmxlICh1cGRhdGluZyB0aGUgaW50ZXJuYWxseSBjYWNoZWRcblx0XHQgKiB2ZXJzaW9uKSBwcmlvciB0byBvcmRlcmluZy4gVGhpcyBhbGxvd3Mgb3JkZXJpbmcgdG8gb2NjdXIgb24gdXNlclxuXHRcdCAqIGVkaXRhYmxlIGVsZW1lbnRzIHN1Y2ggYXMgZm9ybSBpbnB1dHMuXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCBzdGRcblx0XHQgKlxuXHRcdCAqICBAbmFtZSBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uLm9yZGVyRGF0YVR5cGVcblx0XHQgKiAgQGR0b3B0IENvbHVtbnNcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFVzaW5nIGBjb2x1bW5EZWZzYFxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiY29sdW1uRGVmc1wiOiBbXG5cdFx0ICogICAgICAgICAgeyBcIm9yZGVyRGF0YVR5cGVcIjogXCJkb20tdGV4dFwiLCBcInRhcmdldHNcIjogWyAyLCAzIF0gfSxcblx0XHQgKiAgICAgICAgICB7IFwidHlwZVwiOiBcIm51bWVyaWNcIiwgXCJ0YXJnZXRzXCI6IFsgMyBdIH0sXG5cdFx0ICogICAgICAgICAgeyBcIm9yZGVyRGF0YVR5cGVcIjogXCJkb20tc2VsZWN0XCIsIFwidGFyZ2V0c1wiOiBbIDQgXSB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJvcmRlckRhdGFUeXBlXCI6IFwiZG9tLWNoZWNrYm94XCIsIFwidGFyZ2V0c1wiOiBbIDUgXSB9XG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBVc2luZyBgY29sdW1uc2Bcblx0XHQgKiAgICAkKGRvY3VtZW50KS5yZWFkeSggZnVuY3Rpb24oKSB7XG5cdFx0ICogICAgICAkKCcjZXhhbXBsZScpLmRhdGFUYWJsZSgge1xuXHRcdCAqICAgICAgICBcImNvbHVtbnNcIjogW1xuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICB7IFwib3JkZXJEYXRhVHlwZVwiOiBcImRvbS10ZXh0XCIgfSxcblx0XHQgKiAgICAgICAgICB7IFwib3JkZXJEYXRhVHlwZVwiOiBcImRvbS10ZXh0XCIsIFwidHlwZVwiOiBcIm51bWVyaWNcIiB9LFxuXHRcdCAqICAgICAgICAgIHsgXCJvcmRlckRhdGFUeXBlXCI6IFwiZG9tLXNlbGVjdFwiIH0sXG5cdFx0ICogICAgICAgICAgeyBcIm9yZGVyRGF0YVR5cGVcIjogXCJkb20tY2hlY2tib3hcIiB9XG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJzU29ydERhdGFUeXBlXCI6IFwic3RkXCIsXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBUaGUgdGl0bGUgb2YgdGhpcyBjb2x1bW4uXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCBudWxsIDxpPkRlcml2ZWQgZnJvbSB0aGUgJ1RIJyB2YWx1ZSBmb3IgdGhpcyBjb2x1bW4gaW4gdGhlXG5cdFx0ICogICAgb3JpZ2luYWwgSFRNTCB0YWJsZS48L2k+XG5cdFx0ICpcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbi50aXRsZVxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwidGl0bGVcIjogXCJNeSBjb2x1bW4gdGl0bGVcIiwgXCJ0YXJnZXRzXCI6IFsgMCBdIH1cblx0XHQgKiAgICAgICAgXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFVzaW5nIGBjb2x1bW5zYFxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiY29sdW1uc1wiOiBbXG5cdFx0ICogICAgICAgICAgeyBcInRpdGxlXCI6IFwiTXkgY29sdW1uIHRpdGxlXCIgfSxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsXG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJzVGl0bGVcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoZSB0eXBlIGFsbG93cyB5b3UgdG8gc3BlY2lmeSBob3cgdGhlIGRhdGEgZm9yIHRoaXMgY29sdW1uIHdpbGwgYmVcblx0XHQgKiBvcmRlcmVkLiBGb3VyIHR5cGVzIChzdHJpbmcsIG51bWVyaWMsIGRhdGUgYW5kIGh0bWwgKHdoaWNoIHdpbGwgc3RyaXBcblx0XHQgKiBIVE1MIHRhZ3MgYmVmb3JlIG9yZGVyaW5nKSkgYXJlIGN1cnJlbnRseSBhdmFpbGFibGUuIE5vdGUgdGhhdCBvbmx5IGRhdGVcblx0XHQgKiBmb3JtYXRzIHVuZGVyc3Rvb2QgYnkgSmF2YXNjcmlwdCdzIERhdGUoKSBvYmplY3Qgd2lsbCBiZSBhY2NlcHRlZCBhcyB0eXBlXG5cdFx0ICogZGF0ZS4gRm9yIGV4YW1wbGU6IFwiTWFyIDI2LCAyMDA4IDU6MDMgUE1cIi4gTWF5IHRha2UgdGhlIHZhbHVlczogJ3N0cmluZycsXG5cdFx0ICogJ251bWVyaWMnLCAnZGF0ZScgb3IgJ2h0bWwnIChieSBkZWZhdWx0KS4gRnVydGhlciB0eXBlcyBjYW4gYmUgYWRkaW5nXG5cdFx0ICogdGhyb3VnaCBwbHVnLWlucy5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IG51bGwgPGk+QXV0by1kZXRlY3RlZCBmcm9tIHJhdyBkYXRhPC9pPlxuXHRcdCAqXG5cdFx0ICogIEBuYW1lIERhdGFUYWJsZS5kZWZhdWx0cy5jb2x1bW4udHlwZVxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwidHlwZVwiOiBcImh0bWxcIiwgXCJ0YXJnZXRzXCI6IFsgMCBdIH1cblx0XHQgKiAgICAgICAgXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFVzaW5nIGBjb2x1bW5zYFxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiY29sdW1uc1wiOiBbXG5cdFx0ICogICAgICAgICAgeyBcInR5cGVcIjogXCJodG1sXCIgfSxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsXG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJzVHlwZVwiOiBudWxsLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogRGVmaW5pbmcgdGhlIHdpZHRoIG9mIHRoZSBjb2x1bW4sIHRoaXMgcGFyYW1ldGVyIG1heSB0YWtlIGFueSBDU1MgdmFsdWVcblx0XHQgKiAoM2VtLCAyMHB4IGV0YykuIERhdGFUYWJsZXMgYXBwbGllcyAnc21hcnQnIHdpZHRocyB0byBjb2x1bW5zIHdoaWNoIGhhdmUgbm90XG5cdFx0ICogYmVlbiBnaXZlbiBhIHNwZWNpZmljIHdpZHRoIHRocm91Z2ggdGhpcyBpbnRlcmZhY2UgZW5zdXJpbmcgdGhhdCB0aGUgdGFibGVcblx0XHQgKiByZW1haW5zIHJlYWRhYmxlLlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgbnVsbCA8aT5BdXRvbWF0aWM8L2k+XG5cdFx0ICpcblx0XHQgKiAgQG5hbWUgRGF0YVRhYmxlLmRlZmF1bHRzLmNvbHVtbi53aWR0aFxuXHRcdCAqICBAZHRvcHQgQ29sdW1uc1xuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgLy8gVXNpbmcgYGNvbHVtbkRlZnNgXG5cdFx0ICogICAgJChkb2N1bWVudCkucmVhZHkoIGZ1bmN0aW9uKCkge1xuXHRcdCAqICAgICAgJCgnI2V4YW1wbGUnKS5kYXRhVGFibGUoIHtcblx0XHQgKiAgICAgICAgXCJjb2x1bW5EZWZzXCI6IFtcblx0XHQgKiAgICAgICAgICB7IFwid2lkdGhcIjogXCIyMCVcIiwgXCJ0YXJnZXRzXCI6IFsgMCBdIH1cblx0XHQgKiAgICAgICAgXVxuXHRcdCAqICAgICAgfSApO1xuXHRcdCAqICAgIH0gKTtcblx0XHQgKlxuXHRcdCAqICBAZXhhbXBsZVxuXHRcdCAqICAgIC8vIFVzaW5nIGBjb2x1bW5zYFxuXHRcdCAqICAgICQoZG9jdW1lbnQpLnJlYWR5KCBmdW5jdGlvbigpIHtcblx0XHQgKiAgICAgICQoJyNleGFtcGxlJykuZGF0YVRhYmxlKCB7XG5cdFx0ICogICAgICAgIFwiY29sdW1uc1wiOiBbXG5cdFx0ICogICAgICAgICAgeyBcIndpZHRoXCI6IFwiMjAlXCIgfSxcblx0XHQgKiAgICAgICAgICBudWxsLFxuXHRcdCAqICAgICAgICAgIG51bGwsXG5cdFx0ICogICAgICAgICAgbnVsbCxcblx0XHQgKiAgICAgICAgICBudWxsXG5cdFx0ICogICAgICAgIF1cblx0XHQgKiAgICAgIH0gKTtcblx0XHQgKiAgICB9ICk7XG5cdFx0ICovXG5cdFx0XCJzV2lkdGhcIjogbnVsbFxuXHR9O1xuXHRcblx0X2ZuSHVuZ2FyaWFuTWFwKCBEYXRhVGFibGUuZGVmYXVsdHMuY29sdW1uICk7XG5cdFxuXHRcblx0XG5cdC8qKlxuXHQgKiBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdCAtIHRoaXMgaG9sZHMgYWxsIHRoZSBpbmZvcm1hdGlvbiBuZWVkZWQgZm9yIGFcblx0ICogZ2l2ZW4gdGFibGUsIGluY2x1ZGluZyBjb25maWd1cmF0aW9uLCBkYXRhIGFuZCBjdXJyZW50IGFwcGxpY2F0aW9uIG9mIHRoZVxuXHQgKiB0YWJsZSBvcHRpb25zLiBEYXRhVGFibGVzIGRvZXMgbm90IGhhdmUgYSBzaW5nbGUgaW5zdGFuY2UgZm9yIGVhY2ggRGF0YVRhYmxlXG5cdCAqIHdpdGggdGhlIHNldHRpbmdzIGF0dGFjaGVkIHRvIHRoYXQgaW5zdGFuY2UsIGJ1dCByYXRoZXIgaW5zdGFuY2VzIG9mIHRoZVxuXHQgKiBEYXRhVGFibGUgXCJjbGFzc1wiIGFyZSBjcmVhdGVkIG9uLXRoZS1mbHkgYXMgbmVlZGVkICh0eXBpY2FsbHkgYnkgYVxuXHQgKiAkKCkuZGF0YVRhYmxlKCkgY2FsbCkgYW5kIHRoZSBzZXR0aW5ncyBvYmplY3QgaXMgdGhlbiBhcHBsaWVkIHRvIHRoYXRcblx0ICogaW5zdGFuY2UuXG5cdCAqXG5cdCAqIE5vdGUgdGhhdCB0aGlzIG9iamVjdCBpcyByZWxhdGVkIHRvIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9IGJ1dCB0aGlzXG5cdCAqIG9uZSBpcyB0aGUgaW50ZXJuYWwgZGF0YSBzdG9yZSBmb3IgRGF0YVRhYmxlcydzIGNhY2hlIG9mIGNvbHVtbnMuIEl0IHNob3VsZFxuXHQgKiBOT1QgYmUgbWFuaXB1bGF0ZWQgb3V0c2lkZSBvZiBEYXRhVGFibGVzLiBBbnkgY29uZmlndXJhdGlvbiBzaG91bGQgYmUgZG9uZVxuXHQgKiB0aHJvdWdoIHRoZSBpbml0aWFsaXNhdGlvbiBvcHRpb25zLlxuXHQgKiAgQG5hbWVzcGFjZVxuXHQgKiAgQHRvZG8gUmVhbGx5IHNob3VsZCBhdHRhY2ggdGhlIHNldHRpbmdzIG9iamVjdCB0byBpbmRpdmlkdWFsIGluc3RhbmNlcyBzbyB3ZVxuXHQgKiAgICBkb24ndCBuZWVkIHRvIGNyZWF0ZSBuZXcgaW5zdGFuY2VzIG9uIGVhY2ggJCgpLmRhdGFUYWJsZSgpIGNhbGwgKGlmIHRoZVxuXHQgKiAgICB0YWJsZSBhbHJlYWR5IGV4aXN0cykuIEl0IHdvdWxkIGFsc28gc2F2ZSBwYXNzaW5nIG9TZXR0aW5ncyBhcm91bmQgYW5kXG5cdCAqICAgIGludG8gZXZlcnkgc2luZ2xlIGZ1bmN0aW9uLiBIb3dldmVyLCB0aGlzIGlzIGEgdmVyeSBzaWduaWZpY2FudFxuXHQgKiAgICBhcmNoaXRlY3R1cmUgY2hhbmdlIGZvciBEYXRhVGFibGVzIGFuZCB3aWxsIGFsbW9zdCBjZXJ0YWlubHkgYnJlYWtcblx0ICogICAgYmFja3dhcmRzIGNvbXBhdGliaWxpdHkgd2l0aCBvbGRlciBpbnN0YWxsYXRpb25zLiBUaGlzIGlzIHNvbWV0aGluZyB0aGF0XG5cdCAqICAgIHdpbGwgYmUgZG9uZSBpbiAyLjAuXG5cdCAqL1xuXHREYXRhVGFibGUubW9kZWxzLm9TZXR0aW5ncyA9IHtcblx0XHQvKipcblx0XHQgKiBQcmltYXJ5IGZlYXR1cmVzIG9mIERhdGFUYWJsZXMgYW5kIHRoZWlyIGVuYWJsZW1lbnQgc3RhdGUuXG5cdFx0ICogIEBuYW1lc3BhY2Vcblx0XHQgKi9cblx0XHRcIm9GZWF0dXJlc1wiOiB7XG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBGbGFnIHRvIHNheSBpZiBEYXRhVGFibGVzIHNob3VsZCBhdXRvbWF0aWNhbGx5IHRyeSB0byBjYWxjdWxhdGUgdGhlXG5cdFx0XHQgKiBvcHRpbXVtIHRhYmxlIGFuZCBjb2x1bW5zIHdpZHRocyAodHJ1ZSkgb3Igbm90IChmYWxzZSkuXG5cdFx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKi9cblx0XHRcdFwiYkF1dG9XaWR0aFwiOiBudWxsLFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogRGVsYXkgdGhlIGNyZWF0aW9uIG9mIFRSIGFuZCBURCBlbGVtZW50cyB1bnRpbCB0aGV5IGFyZSBhY3R1YWxseVxuXHRcdFx0ICogbmVlZGVkIGJ5IGEgZHJpdmVuIHBhZ2UgZHJhdy4gVGhpcyBjYW4gZ2l2ZSBhIHNpZ25pZmljYW50IHNwZWVkXG5cdFx0XHQgKiBpbmNyZWFzZSBmb3IgQWpheCBzb3VyY2UgYW5kIEphdmFzY3JpcHQgc291cmNlIGRhdGEsIGJ1dCBtYWtlcyBub1xuXHRcdFx0ICogZGlmZmVyZW5jZSBhdCBhbGwgZnJvIERPTSBhbmQgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyB0YWJsZXMuXG5cdFx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKi9cblx0XHRcdFwiYkRlZmVyUmVuZGVyXCI6IG51bGwsXG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBFbmFibGUgZmlsdGVyaW5nIG9uIHRoZSB0YWJsZSBvciBub3QuIE5vdGUgdGhhdCBpZiB0aGlzIGlzIGRpc2FibGVkXG5cdFx0XHQgKiB0aGVuIHRoZXJlIGlzIG5vIGZpbHRlcmluZyBhdCBhbGwgb24gdGhlIHRhYmxlLCBpbmNsdWRpbmcgZm5GaWx0ZXIuXG5cdFx0XHQgKiBUbyBqdXN0IHJlbW92ZSB0aGUgZmlsdGVyaW5nIGlucHV0IHVzZSBzRG9tIGFuZCByZW1vdmUgdGhlICdmJyBvcHRpb24uXG5cdFx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKi9cblx0XHRcdFwiYkZpbHRlclwiOiBudWxsLFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogVGFibGUgaW5mb3JtYXRpb24gZWxlbWVudCAodGhlICdTaG93aW5nIHggb2YgeSByZWNvcmRzJyBkaXYpIGVuYWJsZVxuXHRcdFx0ICogZmxhZy5cblx0XHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHRcdCAqL1xuXHRcdFx0XCJiSW5mb1wiOiBudWxsLFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogUHJlc2VudCBhIHVzZXIgY29udHJvbCBhbGxvd2luZyB0aGUgZW5kIHVzZXIgdG8gY2hhbmdlIHRoZSBwYWdlIHNpemVcblx0XHRcdCAqIHdoZW4gcGFnaW5hdGlvbiBpcyBlbmFibGVkLlxuXHRcdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdFx0ICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uXG5cdFx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdFx0ICovXG5cdFx0XHRcImJMZW5ndGhDaGFuZ2VcIjogbnVsbCxcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIFBhZ2luYXRpb24gZW5hYmxlZCBvciBub3QuIE5vdGUgdGhhdCBpZiB0aGlzIGlzIGRpc2FibGVkIHRoZW4gbGVuZ3RoXG5cdFx0XHQgKiBjaGFuZ2luZyBtdXN0IGFsc28gYmUgZGlzYWJsZWQuXG5cdFx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKi9cblx0XHRcdFwiYlBhZ2luYXRlXCI6IG51bGwsXG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBQcm9jZXNzaW5nIGluZGljYXRvciBlbmFibGUgZmxhZyB3aGVuZXZlciBEYXRhVGFibGVzIGlzIGVuYWN0aW5nIGFcblx0XHRcdCAqIHVzZXIgcmVxdWVzdCAtIHR5cGljYWxseSBhbiBBamF4IHJlcXVlc3QgZm9yIHNlcnZlci1zaWRlIHByb2Nlc3NpbmcuXG5cdFx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKi9cblx0XHRcdFwiYlByb2Nlc3NpbmdcIjogbnVsbCxcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIFNlcnZlci1zaWRlIHByb2Nlc3NpbmcgZW5hYmxlZCBmbGFnIC0gd2hlbiBlbmFibGVkIERhdGFUYWJsZXMgd2lsbFxuXHRcdFx0ICogZ2V0IGFsbCBkYXRhIGZyb20gdGhlIHNlcnZlciBmb3IgZXZlcnkgZHJhdyAtIHRoZXJlIGlzIG5vIGZpbHRlcmluZyxcblx0XHRcdCAqIHNvcnRpbmcgb3IgcGFnaW5nIGRvbmUgb24gdGhlIGNsaWVudC1zaWRlLlxuXHRcdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdFx0ICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uXG5cdFx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdFx0ICovXG5cdFx0XHRcImJTZXJ2ZXJTaWRlXCI6IG51bGwsXG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBTb3J0aW5nIGVuYWJsZW1lbnQgZmxhZy5cblx0XHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHRcdCAqL1xuXHRcdFx0XCJiU29ydFwiOiBudWxsLFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogTXVsdGktY29sdW1uIHNvcnRpbmdcblx0XHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHRcdCAqL1xuXHRcdFx0XCJiU29ydE11bHRpXCI6IG51bGwsXG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBBcHBseSBhIGNsYXNzIHRvIHRoZSBjb2x1bW5zIHdoaWNoIGFyZSBiZWluZyBzb3J0ZWQgdG8gcHJvdmlkZSBhXG5cdFx0XHQgKiB2aXN1YWwgaGlnaGxpZ2h0IG9yIG5vdC4gVGhpcyBjYW4gc2xvdyB0aGluZ3MgZG93biB3aGVuIGVuYWJsZWQgc2luY2Vcblx0XHRcdCAqIHRoZXJlIGlzIGEgbG90IG9mIERPTSBpbnRlcmFjdGlvbi5cblx0XHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHRcdCAqL1xuXHRcdFx0XCJiU29ydENsYXNzZXNcIjogbnVsbCxcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIFN0YXRlIHNhdmluZyBlbmFibGVtZW50IGZsYWcuXG5cdFx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKi9cblx0XHRcdFwiYlN0YXRlU2F2ZVwiOiBudWxsXG5cdFx0fSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFNjcm9sbGluZyBzZXR0aW5ncyBmb3IgYSB0YWJsZS5cblx0XHQgKiAgQG5hbWVzcGFjZVxuXHRcdCAqL1xuXHRcdFwib1Njcm9sbFwiOiB7XG5cdFx0XHQvKipcblx0XHRcdCAqIFdoZW4gdGhlIHRhYmxlIGlzIHNob3J0ZXIgaW4gaGVpZ2h0IHRoYW4gc1Njcm9sbFksIGNvbGxhcHNlIHRoZVxuXHRcdFx0ICogdGFibGUgY29udGFpbmVyIGRvd24gdG8gdGhlIGhlaWdodCBvZiB0aGUgdGFibGUgKHdoZW4gdHJ1ZSkuXG5cdFx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKi9cblx0XHRcdFwiYkNvbGxhcHNlXCI6IG51bGwsXG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBXaWR0aCBvZiB0aGUgc2Nyb2xsYmFyIGZvciB0aGUgd2ViLWJyb3dzZXIncyBwbGF0Zm9ybS4gQ2FsY3VsYXRlZFxuXHRcdFx0ICogZHVyaW5nIHRhYmxlIGluaXRpYWxpc2F0aW9uLlxuXHRcdFx0ICogIEB0eXBlIGludFxuXHRcdFx0ICogIEBkZWZhdWx0IDBcblx0XHRcdCAqL1xuXHRcdFx0XCJpQmFyV2lkdGhcIjogMCxcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIFZpZXdwb3J0IHdpZHRoIGZvciBob3Jpem9udGFsIHNjcm9sbGluZy4gSG9yaXpvbnRhbCBzY3JvbGxpbmcgaXNcblx0XHRcdCAqIGRpc2FibGVkIGlmIGFuIGVtcHR5IHN0cmluZy5cblx0XHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0ICovXG5cdFx0XHRcInNYXCI6IG51bGwsXG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBXaWR0aCB0byBleHBhbmQgdGhlIHRhYmxlIHRvIHdoZW4gdXNpbmcgeC1zY3JvbGxpbmcuIFR5cGljYWxseSB5b3Vcblx0XHRcdCAqIHNob3VsZCBub3QgbmVlZCB0byB1c2UgdGhpcy5cblx0XHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdFx0ICogIEBkZXByZWNhdGVkXG5cdFx0XHQgKi9cblx0XHRcdFwic1hJbm5lclwiOiBudWxsLFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogVmlld3BvcnQgaGVpZ2h0IGZvciB2ZXJ0aWNhbCBzY3JvbGxpbmcuIFZlcnRpY2FsIHNjcm9sbGluZyBpcyBkaXNhYmxlZFxuXHRcdFx0ICogaWYgYW4gZW1wdHkgc3RyaW5nLlxuXHRcdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdFx0ICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uXG5cdFx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0XHQgKi9cblx0XHRcdFwic1lcIjogbnVsbFxuXHRcdH0sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIExhbmd1YWdlIGluZm9ybWF0aW9uIGZvciB0aGUgdGFibGUuXG5cdFx0ICogIEBuYW1lc3BhY2Vcblx0XHQgKiAgQGV4dGVuZHMgRGF0YVRhYmxlLmRlZmF1bHRzLm9MYW5ndWFnZVxuXHRcdCAqL1xuXHRcdFwib0xhbmd1YWdlXCI6IHtcblx0XHRcdC8qKlxuXHRcdFx0ICogSW5mb3JtYXRpb24gY2FsbGJhY2sgZnVuY3Rpb24uIFNlZVxuXHRcdFx0ICoge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0cy5mbkluZm9DYWxsYmFja31cblx0XHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHRcdCAqL1xuXHRcdFx0XCJmbkluZm9DYWxsYmFja1wiOiBudWxsXG5cdFx0fSxcblx0XG5cdFx0LyoqXG5cdFx0ICogQnJvd3NlciBzdXBwb3J0IHBhcmFtZXRlcnNcblx0XHQgKiAgQG5hbWVzcGFjZVxuXHRcdCAqL1xuXHRcdFwib0Jyb3dzZXJcIjoge1xuXHRcdFx0LyoqXG5cdFx0XHQgKiBJbmRpY2F0ZSBpZiB0aGUgYnJvd3NlciBpbmNvcnJlY3RseSBjYWxjdWxhdGVzIHdpZHRoOjEwMCUgaW5zaWRlIGFcblx0XHRcdCAqIHNjcm9sbGluZyBlbGVtZW50IChJRTYvNylcblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHRcdCAqL1xuXHRcdFx0XCJiU2Nyb2xsT3ZlcnNpemVcIjogZmFsc2UsXG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBEZXRlcm1pbmUgaWYgdGhlIHZlcnRpY2FsIHNjcm9sbGJhciBpcyBvbiB0aGUgcmlnaHQgb3IgbGVmdCBvZiB0aGVcblx0XHRcdCAqIHNjcm9sbGluZyBjb250YWluZXIgLSBuZWVkZWQgZm9yIHJ0bCBsYW5ndWFnZSBsYXlvdXQsIGFsdGhvdWdoIG5vdFxuXHRcdFx0ICogYWxsIGJyb3dzZXJzIG1vdmUgdGhlIHNjcm9sbGJhciAoU2FmYXJpKS5cblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHRcdCAqL1xuXHRcdFx0XCJiU2Nyb2xsYmFyTGVmdFwiOiBmYWxzZSxcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIEZsYWcgZm9yIGlmIGBnZXRCb3VuZGluZ0NsaWVudFJlY3RgIGlzIGZ1bGx5IHN1cHBvcnRlZCBvciBub3Rcblx0XHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHRcdCAqL1xuXHRcdFx0XCJiQm91bmRpbmdcIjogZmFsc2UsXG5cdFxuXHRcdFx0LyoqXG5cdFx0XHQgKiBCcm93c2VyIHNjcm9sbGJhciB3aWR0aFxuXHRcdFx0ICogIEB0eXBlIGludGVnZXJcblx0XHRcdCAqICBAZGVmYXVsdCAwXG5cdFx0XHQgKi9cblx0XHRcdFwiYmFyV2lkdGhcIjogMFxuXHRcdH0sXG5cdFxuXHRcblx0XHRcImFqYXhcIjogbnVsbCxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFycmF5IHJlZmVyZW5jaW5nIHRoZSBub2RlcyB3aGljaCBhcmUgdXNlZCBmb3IgdGhlIGZlYXR1cmVzLiBUaGVcblx0XHQgKiBwYXJhbWV0ZXJzIG9mIHRoaXMgb2JqZWN0IG1hdGNoIHdoYXQgaXMgYWxsb3dlZCBieSBzRG9tIC0gaS5lLlxuXHRcdCAqICAgPHVsPlxuXHRcdCAqICAgICA8bGk+J2wnIC0gTGVuZ3RoIGNoYW5naW5nPC9saT5cblx0XHQgKiAgICAgPGxpPidmJyAtIEZpbHRlcmluZyBpbnB1dDwvbGk+XG5cdFx0ICogICAgIDxsaT4ndCcgLSBUaGUgdGFibGUhPC9saT5cblx0XHQgKiAgICAgPGxpPidpJyAtIEluZm9ybWF0aW9uPC9saT5cblx0XHQgKiAgICAgPGxpPidwJyAtIFBhZ2luYXRpb248L2xpPlxuXHRcdCAqICAgICA8bGk+J3InIC0gcFJvY2Vzc2luZzwvbGk+XG5cdFx0ICogICA8L3VsPlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYWFuRmVhdHVyZXNcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFN0b3JlIGRhdGEgaW5mb3JtYXRpb24gLSBzZWUge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1Jvd30gZm9yIGRldGFpbGVkXG5cdFx0ICogaW5mb3JtYXRpb24uXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhb0RhdGFcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFycmF5IG9mIGluZGV4ZXMgd2hpY2ggYXJlIGluIHRoZSBjdXJyZW50IGRpc3BsYXkgKGFmdGVyIGZpbHRlcmluZyBldGMpXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhaURpc3BsYXlcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFycmF5IG9mIGluZGV4ZXMgZm9yIGRpc3BsYXkgLSBubyBmaWx0ZXJpbmdcblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcImFpRGlzcGxheU1hc3RlclwiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogTWFwIG9mIHJvdyBpZHMgdG8gZGF0YSBpbmRleGVzXG5cdFx0ICogIEB0eXBlIG9iamVjdFxuXHRcdCAqICBAZGVmYXVsdCB7fVxuXHRcdCAqL1xuXHRcdFwiYUlkc1wiOiB7fSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU3RvcmUgaW5mb3JtYXRpb24gYWJvdXQgZWFjaCBjb2x1bW4gdGhhdCBpcyBpbiB1c2Vcblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcImFvQ29sdW1uc1wiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU3RvcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHRhYmxlJ3MgaGVhZGVyXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhb0hlYWRlclwiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU3RvcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIHRhYmxlJ3MgZm9vdGVyXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhb0Zvb3RlclwiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU3RvcmUgdGhlIGFwcGxpZWQgZ2xvYmFsIHNlYXJjaCBpbmZvcm1hdGlvbiBpbiBjYXNlIHdlIHdhbnQgdG8gZm9yY2UgYVxuXHRcdCAqIHJlc2VhcmNoIG9yIGNvbXBhcmUgdGhlIG9sZCBzZWFyY2ggdG8gYSBuZXcgb25lLlxuXHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHQgKiAgQG5hbWVzcGFjZVxuXHRcdCAqICBAZXh0ZW5kcyBEYXRhVGFibGUubW9kZWxzLm9TZWFyY2hcblx0XHQgKi9cblx0XHRcIm9QcmV2aW91c1NlYXJjaFwiOiB7fSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU3RvcmUgdGhlIGFwcGxpZWQgc2VhcmNoIGZvciBlYWNoIGNvbHVtbiAtIHNlZVxuXHRcdCAqIHtAbGluayBEYXRhVGFibGUubW9kZWxzLm9TZWFyY2h9IGZvciB0aGUgZm9ybWF0IHRoYXQgaXMgdXNlZCBmb3IgdGhlXG5cdFx0ICogZmlsdGVyaW5nIGluZm9ybWF0aW9uIGZvciBlYWNoIGNvbHVtbi5cblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcImFvUHJlU2VhcmNoQ29sc1wiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU29ydGluZyB0aGF0IGlzIGFwcGxpZWQgdG8gdGhlIHRhYmxlLiBOb3RlIHRoYXQgdGhlIGlubmVyIGFycmF5cyBhcmVcblx0XHQgKiB1c2VkIGluIHRoZSBmb2xsb3dpbmcgbWFubmVyOlxuXHRcdCAqIDx1bD5cblx0XHQgKiAgIDxsaT5JbmRleCAwIC0gY29sdW1uIG51bWJlcjwvbGk+XG5cdFx0ICogICA8bGk+SW5kZXggMSAtIGN1cnJlbnQgc29ydGluZyBkaXJlY3Rpb248L2xpPlxuXHRcdCAqIDwvdWw+XG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAdG9kbyBUaGVzZSBpbm5lciBhcnJheXMgc2hvdWxkIHJlYWxseSBiZSBvYmplY3RzXG5cdFx0ICovXG5cdFx0XCJhYVNvcnRpbmdcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogU29ydGluZyB0aGF0IGlzIGFsd2F5cyBhcHBsaWVkIHRvIHRoZSB0YWJsZSAoaS5lLiBwcmVmaXhlZCBpbiBmcm9udCBvZlxuXHRcdCAqIGFhU29ydGluZykuXG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYWFTb3J0aW5nRml4ZWRcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIENsYXNzZXMgdG8gdXNlIGZvciB0aGUgc3RyaXBpbmcgb2YgYSB0YWJsZS5cblx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0ICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhc1N0cmlwZUNsYXNzZXNcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogSWYgcmVzdG9yaW5nIGEgdGFibGUgLSB3ZSBzaG91bGQgcmVzdG9yZSBpdHMgc3RyaXBpbmcgY2xhc3NlcyBhcyB3ZWxsXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhc0Rlc3Ryb3lTdHJpcGVzXCI6IFtdLFxuXHRcblx0XHQvKipcblx0XHQgKiBJZiByZXN0b3JpbmcgYSB0YWJsZSAtIHdlIHNob3VsZCByZXN0b3JlIGl0cyB3aWR0aFxuXHRcdCAqICBAdHlwZSBpbnRcblx0XHQgKiAgQGRlZmF1bHQgMFxuXHRcdCAqL1xuXHRcdFwic0Rlc3Ryb3lXaWR0aFwiOiAwLFxuXHRcblx0XHQvKipcblx0XHQgKiBDYWxsYmFjayBmdW5jdGlvbnMgYXJyYXkgZm9yIGV2ZXJ5IHRpbWUgYSByb3cgaXMgaW5zZXJ0ZWQgKGkuZS4gb24gYSBkcmF3KS5cblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcImFvUm93Q2FsbGJhY2tcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIENhbGxiYWNrIGZ1bmN0aW9ucyBmb3IgdGhlIGhlYWRlciBvbiBlYWNoIGRyYXcuXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhb0hlYWRlckNhbGxiYWNrXCI6IFtdLFxuXHRcblx0XHQvKipcblx0XHQgKiBDYWxsYmFjayBmdW5jdGlvbiBmb3IgdGhlIGZvb3RlciBvbiBlYWNoIGRyYXcuXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhb0Zvb3RlckNhbGxiYWNrXCI6IFtdLFxuXHRcblx0XHQvKipcblx0XHQgKiBBcnJheSBvZiBjYWxsYmFjayBmdW5jdGlvbnMgZm9yIGRyYXcgY2FsbGJhY2sgZnVuY3Rpb25zXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhb0RyYXdDYWxsYmFja1wiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogQXJyYXkgb2YgY2FsbGJhY2sgZnVuY3Rpb25zIGZvciByb3cgY3JlYXRlZCBmdW5jdGlvblxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYW9Sb3dDcmVhdGVkQ2FsbGJhY2tcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIENhbGxiYWNrIGZ1bmN0aW9ucyBmb3IganVzdCBiZWZvcmUgdGhlIHRhYmxlIGlzIHJlZHJhd24uIEEgcmV0dXJuIG9mXG5cdFx0ICogZmFsc2Ugd2lsbCBiZSB1c2VkIHRvIGNhbmNlbCB0aGUgZHJhdy5cblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcImFvUHJlRHJhd0NhbGxiYWNrXCI6IFtdLFxuXHRcblx0XHQvKipcblx0XHQgKiBDYWxsYmFjayBmdW5jdGlvbnMgZm9yIHdoZW4gdGhlIHRhYmxlIGhhcyBiZWVuIGluaXRpYWxpc2VkLlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYW9Jbml0Q29tcGxldGVcIjogW10sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBDYWxsYmFja3MgZm9yIG1vZGlmeWluZyB0aGUgc2V0dGluZ3MgdG8gYmUgc3RvcmVkIGZvciBzdGF0ZSBzYXZpbmcsIHByaW9yIHRvXG5cdFx0ICogc2F2aW5nIHN0YXRlLlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYW9TdGF0ZVNhdmVQYXJhbXNcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIENhbGxiYWNrcyBmb3IgbW9kaWZ5aW5nIHRoZSBzZXR0aW5ncyB0aGF0IGhhdmUgYmVlbiBzdG9yZWQgZm9yIHN0YXRlIHNhdmluZ1xuXHRcdCAqIHByaW9yIHRvIHVzaW5nIHRoZSBzdG9yZWQgdmFsdWVzIHRvIHJlc3RvcmUgdGhlIHN0YXRlLlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYW9TdGF0ZUxvYWRQYXJhbXNcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIENhbGxiYWNrcyBmb3Igb3BlcmF0aW5nIG9uIHRoZSBzZXR0aW5ncyBvYmplY3Qgb25jZSB0aGUgc2F2ZWQgc3RhdGUgaGFzIGJlZW5cblx0XHQgKiBsb2FkZWRcblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcImFvU3RhdGVMb2FkZWRcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIENhY2hlIHRoZSB0YWJsZSBJRCBmb3IgcXVpY2sgYWNjZXNzXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCA8aT5FbXB0eSBzdHJpbmc8L2k+XG5cdFx0ICovXG5cdFx0XCJzVGFibGVJZFwiOiBcIlwiLFxuXHRcblx0XHQvKipcblx0XHQgKiBUaGUgVEFCTEUgbm9kZSBmb3IgdGhlIG1haW4gdGFibGVcblx0XHQgKiAgQHR5cGUgbm9kZVxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJuVGFibGVcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogUGVybWFuZW50IHJlZiB0byB0aGUgdGhlYWQgZWxlbWVudFxuXHRcdCAqICBAdHlwZSBub2RlXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcIm5USGVhZFwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBQZXJtYW5lbnQgcmVmIHRvIHRoZSB0Zm9vdCBlbGVtZW50IC0gaWYgaXQgZXhpc3RzXG5cdFx0ICogIEB0eXBlIG5vZGVcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwiblRGb290XCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFBlcm1hbmVudCByZWYgdG8gdGhlIHRib2R5IGVsZW1lbnRcblx0XHQgKiAgQHR5cGUgbm9kZVxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJuVEJvZHlcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogQ2FjaGUgdGhlIHdyYXBwZXIgbm9kZSAoY29udGFpbnMgYWxsIERhdGFUYWJsZXMgY29udHJvbGxlZCBlbGVtZW50cylcblx0XHQgKiAgQHR5cGUgbm9kZVxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJuVGFibGVXcmFwcGVyXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEluZGljYXRlIGlmIHdoZW4gdXNpbmcgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyB0aGUgbG9hZGluZyBvZiBkYXRhXG5cdFx0ICogc2hvdWxkIGJlIGRlZmVycmVkIHVudGlsIHRoZSBzZWNvbmQgZHJhdy5cblx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0ICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHQgKi9cblx0XHRcImJEZWZlckxvYWRpbmdcIjogZmFsc2UsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEluZGljYXRlIGlmIGFsbCByZXF1aXJlZCBpbmZvcm1hdGlvbiBoYXMgYmVlbiByZWFkIGluXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHQgKi9cblx0XHRcImJJbml0aWFsaXNlZFwiOiBmYWxzZSxcblx0XG5cdFx0LyoqXG5cdFx0ICogSW5mb3JtYXRpb24gYWJvdXQgb3BlbiByb3dzLiBFYWNoIG9iamVjdCBpbiB0aGUgYXJyYXkgaGFzIHRoZSBwYXJhbWV0ZXJzXG5cdFx0ICogJ25UcicgYW5kICduUGFyZW50J1xuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYW9PcGVuUm93c1wiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogRGljdGF0ZSB0aGUgcG9zaXRpb25pbmcgb2YgRGF0YVRhYmxlcycgY29udHJvbCBlbGVtZW50cyAtIHNlZVxuXHRcdCAqIHtAbGluayBEYXRhVGFibGUubW9kZWwub0luaXQuc0RvbX0uXG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwic0RvbVwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBTZWFyY2ggZGVsYXkgKGluIG1TKVxuXHRcdCAqICBAdHlwZSBpbnRlZ2VyXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcInNlYXJjaERlbGF5XCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFdoaWNoIHR5cGUgb2YgcGFnaW5hdGlvbiBzaG91bGQgYmUgdXNlZC5cblx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0ICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVmYXVsdCB0d29fYnV0dG9uXG5cdFx0ICovXG5cdFx0XCJzUGFnaW5hdGlvblR5cGVcIjogXCJ0d29fYnV0dG9uXCIsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFRoZSBzdGF0ZSBkdXJhdGlvbiAoZm9yIGBzdGF0ZVNhdmVgKSBpbiBzZWNvbmRzLlxuXHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHQgKiAgQHR5cGUgaW50XG5cdFx0ICogIEBkZWZhdWx0IDBcblx0XHQgKi9cblx0XHRcImlTdGF0ZUR1cmF0aW9uXCI6IDAsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFycmF5IG9mIGNhbGxiYWNrIGZ1bmN0aW9ucyBmb3Igc3RhdGUgc2F2aW5nLiBFYWNoIGFycmF5IGVsZW1lbnQgaXMgYW5cblx0XHQgKiBvYmplY3Qgd2l0aCB0aGUgZm9sbG93aW5nIHBhcmFtZXRlcnM6XG5cdFx0ICogICA8dWw+XG5cdFx0ICogICAgIDxsaT5mdW5jdGlvbjpmbiAtIGZ1bmN0aW9uIHRvIGNhbGwuIFRha2VzIHR3byBwYXJhbWV0ZXJzLCBvU2V0dGluZ3Ncblx0XHQgKiAgICAgICBhbmQgdGhlIEpTT04gc3RyaW5nIHRvIHNhdmUgdGhhdCBoYXMgYmVlbiB0aHVzIGZhciBjcmVhdGVkLiBSZXR1cm5zXG5cdFx0ICogICAgICAgYSBKU09OIHN0cmluZyB0byBiZSBpbnNlcnRlZCBpbnRvIGEganNvbiBvYmplY3Rcblx0XHQgKiAgICAgICAoaS5lLiAnXCJwYXJhbVwiOiBbIDAsIDEsIDJdJyk8L2xpPlxuXHRcdCAqICAgICA8bGk+c3RyaW5nOnNOYW1lIC0gbmFtZSBvZiBjYWxsYmFjazwvbGk+XG5cdFx0ICogICA8L3VsPlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYW9TdGF0ZVNhdmVcIjogW10sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEFycmF5IG9mIGNhbGxiYWNrIGZ1bmN0aW9ucyBmb3Igc3RhdGUgbG9hZGluZy4gRWFjaCBhcnJheSBlbGVtZW50IGlzIGFuXG5cdFx0ICogb2JqZWN0IHdpdGggdGhlIGZvbGxvd2luZyBwYXJhbWV0ZXJzOlxuXHRcdCAqICAgPHVsPlxuXHRcdCAqICAgICA8bGk+ZnVuY3Rpb246Zm4gLSBmdW5jdGlvbiB0byBjYWxsLiBUYWtlcyB0d28gcGFyYW1ldGVycywgb1NldHRpbmdzXG5cdFx0ICogICAgICAgYW5kIHRoZSBvYmplY3Qgc3RvcmVkLiBNYXkgcmV0dXJuIGZhbHNlIHRvIGNhbmNlbCBzdGF0ZSBsb2FkaW5nPC9saT5cblx0XHQgKiAgICAgPGxpPnN0cmluZzpzTmFtZSAtIG5hbWUgb2YgY2FsbGJhY2s8L2xpPlxuXHRcdCAqICAgPC91bD5cblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcImFvU3RhdGVMb2FkXCI6IFtdLFxuXHRcblx0XHQvKipcblx0XHQgKiBTdGF0ZSB0aGF0IHdhcyBzYXZlZC4gVXNlZnVsIGZvciBiYWNrIHJlZmVyZW5jZVxuXHRcdCAqICBAdHlwZSBvYmplY3Rcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwib1NhdmVkU3RhdGVcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogU3RhdGUgdGhhdCB3YXMgbG9hZGVkLiBVc2VmdWwgZm9yIGJhY2sgcmVmZXJlbmNlXG5cdFx0ICogIEB0eXBlIG9iamVjdFxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJvTG9hZGVkU3RhdGVcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogU291cmNlIHVybCBmb3IgQUpBWCBkYXRhIGZvciB0aGUgdGFibGUuXG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwic0FqYXhTb3VyY2VcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogUHJvcGVydHkgZnJvbSBhIGdpdmVuIG9iamVjdCBmcm9tIHdoaWNoIHRvIHJlYWQgdGhlIHRhYmxlIGRhdGEgZnJvbS4gVGhpc1xuXHRcdCAqIGNhbiBiZSBhbiBlbXB0eSBzdHJpbmcgKHdoZW4gbm90IHNlcnZlci1zaWRlIHByb2Nlc3NpbmcpLCBpbiB3aGljaCBjYXNlXG5cdFx0ICogaXQgaXMgIGFzc3VtZWQgYW4gYW4gYXJyYXkgaXMgZ2l2ZW4gZGlyZWN0bHkuXG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKi9cblx0XHRcInNBamF4RGF0YVByb3BcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogTm90ZSBpZiBkcmF3IHNob3VsZCBiZSBibG9ja2VkIHdoaWxlIGdldHRpbmcgZGF0YVxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IHRydWVcblx0XHQgKi9cblx0XHRcImJBamF4RGF0YUdldFwiOiB0cnVlLFxuXHRcblx0XHQvKipcblx0XHQgKiBUaGUgbGFzdCBqUXVlcnkgWEhSIG9iamVjdCB0aGF0IHdhcyB1c2VkIGZvciBzZXJ2ZXItc2lkZSBkYXRhIGdhdGhlcmluZy5cblx0XHQgKiBUaGlzIGNhbiBiZSB1c2VkIGZvciB3b3JraW5nIHdpdGggdGhlIFhIUiBpbmZvcm1hdGlvbiBpbiBvbmUgb2YgdGhlXG5cdFx0ICogY2FsbGJhY2tzXG5cdFx0ICogIEB0eXBlIG9iamVjdFxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJqcVhIUlwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBKU09OIHJldHVybmVkIGZyb20gdGhlIHNlcnZlciBpbiB0aGUgbGFzdCBBamF4IHJlcXVlc3Rcblx0XHQgKiAgQHR5cGUgb2JqZWN0XG5cdFx0ICogIEBkZWZhdWx0IHVuZGVmaW5lZFxuXHRcdCAqL1xuXHRcdFwianNvblwiOiB1bmRlZmluZWQsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIERhdGEgc3VibWl0dGVkIGFzIHBhcnQgb2YgdGhlIGxhc3QgQWpheCByZXF1ZXN0XG5cdFx0ICogIEB0eXBlIG9iamVjdFxuXHRcdCAqICBAZGVmYXVsdCB1bmRlZmluZWRcblx0XHQgKi9cblx0XHRcIm9BamF4RGF0YVwiOiB1bmRlZmluZWQsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEZ1bmN0aW9uIHRvIGdldCB0aGUgc2VydmVyLXNpZGUgZGF0YS5cblx0XHQgKiBOb3RlIHRoYXQgdGhpcyBwYXJhbWV0ZXIgd2lsbCBiZSBzZXQgYnkgdGhlIGluaXRpYWxpc2F0aW9uIHJvdXRpbmUuIFRvXG5cdFx0ICogc2V0IGEgZGVmYXVsdCB1c2Uge0BsaW5rIERhdGFUYWJsZS5kZWZhdWx0c30uXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICovXG5cdFx0XCJmblNlcnZlckRhdGFcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogRnVuY3Rpb25zIHdoaWNoIGFyZSBjYWxsZWQgcHJpb3IgdG8gc2VuZGluZyBhbiBBamF4IHJlcXVlc3Qgc28gZXh0cmFcblx0XHQgKiBwYXJhbWV0ZXJzIGNhbiBlYXNpbHkgYmUgc2VudCB0byB0aGUgc2VydmVyXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhb1NlcnZlclBhcmFtc1wiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU2VuZCB0aGUgWEhSIEhUVFAgbWV0aG9kIC0gR0VUIG9yIFBPU1QgKGNvdWxkIGJlIFBVVCBvciBERUxFVEUgaWZcblx0XHQgKiByZXF1aXJlZCkuXG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKi9cblx0XHRcInNTZXJ2ZXJNZXRob2RcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogRm9ybWF0IG51bWJlcnMgZm9yIGRpc3BsYXkuXG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdCAqL1xuXHRcdFwiZm5Gb3JtYXROdW1iZXJcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogTGlzdCBvZiBvcHRpb25zIHRoYXQgY2FuIGJlIHVzZWQgZm9yIHRoZSB1c2VyIHNlbGVjdGFibGUgbGVuZ3RoIG1lbnUuXG5cdFx0ICogTm90ZSB0aGF0IHRoaXMgcGFyYW1ldGVyIHdpbGwgYmUgc2V0IGJ5IHRoZSBpbml0aWFsaXNhdGlvbiByb3V0aW5lLiBUb1xuXHRcdCAqIHNldCBhIGRlZmF1bHQgdXNlIHtAbGluayBEYXRhVGFibGUuZGVmYXVsdHN9LlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqICBAZGVmYXVsdCBbXVxuXHRcdCAqL1xuXHRcdFwiYUxlbmd0aE1lbnVcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogQ291bnRlciBmb3IgdGhlIGRyYXdzIHRoYXQgdGhlIHRhYmxlIGRvZXMuIEFsc28gdXNlZCBhcyBhIHRyYWNrZXIgZm9yXG5cdFx0ICogc2VydmVyLXNpZGUgcHJvY2Vzc2luZ1xuXHRcdCAqICBAdHlwZSBpbnRcblx0XHQgKiAgQGRlZmF1bHQgMFxuXHRcdCAqL1xuXHRcdFwiaURyYXdcIjogMCxcblx0XG5cdFx0LyoqXG5cdFx0ICogSW5kaWNhdGUgaWYgYSByZWRyYXcgaXMgYmVpbmcgZG9uZSAtIHVzZWZ1bCBmb3IgQWpheFxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICovXG5cdFx0XCJiRHJhd2luZ1wiOiBmYWxzZSxcblx0XG5cdFx0LyoqXG5cdFx0ICogRHJhdyBpbmRleCAoaURyYXcpIG9mIHRoZSBsYXN0IGVycm9yIHdoZW4gcGFyc2luZyB0aGUgcmV0dXJuZWQgZGF0YVxuXHRcdCAqICBAdHlwZSBpbnRcblx0XHQgKiAgQGRlZmF1bHQgLTFcblx0XHQgKi9cblx0XHRcImlEcmF3RXJyb3JcIjogLTEsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFBhZ2luZyBkaXNwbGF5IGxlbmd0aFxuXHRcdCAqICBAdHlwZSBpbnRcblx0XHQgKiAgQGRlZmF1bHQgMTBcblx0XHQgKi9cblx0XHRcIl9pRGlzcGxheUxlbmd0aFwiOiAxMCxcblx0XG5cdFx0LyoqXG5cdFx0ICogUGFnaW5nIHN0YXJ0IHBvaW50IC0gYWlEaXNwbGF5IGluZGV4XG5cdFx0ICogIEB0eXBlIGludFxuXHRcdCAqICBAZGVmYXVsdCAwXG5cdFx0ICovXG5cdFx0XCJfaURpc3BsYXlTdGFydFwiOiAwLFxuXHRcblx0XHQvKipcblx0XHQgKiBTZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIC0gbnVtYmVyIG9mIHJlY29yZHMgaW4gdGhlIHJlc3VsdCBzZXRcblx0XHQgKiAoaS5lLiBiZWZvcmUgZmlsdGVyaW5nKSwgVXNlIGZuUmVjb3Jkc1RvdGFsIHJhdGhlciB0aGFuXG5cdFx0ICogdGhpcyBwcm9wZXJ0eSB0byBnZXQgdGhlIHZhbHVlIG9mIHRoZSBudW1iZXIgb2YgcmVjb3JkcywgcmVnYXJkbGVzcyBvZlxuXHRcdCAqIHRoZSBzZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIHNldHRpbmcuXG5cdFx0ICogIEB0eXBlIGludFxuXHRcdCAqICBAZGVmYXVsdCAwXG5cdFx0ICogIEBwcml2YXRlXG5cdFx0ICovXG5cdFx0XCJfaVJlY29yZHNUb3RhbFwiOiAwLFxuXHRcblx0XHQvKipcblx0XHQgKiBTZXJ2ZXItc2lkZSBwcm9jZXNzaW5nIC0gbnVtYmVyIG9mIHJlY29yZHMgaW4gdGhlIGN1cnJlbnQgZGlzcGxheSBzZXRcblx0XHQgKiAoaS5lLiBhZnRlciBmaWx0ZXJpbmcpLiBVc2UgZm5SZWNvcmRzRGlzcGxheSByYXRoZXIgdGhhblxuXHRcdCAqIHRoaXMgcHJvcGVydHkgdG8gZ2V0IHRoZSB2YWx1ZSBvZiB0aGUgbnVtYmVyIG9mIHJlY29yZHMsIHJlZ2FyZGxlc3Mgb2Zcblx0XHQgKiB0aGUgc2VydmVyLXNpZGUgcHJvY2Vzc2luZyBzZXR0aW5nLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IDBcblx0XHQgKiAgQHByaXZhdGVcblx0XHQgKi9cblx0XHRcIl9pUmVjb3Jkc0Rpc3BsYXlcIjogMCxcblx0XG5cdFx0LyoqXG5cdFx0ICogVGhlIGNsYXNzZXMgdG8gdXNlIGZvciB0aGUgdGFibGVcblx0XHQgKiAgQHR5cGUgb2JqZWN0XG5cdFx0ICogIEBkZWZhdWx0IHt9XG5cdFx0ICovXG5cdFx0XCJvQ2xhc3Nlc1wiOiB7fSxcblx0XG5cdFx0LyoqXG5cdFx0ICogRmxhZyBhdHRhY2hlZCB0byB0aGUgc2V0dGluZ3Mgb2JqZWN0IHNvIHlvdSBjYW4gY2hlY2sgaW4gdGhlIGRyYXdcblx0XHQgKiBjYWxsYmFjayBpZiBmaWx0ZXJpbmcgaGFzIGJlZW4gZG9uZSBpbiB0aGUgZHJhdy4gRGVwcmVjYXRlZCBpbiBmYXZvdXIgb2Zcblx0XHQgKiBldmVudHMuXG5cdFx0ICogIEB0eXBlIGJvb2xlYW5cblx0XHQgKiAgQGRlZmF1bHQgZmFsc2Vcblx0XHQgKiAgQGRlcHJlY2F0ZWRcblx0XHQgKi9cblx0XHRcImJGaWx0ZXJlZFwiOiBmYWxzZSxcblx0XG5cdFx0LyoqXG5cdFx0ICogRmxhZyBhdHRhY2hlZCB0byB0aGUgc2V0dGluZ3Mgb2JqZWN0IHNvIHlvdSBjYW4gY2hlY2sgaW4gdGhlIGRyYXdcblx0XHQgKiBjYWxsYmFjayBpZiBzb3J0aW5nIGhhcyBiZWVuIGRvbmUgaW4gdGhlIGRyYXcuIERlcHJlY2F0ZWQgaW4gZmF2b3VyIG9mXG5cdFx0ICogZXZlbnRzLlxuXHRcdCAqICBAdHlwZSBib29sZWFuXG5cdFx0ICogIEBkZWZhdWx0IGZhbHNlXG5cdFx0ICogIEBkZXByZWNhdGVkXG5cdFx0ICovXG5cdFx0XCJiU29ydGVkXCI6IGZhbHNlLFxuXHRcblx0XHQvKipcblx0XHQgKiBJbmRpY2F0ZSB0aGF0IGlmIG11bHRpcGxlIHJvd3MgYXJlIGluIHRoZSBoZWFkZXIgYW5kIHRoZXJlIGlzIG1vcmUgdGhhblxuXHRcdCAqIG9uZSB1bmlxdWUgY2VsbCBwZXIgY29sdW1uLCBpZiB0aGUgdG9wIG9uZSAodHJ1ZSkgb3IgYm90dG9tIG9uZSAoZmFsc2UpXG5cdFx0ICogc2hvdWxkIGJlIHVzZWQgZm9yIHNvcnRpbmcgLyB0aXRsZSBieSBEYXRhVGFibGVzLlxuXHRcdCAqIE5vdGUgdGhhdCB0aGlzIHBhcmFtZXRlciB3aWxsIGJlIHNldCBieSB0aGUgaW5pdGlhbGlzYXRpb24gcm91dGluZS4gVG9cblx0XHQgKiBzZXQgYSBkZWZhdWx0IHVzZSB7QGxpbmsgRGF0YVRhYmxlLmRlZmF1bHRzfS5cblx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdCAqL1xuXHRcdFwiYlNvcnRDZWxsc1RvcFwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBJbml0aWFsaXNhdGlvbiBvYmplY3QgdGhhdCBpcyB1c2VkIGZvciB0aGUgdGFibGVcblx0XHQgKiAgQHR5cGUgb2JqZWN0XG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcIm9Jbml0XCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIERlc3Ryb3kgY2FsbGJhY2sgZnVuY3Rpb25zIC0gZm9yIHBsdWctaW5zIHRvIGF0dGFjaCB0aGVtc2VsdmVzIHRvIHRoZVxuXHRcdCAqIGRlc3Ryb3kgc28gdGhleSBjYW4gY2xlYW4gdXAgbWFya3VwIGFuZCBldmVudHMuXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICovXG5cdFx0XCJhb0Rlc3Ryb3lDYWxsYmFja1wiOiBbXSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEdldCB0aGUgbnVtYmVyIG9mIHJlY29yZHMgaW4gdGhlIGN1cnJlbnQgcmVjb3JkIHNldCwgYmVmb3JlIGZpbHRlcmluZ1xuXHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdCAqL1xuXHRcdFwiZm5SZWNvcmRzVG90YWxcIjogZnVuY3Rpb24gKClcblx0XHR7XG5cdFx0XHRyZXR1cm4gX2ZuRGF0YVNvdXJjZSggdGhpcyApID09ICdzc3AnID9cblx0XHRcdFx0dGhpcy5faVJlY29yZHNUb3RhbCAqIDEgOlxuXHRcdFx0XHR0aGlzLmFpRGlzcGxheU1hc3Rlci5sZW5ndGg7XG5cdFx0fSxcblx0XG5cdFx0LyoqXG5cdFx0ICogR2V0IHRoZSBudW1iZXIgb2YgcmVjb3JkcyBpbiB0aGUgY3VycmVudCByZWNvcmQgc2V0LCBhZnRlciBmaWx0ZXJpbmdcblx0XHQgKiAgQHR5cGUgZnVuY3Rpb25cblx0XHQgKi9cblx0XHRcImZuUmVjb3Jkc0Rpc3BsYXlcIjogZnVuY3Rpb24gKClcblx0XHR7XG5cdFx0XHRyZXR1cm4gX2ZuRGF0YVNvdXJjZSggdGhpcyApID09ICdzc3AnID9cblx0XHRcdFx0dGhpcy5faVJlY29yZHNEaXNwbGF5ICogMSA6XG5cdFx0XHRcdHRoaXMuYWlEaXNwbGF5Lmxlbmd0aDtcblx0XHR9LFxuXHRcblx0XHQvKipcblx0XHQgKiBHZXQgdGhlIGRpc3BsYXkgZW5kIHBvaW50IC0gYWlEaXNwbGF5IGluZGV4XG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICovXG5cdFx0XCJmbkRpc3BsYXlFbmRcIjogZnVuY3Rpb24gKClcblx0XHR7XG5cdFx0XHR2YXJcblx0XHRcdFx0bGVuICAgICAgPSB0aGlzLl9pRGlzcGxheUxlbmd0aCxcblx0XHRcdFx0c3RhcnQgICAgPSB0aGlzLl9pRGlzcGxheVN0YXJ0LFxuXHRcdFx0XHRjYWxjICAgICA9IHN0YXJ0ICsgbGVuLFxuXHRcdFx0XHRyZWNvcmRzICA9IHRoaXMuYWlEaXNwbGF5Lmxlbmd0aCxcblx0XHRcdFx0ZmVhdHVyZXMgPSB0aGlzLm9GZWF0dXJlcyxcblx0XHRcdFx0cGFnaW5hdGUgPSBmZWF0dXJlcy5iUGFnaW5hdGU7XG5cdFxuXHRcdFx0aWYgKCBmZWF0dXJlcy5iU2VydmVyU2lkZSApIHtcblx0XHRcdFx0cmV0dXJuIHBhZ2luYXRlID09PSBmYWxzZSB8fCBsZW4gPT09IC0xID9cblx0XHRcdFx0XHRzdGFydCArIHJlY29yZHMgOlxuXHRcdFx0XHRcdE1hdGgubWluKCBzdGFydCtsZW4sIHRoaXMuX2lSZWNvcmRzRGlzcGxheSApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdHJldHVybiAhIHBhZ2luYXRlIHx8IGNhbGM+cmVjb3JkcyB8fCBsZW49PT0tMSA/XG5cdFx0XHRcdFx0cmVjb3JkcyA6XG5cdFx0XHRcdFx0Y2FsYztcblx0XHRcdH1cblx0XHR9LFxuXHRcblx0XHQvKipcblx0XHQgKiBUaGUgRGF0YVRhYmxlcyBvYmplY3QgZm9yIHRoaXMgdGFibGVcblx0XHQgKiAgQHR5cGUgb2JqZWN0XG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcIm9JbnN0YW5jZVwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiBVbmlxdWUgaWRlbnRpZmllciBmb3IgZWFjaCBpbnN0YW5jZSBvZiB0aGUgRGF0YVRhYmxlcyBvYmplY3QuIElmIHRoZXJlXG5cdFx0ICogaXMgYW4gSUQgb24gdGhlIHRhYmxlIG5vZGUsIHRoZW4gaXQgdGFrZXMgdGhhdCB2YWx1ZSwgb3RoZXJ3aXNlIGFuXG5cdFx0ICogaW5jcmVtZW50aW5nIGludGVybmFsIGNvdW50ZXIgaXMgdXNlZC5cblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHQgKi9cblx0XHRcInNJbnN0YW5jZVwiOiBudWxsLFxuXHRcblx0XHQvKipcblx0XHQgKiB0YWJpbmRleCBhdHRyaWJ1dGUgdmFsdWUgdGhhdCBpcyBhZGRlZCB0byBEYXRhVGFibGVzIGNvbnRyb2wgZWxlbWVudHMsIGFsbG93aW5nXG5cdFx0ICoga2V5Ym9hcmQgbmF2aWdhdGlvbiBvZiB0aGUgdGFibGUgYW5kIGl0cyBjb250cm9scy5cblx0XHQgKi9cblx0XHRcImlUYWJJbmRleFwiOiAwLFxuXHRcblx0XHQvKipcblx0XHQgKiBESVYgY29udGFpbmVyIGZvciB0aGUgZm9vdGVyIHNjcm9sbGluZyB0YWJsZSBpZiBzY3JvbGxpbmdcblx0XHQgKi9cblx0XHRcIm5TY3JvbGxIZWFkXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIERJViBjb250YWluZXIgZm9yIHRoZSBmb290ZXIgc2Nyb2xsaW5nIHRhYmxlIGlmIHNjcm9sbGluZ1xuXHRcdCAqL1xuXHRcdFwiblNjcm9sbEZvb3RcIjogbnVsbCxcblx0XG5cdFx0LyoqXG5cdFx0ICogTGFzdCBhcHBsaWVkIHNvcnRcblx0XHQgKiAgQHR5cGUgYXJyYXlcblx0XHQgKiAgQGRlZmF1bHQgW11cblx0XHQgKi9cblx0XHRcImFMYXN0U29ydFwiOiBbXSxcblx0XG5cdFx0LyoqXG5cdFx0ICogU3RvcmVkIHBsdWctaW4gaW5zdGFuY2VzXG5cdFx0ICogIEB0eXBlIG9iamVjdFxuXHRcdCAqICBAZGVmYXVsdCB7fVxuXHRcdCAqL1xuXHRcdFwib1BsdWdpbnNcIjoge30sXG5cdFxuXHRcdC8qKlxuXHRcdCAqIEZ1bmN0aW9uIHVzZWQgdG8gZ2V0IGEgcm93J3MgaWQgZnJvbSB0aGUgcm93J3MgZGF0YVxuXHRcdCAqICBAdHlwZSBmdW5jdGlvblxuXHRcdCAqICBAZGVmYXVsdCBudWxsXG5cdFx0ICovXG5cdFx0XCJyb3dJZEZuXCI6IG51bGwsXG5cdFxuXHRcdC8qKlxuXHRcdCAqIERhdGEgbG9jYXRpb24gd2hlcmUgdG8gc3RvcmUgYSByb3cncyBpZFxuXHRcdCAqICBAdHlwZSBzdHJpbmdcblx0XHQgKiAgQGRlZmF1bHQgbnVsbFxuXHRcdCAqL1xuXHRcdFwicm93SWRcIjogbnVsbFxuXHR9O1xuXG5cdC8qKlxuXHQgKiBFeHRlbnNpb24gb2JqZWN0IGZvciBEYXRhVGFibGVzIHRoYXQgaXMgdXNlZCB0byBwcm92aWRlIGFsbCBleHRlbnNpb25cblx0ICogb3B0aW9ucy5cblx0ICpcblx0ICogTm90ZSB0aGF0IHRoZSBgRGF0YVRhYmxlLmV4dGAgb2JqZWN0IGlzIGF2YWlsYWJsZSB0aHJvdWdoXG5cdCAqIGBqUXVlcnkuZm4uZGF0YVRhYmxlLmV4dGAgd2hlcmUgaXQgbWF5IGJlIGFjY2Vzc2VkIGFuZCBtYW5pcHVsYXRlZC4gSXQgaXNcblx0ICogYWxzbyBhbGlhc2VkIHRvIGBqUXVlcnkuZm4uZGF0YVRhYmxlRXh0YCBmb3IgaGlzdG9yaWMgcmVhc29ucy5cblx0ICogIEBuYW1lc3BhY2Vcblx0ICogIEBleHRlbmRzIERhdGFUYWJsZS5tb2RlbHMuZXh0XG5cdCAqL1xuXHRcblx0XG5cdC8qKlxuXHQgKiBEYXRhVGFibGVzIGV4dGVuc2lvbnNcblx0ICogXG5cdCAqIFRoaXMgbmFtZXNwYWNlIGFjdHMgYXMgYSBjb2xsZWN0aW9uIGFyZWEgZm9yIHBsdWctaW5zIHRoYXQgY2FuIGJlIHVzZWQgdG9cblx0ICogZXh0ZW5kIERhdGFUYWJsZXMgY2FwYWJpbGl0aWVzLiBJbmRlZWQgbWFueSBvZiB0aGUgYnVpbGQgaW4gbWV0aG9kc1xuXHQgKiB1c2UgdGhpcyBtZXRob2QgdG8gcHJvdmlkZSB0aGVpciBvd24gY2FwYWJpbGl0aWVzIChzb3J0aW5nIG1ldGhvZHMgZm9yXG5cdCAqIGV4YW1wbGUpLlxuXHQgKlxuXHQgKiBOb3RlIHRoYXQgdGhpcyBuYW1lc3BhY2UgaXMgYWxpYXNlZCB0byBgalF1ZXJ5LmZuLmRhdGFUYWJsZUV4dGAgZm9yIGxlZ2FjeVxuXHQgKiByZWFzb25zXG5cdCAqXG5cdCAqICBAbmFtZXNwYWNlXG5cdCAqL1xuXHREYXRhVGFibGUuZXh0ID0gX2V4dCA9IHtcblx0XHQvKipcblx0XHQgKiBCdXR0b25zLiBGb3IgdXNlIHdpdGggdGhlIEJ1dHRvbnMgZXh0ZW5zaW9uIGZvciBEYXRhVGFibGVzLiBUaGlzIGlzXG5cdFx0ICogZGVmaW5lZCBoZXJlIHNvIG90aGVyIGV4dGVuc2lvbnMgY2FuIGRlZmluZSBidXR0b25zIHJlZ2FyZGxlc3Mgb2YgbG9hZFxuXHRcdCAqIG9yZGVyLiBJdCBpcyBfbm90XyB1c2VkIGJ5IERhdGFUYWJsZXMgY29yZS5cblx0XHQgKlxuXHRcdCAqICBAdHlwZSBvYmplY3Rcblx0XHQgKiAgQGRlZmF1bHQge31cblx0XHQgKi9cblx0XHRidXR0b25zOiB7fSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEVsZW1lbnQgY2xhc3MgbmFtZXNcblx0XHQgKlxuXHRcdCAqICBAdHlwZSBvYmplY3Rcblx0XHQgKiAgQGRlZmF1bHQge31cblx0XHQgKi9cblx0XHRjbGFzc2VzOiB7fSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIERhdGFUYWJsZXMgYnVpbGQgdHlwZSAoZXhwYW5kZWQgYnkgdGhlIGRvd25sb2FkIGJ1aWxkZXIpXG5cdFx0ICpcblx0XHQgKiAgQHR5cGUgc3RyaW5nXG5cdFx0ICovXG5cdFx0YnVpbGRlcjogXCItc291cmNlLVwiLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogRXJyb3IgcmVwb3J0aW5nLlxuXHRcdCAqIFxuXHRcdCAqIEhvdyBzaG91bGQgRGF0YVRhYmxlcyByZXBvcnQgYW4gZXJyb3IuIENhbiB0YWtlIHRoZSB2YWx1ZSAnYWxlcnQnLFxuXHRcdCAqICd0aHJvdycsICdub25lJyBvciBhIGZ1bmN0aW9uLlxuXHRcdCAqXG5cdFx0ICogIEB0eXBlIHN0cmluZ3xmdW5jdGlvblxuXHRcdCAqICBAZGVmYXVsdCBhbGVydFxuXHRcdCAqL1xuXHRcdGVyck1vZGU6IFwiYWxlcnRcIixcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEZlYXR1cmUgcGx1Zy1pbnMuXG5cdFx0ICogXG5cdFx0ICogVGhpcyBpcyBhbiBhcnJheSBvZiBvYmplY3RzIHdoaWNoIGRlc2NyaWJlIHRoZSBmZWF0dXJlIHBsdWctaW5zIHRoYXQgYXJlXG5cdFx0ICogYXZhaWxhYmxlIHRvIERhdGFUYWJsZXMuIFRoZXNlIGZlYXR1cmUgcGx1Zy1pbnMgYXJlIHRoZW4gYXZhaWxhYmxlIGZvclxuXHRcdCAqIHVzZSB0aHJvdWdoIHRoZSBgZG9tYCBpbml0aWFsaXNhdGlvbiBvcHRpb24uXG5cdFx0ICogXG5cdFx0ICogRWFjaCBmZWF0dXJlIHBsdWctaW4gaXMgZGVzY3JpYmVkIGJ5IGFuIG9iamVjdCB3aGljaCBtdXN0IGhhdmUgdGhlXG5cdFx0ICogZm9sbG93aW5nIHByb3BlcnRpZXM6XG5cdFx0ICogXG5cdFx0ICogKiBgZm5Jbml0YCAtIGZ1bmN0aW9uIHRoYXQgaXMgdXNlZCB0byBpbml0aWFsaXNlIHRoZSBwbHVnLWluLFxuXHRcdCAqICogYGNGZWF0dXJlYCAtIGEgY2hhcmFjdGVyIHNvIHRoZSBmZWF0dXJlIGNhbiBiZSBlbmFibGVkIGJ5IHRoZSBgZG9tYFxuXHRcdCAqICAgaW5zdGlsbGF0aW9uIG9wdGlvbi4gVGhpcyBpcyBjYXNlIHNlbnNpdGl2ZS5cblx0XHQgKlxuXHRcdCAqIFRoZSBgZm5Jbml0YCBmdW5jdGlvbiBoYXMgdGhlIGZvbGxvd2luZyBpbnB1dCBwYXJhbWV0ZXJzOlxuXHRcdCAqXG5cdFx0ICogMS4gYHtvYmplY3R9YCBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdDogc2VlXG5cdFx0ICogICAge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfVxuXHRcdCAqXG5cdFx0ICogQW5kIHRoZSBmb2xsb3dpbmcgcmV0dXJuIGlzIGV4cGVjdGVkOlxuXHRcdCAqIFxuXHRcdCAqICoge25vZGV8bnVsbH0gVGhlIGVsZW1lbnQgd2hpY2ggY29udGFpbnMgeW91ciBmZWF0dXJlLiBOb3RlIHRoYXQgdGhlXG5cdFx0ICogICByZXR1cm4gbWF5IGFsc28gYmUgdm9pZCBpZiB5b3VyIHBsdWctaW4gZG9lcyBub3QgcmVxdWlyZSB0byBpbmplY3QgYW55XG5cdFx0ICogICBET00gZWxlbWVudHMgaW50byBEYXRhVGFibGVzIGNvbnRyb2wgKGBkb21gKSAtIGZvciBleGFtcGxlIHRoaXMgbWlnaHRcblx0XHQgKiAgIGJlIHVzZWZ1bCB3aGVuIGRldmVsb3BpbmcgYSBwbHVnLWluIHdoaWNoIGFsbG93cyB0YWJsZSBjb250cm9sIHZpYVxuXHRcdCAqICAga2V5Ym9hcmQgZW50cnlcblx0XHQgKlxuXHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdCAqXG5cdFx0ICogIEBleGFtcGxlXG5cdFx0ICogICAgJC5mbi5kYXRhVGFibGUuZXh0LmZlYXR1cmVzLnB1c2goIHtcblx0XHQgKiAgICAgIFwiZm5Jbml0XCI6IGZ1bmN0aW9uKCBvU2V0dGluZ3MgKSB7XG5cdFx0ICogICAgICAgIHJldHVybiBuZXcgVGFibGVUb29scyggeyBcIm9EVFNldHRpbmdzXCI6IG9TZXR0aW5ncyB9ICk7XG5cdFx0ICogICAgICB9LFxuXHRcdCAqICAgICAgXCJjRmVhdHVyZVwiOiBcIlRcIlxuXHRcdCAqICAgIH0gKTtcblx0XHQgKi9cblx0XHRmZWF0dXJlOiBbXSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFJvdyBzZWFyY2hpbmcuXG5cdFx0ICogXG5cdFx0ICogVGhpcyBtZXRob2Qgb2Ygc2VhcmNoaW5nIGlzIGNvbXBsaW1lbnRhcnkgdG8gdGhlIGRlZmF1bHQgdHlwZSBiYXNlZFxuXHRcdCAqIHNlYXJjaGluZywgYW5kIGEgbG90IG1vcmUgY29tcHJlaGVuc2l2ZSBhcyBpdCBhbGxvd3MgeW91IGNvbXBsZXRlIGNvbnRyb2xcblx0XHQgKiBvdmVyIHRoZSBzZWFyY2hpbmcgbG9naWMuIEVhY2ggZWxlbWVudCBpbiB0aGlzIGFycmF5IGlzIGEgZnVuY3Rpb25cblx0XHQgKiAocGFyYW1ldGVycyBkZXNjcmliZWQgYmVsb3cpIHRoYXQgaXMgY2FsbGVkIGZvciBldmVyeSByb3cgaW4gdGhlIHRhYmxlLFxuXHRcdCAqIGFuZCB5b3VyIGxvZ2ljIGRlY2lkZXMgaWYgaXQgc2hvdWxkIGJlIGluY2x1ZGVkIGluIHRoZSBzZWFyY2hpbmcgZGF0YSBzZXRcblx0XHQgKiBvciBub3QuXG5cdFx0ICpcblx0XHQgKiBTZWFyY2hpbmcgZnVuY3Rpb25zIGhhdmUgdGhlIGZvbGxvd2luZyBpbnB1dCBwYXJhbWV0ZXJzOlxuXHRcdCAqXG5cdFx0ICogMS4gYHtvYmplY3R9YCBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdDogc2VlXG5cdFx0ICogICAge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfVxuXHRcdCAqIDIuIGB7YXJyYXl8b2JqZWN0fWAgRGF0YSBmb3IgdGhlIHJvdyB0byBiZSBwcm9jZXNzZWQgKHNhbWUgYXMgdGhlXG5cdFx0ICogICAgb3JpZ2luYWwgZm9ybWF0IHRoYXQgd2FzIHBhc3NlZCBpbiBhcyB0aGUgZGF0YSBzb3VyY2UsIG9yIGFuIGFycmF5XG5cdFx0ICogICAgZnJvbSBhIERPTSBkYXRhIHNvdXJjZVxuXHRcdCAqIDMuIGB7aW50fWAgUm93IGluZGV4ICh7QGxpbmsgRGF0YVRhYmxlLm1vZGVscy5vU2V0dGluZ3MuYW9EYXRhfSksIHdoaWNoXG5cdFx0ICogICAgY2FuIGJlIHVzZWZ1bCB0byByZXRyaWV2ZSB0aGUgYFRSYCBlbGVtZW50IGlmIHlvdSBuZWVkIERPTSBpbnRlcmFjdGlvbi5cblx0XHQgKlxuXHRcdCAqIEFuZCB0aGUgZm9sbG93aW5nIHJldHVybiBpcyBleHBlY3RlZDpcblx0XHQgKlxuXHRcdCAqICoge2Jvb2xlYW59IEluY2x1ZGUgdGhlIHJvdyBpbiB0aGUgc2VhcmNoZWQgcmVzdWx0IHNldCAodHJ1ZSkgb3Igbm90XG5cdFx0ICogICAoZmFsc2UpXG5cdFx0ICpcblx0XHQgKiBOb3RlIHRoYXQgYXMgd2l0aCB0aGUgbWFpbiBzZWFyY2ggYWJpbGl0eSBpbiBEYXRhVGFibGVzLCB0ZWNobmljYWxseSB0aGlzXG5cdFx0ICogaXMgXCJmaWx0ZXJpbmdcIiwgc2luY2UgaXQgaXMgc3VidHJhY3RpdmUuIEhvd2V2ZXIsIGZvciBjb25zaXN0ZW5jeSBpblxuXHRcdCAqIG5hbWluZyB3ZSBjYWxsIGl0IHNlYXJjaGluZyBoZXJlLlxuXHRcdCAqXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICogIEBkZWZhdWx0IFtdXG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBUaGUgZm9sbG93aW5nIGV4YW1wbGUgc2hvd3MgY3VzdG9tIHNlYXJjaCBiZWluZyBhcHBsaWVkIHRvIHRoZVxuXHRcdCAqICAgIC8vIGZvdXJ0aCBjb2x1bW4gKGkuZS4gdGhlIGRhdGFbM10gaW5kZXgpIGJhc2VkIG9uIHR3byBpbnB1dCB2YWx1ZXNcblx0XHQgKiAgICAvLyBmcm9tIHRoZSBlbmQtdXNlciwgbWF0Y2hpbmcgdGhlIGRhdGEgaW4gYSBjZXJ0YWluIHJhbmdlLlxuXHRcdCAqICAgICQuZm4uZGF0YVRhYmxlLmV4dC5zZWFyY2gucHVzaChcblx0XHQgKiAgICAgIGZ1bmN0aW9uKCBzZXR0aW5ncywgZGF0YSwgZGF0YUluZGV4ICkge1xuXHRcdCAqICAgICAgICB2YXIgbWluID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ21pbicpLnZhbHVlICogMTtcblx0XHQgKiAgICAgICAgdmFyIG1heCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtYXgnKS52YWx1ZSAqIDE7XG5cdFx0ICogICAgICAgIHZhciB2ZXJzaW9uID0gZGF0YVszXSA9PSBcIi1cIiA/IDAgOiBkYXRhWzNdKjE7XG5cdFx0ICpcblx0XHQgKiAgICAgICAgaWYgKCBtaW4gPT0gXCJcIiAmJiBtYXggPT0gXCJcIiApIHtcblx0XHQgKiAgICAgICAgICByZXR1cm4gdHJ1ZTtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgICBlbHNlIGlmICggbWluID09IFwiXCIgJiYgdmVyc2lvbiA8IG1heCApIHtcblx0XHQgKiAgICAgICAgICByZXR1cm4gdHJ1ZTtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgICBlbHNlIGlmICggbWluIDwgdmVyc2lvbiAmJiBcIlwiID09IG1heCApIHtcblx0XHQgKiAgICAgICAgICByZXR1cm4gdHJ1ZTtcblx0XHQgKiAgICAgICAgfVxuXHRcdCAqICAgICAgICBlbHNlIGlmICggbWluIDwgdmVyc2lvbiAmJiB2ZXJzaW9uIDwgbWF4ICkge1xuXHRcdCAqICAgICAgICAgIHJldHVybiB0cnVlO1xuXHRcdCAqICAgICAgICB9XG5cdFx0ICogICAgICAgIHJldHVybiBmYWxzZTtcblx0XHQgKiAgICAgIH1cblx0XHQgKiAgICApO1xuXHRcdCAqL1xuXHRcdHNlYXJjaDogW10sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBTZWxlY3RvciBleHRlbnNpb25zXG5cdFx0ICpcblx0XHQgKiBUaGUgYHNlbGVjdG9yYCBvcHRpb24gY2FuIGJlIHVzZWQgdG8gZXh0ZW5kIHRoZSBvcHRpb25zIGF2YWlsYWJsZSBmb3IgdGhlXG5cdFx0ICogc2VsZWN0b3IgbW9kaWZpZXIgb3B0aW9ucyAoYHNlbGVjdG9yLW1vZGlmaWVyYCBvYmplY3QgZGF0YSB0eXBlKSB0aGF0XG5cdFx0ICogZWFjaCBvZiB0aGUgdGhyZWUgYnVpbHQgaW4gc2VsZWN0b3IgdHlwZXMgb2ZmZXIgKHJvdywgY29sdW1uIGFuZCBjZWxsICtcblx0XHQgKiB0aGVpciBwbHVyYWwgY291bnRlcnBhcnRzKS4gRm9yIGV4YW1wbGUgdGhlIFNlbGVjdCBleHRlbnNpb24gdXNlcyB0aGlzXG5cdFx0ICogbWVjaGFuaXNtIHRvIHByb3ZpZGUgYW4gb3B0aW9uIHRvIHNlbGVjdCBvbmx5IHJvd3MsIGNvbHVtbnMgYW5kIGNlbGxzXG5cdFx0ICogdGhhdCBoYXZlIGJlZW4gbWFya2VkIGFzIHNlbGVjdGVkIGJ5IHRoZSBlbmQgdXNlciAoYHtzZWxlY3RlZDogdHJ1ZX1gKSxcblx0XHQgKiB3aGljaCBjYW4gYmUgdXNlZCBpbiBjb25qdW5jdGlvbiB3aXRoIHRoZSBleGlzdGluZyBidWlsdCBpbiBzZWxlY3RvclxuXHRcdCAqIG9wdGlvbnMuXG5cdFx0ICpcblx0XHQgKiBFYWNoIHByb3BlcnR5IGlzIGFuIGFycmF5IHRvIHdoaWNoIGZ1bmN0aW9ucyBjYW4gYmUgcHVzaGVkLiBUaGUgZnVuY3Rpb25zXG5cdFx0ICogdGFrZSB0aHJlZSBhdHRyaWJ1dGVzOlxuXHRcdCAqXG5cdFx0ICogKiBTZXR0aW5ncyBvYmplY3QgZm9yIHRoZSBob3N0IHRhYmxlXG5cdFx0ICogKiBPcHRpb25zIG9iamVjdCAoYHNlbGVjdG9yLW1vZGlmaWVyYCBvYmplY3QgdHlwZSlcblx0XHQgKiAqIEFycmF5IG9mIHNlbGVjdGVkIGl0ZW0gaW5kZXhlc1xuXHRcdCAqXG5cdFx0ICogVGhlIHJldHVybiBpcyBhbiBhcnJheSBvZiB0aGUgcmVzdWx0aW5nIGl0ZW0gaW5kZXhlcyBhZnRlciB0aGUgY3VzdG9tXG5cdFx0ICogc2VsZWN0b3IgaGFzIGJlZW4gYXBwbGllZC5cblx0XHQgKlxuXHRcdCAqICBAdHlwZSBvYmplY3Rcblx0XHQgKi9cblx0XHRzZWxlY3Rvcjoge1xuXHRcdFx0Y2VsbDogW10sXG5cdFx0XHRjb2x1bW46IFtdLFxuXHRcdFx0cm93OiBbXVxuXHRcdH0sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBJbnRlcm5hbCBmdW5jdGlvbnMsIGV4cG9zZWQgZm9yIHVzZWQgaW4gcGx1Zy1pbnMuXG5cdFx0ICogXG5cdFx0ICogUGxlYXNlIG5vdGUgdGhhdCB5b3Ugc2hvdWxkIG5vdCBuZWVkIHRvIHVzZSB0aGUgaW50ZXJuYWwgbWV0aG9kcyBmb3Jcblx0XHQgKiBhbnl0aGluZyBvdGhlciB0aGFuIGEgcGx1Zy1pbiAoYW5kIGV2ZW4gdGhlbiwgdHJ5IHRvIGF2b2lkIGlmIHBvc3NpYmxlKS5cblx0XHQgKiBUaGUgaW50ZXJuYWwgZnVuY3Rpb24gbWF5IGNoYW5nZSBiZXR3ZWVuIHJlbGVhc2VzLlxuXHRcdCAqXG5cdFx0ICogIEB0eXBlIG9iamVjdFxuXHRcdCAqICBAZGVmYXVsdCB7fVxuXHRcdCAqL1xuXHRcdGludGVybmFsOiB7fSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIExlZ2FjeSBjb25maWd1cmF0aW9uIG9wdGlvbnMuIEVuYWJsZSBhbmQgZGlzYWJsZSBsZWdhY3kgb3B0aW9ucyB0aGF0XG5cdFx0ICogYXJlIGF2YWlsYWJsZSBpbiBEYXRhVGFibGVzLlxuXHRcdCAqXG5cdFx0ICogIEB0eXBlIG9iamVjdFxuXHRcdCAqL1xuXHRcdGxlZ2FjeToge1xuXHRcdFx0LyoqXG5cdFx0XHQgKiBFbmFibGUgLyBkaXNhYmxlIERhdGFUYWJsZXMgMS45IGNvbXBhdGlibGUgc2VydmVyLXNpZGUgcHJvY2Vzc2luZ1xuXHRcdFx0ICogcmVxdWVzdHNcblx0XHRcdCAqXG5cdFx0XHQgKiAgQHR5cGUgYm9vbGVhblxuXHRcdFx0ICogIEBkZWZhdWx0IG51bGxcblx0XHRcdCAqL1xuXHRcdFx0YWpheDogbnVsbFxuXHRcdH0sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBQYWdpbmF0aW9uIHBsdWctaW4gbWV0aG9kcy5cblx0XHQgKiBcblx0XHQgKiBFYWNoIGVudHJ5IGluIHRoaXMgb2JqZWN0IGlzIGEgZnVuY3Rpb24gYW5kIGRlZmluZXMgd2hpY2ggYnV0dG9ucyBzaG91bGRcblx0XHQgKiBiZSBzaG93biBieSB0aGUgcGFnaW5hdGlvbiByZW5kZXJpbmcgbWV0aG9kIHRoYXQgaXMgdXNlZCBmb3IgdGhlIHRhYmxlOlxuXHRcdCAqIHtAbGluayBEYXRhVGFibGUuZXh0LnJlbmRlcmVyLnBhZ2VCdXR0b259LiBUaGUgcmVuZGVyZXIgYWRkcmVzc2VzIGhvdyB0aGVcblx0XHQgKiBidXR0b25zIGFyZSBkaXNwbGF5ZWQgaW4gdGhlIGRvY3VtZW50LCB3aGlsZSB0aGUgZnVuY3Rpb25zIGhlcmUgdGVsbCBpdFxuXHRcdCAqIHdoYXQgYnV0dG9ucyB0byBkaXNwbGF5LiBUaGlzIGlzIGRvbmUgYnkgcmV0dXJuaW5nIGFuIGFycmF5IG9mIGJ1dHRvblxuXHRcdCAqIGRlc2NyaXB0aW9ucyAod2hhdCBlYWNoIGJ1dHRvbiB3aWxsIGRvKS5cblx0XHQgKlxuXHRcdCAqIFBhZ2luYXRpb24gdHlwZXMgKHRoZSBmb3VyIGJ1aWx0IGluIG9wdGlvbnMgYW5kIGFueSBhZGRpdGlvbmFsIHBsdWctaW5cblx0XHQgKiBvcHRpb25zIGRlZmluZWQgaGVyZSkgY2FuIGJlIHVzZWQgdGhyb3VnaCB0aGUgYHBhZ2luYXRpb25UeXBlYFxuXHRcdCAqIGluaXRpYWxpc2F0aW9uIHBhcmFtZXRlci5cblx0XHQgKlxuXHRcdCAqIFRoZSBmdW5jdGlvbnMgZGVmaW5lZCB0YWtlIHR3byBwYXJhbWV0ZXJzOlxuXHRcdCAqXG5cdFx0ICogMS4gYHtpbnR9IHBhZ2VgIFRoZSBjdXJyZW50IHBhZ2UgaW5kZXhcblx0XHQgKiAyLiBge2ludH0gcGFnZXNgIFRoZSBudW1iZXIgb2YgcGFnZXMgaW4gdGhlIHRhYmxlXG5cdFx0ICpcblx0XHQgKiBFYWNoIGZ1bmN0aW9uIGlzIGV4cGVjdGVkIHRvIHJldHVybiBhbiBhcnJheSB3aGVyZSBlYWNoIGVsZW1lbnQgb2YgdGhlXG5cdFx0ICogYXJyYXkgY2FuIGJlIG9uZSBvZjpcblx0XHQgKlxuXHRcdCAqICogYGZpcnN0YCAtIEp1bXAgdG8gZmlyc3QgcGFnZSB3aGVuIGFjdGl2YXRlZFxuXHRcdCAqICogYGxhc3RgIC0gSnVtcCB0byBsYXN0IHBhZ2Ugd2hlbiBhY3RpdmF0ZWRcblx0XHQgKiAqIGBwcmV2aW91c2AgLSBTaG93IHByZXZpb3VzIHBhZ2Ugd2hlbiBhY3RpdmF0ZWRcblx0XHQgKiAqIGBuZXh0YCAtIFNob3cgbmV4dCBwYWdlIHdoZW4gYWN0aXZhdGVkXG5cdFx0ICogKiBge2ludH1gIC0gU2hvdyBwYWdlIG9mIHRoZSBpbmRleCBnaXZlblxuXHRcdCAqICogYHthcnJheX1gIC0gQSBuZXN0ZWQgYXJyYXkgY29udGFpbmluZyB0aGUgYWJvdmUgZWxlbWVudHMgdG8gYWRkIGFcblx0XHQgKiAgIGNvbnRhaW5pbmcgJ0RJVicgZWxlbWVudCAobWlnaHQgYmUgdXNlZnVsIGZvciBzdHlsaW5nKS5cblx0XHQgKlxuXHRcdCAqIE5vdGUgdGhhdCBEYXRhVGFibGVzIHYxLjktIHVzZWQgdGhpcyBvYmplY3Qgc2xpZ2h0bHkgZGlmZmVyZW50bHkgd2hlcmVieVxuXHRcdCAqIGFuIG9iamVjdCB3aXRoIHR3byBmdW5jdGlvbnMgd291bGQgYmUgZGVmaW5lZCBmb3IgZWFjaCBwbHVnLWluLiBUaGF0XG5cdFx0ICogYWJpbGl0eSBpcyBzdGlsbCBzdXBwb3J0ZWQgYnkgRGF0YVRhYmxlcyAxLjEwKyB0byBwcm92aWRlIGJhY2t3YXJkc1xuXHRcdCAqIGNvbXBhdGliaWxpdHksIGJ1dCB0aGlzIG9wdGlvbiBvZiB1c2UgaXMgbm93IGRlY3JlbWVudGVkIGFuZCBubyBsb25nZXJcblx0XHQgKiBkb2N1bWVudGVkIGluIERhdGFUYWJsZXMgMS4xMCsuXG5cdFx0ICpcblx0XHQgKiAgQHR5cGUgb2JqZWN0XG5cdFx0ICogIEBkZWZhdWx0IHt9XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBTaG93IHByZXZpb3VzLCBuZXh0IGFuZCBjdXJyZW50IHBhZ2UgYnV0dG9ucyBvbmx5XG5cdFx0ICogICAgJC5mbi5kYXRhVGFibGVFeHQub1BhZ2luYXRpb24uY3VycmVudCA9IGZ1bmN0aW9uICggcGFnZSwgcGFnZXMgKSB7XG5cdFx0ICogICAgICByZXR1cm4gWyAncHJldmlvdXMnLCBwYWdlLCAnbmV4dCcgXTtcblx0XHQgKiAgICB9O1xuXHRcdCAqL1xuXHRcdHBhZ2VyOiB7fSxcblx0XG5cdFxuXHRcdHJlbmRlcmVyOiB7XG5cdFx0XHRwYWdlQnV0dG9uOiB7fSxcblx0XHRcdGhlYWRlcjoge31cblx0XHR9LFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogT3JkZXJpbmcgcGx1Zy1pbnMgLSBjdXN0b20gZGF0YSBzb3VyY2Vcblx0XHQgKiBcblx0XHQgKiBUaGUgZXh0ZW5zaW9uIG9wdGlvbnMgZm9yIG9yZGVyaW5nIG9mIGRhdGEgYXZhaWxhYmxlIGhlcmUgaXMgY29tcGxpbWVudGFyeVxuXHRcdCAqIHRvIHRoZSBkZWZhdWx0IHR5cGUgYmFzZWQgb3JkZXJpbmcgdGhhdCBEYXRhVGFibGVzIHR5cGljYWxseSB1c2VzLiBJdFxuXHRcdCAqIGFsbG93cyBtdWNoIGdyZWF0ZXIgY29udHJvbCBvdmVyIHRoZSB0aGUgZGF0YSB0aGF0IGlzIGJlaW5nIHVzZWQgdG9cblx0XHQgKiBvcmRlciBhIGNvbHVtbiwgYnV0IGlzIG5lY2Vzc2FyaWx5IHRoZXJlZm9yZSBtb3JlIGNvbXBsZXguXG5cdFx0ICogXG5cdFx0ICogVGhpcyB0eXBlIG9mIG9yZGVyaW5nIGlzIHVzZWZ1bCBpZiB5b3Ugd2FudCB0byBkbyBvcmRlcmluZyBiYXNlZCBvbiBkYXRhXG5cdFx0ICogbGl2ZSBmcm9tIHRoZSBET00gKGZvciBleGFtcGxlIHRoZSBjb250ZW50cyBvZiBhbiAnaW5wdXQnIGVsZW1lbnQpIHJhdGhlclxuXHRcdCAqIHRoYW4ganVzdCB0aGUgc3RhdGljIHN0cmluZyB0aGF0IERhdGFUYWJsZXMga25vd3Mgb2YuXG5cdFx0ICogXG5cdFx0ICogVGhlIHdheSB0aGVzZSBwbHVnLWlucyB3b3JrIGlzIHRoYXQgeW91IGNyZWF0ZSBhbiBhcnJheSBvZiB0aGUgdmFsdWVzIHlvdVxuXHRcdCAqIHdpc2ggdG8gYmUgb3JkZXJpbmcgZm9yIHRoZSBjb2x1bW4gaW4gcXVlc3Rpb24gYW5kIHRoZW4gcmV0dXJuIHRoYXRcblx0XHQgKiBhcnJheS4gVGhlIGRhdGEgaW4gdGhlIGFycmF5IG11Y2ggYmUgaW4gdGhlIGluZGV4IG9yZGVyIG9mIHRoZSByb3dzIGluXG5cdFx0ICogdGhlIHRhYmxlIChub3QgdGhlIGN1cnJlbnRseSBvcmRlcmluZyBvcmRlciEpLiBXaGljaCBvcmRlciBkYXRhIGdhdGhlcmluZ1xuXHRcdCAqIGZ1bmN0aW9uIGlzIHJ1biBoZXJlIGRlcGVuZHMgb24gdGhlIGBkdC1pbml0IGNvbHVtbnMub3JkZXJEYXRhVHlwZWBcblx0XHQgKiBwYXJhbWV0ZXIgdGhhdCBpcyB1c2VkIGZvciB0aGUgY29sdW1uIChpZiBhbnkpLlxuXHRcdCAqXG5cdFx0ICogVGhlIGZ1bmN0aW9ucyBkZWZpbmVkIHRha2UgdHdvIHBhcmFtZXRlcnM6XG5cdFx0ICpcblx0XHQgKiAxLiBge29iamVjdH1gIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0OiBzZWVcblx0XHQgKiAgICB7QGxpbmsgRGF0YVRhYmxlLm1vZGVscy5vU2V0dGluZ3N9XG5cdFx0ICogMi4gYHtpbnR9YCBUYXJnZXQgY29sdW1uIGluZGV4XG5cdFx0ICpcblx0XHQgKiBFYWNoIGZ1bmN0aW9uIGlzIGV4cGVjdGVkIHRvIHJldHVybiBhbiBhcnJheTpcblx0XHQgKlxuXHRcdCAqICogYHthcnJheX1gIERhdGEgZm9yIHRoZSBjb2x1bW4gdG8gYmUgb3JkZXJpbmcgdXBvblxuXHRcdCAqXG5cdFx0ICogIEB0eXBlIGFycmF5XG5cdFx0ICpcblx0XHQgKiAgQGV4YW1wbGVcblx0XHQgKiAgICAvLyBPcmRlcmluZyB1c2luZyBgaW5wdXRgIG5vZGUgdmFsdWVzXG5cdFx0ICogICAgJC5mbi5kYXRhVGFibGUuZXh0Lm9yZGVyWydkb20tdGV4dCddID0gZnVuY3Rpb24gICggc2V0dGluZ3MsIGNvbCApXG5cdFx0ICogICAge1xuXHRcdCAqICAgICAgcmV0dXJuIHRoaXMuYXBpKCkuY29sdW1uKCBjb2wsIHtvcmRlcjonaW5kZXgnfSApLm5vZGVzKCkubWFwKCBmdW5jdGlvbiAoIHRkLCBpICkge1xuXHRcdCAqICAgICAgICByZXR1cm4gJCgnaW5wdXQnLCB0ZCkudmFsKCk7XG5cdFx0ICogICAgICB9ICk7XG5cdFx0ICogICAgfVxuXHRcdCAqL1xuXHRcdG9yZGVyOiB7fSxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIFR5cGUgYmFzZWQgcGx1Zy1pbnMuXG5cdFx0ICpcblx0XHQgKiBFYWNoIGNvbHVtbiBpbiBEYXRhVGFibGVzIGhhcyBhIHR5cGUgYXNzaWduZWQgdG8gaXQsIGVpdGhlciBieSBhdXRvbWF0aWNcblx0XHQgKiBkZXRlY3Rpb24gb3IgYnkgZGlyZWN0IGFzc2lnbm1lbnQgdXNpbmcgdGhlIGB0eXBlYCBvcHRpb24gZm9yIHRoZSBjb2x1bW4uXG5cdFx0ICogVGhlIHR5cGUgb2YgYSBjb2x1bW4gd2lsbCBlZmZlY3QgaG93IGl0IGlzIG9yZGVyaW5nIGFuZCBzZWFyY2ggKHBsdWctaW5zXG5cdFx0ICogY2FuIGFsc28gbWFrZSB1c2Ugb2YgdGhlIGNvbHVtbiB0eXBlIGlmIHJlcXVpcmVkKS5cblx0XHQgKlxuXHRcdCAqIEBuYW1lc3BhY2Vcblx0XHQgKi9cblx0XHR0eXBlOiB7XG5cdFx0XHQvKipcblx0XHRcdCAqIFR5cGUgZGV0ZWN0aW9uIGZ1bmN0aW9ucy5cblx0XHRcdCAqXG5cdFx0XHQgKiBUaGUgZnVuY3Rpb25zIGRlZmluZWQgaW4gdGhpcyBvYmplY3QgYXJlIHVzZWQgdG8gYXV0b21hdGljYWxseSBkZXRlY3Rcblx0XHRcdCAqIGEgY29sdW1uJ3MgdHlwZSwgbWFraW5nIGluaXRpYWxpc2F0aW9uIG9mIERhdGFUYWJsZXMgc3VwZXIgZWFzeSwgZXZlblxuXHRcdFx0ICogd2hlbiBjb21wbGV4IGRhdGEgaXMgaW4gdGhlIHRhYmxlLlxuXHRcdFx0ICpcblx0XHRcdCAqIFRoZSBmdW5jdGlvbnMgZGVmaW5lZCB0YWtlIHR3byBwYXJhbWV0ZXJzOlxuXHRcdFx0ICpcblx0XHQgICAgICogIDEuIGB7Kn1gIERhdGEgZnJvbSB0aGUgY29sdW1uIGNlbGwgdG8gYmUgYW5hbHlzZWRcblx0XHQgICAgICogIDIuIGB7c2V0dGluZ3N9YCBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdC4gVGhpcyBjYW4gYmUgdXNlZCB0b1xuXHRcdCAgICAgKiAgICAgcGVyZm9ybSBjb250ZXh0IHNwZWNpZmljIHR5cGUgZGV0ZWN0aW9uIC0gZm9yIGV4YW1wbGUgZGV0ZWN0aW9uXG5cdFx0ICAgICAqICAgICBiYXNlZCBvbiBsYW5ndWFnZSBzZXR0aW5ncyBzdWNoIGFzIHVzaW5nIGEgY29tbWEgZm9yIGEgZGVjaW1hbFxuXHRcdCAgICAgKiAgICAgcGxhY2UuIEdlbmVyYWxseSBzcGVha2luZyB0aGUgb3B0aW9ucyBmcm9tIHRoZSBzZXR0aW5ncyB3aWxsIG5vdFxuXHRcdCAgICAgKiAgICAgYmUgcmVxdWlyZWRcblx0XHRcdCAqXG5cdFx0XHQgKiBFYWNoIGZ1bmN0aW9uIGlzIGV4cGVjdGVkIHRvIHJldHVybjpcblx0XHRcdCAqXG5cdFx0XHQgKiAqIGB7c3RyaW5nfG51bGx9YCBEYXRhIHR5cGUgZGV0ZWN0ZWQsIG9yIG51bGwgaWYgdW5rbm93biAoYW5kIHRodXNcblx0XHRcdCAqICAgcGFzcyBpdCBvbiB0byB0aGUgb3RoZXIgdHlwZSBkZXRlY3Rpb24gZnVuY3Rpb25zLlxuXHRcdFx0ICpcblx0XHRcdCAqICBAdHlwZSBhcnJheVxuXHRcdFx0ICpcblx0XHRcdCAqICBAZXhhbXBsZVxuXHRcdFx0ICogICAgLy8gQ3VycmVuY3kgdHlwZSBkZXRlY3Rpb24gcGx1Zy1pbjpcblx0XHRcdCAqICAgICQuZm4uZGF0YVRhYmxlLmV4dC50eXBlLmRldGVjdC5wdXNoKFxuXHRcdFx0ICogICAgICBmdW5jdGlvbiAoIGRhdGEsIHNldHRpbmdzICkge1xuXHRcdFx0ICogICAgICAgIC8vIENoZWNrIHRoZSBudW1lcmljIHBhcnRcblx0XHRcdCAqICAgICAgICBpZiAoICEgJC5pc051bWVyaWMoIGRhdGEuc3Vic3RyaW5nKDEpICkgKSB7XG5cdFx0XHQgKiAgICAgICAgICByZXR1cm4gbnVsbDtcblx0XHRcdCAqICAgICAgICB9XG5cdFx0XHQgKlxuXHRcdFx0ICogICAgICAgIC8vIENoZWNrIHByZWZpeGVkIGJ5IGN1cnJlbmN5XG5cdFx0XHQgKiAgICAgICAgaWYgKCBkYXRhLmNoYXJBdCgwKSA9PSAnJCcgfHwgZGF0YS5jaGFyQXQoMCkgPT0gJyZwb3VuZDsnICkge1xuXHRcdFx0ICogICAgICAgICAgcmV0dXJuICdjdXJyZW5jeSc7XG5cdFx0XHQgKiAgICAgICAgfVxuXHRcdFx0ICogICAgICAgIHJldHVybiBudWxsO1xuXHRcdFx0ICogICAgICB9XG5cdFx0XHQgKiAgICApO1xuXHRcdFx0ICovXG5cdFx0XHRkZXRlY3Q6IFtdLFxuXHRcblx0XG5cdFx0XHQvKipcblx0XHRcdCAqIFR5cGUgYmFzZWQgc2VhcmNoIGZvcm1hdHRpbmcuXG5cdFx0XHQgKlxuXHRcdFx0ICogVGhlIHR5cGUgYmFzZWQgc2VhcmNoaW5nIGZ1bmN0aW9ucyBjYW4gYmUgdXNlZCB0byBwcmUtZm9ybWF0IHRoZVxuXHRcdFx0ICogZGF0YSB0byBiZSBzZWFyY2ggb24uIEZvciBleGFtcGxlLCBpdCBjYW4gYmUgdXNlZCB0byBzdHJpcCBIVE1MXG5cdFx0XHQgKiB0YWdzIG9yIHRvIGRlLWZvcm1hdCB0ZWxlcGhvbmUgbnVtYmVycyBmb3IgbnVtZXJpYyBvbmx5IHNlYXJjaGluZy5cblx0XHRcdCAqXG5cdFx0XHQgKiBOb3RlIHRoYXQgaXMgYSBzZWFyY2ggaXMgbm90IGRlZmluZWQgZm9yIGEgY29sdW1uIG9mIGEgZ2l2ZW4gdHlwZSxcblx0XHRcdCAqIG5vIHNlYXJjaCBmb3JtYXR0aW5nIHdpbGwgYmUgcGVyZm9ybWVkLlxuXHRcdFx0ICogXG5cdFx0XHQgKiBQcmUtcHJvY2Vzc2luZyBvZiBzZWFyY2hpbmcgZGF0YSBwbHVnLWlucyAtIFdoZW4geW91IGFzc2lnbiB0aGUgc1R5cGVcblx0XHRcdCAqIGZvciBhIGNvbHVtbiAob3IgaGF2ZSBpdCBhdXRvbWF0aWNhbGx5IGRldGVjdGVkIGZvciB5b3UgYnkgRGF0YVRhYmxlc1xuXHRcdFx0ICogb3IgYSB0eXBlIGRldGVjdGlvbiBwbHVnLWluKSwgeW91IHdpbGwgdHlwaWNhbGx5IGJlIHVzaW5nIHRoaXMgZm9yXG5cdFx0XHQgKiBjdXN0b20gc29ydGluZywgYnV0IGl0IGNhbiBhbHNvIGJlIHVzZWQgdG8gcHJvdmlkZSBjdXN0b20gc2VhcmNoaW5nXG5cdFx0XHQgKiBieSBhbGxvd2luZyB5b3UgdG8gcHJlLXByb2Nlc3NpbmcgdGhlIGRhdGEgYW5kIHJldHVybmluZyB0aGUgZGF0YSBpblxuXHRcdFx0ICogdGhlIGZvcm1hdCB0aGF0IHNob3VsZCBiZSBzZWFyY2hlZCB1cG9uLiBUaGlzIGlzIGRvbmUgYnkgYWRkaW5nXG5cdFx0XHQgKiBmdW5jdGlvbnMgdGhpcyBvYmplY3Qgd2l0aCBhIHBhcmFtZXRlciBuYW1lIHdoaWNoIG1hdGNoZXMgdGhlIHNUeXBlXG5cdFx0XHQgKiBmb3IgdGhhdCB0YXJnZXQgY29sdW1uLiBUaGlzIGlzIHRoZSBjb3JvbGxhcnkgb2YgPGk+YWZuU29ydERhdGE8L2k+XG5cdFx0XHQgKiBmb3Igc2VhcmNoaW5nIGRhdGEuXG5cdFx0XHQgKlxuXHRcdFx0ICogVGhlIGZ1bmN0aW9ucyBkZWZpbmVkIHRha2UgYSBzaW5nbGUgcGFyYW1ldGVyOlxuXHRcdFx0ICpcblx0XHQgICAgICogIDEuIGB7Kn1gIERhdGEgZnJvbSB0aGUgY29sdW1uIGNlbGwgdG8gYmUgcHJlcGFyZWQgZm9yIHNlYXJjaGluZ1xuXHRcdFx0ICpcblx0XHRcdCAqIEVhY2ggZnVuY3Rpb24gaXMgZXhwZWN0ZWQgdG8gcmV0dXJuOlxuXHRcdFx0ICpcblx0XHRcdCAqICogYHtzdHJpbmd8bnVsbH1gIEZvcm1hdHRlZCBzdHJpbmcgdGhhdCB3aWxsIGJlIHVzZWQgZm9yIHRoZSBzZWFyY2hpbmcuXG5cdFx0XHQgKlxuXHRcdFx0ICogIEB0eXBlIG9iamVjdFxuXHRcdFx0ICogIEBkZWZhdWx0IHt9XG5cdFx0XHQgKlxuXHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHQgKiAgICAkLmZuLmRhdGFUYWJsZS5leHQudHlwZS5zZWFyY2hbJ3RpdGxlLW51bWVyaWMnXSA9IGZ1bmN0aW9uICggZCApIHtcblx0XHRcdCAqICAgICAgcmV0dXJuIGQucmVwbGFjZSgvXFxuL2csXCIgXCIpLnJlcGxhY2UoIC88Lio/Pi9nLCBcIlwiICk7XG5cdFx0XHQgKiAgICB9XG5cdFx0XHQgKi9cblx0XHRcdHNlYXJjaDoge30sXG5cdFxuXHRcblx0XHRcdC8qKlxuXHRcdFx0ICogVHlwZSBiYXNlZCBvcmRlcmluZy5cblx0XHRcdCAqXG5cdFx0XHQgKiBUaGUgY29sdW1uIHR5cGUgdGVsbHMgRGF0YVRhYmxlcyB3aGF0IG9yZGVyaW5nIHRvIGFwcGx5IHRvIHRoZSB0YWJsZVxuXHRcdFx0ICogd2hlbiBhIGNvbHVtbiBpcyBzb3J0ZWQgdXBvbi4gVGhlIG9yZGVyIGZvciBlYWNoIHR5cGUgdGhhdCBpcyBkZWZpbmVkLFxuXHRcdFx0ICogaXMgZGVmaW5lZCBieSB0aGUgZnVuY3Rpb25zIGF2YWlsYWJsZSBpbiB0aGlzIG9iamVjdC5cblx0XHRcdCAqXG5cdFx0XHQgKiBFYWNoIG9yZGVyaW5nIG9wdGlvbiBjYW4gYmUgZGVzY3JpYmVkIGJ5IHRocmVlIHByb3BlcnRpZXMgYWRkZWQgdG9cblx0XHRcdCAqIHRoaXMgb2JqZWN0OlxuXHRcdFx0ICpcblx0XHRcdCAqICogYHt0eXBlfS1wcmVgIC0gUHJlLWZvcm1hdHRpbmcgZnVuY3Rpb25cblx0XHRcdCAqICogYHt0eXBlfS1hc2NgIC0gQXNjZW5kaW5nIG9yZGVyIGZ1bmN0aW9uXG5cdFx0XHQgKiAqIGB7dHlwZX0tZGVzY2AgLSBEZXNjZW5kaW5nIG9yZGVyIGZ1bmN0aW9uXG5cdFx0XHQgKlxuXHRcdFx0ICogQWxsIHRocmVlIGNhbiBiZSB1c2VkIHRvZ2V0aGVyLCBvbmx5IGB7dHlwZX0tcHJlYCBvciBvbmx5XG5cdFx0XHQgKiBge3R5cGV9LWFzY2AgYW5kIGB7dHlwZX0tZGVzY2AgdG9nZXRoZXIuIEl0IGlzIGdlbmVyYWxseSByZWNvbW1lbmRlZFxuXHRcdFx0ICogdGhhdCBvbmx5IGB7dHlwZX0tcHJlYCBpcyB1c2VkLCBhcyB0aGlzIHByb3ZpZGVzIHRoZSBvcHRpbWFsXG5cdFx0XHQgKiBpbXBsZW1lbnRhdGlvbiBpbiB0ZXJtcyBvZiBzcGVlZCwgYWx0aG91Z2ggdGhlIG90aGVycyBhcmUgcHJvdmlkZWRcblx0XHRcdCAqIGZvciBjb21wYXRpYmlsaXR5IHdpdGggZXhpc3RpbmcgSmF2YXNjcmlwdCBzb3J0IGZ1bmN0aW9ucy5cblx0XHRcdCAqXG5cdFx0XHQgKiBge3R5cGV9LXByZWA6IEZ1bmN0aW9ucyBkZWZpbmVkIHRha2UgYSBzaW5nbGUgcGFyYW1ldGVyOlxuXHRcdFx0ICpcblx0XHQgICAgICogIDEuIGB7Kn1gIERhdGEgZnJvbSB0aGUgY29sdW1uIGNlbGwgdG8gYmUgcHJlcGFyZWQgZm9yIG9yZGVyaW5nXG5cdFx0XHQgKlxuXHRcdFx0ICogQW5kIHJldHVybjpcblx0XHRcdCAqXG5cdFx0XHQgKiAqIGB7Kn1gIERhdGEgdG8gYmUgc29ydGVkIHVwb25cblx0XHRcdCAqXG5cdFx0XHQgKiBge3R5cGV9LWFzY2AgYW5kIGB7dHlwZX0tZGVzY2A6IEZ1bmN0aW9ucyBhcmUgdHlwaWNhbCBKYXZhc2NyaXB0IHNvcnRcblx0XHRcdCAqIGZ1bmN0aW9ucywgdGFraW5nIHR3byBwYXJhbWV0ZXJzOlxuXHRcdFx0ICpcblx0XHQgICAgICogIDEuIGB7Kn1gIERhdGEgdG8gY29tcGFyZSB0byB0aGUgc2Vjb25kIHBhcmFtZXRlclxuXHRcdCAgICAgKiAgMi4gYHsqfWAgRGF0YSB0byBjb21wYXJlIHRvIHRoZSBmaXJzdCBwYXJhbWV0ZXJcblx0XHRcdCAqXG5cdFx0XHQgKiBBbmQgcmV0dXJuaW5nOlxuXHRcdFx0ICpcblx0XHRcdCAqICogYHsqfWAgT3JkZXJpbmcgbWF0Y2g6IDwwIGlmIGZpcnN0IHBhcmFtZXRlciBzaG91bGQgYmUgc29ydGVkIGxvd2VyXG5cdFx0XHQgKiAgIHRoYW4gdGhlIHNlY29uZCBwYXJhbWV0ZXIsID09PTAgaWYgdGhlIHR3byBwYXJhbWV0ZXJzIGFyZSBlcXVhbCBhbmRcblx0XHRcdCAqICAgPjAgaWYgdGhlIGZpcnN0IHBhcmFtZXRlciBzaG91bGQgYmUgc29ydGVkIGhlaWdodCB0aGFuIHRoZSBzZWNvbmRcblx0XHRcdCAqICAgcGFyYW1ldGVyLlxuXHRcdFx0ICogXG5cdFx0XHQgKiAgQHR5cGUgb2JqZWN0XG5cdFx0XHQgKiAgQGRlZmF1bHQge31cblx0XHRcdCAqXG5cdFx0XHQgKiAgQGV4YW1wbGVcblx0XHRcdCAqICAgIC8vIE51bWVyaWMgb3JkZXJpbmcgb2YgZm9ybWF0dGVkIG51bWJlcnMgd2l0aCBhIHByZS1mb3JtYXR0ZXJcblx0XHRcdCAqICAgICQuZXh0ZW5kKCAkLmZuLmRhdGFUYWJsZS5leHQudHlwZS5vcmRlciwge1xuXHRcdFx0ICogICAgICBcInN0cmluZy1wcmVcIjogZnVuY3Rpb24oeCkge1xuXHRcdFx0ICogICAgICAgIGEgPSAoYSA9PT0gXCItXCIgfHwgYSA9PT0gXCJcIikgPyAwIDogYS5yZXBsYWNlKCAvW15cXGRcXC1cXC5dL2csIFwiXCIgKTtcblx0XHRcdCAqICAgICAgICByZXR1cm4gcGFyc2VGbG9hdCggYSApO1xuXHRcdFx0ICogICAgICB9XG5cdFx0XHQgKiAgICB9ICk7XG5cdFx0XHQgKlxuXHRcdFx0ICogIEBleGFtcGxlXG5cdFx0XHQgKiAgICAvLyBDYXNlLXNlbnNpdGl2ZSBzdHJpbmcgb3JkZXJpbmcsIHdpdGggbm8gcHJlLWZvcm1hdHRpbmcgbWV0aG9kXG5cdFx0XHQgKiAgICAkLmV4dGVuZCggJC5mbi5kYXRhVGFibGUuZXh0Lm9yZGVyLCB7XG5cdFx0XHQgKiAgICAgIFwic3RyaW5nLWNhc2UtYXNjXCI6IGZ1bmN0aW9uKHgseSkge1xuXHRcdFx0ICogICAgICAgIHJldHVybiAoKHggPCB5KSA/IC0xIDogKCh4ID4geSkgPyAxIDogMCkpO1xuXHRcdFx0ICogICAgICB9LFxuXHRcdFx0ICogICAgICBcInN0cmluZy1jYXNlLWRlc2NcIjogZnVuY3Rpb24oeCx5KSB7XG5cdFx0XHQgKiAgICAgICAgcmV0dXJuICgoeCA8IHkpID8gMSA6ICgoeCA+IHkpID8gLTEgOiAwKSk7XG5cdFx0XHQgKiAgICAgIH1cblx0XHRcdCAqICAgIH0gKTtcblx0XHRcdCAqL1xuXHRcdFx0b3JkZXI6IHt9XG5cdFx0fSxcblx0XG5cdFx0LyoqXG5cdFx0ICogVW5pcXVlIERhdGFUYWJsZXMgaW5zdGFuY2UgY291bnRlclxuXHRcdCAqXG5cdFx0ICogQHR5cGUgaW50XG5cdFx0ICogQHByaXZhdGVcblx0XHQgKi9cblx0XHRfdW5pcXVlOiAwLFxuXHRcblx0XG5cdFx0Ly9cblx0XHQvLyBEZXByZWNpYXRlZFxuXHRcdC8vIFRoZSBmb2xsb3dpbmcgcHJvcGVydGllcyBhcmUgcmV0YWluZWQgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmxpdHkgb25seS5cblx0XHQvLyBUaGUgc2hvdWxkIG5vdCBiZSB1c2VkIGluIG5ldyBwcm9qZWN0cyBhbmQgd2lsbCBiZSByZW1vdmVkIGluIGEgZnV0dXJlXG5cdFx0Ly8gdmVyc2lvblxuXHRcdC8vXG5cdFxuXHRcdC8qKlxuXHRcdCAqIFZlcnNpb24gY2hlY2sgZnVuY3Rpb24uXG5cdFx0ICogIEB0eXBlIGZ1bmN0aW9uXG5cdFx0ICogIEBkZXByZWNpYXRlZCBTaW5jZSAxLjEwXG5cdFx0ICovXG5cdFx0Zm5WZXJzaW9uQ2hlY2s6IERhdGFUYWJsZS5mblZlcnNpb25DaGVjayxcblx0XG5cdFxuXHRcdC8qKlxuXHRcdCAqIEluZGV4IGZvciB3aGF0ICd0aGlzJyBpbmRleCBBUEkgZnVuY3Rpb25zIHNob3VsZCB1c2Vcblx0XHQgKiAgQHR5cGUgaW50XG5cdFx0ICogIEBkZXByZWNhdGVkIFNpbmNlIHYxLjEwXG5cdFx0ICovXG5cdFx0aUFwaUluZGV4OiAwLFxuXHRcblx0XG5cdFx0LyoqXG5cdFx0ICogalF1ZXJ5IFVJIGNsYXNzIGNvbnRhaW5lclxuXHRcdCAqICBAdHlwZSBvYmplY3Rcblx0XHQgKiAgQGRlcHJlY2F0ZWQgU2luY2UgdjEuMTBcblx0XHQgKi9cblx0XHRvSlVJQ2xhc3Nlczoge30sXG5cdFxuXHRcblx0XHQvKipcblx0XHQgKiBTb2Z0d2FyZSB2ZXJzaW9uXG5cdFx0ICogIEB0eXBlIHN0cmluZ1xuXHRcdCAqICBAZGVwcmVjYXRlZCBTaW5jZSB2MS4xMFxuXHRcdCAqL1xuXHRcdHNWZXJzaW9uOiBEYXRhVGFibGUudmVyc2lvblxuXHR9O1xuXHRcblx0XG5cdC8vXG5cdC8vIEJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LiBBbGlhcyB0byBwcmUgMS4xMCBIdW5nYXJpYW4gbm90YXRpb24gY291bnRlciBwYXJ0c1xuXHQvL1xuXHQkLmV4dGVuZCggX2V4dCwge1xuXHRcdGFmbkZpbHRlcmluZzogX2V4dC5zZWFyY2gsXG5cdFx0YVR5cGVzOiAgICAgICBfZXh0LnR5cGUuZGV0ZWN0LFxuXHRcdG9mblNlYXJjaDogICAgX2V4dC50eXBlLnNlYXJjaCxcblx0XHRvU29ydDogICAgICAgIF9leHQudHlwZS5vcmRlcixcblx0XHRhZm5Tb3J0RGF0YTogIF9leHQub3JkZXIsXG5cdFx0YW9GZWF0dXJlczogICBfZXh0LmZlYXR1cmUsXG5cdFx0b0FwaTogICAgICAgICBfZXh0LmludGVybmFsLFxuXHRcdG9TdGRDbGFzc2VzOiAgX2V4dC5jbGFzc2VzLFxuXHRcdG9QYWdpbmF0aW9uOiAgX2V4dC5wYWdlclxuXHR9ICk7XG5cdFxuXHRcblx0JC5leHRlbmQoIERhdGFUYWJsZS5leHQuY2xhc3Nlcywge1xuXHRcdFwic1RhYmxlXCI6IFwiZGF0YVRhYmxlXCIsXG5cdFx0XCJzTm9Gb290ZXJcIjogXCJuby1mb290ZXJcIixcblx0XG5cdFx0LyogUGFnaW5nIGJ1dHRvbnMgKi9cblx0XHRcInNQYWdlQnV0dG9uXCI6IFwicGFnaW5hdGVfYnV0dG9uXCIsXG5cdFx0XCJzUGFnZUJ1dHRvbkFjdGl2ZVwiOiBcImN1cnJlbnRcIixcblx0XHRcInNQYWdlQnV0dG9uRGlzYWJsZWRcIjogXCJkaXNhYmxlZFwiLFxuXHRcblx0XHQvKiBTdHJpcGluZyBjbGFzc2VzICovXG5cdFx0XCJzU3RyaXBlT2RkXCI6IFwib2RkXCIsXG5cdFx0XCJzU3RyaXBlRXZlblwiOiBcImV2ZW5cIixcblx0XG5cdFx0LyogRW1wdHkgcm93ICovXG5cdFx0XCJzUm93RW1wdHlcIjogXCJkYXRhVGFibGVzX2VtcHR5XCIsXG5cdFxuXHRcdC8qIEZlYXR1cmVzICovXG5cdFx0XCJzV3JhcHBlclwiOiBcImRhdGFUYWJsZXNfd3JhcHBlclwiLFxuXHRcdFwic0ZpbHRlclwiOiBcImRhdGFUYWJsZXNfZmlsdGVyXCIsXG5cdFx0XCJzSW5mb1wiOiBcImRhdGFUYWJsZXNfaW5mb1wiLFxuXHRcdFwic1BhZ2luZ1wiOiBcImRhdGFUYWJsZXNfcGFnaW5hdGUgcGFnaW5nX1wiLCAvKiBOb3RlIHRoYXQgdGhlIHR5cGUgaXMgcG9zdGZpeGVkICovXG5cdFx0XCJzTGVuZ3RoXCI6IFwiZGF0YVRhYmxlc19sZW5ndGhcIixcblx0XHRcInNQcm9jZXNzaW5nXCI6IFwiZGF0YVRhYmxlc19wcm9jZXNzaW5nXCIsXG5cdFxuXHRcdC8qIFNvcnRpbmcgKi9cblx0XHRcInNTb3J0QXNjXCI6IFwic29ydGluZ19hc2NcIixcblx0XHRcInNTb3J0RGVzY1wiOiBcInNvcnRpbmdfZGVzY1wiLFxuXHRcdFwic1NvcnRhYmxlXCI6IFwic29ydGluZ1wiLCAvKiBTb3J0YWJsZSBpbiBib3RoIGRpcmVjdGlvbnMgKi9cblx0XHRcInNTb3J0YWJsZUFzY1wiOiBcInNvcnRpbmdfYXNjX2Rpc2FibGVkXCIsXG5cdFx0XCJzU29ydGFibGVEZXNjXCI6IFwic29ydGluZ19kZXNjX2Rpc2FibGVkXCIsXG5cdFx0XCJzU29ydGFibGVOb25lXCI6IFwic29ydGluZ19kaXNhYmxlZFwiLFxuXHRcdFwic1NvcnRDb2x1bW5cIjogXCJzb3J0aW5nX1wiLCAvKiBOb3RlIHRoYXQgYW4gaW50IGlzIHBvc3RmaXhlZCBmb3IgdGhlIHNvcnRpbmcgb3JkZXIgKi9cblx0XG5cdFx0LyogRmlsdGVyaW5nICovXG5cdFx0XCJzRmlsdGVySW5wdXRcIjogXCJcIixcblx0XG5cdFx0LyogUGFnZSBsZW5ndGggKi9cblx0XHRcInNMZW5ndGhTZWxlY3RcIjogXCJcIixcblx0XG5cdFx0LyogU2Nyb2xsaW5nICovXG5cdFx0XCJzU2Nyb2xsV3JhcHBlclwiOiBcImRhdGFUYWJsZXNfc2Nyb2xsXCIsXG5cdFx0XCJzU2Nyb2xsSGVhZFwiOiBcImRhdGFUYWJsZXNfc2Nyb2xsSGVhZFwiLFxuXHRcdFwic1Njcm9sbEhlYWRJbm5lclwiOiBcImRhdGFUYWJsZXNfc2Nyb2xsSGVhZElubmVyXCIsXG5cdFx0XCJzU2Nyb2xsQm9keVwiOiBcImRhdGFUYWJsZXNfc2Nyb2xsQm9keVwiLFxuXHRcdFwic1Njcm9sbEZvb3RcIjogXCJkYXRhVGFibGVzX3Njcm9sbEZvb3RcIixcblx0XHRcInNTY3JvbGxGb290SW5uZXJcIjogXCJkYXRhVGFibGVzX3Njcm9sbEZvb3RJbm5lclwiLFxuXHRcblx0XHQvKiBNaXNjICovXG5cdFx0XCJzSGVhZGVyVEhcIjogXCJcIixcblx0XHRcInNGb290ZXJUSFwiOiBcIlwiLFxuXHRcblx0XHQvLyBEZXByZWNhdGVkXG5cdFx0XCJzU29ydEpVSUFzY1wiOiBcIlwiLFxuXHRcdFwic1NvcnRKVUlEZXNjXCI6IFwiXCIsXG5cdFx0XCJzU29ydEpVSVwiOiBcIlwiLFxuXHRcdFwic1NvcnRKVUlBc2NBbGxvd2VkXCI6IFwiXCIsXG5cdFx0XCJzU29ydEpVSURlc2NBbGxvd2VkXCI6IFwiXCIsXG5cdFx0XCJzU29ydEpVSVdyYXBwZXJcIjogXCJcIixcblx0XHRcInNTb3J0SWNvblwiOiBcIlwiLFxuXHRcdFwic0pVSUhlYWRlclwiOiBcIlwiLFxuXHRcdFwic0pVSUZvb3RlclwiOiBcIlwiXG5cdH0gKTtcblx0XG5cdFxuXHR2YXIgZXh0UGFnaW5hdGlvbiA9IERhdGFUYWJsZS5leHQucGFnZXI7XG5cdFxuXHRmdW5jdGlvbiBfbnVtYmVycyAoIHBhZ2UsIHBhZ2VzICkge1xuXHRcdHZhclxuXHRcdFx0bnVtYmVycyA9IFtdLFxuXHRcdFx0YnV0dG9ucyA9IGV4dFBhZ2luYXRpb24ubnVtYmVyc19sZW5ndGgsXG5cdFx0XHRoYWxmID0gTWF0aC5mbG9vciggYnV0dG9ucyAvIDIgKSxcblx0XHRcdGkgPSAxO1xuXHRcblx0XHRpZiAoIHBhZ2VzIDw9IGJ1dHRvbnMgKSB7XG5cdFx0XHRudW1iZXJzID0gX3JhbmdlKCAwLCBwYWdlcyApO1xuXHRcdH1cblx0XHRlbHNlIGlmICggcGFnZSA8PSBoYWxmICkge1xuXHRcdFx0bnVtYmVycyA9IF9yYW5nZSggMCwgYnV0dG9ucy0yICk7XG5cdFx0XHRudW1iZXJzLnB1c2goICdlbGxpcHNpcycgKTtcblx0XHRcdG51bWJlcnMucHVzaCggcGFnZXMtMSApO1xuXHRcdH1cblx0XHRlbHNlIGlmICggcGFnZSA+PSBwYWdlcyAtIDEgLSBoYWxmICkge1xuXHRcdFx0bnVtYmVycyA9IF9yYW5nZSggcGFnZXMtKGJ1dHRvbnMtMiksIHBhZ2VzICk7XG5cdFx0XHRudW1iZXJzLnNwbGljZSggMCwgMCwgJ2VsbGlwc2lzJyApOyAvLyBubyB1bnNoaWZ0IGluIGllNlxuXHRcdFx0bnVtYmVycy5zcGxpY2UoIDAsIDAsIDAgKTtcblx0XHR9XG5cdFx0ZWxzZSB7XG5cdFx0XHRudW1iZXJzID0gX3JhbmdlKCBwYWdlLWhhbGYrMiwgcGFnZStoYWxmLTEgKTtcblx0XHRcdG51bWJlcnMucHVzaCggJ2VsbGlwc2lzJyApO1xuXHRcdFx0bnVtYmVycy5wdXNoKCBwYWdlcy0xICk7XG5cdFx0XHRudW1iZXJzLnNwbGljZSggMCwgMCwgJ2VsbGlwc2lzJyApO1xuXHRcdFx0bnVtYmVycy5zcGxpY2UoIDAsIDAsIDAgKTtcblx0XHR9XG5cdFxuXHRcdG51bWJlcnMuRFRfZWwgPSAnc3Bhbic7XG5cdFx0cmV0dXJuIG51bWJlcnM7XG5cdH1cblx0XG5cdFxuXHQkLmV4dGVuZCggZXh0UGFnaW5hdGlvbiwge1xuXHRcdHNpbXBsZTogZnVuY3Rpb24gKCBwYWdlLCBwYWdlcyApIHtcblx0XHRcdHJldHVybiBbICdwcmV2aW91cycsICduZXh0JyBdO1xuXHRcdH0sXG5cdFxuXHRcdGZ1bGw6IGZ1bmN0aW9uICggcGFnZSwgcGFnZXMgKSB7XG5cdFx0XHRyZXR1cm4gWyAgJ2ZpcnN0JywgJ3ByZXZpb3VzJywgJ25leHQnLCAnbGFzdCcgXTtcblx0XHR9LFxuXHRcblx0XHRudW1iZXJzOiBmdW5jdGlvbiAoIHBhZ2UsIHBhZ2VzICkge1xuXHRcdFx0cmV0dXJuIFsgX251bWJlcnMocGFnZSwgcGFnZXMpIF07XG5cdFx0fSxcblx0XG5cdFx0c2ltcGxlX251bWJlcnM6IGZ1bmN0aW9uICggcGFnZSwgcGFnZXMgKSB7XG5cdFx0XHRyZXR1cm4gWyAncHJldmlvdXMnLCBfbnVtYmVycyhwYWdlLCBwYWdlcyksICduZXh0JyBdO1xuXHRcdH0sXG5cdFxuXHRcdGZ1bGxfbnVtYmVyczogZnVuY3Rpb24gKCBwYWdlLCBwYWdlcyApIHtcblx0XHRcdHJldHVybiBbICdmaXJzdCcsICdwcmV2aW91cycsIF9udW1iZXJzKHBhZ2UsIHBhZ2VzKSwgJ25leHQnLCAnbGFzdCcgXTtcblx0XHR9LFxuXHRcdFxuXHRcdGZpcnN0X2xhc3RfbnVtYmVyczogZnVuY3Rpb24gKHBhZ2UsIHBhZ2VzKSB7XG5cdCBcdFx0cmV0dXJuIFsnZmlyc3QnLCBfbnVtYmVycyhwYWdlLCBwYWdlcyksICdsYXN0J107XG5cdCBcdH0sXG5cdFxuXHRcdC8vIEZvciB0ZXN0aW5nIGFuZCBwbHVnLWlucyB0byB1c2Vcblx0XHRfbnVtYmVyczogX251bWJlcnMsXG5cdFxuXHRcdC8vIE51bWJlciBvZiBudW1iZXIgYnV0dG9ucyAoaW5jbHVkaW5nIGVsbGlwc2lzKSB0byBzaG93LiBfTXVzdCBiZSBvZGQhX1xuXHRcdG51bWJlcnNfbGVuZ3RoOiA3XG5cdH0gKTtcblx0XG5cdFxuXHQkLmV4dGVuZCggdHJ1ZSwgRGF0YVRhYmxlLmV4dC5yZW5kZXJlciwge1xuXHRcdHBhZ2VCdXR0b246IHtcblx0XHRcdF86IGZ1bmN0aW9uICggc2V0dGluZ3MsIGhvc3QsIGlkeCwgYnV0dG9ucywgcGFnZSwgcGFnZXMgKSB7XG5cdFx0XHRcdHZhciBjbGFzc2VzID0gc2V0dGluZ3Mub0NsYXNzZXM7XG5cdFx0XHRcdHZhciBsYW5nID0gc2V0dGluZ3Mub0xhbmd1YWdlLm9QYWdpbmF0ZTtcblx0XHRcdFx0dmFyIGFyaWEgPSBzZXR0aW5ncy5vTGFuZ3VhZ2Uub0FyaWEucGFnaW5hdGUgfHwge307XG5cdFx0XHRcdHZhciBidG5EaXNwbGF5LCBidG5DbGFzcywgY291bnRlcj0wO1xuXHRcblx0XHRcdFx0dmFyIGF0dGFjaCA9IGZ1bmN0aW9uKCBjb250YWluZXIsIGJ1dHRvbnMgKSB7XG5cdFx0XHRcdFx0dmFyIGksIGllbiwgbm9kZSwgYnV0dG9uO1xuXHRcdFx0XHRcdHZhciBjbGlja0hhbmRsZXIgPSBmdW5jdGlvbiAoIGUgKSB7XG5cdFx0XHRcdFx0XHRfZm5QYWdlQ2hhbmdlKCBzZXR0aW5ncywgZS5kYXRhLmFjdGlvbiwgdHJ1ZSApO1xuXHRcdFx0XHRcdH07XG5cdFxuXHRcdFx0XHRcdGZvciAoIGk9MCwgaWVuPWJ1dHRvbnMubGVuZ3RoIDsgaTxpZW4gOyBpKysgKSB7XG5cdFx0XHRcdFx0XHRidXR0b24gPSBidXR0b25zW2ldO1xuXHRcblx0XHRcdFx0XHRcdGlmICggJC5pc0FycmF5KCBidXR0b24gKSApIHtcblx0XHRcdFx0XHRcdFx0dmFyIGlubmVyID0gJCggJzwnKyhidXR0b24uRFRfZWwgfHwgJ2RpdicpKycvPicgKVxuXHRcdFx0XHRcdFx0XHRcdC5hcHBlbmRUbyggY29udGFpbmVyICk7XG5cdFx0XHRcdFx0XHRcdGF0dGFjaCggaW5uZXIsIGJ1dHRvbiApO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBudWxsO1xuXHRcdFx0XHRcdFx0XHRidG5DbGFzcyA9ICcnO1xuXHRcblx0XHRcdFx0XHRcdFx0c3dpdGNoICggYnV0dG9uICkge1xuXHRcdFx0XHRcdFx0XHRcdGNhc2UgJ2VsbGlwc2lzJzpcblx0XHRcdFx0XHRcdFx0XHRcdGNvbnRhaW5lci5hcHBlbmQoJzxzcGFuIGNsYXNzPVwiZWxsaXBzaXNcIj4mI3gyMDI2Ozwvc3Bhbj4nKTtcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcblx0XHRcdFx0XHRcdFx0XHRjYXNlICdmaXJzdCc6XG5cdFx0XHRcdFx0XHRcdFx0XHRidG5EaXNwbGF5ID0gbGFuZy5zRmlyc3Q7XG5cdFx0XHRcdFx0XHRcdFx0XHRidG5DbGFzcyA9IGJ1dHRvbiArIChwYWdlID4gMCA/XG5cdFx0XHRcdFx0XHRcdFx0XHRcdCcnIDogJyAnK2NsYXNzZXMuc1BhZ2VCdXR0b25EaXNhYmxlZCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XG5cdFx0XHRcdFx0XHRcdFx0Y2FzZSAncHJldmlvdXMnOlxuXHRcdFx0XHRcdFx0XHRcdFx0YnRuRGlzcGxheSA9IGxhbmcuc1ByZXZpb3VzO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnRuQ2xhc3MgPSBidXR0b24gKyAocGFnZSA+IDAgP1xuXHRcdFx0XHRcdFx0XHRcdFx0XHQnJyA6ICcgJytjbGFzc2VzLnNQYWdlQnV0dG9uRGlzYWJsZWQpO1xuXHRcdFx0XHRcdFx0XHRcdFx0YnJlYWs7XG5cdFxuXHRcdFx0XHRcdFx0XHRcdGNhc2UgJ25leHQnOlxuXHRcdFx0XHRcdFx0XHRcdFx0YnRuRGlzcGxheSA9IGxhbmcuc05leHQ7XG5cdFx0XHRcdFx0XHRcdFx0XHRidG5DbGFzcyA9IGJ1dHRvbiArIChwYWdlIDwgcGFnZXMtMSA/XG5cdFx0XHRcdFx0XHRcdFx0XHRcdCcnIDogJyAnK2NsYXNzZXMuc1BhZ2VCdXR0b25EaXNhYmxlZCk7XG5cdFx0XHRcdFx0XHRcdFx0XHRicmVhaztcblx0XG5cdFx0XHRcdFx0XHRcdFx0Y2FzZSAnbGFzdCc6XG5cdFx0XHRcdFx0XHRcdFx0XHRidG5EaXNwbGF5ID0gbGFuZy5zTGFzdDtcblx0XHRcdFx0XHRcdFx0XHRcdGJ0bkNsYXNzID0gYnV0dG9uICsgKHBhZ2UgPCBwYWdlcy0xID9cblx0XHRcdFx0XHRcdFx0XHRcdFx0JycgOiAnICcrY2xhc3Nlcy5zUGFnZUJ1dHRvbkRpc2FibGVkKTtcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcblx0XHRcdFx0XHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdFx0XHRcdFx0YnRuRGlzcGxheSA9IGJ1dHRvbiArIDE7XG5cdFx0XHRcdFx0XHRcdFx0XHRidG5DbGFzcyA9IHBhZ2UgPT09IGJ1dHRvbiA/XG5cdFx0XHRcdFx0XHRcdFx0XHRcdGNsYXNzZXMuc1BhZ2VCdXR0b25BY3RpdmUgOiAnJztcblx0XHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdFx0XHRpZiAoIGJ0bkRpc3BsYXkgIT09IG51bGwgKSB7XG5cdFx0XHRcdFx0XHRcdFx0bm9kZSA9ICQoJzxhPicsIHtcblx0XHRcdFx0XHRcdFx0XHRcdFx0J2NsYXNzJzogY2xhc3Nlcy5zUGFnZUJ1dHRvbisnICcrYnRuQ2xhc3MsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCdhcmlhLWNvbnRyb2xzJzogc2V0dGluZ3Muc1RhYmxlSWQsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCdhcmlhLWxhYmVsJzogYXJpYVsgYnV0dG9uIF0sXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCdkYXRhLWR0LWlkeCc6IGNvdW50ZXIsXG5cdFx0XHRcdFx0XHRcdFx0XHRcdCd0YWJpbmRleCc6IHNldHRpbmdzLmlUYWJJbmRleCxcblx0XHRcdFx0XHRcdFx0XHRcdFx0J2lkJzogaWR4ID09PSAwICYmIHR5cGVvZiBidXR0b24gPT09ICdzdHJpbmcnID9cblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRzZXR0aW5ncy5zVGFibGVJZCArJ18nKyBidXR0b24gOlxuXHRcdFx0XHRcdFx0XHRcdFx0XHRcdG51bGxcblx0XHRcdFx0XHRcdFx0XHRcdH0gKVxuXHRcdFx0XHRcdFx0XHRcdFx0Lmh0bWwoIGJ0bkRpc3BsYXkgKVxuXHRcdFx0XHRcdFx0XHRcdFx0LmFwcGVuZFRvKCBjb250YWluZXIgKTtcblx0XG5cdFx0XHRcdFx0XHRcdFx0X2ZuQmluZEFjdGlvbihcblx0XHRcdFx0XHRcdFx0XHRcdG5vZGUsIHthY3Rpb246IGJ1dHRvbn0sIGNsaWNrSGFuZGxlclxuXHRcdFx0XHRcdFx0XHRcdCk7XG5cdFxuXHRcdFx0XHRcdFx0XHRcdGNvdW50ZXIrKztcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fTtcblx0XG5cdFx0XHRcdC8vIElFOSB0aHJvd3MgYW4gJ3Vua25vd24gZXJyb3InIGlmIGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQgaXMgdXNlZFxuXHRcdFx0XHQvLyBpbnNpZGUgYW4gaWZyYW1lIG9yIGZyYW1lLiBUcnkgLyBjYXRjaCB0aGUgZXJyb3IuIE5vdCBnb29kIGZvclxuXHRcdFx0XHQvLyBhY2Nlc3NpYmlsaXR5LCBidXQgbmVpdGhlciBhcmUgZnJhbWVzLlxuXHRcdFx0XHR2YXIgYWN0aXZlRWw7XG5cdFxuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdC8vIEJlY2F1c2UgdGhpcyBhcHByb2FjaCBpcyBkZXN0cm95aW5nIGFuZCByZWNyZWF0aW5nIHRoZSBwYWdpbmdcblx0XHRcdFx0XHQvLyBlbGVtZW50cywgZm9jdXMgaXMgbG9zdCBvbiB0aGUgc2VsZWN0IGJ1dHRvbiB3aGljaCBpcyBiYWQgZm9yXG5cdFx0XHRcdFx0Ly8gYWNjZXNzaWJpbGl0eS4gU28gd2Ugd2FudCB0byByZXN0b3JlIGZvY3VzIG9uY2UgdGhlIGRyYXcgaGFzXG5cdFx0XHRcdFx0Ly8gY29tcGxldGVkXG5cdFx0XHRcdFx0YWN0aXZlRWwgPSAkKGhvc3QpLmZpbmQoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkuZGF0YSgnZHQtaWR4Jyk7XG5cdFx0XHRcdH1cblx0XHRcdFx0Y2F0Y2ggKGUpIHt9XG5cdFxuXHRcdFx0XHRhdHRhY2goICQoaG9zdCkuZW1wdHkoKSwgYnV0dG9ucyApO1xuXHRcblx0XHRcdFx0aWYgKCBhY3RpdmVFbCAhPT0gdW5kZWZpbmVkICkge1xuXHRcdFx0XHRcdCQoaG9zdCkuZmluZCggJ1tkYXRhLWR0LWlkeD0nK2FjdGl2ZUVsKyddJyApLmZvY3VzKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH0gKTtcblx0XG5cdFxuXHRcblx0Ly8gQnVpbHQgaW4gdHlwZSBkZXRlY3Rpb24uIFNlZSBtb2RlbC5leHQuYVR5cGVzIGZvciBpbmZvcm1hdGlvbiBhYm91dFxuXHQvLyB3aGF0IGlzIHJlcXVpcmVkIGZyb20gdGhpcyBtZXRob2RzLlxuXHQkLmV4dGVuZCggRGF0YVRhYmxlLmV4dC50eXBlLmRldGVjdCwgW1xuXHRcdC8vIFBsYWluIG51bWJlcnMgLSBmaXJzdCBzaW5jZSBWOCBkZXRlY3RzIHNvbWUgcGxhaW4gbnVtYmVycyBhcyBkYXRlc1xuXHRcdC8vIGUuZy4gRGF0ZS5wYXJzZSgnNTUnKSAoYnV0IG5vdCBhbGwsIGUuZy4gRGF0ZS5wYXJzZSgnMjInKS4uLikuXG5cdFx0ZnVuY3Rpb24gKCBkLCBzZXR0aW5ncyApXG5cdFx0e1xuXHRcdFx0dmFyIGRlY2ltYWwgPSBzZXR0aW5ncy5vTGFuZ3VhZ2Uuc0RlY2ltYWw7XG5cdFx0XHRyZXR1cm4gX2lzTnVtYmVyKCBkLCBkZWNpbWFsICkgPyAnbnVtJytkZWNpbWFsIDogbnVsbDtcblx0XHR9LFxuXHRcblx0XHQvLyBEYXRlcyAob25seSB0aG9zZSByZWNvZ25pc2VkIGJ5IHRoZSBicm93c2VyJ3MgRGF0ZS5wYXJzZSlcblx0XHRmdW5jdGlvbiAoIGQsIHNldHRpbmdzIClcblx0XHR7XG5cdFx0XHQvLyBWOCB0cmllcyBfdmVyeV8gaGFyZCB0byBtYWtlIGEgc3RyaW5nIHBhc3NlZCBpbnRvIGBEYXRlLnBhcnNlKClgXG5cdFx0XHQvLyB2YWxpZCwgc28gd2UgbmVlZCB0byB1c2UgYSByZWdleCB0byByZXN0cmljdCBkYXRlIGZvcm1hdHMuIFVzZSBhXG5cdFx0XHQvLyBwbHVnLWluIGZvciBhbnl0aGluZyBvdGhlciB0aGFuIElTTzg2MDEgc3R5bGUgc3RyaW5nc1xuXHRcdFx0aWYgKCBkICYmICEoZCBpbnN0YW5jZW9mIERhdGUpICYmICEgX3JlX2RhdGUudGVzdChkKSApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0XHR2YXIgcGFyc2VkID0gRGF0ZS5wYXJzZShkKTtcblx0XHRcdHJldHVybiAocGFyc2VkICE9PSBudWxsICYmICFpc05hTihwYXJzZWQpKSB8fCBfZW1wdHkoZCkgPyAnZGF0ZScgOiBudWxsO1xuXHRcdH0sXG5cdFxuXHRcdC8vIEZvcm1hdHRlZCBudW1iZXJzXG5cdFx0ZnVuY3Rpb24gKCBkLCBzZXR0aW5ncyApXG5cdFx0e1xuXHRcdFx0dmFyIGRlY2ltYWwgPSBzZXR0aW5ncy5vTGFuZ3VhZ2Uuc0RlY2ltYWw7XG5cdFx0XHRyZXR1cm4gX2lzTnVtYmVyKCBkLCBkZWNpbWFsLCB0cnVlICkgPyAnbnVtLWZtdCcrZGVjaW1hbCA6IG51bGw7XG5cdFx0fSxcblx0XG5cdFx0Ly8gSFRNTCBudW1lcmljXG5cdFx0ZnVuY3Rpb24gKCBkLCBzZXR0aW5ncyApXG5cdFx0e1xuXHRcdFx0dmFyIGRlY2ltYWwgPSBzZXR0aW5ncy5vTGFuZ3VhZ2Uuc0RlY2ltYWw7XG5cdFx0XHRyZXR1cm4gX2h0bWxOdW1lcmljKCBkLCBkZWNpbWFsICkgPyAnaHRtbC1udW0nK2RlY2ltYWwgOiBudWxsO1xuXHRcdH0sXG5cdFxuXHRcdC8vIEhUTUwgbnVtZXJpYywgZm9ybWF0dGVkXG5cdFx0ZnVuY3Rpb24gKCBkLCBzZXR0aW5ncyApXG5cdFx0e1xuXHRcdFx0dmFyIGRlY2ltYWwgPSBzZXR0aW5ncy5vTGFuZ3VhZ2Uuc0RlY2ltYWw7XG5cdFx0XHRyZXR1cm4gX2h0bWxOdW1lcmljKCBkLCBkZWNpbWFsLCB0cnVlICkgPyAnaHRtbC1udW0tZm10JytkZWNpbWFsIDogbnVsbDtcblx0XHR9LFxuXHRcblx0XHQvLyBIVE1MICh0aGlzIGlzIHN0cmljdCBjaGVja2luZyAtIHRoZXJlIG11c3QgYmUgaHRtbClcblx0XHRmdW5jdGlvbiAoIGQsIHNldHRpbmdzIClcblx0XHR7XG5cdFx0XHRyZXR1cm4gX2VtcHR5KCBkICkgfHwgKHR5cGVvZiBkID09PSAnc3RyaW5nJyAmJiBkLmluZGV4T2YoJzwnKSAhPT0gLTEpID9cblx0XHRcdFx0J2h0bWwnIDogbnVsbDtcblx0XHR9XG5cdF0gKTtcblx0XG5cdFxuXHRcblx0Ly8gRmlsdGVyIGZvcm1hdHRpbmcgZnVuY3Rpb25zLiBTZWUgbW9kZWwuZXh0Lm9mblNlYXJjaCBmb3IgaW5mb3JtYXRpb24gYWJvdXRcblx0Ly8gd2hhdCBpcyByZXF1aXJlZCBmcm9tIHRoZXNlIG1ldGhvZHMuXG5cdC8vIFxuXHQvLyBOb3RlIHRoYXQgYWRkaXRpb25hbCBzZWFyY2ggbWV0aG9kcyBhcmUgYWRkZWQgZm9yIHRoZSBodG1sIG51bWJlcnMgYW5kXG5cdC8vIGh0bWwgZm9ybWF0dGVkIG51bWJlcnMgYnkgYF9hZGROdW1lcmljU29ydCgpYCB3aGVuIHdlIGtub3cgd2hhdCB0aGUgZGVjaW1hbFxuXHQvLyBwbGFjZSBpc1xuXHRcblx0XG5cdCQuZXh0ZW5kKCBEYXRhVGFibGUuZXh0LnR5cGUuc2VhcmNoLCB7XG5cdFx0aHRtbDogZnVuY3Rpb24gKCBkYXRhICkge1xuXHRcdFx0cmV0dXJuIF9lbXB0eShkYXRhKSA/XG5cdFx0XHRcdGRhdGEgOlxuXHRcdFx0XHR0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycgP1xuXHRcdFx0XHRcdGRhdGFcblx0XHRcdFx0XHRcdC5yZXBsYWNlKCBfcmVfbmV3X2xpbmVzLCBcIiBcIiApXG5cdFx0XHRcdFx0XHQucmVwbGFjZSggX3JlX2h0bWwsIFwiXCIgKSA6XG5cdFx0XHRcdFx0Jyc7XG5cdFx0fSxcblx0XG5cdFx0c3RyaW5nOiBmdW5jdGlvbiAoIGRhdGEgKSB7XG5cdFx0XHRyZXR1cm4gX2VtcHR5KGRhdGEpID9cblx0XHRcdFx0ZGF0YSA6XG5cdFx0XHRcdHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJyA/XG5cdFx0XHRcdFx0ZGF0YS5yZXBsYWNlKCBfcmVfbmV3X2xpbmVzLCBcIiBcIiApIDpcblx0XHRcdFx0XHRkYXRhO1xuXHRcdH1cblx0fSApO1xuXHRcblx0XG5cdFxuXHR2YXIgX19udW1lcmljUmVwbGFjZSA9IGZ1bmN0aW9uICggZCwgZGVjaW1hbFBsYWNlLCByZTEsIHJlMiApIHtcblx0XHRpZiAoIGQgIT09IDAgJiYgKCFkIHx8IGQgPT09ICctJykgKSB7XG5cdFx0XHRyZXR1cm4gLUluZmluaXR5O1xuXHRcdH1cblx0XG5cdFx0Ly8gSWYgYSBkZWNpbWFsIHBsYWNlIG90aGVyIHRoYW4gYC5gIGlzIHVzZWQsIGl0IG5lZWRzIHRvIGJlIGdpdmVuIHRvIHRoZVxuXHRcdC8vIGZ1bmN0aW9uIHNvIHdlIGNhbiBkZXRlY3QgaXQgYW5kIHJlcGxhY2Ugd2l0aCBhIGAuYCB3aGljaCBpcyB0aGUgb25seVxuXHRcdC8vIGRlY2ltYWwgcGxhY2UgSmF2YXNjcmlwdCByZWNvZ25pc2VzIC0gaXQgaXMgbm90IGxvY2FsZSBhd2FyZS5cblx0XHRpZiAoIGRlY2ltYWxQbGFjZSApIHtcblx0XHRcdGQgPSBfbnVtVG9EZWNpbWFsKCBkLCBkZWNpbWFsUGxhY2UgKTtcblx0XHR9XG5cdFxuXHRcdGlmICggZC5yZXBsYWNlICkge1xuXHRcdFx0aWYgKCByZTEgKSB7XG5cdFx0XHRcdGQgPSBkLnJlcGxhY2UoIHJlMSwgJycgKTtcblx0XHRcdH1cblx0XG5cdFx0XHRpZiAoIHJlMiApIHtcblx0XHRcdFx0ZCA9IGQucmVwbGFjZSggcmUyLCAnJyApO1xuXHRcdFx0fVxuXHRcdH1cblx0XG5cdFx0cmV0dXJuIGQgKiAxO1xuXHR9O1xuXHRcblx0XG5cdC8vIEFkZCB0aGUgbnVtZXJpYyAnZGVmb3JtYXR0aW5nJyBmdW5jdGlvbnMgZm9yIHNvcnRpbmcgYW5kIHNlYXJjaC4gVGhpcyBpcyBkb25lXG5cdC8vIGluIGEgZnVuY3Rpb24gdG8gcHJvdmlkZSBhbiBlYXN5IGFiaWxpdHkgZm9yIHRoZSBsYW5ndWFnZSBvcHRpb25zIHRvIGFkZFxuXHQvLyBhZGRpdGlvbmFsIG1ldGhvZHMgaWYgYSBub24tcGVyaW9kIGRlY2ltYWwgcGxhY2UgaXMgdXNlZC5cblx0ZnVuY3Rpb24gX2FkZE51bWVyaWNTb3J0ICggZGVjaW1hbFBsYWNlICkge1xuXHRcdCQuZWFjaChcblx0XHRcdHtcblx0XHRcdFx0Ly8gUGxhaW4gbnVtYmVyc1xuXHRcdFx0XHRcIm51bVwiOiBmdW5jdGlvbiAoIGQgKSB7XG5cdFx0XHRcdFx0cmV0dXJuIF9fbnVtZXJpY1JlcGxhY2UoIGQsIGRlY2ltYWxQbGFjZSApO1xuXHRcdFx0XHR9LFxuXHRcblx0XHRcdFx0Ly8gRm9ybWF0dGVkIG51bWJlcnNcblx0XHRcdFx0XCJudW0tZm10XCI6IGZ1bmN0aW9uICggZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gX19udW1lcmljUmVwbGFjZSggZCwgZGVjaW1hbFBsYWNlLCBfcmVfZm9ybWF0dGVkX251bWVyaWMgKTtcblx0XHRcdFx0fSxcblx0XG5cdFx0XHRcdC8vIEhUTUwgbnVtZXJpY1xuXHRcdFx0XHRcImh0bWwtbnVtXCI6IGZ1bmN0aW9uICggZCApIHtcblx0XHRcdFx0XHRyZXR1cm4gX19udW1lcmljUmVwbGFjZSggZCwgZGVjaW1hbFBsYWNlLCBfcmVfaHRtbCApO1xuXHRcdFx0XHR9LFxuXHRcblx0XHRcdFx0Ly8gSFRNTCBudW1lcmljLCBmb3JtYXR0ZWRcblx0XHRcdFx0XCJodG1sLW51bS1mbXRcIjogZnVuY3Rpb24gKCBkICkge1xuXHRcdFx0XHRcdHJldHVybiBfX251bWVyaWNSZXBsYWNlKCBkLCBkZWNpbWFsUGxhY2UsIF9yZV9odG1sLCBfcmVfZm9ybWF0dGVkX251bWVyaWMgKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdGZ1bmN0aW9uICgga2V5LCBmbiApIHtcblx0XHRcdFx0Ly8gQWRkIHRoZSBvcmRlcmluZyBtZXRob2Rcblx0XHRcdFx0X2V4dC50eXBlLm9yZGVyWyBrZXkrZGVjaW1hbFBsYWNlKyctcHJlJyBdID0gZm47XG5cdFxuXHRcdFx0XHQvLyBGb3IgSFRNTCB0eXBlcyBhZGQgYSBzZWFyY2ggZm9ybWF0dGVyIHRoYXQgd2lsbCBzdHJpcCB0aGUgSFRNTFxuXHRcdFx0XHRpZiAoIGtleS5tYXRjaCgvXmh0bWxcXC0vKSApIHtcblx0XHRcdFx0XHRfZXh0LnR5cGUuc2VhcmNoWyBrZXkrZGVjaW1hbFBsYWNlIF0gPSBfZXh0LnR5cGUuc2VhcmNoLmh0bWw7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHQpO1xuXHR9XG5cdFxuXHRcblx0Ly8gRGVmYXVsdCBzb3J0IG1ldGhvZHNcblx0JC5leHRlbmQoIF9leHQudHlwZS5vcmRlciwge1xuXHRcdC8vIERhdGVzXG5cdFx0XCJkYXRlLXByZVwiOiBmdW5jdGlvbiAoIGQgKSB7XG5cdFx0XHRyZXR1cm4gRGF0ZS5wYXJzZSggZCApIHx8IC1JbmZpbml0eTtcblx0XHR9LFxuXHRcblx0XHQvLyBodG1sXG5cdFx0XCJodG1sLXByZVwiOiBmdW5jdGlvbiAoIGEgKSB7XG5cdFx0XHRyZXR1cm4gX2VtcHR5KGEpID9cblx0XHRcdFx0JycgOlxuXHRcdFx0XHRhLnJlcGxhY2UgP1xuXHRcdFx0XHRcdGEucmVwbGFjZSggLzwuKj8+L2csIFwiXCIgKS50b0xvd2VyQ2FzZSgpIDpcblx0XHRcdFx0XHRhKycnO1xuXHRcdH0sXG5cdFxuXHRcdC8vIHN0cmluZ1xuXHRcdFwic3RyaW5nLXByZVwiOiBmdW5jdGlvbiAoIGEgKSB7XG5cdFx0XHQvLyBUaGlzIGlzIGEgbGl0dGxlIGNvbXBsZXgsIGJ1dCBmYXN0ZXIgdGhhbiBhbHdheXMgY2FsbGluZyB0b1N0cmluZyxcblx0XHRcdC8vIGh0dHA6Ly9qc3BlcmYuY29tL3Rvc3RyaW5nLXYtY2hlY2tcblx0XHRcdHJldHVybiBfZW1wdHkoYSkgP1xuXHRcdFx0XHQnJyA6XG5cdFx0XHRcdHR5cGVvZiBhID09PSAnc3RyaW5nJyA/XG5cdFx0XHRcdFx0YS50b0xvd2VyQ2FzZSgpIDpcblx0XHRcdFx0XHQhIGEudG9TdHJpbmcgP1xuXHRcdFx0XHRcdFx0JycgOlxuXHRcdFx0XHRcdFx0YS50b1N0cmluZygpO1xuXHRcdH0sXG5cdFxuXHRcdC8vIHN0cmluZy1hc2MgYW5kIC1kZXNjIGFyZSByZXRhaW5lZCBvbmx5IGZvciBjb21wYXRpYmlsaXR5IHdpdGggdGhlIG9sZFxuXHRcdC8vIHNvcnQgbWV0aG9kc1xuXHRcdFwic3RyaW5nLWFzY1wiOiBmdW5jdGlvbiAoIHgsIHkgKSB7XG5cdFx0XHRyZXR1cm4gKCh4IDwgeSkgPyAtMSA6ICgoeCA+IHkpID8gMSA6IDApKTtcblx0XHR9LFxuXHRcblx0XHRcInN0cmluZy1kZXNjXCI6IGZ1bmN0aW9uICggeCwgeSApIHtcblx0XHRcdHJldHVybiAoKHggPCB5KSA/IDEgOiAoKHggPiB5KSA/IC0xIDogMCkpO1xuXHRcdH1cblx0fSApO1xuXHRcblx0XG5cdC8vIE51bWVyaWMgc29ydGluZyB0eXBlcyAtIG9yZGVyIGRvZXNuJ3QgbWF0dGVyIGhlcmVcblx0X2FkZE51bWVyaWNTb3J0KCAnJyApO1xuXHRcblx0XG5cdCQuZXh0ZW5kKCB0cnVlLCBEYXRhVGFibGUuZXh0LnJlbmRlcmVyLCB7XG5cdFx0aGVhZGVyOiB7XG5cdFx0XHRfOiBmdW5jdGlvbiAoIHNldHRpbmdzLCBjZWxsLCBjb2x1bW4sIGNsYXNzZXMgKSB7XG5cdFx0XHRcdC8vIE5vIGFkZGl0aW9uYWwgbWFyay11cCByZXF1aXJlZFxuXHRcdFx0XHQvLyBBdHRhY2ggYSBzb3J0IGxpc3RlbmVyIHRvIHVwZGF0ZSBvbiBzb3J0IC0gbm90ZSB0aGF0IHVzaW5nIHRoZVxuXHRcdFx0XHQvLyBgRFRgIG5hbWVzcGFjZSB3aWxsIGFsbG93IHRoZSBldmVudCB0byBiZSByZW1vdmVkIGF1dG9tYXRpY2FsbHlcblx0XHRcdFx0Ly8gb24gZGVzdHJveSwgd2hpbGUgdGhlIGBkdGAgbmFtZXNwYWNlZCBldmVudCBpcyB0aGUgb25lIHdlIGFyZVxuXHRcdFx0XHQvLyBsaXN0ZW5pbmcgZm9yXG5cdFx0XHRcdCQoc2V0dGluZ3MublRhYmxlKS5vbiggJ29yZGVyLmR0LkRUJywgZnVuY3Rpb24gKCBlLCBjdHgsIHNvcnRpbmcsIGNvbHVtbnMgKSB7XG5cdFx0XHRcdFx0aWYgKCBzZXR0aW5ncyAhPT0gY3R4ICkgeyAvLyBuZWVkIHRvIGNoZWNrIHRoaXMgdGhpcyBpcyB0aGUgaG9zdFxuXHRcdFx0XHRcdFx0cmV0dXJuOyAgICAgICAgICAgICAgIC8vIHRhYmxlLCBub3QgYSBuZXN0ZWQgb25lXG5cdFx0XHRcdFx0fVxuXHRcblx0XHRcdFx0XHR2YXIgY29sSWR4ID0gY29sdW1uLmlkeDtcblx0XG5cdFx0XHRcdFx0Y2VsbFxuXHRcdFx0XHRcdFx0LnJlbW92ZUNsYXNzKFxuXHRcdFx0XHRcdFx0XHRjb2x1bW4uc1NvcnRpbmdDbGFzcyArJyAnK1xuXHRcdFx0XHRcdFx0XHRjbGFzc2VzLnNTb3J0QXNjICsnICcrXG5cdFx0XHRcdFx0XHRcdGNsYXNzZXMuc1NvcnREZXNjXG5cdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHQuYWRkQ2xhc3MoIGNvbHVtbnNbIGNvbElkeCBdID09ICdhc2MnID9cblx0XHRcdFx0XHRcdFx0Y2xhc3Nlcy5zU29ydEFzYyA6IGNvbHVtbnNbIGNvbElkeCBdID09ICdkZXNjJyA/XG5cdFx0XHRcdFx0XHRcdFx0Y2xhc3Nlcy5zU29ydERlc2MgOlxuXHRcdFx0XHRcdFx0XHRcdGNvbHVtbi5zU29ydGluZ0NsYXNzXG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHR9ICk7XG5cdFx0XHR9LFxuXHRcblx0XHRcdGpxdWVyeXVpOiBmdW5jdGlvbiAoIHNldHRpbmdzLCBjZWxsLCBjb2x1bW4sIGNsYXNzZXMgKSB7XG5cdFx0XHRcdCQoJzxkaXYvPicpXG5cdFx0XHRcdFx0LmFkZENsYXNzKCBjbGFzc2VzLnNTb3J0SlVJV3JhcHBlciApXG5cdFx0XHRcdFx0LmFwcGVuZCggY2VsbC5jb250ZW50cygpIClcblx0XHRcdFx0XHQuYXBwZW5kKCAkKCc8c3Bhbi8+Jylcblx0XHRcdFx0XHRcdC5hZGRDbGFzcyggY2xhc3Nlcy5zU29ydEljb24rJyAnK2NvbHVtbi5zU29ydGluZ0NsYXNzSlVJIClcblx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0LmFwcGVuZFRvKCBjZWxsICk7XG5cdFxuXHRcdFx0XHQvLyBBdHRhY2ggYSBzb3J0IGxpc3RlbmVyIHRvIHVwZGF0ZSBvbiBzb3J0XG5cdFx0XHRcdCQoc2V0dGluZ3MublRhYmxlKS5vbiggJ29yZGVyLmR0LkRUJywgZnVuY3Rpb24gKCBlLCBjdHgsIHNvcnRpbmcsIGNvbHVtbnMgKSB7XG5cdFx0XHRcdFx0aWYgKCBzZXR0aW5ncyAhPT0gY3R4ICkge1xuXHRcdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0dmFyIGNvbElkeCA9IGNvbHVtbi5pZHg7XG5cdFxuXHRcdFx0XHRcdGNlbGxcblx0XHRcdFx0XHRcdC5yZW1vdmVDbGFzcyggY2xhc3Nlcy5zU29ydEFzYyArXCIgXCIrY2xhc3Nlcy5zU29ydERlc2MgKVxuXHRcdFx0XHRcdFx0LmFkZENsYXNzKCBjb2x1bW5zWyBjb2xJZHggXSA9PSAnYXNjJyA/XG5cdFx0XHRcdFx0XHRcdGNsYXNzZXMuc1NvcnRBc2MgOiBjb2x1bW5zWyBjb2xJZHggXSA9PSAnZGVzYycgP1xuXHRcdFx0XHRcdFx0XHRcdGNsYXNzZXMuc1NvcnREZXNjIDpcblx0XHRcdFx0XHRcdFx0XHRjb2x1bW4uc1NvcnRpbmdDbGFzc1xuXHRcdFx0XHRcdFx0KTtcblx0XG5cdFx0XHRcdFx0Y2VsbFxuXHRcdFx0XHRcdFx0LmZpbmQoICdzcGFuLicrY2xhc3Nlcy5zU29ydEljb24gKVxuXHRcdFx0XHRcdFx0LnJlbW92ZUNsYXNzKFxuXHRcdFx0XHRcdFx0XHRjbGFzc2VzLnNTb3J0SlVJQXNjICtcIiBcIitcblx0XHRcdFx0XHRcdFx0Y2xhc3Nlcy5zU29ydEpVSURlc2MgK1wiIFwiK1xuXHRcdFx0XHRcdFx0XHRjbGFzc2VzLnNTb3J0SlVJICtcIiBcIitcblx0XHRcdFx0XHRcdFx0Y2xhc3Nlcy5zU29ydEpVSUFzY0FsbG93ZWQgK1wiIFwiK1xuXHRcdFx0XHRcdFx0XHRjbGFzc2VzLnNTb3J0SlVJRGVzY0FsbG93ZWRcblx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHRcdC5hZGRDbGFzcyggY29sdW1uc1sgY29sSWR4IF0gPT0gJ2FzYycgP1xuXHRcdFx0XHRcdFx0XHRjbGFzc2VzLnNTb3J0SlVJQXNjIDogY29sdW1uc1sgY29sSWR4IF0gPT0gJ2Rlc2MnID9cblx0XHRcdFx0XHRcdFx0XHRjbGFzc2VzLnNTb3J0SlVJRGVzYyA6XG5cdFx0XHRcdFx0XHRcdFx0Y29sdW1uLnNTb3J0aW5nQ2xhc3NKVUlcblx0XHRcdFx0XHRcdCk7XG5cdFx0XHRcdH0gKTtcblx0XHRcdH1cblx0XHR9XG5cdH0gKTtcblx0XG5cdC8qXG5cdCAqIFB1YmxpYyBoZWxwZXIgZnVuY3Rpb25zLiBUaGVzZSBhcmVuJ3QgdXNlZCBpbnRlcm5hbGx5IGJ5IERhdGFUYWJsZXMsIG9yXG5cdCAqIGNhbGxlZCBieSBhbnkgb2YgdGhlIG9wdGlvbnMgcGFzc2VkIGludG8gRGF0YVRhYmxlcywgYnV0IHRoZXkgY2FuIGJlIHVzZWRcblx0ICogZXh0ZXJuYWxseSBieSBkZXZlbG9wZXJzIHdvcmtpbmcgd2l0aCBEYXRhVGFibGVzLiBUaGV5IGFyZSBoZWxwZXIgZnVuY3Rpb25zXG5cdCAqIHRvIG1ha2Ugd29ya2luZyB3aXRoIERhdGFUYWJsZXMgYSBsaXR0bGUgYml0IGVhc2llci5cblx0ICovXG5cdFxuXHR2YXIgX19odG1sRXNjYXBlRW50aXRpZXMgPSBmdW5jdGlvbiAoIGQgKSB7XG5cdFx0cmV0dXJuIHR5cGVvZiBkID09PSAnc3RyaW5nJyA/XG5cdFx0XHRkLnJlcGxhY2UoLzwvZywgJyZsdDsnKS5yZXBsYWNlKC8+L2csICcmZ3Q7JykucmVwbGFjZSgvXCIvZywgJyZxdW90OycpIDpcblx0XHRcdGQ7XG5cdH07XG5cdFxuXHQvKipcblx0ICogSGVscGVycyBmb3IgYGNvbHVtbnMucmVuZGVyYC5cblx0ICpcblx0ICogVGhlIG9wdGlvbnMgZGVmaW5lZCBoZXJlIGNhbiBiZSB1c2VkIHdpdGggdGhlIGBjb2x1bW5zLnJlbmRlcmAgaW5pdGlhbGlzYXRpb25cblx0ICogb3B0aW9uIHRvIHByb3ZpZGUgYSBkaXNwbGF5IHJlbmRlcmVyLiBUaGUgZm9sbG93aW5nIGZ1bmN0aW9ucyBhcmUgZGVmaW5lZDpcblx0ICpcblx0ICogKiBgbnVtYmVyYCAtIFdpbGwgZm9ybWF0IG51bWVyaWMgZGF0YSAoZGVmaW5lZCBieSBgY29sdW1ucy5kYXRhYCkgZm9yXG5cdCAqICAgZGlzcGxheSwgcmV0YWluaW5nIHRoZSBvcmlnaW5hbCB1bmZvcm1hdHRlZCBkYXRhIGZvciBzb3J0aW5nIGFuZCBmaWx0ZXJpbmcuXG5cdCAqICAgSXQgdGFrZXMgNSBwYXJhbWV0ZXJzOlxuXHQgKiAgICogYHN0cmluZ2AgLSBUaG91c2FuZHMgZ3JvdXBpbmcgc2VwYXJhdG9yXG5cdCAqICAgKiBgc3RyaW5nYCAtIERlY2ltYWwgcG9pbnQgaW5kaWNhdG9yXG5cdCAqICAgKiBgaW50ZWdlcmAgLSBOdW1iZXIgb2YgZGVjaW1hbCBwb2ludHMgdG8gc2hvd1xuXHQgKiAgICogYHN0cmluZ2AgKG9wdGlvbmFsKSAtIFByZWZpeC5cblx0ICogICAqIGBzdHJpbmdgIChvcHRpb25hbCkgLSBQb3N0Zml4ICgvc3VmZml4KS5cblx0ICogKiBgdGV4dGAgLSBFc2NhcGUgSFRNTCB0byBoZWxwIHByZXZlbnQgWFNTIGF0dGFja3MuIEl0IGhhcyBubyBvcHRpb25hbFxuXHQgKiAgIHBhcmFtZXRlcnMuXG5cdCAqXG5cdCAqIEBleGFtcGxlXG5cdCAqICAgLy8gQ29sdW1uIGRlZmluaXRpb24gdXNpbmcgdGhlIG51bWJlciByZW5kZXJlclxuXHQgKiAgIHtcblx0ICogICAgIGRhdGE6IFwic2FsYXJ5XCIsXG5cdCAqICAgICByZW5kZXI6ICQuZm4uZGF0YVRhYmxlLnJlbmRlci5udW1iZXIoICdcXCcnLCAnLicsIDAsICckJyApXG5cdCAqICAgfVxuXHQgKlxuXHQgKiBAbmFtZXNwYWNlXG5cdCAqL1xuXHREYXRhVGFibGUucmVuZGVyID0ge1xuXHRcdG51bWJlcjogZnVuY3Rpb24gKCB0aG91c2FuZHMsIGRlY2ltYWwsIHByZWNpc2lvbiwgcHJlZml4LCBwb3N0Zml4ICkge1xuXHRcdFx0cmV0dXJuIHtcblx0XHRcdFx0ZGlzcGxheTogZnVuY3Rpb24gKCBkICkge1xuXHRcdFx0XHRcdGlmICggdHlwZW9mIGQgIT09ICdudW1iZXInICYmIHR5cGVvZiBkICE9PSAnc3RyaW5nJyApIHtcblx0XHRcdFx0XHRcdHJldHVybiBkO1xuXHRcdFx0XHRcdH1cblx0XG5cdFx0XHRcdFx0dmFyIG5lZ2F0aXZlID0gZCA8IDAgPyAnLScgOiAnJztcblx0XHRcdFx0XHR2YXIgZmxvID0gcGFyc2VGbG9hdCggZCApO1xuXHRcblx0XHRcdFx0XHQvLyBJZiBOYU4gdGhlbiB0aGVyZSBpc24ndCBtdWNoIGZvcm1hdHRpbmcgdGhhdCB3ZSBjYW4gZG8gLSBqdXN0XG5cdFx0XHRcdFx0Ly8gcmV0dXJuIGltbWVkaWF0ZWx5LCBlc2NhcGluZyBhbnkgSFRNTCAodGhpcyB3YXMgc3VwcG9zZWQgdG9cblx0XHRcdFx0XHQvLyBiZSBhIG51bWJlciBhZnRlciBhbGwpXG5cdFx0XHRcdFx0aWYgKCBpc05hTiggZmxvICkgKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gX19odG1sRXNjYXBlRW50aXRpZXMoIGQgKTtcblx0XHRcdFx0XHR9XG5cdFxuXHRcdFx0XHRcdGZsbyA9IGZsby50b0ZpeGVkKCBwcmVjaXNpb24gKTtcblx0XHRcdFx0XHRkID0gTWF0aC5hYnMoIGZsbyApO1xuXHRcblx0XHRcdFx0XHR2YXIgaW50UGFydCA9IHBhcnNlSW50KCBkLCAxMCApO1xuXHRcdFx0XHRcdHZhciBmbG9hdFBhcnQgPSBwcmVjaXNpb24gP1xuXHRcdFx0XHRcdFx0ZGVjaW1hbCsoZCAtIGludFBhcnQpLnRvRml4ZWQoIHByZWNpc2lvbiApLnN1YnN0cmluZyggMiApOlxuXHRcdFx0XHRcdFx0Jyc7XG5cdFxuXHRcdFx0XHRcdHJldHVybiBuZWdhdGl2ZSArIChwcmVmaXh8fCcnKSArXG5cdFx0XHRcdFx0XHRpbnRQYXJ0LnRvU3RyaW5nKCkucmVwbGFjZShcblx0XHRcdFx0XHRcdFx0L1xcQig/PShcXGR7M30pKyg/IVxcZCkpL2csIHRob3VzYW5kc1xuXHRcdFx0XHRcdFx0KSArXG5cdFx0XHRcdFx0XHRmbG9hdFBhcnQgK1xuXHRcdFx0XHRcdFx0KHBvc3RmaXh8fCcnKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHR9LFxuXHRcblx0XHR0ZXh0OiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRyZXR1cm4ge1xuXHRcdFx0XHRkaXNwbGF5OiBfX2h0bWxFc2NhcGVFbnRpdGllc1xuXHRcdFx0fTtcblx0XHR9XG5cdH07XG5cdFxuXHRcblx0Lypcblx0ICogVGhpcyBpcyByZWFsbHkgYSBnb29kIGJpdCBydWJiaXNoIHRoaXMgbWV0aG9kIG9mIGV4cG9zaW5nIHRoZSBpbnRlcm5hbCBtZXRob2RzXG5cdCAqIHB1YmxpY2x5Li4uIC0gVG8gYmUgZml4ZWQgaW4gMi4wIHVzaW5nIG1ldGhvZHMgb24gdGhlIHByb3RvdHlwZVxuXHQgKi9cblx0XG5cdFxuXHQvKipcblx0ICogQ3JlYXRlIGEgd3JhcHBlciBmdW5jdGlvbiBmb3IgZXhwb3J0aW5nIGFuIGludGVybmFsIGZ1bmN0aW9ucyB0byBhbiBleHRlcm5hbCBBUEkuXG5cdCAqICBAcGFyYW0ge3N0cmluZ30gZm4gQVBJIGZ1bmN0aW9uIG5hbWVcblx0ICogIEByZXR1cm5zIHtmdW5jdGlvbn0gd3JhcHBlZCBmdW5jdGlvblxuXHQgKiAgQG1lbWJlcm9mIERhdGFUYWJsZSNpbnRlcm5hbFxuXHQgKi9cblx0ZnVuY3Rpb24gX2ZuRXh0ZXJuQXBpRnVuYyAoZm4pXG5cdHtcblx0XHRyZXR1cm4gZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgYXJncyA9IFtfZm5TZXR0aW5nc0Zyb21Ob2RlKCB0aGlzW0RhdGFUYWJsZS5leHQuaUFwaUluZGV4XSApXS5jb25jYXQoXG5cdFx0XHRcdEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cylcblx0XHRcdCk7XG5cdFx0XHRyZXR1cm4gRGF0YVRhYmxlLmV4dC5pbnRlcm5hbFtmbl0uYXBwbHkoIHRoaXMsIGFyZ3MgKTtcblx0XHR9O1xuXHR9XG5cdFxuXHRcblx0LyoqXG5cdCAqIFJlZmVyZW5jZSB0byBpbnRlcm5hbCBmdW5jdGlvbnMgZm9yIHVzZSBieSBwbHVnLWluIGRldmVsb3BlcnMuIE5vdGUgdGhhdFxuXHQgKiB0aGVzZSBtZXRob2RzIGFyZSByZWZlcmVuY2VzIHRvIGludGVybmFsIGZ1bmN0aW9ucyBhbmQgYXJlIGNvbnNpZGVyZWQgdG8gYmVcblx0ICogcHJpdmF0ZS4gSWYgeW91IHVzZSB0aGVzZSBtZXRob2RzLCBiZSBhd2FyZSB0aGF0IHRoZXkgYXJlIGxpYWJsZSB0byBjaGFuZ2Vcblx0ICogYmV0d2VlbiB2ZXJzaW9ucy5cblx0ICogIEBuYW1lc3BhY2Vcblx0ICovXG5cdCQuZXh0ZW5kKCBEYXRhVGFibGUuZXh0LmludGVybmFsLCB7XG5cdFx0X2ZuRXh0ZXJuQXBpRnVuYzogX2ZuRXh0ZXJuQXBpRnVuYyxcblx0XHRfZm5CdWlsZEFqYXg6IF9mbkJ1aWxkQWpheCxcblx0XHRfZm5BamF4VXBkYXRlOiBfZm5BamF4VXBkYXRlLFxuXHRcdF9mbkFqYXhQYXJhbWV0ZXJzOiBfZm5BamF4UGFyYW1ldGVycyxcblx0XHRfZm5BamF4VXBkYXRlRHJhdzogX2ZuQWpheFVwZGF0ZURyYXcsXG5cdFx0X2ZuQWpheERhdGFTcmM6IF9mbkFqYXhEYXRhU3JjLFxuXHRcdF9mbkFkZENvbHVtbjogX2ZuQWRkQ29sdW1uLFxuXHRcdF9mbkNvbHVtbk9wdGlvbnM6IF9mbkNvbHVtbk9wdGlvbnMsXG5cdFx0X2ZuQWRqdXN0Q29sdW1uU2l6aW5nOiBfZm5BZGp1c3RDb2x1bW5TaXppbmcsXG5cdFx0X2ZuVmlzaWJsZVRvQ29sdW1uSW5kZXg6IF9mblZpc2libGVUb0NvbHVtbkluZGV4LFxuXHRcdF9mbkNvbHVtbkluZGV4VG9WaXNpYmxlOiBfZm5Db2x1bW5JbmRleFRvVmlzaWJsZSxcblx0XHRfZm5WaXNibGVDb2x1bW5zOiBfZm5WaXNibGVDb2x1bW5zLFxuXHRcdF9mbkdldENvbHVtbnM6IF9mbkdldENvbHVtbnMsXG5cdFx0X2ZuQ29sdW1uVHlwZXM6IF9mbkNvbHVtblR5cGVzLFxuXHRcdF9mbkFwcGx5Q29sdW1uRGVmczogX2ZuQXBwbHlDb2x1bW5EZWZzLFxuXHRcdF9mbkh1bmdhcmlhbk1hcDogX2ZuSHVuZ2FyaWFuTWFwLFxuXHRcdF9mbkNhbWVsVG9IdW5nYXJpYW46IF9mbkNhbWVsVG9IdW5nYXJpYW4sXG5cdFx0X2ZuTGFuZ3VhZ2VDb21wYXQ6IF9mbkxhbmd1YWdlQ29tcGF0LFxuXHRcdF9mbkJyb3dzZXJEZXRlY3Q6IF9mbkJyb3dzZXJEZXRlY3QsXG5cdFx0X2ZuQWRkRGF0YTogX2ZuQWRkRGF0YSxcblx0XHRfZm5BZGRUcjogX2ZuQWRkVHIsXG5cdFx0X2ZuTm9kZVRvRGF0YUluZGV4OiBfZm5Ob2RlVG9EYXRhSW5kZXgsXG5cdFx0X2ZuTm9kZVRvQ29sdW1uSW5kZXg6IF9mbk5vZGVUb0NvbHVtbkluZGV4LFxuXHRcdF9mbkdldENlbGxEYXRhOiBfZm5HZXRDZWxsRGF0YSxcblx0XHRfZm5TZXRDZWxsRGF0YTogX2ZuU2V0Q2VsbERhdGEsXG5cdFx0X2ZuU3BsaXRPYmpOb3RhdGlvbjogX2ZuU3BsaXRPYmpOb3RhdGlvbixcblx0XHRfZm5HZXRPYmplY3REYXRhRm46IF9mbkdldE9iamVjdERhdGFGbixcblx0XHRfZm5TZXRPYmplY3REYXRhRm46IF9mblNldE9iamVjdERhdGFGbixcblx0XHRfZm5HZXREYXRhTWFzdGVyOiBfZm5HZXREYXRhTWFzdGVyLFxuXHRcdF9mbkNsZWFyVGFibGU6IF9mbkNsZWFyVGFibGUsXG5cdFx0X2ZuRGVsZXRlSW5kZXg6IF9mbkRlbGV0ZUluZGV4LFxuXHRcdF9mbkludmFsaWRhdGU6IF9mbkludmFsaWRhdGUsXG5cdFx0X2ZuR2V0Um93RWxlbWVudHM6IF9mbkdldFJvd0VsZW1lbnRzLFxuXHRcdF9mbkNyZWF0ZVRyOiBfZm5DcmVhdGVUcixcblx0XHRfZm5CdWlsZEhlYWQ6IF9mbkJ1aWxkSGVhZCxcblx0XHRfZm5EcmF3SGVhZDogX2ZuRHJhd0hlYWQsXG5cdFx0X2ZuRHJhdzogX2ZuRHJhdyxcblx0XHRfZm5SZURyYXc6IF9mblJlRHJhdyxcblx0XHRfZm5BZGRPcHRpb25zSHRtbDogX2ZuQWRkT3B0aW9uc0h0bWwsXG5cdFx0X2ZuRGV0ZWN0SGVhZGVyOiBfZm5EZXRlY3RIZWFkZXIsXG5cdFx0X2ZuR2V0VW5pcXVlVGhzOiBfZm5HZXRVbmlxdWVUaHMsXG5cdFx0X2ZuRmVhdHVyZUh0bWxGaWx0ZXI6IF9mbkZlYXR1cmVIdG1sRmlsdGVyLFxuXHRcdF9mbkZpbHRlckNvbXBsZXRlOiBfZm5GaWx0ZXJDb21wbGV0ZSxcblx0XHRfZm5GaWx0ZXJDdXN0b206IF9mbkZpbHRlckN1c3RvbSxcblx0XHRfZm5GaWx0ZXJDb2x1bW46IF9mbkZpbHRlckNvbHVtbixcblx0XHRfZm5GaWx0ZXI6IF9mbkZpbHRlcixcblx0XHRfZm5GaWx0ZXJDcmVhdGVTZWFyY2g6IF9mbkZpbHRlckNyZWF0ZVNlYXJjaCxcblx0XHRfZm5Fc2NhcGVSZWdleDogX2ZuRXNjYXBlUmVnZXgsXG5cdFx0X2ZuRmlsdGVyRGF0YTogX2ZuRmlsdGVyRGF0YSxcblx0XHRfZm5GZWF0dXJlSHRtbEluZm86IF9mbkZlYXR1cmVIdG1sSW5mbyxcblx0XHRfZm5VcGRhdGVJbmZvOiBfZm5VcGRhdGVJbmZvLFxuXHRcdF9mbkluZm9NYWNyb3M6IF9mbkluZm9NYWNyb3MsXG5cdFx0X2ZuSW5pdGlhbGlzZTogX2ZuSW5pdGlhbGlzZSxcblx0XHRfZm5Jbml0Q29tcGxldGU6IF9mbkluaXRDb21wbGV0ZSxcblx0XHRfZm5MZW5ndGhDaGFuZ2U6IF9mbkxlbmd0aENoYW5nZSxcblx0XHRfZm5GZWF0dXJlSHRtbExlbmd0aDogX2ZuRmVhdHVyZUh0bWxMZW5ndGgsXG5cdFx0X2ZuRmVhdHVyZUh0bWxQYWdpbmF0ZTogX2ZuRmVhdHVyZUh0bWxQYWdpbmF0ZSxcblx0XHRfZm5QYWdlQ2hhbmdlOiBfZm5QYWdlQ2hhbmdlLFxuXHRcdF9mbkZlYXR1cmVIdG1sUHJvY2Vzc2luZzogX2ZuRmVhdHVyZUh0bWxQcm9jZXNzaW5nLFxuXHRcdF9mblByb2Nlc3NpbmdEaXNwbGF5OiBfZm5Qcm9jZXNzaW5nRGlzcGxheSxcblx0XHRfZm5GZWF0dXJlSHRtbFRhYmxlOiBfZm5GZWF0dXJlSHRtbFRhYmxlLFxuXHRcdF9mblNjcm9sbERyYXc6IF9mblNjcm9sbERyYXcsXG5cdFx0X2ZuQXBwbHlUb0NoaWxkcmVuOiBfZm5BcHBseVRvQ2hpbGRyZW4sXG5cdFx0X2ZuQ2FsY3VsYXRlQ29sdW1uV2lkdGhzOiBfZm5DYWxjdWxhdGVDb2x1bW5XaWR0aHMsXG5cdFx0X2ZuVGhyb3R0bGU6IF9mblRocm90dGxlLFxuXHRcdF9mbkNvbnZlcnRUb1dpZHRoOiBfZm5Db252ZXJ0VG9XaWR0aCxcblx0XHRfZm5HZXRXaWRlc3ROb2RlOiBfZm5HZXRXaWRlc3ROb2RlLFxuXHRcdF9mbkdldE1heExlblN0cmluZzogX2ZuR2V0TWF4TGVuU3RyaW5nLFxuXHRcdF9mblN0cmluZ1RvQ3NzOiBfZm5TdHJpbmdUb0Nzcyxcblx0XHRfZm5Tb3J0RmxhdHRlbjogX2ZuU29ydEZsYXR0ZW4sXG5cdFx0X2ZuU29ydDogX2ZuU29ydCxcblx0XHRfZm5Tb3J0QXJpYTogX2ZuU29ydEFyaWEsXG5cdFx0X2ZuU29ydExpc3RlbmVyOiBfZm5Tb3J0TGlzdGVuZXIsXG5cdFx0X2ZuU29ydEF0dGFjaExpc3RlbmVyOiBfZm5Tb3J0QXR0YWNoTGlzdGVuZXIsXG5cdFx0X2ZuU29ydGluZ0NsYXNzZXM6IF9mblNvcnRpbmdDbGFzc2VzLFxuXHRcdF9mblNvcnREYXRhOiBfZm5Tb3J0RGF0YSxcblx0XHRfZm5TYXZlU3RhdGU6IF9mblNhdmVTdGF0ZSxcblx0XHRfZm5Mb2FkU3RhdGU6IF9mbkxvYWRTdGF0ZSxcblx0XHRfZm5TZXR0aW5nc0Zyb21Ob2RlOiBfZm5TZXR0aW5nc0Zyb21Ob2RlLFxuXHRcdF9mbkxvZzogX2ZuTG9nLFxuXHRcdF9mbk1hcDogX2ZuTWFwLFxuXHRcdF9mbkJpbmRBY3Rpb246IF9mbkJpbmRBY3Rpb24sXG5cdFx0X2ZuQ2FsbGJhY2tSZWc6IF9mbkNhbGxiYWNrUmVnLFxuXHRcdF9mbkNhbGxiYWNrRmlyZTogX2ZuQ2FsbGJhY2tGaXJlLFxuXHRcdF9mbkxlbmd0aE92ZXJmbG93OiBfZm5MZW5ndGhPdmVyZmxvdyxcblx0XHRfZm5SZW5kZXJlcjogX2ZuUmVuZGVyZXIsXG5cdFx0X2ZuRGF0YVNvdXJjZTogX2ZuRGF0YVNvdXJjZSxcblx0XHRfZm5Sb3dBdHRyaWJ1dGVzOiBfZm5Sb3dBdHRyaWJ1dGVzLFxuXHRcdF9mbkNhbGN1bGF0ZUVuZDogZnVuY3Rpb24gKCkge30gLy8gVXNlZCBieSBhIGxvdCBvZiBwbHVnLWlucywgYnV0IHJlZHVuZGFudFxuXHRcdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gaW4gMS4xMCwgc28gdGhpcyBkZWFkLWVuZCBmdW5jdGlvbiBpc1xuXHRcdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gYWRkZWQgdG8gcHJldmVudCBlcnJvcnNcblx0fSApO1xuXHRcblxuXHQvLyBqUXVlcnkgYWNjZXNzXG5cdCQuZm4uZGF0YVRhYmxlID0gRGF0YVRhYmxlO1xuXG5cdC8vIFByb3ZpZGUgYWNjZXNzIHRvIHRoZSBob3N0IGpRdWVyeSBvYmplY3QgKGNpcmN1bGFyIHJlZmVyZW5jZSlcblx0RGF0YVRhYmxlLiQgPSAkO1xuXG5cdC8vIExlZ2FjeSBhbGlhc2VzXG5cdCQuZm4uZGF0YVRhYmxlU2V0dGluZ3MgPSBEYXRhVGFibGUuc2V0dGluZ3M7XG5cdCQuZm4uZGF0YVRhYmxlRXh0ID0gRGF0YVRhYmxlLmV4dDtcblxuXHQvLyBXaXRoIGEgY2FwaXRhbCBgRGAgd2UgcmV0dXJuIGEgRGF0YVRhYmxlcyBBUEkgaW5zdGFuY2UgcmF0aGVyIHRoYW4gYVxuXHQvLyBqUXVlcnkgb2JqZWN0XG5cdCQuZm4uRGF0YVRhYmxlID0gZnVuY3Rpb24gKCBvcHRzICkge1xuXHRcdHJldHVybiAkKHRoaXMpLmRhdGFUYWJsZSggb3B0cyApLmFwaSgpO1xuXHR9O1xuXG5cdC8vIEFsbCBwcm9wZXJ0aWVzIHRoYXQgYXJlIGF2YWlsYWJsZSB0byAkLmZuLmRhdGFUYWJsZSBzaG91bGQgYWxzbyBiZVxuXHQvLyBhdmFpbGFibGUgb24gJC5mbi5EYXRhVGFibGVcblx0JC5lYWNoKCBEYXRhVGFibGUsIGZ1bmN0aW9uICggcHJvcCwgdmFsICkge1xuXHRcdCQuZm4uRGF0YVRhYmxlWyBwcm9wIF0gPSB2YWw7XG5cdH0gKTtcblxuXG5cdC8vIEluZm9ybWF0aW9uIGFib3V0IGV2ZW50cyBmaXJlZCBieSBEYXRhVGFibGVzIC0gZm9yIGRvY3VtZW50YXRpb24uXG5cdC8qKlxuXHQgKiBEcmF3IGV2ZW50LCBmaXJlZCB3aGVuZXZlciB0aGUgdGFibGUgaXMgcmVkcmF3biBvbiB0aGUgcGFnZSwgYXQgdGhlIHNhbWVcblx0ICogcG9pbnQgYXMgZm5EcmF3Q2FsbGJhY2suIFRoaXMgbWF5IGJlIHVzZWZ1bCBmb3IgYmluZGluZyBldmVudHMgb3Jcblx0ICogcGVyZm9ybWluZyBjYWxjdWxhdGlvbnMgd2hlbiB0aGUgdGFibGUgaXMgYWx0ZXJlZCBhdCBhbGwuXG5cdCAqICBAbmFtZSBEYXRhVGFibGUjZHJhdy5kdFxuXHQgKiAgQGV2ZW50XG5cdCAqICBAcGFyYW0ge2V2ZW50fSBlIGpRdWVyeSBldmVudCBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0IHtAbGluayBEYXRhVGFibGUubW9kZWxzLm9TZXR0aW5nc31cblx0ICovXG5cblx0LyoqXG5cdCAqIFNlYXJjaCBldmVudCwgZmlyZWQgd2hlbiB0aGUgc2VhcmNoaW5nIGFwcGxpZWQgdG8gdGhlIHRhYmxlICh1c2luZyB0aGVcblx0ICogYnVpbHQtaW4gZ2xvYmFsIHNlYXJjaCwgb3IgY29sdW1uIGZpbHRlcnMpIGlzIGFsdGVyZWQuXG5cdCAqICBAbmFtZSBEYXRhVGFibGUjc2VhcmNoLmR0XG5cdCAqICBAZXZlbnRcblx0ICogIEBwYXJhbSB7ZXZlbnR9IGUgalF1ZXJ5IGV2ZW50IG9iamVjdFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG8gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Qge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfVxuXHQgKi9cblxuXHQvKipcblx0ICogUGFnZSBjaGFuZ2UgZXZlbnQsIGZpcmVkIHdoZW4gdGhlIHBhZ2luZyBvZiB0aGUgdGFibGUgaXMgYWx0ZXJlZC5cblx0ICogIEBuYW1lIERhdGFUYWJsZSNwYWdlLmR0XG5cdCAqICBAZXZlbnRcblx0ICogIEBwYXJhbSB7ZXZlbnR9IGUgalF1ZXJ5IGV2ZW50IG9iamVjdFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG8gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Qge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfVxuXHQgKi9cblxuXHQvKipcblx0ICogT3JkZXIgZXZlbnQsIGZpcmVkIHdoZW4gdGhlIG9yZGVyaW5nIGFwcGxpZWQgdG8gdGhlIHRhYmxlIGlzIGFsdGVyZWQuXG5cdCAqICBAbmFtZSBEYXRhVGFibGUjb3JkZXIuZHRcblx0ICogIEBldmVudFxuXHQgKiAgQHBhcmFtIHtldmVudH0gZSBqUXVlcnkgZXZlbnQgb2JqZWN0XG5cdCAqICBAcGFyYW0ge29iamVjdH0gbyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdCB7QGxpbmsgRGF0YVRhYmxlLm1vZGVscy5vU2V0dGluZ3N9XG5cdCAqL1xuXG5cdC8qKlxuXHQgKiBEYXRhVGFibGVzIGluaXRpYWxpc2F0aW9uIGNvbXBsZXRlIGV2ZW50LCBmaXJlZCB3aGVuIHRoZSB0YWJsZSBpcyBmdWxseVxuXHQgKiBkcmF3biwgaW5jbHVkaW5nIEFqYXggZGF0YSBsb2FkZWQsIGlmIEFqYXggZGF0YSBpcyByZXF1aXJlZC5cblx0ICogIEBuYW1lIERhdGFUYWJsZSNpbml0LmR0XG5cdCAqICBAZXZlbnRcblx0ICogIEBwYXJhbSB7ZXZlbnR9IGUgalF1ZXJ5IGV2ZW50IG9iamVjdFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG9TZXR0aW5ncyBEYXRhVGFibGVzIHNldHRpbmdzIG9iamVjdFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IGpzb24gVGhlIEpTT04gb2JqZWN0IHJlcXVlc3QgZnJvbSB0aGUgc2VydmVyIC0gb25seVxuXHQgKiAgICBwcmVzZW50IGlmIGNsaWVudC1zaWRlIEFqYXggc291cmNlZCBkYXRhIGlzIHVzZWQ8L2xpPjwvb2w+XG5cdCAqL1xuXG5cdC8qKlxuXHQgKiBTdGF0ZSBzYXZlIGV2ZW50LCBmaXJlZCB3aGVuIHRoZSB0YWJsZSBoYXMgY2hhbmdlZCBzdGF0ZSBhIG5ldyBzdGF0ZSBzYXZlXG5cdCAqIGlzIHJlcXVpcmVkLiBUaGlzIGV2ZW50IGFsbG93cyBtb2RpZmljYXRpb24gb2YgdGhlIHN0YXRlIHNhdmluZyBvYmplY3Rcblx0ICogcHJpb3IgdG8gYWN0dWFsbHkgZG9pbmcgdGhlIHNhdmUsIGluY2x1ZGluZyBhZGRpdGlvbiBvciBvdGhlciBzdGF0ZVxuXHQgKiBwcm9wZXJ0aWVzIChmb3IgcGx1Zy1pbnMpIG9yIG1vZGlmaWNhdGlvbiBvZiBhIERhdGFUYWJsZXMgY29yZSBwcm9wZXJ0eS5cblx0ICogIEBuYW1lIERhdGFUYWJsZSNzdGF0ZVNhdmVQYXJhbXMuZHRcblx0ICogIEBldmVudFxuXHQgKiAgQHBhcmFtIHtldmVudH0gZSBqUXVlcnkgZXZlbnQgb2JqZWN0XG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge29iamVjdH0ganNvbiBUaGUgc3RhdGUgaW5mb3JtYXRpb24gdG8gYmUgc2F2ZWRcblx0ICovXG5cblx0LyoqXG5cdCAqIFN0YXRlIGxvYWQgZXZlbnQsIGZpcmVkIHdoZW4gdGhlIHRhYmxlIGlzIGxvYWRpbmcgc3RhdGUgZnJvbSB0aGUgc3RvcmVkXG5cdCAqIGRhdGEsIGJ1dCBwcmlvciB0byB0aGUgc2V0dGluZ3Mgb2JqZWN0IGJlaW5nIG1vZGlmaWVkIGJ5IHRoZSBzYXZlZCBzdGF0ZVxuXHQgKiAtIGFsbG93aW5nIG1vZGlmaWNhdGlvbiBvZiB0aGUgc2F2ZWQgc3RhdGUgaXMgcmVxdWlyZWQgb3IgbG9hZGluZyBvZlxuXHQgKiBzdGF0ZSBmb3IgYSBwbHVnLWluLlxuXHQgKiAgQG5hbWUgRGF0YVRhYmxlI3N0YXRlTG9hZFBhcmFtcy5kdFxuXHQgKiAgQGV2ZW50XG5cdCAqICBAcGFyYW0ge2V2ZW50fSBlIGpRdWVyeSBldmVudCBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBqc29uIFRoZSBzYXZlZCBzdGF0ZSBpbmZvcm1hdGlvblxuXHQgKi9cblxuXHQvKipcblx0ICogU3RhdGUgbG9hZGVkIGV2ZW50LCBmaXJlZCB3aGVuIHN0YXRlIGhhcyBiZWVuIGxvYWRlZCBmcm9tIHN0b3JlZCBkYXRhIGFuZFxuXHQgKiB0aGUgc2V0dGluZ3Mgb2JqZWN0IGhhcyBiZWVuIG1vZGlmaWVkIGJ5IHRoZSBsb2FkZWQgZGF0YS5cblx0ICogIEBuYW1lIERhdGFUYWJsZSNzdGF0ZUxvYWRlZC5kdFxuXHQgKiAgQGV2ZW50XG5cdCAqICBAcGFyYW0ge2V2ZW50fSBlIGpRdWVyeSBldmVudCBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvU2V0dGluZ3MgRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBqc29uIFRoZSBzYXZlZCBzdGF0ZSBpbmZvcm1hdGlvblxuXHQgKi9cblxuXHQvKipcblx0ICogUHJvY2Vzc2luZyBldmVudCwgZmlyZWQgd2hlbiBEYXRhVGFibGVzIGlzIGRvaW5nIHNvbWUga2luZCBvZiBwcm9jZXNzaW5nXG5cdCAqIChiZSBpdCwgb3JkZXIsIHNlYXJjZyBvciBhbnl0aGluZyBlbHNlKS4gSXQgY2FuIGJlIHVzZWQgdG8gaW5kaWNhdGUgdG9cblx0ICogdGhlIGVuZCB1c2VyIHRoYXQgdGhlcmUgaXMgc29tZXRoaW5nIGhhcHBlbmluZywgb3IgdGhhdCBzb21ldGhpbmcgaGFzXG5cdCAqIGZpbmlzaGVkLlxuXHQgKiAgQG5hbWUgRGF0YVRhYmxlI3Byb2Nlc3NpbmcuZHRcblx0ICogIEBldmVudFxuXHQgKiAgQHBhcmFtIHtldmVudH0gZSBqUXVlcnkgZXZlbnQgb2JqZWN0XG5cdCAqICBAcGFyYW0ge29iamVjdH0gb1NldHRpbmdzIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0XG5cdCAqICBAcGFyYW0ge2Jvb2xlYW59IGJTaG93IEZsYWcgZm9yIGlmIERhdGFUYWJsZXMgaXMgZG9pbmcgcHJvY2Vzc2luZyBvciBub3Rcblx0ICovXG5cblx0LyoqXG5cdCAqIEFqYXggKFhIUikgZXZlbnQsIGZpcmVkIHdoZW5ldmVyIGFuIEFqYXggcmVxdWVzdCBpcyBjb21wbGV0ZWQgZnJvbSBhXG5cdCAqIHJlcXVlc3QgdG8gbWFkZSB0byB0aGUgc2VydmVyIGZvciBuZXcgZGF0YS4gVGhpcyBldmVudCBpcyBjYWxsZWQgYmVmb3JlXG5cdCAqIERhdGFUYWJsZXMgcHJvY2Vzc2VkIHRoZSByZXR1cm5lZCBkYXRhLCBzbyBpdCBjYW4gYWxzbyBiZSB1c2VkIHRvIHByZS1cblx0ICogcHJvY2VzcyB0aGUgZGF0YSByZXR1cm5lZCBmcm9tIHRoZSBzZXJ2ZXIsIGlmIG5lZWRlZC5cblx0ICpcblx0ICogTm90ZSB0aGF0IHRoaXMgdHJpZ2dlciBpcyBjYWxsZWQgaW4gYGZuU2VydmVyRGF0YWAsIGlmIHlvdSBvdmVycmlkZVxuXHQgKiBgZm5TZXJ2ZXJEYXRhYCBhbmQgd2hpY2ggdG8gdXNlIHRoaXMgZXZlbnQsIHlvdSBuZWVkIHRvIHRyaWdnZXIgaXQgaW4geW91XG5cdCAqIHN1Y2Nlc3MgZnVuY3Rpb24uXG5cdCAqICBAbmFtZSBEYXRhVGFibGUjeGhyLmR0XG5cdCAqICBAZXZlbnRcblx0ICogIEBwYXJhbSB7ZXZlbnR9IGUgalF1ZXJ5IGV2ZW50IG9iamVjdFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG8gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Qge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfVxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IGpzb24gSlNPTiByZXR1cm5lZCBmcm9tIHRoZSBzZXJ2ZXJcblx0ICpcblx0ICogIEBleGFtcGxlXG5cdCAqICAgICAvLyBVc2UgYSBjdXN0b20gcHJvcGVydHkgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyIGluIGFub3RoZXIgRE9NIGVsZW1lbnRcblx0ICogICAgICQoJyN0YWJsZScpLmRhdGFUYWJsZSgpLm9uKCd4aHIuZHQnLCBmdW5jdGlvbiAoZSwgc2V0dGluZ3MsIGpzb24pIHtcblx0ICogICAgICAgJCgnI3N0YXR1cycpLmh0bWwoIGpzb24uc3RhdHVzICk7XG5cdCAqICAgICB9ICk7XG5cdCAqXG5cdCAqICBAZXhhbXBsZVxuXHQgKiAgICAgLy8gUHJlLXByb2Nlc3MgdGhlIGRhdGEgcmV0dXJuZWQgZnJvbSB0aGUgc2VydmVyXG5cdCAqICAgICAkKCcjdGFibGUnKS5kYXRhVGFibGUoKS5vbigneGhyLmR0JywgZnVuY3Rpb24gKGUsIHNldHRpbmdzLCBqc29uKSB7XG5cdCAqICAgICAgIGZvciAoIHZhciBpPTAsIGllbj1qc29uLmFhRGF0YS5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0ICogICAgICAgICBqc29uLmFhRGF0YVtpXS5zdW0gPSBqc29uLmFhRGF0YVtpXS5vbmUgKyBqc29uLmFhRGF0YVtpXS50d287XG5cdCAqICAgICAgIH1cblx0ICogICAgICAgLy8gTm90ZSBubyByZXR1cm4gLSBtYW5pcHVsYXRlIHRoZSBkYXRhIGRpcmVjdGx5IGluIHRoZSBKU09OIG9iamVjdC5cblx0ICogICAgIH0gKTtcblx0ICovXG5cblx0LyoqXG5cdCAqIERlc3Ryb3kgZXZlbnQsIGZpcmVkIHdoZW4gdGhlIERhdGFUYWJsZSBpcyBkZXN0cm95ZWQgYnkgY2FsbGluZyBmbkRlc3Ryb3lcblx0ICogb3IgcGFzc2luZyB0aGUgYkRlc3Ryb3k6dHJ1ZSBwYXJhbWV0ZXIgaW4gdGhlIGluaXRpYWxpc2F0aW9uIG9iamVjdC4gVGhpc1xuXHQgKiBjYW4gYmUgdXNlZCB0byByZW1vdmUgYm91bmQgZXZlbnRzLCBhZGRlZCBET00gbm9kZXMsIGV0Yy5cblx0ICogIEBuYW1lIERhdGFUYWJsZSNkZXN0cm95LmR0XG5cdCAqICBAZXZlbnRcblx0ICogIEBwYXJhbSB7ZXZlbnR9IGUgalF1ZXJ5IGV2ZW50IG9iamVjdFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG8gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Qge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfVxuXHQgKi9cblxuXHQvKipcblx0ICogUGFnZSBsZW5ndGggY2hhbmdlIGV2ZW50LCBmaXJlZCB3aGVuIG51bWJlciBvZiByZWNvcmRzIHRvIHNob3cgb24gZWFjaFxuXHQgKiBwYWdlICh0aGUgbGVuZ3RoKSBpcyBjaGFuZ2VkLlxuXHQgKiAgQG5hbWUgRGF0YVRhYmxlI2xlbmd0aC5kdFxuXHQgKiAgQGV2ZW50XG5cdCAqICBAcGFyYW0ge2V2ZW50fSBlIGpRdWVyeSBldmVudCBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0IHtAbGluayBEYXRhVGFibGUubW9kZWxzLm9TZXR0aW5nc31cblx0ICogIEBwYXJhbSB7aW50ZWdlcn0gbGVuIE5ldyBsZW5ndGhcblx0ICovXG5cblx0LyoqXG5cdCAqIENvbHVtbiBzaXppbmcgaGFzIGNoYW5nZWQuXG5cdCAqICBAbmFtZSBEYXRhVGFibGUjY29sdW1uLXNpemluZy5kdFxuXHQgKiAgQGV2ZW50XG5cdCAqICBAcGFyYW0ge2V2ZW50fSBlIGpRdWVyeSBldmVudCBvYmplY3Rcblx0ICogIEBwYXJhbSB7b2JqZWN0fSBvIERhdGFUYWJsZXMgc2V0dGluZ3Mgb2JqZWN0IHtAbGluayBEYXRhVGFibGUubW9kZWxzLm9TZXR0aW5nc31cblx0ICovXG5cblx0LyoqXG5cdCAqIENvbHVtbiB2aXNpYmlsaXR5IGhhcyBjaGFuZ2VkLlxuXHQgKiAgQG5hbWUgRGF0YVRhYmxlI2NvbHVtbi12aXNpYmlsaXR5LmR0XG5cdCAqICBAZXZlbnRcblx0ICogIEBwYXJhbSB7ZXZlbnR9IGUgalF1ZXJ5IGV2ZW50IG9iamVjdFxuXHQgKiAgQHBhcmFtIHtvYmplY3R9IG8gRGF0YVRhYmxlcyBzZXR0aW5ncyBvYmplY3Qge0BsaW5rIERhdGFUYWJsZS5tb2RlbHMub1NldHRpbmdzfVxuXHQgKiAgQHBhcmFtIHtpbnR9IGNvbHVtbiBDb2x1bW4gaW5kZXhcblx0ICogIEBwYXJhbSB7Ym9vbH0gdmlzIGBmYWxzZWAgaWYgY29sdW1uIG5vdyBoaWRkZW4sIG9yIGB0cnVlYCBpZiB2aXNpYmxlXG5cdCAqL1xuXG5cdHJldHVybiAkLmZuLmRhdGFUYWJsZTtcbn0pKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2RhdGF0YWJsZXMubmV0L2pzL2pxdWVyeS5kYXRhVGFibGVzLmpzXG4vLyBtb2R1bGUgaWQgPSA0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBBZnJpa2FhbnMgW2FmXVxuLy8hIGF1dGhvciA6IFdlcm5lciBNb2xsZW50emUgOiBodHRwczovL2dpdGh1Yi5jb20vd2VybmVybVxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBhZiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2FmJywge1xuICAgIG1vbnRocyA6ICdKYW51YXJpZV9GZWJydWFyaWVfTWFhcnRfQXByaWxfTWVpX0p1bmllX0p1bGllX0F1Z3VzdHVzX1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTXJ0X0Fwcl9NZWlfSnVuX0p1bF9BdWdfU2VwX09rdF9Ob3ZfRGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1NvbmRhZ19NYWFuZGFnX0RpbnNkYWdfV29lbnNkYWdfRG9uZGVyZGFnX1ZyeWRhZ19TYXRlcmRhZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1Nvbl9NYWFfRGluX1dvZV9Eb25fVnJ5X1NhdCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTb19NYV9EaV9Xb19Eb19Wcl9TYScuc3BsaXQoJ18nKSxcbiAgICBtZXJpZGllbVBhcnNlOiAvdm18bm0vaSxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXm5tJC9pLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ3ZtJyA6ICdWTSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdubScgOiAnTk0nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVmFuZGFnIG9tXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW03DtHJlIG9tXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW29tXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0dpc3RlciBvbV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbTGFhc10gZGRkZCBbb21dIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ29vciAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgZ2VsZWRlJyxcbiAgICAgICAgcyA6ICdcXCduIHBhYXIgc2Vrb25kZXMnLFxuICAgICAgICBzcyA6ICclZCBzZWtvbmRlcycsXG4gICAgICAgIG0gOiAnXFwnbiBtaW51dXQnLFxuICAgICAgICBtbSA6ICclZCBtaW51dGUnLFxuICAgICAgICBoIDogJ1xcJ24gdXVyJyxcbiAgICAgICAgaGggOiAnJWQgdXJlJyxcbiAgICAgICAgZCA6ICdcXCduIGRhZycsXG4gICAgICAgIGRkIDogJyVkIGRhZScsXG4gICAgICAgIE0gOiAnXFwnbiBtYWFuZCcsXG4gICAgICAgIE1NIDogJyVkIG1hYW5kZScsXG4gICAgICAgIHkgOiAnXFwnbiBqYWFyJyxcbiAgICAgICAgeXkgOiAnJWQgamFhcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdGV8ZGUpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgKChudW1iZXIgPT09IDEgfHwgbnVtYmVyID09PSA4IHx8IG51bWJlciA+PSAyMCkgPyAnc3RlJyA6ICdkZScpOyAvLyBUaGFua3MgdG8gSm9yaXMgUsO2bGluZyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qanVwaXRlclxuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTWFhbmRhZyBpcyBkaWUgZWVyc3RlIGRhZyB2YW4gZGllIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIERpZSB3ZWVrIHdhdCBkaWUgNGRlIEphbnVhcmllIGJldmF0IGlzIGRpZSBlZXJzdGUgd2VlayB2YW4gZGllIGphYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBhZjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvYWYuanNcbi8vIG1vZHVsZSBpZCA9IDVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEFyYWJpYyBbYXJdXG4vLyEgYXV0aG9yIDogQWJkZWwgU2FpZDogaHR0cHM6Ly9naXRodWIuY29tL2FiZGVsc2FpZFxuLy8hIGF1dGhvciA6IEFobWVkIEVsa2hhdGliXG4vLyEgYXV0aG9yIDogZm9yYWJpIGh0dHBzOi8vZ2l0aHViLmNvbS9mb3JhYmlcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgc3ltYm9sTWFwID0ge1xuICAgICcxJzogJ9mhJyxcbiAgICAnMic6ICfZoicsXG4gICAgJzMnOiAn2aMnLFxuICAgICc0JzogJ9mkJyxcbiAgICAnNSc6ICfZpScsXG4gICAgJzYnOiAn2aYnLFxuICAgICc3JzogJ9mnJyxcbiAgICAnOCc6ICfZqCcsXG4gICAgJzknOiAn2aknLFxuICAgICcwJzogJ9mgJ1xufTtcbnZhciBudW1iZXJNYXAgPSB7XG4gICAgJ9mhJzogJzEnLFxuICAgICfZoic6ICcyJyxcbiAgICAn2aMnOiAnMycsXG4gICAgJ9mkJzogJzQnLFxuICAgICfZpSc6ICc1JyxcbiAgICAn2aYnOiAnNicsXG4gICAgJ9mnJzogJzcnLFxuICAgICfZqCc6ICc4JyxcbiAgICAn2aknOiAnOScsXG4gICAgJ9mgJzogJzAnXG59O1xudmFyIHBsdXJhbEZvcm0gPSBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuID09PSAwID8gMCA6IG4gPT09IDEgPyAxIDogbiA9PT0gMiA/IDIgOiBuICUgMTAwID49IDMgJiYgbiAlIDEwMCA8PSAxMCA/IDMgOiBuICUgMTAwID49IDExID8gNCA6IDU7XG59O1xudmFyIHBsdXJhbHMgPSB7XG4gICAgcyA6IFsn2KPZgtmEINmF2YYg2KvYp9mG2YrYqScsICfYq9in2YbZitipINmI2KfYrdiv2KknLCBbJ9ir2KfZhtmK2KrYp9mGJywgJ9ir2KfZhtmK2KrZitmGJ10sICclZCDYq9mI2KfZhicsICclZCDYq9in2YbZitipJywgJyVkINir2KfZhtmK2KknXSxcbiAgICBtIDogWyfYo9mC2YQg2YXZhiDYr9mC2YrZgtipJywgJ9iv2YLZitmC2Kkg2YjYp9it2K/YqScsIFsn2K/ZgtmK2YLYqtin2YYnLCAn2K/ZgtmK2YLYqtmK2YYnXSwgJyVkINiv2YLYp9im2YInLCAnJWQg2K/ZgtmK2YLYqScsICclZCDYr9mC2YrZgtipJ10sXG4gICAgaCA6IFsn2KPZgtmEINmF2YYg2LPYp9i52KknLCAn2LPYp9i52Kkg2YjYp9it2K/YqScsIFsn2LPYp9i52KrYp9mGJywgJ9iz2KfYudiq2YrZhiddLCAnJWQg2LPYp9i52KfYqicsICclZCDYs9in2LnYqScsICclZCDYs9in2LnYqSddLFxuICAgIGQgOiBbJ9ij2YLZhCDZhdmGINmK2YjZhScsICfZitmI2YUg2YjYp9it2K8nLCBbJ9mK2YjZhdin2YYnLCAn2YrZiNmF2YrZhiddLCAnJWQg2KPZitin2YUnLCAnJWQg2YrZiNmF2YvYpycsICclZCDZitmI2YUnXSxcbiAgICBNIDogWyfYo9mC2YQg2YXZhiDYtNmH2LEnLCAn2LTZh9ixINmI2KfYrdivJywgWyfYtNmH2LHYp9mGJywgJ9i02YfYsdmK2YYnXSwgJyVkINij2LTZh9ixJywgJyVkINi02YfYsdinJywgJyVkINi02YfYsSddLFxuICAgIHkgOiBbJ9ij2YLZhCDZhdmGINi52KfZhScsICfYudin2YUg2YjYp9it2K8nLCBbJ9i52KfZhdin2YYnLCAn2LnYp9mF2YrZhiddLCAnJWQg2KPYudmI2KfZhScsICclZCDYudin2YXZi9inJywgJyVkINi52KfZhSddXG59O1xudmFyIHBsdXJhbGl6ZSA9IGZ1bmN0aW9uICh1KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIGYgPSBwbHVyYWxGb3JtKG51bWJlciksXG4gICAgICAgICAgICBzdHIgPSBwbHVyYWxzW3VdW3BsdXJhbEZvcm0obnVtYmVyKV07XG4gICAgICAgIGlmIChmID09PSAyKSB7XG4gICAgICAgICAgICBzdHIgPSBzdHJbd2l0aG91dFN1ZmZpeCA/IDAgOiAxXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UoLyVkL2ksIG51bWJlcik7XG4gICAgfTtcbn07XG52YXIgbW9udGhzID0gW1xuICAgICfZitmG2KfZitixJyxcbiAgICAn2YHYqNix2KfZitixJyxcbiAgICAn2YXYp9ix2LMnLFxuICAgICfYo9io2LHZitmEJyxcbiAgICAn2YXYp9mK2YgnLFxuICAgICfZitmI2YbZitmIJyxcbiAgICAn2YrZiNmE2YrZiCcsXG4gICAgJ9ij2LrYs9i32LMnLFxuICAgICfYs9io2KrZhdio2LEnLFxuICAgICfYo9mD2KrZiNio2LEnLFxuICAgICfZhtmI2YHZhdio2LEnLFxuICAgICfYr9mK2LPZhdio2LEnXG5dO1xuXG52YXIgYXIgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdhcicsIHtcbiAgICBtb250aHMgOiBtb250aHMsXG4gICAgbW9udGhzU2hvcnQgOiBtb250aHMsXG4gICAgd2Vla2RheXMgOiAn2KfZhNij2K3Yr1/Yp9mE2KXYq9mG2YrZhl/Yp9mE2KvZhNin2KvYp9ihX9in2YTYo9ix2KjYudin2KFf2KfZhNiu2YXZitizX9in2YTYrNmF2LnYqV/Yp9mE2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn2KPYrdivX9il2KvZhtmK2YZf2KvZhNin2KvYp9ihX9ij2LHYqNi52KfYoV/YrtmF2YrYs1/YrNmF2LnYqV/Ys9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn2K1f2YZf2Ktf2LFf2K5f2Kxf2LMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0QvXFx1MjAwRk0vXFx1MjAwRllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/YtXzZhS8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gJ9mFJyA9PT0gaW5wdXQ7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfYtSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ9mFJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb2LrYr9mL2Kcg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW9i52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdERheTogJ1vYo9mF2LMg2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ2RkZGQgW9i52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn2KjYudivICVzJyxcbiAgICAgICAgcGFzdCA6ICfZhdmG2LAgJXMnLFxuICAgICAgICBzIDogcGx1cmFsaXplKCdzJyksXG4gICAgICAgIHNzIDogcGx1cmFsaXplKCdzJyksXG4gICAgICAgIG0gOiBwbHVyYWxpemUoJ20nKSxcbiAgICAgICAgbW0gOiBwbHVyYWxpemUoJ20nKSxcbiAgICAgICAgaCA6IHBsdXJhbGl6ZSgnaCcpLFxuICAgICAgICBoaCA6IHBsdXJhbGl6ZSgnaCcpLFxuICAgICAgICBkIDogcGx1cmFsaXplKCdkJyksXG4gICAgICAgIGRkIDogcGx1cmFsaXplKCdkJyksXG4gICAgICAgIE0gOiBwbHVyYWxpemUoJ00nKSxcbiAgICAgICAgTU0gOiBwbHVyYWxpemUoJ00nKSxcbiAgICAgICAgeSA6IHBsdXJhbGl6ZSgneScpLFxuICAgICAgICB5eSA6IHBsdXJhbGl6ZSgneScpXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vZodmi2aPZpNml2abZp9mo2anZoF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDEyICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBhcjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvYXIuanNcbi8vIG1vZHVsZSBpZCA9IDZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEFyYWJpYyAoQWxnZXJpYSkgW2FyLWR6XVxuLy8hIGF1dGhvciA6IE5vdXJlZGRpbmUgTE9VQUhFREogOiBodHRwczovL2dpdGh1Yi5jb20vbm91cmVkZGluZW1lXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGFyRHogPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdhci1keicsIHtcbiAgICBtb250aHMgOiAn2KzYp9mG2YHZil/ZgdmK2YHYsdmKX9mF2KfYsdizX9ij2YHYsdmK2YRf2YXYp9mKX9is2YjYp9mGX9is2YjZitmE2YrYqV/Yo9mI2Kpf2LPYqNiq2YXYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YHZhdio2LFf2K/Zitiz2YXYqNixJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ9is2KfZhtmB2Ypf2YHZitmB2LHZil/Zhdin2LHYs1/Yo9mB2LHZitmEX9mF2KfZil/YrNmI2KfZhl/YrNmI2YrZhNmK2Klf2KPZiNiqX9iz2KjYqtmF2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmB2YXYqNixX9iv2YrYs9mF2KjYsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfYp9mE2KPYrdivX9in2YTYpdir2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfYp9it2K9f2KfYq9mG2YrZhl/Yq9mE2KfYq9in2KFf2KfYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfYo9itX9il2Ktf2KvZhNinX9ij2LFf2K7ZhV/YrNmFX9iz2KgnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW9in2YTZitmI2YUg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9i62K/YpyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW9ij2YXYsyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfZgdmKICVzJyxcbiAgICAgICAgcGFzdCA6ICfZhdmG2LAgJXMnLFxuICAgICAgICBzIDogJ9ir2YjYp9mGJyxcbiAgICAgICAgc3MgOiAnJWQg2KvYp9mG2YrYqScsXG4gICAgICAgIG0gOiAn2K/ZgtmK2YLYqScsXG4gICAgICAgIG1tIDogJyVkINiv2YLYp9im2YInLFxuICAgICAgICBoIDogJ9iz2KfYudipJyxcbiAgICAgICAgaGggOiAnJWQg2LPYp9i52KfYqicsXG4gICAgICAgIGQgOiAn2YrZiNmFJyxcbiAgICAgICAgZGQgOiAnJWQg2KPZitin2YUnLFxuICAgICAgICBNIDogJ9i02YfYsScsXG4gICAgICAgIE1NIDogJyVkINij2LTZh9ixJyxcbiAgICAgICAgeSA6ICfYs9mG2KknLFxuICAgICAgICB5eSA6ICclZCDYs9mG2YjYp9iqJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGFyRHo7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2FyLWR6LmpzXG4vLyBtb2R1bGUgaWQgPSA3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBBcmFiaWMgKEt1d2FpdCkgW2FyLWt3XVxuLy8hIGF1dGhvciA6IE51c3JldCBQYXJsYWs6IGh0dHBzOi8vZ2l0aHViLmNvbS9udXNyZXRwYXJsYWtcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgYXJLdyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2FyLWt3Jywge1xuICAgIG1vbnRocyA6ICfZitmG2KfZitixX9mB2KjYsdin2YrYsV/Zhdin2LHYs1/Yo9io2LHZitmEX9mF2KfZil/ZitmI2YbZitmIX9mK2YjZhNmK2YjYsl/Yuti02Kpf2LTYqtmG2KjYsV/Yo9mD2KrZiNio2LFf2YbZiNmG2KjYsV/Yr9is2YbYqNixJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ9mK2YbYp9mK2LFf2YHYqNix2KfZitixX9mF2KfYsdizX9ij2KjYsdmK2YRf2YXYp9mKX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiNiyX9i62LTYql/YtNiq2YbYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YbYqNixX9iv2KzZhtio2LEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn2KfZhNij2K3Yr1/Yp9mE2KXYqtmG2YrZhl/Yp9mE2KvZhNin2KvYp9ihX9in2YTYo9ix2KjYudin2KFf2KfZhNiu2YXZitizX9in2YTYrNmF2LnYqV/Yp9mE2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn2KfYrdivX9in2KrZhtmK2YZf2KvZhNin2KvYp9ihX9in2LHYqNi52KfYoV/YrtmF2YrYs1/YrNmF2LnYqV/Ys9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn2K1f2YZf2Ktf2LFf2K5f2Kxf2LMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW9in2YTZitmI2YUg2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9i62K/YpyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW9ij2YXYsyDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb2LnZhNmJINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfZgdmKICVzJyxcbiAgICAgICAgcGFzdCA6ICfZhdmG2LAgJXMnLFxuICAgICAgICBzIDogJ9ir2YjYp9mGJyxcbiAgICAgICAgc3MgOiAnJWQg2KvYp9mG2YrYqScsXG4gICAgICAgIG0gOiAn2K/ZgtmK2YLYqScsXG4gICAgICAgIG1tIDogJyVkINiv2YLYp9im2YInLFxuICAgICAgICBoIDogJ9iz2KfYudipJyxcbiAgICAgICAgaGggOiAnJWQg2LPYp9i52KfYqicsXG4gICAgICAgIGQgOiAn2YrZiNmFJyxcbiAgICAgICAgZGQgOiAnJWQg2KPZitin2YUnLFxuICAgICAgICBNIDogJ9i02YfYsScsXG4gICAgICAgIE1NIDogJyVkINij2LTZh9ixJyxcbiAgICAgICAgeSA6ICfYs9mG2KknLFxuICAgICAgICB5eSA6ICclZCDYs9mG2YjYp9iqJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDEyICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBhckt3O1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci1rdy5qc1xuLy8gbW9kdWxlIGlkID0gOFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQXJhYmljIChMeWJpYSkgW2FyLWx5XVxuLy8hIGF1dGhvciA6IEFsaSBIbWVyOiBodHRwczovL2dpdGh1Yi5jb20va2lrb2FuaXNcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgc3ltYm9sTWFwID0ge1xuICAgICcxJzogJzEnLFxuICAgICcyJzogJzInLFxuICAgICczJzogJzMnLFxuICAgICc0JzogJzQnLFxuICAgICc1JzogJzUnLFxuICAgICc2JzogJzYnLFxuICAgICc3JzogJzcnLFxuICAgICc4JzogJzgnLFxuICAgICc5JzogJzknLFxuICAgICcwJzogJzAnXG59O1xudmFyIHBsdXJhbEZvcm0gPSBmdW5jdGlvbiAobikge1xuICAgIHJldHVybiBuID09PSAwID8gMCA6IG4gPT09IDEgPyAxIDogbiA9PT0gMiA/IDIgOiBuICUgMTAwID49IDMgJiYgbiAlIDEwMCA8PSAxMCA/IDMgOiBuICUgMTAwID49IDExID8gNCA6IDU7XG59O1xudmFyIHBsdXJhbHMgPSB7XG4gICAgcyA6IFsn2KPZgtmEINmF2YYg2KvYp9mG2YrYqScsICfYq9in2YbZitipINmI2KfYrdiv2KknLCBbJ9ir2KfZhtmK2KrYp9mGJywgJ9ir2KfZhtmK2KrZitmGJ10sICclZCDYq9mI2KfZhicsICclZCDYq9in2YbZitipJywgJyVkINir2KfZhtmK2KknXSxcbiAgICBtIDogWyfYo9mC2YQg2YXZhiDYr9mC2YrZgtipJywgJ9iv2YLZitmC2Kkg2YjYp9it2K/YqScsIFsn2K/ZgtmK2YLYqtin2YYnLCAn2K/ZgtmK2YLYqtmK2YYnXSwgJyVkINiv2YLYp9im2YInLCAnJWQg2K/ZgtmK2YLYqScsICclZCDYr9mC2YrZgtipJ10sXG4gICAgaCA6IFsn2KPZgtmEINmF2YYg2LPYp9i52KknLCAn2LPYp9i52Kkg2YjYp9it2K/YqScsIFsn2LPYp9i52KrYp9mGJywgJ9iz2KfYudiq2YrZhiddLCAnJWQg2LPYp9i52KfYqicsICclZCDYs9in2LnYqScsICclZCDYs9in2LnYqSddLFxuICAgIGQgOiBbJ9ij2YLZhCDZhdmGINmK2YjZhScsICfZitmI2YUg2YjYp9it2K8nLCBbJ9mK2YjZhdin2YYnLCAn2YrZiNmF2YrZhiddLCAnJWQg2KPZitin2YUnLCAnJWQg2YrZiNmF2YvYpycsICclZCDZitmI2YUnXSxcbiAgICBNIDogWyfYo9mC2YQg2YXZhiDYtNmH2LEnLCAn2LTZh9ixINmI2KfYrdivJywgWyfYtNmH2LHYp9mGJywgJ9i02YfYsdmK2YYnXSwgJyVkINij2LTZh9ixJywgJyVkINi02YfYsdinJywgJyVkINi02YfYsSddLFxuICAgIHkgOiBbJ9ij2YLZhCDZhdmGINi52KfZhScsICfYudin2YUg2YjYp9it2K8nLCBbJ9i52KfZhdin2YYnLCAn2LnYp9mF2YrZhiddLCAnJWQg2KPYudmI2KfZhScsICclZCDYudin2YXZi9inJywgJyVkINi52KfZhSddXG59O1xudmFyIHBsdXJhbGl6ZSA9IGZ1bmN0aW9uICh1KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpIHtcbiAgICAgICAgdmFyIGYgPSBwbHVyYWxGb3JtKG51bWJlciksXG4gICAgICAgICAgICBzdHIgPSBwbHVyYWxzW3VdW3BsdXJhbEZvcm0obnVtYmVyKV07XG4gICAgICAgIGlmIChmID09PSAyKSB7XG4gICAgICAgICAgICBzdHIgPSBzdHJbd2l0aG91dFN1ZmZpeCA/IDAgOiAxXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc3RyLnJlcGxhY2UoLyVkL2ksIG51bWJlcik7XG4gICAgfTtcbn07XG52YXIgbW9udGhzID0gW1xuICAgICfZitmG2KfZitixJyxcbiAgICAn2YHYqNix2KfZitixJyxcbiAgICAn2YXYp9ix2LMnLFxuICAgICfYo9io2LHZitmEJyxcbiAgICAn2YXYp9mK2YgnLFxuICAgICfZitmI2YbZitmIJyxcbiAgICAn2YrZiNmE2YrZiCcsXG4gICAgJ9ij2LrYs9i32LMnLFxuICAgICfYs9io2KrZhdio2LEnLFxuICAgICfYo9mD2KrZiNio2LEnLFxuICAgICfZhtmI2YHZhdio2LEnLFxuICAgICfYr9mK2LPZhdio2LEnXG5dO1xuXG52YXIgYXJMeSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2FyLWx5Jywge1xuICAgIG1vbnRocyA6IG1vbnRocyxcbiAgICBtb250aHNTaG9ydCA6IG1vbnRocyxcbiAgICB3ZWVrZGF5cyA6ICfYp9mE2KPYrdivX9in2YTYpdir2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfYo9it2K9f2KXYq9mG2YrZhl/Yq9mE2KfYq9in2KFf2KPYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnRC9cXHUyMDBGTS9cXHUyMDBGWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL9i1fNmFLyxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAn2YUnID09PSBpbnB1dDtcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ9i1JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn2YUnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1vYp9mE2YrZiNmFINi52YbYryDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dERheTogJ1vYutiv2YvYpyDYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBb2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW9ij2YXYsyDYudmG2K8g2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnZGRkZCBb2LnZhtivINin2YTYs9in2LnYqV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfYqNi52K8gJXMnLFxuICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgIHMgOiBwbHVyYWxpemUoJ3MnKSxcbiAgICAgICAgc3MgOiBwbHVyYWxpemUoJ3MnKSxcbiAgICAgICAgbSA6IHBsdXJhbGl6ZSgnbScpLFxuICAgICAgICBtbSA6IHBsdXJhbGl6ZSgnbScpLFxuICAgICAgICBoIDogcGx1cmFsaXplKCdoJyksXG4gICAgICAgIGhoIDogcGx1cmFsaXplKCdoJyksXG4gICAgICAgIGQgOiBwbHVyYWxpemUoJ2QnKSxcbiAgICAgICAgZGQgOiBwbHVyYWxpemUoJ2QnKSxcbiAgICAgICAgTSA6IHBsdXJhbGl6ZSgnTScpLFxuICAgICAgICBNTSA6IHBsdXJhbGl6ZSgnTScpLFxuICAgICAgICB5IDogcGx1cmFsaXplKCd5JyksXG4gICAgICAgIHl5IDogcGx1cmFsaXplKCd5JylcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDEyICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBhckx5O1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci1seS5qc1xuLy8gbW9kdWxlIGlkID0gOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQXJhYmljIChNb3JvY2NvKSBbYXItbWFdXG4vLyEgYXV0aG9yIDogRWxGYWRpbGkgWWFzc2luZSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9FbEZhZGlsaVlcbi8vISBhdXRob3IgOiBBYmRlbCBTYWlkIDogaHR0cHM6Ly9naXRodWIuY29tL2FiZGVsc2FpZFxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBhck1hID0gbW9tZW50LmRlZmluZUxvY2FsZSgnYXItbWEnLCB7XG4gICAgbW9udGhzIDogJ9mK2YbYp9mK2LFf2YHYqNix2KfZitixX9mF2KfYsdizX9ij2KjYsdmK2YRf2YXYp9mKX9mK2YjZhtmK2Yhf2YrZiNmE2YrZiNiyX9i62LTYql/YtNiq2YbYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YbYqNixX9iv2KzZhtio2LEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2Ypf2YrZiNmG2YrZiF/ZitmI2YTZitmI2LJf2LrYtNiqX9i02KrZhtio2LFf2KPZg9iq2YjYqNixX9mG2YjZhtio2LFf2K/YrNmG2KjYsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfYp9mE2KPYrdivX9in2YTYpdiq2YbZitmGX9in2YTYq9mE2KfYq9in2KFf2KfZhNij2LHYqNi52KfYoV/Yp9mE2K7ZhdmK2LNf2KfZhNis2YXYudipX9in2YTYs9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfYp9it2K9f2KfYqtmG2YrZhl/Yq9mE2KfYq9in2KFf2KfYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfYrV/Zhl/Yq1/YsV/Yrl/YrF/Ysycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9mB2YogJXMnLFxuICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgIHMgOiAn2KvZiNin2YYnLFxuICAgICAgICBzcyA6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgbSA6ICfYr9mC2YrZgtipJyxcbiAgICAgICAgbW0gOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgIGggOiAn2LPYp9i52KknLFxuICAgICAgICBoaCA6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgZCA6ICfZitmI2YUnLFxuICAgICAgICBkZCA6ICclZCDYo9mK2KfZhScsXG4gICAgICAgIE0gOiAn2LTZh9ixJyxcbiAgICAgICAgTU0gOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICB5IDogJ9iz2YbYqScsXG4gICAgICAgIHl5IDogJyVkINiz2YbZiNin2KonXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiA2LCAvLyBTYXR1cmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiAxMiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gYXJNYTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvYXItbWEuanNcbi8vIG1vZHVsZSBpZCA9IDEwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBBcmFiaWMgKFNhdWRpIEFyYWJpYSkgW2FyLXNhXVxuLy8hIGF1dGhvciA6IFN1aGFpbCBBbGtvd2FpbGVldCA6IGh0dHBzOi8vZ2l0aHViLmNvbS94c29oXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHN5bWJvbE1hcCA9IHtcbiAgICAnMSc6ICfZoScsXG4gICAgJzInOiAn2aInLFxuICAgICczJzogJ9mjJyxcbiAgICAnNCc6ICfZpCcsXG4gICAgJzUnOiAn2aUnLFxuICAgICc2JzogJ9mmJyxcbiAgICAnNyc6ICfZpycsXG4gICAgJzgnOiAn2agnLFxuICAgICc5JzogJ9mpJyxcbiAgICAnMCc6ICfZoCdcbn07XG52YXIgbnVtYmVyTWFwID0ge1xuICAgICfZoSc6ICcxJyxcbiAgICAn2aInOiAnMicsXG4gICAgJ9mjJzogJzMnLFxuICAgICfZpCc6ICc0JyxcbiAgICAn2aUnOiAnNScsXG4gICAgJ9mmJzogJzYnLFxuICAgICfZpyc6ICc3JyxcbiAgICAn2agnOiAnOCcsXG4gICAgJ9mpJzogJzknLFxuICAgICfZoCc6ICcwJ1xufTtcblxudmFyIGFyU2EgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdhci1zYScsIHtcbiAgICBtb250aHMgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2YrZiF/ZitmI2YbZitmIX9mK2YjZhNmK2Yhf2KPYutiz2LfYs1/Ys9io2KrZhdio2LFf2KPZg9iq2YjYqNixX9mG2YjZgdmF2KjYsV/Yr9mK2LPZhdio2LEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn2YrZhtin2YrYsV/Zgdio2LHYp9mK2LFf2YXYp9ix2LNf2KPYqNix2YrZhF/Zhdin2YrZiF/ZitmI2YbZitmIX9mK2YjZhNmK2Yhf2KPYutiz2LfYs1/Ys9io2KrZhdio2LFf2KPZg9iq2YjYqNixX9mG2YjZgdmF2KjYsV/Yr9mK2LPZhdio2LEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn2KfZhNij2K3Yr1/Yp9mE2KXYq9mG2YrZhl/Yp9mE2KvZhNin2KvYp9ihX9in2YTYo9ix2KjYudin2KFf2KfZhNiu2YXZitizX9in2YTYrNmF2LnYqV/Yp9mE2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn2KPYrdivX9il2KvZhtmK2YZf2KvZhNin2KvYp9ihX9ij2LHYqNi52KfYoV/YrtmF2YrYs1/YrNmF2LnYqV/Ys9io2KonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn2K1f2YZf2Ktf2LFf2K5f2Kxf2LMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/YtXzZhS8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gJ9mFJyA9PT0gaW5wdXQ7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfYtSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ9mFJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9mB2YogJXMnLFxuICAgICAgICBwYXN0IDogJ9mF2YbYsCAlcycsXG4gICAgICAgIHMgOiAn2KvZiNin2YYnLFxuICAgICAgICBzcyA6ICclZCDYq9in2YbZitipJyxcbiAgICAgICAgbSA6ICfYr9mC2YrZgtipJyxcbiAgICAgICAgbW0gOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgIGggOiAn2LPYp9i52KknLFxuICAgICAgICBoaCA6ICclZCDYs9in2LnYp9iqJyxcbiAgICAgICAgZCA6ICfZitmI2YUnLFxuICAgICAgICBkZCA6ICclZCDYo9mK2KfZhScsXG4gICAgICAgIE0gOiAn2LTZh9ixJyxcbiAgICAgICAgTU0gOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICB5IDogJ9iz2YbYqScsXG4gICAgICAgIHl5IDogJyVkINiz2YbZiNin2KonXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vZodmi2aPZpNml2abZp9mo2anZoF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBhclNhO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hci1zYS5qc1xuLy8gbW9kdWxlIGlkID0gMTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSAgOiAgQXJhYmljIChUdW5pc2lhKSBbYXItdG5dXG4vLyEgYXV0aG9yIDogTmFkZXIgVG91a2FicmkgOiBodHRwczovL2dpdGh1Yi5jb20vbmFkZXJpb1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBhclRuID0gbW9tZW50LmRlZmluZUxvY2FsZSgnYXItdG4nLCB7XG4gICAgbW9udGhzOiAn2KzYp9mG2YHZil/ZgdmK2YHYsdmKX9mF2KfYsdizX9ij2YHYsdmK2YRf2YXYp9mKX9is2YjYp9mGX9is2YjZitmE2YrYqV/Yo9mI2Kpf2LPYqNiq2YXYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YHZhdio2LFf2K/Zitiz2YXYqNixJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAn2KzYp9mG2YHZil/ZgdmK2YHYsdmKX9mF2KfYsdizX9ij2YHYsdmK2YRf2YXYp9mKX9is2YjYp9mGX9is2YjZitmE2YrYqV/Yo9mI2Kpf2LPYqNiq2YXYqNixX9ij2YPYqtmI2KjYsV/ZhtmI2YHZhdio2LFf2K/Zitiz2YXYqNixJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzOiAn2KfZhNij2K3Yr1/Yp9mE2KXYq9mG2YrZhl/Yp9mE2KvZhNin2KvYp9ihX9in2YTYo9ix2KjYudin2KFf2KfZhNiu2YXZitizX9in2YTYrNmF2LnYqV/Yp9mE2LPYqNiqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQ6ICfYo9it2K9f2KXYq9mG2YrZhl/Yq9mE2KfYq9in2KFf2KPYsdio2LnYp9ihX9iu2YXZitizX9is2YXYudipX9iz2KjYqicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbjogJ9itX9mGX9irX9ixX9iuX9isX9izJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgTDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb2KfZhNmK2YjZhSDYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb2LrYr9inINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb2KPZhdizINi52YTZiSDYp9mE2LPYp9i52KldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvYudmE2Ykg2KfZhNiz2KfYudipXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICBmdXR1cmU6ICfZgdmKICVzJyxcbiAgICAgICAgcGFzdDogJ9mF2YbYsCAlcycsXG4gICAgICAgIHM6ICfYq9mI2KfZhicsXG4gICAgICAgIHNzIDogJyVkINir2KfZhtmK2KknLFxuICAgICAgICBtOiAn2K/ZgtmK2YLYqScsXG4gICAgICAgIG1tOiAnJWQg2K/Zgtin2KbZgicsXG4gICAgICAgIGg6ICfYs9in2LnYqScsXG4gICAgICAgIGhoOiAnJWQg2LPYp9i52KfYqicsXG4gICAgICAgIGQ6ICfZitmI2YUnLFxuICAgICAgICBkZDogJyVkINij2YrYp9mFJyxcbiAgICAgICAgTTogJ9i02YfYsScsXG4gICAgICAgIE1NOiAnJWQg2KPYtNmH2LEnLFxuICAgICAgICB5OiAn2LPZhtipJyxcbiAgICAgICAgeXk6ICclZCDYs9mG2YjYp9iqJ1xuICAgIH0sXG4gICAgd2Vlazoge1xuICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3k6IDQgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gYXJUbjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvYXItdG4uanNcbi8vIG1vZHVsZSBpZCA9IDEyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBBemVyYmFpamFuaSBbYXpdXG4vLyEgYXV0aG9yIDogdG9wY2hpeWV2IDogaHR0cHM6Ly9naXRodWIuY29tL3RvcGNoaXlldlxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBzdWZmaXhlcyA9IHtcbiAgICAxOiAnLWluY2knLFxuICAgIDU6ICctaW5jaScsXG4gICAgODogJy1pbmNpJyxcbiAgICA3MDogJy1pbmNpJyxcbiAgICA4MDogJy1pbmNpJyxcbiAgICAyOiAnLW5jaScsXG4gICAgNzogJy1uY2knLFxuICAgIDIwOiAnLW5jaScsXG4gICAgNTA6ICctbmNpJyxcbiAgICAzOiAnLcO8bmPDvCcsXG4gICAgNDogJy3DvG5jw7wnLFxuICAgIDEwMDogJy3DvG5jw7wnLFxuICAgIDY6ICctbmPEsScsXG4gICAgOTogJy11bmN1JyxcbiAgICAxMDogJy11bmN1JyxcbiAgICAzMDogJy11bmN1JyxcbiAgICA2MDogJy3EsW5jxLEnLFxuICAgIDkwOiAnLcSxbmPEsSdcbn07XG5cbnZhciBheiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2F6Jywge1xuICAgIG1vbnRocyA6ICd5YW52YXJfZmV2cmFsX21hcnRfYXByZWxfbWF5X2l5dW5faXl1bF9hdnF1c3Rfc2VudHlhYnJfb2t0eWFicl9ub3lhYnJfZGVrYWJyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ3lhbl9mZXZfbWFyX2Fwcl9tYXlfaXluX2l5bF9hdnFfc2VuX29rdF9ub3lfZGVrJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0JhemFyX0JhemFyIGVydMmZc2lfw4fJmXLFn8mZbmLJmSBheMWfYW3EsV/Dh8mZcsWfyZluYsmZX0PDvG3JmSBheMWfYW3EsV9Dw7xtyZlfxZ7JmW5iyZknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdCYXpfQnpFX8OHQXhfw4fJmXJfQ0F4X0PDvG1fxZ7JmW4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnQnpfQkVfw4dBX8OHyZlfQ0FfQ8O8X8WeyZknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbYnVnw7xuIHNhYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbc2FiYWggc2FhdF0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdbZ8mZbMmZbiBoyZlmdMmZXSBkZGRkIFtzYWF0XSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW2TDvG7JmW5dIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW2tlw6fJmW4gaMmZZnTJmV0gZGRkZCBbc2FhdF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMgc29ucmEnLFxuICAgICAgICBwYXN0IDogJyVzIMmZdnbJmWwnLFxuICAgICAgICBzIDogJ2Jpcm5lw6fJmSBzYW5peXnJmScsXG4gICAgICAgIHNzIDogJyVkIHNhbml5yZknLFxuICAgICAgICBtIDogJ2JpciBkyZlxaXHJmScsXG4gICAgICAgIG1tIDogJyVkIGTJmXFpccmZJyxcbiAgICAgICAgaCA6ICdiaXIgc2FhdCcsXG4gICAgICAgIGhoIDogJyVkIHNhYXQnLFxuICAgICAgICBkIDogJ2JpciBnw7xuJyxcbiAgICAgICAgZGQgOiAnJWQgZ8O8bicsXG4gICAgICAgIE0gOiAnYmlyIGF5JyxcbiAgICAgICAgTU0gOiAnJWQgYXknLFxuICAgICAgICB5IDogJ2JpciBpbCcsXG4gICAgICAgIHl5IDogJyVkIGlsJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL2dlY8mZfHPJmWjJmXJ8Z8O8bmTDvHp8YXjFn2FtLyxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXihnw7xuZMO8enxheMWfYW0pJC8udGVzdChpbnB1dCk7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ2dlY8mZJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAnc8mZaMmZcic7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICByZXR1cm4gJ2fDvG5kw7x6JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAnYXjFn2FtJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjEsW5jxLF8aW5jaXxuY2l8w7xuY8O8fG5jxLF8dW5jdSkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPT09IDApIHsgIC8vIHNwZWNpYWwgY2FzZSBmb3IgemVyb1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICctxLFuY8SxJztcbiAgICAgICAgfVxuICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgYiA9IG51bWJlciAlIDEwMCAtIGEsXG4gICAgICAgICAgICBjID0gbnVtYmVyID49IDEwMCA/IDEwMCA6IG51bGw7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAoc3VmZml4ZXNbYV0gfHwgc3VmZml4ZXNbYl0gfHwgc3VmZml4ZXNbY10pO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGF6O1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9hei5qc1xuLy8gbW9kdWxlIGlkID0gMTNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEJlbGFydXNpYW4gW2JlXVxuLy8hIGF1dGhvciA6IERtaXRyeSBEZW1pZG92IDogaHR0cHM6Ly9naXRodWIuY29tL2RlbWlkb3Y5MVxuLy8hIGF1dGhvcjogUHJhbGVza2E6IGh0dHA6Ly9wcmFsZXNrYS5wcm8vXG4vLyEgQXV0aG9yIDogTWVuZWxpb24gRWxlbnPDumxlIDogaHR0cHM6Ly9naXRodWIuY29tL09pcmVcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG5mdW5jdGlvbiBwbHVyYWwod29yZCwgbnVtKSB7XG4gICAgdmFyIGZvcm1zID0gd29yZC5zcGxpdCgnXycpO1xuICAgIHJldHVybiBudW0gJSAxMCA9PT0gMSAmJiBudW0gJSAxMDAgIT09IDExID8gZm9ybXNbMF0gOiAobnVtICUgMTAgPj0gMiAmJiBudW0gJSAxMCA8PSA0ICYmIChudW0gJSAxMDAgPCAxMCB8fCBudW0gJSAxMDAgPj0gMjApID8gZm9ybXNbMV0gOiBmb3Jtc1syXSk7XG59XG5mdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ3NzJzogd2l0aG91dFN1ZmZpeCA/ICfRgdC10LrRg9C90LTQsF/RgdC10LrRg9C90LTRi1/RgdC10LrRg9C90LQnIDogJ9GB0LXQutGD0L3QtNGDX9GB0LXQutGD0L3QtNGLX9GB0LXQutGD0L3QtCcsXG4gICAgICAgICdtbSc6IHdpdGhvdXRTdWZmaXggPyAn0YXQstGW0LvRltC90LBf0YXQstGW0LvRltC90Ytf0YXQstGW0LvRltC9JyA6ICfRhdCy0ZbQu9GW0L3Rg1/RhdCy0ZbQu9GW0L3Ri1/RhdCy0ZbQu9GW0L0nLFxuICAgICAgICAnaGgnOiB3aXRob3V0U3VmZml4ID8gJ9Cz0LDQtNC30ZbQvdCwX9Cz0LDQtNC30ZbQvdGLX9Cz0LDQtNC30ZbQvScgOiAn0LPQsNC00LfRltC90YNf0LPQsNC00LfRltC90Ytf0LPQsNC00LfRltC9JyxcbiAgICAgICAgJ2RkJzogJ9C00LfQtdC90Yxf0LTQvdGWX9C00LfRkdC9JyxcbiAgICAgICAgJ01NJzogJ9C80LXRgdGP0YZf0LzQtdGB0Y/RhtGLX9C80LXRgdGP0YbQsNGeJyxcbiAgICAgICAgJ3l5JzogJ9Cz0L7QtF/Qs9Cw0LTRi1/Qs9Cw0LTQvtGeJ1xuICAgIH07XG4gICAgaWYgKGtleSA9PT0gJ20nKSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9GF0LLRltC70ZbQvdCwJyA6ICfRhdCy0ZbQu9GW0L3Rgyc7XG4gICAgfVxuICAgIGVsc2UgaWYgKGtleSA9PT0gJ2gnKSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9Cz0LDQtNC30ZbQvdCwJyA6ICfQs9Cw0LTQt9GW0L3Rgyc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgcGx1cmFsKGZvcm1hdFtrZXldLCArbnVtYmVyKTtcbiAgICB9XG59XG5cbnZhciBiZSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2JlJywge1xuICAgIG1vbnRocyA6IHtcbiAgICAgICAgZm9ybWF0OiAn0YHRgtGD0LTQt9C10L3Rj1/Qu9GO0YLQsNCz0LBf0YHQsNC60LDQstGW0LrQsF/QutGA0LDRgdCw0LLRltC60LBf0YLRgNCw0Z7QvdGPX9GH0Y3RgNCy0LXQvdGPX9C70ZbQv9C10L3Rj1/QttC90ZbRntC90Y9f0LLQtdGA0LDRgdC90Y9f0LrQsNGB0YLRgNGL0YfQvdGW0LrQsF/Qu9GW0YHRgtCw0L/QsNC00LBf0YHQvdC10LbQvdGPJy5zcGxpdCgnXycpLFxuICAgICAgICBzdGFuZGFsb25lOiAn0YHRgtGD0LTQt9C10L3RjF/Qu9GO0YLRi1/RgdCw0LrQsNCy0ZbQul/QutGA0LDRgdCw0LLRltC6X9GC0YDQsNCy0LXQvdGMX9GH0Y3RgNCy0LXQvdGMX9C70ZbQv9C10L3RjF/QttC90ZbQstC10L3RjF/QstC10YDQsNGB0LXQvdGMX9C60LDRgdGC0YDRi9GH0L3RltC6X9C70ZbRgdGC0LDQv9Cw0LRf0YHQvdC10LbQsNC90YwnLnNwbGl0KCdfJylcbiAgICB9LFxuICAgIG1vbnRoc1Nob3J0IDogJ9GB0YLRg9C0X9C70Y7Rgl/RgdCw0Lpf0LrRgNCw0YFf0YLRgNCw0LJf0YfRjdGA0LJf0LvRltC/X9C20L3RltCyX9Cy0LXRgF/QutCw0YHRgl/Qu9GW0YHRgl/RgdC90LXQticuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6IHtcbiAgICAgICAgZm9ybWF0OiAn0L3Rj9C00LfQtdC70Y5f0L/QsNC90Y/QtNC30LXQu9Cw0Lpf0LDRntGC0L7RgNCw0Lpf0YHQtdGA0LDQtNGDX9GH0LDRhtCy0LXRgF/Qv9GP0YLQvdGW0YbRg1/RgdGD0LHQvtGC0YMnLnNwbGl0KCdfJyksXG4gICAgICAgIHN0YW5kYWxvbmU6ICfQvdGP0LTQt9C10LvRj1/Qv9Cw0L3Rj9C00LfQtdC70LDQul/QsNGe0YLQvtGA0LDQul/RgdC10YDQsNC00LBf0YfQsNGG0LLQtdGAX9C/0Y/RgtC90ZbRhtCwX9GB0YPQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICAgICAgaXNGb3JtYXQ6IC9cXFsgP1vQktCyXSA/KD860LzRltC90YPQu9GD0Y580L3QsNGB0YLRg9C/0L3Rg9GOKT8gP1xcXSA/ZGRkZC9cbiAgICB9LFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn0L3QtF/Qv9C9X9Cw0YJf0YHRgF/Rh9GGX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfQvdC0X9C/0L1f0LDRgl/RgdGAX9GH0YZf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZINCzLicsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSDQsy4sIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSDQsy4sIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb0KHRkdC90L3RjyDRnl0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW9CX0LDRntGC0YDQsCDRnl0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW9Cj0YfQvtGA0LAg0Z5dIExUJyxcbiAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW9CjXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQoyDQvNGW0L3Rg9C70YPRjl0gZGRkZCBb0Z5dIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0KMg0LzRltC90YPQu9GLXSBkZGRkIFvRnl0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfQv9GA0LDQtyAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMg0YLQsNC80YMnLFxuICAgICAgICBzIDogJ9C90LXQutCw0LvRjNC60ZYg0YHQtdC60YPQvdC0JyxcbiAgICAgICAgbSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIG1tIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgaCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIGhoIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgZCA6ICfQtNC30LXQvdGMJyxcbiAgICAgICAgZGQgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBNIDogJ9C80LXRgdGP0YYnLFxuICAgICAgICBNTSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIHkgOiAn0LPQvtC0JyxcbiAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv0L3QvtGH0Yt80YDQsNC90ZbRhtGLfNC00L3Rj3zQstC10YfQsNGA0LAvLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIC9eKNC00L3Rj3zQstC10YfQsNGA0LApJC8udGVzdChpbnB1dCk7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9C90L7Rh9GLJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn0YDQsNC90ZbRhtGLJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAn0LTQvdGPJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn0LLQtdGH0LDRgNCwJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjRlnzRi3zQs9CwKS8sXG4gICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIChudW1iZXIgJSAxMCA9PT0gMiB8fCBudW1iZXIgJSAxMCA9PT0gMykgJiYgKG51bWJlciAlIDEwMCAhPT0gMTIgJiYgbnVtYmVyICUgMTAwICE9PSAxMykgPyBudW1iZXIgKyAnLdGWJyA6IG51bWJlciArICct0YsnO1xuICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LPQsCc7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBiZTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvYmUuanNcbi8vIG1vZHVsZSBpZCA9IDE0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBCdWxnYXJpYW4gW2JnXVxuLy8hIGF1dGhvciA6IEtyYXNlbiBCb3Jpc292IDogaHR0cHM6Ly9naXRodWIuY29tL2tyYXpcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgYmcgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdiZycsIHtcbiAgICBtb250aHMgOiAn0Y/QvdGD0LDRgNC4X9GE0LXQstGA0YPQsNGA0Lhf0LzQsNGA0YJf0LDQv9GA0LjQu1/QvNCw0Llf0Y7QvdC4X9GO0LvQuF/QsNCy0LPRg9GB0YJf0YHQtdC/0YLQtdC80LLRgNC4X9C+0LrRgtC+0LzQstGA0Lhf0L3QvtC10LzQstGA0Lhf0LTQtdC60LXQvNCy0YDQuCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfRj9C90YBf0YTQtdCyX9C80LDRgF/QsNC/0YBf0LzQsNC5X9GO0L3QuF/RjtC70Lhf0LDQstCzX9GB0LXQv1/QvtC60YJf0L3QvtC1X9C00LXQuicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfQvdC10LTQtdC70Y9f0L/QvtC90LXQtNC10LvQvdC40Lpf0LLRgtC+0YDQvdC40Lpf0YHRgNGP0LTQsF/Rh9C10YLQstGK0YDRgtGK0Lpf0L/QtdGC0YrQul/RgdGK0LHQvtGC0LAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfQvdC10LRf0L/QvtC9X9Cy0YLQvl/RgdGA0Y9f0YfQtdGCX9C/0LXRgl/RgdGK0LEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn0L3QtF/Qv9C9X9Cy0YJf0YHRgF/Rh9GCX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW9CU0L3QtdGBINCyXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9Cj0YLRgNC1INCyXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW9CyXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW9CS0YfQtdGA0LAg0LJdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JIg0LjQt9C80LjQvdCw0LvQsNGC0LBdIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDQuNC30LzQuNC90LDQu9C40Y9dIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfRgdC70LXQtCAlcycsXG4gICAgICAgIHBhc3QgOiAn0L/RgNC10LTQuCAlcycsXG4gICAgICAgIHMgOiAn0L3Rj9C60L7Qu9C60L4g0YHQtdC60YPQvdC00LgnLFxuICAgICAgICBzcyA6ICclZCDRgdC10LrRg9C90LTQuCcsXG4gICAgICAgIG0gOiAn0LzQuNC90YPRgtCwJyxcbiAgICAgICAgbW0gOiAnJWQg0LzQuNC90YPRgtC4JyxcbiAgICAgICAgaCA6ICfRh9Cw0YEnLFxuICAgICAgICBoaCA6ICclZCDRh9Cw0YHQsCcsXG4gICAgICAgIGQgOiAn0LTQtdC9JyxcbiAgICAgICAgZGQgOiAnJWQg0LTQvdC4JyxcbiAgICAgICAgTSA6ICfQvNC10YHQtdGGJyxcbiAgICAgICAgTU0gOiAnJWQg0LzQtdGB0LXRhtCwJyxcbiAgICAgICAgeSA6ICfQs9C+0LTQuNC90LAnLFxuICAgICAgICB5eSA6ICclZCDQs9C+0LTQuNC90LgnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNC10LJ80LXQvXzRgtC4fNCy0Lh80YDQuHzQvNC4KS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGxhc3REaWdpdCA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgbGFzdDJEaWdpdHMgPSBudW1iZXIgJSAxMDA7XG4gICAgICAgIGlmIChudW1iZXIgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC10LInO1xuICAgICAgICB9IGVsc2UgaWYgKGxhc3QyRGlnaXRzID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QtdC9JztcbiAgICAgICAgfSBlbHNlIGlmIChsYXN0MkRpZ2l0cyA+IDEwICYmIGxhc3QyRGlnaXRzIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICB9IGVsc2UgaWYgKGxhc3REaWdpdCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LLQuCc7XG4gICAgICAgIH0gZWxzZSBpZiAobGFzdERpZ2l0ID09PSAyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3RgNC4JztcbiAgICAgICAgfSBlbHNlIGlmIChsYXN0RGlnaXQgPT09IDcgfHwgbGFzdERpZ2l0ID09PSA4KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QvNC4JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gYmc7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2JnLmpzXG4vLyBtb2R1bGUgaWQgPSAxNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQmFtYmFyYSBbYm1dXG4vLyEgYXV0aG9yIDogRXN0ZWxsZSBDb21tZW50IDogaHR0cHM6Ly9naXRodWIuY29tL2VzdGVsbGVjb21tZW50XG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cbi8vIExhbmd1YWdlIGNvbnRhY3QgcGVyc29uIDogQWJkb3VmYXRhIEthbmUgOiBodHRwczovL2dpdGh1Yi5jb20vYWJkb3VmYXRhXG5cbnZhciBibSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2JtJywge1xuICAgIG1vbnRocyA6ICdaYW53dXlla2Fsb19GZXd1cnV5ZWthbG9fTWFyaXNpa2Fsb19Bd2lyaWxpa2Fsb19NyZtrYWxvX1p1d8mbbmthbG9fWnVsdXlla2Fsb19VdGlrYWxvX1PJm3RhbmJ1cnVrYWxvX8mUa3V0yZRidXJ1a2Fsb19Ob3dhbmJ1cnVrYWxvX0Rlc2FuYnVydWthbG8nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnWmFuX0Zld19NYXJfQXdpX03Jm19adXdfWnVsX1V0aV9TyZt0X8mUa3VfTm93X0Rlcycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdLYXJpX050yZtuyZtuX1RhcmF0YV9BcmFiYV9BbGFtaXNhX0p1bWFfU2liaXJpJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnS2FyX050yZtfVGFyX0FyYV9BbGFfSnVtX1NpYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdLYV9OdF9UYV9Bcl9BbF9KdV9TaScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdNTU1NIFt0aWxlXSBEIFtzYW5dIFlZWVknLFxuICAgICAgICBMTEwgOiAnTU1NTSBbdGlsZV0gRCBbc2FuXSBZWVlZIFtsyZtyyZtdIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIE1NTU0gW3RpbGVdIEQgW3Nhbl0gWVlZWSBbbMmbcsmbXSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tCaSBsyZtyyZtdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbU2luaSBsyZtyyZtdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbZG9uIGzJm3LJm10gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tLdW51IGzJm3LJm10gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFt0yZttyZtuZW4gbMmbcsmbXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyBryZRuyZQnLFxuICAgICAgICBwYXN0IDogJ2EgYsmbICVzIGLJlCcsXG4gICAgICAgIHMgOiAnc2FuZ2EgZGFtYSBkYW1hJyxcbiAgICAgICAgc3MgOiAnc2Vrb25kaSAlZCcsXG4gICAgICAgIG0gOiAnbWluaXRpIGtlbGVuJyxcbiAgICAgICAgbW0gOiAnbWluaXRpICVkJyxcbiAgICAgICAgaCA6ICdsyZtyyZsga2VsZW4nLFxuICAgICAgICBoaCA6ICdsyZtyyZsgJWQnLFxuICAgICAgICBkIDogJ3RpbGUga2VsZW4nLFxuICAgICAgICBkZCA6ICd0aWxlICVkJyxcbiAgICAgICAgTSA6ICdrYWxvIGtlbGVuJyxcbiAgICAgICAgTU0gOiAna2FsbyAlZCcsXG4gICAgICAgIHkgOiAnc2FuIGtlbGVuJyxcbiAgICAgICAgeXkgOiAnc2FuICVkJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGJtO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ibS5qc1xuLy8gbW9kdWxlIGlkID0gMTZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEJlbmdhbGkgW2JuXVxuLy8hIGF1dGhvciA6IEthdXNoaWsgR2FuZGhpIDogaHR0cHM6Ly9naXRodWIuY29tL2thdXNoaWtnYW5kaGlcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgc3ltYm9sTWFwID0ge1xuICAgICcxJzogJ+CnpycsXG4gICAgJzInOiAn4KeoJyxcbiAgICAnMyc6ICfgp6knLFxuICAgICc0JzogJ+CnqicsXG4gICAgJzUnOiAn4KerJyxcbiAgICAnNic6ICfgp6wnLFxuICAgICc3JzogJ+CnrScsXG4gICAgJzgnOiAn4KeuJyxcbiAgICAnOSc6ICfgp68nLFxuICAgICcwJzogJ+Cnpidcbn07XG52YXIgbnVtYmVyTWFwID0ge1xuICAgICfgp6cnOiAnMScsXG4gICAgJ+CnqCc6ICcyJyxcbiAgICAn4KepJzogJzMnLFxuICAgICfgp6onOiAnNCcsXG4gICAgJ+Cnqyc6ICc1JyxcbiAgICAn4KesJzogJzYnLFxuICAgICfgp60nOiAnNycsXG4gICAgJ+Cnric6ICc4JyxcbiAgICAn4KevJzogJzknLFxuICAgICfgp6YnOiAnMCdcbn07XG5cbnZhciBibiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2JuJywge1xuICAgIG1vbnRocyA6ICfgppzgpr7gpqjgp4Hgp5/gpr7gprDgp4Bf4Kar4KeH4Kas4KeN4Kaw4KeB4Kef4Ka+4Kaw4Ka/X+CmruCmvuCmsOCnjeCmml/gpo/gpqrgp43gprDgpr/gprJf4Kau4KeHX+CmnOCngeCmqF/gppzgp4HgprLgpr7gpodf4KaG4KaX4Ka44KeN4KafX+CmuOCnh+CmquCnjeCmn+Cnh+CmruCnjeCmrOCmsF/gpoXgppXgp43gpp/gp4vgpqzgprBf4Kao4Kat4KeH4Kau4KeN4Kas4KawX+CmoeCmv+CmuOCnh+CmruCnjeCmrOCmsCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgppzgpr7gpqjgp4Ff4Kar4KeH4KasX+CmruCmvuCmsOCnjeCmml/gpo/gpqrgp43gprBf4Kau4KeHX+CmnOCngeCmqF/gppzgp4HgprJf4KaG4KaXX+CmuOCnh+CmquCnjeCmn1/gpoXgppXgp43gpp/gp4tf4Kao4Kat4KeHX+CmoeCmv+CmuOCnhycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfgprDgpqzgpr/gpqzgpr7gprBf4Ka44KeL4Kau4Kas4Ka+4KawX+CmruCmmeCnjeCml+CmsuCmrOCmvuCmsF/gpqzgp4Hgpqfgpqzgpr7gprBf4Kas4KeD4Ka54Ka44KeN4Kaq4Kak4Ka/4Kas4Ka+4KawX+CmtuCngeCmleCnjeCmsOCmrOCmvuCmsF/gprbgpqjgpr/gpqzgpr7gprAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgprDgpqzgpr9f4Ka44KeL4KauX+CmruCmmeCnjeCml+Cmsl/gpqzgp4Hgpqdf4Kas4KeD4Ka54Ka44KeN4Kaq4Kak4Ka/X+CmtuCngeCmleCnjeCmsF/gprbgpqjgpr8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4Kaw4Kas4Ka/X+CmuOCni+Cmrl/gpq7gppngp43gppdf4Kas4KeB4KanX+CmrOCng+CmueCmg1/gprbgp4HgppXgp43gprBf4Ka24Kao4Ka/Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0g4Ka44Kau4KefJyxcbiAgICAgICAgTFRTIDogJ0EgaDptbTpzcyDgprjgpq7gp58nLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCmuOCmruCnnycsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgprjgpq7gp58nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb4KaG4KacXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW+CmhuCml+CmvuCmruCngOCmleCmvuCmsl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkLCBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW+Cml+CmpOCmleCmvuCmsl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb4KaX4KakXSBkZGRkLCBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyDgpqrgprDgp4cnLFxuICAgICAgICBwYXN0IDogJyVzIOCmhuCml+CnhycsXG4gICAgICAgIHMgOiAn4KaV4Kef4KeH4KaVIOCmuOCnh+CmleCnh+CmqOCnjeCmoScsXG4gICAgICAgIHNzIDogJyVkIOCmuOCnh+CmleCnh+CmqOCnjeCmoScsXG4gICAgICAgIG0gOiAn4KaP4KaVIOCmruCmv+CmqOCmv+CmnycsXG4gICAgICAgIG1tIDogJyVkIOCmruCmv+CmqOCmv+CmnycsXG4gICAgICAgIGggOiAn4KaP4KaVIOCmmOCmqOCnjeCmn+CmvicsXG4gICAgICAgIGhoIDogJyVkIOCmmOCmqOCnjeCmn+CmvicsXG4gICAgICAgIGQgOiAn4KaP4KaVIOCmpuCmv+CmqCcsXG4gICAgICAgIGRkIDogJyVkIOCmpuCmv+CmqCcsXG4gICAgICAgIE0gOiAn4KaP4KaVIOCmruCmvuCmuCcsXG4gICAgICAgIE1NIDogJyVkIOCmruCmvuCmuCcsXG4gICAgICAgIHkgOiAn4KaP4KaVIOCmrOCmm+CmsCcsXG4gICAgICAgIHl5IDogJyVkIOCmrOCmm+CmsCdcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+Cnp+CnqOCnqeCnquCnq+CnrOCnreCnruCnr+Cnpl0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+CmsOCmvuCmpHzgprjgppXgpr7gprJ84Kam4KeB4Kaq4KeB4KawfOCmrOCmv+CmleCmvuCmsnzgprDgpr7gpqQvLFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmICgobWVyaWRpZW0gPT09ICfgprDgpr7gpqQnICYmIGhvdXIgPj0gNCkgfHxcbiAgICAgICAgICAgICAgICAobWVyaWRpZW0gPT09ICfgpqbgp4Hgpqrgp4HgprAnICYmIGhvdXIgPCA1KSB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn4Kas4Ka/4KaV4Ka+4KayJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CmsOCmvuCmpCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CmuOCmleCmvuCmsic7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CmpuCngeCmquCngeCmsCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CmrOCmv+CmleCmvuCmsic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CmsOCmvuCmpCc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBibjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvYm4uanNcbi8vIG1vZHVsZSBpZCA9IDE3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBUaWJldGFuIFtib11cbi8vISBhdXRob3IgOiBUaHVwdGVuIE4uIENoYWtyaXNoYXIgOiBodHRwczovL2dpdGh1Yi5jb20vdmFqcmFkb2dcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgc3ltYm9sTWFwID0ge1xuICAgICcxJzogJ+C8oScsXG4gICAgJzInOiAn4LyiJyxcbiAgICAnMyc6ICfgvKMnLFxuICAgICc0JzogJ+C8pCcsXG4gICAgJzUnOiAn4LylJyxcbiAgICAnNic6ICfgvKYnLFxuICAgICc3JzogJ+C8pycsXG4gICAgJzgnOiAn4LyoJyxcbiAgICAnOSc6ICfgvKknLFxuICAgICcwJzogJ+C8oCdcbn07XG52YXIgbnVtYmVyTWFwID0ge1xuICAgICfgvKEnOiAnMScsXG4gICAgJ+C8oic6ICcyJyxcbiAgICAn4LyjJzogJzMnLFxuICAgICfgvKQnOiAnNCcsXG4gICAgJ+C8pSc6ICc1JyxcbiAgICAn4LymJzogJzYnLFxuICAgICfgvKcnOiAnNycsXG4gICAgJ+C8qCc6ICc4JyxcbiAgICAn4LypJzogJzknLFxuICAgICfgvKAnOiAnMCdcbn07XG5cbnZhciBibyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2JvJywge1xuICAgIG1vbnRocyA6ICfgvZ/gvrPgvIvgvZbgvIvgvZHgvYTgvIvgvZTgvbxf4L2f4L6z4LyL4L2W4LyL4L2C4L2J4L2y4L2m4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9guC9puC9tOC9mOC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvZ7gvbLgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2j4L6U4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9keC+suC9tOC9guC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvZHgvbTgvZPgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2i4L6S4L6x4L2R4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9keC9guC9tOC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvYXgvbTgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2F4L204LyL4L2C4L2F4L2y4L2C4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9luC9heC9tOC8i+C9guC9ieC9suC9puC8i+C9lCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgvZ/gvrPgvIvgvZbgvIvgvZHgvYTgvIvgvZTgvbxf4L2f4L6z4LyL4L2W4LyL4L2C4L2J4L2y4L2m4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9guC9puC9tOC9mOC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvZ7gvbLgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2j4L6U4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9keC+suC9tOC9guC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvZHgvbTgvZPgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2i4L6S4L6x4L2R4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9keC9guC9tOC8i+C9lF/gvZ/gvrPgvIvgvZbgvIvgvZbgvYXgvbTgvIvgvZRf4L2f4L6z4LyL4L2W4LyL4L2W4L2F4L204LyL4L2C4L2F4L2y4L2C4LyL4L2UX+C9n+C+s+C8i+C9luC8i+C9luC9heC9tOC8i+C9guC9ieC9suC9puC8i+C9lCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfgvYLgvZ/gvaDgvIvgvYngvbLgvIvgvZjgvItf4L2C4L2f4L2g4LyL4L2f4L6z4LyL4L2W4LyLX+C9guC9n+C9oOC8i+C9mOC9suC9guC8i+C9keC9mOC9ouC8i1/gvYLgvZ/gvaDgvIvgvaPgvrfgvYLgvIvgvZTgvItf4L2C4L2f4L2g4LyL4L2V4L204L2i4LyL4L2W4L20X+C9guC9n+C9oOC8i+C9lOC8i+C9puC9hOC9puC8i1/gvYLgvZ/gvaDgvIvgvabgvqTgvbrgvZPgvIvgvZTgvIsnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgvYngvbLgvIvgvZjgvItf4L2f4L6z4LyL4L2W4LyLX+C9mOC9suC9guC8i+C9keC9mOC9ouC8i1/gvaPgvrfgvYLgvIvgvZTgvItf4L2V4L204L2i4LyL4L2W4L20X+C9lOC8i+C9puC9hOC9puC8i1/gvabgvqTgvbrgvZPgvIvgvZTgvIsnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4L2J4L2y4LyL4L2Y4LyLX+C9n+C+s+C8i+C9luC8i1/gvZjgvbLgvYLgvIvgvZHgvZjgvaLgvItf4L2j4L634L2C4LyL4L2U4LyLX+C9leC9tOC9ouC8i+C9luC9tF/gvZTgvIvgvabgvYTgvabgvItf4L2m4L6k4L264L2T4LyL4L2U4LyLJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0nLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEEgaDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgvZHgvbLgvIvgvaLgvbLgvYRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4L2m4L2E4LyL4L2J4L2y4L2TXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1vgvZbgvZHgvbTgvZPgvIvgvZXgvrLgvYLgvIvgvaLgvpfgvbrgvabgvIvgvZhdLCBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW+C9geC8i+C9puC9hF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb4L2W4L2R4L204L2T4LyL4L2V4L6y4L2C4LyL4L2Y4L2Q4L2g4LyL4L2YXSBkZGRkLCBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyDgvaPgvIsnLFxuICAgICAgICBwYXN0IDogJyVzIOC9puC+lOC9k+C8i+C9oycsXG4gICAgICAgIHMgOiAn4L2j4L2Y4LyL4L2m4L2EJyxcbiAgICAgICAgc3MgOiAnJWQg4L2m4L6Q4L2i4LyL4L2G4LyNJyxcbiAgICAgICAgbSA6ICfgvabgvpDgvaLgvIvgvZjgvIvgvYLgvYXgvbLgvYInLFxuICAgICAgICBtbSA6ICclZCDgvabgvpDgvaLgvIvgvZgnLFxuICAgICAgICBoIDogJ+C9huC9tOC8i+C9muC9vOC9keC8i+C9guC9heC9suC9gicsXG4gICAgICAgIGhoIDogJyVkIOC9huC9tOC8i+C9muC9vOC9kScsXG4gICAgICAgIGQgOiAn4L2J4L2y4L2T4LyL4L2C4L2F4L2y4L2CJyxcbiAgICAgICAgZGQgOiAnJWQg4L2J4L2y4L2T4LyLJyxcbiAgICAgICAgTSA6ICfgvZ/gvrPgvIvgvZbgvIvgvYLgvYXgvbLgvYInLFxuICAgICAgICBNTSA6ICclZCDgvZ/gvrPgvIvgvZYnLFxuICAgICAgICB5IDogJ+C9o+C9vOC8i+C9guC9heC9suC9gicsXG4gICAgICAgIHl5IDogJyVkIOC9o+C9vCdcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+C8oeC8ouC8o+C8pOC8peC8puC8p+C8qOC8qeC8oF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+C9mOC9muC9k+C8i+C9mOC9vHzgvZ7gvbzgvYLgvabgvIvgvYDgvaZ84L2J4L2y4L2T4LyL4L2C4L204L2EfOC9keC9guC9vOC9hOC8i+C9keC9gnzgvZjgvZrgvZPgvIvgvZjgvbwvLFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmICgobWVyaWRpZW0gPT09ICfgvZjgvZrgvZPgvIvgvZjgvbwnICYmIGhvdXIgPj0gNCkgfHxcbiAgICAgICAgICAgICAgICAobWVyaWRpZW0gPT09ICfgvYngvbLgvZPgvIvgvYLgvbTgvYQnICYmIGhvdXIgPCA1KSB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn4L2R4L2C4L284L2E4LyL4L2R4L2CJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9mOC9muC9k+C8i+C9mOC9vCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9nuC9vOC9guC9puC8i+C9gOC9pic7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9ieC9suC9k+C8i+C9guC9tOC9hCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9keC9guC9vOC9hOC8i+C9keC9gic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C9mOC9muC9k+C8i+C9mOC9vCc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBibztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvYm8uanNcbi8vIG1vZHVsZSBpZCA9IDE4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBCcmV0b24gW2JyXVxuLy8hIGF1dGhvciA6IEplYW4tQmFwdGlzdGUgTGUgRHVpZ291IDogaHR0cHM6Ly9naXRodWIuY29tL2pibGVkdWlnb3VcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG5mdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoTXV0YXRpb24obnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAnbW0nOiAnbXVudXRlbm4nLFxuICAgICAgICAnTU0nOiAnbWl6JyxcbiAgICAgICAgJ2RkJzogJ2RldmV6aCdcbiAgICB9O1xuICAgIHJldHVybiBudW1iZXIgKyAnICcgKyBtdXRhdGlvbihmb3JtYXRba2V5XSwgbnVtYmVyKTtcbn1cbmZ1bmN0aW9uIHNwZWNpYWxNdXRhdGlvbkZvclllYXJzKG51bWJlcikge1xuICAgIHN3aXRjaCAobGFzdE51bWJlcihudW1iZXIpKSB7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICBjYXNlIDQ6XG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgY2FzZSA5OlxuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgYmxvYXonO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgdmxvYXonO1xuICAgIH1cbn1cbmZ1bmN0aW9uIGxhc3ROdW1iZXIobnVtYmVyKSB7XG4gICAgaWYgKG51bWJlciA+IDkpIHtcbiAgICAgICAgcmV0dXJuIGxhc3ROdW1iZXIobnVtYmVyICUgMTApO1xuICAgIH1cbiAgICByZXR1cm4gbnVtYmVyO1xufVxuZnVuY3Rpb24gbXV0YXRpb24odGV4dCwgbnVtYmVyKSB7XG4gICAgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICByZXR1cm4gc29mdE11dGF0aW9uKHRleHQpO1xuICAgIH1cbiAgICByZXR1cm4gdGV4dDtcbn1cbmZ1bmN0aW9uIHNvZnRNdXRhdGlvbih0ZXh0KSB7XG4gICAgdmFyIG11dGF0aW9uVGFibGUgPSB7XG4gICAgICAgICdtJzogJ3YnLFxuICAgICAgICAnYic6ICd2JyxcbiAgICAgICAgJ2QnOiAneidcbiAgICB9O1xuICAgIGlmIChtdXRhdGlvblRhYmxlW3RleHQuY2hhckF0KDApXSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiB0ZXh0O1xuICAgIH1cbiAgICByZXR1cm4gbXV0YXRpb25UYWJsZVt0ZXh0LmNoYXJBdCgwKV0gKyB0ZXh0LnN1YnN0cmluZygxKTtcbn1cblxudmFyIGJyID0gbW9tZW50LmRlZmluZUxvY2FsZSgnYnInLCB7XG4gICAgbW9udGhzIDogJ0dlbnZlcl9DXFwnaHdldnJlcl9NZXVyemhfRWJyZWxfTWFlX01lemhldmVuX0dvdWVyZV9Fb3N0X0d3ZW5nb2xvX0hlcmVfRHVfS2VyenUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnR2VuX0NcXCdod2VfTWV1X0Vicl9NYWVfRXZlX0dvdV9Fb3NfR3dlX0hlcl9EdV9LZXInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnU3VsX0x1bl9NZXVyemhfTWVyY1xcJ2hlcl9ZYW91X0d3ZW5lcl9TYWRvcm4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdTdWxfTHVuX01ldV9NZXJfWWFvX0d3ZV9TYWQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU3VfTHVfTWVfTWVyX1lhX0d3X1NhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ2hbZV1tbSBBJyxcbiAgICAgICAgTFRTIDogJ2hbZV1tbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBbYSB2aXpdIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIFthIHZpel0gTU1NTSBZWVlZIGhbZV1tbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIFthIHZpel0gTU1NTSBZWVlZIGhbZV1tbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0hpeml2IGRhXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW1dhcmNcXCdob2F6aCBkYV0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtkYV0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tEZWNcXCdoIGRhXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW3Bhc2V0IGRhXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdhLWJlbm4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIFxcJ3pvJyxcbiAgICAgICAgcyA6ICd1biBuZWJldWQgc2Vnb25kZW5ub8O5JyxcbiAgICAgICAgc3MgOiAnJWQgZWlsZW5uJyxcbiAgICAgICAgbSA6ICd1ciB2dW51dGVubicsXG4gICAgICAgIG1tIDogcmVsYXRpdmVUaW1lV2l0aE11dGF0aW9uLFxuICAgICAgICBoIDogJ3VuIGV1cicsXG4gICAgICAgIGhoIDogJyVkIGV1cicsXG4gICAgICAgIGQgOiAndW4gZGV2ZXpoJyxcbiAgICAgICAgZGQgOiByZWxhdGl2ZVRpbWVXaXRoTXV0YXRpb24sXG4gICAgICAgIE0gOiAndXIgbWl6JyxcbiAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoTXV0YXRpb24sXG4gICAgICAgIHkgOiAndXIgYmxvYXonLFxuICAgICAgICB5eSA6IHNwZWNpYWxNdXRhdGlvbkZvclllYXJzXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oYcOxfHZldCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSAobnVtYmVyID09PSAxKSA/ICdhw7EnIDogJ3ZldCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gYnI7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2JyLmpzXG4vLyBtb2R1bGUgaWQgPSAxOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQm9zbmlhbiBbYnNdXG4vLyEgYXV0aG9yIDogTmVkaW0gQ2hvbGljaCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9mcm9udHlhcmRcbi8vISBiYXNlZCBvbiAoaHIpIHRyYW5zbGF0aW9uIGJ5IEJvamFuIE1hcmtvdmnEh1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbmZ1bmN0aW9uIHRyYW5zbGF0ZShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2VrdW5kYSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmRlJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmRpJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnamVkbmEgbWludXRhJyA6ICdqZWRuZSBtaW51dGUnO1xuICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtaW51dGEnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWludXRlJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtaW51dGEnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdqZWRhbiBzYXQnIDogJ2plZG5vZyBzYXRhJztcbiAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2F0JztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3NhdGEnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3NhdGknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZGFuJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdkYW5hJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21qZXNlYyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWNhJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtamVzZWNpJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ3l5JzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2dvZGluYSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdnb2RpbmUnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2dvZGluYSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbn1cblxudmFyIGJzID0gbW9tZW50LmRlZmluZUxvY2FsZSgnYnMnLCB7XG4gICAgbW9udGhzIDogJ2phbnVhcl9mZWJydWFyX21hcnRfYXByaWxfbWFqX2p1bmlfanVsaV9hdWd1c3Rfc2VwdGVtYmFyX29rdG9iYXJfbm92ZW1iYXJfZGVjZW1iYXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFuLl9mZWIuX21hci5fYXByLl9tYWouX2p1bi5fanVsLl9hdWcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICduZWRqZWxqYV9wb25lZGplbGpha191dG9yYWtfc3JpamVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnbmVkLl9wb24uX3V0by5fc3JpLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnbmVfcG9fdXRfc3JfxI1lX3BlX3N1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSAgOiAnW2RhbmFzIHVdIExUJyxcbiAgICAgICAgbmV4dERheSAgOiAnW3N1dHJhIHVdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtuZWRqZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzcmlqZWR1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3N1Ym90dV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSAgOiAnW2p1xI1lciB1XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsdV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsZV0gW3N1Ym90ZV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbGldIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3phICVzJyxcbiAgICAgICAgcGFzdCAgIDogJ3ByaWplICVzJyxcbiAgICAgICAgcyAgICAgIDogJ3BhciBzZWt1bmRpJyxcbiAgICAgICAgc3MgICAgIDogdHJhbnNsYXRlLFxuICAgICAgICBtICAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIG1tICAgICA6IHRyYW5zbGF0ZSxcbiAgICAgICAgaCAgICAgIDogdHJhbnNsYXRlLFxuICAgICAgICBoaCAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIGQgICAgICA6ICdkYW4nLFxuICAgICAgICBkZCAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIE0gICAgICA6ICdtamVzZWMnLFxuICAgICAgICBNTSAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIHkgICAgICA6ICdnb2RpbnUnLFxuICAgICAgICB5eSAgICAgOiB0cmFuc2xhdGVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBicztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvYnMuanNcbi8vIG1vZHVsZSBpZCA9IDIwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBDYXRhbGFuIFtjYV1cbi8vISBhdXRob3IgOiBKdWFuIEcuIEh1cnRhZG8gOiBodHRwczovL2dpdGh1Yi5jb20vanVhbmdodXJ0YWRvXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGNhID0gbW9tZW50LmRlZmluZUxvY2FsZSgnY2EnLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICBzdGFuZGFsb25lOiAnZ2VuZXJfZmVicmVyX21hcsOnX2FicmlsX21haWdfanVueV9qdWxpb2xfYWdvc3Rfc2V0ZW1icmVfb2N0dWJyZV9ub3ZlbWJyZV9kZXNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgZm9ybWF0OiAnZGUgZ2VuZXJfZGUgZmVicmVyX2RlIG1hcsOnX2RcXCdhYnJpbF9kZSBtYWlnX2RlIGp1bnlfZGUganVsaW9sX2RcXCdhZ29zdF9kZSBzZXRlbWJyZV9kXFwnb2N0dWJyZV9kZSBub3ZlbWJyZV9kZSBkZXNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICAgICAgaXNGb3JtYXQ6IC9EW29EXT8oXFxzKStNTU1NL1xuICAgIH0sXG4gICAgbW9udGhzU2hvcnQgOiAnZ2VuLl9mZWJyLl9tYXLDp19hYnIuX21haWdfanVueV9qdWwuX2FnLl9zZXQuX29jdC5fbm92Ll9kZXMuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2RpdW1lbmdlX2RpbGx1bnNfZGltYXJ0c19kaW1lY3Jlc19kaWpvdXNfZGl2ZW5kcmVzX2Rpc3NhYnRlJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnZGcuX2RsLl9kdC5fZGMuX2RqLl9kdi5fZHMuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2RnX2RsX2R0X2RjX2RqX2R2X2RzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBbZGVdIFlZWVknLFxuICAgICAgICBsbCA6ICdEIE1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBbZGVdIFlZWVkgW2EgbGVzXSBIOm1tJyxcbiAgICAgICAgbGxsIDogJ0QgTU1NIFlZWVksIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFtkZV0gWVlZWSBbYSBsZXNdIEg6bW0nLFxuICAgICAgICBsbGxsIDogJ2RkZCBEIE1NTSBZWVlZLCBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1thdnVpIGEgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdsZXMnIDogJ2xhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHREYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1tkZW3DoCBhICcgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAnbGVzJyA6ICdsYScpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBuZXh0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnZGRkZCBbYSAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ2xlcycgOiAnbGEnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2FoaXIgYSAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ2xlcycgOiAnbGEnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1tlbF0gZGRkZCBbcGFzc2F0IGEgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdsZXMnIDogJ2xhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkXFwnYXF1w60gJXMnLFxuICAgICAgICBwYXN0IDogJ2ZhICVzJyxcbiAgICAgICAgcyA6ICd1bnMgc2Vnb25zJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vnb25zJyxcbiAgICAgICAgbSA6ICd1biBtaW51dCcsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0cycsXG4gICAgICAgIGggOiAndW5hIGhvcmEnLFxuICAgICAgICBoaCA6ICclZCBob3JlcycsXG4gICAgICAgIGQgOiAndW4gZGlhJyxcbiAgICAgICAgZGQgOiAnJWQgZGllcycsXG4gICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgTU0gOiAnJWQgbWVzb3MnLFxuICAgICAgICB5IDogJ3VuIGFueScsXG4gICAgICAgIHl5IDogJyVkIGFueXMnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0ocnxufHR8w6h8YSkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgdmFyIG91dHB1dCA9IChudW1iZXIgPT09IDEpID8gJ3InIDpcbiAgICAgICAgICAgIChudW1iZXIgPT09IDIpID8gJ24nIDpcbiAgICAgICAgICAgIChudW1iZXIgPT09IDMpID8gJ3InIDpcbiAgICAgICAgICAgIChudW1iZXIgPT09IDQpID8gJ3QnIDogJ8OoJztcbiAgICAgICAgaWYgKHBlcmlvZCA9PT0gJ3cnIHx8IHBlcmlvZCA9PT0gJ1cnKSB7XG4gICAgICAgICAgICBvdXRwdXQgPSAnYSc7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBjYTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvY2EuanNcbi8vIG1vZHVsZSBpZCA9IDIxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBDemVjaCBbY3NdXG4vLyEgYXV0aG9yIDogcGV0cmJlbGEgOiBodHRwczovL2dpdGh1Yi5jb20vcGV0cmJlbGFcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbW9udGhzID0gJ2xlZGVuX8O6bm9yX2LFmWV6ZW5fZHViZW5fa3bEm3Rlbl/EjWVydmVuX8SNZXJ2ZW5lY19zcnBlbl96w6HFmcOtX8WZw61qZW5fbGlzdG9wYWRfcHJvc2luZWMnLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnQgPSAnbGVkX8O6bm9fYsWZZV9kdWJfa3bEm1/EjXZuX8SNdmNfc3JwX3rDocWZX8WZw61qX2xpc19wcm8nLnNwbGl0KCdfJyk7XG5mdW5jdGlvbiBwbHVyYWwobikge1xuICAgIHJldHVybiAobiA+IDEpICYmIChuIDwgNSkgJiYgKH5+KG4gLyAxMCkgIT09IDEpO1xufVxuZnVuY3Rpb24gdHJhbnNsYXRlKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSAncyc6ICAvLyBhIGZldyBzZWNvbmRzIC8gaW4gYSBmZXcgc2Vjb25kcyAvIGEgZmV3IHNlY29uZHMgYWdvXG4gICAgICAgICAgICByZXR1cm4gKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpID8gJ3DDoXIgc2VrdW5kJyA6ICdww6FyIHNla3VuZGFtaSc7XG4gICAgICAgIGNhc2UgJ3NzJzogLy8gOSBzZWNvbmRzIC8gaW4gOSBzZWNvbmRzIC8gOSBzZWNvbmRzIGFnb1xuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbChudW1iZXIpID8gJ3Nla3VuZHknIDogJ3Nla3VuZCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ3Nla3VuZGFtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbSc6ICAvLyBhIG1pbnV0ZSAvIGluIGEgbWludXRlIC8gYSBtaW51dGUgYWdvXG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdtaW51dGEnIDogKGlzRnV0dXJlID8gJ21pbnV0dScgOiAnbWludXRvdScpO1xuICAgICAgICBjYXNlICdtbSc6IC8vIDkgbWludXRlcyAvIGluIDkgbWludXRlcyAvIDkgbWludXRlcyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwobnVtYmVyKSA/ICdtaW51dHknIDogJ21pbnV0Jyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbWludXRhbWknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2gnOiAgLy8gYW4gaG91ciAvIGluIGFuIGhvdXIgLyBhbiBob3VyIGFnb1xuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnaG9kaW5hJyA6IChpc0Z1dHVyZSA/ICdob2RpbnUnIDogJ2hvZGlub3UnKTtcbiAgICAgICAgY2FzZSAnaGgnOiAvLyA5IGhvdXJzIC8gaW4gOSBob3VycyAvIDkgaG91cnMgYWdvXG4gICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsKG51bWJlcikgPyAnaG9kaW55JyA6ICdob2RpbicpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2hvZGluYW1pJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdkJzogIC8vIGEgZGF5IC8gaW4gYSBkYXkgLyBhIGRheSBhZ29cbiAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAnZGVuJyA6ICdkbmVtJztcbiAgICAgICAgY2FzZSAnZGQnOiAvLyA5IGRheXMgLyBpbiA5IGRheXMgLyA5IGRheXMgYWdvXG4gICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsKG51bWJlcikgPyAnZG55JyA6ICdkbsOtJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnZG55JztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdNJzogIC8vIGEgbW9udGggLyBpbiBhIG1vbnRoIC8gYSBtb250aCBhZ29cbiAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAnbcSbc8OtYycgOiAnbcSbc8OtY2VtJztcbiAgICAgICAgY2FzZSAnTU0nOiAvLyA5IG1vbnRocyAvIGluIDkgbW9udGhzIC8gOSBtb250aHMgYWdvXG4gICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsKG51bWJlcikgPyAnbcSbc8OtY2UnIDogJ23Em3PDrWPFrycpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ23Em3PDrWNpJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICd5JzogIC8vIGEgeWVhciAvIGluIGEgeWVhciAvIGEgeWVhciBhZ29cbiAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAncm9rJyA6ICdyb2tlbSc7XG4gICAgICAgIGNhc2UgJ3l5JzogLy8gOSB5ZWFycyAvIGluIDkgeWVhcnMgLyA5IHllYXJzIGFnb1xuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbChudW1iZXIpID8gJ3Jva3knIDogJ2xldCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2xldHknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgfVxufVxuXG52YXIgY3MgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdjcycsIHtcbiAgICBtb250aHMgOiBtb250aHMsXG4gICAgbW9udGhzU2hvcnQgOiBtb250aHNTaG9ydCxcbiAgICBtb250aHNQYXJzZSA6IChmdW5jdGlvbiAobW9udGhzLCBtb250aHNTaG9ydCkge1xuICAgICAgICB2YXIgaSwgX21vbnRoc1BhcnNlID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgICAgICAvLyB1c2UgY3VzdG9tIHBhcnNlciB0byBzb2x2ZSBwcm9ibGVtIHdpdGggSnVseSAoxI1lcnZlbmVjKVxuICAgICAgICAgICAgX21vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cCgnXicgKyBtb250aHNbaV0gKyAnJHxeJyArIG1vbnRoc1Nob3J0W2ldICsgJyQnLCAnaScpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfbW9udGhzUGFyc2U7XG4gICAgfShtb250aHMsIG1vbnRoc1Nob3J0KSksXG4gICAgc2hvcnRNb250aHNQYXJzZSA6IChmdW5jdGlvbiAobW9udGhzU2hvcnQpIHtcbiAgICAgICAgdmFyIGksIF9zaG9ydE1vbnRoc1BhcnNlID0gW107XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgICAgICBfc2hvcnRNb250aHNQYXJzZVtpXSA9IG5ldyBSZWdFeHAoJ14nICsgbW9udGhzU2hvcnRbaV0gKyAnJCcsICdpJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIF9zaG9ydE1vbnRoc1BhcnNlO1xuICAgIH0obW9udGhzU2hvcnQpKSxcbiAgICBsb25nTW9udGhzUGFyc2UgOiAoZnVuY3Rpb24gKG1vbnRocykge1xuICAgICAgICB2YXIgaSwgX2xvbmdNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICAgICAgX2xvbmdNb250aHNQYXJzZVtpXSA9IG5ldyBSZWdFeHAoJ14nICsgbW9udGhzW2ldICsgJyQnLCAnaScpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBfbG9uZ01vbnRoc1BhcnNlO1xuICAgIH0obW9udGhzKSksXG4gICAgd2Vla2RheXMgOiAnbmVkxJtsZV9wb25kxJtsw61fw7p0ZXLDvV9zdMWZZWRhX8SNdHZydGVrX3DDoXRla19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICduZV9wb1/DunRfc3RfxI10X3DDoV9zbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICduZV9wb1/DunRfc3RfxI10X3DDoV9zbycuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBsIDogJ0QuIE0uIFlZWVknXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tkbmVzIHZdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1t6w610cmEgdl0gTFQnLFxuICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t2IG5lZMSbbGkgdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIGRkZGQgW3ZdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZlIHN0xZllZHUgdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdmUgxI10dnJ0ZWsgdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBww6F0ZWsgdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBzb2JvdHUgdl0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5OiAnW3bEjWVyYSB2XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsb3UgbmVkxJtsaSB2XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDqV0gZGRkZCBbdl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWxvdSBzdMWZZWR1IHZdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bMO9XSBkZGRkIFt2XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1ttaW51bG91IHNvYm90dSB2XSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3phICVzJyxcbiAgICAgICAgcGFzdCA6ICdwxZllZCAlcycsXG4gICAgICAgIHMgOiB0cmFuc2xhdGUsXG4gICAgICAgIHNzIDogdHJhbnNsYXRlLFxuICAgICAgICBtIDogdHJhbnNsYXRlLFxuICAgICAgICBtbSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgaCA6IHRyYW5zbGF0ZSxcbiAgICAgICAgaGggOiB0cmFuc2xhdGUsXG4gICAgICAgIGQgOiB0cmFuc2xhdGUsXG4gICAgICAgIGRkIDogdHJhbnNsYXRlLFxuICAgICAgICBNIDogdHJhbnNsYXRlLFxuICAgICAgICBNTSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgeSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgeXkgOiB0cmFuc2xhdGVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gY3M7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2NzLmpzXG4vLyBtb2R1bGUgaWQgPSAyMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQ2h1dmFzaCBbY3ZdXG4vLyEgYXV0aG9yIDogQW5hdG9seSBNaXJvbm92IDogaHR0cHM6Ly9naXRodWIuY29tL21pcm9udG9saVxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBjdiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2N2Jywge1xuICAgIG1vbnRocyA6ICfQutOR0YDQu9Cw0Ydf0L3QsNGA05HRgV/Qv9GD0Yhf0LDQutCwX9C80LDQuV/Sq9OX0YDRgtC80LVf0YPRgtORX9Kr0YPRgNC70LBf0LDQstOR0L1f0Y7Qv9CwX9GH07PQul/RgNCw0YjRgtCw0LInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn0LrTkdGAX9C90LDRgF/Qv9GD0Yhf0LDQutCwX9C80LDQuV/Sq9OX0YBf0YPRgtORX9Kr0YPRgF/QsNCy0L1f0Y7Qv9CwX9GH07PQul/RgNCw0YgnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn0LLRi9GA0YHQsNGA0L3QuNC60YPQvV/RgtGD0L3RgtC40LrRg9C9X9GL0YLQu9Cw0YDQuNC60YPQvV/RjtC90LrRg9C9X9C605fSq9C90LXRgNC90LjQutGD0L1f0Y3RgNC90LXQutGD0L1f0YjTkdC80LDRgtC60YPQvScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9Cy0YvRgF/RgtGD0L1f0YvRgtC7X9GO0L1f0LrTl9KrX9GN0YDQvV/RiNOR0LwnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn0LLRgF/RgtC9X9GL0YJf0Y7QvV/QutKrX9GN0YBf0YjQvCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELU1NLVlZWVknLFxuICAgICAgICBMTCA6ICdZWVlZIFvSq9GD0LvRhdC4XSBNTU1NIFvRg9C505HRhdOX0L1dIERbLdC805fRiNOXXScsXG4gICAgICAgIExMTCA6ICdZWVlZIFvSq9GD0LvRhdC4XSBNTU1NIFvRg9C505HRhdOX0L1dIERbLdC805fRiNOXXSwgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIFlZWVkgW9Kr0YPQu9GF0LhdIE1NTU0gW9GD0LnTkdGF05fQvV0gRFst0LzTl9GI05ddLCBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW9Cf0LDRj9C9XSBMVCBb0YHQtdGF0LXRgtGA0LVdJyxcbiAgICAgICAgbmV4dERheTogJ1vQq9GA0LDQvV0gTFQgW9GB0LXRhdC10YLRgNC1XScsXG4gICAgICAgIGxhc3REYXk6ICdb05bQvdC10YBdIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICBuZXh0V2VlazogJ1vSqtC40YLQtdGBXSBkZGRkIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICBsYXN0V2VlazogJ1vQmNGA0YLQvdOXXSBkZGRkIExUIFvRgdC10YXQtdGC0YDQtV0nLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6IGZ1bmN0aW9uIChvdXRwdXQpIHtcbiAgICAgICAgICAgIHZhciBhZmZpeCA9IC/RgdC10YXQtdGCJC9pLmV4ZWMob3V0cHV0KSA/ICfRgNC10L0nIDogL9Kr0YPQuyQvaS5leGVjKG91dHB1dCkgPyAn0YLQsNC9JyA6ICfRgNCw0L0nO1xuICAgICAgICAgICAgcmV0dXJuIG91dHB1dCArIGFmZml4O1xuICAgICAgICB9LFxuICAgICAgICBwYXN0IDogJyVzINC60LDRj9C70LvQsCcsXG4gICAgICAgIHMgOiAn0L/Tl9GALdC40Log0qvQtdC60LrRg9C90YInLFxuICAgICAgICBzcyA6ICclZCDSq9C10LrQutGD0L3RgicsXG4gICAgICAgIG0gOiAn0L/Tl9GAINC80LjQvdGD0YInLFxuICAgICAgICBtbSA6ICclZCDQvNC40L3Rg9GCJyxcbiAgICAgICAgaCA6ICfQv9OX0YAg0YHQtdGF0LXRgicsXG4gICAgICAgIGhoIDogJyVkINGB0LXRhdC10YInLFxuICAgICAgICBkIDogJ9C/05fRgCDQutGD0L0nLFxuICAgICAgICBkZCA6ICclZCDQutGD0L0nLFxuICAgICAgICBNIDogJ9C/05fRgCDRg9C505HRhScsXG4gICAgICAgIE1NIDogJyVkINGD0LnTkdGFJyxcbiAgICAgICAgeSA6ICfQv9OX0YAg0qvRg9C7JyxcbiAgICAgICAgeXkgOiAnJWQg0qvRg9C7J1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LdC805fRiC8sXG4gICAgb3JkaW5hbCA6ICclZC3QvNOX0YgnLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBjdjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvY3YuanNcbi8vIG1vZHVsZSBpZCA9IDIzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBXZWxzaCBbY3ldXG4vLyEgYXV0aG9yIDogUm9iZXJ0IEFsbGVuIDogaHR0cHM6Ly9naXRodWIuY29tL3JvYmdhbGxlblxuLy8hIGF1dGhvciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9yeWFuZ3JlYXZlc1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBjeSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2N5Jywge1xuICAgIG1vbnRoczogJ0lvbmF3cl9DaHdlZnJvcl9NYXdydGhfRWJyaWxsX01haV9NZWhlZmluX0dvcmZmZW5uYWZfQXdzdF9NZWRpX0h5ZHJlZl9UYWNod2VkZF9SaGFnZnlyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAnSW9uX0Nod2VfTWF3X0Vicl9NYWlfTWVoX0dvcl9Bd3NfTWVkX0h5ZF9UYWNoX1JoYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXM6ICdEeWRkIFN1bF9EeWRkIExsdW5fRHlkZCBNYXdydGhfRHlkZCBNZXJjaGVyX0R5ZGQgSWF1X0R5ZGQgR3dlbmVyX0R5ZGQgU2Fkd3JuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQ6ICdTdWxfTGx1bl9NYXdfTWVyX0lhdV9Hd2VfU2FkJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluOiAnU3VfTGxfTWFfTWVfSWFfR3dfU2EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICAvLyB0aW1lIGZvcm1hdHMgYXJlIHRoZSBzYW1lIGFzIGVuLWdiXG4gICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1tIZWRkaXcgYW1dIExUJyxcbiAgICAgICAgbmV4dERheTogJ1tZZm9yeSBhbV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2FtXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbRGRvZSBhbV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ2RkZGQgW2Rpd2V0aGFmIGFtXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICBmdXR1cmU6ICdtZXduICVzJyxcbiAgICAgICAgcGFzdDogJyVzIHluIMO0bCcsXG4gICAgICAgIHM6ICd5Y2h5ZGlnIGVpbGlhZGF1JyxcbiAgICAgICAgc3M6ICclZCBlaWxpYWQnLFxuICAgICAgICBtOiAnbXVudWQnLFxuICAgICAgICBtbTogJyVkIG11bnVkJyxcbiAgICAgICAgaDogJ2F3cicsXG4gICAgICAgIGhoOiAnJWQgYXdyJyxcbiAgICAgICAgZDogJ2Rpd3Jub2QnLFxuICAgICAgICBkZDogJyVkIGRpd3Jub2QnLFxuICAgICAgICBNOiAnbWlzJyxcbiAgICAgICAgTU06ICclZCBtaXMnLFxuICAgICAgICB5OiAnYmx3eWRkeW4nLFxuICAgICAgICB5eTogJyVkIGZseW5lZGQnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oZmVkfGFpbnxhZnxpbHx5ZGR8ZWR8ZWcpLyxcbiAgICAvLyB0cmFkaXRpb25hbCBvcmRpbmFsIG51bWJlcnMgYWJvdmUgMzEgYXJlIG5vdCBjb21tb25seSB1c2VkIGluIGNvbGxvcXVpYWwgV2Vsc2hcbiAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBiID0gbnVtYmVyLFxuICAgICAgICAgICAgb3V0cHV0ID0gJycsXG4gICAgICAgICAgICBsb29rdXAgPSBbXG4gICAgICAgICAgICAgICAgJycsICdhZicsICdpbCcsICd5ZGQnLCAneWRkJywgJ2VkJywgJ2VkJywgJ2VkJywgJ2ZlZCcsICdmZWQnLCAnZmVkJywgLy8gMWFmIHRvIDEwZmVkXG4gICAgICAgICAgICAgICAgJ2VnJywgJ2ZlZCcsICdlZycsICdlZycsICdmZWQnLCAnZWcnLCAnZWcnLCAnZmVkJywgJ2VnJywgJ2ZlZCcgLy8gMTFlZyB0byAyMGZlZFxuICAgICAgICAgICAgXTtcbiAgICAgICAgaWYgKGIgPiAyMCkge1xuICAgICAgICAgICAgaWYgKGIgPT09IDQwIHx8IGIgPT09IDUwIHx8IGIgPT09IDYwIHx8IGIgPT09IDgwIHx8IGIgPT09IDEwMCkge1xuICAgICAgICAgICAgICAgIG91dHB1dCA9ICdmZWQnOyAvLyBub3QgMzBhaW4sIDcwYWluIG9yIDkwYWluXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG91dHB1dCA9ICdhaW4nO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKGIgPiAwKSB7XG4gICAgICAgICAgICBvdXRwdXQgPSBsb29rdXBbYl07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBjeTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvY3kuanNcbi8vIG1vZHVsZSBpZCA9IDI0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBEYW5pc2ggW2RhXVxuLy8hIGF1dGhvciA6IFVscmlrIE5pZWxzZW4gOiBodHRwczovL2dpdGh1Yi5jb20vbXJiYXNlXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGRhID0gbW9tZW50LmRlZmluZUxvY2FsZSgnZGEnLCB7XG4gICAgbW9udGhzIDogJ2phbnVhcl9mZWJydWFyX21hcnRzX2FwcmlsX21hal9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYWpfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3PDuG5kYWdfbWFuZGFnX3RpcnNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2zDuHJkYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdzw7huX21hbl90aXJfb25zX3Rvcl9mcmVfbMO4cicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdzw7hfbWFfdGlfb25fdG9fZnJfbMO4Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgW2QuXSBELiBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbaSBkYWcga2wuXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW2kgbW9yZ2VuIGtsLl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdww6UgZGRkZCBba2wuXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW2kgZ8OlciBrbC5dIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW2ldIGRkZGRbcyBrbC5dIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ29tICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBzaWRlbicsXG4gICAgICAgIHMgOiAnZsOlIHNla3VuZGVyJyxcbiAgICAgICAgc3MgOiAnJWQgc2VrdW5kZXInLFxuICAgICAgICBtIDogJ2V0IG1pbnV0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXR0ZXInLFxuICAgICAgICBoIDogJ2VuIHRpbWUnLFxuICAgICAgICBoaCA6ICclZCB0aW1lcicsXG4gICAgICAgIGQgOiAnZW4gZGFnJyxcbiAgICAgICAgZGQgOiAnJWQgZGFnZScsXG4gICAgICAgIE0gOiAnZW4gbcOlbmVkJyxcbiAgICAgICAgTU0gOiAnJWQgbcOlbmVkZXInLFxuICAgICAgICB5IDogJ2V0IMOlcicsXG4gICAgICAgIHl5IDogJyVkIMOlcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBkYTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvZGEuanNcbi8vIG1vZHVsZSBpZCA9IDI1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBHZXJtYW4gW2RlXVxuLy8hIGF1dGhvciA6IGxsdWNocyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9sbHVjaHNcbi8vISBhdXRob3I6IE1lbmVsaW9uIEVsZW5zw7psZTogaHR0cHM6Ly9naXRodWIuY29tL09pcmVcbi8vISBhdXRob3IgOiBNaWtvbGFqIERhZGVsYSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWswMWFqXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxuZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAnbSc6IFsnZWluZSBNaW51dGUnLCAnZWluZXIgTWludXRlJ10sXG4gICAgICAgICdoJzogWydlaW5lIFN0dW5kZScsICdlaW5lciBTdHVuZGUnXSxcbiAgICAgICAgJ2QnOiBbJ2VpbiBUYWcnLCAnZWluZW0gVGFnJ10sXG4gICAgICAgICdkZCc6IFtudW1iZXIgKyAnIFRhZ2UnLCBudW1iZXIgKyAnIFRhZ2VuJ10sXG4gICAgICAgICdNJzogWydlaW4gTW9uYXQnLCAnZWluZW0gTW9uYXQnXSxcbiAgICAgICAgJ01NJzogW251bWJlciArICcgTW9uYXRlJywgbnVtYmVyICsgJyBNb25hdGVuJ10sXG4gICAgICAgICd5JzogWydlaW4gSmFocicsICdlaW5lbSBKYWhyJ10sXG4gICAgICAgICd5eSc6IFtudW1iZXIgKyAnIEphaHJlJywgbnVtYmVyICsgJyBKYWhyZW4nXVxuICAgIH07XG4gICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xufVxuXG52YXIgZGUgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdkZScsIHtcbiAgICBtb250aHMgOiAnSmFudWFyX0ZlYnJ1YXJfTcOkcnpfQXByaWxfTWFpX0p1bmlfSnVsaV9BdWd1c3RfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGV6ZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuLl9GZWIuX03DpHJ6X0Fwci5fTWFpX0p1bmlfSnVsaV9BdWcuX1NlcC5fT2t0Ll9Ob3YuX0Rlei4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnU29ubnRhZ19Nb250YWdfRGllbnN0YWdfTWl0dHdvY2hfRG9ubmVyc3RhZ19GcmVpdGFnX1NhbXN0YWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdTby5fTW8uX0RpLl9NaS5fRG8uX0ZyLl9TYS4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU29fTW9fRGlfTWlfRG9fRnJfU2EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbaGV1dGUgdW1dIExUIFtVaHJdJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICAgICAgbmV4dERheTogJ1ttb3JnZW4gdW1dIExUIFtVaHJdJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFt1bV0gTFQgW1Vocl0nLFxuICAgICAgICBsYXN0RGF5OiAnW2dlc3Rlcm4gdW1dIExUIFtVaHJdJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbbGV0enRlbl0gZGRkZCBbdW1dIExUIFtVaHJdJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJ3ZvciAlcycsXG4gICAgICAgIHMgOiAnZWluIHBhYXIgU2VrdW5kZW4nLFxuICAgICAgICBzcyA6ICclZCBTZWt1bmRlbicsXG4gICAgICAgIG0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBtbSA6ICclZCBNaW51dGVuJyxcbiAgICAgICAgaCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIGhoIDogJyVkIFN0dW5kZW4nLFxuICAgICAgICBkIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgZGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBNIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgTU0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICB5IDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgeXkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZGU7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2RlLmpzXG4vLyBtb2R1bGUgaWQgPSAyNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogR2VybWFuIChBdXN0cmlhKSBbZGUtYXRdXG4vLyEgYXV0aG9yIDogbGx1Y2hzIDogaHR0cHM6Ly9naXRodWIuY29tL2xsdWNoc1xuLy8hIGF1dGhvcjogTWVuZWxpb24gRWxlbnPDumxlOiBodHRwczovL2dpdGh1Yi5jb20vT2lyZVxuLy8hIGF1dGhvciA6IE1hcnRpbiBHcm9sbGVyIDogaHR0cHM6Ly9naXRodWIuY29tL01hZE1HXG4vLyEgYXV0aG9yIDogTWlrb2xhaiBEYWRlbGEgOiBodHRwczovL2dpdGh1Yi5jb20vbWlrMDFhalxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbmZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ20nOiBbJ2VpbmUgTWludXRlJywgJ2VpbmVyIE1pbnV0ZSddLFxuICAgICAgICAnaCc6IFsnZWluZSBTdHVuZGUnLCAnZWluZXIgU3R1bmRlJ10sXG4gICAgICAgICdkJzogWydlaW4gVGFnJywgJ2VpbmVtIFRhZyddLFxuICAgICAgICAnZGQnOiBbbnVtYmVyICsgJyBUYWdlJywgbnVtYmVyICsgJyBUYWdlbiddLFxuICAgICAgICAnTSc6IFsnZWluIE1vbmF0JywgJ2VpbmVtIE1vbmF0J10sXG4gICAgICAgICdNTSc6IFtudW1iZXIgKyAnIE1vbmF0ZScsIG51bWJlciArICcgTW9uYXRlbiddLFxuICAgICAgICAneSc6IFsnZWluIEphaHInLCAnZWluZW0gSmFociddLFxuICAgICAgICAneXknOiBbbnVtYmVyICsgJyBKYWhyZScsIG51bWJlciArICcgSmFocmVuJ11cbiAgICB9O1xuICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gZm9ybWF0W2tleV1bMF0gOiBmb3JtYXRba2V5XVsxXTtcbn1cblxudmFyIGRlQXQgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdkZS1hdCcsIHtcbiAgICBtb250aHMgOiAnSsOkbm5lcl9GZWJydWFyX03DpHJ6X0FwcmlsX01haV9KdW5pX0p1bGlfQXVndXN0X1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0RlemVtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0rDpG4uX0ZlYi5fTcOkcnpfQXByLl9NYWlfSnVuaV9KdWxpX0F1Zy5fU2VwLl9Pa3QuX05vdi5fRGV6Licuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdTb25udGFnX01vbnRhZ19EaWVuc3RhZ19NaXR0d29jaF9Eb25uZXJzdGFnX0ZyZWl0YWdfU2Ftc3RhZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1NvLl9Nby5fRGkuX01pLl9Eby5fRnIuX1NhLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTb19Nb19EaV9NaV9Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBELiBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1toZXV0ZSB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3VtXSBMVCBbVWhyXScsXG4gICAgICAgIGxhc3REYXk6ICdbZ2VzdGVybiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBsYXN0V2VlazogJ1tsZXR6dGVuXSBkZGRkIFt1bV0gTFQgW1Vocl0nXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgIHBhc3QgOiAndm9yICVzJyxcbiAgICAgICAgcyA6ICdlaW4gcGFhciBTZWt1bmRlbicsXG4gICAgICAgIHNzIDogJyVkIFNla3VuZGVuJyxcbiAgICAgICAgbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIG1tIDogJyVkIE1pbnV0ZW4nLFxuICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgaGggOiAnJWQgU3R1bmRlbicsXG4gICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBkZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIE0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICB5eSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBkZUF0O1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9kZS1hdC5qc1xuLy8gbW9kdWxlIGlkID0gMjdcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEdlcm1hbiAoU3dpdHplcmxhbmQpIFtkZS1jaF1cbi8vISBhdXRob3IgOiBzc2NodWVsbGVyIDogaHR0cHM6Ly9naXRodWIuY29tL3NzY2h1ZWxsZXJcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG4vLyBiYXNlZCBvbjogaHR0cHM6Ly93d3cuYmsuYWRtaW4uY2gvZG9rdW1lbnRhdGlvbi9zcHJhY2hlbi8wNDkxNS8wNTAxNi9pbmRleC5odG1sP2xhbmc9ZGUjXG5cbmZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ20nOiBbJ2VpbmUgTWludXRlJywgJ2VpbmVyIE1pbnV0ZSddLFxuICAgICAgICAnaCc6IFsnZWluZSBTdHVuZGUnLCAnZWluZXIgU3R1bmRlJ10sXG4gICAgICAgICdkJzogWydlaW4gVGFnJywgJ2VpbmVtIFRhZyddLFxuICAgICAgICAnZGQnOiBbbnVtYmVyICsgJyBUYWdlJywgbnVtYmVyICsgJyBUYWdlbiddLFxuICAgICAgICAnTSc6IFsnZWluIE1vbmF0JywgJ2VpbmVtIE1vbmF0J10sXG4gICAgICAgICdNTSc6IFtudW1iZXIgKyAnIE1vbmF0ZScsIG51bWJlciArICcgTW9uYXRlbiddLFxuICAgICAgICAneSc6IFsnZWluIEphaHInLCAnZWluZW0gSmFociddLFxuICAgICAgICAneXknOiBbbnVtYmVyICsgJyBKYWhyZScsIG51bWJlciArICcgSmFocmVuJ11cbiAgICB9O1xuICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gZm9ybWF0W2tleV1bMF0gOiBmb3JtYXRba2V5XVsxXTtcbn1cblxudmFyIGRlQ2ggPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdkZS1jaCcsIHtcbiAgICBtb250aHMgOiAnSmFudWFyX0ZlYnJ1YXJfTcOkcnpfQXByaWxfTWFpX0p1bmlfSnVsaV9BdWd1c3RfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGV6ZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuLl9GZWIuX03DpHJ6X0Fwci5fTWFpX0p1bmlfSnVsaV9BdWcuX1NlcC5fT2t0Ll9Ob3YuX0Rlei4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnU29ubnRhZ19Nb250YWdfRGllbnN0YWdfTWl0dHdvY2hfRG9ubmVyc3RhZ19GcmVpdGFnX1NhbXN0YWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdTb19Nb19EaV9NaV9Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTb19Nb19EaV9NaV9Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBELiBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1toZXV0ZSB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBzYW1lRWxzZTogJ0wnLFxuICAgICAgICBuZXh0RGF5OiAnW21vcmdlbiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3VtXSBMVCBbVWhyXScsXG4gICAgICAgIGxhc3REYXk6ICdbZ2VzdGVybiB1bV0gTFQgW1Vocl0nLFxuICAgICAgICBsYXN0V2VlazogJ1tsZXR6dGVuXSBkZGRkIFt1bV0gTFQgW1Vocl0nXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgIHBhc3QgOiAndm9yICVzJyxcbiAgICAgICAgcyA6ICdlaW4gcGFhciBTZWt1bmRlbicsXG4gICAgICAgIHNzIDogJyVkIFNla3VuZGVuJyxcbiAgICAgICAgbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIG1tIDogJyVkIE1pbnV0ZW4nLFxuICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgaGggOiAnJWQgU3R1bmRlbicsXG4gICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBkZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIE0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICB5eSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBkZUNoO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9kZS1jaC5qc1xuLy8gbW9kdWxlIGlkID0gMjhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IE1hbGRpdmlhbiBbZHZdXG4vLyEgYXV0aG9yIDogSmF3aXNoIEhhbWVlZCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qYXdpc2hcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbW9udGhzID0gW1xuICAgICfelt6s3oLeqt6H3qbeg96pJyxcbiAgICAn3orerN6E3rDeg96q3ofept6D3qknLFxuICAgICfeid6n3oPeqN6X3qonLFxuICAgICfeh96t3pXesN6D3qnejd6qJyxcbiAgICAn3onerScsXG4gICAgJ96W3qvegt6wJyxcbiAgICAn3pbeqt6N3qbeh96oJyxcbiAgICAn3ofer96O3qbekN6w3pPeqicsXG4gICAgJ96Q3qzeld6w3pPerN6J3rDehN6m3oPeqicsXG4gICAgJ96H3q7eht6w3pPer96E3qbeg96qJyxcbiAgICAn3oLert6I3qzeid6w3oTept6D3qonLFxuICAgICfekd6o3pDerN6J3rDehN6m3oPeqidcbl07XG52YXIgd2Vla2RheXMgPSBbXG4gICAgJ96H3qfei96o3ofesN6M3qYnLFxuICAgICfegN6v3onepicsXG4gICAgJ96H3qbegt6w3o7ep96D3qYnLFxuICAgICfehN6q3ovepicsXG4gICAgJ96E3qreg96n3pDesN6K3qbejN6oJyxcbiAgICAn3oDeqt6G3qreg96qJyxcbiAgICAn3oDert6C3qjegN6o3oPeqidcbl07XG5cbnZhciBkdiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2R2Jywge1xuICAgIG1vbnRocyA6IG1vbnRocyxcbiAgICBtb250aHNTaG9ydCA6IG1vbnRocyxcbiAgICB3ZWVrZGF5cyA6IHdlZWtkYXlzLFxuICAgIHdlZWtkYXlzU2hvcnQgOiB3ZWVrZGF5cyxcbiAgICB3ZWVrZGF5c01pbiA6ICfeh96n3oveqF/egN6v3onepl/eh96m3oLesF/ehN6q3ovepl/ehN6q3oPep1/egN6q3obeql/egN6u3oLeqCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcblxuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnRC9NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/eid6GfN6J3oovLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuICfeid6KJyA9PT0gaW5wdXQ7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfeid6GJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn3oneiic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1veid6o3ofept6L3qpdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb3onep96L3qbeid6nXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1veh96o3ofesN6U3qxdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW96K3qfeh96o3ozeqt6I3qhdIGRkZGQgTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn3ozerN6D3q3ejt6m3ofeqCAlcycsXG4gICAgICAgIHBhc3QgOiAn3obeqt6D3qjegt6wICVzJyxcbiAgICAgICAgcyA6ICfekN6o3obeqt6C3rDejN6q3obert6F3qzeh96wJyxcbiAgICAgICAgc3MgOiAnZCUg3pDeqN6G3qregt6w3ozeqicsXG4gICAgICAgIG0gOiAn3oneqN6C3qjek96s3ofesCcsXG4gICAgICAgIG1tIDogJ96J3qjegt6o3pPeqiAlZCcsXG4gICAgICAgIGggOiAn3o7ept6R3qjeh96o3oPerN6H3rAnLFxuICAgICAgICBoaCA6ICfejt6m3pHeqN6H3qjeg96qICVkJyxcbiAgICAgICAgZCA6ICfei96q3ojept6A3qzeh96wJyxcbiAgICAgICAgZGQgOiAn3oveqt6I3qbekN6wICVkJyxcbiAgICAgICAgTSA6ICfeid6m3oDerN6H3rAnLFxuICAgICAgICBNTSA6ICfeid6m3pDesCAlZCcsXG4gICAgICAgIHkgOiAn3ofept6A3qbeg96s3ofesCcsXG4gICAgICAgIHl5IDogJ96H3qbegN6m3oPeqiAlZCdcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC8sL2csICfYjCcpO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogNywgIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiAxMiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZHY7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2R2LmpzXG4vLyBtb2R1bGUgaWQgPSAyOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogR3JlZWsgW2VsXVxuLy8hIGF1dGhvciA6IEFnZ2Vsb3MgS2FyYWxpYXMgOiBodHRwczovL2dpdGh1Yi5jb20vbWVoaWVsXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oaW5wdXQpIHtcbiAgICByZXR1cm4gaW5wdXQgaW5zdGFuY2VvZiBGdW5jdGlvbiB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaW5wdXQpID09PSAnW29iamVjdCBGdW5jdGlvbl0nO1xufVxuXG5cbnZhciBlbCA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2VsJywge1xuICAgIG1vbnRoc05vbWluYXRpdmVFbCA6ICfOmc6xzr3Ov8+FzqzPgc65zr/Pgl/Ops61zrLPgc6/z4XOrM+BzrnOv8+CX86czqzPgc+EzrnOv8+CX86Rz4DPgc6vzrvOuc6/z4JfzpzOrM65zr/Pgl/Omc6/z43Ovc65zr/Pgl/Omc6/z43Ou865zr/Pgl/Okc+NzrPOv8+Fz4PPhM6/z4JfzqPOtc+Az4TOrc68zrLPgc65zr/Pgl/On866z4TPjs6yz4HOuc6/z4Jfzp3Ov86tzrzOss+BzrnOv8+CX86UzrXOus6tzrzOss+BzrnOv8+CJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc0dlbml0aXZlRWwgOiAnzpnOsc69zr/Phc6xz4HOr86/z4VfzqbOtc6yz4HOv8+FzrHPgc6vzr/PhV/OnM6xz4HPhM6vzr/PhV/Okc+Az4HOuc67zq/Ov8+FX86czrHOkM6/z4VfzpnOv8+Fzr3Or86/z4VfzpnOv8+FzrvOr86/z4VfzpHPhc6zzr/Pjc+Dz4TOv8+FX86jzrXPgM+EzrXOvM6yz4HOr86/z4Vfzp/Ous+Ez4nOss+Bzq/Ov8+FX86dzr/Otc68zrLPgc6vzr/PhV/OlM61zrrOtc68zrLPgc6vzr/PhScuc3BsaXQoJ18nKSxcbiAgICBtb250aHMgOiBmdW5jdGlvbiAobW9tZW50VG9Gb3JtYXQsIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW1vbWVudFRvRm9ybWF0KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzTm9taW5hdGl2ZUVsO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBmb3JtYXQgPT09ICdzdHJpbmcnICYmIC9ELy50ZXN0KGZvcm1hdC5zdWJzdHJpbmcoMCwgZm9ybWF0LmluZGV4T2YoJ01NTU0nKSkpKSB7IC8vIGlmIHRoZXJlIGlzIGEgZGF5IG51bWJlciBiZWZvcmUgJ01NTU0nXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzR2VuaXRpdmVFbFttb21lbnRUb0Zvcm1hdC5tb250aCgpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNOb21pbmF0aXZlRWxbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1vbnRoc1Nob3J0IDogJ86ZzrHOvV/Ops61zrJfzpzOsc+BX86Rz4DPgV/OnM6xz4pfzpnOv8+Fzr1fzpnOv8+FzrtfzpHPhc6zX86jzrXPgF/On866z4Rfzp3Ov861X86UzrXOuicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfOms+Fz4HOuc6xzrrOrl/OlM61z4XPhM6tz4HOsV/OpM+Bzq/PhM63X86kzrXPhM6sz4HPhM63X86gzq3OvM+Az4TOt1/OoM6xz4HOsc+DzrrOtc+Fzq5fzqPOrM6yzrLOsc+Ezr8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfOms+Fz4FfzpTOtc+FX86kz4HOuV/OpM61z4RfzqDOtc68X86gzrHPgV/Oo86xzrInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnzprPhV/OlM61X86kz4FfzqTOtV/OoM61X86gzrFfzqPOsScuc3BsaXQoJ18nKSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnzrzOvCcgOiAnzpzOnCc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfPgM68JyA6ICfOoM6cJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gKChpbnB1dCArICcnKS50b0xvd2VyQ2FzZSgpWzBdID09PSAnzrwnKTtcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2UgOiAvW86gzpxdXFwuP86cP1xcLj8vaSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXJFbCA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbzqPOrs68zrXPgc6xIHt9XSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW86Rz43Pgc65zr8ge31dIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbe31dIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbzqfOuM61z4Ige31dIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW8+Ezr8gz4DPgc6/zrfOs86/z43OvM61zr3Ov10gZGRkZCBbe31dIExUJztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vPhM63zr0gz4DPgc6/zrfOs86/z43OvM61zr3Ot10gZGRkZCBbe31dIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDogZnVuY3Rpb24gKGtleSwgbW9tKSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSB0aGlzLl9jYWxlbmRhckVsW2tleV0sXG4gICAgICAgICAgICBob3VycyA9IG1vbSAmJiBtb20uaG91cnMoKTtcbiAgICAgICAgaWYgKGlzRnVuY3Rpb24ob3V0cHV0KSkge1xuICAgICAgICAgICAgb3V0cHV0ID0gb3V0cHV0LmFwcGx5KG1vbSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dHB1dC5yZXBsYWNlKCd7fScsIChob3VycyAlIDEyID09PSAxID8gJ8+Dz4TOtycgOiAnz4PPhM65z4InKSk7XG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfPg861ICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyDPgM+BzrnOvScsXG4gICAgICAgIHMgOiAnzrvOr86zzrEgzrTOtc+Fz4TOtc+Bz4zOu861z4DPhM6xJyxcbiAgICAgICAgc3MgOiAnJWQgzrTOtc+Fz4TOtc+Bz4zOu861z4DPhM6xJyxcbiAgICAgICAgbSA6ICfOrc69zrEgzrvOtc+Az4TPjCcsXG4gICAgICAgIG1tIDogJyVkIM67zrXPgM+EzqwnLFxuICAgICAgICBoIDogJ868zq/OsSDPjs+BzrEnLFxuICAgICAgICBoaCA6ICclZCDPjs+BzrXPgicsXG4gICAgICAgIGQgOiAnzrzOr86xIM68zq3Pgc6xJyxcbiAgICAgICAgZGQgOiAnJWQgzrzOrc+BzrXPgicsXG4gICAgICAgIE0gOiAnzq3Ovc6xz4IgzrzOrs69zrHPgicsXG4gICAgICAgIE1NIDogJyVkIM68zq7Ovc61z4InLFxuICAgICAgICB5IDogJ86tzr3Osc+CIM+Hz4HPjM69zr/PgicsXG4gICAgICAgIHl5IDogJyVkIM+Hz4HPjM69zrnOsSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfc63LyxcbiAgICBvcmRpbmFsOiAnJWTOtycsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDRzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGVsO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbC5qc1xuLy8gbW9kdWxlIGlkID0gMzBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEVuZ2xpc2ggKEF1c3RyYWxpYSkgW2VuLWF1XVxuLy8hIGF1dGhvciA6IEphcmVkIE1vcnNlIDogaHR0cHM6Ly9naXRodWIuY29tL2phcmNvYWxcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgZW5BdSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2VuLWF1Jywge1xuICAgIG1vbnRocyA6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZHMnLFxuICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAnYW4gaG91cicsXG4gICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgIGRkIDogJyVkIGRheXMnLFxuICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICB5IDogJ2EgeWVhcicsXG4gICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZW5BdTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvZW4tYXUuanNcbi8vIG1vZHVsZSBpZCA9IDMxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBFbmdsaXNoIChDYW5hZGEpIFtlbi1jYV1cbi8vISBhdXRob3IgOiBKb25hdGhhbiBBYm91cmJpaCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb25iY2FcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgZW5DYSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2VuLWNhJywge1xuICAgIG1vbnRocyA6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgTEwgOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgTExMIDogJ01NTU0gRCwgWVlZWSBoOm1tIEEnLFxuICAgICAgICBMTExMIDogJ2RkZGQsIE1NTU0gRCwgWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZHMnLFxuICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAnYW4gaG91cicsXG4gICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgIGRkIDogJyVkIGRheXMnLFxuICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICB5IDogJ2EgeWVhcicsXG4gICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfVxufSk7XG5cbnJldHVybiBlbkNhO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbi1jYS5qc1xuLy8gbW9kdWxlIGlkID0gMzJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEVuZ2xpc2ggKFVuaXRlZCBLaW5nZG9tKSBbZW4tZ2JdXG4vLyEgYXV0aG9yIDogQ2hyaXMgR2VkcmltIDogaHR0cHM6Ly9naXRodWIuY29tL2NocmlzZ2VkcmltXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGVuR2IgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdlbi1nYicsIHtcbiAgICBtb250aHMgOiAnSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTdV9Nb19UdV9XZV9UaF9Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZHMnLFxuICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAnYW4gaG91cicsXG4gICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgIGRkIDogJyVkIGRheXMnLFxuICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICB5IDogJ2EgeWVhcicsXG4gICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZW5HYjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvZW4tZ2IuanNcbi8vIG1vZHVsZSBpZCA9IDMzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBFbmdsaXNoIChJcmVsYW5kKSBbZW4taWVdXG4vLyEgYXV0aG9yIDogQ2hyaXMgQ2FydGxpZGdlIDogaHR0cHM6Ly9naXRodWIuY29tL2NocmlzY2FydGxpZGdlXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGVuSWUgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdlbi1pZScsIHtcbiAgICBtb250aHMgOiAnSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdTdW5kYXlfTW9uZGF5X1R1ZXNkYXlfV2VkbmVzZGF5X1RodXJzZGF5X0ZyaWRheV9TYXR1cmRheScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTdV9Nb19UdV9XZV9UaF9Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELU1NLVlZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tUb21vcnJvdyBhdF0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFthdF0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW0xhc3RdIGRkZGQgW2F0XSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdpbiAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgYWdvJyxcbiAgICAgICAgcyA6ICdhIGZldyBzZWNvbmRzJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kcycsXG4gICAgICAgIG0gOiAnYSBtaW51dGUnLFxuICAgICAgICBtbSA6ICclZCBtaW51dGVzJyxcbiAgICAgICAgaCA6ICdhbiBob3VyJyxcbiAgICAgICAgaGggOiAnJWQgaG91cnMnLFxuICAgICAgICBkIDogJ2EgZGF5JyxcbiAgICAgICAgZGQgOiAnJWQgZGF5cycsXG4gICAgICAgIE0gOiAnYSBtb250aCcsXG4gICAgICAgIE1NIDogJyVkIG1vbnRocycsXG4gICAgICAgIHkgOiAnYSB5ZWFyJyxcbiAgICAgICAgeXkgOiAnJWQgeWVhcnMnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAndGgnIDpcbiAgICAgICAgICAgIChiID09PSAxKSA/ICdzdCcgOlxuICAgICAgICAgICAgKGIgPT09IDIpID8gJ25kJyA6XG4gICAgICAgICAgICAoYiA9PT0gMykgPyAncmQnIDogJ3RoJztcbiAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBlbkllO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lbi1pZS5qc1xuLy8gbW9kdWxlIGlkID0gMzRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEVuZ2xpc2ggKE5ldyBaZWFsYW5kKSBbZW4tbnpdXG4vLyEgYXV0aG9yIDogTHVrZSBNY0dyZWdvciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9sdWtlbWNncmVnb3JcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgZW5OeiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2VuLW56Jywge1xuICAgIG1vbnRocyA6ICdKYW51YXJ5X0ZlYnJ1YXJ5X01hcmNoX0FwcmlsX01heV9KdW5lX0p1bHlfQXVndXN0X1NlcHRlbWJlcl9PY3RvYmVyX05vdmVtYmVyX0RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1N1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU3VuX01vbl9UdWVfV2VkX1RodV9GcmlfU2F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbVG9tb3Jyb3cgYXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tMYXN0XSBkZGRkIFthdF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaW4gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGFnbycsXG4gICAgICAgIHMgOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZHMnLFxuICAgICAgICBtIDogJ2EgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAnYW4gaG91cicsXG4gICAgICAgIGhoIDogJyVkIGhvdXJzJyxcbiAgICAgICAgZCA6ICdhIGRheScsXG4gICAgICAgIGRkIDogJyVkIGRheXMnLFxuICAgICAgICBNIDogJ2EgbW9udGgnLFxuICAgICAgICBNTSA6ICclZCBtb250aHMnLFxuICAgICAgICB5IDogJ2EgeWVhcicsXG4gICAgICAgIHl5IDogJyVkIHllYXJzJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0fG5kfHJkfHRoKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGIgPSBudW1iZXIgJSAxMCxcbiAgICAgICAgICAgIG91dHB1dCA9ICh+fihudW1iZXIgJSAxMDAgLyAxMCkgPT09IDEpID8gJ3RoJyA6XG4gICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICduZCcgOlxuICAgICAgICAgICAgKGIgPT09IDMpID8gJ3JkJyA6ICd0aCc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZW5OejtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvZW4tbnouanNcbi8vIG1vZHVsZSBpZCA9IDM1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBFc3BlcmFudG8gW2VvXVxuLy8hIGF1dGhvciA6IENvbGluIERlYW4gOiBodHRwczovL2dpdGh1Yi5jb20vY29saW5kZWFuXG4vLyEgYXV0aG9yIDogTWlhIE5vcmRlbnRvZnQgSW1wZXJhdG9yaSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWVzdGFzbWlhXG4vLyEgY29tbWVudCA6IG1pZXN0YXNtaWEgY29ycmVjdGVkIHRoZSB0cmFuc2xhdGlvbiBieSBjb2xpbmRlYW5cblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgZW8gPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdlbycsIHtcbiAgICBtb250aHMgOiAnamFudWFyb19mZWJydWFyb19tYXJ0b19hcHJpbG9fbWFqb19qdW5pb19qdWxpb19hxa1ndXN0b19zZXB0ZW1icm9fb2t0b2Jyb19ub3ZlbWJyb19kZWNlbWJybycuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW5fZmViX21hcl9hcHJfbWFqX2p1bl9qdWxfYcWtZ19zZXBfb2t0X25vdl9kZWMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnZGltYW7EiW9fbHVuZG9fbWFyZG9fbWVya3JlZG9fxLVhxa1kb192ZW5kcmVkb19zYWJhdG8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdkaW1fbHVuX21hcmRfbWVya1/EtWHFrV92ZW5fc2FiJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2RpX2x1X21hX21lX8S1YV92ZV9zYScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ1lZWVktTU0tREQnLFxuICAgICAgICBMTCA6ICdEWy1hIGRlXSBNTU1NLCBZWVlZJyxcbiAgICAgICAgTExMIDogJ0RbLWEgZGVdIE1NTU0sIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIFtsYV0gRFstYSBkZV0gTU1NTSwgWVlZWSBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC9bYXBdXFwudFxcLm0vaSxcbiAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0LmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpID09PSAncCc7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAncC50Lm0uJyA6ICdQLlQuTS4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnYS50Lm0uJyA6ICdBLlQuTS4nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbSG9kaWHFrSBqZV0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tNb3JnYcWtIGplXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2plXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0hpZXJhxa0gamVdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW3Bhc2ludGFdIGRkZGQgW2plXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdwb3N0ICVzJyxcbiAgICAgICAgcGFzdCA6ICdhbnRhxa0gJXMnLFxuICAgICAgICBzIDogJ3Nla3VuZG9qJyxcbiAgICAgICAgc3MgOiAnJWQgc2VrdW5kb2onLFxuICAgICAgICBtIDogJ21pbnV0bycsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0b2onLFxuICAgICAgICBoIDogJ2hvcm8nLFxuICAgICAgICBoaCA6ICclZCBob3JvaicsXG4gICAgICAgIGQgOiAndGFnbycsLy9uZSAnZGl1cm5vJywgxIlhciBlc3RhcyB1eml0YSBwb3IgcHJva3NpbXVtb1xuICAgICAgICBkZCA6ICclZCB0YWdvaicsXG4gICAgICAgIE0gOiAnbW9uYXRvJyxcbiAgICAgICAgTU0gOiAnJWQgbW9uYXRvaicsXG4gICAgICAgIHkgOiAnamFybycsXG4gICAgICAgIHl5IDogJyVkIGphcm9qJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9YS8sXG4gICAgb3JkaW5hbCA6ICclZGEnLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBlbztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvZW8uanNcbi8vIG1vZHVsZSBpZCA9IDM2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBTcGFuaXNoIFtlc11cbi8vISBhdXRob3IgOiBKdWxpbyBOYXB1csOtIDogaHR0cHM6Ly9naXRodWIuY29tL2p1bGlvbmNcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbW9udGhzU2hvcnREb3QgPSAnZW5lLl9mZWIuX21hci5fYWJyLl9tYXkuX2p1bi5fanVsLl9hZ28uX3NlcC5fb2N0Ll9ub3YuX2RpYy4nLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnQgPSAnZW5lX2ZlYl9tYXJfYWJyX21heV9qdW5fanVsX2Fnb19zZXBfb2N0X25vdl9kaWMnLnNwbGl0KCdfJyk7XG5cbnZhciBtb250aHNQYXJzZSA9IFsvXmVuZS9pLCAvXmZlYi9pLCAvXm1hci9pLCAvXmFici9pLCAvXm1heS9pLCAvXmp1bi9pLCAvXmp1bC9pLCAvXmFnby9pLCAvXnNlcC9pLCAvXm9jdC9pLCAvXm5vdi9pLCAvXmRpYy9pXTtcbnZhciBtb250aHNSZWdleCA9IC9eKGVuZXJvfGZlYnJlcm98bWFyem98YWJyaWx8bWF5b3xqdW5pb3xqdWxpb3xhZ29zdG98c2VwdGllbWJyZXxvY3R1YnJlfG5vdmllbWJyZXxkaWNpZW1icmV8ZW5lXFwuP3xmZWJcXC4/fG1hclxcLj98YWJyXFwuP3xtYXlcXC4/fGp1blxcLj98anVsXFwuP3xhZ29cXC4/fHNlcFxcLj98b2N0XFwuP3xub3ZcXC4/fGRpY1xcLj8pL2k7XG5cbnZhciBlcyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2VzJywge1xuICAgIG1vbnRocyA6ICdlbmVyb19mZWJyZXJvX21hcnpvX2FicmlsX21heW9fanVuaW9fanVsaW9fYWdvc3RvX3NlcHRpZW1icmVfb2N0dWJyZV9ub3ZpZW1icmVfZGljaWVtYnJlJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdDtcbiAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0W20ubW9udGgoKV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnREb3RbbS5tb250aCgpXTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbW9udGhzUmVnZXggOiBtb250aHNSZWdleCxcbiAgICBtb250aHNTaG9ydFJlZ2V4IDogbW9udGhzUmVnZXgsXG4gICAgbW9udGhzU3RyaWN0UmVnZXggOiAvXihlbmVyb3xmZWJyZXJvfG1hcnpvfGFicmlsfG1heW98anVuaW98anVsaW98YWdvc3RvfHNlcHRpZW1icmV8b2N0dWJyZXxub3ZpZW1icmV8ZGljaWVtYnJlKS9pLFxuICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXggOiAvXihlbmVcXC4/fGZlYlxcLj98bWFyXFwuP3xhYnJcXC4/fG1heVxcLj98anVuXFwuP3xqdWxcXC4/fGFnb1xcLj98c2VwXFwuP3xvY3RcXC4/fG5vdlxcLj98ZGljXFwuPykvaSxcbiAgICBtb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlLFxuICAgIGxvbmdNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlLFxuICAgIHNob3J0TW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSxcbiAgICB3ZWVrZGF5cyA6ICdkb21pbmdvX2x1bmVzX21hcnRlc19tacOpcmNvbGVzX2p1ZXZlc192aWVybmVzX3PDoWJhZG8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdkb20uX2x1bi5fbWFyLl9tacOpLl9qdWUuX3ZpZS5fc8OhYi4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnZG9fbHVfbWFfbWlfanVfdmlfc8OhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2hveSBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbmV4dERheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW21hw7FhbmEgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdkZGRkIFthIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2F5ZXIgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbZWxdIGRkZGQgW3Bhc2FkbyBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2VuICVzJyxcbiAgICAgICAgcGFzdCA6ICdoYWNlICVzJyxcbiAgICAgICAgcyA6ICd1bm9zIHNlZ3VuZG9zJyxcbiAgICAgICAgc3MgOiAnJWQgc2VndW5kb3MnLFxuICAgICAgICBtIDogJ3VuIG1pbnV0bycsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0b3MnLFxuICAgICAgICBoIDogJ3VuYSBob3JhJyxcbiAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICBkIDogJ3VuIGTDrWEnLFxuICAgICAgICBkZCA6ICclZCBkw61hcycsXG4gICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgTU0gOiAnJWQgbWVzZXMnLFxuICAgICAgICB5IDogJ3VuIGHDsW8nLFxuICAgICAgICB5eSA6ICclZCBhw7FvcydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn3Cui8sXG4gICAgb3JkaW5hbCA6ICclZMK6JyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZXM7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2VzLmpzXG4vLyBtb2R1bGUgaWQgPSAzN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU3BhbmlzaCAoRG9taW5pY2FuIFJlcHVibGljKSBbZXMtZG9dXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIG1vbnRoc1Nob3J0RG90ID0gJ2VuZS5fZmViLl9tYXIuX2Fici5fbWF5Ll9qdW4uX2p1bC5fYWdvLl9zZXAuX29jdC5fbm92Ll9kaWMuJy5zcGxpdCgnXycpO1xudmFyIG1vbnRoc1Nob3J0ID0gJ2VuZV9mZWJfbWFyX2Ficl9tYXlfanVuX2p1bF9hZ29fc2VwX29jdF9ub3ZfZGljJy5zcGxpdCgnXycpO1xuXG52YXIgbW9udGhzUGFyc2UgPSBbL15lbmUvaSwgL15mZWIvaSwgL15tYXIvaSwgL15hYnIvaSwgL15tYXkvaSwgL15qdW4vaSwgL15qdWwvaSwgL15hZ28vaSwgL15zZXAvaSwgL15vY3QvaSwgL15ub3YvaSwgL15kaWMvaV07XG52YXIgbW9udGhzUmVnZXggPSAvXihlbmVyb3xmZWJyZXJvfG1hcnpvfGFicmlsfG1heW98anVuaW98anVsaW98YWdvc3RvfHNlcHRpZW1icmV8b2N0dWJyZXxub3ZpZW1icmV8ZGljaWVtYnJlfGVuZVxcLj98ZmViXFwuP3xtYXJcXC4/fGFiclxcLj98bWF5XFwuP3xqdW5cXC4/fGp1bFxcLj98YWdvXFwuP3xzZXBcXC4/fG9jdFxcLj98bm92XFwuP3xkaWNcXC4/KS9pO1xuXG52YXIgZXNEbyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2VzLWRvJywge1xuICAgIG1vbnRocyA6ICdlbmVyb19mZWJyZXJvX21hcnpvX2FicmlsX21heW9fanVuaW9fanVsaW9fYWdvc3RvX3NlcHRpZW1icmVfb2N0dWJyZV9ub3ZpZW1icmVfZGljaWVtYnJlJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdDtcbiAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0W20ubW9udGgoKV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnREb3RbbS5tb250aCgpXTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbW9udGhzUmVnZXg6IG1vbnRoc1JlZ2V4LFxuICAgIG1vbnRoc1Nob3J0UmVnZXg6IG1vbnRoc1JlZ2V4LFxuICAgIG1vbnRoc1N0cmljdFJlZ2V4OiAvXihlbmVyb3xmZWJyZXJvfG1hcnpvfGFicmlsfG1heW98anVuaW98anVsaW98YWdvc3RvfHNlcHRpZW1icmV8b2N0dWJyZXxub3ZpZW1icmV8ZGljaWVtYnJlKS9pLFxuICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKGVuZVxcLj98ZmViXFwuP3xtYXJcXC4/fGFiclxcLj98bWF5XFwuP3xqdW5cXC4/fGp1bFxcLj98YWdvXFwuP3xzZXBcXC4/fG9jdFxcLj98bm92XFwuP3xkaWNcXC4/KS9pLFxuICAgIG1vbnRoc1BhcnNlOiBtb250aHNQYXJzZSxcbiAgICBsb25nTW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlLFxuICAgIHNob3J0TW9udGhzUGFyc2U6IG1vbnRoc1BhcnNlLFxuICAgIHdlZWtkYXlzIDogJ2RvbWluZ29fbHVuZXNfbWFydGVzX21pw6lyY29sZXNfanVldmVzX3ZpZXJuZXNfc8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ2RvbS5fbHVuLl9tYXIuX21pw6kuX2p1ZS5fdmllLl9zw6FiLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdkb19sdV9tYV9taV9qdV92aV9zw6EnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIFtkZV0gTU1NTSBbZGVdIFlZWVkgaDptbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1tob3kgYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHREYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1ttYcOxYW5hIGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBuZXh0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnZGRkZCBbYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3REYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1theWVyIGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2VsXSBkZGRkIFtwYXNhZG8gYSBsYScgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAncycgOiAnJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdlbiAlcycsXG4gICAgICAgIHBhc3QgOiAnaGFjZSAlcycsXG4gICAgICAgIHMgOiAndW5vcyBzZWd1bmRvcycsXG4gICAgICAgIHNzIDogJyVkIHNlZ3VuZG9zJyxcbiAgICAgICAgbSA6ICd1biBtaW51dG8nLFxuICAgICAgICBtbSA6ICclZCBtaW51dG9zJyxcbiAgICAgICAgaCA6ICd1bmEgaG9yYScsXG4gICAgICAgIGhoIDogJyVkIGhvcmFzJyxcbiAgICAgICAgZCA6ICd1biBkw61hJyxcbiAgICAgICAgZGQgOiAnJWQgZMOtYXMnLFxuICAgICAgICBNIDogJ3VuIG1lcycsXG4gICAgICAgIE1NIDogJyVkIG1lc2VzJyxcbiAgICAgICAgeSA6ICd1biBhw7FvJyxcbiAgICAgICAgeXkgOiAnJWQgYcOxb3MnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9wrovLFxuICAgIG9yZGluYWwgOiAnJWTCuicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGVzRG87XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2VzLWRvLmpzXG4vLyBtb2R1bGUgaWQgPSAzOFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU3BhbmlzaCAoVW5pdGVkIFN0YXRlcykgW2VzLXVzXVxuLy8hIGF1dGhvciA6IGJ1c3R0YSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9idXN0dGFcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbW9udGhzU2hvcnREb3QgPSAnZW5lLl9mZWIuX21hci5fYWJyLl9tYXkuX2p1bi5fanVsLl9hZ28uX3NlcC5fb2N0Ll9ub3YuX2RpYy4nLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnQgPSAnZW5lX2ZlYl9tYXJfYWJyX21heV9qdW5fanVsX2Fnb19zZXBfb2N0X25vdl9kaWMnLnNwbGl0KCdfJyk7XG5cbnZhciBlc1VzID0gbW9tZW50LmRlZmluZUxvY2FsZSgnZXMtdXMnLCB7XG4gICAgbW9udGhzIDogJ2VuZXJvX2ZlYnJlcm9fbWFyem9fYWJyaWxfbWF5b19qdW5pb19qdWxpb19hZ29zdG9fc2VwdGllbWJyZV9vY3R1YnJlX25vdmllbWJyZV9kaWNpZW1icmUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiBmdW5jdGlvbiAobSwgZm9ybWF0KSB7XG4gICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0RG90O1xuICAgICAgICB9IGVsc2UgaWYgKC8tTU1NLS8udGVzdChmb3JtYXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRbbS5tb250aCgpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydERvdFttLm1vbnRoKCldO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdkb21pbmdvX2x1bmVzX21hcnRlc19tacOpcmNvbGVzX2p1ZXZlc192aWVybmVzX3PDoWJhZG8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdkb20uX2x1bi5fbWFyLl9tacOpLl9qdWUuX3ZpZS5fc8OhYi4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnZG9fbHVfbWFfbWlfanVfdmlfc8OhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ2g6bW0gQScsXG4gICAgICAgIExUUyA6ICdoOm1tOnNzIEEnLFxuICAgICAgICBMIDogJ01NL0REL1lZWVknLFxuICAgICAgICBMTCA6ICdNTU1NIFtkZV0gRCBbZGVdIFlZWVknLFxuICAgICAgICBMTEwgOiAnTU1NTSBbZGVdIEQgW2RlXSBZWVlZIGg6bW0gQScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgTU1NTSBbZGVdIEQgW2RlXSBZWVlZIGg6bW0gQSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbaG95IGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBuZXh0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbbWHDsWFuYSBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ2RkZGQgW2EgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbYXllciBhIGxhJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICdzJyA6ICcnKSArICddIExUJztcbiAgICAgICAgfSxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1tlbF0gZGRkZCBbcGFzYWRvIGEgbGEnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ3MnIDogJycpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnZW4gJXMnLFxuICAgICAgICBwYXN0IDogJ2hhY2UgJXMnLFxuICAgICAgICBzIDogJ3Vub3Mgc2VndW5kb3MnLFxuICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgIG0gOiAndW4gbWludXRvJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRvcycsXG4gICAgICAgIGggOiAndW5hIGhvcmEnLFxuICAgICAgICBoaCA6ICclZCBob3JhcycsXG4gICAgICAgIGQgOiAndW4gZMOtYScsXG4gICAgICAgIGRkIDogJyVkIGTDrWFzJyxcbiAgICAgICAgTSA6ICd1biBtZXMnLFxuICAgICAgICBNTSA6ICclZCBtZXNlcycsXG4gICAgICAgIHkgOiAndW4gYcOxbycsXG4gICAgICAgIHl5IDogJyVkIGHDsW9zJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfcK6LyxcbiAgICBvcmRpbmFsIDogJyVkwronLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA2ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBlc1VzO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9lcy11cy5qc1xuLy8gbW9kdWxlIGlkID0gMzlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEVzdG9uaWFuIFtldF1cbi8vISBhdXRob3IgOiBIZW5yeSBLZWhsbWFubiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9tYWRoZW5yeVxuLy8hIGltcHJvdmVtZW50cyA6IElsbGltYXIgVGFtYmVrIDogaHR0cHM6Ly9naXRodWIuY29tL3JhZ3Vsa2FcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG5mdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICdzJyA6IFsnbcO1bmUgc2VrdW5kaScsICdtw7VuaSBzZWt1bmQnLCAncGFhciBzZWt1bmRpdCddLFxuICAgICAgICAnc3MnOiBbbnVtYmVyICsgJ3Nla3VuZGknLCBudW1iZXIgKyAnc2VrdW5kaXQnXSxcbiAgICAgICAgJ20nIDogWyfDvGhlIG1pbnV0aScsICfDvGtzIG1pbnV0J10sXG4gICAgICAgICdtbSc6IFtudW1iZXIgKyAnIG1pbnV0aScsIG51bWJlciArICcgbWludXRpdCddLFxuICAgICAgICAnaCcgOiBbJ8O8aGUgdHVubmknLCAndHVuZCBhZWdhJywgJ8O8a3MgdHVuZCddLFxuICAgICAgICAnaGgnOiBbbnVtYmVyICsgJyB0dW5uaScsIG51bWJlciArICcgdHVuZGknXSxcbiAgICAgICAgJ2QnIDogWyfDvGhlIHDDpGV2YScsICfDvGtzIHDDpGV2J10sXG4gICAgICAgICdNJyA6IFsna3V1IGFqYScsICdrdXUgYWVnYScsICfDvGtzIGt1dSddLFxuICAgICAgICAnTU0nOiBbbnVtYmVyICsgJyBrdXUnLCBudW1iZXIgKyAnIGt1dWQnXSxcbiAgICAgICAgJ3knIDogWyfDvGhlIGFhc3RhJywgJ2Fhc3RhJywgJ8O8a3MgYWFzdGEnXSxcbiAgICAgICAgJ3l5JzogW251bWJlciArICcgYWFzdGEnLCBudW1iZXIgKyAnIGFhc3RhdCddXG4gICAgfTtcbiAgICBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gZm9ybWF0W2tleV1bMl0gPyBmb3JtYXRba2V5XVsyXSA6IGZvcm1hdFtrZXldWzFdO1xuICAgIH1cbiAgICByZXR1cm4gaXNGdXR1cmUgPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xufVxuXG52YXIgZXQgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdldCcsIHtcbiAgICBtb250aHMgICAgICAgIDogJ2phYW51YXJfdmVlYnJ1YXJfbcOkcnRzX2FwcmlsbF9tYWlfanV1bmlfanV1bGlfYXVndXN0X3NlcHRlbWJlcl9va3Rvb2Jlcl9ub3ZlbWJlcl9kZXRzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgICA6ICdqYWFuX3ZlZWJyX23DpHJ0c19hcHJfbWFpX2p1dW5pX2p1dWxpX2F1Z19zZXB0X29rdF9ub3ZfZGV0cycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyAgICAgIDogJ3DDvGhhcMOkZXZfZXNtYXNww6Rldl90ZWlzaXDDpGV2X2tvbG1hcMOkZXZfbmVsamFww6Rldl9yZWVkZV9sYXVww6Rldicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1BfRV9UX0tfTl9SX0wnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gICA6ICdQX0VfVF9LX05fUl9MJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCAgIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgICAgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMICAgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMICA6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSAgOiAnW1TDpG5hLF0gTFQnLFxuICAgICAgICBuZXh0RGF5ICA6ICdbSG9tbWUsXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1tKw6RyZ21pbmVdIGRkZGQgTFQnLFxuICAgICAgICBsYXN0RGF5ICA6ICdbRWlsZSxdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW0VlbG1pbmVdIGRkZGQgTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMgcMOkcmFzdCcsXG4gICAgICAgIHBhc3QgICA6ICclcyB0YWdhc2knLFxuICAgICAgICBzICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBzcyAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBtICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBtbSAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBoICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBoaCAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBkICAgICAgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBkZCAgICAgOiAnJWQgcMOkZXZhJyxcbiAgICAgICAgTSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgTU0gICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgeSAgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgeXkgICAgIDogcHJvY2Vzc1JlbGF0aXZlVGltZVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGV0O1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ldC5qc1xuLy8gbW9kdWxlIGlkID0gNDBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEJhc3F1ZSBbZXVdXG4vLyEgYXV0aG9yIDogRW5la28gSWxsYXJyYW1lbmRpIDogaHR0cHM6Ly9naXRodWIuY29tL2VpbGxhcnJhXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGV1ID0gbW9tZW50LmRlZmluZUxvY2FsZSgnZXUnLCB7XG4gICAgbW9udGhzIDogJ3VydGFycmlsYV9vdHNhaWxhX21hcnR4b2FfYXBpcmlsYV9tYWlhdHphX2VrYWluYV91enRhaWxhX2FidXp0dWFfaXJhaWxhX3VycmlhX2F6YXJvYV9hYmVuZHVhJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ3VydC5fb3RzLl9tYXIuX2FwaS5fbWFpLl9la2EuX3V6dC5fYWJ1Ll9pcmEuX3Vyci5fYXphLl9hYmUuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2lnYW5kZWFfYXN0ZWxlaGVuYV9hc3RlYXJ0ZWFfYXN0ZWF6a2VuYV9vc3RlZ3VuYV9vc3RpcmFsYV9sYXJ1bmJhdGEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdpZy5fYWwuX2FyLl9hei5fb2cuX29sLl9sci4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnaWdfYWxfYXJfYXpfb2dfb2xfbHInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ1lZWVktTU0tREQnLFxuICAgICAgICBMTCA6ICdZWVlZW2tvXSBNTU1NW3Jlbl0gRFthXScsXG4gICAgICAgIExMTCA6ICdZWVlZW2tvXSBNTU1NW3Jlbl0gRFthXSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgWVlZWVtrb10gTU1NTVtyZW5dIERbYV0gSEg6bW0nLFxuICAgICAgICBsIDogJ1lZWVktTS1EJyxcbiAgICAgICAgbGwgOiAnWVlZWVtrb10gTU1NIERbYV0nLFxuICAgICAgICBsbGwgOiAnWVlZWVtrb10gTU1NIERbYV0gSEg6bW0nLFxuICAgICAgICBsbGxsIDogJ2RkZCwgWVlZWVtrb10gTU1NIERbYV0gSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbZ2F1cl0gTFRbZXRhbl0nLFxuICAgICAgICBuZXh0RGF5IDogJ1tiaWhhcl0gTFRbZXRhbl0nLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIExUW2V0YW5dJyxcbiAgICAgICAgbGFzdERheSA6ICdbYXR6b10gTFRbZXRhbl0nLFxuICAgICAgICBsYXN0V2VlayA6ICdbYXVycmVrb10gZGRkZCBMVFtldGFuXScsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyBiYXJydScsXG4gICAgICAgIHBhc3QgOiAnZHVlbGEgJXMnLFxuICAgICAgICBzIDogJ3NlZ3VuZG8gYmF0enVrJyxcbiAgICAgICAgc3MgOiAnJWQgc2VndW5kbycsXG4gICAgICAgIG0gOiAnbWludXR1IGJhdCcsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0dScsXG4gICAgICAgIGggOiAnb3JkdSBiYXQnLFxuICAgICAgICBoaCA6ICclZCBvcmR1JyxcbiAgICAgICAgZCA6ICdlZ3VuIGJhdCcsXG4gICAgICAgIGRkIDogJyVkIGVndW4nLFxuICAgICAgICBNIDogJ2hpbGFiZXRlIGJhdCcsXG4gICAgICAgIE1NIDogJyVkIGhpbGFiZXRlJyxcbiAgICAgICAgeSA6ICd1cnRlIGJhdCcsXG4gICAgICAgIHl5IDogJyVkIHVydGUnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZXU7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2V1LmpzXG4vLyBtb2R1bGUgaWQgPSA0MVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogUGVyc2lhbiBbZmFdXG4vLyEgYXV0aG9yIDogRWJyYWhpbSBCeWFnb3dpIDogaHR0cHM6Ly9naXRodWIuY29tL2VicmFtaW5pb1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBzeW1ib2xNYXAgPSB7XG4gICAgJzEnOiAn27EnLFxuICAgICcyJzogJ9uyJyxcbiAgICAnMyc6ICfbsycsXG4gICAgJzQnOiAn27QnLFxuICAgICc1JzogJ9u1JyxcbiAgICAnNic6ICfbticsXG4gICAgJzcnOiAn27cnLFxuICAgICc4JzogJ9u4JyxcbiAgICAnOSc6ICfbuScsXG4gICAgJzAnOiAn27AnXG59O1xudmFyIG51bWJlck1hcCA9IHtcbiAgICAn27EnOiAnMScsXG4gICAgJ9uyJzogJzInLFxuICAgICfbsyc6ICczJyxcbiAgICAn27QnOiAnNCcsXG4gICAgJ9u1JzogJzUnLFxuICAgICfbtic6ICc2JyxcbiAgICAn27cnOiAnNycsXG4gICAgJ9u4JzogJzgnLFxuICAgICfbuSc6ICc5JyxcbiAgICAn27AnOiAnMCdcbn07XG5cbnZhciBmYSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2ZhJywge1xuICAgIG1vbnRocyA6ICfamNin2YbZiNuM2Ydf2YHZiNix24zZh1/Zhdin2LHYs1/YotmI2LHbjNmEX9mF2Ydf2pjZiNim2YZf2pjZiNim24zZh1/Yp9mI2Kpf2LPZvtiq2KfZhdio2LFf2Kfaqdiq2KjYsV/ZhtmI2KfZhdio2LFf2K/Ys9in2YXYqNixJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ9qY2KfZhtmI24zZh1/ZgdmI2LHbjNmHX9mF2KfYsdizX9ii2YjYsduM2YRf2YXZh1/amNmI2KbZhl/amNmI2KbbjNmHX9in2YjYql/Ys9m+2KrYp9mF2KjYsV/Yp9qp2KrYqNixX9mG2YjYp9mF2KjYsV/Yr9iz2KfZhdio2LEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn24zaqVxcdTIwMGPYtNmG2KjZh1/Yr9mI2LTZhtio2Ydf2LPZh1xcdTIwMGPYtNmG2KjZh1/ahtmH2KfYsdi02YbYqNmHX9m+2YbYrFxcdTIwMGPYtNmG2KjZh1/YrNmF2LnZh1/YtNmG2KjZhycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9uM2qlcXHUyMDBj2LTZhtio2Ydf2K/ZiNi02YbYqNmHX9iz2YdcXHUyMDBj2LTZhtio2Ydf2obZh9in2LHYtNmG2KjZh1/ZvtmG2KxcXHUyMDBj2LTZhtio2Ydf2KzZhdi52Ydf2LTZhtio2YcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn24xf2K9f2LNf2oZf2b5f2Kxf2LQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv2YLYqNmEINin2LIg2LjZh9ixfNio2LnYryDYp9iyINi42YfYsS8sXG4gICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAv2KjYudivINin2LIg2LjZh9ixLy50ZXN0KGlucHV0KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ9mC2KjZhCDYp9iyINi42YfYsSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ9io2LnYryDYp9iyINi42YfYsSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vYp9mF2LHZiNiyINiz2KfYudiqXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9mB2LHYr9inINiz2KfYudiqXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW9iz2KfYudiqXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW9iv24zYsdmI2LIg2LPYp9i52KpdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBb2b7bjNi0XSBb2LPYp9i52KpdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9iv2LEgJXMnLFxuICAgICAgICBwYXN0IDogJyVzINm+24zYtCcsXG4gICAgICAgIHMgOiAn2obZhtivINir2KfZhtuM2YcnLFxuICAgICAgICBzcyA6ICfYq9in2YbbjNmHIGQlJyxcbiAgICAgICAgbSA6ICfbjNqpINiv2YLbjNmC2YcnLFxuICAgICAgICBtbSA6ICclZCDYr9mC24zZgtmHJyxcbiAgICAgICAgaCA6ICfbjNqpINiz2KfYudiqJyxcbiAgICAgICAgaGggOiAnJWQg2LPYp9i52KonLFxuICAgICAgICBkIDogJ9uM2qkg2LHZiNiyJyxcbiAgICAgICAgZGQgOiAnJWQg2LHZiNiyJyxcbiAgICAgICAgTSA6ICfbjNqpINmF2KfZhycsXG4gICAgICAgIE1NIDogJyVkINmF2KfZhycsXG4gICAgICAgIHkgOiAn24zaqSDYs9in2YQnLFxuICAgICAgICB5eSA6ICclZCDYs9in2YQnXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vbsC3buV0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgv2IwvZywgJywnKTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwW21hdGNoXTtcbiAgICAgICAgfSkucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfdmFLyxcbiAgICBvcmRpbmFsIDogJyVk2YUnLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDEyIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGZhO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9mYS5qc1xuLy8gbW9kdWxlIGlkID0gNDJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEZpbm5pc2ggW2ZpXVxuLy8hIGF1dGhvciA6IFRhcm1vIEFpZGFudGF1c3RhIDogaHR0cHM6Ly9naXRodWIuY29tL2JsZWFkb2ZcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbnVtYmVyc1Bhc3QgPSAnbm9sbGEgeWtzaSBrYWtzaSBrb2xtZSBuZWxqw6Qgdmlpc2kga3V1c2kgc2VpdHNlbcOkbiBrYWhkZWtzYW4geWhkZWtzw6RuJy5zcGxpdCgnICcpO1xudmFyIG51bWJlcnNGdXR1cmUgPSBbXG4gICAgICAgICdub2xsYScsICd5aGRlbicsICdrYWhkZW4nLCAna29sbWVuJywgJ25lbGrDpG4nLCAndmlpZGVuJywgJ2t1dWRlbicsXG4gICAgICAgIG51bWJlcnNQYXN0WzddLCBudW1iZXJzUGFzdFs4XSwgbnVtYmVyc1Bhc3RbOV1cbiAgICBdO1xuZnVuY3Rpb24gdHJhbnNsYXRlKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciByZXN1bHQgPSAnJztcbiAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdtdXV0YW1hbiBzZWt1bm5pbicgOiAnbXV1dGFtYSBzZWt1bnRpJztcbiAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ3Nla3VubmluJyA6ICdzZWt1bnRpYSc7XG4gICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ21pbnV1dGluJyA6ICdtaW51dXR0aSc7XG4gICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgIHJlc3VsdCA9IGlzRnV0dXJlID8gJ21pbnV1dGluJyA6ICdtaW51dXR0aWEnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ3R1bm5pbicgOiAndHVudGknO1xuICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICd0dW5uaW4nIDogJ3R1bnRpYSc7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAncMOkaXbDpG4nIDogJ3DDpGl2w6QnO1xuICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICdww6RpdsOkbicgOiAncMOkaXbDpMOkJztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdrdXVrYXVkZW4nIDogJ2t1dWthdXNpJztcbiAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgcmVzdWx0ID0gaXNGdXR1cmUgPyAna3V1a2F1ZGVuJyA6ICdrdXVrYXV0dGEnO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgcmV0dXJuIGlzRnV0dXJlID8gJ3Z1b2RlbicgOiAndnVvc2knO1xuICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICByZXN1bHQgPSBpc0Z1dHVyZSA/ICd2dW9kZW4nIDogJ3Z1b3R0YSc7XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG4gICAgcmVzdWx0ID0gdmVyYmFsTnVtYmVyKG51bWJlciwgaXNGdXR1cmUpICsgJyAnICsgcmVzdWx0O1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5mdW5jdGlvbiB2ZXJiYWxOdW1iZXIobnVtYmVyLCBpc0Z1dHVyZSkge1xuICAgIHJldHVybiBudW1iZXIgPCAxMCA/IChpc0Z1dHVyZSA/IG51bWJlcnNGdXR1cmVbbnVtYmVyXSA6IG51bWJlcnNQYXN0W251bWJlcl0pIDogbnVtYmVyO1xufVxuXG52YXIgZmkgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdmaScsIHtcbiAgICBtb250aHMgOiAndGFtbWlrdXVfaGVsbWlrdXVfbWFhbGlza3V1X2h1aHRpa3V1X3RvdWtva3V1X2tlc8Oka3V1X2hlaW7DpGt1dV9lbG9rdXVfc3l5c2t1dV9sb2tha3V1X21hcnJhc2t1dV9qb3VsdWt1dScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICd0YW1taV9oZWxtaV9tYWFsaXNfaHVodGlfdG91a29fa2Vzw6RfaGVpbsOkX2Vsb19zeXlzX2xva2FfbWFycmFzX2pvdWx1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3N1bm51bnRhaV9tYWFuYW50YWlfdGlpc3RhaV9rZXNraXZpaWtrb190b3JzdGFpX3BlcmphbnRhaV9sYXVhbnRhaScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3N1X21hX3RpX2tlX3RvX3BlX2xhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ3N1X21hX3RpX2tlX3RvX3BlX2xhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISC5tbScsXG4gICAgICAgIExUUyA6ICdISC5tbS5zcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0RvIE1NTU1bdGFdIFlZWVknLFxuICAgICAgICBMTEwgOiAnRG8gTU1NTVt0YV0gWVlZWSwgW2tsb10gSEgubW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIERvIE1NTU1bdGFdIFlZWVksIFtrbG9dIEhILm1tJyxcbiAgICAgICAgbCA6ICdELk0uWVlZWScsXG4gICAgICAgIGxsIDogJ0RvIE1NTSBZWVlZJyxcbiAgICAgICAgbGxsIDogJ0RvIE1NTSBZWVlZLCBba2xvXSBISC5tbScsXG4gICAgICAgIGxsbGwgOiAnZGRkLCBEbyBNTU0gWVlZWSwgW2tsb10gSEgubW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbdMOkbsOkw6RuXSBba2xvXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW2h1b21lbm5hXSBba2xvXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2tsb10gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tlaWxlbl0gW2tsb10gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbdmlpbWVdIGRkZGRbbmFdIFtrbG9dIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIHDDpMOkc3TDpCcsXG4gICAgICAgIHBhc3QgOiAnJXMgc2l0dGVuJyxcbiAgICAgICAgcyA6IHRyYW5zbGF0ZSxcbiAgICAgICAgc3MgOiB0cmFuc2xhdGUsXG4gICAgICAgIG0gOiB0cmFuc2xhdGUsXG4gICAgICAgIG1tIDogdHJhbnNsYXRlLFxuICAgICAgICBoIDogdHJhbnNsYXRlLFxuICAgICAgICBoaCA6IHRyYW5zbGF0ZSxcbiAgICAgICAgZCA6IHRyYW5zbGF0ZSxcbiAgICAgICAgZGQgOiB0cmFuc2xhdGUsXG4gICAgICAgIE0gOiB0cmFuc2xhdGUsXG4gICAgICAgIE1NIDogdHJhbnNsYXRlLFxuICAgICAgICB5IDogdHJhbnNsYXRlLFxuICAgICAgICB5eSA6IHRyYW5zbGF0ZVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGZpO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9maS5qc1xuLy8gbW9kdWxlIGlkID0gNDNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEZhcm9lc2UgW2ZvXVxuLy8hIGF1dGhvciA6IFJhZ25hciBKb2hhbm5lc2VuIDogaHR0cHM6Ly9naXRodWIuY29tL3JhZ25hcjEyM1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBmbyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2ZvJywge1xuICAgIG1vbnRocyA6ICdqYW51YXJfZmVicnVhcl9tYXJzX2FwcsOtbF9tYWlfanVuaV9qdWxpX2F1Z3VzdF9zZXB0ZW1iZXJfb2t0b2Jlcl9ub3ZlbWJlcl9kZXNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW5fZmViX21hcl9hcHJfbWFpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2Rlcycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdzdW5udWRhZ3VyX23DoW5hZGFndXJfdMO9c2RhZ3VyX21pa3VkYWd1cl9ow7NzZGFndXJfZnLDrWdnamFkYWd1cl9sZXlnYXJkYWd1cicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3N1bl9tw6FuX3TDvXNfbWlrX2jDs3NfZnLDrV9sZXknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnc3VfbcOhX3TDvV9taV9ow7NfZnJfbGUnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRC4gTU1NTSwgWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vDjSBkYWcga2wuXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW8ONIG1vcmdpbiBrbC5dIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBba2wuXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW8ONIGdqw6FyIGtsLl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbc8Otw7BzdHVdIGRkZGQgW2tsXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICd1bSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgc8Otw7BhbmknLFxuICAgICAgICBzIDogJ2bDoSBzZWt1bmQnLFxuICAgICAgICBzcyA6ICclZCBzZWt1bmRpcicsXG4gICAgICAgIG0gOiAnZWluIG1pbnV0dCcsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0dGlyJyxcbiAgICAgICAgaCA6ICdlaW4gdMOtbWknLFxuICAgICAgICBoaCA6ICclZCB0w61tYXInLFxuICAgICAgICBkIDogJ2VpbiBkYWd1cicsXG4gICAgICAgIGRkIDogJyVkIGRhZ2FyJyxcbiAgICAgICAgTSA6ICdlaW4gbcOhbmHDsGknLFxuICAgICAgICBNTSA6ICclZCBtw6FuYcOwaXInLFxuICAgICAgICB5IDogJ2VpdHQgw6FyJyxcbiAgICAgICAgeXkgOiAnJWQgw6FyJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGZvO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9mby5qc1xuLy8gbW9kdWxlIGlkID0gNDRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEZyZW5jaCBbZnJdXG4vLyEgYXV0aG9yIDogSm9obiBGaXNjaGVyIDogaHR0cHM6Ly9naXRodWIuY29tL2pmcm9mZmljZVxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBmciA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2ZyJywge1xuICAgIG1vbnRocyA6ICdqYW52aWVyX2bDqXZyaWVyX21hcnNfYXZyaWxfbWFpX2p1aW5fanVpbGxldF9hb8O7dF9zZXB0ZW1icmVfb2N0b2JyZV9ub3ZlbWJyZV9kw6ljZW1icmUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFudi5fZsOpdnIuX21hcnNfYXZyLl9tYWlfanVpbl9qdWlsLl9hb8O7dF9zZXB0Ll9vY3QuX25vdi5fZMOpYy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnZGltYW5jaGVfbHVuZGlfbWFyZGlfbWVyY3JlZGlfamV1ZGlfdmVuZHJlZGlfc2FtZWRpJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnZGltLl9sdW4uX21hci5fbWVyLl9qZXUuX3Zlbi5fc2FtLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdkaV9sdV9tYV9tZV9qZV92ZV9zYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0F1am91cmTigJlodWkgw6BdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbRGVtYWluIMOgXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW8OgXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0hpZXIgw6BdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbZGVybmllciDDoF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnZGFucyAlcycsXG4gICAgICAgIHBhc3QgOiAnaWwgeSBhICVzJyxcbiAgICAgICAgcyA6ICdxdWVscXVlcyBzZWNvbmRlcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZGVzJyxcbiAgICAgICAgbSA6ICd1bmUgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAndW5lIGhldXJlJyxcbiAgICAgICAgaGggOiAnJWQgaGV1cmVzJyxcbiAgICAgICAgZCA6ICd1biBqb3VyJyxcbiAgICAgICAgZGQgOiAnJWQgam91cnMnLFxuICAgICAgICBNIDogJ3VuIG1vaXMnLFxuICAgICAgICBNTSA6ICclZCBtb2lzJyxcbiAgICAgICAgeSA6ICd1biBhbicsXG4gICAgICAgIHl5IDogJyVkIGFucydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShlcnwpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBSZXR1cm4gJ2UnIHdoZW4gZGF5IG9mIG1vbnRoID4gMS4gTW92ZSB0aGlzIGNhc2UgaW5zaWRlXG4gICAgICAgICAgICAvLyBibG9jayBmb3IgbWFzY3VsaW5lIHdvcmRzIGJlbG93LlxuICAgICAgICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L2lzc3Vlcy8zMzc1XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdlcicgOiAnJyk7XG5cbiAgICAgICAgICAgIC8vIFdvcmRzIHdpdGggbWFzY3VsaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogbW9pcywgdHJpbWVzdHJlLCBqb3VyXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICBjYXNlICdRJzpcbiAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdlcicgOiAnZScpO1xuXG4gICAgICAgICAgICAvLyBXb3JkcyB3aXRoIGZlbWluaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogc2VtYWluZVxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdyZScgOiAnZScpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZnI7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2ZyLmpzXG4vLyBtb2R1bGUgaWQgPSA0NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogRnJlbmNoIChDYW5hZGEpIFtmci1jYV1cbi8vISBhdXRob3IgOiBKb25hdGhhbiBBYm91cmJpaCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb25iY2FcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgZnJDYSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2ZyLWNhJywge1xuICAgIG1vbnRocyA6ICdqYW52aWVyX2bDqXZyaWVyX21hcnNfYXZyaWxfbWFpX2p1aW5fanVpbGxldF9hb8O7dF9zZXB0ZW1icmVfb2N0b2JyZV9ub3ZlbWJyZV9kw6ljZW1icmUnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFudi5fZsOpdnIuX21hcnNfYXZyLl9tYWlfanVpbl9qdWlsLl9hb8O7dF9zZXB0Ll9vY3QuX25vdi5fZMOpYy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnZGltYW5jaGVfbHVuZGlfbWFyZGlfbWVyY3JlZGlfamV1ZGlfdmVuZHJlZGlfc2FtZWRpJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnZGltLl9sdW4uX21hci5fbWVyLl9qZXUuX3Zlbi5fc2FtLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdkaV9sdV9tYV9tZV9qZV92ZV9zYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0F1am91cmTigJlodWkgw6BdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbRGVtYWluIMOgXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW8OgXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0hpZXIgw6BdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbZGVybmllciDDoF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnZGFucyAlcycsXG4gICAgICAgIHBhc3QgOiAnaWwgeSBhICVzJyxcbiAgICAgICAgcyA6ICdxdWVscXVlcyBzZWNvbmRlcycsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZGVzJyxcbiAgICAgICAgbSA6ICd1bmUgbWludXRlJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcycsXG4gICAgICAgIGggOiAndW5lIGhldXJlJyxcbiAgICAgICAgaGggOiAnJWQgaGV1cmVzJyxcbiAgICAgICAgZCA6ICd1biBqb3VyJyxcbiAgICAgICAgZGQgOiAnJWQgam91cnMnLFxuICAgICAgICBNIDogJ3VuIG1vaXMnLFxuICAgICAgICBNTSA6ICclZCBtb2lzJyxcbiAgICAgICAgeSA6ICd1biBhbicsXG4gICAgICAgIHl5IDogJyVkIGFucydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShlcnxlKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgLy8gV29yZHMgd2l0aCBtYXNjdWxpbmUgZ3JhbW1hdGljYWwgZ2VuZGVyOiBtb2lzLCB0cmltZXN0cmUsIGpvdXJcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIGNhc2UgJ1EnOlxuICAgICAgICAgICAgY2FzZSAnRCc6XG4gICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChudW1iZXIgPT09IDEgPyAnZXInIDogJ2UnKTtcblxuICAgICAgICAgICAgLy8gV29yZHMgd2l0aCBmZW1pbmluZSBncmFtbWF0aWNhbCBnZW5kZXI6IHNlbWFpbmVcbiAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArIChudW1iZXIgPT09IDEgPyAncmUnIDogJ2UnKTtcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZnJDYTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvZnItY2EuanNcbi8vIG1vZHVsZSBpZCA9IDQ2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBGcmVuY2ggKFN3aXR6ZXJsYW5kKSBbZnItY2hdXG4vLyEgYXV0aG9yIDogR2FzcGFyZCBCdWNoZXIgOiBodHRwczovL2dpdGh1Yi5jb20vZ2FzcGFyZFxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBmckNoID0gbW9tZW50LmRlZmluZUxvY2FsZSgnZnItY2gnLCB7XG4gICAgbW9udGhzIDogJ2phbnZpZXJfZsOpdnJpZXJfbWFyc19hdnJpbF9tYWlfanVpbl9qdWlsbGV0X2Fvw7t0X3NlcHRlbWJyZV9vY3RvYnJlX25vdmVtYnJlX2TDqWNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW52Ll9mw6l2ci5fbWFyc19hdnIuX21haV9qdWluX2p1aWwuX2Fvw7t0X3NlcHQuX29jdC5fbm92Ll9kw6ljLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdkaW1hbmNoZV9sdW5kaV9tYXJkaV9tZXJjcmVkaV9qZXVkaV92ZW5kcmVkaV9zYW1lZGknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdkaW0uX2x1bi5fbWFyLl9tZXIuX2pldS5fdmVuLl9zYW0uJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2RpX2x1X21hX21lX2plX3ZlX3NhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbQXVqb3VyZOKAmWh1aSDDoF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tEZW1haW4gw6BdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbw6BdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbSGllciDDoF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtkZXJuaWVyIMOgXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkYW5zICVzJyxcbiAgICAgICAgcGFzdCA6ICdpbCB5IGEgJXMnLFxuICAgICAgICBzIDogJ3F1ZWxxdWVzIHNlY29uZGVzJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kZXMnLFxuICAgICAgICBtIDogJ3VuZSBtaW51dGUnLFxuICAgICAgICBtbSA6ICclZCBtaW51dGVzJyxcbiAgICAgICAgaCA6ICd1bmUgaGV1cmUnLFxuICAgICAgICBoaCA6ICclZCBoZXVyZXMnLFxuICAgICAgICBkIDogJ3VuIGpvdXInLFxuICAgICAgICBkZCA6ICclZCBqb3VycycsXG4gICAgICAgIE0gOiAndW4gbW9pcycsXG4gICAgICAgIE1NIDogJyVkIG1vaXMnLFxuICAgICAgICB5IDogJ3VuIGFuJyxcbiAgICAgICAgeXkgOiAnJWQgYW5zJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KGVyfGUpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAvLyBXb3JkcyB3aXRoIG1hc2N1bGluZSBncmFtbWF0aWNhbCBnZW5kZXI6IG1vaXMsIHRyaW1lc3RyZSwgam91clxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgY2FzZSAnUSc6XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdlcicgOiAnZScpO1xuXG4gICAgICAgICAgICAvLyBXb3JkcyB3aXRoIGZlbWluaW5lIGdyYW1tYXRpY2FsIGdlbmRlcjogc2VtYWluZVxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgKG51bWJlciA9PT0gMSA/ICdyZScgOiAnZScpO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZnJDaDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvZnItY2guanNcbi8vIG1vZHVsZSBpZCA9IDQ3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBGcmlzaWFuIFtmeV1cbi8vISBhdXRob3IgOiBSb2JpbiB2YW4gZGVyIFZsaWV0IDogaHR0cHM6Ly9naXRodWIuY29tL3JvYmluMHZhbjBkZXIwdlxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBtb250aHNTaG9ydFdpdGhEb3RzID0gJ2phbi5fZmViLl9tcnQuX2Fwci5fbWFpX2p1bi5fanVsLl9hdWcuX3NlcC5fb2t0Ll9ub3YuX2Rlcy4nLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnRXaXRob3V0RG90cyA9ICdqYW5fZmViX21ydF9hcHJfbWFpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2Rlcycuc3BsaXQoJ18nKTtcblxudmFyIGZ5ID0gbW9tZW50LmRlZmluZUxvY2FsZSgnZnknLCB7XG4gICAgbW9udGhzIDogJ2phbm5ld2FyaXNfZmVicmV3YXJpc19tYWFydF9hcHJpbF9tYWFpZV9qdW55X2p1bHlfYXVndXN0dXNfc2VwdGltYmVyX29rdG9iZXJfbm92aW1iZXJfZGVzaW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiBmdW5jdGlvbiAobSwgZm9ybWF0KSB7XG4gICAgICAgIGlmICghbSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHM7XG4gICAgICAgIH0gZWxzZSBpZiAoLy1NTU0tLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhvdXREb3RzW20ubW9udGgoKV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRoRG90c1ttLm1vbnRoKCldO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdzbmVpbl9tb2FuZGVpX3RpaXNkZWlfd29hbnNkZWlfdG9uZ2Vyc2RlaV9mcmVlZF9zbmVvbicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3NpLl9tby5fdGkuX3dvLl90by5fZnIuX3NvLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTaV9Nb19UaV9Xb19Ub19Gcl9Tbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQtTU0tWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbaGpvZWQgb21dIExUJyxcbiAgICAgICAgbmV4dERheTogJ1ttb2FybiBvbV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW29tXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbanVzdGVyIG9tXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW8O0ZnLDu25lXSBkZGRkIFtvbV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdvZXIgJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGx5bicsXG4gICAgICAgIHMgOiAnaW4gcGVhciBzZWtvbmRlbicsXG4gICAgICAgIHNzIDogJyVkIHNla29uZGVuJyxcbiAgICAgICAgbSA6ICdpZW4gbWluw7p0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlbicsXG4gICAgICAgIGggOiAnaWVuIG9lcmUnLFxuICAgICAgICBoaCA6ICclZCBvZXJlbicsXG4gICAgICAgIGQgOiAnaWVuIGRlaScsXG4gICAgICAgIGRkIDogJyVkIGRhZ2VuJyxcbiAgICAgICAgTSA6ICdpZW4gbW9hbm5lJyxcbiAgICAgICAgTU0gOiAnJWQgbW9hbm5lbicsXG4gICAgICAgIHkgOiAnaWVuIGppZXInLFxuICAgICAgICB5eSA6ICclZCBqaWVycmVuJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KHN0ZXxkZSkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAoKG51bWJlciA9PT0gMSB8fCBudW1iZXIgPT09IDggfHwgbnVtYmVyID49IDIwKSA/ICdzdGUnIDogJ2RlJyk7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZnk7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2Z5LmpzXG4vLyBtb2R1bGUgaWQgPSA0OFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU2NvdHRpc2ggR2FlbGljIFtnZF1cbi8vISBhdXRob3IgOiBKb24gQXNoZG93biA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb25hc2hkb3duXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIG1vbnRocyA9IFtcbiAgICAnQW0gRmFvaWxsZWFjaCcsICdBbiBHZWFycmFuJywgJ0FtIE3DoHJ0JywgJ0FuIEdpYmxlYW4nLCAnQW4gQ8OoaXRlYW4nLCAnQW4gdC3DkmdtaGlvcycsICdBbiB0LUl1Y2hhcicsICdBbiBMw7luYXN0YWwnLCAnQW4gdC1TdWx0YWluJywgJ0FuIETDoG1oYWlyJywgJ0FuIHQtU2FtaGFpbicsICdBbiBEw7liaGxhY2hkJ1xuXTtcblxudmFyIG1vbnRoc1Nob3J0ID0gWydGYW9pJywgJ0dlYXInLCAnTcOgcnQnLCAnR2libCcsICdDw6hpdCcsICfDkmdtaCcsICdJdWNoJywgJ0zDuW4nLCAnU3VsdCcsICdEw6BtaCcsICdTYW1oJywgJ0TDuWJoJ107XG5cbnZhciB3ZWVrZGF5cyA9IFsnRGlkw7JtaG5haWNoJywgJ0RpbHVhaW4nLCAnRGltw6BpcnQnLCAnRGljaWFkYWluJywgJ0RpYXJkYW9pbicsICdEaWhhb2luZScsICdEaXNhdGhhaXJuZSddO1xuXG52YXIgd2Vla2RheXNTaG9ydCA9IFsnRGlkJywgJ0RpbCcsICdEaW0nLCAnRGljJywgJ0RpYScsICdEaWgnLCAnRGlzJ107XG5cbnZhciB3ZWVrZGF5c01pbiA9IFsnRMOyJywgJ0x1JywgJ03DoCcsICdDaScsICdBcicsICdIYScsICdTYSddO1xuXG52YXIgZ2QgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdnZCcsIHtcbiAgICBtb250aHMgOiBtb250aHMsXG4gICAgbW9udGhzU2hvcnQgOiBtb250aHNTaG9ydCxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6IHdlZWtkYXlzLFxuICAgIHdlZWtkYXlzU2hvcnQgOiB3ZWVrZGF5c1Nob3J0LFxuICAgIHdlZWtkYXlzTWluIDogd2Vla2RheXNNaW4sXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0FuLWRpdWdoIGFpZ10gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tBLW3DoGlyZWFjaCBhaWddIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbYWlnXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0FuLWTDqCBhaWddIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbc2VvIGNoYWlkaF0gW2FpZ10gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnYW5uIGFuICVzJyxcbiAgICAgICAgcGFzdCA6ICdiaG8gY2hpb25uICVzJyxcbiAgICAgICAgcyA6ICdiZWFnYW4gZGlvZ2FuJyxcbiAgICAgICAgc3MgOiAnJWQgZGlvZ2FuJyxcbiAgICAgICAgbSA6ICdtaW9uYWlkJyxcbiAgICAgICAgbW0gOiAnJWQgbWlvbmFpZGVhbicsXG4gICAgICAgIGggOiAndWFpcicsXG4gICAgICAgIGhoIDogJyVkIHVhaXJlYW4nLFxuICAgICAgICBkIDogJ2xhdGhhJyxcbiAgICAgICAgZGQgOiAnJWQgbGF0aGEnLFxuICAgICAgICBNIDogJ23DrG9zJyxcbiAgICAgICAgTU0gOiAnJWQgbcOsb3NhbicsXG4gICAgICAgIHkgOiAnYmxpYWRobmEnLFxuICAgICAgICB5eSA6ICclZCBibGlhZGhuYSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn0oZHxuYXxtaCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBvdXRwdXQgPSBudW1iZXIgPT09IDEgPyAnZCcgOiBudW1iZXIgJSAxMCA9PT0gMiA/ICduYScgOiAnbWgnO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGdkO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9nZC5qc1xuLy8gbW9kdWxlIGlkID0gNDlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEdhbGljaWFuIFtnbF1cbi8vISBhdXRob3IgOiBKdWFuIEcuIEh1cnRhZG8gOiBodHRwczovL2dpdGh1Yi5jb20vanVhbmdodXJ0YWRvXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGdsID0gbW9tZW50LmRlZmluZUxvY2FsZSgnZ2wnLCB7XG4gICAgbW9udGhzIDogJ3hhbmVpcm9fZmVicmVpcm9fbWFyem9fYWJyaWxfbWFpb194dcOxb194dWxsb19hZ29zdG9fc2V0ZW1icm9fb3V0dWJyb19ub3ZlbWJyb19kZWNlbWJybycuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICd4YW4uX2ZlYi5fbWFyLl9hYnIuX21haS5feHXDsS5feHVsLl9hZ28uX3NldC5fb3V0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdkb21pbmdvX2x1bnNfbWFydGVzX23DqXJjb3Jlc194b3Zlc192ZW5yZXNfc8OhYmFkbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ2RvbS5fbHVuLl9tYXIuX23DqXIuX3hvdi5fdmVuLl9zw6FiLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdkb19sdV9tYV9tw6lfeG9fdmVfc8OhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBbZGVdIE1NTU0gW2RlXSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAnW2hveGUgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICfDoXMnIDogJ8OhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHREYXkgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ1ttYcOxw6EgJyArICgodGhpcy5ob3VycygpICE9PSAxKSA/ICfDoXMnIDogJ8OhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHRXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdkZGRkIFsnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ8OhcycgOiAnYScpICsgJ10gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbb250ZSAnICsgKCh0aGlzLmhvdXJzKCkgIT09IDEpID8gJ8OhJyA6ICdhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdbb10gZGRkZCBbcGFzYWRvICcgKyAoKHRoaXMuaG91cnMoKSAhPT0gMSkgPyAnw6FzJyA6ICdhJykgKyAnXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6IGZ1bmN0aW9uIChzdHIpIHtcbiAgICAgICAgICAgIGlmIChzdHIuaW5kZXhPZigndW4nKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnbicgKyBzdHI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gJ2VuICcgKyBzdHI7XG4gICAgICAgIH0sXG4gICAgICAgIHBhc3QgOiAnaGFpICVzJyxcbiAgICAgICAgcyA6ICd1bnMgc2VndW5kb3MnLFxuICAgICAgICBzcyA6ICclZCBzZWd1bmRvcycsXG4gICAgICAgIG0gOiAndW4gbWludXRvJyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRvcycsXG4gICAgICAgIGggOiAndW5oYSBob3JhJyxcbiAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICBkIDogJ3VuIGTDrWEnLFxuICAgICAgICBkZCA6ICclZCBkw61hcycsXG4gICAgICAgIE0gOiAndW4gbWVzJyxcbiAgICAgICAgTU0gOiAnJWQgbWVzZXMnLFxuICAgICAgICB5IDogJ3VuIGFubycsXG4gICAgICAgIHl5IDogJyVkIGFub3MnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9wrovLFxuICAgIG9yZGluYWwgOiAnJWTCuicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGdsO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9nbC5qc1xuLy8gbW9kdWxlIGlkID0gNTBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEtvbmthbmkgTGF0aW4gc2NyaXB0IFtnb20tbGF0bl1cbi8vISBhdXRob3IgOiBUaGUgRGlzY292ZXJlciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9XaWtpRGlzY292ZXJlclxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbmZ1bmN0aW9uIHByb2Nlc3NSZWxhdGl2ZVRpbWUobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ3MnOiBbJ3Rob2RkZSBzZWNvbmRhbmltJywgJ3Rob2RkZSBzZWNvbmQnXSxcbiAgICAgICAgJ3NzJzogW251bWJlciArICcgc2Vjb25kYW5pbScsIG51bWJlciArICcgc2Vjb25kJ10sXG4gICAgICAgICdtJzogWydla2EgbWludGFuJywgJ2VrIG1pbnV0ZSddLFxuICAgICAgICAnbW0nOiBbbnVtYmVyICsgJyBtaW50YW5pbScsIG51bWJlciArICcgbWludGFtJ10sXG4gICAgICAgICdoJzogWydla2EgaG9yYW4nLCAnZWsgaG9yJ10sXG4gICAgICAgICdoaCc6IFtudW1iZXIgKyAnIGhvcmFuaW0nLCBudW1iZXIgKyAnIGhvciddLFxuICAgICAgICAnZCc6IFsnZWthIGRpc2FuJywgJ2VrIGRpcyddLFxuICAgICAgICAnZGQnOiBbbnVtYmVyICsgJyBkaXNhbmltJywgbnVtYmVyICsgJyBkaXMnXSxcbiAgICAgICAgJ00nOiBbJ2VrYSBtaG9pbmVhbicsICdlayBtaG9pbm8nXSxcbiAgICAgICAgJ01NJzogW251bWJlciArICcgbWhvaW5lYW5pbScsIG51bWJlciArICcgbWhvaW5lJ10sXG4gICAgICAgICd5JzogWydla2Egdm9yc2FuJywgJ2VrIHZvcm9zJ10sXG4gICAgICAgICd5eSc6IFtudW1iZXIgKyAnIHZvcnNhbmltJywgbnVtYmVyICsgJyB2b3JzYW0nXVxuICAgIH07XG4gICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xufVxuXG52YXIgZ29tTGF0biA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2dvbS1sYXRuJywge1xuICAgIG1vbnRocyA6ICdKYW5lcl9GZWJyZXJfTWFyc19BYnJpbF9NYWlfSnVuX0p1bGFpX0Fnb3N0X1NldGVtYnJfT3R1YnJfTm92ZW1icl9EZXplbWJyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbi5fRmViLl9NYXJzX0Fici5fTWFpX0p1bl9KdWwuX0Fnby5fU2V0Ll9PdHUuX05vdi5fRGV6Licuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdBaXRhcl9Tb21hcl9Nb25nbGxhcl9CdWR2YXJfQnJlc3Rhcl9TdWtyYXJfU29uXFwndmFyJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnQWl0Ll9Tb20uX01vbi5fQnVkLl9CcmUuX1N1ay5fU29uLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdBaV9TbV9Nb19CdV9Ccl9TdV9Tbicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0gW3ZhenRhXScsXG4gICAgICAgIExUUyA6ICdBIGg6bW06c3MgW3ZhenRhXScsXG4gICAgICAgIEwgOiAnREQtTU0tWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEEgaDptbSBbdmF6dGFdJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBNTU1NW2FjaGVhXSBEbywgWVlZWSwgQSBoOm1tIFt2YXp0YV0nLFxuICAgICAgICBsbGxsOiAnZGRkLCBEIE1NTSBZWVlZLCBBIGg6bW0gW3ZhenRhXSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW0Fpel0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW0ZhbGVhbV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ1tJZXRhIHRvXSBkZGRkWyxdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tLYWxdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbRmF0bG9dIGRkZGRbLF0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcycsXG4gICAgICAgIHBhc3QgOiAnJXMgYWRpbScsXG4gICAgICAgIHMgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBzcyA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIG0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBtbSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIGggOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBoaCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBkZCA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIE0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBNTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICB5eSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn0oZXIpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICAvLyB0aGUgb3JkaW5hbCAnZXInIG9ubHkgYXBwbGllcyB0byBkYXkgb2YgdGhlIG1vbnRoXG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ2VyJztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIGNhc2UgJ1EnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL3JhdGl8c29rYWxsaXxkb25wYXJhbXxzYW5qZS8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAncmF0aScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzb2thbGxpJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdkb25wYXJhbScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID4gMTIgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc2FuamUnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ3JhdGknO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICdzb2thbGxpJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTYpIHtcbiAgICAgICAgICAgIHJldHVybiAnZG9ucGFyYW0nO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICdzYW5qZSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ3JhdGknO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cbnJldHVybiBnb21MYXRuO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9nb20tbGF0bi5qc1xuLy8gbW9kdWxlIGlkID0gNTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEd1amFyYXRpIFtndV1cbi8vISBhdXRob3IgOiBLYXVzaGlrIFRoYW5raSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9LYXVzaGlrMTk4N1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBzeW1ib2xNYXAgPSB7XG4gICAgICAgICcxJzogJ+CrpycsXG4gICAgICAgICcyJzogJ+CrqCcsXG4gICAgICAgICczJzogJ+CrqScsXG4gICAgICAgICc0JzogJ+CrqicsXG4gICAgICAgICc1JzogJ+CrqycsXG4gICAgICAgICc2JzogJ+CrrCcsXG4gICAgICAgICc3JzogJ+CrrScsXG4gICAgICAgICc4JzogJ+CrricsXG4gICAgICAgICc5JzogJ+CrrycsXG4gICAgICAgICcwJzogJ+CrpidcbiAgICB9O1xudmFyIG51bWJlck1hcCA9IHtcbiAgICAgICAgJ+Crpyc6ICcxJyxcbiAgICAgICAgJ+CrqCc6ICcyJyxcbiAgICAgICAgJ+CrqSc6ICczJyxcbiAgICAgICAgJ+Crqic6ICc0JyxcbiAgICAgICAgJ+Crqyc6ICc1JyxcbiAgICAgICAgJ+CrrCc6ICc2JyxcbiAgICAgICAgJ+CrrSc6ICc3JyxcbiAgICAgICAgJ+Crric6ICc4JyxcbiAgICAgICAgJ+Crryc6ICc5JyxcbiAgICAgICAgJ+Crpic6ICcwJ1xuICAgIH07XG5cbnZhciBndSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2d1Jywge1xuICAgIG1vbnRoczogJ+CqnOCqvuCqqOCrjeCqr+CrgeCqhuCqsOCrgF/gqqvgq4fgqqzgq43gqrDgq4HgqobgqrDgq4Bf4Kqu4Kq+4Kqw4KuN4KqaX+Cqj+CqquCrjeCqsOCqv+Cqsl/gqq7gq4df4Kqc4KuC4KqoX+CqnOCrgeCqsuCqvuCqiF/gqpHgqpfgqrjgq43gqp9f4Kq44Kqq4KuN4Kqf4KuH4Kqu4KuN4Kqs4KqwX+CqkeCqleCrjeCqn+CrjeCqrOCqsF/gqqjgqrXgq4fgqq7gq43gqqzgqrBf4Kqh4Kq/4Kq44KuH4Kqu4KuN4Kqs4KqwJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAn4Kqc4Kq+4Kqo4KuN4Kqv4KuBLl/gqqvgq4fgqqzgq43gqrDgq4EuX+CqruCqvuCqsOCrjeCqml/gqo/gqqrgq43gqrDgqr8uX+CqruCrh1/gqpzgq4Lgqqhf4Kqc4KuB4Kqy4Kq+Ll/gqpHgqpcuX+CquOCqquCrjeCqn+Crhy5f4KqR4KqV4KuN4Kqf4KuNLl/gqqjgqrXgq4cuX+CqoeCqv+CquOCrhy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5czogJ+CqsOCqteCqv+CqteCqvuCqsF/gqrjgq4vgqq7gqrXgqr7gqrBf4Kqu4KqC4KqX4Kqz4Kq14Kq+4KqwX+CqrOCrgeCqp+CrjeCqteCqvuCqsF/gqpfgq4HgqrDgq4HgqrXgqr7gqrBf4Kq24KuB4KqV4KuN4Kqw4Kq14Kq+4KqwX+CqtuCqqOCqv+CqteCqvuCqsCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0OiAn4Kqw4Kq14Kq/X+CquOCri+Cqrl/gqq7gqoLgqpfgqrNf4Kqs4KuB4Kqn4KuNX+Cql+CrgeCqsOCrgV/gqrbgq4HgqpXgq43gqrBf4Kq24Kqo4Kq/Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluOiAn4KqwX+CquOCri1/gqq7gqoJf4Kqs4KuBX+Cql+CrgV/gqrbgq4Ff4Kq2Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgIExUOiAnQSBoOm1tIOCqteCqvuCql+CrjeCqr+CrhycsXG4gICAgICAgIExUUzogJ0EgaDptbTpzcyDgqrXgqr7gqpfgq43gqq/gq4cnLFxuICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCqteCqvuCql+CrjeCqr+CrhycsXG4gICAgICAgIExMTEw6ICdkZGRkLCBEIE1NTU0gWVlZWSwgQSBoOm1tIOCqteCqvuCql+CrjeCqr+CrhydcbiAgICB9LFxuICAgIGNhbGVuZGFyOiB7XG4gICAgICAgIHNhbWVEYXk6ICdb4KqG4KqcXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb4KqV4Kq+4Kqy4KuHXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCwgTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW+Cql+Cqh+CqleCqvuCqsuCrh10gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ1vgqqrgqr7gqpvgqrLgqr5dIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgIGZ1dHVyZTogJyVzIOCqruCqvicsXG4gICAgICAgIHBhc3Q6ICclcyDgqqrgq4fgqrngqrLgqr4nLFxuICAgICAgICBzOiAn4KqF4Kqu4KuB4KqVIOCqquCqs+CriycsXG4gICAgICAgIHNzOiAnJWQg4Kq44KuH4KqV4KqC4KqhJyxcbiAgICAgICAgbTogJ+Cqj+CqlSDgqq7gqr/gqqjgqr/gqp8nLFxuICAgICAgICBtbTogJyVkIOCqruCqv+CqqOCqv+CqnycsXG4gICAgICAgIGg6ICfgqo/gqpUg4KqV4Kqy4Kq+4KqVJyxcbiAgICAgICAgaGg6ICclZCDgqpXgqrLgqr7gqpUnLFxuICAgICAgICBkOiAn4KqP4KqVIOCqpuCqv+CqteCquCcsXG4gICAgICAgIGRkOiAnJWQg4Kqm4Kq/4Kq14Kq4JyxcbiAgICAgICAgTTogJ+Cqj+CqlSDgqq7gqrngqr/gqqjgq4snLFxuICAgICAgICBNTTogJyVkIOCqruCqueCqv+CqqOCriycsXG4gICAgICAgIHk6ICfgqo/gqpUg4Kq14Kqw4KuN4Kq3JyxcbiAgICAgICAgeXk6ICclZCDgqrXgqrDgq43gqrcnXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgq6fgq6jgq6ngq6rgq6vgq6zgq63gq67gq6/gq6ZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXBbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIC8vIEd1amFyYXRpIG5vdGF0aW9uIGZvciBtZXJpZGllbXMgYXJlIHF1aXRlIGZ1enp5IGluIHByYWN0aWNlLiBXaGlsZSB0aGVyZSBleGlzdHNcbiAgICAvLyBhIHJpZ2lkIG5vdGlvbiBvZiBhICdQYWhhcicgaXQgaXMgbm90IHVzZWQgYXMgcmlnaWRseSBpbiBtb2Rlcm4gR3VqYXJhdGkuXG4gICAgbWVyaWRpZW1QYXJzZTogL+CqsOCqvuCqpHzgqqzgqqrgq4vgqrB84Kq44Kq14Kq+4KqwfOCquOCqvuCqguCqnC8sXG4gICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgqrDgqr7gqqQnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA8IDQgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4Kq44Kq14Kq+4KqwJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqqzgqqrgq4vgqrAnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqrjgqr7gqoLgqpwnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbTogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kqw4Kq+4KqkJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kq44Kq14Kq+4KqwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kqs4Kqq4KuL4KqwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kq44Kq+4KqC4KqcJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kqw4Kq+4KqkJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgd2Vlazoge1xuICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3k6IDYgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gZ3U7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2d1LmpzXG4vLyBtb2R1bGUgaWQgPSA1MlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogSGVicmV3IFtoZV1cbi8vISBhdXRob3IgOiBUb21lciBDb2hlbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS90b21lclxuLy8hIGF1dGhvciA6IE1vc2hlIFNpbWFudG92IDogaHR0cHM6Ly9naXRodWIuY29tL0RldmVsb3BtZW50SUxcbi8vISBhdXRob3IgOiBUYWwgQXRlciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9UYWxBdGVyXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGhlID0gbW9tZW50LmRlZmluZUxvY2FsZSgnaGUnLCB7XG4gICAgbW9udGhzIDogJ9eZ16DXldeQ16hf16TXkdeo15XXkNeoX9ee16jXpV/XkNek16jXmdecX9ee15DXmV/XmdeV16DXmV/XmdeV15zXmV/XkNeV15LXldeh15hf16HXpNeY157XkdeoX9eQ15XXp9eY15XXkdeoX9eg15XXkdee15HXqF/Xk9em157XkdeoJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ9eZ16DXldezX9ek15HXqNezX9ee16jXpV/XkNek16jXs1/XnteQ15lf15nXldeg15lf15nXldec15lf15DXldeS17Nf16HXpNeY17Nf15DXlden17Nf16DXldeR17Nf15PXptee17MnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn16jXkNep15XXn1/Xqdeg15lf16nXnNeZ16nXmV/XqNeR15nXoteZX9eX157Xmdep15lf16nXmdep15lf16nXkdeqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn15DXs1/XkdezX9eS17Nf15PXs1/XlNezX9eV17Nf16nXsycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfXkF/XkV/Xkl/Xk1/XlF/XlV/XqScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIFvXkV1NTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBb15FdTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIFvXkV1NTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBsIDogJ0QvTS9ZWVlZJyxcbiAgICAgICAgbGwgOiAnRCBNTU0gWVlZWScsXG4gICAgICAgIGxsbCA6ICdEIE1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgbGxsbCA6ICdkZGQsIEQgTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb15TXmdeV150g15HWvl1MVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9ee15fXqCDXkda+XUxUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb15HXqdei15RdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb15DXqtee15XXnCDXkda+XUxUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW9eR15nXldedXSBkZGRkIFvXlNeQ15fXqNeV158g15HXqdei15RdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ9eR16LXldeTICVzJyxcbiAgICAgICAgcGFzdCA6ICfXnNek16DXmSAlcycsXG4gICAgICAgIHMgOiAn157Xodek16gg16nXoNeZ15XXqicsXG4gICAgICAgIHNzIDogJyVkINep16DXmdeV16onLFxuICAgICAgICBtIDogJ9eT16fXlCcsXG4gICAgICAgIG1tIDogJyVkINeT16fXldeqJyxcbiAgICAgICAgaCA6ICfXqdei15QnLFxuICAgICAgICBoaCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ9ep16LXqteZ15nXnSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXqdei15XXqic7XG4gICAgICAgIH0sXG4gICAgICAgIGQgOiAn15nXldedJyxcbiAgICAgICAgZGQgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfXmdeV157XmdeZ150nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcg15nXnteZ150nO1xuICAgICAgICB9LFxuICAgICAgICBNIDogJ9eX15XXk9epJyxcbiAgICAgICAgTU0gOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICfXl9eV15PXqdeZ15nXnSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXl9eV15PXqdeZ150nO1xuICAgICAgICB9LFxuICAgICAgICB5IDogJ9ep16DXlCcsXG4gICAgICAgIHl5IDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgIHJldHVybiAn16nXoNeq15nXmdedJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyICUgMTAgPT09IDAgJiYgbnVtYmVyICE9PSAxMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnINep16DXlCc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyDXqdeg15nXnSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/XkNeX15RcItemfNec16TXoNeUXCLXpnzXkNeX16jXmSDXlNem15TXqNeZ15nXnXzXnNek16DXmSDXlNem15TXqNeZ15nXnXzXnNek16DXldeqINeR15XXp9eofNeR15HXlden16h815HXoteo15EvaSxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXijXkNeX15RcItemfNeQ15fXqNeZINeU16bXlNeo15nXmdedfNeR16LXqNeRKSQvLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNSkge1xuICAgICAgICAgICAgcmV0dXJuICfXnNek16DXldeqINeR15XXp9eoJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgIHJldHVybiAn15HXkdeV16fXqCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICfXnNek16DXlFwi16YnIDogJ9ec16TXoNeZINeU16bXlNeo15nXmdedJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTgpIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ9eQ15fXlFwi16YnIDogJ9eQ15fXqNeZINeU16bXlNeo15nXmdedJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn15HXoteo15EnO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cbnJldHVybiBoZTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvaGUuanNcbi8vIG1vZHVsZSBpZCA9IDUzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBIaW5kaSBbaGldXG4vLyEgYXV0aG9yIDogTWF5YW5rIFNpbmdoYWwgOiBodHRwczovL2dpdGh1Yi5jb20vbWF5YW5rc2luZ2hhbFxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBzeW1ib2xNYXAgPSB7XG4gICAgJzEnOiAn4KWnJyxcbiAgICAnMic6ICfgpagnLFxuICAgICczJzogJ+ClqScsXG4gICAgJzQnOiAn4KWqJyxcbiAgICAnNSc6ICfgpasnLFxuICAgICc2JzogJ+ClrCcsXG4gICAgJzcnOiAn4KWtJyxcbiAgICAnOCc6ICfgpa4nLFxuICAgICc5JzogJ+ClrycsXG4gICAgJzAnOiAn4KWmJ1xufTtcbnZhciBudW1iZXJNYXAgPSB7XG4gICAgJ+Clpyc6ICcxJyxcbiAgICAn4KWoJzogJzInLFxuICAgICfgpaknOiAnMycsXG4gICAgJ+Clqic6ICc0JyxcbiAgICAn4KWrJzogJzUnLFxuICAgICfgpawnOiAnNicsXG4gICAgJ+ClrSc6ICc3JyxcbiAgICAn4KWuJzogJzgnLFxuICAgICfgpa8nOiAnOScsXG4gICAgJ+Clpic6ICcwJ1xufTtcblxudmFyIGhpID0gbW9tZW50LmRlZmluZUxvY2FsZSgnaGknLCB7XG4gICAgbW9udGhzIDogJ+CknOCkqOCkteCksOClgF/gpKvgpLzgpLDgpLXgpLDgpYBf4KSu4KS+4KSw4KWN4KSaX+CkheCkquCljeCksOCliOCksl/gpK7gpIhf4KSc4KWC4KSoX+CknOClgeCksuCkvuCkiF/gpIXgpJfgpLjgpY3gpKRf4KS44KS/4KSk4KSu4KWN4KSs4KSwX+CkheCkleCljeCkn+ClguCkrOCksF/gpKjgpLXgpK7gpY3gpKzgpLBf4KSm4KS/4KS44KSu4KWN4KSs4KSwJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ+CknOCkqC5f4KSr4KS84KSwLl/gpK7gpL7gpLDgpY3gpJpf4KSF4KSq4KWN4KSw4KWILl/gpK7gpIhf4KSc4KWC4KSoX+CknOClgeCksi5f4KSF4KSXLl/gpLjgpL/gpKQuX+CkheCkleCljeCkn+Clgi5f4KSo4KS1Ll/gpKbgpL/gpLguJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgd2Vla2RheXMgOiAn4KSw4KS14KS/4KS14KS+4KSwX+CkuOCli+CkruCkteCkvuCksF/gpK7gpILgpJfgpLLgpLXgpL7gpLBf4KSs4KWB4KSn4KS14KS+4KSwX+Ckl+ClgeCksOClguCkteCkvuCksF/gpLbgpYHgpJXgpY3gpLDgpLXgpL7gpLBf4KS24KSo4KS/4KS14KS+4KSwJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4KSw4KS14KS/X+CkuOCli+Ckrl/gpK7gpILgpJfgpLJf4KSs4KWB4KSnX+Ckl+ClgeCksOClgl/gpLbgpYHgpJXgpY3gpLBf4KS24KSo4KS/Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+CksF/gpLjgpYtf4KSu4KSCX+CkrOClgV/gpJfgpYFf4KS24KWBX+Ckticuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnQSBoOm1tIOCkrOCknOClhycsXG4gICAgICAgIExUUyA6ICdBIGg6bW06c3Mg4KSs4KSc4KWHJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEEgaDptbSDgpKzgpJzgpYcnLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0g4KSs4KSc4KWHJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+CkhuCknF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vgpJXgpLJdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCwgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vgpJXgpLJdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+CkquCkv+Ckm+CksuClh10gZGRkZCwgTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMg4KSu4KWH4KSCJyxcbiAgICAgICAgcGFzdCA6ICclcyDgpKrgpLngpLLgpYcnLFxuICAgICAgICBzIDogJ+CkleClgeCkmyDgpLngpYAg4KSV4KWN4KS34KSjJyxcbiAgICAgICAgc3MgOiAnJWQg4KS44KWH4KSV4KSC4KShJyxcbiAgICAgICAgbSA6ICfgpI/gpJUg4KSu4KS/4KSo4KSfJyxcbiAgICAgICAgbW0gOiAnJWQg4KSu4KS/4KSo4KSfJyxcbiAgICAgICAgaCA6ICfgpI/gpJUg4KSY4KSC4KSf4KS+JyxcbiAgICAgICAgaGggOiAnJWQg4KSY4KSC4KSf4KWHJyxcbiAgICAgICAgZCA6ICfgpI/gpJUg4KSm4KS/4KSoJyxcbiAgICAgICAgZGQgOiAnJWQg4KSm4KS/4KSoJyxcbiAgICAgICAgTSA6ICfgpI/gpJUg4KSu4KS54KWA4KSo4KWHJyxcbiAgICAgICAgTU0gOiAnJWQg4KSu4KS54KWA4KSo4KWHJyxcbiAgICAgICAgeSA6ICfgpI/gpJUg4KS14KSw4KWN4KS3JyxcbiAgICAgICAgeXkgOiAnJWQg4KS14KSw4KWN4KS3J1xuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4KWn4KWo4KWp4KWq4KWr4KWs4KWt4KWu4KWv4KWmXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXBbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICAvLyBIaW5kaSBub3RhdGlvbiBmb3IgbWVyaWRpZW1zIGFyZSBxdWl0ZSBmdXp6eSBpbiBwcmFjdGljZS4gV2hpbGUgdGhlcmUgZXhpc3RzXG4gICAgLy8gYSByaWdpZCBub3Rpb24gb2YgYSAnUGFoYXInIGl0IGlzIG5vdCB1c2VkIGFzIHJpZ2lkbHkgaW4gbW9kZXJuIEhpbmRpLlxuICAgIG1lcmlkaWVtUGFyc2U6IC/gpLDgpL7gpKR84KS44KWB4KSs4KS5fOCkpuCli+CkquCkueCksHzgpLbgpL7gpK4vLFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+CksOCkvuCkpCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgpLjgpYHgpKzgpLknKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkpuCli+CkquCkueCksCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CktuCkvuCkricpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSkJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgIHJldHVybiAn4KS44KWB4KSs4KS5JztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAn4KSm4KWL4KSq4KS54KSwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiAn4KS24KS+4KSuJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSkJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGhpO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9oaS5qc1xuLy8gbW9kdWxlIGlkID0gNTRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IENyb2F0aWFuIFtocl1cbi8vISBhdXRob3IgOiBCb2phbiBNYXJrb3ZpxIcgOiBodHRwczovL2dpdGh1Yi5jb20vYm1hcmtvdmljXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxuZnVuY3Rpb24gdHJhbnNsYXRlKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlICdzcyc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzZWt1bmRhJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3Nla3VuZGUnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ3Nla3VuZGknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdqZWRuYSBtaW51dGEnIDogJ2plZG5lIG1pbnV0ZSc7XG4gICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21pbnV0YSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMiB8fCBudW1iZXIgPT09IDMgfHwgbnVtYmVyID09PSA0KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdtaW51dGUnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21pbnV0YSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ2plZGFuIHNhdCcgOiAnamVkbm9nIHNhdGEnO1xuICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdzYXQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPT09IDIgfHwgbnVtYmVyID09PSAzIHx8IG51bWJlciA9PT0gNCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2F0YSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnc2F0aSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9ICdkYW4nO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2RhbmEnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnbWplc2VjJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21qZXNlY2EnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ21qZXNlY2knO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZ29kaW5hJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyIHx8IG51bWJlciA9PT0gMyB8fCBudW1iZXIgPT09IDQpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gJ2dvZGluZSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSAnZ29kaW5hJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxufVxuXG52YXIgaHIgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdocicsIHtcbiAgICBtb250aHMgOiB7XG4gICAgICAgIGZvcm1hdDogJ3NpamXEjW5qYV92ZWxqYcSNZV9vxb51amthX3RyYXZuamFfc3ZpYm5qYV9saXBuamFfc3JwbmphX2tvbG92b3phX3J1am5hX2xpc3RvcGFkYV9zdHVkZW5vZ2FfcHJvc2luY2EnLnNwbGl0KCdfJyksXG4gICAgICAgIHN0YW5kYWxvbmU6ICdzaWplxI1hbmpfdmVsamHEjWFfb8W+dWpha190cmF2YW5qX3N2aWJhbmpfbGlwYW5qX3NycGFual9rb2xvdm96X3J1amFuX2xpc3RvcGFkX3N0dWRlbmlfcHJvc2luYWMnLnNwbGl0KCdfJylcbiAgICB9LFxuICAgIG1vbnRoc1Nob3J0IDogJ3Npai5fdmVsai5fb8W+dS5fdHJhLl9zdmkuX2xpcC5fc3JwLl9rb2wuX3J1ai5fbGlzLl9zdHUuX3Byby4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICduZWRqZWxqYV9wb25lZGplbGpha191dG9yYWtfc3JpamVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnbmVkLl9wb24uX3V0by5fc3JpLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnbmVfcG9fdXRfc3JfxI1lX3BlX3N1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSAgOiAnW2RhbmFzIHVdIExUJyxcbiAgICAgICAgbmV4dERheSAgOiAnW3N1dHJhIHVdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtuZWRqZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzcmlqZWR1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3N1Ym90dV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSAgOiAnW2p1xI1lciB1XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsdV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJvxaFsZV0gW3N1Ym90ZV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3Byb8WhbGldIGRkZGQgW3VdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3phICVzJyxcbiAgICAgICAgcGFzdCAgIDogJ3ByaWplICVzJyxcbiAgICAgICAgcyAgICAgIDogJ3BhciBzZWt1bmRpJyxcbiAgICAgICAgc3MgICAgIDogdHJhbnNsYXRlLFxuICAgICAgICBtICAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIG1tICAgICA6IHRyYW5zbGF0ZSxcbiAgICAgICAgaCAgICAgIDogdHJhbnNsYXRlLFxuICAgICAgICBoaCAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIGQgICAgICA6ICdkYW4nLFxuICAgICAgICBkZCAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIE0gICAgICA6ICdtamVzZWMnLFxuICAgICAgICBNTSAgICAgOiB0cmFuc2xhdGUsXG4gICAgICAgIHkgICAgICA6ICdnb2RpbnUnLFxuICAgICAgICB5eSAgICAgOiB0cmFuc2xhdGVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBocjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvaHIuanNcbi8vIG1vZHVsZSBpZCA9IDU1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBIdW5nYXJpYW4gW2h1XVxuLy8hIGF1dGhvciA6IEFkYW0gQnJ1bm5lciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hZGFtYnJ1bm5lclxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB3ZWVrRW5kaW5ncyA9ICd2YXPDoXJuYXAgaMOpdGbFkW4ga2VkZGVuIHN6ZXJkw6FuIGNzw7x0w7ZydMO2a8O2biBww6ludGVrZW4gc3pvbWJhdG9uJy5zcGxpdCgnICcpO1xuZnVuY3Rpb24gdHJhbnNsYXRlKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciBudW0gPSBudW1iZXI7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSAncyc6XG4gICAgICAgICAgICByZXR1cm4gKGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXgpID8gJ27DqWjDoW55IG3DoXNvZHBlcmMnIDogJ27DqWjDoW55IG3DoXNvZHBlcmNlJztcbiAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4KSA/ICcgbcOhc29kcGVyYycgOiAnIG3DoXNvZHBlcmNlJztcbiAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICByZXR1cm4gJ2VneScgKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgcGVyYycgOiAnIHBlcmNlJyk7XG4gICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgcGVyYycgOiAnIHBlcmNlJyk7XG4gICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgcmV0dXJuICdlZ3knICsgKGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXggPyAnIMOzcmEnIDogJyDDs3LDoWphJyk7XG4gICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgIHJldHVybiBudW0gKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgw7NyYScgOiAnIMOzcsOhamEnKTtcbiAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICByZXR1cm4gJ2VneScgKyAoaXNGdXR1cmUgfHwgd2l0aG91dFN1ZmZpeCA/ICcgbmFwJyA6ICcgbmFwamEnKTtcbiAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBuYXAnIDogJyBuYXBqYScpO1xuICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIHJldHVybiAnZWd5JyArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyBow7NuYXAnIDogJyBow7NuYXBqYScpO1xuICAgICAgICBjYXNlICdNTSc6XG4gICAgICAgICAgICByZXR1cm4gbnVtICsgKGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXggPyAnIGjDs25hcCcgOiAnIGjDs25hcGphJyk7XG4gICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgcmV0dXJuICdlZ3knICsgKGlzRnV0dXJlIHx8IHdpdGhvdXRTdWZmaXggPyAnIMOpdicgOiAnIMOpdmUnKTtcbiAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgcmV0dXJuIG51bSArIChpc0Z1dHVyZSB8fCB3aXRob3V0U3VmZml4ID8gJyDDqXYnIDogJyDDqXZlJyk7XG4gICAgfVxuICAgIHJldHVybiAnJztcbn1cbmZ1bmN0aW9uIHdlZWsoaXNGdXR1cmUpIHtcbiAgICByZXR1cm4gKGlzRnV0dXJlID8gJycgOiAnW23Dumx0XSAnKSArICdbJyArIHdlZWtFbmRpbmdzW3RoaXMuZGF5KCldICsgJ10gTFRbLWtvcl0nO1xufVxuXG52YXIgaHUgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdodScsIHtcbiAgICBtb250aHMgOiAnamFudcOhcl9mZWJydcOhcl9tw6FyY2l1c1/DoXByaWxpc19tw6FqdXNfasO6bml1c19qw7psaXVzX2F1Z3VzenR1c19zemVwdGVtYmVyX29rdMOzYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbcOhcmNfw6Fwcl9tw6FqX2rDum5fasO6bF9hdWdfc3plcHRfb2t0X25vdl9kZWMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAndmFzw6FybmFwX2jDqXRmxZFfa2VkZF9zemVyZGFfY3PDvHTDtnJ0w7ZrX3DDqW50ZWtfc3pvbWJhdCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3Zhc19ow6l0X2tlZGRfc3plX2Nzw7x0X3DDqW5fc3pvJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ3ZfaF9rX3N6ZV9jc19wX3N6bycuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSDptbScsXG4gICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZLk1NLkRELicsXG4gICAgICAgIExMIDogJ1lZWVkuIE1NTU0gRC4nLFxuICAgICAgICBMTEwgOiAnWVlZWS4gTU1NTSBELiBIOm1tJyxcbiAgICAgICAgTExMTCA6ICdZWVlZLiBNTU1NIEQuLCBkZGRkIEg6bW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAvZGV8ZHUvaSxcbiAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0LmNoYXJBdCgxKS50b0xvd2VyQ2FzZSgpID09PSAndSc7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPT09IHRydWUgPyAnZGUnIDogJ0RFJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID09PSB0cnVlID8gJ2R1JyA6ICdEVSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1ttYV0gTFRbLWtvcl0nLFxuICAgICAgICBuZXh0RGF5IDogJ1tob2xuYXBdIExUWy1rb3JdJyxcbiAgICAgICAgbmV4dFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gd2Vlay5jYWxsKHRoaXMsIHRydWUpO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5IDogJ1t0ZWduYXBdIExUWy1rb3JdJyxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gd2Vlay5jYWxsKHRoaXMsIGZhbHNlKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIG3Dumx2YScsXG4gICAgICAgIHBhc3QgOiAnJXMnLFxuICAgICAgICBzIDogdHJhbnNsYXRlLFxuICAgICAgICBzcyA6IHRyYW5zbGF0ZSxcbiAgICAgICAgbSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgbW0gOiB0cmFuc2xhdGUsXG4gICAgICAgIGggOiB0cmFuc2xhdGUsXG4gICAgICAgIGhoIDogdHJhbnNsYXRlLFxuICAgICAgICBkIDogdHJhbnNsYXRlLFxuICAgICAgICBkZCA6IHRyYW5zbGF0ZSxcbiAgICAgICAgTSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgTU0gOiB0cmFuc2xhdGUsXG4gICAgICAgIHkgOiB0cmFuc2xhdGUsXG4gICAgICAgIHl5IDogdHJhbnNsYXRlXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gaHU7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2h1LmpzXG4vLyBtb2R1bGUgaWQgPSA1NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQXJtZW5pYW4gW2h5LWFtXVxuLy8hIGF1dGhvciA6IEFybWVuZGFyYWJ5YW4gOiBodHRwczovL2dpdGh1Yi5jb20vYXJtZW5kYXJhYnlhblxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBoeUFtID0gbW9tZW50LmRlZmluZUxvY2FsZSgnaHktYW0nLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICBmb3JtYXQ6ICfVsNW41oLVttW+1aHWgNWrX9aD1aXVv9aA1b7VodaA1atf1bTVodaA1b/Vq1/VodW61oDVq9Ws1atf1bTVodW11avVvdWrX9Ww1bjWgtW21avVvdWrX9Ww1bjWgtWs1avVvdWrX9aF1aPVuNW91b/VuNW91atf1b3VpdW61b/VpdW01aLVpdaA1atf1bDVuNWv1b/VpdW01aLVpdaA1atf1bbVuNW11aXVtNWi1aXWgNWrX9Wk1aXVr9W/1aXVtNWi1aXWgNWrJy5zcGxpdCgnXycpLFxuICAgICAgICBzdGFuZGFsb25lOiAn1bDVuNaC1bbVvtWh1oBf1oPVpdW/1oDVvtWh1oBf1bTVodaA1b9f1aHVutaA1avVrF/VtNWh1bXVq9W9X9Ww1bjWgtW21avVvV/VsNW41oLVrNWr1b1f1oXVo9W41b3Vv9W41b1f1b3VpdW61b/VpdW01aLVpdaAX9Ww1bjVr9W/1aXVtNWi1aXWgF/VttW41bXVpdW01aLVpdaAX9Wk1aXVr9W/1aXVtNWi1aXWgCcuc3BsaXQoJ18nKVxuICAgIH0sXG4gICAgbW9udGhzU2hvcnQgOiAn1bDVttW+X9aD1b/WgF/VtNaA1b9f1aHVutaAX9W01bXVvV/VsNW21b1f1bDVrNW9X9aF1aPVvV/VvdW61b9f1bDVr9W/X9W21bTVol/VpNWv1b8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn1a/Vq9aA1aHVr9WrX9Wl1oDVr9W41oLVt9Wh1aLVqdWrX9Wl1oDVpdaE1bfVodWi1anVq1/VudW41oDVpdaE1bfVodWi1anVq1/VsNWr1bbVo9W31aHVotWp1atf1bjWgtaA1aLVodWpX9W31aHVotWh1aknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfVr9aA1a9f1aXWgNWvX9Wl1oDWhF/VudaA1oRf1bDVttWjX9W41oLWgNWiX9W31aLVqScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfVr9aA1a9f1aXWgNWvX9Wl1oDWhF/VudaA1oRf1bDVttWjX9W41oLWgNWiX9W31aLVqScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWSDVqS4nLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkg1akuLCBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkg1akuLCBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW9Wh1bXVvdaF1oBdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1vVvtWh1bLVqF0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW9Wl1oDVpdWvXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJ2RkZGQgW9aF1oDVqCDVqtWh1bTVqF0gTFQnO1xuICAgICAgICB9LFxuICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdb1aHVttaB1aHVrl0gZGRkZCBb1oXWgNWoINWq1aHVtNWoXSBMVCc7XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzINWw1aXVv9W4JyxcbiAgICAgICAgcGFzdCA6ICclcyDVodW81aHVuycsXG4gICAgICAgIHMgOiAn1bTVqyDWhNWh1bbVqyDVvtWh1bXWgNWv1bXVodW2JyxcbiAgICAgICAgc3MgOiAnJWQg1b7VodW11oDVr9W11aHVticsXG4gICAgICAgIG0gOiAn1oDVuNW61aUnLFxuICAgICAgICBtbSA6ICclZCDWgNW41brVpScsXG4gICAgICAgIGggOiAn1arVodW0JyxcbiAgICAgICAgaGggOiAnJWQg1arVodW0JyxcbiAgICAgICAgZCA6ICfWhdaAJyxcbiAgICAgICAgZGQgOiAnJWQg1oXWgCcsXG4gICAgICAgIE0gOiAn1aHVtNWr1b0nLFxuICAgICAgICBNTSA6ICclZCDVodW01avVvScsXG4gICAgICAgIHkgOiAn1b/VodaA1asnLFxuICAgICAgICB5eSA6ICclZCDVv9Wh1oDVqydcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/Vo9Wr1bfVpdaA1b7VoXzVodW81aHVvtW41b/VvtWhfNaB1aXWgNWl1a/VvtWhfNWl1oDVpdWv1bjVtdWh1bYvLFxuICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gL14o1oHVpdaA1aXVr9W+1aF81aXWgNWl1a/VuNW11aHVtikkLy50ZXN0KGlucHV0KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9Wj1avVt9Wl1oDVvtWhJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn1aHVvNWh1b7VuNW/1b7VoSc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICByZXR1cm4gJ9aB1aXWgNWl1a/VvtWhJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn1aXWgNWl1a/VuNW11aHVtic7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfXxcXGR7MSwyfS0o1avVtnzWgNWkKS8sXG4gICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgIGNhc2UgJ0RERG8nOlxuICAgICAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct1avVtic7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdaA1aQnO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gaHlBbTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvaHktYW0uanNcbi8vIG1vZHVsZSBpZCA9IDU3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBJbmRvbmVzaWFuIFtpZF1cbi8vISBhdXRob3IgOiBNb2hhbW1hZCBTYXRyaW8gVXRvbW8gOiBodHRwczovL2dpdGh1Yi5jb20vdHlva1xuLy8hIHJlZmVyZW5jZTogaHR0cDovL2lkLndpa2lzb3VyY2Uub3JnL3dpa2kvUGVkb21hbl9VbXVtX0VqYWFuX0JhaGFzYV9JbmRvbmVzaWFfeWFuZ19EaXNlbXB1cm5ha2FuXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGlkID0gbW9tZW50LmRlZmluZUxvY2FsZSgnaWQnLCB7XG4gICAgbW9udGhzIDogJ0phbnVhcmlfRmVicnVhcmlfTWFyZXRfQXByaWxfTWVpX0p1bmlfSnVsaV9BZ3VzdHVzX1NlcHRlbWJlcl9Pa3RvYmVyX05vdmVtYmVyX0Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NZWlfSnVuX0p1bF9BZ3NfU2VwX09rdF9Ob3ZfRGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ01pbmdndV9TZW5pbl9TZWxhc2FfUmFidV9LYW1pc19KdW1hdF9TYWJ0dScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ01pbl9TZW5fU2VsX1JhYl9LYW1fSnVtX1NhYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdNZ19Tbl9TbF9SYl9LbV9KbV9TYicuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEgubW0nLFxuICAgICAgICBMVFMgOiAnSEgubW0uc3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBbcHVrdWxdIEhILm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL3BhZ2l8c2lhbmd8c29yZXxtYWxhbS8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAncGFnaScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc2lhbmcnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICdzb3JlJyB8fCBtZXJpZGllbSA9PT0gJ21hbGFtJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzIDwgMTEpIHtcbiAgICAgICAgICAgIHJldHVybiAncGFnaSc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgcmV0dXJuICdzaWFuZyc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgcmV0dXJuICdzb3JlJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAnbWFsYW0nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbSGFyaSBpbmkgcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbQmVzb2sgcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbS2VtYXJpbiBwdWt1bF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtsYWx1IHB1a3VsXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdkYWxhbSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgeWFuZyBsYWx1JyxcbiAgICAgICAgcyA6ICdiZWJlcmFwYSBkZXRpaycsXG4gICAgICAgIHNzIDogJyVkIGRldGlrJyxcbiAgICAgICAgbSA6ICdzZW1lbml0JyxcbiAgICAgICAgbW0gOiAnJWQgbWVuaXQnLFxuICAgICAgICBoIDogJ3NlamFtJyxcbiAgICAgICAgaGggOiAnJWQgamFtJyxcbiAgICAgICAgZCA6ICdzZWhhcmknLFxuICAgICAgICBkZCA6ICclZCBoYXJpJyxcbiAgICAgICAgTSA6ICdzZWJ1bGFuJyxcbiAgICAgICAgTU0gOiAnJWQgYnVsYW4nLFxuICAgICAgICB5IDogJ3NldGFodW4nLFxuICAgICAgICB5eSA6ICclZCB0YWh1bidcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBpZDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvaWQuanNcbi8vIG1vZHVsZSBpZCA9IDU4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBJY2VsYW5kaWMgW2lzXVxuLy8hIGF1dGhvciA6IEhpbnJpayDDlnJuIFNpZ3Vyw7Bzc29uIDogaHR0cHM6Ly9naXRodWIuY29tL2hpbnJpa1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbmZ1bmN0aW9uIHBsdXJhbChuKSB7XG4gICAgaWYgKG4gJSAxMDAgPT09IDExKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gZWxzZSBpZiAobiAlIDEwID09PSAxKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiB0cmFuc2xhdGUobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgdmFyIHJlc3VsdCA9IG51bWJlciArICcgJztcbiAgICBzd2l0Y2ggKGtleSkge1xuICAgICAgICBjYXNlICdzJzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ25va2tyYXIgc2Vrw7puZHVyJyA6ICdub2trcnVtIHNla8O6bmR1bSc7XG4gICAgICAgIGNhc2UgJ3NzJzpcbiAgICAgICAgICAgIGlmIChwbHVyYWwobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdzZWvDum5kdXInIDogJ3Nla8O6bmR1bScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdzZWvDum5kYSc7XG4gICAgICAgIGNhc2UgJ20nOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnbcOtbsO6dGEnIDogJ23DrW7DunR1JztcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgaWYgKHBsdXJhbChudW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ23DrW7DunR1cicgOiAnbcOtbsO6dHVtJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ23DrW7DunRhJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbcOtbsO6dHUnO1xuICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICBpZiAocGx1cmFsKG51bWJlcikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAna2x1a2t1c3R1bmRpcicgOiAna2x1a2t1c3R1bmR1bScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdrbHVra3VzdHVuZCc7XG4gICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJ2RhZ3VyJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdkYWcnIDogJ2RlZ2knO1xuICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgICAgICBpZiAocGx1cmFsKG51bWJlcikpIHtcbiAgICAgICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2RhZ2FyJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChpc0Z1dHVyZSA/ICdkYWdhJyA6ICdkw7ZndW0nKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnZGFndXInO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChpc0Z1dHVyZSA/ICdkYWcnIDogJ2RlZ2knKTtcbiAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAnbcOhbnXDsHVyJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpc0Z1dHVyZSA/ICdtw6FudcOwJyA6ICdtw6FudcOwaSc7XG4gICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgIGlmIChwbHVyYWwobnVtYmVyKSkge1xuICAgICAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnbcOhbnXDsGlyJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChpc0Z1dHVyZSA/ICdtw6FudcOwaScgOiAnbcOhbnXDsHVtJyk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ23DoW51w7B1cic7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKGlzRnV0dXJlID8gJ23DoW51w7AnIDogJ23DoW51w7BpJyk7XG4gICAgICAgIGNhc2UgJ3knOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnw6FyJyA6ICfDoXJpJztcbiAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgaWYgKHBsdXJhbChudW1iZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ8OhcicgOiAnw6FydW0nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICfDoXInIDogJ8OhcmknKTtcbiAgICB9XG59XG5cbnZhciBpcyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2lzJywge1xuICAgIG1vbnRocyA6ICdqYW7DumFyX2ZlYnLDumFyX21hcnNfYXByw61sX21hw61fasO6bsOtX2rDumzDrV/DoWfDunN0X3NlcHRlbWJlcl9va3TDs2Jlcl9uw7N2ZW1iZXJfZGVzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFuX2ZlYl9tYXJfYXByX21hw61fasO6bl9qw7psX8OhZ8O6X3NlcF9va3RfbsOzdl9kZXMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnc3VubnVkYWd1cl9tw6FudWRhZ3VyX8O+cmnDsGp1ZGFndXJfbWnDsHZpa3VkYWd1cl9maW1tdHVkYWd1cl9mw7ZzdHVkYWd1cl9sYXVnYXJkYWd1cicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3N1bl9tw6FuX8O+cmlfbWnDsF9maW1fZsO2c19sYXUnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU3VfTcOhX8Oecl9NaV9GaV9Gw7ZfTGEnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgW2tsLl0gSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRC4gTU1NTSBZWVlZIFtrbC5dIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbw60gZGFnIGtsLl0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vDoSBtb3JndW4ga2wuXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2tsLl0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vDrSBnw6ZyIGtsLl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbc8Otw7Bhc3RhXSBkZGRkIFtrbC5dIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2VmdGlyICVzJyxcbiAgICAgICAgcGFzdCA6ICdmeXJpciAlcyBzw63DsGFuJyxcbiAgICAgICAgcyA6IHRyYW5zbGF0ZSxcbiAgICAgICAgc3MgOiB0cmFuc2xhdGUsXG4gICAgICAgIG0gOiB0cmFuc2xhdGUsXG4gICAgICAgIG1tIDogdHJhbnNsYXRlLFxuICAgICAgICBoIDogJ2tsdWtrdXN0dW5kJyxcbiAgICAgICAgaGggOiB0cmFuc2xhdGUsXG4gICAgICAgIGQgOiB0cmFuc2xhdGUsXG4gICAgICAgIGRkIDogdHJhbnNsYXRlLFxuICAgICAgICBNIDogdHJhbnNsYXRlLFxuICAgICAgICBNTSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgeSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgeXkgOiB0cmFuc2xhdGVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBpcztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvaXMuanNcbi8vIG1vZHVsZSBpZCA9IDU5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBJdGFsaWFuIFtpdF1cbi8vISBhdXRob3IgOiBMb3JlbnpvIDogaHR0cHM6Ly9naXRodWIuY29tL2FsaWVtXG4vLyEgYXV0aG9yOiBNYXR0aWEgTGFyZW50aXM6IGh0dHBzOi8vZ2l0aHViLmNvbS9ub3N0YWxnaWF6XG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGl0ID0gbW9tZW50LmRlZmluZUxvY2FsZSgnaXQnLCB7XG4gICAgbW9udGhzIDogJ2dlbm5haW9fZmViYnJhaW9fbWFyem9fYXByaWxlX21hZ2dpb19naXVnbm9fbHVnbGlvX2Fnb3N0b19zZXR0ZW1icmVfb3R0b2JyZV9ub3ZlbWJyZV9kaWNlbWJyZScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdnZW5fZmViX21hcl9hcHJfbWFnX2dpdV9sdWdfYWdvX3NldF9vdHRfbm92X2RpYycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdkb21lbmljYV9sdW5lZMOsX21hcnRlZMOsX21lcmNvbGVkw6xfZ2lvdmVkw6xfdmVuZXJkw6xfc2FiYXRvJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnZG9tX2x1bl9tYXJfbWVyX2dpb192ZW5fc2FiJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2RvX2x1X21hX21lX2dpX3ZlX3NhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbT2dnaSBhbGxlXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbRG9tYW5pIGFsbGVdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFthbGxlXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbSWVyaSBhbGxlXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW2xhIHNjb3JzYV0gZGRkZCBbYWxsZV0gTFQnO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW2xvIHNjb3Jzb10gZGRkZCBbYWxsZV0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6IGZ1bmN0aW9uIChzKSB7XG4gICAgICAgICAgICByZXR1cm4gKCgvXlswLTldLiskLykudGVzdChzKSA/ICd0cmEnIDogJ2luJykgKyAnICcgKyBzO1xuICAgICAgICB9LFxuICAgICAgICBwYXN0IDogJyVzIGZhJyxcbiAgICAgICAgcyA6ICdhbGN1bmkgc2Vjb25kaScsXG4gICAgICAgIHNzIDogJyVkIHNlY29uZGknLFxuICAgICAgICBtIDogJ3VuIG1pbnV0bycsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0aScsXG4gICAgICAgIGggOiAndW5cXCdvcmEnLFxuICAgICAgICBoaCA6ICclZCBvcmUnLFxuICAgICAgICBkIDogJ3VuIGdpb3JubycsXG4gICAgICAgIGRkIDogJyVkIGdpb3JuaScsXG4gICAgICAgIE0gOiAndW4gbWVzZScsXG4gICAgICAgIE1NIDogJyVkIG1lc2knLFxuICAgICAgICB5IDogJ3VuIGFubm8nLFxuICAgICAgICB5eSA6ICclZCBhbm5pJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfcK6LyxcbiAgICBvcmRpbmFsOiAnJWTCuicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGl0O1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9pdC5qc1xuLy8gbW9kdWxlIGlkID0gNjBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEphcGFuZXNlIFtqYV1cbi8vISBhdXRob3IgOiBMSSBMb25nIDogaHR0cHM6Ly9naXRodWIuY29tL2JhcnlvblxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBqYSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2phJywge1xuICAgIG1vbnRocyA6ICcx5pyIXzLmnIhfM+aciF805pyIXzXmnIhfNuaciF835pyIXzjmnIhfOeaciF8xMOaciF8xMeaciF8xMuaciCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICcx5pyIXzLmnIhfM+aciF805pyIXzXmnIhfNuaciF835pyIXzjmnIhfOeaciF8xMOaciF8xMeaciF8xMuaciCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfml6Xmm5zml6Vf5pyI5puc5pelX+eBq+abnOaXpV/msLTmm5zml6Vf5pyo5puc5pelX+mHkeabnOaXpV/lnJ/mm5zml6UnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfml6Vf5pyIX+eBq1/msLRf5pyoX+mHkV/lnJ8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn5pelX+aciF/ngatf5rC0X+acqF/ph5Ff5ZyfJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnWVlZWS9NTS9ERCcsXG4gICAgICAgIExMIDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgIExMTCA6ICdZWVlZ5bm0TeaciETml6UgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ1lZWVnlubRN5pyIROaXpSBISDptbSBkZGRkJyxcbiAgICAgICAgbCA6ICdZWVlZL01NL0REJyxcbiAgICAgICAgbGwgOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgbGxsIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgIGxsbGwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tIGRkZGQnXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv5Y2I5YmNfOWNiOW+jC9pLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn5Y2I5b6MJztcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+WNiOWJjSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+WNiOW+jCc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vku4rml6VdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb5piO5pelXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1vmnaXpgLFdZGRkZCBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW+aYqOaXpV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb5YmN6YCxXWRkZGQgTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfeaXpS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfml6UnO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclc+W+jCcsXG4gICAgICAgIHBhc3QgOiAnJXPliY0nLFxuICAgICAgICBzIDogJ+aVsOenkicsXG4gICAgICAgIHNzIDogJyVk56eSJyxcbiAgICAgICAgbSA6ICcx5YiGJyxcbiAgICAgICAgbW0gOiAnJWTliIYnLFxuICAgICAgICBoIDogJzHmmYLplpMnLFxuICAgICAgICBoaCA6ICclZOaZgumWkycsXG4gICAgICAgIGQgOiAnMeaXpScsXG4gICAgICAgIGRkIDogJyVk5pelJyxcbiAgICAgICAgTSA6ICcx44O25pyIJyxcbiAgICAgICAgTU0gOiAnJWTjg7bmnIgnLFxuICAgICAgICB5IDogJzHlubQnLFxuICAgICAgICB5eSA6ICclZOW5tCdcbiAgICB9XG59KTtcblxucmV0dXJuIGphO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9qYS5qc1xuLy8gbW9kdWxlIGlkID0gNjFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEphdmFuZXNlIFtqdl1cbi8vISBhdXRob3IgOiBSb255IExhbnRpcCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9sYW50aXBcbi8vISByZWZlcmVuY2U6IGh0dHA6Ly9qdi53aWtpcGVkaWEub3JnL3dpa2kvQmFzYV9KYXdhXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGp2ID0gbW9tZW50LmRlZmluZUxvY2FsZSgnanYnLCB7XG4gICAgbW9udGhzIDogJ0phbnVhcmlfRmVicnVhcmlfTWFyZXRfQXByaWxfTWVpX0p1bmlfSnVsaV9BZ3VzdHVzX1NlcHRlbWJlcl9Pa3RvYmVyX05vcGVtYmVyX0Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZWJfTWFyX0Fwcl9NZWlfSnVuX0p1bF9BZ3NfU2VwX09rdF9Ob3BfRGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ01pbmdndV9TZW5lbl9TZWxvc29fUmVidV9LZW1pc19KZW11d2FoX1NlcHR1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnTWluX1Nlbl9TZWxfUmViX0tlbV9KZW1fU2VwJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ01nX1NuX1NsX1JiX0ttX0ptX1NwJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISC5tbScsXG4gICAgICAgIExUUyA6ICdISC5tbS5zcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAvZW5qaW5nfHNpeWFuZ3xzb250ZW58bmRhbHUvLFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ2VuamluZycpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc2l5YW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnc29udGVuJyB8fCBtZXJpZGllbSA9PT0gJ25kYWx1Jykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzIDwgMTEpIHtcbiAgICAgICAgICAgIHJldHVybiAnZW5qaW5nJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE1KSB7XG4gICAgICAgICAgICByZXR1cm4gJ3NpeWFuZyc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgcmV0dXJuICdzb250ZW4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICduZGFsdSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tEaW50ZW4gcHVuaWtvIHB1a3VsXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW01iZW5qYW5nIHB1a3VsXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW3B1a3VsXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW0thbGEgd2luZ2kgcHVrdWxdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBba2VwZW5na2VyIHB1a3VsXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICd3b250ZW4gaW5nICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBpbmdrYW5nIGtlcGVuZ2tlcicsXG4gICAgICAgIHMgOiAnc2F3ZXRhd2lzIGRldGlrJyxcbiAgICAgICAgc3MgOiAnJWQgZGV0aWsnLFxuICAgICAgICBtIDogJ3NldHVuZ2dhbCBtZW5pdCcsXG4gICAgICAgIG1tIDogJyVkIG1lbml0JyxcbiAgICAgICAgaCA6ICdzZXR1bmdnYWwgamFtJyxcbiAgICAgICAgaGggOiAnJWQgamFtJyxcbiAgICAgICAgZCA6ICdzZWRpbnRlbicsXG4gICAgICAgIGRkIDogJyVkIGRpbnRlbicsXG4gICAgICAgIE0gOiAnc2V3dWxhbicsXG4gICAgICAgIE1NIDogJyVkIHd1bGFuJyxcbiAgICAgICAgeSA6ICdzZXRhdW4nLFxuICAgICAgICB5eSA6ICclZCB0YXVuJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGp2O1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9qdi5qc1xuLy8gbW9kdWxlIGlkID0gNjJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEdlb3JnaWFuIFtrYV1cbi8vISBhdXRob3IgOiBJcmFrbGkgSmFuaWFzaHZpbGkgOiBodHRwczovL2dpdGh1Yi5jb20vaXJha2xpLWphbmlhc2h2aWxpXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGthID0gbW9tZW50LmRlZmluZUxvY2FsZSgna2EnLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICBzdGFuZGFsb25lOiAn4YOY4YOQ4YOc4YOV4YOQ4YOg4YOYX+GDl+GDlOGDkeGDlOGDoOGDleGDkOGDmuGDmF/hg5vhg5Dhg6Dhg6Lhg5hf4YOQ4YOe4YOg4YOY4YOa4YOYX+GDm+GDkOGDmOGDoeGDmF/hg5jhg5Xhg5zhg5jhg6Hhg5hf4YOY4YOV4YOa4YOY4YOh4YOYX+GDkOGDkuGDleGDmOGDoeGDouGDnV/hg6Hhg5Thg6Xhg6Lhg5Thg5vhg5Hhg5Thg6Dhg5hf4YOd4YOl4YOi4YOd4YOb4YOR4YOU4YOg4YOYX+GDnOGDneGDlOGDm+GDkeGDlOGDoOGDmF/hg5Phg5Thg5nhg5Thg5vhg5Hhg5Thg6Dhg5gnLnNwbGl0KCdfJyksXG4gICAgICAgIGZvcm1hdDogJ+GDmOGDkOGDnOGDleGDkOGDoOGDoV/hg5fhg5Thg5Hhg5Thg6Dhg5Xhg5Dhg5rhg6Ff4YOb4YOQ4YOg4YOi4YOhX+GDkOGDnuGDoOGDmOGDmuGDmOGDoV/hg5vhg5Dhg5jhg6Hhg6Ff4YOY4YOV4YOc4YOY4YOh4YOhX+GDmOGDleGDmuGDmOGDoeGDoV/hg5Dhg5Lhg5Xhg5jhg6Hhg6Lhg6Ff4YOh4YOU4YOl4YOi4YOU4YOb4YOR4YOU4YOg4YOhX+GDneGDpeGDouGDneGDm+GDkeGDlOGDoOGDoV/hg5zhg53hg5Thg5vhg5Hhg5Thg6Dhg6Ff4YOT4YOU4YOZ4YOU4YOb4YOR4YOU4YOg4YOhJy5zcGxpdCgnXycpXG4gICAgfSxcbiAgICBtb250aHNTaG9ydCA6ICfhg5jhg5Dhg5xf4YOX4YOU4YORX+GDm+GDkOGDoF/hg5Dhg57hg6Bf4YOb4YOQ4YOYX+GDmOGDleGDnF/hg5jhg5Xhg5pf4YOQ4YOS4YOVX+GDoeGDlOGDpV/hg53hg6Xhg6Jf4YOc4YOd4YOUX+GDk+GDlOGDmScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6IHtcbiAgICAgICAgc3RhbmRhbG9uZTogJ+GDmeGDleGDmOGDoOGDkF/hg53hg6Dhg6jhg5Dhg5Hhg5Dhg5fhg5hf4YOh4YOQ4YOb4YOo4YOQ4YOR4YOQ4YOX4YOYX+GDneGDl+GDruGDqOGDkOGDkeGDkOGDl+GDmF/hg67hg6Phg5fhg6jhg5Dhg5Hhg5Dhg5fhg5hf4YOe4YOQ4YOg4YOQ4YOh4YOZ4YOU4YOV4YOYX+GDqOGDkOGDkeGDkOGDl+GDmCcuc3BsaXQoJ18nKSxcbiAgICAgICAgZm9ybWF0OiAn4YOZ4YOV4YOY4YOg4YOQ4YOhX+GDneGDoOGDqOGDkOGDkeGDkOGDl+GDoV/hg6Hhg5Dhg5vhg6jhg5Dhg5Hhg5Dhg5fhg6Ff4YOd4YOX4YOu4YOo4YOQ4YOR4YOQ4YOX4YOhX+GDruGDo+GDl+GDqOGDkOGDkeGDkOGDl+GDoV/hg57hg5Dhg6Dhg5Dhg6Hhg5nhg5Thg5Xhg6Ff4YOo4YOQ4YOR4YOQ4YOX4YOhJy5zcGxpdCgnXycpLFxuICAgICAgICBpc0Zvcm1hdDogLyjhg6zhg5jhg5zhg5B84YOo4YOU4YOb4YOT4YOU4YOSKS9cbiAgICB9LFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4YOZ4YOV4YOYX+GDneGDoOGDqF/hg6Hhg5Dhg5tf4YOd4YOX4YOuX+GDruGDo+GDl1/hg57hg5Dhg6Bf4YOo4YOQ4YORJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+GDmeGDlV/hg53hg6Bf4YOh4YOQX+GDneGDl1/hg67hg6Nf4YOe4YOQX+GDqOGDkCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnaDptbSBBJyxcbiAgICAgICAgTFRTIDogJ2g6bW06c3MgQScsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIGg6bW0gQScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgaDptbSBBJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+GDk+GDpuGDlOGDoV0gTFRbLeGDluGDlF0nLFxuICAgICAgICBuZXh0RGF5IDogJ1vhg67hg5Xhg5Dhg5pdIExUWy3hg5bhg5RdJyxcbiAgICAgICAgbGFzdERheSA6ICdb4YOS4YOj4YOo4YOY4YOcXSBMVFst4YOW4YOUXScsXG4gICAgICAgIG5leHRXZWVrIDogJ1vhg6jhg5Thg5vhg5Phg5Thg5JdIGRkZGQgTFRbLeGDluGDlF0nLFxuICAgICAgICBsYXN0V2VlayA6ICdb4YOs4YOY4YOc4YOQXSBkZGRkIExULeGDluGDlCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6IGZ1bmN0aW9uIChzKSB7XG4gICAgICAgICAgICByZXR1cm4gKC8o4YOs4YOQ4YOb4YOYfOGDrOGDo+GDl+GDmHzhg6Hhg5Dhg5Dhg5fhg5h84YOs4YOU4YOa4YOYKS8pLnRlc3QocykgP1xuICAgICAgICAgICAgICAgIHMucmVwbGFjZSgv4YOYJC8sICfhg6jhg5gnKSA6XG4gICAgICAgICAgICAgICAgcyArICfhg6jhg5gnO1xuICAgICAgICB9LFxuICAgICAgICBwYXN0IDogZnVuY3Rpb24gKHMpIHtcbiAgICAgICAgICAgIGlmICgoLyjhg6zhg5Dhg5vhg5h84YOs4YOj4YOX4YOYfOGDoeGDkOGDkOGDl+GDmHzhg5Phg6bhg5R84YOX4YOV4YOUKS8pLnRlc3QocykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcy5yZXBsYWNlKC8o4YOYfOGDlCkkLywgJ+GDmOGDoSDhg6Phg5nhg5Dhg5wnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgoL+GDrOGDlOGDmuGDmC8pLnRlc3QocykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcy5yZXBsYWNlKC/hg6zhg5Thg5rhg5gkLywgJ+GDrOGDmuGDmOGDoSDhg6Phg5nhg5Dhg5wnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgcyA6ICfhg6Dhg5Dhg5vhg5Phg5Thg5zhg5jhg5vhg5Qg4YOs4YOQ4YOb4YOYJyxcbiAgICAgICAgc3MgOiAnJWQg4YOs4YOQ4YOb4YOYJyxcbiAgICAgICAgbSA6ICfhg6zhg6Phg5fhg5gnLFxuICAgICAgICBtbSA6ICclZCDhg6zhg6Phg5fhg5gnLFxuICAgICAgICBoIDogJ+GDoeGDkOGDkOGDl+GDmCcsXG4gICAgICAgIGhoIDogJyVkIOGDoeGDkOGDkOGDl+GDmCcsXG4gICAgICAgIGQgOiAn4YOT4YOm4YOUJyxcbiAgICAgICAgZGQgOiAnJWQg4YOT4YOm4YOUJyxcbiAgICAgICAgTSA6ICfhg5fhg5Xhg5QnLFxuICAgICAgICBNTSA6ICclZCDhg5fhg5Xhg5QnLFxuICAgICAgICB5IDogJ+GDrOGDlOGDmuGDmCcsXG4gICAgICAgIHl5IDogJyVkIOGDrOGDlOGDmuGDmCdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC8wfDEt4YOa4YOYfOGDm+GDlC1cXGR7MSwyfXxcXGR7MSwyfS3hg5QvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct4YOa4YOYJztcbiAgICAgICAgfVxuICAgICAgICBpZiAoKG51bWJlciA8IDIwKSB8fCAobnVtYmVyIDw9IDEwMCAmJiAobnVtYmVyICUgMjAgPT09IDApKSB8fCAobnVtYmVyICUgMTAwID09PSAwKSkge1xuICAgICAgICAgICAgcmV0dXJuICfhg5vhg5QtJyArIG51bWJlcjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3hg5QnO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSxcbiAgICAgICAgZG95IDogN1xuICAgIH1cbn0pO1xuXG5yZXR1cm4ga2E7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2thLmpzXG4vLyBtb2R1bGUgaWQgPSA2M1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogS2F6YWtoIFtra11cbi8vISBhdXRob3JzIDogTnVybGFuIFJha2hpbXpoYW5vdiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9udXJsYW5cblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgc3VmZml4ZXMgPSB7XG4gICAgMDogJy3RiNGWJyxcbiAgICAxOiAnLdGI0ZYnLFxuICAgIDI6ICct0YjRlicsXG4gICAgMzogJy3RiNGWJyxcbiAgICA0OiAnLdGI0ZYnLFxuICAgIDU6ICct0YjRlicsXG4gICAgNjogJy3RiNGLJyxcbiAgICA3OiAnLdGI0ZYnLFxuICAgIDg6ICct0YjRlicsXG4gICAgOTogJy3RiNGLJyxcbiAgICAxMDogJy3RiNGLJyxcbiAgICAyMDogJy3RiNGLJyxcbiAgICAzMDogJy3RiNGLJyxcbiAgICA0MDogJy3RiNGLJyxcbiAgICA1MDogJy3RiNGWJyxcbiAgICA2MDogJy3RiNGLJyxcbiAgICA3MDogJy3RiNGWJyxcbiAgICA4MDogJy3RiNGWJyxcbiAgICA5MDogJy3RiNGLJyxcbiAgICAxMDA6ICct0YjRlidcbn07XG5cbnZhciBrayA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2trJywge1xuICAgIG1vbnRocyA6ICfSm9Cw0qPRgtCw0YBf0LDSm9C/0LDQvV/QvdCw0YPRgNGL0Ldf0YHTmdGD0ZbRgF/QvNCw0LzRi9GAX9C80LDRg9GB0YvQvF/RiNGW0LvQtNC1X9GC0LDQvNGL0Ldf0pvRi9GA0LrSr9C50LXQul/Sm9Cw0LfQsNC9X9Kb0LDRgNCw0YjQsF/QttC10LvRgtC+0pvRgdCw0L0nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn0pvQsNKjX9Cw0pvQv1/QvdCw0YNf0YHTmdGDX9C80LDQvF/QvNCw0YNf0YjRltC7X9GC0LDQvF/Sm9GL0YBf0pvQsNC3X9Kb0LDRgF/QttC10LsnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn0LbQtdC60YHQtdC90LHRll/QtNKv0LnRgdC10L3QsdGWX9GB0LXQudGB0LXQvdCx0ZZf0YHTmdGA0YHQtdC90LHRll/QsdC10LnRgdC10L3QsdGWX9C20rHQvNCwX9GB0LXQvdCx0ZYnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfQttC10Lpf0LTSr9C5X9GB0LXQuV/RgdOZ0YBf0LHQtdC5X9C20rHQvF/RgdC10L0nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn0LbQul/QtNC5X9GB0Llf0YHRgF/QsdC5X9C20Lxf0YHQvScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb0JHSr9Cz0ZbQvSDRgdCw0pPQsNGCXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9CV0YDRgtC10qMg0YHQsNKT0LDRgl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvRgdCw0pPQsNGCXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW9Ca0LXRiNC1INGB0LDSk9Cw0YJdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW9Oo0YLQutC10L0g0LDQv9GC0LDQvdGL0qNdIGRkZGQgW9GB0LDSk9Cw0YJdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzINGW0YjRltC90LTQtScsXG4gICAgICAgIHBhc3QgOiAnJXMg0LHSsdGA0YvQvScsXG4gICAgICAgIHMgOiAn0LHRltGA0L3QtdGI0LUg0YHQtdC60YPQvdC0JyxcbiAgICAgICAgc3MgOiAnJWQg0YHQtdC60YPQvdC0JyxcbiAgICAgICAgbSA6ICfQsdGW0YAg0LzQuNC90YPRgicsXG4gICAgICAgIG1tIDogJyVkINC80LjQvdGD0YInLFxuICAgICAgICBoIDogJ9Cx0ZbRgCDRgdCw0pPQsNGCJyxcbiAgICAgICAgaGggOiAnJWQg0YHQsNKT0LDRgicsXG4gICAgICAgIGQgOiAn0LHRltGAINC60q/QvScsXG4gICAgICAgIGRkIDogJyVkINC60q/QvScsXG4gICAgICAgIE0gOiAn0LHRltGAINCw0LknLFxuICAgICAgICBNTSA6ICclZCDQsNC5JyxcbiAgICAgICAgeSA6ICfQsdGW0YAg0LbRi9C7JyxcbiAgICAgICAgeXkgOiAnJWQg0LbRi9C7J1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjRiNGWfNGI0YspLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgYiA9IG51bWJlciA+PSAxMDAgPyAxMDAgOiBudWxsO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgKHN1ZmZpeGVzW251bWJlcl0gfHwgc3VmZml4ZXNbYV0gfHwgc3VmZml4ZXNbYl0pO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGtrO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9ray5qc1xuLy8gbW9kdWxlIGlkID0gNjRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IENhbWJvZGlhbiBba21dXG4vLyEgYXV0aG9yIDogS3J1eSBWYW5uYSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9rcnV5dmFubmFcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIga20gPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdrbScsIHtcbiAgICBtb250aHM6ICfhnpjhnoDhnprhnrZf4Z6A4Z674Z6Y4Z+S4Z6X4Z+IX+GemOGeuOGek+Getl/hnpjhn4Hhnp/hnrZf4Z6n4Z6f4Z6X4Z62X+GemOGet+GekOGeu+Gek+Getl/hnoDhnoDhn5LhnoDhnorhnrZf4Z6f4Z644Z6g4Z62X+GegOGeieGfkuGeieGetl/hno/hnrvhnpvhnrZf4Z6c4Z634Z6F4Z+S4Z6G4Z634Z6A4Z62X+GekuGfkuGek+GevCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydDogJ+GemOGegOGemuGetl/hnoDhnrvhnpjhn5Lhnpfhn4hf4Z6Y4Z644Z6T4Z62X+GemOGfgeGen+Getl/hnqfhnp/hnpfhnrZf4Z6Y4Z634Z6Q4Z674Z6T4Z62X+GegOGegOGfkuGegOGeiuGetl/hnp/hnrjhnqDhnrZf4Z6A4Z6J4Z+S4Z6J4Z62X+Gej+Geu+Gem+Getl/hnpzhnrfhnoXhn5LhnobhnrfhnoDhnrZf4Z6S4Z+S4Z6T4Z68Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzOiAn4Z6i4Z624Z6R4Z634Z6P4Z+S4Z6ZX+GeheGfkOGek+GfkuGekV/hnqLhnoThn5LhnoLhnrbhnppf4Z6W4Z674Z6SX+GeluGfkuGemuGeoOGen+GfkuGelOGej+Get+GfjV/hnp/hnrvhnoDhn5Lhnppf4Z6f4Z+F4Z6a4Z+NJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQ6ICfhnqLhnrbhnpHhnrfhno/hn5Lhnplf4Z6F4Z+Q4Z6T4Z+S4Z6RX+GeouGehOGfkuGeguGetuGeml/hnpbhnrvhnpJf4Z6W4Z+S4Z6a4Z6g4Z6f4Z+S4Z6U4Z6P4Z634Z+NX+Gen+Geu+GegOGfkuGeml/hnp/hn4Xhnprhn40nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW46ICfhnqLhnrbhnpHhnrfhno/hn5Lhnplf4Z6F4Z+Q4Z6T4Z+S4Z6RX+GeouGehOGfkuGeguGetuGeml/hnpbhnrvhnpJf4Z6W4Z+S4Z6a4Z6g4Z6f4Z+S4Z6U4Z6P4Z634Z+NX+Gen+Geu+GegOGfkuGeml/hnp/hn4Xhnprhn40nLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgTFQ6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1vhnpDhn5LhnoThn4PhnpPhn4Hhn4cg4Z6Y4Z+J4Z+E4Z6EXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb4Z6f4Z+S4Z6i4Z+C4Z6AIOGemOGfieGfhOGehF0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW+GemOGfieGfhOGehF0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW+GemOGfkuGen+Get+Gem+GemOGet+GeiSDhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvhnp/hnpThn5Lhno/hnrbhnqDhn43hnpjhnrvhnpNdIFvhnpjhn4nhn4ThnoRdIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lOiB7XG4gICAgICAgIGZ1dHVyZTogJyVz4Z6R4Z+A4Z6PJyxcbiAgICAgICAgcGFzdDogJyVz4Z6Y4Z674Z6TJyxcbiAgICAgICAgczogJ+GelOGfieGeu+Gek+GfkuGemOGetuGek+GenOGet+Gek+GetuGekeGeuCcsXG4gICAgICAgIHNzOiAnJWQg4Z6c4Z634Z6T4Z624Z6R4Z64JyxcbiAgICAgICAgbTogJ+GemOGeveGemeGek+GetuGekeGeuCcsXG4gICAgICAgIG1tOiAnJWQg4Z6T4Z624Z6R4Z64JyxcbiAgICAgICAgaDogJ+GemOGeveGemeGemOGfieGfhOGehCcsXG4gICAgICAgIGhoOiAnJWQg4Z6Y4Z+J4Z+E4Z6EJyxcbiAgICAgICAgZDogJ+GemOGeveGemeGekOGfkuGehOGfgycsXG4gICAgICAgIGRkOiAnJWQg4Z6Q4Z+S4Z6E4Z+DJyxcbiAgICAgICAgTTogJ+GemOGeveGemeGegeGfgicsXG4gICAgICAgIE1NOiAnJWQg4Z6B4Z+CJyxcbiAgICAgICAgeTogJ+GemOGeveGemeGehuGfkuGek+GetuGfhicsXG4gICAgICAgIHl5OiAnJWQg4Z6G4Z+S4Z6T4Z624Z+GJ1xuICAgIH0sXG4gICAgd2Vlazoge1xuICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3k6IDQgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4ga207XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2ttLmpzXG4vLyBtb2R1bGUgaWQgPSA2NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogS2FubmFkYSBba25dXG4vLyEgYXV0aG9yIDogUmFqZWV2IE5haWsgOiBodHRwczovL2dpdGh1Yi5jb20vcmFqZWV2bmFpa3RlXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHN5bWJvbE1hcCA9IHtcbiAgICAnMSc6ICfgs6cnLFxuICAgICcyJzogJ+CzqCcsXG4gICAgJzMnOiAn4LOpJyxcbiAgICAnNCc6ICfgs6onLFxuICAgICc1JzogJ+CzqycsXG4gICAgJzYnOiAn4LOsJyxcbiAgICAnNyc6ICfgs60nLFxuICAgICc4JzogJ+CzricsXG4gICAgJzknOiAn4LOvJyxcbiAgICAnMCc6ICfgs6YnXG59O1xudmFyIG51bWJlck1hcCA9IHtcbiAgICAn4LOnJzogJzEnLFxuICAgICfgs6gnOiAnMicsXG4gICAgJ+CzqSc6ICczJyxcbiAgICAn4LOqJzogJzQnLFxuICAgICfgs6snOiAnNScsXG4gICAgJ+CzrCc6ICc2JyxcbiAgICAn4LOtJzogJzcnLFxuICAgICfgs64nOiAnOCcsXG4gICAgJ+Czryc6ICc5JyxcbiAgICAn4LOmJzogJzAnXG59O1xuXG52YXIga24gPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdrbicsIHtcbiAgICBtb250aHMgOiAn4LKc4LKo4LK14LKw4LK/X+Cyq+CzhuCyrOCzjeCysOCyteCysOCyv1/gsq7gsr7gsrDgs43gsprgs41f4LKP4LKq4LON4LKw4LK/4LKy4LONX+CyruCzhuCzlV/gspzgs4Lgsqjgs41f4LKc4LOB4LKy4LOG4LOWX+CyhuCyl+CyuOCzjeCyn+CzjV/gsrjgs4bgsqrgs43gsp/gs4bgsoLgsqzgsrDgs41f4LKF4LKV4LON4LKf4LOG4LOC4LOV4LKs4LKw4LONX+CyqOCyteCzhuCyguCyrOCysOCzjV/gsqHgsr/gsrjgs4bgsoLgsqzgsrDgs40nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn4LKc4LKoX+Cyq+CzhuCyrOCzjeCysF/gsq7gsr7gsrDgs43gsprgs41f4LKP4LKq4LON4LKw4LK/4LKy4LONX+CyruCzhuCzlV/gspzgs4Lgsqjgs41f4LKc4LOB4LKy4LOG4LOWX+CyhuCyl+CyuOCzjeCyn+CzjV/gsrjgs4bgsqrgs43gsp/gs4bgsoLgsqxf4LKF4LKV4LON4LKf4LOG4LOC4LOV4LKsX+CyqOCyteCzhuCyguCyrF/gsqHgsr/gsrjgs4bgsoLgsqwnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICfgsq3gsr7gsqjgs4HgsrXgsr7gsrBf4LK44LOG4LOC4LOV4LKu4LK14LK+4LKwX+CyruCyguCyl+Cys+CyteCyvuCysF/gsqzgs4HgsqfgsrXgsr7gsrBf4LKX4LOB4LKw4LOB4LK14LK+4LKwX+CytuCzgeCyleCzjeCysOCyteCyvuCysF/gsrbgsqjgsr/gsrXgsr7gsrAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgsq3gsr7gsqjgs4Ff4LK44LOG4LOC4LOV4LKuX+CyruCyguCyl+Cys1/gsqzgs4Hgsqdf4LKX4LOB4LKw4LOBX+CytuCzgeCyleCzjeCysF/gsrbgsqjgsr8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4LKt4LK+X+CyuOCzhuCzguCzlV/gsq7gsoJf4LKs4LOBX+Cyl+CzgV/gsrbgs4Ff4LK2Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0nLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEEgaDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgsofgsoLgsqbgs4FdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4LKo4LK+4LKz4LOGXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4LKo4LK/4LKo4LON4LKo4LOGXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgspXgs4bgs4Lgsqjgs4bgsq9dIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIOCyqOCyguCypOCysCcsXG4gICAgICAgIHBhc3QgOiAnJXMg4LK54LK/4LKC4LKm4LOGJyxcbiAgICAgICAgcyA6ICfgspXgs4bgsrLgsrXgs4Eg4LKV4LON4LK34LKj4LKX4LKz4LOBJyxcbiAgICAgICAgc3MgOiAnJWQg4LK44LOG4LKV4LOG4LKC4LKh4LOB4LKX4LKz4LOBJyxcbiAgICAgICAgbSA6ICfgspLgsoLgsqbgs4Eg4LKo4LK/4LKu4LK/4LK3JyxcbiAgICAgICAgbW0gOiAnJWQg4LKo4LK/4LKu4LK/4LK3JyxcbiAgICAgICAgaCA6ICfgspLgsoLgsqbgs4Eg4LKX4LKC4LKf4LOGJyxcbiAgICAgICAgaGggOiAnJWQg4LKX4LKC4LKf4LOGJyxcbiAgICAgICAgZCA6ICfgspLgsoLgsqbgs4Eg4LKm4LK/4LKoJyxcbiAgICAgICAgZGQgOiAnJWQg4LKm4LK/4LKoJyxcbiAgICAgICAgTSA6ICfgspLgsoLgsqbgs4Eg4LKk4LK/4LKC4LKX4LKz4LOBJyxcbiAgICAgICAgTU0gOiAnJWQg4LKk4LK/4LKC4LKX4LKz4LOBJyxcbiAgICAgICAgeSA6ICfgspLgsoLgsqbgs4Eg4LK14LKw4LON4LK3JyxcbiAgICAgICAgeXkgOiAnJWQg4LK14LKw4LON4LK3J1xuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9b4LOn4LOo4LOp4LOq4LOr4LOs4LOt4LOu4LOv4LOmXS9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJNYXBbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHBvc3Rmb3JtYXQ6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC9cXGQvZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gc3ltYm9sTWFwW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv4LKw4LK+4LKk4LON4LKw4LK/fOCyrOCzhuCys+Cyv+Cyl+CzjeCyl+Czhnzgsq7gsqfgs43gsq/gsr7gsrngs43gsqh84LK44LKC4LKc4LOGLyxcbiAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgsrDgsr7gsqTgs43gsrDgsr8nKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA8IDQgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LKs4LOG4LKz4LK/4LKX4LON4LKX4LOGJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgsq7gsqfgs43gsq/gsr7gsrngs43gsqgnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgsrjgsoLgspzgs4YnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXIgPCA0KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CysOCyvuCypOCzjeCysOCyvyc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CyrOCzhuCys+Cyv+Cyl+CzjeCyl+Czhic7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE3KSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CyruCyp+CzjeCyr+CyvuCyueCzjeCyqCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDIwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CyuOCyguCynOCzhic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+CysOCyvuCypOCzjeCysOCyvyc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSjgsqjgs4bgs5UpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+CyqOCzhuCzlSc7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4ga247XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2tuLmpzXG4vLyBtb2R1bGUgaWQgPSA2NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogS29yZWFuIFtrb11cbi8vISBhdXRob3IgOiBLeXVuZ3dvb2ssIFBhcmsgOiBodHRwczovL2dpdGh1Yi5jb20va3l1bmd3MDBrXG4vLyEgYXV0aG9yIDogSmVlZXl1bCBMZWUgPGplZWV5dWxAZ21haWwuY29tPlxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBrbyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2tvJywge1xuICAgIG1vbnRocyA6ICcx7JuUXzLsm5RfM+yblF807JuUXzXsm5RfNuyblF837JuUXzjsm5RfOeyblF8xMOyblF8xMeyblF8xMuyblCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICcx7JuUXzLsm5RfM+yblF807JuUXzXsm5RfNuyblF837JuUXzjsm5RfOeyblF8xMOyblF8xMeyblF8xMuyblCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfsnbzsmpTsnbxf7JuU7JqU7J28X+2ZlOyalOydvF/siJjsmpTsnbxf66qp7JqU7J28X+q4iOyalOydvF/thqDsmpTsnbwnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfsnbxf7JuUX+2ZlF/siJhf66qpX+q4iF/thqAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn7J28X+yblF/tmZRf7IiYX+uqqV/quIhf7YagJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0nLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZLk1NLkREJyxcbiAgICAgICAgTEwgOiAnWVlZWeuFhCBNTU1NIETsnbwnLFxuICAgICAgICBMTEwgOiAnWVlZWeuFhCBNTU1NIETsnbwgQSBoOm1tJyxcbiAgICAgICAgTExMTCA6ICdZWVlZ64WEIE1NTU0gROydvCBkZGRkIEEgaDptbScsXG4gICAgICAgIGwgOiAnWVlZWS5NTS5ERCcsXG4gICAgICAgIGxsIDogJ1lZWVnrhYQgTU1NTSBE7J28JyxcbiAgICAgICAgbGxsIDogJ1lZWVnrhYQgTU1NTSBE7J28IEEgaDptbScsXG4gICAgICAgIGxsbGwgOiAnWVlZWeuFhCBNTU1NIETsnbwgZGRkZCBBIGg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICfsmKTripggTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ+uCtOydvCBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ+yWtOygnCBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ+yngOuCnOyjvCBkZGRkIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIO2bhCcsXG4gICAgICAgIHBhc3QgOiAnJXMg7KCEJyxcbiAgICAgICAgcyA6ICfrqocg7LSIJyxcbiAgICAgICAgc3MgOiAnJWTstIgnLFxuICAgICAgICBtIDogJzHrtoQnLFxuICAgICAgICBtbSA6ICclZOu2hCcsXG4gICAgICAgIGggOiAn7ZWcIOyLnOqwhCcsXG4gICAgICAgIGhoIDogJyVk7Iuc6rCEJyxcbiAgICAgICAgZCA6ICftlZjro6gnLFxuICAgICAgICBkZCA6ICclZOydvCcsXG4gICAgICAgIE0gOiAn7ZWcIOuLrCcsXG4gICAgICAgIE1NIDogJyVk64usJyxcbiAgICAgICAgeSA6ICfsnbwg64WEJyxcbiAgICAgICAgeXkgOiAnJWTrhYQnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlIDogL1xcZHsxLDJ9KOydvHzsm5R87KO8KS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfsnbwnO1xuICAgICAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfsm5QnO1xuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+yjvCc7XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2UgOiAv7Jik7KCEfOyYpO2bhC8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uICh0b2tlbikge1xuICAgICAgICByZXR1cm4gdG9rZW4gPT09ICfsmKTtm4QnO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc1VwcGVyKSB7XG4gICAgICAgIHJldHVybiBob3VyIDwgMTIgPyAn7Jik7KCEJyA6ICfsmKTtm4QnO1xuICAgIH1cbn0pO1xuXG5yZXR1cm4ga287XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2tvLmpzXG4vLyBtb2R1bGUgaWQgPSA2N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogS3lyZ3l6IFtreV1cbi8vISBhdXRob3IgOiBDaHluZ3l6IEFyeXN0YW4gdXVsdSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9jaHluZ3l6XG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxuXG52YXIgc3VmZml4ZXMgPSB7XG4gICAgMDogJy3Rh9KvJyxcbiAgICAxOiAnLdGH0LgnLFxuICAgIDI6ICct0YfQuCcsXG4gICAgMzogJy3Rh9KvJyxcbiAgICA0OiAnLdGH0q8nLFxuICAgIDU6ICct0YfQuCcsXG4gICAgNjogJy3Rh9GLJyxcbiAgICA3OiAnLdGH0LgnLFxuICAgIDg6ICct0YfQuCcsXG4gICAgOTogJy3Rh9GDJyxcbiAgICAxMDogJy3Rh9GDJyxcbiAgICAyMDogJy3Rh9GLJyxcbiAgICAzMDogJy3Rh9GDJyxcbiAgICA0MDogJy3Rh9GLJyxcbiAgICA1MDogJy3Rh9KvJyxcbiAgICA2MDogJy3Rh9GLJyxcbiAgICA3MDogJy3Rh9C4JyxcbiAgICA4MDogJy3Rh9C4JyxcbiAgICA5MDogJy3Rh9GDJyxcbiAgICAxMDA6ICct0YfSrydcbn07XG5cbnZhciBreSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ2t5Jywge1xuICAgIG1vbnRocyA6ICfRj9C90LLQsNGA0Yxf0YTQtdCy0YDQsNC70Yxf0LzQsNGA0YJf0LDQv9GA0LXQu9GMX9C80LDQuV/QuNGO0L3RjF/QuNGO0LvRjF/QsNCy0LPRg9GB0YJf0YHQtdC90YLRj9Cx0YDRjF/QvtC60YLRj9Cx0YDRjF/QvdC+0Y/QsdGA0Yxf0LTQtdC60LDQsdGA0YwnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn0Y/QvdCyX9GE0LXQsl/QvNCw0YDRgl/QsNC/0YBf0LzQsNC5X9C40Y7QvdGMX9C40Y7Qu9GMX9Cw0LLQs1/RgdC10L1f0L7QutGCX9C90L7Rj1/QtNC10LonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn0JbQtdC60YjQtdC80LHQuF/QlNKv0LnRiNOp0LzQsdKvX9Co0LXQudGI0LXQvNCx0Lhf0KjQsNGA0YjQtdC80LHQuF/QkdC10LnRiNC10LzQsdC4X9CW0YPQvNCwX9CY0YjQtdC80LHQuCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9CW0LXQul/QlNKv0Llf0KjQtdC5X9Co0LDRgF/QkdC10Llf0JbRg9C8X9CY0YjQtScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfQltC6X9CU0Llf0KjQuV/QqNGAX9CR0Llf0JbQvF/QmNGIJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vQkdKv0LPSr9C9INGB0LDQsNGCXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9Ct0YDRgtC10qMg0YHQsNCw0YJdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBb0YHQsNCw0YJdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb0JrQtdGH0LUg0YHQsNCw0YJdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW9Oo0YLQutC10L0g0LDQv9GC0LDQvdGL0L1dIGRkZGQgW9C60q/QvdKvXSBb0YHQsNCw0YJdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzINC40YfQuNC90LTQtScsXG4gICAgICAgIHBhc3QgOiAnJXMg0LzRg9GA0YPQvScsXG4gICAgICAgIHMgOiAn0LHQuNGA0L3QtdGH0LUg0YHQtdC60YPQvdC0JyxcbiAgICAgICAgc3MgOiAnJWQg0YHQtdC60YPQvdC0JyxcbiAgICAgICAgbSA6ICfQsdC40YAg0LzSr9C906nRgicsXG4gICAgICAgIG1tIDogJyVkINC80q/QvdOp0YInLFxuICAgICAgICBoIDogJ9Cx0LjRgCDRgdCw0LDRgicsXG4gICAgICAgIGhoIDogJyVkINGB0LDQsNGCJyxcbiAgICAgICAgZCA6ICfQsdC40YAg0LrSr9C9JyxcbiAgICAgICAgZGQgOiAnJWQg0LrSr9C9JyxcbiAgICAgICAgTSA6ICfQsdC40YAg0LDQuScsXG4gICAgICAgIE1NIDogJyVkINCw0LknLFxuICAgICAgICB5IDogJ9Cx0LjRgCDQttGL0LsnLFxuICAgICAgICB5eSA6ICclZCDQttGL0LsnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNGH0Lh80YfRi3zRh9KvfNGH0YMpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICB2YXIgYSA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgYiA9IG51bWJlciA+PSAxMDAgPyAxMDAgOiBudWxsO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgKHN1ZmZpeGVzW251bWJlcl0gfHwgc3VmZml4ZXNbYV0gfHwgc3VmZml4ZXNbYl0pO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIGt5O1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9reS5qc1xuLy8gbW9kdWxlIGlkID0gNjhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IEx1eGVtYm91cmdpc2ggW2xiXVxuLy8hIGF1dGhvciA6IG13ZWltZXJza2lyY2ggOiBodHRwczovL2dpdGh1Yi5jb20vbXdlaW1lcnNraXJjaFxuLy8hIGF1dGhvciA6IERhdmlkIFJhaXNvbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9rd2lzYXR6XG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxuZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAnbSc6IFsnZW5nIE1pbnV0dCcsICdlbmdlciBNaW51dHQnXSxcbiAgICAgICAgJ2gnOiBbJ2VuZyBTdG9ubicsICdlbmdlciBTdG9ubiddLFxuICAgICAgICAnZCc6IFsnZWVuIERhZycsICdlbmdlbSBEYWcnXSxcbiAgICAgICAgJ00nOiBbJ2VlIE1vdW50JywgJ2VuZ2VtIE1vdW50J10sXG4gICAgICAgICd5JzogWydlZSBKb2VyJywgJ2VuZ2VtIEpvZXInXVxuICAgIH07XG4gICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdO1xufVxuZnVuY3Rpb24gcHJvY2Vzc0Z1dHVyZVRpbWUoc3RyaW5nKSB7XG4gICAgdmFyIG51bWJlciA9IHN0cmluZy5zdWJzdHIoMCwgc3RyaW5nLmluZGV4T2YoJyAnKSk7XG4gICAgaWYgKGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihudW1iZXIpKSB7XG4gICAgICAgIHJldHVybiAnYSAnICsgc3RyaW5nO1xuICAgIH1cbiAgICByZXR1cm4gJ2FuICcgKyBzdHJpbmc7XG59XG5mdW5jdGlvbiBwcm9jZXNzUGFzdFRpbWUoc3RyaW5nKSB7XG4gICAgdmFyIG51bWJlciA9IHN0cmluZy5zdWJzdHIoMCwgc3RyaW5nLmluZGV4T2YoJyAnKSk7XG4gICAgaWYgKGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihudW1iZXIpKSB7XG4gICAgICAgIHJldHVybiAndmlydSAnICsgc3RyaW5nO1xuICAgIH1cbiAgICByZXR1cm4gJ3ZpcnVuICcgKyBzdHJpbmc7XG59XG4vKipcbiAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgd29yZCBiZWZvcmUgdGhlIGdpdmVuIG51bWJlciBsb3NlcyB0aGUgJy1uJyBlbmRpbmcuXG4gKiBlLmcuICdhbiAxMCBEZWVnJyBidXQgJ2EgNSBEZWVnJ1xuICpcbiAqIEBwYXJhbSBudW1iZXIge2ludGVnZXJ9XG4gKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAqL1xuZnVuY3Rpb24gZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKG51bWJlcikge1xuICAgIG51bWJlciA9IHBhcnNlSW50KG51bWJlciwgMTApO1xuICAgIGlmIChpc05hTihudW1iZXIpKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgICAgLy8gTmVnYXRpdmUgTnVtYmVyIC0tPiBhbHdheXMgdHJ1ZVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKG51bWJlciA8IDEwKSB7XG4gICAgICAgIC8vIE9ubHkgMSBkaWdpdFxuICAgICAgICBpZiAoNCA8PSBudW1iZXIgJiYgbnVtYmVyIDw9IDcpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2UgaWYgKG51bWJlciA8IDEwMCkge1xuICAgICAgICAvLyAyIGRpZ2l0c1xuICAgICAgICB2YXIgbGFzdERpZ2l0ID0gbnVtYmVyICUgMTAsIGZpcnN0RGlnaXQgPSBudW1iZXIgLyAxMDtcbiAgICAgICAgaWYgKGxhc3REaWdpdCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihmaXJzdERpZ2l0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKGxhc3REaWdpdCk7XG4gICAgfSBlbHNlIGlmIChudW1iZXIgPCAxMDAwMCkge1xuICAgICAgICAvLyAzIG9yIDQgZGlnaXRzIC0tPiByZWN1cnNpdmVseSBjaGVjayBmaXJzdCBkaWdpdFxuICAgICAgICB3aGlsZSAobnVtYmVyID49IDEwKSB7XG4gICAgICAgICAgICBudW1iZXIgPSBudW1iZXIgLyAxMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWlmZWxlclJlZ2VsQXBwbGllc1RvTnVtYmVyKG51bWJlcik7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQW55dGhpbmcgbGFyZ2VyIHRoYW4gNCBkaWdpdHM6IHJlY3Vyc2l2ZWx5IGNoZWNrIGZpcnN0IG4tMyBkaWdpdHNcbiAgICAgICAgbnVtYmVyID0gbnVtYmVyIC8gMTAwMDtcbiAgICAgICAgcmV0dXJuIGVpZmVsZXJSZWdlbEFwcGxpZXNUb051bWJlcihudW1iZXIpO1xuICAgIH1cbn1cblxudmFyIGxiID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbGInLCB7XG4gICAgbW9udGhzOiAnSmFudWFyX0ZlYnJ1YXJfTcOkZXJ6X0FicsOrbGxfTWVlX0p1bmlfSnVsaV9BdWd1c3RfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGV6ZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQ6ICdKYW4uX0ZlYnIuX01yei5fQWJyLl9NZWVfSnVuLl9KdWwuX0F1Zy5fU2VwdC5fT2t0Ll9Ob3YuX0Rlei4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXM6ICdTb25uZGVnX03DqWluZGVnX0TDq25zY2hkZWdfTcOrdHR3b2NoX0Rvbm5lc2NoZGVnX0ZyZWlkZWdfU2Ftc2NoZGVnJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQ6ICdTby5fTcOpLl9Ew6suX03Dqy5fRG8uX0ZyLl9TYS4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW46ICdTb19Nw6lfRMOrX03Dq19Eb19Gcl9TYScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgIExUOiAnSDptbSBbQXVlcl0nLFxuICAgICAgICBMVFM6ICdIOm1tOnNzIFtBdWVyXScsXG4gICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSDptbSBbQXVlcl0nLFxuICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0gW0F1ZXJdJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1tIYXV0IHVtXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCcsXG4gICAgICAgIG5leHREYXk6ICdbTXVlciB1bV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3VtXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbR8Orc2NodGVyIHVtXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvLyBEaWZmZXJlbnQgZGF0ZSBzdHJpbmcgZm9yICdEw6tuc2NoZGVnJyAoVHVlc2RheSkgYW5kICdEb25uZXNjaGRlZycgKFRodXJzZGF5KSBkdWUgdG8gcGhvbm9sb2dpY2FsIHJ1bGVcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW0xlc2NodGVuXSBkZGRkIFt1bV0gTFQnO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW0xlc2NodGVdIGRkZGQgW3VtXSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogcHJvY2Vzc0Z1dHVyZVRpbWUsXG4gICAgICAgIHBhc3QgOiBwcm9jZXNzUGFzdFRpbWUsXG4gICAgICAgIHMgOiAnZSBwdWVyIFNla29ubmVuJyxcbiAgICAgICAgc3MgOiAnJWQgU2Vrb25uZW4nLFxuICAgICAgICBtIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgbW0gOiAnJWQgTWludXR0ZW4nLFxuICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgaGggOiAnJWQgU3Rvbm5lbicsXG4gICAgICAgIGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBkZCA6ICclZCBEZWVnJyxcbiAgICAgICAgTSA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIE1NIDogJyVkIE3DqWludCcsXG4gICAgICAgIHkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICB5eSA6ICclZCBKb2VyJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsOiAnJWQuJyxcbiAgICB3ZWVrOiB7XG4gICAgICAgIGRvdzogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveTogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbGI7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2xiLmpzXG4vLyBtb2R1bGUgaWQgPSA2OVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTGFvIFtsb11cbi8vISBhdXRob3IgOiBSeWFuIEhhcnQgOiBodHRwczovL2dpdGh1Yi5jb20vcnlhbmhhcnQyXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIGxvID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbG8nLCB7XG4gICAgbW9udGhzIDogJ+C6oeC6seC6h+C6geC6reC6mV/guoHgurjguqHgup7gurJf4Lqh4Lq14LqZ4LqyX+C7gOC6oeC6quC6sl/gup7gurbgupTguqrgurDgup7gurJf4Lqh4Lq04LqW4Lq44LqZ4LqyX+C6geC7jeC6peC6sOC6geC6u+C6lF/guqrgurTguofguqvgurJf4LqB4Lqx4LqZ4LqN4LqyX+C6leC6uOC6peC6sl/gup7gurDguojgurTguoFf4LqX4Lqx4LqZ4Lqn4LqyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ+C6oeC6seC6h+C6geC6reC6mV/guoHgurjguqHgup7gurJf4Lqh4Lq14LqZ4LqyX+C7gOC6oeC6quC6sl/gup7gurbgupTguqrgurDgup7gurJf4Lqh4Lq04LqW4Lq44LqZ4LqyX+C6geC7jeC6peC6sOC6geC6u+C6lF/guqrgurTguofguqvgurJf4LqB4Lqx4LqZ4LqN4LqyX+C6leC6uOC6peC6sl/gup7gurDguojgurTguoFf4LqX4Lqx4LqZ4Lqn4LqyJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ+C6reC6suC6l+C6tOC6lF/guojgurHguplf4Lqt4Lqx4LqH4LqE4Lqy4LqZX+C6nuC6uOC6lF/gup7gurDguqvgurHgupRf4Lqq4Lq44LqBX+C7gOC6quC6u+C6sicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+C6l+C6tOC6lF/guojgurHguplf4Lqt4Lqx4LqH4LqE4Lqy4LqZX+C6nuC6uOC6lF/gup7gurDguqvgurHgupRf4Lqq4Lq44LqBX+C7gOC6quC6u+C6sicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfgupdf4LqIX+C6reC6hF/gup5f4Lqe4LqrX+C6quC6gV/guqonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAn4Lqn4Lqx4LqZZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/gupXguq3gupngu4Dguorgurvgu4ngurJ84LqV4Lqt4LqZ4LuB4Lql4LqHLyxcbiAgICBpc1BNOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn4LqV4Lqt4LqZ4LuB4Lql4LqHJztcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C6leC6reC6meC7gOC6iuC6u+C7ieC6sic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ+C6leC6reC6meC7geC6peC6hyc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vguqHgurfgu4ngupngurXgu4ngu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4Lqh4Lq34LuJ4Lqt4Lq34LuI4LqZ4LuA4Lqn4Lql4LqyXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1vguqfgurHgupldZGRkZFvgu5zgu4ngurLgu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4Lqh4Lq34LuJ4Lqn4Lqy4LqZ4LqZ4Lq14LuJ4LuA4Lqn4Lql4LqyXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vguqfgurHgupldZGRkZFvgu4HguqXgu4nguqfgupngurXgu4ngu4DguqfguqXgurJdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ+C6reC6teC6gSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXPgupzgu4jgurLgupnguqHgurInLFxuICAgICAgICBzIDogJ+C6muC7jeC7iOC7gOC6l+C6u+C7iOC6suC7g+C6lOC6p+C6tOC6meC6suC6l+C6tScsXG4gICAgICAgIHNzIDogJyVkIOC6p+C6tOC6meC6suC6l+C6tScgLFxuICAgICAgICBtIDogJzEg4LqZ4Lqy4LqX4Lq1JyxcbiAgICAgICAgbW0gOiAnJWQg4LqZ4Lqy4LqX4Lq1JyxcbiAgICAgICAgaCA6ICcxIOC6iuC6u+C7iOC6p+C7guC6oeC6hycsXG4gICAgICAgIGhoIDogJyVkIOC6iuC6u+C7iOC6p+C7guC6oeC6hycsXG4gICAgICAgIGQgOiAnMSDguqHgurfgu4knLFxuICAgICAgICBkZCA6ICclZCDguqHgurfgu4knLFxuICAgICAgICBNIDogJzEg4LuA4LqU4Lq34Lqt4LqZJyxcbiAgICAgICAgTU0gOiAnJWQg4LuA4LqU4Lq34Lqt4LqZJyxcbiAgICAgICAgeSA6ICcxIOC6m+C6tScsXG4gICAgICAgIHl5IDogJyVkIOC6m+C6tSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC8o4LqX4Lq14LuIKVxcZHsxLDJ9LyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gJ+C6l+C6teC7iCcgKyBudW1iZXI7XG4gICAgfVxufSk7XG5cbnJldHVybiBsbztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvbG8uanNcbi8vIG1vZHVsZSBpZCA9IDcwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBMaXRodWFuaWFuIFtsdF1cbi8vISBhdXRob3IgOiBNaW5kYXVnYXMgTW96xatyYXMgOiBodHRwczovL2dpdGh1Yi5jb20vbW1venVyYXNcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgdW5pdHMgPSB7XG4gICAgJ3NzJyA6ICdzZWt1bmTEl19zZWt1bmTFvmnFs19zZWt1bmRlcycsXG4gICAgJ20nIDogJ21pbnV0xJdfbWludXTEl3NfbWludXTEmScsXG4gICAgJ21tJzogJ21pbnV0xJdzX21pbnXEjWnFs19taW51dGVzJyxcbiAgICAnaCcgOiAndmFsYW5kYV92YWxhbmRvc192YWxhbmTEhScsXG4gICAgJ2hoJzogJ3ZhbGFuZG9zX3ZhbGFuZMWzX3ZhbGFuZGFzJyxcbiAgICAnZCcgOiAnZGllbmFfZGllbm9zX2RpZW7EhScsXG4gICAgJ2RkJzogJ2RpZW5vc19kaWVuxbNfZGllbmFzJyxcbiAgICAnTScgOiAnbcSXbnVvX23El25lc2lvX23El25lc8SvJyxcbiAgICAnTU0nOiAnbcSXbmVzaWFpX23El25lc2nFs19txJduZXNpdXMnLFxuICAgICd5JyA6ICdtZXRhaV9tZXTFs19tZXR1cycsXG4gICAgJ3l5JzogJ21ldGFpX21ldMWzX21ldHVzJ1xufTtcbmZ1bmN0aW9uIHRyYW5zbGF0ZVNlY29uZHMobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXksIGlzRnV0dXJlKSB7XG4gICAgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuICdrZWxpb3Mgc2VrdW5kxJdzJztcbiAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gaXNGdXR1cmUgPyAna2VsacWzIHNla3VuZMW+acWzJyA6ICdrZWxpYXMgc2VrdW5kZXMnO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHRyYW5zbGF0ZVNpbmd1bGFyKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gZm9ybXMoa2V5KVswXSA6IChpc0Z1dHVyZSA/IGZvcm1zKGtleSlbMV0gOiBmb3JtcyhrZXkpWzJdKTtcbn1cbmZ1bmN0aW9uIHNwZWNpYWwobnVtYmVyKSB7XG4gICAgcmV0dXJuIG51bWJlciAlIDEwID09PSAwIHx8IChudW1iZXIgPiAxMCAmJiBudW1iZXIgPCAyMCk7XG59XG5mdW5jdGlvbiBmb3JtcyhrZXkpIHtcbiAgICByZXR1cm4gdW5pdHNba2V5XS5zcGxpdCgnXycpO1xufVxuZnVuY3Rpb24gdHJhbnNsYXRlKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICByZXR1cm4gcmVzdWx0ICsgdHJhbnNsYXRlU2luZ3VsYXIobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXlbMF0sIGlzRnV0dXJlKTtcbiAgICB9IGVsc2UgaWYgKHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdCArIChzcGVjaWFsKG51bWJlcikgPyBmb3JtcyhrZXkpWzFdIDogZm9ybXMoa2V5KVswXSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGlzRnV0dXJlKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgZm9ybXMoa2V5KVsxXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAoc3BlY2lhbChudW1iZXIpID8gZm9ybXMoa2V5KVsxXSA6IGZvcm1zKGtleSlbMl0pO1xuICAgICAgICB9XG4gICAgfVxufVxudmFyIGx0ID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbHQnLCB7XG4gICAgbW9udGhzIDoge1xuICAgICAgICBmb3JtYXQ6ICdzYXVzaW9fdmFzYXJpb19rb3ZvX2JhbGFuZMW+aW9fZ2VndcW+xJdzX2JpcsW+ZWxpb19saWVwb3NfcnVncGrFq8SNaW9fcnVnc8SXam9fc3BhbGlvX2xhcGtyacSNaW9fZ3J1b2TFvmlvJy5zcGxpdCgnXycpLFxuICAgICAgICBzdGFuZGFsb25lOiAnc2F1c2lzX3Zhc2FyaXNfa292YXNfYmFsYW5kaXNfZ2VndcW+xJdfYmlyxb5lbGlzX2xpZXBhX3J1Z3Bqxat0aXNfcnVnc8SXamlzX3NwYWxpc19sYXBrcml0aXNfZ3J1b2Rpcycuc3BsaXQoJ18nKSxcbiAgICAgICAgaXNGb3JtYXQ6IC9EW29EXT8oXFxbW15cXFtcXF1dKlxcXXxcXHMpK01NTU0/fE1NTU0/KFxcW1teXFxbXFxdXSpcXF18XFxzKStEW29EXT8vXG4gICAgfSxcbiAgICBtb250aHNTaG9ydCA6ICdzYXVfdmFzX2tvdl9iYWxfZ2VnX2Jpcl9saWVfcmdwX3Jnc19zcGFfbGFwX2dyZCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6IHtcbiAgICAgICAgZm9ybWF0OiAnc2VrbWFkaWVuxK9fcGlybWFkaWVuxK9fYW50cmFkaWVuxK9fdHJlxI1pYWRpZW7Er19rZXR2aXJ0YWRpZW7Er19wZW5rdGFkaWVuxK9fxaFlxaF0YWRpZW7Erycuc3BsaXQoJ18nKSxcbiAgICAgICAgc3RhbmRhbG9uZTogJ3Nla21hZGllbmlzX3Bpcm1hZGllbmlzX2FudHJhZGllbmlzX3RyZcSNaWFkaWVuaXNfa2V0dmlydGFkaWVuaXNfcGVua3RhZGllbmlzX8WhZcWhdGFkaWVuaXMnLnNwbGl0KCdfJyksXG4gICAgICAgIGlzRm9ybWF0OiAvZGRkZCBISDptbS9cbiAgICB9LFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnU2VrX1Bpcl9BbnRfVHJlX0tldF9QZW5fxaBlxaEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU19QX0FfVF9LX1BuX8WgJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgTEwgOiAnWVlZWSBbbS5dIE1NTU0gRCBbZC5dJyxcbiAgICAgICAgTExMIDogJ1lZWVkgW20uXSBNTU1NIEQgW2QuXSwgSEg6bW0gW3ZhbC5dJyxcbiAgICAgICAgTExMTCA6ICdZWVlZIFttLl0gTU1NTSBEIFtkLl0sIGRkZGQsIEhIOm1tIFt2YWwuXScsXG4gICAgICAgIGwgOiAnWVlZWS1NTS1ERCcsXG4gICAgICAgIGxsIDogJ1lZWVkgW20uXSBNTU1NIEQgW2QuXScsXG4gICAgICAgIGxsbCA6ICdZWVlZIFttLl0gTU1NTSBEIFtkLl0sIEhIOm1tIFt2YWwuXScsXG4gICAgICAgIGxsbGwgOiAnWVlZWSBbbS5dIE1NTU0gRCBbZC5dLCBkZGQsIEhIOm1tIFt2YWwuXSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vFoGlhbmRpZW5dIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbUnl0b2pdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW1Zha2FyXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tQcmHEl2p1c8SvXSBkZGRkIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3BvICVzJyxcbiAgICAgICAgcGFzdCA6ICdwcmllxaEgJXMnLFxuICAgICAgICBzIDogdHJhbnNsYXRlU2Vjb25kcyxcbiAgICAgICAgc3MgOiB0cmFuc2xhdGUsXG4gICAgICAgIG0gOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgbW0gOiB0cmFuc2xhdGUsXG4gICAgICAgIGggOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgaGggOiB0cmFuc2xhdGUsXG4gICAgICAgIGQgOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgZGQgOiB0cmFuc2xhdGUsXG4gICAgICAgIE0gOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgTU0gOiB0cmFuc2xhdGUsXG4gICAgICAgIHkgOiB0cmFuc2xhdGVTaW5ndWxhcixcbiAgICAgICAgeXkgOiB0cmFuc2xhdGVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS1vamkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAnLW9qaSc7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbHQ7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL2x0LmpzXG4vLyBtb2R1bGUgaWQgPSA3MVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTGF0dmlhbiBbbHZdXG4vLyEgYXV0aG9yIDogS3Jpc3RhcHMgS2FybHNvbnMgOiBodHRwczovL2dpdGh1Yi5jb20vc2tha3JpXG4vLyEgYXV0aG9yIDogSsSBbmlzIEVsbWVyaXMgOiBodHRwczovL2dpdGh1Yi5jb20vSmFuaXNFXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHVuaXRzID0ge1xuICAgICdzcyc6ICdzZWt1bmRlc19zZWt1bmTEk21fc2VrdW5kZV9zZWt1bmRlcycuc3BsaXQoJ18nKSxcbiAgICAnbSc6ICdtaW7Fq3Rlc19taW7Fq3TEk21fbWluxat0ZV9taW7Fq3Rlcycuc3BsaXQoJ18nKSxcbiAgICAnbW0nOiAnbWluxat0ZXNfbWluxat0xJNtX21pbsWrdGVfbWluxat0ZXMnLnNwbGl0KCdfJyksXG4gICAgJ2gnOiAnc3R1bmRhc19zdHVuZMSBbV9zdHVuZGFfc3R1bmRhcycuc3BsaXQoJ18nKSxcbiAgICAnaGgnOiAnc3R1bmRhc19zdHVuZMSBbV9zdHVuZGFfc3R1bmRhcycuc3BsaXQoJ18nKSxcbiAgICAnZCc6ICdkaWVuYXNfZGllbsSBbV9kaWVuYV9kaWVuYXMnLnNwbGl0KCdfJyksXG4gICAgJ2RkJzogJ2RpZW5hc19kaWVuxIFtX2RpZW5hX2RpZW5hcycuc3BsaXQoJ18nKSxcbiAgICAnTSc6ICdtxJNuZcWhYV9txJNuZcWhaWVtX23Ek25lc2lzX23Ek25lxaFpJy5zcGxpdCgnXycpLFxuICAgICdNTSc6ICdtxJNuZcWhYV9txJNuZcWhaWVtX23Ek25lc2lzX23Ek25lxaFpJy5zcGxpdCgnXycpLFxuICAgICd5JzogJ2dhZGFfZ2FkaWVtX2dhZHNfZ2FkaScuc3BsaXQoJ18nKSxcbiAgICAneXknOiAnZ2FkYV9nYWRpZW1fZ2Fkc19nYWRpJy5zcGxpdCgnXycpXG59O1xuLyoqXG4gKiBAcGFyYW0gd2l0aG91dFN1ZmZpeCBib29sZWFuIHRydWUgPSBhIGxlbmd0aCBvZiB0aW1lOyBmYWxzZSA9IGJlZm9yZS9hZnRlciBhIHBlcmlvZCBvZiB0aW1lLlxuICovXG5mdW5jdGlvbiBmb3JtYXQoZm9ybXMsIG51bWJlciwgd2l0aG91dFN1ZmZpeCkge1xuICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgIC8vIEUuZy4gXCIyMSBtaW7Fq3RlXCIsIFwiMyBtaW7Fq3Rlc1wiLlxuICAgICAgICByZXR1cm4gbnVtYmVyICUgMTAgPT09IDEgJiYgbnVtYmVyICUgMTAwICE9PSAxMSA/IGZvcm1zWzJdIDogZm9ybXNbM107XG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRS5nLiBcIjIxIG1pbsWrdGVzXCIgYXMgaW4gXCJwxJNjIDIxIG1pbsWrdGVzXCIuXG4gICAgICAgIC8vIEUuZy4gXCIzIG1pbsWrdMSTbVwiIGFzIGluIFwicMSTYyAzIG1pbsWrdMSTbVwiLlxuICAgICAgICByZXR1cm4gbnVtYmVyICUgMTAgPT09IDEgJiYgbnVtYmVyICUgMTAwICE9PSAxMSA/IGZvcm1zWzBdIDogZm9ybXNbMV07XG4gICAgfVxufVxuZnVuY3Rpb24gcmVsYXRpdmVUaW1lV2l0aFBsdXJhbChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgIHJldHVybiBudW1iZXIgKyAnICcgKyBmb3JtYXQodW5pdHNba2V5XSwgbnVtYmVyLCB3aXRob3V0U3VmZml4KTtcbn1cbmZ1bmN0aW9uIHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgIHJldHVybiBmb3JtYXQodW5pdHNba2V5XSwgbnVtYmVyLCB3aXRob3V0U3VmZml4KTtcbn1cbmZ1bmN0aW9uIHJlbGF0aXZlU2Vjb25kcyhudW1iZXIsIHdpdGhvdXRTdWZmaXgpIHtcbiAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdkYcW+YXMgc2VrdW5kZXMnIDogJ2Rhxb7EgW0gc2VrdW5kxJNtJztcbn1cblxudmFyIGx2ID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbHYnLCB7XG4gICAgbW9udGhzIDogJ2phbnbEgXJpc19mZWJydcSBcmlzX21hcnRzX2FwcsSrbGlzX21haWpzX2rFq25panNfasWrbGlqc19hdWd1c3RzX3NlcHRlbWJyaXNfb2t0b2JyaXNfbm92ZW1icmlzX2RlY2VtYnJpcycuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdqYW5fZmViX21hcl9hcHJfbWFpX2rFq25fasWrbF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3N2xJN0ZGllbmFfcGlybWRpZW5hX290cmRpZW5hX3RyZcWhZGllbmFfY2V0dXJ0ZGllbmFfcGlla3RkaWVuYV9zZXN0ZGllbmEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdTdl9QX09fVF9DX1BrX1MnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnU3ZfUF9PX1RfQ19Qa19TJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZLicsXG4gICAgICAgIExMIDogJ1lZWVkuIFtnYWRhXSBELiBNTU1NJyxcbiAgICAgICAgTExMIDogJ1lZWVkuIFtnYWRhXSBELiBNTU1NLCBISDptbScsXG4gICAgICAgIExMTEwgOiAnWVlZWS4gW2dhZGFdIEQuIE1NTU0sIGRkZGQsIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW8Wgb2RpZW4gcHVsa3N0ZW5dIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbUsSrdCBwdWxrc3Rlbl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtwdWxrc3Rlbl0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tWYWthciBwdWxrc3Rlbl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbUGFnxIFqdcWhxIFdIGRkZGQgW3B1bGtzdGVuXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdwxJNjICVzJyxcbiAgICAgICAgcGFzdCA6ICdwaXJtcyAlcycsXG4gICAgICAgIHMgOiByZWxhdGl2ZVNlY29uZHMsXG4gICAgICAgIHNzIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgbSA6IHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcixcbiAgICAgICAgbW0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBoIDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICBoaCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIGQgOiByZWxhdGl2ZVRpbWVXaXRoU2luZ3VsYXIsXG4gICAgICAgIGRkIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgTSA6IHJlbGF0aXZlVGltZVdpdGhTaW5ndWxhcixcbiAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICB5IDogcmVsYXRpdmVUaW1lV2l0aFNpbmd1bGFyLFxuICAgICAgICB5eSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWxcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBsdjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvbHYuanNcbi8vIG1vZHVsZSBpZCA9IDcyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBNb250ZW5lZ3JpbiBbbWVdXG4vLyEgYXV0aG9yIDogTWlvZHJhZyBOaWthxI0gPG1pb2RyYWdAcmVzdGFydGl0Lm1lPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taW9kcmFnbmlrYWNcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgdHJhbnNsYXRvciA9IHtcbiAgICB3b3JkczogeyAvL0RpZmZlcmVudCBncmFtbWF0aWNhbCBjYXNlc1xuICAgICAgICBzczogWydzZWt1bmQnLCAnc2VrdW5kYScsICdzZWt1bmRpJ10sXG4gICAgICAgIG06IFsnamVkYW4gbWludXQnLCAnamVkbm9nIG1pbnV0YSddLFxuICAgICAgICBtbTogWydtaW51dCcsICdtaW51dGEnLCAnbWludXRhJ10sXG4gICAgICAgIGg6IFsnamVkYW4gc2F0JywgJ2plZG5vZyBzYXRhJ10sXG4gICAgICAgIGhoOiBbJ3NhdCcsICdzYXRhJywgJ3NhdGknXSxcbiAgICAgICAgZGQ6IFsnZGFuJywgJ2RhbmEnLCAnZGFuYSddLFxuICAgICAgICBNTTogWydtamVzZWMnLCAnbWplc2VjYScsICdtamVzZWNpJ10sXG4gICAgICAgIHl5OiBbJ2dvZGluYScsICdnb2RpbmUnLCAnZ29kaW5hJ11cbiAgICB9LFxuICAgIGNvcnJlY3RHcmFtbWF0aWNhbENhc2U6IGZ1bmN0aW9uIChudW1iZXIsIHdvcmRLZXkpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciA9PT0gMSA/IHdvcmRLZXlbMF0gOiAobnVtYmVyID49IDIgJiYgbnVtYmVyIDw9IDQgPyB3b3JkS2V5WzFdIDogd29yZEtleVsyXSk7XG4gICAgfSxcbiAgICB0cmFuc2xhdGU6IGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICB2YXIgd29yZEtleSA9IHRyYW5zbGF0b3Iud29yZHNba2V5XTtcbiAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gd29yZEtleVswXSA6IHdvcmRLZXlbMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgdHJhbnNsYXRvci5jb3JyZWN0R3JhbW1hdGljYWxDYXNlKG51bWJlciwgd29yZEtleSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG52YXIgbWUgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdtZScsIHtcbiAgICBtb250aHM6ICdqYW51YXJfZmVicnVhcl9tYXJ0X2FwcmlsX21hal9qdW5fanVsX2F2Z3VzdF9zZXB0ZW1iYXJfb2t0b2Jhcl9ub3ZlbWJhcl9kZWNlbWJhcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydDogJ2phbi5fZmViLl9tYXIuX2Fwci5fbWFqX2p1bl9qdWxfYXZnLl9zZXAuX29rdC5fbm92Ll9kZWMuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzOiAnbmVkamVsamFfcG9uZWRqZWxqYWtfdXRvcmFrX3NyaWplZGFfxI1ldHZydGFrX3BldGFrX3N1Ym90YScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0OiAnbmVkLl9wb24uX3V0by5fc3JpLl/EjWV0Ll9wZXQuX3N1Yi4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW46ICduZV9wb191dF9zcl/EjWVfcGVfc3UnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEw6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEw6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEw6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEw6ICdkZGRkLCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbZGFuYXMgdV0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW3NqdXRyYSB1XSBMVCcsXG5cbiAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW25lZGplbGp1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gW3NyaWplZHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbc3Vib3R1XSBbdV0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdV0gZGRkZCBbdV0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5ICA6ICdbanXEjWUgdV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBsYXN0V2Vla0RheXMgPSBbXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbbmVkamVsamVdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxvZ10gW3BvbmVkamVsamthXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFt1dG9ya2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3JpamVkZV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAnW3Byb8WhbG9nXSBbxI1ldHZydGthXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFtwZXRrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAnW3Byb8WhbGVdIFtzdWJvdGVdIFt1XSBMVCdcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICByZXR1cm4gbGFzdFdlZWtEYXlzW3RoaXMuZGF5KCldO1xuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnemEgJXMnLFxuICAgICAgICBwYXN0ICAgOiAncHJpamUgJXMnLFxuICAgICAgICBzICAgICAgOiAnbmVrb2xpa28gc2VrdW5kaScsXG4gICAgICAgIHNzICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBtICAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgbW0gICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIGggICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBoaCAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgZCAgICAgIDogJ2RhbicsXG4gICAgICAgIGRkICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBNICAgICAgOiAnbWplc2VjJyxcbiAgICAgICAgTU0gICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIHkgICAgICA6ICdnb2RpbnUnLFxuICAgICAgICB5eSAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIG1lO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9tZS5qc1xuLy8gbW9kdWxlIGlkID0gNzNcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IE1hb3JpIFttaV1cbi8vISBhdXRob3IgOiBKb2huIENvcnJpZ2FuIDxyb2JiaWVjbG9zZXRAZ21haWwuY29tPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb2huaWRlYWxcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbWkgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdtaScsIHtcbiAgICBtb250aHM6ICdLb2hpLXTEgXRlX0h1aS10YW5ndXJ1X1BvdXTFqy10ZS1yYW5naV9QYWVuZ2Etd2jEgXdoxIFfSGFyYXR1YV9QaXBpcmlfSMWNbmdvaW5nb2lfSGVyZS10dXJpLWvFjWvEgV9NYWh1cnVfV2hpcmluZ2EtxIEtbnVrdV9XaGlyaW5nYS3EgS1yYW5naV9IYWtpaGVhJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAnS29oaV9IdWlfUG91X1BhZV9IYXJhX1BpcGlfSMWNbmdvaV9IZXJlX01haHVfV2hpLW51X1doaS1yYV9IYWtpJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1JlZ2V4OiAvKD86WydhLXpcXHUwMTAxXFx1MDE0RFxcdTAxNkJdK1xcLT8pezEsM30vaSxcbiAgICBtb250aHNTdHJpY3RSZWdleDogLyg/OlsnYS16XFx1MDEwMVxcdTAxNERcXHUwMTZCXStcXC0/KXsxLDN9L2ksXG4gICAgbW9udGhzU2hvcnRSZWdleDogLyg/OlsnYS16XFx1MDEwMVxcdTAxNERcXHUwMTZCXStcXC0/KXsxLDN9L2ksXG4gICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogLyg/OlsnYS16XFx1MDEwMVxcdTAxNERcXHUwMTZCXStcXC0/KXsxLDJ9L2ksXG4gICAgd2Vla2RheXM6ICdSxIF0YXB1X01hbmVfVMWrcmVpX1dlbmVyZWlfVMSBaXRlX1BhcmFpcmVfSMSBdGFyZWknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydDogJ1RhX01hX1TFq19XZV9UxIFpX1BhX0jEgScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbjogJ1RhX01hX1TFq19XZV9UxIFpX1BhX0jEgScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdDoge1xuICAgICAgICBMVDogJ0hIOm1tJyxcbiAgICAgICAgTFRTOiAnSEg6bW06c3MnLFxuICAgICAgICBMOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEw6ICdEIE1NTU0gWVlZWSBbaV0gSEg6bW0nLFxuICAgICAgICBMTExMOiAnZGRkZCwgRCBNTU1NIFlZWVkgW2ldIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1tpIHRlaWUgbWFoYW5hLCBpXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbYXBvcG8gaV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2ldIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tpbmFuYWhpIGldIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFt3aGFrYW11dHVuZ2EgaV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWU6IHtcbiAgICAgICAgZnV0dXJlOiAnaSByb3RvIGkgJXMnLFxuICAgICAgICBwYXN0OiAnJXMgaSBtdWEnLFxuICAgICAgICBzOiAndGUgaMSTa29uYSBydWFydWEnLFxuICAgICAgICBzczogJyVkIGjEk2tvbmEnLFxuICAgICAgICBtOiAnaGUgbWVuZXRpJyxcbiAgICAgICAgbW06ICclZCBtZW5ldGknLFxuICAgICAgICBoOiAndGUgaGFvcmEnLFxuICAgICAgICBoaDogJyVkIGhhb3JhJyxcbiAgICAgICAgZDogJ2hlIHJhJyxcbiAgICAgICAgZGQ6ICclZCByYScsXG4gICAgICAgIE06ICdoZSBtYXJhbWEnLFxuICAgICAgICBNTTogJyVkIG1hcmFtYScsXG4gICAgICAgIHk6ICdoZSB0YXUnLFxuICAgICAgICB5eTogJyVkIHRhdSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICBvcmRpbmFsOiAnJWTCuicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIG1pO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9taS5qc1xuLy8gbW9kdWxlIGlkID0gNzRcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IE1hY2Vkb25pYW4gW21rXVxuLy8hIGF1dGhvciA6IEJvcmlzbGF2IE1pY2tvdiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9CMGswXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIG1rID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbWsnLCB7XG4gICAgbW9udGhzIDogJ9GY0LDQvdGD0LDRgNC4X9GE0LXQstGA0YPQsNGA0Lhf0LzQsNGA0YJf0LDQv9GA0LjQu1/QvNCw0Zhf0ZjRg9C90Lhf0ZjRg9C70Lhf0LDQstCz0YPRgdGCX9GB0LXQv9GC0LXQvNCy0YDQuF/QvtC60YLQvtC80LLRgNC4X9C90L7QtdC80LLRgNC4X9C00LXQutC10LzQstGA0LgnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn0ZjQsNC9X9GE0LXQsl/QvNCw0YBf0LDQv9GAX9C80LDRmF/RmNGD0L1f0ZjRg9C7X9Cw0LLQs1/RgdC10L9f0L7QutGCX9C90L7QtV/QtNC10LonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn0L3QtdC00LXQu9CwX9C/0L7QvdC10LTQtdC70L3QuNC6X9Cy0YLQvtGA0L3QuNC6X9GB0YDQtdC00LBf0YfQtdGC0LLRgNGC0L7Qul/Qv9C10YLQvtC6X9GB0LDQsdC+0YLQsCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9C90LXQtF/Qv9C+0L1f0LLRgtC+X9GB0YDQtV/Rh9C10YJf0L/QtdGCX9GB0LDQsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfQvWVf0L9vX9Cy0YJf0YHRgF/Rh9C1X9C/0LVf0YFhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0QuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb0JTQtdC90LXRgSDQstC+XSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW9Cj0YLRgNC1INCy0L5dIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW9CS0L5dIGRkZGQgW9Cy0L5dIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb0JLRh9C10YDQsCDQstC+XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CY0LfQvNC40L3QsNGC0LDRgtCwXSBkZGRkIFvQstC+XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQmNC30LzQuNC90LDRgtC40L7Rgl0gZGRkZCBb0LLQvl0gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn0L/QvtGB0LvQtSAlcycsXG4gICAgICAgIHBhc3QgOiAn0L/RgNC10LQgJXMnLFxuICAgICAgICBzIDogJ9C90LXQutC+0LvQutGDINGB0LXQutGD0L3QtNC4JyxcbiAgICAgICAgc3MgOiAnJWQg0YHQtdC60YPQvdC00LgnLFxuICAgICAgICBtIDogJ9C80LjQvdGD0YLQsCcsXG4gICAgICAgIG1tIDogJyVkINC80LjQvdGD0YLQuCcsXG4gICAgICAgIGggOiAn0YfQsNGBJyxcbiAgICAgICAgaGggOiAnJWQg0YfQsNGB0LAnLFxuICAgICAgICBkIDogJ9C00LXQvScsXG4gICAgICAgIGRkIDogJyVkINC00LXQvdCwJyxcbiAgICAgICAgTSA6ICfQvNC10YHQtdGGJyxcbiAgICAgICAgTU0gOiAnJWQg0LzQtdGB0LXRhtC4JyxcbiAgICAgICAgeSA6ICfQs9C+0LTQuNC90LAnLFxuICAgICAgICB5eSA6ICclZCDQs9C+0LTQuNC90LgnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNC10LJ80LXQvXzRgtC4fNCy0Lh80YDQuHzQvNC4KS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgdmFyIGxhc3REaWdpdCA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgbGFzdDJEaWdpdHMgPSBudW1iZXIgJSAxMDA7XG4gICAgICAgIGlmIChudW1iZXIgPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdC10LInO1xuICAgICAgICB9IGVsc2UgaWYgKGxhc3QyRGlnaXRzID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QtdC9JztcbiAgICAgICAgfSBlbHNlIGlmIChsYXN0MkRpZ2l0cyA+IDEwICYmIGxhc3QyRGlnaXRzIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICB9IGVsc2UgaWYgKGxhc3REaWdpdCA9PT0gMSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0LLQuCc7XG4gICAgICAgIH0gZWxzZSBpZiAobGFzdERpZ2l0ID09PSAyKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3RgNC4JztcbiAgICAgICAgfSBlbHNlIGlmIChsYXN0RGlnaXQgPT09IDcgfHwgbGFzdERpZ2l0ID09PSA4KSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QvNC4JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAnLdGC0LgnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbWs7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL21rLmpzXG4vLyBtb2R1bGUgaWQgPSA3NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTWFsYXlhbGFtIFttbF1cbi8vISBhdXRob3IgOiBGbG95ZCBQaW5rIDogaHR0cHM6Ly9naXRodWIuY29tL2Zsb3lkcGlua1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBtbCA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ21sJywge1xuICAgIG1vbnRocyA6ICfgtJzgtKjgtYHgtLXgtLDgtL9f4LSr4LWG4LSs4LWN4LSw4LWB4LS14LSw4LS/X+C0ruC0vuC1vOC0muC1jeC0muC1jV/gtI/gtKrgtY3gtLDgtL/gtb1f4LSu4LWH4LSv4LWNX+C0nOC1guC1ul/gtJzgtYLgtLLgtYhf4LST4LSX4LS44LWN4LSx4LWN4LSx4LWNX+C0uOC1huC0quC1jeC0seC1jeC0seC0guC0rOC1vF/gtJLgtJXgtY3gtJ/gtYvgtKzgtbxf4LSo4LS14LSC4LSs4LW8X+C0oeC0v+C0uOC0guC0rOC1vCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgtJzgtKjgtYEuX+C0q+C1huC0rOC1jeC0sOC1gS5f4LSu4LS+4LW8Ll/gtI/gtKrgtY3gtLDgtL8uX+C0ruC1h+C0r+C1jV/gtJzgtYLgtbpf4LSc4LWC4LSy4LWILl/gtJPgtJcuX+C0uOC1huC0quC1jeC0seC1jeC0sS5f4LSS4LSV4LWN4LSf4LWLLl/gtKjgtLXgtIIuX+C0oeC0v+C0uOC0gi4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAn4LSe4LS+4LSv4LSx4LS+4LS04LWN4LSaX+C0pOC0v+C0meC1jeC0leC0s+C0vuC0tOC1jeC0ml/gtJrgtYrgtLXgtY3gtLXgtL7gtLTgtY3gtJpf4LSs4LWB4LSn4LSo4LS+4LS04LWN4LSaX+C0teC1jeC0r+C0vuC0tOC0vuC0tOC1jeC0ml/gtLXgtYbgtLPgtY3gtLPgtL/gtK/gtL7gtLTgtY3gtJpf4LS24LSo4LS/4LSv4LS+4LS04LWN4LSaJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4LSe4LS+4LSv4LW8X+C0pOC0v+C0meC1jeC0leC1vl/gtJrgtYrgtLXgtY3gtLVf4LSs4LWB4LSn4LW7X+C0teC1jeC0r+C0vuC0tOC0gl/gtLXgtYbgtLPgtY3gtLPgtL9f4LS24LSo4LS/Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+C0nuC0vl/gtKTgtL9f4LSa4LWKX+C0rOC1gV/gtLXgtY3gtK/gtL5f4LS14LWGX+C0ticuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnQSBoOm1tIC3gtKjgtYEnLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzIC3gtKjgtYEnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIC3gtKjgtYEnLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0gLeC0qOC1gSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgtIfgtKjgtY3gtKjgtY1dIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4LSo4LS+4LSz4LWGXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4LSH4LSo4LWN4LSo4LSy4LWGXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgtJXgtLTgtL/gtJ7gtY3gtJ5dIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIOC0leC0tOC0v+C0nuC1jeC0nuC1jScsXG4gICAgICAgIHBhc3QgOiAnJXMg4LSu4LWB4LW74LSq4LWNJyxcbiAgICAgICAgcyA6ICfgtIXgtb3gtKog4LSo4LS/4LSu4LS/4LS34LSZ4LWN4LSZ4LW+JyxcbiAgICAgICAgc3MgOiAnJWQg4LS44LWG4LSV4LWN4LSV4LW74LSh4LWNJyxcbiAgICAgICAgbSA6ICfgtJLgtLDgtYEg4LSu4LS/4LSo4LS/4LSx4LWN4LSx4LWNJyxcbiAgICAgICAgbW0gOiAnJWQg4LSu4LS/4LSo4LS/4LSx4LWN4LSx4LWNJyxcbiAgICAgICAgaCA6ICfgtJLgtLDgtYEg4LSu4LSj4LS/4LSV4LWN4LSV4LWC4LW8JyxcbiAgICAgICAgaGggOiAnJWQg4LSu4LSj4LS/4LSV4LWN4LSV4LWC4LW8JyxcbiAgICAgICAgZCA6ICfgtJLgtLDgtYEg4LSm4LS/4LS14LS44LSCJyxcbiAgICAgICAgZGQgOiAnJWQg4LSm4LS/4LS14LS44LSCJyxcbiAgICAgICAgTSA6ICfgtJLgtLDgtYEg4LSu4LS+4LS44LSCJyxcbiAgICAgICAgTU0gOiAnJWQg4LSu4LS+4LS44LSCJyxcbiAgICAgICAgeSA6ICfgtJLgtLDgtYEg4LS14LW84LS34LSCJyxcbiAgICAgICAgeXkgOiAnJWQg4LS14LW84LS34LSCJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+C0sOC0vuC0pOC1jeC0sOC0v3zgtLDgtL7gtLXgtL/gtLLgtYZ84LSJ4LSa4LWN4LSaIOC0leC0tOC0v+C0nuC1jeC0nuC1jXzgtLXgtYjgtJXgtYHgtKjgtY3gtKjgtYfgtLDgtIJ84LSw4LS+4LSk4LWN4LSw4LS/L2ksXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKChtZXJpZGllbSA9PT0gJ+C0sOC0vuC0pOC1jeC0sOC0vycgJiYgaG91ciA+PSA0KSB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn4LSJ4LSa4LWN4LSaIOC0leC0tOC0v+C0nuC1jeC0nuC1jScgfHxcbiAgICAgICAgICAgICAgICBtZXJpZGllbSA9PT0gJ+C0teC1iOC0leC1geC0qOC1jeC0qOC1h+C0sOC0gicpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfgtLDgtL7gtKTgtY3gtLDgtL8nO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMikge1xuICAgICAgICAgICAgcmV0dXJuICfgtLDgtL7gtLXgtL/gtLLgtYYnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfgtIngtJrgtY3gtJog4LSV4LS04LS/4LSe4LWN4LSe4LWNJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiAn4LS14LWI4LSV4LWB4LSo4LWN4LSo4LWH4LSw4LSCJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4LSw4LS+4LSk4LWN4LSw4LS/JztcbiAgICAgICAgfVxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbWw7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL21sLmpzXG4vLyBtb2R1bGUgaWQgPSA3NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTWFyYXRoaSBbbXJdXG4vLyEgYXV0aG9yIDogSGFyc2hhZCBLYWxlIDogaHR0cHM6Ly9naXRodWIuY29tL2thbGVodlxuLy8hIGF1dGhvciA6IFZpdmVrIEF0aGFseWUgOiBodHRwczovL2dpdGh1Yi5jb20vdm5hdGhhbHllXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHN5bWJvbE1hcCA9IHtcbiAgICAnMSc6ICfgpacnLFxuICAgICcyJzogJ+ClqCcsXG4gICAgJzMnOiAn4KWpJyxcbiAgICAnNCc6ICfgpaonLFxuICAgICc1JzogJ+ClqycsXG4gICAgJzYnOiAn4KWsJyxcbiAgICAnNyc6ICfgpa0nLFxuICAgICc4JzogJ+ClricsXG4gICAgJzknOiAn4KWvJyxcbiAgICAnMCc6ICfgpaYnXG59O1xudmFyIG51bWJlck1hcCA9IHtcbiAgICAn4KWnJzogJzEnLFxuICAgICfgpagnOiAnMicsXG4gICAgJ+ClqSc6ICczJyxcbiAgICAn4KWqJzogJzQnLFxuICAgICfgpasnOiAnNScsXG4gICAgJ+ClrCc6ICc2JyxcbiAgICAn4KWtJzogJzcnLFxuICAgICfgpa4nOiAnOCcsXG4gICAgJ+Clryc6ICc5JyxcbiAgICAn4KWmJzogJzAnXG59O1xuXG5mdW5jdGlvbiByZWxhdGl2ZVRpbWVNcihudW1iZXIsIHdpdGhvdXRTdWZmaXgsIHN0cmluZywgaXNGdXR1cmUpXG57XG4gICAgdmFyIG91dHB1dCA9ICcnO1xuICAgIGlmICh3aXRob3V0U3VmZml4KSB7XG4gICAgICAgIHN3aXRjaCAoc3RyaW5nKSB7XG4gICAgICAgICAgICBjYXNlICdzJzogb3V0cHV0ID0gJ+CkleCkvuCkueClgCDgpLjgpYfgpJXgpILgpKYnOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NzJzogb3V0cHV0ID0gJyVkIOCkuOClh+CkleCkguCkpic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbSc6IG91dHB1dCA9ICfgpI/gpJUg4KSu4KS/4KSo4KS/4KSfJzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtbSc6IG91dHB1dCA9ICclZCDgpK7gpL/gpKjgpL/gpJ/gpYcnOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2gnOiBvdXRwdXQgPSAn4KSP4KSVIOCkpOCkvuCkuCc7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaGgnOiBvdXRwdXQgPSAnJWQg4KSk4KS+4KS4JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkJzogb3V0cHV0ID0gJ+Ckj+CklSDgpKbgpL/gpLXgpLgnOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2RkJzogb3V0cHV0ID0gJyVkIOCkpuCkv+CkteCkuCc7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnTSc6IG91dHB1dCA9ICfgpI/gpJUg4KSu4KS54KS/4KSo4KS+JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdNTSc6IG91dHB1dCA9ICclZCDgpK7gpLngpL/gpKjgpYcnOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3knOiBvdXRwdXQgPSAn4KSP4KSVIOCkteCksOCljeCktyc7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAneXknOiBvdXRwdXQgPSAnJWQg4KS14KSw4KWN4KS34KWHJzsgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHN3aXRjaCAoc3RyaW5nKSB7XG4gICAgICAgICAgICBjYXNlICdzJzogb3V0cHV0ID0gJ+CkleCkvuCkueClgCDgpLjgpYfgpJXgpILgpKbgpL7gpIInOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NzJzogb3V0cHV0ID0gJyVkIOCkuOClh+CkleCkguCkpuCkvuCkgic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbSc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KSu4KS/4KSo4KS/4KSf4KS+JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtbSc6IG91dHB1dCA9ICclZCDgpK7gpL/gpKjgpL/gpJ/gpL7gpIInOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2gnOiBvdXRwdXQgPSAn4KSP4KSV4KS+IOCkpOCkvuCkuOCkvic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnaGgnOiBvdXRwdXQgPSAnJWQg4KSk4KS+4KS44KS+4KSCJzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkJzogb3V0cHV0ID0gJ+Ckj+CkleCkviDgpKbgpL/gpLXgpLjgpL4nOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2RkJzogb3V0cHV0ID0gJyVkIOCkpuCkv+CkteCkuOCkvuCkgic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnTSc6IG91dHB1dCA9ICfgpI/gpJXgpL4g4KSu4KS54KS/4KSo4KWN4KSv4KS+JzsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdNTSc6IG91dHB1dCA9ICclZCDgpK7gpLngpL/gpKjgpY3gpK/gpL7gpIInOyBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3knOiBvdXRwdXQgPSAn4KSP4KSV4KS+IOCkteCksOCljeCkt+Ckvic7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAneXknOiBvdXRwdXQgPSAnJWQg4KS14KSw4KWN4KS34KS+4KSCJzsgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG91dHB1dC5yZXBsYWNlKC8lZC9pLCBudW1iZXIpO1xufVxuXG52YXIgbXIgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdtcicsIHtcbiAgICBtb250aHMgOiAn4KSc4KS+4KSo4KWH4KS14KS+4KSw4KWAX+Ckq+Clh+CkrOCljeCksOClgeCkteCkvuCksOClgF/gpK7gpL7gpLDgpY3gpJpf4KSP4KSq4KWN4KSw4KS/4KSyX+CkruClh1/gpJzgpYLgpKhf4KSc4KWB4KSy4KWIX+CkkeCkl+CkuOCljeCkn1/gpLjgpKrgpY3gpJ/gpYfgpILgpKzgpLBf4KSR4KSV4KWN4KSf4KWL4KSs4KSwX+CkqOCli+CkteCljeCkueClh+CkguCkrOCksF/gpKHgpL/gpLjgpYfgpILgpKzgpLAnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQ6ICfgpJzgpL7gpKjgpYcuX+Ckq+Clh+CkrOCljeCksOClgS5f4KSu4KS+4KSw4KWN4KSaLl/gpI/gpKrgpY3gpLDgpL8uX+CkruClhy5f4KSc4KWC4KSoLl/gpJzgpYHgpLLgpYguX+CkkeCkly5f4KS44KSq4KWN4KSf4KWH4KSCLl/gpJHgpJXgpY3gpJ/gpYsuX+CkqOCli+CkteCljeCkueClh+Ckgi5f4KSh4KS/4KS44KWH4KSCLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICfgpLDgpLXgpL/gpLXgpL7gpLBf4KS44KWL4KSu4KS14KS+4KSwX+CkruCkguCkl+Cks+CkteCkvuCksF/gpKzgpYHgpKfgpLXgpL7gpLBf4KSX4KWB4KSw4KWC4KS14KS+4KSwX+CktuClgeCkleCljeCksOCkteCkvuCksF/gpLbgpKjgpL/gpLXgpL7gpLAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgpLDgpLXgpL9f4KS44KWL4KSuX+CkruCkguCkl+Cks1/gpKzgpYHgpKdf4KSX4KWB4KSw4KWCX+CktuClgeCkleCljeCksF/gpLbgpKjgpL8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4KSwX+CkuOCli1/gpK7gpIJf4KSs4KWBX+Ckl+ClgV/gpLbgpYFf4KS2Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0g4KS14KS+4KSc4KSk4KS+JyxcbiAgICAgICAgTFRTIDogJ0EgaDptbTpzcyDgpLXgpL7gpJzgpKTgpL4nLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQSBoOm1tIOCkteCkvuCknOCkpOCkvicsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSDgpLXgpL7gpJzgpKTgpL4nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb4KSG4KScXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW+CkieCkpuCljeCkr+Ckvl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkLCBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW+CkleCkvuCksl0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ1vgpK7gpL7gpJfgpYDgpLJdIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlOiAnJXPgpK7gpKfgpY3gpK/gpYcnLFxuICAgICAgICBwYXN0OiAnJXPgpKrgpYLgpLDgpY3gpLXgpYAnLFxuICAgICAgICBzOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgc3M6IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICBtOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgbW06IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICBoOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgaGg6IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICBkOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgZGQ6IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICBNOiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgTU06IHJlbGF0aXZlVGltZU1yLFxuICAgICAgICB5OiByZWxhdGl2ZVRpbWVNcixcbiAgICAgICAgeXk6IHJlbGF0aXZlVGltZU1yXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgpafgpajgpangpargpavgpazgpa3gpa7gpa/gpaZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXBbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/gpLDgpL7gpKTgpY3gpLDgpYB84KS44KSV4KS+4KSz4KWAfOCkpuClgeCkquCkvuCksOClgHzgpLjgpL7gpK/gpILgpJXgpL7gpLPgpYAvLFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+CksOCkvuCkpOCljeCksOClgCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgpLjgpJXgpL7gpLPgpYAnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkpuClgeCkquCkvuCksOClgCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkuOCkvuCkr+CkguCkleCkvuCks+ClgCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfgpLDgpL7gpKTgpY3gpLDgpYAnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgpLjgpJXgpL7gpLPgpYAnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfgpKbgpYHgpKrgpL7gpLDgpYAnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgpLjgpL7gpK/gpILgpJXgpL7gpLPgpYAnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfgpLDgpL7gpKTgpY3gpLDgpYAnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbXI7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL21yLmpzXG4vLyBtb2R1bGUgaWQgPSA3N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTWFsYXkgW21zXVxuLy8hIGF1dGhvciA6IFdlbGRhbiBKYW1pbGkgOiBodHRwczovL2dpdGh1Yi5jb20vd2VsZGFuXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIG1zID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbXMnLCB7XG4gICAgbW9udGhzIDogJ0phbnVhcmlfRmVicnVhcmlfTWFjX0FwcmlsX01laV9KdW5fSnVsYWlfT2dvc19TZXB0ZW1iZXJfT2t0b2Jlcl9Ob3ZlbWJlcl9EaXNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdKYW5fRmViX01hY19BcHJfTWVpX0p1bl9KdWxfT2dzX1NlcF9Pa3RfTm92X0Rpcycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdBaGFkX0lzbmluX1NlbGFzYV9SYWJ1X0toYW1pc19KdW1hYXRfU2FidHUnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdBaGRfSXNuX1NlbF9SYWJfS2hhX0p1bV9TYWInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnQWhfSXNfU2xfUmJfS21fSm1fU2InLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hILm1tJyxcbiAgICAgICAgTFRTIDogJ0hILm1tLnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVkgW3B1a3VsXSBISC5tbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC9wYWdpfHRlbmdhaGFyaXxwZXRhbmd8bWFsYW0vLFxuICAgIG1lcmlkaWVtSG91cjogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAncGFnaScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAndGVuZ2FoYXJpJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAncGV0YW5nJyB8fCBtZXJpZGllbSA9PT0gJ21hbGFtJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzIDwgMTEpIHtcbiAgICAgICAgICAgIHJldHVybiAncGFnaSc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgcmV0dXJuICd0ZW5nYWhhcmknO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTkpIHtcbiAgICAgICAgICAgIHJldHVybiAncGV0YW5nJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAnbWFsYW0nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbSGFyaSBpbmkgcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbRXNvayBwdWt1bF0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtwdWt1bF0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tLZWxtYXJpbiBwdWt1bF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtsZXBhcyBwdWt1bF0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnZGFsYW0gJXMnLFxuICAgICAgICBwYXN0IDogJyVzIHlhbmcgbGVwYXMnLFxuICAgICAgICBzIDogJ2JlYmVyYXBhIHNhYXQnLFxuICAgICAgICBzcyA6ICclZCBzYWF0JyxcbiAgICAgICAgbSA6ICdzZW1pbml0JyxcbiAgICAgICAgbW0gOiAnJWQgbWluaXQnLFxuICAgICAgICBoIDogJ3NlamFtJyxcbiAgICAgICAgaGggOiAnJWQgamFtJyxcbiAgICAgICAgZCA6ICdzZWhhcmknLFxuICAgICAgICBkZCA6ICclZCBoYXJpJyxcbiAgICAgICAgTSA6ICdzZWJ1bGFuJyxcbiAgICAgICAgTU0gOiAnJWQgYnVsYW4nLFxuICAgICAgICB5IDogJ3NldGFodW4nLFxuICAgICAgICB5eSA6ICclZCB0YWh1bidcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBtcztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvbXMuanNcbi8vIG1vZHVsZSBpZCA9IDc4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBNYWxheSBbbXMtbXldXG4vLyEgbm90ZSA6IERFUFJFQ0FURUQsIHRoZSBjb3JyZWN0IG9uZSBpcyBbbXNdXG4vLyEgYXV0aG9yIDogV2VsZGFuIEphbWlsaSA6IGh0dHBzOi8vZ2l0aHViLmNvbS93ZWxkYW5cblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbXNNeSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ21zLW15Jywge1xuICAgIG1vbnRocyA6ICdKYW51YXJpX0ZlYnJ1YXJpX01hY19BcHJpbF9NZWlfSnVuX0p1bGFpX09nb3NfU2VwdGVtYmVyX09rdG9iZXJfTm92ZW1iZXJfRGlzZW1iZXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX0ZlYl9NYWNfQXByX01laV9KdW5fSnVsX09nc19TZXBfT2t0X05vdl9EaXMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnQWhhZF9Jc25pbl9TZWxhc2FfUmFidV9LaGFtaXNfSnVtYWF0X1NhYnR1Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnQWhkX0lzbl9TZWxfUmFiX0toYV9KdW1fU2FiJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0FoX0lzX1NsX1JiX0ttX0ptX1NiJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISC5tbScsXG4gICAgICAgIExUUyA6ICdISC5tbS5zcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIFtwdWt1bF0gSEgubW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAvcGFnaXx0ZW5nYWhhcml8cGV0YW5nfG1hbGFtLyxcbiAgICBtZXJpZGllbUhvdXI6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ3BhZ2knKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3RlbmdhaGFyaScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ3BldGFuZycgfHwgbWVyaWRpZW0gPT09ICdtYWxhbScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VycyA8IDExKSB7XG4gICAgICAgICAgICByZXR1cm4gJ3BhZ2knO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXJzIDwgMTUpIHtcbiAgICAgICAgICAgIHJldHVybiAndGVuZ2FoYXJpJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VycyA8IDE5KSB7XG4gICAgICAgICAgICByZXR1cm4gJ3BldGFuZyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJ21hbGFtJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0hhcmkgaW5pIHB1a3VsXSBMVCcsXG4gICAgICAgIG5leHREYXkgOiAnW0Vzb2sgcHVrdWxdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbcHVrdWxdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbS2VsbWFyaW4gcHVrdWxdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnZGRkZCBbbGVwYXMgcHVrdWxdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2RhbGFtICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyB5YW5nIGxlcGFzJyxcbiAgICAgICAgcyA6ICdiZWJlcmFwYSBzYWF0JyxcbiAgICAgICAgc3MgOiAnJWQgc2FhdCcsXG4gICAgICAgIG0gOiAnc2VtaW5pdCcsXG4gICAgICAgIG1tIDogJyVkIG1pbml0JyxcbiAgICAgICAgaCA6ICdzZWphbScsXG4gICAgICAgIGhoIDogJyVkIGphbScsXG4gICAgICAgIGQgOiAnc2VoYXJpJyxcbiAgICAgICAgZGQgOiAnJWQgaGFyaScsXG4gICAgICAgIE0gOiAnc2VidWxhbicsXG4gICAgICAgIE1NIDogJyVkIGJ1bGFuJyxcbiAgICAgICAgeSA6ICdzZXRhaHVuJyxcbiAgICAgICAgeXkgOiAnJWQgdGFodW4nXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbXNNeTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvbXMtbXkuanNcbi8vIG1vZHVsZSBpZCA9IDc5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBNYWx0ZXNlIChNYWx0YSkgW210XVxuLy8hIGF1dGhvciA6IEFsZXNzYW5kcm8gTWFydWNjaWEgOiBodHRwczovL2dpdGh1Yi5jb20vYWxlc21hXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIG10ID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbXQnLCB7XG4gICAgbW9udGhzIDogJ0phbm5hcl9GcmFyX01hcnp1X0FwcmlsX01lamp1X8SgdW5qdV9MdWxqdV9Bd3dpc3N1X1NldHRlbWJydV9PdHR1YnJ1X05vdmVtYnJ1X0RpxItlbWJydScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdKYW5fRnJhX01hcl9BcHJfTWVqX8SgdW5fTHVsX0F3d19TZXRfT3R0X05vdl9EacSLJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0lsLcSmYWRkX0l0LVRuZWpuX0l0LVRsaWV0YV9MLUVyYmfEp2FfSWwtxKZhbWlzX0lsLcSgaW1nxKdhX0lzLVNpYnQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfEpmFkX1RuZV9UbGlfRXJiX8SmYW1fxKBpbV9TaWInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnxKZhX1RuX1RsX0VyX8SmYV/EoGlfU2knLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0lsbHVtIGZpbC1dTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tHxKdhZGEgZmlsLV1MVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW2ZpbC1dTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tJbC1iaWVyYcSnIGZpbC1dTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtsaSBnxKdhZGRhXSBbZmlsLV1MVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdm4oCZICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBpbHUnLFxuICAgICAgICBzIDogJ2Z0aXQgc2Vrb25kaScsXG4gICAgICAgIHNzIDogJyVkIHNla29uZGknLFxuICAgICAgICBtIDogJ21pbnV0YScsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0aScsXG4gICAgICAgIGggOiAnc2llZ8SnYScsXG4gICAgICAgIGhoIDogJyVkIHNpZWfEp2F0JyxcbiAgICAgICAgZCA6ICfEoXVybmF0YScsXG4gICAgICAgIGRkIDogJyVkIMShcmFuZXQnLFxuICAgICAgICBNIDogJ3hhaGFyJyxcbiAgICAgICAgTU0gOiAnJWQgeGh1cicsXG4gICAgICAgIHkgOiAnc2VuYScsXG4gICAgICAgIHl5IDogJyVkIHNuaSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAvXFxkezEsMn3Cui8sXG4gICAgb3JkaW5hbDogJyVkwronLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBtdDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvbXQuanNcbi8vIG1vZHVsZSBpZCA9IDgwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBCdXJtZXNlIFtteV1cbi8vISBhdXRob3IgOiBTcXVhciB0ZWFtLCBteXNxdWFyLmNvbVxuLy8hIGF1dGhvciA6IERhdmlkIFJvc3NlbGxhdCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9naG9sYWRyXG4vLyEgYXV0aG9yIDogVGluIEF1bmcgTGluIDogaHR0cHM6Ly9naXRodWIuY29tL3RoYW55YXd6aW5taW5cblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgc3ltYm9sTWFwID0ge1xuICAgICcxJzogJ+GBgScsXG4gICAgJzInOiAn4YGCJyxcbiAgICAnMyc6ICfhgYMnLFxuICAgICc0JzogJ+GBhCcsXG4gICAgJzUnOiAn4YGFJyxcbiAgICAnNic6ICfhgYYnLFxuICAgICc3JzogJ+GBhycsXG4gICAgJzgnOiAn4YGIJyxcbiAgICAnOSc6ICfhgYknLFxuICAgICcwJzogJ+GBgCdcbn07XG52YXIgbnVtYmVyTWFwID0ge1xuICAgICfhgYEnOiAnMScsXG4gICAgJ+GBgic6ICcyJyxcbiAgICAn4YGDJzogJzMnLFxuICAgICfhgYQnOiAnNCcsXG4gICAgJ+GBhSc6ICc1JyxcbiAgICAn4YGGJzogJzYnLFxuICAgICfhgYcnOiAnNycsXG4gICAgJ+GBiCc6ICc4JyxcbiAgICAn4YGJJzogJzknLFxuICAgICfhgYAnOiAnMCdcbn07XG5cbnZhciBteSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ215Jywge1xuICAgIG1vbnRoczogJ+GAh+GAlOGAuuGAlOGAneGAq+GAm+GArl/hgJbhgLHhgJbhgLHhgKzhgLrhgJ3hgKvhgJvhgK5f4YCZ4YCQ4YC6X+GAp+GAleGAvOGArl/hgJnhgLFf4YCH4YC94YCU4YC6X+GAh+GAsOGAnOGAreGAr+GAhOGAul/hgJ7hgLzhgILhgK/hgJDhgLpf4YCF4YCA4YC64YCQ4YCE4YC64YCY4YCsX+GAoeGAseGArOGAgOGAuuGAkOGAreGAr+GAmOGArF/hgJThgK3hgK/hgJ3hgIThgLrhgJjhgKxf4YCS4YCu4YCH4YCE4YC64YCY4YCsJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0OiAn4YCH4YCU4YC6X+GAluGAsV/hgJnhgJDhgLpf4YCV4YC84YCuX+GAmeGAsV/hgIfhgL3hgJThgLpf4YCc4YCt4YCv4YCE4YC6X+GAnuGAvF/hgIXhgIDhgLpf4YCh4YCx4YCs4YCA4YC6X+GAlOGAreGAr1/hgJLhgK4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXM6ICfhgJDhgJThgIThgLrhgLnhgILhgJThgL3hgLFf4YCQ4YCU4YCE4YC64YC54YCc4YCsX+GAoeGAhOGAuuGAueGAguGAq1/hgJfhgK/hgJLhgLnhgJPhgJ/hgLDhgLhf4YCA4YC84YCs4YCe4YCV4YCQ4YCx4YC4X+GAnuGAseGArOGAgOGAvOGArF/hgIXhgJThgLEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydDogJ+GAlOGAveGAsV/hgJzhgKxf4YCC4YCrX+GAn+GAsOGAuF/hgIDhgLzhgKxf4YCe4YCx4YCsX+GAlOGAsScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbjogJ+GAlOGAveGAsV/hgJzhgKxf4YCC4YCrX+GAn+GAsOGAuF/hgIDhgLzhgKxf4YCe4YCx4YCsX+GAlOGAsScuc3BsaXQoJ18nKSxcblxuICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgIExUOiAnSEg6bW0nLFxuICAgICAgICBMVFM6ICdISDptbTpzcycsXG4gICAgICAgIEw6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEw6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhcjoge1xuICAgICAgICBzYW1lRGF5OiAnW+GAmuGAlOGAsS5dIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgbmV4dERheTogJ1vhgJnhgJThgIDhgLrhgJbhgLzhgJThgLpdIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIExUIFvhgJnhgL7hgKxdJyxcbiAgICAgICAgbGFzdERheTogJ1vhgJnhgJThgLEu4YCAXSBMVCBb4YCZ4YC+4YCsXScsXG4gICAgICAgIGxhc3RXZWVrOiAnW+GAleGAvOGAruGAuOGAgeGAsuGAt+GAnuGAseGArF0gZGRkZCBMVCBb4YCZ4YC+4YCsXScsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZToge1xuICAgICAgICBmdXR1cmU6ICfhgJzhgKzhgJnhgIrhgLrhgLcgJXMg4YCZ4YC+4YCsJyxcbiAgICAgICAgcGFzdDogJ+GAnOGAveGAlOGAuuGAgeGAsuGAt+GAnuGAseGArCAlcyDhgIAnLFxuICAgICAgICBzOiAn4YCF4YCA4YC54YCA4YCU4YC6LuGAoeGAlOGAiuGAuuGAuOGAhOGAmuGAuicsXG4gICAgICAgIHNzIDogJyVkIOGAheGAgOGAueGAgOGAlOGAt+GAuicsXG4gICAgICAgIG06ICfhgJDhgIXhgLrhgJnhgK3hgJThgIXhgLonLFxuICAgICAgICBtbTogJyVkIOGAmeGAreGAlOGAheGAuicsXG4gICAgICAgIGg6ICfhgJDhgIXhgLrhgJThgKzhgJvhgK4nLFxuICAgICAgICBoaDogJyVkIOGAlOGArOGAm+GAricsXG4gICAgICAgIGQ6ICfhgJDhgIXhgLrhgJvhgIDhgLonLFxuICAgICAgICBkZDogJyVkIOGAm+GAgOGAuicsXG4gICAgICAgIE06ICfhgJDhgIXhgLrhgJwnLFxuICAgICAgICBNTTogJyVkIOGAnCcsXG4gICAgICAgIHk6ICfhgJDhgIXhgLrhgJThgL7hgIXhgLonLFxuICAgICAgICB5eTogJyVkIOGAlOGAvuGAheGAuidcbiAgICB9LFxuICAgIHByZXBhcnNlOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvW+GBgeGBguGBg+GBhOGBheGBhuGBh+GBiOGBieGBgF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTWFwW21hdGNoXTtcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvXFxkL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIHN5bWJvbE1hcFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgd2Vlazoge1xuICAgICAgICBkb3c6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3k6IDQgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbXk7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL215LmpzXG4vLyBtb2R1bGUgaWQgPSA4MVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTm9yd2VnaWFuIEJva23DpWwgW25iXVxuLy8hIGF1dGhvcnMgOiBFc3BlbiBIb3ZsYW5kc2RhbCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9yZXh4YXJzXG4vLyEgICAgICAgICAgIFNpZ3VyZCBHYXJ0bWFubiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9zaWd1cmRnYVxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBuYiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ25iJywge1xuICAgIG1vbnRocyA6ICdqYW51YXJfZmVicnVhcl9tYXJzX2FwcmlsX21haV9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbi5fZmViLl9tYXJzX2FwcmlsX21haV9qdW5pX2p1bGlfYXVnLl9zZXAuX29rdC5fbm92Ll9kZXMuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ3PDuG5kYWdfbWFuZGFnX3RpcnNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2zDuHJkYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdzw7guX21hLl90aS5fb24uX3RvLl9mci5fbMO4Licuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdzw7hfbWFfdGlfb25fdG9fZnJfbMO4Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QuIE1NTU0gWVlZWSBba2wuXSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBELiBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tpIGRhZyBrbC5dIExUJyxcbiAgICAgICAgbmV4dERheTogJ1tpIG1vcmdlbiBrbC5dIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtrbC5dIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tpIGfDpXIga2wuXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW2ZvcnJpZ2VdIGRkZGQgW2tsLl0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdvbSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgc2lkZW4nLFxuICAgICAgICBzIDogJ25vZW4gc2VrdW5kZXInLFxuICAgICAgICBzcyA6ICclZCBzZWt1bmRlcicsXG4gICAgICAgIG0gOiAnZXR0IG1pbnV0dCcsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0dGVyJyxcbiAgICAgICAgaCA6ICdlbiB0aW1lJyxcbiAgICAgICAgaGggOiAnJWQgdGltZXInLFxuICAgICAgICBkIDogJ2VuIGRhZycsXG4gICAgICAgIGRkIDogJyVkIGRhZ2VyJyxcbiAgICAgICAgTSA6ICdlbiBtw6VuZWQnLFxuICAgICAgICBNTSA6ICclZCBtw6VuZWRlcicsXG4gICAgICAgIHkgOiAnZXR0IMOlcicsXG4gICAgICAgIHl5IDogJyVkIMOlcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBuYjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvbmIuanNcbi8vIG1vZHVsZSBpZCA9IDgyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBOZXBhbGVzZSBbbmVdXG4vLyEgYXV0aG9yIDogc3V2YXNoIDogaHR0cHM6Ly9naXRodWIuY29tL3N1dmFzaFxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBzeW1ib2xNYXAgPSB7XG4gICAgJzEnOiAn4KWnJyxcbiAgICAnMic6ICfgpagnLFxuICAgICczJzogJ+ClqScsXG4gICAgJzQnOiAn4KWqJyxcbiAgICAnNSc6ICfgpasnLFxuICAgICc2JzogJ+ClrCcsXG4gICAgJzcnOiAn4KWtJyxcbiAgICAnOCc6ICfgpa4nLFxuICAgICc5JzogJ+ClrycsXG4gICAgJzAnOiAn4KWmJ1xufTtcbnZhciBudW1iZXJNYXAgPSB7XG4gICAgJ+Clpyc6ICcxJyxcbiAgICAn4KWoJzogJzInLFxuICAgICfgpaknOiAnMycsXG4gICAgJ+Clqic6ICc0JyxcbiAgICAn4KWrJzogJzUnLFxuICAgICfgpawnOiAnNicsXG4gICAgJ+ClrSc6ICc3JyxcbiAgICAn4KWuJzogJzgnLFxuICAgICfgpa8nOiAnOScsXG4gICAgJ+Clpic6ICcwJ1xufTtcblxudmFyIG5lID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbmUnLCB7XG4gICAgbW9udGhzIDogJ+CknOCkqOCkteCksOClgF/gpKvgpYfgpKzgpY3gpLDgpYHgpLXgpLDgpYBf4KSu4KS+4KSw4KWN4KSaX+CkheCkquCljeCksOCkv+Cksl/gpK7gpIhf4KSc4KWB4KSoX+CknOClgeCksuCkvuCkiF/gpIXgpJfgpLfgpY3gpJ9f4KS44KWH4KSq4KWN4KSf4KWH4KSu4KWN4KSs4KSwX+CkheCkleCljeCkn+Cli+CkrOCksF/gpKjgpYvgpK3gpYfgpK7gpY3gpKzgpLBf4KSh4KS/4KS44KWH4KSu4KWN4KSs4KSwJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ+CknOCkqC5f4KSr4KWH4KSs4KWN4KSw4KWBLl/gpK7gpL7gpLDgpY3gpJpf4KSF4KSq4KWN4KSw4KS/Ll/gpK7gpIhf4KSc4KWB4KSoX+CknOClgeCksuCkvuCkiC5f4KSF4KSXLl/gpLjgpYfgpKrgpY3gpJ8uX+CkheCkleCljeCkn+Cliy5f4KSo4KWL4KSt4KWHLl/gpKHgpL/gpLjgpYcuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ+CkhuCkh+CkpOCkrOCkvuCksF/gpLjgpYvgpK7gpKzgpL7gpLBf4KSu4KSZ4KWN4KSX4KSy4KSs4KS+4KSwX+CkrOClgeCkp+CkrOCkvuCksF/gpKzgpL/gpLngpL/gpKzgpL7gpLBf4KS24KWB4KSV4KWN4KSw4KSs4KS+4KSwX+CktuCkqOCkv+CkrOCkvuCksCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+CkhuCkh+CkpC5f4KS44KWL4KSuLl/gpK7gpJngpY3gpJfgpLIuX+CkrOClgeCkpy5f4KSs4KS/4KS54KS/Ll/gpLbgpYHgpJXgpY3gpLAuX+CktuCkqOCkvy4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4KSGLl/gpLjgpYsuX+CkruCkgi5f4KSs4KWBLl/gpKzgpL8uX+CktuClgS5f4KS2Licuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdB4KSV4KWLIGg6bW0g4KSs4KSc4KWHJyxcbiAgICAgICAgTFRTIDogJ0HgpJXgpYsgaDptbTpzcyDgpKzgpJzgpYcnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSwgQeCkleCliyBoOm1tIOCkrOCknOClhycsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEHgpJXgpYsgaDptbSDgpKzgpJzgpYcnXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgpafgpajgpangpargpavgpazgpa3gpa7gpa/gpaZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXBbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/gpLDgpL7gpKTgpL984KSs4KS/4KS54KS+4KSofOCkpuCkv+CkieCkgeCkuOCli3zgpLjgpL7gpIHgpJ0vLFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+CksOCkvuCkpOCkvycpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgpKzgpL/gpLngpL7gpKgnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkpuCkv+CkieCkgeCkuOCliycpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CkuOCkvuCkgeCknScpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDMpIHtcbiAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSk4KS/JztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn4KSs4KS/4KS54KS+4KSoJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTYpIHtcbiAgICAgICAgICAgIHJldHVybiAn4KSm4KS/4KSJ4KSB4KS44KWLJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiAn4KS44KS+4KSB4KSdJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4KSw4KS+4KSk4KS/JztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+CkhuCknF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vgpK3gpYvgpLLgpL9dIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+CkhuCkieCkgeCkpuCli10gZGRkZFssXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW+CkueCkv+CknOCli10gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb4KSX4KSP4KSV4KWLXSBkZGRkWyxdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVz4KSu4KS+JyxcbiAgICAgICAgcGFzdCA6ICclcyDgpIXgpJfgpL7gpKHgpL8nLFxuICAgICAgICBzIDogJ+CkleClh+CkueClgCDgpJXgpY3gpLfgpKMnLFxuICAgICAgICBzcyA6ICclZCDgpLjgpYfgpJXgpYfgpKPgpY3gpKEnLFxuICAgICAgICBtIDogJ+Ckj+CklSDgpK7gpL/gpKjgpYfgpJ8nLFxuICAgICAgICBtbSA6ICclZCDgpK7gpL/gpKjgpYfgpJ8nLFxuICAgICAgICBoIDogJ+Ckj+CklSDgpJjgpKPgpY3gpJ/gpL4nLFxuICAgICAgICBoaCA6ICclZCDgpJjgpKPgpY3gpJ/gpL4nLFxuICAgICAgICBkIDogJ+Ckj+CklSDgpKbgpL/gpKgnLFxuICAgICAgICBkZCA6ICclZCDgpKbgpL/gpKgnLFxuICAgICAgICBNIDogJ+Ckj+CklSDgpK7gpLngpL/gpKjgpL4nLFxuICAgICAgICBNTSA6ICclZCDgpK7gpLngpL/gpKjgpL4nLFxuICAgICAgICB5IDogJ+Ckj+CklSDgpKzgpLDgpY3gpLcnLFxuICAgICAgICB5eSA6ICclZCDgpKzgpLDgpY3gpLcnXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbmU7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL25lLmpzXG4vLyBtb2R1bGUgaWQgPSA4M1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogRHV0Y2ggW25sXVxuLy8hIGF1dGhvciA6IEpvcmlzIFLDtmxpbmcgOiBodHRwczovL2dpdGh1Yi5jb20vam9yaXNyb2xpbmdcbi8vISBhdXRob3IgOiBKYWNvYiBNaWRkYWcgOiBodHRwczovL2dpdGh1Yi5jb20vbWlkZGFnalxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBtb250aHNTaG9ydFdpdGhEb3RzID0gJ2phbi5fZmViLl9tcnQuX2Fwci5fbWVpX2p1bi5fanVsLl9hdWcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnRXaXRob3V0RG90cyA9ICdqYW5fZmViX21ydF9hcHJfbWVpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2RlYycuc3BsaXQoJ18nKTtcblxudmFyIG1vbnRoc1BhcnNlID0gWy9eamFuL2ksIC9eZmViL2ksIC9ebWFhcnR8bXJ0Lj8kL2ksIC9eYXByL2ksIC9ebWVpJC9pLCAvXmp1bltpLl0/JC9pLCAvXmp1bFtpLl0/JC9pLCAvXmF1Zy9pLCAvXnNlcC9pLCAvXm9rdC9pLCAvXm5vdi9pLCAvXmRlYy9pXTtcbnZhciBtb250aHNSZWdleCA9IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGFwcmlsfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXJ8amFuXFwuP3xmZWJcXC4/fG1ydFxcLj98YXByXFwuP3xqdVtubF1cXC4/fGF1Z1xcLj98c2VwXFwuP3xva3RcXC4/fG5vdlxcLj98ZGVjXFwuPykvaTtcblxudmFyIG5sID0gbW9tZW50LmRlZmluZUxvY2FsZSgnbmwnLCB7XG4gICAgbW9udGhzIDogJ2phbnVhcmlfZmVicnVhcmlfbWFhcnRfYXByaWxfbWVpX2p1bmlfanVsaV9hdWd1c3R1c19zZXB0ZW1iZXJfb2t0b2Jlcl9ub3ZlbWJlcl9kZWNlbWJlcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6IGZ1bmN0aW9uIChtLCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRoRG90cztcbiAgICAgICAgfSBlbHNlIGlmICgvLU1NTS0vLnRlc3QoZm9ybWF0KSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aG91dERvdHNbbS5tb250aCgpXTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzW20ubW9udGgoKV07XG4gICAgICAgIH1cbiAgICB9LFxuXG4gICAgbW9udGhzUmVnZXg6IG1vbnRoc1JlZ2V4LFxuICAgIG1vbnRoc1Nob3J0UmVnZXg6IG1vbnRoc1JlZ2V4LFxuICAgIG1vbnRoc1N0cmljdFJlZ2V4OiAvXihqYW51YXJpfGZlYnJ1YXJpfG1hYXJ0fG1laXxqdVtubF1pfGFwcmlsfGF1Z3VzdHVzfHNlcHRlbWJlcnxva3RvYmVyfG5vdmVtYmVyfGRlY2VtYmVyKS9pLFxuICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKGphblxcLj98ZmViXFwuP3xtcnRcXC4/fGFwclxcLj98bWVpfGp1W25sXVxcLj98YXVnXFwuP3xzZXBcXC4/fG9rdFxcLj98bm92XFwuP3xkZWNcXC4/KS9pLFxuXG4gICAgbW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSxcbiAgICBsb25nTW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSxcbiAgICBzaG9ydE1vbnRoc1BhcnNlIDogbW9udGhzUGFyc2UsXG5cbiAgICB3ZWVrZGF5cyA6ICd6b25kYWdfbWFhbmRhZ19kaW5zZGFnX3dvZW5zZGFnX2RvbmRlcmRhZ192cmlqZGFnX3phdGVyZGFnJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnem8uX21hLl9kaS5fd28uX2RvLl92ci5femEuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ3pvX21hX2RpX3dvX2RvX3ZyX3phJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC1NTS1ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1t2YW5kYWFnIG9tXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbbW9yZ2VuIG9tXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbb21dIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tnaXN0ZXJlbiBvbV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ1thZmdlbG9wZW5dIGRkZGQgW29tXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ292ZXIgJXMnLFxuICAgICAgICBwYXN0IDogJyVzIGdlbGVkZW4nLFxuICAgICAgICBzIDogJ2VlbiBwYWFyIHNlY29uZGVuJyxcbiAgICAgICAgc3MgOiAnJWQgc2Vjb25kZW4nLFxuICAgICAgICBtIDogJ8Opw6luIG1pbnV1dCcsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0ZW4nLFxuICAgICAgICBoIDogJ8Opw6luIHV1cicsXG4gICAgICAgIGhoIDogJyVkIHV1cicsXG4gICAgICAgIGQgOiAnw6nDqW4gZGFnJyxcbiAgICAgICAgZGQgOiAnJWQgZGFnZW4nLFxuICAgICAgICBNIDogJ8Opw6luIG1hYW5kJyxcbiAgICAgICAgTU0gOiAnJWQgbWFhbmRlbicsXG4gICAgICAgIHkgOiAnw6nDqW4gamFhcicsXG4gICAgICAgIHl5IDogJyVkIGphYXInXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3RlfGRlKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciArICgobnVtYmVyID09PSAxIHx8IG51bWJlciA9PT0gOCB8fCBudW1iZXIgPj0gMjApID8gJ3N0ZScgOiAnZGUnKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBubDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvbmwuanNcbi8vIG1vZHVsZSBpZCA9IDg0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBEdXRjaCAoQmVsZ2l1bSkgW25sLWJlXVxuLy8hIGF1dGhvciA6IEpvcmlzIFLDtmxpbmcgOiBodHRwczovL2dpdGh1Yi5jb20vam9yaXNyb2xpbmdcbi8vISBhdXRob3IgOiBKYWNvYiBNaWRkYWcgOiBodHRwczovL2dpdGh1Yi5jb20vbWlkZGFnalxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBtb250aHNTaG9ydFdpdGhEb3RzID0gJ2phbi5fZmViLl9tcnQuX2Fwci5fbWVpX2p1bi5fanVsLl9hdWcuX3NlcC5fb2t0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyk7XG52YXIgbW9udGhzU2hvcnRXaXRob3V0RG90cyA9ICdqYW5fZmViX21ydF9hcHJfbWVpX2p1bl9qdWxfYXVnX3NlcF9va3Rfbm92X2RlYycuc3BsaXQoJ18nKTtcblxudmFyIG1vbnRoc1BhcnNlID0gWy9eamFuL2ksIC9eZmViL2ksIC9ebWFhcnR8bXJ0Lj8kL2ksIC9eYXByL2ksIC9ebWVpJC9pLCAvXmp1bltpLl0/JC9pLCAvXmp1bFtpLl0/JC9pLCAvXmF1Zy9pLCAvXnNlcC9pLCAvXm9rdC9pLCAvXm5vdi9pLCAvXmRlYy9pXTtcbnZhciBtb250aHNSZWdleCA9IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8YXByaWx8bWVpfGFwcmlsfGp1W25sXWl8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXJ8amFuXFwuP3xmZWJcXC4/fG1ydFxcLj98YXByXFwuP3xqdVtubF1cXC4/fGF1Z1xcLj98c2VwXFwuP3xva3RcXC4/fG5vdlxcLj98ZGVjXFwuPykvaTtcblxudmFyIG5sQmUgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdubC1iZScsIHtcbiAgICBtb250aHMgOiAnamFudWFyaV9mZWJydWFyaV9tYWFydF9hcHJpbF9tZWlfanVuaV9qdWxpX2F1Z3VzdHVzX3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogZnVuY3Rpb24gKG0sIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTaG9ydFdpdGhEb3RzO1xuICAgICAgICB9IGVsc2UgaWYgKC8tTU1NLS8udGVzdChmb3JtYXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gbW9udGhzU2hvcnRXaXRob3V0RG90c1ttLm1vbnRoKCldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc1Nob3J0V2l0aERvdHNbbS5tb250aCgpXTtcbiAgICAgICAgfVxuICAgIH0sXG5cbiAgICBtb250aHNSZWdleDogbW9udGhzUmVnZXgsXG4gICAgbW9udGhzU2hvcnRSZWdleDogbW9udGhzUmVnZXgsXG4gICAgbW9udGhzU3RyaWN0UmVnZXg6IC9eKGphbnVhcml8ZmVicnVhcml8bWFhcnR8bWVpfGp1W25sXWl8YXByaWx8YXVndXN0dXN8c2VwdGVtYmVyfG9rdG9iZXJ8bm92ZW1iZXJ8ZGVjZW1iZXIpL2ksXG4gICAgbW9udGhzU2hvcnRTdHJpY3RSZWdleDogL14oamFuXFwuP3xmZWJcXC4/fG1ydFxcLj98YXByXFwuP3xtZWl8anVbbmxdXFwuP3xhdWdcXC4/fHNlcFxcLj98b2t0XFwuP3xub3ZcXC4/fGRlY1xcLj8pL2ksXG5cbiAgICBtb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlLFxuICAgIGxvbmdNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlLFxuICAgIHNob3J0TW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSxcblxuICAgIHdlZWtkYXlzIDogJ3pvbmRhZ19tYWFuZGFnX2RpbnNkYWdfd29lbnNkYWdfZG9uZGVyZGFnX3ZyaWpkYWdfemF0ZXJkYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICd6by5fbWEuX2RpLl93by5fZG8uX3ZyLl96YS4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnem9fbWFfZGlfd29fZG9fdnJfemEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0REL01NL1lZWVknLFxuICAgICAgICBMTCA6ICdEIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW3ZhbmRhYWcgb21dIExUJyxcbiAgICAgICAgbmV4dERheTogJ1ttb3JnZW4gb21dIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtvbV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW2dpc3RlcmVuIG9tXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW2FmZ2Vsb3Blbl0gZGRkZCBbb21dIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnb3ZlciAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgZ2VsZWRlbicsXG4gICAgICAgIHMgOiAnZWVuIHBhYXIgc2Vjb25kZW4nLFxuICAgICAgICBzcyA6ICclZCBzZWNvbmRlbicsXG4gICAgICAgIG0gOiAnw6nDqW4gbWludXV0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlbicsXG4gICAgICAgIGggOiAnw6nDqW4gdXVyJyxcbiAgICAgICAgaGggOiAnJWQgdXVyJyxcbiAgICAgICAgZCA6ICfDqcOpbiBkYWcnLFxuICAgICAgICBkZCA6ICclZCBkYWdlbicsXG4gICAgICAgIE0gOiAnw6nDqW4gbWFhbmQnLFxuICAgICAgICBNTSA6ICclZCBtYWFuZGVuJyxcbiAgICAgICAgeSA6ICfDqcOpbiBqYWFyJyxcbiAgICAgICAgeXkgOiAnJWQgamFhcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShzdGV8ZGUpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgKChudW1iZXIgPT09IDEgfHwgbnVtYmVyID09PSA4IHx8IG51bWJlciA+PSAyMCkgPyAnc3RlJyA6ICdkZScpO1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIG5sQmU7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL25sLWJlLmpzXG4vLyBtb2R1bGUgaWQgPSA4NVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTnlub3JzayBbbm5dXG4vLyEgYXV0aG9yIDogaHR0cHM6Ly9naXRodWIuY29tL21lY2h1d2luZFxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBubiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ25uJywge1xuICAgIG1vbnRocyA6ICdqYW51YXJfZmVicnVhcl9tYXJzX2FwcmlsX21haV9qdW5pX2p1bGlfYXVndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2Rlc2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYWlfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3N1bmRhZ19tw6VuZGFnX3R5c2RhZ19vbnNkYWdfdG9yc2RhZ19mcmVkYWdfbGF1cmRhZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3N1bl9tw6VuX3R5c19vbnNfdG9yX2ZyZV9sYXUnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnc3VfbcOlX3R5X29uX3RvX2ZyX2zDuCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIFtrbC5dIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRC4gTU1NTSBZWVlZIFtrbC5dIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbSSBkYWcga2xva2thXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbSSBtb3Jnb24ga2xva2thXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBba2xva2thXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbSSBnw6VyIGtsb2trYV0gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ1tGw7hyZWfDpWFuZGVdIGRkZGQgW2tsb2trYV0gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdvbSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgc2lkYW4nLFxuICAgICAgICBzIDogJ25va3JlIHNla3VuZCcsXG4gICAgICAgIHNzIDogJyVkIHNla3VuZCcsXG4gICAgICAgIG0gOiAnZWl0IG1pbnV0dCcsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0dCcsXG4gICAgICAgIGggOiAnZWluIHRpbWUnLFxuICAgICAgICBoaCA6ICclZCB0aW1hcicsXG4gICAgICAgIGQgOiAnZWluIGRhZycsXG4gICAgICAgIGRkIDogJyVkIGRhZ2FyJyxcbiAgICAgICAgTSA6ICdlaW4gbcOlbmFkJyxcbiAgICAgICAgTU0gOiAnJWQgbcOlbmFkZXInLFxuICAgICAgICB5IDogJ2VpdCDDpXInLFxuICAgICAgICB5eSA6ICclZCDDpXInXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gbm47XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL25uLmpzXG4vLyBtb2R1bGUgaWQgPSA4NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogUHVuamFiaSAoSW5kaWEpIFtwYS1pbl1cbi8vISBhdXRob3IgOiBIYXJwcmVldCBTaW5naCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9oYXJwcmVldGtoYWxzYWd0Yml0XG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHN5bWJvbE1hcCA9IHtcbiAgICAnMSc6ICfgqacnLFxuICAgICcyJzogJ+CpqCcsXG4gICAgJzMnOiAn4KmpJyxcbiAgICAnNCc6ICfgqaonLFxuICAgICc1JzogJ+CpqycsXG4gICAgJzYnOiAn4KmsJyxcbiAgICAnNyc6ICfgqa0nLFxuICAgICc4JzogJ+CpricsXG4gICAgJzknOiAn4KmvJyxcbiAgICAnMCc6ICfgqaYnXG59O1xudmFyIG51bWJlck1hcCA9IHtcbiAgICAn4KmnJzogJzEnLFxuICAgICfgqagnOiAnMicsXG4gICAgJ+CpqSc6ICczJyxcbiAgICAn4KmqJzogJzQnLFxuICAgICfgqasnOiAnNScsXG4gICAgJ+CprCc6ICc2JyxcbiAgICAn4KmtJzogJzcnLFxuICAgICfgqa4nOiAnOCcsXG4gICAgJ+Cpryc6ICc5JyxcbiAgICAn4KmmJzogJzAnXG59O1xuXG52YXIgcGFJbiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3BhLWluJywge1xuICAgIC8vIFRoZXJlIGFyZSBtb250aHMgbmFtZSBhcyBwZXIgTmFuYWtzaGFoaSBDYWxlbmRlciBidXQgdGhleSBhcmUgbm90IHVzZWQgYXMgcmlnaWRseSBpbiBtb2Rlcm4gUHVuamFiaS5cbiAgICBtb250aHMgOiAn4Kic4Kio4Ki14Kiw4KmAX+Coq+CovOCosOCoteCosOCpgF/gqK7gqL7gqLDgqJpf4KiF4Kiq4KmN4Kiw4KmI4KiyX+CoruCoiF/gqJzgqYLgqKhf4Kic4KmB4Kiy4Ki+4KiIX+CoheCol+CouOCopF/gqLjgqKTgqbDgqKzgqLBf4KiF4KiV4Kik4KmC4Kis4KiwX+CoqOCoteCpsOCorOCosF/gqKbgqLjgqbDgqKzgqLAnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn4Kic4Kio4Ki14Kiw4KmAX+Coq+CovOCosOCoteCosOCpgF/gqK7gqL7gqLDgqJpf4KiF4Kiq4KmN4Kiw4KmI4KiyX+CoruCoiF/gqJzgqYLgqKhf4Kic4KmB4Kiy4Ki+4KiIX+CoheCol+CouOCopF/gqLjgqKTgqbDgqKzgqLBf4KiF4KiV4Kik4KmC4Kis4KiwX+CoqOCoteCpsOCorOCosF/gqKbgqLjgqbDgqKzgqLAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn4KiQ4Kik4Ki14Ki+4KiwX+CouOCpi+CoruCoteCovuCosF/gqK7gqbDgqJfgqLLgqLXgqL7gqLBf4Kis4KmB4Kin4Ki14Ki+4KiwX+CoteCpgOCosOCoteCovuCosF/gqLjgqLzgqYHgqbHgqJXgqLDgqLXgqL7gqLBf4Ki44Ki84Kio4KmA4Kia4Kiw4Ki14Ki+4KiwJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn4KiQ4KikX+CouOCpi+Corl/gqK7gqbDgqJfgqLJf4Kis4KmB4KinX+CoteCpgOCosF/gqLjgqLzgqYHgqJXgqLBf4Ki44Ki84Kio4KmAJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+CokOCopF/gqLjgqYvgqK5f4Kiu4Kmw4KiX4KiyX+CorOCpgeCop1/gqLXgqYDgqLBf4Ki44Ki84KmB4KiV4KiwX+CouOCovOCoqOCpgCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnQSBoOm1tIOCoteConOCphycsXG4gICAgICAgIExUUyA6ICdBIGg6bW06c3Mg4Ki14Kic4KmHJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEEgaDptbSDgqLXgqJzgqYcnLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZLCBBIGg6bW0g4Ki14Kic4KmHJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+CoheConF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vgqJXgqLJdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCwgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vgqJXgqLJdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+CoquCov+Com+CosuCph10gZGRkZCwgTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMg4Ki14Ki/4Kmx4KiaJyxcbiAgICAgICAgcGFzdCA6ICclcyDgqKrgqL/gqJvgqLLgqYcnLFxuICAgICAgICBzIDogJ+ColeCpgeConSDgqLjgqJXgqL/gqbDgqJ8nLFxuICAgICAgICBzcyA6ICclZCDgqLjgqJXgqL/gqbDgqJ8nLFxuICAgICAgICBtIDogJ+Coh+ColSDgqK7gqL/gqbDgqJ8nLFxuICAgICAgICBtbSA6ICclZCDgqK7gqL/gqbDgqJ8nLFxuICAgICAgICBoIDogJ+Coh+CpseColSDgqJjgqbDgqJ/gqL4nLFxuICAgICAgICBoaCA6ICclZCDgqJjgqbDgqJ/gqYcnLFxuICAgICAgICBkIDogJ+Coh+CpseColSDgqKbgqL/gqKgnLFxuICAgICAgICBkZCA6ICclZCDgqKbgqL/gqKgnLFxuICAgICAgICBNIDogJ+Coh+CpseColSDgqK7gqLngqYDgqKjgqL4nLFxuICAgICAgICBNTSA6ICclZCDgqK7gqLngqYDgqKjgqYcnLFxuICAgICAgICB5IDogJ+Coh+CpseColSDgqLjgqL7gqLInLFxuICAgICAgICB5eSA6ICclZCDgqLjgqL7gqLInXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgqafgqajgqangqargqavgqazgqa3gqa7gqa/gqaZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXBbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIC8vIFB1bmphYmkgbm90YXRpb24gZm9yIG1lcmlkaWVtcyBhcmUgcXVpdGUgZnV6enkgaW4gcHJhY3RpY2UuIFdoaWxlIHRoZXJlIGV4aXN0c1xuICAgIC8vIGEgcmlnaWQgbm90aW9uIG9mIGEgJ1BhaGFyJyBpdCBpcyBub3QgdXNlZCBhcyByaWdpZGx5IGluIG1vZGVybiBQdW5qYWJpLlxuICAgIG1lcmlkaWVtUGFyc2U6IC/gqLDgqL7gqKR84Ki44Ki14KmH4KiwfOCopuCpgeCoquCoueCov+CosHzgqLjgqLzgqL7gqK4vLFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ+CosOCovuCopCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyIDwgNCA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfgqLjgqLXgqYfgqLAnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CopuCpgeCoquCoueCov+CosCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDEwID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CouOCovOCovuCoricpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91ciA8IDQpIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kiw4Ki+4KikJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTApIHtcbiAgICAgICAgICAgIHJldHVybiAn4Ki44Ki14KmH4KiwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kim4KmB4Kiq4Ki54Ki/4KiwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMjApIHtcbiAgICAgICAgICAgIHJldHVybiAn4Ki44Ki84Ki+4KiuJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4Kiw4Ki+4KikJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHBhSW47XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3BhLWluLmpzXG4vLyBtb2R1bGUgaWQgPSA4N1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogUG9saXNoIFtwbF1cbi8vISBhdXRob3IgOiBSYWZhbCBIaXJzeiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9ldm9MXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIG1vbnRoc05vbWluYXRpdmUgPSAnc3R5Y3plxYRfbHV0eV9tYXJ6ZWNfa3dpZWNpZcWEX21hal9jemVyd2llY19saXBpZWNfc2llcnBpZcWEX3dyemVzaWXFhF9wYcW6ZHppZXJuaWtfbGlzdG9wYWRfZ3J1ZHppZcWEJy5zcGxpdCgnXycpO1xudmFyIG1vbnRoc1N1YmplY3RpdmUgPSAnc3R5Y3puaWFfbHV0ZWdvX21hcmNhX2t3aWV0bmlhX21hamFfY3plcndjYV9saXBjYV9zaWVycG5pYV93cnplxZtuaWFfcGHFumR6aWVybmlrYV9saXN0b3BhZGFfZ3J1ZG5pYScuc3BsaXQoJ18nKTtcbmZ1bmN0aW9uIHBsdXJhbChuKSB7XG4gICAgcmV0dXJuIChuICUgMTAgPCA1KSAmJiAobiAlIDEwID4gMSkgJiYgKCh+fihuIC8gMTApICUgMTApICE9PSAxKTtcbn1cbmZ1bmN0aW9uIHRyYW5zbGF0ZShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwobnVtYmVyKSA/ICdzZWt1bmR5JyA6ICdzZWt1bmQnKTtcbiAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdtaW51dGEnIDogJ21pbnV0xJknO1xuICAgICAgICBjYXNlICdtbSc6XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbChudW1iZXIpID8gJ21pbnV0eScgOiAnbWludXQnKTtcbiAgICAgICAgY2FzZSAnaCc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCAgPyAnZ29kemluYScgIDogJ2dvZHppbsSZJztcbiAgICAgICAgY2FzZSAnaGgnOlxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwobnVtYmVyKSA/ICdnb2R6aW55JyA6ICdnb2R6aW4nKTtcbiAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwobnVtYmVyKSA/ICdtaWVzacSFY2UnIDogJ21pZXNpxJljeScpO1xuICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbChudW1iZXIpID8gJ2xhdGEnIDogJ2xhdCcpO1xuICAgIH1cbn1cblxudmFyIHBsID0gbW9tZW50LmRlZmluZUxvY2FsZSgncGwnLCB7XG4gICAgbW9udGhzIDogZnVuY3Rpb24gKG1vbWVudFRvRm9ybWF0LCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFtb21lbnRUb0Zvcm1hdCkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc05vbWluYXRpdmU7XG4gICAgICAgIH0gZWxzZSBpZiAoZm9ybWF0ID09PSAnJykge1xuICAgICAgICAgICAgLy8gSGFjazogaWYgZm9ybWF0IGVtcHR5IHdlIGtub3cgdGhpcyBpcyB1c2VkIHRvIGdlbmVyYXRlXG4gICAgICAgICAgICAvLyBSZWdFeHAgYnkgbW9tZW50LiBHaXZlIHRoZW4gYmFjayBib3RoIHZhbGlkIGZvcm1zIG9mIG1vbnRoc1xuICAgICAgICAgICAgLy8gaW4gUmVnRXhwIHJlYWR5IGZvcm1hdC5cbiAgICAgICAgICAgIHJldHVybiAnKCcgKyBtb250aHNTdWJqZWN0aXZlW21vbWVudFRvRm9ybWF0Lm1vbnRoKCldICsgJ3wnICsgbW9udGhzTm9taW5hdGl2ZVttb21lbnRUb0Zvcm1hdC5tb250aCgpXSArICcpJztcbiAgICAgICAgfSBlbHNlIGlmICgvRCBNTU1NLy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgIHJldHVybiBtb250aHNTdWJqZWN0aXZlW21vbWVudFRvRm9ybWF0Lm1vbnRoKCldO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG1vbnRoc05vbWluYXRpdmVbbW9tZW50VG9Gb3JtYXQubW9udGgoKV07XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1vbnRoc1Nob3J0IDogJ3N0eV9sdXRfbWFyX2t3aV9tYWpfY3plX2xpcF9zaWVfd3J6X3BhxbpfbGlzX2dydScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICduaWVkemllbGFfcG9uaWVkemlhxYJla193dG9yZWtfxZtyb2RhX2N6d2FydGVrX3BpxIV0ZWtfc29ib3RhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnbmR6X3Bvbl93dF/Fm3JfY3p3X3B0X3NvYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdOZF9Qbl9XdF/FmnJfQ3pfUHRfU28nLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbRHppxZsgb10gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW0p1dHJvIG9dIExUJyxcbiAgICAgICAgbmV4dFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbVyBuaWVkemllbMSZIG9dIExUJztcblxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbV2Ugd3RvcmVrIG9dIExUJztcblxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbVyDFm3JvZMSZIG9dIExUJztcblxuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbVyBzb2JvdMSZIG9dIExUJztcblxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1ddIGRkZGQgW29dIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheTogJ1tXY3pvcmFqIG9dIExUJyxcbiAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbVyB6ZXN6xYLEhSBuaWVkemllbMSZIG9dIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1cgemVzesWCxIUgxZtyb2TEmSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1tXIHplc3rFgsSFIHNvYm90xJkgb10gTFQnO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW1cgemVzesWCeV0gZGRkZCBbb10gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICd6YSAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgdGVtdScsXG4gICAgICAgIHMgOiAna2lsa2Egc2VrdW5kJyxcbiAgICAgICAgc3MgOiB0cmFuc2xhdGUsXG4gICAgICAgIG0gOiB0cmFuc2xhdGUsXG4gICAgICAgIG1tIDogdHJhbnNsYXRlLFxuICAgICAgICBoIDogdHJhbnNsYXRlLFxuICAgICAgICBoaCA6IHRyYW5zbGF0ZSxcbiAgICAgICAgZCA6ICcxIGR6aWXFhCcsXG4gICAgICAgIGRkIDogJyVkIGRuaScsXG4gICAgICAgIE0gOiAnbWllc2nEhWMnLFxuICAgICAgICBNTSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgeSA6ICdyb2snLFxuICAgICAgICB5eSA6IHRyYW5zbGF0ZVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHBsO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9wbC5qc1xuLy8gbW9kdWxlIGlkID0gODhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFBvcnR1Z3Vlc2UgW3B0XVxuLy8hIGF1dGhvciA6IEplZmZlcnNvbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qYWxleDc5XG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHB0ID0gbW9tZW50LmRlZmluZUxvY2FsZSgncHQnLCB7XG4gICAgbW9udGhzIDogJ2phbmVpcm9fZmV2ZXJlaXJvX21hcsOnb19hYnJpbF9tYWlvX2p1bmhvX2p1bGhvX2Fnb3N0b19zZXRlbWJyb19vdXR1YnJvX25vdmVtYnJvX2RlemVtYnJvJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZXZfbWFyX2Ficl9tYWlfanVuX2p1bF9hZ29fc2V0X291dF9ub3ZfZGV6Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0RvbWluZ29fU2VndW5kYS1mZWlyYV9UZXLDp2EtZmVpcmFfUXVhcnRhLWZlaXJhX1F1aW50YS1mZWlyYV9TZXh0YS1mZWlyYV9Tw6FiYWRvJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnRG9tX1NlZ19UZXJfUXVhX1F1aV9TZXhfU8OhYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdEb18ywqpfM8KqXzTCql81wqpfNsKqX1PDoScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgW2RlXSBNTU1NIFtkZV0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW0hvamUgw6BzXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbQW1hbmjDoyDDoHNdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvDoHNdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tPbnRlbSDDoHNdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5kYXkoKSA9PT0gMCB8fCB0aGlzLmRheSgpID09PSA2KSA/XG4gICAgICAgICAgICAgICAgJ1vDmmx0aW1vXSBkZGRkIFvDoHNdIExUJyA6IC8vIFNhdHVyZGF5ICsgU3VuZGF5XG4gICAgICAgICAgICAgICAgJ1vDmmx0aW1hXSBkZGRkIFvDoHNdIExUJzsgLy8gTW9uZGF5IC0gRnJpZGF5XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2VtICVzJyxcbiAgICAgICAgcGFzdCA6ICdow6EgJXMnLFxuICAgICAgICBzIDogJ3NlZ3VuZG9zJyxcbiAgICAgICAgc3MgOiAnJWQgc2VndW5kb3MnLFxuICAgICAgICBtIDogJ3VtIG1pbnV0bycsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0b3MnLFxuICAgICAgICBoIDogJ3VtYSBob3JhJyxcbiAgICAgICAgaGggOiAnJWQgaG9yYXMnLFxuICAgICAgICBkIDogJ3VtIGRpYScsXG4gICAgICAgIGRkIDogJyVkIGRpYXMnLFxuICAgICAgICBNIDogJ3VtIG3DqnMnLFxuICAgICAgICBNTSA6ICclZCBtZXNlcycsXG4gICAgICAgIHkgOiAndW0gYW5vJyxcbiAgICAgICAgeXkgOiAnJWQgYW5vcydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfcK6LyxcbiAgICBvcmRpbmFsIDogJyVkwronLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBwdDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvcHQuanNcbi8vIG1vZHVsZSBpZCA9IDg5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBQb3J0dWd1ZXNlIChCcmF6aWwpIFtwdC1icl1cbi8vISBhdXRob3IgOiBDYWlvIFJpYmVpcm8gUGVyZWlyYSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9jYWlvLXJpYmVpcm8tcGVyZWlyYVxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBwdEJyID0gbW9tZW50LmRlZmluZUxvY2FsZSgncHQtYnInLCB7XG4gICAgbW9udGhzIDogJ2phbmVpcm9fZmV2ZXJlaXJvX21hcsOnb19hYnJpbF9tYWlvX2p1bmhvX2p1bGhvX2Fnb3N0b19zZXRlbWJyb19vdXR1YnJvX25vdmVtYnJvX2RlemVtYnJvJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZXZfbWFyX2Ficl9tYWlfanVuX2p1bF9hZ29fc2V0X291dF9ub3ZfZGV6Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0RvbWluZ29fU2VndW5kYS1mZWlyYV9UZXLDp2EtZmVpcmFfUXVhcnRhLWZlaXJhX1F1aW50YS1mZWlyYV9TZXh0YS1mZWlyYV9Tw6FiYWRvJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnRG9tX1NlZ19UZXJfUXVhX1F1aV9TZXhfU8OhYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdEb18ywqpfM8KqXzTCql81wqpfNsKqX1PDoScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgW2RlXSBNTU1NIFtkZV0gWVlZWScsXG4gICAgICAgIExMTCA6ICdEIFtkZV0gTU1NTSBbZGVdIFlZWVkgW8Ogc10gSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgW2RlXSBNTU1NIFtkZV0gWVlZWSBbw6BzXSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW0hvamUgw6BzXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbQW1hbmjDoyDDoHNdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFvDoHNdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tPbnRlbSDDoHNdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAodGhpcy5kYXkoKSA9PT0gMCB8fCB0aGlzLmRheSgpID09PSA2KSA/XG4gICAgICAgICAgICAgICAgJ1vDmmx0aW1vXSBkZGRkIFvDoHNdIExUJyA6IC8vIFNhdHVyZGF5ICsgU3VuZGF5XG4gICAgICAgICAgICAgICAgJ1vDmmx0aW1hXSBkZGRkIFvDoHNdIExUJzsgLy8gTW9uZGF5IC0gRnJpZGF5XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ2VtICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBhdHLDoXMnLFxuICAgICAgICBzIDogJ3BvdWNvcyBzZWd1bmRvcycsXG4gICAgICAgIHNzIDogJyVkIHNlZ3VuZG9zJyxcbiAgICAgICAgbSA6ICd1bSBtaW51dG8nLFxuICAgICAgICBtbSA6ICclZCBtaW51dG9zJyxcbiAgICAgICAgaCA6ICd1bWEgaG9yYScsXG4gICAgICAgIGhoIDogJyVkIGhvcmFzJyxcbiAgICAgICAgZCA6ICd1bSBkaWEnLFxuICAgICAgICBkZCA6ICclZCBkaWFzJyxcbiAgICAgICAgTSA6ICd1bSBtw6pzJyxcbiAgICAgICAgTU0gOiAnJWQgbWVzZXMnLFxuICAgICAgICB5IDogJ3VtIGFubycsXG4gICAgICAgIHl5IDogJyVkIGFub3MnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn3Cui8sXG4gICAgb3JkaW5hbCA6ICclZMK6J1xufSk7XG5cbnJldHVybiBwdEJyO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9wdC1ici5qc1xuLy8gbW9kdWxlIGlkID0gOTBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFJvbWFuaWFuIFtyb11cbi8vISBhdXRob3IgOiBWbGFkIEd1cmRpZ2EgOiBodHRwczovL2dpdGh1Yi5jb20vZ3VyZGlnYVxuLy8hIGF1dGhvciA6IFZhbGVudGluIEFnYWNoaSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hdmFseVxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbmZ1bmN0aW9uIHJlbGF0aXZlVGltZVdpdGhQbHVyYWwobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAgICAgJ3NzJzogJ3NlY3VuZGUnLFxuICAgICAgICAgICAgJ21tJzogJ21pbnV0ZScsXG4gICAgICAgICAgICAnaGgnOiAnb3JlJyxcbiAgICAgICAgICAgICdkZCc6ICd6aWxlJyxcbiAgICAgICAgICAgICdNTSc6ICdsdW5pJyxcbiAgICAgICAgICAgICd5eSc6ICdhbmknXG4gICAgICAgIH0sXG4gICAgICAgIHNlcGFyYXRvciA9ICcgJztcbiAgICBpZiAobnVtYmVyICUgMTAwID49IDIwIHx8IChudW1iZXIgPj0gMTAwICYmIG51bWJlciAlIDEwMCA9PT0gMCkpIHtcbiAgICAgICAgc2VwYXJhdG9yID0gJyBkZSAnO1xuICAgIH1cbiAgICByZXR1cm4gbnVtYmVyICsgc2VwYXJhdG9yICsgZm9ybWF0W2tleV07XG59XG5cbnZhciBybyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3JvJywge1xuICAgIG1vbnRocyA6ICdpYW51YXJpZV9mZWJydWFyaWVfbWFydGllX2FwcmlsaWVfbWFpX2l1bmllX2l1bGllX2F1Z3VzdF9zZXB0ZW1icmllX29jdG9tYnJpZV9ub2llbWJyaWVfZGVjZW1icmllJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2lhbi5fZmVici5fbWFydC5fYXByLl9tYWlfaXVuLl9pdWwuX2F1Zy5fc2VwdC5fb2N0Ll9ub3YuX2RlYy4nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdkdW1pbmljxINfbHVuaV9tYXLIm2lfbWllcmN1cmlfam9pX3ZpbmVyaV9zw6JtYsSDdMSDJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnRHVtX0x1bl9NYXJfTWllX0pvaV9WaW5fU8OibScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdEdV9MdV9NYV9NaV9Kb19WaV9Tw6InLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1themkgbGFdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1ttw6JpbmUgbGFdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtsYV0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW2llcmkgbGFdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbZm9zdGFdIGRkZGQgW2xhXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3Blc3RlICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyDDrm4gdXJtxIMnLFxuICAgICAgICBzIDogJ2PDonRldmEgc2VjdW5kZScsXG4gICAgICAgIHNzIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgbSA6ICd1biBtaW51dCcsXG4gICAgICAgIG1tIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgaCA6ICdvIG9yxIMnLFxuICAgICAgICBoaCA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIGQgOiAnbyB6aScsXG4gICAgICAgIGRkIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgTSA6ICdvIGx1bsSDJyxcbiAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICB5IDogJ3VuIGFuJyxcbiAgICAgICAgeXkgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsXG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gcm87XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3JvLmpzXG4vLyBtb2R1bGUgaWQgPSA5MVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogUnVzc2lhbiBbcnVdXG4vLyEgYXV0aG9yIDogVmlrdG9ybWluYXRvciA6IGh0dHBzOi8vZ2l0aHViLmNvbS9WaWt0b3JtaW5hdG9yXG4vLyEgQXV0aG9yIDogTWVuZWxpb24gRWxlbnPDumxlIDogaHR0cHM6Ly9naXRodWIuY29tL09pcmVcbi8vISBhdXRob3IgOiDQmtC+0YDQtdC90LHQtdGA0LMg0JzQsNGA0LogOiBodHRwczovL2dpdGh1Yi5jb20vc29ja2V0cGFpclxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbmZ1bmN0aW9uIHBsdXJhbCh3b3JkLCBudW0pIHtcbiAgICB2YXIgZm9ybXMgPSB3b3JkLnNwbGl0KCdfJyk7XG4gICAgcmV0dXJuIG51bSAlIDEwID09PSAxICYmIG51bSAlIDEwMCAhPT0gMTEgPyBmb3Jtc1swXSA6IChudW0gJSAxMCA+PSAyICYmIG51bSAlIDEwIDw9IDQgJiYgKG51bSAlIDEwMCA8IDEwIHx8IG51bSAlIDEwMCA+PSAyMCkgPyBmb3Jtc1sxXSA6IGZvcm1zWzJdKTtcbn1cbmZ1bmN0aW9uIHJlbGF0aXZlVGltZVdpdGhQbHVyYWwobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICB2YXIgZm9ybWF0ID0ge1xuICAgICAgICAnc3MnOiB3aXRob3V0U3VmZml4ID8gJ9GB0LXQutGD0L3QtNCwX9GB0LXQutGD0L3QtNGLX9GB0LXQutGD0L3QtCcgOiAn0YHQtdC60YPQvdC00YNf0YHQtdC60YPQvdC00Ytf0YHQtdC60YPQvdC0JyxcbiAgICAgICAgJ21tJzogd2l0aG91dFN1ZmZpeCA/ICfQvNC40L3Rg9GC0LBf0LzQuNC90YPRgtGLX9C80LjQvdGD0YInIDogJ9C80LjQvdGD0YLRg1/QvNC40L3Rg9GC0Ytf0LzQuNC90YPRgicsXG4gICAgICAgICdoaCc6ICfRh9Cw0YFf0YfQsNGB0LBf0YfQsNGB0L7QsicsXG4gICAgICAgICdkZCc6ICfQtNC10L3RjF/QtNC90Y9f0LTQvdC10LknLFxuICAgICAgICAnTU0nOiAn0LzQtdGB0Y/Rhl/QvNC10YHRj9GG0LBf0LzQtdGB0Y/RhtC10LInLFxuICAgICAgICAneXknOiAn0LPQvtC0X9Cz0L7QtNCwX9C70LXRgidcbiAgICB9O1xuICAgIGlmIChrZXkgPT09ICdtJykge1xuICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICfQvNC40L3Rg9GC0LAnIDogJ9C80LjQvdGD0YLRgyc7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgcGx1cmFsKGZvcm1hdFtrZXldLCArbnVtYmVyKTtcbiAgICB9XG59XG52YXIgbW9udGhzUGFyc2UgPSBbL17Rj9C90LIvaSwgL17RhNC10LIvaSwgL17QvNCw0YAvaSwgL17QsNC/0YAvaSwgL17QvNCwW9C50Y9dL2ksIC9e0LjRjtC9L2ksIC9e0LjRjtC7L2ksIC9e0LDQstCzL2ksIC9e0YHQtdC9L2ksIC9e0L7QutGCL2ksIC9e0L3QvtGPL2ksIC9e0LTQtdC6L2ldO1xuXG4vLyBodHRwOi8vbmV3LmdyYW1vdGEucnUvc3ByYXZrYS9ydWxlcy8xMzktcHJvcCA6IMKnIDEwM1xuLy8g0KHQvtC60YDQsNGJ0LXQvdC40Y8g0LzQtdGB0Y/RhtC10LI6IGh0dHA6Ly9uZXcuZ3JhbW90YS5ydS9zcHJhdmthL2J1cm8vc2VhcmNoLWFuc3dlcj9zPTI0MjYzN1xuLy8gQ0xEUiBkYXRhOiAgICAgICAgICBodHRwOi8vd3d3LnVuaWNvZGUub3JnL2NsZHIvY2hhcnRzLzI4L3N1bW1hcnkvcnUuaHRtbCMxNzUzXG52YXIgcnUgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdydScsIHtcbiAgICBtb250aHMgOiB7XG4gICAgICAgIGZvcm1hdDogJ9GP0L3QstCw0YDRj1/RhNC10LLRgNCw0LvRj1/QvNCw0YDRgtCwX9Cw0L/RgNC10LvRj1/QvNCw0Y9f0LjRjtC90Y9f0LjRjtC70Y9f0LDQstCz0YPRgdGC0LBf0YHQtdC90YLRj9Cx0YDRj1/QvtC60YLRj9Cx0YDRj1/QvdC+0Y/QsdGA0Y9f0LTQtdC60LDQsdGA0Y8nLnNwbGl0KCdfJyksXG4gICAgICAgIHN0YW5kYWxvbmU6ICfRj9C90LLQsNGA0Yxf0YTQtdCy0YDQsNC70Yxf0LzQsNGA0YJf0LDQv9GA0LXQu9GMX9C80LDQuV/QuNGO0L3RjF/QuNGO0LvRjF/QsNCy0LPRg9GB0YJf0YHQtdC90YLRj9Cx0YDRjF/QvtC60YLRj9Cx0YDRjF/QvdC+0Y/QsdGA0Yxf0LTQtdC60LDQsdGA0YwnLnNwbGl0KCdfJylcbiAgICB9LFxuICAgIG1vbnRoc1Nob3J0IDoge1xuICAgICAgICAvLyDQv9C+IENMRFIg0LjQvNC10L3QvdC+IFwi0LjRjtC7LlwiINC4IFwi0LjRjtC9LlwiLCDQvdC+INC60LDQutC+0Lkg0YHQvNGL0YHQuyDQvNC10L3Rj9GC0Ywg0LHRg9C60LLRgyDQvdCwINGC0L7Rh9C60YMgP1xuICAgICAgICBmb3JtYXQ6ICfRj9C90LIuX9GE0LXQstGALl/QvNCw0YAuX9Cw0L/RgC5f0LzQsNGPX9C40Y7QvdGPX9C40Y7Qu9GPX9Cw0LLQsy5f0YHQtdC90YIuX9C+0LrRgi5f0L3QvtGP0LEuX9C00LXQui4nLnNwbGl0KCdfJyksXG4gICAgICAgIHN0YW5kYWxvbmU6ICfRj9C90LIuX9GE0LXQstGALl/QvNCw0YDRgl/QsNC/0YAuX9C80LDQuV/QuNGO0L3RjF/QuNGO0LvRjF/QsNCy0LMuX9GB0LXQvdGCLl/QvtC60YIuX9C90L7Rj9CxLl/QtNC10LouJy5zcGxpdCgnXycpXG4gICAgfSxcbiAgICB3ZWVrZGF5cyA6IHtcbiAgICAgICAgc3RhbmRhbG9uZTogJ9Cy0L7RgdC60YDQtdGB0LXQvdGM0LVf0L/QvtC90LXQtNC10LvRjNC90LjQul/QstGC0L7RgNC90LjQul/RgdGA0LXQtNCwX9GH0LXRgtCy0LXRgNCzX9C/0Y/RgtC90LjRhtCwX9GB0YPQsdCx0L7RgtCwJy5zcGxpdCgnXycpLFxuICAgICAgICBmb3JtYXQ6ICfQstC+0YHQutGA0LXRgdC10L3RjNC1X9C/0L7QvdC10LTQtdC70YzQvdC40Lpf0LLRgtC+0YDQvdC40Lpf0YHRgNC10LTRg1/Rh9C10YLQstC10YDQs1/Qv9GP0YLQvdC40YbRg1/RgdGD0LHQsdC+0YLRgycuc3BsaXQoJ18nKSxcbiAgICAgICAgaXNGb3JtYXQ6IC9cXFsgP1vQktCyXSA/KD860L/RgNC+0YjQu9GD0Y580YHQu9C10LTRg9GO0YnRg9GOfNGN0YLRgyk/ID9cXF0gP2RkZGQvXG4gICAgfSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9Cy0YFf0L/QvV/QstGCX9GB0YBf0YfRgl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn0LLRgV/Qv9C9X9Cy0YJf0YHRgF/Rh9GCX9C/0YJf0YHQsScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlLFxuICAgIGxvbmdNb250aHNQYXJzZSA6IG1vbnRoc1BhcnNlLFxuICAgIHNob3J0TW9udGhzUGFyc2UgOiBtb250aHNQYXJzZSxcblxuICAgIC8vINC/0L7Qu9C90YvQtSDQvdCw0LfQstCw0L3QuNGPINGBINC/0LDQtNC10LbQsNC80LgsINC/0L4g0YLRgNC4INCx0YPQutCy0YssINC00LvRjyDQvdC10LrQvtGC0L7RgNGL0YUsINC/0L4gNCDQsdGD0LrQstGLLCDRgdC+0LrRgNCw0YnQtdC90LjRjyDRgSDRgtC+0YfQutC+0Lkg0Lgg0LHQtdC3INGC0L7Rh9C60LhcbiAgICBtb250aHNSZWdleDogL14o0Y/QvdCy0LDRgFvRjNGPXXzRj9C90LJcXC4/fNGE0LXQstGA0LDQu1vRjNGPXXzRhNC10LLRgD9cXC4/fNC80LDRgNGC0LA/fNC80LDRgFxcLj980LDQv9GA0LXQu1vRjNGPXXzQsNC/0YBcXC4/fNC80LBb0LnRj1180LjRjtC9W9GM0Y9dfNC40Y7QvVxcLj980LjRjtC7W9GM0Y9dfNC40Y7Qu1xcLj980LDQstCz0YPRgdGC0LA/fNCw0LLQs1xcLj980YHQtdC90YLRj9Cx0YBb0YzRj1180YHQtdC90YI/XFwuP3zQvtC60YLRj9Cx0YBb0YzRj1180L7QutGCXFwuP3zQvdC+0Y/QsdGAW9GM0Y9dfNC90L7Rj9CxP1xcLj980LTQtdC60LDQsdGAW9GM0Y9dfNC00LXQulxcLj8pL2ksXG5cbiAgICAvLyDQutC+0L/QuNGPINC/0YDQtdC00YvQtNGD0YnQtdCz0L5cbiAgICBtb250aHNTaG9ydFJlZ2V4OiAvXijRj9C90LLQsNGAW9GM0Y9dfNGP0L3QslxcLj980YTQtdCy0YDQsNC7W9GM0Y9dfNGE0LXQstGAP1xcLj980LzQsNGA0YLQsD980LzQsNGAXFwuP3zQsNC/0YDQtdC7W9GM0Y9dfNCw0L/RgFxcLj980LzQsFvQudGPXXzQuNGO0L1b0YzRj1180LjRjtC9XFwuP3zQuNGO0Ltb0YzRj1180LjRjtC7XFwuP3zQsNCy0LPRg9GB0YLQsD980LDQstCzXFwuP3zRgdC10L3RgtGP0LHRgFvRjNGPXXzRgdC10L3Rgj9cXC4/fNC+0LrRgtGP0LHRgFvRjNGPXXzQvtC60YJcXC4/fNC90L7Rj9Cx0YBb0YzRj1180L3QvtGP0LE/XFwuP3zQtNC10LrQsNCx0YBb0YzRj1180LTQtdC6XFwuPykvaSxcblxuICAgIC8vINC/0L7Qu9C90YvQtSDQvdCw0LfQstCw0L3QuNGPINGBINC/0LDQtNC10LbQsNC80LhcbiAgICBtb250aHNTdHJpY3RSZWdleDogL14o0Y/QvdCy0LDRgFvRj9GMXXzRhNC10LLRgNCw0Ltb0Y/RjF180LzQsNGA0YLQsD980LDQv9GA0LXQu1vRj9GMXXzQvNCwW9GP0LldfNC40Y7QvVvRj9GMXXzQuNGO0Ltb0Y/RjF180LDQstCz0YPRgdGC0LA/fNGB0LXQvdGC0Y/QsdGAW9GP0YxdfNC+0LrRgtGP0LHRgFvRj9GMXXzQvdC+0Y/QsdGAW9GP0YxdfNC00LXQutCw0LHRgFvRj9GMXSkvaSxcblxuICAgIC8vINCS0YvRgNCw0LbQtdC90LjQtSwg0LrQvtGC0L7RgNC+0LUg0YHQvtC+0YLQstC10YHRgtCy0YPQtdGCINGC0L7Qu9GM0LrQviDRgdC+0LrRgNCw0YnRkdC90L3Ri9C8INGE0L7RgNC80LDQvFxuICAgIG1vbnRoc1Nob3J0U3RyaWN0UmVnZXg6IC9eKNGP0L3QslxcLnzRhNC10LLRgD9cXC580LzQsNGAW9GCLl180LDQv9GAXFwufNC80LBb0Y/QuV180LjRjtC9W9GM0Y8uXXzQuNGO0Ltb0YzRjy5dfNCw0LLQs1xcLnzRgdC10L3Rgj9cXC580L7QutGCXFwufNC90L7Rj9CxP1xcLnzQtNC10LpcXC4pL2ksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZINCzLicsXG4gICAgICAgIExMTCA6ICdEIE1NTU0gWVlZWSDQsy4sIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZINCzLiwgSDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW9Ch0LXQs9C+0LTQvdGPINCyXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb0JfQsNCy0YLRgNCwINCyXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdb0JLRh9C10YDQsCDQsl0gTFQnLFxuICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKG5vdykge1xuICAgICAgICAgICAgaWYgKG5vdy53ZWVrKCkgIT09IHRoaXMud2VlaygpKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINGB0LvQtdC00YPRjtGJ0LXQtV0gZGRkZCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINGB0LvQtdC00YPRjtGJ0LjQuV0gZGRkZCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINGB0LvQtdC00YPRjtGJ0YPRjl0gZGRkZCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRheSgpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CS0L5dIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JJdIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXN0V2VlazogZnVuY3Rpb24gKG5vdykge1xuICAgICAgICAgICAgaWYgKG5vdy53ZWVrKCkgIT09IHRoaXMud2VlaygpKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CSINC/0YDQvtGI0LvQvtC1XSBkZGRkIFvQsl0gTFQnO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JIg0L/RgNC+0YjQu9GL0LldIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vQkiDQv9GA0L7RiNC70YPRjl0gZGRkZCBb0LJdIExUJztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRheSgpID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9CS0L5dIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdb0JJdIGRkZGQgW9CyXSBMVCc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfRh9C10YDQtdC3ICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyDQvdCw0LfQsNC0JyxcbiAgICAgICAgcyA6ICfQvdC10YHQutC+0LvRjNC60L4g0YHQtdC60YPQvdC0JyxcbiAgICAgICAgc3MgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBtIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgbW0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBoIDogJ9GH0LDRgScsXG4gICAgICAgIGhoIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgZCA6ICfQtNC10L3RjCcsXG4gICAgICAgIGRkIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgTSA6ICfQvNC10YHRj9GGJyxcbiAgICAgICAgTU0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICB5IDogJ9Cz0L7QtCcsXG4gICAgICAgIHl5IDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbFxuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL9C90L7Rh9C4fNGD0YLRgNCwfNC00L3Rj3zQstC10YfQtdGA0LAvaSxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXijQtNC90Y980LLQtdGH0LXRgNCwKSQvLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfQvdC+0YfQuCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ9GD0YLRgNCwJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTcpIHtcbiAgICAgICAgICAgIHJldHVybiAn0LTQvdGPJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn0LLQtdGH0LXRgNCwJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9LSjQuXzQs9C+fNGPKS8sXG4gICAgb3JkaW5hbDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgIGNhc2UgJ2QnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QuSc7XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3Qs9C+JztcbiAgICAgICAgICAgIGNhc2UgJ3cnOlxuICAgICAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICct0Y8nO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gcnU7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3J1LmpzXG4vLyBtb2R1bGUgaWQgPSA5MlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU2luZGhpIFtzZF1cbi8vISBhdXRob3IgOiBOYXJhaW4gU2FnYXIgOiBodHRwczovL2dpdGh1Yi5jb20vbmFyYWluc2FnYXJcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbW9udGhzID0gW1xuICAgICfYrNmG2YjYsdmKJyxcbiAgICAn2YHZitio2LHZiNix2YonLFxuICAgICfZhdin2LHahicsXG4gICAgJ9in2b7YsdmK2YQnLFxuICAgICfZhdim2YonLFxuICAgICfYrNmI2YYnLFxuICAgICfYrNmI2YTYp9ih2ZAnLFxuICAgICfYotqv2LPZvScsXG4gICAgJ9iz2YrZvtm92YXYqNixJyxcbiAgICAn2KLaqtm92YjYqNixJyxcbiAgICAn2YbZiNmF2KjYsScsXG4gICAgJ9qK2LPZhdio2LEnXG5dO1xudmFyIGRheXMgPSBbXG4gICAgJ9ii2obYsScsXG4gICAgJ9iz2YjZhdixJyxcbiAgICAn2Kfasdin2LHZiCcsXG4gICAgJ9in2LHYqNi5JyxcbiAgICAn2K7ZhdmK2LMnLFxuICAgICfYrNmF2LknLFxuICAgICfah9mG2ofYsSdcbl07XG5cbnZhciBzZCA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3NkJywge1xuICAgIG1vbnRocyA6IG1vbnRocyxcbiAgICBtb250aHNTaG9ydCA6IG1vbnRocyxcbiAgICB3ZWVrZGF5cyA6IGRheXMsXG4gICAgd2Vla2RheXNTaG9ydCA6IGRheXMsXG4gICAgd2Vla2RheXNNaW4gOiBkYXlzLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRk2IwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv2LXYqNitfNi02KfZhS8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gJ9i02KfZhScgPT09IGlucHV0O1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn2LXYqNitJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJ9i02KfZhSc7XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb2KfahF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vYs9qA2Kfau9mKXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW9in2rPZitmGINmH2YHYqtmKINiq2YpdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb2qrYp9mE2YfZh10gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb2q/Ystix2YrZhCDZh9mB2KrZil0gZGRkZCBb2KrZil0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMg2b7ZiNihJyxcbiAgICAgICAgcGFzdCA6ICclcyDYp9qzJyxcbiAgICAgICAgcyA6ICfahtmG2K8g2LPZitqq2YbaiicsXG4gICAgICAgIHNzIDogJyVkINiz2YraqtmG2oonLFxuICAgICAgICBtIDogJ9mH2qog2YXZhtm9JyxcbiAgICAgICAgbW0gOiAnJWQg2YXZhtm9JyxcbiAgICAgICAgaCA6ICfZh9qqINqq2YTYp9qqJyxcbiAgICAgICAgaGggOiAnJWQg2qrZhNin2qonLFxuICAgICAgICBkIDogJ9mH2qog2o/ZitmG2YfZhicsXG4gICAgICAgIGRkIDogJyVkINqP2YrZhtmH2YYnLFxuICAgICAgICBNIDogJ9mH2qog2YXZh9mK2YbZiCcsXG4gICAgICAgIE1NIDogJyVkINmF2YfZitmG2KcnLFxuICAgICAgICB5IDogJ9mH2qog2LPYp9mEJyxcbiAgICAgICAgeXkgOiAnJWQg2LPYp9mEJ1xuICAgIH0sXG4gICAgcHJlcGFyc2U6IGZ1bmN0aW9uIChzdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5yZXBsYWNlKC/YjC9nLCAnLCcpO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoLywvZywgJ9iMJyk7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gc2Q7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3NkLmpzXG4vLyBtb2R1bGUgaWQgPSA5M1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogTm9ydGhlcm4gU2FtaSBbc2VdXG4vLyEgYXV0aG9ycyA6IELDpXJkIFJvbHN0YWQgSGVucmlrc2VuIDogaHR0cHM6Ly9naXRodWIuY29tL2thcmFtZWxsXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxuXG52YXIgc2UgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdzZScsIHtcbiAgICBtb250aHMgOiAnb8SRxJFhamFnZW3DoW5udV9ndW92dmFtw6FubnVfbmp1a8SNYW3DoW5udV9jdW/Fi29tw6FubnVfbWllc3NlbcOhbm51X2dlYXNzZW3DoW5udV9zdW9pZG5lbcOhbm51X2JvcmdlbcOhbm51X8SNYWvEjWFtw6FubnVfZ29sZ2dvdG3DoW5udV9za8OhYm1hbcOhbm51X2p1b3ZsYW3DoW5udScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdvxJHEkWpfZ3Vvdl9uanVrX2N1b19taWVzX2dlYXNfc3VvaV9ib3JnX8SNYWvEjV9nb2xnX3Nrw6FiX2p1b3YnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnc290bmFiZWFpdmlfdnVvc3PDoXJnYV9tYcWLxYtlYsOhcmdhX2dhc2thdmFoa2t1X2R1b3Jhc3RhdF9iZWFyamFkYXRfbMOhdnZhcmRhdCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ3NvdG5fdnVvc19tYcWLX2dhc2tfZHVvcl9iZWFyX2zDoXYnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnc192X21fZ19kX2JfTCcuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdNTU1NIEQuIFtiLl0gWVlZWScsXG4gICAgICAgIExMTCA6ICdNTU1NIEQuIFtiLl0gWVlZWSBbdGkuXSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgTU1NTSBELiBbYi5dIFlZWVkgW3RpLl0gSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tvdG5lIHRpXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbaWh0dGluIHRpXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbdGldIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tpa3RlIHRpXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW292ZGRpdF0gZGRkZCBbdGldIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMgZ2Vhxb5lcycsXG4gICAgICAgIHBhc3QgOiAnbWHFi2l0ICVzJyxcbiAgICAgICAgcyA6ICdtb2FkZGUgc2VrdW5kZGF0JyxcbiAgICAgICAgc3M6ICclZCBzZWt1bmRkYXQnLFxuICAgICAgICBtIDogJ29rdGEgbWludWh0YScsXG4gICAgICAgIG1tIDogJyVkIG1pbnVodGF0JyxcbiAgICAgICAgaCA6ICdva3RhIGRpaW1tdScsXG4gICAgICAgIGhoIDogJyVkIGRpaW1tdXQnLFxuICAgICAgICBkIDogJ29rdGEgYmVhaXZpJyxcbiAgICAgICAgZGQgOiAnJWQgYmVhaXZ2aXQnLFxuICAgICAgICBNIDogJ29rdGEgbcOhbm51JyxcbiAgICAgICAgTU0gOiAnJWQgbcOhbnV0JyxcbiAgICAgICAgeSA6ICdva3RhIGphaGtpJyxcbiAgICAgICAgeXkgOiAnJWQgamFnaXQnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gc2U7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3NlLmpzXG4vLyBtb2R1bGUgaWQgPSA5NFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU2luaGFsZXNlIFtzaV1cbi8vISBhdXRob3IgOiBTYW1wYXRoIFNpdGluYW1hbHV3YSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9zYW1wYXRoc3Jpc1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbi8qanNoaW50IC1XMTAwKi9cbnZhciBzaSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3NpJywge1xuICAgIG1vbnRocyA6ICfgtqLgtrHgt4Dgt4/gtrvgt5Jf4La04LeZ4La24La74LeA4LeP4La74LeSX+C2uOC3j+C2u+C3iuC2reC3lF/gtoXgtrTgt4rigI3gtrvgt5rgtr3gt4pf4La44LeQ4La64LeSX+C2ouC3luC2seC3kl/gtqLgt5bgtr3gt5Jf4LaF4Lac4Led4LeD4LeK4Lat4LeUX+C3g+C3kOC2tOC3iuC2reC3kOC2uOC3iuC2tuC2u+C3il/gtpTgtprgt4rgtq3gt53gtrbgtrvgt4pf4Lax4Lec4LeA4LeQ4La44LeK4La24La74LeKX+C2r+C3meC3g+C3kOC2uOC3iuC2tuC2u+C3iicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgtqLgtrFf4La04LeZ4La2X+C2uOC3j+C2u+C3il/gtoXgtrTgt4pf4La44LeQ4La64LeSX+C2ouC3luC2seC3kl/gtqLgt5bgtr3gt5Jf4LaF4Lac4LedX+C3g+C3kOC2tOC3il/gtpTgtprgt4pf4Lax4Lec4LeA4LeQX+C2r+C3meC3g+C3kCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfgtongtrvgt5Lgtq/gt49f4LeD4Laz4LeU4Lav4LePX+C2heC2n+C3hOC2u+C3lOC3gOC3j+C2r+C3j1/gtrbgtq/gt4/gtq/gt49f4La24LeK4oCN4La74LeE4LeD4LeK4La04Lat4LeS4Lax4LeK4Lav4LePX+C3g+C3kuC2muC3lOC2u+C3j+C2r+C3j1/gt4Pgt5ngtrHgt4Pgt5Tgtrvgt4/gtq/gt48nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgtongtrvgt5Jf4LeD4Laz4LeUX+C2heC2n1/gtrbgtq/gt49f4La24LeK4oCN4La74LeEX+C3g+C3kuC2muC3lF/gt4Pgt5ngtrEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4LaJX+C3g1/gtoVf4La2X+C2tuC3iuKAjeC2u1/gt4Pgt5Jf4LeD4LeZJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ2EgaDptbScsXG4gICAgICAgIExUUyA6ICdhIGg6bW06c3MnLFxuICAgICAgICBMIDogJ1lZWVkvTU0vREQnLFxuICAgICAgICBMTCA6ICdZWVlZIE1NTU0gRCcsXG4gICAgICAgIExMTCA6ICdZWVlZIE1NTU0gRCwgYSBoOm1tJyxcbiAgICAgICAgTExMTCA6ICdZWVlZIE1NTU0gRCBb4LeA4LeQ4Lax4LeSXSBkZGRkLCBhIGg6bW06c3MnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb4LaF4LavXSBMVFvgtqddJyxcbiAgICAgICAgbmV4dERheSA6ICdb4LeE4LeZ4LanXSBMVFvgtqddJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBMVFvgtqddJyxcbiAgICAgICAgbGFzdERheSA6ICdb4LaK4La64LeaXSBMVFvgtqddJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+C2tOC3g+C3lOC2nOC3kuC2ul0gZGRkZCBMVFvgtqddJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVz4Laa4LeS4Lax4LeKJyxcbiAgICAgICAgcGFzdCA6ICclc+C2muC2pyDgtrTgt5ngtrsnLFxuICAgICAgICBzIDogJ+C2reC2reC3iuC2tOC2uyDgtprgt5Lgt4Tgt5LgtrTgtronLFxuICAgICAgICBzcyA6ICfgtq3gtq3gt4rgtrTgtrsgJWQnLFxuICAgICAgICBtIDogJ+C2uOC3kuC2seC3kuC2reC3iuC2reC3lOC3gCcsXG4gICAgICAgIG1tIDogJ+C2uOC3kuC2seC3kuC2reC3iuC2reC3lCAlZCcsXG4gICAgICAgIGggOiAn4La04LeQ4La6JyxcbiAgICAgICAgaGggOiAn4La04LeQ4La6ICVkJyxcbiAgICAgICAgZCA6ICfgtq/gt5LgtrHgtronLFxuICAgICAgICBkZCA6ICfgtq/gt5LgtrEgJWQnLFxuICAgICAgICBNIDogJ+C2uOC3j+C3g+C2uicsXG4gICAgICAgIE1NIDogJ+C2uOC3j+C3gyAlZCcsXG4gICAgICAgIHkgOiAn4LeA4LeD4La7JyxcbiAgICAgICAgeXkgOiAn4LeA4LeD4La7ICVkJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9IOC3gOC3kOC2seC3ki8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciArICcg4LeA4LeQ4Lax4LeSJztcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2UgOiAv4La04LeZ4La7IOC3gOC2u+C3lHzgtrTgt4Pgt4og4LeA4La74LeUfOC2tOC3mS7gt4B84La0LuC3gC4vLFxuICAgIGlzUE0gOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ID09PSAn4La0LuC3gC4nIHx8IGlucHV0ID09PSAn4La04LeD4LeKIOC3gOC2u+C3lCc7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAn4La0LuC3gC4nIDogJ+C2tOC3g+C3iiDgt4Dgtrvgt5QnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAn4La04LeZLuC3gC4nIDogJ+C2tOC3meC2uyDgt4Dgtrvgt5QnO1xuICAgICAgICB9XG4gICAgfVxufSk7XG5cbnJldHVybiBzaTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvc2kuanNcbi8vIG1vZHVsZSBpZCA9IDk1XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBTbG92YWsgW3NrXVxuLy8hIGF1dGhvciA6IE1hcnRpbiBNaW5rYSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9rMnNcbi8vISBiYXNlZCBvbiB3b3JrIG9mIHBldHJiZWxhIDogaHR0cHM6Ly9naXRodWIuY29tL3BldHJiZWxhXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIG1vbnRocyA9ICdqYW51w6FyX2ZlYnJ1w6FyX21hcmVjX2FwcsOtbF9tw6FqX2rDum5fasO6bF9hdWd1c3Rfc2VwdGVtYmVyX29rdMOzYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpO1xudmFyIG1vbnRoc1Nob3J0ID0gJ2phbl9mZWJfbWFyX2Fwcl9tw6FqX2rDum5fasO6bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpO1xuZnVuY3Rpb24gcGx1cmFsKG4pIHtcbiAgICByZXR1cm4gKG4gPiAxKSAmJiAobiA8IDUpO1xufVxuZnVuY3Rpb24gdHJhbnNsYXRlKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciByZXN1bHQgPSBudW1iZXIgKyAnICc7XG4gICAgc3dpdGNoIChrZXkpIHtcbiAgICAgICAgY2FzZSAncyc6ICAvLyBhIGZldyBzZWNvbmRzIC8gaW4gYSBmZXcgc2Vjb25kcyAvIGEgZmV3IHNlY29uZHMgYWdvXG4gICAgICAgICAgICByZXR1cm4gKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpID8gJ3DDoXIgc2Vrw7puZCcgOiAncMOhciBzZWt1bmRhbWknO1xuICAgICAgICBjYXNlICdzcyc6IC8vIDkgc2Vjb25kcyAvIGluIDkgc2Vjb25kcyAvIDkgc2Vjb25kcyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwobnVtYmVyKSA/ICdzZWt1bmR5JyA6ICdzZWvDum5kJyk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAnc2VrdW5kYW1pJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdtJzogIC8vIGEgbWludXRlIC8gaW4gYSBtaW51dGUgLyBhIG1pbnV0ZSBhZ29cbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ21pbsO6dGEnIDogKGlzRnV0dXJlID8gJ21pbsO6dHUnIDogJ21pbsO6dG91Jyk7XG4gICAgICAgIGNhc2UgJ21tJzogLy8gOSBtaW51dGVzIC8gaW4gOSBtaW51dGVzIC8gOSBtaW51dGVzIGFnb1xuICAgICAgICAgICAgaWYgKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgKHBsdXJhbChudW1iZXIpID8gJ21pbsO6dHknIDogJ21pbsO6dCcpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ21pbsO6dGFtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnaCc6ICAvLyBhbiBob3VyIC8gaW4gYW4gaG91ciAvIGFuIGhvdXIgYWdvXG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdob2RpbmEnIDogKGlzRnV0dXJlID8gJ2hvZGludScgOiAnaG9kaW5vdScpO1xuICAgICAgICBjYXNlICdoaCc6IC8vIDkgaG91cnMgLyBpbiA5IGhvdXJzIC8gOSBob3VycyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwobnVtYmVyKSA/ICdob2RpbnknIDogJ2hvZMOtbicpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ2hvZGluYW1pJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdkJzogIC8vIGEgZGF5IC8gaW4gYSBkYXkgLyBhIGRheSBhZ29cbiAgICAgICAgICAgIHJldHVybiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkgPyAnZGXFiCcgOiAnZMWIb20nO1xuICAgICAgICBjYXNlICdkZCc6IC8vIDkgZGF5cyAvIGluIDkgZGF5cyAvIDkgZGF5cyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwobnVtYmVyKSA/ICdkbmknIDogJ2Ruw60nKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdkxYhhbWknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ00nOiAgLy8gYSBtb250aCAvIGluIGEgbW9udGggLyBhIG1vbnRoIGFnb1xuICAgICAgICAgICAgcmV0dXJuICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSA/ICdtZXNpYWMnIDogJ21lc2lhY29tJztcbiAgICAgICAgY2FzZSAnTU0nOiAvLyA5IG1vbnRocyAvIGluIDkgbW9udGhzIC8gOSBtb250aHMgYWdvXG4gICAgICAgICAgICBpZiAod2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKyAocGx1cmFsKG51bWJlcikgPyAnbWVzaWFjZScgOiAnbWVzaWFjb3YnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArICdtZXNpYWNtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAneSc6ICAvLyBhIHllYXIgLyBpbiBhIHllYXIgLyBhIHllYXIgYWdvXG4gICAgICAgICAgICByZXR1cm4gKHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUpID8gJ3JvaycgOiAncm9rb20nO1xuICAgICAgICBjYXNlICd5eSc6IC8vIDkgeWVhcnMgLyBpbiA5IHllYXJzIC8gOSB5ZWFycyBhZ29cbiAgICAgICAgICAgIGlmICh3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdCArIChwbHVyYWwobnVtYmVyKSA/ICdyb2t5JyA6ICdyb2tvdicpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0ICsgJ3Jva21pJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgIH1cbn1cblxudmFyIHNrID0gbW9tZW50LmRlZmluZUxvY2FsZSgnc2snLCB7XG4gICAgbW9udGhzIDogbW9udGhzLFxuICAgIG1vbnRoc1Nob3J0IDogbW9udGhzU2hvcnQsXG4gICAgd2Vla2RheXMgOiAnbmVkZcS+YV9wb25kZWxva191dG9yb2tfc3RyZWRhX8WhdHZydG9rX3BpYXRva19zb2JvdGEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICduZV9wb191dF9zdF/FoXRfcGlfc28nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnbmVfcG9fdXRfc3RfxaF0X3BpX3NvJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTCA6ICdELiBNTU1NIFlZWVkgSDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCBELiBNTU1NIFlZWVkgSDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW2RuZXMgb10gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW3phanRyYSBvXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3YgbmVkZcS+dSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdl0gZGRkZCBbb10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBzdHJlZHUgb10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdm8gxaF0dnJ0b2sgb10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBwaWF0b2sgb10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdiBzb2JvdHUgb10gTFQnO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBsYXN0RGF5OiAnW3bEjWVyYSBvXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw7ogbmVkZcS+dSBvXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDvV0gZGRkZCBbb10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbbWludWzDuiBzdHJlZHUgb10gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw71dIGRkZGQgW29dIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW21pbnVsw7ogc29ib3R1IG9dIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnemEgJXMnLFxuICAgICAgICBwYXN0IDogJ3ByZWQgJXMnLFxuICAgICAgICBzIDogdHJhbnNsYXRlLFxuICAgICAgICBzcyA6IHRyYW5zbGF0ZSxcbiAgICAgICAgbSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgbW0gOiB0cmFuc2xhdGUsXG4gICAgICAgIGggOiB0cmFuc2xhdGUsXG4gICAgICAgIGhoIDogdHJhbnNsYXRlLFxuICAgICAgICBkIDogdHJhbnNsYXRlLFxuICAgICAgICBkZCA6IHRyYW5zbGF0ZSxcbiAgICAgICAgTSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgTU0gOiB0cmFuc2xhdGUsXG4gICAgICAgIHkgOiB0cmFuc2xhdGUsXG4gICAgICAgIHl5IDogdHJhbnNsYXRlXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gc2s7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3NrLmpzXG4vLyBtb2R1bGUgaWQgPSA5NlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogU2xvdmVuaWFuIFtzbF1cbi8vISBhdXRob3IgOiBSb2JlcnQgU2Vkb3bFoWVrIDogaHR0cHM6Ly9naXRodWIuY29tL3NlZG92c2VrXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxuZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aXZlVGltZShudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSwgaXNGdXR1cmUpIHtcbiAgICB2YXIgcmVzdWx0ID0gbnVtYmVyICsgJyAnO1xuICAgIHN3aXRjaCAoa2V5KSB7XG4gICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbmVrYWogc2VrdW5kJyA6ICduZWthaiBzZWt1bmRhbWknO1xuICAgICAgICBjYXNlICdzcyc6XG4gICAgICAgICAgICBpZiAobnVtYmVyID09PSAxKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggPyAnc2VrdW5kbycgOiAnc2VrdW5kaSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ3Nla3VuZGknIDogJ3Nla3VuZGFoJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgNSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ3Nla3VuZGUnIDogJ3Nla3VuZGFoJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnc2VrdW5kJyA6ICdzZWt1bmQnO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/ICdlbmEgbWludXRhJyA6ICdlbm8gbWludXRvJztcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4ID8gJ21pbnV0YScgOiAnbWludXRvJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWludXRpJyA6ICdtaW51dGFtYSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDUpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtaW51dGUnIDogJ21pbnV0YW1pJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWludXQnIDogJ21pbnV0YW1pJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIGNhc2UgJ2gnOlxuICAgICAgICAgICAgcmV0dXJuIHdpdGhvdXRTdWZmaXggPyAnZW5hIHVyYScgOiAnZW5vIHVybyc7XG4gICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgICAgIGlmIChudW1iZXIgPT09IDEpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCA/ICd1cmEnIDogJ3Vybyc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ3VyaScgOiAndXJhbWEnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChudW1iZXIgPCA1KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAndXJlJyA6ICd1cmFtaSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ3VyJyA6ICd1cmFtaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2VuIGRhbicgOiAnZW5pbSBkbmVtJztcbiAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2RhbicgOiAnZG5lbSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA9PT0gMikge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2RuaScgOiAnZG5ldm9tYSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2RuaScgOiAnZG5ldmknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgY2FzZSAnTSc6XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdlbiBtZXNlYycgOiAnZW5pbSBtZXNlY2VtJztcbiAgICAgICAgY2FzZSAnTU0nOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ21lc2VjJyA6ICdtZXNlY2VtJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbWVzZWNhJyA6ICdtZXNlY2VtYSc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bWJlciA8IDUpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdtZXNlY2UnIDogJ21lc2VjaSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ21lc2VjZXYnIDogJ21lc2VjaSc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICBjYXNlICd5JzpcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2VubyBsZXRvJyA6ICdlbmltIGxldG9tJztcbiAgICAgICAgY2FzZSAneXknOlxuICAgICAgICAgICAgaWYgKG51bWJlciA9PT0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2xldG8nIDogJ2xldG9tJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyID09PSAyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ICs9IHdpdGhvdXRTdWZmaXggfHwgaXNGdXR1cmUgPyAnbGV0aScgOiAnbGV0b21hJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAobnVtYmVyIDwgNSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCArPSB3aXRob3V0U3VmZml4IHx8IGlzRnV0dXJlID8gJ2xldGEnIDogJ2xldGknO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgKz0gd2l0aG91dFN1ZmZpeCB8fCBpc0Z1dHVyZSA/ICdsZXQnIDogJ2xldGknO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG59XG5cbnZhciBzbCA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3NsJywge1xuICAgIG1vbnRocyA6ICdqYW51YXJfZmVicnVhcl9tYXJlY19hcHJpbF9tYWpfanVuaWpfanVsaWpfYXZndXN0X3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbi5fZmViLl9tYXIuX2Fwci5fbWFqLl9qdW4uX2p1bC5fYXZnLl9zZXAuX29rdC5fbm92Ll9kZWMuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnbmVkZWxqYV9wb25lZGVsamVrX3RvcmVrX3NyZWRhX8SNZXRydGVrX3BldGVrX3NvYm90YScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ25lZC5fcG9uLl90b3IuX3NyZS5fxI1ldC5fcGV0Ll9zb2IuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ25lX3BvX3RvX3NyX8SNZV9wZV9zbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMIDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTCA6ICdELiBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgIDogJ1tkYW5lcyBvYl0gTFQnLFxuICAgICAgICBuZXh0RGF5ICA6ICdbanV0cmkgb2JdIExUJyxcblxuICAgICAgICBuZXh0V2VlayA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5kYXkoKSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdl0gW25lZGVsam9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdl0gW3NyZWRvXSBbb2JdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ZdIFtzb2JvdG9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbdl0gZGRkZCBbb2JdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSAgOiAnW3bEjWVyYWogb2JdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ByZWrFoW5qb10gW25lZGVsam9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJlasWhbmpvXSBbc3JlZG9dIFtvYl0gTFQnO1xuICAgICAgICAgICAgICAgIGNhc2UgNjpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuICdbcHJlasWhbmpvXSBbc29ib3RvXSBbb2JdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgNDpcbiAgICAgICAgICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3ByZWrFoW5qaV0gZGRkZCBbb2JdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ8SNZXogJXMnLFxuICAgICAgICBwYXN0ICAgOiAncHJlZCAlcycsXG4gICAgICAgIHMgICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIHNzICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIG0gICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIG1tICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIGggICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIGhoICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIGQgICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIGRkICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIE0gICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIE1NICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIHkgICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWUsXG4gICAgICAgIHl5ICAgICA6IHByb2Nlc3NSZWxhdGl2ZVRpbWVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBzbDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvc2wuanNcbi8vIG1vZHVsZSBpZCA9IDk3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBBbGJhbmlhbiBbc3FdXG4vLyEgYXV0aG9yIDogRmxha8OrcmltIElzbWFuaSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9mbGFrZXJpbWlcbi8vISBhdXRob3IgOiBNZW5lbGlvbiBFbGVuc8O6bGUgOiBodHRwczovL2dpdGh1Yi5jb20vT2lyZVxuLy8hIGF1dGhvciA6IE9lcmQgQ3VrYWxsYSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9vZXJkXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHNxID0gbW9tZW50LmRlZmluZUxvY2FsZSgnc3EnLCB7XG4gICAgbW9udGhzIDogJ0phbmFyX1Noa3VydF9NYXJzX1ByaWxsX01hal9RZXJzaG9yX0tvcnJpa19HdXNodF9TaHRhdG9yX1RldG9yX07Dq250b3JfRGhqZXRvcicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdKYW5fU2hrX01hcl9QcmlfTWFqX1Flcl9Lb3JfR3VzX1NodF9UZXRfTsOrbl9EaGonLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnRSBEaWVsX0UgSMOrbsOrX0UgTWFydMOrX0UgTcOrcmt1csOrX0UgRW5qdGVfRSBQcmVtdGVfRSBTaHR1bsOrJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnRGllX0jDq25fTWFyX03Dq3JfRW5qX1ByZV9TaHQnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnRF9IX01hX03Dq19FX1BfU2gnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICBtZXJpZGllbVBhcnNlOiAvUER8TUQvLFxuICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQuY2hhckF0KDApID09PSAnTSc7XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VycywgbWludXRlcywgaXNMb3dlcikge1xuICAgICAgICByZXR1cm4gaG91cnMgPCAxMiA/ICdQRCcgOiAnTUQnO1xuICAgIH0sXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW1NvdCBuw6tdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbTmVzw6tyIG7Dq10gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtuw6tdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbRGplIG7Dq10gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFtlIGthbHVhciBuw6tdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ27DqyAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgbcOrIHBhcsOrJyxcbiAgICAgICAgcyA6ICdkaXNhIHNla29uZGEnLFxuICAgICAgICBzcyA6ICclZCBzZWtvbmRhJyxcbiAgICAgICAgbSA6ICduasOrIG1pbnV0w6snLFxuICAgICAgICBtbSA6ICclZCBtaW51dGEnLFxuICAgICAgICBoIDogJ25qw6sgb3LDqycsXG4gICAgICAgIGhoIDogJyVkIG9yw6snLFxuICAgICAgICBkIDogJ25qw6sgZGl0w6snLFxuICAgICAgICBkZCA6ICclZCBkaXTDqycsXG4gICAgICAgIE0gOiAnbmrDqyBtdWFqJyxcbiAgICAgICAgTU0gOiAnJWQgbXVhaicsXG4gICAgICAgIHkgOiAnbmrDqyB2aXQnLFxuICAgICAgICB5eSA6ICclZCB2aXRlJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHNxO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zcS5qc1xuLy8gbW9kdWxlIGlkID0gOThcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFNlcmJpYW4gW3NyXVxuLy8hIGF1dGhvciA6IE1pbGFuIEphbmHEjWtvdmnEhzxtaWxhbmphbmFja292aWNAZ21haWwuY29tPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWxhbi1qXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHRyYW5zbGF0b3IgPSB7XG4gICAgd29yZHM6IHsgLy9EaWZmZXJlbnQgZ3JhbW1hdGljYWwgY2FzZXNcbiAgICAgICAgc3M6IFsnc2VrdW5kYScsICdzZWt1bmRlJywgJ3Nla3VuZGknXSxcbiAgICAgICAgbTogWydqZWRhbiBtaW51dCcsICdqZWRuZSBtaW51dGUnXSxcbiAgICAgICAgbW06IFsnbWludXQnLCAnbWludXRlJywgJ21pbnV0YSddLFxuICAgICAgICBoOiBbJ2plZGFuIHNhdCcsICdqZWRub2cgc2F0YSddLFxuICAgICAgICBoaDogWydzYXQnLCAnc2F0YScsICdzYXRpJ10sXG4gICAgICAgIGRkOiBbJ2RhbicsICdkYW5hJywgJ2RhbmEnXSxcbiAgICAgICAgTU06IFsnbWVzZWMnLCAnbWVzZWNhJywgJ21lc2VjaSddLFxuICAgICAgICB5eTogWydnb2RpbmEnLCAnZ29kaW5lJywgJ2dvZGluYSddXG4gICAgfSxcbiAgICBjb3JyZWN0R3JhbW1hdGljYWxDYXNlOiBmdW5jdGlvbiAobnVtYmVyLCB3b3JkS2V5KSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgPT09IDEgPyB3b3JkS2V5WzBdIDogKG51bWJlciA+PSAyICYmIG51bWJlciA8PSA0ID8gd29yZEtleVsxXSA6IHdvcmRLZXlbMl0pO1xuICAgIH0sXG4gICAgdHJhbnNsYXRlOiBmdW5jdGlvbiAobnVtYmVyLCB3aXRob3V0U3VmZml4LCBrZXkpIHtcbiAgICAgICAgdmFyIHdvcmRLZXkgPSB0cmFuc2xhdG9yLndvcmRzW2tleV07XG4gICAgICAgIGlmIChrZXkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gd2l0aG91dFN1ZmZpeCA/IHdvcmRLZXlbMF0gOiB3b3JkS2V5WzFdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICcgJyArIHRyYW5zbGF0b3IuY29ycmVjdEdyYW1tYXRpY2FsQ2FzZShudW1iZXIsIHdvcmRLZXkpO1xuICAgICAgICB9XG4gICAgfVxufTtcblxudmFyIHNyID0gbW9tZW50LmRlZmluZUxvY2FsZSgnc3InLCB7XG4gICAgbW9udGhzOiAnamFudWFyX2ZlYnJ1YXJfbWFydF9hcHJpbF9tYWpfanVuX2p1bF9hdmd1c3Rfc2VwdGVtYmFyX29rdG9iYXJfbm92ZW1iYXJfZGVjZW1iYXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQ6ICdqYW4uX2ZlYi5fbWFyLl9hcHIuX21hal9qdW5fanVsX2F2Zy5fc2VwLl9va3QuX25vdi5fZGVjLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgIHdlZWtkYXlzOiAnbmVkZWxqYV9wb25lZGVsamFrX3V0b3Jha19zcmVkYV/EjWV0dnJ0YWtfcGV0YWtfc3Vib3RhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQ6ICduZWQuX3Bvbi5fdXRvLl9zcmUuX8SNZXQuX3BldC5fc3ViLicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbjogJ25lX3BvX3V0X3NyX8SNZV9wZV9zdScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0OiB7XG4gICAgICAgIExUOiAnSDptbScsXG4gICAgICAgIExUUyA6ICdIOm1tOnNzJyxcbiAgICAgICAgTDogJ0RELk1NLllZWVknLFxuICAgICAgICBMTDogJ0QuIE1NTU0gWVlZWScsXG4gICAgICAgIExMTDogJ0QuIE1NTU0gWVlZWSBIOm1tJyxcbiAgICAgICAgTExMTDogJ2RkZGQsIEQuIE1NTU0gWVlZWSBIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXI6IHtcbiAgICAgICAgc2FtZURheTogJ1tkYW5hcyB1XSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbc3V0cmEgdV0gTFQnLFxuICAgICAgICBuZXh0V2VlazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLmRheSgpKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBbbmVkZWxqdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzcmVkdV0gW3VdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW3VdIFtzdWJvdHVdIFt1XSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1t1XSBkZGRkIFt1XSBMVCc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIGxhc3REYXkgIDogJ1tqdcSNZSB1XSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGxhc3RXZWVrRGF5cyA9IFtcbiAgICAgICAgICAgICAgICAnW3Byb8WhbGVdIFtuZWRlbGplXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFtwb25lZGVsamthXSBbdV0gTFQnLFxuICAgICAgICAgICAgICAgICdbcHJvxaFsb2ddIFt1dG9ya2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3JlZGVdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxvZ10gW8SNZXR2cnRrYV0gW3VdIExUJyxcbiAgICAgICAgICAgICAgICAnW3Byb8WhbG9nXSBbcGV0a2FdIFt1XSBMVCcsXG4gICAgICAgICAgICAgICAgJ1twcm/FoWxlXSBbc3Vib3RlXSBbdV0gTFQnXG4gICAgICAgICAgICBdO1xuICAgICAgICAgICAgcmV0dXJuIGxhc3RXZWVrRGF5c1t0aGlzLmRheSgpXTtcbiAgICAgICAgfSxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ3phICVzJyxcbiAgICAgICAgcGFzdCAgIDogJ3ByZSAlcycsXG4gICAgICAgIHMgICAgICA6ICduZWtvbGlrbyBzZWt1bmRpJyxcbiAgICAgICAgc3MgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIG0gICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBtbSAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgaCAgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIGhoICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBkICAgICAgOiAnZGFuJyxcbiAgICAgICAgZGQgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIE0gICAgICA6ICdtZXNlYycsXG4gICAgICAgIE1NICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICB5ICAgICAgOiAnZ29kaW51JyxcbiAgICAgICAgeXkgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGVcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfVxcLi8sXG4gICAgb3JkaW5hbCA6ICclZC4nLFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBzcjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvc3IuanNcbi8vIG1vZHVsZSBpZCA9IDk5XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBTZXJiaWFuIEN5cmlsbGljIFtzci1jeXJsXVxuLy8hIGF1dGhvciA6IE1pbGFuIEphbmHEjWtvdmnEhzxtaWxhbmphbmFja292aWNAZ21haWwuY29tPiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9taWxhbi1qXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHRyYW5zbGF0b3IgPSB7XG4gICAgd29yZHM6IHsgLy9EaWZmZXJlbnQgZ3JhbW1hdGljYWwgY2FzZXNcbiAgICAgICAgc3M6IFsn0YHQtdC60YPQvdC00LAnLCAn0YHQtdC60YPQvdC00LUnLCAn0YHQtdC60YPQvdC00LgnXSxcbiAgICAgICAgbTogWyfRmNC10LTQsNC9INC80LjQvdGD0YInLCAn0ZjQtdC00L3QtSDQvNC40L3Rg9GC0LUnXSxcbiAgICAgICAgbW06IFsn0LzQuNC90YPRgicsICfQvNC40L3Rg9GC0LUnLCAn0LzQuNC90YPRgtCwJ10sXG4gICAgICAgIGg6IFsn0ZjQtdC00LDQvSDRgdCw0YInLCAn0ZjQtdC00L3QvtCzINGB0LDRgtCwJ10sXG4gICAgICAgIGhoOiBbJ9GB0LDRgicsICfRgdCw0YLQsCcsICfRgdCw0YLQuCddLFxuICAgICAgICBkZDogWyfQtNCw0L0nLCAn0LTQsNC90LAnLCAn0LTQsNC90LAnXSxcbiAgICAgICAgTU06IFsn0LzQtdGB0LXRhicsICfQvNC10YHQtdGG0LAnLCAn0LzQtdGB0LXRhtC4J10sXG4gICAgICAgIHl5OiBbJ9Cz0L7QtNC40L3QsCcsICfQs9C+0LTQuNC90LUnLCAn0LPQvtC00LjQvdCwJ11cbiAgICB9LFxuICAgIGNvcnJlY3RHcmFtbWF0aWNhbENhc2U6IGZ1bmN0aW9uIChudW1iZXIsIHdvcmRLZXkpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlciA9PT0gMSA/IHdvcmRLZXlbMF0gOiAobnVtYmVyID49IDIgJiYgbnVtYmVyIDw9IDQgPyB3b3JkS2V5WzFdIDogd29yZEtleVsyXSk7XG4gICAgfSxcbiAgICB0cmFuc2xhdGU6IGZ1bmN0aW9uIChudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGtleSkge1xuICAgICAgICB2YXIgd29yZEtleSA9IHRyYW5zbGF0b3Iud29yZHNba2V5XTtcbiAgICAgICAgaWYgKGtleS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gd29yZEtleVswXSA6IHdvcmRLZXlbMV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJyAnICsgdHJhbnNsYXRvci5jb3JyZWN0R3JhbW1hdGljYWxDYXNlKG51bWJlciwgd29yZEtleSk7XG4gICAgICAgIH1cbiAgICB9XG59O1xuXG52YXIgc3JDeXJsID0gbW9tZW50LmRlZmluZUxvY2FsZSgnc3ItY3lybCcsIHtcbiAgICBtb250aHM6ICfRmNCw0L3Rg9Cw0YBf0YTQtdCx0YDRg9Cw0YBf0LzQsNGA0YJf0LDQv9GA0LjQu1/QvNCw0Zhf0ZjRg9C9X9GY0YPQu1/QsNCy0LPRg9GB0YJf0YHQtdC/0YLQtdC80LHQsNGAX9C+0LrRgtC+0LHQsNGAX9C90L7QstC10LzQsdCw0YBf0LTQtdGG0LXQvNCx0LDRgCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydDogJ9GY0LDQvS5f0YTQtdCxLl/QvNCw0YAuX9Cw0L/RgC5f0LzQsNGYX9GY0YPQvV/RmNGD0Ltf0LDQstCzLl/RgdC10L8uX9C+0LrRgi5f0L3QvtCyLl/QtNC10YYuJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3Q6IHRydWUsXG4gICAgd2Vla2RheXM6ICfQvdC10LTQtdGZ0LBf0L/QvtC90LXQtNC10ZnQsNC6X9GD0YLQvtGA0LDQul/RgdGA0LXQtNCwX9GH0LXRgtCy0YDRgtCw0Lpf0L/QtdGC0LDQul/RgdGD0LHQvtGC0LAnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydDogJ9C90LXQtC5f0L/QvtC9Ll/Rg9GC0L4uX9GB0YDQtS5f0YfQtdGCLl/Qv9C10YIuX9GB0YPQsS4nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW46ICfQvdC1X9C/0L5f0YPRgl/RgdGAX9GH0LVf0L/QtV/RgdGDJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQ6IHtcbiAgICAgICAgTFQ6ICdIOm1tJyxcbiAgICAgICAgTFRTIDogJ0g6bW06c3MnLFxuICAgICAgICBMOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMOiAnRC4gTU1NTSBZWVlZJyxcbiAgICAgICAgTExMOiAnRC4gTU1NTSBZWVlZIEg6bW0nLFxuICAgICAgICBMTExMOiAnZGRkZCwgRC4gTU1NTSBZWVlZIEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhcjoge1xuICAgICAgICBzYW1lRGF5OiAnW9C00LDQvdCw0YEg0YNdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1vRgdGD0YLRgNCwINGDXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9GDXSBb0L3QtdC00LXRmdGDXSBb0YNdIExUJztcbiAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAnW9GDXSBb0YHRgNC10LTRg10gW9GDXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vRg10gW9GB0YPQsdC+0YLRg10gW9GDXSBMVCc7XG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gJ1vRg10gZGRkZCBb0YNdIExUJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbGFzdERheSAgOiAnW9GY0YPRh9C1INGDXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGxhc3RXZWVrRGF5cyA9IFtcbiAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQtV0gW9C90LXQtNC10ZnQtV0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70L7Qs10gW9C/0L7QvdC10LTQtdGZ0LrQsF0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70L7Qs10gW9GD0YLQvtGA0LrQsF0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70LVdIFvRgdGA0LXQtNC1XSBb0YNdIExUJyxcbiAgICAgICAgICAgICAgICAnW9C/0YDQvtGI0LvQvtCzXSBb0YfQtdGC0LLRgNGC0LrQsF0gW9GDXSBMVCcsXG4gICAgICAgICAgICAgICAgJ1vQv9GA0L7RiNC70L7Qs10gW9C/0LXRgtC60LBdIFvRg10gTFQnLFxuICAgICAgICAgICAgICAgICdb0L/RgNC+0YjQu9C1XSBb0YHRg9Cx0L7RgtC1XSBb0YNdIExUJ1xuICAgICAgICAgICAgXTtcbiAgICAgICAgICAgIHJldHVybiBsYXN0V2Vla0RheXNbdGhpcy5kYXkoKV07XG4gICAgICAgIH0sXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfQt9CwICVzJyxcbiAgICAgICAgcGFzdCAgIDogJ9C/0YDQtSAlcycsXG4gICAgICAgIHMgICAgICA6ICfQvdC10LrQvtC70LjQutC+INGB0LXQutGD0L3QtNC4JyxcbiAgICAgICAgc3MgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIG0gICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBtbSAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZSxcbiAgICAgICAgaCAgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIGhoICAgICA6IHRyYW5zbGF0b3IudHJhbnNsYXRlLFxuICAgICAgICBkICAgICAgOiAn0LTQsNC9JyxcbiAgICAgICAgZGQgICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIE0gICAgICA6ICfQvNC10YHQtdGGJyxcbiAgICAgICAgTU0gICAgIDogdHJhbnNsYXRvci50cmFuc2xhdGUsXG4gICAgICAgIHkgICAgICA6ICfQs9C+0LTQuNC90YMnLFxuICAgICAgICB5eSAgICAgOiB0cmFuc2xhdG9yLnRyYW5zbGF0ZVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHNyQ3lybDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvc3ItY3lybC5qc1xuLy8gbW9kdWxlIGlkID0gMTAwXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBzaVN3YXRpIFtzc11cbi8vISBhdXRob3IgOiBOaWNvbGFpIERhdmllczxtYWlsQG5pY29sYWkuaW8+IDogaHR0cHM6Ly9naXRodWIuY29tL25pY29sYWlkYXZpZXNcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG5cbnZhciBzcyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3NzJywge1xuICAgIG1vbnRocyA6IFwiQmhpbWJpZHZ3YW5lX0luZGxvdmFuYV9JbmRsb3YnbGVua2h1bHVfTWFiYXNhX0lua2h3ZWtod2V0aV9JbmhsYWJhX0tob2x3YW5lX0luZ2NpX0lueW9uaV9JbXBoYWxhX0x3ZXRpX0luZ29uZ29uaVwiLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnQmhpX0luYV9JbnVfTWFiX0lua19JbmhfS2hvX0lnY19JbnlfSW1wX0x3ZV9JZ28nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnTGlzb250Zm9fVW1zb21idWx1a29fTGVzaWJpbGlfTGVzaXRzYXRmdV9MZXNpbmVfTGVzaWhsYW51X1VtZ2NpYmVsbycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0xpc19VbWJfTHNiX0xlc19Mc2lfTHNoX1VtZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdMaV9Vc19MYl9MdF9Mc19MaF9VZycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbTmFtdWhsYSBuZ2FdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdbS3VzYXNhIG5nYV0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtuZ2FdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdbSXRvbG8gbmdhXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ2RkZGQgW2xlbGlwaGVsaWxlXSBbbmdhXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICduZ2EgJXMnLFxuICAgICAgICBwYXN0IDogJ3dlbnRla2EgbmdhICVzJyxcbiAgICAgICAgcyA6ICdlbWl6dXp3YW5hIGxvbWNhbmUnLFxuICAgICAgICBzcyA6ICclZCBtenV6d2FuYScsXG4gICAgICAgIG0gOiAndW16dXp1JyxcbiAgICAgICAgbW0gOiAnJWQgZW1penV6dScsXG4gICAgICAgIGggOiAnbGlob3JhJyxcbiAgICAgICAgaGggOiAnJWQgZW1haG9yYScsXG4gICAgICAgIGQgOiAnbGlsYW5nYScsXG4gICAgICAgIGRkIDogJyVkIGVtYWxhbmdhJyxcbiAgICAgICAgTSA6ICdpbnlhbmdhJyxcbiAgICAgICAgTU0gOiAnJWQgdGlueWFuZ2EnLFxuICAgICAgICB5IDogJ3Vtbnlha2EnLFxuICAgICAgICB5eSA6ICclZCBpbWlueWFrYSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC9la3VzZW5pfGVtaW5pfGVudHNhbWJhbWF8ZWJ1c3VrdS8sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzIDwgMTEpIHtcbiAgICAgICAgICAgIHJldHVybiAnZWt1c2VuaSc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxNSkge1xuICAgICAgICAgICAgcmV0dXJuICdlbWluaSc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91cnMgPCAxOSkge1xuICAgICAgICAgICAgcmV0dXJuICdlbnRzYW1iYW1hJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAnZWJ1c3VrdSc7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtSG91ciA6IGZ1bmN0aW9uIChob3VyLCBtZXJpZGllbSkge1xuICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcbiAgICAgICAgICAgIGhvdXIgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtZXJpZGllbSA9PT0gJ2VrdXNlbmknKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ2VtaW5pJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAnZW50c2FtYmFtYScgfHwgbWVyaWRpZW0gPT09ICdlYnVzdWt1Jykge1xuICAgICAgICAgICAgaWYgKGhvdXIgPT09IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS8sXG4gICAgb3JkaW5hbCA6ICclZCcsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHNzO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS9zcy5qc1xuLy8gbW9kdWxlIGlkID0gMTAxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBTd2VkaXNoIFtzdl1cbi8vISBhdXRob3IgOiBKZW5zIEFsbSA6IGh0dHBzOi8vZ2l0aHViLmNvbS91bG11c1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBzdiA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3N2Jywge1xuICAgIG1vbnRocyA6ICdqYW51YXJpX2ZlYnJ1YXJpX21hcnNfYXByaWxfbWFqX2p1bmlfanVsaV9hdWd1c3RpX3NlcHRlbWJlcl9va3RvYmVyX25vdmVtYmVyX2RlY2VtYmVyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ2phbl9mZWJfbWFyX2Fwcl9tYWpfanVuX2p1bF9hdWdfc2VwX29rdF9ub3ZfZGVjJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ3PDtm5kYWdfbcOlbmRhZ190aXNkYWdfb25zZGFnX3RvcnNkYWdfZnJlZGFnX2zDtnJkYWcnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdzw7ZuX23DpW5fdGlzX29uc190b3JfZnJlX2zDtnInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnc8O2X23DpV90aV9vbl90b19mcl9sw7YnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZLU1NLUREJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgW2tsLl0gSEg6bW0nLFxuICAgICAgICBsbGwgOiAnRCBNTU0gWVlZWSBISDptbScsXG4gICAgICAgIGxsbGwgOiAnZGRkIEQgTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1tJZGFnXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbSW1vcmdvbl0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW0lnw6VyXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnW1DDpV0gZGRkZCBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnW0ldIGRkZGRbc10gTFQnLFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdvbSAlcycsXG4gICAgICAgIHBhc3QgOiAnZsO2ciAlcyBzZWRhbicsXG4gICAgICAgIHMgOiAnbsOlZ3JhIHNla3VuZGVyJyxcbiAgICAgICAgc3MgOiAnJWQgc2VrdW5kZXInLFxuICAgICAgICBtIDogJ2VuIG1pbnV0JyxcbiAgICAgICAgbW0gOiAnJWQgbWludXRlcicsXG4gICAgICAgIGggOiAnZW4gdGltbWUnLFxuICAgICAgICBoaCA6ICclZCB0aW1tYXInLFxuICAgICAgICBkIDogJ2VuIGRhZycsXG4gICAgICAgIGRkIDogJyVkIGRhZ2FyJyxcbiAgICAgICAgTSA6ICdlbiBtw6VuYWQnLFxuICAgICAgICBNTSA6ICclZCBtw6VuYWRlcicsXG4gICAgICAgIHkgOiAnZXR0IMOlcicsXG4gICAgICAgIHl5IDogJyVkIMOlcidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfShlfGEpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAnZScgOlxuICAgICAgICAgICAgKGIgPT09IDEpID8gJ2EnIDpcbiAgICAgICAgICAgIChiID09PSAyKSA/ICdhJyA6XG4gICAgICAgICAgICAoYiA9PT0gMykgPyAnZScgOiAnZSc7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gc3Y7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3N2LmpzXG4vLyBtb2R1bGUgaWQgPSAxMDJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFN3YWhpbGkgW3N3XVxuLy8hIGF1dGhvciA6IEZhaGFkIEthc3NpbSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9mYWRzZWxcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgc3cgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCdzdycsIHtcbiAgICBtb250aHMgOiAnSmFudWFyaV9GZWJydWFyaV9NYWNoaV9BcHJpbGlfTWVpX0p1bmlfSnVsYWlfQWdvc3RpX1NlcHRlbWJhX09rdG9iYV9Ob3ZlbWJhX0Rlc2VtYmEnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnSmFuX0ZlYl9NYWNfQXByX01laV9KdW5fSnVsX0Fnb19TZXBfT2t0X05vdl9EZXMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAnSnVtYXBpbGlfSnVtYXRhdHVfSnVtYW5uZV9KdW1hdGFub19BbGhhbWlzaV9JanVtYWFfSnVtYW1vc2knLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdKcGxfSnRhdF9Kbm5lX0p0YW5fQWxoX0lqbV9KbW9zJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0oyX0ozX0o0X0o1X0FsX0lqX0oxJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW2xlbyBzYWFdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdba2VzaG8gc2FhXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1t3aWtpIGlqYXlvXSBkZGRkIFtzYWF0XSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW2phbmFdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW3dpa2kgaWxpeW9waXRhXSBkZGRkIFtzYWF0XSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclcyBiYWFkYXllJyxcbiAgICAgICAgcGFzdCA6ICd0b2tlYSAlcycsXG4gICAgICAgIHMgOiAnaGl2aSBwdW5kZScsXG4gICAgICAgIHNzIDogJ3Nla3VuZGUgJWQnLFxuICAgICAgICBtIDogJ2Rha2lrYSBtb2phJyxcbiAgICAgICAgbW0gOiAnZGFraWthICVkJyxcbiAgICAgICAgaCA6ICdzYWEgbGltb2phJyxcbiAgICAgICAgaGggOiAnbWFzYWEgJWQnLFxuICAgICAgICBkIDogJ3Npa3UgbW9qYScsXG4gICAgICAgIGRkIDogJ21hc2lrdSAlZCcsXG4gICAgICAgIE0gOiAnbXdlemkgbW1vamEnLFxuICAgICAgICBNTSA6ICdtaWV6aSAlZCcsXG4gICAgICAgIHkgOiAnbXdha2EgbW1vamEnLFxuICAgICAgICB5eSA6ICdtaWFrYSAlZCdcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiBzdztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvc3cuanNcbi8vIG1vZHVsZSBpZCA9IDEwM1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVGFtaWwgW3RhXVxuLy8hIGF1dGhvciA6IEFyanVua3VtYXIgS3Jpc2huYW1vb3J0aHkgOiBodHRwczovL2dpdGh1Yi5jb20vdGsxMjA0MDRcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgc3ltYm9sTWFwID0ge1xuICAgICcxJzogJ+CvpycsXG4gICAgJzInOiAn4K+oJyxcbiAgICAnMyc6ICfgr6knLFxuICAgICc0JzogJ+CvqicsXG4gICAgJzUnOiAn4K+rJyxcbiAgICAnNic6ICfgr6wnLFxuICAgICc3JzogJ+CvrScsXG4gICAgJzgnOiAn4K+uJyxcbiAgICAnOSc6ICfgr68nLFxuICAgICcwJzogJ+Cvpidcbn07XG52YXIgbnVtYmVyTWFwID0ge1xuICAgICfgr6cnOiAnMScsXG4gICAgJ+CvqCc6ICcyJyxcbiAgICAn4K+pJzogJzMnLFxuICAgICfgr6onOiAnNCcsXG4gICAgJ+Cvqyc6ICc1JyxcbiAgICAn4K+sJzogJzYnLFxuICAgICfgr60nOiAnNycsXG4gICAgJ+Cvric6ICc4JyxcbiAgICAn4K+vJzogJzknLFxuICAgICfgr6YnOiAnMCdcbn07XG5cbnZhciB0YSA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3RhJywge1xuICAgIG1vbnRocyA6ICfgrpzgrqngrrXgrrDgrr9f4K6q4K6/4K6q4K+N4K6w4K614K6w4K6/X+CuruCuvuCusOCvjeCumuCvjV/gro/grqrgr43grrDgrrLgr41f4K6u4K+HX+CunOCvguCuqeCvjV/grpzgr4LgrrLgr4hf4K6G4K6V4K644K+N4K6f4K+NX+CumuCvhuCuquCvjeCun+CvhuCuruCvjeCuquCusOCvjV/groXgrpXgr43grp/gr4fgrr7grqrgrrDgr41f4K6o4K614K6u4K+N4K6q4K6w4K+NX+Cun+Cuv+CumuCuruCvjeCuquCusOCvjScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfgrpzgrqngrrXgrrDgrr9f4K6q4K6/4K6q4K+N4K6w4K614K6w4K6/X+CuruCuvuCusOCvjeCumuCvjV/gro/grqrgr43grrDgrrLgr41f4K6u4K+HX+CunOCvguCuqeCvjV/grpzgr4LgrrLgr4hf4K6G4K6V4K644K+N4K6f4K+NX+CumuCvhuCuquCvjeCun+CvhuCuruCvjeCuquCusOCvjV/groXgrpXgr43grp/gr4fgrr7grqrgrrDgr41f4K6o4K614K6u4K+N4K6q4K6w4K+NX+Cun+Cuv+CumuCuruCvjeCuquCusOCvjScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfgrp7grr7grq/grr/grrHgr43grrHgr4HgrpXgr43grpXgrr/grrTgrq7gr4hf4K6k4K6/4K6Z4K+N4K6V4K6f4K+N4K6V4K6/4K604K6u4K+IX+CumuCvhuCuteCvjeCuteCuvuCur+CvjeCuleCuv+CutOCuruCviF/grqrgr4HgrqTgrqngr43grpXgrr/grrTgrq7gr4hf4K614K6/4K6v4K6+4K604K6V4K+N4K6V4K6/4K604K6u4K+IX+CuteCvhuCus+CvjeCus+Cuv+CuleCvjeCuleCuv+CutOCuruCviF/grprgrqngrr/grpXgr43grpXgrr/grrTgrq7gr4gnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgrp7grr7grq/grr/grrHgr4Ff4K6k4K6/4K6Z4K+N4K6V4K6z4K+NX+CumuCvhuCuteCvjeCuteCuvuCur+CvjV/grqrgr4HgrqTgrqngr41f4K614K6/4K6v4K6+4K604K6p4K+NX+CuteCvhuCus+CvjeCus+Cuv1/grprgrqngrr8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4K6e4K6+X+CupOCuv1/grprgr4Zf4K6q4K+BX+CuteCuv1/grrXgr4Zf4K6aJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZLCBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+Cuh+CuqeCvjeCuseCvgV0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vgrqjgrr7grrPgr4hdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCwgTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vgrqjgr4fgrrHgr43grrHgr4FdIExUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+CuleCun+CuqOCvjeCupCDgrrXgrr7grrDgrq7gr41dIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIOCuh+CusuCvjScsXG4gICAgICAgIHBhc3QgOiAnJXMg4K6u4K+B4K6p4K+NJyxcbiAgICAgICAgcyA6ICfgrpLgrrDgr4Eg4K6a4K6/4K6yIOCuteCuv+CuqOCuvuCun+Cuv+CuleCus+CvjScsXG4gICAgICAgIHNzIDogJyVkIOCuteCuv+CuqOCuvuCun+Cuv+CuleCus+CvjScsXG4gICAgICAgIG0gOiAn4K6S4K6w4K+BIOCuqOCuv+CuruCuv+Cun+CuruCvjScsXG4gICAgICAgIG1tIDogJyVkIOCuqOCuv+CuruCuv+Cun+CumeCvjeCuleCus+CvjScsXG4gICAgICAgIGggOiAn4K6S4K6w4K+BIOCuruCuo+CuvyDgrqjgr4fgrrDgrq7gr40nLFxuICAgICAgICBoaCA6ICclZCDgrq7grqPgrr8g4K6o4K+H4K6w4K6u4K+NJyxcbiAgICAgICAgZCA6ICfgrpLgrrDgr4Eg4K6o4K6+4K6z4K+NJyxcbiAgICAgICAgZGQgOiAnJWQg4K6o4K6+4K6f4K+N4K6V4K6z4K+NJyxcbiAgICAgICAgTSA6ICfgrpLgrrDgr4Eg4K6u4K6+4K6k4K6u4K+NJyxcbiAgICAgICAgTU0gOiAnJWQg4K6u4K6+4K6k4K6Z4K+N4K6V4K6z4K+NJyxcbiAgICAgICAgeSA6ICfgrpLgrrDgr4Eg4K614K6w4K+B4K6f4K6u4K+NJyxcbiAgICAgICAgeXkgOiAnJWQg4K6G4K6j4K+N4K6f4K+B4K6V4K6z4K+NJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ94K614K6k4K+BLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+CuteCupOCvgSc7XG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1vgr6fgr6jgr6ngr6rgr6vgr6zgr63gr67gr6/gr6ZdL2csIGZ1bmN0aW9uIChtYXRjaCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlck1hcFttYXRjaF07XG4gICAgICAgIH0pO1xuICAgIH0sXG4gICAgcG9zdGZvcm1hdDogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL1xcZC9nLCBmdW5jdGlvbiAobWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybiBzeW1ib2xNYXBbbWF0Y2hdO1xuICAgICAgICB9KTtcbiAgICB9LFxuICAgIC8vIHJlZmVyIGh0dHA6Ly90YS53aWtpcGVkaWEub3JnL3MvMWVyMVxuICAgIG1lcmlkaWVtUGFyc2U6IC/grq/grr7grq7grq7gr4184K614K+I4K6V4K6x4K+IfOCuleCuvuCusuCviHzgrqjgrqPgr43grqrgrpXgrrLgr4184K6O4K6x4K+N4K6q4K6+4K6f4K+BfOCuruCuvuCusuCviC8sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMikge1xuICAgICAgICAgICAgcmV0dXJuICcg4K6v4K6+4K6u4K6u4K+NJztcbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgNikge1xuICAgICAgICAgICAgcmV0dXJuICcg4K614K+I4K6V4K6x4K+IJzsgIC8vIOCuteCviOCuleCuseCviFxuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgcmV0dXJuICcg4K6V4K6+4K6y4K+IJzsgLy8g4K6V4K6+4K6y4K+IXG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDE0KSB7XG4gICAgICAgICAgICByZXR1cm4gJyDgrqjgrqPgr43grqrgrpXgrrLgr40nOyAvLyDgrqjgrqPgr43grqrgrpXgrrLgr41cbiAgICAgICAgfSBlbHNlIGlmIChob3VyIDwgMTgpIHtcbiAgICAgICAgICAgIHJldHVybiAnIOCujuCuseCvjeCuquCuvuCun+CvgSc7IC8vIOCujuCuseCvjeCuquCuvuCun+CvgVxuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMikge1xuICAgICAgICAgICAgcmV0dXJuICcg4K6u4K6+4K6y4K+IJzsgLy8g4K6u4K6+4K6y4K+IXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gJyDgrq/grr7grq7grq7gr40nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICfgrq/grr7grq7grq7gr40nKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciA8IDIgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4K614K+I4K6V4K6x4K+IJyB8fCBtZXJpZGllbSA9PT0gJ+CuleCuvuCusuCviCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4K6o4K6j4K+N4K6q4K6V4K6y4K+NJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMCwgLy8gU3VuZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDYgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHRhO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS90YS5qc1xuLy8gbW9kdWxlIGlkID0gMTA0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBUZWx1Z3UgW3RlXVxuLy8hIGF1dGhvciA6IEtyaXNobmEgQ2hhaXRhbnlhIFRob3RhIDogaHR0cHM6Ly9naXRodWIuY29tL2tjdGhvdGFcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgdGUgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCd0ZScsIHtcbiAgICBtb250aHMgOiAn4LCc4LCo4LC14LCw4LC/X+Cwq+Cwv+CwrOCxjeCwsOCwteCwsOCwv1/gsK7gsL7gsLDgsY3gsJrgsL9f4LCP4LCq4LGN4LCw4LC/4LCy4LGNX+CwruCxh1/gsJzgsYLgsKjgsY1f4LCc4LGC4LCy4LGG4LGWX+CwhuCwl+CwuOCxjeCwn+CxgV/gsLjgsYbgsKrgsY3gsJ/gsYbgsILgsKzgsLDgsY1f4LCF4LCV4LGN4LCf4LGL4LCs4LCw4LGNX+CwqOCwteCwguCwrOCwsOCxjV/gsKHgsL/gsLjgsYbgsILgsKzgsLDgsY0nLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAn4LCc4LCoLl/gsKvgsL/gsKzgsY3gsLAuX+CwruCwvuCwsOCxjeCwmuCwv1/gsI/gsKrgsY3gsLDgsL8uX+CwruCxh1/gsJzgsYLgsKjgsY1f4LCc4LGC4LCy4LGG4LGWX+CwhuCwly5f4LC44LGG4LCq4LGNLl/gsIXgsJXgsY3gsJ/gsYsuX+CwqOCwtS5f4LCh4LC/4LC44LGGLicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICfgsIbgsKbgsL/gsLXgsL7gsLDgsIJf4LC44LGL4LCu4LC14LC+4LCw4LCCX+CwruCwguCwl+Cws+CwteCwvuCwsOCwgl/gsKzgsYHgsKfgsLXgsL7gsLDgsIJf4LCX4LGB4LCw4LGB4LC14LC+4LCw4LCCX+CwtuCxgeCwleCxjeCwsOCwteCwvuCwsOCwgl/gsLbgsKjgsL/gsLXgsL7gsLDgsIInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfgsIbgsKbgsL9f4LC44LGL4LCuX+CwruCwguCwl+Cws1/gsKzgsYHgsKdf4LCX4LGB4LCw4LGBX+CwtuCxgeCwleCxjeCwsF/gsLbgsKjgsL8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4LCGX+CwuOCxi1/gsK7gsIJf4LCs4LGBX+Cwl+CxgV/gsLbgsYFf4LC2Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdBIGg6bW0nLFxuICAgICAgICBMVFMgOiAnQSBoOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVksIEEgaDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFlZWVksIEEgaDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vgsKjgsYfgsKHgsYFdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4LCw4LGH4LCq4LGBXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQsIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4LCo4LC/4LCo4LGN4LCoXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1vgsJfgsKRdIGRkZGQsIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIOCwsuCxiycsXG4gICAgICAgIHBhc3QgOiAnJXMg4LCV4LGN4LCw4LC/4LCk4LCCJyxcbiAgICAgICAgcyA6ICfgsJXgsYrgsKjgsY3gsKjgsL8g4LCV4LGN4LC34LCj4LC+4LCy4LGBJyxcbiAgICAgICAgc3MgOiAnJWQg4LC44LGG4LCV4LCo4LGN4LCy4LGBJyxcbiAgICAgICAgbSA6ICfgsJLgsJUg4LCo4LC/4LCu4LC/4LC34LCCJyxcbiAgICAgICAgbW0gOiAnJWQg4LCo4LC/4LCu4LC/4LC34LC+4LCy4LGBJyxcbiAgICAgICAgaCA6ICfgsJLgsJUg4LCX4LCC4LCfJyxcbiAgICAgICAgaGggOiAnJWQg4LCX4LCC4LCf4LCy4LGBJyxcbiAgICAgICAgZCA6ICfgsJLgsJUg4LCw4LGL4LCc4LGBJyxcbiAgICAgICAgZGQgOiAnJWQg4LCw4LGL4LCc4LGB4LCy4LGBJyxcbiAgICAgICAgTSA6ICfgsJLgsJUg4LCo4LGG4LCyJyxcbiAgICAgICAgTU0gOiAnJWQg4LCo4LGG4LCy4LCy4LGBJyxcbiAgICAgICAgeSA6ICfgsJLgsJUg4LC44LCC4LC14LCk4LGN4LC44LCw4LCCJyxcbiAgICAgICAgeXkgOiAnJWQg4LC44LCC4LC14LCk4LGN4LC44LCw4LC+4LCy4LGBJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZSA6IC9cXGR7MSwyfeCwtS8sXG4gICAgb3JkaW5hbCA6ICclZOCwtScsXG4gICAgbWVyaWRpZW1QYXJzZTogL+CwsOCwvuCwpOCxjeCwsOCwv3zgsIngsKbgsK/gsIJ84LCu4LCn4LGN4LCv4LC+4LC54LGN4LCo4LCCfOCwuOCwvuCwr+CwguCwpOCxjeCwsOCwgi8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn4LCw4LC+4LCk4LGN4LCw4LC/Jykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPCA0ID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+CwieCwpuCwr+CwgicpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LCu4LCn4LGN4LCv4LC+4LC54LGN4LCo4LCCJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTAgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn4LC44LC+4LCv4LCC4LCk4LGN4LCw4LCCJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfgsLDgsL7gsKTgsY3gsLDgsL8nO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgsIngsKbgsK/gsIInO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfgsK7gsKfgsY3gsK/gsL7gsLngsY3gsKjgsIInO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAyMCkge1xuICAgICAgICAgICAgcmV0dXJuICfgsLjgsL7gsK/gsILgsKTgsY3gsLDgsIInO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfgsLDgsL7gsKTgsY3gsLDgsL8nO1xuICAgICAgICB9XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAwLCAvLyBTdW5kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gdGU7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3RlLmpzXG4vLyBtb2R1bGUgaWQgPSAxMDVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFRldHVuIERpbGkgKEVhc3QgVGltb3IpIFt0ZXRdXG4vLyEgYXV0aG9yIDogSm9zaHVhIEJyb29rcyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9qb3NoYnJvb2tzXG4vLyEgYXV0aG9yIDogT25vcmlvIERlIEouIEFmb25zbyA6IGh0dHBzOi8vZ2l0aHViLmNvbS9tYXJvYm9cblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgdGV0ID0gbW9tZW50LmRlZmluZUxvY2FsZSgndGV0Jywge1xuICAgIG1vbnRocyA6ICdKYW5laXJ1X0ZldmVyZWlydV9NYXJzdV9BYnJpbF9NYWl1X0p1bml1X0p1bGl1X0F1Z3VzdHVfU2V0ZW1icnVfT3V0dWJydV9Ob3ZlbWJydV9EZXplbWJydScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdKYW5fRmV2X01hcl9BYnJfTWFpX0p1bl9KdWxfQXVnX1NldF9PdXRfTm92X0Rleicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdEb21pbmd1X1NlZ3VuZGFfVGVyc2FfS3VhcnRhX0tpbnRhX1NleHRhX1NhYmFkdScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0RvbV9TZWdfVGVyc19LdWFfS2ludF9TZXh0X1NhYicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdEb19TZWdfVGVfS3VfS2lfU2V4X1NhJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW09oaW4gaWhhXSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdbQWJhbiBpaGFdIExUJyxcbiAgICAgICAgbmV4dFdlZWs6ICdkZGRkIFtpaGFdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tIb3Jpc2VpayBpaGFdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFtzZW1hbmEga290dWtdIFtpaGFdIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnaWhhICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBsaXViYScsXG4gICAgICAgIHMgOiAnbWludXR1IGJhbHVuJyxcbiAgICAgICAgc3MgOiAnbWludXR1ICVkJyxcbiAgICAgICAgbSA6ICdtaW51dHUgaWRhJyxcbiAgICAgICAgbW0gOiAnbWludXR1cyAlZCcsXG4gICAgICAgIGggOiAnaG9yYXMgaWRhJyxcbiAgICAgICAgaGggOiAnaG9yYXMgJWQnLFxuICAgICAgICBkIDogJ2xvcm9uIGlkYScsXG4gICAgICAgIGRkIDogJ2xvcm9uICVkJyxcbiAgICAgICAgTSA6ICdmdWxhbiBpZGEnLFxuICAgICAgICBNTSA6ICdmdWxhbiAlZCcsXG4gICAgICAgIHkgOiAndGluYW4gaWRhJyxcbiAgICAgICAgeXkgOiAndGluYW4gJWQnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0oc3R8bmR8cmR8dGgpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlcikge1xuICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgb3V0cHV0ID0gKH5+KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAndGgnIDpcbiAgICAgICAgICAgIChiID09PSAxKSA/ICdzdCcgOlxuICAgICAgICAgICAgKGIgPT09IDIpID8gJ25kJyA6XG4gICAgICAgICAgICAoYiA9PT0gMykgPyAncmQnIDogJ3RoJztcbiAgICAgICAgcmV0dXJuIG51bWJlciArIG91dHB1dDtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiB0ZXQ7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3RldC5qc1xuLy8gbW9kdWxlIGlkID0gMTA2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBUaGFpIFt0aF1cbi8vISBhdXRob3IgOiBLcmlkc2FkYSBUaGFuYWJ1bHBvbmcgOiBodHRwczovL2dpdGh1Yi5jb20vc2lyblxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB0aCA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3RoJywge1xuICAgIG1vbnRocyA6ICfguKHguIHguKPguLLguITguKFf4LiB4Li44Lih4Lig4Liy4Lie4Lix4LiZ4LiY4LmMX+C4oeC4teC4meC4suC4hOC4oV/guYDguKHguKnguLLguKLguJlf4Lie4Lik4Lip4Lig4Liy4LiE4LihX+C4oeC4tOC4luC4uOC4meC4suC4ouC4mV/guIHguKPguIHguI7guLLguITguKFf4Liq4Li04LiH4Lir4Liy4LiE4LihX+C4geC4seC4meC4ouC4suC4ouC4mV/guJXguLjguKXguLLguITguKFf4Lie4Lik4Lio4LiI4Li04LiB4Liy4Lii4LiZX+C4mOC4seC4meC4p+C4suC4hOC4oScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfguKEu4LiELl/guIEu4LieLl/guKHguLUu4LiELl/guYDguKEu4LiiLl/guJ4u4LiELl/guKHguLQu4LiiLl/guIEu4LiELl/guKou4LiELl/guIEu4LiiLl/guJUu4LiELl/guJ4u4LiiLl/guJgu4LiELicuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0OiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ+C4reC4suC4l+C4tOC4leC4ouC5jF/guIjguLHguJnguJfguKPguYxf4Lit4Lix4LiH4LiE4Liy4LijX+C4nuC4uOC4mF/guJ7guKTguKvguLHguKrguJrguJTguLVf4Lio4Li44LiB4Lij4LmMX+C5gOC4quC4suC4o+C5jCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+C4reC4suC4l+C4tOC4leC4ouC5jF/guIjguLHguJnguJfguKPguYxf4Lit4Lix4LiH4LiE4Liy4LijX+C4nuC4uOC4mF/guJ7guKTguKvguLHguKpf4Lio4Li44LiB4Lij4LmMX+C5gOC4quC4suC4o+C5jCcuc3BsaXQoJ18nKSwgLy8geWVzLCB0aHJlZSBjaGFyYWN0ZXJzIGRpZmZlcmVuY2VcbiAgICB3ZWVrZGF5c01pbiA6ICfguK3guLIuX+C4iC5f4LitLl/guJ4uX+C4nuC4pC5f4LioLl/guKouJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0g6bW0nLFxuICAgICAgICBMVFMgOiAnSDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIOC5gOC4p+C4peC4siBIOm1tJyxcbiAgICAgICAgTExMTCA6ICfguKfguLHguJlkZGRk4LiX4Li14LmIIEQgTU1NTSBZWVlZIOC5gOC4p+C4peC4siBIOm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+C4geC5iOC4reC4meC5gOC4l+C4teC5iOC4ouC4h3zguKvguKXguLHguIfguYDguJfguLXguYjguKLguIcvLFxuICAgIGlzUE06IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQgPT09ICfguKvguKXguLHguIfguYDguJfguLXguYjguKLguIcnO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn4LiB4LmI4Lit4LiZ4LmA4LiX4Li14LmI4Lii4LiHJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn4Lir4Lil4Lix4LiH4LmA4LiX4Li14LmI4Lii4LiHJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+C4p+C4seC4meC4meC4teC5iSDguYDguKfguKXguLJdIExUJyxcbiAgICAgICAgbmV4dERheSA6ICdb4Lie4Lij4Li44LmI4LiH4LiZ4Li14LmJIOC5gOC4p+C4peC4sl0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkW+C4q+C4meC5ieC4siDguYDguKfguKXguLJdIExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb4LmA4Lih4Li34LmI4Lit4Lin4Liy4LiZ4LiZ4Li14LmJIOC5gOC4p+C4peC4sl0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb4Lin4Lix4LiZXWRkZGRb4LiX4Li14LmI4LmB4Lil4LmJ4LinIOC5gOC4p+C4peC4sl0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn4Lit4Li14LiBICVzJyxcbiAgICAgICAgcGFzdCA6ICclc+C4l+C4teC5iOC5geC4peC5ieC4pycsXG4gICAgICAgIHMgOiAn4LmE4Lih4LmI4LiB4Li14LmI4Lin4Li04LiZ4Liy4LiX4Li1JyxcbiAgICAgICAgc3MgOiAnJWQg4Lin4Li04LiZ4Liy4LiX4Li1JyxcbiAgICAgICAgbSA6ICcxIOC4meC4suC4l+C4tScsXG4gICAgICAgIG1tIDogJyVkIOC4meC4suC4l+C4tScsXG4gICAgICAgIGggOiAnMSDguIrguLHguYjguKfguYLguKHguIcnLFxuICAgICAgICBoaCA6ICclZCDguIrguLHguYjguKfguYLguKHguIcnLFxuICAgICAgICBkIDogJzEg4Lin4Lix4LiZJyxcbiAgICAgICAgZGQgOiAnJWQg4Lin4Lix4LiZJyxcbiAgICAgICAgTSA6ICcxIOC5gOC4lOC4t+C4reC4mScsXG4gICAgICAgIE1NIDogJyVkIOC5gOC4lOC4t+C4reC4mScsXG4gICAgICAgIHkgOiAnMSDguJvguLUnLFxuICAgICAgICB5eSA6ICclZCDguJvguLUnXG4gICAgfVxufSk7XG5cbnJldHVybiB0aDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdGguanNcbi8vIG1vZHVsZSBpZCA9IDEwN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVGFnYWxvZyAoUGhpbGlwcGluZXMpIFt0bC1waF1cbi8vISBhdXRob3IgOiBEYW4gSGFnbWFuIDogaHR0cHM6Ly9naXRodWIuY29tL2hhZ21hbmRhblxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB0bFBoID0gbW9tZW50LmRlZmluZUxvY2FsZSgndGwtcGgnLCB7XG4gICAgbW9udGhzIDogJ0VuZXJvX1BlYnJlcm9fTWFyc29fQWJyaWxfTWF5b19IdW55b19IdWx5b19BZ29zdG9fU2V0eWVtYnJlX09rdHVicmVfTm9ieWVtYnJlX0Rpc3llbWJyZScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdFbmVfUGViX01hcl9BYnJfTWF5X0h1bl9IdWxfQWdvX1NldF9Pa3RfTm9iX0Rpcycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdMaW5nZ29fTHVuZXNfTWFydGVzX01peWVya3VsZXNfSHV3ZWJlc19CaXllcm5lc19TYWJhZG8nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdMaW5fTHVuX01hcl9NaXlfSHV3X0JpeV9TYWInLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnTGlfTHVfTWFfTWlfSHVfQmlfU2FiJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnTU0vRC9ZWVlZJyxcbiAgICAgICAgTEwgOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgTExMIDogJ01NTU0gRCwgWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgTU1NTSBERCwgWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnTFQgW25nYXlvbmcgYXJhd10nLFxuICAgICAgICBuZXh0RGF5OiAnW0J1a2FzIG5nXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnTFQgW3NhIHN1c3Vub2QgbmFdIGRkZGQnLFxuICAgICAgICBsYXN0RGF5OiAnTFQgW2thaGFwb25dJyxcbiAgICAgICAgbGFzdFdlZWs6ICdMVCBbbm9vbmcgbmFrYXJhYW5nXSBkZGRkJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnc2EgbG9vYiBuZyAlcycsXG4gICAgICAgIHBhc3QgOiAnJXMgYW5nIG5ha2FsaXBhcycsXG4gICAgICAgIHMgOiAnaWxhbmcgc2VndW5kbycsXG4gICAgICAgIHNzIDogJyVkIHNlZ3VuZG8nLFxuICAgICAgICBtIDogJ2lzYW5nIG1pbnV0bycsXG4gICAgICAgIG1tIDogJyVkIG1pbnV0bycsXG4gICAgICAgIGggOiAnaXNhbmcgb3JhcycsXG4gICAgICAgIGhoIDogJyVkIG9yYXMnLFxuICAgICAgICBkIDogJ2lzYW5nIGFyYXcnLFxuICAgICAgICBkZCA6ICclZCBhcmF3JyxcbiAgICAgICAgTSA6ICdpc2FuZyBidXdhbicsXG4gICAgICAgIE1NIDogJyVkIGJ1d2FuJyxcbiAgICAgICAgeSA6ICdpc2FuZyB0YW9uJyxcbiAgICAgICAgeXkgOiAnJWQgdGFvbidcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiB0bFBoO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS90bC1waC5qc1xuLy8gbW9kdWxlIGlkID0gMTA4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBLbGluZ29uIFt0bGhdXG4vLyEgYXV0aG9yIDogRG9taW5pa2EgS3J1ayA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hbWFyYW50aHJvc2VcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgbnVtYmVyc05vdW5zID0gJ3BhZ2hfd2HigJlfY2hh4oCZX3dlal9sb1NfdmFnaF9qYXZfU29jaF9jaG9yZ2hfSHV0Jy5zcGxpdCgnXycpO1xuXG5mdW5jdGlvbiB0cmFuc2xhdGVGdXR1cmUob3V0cHV0KSB7XG4gICAgdmFyIHRpbWUgPSBvdXRwdXQ7XG4gICAgdGltZSA9IChvdXRwdXQuaW5kZXhPZignamFqJykgIT09IC0xKSA/XG4gICAgdGltZS5zbGljZSgwLCAtMykgKyAnbGVTJyA6XG4gICAgKG91dHB1dC5pbmRleE9mKCdqYXInKSAhPT0gLTEpID9cbiAgICB0aW1lLnNsaWNlKDAsIC0zKSArICd3YVEnIDpcbiAgICAob3V0cHV0LmluZGV4T2YoJ0RJUycpICE9PSAtMSkgP1xuICAgIHRpbWUuc2xpY2UoMCwgLTMpICsgJ25lbScgOlxuICAgIHRpbWUgKyAnIHBJcSc7XG4gICAgcmV0dXJuIHRpbWU7XG59XG5cbmZ1bmN0aW9uIHRyYW5zbGF0ZVBhc3Qob3V0cHV0KSB7XG4gICAgdmFyIHRpbWUgPSBvdXRwdXQ7XG4gICAgdGltZSA9IChvdXRwdXQuaW5kZXhPZignamFqJykgIT09IC0xKSA/XG4gICAgdGltZS5zbGljZSgwLCAtMykgKyAnSHXigJknIDpcbiAgICAob3V0cHV0LmluZGV4T2YoJ2phcicpICE9PSAtMSkgP1xuICAgIHRpbWUuc2xpY2UoMCwgLTMpICsgJ3dlbicgOlxuICAgIChvdXRwdXQuaW5kZXhPZignRElTJykgIT09IC0xKSA/XG4gICAgdGltZS5zbGljZSgwLCAtMykgKyAnYmVuJyA6XG4gICAgdGltZSArICcgcmV0JztcbiAgICByZXR1cm4gdGltZTtcbn1cblxuZnVuY3Rpb24gdHJhbnNsYXRlKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgIHZhciBudW1iZXJOb3VuID0gbnVtYmVyQXNOb3VuKG51bWJlcik7XG4gICAgc3dpdGNoIChzdHJpbmcpIHtcbiAgICAgICAgY2FzZSAnc3MnOlxuICAgICAgICAgICAgcmV0dXJuIG51bWJlck5vdW4gKyAnIGx1cCc7XG4gICAgICAgIGNhc2UgJ21tJzpcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyB0dXAnO1xuICAgICAgICBjYXNlICdoaCc6XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgcmVwJztcbiAgICAgICAgY2FzZSAnZGQnOlxuICAgICAgICAgICAgcmV0dXJuIG51bWJlck5vdW4gKyAnIGphaic7XG4gICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgICAgIHJldHVybiBudW1iZXJOb3VuICsgJyBqYXInO1xuICAgICAgICBjYXNlICd5eSc6XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyTm91biArICcgRElTJztcbiAgICB9XG59XG5cbmZ1bmN0aW9uIG51bWJlckFzTm91bihudW1iZXIpIHtcbiAgICB2YXIgaHVuZHJlZCA9IE1hdGguZmxvb3IoKG51bWJlciAlIDEwMDApIC8gMTAwKSxcbiAgICB0ZW4gPSBNYXRoLmZsb29yKChudW1iZXIgJSAxMDApIC8gMTApLFxuICAgIG9uZSA9IG51bWJlciAlIDEwLFxuICAgIHdvcmQgPSAnJztcbiAgICBpZiAoaHVuZHJlZCA+IDApIHtcbiAgICAgICAgd29yZCArPSBudW1iZXJzTm91bnNbaHVuZHJlZF0gKyAndmF0bGgnO1xuICAgIH1cbiAgICBpZiAodGVuID4gMCkge1xuICAgICAgICB3b3JkICs9ICgod29yZCAhPT0gJycpID8gJyAnIDogJycpICsgbnVtYmVyc05vdW5zW3Rlbl0gKyAnbWFIJztcbiAgICB9XG4gICAgaWYgKG9uZSA+IDApIHtcbiAgICAgICAgd29yZCArPSAoKHdvcmQgIT09ICcnKSA/ICcgJyA6ICcnKSArIG51bWJlcnNOb3Vuc1tvbmVdO1xuICAgIH1cbiAgICByZXR1cm4gKHdvcmQgPT09ICcnKSA/ICdwYWdoJyA6IHdvcmQ7XG59XG5cbnZhciB0bGggPSBtb21lbnQuZGVmaW5lTG9jYWxlKCd0bGgnLCB7XG4gICAgbW9udGhzIDogJ3RlcmHigJkgamFyIHdh4oCZX3RlcmHigJkgamFyIGNoYeKAmV90ZXJh4oCZIGphciB3ZWpfdGVyYeKAmSBqYXIgbG9TX3RlcmHigJkgamFyIHZhZ2hfdGVyYeKAmSBqYXIgamF2X3RlcmHigJkgamFyIFNvY2hfdGVyYeKAmSBqYXIgY2hvcmdoX3RlcmHigJkgamFyIEh1dF90ZXJh4oCZIGphciB3YeKAmW1hSF90ZXJh4oCZIGphciB3YeKAmW1hSCB3YeKAmV90ZXJh4oCZIGphciB3YeKAmW1hSCBjaGHigJknLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnamFyIHdh4oCZX2phciBjaGHigJlfamFyIHdlal9qYXIgbG9TX2phciB2YWdoX2phciBqYXZfamFyIFNvY2hfamFyIGNob3JnaF9qYXIgSHV0X2phciB3YeKAmW1hSF9qYXIgd2HigJltYUggd2HigJlfamFyIHdh4oCZbWFIIGNoYeKAmScuc3BsaXQoJ18nKSxcbiAgICBtb250aHNQYXJzZUV4YWN0IDogdHJ1ZSxcbiAgICB3ZWVrZGF5cyA6ICdsb2ptSXRqYWpfRGFTamFqX3Bvdmphal9naEl0bGhqYWpfbG9naGphal9idXFqYWpfZ2hJbmphaicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ2xvam1JdGphal9EYVNqYWpfcG92amFqX2doSXRsaGphal9sb2doamFqX2J1cWphal9naEluamFqJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ2xvam1JdGphal9EYVNqYWpfcG92amFqX2doSXRsaGphal9sb2doamFqX2J1cWphal9naEluamFqJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW0RhSGphal0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW3dh4oCZbGVTXSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnTExMJyxcbiAgICAgICAgbGFzdERheTogJ1t3YeKAmUh14oCZXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrOiAnTExMJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiB0cmFuc2xhdGVGdXR1cmUsXG4gICAgICAgIHBhc3QgOiB0cmFuc2xhdGVQYXN0LFxuICAgICAgICBzIDogJ3B1UyBsdXAnLFxuICAgICAgICBzcyA6IHRyYW5zbGF0ZSxcbiAgICAgICAgbSA6ICd3YeKAmSB0dXAnLFxuICAgICAgICBtbSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgaCA6ICd3YeKAmSByZXAnLFxuICAgICAgICBoaCA6IHRyYW5zbGF0ZSxcbiAgICAgICAgZCA6ICd3YeKAmSBqYWonLFxuICAgICAgICBkZCA6IHRyYW5zbGF0ZSxcbiAgICAgICAgTSA6ICd3YeKAmSBqYXInLFxuICAgICAgICBNTSA6IHRyYW5zbGF0ZSxcbiAgICAgICAgeSA6ICd3YeKAmSBESVMnLFxuICAgICAgICB5eSA6IHRyYW5zbGF0ZVxuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9XFwuLyxcbiAgICBvcmRpbmFsIDogJyVkLicsXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHRsaDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdGxoLmpzXG4vLyBtb2R1bGUgaWQgPSAxMDlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFR1cmtpc2ggW3RyXVxuLy8hIGF1dGhvcnMgOiBFcmhhbiBHdW5kb2dhbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9lcmhhbmd1bmRvZ2FuLFxuLy8hICAgICAgICAgICBCdXJhayBZacSfaXQgS2F5YTogaHR0cHM6Ly9naXRodWIuY29tL0JZS1xuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciBzdWZmaXhlcyA9IHtcbiAgICAxOiAnXFwnaW5jaScsXG4gICAgNTogJ1xcJ2luY2knLFxuICAgIDg6ICdcXCdpbmNpJyxcbiAgICA3MDogJ1xcJ2luY2knLFxuICAgIDgwOiAnXFwnaW5jaScsXG4gICAgMjogJ1xcJ25jaScsXG4gICAgNzogJ1xcJ25jaScsXG4gICAgMjA6ICdcXCduY2knLFxuICAgIDUwOiAnXFwnbmNpJyxcbiAgICAzOiAnXFwnw7xuY8O8JyxcbiAgICA0OiAnXFwnw7xuY8O8JyxcbiAgICAxMDA6ICdcXCfDvG5jw7wnLFxuICAgIDY6ICdcXCduY8SxJyxcbiAgICA5OiAnXFwndW5jdScsXG4gICAgMTA6ICdcXCd1bmN1JyxcbiAgICAzMDogJ1xcJ3VuY3UnLFxuICAgIDYwOiAnXFwnxLFuY8SxJyxcbiAgICA5MDogJ1xcJ8SxbmPEsSdcbn07XG5cbnZhciB0ciA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3RyJywge1xuICAgIG1vbnRocyA6ICdPY2FrX8WedWJhdF9NYXJ0X05pc2FuX01hecSxc19IYXppcmFuX1RlbW11el9BxJ91c3Rvc19FeWzDvGxfRWtpbV9LYXPEsW1fQXJhbMSxaycuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICdPY2FfxZ51Yl9NYXJfTmlzX01heV9IYXpfVGVtX0HEn3VfRXlsX0VraV9LYXNfQXJhJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ1BhemFyX1BhemFydGVzaV9TYWzEsV/Dh2FyxZ9hbWJhX1BlcsWfZW1iZV9DdW1hX0N1bWFydGVzaScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1Bhel9QdHNfU2FsX8OHYXJfUGVyX0N1bV9DdHMnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAnUHpfUHRfU2Ffw4dhX1BlX0N1X0N0Jy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQuTU0uWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tidWfDvG4gc2FhdF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1t5YXLEsW4gc2FhdF0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdbZ2VsZWNla10gZGRkZCBbc2FhdF0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tkw7xuXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1tnZcOnZW5dIGRkZGQgW3NhYXRdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIHNvbnJhJyxcbiAgICAgICAgcGFzdCA6ICclcyDDtm5jZScsXG4gICAgICAgIHMgOiAnYmlya2HDpyBzYW5peWUnLFxuICAgICAgICBzcyA6ICclZCBzYW5peWUnLFxuICAgICAgICBtIDogJ2JpciBkYWtpa2EnLFxuICAgICAgICBtbSA6ICclZCBkYWtpa2EnLFxuICAgICAgICBoIDogJ2JpciBzYWF0JyxcbiAgICAgICAgaGggOiAnJWQgc2FhdCcsXG4gICAgICAgIGQgOiAnYmlyIGfDvG4nLFxuICAgICAgICBkZCA6ICclZCBnw7xuJyxcbiAgICAgICAgTSA6ICdiaXIgYXknLFxuICAgICAgICBNTSA6ICclZCBheScsXG4gICAgICAgIHkgOiAnYmlyIHnEsWwnLFxuICAgICAgICB5eSA6ICclZCB5xLFsJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9JyhpbmNpfG5jaXzDvG5jw7x8bmPEsXx1bmN1fMSxbmPEsSkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPT09IDApIHsgIC8vIHNwZWNpYWwgY2FzZSBmb3IgemVyb1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICdcXCfEsW5jxLEnO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBiID0gbnVtYmVyICUgMTAwIC0gYSxcbiAgICAgICAgICAgIGMgPSBudW1iZXIgPj0gMTAwID8gMTAwIDogbnVsbDtcbiAgICAgICAgcmV0dXJuIG51bWJlciArIChzdWZmaXhlc1thXSB8fCBzdWZmaXhlc1tiXSB8fCBzdWZmaXhlc1tjXSk7XG4gICAgfSxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNyAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5yZXR1cm4gdHI7XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3RyLmpzXG4vLyBtb2R1bGUgaWQgPSAxMTBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFRhbG9zc2FuIFt0emxdXG4vLyEgYXV0aG9yIDogUm9iaW4gdmFuIGRlciBWbGlldCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9yb2JpbjB2YW4wZGVyMHZcbi8vISBhdXRob3IgOiBJdXN0w6wgQ2FudW5cblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG4vLyBBZnRlciB0aGUgeWVhciB0aGVyZSBzaG91bGQgYmUgYSBzbGFzaCBhbmQgdGhlIGFtb3VudCBvZiB5ZWFycyBzaW5jZSBEZWNlbWJlciAyNiwgMTk3OSBpbiBSb21hbiBudW1lcmFscy5cbi8vIFRoaXMgaXMgY3VycmVudGx5IHRvbyBkaWZmaWN1bHQgKG1heWJlIGV2ZW4gaW1wb3NzaWJsZSkgdG8gYWRkLlxudmFyIHR6bCA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3R6bCcsIHtcbiAgICBtb250aHMgOiAnSmFudWFyX0ZldnJhZ2xoX01hcsOnX0F2csOvdV9NYWlfR8O8bl9KdWxpYV9HdXNjaHRfU2V0ZW12YXJfTGlzdG9ww6R0c19Ob2VtdmFyX1plY2VtdmFyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0phbl9GZXZfTWFyX0F2cl9NYWlfR8O8bl9KdWxfR3VzX1NldF9MaXNfTm9lX1plYycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdTw7psYWRpX0zDum5lw6dpX01haXR6aV9Nw6FyY3VyaV9YaMO6YWRpX1Zpw6luZXLDp2lfU8OhdHVyaScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1PDumxfTMO6bl9NYWlfTcOhcl9YaMO6X1Zpw6lfU8OhdCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdTw7pfTMO6X01hX03DoV9YaF9WaV9Tw6EnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hILm1tJyxcbiAgICAgICAgTFRTIDogJ0hILm1tLnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRC4gTU1NTSBbZGFsbGFzXSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QuIE1NTU0gW2RhbGxhc10gWVlZWSBISC5tbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgW2xpXSBELiBNTU1NIFtkYWxsYXNdIFlZWVkgSEgubW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAvZFxcJ298ZFxcJ2EvaSxcbiAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAnZFxcJ28nID09PSBpbnB1dC50b0xvd2VyQ2FzZSgpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91cnMsIG1pbnV0ZXMsIGlzTG93ZXIpIHtcbiAgICAgICAgaWYgKGhvdXJzID4gMTEpIHtcbiAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2RcXCdvJyA6ICdEXFwnTyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdkXFwnYScgOiAnRFxcJ0EnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbb3hoaSDDoF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tkZW3DoCDDoF0gTFQnLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFvDoF0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tpZWlyaSDDoF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbc8O8ciBlbF0gZGRkZCBbbGFzdGV1IMOgXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICdvc3ByZWkgJXMnLFxuICAgICAgICBwYXN0IDogJ2phJXMnLFxuICAgICAgICBzIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgc3MgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBtIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgbW0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBoIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgaGggOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBkIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgZGQgOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICBNIDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgTU0gOiBwcm9jZXNzUmVsYXRpdmVUaW1lLFxuICAgICAgICB5IDogcHJvY2Vzc1JlbGF0aXZlVGltZSxcbiAgICAgICAgeXkgOiBwcm9jZXNzUmVsYXRpdmVUaW1lXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn1cXC4vLFxuICAgIG9yZGluYWwgOiAnJWQuJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gNHRoIGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgIH1cbn0pO1xuXG5mdW5jdGlvbiBwcm9jZXNzUmVsYXRpdmVUaW1lKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5LCBpc0Z1dHVyZSkge1xuICAgIHZhciBmb3JtYXQgPSB7XG4gICAgICAgICdzJzogWyd2aWVuc2FzIHNlY3VuZHMnLCAnXFwnaWVuc2FzIHNlY3VuZHMnXSxcbiAgICAgICAgJ3NzJzogW251bWJlciArICcgc2VjdW5kcycsICcnICsgbnVtYmVyICsgJyBzZWN1bmRzJ10sXG4gICAgICAgICdtJzogWydcXCduIG3DrXV0JywgJ1xcJ2llbnMgbcOtdXQnXSxcbiAgICAgICAgJ21tJzogW251bWJlciArICcgbcOtdXRzJywgJycgKyBudW1iZXIgKyAnIG3DrXV0cyddLFxuICAgICAgICAnaCc6IFsnXFwnbiDDvm9yYScsICdcXCdpZW5zYSDDvm9yYSddLFxuICAgICAgICAnaGgnOiBbbnVtYmVyICsgJyDDvm9yYXMnLCAnJyArIG51bWJlciArICcgw75vcmFzJ10sXG4gICAgICAgICdkJzogWydcXCduIHppdWEnLCAnXFwnaWVuc2Egeml1YSddLFxuICAgICAgICAnZGQnOiBbbnVtYmVyICsgJyB6aXVhcycsICcnICsgbnVtYmVyICsgJyB6aXVhcyddLFxuICAgICAgICAnTSc6IFsnXFwnbiBtZXMnLCAnXFwnaWVucyBtZXMnXSxcbiAgICAgICAgJ01NJzogW251bWJlciArICcgbWVzZW4nLCAnJyArIG51bWJlciArICcgbWVzZW4nXSxcbiAgICAgICAgJ3knOiBbJ1xcJ24gYXInLCAnXFwnaWVucyBhciddLFxuICAgICAgICAneXknOiBbbnVtYmVyICsgJyBhcnMnLCAnJyArIG51bWJlciArICcgYXJzJ11cbiAgICB9O1xuICAgIHJldHVybiBpc0Z1dHVyZSA/IGZvcm1hdFtrZXldWzBdIDogKHdpdGhvdXRTdWZmaXggPyBmb3JtYXRba2V5XVswXSA6IGZvcm1hdFtrZXldWzFdKTtcbn1cblxucmV0dXJuIHR6bDtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdHpsLmpzXG4vLyBtb2R1bGUgaWQgPSAxMTFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IENlbnRyYWwgQXRsYXMgVGFtYXppZ2h0IFt0em1dXG4vLyEgYXV0aG9yIDogQWJkZWwgU2FpZCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hYmRlbHNhaWRcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgdHptID0gbW9tZW50LmRlZmluZUxvY2FsZSgndHptJywge1xuICAgIG1vbnRocyA6ICfitYnitY/itY/itLDitaLitZRf4rSx4rWV4rSw4rWi4rWVX+K1juK0sOK1leK1ml/itYnitLHitZTitYnitZRf4rWO4rSw4rWi4rWi4rWTX+K1ouK1k+K1j+K1ouK1k1/itaLitZPitY3itaLitZPitaNf4rWW4rWT4rWb4rWcX+K1m+K1k+K1nOK0sOK1j+K0seK1ieK1lF/itL3itZ/itZPitLHitZVf4rWP4rWT4rWh4rSw4rWP4rSx4rWJ4rWUX+K0t+K1k+K1iuK1j+K0seK1ieK1lCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfitYnitY/itY/itLDitaLitZRf4rSx4rWV4rSw4rWi4rWVX+K1juK0sOK1leK1ml/itYnitLHitZTitYnitZRf4rWO4rSw4rWi4rWi4rWTX+K1ouK1k+K1j+K1ouK1k1/itaLitZPitY3itaLitZPitaNf4rWW4rWT4rWb4rWcX+K1m+K1k+K1nOK0sOK1j+K0seK1ieK1lF/itL3itZ/itZPitLHitZVf4rWP4rWT4rWh4rSw4rWP4rSx4rWJ4rWUX+K0t+K1k+K1iuK1j+K0seK1ieK1lCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfitLDitZnitLDitY7itLDitZlf4rSw4rWi4rWP4rSw4rWZX+K0sOK1meK1ieK1j+K0sOK1mV/itLDitL3itZTitLDitZlf4rSw4rS94rWh4rSw4rWZX+K0sOK1meK1ieK1juK1oeK0sOK1mV/itLDitZnitYnitLnitaLitLDitZknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfitLDitZnitLDitY7itLDitZlf4rSw4rWi4rWP4rSw4rWZX+K0sOK1meK1ieK1j+K0sOK1mV/itLDitL3itZTitLDitZlf4rSw4rS94rWh4rSw4rWZX+K0sOK1meK1ieK1juK1oeK0sOK1mV/itLDitZnitYnitLnitaLitLDitZknLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn4rSw4rWZ4rSw4rWO4rSw4rWZX+K0sOK1ouK1j+K0sOK1mV/itLDitZnitYnitY/itLDitZlf4rSw4rS94rWU4rSw4rWZX+K0sOK0veK1oeK0sOK1mV/itLDitZnitYnitY7itaHitLDitZlf4rSw4rWZ4rWJ4rS54rWi4rSw4rWZJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUzogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogJ1vitLDitZnitLfitYUg4rS0XSBMVCcsXG4gICAgICAgIG5leHREYXk6ICdb4rSw4rWZ4rS94rSwIOK0tF0gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW+K0tF0gTFQnLFxuICAgICAgICBsYXN0RGF5OiAnW+K0sOK1muK0sOK1j+K1nCDitLRdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdkZGRkIFvitLRdIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn4rS34rSw4rS34rWFIOK1mSDitaLitLDitY8gJXMnLFxuICAgICAgICBwYXN0IDogJ+K1ouK0sOK1jyAlcycsXG4gICAgICAgIHMgOiAn4rWJ4rWO4rWJ4rS9JyxcbiAgICAgICAgc3MgOiAnJWQg4rWJ4rWO4rWJ4rS9JyxcbiAgICAgICAgbSA6ICfitY7itYnitY/itZPitLonLFxuICAgICAgICBtbSA6ICclZCDitY7itYnitY/itZPitLonLFxuICAgICAgICBoIDogJ+K1meK0sOK1hOK0sCcsXG4gICAgICAgIGhoIDogJyVkIOK1nOK0sOK1meK1meK0sOK1hOK1ieK1jycsXG4gICAgICAgIGQgOiAn4rSw4rWZ4rWZJyxcbiAgICAgICAgZGQgOiAnJWQgb+K1meK1meK0sOK1jycsXG4gICAgICAgIE0gOiAn4rSw4rWib+K1k+K1lCcsXG4gICAgICAgIE1NIDogJyVkIOK1ieK1ouK1ouK1ieK1lOK1jycsXG4gICAgICAgIHkgOiAn4rSw4rWZ4rSz4rSw4rWZJyxcbiAgICAgICAgeXkgOiAnJWQg4rWJ4rWZ4rSz4rSw4rWZ4rWPJ1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogNiwgLy8gU2F0dXJkYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogMTIgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHR6bTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdHptLmpzXG4vLyBtb2R1bGUgaWQgPSAxMTJcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IENlbnRyYWwgQXRsYXMgVGFtYXppZ2h0IExhdGluIFt0em0tbGF0bl1cbi8vISBhdXRob3IgOiBBYmRlbCBTYWlkIDogaHR0cHM6Ly9naXRodWIuY29tL2FiZGVsc2FpZFxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB0em1MYXRuID0gbW9tZW50LmRlZmluZUxvY2FsZSgndHptLWxhdG4nLCB7XG4gICAgbW9udGhzIDogJ2lubmF5cl9icsukYXlyy6RfbWFyy6Rzy6RfaWJyaXJfbWF5eXdfeXdueXdfeXdseXd6X8mjd8WhdF/FoXd0YW5iaXJfa3TLpHdicsukX253d2FuYmlyX2R3am5iaXInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnaW5uYXlyX2Jyy6RheXLLpF9tYXLLpHPLpF9pYnJpcl9tYXl5d195d255d195d2x5d3pfyaN3xaF0X8Whd3RhbmJpcl9rdMukd2Jyy6Rfbnd3YW5iaXJfZHdqbmJpcicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdhc2FtYXNfYXluYXNfYXNpbmFzX2FrcmFzX2Frd2FzX2FzaW13YXNfYXNp4biNeWFzJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAnYXNhbWFzX2F5bmFzX2FzaW5hc19ha3Jhc19ha3dhc19hc2ltd2FzX2FzaeG4jXlhcycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdhc2FtYXNfYXluYXNfYXNpbmFzX2FrcmFzX2Frd2FzX2FzaW13YXNfYXNp4biNeWFzJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkIEQgTU1NTSBZWVlZIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXk6ICdbYXNka2ggZ10gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW2Fza2EgZ10gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW2ddIExUJyxcbiAgICAgICAgbGFzdERheTogJ1thc3NhbnQgZ10gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ2RkZGQgW2ddIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnZGFka2ggcyB5YW4gJXMnLFxuICAgICAgICBwYXN0IDogJ3lhbiAlcycsXG4gICAgICAgIHMgOiAnaW1paycsXG4gICAgICAgIHNzIDogJyVkIGltaWsnLFxuICAgICAgICBtIDogJ21pbnXhuI0nLFxuICAgICAgICBtbSA6ICclZCBtaW514biNJyxcbiAgICAgICAgaCA6ICdzYcmbYScsXG4gICAgICAgIGhoIDogJyVkIHRhc3NhyZtpbicsXG4gICAgICAgIGQgOiAnYXNzJyxcbiAgICAgICAgZGQgOiAnJWQgb3NzYW4nLFxuICAgICAgICBNIDogJ2F5b3dyJyxcbiAgICAgICAgTU0gOiAnJWQgaXl5aXJuJyxcbiAgICAgICAgeSA6ICdhc2dhcycsXG4gICAgICAgIHl5IDogJyVkIGlzZ2FzbidcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDYsIC8vIFNhdHVyZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDEyICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiB0em1MYXRuO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS90em0tbGF0bi5qc1xuLy8gbW9kdWxlIGlkID0gMTEzXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBVa3JhaW5pYW4gW3VrXVxuLy8hIGF1dGhvciA6IHplbWxhbmluIDogaHR0cHM6Ly9naXRodWIuY29tL3plbWxhbmluXG4vLyEgQXV0aG9yIDogTWVuZWxpb24gRWxlbnPDumxlIDogaHR0cHM6Ly9naXRodWIuY29tL09pcmVcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG5mdW5jdGlvbiBwbHVyYWwod29yZCwgbnVtKSB7XG4gICAgdmFyIGZvcm1zID0gd29yZC5zcGxpdCgnXycpO1xuICAgIHJldHVybiBudW0gJSAxMCA9PT0gMSAmJiBudW0gJSAxMDAgIT09IDExID8gZm9ybXNbMF0gOiAobnVtICUgMTAgPj0gMiAmJiBudW0gJSAxMCA8PSA0ICYmIChudW0gJSAxMDAgPCAxMCB8fCBudW0gJSAxMDAgPj0gMjApID8gZm9ybXNbMV0gOiBmb3Jtc1syXSk7XG59XG5mdW5jdGlvbiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsKG51bWJlciwgd2l0aG91dFN1ZmZpeCwga2V5KSB7XG4gICAgdmFyIGZvcm1hdCA9IHtcbiAgICAgICAgJ3NzJzogd2l0aG91dFN1ZmZpeCA/ICfRgdC10LrRg9C90LTQsF/RgdC10LrRg9C90LTQuF/RgdC10LrRg9C90LQnIDogJ9GB0LXQutGD0L3QtNGDX9GB0LXQutGD0L3QtNC4X9GB0LXQutGD0L3QtCcsXG4gICAgICAgICdtbSc6IHdpdGhvdXRTdWZmaXggPyAn0YXQstC40LvQuNC90LBf0YXQstC40LvQuNC90Lhf0YXQstC40LvQuNC9JyA6ICfRhdCy0LjQu9C40L3Rg1/RhdCy0LjQu9C40L3QuF/RhdCy0LjQu9C40L0nLFxuICAgICAgICAnaGgnOiB3aXRob3V0U3VmZml4ID8gJ9Cz0L7QtNC40L3QsF/Qs9C+0LTQuNC90Lhf0LPQvtC00LjQvScgOiAn0LPQvtC00LjQvdGDX9Cz0L7QtNC40L3QuF/Qs9C+0LTQuNC9JyxcbiAgICAgICAgJ2RkJzogJ9C00LXQvdGMX9C00L3Rll/QtNC90ZbQsicsXG4gICAgICAgICdNTSc6ICfQvNGW0YHRj9GG0Yxf0LzRltGB0Y/RhtGWX9C80ZbRgdGP0YbRltCyJyxcbiAgICAgICAgJ3l5JzogJ9GA0ZbQul/RgNC+0LrQuF/RgNC+0LrRltCyJ1xuICAgIH07XG4gICAgaWYgKGtleSA9PT0gJ20nKSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9GF0LLQuNC70LjQvdCwJyA6ICfRhdCy0LjQu9C40L3Rgyc7XG4gICAgfVxuICAgIGVsc2UgaWYgKGtleSA9PT0gJ2gnKSB7XG4gICAgICAgIHJldHVybiB3aXRob3V0U3VmZml4ID8gJ9Cz0L7QtNC40L3QsCcgOiAn0LPQvtC00LjQvdGDJztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBudW1iZXIgKyAnICcgKyBwbHVyYWwoZm9ybWF0W2tleV0sICtudW1iZXIpO1xuICAgIH1cbn1cbmZ1bmN0aW9uIHdlZWtkYXlzQ2FzZVJlcGxhY2UobSwgZm9ybWF0KSB7XG4gICAgdmFyIHdlZWtkYXlzID0ge1xuICAgICAgICAnbm9taW5hdGl2ZSc6ICfQvdC10LTRltC70Y9f0L/QvtC90LXQtNGW0LvQvtC6X9Cy0ZbQstGC0L7RgNC+0Lpf0YHQtdGA0LXQtNCwX9GH0LXRgtCy0LXRgF/Qv+KAmdGP0YLQvdC40YbRj1/RgdGD0LHQvtGC0LAnLnNwbGl0KCdfJyksXG4gICAgICAgICdhY2N1c2F0aXZlJzogJ9C90LXQtNGW0LvRjl/Qv9C+0L3QtdC00ZbQu9C+0Lpf0LLRltCy0YLQvtGA0L7Qul/RgdC10YDQtdC00YNf0YfQtdGC0LLQtdGAX9C/4oCZ0Y/RgtC90LjRhtGOX9GB0YPQsdC+0YLRgycuc3BsaXQoJ18nKSxcbiAgICAgICAgJ2dlbml0aXZlJzogJ9C90LXQtNGW0LvRll/Qv9C+0L3QtdC00ZbQu9C60LBf0LLRltCy0YLQvtGA0LrQsF/RgdC10YDQtdC00Lhf0YfQtdGC0LLQtdGA0LPQsF/Qv+KAmdGP0YLQvdC40YbRll/RgdGD0LHQvtGC0LgnLnNwbGl0KCdfJylcbiAgICB9O1xuXG4gICAgaWYgKCFtKSB7XG4gICAgICAgIHJldHVybiB3ZWVrZGF5c1snbm9taW5hdGl2ZSddO1xuICAgIH1cblxuICAgIHZhciBub3VuQ2FzZSA9ICgvKFxcW1vQktCy0KPRg11cXF0pID9kZGRkLykudGVzdChmb3JtYXQpID9cbiAgICAgICAgJ2FjY3VzYXRpdmUnIDpcbiAgICAgICAgKCgvXFxbPyg/OtC80LjQvdGD0LvQvtGXfNC90LDRgdGC0YPQv9C90L7Rlyk/ID9cXF0gP2RkZGQvKS50ZXN0KGZvcm1hdCkgP1xuICAgICAgICAgICAgJ2dlbml0aXZlJyA6XG4gICAgICAgICAgICAnbm9taW5hdGl2ZScpO1xuICAgIHJldHVybiB3ZWVrZGF5c1tub3VuQ2FzZV1bbS5kYXkoKV07XG59XG5mdW5jdGlvbiBwcm9jZXNzSG91cnNGdW5jdGlvbihzdHIpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gc3RyICsgJ9C+JyArICh0aGlzLmhvdXJzKCkgPT09IDExID8gJ9CxJyA6ICcnKSArICddIExUJztcbiAgICB9O1xufVxuXG52YXIgdWsgPSBtb21lbnQuZGVmaW5lTG9jYWxlKCd1aycsIHtcbiAgICBtb250aHMgOiB7XG4gICAgICAgICdmb3JtYXQnOiAn0YHRltGH0L3Rj1/Qu9GO0YLQvtCz0L5f0LHQtdGA0LXQt9C90Y9f0LrQstGW0YLQvdGPX9GC0YDQsNCy0L3Rj1/Rh9C10YDQstC90Y9f0LvQuNC/0L3Rj1/RgdC10YDQv9C90Y9f0LLQtdGA0LXRgdC90Y9f0LbQvtCy0YLQvdGPX9C70LjRgdGC0L7Qv9Cw0LTQsF/Qs9GA0YPQtNC90Y8nLnNwbGl0KCdfJyksXG4gICAgICAgICdzdGFuZGFsb25lJzogJ9GB0ZbRh9C10L3RjF/Qu9GO0YLQuNC5X9Cx0LXRgNC10LfQtdC90Yxf0LrQstGW0YLQtdC90Yxf0YLRgNCw0LLQtdC90Yxf0YfQtdGA0LLQtdC90Yxf0LvQuNC/0LXQvdGMX9GB0LXRgNC/0LXQvdGMX9Cy0LXRgNC10YHQtdC90Yxf0LbQvtCy0YLQtdC90Yxf0LvQuNGB0YLQvtC/0LDQtF/Qs9GA0YPQtNC10L3RjCcuc3BsaXQoJ18nKVxuICAgIH0sXG4gICAgbW9udGhzU2hvcnQgOiAn0YHRltGHX9C70Y7Rgl/QsdC10YBf0LrQstGW0YJf0YLRgNCw0LJf0YfQtdGA0LJf0LvQuNC/X9GB0LXRgNC/X9Cy0LXRgF/QttC+0LLRgl/Qu9C40YHRgl/Qs9GA0YPQtCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6IHdlZWtkYXlzQ2FzZVJlcGxhY2UsXG4gICAgd2Vla2RheXNTaG9ydCA6ICfQvdC0X9C/0L1f0LLRgl/RgdGAX9GH0YJf0L/Rgl/RgdCxJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ9C90LRf0L/QvV/QstGCX9GB0YBf0YfRgl/Qv9GCX9GB0LEnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC5NTS5ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVkg0YAuJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZINGALiwgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ2RkZGQsIEQgTU1NTSBZWVlZINGALiwgSEg6bW0nXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheTogcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQodGM0L7Qs9C+0LTQvdGWICcpLFxuICAgICAgICBuZXh0RGF5OiBwcm9jZXNzSG91cnNGdW5jdGlvbignW9CX0LDQstGC0YDQsCAnKSxcbiAgICAgICAgbGFzdERheTogcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQktGH0L7RgNCwICcpLFxuICAgICAgICBuZXh0V2VlazogcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQo10gZGRkZCBbJyksXG4gICAgICAgIGxhc3RXZWVrOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuZGF5KCkpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwcm9jZXNzSG91cnNGdW5jdGlvbignW9Cc0LjQvdGD0LvQvtGXXSBkZGRkIFsnKS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcHJvY2Vzc0hvdXJzRnVuY3Rpb24oJ1vQnNC40L3Rg9C70L7Qs9C+XSBkZGRkIFsnKS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBzYW1lRWxzZTogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICfQt9CwICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyDRgtC+0LzRgycsXG4gICAgICAgIHMgOiAn0LTQtdC60ZbQu9GM0LrQsCDRgdC10LrRg9C90LQnLFxuICAgICAgICBzcyA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIG0gOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBtbSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWwsXG4gICAgICAgIGggOiAn0LPQvtC00LjQvdGDJyxcbiAgICAgICAgaGggOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBkIDogJ9C00LXQvdGMJyxcbiAgICAgICAgZGQgOiByZWxhdGl2ZVRpbWVXaXRoUGx1cmFsLFxuICAgICAgICBNIDogJ9C80ZbRgdGP0YbRjCcsXG4gICAgICAgIE1NIDogcmVsYXRpdmVUaW1lV2l0aFBsdXJhbCxcbiAgICAgICAgeSA6ICfRgNGW0LonLFxuICAgICAgICB5eSA6IHJlbGF0aXZlVGltZVdpdGhQbHVyYWxcbiAgICB9LFxuICAgIC8vIE0uIEUuOiB0aG9zZSB0d28gYXJlIHZpcnR1YWxseSB1bnVzZWQgYnV0IGEgdXNlciBtaWdodCB3YW50IHRvIGltcGxlbWVudCB0aGVtIGZvciBoaXMvaGVyIHdlYnNpdGUgZm9yIHNvbWUgcmVhc29uXG4gICAgbWVyaWRpZW1QYXJzZTogL9C90L7Rh9GWfNGA0LDQvdC60YN80LTQvdGPfNCy0LXRh9C+0YDQsC8sXG4gICAgaXNQTTogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAvXijQtNC90Y980LLQtdGH0L7RgNCwKSQvLnRlc3QoaW5wdXQpO1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgNCkge1xuICAgICAgICAgICAgcmV0dXJuICfQvdC+0YfRlic7XG4gICAgICAgIH0gZWxzZSBpZiAoaG91ciA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gJ9GA0LDQvdC60YMnO1xuICAgICAgICB9IGVsc2UgaWYgKGhvdXIgPCAxNykge1xuICAgICAgICAgICAgcmV0dXJuICfQtNC90Y8nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfQstC10YfQvtGA0LAnO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0tKNC5fNCz0L4pLyxcbiAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyLCBwZXJpb2QpIHtcbiAgICAgICAgc3dpdGNoIChwZXJpb2QpIHtcbiAgICAgICAgICAgIGNhc2UgJ00nOlxuICAgICAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgICAgICBjYXNlICdEREQnOlxuICAgICAgICAgICAgY2FzZSAndyc6XG4gICAgICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3QuSc7XG4gICAgICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJy3Qs9C+JztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDcgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDFzdCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHVrO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS91ay5qc1xuLy8gbW9kdWxlIGlkID0gMTE0XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBVcmR1IFt1cl1cbi8vISBhdXRob3IgOiBTYXdvb2QgQWxhbSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9pYm5lc2F5ZWVkXG4vLyEgYXV0aG9yIDogWmFjayA6IGh0dHBzOi8vZ2l0aHViLmNvbS9aYWNrVmlzaW9uXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIG1vbnRocyA9IFtcbiAgICAn2KzZhtmI2LHbjCcsXG4gICAgJ9mB2LHZiNix24wnLFxuICAgICfZhdin2LHahicsXG4gICAgJ9in2b7YsduM2YQnLFxuICAgICfZhdim24wnLFxuICAgICfYrNmI2YYnLFxuICAgICfYrNmI2YTYp9im24wnLFxuICAgICfYp9qv2LPYqicsXG4gICAgJ9iz2KrZhdio2LEnLFxuICAgICfYp9qp2KrZiNio2LEnLFxuICAgICfZhtmI2YXYqNixJyxcbiAgICAn2K/Ys9mF2KjYsSdcbl07XG52YXIgZGF5cyA9IFtcbiAgICAn2KfYqtmI2KfYsScsXG4gICAgJ9m+24zYsScsXG4gICAgJ9mF2Ybar9mEJyxcbiAgICAn2KjYr9q+JyxcbiAgICAn2KzZhdi52LHYp9iqJyxcbiAgICAn2KzZhdi524EnLFxuICAgICfbgdmB2KrbgSdcbl07XG5cbnZhciB1ciA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3VyJywge1xuICAgIG1vbnRocyA6IG1vbnRocyxcbiAgICBtb250aHNTaG9ydCA6IG1vbnRocyxcbiAgICB3ZWVrZGF5cyA6IGRheXMsXG4gICAgd2Vla2RheXNTaG9ydCA6IGRheXMsXG4gICAgd2Vla2RheXNNaW4gOiBkYXlzLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRk2IwgRCBNTU1NIFlZWVkgSEg6bW0nXG4gICAgfSxcbiAgICBtZXJpZGllbVBhcnNlOiAv2LXYqNitfNi02KfZhS8sXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gJ9i02KfZhScgPT09IGlucHV0O1xuICAgIH0sXG4gICAgbWVyaWRpZW0gOiBmdW5jdGlvbiAoaG91ciwgbWludXRlLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VyIDwgMTIpIHtcbiAgICAgICAgICAgIHJldHVybiAn2LXYqNitJztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gJ9i02KfZhSc7XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb2KLYrCDYqNmI2YLYql0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vaqdmEINio2YjZgtiqXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW9io2YjZgtiqXSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW9qv2LDYtNiq24Eg2LHZiNiyINio2YjZgtiqXSBMVCcsXG4gICAgICAgIGxhc3RXZWVrIDogJ1var9iw2LTYqtuBXSBkZGRkIFvYqNmI2YLYql0gTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXMg2KjYudivJyxcbiAgICAgICAgcGFzdCA6ICclcyDZgtio2YQnLFxuICAgICAgICBzIDogJ9qG2YbYryDYs9uM2qnZhtqIJyxcbiAgICAgICAgc3MgOiAnJWQg2LPbjNqp2YbaiCcsXG4gICAgICAgIG0gOiAn2KfbjNqpINmF2YbZuScsXG4gICAgICAgIG1tIDogJyVkINmF2YbZuScsXG4gICAgICAgIGggOiAn2KfbjNqpINqv2r7Zhtm524EnLFxuICAgICAgICBoaCA6ICclZCDar9q+2YbZuduSJyxcbiAgICAgICAgZCA6ICfYp9uM2qkg2K/ZhicsXG4gICAgICAgIGRkIDogJyVkINiv2YYnLFxuICAgICAgICBNIDogJ9in24zaqSDZhdin24EnLFxuICAgICAgICBNTSA6ICclZCDZhdin24EnLFxuICAgICAgICB5IDogJ9in24zaqSDYs9in2YQnLFxuICAgICAgICB5eSA6ICclZCDYs9in2YQnXG4gICAgfSxcbiAgICBwcmVwYXJzZTogZnVuY3Rpb24gKHN0cmluZykge1xuICAgICAgICByZXR1cm4gc3RyaW5nLnJlcGxhY2UoL9iML2csICcsJyk7XG4gICAgfSxcbiAgICBwb3N0Zm9ybWF0OiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmcucmVwbGFjZSgvLC9nLCAn2IwnKTtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiB1cjtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdXIuanNcbi8vIG1vZHVsZSBpZCA9IDExNVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVXpiZWsgW3V6XVxuLy8hIGF1dGhvciA6IFNhcmRvciBNdW1pbm92IDogaHR0cHM6Ly9naXRodWIuY29tL211bWlub2ZmXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHV6ID0gbW9tZW50LmRlZmluZUxvY2FsZSgndXonLCB7XG4gICAgbW9udGhzIDogJ9GP0L3QstCw0YBf0YTQtdCy0YDQsNC7X9C80LDRgNGCX9Cw0L/RgNC10Ltf0LzQsNC5X9C40Y7QvV/QuNGO0Ltf0LDQstCz0YPRgdGCX9GB0LXQvdGC0Y/QsdGAX9C+0LrRgtGP0LHRgF/QvdC+0Y/QsdGAX9C00LXQutCw0LHRgCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICfRj9C90LJf0YTQtdCyX9C80LDRgF/QsNC/0YBf0LzQsNC5X9C40Y7QvV/QuNGO0Ltf0LDQstCzX9GB0LXQvV/QvtC60YJf0L3QvtGPX9C00LXQuicuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfQr9C60YjQsNC90LHQsF/QlNGD0YjQsNC90LHQsF/QodC10YjQsNC90LHQsF/Qp9C+0YDRiNCw0L3QsdCwX9Cf0LDQudGI0LDQvdCx0LBf0JbRg9C80LBf0KjQsNC90LHQsCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ9Cv0LrRiF/QlNGD0Yhf0KHQtdGIX9Cn0L7RgF/Qn9Cw0Llf0JbRg9C8X9Co0LDQvScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfQr9C6X9CU0YNf0KHQtV/Qp9C+X9Cf0LBf0JbRg1/QqNCwJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdEIE1NTU0gWVlZWSwgZGRkZCBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1vQkdGD0LPRg9C9INGB0L7QsNGCXSBMVCBb0LTQsF0nLFxuICAgICAgICBuZXh0RGF5IDogJ1vQrdGA0YLQsNCz0LBdIExUIFvQtNCwXScsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW9C60YPQvdC4INGB0L7QsNGCXSBMVCBb0LTQsF0nLFxuICAgICAgICBsYXN0RGF5IDogJ1vQmtC10YfQsCDRgdC+0LDRgl0gTFQgW9C00LBdJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW9Cj0YLQs9Cw0L1dIGRkZGQgW9C60YPQvdC4INGB0L7QsNGCXSBMVCBb0LTQsF0nLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAn0K/QutC40L0gJXMg0LjRh9C40LTQsCcsXG4gICAgICAgIHBhc3QgOiAn0JHQuNGAINC90LXRh9CwICVzINC+0LvQtNC40L0nLFxuICAgICAgICBzIDogJ9GE0YPRgNGB0LDRgicsXG4gICAgICAgIHNzIDogJyVkINGE0YPRgNGB0LDRgicsXG4gICAgICAgIG0gOiAn0LHQuNGAINC00LDQutC40LrQsCcsXG4gICAgICAgIG1tIDogJyVkINC00LDQutC40LrQsCcsXG4gICAgICAgIGggOiAn0LHQuNGAINGB0L7QsNGCJyxcbiAgICAgICAgaGggOiAnJWQg0YHQvtCw0YInLFxuICAgICAgICBkIDogJ9Cx0LjRgCDQutGD0L0nLFxuICAgICAgICBkZCA6ICclZCDQutGD0L0nLFxuICAgICAgICBNIDogJ9Cx0LjRgCDQvtC5JyxcbiAgICAgICAgTU0gOiAnJWQg0L7QuScsXG4gICAgICAgIHkgOiAn0LHQuNGAINC50LjQuycsXG4gICAgICAgIHl5IDogJyVkINC50LjQuydcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiB1ejtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdXouanNcbi8vIG1vZHVsZSBpZCA9IDExNlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVXpiZWsgTGF0aW4gW3V6LWxhdG5dXG4vLyEgYXV0aG9yIDogUmFzdWxiZWsgTWlyemF5ZXYgOiBnaXRodWIuY29tL1Jhc3VsYmVlZWtcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgdXpMYXRuID0gbW9tZW50LmRlZmluZUxvY2FsZSgndXotbGF0bicsIHtcbiAgICBtb250aHMgOiAnWWFudmFyX0ZldnJhbF9NYXJ0X0FwcmVsX01heV9JeXVuX0l5dWxfQXZndXN0X1NlbnRhYnJfT2t0YWJyX05veWFicl9EZWthYnInLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnWWFuX0Zldl9NYXJfQXByX01heV9JeXVuX0l5dWxfQXZnX1Nlbl9Pa3RfTm95X0Rlaycuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICdZYWtzaGFuYmFfRHVzaGFuYmFfU2VzaGFuYmFfQ2hvcnNoYW5iYV9QYXlzaGFuYmFfSnVtYV9TaGFuYmEnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICdZYWtfRHVzaF9TZXNoX0Nob3JfUGF5X0p1bV9TaGFuJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1lhX0R1X1NlX0Nob19QYV9KdV9TaGEnLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ0QgTU1NTSBZWVlZLCBkZGRkIEhIOm1tJ1xuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW0J1Z3VuIHNvYXRdIExUIFtkYV0nLFxuICAgICAgICBuZXh0RGF5IDogJ1tFcnRhZ2FdIExUIFtkYV0nLFxuICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFtrdW5pIHNvYXRdIExUIFtkYV0nLFxuICAgICAgICBsYXN0RGF5IDogJ1tLZWNoYSBzb2F0XSBMVCBbZGFdJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW09cXCd0Z2FuXSBkZGRkIFtrdW5pIHNvYXRdIExUIFtkYV0nLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnWWFxaW4gJXMgaWNoaWRhJyxcbiAgICAgICAgcGFzdCA6ICdCaXIgbmVjaGEgJXMgb2xkaW4nLFxuICAgICAgICBzIDogJ3Nvbml5YScsXG4gICAgICAgIHNzIDogJyVkIHNvbml5YScsXG4gICAgICAgIG0gOiAnYmlyIGRhcWlxYScsXG4gICAgICAgIG1tIDogJyVkIGRhcWlxYScsXG4gICAgICAgIGggOiAnYmlyIHNvYXQnLFxuICAgICAgICBoaCA6ICclZCBzb2F0JyxcbiAgICAgICAgZCA6ICdiaXIga3VuJyxcbiAgICAgICAgZGQgOiAnJWQga3VuJyxcbiAgICAgICAgTSA6ICdiaXIgb3knLFxuICAgICAgICBNTSA6ICclZCBveScsXG4gICAgICAgIHkgOiAnYmlyIHlpbCcsXG4gICAgICAgIHl5IDogJyVkIHlpbCdcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA3ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiAxc3QgaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiB1ekxhdG47XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3V6LWxhdG4uanNcbi8vIG1vZHVsZSBpZCA9IDExN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogVmlldG5hbWVzZSBbdmldXG4vLyEgYXV0aG9yIDogQmFuZyBOZ3V5ZW4gOiBodHRwczovL2dpdGh1Yi5jb20vYmFuZ25rXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHZpID0gbW9tZW50LmRlZmluZUxvY2FsZSgndmknLCB7XG4gICAgbW9udGhzIDogJ3Row6FuZyAxX3Row6FuZyAyX3Row6FuZyAzX3Row6FuZyA0X3Row6FuZyA1X3Row6FuZyA2X3Row6FuZyA3X3Row6FuZyA4X3Row6FuZyA5X3Row6FuZyAxMF90aMOhbmcgMTFfdGjDoW5nIDEyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ1RoMDFfVGgwMl9UaDAzX1RoMDRfVGgwNV9UaDA2X1RoMDdfVGgwOF9UaDA5X1RoMTBfVGgxMV9UaDEyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIHdlZWtkYXlzIDogJ2No4bunIG5o4bqtdF90aOG7qSBoYWlfdGjhu6kgYmFfdGjhu6kgdMawX3Ro4bupIG7Eg21fdGjhu6kgc8OhdV90aOG7qSBi4bqjeScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0NOX1QyX1QzX1Q0X1Q1X1Q2X1Q3Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ0NOX1QyX1QzX1Q0X1Q1X1Q2X1Q3Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgbWVyaWRpZW1QYXJzZTogL3NhfGNoL2ksXG4gICAgaXNQTSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gL15jaCQvaS50ZXN0KGlucHV0KTtcbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VycyA8IDEyKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdzYScgOiAnU0EnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnY2gnIDogJ0NIJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFtuxINtXSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBbbsSDbV0gWVlZWSBISDptbScsXG4gICAgICAgIExMTEwgOiAnZGRkZCwgRCBNTU1NIFtuxINtXSBZWVlZIEhIOm1tJyxcbiAgICAgICAgbCA6ICdERC9NL1lZWVknLFxuICAgICAgICBsbCA6ICdEIE1NTSBZWVlZJyxcbiAgICAgICAgbGxsIDogJ0QgTU1NIFlZWVkgSEg6bW0nLFxuICAgICAgICBsbGxsIDogJ2RkZCwgRCBNTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5OiAnW0jDtG0gbmF5IGzDumNdIExUJyxcbiAgICAgICAgbmV4dERheTogJ1tOZ8OgeSBtYWkgbMO6Y10gTFQnLFxuICAgICAgICBuZXh0V2VlazogJ2RkZGQgW3R14bqnbiB04bubaSBsw7pjXSBMVCcsXG4gICAgICAgIGxhc3REYXk6ICdbSMO0bSBxdWEgbMO6Y10gTFQnLFxuICAgICAgICBsYXN0V2VlazogJ2RkZGQgW3R14bqnbiBy4buTaSBsw7pjXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVzIHThu5tpJyxcbiAgICAgICAgcGFzdCA6ICclcyB0csaw4bubYycsXG4gICAgICAgIHMgOiAndsOgaSBnacOieScsXG4gICAgICAgIHNzIDogJyVkIGdpw6J5JyAsXG4gICAgICAgIG0gOiAnbeG7mXQgcGjDunQnLFxuICAgICAgICBtbSA6ICclZCBwaMO6dCcsXG4gICAgICAgIGggOiAnbeG7mXQgZ2nhu50nLFxuICAgICAgICBoaCA6ICclZCBnaeG7nScsXG4gICAgICAgIGQgOiAnbeG7mXQgbmfDoHknLFxuICAgICAgICBkZCA6ICclZCBuZ8OgeScsXG4gICAgICAgIE0gOiAnbeG7mXQgdGjDoW5nJyxcbiAgICAgICAgTU0gOiAnJWQgdGjDoW5nJyxcbiAgICAgICAgeSA6ICdt4buZdCBuxINtJyxcbiAgICAgICAgeXkgOiAnJWQgbsSDbSdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIGRvdyA6IDEsIC8vIE1vbmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3kgOiA0ICAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiB2aTtcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvdmkuanNcbi8vIG1vZHVsZSBpZCA9IDExOFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogUHNldWRvIFt4LXBzZXVkb11cbi8vISBhdXRob3IgOiBBbmRyZXcgSG9vZCA6IGh0dHBzOi8vZ2l0aHViLmNvbS9hbmRyZXdob29kMTI1XG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHhQc2V1ZG8gPSBtb21lbnQuZGVmaW5lTG9jYWxlKCd4LXBzZXVkbycsIHtcbiAgICBtb250aHMgOiAnSn7DocOxw7rDoX5yw71fRn7DqWJyw7p+w6Fyw71ffk3DoXJjfmhfw4FwfnLDrWxffk3DocO9X35Kw7rDscOpfl9Kw7psfsO9X8OBw7p+Z8O6c3R+X1PDqXB+dMOpbWJ+w6lyX8OTfmN0w7NifsOpcl/DkX7Ds3bDqW1+YsOpcl9+RMOpY8Opfm1iw6lyJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJ0p+w6HDsV9+RsOpYl9+TcOhcl9+w4Fwcl9+TcOhw71ffkrDusOxX35Kw7psX37DgcO6Z19+U8OpcF9+w5NjdF9+w5HDs3ZffkTDqWMnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzUGFyc2VFeGFjdCA6IHRydWUsXG4gICAgd2Vla2RheXMgOiAnU37DusOxZMOhfsO9X03Ds37DsWTDocO9fl9Uw7rDqX5zZMOhw71+X1fDqWR+w7HDqXNkfsOhw71fVH5ow7pyc35kw6HDvV9+RnLDrWR+w6HDvV9TfsOhdMO6cn5kw6HDvScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ1N+w7rDsV9+TcOzw7FfflTDusOpX35Xw6lkX35UaMO6X35GcsOtX35Tw6F0Jy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ1N+w7pfTcOzfl9Uw7pfflfDqV9UfmhfRnJ+X1PDoScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1BhcnNlRXhhY3QgOiB0cnVlLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIEwgOiAnREQvTU0vWVlZWScsXG4gICAgICAgIExMIDogJ0QgTU1NTSBZWVlZJyxcbiAgICAgICAgTExMIDogJ0QgTU1NTSBZWVlZIEhIOm1tJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBISDptbSdcbiAgICB9LFxuICAgIGNhbGVuZGFyIDoge1xuICAgICAgICBzYW1lRGF5IDogJ1tUfsOzZMOhfsO9IMOhdF0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1tUfsOzbcOzfnJyw7N+dyDDoXRdIExUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnZGRkZCBbw6F0XSBMVCcsXG4gICAgICAgIGxhc3REYXkgOiAnW8OdfsOpc3R+w6lyZMOhfsO9IMOhdF0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdbTH7DoXN0XSBkZGRkIFvDoXRdIExUJyxcbiAgICAgICAgc2FtZUVsc2UgOiAnTCdcbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJ8OtfsOxICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyDDoX5nw7MnLFxuICAgICAgICBzIDogJ8OhIH5mw6l3IH5zw6ljw7N+w7FkcycsXG4gICAgICAgIHNzIDogJyVkIHN+w6ljw7PDsX5kcycsXG4gICAgICAgIG0gOiAnw6Egfm3DrcOxfsO6dMOpJyxcbiAgICAgICAgbW0gOiAnJWQgbX7DrcOxw7p+dMOpcycsXG4gICAgICAgIGggOiAnw6F+w7EgaMOzfsO6cicsXG4gICAgICAgIGhoIDogJyVkIGh+w7PDunJzJyxcbiAgICAgICAgZCA6ICfDoSB+ZMOhw70nLFxuICAgICAgICBkZCA6ICclZCBkfsOhw71zJyxcbiAgICAgICAgTSA6ICfDoSB+bcOzw7F+dGgnLFxuICAgICAgICBNTSA6ICclZCBtfsOzw7F0fmhzJyxcbiAgICAgICAgeSA6ICfDoSB+w73DqcOhcicsXG4gICAgICAgIHl5IDogJyVkIMO9fsOpw6FycydcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSh0aHxzdHxuZHxyZCkvLFxuICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICBvdXRwdXQgPSAofn4obnVtYmVyICUgMTAwIC8gMTApID09PSAxKSA/ICd0aCcgOlxuICAgICAgICAgICAgKGIgPT09IDEpID8gJ3N0JyA6XG4gICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgIChiID09PSAzKSA/ICdyZCcgOiAndGgnO1xuICAgICAgICByZXR1cm4gbnVtYmVyICsgb3V0cHV0O1xuICAgIH0sXG4gICAgd2VlayA6IHtcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHhQc2V1ZG87XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3gtcHNldWRvLmpzXG4vLyBtb2R1bGUgaWQgPSAxMTlcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IFlvcnViYSBOaWdlcmlhIFt5b11cbi8vISBhdXRob3IgOiBBdG9sYWdiZSBBYmlzb3llIDogaHR0cHM6Ly9naXRodWIuY29tL2FuZGVsYS1iYXRvbGFnYmVcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgeW8gPSBtb21lbnQuZGVmaW5lTG9jYWxlKCd5bycsIHtcbiAgICBtb250aHMgOiAnU+G6ucyBcuG6ucyBX0XMgHJlzIBsZcyAX+G6uHLhurnMgG5hzIBfScyAZ2JlzIFfRcyAYmliaV9PzIBrdcyAZHVfQWfhurltb19PzIBndcyBbl9Pd2V3ZV/hu4zMgHdhzIByYcyAX0JlzIFsdcyBX+G7jMyAcOG6ucyAzIAnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnU+G6ucyBcl9FzIBybF/hurhybl9JzIBnYl9FzIBiaV9PzIBrdcyAX0Fn4bq5X0/MgGd1zIFfT3dlX+G7jMyAd2HMgF9CZcyBbF/hu4zMgHDhurnMgMyAJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ0HMgGnMgGt1zIFfQWplzIFfScyAc+G6ucyBZ3VuX+G7jGrhu43MgXJ1zIFf4buMauG7jcyBYuG7jV/hurh0acyAX0HMgGJhzIFt4bq5zIF0YScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ0HMgGnMgGtfQWplzIFfScyAc+G6ucyBX+G7jGpyX+G7jGpiX+G6uHRpzIBfQcyAYmHMgScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICdBzIBpzIBfQWpfScyAc1/hu4xyX+G7jGJf4bq4dF9BzIBiJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdoOm1tIEEnLFxuICAgICAgICBMVFMgOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTCA6ICdERC9NTS9ZWVlZJyxcbiAgICAgICAgTEwgOiAnRCBNTU1NIFlZWVknLFxuICAgICAgICBMTEwgOiAnRCBNTU1NIFlZWVkgaDptbSBBJyxcbiAgICAgICAgTExMTCA6ICdkZGRkLCBEIE1NTU0gWVlZWSBoOm1tIEEnXG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdbT8yAbmnMgCBuaV0gTFQnLFxuICAgICAgICBuZXh0RGF5IDogJ1vhu4zMgGxhIG5pXSBMVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ2RkZGQgW+G7jHPhurnMgCB0b8yBblxcJ2Lhu41dIFtuaV0gTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1tBzIBuYSBuaV0gTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdkZGRkIFvhu4xz4bq5zIAgdG/MgWzhu43MgV0gW25pXSBMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICduacyBICVzJyxcbiAgICAgICAgcGFzdCA6ICclcyBr4buNamHMgScsXG4gICAgICAgIHMgOiAnacyAc+G6uWp1zIEgYWF5YcyBIGRpZScsXG4gICAgICAgIHNzIDonYWF5YcyBICVkJyxcbiAgICAgICAgbSA6ICdpzIBz4bq5anXMgSBrYW4nLFxuICAgICAgICBtbSA6ICdpzIBz4bq5anXMgSAlZCcsXG4gICAgICAgIGggOiAnd2HMgWthdGkga2FuJyxcbiAgICAgICAgaGggOiAnd2HMgWthdGkgJWQnLFxuICAgICAgICBkIDogJ+G7jWrhu43MgSBrYW4nLFxuICAgICAgICBkZCA6ICfhu41q4buNzIEgJWQnLFxuICAgICAgICBNIDogJ29zdcyAIGthbicsXG4gICAgICAgIE1NIDogJ29zdcyAICVkJyxcbiAgICAgICAgeSA6ICfhu41kdcyBbiBrYW4nLFxuICAgICAgICB5eSA6ICfhu41kdcyBbiAlZCdcbiAgICB9LFxuICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2UgOiAv4buNauG7jcyBXFxzXFxkezEsMn0vLFxuICAgIG9yZGluYWwgOiAn4buNauG7jcyBICVkJyxcbiAgICB3ZWVrIDoge1xuICAgICAgICBkb3cgOiAxLCAvLyBNb25kYXkgaXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cbiAgICAgICAgZG95IDogNCAvLyBUaGUgd2VlayB0aGF0IGNvbnRhaW5zIEphbiA0dGggaXMgdGhlIGZpcnN0IHdlZWsgb2YgdGhlIHllYXIuXG4gICAgfVxufSk7XG5cbnJldHVybiB5bztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUveW8uanNcbi8vIG1vZHVsZSBpZCA9IDEyMFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyEgbW9tZW50LmpzIGxvY2FsZSBjb25maWd1cmF0aW9uXG4vLyEgbG9jYWxlIDogQ2hpbmVzZSAoQ2hpbmEpIFt6aC1jbl1cbi8vISBhdXRob3IgOiBzdXVwaWMgOiBodHRwczovL2dpdGh1Yi5jb20vc3V1cGljXG4vLyEgYXV0aG9yIDogWmVubyBaZW5nIDogaHR0cHM6Ly9naXRodWIuY29tL3plbm96ZW5nXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnXG4gICAgICAgJiYgdHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgPyBmYWN0b3J5KHJlcXVpcmUoJy4uL21vbWVudCcpKSA6XG4gICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWycuLi9tb21lbnQnXSwgZmFjdG9yeSkgOlxuICAgZmFjdG9yeShnbG9iYWwubW9tZW50KVxufSh0aGlzLCAoZnVuY3Rpb24gKG1vbWVudCkgeyAndXNlIHN0cmljdCc7XG5cblxudmFyIHpoQ24gPSBtb21lbnQuZGVmaW5lTG9jYWxlKCd6aC1jbicsIHtcbiAgICBtb250aHMgOiAn5LiA5pyIX+S6jOaciF/kuInmnIhf5Zub5pyIX+S6lOaciF/lha3mnIhf5LiD5pyIX+WFq+aciF/kuZ3mnIhf5Y2B5pyIX+WNgeS4gOaciF/ljYHkuozmnIgnLnNwbGl0KCdfJyksXG4gICAgbW9udGhzU2hvcnQgOiAnMeaciF8y5pyIXzPmnIhfNOaciF815pyIXzbmnIhfN+aciF845pyIXznmnIhfMTDmnIhfMTHmnIhfMTLmnIgnLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXMgOiAn5pif5pyf5pelX+aYn+acn+S4gF/mmJ/mnJ/kuoxf5pif5pyf5LiJX+aYn+acn+Wbm1/mmJ/mnJ/kupRf5pif5pyf5YWtJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzU2hvcnQgOiAn5ZGo5pelX+WRqOS4gF/lkajkuoxf5ZGo5LiJX+WRqOWbm1/lkajkupRf5ZGo5YWtJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzTWluIDogJ+aXpV/kuIBf5LqMX+S4iV/lm5tf5LqUX+WFrScuc3BsaXQoJ18nKSxcbiAgICBsb25nRGF0ZUZvcm1hdCA6IHtcbiAgICAgICAgTFQgOiAnSEg6bW0nLFxuICAgICAgICBMVFMgOiAnSEg6bW06c3MnLFxuICAgICAgICBMIDogJ1lZWVkvTU0vREQnLFxuICAgICAgICBMTCA6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICBMTEwgOiAnWVlZWeW5tE3mnIhE5pelQWjngrltbeWIhicsXG4gICAgICAgIExMTEwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZEFo54K5bW3liIYnLFxuICAgICAgICBsIDogJ1lZWVkvTS9EJyxcbiAgICAgICAgbGwgOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgbGxsIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgIGxsbGwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/lh4zmmah85pep5LiKfOS4iuWNiHzkuK3ljYh85LiL5Y2IfOaZmuS4ii8sXG4gICAgbWVyaWRpZW1Ib3VyOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICflh4zmmagnIHx8IG1lcmlkaWVtID09PSAn5pep5LiKJyB8fFxuICAgICAgICAgICAgICAgIG1lcmlkaWVtID09PSAn5LiK5Y2IJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH0gZWxzZSBpZiAobWVyaWRpZW0gPT09ICfkuIvljYgnIHx8IG1lcmlkaWVtID09PSAn5pma5LiKJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vICfkuK3ljYgnXG4gICAgICAgICAgICByZXR1cm4gaG91ciA+PSAxMSA/IGhvdXIgOiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICB2YXIgaG0gPSBob3VyICogMTAwICsgbWludXRlO1xuICAgICAgICBpZiAoaG0gPCA2MDApIHtcbiAgICAgICAgICAgIHJldHVybiAn5YeM5pmoJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgcmV0dXJuICfml6nkuIonO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTEzMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuIrljYgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTIzMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuK3ljYgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTgwMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuIvljYgnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfmmZrkuIonO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb5LuK5aSpXUxUJyxcbiAgICAgICAgbmV4dERheSA6ICdb5piO5aSpXUxUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+S4i11kZGRkTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vmmKjlpKldTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb5LiKXWRkZGRMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0o5pelfOaciHzlkagpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdkJzpcbiAgICAgICAgICAgIGNhc2UgJ0QnOlxuICAgICAgICAgICAgY2FzZSAnREREJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aXpSc7XG4gICAgICAgICAgICBjYXNlICdNJzpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aciCc7XG4gICAgICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgICAgIGNhc2UgJ1cnOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5ZGoJztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlcjtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgcmVsYXRpdmVUaW1lIDoge1xuICAgICAgICBmdXR1cmUgOiAnJXPlhoUnLFxuICAgICAgICBwYXN0IDogJyVz5YmNJyxcbiAgICAgICAgcyA6ICflh6Dnp5InLFxuICAgICAgICBzcyA6ICclZCDnp5InLFxuICAgICAgICBtIDogJzEg5YiG6ZKfJyxcbiAgICAgICAgbW0gOiAnJWQg5YiG6ZKfJyxcbiAgICAgICAgaCA6ICcxIOWwj+aXticsXG4gICAgICAgIGhoIDogJyVkIOWwj+aXticsXG4gICAgICAgIGQgOiAnMSDlpKknLFxuICAgICAgICBkZCA6ICclZCDlpKknLFxuICAgICAgICBNIDogJzEg5Liq5pyIJyxcbiAgICAgICAgTU0gOiAnJWQg5Liq5pyIJyxcbiAgICAgICAgeSA6ICcxIOW5tCcsXG4gICAgICAgIHl5IDogJyVkIOW5tCdcbiAgICB9LFxuICAgIHdlZWsgOiB7XG4gICAgICAgIC8vIEdCL1QgNzQwOC0xOTk044CK5pWw5o2u5YWD5ZKM5Lqk5o2i5qC85byPwrfkv6Hmga/kuqTmjaLCt+aXpeacn+WSjOaXtumXtOihqOekuuazleOAi+S4jklTTyA4NjAxOjE5ODjnrYnmlYhcbiAgICAgICAgZG93IDogMSwgLy8gTW9uZGF5IGlzIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG4gICAgICAgIGRveSA6IDQgIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDR0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9XG59KTtcblxucmV0dXJuIHpoQ247XG5cbn0pKSk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9tb21lbnQvbG9jYWxlL3poLWNuLmpzXG4vLyBtb2R1bGUgaWQgPSAxMjFcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLy8hIG1vbWVudC5qcyBsb2NhbGUgY29uZmlndXJhdGlvblxuLy8hIGxvY2FsZSA6IENoaW5lc2UgKEhvbmcgS29uZykgW3poLWhrXVxuLy8hIGF1dGhvciA6IEJlbiA6IGh0dHBzOi8vZ2l0aHViLmNvbS9iZW4tbGluXG4vLyEgYXV0aG9yIDogQ2hyaXMgTGFtIDogaHR0cHM6Ly9naXRodWIuY29tL2hlaGFjaHJpc1xuLy8hIGF1dGhvciA6IEtvbnN0YW50aW4gOiBodHRwczovL2dpdGh1Yi5jb20vc2tmZFxuXG47KGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJ1xuICAgICAgICYmIHR5cGVvZiByZXF1aXJlID09PSAnZnVuY3Rpb24nID8gZmFjdG9yeShyZXF1aXJlKCcuLi9tb21lbnQnKSkgOlxuICAgdHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnLi4vbW9tZW50J10sIGZhY3RvcnkpIDpcbiAgIGZhY3RvcnkoZ2xvYmFsLm1vbWVudClcbn0odGhpcywgKGZ1bmN0aW9uIChtb21lbnQpIHsgJ3VzZSBzdHJpY3QnO1xuXG5cbnZhciB6aEhrID0gbW9tZW50LmRlZmluZUxvY2FsZSgnemgtaGsnLCB7XG4gICAgbW9udGhzIDogJ+S4gOaciF/kuozmnIhf5LiJ5pyIX+Wbm+aciF/kupTmnIhf5YWt5pyIX+S4g+aciF/lhavmnIhf5Lmd5pyIX+WNgeaciF/ljYHkuIDmnIhf5Y2B5LqM5pyIJy5zcGxpdCgnXycpLFxuICAgIG1vbnRoc1Nob3J0IDogJzHmnIhfMuaciF8z5pyIXzTmnIhfNeaciF825pyIXzfmnIhfOOaciF855pyIXzEw5pyIXzEx5pyIXzEy5pyIJy5zcGxpdCgnXycpLFxuICAgIHdlZWtkYXlzIDogJ+aYn+acn+aXpV/mmJ/mnJ/kuIBf5pif5pyf5LqMX+aYn+acn+S4iV/mmJ/mnJ/lm5tf5pif5pyf5LqUX+aYn+acn+WFrScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c1Nob3J0IDogJ+mAseaXpV/pgLHkuIBf6YCx5LqMX+mAseS4iV/pgLHlm5tf6YCx5LqUX+mAseWFrScuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5c01pbiA6ICfml6Vf5LiAX+S6jF/kuIlf5ZubX+S6lF/lha0nLnNwbGl0KCdfJyksXG4gICAgbG9uZ0RhdGVGb3JtYXQgOiB7XG4gICAgICAgIExUIDogJ0hIOm1tJyxcbiAgICAgICAgTFRTIDogJ0hIOm1tOnNzJyxcbiAgICAgICAgTCA6ICdZWVlZL01NL0REJyxcbiAgICAgICAgTEwgOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgTExMIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgIExMTEwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbScsXG4gICAgICAgIGwgOiAnWVlZWS9NL0QnLFxuICAgICAgICBsbCA6ICdZWVlZ5bm0TeaciETml6UnLFxuICAgICAgICBsbGwgOiAnWVlZWeW5tE3mnIhE5pelIEhIOm1tJyxcbiAgICAgICAgbGxsbCA6ICdZWVlZ5bm0TeaciETml6VkZGRkIEhIOm1tJ1xuICAgIH0sXG4gICAgbWVyaWRpZW1QYXJzZTogL+WHjOaZqHzml6nkuIp85LiK5Y2IfOS4reWNiHzkuIvljYh85pma5LiKLyxcbiAgICBtZXJpZGllbUhvdXIgOiBmdW5jdGlvbiAoaG91ciwgbWVyaWRpZW0pIHtcbiAgICAgICAgaWYgKGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICBob3VyID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWVyaWRpZW0gPT09ICflh4zmmagnIHx8IG1lcmlkaWVtID09PSAn5pep5LiKJyB8fCBtZXJpZGllbSA9PT0gJ+S4iuWNiCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn5Lit5Y2IJykge1xuICAgICAgICAgICAgcmV0dXJuIGhvdXIgPj0gMTEgPyBob3VyIDogaG91ciArIDEyO1xuICAgICAgICB9IGVsc2UgaWYgKG1lcmlkaWVtID09PSAn5LiL5Y2IJyB8fCBtZXJpZGllbSA9PT0gJ+aZmuS4iicpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyICsgMTI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXIsIG1pbnV0ZSwgaXNMb3dlcikge1xuICAgICAgICB2YXIgaG0gPSBob3VyICogMTAwICsgbWludXRlO1xuICAgICAgICBpZiAoaG0gPCA2MDApIHtcbiAgICAgICAgICAgIHJldHVybiAn5YeM5pmoJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDkwMCkge1xuICAgICAgICAgICAgcmV0dXJuICfml6nkuIonO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTEzMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuIrljYgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTIzMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuK3ljYgnO1xuICAgICAgICB9IGVsc2UgaWYgKGhtIDwgMTgwMCkge1xuICAgICAgICAgICAgcmV0dXJuICfkuIvljYgnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuICfmmZrkuIonO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBjYWxlbmRhciA6IHtcbiAgICAgICAgc2FtZURheSA6ICdb5LuK5aSpXUxUJyxcbiAgICAgICAgbmV4dERheSA6ICdb5piO5aSpXUxUJyxcbiAgICAgICAgbmV4dFdlZWsgOiAnW+S4i11kZGRkTFQnLFxuICAgICAgICBsYXN0RGF5IDogJ1vmmKjlpKldTFQnLFxuICAgICAgICBsYXN0V2VlayA6ICdb5LiKXWRkZGRMVCcsXG4gICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgfSxcbiAgICBkYXlPZk1vbnRoT3JkaW5hbFBhcnNlOiAvXFxkezEsMn0o5pelfOaciHzpgLEpLyxcbiAgICBvcmRpbmFsIDogZnVuY3Rpb24gKG51bWJlciwgcGVyaW9kKSB7XG4gICAgICAgIHN3aXRjaCAocGVyaW9kKSB7XG4gICAgICAgICAgICBjYXNlICdkJyA6XG4gICAgICAgICAgICBjYXNlICdEJyA6XG4gICAgICAgICAgICBjYXNlICdEREQnIDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+aXpSc7XG4gICAgICAgICAgICBjYXNlICdNJyA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfmnIgnO1xuICAgICAgICAgICAgY2FzZSAndycgOlxuICAgICAgICAgICAgY2FzZSAnVycgOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn6YCxJztcbiAgICAgICAgICAgIGRlZmF1bHQgOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXI7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIHJlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgZnV0dXJlIDogJyVz5YWnJyxcbiAgICAgICAgcGFzdCA6ICclc+WJjScsXG4gICAgICAgIHMgOiAn5bm+56eSJyxcbiAgICAgICAgc3MgOiAnJWQg56eSJyxcbiAgICAgICAgbSA6ICcxIOWIhumQmCcsXG4gICAgICAgIG1tIDogJyVkIOWIhumQmCcsXG4gICAgICAgIGggOiAnMSDlsI/mmYInLFxuICAgICAgICBoaCA6ICclZCDlsI/mmYInLFxuICAgICAgICBkIDogJzEg5aSpJyxcbiAgICAgICAgZGQgOiAnJWQg5aSpJyxcbiAgICAgICAgTSA6ICcxIOWAi+aciCcsXG4gICAgICAgIE1NIDogJyVkIOWAi+aciCcsXG4gICAgICAgIHkgOiAnMSDlubQnLFxuICAgICAgICB5eSA6ICclZCDlubQnXG4gICAgfVxufSk7XG5cbnJldHVybiB6aEhrO1xuXG59KSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZS96aC1oay5qc1xuLy8gbW9kdWxlIGlkID0gMTIyXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8vISBtb21lbnQuanMgbG9jYWxlIGNvbmZpZ3VyYXRpb25cbi8vISBsb2NhbGUgOiBDaGluZXNlIChUYWl3YW4pIFt6aC10d11cbi8vISBhdXRob3IgOiBCZW4gOiBodHRwczovL2dpdGh1Yi5jb20vYmVuLWxpblxuLy8hIGF1dGhvciA6IENocmlzIExhbSA6IGh0dHBzOi8vZ2l0aHViLmNvbS9oZWhhY2hyaXNcblxuOyhmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gICB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgJiYgdHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAmJiB0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyA/IGZhY3RvcnkocmVxdWlyZSgnLi4vbW9tZW50JykpIDpcbiAgIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJy4uL21vbWVudCddLCBmYWN0b3J5KSA6XG4gICBmYWN0b3J5KGdsb2JhbC5tb21lbnQpXG59KHRoaXMsIChmdW5jdGlvbiAobW9tZW50KSB7ICd1c2Ugc3RyaWN0JztcblxuXG52YXIgemhUdyA9IG1vbWVudC5kZWZpbmVMb2NhbGUoJ3poLXR3Jywge1xuICAgIG1vbnRocyA6ICfkuIDmnIhf5LqM5pyIX+S4ieaciF/lm5vmnIhf5LqU5pyIX+WFreaciF/kuIPmnIhf5YWr5pyIX+S5neaciF/ljYHmnIhf5Y2B5LiA5pyIX+WNgeS6jOaciCcuc3BsaXQoJ18nKSxcbiAgICBtb250aHNTaG9ydCA6ICcx5pyIXzLmnIhfM+aciF805pyIXzXmnIhfNuaciF835pyIXzjmnIhfOeaciF8xMOaciF8xMeaciF8xMuaciCcuc3BsaXQoJ18nKSxcbiAgICB3ZWVrZGF5cyA6ICfmmJ/mnJ/ml6Vf5pif5pyf5LiAX+aYn+acn+S6jF/mmJ/mnJ/kuIlf5pif5pyf5ZubX+aYn+acn+S6lF/mmJ/mnJ/lha0nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNTaG9ydCA6ICfpgLHml6Vf6YCx5LiAX+mAseS6jF/pgLHkuIlf6YCx5ZubX+mAseS6lF/pgLHlha0nLnNwbGl0KCdfJyksXG4gICAgd2Vla2RheXNNaW4gOiAn5pelX+S4gF/kuoxf5LiJX+Wbm1/kupRf5YWtJy5zcGxpdCgnXycpLFxuICAgIGxvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICBMVCA6ICdISDptbScsXG4gICAgICAgIExUUyA6ICdISDptbTpzcycsXG4gICAgICAgIEwgOiAnWVlZWS9NTS9ERCcsXG4gICAgICAgIExMIDogJ1lZWVnlubRN5pyIROaXpScsXG4gICAgICAgIExMTCA6ICdZWVlZ5bm0TeaciETml6UgSEg6bW0nLFxuICAgICAgICBMTExMIDogJ1lZWVnlubRN5pyIROaXpWRkZGQgSEg6bW0nLFxuICAgICAgICBsIDogJ1lZWVkvTS9EJyxcbiAgICAgICAgbGwgOiAnWVlZWeW5tE3mnIhE5pelJyxcbiAgICAgICAgbGxsIDogJ1lZWVnlubRN5pyIROaXpSBISDptbScsXG4gICAgICAgIGxsbGwgOiAnWVlZWeW5tE3mnIhE5pelZGRkZCBISDptbSdcbiAgICB9LFxuICAgIG1lcmlkaWVtUGFyc2U6IC/lh4zmmah85pep5LiKfOS4iuWNiHzkuK3ljYh85LiL5Y2IfOaZmuS4ii8sXG4gICAgbWVyaWRpZW1Ib3VyIDogZnVuY3Rpb24gKGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIGlmIChob3VyID09PSAxMikge1xuICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1lcmlkaWVtID09PSAn5YeM5pmoJyB8fCBtZXJpZGllbSA9PT0gJ+aXqeS4iicgfHwgbWVyaWRpZW0gPT09ICfkuIrljYgnKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+S4reWNiCcpIHtcbiAgICAgICAgICAgIHJldHVybiBob3VyID49IDExID8gaG91ciA6IGhvdXIgKyAxMjtcbiAgICAgICAgfSBlbHNlIGlmIChtZXJpZGllbSA9PT0gJ+S4i+WNiCcgfHwgbWVyaWRpZW0gPT09ICfmmZrkuIonKSB7XG4gICAgICAgICAgICByZXR1cm4gaG91ciArIDEyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICBtZXJpZGllbSA6IGZ1bmN0aW9uIChob3VyLCBtaW51dGUsIGlzTG93ZXIpIHtcbiAgICAgICAgdmFyIGhtID0gaG91ciAqIDEwMCArIG1pbnV0ZTtcbiAgICAgICAgaWYgKGhtIDwgNjAwKSB7XG4gICAgICAgICAgICByZXR1cm4gJ+WHjOaZqCc7XG4gICAgICAgIH0gZWxzZSBpZiAoaG0gPCA5MDApIHtcbiAgICAgICAgICAgIHJldHVybiAn5pep5LiKJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDExMzApIHtcbiAgICAgICAgICAgIHJldHVybiAn5LiK5Y2IJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDEyMzApIHtcbiAgICAgICAgICAgIHJldHVybiAn5Lit5Y2IJztcbiAgICAgICAgfSBlbHNlIGlmIChobSA8IDE4MDApIHtcbiAgICAgICAgICAgIHJldHVybiAn5LiL5Y2IJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiAn5pma5LiKJztcbiAgICAgICAgfVxuICAgIH0sXG4gICAgY2FsZW5kYXIgOiB7XG4gICAgICAgIHNhbWVEYXkgOiAnW+S7iuWkqV1MVCcsXG4gICAgICAgIG5leHREYXkgOiAnW+aYjuWkqV1MVCcsXG4gICAgICAgIG5leHRXZWVrIDogJ1vkuItdZGRkZExUJyxcbiAgICAgICAgbGFzdERheSA6ICdb5pio5aSpXUxUJyxcbiAgICAgICAgbGFzdFdlZWsgOiAnW+S4il1kZGRkTFQnLFxuICAgICAgICBzYW1lRWxzZSA6ICdMJ1xuICAgIH0sXG4gICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogL1xcZHsxLDJ9KOaXpXzmnIh86YCxKS8sXG4gICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIsIHBlcmlvZCkge1xuICAgICAgICBzd2l0Y2ggKHBlcmlvZCkge1xuICAgICAgICAgICAgY2FzZSAnZCcgOlxuICAgICAgICAgICAgY2FzZSAnRCcgOlxuICAgICAgICAgICAgY2FzZSAnREREJyA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bWJlciArICfml6UnO1xuICAgICAgICAgICAgY2FzZSAnTScgOlxuICAgICAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyAn5pyIJztcbiAgICAgICAgICAgIGNhc2UgJ3cnIDpcbiAgICAgICAgICAgIGNhc2UgJ1cnIDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyICsgJ+mAsSc7XG4gICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVtYmVyO1xuICAgICAgICB9XG4gICAgfSxcbiAgICByZWxhdGl2ZVRpbWUgOiB7XG4gICAgICAgIGZ1dHVyZSA6ICclc+WFpycsXG4gICAgICAgIHBhc3QgOiAnJXPliY0nLFxuICAgICAgICBzIDogJ+W5vuenkicsXG4gICAgICAgIHNzIDogJyVkIOenkicsXG4gICAgICAgIG0gOiAnMSDliIbpkJgnLFxuICAgICAgICBtbSA6ICclZCDliIbpkJgnLFxuICAgICAgICBoIDogJzEg5bCP5pmCJyxcbiAgICAgICAgaGggOiAnJWQg5bCP5pmCJyxcbiAgICAgICAgZCA6ICcxIOWkqScsXG4gICAgICAgIGRkIDogJyVkIOWkqScsXG4gICAgICAgIE0gOiAnMSDlgIvmnIgnLFxuICAgICAgICBNTSA6ICclZCDlgIvmnIgnLFxuICAgICAgICB5IDogJzEg5bm0JyxcbiAgICAgICAgeXkgOiAnJWQg5bm0J1xuICAgIH1cbn0pO1xuXG5yZXR1cm4gemhUdztcblxufSkpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL21vbWVudC9sb2NhbGUvemgtdHcuanNcbi8vIG1vZHVsZSBpZCA9IDEyM1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKipcbiAqIHdlYnRyZWVzOiBvbmxpbmUgZ2VuZWFsb2d5XG4gKiBDb3B5cmlnaHQgKEMpIDIwMTcgd2VidHJlZXMgZGV2ZWxvcG1lbnQgdGVhbVxuICogVGhpcyBwcm9ncmFtIGlzIGZyZWUgc29mdHdhcmU6IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vciBtb2RpZnlcbiAqIGl0IHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5XG4gKiB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uLCBlaXRoZXIgdmVyc2lvbiAzIG9mIHRoZSBMaWNlbnNlLCBvclxuICogKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqIFRoaXMgcHJvZ3JhbSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS4gU2VlIHRoZVxuICogR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UgZm9yIG1vcmUgZGV0YWlscy5cbiAqIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlXG4gKiBhbG9uZyB3aXRoIHRoaXMgcHJvZ3JhbS4gSWYgbm90LCBzZWUgPGh0dHA6Ly93d3cuZ251Lm9yZy9saWNlbnNlcy8+LlxuICovXG5cbmltcG9ydCAkIGZyb20gIFwianF1ZXJ5XCI7XG53aW5kb3cuJCA9IHdpbmRvdy5qUXVlcnkgPSAkO1xuaW1wb3J0IFwicG9wcGVyLmpzXCI7XG5pbXBvcnQgXCJib290c3RyYXBcIjtcbmltcG9ydCBcImRhdGF0YWJsZXMubmV0XCI7XG5pbXBvcnQgXCJjb3JlanMtdHlwZWFoZWFkXCI7XG5pbXBvcnQgXCJkYXRhdGFibGVzLm5ldC1iczRcIjtcbmltcG9ydCBcInNvcnRhYmxlanNcIjtcbmltcG9ydCBcInNlbGVjdDJcIjtcbmltcG9ydCBcIm1vbWVudFwiO1xuaW1wb3J0IFwiZW9uYXNkYW4tYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyXCI7XG5pbXBvcnQgXCJqcXVlcnktY29sb3Jib3hcIjtcbmltcG9ydCBcIndoZWVsem9vbVwiO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vcmVzb3VyY2VzL2Fzc2V0cy9qcy92ZW5kb3IuanMiLCIvKiFcbiAgKiBCb290c3RyYXAgdjQuMC4wLWJldGEuMyAoaHR0cHM6Ly9nZXRib290c3RyYXAuY29tKVxuICAqIENvcHlyaWdodCAyMDExLTIwMTcgVGhlIEJvb3RzdHJhcCBBdXRob3JzIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvZ3JhcGhzL2NvbnRyaWJ1dG9ycylcbiAgKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICAqL1xuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcblx0dHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzLCByZXF1aXJlKCdqcXVlcnknKSwgcmVxdWlyZSgncG9wcGVyLmpzJykpIDpcblx0dHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kID8gZGVmaW5lKFsnZXhwb3J0cycsICdqcXVlcnknLCAncG9wcGVyLmpzJ10sIGZhY3RvcnkpIDpcblx0KGZhY3RvcnkoKGdsb2JhbC5ib290c3RyYXAgPSB7fSksZ2xvYmFsLmpRdWVyeSxnbG9iYWwuUG9wcGVyKSk7XG59KHRoaXMsIChmdW5jdGlvbiAoZXhwb3J0cywkLFBvcHBlcikgeyAndXNlIHN0cmljdCc7XG5cbiQgPSAkICYmICQuaGFzT3duUHJvcGVydHkoJ2RlZmF1bHQnKSA/ICRbJ2RlZmF1bHQnXSA6ICQ7XG5Qb3BwZXIgPSBQb3BwZXIgJiYgUG9wcGVyLmhhc093blByb3BlcnR5KCdkZWZhdWx0JykgPyBQb3BwZXJbJ2RlZmF1bHQnXSA6IFBvcHBlcjtcblxuZnVuY3Rpb24gX2RlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTtcbiAgICBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7XG4gICAgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlO1xuICAgIGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9jcmVhdGVDbGFzcyhDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHtcbiAgaWYgKHByb3RvUHJvcHMpIF9kZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7XG4gIGlmIChzdGF0aWNQcm9wcykgX2RlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTtcbiAgcmV0dXJuIENvbnN0cnVjdG9yO1xufVxuXG5mdW5jdGlvbiBfZXh0ZW5kcygpIHtcbiAgX2V4dGVuZHMgPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uICh0YXJnZXQpIHtcbiAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXTtcblxuICAgICAgZm9yICh2YXIga2V5IGluIHNvdXJjZSkge1xuICAgICAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHNvdXJjZSwga2V5KSkge1xuICAgICAgICAgIHRhcmdldFtrZXldID0gc291cmNlW2tleV07XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xuICB9O1xuXG4gIHJldHVybiBfZXh0ZW5kcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuXG5mdW5jdGlvbiBfaW5oZXJpdHNMb29zZShzdWJDbGFzcywgc3VwZXJDbGFzcykge1xuICBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MucHJvdG90eXBlKTtcbiAgc3ViQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gc3ViQ2xhc3M7XG4gIHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7XG59XG5cbi8qKlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEJvb3RzdHJhcCAodjQuMC4wLWJldGEuMyk6IHV0aWwuanNcbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbnZhciBVdGlsID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBQcml2YXRlIFRyYW5zaXRpb25FbmQgSGVscGVyc1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIHZhciB0cmFuc2l0aW9uID0gZmFsc2U7XG4gIHZhciBNQVhfVUlEID0gMTAwMDAwMDsgLy8gc2hvdXRvdXQgQW5ndXNDcm9sbCAoaHR0cHM6Ly9nb28uZ2wvcHh3UUdwKVxuXG4gIGZ1bmN0aW9uIHRvVHlwZShvYmopIHtcbiAgICByZXR1cm4ge30udG9TdHJpbmcuY2FsbChvYmopLm1hdGNoKC9cXHMoW2EtekEtWl0rKS8pWzFdLnRvTG93ZXJDYXNlKCk7XG4gIH1cblxuICBmdW5jdGlvbiBnZXRTcGVjaWFsVHJhbnNpdGlvbkVuZEV2ZW50KCkge1xuICAgIHJldHVybiB7XG4gICAgICBiaW5kVHlwZTogdHJhbnNpdGlvbi5lbmQsXG4gICAgICBkZWxlZ2F0ZVR5cGU6IHRyYW5zaXRpb24uZW5kLFxuICAgICAgaGFuZGxlOiBmdW5jdGlvbiBoYW5kbGUoZXZlbnQpIHtcbiAgICAgICAgaWYgKCQkJDEoZXZlbnQudGFyZ2V0KS5pcyh0aGlzKSkge1xuICAgICAgICAgIHJldHVybiBldmVudC5oYW5kbGVPYmouaGFuZGxlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIHByZWZlci1yZXN0LXBhcmFtc1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby11bmRlZmluZWRcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gdHJhbnNpdGlvbkVuZFRlc3QoKSB7XG4gICAgaWYgKHdpbmRvdy5RVW5pdCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBlbmQ6ICd0cmFuc2l0aW9uZW5kJ1xuICAgIH07XG4gIH1cblxuICBmdW5jdGlvbiB0cmFuc2l0aW9uRW5kRW11bGF0b3IoZHVyYXRpb24pIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuICAgICQkJDEodGhpcykub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGNhbGxlZCA9IHRydWU7XG4gICAgfSk7XG4gICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoIWNhbGxlZCkge1xuICAgICAgICBVdGlsLnRyaWdnZXJUcmFuc2l0aW9uRW5kKF90aGlzKTtcbiAgICAgIH1cbiAgICB9LCBkdXJhdGlvbik7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICBmdW5jdGlvbiBzZXRUcmFuc2l0aW9uRW5kU3VwcG9ydCgpIHtcbiAgICB0cmFuc2l0aW9uID0gdHJhbnNpdGlvbkVuZFRlc3QoKTtcbiAgICAkJCQxLmZuLmVtdWxhdGVUcmFuc2l0aW9uRW5kID0gdHJhbnNpdGlvbkVuZEVtdWxhdG9yO1xuXG4gICAgaWYgKFV0aWwuc3VwcG9ydHNUcmFuc2l0aW9uRW5kKCkpIHtcbiAgICAgICQkJDEuZXZlbnQuc3BlY2lhbFtVdGlsLlRSQU5TSVRJT05fRU5EXSA9IGdldFNwZWNpYWxUcmFuc2l0aW9uRW5kRXZlbnQoKTtcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBlc2NhcGVJZChzZWxlY3Rvcikge1xuICAgIC8vIHdlIGVzY2FwZSBJRHMgaW4gY2FzZSBvZiBzcGVjaWFsIHNlbGVjdG9ycyAoc2VsZWN0b3IgPSAnI215SWQ6c29tZXRoaW5nJylcbiAgICAvLyAkLmVzY2FwZVNlbGVjdG9yIGRvZXMgbm90IGV4aXN0IGluIGpRdWVyeSA8IDNcbiAgICBzZWxlY3RvciA9IHR5cGVvZiAkJCQxLmVzY2FwZVNlbGVjdG9yID09PSAnZnVuY3Rpb24nID8gJCQkMS5lc2NhcGVTZWxlY3RvcihzZWxlY3Rvcikuc3Vic3RyKDEpIDogc2VsZWN0b3IucmVwbGFjZSgvKDp8XFwufFxcW3xcXF18LHw9fEApL2csICdcXFxcJDEnKTtcbiAgICByZXR1cm4gc2VsZWN0b3I7XG4gIH1cbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIFB1YmxpYyBVdGlsIEFwaVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuXG4gIHZhciBVdGlsID0ge1xuICAgIFRSQU5TSVRJT05fRU5EOiAnYnNUcmFuc2l0aW9uRW5kJyxcbiAgICBnZXRVSUQ6IGZ1bmN0aW9uIGdldFVJRChwcmVmaXgpIHtcbiAgICAgIGRvIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLWJpdHdpc2VcbiAgICAgICAgcHJlZml4ICs9IH5+KE1hdGgucmFuZG9tKCkgKiBNQVhfVUlEKTsgLy8gXCJ+flwiIGFjdHMgbGlrZSBhIGZhc3RlciBNYXRoLmZsb29yKCkgaGVyZVxuICAgICAgfSB3aGlsZSAoZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQocHJlZml4KSk7XG5cbiAgICAgIHJldHVybiBwcmVmaXg7XG4gICAgfSxcbiAgICBnZXRTZWxlY3RvckZyb21FbGVtZW50OiBmdW5jdGlvbiBnZXRTZWxlY3RvckZyb21FbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgIHZhciBzZWxlY3RvciA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLXRhcmdldCcpO1xuXG4gICAgICBpZiAoIXNlbGVjdG9yIHx8IHNlbGVjdG9yID09PSAnIycpIHtcbiAgICAgICAgc2VsZWN0b3IgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnaHJlZicpIHx8ICcnO1xuICAgICAgfSAvLyBpZiBpdCdzIGFuIElEXG5cblxuICAgICAgaWYgKHNlbGVjdG9yLmNoYXJBdCgwKSA9PT0gJyMnKSB7XG4gICAgICAgIHNlbGVjdG9yID0gZXNjYXBlSWQoc2VsZWN0b3IpO1xuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICB2YXIgJHNlbGVjdG9yID0gJCQkMShkb2N1bWVudCkuZmluZChzZWxlY3Rvcik7XG4gICAgICAgIHJldHVybiAkc2VsZWN0b3IubGVuZ3RoID4gMCA/IHNlbGVjdG9yIDogbnVsbDtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgIH0sXG4gICAgcmVmbG93OiBmdW5jdGlvbiByZWZsb3coZWxlbWVudCkge1xuICAgICAgcmV0dXJuIGVsZW1lbnQub2Zmc2V0SGVpZ2h0O1xuICAgIH0sXG4gICAgdHJpZ2dlclRyYW5zaXRpb25FbmQ6IGZ1bmN0aW9uIHRyaWdnZXJUcmFuc2l0aW9uRW5kKGVsZW1lbnQpIHtcbiAgICAgICQkJDEoZWxlbWVudCkudHJpZ2dlcih0cmFuc2l0aW9uLmVuZCk7XG4gICAgfSxcbiAgICBzdXBwb3J0c1RyYW5zaXRpb25FbmQ6IGZ1bmN0aW9uIHN1cHBvcnRzVHJhbnNpdGlvbkVuZCgpIHtcbiAgICAgIHJldHVybiBCb29sZWFuKHRyYW5zaXRpb24pO1xuICAgIH0sXG4gICAgaXNFbGVtZW50OiBmdW5jdGlvbiBpc0VsZW1lbnQob2JqKSB7XG4gICAgICByZXR1cm4gKG9ialswXSB8fCBvYmopLm5vZGVUeXBlO1xuICAgIH0sXG4gICAgdHlwZUNoZWNrQ29uZmlnOiBmdW5jdGlvbiB0eXBlQ2hlY2tDb25maWcoY29tcG9uZW50TmFtZSwgY29uZmlnLCBjb25maWdUeXBlcykge1xuICAgICAgZm9yICh2YXIgcHJvcGVydHkgaW4gY29uZmlnVHlwZXMpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChjb25maWdUeXBlcywgcHJvcGVydHkpKSB7XG4gICAgICAgICAgdmFyIGV4cGVjdGVkVHlwZXMgPSBjb25maWdUeXBlc1twcm9wZXJ0eV07XG4gICAgICAgICAgdmFyIHZhbHVlID0gY29uZmlnW3Byb3BlcnR5XTtcbiAgICAgICAgICB2YXIgdmFsdWVUeXBlID0gdmFsdWUgJiYgVXRpbC5pc0VsZW1lbnQodmFsdWUpID8gJ2VsZW1lbnQnIDogdG9UeXBlKHZhbHVlKTtcblxuICAgICAgICAgIGlmICghbmV3IFJlZ0V4cChleHBlY3RlZFR5cGVzKS50ZXN0KHZhbHVlVHlwZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihjb21wb25lbnROYW1lLnRvVXBwZXJDYXNlKCkgKyBcIjogXCIgKyAoXCJPcHRpb24gXFxcIlwiICsgcHJvcGVydHkgKyBcIlxcXCIgcHJvdmlkZWQgdHlwZSBcXFwiXCIgKyB2YWx1ZVR5cGUgKyBcIlxcXCIgXCIpICsgKFwiYnV0IGV4cGVjdGVkIHR5cGUgXFxcIlwiICsgZXhwZWN0ZWRUeXBlcyArIFwiXFxcIi5cIikpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgc2V0VHJhbnNpdGlvbkVuZFN1cHBvcnQoKTtcbiAgcmV0dXJuIFV0aWw7XG59KCQpO1xuXG4vKipcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBCb290c3RyYXAgKHY0LjAuMC1iZXRhLjMpOiBhbGVydC5qc1xuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxudmFyIEFsZXJ0ID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICB2YXIgTkFNRSA9ICdhbGVydCc7XG4gIHZhciBWRVJTSU9OID0gJzQuMC4wLWJldGEuMyc7XG4gIHZhciBEQVRBX0tFWSA9ICdicy5hbGVydCc7XG4gIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICB2YXIgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICB2YXIgVFJBTlNJVElPTl9EVVJBVElPTiA9IDE1MDtcbiAgdmFyIFNlbGVjdG9yID0ge1xuICAgIERJU01JU1M6ICdbZGF0YS1kaXNtaXNzPVwiYWxlcnRcIl0nXG4gIH07XG4gIHZhciBFdmVudCA9IHtcbiAgICBDTE9TRTogXCJjbG9zZVwiICsgRVZFTlRfS0VZLFxuICAgIENMT1NFRDogXCJjbG9zZWRcIiArIEVWRU5UX0tFWSxcbiAgICBDTElDS19EQVRBX0FQSTogXCJjbGlja1wiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gIH07XG4gIHZhciBDbGFzc05hbWUgPSB7XG4gICAgQUxFUlQ6ICdhbGVydCcsXG4gICAgRkFERTogJ2ZhZGUnLFxuICAgIFNIT1c6ICdzaG93J1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICB9O1xuXG4gIHZhciBBbGVydCA9XG4gIC8qI19fUFVSRV9fKi9cbiAgZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEFsZXJ0KGVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgIH0gLy8gZ2V0dGVyc1xuXG5cbiAgICB2YXIgX3Byb3RvID0gQWxlcnQucHJvdG90eXBlO1xuXG4gICAgLy8gcHVibGljXG4gICAgX3Byb3RvLmNsb3NlID0gZnVuY3Rpb24gY2xvc2UoZWxlbWVudCkge1xuICAgICAgZWxlbWVudCA9IGVsZW1lbnQgfHwgdGhpcy5fZWxlbWVudDtcblxuICAgICAgdmFyIHJvb3RFbGVtZW50ID0gdGhpcy5fZ2V0Um9vdEVsZW1lbnQoZWxlbWVudCk7XG5cbiAgICAgIHZhciBjdXN0b21FdmVudCA9IHRoaXMuX3RyaWdnZXJDbG9zZUV2ZW50KHJvb3RFbGVtZW50KTtcblxuICAgICAgaWYgKGN1c3RvbUV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fcmVtb3ZlRWxlbWVudChyb290RWxlbWVudCk7XG4gICAgfTtcblxuICAgIF9wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICB9OyAvLyBwcml2YXRlXG5cblxuICAgIF9wcm90by5fZ2V0Um9vdEVsZW1lbnQgPSBmdW5jdGlvbiBfZ2V0Um9vdEVsZW1lbnQoZWxlbWVudCkge1xuICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KGVsZW1lbnQpO1xuICAgICAgdmFyIHBhcmVudCA9IGZhbHNlO1xuXG4gICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgcGFyZW50ID0gJCQkMShzZWxlY3RvcilbMF07XG4gICAgICB9XG5cbiAgICAgIGlmICghcGFyZW50KSB7XG4gICAgICAgIHBhcmVudCA9ICQkJDEoZWxlbWVudCkuY2xvc2VzdChcIi5cIiArIENsYXNzTmFtZS5BTEVSVClbMF07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwYXJlbnQ7XG4gICAgfTtcblxuICAgIF9wcm90by5fdHJpZ2dlckNsb3NlRXZlbnQgPSBmdW5jdGlvbiBfdHJpZ2dlckNsb3NlRXZlbnQoZWxlbWVudCkge1xuICAgICAgdmFyIGNsb3NlRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LkNMT1NFKTtcbiAgICAgICQkJDEoZWxlbWVudCkudHJpZ2dlcihjbG9zZUV2ZW50KTtcbiAgICAgIHJldHVybiBjbG9zZUV2ZW50O1xuICAgIH07XG5cbiAgICBfcHJvdG8uX3JlbW92ZUVsZW1lbnQgPSBmdW5jdGlvbiBfcmVtb3ZlRWxlbWVudChlbGVtZW50KSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICAkJCQxKGVsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKTtcblxuICAgICAgaWYgKCFVdGlsLnN1cHBvcnRzVHJhbnNpdGlvbkVuZCgpIHx8ICEkJCQxKGVsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKSkge1xuICAgICAgICB0aGlzLl9kZXN0cm95RWxlbWVudChlbGVtZW50KTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgICQkJDEoZWxlbWVudCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICByZXR1cm4gX3RoaXMuX2Rlc3Ryb3lFbGVtZW50KGVsZW1lbnQsIGV2ZW50KTtcbiAgICAgIH0pLmVtdWxhdGVUcmFuc2l0aW9uRW5kKFRSQU5TSVRJT05fRFVSQVRJT04pO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2Rlc3Ryb3lFbGVtZW50ID0gZnVuY3Rpb24gX2Rlc3Ryb3lFbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgICQkJDEoZWxlbWVudCkuZGV0YWNoKCkudHJpZ2dlcihFdmVudC5DTE9TRUQpLnJlbW92ZSgpO1xuICAgIH07IC8vIHN0YXRpY1xuXG5cbiAgICBBbGVydC5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJGVsZW1lbnQgPSAkJCQxKHRoaXMpO1xuICAgICAgICB2YXIgZGF0YSA9ICRlbGVtZW50LmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgIGRhdGEgPSBuZXcgQWxlcnQodGhpcyk7XG4gICAgICAgICAgJGVsZW1lbnQuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnID09PSAnY2xvc2UnKSB7XG4gICAgICAgICAgZGF0YVtjb25maWddKHRoaXMpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgQWxlcnQuX2hhbmRsZURpc21pc3MgPSBmdW5jdGlvbiBfaGFuZGxlRGlzbWlzcyhhbGVydEluc3RhbmNlKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIGlmIChldmVudCkge1xuICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBhbGVydEluc3RhbmNlLmNsb3NlKHRoaXMpO1xuICAgICAgfTtcbiAgICB9O1xuXG4gICAgX2NyZWF0ZUNsYXNzKEFsZXJ0LCBudWxsLCBbe1xuICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgIH1cbiAgICB9XSk7XG4gICAgcmV0dXJuIEFsZXJ0O1xuICB9KCk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG5cbiAgJCQkMShkb2N1bWVudCkub24oRXZlbnQuQ0xJQ0tfREFUQV9BUEksIFNlbGVjdG9yLkRJU01JU1MsIEFsZXJ0Ll9oYW5kbGVEaXNtaXNzKG5ldyBBbGVydCgpKSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICAkJCQxLmZuW05BTUVdID0gQWxlcnQuX2pRdWVyeUludGVyZmFjZTtcbiAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IEFsZXJ0O1xuXG4gICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgIHJldHVybiBBbGVydC5falF1ZXJ5SW50ZXJmYWNlO1xuICB9O1xuXG4gIHJldHVybiBBbGVydDtcbn0oJCk7XG5cbi8qKlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEJvb3RzdHJhcCAodjQuMC4wLWJldGEuMyk6IGJ1dHRvbi5qc1xuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxudmFyIEJ1dHRvbiA9IGZ1bmN0aW9uICgkJCQxKSB7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ29uc3RhbnRzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgdmFyIE5BTUUgPSAnYnV0dG9uJztcbiAgdmFyIFZFUlNJT04gPSAnNC4wLjAtYmV0YS4zJztcbiAgdmFyIERBVEFfS0VZID0gJ2JzLmJ1dHRvbic7XG4gIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICB2YXIgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgIEFDVElWRTogJ2FjdGl2ZScsXG4gICAgQlVUVE9OOiAnYnRuJyxcbiAgICBGT0NVUzogJ2ZvY3VzJ1xuICB9O1xuICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgREFUQV9UT0dHTEVfQ0FSUk9UOiAnW2RhdGEtdG9nZ2xlXj1cImJ1dHRvblwiXScsXG4gICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCJidXR0b25zXCJdJyxcbiAgICBJTlBVVDogJ2lucHV0JyxcbiAgICBBQ1RJVkU6ICcuYWN0aXZlJyxcbiAgICBCVVRUT046ICcuYnRuJ1xuICB9O1xuICB2YXIgRXZlbnQgPSB7XG4gICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSxcbiAgICBGT0NVU19CTFVSX0RBVEFfQVBJOiBcImZvY3VzXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVkgKyBcIiBcIiArIChcImJsdXJcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSlcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cbiAgfTtcblxuICB2YXIgQnV0dG9uID1cbiAgLyojX19QVVJFX18qL1xuICBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQnV0dG9uKGVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgIH0gLy8gZ2V0dGVyc1xuXG5cbiAgICB2YXIgX3Byb3RvID0gQnV0dG9uLnByb3RvdHlwZTtcblxuICAgIC8vIHB1YmxpY1xuICAgIF9wcm90by50b2dnbGUgPSBmdW5jdGlvbiB0b2dnbGUoKSB7XG4gICAgICB2YXIgdHJpZ2dlckNoYW5nZUV2ZW50ID0gdHJ1ZTtcbiAgICAgIHZhciBhZGRBcmlhUHJlc3NlZCA9IHRydWU7XG4gICAgICB2YXIgcm9vdEVsZW1lbnQgPSAkJCQxKHRoaXMuX2VsZW1lbnQpLmNsb3Nlc3QoU2VsZWN0b3IuREFUQV9UT0dHTEUpWzBdO1xuXG4gICAgICBpZiAocm9vdEVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGlucHV0ID0gJCQkMSh0aGlzLl9lbGVtZW50KS5maW5kKFNlbGVjdG9yLklOUFVUKVswXTtcblxuICAgICAgICBpZiAoaW5wdXQpIHtcbiAgICAgICAgICBpZiAoaW5wdXQudHlwZSA9PT0gJ3JhZGlvJykge1xuICAgICAgICAgICAgaWYgKGlucHV0LmNoZWNrZWQgJiYgJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuQUNUSVZFKSkge1xuICAgICAgICAgICAgICB0cmlnZ2VyQ2hhbmdlRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgIHZhciBhY3RpdmVFbGVtZW50ID0gJCQkMShyb290RWxlbWVudCkuZmluZChTZWxlY3Rvci5BQ1RJVkUpWzBdO1xuXG4gICAgICAgICAgICAgIGlmIChhY3RpdmVFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgJCQkMShhY3RpdmVFbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0cmlnZ2VyQ2hhbmdlRXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChpbnB1dC5oYXNBdHRyaWJ1dGUoJ2Rpc2FibGVkJykgfHwgcm9vdEVsZW1lbnQuaGFzQXR0cmlidXRlKCdkaXNhYmxlZCcpIHx8IGlucHV0LmNsYXNzTGlzdC5jb250YWlucygnZGlzYWJsZWQnKSB8fCByb290RWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ2Rpc2FibGVkJykpIHtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpbnB1dC5jaGVja2VkID0gISQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgICAkJCQxKGlucHV0KS50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpbnB1dC5mb2N1cygpO1xuICAgICAgICAgIGFkZEFyaWFQcmVzc2VkID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGFkZEFyaWFQcmVzc2VkKSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLXByZXNzZWQnLCAhJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuQUNUSVZFKSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0cmlnZ2VyQ2hhbmdlRXZlbnQpIHtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50b2dnbGVDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLmRpc3Bvc2UgPSBmdW5jdGlvbiBkaXNwb3NlKCkge1xuICAgICAgJCQkMS5yZW1vdmVEYXRhKHRoaXMuX2VsZW1lbnQsIERBVEFfS0VZKTtcbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgIH07IC8vIHN0YXRpY1xuXG5cbiAgICBCdXR0b24uX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgIGRhdGEgPSBuZXcgQnV0dG9uKHRoaXMpO1xuICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnID09PSAndG9nZ2xlJykge1xuICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgX2NyZWF0ZUNsYXNzKEJ1dHRvbiwgbnVsbCwgW3tcbiAgICAgIGtleTogXCJWRVJTSU9OXCIsXG4gICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICB9XG4gICAgfV0pO1xuICAgIHJldHVybiBCdXR0b247XG4gIH0oKTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cblxuICAkJCQxKGRvY3VtZW50KS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEVfQ0FSUk9ULCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHZhciBidXR0b24gPSBldmVudC50YXJnZXQ7XG5cbiAgICBpZiAoISQkJDEoYnV0dG9uKS5oYXNDbGFzcyhDbGFzc05hbWUuQlVUVE9OKSkge1xuICAgICAgYnV0dG9uID0gJCQkMShidXR0b24pLmNsb3Nlc3QoU2VsZWN0b3IuQlVUVE9OKTtcbiAgICB9XG5cbiAgICBCdXR0b24uX2pRdWVyeUludGVyZmFjZS5jYWxsKCQkJDEoYnV0dG9uKSwgJ3RvZ2dsZScpO1xuICB9KS5vbihFdmVudC5GT0NVU19CTFVSX0RBVEFfQVBJLCBTZWxlY3Rvci5EQVRBX1RPR0dMRV9DQVJST1QsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciBidXR0b24gPSAkJCQxKGV2ZW50LnRhcmdldCkuY2xvc2VzdChTZWxlY3Rvci5CVVRUT04pWzBdO1xuICAgICQkJDEoYnV0dG9uKS50b2dnbGVDbGFzcyhDbGFzc05hbWUuRk9DVVMsIC9eZm9jdXMoaW4pPyQvLnRlc3QoZXZlbnQudHlwZSkpO1xuICB9KTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBqUXVlcnlcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG4gICQkJDEuZm5bTkFNRV0gPSBCdXR0b24uX2pRdWVyeUludGVyZmFjZTtcbiAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IEJ1dHRvbjtcblxuICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICByZXR1cm4gQnV0dG9uLl9qUXVlcnlJbnRlcmZhY2U7XG4gIH07XG5cbiAgcmV0dXJuIEJ1dHRvbjtcbn0oJCk7XG5cbi8qKlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEJvb3RzdHJhcCAodjQuMC4wLWJldGEuMyk6IGNhcm91c2VsLmpzXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG52YXIgQ2Fyb3VzZWwgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENvbnN0YW50c1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIHZhciBOQU1FID0gJ2Nhcm91c2VsJztcbiAgdmFyIFZFUlNJT04gPSAnNC4wLjAtYmV0YS4zJztcbiAgdmFyIERBVEFfS0VZID0gJ2JzLmNhcm91c2VsJztcbiAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gIHZhciBUUkFOU0lUSU9OX0RVUkFUSU9OID0gNjAwO1xuICB2YXIgQVJST1dfTEVGVF9LRVlDT0RFID0gMzc7IC8vIEtleWJvYXJkRXZlbnQud2hpY2ggdmFsdWUgZm9yIGxlZnQgYXJyb3cga2V5XG5cbiAgdmFyIEFSUk9XX1JJR0hUX0tFWUNPREUgPSAzOTsgLy8gS2V5Ym9hcmRFdmVudC53aGljaCB2YWx1ZSBmb3IgcmlnaHQgYXJyb3cga2V5XG5cbiAgdmFyIFRPVUNIRVZFTlRfQ09NUEFUX1dBSVQgPSA1MDA7IC8vIFRpbWUgZm9yIG1vdXNlIGNvbXBhdCBldmVudHMgdG8gZmlyZSBhZnRlciB0b3VjaFxuXG4gIHZhciBEZWZhdWx0ID0ge1xuICAgIGludGVydmFsOiA1MDAwLFxuICAgIGtleWJvYXJkOiB0cnVlLFxuICAgIHNsaWRlOiBmYWxzZSxcbiAgICBwYXVzZTogJ2hvdmVyJyxcbiAgICB3cmFwOiB0cnVlXG4gIH07XG4gIHZhciBEZWZhdWx0VHlwZSA9IHtcbiAgICBpbnRlcnZhbDogJyhudW1iZXJ8Ym9vbGVhbiknLFxuICAgIGtleWJvYXJkOiAnYm9vbGVhbicsXG4gICAgc2xpZGU6ICcoYm9vbGVhbnxzdHJpbmcpJyxcbiAgICBwYXVzZTogJyhzdHJpbmd8Ym9vbGVhbiknLFxuICAgIHdyYXA6ICdib29sZWFuJ1xuICB9O1xuICB2YXIgRGlyZWN0aW9uID0ge1xuICAgIE5FWFQ6ICduZXh0JyxcbiAgICBQUkVWOiAncHJldicsXG4gICAgTEVGVDogJ2xlZnQnLFxuICAgIFJJR0hUOiAncmlnaHQnXG4gIH07XG4gIHZhciBFdmVudCA9IHtcbiAgICBTTElERTogXCJzbGlkZVwiICsgRVZFTlRfS0VZLFxuICAgIFNMSUQ6IFwic2xpZFwiICsgRVZFTlRfS0VZLFxuICAgIEtFWURPV046IFwia2V5ZG93blwiICsgRVZFTlRfS0VZLFxuICAgIE1PVVNFRU5URVI6IFwibW91c2VlbnRlclwiICsgRVZFTlRfS0VZLFxuICAgIE1PVVNFTEVBVkU6IFwibW91c2VsZWF2ZVwiICsgRVZFTlRfS0VZLFxuICAgIFRPVUNIRU5EOiBcInRvdWNoZW5kXCIgKyBFVkVOVF9LRVksXG4gICAgTE9BRF9EQVRBX0FQSTogXCJsb2FkXCIgKyBFVkVOVF9LRVkgKyBEQVRBX0FQSV9LRVksXG4gICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWVxuICB9O1xuICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgIENBUk9VU0VMOiAnY2Fyb3VzZWwnLFxuICAgIEFDVElWRTogJ2FjdGl2ZScsXG4gICAgU0xJREU6ICdzbGlkZScsXG4gICAgUklHSFQ6ICdjYXJvdXNlbC1pdGVtLXJpZ2h0JyxcbiAgICBMRUZUOiAnY2Fyb3VzZWwtaXRlbS1sZWZ0JyxcbiAgICBORVhUOiAnY2Fyb3VzZWwtaXRlbS1uZXh0JyxcbiAgICBQUkVWOiAnY2Fyb3VzZWwtaXRlbS1wcmV2JyxcbiAgICBJVEVNOiAnY2Fyb3VzZWwtaXRlbSdcbiAgfTtcbiAgdmFyIFNlbGVjdG9yID0ge1xuICAgIEFDVElWRTogJy5hY3RpdmUnLFxuICAgIEFDVElWRV9JVEVNOiAnLmFjdGl2ZS5jYXJvdXNlbC1pdGVtJyxcbiAgICBJVEVNOiAnLmNhcm91c2VsLWl0ZW0nLFxuICAgIE5FWFRfUFJFVjogJy5jYXJvdXNlbC1pdGVtLW5leHQsIC5jYXJvdXNlbC1pdGVtLXByZXYnLFxuICAgIElORElDQVRPUlM6ICcuY2Fyb3VzZWwtaW5kaWNhdG9ycycsXG4gICAgREFUQV9TTElERTogJ1tkYXRhLXNsaWRlXSwgW2RhdGEtc2xpZGUtdG9dJyxcbiAgICBEQVRBX1JJREU6ICdbZGF0YS1yaWRlPVwiY2Fyb3VzZWxcIl0nXG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gIH07XG5cbiAgdmFyIENhcm91c2VsID1cbiAgLyojX19QVVJFX18qL1xuICBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ2Fyb3VzZWwoZWxlbWVudCwgY29uZmlnKSB7XG4gICAgICB0aGlzLl9pdGVtcyA9IG51bGw7XG4gICAgICB0aGlzLl9pbnRlcnZhbCA9IG51bGw7XG4gICAgICB0aGlzLl9hY3RpdmVFbGVtZW50ID0gbnVsbDtcbiAgICAgIHRoaXMuX2lzUGF1c2VkID0gZmFsc2U7XG4gICAgICB0aGlzLl9pc1NsaWRpbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMudG91Y2hUaW1lb3V0ID0gbnVsbDtcbiAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgdGhpcy5fZWxlbWVudCA9ICQkJDEoZWxlbWVudClbMF07XG4gICAgICB0aGlzLl9pbmRpY2F0b3JzRWxlbWVudCA9ICQkJDEodGhpcy5fZWxlbWVudCkuZmluZChTZWxlY3Rvci5JTkRJQ0FUT1JTKVswXTtcblxuICAgICAgdGhpcy5fYWRkRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICB9IC8vIGdldHRlcnNcblxuXG4gICAgdmFyIF9wcm90byA9IENhcm91c2VsLnByb3RvdHlwZTtcblxuICAgIC8vIHB1YmxpY1xuICAgIF9wcm90by5uZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHtcbiAgICAgIGlmICghdGhpcy5faXNTbGlkaW5nKSB7XG4gICAgICAgIHRoaXMuX3NsaWRlKERpcmVjdGlvbi5ORVhUKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLm5leHRXaGVuVmlzaWJsZSA9IGZ1bmN0aW9uIG5leHRXaGVuVmlzaWJsZSgpIHtcbiAgICAgIC8vIERvbid0IGNhbGwgbmV4dCB3aGVuIHRoZSBwYWdlIGlzbid0IHZpc2libGVcbiAgICAgIC8vIG9yIHRoZSBjYXJvdXNlbCBvciBpdHMgcGFyZW50IGlzbid0IHZpc2libGVcbiAgICAgIGlmICghZG9jdW1lbnQuaGlkZGVuICYmICQkJDEodGhpcy5fZWxlbWVudCkuaXMoJzp2aXNpYmxlJykgJiYgJCQkMSh0aGlzLl9lbGVtZW50KS5jc3MoJ3Zpc2liaWxpdHknKSAhPT0gJ2hpZGRlbicpIHtcbiAgICAgICAgdGhpcy5uZXh0KCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by5wcmV2ID0gZnVuY3Rpb24gcHJldigpIHtcbiAgICAgIGlmICghdGhpcy5faXNTbGlkaW5nKSB7XG4gICAgICAgIHRoaXMuX3NsaWRlKERpcmVjdGlvbi5QUkVWKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLnBhdXNlID0gZnVuY3Rpb24gcGF1c2UoZXZlbnQpIHtcbiAgICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgdGhpcy5faXNQYXVzZWQgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBpZiAoJCQkMSh0aGlzLl9lbGVtZW50KS5maW5kKFNlbGVjdG9yLk5FWFRfUFJFVilbMF0gJiYgVXRpbC5zdXBwb3J0c1RyYW5zaXRpb25FbmQoKSkge1xuICAgICAgICBVdGlsLnRyaWdnZXJUcmFuc2l0aW9uRW5kKHRoaXMuX2VsZW1lbnQpO1xuICAgICAgICB0aGlzLmN5Y2xlKHRydWUpO1xuICAgICAgfVxuXG4gICAgICBjbGVhckludGVydmFsKHRoaXMuX2ludGVydmFsKTtcbiAgICAgIHRoaXMuX2ludGVydmFsID0gbnVsbDtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmN5Y2xlID0gZnVuY3Rpb24gY3ljbGUoZXZlbnQpIHtcbiAgICAgIGlmICghZXZlbnQpIHtcbiAgICAgICAgdGhpcy5faXNQYXVzZWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2ludGVydmFsKSB7XG4gICAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5faW50ZXJ2YWwpO1xuICAgICAgICB0aGlzLl9pbnRlcnZhbCA9IG51bGw7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcuaW50ZXJ2YWwgJiYgIXRoaXMuX2lzUGF1c2VkKSB7XG4gICAgICAgIHRoaXMuX2ludGVydmFsID0gc2V0SW50ZXJ2YWwoKGRvY3VtZW50LnZpc2liaWxpdHlTdGF0ZSA/IHRoaXMubmV4dFdoZW5WaXNpYmxlIDogdGhpcy5uZXh0KS5iaW5kKHRoaXMpLCB0aGlzLl9jb25maWcuaW50ZXJ2YWwpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8udG8gPSBmdW5jdGlvbiB0byhpbmRleCkge1xuICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgdGhpcy5fYWN0aXZlRWxlbWVudCA9ICQkJDEodGhpcy5fZWxlbWVudCkuZmluZChTZWxlY3Rvci5BQ1RJVkVfSVRFTSlbMF07XG5cbiAgICAgIHZhciBhY3RpdmVJbmRleCA9IHRoaXMuX2dldEl0ZW1JbmRleCh0aGlzLl9hY3RpdmVFbGVtZW50KTtcblxuICAgICAgaWYgKGluZGV4ID4gdGhpcy5faXRlbXMubGVuZ3RoIC0gMSB8fCBpbmRleCA8IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faXNTbGlkaW5nKSB7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub25lKEV2ZW50LlNMSUQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMudG8oaW5kZXgpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoYWN0aXZlSW5kZXggPT09IGluZGV4KSB7XG4gICAgICAgIHRoaXMucGF1c2UoKTtcbiAgICAgICAgdGhpcy5jeWNsZSgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBkaXJlY3Rpb24gPSBpbmRleCA+IGFjdGl2ZUluZGV4ID8gRGlyZWN0aW9uLk5FWFQgOiBEaXJlY3Rpb24uUFJFVjtcblxuICAgICAgdGhpcy5fc2xpZGUoZGlyZWN0aW9uLCB0aGlzLl9pdGVtc1tpbmRleF0pO1xuICAgIH07XG5cbiAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9mZihFVkVOVF9LRVkpO1xuICAgICAgJCQkMS5yZW1vdmVEYXRhKHRoaXMuX2VsZW1lbnQsIERBVEFfS0VZKTtcbiAgICAgIHRoaXMuX2l0ZW1zID0gbnVsbDtcbiAgICAgIHRoaXMuX2NvbmZpZyA9IG51bGw7XG4gICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICAgIHRoaXMuX2ludGVydmFsID0gbnVsbDtcbiAgICAgIHRoaXMuX2lzUGF1c2VkID0gbnVsbDtcbiAgICAgIHRoaXMuX2lzU2xpZGluZyA9IG51bGw7XG4gICAgICB0aGlzLl9hY3RpdmVFbGVtZW50ID0gbnVsbDtcbiAgICAgIHRoaXMuX2luZGljYXRvcnNFbGVtZW50ID0gbnVsbDtcbiAgICB9OyAvLyBwcml2YXRlXG5cblxuICAgIF9wcm90by5fZ2V0Q29uZmlnID0gZnVuY3Rpb24gX2dldENvbmZpZyhjb25maWcpIHtcbiAgICAgIGNvbmZpZyA9IF9leHRlbmRzKHt9LCBEZWZhdWx0LCBjb25maWcpO1xuICAgICAgVXRpbC50eXBlQ2hlY2tDb25maWcoTkFNRSwgY29uZmlnLCBEZWZhdWx0VHlwZSk7XG4gICAgICByZXR1cm4gY29uZmlnO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2FkZEV2ZW50TGlzdGVuZXJzID0gZnVuY3Rpb24gX2FkZEV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcua2V5Ym9hcmQpIHtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbihFdmVudC5LRVlET1dOLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMyLl9rZXlkb3duKGV2ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLl9jb25maWcucGF1c2UgPT09ICdob3ZlcicpIHtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbihFdmVudC5NT1VTRUVOVEVSLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMyLnBhdXNlKGV2ZW50KTtcbiAgICAgICAgfSkub24oRXZlbnQuTU9VU0VMRUFWRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzMi5jeWNsZShldmVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmICgnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQpIHtcbiAgICAgICAgICAvLyBpZiBpdCdzIGEgdG91Y2gtZW5hYmxlZCBkZXZpY2UsIG1vdXNlZW50ZXIvbGVhdmUgYXJlIGZpcmVkIGFzXG4gICAgICAgICAgLy8gcGFydCBvZiB0aGUgbW91c2UgY29tcGF0aWJpbGl0eSBldmVudHMgb24gZmlyc3QgdGFwIC0gdGhlIGNhcm91c2VsXG4gICAgICAgICAgLy8gd291bGQgc3RvcCBjeWNsaW5nIHVudGlsIHVzZXIgdGFwcGVkIG91dCBvZiBpdDtcbiAgICAgICAgICAvLyBoZXJlLCB3ZSBsaXN0ZW4gZm9yIHRvdWNoZW5kLCBleHBsaWNpdGx5IHBhdXNlIHRoZSBjYXJvdXNlbFxuICAgICAgICAgIC8vIChhcyBpZiBpdCdzIHRoZSBzZWNvbmQgdGltZSB3ZSB0YXAgb24gaXQsIG1vdXNlZW50ZXIgY29tcGF0IGV2ZW50XG4gICAgICAgICAgLy8gaXMgTk9UIGZpcmVkKSBhbmQgYWZ0ZXIgYSB0aW1lb3V0ICh0byBhbGxvdyBmb3IgbW91c2UgY29tcGF0aWJpbGl0eVxuICAgICAgICAgIC8vIGV2ZW50cyB0byBmaXJlKSB3ZSBleHBsaWNpdGx5IHJlc3RhcnQgY3ljbGluZ1xuICAgICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub24oRXZlbnQuVE9VQ0hFTkQsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzMi5wYXVzZSgpO1xuXG4gICAgICAgICAgICBpZiAoX3RoaXMyLnRvdWNoVGltZW91dCkge1xuICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoX3RoaXMyLnRvdWNoVGltZW91dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIF90aGlzMi50b3VjaFRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgICByZXR1cm4gX3RoaXMyLmN5Y2xlKGV2ZW50KTtcbiAgICAgICAgICAgIH0sIFRPVUNIRVZFTlRfQ09NUEFUX1dBSVQgKyBfdGhpczIuX2NvbmZpZy5pbnRlcnZhbCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9rZXlkb3duID0gZnVuY3Rpb24gX2tleWRvd24oZXZlbnQpIHtcbiAgICAgIGlmICgvaW5wdXR8dGV4dGFyZWEvaS50ZXN0KGV2ZW50LnRhcmdldC50YWdOYW1lKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHN3aXRjaCAoZXZlbnQud2hpY2gpIHtcbiAgICAgICAgY2FzZSBBUlJPV19MRUZUX0tFWUNPREU6XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB0aGlzLnByZXYoKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBjYXNlIEFSUk9XX1JJR0hUX0tFWUNPREU6XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICB0aGlzLm5leHQoKTtcbiAgICAgICAgICBicmVhaztcblxuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9nZXRJdGVtSW5kZXggPSBmdW5jdGlvbiBfZ2V0SXRlbUluZGV4KGVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX2l0ZW1zID0gJCQkMS5tYWtlQXJyYXkoJCQkMShlbGVtZW50KS5wYXJlbnQoKS5maW5kKFNlbGVjdG9yLklURU0pKTtcbiAgICAgIHJldHVybiB0aGlzLl9pdGVtcy5pbmRleE9mKGVsZW1lbnQpO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldEl0ZW1CeURpcmVjdGlvbiA9IGZ1bmN0aW9uIF9nZXRJdGVtQnlEaXJlY3Rpb24oZGlyZWN0aW9uLCBhY3RpdmVFbGVtZW50KSB7XG4gICAgICB2YXIgaXNOZXh0RGlyZWN0aW9uID0gZGlyZWN0aW9uID09PSBEaXJlY3Rpb24uTkVYVDtcbiAgICAgIHZhciBpc1ByZXZEaXJlY3Rpb24gPSBkaXJlY3Rpb24gPT09IERpcmVjdGlvbi5QUkVWO1xuXG4gICAgICB2YXIgYWN0aXZlSW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgoYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgIHZhciBsYXN0SXRlbUluZGV4ID0gdGhpcy5faXRlbXMubGVuZ3RoIC0gMTtcbiAgICAgIHZhciBpc0dvaW5nVG9XcmFwID0gaXNQcmV2RGlyZWN0aW9uICYmIGFjdGl2ZUluZGV4ID09PSAwIHx8IGlzTmV4dERpcmVjdGlvbiAmJiBhY3RpdmVJbmRleCA9PT0gbGFzdEl0ZW1JbmRleDtcblxuICAgICAgaWYgKGlzR29pbmdUb1dyYXAgJiYgIXRoaXMuX2NvbmZpZy53cmFwKSB7XG4gICAgICAgIHJldHVybiBhY3RpdmVFbGVtZW50O1xuICAgICAgfVxuXG4gICAgICB2YXIgZGVsdGEgPSBkaXJlY3Rpb24gPT09IERpcmVjdGlvbi5QUkVWID8gLTEgOiAxO1xuICAgICAgdmFyIGl0ZW1JbmRleCA9IChhY3RpdmVJbmRleCArIGRlbHRhKSAlIHRoaXMuX2l0ZW1zLmxlbmd0aDtcbiAgICAgIHJldHVybiBpdGVtSW5kZXggPT09IC0xID8gdGhpcy5faXRlbXNbdGhpcy5faXRlbXMubGVuZ3RoIC0gMV0gOiB0aGlzLl9pdGVtc1tpdGVtSW5kZXhdO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX3RyaWdnZXJTbGlkZUV2ZW50ID0gZnVuY3Rpb24gX3RyaWdnZXJTbGlkZUV2ZW50KHJlbGF0ZWRUYXJnZXQsIGV2ZW50RGlyZWN0aW9uTmFtZSkge1xuICAgICAgdmFyIHRhcmdldEluZGV4ID0gdGhpcy5fZ2V0SXRlbUluZGV4KHJlbGF0ZWRUYXJnZXQpO1xuXG4gICAgICB2YXIgZnJvbUluZGV4ID0gdGhpcy5fZ2V0SXRlbUluZGV4KCQkJDEodGhpcy5fZWxlbWVudCkuZmluZChTZWxlY3Rvci5BQ1RJVkVfSVRFTSlbMF0pO1xuXG4gICAgICB2YXIgc2xpZGVFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuU0xJREUsIHtcbiAgICAgICAgcmVsYXRlZFRhcmdldDogcmVsYXRlZFRhcmdldCxcbiAgICAgICAgZGlyZWN0aW9uOiBldmVudERpcmVjdGlvbk5hbWUsXG4gICAgICAgIGZyb206IGZyb21JbmRleCxcbiAgICAgICAgdG86IHRhcmdldEluZGV4XG4gICAgICB9KTtcbiAgICAgICQkJDEodGhpcy5fZWxlbWVudCkudHJpZ2dlcihzbGlkZUV2ZW50KTtcbiAgICAgIHJldHVybiBzbGlkZUV2ZW50O1xuICAgIH07XG5cbiAgICBfcHJvdG8uX3NldEFjdGl2ZUluZGljYXRvckVsZW1lbnQgPSBmdW5jdGlvbiBfc2V0QWN0aXZlSW5kaWNhdG9yRWxlbWVudChlbGVtZW50KSB7XG4gICAgICBpZiAodGhpcy5faW5kaWNhdG9yc0VsZW1lbnQpIHtcbiAgICAgICAgJCQkMSh0aGlzLl9pbmRpY2F0b3JzRWxlbWVudCkuZmluZChTZWxlY3Rvci5BQ1RJVkUpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuXG4gICAgICAgIHZhciBuZXh0SW5kaWNhdG9yID0gdGhpcy5faW5kaWNhdG9yc0VsZW1lbnQuY2hpbGRyZW5bdGhpcy5fZ2V0SXRlbUluZGV4KGVsZW1lbnQpXTtcblxuICAgICAgICBpZiAobmV4dEluZGljYXRvcikge1xuICAgICAgICAgICQkJDEobmV4dEluZGljYXRvcikuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9zbGlkZSA9IGZ1bmN0aW9uIF9zbGlkZShkaXJlY3Rpb24sIGVsZW1lbnQpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICB2YXIgYWN0aXZlRWxlbWVudCA9ICQkJDEodGhpcy5fZWxlbWVudCkuZmluZChTZWxlY3Rvci5BQ1RJVkVfSVRFTSlbMF07XG5cbiAgICAgIHZhciBhY3RpdmVFbGVtZW50SW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgoYWN0aXZlRWxlbWVudCk7XG5cbiAgICAgIHZhciBuZXh0RWxlbWVudCA9IGVsZW1lbnQgfHwgYWN0aXZlRWxlbWVudCAmJiB0aGlzLl9nZXRJdGVtQnlEaXJlY3Rpb24oZGlyZWN0aW9uLCBhY3RpdmVFbGVtZW50KTtcblxuICAgICAgdmFyIG5leHRFbGVtZW50SW5kZXggPSB0aGlzLl9nZXRJdGVtSW5kZXgobmV4dEVsZW1lbnQpO1xuXG4gICAgICB2YXIgaXNDeWNsaW5nID0gQm9vbGVhbih0aGlzLl9pbnRlcnZhbCk7XG4gICAgICB2YXIgZGlyZWN0aW9uYWxDbGFzc05hbWU7XG4gICAgICB2YXIgb3JkZXJDbGFzc05hbWU7XG4gICAgICB2YXIgZXZlbnREaXJlY3Rpb25OYW1lO1xuXG4gICAgICBpZiAoZGlyZWN0aW9uID09PSBEaXJlY3Rpb24uTkVYVCkge1xuICAgICAgICBkaXJlY3Rpb25hbENsYXNzTmFtZSA9IENsYXNzTmFtZS5MRUZUO1xuICAgICAgICBvcmRlckNsYXNzTmFtZSA9IENsYXNzTmFtZS5ORVhUO1xuICAgICAgICBldmVudERpcmVjdGlvbk5hbWUgPSBEaXJlY3Rpb24uTEVGVDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGRpcmVjdGlvbmFsQ2xhc3NOYW1lID0gQ2xhc3NOYW1lLlJJR0hUO1xuICAgICAgICBvcmRlckNsYXNzTmFtZSA9IENsYXNzTmFtZS5QUkVWO1xuICAgICAgICBldmVudERpcmVjdGlvbk5hbWUgPSBEaXJlY3Rpb24uUklHSFQ7XG4gICAgICB9XG5cbiAgICAgIGlmIChuZXh0RWxlbWVudCAmJiAkJCQxKG5leHRFbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuQUNUSVZFKSkge1xuICAgICAgICB0aGlzLl9pc1NsaWRpbmcgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgc2xpZGVFdmVudCA9IHRoaXMuX3RyaWdnZXJTbGlkZUV2ZW50KG5leHRFbGVtZW50LCBldmVudERpcmVjdGlvbk5hbWUpO1xuXG4gICAgICBpZiAoc2xpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGlmICghYWN0aXZlRWxlbWVudCB8fCAhbmV4dEVsZW1lbnQpIHtcbiAgICAgICAgLy8gc29tZSB3ZWlyZG5lc3MgaXMgaGFwcGVuaW5nLCBzbyB3ZSBiYWlsXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy5faXNTbGlkaW5nID0gdHJ1ZTtcblxuICAgICAgaWYgKGlzQ3ljbGluZykge1xuICAgICAgICB0aGlzLnBhdXNlKCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3NldEFjdGl2ZUluZGljYXRvckVsZW1lbnQobmV4dEVsZW1lbnQpO1xuXG4gICAgICB2YXIgc2xpZEV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TTElELCB7XG4gICAgICAgIHJlbGF0ZWRUYXJnZXQ6IG5leHRFbGVtZW50LFxuICAgICAgICBkaXJlY3Rpb246IGV2ZW50RGlyZWN0aW9uTmFtZSxcbiAgICAgICAgZnJvbTogYWN0aXZlRWxlbWVudEluZGV4LFxuICAgICAgICB0bzogbmV4dEVsZW1lbnRJbmRleFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChVdGlsLnN1cHBvcnRzVHJhbnNpdGlvbkVuZCgpICYmICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNMSURFKSkge1xuICAgICAgICAkJCQxKG5leHRFbGVtZW50KS5hZGRDbGFzcyhvcmRlckNsYXNzTmFtZSk7XG4gICAgICAgIFV0aWwucmVmbG93KG5leHRFbGVtZW50KTtcbiAgICAgICAgJCQkMShhY3RpdmVFbGVtZW50KS5hZGRDbGFzcyhkaXJlY3Rpb25hbENsYXNzTmFtZSk7XG4gICAgICAgICQkJDEobmV4dEVsZW1lbnQpLmFkZENsYXNzKGRpcmVjdGlvbmFsQ2xhc3NOYW1lKTtcbiAgICAgICAgJCQkMShhY3RpdmVFbGVtZW50KS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICQkJDEobmV4dEVsZW1lbnQpLnJlbW92ZUNsYXNzKGRpcmVjdGlvbmFsQ2xhc3NOYW1lICsgXCIgXCIgKyBvcmRlckNsYXNzTmFtZSkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgICAgJCQkMShhY3RpdmVFbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQUNUSVZFICsgXCIgXCIgKyBvcmRlckNsYXNzTmFtZSArIFwiIFwiICsgZGlyZWN0aW9uYWxDbGFzc05hbWUpO1xuICAgICAgICAgIF90aGlzMy5faXNTbGlkaW5nID0gZmFsc2U7XG4gICAgICAgICAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gJCQkMShfdGhpczMuX2VsZW1lbnQpLnRyaWdnZXIoc2xpZEV2ZW50KTtcbiAgICAgICAgICB9LCAwKTtcbiAgICAgICAgfSkuZW11bGF0ZVRyYW5zaXRpb25FbmQoVFJBTlNJVElPTl9EVVJBVElPTik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAkJCQxKGFjdGl2ZUVsZW1lbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICAkJCQxKG5leHRFbGVtZW50KS5hZGRDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgdGhpcy5faXNTbGlkaW5nID0gZmFsc2U7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkudHJpZ2dlcihzbGlkRXZlbnQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoaXNDeWNsaW5nKSB7XG4gICAgICAgIHRoaXMuY3ljbGUoKTtcbiAgICAgIH1cbiAgICB9OyAvLyBzdGF0aWNcblxuXG4gICAgQ2Fyb3VzZWwuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgIHZhciBfY29uZmlnID0gX2V4dGVuZHMoe30sIERlZmF1bHQsICQkJDEodGhpcykuZGF0YSgpKTtcblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICBfY29uZmlnID0gX2V4dGVuZHMoe30sIF9jb25maWcsIGNvbmZpZyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYWN0aW9uID0gdHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycgPyBjb25maWcgOiBfY29uZmlnLnNsaWRlO1xuXG4gICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgIGRhdGEgPSBuZXcgQ2Fyb3VzZWwodGhpcywgX2NvbmZpZyk7XG4gICAgICAgICAgJCQkMSh0aGlzKS5kYXRhKERBVEFfS0VZLCBkYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIGRhdGEudG8oY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgYWN0aW9uID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YVthY3Rpb25dID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gbWV0aG9kIG5hbWVkIFxcXCJcIiArIGFjdGlvbiArIFwiXFxcIlwiKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBkYXRhW2FjdGlvbl0oKTtcbiAgICAgICAgfSBlbHNlIGlmIChfY29uZmlnLmludGVydmFsKSB7XG4gICAgICAgICAgZGF0YS5wYXVzZSgpO1xuICAgICAgICAgIGRhdGEuY3ljbGUoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIENhcm91c2VsLl9kYXRhQXBpQ2xpY2tIYW5kbGVyID0gZnVuY3Rpb24gX2RhdGFBcGlDbGlja0hhbmRsZXIoZXZlbnQpIHtcbiAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCh0aGlzKTtcblxuICAgICAgaWYgKCFzZWxlY3Rvcikge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciB0YXJnZXQgPSAkJCQxKHNlbGVjdG9yKVswXTtcblxuICAgICAgaWYgKCF0YXJnZXQgfHwgISQkJDEodGFyZ2V0KS5oYXNDbGFzcyhDbGFzc05hbWUuQ0FST1VTRUwpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGNvbmZpZyA9IF9leHRlbmRzKHt9LCAkJCQxKHRhcmdldCkuZGF0YSgpLCAkJCQxKHRoaXMpLmRhdGEoKSk7XG4gICAgICB2YXIgc2xpZGVJbmRleCA9IHRoaXMuZ2V0QXR0cmlidXRlKCdkYXRhLXNsaWRlLXRvJyk7XG5cbiAgICAgIGlmIChzbGlkZUluZGV4KSB7XG4gICAgICAgIGNvbmZpZy5pbnRlcnZhbCA9IGZhbHNlO1xuICAgICAgfVxuXG4gICAgICBDYXJvdXNlbC5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJCQkMSh0YXJnZXQpLCBjb25maWcpO1xuXG4gICAgICBpZiAoc2xpZGVJbmRleCkge1xuICAgICAgICAkJCQxKHRhcmdldCkuZGF0YShEQVRBX0tFWSkudG8oc2xpZGVJbmRleCk7XG4gICAgICB9XG5cbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfTtcblxuICAgIF9jcmVhdGVDbGFzcyhDYXJvdXNlbCwgbnVsbCwgW3tcbiAgICAgIGtleTogXCJWRVJTSU9OXCIsXG4gICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgIH1cbiAgICB9XSk7XG4gICAgcmV0dXJuIENhcm91c2VsO1xuICB9KCk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG5cbiAgJCQkMShkb2N1bWVudCkub24oRXZlbnQuQ0xJQ0tfREFUQV9BUEksIFNlbGVjdG9yLkRBVEFfU0xJREUsIENhcm91c2VsLl9kYXRhQXBpQ2xpY2tIYW5kbGVyKTtcbiAgJCQkMSh3aW5kb3cpLm9uKEV2ZW50LkxPQURfREFUQV9BUEksIGZ1bmN0aW9uICgpIHtcbiAgICAkJCQxKFNlbGVjdG9yLkRBVEFfUklERSkuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJGNhcm91c2VsID0gJCQkMSh0aGlzKTtcblxuICAgICAgQ2Fyb3VzZWwuX2pRdWVyeUludGVyZmFjZS5jYWxsKCRjYXJvdXNlbCwgJGNhcm91c2VsLmRhdGEoKSk7XG4gICAgfSk7XG4gIH0pO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIGpRdWVyeVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgJCQkMS5mbltOQU1FXSA9IENhcm91c2VsLl9qUXVlcnlJbnRlcmZhY2U7XG4gICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBDYXJvdXNlbDtcblxuICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICByZXR1cm4gQ2Fyb3VzZWwuX2pRdWVyeUludGVyZmFjZTtcbiAgfTtcblxuICByZXR1cm4gQ2Fyb3VzZWw7XG59KCQpO1xuXG4vKipcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBCb290c3RyYXAgKHY0LjAuMC1iZXRhLjMpOiBjb2xsYXBzZS5qc1xuICogTGljZW5zZWQgdW5kZXIgTUlUIChodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvYmxvYi9tYXN0ZXIvTElDRU5TRSlcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKi9cblxudmFyIENvbGxhcHNlID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICB2YXIgTkFNRSA9ICdjb2xsYXBzZSc7XG4gIHZhciBWRVJTSU9OID0gJzQuMC4wLWJldGEuMyc7XG4gIHZhciBEQVRBX0tFWSA9ICdicy5jb2xsYXBzZSc7XG4gIHZhciBFVkVOVF9LRVkgPSBcIi5cIiArIERBVEFfS0VZO1xuICB2YXIgREFUQV9BUElfS0VZID0gJy5kYXRhLWFwaSc7XG4gIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICB2YXIgVFJBTlNJVElPTl9EVVJBVElPTiA9IDYwMDtcbiAgdmFyIERlZmF1bHQgPSB7XG4gICAgdG9nZ2xlOiB0cnVlLFxuICAgIHBhcmVudDogJydcbiAgfTtcbiAgdmFyIERlZmF1bHRUeXBlID0ge1xuICAgIHRvZ2dsZTogJ2Jvb2xlYW4nLFxuICAgIHBhcmVudDogJyhzdHJpbmd8ZWxlbWVudCknXG4gIH07XG4gIHZhciBFdmVudCA9IHtcbiAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICBTSE9XTjogXCJzaG93blwiICsgRVZFTlRfS0VZLFxuICAgIEhJREU6IFwiaGlkZVwiICsgRVZFTlRfS0VZLFxuICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICBDTElDS19EQVRBX0FQSTogXCJjbGlja1wiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gIH07XG4gIHZhciBDbGFzc05hbWUgPSB7XG4gICAgU0hPVzogJ3Nob3cnLFxuICAgIENPTExBUFNFOiAnY29sbGFwc2UnLFxuICAgIENPTExBUFNJTkc6ICdjb2xsYXBzaW5nJyxcbiAgICBDT0xMQVBTRUQ6ICdjb2xsYXBzZWQnXG4gIH07XG4gIHZhciBEaW1lbnNpb24gPSB7XG4gICAgV0lEVEg6ICd3aWR0aCcsXG4gICAgSEVJR0hUOiAnaGVpZ2h0J1xuICB9O1xuICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgQUNUSVZFUzogJy5zaG93LCAuY29sbGFwc2luZycsXG4gICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCJjb2xsYXBzZVwiXSdcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cbiAgfTtcblxuICB2YXIgQ29sbGFwc2UgPVxuICAvKiNfX1BVUkVfXyovXG4gIGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBDb2xsYXBzZShlbGVtZW50LCBjb25maWcpIHtcbiAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICB0aGlzLl9jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgIHRoaXMuX3RyaWdnZXJBcnJheSA9ICQkJDEubWFrZUFycmF5KCQkJDEoXCJbZGF0YS10b2dnbGU9XFxcImNvbGxhcHNlXFxcIl1baHJlZj1cXFwiI1wiICsgZWxlbWVudC5pZCArIFwiXFxcIl0sXCIgKyAoXCJbZGF0YS10b2dnbGU9XFxcImNvbGxhcHNlXFxcIl1bZGF0YS10YXJnZXQ9XFxcIiNcIiArIGVsZW1lbnQuaWQgKyBcIlxcXCJdXCIpKSk7XG4gICAgICB2YXIgdGFiVG9nZ2xlcyA9ICQkJDEoU2VsZWN0b3IuREFUQV9UT0dHTEUpO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRhYlRvZ2dsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIGVsZW0gPSB0YWJUb2dnbGVzW2ldO1xuICAgICAgICB2YXIgc2VsZWN0b3IgPSBVdGlsLmdldFNlbGVjdG9yRnJvbUVsZW1lbnQoZWxlbSk7XG5cbiAgICAgICAgaWYgKHNlbGVjdG9yICE9PSBudWxsICYmICQkJDEoc2VsZWN0b3IpLmZpbHRlcihlbGVtZW50KS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdGhpcy5fdHJpZ2dlckFycmF5LnB1c2goZWxlbSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5fcGFyZW50ID0gdGhpcy5fY29uZmlnLnBhcmVudCA/IHRoaXMuX2dldFBhcmVudCgpIDogbnVsbDtcblxuICAgICAgaWYgKCF0aGlzLl9jb25maWcucGFyZW50KSB7XG4gICAgICAgIHRoaXMuX2FkZEFyaWFBbmRDb2xsYXBzZWRDbGFzcyh0aGlzLl9lbGVtZW50LCB0aGlzLl90cmlnZ2VyQXJyYXkpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5fY29uZmlnLnRvZ2dsZSkge1xuICAgICAgICB0aGlzLnRvZ2dsZSgpO1xuICAgICAgfVxuICAgIH0gLy8gZ2V0dGVyc1xuXG5cbiAgICB2YXIgX3Byb3RvID0gQ29sbGFwc2UucHJvdG90eXBlO1xuXG4gICAgLy8gcHVibGljXG4gICAgX3Byb3RvLnRvZ2dsZSA9IGZ1bmN0aW9uIHRvZ2dsZSgpIHtcbiAgICAgIGlmICgkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5TSE9XKSkge1xuICAgICAgICB0aGlzLmhpZGUoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuc2hvdygpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8uc2hvdyA9IGZ1bmN0aW9uIHNob3coKSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICBpZiAodGhpcy5faXNUcmFuc2l0aW9uaW5nIHx8ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGFjdGl2ZXM7XG4gICAgICB2YXIgYWN0aXZlc0RhdGE7XG5cbiAgICAgIGlmICh0aGlzLl9wYXJlbnQpIHtcbiAgICAgICAgYWN0aXZlcyA9ICQkJDEubWFrZUFycmF5KCQkJDEodGhpcy5fcGFyZW50KS5jaGlsZHJlbigpLmNoaWxkcmVuKFNlbGVjdG9yLkFDVElWRVMpKTtcblxuICAgICAgICBpZiAoIWFjdGl2ZXMubGVuZ3RoKSB7XG4gICAgICAgICAgYWN0aXZlcyA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYgKGFjdGl2ZXMpIHtcbiAgICAgICAgYWN0aXZlc0RhdGEgPSAkJCQxKGFjdGl2ZXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgIGlmIChhY3RpdmVzRGF0YSAmJiBhY3RpdmVzRGF0YS5faXNUcmFuc2l0aW9uaW5nKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHZhciBzdGFydEV2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TSE9XKTtcbiAgICAgICQkJDEodGhpcy5fZWxlbWVudCkudHJpZ2dlcihzdGFydEV2ZW50KTtcblxuICAgICAgaWYgKHN0YXJ0RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoYWN0aXZlcykge1xuICAgICAgICBDb2xsYXBzZS5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJCQkMShhY3RpdmVzKSwgJ2hpZGUnKTtcblxuICAgICAgICBpZiAoIWFjdGl2ZXNEYXRhKSB7XG4gICAgICAgICAgJCQkMShhY3RpdmVzKS5kYXRhKERBVEFfS0VZLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB2YXIgZGltZW5zaW9uID0gdGhpcy5fZ2V0RGltZW5zaW9uKCk7XG5cbiAgICAgICQkJDEodGhpcy5fZWxlbWVudCkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFKS5hZGRDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0lORyk7XG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSAwO1xuXG4gICAgICBpZiAodGhpcy5fdHJpZ2dlckFycmF5Lmxlbmd0aCkge1xuICAgICAgICAkJCQxKHRoaXMuX3RyaWdnZXJBcnJheSkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFRCkuYXR0cignYXJpYS1leHBhbmRlZCcsIHRydWUpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnNldFRyYW5zaXRpb25pbmcodHJ1ZSk7XG5cbiAgICAgIHZhciBjb21wbGV0ZSA9IGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgICAkJCQxKF90aGlzLl9lbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0lORykuYWRkQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFKS5hZGRDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG4gICAgICAgIF90aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSAnJztcblxuICAgICAgICBfdGhpcy5zZXRUcmFuc2l0aW9uaW5nKGZhbHNlKTtcblxuICAgICAgICAkJCQxKF90aGlzLl9lbGVtZW50KS50cmlnZ2VyKEV2ZW50LlNIT1dOKTtcbiAgICAgIH07XG5cbiAgICAgIGlmICghVXRpbC5zdXBwb3J0c1RyYW5zaXRpb25FbmQoKSkge1xuICAgICAgICBjb21wbGV0ZSgpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBjYXBpdGFsaXplZERpbWVuc2lvbiA9IGRpbWVuc2lvblswXS50b1VwcGVyQ2FzZSgpICsgZGltZW5zaW9uLnNsaWNlKDEpO1xuICAgICAgdmFyIHNjcm9sbFNpemUgPSBcInNjcm9sbFwiICsgY2FwaXRhbGl6ZWREaW1lbnNpb247XG4gICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBjb21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQoVFJBTlNJVElPTl9EVVJBVElPTik7XG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSB0aGlzLl9lbGVtZW50W3Njcm9sbFNpemVdICsgXCJweFwiO1xuICAgIH07XG5cbiAgICBfcHJvdG8uaGlkZSA9IGZ1bmN0aW9uIGhpZGUoKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgaWYgKHRoaXMuX2lzVHJhbnNpdGlvbmluZyB8fCAhJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVykpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgc3RhcnRFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuSElERSk7XG4gICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnRyaWdnZXIoc3RhcnRFdmVudCk7XG5cbiAgICAgIGlmIChzdGFydEV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGRpbWVuc2lvbiA9IHRoaXMuX2dldERpbWVuc2lvbigpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSB0aGlzLl9lbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpW2RpbWVuc2lvbl0gKyBcInB4XCI7XG4gICAgICBVdGlsLnJlZmxvdyh0aGlzLl9lbGVtZW50KTtcbiAgICAgICQkJDEodGhpcy5fZWxlbWVudCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNJTkcpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5DT0xMQVBTRSkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICBpZiAodGhpcy5fdHJpZ2dlckFycmF5Lmxlbmd0aCkge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuX3RyaWdnZXJBcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIHZhciB0cmlnZ2VyID0gdGhpcy5fdHJpZ2dlckFycmF5W2ldO1xuICAgICAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudCh0cmlnZ2VyKTtcblxuICAgICAgICAgIGlmIChzZWxlY3RvciAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyICRlbGVtID0gJCQkMShzZWxlY3Rvcik7XG5cbiAgICAgICAgICAgIGlmICghJGVsZW0uaGFzQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpKSB7XG4gICAgICAgICAgICAgICQkJDEodHJpZ2dlcikuYWRkQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFRCkuYXR0cignYXJpYS1leHBhbmRlZCcsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5zZXRUcmFuc2l0aW9uaW5nKHRydWUpO1xuXG4gICAgICB2YXIgY29tcGxldGUgPSBmdW5jdGlvbiBjb21wbGV0ZSgpIHtcbiAgICAgICAgX3RoaXMyLnNldFRyYW5zaXRpb25pbmcoZmFsc2UpO1xuXG4gICAgICAgICQkJDEoX3RoaXMyLl9lbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuQ09MTEFQU0lORykuYWRkQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFKS50cmlnZ2VyKEV2ZW50LkhJRERFTik7XG4gICAgICB9O1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlW2RpbWVuc2lvbl0gPSAnJztcblxuICAgICAgaWYgKCFVdGlsLnN1cHBvcnRzVHJhbnNpdGlvbkVuZCgpKSB7XG4gICAgICAgIGNvbXBsZXRlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgY29tcGxldGUpLmVtdWxhdGVUcmFuc2l0aW9uRW5kKFRSQU5TSVRJT05fRFVSQVRJT04pO1xuICAgIH07XG5cbiAgICBfcHJvdG8uc2V0VHJhbnNpdGlvbmluZyA9IGZ1bmN0aW9uIHNldFRyYW5zaXRpb25pbmcoaXNUcmFuc2l0aW9uaW5nKSB7XG4gICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSBpc1RyYW5zaXRpb25pbmc7XG4gICAgfTtcblxuICAgIF9wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICB0aGlzLl9jb25maWcgPSBudWxsO1xuICAgICAgdGhpcy5fcGFyZW50ID0gbnVsbDtcbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgdGhpcy5fdHJpZ2dlckFycmF5ID0gbnVsbDtcbiAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IG51bGw7XG4gICAgfTsgLy8gcHJpdmF0ZVxuXG5cbiAgICBfcHJvdG8uX2dldENvbmZpZyA9IGZ1bmN0aW9uIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICBjb25maWcgPSBfZXh0ZW5kcyh7fSwgRGVmYXVsdCwgY29uZmlnKTtcbiAgICAgIGNvbmZpZy50b2dnbGUgPSBCb29sZWFuKGNvbmZpZy50b2dnbGUpOyAvLyBjb2VyY2Ugc3RyaW5nIHZhbHVlc1xuXG4gICAgICBVdGlsLnR5cGVDaGVja0NvbmZpZyhOQU1FLCBjb25maWcsIERlZmF1bHRUeXBlKTtcbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfTtcblxuICAgIF9wcm90by5fZ2V0RGltZW5zaW9uID0gZnVuY3Rpb24gX2dldERpbWVuc2lvbigpIHtcbiAgICAgIHZhciBoYXNXaWR0aCA9ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoRGltZW5zaW9uLldJRFRIKTtcbiAgICAgIHJldHVybiBoYXNXaWR0aCA/IERpbWVuc2lvbi5XSURUSCA6IERpbWVuc2lvbi5IRUlHSFQ7XG4gICAgfTtcblxuICAgIF9wcm90by5fZ2V0UGFyZW50ID0gZnVuY3Rpb24gX2dldFBhcmVudCgpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICB2YXIgcGFyZW50ID0gbnVsbDtcblxuICAgICAgaWYgKFV0aWwuaXNFbGVtZW50KHRoaXMuX2NvbmZpZy5wYXJlbnQpKSB7XG4gICAgICAgIHBhcmVudCA9IHRoaXMuX2NvbmZpZy5wYXJlbnQ7IC8vIGl0J3MgYSBqUXVlcnkgb2JqZWN0XG5cbiAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9jb25maWcucGFyZW50LmpxdWVyeSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBwYXJlbnQgPSB0aGlzLl9jb25maWcucGFyZW50WzBdO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBwYXJlbnQgPSAkJCQxKHRoaXMuX2NvbmZpZy5wYXJlbnQpWzBdO1xuICAgICAgfVxuXG4gICAgICB2YXIgc2VsZWN0b3IgPSBcIltkYXRhLXRvZ2dsZT1cXFwiY29sbGFwc2VcXFwiXVtkYXRhLXBhcmVudD1cXFwiXCIgKyB0aGlzLl9jb25maWcucGFyZW50ICsgXCJcXFwiXVwiO1xuICAgICAgJCQkMShwYXJlbnQpLmZpbmQoc2VsZWN0b3IpLmVhY2goZnVuY3Rpb24gKGksIGVsZW1lbnQpIHtcbiAgICAgICAgX3RoaXMzLl9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3MoQ29sbGFwc2UuX2dldFRhcmdldEZyb21FbGVtZW50KGVsZW1lbnQpLCBbZWxlbWVudF0pO1xuICAgICAgfSk7XG4gICAgICByZXR1cm4gcGFyZW50O1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2FkZEFyaWFBbmRDb2xsYXBzZWRDbGFzcyA9IGZ1bmN0aW9uIF9hZGRBcmlhQW5kQ29sbGFwc2VkQ2xhc3MoZWxlbWVudCwgdHJpZ2dlckFycmF5KSB7XG4gICAgICBpZiAoZWxlbWVudCkge1xuICAgICAgICB2YXIgaXNPcGVuID0gJCQkMShlbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG5cbiAgICAgICAgaWYgKHRyaWdnZXJBcnJheS5sZW5ndGgpIHtcbiAgICAgICAgICAkJCQxKHRyaWdnZXJBcnJheSkudG9nZ2xlQ2xhc3MoQ2xhc3NOYW1lLkNPTExBUFNFRCwgIWlzT3BlbikuYXR0cignYXJpYS1leHBhbmRlZCcsIGlzT3Blbik7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9OyAvLyBzdGF0aWNcblxuXG4gICAgQ29sbGFwc2UuX2dldFRhcmdldEZyb21FbGVtZW50ID0gZnVuY3Rpb24gX2dldFRhcmdldEZyb21FbGVtZW50KGVsZW1lbnQpIHtcbiAgICAgIHZhciBzZWxlY3RvciA9IFV0aWwuZ2V0U2VsZWN0b3JGcm9tRWxlbWVudChlbGVtZW50KTtcbiAgICAgIHJldHVybiBzZWxlY3RvciA/ICQkJDEoc2VsZWN0b3IpWzBdIDogbnVsbDtcbiAgICB9O1xuXG4gICAgQ29sbGFwc2UuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICR0aGlzID0gJCQkMSh0aGlzKTtcbiAgICAgICAgdmFyIGRhdGEgPSAkdGhpcy5kYXRhKERBVEFfS0VZKTtcblxuICAgICAgICB2YXIgX2NvbmZpZyA9IF9leHRlbmRzKHt9LCBEZWZhdWx0LCAkdGhpcy5kYXRhKCksIHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnICYmIGNvbmZpZyk7XG5cbiAgICAgICAgaWYgKCFkYXRhICYmIF9jb25maWcudG9nZ2xlICYmIC9zaG93fGhpZGUvLnRlc3QoY29uZmlnKSkge1xuICAgICAgICAgIF9jb25maWcudG9nZ2xlID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICBkYXRhID0gbmV3IENvbGxhcHNlKHRoaXMsIF9jb25maWcpO1xuICAgICAgICAgICR0aGlzLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgX2NyZWF0ZUNsYXNzKENvbGxhcHNlLCBudWxsLCBbe1xuICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgfVxuICAgIH1dKTtcbiAgICByZXR1cm4gQ29sbGFwc2U7XG4gIH0oKTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cblxuICAkJCQxKGRvY3VtZW50KS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEUsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIC8vIHByZXZlbnREZWZhdWx0IG9ubHkgZm9yIDxhPiBlbGVtZW50cyAod2hpY2ggY2hhbmdlIHRoZSBVUkwpIG5vdCBpbnNpZGUgdGhlIGNvbGxhcHNpYmxlIGVsZW1lbnRcbiAgICBpZiAoZXZlbnQuY3VycmVudFRhcmdldC50YWdOYW1lID09PSAnQScpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuXG4gICAgdmFyICR0cmlnZ2VyID0gJCQkMSh0aGlzKTtcbiAgICB2YXIgc2VsZWN0b3IgPSBVdGlsLmdldFNlbGVjdG9yRnJvbUVsZW1lbnQodGhpcyk7XG4gICAgJCQkMShzZWxlY3RvcikuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJHRhcmdldCA9ICQkJDEodGhpcyk7XG4gICAgICB2YXIgZGF0YSA9ICR0YXJnZXQuZGF0YShEQVRBX0tFWSk7XG4gICAgICB2YXIgY29uZmlnID0gZGF0YSA/ICd0b2dnbGUnIDogJHRyaWdnZXIuZGF0YSgpO1xuXG4gICAgICBDb2xsYXBzZS5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJHRhcmdldCwgY29uZmlnKTtcbiAgICB9KTtcbiAgfSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICAkJCQxLmZuW05BTUVdID0gQ29sbGFwc2UuX2pRdWVyeUludGVyZmFjZTtcbiAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IENvbGxhcHNlO1xuXG4gICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgIHJldHVybiBDb2xsYXBzZS5falF1ZXJ5SW50ZXJmYWNlO1xuICB9O1xuXG4gIHJldHVybiBDb2xsYXBzZTtcbn0oJCk7XG5cbi8qKlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEJvb3RzdHJhcCAodjQuMC4wLWJldGEuMyk6IGRyb3Bkb3duLmpzXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG52YXIgRHJvcGRvd24gPSBmdW5jdGlvbiAoJCQkMSkge1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENvbnN0YW50c1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIHZhciBOQU1FID0gJ2Ryb3Bkb3duJztcbiAgdmFyIFZFUlNJT04gPSAnNC4wLjAtYmV0YS4zJztcbiAgdmFyIERBVEFfS0VZID0gJ2JzLmRyb3Bkb3duJztcbiAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gIHZhciBFU0NBUEVfS0VZQ09ERSA9IDI3OyAvLyBLZXlib2FyZEV2ZW50LndoaWNoIHZhbHVlIGZvciBFc2NhcGUgKEVzYykga2V5XG5cbiAgdmFyIFNQQUNFX0tFWUNPREUgPSAzMjsgLy8gS2V5Ym9hcmRFdmVudC53aGljaCB2YWx1ZSBmb3Igc3BhY2Uga2V5XG5cbiAgdmFyIFRBQl9LRVlDT0RFID0gOTsgLy8gS2V5Ym9hcmRFdmVudC53aGljaCB2YWx1ZSBmb3IgdGFiIGtleVxuXG4gIHZhciBBUlJPV19VUF9LRVlDT0RFID0gMzg7IC8vIEtleWJvYXJkRXZlbnQud2hpY2ggdmFsdWUgZm9yIHVwIGFycm93IGtleVxuXG4gIHZhciBBUlJPV19ET1dOX0tFWUNPREUgPSA0MDsgLy8gS2V5Ym9hcmRFdmVudC53aGljaCB2YWx1ZSBmb3IgZG93biBhcnJvdyBrZXlcblxuICB2YXIgUklHSFRfTU9VU0VfQlVUVE9OX1dISUNIID0gMzsgLy8gTW91c2VFdmVudC53aGljaCB2YWx1ZSBmb3IgdGhlIHJpZ2h0IGJ1dHRvbiAoYXNzdW1pbmcgYSByaWdodC1oYW5kZWQgbW91c2UpXG5cbiAgdmFyIFJFR0VYUF9LRVlET1dOID0gbmV3IFJlZ0V4cChBUlJPV19VUF9LRVlDT0RFICsgXCJ8XCIgKyBBUlJPV19ET1dOX0tFWUNPREUgKyBcInxcIiArIEVTQ0FQRV9LRVlDT0RFKTtcbiAgdmFyIEV2ZW50ID0ge1xuICAgIEhJREU6IFwiaGlkZVwiICsgRVZFTlRfS0VZLFxuICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICBTSE9XTjogXCJzaG93blwiICsgRVZFTlRfS0VZLFxuICAgIENMSUNLOiBcImNsaWNrXCIgKyBFVkVOVF9LRVksXG4gICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSxcbiAgICBLRVlET1dOX0RBVEFfQVBJOiBcImtleWRvd25cIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWSxcbiAgICBLRVlVUF9EQVRBX0FQSTogXCJrZXl1cFwiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gIH07XG4gIHZhciBDbGFzc05hbWUgPSB7XG4gICAgRElTQUJMRUQ6ICdkaXNhYmxlZCcsXG4gICAgU0hPVzogJ3Nob3cnLFxuICAgIERST1BVUDogJ2Ryb3B1cCcsXG4gICAgRFJPUFJJR0hUOiAnZHJvcHJpZ2h0JyxcbiAgICBEUk9QTEVGVDogJ2Ryb3BsZWZ0JyxcbiAgICBNRU5VUklHSFQ6ICdkcm9wZG93bi1tZW51LXJpZ2h0JyxcbiAgICBNRU5VTEVGVDogJ2Ryb3Bkb3duLW1lbnUtbGVmdCcsXG4gICAgUE9TSVRJT05fU1RBVElDOiAncG9zaXRpb24tc3RhdGljJ1xuICB9O1xuICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCJkcm9wZG93blwiXScsXG4gICAgRk9STV9DSElMRDogJy5kcm9wZG93biBmb3JtJyxcbiAgICBNRU5VOiAnLmRyb3Bkb3duLW1lbnUnLFxuICAgIE5BVkJBUl9OQVY6ICcubmF2YmFyLW5hdicsXG4gICAgVklTSUJMRV9JVEVNUzogJy5kcm9wZG93bi1tZW51IC5kcm9wZG93bi1pdGVtOm5vdCguZGlzYWJsZWQpJ1xuICB9O1xuICB2YXIgQXR0YWNobWVudE1hcCA9IHtcbiAgICBUT1A6ICd0b3Atc3RhcnQnLFxuICAgIFRPUEVORDogJ3RvcC1lbmQnLFxuICAgIEJPVFRPTTogJ2JvdHRvbS1zdGFydCcsXG4gICAgQk9UVE9NRU5EOiAnYm90dG9tLWVuZCcsXG4gICAgUklHSFQ6ICdyaWdodC1zdGFydCcsXG4gICAgUklHSFRFTkQ6ICdyaWdodC1lbmQnLFxuICAgIExFRlQ6ICdsZWZ0LXN0YXJ0JyxcbiAgICBMRUZURU5EOiAnbGVmdC1lbmQnXG4gIH07XG4gIHZhciBEZWZhdWx0ID0ge1xuICAgIG9mZnNldDogMCxcbiAgICBmbGlwOiB0cnVlLFxuICAgIGJvdW5kYXJ5OiAnc2Nyb2xsUGFyZW50J1xuICB9O1xuICB2YXIgRGVmYXVsdFR5cGUgPSB7XG4gICAgb2Zmc2V0OiAnKG51bWJlcnxzdHJpbmd8ZnVuY3Rpb24pJyxcbiAgICBmbGlwOiAnYm9vbGVhbicsXG4gICAgYm91bmRhcnk6ICcoc3RyaW5nfGVsZW1lbnQpJ1xuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICB9O1xuXG4gIHZhciBEcm9wZG93biA9XG4gIC8qI19fUFVSRV9fKi9cbiAgZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIERyb3Bkb3duKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgdGhpcy5fZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICB0aGlzLl9wb3BwZXIgPSBudWxsO1xuICAgICAgdGhpcy5fY29uZmlnID0gdGhpcy5fZ2V0Q29uZmlnKGNvbmZpZyk7XG4gICAgICB0aGlzLl9tZW51ID0gdGhpcy5fZ2V0TWVudUVsZW1lbnQoKTtcbiAgICAgIHRoaXMuX2luTmF2YmFyID0gdGhpcy5fZGV0ZWN0TmF2YmFyKCk7XG5cbiAgICAgIHRoaXMuX2FkZEV2ZW50TGlzdGVuZXJzKCk7XG4gICAgfSAvLyBnZXR0ZXJzXG5cblxuICAgIHZhciBfcHJvdG8gPSBEcm9wZG93bi5wcm90b3R5cGU7XG5cbiAgICAvLyBwdWJsaWNcbiAgICBfcHJvdG8udG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKCkge1xuICAgICAgaWYgKHRoaXMuX2VsZW1lbnQuZGlzYWJsZWQgfHwgJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuRElTQUJMRUQpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIHBhcmVudCA9IERyb3Bkb3duLl9nZXRQYXJlbnRGcm9tRWxlbWVudCh0aGlzLl9lbGVtZW50KTtcblxuICAgICAgdmFyIGlzQWN0aXZlID0gJCQkMSh0aGlzLl9tZW51KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG5cbiAgICAgIERyb3Bkb3duLl9jbGVhck1lbnVzKCk7XG5cbiAgICAgIGlmIChpc0FjdGl2ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciByZWxhdGVkVGFyZ2V0ID0ge1xuICAgICAgICByZWxhdGVkVGFyZ2V0OiB0aGlzLl9lbGVtZW50XG4gICAgICB9O1xuICAgICAgdmFyIHNob3dFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuU0hPVywgcmVsYXRlZFRhcmdldCk7XG4gICAgICAkJCQxKHBhcmVudCkudHJpZ2dlcihzaG93RXZlbnQpO1xuXG4gICAgICBpZiAoc2hvd0V2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH0gLy8gRGlzYWJsZSB0b3RhbGx5IFBvcHBlci5qcyBmb3IgRHJvcGRvd24gaW4gTmF2YmFyXG5cblxuICAgICAgaWYgKCF0aGlzLl9pbk5hdmJhcikge1xuICAgICAgICAvKipcbiAgICAgICAgICogQ2hlY2sgZm9yIFBvcHBlciBkZXBlbmRlbmN5XG4gICAgICAgICAqIFBvcHBlciAtIGh0dHBzOi8vcG9wcGVyLmpzLm9yZ1xuICAgICAgICAgKi9cbiAgICAgICAgaWYgKHR5cGVvZiBQb3BwZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCb290c3RyYXAgZHJvcGRvd24gcmVxdWlyZSBQb3BwZXIuanMgKGh0dHBzOi8vcG9wcGVyLmpzLm9yZyknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBlbGVtZW50ID0gdGhpcy5fZWxlbWVudDsgLy8gZm9yIGRyb3B1cCB3aXRoIGFsaWdubWVudCB3ZSB1c2UgdGhlIHBhcmVudCBhcyBwb3BwZXIgY29udGFpbmVyXG5cbiAgICAgICAgaWYgKCQkJDEocGFyZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuRFJPUFVQKSkge1xuICAgICAgICAgIGlmICgkJCQxKHRoaXMuX21lbnUpLmhhc0NsYXNzKENsYXNzTmFtZS5NRU5VTEVGVCkgfHwgJCQkMSh0aGlzLl9tZW51KS5oYXNDbGFzcyhDbGFzc05hbWUuTUVOVVJJR0hUKSkge1xuICAgICAgICAgICAgZWxlbWVudCA9IHBhcmVudDtcbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gSWYgYm91bmRhcnkgaXMgbm90IGBzY3JvbGxQYXJlbnRgLCB0aGVuIHNldCBwb3NpdGlvbiB0byBgc3RhdGljYFxuICAgICAgICAvLyB0byBhbGxvdyB0aGUgbWVudSB0byBcImVzY2FwZVwiIHRoZSBzY3JvbGwgcGFyZW50J3MgYm91bmRhcmllc1xuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vdHdicy9ib290c3RyYXAvaXNzdWVzLzI0MjUxXG5cblxuICAgICAgICBpZiAodGhpcy5fY29uZmlnLmJvdW5kYXJ5ICE9PSAnc2Nyb2xsUGFyZW50Jykge1xuICAgICAgICAgICQkJDEocGFyZW50KS5hZGRDbGFzcyhDbGFzc05hbWUuUE9TSVRJT05fU1RBVElDKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3BvcHBlciA9IG5ldyBQb3BwZXIoZWxlbWVudCwgdGhpcy5fbWVudSwgdGhpcy5fZ2V0UG9wcGVyQ29uZmlnKCkpO1xuICAgICAgfSAvLyBpZiB0aGlzIGlzIGEgdG91Y2gtZW5hYmxlZCBkZXZpY2Ugd2UgYWRkIGV4dHJhXG4gICAgICAvLyBlbXB0eSBtb3VzZW92ZXIgbGlzdGVuZXJzIHRvIHRoZSBib2R5J3MgaW1tZWRpYXRlIGNoaWxkcmVuO1xuICAgICAgLy8gb25seSBuZWVkZWQgYmVjYXVzZSBvZiBicm9rZW4gZXZlbnQgZGVsZWdhdGlvbiBvbiBpT1NcbiAgICAgIC8vIGh0dHBzOi8vd3d3LnF1aXJrc21vZGUub3JnL2Jsb2cvYXJjaGl2ZXMvMjAxNC8wMi9tb3VzZV9ldmVudF9idWIuaHRtbFxuXG5cbiAgICAgIGlmICgnb250b3VjaHN0YXJ0JyBpbiBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgJiYgISQkJDEocGFyZW50KS5jbG9zZXN0KFNlbGVjdG9yLk5BVkJBUl9OQVYpLmxlbmd0aCkge1xuICAgICAgICAkJCQxKCdib2R5JykuY2hpbGRyZW4oKS5vbignbW91c2VvdmVyJywgbnVsbCwgJCQkMS5ub29wKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fZWxlbWVudC5mb2N1cygpO1xuXG4gICAgICB0aGlzLl9lbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsIHRydWUpO1xuXG4gICAgICAkJCQxKHRoaXMuX21lbnUpLnRvZ2dsZUNsYXNzKENsYXNzTmFtZS5TSE9XKTtcbiAgICAgICQkJDEocGFyZW50KS50b2dnbGVDbGFzcyhDbGFzc05hbWUuU0hPVykudHJpZ2dlcigkJCQxLkV2ZW50KEV2ZW50LlNIT1dOLCByZWxhdGVkVGFyZ2V0KSk7XG4gICAgfTtcblxuICAgIF9wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9mZihFVkVOVF9LRVkpO1xuICAgICAgdGhpcy5fZWxlbWVudCA9IG51bGw7XG4gICAgICB0aGlzLl9tZW51ID0gbnVsbDtcblxuICAgICAgaWYgKHRoaXMuX3BvcHBlciAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLl9wb3BwZXIuZGVzdHJveSgpO1xuXG4gICAgICAgIHRoaXMuX3BvcHBlciA9IG51bGw7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoKSB7XG4gICAgICB0aGlzLl9pbk5hdmJhciA9IHRoaXMuX2RldGVjdE5hdmJhcigpO1xuXG4gICAgICBpZiAodGhpcy5fcG9wcGVyICE9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3BvcHBlci5zY2hlZHVsZVVwZGF0ZSgpO1xuICAgICAgfVxuICAgIH07IC8vIHByaXZhdGVcblxuXG4gICAgX3Byb3RvLl9hZGRFdmVudExpc3RlbmVycyA9IGZ1bmN0aW9uIF9hZGRFdmVudExpc3RlbmVycygpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub24oRXZlbnQuQ0xJQ0ssIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgICAgICBfdGhpcy50b2dnbGUoKTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldENvbmZpZyA9IGZ1bmN0aW9uIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICBjb25maWcgPSBfZXh0ZW5kcyh7fSwgdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0LCAkJCQxKHRoaXMuX2VsZW1lbnQpLmRhdGEoKSwgY29uZmlnKTtcbiAgICAgIFV0aWwudHlwZUNoZWNrQ29uZmlnKE5BTUUsIGNvbmZpZywgdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0VHlwZSk7XG4gICAgICByZXR1cm4gY29uZmlnO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldE1lbnVFbGVtZW50ID0gZnVuY3Rpb24gX2dldE1lbnVFbGVtZW50KCkge1xuICAgICAgaWYgKCF0aGlzLl9tZW51KSB7XG4gICAgICAgIHZhciBwYXJlbnQgPSBEcm9wZG93bi5fZ2V0UGFyZW50RnJvbUVsZW1lbnQodGhpcy5fZWxlbWVudCk7XG5cbiAgICAgICAgdGhpcy5fbWVudSA9ICQkJDEocGFyZW50KS5maW5kKFNlbGVjdG9yLk1FTlUpWzBdO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGhpcy5fbWVudTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9nZXRQbGFjZW1lbnQgPSBmdW5jdGlvbiBfZ2V0UGxhY2VtZW50KCkge1xuICAgICAgdmFyICRwYXJlbnREcm9wZG93biA9ICQkJDEodGhpcy5fZWxlbWVudCkucGFyZW50KCk7XG4gICAgICB2YXIgcGxhY2VtZW50ID0gQXR0YWNobWVudE1hcC5CT1RUT007IC8vIEhhbmRsZSBkcm9wdXBcblxuICAgICAgaWYgKCRwYXJlbnREcm9wZG93bi5oYXNDbGFzcyhDbGFzc05hbWUuRFJPUFVQKSkge1xuICAgICAgICBwbGFjZW1lbnQgPSBBdHRhY2htZW50TWFwLlRPUDtcblxuICAgICAgICBpZiAoJCQkMSh0aGlzLl9tZW51KS5oYXNDbGFzcyhDbGFzc05hbWUuTUVOVVJJR0hUKSkge1xuICAgICAgICAgIHBsYWNlbWVudCA9IEF0dGFjaG1lbnRNYXAuVE9QRU5EO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKCRwYXJlbnREcm9wZG93bi5oYXNDbGFzcyhDbGFzc05hbWUuRFJPUFJJR0hUKSkge1xuICAgICAgICBwbGFjZW1lbnQgPSBBdHRhY2htZW50TWFwLlJJR0hUO1xuICAgICAgfSBlbHNlIGlmICgkcGFyZW50RHJvcGRvd24uaGFzQ2xhc3MoQ2xhc3NOYW1lLkRST1BMRUZUKSkge1xuICAgICAgICBwbGFjZW1lbnQgPSBBdHRhY2htZW50TWFwLkxFRlQ7XG4gICAgICB9IGVsc2UgaWYgKCQkJDEodGhpcy5fbWVudSkuaGFzQ2xhc3MoQ2xhc3NOYW1lLk1FTlVSSUdIVCkpIHtcbiAgICAgICAgcGxhY2VtZW50ID0gQXR0YWNobWVudE1hcC5CT1RUT01FTkQ7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwbGFjZW1lbnQ7XG4gICAgfTtcblxuICAgIF9wcm90by5fZGV0ZWN0TmF2YmFyID0gZnVuY3Rpb24gX2RldGVjdE5hdmJhcigpIHtcbiAgICAgIHJldHVybiAkJCQxKHRoaXMuX2VsZW1lbnQpLmNsb3Nlc3QoJy5uYXZiYXInKS5sZW5ndGggPiAwO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldFBvcHBlckNvbmZpZyA9IGZ1bmN0aW9uIF9nZXRQb3BwZXJDb25maWcoKSB7XG4gICAgICB2YXIgX3RoaXMyID0gdGhpcztcblxuICAgICAgdmFyIG9mZnNldENvbmYgPSB7fTtcblxuICAgICAgaWYgKHR5cGVvZiB0aGlzLl9jb25maWcub2Zmc2V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIG9mZnNldENvbmYuZm4gPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICAgIGRhdGEub2Zmc2V0cyA9IF9leHRlbmRzKHt9LCBkYXRhLm9mZnNldHMsIF90aGlzMi5fY29uZmlnLm9mZnNldChkYXRhLm9mZnNldHMpIHx8IHt9KTtcbiAgICAgICAgICByZXR1cm4gZGF0YTtcbiAgICAgICAgfTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9mZnNldENvbmYub2Zmc2V0ID0gdGhpcy5fY29uZmlnLm9mZnNldDtcbiAgICAgIH1cblxuICAgICAgdmFyIHBvcHBlckNvbmZpZyA9IHtcbiAgICAgICAgcGxhY2VtZW50OiB0aGlzLl9nZXRQbGFjZW1lbnQoKSxcbiAgICAgICAgbW9kaWZpZXJzOiB7XG4gICAgICAgICAgb2Zmc2V0OiBvZmZzZXRDb25mLFxuICAgICAgICAgIGZsaXA6IHtcbiAgICAgICAgICAgIGVuYWJsZWQ6IHRoaXMuX2NvbmZpZy5mbGlwXG4gICAgICAgICAgfSxcbiAgICAgICAgICBwcmV2ZW50T3ZlcmZsb3c6IHtcbiAgICAgICAgICAgIGJvdW5kYXJpZXNFbGVtZW50OiB0aGlzLl9jb25maWcuYm91bmRhcnlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH07XG4gICAgICByZXR1cm4gcG9wcGVyQ29uZmlnO1xuICAgIH07IC8vIHN0YXRpY1xuXG5cbiAgICBEcm9wZG93bi5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgdmFyIF9jb25maWcgPSB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyA/IGNvbmZpZyA6IG51bGw7XG5cbiAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgZGF0YSA9IG5ldyBEcm9wZG93bih0aGlzLCBfY29uZmlnKTtcbiAgICAgICAgICAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgRHJvcGRvd24uX2NsZWFyTWVudXMgPSBmdW5jdGlvbiBfY2xlYXJNZW51cyhldmVudCkge1xuICAgICAgaWYgKGV2ZW50ICYmIChldmVudC53aGljaCA9PT0gUklHSFRfTU9VU0VfQlVUVE9OX1dISUNIIHx8IGV2ZW50LnR5cGUgPT09ICdrZXl1cCcgJiYgZXZlbnQud2hpY2ggIT09IFRBQl9LRVlDT0RFKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciB0b2dnbGVzID0gJCQkMS5tYWtlQXJyYXkoJCQkMShTZWxlY3Rvci5EQVRBX1RPR0dMRSkpO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRvZ2dsZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIHBhcmVudCA9IERyb3Bkb3duLl9nZXRQYXJlbnRGcm9tRWxlbWVudCh0b2dnbGVzW2ldKTtcblxuICAgICAgICB2YXIgY29udGV4dCA9ICQkJDEodG9nZ2xlc1tpXSkuZGF0YShEQVRBX0tFWSk7XG4gICAgICAgIHZhciByZWxhdGVkVGFyZ2V0ID0ge1xuICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHRvZ2dsZXNbaV1cbiAgICAgICAgfTtcblxuICAgICAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBkcm9wZG93bk1lbnUgPSBjb250ZXh0Ll9tZW51O1xuXG4gICAgICAgIGlmICghJCQkMShwYXJlbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5TSE9XKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGV2ZW50ICYmIChldmVudC50eXBlID09PSAnY2xpY2snICYmIC9pbnB1dHx0ZXh0YXJlYS9pLnRlc3QoZXZlbnQudGFyZ2V0LnRhZ05hbWUpIHx8IGV2ZW50LnR5cGUgPT09ICdrZXl1cCcgJiYgZXZlbnQud2hpY2ggPT09IFRBQl9LRVlDT0RFKSAmJiAkJCQxLmNvbnRhaW5zKHBhcmVudCwgZXZlbnQudGFyZ2V0KSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGhpZGVFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuSElERSwgcmVsYXRlZFRhcmdldCk7XG4gICAgICAgICQkJDEocGFyZW50KS50cmlnZ2VyKGhpZGVFdmVudCk7XG5cbiAgICAgICAgaWYgKGhpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9IC8vIGlmIHRoaXMgaXMgYSB0b3VjaC1lbmFibGVkIGRldmljZSB3ZSByZW1vdmUgdGhlIGV4dHJhXG4gICAgICAgIC8vIGVtcHR5IG1vdXNlb3ZlciBsaXN0ZW5lcnMgd2UgYWRkZWQgZm9yIGlPUyBzdXBwb3J0XG5cblxuICAgICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgICAgJCQkMSgnYm9keScpLmNoaWxkcmVuKCkub2ZmKCdtb3VzZW92ZXInLCBudWxsLCAkJCQxLm5vb3ApO1xuICAgICAgICB9XG5cbiAgICAgICAgdG9nZ2xlc1tpXS5zZXRBdHRyaWJ1dGUoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcbiAgICAgICAgJCQkMShkcm9wZG93bk1lbnUpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKTtcbiAgICAgICAgJCQkMShwYXJlbnQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XKS50cmlnZ2VyKCQkJDEuRXZlbnQoRXZlbnQuSElEREVOLCByZWxhdGVkVGFyZ2V0KSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIERyb3Bkb3duLl9nZXRQYXJlbnRGcm9tRWxlbWVudCA9IGZ1bmN0aW9uIF9nZXRQYXJlbnRGcm9tRWxlbWVudChlbGVtZW50KSB7XG4gICAgICB2YXIgcGFyZW50O1xuICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KGVsZW1lbnQpO1xuXG4gICAgICBpZiAoc2VsZWN0b3IpIHtcbiAgICAgICAgcGFyZW50ID0gJCQkMShzZWxlY3RvcilbMF07XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBwYXJlbnQgfHwgZWxlbWVudC5wYXJlbnROb2RlO1xuICAgIH07XG5cbiAgICBEcm9wZG93bi5fZGF0YUFwaUtleWRvd25IYW5kbGVyID0gZnVuY3Rpb24gX2RhdGFBcGlLZXlkb3duSGFuZGxlcihldmVudCkge1xuICAgICAgLy8gSWYgbm90IGlucHV0L3RleHRhcmVhOlxuICAgICAgLy8gIC0gQW5kIG5vdCBhIGtleSBpbiBSRUdFWFBfS0VZRE9XTiA9PiBub3QgYSBkcm9wZG93biBjb21tYW5kXG4gICAgICAvLyBJZiBpbnB1dC90ZXh0YXJlYTpcbiAgICAgIC8vICAtIElmIHNwYWNlIGtleSA9PiBub3QgYSBkcm9wZG93biBjb21tYW5kXG4gICAgICAvLyAgLSBJZiBrZXkgaXMgb3RoZXIgdGhhbiBlc2NhcGVcbiAgICAgIC8vICAgIC0gSWYga2V5IGlzIG5vdCB1cCBvciBkb3duID0+IG5vdCBhIGRyb3Bkb3duIGNvbW1hbmRcbiAgICAgIC8vICAgIC0gSWYgdHJpZ2dlciBpbnNpZGUgdGhlIG1lbnUgPT4gbm90IGEgZHJvcGRvd24gY29tbWFuZFxuICAgICAgaWYgKC9pbnB1dHx0ZXh0YXJlYS9pLnRlc3QoZXZlbnQudGFyZ2V0LnRhZ05hbWUpID8gZXZlbnQud2hpY2ggPT09IFNQQUNFX0tFWUNPREUgfHwgZXZlbnQud2hpY2ggIT09IEVTQ0FQRV9LRVlDT0RFICYmIChldmVudC53aGljaCAhPT0gQVJST1dfRE9XTl9LRVlDT0RFICYmIGV2ZW50LndoaWNoICE9PSBBUlJPV19VUF9LRVlDT0RFIHx8ICQkJDEoZXZlbnQudGFyZ2V0KS5jbG9zZXN0KFNlbGVjdG9yLk1FTlUpLmxlbmd0aCkgOiAhUkVHRVhQX0tFWURPV04udGVzdChldmVudC53aGljaCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIGlmICh0aGlzLmRpc2FibGVkIHx8ICQkJDEodGhpcykuaGFzQ2xhc3MoQ2xhc3NOYW1lLkRJU0FCTEVEKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBwYXJlbnQgPSBEcm9wZG93bi5fZ2V0UGFyZW50RnJvbUVsZW1lbnQodGhpcyk7XG5cbiAgICAgIHZhciBpc0FjdGl2ZSA9ICQkJDEocGFyZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG5cbiAgICAgIGlmICghaXNBY3RpdmUgJiYgKGV2ZW50LndoaWNoICE9PSBFU0NBUEVfS0VZQ09ERSB8fCBldmVudC53aGljaCAhPT0gU1BBQ0VfS0VZQ09ERSkgfHwgaXNBY3RpdmUgJiYgKGV2ZW50LndoaWNoID09PSBFU0NBUEVfS0VZQ09ERSB8fCBldmVudC53aGljaCA9PT0gU1BBQ0VfS0VZQ09ERSkpIHtcbiAgICAgICAgaWYgKGV2ZW50LndoaWNoID09PSBFU0NBUEVfS0VZQ09ERSkge1xuICAgICAgICAgIHZhciB0b2dnbGUgPSAkJCQxKHBhcmVudCkuZmluZChTZWxlY3Rvci5EQVRBX1RPR0dMRSlbMF07XG4gICAgICAgICAgJCQkMSh0b2dnbGUpLnRyaWdnZXIoJ2ZvY3VzJyk7XG4gICAgICAgIH1cblxuICAgICAgICAkJCQxKHRoaXMpLnRyaWdnZXIoJ2NsaWNrJyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGl0ZW1zID0gJCQkMShwYXJlbnQpLmZpbmQoU2VsZWN0b3IuVklTSUJMRV9JVEVNUykuZ2V0KCk7XG5cbiAgICAgIGlmICghaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGluZGV4ID0gaXRlbXMuaW5kZXhPZihldmVudC50YXJnZXQpO1xuXG4gICAgICBpZiAoZXZlbnQud2hpY2ggPT09IEFSUk9XX1VQX0tFWUNPREUgJiYgaW5kZXggPiAwKSB7XG4gICAgICAgIC8vIHVwXG4gICAgICAgIGluZGV4LS07XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudC53aGljaCA9PT0gQVJST1dfRE9XTl9LRVlDT0RFICYmIGluZGV4IDwgaXRlbXMubGVuZ3RoIC0gMSkge1xuICAgICAgICAvLyBkb3duXG4gICAgICAgIGluZGV4Kys7XG4gICAgICB9XG5cbiAgICAgIGlmIChpbmRleCA8IDApIHtcbiAgICAgICAgaW5kZXggPSAwO1xuICAgICAgfVxuXG4gICAgICBpdGVtc1tpbmRleF0uZm9jdXMoKTtcbiAgICB9O1xuXG4gICAgX2NyZWF0ZUNsYXNzKERyb3Bkb3duLCBudWxsLCBbe1xuICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJEZWZhdWx0VHlwZVwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBEZWZhdWx0VHlwZTtcbiAgICAgIH1cbiAgICB9XSk7XG4gICAgcmV0dXJuIERyb3Bkb3duO1xuICB9KCk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG5cbiAgJCQkMShkb2N1bWVudCkub24oRXZlbnQuS0VZRE9XTl9EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEUsIERyb3Bkb3duLl9kYXRhQXBpS2V5ZG93bkhhbmRsZXIpLm9uKEV2ZW50LktFWURPV05fREFUQV9BUEksIFNlbGVjdG9yLk1FTlUsIERyb3Bkb3duLl9kYXRhQXBpS2V5ZG93bkhhbmRsZXIpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJICsgXCIgXCIgKyBFdmVudC5LRVlVUF9EQVRBX0FQSSwgRHJvcGRvd24uX2NsZWFyTWVudXMpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIERyb3Bkb3duLl9qUXVlcnlJbnRlcmZhY2UuY2FsbCgkJCQxKHRoaXMpLCAndG9nZ2xlJyk7XG4gIH0pLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5GT1JNX0NISUxELCBmdW5jdGlvbiAoZSkge1xuICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gIH0pO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIGpRdWVyeVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgJCQkMS5mbltOQU1FXSA9IERyb3Bkb3duLl9qUXVlcnlJbnRlcmZhY2U7XG4gICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBEcm9wZG93bjtcblxuICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICByZXR1cm4gRHJvcGRvd24uX2pRdWVyeUludGVyZmFjZTtcbiAgfTtcblxuICByZXR1cm4gRHJvcGRvd247XG59KCQsIFBvcHBlcik7XG5cbi8qKlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEJvb3RzdHJhcCAodjQuMC4wLWJldGEuMyk6IG1vZGFsLmpzXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG52YXIgTW9kYWwgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENvbnN0YW50c1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIHZhciBOQU1FID0gJ21vZGFsJztcbiAgdmFyIFZFUlNJT04gPSAnNC4wLjAtYmV0YS4zJztcbiAgdmFyIERBVEFfS0VZID0gJ2JzLm1vZGFsJztcbiAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gIHZhciBUUkFOU0lUSU9OX0RVUkFUSU9OID0gMzAwO1xuICB2YXIgQkFDS0RST1BfVFJBTlNJVElPTl9EVVJBVElPTiA9IDE1MDtcbiAgdmFyIEVTQ0FQRV9LRVlDT0RFID0gMjc7IC8vIEtleWJvYXJkRXZlbnQud2hpY2ggdmFsdWUgZm9yIEVzY2FwZSAoRXNjKSBrZXlcblxuICB2YXIgRGVmYXVsdCA9IHtcbiAgICBiYWNrZHJvcDogdHJ1ZSxcbiAgICBrZXlib2FyZDogdHJ1ZSxcbiAgICBmb2N1czogdHJ1ZSxcbiAgICBzaG93OiB0cnVlXG4gIH07XG4gIHZhciBEZWZhdWx0VHlwZSA9IHtcbiAgICBiYWNrZHJvcDogJyhib29sZWFufHN0cmluZyknLFxuICAgIGtleWJvYXJkOiAnYm9vbGVhbicsXG4gICAgZm9jdXM6ICdib29sZWFuJyxcbiAgICBzaG93OiAnYm9vbGVhbidcbiAgfTtcbiAgdmFyIEV2ZW50ID0ge1xuICAgIEhJREU6IFwiaGlkZVwiICsgRVZFTlRfS0VZLFxuICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICBTSE9XTjogXCJzaG93blwiICsgRVZFTlRfS0VZLFxuICAgIEZPQ1VTSU46IFwiZm9jdXNpblwiICsgRVZFTlRfS0VZLFxuICAgIFJFU0laRTogXCJyZXNpemVcIiArIEVWRU5UX0tFWSxcbiAgICBDTElDS19ESVNNSVNTOiBcImNsaWNrLmRpc21pc3NcIiArIEVWRU5UX0tFWSxcbiAgICBLRVlET1dOX0RJU01JU1M6IFwia2V5ZG93bi5kaXNtaXNzXCIgKyBFVkVOVF9LRVksXG4gICAgTU9VU0VVUF9ESVNNSVNTOiBcIm1vdXNldXAuZGlzbWlzc1wiICsgRVZFTlRfS0VZLFxuICAgIE1PVVNFRE9XTl9ESVNNSVNTOiBcIm1vdXNlZG93bi5kaXNtaXNzXCIgKyBFVkVOVF9LRVksXG4gICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWVxuICB9O1xuICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgIFNDUk9MTEJBUl9NRUFTVVJFUjogJ21vZGFsLXNjcm9sbGJhci1tZWFzdXJlJyxcbiAgICBCQUNLRFJPUDogJ21vZGFsLWJhY2tkcm9wJyxcbiAgICBPUEVOOiAnbW9kYWwtb3BlbicsXG4gICAgRkFERTogJ2ZhZGUnLFxuICAgIFNIT1c6ICdzaG93J1xuICB9O1xuICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgRElBTE9HOiAnLm1vZGFsLWRpYWxvZycsXG4gICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCJtb2RhbFwiXScsXG4gICAgREFUQV9ESVNNSVNTOiAnW2RhdGEtZGlzbWlzcz1cIm1vZGFsXCJdJyxcbiAgICBGSVhFRF9DT05URU5UOiAnLmZpeGVkLXRvcCwgLmZpeGVkLWJvdHRvbSwgLmlzLWZpeGVkLCAuc3RpY2t5LXRvcCcsXG4gICAgU1RJQ0tZX0NPTlRFTlQ6ICcuc3RpY2t5LXRvcCcsXG4gICAgTkFWQkFSX1RPR0dMRVI6ICcubmF2YmFyLXRvZ2dsZXInXG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gIH07XG5cbiAgdmFyIE1vZGFsID1cbiAgLyojX19QVVJFX18qL1xuICBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gTW9kYWwoZWxlbWVudCwgY29uZmlnKSB7XG4gICAgICB0aGlzLl9jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgdGhpcy5fZGlhbG9nID0gJCQkMShlbGVtZW50KS5maW5kKFNlbGVjdG9yLkRJQUxPRylbMF07XG4gICAgICB0aGlzLl9iYWNrZHJvcCA9IG51bGw7XG4gICAgICB0aGlzLl9pc1Nob3duID0gZmFsc2U7XG4gICAgICB0aGlzLl9pc0JvZHlPdmVyZmxvd2luZyA9IGZhbHNlO1xuICAgICAgdGhpcy5faWdub3JlQmFja2Ryb3BDbGljayA9IGZhbHNlO1xuICAgICAgdGhpcy5fb3JpZ2luYWxCb2R5UGFkZGluZyA9IDA7XG4gICAgICB0aGlzLl9zY3JvbGxiYXJXaWR0aCA9IDA7XG4gICAgfSAvLyBnZXR0ZXJzXG5cblxuICAgIHZhciBfcHJvdG8gPSBNb2RhbC5wcm90b3R5cGU7XG5cbiAgICAvLyBwdWJsaWNcbiAgICBfcHJvdG8udG9nZ2xlID0gZnVuY3Rpb24gdG9nZ2xlKHJlbGF0ZWRUYXJnZXQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9pc1Nob3duID8gdGhpcy5oaWRlKCkgOiB0aGlzLnNob3cocmVsYXRlZFRhcmdldCk7XG4gICAgfTtcblxuICAgIF9wcm90by5zaG93ID0gZnVuY3Rpb24gc2hvdyhyZWxhdGVkVGFyZ2V0KSB7XG4gICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgICBpZiAodGhpcy5faXNUcmFuc2l0aW9uaW5nIHx8IHRoaXMuX2lzU2hvd24pIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoVXRpbC5zdXBwb3J0c1RyYW5zaXRpb25FbmQoKSAmJiAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKSkge1xuICAgICAgICB0aGlzLl9pc1RyYW5zaXRpb25pbmcgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgc2hvd0V2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TSE9XLCB7XG4gICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHJlbGF0ZWRUYXJnZXRcbiAgICAgIH0pO1xuICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50cmlnZ2VyKHNob3dFdmVudCk7XG5cbiAgICAgIGlmICh0aGlzLl9pc1Nob3duIHx8IHNob3dFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2lzU2hvd24gPSB0cnVlO1xuXG4gICAgICB0aGlzLl9jaGVja1Njcm9sbGJhcigpO1xuXG4gICAgICB0aGlzLl9zZXRTY3JvbGxiYXIoKTtcblxuICAgICAgdGhpcy5fYWRqdXN0RGlhbG9nKCk7XG5cbiAgICAgICQkJDEoZG9jdW1lbnQuYm9keSkuYWRkQ2xhc3MoQ2xhc3NOYW1lLk9QRU4pO1xuXG4gICAgICB0aGlzLl9zZXRFc2NhcGVFdmVudCgpO1xuXG4gICAgICB0aGlzLl9zZXRSZXNpemVFdmVudCgpO1xuXG4gICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uKEV2ZW50LkNMSUNLX0RJU01JU1MsIFNlbGVjdG9yLkRBVEFfRElTTUlTUywgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgIHJldHVybiBfdGhpcy5oaWRlKGV2ZW50KTtcbiAgICAgIH0pO1xuICAgICAgJCQkMSh0aGlzLl9kaWFsb2cpLm9uKEV2ZW50Lk1PVVNFRE9XTl9ESVNNSVNTLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICQkJDEoX3RoaXMuX2VsZW1lbnQpLm9uZShFdmVudC5NT1VTRVVQX0RJU01JU1MsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgIGlmICgkJCQxKGV2ZW50LnRhcmdldCkuaXMoX3RoaXMuX2VsZW1lbnQpKSB7XG4gICAgICAgICAgICBfdGhpcy5faWdub3JlQmFja2Ryb3BDbGljayA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLl9zaG93QmFja2Ryb3AoZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX3RoaXMuX3Nob3dFbGVtZW50KHJlbGF0ZWRUYXJnZXQpO1xuICAgICAgfSk7XG4gICAgfTtcblxuICAgIF9wcm90by5oaWRlID0gZnVuY3Rpb24gaGlkZShldmVudCkge1xuICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgIGlmIChldmVudCkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuXG4gICAgICBpZiAodGhpcy5faXNUcmFuc2l0aW9uaW5nIHx8ICF0aGlzLl9pc1Nob3duKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGhpZGVFdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuSElERSk7XG4gICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLnRyaWdnZXIoaGlkZUV2ZW50KTtcblxuICAgICAgaWYgKCF0aGlzLl9pc1Nob3duIHx8IGhpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX2lzU2hvd24gPSBmYWxzZTtcbiAgICAgIHZhciB0cmFuc2l0aW9uID0gVXRpbC5zdXBwb3J0c1RyYW5zaXRpb25FbmQoKSAmJiAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKTtcblxuICAgICAgaWYgKHRyYW5zaXRpb24pIHtcbiAgICAgICAgdGhpcy5faXNUcmFuc2l0aW9uaW5nID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fc2V0RXNjYXBlRXZlbnQoKTtcblxuICAgICAgdGhpcy5fc2V0UmVzaXplRXZlbnQoKTtcblxuICAgICAgJCQkMShkb2N1bWVudCkub2ZmKEV2ZW50LkZPQ1VTSU4pO1xuICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuU0hPVyk7XG4gICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9mZihFdmVudC5DTElDS19ESVNNSVNTKTtcbiAgICAgICQkJDEodGhpcy5fZGlhbG9nKS5vZmYoRXZlbnQuTU9VU0VET1dOX0RJU01JU1MpO1xuXG4gICAgICBpZiAodHJhbnNpdGlvbikge1xuICAgICAgICAkJCQxKHRoaXMuX2VsZW1lbnQpLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICByZXR1cm4gX3RoaXMyLl9oaWRlTW9kYWwoZXZlbnQpO1xuICAgICAgICB9KS5lbXVsYXRlVHJhbnNpdGlvbkVuZChUUkFOU0lUSU9OX0RVUkFUSU9OKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX2hpZGVNb2RhbCgpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAkJCQxLnJlbW92ZURhdGEodGhpcy5fZWxlbWVudCwgREFUQV9LRVkpO1xuICAgICAgJCQkMSh3aW5kb3csIGRvY3VtZW50LCB0aGlzLl9lbGVtZW50LCB0aGlzLl9iYWNrZHJvcCkub2ZmKEVWRU5UX0tFWSk7XG4gICAgICB0aGlzLl9jb25maWcgPSBudWxsO1xuICAgICAgdGhpcy5fZWxlbWVudCA9IG51bGw7XG4gICAgICB0aGlzLl9kaWFsb2cgPSBudWxsO1xuICAgICAgdGhpcy5fYmFja2Ryb3AgPSBudWxsO1xuICAgICAgdGhpcy5faXNTaG93biA9IG51bGw7XG4gICAgICB0aGlzLl9pc0JvZHlPdmVyZmxvd2luZyA9IG51bGw7XG4gICAgICB0aGlzLl9pZ25vcmVCYWNrZHJvcENsaWNrID0gbnVsbDtcbiAgICAgIHRoaXMuX3Njcm9sbGJhcldpZHRoID0gbnVsbDtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmhhbmRsZVVwZGF0ZSA9IGZ1bmN0aW9uIGhhbmRsZVVwZGF0ZSgpIHtcbiAgICAgIHRoaXMuX2FkanVzdERpYWxvZygpO1xuICAgIH07IC8vIHByaXZhdGVcblxuXG4gICAgX3Byb3RvLl9nZXRDb25maWcgPSBmdW5jdGlvbiBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgY29uZmlnID0gX2V4dGVuZHMoe30sIERlZmF1bHQsIGNvbmZpZyk7XG4gICAgICBVdGlsLnR5cGVDaGVja0NvbmZpZyhOQU1FLCBjb25maWcsIERlZmF1bHRUeXBlKTtcbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfTtcblxuICAgIF9wcm90by5fc2hvd0VsZW1lbnQgPSBmdW5jdGlvbiBfc2hvd0VsZW1lbnQocmVsYXRlZFRhcmdldCkge1xuICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgIHZhciB0cmFuc2l0aW9uID0gVXRpbC5zdXBwb3J0c1RyYW5zaXRpb25FbmQoKSAmJiAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKTtcblxuICAgICAgaWYgKCF0aGlzLl9lbGVtZW50LnBhcmVudE5vZGUgfHwgdGhpcy5fZWxlbWVudC5wYXJlbnROb2RlLm5vZGVUeXBlICE9PSBOb2RlLkVMRU1FTlRfTk9ERSkge1xuICAgICAgICAvLyBkb24ndCBtb3ZlIG1vZGFscyBkb20gcG9zaXRpb25cbiAgICAgICAgZG9jdW1lbnQuYm9keS5hcHBlbmRDaGlsZCh0aGlzLl9lbGVtZW50KTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gJ2Jsb2NrJztcblxuICAgICAgdGhpcy5fZWxlbWVudC5yZW1vdmVBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJyk7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuc2Nyb2xsVG9wID0gMDtcblxuICAgICAgaWYgKHRyYW5zaXRpb24pIHtcbiAgICAgICAgVXRpbC5yZWZsb3codGhpcy5fZWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgICQkJDEodGhpcy5fZWxlbWVudCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICBpZiAodGhpcy5fY29uZmlnLmZvY3VzKSB7XG4gICAgICAgIHRoaXMuX2VuZm9yY2VGb2N1cygpO1xuICAgICAgfVxuXG4gICAgICB2YXIgc2hvd25FdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuU0hPV04sIHtcbiAgICAgICAgcmVsYXRlZFRhcmdldDogcmVsYXRlZFRhcmdldFxuICAgICAgfSk7XG5cbiAgICAgIHZhciB0cmFuc2l0aW9uQ29tcGxldGUgPSBmdW5jdGlvbiB0cmFuc2l0aW9uQ29tcGxldGUoKSB7XG4gICAgICAgIGlmIChfdGhpczMuX2NvbmZpZy5mb2N1cykge1xuICAgICAgICAgIF90aGlzMy5fZWxlbWVudC5mb2N1cygpO1xuICAgICAgICB9XG5cbiAgICAgICAgX3RoaXMzLl9pc1RyYW5zaXRpb25pbmcgPSBmYWxzZTtcbiAgICAgICAgJCQkMShfdGhpczMuX2VsZW1lbnQpLnRyaWdnZXIoc2hvd25FdmVudCk7XG4gICAgICB9O1xuXG4gICAgICBpZiAodHJhbnNpdGlvbikge1xuICAgICAgICAkJCQxKHRoaXMuX2RpYWxvZykub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIHRyYW5zaXRpb25Db21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQoVFJBTlNJVElPTl9EVVJBVElPTik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0cmFuc2l0aW9uQ29tcGxldGUoKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9lbmZvcmNlRm9jdXMgPSBmdW5jdGlvbiBfZW5mb3JjZUZvY3VzKCkge1xuICAgICAgdmFyIF90aGlzNCA9IHRoaXM7XG5cbiAgICAgICQkJDEoZG9jdW1lbnQpLm9mZihFdmVudC5GT0NVU0lOKSAvLyBndWFyZCBhZ2FpbnN0IGluZmluaXRlIGZvY3VzIGxvb3BcbiAgICAgIC5vbihFdmVudC5GT0NVU0lOLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgaWYgKGRvY3VtZW50ICE9PSBldmVudC50YXJnZXQgJiYgX3RoaXM0Ll9lbGVtZW50ICE9PSBldmVudC50YXJnZXQgJiYgISQkJDEoX3RoaXM0Ll9lbGVtZW50KS5oYXMoZXZlbnQudGFyZ2V0KS5sZW5ndGgpIHtcbiAgICAgICAgICBfdGhpczQuX2VsZW1lbnQuZm9jdXMoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIF9wcm90by5fc2V0RXNjYXBlRXZlbnQgPSBmdW5jdGlvbiBfc2V0RXNjYXBlRXZlbnQoKSB7XG4gICAgICB2YXIgX3RoaXM1ID0gdGhpcztcblxuICAgICAgaWYgKHRoaXMuX2lzU2hvd24gJiYgdGhpcy5fY29uZmlnLmtleWJvYXJkKSB7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub24oRXZlbnQuS0VZRE9XTl9ESVNNSVNTLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICBpZiAoZXZlbnQud2hpY2ggPT09IEVTQ0FQRV9LRVlDT0RFKSB7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICBfdGhpczUuaGlkZSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2UgaWYgKCF0aGlzLl9pc1Nob3duKSB7XG4gICAgICAgICQkJDEodGhpcy5fZWxlbWVudCkub2ZmKEV2ZW50LktFWURPV05fRElTTUlTUyk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by5fc2V0UmVzaXplRXZlbnQgPSBmdW5jdGlvbiBfc2V0UmVzaXplRXZlbnQoKSB7XG4gICAgICB2YXIgX3RoaXM2ID0gdGhpcztcblxuICAgICAgaWYgKHRoaXMuX2lzU2hvd24pIHtcbiAgICAgICAgJCQkMSh3aW5kb3cpLm9uKEV2ZW50LlJFU0laRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgcmV0dXJuIF90aGlzNi5oYW5kbGVVcGRhdGUoZXZlbnQpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgICQkJDEod2luZG93KS5vZmYoRXZlbnQuUkVTSVpFKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9oaWRlTW9kYWwgPSBmdW5jdGlvbiBfaGlkZU1vZGFsKCkge1xuICAgICAgdmFyIF90aGlzNyA9IHRoaXM7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUuZGlzcGxheSA9ICdub25lJztcblxuICAgICAgdGhpcy5fZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2FyaWEtaGlkZGVuJywgdHJ1ZSk7XG5cbiAgICAgIHRoaXMuX2lzVHJhbnNpdGlvbmluZyA9IGZhbHNlO1xuXG4gICAgICB0aGlzLl9zaG93QmFja2Ryb3AoZnVuY3Rpb24gKCkge1xuICAgICAgICAkJCQxKGRvY3VtZW50LmJvZHkpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5PUEVOKTtcblxuICAgICAgICBfdGhpczcuX3Jlc2V0QWRqdXN0bWVudHMoKTtcblxuICAgICAgICBfdGhpczcuX3Jlc2V0U2Nyb2xsYmFyKCk7XG5cbiAgICAgICAgJCQkMShfdGhpczcuX2VsZW1lbnQpLnRyaWdnZXIoRXZlbnQuSElEREVOKTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX3JlbW92ZUJhY2tkcm9wID0gZnVuY3Rpb24gX3JlbW92ZUJhY2tkcm9wKCkge1xuICAgICAgaWYgKHRoaXMuX2JhY2tkcm9wKSB7XG4gICAgICAgICQkJDEodGhpcy5fYmFja2Ryb3ApLnJlbW92ZSgpO1xuICAgICAgICB0aGlzLl9iYWNrZHJvcCA9IG51bGw7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by5fc2hvd0JhY2tkcm9wID0gZnVuY3Rpb24gX3Nob3dCYWNrZHJvcChjYWxsYmFjaykge1xuICAgICAgdmFyIF90aGlzOCA9IHRoaXM7XG5cbiAgICAgIHZhciBhbmltYXRlID0gJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuRkFERSkgPyBDbGFzc05hbWUuRkFERSA6ICcnO1xuXG4gICAgICBpZiAodGhpcy5faXNTaG93biAmJiB0aGlzLl9jb25maWcuYmFja2Ryb3ApIHtcbiAgICAgICAgdmFyIGRvQW5pbWF0ZSA9IFV0aWwuc3VwcG9ydHNUcmFuc2l0aW9uRW5kKCkgJiYgYW5pbWF0ZTtcbiAgICAgICAgdGhpcy5fYmFja2Ryb3AgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgdGhpcy5fYmFja2Ryb3AuY2xhc3NOYW1lID0gQ2xhc3NOYW1lLkJBQ0tEUk9QO1xuXG4gICAgICAgIGlmIChhbmltYXRlKSB7XG4gICAgICAgICAgJCQkMSh0aGlzLl9iYWNrZHJvcCkuYWRkQ2xhc3MoYW5pbWF0ZSk7XG4gICAgICAgIH1cblxuICAgICAgICAkJCQxKHRoaXMuX2JhY2tkcm9wKS5hcHBlbmRUbyhkb2N1bWVudC5ib2R5KTtcbiAgICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS5vbihFdmVudC5DTElDS19ESVNNSVNTLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICBpZiAoX3RoaXM4Ll9pZ25vcmVCYWNrZHJvcENsaWNrKSB7XG4gICAgICAgICAgICBfdGhpczguX2lnbm9yZUJhY2tkcm9wQ2xpY2sgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoZXZlbnQudGFyZ2V0ICE9PSBldmVudC5jdXJyZW50VGFyZ2V0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKF90aGlzOC5fY29uZmlnLmJhY2tkcm9wID09PSAnc3RhdGljJykge1xuICAgICAgICAgICAgX3RoaXM4Ll9lbGVtZW50LmZvY3VzKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIF90aGlzOC5oaWRlKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICBpZiAoZG9BbmltYXRlKSB7XG4gICAgICAgICAgVXRpbC5yZWZsb3codGhpcy5fYmFja2Ryb3ApO1xuICAgICAgICB9XG5cbiAgICAgICAgJCQkMSh0aGlzLl9iYWNrZHJvcCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWRvQW5pbWF0ZSkge1xuICAgICAgICAgIGNhbGxiYWNrKCk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgJCQkMSh0aGlzLl9iYWNrZHJvcCkub25lKFV0aWwuVFJBTlNJVElPTl9FTkQsIGNhbGxiYWNrKS5lbXVsYXRlVHJhbnNpdGlvbkVuZChCQUNLRFJPUF9UUkFOU0lUSU9OX0RVUkFUSU9OKTtcbiAgICAgIH0gZWxzZSBpZiAoIXRoaXMuX2lzU2hvd24gJiYgdGhpcy5fYmFja2Ryb3ApIHtcbiAgICAgICAgJCQkMSh0aGlzLl9iYWNrZHJvcCkucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICAgIHZhciBjYWxsYmFja1JlbW92ZSA9IGZ1bmN0aW9uIGNhbGxiYWNrUmVtb3ZlKCkge1xuICAgICAgICAgIF90aGlzOC5fcmVtb3ZlQmFja2Ryb3AoKTtcblxuICAgICAgICAgIGlmIChjYWxsYmFjaykge1xuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKFV0aWwuc3VwcG9ydHNUcmFuc2l0aW9uRW5kKCkgJiYgJCQkMSh0aGlzLl9lbGVtZW50KS5oYXNDbGFzcyhDbGFzc05hbWUuRkFERSkpIHtcbiAgICAgICAgICAkJCQxKHRoaXMuX2JhY2tkcm9wKS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgY2FsbGJhY2tSZW1vdmUpLmVtdWxhdGVUcmFuc2l0aW9uRW5kKEJBQ0tEUk9QX1RSQU5TSVRJT05fRFVSQVRJT04pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhbGxiYWNrUmVtb3ZlKCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgIH1cbiAgICB9OyAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgLy8gdGhlIGZvbGxvd2luZyBtZXRob2RzIGFyZSB1c2VkIHRvIGhhbmRsZSBvdmVyZmxvd2luZyBtb2RhbHNcbiAgICAvLyB0b2RvIChmYXQpOiB0aGVzZSBzaG91bGQgcHJvYmFibHkgYmUgcmVmYWN0b3JlZCBvdXQgb2YgbW9kYWwuanNcbiAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cblxuICAgIF9wcm90by5fYWRqdXN0RGlhbG9nID0gZnVuY3Rpb24gX2FkanVzdERpYWxvZygpIHtcbiAgICAgIHZhciBpc01vZGFsT3ZlcmZsb3dpbmcgPSB0aGlzLl9lbGVtZW50LnNjcm9sbEhlaWdodCA+IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5jbGllbnRIZWlnaHQ7XG5cbiAgICAgIGlmICghdGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcgJiYgaXNNb2RhbE92ZXJmbG93aW5nKSB7XG4gICAgICAgIHRoaXMuX2VsZW1lbnQuc3R5bGUucGFkZGluZ0xlZnQgPSB0aGlzLl9zY3JvbGxiYXJXaWR0aCArIFwicHhcIjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2lzQm9keU92ZXJmbG93aW5nICYmICFpc01vZGFsT3ZlcmZsb3dpbmcpIHtcbiAgICAgICAgdGhpcy5fZWxlbWVudC5zdHlsZS5wYWRkaW5nUmlnaHQgPSB0aGlzLl9zY3JvbGxiYXJXaWR0aCArIFwicHhcIjtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9yZXNldEFkanVzdG1lbnRzID0gZnVuY3Rpb24gX3Jlc2V0QWRqdXN0bWVudHMoKSB7XG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLnBhZGRpbmdMZWZ0ID0gJyc7XG4gICAgICB0aGlzLl9lbGVtZW50LnN0eWxlLnBhZGRpbmdSaWdodCA9ICcnO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2NoZWNrU2Nyb2xsYmFyID0gZnVuY3Rpb24gX2NoZWNrU2Nyb2xsYmFyKCkge1xuICAgICAgdmFyIHJlY3QgPSBkb2N1bWVudC5ib2R5LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgdGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcgPSByZWN0LmxlZnQgKyByZWN0LnJpZ2h0IDwgd2luZG93LmlubmVyV2lkdGg7XG4gICAgICB0aGlzLl9zY3JvbGxiYXJXaWR0aCA9IHRoaXMuX2dldFNjcm9sbGJhcldpZHRoKCk7XG4gICAgfTtcblxuICAgIF9wcm90by5fc2V0U2Nyb2xsYmFyID0gZnVuY3Rpb24gX3NldFNjcm9sbGJhcigpIHtcbiAgICAgIHZhciBfdGhpczkgPSB0aGlzO1xuXG4gICAgICBpZiAodGhpcy5faXNCb2R5T3ZlcmZsb3dpbmcpIHtcbiAgICAgICAgLy8gTm90ZTogRE9NTm9kZS5zdHlsZS5wYWRkaW5nUmlnaHQgcmV0dXJucyB0aGUgYWN0dWFsIHZhbHVlIG9yICcnIGlmIG5vdCBzZXRcbiAgICAgICAgLy8gICB3aGlsZSAkKERPTU5vZGUpLmNzcygncGFkZGluZy1yaWdodCcpIHJldHVybnMgdGhlIGNhbGN1bGF0ZWQgdmFsdWUgb3IgMCBpZiBub3Qgc2V0XG4gICAgICAgIC8vIEFkanVzdCBmaXhlZCBjb250ZW50IHBhZGRpbmdcbiAgICAgICAgJCQkMShTZWxlY3Rvci5GSVhFRF9DT05URU5UKS5lYWNoKGZ1bmN0aW9uIChpbmRleCwgZWxlbWVudCkge1xuICAgICAgICAgIHZhciBhY3R1YWxQYWRkaW5nID0gJCQkMShlbGVtZW50KVswXS5zdHlsZS5wYWRkaW5nUmlnaHQ7XG4gICAgICAgICAgdmFyIGNhbGN1bGF0ZWRQYWRkaW5nID0gJCQkMShlbGVtZW50KS5jc3MoJ3BhZGRpbmctcmlnaHQnKTtcbiAgICAgICAgICAkJCQxKGVsZW1lbnQpLmRhdGEoJ3BhZGRpbmctcmlnaHQnLCBhY3R1YWxQYWRkaW5nKS5jc3MoJ3BhZGRpbmctcmlnaHQnLCBwYXJzZUZsb2F0KGNhbGN1bGF0ZWRQYWRkaW5nKSArIF90aGlzOS5fc2Nyb2xsYmFyV2lkdGggKyBcInB4XCIpO1xuICAgICAgICB9KTsgLy8gQWRqdXN0IHN0aWNreSBjb250ZW50IG1hcmdpblxuXG4gICAgICAgICQkJDEoU2VsZWN0b3IuU1RJQ0tZX0NPTlRFTlQpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG4gICAgICAgICAgdmFyIGFjdHVhbE1hcmdpbiA9ICQkJDEoZWxlbWVudClbMF0uc3R5bGUubWFyZ2luUmlnaHQ7XG4gICAgICAgICAgdmFyIGNhbGN1bGF0ZWRNYXJnaW4gPSAkJCQxKGVsZW1lbnQpLmNzcygnbWFyZ2luLXJpZ2h0Jyk7XG4gICAgICAgICAgJCQkMShlbGVtZW50KS5kYXRhKCdtYXJnaW4tcmlnaHQnLCBhY3R1YWxNYXJnaW4pLmNzcygnbWFyZ2luLXJpZ2h0JywgcGFyc2VGbG9hdChjYWxjdWxhdGVkTWFyZ2luKSAtIF90aGlzOS5fc2Nyb2xsYmFyV2lkdGggKyBcInB4XCIpO1xuICAgICAgICB9KTsgLy8gQWRqdXN0IG5hdmJhci10b2dnbGVyIG1hcmdpblxuXG4gICAgICAgICQkJDEoU2VsZWN0b3IuTkFWQkFSX1RPR0dMRVIpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG4gICAgICAgICAgdmFyIGFjdHVhbE1hcmdpbiA9ICQkJDEoZWxlbWVudClbMF0uc3R5bGUubWFyZ2luUmlnaHQ7XG4gICAgICAgICAgdmFyIGNhbGN1bGF0ZWRNYXJnaW4gPSAkJCQxKGVsZW1lbnQpLmNzcygnbWFyZ2luLXJpZ2h0Jyk7XG4gICAgICAgICAgJCQkMShlbGVtZW50KS5kYXRhKCdtYXJnaW4tcmlnaHQnLCBhY3R1YWxNYXJnaW4pLmNzcygnbWFyZ2luLXJpZ2h0JywgcGFyc2VGbG9hdChjYWxjdWxhdGVkTWFyZ2luKSArIF90aGlzOS5fc2Nyb2xsYmFyV2lkdGggKyBcInB4XCIpO1xuICAgICAgICB9KTsgLy8gQWRqdXN0IGJvZHkgcGFkZGluZ1xuXG4gICAgICAgIHZhciBhY3R1YWxQYWRkaW5nID0gZG9jdW1lbnQuYm9keS5zdHlsZS5wYWRkaW5nUmlnaHQ7XG4gICAgICAgIHZhciBjYWxjdWxhdGVkUGFkZGluZyA9ICQkJDEoJ2JvZHknKS5jc3MoJ3BhZGRpbmctcmlnaHQnKTtcbiAgICAgICAgJCQkMSgnYm9keScpLmRhdGEoJ3BhZGRpbmctcmlnaHQnLCBhY3R1YWxQYWRkaW5nKS5jc3MoJ3BhZGRpbmctcmlnaHQnLCBwYXJzZUZsb2F0KGNhbGN1bGF0ZWRQYWRkaW5nKSArIHRoaXMuX3Njcm9sbGJhcldpZHRoICsgXCJweFwiKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9yZXNldFNjcm9sbGJhciA9IGZ1bmN0aW9uIF9yZXNldFNjcm9sbGJhcigpIHtcbiAgICAgIC8vIFJlc3RvcmUgZml4ZWQgY29udGVudCBwYWRkaW5nXG4gICAgICAkJCQxKFNlbGVjdG9yLkZJWEVEX0NPTlRFTlQpLmVhY2goZnVuY3Rpb24gKGluZGV4LCBlbGVtZW50KSB7XG4gICAgICAgIHZhciBwYWRkaW5nID0gJCQkMShlbGVtZW50KS5kYXRhKCdwYWRkaW5nLXJpZ2h0Jyk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBwYWRkaW5nICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICQkJDEoZWxlbWVudCkuY3NzKCdwYWRkaW5nLXJpZ2h0JywgcGFkZGluZykucmVtb3ZlRGF0YSgncGFkZGluZy1yaWdodCcpO1xuICAgICAgICB9XG4gICAgICB9KTsgLy8gUmVzdG9yZSBzdGlja3kgY29udGVudCBhbmQgbmF2YmFyLXRvZ2dsZXIgbWFyZ2luXG5cbiAgICAgICQkJDEoU2VsZWN0b3IuU1RJQ0tZX0NPTlRFTlQgKyBcIiwgXCIgKyBTZWxlY3Rvci5OQVZCQVJfVE9HR0xFUikuZWFjaChmdW5jdGlvbiAoaW5kZXgsIGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIG1hcmdpbiA9ICQkJDEoZWxlbWVudCkuZGF0YSgnbWFyZ2luLXJpZ2h0Jyk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBtYXJnaW4gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgJCQkMShlbGVtZW50KS5jc3MoJ21hcmdpbi1yaWdodCcsIG1hcmdpbikucmVtb3ZlRGF0YSgnbWFyZ2luLXJpZ2h0Jyk7XG4gICAgICAgIH1cbiAgICAgIH0pOyAvLyBSZXN0b3JlIGJvZHkgcGFkZGluZ1xuXG4gICAgICB2YXIgcGFkZGluZyA9ICQkJDEoJ2JvZHknKS5kYXRhKCdwYWRkaW5nLXJpZ2h0Jyk7XG5cbiAgICAgIGlmICh0eXBlb2YgcGFkZGluZyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgJCQkMSgnYm9keScpLmNzcygncGFkZGluZy1yaWdodCcsIHBhZGRpbmcpLnJlbW92ZURhdGEoJ3BhZGRpbmctcmlnaHQnKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9nZXRTY3JvbGxiYXJXaWR0aCA9IGZ1bmN0aW9uIF9nZXRTY3JvbGxiYXJXaWR0aCgpIHtcbiAgICAgIC8vIHRoeCBkLndhbHNoXG4gICAgICB2YXIgc2Nyb2xsRGl2ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gICAgICBzY3JvbGxEaXYuY2xhc3NOYW1lID0gQ2xhc3NOYW1lLlNDUk9MTEJBUl9NRUFTVVJFUjtcbiAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc2Nyb2xsRGl2KTtcbiAgICAgIHZhciBzY3JvbGxiYXJXaWR0aCA9IHNjcm9sbERpdi5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS53aWR0aCAtIHNjcm9sbERpdi5jbGllbnRXaWR0aDtcbiAgICAgIGRvY3VtZW50LmJvZHkucmVtb3ZlQ2hpbGQoc2Nyb2xsRGl2KTtcbiAgICAgIHJldHVybiBzY3JvbGxiYXJXaWR0aDtcbiAgICB9OyAvLyBzdGF0aWNcblxuXG4gICAgTW9kYWwuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnLCByZWxhdGVkVGFyZ2V0KSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgIHZhciBfY29uZmlnID0gX2V4dGVuZHMoe30sIE1vZGFsLkRlZmF1bHQsICQkJDEodGhpcykuZGF0YSgpLCB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyAmJiBjb25maWcpO1xuXG4gICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgIGRhdGEgPSBuZXcgTW9kYWwodGhpcywgX2NvbmZpZyk7XG4gICAgICAgICAgJCQkMSh0aGlzKS5kYXRhKERBVEFfS0VZLCBkYXRhKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGlmICh0eXBlb2YgZGF0YVtjb25maWddID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTm8gbWV0aG9kIG5hbWVkIFxcXCJcIiArIGNvbmZpZyArIFwiXFxcIlwiKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBkYXRhW2NvbmZpZ10ocmVsYXRlZFRhcmdldCk7XG4gICAgICAgIH0gZWxzZSBpZiAoX2NvbmZpZy5zaG93KSB7XG4gICAgICAgICAgZGF0YS5zaG93KHJlbGF0ZWRUYXJnZXQpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgX2NyZWF0ZUNsYXNzKE1vZGFsLCBudWxsLCBbe1xuICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgfVxuICAgIH1dKTtcbiAgICByZXR1cm4gTW9kYWw7XG4gIH0oKTtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBEYXRhIEFwaSBpbXBsZW1lbnRhdGlvblxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cblxuICAkJCQxKGRvY3VtZW50KS5vbihFdmVudC5DTElDS19EQVRBX0FQSSwgU2VsZWN0b3IuREFUQV9UT0dHTEUsIGZ1bmN0aW9uIChldmVudCkge1xuICAgIHZhciBfdGhpczEwID0gdGhpcztcblxuICAgIHZhciB0YXJnZXQ7XG4gICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KHRoaXMpO1xuXG4gICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICB0YXJnZXQgPSAkJCQxKHNlbGVjdG9yKVswXTtcbiAgICB9XG5cbiAgICB2YXIgY29uZmlnID0gJCQkMSh0YXJnZXQpLmRhdGEoREFUQV9LRVkpID8gJ3RvZ2dsZScgOiBfZXh0ZW5kcyh7fSwgJCQkMSh0YXJnZXQpLmRhdGEoKSwgJCQkMSh0aGlzKS5kYXRhKCkpO1xuXG4gICAgaWYgKHRoaXMudGFnTmFtZSA9PT0gJ0EnIHx8IHRoaXMudGFnTmFtZSA9PT0gJ0FSRUEnKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIHZhciAkdGFyZ2V0ID0gJCQkMSh0YXJnZXQpLm9uZShFdmVudC5TSE9XLCBmdW5jdGlvbiAoc2hvd0V2ZW50KSB7XG4gICAgICBpZiAoc2hvd0V2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgIC8vIG9ubHkgcmVnaXN0ZXIgZm9jdXMgcmVzdG9yZXIgaWYgbW9kYWwgd2lsbCBhY3R1YWxseSBnZXQgc2hvd25cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAkdGFyZ2V0Lm9uZShFdmVudC5ISURERU4sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCQkJDEoX3RoaXMxMCkuaXMoJzp2aXNpYmxlJykpIHtcbiAgICAgICAgICBfdGhpczEwLmZvY3VzKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgTW9kYWwuX2pRdWVyeUludGVyZmFjZS5jYWxsKCQkJDEodGFyZ2V0KSwgY29uZmlnLCB0aGlzKTtcbiAgfSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICAkJCQxLmZuW05BTUVdID0gTW9kYWwuX2pRdWVyeUludGVyZmFjZTtcbiAgJCQkMS5mbltOQU1FXS5Db25zdHJ1Y3RvciA9IE1vZGFsO1xuXG4gICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgIHJldHVybiBNb2RhbC5falF1ZXJ5SW50ZXJmYWNlO1xuICB9O1xuXG4gIHJldHVybiBNb2RhbDtcbn0oJCk7XG5cbi8qKlxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEJvb3RzdHJhcCAodjQuMC4wLWJldGEuMyk6IHRvb2x0aXAuanNcbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbnZhciBUb29sdGlwID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICB2YXIgTkFNRSA9ICd0b29sdGlwJztcbiAgdmFyIFZFUlNJT04gPSAnNC4wLjAtYmV0YS4zJztcbiAgdmFyIERBVEFfS0VZID0gJ2JzLnRvb2x0aXAnO1xuICB2YXIgRVZFTlRfS0VZID0gXCIuXCIgKyBEQVRBX0tFWTtcbiAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gIHZhciBUUkFOU0lUSU9OX0RVUkFUSU9OID0gMTUwO1xuICB2YXIgQ0xBU1NfUFJFRklYID0gJ2JzLXRvb2x0aXAnO1xuICB2YXIgQlNDTFNfUFJFRklYX1JFR0VYID0gbmV3IFJlZ0V4cChcIihefFxcXFxzKVwiICsgQ0xBU1NfUFJFRklYICsgXCJcXFxcUytcIiwgJ2cnKTtcbiAgdmFyIERlZmF1bHRUeXBlID0ge1xuICAgIGFuaW1hdGlvbjogJ2Jvb2xlYW4nLFxuICAgIHRlbXBsYXRlOiAnc3RyaW5nJyxcbiAgICB0aXRsZTogJyhzdHJpbmd8ZWxlbWVudHxmdW5jdGlvbiknLFxuICAgIHRyaWdnZXI6ICdzdHJpbmcnLFxuICAgIGRlbGF5OiAnKG51bWJlcnxvYmplY3QpJyxcbiAgICBodG1sOiAnYm9vbGVhbicsXG4gICAgc2VsZWN0b3I6ICcoc3RyaW5nfGJvb2xlYW4pJyxcbiAgICBwbGFjZW1lbnQ6ICcoc3RyaW5nfGZ1bmN0aW9uKScsXG4gICAgb2Zmc2V0OiAnKG51bWJlcnxzdHJpbmcpJyxcbiAgICBjb250YWluZXI6ICcoc3RyaW5nfGVsZW1lbnR8Ym9vbGVhbiknLFxuICAgIGZhbGxiYWNrUGxhY2VtZW50OiAnKHN0cmluZ3xhcnJheSknLFxuICAgIGJvdW5kYXJ5OiAnKHN0cmluZ3xlbGVtZW50KSdcbiAgfTtcbiAgdmFyIEF0dGFjaG1lbnRNYXAgPSB7XG4gICAgQVVUTzogJ2F1dG8nLFxuICAgIFRPUDogJ3RvcCcsXG4gICAgUklHSFQ6ICdyaWdodCcsXG4gICAgQk9UVE9NOiAnYm90dG9tJyxcbiAgICBMRUZUOiAnbGVmdCdcbiAgfTtcbiAgdmFyIERlZmF1bHQgPSB7XG4gICAgYW5pbWF0aW9uOiB0cnVlLFxuICAgIHRlbXBsYXRlOiAnPGRpdiBjbGFzcz1cInRvb2x0aXBcIiByb2xlPVwidG9vbHRpcFwiPicgKyAnPGRpdiBjbGFzcz1cImFycm93XCI+PC9kaXY+JyArICc8ZGl2IGNsYXNzPVwidG9vbHRpcC1pbm5lclwiPjwvZGl2PjwvZGl2PicsXG4gICAgdHJpZ2dlcjogJ2hvdmVyIGZvY3VzJyxcbiAgICB0aXRsZTogJycsXG4gICAgZGVsYXk6IDAsXG4gICAgaHRtbDogZmFsc2UsXG4gICAgc2VsZWN0b3I6IGZhbHNlLFxuICAgIHBsYWNlbWVudDogJ3RvcCcsXG4gICAgb2Zmc2V0OiAwLFxuICAgIGNvbnRhaW5lcjogZmFsc2UsXG4gICAgZmFsbGJhY2tQbGFjZW1lbnQ6ICdmbGlwJyxcbiAgICBib3VuZGFyeTogJ3Njcm9sbFBhcmVudCdcbiAgfTtcbiAgdmFyIEhvdmVyU3RhdGUgPSB7XG4gICAgU0hPVzogJ3Nob3cnLFxuICAgIE9VVDogJ291dCdcbiAgfTtcbiAgdmFyIEV2ZW50ID0ge1xuICAgIEhJREU6IFwiaGlkZVwiICsgRVZFTlRfS0VZLFxuICAgIEhJRERFTjogXCJoaWRkZW5cIiArIEVWRU5UX0tFWSxcbiAgICBTSE9XOiBcInNob3dcIiArIEVWRU5UX0tFWSxcbiAgICBTSE9XTjogXCJzaG93blwiICsgRVZFTlRfS0VZLFxuICAgIElOU0VSVEVEOiBcImluc2VydGVkXCIgKyBFVkVOVF9LRVksXG4gICAgQ0xJQ0s6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSxcbiAgICBGT0NVU0lOOiBcImZvY3VzaW5cIiArIEVWRU5UX0tFWSxcbiAgICBGT0NVU09VVDogXCJmb2N1c291dFwiICsgRVZFTlRfS0VZLFxuICAgIE1PVVNFRU5URVI6IFwibW91c2VlbnRlclwiICsgRVZFTlRfS0VZLFxuICAgIE1PVVNFTEVBVkU6IFwibW91c2VsZWF2ZVwiICsgRVZFTlRfS0VZXG4gIH07XG4gIHZhciBDbGFzc05hbWUgPSB7XG4gICAgRkFERTogJ2ZhZGUnLFxuICAgIFNIT1c6ICdzaG93J1xuICB9O1xuICB2YXIgU2VsZWN0b3IgPSB7XG4gICAgVE9PTFRJUDogJy50b29sdGlwJyxcbiAgICBUT09MVElQX0lOTkVSOiAnLnRvb2x0aXAtaW5uZXInLFxuICAgIEFSUk9XOiAnLmFycm93J1xuICB9O1xuICB2YXIgVHJpZ2dlciA9IHtcbiAgICBIT1ZFUjogJ2hvdmVyJyxcbiAgICBGT0NVUzogJ2ZvY3VzJyxcbiAgICBDTElDSzogJ2NsaWNrJyxcbiAgICBNQU5VQUw6ICdtYW51YWwnXG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gIH07XG5cbiAgdmFyIFRvb2x0aXAgPVxuICAvKiNfX1BVUkVfXyovXG4gIGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUb29sdGlwKGVsZW1lbnQsIGNvbmZpZykge1xuICAgICAgLyoqXG4gICAgICAgKiBDaGVjayBmb3IgUG9wcGVyIGRlcGVuZGVuY3lcbiAgICAgICAqIFBvcHBlciAtIGh0dHBzOi8vcG9wcGVyLmpzLm9yZ1xuICAgICAgICovXG4gICAgICBpZiAodHlwZW9mIFBvcHBlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdCb290c3RyYXAgdG9vbHRpcHMgcmVxdWlyZSBQb3BwZXIuanMgKGh0dHBzOi8vcG9wcGVyLmpzLm9yZyknKTtcbiAgICAgIH0gLy8gcHJpdmF0ZVxuXG5cbiAgICAgIHRoaXMuX2lzRW5hYmxlZCA9IHRydWU7XG4gICAgICB0aGlzLl90aW1lb3V0ID0gMDtcbiAgICAgIHRoaXMuX2hvdmVyU3RhdGUgPSAnJztcbiAgICAgIHRoaXMuX2FjdGl2ZVRyaWdnZXIgPSB7fTtcbiAgICAgIHRoaXMuX3BvcHBlciA9IG51bGw7IC8vIHByb3RlY3RlZFxuXG4gICAgICB0aGlzLmVsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgdGhpcy5jb25maWcgPSB0aGlzLl9nZXRDb25maWcoY29uZmlnKTtcbiAgICAgIHRoaXMudGlwID0gbnVsbDtcblxuICAgICAgdGhpcy5fc2V0TGlzdGVuZXJzKCk7XG4gICAgfSAvLyBnZXR0ZXJzXG5cblxuICAgIHZhciBfcHJvdG8gPSBUb29sdGlwLnByb3RvdHlwZTtcblxuICAgIC8vIHB1YmxpY1xuICAgIF9wcm90by5lbmFibGUgPSBmdW5jdGlvbiBlbmFibGUoKSB7XG4gICAgICB0aGlzLl9pc0VuYWJsZWQgPSB0cnVlO1xuICAgIH07XG5cbiAgICBfcHJvdG8uZGlzYWJsZSA9IGZ1bmN0aW9uIGRpc2FibGUoKSB7XG4gICAgICB0aGlzLl9pc0VuYWJsZWQgPSBmYWxzZTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLnRvZ2dsZUVuYWJsZWQgPSBmdW5jdGlvbiB0b2dnbGVFbmFibGVkKCkge1xuICAgICAgdGhpcy5faXNFbmFibGVkID0gIXRoaXMuX2lzRW5hYmxlZDtcbiAgICB9O1xuXG4gICAgX3Byb3RvLnRvZ2dsZSA9IGZ1bmN0aW9uIHRvZ2dsZShldmVudCkge1xuICAgICAgaWYgKCF0aGlzLl9pc0VuYWJsZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgdmFyIGRhdGFLZXkgPSB0aGlzLmNvbnN0cnVjdG9yLkRBVEFfS0VZO1xuICAgICAgICB2YXIgY29udGV4dCA9ICQkJDEoZXZlbnQuY3VycmVudFRhcmdldCkuZGF0YShkYXRhS2V5KTtcblxuICAgICAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgICAgICBjb250ZXh0ID0gbmV3IHRoaXMuY29uc3RydWN0b3IoZXZlbnQuY3VycmVudFRhcmdldCwgdGhpcy5fZ2V0RGVsZWdhdGVDb25maWcoKSk7XG4gICAgICAgICAgJCQkMShldmVudC5jdXJyZW50VGFyZ2V0KS5kYXRhKGRhdGFLZXksIGNvbnRleHQpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29udGV4dC5fYWN0aXZlVHJpZ2dlci5jbGljayA9ICFjb250ZXh0Ll9hY3RpdmVUcmlnZ2VyLmNsaWNrO1xuXG4gICAgICAgIGlmIChjb250ZXh0Ll9pc1dpdGhBY3RpdmVUcmlnZ2VyKCkpIHtcbiAgICAgICAgICBjb250ZXh0Ll9lbnRlcihudWxsLCBjb250ZXh0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb250ZXh0Ll9sZWF2ZShudWxsLCBjb250ZXh0KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKCQkJDEodGhpcy5nZXRUaXBFbGVtZW50KCkpLmhhc0NsYXNzKENsYXNzTmFtZS5TSE9XKSkge1xuICAgICAgICAgIHRoaXMuX2xlYXZlKG51bGwsIHRoaXMpO1xuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZW50ZXIobnVsbCwgdGhpcyk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLl90aW1lb3V0KTtcbiAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLmVsZW1lbnQsIHRoaXMuY29uc3RydWN0b3IuREFUQV9LRVkpO1xuICAgICAgJCQkMSh0aGlzLmVsZW1lbnQpLm9mZih0aGlzLmNvbnN0cnVjdG9yLkVWRU5UX0tFWSk7XG4gICAgICAkJCQxKHRoaXMuZWxlbWVudCkuY2xvc2VzdCgnLm1vZGFsJykub2ZmKCdoaWRlLmJzLm1vZGFsJyk7XG5cbiAgICAgIGlmICh0aGlzLnRpcCkge1xuICAgICAgICAkJCQxKHRoaXMudGlwKS5yZW1vdmUoKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5faXNFbmFibGVkID0gbnVsbDtcbiAgICAgIHRoaXMuX3RpbWVvdXQgPSBudWxsO1xuICAgICAgdGhpcy5faG92ZXJTdGF0ZSA9IG51bGw7XG4gICAgICB0aGlzLl9hY3RpdmVUcmlnZ2VyID0gbnVsbDtcblxuICAgICAgaWYgKHRoaXMuX3BvcHBlciAhPT0gbnVsbCkge1xuICAgICAgICB0aGlzLl9wb3BwZXIuZGVzdHJveSgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9wb3BwZXIgPSBudWxsO1xuICAgICAgdGhpcy5lbGVtZW50ID0gbnVsbDtcbiAgICAgIHRoaXMuY29uZmlnID0gbnVsbDtcbiAgICAgIHRoaXMudGlwID0gbnVsbDtcbiAgICB9O1xuXG4gICAgX3Byb3RvLnNob3cgPSBmdW5jdGlvbiBzaG93KCkge1xuICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgaWYgKCQkJDEodGhpcy5lbGVtZW50KS5jc3MoJ2Rpc3BsYXknKSA9PT0gJ25vbmUnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignUGxlYXNlIHVzZSBzaG93IG9uIHZpc2libGUgZWxlbWVudHMnKTtcbiAgICAgIH1cblxuICAgICAgdmFyIHNob3dFdmVudCA9ICQkJDEuRXZlbnQodGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5TSE9XKTtcblxuICAgICAgaWYgKHRoaXMuaXNXaXRoQ29udGVudCgpICYmIHRoaXMuX2lzRW5hYmxlZCkge1xuICAgICAgICAkJCQxKHRoaXMuZWxlbWVudCkudHJpZ2dlcihzaG93RXZlbnQpO1xuICAgICAgICB2YXIgaXNJblRoZURvbSA9ICQkJDEuY29udGFpbnModGhpcy5lbGVtZW50Lm93bmVyRG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LCB0aGlzLmVsZW1lbnQpO1xuXG4gICAgICAgIGlmIChzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkgfHwgIWlzSW5UaGVEb20pIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdGlwID0gdGhpcy5nZXRUaXBFbGVtZW50KCk7XG4gICAgICAgIHZhciB0aXBJZCA9IFV0aWwuZ2V0VUlEKHRoaXMuY29uc3RydWN0b3IuTkFNRSk7XG4gICAgICAgIHRpcC5zZXRBdHRyaWJ1dGUoJ2lkJywgdGlwSWQpO1xuICAgICAgICB0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKCdhcmlhLWRlc2NyaWJlZGJ5JywgdGlwSWQpO1xuICAgICAgICB0aGlzLnNldENvbnRlbnQoKTtcblxuICAgICAgICBpZiAodGhpcy5jb25maWcuYW5pbWF0aW9uKSB7XG4gICAgICAgICAgJCQkMSh0aXApLmFkZENsYXNzKENsYXNzTmFtZS5GQURFKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBwbGFjZW1lbnQgPSB0eXBlb2YgdGhpcy5jb25maWcucGxhY2VtZW50ID09PSAnZnVuY3Rpb24nID8gdGhpcy5jb25maWcucGxhY2VtZW50LmNhbGwodGhpcywgdGlwLCB0aGlzLmVsZW1lbnQpIDogdGhpcy5jb25maWcucGxhY2VtZW50O1xuXG4gICAgICAgIHZhciBhdHRhY2htZW50ID0gdGhpcy5fZ2V0QXR0YWNobWVudChwbGFjZW1lbnQpO1xuXG4gICAgICAgIHRoaXMuYWRkQXR0YWNobWVudENsYXNzKGF0dGFjaG1lbnQpO1xuICAgICAgICB2YXIgY29udGFpbmVyID0gdGhpcy5jb25maWcuY29udGFpbmVyID09PSBmYWxzZSA/IGRvY3VtZW50LmJvZHkgOiAkJCQxKHRoaXMuY29uZmlnLmNvbnRhaW5lcik7XG4gICAgICAgICQkJDEodGlwKS5kYXRhKHRoaXMuY29uc3RydWN0b3IuREFUQV9LRVksIHRoaXMpO1xuXG4gICAgICAgIGlmICghJCQkMS5jb250YWlucyh0aGlzLmVsZW1lbnQub3duZXJEb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIHRoaXMudGlwKSkge1xuICAgICAgICAgICQkJDEodGlwKS5hcHBlbmRUbyhjb250YWluZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgJCQkMSh0aGlzLmVsZW1lbnQpLnRyaWdnZXIodGhpcy5jb25zdHJ1Y3Rvci5FdmVudC5JTlNFUlRFRCk7XG4gICAgICAgIHRoaXMuX3BvcHBlciA9IG5ldyBQb3BwZXIodGhpcy5lbGVtZW50LCB0aXAsIHtcbiAgICAgICAgICBwbGFjZW1lbnQ6IGF0dGFjaG1lbnQsXG4gICAgICAgICAgbW9kaWZpZXJzOiB7XG4gICAgICAgICAgICBvZmZzZXQ6IHtcbiAgICAgICAgICAgICAgb2Zmc2V0OiB0aGlzLmNvbmZpZy5vZmZzZXRcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmbGlwOiB7XG4gICAgICAgICAgICAgIGJlaGF2aW9yOiB0aGlzLmNvbmZpZy5mYWxsYmFja1BsYWNlbWVudFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGFycm93OiB7XG4gICAgICAgICAgICAgIGVsZW1lbnQ6IFNlbGVjdG9yLkFSUk9XXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcHJldmVudE92ZXJmbG93OiB7XG4gICAgICAgICAgICAgIGJvdW5kYXJpZXNFbGVtZW50OiB0aGlzLmNvbmZpZy5ib3VuZGFyeVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgb25DcmVhdGU6IGZ1bmN0aW9uIG9uQ3JlYXRlKGRhdGEpIHtcbiAgICAgICAgICAgIGlmIChkYXRhLm9yaWdpbmFsUGxhY2VtZW50ICE9PSBkYXRhLnBsYWNlbWVudCkge1xuICAgICAgICAgICAgICBfdGhpcy5faGFuZGxlUG9wcGVyUGxhY2VtZW50Q2hhbmdlKGRhdGEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0sXG4gICAgICAgICAgb25VcGRhdGU6IGZ1bmN0aW9uIG9uVXBkYXRlKGRhdGEpIHtcbiAgICAgICAgICAgIF90aGlzLl9oYW5kbGVQb3BwZXJQbGFjZW1lbnRDaGFuZ2UoZGF0YSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgJCQkMSh0aXApLmFkZENsYXNzKENsYXNzTmFtZS5TSE9XKTsgLy8gaWYgdGhpcyBpcyBhIHRvdWNoLWVuYWJsZWQgZGV2aWNlIHdlIGFkZCBleHRyYVxuICAgICAgICAvLyBlbXB0eSBtb3VzZW92ZXIgbGlzdGVuZXJzIHRvIHRoZSBib2R5J3MgaW1tZWRpYXRlIGNoaWxkcmVuO1xuICAgICAgICAvLyBvbmx5IG5lZWRlZCBiZWNhdXNlIG9mIGJyb2tlbiBldmVudCBkZWxlZ2F0aW9uIG9uIGlPU1xuICAgICAgICAvLyBodHRwczovL3d3dy5xdWlya3Ntb2RlLm9yZy9ibG9nL2FyY2hpdmVzLzIwMTQvMDIvbW91c2VfZXZlbnRfYnViLmh0bWxcblxuICAgICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgICAgJCQkMSgnYm9keScpLmNoaWxkcmVuKCkub24oJ21vdXNlb3ZlcicsIG51bGwsICQkJDEubm9vcCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgY29tcGxldGUgPSBmdW5jdGlvbiBjb21wbGV0ZSgpIHtcbiAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLmFuaW1hdGlvbikge1xuICAgICAgICAgICAgX3RoaXMuX2ZpeFRyYW5zaXRpb24oKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICB2YXIgcHJldkhvdmVyU3RhdGUgPSBfdGhpcy5faG92ZXJTdGF0ZTtcbiAgICAgICAgICBfdGhpcy5faG92ZXJTdGF0ZSA9IG51bGw7XG4gICAgICAgICAgJCQkMShfdGhpcy5lbGVtZW50KS50cmlnZ2VyKF90aGlzLmNvbnN0cnVjdG9yLkV2ZW50LlNIT1dOKTtcblxuICAgICAgICAgIGlmIChwcmV2SG92ZXJTdGF0ZSA9PT0gSG92ZXJTdGF0ZS5PVVQpIHtcbiAgICAgICAgICAgIF90aGlzLl9sZWF2ZShudWxsLCBfdGhpcyk7XG4gICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChVdGlsLnN1cHBvcnRzVHJhbnNpdGlvbkVuZCgpICYmICQkJDEodGhpcy50aXApLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKSkge1xuICAgICAgICAgICQkJDEodGhpcy50aXApLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBjb21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQoVG9vbHRpcC5fVFJBTlNJVElPTl9EVVJBVElPTik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29tcGxldGUoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8uaGlkZSA9IGZ1bmN0aW9uIGhpZGUoY2FsbGJhY2spIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgdGlwID0gdGhpcy5nZXRUaXBFbGVtZW50KCk7XG4gICAgICB2YXIgaGlkZUV2ZW50ID0gJCQkMS5FdmVudCh0aGlzLmNvbnN0cnVjdG9yLkV2ZW50LkhJREUpO1xuXG4gICAgICB2YXIgY29tcGxldGUgPSBmdW5jdGlvbiBjb21wbGV0ZSgpIHtcbiAgICAgICAgaWYgKF90aGlzMi5faG92ZXJTdGF0ZSAhPT0gSG92ZXJTdGF0ZS5TSE9XICYmIHRpcC5wYXJlbnROb2RlKSB7XG4gICAgICAgICAgdGlwLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGlwKTtcbiAgICAgICAgfVxuXG4gICAgICAgIF90aGlzMi5fY2xlYW5UaXBDbGFzcygpO1xuXG4gICAgICAgIF90aGlzMi5lbGVtZW50LnJlbW92ZUF0dHJpYnV0ZSgnYXJpYS1kZXNjcmliZWRieScpO1xuXG4gICAgICAgICQkJDEoX3RoaXMyLmVsZW1lbnQpLnRyaWdnZXIoX3RoaXMyLmNvbnN0cnVjdG9yLkV2ZW50LkhJRERFTik7XG5cbiAgICAgICAgaWYgKF90aGlzMi5fcG9wcGVyICE9PSBudWxsKSB7XG4gICAgICAgICAgX3RoaXMyLl9wb3BwZXIuZGVzdHJveSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNhbGxiYWNrKSB7XG4gICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgfTtcblxuICAgICAgJCQkMSh0aGlzLmVsZW1lbnQpLnRyaWdnZXIoaGlkZUV2ZW50KTtcblxuICAgICAgaWYgKGhpZGVFdmVudC5pc0RlZmF1bHRQcmV2ZW50ZWQoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgICQkJDEodGlwKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuU0hPVyk7IC8vIGlmIHRoaXMgaXMgYSB0b3VjaC1lbmFibGVkIGRldmljZSB3ZSByZW1vdmUgdGhlIGV4dHJhXG4gICAgICAvLyBlbXB0eSBtb3VzZW92ZXIgbGlzdGVuZXJzIHdlIGFkZGVkIGZvciBpT1Mgc3VwcG9ydFxuXG4gICAgICBpZiAoJ29udG91Y2hzdGFydCcgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgICQkJDEoJ2JvZHknKS5jaGlsZHJlbigpLm9mZignbW91c2VvdmVyJywgbnVsbCwgJCQkMS5ub29wKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fYWN0aXZlVHJpZ2dlcltUcmlnZ2VyLkNMSUNLXSA9IGZhbHNlO1xuICAgICAgdGhpcy5fYWN0aXZlVHJpZ2dlcltUcmlnZ2VyLkZPQ1VTXSA9IGZhbHNlO1xuICAgICAgdGhpcy5fYWN0aXZlVHJpZ2dlcltUcmlnZ2VyLkhPVkVSXSA9IGZhbHNlO1xuXG4gICAgICBpZiAoVXRpbC5zdXBwb3J0c1RyYW5zaXRpb25FbmQoKSAmJiAkJCQxKHRoaXMudGlwKS5oYXNDbGFzcyhDbGFzc05hbWUuRkFERSkpIHtcbiAgICAgICAgJCQkMSh0aXApLm9uZShVdGlsLlRSQU5TSVRJT05fRU5ELCBjb21wbGV0ZSkuZW11bGF0ZVRyYW5zaXRpb25FbmQoVFJBTlNJVElPTl9EVVJBVElPTik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb21wbGV0ZSgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9ob3ZlclN0YXRlID0gJyc7XG4gICAgfTtcblxuICAgIF9wcm90by51cGRhdGUgPSBmdW5jdGlvbiB1cGRhdGUoKSB7XG4gICAgICBpZiAodGhpcy5fcG9wcGVyICE9PSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3BvcHBlci5zY2hlZHVsZVVwZGF0ZSgpO1xuICAgICAgfVxuICAgIH07IC8vIHByb3RlY3RlZFxuXG5cbiAgICBfcHJvdG8uaXNXaXRoQ29udGVudCA9IGZ1bmN0aW9uIGlzV2l0aENvbnRlbnQoKSB7XG4gICAgICByZXR1cm4gQm9vbGVhbih0aGlzLmdldFRpdGxlKCkpO1xuICAgIH07XG5cbiAgICBfcHJvdG8uYWRkQXR0YWNobWVudENsYXNzID0gZnVuY3Rpb24gYWRkQXR0YWNobWVudENsYXNzKGF0dGFjaG1lbnQpIHtcbiAgICAgICQkJDEodGhpcy5nZXRUaXBFbGVtZW50KCkpLmFkZENsYXNzKENMQVNTX1BSRUZJWCArIFwiLVwiICsgYXR0YWNobWVudCk7XG4gICAgfTtcblxuICAgIF9wcm90by5nZXRUaXBFbGVtZW50ID0gZnVuY3Rpb24gZ2V0VGlwRWxlbWVudCgpIHtcbiAgICAgIHRoaXMudGlwID0gdGhpcy50aXAgfHwgJCQkMSh0aGlzLmNvbmZpZy50ZW1wbGF0ZSlbMF07XG4gICAgICByZXR1cm4gdGhpcy50aXA7XG4gICAgfTtcblxuICAgIF9wcm90by5zZXRDb250ZW50ID0gZnVuY3Rpb24gc2V0Q29udGVudCgpIHtcbiAgICAgIHZhciAkdGlwID0gJCQkMSh0aGlzLmdldFRpcEVsZW1lbnQoKSk7XG4gICAgICB0aGlzLnNldEVsZW1lbnRDb250ZW50KCR0aXAuZmluZChTZWxlY3Rvci5UT09MVElQX0lOTkVSKSwgdGhpcy5nZXRUaXRsZSgpKTtcbiAgICAgICR0aXAucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkZBREUgKyBcIiBcIiArIENsYXNzTmFtZS5TSE9XKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLnNldEVsZW1lbnRDb250ZW50ID0gZnVuY3Rpb24gc2V0RWxlbWVudENvbnRlbnQoJGVsZW1lbnQsIGNvbnRlbnQpIHtcbiAgICAgIHZhciBodG1sID0gdGhpcy5jb25maWcuaHRtbDtcblxuICAgICAgaWYgKHR5cGVvZiBjb250ZW50ID09PSAnb2JqZWN0JyAmJiAoY29udGVudC5ub2RlVHlwZSB8fCBjb250ZW50LmpxdWVyeSkpIHtcbiAgICAgICAgLy8gY29udGVudCBpcyBhIERPTSBub2RlIG9yIGEgalF1ZXJ5XG4gICAgICAgIGlmIChodG1sKSB7XG4gICAgICAgICAgaWYgKCEkJCQxKGNvbnRlbnQpLnBhcmVudCgpLmlzKCRlbGVtZW50KSkge1xuICAgICAgICAgICAgJGVsZW1lbnQuZW1wdHkoKS5hcHBlbmQoY29udGVudCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICRlbGVtZW50LnRleHQoJCQkMShjb250ZW50KS50ZXh0KCkpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAkZWxlbWVudFtodG1sID8gJ2h0bWwnIDogJ3RleHQnXShjb250ZW50KTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLmdldFRpdGxlID0gZnVuY3Rpb24gZ2V0VGl0bGUoKSB7XG4gICAgICB2YXIgdGl0bGUgPSB0aGlzLmVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLW9yaWdpbmFsLXRpdGxlJyk7XG5cbiAgICAgIGlmICghdGl0bGUpIHtcbiAgICAgICAgdGl0bGUgPSB0eXBlb2YgdGhpcy5jb25maWcudGl0bGUgPT09ICdmdW5jdGlvbicgPyB0aGlzLmNvbmZpZy50aXRsZS5jYWxsKHRoaXMuZWxlbWVudCkgOiB0aGlzLmNvbmZpZy50aXRsZTtcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRpdGxlO1xuICAgIH07IC8vIHByaXZhdGVcblxuXG4gICAgX3Byb3RvLl9nZXRBdHRhY2htZW50ID0gZnVuY3Rpb24gX2dldEF0dGFjaG1lbnQocGxhY2VtZW50KSB7XG4gICAgICByZXR1cm4gQXR0YWNobWVudE1hcFtwbGFjZW1lbnQudG9VcHBlckNhc2UoKV07XG4gICAgfTtcblxuICAgIF9wcm90by5fc2V0TGlzdGVuZXJzID0gZnVuY3Rpb24gX3NldExpc3RlbmVycygpIHtcbiAgICAgIHZhciBfdGhpczMgPSB0aGlzO1xuXG4gICAgICB2YXIgdHJpZ2dlcnMgPSB0aGlzLmNvbmZpZy50cmlnZ2VyLnNwbGl0KCcgJyk7XG4gICAgICB0cmlnZ2Vycy5mb3JFYWNoKGZ1bmN0aW9uICh0cmlnZ2VyKSB7XG4gICAgICAgIGlmICh0cmlnZ2VyID09PSAnY2xpY2snKSB7XG4gICAgICAgICAgJCQkMShfdGhpczMuZWxlbWVudCkub24oX3RoaXMzLmNvbnN0cnVjdG9yLkV2ZW50LkNMSUNLLCBfdGhpczMuY29uZmlnLnNlbGVjdG9yLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczMudG9nZ2xlKGV2ZW50KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIGlmICh0cmlnZ2VyICE9PSBUcmlnZ2VyLk1BTlVBTCkge1xuICAgICAgICAgIHZhciBldmVudEluID0gdHJpZ2dlciA9PT0gVHJpZ2dlci5IT1ZFUiA/IF90aGlzMy5jb25zdHJ1Y3Rvci5FdmVudC5NT1VTRUVOVEVSIDogX3RoaXMzLmNvbnN0cnVjdG9yLkV2ZW50LkZPQ1VTSU47XG4gICAgICAgICAgdmFyIGV2ZW50T3V0ID0gdHJpZ2dlciA9PT0gVHJpZ2dlci5IT1ZFUiA/IF90aGlzMy5jb25zdHJ1Y3Rvci5FdmVudC5NT1VTRUxFQVZFIDogX3RoaXMzLmNvbnN0cnVjdG9yLkV2ZW50LkZPQ1VTT1VUO1xuICAgICAgICAgICQkJDEoX3RoaXMzLmVsZW1lbnQpLm9uKGV2ZW50SW4sIF90aGlzMy5jb25maWcuc2VsZWN0b3IsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgcmV0dXJuIF90aGlzMy5fZW50ZXIoZXZlbnQpO1xuICAgICAgICAgIH0pLm9uKGV2ZW50T3V0LCBfdGhpczMuY29uZmlnLnNlbGVjdG9yLCBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBfdGhpczMuX2xlYXZlKGV2ZW50KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgICQkJDEoX3RoaXMzLmVsZW1lbnQpLmNsb3Nlc3QoJy5tb2RhbCcpLm9uKCdoaWRlLmJzLm1vZGFsJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiBfdGhpczMuaGlkZSgpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAodGhpcy5jb25maWcuc2VsZWN0b3IpIHtcbiAgICAgICAgdGhpcy5jb25maWcgPSBfZXh0ZW5kcyh7fSwgdGhpcy5jb25maWcsIHtcbiAgICAgICAgICB0cmlnZ2VyOiAnbWFudWFsJyxcbiAgICAgICAgICBzZWxlY3RvcjogJydcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9maXhUaXRsZSgpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfcHJvdG8uX2ZpeFRpdGxlID0gZnVuY3Rpb24gX2ZpeFRpdGxlKCkge1xuICAgICAgdmFyIHRpdGxlVHlwZSA9IHR5cGVvZiB0aGlzLmVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLW9yaWdpbmFsLXRpdGxlJyk7XG5cbiAgICAgIGlmICh0aGlzLmVsZW1lbnQuZ2V0QXR0cmlidXRlKCd0aXRsZScpIHx8IHRpdGxlVHlwZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhpcy5lbGVtZW50LnNldEF0dHJpYnV0ZSgnZGF0YS1vcmlnaW5hbC10aXRsZScsIHRoaXMuZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3RpdGxlJykgfHwgJycpO1xuICAgICAgICB0aGlzLmVsZW1lbnQuc2V0QXR0cmlidXRlKCd0aXRsZScsICcnKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9lbnRlciA9IGZ1bmN0aW9uIF9lbnRlcihldmVudCwgY29udGV4dCkge1xuICAgICAgdmFyIGRhdGFLZXkgPSB0aGlzLmNvbnN0cnVjdG9yLkRBVEFfS0VZO1xuICAgICAgY29udGV4dCA9IGNvbnRleHQgfHwgJCQkMShldmVudC5jdXJyZW50VGFyZ2V0KS5kYXRhKGRhdGFLZXkpO1xuXG4gICAgICBpZiAoIWNvbnRleHQpIHtcbiAgICAgICAgY29udGV4dCA9IG5ldyB0aGlzLmNvbnN0cnVjdG9yKGV2ZW50LmN1cnJlbnRUYXJnZXQsIHRoaXMuX2dldERlbGVnYXRlQ29uZmlnKCkpO1xuICAgICAgICAkJCQxKGV2ZW50LmN1cnJlbnRUYXJnZXQpLmRhdGEoZGF0YUtleSwgY29udGV4dCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChldmVudCkge1xuICAgICAgICBjb250ZXh0Ll9hY3RpdmVUcmlnZ2VyW2V2ZW50LnR5cGUgPT09ICdmb2N1c2luJyA/IFRyaWdnZXIuRk9DVVMgOiBUcmlnZ2VyLkhPVkVSXSA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICgkJCQxKGNvbnRleHQuZ2V0VGlwRWxlbWVudCgpKS5oYXNDbGFzcyhDbGFzc05hbWUuU0hPVykgfHwgY29udGV4dC5faG92ZXJTdGF0ZSA9PT0gSG92ZXJTdGF0ZS5TSE9XKSB7XG4gICAgICAgIGNvbnRleHQuX2hvdmVyU3RhdGUgPSBIb3ZlclN0YXRlLlNIT1c7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY2xlYXJUaW1lb3V0KGNvbnRleHQuX3RpbWVvdXQpO1xuICAgICAgY29udGV4dC5faG92ZXJTdGF0ZSA9IEhvdmVyU3RhdGUuU0hPVztcblxuICAgICAgaWYgKCFjb250ZXh0LmNvbmZpZy5kZWxheSB8fCAhY29udGV4dC5jb25maWcuZGVsYXkuc2hvdykge1xuICAgICAgICBjb250ZXh0LnNob3coKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb250ZXh0Ll90aW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChjb250ZXh0Ll9ob3ZlclN0YXRlID09PSBIb3ZlclN0YXRlLlNIT1cpIHtcbiAgICAgICAgICBjb250ZXh0LnNob3coKTtcbiAgICAgICAgfVxuICAgICAgfSwgY29udGV4dC5jb25maWcuZGVsYXkuc2hvdyk7XG4gICAgfTtcblxuICAgIF9wcm90by5fbGVhdmUgPSBmdW5jdGlvbiBfbGVhdmUoZXZlbnQsIGNvbnRleHQpIHtcbiAgICAgIHZhciBkYXRhS2V5ID0gdGhpcy5jb25zdHJ1Y3Rvci5EQVRBX0tFWTtcbiAgICAgIGNvbnRleHQgPSBjb250ZXh0IHx8ICQkJDEoZXZlbnQuY3VycmVudFRhcmdldCkuZGF0YShkYXRhS2V5KTtcblxuICAgICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICAgIGNvbnRleHQgPSBuZXcgdGhpcy5jb25zdHJ1Y3RvcihldmVudC5jdXJyZW50VGFyZ2V0LCB0aGlzLl9nZXREZWxlZ2F0ZUNvbmZpZygpKTtcbiAgICAgICAgJCQkMShldmVudC5jdXJyZW50VGFyZ2V0KS5kYXRhKGRhdGFLZXksIGNvbnRleHQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZXZlbnQpIHtcbiAgICAgICAgY29udGV4dC5fYWN0aXZlVHJpZ2dlcltldmVudC50eXBlID09PSAnZm9jdXNvdXQnID8gVHJpZ2dlci5GT0NVUyA6IFRyaWdnZXIuSE9WRVJdID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGlmIChjb250ZXh0Ll9pc1dpdGhBY3RpdmVUcmlnZ2VyKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjbGVhclRpbWVvdXQoY29udGV4dC5fdGltZW91dCk7XG4gICAgICBjb250ZXh0Ll9ob3ZlclN0YXRlID0gSG92ZXJTdGF0ZS5PVVQ7XG5cbiAgICAgIGlmICghY29udGV4dC5jb25maWcuZGVsYXkgfHwgIWNvbnRleHQuY29uZmlnLmRlbGF5LmhpZGUpIHtcbiAgICAgICAgY29udGV4dC5oaWRlKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgY29udGV4dC5fdGltZW91dCA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoY29udGV4dC5faG92ZXJTdGF0ZSA9PT0gSG92ZXJTdGF0ZS5PVVQpIHtcbiAgICAgICAgICBjb250ZXh0LmhpZGUoKTtcbiAgICAgICAgfVxuICAgICAgfSwgY29udGV4dC5jb25maWcuZGVsYXkuaGlkZSk7XG4gICAgfTtcblxuICAgIF9wcm90by5faXNXaXRoQWN0aXZlVHJpZ2dlciA9IGZ1bmN0aW9uIF9pc1dpdGhBY3RpdmVUcmlnZ2VyKCkge1xuICAgICAgZm9yICh2YXIgdHJpZ2dlciBpbiB0aGlzLl9hY3RpdmVUcmlnZ2VyKSB7XG4gICAgICAgIGlmICh0aGlzLl9hY3RpdmVUcmlnZ2VyW3RyaWdnZXJdKSB7XG4gICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldENvbmZpZyA9IGZ1bmN0aW9uIF9nZXRDb25maWcoY29uZmlnKSB7XG4gICAgICBjb25maWcgPSBfZXh0ZW5kcyh7fSwgdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0LCAkJCQxKHRoaXMuZWxlbWVudCkuZGF0YSgpLCBjb25maWcpO1xuXG4gICAgICBpZiAodHlwZW9mIGNvbmZpZy5kZWxheSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgY29uZmlnLmRlbGF5ID0ge1xuICAgICAgICAgIHNob3c6IGNvbmZpZy5kZWxheSxcbiAgICAgICAgICBoaWRlOiBjb25maWcuZGVsYXlcbiAgICAgICAgfTtcbiAgICAgIH1cblxuICAgICAgaWYgKHR5cGVvZiBjb25maWcudGl0bGUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGNvbmZpZy50aXRsZSA9IGNvbmZpZy50aXRsZS50b1N0cmluZygpO1xuICAgICAgfVxuXG4gICAgICBpZiAodHlwZW9mIGNvbmZpZy5jb250ZW50ID09PSAnbnVtYmVyJykge1xuICAgICAgICBjb25maWcuY29udGVudCA9IGNvbmZpZy5jb250ZW50LnRvU3RyaW5nKCk7XG4gICAgICB9XG5cbiAgICAgIFV0aWwudHlwZUNoZWNrQ29uZmlnKE5BTUUsIGNvbmZpZywgdGhpcy5jb25zdHJ1Y3Rvci5EZWZhdWx0VHlwZSk7XG4gICAgICByZXR1cm4gY29uZmlnO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldERlbGVnYXRlQ29uZmlnID0gZnVuY3Rpb24gX2dldERlbGVnYXRlQ29uZmlnKCkge1xuICAgICAgdmFyIGNvbmZpZyA9IHt9O1xuXG4gICAgICBpZiAodGhpcy5jb25maWcpIHtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuY29uZmlnKSB7XG4gICAgICAgICAgaWYgKHRoaXMuY29uc3RydWN0b3IuRGVmYXVsdFtrZXldICE9PSB0aGlzLmNvbmZpZ1trZXldKSB7XG4gICAgICAgICAgICBjb25maWdba2V5XSA9IHRoaXMuY29uZmlnW2tleV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjb25maWc7XG4gICAgfTtcblxuICAgIF9wcm90by5fY2xlYW5UaXBDbGFzcyA9IGZ1bmN0aW9uIF9jbGVhblRpcENsYXNzKCkge1xuICAgICAgdmFyICR0aXAgPSAkJCQxKHRoaXMuZ2V0VGlwRWxlbWVudCgpKTtcbiAgICAgIHZhciB0YWJDbGFzcyA9ICR0aXAuYXR0cignY2xhc3MnKS5tYXRjaChCU0NMU19QUkVGSVhfUkVHRVgpO1xuXG4gICAgICBpZiAodGFiQ2xhc3MgIT09IG51bGwgJiYgdGFiQ2xhc3MubGVuZ3RoID4gMCkge1xuICAgICAgICAkdGlwLnJlbW92ZUNsYXNzKHRhYkNsYXNzLmpvaW4oJycpKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl9oYW5kbGVQb3BwZXJQbGFjZW1lbnRDaGFuZ2UgPSBmdW5jdGlvbiBfaGFuZGxlUG9wcGVyUGxhY2VtZW50Q2hhbmdlKGRhdGEpIHtcbiAgICAgIHRoaXMuX2NsZWFuVGlwQ2xhc3MoKTtcblxuICAgICAgdGhpcy5hZGRBdHRhY2htZW50Q2xhc3ModGhpcy5fZ2V0QXR0YWNobWVudChkYXRhLnBsYWNlbWVudCkpO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2ZpeFRyYW5zaXRpb24gPSBmdW5jdGlvbiBfZml4VHJhbnNpdGlvbigpIHtcbiAgICAgIHZhciB0aXAgPSB0aGlzLmdldFRpcEVsZW1lbnQoKTtcbiAgICAgIHZhciBpbml0Q29uZmlnQW5pbWF0aW9uID0gdGhpcy5jb25maWcuYW5pbWF0aW9uO1xuXG4gICAgICBpZiAodGlwLmdldEF0dHJpYnV0ZSgneC1wbGFjZW1lbnQnKSAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgICQkJDEodGlwKS5yZW1vdmVDbGFzcyhDbGFzc05hbWUuRkFERSk7XG4gICAgICB0aGlzLmNvbmZpZy5hbmltYXRpb24gPSBmYWxzZTtcbiAgICAgIHRoaXMuaGlkZSgpO1xuICAgICAgdGhpcy5zaG93KCk7XG4gICAgICB0aGlzLmNvbmZpZy5hbmltYXRpb24gPSBpbml0Q29uZmlnQW5pbWF0aW9uO1xuICAgIH07IC8vIHN0YXRpY1xuXG5cbiAgICBUb29sdGlwLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBkYXRhID0gJCQkMSh0aGlzKS5kYXRhKERBVEFfS0VZKTtcblxuICAgICAgICB2YXIgX2NvbmZpZyA9IHR5cGVvZiBjb25maWcgPT09ICdvYmplY3QnICYmIGNvbmZpZztcblxuICAgICAgICBpZiAoIWRhdGEgJiYgL2Rpc3Bvc2V8aGlkZS8udGVzdChjb25maWcpKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgZGF0YSA9IG5ldyBUb29sdGlwKHRoaXMsIF9jb25maWcpO1xuICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZGF0YVtjb25maWddKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfY3JlYXRlQ2xhc3MoVG9vbHRpcCwgbnVsbCwgW3tcbiAgICAgIGtleTogXCJWRVJTSU9OXCIsXG4gICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIFZFUlNJT047XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIkRlZmF1bHRcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gRGVmYXVsdDtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiTkFNRVwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBOQU1FO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJEQVRBX0tFWVwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBEQVRBX0tFWTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiRXZlbnRcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gRXZlbnQ7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIkVWRU5UX0tFWVwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBFVkVOVF9LRVk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIkRlZmF1bHRUeXBlXCIsXG4gICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIERlZmF1bHRUeXBlO1xuICAgICAgfVxuICAgIH1dKTtcbiAgICByZXR1cm4gVG9vbHRpcDtcbiAgfSgpO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIGpRdWVyeVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cblxuICAkJCQxLmZuW05BTUVdID0gVG9vbHRpcC5falF1ZXJ5SW50ZXJmYWNlO1xuICAkJCQxLmZuW05BTUVdLkNvbnN0cnVjdG9yID0gVG9vbHRpcDtcblxuICAkJCQxLmZuW05BTUVdLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgJCQkMS5mbltOQU1FXSA9IEpRVUVSWV9OT19DT05GTElDVDtcbiAgICByZXR1cm4gVG9vbHRpcC5falF1ZXJ5SW50ZXJmYWNlO1xuICB9O1xuXG4gIHJldHVybiBUb29sdGlwO1xufSgkLCBQb3BwZXIpO1xuXG4vKipcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBCb290c3RyYXAgKHY0LjAuMC1iZXRhLjMpOiBwb3BvdmVyLmpzXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG52YXIgUG9wb3ZlciA9IGZ1bmN0aW9uICgkJCQxKSB7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogQ29uc3RhbnRzXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cbiAgdmFyIE5BTUUgPSAncG9wb3Zlcic7XG4gIHZhciBWRVJTSU9OID0gJzQuMC4wLWJldGEuMyc7XG4gIHZhciBEQVRBX0tFWSA9ICdicy5wb3BvdmVyJztcbiAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gIHZhciBKUVVFUllfTk9fQ09ORkxJQ1QgPSAkJCQxLmZuW05BTUVdO1xuICB2YXIgQ0xBU1NfUFJFRklYID0gJ2JzLXBvcG92ZXInO1xuICB2YXIgQlNDTFNfUFJFRklYX1JFR0VYID0gbmV3IFJlZ0V4cChcIihefFxcXFxzKVwiICsgQ0xBU1NfUFJFRklYICsgXCJcXFxcUytcIiwgJ2cnKTtcbiAgdmFyIERlZmF1bHQgPSBfZXh0ZW5kcyh7fSwgVG9vbHRpcC5EZWZhdWx0LCB7XG4gICAgcGxhY2VtZW50OiAncmlnaHQnLFxuICAgIHRyaWdnZXI6ICdjbGljaycsXG4gICAgY29udGVudDogJycsXG4gICAgdGVtcGxhdGU6ICc8ZGl2IGNsYXNzPVwicG9wb3ZlclwiIHJvbGU9XCJ0b29sdGlwXCI+JyArICc8ZGl2IGNsYXNzPVwiYXJyb3dcIj48L2Rpdj4nICsgJzxoMyBjbGFzcz1cInBvcG92ZXItaGVhZGVyXCI+PC9oMz4nICsgJzxkaXYgY2xhc3M9XCJwb3BvdmVyLWJvZHlcIj48L2Rpdj48L2Rpdj4nXG4gIH0pO1xuICB2YXIgRGVmYXVsdFR5cGUgPSBfZXh0ZW5kcyh7fSwgVG9vbHRpcC5EZWZhdWx0VHlwZSwge1xuICAgIGNvbnRlbnQ6ICcoc3RyaW5nfGVsZW1lbnR8ZnVuY3Rpb24pJ1xuICB9KTtcbiAgdmFyIENsYXNzTmFtZSA9IHtcbiAgICBGQURFOiAnZmFkZScsXG4gICAgU0hPVzogJ3Nob3cnXG4gIH07XG4gIHZhciBTZWxlY3RvciA9IHtcbiAgICBUSVRMRTogJy5wb3BvdmVyLWhlYWRlcicsXG4gICAgQ09OVEVOVDogJy5wb3BvdmVyLWJvZHknXG4gIH07XG4gIHZhciBFdmVudCA9IHtcbiAgICBISURFOiBcImhpZGVcIiArIEVWRU5UX0tFWSxcbiAgICBISURERU46IFwiaGlkZGVuXCIgKyBFVkVOVF9LRVksXG4gICAgU0hPVzogXCJzaG93XCIgKyBFVkVOVF9LRVksXG4gICAgU0hPV046IFwic2hvd25cIiArIEVWRU5UX0tFWSxcbiAgICBJTlNFUlRFRDogXCJpbnNlcnRlZFwiICsgRVZFTlRfS0VZLFxuICAgIENMSUNLOiBcImNsaWNrXCIgKyBFVkVOVF9LRVksXG4gICAgRk9DVVNJTjogXCJmb2N1c2luXCIgKyBFVkVOVF9LRVksXG4gICAgRk9DVVNPVVQ6IFwiZm9jdXNvdXRcIiArIEVWRU5UX0tFWSxcbiAgICBNT1VTRUVOVEVSOiBcIm1vdXNlZW50ZXJcIiArIEVWRU5UX0tFWSxcbiAgICBNT1VTRUxFQVZFOiBcIm1vdXNlbGVhdmVcIiArIEVWRU5UX0tFWVxuICAgIC8qKlxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqIENsYXNzIERlZmluaXRpb25cbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKi9cblxuICB9O1xuXG4gIHZhciBQb3BvdmVyID1cbiAgLyojX19QVVJFX18qL1xuICBmdW5jdGlvbiAoX1Rvb2x0aXApIHtcbiAgICBfaW5oZXJpdHNMb29zZShQb3BvdmVyLCBfVG9vbHRpcCk7XG5cbiAgICBmdW5jdGlvbiBQb3BvdmVyKCkge1xuICAgICAgcmV0dXJuIF9Ub29sdGlwLmFwcGx5KHRoaXMsIGFyZ3VtZW50cykgfHwgdGhpcztcbiAgICB9XG5cbiAgICB2YXIgX3Byb3RvID0gUG9wb3Zlci5wcm90b3R5cGU7XG5cbiAgICAvLyBvdmVycmlkZXNcbiAgICBfcHJvdG8uaXNXaXRoQ29udGVudCA9IGZ1bmN0aW9uIGlzV2l0aENvbnRlbnQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5nZXRUaXRsZSgpIHx8IHRoaXMuX2dldENvbnRlbnQoKTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLmFkZEF0dGFjaG1lbnRDbGFzcyA9IGZ1bmN0aW9uIGFkZEF0dGFjaG1lbnRDbGFzcyhhdHRhY2htZW50KSB7XG4gICAgICAkJCQxKHRoaXMuZ2V0VGlwRWxlbWVudCgpKS5hZGRDbGFzcyhDTEFTU19QUkVGSVggKyBcIi1cIiArIGF0dGFjaG1lbnQpO1xuICAgIH07XG5cbiAgICBfcHJvdG8uZ2V0VGlwRWxlbWVudCA9IGZ1bmN0aW9uIGdldFRpcEVsZW1lbnQoKSB7XG4gICAgICB0aGlzLnRpcCA9IHRoaXMudGlwIHx8ICQkJDEodGhpcy5jb25maWcudGVtcGxhdGUpWzBdO1xuICAgICAgcmV0dXJuIHRoaXMudGlwO1xuICAgIH07XG5cbiAgICBfcHJvdG8uc2V0Q29udGVudCA9IGZ1bmN0aW9uIHNldENvbnRlbnQoKSB7XG4gICAgICB2YXIgJHRpcCA9ICQkJDEodGhpcy5nZXRUaXBFbGVtZW50KCkpOyAvLyB3ZSB1c2UgYXBwZW5kIGZvciBodG1sIG9iamVjdHMgdG8gbWFpbnRhaW4ganMgZXZlbnRzXG5cbiAgICAgIHRoaXMuc2V0RWxlbWVudENvbnRlbnQoJHRpcC5maW5kKFNlbGVjdG9yLlRJVExFKSwgdGhpcy5nZXRUaXRsZSgpKTtcblxuICAgICAgdmFyIGNvbnRlbnQgPSB0aGlzLl9nZXRDb250ZW50KCk7XG5cbiAgICAgIGlmICh0eXBlb2YgY29udGVudCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjb250ZW50ID0gY29udGVudC5jYWxsKHRoaXMuZWxlbWVudCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2V0RWxlbWVudENvbnRlbnQoJHRpcC5maW5kKFNlbGVjdG9yLkNPTlRFTlQpLCBjb250ZW50KTtcbiAgICAgICR0aXAucmVtb3ZlQ2xhc3MoQ2xhc3NOYW1lLkZBREUgKyBcIiBcIiArIENsYXNzTmFtZS5TSE9XKTtcbiAgICB9OyAvLyBwcml2YXRlXG5cblxuICAgIF9wcm90by5fZ2V0Q29udGVudCA9IGZ1bmN0aW9uIF9nZXRDb250ZW50KCkge1xuICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtY29udGVudCcpIHx8IHRoaXMuY29uZmlnLmNvbnRlbnQ7XG4gICAgfTtcblxuICAgIF9wcm90by5fY2xlYW5UaXBDbGFzcyA9IGZ1bmN0aW9uIF9jbGVhblRpcENsYXNzKCkge1xuICAgICAgdmFyICR0aXAgPSAkJCQxKHRoaXMuZ2V0VGlwRWxlbWVudCgpKTtcbiAgICAgIHZhciB0YWJDbGFzcyA9ICR0aXAuYXR0cignY2xhc3MnKS5tYXRjaChCU0NMU19QUkVGSVhfUkVHRVgpO1xuXG4gICAgICBpZiAodGFiQ2xhc3MgIT09IG51bGwgJiYgdGFiQ2xhc3MubGVuZ3RoID4gMCkge1xuICAgICAgICAkdGlwLnJlbW92ZUNsYXNzKHRhYkNsYXNzLmpvaW4oJycpKTtcbiAgICAgIH1cbiAgICB9OyAvLyBzdGF0aWNcblxuXG4gICAgUG9wb3Zlci5falF1ZXJ5SW50ZXJmYWNlID0gZnVuY3Rpb24gX2pRdWVyeUludGVyZmFjZShjb25maWcpIHtcbiAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZGF0YSA9ICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgdmFyIF9jb25maWcgPSB0eXBlb2YgY29uZmlnID09PSAnb2JqZWN0JyA/IGNvbmZpZyA6IG51bGw7XG5cbiAgICAgICAgaWYgKCFkYXRhICYmIC9kZXN0cm95fGhpZGUvLnRlc3QoY29uZmlnKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgIGRhdGEgPSBuZXcgUG9wb3Zlcih0aGlzLCBfY29uZmlnKTtcbiAgICAgICAgICAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVksIGRhdGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBjb25maWcgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgaWYgKHR5cGVvZiBkYXRhW2NvbmZpZ10gPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBtZXRob2QgbmFtZWQgXFxcIlwiICsgY29uZmlnICsgXCJcXFwiXCIpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGRhdGFbY29uZmlnXSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgX2NyZWF0ZUNsYXNzKFBvcG92ZXIsIG51bGwsIFt7XG4gICAgICBrZXk6IFwiVkVSU0lPTlwiLFxuICAgICAgLy8gZ2V0dGVyc1xuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBWRVJTSU9OO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJEZWZhdWx0XCIsXG4gICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIERlZmF1bHQ7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIk5BTUVcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gTkFNRTtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiREFUQV9LRVlcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gREFUQV9LRVk7XG4gICAgICB9XG4gICAgfSwge1xuICAgICAga2V5OiBcIkV2ZW50XCIsXG4gICAgICBnZXQ6IGZ1bmN0aW9uIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIEV2ZW50O1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJFVkVOVF9LRVlcIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gRVZFTlRfS0VZO1xuICAgICAgfVxuICAgIH0sIHtcbiAgICAgIGtleTogXCJEZWZhdWx0VHlwZVwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBEZWZhdWx0VHlwZTtcbiAgICAgIH1cbiAgICB9XSk7XG4gICAgcmV0dXJuIFBvcG92ZXI7XG4gIH0oVG9vbHRpcCk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuXG4gICQkJDEuZm5bTkFNRV0gPSBQb3BvdmVyLl9qUXVlcnlJbnRlcmZhY2U7XG4gICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBQb3BvdmVyO1xuXG4gICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgIHJldHVybiBQb3BvdmVyLl9qUXVlcnlJbnRlcmZhY2U7XG4gIH07XG5cbiAgcmV0dXJuIFBvcG92ZXI7XG59KCQpO1xuXG4vKipcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBCb290c3RyYXAgKHY0LjAuMC1iZXRhLjMpOiBzY3JvbGxzcHkuanNcbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbnZhciBTY3JvbGxTcHkgPSBmdW5jdGlvbiAoJCQkMSkge1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIENvbnN0YW50c1xuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG4gIHZhciBOQU1FID0gJ3Njcm9sbHNweSc7XG4gIHZhciBWRVJTSU9OID0gJzQuMC4wLWJldGEuMyc7XG4gIHZhciBEQVRBX0tFWSA9ICdicy5zY3JvbGxzcHknO1xuICB2YXIgRVZFTlRfS0VZID0gXCIuXCIgKyBEQVRBX0tFWTtcbiAgdmFyIERBVEFfQVBJX0tFWSA9ICcuZGF0YS1hcGknO1xuICB2YXIgSlFVRVJZX05PX0NPTkZMSUNUID0gJCQkMS5mbltOQU1FXTtcbiAgdmFyIERlZmF1bHQgPSB7XG4gICAgb2Zmc2V0OiAxMCxcbiAgICBtZXRob2Q6ICdhdXRvJyxcbiAgICB0YXJnZXQ6ICcnXG4gIH07XG4gIHZhciBEZWZhdWx0VHlwZSA9IHtcbiAgICBvZmZzZXQ6ICdudW1iZXInLFxuICAgIG1ldGhvZDogJ3N0cmluZycsXG4gICAgdGFyZ2V0OiAnKHN0cmluZ3xlbGVtZW50KSdcbiAgfTtcbiAgdmFyIEV2ZW50ID0ge1xuICAgIEFDVElWQVRFOiBcImFjdGl2YXRlXCIgKyBFVkVOVF9LRVksXG4gICAgU0NST0xMOiBcInNjcm9sbFwiICsgRVZFTlRfS0VZLFxuICAgIExPQURfREFUQV9BUEk6IFwibG9hZFwiICsgRVZFTlRfS0VZICsgREFUQV9BUElfS0VZXG4gIH07XG4gIHZhciBDbGFzc05hbWUgPSB7XG4gICAgRFJPUERPV05fSVRFTTogJ2Ryb3Bkb3duLWl0ZW0nLFxuICAgIERST1BET1dOX01FTlU6ICdkcm9wZG93bi1tZW51JyxcbiAgICBBQ1RJVkU6ICdhY3RpdmUnXG4gIH07XG4gIHZhciBTZWxlY3RvciA9IHtcbiAgICBEQVRBX1NQWTogJ1tkYXRhLXNweT1cInNjcm9sbFwiXScsXG4gICAgQUNUSVZFOiAnLmFjdGl2ZScsXG4gICAgTkFWX0xJU1RfR1JPVVA6ICcubmF2LCAubGlzdC1ncm91cCcsXG4gICAgTkFWX0xJTktTOiAnLm5hdi1saW5rJyxcbiAgICBOQVZfSVRFTVM6ICcubmF2LWl0ZW0nLFxuICAgIExJU1RfSVRFTVM6ICcubGlzdC1ncm91cC1pdGVtJyxcbiAgICBEUk9QRE9XTjogJy5kcm9wZG93bicsXG4gICAgRFJPUERPV05fSVRFTVM6ICcuZHJvcGRvd24taXRlbScsXG4gICAgRFJPUERPV05fVE9HR0xFOiAnLmRyb3Bkb3duLXRvZ2dsZSdcbiAgfTtcbiAgdmFyIE9mZnNldE1ldGhvZCA9IHtcbiAgICBPRkZTRVQ6ICdvZmZzZXQnLFxuICAgIFBPU0lUSU9OOiAncG9zaXRpb24nXG4gICAgLyoqXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICogQ2xhc3MgRGVmaW5pdGlvblxuICAgICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAqL1xuXG4gIH07XG5cbiAgdmFyIFNjcm9sbFNweSA9XG4gIC8qI19fUFVSRV9fKi9cbiAgZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNjcm9sbFNweShlbGVtZW50LCBjb25maWcpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgICAgdGhpcy5fc2Nyb2xsRWxlbWVudCA9IGVsZW1lbnQudGFnTmFtZSA9PT0gJ0JPRFknID8gd2luZG93IDogZWxlbWVudDtcbiAgICAgIHRoaXMuX2NvbmZpZyA9IHRoaXMuX2dldENvbmZpZyhjb25maWcpO1xuICAgICAgdGhpcy5fc2VsZWN0b3IgPSB0aGlzLl9jb25maWcudGFyZ2V0ICsgXCIgXCIgKyBTZWxlY3Rvci5OQVZfTElOS1MgKyBcIixcIiArICh0aGlzLl9jb25maWcudGFyZ2V0ICsgXCIgXCIgKyBTZWxlY3Rvci5MSVNUX0lURU1TICsgXCIsXCIpICsgKHRoaXMuX2NvbmZpZy50YXJnZXQgKyBcIiBcIiArIFNlbGVjdG9yLkRST1BET1dOX0lURU1TKTtcbiAgICAgIHRoaXMuX29mZnNldHMgPSBbXTtcbiAgICAgIHRoaXMuX3RhcmdldHMgPSBbXTtcbiAgICAgIHRoaXMuX2FjdGl2ZVRhcmdldCA9IG51bGw7XG4gICAgICB0aGlzLl9zY3JvbGxIZWlnaHQgPSAwO1xuICAgICAgJCQkMSh0aGlzLl9zY3JvbGxFbGVtZW50KS5vbihFdmVudC5TQ1JPTEwsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICByZXR1cm4gX3RoaXMuX3Byb2Nlc3MoZXZlbnQpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLnJlZnJlc2goKTtcblxuICAgICAgdGhpcy5fcHJvY2VzcygpO1xuICAgIH0gLy8gZ2V0dGVyc1xuXG5cbiAgICB2YXIgX3Byb3RvID0gU2Nyb2xsU3B5LnByb3RvdHlwZTtcblxuICAgIC8vIHB1YmxpY1xuICAgIF9wcm90by5yZWZyZXNoID0gZnVuY3Rpb24gcmVmcmVzaCgpIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgYXV0b01ldGhvZCA9IHRoaXMuX3Njcm9sbEVsZW1lbnQgIT09IHRoaXMuX3Njcm9sbEVsZW1lbnQud2luZG93ID8gT2Zmc2V0TWV0aG9kLlBPU0lUSU9OIDogT2Zmc2V0TWV0aG9kLk9GRlNFVDtcbiAgICAgIHZhciBvZmZzZXRNZXRob2QgPSB0aGlzLl9jb25maWcubWV0aG9kID09PSAnYXV0bycgPyBhdXRvTWV0aG9kIDogdGhpcy5fY29uZmlnLm1ldGhvZDtcbiAgICAgIHZhciBvZmZzZXRCYXNlID0gb2Zmc2V0TWV0aG9kID09PSBPZmZzZXRNZXRob2QuUE9TSVRJT04gPyB0aGlzLl9nZXRTY3JvbGxUb3AoKSA6IDA7XG4gICAgICB0aGlzLl9vZmZzZXRzID0gW107XG4gICAgICB0aGlzLl90YXJnZXRzID0gW107XG4gICAgICB0aGlzLl9zY3JvbGxIZWlnaHQgPSB0aGlzLl9nZXRTY3JvbGxIZWlnaHQoKTtcbiAgICAgIHZhciB0YXJnZXRzID0gJCQkMS5tYWtlQXJyYXkoJCQkMSh0aGlzLl9zZWxlY3RvcikpO1xuICAgICAgdGFyZ2V0cy5tYXAoZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAgICAgdmFyIHRhcmdldDtcbiAgICAgICAgdmFyIHRhcmdldFNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KGVsZW1lbnQpO1xuXG4gICAgICAgIGlmICh0YXJnZXRTZWxlY3Rvcikge1xuICAgICAgICAgIHRhcmdldCA9ICQkJDEodGFyZ2V0U2VsZWN0b3IpWzBdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRhcmdldCkge1xuICAgICAgICAgIHZhciB0YXJnZXRCQ1IgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cbiAgICAgICAgICBpZiAodGFyZ2V0QkNSLndpZHRoIHx8IHRhcmdldEJDUi5oZWlnaHQpIHtcbiAgICAgICAgICAgIC8vIHRvZG8gKGZhdCk6IHJlbW92ZSBza2V0Y2ggcmVsaWFuY2Ugb24galF1ZXJ5IHBvc2l0aW9uL29mZnNldFxuICAgICAgICAgICAgcmV0dXJuIFskJCQxKHRhcmdldClbb2Zmc2V0TWV0aG9kXSgpLnRvcCArIG9mZnNldEJhc2UsIHRhcmdldFNlbGVjdG9yXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH0pLmZpbHRlcihmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICByZXR1cm4gaXRlbTtcbiAgICAgIH0pLnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIGFbMF0gLSBiWzBdO1xuICAgICAgfSkuZm9yRWFjaChmdW5jdGlvbiAoaXRlbSkge1xuICAgICAgICBfdGhpczIuX29mZnNldHMucHVzaChpdGVtWzBdKTtcblxuICAgICAgICBfdGhpczIuX3RhcmdldHMucHVzaChpdGVtWzFdKTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfcHJvdG8uZGlzcG9zZSA9IGZ1bmN0aW9uIGRpc3Bvc2UoKSB7XG4gICAgICAkJCQxLnJlbW92ZURhdGEodGhpcy5fZWxlbWVudCwgREFUQV9LRVkpO1xuICAgICAgJCQkMSh0aGlzLl9zY3JvbGxFbGVtZW50KS5vZmYoRVZFTlRfS0VZKTtcbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBudWxsO1xuICAgICAgdGhpcy5fc2Nyb2xsRWxlbWVudCA9IG51bGw7XG4gICAgICB0aGlzLl9jb25maWcgPSBudWxsO1xuICAgICAgdGhpcy5fc2VsZWN0b3IgPSBudWxsO1xuICAgICAgdGhpcy5fb2Zmc2V0cyA9IG51bGw7XG4gICAgICB0aGlzLl90YXJnZXRzID0gbnVsbDtcbiAgICAgIHRoaXMuX2FjdGl2ZVRhcmdldCA9IG51bGw7XG4gICAgICB0aGlzLl9zY3JvbGxIZWlnaHQgPSBudWxsO1xuICAgIH07IC8vIHByaXZhdGVcblxuXG4gICAgX3Byb3RvLl9nZXRDb25maWcgPSBmdW5jdGlvbiBfZ2V0Q29uZmlnKGNvbmZpZykge1xuICAgICAgY29uZmlnID0gX2V4dGVuZHMoe30sIERlZmF1bHQsIGNvbmZpZyk7XG5cbiAgICAgIGlmICh0eXBlb2YgY29uZmlnLnRhcmdldCAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdmFyIGlkID0gJCQkMShjb25maWcudGFyZ2V0KS5hdHRyKCdpZCcpO1xuXG4gICAgICAgIGlmICghaWQpIHtcbiAgICAgICAgICBpZCA9IFV0aWwuZ2V0VUlEKE5BTUUpO1xuICAgICAgICAgICQkJDEoY29uZmlnLnRhcmdldCkuYXR0cignaWQnLCBpZCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25maWcudGFyZ2V0ID0gXCIjXCIgKyBpZDtcbiAgICAgIH1cblxuICAgICAgVXRpbC50eXBlQ2hlY2tDb25maWcoTkFNRSwgY29uZmlnLCBEZWZhdWx0VHlwZSk7XG4gICAgICByZXR1cm4gY29uZmlnO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldFNjcm9sbFRvcCA9IGZ1bmN0aW9uIF9nZXRTY3JvbGxUb3AoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fc2Nyb2xsRWxlbWVudCA9PT0gd2luZG93ID8gdGhpcy5fc2Nyb2xsRWxlbWVudC5wYWdlWU9mZnNldCA6IHRoaXMuX3Njcm9sbEVsZW1lbnQuc2Nyb2xsVG9wO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldFNjcm9sbEhlaWdodCA9IGZ1bmN0aW9uIF9nZXRTY3JvbGxIZWlnaHQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fc2Nyb2xsRWxlbWVudC5zY3JvbGxIZWlnaHQgfHwgTWF0aC5tYXgoZG9jdW1lbnQuYm9keS5zY3JvbGxIZWlnaHQsIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zY3JvbGxIZWlnaHQpO1xuICAgIH07XG5cbiAgICBfcHJvdG8uX2dldE9mZnNldEhlaWdodCA9IGZ1bmN0aW9uIF9nZXRPZmZzZXRIZWlnaHQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5fc2Nyb2xsRWxlbWVudCA9PT0gd2luZG93ID8gd2luZG93LmlubmVySGVpZ2h0IDogdGhpcy5fc2Nyb2xsRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5oZWlnaHQ7XG4gICAgfTtcblxuICAgIF9wcm90by5fcHJvY2VzcyA9IGZ1bmN0aW9uIF9wcm9jZXNzKCkge1xuICAgICAgdmFyIHNjcm9sbFRvcCA9IHRoaXMuX2dldFNjcm9sbFRvcCgpICsgdGhpcy5fY29uZmlnLm9mZnNldDtcblxuICAgICAgdmFyIHNjcm9sbEhlaWdodCA9IHRoaXMuX2dldFNjcm9sbEhlaWdodCgpO1xuXG4gICAgICB2YXIgbWF4U2Nyb2xsID0gdGhpcy5fY29uZmlnLm9mZnNldCArIHNjcm9sbEhlaWdodCAtIHRoaXMuX2dldE9mZnNldEhlaWdodCgpO1xuXG4gICAgICBpZiAodGhpcy5fc2Nyb2xsSGVpZ2h0ICE9PSBzY3JvbGxIZWlnaHQpIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoKCk7XG4gICAgICB9XG5cbiAgICAgIGlmIChzY3JvbGxUb3AgPj0gbWF4U2Nyb2xsKSB7XG4gICAgICAgIHZhciB0YXJnZXQgPSB0aGlzLl90YXJnZXRzW3RoaXMuX3RhcmdldHMubGVuZ3RoIC0gMV07XG5cbiAgICAgICAgaWYgKHRoaXMuX2FjdGl2ZVRhcmdldCAhPT0gdGFyZ2V0KSB7XG4gICAgICAgICAgdGhpcy5fYWN0aXZhdGUodGFyZ2V0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMuX2FjdGl2ZVRhcmdldCAmJiBzY3JvbGxUb3AgPCB0aGlzLl9vZmZzZXRzWzBdICYmIHRoaXMuX29mZnNldHNbMF0gPiAwKSB7XG4gICAgICAgIHRoaXMuX2FjdGl2ZVRhcmdldCA9IG51bGw7XG5cbiAgICAgICAgdGhpcy5fY2xlYXIoKTtcblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGZvciAodmFyIGkgPSB0aGlzLl9vZmZzZXRzLmxlbmd0aDsgaS0tOykge1xuICAgICAgICB2YXIgaXNBY3RpdmVUYXJnZXQgPSB0aGlzLl9hY3RpdmVUYXJnZXQgIT09IHRoaXMuX3RhcmdldHNbaV0gJiYgc2Nyb2xsVG9wID49IHRoaXMuX29mZnNldHNbaV0gJiYgKHR5cGVvZiB0aGlzLl9vZmZzZXRzW2kgKyAxXSA9PT0gJ3VuZGVmaW5lZCcgfHwgc2Nyb2xsVG9wIDwgdGhpcy5fb2Zmc2V0c1tpICsgMV0pO1xuXG4gICAgICAgIGlmIChpc0FjdGl2ZVRhcmdldCkge1xuICAgICAgICAgIHRoaXMuX2FjdGl2YXRlKHRoaXMuX3RhcmdldHNbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by5fYWN0aXZhdGUgPSBmdW5jdGlvbiBfYWN0aXZhdGUodGFyZ2V0KSB7XG4gICAgICB0aGlzLl9hY3RpdmVUYXJnZXQgPSB0YXJnZXQ7XG5cbiAgICAgIHRoaXMuX2NsZWFyKCk7XG5cbiAgICAgIHZhciBxdWVyaWVzID0gdGhpcy5fc2VsZWN0b3Iuc3BsaXQoJywnKTsgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGFycm93LWJvZHktc3R5bGVcblxuXG4gICAgICBxdWVyaWVzID0gcXVlcmllcy5tYXAoZnVuY3Rpb24gKHNlbGVjdG9yKSB7XG4gICAgICAgIHJldHVybiBzZWxlY3RvciArIFwiW2RhdGEtdGFyZ2V0PVxcXCJcIiArIHRhcmdldCArIFwiXFxcIl0sXCIgKyAoc2VsZWN0b3IgKyBcIltocmVmPVxcXCJcIiArIHRhcmdldCArIFwiXFxcIl1cIik7XG4gICAgICB9KTtcbiAgICAgIHZhciAkbGluayA9ICQkJDEocXVlcmllcy5qb2luKCcsJykpO1xuXG4gICAgICBpZiAoJGxpbmsuaGFzQ2xhc3MoQ2xhc3NOYW1lLkRST1BET1dOX0lURU0pKSB7XG4gICAgICAgICRsaW5rLmNsb3Nlc3QoU2VsZWN0b3IuRFJPUERPV04pLmZpbmQoU2VsZWN0b3IuRFJPUERPV05fVE9HR0xFKS5hZGRDbGFzcyhDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgJGxpbmsuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBTZXQgdHJpZ2dlcmVkIGxpbmsgYXMgYWN0aXZlXG4gICAgICAgICRsaW5rLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpOyAvLyBTZXQgdHJpZ2dlcmVkIGxpbmtzIHBhcmVudHMgYXMgYWN0aXZlXG4gICAgICAgIC8vIFdpdGggYm90aCA8dWw+IGFuZCA8bmF2PiBtYXJrdXAgYSBwYXJlbnQgaXMgdGhlIHByZXZpb3VzIHNpYmxpbmcgb2YgYW55IG5hdiBhbmNlc3RvclxuXG4gICAgICAgICRsaW5rLnBhcmVudHMoU2VsZWN0b3IuTkFWX0xJU1RfR1JPVVApLnByZXYoU2VsZWN0b3IuTkFWX0xJTktTICsgXCIsIFwiICsgU2VsZWN0b3IuTElTVF9JVEVNUykuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7IC8vIEhhbmRsZSBzcGVjaWFsIGNhc2Ugd2hlbiAubmF2LWxpbmsgaXMgaW5zaWRlIC5uYXYtaXRlbVxuXG4gICAgICAgICRsaW5rLnBhcmVudHMoU2VsZWN0b3IuTkFWX0xJU1RfR1JPVVApLnByZXYoU2VsZWN0b3IuTkFWX0lURU1TKS5jaGlsZHJlbihTZWxlY3Rvci5OQVZfTElOS1MpLmFkZENsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgfVxuXG4gICAgICAkJCQxKHRoaXMuX3Njcm9sbEVsZW1lbnQpLnRyaWdnZXIoRXZlbnQuQUNUSVZBVEUsIHtcbiAgICAgICAgcmVsYXRlZFRhcmdldDogdGFyZ2V0XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgX3Byb3RvLl9jbGVhciA9IGZ1bmN0aW9uIF9jbGVhcigpIHtcbiAgICAgICQkJDEodGhpcy5fc2VsZWN0b3IpLmZpbHRlcihTZWxlY3Rvci5BQ1RJVkUpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgIH07IC8vIHN0YXRpY1xuXG5cbiAgICBTY3JvbGxTcHkuX2pRdWVyeUludGVyZmFjZSA9IGZ1bmN0aW9uIF9qUXVlcnlJbnRlcmZhY2UoY29uZmlnKSB7XG4gICAgICByZXR1cm4gdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGRhdGEgPSAkJCQxKHRoaXMpLmRhdGEoREFUQV9LRVkpO1xuXG4gICAgICAgIHZhciBfY29uZmlnID0gdHlwZW9mIGNvbmZpZyA9PT0gJ29iamVjdCcgJiYgY29uZmlnO1xuXG4gICAgICAgIGlmICghZGF0YSkge1xuICAgICAgICAgIGRhdGEgPSBuZXcgU2Nyb2xsU3B5KHRoaXMsIF9jb25maWcpO1xuICAgICAgICAgICQkJDEodGhpcykuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZGF0YVtjb25maWddKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfY3JlYXRlQ2xhc3MoU2Nyb2xsU3B5LCBudWxsLCBbe1xuICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgIH1cbiAgICB9LCB7XG4gICAgICBrZXk6IFwiRGVmYXVsdFwiLFxuICAgICAgZ2V0OiBmdW5jdGlvbiBnZXQoKSB7XG4gICAgICAgIHJldHVybiBEZWZhdWx0O1xuICAgICAgfVxuICAgIH1dKTtcbiAgICByZXR1cm4gU2Nyb2xsU3B5O1xuICB9KCk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogRGF0YSBBcGkgaW1wbGVtZW50YXRpb25cbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuXG5cbiAgJCQkMSh3aW5kb3cpLm9uKEV2ZW50LkxPQURfREFUQV9BUEksIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2Nyb2xsU3B5cyA9ICQkJDEubWFrZUFycmF5KCQkJDEoU2VsZWN0b3IuREFUQV9TUFkpKTtcblxuICAgIGZvciAodmFyIGkgPSBzY3JvbGxTcHlzLmxlbmd0aDsgaS0tOykge1xuICAgICAgdmFyICRzcHkgPSAkJCQxKHNjcm9sbFNweXNbaV0pO1xuXG4gICAgICBTY3JvbGxTcHkuX2pRdWVyeUludGVyZmFjZS5jYWxsKCRzcHksICRzcHkuZGF0YSgpKTtcbiAgICB9XG4gIH0pO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIGpRdWVyeVxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICovXG5cbiAgJCQkMS5mbltOQU1FXSA9IFNjcm9sbFNweS5falF1ZXJ5SW50ZXJmYWNlO1xuICAkJCQxLmZuW05BTUVdLkNvbnN0cnVjdG9yID0gU2Nyb2xsU3B5O1xuXG4gICQkJDEuZm5bTkFNRV0ubm9Db25mbGljdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAkJCQxLmZuW05BTUVdID0gSlFVRVJZX05PX0NPTkZMSUNUO1xuICAgIHJldHVybiBTY3JvbGxTcHkuX2pRdWVyeUludGVyZmFjZTtcbiAgfTtcblxuICByZXR1cm4gU2Nyb2xsU3B5O1xufSgkKTtcblxuLyoqXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICogQm9vdHN0cmFwICh2NC4wLjAtYmV0YS4zKTogdGFiLmpzXG4gKiBMaWNlbnNlZCB1bmRlciBNSVQgKGh0dHBzOi8vZ2l0aHViLmNvbS90d2JzL2Jvb3RzdHJhcC9ibG9iL21hc3Rlci9MSUNFTlNFKVxuICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqL1xuXG52YXIgVGFiID0gZnVuY3Rpb24gKCQkJDEpIHtcbiAgLyoqXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKiBDb25zdGFudHNcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqL1xuICB2YXIgTkFNRSA9ICd0YWInO1xuICB2YXIgVkVSU0lPTiA9ICc0LjAuMC1iZXRhLjMnO1xuICB2YXIgREFUQV9LRVkgPSAnYnMudGFiJztcbiAgdmFyIEVWRU5UX0tFWSA9IFwiLlwiICsgREFUQV9LRVk7XG4gIHZhciBEQVRBX0FQSV9LRVkgPSAnLmRhdGEtYXBpJztcbiAgdmFyIEpRVUVSWV9OT19DT05GTElDVCA9ICQkJDEuZm5bTkFNRV07XG4gIHZhciBUUkFOU0lUSU9OX0RVUkFUSU9OID0gMTUwO1xuICB2YXIgRXZlbnQgPSB7XG4gICAgSElERTogXCJoaWRlXCIgKyBFVkVOVF9LRVksXG4gICAgSElEREVOOiBcImhpZGRlblwiICsgRVZFTlRfS0VZLFxuICAgIFNIT1c6IFwic2hvd1wiICsgRVZFTlRfS0VZLFxuICAgIFNIT1dOOiBcInNob3duXCIgKyBFVkVOVF9LRVksXG4gICAgQ0xJQ0tfREFUQV9BUEk6IFwiY2xpY2tcIiArIEVWRU5UX0tFWSArIERBVEFfQVBJX0tFWVxuICB9O1xuICB2YXIgQ2xhc3NOYW1lID0ge1xuICAgIERST1BET1dOX01FTlU6ICdkcm9wZG93bi1tZW51JyxcbiAgICBBQ1RJVkU6ICdhY3RpdmUnLFxuICAgIERJU0FCTEVEOiAnZGlzYWJsZWQnLFxuICAgIEZBREU6ICdmYWRlJyxcbiAgICBTSE9XOiAnc2hvdydcbiAgfTtcbiAgdmFyIFNlbGVjdG9yID0ge1xuICAgIERST1BET1dOOiAnLmRyb3Bkb3duJyxcbiAgICBOQVZfTElTVF9HUk9VUDogJy5uYXYsIC5saXN0LWdyb3VwJyxcbiAgICBBQ1RJVkU6ICcuYWN0aXZlJyxcbiAgICBBQ1RJVkVfVUw6ICc+IGxpID4gLmFjdGl2ZScsXG4gICAgREFUQV9UT0dHTEU6ICdbZGF0YS10b2dnbGU9XCJ0YWJcIl0sIFtkYXRhLXRvZ2dsZT1cInBpbGxcIl0sIFtkYXRhLXRvZ2dsZT1cImxpc3RcIl0nLFxuICAgIERST1BET1dOX1RPR0dMRTogJy5kcm9wZG93bi10b2dnbGUnLFxuICAgIERST1BET1dOX0FDVElWRV9DSElMRDogJz4gLmRyb3Bkb3duLW1lbnUgLmFjdGl2ZSdcbiAgICAvKipcbiAgICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgKiBDbGFzcyBEZWZpbml0aW9uXG4gICAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICovXG5cbiAgfTtcblxuICB2YXIgVGFiID1cbiAgLyojX19QVVJFX18qL1xuICBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gVGFiKGVsZW1lbnQpIHtcbiAgICAgIHRoaXMuX2VsZW1lbnQgPSBlbGVtZW50O1xuICAgIH0gLy8gZ2V0dGVyc1xuXG5cbiAgICB2YXIgX3Byb3RvID0gVGFiLnByb3RvdHlwZTtcblxuICAgIC8vIHB1YmxpY1xuICAgIF9wcm90by5zaG93ID0gZnVuY3Rpb24gc2hvdygpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIGlmICh0aGlzLl9lbGVtZW50LnBhcmVudE5vZGUgJiYgdGhpcy5fZWxlbWVudC5wYXJlbnROb2RlLm5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSAmJiAkJCQxKHRoaXMuX2VsZW1lbnQpLmhhc0NsYXNzKENsYXNzTmFtZS5BQ1RJVkUpIHx8ICQkJDEodGhpcy5fZWxlbWVudCkuaGFzQ2xhc3MoQ2xhc3NOYW1lLkRJU0FCTEVEKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciB0YXJnZXQ7XG4gICAgICB2YXIgcHJldmlvdXM7XG4gICAgICB2YXIgbGlzdEVsZW1lbnQgPSAkJCQxKHRoaXMuX2VsZW1lbnQpLmNsb3Nlc3QoU2VsZWN0b3IuTkFWX0xJU1RfR1JPVVApWzBdO1xuICAgICAgdmFyIHNlbGVjdG9yID0gVXRpbC5nZXRTZWxlY3RvckZyb21FbGVtZW50KHRoaXMuX2VsZW1lbnQpO1xuXG4gICAgICBpZiAobGlzdEVsZW1lbnQpIHtcbiAgICAgICAgdmFyIGl0ZW1TZWxlY3RvciA9IGxpc3RFbGVtZW50Lm5vZGVOYW1lID09PSAnVUwnID8gU2VsZWN0b3IuQUNUSVZFX1VMIDogU2VsZWN0b3IuQUNUSVZFO1xuICAgICAgICBwcmV2aW91cyA9ICQkJDEubWFrZUFycmF5KCQkJDEobGlzdEVsZW1lbnQpLmZpbmQoaXRlbVNlbGVjdG9yKSk7XG4gICAgICAgIHByZXZpb3VzID0gcHJldmlvdXNbcHJldmlvdXMubGVuZ3RoIC0gMV07XG4gICAgICB9XG5cbiAgICAgIHZhciBoaWRlRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LkhJREUsIHtcbiAgICAgICAgcmVsYXRlZFRhcmdldDogdGhpcy5fZWxlbWVudFxuICAgICAgfSk7XG4gICAgICB2YXIgc2hvd0V2ZW50ID0gJCQkMS5FdmVudChFdmVudC5TSE9XLCB7XG4gICAgICAgIHJlbGF0ZWRUYXJnZXQ6IHByZXZpb3VzXG4gICAgICB9KTtcblxuICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgICQkJDEocHJldmlvdXMpLnRyaWdnZXIoaGlkZUV2ZW50KTtcbiAgICAgIH1cblxuICAgICAgJCQkMSh0aGlzLl9lbGVtZW50KS50cmlnZ2VyKHNob3dFdmVudCk7XG5cbiAgICAgIGlmIChzaG93RXZlbnQuaXNEZWZhdWx0UHJldmVudGVkKCkgfHwgaGlkZUV2ZW50LmlzRGVmYXVsdFByZXZlbnRlZCgpKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHNlbGVjdG9yKSB7XG4gICAgICAgIHRhcmdldCA9ICQkJDEoc2VsZWN0b3IpWzBdO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl9hY3RpdmF0ZSh0aGlzLl9lbGVtZW50LCBsaXN0RWxlbWVudCk7XG5cbiAgICAgIHZhciBjb21wbGV0ZSA9IGZ1bmN0aW9uIGNvbXBsZXRlKCkge1xuICAgICAgICB2YXIgaGlkZGVuRXZlbnQgPSAkJCQxLkV2ZW50KEV2ZW50LkhJRERFTiwge1xuICAgICAgICAgIHJlbGF0ZWRUYXJnZXQ6IF90aGlzLl9lbGVtZW50XG4gICAgICAgIH0pO1xuICAgICAgICB2YXIgc2hvd25FdmVudCA9ICQkJDEuRXZlbnQoRXZlbnQuU0hPV04sIHtcbiAgICAgICAgICByZWxhdGVkVGFyZ2V0OiBwcmV2aW91c1xuICAgICAgICB9KTtcbiAgICAgICAgJCQkMShwcmV2aW91cykudHJpZ2dlcihoaWRkZW5FdmVudCk7XG4gICAgICAgICQkJDEoX3RoaXMuX2VsZW1lbnQpLnRyaWdnZXIoc2hvd25FdmVudCk7XG4gICAgICB9O1xuXG4gICAgICBpZiAodGFyZ2V0KSB7XG4gICAgICAgIHRoaXMuX2FjdGl2YXRlKHRhcmdldCwgdGFyZ2V0LnBhcmVudE5vZGUsIGNvbXBsZXRlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbXBsZXRlKCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF9wcm90by5kaXNwb3NlID0gZnVuY3Rpb24gZGlzcG9zZSgpIHtcbiAgICAgICQkJDEucmVtb3ZlRGF0YSh0aGlzLl9lbGVtZW50LCBEQVRBX0tFWSk7XG4gICAgICB0aGlzLl9lbGVtZW50ID0gbnVsbDtcbiAgICB9OyAvLyBwcml2YXRlXG5cblxuICAgIF9wcm90by5fYWN0aXZhdGUgPSBmdW5jdGlvbiBfYWN0aXZhdGUoZWxlbWVudCwgY29udGFpbmVyLCBjYWxsYmFjaykge1xuICAgICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICAgIHZhciBhY3RpdmVFbGVtZW50cztcblxuICAgICAgaWYgKGNvbnRhaW5lci5ub2RlTmFtZSA9PT0gJ1VMJykge1xuICAgICAgICBhY3RpdmVFbGVtZW50cyA9ICQkJDEoY29udGFpbmVyKS5maW5kKFNlbGVjdG9yLkFDVElWRV9VTCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBhY3RpdmVFbGVtZW50cyA9ICQkJDEoY29udGFpbmVyKS5jaGlsZHJlbihTZWxlY3Rvci5BQ1RJVkUpO1xuICAgICAgfVxuXG4gICAgICB2YXIgYWN0aXZlID0gYWN0aXZlRWxlbWVudHNbMF07XG4gICAgICB2YXIgaXNUcmFuc2l0aW9uaW5nID0gY2FsbGJhY2sgJiYgVXRpbC5zdXBwb3J0c1RyYW5zaXRpb25FbmQoKSAmJiBhY3RpdmUgJiYgJCQkMShhY3RpdmUpLmhhc0NsYXNzKENsYXNzTmFtZS5GQURFKTtcblxuICAgICAgdmFyIGNvbXBsZXRlID0gZnVuY3Rpb24gY29tcGxldGUoKSB7XG4gICAgICAgIHJldHVybiBfdGhpczIuX3RyYW5zaXRpb25Db21wbGV0ZShlbGVtZW50LCBhY3RpdmUsIGNhbGxiYWNrKTtcbiAgICAgIH07XG5cbiAgICAgIGlmIChhY3RpdmUgJiYgaXNUcmFuc2l0aW9uaW5nKSB7XG4gICAgICAgICQkJDEoYWN0aXZlKS5vbmUoVXRpbC5UUkFOU0lUSU9OX0VORCwgY29tcGxldGUpLmVtdWxhdGVUcmFuc2l0aW9uRW5kKFRSQU5TSVRJT05fRFVSQVRJT04pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29tcGxldGUoKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3Byb3RvLl90cmFuc2l0aW9uQ29tcGxldGUgPSBmdW5jdGlvbiBfdHJhbnNpdGlvbkNvbXBsZXRlKGVsZW1lbnQsIGFjdGl2ZSwgY2FsbGJhY2spIHtcbiAgICAgIGlmIChhY3RpdmUpIHtcbiAgICAgICAgJCQkMShhY3RpdmUpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5TSE9XICsgXCIgXCIgKyBDbGFzc05hbWUuQUNUSVZFKTtcbiAgICAgICAgdmFyIGRyb3Bkb3duQ2hpbGQgPSAkJCQxKGFjdGl2ZS5wYXJlbnROb2RlKS5maW5kKFNlbGVjdG9yLkRST1BET1dOX0FDVElWRV9DSElMRClbMF07XG5cbiAgICAgICAgaWYgKGRyb3Bkb3duQ2hpbGQpIHtcbiAgICAgICAgICAkJCQxKGRyb3Bkb3duQ2hpbGQpLnJlbW92ZUNsYXNzKENsYXNzTmFtZS5BQ1RJVkUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGFjdGl2ZS5nZXRBdHRyaWJ1dGUoJ3JvbGUnKSA9PT0gJ3RhYicpIHtcbiAgICAgICAgICBhY3RpdmUuc2V0QXR0cmlidXRlKCdhcmlhLXNlbGVjdGVkJywgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgICQkJDEoZWxlbWVudCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG5cbiAgICAgIGlmIChlbGVtZW50LmdldEF0dHJpYnV0ZSgncm9sZScpID09PSAndGFiJykge1xuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1zZWxlY3RlZCcsIHRydWUpO1xuICAgICAgfVxuXG4gICAgICBVdGlsLnJlZmxvdyhlbGVtZW50KTtcbiAgICAgICQkJDEoZWxlbWVudCkuYWRkQ2xhc3MoQ2xhc3NOYW1lLlNIT1cpO1xuXG4gICAgICBpZiAoZWxlbWVudC5wYXJlbnROb2RlICYmICQkJDEoZWxlbWVudC5wYXJlbnROb2RlKS5oYXNDbGFzcyhDbGFzc05hbWUuRFJPUERPV05fTUVOVSkpIHtcbiAgICAgICAgdmFyIGRyb3Bkb3duRWxlbWVudCA9ICQkJDEoZWxlbWVudCkuY2xvc2VzdChTZWxlY3Rvci5EUk9QRE9XTilbMF07XG5cbiAgICAgICAgaWYgKGRyb3Bkb3duRWxlbWVudCkge1xuICAgICAgICAgICQkJDEoZHJvcGRvd25FbGVtZW50KS5maW5kKFNlbGVjdG9yLkRST1BET1dOX1RPR0dMRSkuYWRkQ2xhc3MoQ2xhc3NOYW1lLkFDVElWRSk7XG4gICAgICAgIH1cblxuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnYXJpYS1leHBhbmRlZCcsIHRydWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoY2FsbGJhY2spIHtcbiAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgIH1cbiAgICB9OyAvLyBzdGF0aWNcblxuXG4gICAgVGFiLl9qUXVlcnlJbnRlcmZhY2UgPSBmdW5jdGlvbiBfalF1ZXJ5SW50ZXJmYWNlKGNvbmZpZykge1xuICAgICAgcmV0dXJuIHRoaXMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkdGhpcyA9ICQkJDEodGhpcyk7XG4gICAgICAgIHZhciBkYXRhID0gJHRoaXMuZGF0YShEQVRBX0tFWSk7XG5cbiAgICAgICAgaWYgKCFkYXRhKSB7XG4gICAgICAgICAgZGF0YSA9IG5ldyBUYWIodGhpcyk7XG4gICAgICAgICAgJHRoaXMuZGF0YShEQVRBX0tFWSwgZGF0YSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGNvbmZpZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGRhdGFbY29uZmlnXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIk5vIG1ldGhvZCBuYW1lZCBcXFwiXCIgKyBjb25maWcgKyBcIlxcXCJcIik7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgZGF0YVtjb25maWddKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfY3JlYXRlQ2xhc3MoVGFiLCBudWxsLCBbe1xuICAgICAga2V5OiBcIlZFUlNJT05cIixcbiAgICAgIGdldDogZnVuY3Rpb24gZ2V0KCkge1xuICAgICAgICByZXR1cm4gVkVSU0lPTjtcbiAgICAgIH1cbiAgICB9XSk7XG4gICAgcmV0dXJuIFRhYjtcbiAgfSgpO1xuICAvKipcbiAgICogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAqIERhdGEgQXBpIGltcGxlbWVudGF0aW9uXG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuXG4gICQkJDEoZG9jdW1lbnQpLm9uKEV2ZW50LkNMSUNLX0RBVEFfQVBJLCBTZWxlY3Rvci5EQVRBX1RPR0dMRSwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgIFRhYi5falF1ZXJ5SW50ZXJmYWNlLmNhbGwoJCQkMSh0aGlzKSwgJ3Nob3cnKTtcbiAgfSk7XG4gIC8qKlxuICAgKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICogalF1ZXJ5XG4gICAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgKi9cblxuICAkJCQxLmZuW05BTUVdID0gVGFiLl9qUXVlcnlJbnRlcmZhY2U7XG4gICQkJDEuZm5bTkFNRV0uQ29uc3RydWN0b3IgPSBUYWI7XG5cbiAgJCQkMS5mbltOQU1FXS5ub0NvbmZsaWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICQkJDEuZm5bTkFNRV0gPSBKUVVFUllfTk9fQ09ORkxJQ1Q7XG4gICAgcmV0dXJuIFRhYi5falF1ZXJ5SW50ZXJmYWNlO1xuICB9O1xuXG4gIHJldHVybiBUYWI7XG59KCQpO1xuXG4vKipcbiAqIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBCb290c3RyYXAgKHY0LjAuMC1hbHBoYS42KTogaW5kZXguanNcbiAqIExpY2Vuc2VkIHVuZGVyIE1JVCAoaHR0cHM6Ly9naXRodWIuY29tL3R3YnMvYm9vdHN0cmFwL2Jsb2IvbWFzdGVyL0xJQ0VOU0UpXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICovXG5cbihmdW5jdGlvbiAoJCQkMSkge1xuICBpZiAodHlwZW9mICQkJDEgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdCb290c3RyYXBcXCdzIEphdmFTY3JpcHQgcmVxdWlyZXMgalF1ZXJ5LiBqUXVlcnkgbXVzdCBiZSBpbmNsdWRlZCBiZWZvcmUgQm9vdHN0cmFwXFwncyBKYXZhU2NyaXB0LicpO1xuICB9XG5cbiAgdmFyIHZlcnNpb24gPSAkJCQxLmZuLmpxdWVyeS5zcGxpdCgnICcpWzBdLnNwbGl0KCcuJyk7XG4gIHZhciBtaW5NYWpvciA9IDE7XG4gIHZhciBsdE1ham9yID0gMjtcbiAgdmFyIG1pbk1pbm9yID0gOTtcbiAgdmFyIG1pblBhdGNoID0gMTtcbiAgdmFyIG1heE1ham9yID0gNDtcblxuICBpZiAodmVyc2lvblswXSA8IGx0TWFqb3IgJiYgdmVyc2lvblsxXSA8IG1pbk1pbm9yIHx8IHZlcnNpb25bMF0gPT09IG1pbk1ham9yICYmIHZlcnNpb25bMV0gPT09IG1pbk1pbm9yICYmIHZlcnNpb25bMl0gPCBtaW5QYXRjaCB8fCB2ZXJzaW9uWzBdID49IG1heE1ham9yKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdCb290c3RyYXBcXCdzIEphdmFTY3JpcHQgcmVxdWlyZXMgYXQgbGVhc3QgalF1ZXJ5IHYxLjkuMSBidXQgbGVzcyB0aGFuIHY0LjAuMCcpO1xuICB9XG59KSgkKTtcblxuZXhwb3J0cy5VdGlsID0gVXRpbDtcbmV4cG9ydHMuQWxlcnQgPSBBbGVydDtcbmV4cG9ydHMuQnV0dG9uID0gQnV0dG9uO1xuZXhwb3J0cy5DYXJvdXNlbCA9IENhcm91c2VsO1xuZXhwb3J0cy5Db2xsYXBzZSA9IENvbGxhcHNlO1xuZXhwb3J0cy5Ecm9wZG93biA9IERyb3Bkb3duO1xuZXhwb3J0cy5Nb2RhbCA9IE1vZGFsO1xuZXhwb3J0cy5Qb3BvdmVyID0gUG9wb3ZlcjtcbmV4cG9ydHMuU2Nyb2xsc3B5ID0gU2Nyb2xsU3B5O1xuZXhwb3J0cy5UYWIgPSBUYWI7XG5leHBvcnRzLlRvb2x0aXAgPSBUb29sdGlwO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuXG59KSkpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Ym9vdHN0cmFwLmpzLm1hcFxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYm9vdHN0cmFwL2Rpc3QvanMvYm9vdHN0cmFwLmpzXG4vLyBtb2R1bGUgaWQgPSAxMjZcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyohXG4gKiB0eXBlYWhlYWQuanMgMS4yLjBcbiAqIGh0dHBzOi8vZ2l0aHViLmNvbS90d2l0dGVyL3R5cGVhaGVhZC5qc1xuICogQ29weXJpZ2h0IDIwMTMtMjAxNyBUd2l0dGVyLCBJbmMuIGFuZCBvdGhlciBjb250cmlidXRvcnM7IExpY2Vuc2VkIE1JVFxuICovXG5cbihmdW5jdGlvbihyb290LCBmYWN0b3J5KSB7XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG4gICAgICAgIGRlZmluZShbIFwianF1ZXJ5XCIgXSwgZnVuY3Rpb24oYTApIHtcbiAgICAgICAgICAgIHJldHVybiByb290W1wiQmxvb2Rob3VuZFwiXSA9IGZhY3RvcnkoYTApO1xuICAgICAgICB9KTtcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwianF1ZXJ5XCIpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICByb290W1wiQmxvb2Rob3VuZFwiXSA9IGZhY3Rvcnkocm9vdFtcImpRdWVyeVwiXSk7XG4gICAgfVxufSkodGhpcywgZnVuY3Rpb24oJCkge1xuICAgIHZhciBfID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaXNNc2llOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gLyhtc2llfHRyaWRlbnQpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSA/IG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goLyhtc2llIHxydjopKFxcZCsoLlxcZCspPykvaSlbMl0gOiBmYWxzZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0JsYW5rU3RyaW5nOiBmdW5jdGlvbihzdHIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIXN0ciB8fCAvXlxccyokLy50ZXN0KHN0cik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXNjYXBlUmVnRXhDaGFyczogZnVuY3Rpb24oc3RyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9bXFwtXFxbXFxdXFwvXFx7XFx9XFwoXFwpXFwqXFwrXFw/XFwuXFxcXFxcXlxcJFxcfF0vZywgXCJcXFxcJCZcIik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXNTdHJpbmc6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSBcInN0cmluZ1wiO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzTnVtYmVyOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJudW1iZXJcIjtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0FycmF5OiAkLmlzQXJyYXksXG4gICAgICAgICAgICBpc0Z1bmN0aW9uOiAkLmlzRnVuY3Rpb24sXG4gICAgICAgICAgICBpc09iamVjdDogJC5pc1BsYWluT2JqZWN0LFxuICAgICAgICAgICAgaXNVbmRlZmluZWQ6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSBcInVuZGVmaW5lZFwiO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzRWxlbWVudDogZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICEhKG9iaiAmJiBvYmoubm9kZVR5cGUgPT09IDEpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzSlF1ZXJ5OiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgJDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0b1N0cjogZnVuY3Rpb24gdG9TdHIocykge1xuICAgICAgICAgICAgICAgIHJldHVybiBfLmlzVW5kZWZpbmVkKHMpIHx8IHMgPT09IG51bGwgPyBcIlwiIDogcyArIFwiXCI7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYmluZDogJC5wcm94eSxcbiAgICAgICAgICAgIGVhY2g6IGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGNiKSB7XG4gICAgICAgICAgICAgICAgJC5lYWNoKGNvbGxlY3Rpb24sIHJldmVyc2VBcmdzKTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiByZXZlcnNlQXJncyhpbmRleCwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNiKHZhbHVlLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1hcDogJC5tYXAsXG4gICAgICAgICAgICBmaWx0ZXI6ICQuZ3JlcCxcbiAgICAgICAgICAgIGV2ZXJ5OiBmdW5jdGlvbihvYmosIHRlc3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAoIW9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkLmVhY2gob2JqLCBmdW5jdGlvbihrZXksIHZhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShyZXN1bHQgPSB0ZXN0LmNhbGwobnVsbCwgdmFsLCBrZXksIG9iaikpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gISFyZXN1bHQ7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc29tZTogZnVuY3Rpb24ob2JqLCB0ZXN0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmICghb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICQuZWFjaChvYmosIGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPSB0ZXN0LmNhbGwobnVsbCwgdmFsLCBrZXksIG9iaikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiAhIXJlc3VsdDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtaXhpbjogJC5leHRlbmQsXG4gICAgICAgICAgICBpZGVudGl0eTogZnVuY3Rpb24oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsb25lOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQodHJ1ZSwge30sIG9iaik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0SWRHZW5lcmF0b3I6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHZhciBjb3VudGVyID0gMDtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb3VudGVyKys7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0ZW1wbGF0aWZ5OiBmdW5jdGlvbiB0ZW1wbGF0aWZ5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmlzRnVuY3Rpb24ob2JqKSA/IG9iaiA6IHRlbXBsYXRlO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHRlbXBsYXRlKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlZmVyOiBmdW5jdGlvbihmbikge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZm4sIDApO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlYm91bmNlOiBmdW5jdGlvbihmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGltZW91dCwgcmVzdWx0O1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbnRleHQgPSB0aGlzLCBhcmdzID0gYXJndW1lbnRzLCBsYXRlciwgY2FsbE5vdztcbiAgICAgICAgICAgICAgICAgICAgbGF0ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpbW1lZGlhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xuICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxOb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRocm90dGxlOiBmdW5jdGlvbihmdW5jLCB3YWl0KSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRleHQsIGFyZ3MsIHRpbWVvdXQsIHJlc3VsdCwgcHJldmlvdXMsIGxhdGVyO1xuICAgICAgICAgICAgICAgIHByZXZpb3VzID0gMDtcbiAgICAgICAgICAgICAgICBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBwcmV2aW91cyA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm93ID0gbmV3IERhdGUoKSwgcmVtYWluaW5nID0gd2FpdCAtIChub3cgLSBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtYWluaW5nIDw9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXMgPSBub3c7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCF0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgcmVtYWluaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3RyaW5naWZ5OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXy5pc1N0cmluZyh2YWwpID8gdmFsIDogSlNPTi5zdHJpbmdpZnkodmFsKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBndWlkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfcDgocykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcCA9IChNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDE2KSArIFwiMDAwMDAwMDAwXCIpLnN1YnN0cigyLCA4KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMgPyBcIi1cIiArIHAuc3Vic3RyKDAsIDQpICsgXCItXCIgKyBwLnN1YnN0cig0LCA0KSA6IHA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBcInR0LVwiICsgX3A4KCkgKyBfcDgodHJ1ZSkgKyBfcDgodHJ1ZSkgKyBfcDgoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBub29wOiBmdW5jdGlvbigpIHt9XG4gICAgICAgIH07XG4gICAgfSgpO1xuICAgIHZhciBWRVJTSU9OID0gXCIxLjIuMFwiO1xuICAgIHZhciB0b2tlbml6ZXJzID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbm9ud29yZDogbm9ud29yZCxcbiAgICAgICAgICAgIHdoaXRlc3BhY2U6IHdoaXRlc3BhY2UsXG4gICAgICAgICAgICBuZ3JhbTogbmdyYW0sXG4gICAgICAgICAgICBvYmo6IHtcbiAgICAgICAgICAgICAgICBub253b3JkOiBnZXRPYmpUb2tlbml6ZXIobm9ud29yZCksXG4gICAgICAgICAgICAgICAgd2hpdGVzcGFjZTogZ2V0T2JqVG9rZW5pemVyKHdoaXRlc3BhY2UpLFxuICAgICAgICAgICAgICAgIG5ncmFtOiBnZXRPYmpUb2tlbml6ZXIobmdyYW0pXG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGZ1bmN0aW9uIHdoaXRlc3BhY2Uoc3RyKSB7XG4gICAgICAgICAgICBzdHIgPSBfLnRvU3RyKHN0cik7XG4gICAgICAgICAgICByZXR1cm4gc3RyID8gc3RyLnNwbGl0KC9cXHMrLykgOiBbXTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBub253b3JkKHN0cikge1xuICAgICAgICAgICAgc3RyID0gXy50b1N0cihzdHIpO1xuICAgICAgICAgICAgcmV0dXJuIHN0ciA/IHN0ci5zcGxpdCgvXFxXKy8pIDogW107XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gbmdyYW0oc3RyKSB7XG4gICAgICAgICAgICBzdHIgPSBfLnRvU3RyKHN0cik7XG4gICAgICAgICAgICB2YXIgdG9rZW5zID0gW10sIHdvcmQgPSBcIlwiO1xuICAgICAgICAgICAgXy5lYWNoKHN0ci5zcGxpdChcIlwiKSwgZnVuY3Rpb24oY2hhcikge1xuICAgICAgICAgICAgICAgIGlmIChjaGFyLm1hdGNoKC9cXHMrLykpIHtcbiAgICAgICAgICAgICAgICAgICAgd29yZCA9IFwiXCI7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdG9rZW5zLnB1c2god29yZCArIGNoYXIpO1xuICAgICAgICAgICAgICAgICAgICB3b3JkICs9IGNoYXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gdG9rZW5zO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdldE9ialRva2VuaXplcih0b2tlbml6ZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiBzZXRLZXkoa2V5cykge1xuICAgICAgICAgICAgICAgIGtleXMgPSBfLmlzQXJyYXkoa2V5cykgPyBrZXlzIDogW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiB0b2tlbml6ZShvKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciB0b2tlbnMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgXy5lYWNoKGtleXMsIGZ1bmN0aW9uKGspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRva2VucyA9IHRva2Vucy5jb25jYXQodG9rZW5pemVyKF8udG9TdHIob1trXSkpKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0b2tlbnM7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9KCk7XG4gICAgdmFyIExydUNhY2hlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBmdW5jdGlvbiBMcnVDYWNoZShtYXhTaXplKSB7XG4gICAgICAgICAgICB0aGlzLm1heFNpemUgPSBfLmlzTnVtYmVyKG1heFNpemUpID8gbWF4U2l6ZSA6IDEwMDtcbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgICAgIGlmICh0aGlzLm1heFNpemUgPD0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0ID0gdGhpcy5nZXQgPSAkLm5vb3A7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgXy5taXhpbihMcnVDYWNoZS5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIHNldDogZnVuY3Rpb24gc2V0KGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRhaWxJdGVtID0gdGhpcy5saXN0LnRhaWwsIG5vZGU7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2l6ZSA+PSB0aGlzLm1heFNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5saXN0LnJlbW92ZSh0YWlsSXRlbSk7XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLmhhc2hbdGFpbEl0ZW0ua2V5XTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zaXplLS07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChub2RlID0gdGhpcy5oYXNoW2tleV0pIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS52YWwgPSB2YWw7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGlzdC5tb3ZlVG9Gcm9udChub2RlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBub2RlID0gbmV3IE5vZGUoa2V5LCB2YWwpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxpc3QuYWRkKG5vZGUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmhhc2hba2V5XSA9IG5vZGU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2l6ZSsrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldChrZXkpIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9kZSA9IHRoaXMuaGFzaFtrZXldO1xuICAgICAgICAgICAgICAgIGlmIChub2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMubGlzdC5tb3ZlVG9Gcm9udChub2RlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG5vZGUudmFsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXNldDogZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zaXplID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLmhhc2ggPSB7fTtcbiAgICAgICAgICAgICAgICB0aGlzLmxpc3QgPSBuZXcgTGlzdCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgZnVuY3Rpb24gTGlzdCgpIHtcbiAgICAgICAgICAgIHRoaXMuaGVhZCA9IHRoaXMudGFpbCA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgXy5taXhpbihMaXN0LnByb3RvdHlwZSwge1xuICAgICAgICAgICAgYWRkOiBmdW5jdGlvbiBhZGQobm9kZSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmhlYWQpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5uZXh0ID0gdGhpcy5oZWFkO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmhlYWQucHJldiA9IG5vZGU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuaGVhZCA9IG5vZGU7XG4gICAgICAgICAgICAgICAgdGhpcy50YWlsID0gdGhpcy50YWlsIHx8IG5vZGU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmVtb3ZlOiBmdW5jdGlvbiByZW1vdmUobm9kZSkge1xuICAgICAgICAgICAgICAgIG5vZGUucHJldiA/IG5vZGUucHJldi5uZXh0ID0gbm9kZS5uZXh0IDogdGhpcy5oZWFkID0gbm9kZS5uZXh0O1xuICAgICAgICAgICAgICAgIG5vZGUubmV4dCA/IG5vZGUubmV4dC5wcmV2ID0gbm9kZS5wcmV2IDogdGhpcy50YWlsID0gbm9kZS5wcmV2O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1vdmVUb0Zyb250OiBmdW5jdGlvbihub2RlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmUobm9kZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGQobm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBmdW5jdGlvbiBOb2RlKGtleSwgdmFsKSB7XG4gICAgICAgICAgICB0aGlzLmtleSA9IGtleTtcbiAgICAgICAgICAgIHRoaXMudmFsID0gdmFsO1xuICAgICAgICAgICAgdGhpcy5wcmV2ID0gdGhpcy5uZXh0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gTHJ1Q2FjaGU7XG4gICAgfSgpO1xuICAgIHZhciBQZXJzaXN0ZW50U3RvcmFnZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgdmFyIExPQ0FMX1NUT1JBR0U7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBMT0NBTF9TVE9SQUdFID0gd2luZG93LmxvY2FsU3RvcmFnZTtcbiAgICAgICAgICAgIExPQ0FMX1NUT1JBR0Uuc2V0SXRlbShcIn5+flwiLCBcIiFcIik7XG4gICAgICAgICAgICBMT0NBTF9TVE9SQUdFLnJlbW92ZUl0ZW0oXCJ+fn5cIik7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgTE9DQUxfU1RPUkFHRSA9IG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gUGVyc2lzdGVudFN0b3JhZ2UobmFtZXNwYWNlLCBvdmVycmlkZSkge1xuICAgICAgICAgICAgdGhpcy5wcmVmaXggPSBbIFwiX19cIiwgbmFtZXNwYWNlLCBcIl9fXCIgXS5qb2luKFwiXCIpO1xuICAgICAgICAgICAgdGhpcy50dGxLZXkgPSBcIl9fdHRsX19cIjtcbiAgICAgICAgICAgIHRoaXMua2V5TWF0Y2hlciA9IG5ldyBSZWdFeHAoXCJeXCIgKyBfLmVzY2FwZVJlZ0V4Q2hhcnModGhpcy5wcmVmaXgpKTtcbiAgICAgICAgICAgIHRoaXMubHMgPSBvdmVycmlkZSB8fCBMT0NBTF9TVE9SQUdFO1xuICAgICAgICAgICAgIXRoaXMubHMgJiYgdGhpcy5fbm9vcCgpO1xuICAgICAgICB9XG4gICAgICAgIF8ubWl4aW4oUGVyc2lzdGVudFN0b3JhZ2UucHJvdG90eXBlLCB7XG4gICAgICAgICAgICBfcHJlZml4OiBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wcmVmaXggKyBrZXk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX3R0bEtleTogZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3ByZWZpeChrZXkpICsgdGhpcy50dGxLZXk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX25vb3A6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZ2V0ID0gdGhpcy5zZXQgPSB0aGlzLnJlbW92ZSA9IHRoaXMuY2xlYXIgPSB0aGlzLmlzRXhwaXJlZCA9IF8ubm9vcDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfc2FmZVNldDogZnVuY3Rpb24oa2V5LCB2YWwpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxzLnNldEl0ZW0oa2V5LCB2YWwpO1xuICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyLm5hbWUgPT09IFwiUXVvdGFFeGNlZWRlZEVycm9yXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX25vb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKGtleSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRXhwaXJlZChrZXkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3ZlKGtleSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBkZWNvZGUodGhpcy5scy5nZXRJdGVtKHRoaXMuX3ByZWZpeChrZXkpKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0OiBmdW5jdGlvbihrZXksIHZhbCwgdHRsKSB7XG4gICAgICAgICAgICAgICAgaWYgKF8uaXNOdW1iZXIodHRsKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zYWZlU2V0KHRoaXMuX3R0bEtleShrZXkpLCBlbmNvZGUobm93KCkgKyB0dGwpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmxzLnJlbW92ZUl0ZW0odGhpcy5fdHRsS2V5KGtleSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fc2FmZVNldCh0aGlzLl9wcmVmaXgoa2V5KSwgZW5jb2RlKHZhbCkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlbW92ZTogZnVuY3Rpb24oa2V5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5scy5yZW1vdmVJdGVtKHRoaXMuX3R0bEtleShrZXkpKTtcbiAgICAgICAgICAgICAgICB0aGlzLmxzLnJlbW92ZUl0ZW0odGhpcy5fcHJlZml4KGtleSkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsZWFyOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB2YXIgaSwga2V5cyA9IGdhdGhlck1hdGNoaW5nS2V5cyh0aGlzLmtleU1hdGNoZXIpO1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IGtleXMubGVuZ3RoOyBpLS07ICkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW92ZShrZXlzW2ldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXNFeHBpcmVkOiBmdW5jdGlvbihrZXkpIHtcbiAgICAgICAgICAgICAgICB2YXIgdHRsID0gZGVjb2RlKHRoaXMubHMuZ2V0SXRlbSh0aGlzLl90dGxLZXkoa2V5KSkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBfLmlzTnVtYmVyKHR0bCkgJiYgbm93KCkgPiB0dGwgPyB0cnVlIDogZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gUGVyc2lzdGVudFN0b3JhZ2U7XG4gICAgICAgIGZ1bmN0aW9uIG5vdygpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBlbmNvZGUodmFsKSB7XG4gICAgICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkoXy5pc1VuZGVmaW5lZCh2YWwpID8gbnVsbCA6IHZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZGVjb2RlKHZhbCkge1xuICAgICAgICAgICAgcmV0dXJuICQucGFyc2VKU09OKHZhbCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2F0aGVyTWF0Y2hpbmdLZXlzKGtleU1hdGNoZXIpIHtcbiAgICAgICAgICAgIHZhciBpLCBrZXksIGtleXMgPSBbXSwgbGVuID0gTE9DQUxfU1RPUkFHRS5sZW5ndGg7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoKGtleSA9IExPQ0FMX1NUT1JBR0Uua2V5KGkpKS5tYXRjaChrZXlNYXRjaGVyKSkge1xuICAgICAgICAgICAgICAgICAgICBrZXlzLnB1c2goa2V5LnJlcGxhY2Uoa2V5TWF0Y2hlciwgXCJcIikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBrZXlzO1xuICAgICAgICB9XG4gICAgfSgpO1xuICAgIHZhciBUcmFuc3BvcnQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIHZhciBwZW5kaW5nUmVxdWVzdHNDb3VudCA9IDAsIHBlbmRpbmdSZXF1ZXN0cyA9IHt9LCBzaGFyZWRDYWNoZSA9IG5ldyBMcnVDYWNoZSgxMCk7XG4gICAgICAgIGZ1bmN0aW9uIFRyYW5zcG9ydChvKSB7XG4gICAgICAgICAgICBvID0gbyB8fCB7fTtcbiAgICAgICAgICAgIHRoaXMubWF4UGVuZGluZ1JlcXVlc3RzID0gby5tYXhQZW5kaW5nUmVxdWVzdHMgfHwgNjtcbiAgICAgICAgICAgIHRoaXMuY2FuY2VsbGVkID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmxhc3RSZXEgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5fc2VuZCA9IG8udHJhbnNwb3J0O1xuICAgICAgICAgICAgdGhpcy5fZ2V0ID0gby5saW1pdGVyID8gby5saW1pdGVyKHRoaXMuX2dldCkgOiB0aGlzLl9nZXQ7XG4gICAgICAgICAgICB0aGlzLl9jYWNoZSA9IG8uY2FjaGUgPT09IGZhbHNlID8gbmV3IExydUNhY2hlKDApIDogc2hhcmVkQ2FjaGU7XG4gICAgICAgIH1cbiAgICAgICAgVHJhbnNwb3J0LnNldE1heFBlbmRpbmdSZXF1ZXN0cyA9IGZ1bmN0aW9uIHNldE1heFBlbmRpbmdSZXF1ZXN0cyhudW0pIHtcbiAgICAgICAgICAgIHRoaXMubWF4UGVuZGluZ1JlcXVlc3RzID0gbnVtO1xuICAgICAgICB9O1xuICAgICAgICBUcmFuc3BvcnQucmVzZXRDYWNoZSA9IGZ1bmN0aW9uIHJlc2V0Q2FjaGUoKSB7XG4gICAgICAgICAgICBzaGFyZWRDYWNoZS5yZXNldCgpO1xuICAgICAgICB9O1xuICAgICAgICBfLm1peGluKFRyYW5zcG9ydC5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIF9maW5nZXJwcmludDogZnVuY3Rpb24gZmluZ2VycHJpbnQobykge1xuICAgICAgICAgICAgICAgIG8gPSBvIHx8IHt9O1xuICAgICAgICAgICAgICAgIHJldHVybiBvLnVybCArIG8udHlwZSArICQucGFyYW0oby5kYXRhIHx8IHt9KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfZ2V0OiBmdW5jdGlvbihvLCBjYikge1xuICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcywgZmluZ2VycHJpbnQsIGpxWGhyO1xuICAgICAgICAgICAgICAgIGZpbmdlcnByaW50ID0gdGhpcy5fZmluZ2VycHJpbnQobyk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuY2FuY2VsbGVkIHx8IGZpbmdlcnByaW50ICE9PSB0aGlzLmxhc3RSZXEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoanFYaHIgPSBwZW5kaW5nUmVxdWVzdHNbZmluZ2VycHJpbnRdKSB7XG4gICAgICAgICAgICAgICAgICAgIGpxWGhyLmRvbmUoZG9uZSkuZmFpbChmYWlsKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHBlbmRpbmdSZXF1ZXN0c0NvdW50IDwgdGhpcy5tYXhQZW5kaW5nUmVxdWVzdHMpIHtcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3RzQ291bnQrKztcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3RzW2ZpbmdlcnByaW50XSA9IHRoaXMuX3NlbmQobykuZG9uZShkb25lKS5mYWlsKGZhaWwpLmFsd2F5cyhhbHdheXMpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMub25EZWNrUmVxdWVzdEFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGRvbmUocmVzcCkge1xuICAgICAgICAgICAgICAgICAgICBjYihudWxsLCByZXNwKTtcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5fY2FjaGUuc2V0KGZpbmdlcnByaW50LCByZXNwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gZmFpbCgpIHtcbiAgICAgICAgICAgICAgICAgICAgY2IodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGFsd2F5cygpIHtcbiAgICAgICAgICAgICAgICAgICAgcGVuZGluZ1JlcXVlc3RzQ291bnQtLTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHBlbmRpbmdSZXF1ZXN0c1tmaW5nZXJwcmludF07XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGF0Lm9uRGVja1JlcXVlc3RBcmdzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGF0Ll9nZXQuYXBwbHkodGhhdCwgdGhhdC5vbkRlY2tSZXF1ZXN0QXJncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGF0Lm9uRGVja1JlcXVlc3RBcmdzID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uKG8sIGNiKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3AsIGZpbmdlcnByaW50O1xuICAgICAgICAgICAgICAgIGNiID0gY2IgfHwgJC5ub29wO1xuICAgICAgICAgICAgICAgIG8gPSBfLmlzU3RyaW5nKG8pID8ge1xuICAgICAgICAgICAgICAgICAgICB1cmw6IG9cbiAgICAgICAgICAgICAgICB9IDogbyB8fCB7fTtcbiAgICAgICAgICAgICAgICBmaW5nZXJwcmludCA9IHRoaXMuX2ZpbmdlcnByaW50KG8pO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuY2VsbGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5sYXN0UmVxID0gZmluZ2VycHJpbnQ7XG4gICAgICAgICAgICAgICAgaWYgKHJlc3AgPSB0aGlzLl9jYWNoZS5nZXQoZmluZ2VycHJpbnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNiKG51bGwsIHJlc3ApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2dldChvLCBjYik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNhbmNlbDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5jZWxsZWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFRyYW5zcG9ydDtcbiAgICB9KCk7XG4gICAgdmFyIFNlYXJjaEluZGV4ID0gd2luZG93LlNlYXJjaEluZGV4ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICB2YXIgQ0hJTERSRU4gPSBcImNcIiwgSURTID0gXCJpXCI7XG4gICAgICAgIGZ1bmN0aW9uIFNlYXJjaEluZGV4KG8pIHtcbiAgICAgICAgICAgIG8gPSBvIHx8IHt9O1xuICAgICAgICAgICAgaWYgKCFvLmRhdHVtVG9rZW5pemVyIHx8ICFvLnF1ZXJ5VG9rZW5pemVyKSB7XG4gICAgICAgICAgICAgICAgJC5lcnJvcihcImRhdHVtVG9rZW5pemVyIGFuZCBxdWVyeVRva2VuaXplciBhcmUgYm90aCByZXF1aXJlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuaWRlbnRpZnkgPSBvLmlkZW50aWZ5IHx8IF8uc3RyaW5naWZ5O1xuICAgICAgICAgICAgdGhpcy5kYXR1bVRva2VuaXplciA9IG8uZGF0dW1Ub2tlbml6ZXI7XG4gICAgICAgICAgICB0aGlzLnF1ZXJ5VG9rZW5pemVyID0gby5xdWVyeVRva2VuaXplcjtcbiAgICAgICAgICAgIHRoaXMubWF0Y2hBbnlRdWVyeVRva2VuID0gby5tYXRjaEFueVF1ZXJ5VG9rZW47XG4gICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG4gICAgICAgIH1cbiAgICAgICAgXy5taXhpbihTZWFyY2hJbmRleC5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIGJvb3RzdHJhcDogZnVuY3Rpb24gYm9vdHN0cmFwKG8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdHVtcyA9IG8uZGF0dW1zO1xuICAgICAgICAgICAgICAgIHRoaXMudHJpZSA9IG8udHJpZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhZGQ6IGZ1bmN0aW9uKGRhdGEpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgZGF0YSA9IF8uaXNBcnJheShkYXRhKSA/IGRhdGEgOiBbIGRhdGEgXTtcbiAgICAgICAgICAgICAgICBfLmVhY2goZGF0YSwgZnVuY3Rpb24oZGF0dW0pIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGlkLCB0b2tlbnM7XG4gICAgICAgICAgICAgICAgICAgIHRoYXQuZGF0dW1zW2lkID0gdGhhdC5pZGVudGlmeShkYXR1bSldID0gZGF0dW07XG4gICAgICAgICAgICAgICAgICAgIHRva2VucyA9IG5vcm1hbGl6ZVRva2Vucyh0aGF0LmRhdHVtVG9rZW5pemVyKGRhdHVtKSk7XG4gICAgICAgICAgICAgICAgICAgIF8uZWFjaCh0b2tlbnMsIGZ1bmN0aW9uKHRva2VuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZSwgY2hhcnMsIGNoO1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZSA9IHRoYXQudHJpZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNoYXJzID0gdG9rZW4uc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoY2ggPSBjaGFycy5zaGlmdCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZSA9IG5vZGVbQ0hJTERSRU5dW2NoXSB8fCAobm9kZVtDSElMRFJFTl1bY2hdID0gbmV3Tm9kZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub2RlW0lEU10ucHVzaChpZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KGlkcykge1xuICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcztcbiAgICAgICAgICAgICAgICByZXR1cm4gXy5tYXAoaWRzLCBmdW5jdGlvbihpZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5kYXR1bXNbaWRdO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlYXJjaDogZnVuY3Rpb24gc2VhcmNoKHF1ZXJ5KSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLCB0b2tlbnMsIG1hdGNoZXM7XG4gICAgICAgICAgICAgICAgdG9rZW5zID0gbm9ybWFsaXplVG9rZW5zKHRoaXMucXVlcnlUb2tlbml6ZXIocXVlcnkpKTtcbiAgICAgICAgICAgICAgICBfLmVhY2godG9rZW5zLCBmdW5jdGlvbih0b2tlbikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9kZSwgY2hhcnMsIGNoLCBpZHM7XG4gICAgICAgICAgICAgICAgICAgIGlmIChtYXRjaGVzICYmIG1hdGNoZXMubGVuZ3RoID09PSAwICYmICF0aGF0Lm1hdGNoQW55UXVlcnlUb2tlbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIG5vZGUgPSB0aGF0LnRyaWU7XG4gICAgICAgICAgICAgICAgICAgIGNoYXJzID0gdG9rZW4uc3BsaXQoXCJcIik7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlIChub2RlICYmIChjaCA9IGNoYXJzLnNoaWZ0KCkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlID0gbm9kZVtDSElMRFJFTl1bY2hdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChub2RlICYmIGNoYXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWRzID0gbm9kZVtJRFNdLnNsaWNlKDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hlcyA9IG1hdGNoZXMgPyBnZXRJbnRlcnNlY3Rpb24obWF0Y2hlcywgaWRzKSA6IGlkcztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhhdC5tYXRjaEFueVF1ZXJ5VG9rZW4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRjaGVzID0gW107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG1hdGNoZXMgPyBfLm1hcCh1bmlxdWUobWF0Y2hlcyksIGZ1bmN0aW9uKGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGF0LmRhdHVtc1tpZF07XG4gICAgICAgICAgICAgICAgfSkgOiBbXTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhbGw6IGZ1bmN0aW9uIGFsbCgpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsdWVzID0gW107XG4gICAgICAgICAgICAgICAgZm9yICh2YXIga2V5IGluIHRoaXMuZGF0dW1zKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlcy5wdXNoKHRoaXMuZGF0dW1zW2tleV0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWVzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlc2V0OiBmdW5jdGlvbiByZXNldCgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmRhdHVtcyA9IHt9O1xuICAgICAgICAgICAgICAgIHRoaXMudHJpZSA9IG5ld05vZGUoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXJpYWxpemU6IGZ1bmN0aW9uIHNlcmlhbGl6ZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBkYXR1bXM6IHRoaXMuZGF0dW1zLFxuICAgICAgICAgICAgICAgICAgICB0cmllOiB0aGlzLnRyaWVcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFNlYXJjaEluZGV4O1xuICAgICAgICBmdW5jdGlvbiBub3JtYWxpemVUb2tlbnModG9rZW5zKSB7XG4gICAgICAgICAgICB0b2tlbnMgPSBfLmZpbHRlcih0b2tlbnMsIGZ1bmN0aW9uKHRva2VuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICEhdG9rZW47XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRva2VucyA9IF8ubWFwKHRva2VucywgZnVuY3Rpb24odG9rZW4pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdG9rZW4udG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcmV0dXJuIHRva2VucztcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBuZXdOb2RlKCkge1xuICAgICAgICAgICAgdmFyIG5vZGUgPSB7fTtcbiAgICAgICAgICAgIG5vZGVbSURTXSA9IFtdO1xuICAgICAgICAgICAgbm9kZVtDSElMRFJFTl0gPSB7fTtcbiAgICAgICAgICAgIHJldHVybiBub2RlO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHVuaXF1ZShhcnJheSkge1xuICAgICAgICAgICAgdmFyIHNlZW4gPSB7fSwgdW5pcXVlcyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IGFycmF5Lmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFzZWVuW2FycmF5W2ldXSkge1xuICAgICAgICAgICAgICAgICAgICBzZWVuW2FycmF5W2ldXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHVuaXF1ZXMucHVzaChhcnJheVtpXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHVuaXF1ZXM7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2V0SW50ZXJzZWN0aW9uKGFycmF5QSwgYXJyYXlCKSB7XG4gICAgICAgICAgICB2YXIgYWkgPSAwLCBiaSA9IDAsIGludGVyc2VjdGlvbiA9IFtdO1xuICAgICAgICAgICAgYXJyYXlBID0gYXJyYXlBLnNvcnQoKTtcbiAgICAgICAgICAgIGFycmF5QiA9IGFycmF5Qi5zb3J0KCk7XG4gICAgICAgICAgICB2YXIgbGVuQXJyYXlBID0gYXJyYXlBLmxlbmd0aCwgbGVuQXJyYXlCID0gYXJyYXlCLmxlbmd0aDtcbiAgICAgICAgICAgIHdoaWxlIChhaSA8IGxlbkFycmF5QSAmJiBiaSA8IGxlbkFycmF5Qikge1xuICAgICAgICAgICAgICAgIGlmIChhcnJheUFbYWldIDwgYXJyYXlCW2JpXSkge1xuICAgICAgICAgICAgICAgICAgICBhaSsrO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoYXJyYXlBW2FpXSA+IGFycmF5QltiaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgYmkrKztcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpbnRlcnNlY3Rpb24ucHVzaChhcnJheUFbYWldKTtcbiAgICAgICAgICAgICAgICAgICAgYWkrKztcbiAgICAgICAgICAgICAgICAgICAgYmkrKztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaW50ZXJzZWN0aW9uO1xuICAgICAgICB9XG4gICAgfSgpO1xuICAgIHZhciBQcmVmZXRjaCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgdmFyIGtleXM7XG4gICAgICAgIGtleXMgPSB7XG4gICAgICAgICAgICBkYXRhOiBcImRhdGFcIixcbiAgICAgICAgICAgIHByb3RvY29sOiBcInByb3RvY29sXCIsXG4gICAgICAgICAgICB0aHVtYnByaW50OiBcInRodW1icHJpbnRcIlxuICAgICAgICB9O1xuICAgICAgICBmdW5jdGlvbiBQcmVmZXRjaChvKSB7XG4gICAgICAgICAgICB0aGlzLnVybCA9IG8udXJsO1xuICAgICAgICAgICAgdGhpcy50dGwgPSBvLnR0bDtcbiAgICAgICAgICAgIHRoaXMuY2FjaGUgPSBvLmNhY2hlO1xuICAgICAgICAgICAgdGhpcy5wcmVwYXJlID0gby5wcmVwYXJlO1xuICAgICAgICAgICAgdGhpcy50cmFuc2Zvcm0gPSBvLnRyYW5zZm9ybTtcbiAgICAgICAgICAgIHRoaXMudHJhbnNwb3J0ID0gby50cmFuc3BvcnQ7XG4gICAgICAgICAgICB0aGlzLnRodW1icHJpbnQgPSBvLnRodW1icHJpbnQ7XG4gICAgICAgICAgICB0aGlzLnN0b3JhZ2UgPSBuZXcgUGVyc2lzdGVudFN0b3JhZ2Uoby5jYWNoZUtleSk7XG4gICAgICAgIH1cbiAgICAgICAgXy5taXhpbihQcmVmZXRjaC5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIF9zZXR0aW5nczogZnVuY3Rpb24gc2V0dGluZ3MoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgdXJsOiB0aGlzLnVybCxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJHRVRcIixcbiAgICAgICAgICAgICAgICAgICAgZGF0YVR5cGU6IFwianNvblwiXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdG9yZTogZnVuY3Rpb24gc3RvcmUoZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5jYWNoZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoa2V5cy5kYXRhLCBkYXRhLCB0aGlzLnR0bCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zdG9yYWdlLnNldChrZXlzLnByb3RvY29sLCBsb2NhdGlvbi5wcm90b2NvbCwgdGhpcy50dGwpO1xuICAgICAgICAgICAgICAgIHRoaXMuc3RvcmFnZS5zZXQoa2V5cy50aHVtYnByaW50LCB0aGlzLnRodW1icHJpbnQsIHRoaXMudHRsKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmcm9tQ2FjaGU6IGZ1bmN0aW9uIGZyb21DYWNoZSgpIHtcbiAgICAgICAgICAgICAgICB2YXIgc3RvcmVkID0ge30sIGlzRXhwaXJlZDtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2FjaGUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN0b3JlZC5kYXRhID0gdGhpcy5zdG9yYWdlLmdldChrZXlzLmRhdGEpO1xuICAgICAgICAgICAgICAgIHN0b3JlZC5wcm90b2NvbCA9IHRoaXMuc3RvcmFnZS5nZXQoa2V5cy5wcm90b2NvbCk7XG4gICAgICAgICAgICAgICAgc3RvcmVkLnRodW1icHJpbnQgPSB0aGlzLnN0b3JhZ2UuZ2V0KGtleXMudGh1bWJwcmludCk7XG4gICAgICAgICAgICAgICAgaXNFeHBpcmVkID0gc3RvcmVkLnRodW1icHJpbnQgIT09IHRoaXMudGh1bWJwcmludCB8fCBzdG9yZWQucHJvdG9jb2wgIT09IGxvY2F0aW9uLnByb3RvY29sO1xuICAgICAgICAgICAgICAgIHJldHVybiBzdG9yZWQuZGF0YSAmJiAhaXNFeHBpcmVkID8gc3RvcmVkLmRhdGEgOiBudWxsO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZyb21OZXR3b3JrOiBmdW5jdGlvbihjYikge1xuICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcywgc2V0dGluZ3M7XG4gICAgICAgICAgICAgICAgaWYgKCFjYikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHNldHRpbmdzID0gdGhpcy5wcmVwYXJlKHRoaXMuX3NldHRpbmdzKCkpO1xuICAgICAgICAgICAgICAgIHRoaXMudHJhbnNwb3J0KHNldHRpbmdzKS5mYWlsKG9uRXJyb3IpLmRvbmUob25SZXNwb25zZSk7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gb25FcnJvcigpIHtcbiAgICAgICAgICAgICAgICAgICAgY2IodHJ1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIG9uUmVzcG9uc2UocmVzcCkge1xuICAgICAgICAgICAgICAgICAgICBjYihudWxsLCB0aGF0LnRyYW5zZm9ybShyZXNwKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsZWFyOiBmdW5jdGlvbiBjbGVhcigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnN0b3JhZ2UuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBQcmVmZXRjaDtcbiAgICB9KCk7XG4gICAgdmFyIFJlbW90ZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgZnVuY3Rpb24gUmVtb3RlKG8pIHtcbiAgICAgICAgICAgIHRoaXMudXJsID0gby51cmw7XG4gICAgICAgICAgICB0aGlzLnByZXBhcmUgPSBvLnByZXBhcmU7XG4gICAgICAgICAgICB0aGlzLnRyYW5zZm9ybSA9IG8udHJhbnNmb3JtO1xuICAgICAgICAgICAgdGhpcy5pbmRleFJlc3BvbnNlID0gby5pbmRleFJlc3BvbnNlO1xuICAgICAgICAgICAgdGhpcy50cmFuc3BvcnQgPSBuZXcgVHJhbnNwb3J0KHtcbiAgICAgICAgICAgICAgICBjYWNoZTogby5jYWNoZSxcbiAgICAgICAgICAgICAgICBsaW1pdGVyOiBvLmxpbWl0ZXIsXG4gICAgICAgICAgICAgICAgdHJhbnNwb3J0OiBvLnRyYW5zcG9ydCxcbiAgICAgICAgICAgICAgICBtYXhQZW5kaW5nUmVxdWVzdHM6IG8ubWF4UGVuZGluZ1JlcXVlc3RzXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBfLm1peGluKFJlbW90ZS5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIF9zZXR0aW5nczogZnVuY3Rpb24gc2V0dGluZ3MoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgdXJsOiB0aGlzLnVybCxcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogXCJHRVRcIixcbiAgICAgICAgICAgICAgICAgICAgZGF0YVR5cGU6IFwianNvblwiXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQ6IGZ1bmN0aW9uIGdldChxdWVyeSwgY2IpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXMsIHNldHRpbmdzO1xuICAgICAgICAgICAgICAgIGlmICghY2IpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBxdWVyeSA9IHF1ZXJ5IHx8IFwiXCI7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MgPSB0aGlzLnByZXBhcmUocXVlcnksIHRoaXMuX3NldHRpbmdzKCkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnRyYW5zcG9ydC5nZXQoc2V0dGluZ3MsIG9uUmVzcG9uc2UpO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIG9uUmVzcG9uc2UoZXJyLCByZXNwKSB7XG4gICAgICAgICAgICAgICAgICAgIGVyciA/IGNiKFtdKSA6IGNiKHRoYXQudHJhbnNmb3JtKHJlc3ApKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2FuY2VsTGFzdFJlcXVlc3Q6IGZ1bmN0aW9uIGNhbmNlbExhc3RSZXF1ZXN0KCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHJhbnNwb3J0LmNhbmNlbCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFJlbW90ZTtcbiAgICB9KCk7XG4gICAgdmFyIG9QYXJzZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBwYXJzZShvKSB7XG4gICAgICAgICAgICB2YXIgZGVmYXVsdHMsIHNvcnRlcjtcbiAgICAgICAgICAgIGRlZmF1bHRzID0ge1xuICAgICAgICAgICAgICAgIGluaXRpYWxpemU6IHRydWUsXG4gICAgICAgICAgICAgICAgaWRlbnRpZnk6IF8uc3RyaW5naWZ5LFxuICAgICAgICAgICAgICAgIGRhdHVtVG9rZW5pemVyOiBudWxsLFxuICAgICAgICAgICAgICAgIHF1ZXJ5VG9rZW5pemVyOiBudWxsLFxuICAgICAgICAgICAgICAgIG1hdGNoQW55UXVlcnlUb2tlbjogZmFsc2UsXG4gICAgICAgICAgICAgICAgc3VmZmljaWVudDogNSxcbiAgICAgICAgICAgICAgICBpbmRleFJlbW90ZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgc29ydGVyOiBudWxsLFxuICAgICAgICAgICAgICAgIGxvY2FsOiBbXSxcbiAgICAgICAgICAgICAgICBwcmVmZXRjaDogbnVsbCxcbiAgICAgICAgICAgICAgICByZW1vdGU6IG51bGxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBvID0gXy5taXhpbihkZWZhdWx0cywgbyB8fCB7fSk7XG4gICAgICAgICAgICAhby5kYXR1bVRva2VuaXplciAmJiAkLmVycm9yKFwiZGF0dW1Ub2tlbml6ZXIgaXMgcmVxdWlyZWRcIik7XG4gICAgICAgICAgICAhby5xdWVyeVRva2VuaXplciAmJiAkLmVycm9yKFwicXVlcnlUb2tlbml6ZXIgaXMgcmVxdWlyZWRcIik7XG4gICAgICAgICAgICBzb3J0ZXIgPSBvLnNvcnRlcjtcbiAgICAgICAgICAgIG8uc29ydGVyID0gc29ydGVyID8gZnVuY3Rpb24oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4LnNvcnQoc29ydGVyKTtcbiAgICAgICAgICAgIH0gOiBfLmlkZW50aXR5O1xuICAgICAgICAgICAgby5sb2NhbCA9IF8uaXNGdW5jdGlvbihvLmxvY2FsKSA/IG8ubG9jYWwoKSA6IG8ubG9jYWw7XG4gICAgICAgICAgICBvLnByZWZldGNoID0gcGFyc2VQcmVmZXRjaChvLnByZWZldGNoKTtcbiAgICAgICAgICAgIG8ucmVtb3RlID0gcGFyc2VSZW1vdGUoby5yZW1vdGUpO1xuICAgICAgICAgICAgcmV0dXJuIG87XG4gICAgICAgIH07XG4gICAgICAgIGZ1bmN0aW9uIHBhcnNlUHJlZmV0Y2gobykge1xuICAgICAgICAgICAgdmFyIGRlZmF1bHRzO1xuICAgICAgICAgICAgaWYgKCFvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZWZhdWx0cyA9IHtcbiAgICAgICAgICAgICAgICB1cmw6IG51bGwsXG4gICAgICAgICAgICAgICAgdHRsOiAyNCAqIDYwICogNjAgKiAxZTMsXG4gICAgICAgICAgICAgICAgY2FjaGU6IHRydWUsXG4gICAgICAgICAgICAgICAgY2FjaGVLZXk6IG51bGwsXG4gICAgICAgICAgICAgICAgdGh1bWJwcmludDogXCJcIixcbiAgICAgICAgICAgICAgICBwcmVwYXJlOiBfLmlkZW50aXR5LFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogXy5pZGVudGl0eSxcbiAgICAgICAgICAgICAgICB0cmFuc3BvcnQ6IG51bGxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBvID0gXy5pc1N0cmluZyhvKSA/IHtcbiAgICAgICAgICAgICAgICB1cmw6IG9cbiAgICAgICAgICAgIH0gOiBvO1xuICAgICAgICAgICAgbyA9IF8ubWl4aW4oZGVmYXVsdHMsIG8pO1xuICAgICAgICAgICAgIW8udXJsICYmICQuZXJyb3IoXCJwcmVmZXRjaCByZXF1aXJlcyB1cmwgdG8gYmUgc2V0XCIpO1xuICAgICAgICAgICAgby50cmFuc2Zvcm0gPSBvLmZpbHRlciB8fCBvLnRyYW5zZm9ybTtcbiAgICAgICAgICAgIG8uY2FjaGVLZXkgPSBvLmNhY2hlS2V5IHx8IG8udXJsO1xuICAgICAgICAgICAgby50aHVtYnByaW50ID0gVkVSU0lPTiArIG8udGh1bWJwcmludDtcbiAgICAgICAgICAgIG8udHJhbnNwb3J0ID0gby50cmFuc3BvcnQgPyBjYWxsYmFja1RvRGVmZXJyZWQoby50cmFuc3BvcnQpIDogJC5hamF4O1xuICAgICAgICAgICAgcmV0dXJuIG87XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcGFyc2VSZW1vdGUobykge1xuICAgICAgICAgICAgdmFyIGRlZmF1bHRzO1xuICAgICAgICAgICAgaWYgKCFvKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmYXVsdHMgPSB7XG4gICAgICAgICAgICAgICAgdXJsOiBudWxsLFxuICAgICAgICAgICAgICAgIGNhY2hlOiB0cnVlLFxuICAgICAgICAgICAgICAgIHByZXBhcmU6IG51bGwsXG4gICAgICAgICAgICAgICAgcmVwbGFjZTogbnVsbCxcbiAgICAgICAgICAgICAgICB3aWxkY2FyZDogbnVsbCxcbiAgICAgICAgICAgICAgICBsaW1pdGVyOiBudWxsLFxuICAgICAgICAgICAgICAgIHJhdGVMaW1pdEJ5OiBcImRlYm91bmNlXCIsXG4gICAgICAgICAgICAgICAgcmF0ZUxpbWl0V2FpdDogMzAwLFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogXy5pZGVudGl0eSxcbiAgICAgICAgICAgICAgICB0cmFuc3BvcnQ6IG51bGxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBvID0gXy5pc1N0cmluZyhvKSA/IHtcbiAgICAgICAgICAgICAgICB1cmw6IG9cbiAgICAgICAgICAgIH0gOiBvO1xuICAgICAgICAgICAgbyA9IF8ubWl4aW4oZGVmYXVsdHMsIG8pO1xuICAgICAgICAgICAgIW8udXJsICYmICQuZXJyb3IoXCJyZW1vdGUgcmVxdWlyZXMgdXJsIHRvIGJlIHNldFwiKTtcbiAgICAgICAgICAgIG8udHJhbnNmb3JtID0gby5maWx0ZXIgfHwgby50cmFuc2Zvcm07XG4gICAgICAgICAgICBvLnByZXBhcmUgPSB0b1JlbW90ZVByZXBhcmUobyk7XG4gICAgICAgICAgICBvLmxpbWl0ZXIgPSB0b0xpbWl0ZXIobyk7XG4gICAgICAgICAgICBvLnRyYW5zcG9ydCA9IG8udHJhbnNwb3J0ID8gY2FsbGJhY2tUb0RlZmVycmVkKG8udHJhbnNwb3J0KSA6ICQuYWpheDtcbiAgICAgICAgICAgIGRlbGV0ZSBvLnJlcGxhY2U7XG4gICAgICAgICAgICBkZWxldGUgby53aWxkY2FyZDtcbiAgICAgICAgICAgIGRlbGV0ZSBvLnJhdGVMaW1pdEJ5O1xuICAgICAgICAgICAgZGVsZXRlIG8ucmF0ZUxpbWl0V2FpdDtcbiAgICAgICAgICAgIHJldHVybiBvO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIHRvUmVtb3RlUHJlcGFyZShvKSB7XG4gICAgICAgICAgICB2YXIgcHJlcGFyZSwgcmVwbGFjZSwgd2lsZGNhcmQ7XG4gICAgICAgICAgICBwcmVwYXJlID0gby5wcmVwYXJlO1xuICAgICAgICAgICAgcmVwbGFjZSA9IG8ucmVwbGFjZTtcbiAgICAgICAgICAgIHdpbGRjYXJkID0gby53aWxkY2FyZDtcbiAgICAgICAgICAgIGlmIChwcmVwYXJlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHByZXBhcmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocmVwbGFjZSkge1xuICAgICAgICAgICAgICAgIHByZXBhcmUgPSBwcmVwYXJlQnlSZXBsYWNlO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChvLndpbGRjYXJkKSB7XG4gICAgICAgICAgICAgICAgcHJlcGFyZSA9IHByZXBhcmVCeVdpbGRjYXJkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcmVwYXJlID0gaWRlbnRpdHlQcmVwYXJlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHByZXBhcmU7XG4gICAgICAgICAgICBmdW5jdGlvbiBwcmVwYXJlQnlSZXBsYWNlKHF1ZXJ5LCBzZXR0aW5ncykge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLnVybCA9IHJlcGxhY2Uoc2V0dGluZ3MudXJsLCBxdWVyeSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHNldHRpbmdzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gcHJlcGFyZUJ5V2lsZGNhcmQocXVlcnksIHNldHRpbmdzKSB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MudXJsID0gc2V0dGluZ3MudXJsLnJlcGxhY2Uod2lsZGNhcmQsIGVuY29kZVVSSUNvbXBvbmVudChxdWVyeSkpO1xuICAgICAgICAgICAgICAgIHJldHVybiBzZXR0aW5ncztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZ1bmN0aW9uIGlkZW50aXR5UHJlcGFyZShxdWVyeSwgc2V0dGluZ3MpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gc2V0dGluZ3M7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gdG9MaW1pdGVyKG8pIHtcbiAgICAgICAgICAgIHZhciBsaW1pdGVyLCBtZXRob2QsIHdhaXQ7XG4gICAgICAgICAgICBsaW1pdGVyID0gby5saW1pdGVyO1xuICAgICAgICAgICAgbWV0aG9kID0gby5yYXRlTGltaXRCeTtcbiAgICAgICAgICAgIHdhaXQgPSBvLnJhdGVMaW1pdFdhaXQ7XG4gICAgICAgICAgICBpZiAoIWxpbWl0ZXIpIHtcbiAgICAgICAgICAgICAgICBsaW1pdGVyID0gL150aHJvdHRsZSQvaS50ZXN0KG1ldGhvZCkgPyB0aHJvdHRsZSh3YWl0KSA6IGRlYm91bmNlKHdhaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGxpbWl0ZXI7XG4gICAgICAgICAgICBmdW5jdGlvbiBkZWJvdW5jZSh3YWl0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIGRlYm91bmNlKGZuKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfLmRlYm91bmNlKGZuLCB3YWl0KTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gdGhyb3R0bGUod2FpdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiB0aHJvdHRsZShmbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gXy50aHJvdHRsZShmbiwgd2FpdCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBjYWxsYmFja1RvRGVmZXJyZWQoZm4pIHtcbiAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbiB3cmFwcGVyKG8pIHtcbiAgICAgICAgICAgICAgICB2YXIgZGVmZXJyZWQgPSAkLkRlZmVycmVkKCk7XG4gICAgICAgICAgICAgICAgZm4obywgb25TdWNjZXNzLCBvbkVycm9yKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZGVmZXJyZWQ7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gb25TdWNjZXNzKHJlc3ApIHtcbiAgICAgICAgICAgICAgICAgICAgXy5kZWZlcihmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUocmVzcCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBvbkVycm9yKGVycikge1xuICAgICAgICAgICAgICAgICAgICBfLmRlZmVyKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVmZXJyZWQucmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9KCk7XG4gICAgdmFyIEJsb29kaG91bmQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIHZhciBvbGQ7XG4gICAgICAgIG9sZCA9IHdpbmRvdyAmJiB3aW5kb3cuQmxvb2Rob3VuZDtcbiAgICAgICAgZnVuY3Rpb24gQmxvb2Rob3VuZChvKSB7XG4gICAgICAgICAgICBvID0gb1BhcnNlcihvKTtcbiAgICAgICAgICAgIHRoaXMuc29ydGVyID0gby5zb3J0ZXI7XG4gICAgICAgICAgICB0aGlzLmlkZW50aWZ5ID0gby5pZGVudGlmeTtcbiAgICAgICAgICAgIHRoaXMuc3VmZmljaWVudCA9IG8uc3VmZmljaWVudDtcbiAgICAgICAgICAgIHRoaXMuaW5kZXhSZW1vdGUgPSBvLmluZGV4UmVtb3RlO1xuICAgICAgICAgICAgdGhpcy5sb2NhbCA9IG8ubG9jYWw7XG4gICAgICAgICAgICB0aGlzLnJlbW90ZSA9IG8ucmVtb3RlID8gbmV3IFJlbW90ZShvLnJlbW90ZSkgOiBudWxsO1xuICAgICAgICAgICAgdGhpcy5wcmVmZXRjaCA9IG8ucHJlZmV0Y2ggPyBuZXcgUHJlZmV0Y2goby5wcmVmZXRjaCkgOiBudWxsO1xuICAgICAgICAgICAgdGhpcy5pbmRleCA9IG5ldyBTZWFyY2hJbmRleCh7XG4gICAgICAgICAgICAgICAgaWRlbnRpZnk6IHRoaXMuaWRlbnRpZnksXG4gICAgICAgICAgICAgICAgZGF0dW1Ub2tlbml6ZXI6IG8uZGF0dW1Ub2tlbml6ZXIsXG4gICAgICAgICAgICAgICAgcXVlcnlUb2tlbml6ZXI6IG8ucXVlcnlUb2tlbml6ZXJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgby5pbml0aWFsaXplICE9PSBmYWxzZSAmJiB0aGlzLmluaXRpYWxpemUoKTtcbiAgICAgICAgfVxuICAgICAgICBCbG9vZGhvdW5kLm5vQ29uZmxpY3QgPSBmdW5jdGlvbiBub0NvbmZsaWN0KCkge1xuICAgICAgICAgICAgd2luZG93ICYmICh3aW5kb3cuQmxvb2Rob3VuZCA9IG9sZCk7XG4gICAgICAgICAgICByZXR1cm4gQmxvb2Rob3VuZDtcbiAgICAgICAgfTtcbiAgICAgICAgQmxvb2Rob3VuZC50b2tlbml6ZXJzID0gdG9rZW5pemVycztcbiAgICAgICAgXy5taXhpbihCbG9vZGhvdW5kLnByb3RvdHlwZSwge1xuICAgICAgICAgICAgX190dEFkYXB0ZXI6IGZ1bmN0aW9uIHR0QWRhcHRlcigpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXM7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucmVtb3RlID8gd2l0aEFzeW5jIDogd2l0aG91dEFzeW5jO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHdpdGhBc3luYyhxdWVyeSwgc3luYywgYXN5bmMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoYXQuc2VhcmNoKHF1ZXJ5LCBzeW5jLCBhc3luYyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHdpdGhvdXRBc3luYyhxdWVyeSwgc3luYykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhhdC5zZWFyY2gocXVlcnksIHN5bmMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfbG9hZFByZWZldGNoOiBmdW5jdGlvbiBsb2FkUHJlZmV0Y2goKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLCBkZWZlcnJlZCwgc2VyaWFsaXplZDtcbiAgICAgICAgICAgICAgICBkZWZlcnJlZCA9ICQuRGVmZXJyZWQoKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMucHJlZmV0Y2gpIHtcbiAgICAgICAgICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc2VyaWFsaXplZCA9IHRoaXMucHJlZmV0Y2guZnJvbUNhY2hlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5pbmRleC5ib290c3RyYXAoc2VyaWFsaXplZCk7XG4gICAgICAgICAgICAgICAgICAgIGRlZmVycmVkLnJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnByZWZldGNoLmZyb21OZXR3b3JrKGRvbmUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZGVmZXJyZWQucHJvbWlzZSgpO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGRvbmUoZXJyLCBkYXRhKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBkZWZlcnJlZC5yZWplY3QoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB0aGF0LmFkZChkYXRhKTtcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5wcmVmZXRjaC5zdG9yZSh0aGF0LmluZGV4LnNlcmlhbGl6ZSgpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmZXJyZWQucmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfaW5pdGlhbGl6ZTogZnVuY3Rpb24gaW5pdGlhbGl6ZSgpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhhdCA9IHRoaXMsIGRlZmVycmVkO1xuICAgICAgICAgICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgICAgICAgICAodGhpcy5pbml0UHJvbWlzZSA9IHRoaXMuX2xvYWRQcmVmZXRjaCgpKS5kb25lKGFkZExvY2FsVG9JbmRleCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5pdFByb21pc2U7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gYWRkTG9jYWxUb0luZGV4KCkge1xuICAgICAgICAgICAgICAgICAgICB0aGF0LmFkZCh0aGF0LmxvY2FsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW5pdGlhbGl6ZTogZnVuY3Rpb24gaW5pdGlhbGl6ZShmb3JjZSkge1xuICAgICAgICAgICAgICAgIHJldHVybiAhdGhpcy5pbml0UHJvbWlzZSB8fCBmb3JjZSA/IHRoaXMuX2luaXRpYWxpemUoKSA6IHRoaXMuaW5pdFByb21pc2U7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWRkOiBmdW5jdGlvbiBhZGQoZGF0YSkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5kZXguYWRkKGRhdGEpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gZ2V0KGlkcykge1xuICAgICAgICAgICAgICAgIGlkcyA9IF8uaXNBcnJheShpZHMpID8gaWRzIDogW10uc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmluZGV4LmdldChpZHMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlYXJjaDogZnVuY3Rpb24gc2VhcmNoKHF1ZXJ5LCBzeW5jLCBhc3luYykge1xuICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcywgbG9jYWw7XG4gICAgICAgICAgICAgICAgc3luYyA9IHN5bmMgfHwgXy5ub29wO1xuICAgICAgICAgICAgICAgIGFzeW5jID0gYXN5bmMgfHwgXy5ub29wO1xuICAgICAgICAgICAgICAgIGxvY2FsID0gdGhpcy5zb3J0ZXIodGhpcy5pbmRleC5zZWFyY2gocXVlcnkpKTtcbiAgICAgICAgICAgICAgICBzeW5jKHRoaXMucmVtb3RlID8gbG9jYWwuc2xpY2UoKSA6IGxvY2FsKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yZW1vdGUgJiYgbG9jYWwubGVuZ3RoIDwgdGhpcy5zdWZmaWNpZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmVtb3RlLmdldChxdWVyeSwgcHJvY2Vzc1JlbW90ZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnJlbW90ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbW90ZS5jYW5jZWxMYXN0UmVxdWVzdCgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBwcm9jZXNzUmVtb3RlKHJlbW90ZSkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm9uRHVwbGljYXRlcyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICBfLmVhY2gocmVtb3RlLCBmdW5jdGlvbihyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAhXy5zb21lKGxvY2FsLCBmdW5jdGlvbihsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoYXQuaWRlbnRpZnkocikgPT09IHRoYXQuaWRlbnRpZnkobCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KSAmJiBub25EdXBsaWNhdGVzLnB1c2gocik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB0aGF0LmluZGV4UmVtb3RlICYmIHRoYXQuYWRkKG5vbkR1cGxpY2F0ZXMpO1xuICAgICAgICAgICAgICAgICAgICBhc3luYyhub25EdXBsaWNhdGVzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWxsOiBmdW5jdGlvbiBhbGwoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5kZXguYWxsKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaW5kZXgucmVzZXQoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbGVhclByZWZldGNoQ2FjaGU6IGZ1bmN0aW9uIGNsZWFyUHJlZmV0Y2hDYWNoZSgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnByZWZldGNoICYmIHRoaXMucHJlZmV0Y2guY2xlYXIoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbGVhclJlbW90ZUNhY2hlOiBmdW5jdGlvbiBjbGVhclJlbW90ZUNhY2hlKCkge1xuICAgICAgICAgICAgICAgIFRyYW5zcG9ydC5yZXNldENhY2hlKCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdHRBZGFwdGVyOiBmdW5jdGlvbiB0dEFkYXB0ZXIoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX190dEFkYXB0ZXIoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiBCbG9vZGhvdW5kO1xuICAgIH0oKTtcbiAgICByZXR1cm4gQmxvb2Rob3VuZDtcbn0pO1xuXG4oZnVuY3Rpb24ocm9vdCwgZmFjdG9yeSkge1xuICAgIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoWyBcImpxdWVyeVwiIF0sIGZ1bmN0aW9uKGEwKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFjdG9yeShhMCk7XG4gICAgICAgIH0pO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoXCJqcXVlcnlcIikpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGZhY3Rvcnkocm9vdFtcImpRdWVyeVwiXSk7XG4gICAgfVxufSkodGhpcywgZnVuY3Rpb24oJCkge1xuICAgIHZhciBfID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaXNNc2llOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gLyhtc2llfHRyaWRlbnQpL2kudGVzdChuYXZpZ2F0b3IudXNlckFnZW50KSA/IG5hdmlnYXRvci51c2VyQWdlbnQubWF0Y2goLyhtc2llIHxydjopKFxcZCsoLlxcZCspPykvaSlbMl0gOiBmYWxzZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0JsYW5rU3RyaW5nOiBmdW5jdGlvbihzdHIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gIXN0ciB8fCAvXlxccyokLy50ZXN0KHN0cik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXNjYXBlUmVnRXhDaGFyczogZnVuY3Rpb24oc3RyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9bXFwtXFxbXFxdXFwvXFx7XFx9XFwoXFwpXFwqXFwrXFw/XFwuXFxcXFxcXlxcJFxcfF0vZywgXCJcXFxcJCZcIik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaXNTdHJpbmc6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSBcInN0cmluZ1wiO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzTnVtYmVyOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gXCJudW1iZXJcIjtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0FycmF5OiAkLmlzQXJyYXksXG4gICAgICAgICAgICBpc0Z1bmN0aW9uOiAkLmlzRnVuY3Rpb24sXG4gICAgICAgICAgICBpc09iamVjdDogJC5pc1BsYWluT2JqZWN0LFxuICAgICAgICAgICAgaXNVbmRlZmluZWQ6IGZ1bmN0aW9uKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0eXBlb2Ygb2JqID09PSBcInVuZGVmaW5lZFwiO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzRWxlbWVudDogZnVuY3Rpb24ob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuICEhKG9iaiAmJiBvYmoubm9kZVR5cGUgPT09IDEpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzSlF1ZXJ5OiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgJDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0b1N0cjogZnVuY3Rpb24gdG9TdHIocykge1xuICAgICAgICAgICAgICAgIHJldHVybiBfLmlzVW5kZWZpbmVkKHMpIHx8IHMgPT09IG51bGwgPyBcIlwiIDogcyArIFwiXCI7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYmluZDogJC5wcm94eSxcbiAgICAgICAgICAgIGVhY2g6IGZ1bmN0aW9uKGNvbGxlY3Rpb24sIGNiKSB7XG4gICAgICAgICAgICAgICAgJC5lYWNoKGNvbGxlY3Rpb24sIHJldmVyc2VBcmdzKTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiByZXZlcnNlQXJncyhpbmRleCwgdmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGNiKHZhbHVlLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1hcDogJC5tYXAsXG4gICAgICAgICAgICBmaWx0ZXI6ICQuZ3JlcCxcbiAgICAgICAgICAgIGV2ZXJ5OiBmdW5jdGlvbihvYmosIHRlc3QpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBpZiAoIW9iaikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAkLmVhY2gob2JqLCBmdW5jdGlvbihrZXksIHZhbCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIShyZXN1bHQgPSB0ZXN0LmNhbGwobnVsbCwgdmFsLCBrZXksIG9iaikpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gISFyZXN1bHQ7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc29tZTogZnVuY3Rpb24ob2JqLCB0ZXN0KSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmICghb2JqKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICQuZWFjaChvYmosIGZ1bmN0aW9uKGtleSwgdmFsKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQgPSB0ZXN0LmNhbGwobnVsbCwgdmFsLCBrZXksIG9iaikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiAhIXJlc3VsdDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtaXhpbjogJC5leHRlbmQsXG4gICAgICAgICAgICBpZGVudGl0eTogZnVuY3Rpb24oeCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB4O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsb25lOiBmdW5jdGlvbihvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gJC5leHRlbmQodHJ1ZSwge30sIG9iaik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0SWRHZW5lcmF0b3I6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHZhciBjb3VudGVyID0gMDtcbiAgICAgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjb3VudGVyKys7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB0ZW1wbGF0aWZ5OiBmdW5jdGlvbiB0ZW1wbGF0aWZ5KG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiAkLmlzRnVuY3Rpb24ob2JqKSA/IG9iaiA6IHRlbXBsYXRlO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHRlbXBsYXRlKCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gU3RyaW5nKG9iaik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlZmVyOiBmdW5jdGlvbihmbikge1xuICAgICAgICAgICAgICAgIHNldFRpbWVvdXQoZm4sIDApO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlYm91bmNlOiBmdW5jdGlvbihmdW5jLCB3YWl0LCBpbW1lZGlhdGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgdGltZW91dCwgcmVzdWx0O1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGNvbnRleHQgPSB0aGlzLCBhcmdzID0gYXJndW1lbnRzLCBsYXRlciwgY2FsbE5vdztcbiAgICAgICAgICAgICAgICAgICAgbGF0ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFpbW1lZGlhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBjYWxsTm93ID0gaW1tZWRpYXRlICYmICF0aW1lb3V0O1xuICAgICAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGxhdGVyLCB3YWl0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNhbGxOb3cpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkoY29udGV4dCwgYXJncyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHRocm90dGxlOiBmdW5jdGlvbihmdW5jLCB3YWl0KSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRleHQsIGFyZ3MsIHRpbWVvdXQsIHJlc3VsdCwgcHJldmlvdXMsIGxhdGVyO1xuICAgICAgICAgICAgICAgIHByZXZpb3VzID0gMDtcbiAgICAgICAgICAgICAgICBsYXRlciA9IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICBwcmV2aW91cyA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbm93ID0gbmV3IERhdGUoKSwgcmVtYWluaW5nID0gd2FpdCAtIChub3cgLSBwcmV2aW91cyk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQgPSB0aGlzO1xuICAgICAgICAgICAgICAgICAgICBhcmdzID0gYXJndW1lbnRzO1xuICAgICAgICAgICAgICAgICAgICBpZiAocmVtYWluaW5nIDw9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVvdXQgPSBudWxsO1xuICAgICAgICAgICAgICAgICAgICAgICAgcHJldmlvdXMgPSBub3c7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCF0aW1lb3V0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lb3V0ID0gc2V0VGltZW91dChsYXRlciwgcmVtYWluaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3RyaW5naWZ5OiBmdW5jdGlvbih2YWwpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXy5pc1N0cmluZyh2YWwpID8gdmFsIDogSlNPTi5zdHJpbmdpZnkodmFsKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBndWlkOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBfcDgocykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcCA9IChNYXRoLnJhbmRvbSgpLnRvU3RyaW5nKDE2KSArIFwiMDAwMDAwMDAwXCIpLnN1YnN0cigyLCA4KTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHMgPyBcIi1cIiArIHAuc3Vic3RyKDAsIDQpICsgXCItXCIgKyBwLnN1YnN0cig0LCA0KSA6IHA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBcInR0LVwiICsgX3A4KCkgKyBfcDgodHJ1ZSkgKyBfcDgodHJ1ZSkgKyBfcDgoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBub29wOiBmdW5jdGlvbigpIHt9XG4gICAgICAgIH07XG4gICAgfSgpO1xuICAgIHZhciBXV1cgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIHZhciBkZWZhdWx0Q2xhc3NOYW1lcyA9IHtcbiAgICAgICAgICAgIHdyYXBwZXI6IFwidHdpdHRlci10eXBlYWhlYWRcIixcbiAgICAgICAgICAgIGlucHV0OiBcInR0LWlucHV0XCIsXG4gICAgICAgICAgICBoaW50OiBcInR0LWhpbnRcIixcbiAgICAgICAgICAgIG1lbnU6IFwidHQtbWVudVwiLFxuICAgICAgICAgICAgZGF0YXNldDogXCJ0dC1kYXRhc2V0XCIsXG4gICAgICAgICAgICBzdWdnZXN0aW9uOiBcInR0LXN1Z2dlc3Rpb25cIixcbiAgICAgICAgICAgIHNlbGVjdGFibGU6IFwidHQtc2VsZWN0YWJsZVwiLFxuICAgICAgICAgICAgZW1wdHk6IFwidHQtZW1wdHlcIixcbiAgICAgICAgICAgIG9wZW46IFwidHQtb3BlblwiLFxuICAgICAgICAgICAgY3Vyc29yOiBcInR0LWN1cnNvclwiLFxuICAgICAgICAgICAgaGlnaGxpZ2h0OiBcInR0LWhpZ2hsaWdodFwiXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBidWlsZDtcbiAgICAgICAgZnVuY3Rpb24gYnVpbGQobykge1xuICAgICAgICAgICAgdmFyIHd3dywgY2xhc3NlcztcbiAgICAgICAgICAgIGNsYXNzZXMgPSBfLm1peGluKHt9LCBkZWZhdWx0Q2xhc3NOYW1lcywgbyk7XG4gICAgICAgICAgICB3d3cgPSB7XG4gICAgICAgICAgICAgICAgY3NzOiBidWlsZENzcygpLFxuICAgICAgICAgICAgICAgIGNsYXNzZXM6IGNsYXNzZXMsXG4gICAgICAgICAgICAgICAgaHRtbDogYnVpbGRIdG1sKGNsYXNzZXMpLFxuICAgICAgICAgICAgICAgIHNlbGVjdG9yczogYnVpbGRTZWxlY3RvcnMoY2xhc3NlcylcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGNzczogd3d3LmNzcyxcbiAgICAgICAgICAgICAgICBodG1sOiB3d3cuaHRtbCxcbiAgICAgICAgICAgICAgICBjbGFzc2VzOiB3d3cuY2xhc3NlcyxcbiAgICAgICAgICAgICAgICBzZWxlY3RvcnM6IHd3dy5zZWxlY3RvcnMsXG4gICAgICAgICAgICAgICAgbWl4aW46IGZ1bmN0aW9uKG8pIHtcbiAgICAgICAgICAgICAgICAgICAgXy5taXhpbihvLCB3d3cpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gYnVpbGRIdG1sKGMpIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgd3JhcHBlcjogJzxzcGFuIGNsYXNzPVwiJyArIGMud3JhcHBlciArICdcIj48L3NwYW4+JyxcbiAgICAgICAgICAgICAgICBtZW51OiAnPGRpdiByb2xlPVwibGlzdGJveFwiIGNsYXNzPVwiJyArIGMubWVudSArICdcIj48L2Rpdj4nXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGJ1aWxkU2VsZWN0b3JzKGNsYXNzZXMpIHtcbiAgICAgICAgICAgIHZhciBzZWxlY3RvcnMgPSB7fTtcbiAgICAgICAgICAgIF8uZWFjaChjbGFzc2VzLCBmdW5jdGlvbih2LCBrKSB7XG4gICAgICAgICAgICAgICAgc2VsZWN0b3JzW2tdID0gXCIuXCIgKyB2O1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm4gc2VsZWN0b3JzO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGJ1aWxkQ3NzKCkge1xuICAgICAgICAgICAgdmFyIGNzcyA9IHtcbiAgICAgICAgICAgICAgICB3cmFwcGVyOiB7XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiBcInJlbGF0aXZlXCIsXG4gICAgICAgICAgICAgICAgICAgIGRpc3BsYXk6IFwiaW5saW5lLWJsb2NrXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGhpbnQ6IHtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IFwiYWJzb2x1dGVcIixcbiAgICAgICAgICAgICAgICAgICAgdG9wOiBcIjBcIixcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogXCIwXCIsXG4gICAgICAgICAgICAgICAgICAgIGJvcmRlckNvbG9yOiBcInRyYW5zcGFyZW50XCIsXG4gICAgICAgICAgICAgICAgICAgIGJveFNoYWRvdzogXCJub25lXCIsXG4gICAgICAgICAgICAgICAgICAgIG9wYWNpdHk6IFwiMVwiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBpbnB1dDoge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbjogXCJyZWxhdGl2ZVwiLFxuICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbEFsaWduOiBcInRvcFwiLFxuICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kQ29sb3I6IFwidHJhbnNwYXJlbnRcIlxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgaW5wdXRXaXRoTm9IaW50OiB7XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uOiBcInJlbGF0aXZlXCIsXG4gICAgICAgICAgICAgICAgICAgIHZlcnRpY2FsQWxpZ246IFwidG9wXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG1lbnU6IHtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb246IFwiYWJzb2x1dGVcIixcbiAgICAgICAgICAgICAgICAgICAgdG9wOiBcIjEwMCVcIixcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogXCIwXCIsXG4gICAgICAgICAgICAgICAgICAgIHpJbmRleDogXCIxMDBcIixcbiAgICAgICAgICAgICAgICAgICAgZGlzcGxheTogXCJub25lXCJcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGx0cjoge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0OiBcIjBcIixcbiAgICAgICAgICAgICAgICAgICAgcmlnaHQ6IFwiYXV0b1wiXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBydGw6IHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogXCJhdXRvXCIsXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0OiBcIiAwXCJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKF8uaXNNc2llKCkpIHtcbiAgICAgICAgICAgICAgICBfLm1peGluKGNzcy5pbnB1dCwge1xuICAgICAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kSW1hZ2U6IFwidXJsKGRhdGE6aW1hZ2UvZ2lmO2Jhc2U2NCxSMGxHT0RsaEFRQUJBSUFBQUFBQUFQLy8veUg1QkFFQUFBQUFMQUFBQUFBQkFBRUFBQUlCUkFBNylcIlxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNzcztcbiAgICAgICAgfVxuICAgIH0oKTtcbiAgICB2YXIgRXZlbnRCdXMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIHZhciBuYW1lc3BhY2UsIGRlcHJlY2F0aW9uTWFwO1xuICAgICAgICBuYW1lc3BhY2UgPSBcInR5cGVhaGVhZDpcIjtcbiAgICAgICAgZGVwcmVjYXRpb25NYXAgPSB7XG4gICAgICAgICAgICByZW5kZXI6IFwicmVuZGVyZWRcIixcbiAgICAgICAgICAgIGN1cnNvcmNoYW5nZTogXCJjdXJzb3JjaGFuZ2VkXCIsXG4gICAgICAgICAgICBzZWxlY3Q6IFwic2VsZWN0ZWRcIixcbiAgICAgICAgICAgIGF1dG9jb21wbGV0ZTogXCJhdXRvY29tcGxldGVkXCJcbiAgICAgICAgfTtcbiAgICAgICAgZnVuY3Rpb24gRXZlbnRCdXMobykge1xuICAgICAgICAgICAgaWYgKCFvIHx8ICFvLmVsKSB7XG4gICAgICAgICAgICAgICAgJC5lcnJvcihcIkV2ZW50QnVzIGluaXRpYWxpemVkIHdpdGhvdXQgZWxcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLiRlbCA9ICQoby5lbCk7XG4gICAgICAgIH1cbiAgICAgICAgXy5taXhpbihFdmVudEJ1cy5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIF90cmlnZ2VyOiBmdW5jdGlvbih0eXBlLCBhcmdzKSB7XG4gICAgICAgICAgICAgICAgdmFyICRlID0gJC5FdmVudChuYW1lc3BhY2UgKyB0eXBlKTtcbiAgICAgICAgICAgICAgICB0aGlzLiRlbC50cmlnZ2VyLmNhbGwodGhpcy4kZWwsICRlLCBhcmdzIHx8IFtdKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gJGU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYmVmb3JlOiBmdW5jdGlvbih0eXBlKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MsICRlO1xuICAgICAgICAgICAgICAgIGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgICAgICAgICAgJGUgPSB0aGlzLl90cmlnZ2VyKFwiYmVmb3JlXCIgKyB0eXBlLCBhcmdzKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gJGUuaXNEZWZhdWx0UHJldmVudGVkKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdHJpZ2dlcjogZnVuY3Rpb24odHlwZSkge1xuICAgICAgICAgICAgICAgIHZhciBkZXByZWNhdGVkVHlwZTtcbiAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyKHR5cGUsIFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgICAgICAgICAgICAgaWYgKGRlcHJlY2F0ZWRUeXBlID0gZGVwcmVjYXRpb25NYXBbdHlwZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlcihkZXByZWNhdGVkVHlwZSwgW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gRXZlbnRCdXM7XG4gICAgfSgpO1xuICAgIHZhciBFdmVudEVtaXR0ZXIgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIHZhciBzcGxpdHRlciA9IC9cXHMrLywgbmV4dFRpY2sgPSBnZXROZXh0VGljaygpO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgb25TeW5jOiBvblN5bmMsXG4gICAgICAgICAgICBvbkFzeW5jOiBvbkFzeW5jLFxuICAgICAgICAgICAgb2ZmOiBvZmYsXG4gICAgICAgICAgICB0cmlnZ2VyOiB0cmlnZ2VyXG4gICAgICAgIH07XG4gICAgICAgIGZ1bmN0aW9uIG9uKG1ldGhvZCwgdHlwZXMsIGNiLCBjb250ZXh0KSB7XG4gICAgICAgICAgICB2YXIgdHlwZTtcbiAgICAgICAgICAgIGlmICghY2IpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHR5cGVzID0gdHlwZXMuc3BsaXQoc3BsaXR0ZXIpO1xuICAgICAgICAgICAgY2IgPSBjb250ZXh0ID8gYmluZENvbnRleHQoY2IsIGNvbnRleHQpIDogY2I7XG4gICAgICAgICAgICB0aGlzLl9jYWxsYmFja3MgPSB0aGlzLl9jYWxsYmFja3MgfHwge307XG4gICAgICAgICAgICB3aGlsZSAodHlwZSA9IHR5cGVzLnNoaWZ0KCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9jYWxsYmFja3NbdHlwZV0gPSB0aGlzLl9jYWxsYmFja3NbdHlwZV0gfHwge1xuICAgICAgICAgICAgICAgICAgICBzeW5jOiBbXSxcbiAgICAgICAgICAgICAgICAgICAgYXN5bmM6IFtdXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLl9jYWxsYmFja3NbdHlwZV1bbWV0aG9kXS5wdXNoKGNiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIG9uQXN5bmModHlwZXMsIGNiLCBjb250ZXh0KSB7XG4gICAgICAgICAgICByZXR1cm4gb24uY2FsbCh0aGlzLCBcImFzeW5jXCIsIHR5cGVzLCBjYiwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gb25TeW5jKHR5cGVzLCBjYiwgY29udGV4dCkge1xuICAgICAgICAgICAgcmV0dXJuIG9uLmNhbGwodGhpcywgXCJzeW5jXCIsIHR5cGVzLCBjYiwgY29udGV4dCk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gb2ZmKHR5cGVzKSB7XG4gICAgICAgICAgICB2YXIgdHlwZTtcbiAgICAgICAgICAgIGlmICghdGhpcy5fY2FsbGJhY2tzKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0eXBlcyA9IHR5cGVzLnNwbGl0KHNwbGl0dGVyKTtcbiAgICAgICAgICAgIHdoaWxlICh0eXBlID0gdHlwZXMuc2hpZnQoKSkge1xuICAgICAgICAgICAgICAgIGRlbGV0ZSB0aGlzLl9jYWxsYmFja3NbdHlwZV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiB0cmlnZ2VyKHR5cGVzKSB7XG4gICAgICAgICAgICB2YXIgdHlwZSwgY2FsbGJhY2tzLCBhcmdzLCBzeW5jRmx1c2gsIGFzeW5jRmx1c2g7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX2NhbGxiYWNrcykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHlwZXMgPSB0eXBlcy5zcGxpdChzcGxpdHRlcik7XG4gICAgICAgICAgICBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgd2hpbGUgKCh0eXBlID0gdHlwZXMuc2hpZnQoKSkgJiYgKGNhbGxiYWNrcyA9IHRoaXMuX2NhbGxiYWNrc1t0eXBlXSkpIHtcbiAgICAgICAgICAgICAgICBzeW5jRmx1c2ggPSBnZXRGbHVzaChjYWxsYmFja3Muc3luYywgdGhpcywgWyB0eXBlIF0uY29uY2F0KGFyZ3MpKTtcbiAgICAgICAgICAgICAgICBhc3luY0ZsdXNoID0gZ2V0Rmx1c2goY2FsbGJhY2tzLmFzeW5jLCB0aGlzLCBbIHR5cGUgXS5jb25jYXQoYXJncykpO1xuICAgICAgICAgICAgICAgIHN5bmNGbHVzaCgpICYmIG5leHRUaWNrKGFzeW5jRmx1c2gpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2V0Rmx1c2goY2FsbGJhY2tzLCBjb250ZXh0LCBhcmdzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmx1c2g7XG4gICAgICAgICAgICBmdW5jdGlvbiBmbHVzaCgpIHtcbiAgICAgICAgICAgICAgICB2YXIgY2FuY2VsbGVkO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSBjYWxsYmFja3MubGVuZ3RoOyAhY2FuY2VsbGVkICYmIGkgPCBsZW47IGkgKz0gMSkge1xuICAgICAgICAgICAgICAgICAgICBjYW5jZWxsZWQgPSBjYWxsYmFja3NbaV0uYXBwbHkoY29udGV4dCwgYXJncykgPT09IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gIWNhbmNlbGxlZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBnZXROZXh0VGljaygpIHtcbiAgICAgICAgICAgIHZhciBuZXh0VGlja0ZuO1xuICAgICAgICAgICAgaWYgKHdpbmRvdy5zZXRJbW1lZGlhdGUpIHtcbiAgICAgICAgICAgICAgICBuZXh0VGlja0ZuID0gZnVuY3Rpb24gbmV4dFRpY2tTZXRJbW1lZGlhdGUoZm4pIHtcbiAgICAgICAgICAgICAgICAgICAgc2V0SW1tZWRpYXRlKGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbmV4dFRpY2tGbiA9IGZ1bmN0aW9uIG5leHRUaWNrU2V0VGltZW91dChmbikge1xuICAgICAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm4oKTtcbiAgICAgICAgICAgICAgICAgICAgfSwgMCk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXh0VGlja0ZuO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGJpbmRDb250ZXh0KGZuLCBjb250ZXh0KSB7XG4gICAgICAgICAgICByZXR1cm4gZm4uYmluZCA/IGZuLmJpbmQoY29udGV4dCkgOiBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBmbi5hcHBseShjb250ZXh0LCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCkpO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH0oKTtcbiAgICB2YXIgaGlnaGxpZ2h0ID0gZnVuY3Rpb24oZG9jKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICB2YXIgZGVmYXVsdHMgPSB7XG4gICAgICAgICAgICBub2RlOiBudWxsLFxuICAgICAgICAgICAgcGF0dGVybjogbnVsbCxcbiAgICAgICAgICAgIHRhZ05hbWU6IFwic3Ryb25nXCIsXG4gICAgICAgICAgICBjbGFzc05hbWU6IG51bGwsXG4gICAgICAgICAgICB3b3Jkc09ubHk6IGZhbHNlLFxuICAgICAgICAgICAgY2FzZVNlbnNpdGl2ZTogZmFsc2UsXG4gICAgICAgICAgICBkaWFjcml0aWNJbnNlbnNpdGl2ZTogZmFsc2VcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGFjY2VudGVkID0ge1xuICAgICAgICAgICAgQTogXCJbQWHCqsOALcOFw6Atw6XEgC3EhceNx47IgC3Ig8imyKfhtKzhtYPhuIDhuIHhuprhuqAt4bqj4oKQ4oSA4oSB4oS74pKc4pK24pOQ442xLeONtOOOgC3jjoTjjojjjonjjqkt446v44+C44+K44+f44+/77yh772BXVwiLFxuICAgICAgICAgICAgQjogXCJbQmLhtK7htYfhuIIt4biH4oSs4pKd4pK34pOR4420446FLeOOh+OPg+OPiOOPlOOPne+8ou+9gl1cIixcbiAgICAgICAgICAgIEM6IFwiW0Njw4fDp8SGLcSN4bac4oSA4oSC4oSD4oSF4oSG4oSt4oWt4oW94pKe4pK44pOS4422446I446J446d446g446k44+ELeOPh++8o++9g11cIixcbiAgICAgICAgICAgIEQ6IFwiW0RkxI7Ej8eELceGx7Etx7PhtLDhtYjhuIot4biT4oWF4oWG4oWu4oW+4pKf4pK54pOT44uP442y4423LeONueOOl+OOrS3jjq/jj4Xjj4jvvKTvvYRdXCIsXG4gICAgICAgICAgICBFOiBcIltFZcOILcOLw6gtw6vEki3Em8iELciHyKjIqeG0seG1ieG4mC3huJvhurgt4bq94oKR4oSh4oSv4oSw4oWH4pKg4pK64pOU44mQ44uN44uO77yl772FXVwiLFxuICAgICAgICAgICAgRjogXCJbRmbhtqDhuJ7huJ/ihInihLHihLvikqHikrvik5Xjjoot446M446Z76yALe+shO+8pu+9hl1cIixcbiAgICAgICAgICAgIEc6IFwiW0dnxJwtxKPHpsenx7THteG0s+G1jeG4oOG4oeKEiuKSouKSvOKTluOLjOOLjeOOh+OOjS3jjo/jjpPjjqzjj4bjj4njj5Ljj7/vvKfvvYddXCIsXG4gICAgICAgICAgICBIOiBcIltIaMSkxKXInsifyrDhtLThuKIt4bir4bqW4oSLLeKEjuKSo+KSveKTl+OLjOONseOOkC3jjpTjj4rjj4vjj5fvvKjvvYhdXCIsXG4gICAgICAgICAgICBJOiBcIltJacOMLcOPw6wtw6/EqC3EsMSyxLPHj8eQyIgtyIvhtLXhtaLhuKzhuK3hu4gt4buL4oGx4oSQ4oSR4oS54oWI4oWgLeKFo+KFpS3ihajiharihavihbAt4oWz4oW1LeKFuOKFuuKFu+KSpOKSvuKTmOONuuOPjOOPle+sge+sg++8qe+9iV1cIixcbiAgICAgICAgICAgIEo6IFwiW0pqxLItxLXHhy3HjMewyrLhtLbihYnikqXikr/ik5nisbzvvKrvvYpdXCIsXG4gICAgICAgICAgICBLOiBcIltLa8S2xLfHqMep4bS34bWP4biwLeG4teKEquKSpuKTgOKTmuOOhOOOheOOieOOj+OOkeOOmOOOnuOOouOOpuOOquOOuOOOvuOPgOOPhuOPjS3jj4/vvKvvvYtdXCIsXG4gICAgICAgICAgICBMOiBcIltMbMS5LcWAx4ctx4nLoeG0uOG4tuG4t+G4ui3huL3ihJLihJPihKHihazihbzikqfik4Hik5vji4/jjojjjonjj5At44+T44+V44+W44+/76yC76yE77ys772MXVwiLFxuICAgICAgICAgICAgTTogXCJbTW3htLnhtZDhuL4t4bmD4oSg4oSi4oSz4oWv4oW/4pKo4pOC4pOc4423LeONueOOg+OOhuOOjuOOkuOOluOOmS3jjqjjjqvjjrPjjrfjjrnjjr3jjr/jj4Hjj4Ljj47jj5Djj5Qt44+W44+Y44+Z44+e44+f77yt772NXVwiLFxuICAgICAgICAgICAgTjogXCJbTm7DkcOxxYMtxYnHii3HjMe4x7nhtLrhuYQt4bmL4oG/4oSV4oSW4pKp4pOD4pOd446B446L446a446x4461446744+M44+R77yu772OXVwiLFxuICAgICAgICAgICAgTzogXCJbT2/CusOSLcOWw7Itw7bFjC3FkcagxqHHkceSx6rHq8iMLciPyK7Ir+G0vOG1kuG7jC3hu4/igpLihIXihJbihLTikqrik4Tik57jjbXjj4fjj5Ljj5bvvK/vvY9dXCIsXG4gICAgICAgICAgICBQOiBcIltQcOG0vuG1luG5lC3huZfihJnikqvik4Xik5/jiZDjjbHjjbbjjoDjjorjjqkt446s446w4460446644+L44+XLeOPmu+8sO+9kF1cIixcbiAgICAgICAgICAgIFE6IFwiW1Fx4oSa4pKs4pOG4pOg44+D77yx772RXVwiLFxuICAgICAgICAgICAgUjogXCJbUnLFlC3FmciQLciTyrPhtL/htaPhuZgt4bmb4bme4bmf4oKo4oSbLeKEneKSreKTh+KToeOLjeONtOOOrS3jjq/jj5rjj5vvvLLvvZJdXCIsXG4gICAgICAgICAgICBTOiBcIltTc8WaLcWhxb/ImMiZy6LhuaAt4bmj4oKo4oSB4oSg4pKu4pOI4pOi446n446o446uLeOOs+OPm+OPnO+shu+8s++9k11cIixcbiAgICAgICAgICAgIFQ6IFwiW1R0xaItxaXImsib4bWA4bWX4bmqLeG5seG6l+KEoeKEouKSr+KTieKTo+OJkOOLj+OOlOOPj++she+shu+8tO+9lF1cIixcbiAgICAgICAgICAgIFU6IFwiW1V1w5ktw5zDuS3DvMWoLcWzxq/GsMeTx5TIlC3Il+G1geG1mOG1pOG5si3hubfhu6Qt4bun4oSG4pKw4pOK4pOk442z442677y1772VXVwiLFxuICAgICAgICAgICAgVjogXCJbVnbhtZvhtaXhubwt4bm/4oWjLeKFp+KFsy3ihbfikrHik4vik6Xisb3ji47jjbXjjrQt446544+c44+e77y2772WXVwiLFxuICAgICAgICAgICAgVzogXCJbV3fFtMW1yrfhtYLhuoAt4bqJ4bqY4pKy4pOM4pOm4466LeOOv+OPne+8t++9l11cIixcbiAgICAgICAgICAgIFg6IFwiW1h4y6Phuoot4bqN4oKT4oS74oWoLeKFq+KFuC3ihbvikrPik43ik6fjj5PvvLjvvZhdXCIsXG4gICAgICAgICAgICBZOiBcIltZecOdw73Dv8W2LcW4yLLIs8q44bqO4bqP4bqZ4buyLeG7ueKStOKTjuKTqOOPie+8ue+9mV1cIixcbiAgICAgICAgICAgIFo6IFwiW1p6xbktxb7HsS3Hs+G2u+G6kC3hupXihKTihKjikrXik4/ik6njjpAt446U77y6772aXVwiXG4gICAgICAgIH07XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBoaWdodGxpZ2h0KG8pIHtcbiAgICAgICAgICAgIHZhciByZWdleDtcbiAgICAgICAgICAgIG8gPSBfLm1peGluKHt9LCBkZWZhdWx0cywgbyk7XG4gICAgICAgICAgICBpZiAoIW8ubm9kZSB8fCAhby5wYXR0ZXJuKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgby5wYXR0ZXJuID0gXy5pc0FycmF5KG8ucGF0dGVybikgPyBvLnBhdHRlcm4gOiBbIG8ucGF0dGVybiBdO1xuICAgICAgICAgICAgcmVnZXggPSBnZXRSZWdleChvLnBhdHRlcm4sIG8uY2FzZVNlbnNpdGl2ZSwgby53b3Jkc09ubHksIG8uZGlhY3JpdGljSW5zZW5zaXRpdmUpO1xuICAgICAgICAgICAgdHJhdmVyc2Uoby5ub2RlLCBoaWdodGxpZ2h0VGV4dE5vZGUpO1xuICAgICAgICAgICAgZnVuY3Rpb24gaGlnaHRsaWdodFRleHROb2RlKHRleHROb2RlKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1hdGNoLCBwYXR0ZXJuTm9kZSwgd3JhcHBlck5vZGU7XG4gICAgICAgICAgICAgICAgaWYgKG1hdGNoID0gcmVnZXguZXhlYyh0ZXh0Tm9kZS5kYXRhKSkge1xuICAgICAgICAgICAgICAgICAgICB3cmFwcGVyTm9kZSA9IGRvYy5jcmVhdGVFbGVtZW50KG8udGFnTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIG8uY2xhc3NOYW1lICYmICh3cmFwcGVyTm9kZS5jbGFzc05hbWUgPSBvLmNsYXNzTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIHBhdHRlcm5Ob2RlID0gdGV4dE5vZGUuc3BsaXRUZXh0KG1hdGNoLmluZGV4KTtcbiAgICAgICAgICAgICAgICAgICAgcGF0dGVybk5vZGUuc3BsaXRUZXh0KG1hdGNoWzBdLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIHdyYXBwZXJOb2RlLmFwcGVuZENoaWxkKHBhdHRlcm5Ob2RlLmNsb25lTm9kZSh0cnVlKSk7XG4gICAgICAgICAgICAgICAgICAgIHRleHROb2RlLnBhcmVudE5vZGUucmVwbGFjZUNoaWxkKHdyYXBwZXJOb2RlLCBwYXR0ZXJuTm9kZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiAhIW1hdGNoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZnVuY3Rpb24gdHJhdmVyc2UoZWwsIGhpZ2h0bGlnaHRUZXh0Tm9kZSkge1xuICAgICAgICAgICAgICAgIHZhciBjaGlsZE5vZGUsIFRFWFRfTk9ERV9UWVBFID0gMztcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGVsLmNoaWxkTm9kZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgY2hpbGROb2RlID0gZWwuY2hpbGROb2Rlc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNoaWxkTm9kZS5ub2RlVHlwZSA9PT0gVEVYVF9OT0RFX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGkgKz0gaGlnaHRsaWdodFRleHROb2RlKGNoaWxkTm9kZSkgPyAxIDogMDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYXZlcnNlKGNoaWxkTm9kZSwgaGlnaHRsaWdodFRleHROb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgZnVuY3Rpb24gYWNjZW50X3JlcGxhY2VyKGNocikge1xuICAgICAgICAgICAgcmV0dXJuIGFjY2VudGVkW2Noci50b1VwcGVyQ2FzZSgpXSB8fCBjaHI7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gZ2V0UmVnZXgocGF0dGVybnMsIGNhc2VTZW5zaXRpdmUsIHdvcmRzT25seSwgZGlhY3JpdGljSW5zZW5zaXRpdmUpIHtcbiAgICAgICAgICAgIHZhciBlc2NhcGVkUGF0dGVybnMgPSBbXSwgcmVnZXhTdHI7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gcGF0dGVybnMubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgZXNjYXBlZFdvcmQgPSBfLmVzY2FwZVJlZ0V4Q2hhcnMocGF0dGVybnNbaV0pO1xuICAgICAgICAgICAgICAgIGlmIChkaWFjcml0aWNJbnNlbnNpdGl2ZSkge1xuICAgICAgICAgICAgICAgICAgICBlc2NhcGVkV29yZCA9IGVzY2FwZWRXb3JkLnJlcGxhY2UoL1xcUy9nLCBhY2NlbnRfcmVwbGFjZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlc2NhcGVkUGF0dGVybnMucHVzaChlc2NhcGVkV29yZCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZWdleFN0ciA9IHdvcmRzT25seSA/IFwiXFxcXGIoXCIgKyBlc2NhcGVkUGF0dGVybnMuam9pbihcInxcIikgKyBcIilcXFxcYlwiIDogXCIoXCIgKyBlc2NhcGVkUGF0dGVybnMuam9pbihcInxcIikgKyBcIilcIjtcbiAgICAgICAgICAgIHJldHVybiBjYXNlU2Vuc2l0aXZlID8gbmV3IFJlZ0V4cChyZWdleFN0cikgOiBuZXcgUmVnRXhwKHJlZ2V4U3RyLCBcImlcIik7XG4gICAgICAgIH1cbiAgICB9KHdpbmRvdy5kb2N1bWVudCk7XG4gICAgdmFyIElucHV0ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICB2YXIgc3BlY2lhbEtleUNvZGVNYXA7XG4gICAgICAgIHNwZWNpYWxLZXlDb2RlTWFwID0ge1xuICAgICAgICAgICAgOTogXCJ0YWJcIixcbiAgICAgICAgICAgIDI3OiBcImVzY1wiLFxuICAgICAgICAgICAgMzc6IFwibGVmdFwiLFxuICAgICAgICAgICAgMzk6IFwicmlnaHRcIixcbiAgICAgICAgICAgIDEzOiBcImVudGVyXCIsXG4gICAgICAgICAgICAzODogXCJ1cFwiLFxuICAgICAgICAgICAgNDA6IFwiZG93blwiXG4gICAgICAgIH07XG4gICAgICAgIGZ1bmN0aW9uIElucHV0KG8sIHd3dykge1xuICAgICAgICAgICAgbyA9IG8gfHwge307XG4gICAgICAgICAgICBpZiAoIW8uaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAkLmVycm9yKFwiaW5wdXQgaXMgbWlzc2luZ1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHd3dy5taXhpbih0aGlzKTtcbiAgICAgICAgICAgIHRoaXMuJGhpbnQgPSAkKG8uaGludCk7XG4gICAgICAgICAgICB0aGlzLiRpbnB1dCA9ICQoby5pbnB1dCk7XG4gICAgICAgICAgICB0aGlzLiRpbnB1dC5hdHRyKHtcbiAgICAgICAgICAgICAgICBcImFyaWEtYWN0aXZlZGVzY2VuZGFudFwiOiBcIlwiLFxuICAgICAgICAgICAgICAgIFwiYXJpYS1vd25zXCI6IHRoaXMuJGlucHV0LmF0dHIoXCJpZFwiKSArIFwiX2xpc3Rib3hcIixcbiAgICAgICAgICAgICAgICByb2xlOiBcImNvbWJvYm94XCIsXG4gICAgICAgICAgICAgICAgXCJhcmlhLXJlYWRvbmx5XCI6IFwidHJ1ZVwiLFxuICAgICAgICAgICAgICAgIFwiYXJpYS1hdXRvY29tcGxldGVcIjogXCJsaXN0XCJcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgJCh3d3cubWVudSkuYXR0cihcImlkXCIsIHRoaXMuJGlucHV0LmF0dHIoXCJpZFwiKSArIFwiX2xpc3Rib3hcIik7XG4gICAgICAgICAgICB0aGlzLnF1ZXJ5ID0gdGhpcy4kaW5wdXQudmFsKCk7XG4gICAgICAgICAgICB0aGlzLnF1ZXJ5V2hlbkZvY3VzZWQgPSB0aGlzLmhhc0ZvY3VzKCkgPyB0aGlzLnF1ZXJ5IDogbnVsbDtcbiAgICAgICAgICAgIHRoaXMuJG92ZXJmbG93SGVscGVyID0gYnVpbGRPdmVyZmxvd0hlbHBlcih0aGlzLiRpbnB1dCk7XG4gICAgICAgICAgICB0aGlzLl9jaGVja0xhbmd1YWdlRGlyZWN0aW9uKCk7XG4gICAgICAgICAgICBpZiAodGhpcy4kaGludC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldEhpbnQgPSB0aGlzLmdldEhpbnQgPSB0aGlzLmNsZWFySGludCA9IHRoaXMuY2xlYXJIaW50SWZJbnZhbGlkID0gXy5ub29wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5vblN5bmMoXCJjdXJzb3JjaGFuZ2VcIiwgdGhpcy5fdXBkYXRlRGVzY2VuZGVudCk7XG4gICAgICAgIH1cbiAgICAgICAgSW5wdXQubm9ybWFsaXplUXVlcnkgPSBmdW5jdGlvbihzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiBfLnRvU3RyKHN0cikucmVwbGFjZSgvXlxccyovZywgXCJcIikucmVwbGFjZSgvXFxzezIsfS9nLCBcIiBcIik7XG4gICAgICAgIH07XG4gICAgICAgIF8ubWl4aW4oSW5wdXQucHJvdG90eXBlLCBFdmVudEVtaXR0ZXIsIHtcbiAgICAgICAgICAgIF9vbkJsdXI6IGZ1bmN0aW9uIG9uQmx1cigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2V0SW5wdXRWYWx1ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlcihcImJsdXJyZWRcIik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29uRm9jdXM6IGZ1bmN0aW9uIG9uRm9jdXMoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5xdWVyeVdoZW5Gb2N1c2VkID0gdGhpcy5xdWVyeTtcbiAgICAgICAgICAgICAgICB0aGlzLnRyaWdnZXIoXCJmb2N1c2VkXCIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vbktleWRvd246IGZ1bmN0aW9uIG9uS2V5ZG93bigkZSkge1xuICAgICAgICAgICAgICAgIHZhciBrZXlOYW1lID0gc3BlY2lhbEtleUNvZGVNYXBbJGUud2hpY2ggfHwgJGUua2V5Q29kZV07XG4gICAgICAgICAgICAgICAgdGhpcy5fbWFuYWdlUHJldmVudERlZmF1bHQoa2V5TmFtZSwgJGUpO1xuICAgICAgICAgICAgICAgIGlmIChrZXlOYW1lICYmIHRoaXMuX3Nob3VsZFRyaWdnZXIoa2V5TmFtZSwgJGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlcihrZXlOYW1lICsgXCJLZXllZFwiLCAkZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vbklucHV0OiBmdW5jdGlvbiBvbklucHV0KCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFF1ZXJ5KHRoaXMuZ2V0SW5wdXRWYWx1ZSgpKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFySGludElmSW52YWxpZCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2NoZWNrTGFuZ3VhZ2VEaXJlY3Rpb24oKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfbWFuYWdlUHJldmVudERlZmF1bHQ6IGZ1bmN0aW9uIG1hbmFnZVByZXZlbnREZWZhdWx0KGtleU5hbWUsICRlKSB7XG4gICAgICAgICAgICAgICAgdmFyIHByZXZlbnREZWZhdWx0O1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5TmFtZSkge1xuICAgICAgICAgICAgICAgICAgY2FzZSBcInVwXCI6XG4gICAgICAgICAgICAgICAgICBjYXNlIFwiZG93blwiOlxuICAgICAgICAgICAgICAgICAgICBwcmV2ZW50RGVmYXVsdCA9ICF3aXRoTW9kaWZpZXIoJGUpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcblxuICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcHJldmVudERlZmF1bHQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcHJldmVudERlZmF1bHQgJiYgJGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfc2hvdWxkVHJpZ2dlcjogZnVuY3Rpb24gc2hvdWxkVHJpZ2dlcihrZXlOYW1lLCAkZSkge1xuICAgICAgICAgICAgICAgIHZhciB0cmlnZ2VyO1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoa2V5TmFtZSkge1xuICAgICAgICAgICAgICAgICAgY2FzZSBcInRhYlwiOlxuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyID0gIXdpdGhNb2RpZmllcigkZSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyaWdnZXI7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX2NoZWNrTGFuZ3VhZ2VEaXJlY3Rpb246IGZ1bmN0aW9uIGNoZWNrTGFuZ3VhZ2VEaXJlY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRpciA9ICh0aGlzLiRpbnB1dC5jc3MoXCJkaXJlY3Rpb25cIikgfHwgXCJsdHJcIikudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kaXIgIT09IGRpcikge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpciA9IGRpcjtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kaGludC5hdHRyKFwiZGlyXCIsIGRpcik7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlcihcImxhbmdEaXJDaGFuZ2VkXCIsIGRpcik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9zZXRRdWVyeTogZnVuY3Rpb24gc2V0UXVlcnkodmFsLCBzaWxlbnQpIHtcbiAgICAgICAgICAgICAgICB2YXIgYXJlRXF1aXZhbGVudCwgaGFzRGlmZmVyZW50V2hpdGVzcGFjZTtcbiAgICAgICAgICAgICAgICBhcmVFcXVpdmFsZW50ID0gYXJlUXVlcmllc0VxdWl2YWxlbnQodmFsLCB0aGlzLnF1ZXJ5KTtcbiAgICAgICAgICAgICAgICBoYXNEaWZmZXJlbnRXaGl0ZXNwYWNlID0gYXJlRXF1aXZhbGVudCA/IHRoaXMucXVlcnkubGVuZ3RoICE9PSB2YWwubGVuZ3RoIDogZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5xdWVyeSA9IHZhbDtcbiAgICAgICAgICAgICAgICBpZiAoIXNpbGVudCAmJiAhYXJlRXF1aXZhbGVudCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnRyaWdnZXIoXCJxdWVyeUNoYW5nZWRcIiwgdGhpcy5xdWVyeSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghc2lsZW50ICYmIGhhc0RpZmZlcmVudFdoaXRlc3BhY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyKFwid2hpdGVzcGFjZUNoYW5nZWRcIiwgdGhpcy5xdWVyeSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF91cGRhdGVEZXNjZW5kZW50OiBmdW5jdGlvbiB1cGRhdGVEZXNjZW5kZW50KGV2ZW50LCBpZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGlucHV0LmF0dHIoXCJhcmlhLWFjdGl2ZWRlc2NlbmRhbnRcIiwgaWQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJpbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcywgb25CbHVyLCBvbkZvY3VzLCBvbktleWRvd24sIG9uSW5wdXQ7XG4gICAgICAgICAgICAgICAgb25CbHVyID0gXy5iaW5kKHRoaXMuX29uQmx1ciwgdGhpcyk7XG4gICAgICAgICAgICAgICAgb25Gb2N1cyA9IF8uYmluZCh0aGlzLl9vbkZvY3VzLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBvbktleWRvd24gPSBfLmJpbmQodGhpcy5fb25LZXlkb3duLCB0aGlzKTtcbiAgICAgICAgICAgICAgICBvbklucHV0ID0gXy5iaW5kKHRoaXMuX29uSW5wdXQsIHRoaXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuJGlucHV0Lm9uKFwiYmx1ci50dFwiLCBvbkJsdXIpLm9uKFwiZm9jdXMudHRcIiwgb25Gb2N1cykub24oXCJrZXlkb3duLnR0XCIsIG9uS2V5ZG93bik7XG4gICAgICAgICAgICAgICAgaWYgKCFfLmlzTXNpZSgpIHx8IF8uaXNNc2llKCkgPiA5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJGlucHV0Lm9uKFwiaW5wdXQudHRcIiwgb25JbnB1dCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kaW5wdXQub24oXCJrZXlkb3duLnR0IGtleXByZXNzLnR0IGN1dC50dCBwYXN0ZS50dFwiLCBmdW5jdGlvbigkZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNwZWNpYWxLZXlDb2RlTWFwWyRlLndoaWNoIHx8ICRlLmtleUNvZGVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgXy5kZWZlcihfLmJpbmQodGhhdC5fb25JbnB1dCwgdGhhdCwgJGUpKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZvY3VzOiBmdW5jdGlvbiBmb2N1cygpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRpbnB1dC5mb2N1cygpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGJsdXI6IGZ1bmN0aW9uIGJsdXIoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kaW5wdXQuYmx1cigpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldExhbmdEaXI6IGZ1bmN0aW9uIGdldExhbmdEaXIoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGlyO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldFF1ZXJ5OiBmdW5jdGlvbiBnZXRRdWVyeSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5xdWVyeSB8fCBcIlwiO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldFF1ZXJ5OiBmdW5jdGlvbiBzZXRRdWVyeSh2YWwsIHNpbGVudCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SW5wdXRWYWx1ZSh2YWwpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFF1ZXJ5KHZhbCwgc2lsZW50KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoYXNRdWVyeUNoYW5nZWRTaW5jZUxhc3RGb2N1czogZnVuY3Rpb24gaGFzUXVlcnlDaGFuZ2VkU2luY2VMYXN0Rm9jdXMoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMucXVlcnkgIT09IHRoaXMucXVlcnlXaGVuRm9jdXNlZDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXRJbnB1dFZhbHVlOiBmdW5jdGlvbiBnZXRJbnB1dFZhbHVlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiRpbnB1dC52YWwoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXRJbnB1dFZhbHVlOiBmdW5jdGlvbiBzZXRJbnB1dFZhbHVlKHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kaW5wdXQudmFsKHZhbHVlKTtcbiAgICAgICAgICAgICAgICB0aGlzLmNsZWFySGludElmSW52YWxpZCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2NoZWNrTGFuZ3VhZ2VEaXJlY3Rpb24oKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZXNldElucHV0VmFsdWU6IGZ1bmN0aW9uIHJlc2V0SW5wdXRWYWx1ZSgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldElucHV0VmFsdWUodGhpcy5xdWVyeSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0SGludDogZnVuY3Rpb24gZ2V0SGludCgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4kaGludC52YWwoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXRIaW50OiBmdW5jdGlvbiBzZXRIaW50KHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kaGludC52YWwodmFsdWUpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsZWFySGludDogZnVuY3Rpb24gY2xlYXJIaW50KCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0SGludChcIlwiKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbGVhckhpbnRJZkludmFsaWQ6IGZ1bmN0aW9uIGNsZWFySGludElmSW52YWxpZCgpIHtcbiAgICAgICAgICAgICAgICB2YXIgdmFsLCBoaW50LCB2YWxJc1ByZWZpeE9mSGludCwgaXNWYWxpZDtcbiAgICAgICAgICAgICAgICB2YWwgPSB0aGlzLmdldElucHV0VmFsdWUoKTtcbiAgICAgICAgICAgICAgICBoaW50ID0gdGhpcy5nZXRIaW50KCk7XG4gICAgICAgICAgICAgICAgdmFsSXNQcmVmaXhPZkhpbnQgPSB2YWwgIT09IGhpbnQgJiYgaGludC5pbmRleE9mKHZhbCkgPT09IDA7XG4gICAgICAgICAgICAgICAgaXNWYWxpZCA9IHZhbCAhPT0gXCJcIiAmJiB2YWxJc1ByZWZpeE9mSGludCAmJiAhdGhpcy5oYXNPdmVyZmxvdygpO1xuICAgICAgICAgICAgICAgICFpc1ZhbGlkICYmIHRoaXMuY2xlYXJIaW50KCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGFzRm9jdXM6IGZ1bmN0aW9uIGhhc0ZvY3VzKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiRpbnB1dC5pcyhcIjpmb2N1c1wiKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoYXNPdmVyZmxvdzogZnVuY3Rpb24gaGFzT3ZlcmZsb3coKSB7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnN0cmFpbnQgPSB0aGlzLiRpbnB1dC53aWR0aCgpIC0gMjtcbiAgICAgICAgICAgICAgICB0aGlzLiRvdmVyZmxvd0hlbHBlci50ZXh0KHRoaXMuZ2V0SW5wdXRWYWx1ZSgpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4kb3ZlcmZsb3dIZWxwZXIud2lkdGgoKSA+PSBjb25zdHJhaW50O1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzQ3Vyc29yQXRFbmQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHZhciB2YWx1ZUxlbmd0aCwgc2VsZWN0aW9uU3RhcnQsIHJhbmdlO1xuICAgICAgICAgICAgICAgIHZhbHVlTGVuZ3RoID0gdGhpcy4kaW5wdXQudmFsKCkubGVuZ3RoO1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvblN0YXJ0ID0gdGhpcy4kaW5wdXRbMF0uc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICAgICAgaWYgKF8uaXNOdW1iZXIoc2VsZWN0aW9uU3RhcnQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBzZWxlY3Rpb25TdGFydCA9PT0gdmFsdWVMZW5ndGg7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChkb2N1bWVudC5zZWxlY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2UgPSBkb2N1bWVudC5zZWxlY3Rpb24uY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2UubW92ZVN0YXJ0KFwiY2hhcmFjdGVyXCIsIC12YWx1ZUxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB2YWx1ZUxlbmd0aCA9PT0gcmFuZ2UudGV4dC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kaGludC5vZmYoXCIudHRcIik7XG4gICAgICAgICAgICAgICAgdGhpcy4kaW5wdXQub2ZmKFwiLnR0XCIpO1xuICAgICAgICAgICAgICAgIHRoaXMuJG92ZXJmbG93SGVscGVyLnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuJGhpbnQgPSB0aGlzLiRpbnB1dCA9IHRoaXMuJG92ZXJmbG93SGVscGVyID0gJChcIjxkaXY+XCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIElucHV0O1xuICAgICAgICBmdW5jdGlvbiBidWlsZE92ZXJmbG93SGVscGVyKCRpbnB1dCkge1xuICAgICAgICAgICAgcmV0dXJuICQoJzxwcmUgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9wcmU+JykuY3NzKHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbjogXCJhYnNvbHV0ZVwiLFxuICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6IFwiaGlkZGVuXCIsXG4gICAgICAgICAgICAgICAgd2hpdGVTcGFjZTogXCJwcmVcIixcbiAgICAgICAgICAgICAgICBmb250RmFtaWx5OiAkaW5wdXQuY3NzKFwiZm9udC1mYW1pbHlcIiksXG4gICAgICAgICAgICAgICAgZm9udFNpemU6ICRpbnB1dC5jc3MoXCJmb250LXNpemVcIiksXG4gICAgICAgICAgICAgICAgZm9udFN0eWxlOiAkaW5wdXQuY3NzKFwiZm9udC1zdHlsZVwiKSxcbiAgICAgICAgICAgICAgICBmb250VmFyaWFudDogJGlucHV0LmNzcyhcImZvbnQtdmFyaWFudFwiKSxcbiAgICAgICAgICAgICAgICBmb250V2VpZ2h0OiAkaW5wdXQuY3NzKFwiZm9udC13ZWlnaHRcIiksXG4gICAgICAgICAgICAgICAgd29yZFNwYWNpbmc6ICRpbnB1dC5jc3MoXCJ3b3JkLXNwYWNpbmdcIiksXG4gICAgICAgICAgICAgICAgbGV0dGVyU3BhY2luZzogJGlucHV0LmNzcyhcImxldHRlci1zcGFjaW5nXCIpLFxuICAgICAgICAgICAgICAgIHRleHRJbmRlbnQ6ICRpbnB1dC5jc3MoXCJ0ZXh0LWluZGVudFwiKSxcbiAgICAgICAgICAgICAgICB0ZXh0UmVuZGVyaW5nOiAkaW5wdXQuY3NzKFwidGV4dC1yZW5kZXJpbmdcIiksXG4gICAgICAgICAgICAgICAgdGV4dFRyYW5zZm9ybTogJGlucHV0LmNzcyhcInRleHQtdHJhbnNmb3JtXCIpXG4gICAgICAgICAgICB9KS5pbnNlcnRBZnRlcigkaW5wdXQpO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGFyZVF1ZXJpZXNFcXVpdmFsZW50KGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiBJbnB1dC5ub3JtYWxpemVRdWVyeShhKSA9PT0gSW5wdXQubm9ybWFsaXplUXVlcnkoYik7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gd2l0aE1vZGlmaWVyKCRlKSB7XG4gICAgICAgICAgICByZXR1cm4gJGUuYWx0S2V5IHx8ICRlLmN0cmxLZXkgfHwgJGUubWV0YUtleSB8fCAkZS5zaGlmdEtleTtcbiAgICAgICAgfVxuICAgIH0oKTtcbiAgICB2YXIgRGF0YXNldCA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBcInVzZSBzdHJpY3RcIjtcbiAgICAgICAgdmFyIGtleXMsIG5hbWVHZW5lcmF0b3I7XG4gICAgICAgIGtleXMgPSB7XG4gICAgICAgICAgICBkYXRhc2V0OiBcInR0LXNlbGVjdGFibGUtZGF0YXNldFwiLFxuICAgICAgICAgICAgdmFsOiBcInR0LXNlbGVjdGFibGUtZGlzcGxheVwiLFxuICAgICAgICAgICAgb2JqOiBcInR0LXNlbGVjdGFibGUtb2JqZWN0XCJcbiAgICAgICAgfTtcbiAgICAgICAgbmFtZUdlbmVyYXRvciA9IF8uZ2V0SWRHZW5lcmF0b3IoKTtcbiAgICAgICAgZnVuY3Rpb24gRGF0YXNldChvLCB3d3cpIHtcbiAgICAgICAgICAgIG8gPSBvIHx8IHt9O1xuICAgICAgICAgICAgby50ZW1wbGF0ZXMgPSBvLnRlbXBsYXRlcyB8fCB7fTtcbiAgICAgICAgICAgIG8udGVtcGxhdGVzLm5vdEZvdW5kID0gby50ZW1wbGF0ZXMubm90Rm91bmQgfHwgby50ZW1wbGF0ZXMuZW1wdHk7XG4gICAgICAgICAgICBpZiAoIW8uc291cmNlKSB7XG4gICAgICAgICAgICAgICAgJC5lcnJvcihcIm1pc3Npbmcgc291cmNlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFvLm5vZGUpIHtcbiAgICAgICAgICAgICAgICAkLmVycm9yKFwibWlzc2luZyBub2RlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG8ubmFtZSAmJiAhaXNWYWxpZE5hbWUoby5uYW1lKSkge1xuICAgICAgICAgICAgICAgICQuZXJyb3IoXCJpbnZhbGlkIGRhdGFzZXQgbmFtZTogXCIgKyBvLm5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd3d3Lm1peGluKHRoaXMpO1xuICAgICAgICAgICAgdGhpcy5oaWdobGlnaHQgPSAhIW8uaGlnaGxpZ2h0O1xuICAgICAgICAgICAgdGhpcy5uYW1lID0gXy50b1N0cihvLm5hbWUgfHwgbmFtZUdlbmVyYXRvcigpKTtcbiAgICAgICAgICAgIHRoaXMubGltaXQgPSBvLmxpbWl0IHx8IDU7XG4gICAgICAgICAgICB0aGlzLmRpc3BsYXlGbiA9IGdldERpc3BsYXlGbihvLmRpc3BsYXkgfHwgby5kaXNwbGF5S2V5KTtcbiAgICAgICAgICAgIHRoaXMudGVtcGxhdGVzID0gZ2V0VGVtcGxhdGVzKG8udGVtcGxhdGVzLCB0aGlzLmRpc3BsYXlGbik7XG4gICAgICAgICAgICB0aGlzLnNvdXJjZSA9IG8uc291cmNlLl9fdHRBZGFwdGVyID8gby5zb3VyY2UuX190dEFkYXB0ZXIoKSA6IG8uc291cmNlO1xuICAgICAgICAgICAgdGhpcy5hc3luYyA9IF8uaXNVbmRlZmluZWQoby5hc3luYykgPyB0aGlzLnNvdXJjZS5sZW5ndGggPiAyIDogISFvLmFzeW5jO1xuICAgICAgICAgICAgdGhpcy5fcmVzZXRMYXN0U3VnZ2VzdGlvbigpO1xuICAgICAgICAgICAgdGhpcy4kZWwgPSAkKG8ubm9kZSkuYXR0cihcInJvbGVcIiwgXCJwcmVzZW50YXRpb25cIikuYWRkQ2xhc3ModGhpcy5jbGFzc2VzLmRhdGFzZXQpLmFkZENsYXNzKHRoaXMuY2xhc3Nlcy5kYXRhc2V0ICsgXCItXCIgKyB0aGlzLm5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIERhdGFzZXQuZXh0cmFjdERhdGEgPSBmdW5jdGlvbiBleHRyYWN0RGF0YShlbCkge1xuICAgICAgICAgICAgdmFyICRlbCA9ICQoZWwpO1xuICAgICAgICAgICAgaWYgKCRlbC5kYXRhKGtleXMub2JqKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFzZXQ6ICRlbC5kYXRhKGtleXMuZGF0YXNldCkgfHwgXCJcIixcbiAgICAgICAgICAgICAgICAgICAgdmFsOiAkZWwuZGF0YShrZXlzLnZhbCkgfHwgXCJcIixcbiAgICAgICAgICAgICAgICAgICAgb2JqOiAkZWwuZGF0YShrZXlzLm9iaikgfHwgbnVsbFxuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfTtcbiAgICAgICAgXy5taXhpbihEYXRhc2V0LnByb3RvdHlwZSwgRXZlbnRFbWl0dGVyLCB7XG4gICAgICAgICAgICBfb3ZlcndyaXRlOiBmdW5jdGlvbiBvdmVyd3JpdGUocXVlcnksIHN1Z2dlc3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSBzdWdnZXN0aW9ucyB8fCBbXTtcbiAgICAgICAgICAgICAgICBpZiAoc3VnZ2VzdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbmRlclN1Z2dlc3Rpb25zKHF1ZXJ5LCBzdWdnZXN0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLmFzeW5jICYmIHRoaXMudGVtcGxhdGVzLnBlbmRpbmcpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVuZGVyUGVuZGluZyhxdWVyeSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5hc3luYyAmJiB0aGlzLnRlbXBsYXRlcy5ub3RGb3VuZCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW5kZXJOb3RGb3VuZChxdWVyeSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZW1wdHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyKFwicmVuZGVyZWRcIiwgc3VnZ2VzdGlvbnMsIGZhbHNlLCB0aGlzLm5hbWUpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9hcHBlbmQ6IGZ1bmN0aW9uIGFwcGVuZChxdWVyeSwgc3VnZ2VzdGlvbnMpIHtcbiAgICAgICAgICAgICAgICBzdWdnZXN0aW9ucyA9IHN1Z2dlc3Rpb25zIHx8IFtdO1xuICAgICAgICAgICAgICAgIGlmIChzdWdnZXN0aW9ucy5sZW5ndGggJiYgdGhpcy4kbGFzdFN1Z2dlc3Rpb24ubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2FwcGVuZFN1Z2dlc3Rpb25zKHF1ZXJ5LCBzdWdnZXN0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzdWdnZXN0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVuZGVyU3VnZ2VzdGlvbnMocXVlcnksIHN1Z2dlc3Rpb25zKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLiRsYXN0U3VnZ2VzdGlvbi5sZW5ndGggJiYgdGhpcy50ZW1wbGF0ZXMubm90Rm91bmQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVuZGVyTm90Rm91bmQocXVlcnkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnRyaWdnZXIoXCJyZW5kZXJlZFwiLCBzdWdnZXN0aW9ucywgdHJ1ZSwgdGhpcy5uYW1lKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfcmVuZGVyU3VnZ2VzdGlvbnM6IGZ1bmN0aW9uIHJlbmRlclN1Z2dlc3Rpb25zKHF1ZXJ5LCBzdWdnZXN0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciAkZnJhZ21lbnQ7XG4gICAgICAgICAgICAgICAgJGZyYWdtZW50ID0gdGhpcy5fZ2V0U3VnZ2VzdGlvbnNGcmFnbWVudChxdWVyeSwgc3VnZ2VzdGlvbnMpO1xuICAgICAgICAgICAgICAgIHRoaXMuJGxhc3RTdWdnZXN0aW9uID0gJGZyYWdtZW50LmNoaWxkcmVuKCkubGFzdCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuJGVsLmh0bWwoJGZyYWdtZW50KS5wcmVwZW5kKHRoaXMuX2dldEhlYWRlcihxdWVyeSwgc3VnZ2VzdGlvbnMpKS5hcHBlbmQodGhpcy5fZ2V0Rm9vdGVyKHF1ZXJ5LCBzdWdnZXN0aW9ucykpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9hcHBlbmRTdWdnZXN0aW9uczogZnVuY3Rpb24gYXBwZW5kU3VnZ2VzdGlvbnMocXVlcnksIHN1Z2dlc3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyICRmcmFnbWVudCwgJGxhc3RTdWdnZXN0aW9uO1xuICAgICAgICAgICAgICAgICRmcmFnbWVudCA9IHRoaXMuX2dldFN1Z2dlc3Rpb25zRnJhZ21lbnQocXVlcnksIHN1Z2dlc3Rpb25zKTtcbiAgICAgICAgICAgICAgICAkbGFzdFN1Z2dlc3Rpb24gPSAkZnJhZ21lbnQuY2hpbGRyZW4oKS5sYXN0KCk7XG4gICAgICAgICAgICAgICAgdGhpcy4kbGFzdFN1Z2dlc3Rpb24uYWZ0ZXIoJGZyYWdtZW50KTtcbiAgICAgICAgICAgICAgICB0aGlzLiRsYXN0U3VnZ2VzdGlvbiA9ICRsYXN0U3VnZ2VzdGlvbjtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfcmVuZGVyUGVuZGluZzogZnVuY3Rpb24gcmVuZGVyUGVuZGluZyhxdWVyeSkge1xuICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9IHRoaXMudGVtcGxhdGVzLnBlbmRpbmc7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzZXRMYXN0U3VnZ2VzdGlvbigpO1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlICYmIHRoaXMuJGVsLmh0bWwodGVtcGxhdGUoe1xuICAgICAgICAgICAgICAgICAgICBxdWVyeTogcXVlcnksXG4gICAgICAgICAgICAgICAgICAgIGRhdGFzZXQ6IHRoaXMubmFtZVxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfcmVuZGVyTm90Rm91bmQ6IGZ1bmN0aW9uIHJlbmRlck5vdEZvdW5kKHF1ZXJ5KSB7XG4gICAgICAgICAgICAgICAgdmFyIHRlbXBsYXRlID0gdGhpcy50ZW1wbGF0ZXMubm90Rm91bmQ7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzZXRMYXN0U3VnZ2VzdGlvbigpO1xuICAgICAgICAgICAgICAgIHRlbXBsYXRlICYmIHRoaXMuJGVsLmh0bWwodGVtcGxhdGUoe1xuICAgICAgICAgICAgICAgICAgICBxdWVyeTogcXVlcnksXG4gICAgICAgICAgICAgICAgICAgIGRhdGFzZXQ6IHRoaXMubmFtZVxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfZW1wdHk6IGZ1bmN0aW9uIGVtcHR5KCkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVsLmVtcHR5KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVzZXRMYXN0U3VnZ2VzdGlvbigpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9nZXRTdWdnZXN0aW9uc0ZyYWdtZW50OiBmdW5jdGlvbiBnZXRTdWdnZXN0aW9uc0ZyYWdtZW50KHF1ZXJ5LCBzdWdnZXN0aW9ucykge1xuICAgICAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcywgZnJhZ21lbnQ7XG4gICAgICAgICAgICAgICAgZnJhZ21lbnQgPSBkb2N1bWVudC5jcmVhdGVEb2N1bWVudEZyYWdtZW50KCk7XG4gICAgICAgICAgICAgICAgXy5lYWNoKHN1Z2dlc3Rpb25zLCBmdW5jdGlvbiBnZXRTdWdnZXN0aW9uTm9kZShzdWdnZXN0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciAkZWwsIGNvbnRleHQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnRleHQgPSB0aGF0Ll9pbmplY3RRdWVyeShxdWVyeSwgc3VnZ2VzdGlvbik7XG4gICAgICAgICAgICAgICAgICAgICRlbCA9ICQodGhhdC50ZW1wbGF0ZXMuc3VnZ2VzdGlvbihjb250ZXh0KSkuZGF0YShrZXlzLmRhdGFzZXQsIHRoYXQubmFtZSkuZGF0YShrZXlzLm9iaiwgc3VnZ2VzdGlvbikuZGF0YShrZXlzLnZhbCwgdGhhdC5kaXNwbGF5Rm4oc3VnZ2VzdGlvbikpLmFkZENsYXNzKHRoYXQuY2xhc3Nlcy5zdWdnZXN0aW9uICsgXCIgXCIgKyB0aGF0LmNsYXNzZXMuc2VsZWN0YWJsZSk7XG4gICAgICAgICAgICAgICAgICAgIGZyYWdtZW50LmFwcGVuZENoaWxkKCRlbFswXSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHQgJiYgaGlnaGxpZ2h0KHtcbiAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lOiB0aGlzLmNsYXNzZXMuaGlnaGxpZ2h0LFxuICAgICAgICAgICAgICAgICAgICBub2RlOiBmcmFnbWVudCxcbiAgICAgICAgICAgICAgICAgICAgcGF0dGVybjogcXVlcnlcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gJChmcmFnbWVudCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX2dldEZvb3RlcjogZnVuY3Rpb24gZ2V0Rm9vdGVyKHF1ZXJ5LCBzdWdnZXN0aW9ucykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnRlbXBsYXRlcy5mb290ZXIgPyB0aGlzLnRlbXBsYXRlcy5mb290ZXIoe1xuICAgICAgICAgICAgICAgICAgICBxdWVyeTogcXVlcnksXG4gICAgICAgICAgICAgICAgICAgIHN1Z2dlc3Rpb25zOiBzdWdnZXN0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgZGF0YXNldDogdGhpcy5uYW1lXG4gICAgICAgICAgICAgICAgfSkgOiBudWxsO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9nZXRIZWFkZXI6IGZ1bmN0aW9uIGdldEhlYWRlcihxdWVyeSwgc3VnZ2VzdGlvbnMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50ZW1wbGF0ZXMuaGVhZGVyID8gdGhpcy50ZW1wbGF0ZXMuaGVhZGVyKHtcbiAgICAgICAgICAgICAgICAgICAgcXVlcnk6IHF1ZXJ5LFxuICAgICAgICAgICAgICAgICAgICBzdWdnZXN0aW9uczogc3VnZ2VzdGlvbnMsXG4gICAgICAgICAgICAgICAgICAgIGRhdGFzZXQ6IHRoaXMubmFtZVxuICAgICAgICAgICAgICAgIH0pIDogbnVsbDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfcmVzZXRMYXN0U3VnZ2VzdGlvbjogZnVuY3Rpb24gcmVzZXRMYXN0U3VnZ2VzdGlvbigpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRsYXN0U3VnZ2VzdGlvbiA9ICQoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfaW5qZWN0UXVlcnk6IGZ1bmN0aW9uIGluamVjdFF1ZXJ5KHF1ZXJ5LCBvYmopIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gXy5pc09iamVjdChvYmopID8gXy5taXhpbih7XG4gICAgICAgICAgICAgICAgICAgIF9xdWVyeTogcXVlcnlcbiAgICAgICAgICAgICAgICB9LCBvYmopIDogb2JqO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVwZGF0ZTogZnVuY3Rpb24gdXBkYXRlKHF1ZXJ5KSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLCBjYW5jZWxlZCA9IGZhbHNlLCBzeW5jQ2FsbGVkID0gZmFsc2UsIHJlbmRlcmVkID0gMDtcbiAgICAgICAgICAgICAgICB0aGlzLmNhbmNlbCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuY2FuY2VsID0gZnVuY3Rpb24gY2FuY2VsKCkge1xuICAgICAgICAgICAgICAgICAgICBjYW5jZWxlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoYXQuY2FuY2VsID0gJC5ub29wO1xuICAgICAgICAgICAgICAgICAgICB0aGF0LmFzeW5jICYmIHRoYXQudHJpZ2dlcihcImFzeW5jQ2FuY2VsZWRcIiwgcXVlcnksIHRoYXQubmFtZSk7XG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB0aGlzLnNvdXJjZShxdWVyeSwgc3luYywgYXN5bmMpO1xuICAgICAgICAgICAgICAgICFzeW5jQ2FsbGVkICYmIHN5bmMoW10pO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIHN5bmMoc3VnZ2VzdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN5bmNDYWxsZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzeW5jQ2FsbGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSAoc3VnZ2VzdGlvbnMgfHwgW10pLnNsaWNlKDAsIHRoYXQubGltaXQpO1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJlZCA9IHN1Z2dlc3Rpb25zLmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5fb3ZlcndyaXRlKHF1ZXJ5LCBzdWdnZXN0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZW5kZXJlZCA8IHRoYXQubGltaXQgJiYgdGhhdC5hc3luYykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC50cmlnZ2VyKFwiYXN5bmNSZXF1ZXN0ZWRcIiwgcXVlcnksIHRoYXQubmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gYXN5bmMoc3VnZ2VzdGlvbnMpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VnZ2VzdGlvbnMgPSBzdWdnZXN0aW9ucyB8fCBbXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjYW5jZWxlZCAmJiByZW5kZXJlZCA8IHRoYXQubGltaXQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoYXQuY2FuY2VsID0gJC5ub29wO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlkeCA9IE1hdGguYWJzKHJlbmRlcmVkIC0gdGhhdC5saW1pdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZW5kZXJlZCArPSBpZHg7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGF0Ll9hcHBlbmQocXVlcnksIHN1Z2dlc3Rpb25zLnNsaWNlKDAsIGlkeCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhhdC5hc3luYyAmJiB0aGF0LnRyaWdnZXIoXCJhc3luY1JlY2VpdmVkXCIsIHF1ZXJ5LCB0aGF0Lm5hbWUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNhbmNlbDogJC5ub29wLFxuICAgICAgICAgICAgY2xlYXI6IGZ1bmN0aW9uIGNsZWFyKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2VtcHR5KCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnRyaWdnZXIoXCJjbGVhcmVkXCIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzRW1wdHk6IGZ1bmN0aW9uIGlzRW1wdHkoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuJGVsLmlzKFwiOmVtcHR5XCIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kZWwgPSAkKFwiPGRpdj5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gRGF0YXNldDtcbiAgICAgICAgZnVuY3Rpb24gZ2V0RGlzcGxheUZuKGRpc3BsYXkpIHtcbiAgICAgICAgICAgIGRpc3BsYXkgPSBkaXNwbGF5IHx8IF8uc3RyaW5naWZ5O1xuICAgICAgICAgICAgcmV0dXJuIF8uaXNGdW5jdGlvbihkaXNwbGF5KSA/IGRpc3BsYXkgOiBkaXNwbGF5Rm47XG4gICAgICAgICAgICBmdW5jdGlvbiBkaXNwbGF5Rm4ob2JqKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9ialtkaXNwbGF5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBnZXRUZW1wbGF0ZXModGVtcGxhdGVzLCBkaXNwbGF5Rm4pIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgbm90Rm91bmQ6IHRlbXBsYXRlcy5ub3RGb3VuZCAmJiBfLnRlbXBsYXRpZnkodGVtcGxhdGVzLm5vdEZvdW5kKSxcbiAgICAgICAgICAgICAgICBwZW5kaW5nOiB0ZW1wbGF0ZXMucGVuZGluZyAmJiBfLnRlbXBsYXRpZnkodGVtcGxhdGVzLnBlbmRpbmcpLFxuICAgICAgICAgICAgICAgIGhlYWRlcjogdGVtcGxhdGVzLmhlYWRlciAmJiBfLnRlbXBsYXRpZnkodGVtcGxhdGVzLmhlYWRlciksXG4gICAgICAgICAgICAgICAgZm9vdGVyOiB0ZW1wbGF0ZXMuZm9vdGVyICYmIF8udGVtcGxhdGlmeSh0ZW1wbGF0ZXMuZm9vdGVyKSxcbiAgICAgICAgICAgICAgICBzdWdnZXN0aW9uOiB0ZW1wbGF0ZXMuc3VnZ2VzdGlvbiB8fCBzdWdnZXN0aW9uVGVtcGxhdGVcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBmdW5jdGlvbiBzdWdnZXN0aW9uVGVtcGxhdGUoY29udGV4dCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkKCc8ZGl2IHJvbGU9XCJvcHRpb25cIj4nKS5hdHRyKFwiaWRcIiwgXy5ndWlkKCkpLnRleHQoZGlzcGxheUZuKGNvbnRleHQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmdW5jdGlvbiBpc1ZhbGlkTmFtZShzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiAvXltfYS16QS1aMC05LV0rJC8udGVzdChzdHIpO1xuICAgICAgICB9XG4gICAgfSgpO1xuICAgIHZhciBNZW51ID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xuICAgICAgICBmdW5jdGlvbiBNZW51KG8sIHd3dykge1xuICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzO1xuICAgICAgICAgICAgbyA9IG8gfHwge307XG4gICAgICAgICAgICBpZiAoIW8ubm9kZSkge1xuICAgICAgICAgICAgICAgICQuZXJyb3IoXCJub2RlIGlzIHJlcXVpcmVkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgd3d3Lm1peGluKHRoaXMpO1xuICAgICAgICAgICAgdGhpcy4kbm9kZSA9ICQoby5ub2RlKTtcbiAgICAgICAgICAgIHRoaXMucXVlcnkgPSBudWxsO1xuICAgICAgICAgICAgdGhpcy5kYXRhc2V0cyA9IF8ubWFwKG8uZGF0YXNldHMsIGluaXRpYWxpemVEYXRhc2V0KTtcbiAgICAgICAgICAgIGZ1bmN0aW9uIGluaXRpYWxpemVEYXRhc2V0KG9EYXRhc2V0KSB7XG4gICAgICAgICAgICAgICAgdmFyIG5vZGUgPSB0aGF0LiRub2RlLmZpbmQob0RhdGFzZXQubm9kZSkuZmlyc3QoKTtcbiAgICAgICAgICAgICAgICBvRGF0YXNldC5ub2RlID0gbm9kZS5sZW5ndGggPyBub2RlIDogJChcIjxkaXY+XCIpLmFwcGVuZFRvKHRoYXQuJG5vZGUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGF0YXNldChvRGF0YXNldCwgd3d3KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBfLm1peGluKE1lbnUucHJvdG90eXBlLCBFdmVudEVtaXR0ZXIsIHtcbiAgICAgICAgICAgIF9vblNlbGVjdGFibGVDbGljazogZnVuY3Rpb24gb25TZWxlY3RhYmxlQ2xpY2soJGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnRyaWdnZXIoXCJzZWxlY3RhYmxlQ2xpY2tlZFwiLCAkKCRlLmN1cnJlbnRUYXJnZXQpKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfb25SZW5kZXJlZDogZnVuY3Rpb24gb25SZW5kZXJlZCh0eXBlLCBkYXRhc2V0LCBzdWdnZXN0aW9ucywgYXN5bmMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRub2RlLnRvZ2dsZUNsYXNzKHRoaXMuY2xhc3Nlcy5lbXB0eSwgdGhpcy5fYWxsRGF0YXNldHNFbXB0eSgpKTtcbiAgICAgICAgICAgICAgICB0aGlzLnRyaWdnZXIoXCJkYXRhc2V0UmVuZGVyZWRcIiwgZGF0YXNldCwgc3VnZ2VzdGlvbnMsIGFzeW5jKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfb25DbGVhcmVkOiBmdW5jdGlvbiBvbkNsZWFyZWQoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kbm9kZS50b2dnbGVDbGFzcyh0aGlzLmNsYXNzZXMuZW1wdHksIHRoaXMuX2FsbERhdGFzZXRzRW1wdHkoKSk7XG4gICAgICAgICAgICAgICAgdGhpcy50cmlnZ2VyKFwiZGF0YXNldENsZWFyZWRcIik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX3Byb3BhZ2F0ZTogZnVuY3Rpb24gcHJvcGFnYXRlKCkge1xuICAgICAgICAgICAgICAgIHRoaXMudHJpZ2dlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9hbGxEYXRhc2V0c0VtcHR5OiBmdW5jdGlvbiBhbGxEYXRhc2V0c0VtcHR5KCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfLmV2ZXJ5KHRoaXMuZGF0YXNldHMsIF8uYmluZChmdW5jdGlvbiBpc0RhdGFzZXRFbXB0eShkYXRhc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBpc0VtcHR5ID0gZGF0YXNldC5pc0VtcHR5KCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJG5vZGUuYXR0cihcImFyaWEtZXhwYW5kZWRcIiwgIWlzRW1wdHkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNFbXB0eTtcbiAgICAgICAgICAgICAgICB9LCB0aGlzKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX2dldFNlbGVjdGFibGVzOiBmdW5jdGlvbiBnZXRTZWxlY3RhYmxlcygpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy4kbm9kZS5maW5kKHRoaXMuc2VsZWN0b3JzLnNlbGVjdGFibGUpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9yZW1vdmVDdXJzb3I6IGZ1bmN0aW9uIF9yZW1vdmVDdXJzb3IoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRzZWxlY3RhYmxlID0gdGhpcy5nZXRBY3RpdmVTZWxlY3RhYmxlKCk7XG4gICAgICAgICAgICAgICAgJHNlbGVjdGFibGUgJiYgJHNlbGVjdGFibGUucmVtb3ZlQ2xhc3ModGhpcy5jbGFzc2VzLmN1cnNvcik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX2Vuc3VyZVZpc2libGU6IGZ1bmN0aW9uIGVuc3VyZVZpc2libGUoJGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVsVG9wLCBlbEJvdHRvbSwgbm9kZVNjcm9sbFRvcCwgbm9kZUhlaWdodDtcbiAgICAgICAgICAgICAgICBlbFRvcCA9ICRlbC5wb3NpdGlvbigpLnRvcDtcbiAgICAgICAgICAgICAgICBlbEJvdHRvbSA9IGVsVG9wICsgJGVsLm91dGVySGVpZ2h0KHRydWUpO1xuICAgICAgICAgICAgICAgIG5vZGVTY3JvbGxUb3AgPSB0aGlzLiRub2RlLnNjcm9sbFRvcCgpO1xuICAgICAgICAgICAgICAgIG5vZGVIZWlnaHQgPSB0aGlzLiRub2RlLmhlaWdodCgpICsgcGFyc2VJbnQodGhpcy4kbm9kZS5jc3MoXCJwYWRkaW5nVG9wXCIpLCAxMCkgKyBwYXJzZUludCh0aGlzLiRub2RlLmNzcyhcInBhZGRpbmdCb3R0b21cIiksIDEwKTtcbiAgICAgICAgICAgICAgICBpZiAoZWxUb3AgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuJG5vZGUuc2Nyb2xsVG9wKG5vZGVTY3JvbGxUb3AgKyBlbFRvcCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChub2RlSGVpZ2h0IDwgZWxCb3R0b20pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy4kbm9kZS5zY3JvbGxUb3Aobm9kZVNjcm9sbFRvcCArIChlbEJvdHRvbSAtIG5vZGVIZWlnaHQpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYmluZDogZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRoYXQgPSB0aGlzLCBvblNlbGVjdGFibGVDbGljaztcbiAgICAgICAgICAgICAgICBvblNlbGVjdGFibGVDbGljayA9IF8uYmluZCh0aGlzLl9vblNlbGVjdGFibGVDbGljaywgdGhpcyk7XG4gICAgICAgICAgICAgICAgdGhpcy4kbm9kZS5vbihcImNsaWNrLnR0XCIsIHRoaXMuc2VsZWN0b3JzLnNlbGVjdGFibGUsIG9uU2VsZWN0YWJsZUNsaWNrKTtcbiAgICAgICAgICAgICAgICB0aGlzLiRub2RlLm9uKFwibW91c2VvdmVyXCIsIHRoaXMuc2VsZWN0b3JzLnNlbGVjdGFibGUsIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgICAgICB0aGF0LnNldEN1cnNvcigkKHRoaXMpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLiRub2RlLm9uKFwibW91c2VsZWF2ZVwiLCBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhhdC5fcmVtb3ZlQ3Vyc29yKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgXy5lYWNoKHRoaXMuZGF0YXNldHMsIGZ1bmN0aW9uKGRhdGFzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YXNldC5vblN5bmMoXCJhc3luY1JlcXVlc3RlZFwiLCB0aGF0Ll9wcm9wYWdhdGUsIHRoYXQpLm9uU3luYyhcImFzeW5jQ2FuY2VsZWRcIiwgdGhhdC5fcHJvcGFnYXRlLCB0aGF0KS5vblN5bmMoXCJhc3luY1JlY2VpdmVkXCIsIHRoYXQuX3Byb3BhZ2F0ZSwgdGhhdCkub25TeW5jKFwicmVuZGVyZWRcIiwgdGhhdC5fb25SZW5kZXJlZCwgdGhhdCkub25TeW5jKFwiY2xlYXJlZFwiLCB0aGF0Ll9vbkNsZWFyZWQsIHRoYXQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzT3BlbjogZnVuY3Rpb24gaXNPcGVuKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLiRub2RlLmhhc0NsYXNzKHRoaXMuY2xhc3Nlcy5vcGVuKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvcGVuOiBmdW5jdGlvbiBvcGVuKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuJG5vZGUuc2Nyb2xsVG9wKDApO1xuICAgICAgICAgICAgICAgIHRoaXMuJG5vZGUuYWRkQ2xhc3ModGhpcy5jbGFzc2VzLm9wZW4pO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsb3NlOiBmdW5jdGlvbiBjbG9zZSgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRub2RlLmF0dHIoXCJhcmlhLWV4cGFuZGVkXCIsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICB0aGlzLiRub2RlLnJlbW92ZUNsYXNzKHRoaXMuY2xhc3Nlcy5vcGVuKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDdXJzb3IoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXRMYW5ndWFnZURpcmVjdGlvbjogZnVuY3Rpb24gc2V0TGFuZ3VhZ2VEaXJlY3Rpb24oZGlyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kbm9kZS5hdHRyKFwiZGlyXCIsIGRpcik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2VsZWN0YWJsZVJlbGF0aXZlVG9DdXJzb3I6IGZ1bmN0aW9uIHNlbGVjdGFibGVSZWxhdGl2ZVRvQ3Vyc29yKGRlbHRhKSB7XG4gICAgICAgICAgICAgICAgdmFyICRzZWxlY3RhYmxlcywgJG9sZEN1cnNvciwgb2xkSW5kZXgsIG5ld0luZGV4O1xuICAgICAgICAgICAgICAgICRvbGRDdXJzb3IgPSB0aGlzLmdldEFjdGl2ZVNlbGVjdGFibGUoKTtcbiAgICAgICAgICAgICAgICAkc2VsZWN0YWJsZXMgPSB0aGlzLl9nZXRTZWxlY3RhYmxlcygpO1xuICAgICAgICAgICAgICAgIG9sZEluZGV4ID0gJG9sZEN1cnNvciA/ICRzZWxlY3RhYmxlcy5pbmRleCgkb2xkQ3Vyc29yKSA6IC0xO1xuICAgICAgICAgICAgICAgIG5ld0luZGV4ID0gb2xkSW5kZXggKyBkZWx0YTtcbiAgICAgICAgICAgICAgICBuZXdJbmRleCA9IChuZXdJbmRleCArIDEpICUgKCRzZWxlY3RhYmxlcy5sZW5ndGggKyAxKSAtIDE7XG4gICAgICAgICAgICAgICAgbmV3SW5kZXggPSBuZXdJbmRleCA8IC0xID8gJHNlbGVjdGFibGVzLmxlbmd0aCAtIDEgOiBuZXdJbmRleDtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3SW5kZXggPT09IC0xID8gbnVsbCA6ICRzZWxlY3RhYmxlcy5lcShuZXdJbmRleCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0Q3Vyc29yOiBmdW5jdGlvbiBzZXRDdXJzb3IoJHNlbGVjdGFibGUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDdXJzb3IoKTtcbiAgICAgICAgICAgICAgICBpZiAoJHNlbGVjdGFibGUgPSAkc2VsZWN0YWJsZSAmJiAkc2VsZWN0YWJsZS5maXJzdCgpKSB7XG4gICAgICAgICAgICAgICAgICAgICRzZWxlY3RhYmxlLmFkZENsYXNzKHRoaXMuY2xhc3Nlcy5jdXJzb3IpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9lbnN1cmVWaXNpYmxlKCRzZWxlY3RhYmxlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0U2VsZWN0YWJsZURhdGE6IGZ1bmN0aW9uIGdldFNlbGVjdGFibGVEYXRhKCRlbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAkZWwgJiYgJGVsLmxlbmd0aCA/IERhdGFzZXQuZXh0cmFjdERhdGEoJGVsKSA6IG51bGw7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0QWN0aXZlU2VsZWN0YWJsZTogZnVuY3Rpb24gZ2V0QWN0aXZlU2VsZWN0YWJsZSgpIHtcbiAgICAgICAgICAgICAgICB2YXIgJHNlbGVjdGFibGUgPSB0aGlzLl9nZXRTZWxlY3RhYmxlcygpLmZpbHRlcih0aGlzLnNlbGVjdG9ycy5jdXJzb3IpLmZpcnN0KCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuICRzZWxlY3RhYmxlLmxlbmd0aCA/ICRzZWxlY3RhYmxlIDogbnVsbDtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXRUb3BTZWxlY3RhYmxlOiBmdW5jdGlvbiBnZXRUb3BTZWxlY3RhYmxlKCkge1xuICAgICAgICAgICAgICAgIHZhciAkc2VsZWN0YWJsZSA9IHRoaXMuX2dldFNlbGVjdGFibGVzKCkuZmlyc3QoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gJHNlbGVjdGFibGUubGVuZ3RoID8gJHNlbGVjdGFibGUgOiBudWxsO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVwZGF0ZTogZnVuY3Rpb24gdXBkYXRlKHF1ZXJ5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGlzVmFsaWRVcGRhdGUgPSBxdWVyeSAhPT0gdGhpcy5xdWVyeTtcbiAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZFVwZGF0ZSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnF1ZXJ5ID0gcXVlcnk7XG4gICAgICAgICAgICAgICAgICAgIF8uZWFjaCh0aGlzLmRhdGFzZXRzLCB1cGRhdGVEYXRhc2V0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzVmFsaWRVcGRhdGU7XG4gICAgICAgICAgICAgICAgZnVuY3Rpb24gdXBkYXRlRGF0YXNldChkYXRhc2V0KSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFzZXQudXBkYXRlKHF1ZXJ5KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW1wdHk6IGZ1bmN0aW9uIGVtcHR5KCkge1xuICAgICAgICAgICAgICAgIF8uZWFjaCh0aGlzLmRhdGFzZXRzLCBjbGVhckRhdGFzZXQpO1xuICAgICAgICAgICAgICAgIHRoaXMucXVlcnkgPSBudWxsO1xuICAgICAgICAgICAgICAgIHRoaXMuJG5vZGUuYWRkQ2xhc3ModGhpcy5jbGFzc2VzLmVtcHR5KTtcbiAgICAgICAgICAgICAgICBmdW5jdGlvbiBjbGVhckRhdGFzZXQoZGF0YXNldCkge1xuICAgICAgICAgICAgICAgICAgICBkYXRhc2V0LmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlc3Ryb3k6IGZ1bmN0aW9uIGRlc3Ryb3koKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kbm9kZS5vZmYoXCIudHRcIik7XG4gICAgICAgICAgICAgICAgdGhpcy4kbm9kZSA9ICQoXCI8ZGl2PlwiKTtcbiAgICAgICAgICAgICAgICBfLmVhY2godGhpcy5kYXRhc2V0cywgZGVzdHJveURhdGFzZXQpO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGRlc3Ryb3lEYXRhc2V0KGRhdGFzZXQpIHtcbiAgICAgICAgICAgICAgICAgICAgZGF0YXNldC5kZXN0cm95KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIE1lbnU7XG4gICAgfSgpO1xuICAgIHZhciBTdGF0dXMgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIGZ1bmN0aW9uIFN0YXR1cyhvcHRpb25zKSB7XG4gICAgICAgICAgICB0aGlzLiRlbCA9ICQoXCI8c3Bhbj48L3NwYW4+XCIsIHtcbiAgICAgICAgICAgICAgICByb2xlOiBcInN0YXR1c1wiLFxuICAgICAgICAgICAgICAgIFwiYXJpYS1saXZlXCI6IFwicG9saXRlXCJcbiAgICAgICAgICAgIH0pLmNzcyh7XG4gICAgICAgICAgICAgICAgcG9zaXRpb246IFwiYWJzb2x1dGVcIixcbiAgICAgICAgICAgICAgICBwYWRkaW5nOiBcIjBcIixcbiAgICAgICAgICAgICAgICBib3JkZXI6IFwiMFwiLFxuICAgICAgICAgICAgICAgIGhlaWdodDogXCIxcHhcIixcbiAgICAgICAgICAgICAgICB3aWR0aDogXCIxcHhcIixcbiAgICAgICAgICAgICAgICBcIm1hcmdpbi1ib3R0b21cIjogXCItMXB4XCIsXG4gICAgICAgICAgICAgICAgXCJtYXJnaW4tcmlnaHRcIjogXCItMXB4XCIsXG4gICAgICAgICAgICAgICAgb3ZlcmZsb3c6IFwiaGlkZGVuXCIsXG4gICAgICAgICAgICAgICAgY2xpcDogXCJyZWN0KDAgMCAwIDApXCIsXG4gICAgICAgICAgICAgICAgXCJ3aGl0ZS1zcGFjZVwiOiBcIm5vd3JhcFwiXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIG9wdGlvbnMuJGlucHV0LmFmdGVyKHRoaXMuJGVsKTtcbiAgICAgICAgICAgIF8uZWFjaChvcHRpb25zLm1lbnUuZGF0YXNldHMsIF8uYmluZChmdW5jdGlvbihkYXRhc2V0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGFzZXQub25TeW5jKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFzZXQub25TeW5jKFwicmVuZGVyZWRcIiwgXy5iaW5kKHRoaXMudXBkYXRlLCB0aGlzKSk7XG4gICAgICAgICAgICAgICAgICAgIGRhdGFzZXQub25TeW5jKFwiY2xlYXJlZFwiLCBfLmJpbmQodGhpcy5jbGVhcmVkLCB0aGlzKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSwgdGhpcykpO1xuICAgICAgICB9XG4gICAgICAgIF8ubWl4aW4oU3RhdHVzLnByb3RvdHlwZSwge1xuICAgICAgICAgICAgdXBkYXRlOiBmdW5jdGlvbiB1cGRhdGUoZXZlbnQsIHN1Z2dlc3Rpb25zKSB7XG4gICAgICAgICAgICAgICAgdmFyIGxlbmd0aCA9IHN1Z2dlc3Rpb25zLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB2YXIgd29yZHM7XG4gICAgICAgICAgICAgICAgaWYgKGxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICB3b3JkcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdDogXCJyZXN1bHRcIixcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzOiBcImlzXCJcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB3b3JkcyA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdDogXCJyZXN1bHRzXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICBpczogXCJhcmVcIlxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLiRlbC50ZXh0KGxlbmd0aCArIFwiIFwiICsgd29yZHMucmVzdWx0ICsgXCIgXCIgKyB3b3Jkcy5pcyArIFwiIGF2YWlsYWJsZSwgdXNlIHVwIGFuZCBkb3duIGFycm93IGtleXMgdG8gbmF2aWdhdGUuXCIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNsZWFyZWQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuJGVsLnRleHQoXCJcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gU3RhdHVzO1xuICAgIH0oKTtcbiAgICB2YXIgRGVmYXVsdE1lbnUgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIHZhciBzID0gTWVudS5wcm90b3R5cGU7XG4gICAgICAgIGZ1bmN0aW9uIERlZmF1bHRNZW51KCkge1xuICAgICAgICAgICAgTWVudS5hcHBseSh0aGlzLCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCkpO1xuICAgICAgICB9XG4gICAgICAgIF8ubWl4aW4oRGVmYXVsdE1lbnUucHJvdG90eXBlLCBNZW51LnByb3RvdHlwZSwge1xuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gb3BlbigpIHtcbiAgICAgICAgICAgICAgICAhdGhpcy5fYWxsRGF0YXNldHNFbXB0eSgpICYmIHRoaXMuX3Nob3coKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcy5vcGVuLmFwcGx5KHRoaXMsIFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY2xvc2U6IGZ1bmN0aW9uIGNsb3NlKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2hpZGUoKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gcy5jbG9zZS5hcHBseSh0aGlzLCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vblJlbmRlcmVkOiBmdW5jdGlvbiBvblJlbmRlcmVkKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9hbGxEYXRhc2V0c0VtcHR5KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faGlkZSgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNPcGVuKCkgJiYgdGhpcy5fc2hvdygpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcy5fb25SZW5kZXJlZC5hcHBseSh0aGlzLCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vbkNsZWFyZWQ6IGZ1bmN0aW9uIG9uQ2xlYXJlZCgpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fYWxsRGF0YXNldHNFbXB0eSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2hpZGUoKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmlzT3BlbigpICYmIHRoaXMuX3Nob3coKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHMuX29uQ2xlYXJlZC5hcHBseSh0aGlzLCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMCkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldExhbmd1YWdlRGlyZWN0aW9uOiBmdW5jdGlvbiBzZXRMYW5ndWFnZURpcmVjdGlvbihkaXIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLiRub2RlLmNzcyhkaXIgPT09IFwibHRyXCIgPyB0aGlzLmNzcy5sdHIgOiB0aGlzLmNzcy5ydGwpO1xuICAgICAgICAgICAgICAgIHJldHVybiBzLnNldExhbmd1YWdlRGlyZWN0aW9uLmFwcGx5KHRoaXMsIFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX2hpZGU6IGZ1bmN0aW9uIGhpZGUoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kbm9kZS5oaWRlKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX3Nob3c6IGZ1bmN0aW9uIHNob3coKSB7XG4gICAgICAgICAgICAgICAgdGhpcy4kbm9kZS5jc3MoXCJkaXNwbGF5XCIsIFwiYmxvY2tcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gRGVmYXVsdE1lbnU7XG4gICAgfSgpO1xuICAgIHZhciBUeXBlYWhlYWQgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIGZ1bmN0aW9uIFR5cGVhaGVhZChvLCB3d3cpIHtcbiAgICAgICAgICAgIHZhciBvbkZvY3VzZWQsIG9uQmx1cnJlZCwgb25FbnRlcktleWVkLCBvblRhYktleWVkLCBvbkVzY0tleWVkLCBvblVwS2V5ZWQsIG9uRG93bktleWVkLCBvbkxlZnRLZXllZCwgb25SaWdodEtleWVkLCBvblF1ZXJ5Q2hhbmdlZCwgb25XaGl0ZXNwYWNlQ2hhbmdlZDtcbiAgICAgICAgICAgIG8gPSBvIHx8IHt9O1xuICAgICAgICAgICAgaWYgKCFvLmlucHV0KSB7XG4gICAgICAgICAgICAgICAgJC5lcnJvcihcIm1pc3NpbmcgaW5wdXRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW8ubWVudSkge1xuICAgICAgICAgICAgICAgICQuZXJyb3IoXCJtaXNzaW5nIG1lbnVcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW8uZXZlbnRCdXMpIHtcbiAgICAgICAgICAgICAgICAkLmVycm9yKFwibWlzc2luZyBldmVudCBidXNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB3d3cubWl4aW4odGhpcyk7XG4gICAgICAgICAgICB0aGlzLmV2ZW50QnVzID0gby5ldmVudEJ1cztcbiAgICAgICAgICAgIHRoaXMubWluTGVuZ3RoID0gXy5pc051bWJlcihvLm1pbkxlbmd0aCkgPyBvLm1pbkxlbmd0aCA6IDE7XG4gICAgICAgICAgICB0aGlzLmlucHV0ID0gby5pbnB1dDtcbiAgICAgICAgICAgIHRoaXMubWVudSA9IG8ubWVudTtcbiAgICAgICAgICAgIHRoaXMuZW5hYmxlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLmF1dG9zZWxlY3QgPSAhIW8uYXV0b3NlbGVjdDtcbiAgICAgICAgICAgIHRoaXMuYWN0aXZlID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLmlucHV0Lmhhc0ZvY3VzKCkgJiYgdGhpcy5hY3RpdmF0ZSgpO1xuICAgICAgICAgICAgdGhpcy5kaXIgPSB0aGlzLmlucHV0LmdldExhbmdEaXIoKTtcbiAgICAgICAgICAgIHRoaXMuX2hhY2tzKCk7XG4gICAgICAgICAgICB0aGlzLm1lbnUuYmluZCgpLm9uU3luYyhcInNlbGVjdGFibGVDbGlja2VkXCIsIHRoaXMuX29uU2VsZWN0YWJsZUNsaWNrZWQsIHRoaXMpLm9uU3luYyhcImFzeW5jUmVxdWVzdGVkXCIsIHRoaXMuX29uQXN5bmNSZXF1ZXN0ZWQsIHRoaXMpLm9uU3luYyhcImFzeW5jQ2FuY2VsZWRcIiwgdGhpcy5fb25Bc3luY0NhbmNlbGVkLCB0aGlzKS5vblN5bmMoXCJhc3luY1JlY2VpdmVkXCIsIHRoaXMuX29uQXN5bmNSZWNlaXZlZCwgdGhpcykub25TeW5jKFwiZGF0YXNldFJlbmRlcmVkXCIsIHRoaXMuX29uRGF0YXNldFJlbmRlcmVkLCB0aGlzKS5vblN5bmMoXCJkYXRhc2V0Q2xlYXJlZFwiLCB0aGlzLl9vbkRhdGFzZXRDbGVhcmVkLCB0aGlzKTtcbiAgICAgICAgICAgIG9uRm9jdXNlZCA9IGModGhpcywgXCJhY3RpdmF0ZVwiLCBcIm9wZW5cIiwgXCJfb25Gb2N1c2VkXCIpO1xuICAgICAgICAgICAgb25CbHVycmVkID0gYyh0aGlzLCBcImRlYWN0aXZhdGVcIiwgXCJfb25CbHVycmVkXCIpO1xuICAgICAgICAgICAgb25FbnRlcktleWVkID0gYyh0aGlzLCBcImlzQWN0aXZlXCIsIFwiaXNPcGVuXCIsIFwiX29uRW50ZXJLZXllZFwiKTtcbiAgICAgICAgICAgIG9uVGFiS2V5ZWQgPSBjKHRoaXMsIFwiaXNBY3RpdmVcIiwgXCJpc09wZW5cIiwgXCJfb25UYWJLZXllZFwiKTtcbiAgICAgICAgICAgIG9uRXNjS2V5ZWQgPSBjKHRoaXMsIFwiaXNBY3RpdmVcIiwgXCJfb25Fc2NLZXllZFwiKTtcbiAgICAgICAgICAgIG9uVXBLZXllZCA9IGModGhpcywgXCJpc0FjdGl2ZVwiLCBcIm9wZW5cIiwgXCJfb25VcEtleWVkXCIpO1xuICAgICAgICAgICAgb25Eb3duS2V5ZWQgPSBjKHRoaXMsIFwiaXNBY3RpdmVcIiwgXCJvcGVuXCIsIFwiX29uRG93bktleWVkXCIpO1xuICAgICAgICAgICAgb25MZWZ0S2V5ZWQgPSBjKHRoaXMsIFwiaXNBY3RpdmVcIiwgXCJpc09wZW5cIiwgXCJfb25MZWZ0S2V5ZWRcIik7XG4gICAgICAgICAgICBvblJpZ2h0S2V5ZWQgPSBjKHRoaXMsIFwiaXNBY3RpdmVcIiwgXCJpc09wZW5cIiwgXCJfb25SaWdodEtleWVkXCIpO1xuICAgICAgICAgICAgb25RdWVyeUNoYW5nZWQgPSBjKHRoaXMsIFwiX29wZW5JZkFjdGl2ZVwiLCBcIl9vblF1ZXJ5Q2hhbmdlZFwiKTtcbiAgICAgICAgICAgIG9uV2hpdGVzcGFjZUNoYW5nZWQgPSBjKHRoaXMsIFwiX29wZW5JZkFjdGl2ZVwiLCBcIl9vbldoaXRlc3BhY2VDaGFuZ2VkXCIpO1xuICAgICAgICAgICAgdGhpcy5pbnB1dC5iaW5kKCkub25TeW5jKFwiZm9jdXNlZFwiLCBvbkZvY3VzZWQsIHRoaXMpLm9uU3luYyhcImJsdXJyZWRcIiwgb25CbHVycmVkLCB0aGlzKS5vblN5bmMoXCJlbnRlcktleWVkXCIsIG9uRW50ZXJLZXllZCwgdGhpcykub25TeW5jKFwidGFiS2V5ZWRcIiwgb25UYWJLZXllZCwgdGhpcykub25TeW5jKFwiZXNjS2V5ZWRcIiwgb25Fc2NLZXllZCwgdGhpcykub25TeW5jKFwidXBLZXllZFwiLCBvblVwS2V5ZWQsIHRoaXMpLm9uU3luYyhcImRvd25LZXllZFwiLCBvbkRvd25LZXllZCwgdGhpcykub25TeW5jKFwibGVmdEtleWVkXCIsIG9uTGVmdEtleWVkLCB0aGlzKS5vblN5bmMoXCJyaWdodEtleWVkXCIsIG9uUmlnaHRLZXllZCwgdGhpcykub25TeW5jKFwicXVlcnlDaGFuZ2VkXCIsIG9uUXVlcnlDaGFuZ2VkLCB0aGlzKS5vblN5bmMoXCJ3aGl0ZXNwYWNlQ2hhbmdlZFwiLCBvbldoaXRlc3BhY2VDaGFuZ2VkLCB0aGlzKS5vblN5bmMoXCJsYW5nRGlyQ2hhbmdlZFwiLCB0aGlzLl9vbkxhbmdEaXJDaGFuZ2VkLCB0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICBfLm1peGluKFR5cGVhaGVhZC5wcm90b3R5cGUsIHtcbiAgICAgICAgICAgIF9oYWNrczogZnVuY3Rpb24gaGFja3MoKSB7XG4gICAgICAgICAgICAgICAgdmFyICRpbnB1dCwgJG1lbnU7XG4gICAgICAgICAgICAgICAgJGlucHV0ID0gdGhpcy5pbnB1dC4kaW5wdXQgfHwgJChcIjxkaXY+XCIpO1xuICAgICAgICAgICAgICAgICRtZW51ID0gdGhpcy5tZW51LiRub2RlIHx8ICQoXCI8ZGl2PlwiKTtcbiAgICAgICAgICAgICAgICAkaW5wdXQub24oXCJibHVyLnR0XCIsIGZ1bmN0aW9uKCRlKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBhY3RpdmUsIGlzQWN0aXZlLCBoYXNBY3RpdmU7XG4gICAgICAgICAgICAgICAgICAgIGFjdGl2ZSA9IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG4gICAgICAgICAgICAgICAgICAgIGlzQWN0aXZlID0gJG1lbnUuaXMoYWN0aXZlKTtcbiAgICAgICAgICAgICAgICAgICAgaGFzQWN0aXZlID0gJG1lbnUuaGFzKGFjdGl2ZSkubGVuZ3RoID4gMDtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF8uaXNNc2llKCkgJiYgKGlzQWN0aXZlIHx8IGhhc0FjdGl2ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF8uZGVmZXIoZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICRtZW51Lm9uKFwibW91c2Vkb3duLnR0XCIsIGZ1bmN0aW9uKCRlKSB7XG4gICAgICAgICAgICAgICAgICAgICRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29uU2VsZWN0YWJsZUNsaWNrZWQ6IGZ1bmN0aW9uIG9uU2VsZWN0YWJsZUNsaWNrZWQodHlwZSwgJGVsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3QoJGVsKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfb25EYXRhc2V0Q2xlYXJlZDogZnVuY3Rpb24gb25EYXRhc2V0Q2xlYXJlZCgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVIaW50KCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29uRGF0YXNldFJlbmRlcmVkOiBmdW5jdGlvbiBvbkRhdGFzZXRSZW5kZXJlZCh0eXBlLCBzdWdnZXN0aW9ucywgYXN5bmMsIGRhdGFzZXQpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl91cGRhdGVIaW50KCk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuYXV0b3NlbGVjdCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY3Vyc29yQ2xhc3MgPSB0aGlzLnNlbGVjdG9ycy5jdXJzb3Iuc3Vic3RyKDEpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lbnUuJG5vZGUuZmluZCh0aGlzLnNlbGVjdG9ycy5zdWdnZXN0aW9uKS5maXJzdCgpLmFkZENsYXNzKGN1cnNvckNsYXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy50cmlnZ2VyKFwicmVuZGVyXCIsIHN1Z2dlc3Rpb25zLCBhc3luYywgZGF0YXNldCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29uQXN5bmNSZXF1ZXN0ZWQ6IGZ1bmN0aW9uIG9uQXN5bmNSZXF1ZXN0ZWQodHlwZSwgZGF0YXNldCwgcXVlcnkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLnRyaWdnZXIoXCJhc3luY3JlcXVlc3RcIiwgcXVlcnksIGRhdGFzZXQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vbkFzeW5jQ2FuY2VsZWQ6IGZ1bmN0aW9uIG9uQXN5bmNDYW5jZWxlZCh0eXBlLCBkYXRhc2V0LCBxdWVyeSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMudHJpZ2dlcihcImFzeW5jY2FuY2VsXCIsIHF1ZXJ5LCBkYXRhc2V0KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfb25Bc3luY1JlY2VpdmVkOiBmdW5jdGlvbiBvbkFzeW5jUmVjZWl2ZWQodHlwZSwgZGF0YXNldCwgcXVlcnkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLnRyaWdnZXIoXCJhc3luY3JlY2VpdmVcIiwgcXVlcnksIGRhdGFzZXQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vbkZvY3VzZWQ6IGZ1bmN0aW9uIG9uRm9jdXNlZCgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9taW5MZW5ndGhNZXQoKSAmJiB0aGlzLm1lbnUudXBkYXRlKHRoaXMuaW5wdXQuZ2V0UXVlcnkoKSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29uQmx1cnJlZDogZnVuY3Rpb24gb25CbHVycmVkKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlucHV0Lmhhc1F1ZXJ5Q2hhbmdlZFNpbmNlTGFzdEZvY3VzKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5ldmVudEJ1cy50cmlnZ2VyKFwiY2hhbmdlXCIsIHRoaXMuaW5wdXQuZ2V0UXVlcnkoKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vbkVudGVyS2V5ZWQ6IGZ1bmN0aW9uIG9uRW50ZXJLZXllZCh0eXBlLCAkZSkge1xuICAgICAgICAgICAgICAgIHZhciAkc2VsZWN0YWJsZTtcbiAgICAgICAgICAgICAgICBpZiAoJHNlbGVjdGFibGUgPSB0aGlzLm1lbnUuZ2V0QWN0aXZlU2VsZWN0YWJsZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdCgkc2VsZWN0YWJsZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAkZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5hdXRvc2VsZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdCh0aGlzLm1lbnUuZ2V0VG9wU2VsZWN0YWJsZSgpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRlLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vblRhYktleWVkOiBmdW5jdGlvbiBvblRhYktleWVkKHR5cGUsICRlKSB7XG4gICAgICAgICAgICAgICAgdmFyICRzZWxlY3RhYmxlO1xuICAgICAgICAgICAgICAgIGlmICgkc2VsZWN0YWJsZSA9IHRoaXMubWVudS5nZXRBY3RpdmVTZWxlY3RhYmxlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZWxlY3QoJHNlbGVjdGFibGUpICYmICRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICgkc2VsZWN0YWJsZSA9IHRoaXMubWVudS5nZXRUb3BTZWxlY3RhYmxlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hdXRvY29tcGxldGUoJHNlbGVjdGFibGUpICYmICRlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vbkVzY0tleWVkOiBmdW5jdGlvbiBvbkVzY0tleWVkKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfb25VcEtleWVkOiBmdW5jdGlvbiBvblVwS2V5ZWQoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5tb3ZlQ3Vyc29yKC0xKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfb25Eb3duS2V5ZWQ6IGZ1bmN0aW9uIG9uRG93bktleWVkKCkge1xuICAgICAgICAgICAgICAgIHRoaXMubW92ZUN1cnNvcigrMSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29uTGVmdEtleWVkOiBmdW5jdGlvbiBvbkxlZnRLZXllZCgpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5kaXIgPT09IFwicnRsXCIgJiYgdGhpcy5pbnB1dC5pc0N1cnNvckF0RW5kKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hdXRvY29tcGxldGUodGhpcy5tZW51LmdldEFjdGl2ZVNlbGVjdGFibGUoKSB8fCB0aGlzLm1lbnUuZ2V0VG9wU2VsZWN0YWJsZSgpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29uUmlnaHRLZXllZDogZnVuY3Rpb24gb25SaWdodEtleWVkKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpciA9PT0gXCJsdHJcIiAmJiB0aGlzLmlucHV0LmlzQ3Vyc29yQXRFbmQoKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmF1dG9jb21wbGV0ZSh0aGlzLm1lbnUuZ2V0QWN0aXZlU2VsZWN0YWJsZSgpIHx8IHRoaXMubWVudS5nZXRUb3BTZWxlY3RhYmxlKCkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfb25RdWVyeUNoYW5nZWQ6IGZ1bmN0aW9uIG9uUXVlcnlDaGFuZ2VkKGUsIHF1ZXJ5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbWluTGVuZ3RoTWV0KHF1ZXJ5KSA/IHRoaXMubWVudS51cGRhdGUocXVlcnkpIDogdGhpcy5tZW51LmVtcHR5KCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29uV2hpdGVzcGFjZUNoYW5nZWQ6IGZ1bmN0aW9uIG9uV2hpdGVzcGFjZUNoYW5nZWQoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlSGludCgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF9vbkxhbmdEaXJDaGFuZ2VkOiBmdW5jdGlvbiBvbkxhbmdEaXJDaGFuZ2VkKGUsIGRpcikge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmRpciAhPT0gZGlyKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGlyID0gZGlyO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLm1lbnUuc2V0TGFuZ3VhZ2VEaXJlY3Rpb24oZGlyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgX29wZW5JZkFjdGl2ZTogZnVuY3Rpb24gb3BlbklmQWN0aXZlKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaXNBY3RpdmUoKSAmJiB0aGlzLm9wZW4oKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBfbWluTGVuZ3RoTWV0OiBmdW5jdGlvbiBtaW5MZW5ndGhNZXQocXVlcnkpIHtcbiAgICAgICAgICAgICAgICBxdWVyeSA9IF8uaXNTdHJpbmcocXVlcnkpID8gcXVlcnkgOiB0aGlzLmlucHV0LmdldFF1ZXJ5KCkgfHwgXCJcIjtcbiAgICAgICAgICAgICAgICByZXR1cm4gcXVlcnkubGVuZ3RoID49IHRoaXMubWluTGVuZ3RoO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF91cGRhdGVIaW50OiBmdW5jdGlvbiB1cGRhdGVIaW50KCkge1xuICAgICAgICAgICAgICAgIHZhciAkc2VsZWN0YWJsZSwgZGF0YSwgdmFsLCBxdWVyeSwgZXNjYXBlZFF1ZXJ5LCBmcm9udE1hdGNoUmVnRXgsIG1hdGNoO1xuICAgICAgICAgICAgICAgICRzZWxlY3RhYmxlID0gdGhpcy5tZW51LmdldFRvcFNlbGVjdGFibGUoKTtcbiAgICAgICAgICAgICAgICBkYXRhID0gdGhpcy5tZW51LmdldFNlbGVjdGFibGVEYXRhKCRzZWxlY3RhYmxlKTtcbiAgICAgICAgICAgICAgICB2YWwgPSB0aGlzLmlucHV0LmdldElucHV0VmFsdWUoKTtcbiAgICAgICAgICAgICAgICBpZiAoZGF0YSAmJiAhXy5pc0JsYW5rU3RyaW5nKHZhbCkgJiYgIXRoaXMuaW5wdXQuaGFzT3ZlcmZsb3coKSkge1xuICAgICAgICAgICAgICAgICAgICBxdWVyeSA9IElucHV0Lm5vcm1hbGl6ZVF1ZXJ5KHZhbCk7XG4gICAgICAgICAgICAgICAgICAgIGVzY2FwZWRRdWVyeSA9IF8uZXNjYXBlUmVnRXhDaGFycyhxdWVyeSk7XG4gICAgICAgICAgICAgICAgICAgIGZyb250TWF0Y2hSZWdFeCA9IG5ldyBSZWdFeHAoXCJeKD86XCIgKyBlc2NhcGVkUXVlcnkgKyBcIikoLiskKVwiLCBcImlcIik7XG4gICAgICAgICAgICAgICAgICAgIG1hdGNoID0gZnJvbnRNYXRjaFJlZ0V4LmV4ZWMoZGF0YS52YWwpO1xuICAgICAgICAgICAgICAgICAgICBtYXRjaCAmJiB0aGlzLmlucHV0LnNldEhpbnQodmFsICsgbWF0Y2hbMV0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQuY2xlYXJIaW50KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzRW5hYmxlZDogZnVuY3Rpb24gaXNFbmFibGVkKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmVuYWJsZWQ7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW5hYmxlOiBmdW5jdGlvbiBlbmFibGUoKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5lbmFibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaXNhYmxlOiBmdW5jdGlvbiBkaXNhYmxlKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuZW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzQWN0aXZlOiBmdW5jdGlvbiBpc0FjdGl2ZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hY3RpdmU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWN0aXZhdGU6IGZ1bmN0aW9uIGFjdGl2YXRlKCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzQWN0aXZlKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5pc0VuYWJsZWQoKSB8fCB0aGlzLmV2ZW50QnVzLmJlZm9yZShcImFjdGl2ZVwiKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hY3RpdmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLnRyaWdnZXIoXCJhY3RpdmVcIik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWFjdGl2YXRlOiBmdW5jdGlvbiBkZWFjdGl2YXRlKCkge1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0FjdGl2ZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5ldmVudEJ1cy5iZWZvcmUoXCJpZGxlXCIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmFjdGl2ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMudHJpZ2dlcihcImlkbGVcIik7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc09wZW46IGZ1bmN0aW9uIGlzT3BlbigpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tZW51LmlzT3BlbigpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG9wZW46IGZ1bmN0aW9uIG9wZW4oKSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzT3BlbigpICYmICF0aGlzLmV2ZW50QnVzLmJlZm9yZShcIm9wZW5cIikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZW51Lm9wZW4oKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlSGludCgpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLnRyaWdnZXIoXCJvcGVuXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5pc09wZW4oKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24gY2xvc2UoKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNPcGVuKCkgJiYgIXRoaXMuZXZlbnRCdXMuYmVmb3JlKFwiY2xvc2VcIikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZW51LmNsb3NlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQuY2xlYXJIaW50KCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQucmVzZXRJbnB1dFZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMudHJpZ2dlcihcImNsb3NlXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gIXRoaXMuaXNPcGVuKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0VmFsOiBmdW5jdGlvbiBzZXRWYWwodmFsKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dC5zZXRRdWVyeShfLnRvU3RyKHZhbCkpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldFZhbDogZnVuY3Rpb24gZ2V0VmFsKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmlucHV0LmdldFF1ZXJ5KCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2VsZWN0OiBmdW5jdGlvbiBzZWxlY3QoJHNlbGVjdGFibGUpIHtcbiAgICAgICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMubWVudS5nZXRTZWxlY3RhYmxlRGF0YSgkc2VsZWN0YWJsZSk7XG4gICAgICAgICAgICAgICAgaWYgKGRhdGEgJiYgIXRoaXMuZXZlbnRCdXMuYmVmb3JlKFwic2VsZWN0XCIsIGRhdGEub2JqLCBkYXRhLmRhdGFzZXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQuc2V0UXVlcnkoZGF0YS52YWwsIHRydWUpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLnRyaWdnZXIoXCJzZWxlY3RcIiwgZGF0YS5vYmosIGRhdGEuZGF0YXNldCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xvc2UoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhdXRvY29tcGxldGU6IGZ1bmN0aW9uIGF1dG9jb21wbGV0ZSgkc2VsZWN0YWJsZSkge1xuICAgICAgICAgICAgICAgIHZhciBxdWVyeSwgZGF0YSwgaXNWYWxpZDtcbiAgICAgICAgICAgICAgICBxdWVyeSA9IHRoaXMuaW5wdXQuZ2V0UXVlcnkoKTtcbiAgICAgICAgICAgICAgICBkYXRhID0gdGhpcy5tZW51LmdldFNlbGVjdGFibGVEYXRhKCRzZWxlY3RhYmxlKTtcbiAgICAgICAgICAgICAgICBpc1ZhbGlkID0gZGF0YSAmJiBxdWVyeSAhPT0gZGF0YS52YWw7XG4gICAgICAgICAgICAgICAgaWYgKGlzVmFsaWQgJiYgIXRoaXMuZXZlbnRCdXMuYmVmb3JlKFwiYXV0b2NvbXBsZXRlXCIsIGRhdGEub2JqLCBkYXRhLmRhdGFzZXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQuc2V0UXVlcnkoZGF0YS52YWwpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmV2ZW50QnVzLnRyaWdnZXIoXCJhdXRvY29tcGxldGVcIiwgZGF0YS5vYmosIGRhdGEuZGF0YXNldCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbW92ZUN1cnNvcjogZnVuY3Rpb24gbW92ZUN1cnNvcihkZWx0YSkge1xuICAgICAgICAgICAgICAgIHZhciBxdWVyeSwgJGNhbmRpZGF0ZSwgZGF0YSwgc3VnZ2VzdGlvbiwgZGF0YXNldE5hbWUsIGNhbmNlbE1vdmUsIGlkO1xuICAgICAgICAgICAgICAgIHF1ZXJ5ID0gdGhpcy5pbnB1dC5nZXRRdWVyeSgpO1xuICAgICAgICAgICAgICAgICRjYW5kaWRhdGUgPSB0aGlzLm1lbnUuc2VsZWN0YWJsZVJlbGF0aXZlVG9DdXJzb3IoZGVsdGEpO1xuICAgICAgICAgICAgICAgIGRhdGEgPSB0aGlzLm1lbnUuZ2V0U2VsZWN0YWJsZURhdGEoJGNhbmRpZGF0ZSk7XG4gICAgICAgICAgICAgICAgc3VnZ2VzdGlvbiA9IGRhdGEgPyBkYXRhLm9iaiA6IG51bGw7XG4gICAgICAgICAgICAgICAgZGF0YXNldE5hbWUgPSBkYXRhID8gZGF0YS5kYXRhc2V0IDogbnVsbDtcbiAgICAgICAgICAgICAgICBpZCA9ICRjYW5kaWRhdGUgPyAkY2FuZGlkYXRlLmF0dHIoXCJpZFwiKSA6IG51bGw7XG4gICAgICAgICAgICAgICAgdGhpcy5pbnB1dC50cmlnZ2VyKFwiY3Vyc29yY2hhbmdlXCIsIGlkKTtcbiAgICAgICAgICAgICAgICBjYW5jZWxNb3ZlID0gdGhpcy5fbWluTGVuZ3RoTWV0KCkgJiYgdGhpcy5tZW51LnVwZGF0ZShxdWVyeSk7XG4gICAgICAgICAgICAgICAgaWYgKCFjYW5jZWxNb3ZlICYmICF0aGlzLmV2ZW50QnVzLmJlZm9yZShcImN1cnNvcmNoYW5nZVwiLCBzdWdnZXN0aW9uLCBkYXRhc2V0TmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tZW51LnNldEN1cnNvcigkY2FuZGlkYXRlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuaW5wdXQuc2V0SW5wdXRWYWx1ZShkYXRhLnZhbCk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmlucHV0LnJlc2V0SW5wdXRWYWx1ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdXBkYXRlSGludCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRCdXMudHJpZ2dlcihcImN1cnNvcmNoYW5nZVwiLCBzdWdnZXN0aW9uLCBkYXRhc2V0TmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVzdHJveTogZnVuY3Rpb24gZGVzdHJveSgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmlucHV0LmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB0aGlzLm1lbnUuZGVzdHJveSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIFR5cGVhaGVhZDtcbiAgICAgICAgZnVuY3Rpb24gYyhjdHgpIHtcbiAgICAgICAgICAgIHZhciBtZXRob2RzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgICAgICAgICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICAgICAgICAgIF8uZWFjaChtZXRob2RzLCBmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGN0eFttZXRob2RdLmFwcGx5KGN0eCwgYXJncyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfSgpO1xuICAgIChmdW5jdGlvbigpIHtcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XG4gICAgICAgIHZhciBvbGQsIGtleXMsIG1ldGhvZHM7XG4gICAgICAgIG9sZCA9ICQuZm4udHlwZWFoZWFkO1xuICAgICAgICBrZXlzID0ge1xuICAgICAgICAgICAgd3d3OiBcInR0LXd3d1wiLFxuICAgICAgICAgICAgYXR0cnM6IFwidHQtYXR0cnNcIixcbiAgICAgICAgICAgIHR5cGVhaGVhZDogXCJ0dC10eXBlYWhlYWRcIlxuICAgICAgICB9O1xuICAgICAgICBtZXRob2RzID0ge1xuICAgICAgICAgICAgaW5pdGlhbGl6ZTogZnVuY3Rpb24gaW5pdGlhbGl6ZShvLCBkYXRhc2V0cykge1xuICAgICAgICAgICAgICAgIHZhciB3d3c7XG4gICAgICAgICAgICAgICAgZGF0YXNldHMgPSBfLmlzQXJyYXkoZGF0YXNldHMpID8gZGF0YXNldHMgOiBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gICAgICAgICAgICAgICAgbyA9IG8gfHwge307XG4gICAgICAgICAgICAgICAgd3d3ID0gV1dXKG8uY2xhc3NOYW1lcyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZWFjaChhdHRhY2gpO1xuICAgICAgICAgICAgICAgIGZ1bmN0aW9uIGF0dGFjaCgpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyICRpbnB1dCwgJHdyYXBwZXIsICRoaW50LCAkbWVudSwgZGVmYXVsdEhpbnQsIGRlZmF1bHRNZW51LCBldmVudEJ1cywgaW5wdXQsIG1lbnUsIHN0YXR1cywgdHlwZWFoZWFkLCBNZW51Q29uc3RydWN0b3I7XG4gICAgICAgICAgICAgICAgICAgIF8uZWFjaChkYXRhc2V0cywgZnVuY3Rpb24oZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZC5oaWdobGlnaHQgPSAhIW8uaGlnaGxpZ2h0O1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgJGlucHV0ID0gJCh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgJHdyYXBwZXIgPSAkKHd3dy5odG1sLndyYXBwZXIpO1xuICAgICAgICAgICAgICAgICAgICAkaGludCA9ICRlbE9yTnVsbChvLmhpbnQpO1xuICAgICAgICAgICAgICAgICAgICAkbWVudSA9ICRlbE9yTnVsbChvLm1lbnUpO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0SGludCA9IG8uaGludCAhPT0gZmFsc2UgJiYgISRoaW50O1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0TWVudSA9IG8ubWVudSAhPT0gZmFsc2UgJiYgISRtZW51O1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0SGludCAmJiAoJGhpbnQgPSBidWlsZEhpbnRGcm9tSW5wdXQoJGlucHV0LCB3d3cpKTtcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdE1lbnUgJiYgKCRtZW51ID0gJCh3d3cuaHRtbC5tZW51KS5jc3Mod3d3LmNzcy5tZW51KSk7XG4gICAgICAgICAgICAgICAgICAgICRoaW50ICYmICRoaW50LnZhbChcIlwiKTtcbiAgICAgICAgICAgICAgICAgICAgJGlucHV0ID0gcHJlcElucHV0KCRpbnB1dCwgd3d3KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRlZmF1bHRIaW50IHx8IGRlZmF1bHRNZW51KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAkd3JhcHBlci5jc3Mod3d3LmNzcy53cmFwcGVyKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dC5jc3MoZGVmYXVsdEhpbnQgPyB3d3cuY3NzLmlucHV0IDogd3d3LmNzcy5pbnB1dFdpdGhOb0hpbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgJGlucHV0LndyYXAoJHdyYXBwZXIpLnBhcmVudCgpLnByZXBlbmQoZGVmYXVsdEhpbnQgPyAkaGludCA6IG51bGwpLmFwcGVuZChkZWZhdWx0TWVudSA/ICRtZW51IDogbnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgTWVudUNvbnN0cnVjdG9yID0gZGVmYXVsdE1lbnUgPyBEZWZhdWx0TWVudSA6IE1lbnU7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50QnVzID0gbmV3IEV2ZW50QnVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVsOiAkaW5wdXRcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0ID0gbmV3IElucHV0KHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhpbnQ6ICRoaW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQ6ICRpbnB1dFxuICAgICAgICAgICAgICAgICAgICB9LCB3d3cpO1xuICAgICAgICAgICAgICAgICAgICBtZW51ID0gbmV3IE1lbnVDb25zdHJ1Y3Rvcih7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlOiAkbWVudSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFzZXRzOiBkYXRhc2V0c1xuICAgICAgICAgICAgICAgICAgICB9LCB3d3cpO1xuICAgICAgICAgICAgICAgICAgICBzdGF0dXMgPSBuZXcgU3RhdHVzKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICRpbnB1dDogJGlucHV0LFxuICAgICAgICAgICAgICAgICAgICAgICAgbWVudTogbWVudVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZWFoZWFkID0gbmV3IFR5cGVhaGVhZCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dDogaW5wdXQsXG4gICAgICAgICAgICAgICAgICAgICAgICBtZW51OiBtZW51LFxuICAgICAgICAgICAgICAgICAgICAgICAgZXZlbnRCdXM6IGV2ZW50QnVzLFxuICAgICAgICAgICAgICAgICAgICAgICAgbWluTGVuZ3RoOiBvLm1pbkxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9zZWxlY3Q6IG8uYXV0b3NlbGVjdFxuICAgICAgICAgICAgICAgICAgICB9LCB3d3cpO1xuICAgICAgICAgICAgICAgICAgICAkaW5wdXQuZGF0YShrZXlzLnd3dywgd3d3KTtcbiAgICAgICAgICAgICAgICAgICAgJGlucHV0LmRhdGEoa2V5cy50eXBlYWhlYWQsIHR5cGVhaGVhZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzRW5hYmxlZDogZnVuY3Rpb24gaXNFbmFibGVkKCkge1xuICAgICAgICAgICAgICAgIHZhciBlbmFibGVkO1xuICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLmZpcnN0KCksIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgZW5hYmxlZCA9IHQuaXNFbmFibGVkKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVuYWJsZWQ7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZW5hYmxlOiBmdW5jdGlvbiBlbmFibGUoKSB7XG4gICAgICAgICAgICAgICAgdHRFYWNoKHRoaXMsIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdC5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaXNhYmxlOiBmdW5jdGlvbiBkaXNhYmxlKCkge1xuICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLCBmdW5jdGlvbih0KSB7XG4gICAgICAgICAgICAgICAgICAgIHQuZGlzYWJsZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzQWN0aXZlOiBmdW5jdGlvbiBpc0FjdGl2ZSgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYWN0aXZlO1xuICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLmZpcnN0KCksIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlID0gdC5pc0FjdGl2ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiBhY3RpdmU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYWN0aXZhdGU6IGZ1bmN0aW9uIGFjdGl2YXRlKCkge1xuICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLCBmdW5jdGlvbih0KSB7XG4gICAgICAgICAgICAgICAgICAgIHQuYWN0aXZhdGUoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWFjdGl2YXRlOiBmdW5jdGlvbiBkZWFjdGl2YXRlKCkge1xuICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLCBmdW5jdGlvbih0KSB7XG4gICAgICAgICAgICAgICAgICAgIHQuZGVhY3RpdmF0ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzT3BlbjogZnVuY3Rpb24gaXNPcGVuKCkge1xuICAgICAgICAgICAgICAgIHZhciBvcGVuO1xuICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLmZpcnN0KCksIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgb3BlbiA9IHQuaXNPcGVuKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wZW47XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3BlbjogZnVuY3Rpb24gb3BlbigpIHtcbiAgICAgICAgICAgICAgICB0dEVhY2godGhpcywgZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgICAgICAgICB0Lm9wZW4oKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjbG9zZTogZnVuY3Rpb24gY2xvc2UoKSB7XG4gICAgICAgICAgICAgICAgdHRFYWNoKHRoaXMsIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgdC5jbG9zZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlbGVjdDogZnVuY3Rpb24gc2VsZWN0KGVsKSB7XG4gICAgICAgICAgICAgICAgdmFyIHN1Y2Nlc3MgPSBmYWxzZSwgJGVsID0gJChlbCk7XG4gICAgICAgICAgICAgICAgdHRFYWNoKHRoaXMuZmlyc3QoKSwgZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzID0gdC5zZWxlY3QoJGVsKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3VjY2VzcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBhdXRvY29tcGxldGU6IGZ1bmN0aW9uIGF1dG9jb21wbGV0ZShlbCkge1xuICAgICAgICAgICAgICAgIHZhciBzdWNjZXNzID0gZmFsc2UsICRlbCA9ICQoZWwpO1xuICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLmZpcnN0KCksIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgc3VjY2VzcyA9IHQuYXV0b2NvbXBsZXRlKCRlbCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHN1Y2Nlc3M7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbW92ZUN1cnNvcjogZnVuY3Rpb24gbW92ZUN1cnNvZShkZWx0YSkge1xuICAgICAgICAgICAgICAgIHZhciBzdWNjZXNzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdHRFYWNoKHRoaXMuZmlyc3QoKSwgZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgICAgICAgICBzdWNjZXNzID0gdC5tb3ZlQ3Vyc29yKGRlbHRhKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gc3VjY2VzcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2YWw6IGZ1bmN0aW9uIHZhbChuZXdWYWwpIHtcbiAgICAgICAgICAgICAgICB2YXIgcXVlcnk7XG4gICAgICAgICAgICAgICAgaWYgKCFhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLmZpcnN0KCksIGZ1bmN0aW9uKHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHF1ZXJ5ID0gdC5nZXRWYWwoKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBxdWVyeTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0dEVhY2godGhpcywgZnVuY3Rpb24odCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdC5zZXRWYWwoXy50b1N0cihuZXdWYWwpKTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZXN0cm95OiBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgICAgICAgICAgICAgIHR0RWFjaCh0aGlzLCBmdW5jdGlvbih0eXBlYWhlYWQsICRpbnB1dCkge1xuICAgICAgICAgICAgICAgICAgICByZXZlcnQoJGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZWFoZWFkLmRlc3Ryb3koKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgJC5mbi50eXBlYWhlYWQgPSBmdW5jdGlvbihtZXRob2QpIHtcbiAgICAgICAgICAgIGlmIChtZXRob2RzW21ldGhvZF0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWV0aG9kc1ttZXRob2RdLmFwcGx5KHRoaXMsIFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBtZXRob2RzLmluaXRpYWxpemUuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgJC5mbi50eXBlYWhlYWQubm9Db25mbGljdCA9IGZ1bmN0aW9uIG5vQ29uZmxpY3QoKSB7XG4gICAgICAgICAgICAkLmZuLnR5cGVhaGVhZCA9IG9sZDtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9O1xuICAgICAgICBmdW5jdGlvbiB0dEVhY2goJGVscywgZm4pIHtcbiAgICAgICAgICAgICRlbHMuZWFjaChmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICB2YXIgJGlucHV0ID0gJCh0aGlzKSwgdHlwZWFoZWFkO1xuICAgICAgICAgICAgICAgICh0eXBlYWhlYWQgPSAkaW5wdXQuZGF0YShrZXlzLnR5cGVhaGVhZCkpICYmIGZuKHR5cGVhaGVhZCwgJGlucHV0KTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGJ1aWxkSGludEZyb21JbnB1dCgkaW5wdXQsIHd3dykge1xuICAgICAgICAgICAgcmV0dXJuICRpbnB1dC5jbG9uZSgpLmFkZENsYXNzKHd3dy5jbGFzc2VzLmhpbnQpLnJlbW92ZURhdGEoKS5jc3Mod3d3LmNzcy5oaW50KS5jc3MoZ2V0QmFja2dyb3VuZFN0eWxlcygkaW5wdXQpKS5wcm9wKHtcbiAgICAgICAgICAgICAgICByZWFkb25seTogdHJ1ZSxcbiAgICAgICAgICAgICAgICByZXF1aXJlZDogZmFsc2VcbiAgICAgICAgICAgIH0pLnJlbW92ZUF0dHIoXCJpZCBuYW1lIHBsYWNlaG9sZGVyXCIpLnJlbW92ZUNsYXNzKFwicmVxdWlyZWRcIikuYXR0cih7XG4gICAgICAgICAgICAgICAgc3BlbGxjaGVjazogXCJmYWxzZVwiLFxuICAgICAgICAgICAgICAgIHRhYmluZGV4OiAtMVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcHJlcElucHV0KCRpbnB1dCwgd3d3KSB7XG4gICAgICAgICAgICAkaW5wdXQuZGF0YShrZXlzLmF0dHJzLCB7XG4gICAgICAgICAgICAgICAgZGlyOiAkaW5wdXQuYXR0cihcImRpclwiKSxcbiAgICAgICAgICAgICAgICBhdXRvY29tcGxldGU6ICRpbnB1dC5hdHRyKFwiYXV0b2NvbXBsZXRlXCIpLFxuICAgICAgICAgICAgICAgIHNwZWxsY2hlY2s6ICRpbnB1dC5hdHRyKFwic3BlbGxjaGVja1wiKSxcbiAgICAgICAgICAgICAgICBzdHlsZTogJGlucHV0LmF0dHIoXCJzdHlsZVwiKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAkaW5wdXQuYWRkQ2xhc3Mod3d3LmNsYXNzZXMuaW5wdXQpLmF0dHIoe1xuICAgICAgICAgICAgICAgIHNwZWxsY2hlY2s6IGZhbHNlXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgISRpbnB1dC5hdHRyKFwiZGlyXCIpICYmICRpbnB1dC5hdHRyKFwiZGlyXCIsIFwiYXV0b1wiKTtcbiAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHt9XG4gICAgICAgICAgICByZXR1cm4gJGlucHV0O1xuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uIGdldEJhY2tncm91bmRTdHlsZXMoJGVsKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIGJhY2tncm91bmRBdHRhY2htZW50OiAkZWwuY3NzKFwiYmFja2dyb3VuZC1hdHRhY2htZW50XCIpLFxuICAgICAgICAgICAgICAgIGJhY2tncm91bmRDbGlwOiAkZWwuY3NzKFwiYmFja2dyb3VuZC1jbGlwXCIpLFxuICAgICAgICAgICAgICAgIGJhY2tncm91bmRDb2xvcjogJGVsLmNzcyhcImJhY2tncm91bmQtY29sb3JcIiksXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZEltYWdlOiAkZWwuY3NzKFwiYmFja2dyb3VuZC1pbWFnZVwiKSxcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kT3JpZ2luOiAkZWwuY3NzKFwiYmFja2dyb3VuZC1vcmlnaW5cIiksXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZFBvc2l0aW9uOiAkZWwuY3NzKFwiYmFja2dyb3VuZC1wb3NpdGlvblwiKSxcbiAgICAgICAgICAgICAgICBiYWNrZ3JvdW5kUmVwZWF0OiAkZWwuY3NzKFwiYmFja2dyb3VuZC1yZXBlYXRcIiksXG4gICAgICAgICAgICAgICAgYmFja2dyb3VuZFNpemU6ICRlbC5jc3MoXCJiYWNrZ3JvdW5kLXNpemVcIilcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZnVuY3Rpb24gcmV2ZXJ0KCRpbnB1dCkge1xuICAgICAgICAgICAgdmFyIHd3dywgJHdyYXBwZXI7XG4gICAgICAgICAgICB3d3cgPSAkaW5wdXQuZGF0YShrZXlzLnd3dyk7XG4gICAgICAgICAgICAkd3JhcHBlciA9ICRpbnB1dC5wYXJlbnQoKS5maWx0ZXIod3d3LnNlbGVjdG9ycy53cmFwcGVyKTtcbiAgICAgICAgICAgIF8uZWFjaCgkaW5wdXQuZGF0YShrZXlzLmF0dHJzKSwgZnVuY3Rpb24odmFsLCBrZXkpIHtcbiAgICAgICAgICAgICAgICBfLmlzVW5kZWZpbmVkKHZhbCkgPyAkaW5wdXQucmVtb3ZlQXR0cihrZXkpIDogJGlucHV0LmF0dHIoa2V5LCB2YWwpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAkaW5wdXQucmVtb3ZlRGF0YShrZXlzLnR5cGVhaGVhZCkucmVtb3ZlRGF0YShrZXlzLnd3dykucmVtb3ZlRGF0YShrZXlzLmF0dHIpLnJlbW92ZUNsYXNzKHd3dy5jbGFzc2VzLmlucHV0KTtcbiAgICAgICAgICAgIGlmICgkd3JhcHBlci5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAkaW5wdXQuZGV0YWNoKCkuaW5zZXJ0QWZ0ZXIoJHdyYXBwZXIpO1xuICAgICAgICAgICAgICAgICR3cmFwcGVyLnJlbW92ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZ1bmN0aW9uICRlbE9yTnVsbChvYmopIHtcbiAgICAgICAgICAgIHZhciBpc1ZhbGlkLCAkZWw7XG4gICAgICAgICAgICBpc1ZhbGlkID0gXy5pc0pRdWVyeShvYmopIHx8IF8uaXNFbGVtZW50KG9iaik7XG4gICAgICAgICAgICAkZWwgPSBpc1ZhbGlkID8gJChvYmopLmZpcnN0KCkgOiBbXTtcbiAgICAgICAgICAgIHJldHVybiAkZWwubGVuZ3RoID8gJGVsIDogbnVsbDtcbiAgICAgICAgfVxuICAgIH0pKCk7XG59KTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9jb3JlanMtdHlwZWFoZWFkL2Rpc3QvdHlwZWFoZWFkLmJ1bmRsZS5qc1xuLy8gbW9kdWxlIGlkID0gMTI3XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsInZhciBhcHBseSA9IEZ1bmN0aW9uLnByb3RvdHlwZS5hcHBseTtcblxuLy8gRE9NIEFQSXMsIGZvciBjb21wbGV0ZW5lc3NcblxuZXhwb3J0cy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgVGltZW91dChhcHBseS5jYWxsKHNldFRpbWVvdXQsIHdpbmRvdywgYXJndW1lbnRzKSwgY2xlYXJUaW1lb3V0KTtcbn07XG5leHBvcnRzLnNldEludGVydmFsID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgVGltZW91dChhcHBseS5jYWxsKHNldEludGVydmFsLCB3aW5kb3csIGFyZ3VtZW50cyksIGNsZWFySW50ZXJ2YWwpO1xufTtcbmV4cG9ydHMuY2xlYXJUaW1lb3V0ID1cbmV4cG9ydHMuY2xlYXJJbnRlcnZhbCA9IGZ1bmN0aW9uKHRpbWVvdXQpIHtcbiAgaWYgKHRpbWVvdXQpIHtcbiAgICB0aW1lb3V0LmNsb3NlKCk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIFRpbWVvdXQoaWQsIGNsZWFyRm4pIHtcbiAgdGhpcy5faWQgPSBpZDtcbiAgdGhpcy5fY2xlYXJGbiA9IGNsZWFyRm47XG59XG5UaW1lb3V0LnByb3RvdHlwZS51bnJlZiA9IFRpbWVvdXQucHJvdG90eXBlLnJlZiA9IGZ1bmN0aW9uKCkge307XG5UaW1lb3V0LnByb3RvdHlwZS5jbG9zZSA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLl9jbGVhckZuLmNhbGwod2luZG93LCB0aGlzLl9pZCk7XG59O1xuXG4vLyBEb2VzIG5vdCBzdGFydCB0aGUgdGltZSwganVzdCBzZXRzIHVwIHRoZSBtZW1iZXJzIG5lZWRlZC5cbmV4cG9ydHMuZW5yb2xsID0gZnVuY3Rpb24oaXRlbSwgbXNlY3MpIHtcbiAgY2xlYXJUaW1lb3V0KGl0ZW0uX2lkbGVUaW1lb3V0SWQpO1xuICBpdGVtLl9pZGxlVGltZW91dCA9IG1zZWNzO1xufTtcblxuZXhwb3J0cy51bmVucm9sbCA9IGZ1bmN0aW9uKGl0ZW0pIHtcbiAgY2xlYXJUaW1lb3V0KGl0ZW0uX2lkbGVUaW1lb3V0SWQpO1xuICBpdGVtLl9pZGxlVGltZW91dCA9IC0xO1xufTtcblxuZXhwb3J0cy5fdW5yZWZBY3RpdmUgPSBleHBvcnRzLmFjdGl2ZSA9IGZ1bmN0aW9uKGl0ZW0pIHtcbiAgY2xlYXJUaW1lb3V0KGl0ZW0uX2lkbGVUaW1lb3V0SWQpO1xuXG4gIHZhciBtc2VjcyA9IGl0ZW0uX2lkbGVUaW1lb3V0O1xuICBpZiAobXNlY3MgPj0gMCkge1xuICAgIGl0ZW0uX2lkbGVUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uIG9uVGltZW91dCgpIHtcbiAgICAgIGlmIChpdGVtLl9vblRpbWVvdXQpXG4gICAgICAgIGl0ZW0uX29uVGltZW91dCgpO1xuICAgIH0sIG1zZWNzKTtcbiAgfVxufTtcblxuLy8gc2V0aW1tZWRpYXRlIGF0dGFjaGVzIGl0c2VsZiB0byB0aGUgZ2xvYmFsIG9iamVjdFxucmVxdWlyZShcInNldGltbWVkaWF0ZVwiKTtcbmV4cG9ydHMuc2V0SW1tZWRpYXRlID0gc2V0SW1tZWRpYXRlO1xuZXhwb3J0cy5jbGVhckltbWVkaWF0ZSA9IGNsZWFySW1tZWRpYXRlO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvdGltZXJzLWJyb3dzZXJpZnkvbWFpbi5qc1xuLy8gbW9kdWxlIGlkID0gMTI4XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIihmdW5jdGlvbiAoZ2xvYmFsLCB1bmRlZmluZWQpIHtcbiAgICBcInVzZSBzdHJpY3RcIjtcblxuICAgIGlmIChnbG9iYWwuc2V0SW1tZWRpYXRlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgbmV4dEhhbmRsZSA9IDE7IC8vIFNwZWMgc2F5cyBncmVhdGVyIHRoYW4gemVyb1xuICAgIHZhciB0YXNrc0J5SGFuZGxlID0ge307XG4gICAgdmFyIGN1cnJlbnRseVJ1bm5pbmdBVGFzayA9IGZhbHNlO1xuICAgIHZhciBkb2MgPSBnbG9iYWwuZG9jdW1lbnQ7XG4gICAgdmFyIHJlZ2lzdGVySW1tZWRpYXRlO1xuXG4gICAgZnVuY3Rpb24gc2V0SW1tZWRpYXRlKGNhbGxiYWNrKSB7XG4gICAgICAvLyBDYWxsYmFjayBjYW4gZWl0aGVyIGJlIGEgZnVuY3Rpb24gb3IgYSBzdHJpbmdcbiAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgIT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICBjYWxsYmFjayA9IG5ldyBGdW5jdGlvbihcIlwiICsgY2FsbGJhY2spO1xuICAgICAgfVxuICAgICAgLy8gQ29weSBmdW5jdGlvbiBhcmd1bWVudHNcbiAgICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJncy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgIGFyZ3NbaV0gPSBhcmd1bWVudHNbaSArIDFdO1xuICAgICAgfVxuICAgICAgLy8gU3RvcmUgYW5kIHJlZ2lzdGVyIHRoZSB0YXNrXG4gICAgICB2YXIgdGFzayA9IHsgY2FsbGJhY2s6IGNhbGxiYWNrLCBhcmdzOiBhcmdzIH07XG4gICAgICB0YXNrc0J5SGFuZGxlW25leHRIYW5kbGVdID0gdGFzaztcbiAgICAgIHJlZ2lzdGVySW1tZWRpYXRlKG5leHRIYW5kbGUpO1xuICAgICAgcmV0dXJuIG5leHRIYW5kbGUrKztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjbGVhckltbWVkaWF0ZShoYW5kbGUpIHtcbiAgICAgICAgZGVsZXRlIHRhc2tzQnlIYW5kbGVbaGFuZGxlXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBydW4odGFzaykge1xuICAgICAgICB2YXIgY2FsbGJhY2sgPSB0YXNrLmNhbGxiYWNrO1xuICAgICAgICB2YXIgYXJncyA9IHRhc2suYXJncztcbiAgICAgICAgc3dpdGNoIChhcmdzLmxlbmd0aCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICBjYWxsYmFjaygpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgIGNhbGxiYWNrKGFyZ3NbMF0pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIGNhbGxiYWNrKGFyZ3NbMF0sIGFyZ3NbMV0pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgIGNhbGxiYWNrKGFyZ3NbMF0sIGFyZ3NbMV0sIGFyZ3NbMl0pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICBjYWxsYmFjay5hcHBseSh1bmRlZmluZWQsIGFyZ3MpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBydW5JZlByZXNlbnQoaGFuZGxlKSB7XG4gICAgICAgIC8vIEZyb20gdGhlIHNwZWM6IFwiV2FpdCB1bnRpbCBhbnkgaW52b2NhdGlvbnMgb2YgdGhpcyBhbGdvcml0aG0gc3RhcnRlZCBiZWZvcmUgdGhpcyBvbmUgaGF2ZSBjb21wbGV0ZWQuXCJcbiAgICAgICAgLy8gU28gaWYgd2UncmUgY3VycmVudGx5IHJ1bm5pbmcgYSB0YXNrLCB3ZSdsbCBuZWVkIHRvIGRlbGF5IHRoaXMgaW52b2NhdGlvbi5cbiAgICAgICAgaWYgKGN1cnJlbnRseVJ1bm5pbmdBVGFzaykge1xuICAgICAgICAgICAgLy8gRGVsYXkgYnkgZG9pbmcgYSBzZXRUaW1lb3V0LiBzZXRJbW1lZGlhdGUgd2FzIHRyaWVkIGluc3RlYWQsIGJ1dCBpbiBGaXJlZm94IDcgaXQgZ2VuZXJhdGVkIGFcbiAgICAgICAgICAgIC8vIFwidG9vIG11Y2ggcmVjdXJzaW9uXCIgZXJyb3IuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KHJ1bklmUHJlc2VudCwgMCwgaGFuZGxlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhciB0YXNrID0gdGFza3NCeUhhbmRsZVtoYW5kbGVdO1xuICAgICAgICAgICAgaWYgKHRhc2spIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50bHlSdW5uaW5nQVRhc2sgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHJ1bih0YXNrKTtcbiAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICBjbGVhckltbWVkaWF0ZShoYW5kbGUpO1xuICAgICAgICAgICAgICAgICAgICBjdXJyZW50bHlSdW5uaW5nQVRhc2sgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsTmV4dFRpY2tJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgcmVnaXN0ZXJJbW1lZGlhdGUgPSBmdW5jdGlvbihoYW5kbGUpIHtcbiAgICAgICAgICAgIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24gKCkgeyBydW5JZlByZXNlbnQoaGFuZGxlKTsgfSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2FuVXNlUG9zdE1lc3NhZ2UoKSB7XG4gICAgICAgIC8vIFRoZSB0ZXN0IGFnYWluc3QgYGltcG9ydFNjcmlwdHNgIHByZXZlbnRzIHRoaXMgaW1wbGVtZW50YXRpb24gZnJvbSBiZWluZyBpbnN0YWxsZWQgaW5zaWRlIGEgd2ViIHdvcmtlcixcbiAgICAgICAgLy8gd2hlcmUgYGdsb2JhbC5wb3N0TWVzc2FnZWAgbWVhbnMgc29tZXRoaW5nIGNvbXBsZXRlbHkgZGlmZmVyZW50IGFuZCBjYW4ndCBiZSB1c2VkIGZvciB0aGlzIHB1cnBvc2UuXG4gICAgICAgIGlmIChnbG9iYWwucG9zdE1lc3NhZ2UgJiYgIWdsb2JhbC5pbXBvcnRTY3JpcHRzKSB7XG4gICAgICAgICAgICB2YXIgcG9zdE1lc3NhZ2VJc0FzeW5jaHJvbm91cyA9IHRydWU7XG4gICAgICAgICAgICB2YXIgb2xkT25NZXNzYWdlID0gZ2xvYmFsLm9ubWVzc2FnZTtcbiAgICAgICAgICAgIGdsb2JhbC5vbm1lc3NhZ2UgPSBmdW5jdGlvbigpIHtcbiAgICAgICAgICAgICAgICBwb3N0TWVzc2FnZUlzQXN5bmNocm9ub3VzID0gZmFsc2U7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgZ2xvYmFsLnBvc3RNZXNzYWdlKFwiXCIsIFwiKlwiKTtcbiAgICAgICAgICAgIGdsb2JhbC5vbm1lc3NhZ2UgPSBvbGRPbk1lc3NhZ2U7XG4gICAgICAgICAgICByZXR1cm4gcG9zdE1lc3NhZ2VJc0FzeW5jaHJvbm91cztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxQb3N0TWVzc2FnZUltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICAvLyBJbnN0YWxscyBhbiBldmVudCBoYW5kbGVyIG9uIGBnbG9iYWxgIGZvciB0aGUgYG1lc3NhZ2VgIGV2ZW50OiBzZWVcbiAgICAgICAgLy8gKiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi9ET00vd2luZG93LnBvc3RNZXNzYWdlXG4gICAgICAgIC8vICogaHR0cDovL3d3dy53aGF0d2cub3JnL3NwZWNzL3dlYi1hcHBzL2N1cnJlbnQtd29yay9tdWx0aXBhZ2UvY29tbXMuaHRtbCNjcm9zc0RvY3VtZW50TWVzc2FnZXNcblxuICAgICAgICB2YXIgbWVzc2FnZVByZWZpeCA9IFwic2V0SW1tZWRpYXRlJFwiICsgTWF0aC5yYW5kb20oKSArIFwiJFwiO1xuICAgICAgICB2YXIgb25HbG9iYWxNZXNzYWdlID0gZnVuY3Rpb24oZXZlbnQpIHtcbiAgICAgICAgICAgIGlmIChldmVudC5zb3VyY2UgPT09IGdsb2JhbCAmJlxuICAgICAgICAgICAgICAgIHR5cGVvZiBldmVudC5kYXRhID09PSBcInN0cmluZ1wiICYmXG4gICAgICAgICAgICAgICAgZXZlbnQuZGF0YS5pbmRleE9mKG1lc3NhZ2VQcmVmaXgpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcnVuSWZQcmVzZW50KCtldmVudC5kYXRhLnNsaWNlKG1lc3NhZ2VQcmVmaXgubGVuZ3RoKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG5cbiAgICAgICAgaWYgKGdsb2JhbC5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgICAgICAgICBnbG9iYWwuYWRkRXZlbnRMaXN0ZW5lcihcIm1lc3NhZ2VcIiwgb25HbG9iYWxNZXNzYWdlLCBmYWxzZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnbG9iYWwuYXR0YWNoRXZlbnQoXCJvbm1lc3NhZ2VcIiwgb25HbG9iYWxNZXNzYWdlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlZ2lzdGVySW1tZWRpYXRlID0gZnVuY3Rpb24oaGFuZGxlKSB7XG4gICAgICAgICAgICBnbG9iYWwucG9zdE1lc3NhZ2UobWVzc2FnZVByZWZpeCArIGhhbmRsZSwgXCIqXCIpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxNZXNzYWdlQ2hhbm5lbEltcGxlbWVudGF0aW9uKCkge1xuICAgICAgICB2YXIgY2hhbm5lbCA9IG5ldyBNZXNzYWdlQ2hhbm5lbCgpO1xuICAgICAgICBjaGFubmVsLnBvcnQxLm9ubWVzc2FnZSA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICB2YXIgaGFuZGxlID0gZXZlbnQuZGF0YTtcbiAgICAgICAgICAgIHJ1bklmUHJlc2VudChoYW5kbGUpO1xuICAgICAgICB9O1xuXG4gICAgICAgIHJlZ2lzdGVySW1tZWRpYXRlID0gZnVuY3Rpb24oaGFuZGxlKSB7XG4gICAgICAgICAgICBjaGFubmVsLnBvcnQyLnBvc3RNZXNzYWdlKGhhbmRsZSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbFJlYWR5U3RhdGVDaGFuZ2VJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgdmFyIGh0bWwgPSBkb2MuZG9jdW1lbnRFbGVtZW50O1xuICAgICAgICByZWdpc3RlckltbWVkaWF0ZSA9IGZ1bmN0aW9uKGhhbmRsZSkge1xuICAgICAgICAgICAgLy8gQ3JlYXRlIGEgPHNjcmlwdD4gZWxlbWVudDsgaXRzIHJlYWR5c3RhdGVjaGFuZ2UgZXZlbnQgd2lsbCBiZSBmaXJlZCBhc3luY2hyb25vdXNseSBvbmNlIGl0IGlzIGluc2VydGVkXG4gICAgICAgICAgICAvLyBpbnRvIHRoZSBkb2N1bWVudC4gRG8gc28sIHRodXMgcXVldWluZyB1cCB0aGUgdGFzay4gUmVtZW1iZXIgdG8gY2xlYW4gdXAgb25jZSBpdCdzIGJlZW4gY2FsbGVkLlxuICAgICAgICAgICAgdmFyIHNjcmlwdCA9IGRvYy5jcmVhdGVFbGVtZW50KFwic2NyaXB0XCIpO1xuICAgICAgICAgICAgc2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBydW5JZlByZXNlbnQoaGFuZGxlKTtcbiAgICAgICAgICAgICAgICBzY3JpcHQub25yZWFkeXN0YXRlY2hhbmdlID0gbnVsbDtcbiAgICAgICAgICAgICAgICBodG1sLnJlbW92ZUNoaWxkKHNjcmlwdCk7XG4gICAgICAgICAgICAgICAgc2NyaXB0ID0gbnVsbDtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBodG1sLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbFNldFRpbWVvdXRJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgcmVnaXN0ZXJJbW1lZGlhdGUgPSBmdW5jdGlvbihoYW5kbGUpIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQocnVuSWZQcmVzZW50LCAwLCBoYW5kbGUpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8vIElmIHN1cHBvcnRlZCwgd2Ugc2hvdWxkIGF0dGFjaCB0byB0aGUgcHJvdG90eXBlIG9mIGdsb2JhbCwgc2luY2UgdGhhdCBpcyB3aGVyZSBzZXRUaW1lb3V0IGV0IGFsLiBsaXZlLlxuICAgIHZhciBhdHRhY2hUbyA9IE9iamVjdC5nZXRQcm90b3R5cGVPZiAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoZ2xvYmFsKTtcbiAgICBhdHRhY2hUbyA9IGF0dGFjaFRvICYmIGF0dGFjaFRvLnNldFRpbWVvdXQgPyBhdHRhY2hUbyA6IGdsb2JhbDtcblxuICAgIC8vIERvbid0IGdldCBmb29sZWQgYnkgZS5nLiBicm93c2VyaWZ5IGVudmlyb25tZW50cy5cbiAgICBpZiAoe30udG9TdHJpbmcuY2FsbChnbG9iYWwucHJvY2VzcykgPT09IFwiW29iamVjdCBwcm9jZXNzXVwiKSB7XG4gICAgICAgIC8vIEZvciBOb2RlLmpzIGJlZm9yZSAwLjlcbiAgICAgICAgaW5zdGFsbE5leHRUaWNrSW1wbGVtZW50YXRpb24oKTtcblxuICAgIH0gZWxzZSBpZiAoY2FuVXNlUG9zdE1lc3NhZ2UoKSkge1xuICAgICAgICAvLyBGb3Igbm9uLUlFMTAgbW9kZXJuIGJyb3dzZXJzXG4gICAgICAgIGluc3RhbGxQb3N0TWVzc2FnZUltcGxlbWVudGF0aW9uKCk7XG5cbiAgICB9IGVsc2UgaWYgKGdsb2JhbC5NZXNzYWdlQ2hhbm5lbCkge1xuICAgICAgICAvLyBGb3Igd2ViIHdvcmtlcnMsIHdoZXJlIHN1cHBvcnRlZFxuICAgICAgICBpbnN0YWxsTWVzc2FnZUNoYW5uZWxJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIGlmIChkb2MgJiYgXCJvbnJlYWR5c3RhdGVjaGFuZ2VcIiBpbiBkb2MuY3JlYXRlRWxlbWVudChcInNjcmlwdFwiKSkge1xuICAgICAgICAvLyBGb3IgSUUgNuKAkzhcbiAgICAgICAgaW5zdGFsbFJlYWR5U3RhdGVDaGFuZ2VJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRm9yIG9sZGVyIGJyb3dzZXJzXG4gICAgICAgIGluc3RhbGxTZXRUaW1lb3V0SW1wbGVtZW50YXRpb24oKTtcbiAgICB9XG5cbiAgICBhdHRhY2hUby5zZXRJbW1lZGlhdGUgPSBzZXRJbW1lZGlhdGU7XG4gICAgYXR0YWNoVG8uY2xlYXJJbW1lZGlhdGUgPSBjbGVhckltbWVkaWF0ZTtcbn0odHlwZW9mIHNlbGYgPT09IFwidW5kZWZpbmVkXCIgPyB0eXBlb2YgZ2xvYmFsID09PSBcInVuZGVmaW5lZFwiID8gdGhpcyA6IGdsb2JhbCA6IHNlbGYpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL3NldGltbWVkaWF0ZS9zZXRJbW1lZGlhdGUuanNcbi8vIG1vZHVsZSBpZCA9IDEyOVxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvLyBzaGltIGZvciB1c2luZyBwcm9jZXNzIGluIGJyb3dzZXJcbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuLy8gY2FjaGVkIGZyb20gd2hhdGV2ZXIgZ2xvYmFsIGlzIHByZXNlbnQgc28gdGhhdCB0ZXN0IHJ1bm5lcnMgdGhhdCBzdHViIGl0XG4vLyBkb24ndCBicmVhayB0aGluZ3MuICBCdXQgd2UgbmVlZCB0byB3cmFwIGl0IGluIGEgdHJ5IGNhdGNoIGluIGNhc2UgaXQgaXNcbi8vIHdyYXBwZWQgaW4gc3RyaWN0IG1vZGUgY29kZSB3aGljaCBkb2Vzbid0IGRlZmluZSBhbnkgZ2xvYmFscy4gIEl0J3MgaW5zaWRlIGFcbi8vIGZ1bmN0aW9uIGJlY2F1c2UgdHJ5L2NhdGNoZXMgZGVvcHRpbWl6ZSBpbiBjZXJ0YWluIGVuZ2luZXMuXG5cbnZhciBjYWNoZWRTZXRUaW1lb3V0O1xudmFyIGNhY2hlZENsZWFyVGltZW91dDtcblxuZnVuY3Rpb24gZGVmYXVsdFNldFRpbW91dCgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ3NldFRpbWVvdXQgaGFzIG5vdCBiZWVuIGRlZmluZWQnKTtcbn1cbmZ1bmN0aW9uIGRlZmF1bHRDbGVhclRpbWVvdXQgKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignY2xlYXJUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG4oZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2Ygc2V0VGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gZGVmYXVsdFNldFRpbW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIGlmICh0eXBlb2YgY2xlYXJUaW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgICAgICB9XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBkZWZhdWx0Q2xlYXJUaW1lb3V0O1xuICAgIH1cbn0gKCkpXG5mdW5jdGlvbiBydW5UaW1lb3V0KGZ1bikge1xuICAgIGlmIChjYWNoZWRTZXRUaW1lb3V0ID09PSBzZXRUaW1lb3V0KSB7XG4gICAgICAgIC8vbm9ybWFsIGVudmlyb21lbnRzIGluIHNhbmUgc2l0dWF0aW9uc1xuICAgICAgICByZXR1cm4gc2V0VGltZW91dChmdW4sIDApO1xuICAgIH1cbiAgICAvLyBpZiBzZXRUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkU2V0VGltZW91dCA9PT0gZGVmYXVsdFNldFRpbW91dCB8fCAhY2FjaGVkU2V0VGltZW91dCkgJiYgc2V0VGltZW91dCkge1xuICAgICAgICBjYWNoZWRTZXRUaW1lb3V0ID0gc2V0VGltZW91dDtcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dChmdW4sIDApO1xuICAgIH0gY2F0Y2goZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRTZXRUaW1lb3V0LmNhbGwobnVsbCwgZnVuLCAwKTtcbiAgICAgICAgfSBjYXRjaChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yXG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKHRoaXMsIGZ1biwgMCk7XG4gICAgICAgIH1cbiAgICB9XG5cblxufVxuZnVuY3Rpb24gcnVuQ2xlYXJUaW1lb3V0KG1hcmtlcikge1xuICAgIGlmIChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGNsZWFyVGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICAvLyBpZiBjbGVhclRpbWVvdXQgd2Fzbid0IGF2YWlsYWJsZSBidXQgd2FzIGxhdHRlciBkZWZpbmVkXG4gICAgaWYgKChjYWNoZWRDbGVhclRpbWVvdXQgPT09IGRlZmF1bHRDbGVhclRpbWVvdXQgfHwgIWNhY2hlZENsZWFyVGltZW91dCkgJiYgY2xlYXJUaW1lb3V0KSB7XG4gICAgICAgIGNhY2hlZENsZWFyVGltZW91dCA9IGNsZWFyVGltZW91dDtcbiAgICAgICAgcmV0dXJuIGNsZWFyVGltZW91dChtYXJrZXIpO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICAvLyB3aGVuIHdoZW4gc29tZWJvZHkgaGFzIHNjcmV3ZWQgd2l0aCBzZXRUaW1lb3V0IGJ1dCBubyBJLkUuIG1hZGRuZXNzXG4gICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFdoZW4gd2UgYXJlIGluIEkuRS4gYnV0IHRoZSBzY3JpcHQgaGFzIGJlZW4gZXZhbGVkIHNvIEkuRS4gZG9lc24ndCAgdHJ1c3QgdGhlIGdsb2JhbCBvYmplY3Qgd2hlbiBjYWxsZWQgbm9ybWFsbHlcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbChudWxsLCBtYXJrZXIpO1xuICAgICAgICB9IGNhdGNoIChlKXtcbiAgICAgICAgICAgIC8vIHNhbWUgYXMgYWJvdmUgYnV0IHdoZW4gaXQncyBhIHZlcnNpb24gb2YgSS5FLiB0aGF0IG11c3QgaGF2ZSB0aGUgZ2xvYmFsIG9iamVjdCBmb3IgJ3RoaXMnLCBob3BmdWxseSBvdXIgY29udGV4dCBjb3JyZWN0IG90aGVyd2lzZSBpdCB3aWxsIHRocm93IGEgZ2xvYmFsIGVycm9yLlxuICAgICAgICAgICAgLy8gU29tZSB2ZXJzaW9ucyBvZiBJLkUuIGhhdmUgZGlmZmVyZW50IHJ1bGVzIGZvciBjbGVhclRpbWVvdXQgdnMgc2V0VGltZW91dFxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZENsZWFyVGltZW91dC5jYWxsKHRoaXMsIG1hcmtlcik7XG4gICAgICAgIH1cbiAgICB9XG5cblxuXG59XG52YXIgcXVldWUgPSBbXTtcbnZhciBkcmFpbmluZyA9IGZhbHNlO1xudmFyIGN1cnJlbnRRdWV1ZTtcbnZhciBxdWV1ZUluZGV4ID0gLTE7XG5cbmZ1bmN0aW9uIGNsZWFuVXBOZXh0VGljaygpIHtcbiAgICBpZiAoIWRyYWluaW5nIHx8ICFjdXJyZW50UXVldWUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIGlmIChjdXJyZW50UXVldWUubGVuZ3RoKSB7XG4gICAgICAgIHF1ZXVlID0gY3VycmVudFF1ZXVlLmNvbmNhdChxdWV1ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgIH1cbiAgICBpZiAocXVldWUubGVuZ3RoKSB7XG4gICAgICAgIGRyYWluUXVldWUoKTtcbiAgICB9XG59XG5cbmZ1bmN0aW9uIGRyYWluUXVldWUoKSB7XG4gICAgaWYgKGRyYWluaW5nKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgdmFyIHRpbWVvdXQgPSBydW5UaW1lb3V0KGNsZWFuVXBOZXh0VGljayk7XG4gICAgZHJhaW5pbmcgPSB0cnVlO1xuXG4gICAgdmFyIGxlbiA9IHF1ZXVlLmxlbmd0aDtcbiAgICB3aGlsZShsZW4pIHtcbiAgICAgICAgY3VycmVudFF1ZXVlID0gcXVldWU7XG4gICAgICAgIHF1ZXVlID0gW107XG4gICAgICAgIHdoaWxlICgrK3F1ZXVlSW5kZXggPCBsZW4pIHtcbiAgICAgICAgICAgIGlmIChjdXJyZW50UXVldWUpIHtcbiAgICAgICAgICAgICAgICBjdXJyZW50UXVldWVbcXVldWVJbmRleF0ucnVuKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcXVldWVJbmRleCA9IC0xO1xuICAgICAgICBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgfVxuICAgIGN1cnJlbnRRdWV1ZSA9IG51bGw7XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBydW5DbGVhclRpbWVvdXQodGltZW91dCk7XG59XG5cbnByb2Nlc3MubmV4dFRpY2sgPSBmdW5jdGlvbiAoZnVuKSB7XG4gICAgdmFyIGFyZ3MgPSBuZXcgQXJyYXkoYXJndW1lbnRzLmxlbmd0aCAtIDEpO1xuICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID4gMSkge1xuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgYXJnc1tpIC0gMV0gPSBhcmd1bWVudHNbaV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcXVldWUucHVzaChuZXcgSXRlbShmdW4sIGFyZ3MpKTtcbiAgICBpZiAocXVldWUubGVuZ3RoID09PSAxICYmICFkcmFpbmluZykge1xuICAgICAgICBydW5UaW1lb3V0KGRyYWluUXVldWUpO1xuICAgIH1cbn07XG5cbi8vIHY4IGxpa2VzIHByZWRpY3RpYmxlIG9iamVjdHNcbmZ1bmN0aW9uIEl0ZW0oZnVuLCBhcnJheSkge1xuICAgIHRoaXMuZnVuID0gZnVuO1xuICAgIHRoaXMuYXJyYXkgPSBhcnJheTtcbn1cbkl0ZW0ucHJvdG90eXBlLnJ1biA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmZ1bi5hcHBseShudWxsLCB0aGlzLmFycmF5KTtcbn07XG5wcm9jZXNzLnRpdGxlID0gJ2Jyb3dzZXInO1xucHJvY2Vzcy5icm93c2VyID0gdHJ1ZTtcbnByb2Nlc3MuZW52ID0ge307XG5wcm9jZXNzLmFyZ3YgPSBbXTtcbnByb2Nlc3MudmVyc2lvbiA9ICcnOyAvLyBlbXB0eSBzdHJpbmcgdG8gYXZvaWQgcmVnZXhwIGlzc3Vlc1xucHJvY2Vzcy52ZXJzaW9ucyA9IHt9O1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnByZXBlbmRPbmNlTGlzdGVuZXIgPSBub29wO1xuXG5wcm9jZXNzLmxpc3RlbmVycyA9IGZ1bmN0aW9uIChuYW1lKSB7IHJldHVybiBbXSB9XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufTtcblxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5wcm9jZXNzLnVtYXNrID0gZnVuY3Rpb24oKSB7IHJldHVybiAwOyB9O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvcHJvY2Vzcy9icm93c2VyLmpzXG4vLyBtb2R1bGUgaWQgPSAxMzBcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyohIERhdGFUYWJsZXMgQm9vdHN0cmFwIDMgaW50ZWdyYXRpb25cbiAqIMKpMjAxMS0yMDE1IFNwcnlNZWRpYSBMdGQgLSBkYXRhdGFibGVzLm5ldC9saWNlbnNlXG4gKi9cblxuLyoqXG4gKiBEYXRhVGFibGVzIGludGVncmF0aW9uIGZvciBCb290c3RyYXAgMy4gVGhpcyByZXF1aXJlcyBCb290c3RyYXAgMyBhbmRcbiAqIERhdGFUYWJsZXMgMS4xMCBvciBuZXdlci5cbiAqXG4gKiBUaGlzIGZpbGUgc2V0cyB0aGUgZGVmYXVsdHMgYW5kIGFkZHMgb3B0aW9ucyB0byBEYXRhVGFibGVzIHRvIHN0eWxlIGl0c1xuICogY29udHJvbHMgdXNpbmcgQm9vdHN0cmFwLiBTZWUgaHR0cDovL2RhdGF0YWJsZXMubmV0L21hbnVhbC9zdHlsaW5nL2Jvb3RzdHJhcFxuICogZm9yIGZ1cnRoZXIgaW5mb3JtYXRpb24uXG4gKi9cbihmdW5jdGlvbiggZmFjdG9yeSApe1xuXHRpZiAoIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoIFsnanF1ZXJ5JywgJ2RhdGF0YWJsZXMubmV0J10sIGZ1bmN0aW9uICggJCApIHtcblx0XHRcdHJldHVybiBmYWN0b3J5KCAkLCB3aW5kb3csIGRvY3VtZW50ICk7XG5cdFx0fSApO1xuXHR9XG5cdGVsc2UgaWYgKCB0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcgKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChyb290LCAkKSB7XG5cdFx0XHRpZiAoICEgcm9vdCApIHtcblx0XHRcdFx0cm9vdCA9IHdpbmRvdztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCAhICQgfHwgISAkLmZuLmRhdGFUYWJsZSApIHtcblx0XHRcdFx0Ly8gUmVxdWlyZSBEYXRhVGFibGVzLCB3aGljaCBhdHRhY2hlcyB0byBqUXVlcnksIGluY2x1ZGluZ1xuXHRcdFx0XHQvLyBqUXVlcnkgaWYgbmVlZGVkIGFuZCBoYXZlIGEgJCBwcm9wZXJ0eSBzbyB3ZSBjYW4gYWNjZXNzIHRoZVxuXHRcdFx0XHQvLyBqUXVlcnkgb2JqZWN0IHRoYXQgaXMgdXNlZFxuXHRcdFx0XHQkID0gcmVxdWlyZSgnZGF0YXRhYmxlcy5uZXQnKShyb290LCAkKS4kO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gZmFjdG9yeSggJCwgcm9vdCwgcm9vdC5kb2N1bWVudCApO1xuXHRcdH07XG5cdH1cblx0ZWxzZSB7XG5cdFx0Ly8gQnJvd3NlclxuXHRcdGZhY3RvcnkoIGpRdWVyeSwgd2luZG93LCBkb2N1bWVudCApO1xuXHR9XG59KGZ1bmN0aW9uKCAkLCB3aW5kb3csIGRvY3VtZW50LCB1bmRlZmluZWQgKSB7XG4ndXNlIHN0cmljdCc7XG52YXIgRGF0YVRhYmxlID0gJC5mbi5kYXRhVGFibGU7XG5cblxuLyogU2V0IHRoZSBkZWZhdWx0cyBmb3IgRGF0YVRhYmxlcyBpbml0aWFsaXNhdGlvbiAqL1xuJC5leHRlbmQoIHRydWUsIERhdGFUYWJsZS5kZWZhdWx0cywge1xuXHRkb206XG5cdFx0XCI8J3Jvdyc8J2NvbC1zbS0xMiBjb2wtbWQtNidsPjwnY29sLXNtLTEyIGNvbC1tZC02J2Y+PlwiICtcblx0XHRcIjwncm93JzwnY29sLXNtLTEyJ3RyPj5cIiArXG5cdFx0XCI8J3Jvdyc8J2NvbC1zbS0xMiBjb2wtbWQtNSdpPjwnY29sLXNtLTEyIGNvbC1tZC03J3A+PlwiLFxuXHRyZW5kZXJlcjogJ2Jvb3RzdHJhcCdcbn0gKTtcblxuXG4vKiBEZWZhdWx0IGNsYXNzIG1vZGlmaWNhdGlvbiAqL1xuJC5leHRlbmQoIERhdGFUYWJsZS5leHQuY2xhc3Nlcywge1xuXHRzV3JhcHBlcjogICAgICBcImRhdGFUYWJsZXNfd3JhcHBlciBjb250YWluZXItZmx1aWQgZHQtYm9vdHN0cmFwNFwiLFxuXHRzRmlsdGVySW5wdXQ6ICBcImZvcm0tY29udHJvbCBmb3JtLWNvbnRyb2wtc21cIixcblx0c0xlbmd0aFNlbGVjdDogXCJmb3JtLWNvbnRyb2wgZm9ybS1jb250cm9sLXNtXCIsXG5cdHNQcm9jZXNzaW5nOiAgIFwiZGF0YVRhYmxlc19wcm9jZXNzaW5nIGNhcmRcIixcblx0c1BhZ2VCdXR0b246ICAgXCJwYWdpbmF0ZV9idXR0b24gcGFnZS1pdGVtXCJcbn0gKTtcblxuXG4vKiBCb290c3RyYXAgcGFnaW5nIGJ1dHRvbiByZW5kZXJlciAqL1xuRGF0YVRhYmxlLmV4dC5yZW5kZXJlci5wYWdlQnV0dG9uLmJvb3RzdHJhcCA9IGZ1bmN0aW9uICggc2V0dGluZ3MsIGhvc3QsIGlkeCwgYnV0dG9ucywgcGFnZSwgcGFnZXMgKSB7XG5cdHZhciBhcGkgICAgID0gbmV3IERhdGFUYWJsZS5BcGkoIHNldHRpbmdzICk7XG5cdHZhciBjbGFzc2VzID0gc2V0dGluZ3Mub0NsYXNzZXM7XG5cdHZhciBsYW5nICAgID0gc2V0dGluZ3Mub0xhbmd1YWdlLm9QYWdpbmF0ZTtcblx0dmFyIGFyaWEgPSBzZXR0aW5ncy5vTGFuZ3VhZ2Uub0FyaWEucGFnaW5hdGUgfHwge307XG5cdHZhciBidG5EaXNwbGF5LCBidG5DbGFzcywgY291bnRlcj0wO1xuXG5cdHZhciBhdHRhY2ggPSBmdW5jdGlvbiggY29udGFpbmVyLCBidXR0b25zICkge1xuXHRcdHZhciBpLCBpZW4sIG5vZGUsIGJ1dHRvbjtcblx0XHR2YXIgY2xpY2tIYW5kbGVyID0gZnVuY3Rpb24gKCBlICkge1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0aWYgKCAhJChlLmN1cnJlbnRUYXJnZXQpLmhhc0NsYXNzKCdkaXNhYmxlZCcpICYmIGFwaS5wYWdlKCkgIT0gZS5kYXRhLmFjdGlvbiApIHtcblx0XHRcdFx0YXBpLnBhZ2UoIGUuZGF0YS5hY3Rpb24gKS5kcmF3KCAncGFnZScgKTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0Zm9yICggaT0wLCBpZW49YnV0dG9ucy5sZW5ndGggOyBpPGllbiA7IGkrKyApIHtcblx0XHRcdGJ1dHRvbiA9IGJ1dHRvbnNbaV07XG5cblx0XHRcdGlmICggJC5pc0FycmF5KCBidXR0b24gKSApIHtcblx0XHRcdFx0YXR0YWNoKCBjb250YWluZXIsIGJ1dHRvbiApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGJ0bkRpc3BsYXkgPSAnJztcblx0XHRcdFx0YnRuQ2xhc3MgPSAnJztcblxuXHRcdFx0XHRzd2l0Y2ggKCBidXR0b24gKSB7XG5cdFx0XHRcdFx0Y2FzZSAnZWxsaXBzaXMnOlxuXHRcdFx0XHRcdFx0YnRuRGlzcGxheSA9ICcmI3gyMDI2Oyc7XG5cdFx0XHRcdFx0XHRidG5DbGFzcyA9ICdkaXNhYmxlZCc7XG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdGNhc2UgJ2ZpcnN0Jzpcblx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBsYW5nLnNGaXJzdDtcblx0XHRcdFx0XHRcdGJ0bkNsYXNzID0gYnV0dG9uICsgKHBhZ2UgPiAwID9cblx0XHRcdFx0XHRcdFx0JycgOiAnIGRpc2FibGVkJyk7XG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdGNhc2UgJ3ByZXZpb3VzJzpcblx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBsYW5nLnNQcmV2aW91cztcblx0XHRcdFx0XHRcdGJ0bkNsYXNzID0gYnV0dG9uICsgKHBhZ2UgPiAwID9cblx0XHRcdFx0XHRcdFx0JycgOiAnIGRpc2FibGVkJyk7XG5cdFx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRcdGNhc2UgJ25leHQnOlxuXHRcdFx0XHRcdFx0YnRuRGlzcGxheSA9IGxhbmcuc05leHQ7XG5cdFx0XHRcdFx0XHRidG5DbGFzcyA9IGJ1dHRvbiArIChwYWdlIDwgcGFnZXMtMSA/XG5cdFx0XHRcdFx0XHRcdCcnIDogJyBkaXNhYmxlZCcpO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0XHRjYXNlICdsYXN0Jzpcblx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBsYW5nLnNMYXN0O1xuXHRcdFx0XHRcdFx0YnRuQ2xhc3MgPSBidXR0b24gKyAocGFnZSA8IHBhZ2VzLTEgP1xuXHRcdFx0XHRcdFx0XHQnJyA6ICcgZGlzYWJsZWQnKTtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRcdGJ0bkRpc3BsYXkgPSBidXR0b24gKyAxO1xuXHRcdFx0XHRcdFx0YnRuQ2xhc3MgPSBwYWdlID09PSBidXR0b24gP1xuXHRcdFx0XHRcdFx0XHQnYWN0aXZlJyA6ICcnO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIGJ0bkRpc3BsYXkgKSB7XG5cdFx0XHRcdFx0bm9kZSA9ICQoJzxsaT4nLCB7XG5cdFx0XHRcdFx0XHRcdCdjbGFzcyc6IGNsYXNzZXMuc1BhZ2VCdXR0b24rJyAnK2J0bkNsYXNzLFxuXHRcdFx0XHRcdFx0XHQnaWQnOiBpZHggPT09IDAgJiYgdHlwZW9mIGJ1dHRvbiA9PT0gJ3N0cmluZycgP1xuXHRcdFx0XHRcdFx0XHRcdHNldHRpbmdzLnNUYWJsZUlkICsnXycrIGJ1dHRvbiA6XG5cdFx0XHRcdFx0XHRcdFx0bnVsbFxuXHRcdFx0XHRcdFx0fSApXG5cdFx0XHRcdFx0XHQuYXBwZW5kKCAkKCc8YT4nLCB7XG5cdFx0XHRcdFx0XHRcdFx0J2hyZWYnOiAnIycsXG5cdFx0XHRcdFx0XHRcdFx0J2FyaWEtY29udHJvbHMnOiBzZXR0aW5ncy5zVGFibGVJZCxcblx0XHRcdFx0XHRcdFx0XHQnYXJpYS1sYWJlbCc6IGFyaWFbIGJ1dHRvbiBdLFxuXHRcdFx0XHRcdFx0XHRcdCdkYXRhLWR0LWlkeCc6IGNvdW50ZXIsXG5cdFx0XHRcdFx0XHRcdFx0J3RhYmluZGV4Jzogc2V0dGluZ3MuaVRhYkluZGV4LFxuXHRcdFx0XHRcdFx0XHRcdCdjbGFzcyc6ICdwYWdlLWxpbmsnXG5cdFx0XHRcdFx0XHRcdH0gKVxuXHRcdFx0XHRcdFx0XHQuaHRtbCggYnRuRGlzcGxheSApXG5cdFx0XHRcdFx0XHQpXG5cdFx0XHRcdFx0XHQuYXBwZW5kVG8oIGNvbnRhaW5lciApO1xuXG5cdFx0XHRcdFx0c2V0dGluZ3Mub0FwaS5fZm5CaW5kQWN0aW9uKFxuXHRcdFx0XHRcdFx0bm9kZSwge2FjdGlvbjogYnV0dG9ufSwgY2xpY2tIYW5kbGVyXG5cdFx0XHRcdFx0KTtcblxuXHRcdFx0XHRcdGNvdW50ZXIrKztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0fTtcblxuXHQvLyBJRTkgdGhyb3dzIGFuICd1bmtub3duIGVycm9yJyBpZiBkb2N1bWVudC5hY3RpdmVFbGVtZW50IGlzIHVzZWRcblx0Ly8gaW5zaWRlIGFuIGlmcmFtZSBvciBmcmFtZS4gXG5cdHZhciBhY3RpdmVFbDtcblxuXHR0cnkge1xuXHRcdC8vIEJlY2F1c2UgdGhpcyBhcHByb2FjaCBpcyBkZXN0cm95aW5nIGFuZCByZWNyZWF0aW5nIHRoZSBwYWdpbmdcblx0XHQvLyBlbGVtZW50cywgZm9jdXMgaXMgbG9zdCBvbiB0aGUgc2VsZWN0IGJ1dHRvbiB3aGljaCBpcyBiYWQgZm9yXG5cdFx0Ly8gYWNjZXNzaWJpbGl0eS4gU28gd2Ugd2FudCB0byByZXN0b3JlIGZvY3VzIG9uY2UgdGhlIGRyYXcgaGFzXG5cdFx0Ly8gY29tcGxldGVkXG5cdFx0YWN0aXZlRWwgPSAkKGhvc3QpLmZpbmQoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkuZGF0YSgnZHQtaWR4Jyk7XG5cdH1cblx0Y2F0Y2ggKGUpIHt9XG5cblx0YXR0YWNoKFxuXHRcdCQoaG9zdCkuZW1wdHkoKS5odG1sKCc8dWwgY2xhc3M9XCJwYWdpbmF0aW9uXCIvPicpLmNoaWxkcmVuKCd1bCcpLFxuXHRcdGJ1dHRvbnNcblx0KTtcblxuXHRpZiAoIGFjdGl2ZUVsICE9PSB1bmRlZmluZWQgKSB7XG5cdFx0JChob3N0KS5maW5kKCAnW2RhdGEtZHQtaWR4PScrYWN0aXZlRWwrJ10nICkuZm9jdXMoKTtcblx0fVxufTtcblxuXG5yZXR1cm4gRGF0YVRhYmxlO1xufSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvZGF0YXRhYmxlcy5uZXQtYnM0L2pzL2RhdGFUYWJsZXMuYm9vdHN0cmFwNC5qc1xuLy8gbW9kdWxlIGlkID0gMTMxXG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qKiFcbiAqIFNvcnRhYmxlXG4gKiBAYXV0aG9yXHRSdWJhWGEgICA8dHJhc2hAcnViYXhhLm9yZz5cbiAqIEBsaWNlbnNlIE1JVFxuICovXG5cbihmdW5jdGlvbiBzb3J0YWJsZU1vZHVsZShmYWN0b3J5KSB7XG5cdFwidXNlIHN0cmljdFwiO1xuXG5cdGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuXHRcdGRlZmluZShmYWN0b3J5KTtcblx0fVxuXHRlbHNlIGlmICh0eXBlb2YgbW9kdWxlICE9IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIG1vZHVsZS5leHBvcnRzICE9IFwidW5kZWZpbmVkXCIpIHtcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGZhY3RvcnkoKTtcblx0fVxuXHRlbHNlIHtcblx0XHQvKiBqc2hpbnQgc3ViOnRydWUgKi9cblx0XHR3aW5kb3dbXCJTb3J0YWJsZVwiXSA9IGZhY3RvcnkoKTtcblx0fVxufSkoZnVuY3Rpb24gc29ydGFibGVGYWN0b3J5KCkge1xuXHRcInVzZSBzdHJpY3RcIjtcblxuXHRpZiAodHlwZW9mIHdpbmRvdyA9PT0gXCJ1bmRlZmluZWRcIiB8fCAhd2luZG93LmRvY3VtZW50KSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uIHNvcnRhYmxlRXJyb3IoKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJTb3J0YWJsZS5qcyByZXF1aXJlcyBhIHdpbmRvdyB3aXRoIGEgZG9jdW1lbnRcIik7XG5cdFx0fTtcblx0fVxuXG5cdHZhciBkcmFnRWwsXG5cdFx0cGFyZW50RWwsXG5cdFx0Z2hvc3RFbCxcblx0XHRjbG9uZUVsLFxuXHRcdHJvb3RFbCxcblx0XHRuZXh0RWwsXG5cdFx0bGFzdERvd25FbCxcblxuXHRcdHNjcm9sbEVsLFxuXHRcdHNjcm9sbFBhcmVudEVsLFxuXHRcdHNjcm9sbEN1c3RvbUZuLFxuXG5cdFx0bGFzdEVsLFxuXHRcdGxhc3RDU1MsXG5cdFx0bGFzdFBhcmVudENTUyxcblxuXHRcdG9sZEluZGV4LFxuXHRcdG5ld0luZGV4LFxuXG5cdFx0YWN0aXZlR3JvdXAsXG5cdFx0cHV0U29ydGFibGUsXG5cblx0XHRhdXRvU2Nyb2xsID0ge30sXG5cblx0XHR0YXBFdnQsXG5cdFx0dG91Y2hFdnQsXG5cblx0XHRtb3ZlZCxcblxuXHRcdC8qKiBAY29uc3QgKi9cblx0XHRSX1NQQUNFID0gL1xccysvZyxcblx0XHRSX0ZMT0FUID0gL2xlZnR8cmlnaHR8aW5saW5lLyxcblxuXHRcdGV4cGFuZG8gPSAnU29ydGFibGUnICsgKG5ldyBEYXRlKS5nZXRUaW1lKCksXG5cblx0XHR3aW4gPSB3aW5kb3csXG5cdFx0ZG9jdW1lbnQgPSB3aW4uZG9jdW1lbnQsXG5cdFx0cGFyc2VJbnQgPSB3aW4ucGFyc2VJbnQsXG5cdFx0c2V0VGltZW91dCA9IHdpbi5zZXRUaW1lb3V0LFxuXG5cdFx0JCA9IHdpbi5qUXVlcnkgfHwgd2luLlplcHRvLFxuXHRcdFBvbHltZXIgPSB3aW4uUG9seW1lcixcblxuXHRcdGNhcHR1cmVNb2RlID0gZmFsc2UsXG5cdFx0cGFzc2l2ZU1vZGUgPSBmYWxzZSxcblxuXHRcdHN1cHBvcnREcmFnZ2FibGUgPSAoJ2RyYWdnYWJsZScgaW4gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2JykpLFxuXHRcdHN1cHBvcnRDc3NQb2ludGVyRXZlbnRzID0gKGZ1bmN0aW9uIChlbCkge1xuXHRcdFx0Ly8gZmFsc2Ugd2hlbiBJRTExXG5cdFx0XHRpZiAoISFuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKC8oPzpUcmlkZW50LipydlsgOl0/MTFcXC58bXNpZSkvaSkpIHtcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdFx0fVxuXHRcdFx0ZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd4Jyk7XG5cdFx0XHRlbC5zdHlsZS5jc3NUZXh0ID0gJ3BvaW50ZXItZXZlbnRzOmF1dG8nO1xuXHRcdFx0cmV0dXJuIGVsLnN0eWxlLnBvaW50ZXJFdmVudHMgPT09ICdhdXRvJztcblx0XHR9KSgpLFxuXG5cdFx0X3NpbGVudCA9IGZhbHNlLFxuXG5cdFx0YWJzID0gTWF0aC5hYnMsXG5cdFx0bWluID0gTWF0aC5taW4sXG5cblx0XHRzYXZlZElucHV0Q2hlY2tlZCA9IFtdLFxuXHRcdHRvdWNoRHJhZ092ZXJMaXN0ZW5lcnMgPSBbXSxcblxuXHRcdF9hdXRvU2Nyb2xsID0gX3Rocm90dGxlKGZ1bmN0aW9uICgvKipFdmVudCovZXZ0LCAvKipPYmplY3QqL29wdGlvbnMsIC8qKkhUTUxFbGVtZW50Ki9yb290RWwpIHtcblx0XHRcdC8vIEJ1ZzogaHR0cHM6Ly9idWd6aWxsYS5tb3ppbGxhLm9yZy9zaG93X2J1Zy5jZ2k/aWQ9NTA1NTIxXG5cdFx0XHRpZiAocm9vdEVsICYmIG9wdGlvbnMuc2Nyb2xsKSB7XG5cdFx0XHRcdHZhciBfdGhpcyA9IHJvb3RFbFtleHBhbmRvXSxcblx0XHRcdFx0XHRlbCxcblx0XHRcdFx0XHRyZWN0LFxuXHRcdFx0XHRcdHNlbnMgPSBvcHRpb25zLnNjcm9sbFNlbnNpdGl2aXR5LFxuXHRcdFx0XHRcdHNwZWVkID0gb3B0aW9ucy5zY3JvbGxTcGVlZCxcblxuXHRcdFx0XHRcdHggPSBldnQuY2xpZW50WCxcblx0XHRcdFx0XHR5ID0gZXZ0LmNsaWVudFksXG5cblx0XHRcdFx0XHR3aW5XaWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoLFxuXHRcdFx0XHRcdHdpbkhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodCxcblxuXHRcdFx0XHRcdHZ4LFxuXHRcdFx0XHRcdHZ5LFxuXG5cdFx0XHRcdFx0c2Nyb2xsT2Zmc2V0WCxcblx0XHRcdFx0XHRzY3JvbGxPZmZzZXRZXG5cdFx0XHRcdDtcblxuXHRcdFx0XHQvLyBEZWxlY3Qgc2Nyb2xsRWxcblx0XHRcdFx0aWYgKHNjcm9sbFBhcmVudEVsICE9PSByb290RWwpIHtcblx0XHRcdFx0XHRzY3JvbGxFbCA9IG9wdGlvbnMuc2Nyb2xsO1xuXHRcdFx0XHRcdHNjcm9sbFBhcmVudEVsID0gcm9vdEVsO1xuXHRcdFx0XHRcdHNjcm9sbEN1c3RvbUZuID0gb3B0aW9ucy5zY3JvbGxGbjtcblxuXHRcdFx0XHRcdGlmIChzY3JvbGxFbCA9PT0gdHJ1ZSkge1xuXHRcdFx0XHRcdFx0c2Nyb2xsRWwgPSByb290RWw7XG5cblx0XHRcdFx0XHRcdGRvIHtcblx0XHRcdFx0XHRcdFx0aWYgKChzY3JvbGxFbC5vZmZzZXRXaWR0aCA8IHNjcm9sbEVsLnNjcm9sbFdpZHRoKSB8fFxuXHRcdFx0XHRcdFx0XHRcdChzY3JvbGxFbC5vZmZzZXRIZWlnaHQgPCBzY3JvbGxFbC5zY3JvbGxIZWlnaHQpXG5cdFx0XHRcdFx0XHRcdCkge1xuXHRcdFx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdC8qIGpzaGludCBib3NzOnRydWUgKi9cblx0XHRcdFx0XHRcdH0gd2hpbGUgKHNjcm9sbEVsID0gc2Nyb2xsRWwucGFyZW50Tm9kZSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHNjcm9sbEVsKSB7XG5cdFx0XHRcdFx0ZWwgPSBzY3JvbGxFbDtcblx0XHRcdFx0XHRyZWN0ID0gc2Nyb2xsRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdFx0XHRcdFx0dnggPSAoYWJzKHJlY3QucmlnaHQgLSB4KSA8PSBzZW5zKSAtIChhYnMocmVjdC5sZWZ0IC0geCkgPD0gc2Vucyk7XG5cdFx0XHRcdFx0dnkgPSAoYWJzKHJlY3QuYm90dG9tIC0geSkgPD0gc2VucykgLSAoYWJzKHJlY3QudG9wIC0geSkgPD0gc2Vucyk7XG5cdFx0XHRcdH1cblxuXG5cdFx0XHRcdGlmICghKHZ4IHx8IHZ5KSkge1xuXHRcdFx0XHRcdHZ4ID0gKHdpbldpZHRoIC0geCA8PSBzZW5zKSAtICh4IDw9IHNlbnMpO1xuXHRcdFx0XHRcdHZ5ID0gKHdpbkhlaWdodCAtIHkgPD0gc2VucykgLSAoeSA8PSBzZW5zKTtcblxuXHRcdFx0XHRcdC8qIGpzaGludCBleHByOnRydWUgKi9cblx0XHRcdFx0XHQodnggfHwgdnkpICYmIChlbCA9IHdpbik7XG5cdFx0XHRcdH1cblxuXG5cdFx0XHRcdGlmIChhdXRvU2Nyb2xsLnZ4ICE9PSB2eCB8fCBhdXRvU2Nyb2xsLnZ5ICE9PSB2eSB8fCBhdXRvU2Nyb2xsLmVsICE9PSBlbCkge1xuXHRcdFx0XHRcdGF1dG9TY3JvbGwuZWwgPSBlbDtcblx0XHRcdFx0XHRhdXRvU2Nyb2xsLnZ4ID0gdng7XG5cdFx0XHRcdFx0YXV0b1Njcm9sbC52eSA9IHZ5O1xuXG5cdFx0XHRcdFx0Y2xlYXJJbnRlcnZhbChhdXRvU2Nyb2xsLnBpZCk7XG5cblx0XHRcdFx0XHRpZiAoZWwpIHtcblx0XHRcdFx0XHRcdGF1dG9TY3JvbGwucGlkID0gc2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0XHRzY3JvbGxPZmZzZXRZID0gdnkgPyB2eSAqIHNwZWVkIDogMDtcblx0XHRcdFx0XHRcdFx0c2Nyb2xsT2Zmc2V0WCA9IHZ4ID8gdnggKiBzcGVlZCA6IDA7XG5cblx0XHRcdFx0XHRcdFx0aWYgKCdmdW5jdGlvbicgPT09IHR5cGVvZihzY3JvbGxDdXN0b21GbikpIHtcblx0XHRcdFx0XHRcdFx0XHRyZXR1cm4gc2Nyb2xsQ3VzdG9tRm4uY2FsbChfdGhpcywgc2Nyb2xsT2Zmc2V0WCwgc2Nyb2xsT2Zmc2V0WSwgZXZ0KTtcblx0XHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHRcdGlmIChlbCA9PT0gd2luKSB7XG5cdFx0XHRcdFx0XHRcdFx0d2luLnNjcm9sbFRvKHdpbi5wYWdlWE9mZnNldCArIHNjcm9sbE9mZnNldFgsIHdpbi5wYWdlWU9mZnNldCArIHNjcm9sbE9mZnNldFkpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdGVsLnNjcm9sbFRvcCArPSBzY3JvbGxPZmZzZXRZO1xuXHRcdFx0XHRcdFx0XHRcdGVsLnNjcm9sbExlZnQgKz0gc2Nyb2xsT2Zmc2V0WDtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fSwgMjQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sIDMwKSxcblxuXHRcdF9wcmVwYXJlR3JvdXAgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuXHRcdFx0ZnVuY3Rpb24gdG9Gbih2YWx1ZSwgcHVsbCkge1xuXHRcdFx0XHRpZiAodmFsdWUgPT09IHZvaWQgMCB8fCB2YWx1ZSA9PT0gdHJ1ZSkge1xuXHRcdFx0XHRcdHZhbHVlID0gZ3JvdXAubmFtZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0XHRyZXR1cm4gdmFsdWU7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uICh0bywgZnJvbSkge1xuXHRcdFx0XHRcdFx0dmFyIGZyb21Hcm91cCA9IGZyb20ub3B0aW9ucy5ncm91cC5uYW1lO1xuXG5cdFx0XHRcdFx0XHRyZXR1cm4gcHVsbFxuXHRcdFx0XHRcdFx0XHQ/IHZhbHVlXG5cdFx0XHRcdFx0XHRcdDogdmFsdWUgJiYgKHZhbHVlLmpvaW5cblx0XHRcdFx0XHRcdFx0XHQ/IHZhbHVlLmluZGV4T2YoZnJvbUdyb3VwKSA+IC0xXG5cdFx0XHRcdFx0XHRcdFx0OiAoZnJvbUdyb3VwID09IHZhbHVlKVxuXHRcdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0dmFyIGdyb3VwID0ge307XG5cdFx0XHR2YXIgb3JpZ2luYWxHcm91cCA9IG9wdGlvbnMuZ3JvdXA7XG5cblx0XHRcdGlmICghb3JpZ2luYWxHcm91cCB8fCB0eXBlb2Ygb3JpZ2luYWxHcm91cCAhPSAnb2JqZWN0Jykge1xuXHRcdFx0XHRvcmlnaW5hbEdyb3VwID0ge25hbWU6IG9yaWdpbmFsR3JvdXB9O1xuXHRcdFx0fVxuXG5cdFx0XHRncm91cC5uYW1lID0gb3JpZ2luYWxHcm91cC5uYW1lO1xuXHRcdFx0Z3JvdXAuY2hlY2tQdWxsID0gdG9GbihvcmlnaW5hbEdyb3VwLnB1bGwsIHRydWUpO1xuXHRcdFx0Z3JvdXAuY2hlY2tQdXQgPSB0b0ZuKG9yaWdpbmFsR3JvdXAucHV0KTtcblx0XHRcdGdyb3VwLnJldmVydENsb25lID0gb3JpZ2luYWxHcm91cC5yZXZlcnRDbG9uZTtcblxuXHRcdFx0b3B0aW9ucy5ncm91cCA9IGdyb3VwO1xuXHRcdH1cblx0O1xuXG5cdC8vIERldGVjdCBzdXBwb3J0IGEgcGFzc2l2ZSBtb2RlXG5cdHRyeSB7XG5cdFx0d2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3Rlc3QnLCBudWxsLCBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdwYXNzaXZlJywge1xuXHRcdFx0Z2V0OiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdC8vIGBmYWxzZWAsIGJlY2F1c2UgZXZlcnl0aGluZyBzdGFydHMgdG8gd29yayBpbmNvcnJlY3RseSBhbmQgaW5zdGVhZCBvZiBkJ24nZCxcblx0XHRcdFx0Ly8gYmVnaW5zIHRoZSBwYWdlIGhhcyBzY3JvbGxlZC5cblx0XHRcdFx0cGFzc2l2ZU1vZGUgPSBmYWxzZTtcblx0XHRcdFx0Y2FwdHVyZU1vZGUgPSB7XG5cdFx0XHRcdFx0Y2FwdHVyZTogZmFsc2UsXG5cdFx0XHRcdFx0cGFzc2l2ZTogcGFzc2l2ZU1vZGVcblx0XHRcdFx0fTtcblx0XHRcdH1cblx0XHR9KSk7XG5cdH0gY2F0Y2ggKGVycikge31cblxuXHQvKipcblx0ICogQGNsYXNzICBTb3J0YWJsZVxuXHQgKiBAcGFyYW0gIHtIVE1MRWxlbWVudH0gIGVsXG5cdCAqIEBwYXJhbSAge09iamVjdH0gICAgICAgW29wdGlvbnNdXG5cdCAqL1xuXHRmdW5jdGlvbiBTb3J0YWJsZShlbCwgb3B0aW9ucykge1xuXHRcdGlmICghKGVsICYmIGVsLm5vZGVUeXBlICYmIGVsLm5vZGVUeXBlID09PSAxKSkge1xuXHRcdFx0dGhyb3cgJ1NvcnRhYmxlOiBgZWxgIG11c3QgYmUgSFRNTEVsZW1lbnQsIGFuZCBub3QgJyArIHt9LnRvU3RyaW5nLmNhbGwoZWwpO1xuXHRcdH1cblxuXHRcdHRoaXMuZWwgPSBlbDsgLy8gcm9vdCBlbGVtZW50XG5cdFx0dGhpcy5vcHRpb25zID0gb3B0aW9ucyA9IF9leHRlbmQoe30sIG9wdGlvbnMpO1xuXG5cblx0XHQvLyBFeHBvcnQgaW5zdGFuY2Vcblx0XHRlbFtleHBhbmRvXSA9IHRoaXM7XG5cblx0XHQvLyBEZWZhdWx0IG9wdGlvbnNcblx0XHR2YXIgZGVmYXVsdHMgPSB7XG5cdFx0XHRncm91cDogTWF0aC5yYW5kb20oKSxcblx0XHRcdHNvcnQ6IHRydWUsXG5cdFx0XHRkaXNhYmxlZDogZmFsc2UsXG5cdFx0XHRzdG9yZTogbnVsbCxcblx0XHRcdGhhbmRsZTogbnVsbCxcblx0XHRcdHNjcm9sbDogdHJ1ZSxcblx0XHRcdHNjcm9sbFNlbnNpdGl2aXR5OiAzMCxcblx0XHRcdHNjcm9sbFNwZWVkOiAxMCxcblx0XHRcdGRyYWdnYWJsZTogL1t1b11sL2kudGVzdChlbC5ub2RlTmFtZSkgPyAnbGknIDogJz4qJyxcblx0XHRcdGdob3N0Q2xhc3M6ICdzb3J0YWJsZS1naG9zdCcsXG5cdFx0XHRjaG9zZW5DbGFzczogJ3NvcnRhYmxlLWNob3NlbicsXG5cdFx0XHRkcmFnQ2xhc3M6ICdzb3J0YWJsZS1kcmFnJyxcblx0XHRcdGlnbm9yZTogJ2EsIGltZycsXG5cdFx0XHRmaWx0ZXI6IG51bGwsXG5cdFx0XHRwcmV2ZW50T25GaWx0ZXI6IHRydWUsXG5cdFx0XHRhbmltYXRpb246IDAsXG5cdFx0XHRzZXREYXRhOiBmdW5jdGlvbiAoZGF0YVRyYW5zZmVyLCBkcmFnRWwpIHtcblx0XHRcdFx0ZGF0YVRyYW5zZmVyLnNldERhdGEoJ1RleHQnLCBkcmFnRWwudGV4dENvbnRlbnQpO1xuXHRcdFx0fSxcblx0XHRcdGRyb3BCdWJibGU6IGZhbHNlLFxuXHRcdFx0ZHJhZ292ZXJCdWJibGU6IGZhbHNlLFxuXHRcdFx0ZGF0YUlkQXR0cjogJ2RhdGEtaWQnLFxuXHRcdFx0ZGVsYXk6IDAsXG5cdFx0XHRmb3JjZUZhbGxiYWNrOiBmYWxzZSxcblx0XHRcdGZhbGxiYWNrQ2xhc3M6ICdzb3J0YWJsZS1mYWxsYmFjaycsXG5cdFx0XHRmYWxsYmFja09uQm9keTogZmFsc2UsXG5cdFx0XHRmYWxsYmFja1RvbGVyYW5jZTogMCxcblx0XHRcdGZhbGxiYWNrT2Zmc2V0OiB7eDogMCwgeTogMH0sXG5cdFx0XHRzdXBwb3J0UG9pbnRlcjogU29ydGFibGUuc3VwcG9ydFBvaW50ZXIgIT09IGZhbHNlXG5cdFx0fTtcblxuXG5cdFx0Ly8gU2V0IGRlZmF1bHQgb3B0aW9uc1xuXHRcdGZvciAodmFyIG5hbWUgaW4gZGVmYXVsdHMpIHtcblx0XHRcdCEobmFtZSBpbiBvcHRpb25zKSAmJiAob3B0aW9uc1tuYW1lXSA9IGRlZmF1bHRzW25hbWVdKTtcblx0XHR9XG5cblx0XHRfcHJlcGFyZUdyb3VwKG9wdGlvbnMpO1xuXG5cdFx0Ly8gQmluZCBhbGwgcHJpdmF0ZSBtZXRob2RzXG5cdFx0Zm9yICh2YXIgZm4gaW4gdGhpcykge1xuXHRcdFx0aWYgKGZuLmNoYXJBdCgwKSA9PT0gJ18nICYmIHR5cGVvZiB0aGlzW2ZuXSA9PT0gJ2Z1bmN0aW9uJykge1xuXHRcdFx0XHR0aGlzW2ZuXSA9IHRoaXNbZm5dLmJpbmQodGhpcyk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0Ly8gU2V0dXAgZHJhZyBtb2RlXG5cdFx0dGhpcy5uYXRpdmVEcmFnZ2FibGUgPSBvcHRpb25zLmZvcmNlRmFsbGJhY2sgPyBmYWxzZSA6IHN1cHBvcnREcmFnZ2FibGU7XG5cblx0XHQvLyBCaW5kIGV2ZW50c1xuXHRcdF9vbihlbCwgJ21vdXNlZG93bicsIHRoaXMuX29uVGFwU3RhcnQpO1xuXHRcdF9vbihlbCwgJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblRhcFN0YXJ0KTtcblx0XHRvcHRpb25zLnN1cHBvcnRQb2ludGVyICYmIF9vbihlbCwgJ3BvaW50ZXJkb3duJywgdGhpcy5fb25UYXBTdGFydCk7XG5cblx0XHRpZiAodGhpcy5uYXRpdmVEcmFnZ2FibGUpIHtcblx0XHRcdF9vbihlbCwgJ2RyYWdvdmVyJywgdGhpcyk7XG5cdFx0XHRfb24oZWwsICdkcmFnZW50ZXInLCB0aGlzKTtcblx0XHR9XG5cblx0XHR0b3VjaERyYWdPdmVyTGlzdGVuZXJzLnB1c2godGhpcy5fb25EcmFnT3Zlcik7XG5cblx0XHQvLyBSZXN0b3JlIHNvcnRpbmdcblx0XHRvcHRpb25zLnN0b3JlICYmIHRoaXMuc29ydChvcHRpb25zLnN0b3JlLmdldCh0aGlzKSk7XG5cdH1cblxuXG5cdFNvcnRhYmxlLnByb3RvdHlwZSA9IC8qKiBAbGVuZHMgU29ydGFibGUucHJvdG90eXBlICovIHtcblx0XHRjb25zdHJ1Y3RvcjogU29ydGFibGUsXG5cblx0XHRfb25UYXBTdGFydDogZnVuY3Rpb24gKC8qKiBFdmVudHxUb3VjaEV2ZW50ICovZXZ0KSB7XG5cdFx0XHR2YXIgX3RoaXMgPSB0aGlzLFxuXHRcdFx0XHRlbCA9IHRoaXMuZWwsXG5cdFx0XHRcdG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG5cdFx0XHRcdHByZXZlbnRPbkZpbHRlciA9IG9wdGlvbnMucHJldmVudE9uRmlsdGVyLFxuXHRcdFx0XHR0eXBlID0gZXZ0LnR5cGUsXG5cdFx0XHRcdHRvdWNoID0gZXZ0LnRvdWNoZXMgJiYgZXZ0LnRvdWNoZXNbMF0sXG5cdFx0XHRcdHRhcmdldCA9ICh0b3VjaCB8fCBldnQpLnRhcmdldCxcblx0XHRcdFx0b3JpZ2luYWxUYXJnZXQgPSBldnQudGFyZ2V0LnNoYWRvd1Jvb3QgJiYgKGV2dC5wYXRoICYmIGV2dC5wYXRoWzBdKSB8fCB0YXJnZXQsXG5cdFx0XHRcdGZpbHRlciA9IG9wdGlvbnMuZmlsdGVyLFxuXHRcdFx0XHRzdGFydEluZGV4O1xuXG5cdFx0XHRfc2F2ZUlucHV0Q2hlY2tlZFN0YXRlKGVsKTtcblxuXG5cdFx0XHQvLyBEb24ndCB0cmlnZ2VyIHN0YXJ0IGV2ZW50IHdoZW4gYW4gZWxlbWVudCBpcyBiZWVuIGRyYWdnZWQsIG90aGVyd2lzZSB0aGUgZXZ0Lm9sZGluZGV4IGFsd2F5cyB3cm9uZyB3aGVuIHNldCBvcHRpb24uZ3JvdXAuXG5cdFx0XHRpZiAoZHJhZ0VsKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKC9tb3VzZWRvd258cG9pbnRlcmRvd24vLnRlc3QodHlwZSkgJiYgZXZ0LmJ1dHRvbiAhPT0gMCB8fCBvcHRpb25zLmRpc2FibGVkKSB7XG5cdFx0XHRcdHJldHVybjsgLy8gb25seSBsZWZ0IGJ1dHRvbiBvciBlbmFibGVkXG5cdFx0XHR9XG5cblx0XHRcdC8vIGNhbmNlbCBkbmQgaWYgb3JpZ2luYWwgdGFyZ2V0IGlzIGNvbnRlbnQgZWRpdGFibGVcblx0XHRcdGlmIChvcmlnaW5hbFRhcmdldC5pc0NvbnRlbnRFZGl0YWJsZSkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdHRhcmdldCA9IF9jbG9zZXN0KHRhcmdldCwgb3B0aW9ucy5kcmFnZ2FibGUsIGVsKTtcblxuXHRcdFx0aWYgKCF0YXJnZXQpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAobGFzdERvd25FbCA9PT0gdGFyZ2V0KSB7XG5cdFx0XHRcdC8vIElnbm9yaW5nIGR1cGxpY2F0ZSBgZG93bmBcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBHZXQgdGhlIGluZGV4IG9mIHRoZSBkcmFnZ2VkIGVsZW1lbnQgd2l0aGluIGl0cyBwYXJlbnRcblx0XHRcdHN0YXJ0SW5kZXggPSBfaW5kZXgodGFyZ2V0LCBvcHRpb25zLmRyYWdnYWJsZSk7XG5cblx0XHRcdC8vIENoZWNrIGZpbHRlclxuXHRcdFx0aWYgKHR5cGVvZiBmaWx0ZXIgPT09ICdmdW5jdGlvbicpIHtcblx0XHRcdFx0aWYgKGZpbHRlci5jYWxsKHRoaXMsIGV2dCwgdGFyZ2V0LCB0aGlzKSkge1xuXHRcdFx0XHRcdF9kaXNwYXRjaEV2ZW50KF90aGlzLCBvcmlnaW5hbFRhcmdldCwgJ2ZpbHRlcicsIHRhcmdldCwgZWwsIGVsLCBzdGFydEluZGV4KTtcblx0XHRcdFx0XHRwcmV2ZW50T25GaWx0ZXIgJiYgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0cmV0dXJuOyAvLyBjYW5jZWwgZG5kXG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdGVsc2UgaWYgKGZpbHRlcikge1xuXHRcdFx0XHRmaWx0ZXIgPSBmaWx0ZXIuc3BsaXQoJywnKS5zb21lKGZ1bmN0aW9uIChjcml0ZXJpYSkge1xuXHRcdFx0XHRcdGNyaXRlcmlhID0gX2Nsb3Nlc3Qob3JpZ2luYWxUYXJnZXQsIGNyaXRlcmlhLnRyaW0oKSwgZWwpO1xuXG5cdFx0XHRcdFx0aWYgKGNyaXRlcmlhKSB7XG5cdFx0XHRcdFx0XHRfZGlzcGF0Y2hFdmVudChfdGhpcywgY3JpdGVyaWEsICdmaWx0ZXInLCB0YXJnZXQsIGVsLCBlbCwgc3RhcnRJbmRleCk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdGlmIChmaWx0ZXIpIHtcblx0XHRcdFx0XHRwcmV2ZW50T25GaWx0ZXIgJiYgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0cmV0dXJuOyAvLyBjYW5jZWwgZG5kXG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKG9wdGlvbnMuaGFuZGxlICYmICFfY2xvc2VzdChvcmlnaW5hbFRhcmdldCwgb3B0aW9ucy5oYW5kbGUsIGVsKSkge1xuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdC8vIFByZXBhcmUgYGRyYWdzdGFydGBcblx0XHRcdHRoaXMuX3ByZXBhcmVEcmFnU3RhcnQoZXZ0LCB0b3VjaCwgdGFyZ2V0LCBzdGFydEluZGV4KTtcblx0XHR9LFxuXG5cdFx0X3ByZXBhcmVEcmFnU3RhcnQ6IGZ1bmN0aW9uICgvKiogRXZlbnQgKi9ldnQsIC8qKiBUb3VjaCAqL3RvdWNoLCAvKiogSFRNTEVsZW1lbnQgKi90YXJnZXQsIC8qKiBOdW1iZXIgKi9zdGFydEluZGV4KSB7XG5cdFx0XHR2YXIgX3RoaXMgPSB0aGlzLFxuXHRcdFx0XHRlbCA9IF90aGlzLmVsLFxuXHRcdFx0XHRvcHRpb25zID0gX3RoaXMub3B0aW9ucyxcblx0XHRcdFx0b3duZXJEb2N1bWVudCA9IGVsLm93bmVyRG9jdW1lbnQsXG5cdFx0XHRcdGRyYWdTdGFydEZuO1xuXG5cdFx0XHRpZiAodGFyZ2V0ICYmICFkcmFnRWwgJiYgKHRhcmdldC5wYXJlbnROb2RlID09PSBlbCkpIHtcblx0XHRcdFx0dGFwRXZ0ID0gZXZ0O1xuXG5cdFx0XHRcdHJvb3RFbCA9IGVsO1xuXHRcdFx0XHRkcmFnRWwgPSB0YXJnZXQ7XG5cdFx0XHRcdHBhcmVudEVsID0gZHJhZ0VsLnBhcmVudE5vZGU7XG5cdFx0XHRcdG5leHRFbCA9IGRyYWdFbC5uZXh0U2libGluZztcblx0XHRcdFx0bGFzdERvd25FbCA9IHRhcmdldDtcblx0XHRcdFx0YWN0aXZlR3JvdXAgPSBvcHRpb25zLmdyb3VwO1xuXHRcdFx0XHRvbGRJbmRleCA9IHN0YXJ0SW5kZXg7XG5cblx0XHRcdFx0dGhpcy5fbGFzdFggPSAodG91Y2ggfHwgZXZ0KS5jbGllbnRYO1xuXHRcdFx0XHR0aGlzLl9sYXN0WSA9ICh0b3VjaCB8fCBldnQpLmNsaWVudFk7XG5cblx0XHRcdFx0ZHJhZ0VsLnN0eWxlWyd3aWxsLWNoYW5nZSddID0gJ2FsbCc7XG5cblx0XHRcdFx0ZHJhZ1N0YXJ0Rm4gPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0Ly8gRGVsYXllZCBkcmFnIGhhcyBiZWVuIHRyaWdnZXJlZFxuXHRcdFx0XHRcdC8vIHdlIGNhbiByZS1lbmFibGUgdGhlIGV2ZW50czogdG91Y2htb3ZlL21vdXNlbW92ZVxuXHRcdFx0XHRcdF90aGlzLl9kaXNhYmxlRGVsYXllZERyYWcoKTtcblxuXHRcdFx0XHRcdC8vIE1ha2UgdGhlIGVsZW1lbnQgZHJhZ2dhYmxlXG5cdFx0XHRcdFx0ZHJhZ0VsLmRyYWdnYWJsZSA9IF90aGlzLm5hdGl2ZURyYWdnYWJsZTtcblxuXHRcdFx0XHRcdC8vIENob3NlbiBpdGVtXG5cdFx0XHRcdFx0X3RvZ2dsZUNsYXNzKGRyYWdFbCwgb3B0aW9ucy5jaG9zZW5DbGFzcywgdHJ1ZSk7XG5cblx0XHRcdFx0XHQvLyBCaW5kIHRoZSBldmVudHM6IGRyYWdzdGFydC9kcmFnZW5kXG5cdFx0XHRcdFx0X3RoaXMuX3RyaWdnZXJEcmFnU3RhcnQoZXZ0LCB0b3VjaCk7XG5cblx0XHRcdFx0XHQvLyBEcmFnIHN0YXJ0IGV2ZW50XG5cdFx0XHRcdFx0X2Rpc3BhdGNoRXZlbnQoX3RoaXMsIHJvb3RFbCwgJ2Nob29zZScsIGRyYWdFbCwgcm9vdEVsLCByb290RWwsIG9sZEluZGV4KTtcblx0XHRcdFx0fTtcblxuXHRcdFx0XHQvLyBEaXNhYmxlIFwiZHJhZ2dhYmxlXCJcblx0XHRcdFx0b3B0aW9ucy5pZ25vcmUuc3BsaXQoJywnKS5mb3JFYWNoKGZ1bmN0aW9uIChjcml0ZXJpYSkge1xuXHRcdFx0XHRcdF9maW5kKGRyYWdFbCwgY3JpdGVyaWEudHJpbSgpLCBfZGlzYWJsZURyYWdnYWJsZSk7XG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdF9vbihvd25lckRvY3VtZW50LCAnbW91c2V1cCcsIF90aGlzLl9vbkRyb3ApO1xuXHRcdFx0XHRfb24ob3duZXJEb2N1bWVudCwgJ3RvdWNoZW5kJywgX3RoaXMuX29uRHJvcCk7XG5cdFx0XHRcdF9vbihvd25lckRvY3VtZW50LCAndG91Y2hjYW5jZWwnLCBfdGhpcy5fb25Ecm9wKTtcblx0XHRcdFx0X29uKG93bmVyRG9jdW1lbnQsICdzZWxlY3RzdGFydCcsIF90aGlzKTtcblx0XHRcdFx0b3B0aW9ucy5zdXBwb3J0UG9pbnRlciAmJiBfb24ob3duZXJEb2N1bWVudCwgJ3BvaW50ZXJjYW5jZWwnLCBfdGhpcy5fb25Ecm9wKTtcblxuXHRcdFx0XHRpZiAob3B0aW9ucy5kZWxheSkge1xuXHRcdFx0XHRcdC8vIElmIHRoZSB1c2VyIG1vdmVzIHRoZSBwb2ludGVyIG9yIGxldCBnbyB0aGUgY2xpY2sgb3IgdG91Y2hcblx0XHRcdFx0XHQvLyBiZWZvcmUgdGhlIGRlbGF5IGhhcyBiZWVuIHJlYWNoZWQ6XG5cdFx0XHRcdFx0Ly8gZGlzYWJsZSB0aGUgZGVsYXllZCBkcmFnXG5cdFx0XHRcdFx0X29uKG93bmVyRG9jdW1lbnQsICdtb3VzZXVwJywgX3RoaXMuX2Rpc2FibGVEZWxheWVkRHJhZyk7XG5cdFx0XHRcdFx0X29uKG93bmVyRG9jdW1lbnQsICd0b3VjaGVuZCcsIF90aGlzLl9kaXNhYmxlRGVsYXllZERyYWcpO1xuXHRcdFx0XHRcdF9vbihvd25lckRvY3VtZW50LCAndG91Y2hjYW5jZWwnLCBfdGhpcy5fZGlzYWJsZURlbGF5ZWREcmFnKTtcblx0XHRcdFx0XHRfb24ob3duZXJEb2N1bWVudCwgJ21vdXNlbW92ZScsIF90aGlzLl9kaXNhYmxlRGVsYXllZERyYWcpO1xuXHRcdFx0XHRcdF9vbihvd25lckRvY3VtZW50LCAndG91Y2htb3ZlJywgX3RoaXMuX2Rpc2FibGVEZWxheWVkRHJhZyk7XG5cdFx0XHRcdFx0b3B0aW9ucy5zdXBwb3J0UG9pbnRlciAmJiBfb24ob3duZXJEb2N1bWVudCwgJ3BvaW50ZXJtb3ZlJywgX3RoaXMuX2Rpc2FibGVEZWxheWVkRHJhZyk7XG5cblx0XHRcdFx0XHRfdGhpcy5fZHJhZ1N0YXJ0VGltZXIgPSBzZXRUaW1lb3V0KGRyYWdTdGFydEZuLCBvcHRpb25zLmRlbGF5KTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRkcmFnU3RhcnRGbigpO1xuXHRcdFx0XHR9XG5cblxuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRfZGlzYWJsZURlbGF5ZWREcmFnOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHR2YXIgb3duZXJEb2N1bWVudCA9IHRoaXMuZWwub3duZXJEb2N1bWVudDtcblxuXHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX2RyYWdTdGFydFRpbWVyKTtcblx0XHRcdF9vZmYob3duZXJEb2N1bWVudCwgJ21vdXNldXAnLCB0aGlzLl9kaXNhYmxlRGVsYXllZERyYWcpO1xuXHRcdFx0X29mZihvd25lckRvY3VtZW50LCAndG91Y2hlbmQnLCB0aGlzLl9kaXNhYmxlRGVsYXllZERyYWcpO1xuXHRcdFx0X29mZihvd25lckRvY3VtZW50LCAndG91Y2hjYW5jZWwnLCB0aGlzLl9kaXNhYmxlRGVsYXllZERyYWcpO1xuXHRcdFx0X29mZihvd25lckRvY3VtZW50LCAnbW91c2Vtb3ZlJywgdGhpcy5fZGlzYWJsZURlbGF5ZWREcmFnKTtcblx0XHRcdF9vZmYob3duZXJEb2N1bWVudCwgJ3RvdWNobW92ZScsIHRoaXMuX2Rpc2FibGVEZWxheWVkRHJhZyk7XG5cdFx0XHRfb2ZmKG93bmVyRG9jdW1lbnQsICdwb2ludGVybW92ZScsIHRoaXMuX2Rpc2FibGVEZWxheWVkRHJhZyk7XG5cdFx0fSxcblxuXHRcdF90cmlnZ2VyRHJhZ1N0YXJ0OiBmdW5jdGlvbiAoLyoqIEV2ZW50ICovZXZ0LCAvKiogVG91Y2ggKi90b3VjaCkge1xuXHRcdFx0dG91Y2ggPSB0b3VjaCB8fCAoZXZ0LnBvaW50ZXJUeXBlID09ICd0b3VjaCcgPyBldnQgOiBudWxsKTtcblxuXHRcdFx0aWYgKHRvdWNoKSB7XG5cdFx0XHRcdC8vIFRvdWNoIGRldmljZSBzdXBwb3J0XG5cdFx0XHRcdHRhcEV2dCA9IHtcblx0XHRcdFx0XHR0YXJnZXQ6IGRyYWdFbCxcblx0XHRcdFx0XHRjbGllbnRYOiB0b3VjaC5jbGllbnRYLFxuXHRcdFx0XHRcdGNsaWVudFk6IHRvdWNoLmNsaWVudFlcblx0XHRcdFx0fTtcblxuXHRcdFx0XHR0aGlzLl9vbkRyYWdTdGFydCh0YXBFdnQsICd0b3VjaCcpO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSBpZiAoIXRoaXMubmF0aXZlRHJhZ2dhYmxlKSB7XG5cdFx0XHRcdHRoaXMuX29uRHJhZ1N0YXJ0KHRhcEV2dCwgdHJ1ZSk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0X29uKGRyYWdFbCwgJ2RyYWdlbmQnLCB0aGlzKTtcblx0XHRcdFx0X29uKHJvb3RFbCwgJ2RyYWdzdGFydCcsIHRoaXMuX29uRHJhZ1N0YXJ0KTtcblx0XHRcdH1cblxuXHRcdFx0dHJ5IHtcblx0XHRcdFx0aWYgKGRvY3VtZW50LnNlbGVjdGlvbikge1xuXHRcdFx0XHRcdC8vIFRpbWVvdXQgbmVjY2Vzc2FyeSBmb3IgSUU5XG5cdFx0XHRcdFx0X25leHRUaWNrKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdGRvY3VtZW50LnNlbGVjdGlvbi5lbXB0eSgpO1xuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHdpbmRvdy5nZXRTZWxlY3Rpb24oKS5yZW1vdmVBbGxSYW5nZXMoKTtcblx0XHRcdFx0fVxuXHRcdFx0fSBjYXRjaCAoZXJyKSB7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdF9kcmFnU3RhcnRlZDogZnVuY3Rpb24gKCkge1xuXHRcdFx0aWYgKHJvb3RFbCAmJiBkcmFnRWwpIHtcblx0XHRcdFx0dmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cblx0XHRcdFx0Ly8gQXBwbHkgZWZmZWN0XG5cdFx0XHRcdF90b2dnbGVDbGFzcyhkcmFnRWwsIG9wdGlvbnMuZ2hvc3RDbGFzcywgdHJ1ZSk7XG5cdFx0XHRcdF90b2dnbGVDbGFzcyhkcmFnRWwsIG9wdGlvbnMuZHJhZ0NsYXNzLCBmYWxzZSk7XG5cblx0XHRcdFx0U29ydGFibGUuYWN0aXZlID0gdGhpcztcblxuXHRcdFx0XHQvLyBEcmFnIHN0YXJ0IGV2ZW50XG5cdFx0XHRcdF9kaXNwYXRjaEV2ZW50KHRoaXMsIHJvb3RFbCwgJ3N0YXJ0JywgZHJhZ0VsLCByb290RWwsIHJvb3RFbCwgb2xkSW5kZXgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5fbnVsbGluZygpO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRfZW11bGF0ZURyYWdPdmVyOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRpZiAodG91Y2hFdnQpIHtcblx0XHRcdFx0aWYgKHRoaXMuX2xhc3RYID09PSB0b3VjaEV2dC5jbGllbnRYICYmIHRoaXMuX2xhc3RZID09PSB0b3VjaEV2dC5jbGllbnRZKSB7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dGhpcy5fbGFzdFggPSB0b3VjaEV2dC5jbGllbnRYO1xuXHRcdFx0XHR0aGlzLl9sYXN0WSA9IHRvdWNoRXZ0LmNsaWVudFk7XG5cblx0XHRcdFx0aWYgKCFzdXBwb3J0Q3NzUG9pbnRlckV2ZW50cykge1xuXHRcdFx0XHRcdF9jc3MoZ2hvc3RFbCwgJ2Rpc3BsYXknLCAnbm9uZScpO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0dmFyIHRhcmdldCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQodG91Y2hFdnQuY2xpZW50WCwgdG91Y2hFdnQuY2xpZW50WSk7XG5cdFx0XHRcdHZhciBwYXJlbnQgPSB0YXJnZXQ7XG5cdFx0XHRcdHZhciBpID0gdG91Y2hEcmFnT3Zlckxpc3RlbmVycy5sZW5ndGg7XG5cblx0XHRcdFx0aWYgKHRhcmdldCAmJiB0YXJnZXQuc2hhZG93Um9vdCkge1xuXHRcdFx0XHRcdHRhcmdldCA9IHRhcmdldC5zaGFkb3dSb290LmVsZW1lbnRGcm9tUG9pbnQodG91Y2hFdnQuY2xpZW50WCwgdG91Y2hFdnQuY2xpZW50WSk7XG5cdFx0XHRcdFx0cGFyZW50ID0gdGFyZ2V0O1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHBhcmVudCkge1xuXHRcdFx0XHRcdGRvIHtcblx0XHRcdFx0XHRcdGlmIChwYXJlbnRbZXhwYW5kb10pIHtcblx0XHRcdFx0XHRcdFx0d2hpbGUgKGktLSkge1xuXHRcdFx0XHRcdFx0XHRcdHRvdWNoRHJhZ092ZXJMaXN0ZW5lcnNbaV0oe1xuXHRcdFx0XHRcdFx0XHRcdFx0Y2xpZW50WDogdG91Y2hFdnQuY2xpZW50WCxcblx0XHRcdFx0XHRcdFx0XHRcdGNsaWVudFk6IHRvdWNoRXZ0LmNsaWVudFksXG5cdFx0XHRcdFx0XHRcdFx0XHR0YXJnZXQ6IHRhcmdldCxcblx0XHRcdFx0XHRcdFx0XHRcdHJvb3RFbDogcGFyZW50XG5cdFx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0dGFyZ2V0ID0gcGFyZW50OyAvLyBzdG9yZSBsYXN0IGVsZW1lbnRcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0LyoganNoaW50IGJvc3M6dHJ1ZSAqL1xuXHRcdFx0XHRcdHdoaWxlIChwYXJlbnQgPSBwYXJlbnQucGFyZW50Tm9kZSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoIXN1cHBvcnRDc3NQb2ludGVyRXZlbnRzKSB7XG5cdFx0XHRcdFx0X2NzcyhnaG9zdEVsLCAnZGlzcGxheScsICcnKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH0sXG5cblxuXHRcdF9vblRvdWNoTW92ZTogZnVuY3Rpb24gKC8qKlRvdWNoRXZlbnQqL2V2dCkge1xuXHRcdFx0aWYgKHRhcEV2dCkge1xuXHRcdFx0XHR2YXJcdG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG5cdFx0XHRcdFx0ZmFsbGJhY2tUb2xlcmFuY2UgPSBvcHRpb25zLmZhbGxiYWNrVG9sZXJhbmNlLFxuXHRcdFx0XHRcdGZhbGxiYWNrT2Zmc2V0ID0gb3B0aW9ucy5mYWxsYmFja09mZnNldCxcblx0XHRcdFx0XHR0b3VjaCA9IGV2dC50b3VjaGVzID8gZXZ0LnRvdWNoZXNbMF0gOiBldnQsXG5cdFx0XHRcdFx0ZHggPSAodG91Y2guY2xpZW50WCAtIHRhcEV2dC5jbGllbnRYKSArIGZhbGxiYWNrT2Zmc2V0LngsXG5cdFx0XHRcdFx0ZHkgPSAodG91Y2guY2xpZW50WSAtIHRhcEV2dC5jbGllbnRZKSArIGZhbGxiYWNrT2Zmc2V0LnksXG5cdFx0XHRcdFx0dHJhbnNsYXRlM2QgPSBldnQudG91Y2hlcyA/ICd0cmFuc2xhdGUzZCgnICsgZHggKyAncHgsJyArIGR5ICsgJ3B4LDApJyA6ICd0cmFuc2xhdGUoJyArIGR4ICsgJ3B4LCcgKyBkeSArICdweCknO1xuXG5cdFx0XHRcdC8vIG9ubHkgc2V0IHRoZSBzdGF0dXMgdG8gZHJhZ2dpbmcsIHdoZW4gd2UgYXJlIGFjdHVhbGx5IGRyYWdnaW5nXG5cdFx0XHRcdGlmICghU29ydGFibGUuYWN0aXZlKSB7XG5cdFx0XHRcdFx0aWYgKGZhbGxiYWNrVG9sZXJhbmNlICYmXG5cdFx0XHRcdFx0XHRtaW4oYWJzKHRvdWNoLmNsaWVudFggLSB0aGlzLl9sYXN0WCksIGFicyh0b3VjaC5jbGllbnRZIC0gdGhpcy5fbGFzdFkpKSA8IGZhbGxiYWNrVG9sZXJhbmNlXG5cdFx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0dGhpcy5fZHJhZ1N0YXJ0ZWQoKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIGFzIHdlbGwgYXMgY3JlYXRpbmcgdGhlIGdob3N0IGVsZW1lbnQgb24gdGhlIGRvY3VtZW50IGJvZHlcblx0XHRcdFx0dGhpcy5fYXBwZW5kR2hvc3QoKTtcblxuXHRcdFx0XHRtb3ZlZCA9IHRydWU7XG5cdFx0XHRcdHRvdWNoRXZ0ID0gdG91Y2g7XG5cblx0XHRcdFx0X2NzcyhnaG9zdEVsLCAnd2Via2l0VHJhbnNmb3JtJywgdHJhbnNsYXRlM2QpO1xuXHRcdFx0XHRfY3NzKGdob3N0RWwsICdtb3pUcmFuc2Zvcm0nLCB0cmFuc2xhdGUzZCk7XG5cdFx0XHRcdF9jc3MoZ2hvc3RFbCwgJ21zVHJhbnNmb3JtJywgdHJhbnNsYXRlM2QpO1xuXHRcdFx0XHRfY3NzKGdob3N0RWwsICd0cmFuc2Zvcm0nLCB0cmFuc2xhdGUzZCk7XG5cblx0XHRcdFx0ZXZ0LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR9XG5cdFx0fSxcblxuXHRcdF9hcHBlbmRHaG9zdDogZnVuY3Rpb24gKCkge1xuXHRcdFx0aWYgKCFnaG9zdEVsKSB7XG5cdFx0XHRcdHZhciByZWN0ID0gZHJhZ0VsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLFxuXHRcdFx0XHRcdGNzcyA9IF9jc3MoZHJhZ0VsKSxcblx0XHRcdFx0XHRvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuXHRcdFx0XHRcdGdob3N0UmVjdDtcblxuXHRcdFx0XHRnaG9zdEVsID0gZHJhZ0VsLmNsb25lTm9kZSh0cnVlKTtcblxuXHRcdFx0XHRfdG9nZ2xlQ2xhc3MoZ2hvc3RFbCwgb3B0aW9ucy5naG9zdENsYXNzLCBmYWxzZSk7XG5cdFx0XHRcdF90b2dnbGVDbGFzcyhnaG9zdEVsLCBvcHRpb25zLmZhbGxiYWNrQ2xhc3MsIHRydWUpO1xuXHRcdFx0XHRfdG9nZ2xlQ2xhc3MoZ2hvc3RFbCwgb3B0aW9ucy5kcmFnQ2xhc3MsIHRydWUpO1xuXG5cdFx0XHRcdF9jc3MoZ2hvc3RFbCwgJ3RvcCcsIHJlY3QudG9wIC0gcGFyc2VJbnQoY3NzLm1hcmdpblRvcCwgMTApKTtcblx0XHRcdFx0X2NzcyhnaG9zdEVsLCAnbGVmdCcsIHJlY3QubGVmdCAtIHBhcnNlSW50KGNzcy5tYXJnaW5MZWZ0LCAxMCkpO1xuXHRcdFx0XHRfY3NzKGdob3N0RWwsICd3aWR0aCcsIHJlY3Qud2lkdGgpO1xuXHRcdFx0XHRfY3NzKGdob3N0RWwsICdoZWlnaHQnLCByZWN0LmhlaWdodCk7XG5cdFx0XHRcdF9jc3MoZ2hvc3RFbCwgJ29wYWNpdHknLCAnMC44Jyk7XG5cdFx0XHRcdF9jc3MoZ2hvc3RFbCwgJ3Bvc2l0aW9uJywgJ2ZpeGVkJyk7XG5cdFx0XHRcdF9jc3MoZ2hvc3RFbCwgJ3pJbmRleCcsICcxMDAwMDAnKTtcblx0XHRcdFx0X2NzcyhnaG9zdEVsLCAncG9pbnRlckV2ZW50cycsICdub25lJyk7XG5cblx0XHRcdFx0b3B0aW9ucy5mYWxsYmFja09uQm9keSAmJiBkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKGdob3N0RWwpIHx8IHJvb3RFbC5hcHBlbmRDaGlsZChnaG9zdEVsKTtcblxuXHRcdFx0XHQvLyBGaXhpbmcgZGltZW5zaW9ucy5cblx0XHRcdFx0Z2hvc3RSZWN0ID0gZ2hvc3RFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRcdFx0X2NzcyhnaG9zdEVsLCAnd2lkdGgnLCByZWN0LndpZHRoICogMiAtIGdob3N0UmVjdC53aWR0aCk7XG5cdFx0XHRcdF9jc3MoZ2hvc3RFbCwgJ2hlaWdodCcsIHJlY3QuaGVpZ2h0ICogMiAtIGdob3N0UmVjdC5oZWlnaHQpO1xuXHRcdFx0fVxuXHRcdH0sXG5cblx0XHRfb25EcmFnU3RhcnQ6IGZ1bmN0aW9uICgvKipFdmVudCovZXZ0LCAvKipib29sZWFuKi91c2VGYWxsYmFjaykge1xuXHRcdFx0dmFyIF90aGlzID0gdGhpcztcblx0XHRcdHZhciBkYXRhVHJhbnNmZXIgPSBldnQuZGF0YVRyYW5zZmVyO1xuXHRcdFx0dmFyIG9wdGlvbnMgPSBfdGhpcy5vcHRpb25zO1xuXG5cdFx0XHRfdGhpcy5fb2ZmVXBFdmVudHMoKTtcblxuXHRcdFx0aWYgKGFjdGl2ZUdyb3VwLmNoZWNrUHVsbChfdGhpcywgX3RoaXMsIGRyYWdFbCwgZXZ0KSkge1xuXHRcdFx0XHRjbG9uZUVsID0gX2Nsb25lKGRyYWdFbCk7XG5cblx0XHRcdFx0Y2xvbmVFbC5kcmFnZ2FibGUgPSBmYWxzZTtcblx0XHRcdFx0Y2xvbmVFbC5zdHlsZVsnd2lsbC1jaGFuZ2UnXSA9ICcnO1xuXG5cdFx0XHRcdF9jc3MoY2xvbmVFbCwgJ2Rpc3BsYXknLCAnbm9uZScpO1xuXHRcdFx0XHRfdG9nZ2xlQ2xhc3MoY2xvbmVFbCwgX3RoaXMub3B0aW9ucy5jaG9zZW5DbGFzcywgZmFsc2UpO1xuXG5cdFx0XHRcdC8vICMxMTQzOiBJRnJhbWUgc3VwcG9ydCB3b3JrYXJvdW5kXG5cdFx0XHRcdF90aGlzLl9jbG9uZUlkID0gX25leHRUaWNrKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRyb290RWwuaW5zZXJ0QmVmb3JlKGNsb25lRWwsIGRyYWdFbCk7XG5cdFx0XHRcdFx0X2Rpc3BhdGNoRXZlbnQoX3RoaXMsIHJvb3RFbCwgJ2Nsb25lJywgZHJhZ0VsKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9XG5cblx0XHRcdF90b2dnbGVDbGFzcyhkcmFnRWwsIG9wdGlvbnMuZHJhZ0NsYXNzLCB0cnVlKTtcblxuXHRcdFx0aWYgKHVzZUZhbGxiYWNrKSB7XG5cdFx0XHRcdGlmICh1c2VGYWxsYmFjayA9PT0gJ3RvdWNoJykge1xuXHRcdFx0XHRcdC8vIEJpbmQgdG91Y2ggZXZlbnRzXG5cdFx0XHRcdFx0X29uKGRvY3VtZW50LCAndG91Y2htb3ZlJywgX3RoaXMuX29uVG91Y2hNb3ZlKTtcblx0XHRcdFx0XHRfb24oZG9jdW1lbnQsICd0b3VjaGVuZCcsIF90aGlzLl9vbkRyb3ApO1xuXHRcdFx0XHRcdF9vbihkb2N1bWVudCwgJ3RvdWNoY2FuY2VsJywgX3RoaXMuX29uRHJvcCk7XG5cblx0XHRcdFx0XHRpZiAob3B0aW9ucy5zdXBwb3J0UG9pbnRlcikge1xuXHRcdFx0XHRcdFx0X29uKGRvY3VtZW50LCAncG9pbnRlcm1vdmUnLCBfdGhpcy5fb25Ub3VjaE1vdmUpO1xuXHRcdFx0XHRcdFx0X29uKGRvY3VtZW50LCAncG9pbnRlcnVwJywgX3RoaXMuX29uRHJvcCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdC8vIE9sZCBicndvc2VyXG5cdFx0XHRcdFx0X29uKGRvY3VtZW50LCAnbW91c2Vtb3ZlJywgX3RoaXMuX29uVG91Y2hNb3ZlKTtcblx0XHRcdFx0XHRfb24oZG9jdW1lbnQsICdtb3VzZXVwJywgX3RoaXMuX29uRHJvcCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRfdGhpcy5fbG9vcElkID0gc2V0SW50ZXJ2YWwoX3RoaXMuX2VtdWxhdGVEcmFnT3ZlciwgNTApO1xuXHRcdFx0fVxuXHRcdFx0ZWxzZSB7XG5cdFx0XHRcdGlmIChkYXRhVHJhbnNmZXIpIHtcblx0XHRcdFx0XHRkYXRhVHJhbnNmZXIuZWZmZWN0QWxsb3dlZCA9ICdtb3ZlJztcblx0XHRcdFx0XHRvcHRpb25zLnNldERhdGEgJiYgb3B0aW9ucy5zZXREYXRhLmNhbGwoX3RoaXMsIGRhdGFUcmFuc2ZlciwgZHJhZ0VsKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdF9vbihkb2N1bWVudCwgJ2Ryb3AnLCBfdGhpcyk7XG5cblx0XHRcdFx0Ly8gIzExNDM6INCR0YvQstCw0LXRgiDRjdC70LXQvNC10L3RgiDRgSBJRnJhbWUg0LLQvdGD0YLRgNC4INCx0LvQvtC60LjRgNGD0LXRgiBgZHJvcGAsXG5cdFx0XHRcdC8vINC/0L7RjdGC0L7QvNGDINC10YHQu9C4INCy0YvQt9Cy0LDQu9GB0Y8gYG1vdXNlb3ZlcmAsINC30L3QsNGH0LjRgiDQvdCw0LTQviDQvtGC0LzQtdC90Y/RgtGMINCy0LXRgdGMIGQnbidkLlxuXHRcdFx0XHQvLyBCcmVha2luZyBDaHJvbWUgNjIrXG5cdFx0XHRcdC8vIF9vbihkb2N1bWVudCwgJ21vdXNlb3ZlcicsIF90aGlzKTtcblxuXHRcdFx0XHRfdGhpcy5fZHJhZ1N0YXJ0SWQgPSBfbmV4dFRpY2soX3RoaXMuX2RyYWdTdGFydGVkKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0X29uRHJhZ092ZXI6IGZ1bmN0aW9uICgvKipFdmVudCovZXZ0KSB7XG5cdFx0XHR2YXIgZWwgPSB0aGlzLmVsLFxuXHRcdFx0XHR0YXJnZXQsXG5cdFx0XHRcdGRyYWdSZWN0LFxuXHRcdFx0XHR0YXJnZXRSZWN0LFxuXHRcdFx0XHRyZXZlcnQsXG5cdFx0XHRcdG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG5cdFx0XHRcdGdyb3VwID0gb3B0aW9ucy5ncm91cCxcblx0XHRcdFx0YWN0aXZlU29ydGFibGUgPSBTb3J0YWJsZS5hY3RpdmUsXG5cdFx0XHRcdGlzT3duZXIgPSAoYWN0aXZlR3JvdXAgPT09IGdyb3VwKSxcblx0XHRcdFx0aXNNb3ZpbmdCZXR3ZWVuU29ydGFibGUgPSBmYWxzZSxcblx0XHRcdFx0Y2FuU29ydCA9IG9wdGlvbnMuc29ydDtcblxuXHRcdFx0aWYgKGV2dC5wcmV2ZW50RGVmYXVsdCAhPT0gdm9pZCAwKSB7XG5cdFx0XHRcdGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHQhb3B0aW9ucy5kcmFnb3ZlckJ1YmJsZSAmJiBldnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChkcmFnRWwuYW5pbWF0ZWQpIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRtb3ZlZCA9IHRydWU7XG5cblx0XHRcdGlmIChhY3RpdmVTb3J0YWJsZSAmJiAhb3B0aW9ucy5kaXNhYmxlZCAmJlxuXHRcdFx0XHQoaXNPd25lclxuXHRcdFx0XHRcdD8gY2FuU29ydCB8fCAocmV2ZXJ0ID0gIXJvb3RFbC5jb250YWlucyhkcmFnRWwpKSAvLyBSZXZlcnRpbmcgaXRlbSBpbnRvIHRoZSBvcmlnaW5hbCBsaXN0XG5cdFx0XHRcdFx0OiAoXG5cdFx0XHRcdFx0XHRwdXRTb3J0YWJsZSA9PT0gdGhpcyB8fFxuXHRcdFx0XHRcdFx0KFxuXHRcdFx0XHRcdFx0XHQoYWN0aXZlU29ydGFibGUubGFzdFB1bGxNb2RlID0gYWN0aXZlR3JvdXAuY2hlY2tQdWxsKHRoaXMsIGFjdGl2ZVNvcnRhYmxlLCBkcmFnRWwsIGV2dCkpICYmXG5cdFx0XHRcdFx0XHRcdGdyb3VwLmNoZWNrUHV0KHRoaXMsIGFjdGl2ZVNvcnRhYmxlLCBkcmFnRWwsIGV2dClcblx0XHRcdFx0XHRcdClcblx0XHRcdFx0XHQpXG5cdFx0XHRcdCkgJiZcblx0XHRcdFx0KGV2dC5yb290RWwgPT09IHZvaWQgMCB8fCBldnQucm9vdEVsID09PSB0aGlzLmVsKSAvLyB0b3VjaCBmYWxsYmFja1xuXHRcdFx0KSB7XG5cdFx0XHRcdC8vIFNtYXJ0IGF1dG8tc2Nyb2xsaW5nXG5cdFx0XHRcdF9hdXRvU2Nyb2xsKGV2dCwgb3B0aW9ucywgdGhpcy5lbCk7XG5cblx0XHRcdFx0aWYgKF9zaWxlbnQpIHtcblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXHRcdFx0XHR0YXJnZXQgPSBfY2xvc2VzdChldnQudGFyZ2V0LCBvcHRpb25zLmRyYWdnYWJsZSwgZWwpO1xuXHRcdFx0XHRkcmFnUmVjdCA9IGRyYWdFbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblxuXHRcdFx0XHRpZiAocHV0U29ydGFibGUgIT09IHRoaXMpIHtcblx0XHRcdFx0XHRwdXRTb3J0YWJsZSA9IHRoaXM7XG5cdFx0XHRcdFx0aXNNb3ZpbmdCZXR3ZWVuU29ydGFibGUgPSB0cnVlO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0aWYgKHJldmVydCkge1xuXHRcdFx0XHRcdF9jbG9uZUhpZGUoYWN0aXZlU29ydGFibGUsIHRydWUpO1xuXHRcdFx0XHRcdHBhcmVudEVsID0gcm9vdEVsOyAvLyBhY3R1YWxpemF0aW9uXG5cblx0XHRcdFx0XHRpZiAoY2xvbmVFbCB8fCBuZXh0RWwpIHtcblx0XHRcdFx0XHRcdHJvb3RFbC5pbnNlcnRCZWZvcmUoZHJhZ0VsLCBjbG9uZUVsIHx8IG5leHRFbCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGVsc2UgaWYgKCFjYW5Tb3J0KSB7XG5cdFx0XHRcdFx0XHRyb290RWwuYXBwZW5kQ2hpbGQoZHJhZ0VsKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdH1cblxuXG5cdFx0XHRcdGlmICgoZWwuY2hpbGRyZW4ubGVuZ3RoID09PSAwKSB8fCAoZWwuY2hpbGRyZW5bMF0gPT09IGdob3N0RWwpIHx8XG5cdFx0XHRcdFx0KGVsID09PSBldnQudGFyZ2V0KSAmJiAoX2dob3N0SXNMYXN0KGVsLCBldnQpKVxuXHRcdFx0XHQpIHtcblx0XHRcdFx0XHQvL2Fzc2lnbiB0YXJnZXQgb25seSBpZiBjb25kaXRpb24gaXMgdHJ1ZVxuXHRcdFx0XHRcdGlmIChlbC5jaGlsZHJlbi5sZW5ndGggIT09IDAgJiYgZWwuY2hpbGRyZW5bMF0gIT09IGdob3N0RWwgJiYgZWwgPT09IGV2dC50YXJnZXQpIHtcblx0XHRcdFx0XHRcdHRhcmdldCA9IGVsLmxhc3RFbGVtZW50Q2hpbGQ7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKHRhcmdldCkge1xuXHRcdFx0XHRcdFx0aWYgKHRhcmdldC5hbmltYXRlZCkge1xuXHRcdFx0XHRcdFx0XHRyZXR1cm47XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHRhcmdldFJlY3QgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0X2Nsb25lSGlkZShhY3RpdmVTb3J0YWJsZSwgaXNPd25lcik7XG5cblx0XHRcdFx0XHRpZiAoX29uTW92ZShyb290RWwsIGVsLCBkcmFnRWwsIGRyYWdSZWN0LCB0YXJnZXQsIHRhcmdldFJlY3QsIGV2dCkgIT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0XHRpZiAoIWRyYWdFbC5jb250YWlucyhlbCkpIHtcblx0XHRcdFx0XHRcdFx0ZWwuYXBwZW5kQ2hpbGQoZHJhZ0VsKTtcblx0XHRcdFx0XHRcdFx0cGFyZW50RWwgPSBlbDsgLy8gYWN0dWFsaXphdGlvblxuXHRcdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0XHR0aGlzLl9hbmltYXRlKGRyYWdSZWN0LCBkcmFnRWwpO1xuXHRcdFx0XHRcdFx0dGFyZ2V0ICYmIHRoaXMuX2FuaW1hdGUodGFyZ2V0UmVjdCwgdGFyZ2V0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdFx0ZWxzZSBpZiAodGFyZ2V0ICYmICF0YXJnZXQuYW5pbWF0ZWQgJiYgdGFyZ2V0ICE9PSBkcmFnRWwgJiYgKHRhcmdldC5wYXJlbnROb2RlW2V4cGFuZG9dICE9PSB2b2lkIDApKSB7XG5cdFx0XHRcdFx0aWYgKGxhc3RFbCAhPT0gdGFyZ2V0KSB7XG5cdFx0XHRcdFx0XHRsYXN0RWwgPSB0YXJnZXQ7XG5cdFx0XHRcdFx0XHRsYXN0Q1NTID0gX2Nzcyh0YXJnZXQpO1xuXHRcdFx0XHRcdFx0bGFzdFBhcmVudENTUyA9IF9jc3ModGFyZ2V0LnBhcmVudE5vZGUpO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHRhcmdldFJlY3QgPSB0YXJnZXQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cblx0XHRcdFx0XHR2YXIgd2lkdGggPSB0YXJnZXRSZWN0LnJpZ2h0IC0gdGFyZ2V0UmVjdC5sZWZ0LFxuXHRcdFx0XHRcdFx0aGVpZ2h0ID0gdGFyZ2V0UmVjdC5ib3R0b20gLSB0YXJnZXRSZWN0LnRvcCxcblx0XHRcdFx0XHRcdGZsb2F0aW5nID0gUl9GTE9BVC50ZXN0KGxhc3RDU1MuY3NzRmxvYXQgKyBsYXN0Q1NTLmRpc3BsYXkpXG5cdFx0XHRcdFx0XHRcdHx8IChsYXN0UGFyZW50Q1NTLmRpc3BsYXkgPT0gJ2ZsZXgnICYmIGxhc3RQYXJlbnRDU1NbJ2ZsZXgtZGlyZWN0aW9uJ10uaW5kZXhPZigncm93JykgPT09IDApLFxuXHRcdFx0XHRcdFx0aXNXaWRlID0gKHRhcmdldC5vZmZzZXRXaWR0aCA+IGRyYWdFbC5vZmZzZXRXaWR0aCksXG5cdFx0XHRcdFx0XHRpc0xvbmcgPSAodGFyZ2V0Lm9mZnNldEhlaWdodCA+IGRyYWdFbC5vZmZzZXRIZWlnaHQpLFxuXHRcdFx0XHRcdFx0aGFsZndheSA9IChmbG9hdGluZyA/IChldnQuY2xpZW50WCAtIHRhcmdldFJlY3QubGVmdCkgLyB3aWR0aCA6IChldnQuY2xpZW50WSAtIHRhcmdldFJlY3QudG9wKSAvIGhlaWdodCkgPiAwLjUsXG5cdFx0XHRcdFx0XHRuZXh0U2libGluZyA9IHRhcmdldC5uZXh0RWxlbWVudFNpYmxpbmcsXG5cdFx0XHRcdFx0XHRhZnRlciA9IGZhbHNlXG5cdFx0XHRcdFx0O1xuXG5cdFx0XHRcdFx0aWYgKGZsb2F0aW5nKSB7XG5cdFx0XHRcdFx0XHR2YXIgZWxUb3AgPSBkcmFnRWwub2Zmc2V0VG9wLFxuXHRcdFx0XHRcdFx0XHR0Z1RvcCA9IHRhcmdldC5vZmZzZXRUb3A7XG5cblx0XHRcdFx0XHRcdGlmIChlbFRvcCA9PT0gdGdUb3ApIHtcblx0XHRcdFx0XHRcdFx0YWZ0ZXIgPSAodGFyZ2V0LnByZXZpb3VzRWxlbWVudFNpYmxpbmcgPT09IGRyYWdFbCkgJiYgIWlzV2lkZSB8fCBoYWxmd2F5ICYmIGlzV2lkZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGVsc2UgaWYgKHRhcmdldC5wcmV2aW91c0VsZW1lbnRTaWJsaW5nID09PSBkcmFnRWwgfHwgZHJhZ0VsLnByZXZpb3VzRWxlbWVudFNpYmxpbmcgPT09IHRhcmdldCkge1xuXHRcdFx0XHRcdFx0XHRhZnRlciA9IChldnQuY2xpZW50WSAtIHRhcmdldFJlY3QudG9wKSAvIGhlaWdodCA+IDAuNTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdGFmdGVyID0gdGdUb3AgPiBlbFRvcDtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoIWlzTW92aW5nQmV0d2VlblNvcnRhYmxlKSB7XG5cdFx0XHRcdFx0XHRhZnRlciA9IChuZXh0U2libGluZyAhPT0gZHJhZ0VsKSAmJiAhaXNMb25nIHx8IGhhbGZ3YXkgJiYgaXNMb25nO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHZhciBtb3ZlVmVjdG9yID0gX29uTW92ZShyb290RWwsIGVsLCBkcmFnRWwsIGRyYWdSZWN0LCB0YXJnZXQsIHRhcmdldFJlY3QsIGV2dCwgYWZ0ZXIpO1xuXG5cdFx0XHRcdFx0aWYgKG1vdmVWZWN0b3IgIT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0XHRpZiAobW92ZVZlY3RvciA9PT0gMSB8fCBtb3ZlVmVjdG9yID09PSAtMSkge1xuXHRcdFx0XHRcdFx0XHRhZnRlciA9IChtb3ZlVmVjdG9yID09PSAxKTtcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0X3NpbGVudCA9IHRydWU7XG5cdFx0XHRcdFx0XHRzZXRUaW1lb3V0KF91bnNpbGVudCwgMzApO1xuXG5cdFx0XHRcdFx0XHRfY2xvbmVIaWRlKGFjdGl2ZVNvcnRhYmxlLCBpc093bmVyKTtcblxuXHRcdFx0XHRcdFx0aWYgKCFkcmFnRWwuY29udGFpbnMoZWwpKSB7XG5cdFx0XHRcdFx0XHRcdGlmIChhZnRlciAmJiAhbmV4dFNpYmxpbmcpIHtcblx0XHRcdFx0XHRcdFx0XHRlbC5hcHBlbmRDaGlsZChkcmFnRWwpO1xuXHRcdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRcdHRhcmdldC5wYXJlbnROb2RlLmluc2VydEJlZm9yZShkcmFnRWwsIGFmdGVyID8gbmV4dFNpYmxpbmcgOiB0YXJnZXQpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdHBhcmVudEVsID0gZHJhZ0VsLnBhcmVudE5vZGU7IC8vIGFjdHVhbGl6YXRpb25cblxuXHRcdFx0XHRcdFx0dGhpcy5fYW5pbWF0ZShkcmFnUmVjdCwgZHJhZ0VsKTtcblx0XHRcdFx0XHRcdHRoaXMuX2FuaW1hdGUodGFyZ2V0UmVjdCwgdGFyZ2V0KTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0X2FuaW1hdGU6IGZ1bmN0aW9uIChwcmV2UmVjdCwgdGFyZ2V0KSB7XG5cdFx0XHR2YXIgbXMgPSB0aGlzLm9wdGlvbnMuYW5pbWF0aW9uO1xuXG5cdFx0XHRpZiAobXMpIHtcblx0XHRcdFx0dmFyIGN1cnJlbnRSZWN0ID0gdGFyZ2V0LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG5cdFx0XHRcdGlmIChwcmV2UmVjdC5ub2RlVHlwZSA9PT0gMSkge1xuXHRcdFx0XHRcdHByZXZSZWN0ID0gcHJldlJlY3QuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRfY3NzKHRhcmdldCwgJ3RyYW5zaXRpb24nLCAnbm9uZScpO1xuXHRcdFx0XHRfY3NzKHRhcmdldCwgJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUzZCgnXG5cdFx0XHRcdFx0KyAocHJldlJlY3QubGVmdCAtIGN1cnJlbnRSZWN0LmxlZnQpICsgJ3B4LCdcblx0XHRcdFx0XHQrIChwcmV2UmVjdC50b3AgLSBjdXJyZW50UmVjdC50b3ApICsgJ3B4LDApJ1xuXHRcdFx0XHQpO1xuXG5cdFx0XHRcdHRhcmdldC5vZmZzZXRXaWR0aDsgLy8gcmVwYWludFxuXG5cdFx0XHRcdF9jc3ModGFyZ2V0LCAndHJhbnNpdGlvbicsICdhbGwgJyArIG1zICsgJ21zJyk7XG5cdFx0XHRcdF9jc3ModGFyZ2V0LCAndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZTNkKDAsMCwwKScpO1xuXG5cdFx0XHRcdGNsZWFyVGltZW91dCh0YXJnZXQuYW5pbWF0ZWQpO1xuXHRcdFx0XHR0YXJnZXQuYW5pbWF0ZWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRfY3NzKHRhcmdldCwgJ3RyYW5zaXRpb24nLCAnJyk7XG5cdFx0XHRcdFx0X2Nzcyh0YXJnZXQsICd0cmFuc2Zvcm0nLCAnJyk7XG5cdFx0XHRcdFx0dGFyZ2V0LmFuaW1hdGVkID0gZmFsc2U7XG5cdFx0XHRcdH0sIG1zKTtcblx0XHRcdH1cblx0XHR9LFxuXG5cdFx0X29mZlVwRXZlbnRzOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHR2YXIgb3duZXJEb2N1bWVudCA9IHRoaXMuZWwub3duZXJEb2N1bWVudDtcblxuXHRcdFx0X29mZihkb2N1bWVudCwgJ3RvdWNobW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlKTtcblx0XHRcdF9vZmYoZG9jdW1lbnQsICdwb2ludGVybW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlKTtcblx0XHRcdF9vZmYob3duZXJEb2N1bWVudCwgJ21vdXNldXAnLCB0aGlzLl9vbkRyb3ApO1xuXHRcdFx0X29mZihvd25lckRvY3VtZW50LCAndG91Y2hlbmQnLCB0aGlzLl9vbkRyb3ApO1xuXHRcdFx0X29mZihvd25lckRvY3VtZW50LCAncG9pbnRlcnVwJywgdGhpcy5fb25Ecm9wKTtcblx0XHRcdF9vZmYob3duZXJEb2N1bWVudCwgJ3RvdWNoY2FuY2VsJywgdGhpcy5fb25Ecm9wKTtcblx0XHRcdF9vZmYob3duZXJEb2N1bWVudCwgJ3BvaW50ZXJjYW5jZWwnLCB0aGlzLl9vbkRyb3ApO1xuXHRcdFx0X29mZihvd25lckRvY3VtZW50LCAnc2VsZWN0c3RhcnQnLCB0aGlzKTtcblx0XHR9LFxuXG5cdFx0X29uRHJvcDogZnVuY3Rpb24gKC8qKkV2ZW50Ki9ldnQpIHtcblx0XHRcdHZhciBlbCA9IHRoaXMuZWwsXG5cdFx0XHRcdG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cblx0XHRcdGNsZWFySW50ZXJ2YWwodGhpcy5fbG9vcElkKTtcblx0XHRcdGNsZWFySW50ZXJ2YWwoYXV0b1Njcm9sbC5waWQpO1xuXHRcdFx0Y2xlYXJUaW1lb3V0KHRoaXMuX2RyYWdTdGFydFRpbWVyKTtcblxuXHRcdFx0X2NhbmNlbE5leHRUaWNrKHRoaXMuX2Nsb25lSWQpO1xuXHRcdFx0X2NhbmNlbE5leHRUaWNrKHRoaXMuX2RyYWdTdGFydElkKTtcblxuXHRcdFx0Ly8gVW5iaW5kIGV2ZW50c1xuXHRcdFx0X29mZihkb2N1bWVudCwgJ21vdXNlb3ZlcicsIHRoaXMpO1xuXHRcdFx0X29mZihkb2N1bWVudCwgJ21vdXNlbW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlKTtcblxuXHRcdFx0aWYgKHRoaXMubmF0aXZlRHJhZ2dhYmxlKSB7XG5cdFx0XHRcdF9vZmYoZG9jdW1lbnQsICdkcm9wJywgdGhpcyk7XG5cdFx0XHRcdF9vZmYoZWwsICdkcmFnc3RhcnQnLCB0aGlzLl9vbkRyYWdTdGFydCk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuX29mZlVwRXZlbnRzKCk7XG5cblx0XHRcdGlmIChldnQpIHtcblx0XHRcdFx0aWYgKG1vdmVkKSB7XG5cdFx0XHRcdFx0ZXZ0LnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0IW9wdGlvbnMuZHJvcEJ1YmJsZSAmJiBldnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRnaG9zdEVsICYmIGdob3N0RWwucGFyZW50Tm9kZSAmJiBnaG9zdEVsLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZ2hvc3RFbCk7XG5cblx0XHRcdFx0aWYgKHJvb3RFbCA9PT0gcGFyZW50RWwgfHwgU29ydGFibGUuYWN0aXZlLmxhc3RQdWxsTW9kZSAhPT0gJ2Nsb25lJykge1xuXHRcdFx0XHRcdC8vIFJlbW92ZSBjbG9uZVxuXHRcdFx0XHRcdGNsb25lRWwgJiYgY2xvbmVFbC5wYXJlbnROb2RlICYmIGNsb25lRWwucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChjbG9uZUVsKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChkcmFnRWwpIHtcblx0XHRcdFx0XHRpZiAodGhpcy5uYXRpdmVEcmFnZ2FibGUpIHtcblx0XHRcdFx0XHRcdF9vZmYoZHJhZ0VsLCAnZHJhZ2VuZCcsIHRoaXMpO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdF9kaXNhYmxlRHJhZ2dhYmxlKGRyYWdFbCk7XG5cdFx0XHRcdFx0ZHJhZ0VsLnN0eWxlWyd3aWxsLWNoYW5nZSddID0gJyc7XG5cblx0XHRcdFx0XHQvLyBSZW1vdmUgY2xhc3Mnc1xuXHRcdFx0XHRcdF90b2dnbGVDbGFzcyhkcmFnRWwsIHRoaXMub3B0aW9ucy5naG9zdENsYXNzLCBmYWxzZSk7XG5cdFx0XHRcdFx0X3RvZ2dsZUNsYXNzKGRyYWdFbCwgdGhpcy5vcHRpb25zLmNob3NlbkNsYXNzLCBmYWxzZSk7XG5cblx0XHRcdFx0XHQvLyBEcmFnIHN0b3AgZXZlbnRcblx0XHRcdFx0XHRfZGlzcGF0Y2hFdmVudCh0aGlzLCByb290RWwsICd1bmNob29zZScsIGRyYWdFbCwgcGFyZW50RWwsIHJvb3RFbCwgb2xkSW5kZXgpO1xuXG5cdFx0XHRcdFx0aWYgKHJvb3RFbCAhPT0gcGFyZW50RWwpIHtcblx0XHRcdFx0XHRcdG5ld0luZGV4ID0gX2luZGV4KGRyYWdFbCwgb3B0aW9ucy5kcmFnZ2FibGUpO1xuXG5cdFx0XHRcdFx0XHRpZiAobmV3SW5kZXggPj0gMCkge1xuXHRcdFx0XHRcdFx0XHQvLyBBZGQgZXZlbnRcblx0XHRcdFx0XHRcdFx0X2Rpc3BhdGNoRXZlbnQobnVsbCwgcGFyZW50RWwsICdhZGQnLCBkcmFnRWwsIHBhcmVudEVsLCByb290RWwsIG9sZEluZGV4LCBuZXdJbmRleCk7XG5cblx0XHRcdFx0XHRcdFx0Ly8gUmVtb3ZlIGV2ZW50XG5cdFx0XHRcdFx0XHRcdF9kaXNwYXRjaEV2ZW50KHRoaXMsIHJvb3RFbCwgJ3JlbW92ZScsIGRyYWdFbCwgcGFyZW50RWwsIHJvb3RFbCwgb2xkSW5kZXgsIG5ld0luZGV4KTtcblxuXHRcdFx0XHRcdFx0XHQvLyBkcmFnIGZyb20gb25lIGxpc3QgYW5kIGRyb3AgaW50byBhbm90aGVyXG5cdFx0XHRcdFx0XHRcdF9kaXNwYXRjaEV2ZW50KG51bGwsIHBhcmVudEVsLCAnc29ydCcsIGRyYWdFbCwgcGFyZW50RWwsIHJvb3RFbCwgb2xkSW5kZXgsIG5ld0luZGV4KTtcblx0XHRcdFx0XHRcdFx0X2Rpc3BhdGNoRXZlbnQodGhpcywgcm9vdEVsLCAnc29ydCcsIGRyYWdFbCwgcGFyZW50RWwsIHJvb3RFbCwgb2xkSW5kZXgsIG5ld0luZGV4KTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0ZWxzZSB7XG5cdFx0XHRcdFx0XHRpZiAoZHJhZ0VsLm5leHRTaWJsaW5nICE9PSBuZXh0RWwpIHtcblx0XHRcdFx0XHRcdFx0Ly8gR2V0IHRoZSBpbmRleCBvZiB0aGUgZHJhZ2dlZCBlbGVtZW50IHdpdGhpbiBpdHMgcGFyZW50XG5cdFx0XHRcdFx0XHRcdG5ld0luZGV4ID0gX2luZGV4KGRyYWdFbCwgb3B0aW9ucy5kcmFnZ2FibGUpO1xuXG5cdFx0XHRcdFx0XHRcdGlmIChuZXdJbmRleCA+PSAwKSB7XG5cdFx0XHRcdFx0XHRcdFx0Ly8gZHJhZyAmIGRyb3Agd2l0aGluIHRoZSBzYW1lIGxpc3Rcblx0XHRcdFx0XHRcdFx0XHRfZGlzcGF0Y2hFdmVudCh0aGlzLCByb290RWwsICd1cGRhdGUnLCBkcmFnRWwsIHBhcmVudEVsLCByb290RWwsIG9sZEluZGV4LCBuZXdJbmRleCk7XG5cdFx0XHRcdFx0XHRcdFx0X2Rpc3BhdGNoRXZlbnQodGhpcywgcm9vdEVsLCAnc29ydCcsIGRyYWdFbCwgcGFyZW50RWwsIHJvb3RFbCwgb2xkSW5kZXgsIG5ld0luZGV4KTtcblx0XHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmIChTb3J0YWJsZS5hY3RpdmUpIHtcblx0XHRcdFx0XHRcdC8qIGpzaGludCBlcW51bGw6dHJ1ZSAqL1xuXHRcdFx0XHRcdFx0aWYgKG5ld0luZGV4ID09IG51bGwgfHwgbmV3SW5kZXggPT09IC0xKSB7XG5cdFx0XHRcdFx0XHRcdG5ld0luZGV4ID0gb2xkSW5kZXg7XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdF9kaXNwYXRjaEV2ZW50KHRoaXMsIHJvb3RFbCwgJ2VuZCcsIGRyYWdFbCwgcGFyZW50RWwsIHJvb3RFbCwgb2xkSW5kZXgsIG5ld0luZGV4KTtcblxuXHRcdFx0XHRcdFx0Ly8gU2F2ZSBzb3J0aW5nXG5cdFx0XHRcdFx0XHR0aGlzLnNhdmUoKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblxuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLl9udWxsaW5nKCk7XG5cdFx0fSxcblxuXHRcdF9udWxsaW5nOiBmdW5jdGlvbigpIHtcblx0XHRcdHJvb3RFbCA9XG5cdFx0XHRkcmFnRWwgPVxuXHRcdFx0cGFyZW50RWwgPVxuXHRcdFx0Z2hvc3RFbCA9XG5cdFx0XHRuZXh0RWwgPVxuXHRcdFx0Y2xvbmVFbCA9XG5cdFx0XHRsYXN0RG93bkVsID1cblxuXHRcdFx0c2Nyb2xsRWwgPVxuXHRcdFx0c2Nyb2xsUGFyZW50RWwgPVxuXG5cdFx0XHR0YXBFdnQgPVxuXHRcdFx0dG91Y2hFdnQgPVxuXG5cdFx0XHRtb3ZlZCA9XG5cdFx0XHRuZXdJbmRleCA9XG5cblx0XHRcdGxhc3RFbCA9XG5cdFx0XHRsYXN0Q1NTID1cblxuXHRcdFx0cHV0U29ydGFibGUgPVxuXHRcdFx0YWN0aXZlR3JvdXAgPVxuXHRcdFx0U29ydGFibGUuYWN0aXZlID0gbnVsbDtcblxuXHRcdFx0c2F2ZWRJbnB1dENoZWNrZWQuZm9yRWFjaChmdW5jdGlvbiAoZWwpIHtcblx0XHRcdFx0ZWwuY2hlY2tlZCA9IHRydWU7XG5cdFx0XHR9KTtcblx0XHRcdHNhdmVkSW5wdXRDaGVja2VkLmxlbmd0aCA9IDA7XG5cdFx0fSxcblxuXHRcdGhhbmRsZUV2ZW50OiBmdW5jdGlvbiAoLyoqRXZlbnQqL2V2dCkge1xuXHRcdFx0c3dpdGNoIChldnQudHlwZSkge1xuXHRcdFx0XHRjYXNlICdkcm9wJzpcblx0XHRcdFx0Y2FzZSAnZHJhZ2VuZCc6XG5cdFx0XHRcdFx0dGhpcy5fb25Ecm9wKGV2dCk7XG5cdFx0XHRcdFx0YnJlYWs7XG5cblx0XHRcdFx0Y2FzZSAnZHJhZ292ZXInOlxuXHRcdFx0XHRjYXNlICdkcmFnZW50ZXInOlxuXHRcdFx0XHRcdGlmIChkcmFnRWwpIHtcblx0XHRcdFx0XHRcdHRoaXMuX29uRHJhZ092ZXIoZXZ0KTtcblx0XHRcdFx0XHRcdF9nbG9iYWxEcmFnT3ZlcihldnQpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRicmVhaztcblxuXHRcdFx0XHRjYXNlICdtb3VzZW92ZXInOlxuXHRcdFx0XHRcdHRoaXMuX29uRHJvcChldnQpO1xuXHRcdFx0XHRcdGJyZWFrO1xuXG5cdFx0XHRcdGNhc2UgJ3NlbGVjdHN0YXJ0Jzpcblx0XHRcdFx0XHRldnQucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdH1cblx0XHR9LFxuXG5cblx0XHQvKipcblx0XHQgKiBTZXJpYWxpemVzIHRoZSBpdGVtIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5nLlxuXHRcdCAqIEByZXR1cm5zIHtTdHJpbmdbXX1cblx0XHQgKi9cblx0XHR0b0FycmF5OiBmdW5jdGlvbiAoKSB7XG5cdFx0XHR2YXIgb3JkZXIgPSBbXSxcblx0XHRcdFx0ZWwsXG5cdFx0XHRcdGNoaWxkcmVuID0gdGhpcy5lbC5jaGlsZHJlbixcblx0XHRcdFx0aSA9IDAsXG5cdFx0XHRcdG4gPSBjaGlsZHJlbi5sZW5ndGgsXG5cdFx0XHRcdG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7XG5cblx0XHRcdGZvciAoOyBpIDwgbjsgaSsrKSB7XG5cdFx0XHRcdGVsID0gY2hpbGRyZW5baV07XG5cdFx0XHRcdGlmIChfY2xvc2VzdChlbCwgb3B0aW9ucy5kcmFnZ2FibGUsIHRoaXMuZWwpKSB7XG5cdFx0XHRcdFx0b3JkZXIucHVzaChlbC5nZXRBdHRyaWJ1dGUob3B0aW9ucy5kYXRhSWRBdHRyKSB8fCBfZ2VuZXJhdGVJZChlbCkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBvcmRlcjtcblx0XHR9LFxuXG5cblx0XHQvKipcblx0XHQgKiBTb3J0cyB0aGUgZWxlbWVudHMgYWNjb3JkaW5nIHRvIHRoZSBhcnJheS5cblx0XHQgKiBAcGFyYW0gIHtTdHJpbmdbXX0gIG9yZGVyICBvcmRlciBvZiB0aGUgaXRlbXNcblx0XHQgKi9cblx0XHRzb3J0OiBmdW5jdGlvbiAob3JkZXIpIHtcblx0XHRcdHZhciBpdGVtcyA9IHt9LCByb290RWwgPSB0aGlzLmVsO1xuXG5cdFx0XHR0aGlzLnRvQXJyYXkoKS5mb3JFYWNoKGZ1bmN0aW9uIChpZCwgaSkge1xuXHRcdFx0XHR2YXIgZWwgPSByb290RWwuY2hpbGRyZW5baV07XG5cblx0XHRcdFx0aWYgKF9jbG9zZXN0KGVsLCB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlLCByb290RWwpKSB7XG5cdFx0XHRcdFx0aXRlbXNbaWRdID0gZWw7XG5cdFx0XHRcdH1cblx0XHRcdH0sIHRoaXMpO1xuXG5cdFx0XHRvcmRlci5mb3JFYWNoKGZ1bmN0aW9uIChpZCkge1xuXHRcdFx0XHRpZiAoaXRlbXNbaWRdKSB7XG5cdFx0XHRcdFx0cm9vdEVsLnJlbW92ZUNoaWxkKGl0ZW1zW2lkXSk7XG5cdFx0XHRcdFx0cm9vdEVsLmFwcGVuZENoaWxkKGl0ZW1zW2lkXSk7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH0sXG5cblxuXHRcdC8qKlxuXHRcdCAqIFNhdmUgdGhlIGN1cnJlbnQgc29ydGluZ1xuXHRcdCAqL1xuXHRcdHNhdmU6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciBzdG9yZSA9IHRoaXMub3B0aW9ucy5zdG9yZTtcblx0XHRcdHN0b3JlICYmIHN0b3JlLnNldCh0aGlzKTtcblx0XHR9LFxuXG5cblx0XHQvKipcblx0XHQgKiBGb3IgZWFjaCBlbGVtZW50IGluIHRoZSBzZXQsIGdldCB0aGUgZmlyc3QgZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIHNlbGVjdG9yIGJ5IHRlc3RpbmcgdGhlIGVsZW1lbnQgaXRzZWxmIGFuZCB0cmF2ZXJzaW5nIHVwIHRocm91Z2ggaXRzIGFuY2VzdG9ycyBpbiB0aGUgRE9NIHRyZWUuXG5cdFx0ICogQHBhcmFtICAge0hUTUxFbGVtZW50fSAgZWxcblx0XHQgKiBAcGFyYW0gICB7U3RyaW5nfSAgICAgICBbc2VsZWN0b3JdICBkZWZhdWx0OiBgb3B0aW9ucy5kcmFnZ2FibGVgXG5cdFx0ICogQHJldHVybnMge0hUTUxFbGVtZW50fG51bGx9XG5cdFx0ICovXG5cdFx0Y2xvc2VzdDogZnVuY3Rpb24gKGVsLCBzZWxlY3Rvcikge1xuXHRcdFx0cmV0dXJuIF9jbG9zZXN0KGVsLCBzZWxlY3RvciB8fCB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlLCB0aGlzLmVsKTtcblx0XHR9LFxuXG5cblx0XHQvKipcblx0XHQgKiBTZXQvZ2V0IG9wdGlvblxuXHRcdCAqIEBwYXJhbSAgIHtzdHJpbmd9IG5hbWVcblx0XHQgKiBAcGFyYW0gICB7Kn0gICAgICBbdmFsdWVdXG5cdFx0ICogQHJldHVybnMgeyp9XG5cdFx0ICovXG5cdFx0b3B0aW9uOiBmdW5jdGlvbiAobmFtZSwgdmFsdWUpIHtcblx0XHRcdHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuXG5cdFx0XHRpZiAodmFsdWUgPT09IHZvaWQgMCkge1xuXHRcdFx0XHRyZXR1cm4gb3B0aW9uc1tuYW1lXTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG9wdGlvbnNbbmFtZV0gPSB2YWx1ZTtcblxuXHRcdFx0XHRpZiAobmFtZSA9PT0gJ2dyb3VwJykge1xuXHRcdFx0XHRcdF9wcmVwYXJlR3JvdXAob3B0aW9ucyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9LFxuXG5cblx0XHQvKipcblx0XHQgKiBEZXN0cm95XG5cdFx0ICovXG5cdFx0ZGVzdHJveTogZnVuY3Rpb24gKCkge1xuXHRcdFx0dmFyIGVsID0gdGhpcy5lbDtcblxuXHRcdFx0ZWxbZXhwYW5kb10gPSBudWxsO1xuXG5cdFx0XHRfb2ZmKGVsLCAnbW91c2Vkb3duJywgdGhpcy5fb25UYXBTdGFydCk7XG5cdFx0XHRfb2ZmKGVsLCAndG91Y2hzdGFydCcsIHRoaXMuX29uVGFwU3RhcnQpO1xuXHRcdFx0X29mZihlbCwgJ3BvaW50ZXJkb3duJywgdGhpcy5fb25UYXBTdGFydCk7XG5cblx0XHRcdGlmICh0aGlzLm5hdGl2ZURyYWdnYWJsZSkge1xuXHRcdFx0XHRfb2ZmKGVsLCAnZHJhZ292ZXInLCB0aGlzKTtcblx0XHRcdFx0X29mZihlbCwgJ2RyYWdlbnRlcicsIHRoaXMpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBSZW1vdmUgZHJhZ2dhYmxlIGF0dHJpYnV0ZXNcblx0XHRcdEFycmF5LnByb3RvdHlwZS5mb3JFYWNoLmNhbGwoZWwucXVlcnlTZWxlY3RvckFsbCgnW2RyYWdnYWJsZV0nKSwgZnVuY3Rpb24gKGVsKSB7XG5cdFx0XHRcdGVsLnJlbW92ZUF0dHJpYnV0ZSgnZHJhZ2dhYmxlJyk7XG5cdFx0XHR9KTtcblxuXHRcdFx0dG91Y2hEcmFnT3Zlckxpc3RlbmVycy5zcGxpY2UodG91Y2hEcmFnT3Zlckxpc3RlbmVycy5pbmRleE9mKHRoaXMuX29uRHJhZ092ZXIpLCAxKTtcblxuXHRcdFx0dGhpcy5fb25Ecm9wKCk7XG5cblx0XHRcdHRoaXMuZWwgPSBlbCA9IG51bGw7XG5cdFx0fVxuXHR9O1xuXG5cblx0ZnVuY3Rpb24gX2Nsb25lSGlkZShzb3J0YWJsZSwgc3RhdGUpIHtcblx0XHRpZiAoc29ydGFibGUubGFzdFB1bGxNb2RlICE9PSAnY2xvbmUnKSB7XG5cdFx0XHRzdGF0ZSA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKGNsb25lRWwgJiYgKGNsb25lRWwuc3RhdGUgIT09IHN0YXRlKSkge1xuXHRcdFx0X2NzcyhjbG9uZUVsLCAnZGlzcGxheScsIHN0YXRlID8gJ25vbmUnIDogJycpO1xuXG5cdFx0XHRpZiAoIXN0YXRlKSB7XG5cdFx0XHRcdGlmIChjbG9uZUVsLnN0YXRlKSB7XG5cdFx0XHRcdFx0aWYgKHNvcnRhYmxlLm9wdGlvbnMuZ3JvdXAucmV2ZXJ0Q2xvbmUpIHtcblx0XHRcdFx0XHRcdHJvb3RFbC5pbnNlcnRCZWZvcmUoY2xvbmVFbCwgbmV4dEVsKTtcblx0XHRcdFx0XHRcdHNvcnRhYmxlLl9hbmltYXRlKGRyYWdFbCwgY2xvbmVFbCk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJvb3RFbC5pbnNlcnRCZWZvcmUoY2xvbmVFbCwgZHJhZ0VsKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0Y2xvbmVFbC5zdGF0ZSA9IHN0YXRlO1xuXHRcdH1cblx0fVxuXG5cblx0ZnVuY3Rpb24gX2Nsb3Nlc3QoLyoqSFRNTEVsZW1lbnQqL2VsLCAvKipTdHJpbmcqL3NlbGVjdG9yLCAvKipIVE1MRWxlbWVudCovY3R4KSB7XG5cdFx0aWYgKGVsKSB7XG5cdFx0XHRjdHggPSBjdHggfHwgZG9jdW1lbnQ7XG5cblx0XHRcdGRvIHtcblx0XHRcdFx0aWYgKChzZWxlY3RvciA9PT0gJz4qJyAmJiBlbC5wYXJlbnROb2RlID09PSBjdHgpIHx8IF9tYXRjaGVzKGVsLCBzZWxlY3RvcikpIHtcblx0XHRcdFx0XHRyZXR1cm4gZWw7XG5cdFx0XHRcdH1cblx0XHRcdFx0LyoganNoaW50IGJvc3M6dHJ1ZSAqL1xuXHRcdFx0fSB3aGlsZSAoZWwgPSBfZ2V0UGFyZW50T3JIb3N0KGVsKSk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIG51bGw7XG5cdH1cblxuXG5cdGZ1bmN0aW9uIF9nZXRQYXJlbnRPckhvc3QoZWwpIHtcblx0XHR2YXIgcGFyZW50ID0gZWwuaG9zdDtcblxuXHRcdHJldHVybiAocGFyZW50ICYmIHBhcmVudC5ub2RlVHlwZSkgPyBwYXJlbnQgOiBlbC5wYXJlbnROb2RlO1xuXHR9XG5cblxuXHRmdW5jdGlvbiBfZ2xvYmFsRHJhZ092ZXIoLyoqRXZlbnQqL2V2dCkge1xuXHRcdGlmIChldnQuZGF0YVRyYW5zZmVyKSB7XG5cdFx0XHRldnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbW92ZSc7XG5cdFx0fVxuXHRcdGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xuXHR9XG5cblxuXHRmdW5jdGlvbiBfb24oZWwsIGV2ZW50LCBmbikge1xuXHRcdGVsLmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGZuLCBjYXB0dXJlTW9kZSk7XG5cdH1cblxuXG5cdGZ1bmN0aW9uIF9vZmYoZWwsIGV2ZW50LCBmbikge1xuXHRcdGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIGZuLCBjYXB0dXJlTW9kZSk7XG5cdH1cblxuXG5cdGZ1bmN0aW9uIF90b2dnbGVDbGFzcyhlbCwgbmFtZSwgc3RhdGUpIHtcblx0XHRpZiAoZWwpIHtcblx0XHRcdGlmIChlbC5jbGFzc0xpc3QpIHtcblx0XHRcdFx0ZWwuY2xhc3NMaXN0W3N0YXRlID8gJ2FkZCcgOiAncmVtb3ZlJ10obmFtZSk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0dmFyIGNsYXNzTmFtZSA9ICgnICcgKyBlbC5jbGFzc05hbWUgKyAnICcpLnJlcGxhY2UoUl9TUEFDRSwgJyAnKS5yZXBsYWNlKCcgJyArIG5hbWUgKyAnICcsICcgJyk7XG5cdFx0XHRcdGVsLmNsYXNzTmFtZSA9IChjbGFzc05hbWUgKyAoc3RhdGUgPyAnICcgKyBuYW1lIDogJycpKS5yZXBsYWNlKFJfU1BBQ0UsICcgJyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblxuXHRmdW5jdGlvbiBfY3NzKGVsLCBwcm9wLCB2YWwpIHtcblx0XHR2YXIgc3R5bGUgPSBlbCAmJiBlbC5zdHlsZTtcblxuXHRcdGlmIChzdHlsZSkge1xuXHRcdFx0aWYgKHZhbCA9PT0gdm9pZCAwKSB7XG5cdFx0XHRcdGlmIChkb2N1bWVudC5kZWZhdWx0VmlldyAmJiBkb2N1bWVudC5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKSB7XG5cdFx0XHRcdFx0dmFsID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShlbCwgJycpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGVsc2UgaWYgKGVsLmN1cnJlbnRTdHlsZSkge1xuXHRcdFx0XHRcdHZhbCA9IGVsLmN1cnJlbnRTdHlsZTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdHJldHVybiBwcm9wID09PSB2b2lkIDAgPyB2YWwgOiB2YWxbcHJvcF07XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0aWYgKCEocHJvcCBpbiBzdHlsZSkpIHtcblx0XHRcdFx0XHRwcm9wID0gJy13ZWJraXQtJyArIHByb3A7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRzdHlsZVtwcm9wXSA9IHZhbCArICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJyA/ICcnIDogJ3B4Jyk7XG5cdFx0XHR9XG5cdFx0fVxuXHR9XG5cblxuXHRmdW5jdGlvbiBfZmluZChjdHgsIHRhZ05hbWUsIGl0ZXJhdG9yKSB7XG5cdFx0aWYgKGN0eCkge1xuXHRcdFx0dmFyIGxpc3QgPSBjdHguZ2V0RWxlbWVudHNCeVRhZ05hbWUodGFnTmFtZSksIGkgPSAwLCBuID0gbGlzdC5sZW5ndGg7XG5cblx0XHRcdGlmIChpdGVyYXRvcikge1xuXHRcdFx0XHRmb3IgKDsgaSA8IG47IGkrKykge1xuXHRcdFx0XHRcdGl0ZXJhdG9yKGxpc3RbaV0sIGkpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdHJldHVybiBsaXN0O1xuXHRcdH1cblxuXHRcdHJldHVybiBbXTtcblx0fVxuXG5cblxuXHRmdW5jdGlvbiBfZGlzcGF0Y2hFdmVudChzb3J0YWJsZSwgcm9vdEVsLCBuYW1lLCB0YXJnZXRFbCwgdG9FbCwgZnJvbUVsLCBzdGFydEluZGV4LCBuZXdJbmRleCkge1xuXHRcdHNvcnRhYmxlID0gKHNvcnRhYmxlIHx8IHJvb3RFbFtleHBhbmRvXSk7XG5cblx0XHR2YXIgZXZ0ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50JyksXG5cdFx0XHRvcHRpb25zID0gc29ydGFibGUub3B0aW9ucyxcblx0XHRcdG9uTmFtZSA9ICdvbicgKyBuYW1lLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgbmFtZS5zdWJzdHIoMSk7XG5cblx0XHRldnQuaW5pdEV2ZW50KG5hbWUsIHRydWUsIHRydWUpO1xuXG5cdFx0ZXZ0LnRvID0gdG9FbCB8fCByb290RWw7XG5cdFx0ZXZ0LmZyb20gPSBmcm9tRWwgfHwgcm9vdEVsO1xuXHRcdGV2dC5pdGVtID0gdGFyZ2V0RWwgfHwgcm9vdEVsO1xuXHRcdGV2dC5jbG9uZSA9IGNsb25lRWw7XG5cblx0XHRldnQub2xkSW5kZXggPSBzdGFydEluZGV4O1xuXHRcdGV2dC5uZXdJbmRleCA9IG5ld0luZGV4O1xuXG5cdFx0cm9vdEVsLmRpc3BhdGNoRXZlbnQoZXZ0KTtcblxuXHRcdGlmIChvcHRpb25zW29uTmFtZV0pIHtcblx0XHRcdG9wdGlvbnNbb25OYW1lXS5jYWxsKHNvcnRhYmxlLCBldnQpO1xuXHRcdH1cblx0fVxuXG5cblx0ZnVuY3Rpb24gX29uTW92ZShmcm9tRWwsIHRvRWwsIGRyYWdFbCwgZHJhZ1JlY3QsIHRhcmdldEVsLCB0YXJnZXRSZWN0LCBvcmlnaW5hbEV2dCwgd2lsbEluc2VydEFmdGVyKSB7XG5cdFx0dmFyIGV2dCxcblx0XHRcdHNvcnRhYmxlID0gZnJvbUVsW2V4cGFuZG9dLFxuXHRcdFx0b25Nb3ZlRm4gPSBzb3J0YWJsZS5vcHRpb25zLm9uTW92ZSxcblx0XHRcdHJldFZhbDtcblxuXHRcdGV2dCA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdFdmVudCcpO1xuXHRcdGV2dC5pbml0RXZlbnQoJ21vdmUnLCB0cnVlLCB0cnVlKTtcblxuXHRcdGV2dC50byA9IHRvRWw7XG5cdFx0ZXZ0LmZyb20gPSBmcm9tRWw7XG5cdFx0ZXZ0LmRyYWdnZWQgPSBkcmFnRWw7XG5cdFx0ZXZ0LmRyYWdnZWRSZWN0ID0gZHJhZ1JlY3Q7XG5cdFx0ZXZ0LnJlbGF0ZWQgPSB0YXJnZXRFbCB8fCB0b0VsO1xuXHRcdGV2dC5yZWxhdGVkUmVjdCA9IHRhcmdldFJlY3QgfHwgdG9FbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcblx0XHRldnQud2lsbEluc2VydEFmdGVyID0gd2lsbEluc2VydEFmdGVyO1xuXG5cdFx0ZnJvbUVsLmRpc3BhdGNoRXZlbnQoZXZ0KTtcblxuXHRcdGlmIChvbk1vdmVGbikge1xuXHRcdFx0cmV0VmFsID0gb25Nb3ZlRm4uY2FsbChzb3J0YWJsZSwgZXZ0LCBvcmlnaW5hbEV2dCk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHJldFZhbDtcblx0fVxuXG5cblx0ZnVuY3Rpb24gX2Rpc2FibGVEcmFnZ2FibGUoZWwpIHtcblx0XHRlbC5kcmFnZ2FibGUgPSBmYWxzZTtcblx0fVxuXG5cblx0ZnVuY3Rpb24gX3Vuc2lsZW50KCkge1xuXHRcdF9zaWxlbnQgPSBmYWxzZTtcblx0fVxuXG5cblx0LyoqIEByZXR1cm5zIHtIVE1MRWxlbWVudHxmYWxzZX0gKi9cblx0ZnVuY3Rpb24gX2dob3N0SXNMYXN0KGVsLCBldnQpIHtcblx0XHR2YXIgbGFzdEVsID0gZWwubGFzdEVsZW1lbnRDaGlsZCxcblx0XHRcdHJlY3QgPSBsYXN0RWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG5cblx0XHQvLyA1IOKAlCBtaW4gZGVsdGFcblx0XHQvLyBhYnMg4oCUINC90LXQu9GM0LfRjyDQtNC+0LHQsNCy0LvRj9GC0YwsINCwINGC0L4g0LPQu9GO0LrQuCDQv9GA0Lgg0L3QsNCy0LXQtNC10L3QuNC4INGB0LLQtdGA0YXRg1xuXHRcdHJldHVybiAoZXZ0LmNsaWVudFkgLSAocmVjdC50b3AgKyByZWN0LmhlaWdodCkgPiA1KSB8fFxuXHRcdFx0KGV2dC5jbGllbnRYIC0gKHJlY3QubGVmdCArIHJlY3Qud2lkdGgpID4gNSk7XG5cdH1cblxuXG5cdC8qKlxuXHQgKiBHZW5lcmF0ZSBpZFxuXHQgKiBAcGFyYW0gICB7SFRNTEVsZW1lbnR9IGVsXG5cdCAqIEByZXR1cm5zIHtTdHJpbmd9XG5cdCAqIEBwcml2YXRlXG5cdCAqL1xuXHRmdW5jdGlvbiBfZ2VuZXJhdGVJZChlbCkge1xuXHRcdHZhciBzdHIgPSBlbC50YWdOYW1lICsgZWwuY2xhc3NOYW1lICsgZWwuc3JjICsgZWwuaHJlZiArIGVsLnRleHRDb250ZW50LFxuXHRcdFx0aSA9IHN0ci5sZW5ndGgsXG5cdFx0XHRzdW0gPSAwO1xuXG5cdFx0d2hpbGUgKGktLSkge1xuXHRcdFx0c3VtICs9IHN0ci5jaGFyQ29kZUF0KGkpO1xuXHRcdH1cblxuXHRcdHJldHVybiBzdW0udG9TdHJpbmcoMzYpO1xuXHR9XG5cblx0LyoqXG5cdCAqIFJldHVybnMgdGhlIGluZGV4IG9mIGFuIGVsZW1lbnQgd2l0aGluIGl0cyBwYXJlbnQgZm9yIGEgc2VsZWN0ZWQgc2V0IG9mXG5cdCAqIGVsZW1lbnRzXG5cdCAqIEBwYXJhbSAge0hUTUxFbGVtZW50fSBlbFxuXHQgKiBAcGFyYW0gIHtzZWxlY3Rvcn0gc2VsZWN0b3Jcblx0ICogQHJldHVybiB7bnVtYmVyfVxuXHQgKi9cblx0ZnVuY3Rpb24gX2luZGV4KGVsLCBzZWxlY3Rvcikge1xuXHRcdHZhciBpbmRleCA9IDA7XG5cblx0XHRpZiAoIWVsIHx8ICFlbC5wYXJlbnROb2RlKSB7XG5cdFx0XHRyZXR1cm4gLTE7XG5cdFx0fVxuXG5cdFx0d2hpbGUgKGVsICYmIChlbCA9IGVsLnByZXZpb3VzRWxlbWVudFNpYmxpbmcpKSB7XG5cdFx0XHRpZiAoKGVsLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgIT09ICdURU1QTEFURScpICYmIChzZWxlY3RvciA9PT0gJz4qJyB8fCBfbWF0Y2hlcyhlbCwgc2VsZWN0b3IpKSkge1xuXHRcdFx0XHRpbmRleCsrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHJldHVybiBpbmRleDtcblx0fVxuXG5cdGZ1bmN0aW9uIF9tYXRjaGVzKC8qKkhUTUxFbGVtZW50Ki9lbCwgLyoqU3RyaW5nKi9zZWxlY3Rvcikge1xuXHRcdGlmIChlbCkge1xuXHRcdFx0c2VsZWN0b3IgPSBzZWxlY3Rvci5zcGxpdCgnLicpO1xuXG5cdFx0XHR2YXIgdGFnID0gc2VsZWN0b3Iuc2hpZnQoKS50b1VwcGVyQ2FzZSgpLFxuXHRcdFx0XHRyZSA9IG5ldyBSZWdFeHAoJ1xcXFxzKCcgKyBzZWxlY3Rvci5qb2luKCd8JykgKyAnKSg/PVxcXFxzKScsICdnJyk7XG5cblx0XHRcdHJldHVybiAoXG5cdFx0XHRcdCh0YWcgPT09ICcnIHx8IGVsLm5vZGVOYW1lLnRvVXBwZXJDYXNlKCkgPT0gdGFnKSAmJlxuXHRcdFx0XHQoIXNlbGVjdG9yLmxlbmd0aCB8fCAoKCcgJyArIGVsLmNsYXNzTmFtZSArICcgJykubWF0Y2gocmUpIHx8IFtdKS5sZW5ndGggPT0gc2VsZWN0b3IubGVuZ3RoKVxuXHRcdFx0KTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHRmdW5jdGlvbiBfdGhyb3R0bGUoY2FsbGJhY2ssIG1zKSB7XG5cdFx0dmFyIGFyZ3MsIF90aGlzO1xuXG5cdFx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0XHRcdGlmIChhcmdzID09PSB2b2lkIDApIHtcblx0XHRcdFx0YXJncyA9IGFyZ3VtZW50cztcblx0XHRcdFx0X3RoaXMgPSB0aGlzO1xuXG5cdFx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdGlmIChhcmdzLmxlbmd0aCA9PT0gMSkge1xuXHRcdFx0XHRcdFx0Y2FsbGJhY2suY2FsbChfdGhpcywgYXJnc1swXSk7XG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdGNhbGxiYWNrLmFwcGx5KF90aGlzLCBhcmdzKTtcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRhcmdzID0gdm9pZCAwO1xuXHRcdFx0XHR9LCBtcyk7XG5cdFx0XHR9XG5cdFx0fTtcblx0fVxuXG5cdGZ1bmN0aW9uIF9leHRlbmQoZHN0LCBzcmMpIHtcblx0XHRpZiAoZHN0ICYmIHNyYykge1xuXHRcdFx0Zm9yICh2YXIga2V5IGluIHNyYykge1xuXHRcdFx0XHRpZiAoc3JjLmhhc093blByb3BlcnR5KGtleSkpIHtcblx0XHRcdFx0XHRkc3Rba2V5XSA9IHNyY1trZXldO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGRzdDtcblx0fVxuXG5cdGZ1bmN0aW9uIF9jbG9uZShlbCkge1xuXHRcdGlmIChQb2x5bWVyICYmIFBvbHltZXIuZG9tKSB7XG5cdFx0XHRyZXR1cm4gUG9seW1lci5kb20oZWwpLmNsb25lTm9kZSh0cnVlKTtcblx0XHR9XG5cdFx0ZWxzZSBpZiAoJCkge1xuXHRcdFx0cmV0dXJuICQoZWwpLmNsb25lKHRydWUpWzBdO1xuXHRcdH1cblx0XHRlbHNlIHtcblx0XHRcdHJldHVybiBlbC5jbG9uZU5vZGUodHJ1ZSk7XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gX3NhdmVJbnB1dENoZWNrZWRTdGF0ZShyb290KSB7XG5cdFx0dmFyIGlucHV0cyA9IHJvb3QuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2lucHV0Jyk7XG5cdFx0dmFyIGlkeCA9IGlucHV0cy5sZW5ndGg7XG5cblx0XHR3aGlsZSAoaWR4LS0pIHtcblx0XHRcdHZhciBlbCA9IGlucHV0c1tpZHhdO1xuXHRcdFx0ZWwuY2hlY2tlZCAmJiBzYXZlZElucHV0Q2hlY2tlZC5wdXNoKGVsKTtcblx0XHR9XG5cdH1cblxuXHRmdW5jdGlvbiBfbmV4dFRpY2soZm4pIHtcblx0XHRyZXR1cm4gc2V0VGltZW91dChmbiwgMCk7XG5cdH1cblxuXHRmdW5jdGlvbiBfY2FuY2VsTmV4dFRpY2soaWQpIHtcblx0XHRyZXR1cm4gY2xlYXJUaW1lb3V0KGlkKTtcblx0fVxuXG5cdC8vIEZpeGVkICM5NzM6XG5cdF9vbihkb2N1bWVudCwgJ3RvdWNobW92ZScsIGZ1bmN0aW9uIChldnQpIHtcblx0XHRpZiAoU29ydGFibGUuYWN0aXZlKSB7XG5cdFx0XHRldnQucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cdH0pO1xuXG5cdC8vIEV4cG9ydCB1dGlsc1xuXHRTb3J0YWJsZS51dGlscyA9IHtcblx0XHRvbjogX29uLFxuXHRcdG9mZjogX29mZixcblx0XHRjc3M6IF9jc3MsXG5cdFx0ZmluZDogX2ZpbmQsXG5cdFx0aXM6IGZ1bmN0aW9uIChlbCwgc2VsZWN0b3IpIHtcblx0XHRcdHJldHVybiAhIV9jbG9zZXN0KGVsLCBzZWxlY3RvciwgZWwpO1xuXHRcdH0sXG5cdFx0ZXh0ZW5kOiBfZXh0ZW5kLFxuXHRcdHRocm90dGxlOiBfdGhyb3R0bGUsXG5cdFx0Y2xvc2VzdDogX2Nsb3Nlc3QsXG5cdFx0dG9nZ2xlQ2xhc3M6IF90b2dnbGVDbGFzcyxcblx0XHRjbG9uZTogX2Nsb25lLFxuXHRcdGluZGV4OiBfaW5kZXgsXG5cdFx0bmV4dFRpY2s6IF9uZXh0VGljayxcblx0XHRjYW5jZWxOZXh0VGljazogX2NhbmNlbE5leHRUaWNrXG5cdH07XG5cblxuXHQvKipcblx0ICogQ3JlYXRlIHNvcnRhYmxlIGluc3RhbmNlXG5cdCAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9ICBlbFxuXHQgKiBAcGFyYW0ge09iamVjdH0gICAgICBbb3B0aW9uc11cblx0ICovXG5cdFNvcnRhYmxlLmNyZWF0ZSA9IGZ1bmN0aW9uIChlbCwgb3B0aW9ucykge1xuXHRcdHJldHVybiBuZXcgU29ydGFibGUoZWwsIG9wdGlvbnMpO1xuXHR9O1xuXG5cblx0Ly8gRXhwb3J0XG5cdFNvcnRhYmxlLnZlcnNpb24gPSAnMS43LjAnO1xuXHRyZXR1cm4gU29ydGFibGU7XG59KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL3NvcnRhYmxlanMvU29ydGFibGUuanNcbi8vIG1vZHVsZSBpZCA9IDEzMlxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiFcbiAqIFNlbGVjdDIgNC4wLjYtcmMuMVxuICogaHR0cHM6Ly9zZWxlY3QyLmdpdGh1Yi5pb1xuICpcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgbGljZW5zZVxuICogaHR0cHM6Ly9naXRodWIuY29tL3NlbGVjdDIvc2VsZWN0Mi9ibG9iL21hc3Rlci9MSUNFTlNFLm1kXG4gKi9cbjsoZnVuY3Rpb24gKGZhY3RvcnkpIHtcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgIC8vIEFNRC4gUmVnaXN0ZXIgYXMgYW4gYW5vbnltb3VzIG1vZHVsZS5cbiAgICBkZWZpbmUoWydqcXVlcnknXSwgZmFjdG9yeSk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIG1vZHVsZSA9PT0gJ29iamVjdCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICAvLyBOb2RlL0NvbW1vbkpTXG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAocm9vdCwgalF1ZXJ5KSB7XG4gICAgICBpZiAoalF1ZXJ5ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgLy8gcmVxdWlyZSgnalF1ZXJ5JykgcmV0dXJucyBhIGZhY3RvcnkgdGhhdCByZXF1aXJlcyB3aW5kb3cgdG9cbiAgICAgICAgLy8gYnVpbGQgYSBqUXVlcnkgaW5zdGFuY2UsIHdlIG5vcm1hbGl6ZSBob3cgd2UgdXNlIG1vZHVsZXNcbiAgICAgICAgLy8gdGhhdCByZXF1aXJlIHRoaXMgcGF0dGVybiBidXQgdGhlIHdpbmRvdyBwcm92aWRlZCBpcyBhIG5vb3BcbiAgICAgICAgLy8gaWYgaXQncyBkZWZpbmVkIChob3cganF1ZXJ5IHdvcmtzKVxuICAgICAgICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICBqUXVlcnkgPSByZXF1aXJlKCdqcXVlcnknKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICBqUXVlcnkgPSByZXF1aXJlKCdqcXVlcnknKShyb290KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZmFjdG9yeShqUXVlcnkpO1xuICAgICAgcmV0dXJuIGpRdWVyeTtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIC8vIEJyb3dzZXIgZ2xvYmFsc1xuICAgIGZhY3RvcnkoalF1ZXJ5KTtcbiAgfVxufSAoZnVuY3Rpb24gKGpRdWVyeSkge1xuICAvLyBUaGlzIGlzIG5lZWRlZCBzbyB3ZSBjYW4gY2F0Y2ggdGhlIEFNRCBsb2FkZXIgY29uZmlndXJhdGlvbiBhbmQgdXNlIGl0XG4gIC8vIFRoZSBpbm5lciBmaWxlIHNob3VsZCBiZSB3cmFwcGVkIChieSBgYmFubmVyLnN0YXJ0LmpzYCkgaW4gYSBmdW5jdGlvbiB0aGF0XG4gIC8vIHJldHVybnMgdGhlIEFNRCBsb2FkZXIgcmVmZXJlbmNlcy5cbiAgdmFyIFMyID0oZnVuY3Rpb24gKCkge1xuICAvLyBSZXN0b3JlIHRoZSBTZWxlY3QyIEFNRCBsb2FkZXIgc28gaXQgY2FuIGJlIHVzZWRcbiAgLy8gTmVlZGVkIG1vc3RseSBpbiB0aGUgbGFuZ3VhZ2UgZmlsZXMsIHdoZXJlIHRoZSBsb2FkZXIgaXMgbm90IGluc2VydGVkXG4gIGlmIChqUXVlcnkgJiYgalF1ZXJ5LmZuICYmIGpRdWVyeS5mbi5zZWxlY3QyICYmIGpRdWVyeS5mbi5zZWxlY3QyLmFtZCkge1xuICAgIHZhciBTMiA9IGpRdWVyeS5mbi5zZWxlY3QyLmFtZDtcbiAgfVxudmFyIFMyOyhmdW5jdGlvbiAoKSB7IGlmICghUzIgfHwgIVMyLnJlcXVpcmVqcykge1xuaWYgKCFTMikgeyBTMiA9IHt9OyB9IGVsc2UgeyByZXF1aXJlID0gUzI7IH1cbi8qKlxuICogQGxpY2Vuc2UgYWxtb25kIDAuMy4zIENvcHlyaWdodCBqUXVlcnkgRm91bmRhdGlvbiBhbmQgb3RoZXIgY29udHJpYnV0b3JzLlxuICogUmVsZWFzZWQgdW5kZXIgTUlUIGxpY2Vuc2UsIGh0dHA6Ly9naXRodWIuY29tL3JlcXVpcmVqcy9hbG1vbmQvTElDRU5TRVxuICovXG4vL0dvaW5nIHNsb3BweSB0byBhdm9pZCAndXNlIHN0cmljdCcgc3RyaW5nIGNvc3QsIGJ1dCBzdHJpY3QgcHJhY3RpY2VzIHNob3VsZFxuLy9iZSBmb2xsb3dlZC5cbi8qZ2xvYmFsIHNldFRpbWVvdXQ6IGZhbHNlICovXG5cbnZhciByZXF1aXJlanMsIHJlcXVpcmUsIGRlZmluZTtcbihmdW5jdGlvbiAodW5kZWYpIHtcbiAgICB2YXIgbWFpbiwgcmVxLCBtYWtlTWFwLCBoYW5kbGVycyxcbiAgICAgICAgZGVmaW5lZCA9IHt9LFxuICAgICAgICB3YWl0aW5nID0ge30sXG4gICAgICAgIGNvbmZpZyA9IHt9LFxuICAgICAgICBkZWZpbmluZyA9IHt9LFxuICAgICAgICBoYXNPd24gPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LFxuICAgICAgICBhcHMgPSBbXS5zbGljZSxcbiAgICAgICAganNTdWZmaXhSZWdFeHAgPSAvXFwuanMkLztcblxuICAgIGZ1bmN0aW9uIGhhc1Byb3Aob2JqLCBwcm9wKSB7XG4gICAgICAgIHJldHVybiBoYXNPd24uY2FsbChvYmosIHByb3ApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdpdmVuIGEgcmVsYXRpdmUgbW9kdWxlIG5hbWUsIGxpa2UgLi9zb21ldGhpbmcsIG5vcm1hbGl6ZSBpdCB0b1xuICAgICAqIGEgcmVhbCBuYW1lIHRoYXQgY2FuIGJlIG1hcHBlZCB0byBhIHBhdGguXG4gICAgICogQHBhcmFtIHtTdHJpbmd9IG5hbWUgdGhlIHJlbGF0aXZlIG5hbWVcbiAgICAgKiBAcGFyYW0ge1N0cmluZ30gYmFzZU5hbWUgYSByZWFsIG5hbWUgdGhhdCB0aGUgbmFtZSBhcmcgaXMgcmVsYXRpdmVcbiAgICAgKiB0by5cbiAgICAgKiBAcmV0dXJucyB7U3RyaW5nfSBub3JtYWxpemVkIG5hbWVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBub3JtYWxpemUobmFtZSwgYmFzZU5hbWUpIHtcbiAgICAgICAgdmFyIG5hbWVQYXJ0cywgbmFtZVNlZ21lbnQsIG1hcFZhbHVlLCBmb3VuZE1hcCwgbGFzdEluZGV4LFxuICAgICAgICAgICAgZm91bmRJLCBmb3VuZFN0YXJNYXAsIHN0YXJJLCBpLCBqLCBwYXJ0LCBub3JtYWxpemVkQmFzZVBhcnRzLFxuICAgICAgICAgICAgYmFzZVBhcnRzID0gYmFzZU5hbWUgJiYgYmFzZU5hbWUuc3BsaXQoXCIvXCIpLFxuICAgICAgICAgICAgbWFwID0gY29uZmlnLm1hcCxcbiAgICAgICAgICAgIHN0YXJNYXAgPSAobWFwICYmIG1hcFsnKiddKSB8fCB7fTtcblxuICAgICAgICAvL0FkanVzdCBhbnkgcmVsYXRpdmUgcGF0aHMuXG4gICAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgICAgICBuYW1lID0gbmFtZS5zcGxpdCgnLycpO1xuICAgICAgICAgICAgbGFzdEluZGV4ID0gbmFtZS5sZW5ndGggLSAxO1xuXG4gICAgICAgICAgICAvLyBJZiB3YW50aW5nIG5vZGUgSUQgY29tcGF0aWJpbGl0eSwgc3RyaXAgLmpzIGZyb20gZW5kXG4gICAgICAgICAgICAvLyBvZiBJRHMuIEhhdmUgdG8gZG8gdGhpcyBoZXJlLCBhbmQgbm90IGluIG5hbWVUb1VybFxuICAgICAgICAgICAgLy8gYmVjYXVzZSBub2RlIGFsbG93cyBlaXRoZXIgLmpzIG9yIG5vbiAuanMgdG8gbWFwXG4gICAgICAgICAgICAvLyB0byBzYW1lIGZpbGUuXG4gICAgICAgICAgICBpZiAoY29uZmlnLm5vZGVJZENvbXBhdCAmJiBqc1N1ZmZpeFJlZ0V4cC50ZXN0KG5hbWVbbGFzdEluZGV4XSkpIHtcbiAgICAgICAgICAgICAgICBuYW1lW2xhc3RJbmRleF0gPSBuYW1lW2xhc3RJbmRleF0ucmVwbGFjZShqc1N1ZmZpeFJlZ0V4cCwgJycpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTdGFydHMgd2l0aCBhICcuJyBzbyBuZWVkIHRoZSBiYXNlTmFtZVxuICAgICAgICAgICAgaWYgKG5hbWVbMF0uY2hhckF0KDApID09PSAnLicgJiYgYmFzZVBhcnRzKSB7XG4gICAgICAgICAgICAgICAgLy9Db252ZXJ0IGJhc2VOYW1lIHRvIGFycmF5LCBhbmQgbG9wIG9mZiB0aGUgbGFzdCBwYXJ0LFxuICAgICAgICAgICAgICAgIC8vc28gdGhhdCAuIG1hdGNoZXMgdGhhdCAnZGlyZWN0b3J5JyBhbmQgbm90IG5hbWUgb2YgdGhlIGJhc2VOYW1lJ3NcbiAgICAgICAgICAgICAgICAvL21vZHVsZS4gRm9yIGluc3RhbmNlLCBiYXNlTmFtZSBvZiAnb25lL3R3by90aHJlZScsIG1hcHMgdG9cbiAgICAgICAgICAgICAgICAvLydvbmUvdHdvL3RocmVlLmpzJywgYnV0IHdlIHdhbnQgdGhlIGRpcmVjdG9yeSwgJ29uZS90d28nIGZvclxuICAgICAgICAgICAgICAgIC8vdGhpcyBub3JtYWxpemF0aW9uLlxuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRCYXNlUGFydHMgPSBiYXNlUGFydHMuc2xpY2UoMCwgYmFzZVBhcnRzLmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgIG5hbWUgPSBub3JtYWxpemVkQmFzZVBhcnRzLmNvbmNhdChuYW1lKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9zdGFydCB0cmltRG90c1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IG5hbWUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwYXJ0ID0gbmFtZVtpXTtcbiAgICAgICAgICAgICAgICBpZiAocGFydCA9PT0gJy4nKSB7XG4gICAgICAgICAgICAgICAgICAgIG5hbWUuc3BsaWNlKGksIDEpO1xuICAgICAgICAgICAgICAgICAgICBpIC09IDE7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChwYXJ0ID09PSAnLi4nKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGF0IHRoZSBzdGFydCwgb3IgcHJldmlvdXMgdmFsdWUgaXMgc3RpbGwgLi4sXG4gICAgICAgICAgICAgICAgICAgIC8vIGtlZXAgdGhlbSBzbyB0aGF0IHdoZW4gY29udmVydGVkIHRvIGEgcGF0aCBpdCBtYXlcbiAgICAgICAgICAgICAgICAgICAgLy8gc3RpbGwgd29yayB3aGVuIGNvbnZlcnRlZCB0byBhIHBhdGgsIGV2ZW4gdGhvdWdoXG4gICAgICAgICAgICAgICAgICAgIC8vIGFzIGFuIElEIGl0IGlzIGxlc3MgdGhhbiBpZGVhbC4gSW4gbGFyZ2VyIHBvaW50XG4gICAgICAgICAgICAgICAgICAgIC8vIHJlbGVhc2VzLCBtYXkgYmUgYmV0dGVyIHRvIGp1c3Qga2ljayBvdXQgYW4gZXJyb3IuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpID09PSAwIHx8IChpID09PSAxICYmIG5hbWVbMl0gPT09ICcuLicpIHx8IG5hbWVbaSAtIDFdID09PSAnLi4nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbmFtZS5zcGxpY2UoaSAtIDEsIDIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaSAtPSAyO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy9lbmQgdHJpbURvdHNcblxuICAgICAgICAgICAgbmFtZSA9IG5hbWUuam9pbignLycpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9BcHBseSBtYXAgY29uZmlnIGlmIGF2YWlsYWJsZS5cbiAgICAgICAgaWYgKChiYXNlUGFydHMgfHwgc3Rhck1hcCkgJiYgbWFwKSB7XG4gICAgICAgICAgICBuYW1lUGFydHMgPSBuYW1lLnNwbGl0KCcvJyk7XG5cbiAgICAgICAgICAgIGZvciAoaSA9IG5hbWVQYXJ0cy5sZW5ndGg7IGkgPiAwOyBpIC09IDEpIHtcbiAgICAgICAgICAgICAgICBuYW1lU2VnbWVudCA9IG5hbWVQYXJ0cy5zbGljZSgwLCBpKS5qb2luKFwiL1wiKTtcblxuICAgICAgICAgICAgICAgIGlmIChiYXNlUGFydHMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy9GaW5kIHRoZSBsb25nZXN0IGJhc2VOYW1lIHNlZ21lbnQgbWF0Y2ggaW4gdGhlIGNvbmZpZy5cbiAgICAgICAgICAgICAgICAgICAgLy9TbywgZG8gam9pbnMgb24gdGhlIGJpZ2dlc3QgdG8gc21hbGxlc3QgbGVuZ3RocyBvZiBiYXNlUGFydHMuXG4gICAgICAgICAgICAgICAgICAgIGZvciAoaiA9IGJhc2VQYXJ0cy5sZW5ndGg7IGogPiAwOyBqIC09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG1hcFZhbHVlID0gbWFwW2Jhc2VQYXJ0cy5zbGljZSgwLCBqKS5qb2luKCcvJyldO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAvL2Jhc2VOYW1lIHNlZ21lbnQgaGFzICBjb25maWcsIGZpbmQgaWYgaXQgaGFzIG9uZSBmb3JcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vdGhpcyBuYW1lLlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwVmFsdWUgPSBtYXBWYWx1ZVtuYW1lU2VnbWVudF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG1hcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vTWF0Y2gsIHVwZGF0ZSBuYW1lIHRvIHRoZSBuZXcgdmFsdWUuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvdW5kTWFwID0gbWFwVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvdW5kSSA9IGk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChmb3VuZE1hcCkge1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvL0NoZWNrIGZvciBhIHN0YXIgbWFwIG1hdGNoLCBidXQganVzdCBob2xkIG9uIHRvIGl0LFxuICAgICAgICAgICAgICAgIC8vaWYgdGhlcmUgaXMgYSBzaG9ydGVyIHNlZ21lbnQgbWF0Y2ggbGF0ZXIgaW4gYSBtYXRjaGluZ1xuICAgICAgICAgICAgICAgIC8vY29uZmlnLCB0aGVuIGZhdm9yIG92ZXIgdGhpcyBzdGFyIG1hcC5cbiAgICAgICAgICAgICAgICBpZiAoIWZvdW5kU3Rhck1hcCAmJiBzdGFyTWFwICYmIHN0YXJNYXBbbmFtZVNlZ21lbnRdKSB7XG4gICAgICAgICAgICAgICAgICAgIGZvdW5kU3Rhck1hcCA9IHN0YXJNYXBbbmFtZVNlZ21lbnRdO1xuICAgICAgICAgICAgICAgICAgICBzdGFySSA9IGk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIWZvdW5kTWFwICYmIGZvdW5kU3Rhck1hcCkge1xuICAgICAgICAgICAgICAgIGZvdW5kTWFwID0gZm91bmRTdGFyTWFwO1xuICAgICAgICAgICAgICAgIGZvdW5kSSA9IHN0YXJJO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZm91bmRNYXApIHtcbiAgICAgICAgICAgICAgICBuYW1lUGFydHMuc3BsaWNlKDAsIGZvdW5kSSwgZm91bmRNYXApO1xuICAgICAgICAgICAgICAgIG5hbWUgPSBuYW1lUGFydHMuam9pbignLycpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5hbWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZVJlcXVpcmUocmVsTmFtZSwgZm9yY2VTeW5jKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvL0EgdmVyc2lvbiBvZiBhIHJlcXVpcmUgZnVuY3Rpb24gdGhhdCBwYXNzZXMgYSBtb2R1bGVOYW1lXG4gICAgICAgICAgICAvL3ZhbHVlIGZvciBpdGVtcyB0aGF0IG1heSBuZWVkIHRvXG4gICAgICAgICAgICAvL2xvb2sgdXAgcGF0aHMgcmVsYXRpdmUgdG8gdGhlIG1vZHVsZU5hbWVcbiAgICAgICAgICAgIHZhciBhcmdzID0gYXBzLmNhbGwoYXJndW1lbnRzLCAwKTtcblxuICAgICAgICAgICAgLy9JZiBmaXJzdCBhcmcgaXMgbm90IHJlcXVpcmUoJ3N0cmluZycpLCBhbmQgdGhlcmUgaXMgb25seVxuICAgICAgICAgICAgLy9vbmUgYXJnLCBpdCBpcyB0aGUgYXJyYXkgZm9ybSB3aXRob3V0IGEgY2FsbGJhY2suIEluc2VydFxuICAgICAgICAgICAgLy9hIG51bGwgc28gdGhhdCB0aGUgZm9sbG93aW5nIGNvbmNhdCBpcyBjb3JyZWN0LlxuICAgICAgICAgICAgaWYgKHR5cGVvZiBhcmdzWzBdICE9PSAnc3RyaW5nJyAmJiBhcmdzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgIGFyZ3MucHVzaChudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXEuYXBwbHkodW5kZWYsIGFyZ3MuY29uY2F0KFtyZWxOYW1lLCBmb3JjZVN5bmNdKSk7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZU5vcm1hbGl6ZShyZWxOYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZShuYW1lLCByZWxOYW1lKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlTG9hZChkZXBOYW1lKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgIGRlZmluZWRbZGVwTmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjYWxsRGVwKG5hbWUpIHtcbiAgICAgICAgaWYgKGhhc1Byb3Aod2FpdGluZywgbmFtZSkpIHtcbiAgICAgICAgICAgIHZhciBhcmdzID0gd2FpdGluZ1tuYW1lXTtcbiAgICAgICAgICAgIGRlbGV0ZSB3YWl0aW5nW25hbWVdO1xuICAgICAgICAgICAgZGVmaW5pbmdbbmFtZV0gPSB0cnVlO1xuICAgICAgICAgICAgbWFpbi5hcHBseSh1bmRlZiwgYXJncyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIWhhc1Byb3AoZGVmaW5lZCwgbmFtZSkgJiYgIWhhc1Byb3AoZGVmaW5pbmcsIG5hbWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vICcgKyBuYW1lKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGVmaW5lZFtuYW1lXTtcbiAgICB9XG5cbiAgICAvL1R1cm5zIGEgcGx1Z2luIXJlc291cmNlIHRvIFtwbHVnaW4sIHJlc291cmNlXVxuICAgIC8vd2l0aCB0aGUgcGx1Z2luIGJlaW5nIHVuZGVmaW5lZCBpZiB0aGUgbmFtZVxuICAgIC8vZGlkIG5vdCBoYXZlIGEgcGx1Z2luIHByZWZpeC5cbiAgICBmdW5jdGlvbiBzcGxpdFByZWZpeChuYW1lKSB7XG4gICAgICAgIHZhciBwcmVmaXgsXG4gICAgICAgICAgICBpbmRleCA9IG5hbWUgPyBuYW1lLmluZGV4T2YoJyEnKSA6IC0xO1xuICAgICAgICBpZiAoaW5kZXggPiAtMSkge1xuICAgICAgICAgICAgcHJlZml4ID0gbmFtZS5zdWJzdHJpbmcoMCwgaW5kZXgpO1xuICAgICAgICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyaW5nKGluZGV4ICsgMSwgbmFtZS5sZW5ndGgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbcHJlZml4LCBuYW1lXTtcbiAgICB9XG5cbiAgICAvL0NyZWF0ZXMgYSBwYXJ0cyBhcnJheSBmb3IgYSByZWxOYW1lIHdoZXJlIGZpcnN0IHBhcnQgaXMgcGx1Z2luIElELFxuICAgIC8vc2Vjb25kIHBhcnQgaXMgcmVzb3VyY2UgSUQuIEFzc3VtZXMgcmVsTmFtZSBoYXMgYWxyZWFkeSBiZWVuIG5vcm1hbGl6ZWQuXG4gICAgZnVuY3Rpb24gbWFrZVJlbFBhcnRzKHJlbE5hbWUpIHtcbiAgICAgICAgcmV0dXJuIHJlbE5hbWUgPyBzcGxpdFByZWZpeChyZWxOYW1lKSA6IFtdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ha2VzIGEgbmFtZSBtYXAsIG5vcm1hbGl6aW5nIHRoZSBuYW1lLCBhbmQgdXNpbmcgYSBwbHVnaW5cbiAgICAgKiBmb3Igbm9ybWFsaXphdGlvbiBpZiBuZWNlc3NhcnkuIEdyYWJzIGEgcmVmIHRvIHBsdWdpblxuICAgICAqIHRvbywgYXMgYW4gb3B0aW1pemF0aW9uLlxuICAgICAqL1xuICAgIG1ha2VNYXAgPSBmdW5jdGlvbiAobmFtZSwgcmVsUGFydHMpIHtcbiAgICAgICAgdmFyIHBsdWdpbixcbiAgICAgICAgICAgIHBhcnRzID0gc3BsaXRQcmVmaXgobmFtZSksXG4gICAgICAgICAgICBwcmVmaXggPSBwYXJ0c1swXSxcbiAgICAgICAgICAgIHJlbFJlc291cmNlTmFtZSA9IHJlbFBhcnRzWzFdO1xuXG4gICAgICAgIG5hbWUgPSBwYXJ0c1sxXTtcblxuICAgICAgICBpZiAocHJlZml4KSB7XG4gICAgICAgICAgICBwcmVmaXggPSBub3JtYWxpemUocHJlZml4LCByZWxSZXNvdXJjZU5hbWUpO1xuICAgICAgICAgICAgcGx1Z2luID0gY2FsbERlcChwcmVmaXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9Ob3JtYWxpemUgYWNjb3JkaW5nXG4gICAgICAgIGlmIChwcmVmaXgpIHtcbiAgICAgICAgICAgIGlmIChwbHVnaW4gJiYgcGx1Z2luLm5vcm1hbGl6ZSkge1xuICAgICAgICAgICAgICAgIG5hbWUgPSBwbHVnaW4ubm9ybWFsaXplKG5hbWUsIG1ha2VOb3JtYWxpemUocmVsUmVzb3VyY2VOYW1lKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG5hbWUgPSBub3JtYWxpemUobmFtZSwgcmVsUmVzb3VyY2VOYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5hbWUgPSBub3JtYWxpemUobmFtZSwgcmVsUmVzb3VyY2VOYW1lKTtcbiAgICAgICAgICAgIHBhcnRzID0gc3BsaXRQcmVmaXgobmFtZSk7XG4gICAgICAgICAgICBwcmVmaXggPSBwYXJ0c1swXTtcbiAgICAgICAgICAgIG5hbWUgPSBwYXJ0c1sxXTtcbiAgICAgICAgICAgIGlmIChwcmVmaXgpIHtcbiAgICAgICAgICAgICAgICBwbHVnaW4gPSBjYWxsRGVwKHByZWZpeCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvL1VzaW5nIHJpZGljdWxvdXMgcHJvcGVydHkgbmFtZXMgZm9yIHNwYWNlIHJlYXNvbnNcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGY6IHByZWZpeCA/IHByZWZpeCArICchJyArIG5hbWUgOiBuYW1lLCAvL2Z1bGxOYW1lXG4gICAgICAgICAgICBuOiBuYW1lLFxuICAgICAgICAgICAgcHI6IHByZWZpeCxcbiAgICAgICAgICAgIHA6IHBsdWdpblxuICAgICAgICB9O1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiBtYWtlQ29uZmlnKG5hbWUpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiAoY29uZmlnICYmIGNvbmZpZy5jb25maWcgJiYgY29uZmlnLmNvbmZpZ1tuYW1lXSkgfHwge307XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgaGFuZGxlcnMgPSB7XG4gICAgICAgIHJlcXVpcmU6IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4gbWFrZVJlcXVpcmUobmFtZSk7XG4gICAgICAgIH0sXG4gICAgICAgIGV4cG9ydHM6IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgICAgICAgICB2YXIgZSA9IGRlZmluZWRbbmFtZV07XG4gICAgICAgICAgICBpZiAodHlwZW9mIGUgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiAoZGVmaW5lZFtuYW1lXSA9IHt9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgbW9kdWxlOiBmdW5jdGlvbiAobmFtZSkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBpZDogbmFtZSxcbiAgICAgICAgICAgICAgICB1cmk6ICcnLFxuICAgICAgICAgICAgICAgIGV4cG9ydHM6IGRlZmluZWRbbmFtZV0sXG4gICAgICAgICAgICAgICAgY29uZmlnOiBtYWtlQ29uZmlnKG5hbWUpXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIG1haW4gPSBmdW5jdGlvbiAobmFtZSwgZGVwcywgY2FsbGJhY2ssIHJlbE5hbWUpIHtcbiAgICAgICAgdmFyIGNqc01vZHVsZSwgZGVwTmFtZSwgcmV0LCBtYXAsIGksIHJlbFBhcnRzLFxuICAgICAgICAgICAgYXJncyA9IFtdLFxuICAgICAgICAgICAgY2FsbGJhY2tUeXBlID0gdHlwZW9mIGNhbGxiYWNrLFxuICAgICAgICAgICAgdXNpbmdFeHBvcnRzO1xuXG4gICAgICAgIC8vVXNlIG5hbWUgaWYgbm8gcmVsTmFtZVxuICAgICAgICByZWxOYW1lID0gcmVsTmFtZSB8fCBuYW1lO1xuICAgICAgICByZWxQYXJ0cyA9IG1ha2VSZWxQYXJ0cyhyZWxOYW1lKTtcblxuICAgICAgICAvL0NhbGwgdGhlIGNhbGxiYWNrIHRvIGRlZmluZSB0aGUgbW9kdWxlLCBpZiBuZWNlc3NhcnkuXG4gICAgICAgIGlmIChjYWxsYmFja1R5cGUgPT09ICd1bmRlZmluZWQnIHx8IGNhbGxiYWNrVHlwZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgLy9QdWxsIG91dCB0aGUgZGVmaW5lZCBkZXBlbmRlbmNpZXMgYW5kIHBhc3MgdGhlIG9yZGVyZWRcbiAgICAgICAgICAgIC8vdmFsdWVzIHRvIHRoZSBjYWxsYmFjay5cbiAgICAgICAgICAgIC8vRGVmYXVsdCB0byBbcmVxdWlyZSwgZXhwb3J0cywgbW9kdWxlXSBpZiBubyBkZXBzXG4gICAgICAgICAgICBkZXBzID0gIWRlcHMubGVuZ3RoICYmIGNhbGxiYWNrLmxlbmd0aCA/IFsncmVxdWlyZScsICdleHBvcnRzJywgJ21vZHVsZSddIDogZGVwcztcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBkZXBzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICAgICAgbWFwID0gbWFrZU1hcChkZXBzW2ldLCByZWxQYXJ0cyk7XG4gICAgICAgICAgICAgICAgZGVwTmFtZSA9IG1hcC5mO1xuXG4gICAgICAgICAgICAgICAgLy9GYXN0IHBhdGggQ29tbW9uSlMgc3RhbmRhcmQgZGVwZW5kZW5jaWVzLlxuICAgICAgICAgICAgICAgIGlmIChkZXBOYW1lID09PSBcInJlcXVpcmVcIikge1xuICAgICAgICAgICAgICAgICAgICBhcmdzW2ldID0gaGFuZGxlcnMucmVxdWlyZShuYW1lKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGRlcE5hbWUgPT09IFwiZXhwb3J0c1wiKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vQ29tbW9uSlMgbW9kdWxlIHNwZWMgMS4xXG4gICAgICAgICAgICAgICAgICAgIGFyZ3NbaV0gPSBoYW5kbGVycy5leHBvcnRzKG5hbWUpO1xuICAgICAgICAgICAgICAgICAgICB1c2luZ0V4cG9ydHMgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZGVwTmFtZSA9PT0gXCJtb2R1bGVcIikge1xuICAgICAgICAgICAgICAgICAgICAvL0NvbW1vbkpTIG1vZHVsZSBzcGVjIDEuMVxuICAgICAgICAgICAgICAgICAgICBjanNNb2R1bGUgPSBhcmdzW2ldID0gaGFuZGxlcnMubW9kdWxlKG5hbWUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaGFzUHJvcChkZWZpbmVkLCBkZXBOYW1lKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzUHJvcCh3YWl0aW5nLCBkZXBOYW1lKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFzUHJvcChkZWZpbmluZywgZGVwTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgYXJnc1tpXSA9IGNhbGxEZXAoZGVwTmFtZSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtYXAucCkge1xuICAgICAgICAgICAgICAgICAgICBtYXAucC5sb2FkKG1hcC5uLCBtYWtlUmVxdWlyZShyZWxOYW1lLCB0cnVlKSwgbWFrZUxvYWQoZGVwTmFtZSksIHt9KTtcbiAgICAgICAgICAgICAgICAgICAgYXJnc1tpXSA9IGRlZmluZWRbZGVwTmFtZV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKG5hbWUgKyAnIG1pc3NpbmcgJyArIGRlcE5hbWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0ID0gY2FsbGJhY2sgPyBjYWxsYmFjay5hcHBseShkZWZpbmVkW25hbWVdLCBhcmdzKSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgaWYgKG5hbWUpIHtcbiAgICAgICAgICAgICAgICAvL0lmIHNldHRpbmcgZXhwb3J0cyB2aWEgXCJtb2R1bGVcIiBpcyBpbiBwbGF5LFxuICAgICAgICAgICAgICAgIC8vZmF2b3IgdGhhdCBvdmVyIHJldHVybiB2YWx1ZSBhbmQgZXhwb3J0cy4gQWZ0ZXIgdGhhdCxcbiAgICAgICAgICAgICAgICAvL2Zhdm9yIGEgbm9uLXVuZGVmaW5lZCByZXR1cm4gdmFsdWUgb3ZlciBleHBvcnRzIHVzZS5cbiAgICAgICAgICAgICAgICBpZiAoY2pzTW9kdWxlICYmIGNqc01vZHVsZS5leHBvcnRzICE9PSB1bmRlZiAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgY2pzTW9kdWxlLmV4cG9ydHMgIT09IGRlZmluZWRbbmFtZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgZGVmaW5lZFtuYW1lXSA9IGNqc01vZHVsZS5leHBvcnRzO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmV0ICE9PSB1bmRlZiB8fCAhdXNpbmdFeHBvcnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vVXNlIHRoZSByZXR1cm4gdmFsdWUgZnJvbSB0aGUgZnVuY3Rpb24uXG4gICAgICAgICAgICAgICAgICAgIGRlZmluZWRbbmFtZV0gPSByZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKG5hbWUpIHtcbiAgICAgICAgICAgIC8vTWF5IGp1c3QgYmUgYW4gb2JqZWN0IGRlZmluaXRpb24gZm9yIHRoZSBtb2R1bGUuIE9ubHlcbiAgICAgICAgICAgIC8vd29ycnkgYWJvdXQgZGVmaW5pbmcgaWYgaGF2ZSBhIG1vZHVsZSBuYW1lLlxuICAgICAgICAgICAgZGVmaW5lZFtuYW1lXSA9IGNhbGxiYWNrO1xuICAgICAgICB9XG4gICAgfTtcblxuICAgIHJlcXVpcmVqcyA9IHJlcXVpcmUgPSByZXEgPSBmdW5jdGlvbiAoZGVwcywgY2FsbGJhY2ssIHJlbE5hbWUsIGZvcmNlU3luYywgYWx0KSB7XG4gICAgICAgIGlmICh0eXBlb2YgZGVwcyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgaWYgKGhhbmRsZXJzW2RlcHNdKSB7XG4gICAgICAgICAgICAgICAgLy9jYWxsYmFjayBpbiB0aGlzIGNhc2UgaXMgcmVhbGx5IHJlbE5hbWVcbiAgICAgICAgICAgICAgICByZXR1cm4gaGFuZGxlcnNbZGVwc10oY2FsbGJhY2spO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy9KdXN0IHJldHVybiB0aGUgbW9kdWxlIHdhbnRlZC4gSW4gdGhpcyBzY2VuYXJpbywgdGhlXG4gICAgICAgICAgICAvL2RlcHMgYXJnIGlzIHRoZSBtb2R1bGUgbmFtZSwgYW5kIHNlY29uZCBhcmcgKGlmIHBhc3NlZClcbiAgICAgICAgICAgIC8vaXMganVzdCB0aGUgcmVsTmFtZS5cbiAgICAgICAgICAgIC8vTm9ybWFsaXplIG1vZHVsZSBuYW1lLCBpZiBpdCBjb250YWlucyAuIG9yIC4uXG4gICAgICAgICAgICByZXR1cm4gY2FsbERlcChtYWtlTWFwKGRlcHMsIG1ha2VSZWxQYXJ0cyhjYWxsYmFjaykpLmYpO1xuICAgICAgICB9IGVsc2UgaWYgKCFkZXBzLnNwbGljZSkge1xuICAgICAgICAgICAgLy9kZXBzIGlzIGEgY29uZmlnIG9iamVjdCwgbm90IGFuIGFycmF5LlxuICAgICAgICAgICAgY29uZmlnID0gZGVwcztcbiAgICAgICAgICAgIGlmIChjb25maWcuZGVwcykge1xuICAgICAgICAgICAgICAgIHJlcShjb25maWcuZGVwcywgY29uZmlnLmNhbGxiYWNrKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghY2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChjYWxsYmFjay5zcGxpY2UpIHtcbiAgICAgICAgICAgICAgICAvL2NhbGxiYWNrIGlzIGFuIGFycmF5LCB3aGljaCBtZWFucyBpdCBpcyBhIGRlcGVuZGVuY3kgbGlzdC5cbiAgICAgICAgICAgICAgICAvL0FkanVzdCBhcmdzIGlmIHRoZXJlIGFyZSBkZXBlbmRlbmNpZXNcbiAgICAgICAgICAgICAgICBkZXBzID0gY2FsbGJhY2s7XG4gICAgICAgICAgICAgICAgY2FsbGJhY2sgPSByZWxOYW1lO1xuICAgICAgICAgICAgICAgIHJlbE5hbWUgPSBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkZXBzID0gdW5kZWY7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvL1N1cHBvcnQgcmVxdWlyZShbJ2EnXSlcbiAgICAgICAgY2FsbGJhY2sgPSBjYWxsYmFjayB8fCBmdW5jdGlvbiAoKSB7fTtcblxuICAgICAgICAvL0lmIHJlbE5hbWUgaXMgYSBmdW5jdGlvbiwgaXQgaXMgYW4gZXJyYmFjayBoYW5kbGVyLFxuICAgICAgICAvL3NvIHJlbW92ZSBpdC5cbiAgICAgICAgaWYgKHR5cGVvZiByZWxOYW1lID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZWxOYW1lID0gZm9yY2VTeW5jO1xuICAgICAgICAgICAgZm9yY2VTeW5jID0gYWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy9TaW11bGF0ZSBhc3luYyBjYWxsYmFjaztcbiAgICAgICAgaWYgKGZvcmNlU3luYykge1xuICAgICAgICAgICAgbWFpbih1bmRlZiwgZGVwcywgY2FsbGJhY2ssIHJlbE5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy9Vc2luZyBhIG5vbi16ZXJvIHZhbHVlIGJlY2F1c2Ugb2YgY29uY2VybiBmb3Igd2hhdCBvbGQgYnJvd3NlcnNcbiAgICAgICAgICAgIC8vZG8sIGFuZCBsYXRlc3QgYnJvd3NlcnMgXCJ1cGdyYWRlXCIgdG8gNCBpZiBsb3dlciB2YWx1ZSBpcyB1c2VkOlxuICAgICAgICAgICAgLy9odHRwOi8vd3d3LndoYXR3Zy5vcmcvc3BlY3Mvd2ViLWFwcHMvY3VycmVudC13b3JrL211bHRpcGFnZS90aW1lcnMuaHRtbCNkb20td2luZG93dGltZXJzLXNldHRpbWVvdXQ6XG4gICAgICAgICAgICAvL0lmIHdhbnQgYSB2YWx1ZSBpbW1lZGlhdGVseSwgdXNlIHJlcXVpcmUoJ2lkJykgaW5zdGVhZCAtLSBzb21ldGhpbmdcbiAgICAgICAgICAgIC8vdGhhdCB3b3JrcyBpbiBhbG1vbmQgb24gdGhlIGdsb2JhbCBsZXZlbCwgYnV0IG5vdCBndWFyYW50ZWVkIGFuZFxuICAgICAgICAgICAgLy91bmxpa2VseSB0byB3b3JrIGluIG90aGVyIEFNRCBpbXBsZW1lbnRhdGlvbnMuXG4gICAgICAgICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBtYWluKHVuZGVmLCBkZXBzLCBjYWxsYmFjaywgcmVsTmFtZSk7XG4gICAgICAgICAgICB9LCA0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXE7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEp1c3QgZHJvcHMgdGhlIGNvbmZpZyBvbiB0aGUgZmxvb3IsIGJ1dCByZXR1cm5zIHJlcSBpbiBjYXNlXG4gICAgICogdGhlIGNvbmZpZyByZXR1cm4gdmFsdWUgaXMgdXNlZC5cbiAgICAgKi9cbiAgICByZXEuY29uZmlnID0gZnVuY3Rpb24gKGNmZykge1xuICAgICAgICByZXR1cm4gcmVxKGNmZyk7XG4gICAgfTtcblxuICAgIC8qKlxuICAgICAqIEV4cG9zZSBtb2R1bGUgcmVnaXN0cnkgZm9yIGRlYnVnZ2luZyBhbmQgdG9vbGluZ1xuICAgICAqL1xuICAgIHJlcXVpcmVqcy5fZGVmaW5lZCA9IGRlZmluZWQ7XG5cbiAgICBkZWZpbmUgPSBmdW5jdGlvbiAobmFtZSwgZGVwcywgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKHR5cGVvZiBuYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTZWUgYWxtb25kIFJFQURNRTogaW5jb3JyZWN0IG1vZHVsZSBidWlsZCwgbm8gbW9kdWxlIG5hbWUnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vVGhpcyBtb2R1bGUgbWF5IG5vdCBoYXZlIGRlcGVuZGVuY2llc1xuICAgICAgICBpZiAoIWRlcHMuc3BsaWNlKSB7XG4gICAgICAgICAgICAvL2RlcHMgaXMgbm90IGFuIGFycmF5LCBzbyBwcm9iYWJseSBtZWFuc1xuICAgICAgICAgICAgLy9hbiBvYmplY3QgbGl0ZXJhbCBvciBmYWN0b3J5IGZ1bmN0aW9uIGZvclxuICAgICAgICAgICAgLy90aGUgdmFsdWUuIEFkanVzdCBhcmdzLlxuICAgICAgICAgICAgY2FsbGJhY2sgPSBkZXBzO1xuICAgICAgICAgICAgZGVwcyA9IFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFoYXNQcm9wKGRlZmluZWQsIG5hbWUpICYmICFoYXNQcm9wKHdhaXRpbmcsIG5hbWUpKSB7XG4gICAgICAgICAgICB3YWl0aW5nW25hbWVdID0gW25hbWUsIGRlcHMsIGNhbGxiYWNrXTtcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBkZWZpbmUuYW1kID0ge1xuICAgICAgICBqUXVlcnk6IHRydWVcbiAgICB9O1xufSgpKTtcblxuUzIucmVxdWlyZWpzID0gcmVxdWlyZWpzO1MyLnJlcXVpcmUgPSByZXF1aXJlO1MyLmRlZmluZSA9IGRlZmluZTtcbn1cbn0oKSk7XG5TMi5kZWZpbmUoXCJhbG1vbmRcIiwgZnVuY3Rpb24oKXt9KTtcblxuLyogZ2xvYmFsIGpRdWVyeTpmYWxzZSwgJDpmYWxzZSAqL1xuUzIuZGVmaW5lKCdqcXVlcnknLFtdLGZ1bmN0aW9uICgpIHtcbiAgdmFyIF8kID0galF1ZXJ5IHx8ICQ7XG5cbiAgaWYgKF8kID09IG51bGwgJiYgY29uc29sZSAmJiBjb25zb2xlLmVycm9yKSB7XG4gICAgY29uc29sZS5lcnJvcihcbiAgICAgICdTZWxlY3QyOiBBbiBpbnN0YW5jZSBvZiBqUXVlcnkgb3IgYSBqUXVlcnktY29tcGF0aWJsZSBsaWJyYXJ5IHdhcyBub3QgJyArXG4gICAgICAnZm91bmQuIE1ha2Ugc3VyZSB0aGF0IHlvdSBhcmUgaW5jbHVkaW5nIGpRdWVyeSBiZWZvcmUgU2VsZWN0MiBvbiB5b3VyICcgK1xuICAgICAgJ3dlYiBwYWdlLidcbiAgICApO1xuICB9XG5cbiAgcmV0dXJuIF8kO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi91dGlscycsW1xuICAnanF1ZXJ5J1xuXSwgZnVuY3Rpb24gKCQpIHtcbiAgdmFyIFV0aWxzID0ge307XG5cbiAgVXRpbHMuRXh0ZW5kID0gZnVuY3Rpb24gKENoaWxkQ2xhc3MsIFN1cGVyQ2xhc3MpIHtcbiAgICB2YXIgX19oYXNQcm9wID0ge30uaGFzT3duUHJvcGVydHk7XG5cbiAgICBmdW5jdGlvbiBCYXNlQ29uc3RydWN0b3IgKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IENoaWxkQ2xhc3M7XG4gICAgfVxuXG4gICAgZm9yICh2YXIga2V5IGluIFN1cGVyQ2xhc3MpIHtcbiAgICAgIGlmIChfX2hhc1Byb3AuY2FsbChTdXBlckNsYXNzLCBrZXkpKSB7XG4gICAgICAgIENoaWxkQ2xhc3Nba2V5XSA9IFN1cGVyQ2xhc3Nba2V5XTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBCYXNlQ29uc3RydWN0b3IucHJvdG90eXBlID0gU3VwZXJDbGFzcy5wcm90b3R5cGU7XG4gICAgQ2hpbGRDbGFzcy5wcm90b3R5cGUgPSBuZXcgQmFzZUNvbnN0cnVjdG9yKCk7XG4gICAgQ2hpbGRDbGFzcy5fX3N1cGVyX18gPSBTdXBlckNsYXNzLnByb3RvdHlwZTtcblxuICAgIHJldHVybiBDaGlsZENsYXNzO1xuICB9O1xuXG4gIGZ1bmN0aW9uIGdldE1ldGhvZHMgKHRoZUNsYXNzKSB7XG4gICAgdmFyIHByb3RvID0gdGhlQ2xhc3MucHJvdG90eXBlO1xuXG4gICAgdmFyIG1ldGhvZHMgPSBbXTtcblxuICAgIGZvciAodmFyIG1ldGhvZE5hbWUgaW4gcHJvdG8pIHtcbiAgICAgIHZhciBtID0gcHJvdG9bbWV0aG9kTmFtZV07XG5cbiAgICAgIGlmICh0eXBlb2YgbSAhPT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgaWYgKG1ldGhvZE5hbWUgPT09ICdjb25zdHJ1Y3RvcicpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIG1ldGhvZHMucHVzaChtZXRob2ROYW1lKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWV0aG9kcztcbiAgfVxuXG4gIFV0aWxzLkRlY29yYXRlID0gZnVuY3Rpb24gKFN1cGVyQ2xhc3MsIERlY29yYXRvckNsYXNzKSB7XG4gICAgdmFyIGRlY29yYXRlZE1ldGhvZHMgPSBnZXRNZXRob2RzKERlY29yYXRvckNsYXNzKTtcbiAgICB2YXIgc3VwZXJNZXRob2RzID0gZ2V0TWV0aG9kcyhTdXBlckNsYXNzKTtcblxuICAgIGZ1bmN0aW9uIERlY29yYXRlZENsYXNzICgpIHtcbiAgICAgIHZhciB1bnNoaWZ0ID0gQXJyYXkucHJvdG90eXBlLnVuc2hpZnQ7XG5cbiAgICAgIHZhciBhcmdDb3VudCA9IERlY29yYXRvckNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3Rvci5sZW5ndGg7XG5cbiAgICAgIHZhciBjYWxsZWRDb25zdHJ1Y3RvciA9IFN1cGVyQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yO1xuXG4gICAgICBpZiAoYXJnQ291bnQgPiAwKSB7XG4gICAgICAgIHVuc2hpZnQuY2FsbChhcmd1bWVudHMsIFN1cGVyQ2xhc3MucHJvdG90eXBlLmNvbnN0cnVjdG9yKTtcblxuICAgICAgICBjYWxsZWRDb25zdHJ1Y3RvciA9IERlY29yYXRvckNsYXNzLnByb3RvdHlwZS5jb25zdHJ1Y3RvcjtcbiAgICAgIH1cblxuICAgICAgY2FsbGVkQ29uc3RydWN0b3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9XG5cbiAgICBEZWNvcmF0b3JDbGFzcy5kaXNwbGF5TmFtZSA9IFN1cGVyQ2xhc3MuZGlzcGxheU5hbWU7XG5cbiAgICBmdW5jdGlvbiBjdHIgKCkge1xuICAgICAgdGhpcy5jb25zdHJ1Y3RvciA9IERlY29yYXRlZENsYXNzO1xuICAgIH1cblxuICAgIERlY29yYXRlZENsYXNzLnByb3RvdHlwZSA9IG5ldyBjdHIoKTtcblxuICAgIGZvciAodmFyIG0gPSAwOyBtIDwgc3VwZXJNZXRob2RzLmxlbmd0aDsgbSsrKSB7XG4gICAgICB2YXIgc3VwZXJNZXRob2QgPSBzdXBlck1ldGhvZHNbbV07XG5cbiAgICAgIERlY29yYXRlZENsYXNzLnByb3RvdHlwZVtzdXBlck1ldGhvZF0gPVxuICAgICAgICBTdXBlckNsYXNzLnByb3RvdHlwZVtzdXBlck1ldGhvZF07XG4gICAgfVxuXG4gICAgdmFyIGNhbGxlZE1ldGhvZCA9IGZ1bmN0aW9uIChtZXRob2ROYW1lKSB7XG4gICAgICAvLyBTdHViIG91dCB0aGUgb3JpZ2luYWwgbWV0aG9kIGlmIGl0J3Mgbm90IGRlY29yYXRpbmcgYW4gYWN0dWFsIG1ldGhvZFxuICAgICAgdmFyIG9yaWdpbmFsTWV0aG9kID0gZnVuY3Rpb24gKCkge307XG5cbiAgICAgIGlmIChtZXRob2ROYW1lIGluIERlY29yYXRlZENsYXNzLnByb3RvdHlwZSkge1xuICAgICAgICBvcmlnaW5hbE1ldGhvZCA9IERlY29yYXRlZENsYXNzLnByb3RvdHlwZVttZXRob2ROYW1lXTtcbiAgICAgIH1cblxuICAgICAgdmFyIGRlY29yYXRlZE1ldGhvZCA9IERlY29yYXRvckNsYXNzLnByb3RvdHlwZVttZXRob2ROYW1lXTtcblxuICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHVuc2hpZnQgPSBBcnJheS5wcm90b3R5cGUudW5zaGlmdDtcblxuICAgICAgICB1bnNoaWZ0LmNhbGwoYXJndW1lbnRzLCBvcmlnaW5hbE1ldGhvZCk7XG5cbiAgICAgICAgcmV0dXJuIGRlY29yYXRlZE1ldGhvZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgICAgfTtcbiAgICB9O1xuXG4gICAgZm9yICh2YXIgZCA9IDA7IGQgPCBkZWNvcmF0ZWRNZXRob2RzLmxlbmd0aDsgZCsrKSB7XG4gICAgICB2YXIgZGVjb3JhdGVkTWV0aG9kID0gZGVjb3JhdGVkTWV0aG9kc1tkXTtcblxuICAgICAgRGVjb3JhdGVkQ2xhc3MucHJvdG90eXBlW2RlY29yYXRlZE1ldGhvZF0gPSBjYWxsZWRNZXRob2QoZGVjb3JhdGVkTWV0aG9kKTtcbiAgICB9XG5cbiAgICByZXR1cm4gRGVjb3JhdGVkQ2xhc3M7XG4gIH07XG5cbiAgdmFyIE9ic2VydmFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5saXN0ZW5lcnMgPSB7fTtcbiAgfTtcblxuICBPYnNlcnZhYmxlLnByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIChldmVudCwgY2FsbGJhY2spIHtcbiAgICB0aGlzLmxpc3RlbmVycyA9IHRoaXMubGlzdGVuZXJzIHx8IHt9O1xuXG4gICAgaWYgKGV2ZW50IGluIHRoaXMubGlzdGVuZXJzKSB7XG4gICAgICB0aGlzLmxpc3RlbmVyc1tldmVudF0ucHVzaChjYWxsYmFjayk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMubGlzdGVuZXJzW2V2ZW50XSA9IFtjYWxsYmFja107XG4gICAgfVxuICB9O1xuXG4gIE9ic2VydmFibGUucHJvdG90eXBlLnRyaWdnZXIgPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICB2YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG4gICAgdmFyIHBhcmFtcyA9IHNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKTtcblxuICAgIHRoaXMubGlzdGVuZXJzID0gdGhpcy5saXN0ZW5lcnMgfHwge307XG5cbiAgICAvLyBQYXJhbXMgc2hvdWxkIGFsd2F5cyBjb21lIGluIGFzIGFuIGFycmF5XG4gICAgaWYgKHBhcmFtcyA9PSBudWxsKSB7XG4gICAgICBwYXJhbXMgPSBbXTtcbiAgICB9XG5cbiAgICAvLyBJZiB0aGVyZSBhcmUgbm8gYXJndW1lbnRzIHRvIHRoZSBldmVudCwgdXNlIGEgdGVtcG9yYXJ5IG9iamVjdFxuICAgIGlmIChwYXJhbXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBwYXJhbXMucHVzaCh7fSk7XG4gICAgfVxuXG4gICAgLy8gU2V0IHRoZSBgX3R5cGVgIG9mIHRoZSBmaXJzdCBvYmplY3QgdG8gdGhlIGV2ZW50XG4gICAgcGFyYW1zWzBdLl90eXBlID0gZXZlbnQ7XG5cbiAgICBpZiAoZXZlbnQgaW4gdGhpcy5saXN0ZW5lcnMpIHtcbiAgICAgIHRoaXMuaW52b2tlKHRoaXMubGlzdGVuZXJzW2V2ZW50XSwgc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpKTtcbiAgICB9XG5cbiAgICBpZiAoJyonIGluIHRoaXMubGlzdGVuZXJzKSB7XG4gICAgICB0aGlzLmludm9rZSh0aGlzLmxpc3RlbmVyc1snKiddLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfTtcblxuICBPYnNlcnZhYmxlLnByb3RvdHlwZS5pbnZva2UgPSBmdW5jdGlvbiAobGlzdGVuZXJzLCBwYXJhbXMpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gbGlzdGVuZXJzLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBsaXN0ZW5lcnNbaV0uYXBwbHkodGhpcywgcGFyYW1zKTtcbiAgICB9XG4gIH07XG5cbiAgVXRpbHMuT2JzZXJ2YWJsZSA9IE9ic2VydmFibGU7XG5cbiAgVXRpbHMuZ2VuZXJhdGVDaGFycyA9IGZ1bmN0aW9uIChsZW5ndGgpIHtcbiAgICB2YXIgY2hhcnMgPSAnJztcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpKyspIHtcbiAgICAgIHZhciByYW5kb21DaGFyID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMzYpO1xuICAgICAgY2hhcnMgKz0gcmFuZG9tQ2hhci50b1N0cmluZygzNik7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNoYXJzO1xuICB9O1xuXG4gIFV0aWxzLmJpbmQgPSBmdW5jdGlvbiAoZnVuYywgY29udGV4dCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgICBmdW5jLmFwcGx5KGNvbnRleHQsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfTtcblxuICBVdGlscy5fY29udmVydERhdGEgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIGZvciAodmFyIG9yaWdpbmFsS2V5IGluIGRhdGEpIHtcbiAgICAgIHZhciBrZXlzID0gb3JpZ2luYWxLZXkuc3BsaXQoJy0nKTtcblxuICAgICAgdmFyIGRhdGFMZXZlbCA9IGRhdGE7XG5cbiAgICAgIGlmIChrZXlzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgZm9yICh2YXIgayA9IDA7IGsgPCBrZXlzLmxlbmd0aDsgaysrKSB7XG4gICAgICAgIHZhciBrZXkgPSBrZXlzW2tdO1xuXG4gICAgICAgIC8vIExvd2VyY2FzZSB0aGUgZmlyc3QgbGV0dGVyXG4gICAgICAgIC8vIEJ5IGRlZmF1bHQsIGRhc2gtc2VwYXJhdGVkIGJlY29tZXMgY2FtZWxDYXNlXG4gICAgICAgIGtleSA9IGtleS5zdWJzdHJpbmcoMCwgMSkudG9Mb3dlckNhc2UoKSArIGtleS5zdWJzdHJpbmcoMSk7XG5cbiAgICAgICAgaWYgKCEoa2V5IGluIGRhdGFMZXZlbCkpIHtcbiAgICAgICAgICBkYXRhTGV2ZWxba2V5XSA9IHt9O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGsgPT0ga2V5cy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgZGF0YUxldmVsW2tleV0gPSBkYXRhW29yaWdpbmFsS2V5XTtcbiAgICAgICAgfVxuXG4gICAgICAgIGRhdGFMZXZlbCA9IGRhdGFMZXZlbFtrZXldO1xuICAgICAgfVxuXG4gICAgICBkZWxldGUgZGF0YVtvcmlnaW5hbEtleV07XG4gICAgfVxuXG4gICAgcmV0dXJuIGRhdGE7XG4gIH07XG5cbiAgVXRpbHMuaGFzU2Nyb2xsID0gZnVuY3Rpb24gKGluZGV4LCBlbCkge1xuICAgIC8vIEFkYXB0ZWQgZnJvbSB0aGUgZnVuY3Rpb24gY3JlYXRlZCBieSBAU2hhZG93U2NyaXB0ZXJcbiAgICAvLyBhbmQgYWRhcHRlZCBieSBAQmlsbEJhcnJ5IG9uIHRoZSBTdGFjayBFeGNoYW5nZSBDb2RlIFJldmlldyB3ZWJzaXRlLlxuICAgIC8vIFRoZSBvcmlnaW5hbCBjb2RlIGNhbiBiZSBmb3VuZCBhdFxuICAgIC8vIGh0dHA6Ly9jb2RlcmV2aWV3LnN0YWNrZXhjaGFuZ2UuY29tL3EvMTMzMzhcbiAgICAvLyBhbmQgd2FzIGRlc2lnbmVkIHRvIGJlIHVzZWQgd2l0aCB0aGUgU2l6emxlIHNlbGVjdG9yIGVuZ2luZS5cblxuICAgIHZhciAkZWwgPSAkKGVsKTtcbiAgICB2YXIgb3ZlcmZsb3dYID0gZWwuc3R5bGUub3ZlcmZsb3dYO1xuICAgIHZhciBvdmVyZmxvd1kgPSBlbC5zdHlsZS5vdmVyZmxvd1k7XG5cbiAgICAvL0NoZWNrIGJvdGggeCBhbmQgeSBkZWNsYXJhdGlvbnNcbiAgICBpZiAob3ZlcmZsb3dYID09PSBvdmVyZmxvd1kgJiZcbiAgICAgICAgKG92ZXJmbG93WSA9PT0gJ2hpZGRlbicgfHwgb3ZlcmZsb3dZID09PSAndmlzaWJsZScpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgaWYgKG92ZXJmbG93WCA9PT0gJ3Njcm9sbCcgfHwgb3ZlcmZsb3dZID09PSAnc2Nyb2xsJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgcmV0dXJuICgkZWwuaW5uZXJIZWlnaHQoKSA8IGVsLnNjcm9sbEhlaWdodCB8fFxuICAgICAgJGVsLmlubmVyV2lkdGgoKSA8IGVsLnNjcm9sbFdpZHRoKTtcbiAgfTtcblxuICBVdGlscy5lc2NhcGVNYXJrdXAgPSBmdW5jdGlvbiAobWFya3VwKSB7XG4gICAgdmFyIHJlcGxhY2VNYXAgPSB7XG4gICAgICAnXFxcXCc6ICcmIzkyOycsXG4gICAgICAnJic6ICcmYW1wOycsXG4gICAgICAnPCc6ICcmbHQ7JyxcbiAgICAgICc+JzogJyZndDsnLFxuICAgICAgJ1wiJzogJyZxdW90OycsXG4gICAgICAnXFwnJzogJyYjMzk7JyxcbiAgICAgICcvJzogJyYjNDc7J1xuICAgIH07XG5cbiAgICAvLyBEbyBub3QgdHJ5IHRvIGVzY2FwZSB0aGUgbWFya3VwIGlmIGl0J3Mgbm90IGEgc3RyaW5nXG4gICAgaWYgKHR5cGVvZiBtYXJrdXAgIT09ICdzdHJpbmcnKSB7XG4gICAgICByZXR1cm4gbWFya3VwO1xuICAgIH1cblxuICAgIHJldHVybiBTdHJpbmcobWFya3VwKS5yZXBsYWNlKC9bJjw+XCInXFwvXFxcXF0vZywgZnVuY3Rpb24gKG1hdGNoKSB7XG4gICAgICByZXR1cm4gcmVwbGFjZU1hcFttYXRjaF07XG4gICAgfSk7XG4gIH07XG5cbiAgLy8gQXBwZW5kIGFuIGFycmF5IG9mIGpRdWVyeSBub2RlcyB0byBhIGdpdmVuIGVsZW1lbnQuXG4gIFV0aWxzLmFwcGVuZE1hbnkgPSBmdW5jdGlvbiAoJGVsZW1lbnQsICRub2Rlcykge1xuICAgIC8vIGpRdWVyeSAxLjcueCBkb2VzIG5vdCBzdXBwb3J0ICQuZm4uYXBwZW5kKCkgd2l0aCBhbiBhcnJheVxuICAgIC8vIEZhbGwgYmFjayB0byBhIGpRdWVyeSBvYmplY3QgY29sbGVjdGlvbiB1c2luZyAkLmZuLmFkZCgpXG4gICAgaWYgKCQuZm4uanF1ZXJ5LnN1YnN0cigwLCAzKSA9PT0gJzEuNycpIHtcbiAgICAgIHZhciAkanFOb2RlcyA9ICQoKTtcblxuICAgICAgJC5tYXAoJG5vZGVzLCBmdW5jdGlvbiAobm9kZSkge1xuICAgICAgICAkanFOb2RlcyA9ICRqcU5vZGVzLmFkZChub2RlKTtcbiAgICAgIH0pO1xuXG4gICAgICAkbm9kZXMgPSAkanFOb2RlcztcbiAgICB9XG5cbiAgICAkZWxlbWVudC5hcHBlbmQoJG5vZGVzKTtcbiAgfTtcblxuICAvLyBDYWNoZSBvYmplY3RzIGluIFV0aWxzLl9fY2FjaGUgaW5zdGVhZCBvZiAkLmRhdGEgKHNlZSAjNDM0NilcbiAgVXRpbHMuX19jYWNoZSA9IHt9O1xuXG4gIHZhciBpZCA9IDA7XG4gIFV0aWxzLkdldFVuaXF1ZUVsZW1lbnRJZCA9IGZ1bmN0aW9uIChlbGVtZW50KSB7XG4gICAgLy8gR2V0IGEgdW5pcXVlIGVsZW1lbnQgSWQuIElmIGVsZW1lbnQgaGFzIG5vIGlkLCBcbiAgICAvLyBjcmVhdGVzIGEgbmV3IHVuaXF1ZSBudW1iZXIsIHN0b3JlcyBpdCBpbiB0aGUgaWQgXG4gICAgLy8gYXR0cmlidXRlIGFuZCByZXR1cm5zIHRoZSBuZXcgaWQuIFxuICAgIC8vIElmIGFuIGlkIGFscmVhZHkgZXhpc3RzLCBpdCBzaW1wbHkgcmV0dXJucyBpdC5cblxuICAgIHZhciBzZWxlY3QySWQgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS1zZWxlY3QyLWlkJyk7XG4gICAgaWYgKHNlbGVjdDJJZCA9PSBudWxsKSB7XG4gICAgICAvLyBJZiBlbGVtZW50IGhhcyBpZCwgdXNlIGl0LlxuICAgICAgaWYgKGVsZW1lbnQuaWQpIHtcbiAgICAgICAgc2VsZWN0MklkID0gZWxlbWVudC5pZDtcbiAgICAgICAgZWxlbWVudC5zZXRBdHRyaWJ1dGUoJ2RhdGEtc2VsZWN0Mi1pZCcsIHNlbGVjdDJJZCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBlbGVtZW50LnNldEF0dHJpYnV0ZSgnZGF0YS1zZWxlY3QyLWlkJywgKytpZCk7XG4gICAgICAgIHNlbGVjdDJJZCA9IGlkLnRvU3RyaW5nKCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBzZWxlY3QySWQ7XG4gIH07XG5cbiAgVXRpbHMuU3RvcmVEYXRhID0gZnVuY3Rpb24gKGVsZW1lbnQsIG5hbWUsIHZhbHVlKSB7XG4gICAgLy8gU3RvcmVzIGFuIGl0ZW0gaW4gdGhlIGNhY2hlIGZvciBhIHNwZWNpZmllZCBlbGVtZW50LlxuICAgIC8vIG5hbWUgaXMgdGhlIGNhY2hlIGtleS4gICAgXG4gICAgdmFyIGlkID0gVXRpbHMuR2V0VW5pcXVlRWxlbWVudElkKGVsZW1lbnQpO1xuICAgIGlmICghVXRpbHMuX19jYWNoZVtpZF0pIHtcbiAgICAgIFV0aWxzLl9fY2FjaGVbaWRdID0ge307XG4gICAgfVxuXG4gICAgVXRpbHMuX19jYWNoZVtpZF1bbmFtZV0gPSB2YWx1ZTtcbiAgfTtcblxuICBVdGlscy5HZXREYXRhID0gZnVuY3Rpb24gKGVsZW1lbnQsIG5hbWUpIHtcbiAgICAvLyBSZXRyaWV2ZXMgYSB2YWx1ZSBmcm9tIHRoZSBjYWNoZSBieSBpdHMga2V5IChuYW1lKVxuICAgIC8vIG5hbWUgaXMgb3B0aW9uYWwuIElmIG5vIG5hbWUgc3BlY2lmaWVkLCByZXR1cm4gXG4gICAgLy8gYWxsIGNhY2hlIGl0ZW1zIGZvciB0aGUgc3BlY2lmaWVkIGVsZW1lbnQuXG4gICAgLy8gYW5kIGZvciBhIHNwZWNpZmllZCBlbGVtZW50LlxuICAgIHZhciBpZCA9IFV0aWxzLkdldFVuaXF1ZUVsZW1lbnRJZChlbGVtZW50KTtcbiAgICBpZiAobmFtZSkge1xuICAgICAgaWYgKFV0aWxzLl9fY2FjaGVbaWRdKSB7XG4gICAgICAgIHJldHVybiBVdGlscy5fX2NhY2hlW2lkXVtuYW1lXSAhPSBudWxsID8gXG5cdCAgICAgIFV0aWxzLl9fY2FjaGVbaWRdW25hbWVdOlxuXHQgICAgICAkKGVsZW1lbnQpLmRhdGEobmFtZSk7IC8vIEZhbGxiYWNrIHRvIEhUTUw1IGRhdGEgYXR0cmlicy5cbiAgICAgIH1cbiAgICAgIHJldHVybiAkKGVsZW1lbnQpLmRhdGEobmFtZSk7IC8vIEZhbGxiYWNrIHRvIEhUTUw1IGRhdGEgYXR0cmlicy5cbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFV0aWxzLl9fY2FjaGVbaWRdO1x0XHRcdCAgIFxuICAgIH1cbiAgfTtcblxuICBVdGlscy5SZW1vdmVEYXRhID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgICAvLyBSZW1vdmVzIGFsbCBjYWNoZWQgaXRlbXMgZm9yIGEgc3BlY2lmaWVkIGVsZW1lbnQuXG4gICAgdmFyIGlkID0gVXRpbHMuR2V0VW5pcXVlRWxlbWVudElkKGVsZW1lbnQpO1xuICAgIGlmIChVdGlscy5fX2NhY2hlW2lkXSAhPSBudWxsKSB7XG4gICAgICBkZWxldGUgVXRpbHMuX19jYWNoZVtpZF07XG4gICAgfVxuICB9O1xuXG4gIHJldHVybiBVdGlscztcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIvcmVzdWx0cycsW1xuICAnanF1ZXJ5JyxcbiAgJy4vdXRpbHMnXG5dLCBmdW5jdGlvbiAoJCwgVXRpbHMpIHtcbiAgZnVuY3Rpb24gUmVzdWx0cyAoJGVsZW1lbnQsIG9wdGlvbnMsIGRhdGFBZGFwdGVyKSB7XG4gICAgdGhpcy4kZWxlbWVudCA9ICRlbGVtZW50O1xuICAgIHRoaXMuZGF0YSA9IGRhdGFBZGFwdGVyO1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cbiAgICBSZXN1bHRzLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5jYWxsKHRoaXMpO1xuICB9XG5cbiAgVXRpbHMuRXh0ZW5kKFJlc3VsdHMsIFV0aWxzLk9ic2VydmFibGUpO1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJHJlc3VsdHMgPSAkKFxuICAgICAgJzx1bCBjbGFzcz1cInNlbGVjdDItcmVzdWx0c19fb3B0aW9uc1wiIHJvbGU9XCJ0cmVlXCI+PC91bD4nXG4gICAgKTtcblxuICAgIGlmICh0aGlzLm9wdGlvbnMuZ2V0KCdtdWx0aXBsZScpKSB7XG4gICAgICAkcmVzdWx0cy5hdHRyKCdhcmlhLW11bHRpc2VsZWN0YWJsZScsICd0cnVlJyk7XG4gICAgfVxuXG4gICAgdGhpcy4kcmVzdWx0cyA9ICRyZXN1bHRzO1xuXG4gICAgcmV0dXJuICRyZXN1bHRzO1xuICB9O1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuJHJlc3VsdHMuZW1wdHkoKTtcbiAgfTtcblxuICBSZXN1bHRzLnByb3RvdHlwZS5kaXNwbGF5TWVzc2FnZSA9IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICB2YXIgZXNjYXBlTWFya3VwID0gdGhpcy5vcHRpb25zLmdldCgnZXNjYXBlTWFya3VwJyk7XG5cbiAgICB0aGlzLmNsZWFyKCk7XG4gICAgdGhpcy5oaWRlTG9hZGluZygpO1xuXG4gICAgdmFyICRtZXNzYWdlID0gJChcbiAgICAgICc8bGkgcm9sZT1cInRyZWVpdGVtXCIgYXJpYS1saXZlPVwiYXNzZXJ0aXZlXCInICtcbiAgICAgICcgY2xhc3M9XCJzZWxlY3QyLXJlc3VsdHNfX29wdGlvblwiPjwvbGk+J1xuICAgICk7XG5cbiAgICB2YXIgbWVzc2FnZSA9IHRoaXMub3B0aW9ucy5nZXQoJ3RyYW5zbGF0aW9ucycpLmdldChwYXJhbXMubWVzc2FnZSk7XG5cbiAgICAkbWVzc2FnZS5hcHBlbmQoXG4gICAgICBlc2NhcGVNYXJrdXAoXG4gICAgICAgIG1lc3NhZ2UocGFyYW1zLmFyZ3MpXG4gICAgICApXG4gICAgKTtcblxuICAgICRtZXNzYWdlWzBdLmNsYXNzTmFtZSArPSAnIHNlbGVjdDItcmVzdWx0c19fbWVzc2FnZSc7XG5cbiAgICB0aGlzLiRyZXN1bHRzLmFwcGVuZCgkbWVzc2FnZSk7XG4gIH07XG5cbiAgUmVzdWx0cy5wcm90b3R5cGUuaGlkZU1lc3NhZ2VzID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuJHJlc3VsdHMuZmluZCgnLnNlbGVjdDItcmVzdWx0c19fbWVzc2FnZScpLnJlbW92ZSgpO1xuICB9O1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLmFwcGVuZCA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgdGhpcy5oaWRlTG9hZGluZygpO1xuXG4gICAgdmFyICRvcHRpb25zID0gW107XG5cbiAgICBpZiAoZGF0YS5yZXN1bHRzID09IG51bGwgfHwgZGF0YS5yZXN1bHRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgaWYgKHRoaXMuJHJlc3VsdHMuY2hpbGRyZW4oKS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdGhpcy50cmlnZ2VyKCdyZXN1bHRzOm1lc3NhZ2UnLCB7XG4gICAgICAgICAgbWVzc2FnZTogJ25vUmVzdWx0cydcbiAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBkYXRhLnJlc3VsdHMgPSB0aGlzLnNvcnQoZGF0YS5yZXN1bHRzKTtcblxuICAgIGZvciAodmFyIGQgPSAwOyBkIDwgZGF0YS5yZXN1bHRzLmxlbmd0aDsgZCsrKSB7XG4gICAgICB2YXIgaXRlbSA9IGRhdGEucmVzdWx0c1tkXTtcblxuICAgICAgdmFyICRvcHRpb24gPSB0aGlzLm9wdGlvbihpdGVtKTtcblxuICAgICAgJG9wdGlvbnMucHVzaCgkb3B0aW9uKTtcbiAgICB9XG5cbiAgICB0aGlzLiRyZXN1bHRzLmFwcGVuZCgkb3B0aW9ucyk7XG4gIH07XG5cbiAgUmVzdWx0cy5wcm90b3R5cGUucG9zaXRpb24gPSBmdW5jdGlvbiAoJHJlc3VsdHMsICRkcm9wZG93bikge1xuICAgIHZhciAkcmVzdWx0c0NvbnRhaW5lciA9ICRkcm9wZG93bi5maW5kKCcuc2VsZWN0Mi1yZXN1bHRzJyk7XG4gICAgJHJlc3VsdHNDb250YWluZXIuYXBwZW5kKCRyZXN1bHRzKTtcbiAgfTtcblxuICBSZXN1bHRzLnByb3RvdHlwZS5zb3J0ID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICB2YXIgc29ydGVyID0gdGhpcy5vcHRpb25zLmdldCgnc29ydGVyJyk7XG5cbiAgICByZXR1cm4gc29ydGVyKGRhdGEpO1xuICB9O1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLmhpZ2hsaWdodEZpcnN0SXRlbSA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJG9wdGlvbnMgPSB0aGlzLiRyZXN1bHRzXG4gICAgICAuZmluZCgnLnNlbGVjdDItcmVzdWx0c19fb3B0aW9uW2FyaWEtc2VsZWN0ZWRdJyk7XG5cbiAgICB2YXIgJHNlbGVjdGVkID0gJG9wdGlvbnMuZmlsdGVyKCdbYXJpYS1zZWxlY3RlZD10cnVlXScpO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlcmUgYXJlIGFueSBzZWxlY3RlZCBvcHRpb25zXG4gICAgaWYgKCRzZWxlY3RlZC5sZW5ndGggPiAwKSB7XG4gICAgICAvLyBJZiB0aGVyZSBhcmUgc2VsZWN0ZWQgb3B0aW9ucywgaGlnaGxpZ2h0IHRoZSBmaXJzdFxuICAgICAgJHNlbGVjdGVkLmZpcnN0KCkudHJpZ2dlcignbW91c2VlbnRlcicpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiB0aGVyZSBhcmUgbm8gc2VsZWN0ZWQgb3B0aW9ucywgaGlnaGxpZ2h0IHRoZSBmaXJzdCBvcHRpb25cbiAgICAgIC8vIGluIHRoZSBkcm9wZG93blxuICAgICAgJG9wdGlvbnMuZmlyc3QoKS50cmlnZ2VyKCdtb3VzZWVudGVyJyk7XG4gICAgfVxuXG4gICAgdGhpcy5lbnN1cmVIaWdobGlnaHRWaXNpYmxlKCk7XG4gIH07XG5cbiAgUmVzdWx0cy5wcm90b3R5cGUuc2V0Q2xhc3NlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB0aGlzLmRhdGEuY3VycmVudChmdW5jdGlvbiAoc2VsZWN0ZWQpIHtcbiAgICAgIHZhciBzZWxlY3RlZElkcyA9ICQubWFwKHNlbGVjdGVkLCBmdW5jdGlvbiAocykge1xuICAgICAgICByZXR1cm4gcy5pZC50b1N0cmluZygpO1xuICAgICAgfSk7XG5cbiAgICAgIHZhciAkb3B0aW9ucyA9IHNlbGYuJHJlc3VsdHNcbiAgICAgICAgLmZpbmQoJy5zZWxlY3QyLXJlc3VsdHNfX29wdGlvblthcmlhLXNlbGVjdGVkXScpO1xuXG4gICAgICAkb3B0aW9ucy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyICRvcHRpb24gPSAkKHRoaXMpO1xuXG4gICAgICAgIHZhciBpdGVtID0gVXRpbHMuR2V0RGF0YSh0aGlzLCAnZGF0YScpO1xuXG4gICAgICAgIC8vIGlkIG5lZWRzIHRvIGJlIGNvbnZlcnRlZCB0byBhIHN0cmluZyB3aGVuIGNvbXBhcmluZ1xuICAgICAgICB2YXIgaWQgPSAnJyArIGl0ZW0uaWQ7XG5cbiAgICAgICAgaWYgKChpdGVtLmVsZW1lbnQgIT0gbnVsbCAmJiBpdGVtLmVsZW1lbnQuc2VsZWN0ZWQpIHx8XG4gICAgICAgICAgICAoaXRlbS5lbGVtZW50ID09IG51bGwgJiYgJC5pbkFycmF5KGlkLCBzZWxlY3RlZElkcykgPiAtMSkpIHtcbiAgICAgICAgICAkb3B0aW9uLmF0dHIoJ2FyaWEtc2VsZWN0ZWQnLCAndHJ1ZScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICRvcHRpb24uYXR0cignYXJpYS1zZWxlY3RlZCcsICdmYWxzZScpO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIH0pO1xuICB9O1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLnNob3dMb2FkaW5nID0gZnVuY3Rpb24gKHBhcmFtcykge1xuICAgIHRoaXMuaGlkZUxvYWRpbmcoKTtcblxuICAgIHZhciBsb2FkaW5nTW9yZSA9IHRoaXMub3B0aW9ucy5nZXQoJ3RyYW5zbGF0aW9ucycpLmdldCgnc2VhcmNoaW5nJyk7XG5cbiAgICB2YXIgbG9hZGluZyA9IHtcbiAgICAgIGRpc2FibGVkOiB0cnVlLFxuICAgICAgbG9hZGluZzogdHJ1ZSxcbiAgICAgIHRleHQ6IGxvYWRpbmdNb3JlKHBhcmFtcylcbiAgICB9O1xuICAgIHZhciAkbG9hZGluZyA9IHRoaXMub3B0aW9uKGxvYWRpbmcpO1xuICAgICRsb2FkaW5nLmNsYXNzTmFtZSArPSAnIGxvYWRpbmctcmVzdWx0cyc7XG5cbiAgICB0aGlzLiRyZXN1bHRzLnByZXBlbmQoJGxvYWRpbmcpO1xuICB9O1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLmhpZGVMb2FkaW5nID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuJHJlc3VsdHMuZmluZCgnLmxvYWRpbmctcmVzdWx0cycpLnJlbW92ZSgpO1xuICB9O1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLm9wdGlvbiA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgdmFyIG9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpJyk7XG4gICAgb3B0aW9uLmNsYXNzTmFtZSA9ICdzZWxlY3QyLXJlc3VsdHNfX29wdGlvbic7XG5cbiAgICB2YXIgYXR0cnMgPSB7XG4gICAgICAncm9sZSc6ICd0cmVlaXRlbScsXG4gICAgICAnYXJpYS1zZWxlY3RlZCc6ICdmYWxzZSdcbiAgICB9O1xuXG4gICAgaWYgKGRhdGEuZGlzYWJsZWQpIHtcbiAgICAgIGRlbGV0ZSBhdHRyc1snYXJpYS1zZWxlY3RlZCddO1xuICAgICAgYXR0cnNbJ2FyaWEtZGlzYWJsZWQnXSA9ICd0cnVlJztcbiAgICB9XG5cbiAgICBpZiAoZGF0YS5pZCA9PSBudWxsKSB7XG4gICAgICBkZWxldGUgYXR0cnNbJ2FyaWEtc2VsZWN0ZWQnXTtcbiAgICB9XG5cbiAgICBpZiAoZGF0YS5fcmVzdWx0SWQgIT0gbnVsbCkge1xuICAgICAgb3B0aW9uLmlkID0gZGF0YS5fcmVzdWx0SWQ7XG4gICAgfVxuXG4gICAgaWYgKGRhdGEudGl0bGUpIHtcbiAgICAgIG9wdGlvbi50aXRsZSA9IGRhdGEudGl0bGU7XG4gICAgfVxuXG4gICAgaWYgKGRhdGEuY2hpbGRyZW4pIHtcbiAgICAgIGF0dHJzLnJvbGUgPSAnZ3JvdXAnO1xuICAgICAgYXR0cnNbJ2FyaWEtbGFiZWwnXSA9IGRhdGEudGV4dDtcbiAgICAgIGRlbGV0ZSBhdHRyc1snYXJpYS1zZWxlY3RlZCddO1xuICAgIH1cblxuICAgIGZvciAodmFyIGF0dHIgaW4gYXR0cnMpIHtcbiAgICAgIHZhciB2YWwgPSBhdHRyc1thdHRyXTtcblxuICAgICAgb3B0aW9uLnNldEF0dHJpYnV0ZShhdHRyLCB2YWwpO1xuICAgIH1cblxuICAgIGlmIChkYXRhLmNoaWxkcmVuKSB7XG4gICAgICB2YXIgJG9wdGlvbiA9ICQob3B0aW9uKTtcblxuICAgICAgdmFyIGxhYmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3Ryb25nJyk7XG4gICAgICBsYWJlbC5jbGFzc05hbWUgPSAnc2VsZWN0Mi1yZXN1bHRzX19ncm91cCc7XG5cbiAgICAgIHZhciAkbGFiZWwgPSAkKGxhYmVsKTtcbiAgICAgIHRoaXMudGVtcGxhdGUoZGF0YSwgbGFiZWwpO1xuXG4gICAgICB2YXIgJGNoaWxkcmVuID0gW107XG5cbiAgICAgIGZvciAodmFyIGMgPSAwOyBjIDwgZGF0YS5jaGlsZHJlbi5sZW5ndGg7IGMrKykge1xuICAgICAgICB2YXIgY2hpbGQgPSBkYXRhLmNoaWxkcmVuW2NdO1xuXG4gICAgICAgIHZhciAkY2hpbGQgPSB0aGlzLm9wdGlvbihjaGlsZCk7XG5cbiAgICAgICAgJGNoaWxkcmVuLnB1c2goJGNoaWxkKTtcbiAgICAgIH1cblxuICAgICAgdmFyICRjaGlsZHJlbkNvbnRhaW5lciA9ICQoJzx1bD48L3VsPicsIHtcbiAgICAgICAgJ2NsYXNzJzogJ3NlbGVjdDItcmVzdWx0c19fb3B0aW9ucyBzZWxlY3QyLXJlc3VsdHNfX29wdGlvbnMtLW5lc3RlZCdcbiAgICAgIH0pO1xuXG4gICAgICAkY2hpbGRyZW5Db250YWluZXIuYXBwZW5kKCRjaGlsZHJlbik7XG5cbiAgICAgICRvcHRpb24uYXBwZW5kKGxhYmVsKTtcbiAgICAgICRvcHRpb24uYXBwZW5kKCRjaGlsZHJlbkNvbnRhaW5lcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudGVtcGxhdGUoZGF0YSwgb3B0aW9uKTtcbiAgICB9XG5cbiAgICBVdGlscy5TdG9yZURhdGEob3B0aW9uLCAnZGF0YScsIGRhdGEpO1xuXG4gICAgcmV0dXJuIG9wdGlvbjtcbiAgfTtcblxuICBSZXN1bHRzLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24gKGNvbnRhaW5lciwgJGNvbnRhaW5lcikge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHZhciBpZCA9IGNvbnRhaW5lci5pZCArICctcmVzdWx0cyc7XG5cbiAgICB0aGlzLiRyZXN1bHRzLmF0dHIoJ2lkJywgaWQpO1xuXG4gICAgY29udGFpbmVyLm9uKCdyZXN1bHRzOmFsbCcsIGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgIHNlbGYuY2xlYXIoKTtcbiAgICAgIHNlbGYuYXBwZW5kKHBhcmFtcy5kYXRhKTtcblxuICAgICAgaWYgKGNvbnRhaW5lci5pc09wZW4oKSkge1xuICAgICAgICBzZWxmLnNldENsYXNzZXMoKTtcbiAgICAgICAgc2VsZi5oaWdobGlnaHRGaXJzdEl0ZW0oKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbigncmVzdWx0czphcHBlbmQnLCBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICBzZWxmLmFwcGVuZChwYXJhbXMuZGF0YSk7XG5cbiAgICAgIGlmIChjb250YWluZXIuaXNPcGVuKCkpIHtcbiAgICAgICAgc2VsZi5zZXRDbGFzc2VzKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ3F1ZXJ5JywgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgc2VsZi5oaWRlTWVzc2FnZXMoKTtcbiAgICAgIHNlbGYuc2hvd0xvYWRpbmcocGFyYW1zKTtcbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbignc2VsZWN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKCFjb250YWluZXIuaXNPcGVuKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzZWxmLnNldENsYXNzZXMoKTtcbiAgICAgIHNlbGYuaGlnaGxpZ2h0Rmlyc3RJdGVtKCk7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ3Vuc2VsZWN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKCFjb250YWluZXIuaXNPcGVuKCkpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzZWxmLnNldENsYXNzZXMoKTtcbiAgICAgIHNlbGYuaGlnaGxpZ2h0Rmlyc3RJdGVtKCk7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ29wZW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBXaGVuIHRoZSBkcm9wZG93biBpcyBvcGVuLCBhcmlhLWV4cGVuZGVkPVwidHJ1ZVwiXG4gICAgICBzZWxmLiRyZXN1bHRzLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCAndHJ1ZScpO1xuICAgICAgc2VsZi4kcmVzdWx0cy5hdHRyKCdhcmlhLWhpZGRlbicsICdmYWxzZScpO1xuXG4gICAgICBzZWxmLnNldENsYXNzZXMoKTtcbiAgICAgIHNlbGYuZW5zdXJlSGlnaGxpZ2h0VmlzaWJsZSgpO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdjbG9zZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFdoZW4gdGhlIGRyb3Bkb3duIGlzIGNsb3NlZCwgYXJpYS1leHBlbmRlZD1cImZhbHNlXCJcbiAgICAgIHNlbGYuJHJlc3VsdHMuYXR0cignYXJpYS1leHBhbmRlZCcsICdmYWxzZScpO1xuICAgICAgc2VsZi4kcmVzdWx0cy5hdHRyKCdhcmlhLWhpZGRlbicsICd0cnVlJyk7XG4gICAgICBzZWxmLiRyZXN1bHRzLnJlbW92ZUF0dHIoJ2FyaWEtYWN0aXZlZGVzY2VuZGFudCcpO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdyZXN1bHRzOnRvZ2dsZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkaGlnaGxpZ2h0ZWQgPSBzZWxmLmdldEhpZ2hsaWdodGVkUmVzdWx0cygpO1xuXG4gICAgICBpZiAoJGhpZ2hsaWdodGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgICRoaWdobGlnaHRlZC50cmlnZ2VyKCdtb3VzZXVwJyk7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ3Jlc3VsdHM6c2VsZWN0JywgZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICRoaWdobGlnaHRlZCA9IHNlbGYuZ2V0SGlnaGxpZ2h0ZWRSZXN1bHRzKCk7XG5cbiAgICAgIGlmICgkaGlnaGxpZ2h0ZWQubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGRhdGEgPSBVdGlscy5HZXREYXRhKCRoaWdobGlnaHRlZFswXSwgJ2RhdGEnKTtcblxuICAgICAgaWYgKCRoaWdobGlnaHRlZC5hdHRyKCdhcmlhLXNlbGVjdGVkJykgPT0gJ3RydWUnKSB7XG4gICAgICAgIHNlbGYudHJpZ2dlcignY2xvc2UnLCB7fSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzZWxmLnRyaWdnZXIoJ3NlbGVjdCcsIHtcbiAgICAgICAgICBkYXRhOiBkYXRhXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdyZXN1bHRzOnByZXZpb3VzJywgZnVuY3Rpb24gKCkge1xuICAgICAgdmFyICRoaWdobGlnaHRlZCA9IHNlbGYuZ2V0SGlnaGxpZ2h0ZWRSZXN1bHRzKCk7XG5cbiAgICAgIHZhciAkb3B0aW9ucyA9IHNlbGYuJHJlc3VsdHMuZmluZCgnW2FyaWEtc2VsZWN0ZWRdJyk7XG5cbiAgICAgIHZhciBjdXJyZW50SW5kZXggPSAkb3B0aW9ucy5pbmRleCgkaGlnaGxpZ2h0ZWQpO1xuXG4gICAgICAvLyBJZiB3ZSBhcmUgYWxyZWFkeSBhdCB0ZSB0b3AsIGRvbid0IG1vdmUgZnVydGhlclxuICAgICAgLy8gSWYgbm8gb3B0aW9ucywgY3VycmVudEluZGV4IHdpbGwgYmUgLTFcbiAgICAgIGlmIChjdXJyZW50SW5kZXggPD0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBuZXh0SW5kZXggPSBjdXJyZW50SW5kZXggLSAxO1xuXG4gICAgICAvLyBJZiBub25lIGFyZSBoaWdobGlnaHRlZCwgaGlnaGxpZ2h0IHRoZSBmaXJzdFxuICAgICAgaWYgKCRoaWdobGlnaHRlZC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgbmV4dEluZGV4ID0gMDtcbiAgICAgIH1cblxuICAgICAgdmFyICRuZXh0ID0gJG9wdGlvbnMuZXEobmV4dEluZGV4KTtcblxuICAgICAgJG5leHQudHJpZ2dlcignbW91c2VlbnRlcicpO1xuXG4gICAgICB2YXIgY3VycmVudE9mZnNldCA9IHNlbGYuJHJlc3VsdHMub2Zmc2V0KCkudG9wO1xuICAgICAgdmFyIG5leHRUb3AgPSAkbmV4dC5vZmZzZXQoKS50b3A7XG4gICAgICB2YXIgbmV4dE9mZnNldCA9IHNlbGYuJHJlc3VsdHMuc2Nyb2xsVG9wKCkgKyAobmV4dFRvcCAtIGN1cnJlbnRPZmZzZXQpO1xuXG4gICAgICBpZiAobmV4dEluZGV4ID09PSAwKSB7XG4gICAgICAgIHNlbGYuJHJlc3VsdHMuc2Nyb2xsVG9wKDApO1xuICAgICAgfSBlbHNlIGlmIChuZXh0VG9wIC0gY3VycmVudE9mZnNldCA8IDApIHtcbiAgICAgICAgc2VsZi4kcmVzdWx0cy5zY3JvbGxUb3AobmV4dE9mZnNldCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ3Jlc3VsdHM6bmV4dCcsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkaGlnaGxpZ2h0ZWQgPSBzZWxmLmdldEhpZ2hsaWdodGVkUmVzdWx0cygpO1xuXG4gICAgICB2YXIgJG9wdGlvbnMgPSBzZWxmLiRyZXN1bHRzLmZpbmQoJ1thcmlhLXNlbGVjdGVkXScpO1xuXG4gICAgICB2YXIgY3VycmVudEluZGV4ID0gJG9wdGlvbnMuaW5kZXgoJGhpZ2hsaWdodGVkKTtcblxuICAgICAgdmFyIG5leHRJbmRleCA9IGN1cnJlbnRJbmRleCArIDE7XG5cbiAgICAgIC8vIElmIHdlIGFyZSBhdCB0aGUgbGFzdCBvcHRpb24sIHN0YXkgdGhlcmVcbiAgICAgIGlmIChuZXh0SW5kZXggPj0gJG9wdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyICRuZXh0ID0gJG9wdGlvbnMuZXEobmV4dEluZGV4KTtcblxuICAgICAgJG5leHQudHJpZ2dlcignbW91c2VlbnRlcicpO1xuXG4gICAgICB2YXIgY3VycmVudE9mZnNldCA9IHNlbGYuJHJlc3VsdHMub2Zmc2V0KCkudG9wICtcbiAgICAgICAgc2VsZi4kcmVzdWx0cy5vdXRlckhlaWdodChmYWxzZSk7XG4gICAgICB2YXIgbmV4dEJvdHRvbSA9ICRuZXh0Lm9mZnNldCgpLnRvcCArICRuZXh0Lm91dGVySGVpZ2h0KGZhbHNlKTtcbiAgICAgIHZhciBuZXh0T2Zmc2V0ID0gc2VsZi4kcmVzdWx0cy5zY3JvbGxUb3AoKSArIG5leHRCb3R0b20gLSBjdXJyZW50T2Zmc2V0O1xuXG4gICAgICBpZiAobmV4dEluZGV4ID09PSAwKSB7XG4gICAgICAgIHNlbGYuJHJlc3VsdHMuc2Nyb2xsVG9wKDApO1xuICAgICAgfSBlbHNlIGlmIChuZXh0Qm90dG9tID4gY3VycmVudE9mZnNldCkge1xuICAgICAgICBzZWxmLiRyZXN1bHRzLnNjcm9sbFRvcChuZXh0T2Zmc2V0KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbigncmVzdWx0czpmb2N1cycsIGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgIHBhcmFtcy5lbGVtZW50LmFkZENsYXNzKCdzZWxlY3QyLXJlc3VsdHNfX29wdGlvbi0taGlnaGxpZ2h0ZWQnKTtcbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbigncmVzdWx0czptZXNzYWdlJywgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgc2VsZi5kaXNwbGF5TWVzc2FnZShwYXJhbXMpO1xuICAgIH0pO1xuXG4gICAgaWYgKCQuZm4ubW91c2V3aGVlbCkge1xuICAgICAgdGhpcy4kcmVzdWx0cy5vbignbW91c2V3aGVlbCcsIGZ1bmN0aW9uIChlKSB7XG4gICAgICAgIHZhciB0b3AgPSBzZWxmLiRyZXN1bHRzLnNjcm9sbFRvcCgpO1xuXG4gICAgICAgIHZhciBib3R0b20gPSBzZWxmLiRyZXN1bHRzLmdldCgwKS5zY3JvbGxIZWlnaHQgLSB0b3AgKyBlLmRlbHRhWTtcblxuICAgICAgICB2YXIgaXNBdFRvcCA9IGUuZGVsdGFZID4gMCAmJiB0b3AgLSBlLmRlbHRhWSA8PSAwO1xuICAgICAgICB2YXIgaXNBdEJvdHRvbSA9IGUuZGVsdGFZIDwgMCAmJiBib3R0b20gPD0gc2VsZi4kcmVzdWx0cy5oZWlnaHQoKTtcblxuICAgICAgICBpZiAoaXNBdFRvcCkge1xuICAgICAgICAgIHNlbGYuJHJlc3VsdHMuc2Nyb2xsVG9wKDApO1xuXG4gICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBdEJvdHRvbSkge1xuICAgICAgICAgIHNlbGYuJHJlc3VsdHMuc2Nyb2xsVG9wKFxuICAgICAgICAgICAgc2VsZi4kcmVzdWx0cy5nZXQoMCkuc2Nyb2xsSGVpZ2h0IC0gc2VsZi4kcmVzdWx0cy5oZWlnaHQoKVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy4kcmVzdWx0cy5vbignbW91c2V1cCcsICcuc2VsZWN0Mi1yZXN1bHRzX19vcHRpb25bYXJpYS1zZWxlY3RlZF0nLFxuICAgICAgZnVuY3Rpb24gKGV2dCkge1xuICAgICAgdmFyICR0aGlzID0gJCh0aGlzKTtcblxuICAgICAgdmFyIGRhdGEgPSBVdGlscy5HZXREYXRhKHRoaXMsICdkYXRhJyk7XG5cbiAgICAgIGlmICgkdGhpcy5hdHRyKCdhcmlhLXNlbGVjdGVkJykgPT09ICd0cnVlJykge1xuICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmdldCgnbXVsdGlwbGUnKSkge1xuICAgICAgICAgIHNlbGYudHJpZ2dlcigndW5zZWxlY3QnLCB7XG4gICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBldnQsXG4gICAgICAgICAgICBkYXRhOiBkYXRhXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgc2VsZi50cmlnZ2VyKCdjbG9zZScsIHt9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgc2VsZi50cmlnZ2VyKCdzZWxlY3QnLCB7XG4gICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2dCxcbiAgICAgICAgZGF0YTogZGF0YVxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLiRyZXN1bHRzLm9uKCdtb3VzZWVudGVyJywgJy5zZWxlY3QyLXJlc3VsdHNfX29wdGlvblthcmlhLXNlbGVjdGVkXScsXG4gICAgICBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICB2YXIgZGF0YSA9IFV0aWxzLkdldERhdGEodGhpcywgJ2RhdGEnKTtcblxuICAgICAgc2VsZi5nZXRIaWdobGlnaHRlZFJlc3VsdHMoKVxuICAgICAgICAgIC5yZW1vdmVDbGFzcygnc2VsZWN0Mi1yZXN1bHRzX19vcHRpb24tLWhpZ2hsaWdodGVkJyk7XG5cbiAgICAgIHNlbGYudHJpZ2dlcigncmVzdWx0czpmb2N1cycsIHtcbiAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgZWxlbWVudDogJCh0aGlzKVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgUmVzdWx0cy5wcm90b3R5cGUuZ2V0SGlnaGxpZ2h0ZWRSZXN1bHRzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkaGlnaGxpZ2h0ZWQgPSB0aGlzLiRyZXN1bHRzXG4gICAgLmZpbmQoJy5zZWxlY3QyLXJlc3VsdHNfX29wdGlvbi0taGlnaGxpZ2h0ZWQnKTtcblxuICAgIHJldHVybiAkaGlnaGxpZ2h0ZWQ7XG4gIH07XG5cbiAgUmVzdWx0cy5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLiRyZXN1bHRzLnJlbW92ZSgpO1xuICB9O1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLmVuc3VyZUhpZ2hsaWdodFZpc2libGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRoaWdobGlnaHRlZCA9IHRoaXMuZ2V0SGlnaGxpZ2h0ZWRSZXN1bHRzKCk7XG5cbiAgICBpZiAoJGhpZ2hsaWdodGVkLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciAkb3B0aW9ucyA9IHRoaXMuJHJlc3VsdHMuZmluZCgnW2FyaWEtc2VsZWN0ZWRdJyk7XG5cbiAgICB2YXIgY3VycmVudEluZGV4ID0gJG9wdGlvbnMuaW5kZXgoJGhpZ2hsaWdodGVkKTtcblxuICAgIHZhciBjdXJyZW50T2Zmc2V0ID0gdGhpcy4kcmVzdWx0cy5vZmZzZXQoKS50b3A7XG4gICAgdmFyIG5leHRUb3AgPSAkaGlnaGxpZ2h0ZWQub2Zmc2V0KCkudG9wO1xuICAgIHZhciBuZXh0T2Zmc2V0ID0gdGhpcy4kcmVzdWx0cy5zY3JvbGxUb3AoKSArIChuZXh0VG9wIC0gY3VycmVudE9mZnNldCk7XG5cbiAgICB2YXIgb2Zmc2V0RGVsdGEgPSBuZXh0VG9wIC0gY3VycmVudE9mZnNldDtcbiAgICBuZXh0T2Zmc2V0IC09ICRoaWdobGlnaHRlZC5vdXRlckhlaWdodChmYWxzZSkgKiAyO1xuXG4gICAgaWYgKGN1cnJlbnRJbmRleCA8PSAyKSB7XG4gICAgICB0aGlzLiRyZXN1bHRzLnNjcm9sbFRvcCgwKTtcbiAgICB9IGVsc2UgaWYgKG9mZnNldERlbHRhID4gdGhpcy4kcmVzdWx0cy5vdXRlckhlaWdodCgpIHx8IG9mZnNldERlbHRhIDwgMCkge1xuICAgICAgdGhpcy4kcmVzdWx0cy5zY3JvbGxUb3AobmV4dE9mZnNldCk7XG4gICAgfVxuICB9O1xuXG4gIFJlc3VsdHMucHJvdG90eXBlLnRlbXBsYXRlID0gZnVuY3Rpb24gKHJlc3VsdCwgY29udGFpbmVyKSB7XG4gICAgdmFyIHRlbXBsYXRlID0gdGhpcy5vcHRpb25zLmdldCgndGVtcGxhdGVSZXN1bHQnKTtcbiAgICB2YXIgZXNjYXBlTWFya3VwID0gdGhpcy5vcHRpb25zLmdldCgnZXNjYXBlTWFya3VwJyk7XG5cbiAgICB2YXIgY29udGVudCA9IHRlbXBsYXRlKHJlc3VsdCwgY29udGFpbmVyKTtcblxuICAgIGlmIChjb250ZW50ID09IG51bGwpIHtcbiAgICAgIGNvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gJ25vbmUnO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGNvbnRlbnQgPT09ICdzdHJpbmcnKSB7XG4gICAgICBjb250YWluZXIuaW5uZXJIVE1MID0gZXNjYXBlTWFya3VwKGNvbnRlbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAkKGNvbnRhaW5lcikuYXBwZW5kKGNvbnRlbnQpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gUmVzdWx0cztcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIva2V5cycsW1xuXG5dLCBmdW5jdGlvbiAoKSB7XG4gIHZhciBLRVlTID0ge1xuICAgIEJBQ0tTUEFDRTogOCxcbiAgICBUQUI6IDksXG4gICAgRU5URVI6IDEzLFxuICAgIFNISUZUOiAxNixcbiAgICBDVFJMOiAxNyxcbiAgICBBTFQ6IDE4LFxuICAgIEVTQzogMjcsXG4gICAgU1BBQ0U6IDMyLFxuICAgIFBBR0VfVVA6IDMzLFxuICAgIFBBR0VfRE9XTjogMzQsXG4gICAgRU5EOiAzNSxcbiAgICBIT01FOiAzNixcbiAgICBMRUZUOiAzNyxcbiAgICBVUDogMzgsXG4gICAgUklHSFQ6IDM5LFxuICAgIERPV046IDQwLFxuICAgIERFTEVURTogNDZcbiAgfTtcblxuICByZXR1cm4gS0VZUztcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIvc2VsZWN0aW9uL2Jhc2UnLFtcbiAgJ2pxdWVyeScsXG4gICcuLi91dGlscycsXG4gICcuLi9rZXlzJ1xuXSwgZnVuY3Rpb24gKCQsIFV0aWxzLCBLRVlTKSB7XG4gIGZ1bmN0aW9uIEJhc2VTZWxlY3Rpb24gKCRlbGVtZW50LCBvcHRpb25zKSB7XG4gICAgdGhpcy4kZWxlbWVudCA9ICRlbGVtZW50O1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG5cbiAgICBCYXNlU2VsZWN0aW9uLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5jYWxsKHRoaXMpO1xuICB9XG5cbiAgVXRpbHMuRXh0ZW5kKEJhc2VTZWxlY3Rpb24sIFV0aWxzLk9ic2VydmFibGUpO1xuXG4gIEJhc2VTZWxlY3Rpb24ucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJHNlbGVjdGlvbiA9ICQoXG4gICAgICAnPHNwYW4gY2xhc3M9XCJzZWxlY3QyLXNlbGVjdGlvblwiIHJvbGU9XCJjb21ib2JveFwiICcgK1xuICAgICAgJyBhcmlhLWhhc3BvcHVwPVwidHJ1ZVwiIGFyaWEtZXhwYW5kZWQ9XCJmYWxzZVwiPicgK1xuICAgICAgJzwvc3Bhbj4nXG4gICAgKTtcblxuICAgIHRoaXMuX3RhYmluZGV4ID0gMDtcblxuICAgIGlmIChVdGlscy5HZXREYXRhKHRoaXMuJGVsZW1lbnRbMF0sICdvbGQtdGFiaW5kZXgnKSAhPSBudWxsKSB7XG4gICAgICB0aGlzLl90YWJpbmRleCA9IFV0aWxzLkdldERhdGEodGhpcy4kZWxlbWVudFswXSwgJ29sZC10YWJpbmRleCcpO1xuICAgIH0gZWxzZSBpZiAodGhpcy4kZWxlbWVudC5hdHRyKCd0YWJpbmRleCcpICE9IG51bGwpIHtcbiAgICAgIHRoaXMuX3RhYmluZGV4ID0gdGhpcy4kZWxlbWVudC5hdHRyKCd0YWJpbmRleCcpO1xuICAgIH1cblxuICAgICRzZWxlY3Rpb24uYXR0cigndGl0bGUnLCB0aGlzLiRlbGVtZW50LmF0dHIoJ3RpdGxlJykpO1xuICAgICRzZWxlY3Rpb24uYXR0cigndGFiaW5kZXgnLCB0aGlzLl90YWJpbmRleCk7XG5cbiAgICB0aGlzLiRzZWxlY3Rpb24gPSAkc2VsZWN0aW9uO1xuXG4gICAgcmV0dXJuICRzZWxlY3Rpb247XG4gIH07XG5cbiAgQmFzZVNlbGVjdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uIChjb250YWluZXIsICRjb250YWluZXIpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgaWQgPSBjb250YWluZXIuaWQgKyAnLWNvbnRhaW5lcic7XG4gICAgdmFyIHJlc3VsdHNJZCA9IGNvbnRhaW5lci5pZCArICctcmVzdWx0cyc7XG5cbiAgICB0aGlzLmNvbnRhaW5lciA9IGNvbnRhaW5lcjtcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5vbignZm9jdXMnLCBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICBzZWxmLnRyaWdnZXIoJ2ZvY3VzJywgZXZ0KTtcbiAgICB9KTtcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5vbignYmx1cicsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIHNlbGYuX2hhbmRsZUJsdXIoZXZ0KTtcbiAgICB9KTtcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5vbigna2V5ZG93bicsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIHNlbGYudHJpZ2dlcigna2V5cHJlc3MnLCBldnQpO1xuXG4gICAgICBpZiAoZXZ0LndoaWNoID09PSBLRVlTLlNQQUNFKSB7XG4gICAgICAgIGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdyZXN1bHRzOmZvY3VzJywgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgc2VsZi4kc2VsZWN0aW9uLmF0dHIoJ2FyaWEtYWN0aXZlZGVzY2VuZGFudCcsIHBhcmFtcy5kYXRhLl9yZXN1bHRJZCk7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ3NlbGVjdGlvbjp1cGRhdGUnLCBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICBzZWxmLnVwZGF0ZShwYXJhbXMuZGF0YSk7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ29wZW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBXaGVuIHRoZSBkcm9wZG93biBpcyBvcGVuLCBhcmlhLWV4cGFuZGVkPVwidHJ1ZVwiXG4gICAgICBzZWxmLiRzZWxlY3Rpb24uYXR0cignYXJpYS1leHBhbmRlZCcsICd0cnVlJyk7XG4gICAgICBzZWxmLiRzZWxlY3Rpb24uYXR0cignYXJpYS1vd25zJywgcmVzdWx0c0lkKTtcblxuICAgICAgc2VsZi5fYXR0YWNoQ2xvc2VIYW5kbGVyKGNvbnRhaW5lcik7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ2Nsb3NlJywgZnVuY3Rpb24gKCkge1xuICAgICAgLy8gV2hlbiB0aGUgZHJvcGRvd24gaXMgY2xvc2VkLCBhcmlhLWV4cGFuZGVkPVwiZmFsc2VcIlxuICAgICAgc2VsZi4kc2VsZWN0aW9uLmF0dHIoJ2FyaWEtZXhwYW5kZWQnLCAnZmFsc2UnKTtcbiAgICAgIHNlbGYuJHNlbGVjdGlvbi5yZW1vdmVBdHRyKCdhcmlhLWFjdGl2ZWRlc2NlbmRhbnQnKTtcbiAgICAgIHNlbGYuJHNlbGVjdGlvbi5yZW1vdmVBdHRyKCdhcmlhLW93bnMnKTtcblxuICAgICAgc2VsZi4kc2VsZWN0aW9uLmZvY3VzKCk7XG4gICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHNlbGYuJHNlbGVjdGlvbi5mb2N1cygpO1xuICAgICAgfSwgMCk7XG5cbiAgICAgIHNlbGYuX2RldGFjaENsb3NlSGFuZGxlcihjb250YWluZXIpO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdlbmFibGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLiRzZWxlY3Rpb24uYXR0cigndGFiaW5kZXgnLCBzZWxmLl90YWJpbmRleCk7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ2Rpc2FibGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLiRzZWxlY3Rpb24uYXR0cigndGFiaW5kZXgnLCAnLTEnKTtcbiAgICB9KTtcbiAgfTtcblxuICBCYXNlU2VsZWN0aW9uLnByb3RvdHlwZS5faGFuZGxlQmx1ciA9IGZ1bmN0aW9uIChldnQpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAvLyBUaGlzIG5lZWRzIHRvIGJlIGRlbGF5ZWQgYXMgdGhlIGFjdGl2ZSBlbGVtZW50IGlzIHRoZSBib2R5IHdoZW4gdGhlIHRhYlxuICAgIC8vIGtleSBpcyBwcmVzc2VkLCBwb3NzaWJseSBhbG9uZyB3aXRoIG90aGVycy5cbiAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICAvLyBEb24ndCB0cmlnZ2VyIGBibHVyYCBpZiB0aGUgZm9jdXMgaXMgc3RpbGwgaW4gdGhlIHNlbGVjdGlvblxuICAgICAgaWYgKFxuICAgICAgICAoZG9jdW1lbnQuYWN0aXZlRWxlbWVudCA9PSBzZWxmLiRzZWxlY3Rpb25bMF0pIHx8XG4gICAgICAgICgkLmNvbnRhaW5zKHNlbGYuJHNlbGVjdGlvblswXSwgZG9jdW1lbnQuYWN0aXZlRWxlbWVudCkpXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzZWxmLnRyaWdnZXIoJ2JsdXInLCBldnQpO1xuICAgIH0sIDEpO1xuICB9O1xuXG4gIEJhc2VTZWxlY3Rpb24ucHJvdG90eXBlLl9hdHRhY2hDbG9zZUhhbmRsZXIgPSBmdW5jdGlvbiAoY29udGFpbmVyKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgJChkb2N1bWVudC5ib2R5KS5vbignbW91c2Vkb3duLnNlbGVjdDIuJyArIGNvbnRhaW5lci5pZCwgZnVuY3Rpb24gKGUpIHtcbiAgICAgIHZhciAkdGFyZ2V0ID0gJChlLnRhcmdldCk7XG5cbiAgICAgIHZhciAkc2VsZWN0ID0gJHRhcmdldC5jbG9zZXN0KCcuc2VsZWN0MicpO1xuXG4gICAgICB2YXIgJGFsbCA9ICQoJy5zZWxlY3QyLnNlbGVjdDItY29udGFpbmVyLS1vcGVuJyk7XG5cbiAgICAgICRhbGwuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyk7XG5cbiAgICAgICAgaWYgKHRoaXMgPT0gJHNlbGVjdFswXSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciAkZWxlbWVudCA9IFV0aWxzLkdldERhdGEodGhpcywgJ2VsZW1lbnQnKTtcblxuICAgICAgICAkZWxlbWVudC5zZWxlY3QyKCdjbG9zZScpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH07XG5cbiAgQmFzZVNlbGVjdGlvbi5wcm90b3R5cGUuX2RldGFjaENsb3NlSGFuZGxlciA9IGZ1bmN0aW9uIChjb250YWluZXIpIHtcbiAgICAkKGRvY3VtZW50LmJvZHkpLm9mZignbW91c2Vkb3duLnNlbGVjdDIuJyArIGNvbnRhaW5lci5pZCk7XG4gIH07XG5cbiAgQmFzZVNlbGVjdGlvbi5wcm90b3R5cGUucG9zaXRpb24gPSBmdW5jdGlvbiAoJHNlbGVjdGlvbiwgJGNvbnRhaW5lcikge1xuICAgIHZhciAkc2VsZWN0aW9uQ29udGFpbmVyID0gJGNvbnRhaW5lci5maW5kKCcuc2VsZWN0aW9uJyk7XG4gICAgJHNlbGVjdGlvbkNvbnRhaW5lci5hcHBlbmQoJHNlbGVjdGlvbik7XG4gIH07XG5cbiAgQmFzZVNlbGVjdGlvbi5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLl9kZXRhY2hDbG9zZUhhbmRsZXIodGhpcy5jb250YWluZXIpO1xuICB9O1xuXG4gIEJhc2VTZWxlY3Rpb24ucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdUaGUgYHVwZGF0ZWAgbWV0aG9kIG11c3QgYmUgZGVmaW5lZCBpbiBjaGlsZCBjbGFzc2VzLicpO1xuICB9O1xuXG4gIHJldHVybiBCYXNlU2VsZWN0aW9uO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9zZWxlY3Rpb24vc2luZ2xlJyxbXG4gICdqcXVlcnknLFxuICAnLi9iYXNlJyxcbiAgJy4uL3V0aWxzJyxcbiAgJy4uL2tleXMnXG5dLCBmdW5jdGlvbiAoJCwgQmFzZVNlbGVjdGlvbiwgVXRpbHMsIEtFWVMpIHtcbiAgZnVuY3Rpb24gU2luZ2xlU2VsZWN0aW9uICgpIHtcbiAgICBTaW5nbGVTZWxlY3Rpb24uX19zdXBlcl9fLmNvbnN0cnVjdG9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cblxuICBVdGlscy5FeHRlbmQoU2luZ2xlU2VsZWN0aW9uLCBCYXNlU2VsZWN0aW9uKTtcblxuICBTaW5nbGVTZWxlY3Rpb24ucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJHNlbGVjdGlvbiA9IFNpbmdsZVNlbGVjdGlvbi5fX3N1cGVyX18ucmVuZGVyLmNhbGwodGhpcyk7XG5cbiAgICAkc2VsZWN0aW9uLmFkZENsYXNzKCdzZWxlY3QyLXNlbGVjdGlvbi0tc2luZ2xlJyk7XG5cbiAgICAkc2VsZWN0aW9uLmh0bWwoXG4gICAgICAnPHNwYW4gY2xhc3M9XCJzZWxlY3QyLXNlbGVjdGlvbl9fcmVuZGVyZWRcIj48L3NwYW4+JyArXG4gICAgICAnPHNwYW4gY2xhc3M9XCJzZWxlY3QyLXNlbGVjdGlvbl9fYXJyb3dcIiByb2xlPVwicHJlc2VudGF0aW9uXCI+JyArXG4gICAgICAgICc8YiByb2xlPVwicHJlc2VudGF0aW9uXCI+PC9iPicgK1xuICAgICAgJzwvc3Bhbj4nXG4gICAgKTtcblxuICAgIHJldHVybiAkc2VsZWN0aW9uO1xuICB9O1xuXG4gIFNpbmdsZVNlbGVjdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uIChjb250YWluZXIsICRjb250YWluZXIpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBTaW5nbGVTZWxlY3Rpb24uX19zdXBlcl9fLmJpbmQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcblxuICAgIHZhciBpZCA9IGNvbnRhaW5lci5pZCArICctY29udGFpbmVyJztcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5maW5kKCcuc2VsZWN0Mi1zZWxlY3Rpb25fX3JlbmRlcmVkJylcbiAgICAgIC5hdHRyKCdpZCcsIGlkKVxuICAgICAgLmF0dHIoJ3JvbGUnLCAndGV4dGJveCcpXG4gICAgICAuYXR0cignYXJpYS1yZWFkb25seScsICd0cnVlJyk7XG4gICAgdGhpcy4kc2VsZWN0aW9uLmF0dHIoJ2FyaWEtbGFiZWxsZWRieScsIGlkKTtcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5vbignbW91c2Vkb3duJywgZnVuY3Rpb24gKGV2dCkge1xuICAgICAgLy8gT25seSByZXNwb25kIHRvIGxlZnQgY2xpY2tzXG4gICAgICBpZiAoZXZ0LndoaWNoICE9PSAxKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgc2VsZi50cmlnZ2VyKCd0b2dnbGUnLCB7XG4gICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2dFxuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLiRzZWxlY3Rpb24ub24oJ2ZvY3VzJywgZnVuY3Rpb24gKGV2dCkge1xuICAgICAgLy8gVXNlciBmb2N1c2VzIG9uIHRoZSBjb250YWluZXJcbiAgICB9KTtcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5vbignYmx1cicsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIC8vIFVzZXIgZXhpdHMgdGhlIGNvbnRhaW5lclxuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdmb2N1cycsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIGlmICghY29udGFpbmVyLmlzT3BlbigpKSB7XG4gICAgICAgIHNlbGYuJHNlbGVjdGlvbi5mb2N1cygpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIFNpbmdsZVNlbGVjdGlvbi5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRyZW5kZXJlZCA9IHRoaXMuJHNlbGVjdGlvbi5maW5kKCcuc2VsZWN0Mi1zZWxlY3Rpb25fX3JlbmRlcmVkJyk7XG4gICAgJHJlbmRlcmVkLmVtcHR5KCk7XG4gICAgJHJlbmRlcmVkLnJlbW92ZUF0dHIoJ3RpdGxlJyk7IC8vIGNsZWFyIHRvb2x0aXAgb24gZW1wdHlcbiAgfTtcblxuICBTaW5nbGVTZWxlY3Rpb24ucHJvdG90eXBlLmRpc3BsYXkgPSBmdW5jdGlvbiAoZGF0YSwgY29udGFpbmVyKSB7XG4gICAgdmFyIHRlbXBsYXRlID0gdGhpcy5vcHRpb25zLmdldCgndGVtcGxhdGVTZWxlY3Rpb24nKTtcbiAgICB2YXIgZXNjYXBlTWFya3VwID0gdGhpcy5vcHRpb25zLmdldCgnZXNjYXBlTWFya3VwJyk7XG5cbiAgICByZXR1cm4gZXNjYXBlTWFya3VwKHRlbXBsYXRlKGRhdGEsIGNvbnRhaW5lcikpO1xuICB9O1xuXG4gIFNpbmdsZVNlbGVjdGlvbi5wcm90b3R5cGUuc2VsZWN0aW9uQ29udGFpbmVyID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiAkKCc8c3Bhbj48L3NwYW4+Jyk7XG4gIH07XG5cbiAgU2luZ2xlU2VsZWN0aW9uLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIGlmIChkYXRhLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5jbGVhcigpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBzZWxlY3Rpb24gPSBkYXRhWzBdO1xuXG4gICAgdmFyICRyZW5kZXJlZCA9IHRoaXMuJHNlbGVjdGlvbi5maW5kKCcuc2VsZWN0Mi1zZWxlY3Rpb25fX3JlbmRlcmVkJyk7XG4gICAgdmFyIGZvcm1hdHRlZCA9IHRoaXMuZGlzcGxheShzZWxlY3Rpb24sICRyZW5kZXJlZCk7XG5cbiAgICAkcmVuZGVyZWQuZW1wdHkoKS5hcHBlbmQoZm9ybWF0dGVkKTtcbiAgICAkcmVuZGVyZWQuYXR0cigndGl0bGUnLCBzZWxlY3Rpb24udGl0bGUgfHwgc2VsZWN0aW9uLnRleHQpO1xuICB9O1xuXG4gIHJldHVybiBTaW5nbGVTZWxlY3Rpb247XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL3NlbGVjdGlvbi9tdWx0aXBsZScsW1xuICAnanF1ZXJ5JyxcbiAgJy4vYmFzZScsXG4gICcuLi91dGlscydcbl0sIGZ1bmN0aW9uICgkLCBCYXNlU2VsZWN0aW9uLCBVdGlscykge1xuICBmdW5jdGlvbiBNdWx0aXBsZVNlbGVjdGlvbiAoJGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICBNdWx0aXBsZVNlbGVjdGlvbi5fX3N1cGVyX18uY29uc3RydWN0b3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIFV0aWxzLkV4dGVuZChNdWx0aXBsZVNlbGVjdGlvbiwgQmFzZVNlbGVjdGlvbik7XG5cbiAgTXVsdGlwbGVTZWxlY3Rpb24ucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJHNlbGVjdGlvbiA9IE11bHRpcGxlU2VsZWN0aW9uLl9fc3VwZXJfXy5yZW5kZXIuY2FsbCh0aGlzKTtcblxuICAgICRzZWxlY3Rpb24uYWRkQ2xhc3MoJ3NlbGVjdDItc2VsZWN0aW9uLS1tdWx0aXBsZScpO1xuXG4gICAgJHNlbGVjdGlvbi5odG1sKFxuICAgICAgJzx1bCBjbGFzcz1cInNlbGVjdDItc2VsZWN0aW9uX19yZW5kZXJlZFwiPjwvdWw+J1xuICAgICk7XG5cbiAgICByZXR1cm4gJHNlbGVjdGlvbjtcbiAgfTtcblxuICBNdWx0aXBsZVNlbGVjdGlvbi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uIChjb250YWluZXIsICRjb250YWluZXIpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBNdWx0aXBsZVNlbGVjdGlvbi5fX3N1cGVyX18uYmluZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuXG4gICAgdGhpcy4kc2VsZWN0aW9uLm9uKCdjbGljaycsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIHNlbGYudHJpZ2dlcigndG9nZ2xlJywge1xuICAgICAgICBvcmlnaW5hbEV2ZW50OiBldnRcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGhpcy4kc2VsZWN0aW9uLm9uKFxuICAgICAgJ2NsaWNrJyxcbiAgICAgICcuc2VsZWN0Mi1zZWxlY3Rpb25fX2Nob2ljZV9fcmVtb3ZlJyxcbiAgICAgIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgICAgLy8gSWdub3JlIHRoZSBldmVudCBpZiBpdCBpcyBkaXNhYmxlZFxuICAgICAgICBpZiAoc2VsZi5vcHRpb25zLmdldCgnZGlzYWJsZWQnKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciAkcmVtb3ZlID0gJCh0aGlzKTtcbiAgICAgICAgdmFyICRzZWxlY3Rpb24gPSAkcmVtb3ZlLnBhcmVudCgpO1xuXG4gICAgICAgIHZhciBkYXRhID0gVXRpbHMuR2V0RGF0YSgkc2VsZWN0aW9uWzBdLCAnZGF0YScpO1xuXG4gICAgICAgIHNlbGYudHJpZ2dlcigndW5zZWxlY3QnLCB7XG4gICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZ0LFxuICAgICAgICAgIGRhdGE6IGRhdGFcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgKTtcbiAgfTtcblxuICBNdWx0aXBsZVNlbGVjdGlvbi5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRyZW5kZXJlZCA9IHRoaXMuJHNlbGVjdGlvbi5maW5kKCcuc2VsZWN0Mi1zZWxlY3Rpb25fX3JlbmRlcmVkJyk7XG4gICAgJHJlbmRlcmVkLmVtcHR5KCk7XG4gICAgJHJlbmRlcmVkLnJlbW92ZUF0dHIoJ3RpdGxlJyk7XG4gIH07XG5cbiAgTXVsdGlwbGVTZWxlY3Rpb24ucHJvdG90eXBlLmRpc3BsYXkgPSBmdW5jdGlvbiAoZGF0YSwgY29udGFpbmVyKSB7XG4gICAgdmFyIHRlbXBsYXRlID0gdGhpcy5vcHRpb25zLmdldCgndGVtcGxhdGVTZWxlY3Rpb24nKTtcbiAgICB2YXIgZXNjYXBlTWFya3VwID0gdGhpcy5vcHRpb25zLmdldCgnZXNjYXBlTWFya3VwJyk7XG5cbiAgICByZXR1cm4gZXNjYXBlTWFya3VwKHRlbXBsYXRlKGRhdGEsIGNvbnRhaW5lcikpO1xuICB9O1xuXG4gIE11bHRpcGxlU2VsZWN0aW9uLnByb3RvdHlwZS5zZWxlY3Rpb25Db250YWluZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyICRjb250YWluZXIgPSAkKFxuICAgICAgJzxsaSBjbGFzcz1cInNlbGVjdDItc2VsZWN0aW9uX19jaG9pY2VcIj4nICtcbiAgICAgICAgJzxzcGFuIGNsYXNzPVwic2VsZWN0Mi1zZWxlY3Rpb25fX2Nob2ljZV9fcmVtb3ZlXCIgcm9sZT1cInByZXNlbnRhdGlvblwiPicgK1xuICAgICAgICAgICcmdGltZXM7JyArXG4gICAgICAgICc8L3NwYW4+JyArXG4gICAgICAnPC9saT4nXG4gICAgKTtcblxuICAgIHJldHVybiAkY29udGFpbmVyO1xuICB9O1xuXG4gIE11bHRpcGxlU2VsZWN0aW9uLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIHRoaXMuY2xlYXIoKTtcblxuICAgIGlmIChkYXRhLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciAkc2VsZWN0aW9ucyA9IFtdO1xuXG4gICAgZm9yICh2YXIgZCA9IDA7IGQgPCBkYXRhLmxlbmd0aDsgZCsrKSB7XG4gICAgICB2YXIgc2VsZWN0aW9uID0gZGF0YVtkXTtcblxuICAgICAgdmFyICRzZWxlY3Rpb24gPSB0aGlzLnNlbGVjdGlvbkNvbnRhaW5lcigpO1xuICAgICAgdmFyIGZvcm1hdHRlZCA9IHRoaXMuZGlzcGxheShzZWxlY3Rpb24sICRzZWxlY3Rpb24pO1xuXG4gICAgICAkc2VsZWN0aW9uLmFwcGVuZChmb3JtYXR0ZWQpO1xuICAgICAgJHNlbGVjdGlvbi5hdHRyKCd0aXRsZScsIHNlbGVjdGlvbi50aXRsZSB8fCBzZWxlY3Rpb24udGV4dCk7XG5cbiAgICAgIFV0aWxzLlN0b3JlRGF0YSgkc2VsZWN0aW9uWzBdLCAnZGF0YScsIHNlbGVjdGlvbik7XG5cbiAgICAgICRzZWxlY3Rpb25zLnB1c2goJHNlbGVjdGlvbik7XG4gICAgfVxuXG4gICAgdmFyICRyZW5kZXJlZCA9IHRoaXMuJHNlbGVjdGlvbi5maW5kKCcuc2VsZWN0Mi1zZWxlY3Rpb25fX3JlbmRlcmVkJyk7XG5cbiAgICBVdGlscy5hcHBlbmRNYW55KCRyZW5kZXJlZCwgJHNlbGVjdGlvbnMpO1xuICB9O1xuXG4gIHJldHVybiBNdWx0aXBsZVNlbGVjdGlvbjtcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIvc2VsZWN0aW9uL3BsYWNlaG9sZGVyJyxbXG4gICcuLi91dGlscydcbl0sIGZ1bmN0aW9uIChVdGlscykge1xuICBmdW5jdGlvbiBQbGFjZWhvbGRlciAoZGVjb3JhdGVkLCAkZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMucGxhY2Vob2xkZXIgPSB0aGlzLm5vcm1hbGl6ZVBsYWNlaG9sZGVyKG9wdGlvbnMuZ2V0KCdwbGFjZWhvbGRlcicpKTtcblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsICRlbGVtZW50LCBvcHRpb25zKTtcbiAgfVxuXG4gIFBsYWNlaG9sZGVyLnByb3RvdHlwZS5ub3JtYWxpemVQbGFjZWhvbGRlciA9IGZ1bmN0aW9uIChfLCBwbGFjZWhvbGRlcikge1xuICAgIGlmICh0eXBlb2YgcGxhY2Vob2xkZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICBwbGFjZWhvbGRlciA9IHtcbiAgICAgICAgaWQ6ICcnLFxuICAgICAgICB0ZXh0OiBwbGFjZWhvbGRlclxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGxhY2Vob2xkZXI7XG4gIH07XG5cbiAgUGxhY2Vob2xkZXIucHJvdG90eXBlLmNyZWF0ZVBsYWNlaG9sZGVyID0gZnVuY3Rpb24gKGRlY29yYXRlZCwgcGxhY2Vob2xkZXIpIHtcbiAgICB2YXIgJHBsYWNlaG9sZGVyID0gdGhpcy5zZWxlY3Rpb25Db250YWluZXIoKTtcblxuICAgICRwbGFjZWhvbGRlci5odG1sKHRoaXMuZGlzcGxheShwbGFjZWhvbGRlcikpO1xuICAgICRwbGFjZWhvbGRlci5hZGRDbGFzcygnc2VsZWN0Mi1zZWxlY3Rpb25fX3BsYWNlaG9sZGVyJylcbiAgICAgICAgICAgICAgICAucmVtb3ZlQ2xhc3MoJ3NlbGVjdDItc2VsZWN0aW9uX19jaG9pY2UnKTtcblxuICAgIHJldHVybiAkcGxhY2Vob2xkZXI7XG4gIH07XG5cbiAgUGxhY2Vob2xkZXIucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIGRhdGEpIHtcbiAgICB2YXIgc2luZ2xlUGxhY2Vob2xkZXIgPSAoXG4gICAgICBkYXRhLmxlbmd0aCA9PSAxICYmIGRhdGFbMF0uaWQgIT0gdGhpcy5wbGFjZWhvbGRlci5pZFxuICAgICk7XG4gICAgdmFyIG11bHRpcGxlU2VsZWN0aW9ucyA9IGRhdGEubGVuZ3RoID4gMTtcblxuICAgIGlmIChtdWx0aXBsZVNlbGVjdGlvbnMgfHwgc2luZ2xlUGxhY2Vob2xkZXIpIHtcbiAgICAgIHJldHVybiBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBkYXRhKTtcbiAgICB9XG5cbiAgICB0aGlzLmNsZWFyKCk7XG5cbiAgICB2YXIgJHBsYWNlaG9sZGVyID0gdGhpcy5jcmVhdGVQbGFjZWhvbGRlcih0aGlzLnBsYWNlaG9sZGVyKTtcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5maW5kKCcuc2VsZWN0Mi1zZWxlY3Rpb25fX3JlbmRlcmVkJykuYXBwZW5kKCRwbGFjZWhvbGRlcik7XG4gIH07XG5cbiAgcmV0dXJuIFBsYWNlaG9sZGVyO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9zZWxlY3Rpb24vYWxsb3dDbGVhcicsW1xuICAnanF1ZXJ5JyxcbiAgJy4uL2tleXMnLFxuICAnLi4vdXRpbHMnXG5dLCBmdW5jdGlvbiAoJCwgS0VZUywgVXRpbHMpIHtcbiAgZnVuY3Rpb24gQWxsb3dDbGVhciAoKSB7IH1cblxuICBBbGxvd0NsZWFyLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24gKGRlY29yYXRlZCwgY29udGFpbmVyLCAkY29udGFpbmVyKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgZGVjb3JhdGVkLmNhbGwodGhpcywgY29udGFpbmVyLCAkY29udGFpbmVyKTtcblxuICAgIGlmICh0aGlzLnBsYWNlaG9sZGVyID09IG51bGwpIHtcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuZ2V0KCdkZWJ1ZycpICYmIHdpbmRvdy5jb25zb2xlICYmIGNvbnNvbGUuZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcbiAgICAgICAgICAnU2VsZWN0MjogVGhlIGBhbGxvd0NsZWFyYCBvcHRpb24gc2hvdWxkIGJlIHVzZWQgaW4gY29tYmluYXRpb24gJyArXG4gICAgICAgICAgJ3dpdGggdGhlIGBwbGFjZWhvbGRlcmAgb3B0aW9uLidcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLiRzZWxlY3Rpb24ub24oJ21vdXNlZG93bicsICcuc2VsZWN0Mi1zZWxlY3Rpb25fX2NsZWFyJyxcbiAgICAgIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgICAgc2VsZi5faGFuZGxlQ2xlYXIoZXZ0KTtcbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbigna2V5cHJlc3MnLCBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICBzZWxmLl9oYW5kbGVLZXlib2FyZENsZWFyKGV2dCwgY29udGFpbmVyKTtcbiAgICB9KTtcbiAgfTtcblxuICBBbGxvd0NsZWFyLnByb3RvdHlwZS5faGFuZGxlQ2xlYXIgPSBmdW5jdGlvbiAoXywgZXZ0KSB7XG4gICAgLy8gSWdub3JlIHRoZSBldmVudCBpZiBpdCBpcyBkaXNhYmxlZFxuICAgIGlmICh0aGlzLm9wdGlvbnMuZ2V0KCdkaXNhYmxlZCcpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyICRjbGVhciA9IHRoaXMuJHNlbGVjdGlvbi5maW5kKCcuc2VsZWN0Mi1zZWxlY3Rpb25fX2NsZWFyJyk7XG5cbiAgICAvLyBJZ25vcmUgdGhlIGV2ZW50IGlmIG5vdGhpbmcgaGFzIGJlZW4gc2VsZWN0ZWRcbiAgICBpZiAoJGNsZWFyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGV2dC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIHZhciBkYXRhID0gVXRpbHMuR2V0RGF0YSgkY2xlYXJbMF0sICdkYXRhJyk7XG5cbiAgICB2YXIgcHJldmlvdXNWYWwgPSB0aGlzLiRlbGVtZW50LnZhbCgpO1xuICAgIHRoaXMuJGVsZW1lbnQudmFsKHRoaXMucGxhY2Vob2xkZXIuaWQpO1xuXG4gICAgdmFyIHVuc2VsZWN0RGF0YSA9IHtcbiAgICAgIGRhdGE6IGRhdGFcbiAgICB9O1xuICAgIHRoaXMudHJpZ2dlcignY2xlYXInLCB1bnNlbGVjdERhdGEpO1xuICAgIGlmICh1bnNlbGVjdERhdGEucHJldmVudGVkKSB7XG4gICAgICB0aGlzLiRlbGVtZW50LnZhbChwcmV2aW91c1ZhbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZm9yICh2YXIgZCA9IDA7IGQgPCBkYXRhLmxlbmd0aDsgZCsrKSB7XG4gICAgICB1bnNlbGVjdERhdGEgPSB7XG4gICAgICAgIGRhdGE6IGRhdGFbZF1cbiAgICAgIH07XG5cbiAgICAgIC8vIFRyaWdnZXIgdGhlIGB1bnNlbGVjdGAgZXZlbnQsIHNvIHBlb3BsZSBjYW4gcHJldmVudCBpdCBmcm9tIGJlaW5nXG4gICAgICAvLyBjbGVhcmVkLlxuICAgICAgdGhpcy50cmlnZ2VyKCd1bnNlbGVjdCcsIHVuc2VsZWN0RGF0YSk7XG5cbiAgICAgIC8vIElmIHRoZSBldmVudCB3YXMgcHJldmVudGVkLCBkb24ndCBjbGVhciBpdCBvdXQuXG4gICAgICBpZiAodW5zZWxlY3REYXRhLnByZXZlbnRlZCkge1xuICAgICAgICB0aGlzLiRlbGVtZW50LnZhbChwcmV2aW91c1ZhbCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoJ2NoYW5nZScpO1xuXG4gICAgdGhpcy50cmlnZ2VyKCd0b2dnbGUnLCB7fSk7XG4gIH07XG5cbiAgQWxsb3dDbGVhci5wcm90b3R5cGUuX2hhbmRsZUtleWJvYXJkQ2xlYXIgPSBmdW5jdGlvbiAoXywgZXZ0LCBjb250YWluZXIpIHtcbiAgICBpZiAoY29udGFpbmVyLmlzT3BlbigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGV2dC53aGljaCA9PSBLRVlTLkRFTEVURSB8fCBldnQud2hpY2ggPT0gS0VZUy5CQUNLU1BBQ0UpIHtcbiAgICAgIHRoaXMuX2hhbmRsZUNsZWFyKGV2dCk7XG4gICAgfVxuICB9O1xuXG4gIEFsbG93Q2xlYXIucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIGRhdGEpIHtcbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBkYXRhKTtcblxuICAgIGlmICh0aGlzLiRzZWxlY3Rpb24uZmluZCgnLnNlbGVjdDItc2VsZWN0aW9uX19wbGFjZWhvbGRlcicpLmxlbmd0aCA+IDAgfHxcbiAgICAgICAgZGF0YS5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB2YXIgJHJlbW92ZSA9ICQoXG4gICAgICAnPHNwYW4gY2xhc3M9XCJzZWxlY3QyLXNlbGVjdGlvbl9fY2xlYXJcIj4nICtcbiAgICAgICAgJyZ0aW1lczsnICtcbiAgICAgICc8L3NwYW4+J1xuICAgICk7XG4gICAgVXRpbHMuU3RvcmVEYXRhKCRyZW1vdmVbMF0sICdkYXRhJywgZGF0YSk7XG5cbiAgICB0aGlzLiRzZWxlY3Rpb24uZmluZCgnLnNlbGVjdDItc2VsZWN0aW9uX19yZW5kZXJlZCcpLnByZXBlbmQoJHJlbW92ZSk7XG4gIH07XG5cbiAgcmV0dXJuIEFsbG93Q2xlYXI7XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL3NlbGVjdGlvbi9zZWFyY2gnLFtcbiAgJ2pxdWVyeScsXG4gICcuLi91dGlscycsXG4gICcuLi9rZXlzJ1xuXSwgZnVuY3Rpb24gKCQsIFV0aWxzLCBLRVlTKSB7XG4gIGZ1bmN0aW9uIFNlYXJjaCAoZGVjb3JhdGVkLCAkZWxlbWVudCwgb3B0aW9ucykge1xuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsICRlbGVtZW50LCBvcHRpb25zKTtcbiAgfVxuXG4gIFNlYXJjaC5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKGRlY29yYXRlZCkge1xuICAgIHZhciAkc2VhcmNoID0gJChcbiAgICAgICc8bGkgY2xhc3M9XCJzZWxlY3QyLXNlYXJjaCBzZWxlY3QyLXNlYXJjaC0taW5saW5lXCI+JyArXG4gICAgICAgICc8aW5wdXQgY2xhc3M9XCJzZWxlY3QyLXNlYXJjaF9fZmllbGRcIiB0eXBlPVwic2VhcmNoXCIgdGFiaW5kZXg9XCItMVwiJyArXG4gICAgICAgICcgYXV0b2NvbXBsZXRlPVwib2ZmXCIgYXV0b2NvcnJlY3Q9XCJvZmZcIiBhdXRvY2FwaXRhbGl6ZT1cIm5vbmVcIicgK1xuICAgICAgICAnIHNwZWxsY2hlY2s9XCJmYWxzZVwiIHJvbGU9XCJ0ZXh0Ym94XCIgYXJpYS1hdXRvY29tcGxldGU9XCJsaXN0XCIgLz4nICtcbiAgICAgICc8L2xpPidcbiAgICApO1xuXG4gICAgdGhpcy4kc2VhcmNoQ29udGFpbmVyID0gJHNlYXJjaDtcbiAgICB0aGlzLiRzZWFyY2ggPSAkc2VhcmNoLmZpbmQoJ2lucHV0Jyk7XG5cbiAgICB2YXIgJHJlbmRlcmVkID0gZGVjb3JhdGVkLmNhbGwodGhpcyk7XG5cbiAgICB0aGlzLl90cmFuc2ZlclRhYkluZGV4KCk7XG5cbiAgICByZXR1cm4gJHJlbmRlcmVkO1xuICB9O1xuXG4gIFNlYXJjaC5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIGNvbnRhaW5lciwgJGNvbnRhaW5lcikge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsIGNvbnRhaW5lciwgJGNvbnRhaW5lcik7XG5cbiAgICBjb250YWluZXIub24oJ29wZW4nLCBmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLiRzZWFyY2gudHJpZ2dlcignZm9jdXMnKTtcbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbignY2xvc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLiRzZWFyY2gudmFsKCcnKTtcbiAgICAgIHNlbGYuJHNlYXJjaC5yZW1vdmVBdHRyKCdhcmlhLWFjdGl2ZWRlc2NlbmRhbnQnKTtcbiAgICAgIHNlbGYuJHNlYXJjaC50cmlnZ2VyKCdmb2N1cycpO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdlbmFibGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLiRzZWFyY2gucHJvcCgnZGlzYWJsZWQnLCBmYWxzZSk7XG5cbiAgICAgIHNlbGYuX3RyYW5zZmVyVGFiSW5kZXgoKTtcbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbignZGlzYWJsZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYuJHNlYXJjaC5wcm9wKCdkaXNhYmxlZCcsIHRydWUpO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdmb2N1cycsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIHNlbGYuJHNlYXJjaC50cmlnZ2VyKCdmb2N1cycpO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdyZXN1bHRzOmZvY3VzJywgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgc2VsZi4kc2VhcmNoLmF0dHIoJ2FyaWEtYWN0aXZlZGVzY2VuZGFudCcsIHBhcmFtcy5pZCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLiRzZWxlY3Rpb24ub24oJ2ZvY3VzaW4nLCAnLnNlbGVjdDItc2VhcmNoLS1pbmxpbmUnLCBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICBzZWxmLnRyaWdnZXIoJ2ZvY3VzJywgZXZ0KTtcbiAgICB9KTtcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5vbignZm9jdXNvdXQnLCAnLnNlbGVjdDItc2VhcmNoLS1pbmxpbmUnLCBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICBzZWxmLl9oYW5kbGVCbHVyKGV2dCk7XG4gICAgfSk7XG5cbiAgICB0aGlzLiRzZWxlY3Rpb24ub24oJ2tleWRvd24nLCAnLnNlbGVjdDItc2VhcmNoLS1pbmxpbmUnLCBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICBldnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICAgIHNlbGYudHJpZ2dlcigna2V5cHJlc3MnLCBldnQpO1xuXG4gICAgICBzZWxmLl9rZXlVcFByZXZlbnRlZCA9IGV2dC5pc0RlZmF1bHRQcmV2ZW50ZWQoKTtcblxuICAgICAgdmFyIGtleSA9IGV2dC53aGljaDtcblxuICAgICAgaWYgKGtleSA9PT0gS0VZUy5CQUNLU1BBQ0UgJiYgc2VsZi4kc2VhcmNoLnZhbCgpID09PSAnJykge1xuICAgICAgICB2YXIgJHByZXZpb3VzQ2hvaWNlID0gc2VsZi4kc2VhcmNoQ29udGFpbmVyXG4gICAgICAgICAgLnByZXYoJy5zZWxlY3QyLXNlbGVjdGlvbl9fY2hvaWNlJyk7XG5cbiAgICAgICAgaWYgKCRwcmV2aW91c0Nob2ljZS5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgdmFyIGl0ZW0gPSBVdGlscy5HZXREYXRhKCRwcmV2aW91c0Nob2ljZVswXSwgJ2RhdGEnKTtcblxuICAgICAgICAgIHNlbGYuc2VhcmNoUmVtb3ZlQ2hvaWNlKGl0ZW0pO1xuXG4gICAgICAgICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFRyeSB0byBkZXRlY3QgdGhlIElFIHZlcnNpb24gc2hvdWxkIHRoZSBgZG9jdW1lbnRNb2RlYCBwcm9wZXJ0eSB0aGF0XG4gICAgLy8gaXMgc3RvcmVkIG9uIHRoZSBkb2N1bWVudC4gVGhpcyBpcyBvbmx5IGltcGxlbWVudGVkIGluIElFIGFuZCBpc1xuICAgIC8vIHNsaWdodGx5IGNsZWFuZXIgdGhhbiBkb2luZyBhIHVzZXIgYWdlbnQgY2hlY2suXG4gICAgLy8gVGhpcyBwcm9wZXJ0eSBpcyBub3QgYXZhaWxhYmxlIGluIEVkZ2UsIGJ1dCBFZGdlIGFsc28gZG9lc24ndCBoYXZlXG4gICAgLy8gdGhpcyBidWcuXG4gICAgdmFyIG1zaWUgPSBkb2N1bWVudC5kb2N1bWVudE1vZGU7XG4gICAgdmFyIGRpc2FibGVJbnB1dEV2ZW50cyA9IG1zaWUgJiYgbXNpZSA8PSAxMTtcblxuICAgIC8vIFdvcmthcm91bmQgZm9yIGJyb3dzZXJzIHdoaWNoIGRvIG5vdCBzdXBwb3J0IHRoZSBgaW5wdXRgIGV2ZW50XG4gICAgLy8gVGhpcyB3aWxsIHByZXZlbnQgZG91YmxlLXRyaWdnZXJpbmcgb2YgZXZlbnRzIGZvciBicm93c2VycyB3aGljaCBzdXBwb3J0XG4gICAgLy8gYm90aCB0aGUgYGtleXVwYCBhbmQgYGlucHV0YCBldmVudHMuXG4gICAgdGhpcy4kc2VsZWN0aW9uLm9uKFxuICAgICAgJ2lucHV0LnNlYXJjaGNoZWNrJyxcbiAgICAgICcuc2VsZWN0Mi1zZWFyY2gtLWlubGluZScsXG4gICAgICBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICAgIC8vIElFIHdpbGwgdHJpZ2dlciB0aGUgYGlucHV0YCBldmVudCB3aGVuIGEgcGxhY2Vob2xkZXIgaXMgdXNlZCBvbiBhXG4gICAgICAgIC8vIHNlYXJjaCBib3guIFRvIGdldCBhcm91bmQgdGhpcyBpc3N1ZSwgd2UgYXJlIGZvcmNlZCB0byBpZ25vcmUgYWxsXG4gICAgICAgIC8vIGBpbnB1dGAgZXZlbnRzIGluIElFIGFuZCBrZWVwIHVzaW5nIGBrZXl1cGAuXG4gICAgICAgIGlmIChkaXNhYmxlSW5wdXRFdmVudHMpIHtcbiAgICAgICAgICBzZWxmLiRzZWxlY3Rpb24ub2ZmKCdpbnB1dC5zZWFyY2ggaW5wdXQuc2VhcmNoY2hlY2snKTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVbmJpbmQgdGhlIGR1cGxpY2F0ZWQgYGtleXVwYCBldmVudFxuICAgICAgICBzZWxmLiRzZWxlY3Rpb24ub2ZmKCdrZXl1cC5zZWFyY2gnKTtcbiAgICAgIH1cbiAgICApO1xuXG4gICAgdGhpcy4kc2VsZWN0aW9uLm9uKFxuICAgICAgJ2tleXVwLnNlYXJjaCBpbnB1dC5zZWFyY2gnLFxuICAgICAgJy5zZWxlY3QyLXNlYXJjaC0taW5saW5lJyxcbiAgICAgIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgICAgLy8gSUUgd2lsbCB0cmlnZ2VyIHRoZSBgaW5wdXRgIGV2ZW50IHdoZW4gYSBwbGFjZWhvbGRlciBpcyB1c2VkIG9uIGFcbiAgICAgICAgLy8gc2VhcmNoIGJveC4gVG8gZ2V0IGFyb3VuZCB0aGlzIGlzc3VlLCB3ZSBhcmUgZm9yY2VkIHRvIGlnbm9yZSBhbGxcbiAgICAgICAgLy8gYGlucHV0YCBldmVudHMgaW4gSUUgYW5kIGtlZXAgdXNpbmcgYGtleXVwYC5cbiAgICAgICAgaWYgKGRpc2FibGVJbnB1dEV2ZW50cyAmJiBldnQudHlwZSA9PT0gJ2lucHV0Jykge1xuICAgICAgICAgIHNlbGYuJHNlbGVjdGlvbi5vZmYoJ2lucHV0LnNlYXJjaCBpbnB1dC5zZWFyY2hjaGVjaycpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBrZXkgPSBldnQud2hpY2g7XG5cbiAgICAgICAgLy8gV2UgY2FuIGZyZWVseSBpZ25vcmUgZXZlbnRzIGZyb20gbW9kaWZpZXIga2V5c1xuICAgICAgICBpZiAoa2V5ID09IEtFWVMuU0hJRlQgfHwga2V5ID09IEtFWVMuQ1RSTCB8fCBrZXkgPT0gS0VZUy5BTFQpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUYWJiaW5nIHdpbGwgYmUgaGFuZGxlZCBkdXJpbmcgdGhlIGBrZXlkb3duYCBwaGFzZVxuICAgICAgICBpZiAoa2V5ID09IEtFWVMuVEFCKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgc2VsZi5oYW5kbGVTZWFyY2goZXZ0KTtcbiAgICAgIH1cbiAgICApO1xuICB9O1xuXG4gIC8qKlxuICAgKiBUaGlzIG1ldGhvZCB3aWxsIHRyYW5zZmVyIHRoZSB0YWJpbmRleCBhdHRyaWJ1dGUgZnJvbSB0aGUgcmVuZGVyZWRcbiAgICogc2VsZWN0aW9uIHRvIHRoZSBzZWFyY2ggYm94LiBUaGlzIGFsbG93cyBmb3IgdGhlIHNlYXJjaCBib3ggdG8gYmUgdXNlZCBhc1xuICAgKiB0aGUgcHJpbWFyeSBmb2N1cyBpbnN0ZWFkIG9mIHRoZSBzZWxlY3Rpb24gY29udGFpbmVyLlxuICAgKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgU2VhcmNoLnByb3RvdHlwZS5fdHJhbnNmZXJUYWJJbmRleCA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQpIHtcbiAgICB0aGlzLiRzZWFyY2guYXR0cigndGFiaW5kZXgnLCB0aGlzLiRzZWxlY3Rpb24uYXR0cigndGFiaW5kZXgnKSk7XG4gICAgdGhpcy4kc2VsZWN0aW9uLmF0dHIoJ3RhYmluZGV4JywgJy0xJyk7XG4gIH07XG5cbiAgU2VhcmNoLnByb3RvdHlwZS5jcmVhdGVQbGFjZWhvbGRlciA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIHBsYWNlaG9sZGVyKSB7XG4gICAgdGhpcy4kc2VhcmNoLmF0dHIoJ3BsYWNlaG9sZGVyJywgcGxhY2Vob2xkZXIudGV4dCk7XG4gIH07XG5cbiAgU2VhcmNoLnByb3RvdHlwZS51cGRhdGUgPSBmdW5jdGlvbiAoZGVjb3JhdGVkLCBkYXRhKSB7XG4gICAgdmFyIHNlYXJjaEhhZEZvY3VzID0gdGhpcy4kc2VhcmNoWzBdID09IGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQ7XG5cbiAgICB0aGlzLiRzZWFyY2guYXR0cigncGxhY2Vob2xkZXInLCAnJyk7XG5cbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBkYXRhKTtcblxuICAgIHRoaXMuJHNlbGVjdGlvbi5maW5kKCcuc2VsZWN0Mi1zZWxlY3Rpb25fX3JlbmRlcmVkJylcbiAgICAgICAgICAgICAgICAgICAuYXBwZW5kKHRoaXMuJHNlYXJjaENvbnRhaW5lcik7XG5cbiAgICB0aGlzLnJlc2l6ZVNlYXJjaCgpO1xuICAgIGlmIChzZWFyY2hIYWRGb2N1cykge1xuICAgICAgdmFyIGlzVGFnSW5wdXQgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ1tkYXRhLXNlbGVjdDItdGFnXScpLmxlbmd0aDtcbiAgICAgIGlmIChpc1RhZ0lucHV0KSB7XG4gICAgICAgIC8vIGZpeCBJRTExIGJ1ZyB3aGVyZSB0YWcgaW5wdXQgbG9zdCBmb2N1c1xuICAgICAgICB0aGlzLiRlbGVtZW50LmZvY3VzKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLiRzZWFyY2guZm9jdXMoKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG5cbiAgU2VhcmNoLnByb3RvdHlwZS5oYW5kbGVTZWFyY2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5yZXNpemVTZWFyY2goKTtcblxuICAgIGlmICghdGhpcy5fa2V5VXBQcmV2ZW50ZWQpIHtcbiAgICAgIHZhciBpbnB1dCA9IHRoaXMuJHNlYXJjaC52YWwoKTtcblxuICAgICAgdGhpcy50cmlnZ2VyKCdxdWVyeScsIHtcbiAgICAgICAgdGVybTogaW5wdXRcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuX2tleVVwUHJldmVudGVkID0gZmFsc2U7XG4gIH07XG5cbiAgU2VhcmNoLnByb3RvdHlwZS5zZWFyY2hSZW1vdmVDaG9pY2UgPSBmdW5jdGlvbiAoZGVjb3JhdGVkLCBpdGVtKSB7XG4gICAgdGhpcy50cmlnZ2VyKCd1bnNlbGVjdCcsIHtcbiAgICAgIGRhdGE6IGl0ZW1cbiAgICB9KTtcblxuICAgIHRoaXMuJHNlYXJjaC52YWwoaXRlbS50ZXh0KTtcbiAgICB0aGlzLmhhbmRsZVNlYXJjaCgpO1xuICB9O1xuXG4gIFNlYXJjaC5wcm90b3R5cGUucmVzaXplU2VhcmNoID0gZnVuY3Rpb24gKCkge1xuICAgIHRoaXMuJHNlYXJjaC5jc3MoJ3dpZHRoJywgJzI1cHgnKTtcblxuICAgIHZhciB3aWR0aCA9ICcnO1xuXG4gICAgaWYgKHRoaXMuJHNlYXJjaC5hdHRyKCdwbGFjZWhvbGRlcicpICE9PSAnJykge1xuICAgICAgd2lkdGggPSB0aGlzLiRzZWxlY3Rpb24uZmluZCgnLnNlbGVjdDItc2VsZWN0aW9uX19yZW5kZXJlZCcpLmlubmVyV2lkdGgoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIG1pbmltdW1XaWR0aCA9IHRoaXMuJHNlYXJjaC52YWwoKS5sZW5ndGggKyAxO1xuXG4gICAgICB3aWR0aCA9IChtaW5pbXVtV2lkdGggKiAwLjc1KSArICdlbSc7XG4gICAgfVxuXG4gICAgdGhpcy4kc2VhcmNoLmNzcygnd2lkdGgnLCB3aWR0aCk7XG4gIH07XG5cbiAgcmV0dXJuIFNlYXJjaDtcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIvc2VsZWN0aW9uL2V2ZW50UmVsYXknLFtcbiAgJ2pxdWVyeSdcbl0sIGZ1bmN0aW9uICgkKSB7XG4gIGZ1bmN0aW9uIEV2ZW50UmVsYXkgKCkgeyB9XG5cbiAgRXZlbnRSZWxheS5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIGNvbnRhaW5lciwgJGNvbnRhaW5lcikge1xuICAgIHZhciBzZWxmID0gdGhpcztcbiAgICB2YXIgcmVsYXlFdmVudHMgPSBbXG4gICAgICAnb3BlbicsICdvcGVuaW5nJyxcbiAgICAgICdjbG9zZScsICdjbG9zaW5nJyxcbiAgICAgICdzZWxlY3QnLCAnc2VsZWN0aW5nJyxcbiAgICAgICd1bnNlbGVjdCcsICd1bnNlbGVjdGluZycsXG4gICAgICAnY2xlYXInLCAnY2xlYXJpbmcnXG4gICAgXTtcblxuICAgIHZhciBwcmV2ZW50YWJsZUV2ZW50cyA9IFtcbiAgICAgICdvcGVuaW5nJywgJ2Nsb3NpbmcnLCAnc2VsZWN0aW5nJywgJ3Vuc2VsZWN0aW5nJywgJ2NsZWFyaW5nJ1xuICAgIF07XG5cbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBjb250YWluZXIsICRjb250YWluZXIpO1xuXG4gICAgY29udGFpbmVyLm9uKCcqJywgZnVuY3Rpb24gKG5hbWUsIHBhcmFtcykge1xuICAgICAgLy8gSWdub3JlIGV2ZW50cyB0aGF0IHNob3VsZCBub3QgYmUgcmVsYXllZFxuICAgICAgaWYgKCQuaW5BcnJheShuYW1lLCByZWxheUV2ZW50cykgPT09IC0xKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gVGhlIHBhcmFtZXRlcnMgc2hvdWxkIGFsd2F5cyBiZSBhbiBvYmplY3RcbiAgICAgIHBhcmFtcyA9IHBhcmFtcyB8fCB7fTtcblxuICAgICAgLy8gR2VuZXJhdGUgdGhlIGpRdWVyeSBldmVudCBmb3IgdGhlIFNlbGVjdDIgZXZlbnRcbiAgICAgIHZhciBldnQgPSAkLkV2ZW50KCdzZWxlY3QyOicgKyBuYW1lLCB7XG4gICAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgICB9KTtcblxuICAgICAgc2VsZi4kZWxlbWVudC50cmlnZ2VyKGV2dCk7XG5cbiAgICAgIC8vIE9ubHkgaGFuZGxlIHByZXZlbnRhYmxlIGV2ZW50cyBpZiBpdCB3YXMgb25lXG4gICAgICBpZiAoJC5pbkFycmF5KG5hbWUsIHByZXZlbnRhYmxlRXZlbnRzKSA9PT0gLTEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBwYXJhbXMucHJldmVudGVkID0gZXZ0LmlzRGVmYXVsdFByZXZlbnRlZCgpO1xuICAgIH0pO1xuICB9O1xuXG4gIHJldHVybiBFdmVudFJlbGF5O1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi90cmFuc2xhdGlvbicsW1xuICAnanF1ZXJ5JyxcbiAgJ3JlcXVpcmUnXG5dLCBmdW5jdGlvbiAoJCwgcmVxdWlyZSkge1xuICBmdW5jdGlvbiBUcmFuc2xhdGlvbiAoZGljdCkge1xuICAgIHRoaXMuZGljdCA9IGRpY3QgfHwge307XG4gIH1cblxuICBUcmFuc2xhdGlvbi5wcm90b3R5cGUuYWxsID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLmRpY3Q7XG4gIH07XG5cbiAgVHJhbnNsYXRpb24ucHJvdG90eXBlLmdldCA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgICByZXR1cm4gdGhpcy5kaWN0W2tleV07XG4gIH07XG5cbiAgVHJhbnNsYXRpb24ucHJvdG90eXBlLmV4dGVuZCA9IGZ1bmN0aW9uICh0cmFuc2xhdGlvbikge1xuICAgIHRoaXMuZGljdCA9ICQuZXh0ZW5kKHt9LCB0cmFuc2xhdGlvbi5hbGwoKSwgdGhpcy5kaWN0KTtcbiAgfTtcblxuICAvLyBTdGF0aWMgZnVuY3Rpb25zXG5cbiAgVHJhbnNsYXRpb24uX2NhY2hlID0ge307XG5cbiAgVHJhbnNsYXRpb24ubG9hZFBhdGggPSBmdW5jdGlvbiAocGF0aCkge1xuICAgIGlmICghKHBhdGggaW4gVHJhbnNsYXRpb24uX2NhY2hlKSkge1xuICAgICAgdmFyIHRyYW5zbGF0aW9ucyA9IHJlcXVpcmUocGF0aCk7XG5cbiAgICAgIFRyYW5zbGF0aW9uLl9jYWNoZVtwYXRoXSA9IHRyYW5zbGF0aW9ucztcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFRyYW5zbGF0aW9uKFRyYW5zbGF0aW9uLl9jYWNoZVtwYXRoXSk7XG4gIH07XG5cbiAgcmV0dXJuIFRyYW5zbGF0aW9uO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9kaWFjcml0aWNzJyxbXG5cbl0sIGZ1bmN0aW9uICgpIHtcbiAgdmFyIGRpYWNyaXRpY3MgPSB7XG4gICAgJ1xcdTI0QjYnOiAnQScsXG4gICAgJ1xcdUZGMjEnOiAnQScsXG4gICAgJ1xcdTAwQzAnOiAnQScsXG4gICAgJ1xcdTAwQzEnOiAnQScsXG4gICAgJ1xcdTAwQzInOiAnQScsXG4gICAgJ1xcdTFFQTYnOiAnQScsXG4gICAgJ1xcdTFFQTQnOiAnQScsXG4gICAgJ1xcdTFFQUEnOiAnQScsXG4gICAgJ1xcdTFFQTgnOiAnQScsXG4gICAgJ1xcdTAwQzMnOiAnQScsXG4gICAgJ1xcdTAxMDAnOiAnQScsXG4gICAgJ1xcdTAxMDInOiAnQScsXG4gICAgJ1xcdTFFQjAnOiAnQScsXG4gICAgJ1xcdTFFQUUnOiAnQScsXG4gICAgJ1xcdTFFQjQnOiAnQScsXG4gICAgJ1xcdTFFQjInOiAnQScsXG4gICAgJ1xcdTAyMjYnOiAnQScsXG4gICAgJ1xcdTAxRTAnOiAnQScsXG4gICAgJ1xcdTAwQzQnOiAnQScsXG4gICAgJ1xcdTAxREUnOiAnQScsXG4gICAgJ1xcdTFFQTInOiAnQScsXG4gICAgJ1xcdTAwQzUnOiAnQScsXG4gICAgJ1xcdTAxRkEnOiAnQScsXG4gICAgJ1xcdTAxQ0QnOiAnQScsXG4gICAgJ1xcdTAyMDAnOiAnQScsXG4gICAgJ1xcdTAyMDInOiAnQScsXG4gICAgJ1xcdTFFQTAnOiAnQScsXG4gICAgJ1xcdTFFQUMnOiAnQScsXG4gICAgJ1xcdTFFQjYnOiAnQScsXG4gICAgJ1xcdTFFMDAnOiAnQScsXG4gICAgJ1xcdTAxMDQnOiAnQScsXG4gICAgJ1xcdTAyM0EnOiAnQScsXG4gICAgJ1xcdTJDNkYnOiAnQScsXG4gICAgJ1xcdUE3MzInOiAnQUEnLFxuICAgICdcXHUwMEM2JzogJ0FFJyxcbiAgICAnXFx1MDFGQyc6ICdBRScsXG4gICAgJ1xcdTAxRTInOiAnQUUnLFxuICAgICdcXHVBNzM0JzogJ0FPJyxcbiAgICAnXFx1QTczNic6ICdBVScsXG4gICAgJ1xcdUE3MzgnOiAnQVYnLFxuICAgICdcXHVBNzNBJzogJ0FWJyxcbiAgICAnXFx1QTczQyc6ICdBWScsXG4gICAgJ1xcdTI0QjcnOiAnQicsXG4gICAgJ1xcdUZGMjInOiAnQicsXG4gICAgJ1xcdTFFMDInOiAnQicsXG4gICAgJ1xcdTFFMDQnOiAnQicsXG4gICAgJ1xcdTFFMDYnOiAnQicsXG4gICAgJ1xcdTAyNDMnOiAnQicsXG4gICAgJ1xcdTAxODInOiAnQicsXG4gICAgJ1xcdTAxODEnOiAnQicsXG4gICAgJ1xcdTI0QjgnOiAnQycsXG4gICAgJ1xcdUZGMjMnOiAnQycsXG4gICAgJ1xcdTAxMDYnOiAnQycsXG4gICAgJ1xcdTAxMDgnOiAnQycsXG4gICAgJ1xcdTAxMEEnOiAnQycsXG4gICAgJ1xcdTAxMEMnOiAnQycsXG4gICAgJ1xcdTAwQzcnOiAnQycsXG4gICAgJ1xcdTFFMDgnOiAnQycsXG4gICAgJ1xcdTAxODcnOiAnQycsXG4gICAgJ1xcdTAyM0InOiAnQycsXG4gICAgJ1xcdUE3M0UnOiAnQycsXG4gICAgJ1xcdTI0QjknOiAnRCcsXG4gICAgJ1xcdUZGMjQnOiAnRCcsXG4gICAgJ1xcdTFFMEEnOiAnRCcsXG4gICAgJ1xcdTAxMEUnOiAnRCcsXG4gICAgJ1xcdTFFMEMnOiAnRCcsXG4gICAgJ1xcdTFFMTAnOiAnRCcsXG4gICAgJ1xcdTFFMTInOiAnRCcsXG4gICAgJ1xcdTFFMEUnOiAnRCcsXG4gICAgJ1xcdTAxMTAnOiAnRCcsXG4gICAgJ1xcdTAxOEInOiAnRCcsXG4gICAgJ1xcdTAxOEEnOiAnRCcsXG4gICAgJ1xcdTAxODknOiAnRCcsXG4gICAgJ1xcdUE3NzknOiAnRCcsXG4gICAgJ1xcdTAxRjEnOiAnRFonLFxuICAgICdcXHUwMUM0JzogJ0RaJyxcbiAgICAnXFx1MDFGMic6ICdEeicsXG4gICAgJ1xcdTAxQzUnOiAnRHonLFxuICAgICdcXHUyNEJBJzogJ0UnLFxuICAgICdcXHVGRjI1JzogJ0UnLFxuICAgICdcXHUwMEM4JzogJ0UnLFxuICAgICdcXHUwMEM5JzogJ0UnLFxuICAgICdcXHUwMENBJzogJ0UnLFxuICAgICdcXHUxRUMwJzogJ0UnLFxuICAgICdcXHUxRUJFJzogJ0UnLFxuICAgICdcXHUxRUM0JzogJ0UnLFxuICAgICdcXHUxRUMyJzogJ0UnLFxuICAgICdcXHUxRUJDJzogJ0UnLFxuICAgICdcXHUwMTEyJzogJ0UnLFxuICAgICdcXHUxRTE0JzogJ0UnLFxuICAgICdcXHUxRTE2JzogJ0UnLFxuICAgICdcXHUwMTE0JzogJ0UnLFxuICAgICdcXHUwMTE2JzogJ0UnLFxuICAgICdcXHUwMENCJzogJ0UnLFxuICAgICdcXHUxRUJBJzogJ0UnLFxuICAgICdcXHUwMTFBJzogJ0UnLFxuICAgICdcXHUwMjA0JzogJ0UnLFxuICAgICdcXHUwMjA2JzogJ0UnLFxuICAgICdcXHUxRUI4JzogJ0UnLFxuICAgICdcXHUxRUM2JzogJ0UnLFxuICAgICdcXHUwMjI4JzogJ0UnLFxuICAgICdcXHUxRTFDJzogJ0UnLFxuICAgICdcXHUwMTE4JzogJ0UnLFxuICAgICdcXHUxRTE4JzogJ0UnLFxuICAgICdcXHUxRTFBJzogJ0UnLFxuICAgICdcXHUwMTkwJzogJ0UnLFxuICAgICdcXHUwMThFJzogJ0UnLFxuICAgICdcXHUyNEJCJzogJ0YnLFxuICAgICdcXHVGRjI2JzogJ0YnLFxuICAgICdcXHUxRTFFJzogJ0YnLFxuICAgICdcXHUwMTkxJzogJ0YnLFxuICAgICdcXHVBNzdCJzogJ0YnLFxuICAgICdcXHUyNEJDJzogJ0cnLFxuICAgICdcXHVGRjI3JzogJ0cnLFxuICAgICdcXHUwMUY0JzogJ0cnLFxuICAgICdcXHUwMTFDJzogJ0cnLFxuICAgICdcXHUxRTIwJzogJ0cnLFxuICAgICdcXHUwMTFFJzogJ0cnLFxuICAgICdcXHUwMTIwJzogJ0cnLFxuICAgICdcXHUwMUU2JzogJ0cnLFxuICAgICdcXHUwMTIyJzogJ0cnLFxuICAgICdcXHUwMUU0JzogJ0cnLFxuICAgICdcXHUwMTkzJzogJ0cnLFxuICAgICdcXHVBN0EwJzogJ0cnLFxuICAgICdcXHVBNzdEJzogJ0cnLFxuICAgICdcXHVBNzdFJzogJ0cnLFxuICAgICdcXHUyNEJEJzogJ0gnLFxuICAgICdcXHVGRjI4JzogJ0gnLFxuICAgICdcXHUwMTI0JzogJ0gnLFxuICAgICdcXHUxRTIyJzogJ0gnLFxuICAgICdcXHUxRTI2JzogJ0gnLFxuICAgICdcXHUwMjFFJzogJ0gnLFxuICAgICdcXHUxRTI0JzogJ0gnLFxuICAgICdcXHUxRTI4JzogJ0gnLFxuICAgICdcXHUxRTJBJzogJ0gnLFxuICAgICdcXHUwMTI2JzogJ0gnLFxuICAgICdcXHUyQzY3JzogJ0gnLFxuICAgICdcXHUyQzc1JzogJ0gnLFxuICAgICdcXHVBNzhEJzogJ0gnLFxuICAgICdcXHUyNEJFJzogJ0knLFxuICAgICdcXHVGRjI5JzogJ0knLFxuICAgICdcXHUwMENDJzogJ0knLFxuICAgICdcXHUwMENEJzogJ0knLFxuICAgICdcXHUwMENFJzogJ0knLFxuICAgICdcXHUwMTI4JzogJ0knLFxuICAgICdcXHUwMTJBJzogJ0knLFxuICAgICdcXHUwMTJDJzogJ0knLFxuICAgICdcXHUwMTMwJzogJ0knLFxuICAgICdcXHUwMENGJzogJ0knLFxuICAgICdcXHUxRTJFJzogJ0knLFxuICAgICdcXHUxRUM4JzogJ0knLFxuICAgICdcXHUwMUNGJzogJ0knLFxuICAgICdcXHUwMjA4JzogJ0knLFxuICAgICdcXHUwMjBBJzogJ0knLFxuICAgICdcXHUxRUNBJzogJ0knLFxuICAgICdcXHUwMTJFJzogJ0knLFxuICAgICdcXHUxRTJDJzogJ0knLFxuICAgICdcXHUwMTk3JzogJ0knLFxuICAgICdcXHUyNEJGJzogJ0onLFxuICAgICdcXHVGRjJBJzogJ0onLFxuICAgICdcXHUwMTM0JzogJ0onLFxuICAgICdcXHUwMjQ4JzogJ0onLFxuICAgICdcXHUyNEMwJzogJ0snLFxuICAgICdcXHVGRjJCJzogJ0snLFxuICAgICdcXHUxRTMwJzogJ0snLFxuICAgICdcXHUwMUU4JzogJ0snLFxuICAgICdcXHUxRTMyJzogJ0snLFxuICAgICdcXHUwMTM2JzogJ0snLFxuICAgICdcXHUxRTM0JzogJ0snLFxuICAgICdcXHUwMTk4JzogJ0snLFxuICAgICdcXHUyQzY5JzogJ0snLFxuICAgICdcXHVBNzQwJzogJ0snLFxuICAgICdcXHVBNzQyJzogJ0snLFxuICAgICdcXHVBNzQ0JzogJ0snLFxuICAgICdcXHVBN0EyJzogJ0snLFxuICAgICdcXHUyNEMxJzogJ0wnLFxuICAgICdcXHVGRjJDJzogJ0wnLFxuICAgICdcXHUwMTNGJzogJ0wnLFxuICAgICdcXHUwMTM5JzogJ0wnLFxuICAgICdcXHUwMTNEJzogJ0wnLFxuICAgICdcXHUxRTM2JzogJ0wnLFxuICAgICdcXHUxRTM4JzogJ0wnLFxuICAgICdcXHUwMTNCJzogJ0wnLFxuICAgICdcXHUxRTNDJzogJ0wnLFxuICAgICdcXHUxRTNBJzogJ0wnLFxuICAgICdcXHUwMTQxJzogJ0wnLFxuICAgICdcXHUwMjNEJzogJ0wnLFxuICAgICdcXHUyQzYyJzogJ0wnLFxuICAgICdcXHUyQzYwJzogJ0wnLFxuICAgICdcXHVBNzQ4JzogJ0wnLFxuICAgICdcXHVBNzQ2JzogJ0wnLFxuICAgICdcXHVBNzgwJzogJ0wnLFxuICAgICdcXHUwMUM3JzogJ0xKJyxcbiAgICAnXFx1MDFDOCc6ICdMaicsXG4gICAgJ1xcdTI0QzInOiAnTScsXG4gICAgJ1xcdUZGMkQnOiAnTScsXG4gICAgJ1xcdTFFM0UnOiAnTScsXG4gICAgJ1xcdTFFNDAnOiAnTScsXG4gICAgJ1xcdTFFNDInOiAnTScsXG4gICAgJ1xcdTJDNkUnOiAnTScsXG4gICAgJ1xcdTAxOUMnOiAnTScsXG4gICAgJ1xcdTI0QzMnOiAnTicsXG4gICAgJ1xcdUZGMkUnOiAnTicsXG4gICAgJ1xcdTAxRjgnOiAnTicsXG4gICAgJ1xcdTAxNDMnOiAnTicsXG4gICAgJ1xcdTAwRDEnOiAnTicsXG4gICAgJ1xcdTFFNDQnOiAnTicsXG4gICAgJ1xcdTAxNDcnOiAnTicsXG4gICAgJ1xcdTFFNDYnOiAnTicsXG4gICAgJ1xcdTAxNDUnOiAnTicsXG4gICAgJ1xcdTFFNEEnOiAnTicsXG4gICAgJ1xcdTFFNDgnOiAnTicsXG4gICAgJ1xcdTAyMjAnOiAnTicsXG4gICAgJ1xcdTAxOUQnOiAnTicsXG4gICAgJ1xcdUE3OTAnOiAnTicsXG4gICAgJ1xcdUE3QTQnOiAnTicsXG4gICAgJ1xcdTAxQ0EnOiAnTkonLFxuICAgICdcXHUwMUNCJzogJ05qJyxcbiAgICAnXFx1MjRDNCc6ICdPJyxcbiAgICAnXFx1RkYyRic6ICdPJyxcbiAgICAnXFx1MDBEMic6ICdPJyxcbiAgICAnXFx1MDBEMyc6ICdPJyxcbiAgICAnXFx1MDBENCc6ICdPJyxcbiAgICAnXFx1MUVEMic6ICdPJyxcbiAgICAnXFx1MUVEMCc6ICdPJyxcbiAgICAnXFx1MUVENic6ICdPJyxcbiAgICAnXFx1MUVENCc6ICdPJyxcbiAgICAnXFx1MDBENSc6ICdPJyxcbiAgICAnXFx1MUU0Qyc6ICdPJyxcbiAgICAnXFx1MDIyQyc6ICdPJyxcbiAgICAnXFx1MUU0RSc6ICdPJyxcbiAgICAnXFx1MDE0Qyc6ICdPJyxcbiAgICAnXFx1MUU1MCc6ICdPJyxcbiAgICAnXFx1MUU1Mic6ICdPJyxcbiAgICAnXFx1MDE0RSc6ICdPJyxcbiAgICAnXFx1MDIyRSc6ICdPJyxcbiAgICAnXFx1MDIzMCc6ICdPJyxcbiAgICAnXFx1MDBENic6ICdPJyxcbiAgICAnXFx1MDIyQSc6ICdPJyxcbiAgICAnXFx1MUVDRSc6ICdPJyxcbiAgICAnXFx1MDE1MCc6ICdPJyxcbiAgICAnXFx1MDFEMSc6ICdPJyxcbiAgICAnXFx1MDIwQyc6ICdPJyxcbiAgICAnXFx1MDIwRSc6ICdPJyxcbiAgICAnXFx1MDFBMCc6ICdPJyxcbiAgICAnXFx1MUVEQyc6ICdPJyxcbiAgICAnXFx1MUVEQSc6ICdPJyxcbiAgICAnXFx1MUVFMCc6ICdPJyxcbiAgICAnXFx1MUVERSc6ICdPJyxcbiAgICAnXFx1MUVFMic6ICdPJyxcbiAgICAnXFx1MUVDQyc6ICdPJyxcbiAgICAnXFx1MUVEOCc6ICdPJyxcbiAgICAnXFx1MDFFQSc6ICdPJyxcbiAgICAnXFx1MDFFQyc6ICdPJyxcbiAgICAnXFx1MDBEOCc6ICdPJyxcbiAgICAnXFx1MDFGRSc6ICdPJyxcbiAgICAnXFx1MDE4Nic6ICdPJyxcbiAgICAnXFx1MDE5Ric6ICdPJyxcbiAgICAnXFx1QTc0QSc6ICdPJyxcbiAgICAnXFx1QTc0Qyc6ICdPJyxcbiAgICAnXFx1MDFBMic6ICdPSScsXG4gICAgJ1xcdUE3NEUnOiAnT08nLFxuICAgICdcXHUwMjIyJzogJ09VJyxcbiAgICAnXFx1MjRDNSc6ICdQJyxcbiAgICAnXFx1RkYzMCc6ICdQJyxcbiAgICAnXFx1MUU1NCc6ICdQJyxcbiAgICAnXFx1MUU1Nic6ICdQJyxcbiAgICAnXFx1MDFBNCc6ICdQJyxcbiAgICAnXFx1MkM2Myc6ICdQJyxcbiAgICAnXFx1QTc1MCc6ICdQJyxcbiAgICAnXFx1QTc1Mic6ICdQJyxcbiAgICAnXFx1QTc1NCc6ICdQJyxcbiAgICAnXFx1MjRDNic6ICdRJyxcbiAgICAnXFx1RkYzMSc6ICdRJyxcbiAgICAnXFx1QTc1Nic6ICdRJyxcbiAgICAnXFx1QTc1OCc6ICdRJyxcbiAgICAnXFx1MDI0QSc6ICdRJyxcbiAgICAnXFx1MjRDNyc6ICdSJyxcbiAgICAnXFx1RkYzMic6ICdSJyxcbiAgICAnXFx1MDE1NCc6ICdSJyxcbiAgICAnXFx1MUU1OCc6ICdSJyxcbiAgICAnXFx1MDE1OCc6ICdSJyxcbiAgICAnXFx1MDIxMCc6ICdSJyxcbiAgICAnXFx1MDIxMic6ICdSJyxcbiAgICAnXFx1MUU1QSc6ICdSJyxcbiAgICAnXFx1MUU1Qyc6ICdSJyxcbiAgICAnXFx1MDE1Nic6ICdSJyxcbiAgICAnXFx1MUU1RSc6ICdSJyxcbiAgICAnXFx1MDI0Qyc6ICdSJyxcbiAgICAnXFx1MkM2NCc6ICdSJyxcbiAgICAnXFx1QTc1QSc6ICdSJyxcbiAgICAnXFx1QTdBNic6ICdSJyxcbiAgICAnXFx1QTc4Mic6ICdSJyxcbiAgICAnXFx1MjRDOCc6ICdTJyxcbiAgICAnXFx1RkYzMyc6ICdTJyxcbiAgICAnXFx1MUU5RSc6ICdTJyxcbiAgICAnXFx1MDE1QSc6ICdTJyxcbiAgICAnXFx1MUU2NCc6ICdTJyxcbiAgICAnXFx1MDE1Qyc6ICdTJyxcbiAgICAnXFx1MUU2MCc6ICdTJyxcbiAgICAnXFx1MDE2MCc6ICdTJyxcbiAgICAnXFx1MUU2Nic6ICdTJyxcbiAgICAnXFx1MUU2Mic6ICdTJyxcbiAgICAnXFx1MUU2OCc6ICdTJyxcbiAgICAnXFx1MDIxOCc6ICdTJyxcbiAgICAnXFx1MDE1RSc6ICdTJyxcbiAgICAnXFx1MkM3RSc6ICdTJyxcbiAgICAnXFx1QTdBOCc6ICdTJyxcbiAgICAnXFx1QTc4NCc6ICdTJyxcbiAgICAnXFx1MjRDOSc6ICdUJyxcbiAgICAnXFx1RkYzNCc6ICdUJyxcbiAgICAnXFx1MUU2QSc6ICdUJyxcbiAgICAnXFx1MDE2NCc6ICdUJyxcbiAgICAnXFx1MUU2Qyc6ICdUJyxcbiAgICAnXFx1MDIxQSc6ICdUJyxcbiAgICAnXFx1MDE2Mic6ICdUJyxcbiAgICAnXFx1MUU3MCc6ICdUJyxcbiAgICAnXFx1MUU2RSc6ICdUJyxcbiAgICAnXFx1MDE2Nic6ICdUJyxcbiAgICAnXFx1MDFBQyc6ICdUJyxcbiAgICAnXFx1MDFBRSc6ICdUJyxcbiAgICAnXFx1MDIzRSc6ICdUJyxcbiAgICAnXFx1QTc4Nic6ICdUJyxcbiAgICAnXFx1QTcyOCc6ICdUWicsXG4gICAgJ1xcdTI0Q0EnOiAnVScsXG4gICAgJ1xcdUZGMzUnOiAnVScsXG4gICAgJ1xcdTAwRDknOiAnVScsXG4gICAgJ1xcdTAwREEnOiAnVScsXG4gICAgJ1xcdTAwREInOiAnVScsXG4gICAgJ1xcdTAxNjgnOiAnVScsXG4gICAgJ1xcdTFFNzgnOiAnVScsXG4gICAgJ1xcdTAxNkEnOiAnVScsXG4gICAgJ1xcdTFFN0EnOiAnVScsXG4gICAgJ1xcdTAxNkMnOiAnVScsXG4gICAgJ1xcdTAwREMnOiAnVScsXG4gICAgJ1xcdTAxREInOiAnVScsXG4gICAgJ1xcdTAxRDcnOiAnVScsXG4gICAgJ1xcdTAxRDUnOiAnVScsXG4gICAgJ1xcdTAxRDknOiAnVScsXG4gICAgJ1xcdTFFRTYnOiAnVScsXG4gICAgJ1xcdTAxNkUnOiAnVScsXG4gICAgJ1xcdTAxNzAnOiAnVScsXG4gICAgJ1xcdTAxRDMnOiAnVScsXG4gICAgJ1xcdTAyMTQnOiAnVScsXG4gICAgJ1xcdTAyMTYnOiAnVScsXG4gICAgJ1xcdTAxQUYnOiAnVScsXG4gICAgJ1xcdTFFRUEnOiAnVScsXG4gICAgJ1xcdTFFRTgnOiAnVScsXG4gICAgJ1xcdTFFRUUnOiAnVScsXG4gICAgJ1xcdTFFRUMnOiAnVScsXG4gICAgJ1xcdTFFRjAnOiAnVScsXG4gICAgJ1xcdTFFRTQnOiAnVScsXG4gICAgJ1xcdTFFNzInOiAnVScsXG4gICAgJ1xcdTAxNzInOiAnVScsXG4gICAgJ1xcdTFFNzYnOiAnVScsXG4gICAgJ1xcdTFFNzQnOiAnVScsXG4gICAgJ1xcdTAyNDQnOiAnVScsXG4gICAgJ1xcdTI0Q0InOiAnVicsXG4gICAgJ1xcdUZGMzYnOiAnVicsXG4gICAgJ1xcdTFFN0MnOiAnVicsXG4gICAgJ1xcdTFFN0UnOiAnVicsXG4gICAgJ1xcdTAxQjInOiAnVicsXG4gICAgJ1xcdUE3NUUnOiAnVicsXG4gICAgJ1xcdTAyNDUnOiAnVicsXG4gICAgJ1xcdUE3NjAnOiAnVlknLFxuICAgICdcXHUyNENDJzogJ1cnLFxuICAgICdcXHVGRjM3JzogJ1cnLFxuICAgICdcXHUxRTgwJzogJ1cnLFxuICAgICdcXHUxRTgyJzogJ1cnLFxuICAgICdcXHUwMTc0JzogJ1cnLFxuICAgICdcXHUxRTg2JzogJ1cnLFxuICAgICdcXHUxRTg0JzogJ1cnLFxuICAgICdcXHUxRTg4JzogJ1cnLFxuICAgICdcXHUyQzcyJzogJ1cnLFxuICAgICdcXHUyNENEJzogJ1gnLFxuICAgICdcXHVGRjM4JzogJ1gnLFxuICAgICdcXHUxRThBJzogJ1gnLFxuICAgICdcXHUxRThDJzogJ1gnLFxuICAgICdcXHUyNENFJzogJ1knLFxuICAgICdcXHVGRjM5JzogJ1knLFxuICAgICdcXHUxRUYyJzogJ1knLFxuICAgICdcXHUwMEREJzogJ1knLFxuICAgICdcXHUwMTc2JzogJ1knLFxuICAgICdcXHUxRUY4JzogJ1knLFxuICAgICdcXHUwMjMyJzogJ1knLFxuICAgICdcXHUxRThFJzogJ1knLFxuICAgICdcXHUwMTc4JzogJ1knLFxuICAgICdcXHUxRUY2JzogJ1knLFxuICAgICdcXHUxRUY0JzogJ1knLFxuICAgICdcXHUwMUIzJzogJ1knLFxuICAgICdcXHUwMjRFJzogJ1knLFxuICAgICdcXHUxRUZFJzogJ1knLFxuICAgICdcXHUyNENGJzogJ1onLFxuICAgICdcXHVGRjNBJzogJ1onLFxuICAgICdcXHUwMTc5JzogJ1onLFxuICAgICdcXHUxRTkwJzogJ1onLFxuICAgICdcXHUwMTdCJzogJ1onLFxuICAgICdcXHUwMTdEJzogJ1onLFxuICAgICdcXHUxRTkyJzogJ1onLFxuICAgICdcXHUxRTk0JzogJ1onLFxuICAgICdcXHUwMUI1JzogJ1onLFxuICAgICdcXHUwMjI0JzogJ1onLFxuICAgICdcXHUyQzdGJzogJ1onLFxuICAgICdcXHUyQzZCJzogJ1onLFxuICAgICdcXHVBNzYyJzogJ1onLFxuICAgICdcXHUyNEQwJzogJ2EnLFxuICAgICdcXHVGRjQxJzogJ2EnLFxuICAgICdcXHUxRTlBJzogJ2EnLFxuICAgICdcXHUwMEUwJzogJ2EnLFxuICAgICdcXHUwMEUxJzogJ2EnLFxuICAgICdcXHUwMEUyJzogJ2EnLFxuICAgICdcXHUxRUE3JzogJ2EnLFxuICAgICdcXHUxRUE1JzogJ2EnLFxuICAgICdcXHUxRUFCJzogJ2EnLFxuICAgICdcXHUxRUE5JzogJ2EnLFxuICAgICdcXHUwMEUzJzogJ2EnLFxuICAgICdcXHUwMTAxJzogJ2EnLFxuICAgICdcXHUwMTAzJzogJ2EnLFxuICAgICdcXHUxRUIxJzogJ2EnLFxuICAgICdcXHUxRUFGJzogJ2EnLFxuICAgICdcXHUxRUI1JzogJ2EnLFxuICAgICdcXHUxRUIzJzogJ2EnLFxuICAgICdcXHUwMjI3JzogJ2EnLFxuICAgICdcXHUwMUUxJzogJ2EnLFxuICAgICdcXHUwMEU0JzogJ2EnLFxuICAgICdcXHUwMURGJzogJ2EnLFxuICAgICdcXHUxRUEzJzogJ2EnLFxuICAgICdcXHUwMEU1JzogJ2EnLFxuICAgICdcXHUwMUZCJzogJ2EnLFxuICAgICdcXHUwMUNFJzogJ2EnLFxuICAgICdcXHUwMjAxJzogJ2EnLFxuICAgICdcXHUwMjAzJzogJ2EnLFxuICAgICdcXHUxRUExJzogJ2EnLFxuICAgICdcXHUxRUFEJzogJ2EnLFxuICAgICdcXHUxRUI3JzogJ2EnLFxuICAgICdcXHUxRTAxJzogJ2EnLFxuICAgICdcXHUwMTA1JzogJ2EnLFxuICAgICdcXHUyQzY1JzogJ2EnLFxuICAgICdcXHUwMjUwJzogJ2EnLFxuICAgICdcXHVBNzMzJzogJ2FhJyxcbiAgICAnXFx1MDBFNic6ICdhZScsXG4gICAgJ1xcdTAxRkQnOiAnYWUnLFxuICAgICdcXHUwMUUzJzogJ2FlJyxcbiAgICAnXFx1QTczNSc6ICdhbycsXG4gICAgJ1xcdUE3MzcnOiAnYXUnLFxuICAgICdcXHVBNzM5JzogJ2F2JyxcbiAgICAnXFx1QTczQic6ICdhdicsXG4gICAgJ1xcdUE3M0QnOiAnYXknLFxuICAgICdcXHUyNEQxJzogJ2InLFxuICAgICdcXHVGRjQyJzogJ2InLFxuICAgICdcXHUxRTAzJzogJ2InLFxuICAgICdcXHUxRTA1JzogJ2InLFxuICAgICdcXHUxRTA3JzogJ2InLFxuICAgICdcXHUwMTgwJzogJ2InLFxuICAgICdcXHUwMTgzJzogJ2InLFxuICAgICdcXHUwMjUzJzogJ2InLFxuICAgICdcXHUyNEQyJzogJ2MnLFxuICAgICdcXHVGRjQzJzogJ2MnLFxuICAgICdcXHUwMTA3JzogJ2MnLFxuICAgICdcXHUwMTA5JzogJ2MnLFxuICAgICdcXHUwMTBCJzogJ2MnLFxuICAgICdcXHUwMTBEJzogJ2MnLFxuICAgICdcXHUwMEU3JzogJ2MnLFxuICAgICdcXHUxRTA5JzogJ2MnLFxuICAgICdcXHUwMTg4JzogJ2MnLFxuICAgICdcXHUwMjNDJzogJ2MnLFxuICAgICdcXHVBNzNGJzogJ2MnLFxuICAgICdcXHUyMTg0JzogJ2MnLFxuICAgICdcXHUyNEQzJzogJ2QnLFxuICAgICdcXHVGRjQ0JzogJ2QnLFxuICAgICdcXHUxRTBCJzogJ2QnLFxuICAgICdcXHUwMTBGJzogJ2QnLFxuICAgICdcXHUxRTBEJzogJ2QnLFxuICAgICdcXHUxRTExJzogJ2QnLFxuICAgICdcXHUxRTEzJzogJ2QnLFxuICAgICdcXHUxRTBGJzogJ2QnLFxuICAgICdcXHUwMTExJzogJ2QnLFxuICAgICdcXHUwMThDJzogJ2QnLFxuICAgICdcXHUwMjU2JzogJ2QnLFxuICAgICdcXHUwMjU3JzogJ2QnLFxuICAgICdcXHVBNzdBJzogJ2QnLFxuICAgICdcXHUwMUYzJzogJ2R6JyxcbiAgICAnXFx1MDFDNic6ICdkeicsXG4gICAgJ1xcdTI0RDQnOiAnZScsXG4gICAgJ1xcdUZGNDUnOiAnZScsXG4gICAgJ1xcdTAwRTgnOiAnZScsXG4gICAgJ1xcdTAwRTknOiAnZScsXG4gICAgJ1xcdTAwRUEnOiAnZScsXG4gICAgJ1xcdTFFQzEnOiAnZScsXG4gICAgJ1xcdTFFQkYnOiAnZScsXG4gICAgJ1xcdTFFQzUnOiAnZScsXG4gICAgJ1xcdTFFQzMnOiAnZScsXG4gICAgJ1xcdTFFQkQnOiAnZScsXG4gICAgJ1xcdTAxMTMnOiAnZScsXG4gICAgJ1xcdTFFMTUnOiAnZScsXG4gICAgJ1xcdTFFMTcnOiAnZScsXG4gICAgJ1xcdTAxMTUnOiAnZScsXG4gICAgJ1xcdTAxMTcnOiAnZScsXG4gICAgJ1xcdTAwRUInOiAnZScsXG4gICAgJ1xcdTFFQkInOiAnZScsXG4gICAgJ1xcdTAxMUInOiAnZScsXG4gICAgJ1xcdTAyMDUnOiAnZScsXG4gICAgJ1xcdTAyMDcnOiAnZScsXG4gICAgJ1xcdTFFQjknOiAnZScsXG4gICAgJ1xcdTFFQzcnOiAnZScsXG4gICAgJ1xcdTAyMjknOiAnZScsXG4gICAgJ1xcdTFFMUQnOiAnZScsXG4gICAgJ1xcdTAxMTknOiAnZScsXG4gICAgJ1xcdTFFMTknOiAnZScsXG4gICAgJ1xcdTFFMUInOiAnZScsXG4gICAgJ1xcdTAyNDcnOiAnZScsXG4gICAgJ1xcdTAyNUInOiAnZScsXG4gICAgJ1xcdTAxREQnOiAnZScsXG4gICAgJ1xcdTI0RDUnOiAnZicsXG4gICAgJ1xcdUZGNDYnOiAnZicsXG4gICAgJ1xcdTFFMUYnOiAnZicsXG4gICAgJ1xcdTAxOTInOiAnZicsXG4gICAgJ1xcdUE3N0MnOiAnZicsXG4gICAgJ1xcdTI0RDYnOiAnZycsXG4gICAgJ1xcdUZGNDcnOiAnZycsXG4gICAgJ1xcdTAxRjUnOiAnZycsXG4gICAgJ1xcdTAxMUQnOiAnZycsXG4gICAgJ1xcdTFFMjEnOiAnZycsXG4gICAgJ1xcdTAxMUYnOiAnZycsXG4gICAgJ1xcdTAxMjEnOiAnZycsXG4gICAgJ1xcdTAxRTcnOiAnZycsXG4gICAgJ1xcdTAxMjMnOiAnZycsXG4gICAgJ1xcdTAxRTUnOiAnZycsXG4gICAgJ1xcdTAyNjAnOiAnZycsXG4gICAgJ1xcdUE3QTEnOiAnZycsXG4gICAgJ1xcdTFENzknOiAnZycsXG4gICAgJ1xcdUE3N0YnOiAnZycsXG4gICAgJ1xcdTI0RDcnOiAnaCcsXG4gICAgJ1xcdUZGNDgnOiAnaCcsXG4gICAgJ1xcdTAxMjUnOiAnaCcsXG4gICAgJ1xcdTFFMjMnOiAnaCcsXG4gICAgJ1xcdTFFMjcnOiAnaCcsXG4gICAgJ1xcdTAyMUYnOiAnaCcsXG4gICAgJ1xcdTFFMjUnOiAnaCcsXG4gICAgJ1xcdTFFMjknOiAnaCcsXG4gICAgJ1xcdTFFMkInOiAnaCcsXG4gICAgJ1xcdTFFOTYnOiAnaCcsXG4gICAgJ1xcdTAxMjcnOiAnaCcsXG4gICAgJ1xcdTJDNjgnOiAnaCcsXG4gICAgJ1xcdTJDNzYnOiAnaCcsXG4gICAgJ1xcdTAyNjUnOiAnaCcsXG4gICAgJ1xcdTAxOTUnOiAnaHYnLFxuICAgICdcXHUyNEQ4JzogJ2knLFxuICAgICdcXHVGRjQ5JzogJ2knLFxuICAgICdcXHUwMEVDJzogJ2knLFxuICAgICdcXHUwMEVEJzogJ2knLFxuICAgICdcXHUwMEVFJzogJ2knLFxuICAgICdcXHUwMTI5JzogJ2knLFxuICAgICdcXHUwMTJCJzogJ2knLFxuICAgICdcXHUwMTJEJzogJ2knLFxuICAgICdcXHUwMEVGJzogJ2knLFxuICAgICdcXHUxRTJGJzogJ2knLFxuICAgICdcXHUxRUM5JzogJ2knLFxuICAgICdcXHUwMUQwJzogJ2knLFxuICAgICdcXHUwMjA5JzogJ2knLFxuICAgICdcXHUwMjBCJzogJ2knLFxuICAgICdcXHUxRUNCJzogJ2knLFxuICAgICdcXHUwMTJGJzogJ2knLFxuICAgICdcXHUxRTJEJzogJ2knLFxuICAgICdcXHUwMjY4JzogJ2knLFxuICAgICdcXHUwMTMxJzogJ2knLFxuICAgICdcXHUyNEQ5JzogJ2onLFxuICAgICdcXHVGRjRBJzogJ2onLFxuICAgICdcXHUwMTM1JzogJ2onLFxuICAgICdcXHUwMUYwJzogJ2onLFxuICAgICdcXHUwMjQ5JzogJ2onLFxuICAgICdcXHUyNERBJzogJ2snLFxuICAgICdcXHVGRjRCJzogJ2snLFxuICAgICdcXHUxRTMxJzogJ2snLFxuICAgICdcXHUwMUU5JzogJ2snLFxuICAgICdcXHUxRTMzJzogJ2snLFxuICAgICdcXHUwMTM3JzogJ2snLFxuICAgICdcXHUxRTM1JzogJ2snLFxuICAgICdcXHUwMTk5JzogJ2snLFxuICAgICdcXHUyQzZBJzogJ2snLFxuICAgICdcXHVBNzQxJzogJ2snLFxuICAgICdcXHVBNzQzJzogJ2snLFxuICAgICdcXHVBNzQ1JzogJ2snLFxuICAgICdcXHVBN0EzJzogJ2snLFxuICAgICdcXHUyNERCJzogJ2wnLFxuICAgICdcXHVGRjRDJzogJ2wnLFxuICAgICdcXHUwMTQwJzogJ2wnLFxuICAgICdcXHUwMTNBJzogJ2wnLFxuICAgICdcXHUwMTNFJzogJ2wnLFxuICAgICdcXHUxRTM3JzogJ2wnLFxuICAgICdcXHUxRTM5JzogJ2wnLFxuICAgICdcXHUwMTNDJzogJ2wnLFxuICAgICdcXHUxRTNEJzogJ2wnLFxuICAgICdcXHUxRTNCJzogJ2wnLFxuICAgICdcXHUwMTdGJzogJ2wnLFxuICAgICdcXHUwMTQyJzogJ2wnLFxuICAgICdcXHUwMTlBJzogJ2wnLFxuICAgICdcXHUwMjZCJzogJ2wnLFxuICAgICdcXHUyQzYxJzogJ2wnLFxuICAgICdcXHVBNzQ5JzogJ2wnLFxuICAgICdcXHVBNzgxJzogJ2wnLFxuICAgICdcXHVBNzQ3JzogJ2wnLFxuICAgICdcXHUwMUM5JzogJ2xqJyxcbiAgICAnXFx1MjREQyc6ICdtJyxcbiAgICAnXFx1RkY0RCc6ICdtJyxcbiAgICAnXFx1MUUzRic6ICdtJyxcbiAgICAnXFx1MUU0MSc6ICdtJyxcbiAgICAnXFx1MUU0Myc6ICdtJyxcbiAgICAnXFx1MDI3MSc6ICdtJyxcbiAgICAnXFx1MDI2Ric6ICdtJyxcbiAgICAnXFx1MjRERCc6ICduJyxcbiAgICAnXFx1RkY0RSc6ICduJyxcbiAgICAnXFx1MDFGOSc6ICduJyxcbiAgICAnXFx1MDE0NCc6ICduJyxcbiAgICAnXFx1MDBGMSc6ICduJyxcbiAgICAnXFx1MUU0NSc6ICduJyxcbiAgICAnXFx1MDE0OCc6ICduJyxcbiAgICAnXFx1MUU0Nyc6ICduJyxcbiAgICAnXFx1MDE0Nic6ICduJyxcbiAgICAnXFx1MUU0Qic6ICduJyxcbiAgICAnXFx1MUU0OSc6ICduJyxcbiAgICAnXFx1MDE5RSc6ICduJyxcbiAgICAnXFx1MDI3Mic6ICduJyxcbiAgICAnXFx1MDE0OSc6ICduJyxcbiAgICAnXFx1QTc5MSc6ICduJyxcbiAgICAnXFx1QTdBNSc6ICduJyxcbiAgICAnXFx1MDFDQyc6ICduaicsXG4gICAgJ1xcdTI0REUnOiAnbycsXG4gICAgJ1xcdUZGNEYnOiAnbycsXG4gICAgJ1xcdTAwRjInOiAnbycsXG4gICAgJ1xcdTAwRjMnOiAnbycsXG4gICAgJ1xcdTAwRjQnOiAnbycsXG4gICAgJ1xcdTFFRDMnOiAnbycsXG4gICAgJ1xcdTFFRDEnOiAnbycsXG4gICAgJ1xcdTFFRDcnOiAnbycsXG4gICAgJ1xcdTFFRDUnOiAnbycsXG4gICAgJ1xcdTAwRjUnOiAnbycsXG4gICAgJ1xcdTFFNEQnOiAnbycsXG4gICAgJ1xcdTAyMkQnOiAnbycsXG4gICAgJ1xcdTFFNEYnOiAnbycsXG4gICAgJ1xcdTAxNEQnOiAnbycsXG4gICAgJ1xcdTFFNTEnOiAnbycsXG4gICAgJ1xcdTFFNTMnOiAnbycsXG4gICAgJ1xcdTAxNEYnOiAnbycsXG4gICAgJ1xcdTAyMkYnOiAnbycsXG4gICAgJ1xcdTAyMzEnOiAnbycsXG4gICAgJ1xcdTAwRjYnOiAnbycsXG4gICAgJ1xcdTAyMkInOiAnbycsXG4gICAgJ1xcdTFFQ0YnOiAnbycsXG4gICAgJ1xcdTAxNTEnOiAnbycsXG4gICAgJ1xcdTAxRDInOiAnbycsXG4gICAgJ1xcdTAyMEQnOiAnbycsXG4gICAgJ1xcdTAyMEYnOiAnbycsXG4gICAgJ1xcdTAxQTEnOiAnbycsXG4gICAgJ1xcdTFFREQnOiAnbycsXG4gICAgJ1xcdTFFREInOiAnbycsXG4gICAgJ1xcdTFFRTEnOiAnbycsXG4gICAgJ1xcdTFFREYnOiAnbycsXG4gICAgJ1xcdTFFRTMnOiAnbycsXG4gICAgJ1xcdTFFQ0QnOiAnbycsXG4gICAgJ1xcdTFFRDknOiAnbycsXG4gICAgJ1xcdTAxRUInOiAnbycsXG4gICAgJ1xcdTAxRUQnOiAnbycsXG4gICAgJ1xcdTAwRjgnOiAnbycsXG4gICAgJ1xcdTAxRkYnOiAnbycsXG4gICAgJ1xcdTAyNTQnOiAnbycsXG4gICAgJ1xcdUE3NEInOiAnbycsXG4gICAgJ1xcdUE3NEQnOiAnbycsXG4gICAgJ1xcdTAyNzUnOiAnbycsXG4gICAgJ1xcdTAxQTMnOiAnb2knLFxuICAgICdcXHUwMjIzJzogJ291JyxcbiAgICAnXFx1QTc0Ric6ICdvbycsXG4gICAgJ1xcdTI0REYnOiAncCcsXG4gICAgJ1xcdUZGNTAnOiAncCcsXG4gICAgJ1xcdTFFNTUnOiAncCcsXG4gICAgJ1xcdTFFNTcnOiAncCcsXG4gICAgJ1xcdTAxQTUnOiAncCcsXG4gICAgJ1xcdTFEN0QnOiAncCcsXG4gICAgJ1xcdUE3NTEnOiAncCcsXG4gICAgJ1xcdUE3NTMnOiAncCcsXG4gICAgJ1xcdUE3NTUnOiAncCcsXG4gICAgJ1xcdTI0RTAnOiAncScsXG4gICAgJ1xcdUZGNTEnOiAncScsXG4gICAgJ1xcdTAyNEInOiAncScsXG4gICAgJ1xcdUE3NTcnOiAncScsXG4gICAgJ1xcdUE3NTknOiAncScsXG4gICAgJ1xcdTI0RTEnOiAncicsXG4gICAgJ1xcdUZGNTInOiAncicsXG4gICAgJ1xcdTAxNTUnOiAncicsXG4gICAgJ1xcdTFFNTknOiAncicsXG4gICAgJ1xcdTAxNTknOiAncicsXG4gICAgJ1xcdTAyMTEnOiAncicsXG4gICAgJ1xcdTAyMTMnOiAncicsXG4gICAgJ1xcdTFFNUInOiAncicsXG4gICAgJ1xcdTFFNUQnOiAncicsXG4gICAgJ1xcdTAxNTcnOiAncicsXG4gICAgJ1xcdTFFNUYnOiAncicsXG4gICAgJ1xcdTAyNEQnOiAncicsXG4gICAgJ1xcdTAyN0QnOiAncicsXG4gICAgJ1xcdUE3NUInOiAncicsXG4gICAgJ1xcdUE3QTcnOiAncicsXG4gICAgJ1xcdUE3ODMnOiAncicsXG4gICAgJ1xcdTI0RTInOiAncycsXG4gICAgJ1xcdUZGNTMnOiAncycsXG4gICAgJ1xcdTAwREYnOiAncycsXG4gICAgJ1xcdTAxNUInOiAncycsXG4gICAgJ1xcdTFFNjUnOiAncycsXG4gICAgJ1xcdTAxNUQnOiAncycsXG4gICAgJ1xcdTFFNjEnOiAncycsXG4gICAgJ1xcdTAxNjEnOiAncycsXG4gICAgJ1xcdTFFNjcnOiAncycsXG4gICAgJ1xcdTFFNjMnOiAncycsXG4gICAgJ1xcdTFFNjknOiAncycsXG4gICAgJ1xcdTAyMTknOiAncycsXG4gICAgJ1xcdTAxNUYnOiAncycsXG4gICAgJ1xcdTAyM0YnOiAncycsXG4gICAgJ1xcdUE3QTknOiAncycsXG4gICAgJ1xcdUE3ODUnOiAncycsXG4gICAgJ1xcdTFFOUInOiAncycsXG4gICAgJ1xcdTI0RTMnOiAndCcsXG4gICAgJ1xcdUZGNTQnOiAndCcsXG4gICAgJ1xcdTFFNkInOiAndCcsXG4gICAgJ1xcdTFFOTcnOiAndCcsXG4gICAgJ1xcdTAxNjUnOiAndCcsXG4gICAgJ1xcdTFFNkQnOiAndCcsXG4gICAgJ1xcdTAyMUInOiAndCcsXG4gICAgJ1xcdTAxNjMnOiAndCcsXG4gICAgJ1xcdTFFNzEnOiAndCcsXG4gICAgJ1xcdTFFNkYnOiAndCcsXG4gICAgJ1xcdTAxNjcnOiAndCcsXG4gICAgJ1xcdTAxQUQnOiAndCcsXG4gICAgJ1xcdTAyODgnOiAndCcsXG4gICAgJ1xcdTJDNjYnOiAndCcsXG4gICAgJ1xcdUE3ODcnOiAndCcsXG4gICAgJ1xcdUE3MjknOiAndHonLFxuICAgICdcXHUyNEU0JzogJ3UnLFxuICAgICdcXHVGRjU1JzogJ3UnLFxuICAgICdcXHUwMEY5JzogJ3UnLFxuICAgICdcXHUwMEZBJzogJ3UnLFxuICAgICdcXHUwMEZCJzogJ3UnLFxuICAgICdcXHUwMTY5JzogJ3UnLFxuICAgICdcXHUxRTc5JzogJ3UnLFxuICAgICdcXHUwMTZCJzogJ3UnLFxuICAgICdcXHUxRTdCJzogJ3UnLFxuICAgICdcXHUwMTZEJzogJ3UnLFxuICAgICdcXHUwMEZDJzogJ3UnLFxuICAgICdcXHUwMURDJzogJ3UnLFxuICAgICdcXHUwMUQ4JzogJ3UnLFxuICAgICdcXHUwMUQ2JzogJ3UnLFxuICAgICdcXHUwMURBJzogJ3UnLFxuICAgICdcXHUxRUU3JzogJ3UnLFxuICAgICdcXHUwMTZGJzogJ3UnLFxuICAgICdcXHUwMTcxJzogJ3UnLFxuICAgICdcXHUwMUQ0JzogJ3UnLFxuICAgICdcXHUwMjE1JzogJ3UnLFxuICAgICdcXHUwMjE3JzogJ3UnLFxuICAgICdcXHUwMUIwJzogJ3UnLFxuICAgICdcXHUxRUVCJzogJ3UnLFxuICAgICdcXHUxRUU5JzogJ3UnLFxuICAgICdcXHUxRUVGJzogJ3UnLFxuICAgICdcXHUxRUVEJzogJ3UnLFxuICAgICdcXHUxRUYxJzogJ3UnLFxuICAgICdcXHUxRUU1JzogJ3UnLFxuICAgICdcXHUxRTczJzogJ3UnLFxuICAgICdcXHUwMTczJzogJ3UnLFxuICAgICdcXHUxRTc3JzogJ3UnLFxuICAgICdcXHUxRTc1JzogJ3UnLFxuICAgICdcXHUwMjg5JzogJ3UnLFxuICAgICdcXHUyNEU1JzogJ3YnLFxuICAgICdcXHVGRjU2JzogJ3YnLFxuICAgICdcXHUxRTdEJzogJ3YnLFxuICAgICdcXHUxRTdGJzogJ3YnLFxuICAgICdcXHUwMjhCJzogJ3YnLFxuICAgICdcXHVBNzVGJzogJ3YnLFxuICAgICdcXHUwMjhDJzogJ3YnLFxuICAgICdcXHVBNzYxJzogJ3Z5JyxcbiAgICAnXFx1MjRFNic6ICd3JyxcbiAgICAnXFx1RkY1Nyc6ICd3JyxcbiAgICAnXFx1MUU4MSc6ICd3JyxcbiAgICAnXFx1MUU4Myc6ICd3JyxcbiAgICAnXFx1MDE3NSc6ICd3JyxcbiAgICAnXFx1MUU4Nyc6ICd3JyxcbiAgICAnXFx1MUU4NSc6ICd3JyxcbiAgICAnXFx1MUU5OCc6ICd3JyxcbiAgICAnXFx1MUU4OSc6ICd3JyxcbiAgICAnXFx1MkM3Myc6ICd3JyxcbiAgICAnXFx1MjRFNyc6ICd4JyxcbiAgICAnXFx1RkY1OCc6ICd4JyxcbiAgICAnXFx1MUU4Qic6ICd4JyxcbiAgICAnXFx1MUU4RCc6ICd4JyxcbiAgICAnXFx1MjRFOCc6ICd5JyxcbiAgICAnXFx1RkY1OSc6ICd5JyxcbiAgICAnXFx1MUVGMyc6ICd5JyxcbiAgICAnXFx1MDBGRCc6ICd5JyxcbiAgICAnXFx1MDE3Nyc6ICd5JyxcbiAgICAnXFx1MUVGOSc6ICd5JyxcbiAgICAnXFx1MDIzMyc6ICd5JyxcbiAgICAnXFx1MUU4Ric6ICd5JyxcbiAgICAnXFx1MDBGRic6ICd5JyxcbiAgICAnXFx1MUVGNyc6ICd5JyxcbiAgICAnXFx1MUU5OSc6ICd5JyxcbiAgICAnXFx1MUVGNSc6ICd5JyxcbiAgICAnXFx1MDFCNCc6ICd5JyxcbiAgICAnXFx1MDI0Ric6ICd5JyxcbiAgICAnXFx1MUVGRic6ICd5JyxcbiAgICAnXFx1MjRFOSc6ICd6JyxcbiAgICAnXFx1RkY1QSc6ICd6JyxcbiAgICAnXFx1MDE3QSc6ICd6JyxcbiAgICAnXFx1MUU5MSc6ICd6JyxcbiAgICAnXFx1MDE3Qyc6ICd6JyxcbiAgICAnXFx1MDE3RSc6ICd6JyxcbiAgICAnXFx1MUU5Myc6ICd6JyxcbiAgICAnXFx1MUU5NSc6ICd6JyxcbiAgICAnXFx1MDFCNic6ICd6JyxcbiAgICAnXFx1MDIyNSc6ICd6JyxcbiAgICAnXFx1MDI0MCc6ICd6JyxcbiAgICAnXFx1MkM2Qyc6ICd6JyxcbiAgICAnXFx1QTc2Myc6ICd6JyxcbiAgICAnXFx1MDM4Nic6ICdcXHUwMzkxJyxcbiAgICAnXFx1MDM4OCc6ICdcXHUwMzk1JyxcbiAgICAnXFx1MDM4OSc6ICdcXHUwMzk3JyxcbiAgICAnXFx1MDM4QSc6ICdcXHUwMzk5JyxcbiAgICAnXFx1MDNBQSc6ICdcXHUwMzk5JyxcbiAgICAnXFx1MDM4Qyc6ICdcXHUwMzlGJyxcbiAgICAnXFx1MDM4RSc6ICdcXHUwM0E1JyxcbiAgICAnXFx1MDNBQic6ICdcXHUwM0E1JyxcbiAgICAnXFx1MDM4Ric6ICdcXHUwM0E5JyxcbiAgICAnXFx1MDNBQyc6ICdcXHUwM0IxJyxcbiAgICAnXFx1MDNBRCc6ICdcXHUwM0I1JyxcbiAgICAnXFx1MDNBRSc6ICdcXHUwM0I3JyxcbiAgICAnXFx1MDNBRic6ICdcXHUwM0I5JyxcbiAgICAnXFx1MDNDQSc6ICdcXHUwM0I5JyxcbiAgICAnXFx1MDM5MCc6ICdcXHUwM0I5JyxcbiAgICAnXFx1MDNDQyc6ICdcXHUwM0JGJyxcbiAgICAnXFx1MDNDRCc6ICdcXHUwM0M1JyxcbiAgICAnXFx1MDNDQic6ICdcXHUwM0M1JyxcbiAgICAnXFx1MDNCMCc6ICdcXHUwM0M1JyxcbiAgICAnXFx1MDNDOSc6ICdcXHUwM0M5JyxcbiAgICAnXFx1MDNDMic6ICdcXHUwM0MzJ1xuICB9O1xuXG4gIHJldHVybiBkaWFjcml0aWNzO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9kYXRhL2Jhc2UnLFtcbiAgJy4uL3V0aWxzJ1xuXSwgZnVuY3Rpb24gKFV0aWxzKSB7XG4gIGZ1bmN0aW9uIEJhc2VBZGFwdGVyICgkZWxlbWVudCwgb3B0aW9ucykge1xuICAgIEJhc2VBZGFwdGVyLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5jYWxsKHRoaXMpO1xuICB9XG5cbiAgVXRpbHMuRXh0ZW5kKEJhc2VBZGFwdGVyLCBVdGlscy5PYnNlcnZhYmxlKTtcblxuICBCYXNlQWRhcHRlci5wcm90b3R5cGUuY3VycmVudCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIHRocm93IG5ldyBFcnJvcignVGhlIGBjdXJyZW50YCBtZXRob2QgbXVzdCBiZSBkZWZpbmVkIGluIGNoaWxkIGNsYXNzZXMuJyk7XG4gIH07XG5cbiAgQmFzZUFkYXB0ZXIucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1RoZSBgcXVlcnlgIG1ldGhvZCBtdXN0IGJlIGRlZmluZWQgaW4gY2hpbGQgY2xhc3Nlcy4nKTtcbiAgfTtcblxuICBCYXNlQWRhcHRlci5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uIChjb250YWluZXIsICRjb250YWluZXIpIHtcbiAgICAvLyBDYW4gYmUgaW1wbGVtZW50ZWQgaW4gc3ViY2xhc3Nlc1xuICB9O1xuXG4gIEJhc2VBZGFwdGVyLnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xuICAgIC8vIENhbiBiZSBpbXBsZW1lbnRlZCBpbiBzdWJjbGFzc2VzXG4gIH07XG5cbiAgQmFzZUFkYXB0ZXIucHJvdG90eXBlLmdlbmVyYXRlUmVzdWx0SWQgPSBmdW5jdGlvbiAoY29udGFpbmVyLCBkYXRhKSB7XG4gICAgdmFyIGlkID0gY29udGFpbmVyLmlkICsgJy1yZXN1bHQtJztcblxuICAgIGlkICs9IFV0aWxzLmdlbmVyYXRlQ2hhcnMoNCk7XG5cbiAgICBpZiAoZGF0YS5pZCAhPSBudWxsKSB7XG4gICAgICBpZCArPSAnLScgKyBkYXRhLmlkLnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlkICs9ICctJyArIFV0aWxzLmdlbmVyYXRlQ2hhcnMoNCk7XG4gICAgfVxuICAgIHJldHVybiBpZDtcbiAgfTtcblxuICByZXR1cm4gQmFzZUFkYXB0ZXI7XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2RhdGEvc2VsZWN0JyxbXG4gICcuL2Jhc2UnLFxuICAnLi4vdXRpbHMnLFxuICAnanF1ZXJ5J1xuXSwgZnVuY3Rpb24gKEJhc2VBZGFwdGVyLCBVdGlscywgJCkge1xuICBmdW5jdGlvbiBTZWxlY3RBZGFwdGVyICgkZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMuJGVsZW1lbnQgPSAkZWxlbWVudDtcbiAgICB0aGlzLm9wdGlvbnMgPSBvcHRpb25zO1xuXG4gICAgU2VsZWN0QWRhcHRlci5fX3N1cGVyX18uY29uc3RydWN0b3IuY2FsbCh0aGlzKTtcbiAgfVxuXG4gIFV0aWxzLkV4dGVuZChTZWxlY3RBZGFwdGVyLCBCYXNlQWRhcHRlcik7XG5cbiAgU2VsZWN0QWRhcHRlci5wcm90b3R5cGUuY3VycmVudCA9IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgIHZhciBkYXRhID0gW107XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdGhpcy4kZWxlbWVudC5maW5kKCc6c2VsZWN0ZWQnKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIHZhciAkb3B0aW9uID0gJCh0aGlzKTtcblxuICAgICAgdmFyIG9wdGlvbiA9IHNlbGYuaXRlbSgkb3B0aW9uKTtcblxuICAgICAgZGF0YS5wdXNoKG9wdGlvbik7XG4gICAgfSk7XG5cbiAgICBjYWxsYmFjayhkYXRhKTtcbiAgfTtcblxuICBTZWxlY3RBZGFwdGVyLnByb3RvdHlwZS5zZWxlY3QgPSBmdW5jdGlvbiAoZGF0YSkge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIGRhdGEuc2VsZWN0ZWQgPSB0cnVlO1xuXG4gICAgLy8gSWYgZGF0YS5lbGVtZW50IGlzIGEgRE9NIG5vZGUsIHVzZSBpdCBpbnN0ZWFkXG4gICAgaWYgKCQoZGF0YS5lbGVtZW50KS5pcygnb3B0aW9uJykpIHtcbiAgICAgIGRhdGEuZWxlbWVudC5zZWxlY3RlZCA9IHRydWU7XG5cbiAgICAgIHRoaXMuJGVsZW1lbnQudHJpZ2dlcignY2hhbmdlJyk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy4kZWxlbWVudC5wcm9wKCdtdWx0aXBsZScpKSB7XG4gICAgICB0aGlzLmN1cnJlbnQoZnVuY3Rpb24gKGN1cnJlbnREYXRhKSB7XG4gICAgICAgIHZhciB2YWwgPSBbXTtcblxuICAgICAgICBkYXRhID0gW2RhdGFdO1xuICAgICAgICBkYXRhLnB1c2guYXBwbHkoZGF0YSwgY3VycmVudERhdGEpO1xuXG4gICAgICAgIGZvciAodmFyIGQgPSAwOyBkIDwgZGF0YS5sZW5ndGg7IGQrKykge1xuICAgICAgICAgIHZhciBpZCA9IGRhdGFbZF0uaWQ7XG5cbiAgICAgICAgICBpZiAoJC5pbkFycmF5KGlkLCB2YWwpID09PSAtMSkge1xuICAgICAgICAgICAgdmFsLnB1c2goaWQpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYuJGVsZW1lbnQudmFsKHZhbCk7XG4gICAgICAgIHNlbGYuJGVsZW1lbnQudHJpZ2dlcignY2hhbmdlJyk7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHZhbCA9IGRhdGEuaWQ7XG5cbiAgICAgIHRoaXMuJGVsZW1lbnQudmFsKHZhbCk7XG4gICAgICB0aGlzLiRlbGVtZW50LnRyaWdnZXIoJ2NoYW5nZScpO1xuICAgIH1cbiAgfTtcblxuICBTZWxlY3RBZGFwdGVyLnByb3RvdHlwZS51bnNlbGVjdCA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgaWYgKCF0aGlzLiRlbGVtZW50LnByb3AoJ211bHRpcGxlJykpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBkYXRhLnNlbGVjdGVkID0gZmFsc2U7XG5cbiAgICBpZiAoJChkYXRhLmVsZW1lbnQpLmlzKCdvcHRpb24nKSkge1xuICAgICAgZGF0YS5lbGVtZW50LnNlbGVjdGVkID0gZmFsc2U7XG5cbiAgICAgIHRoaXMuJGVsZW1lbnQudHJpZ2dlcignY2hhbmdlJyk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmN1cnJlbnQoZnVuY3Rpb24gKGN1cnJlbnREYXRhKSB7XG4gICAgICB2YXIgdmFsID0gW107XG5cbiAgICAgIGZvciAodmFyIGQgPSAwOyBkIDwgY3VycmVudERhdGEubGVuZ3RoOyBkKyspIHtcbiAgICAgICAgdmFyIGlkID0gY3VycmVudERhdGFbZF0uaWQ7XG5cbiAgICAgICAgaWYgKGlkICE9PSBkYXRhLmlkICYmICQuaW5BcnJheShpZCwgdmFsKSA9PT0gLTEpIHtcbiAgICAgICAgICB2YWwucHVzaChpZCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgc2VsZi4kZWxlbWVudC52YWwodmFsKTtcblxuICAgICAgc2VsZi4kZWxlbWVudC50cmlnZ2VyKCdjaGFuZ2UnKTtcbiAgICB9KTtcbiAgfTtcblxuICBTZWxlY3RBZGFwdGVyLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24gKGNvbnRhaW5lciwgJGNvbnRhaW5lcikge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHRoaXMuY29udGFpbmVyID0gY29udGFpbmVyO1xuXG4gICAgY29udGFpbmVyLm9uKCdzZWxlY3QnLCBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICBzZWxmLnNlbGVjdChwYXJhbXMuZGF0YSk7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ3Vuc2VsZWN0JywgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgc2VsZi51bnNlbGVjdChwYXJhbXMuZGF0YSk7XG4gICAgfSk7XG4gIH07XG5cbiAgU2VsZWN0QWRhcHRlci5wcm90b3R5cGUuZGVzdHJveSA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBSZW1vdmUgYW55dGhpbmcgYWRkZWQgdG8gY2hpbGQgZWxlbWVudHNcbiAgICB0aGlzLiRlbGVtZW50LmZpbmQoJyonKS5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgIC8vIFJlbW92ZSBhbnkgY3VzdG9tIGRhdGEgc2V0IGJ5IFNlbGVjdDJcbiAgICAgIFV0aWxzLlJlbW92ZURhdGEodGhpcyk7XG4gICAgfSk7XG4gIH07XG5cbiAgU2VsZWN0QWRhcHRlci5wcm90b3R5cGUucXVlcnkgPSBmdW5jdGlvbiAocGFyYW1zLCBjYWxsYmFjaykge1xuICAgIHZhciBkYXRhID0gW107XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyICRvcHRpb25zID0gdGhpcy4kZWxlbWVudC5jaGlsZHJlbigpO1xuXG4gICAgJG9wdGlvbnMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgJG9wdGlvbiA9ICQodGhpcyk7XG5cbiAgICAgIGlmICghJG9wdGlvbi5pcygnb3B0aW9uJykgJiYgISRvcHRpb24uaXMoJ29wdGdyb3VwJykpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgb3B0aW9uID0gc2VsZi5pdGVtKCRvcHRpb24pO1xuXG4gICAgICB2YXIgbWF0Y2hlcyA9IHNlbGYubWF0Y2hlcyhwYXJhbXMsIG9wdGlvbik7XG5cbiAgICAgIGlmIChtYXRjaGVzICE9PSBudWxsKSB7XG4gICAgICAgIGRhdGEucHVzaChtYXRjaGVzKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNhbGxiYWNrKHtcbiAgICAgIHJlc3VsdHM6IGRhdGFcbiAgICB9KTtcbiAgfTtcblxuICBTZWxlY3RBZGFwdGVyLnByb3RvdHlwZS5hZGRPcHRpb25zID0gZnVuY3Rpb24gKCRvcHRpb25zKSB7XG4gICAgVXRpbHMuYXBwZW5kTWFueSh0aGlzLiRlbGVtZW50LCAkb3B0aW9ucyk7XG4gIH07XG5cbiAgU2VsZWN0QWRhcHRlci5wcm90b3R5cGUub3B0aW9uID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICB2YXIgb3B0aW9uO1xuXG4gICAgaWYgKGRhdGEuY2hpbGRyZW4pIHtcbiAgICAgIG9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29wdGdyb3VwJyk7XG4gICAgICBvcHRpb24ubGFiZWwgPSBkYXRhLnRleHQ7XG4gICAgfSBlbHNlIHtcbiAgICAgIG9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ29wdGlvbicpO1xuXG4gICAgICBpZiAob3B0aW9uLnRleHRDb250ZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgb3B0aW9uLnRleHRDb250ZW50ID0gZGF0YS50ZXh0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3B0aW9uLmlubmVyVGV4dCA9IGRhdGEudGV4dDtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoZGF0YS5pZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBvcHRpb24udmFsdWUgPSBkYXRhLmlkO1xuICAgIH1cblxuICAgIGlmIChkYXRhLmRpc2FibGVkKSB7XG4gICAgICBvcHRpb24uZGlzYWJsZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChkYXRhLnNlbGVjdGVkKSB7XG4gICAgICBvcHRpb24uc2VsZWN0ZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmIChkYXRhLnRpdGxlKSB7XG4gICAgICBvcHRpb24udGl0bGUgPSBkYXRhLnRpdGxlO1xuICAgIH1cblxuICAgIHZhciAkb3B0aW9uID0gJChvcHRpb24pO1xuXG4gICAgdmFyIG5vcm1hbGl6ZWREYXRhID0gdGhpcy5fbm9ybWFsaXplSXRlbShkYXRhKTtcbiAgICBub3JtYWxpemVkRGF0YS5lbGVtZW50ID0gb3B0aW9uO1xuXG4gICAgLy8gT3ZlcnJpZGUgdGhlIG9wdGlvbidzIGRhdGEgd2l0aCB0aGUgY29tYmluZWQgZGF0YVxuICAgIFV0aWxzLlN0b3JlRGF0YShvcHRpb24sICdkYXRhJywgbm9ybWFsaXplZERhdGEpO1xuXG4gICAgcmV0dXJuICRvcHRpb247XG4gIH07XG5cbiAgU2VsZWN0QWRhcHRlci5wcm90b3R5cGUuaXRlbSA9IGZ1bmN0aW9uICgkb3B0aW9uKSB7XG4gICAgdmFyIGRhdGEgPSB7fTtcblxuICAgIGRhdGEgPSBVdGlscy5HZXREYXRhKCRvcHRpb25bMF0sICdkYXRhJyk7XG5cbiAgICBpZiAoZGF0YSAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gZGF0YTtcbiAgICB9XG5cbiAgICBpZiAoJG9wdGlvbi5pcygnb3B0aW9uJykpIHtcbiAgICAgIGRhdGEgPSB7XG4gICAgICAgIGlkOiAkb3B0aW9uLnZhbCgpLFxuICAgICAgICB0ZXh0OiAkb3B0aW9uLnRleHQoKSxcbiAgICAgICAgZGlzYWJsZWQ6ICRvcHRpb24ucHJvcCgnZGlzYWJsZWQnKSxcbiAgICAgICAgc2VsZWN0ZWQ6ICRvcHRpb24ucHJvcCgnc2VsZWN0ZWQnKSxcbiAgICAgICAgdGl0bGU6ICRvcHRpb24ucHJvcCgndGl0bGUnKVxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKCRvcHRpb24uaXMoJ29wdGdyb3VwJykpIHtcbiAgICAgIGRhdGEgPSB7XG4gICAgICAgIHRleHQ6ICRvcHRpb24ucHJvcCgnbGFiZWwnKSxcbiAgICAgICAgY2hpbGRyZW46IFtdLFxuICAgICAgICB0aXRsZTogJG9wdGlvbi5wcm9wKCd0aXRsZScpXG4gICAgICB9O1xuXG4gICAgICB2YXIgJGNoaWxkcmVuID0gJG9wdGlvbi5jaGlsZHJlbignb3B0aW9uJyk7XG4gICAgICB2YXIgY2hpbGRyZW4gPSBbXTtcblxuICAgICAgZm9yICh2YXIgYyA9IDA7IGMgPCAkY2hpbGRyZW4ubGVuZ3RoOyBjKyspIHtcbiAgICAgICAgdmFyICRjaGlsZCA9ICQoJGNoaWxkcmVuW2NdKTtcblxuICAgICAgICB2YXIgY2hpbGQgPSB0aGlzLml0ZW0oJGNoaWxkKTtcblxuICAgICAgICBjaGlsZHJlbi5wdXNoKGNoaWxkKTtcbiAgICAgIH1cblxuICAgICAgZGF0YS5jaGlsZHJlbiA9IGNoaWxkcmVuO1xuICAgIH1cblxuICAgIGRhdGEgPSB0aGlzLl9ub3JtYWxpemVJdGVtKGRhdGEpO1xuICAgIGRhdGEuZWxlbWVudCA9ICRvcHRpb25bMF07XG5cbiAgICBVdGlscy5TdG9yZURhdGEoJG9wdGlvblswXSwgJ2RhdGEnLCBkYXRhKTtcblxuICAgIHJldHVybiBkYXRhO1xuICB9O1xuXG4gIFNlbGVjdEFkYXB0ZXIucHJvdG90eXBlLl9ub3JtYWxpemVJdGVtID0gZnVuY3Rpb24gKGl0ZW0pIHtcbiAgICBpZiAoaXRlbSAhPT0gT2JqZWN0KGl0ZW0pKSB7XG4gICAgICBpdGVtID0ge1xuICAgICAgICBpZDogaXRlbSxcbiAgICAgICAgdGV4dDogaXRlbVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBpdGVtID0gJC5leHRlbmQoe30sIHtcbiAgICAgIHRleHQ6ICcnXG4gICAgfSwgaXRlbSk7XG5cbiAgICB2YXIgZGVmYXVsdHMgPSB7XG4gICAgICBzZWxlY3RlZDogZmFsc2UsXG4gICAgICBkaXNhYmxlZDogZmFsc2VcbiAgICB9O1xuXG4gICAgaWYgKGl0ZW0uaWQgIT0gbnVsbCkge1xuICAgICAgaXRlbS5pZCA9IGl0ZW0uaWQudG9TdHJpbmcoKTtcbiAgICB9XG5cbiAgICBpZiAoaXRlbS50ZXh0ICE9IG51bGwpIHtcbiAgICAgIGl0ZW0udGV4dCA9IGl0ZW0udGV4dC50b1N0cmluZygpO1xuICAgIH1cblxuICAgIGlmIChpdGVtLl9yZXN1bHRJZCA9PSBudWxsICYmIGl0ZW0uaWQgJiYgdGhpcy5jb250YWluZXIgIT0gbnVsbCkge1xuICAgICAgaXRlbS5fcmVzdWx0SWQgPSB0aGlzLmdlbmVyYXRlUmVzdWx0SWQodGhpcy5jb250YWluZXIsIGl0ZW0pO1xuICAgIH1cblxuICAgIHJldHVybiAkLmV4dGVuZCh7fSwgZGVmYXVsdHMsIGl0ZW0pO1xuICB9O1xuXG4gIFNlbGVjdEFkYXB0ZXIucHJvdG90eXBlLm1hdGNoZXMgPSBmdW5jdGlvbiAocGFyYW1zLCBkYXRhKSB7XG4gICAgdmFyIG1hdGNoZXIgPSB0aGlzLm9wdGlvbnMuZ2V0KCdtYXRjaGVyJyk7XG5cbiAgICByZXR1cm4gbWF0Y2hlcihwYXJhbXMsIGRhdGEpO1xuICB9O1xuXG4gIHJldHVybiBTZWxlY3RBZGFwdGVyO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9kYXRhL2FycmF5JyxbXG4gICcuL3NlbGVjdCcsXG4gICcuLi91dGlscycsXG4gICdqcXVlcnknXG5dLCBmdW5jdGlvbiAoU2VsZWN0QWRhcHRlciwgVXRpbHMsICQpIHtcbiAgZnVuY3Rpb24gQXJyYXlBZGFwdGVyICgkZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHZhciBkYXRhID0gb3B0aW9ucy5nZXQoJ2RhdGEnKSB8fCBbXTtcblxuICAgIEFycmF5QWRhcHRlci5fX3N1cGVyX18uY29uc3RydWN0b3IuY2FsbCh0aGlzLCAkZWxlbWVudCwgb3B0aW9ucyk7XG5cbiAgICB0aGlzLmFkZE9wdGlvbnModGhpcy5jb252ZXJ0VG9PcHRpb25zKGRhdGEpKTtcbiAgfVxuXG4gIFV0aWxzLkV4dGVuZChBcnJheUFkYXB0ZXIsIFNlbGVjdEFkYXB0ZXIpO1xuXG4gIEFycmF5QWRhcHRlci5wcm90b3R5cGUuc2VsZWN0ID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICB2YXIgJG9wdGlvbiA9IHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uJykuZmlsdGVyKGZ1bmN0aW9uIChpLCBlbG0pIHtcbiAgICAgIHJldHVybiBlbG0udmFsdWUgPT0gZGF0YS5pZC50b1N0cmluZygpO1xuICAgIH0pO1xuXG4gICAgaWYgKCRvcHRpb24ubGVuZ3RoID09PSAwKSB7XG4gICAgICAkb3B0aW9uID0gdGhpcy5vcHRpb24oZGF0YSk7XG5cbiAgICAgIHRoaXMuYWRkT3B0aW9ucygkb3B0aW9uKTtcbiAgICB9XG5cbiAgICBBcnJheUFkYXB0ZXIuX19zdXBlcl9fLnNlbGVjdC5jYWxsKHRoaXMsIGRhdGEpO1xuICB9O1xuXG4gIEFycmF5QWRhcHRlci5wcm90b3R5cGUuY29udmVydFRvT3B0aW9ucyA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyICRleGlzdGluZyA9IHRoaXMuJGVsZW1lbnQuZmluZCgnb3B0aW9uJyk7XG4gICAgdmFyIGV4aXN0aW5nSWRzID0gJGV4aXN0aW5nLm1hcChmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gc2VsZi5pdGVtKCQodGhpcykpLmlkO1xuICAgIH0pLmdldCgpO1xuXG4gICAgdmFyICRvcHRpb25zID0gW107XG5cbiAgICAvLyBGaWx0ZXIgb3V0IGFsbCBpdGVtcyBleGNlcHQgZm9yIHRoZSBvbmUgcGFzc2VkIGluIHRoZSBhcmd1bWVudFxuICAgIGZ1bmN0aW9uIG9ubHlJdGVtIChpdGVtKSB7XG4gICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gJCh0aGlzKS52YWwoKSA9PSBpdGVtLmlkO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBmb3IgKHZhciBkID0gMDsgZCA8IGRhdGEubGVuZ3RoOyBkKyspIHtcbiAgICAgIHZhciBpdGVtID0gdGhpcy5fbm9ybWFsaXplSXRlbShkYXRhW2RdKTtcblxuICAgICAgLy8gU2tpcCBpdGVtcyB3aGljaCB3ZXJlIHByZS1sb2FkZWQsIG9ubHkgbWVyZ2UgdGhlIGRhdGFcbiAgICAgIGlmICgkLmluQXJyYXkoaXRlbS5pZCwgZXhpc3RpbmdJZHMpID49IDApIHtcbiAgICAgICAgdmFyICRleGlzdGluZ09wdGlvbiA9ICRleGlzdGluZy5maWx0ZXIob25seUl0ZW0oaXRlbSkpO1xuXG4gICAgICAgIHZhciBleGlzdGluZ0RhdGEgPSB0aGlzLml0ZW0oJGV4aXN0aW5nT3B0aW9uKTtcbiAgICAgICAgdmFyIG5ld0RhdGEgPSAkLmV4dGVuZCh0cnVlLCB7fSwgaXRlbSwgZXhpc3RpbmdEYXRhKTtcblxuICAgICAgICB2YXIgJG5ld09wdGlvbiA9IHRoaXMub3B0aW9uKG5ld0RhdGEpO1xuXG4gICAgICAgICRleGlzdGluZ09wdGlvbi5yZXBsYWNlV2l0aCgkbmV3T3B0aW9uKTtcblxuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cblxuICAgICAgdmFyICRvcHRpb24gPSB0aGlzLm9wdGlvbihpdGVtKTtcblxuICAgICAgaWYgKGl0ZW0uY2hpbGRyZW4pIHtcbiAgICAgICAgdmFyICRjaGlsZHJlbiA9IHRoaXMuY29udmVydFRvT3B0aW9ucyhpdGVtLmNoaWxkcmVuKTtcblxuICAgICAgICBVdGlscy5hcHBlbmRNYW55KCRvcHRpb24sICRjaGlsZHJlbik7XG4gICAgICB9XG5cbiAgICAgICRvcHRpb25zLnB1c2goJG9wdGlvbik7XG4gICAgfVxuXG4gICAgcmV0dXJuICRvcHRpb25zO1xuICB9O1xuXG4gIHJldHVybiBBcnJheUFkYXB0ZXI7XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2RhdGEvYWpheCcsW1xuICAnLi9hcnJheScsXG4gICcuLi91dGlscycsXG4gICdqcXVlcnknXG5dLCBmdW5jdGlvbiAoQXJyYXlBZGFwdGVyLCBVdGlscywgJCkge1xuICBmdW5jdGlvbiBBamF4QWRhcHRlciAoJGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLmFqYXhPcHRpb25zID0gdGhpcy5fYXBwbHlEZWZhdWx0cyhvcHRpb25zLmdldCgnYWpheCcpKTtcblxuICAgIGlmICh0aGlzLmFqYXhPcHRpb25zLnByb2Nlc3NSZXN1bHRzICE9IG51bGwpIHtcbiAgICAgIHRoaXMucHJvY2Vzc1Jlc3VsdHMgPSB0aGlzLmFqYXhPcHRpb25zLnByb2Nlc3NSZXN1bHRzO1xuICAgIH1cblxuICAgIEFqYXhBZGFwdGVyLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5jYWxsKHRoaXMsICRlbGVtZW50LCBvcHRpb25zKTtcbiAgfVxuXG4gIFV0aWxzLkV4dGVuZChBamF4QWRhcHRlciwgQXJyYXlBZGFwdGVyKTtcblxuICBBamF4QWRhcHRlci5wcm90b3R5cGUuX2FwcGx5RGVmYXVsdHMgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgIHZhciBkZWZhdWx0cyA9IHtcbiAgICAgIGRhdGE6IGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCBwYXJhbXMsIHtcbiAgICAgICAgICBxOiBwYXJhbXMudGVybVxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICB0cmFuc3BvcnQ6IGZ1bmN0aW9uIChwYXJhbXMsIHN1Y2Nlc3MsIGZhaWx1cmUpIHtcbiAgICAgICAgdmFyICRyZXF1ZXN0ID0gJC5hamF4KHBhcmFtcyk7XG5cbiAgICAgICAgJHJlcXVlc3QudGhlbihzdWNjZXNzKTtcbiAgICAgICAgJHJlcXVlc3QuZmFpbChmYWlsdXJlKTtcblxuICAgICAgICByZXR1cm4gJHJlcXVlc3Q7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiAkLmV4dGVuZCh7fSwgZGVmYXVsdHMsIG9wdGlvbnMsIHRydWUpO1xuICB9O1xuXG4gIEFqYXhBZGFwdGVyLnByb3RvdHlwZS5wcm9jZXNzUmVzdWx0cyA9IGZ1bmN0aW9uIChyZXN1bHRzKSB7XG4gICAgcmV0dXJuIHJlc3VsdHM7XG4gIH07XG5cbiAgQWpheEFkYXB0ZXIucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24gKHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICB2YXIgbWF0Y2hlcyA9IFtdO1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIGlmICh0aGlzLl9yZXF1ZXN0ICE9IG51bGwpIHtcbiAgICAgIC8vIEpTT05QIHJlcXVlc3RzIGNhbm5vdCBhbHdheXMgYmUgYWJvcnRlZFxuICAgICAgaWYgKCQuaXNGdW5jdGlvbih0aGlzLl9yZXF1ZXN0LmFib3J0KSkge1xuICAgICAgICB0aGlzLl9yZXF1ZXN0LmFib3J0KCk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3JlcXVlc3QgPSBudWxsO1xuICAgIH1cblxuICAgIHZhciBvcHRpb25zID0gJC5leHRlbmQoe1xuICAgICAgdHlwZTogJ0dFVCdcbiAgICB9LCB0aGlzLmFqYXhPcHRpb25zKTtcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy51cmwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIG9wdGlvbnMudXJsID0gb3B0aW9ucy51cmwuY2FsbCh0aGlzLiRlbGVtZW50LCBwYXJhbXMpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5kYXRhID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBvcHRpb25zLmRhdGEgPSBvcHRpb25zLmRhdGEuY2FsbCh0aGlzLiRlbGVtZW50LCBwYXJhbXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlcXVlc3QgKCkge1xuICAgICAgdmFyICRyZXF1ZXN0ID0gb3B0aW9ucy50cmFuc3BvcnQob3B0aW9ucywgZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgdmFyIHJlc3VsdHMgPSBzZWxmLnByb2Nlc3NSZXN1bHRzKGRhdGEsIHBhcmFtcyk7XG5cbiAgICAgICAgaWYgKHNlbGYub3B0aW9ucy5nZXQoJ2RlYnVnJykgJiYgd2luZG93LmNvbnNvbGUgJiYgY29uc29sZS5lcnJvcikge1xuICAgICAgICAgIC8vIENoZWNrIHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSByZXNwb25zZSBpbmNsdWRlZCBhIGByZXN1bHRzYCBrZXkuXG4gICAgICAgICAgaWYgKCFyZXN1bHRzIHx8ICFyZXN1bHRzLnJlc3VsdHMgfHwgISQuaXNBcnJheShyZXN1bHRzLnJlc3VsdHMpKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgICAnU2VsZWN0MjogVGhlIEFKQVggcmVzdWx0cyBkaWQgbm90IHJldHVybiBhbiBhcnJheSBpbiB0aGUgJyArXG4gICAgICAgICAgICAgICdgcmVzdWx0c2Aga2V5IG9mIHRoZSByZXNwb25zZS4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNhbGxiYWNrKHJlc3VsdHMpO1xuICAgICAgfSwgZnVuY3Rpb24gKCkge1xuICAgICAgICAvLyBBdHRlbXB0IHRvIGRldGVjdCBpZiBhIHJlcXVlc3Qgd2FzIGFib3J0ZWRcbiAgICAgICAgLy8gT25seSB3b3JrcyBpZiB0aGUgdHJhbnNwb3J0IGV4cG9zZXMgYSBzdGF0dXMgcHJvcGVydHlcbiAgICAgICAgaWYgKCdzdGF0dXMnIGluICRyZXF1ZXN0ICYmXG4gICAgICAgICAgICAoJHJlcXVlc3Quc3RhdHVzID09PSAwIHx8ICRyZXF1ZXN0LnN0YXR1cyA9PT0gJzAnKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHNlbGYudHJpZ2dlcigncmVzdWx0czptZXNzYWdlJywge1xuICAgICAgICAgIG1lc3NhZ2U6ICdlcnJvckxvYWRpbmcnXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG5cbiAgICAgIHNlbGYuX3JlcXVlc3QgPSAkcmVxdWVzdDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5hamF4T3B0aW9ucy5kZWxheSAmJiBwYXJhbXMudGVybSAhPSBudWxsKSB7XG4gICAgICBpZiAodGhpcy5fcXVlcnlUaW1lb3V0KSB7XG4gICAgICAgIHdpbmRvdy5jbGVhclRpbWVvdXQodGhpcy5fcXVlcnlUaW1lb3V0KTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5fcXVlcnlUaW1lb3V0ID0gd2luZG93LnNldFRpbWVvdXQocmVxdWVzdCwgdGhpcy5hamF4T3B0aW9ucy5kZWxheSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlcXVlc3QoKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIEFqYXhBZGFwdGVyO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9kYXRhL3RhZ3MnLFtcbiAgJ2pxdWVyeSdcbl0sIGZ1bmN0aW9uICgkKSB7XG4gIGZ1bmN0aW9uIFRhZ3MgKGRlY29yYXRlZCwgJGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB2YXIgdGFncyA9IG9wdGlvbnMuZ2V0KCd0YWdzJyk7XG5cbiAgICB2YXIgY3JlYXRlVGFnID0gb3B0aW9ucy5nZXQoJ2NyZWF0ZVRhZycpO1xuXG4gICAgaWYgKGNyZWF0ZVRhZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLmNyZWF0ZVRhZyA9IGNyZWF0ZVRhZztcbiAgICB9XG5cbiAgICB2YXIgaW5zZXJ0VGFnID0gb3B0aW9ucy5nZXQoJ2luc2VydFRhZycpO1xuXG4gICAgaWYgKGluc2VydFRhZyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMuaW5zZXJ0VGFnID0gaW5zZXJ0VGFnO1xuICAgIH1cblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsICRlbGVtZW50LCBvcHRpb25zKTtcblxuICAgIGlmICgkLmlzQXJyYXkodGFncykpIHtcbiAgICAgIGZvciAodmFyIHQgPSAwOyB0IDwgdGFncy5sZW5ndGg7IHQrKykge1xuICAgICAgICB2YXIgdGFnID0gdGFnc1t0XTtcbiAgICAgICAgdmFyIGl0ZW0gPSB0aGlzLl9ub3JtYWxpemVJdGVtKHRhZyk7XG5cbiAgICAgICAgdmFyICRvcHRpb24gPSB0aGlzLm9wdGlvbihpdGVtKTtcblxuICAgICAgICB0aGlzLiRlbGVtZW50LmFwcGVuZCgkb3B0aW9uKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBUYWdzLnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB0aGlzLl9yZW1vdmVPbGRUYWdzKCk7XG5cbiAgICBpZiAocGFyYW1zLnRlcm0gPT0gbnVsbCB8fCBwYXJhbXMucGFnZSAhPSBudWxsKSB7XG4gICAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB3cmFwcGVyIChvYmosIGNoaWxkKSB7XG4gICAgICB2YXIgZGF0YSA9IG9iai5yZXN1bHRzO1xuXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGRhdGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgdmFyIG9wdGlvbiA9IGRhdGFbaV07XG5cbiAgICAgICAgdmFyIGNoZWNrQ2hpbGRyZW4gPSAoXG4gICAgICAgICAgb3B0aW9uLmNoaWxkcmVuICE9IG51bGwgJiZcbiAgICAgICAgICAhd3JhcHBlcih7XG4gICAgICAgICAgICByZXN1bHRzOiBvcHRpb24uY2hpbGRyZW5cbiAgICAgICAgICB9LCB0cnVlKVxuICAgICAgICApO1xuXG4gICAgICAgIHZhciBvcHRpb25UZXh0ID0gKG9wdGlvbi50ZXh0IHx8ICcnKS50b1VwcGVyQ2FzZSgpO1xuICAgICAgICB2YXIgcGFyYW1zVGVybSA9IChwYXJhbXMudGVybSB8fCAnJykudG9VcHBlckNhc2UoKTtcblxuICAgICAgICB2YXIgY2hlY2tUZXh0ID0gb3B0aW9uVGV4dCA9PT0gcGFyYW1zVGVybTtcblxuICAgICAgICBpZiAoY2hlY2tUZXh0IHx8IGNoZWNrQ2hpbGRyZW4pIHtcbiAgICAgICAgICBpZiAoY2hpbGQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBvYmouZGF0YSA9IGRhdGE7XG4gICAgICAgICAgY2FsbGJhY2sob2JqKTtcblxuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoY2hpbGQpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG5cbiAgICAgIHZhciB0YWcgPSBzZWxmLmNyZWF0ZVRhZyhwYXJhbXMpO1xuXG4gICAgICBpZiAodGFnICE9IG51bGwpIHtcbiAgICAgICAgdmFyICRvcHRpb24gPSBzZWxmLm9wdGlvbih0YWcpO1xuICAgICAgICAkb3B0aW9uLmF0dHIoJ2RhdGEtc2VsZWN0Mi10YWcnLCB0cnVlKTtcblxuICAgICAgICBzZWxmLmFkZE9wdGlvbnMoWyRvcHRpb25dKTtcblxuICAgICAgICBzZWxmLmluc2VydFRhZyhkYXRhLCB0YWcpO1xuICAgICAgfVxuXG4gICAgICBvYmoucmVzdWx0cyA9IGRhdGE7XG5cbiAgICAgIGNhbGxiYWNrKG9iaik7XG4gICAgfVxuXG4gICAgZGVjb3JhdGVkLmNhbGwodGhpcywgcGFyYW1zLCB3cmFwcGVyKTtcbiAgfTtcblxuICBUYWdzLnByb3RvdHlwZS5jcmVhdGVUYWcgPSBmdW5jdGlvbiAoZGVjb3JhdGVkLCBwYXJhbXMpIHtcbiAgICB2YXIgdGVybSA9ICQudHJpbShwYXJhbXMudGVybSk7XG5cbiAgICBpZiAodGVybSA9PT0gJycpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBpZDogdGVybSxcbiAgICAgIHRleHQ6IHRlcm1cbiAgICB9O1xuICB9O1xuXG4gIFRhZ3MucHJvdG90eXBlLmluc2VydFRhZyA9IGZ1bmN0aW9uIChfLCBkYXRhLCB0YWcpIHtcbiAgICBkYXRhLnVuc2hpZnQodGFnKTtcbiAgfTtcblxuICBUYWdzLnByb3RvdHlwZS5fcmVtb3ZlT2xkVGFncyA9IGZ1bmN0aW9uIChfKSB7XG4gICAgdmFyIHRhZyA9IHRoaXMuX2xhc3RUYWc7XG5cbiAgICB2YXIgJG9wdGlvbnMgPSB0aGlzLiRlbGVtZW50LmZpbmQoJ29wdGlvbltkYXRhLXNlbGVjdDItdGFnXScpO1xuXG4gICAgJG9wdGlvbnMuZWFjaChmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAodGhpcy5zZWxlY3RlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgICQodGhpcykucmVtb3ZlKCk7XG4gICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIFRhZ3M7XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2RhdGEvdG9rZW5pemVyJyxbXG4gICdqcXVlcnknXG5dLCBmdW5jdGlvbiAoJCkge1xuICBmdW5jdGlvbiBUb2tlbml6ZXIgKGRlY29yYXRlZCwgJGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB2YXIgdG9rZW5pemVyID0gb3B0aW9ucy5nZXQoJ3Rva2VuaXplcicpO1xuXG4gICAgaWYgKHRva2VuaXplciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnRva2VuaXplciA9IHRva2VuaXplcjtcbiAgICB9XG5cbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCAkZWxlbWVudCwgb3B0aW9ucyk7XG4gIH1cblxuICBUb2tlbml6ZXIucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbiAoZGVjb3JhdGVkLCBjb250YWluZXIsICRjb250YWluZXIpIHtcbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBjb250YWluZXIsICRjb250YWluZXIpO1xuXG4gICAgdGhpcy4kc2VhcmNoID0gIGNvbnRhaW5lci5kcm9wZG93bi4kc2VhcmNoIHx8IGNvbnRhaW5lci5zZWxlY3Rpb24uJHNlYXJjaCB8fFxuICAgICAgJGNvbnRhaW5lci5maW5kKCcuc2VsZWN0Mi1zZWFyY2hfX2ZpZWxkJyk7XG4gIH07XG5cbiAgVG9rZW5pemVyLnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVBbmRTZWxlY3QgKGRhdGEpIHtcbiAgICAgIC8vIE5vcm1hbGl6ZSB0aGUgZGF0YSBvYmplY3Qgc28gd2UgY2FuIHVzZSBpdCBmb3IgY2hlY2tzXG4gICAgICB2YXIgaXRlbSA9IHNlbGYuX25vcm1hbGl6ZUl0ZW0oZGF0YSk7XG5cbiAgICAgIC8vIENoZWNrIGlmIHRoZSBkYXRhIG9iamVjdCBhbHJlYWR5IGV4aXN0cyBhcyBhIHRhZ1xuICAgICAgLy8gU2VsZWN0IGl0IGlmIGl0IGRvZXNuJ3RcbiAgICAgIHZhciAkZXhpc3RpbmdPcHRpb25zID0gc2VsZi4kZWxlbWVudC5maW5kKCdvcHRpb24nKS5maWx0ZXIoZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gJCh0aGlzKS52YWwoKSA9PT0gaXRlbS5pZDtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBJZiBhbiBleGlzdGluZyBvcHRpb24gd2Fzbid0IGZvdW5kIGZvciBpdCwgY3JlYXRlIHRoZSBvcHRpb25cbiAgICAgIGlmICghJGV4aXN0aW5nT3B0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgdmFyICRvcHRpb24gPSBzZWxmLm9wdGlvbihpdGVtKTtcbiAgICAgICAgJG9wdGlvbi5hdHRyKCdkYXRhLXNlbGVjdDItdGFnJywgdHJ1ZSk7XG5cbiAgICAgICAgc2VsZi5fcmVtb3ZlT2xkVGFncygpO1xuICAgICAgICBzZWxmLmFkZE9wdGlvbnMoWyRvcHRpb25dKTtcbiAgICAgIH1cblxuICAgICAgLy8gU2VsZWN0IHRoZSBpdGVtLCBub3cgdGhhdCB3ZSBrbm93IHRoZXJlIGlzIGFuIG9wdGlvbiBmb3IgaXRcbiAgICAgIHNlbGVjdChpdGVtKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZWxlY3QgKGRhdGEpIHtcbiAgICAgIHNlbGYudHJpZ2dlcignc2VsZWN0Jywge1xuICAgICAgICBkYXRhOiBkYXRhXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBwYXJhbXMudGVybSA9IHBhcmFtcy50ZXJtIHx8ICcnO1xuXG4gICAgdmFyIHRva2VuRGF0YSA9IHRoaXMudG9rZW5pemVyKHBhcmFtcywgdGhpcy5vcHRpb25zLCBjcmVhdGVBbmRTZWxlY3QpO1xuXG4gICAgaWYgKHRva2VuRGF0YS50ZXJtICE9PSBwYXJhbXMudGVybSkge1xuICAgICAgLy8gUmVwbGFjZSB0aGUgc2VhcmNoIHRlcm0gaWYgd2UgaGF2ZSB0aGUgc2VhcmNoIGJveFxuICAgICAgaWYgKHRoaXMuJHNlYXJjaC5sZW5ndGgpIHtcbiAgICAgICAgdGhpcy4kc2VhcmNoLnZhbCh0b2tlbkRhdGEudGVybSk7XG4gICAgICAgIHRoaXMuJHNlYXJjaC5mb2N1cygpO1xuICAgICAgfVxuXG4gICAgICBwYXJhbXMudGVybSA9IHRva2VuRGF0YS50ZXJtO1xuICAgIH1cblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsIHBhcmFtcywgY2FsbGJhY2spO1xuICB9O1xuXG4gIFRva2VuaXplci5wcm90b3R5cGUudG9rZW5pemVyID0gZnVuY3Rpb24gKF8sIHBhcmFtcywgb3B0aW9ucywgY2FsbGJhY2spIHtcbiAgICB2YXIgc2VwYXJhdG9ycyA9IG9wdGlvbnMuZ2V0KCd0b2tlblNlcGFyYXRvcnMnKSB8fCBbXTtcbiAgICB2YXIgdGVybSA9IHBhcmFtcy50ZXJtO1xuICAgIHZhciBpID0gMDtcblxuICAgIHZhciBjcmVhdGVUYWcgPSB0aGlzLmNyZWF0ZVRhZyB8fCBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBpZDogcGFyYW1zLnRlcm0sXG4gICAgICAgIHRleHQ6IHBhcmFtcy50ZXJtXG4gICAgICB9O1xuICAgIH07XG5cbiAgICB3aGlsZSAoaSA8IHRlcm0ubGVuZ3RoKSB7XG4gICAgICB2YXIgdGVybUNoYXIgPSB0ZXJtW2ldO1xuXG4gICAgICBpZiAoJC5pbkFycmF5KHRlcm1DaGFyLCBzZXBhcmF0b3JzKSA9PT0gLTEpIHtcbiAgICAgICAgaSsrO1xuXG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICB2YXIgcGFydCA9IHRlcm0uc3Vic3RyKDAsIGkpO1xuICAgICAgdmFyIHBhcnRQYXJhbXMgPSAkLmV4dGVuZCh7fSwgcGFyYW1zLCB7XG4gICAgICAgIHRlcm06IHBhcnRcbiAgICAgIH0pO1xuXG4gICAgICB2YXIgZGF0YSA9IGNyZWF0ZVRhZyhwYXJ0UGFyYW1zKTtcblxuICAgICAgaWYgKGRhdGEgPT0gbnVsbCkge1xuICAgICAgICBpKys7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjYWxsYmFjayhkYXRhKTtcblxuICAgICAgLy8gUmVzZXQgdGhlIHRlcm0gdG8gbm90IGluY2x1ZGUgdGhlIHRva2VuaXplZCBwb3J0aW9uXG4gICAgICB0ZXJtID0gdGVybS5zdWJzdHIoaSArIDEpIHx8ICcnO1xuICAgICAgaSA9IDA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHRlcm06IHRlcm1cbiAgICB9O1xuICB9O1xuXG4gIHJldHVybiBUb2tlbml6ZXI7XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2RhdGEvbWluaW11bUlucHV0TGVuZ3RoJyxbXG5cbl0sIGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gTWluaW11bUlucHV0TGVuZ3RoIChkZWNvcmF0ZWQsICRlLCBvcHRpb25zKSB7XG4gICAgdGhpcy5taW5pbXVtSW5wdXRMZW5ndGggPSBvcHRpb25zLmdldCgnbWluaW11bUlucHV0TGVuZ3RoJyk7XG5cbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCAkZSwgb3B0aW9ucyk7XG4gIH1cblxuICBNaW5pbXVtSW5wdXRMZW5ndGgucHJvdG90eXBlLnF1ZXJ5ID0gZnVuY3Rpb24gKGRlY29yYXRlZCwgcGFyYW1zLCBjYWxsYmFjaykge1xuICAgIHBhcmFtcy50ZXJtID0gcGFyYW1zLnRlcm0gfHwgJyc7XG5cbiAgICBpZiAocGFyYW1zLnRlcm0ubGVuZ3RoIDwgdGhpcy5taW5pbXVtSW5wdXRMZW5ndGgpIHtcbiAgICAgIHRoaXMudHJpZ2dlcigncmVzdWx0czptZXNzYWdlJywge1xuICAgICAgICBtZXNzYWdlOiAnaW5wdXRUb29TaG9ydCcsXG4gICAgICAgIGFyZ3M6IHtcbiAgICAgICAgICBtaW5pbXVtOiB0aGlzLm1pbmltdW1JbnB1dExlbmd0aCxcbiAgICAgICAgICBpbnB1dDogcGFyYW1zLnRlcm0sXG4gICAgICAgICAgcGFyYW1zOiBwYXJhbXNcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBwYXJhbXMsIGNhbGxiYWNrKTtcbiAgfTtcblxuICByZXR1cm4gTWluaW11bUlucHV0TGVuZ3RoO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9kYXRhL21heGltdW1JbnB1dExlbmd0aCcsW1xuXG5dLCBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIE1heGltdW1JbnB1dExlbmd0aCAoZGVjb3JhdGVkLCAkZSwgb3B0aW9ucykge1xuICAgIHRoaXMubWF4aW11bUlucHV0TGVuZ3RoID0gb3B0aW9ucy5nZXQoJ21heGltdW1JbnB1dExlbmd0aCcpO1xuXG4gICAgZGVjb3JhdGVkLmNhbGwodGhpcywgJGUsIG9wdGlvbnMpO1xuICB9XG5cbiAgTWF4aW11bUlucHV0TGVuZ3RoLnByb3RvdHlwZS5xdWVyeSA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIHBhcmFtcywgY2FsbGJhY2spIHtcbiAgICBwYXJhbXMudGVybSA9IHBhcmFtcy50ZXJtIHx8ICcnO1xuXG4gICAgaWYgKHRoaXMubWF4aW11bUlucHV0TGVuZ3RoID4gMCAmJlxuICAgICAgICBwYXJhbXMudGVybS5sZW5ndGggPiB0aGlzLm1heGltdW1JbnB1dExlbmd0aCkge1xuICAgICAgdGhpcy50cmlnZ2VyKCdyZXN1bHRzOm1lc3NhZ2UnLCB7XG4gICAgICAgIG1lc3NhZ2U6ICdpbnB1dFRvb0xvbmcnLFxuICAgICAgICBhcmdzOiB7XG4gICAgICAgICAgbWF4aW11bTogdGhpcy5tYXhpbXVtSW5wdXRMZW5ndGgsXG4gICAgICAgICAgaW5wdXQ6IHBhcmFtcy50ZXJtLFxuICAgICAgICAgIHBhcmFtczogcGFyYW1zXG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZGVjb3JhdGVkLmNhbGwodGhpcywgcGFyYW1zLCBjYWxsYmFjayk7XG4gIH07XG5cbiAgcmV0dXJuIE1heGltdW1JbnB1dExlbmd0aDtcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIvZGF0YS9tYXhpbXVtU2VsZWN0aW9uTGVuZ3RoJyxbXG5cbl0sIGZ1bmN0aW9uICgpe1xuICBmdW5jdGlvbiBNYXhpbXVtU2VsZWN0aW9uTGVuZ3RoIChkZWNvcmF0ZWQsICRlLCBvcHRpb25zKSB7XG4gICAgdGhpcy5tYXhpbXVtU2VsZWN0aW9uTGVuZ3RoID0gb3B0aW9ucy5nZXQoJ21heGltdW1TZWxlY3Rpb25MZW5ndGgnKTtcblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsICRlLCBvcHRpb25zKTtcbiAgfVxuXG4gIE1heGltdW1TZWxlY3Rpb25MZW5ndGgucHJvdG90eXBlLnF1ZXJ5ID1cbiAgICBmdW5jdGlvbiAoZGVjb3JhdGVkLCBwYXJhbXMsIGNhbGxiYWNrKSB7XG4gICAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICAgIHRoaXMuY3VycmVudChmdW5jdGlvbiAoY3VycmVudERhdGEpIHtcbiAgICAgICAgdmFyIGNvdW50ID0gY3VycmVudERhdGEgIT0gbnVsbCA/IGN1cnJlbnREYXRhLmxlbmd0aCA6IDA7XG4gICAgICAgIGlmIChzZWxmLm1heGltdW1TZWxlY3Rpb25MZW5ndGggPiAwICYmXG4gICAgICAgICAgY291bnQgPj0gc2VsZi5tYXhpbXVtU2VsZWN0aW9uTGVuZ3RoKSB7XG4gICAgICAgICAgc2VsZi50cmlnZ2VyKCdyZXN1bHRzOm1lc3NhZ2UnLCB7XG4gICAgICAgICAgICBtZXNzYWdlOiAnbWF4aW11bVNlbGVjdGVkJyxcbiAgICAgICAgICAgIGFyZ3M6IHtcbiAgICAgICAgICAgICAgbWF4aW11bTogc2VsZi5tYXhpbXVtU2VsZWN0aW9uTGVuZ3RoXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGRlY29yYXRlZC5jYWxsKHNlbGYsIHBhcmFtcywgY2FsbGJhY2spO1xuICAgICAgfSk7XG4gIH07XG5cbiAgcmV0dXJuIE1heGltdW1TZWxlY3Rpb25MZW5ndGg7XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2Ryb3Bkb3duJyxbXG4gICdqcXVlcnknLFxuICAnLi91dGlscydcbl0sIGZ1bmN0aW9uICgkLCBVdGlscykge1xuICBmdW5jdGlvbiBEcm9wZG93biAoJGVsZW1lbnQsIG9wdGlvbnMpIHtcbiAgICB0aGlzLiRlbGVtZW50ID0gJGVsZW1lbnQ7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcblxuICAgIERyb3Bkb3duLl9fc3VwZXJfXy5jb25zdHJ1Y3Rvci5jYWxsKHRoaXMpO1xuICB9XG5cbiAgVXRpbHMuRXh0ZW5kKERyb3Bkb3duLCBVdGlscy5PYnNlcnZhYmxlKTtcblxuICBEcm9wZG93bi5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkZHJvcGRvd24gPSAkKFxuICAgICAgJzxzcGFuIGNsYXNzPVwic2VsZWN0Mi1kcm9wZG93blwiPicgK1xuICAgICAgICAnPHNwYW4gY2xhc3M9XCJzZWxlY3QyLXJlc3VsdHNcIj48L3NwYW4+JyArXG4gICAgICAnPC9zcGFuPidcbiAgICApO1xuXG4gICAgJGRyb3Bkb3duLmF0dHIoJ2RpcicsIHRoaXMub3B0aW9ucy5nZXQoJ2RpcicpKTtcblxuICAgIHRoaXMuJGRyb3Bkb3duID0gJGRyb3Bkb3duO1xuXG4gICAgcmV0dXJuICRkcm9wZG93bjtcbiAgfTtcblxuICBEcm9wZG93bi5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAvLyBTaG91bGQgYmUgaW1wbGVtZW50ZWQgaW4gc3ViY2xhc3Nlc1xuICB9O1xuXG4gIERyb3Bkb3duLnByb3RvdHlwZS5wb3NpdGlvbiA9IGZ1bmN0aW9uICgkZHJvcGRvd24sICRjb250YWluZXIpIHtcbiAgICAvLyBTaG91bGQgYmUgaW1wbG1lbnRlZCBpbiBzdWJjbGFzc2VzXG4gIH07XG5cbiAgRHJvcGRvd24ucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgLy8gUmVtb3ZlIHRoZSBkcm9wZG93biBmcm9tIHRoZSBET01cbiAgICB0aGlzLiRkcm9wZG93bi5yZW1vdmUoKTtcbiAgfTtcblxuICByZXR1cm4gRHJvcGRvd247XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2Ryb3Bkb3duL3NlYXJjaCcsW1xuICAnanF1ZXJ5JyxcbiAgJy4uL3V0aWxzJ1xuXSwgZnVuY3Rpb24gKCQsIFV0aWxzKSB7XG4gIGZ1bmN0aW9uIFNlYXJjaCAoKSB7IH1cblxuICBTZWFyY2gucHJvdG90eXBlLnJlbmRlciA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQpIHtcbiAgICB2YXIgJHJlbmRlcmVkID0gZGVjb3JhdGVkLmNhbGwodGhpcyk7XG5cbiAgICB2YXIgJHNlYXJjaCA9ICQoXG4gICAgICAnPHNwYW4gY2xhc3M9XCJzZWxlY3QyLXNlYXJjaCBzZWxlY3QyLXNlYXJjaC0tZHJvcGRvd25cIj4nICtcbiAgICAgICAgJzxpbnB1dCBjbGFzcz1cInNlbGVjdDItc2VhcmNoX19maWVsZFwiIHR5cGU9XCJzZWFyY2hcIiB0YWJpbmRleD1cIi0xXCInICtcbiAgICAgICAgJyBhdXRvY29tcGxldGU9XCJvZmZcIiBhdXRvY29ycmVjdD1cIm9mZlwiIGF1dG9jYXBpdGFsaXplPVwibm9uZVwiJyArXG4gICAgICAgICcgc3BlbGxjaGVjaz1cImZhbHNlXCIgcm9sZT1cInRleHRib3hcIiAvPicgK1xuICAgICAgJzwvc3Bhbj4nXG4gICAgKTtcblxuICAgIHRoaXMuJHNlYXJjaENvbnRhaW5lciA9ICRzZWFyY2g7XG4gICAgdGhpcy4kc2VhcmNoID0gJHNlYXJjaC5maW5kKCdpbnB1dCcpO1xuXG4gICAgJHJlbmRlcmVkLnByZXBlbmQoJHNlYXJjaCk7XG5cbiAgICByZXR1cm4gJHJlbmRlcmVkO1xuICB9O1xuXG4gIFNlYXJjaC5wcm90b3R5cGUuYmluZCA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIGNvbnRhaW5lciwgJGNvbnRhaW5lcikge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsIGNvbnRhaW5lciwgJGNvbnRhaW5lcik7XG5cbiAgICB0aGlzLiRzZWFyY2gub24oJ2tleWRvd24nLCBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICBzZWxmLnRyaWdnZXIoJ2tleXByZXNzJywgZXZ0KTtcblxuICAgICAgc2VsZi5fa2V5VXBQcmV2ZW50ZWQgPSBldnQuaXNEZWZhdWx0UHJldmVudGVkKCk7XG4gICAgfSk7XG5cbiAgICAvLyBXb3JrYXJvdW5kIGZvciBicm93c2VycyB3aGljaCBkbyBub3Qgc3VwcG9ydCB0aGUgYGlucHV0YCBldmVudFxuICAgIC8vIFRoaXMgd2lsbCBwcmV2ZW50IGRvdWJsZS10cmlnZ2VyaW5nIG9mIGV2ZW50cyBmb3IgYnJvd3NlcnMgd2hpY2ggc3VwcG9ydFxuICAgIC8vIGJvdGggdGhlIGBrZXl1cGAgYW5kIGBpbnB1dGAgZXZlbnRzLlxuICAgIHRoaXMuJHNlYXJjaC5vbignaW5wdXQnLCBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgICAvLyBVbmJpbmQgdGhlIGR1cGxpY2F0ZWQgYGtleXVwYCBldmVudFxuICAgICAgJCh0aGlzKS5vZmYoJ2tleXVwJyk7XG4gICAgfSk7XG5cbiAgICB0aGlzLiRzZWFyY2gub24oJ2tleXVwIGlucHV0JywgZnVuY3Rpb24gKGV2dCkge1xuICAgICAgc2VsZi5oYW5kbGVTZWFyY2goZXZ0KTtcbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbignb3BlbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYuJHNlYXJjaC5hdHRyKCd0YWJpbmRleCcsIDApO1xuXG4gICAgICBzZWxmLiRzZWFyY2guZm9jdXMoKTtcblxuICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuICAgICAgICBzZWxmLiRzZWFyY2guZm9jdXMoKTtcbiAgICAgIH0sIDApO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdjbG9zZScsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYuJHNlYXJjaC5hdHRyKCd0YWJpbmRleCcsIC0xKTtcblxuICAgICAgc2VsZi4kc2VhcmNoLnZhbCgnJyk7XG4gICAgICBzZWxmLiRzZWFyY2guYmx1cigpO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdmb2N1cycsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmICghY29udGFpbmVyLmlzT3BlbigpKSB7XG4gICAgICAgIHNlbGYuJHNlYXJjaC5mb2N1cygpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdyZXN1bHRzOmFsbCcsIGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgIGlmIChwYXJhbXMucXVlcnkudGVybSA9PSBudWxsIHx8IHBhcmFtcy5xdWVyeS50ZXJtID09PSAnJykge1xuICAgICAgICB2YXIgc2hvd1NlYXJjaCA9IHNlbGYuc2hvd1NlYXJjaChwYXJhbXMpO1xuXG4gICAgICAgIGlmIChzaG93U2VhcmNoKSB7XG4gICAgICAgICAgc2VsZi4kc2VhcmNoQ29udGFpbmVyLnJlbW92ZUNsYXNzKCdzZWxlY3QyLXNlYXJjaC0taGlkZScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHNlbGYuJHNlYXJjaENvbnRhaW5lci5hZGRDbGFzcygnc2VsZWN0Mi1zZWFyY2gtLWhpZGUnKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIFNlYXJjaC5wcm90b3R5cGUuaGFuZGxlU2VhcmNoID0gZnVuY3Rpb24gKGV2dCkge1xuICAgIGlmICghdGhpcy5fa2V5VXBQcmV2ZW50ZWQpIHtcbiAgICAgIHZhciBpbnB1dCA9IHRoaXMuJHNlYXJjaC52YWwoKTtcblxuICAgICAgdGhpcy50cmlnZ2VyKCdxdWVyeScsIHtcbiAgICAgICAgdGVybTogaW5wdXRcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMuX2tleVVwUHJldmVudGVkID0gZmFsc2U7XG4gIH07XG5cbiAgU2VhcmNoLnByb3RvdHlwZS5zaG93U2VhcmNoID0gZnVuY3Rpb24gKF8sIHBhcmFtcykge1xuICAgIHJldHVybiB0cnVlO1xuICB9O1xuXG4gIHJldHVybiBTZWFyY2g7XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2Ryb3Bkb3duL2hpZGVQbGFjZWhvbGRlcicsW1xuXG5dLCBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEhpZGVQbGFjZWhvbGRlciAoZGVjb3JhdGVkLCAkZWxlbWVudCwgb3B0aW9ucywgZGF0YUFkYXB0ZXIpIHtcbiAgICB0aGlzLnBsYWNlaG9sZGVyID0gdGhpcy5ub3JtYWxpemVQbGFjZWhvbGRlcihvcHRpb25zLmdldCgncGxhY2Vob2xkZXInKSk7XG5cbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCAkZWxlbWVudCwgb3B0aW9ucywgZGF0YUFkYXB0ZXIpO1xuICB9XG5cbiAgSGlkZVBsYWNlaG9sZGVyLnByb3RvdHlwZS5hcHBlbmQgPSBmdW5jdGlvbiAoZGVjb3JhdGVkLCBkYXRhKSB7XG4gICAgZGF0YS5yZXN1bHRzID0gdGhpcy5yZW1vdmVQbGFjZWhvbGRlcihkYXRhLnJlc3VsdHMpO1xuXG4gICAgZGVjb3JhdGVkLmNhbGwodGhpcywgZGF0YSk7XG4gIH07XG5cbiAgSGlkZVBsYWNlaG9sZGVyLnByb3RvdHlwZS5ub3JtYWxpemVQbGFjZWhvbGRlciA9IGZ1bmN0aW9uIChfLCBwbGFjZWhvbGRlcikge1xuICAgIGlmICh0eXBlb2YgcGxhY2Vob2xkZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICBwbGFjZWhvbGRlciA9IHtcbiAgICAgICAgaWQ6ICcnLFxuICAgICAgICB0ZXh0OiBwbGFjZWhvbGRlclxuICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gcGxhY2Vob2xkZXI7XG4gIH07XG5cbiAgSGlkZVBsYWNlaG9sZGVyLnByb3RvdHlwZS5yZW1vdmVQbGFjZWhvbGRlciA9IGZ1bmN0aW9uIChfLCBkYXRhKSB7XG4gICAgdmFyIG1vZGlmaWVkRGF0YSA9IGRhdGEuc2xpY2UoMCk7XG5cbiAgICBmb3IgKHZhciBkID0gZGF0YS5sZW5ndGggLSAxOyBkID49IDA7IGQtLSkge1xuICAgICAgdmFyIGl0ZW0gPSBkYXRhW2RdO1xuXG4gICAgICBpZiAodGhpcy5wbGFjZWhvbGRlci5pZCA9PT0gaXRlbS5pZCkge1xuICAgICAgICBtb2RpZmllZERhdGEuc3BsaWNlKGQsIDEpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBtb2RpZmllZERhdGE7XG4gIH07XG5cbiAgcmV0dXJuIEhpZGVQbGFjZWhvbGRlcjtcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIvZHJvcGRvd24vaW5maW5pdGVTY3JvbGwnLFtcbiAgJ2pxdWVyeSdcbl0sIGZ1bmN0aW9uICgkKSB7XG4gIGZ1bmN0aW9uIEluZmluaXRlU2Nyb2xsIChkZWNvcmF0ZWQsICRlbGVtZW50LCBvcHRpb25zLCBkYXRhQWRhcHRlcikge1xuICAgIHRoaXMubGFzdFBhcmFtcyA9IHt9O1xuXG4gICAgZGVjb3JhdGVkLmNhbGwodGhpcywgJGVsZW1lbnQsIG9wdGlvbnMsIGRhdGFBZGFwdGVyKTtcblxuICAgIHRoaXMuJGxvYWRpbmdNb3JlID0gdGhpcy5jcmVhdGVMb2FkaW5nTW9yZSgpO1xuICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xuICB9XG5cbiAgSW5maW5pdGVTY3JvbGwucHJvdG90eXBlLmFwcGVuZCA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIGRhdGEpIHtcbiAgICB0aGlzLiRsb2FkaW5nTW9yZS5yZW1vdmUoKTtcbiAgICB0aGlzLmxvYWRpbmcgPSBmYWxzZTtcblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsIGRhdGEpO1xuXG4gICAgaWYgKHRoaXMuc2hvd0xvYWRpbmdNb3JlKGRhdGEpKSB7XG4gICAgICB0aGlzLiRyZXN1bHRzLmFwcGVuZCh0aGlzLiRsb2FkaW5nTW9yZSk7XG4gICAgfVxuICB9O1xuXG4gIEluZmluaXRlU2Nyb2xsLnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24gKGRlY29yYXRlZCwgY29udGFpbmVyLCAkY29udGFpbmVyKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgZGVjb3JhdGVkLmNhbGwodGhpcywgY29udGFpbmVyLCAkY29udGFpbmVyKTtcblxuICAgIGNvbnRhaW5lci5vbigncXVlcnknLCBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICBzZWxmLmxhc3RQYXJhbXMgPSBwYXJhbXM7XG4gICAgICBzZWxmLmxvYWRpbmcgPSB0cnVlO1xuICAgIH0pO1xuXG4gICAgY29udGFpbmVyLm9uKCdxdWVyeTphcHBlbmQnLCBmdW5jdGlvbiAocGFyYW1zKSB7XG4gICAgICBzZWxmLmxhc3RQYXJhbXMgPSBwYXJhbXM7XG4gICAgICBzZWxmLmxvYWRpbmcgPSB0cnVlO1xuICAgIH0pO1xuXG4gICAgdGhpcy4kcmVzdWx0cy5vbignc2Nyb2xsJywgZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGlzTG9hZE1vcmVWaXNpYmxlID0gJC5jb250YWlucyhcbiAgICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LFxuICAgICAgICBzZWxmLiRsb2FkaW5nTW9yZVswXVxuICAgICAgKTtcblxuICAgICAgaWYgKHNlbGYubG9hZGluZyB8fCAhaXNMb2FkTW9yZVZpc2libGUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgY3VycmVudE9mZnNldCA9IHNlbGYuJHJlc3VsdHMub2Zmc2V0KCkudG9wICtcbiAgICAgICAgc2VsZi4kcmVzdWx0cy5vdXRlckhlaWdodChmYWxzZSk7XG4gICAgICB2YXIgbG9hZGluZ01vcmVPZmZzZXQgPSBzZWxmLiRsb2FkaW5nTW9yZS5vZmZzZXQoKS50b3AgK1xuICAgICAgICBzZWxmLiRsb2FkaW5nTW9yZS5vdXRlckhlaWdodChmYWxzZSk7XG5cbiAgICAgIGlmIChjdXJyZW50T2Zmc2V0ICsgNTAgPj0gbG9hZGluZ01vcmVPZmZzZXQpIHtcbiAgICAgICAgc2VsZi5sb2FkTW9yZSgpO1xuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIEluZmluaXRlU2Nyb2xsLnByb3RvdHlwZS5sb2FkTW9yZSA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xuXG4gICAgdmFyIHBhcmFtcyA9ICQuZXh0ZW5kKHt9LCB7cGFnZTogMX0sIHRoaXMubGFzdFBhcmFtcyk7XG5cbiAgICBwYXJhbXMucGFnZSsrO1xuXG4gICAgdGhpcy50cmlnZ2VyKCdxdWVyeTphcHBlbmQnLCBwYXJhbXMpO1xuICB9O1xuXG4gIEluZmluaXRlU2Nyb2xsLnByb3RvdHlwZS5zaG93TG9hZGluZ01vcmUgPSBmdW5jdGlvbiAoXywgZGF0YSkge1xuICAgIHJldHVybiBkYXRhLnBhZ2luYXRpb24gJiYgZGF0YS5wYWdpbmF0aW9uLm1vcmU7XG4gIH07XG5cbiAgSW5maW5pdGVTY3JvbGwucHJvdG90eXBlLmNyZWF0ZUxvYWRpbmdNb3JlID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkb3B0aW9uID0gJChcbiAgICAgICc8bGkgJyArXG4gICAgICAnY2xhc3M9XCJzZWxlY3QyLXJlc3VsdHNfX29wdGlvbiBzZWxlY3QyLXJlc3VsdHNfX29wdGlvbi0tbG9hZC1tb3JlXCInICtcbiAgICAgICdyb2xlPVwidHJlZWl0ZW1cIiBhcmlhLWRpc2FibGVkPVwidHJ1ZVwiPjwvbGk+J1xuICAgICk7XG5cbiAgICB2YXIgbWVzc2FnZSA9IHRoaXMub3B0aW9ucy5nZXQoJ3RyYW5zbGF0aW9ucycpLmdldCgnbG9hZGluZ01vcmUnKTtcblxuICAgICRvcHRpb24uaHRtbChtZXNzYWdlKHRoaXMubGFzdFBhcmFtcykpO1xuXG4gICAgcmV0dXJuICRvcHRpb247XG4gIH07XG5cbiAgcmV0dXJuIEluZmluaXRlU2Nyb2xsO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9kcm9wZG93bi9hdHRhY2hCb2R5JyxbXG4gICdqcXVlcnknLFxuICAnLi4vdXRpbHMnXG5dLCBmdW5jdGlvbiAoJCwgVXRpbHMpIHtcbiAgZnVuY3Rpb24gQXR0YWNoQm9keSAoZGVjb3JhdGVkLCAkZWxlbWVudCwgb3B0aW9ucykge1xuICAgIHRoaXMuJGRyb3Bkb3duUGFyZW50ID0gb3B0aW9ucy5nZXQoJ2Ryb3Bkb3duUGFyZW50JykgfHwgJChkb2N1bWVudC5ib2R5KTtcblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsICRlbGVtZW50LCBvcHRpb25zKTtcbiAgfVxuXG4gIEF0dGFjaEJvZHkucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbiAoZGVjb3JhdGVkLCBjb250YWluZXIsICRjb250YWluZXIpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB2YXIgc2V0dXBSZXN1bHRzRXZlbnRzID0gZmFsc2U7XG5cbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBjb250YWluZXIsICRjb250YWluZXIpO1xuXG4gICAgY29udGFpbmVyLm9uKCdvcGVuJywgZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi5fc2hvd0Ryb3Bkb3duKCk7XG4gICAgICBzZWxmLl9hdHRhY2hQb3NpdGlvbmluZ0hhbmRsZXIoY29udGFpbmVyKTtcblxuICAgICAgaWYgKCFzZXR1cFJlc3VsdHNFdmVudHMpIHtcbiAgICAgICAgc2V0dXBSZXN1bHRzRXZlbnRzID0gdHJ1ZTtcblxuICAgICAgICBjb250YWluZXIub24oJ3Jlc3VsdHM6YWxsJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHNlbGYuX3Bvc2l0aW9uRHJvcGRvd24oKTtcbiAgICAgICAgICBzZWxmLl9yZXNpemVEcm9wZG93bigpO1xuICAgICAgICB9KTtcblxuICAgICAgICBjb250YWluZXIub24oJ3Jlc3VsdHM6YXBwZW5kJywgZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHNlbGYuX3Bvc2l0aW9uRHJvcGRvd24oKTtcbiAgICAgICAgICBzZWxmLl9yZXNpemVEcm9wZG93bigpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIGNvbnRhaW5lci5vbignY2xvc2UnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLl9oaWRlRHJvcGRvd24oKTtcbiAgICAgIHNlbGYuX2RldGFjaFBvc2l0aW9uaW5nSGFuZGxlcihjb250YWluZXIpO1xuICAgIH0pO1xuXG4gICAgdGhpcy4kZHJvcGRvd25Db250YWluZXIub24oJ21vdXNlZG93bicsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIGV2dC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICB9KTtcbiAgfTtcblxuICBBdHRhY2hCb2R5LnByb3RvdHlwZS5kZXN0cm95ID0gZnVuY3Rpb24gKGRlY29yYXRlZCkge1xuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMpO1xuXG4gICAgdGhpcy4kZHJvcGRvd25Db250YWluZXIucmVtb3ZlKCk7XG4gIH07XG5cbiAgQXR0YWNoQm9keS5wcm90b3R5cGUucG9zaXRpb24gPSBmdW5jdGlvbiAoZGVjb3JhdGVkLCAkZHJvcGRvd24sICRjb250YWluZXIpIHtcbiAgICAvLyBDbG9uZSBhbGwgb2YgdGhlIGNvbnRhaW5lciBjbGFzc2VzXG4gICAgJGRyb3Bkb3duLmF0dHIoJ2NsYXNzJywgJGNvbnRhaW5lci5hdHRyKCdjbGFzcycpKTtcblxuICAgICRkcm9wZG93bi5yZW1vdmVDbGFzcygnc2VsZWN0MicpO1xuICAgICRkcm9wZG93bi5hZGRDbGFzcygnc2VsZWN0Mi1jb250YWluZXItLW9wZW4nKTtcblxuICAgICRkcm9wZG93bi5jc3Moe1xuICAgICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgICB0b3A6IC05OTk5OTlcbiAgICB9KTtcblxuICAgIHRoaXMuJGNvbnRhaW5lciA9ICRjb250YWluZXI7XG4gIH07XG5cbiAgQXR0YWNoQm9keS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKGRlY29yYXRlZCkge1xuICAgIHZhciAkY29udGFpbmVyID0gJCgnPHNwYW4+PC9zcGFuPicpO1xuXG4gICAgdmFyICRkcm9wZG93biA9IGRlY29yYXRlZC5jYWxsKHRoaXMpO1xuICAgICRjb250YWluZXIuYXBwZW5kKCRkcm9wZG93bik7XG5cbiAgICB0aGlzLiRkcm9wZG93bkNvbnRhaW5lciA9ICRjb250YWluZXI7XG5cbiAgICByZXR1cm4gJGNvbnRhaW5lcjtcbiAgfTtcblxuICBBdHRhY2hCb2R5LnByb3RvdHlwZS5faGlkZURyb3Bkb3duID0gZnVuY3Rpb24gKGRlY29yYXRlZCkge1xuICAgIHRoaXMuJGRyb3Bkb3duQ29udGFpbmVyLmRldGFjaCgpO1xuICB9O1xuXG4gIEF0dGFjaEJvZHkucHJvdG90eXBlLl9hdHRhY2hQb3NpdGlvbmluZ0hhbmRsZXIgPVxuICAgICAgZnVuY3Rpb24gKGRlY29yYXRlZCwgY29udGFpbmVyKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdmFyIHNjcm9sbEV2ZW50ID0gJ3Njcm9sbC5zZWxlY3QyLicgKyBjb250YWluZXIuaWQ7XG4gICAgdmFyIHJlc2l6ZUV2ZW50ID0gJ3Jlc2l6ZS5zZWxlY3QyLicgKyBjb250YWluZXIuaWQ7XG4gICAgdmFyIG9yaWVudGF0aW9uRXZlbnQgPSAnb3JpZW50YXRpb25jaGFuZ2Uuc2VsZWN0Mi4nICsgY29udGFpbmVyLmlkO1xuXG4gICAgdmFyICR3YXRjaGVycyA9IHRoaXMuJGNvbnRhaW5lci5wYXJlbnRzKCkuZmlsdGVyKFV0aWxzLmhhc1Njcm9sbCk7XG4gICAgJHdhdGNoZXJzLmVhY2goZnVuY3Rpb24gKCkge1xuICAgICAgVXRpbHMuU3RvcmVEYXRhKHRoaXMsICdzZWxlY3QyLXNjcm9sbC1wb3NpdGlvbicsIHtcbiAgICAgICAgeDogJCh0aGlzKS5zY3JvbGxMZWZ0KCksXG4gICAgICAgIHk6ICQodGhpcykuc2Nyb2xsVG9wKClcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgJHdhdGNoZXJzLm9uKHNjcm9sbEV2ZW50LCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgIHZhciBwb3NpdGlvbiA9IFV0aWxzLkdldERhdGEodGhpcywgJ3NlbGVjdDItc2Nyb2xsLXBvc2l0aW9uJyk7XG4gICAgICAkKHRoaXMpLnNjcm9sbFRvcChwb3NpdGlvbi55KTtcbiAgICB9KTtcblxuICAgICQod2luZG93KS5vbihzY3JvbGxFdmVudCArICcgJyArIHJlc2l6ZUV2ZW50ICsgJyAnICsgb3JpZW50YXRpb25FdmVudCxcbiAgICAgIGZ1bmN0aW9uIChlKSB7XG4gICAgICBzZWxmLl9wb3NpdGlvbkRyb3Bkb3duKCk7XG4gICAgICBzZWxmLl9yZXNpemVEcm9wZG93bigpO1xuICAgIH0pO1xuICB9O1xuXG4gIEF0dGFjaEJvZHkucHJvdG90eXBlLl9kZXRhY2hQb3NpdGlvbmluZ0hhbmRsZXIgPVxuICAgICAgZnVuY3Rpb24gKGRlY29yYXRlZCwgY29udGFpbmVyKSB7XG4gICAgdmFyIHNjcm9sbEV2ZW50ID0gJ3Njcm9sbC5zZWxlY3QyLicgKyBjb250YWluZXIuaWQ7XG4gICAgdmFyIHJlc2l6ZUV2ZW50ID0gJ3Jlc2l6ZS5zZWxlY3QyLicgKyBjb250YWluZXIuaWQ7XG4gICAgdmFyIG9yaWVudGF0aW9uRXZlbnQgPSAnb3JpZW50YXRpb25jaGFuZ2Uuc2VsZWN0Mi4nICsgY29udGFpbmVyLmlkO1xuXG4gICAgdmFyICR3YXRjaGVycyA9IHRoaXMuJGNvbnRhaW5lci5wYXJlbnRzKCkuZmlsdGVyKFV0aWxzLmhhc1Njcm9sbCk7XG4gICAgJHdhdGNoZXJzLm9mZihzY3JvbGxFdmVudCk7XG5cbiAgICAkKHdpbmRvdykub2ZmKHNjcm9sbEV2ZW50ICsgJyAnICsgcmVzaXplRXZlbnQgKyAnICcgKyBvcmllbnRhdGlvbkV2ZW50KTtcbiAgfTtcblxuICBBdHRhY2hCb2R5LnByb3RvdHlwZS5fcG9zaXRpb25Ecm9wZG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgJHdpbmRvdyA9ICQod2luZG93KTtcblxuICAgIHZhciBpc0N1cnJlbnRseUFib3ZlID0gdGhpcy4kZHJvcGRvd24uaGFzQ2xhc3MoJ3NlbGVjdDItZHJvcGRvd24tLWFib3ZlJyk7XG4gICAgdmFyIGlzQ3VycmVudGx5QmVsb3cgPSB0aGlzLiRkcm9wZG93bi5oYXNDbGFzcygnc2VsZWN0Mi1kcm9wZG93bi0tYmVsb3cnKTtcblxuICAgIHZhciBuZXdEaXJlY3Rpb24gPSBudWxsO1xuXG4gICAgdmFyIG9mZnNldCA9IHRoaXMuJGNvbnRhaW5lci5vZmZzZXQoKTtcblxuICAgIG9mZnNldC5ib3R0b20gPSBvZmZzZXQudG9wICsgdGhpcy4kY29udGFpbmVyLm91dGVySGVpZ2h0KGZhbHNlKTtcblxuICAgIHZhciBjb250YWluZXIgPSB7XG4gICAgICBoZWlnaHQ6IHRoaXMuJGNvbnRhaW5lci5vdXRlckhlaWdodChmYWxzZSlcbiAgICB9O1xuXG4gICAgY29udGFpbmVyLnRvcCA9IG9mZnNldC50b3A7XG4gICAgY29udGFpbmVyLmJvdHRvbSA9IG9mZnNldC50b3AgKyBjb250YWluZXIuaGVpZ2h0O1xuXG4gICAgdmFyIGRyb3Bkb3duID0ge1xuICAgICAgaGVpZ2h0OiB0aGlzLiRkcm9wZG93bi5vdXRlckhlaWdodChmYWxzZSlcbiAgICB9O1xuXG4gICAgdmFyIHZpZXdwb3J0ID0ge1xuICAgICAgdG9wOiAkd2luZG93LnNjcm9sbFRvcCgpLFxuICAgICAgYm90dG9tOiAkd2luZG93LnNjcm9sbFRvcCgpICsgJHdpbmRvdy5oZWlnaHQoKVxuICAgIH07XG5cbiAgICB2YXIgZW5vdWdoUm9vbUFib3ZlID0gdmlld3BvcnQudG9wIDwgKG9mZnNldC50b3AgLSBkcm9wZG93bi5oZWlnaHQpO1xuICAgIHZhciBlbm91Z2hSb29tQmVsb3cgPSB2aWV3cG9ydC5ib3R0b20gPiAob2Zmc2V0LmJvdHRvbSArIGRyb3Bkb3duLmhlaWdodCk7XG5cbiAgICB2YXIgY3NzID0ge1xuICAgICAgbGVmdDogb2Zmc2V0LmxlZnQsXG4gICAgICB0b3A6IGNvbnRhaW5lci5ib3R0b21cbiAgICB9O1xuXG4gICAgLy8gRGV0ZXJtaW5lIHdoYXQgdGhlIHBhcmVudCBlbGVtZW50IGlzIHRvIHVzZSBmb3IgY2FsY2l1bGF0aW5nIHRoZSBvZmZzZXRcbiAgICB2YXIgJG9mZnNldFBhcmVudCA9IHRoaXMuJGRyb3Bkb3duUGFyZW50O1xuXG4gICAgLy8gRm9yIHN0YXRpY2FsbHkgcG9zaXRvbmVkIGVsZW1lbnRzLCB3ZSBuZWVkIHRvIGdldCB0aGUgZWxlbWVudFxuICAgIC8vIHRoYXQgaXMgZGV0ZXJtaW5pbmcgdGhlIG9mZnNldFxuICAgIGlmICgkb2Zmc2V0UGFyZW50LmNzcygncG9zaXRpb24nKSA9PT0gJ3N0YXRpYycpIHtcbiAgICAgICRvZmZzZXRQYXJlbnQgPSAkb2Zmc2V0UGFyZW50Lm9mZnNldFBhcmVudCgpO1xuICAgIH1cblxuICAgIHZhciBwYXJlbnRPZmZzZXQgPSAkb2Zmc2V0UGFyZW50Lm9mZnNldCgpO1xuXG4gICAgY3NzLnRvcCAtPSBwYXJlbnRPZmZzZXQudG9wO1xuICAgIGNzcy5sZWZ0IC09IHBhcmVudE9mZnNldC5sZWZ0O1xuXG4gICAgaWYgKCFpc0N1cnJlbnRseUFib3ZlICYmICFpc0N1cnJlbnRseUJlbG93KSB7XG4gICAgICBuZXdEaXJlY3Rpb24gPSAnYmVsb3cnO1xuICAgIH1cblxuICAgIGlmICghZW5vdWdoUm9vbUJlbG93ICYmIGVub3VnaFJvb21BYm92ZSAmJiAhaXNDdXJyZW50bHlBYm92ZSkge1xuICAgICAgbmV3RGlyZWN0aW9uID0gJ2Fib3ZlJztcbiAgICB9IGVsc2UgaWYgKCFlbm91Z2hSb29tQWJvdmUgJiYgZW5vdWdoUm9vbUJlbG93ICYmIGlzQ3VycmVudGx5QWJvdmUpIHtcbiAgICAgIG5ld0RpcmVjdGlvbiA9ICdiZWxvdyc7XG4gICAgfVxuXG4gICAgaWYgKG5ld0RpcmVjdGlvbiA9PSAnYWJvdmUnIHx8XG4gICAgICAoaXNDdXJyZW50bHlBYm92ZSAmJiBuZXdEaXJlY3Rpb24gIT09ICdiZWxvdycpKSB7XG4gICAgICBjc3MudG9wID0gY29udGFpbmVyLnRvcCAtIHBhcmVudE9mZnNldC50b3AgLSBkcm9wZG93bi5oZWlnaHQ7XG4gICAgfVxuXG4gICAgaWYgKG5ld0RpcmVjdGlvbiAhPSBudWxsKSB7XG4gICAgICB0aGlzLiRkcm9wZG93blxuICAgICAgICAucmVtb3ZlQ2xhc3MoJ3NlbGVjdDItZHJvcGRvd24tLWJlbG93IHNlbGVjdDItZHJvcGRvd24tLWFib3ZlJylcbiAgICAgICAgLmFkZENsYXNzKCdzZWxlY3QyLWRyb3Bkb3duLS0nICsgbmV3RGlyZWN0aW9uKTtcbiAgICAgIHRoaXMuJGNvbnRhaW5lclxuICAgICAgICAucmVtb3ZlQ2xhc3MoJ3NlbGVjdDItY29udGFpbmVyLS1iZWxvdyBzZWxlY3QyLWNvbnRhaW5lci0tYWJvdmUnKVxuICAgICAgICAuYWRkQ2xhc3MoJ3NlbGVjdDItY29udGFpbmVyLS0nICsgbmV3RGlyZWN0aW9uKTtcbiAgICB9XG5cbiAgICB0aGlzLiRkcm9wZG93bkNvbnRhaW5lci5jc3MoY3NzKTtcbiAgfTtcblxuICBBdHRhY2hCb2R5LnByb3RvdHlwZS5fcmVzaXplRHJvcGRvd24gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNzcyA9IHtcbiAgICAgIHdpZHRoOiB0aGlzLiRjb250YWluZXIub3V0ZXJXaWR0aChmYWxzZSkgKyAncHgnXG4gICAgfTtcblxuICAgIGlmICh0aGlzLm9wdGlvbnMuZ2V0KCdkcm9wZG93bkF1dG9XaWR0aCcpKSB7XG4gICAgICBjc3MubWluV2lkdGggPSBjc3Mud2lkdGg7XG4gICAgICBjc3MucG9zaXRpb24gPSAncmVsYXRpdmUnO1xuICAgICAgY3NzLndpZHRoID0gJ2F1dG8nO1xuICAgIH1cblxuICAgIHRoaXMuJGRyb3Bkb3duLmNzcyhjc3MpO1xuICB9O1xuXG4gIEF0dGFjaEJvZHkucHJvdG90eXBlLl9zaG93RHJvcGRvd24gPSBmdW5jdGlvbiAoZGVjb3JhdGVkKSB7XG4gICAgdGhpcy4kZHJvcGRvd25Db250YWluZXIuYXBwZW5kVG8odGhpcy4kZHJvcGRvd25QYXJlbnQpO1xuXG4gICAgdGhpcy5fcG9zaXRpb25Ecm9wZG93bigpO1xuICAgIHRoaXMuX3Jlc2l6ZURyb3Bkb3duKCk7XG4gIH07XG5cbiAgcmV0dXJuIEF0dGFjaEJvZHk7XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2Ryb3Bkb3duL21pbmltdW1SZXN1bHRzRm9yU2VhcmNoJyxbXG5cbl0sIGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gY291bnRSZXN1bHRzIChkYXRhKSB7XG4gICAgdmFyIGNvdW50ID0gMDtcblxuICAgIGZvciAodmFyIGQgPSAwOyBkIDwgZGF0YS5sZW5ndGg7IGQrKykge1xuICAgICAgdmFyIGl0ZW0gPSBkYXRhW2RdO1xuXG4gICAgICBpZiAoaXRlbS5jaGlsZHJlbikge1xuICAgICAgICBjb3VudCArPSBjb3VudFJlc3VsdHMoaXRlbS5jaGlsZHJlbik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb3VudCsrO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBjb3VudDtcbiAgfVxuXG4gIGZ1bmN0aW9uIE1pbmltdW1SZXN1bHRzRm9yU2VhcmNoIChkZWNvcmF0ZWQsICRlbGVtZW50LCBvcHRpb25zLCBkYXRhQWRhcHRlcikge1xuICAgIHRoaXMubWluaW11bVJlc3VsdHNGb3JTZWFyY2ggPSBvcHRpb25zLmdldCgnbWluaW11bVJlc3VsdHNGb3JTZWFyY2gnKTtcblxuICAgIGlmICh0aGlzLm1pbmltdW1SZXN1bHRzRm9yU2VhcmNoIDwgMCkge1xuICAgICAgdGhpcy5taW5pbXVtUmVzdWx0c0ZvclNlYXJjaCA9IEluZmluaXR5O1xuICAgIH1cblxuICAgIGRlY29yYXRlZC5jYWxsKHRoaXMsICRlbGVtZW50LCBvcHRpb25zLCBkYXRhQWRhcHRlcik7XG4gIH1cblxuICBNaW5pbXVtUmVzdWx0c0ZvclNlYXJjaC5wcm90b3R5cGUuc2hvd1NlYXJjaCA9IGZ1bmN0aW9uIChkZWNvcmF0ZWQsIHBhcmFtcykge1xuICAgIGlmIChjb3VudFJlc3VsdHMocGFyYW1zLmRhdGEucmVzdWx0cykgPCB0aGlzLm1pbmltdW1SZXN1bHRzRm9yU2VhcmNoKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgcmV0dXJuIGRlY29yYXRlZC5jYWxsKHRoaXMsIHBhcmFtcyk7XG4gIH07XG5cbiAgcmV0dXJuIE1pbmltdW1SZXN1bHRzRm9yU2VhcmNoO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9kcm9wZG93bi9zZWxlY3RPbkNsb3NlJyxbXG4gICcuLi91dGlscydcbl0sIGZ1bmN0aW9uIChVdGlscykge1xuICBmdW5jdGlvbiBTZWxlY3RPbkNsb3NlICgpIHsgfVxuXG4gIFNlbGVjdE9uQ2xvc2UucHJvdG90eXBlLmJpbmQgPSBmdW5jdGlvbiAoZGVjb3JhdGVkLCBjb250YWluZXIsICRjb250YWluZXIpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICBkZWNvcmF0ZWQuY2FsbCh0aGlzLCBjb250YWluZXIsICRjb250YWluZXIpO1xuXG4gICAgY29udGFpbmVyLm9uKCdjbG9zZScsIGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgIHNlbGYuX2hhbmRsZVNlbGVjdE9uQ2xvc2UocGFyYW1zKTtcbiAgICB9KTtcbiAgfTtcblxuICBTZWxlY3RPbkNsb3NlLnByb3RvdHlwZS5faGFuZGxlU2VsZWN0T25DbG9zZSA9IGZ1bmN0aW9uIChfLCBwYXJhbXMpIHtcbiAgICBpZiAocGFyYW1zICYmIHBhcmFtcy5vcmlnaW5hbFNlbGVjdDJFdmVudCAhPSBudWxsKSB7XG4gICAgICB2YXIgZXZlbnQgPSBwYXJhbXMub3JpZ2luYWxTZWxlY3QyRXZlbnQ7XG5cbiAgICAgIC8vIERvbid0IHNlbGVjdCBhbiBpdGVtIGlmIHRoZSBjbG9zZSBldmVudCB3YXMgdHJpZ2dlcmVkIGZyb20gYSBzZWxlY3Qgb3JcbiAgICAgIC8vIHVuc2VsZWN0IGV2ZW50XG4gICAgICBpZiAoZXZlbnQuX3R5cGUgPT09ICdzZWxlY3QnIHx8IGV2ZW50Ll90eXBlID09PSAndW5zZWxlY3QnKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgJGhpZ2hsaWdodGVkUmVzdWx0cyA9IHRoaXMuZ2V0SGlnaGxpZ2h0ZWRSZXN1bHRzKCk7XG5cbiAgICAvLyBPbmx5IHNlbGVjdCBoaWdobGlnaHRlZCByZXN1bHRzXG4gICAgaWYgKCRoaWdobGlnaHRlZFJlc3VsdHMubGVuZ3RoIDwgMSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHZhciBkYXRhID0gVXRpbHMuR2V0RGF0YSgkaGlnaGxpZ2h0ZWRSZXN1bHRzWzBdLCAnZGF0YScpO1xuXG4gICAgLy8gRG9uJ3QgcmUtc2VsZWN0IGFscmVhZHkgc2VsZWN0ZWQgcmVzdWx0ZVxuICAgIGlmIChcbiAgICAgIChkYXRhLmVsZW1lbnQgIT0gbnVsbCAmJiBkYXRhLmVsZW1lbnQuc2VsZWN0ZWQpIHx8XG4gICAgICAoZGF0YS5lbGVtZW50ID09IG51bGwgJiYgZGF0YS5zZWxlY3RlZClcbiAgICApIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnRyaWdnZXIoJ3NlbGVjdCcsIHtcbiAgICAgICAgZGF0YTogZGF0YVxuICAgIH0pO1xuICB9O1xuXG4gIHJldHVybiBTZWxlY3RPbkNsb3NlO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9kcm9wZG93bi9jbG9zZU9uU2VsZWN0JyxbXG5cbl0sIGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gQ2xvc2VPblNlbGVjdCAoKSB7IH1cblxuICBDbG9zZU9uU2VsZWN0LnByb3RvdHlwZS5iaW5kID0gZnVuY3Rpb24gKGRlY29yYXRlZCwgY29udGFpbmVyLCAkY29udGFpbmVyKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgZGVjb3JhdGVkLmNhbGwodGhpcywgY29udGFpbmVyLCAkY29udGFpbmVyKTtcblxuICAgIGNvbnRhaW5lci5vbignc2VsZWN0JywgZnVuY3Rpb24gKGV2dCkge1xuICAgICAgc2VsZi5fc2VsZWN0VHJpZ2dlcmVkKGV2dCk7XG4gICAgfSk7XG5cbiAgICBjb250YWluZXIub24oJ3Vuc2VsZWN0JywgZnVuY3Rpb24gKGV2dCkge1xuICAgICAgc2VsZi5fc2VsZWN0VHJpZ2dlcmVkKGV2dCk7XG4gICAgfSk7XG4gIH07XG5cbiAgQ2xvc2VPblNlbGVjdC5wcm90b3R5cGUuX3NlbGVjdFRyaWdnZXJlZCA9IGZ1bmN0aW9uIChfLCBldnQpIHtcbiAgICB2YXIgb3JpZ2luYWxFdmVudCA9IGV2dC5vcmlnaW5hbEV2ZW50O1xuXG4gICAgLy8gRG9uJ3QgY2xvc2UgaWYgdGhlIGNvbnRyb2wga2V5IGlzIGJlaW5nIGhlbGRcbiAgICBpZiAob3JpZ2luYWxFdmVudCAmJiBvcmlnaW5hbEV2ZW50LmN0cmxLZXkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnRyaWdnZXIoJ2Nsb3NlJywge1xuICAgICAgb3JpZ2luYWxFdmVudDogb3JpZ2luYWxFdmVudCxcbiAgICAgIG9yaWdpbmFsU2VsZWN0MkV2ZW50OiBldnRcbiAgICB9KTtcbiAgfTtcblxuICByZXR1cm4gQ2xvc2VPblNlbGVjdDtcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIvaTE4bi9lbicsW10sZnVuY3Rpb24gKCkge1xuICAvLyBFbmdsaXNoXG4gIHJldHVybiB7XG4gICAgZXJyb3JMb2FkaW5nOiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ1RoZSByZXN1bHRzIGNvdWxkIG5vdCBiZSBsb2FkZWQuJztcbiAgICB9LFxuICAgIGlucHV0VG9vTG9uZzogZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgIHZhciBvdmVyQ2hhcnMgPSBhcmdzLmlucHV0Lmxlbmd0aCAtIGFyZ3MubWF4aW11bTtcblxuICAgICAgdmFyIG1lc3NhZ2UgPSAnUGxlYXNlIGRlbGV0ZSAnICsgb3ZlckNoYXJzICsgJyBjaGFyYWN0ZXInO1xuXG4gICAgICBpZiAob3ZlckNoYXJzICE9IDEpIHtcbiAgICAgICAgbWVzc2FnZSArPSAncyc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBtZXNzYWdlO1xuICAgIH0sXG4gICAgaW5wdXRUb29TaG9ydDogZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgIHZhciByZW1haW5pbmdDaGFycyA9IGFyZ3MubWluaW11bSAtIGFyZ3MuaW5wdXQubGVuZ3RoO1xuXG4gICAgICB2YXIgbWVzc2FnZSA9ICdQbGVhc2UgZW50ZXIgJyArIHJlbWFpbmluZ0NoYXJzICsgJyBvciBtb3JlIGNoYXJhY3RlcnMnO1xuXG4gICAgICByZXR1cm4gbWVzc2FnZTtcbiAgICB9LFxuICAgIGxvYWRpbmdNb3JlOiBmdW5jdGlvbiAoKSB7XG4gICAgICByZXR1cm4gJ0xvYWRpbmcgbW9yZSByZXN1bHRz4oCmJztcbiAgICB9LFxuICAgIG1heGltdW1TZWxlY3RlZDogZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICAgIHZhciBtZXNzYWdlID0gJ1lvdSBjYW4gb25seSBzZWxlY3QgJyArIGFyZ3MubWF4aW11bSArICcgaXRlbSc7XG5cbiAgICAgIGlmIChhcmdzLm1heGltdW0gIT0gMSkge1xuICAgICAgICBtZXNzYWdlICs9ICdzJztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIG1lc3NhZ2U7XG4gICAgfSxcbiAgICBub1Jlc3VsdHM6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnTm8gcmVzdWx0cyBmb3VuZCc7XG4gICAgfSxcbiAgICBzZWFyY2hpbmc6IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiAnU2VhcmNoaW5n4oCmJztcbiAgICB9XG4gIH07XG59KTtcblxuUzIuZGVmaW5lKCdzZWxlY3QyL2RlZmF1bHRzJyxbXG4gICdqcXVlcnknLFxuICAncmVxdWlyZScsXG5cbiAgJy4vcmVzdWx0cycsXG5cbiAgJy4vc2VsZWN0aW9uL3NpbmdsZScsXG4gICcuL3NlbGVjdGlvbi9tdWx0aXBsZScsXG4gICcuL3NlbGVjdGlvbi9wbGFjZWhvbGRlcicsXG4gICcuL3NlbGVjdGlvbi9hbGxvd0NsZWFyJyxcbiAgJy4vc2VsZWN0aW9uL3NlYXJjaCcsXG4gICcuL3NlbGVjdGlvbi9ldmVudFJlbGF5JyxcblxuICAnLi91dGlscycsXG4gICcuL3RyYW5zbGF0aW9uJyxcbiAgJy4vZGlhY3JpdGljcycsXG5cbiAgJy4vZGF0YS9zZWxlY3QnLFxuICAnLi9kYXRhL2FycmF5JyxcbiAgJy4vZGF0YS9hamF4JyxcbiAgJy4vZGF0YS90YWdzJyxcbiAgJy4vZGF0YS90b2tlbml6ZXInLFxuICAnLi9kYXRhL21pbmltdW1JbnB1dExlbmd0aCcsXG4gICcuL2RhdGEvbWF4aW11bUlucHV0TGVuZ3RoJyxcbiAgJy4vZGF0YS9tYXhpbXVtU2VsZWN0aW9uTGVuZ3RoJyxcblxuICAnLi9kcm9wZG93bicsXG4gICcuL2Ryb3Bkb3duL3NlYXJjaCcsXG4gICcuL2Ryb3Bkb3duL2hpZGVQbGFjZWhvbGRlcicsXG4gICcuL2Ryb3Bkb3duL2luZmluaXRlU2Nyb2xsJyxcbiAgJy4vZHJvcGRvd24vYXR0YWNoQm9keScsXG4gICcuL2Ryb3Bkb3duL21pbmltdW1SZXN1bHRzRm9yU2VhcmNoJyxcbiAgJy4vZHJvcGRvd24vc2VsZWN0T25DbG9zZScsXG4gICcuL2Ryb3Bkb3duL2Nsb3NlT25TZWxlY3QnLFxuXG4gICcuL2kxOG4vZW4nXG5dLCBmdW5jdGlvbiAoJCwgcmVxdWlyZSxcblxuICAgICAgICAgICAgIFJlc3VsdHNMaXN0LFxuXG4gICAgICAgICAgICAgU2luZ2xlU2VsZWN0aW9uLCBNdWx0aXBsZVNlbGVjdGlvbiwgUGxhY2Vob2xkZXIsIEFsbG93Q2xlYXIsXG4gICAgICAgICAgICAgU2VsZWN0aW9uU2VhcmNoLCBFdmVudFJlbGF5LFxuXG4gICAgICAgICAgICAgVXRpbHMsIFRyYW5zbGF0aW9uLCBESUFDUklUSUNTLFxuXG4gICAgICAgICAgICAgU2VsZWN0RGF0YSwgQXJyYXlEYXRhLCBBamF4RGF0YSwgVGFncywgVG9rZW5pemVyLFxuICAgICAgICAgICAgIE1pbmltdW1JbnB1dExlbmd0aCwgTWF4aW11bUlucHV0TGVuZ3RoLCBNYXhpbXVtU2VsZWN0aW9uTGVuZ3RoLFxuXG4gICAgICAgICAgICAgRHJvcGRvd24sIERyb3Bkb3duU2VhcmNoLCBIaWRlUGxhY2Vob2xkZXIsIEluZmluaXRlU2Nyb2xsLFxuICAgICAgICAgICAgIEF0dGFjaEJvZHksIE1pbmltdW1SZXN1bHRzRm9yU2VhcmNoLCBTZWxlY3RPbkNsb3NlLCBDbG9zZU9uU2VsZWN0LFxuXG4gICAgICAgICAgICAgRW5nbGlzaFRyYW5zbGF0aW9uKSB7XG4gIGZ1bmN0aW9uIERlZmF1bHRzICgpIHtcbiAgICB0aGlzLnJlc2V0KCk7XG4gIH1cblxuICBEZWZhdWx0cy5wcm90b3R5cGUuYXBwbHkgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgIG9wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgdGhpcy5kZWZhdWx0cywgb3B0aW9ucyk7XG5cbiAgICBpZiAob3B0aW9ucy5kYXRhQWRhcHRlciA9PSBudWxsKSB7XG4gICAgICBpZiAob3B0aW9ucy5hamF4ICE9IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucy5kYXRhQWRhcHRlciA9IEFqYXhEYXRhO1xuICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmRhdGEgIT0gbnVsbCkge1xuICAgICAgICBvcHRpb25zLmRhdGFBZGFwdGVyID0gQXJyYXlEYXRhO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3B0aW9ucy5kYXRhQWRhcHRlciA9IFNlbGVjdERhdGE7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLm1pbmltdW1JbnB1dExlbmd0aCA+IDApIHtcbiAgICAgICAgb3B0aW9ucy5kYXRhQWRhcHRlciA9IFV0aWxzLkRlY29yYXRlKFxuICAgICAgICAgIG9wdGlvbnMuZGF0YUFkYXB0ZXIsXG4gICAgICAgICAgTWluaW11bUlucHV0TGVuZ3RoXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLm1heGltdW1JbnB1dExlbmd0aCA+IDApIHtcbiAgICAgICAgb3B0aW9ucy5kYXRhQWRhcHRlciA9IFV0aWxzLkRlY29yYXRlKFxuICAgICAgICAgIG9wdGlvbnMuZGF0YUFkYXB0ZXIsXG4gICAgICAgICAgTWF4aW11bUlucHV0TGVuZ3RoXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLm1heGltdW1TZWxlY3Rpb25MZW5ndGggPiAwKSB7XG4gICAgICAgIG9wdGlvbnMuZGF0YUFkYXB0ZXIgPSBVdGlscy5EZWNvcmF0ZShcbiAgICAgICAgICBvcHRpb25zLmRhdGFBZGFwdGVyLFxuICAgICAgICAgIE1heGltdW1TZWxlY3Rpb25MZW5ndGhcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMudGFncykge1xuICAgICAgICBvcHRpb25zLmRhdGFBZGFwdGVyID0gVXRpbHMuRGVjb3JhdGUob3B0aW9ucy5kYXRhQWRhcHRlciwgVGFncyk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnRva2VuU2VwYXJhdG9ycyAhPSBudWxsIHx8IG9wdGlvbnMudG9rZW5pemVyICE9IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucy5kYXRhQWRhcHRlciA9IFV0aWxzLkRlY29yYXRlKFxuICAgICAgICAgIG9wdGlvbnMuZGF0YUFkYXB0ZXIsXG4gICAgICAgICAgVG9rZW5pemVyXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChvcHRpb25zLnF1ZXJ5ICE9IG51bGwpIHtcbiAgICAgICAgdmFyIFF1ZXJ5ID0gcmVxdWlyZShvcHRpb25zLmFtZEJhc2UgKyAnY29tcGF0L3F1ZXJ5Jyk7XG5cbiAgICAgICAgb3B0aW9ucy5kYXRhQWRhcHRlciA9IFV0aWxzLkRlY29yYXRlKFxuICAgICAgICAgIG9wdGlvbnMuZGF0YUFkYXB0ZXIsXG4gICAgICAgICAgUXVlcnlcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuaW5pdFNlbGVjdGlvbiAhPSBudWxsKSB7XG4gICAgICAgIHZhciBJbml0U2VsZWN0aW9uID0gcmVxdWlyZShvcHRpb25zLmFtZEJhc2UgKyAnY29tcGF0L2luaXRTZWxlY3Rpb24nKTtcblxuICAgICAgICBvcHRpb25zLmRhdGFBZGFwdGVyID0gVXRpbHMuRGVjb3JhdGUoXG4gICAgICAgICAgb3B0aW9ucy5kYXRhQWRhcHRlcixcbiAgICAgICAgICBJbml0U2VsZWN0aW9uXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMucmVzdWx0c0FkYXB0ZXIgPT0gbnVsbCkge1xuICAgICAgb3B0aW9ucy5yZXN1bHRzQWRhcHRlciA9IFJlc3VsdHNMaXN0O1xuXG4gICAgICBpZiAob3B0aW9ucy5hamF4ICE9IG51bGwpIHtcbiAgICAgICAgb3B0aW9ucy5yZXN1bHRzQWRhcHRlciA9IFV0aWxzLkRlY29yYXRlKFxuICAgICAgICAgIG9wdGlvbnMucmVzdWx0c0FkYXB0ZXIsXG4gICAgICAgICAgSW5maW5pdGVTY3JvbGxcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMucGxhY2Vob2xkZXIgIT0gbnVsbCkge1xuICAgICAgICBvcHRpb25zLnJlc3VsdHNBZGFwdGVyID0gVXRpbHMuRGVjb3JhdGUoXG4gICAgICAgICAgb3B0aW9ucy5yZXN1bHRzQWRhcHRlcixcbiAgICAgICAgICBIaWRlUGxhY2Vob2xkZXJcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuc2VsZWN0T25DbG9zZSkge1xuICAgICAgICBvcHRpb25zLnJlc3VsdHNBZGFwdGVyID0gVXRpbHMuRGVjb3JhdGUoXG4gICAgICAgICAgb3B0aW9ucy5yZXN1bHRzQWRhcHRlcixcbiAgICAgICAgICBTZWxlY3RPbkNsb3NlXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnMuZHJvcGRvd25BZGFwdGVyID09IG51bGwpIHtcbiAgICAgIGlmIChvcHRpb25zLm11bHRpcGxlKSB7XG4gICAgICAgIG9wdGlvbnMuZHJvcGRvd25BZGFwdGVyID0gRHJvcGRvd247XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB2YXIgU2VhcmNoYWJsZURyb3Bkb3duID0gVXRpbHMuRGVjb3JhdGUoRHJvcGRvd24sIERyb3Bkb3duU2VhcmNoKTtcblxuICAgICAgICBvcHRpb25zLmRyb3Bkb3duQWRhcHRlciA9IFNlYXJjaGFibGVEcm9wZG93bjtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMubWluaW11bVJlc3VsdHNGb3JTZWFyY2ggIT09IDApIHtcbiAgICAgICAgb3B0aW9ucy5kcm9wZG93bkFkYXB0ZXIgPSBVdGlscy5EZWNvcmF0ZShcbiAgICAgICAgICBvcHRpb25zLmRyb3Bkb3duQWRhcHRlcixcbiAgICAgICAgICBNaW5pbXVtUmVzdWx0c0ZvclNlYXJjaFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5jbG9zZU9uU2VsZWN0KSB7XG4gICAgICAgIG9wdGlvbnMuZHJvcGRvd25BZGFwdGVyID0gVXRpbHMuRGVjb3JhdGUoXG4gICAgICAgICAgb3B0aW9ucy5kcm9wZG93bkFkYXB0ZXIsXG4gICAgICAgICAgQ2xvc2VPblNlbGVjdFxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAoXG4gICAgICAgIG9wdGlvbnMuZHJvcGRvd25Dc3NDbGFzcyAhPSBudWxsIHx8XG4gICAgICAgIG9wdGlvbnMuZHJvcGRvd25Dc3MgIT0gbnVsbCB8fFxuICAgICAgICBvcHRpb25zLmFkYXB0RHJvcGRvd25Dc3NDbGFzcyAhPSBudWxsXG4gICAgICApIHtcbiAgICAgICAgdmFyIERyb3Bkb3duQ1NTID0gcmVxdWlyZShvcHRpb25zLmFtZEJhc2UgKyAnY29tcGF0L2Ryb3Bkb3duQ3NzJyk7XG5cbiAgICAgICAgb3B0aW9ucy5kcm9wZG93bkFkYXB0ZXIgPSBVdGlscy5EZWNvcmF0ZShcbiAgICAgICAgICBvcHRpb25zLmRyb3Bkb3duQWRhcHRlcixcbiAgICAgICAgICBEcm9wZG93bkNTU1xuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBvcHRpb25zLmRyb3Bkb3duQWRhcHRlciA9IFV0aWxzLkRlY29yYXRlKFxuICAgICAgICBvcHRpb25zLmRyb3Bkb3duQWRhcHRlcixcbiAgICAgICAgQXR0YWNoQm9keVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5zZWxlY3Rpb25BZGFwdGVyID09IG51bGwpIHtcbiAgICAgIGlmIChvcHRpb25zLm11bHRpcGxlKSB7XG4gICAgICAgIG9wdGlvbnMuc2VsZWN0aW9uQWRhcHRlciA9IE11bHRpcGxlU2VsZWN0aW9uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3B0aW9ucy5zZWxlY3Rpb25BZGFwdGVyID0gU2luZ2xlU2VsZWN0aW9uO1xuICAgICAgfVxuXG4gICAgICAvLyBBZGQgdGhlIHBsYWNlaG9sZGVyIG1peGluIGlmIGEgcGxhY2Vob2xkZXIgd2FzIHNwZWNpZmllZFxuICAgICAgaWYgKG9wdGlvbnMucGxhY2Vob2xkZXIgIT0gbnVsbCkge1xuICAgICAgICBvcHRpb25zLnNlbGVjdGlvbkFkYXB0ZXIgPSBVdGlscy5EZWNvcmF0ZShcbiAgICAgICAgICBvcHRpb25zLnNlbGVjdGlvbkFkYXB0ZXIsXG4gICAgICAgICAgUGxhY2Vob2xkZXJcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuYWxsb3dDbGVhcikge1xuICAgICAgICBvcHRpb25zLnNlbGVjdGlvbkFkYXB0ZXIgPSBVdGlscy5EZWNvcmF0ZShcbiAgICAgICAgICBvcHRpb25zLnNlbGVjdGlvbkFkYXB0ZXIsXG4gICAgICAgICAgQWxsb3dDbGVhclxuICAgICAgICApO1xuICAgICAgfVxuXG4gICAgICBpZiAob3B0aW9ucy5tdWx0aXBsZSkge1xuICAgICAgICBvcHRpb25zLnNlbGVjdGlvbkFkYXB0ZXIgPSBVdGlscy5EZWNvcmF0ZShcbiAgICAgICAgICBvcHRpb25zLnNlbGVjdGlvbkFkYXB0ZXIsXG4gICAgICAgICAgU2VsZWN0aW9uU2VhcmNoXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGlmIChcbiAgICAgICAgb3B0aW9ucy5jb250YWluZXJDc3NDbGFzcyAhPSBudWxsIHx8XG4gICAgICAgIG9wdGlvbnMuY29udGFpbmVyQ3NzICE9IG51bGwgfHxcbiAgICAgICAgb3B0aW9ucy5hZGFwdENvbnRhaW5lckNzc0NsYXNzICE9IG51bGxcbiAgICAgICkge1xuICAgICAgICB2YXIgQ29udGFpbmVyQ1NTID0gcmVxdWlyZShvcHRpb25zLmFtZEJhc2UgKyAnY29tcGF0L2NvbnRhaW5lckNzcycpO1xuXG4gICAgICAgIG9wdGlvbnMuc2VsZWN0aW9uQWRhcHRlciA9IFV0aWxzLkRlY29yYXRlKFxuICAgICAgICAgIG9wdGlvbnMuc2VsZWN0aW9uQWRhcHRlcixcbiAgICAgICAgICBDb250YWluZXJDU1NcbiAgICAgICAgKTtcbiAgICAgIH1cblxuICAgICAgb3B0aW9ucy5zZWxlY3Rpb25BZGFwdGVyID0gVXRpbHMuRGVjb3JhdGUoXG4gICAgICAgIG9wdGlvbnMuc2VsZWN0aW9uQWRhcHRlcixcbiAgICAgICAgRXZlbnRSZWxheVxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMubGFuZ3VhZ2UgPT09ICdzdHJpbmcnKSB7XG4gICAgICAvLyBDaGVjayBpZiB0aGUgbGFuZ3VhZ2UgaXMgc3BlY2lmaWVkIHdpdGggYSByZWdpb25cbiAgICAgIGlmIChvcHRpb25zLmxhbmd1YWdlLmluZGV4T2YoJy0nKSA+IDApIHtcbiAgICAgICAgLy8gRXh0cmFjdCB0aGUgcmVnaW9uIGluZm9ybWF0aW9uIGlmIGl0IGlzIGluY2x1ZGVkXG4gICAgICAgIHZhciBsYW5ndWFnZVBhcnRzID0gb3B0aW9ucy5sYW5ndWFnZS5zcGxpdCgnLScpO1xuICAgICAgICB2YXIgYmFzZUxhbmd1YWdlID0gbGFuZ3VhZ2VQYXJ0c1swXTtcblxuICAgICAgICBvcHRpb25zLmxhbmd1YWdlID0gW29wdGlvbnMubGFuZ3VhZ2UsIGJhc2VMYW5ndWFnZV07XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcHRpb25zLmxhbmd1YWdlID0gW29wdGlvbnMubGFuZ3VhZ2VdO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICgkLmlzQXJyYXkob3B0aW9ucy5sYW5ndWFnZSkpIHtcbiAgICAgIHZhciBsYW5ndWFnZXMgPSBuZXcgVHJhbnNsYXRpb24oKTtcbiAgICAgIG9wdGlvbnMubGFuZ3VhZ2UucHVzaCgnZW4nKTtcblxuICAgICAgdmFyIGxhbmd1YWdlTmFtZXMgPSBvcHRpb25zLmxhbmd1YWdlO1xuXG4gICAgICBmb3IgKHZhciBsID0gMDsgbCA8IGxhbmd1YWdlTmFtZXMubGVuZ3RoOyBsKyspIHtcbiAgICAgICAgdmFyIG5hbWUgPSBsYW5ndWFnZU5hbWVzW2xdO1xuICAgICAgICB2YXIgbGFuZ3VhZ2UgPSB7fTtcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIFRyeSB0byBsb2FkIGl0IHdpdGggdGhlIG9yaWdpbmFsIG5hbWVcbiAgICAgICAgICBsYW5ndWFnZSA9IFRyYW5zbGF0aW9uLmxvYWRQYXRoKG5hbWUpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIElmIHdlIGNvdWxkbid0IGxvYWQgaXQsIGNoZWNrIGlmIGl0IHdhc24ndCB0aGUgZnVsbCBwYXRoXG4gICAgICAgICAgICBuYW1lID0gdGhpcy5kZWZhdWx0cy5hbWRMYW5ndWFnZUJhc2UgKyBuYW1lO1xuICAgICAgICAgICAgbGFuZ3VhZ2UgPSBUcmFuc2xhdGlvbi5sb2FkUGF0aChuYW1lKTtcbiAgICAgICAgICB9IGNhdGNoIChleCkge1xuICAgICAgICAgICAgLy8gVGhlIHRyYW5zbGF0aW9uIGNvdWxkIG5vdCBiZSBsb2FkZWQgYXQgYWxsLiBTb21ldGltZXMgdGhpcyBpc1xuICAgICAgICAgICAgLy8gYmVjYXVzZSBvZiBhIGNvbmZpZ3VyYXRpb24gcHJvYmxlbSwgb3RoZXIgdGltZXMgdGhpcyBjYW4gYmVcbiAgICAgICAgICAgIC8vIGJlY2F1c2Ugb2YgaG93IFNlbGVjdDIgaGVscHMgbG9hZCBhbGwgcG9zc2libGUgdHJhbnNsYXRpb24gZmlsZXMuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWJ1ZyAmJiB3aW5kb3cuY29uc29sZSAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgICAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICAgICAgICdTZWxlY3QyOiBUaGUgbGFuZ3VhZ2UgZmlsZSBmb3IgXCInICsgbmFtZSArICdcIiBjb3VsZCBub3QgYmUgJyArXG4gICAgICAgICAgICAgICAgJ2F1dG9tYXRpY2FsbHkgbG9hZGVkLiBBIGZhbGxiYWNrIHdpbGwgYmUgdXNlZCBpbnN0ZWFkLidcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGFuZ3VhZ2VzLmV4dGVuZChsYW5ndWFnZSk7XG4gICAgICB9XG5cbiAgICAgIG9wdGlvbnMudHJhbnNsYXRpb25zID0gbGFuZ3VhZ2VzO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgYmFzZVRyYW5zbGF0aW9uID0gVHJhbnNsYXRpb24ubG9hZFBhdGgoXG4gICAgICAgIHRoaXMuZGVmYXVsdHMuYW1kTGFuZ3VhZ2VCYXNlICsgJ2VuJ1xuICAgICAgKTtcbiAgICAgIHZhciBjdXN0b21UcmFuc2xhdGlvbiA9IG5ldyBUcmFuc2xhdGlvbihvcHRpb25zLmxhbmd1YWdlKTtcblxuICAgICAgY3VzdG9tVHJhbnNsYXRpb24uZXh0ZW5kKGJhc2VUcmFuc2xhdGlvbik7XG5cbiAgICAgIG9wdGlvbnMudHJhbnNsYXRpb25zID0gY3VzdG9tVHJhbnNsYXRpb247XG4gICAgfVxuXG4gICAgcmV0dXJuIG9wdGlvbnM7XG4gIH07XG5cbiAgRGVmYXVsdHMucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIHN0cmlwRGlhY3JpdGljcyAodGV4dCkge1xuICAgICAgLy8gVXNlZCAndW5pIHJhbmdlICsgbmFtZWQgZnVuY3Rpb24nIGZyb20gaHR0cDovL2pzcGVyZi5jb20vZGlhY3JpdGljcy8xOFxuICAgICAgZnVuY3Rpb24gbWF0Y2goYSkge1xuICAgICAgICByZXR1cm4gRElBQ1JJVElDU1thXSB8fCBhO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdGV4dC5yZXBsYWNlKC9bXlxcdTAwMDAtXFx1MDA3RV0vZywgbWF0Y2gpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1hdGNoZXIgKHBhcmFtcywgZGF0YSkge1xuICAgICAgLy8gQWx3YXlzIHJldHVybiB0aGUgb2JqZWN0IGlmIHRoZXJlIGlzIG5vdGhpbmcgdG8gY29tcGFyZVxuICAgICAgaWYgKCQudHJpbShwYXJhbXMudGVybSkgPT09ICcnKSB7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgfVxuXG4gICAgICAvLyBEbyBhIHJlY3Vyc2l2ZSBjaGVjayBmb3Igb3B0aW9ucyB3aXRoIGNoaWxkcmVuXG4gICAgICBpZiAoZGF0YS5jaGlsZHJlbiAmJiBkYXRhLmNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgLy8gQ2xvbmUgdGhlIGRhdGEgb2JqZWN0IGlmIHRoZXJlIGFyZSBjaGlsZHJlblxuICAgICAgICAvLyBUaGlzIGlzIHJlcXVpcmVkIGFzIHdlIG1vZGlmeSB0aGUgb2JqZWN0IHRvIHJlbW92ZSBhbnkgbm9uLW1hdGNoZXNcbiAgICAgICAgdmFyIG1hdGNoID0gJC5leHRlbmQodHJ1ZSwge30sIGRhdGEpO1xuXG4gICAgICAgIC8vIENoZWNrIGVhY2ggY2hpbGQgb2YgdGhlIG9wdGlvblxuICAgICAgICBmb3IgKHZhciBjID0gZGF0YS5jaGlsZHJlbi5sZW5ndGggLSAxOyBjID49IDA7IGMtLSkge1xuICAgICAgICAgIHZhciBjaGlsZCA9IGRhdGEuY2hpbGRyZW5bY107XG5cbiAgICAgICAgICB2YXIgbWF0Y2hlcyA9IG1hdGNoZXIocGFyYW1zLCBjaGlsZCk7XG5cbiAgICAgICAgICAvLyBJZiB0aGVyZSB3YXNuJ3QgYSBtYXRjaCwgcmVtb3ZlIHRoZSBvYmplY3QgaW4gdGhlIGFycmF5XG4gICAgICAgICAgaWYgKG1hdGNoZXMgPT0gbnVsbCkge1xuICAgICAgICAgICAgbWF0Y2guY2hpbGRyZW4uc3BsaWNlKGMsIDEpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIGFueSBjaGlsZHJlbiBtYXRjaGVkLCByZXR1cm4gdGhlIG5ldyBvYmplY3RcbiAgICAgICAgaWYgKG1hdGNoLmNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICByZXR1cm4gbWF0Y2g7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGVyZSB3ZXJlIG5vIG1hdGNoaW5nIGNoaWxkcmVuLCBjaGVjayBqdXN0IHRoZSBwbGFpbiBvYmplY3RcbiAgICAgICAgcmV0dXJuIG1hdGNoZXIocGFyYW1zLCBtYXRjaCk7XG4gICAgICB9XG5cbiAgICAgIHZhciBvcmlnaW5hbCA9IHN0cmlwRGlhY3JpdGljcyhkYXRhLnRleHQpLnRvVXBwZXJDYXNlKCk7XG4gICAgICB2YXIgdGVybSA9IHN0cmlwRGlhY3JpdGljcyhwYXJhbXMudGVybSkudG9VcHBlckNhc2UoKTtcblxuICAgICAgLy8gQ2hlY2sgaWYgdGhlIHRleHQgY29udGFpbnMgdGhlIHRlcm1cbiAgICAgIGlmIChvcmlnaW5hbC5pbmRleE9mKHRlcm0pID4gLTEpIHtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICB9XG5cbiAgICAgIC8vIElmIGl0IGRvZXNuJ3QgY29udGFpbiB0aGUgdGVybSwgZG9uJ3QgcmV0dXJuIGFueXRoaW5nXG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICB0aGlzLmRlZmF1bHRzID0ge1xuICAgICAgYW1kQmFzZTogJy4vJyxcbiAgICAgIGFtZExhbmd1YWdlQmFzZTogJy4vaTE4bi8nLFxuICAgICAgY2xvc2VPblNlbGVjdDogdHJ1ZSxcbiAgICAgIGRlYnVnOiBmYWxzZSxcbiAgICAgIGRyb3Bkb3duQXV0b1dpZHRoOiBmYWxzZSxcbiAgICAgIGVzY2FwZU1hcmt1cDogVXRpbHMuZXNjYXBlTWFya3VwLFxuICAgICAgbGFuZ3VhZ2U6IEVuZ2xpc2hUcmFuc2xhdGlvbixcbiAgICAgIG1hdGNoZXI6IG1hdGNoZXIsXG4gICAgICBtaW5pbXVtSW5wdXRMZW5ndGg6IDAsXG4gICAgICBtYXhpbXVtSW5wdXRMZW5ndGg6IDAsXG4gICAgICBtYXhpbXVtU2VsZWN0aW9uTGVuZ3RoOiAwLFxuICAgICAgbWluaW11bVJlc3VsdHNGb3JTZWFyY2g6IDAsXG4gICAgICBzZWxlY3RPbkNsb3NlOiBmYWxzZSxcbiAgICAgIHNvcnRlcjogZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICB9LFxuICAgICAgdGVtcGxhdGVSZXN1bHQ6IGZ1bmN0aW9uIChyZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuIHJlc3VsdC50ZXh0O1xuICAgICAgfSxcbiAgICAgIHRlbXBsYXRlU2VsZWN0aW9uOiBmdW5jdGlvbiAoc2VsZWN0aW9uKSB7XG4gICAgICAgIHJldHVybiBzZWxlY3Rpb24udGV4dDtcbiAgICAgIH0sXG4gICAgICB0aGVtZTogJ2RlZmF1bHQnLFxuICAgICAgd2lkdGg6ICdyZXNvbHZlJ1xuICAgIH07XG4gIH07XG5cbiAgRGVmYXVsdHMucHJvdG90eXBlLnNldCA9IGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgdmFyIGNhbWVsS2V5ID0gJC5jYW1lbENhc2Uoa2V5KTtcblxuICAgIHZhciBkYXRhID0ge307XG4gICAgZGF0YVtjYW1lbEtleV0gPSB2YWx1ZTtcblxuICAgIHZhciBjb252ZXJ0ZWREYXRhID0gVXRpbHMuX2NvbnZlcnREYXRhKGRhdGEpO1xuXG4gICAgJC5leHRlbmQodHJ1ZSwgdGhpcy5kZWZhdWx0cywgY29udmVydGVkRGF0YSk7XG4gIH07XG5cbiAgdmFyIGRlZmF1bHRzID0gbmV3IERlZmF1bHRzKCk7XG5cbiAgcmV0dXJuIGRlZmF1bHRzO1xufSk7XG5cblMyLmRlZmluZSgnc2VsZWN0Mi9vcHRpb25zJyxbXG4gICdyZXF1aXJlJyxcbiAgJ2pxdWVyeScsXG4gICcuL2RlZmF1bHRzJyxcbiAgJy4vdXRpbHMnXG5dLCBmdW5jdGlvbiAocmVxdWlyZSwgJCwgRGVmYXVsdHMsIFV0aWxzKSB7XG4gIGZ1bmN0aW9uIE9wdGlvbnMgKG9wdGlvbnMsICRlbGVtZW50KSB7XG4gICAgdGhpcy5vcHRpb25zID0gb3B0aW9ucztcblxuICAgIGlmICgkZWxlbWVudCAhPSBudWxsKSB7XG4gICAgICB0aGlzLmZyb21FbGVtZW50KCRlbGVtZW50KTtcbiAgICB9XG5cbiAgICB0aGlzLm9wdGlvbnMgPSBEZWZhdWx0cy5hcHBseSh0aGlzLm9wdGlvbnMpO1xuXG4gICAgaWYgKCRlbGVtZW50ICYmICRlbGVtZW50LmlzKCdpbnB1dCcpKSB7XG4gICAgICB2YXIgSW5wdXRDb21wYXQgPSByZXF1aXJlKHRoaXMuZ2V0KCdhbWRCYXNlJykgKyAnY29tcGF0L2lucHV0RGF0YScpO1xuXG4gICAgICB0aGlzLm9wdGlvbnMuZGF0YUFkYXB0ZXIgPSBVdGlscy5EZWNvcmF0ZShcbiAgICAgICAgdGhpcy5vcHRpb25zLmRhdGFBZGFwdGVyLFxuICAgICAgICBJbnB1dENvbXBhdFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICBPcHRpb25zLnByb3RvdHlwZS5mcm9tRWxlbWVudCA9IGZ1bmN0aW9uICgkZSkge1xuICAgIHZhciBleGNsdWRlZERhdGEgPSBbJ3NlbGVjdDInXTtcblxuICAgIGlmICh0aGlzLm9wdGlvbnMubXVsdGlwbGUgPT0gbnVsbCkge1xuICAgICAgdGhpcy5vcHRpb25zLm11bHRpcGxlID0gJGUucHJvcCgnbXVsdGlwbGUnKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmRpc2FibGVkID09IG51bGwpIHtcbiAgICAgIHRoaXMub3B0aW9ucy5kaXNhYmxlZCA9ICRlLnByb3AoJ2Rpc2FibGVkJyk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMub3B0aW9ucy5sYW5ndWFnZSA9PSBudWxsKSB7XG4gICAgICBpZiAoJGUucHJvcCgnbGFuZycpKSB7XG4gICAgICAgIHRoaXMub3B0aW9ucy5sYW5ndWFnZSA9ICRlLnByb3AoJ2xhbmcnKS50b0xvd2VyQ2FzZSgpO1xuICAgICAgfSBlbHNlIGlmICgkZS5jbG9zZXN0KCdbbGFuZ10nKS5wcm9wKCdsYW5nJykpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zLmxhbmd1YWdlID0gJGUuY2xvc2VzdCgnW2xhbmddJykucHJvcCgnbGFuZycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLm9wdGlvbnMuZGlyID09IG51bGwpIHtcbiAgICAgIGlmICgkZS5wcm9wKCdkaXInKSkge1xuICAgICAgICB0aGlzLm9wdGlvbnMuZGlyID0gJGUucHJvcCgnZGlyJyk7XG4gICAgICB9IGVsc2UgaWYgKCRlLmNsb3Nlc3QoJ1tkaXJdJykucHJvcCgnZGlyJykpIHtcbiAgICAgICAgdGhpcy5vcHRpb25zLmRpciA9ICRlLmNsb3Nlc3QoJ1tkaXJdJykucHJvcCgnZGlyJyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm9wdGlvbnMuZGlyID0gJ2x0cic7XG4gICAgICB9XG4gICAgfVxuXG4gICAgJGUucHJvcCgnZGlzYWJsZWQnLCB0aGlzLm9wdGlvbnMuZGlzYWJsZWQpO1xuICAgICRlLnByb3AoJ211bHRpcGxlJywgdGhpcy5vcHRpb25zLm11bHRpcGxlKTtcblxuICAgIGlmIChVdGlscy5HZXREYXRhKCRlWzBdLCAnc2VsZWN0MlRhZ3MnKSkge1xuICAgICAgaWYgKHRoaXMub3B0aW9ucy5kZWJ1ZyAmJiB3aW5kb3cuY29uc29sZSAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICAgICdTZWxlY3QyOiBUaGUgYGRhdGEtc2VsZWN0Mi10YWdzYCBhdHRyaWJ1dGUgaGFzIGJlZW4gY2hhbmdlZCB0byAnICtcbiAgICAgICAgICAndXNlIHRoZSBgZGF0YS1kYXRhYCBhbmQgYGRhdGEtdGFncz1cInRydWVcImAgYXR0cmlidXRlcyBhbmQgd2lsbCBiZSAnICtcbiAgICAgICAgICAncmVtb3ZlZCBpbiBmdXR1cmUgdmVyc2lvbnMgb2YgU2VsZWN0Mi4nXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIFV0aWxzLlN0b3JlRGF0YSgkZVswXSwgJ2RhdGEnLCBVdGlscy5HZXREYXRhKCRlWzBdLCAnc2VsZWN0MlRhZ3MnKSk7XG4gICAgICBVdGlscy5TdG9yZURhdGEoJGVbMF0sICd0YWdzJywgdHJ1ZSk7XG4gICAgfVxuXG4gICAgaWYgKFV0aWxzLkdldERhdGEoJGVbMF0sICdhamF4VXJsJykpIHtcbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuZGVidWcgJiYgd2luZG93LmNvbnNvbGUgJiYgY29uc29sZS53YXJuKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAnU2VsZWN0MjogVGhlIGBkYXRhLWFqYXgtdXJsYCBhdHRyaWJ1dGUgaGFzIGJlZW4gY2hhbmdlZCB0byAnICtcbiAgICAgICAgICAnYGRhdGEtYWpheC0tdXJsYCBhbmQgc3VwcG9ydCBmb3IgdGhlIG9sZCBhdHRyaWJ1dGUgd2lsbCBiZSByZW1vdmVkJyArXG4gICAgICAgICAgJyBpbiBmdXR1cmUgdmVyc2lvbnMgb2YgU2VsZWN0Mi4nXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgICRlLmF0dHIoJ2FqYXgtLXVybCcsIFV0aWxzLkdldERhdGEoJGVbMF0sICdhamF4VXJsJykpO1xuICAgICAgVXRpbHMuU3RvcmVEYXRhKCRlWzBdLCAnYWpheC1VcmwnLCBVdGlscy5HZXREYXRhKCRlWzBdLCAnYWpheFVybCcpKTtcblx0ICBcbiAgICB9XG5cbiAgICB2YXIgZGF0YXNldCA9IHt9O1xuXG4gICAgLy8gUHJlZmVyIHRoZSBlbGVtZW50J3MgYGRhdGFzZXRgIGF0dHJpYnV0ZSBpZiBpdCBleGlzdHNcbiAgICAvLyBqUXVlcnkgMS54IGRvZXMgbm90IGNvcnJlY3RseSBoYW5kbGUgZGF0YSBhdHRyaWJ1dGVzIHdpdGggbXVsdGlwbGUgZGFzaGVzXG4gICAgaWYgKCQuZm4uanF1ZXJ5ICYmICQuZm4uanF1ZXJ5LnN1YnN0cigwLCAyKSA9PSAnMS4nICYmICRlWzBdLmRhdGFzZXQpIHtcbiAgICAgIGRhdGFzZXQgPSAkLmV4dGVuZCh0cnVlLCB7fSwgJGVbMF0uZGF0YXNldCwgVXRpbHMuR2V0RGF0YSgkZVswXSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkYXRhc2V0ID0gVXRpbHMuR2V0RGF0YSgkZVswXSk7XG4gICAgfVxuXG4gICAgdmFyIGRhdGEgPSAkLmV4dGVuZCh0cnVlLCB7fSwgZGF0YXNldCk7XG5cbiAgICBkYXRhID0gVXRpbHMuX2NvbnZlcnREYXRhKGRhdGEpO1xuXG4gICAgZm9yICh2YXIga2V5IGluIGRhdGEpIHtcbiAgICAgIGlmICgkLmluQXJyYXkoa2V5LCBleGNsdWRlZERhdGEpID4gLTEpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmICgkLmlzUGxhaW5PYmplY3QodGhpcy5vcHRpb25zW2tleV0pKSB7XG4gICAgICAgICQuZXh0ZW5kKHRoaXMub3B0aW9uc1trZXldLCBkYXRhW2tleV0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5vcHRpb25zW2tleV0gPSBkYXRhW2tleV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXM7XG4gIH07XG5cbiAgT3B0aW9ucy5wcm90b3R5cGUuZ2V0ID0gZnVuY3Rpb24gKGtleSkge1xuICAgIHJldHVybiB0aGlzLm9wdGlvbnNba2V5XTtcbiAgfTtcblxuICBPcHRpb25zLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbiAoa2V5LCB2YWwpIHtcbiAgICB0aGlzLm9wdGlvbnNba2V5XSA9IHZhbDtcbiAgfTtcblxuICByZXR1cm4gT3B0aW9ucztcbn0pO1xuXG5TMi5kZWZpbmUoJ3NlbGVjdDIvY29yZScsW1xuICAnanF1ZXJ5JyxcbiAgJy4vb3B0aW9ucycsXG4gICcuL3V0aWxzJyxcbiAgJy4va2V5cydcbl0sIGZ1bmN0aW9uICgkLCBPcHRpb25zLCBVdGlscywgS0VZUykge1xuICB2YXIgU2VsZWN0MiA9IGZ1bmN0aW9uICgkZWxlbWVudCwgb3B0aW9ucykge1xuICAgIGlmIChVdGlscy5HZXREYXRhKCRlbGVtZW50WzBdLCAnc2VsZWN0MicpICE9IG51bGwpIHtcbiAgICAgIFV0aWxzLkdldERhdGEoJGVsZW1lbnRbMF0sICdzZWxlY3QyJykuZGVzdHJveSgpO1xuICAgIH1cblxuICAgIHRoaXMuJGVsZW1lbnQgPSAkZWxlbWVudDtcblxuICAgIHRoaXMuaWQgPSB0aGlzLl9nZW5lcmF0ZUlkKCRlbGVtZW50KTtcblxuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gICAgdGhpcy5vcHRpb25zID0gbmV3IE9wdGlvbnMob3B0aW9ucywgJGVsZW1lbnQpO1xuXG4gICAgU2VsZWN0Mi5fX3N1cGVyX18uY29uc3RydWN0b3IuY2FsbCh0aGlzKTtcblxuICAgIC8vIFNldCB1cCB0aGUgdGFiaW5kZXhcblxuICAgIHZhciB0YWJpbmRleCA9ICRlbGVtZW50LmF0dHIoJ3RhYmluZGV4JykgfHwgMDtcbiAgICBVdGlscy5TdG9yZURhdGEoJGVsZW1lbnRbMF0sICdvbGQtdGFiaW5kZXgnLCB0YWJpbmRleCk7XG4gICAgJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnLCAnLTEnKTtcblxuICAgIC8vIFNldCB1cCBjb250YWluZXJzIGFuZCBhZGFwdGVyc1xuXG4gICAgdmFyIERhdGFBZGFwdGVyID0gdGhpcy5vcHRpb25zLmdldCgnZGF0YUFkYXB0ZXInKTtcbiAgICB0aGlzLmRhdGFBZGFwdGVyID0gbmV3IERhdGFBZGFwdGVyKCRlbGVtZW50LCB0aGlzLm9wdGlvbnMpO1xuXG4gICAgdmFyICRjb250YWluZXIgPSB0aGlzLnJlbmRlcigpO1xuXG4gICAgdGhpcy5fcGxhY2VDb250YWluZXIoJGNvbnRhaW5lcik7XG5cbiAgICB2YXIgU2VsZWN0aW9uQWRhcHRlciA9IHRoaXMub3B0aW9ucy5nZXQoJ3NlbGVjdGlvbkFkYXB0ZXInKTtcbiAgICB0aGlzLnNlbGVjdGlvbiA9IG5ldyBTZWxlY3Rpb25BZGFwdGVyKCRlbGVtZW50LCB0aGlzLm9wdGlvbnMpO1xuICAgIHRoaXMuJHNlbGVjdGlvbiA9IHRoaXMuc2VsZWN0aW9uLnJlbmRlcigpO1xuXG4gICAgdGhpcy5zZWxlY3Rpb24ucG9zaXRpb24odGhpcy4kc2VsZWN0aW9uLCAkY29udGFpbmVyKTtcblxuICAgIHZhciBEcm9wZG93bkFkYXB0ZXIgPSB0aGlzLm9wdGlvbnMuZ2V0KCdkcm9wZG93bkFkYXB0ZXInKTtcbiAgICB0aGlzLmRyb3Bkb3duID0gbmV3IERyb3Bkb3duQWRhcHRlcigkZWxlbWVudCwgdGhpcy5vcHRpb25zKTtcbiAgICB0aGlzLiRkcm9wZG93biA9IHRoaXMuZHJvcGRvd24ucmVuZGVyKCk7XG5cbiAgICB0aGlzLmRyb3Bkb3duLnBvc2l0aW9uKHRoaXMuJGRyb3Bkb3duLCAkY29udGFpbmVyKTtcblxuICAgIHZhciBSZXN1bHRzQWRhcHRlciA9IHRoaXMub3B0aW9ucy5nZXQoJ3Jlc3VsdHNBZGFwdGVyJyk7XG4gICAgdGhpcy5yZXN1bHRzID0gbmV3IFJlc3VsdHNBZGFwdGVyKCRlbGVtZW50LCB0aGlzLm9wdGlvbnMsIHRoaXMuZGF0YUFkYXB0ZXIpO1xuICAgIHRoaXMuJHJlc3VsdHMgPSB0aGlzLnJlc3VsdHMucmVuZGVyKCk7XG5cbiAgICB0aGlzLnJlc3VsdHMucG9zaXRpb24odGhpcy4kcmVzdWx0cywgdGhpcy4kZHJvcGRvd24pO1xuXG4gICAgLy8gQmluZCBldmVudHNcblxuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIC8vIEJpbmQgdGhlIGNvbnRhaW5lciB0byBhbGwgb2YgdGhlIGFkYXB0ZXJzXG4gICAgdGhpcy5fYmluZEFkYXB0ZXJzKCk7XG5cbiAgICAvLyBSZWdpc3RlciBhbnkgRE9NIGV2ZW50IGhhbmRsZXJzXG4gICAgdGhpcy5fcmVnaXN0ZXJEb21FdmVudHMoKTtcblxuICAgIC8vIFJlZ2lzdGVyIGFueSBpbnRlcm5hbCBldmVudCBoYW5kbGVyc1xuICAgIHRoaXMuX3JlZ2lzdGVyRGF0YUV2ZW50cygpO1xuICAgIHRoaXMuX3JlZ2lzdGVyU2VsZWN0aW9uRXZlbnRzKCk7XG4gICAgdGhpcy5fcmVnaXN0ZXJEcm9wZG93bkV2ZW50cygpO1xuICAgIHRoaXMuX3JlZ2lzdGVyUmVzdWx0c0V2ZW50cygpO1xuICAgIHRoaXMuX3JlZ2lzdGVyRXZlbnRzKCk7XG5cbiAgICAvLyBTZXQgdGhlIGluaXRpYWwgc3RhdGVcbiAgICB0aGlzLmRhdGFBZGFwdGVyLmN1cnJlbnQoZnVuY3Rpb24gKGluaXRpYWxEYXRhKSB7XG4gICAgICBzZWxmLnRyaWdnZXIoJ3NlbGVjdGlvbjp1cGRhdGUnLCB7XG4gICAgICAgIGRhdGE6IGluaXRpYWxEYXRhXG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIEhpZGUgdGhlIG9yaWdpbmFsIHNlbGVjdFxuICAgICRlbGVtZW50LmFkZENsYXNzKCdzZWxlY3QyLWhpZGRlbi1hY2Nlc3NpYmxlJyk7XG4gICAgJGVsZW1lbnQuYXR0cignYXJpYS1oaWRkZW4nLCAndHJ1ZScpO1xuXG4gICAgLy8gU3luY2hyb25pemUgYW55IG1vbml0b3JlZCBhdHRyaWJ1dGVzXG4gICAgdGhpcy5fc3luY0F0dHJpYnV0ZXMoKTtcblxuICAgIFV0aWxzLlN0b3JlRGF0YSgkZWxlbWVudFswXSwgJ3NlbGVjdDInLCB0aGlzKTtcblxuICAgIC8vIEVuc3VyZSBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eSB3aXRoICRlbGVtZW50LmRhdGEoJ3NlbGVjdDInKS5cbiAgICAkZWxlbWVudC5kYXRhKCdzZWxlY3QyJywgdGhpcyk7XG4gIH07XG5cbiAgVXRpbHMuRXh0ZW5kKFNlbGVjdDIsIFV0aWxzLk9ic2VydmFibGUpO1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLl9nZW5lcmF0ZUlkID0gZnVuY3Rpb24gKCRlbGVtZW50KSB7XG4gICAgdmFyIGlkID0gJyc7XG5cbiAgICBpZiAoJGVsZW1lbnQuYXR0cignaWQnKSAhPSBudWxsKSB7XG4gICAgICBpZCA9ICRlbGVtZW50LmF0dHIoJ2lkJyk7XG4gICAgfSBlbHNlIGlmICgkZWxlbWVudC5hdHRyKCduYW1lJykgIT0gbnVsbCkge1xuICAgICAgaWQgPSAkZWxlbWVudC5hdHRyKCduYW1lJykgKyAnLScgKyBVdGlscy5nZW5lcmF0ZUNoYXJzKDIpO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZCA9IFV0aWxzLmdlbmVyYXRlQ2hhcnMoNCk7XG4gICAgfVxuXG4gICAgaWQgPSBpZC5yZXBsYWNlKC8oOnxcXC58XFxbfFxcXXwsKS9nLCAnJyk7XG4gICAgaWQgPSAnc2VsZWN0Mi0nICsgaWQ7XG5cbiAgICByZXR1cm4gaWQ7XG4gIH07XG5cbiAgU2VsZWN0Mi5wcm90b3R5cGUuX3BsYWNlQ29udGFpbmVyID0gZnVuY3Rpb24gKCRjb250YWluZXIpIHtcbiAgICAkY29udGFpbmVyLmluc2VydEFmdGVyKHRoaXMuJGVsZW1lbnQpO1xuXG4gICAgdmFyIHdpZHRoID0gdGhpcy5fcmVzb2x2ZVdpZHRoKHRoaXMuJGVsZW1lbnQsIHRoaXMub3B0aW9ucy5nZXQoJ3dpZHRoJykpO1xuXG4gICAgaWYgKHdpZHRoICE9IG51bGwpIHtcbiAgICAgICRjb250YWluZXIuY3NzKCd3aWR0aCcsIHdpZHRoKTtcbiAgICB9XG4gIH07XG5cbiAgU2VsZWN0Mi5wcm90b3R5cGUuX3Jlc29sdmVXaWR0aCA9IGZ1bmN0aW9uICgkZWxlbWVudCwgbWV0aG9kKSB7XG4gICAgdmFyIFdJRFRIID0gL153aWR0aDooKFstK10/KFswLTldKlxcLik/WzAtOV0rKShweHxlbXxleHwlfGlufGNtfG1tfHB0fHBjKSkvaTtcblxuICAgIGlmIChtZXRob2QgPT0gJ3Jlc29sdmUnKSB7XG4gICAgICB2YXIgc3R5bGVXaWR0aCA9IHRoaXMuX3Jlc29sdmVXaWR0aCgkZWxlbWVudCwgJ3N0eWxlJyk7XG5cbiAgICAgIGlmIChzdHlsZVdpZHRoICE9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHN0eWxlV2lkdGg7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLl9yZXNvbHZlV2lkdGgoJGVsZW1lbnQsICdlbGVtZW50Jyk7XG4gICAgfVxuXG4gICAgaWYgKG1ldGhvZCA9PSAnZWxlbWVudCcpIHtcbiAgICAgIHZhciBlbGVtZW50V2lkdGggPSAkZWxlbWVudC5vdXRlcldpZHRoKGZhbHNlKTtcblxuICAgICAgaWYgKGVsZW1lbnRXaWR0aCA8PSAwKSB7XG4gICAgICAgIHJldHVybiAnYXV0byc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBlbGVtZW50V2lkdGggKyAncHgnO1xuICAgIH1cblxuICAgIGlmIChtZXRob2QgPT0gJ3N0eWxlJykge1xuICAgICAgdmFyIHN0eWxlID0gJGVsZW1lbnQuYXR0cignc3R5bGUnKTtcblxuICAgICAgaWYgKHR5cGVvZihzdHlsZSkgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuXG4gICAgICB2YXIgYXR0cnMgPSBzdHlsZS5zcGxpdCgnOycpO1xuXG4gICAgICBmb3IgKHZhciBpID0gMCwgbCA9IGF0dHJzLmxlbmd0aDsgaSA8IGw7IGkgPSBpICsgMSkge1xuICAgICAgICB2YXIgYXR0ciA9IGF0dHJzW2ldLnJlcGxhY2UoL1xccy9nLCAnJyk7XG4gICAgICAgIHZhciBtYXRjaGVzID0gYXR0ci5tYXRjaChXSURUSCk7XG5cbiAgICAgICAgaWYgKG1hdGNoZXMgIT09IG51bGwgJiYgbWF0Y2hlcy5sZW5ndGggPj0gMSkge1xuICAgICAgICAgIHJldHVybiBtYXRjaGVzWzFdO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBtZXRob2Q7XG4gIH07XG5cbiAgU2VsZWN0Mi5wcm90b3R5cGUuX2JpbmRBZGFwdGVycyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLmRhdGFBZGFwdGVyLmJpbmQodGhpcywgdGhpcy4kY29udGFpbmVyKTtcbiAgICB0aGlzLnNlbGVjdGlvbi5iaW5kKHRoaXMsIHRoaXMuJGNvbnRhaW5lcik7XG5cbiAgICB0aGlzLmRyb3Bkb3duLmJpbmQodGhpcywgdGhpcy4kY29udGFpbmVyKTtcbiAgICB0aGlzLnJlc3VsdHMuYmluZCh0aGlzLCB0aGlzLiRjb250YWluZXIpO1xuICB9O1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLl9yZWdpc3RlckRvbUV2ZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB0aGlzLiRlbGVtZW50Lm9uKCdjaGFuZ2Uuc2VsZWN0MicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYuZGF0YUFkYXB0ZXIuY3VycmVudChmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBzZWxmLnRyaWdnZXIoJ3NlbGVjdGlvbjp1cGRhdGUnLCB7XG4gICAgICAgICAgZGF0YTogZGF0YVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGhpcy4kZWxlbWVudC5vbignZm9jdXMuc2VsZWN0MicsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIHNlbGYudHJpZ2dlcignZm9jdXMnLCBldnQpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5fc3luY0EgPSBVdGlscy5iaW5kKHRoaXMuX3N5bmNBdHRyaWJ1dGVzLCB0aGlzKTtcbiAgICB0aGlzLl9zeW5jUyA9IFV0aWxzLmJpbmQodGhpcy5fc3luY1N1YnRyZWUsIHRoaXMpO1xuXG4gICAgaWYgKHRoaXMuJGVsZW1lbnRbMF0uYXR0YWNoRXZlbnQpIHtcbiAgICAgIHRoaXMuJGVsZW1lbnRbMF0uYXR0YWNoRXZlbnQoJ29ucHJvcGVydHljaGFuZ2UnLCB0aGlzLl9zeW5jQSk7XG4gICAgfVxuXG4gICAgdmFyIG9ic2VydmVyID0gd2luZG93Lk11dGF0aW9uT2JzZXJ2ZXIgfHxcbiAgICAgIHdpbmRvdy5XZWJLaXRNdXRhdGlvbk9ic2VydmVyIHx8XG4gICAgICB3aW5kb3cuTW96TXV0YXRpb25PYnNlcnZlclxuICAgIDtcblxuICAgIGlmIChvYnNlcnZlciAhPSBudWxsKSB7XG4gICAgICB0aGlzLl9vYnNlcnZlciA9IG5ldyBvYnNlcnZlcihmdW5jdGlvbiAobXV0YXRpb25zKSB7XG4gICAgICAgICQuZWFjaChtdXRhdGlvbnMsIHNlbGYuX3N5bmNBKTtcbiAgICAgICAgJC5lYWNoKG11dGF0aW9ucywgc2VsZi5fc3luY1MpO1xuICAgICAgfSk7XG4gICAgICB0aGlzLl9vYnNlcnZlci5vYnNlcnZlKHRoaXMuJGVsZW1lbnRbMF0sIHtcbiAgICAgICAgYXR0cmlidXRlczogdHJ1ZSxcbiAgICAgICAgY2hpbGRMaXN0OiB0cnVlLFxuICAgICAgICBzdWJ0cmVlOiBmYWxzZVxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmICh0aGlzLiRlbGVtZW50WzBdLmFkZEV2ZW50TGlzdGVuZXIpIHtcbiAgICAgIHRoaXMuJGVsZW1lbnRbMF0uYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgJ0RPTUF0dHJNb2RpZmllZCcsXG4gICAgICAgIHNlbGYuX3N5bmNBLFxuICAgICAgICBmYWxzZVxuICAgICAgKTtcbiAgICAgIHRoaXMuJGVsZW1lbnRbMF0uYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgJ0RPTU5vZGVJbnNlcnRlZCcsXG4gICAgICAgIHNlbGYuX3N5bmNTLFxuICAgICAgICBmYWxzZVxuICAgICAgKTtcbiAgICAgIHRoaXMuJGVsZW1lbnRbMF0uYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgICAgJ0RPTU5vZGVSZW1vdmVkJyxcbiAgICAgICAgc2VsZi5fc3luY1MsXG4gICAgICAgIGZhbHNlXG4gICAgICApO1xuICAgIH1cbiAgfTtcblxuICBTZWxlY3QyLnByb3RvdHlwZS5fcmVnaXN0ZXJEYXRhRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIHRoaXMuZGF0YUFkYXB0ZXIub24oJyonLCBmdW5jdGlvbiAobmFtZSwgcGFyYW1zKSB7XG4gICAgICBzZWxmLnRyaWdnZXIobmFtZSwgcGFyYW1zKTtcbiAgICB9KTtcbiAgfTtcblxuICBTZWxlY3QyLnByb3RvdHlwZS5fcmVnaXN0ZXJTZWxlY3Rpb25FdmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuICAgIHZhciBub25SZWxheUV2ZW50cyA9IFsndG9nZ2xlJywgJ2ZvY3VzJ107XG5cbiAgICB0aGlzLnNlbGVjdGlvbi5vbigndG9nZ2xlJywgZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi50b2dnbGVEcm9wZG93bigpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5zZWxlY3Rpb24ub24oJ2ZvY3VzJywgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgc2VsZi5mb2N1cyhwYXJhbXMpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5zZWxlY3Rpb24ub24oJyonLCBmdW5jdGlvbiAobmFtZSwgcGFyYW1zKSB7XG4gICAgICBpZiAoJC5pbkFycmF5KG5hbWUsIG5vblJlbGF5RXZlbnRzKSAhPT0gLTEpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBzZWxmLnRyaWdnZXIobmFtZSwgcGFyYW1zKTtcbiAgICB9KTtcbiAgfTtcblxuICBTZWxlY3QyLnByb3RvdHlwZS5fcmVnaXN0ZXJEcm9wZG93bkV2ZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB0aGlzLmRyb3Bkb3duLm9uKCcqJywgZnVuY3Rpb24gKG5hbWUsIHBhcmFtcykge1xuICAgICAgc2VsZi50cmlnZ2VyKG5hbWUsIHBhcmFtcyk7XG4gICAgfSk7XG4gIH07XG5cbiAgU2VsZWN0Mi5wcm90b3R5cGUuX3JlZ2lzdGVyUmVzdWx0c0V2ZW50cyA9IGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc2VsZiA9IHRoaXM7XG5cbiAgICB0aGlzLnJlc3VsdHMub24oJyonLCBmdW5jdGlvbiAobmFtZSwgcGFyYW1zKSB7XG4gICAgICBzZWxmLnRyaWdnZXIobmFtZSwgcGFyYW1zKTtcbiAgICB9KTtcbiAgfTtcblxuICBTZWxlY3QyLnByb3RvdHlwZS5fcmVnaXN0ZXJFdmVudHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzO1xuXG4gICAgdGhpcy5vbignb3BlbicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYuJGNvbnRhaW5lci5hZGRDbGFzcygnc2VsZWN0Mi1jb250YWluZXItLW9wZW4nKTtcbiAgICB9KTtcblxuICAgIHRoaXMub24oJ2Nsb3NlJywgZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdzZWxlY3QyLWNvbnRhaW5lci0tb3BlbicpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5vbignZW5hYmxlJywgZnVuY3Rpb24gKCkge1xuICAgICAgc2VsZi4kY29udGFpbmVyLnJlbW92ZUNsYXNzKCdzZWxlY3QyLWNvbnRhaW5lci0tZGlzYWJsZWQnKTtcbiAgICB9KTtcblxuICAgIHRoaXMub24oJ2Rpc2FibGUnLCBmdW5jdGlvbiAoKSB7XG4gICAgICBzZWxmLiRjb250YWluZXIuYWRkQ2xhc3MoJ3NlbGVjdDItY29udGFpbmVyLS1kaXNhYmxlZCcpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5vbignYmx1cicsIGZ1bmN0aW9uICgpIHtcbiAgICAgIHNlbGYuJGNvbnRhaW5lci5yZW1vdmVDbGFzcygnc2VsZWN0Mi1jb250YWluZXItLWZvY3VzJyk7XG4gICAgfSk7XG5cbiAgICB0aGlzLm9uKCdxdWVyeScsIGZ1bmN0aW9uIChwYXJhbXMpIHtcbiAgICAgIGlmICghc2VsZi5pc09wZW4oKSkge1xuICAgICAgICBzZWxmLnRyaWdnZXIoJ29wZW4nLCB7fSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuZGF0YUFkYXB0ZXIucXVlcnkocGFyYW1zLCBmdW5jdGlvbiAoZGF0YSkge1xuICAgICAgICBzZWxmLnRyaWdnZXIoJ3Jlc3VsdHM6YWxsJywge1xuICAgICAgICAgIGRhdGE6IGRhdGEsXG4gICAgICAgICAgcXVlcnk6IHBhcmFtc1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgdGhpcy5vbigncXVlcnk6YXBwZW5kJywgZnVuY3Rpb24gKHBhcmFtcykge1xuICAgICAgdGhpcy5kYXRhQWRhcHRlci5xdWVyeShwYXJhbXMsIGZ1bmN0aW9uIChkYXRhKSB7XG4gICAgICAgIHNlbGYudHJpZ2dlcigncmVzdWx0czphcHBlbmQnLCB7XG4gICAgICAgICAgZGF0YTogZGF0YSxcbiAgICAgICAgICBxdWVyeTogcGFyYW1zXG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICB0aGlzLm9uKCdrZXlwcmVzcycsIGZ1bmN0aW9uIChldnQpIHtcbiAgICAgIHZhciBrZXkgPSBldnQud2hpY2g7XG5cbiAgICAgIGlmIChzZWxmLmlzT3BlbigpKSB7XG4gICAgICAgIGlmIChrZXkgPT09IEtFWVMuRVNDIHx8IGtleSA9PT0gS0VZUy5UQUIgfHxcbiAgICAgICAgICAgIChrZXkgPT09IEtFWVMuVVAgJiYgZXZ0LmFsdEtleSkpIHtcbiAgICAgICAgICBzZWxmLmNsb3NlKCk7XG5cbiAgICAgICAgICBldnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09IEtFWVMuRU5URVIpIHtcbiAgICAgICAgICBzZWxmLnRyaWdnZXIoJ3Jlc3VsdHM6c2VsZWN0Jywge30pO1xuXG4gICAgICAgICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0gZWxzZSBpZiAoKGtleSA9PT0gS0VZUy5TUEFDRSAmJiBldnQuY3RybEtleSkpIHtcbiAgICAgICAgICBzZWxmLnRyaWdnZXIoJ3Jlc3VsdHM6dG9nZ2xlJywge30pO1xuXG4gICAgICAgICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0gZWxzZSBpZiAoa2V5ID09PSBLRVlTLlVQKSB7XG4gICAgICAgICAgc2VsZi50cmlnZ2VyKCdyZXN1bHRzOnByZXZpb3VzJywge30pO1xuXG4gICAgICAgICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIH0gZWxzZSBpZiAoa2V5ID09PSBLRVlTLkRPV04pIHtcbiAgICAgICAgICBzZWxmLnRyaWdnZXIoJ3Jlc3VsdHM6bmV4dCcsIHt9KTtcblxuICAgICAgICAgIGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoa2V5ID09PSBLRVlTLkVOVEVSIHx8IGtleSA9PT0gS0VZUy5TUEFDRSB8fFxuICAgICAgICAgICAgKGtleSA9PT0gS0VZUy5ET1dOICYmIGV2dC5hbHRLZXkpKSB7XG4gICAgICAgICAgc2VsZi5vcGVuKCk7XG5cbiAgICAgICAgICBldnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLl9zeW5jQXR0cmlidXRlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICB0aGlzLm9wdGlvbnMuc2V0KCdkaXNhYmxlZCcsIHRoaXMuJGVsZW1lbnQucHJvcCgnZGlzYWJsZWQnKSk7XG5cbiAgICBpZiAodGhpcy5vcHRpb25zLmdldCgnZGlzYWJsZWQnKSkge1xuICAgICAgaWYgKHRoaXMuaXNPcGVuKCkpIHtcbiAgICAgICAgdGhpcy5jbG9zZSgpO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnRyaWdnZXIoJ2Rpc2FibGUnLCB7fSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMudHJpZ2dlcignZW5hYmxlJywge30pO1xuICAgIH1cbiAgfTtcblxuICBTZWxlY3QyLnByb3RvdHlwZS5fc3luY1N1YnRyZWUgPSBmdW5jdGlvbiAoZXZ0LCBtdXRhdGlvbnMpIHtcbiAgICB2YXIgY2hhbmdlZCA9IGZhbHNlO1xuICAgIHZhciBzZWxmID0gdGhpcztcblxuICAgIC8vIElnbm9yZSBhbnkgbXV0YXRpb24gZXZlbnRzIHJhaXNlZCBmb3IgZWxlbWVudHMgdGhhdCBhcmVuJ3Qgb3B0aW9ucyBvclxuICAgIC8vIG9wdGdyb3Vwcy4gVGhpcyBoYW5kbGVzIHRoZSBjYXNlIHdoZW4gdGhlIHNlbGVjdCBlbGVtZW50IGlzIGRlc3Ryb3llZFxuICAgIGlmIChcbiAgICAgIGV2dCAmJiBldnQudGFyZ2V0ICYmIChcbiAgICAgICAgZXZ0LnRhcmdldC5ub2RlTmFtZSAhPT0gJ09QVElPTicgJiYgZXZ0LnRhcmdldC5ub2RlTmFtZSAhPT0gJ09QVEdST1VQJ1xuICAgICAgKVxuICAgICkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghbXV0YXRpb25zKSB7XG4gICAgICAvLyBJZiBtdXRhdGlvbiBldmVudHMgYXJlbid0IHN1cHBvcnRlZCwgdGhlbiB3ZSBjYW4gb25seSBhc3N1bWUgdGhhdCB0aGVcbiAgICAgIC8vIGNoYW5nZSBhZmZlY3RlZCB0aGUgc2VsZWN0aW9uc1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgfSBlbHNlIGlmIChtdXRhdGlvbnMuYWRkZWROb2RlcyAmJiBtdXRhdGlvbnMuYWRkZWROb2Rlcy5sZW5ndGggPiAwKSB7XG4gICAgICBmb3IgKHZhciBuID0gMDsgbiA8IG11dGF0aW9ucy5hZGRlZE5vZGVzLmxlbmd0aDsgbisrKSB7XG4gICAgICAgIHZhciBub2RlID0gbXV0YXRpb25zLmFkZGVkTm9kZXNbbl07XG5cbiAgICAgICAgaWYgKG5vZGUuc2VsZWN0ZWQpIHtcbiAgICAgICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAobXV0YXRpb25zLnJlbW92ZWROb2RlcyAmJiBtdXRhdGlvbnMucmVtb3ZlZE5vZGVzLmxlbmd0aCA+IDApIHtcbiAgICAgIGNoYW5nZWQgPSB0cnVlO1xuICAgIH1cblxuICAgIC8vIE9ubHkgcmUtcHVsbCB0aGUgZGF0YSBpZiB3ZSB0aGluayB0aGVyZSBpcyBhIGNoYW5nZVxuICAgIGlmIChjaGFuZ2VkKSB7XG4gICAgICB0aGlzLmRhdGFBZGFwdGVyLmN1cnJlbnQoZnVuY3Rpb24gKGN1cnJlbnREYXRhKSB7XG4gICAgICAgIHNlbGYudHJpZ2dlcignc2VsZWN0aW9uOnVwZGF0ZScsIHtcbiAgICAgICAgICBkYXRhOiBjdXJyZW50RGF0YVxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogT3ZlcnJpZGUgdGhlIHRyaWdnZXIgbWV0aG9kIHRvIGF1dG9tYXRpY2FsbHkgdHJpZ2dlciBwcmUtZXZlbnRzIHdoZW5cbiAgICogdGhlcmUgYXJlIGV2ZW50cyB0aGF0IGNhbiBiZSBwcmV2ZW50ZWQuXG4gICAqL1xuICBTZWxlY3QyLnByb3RvdHlwZS50cmlnZ2VyID0gZnVuY3Rpb24gKG5hbWUsIGFyZ3MpIHtcbiAgICB2YXIgYWN0dWFsVHJpZ2dlciA9IFNlbGVjdDIuX19zdXBlcl9fLnRyaWdnZXI7XG4gICAgdmFyIHByZVRyaWdnZXJNYXAgPSB7XG4gICAgICAnb3Blbic6ICdvcGVuaW5nJyxcbiAgICAgICdjbG9zZSc6ICdjbG9zaW5nJyxcbiAgICAgICdzZWxlY3QnOiAnc2VsZWN0aW5nJyxcbiAgICAgICd1bnNlbGVjdCc6ICd1bnNlbGVjdGluZycsXG4gICAgICAnY2xlYXInOiAnY2xlYXJpbmcnXG4gICAgfTtcblxuICAgIGlmIChhcmdzID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGFyZ3MgPSB7fTtcbiAgICB9XG5cbiAgICBpZiAobmFtZSBpbiBwcmVUcmlnZ2VyTWFwKSB7XG4gICAgICB2YXIgcHJlVHJpZ2dlck5hbWUgPSBwcmVUcmlnZ2VyTWFwW25hbWVdO1xuICAgICAgdmFyIHByZVRyaWdnZXJBcmdzID0ge1xuICAgICAgICBwcmV2ZW50ZWQ6IGZhbHNlLFxuICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICBhcmdzOiBhcmdzXG4gICAgICB9O1xuXG4gICAgICBhY3R1YWxUcmlnZ2VyLmNhbGwodGhpcywgcHJlVHJpZ2dlck5hbWUsIHByZVRyaWdnZXJBcmdzKTtcblxuICAgICAgaWYgKHByZVRyaWdnZXJBcmdzLnByZXZlbnRlZCkge1xuICAgICAgICBhcmdzLnByZXZlbnRlZCA9IHRydWU7XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cblxuICAgIGFjdHVhbFRyaWdnZXIuY2FsbCh0aGlzLCBuYW1lLCBhcmdzKTtcbiAgfTtcblxuICBTZWxlY3QyLnByb3RvdHlwZS50b2dnbGVEcm9wZG93biA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5vcHRpb25zLmdldCgnZGlzYWJsZWQnKSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmlzT3BlbigpKSB7XG4gICAgICB0aGlzLmNsb3NlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMub3BlbigpO1xuICAgIH1cbiAgfTtcblxuICBTZWxlY3QyLnByb3RvdHlwZS5vcGVuID0gZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLmlzT3BlbigpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy50cmlnZ2VyKCdxdWVyeScsIHt9KTtcbiAgfTtcblxuICBTZWxlY3QyLnByb3RvdHlwZS5jbG9zZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoIXRoaXMuaXNPcGVuKCkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnRyaWdnZXIoJ2Nsb3NlJywge30pO1xuICB9O1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLmlzT3BlbiA9IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy4kY29udGFpbmVyLmhhc0NsYXNzKCdzZWxlY3QyLWNvbnRhaW5lci0tb3BlbicpO1xuICB9O1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLmhhc0ZvY3VzID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLiRjb250YWluZXIuaGFzQ2xhc3MoJ3NlbGVjdDItY29udGFpbmVyLS1mb2N1cycpO1xuICB9O1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLmZvY3VzID0gZnVuY3Rpb24gKGRhdGEpIHtcbiAgICAvLyBObyBuZWVkIHRvIHJlLXRyaWdnZXIgZm9jdXMgZXZlbnRzIGlmIHdlIGFyZSBhbHJlYWR5IGZvY3VzZWRcbiAgICBpZiAodGhpcy5oYXNGb2N1cygpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy4kY29udGFpbmVyLmFkZENsYXNzKCdzZWxlY3QyLWNvbnRhaW5lci0tZm9jdXMnKTtcbiAgICB0aGlzLnRyaWdnZXIoJ2ZvY3VzJywge30pO1xuICB9O1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLmVuYWJsZSA9IGZ1bmN0aW9uIChhcmdzKSB7XG4gICAgaWYgKHRoaXMub3B0aW9ucy5nZXQoJ2RlYnVnJykgJiYgd2luZG93LmNvbnNvbGUgJiYgY29uc29sZS53YXJuKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICdTZWxlY3QyOiBUaGUgYHNlbGVjdDIoXCJlbmFibGVcIilgIG1ldGhvZCBoYXMgYmVlbiBkZXByZWNhdGVkIGFuZCB3aWxsJyArXG4gICAgICAgICcgYmUgcmVtb3ZlZCBpbiBsYXRlciBTZWxlY3QyIHZlcnNpb25zLiBVc2UgJGVsZW1lbnQucHJvcChcImRpc2FibGVkXCIpJyArXG4gICAgICAgICcgaW5zdGVhZC4nXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChhcmdzID09IG51bGwgfHwgYXJncy5sZW5ndGggPT09IDApIHtcbiAgICAgIGFyZ3MgPSBbdHJ1ZV07XG4gICAgfVxuXG4gICAgdmFyIGRpc2FibGVkID0gIWFyZ3NbMF07XG5cbiAgICB0aGlzLiRlbGVtZW50LnByb3AoJ2Rpc2FibGVkJywgZGlzYWJsZWQpO1xuICB9O1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLmRhdGEgPSBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMub3B0aW9ucy5nZXQoJ2RlYnVnJykgJiZcbiAgICAgICAgYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgd2luZG93LmNvbnNvbGUgJiYgY29uc29sZS53YXJuKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgICdTZWxlY3QyOiBEYXRhIGNhbiBubyBsb25nZXIgYmUgc2V0IHVzaW5nIGBzZWxlY3QyKFwiZGF0YVwiKWAuIFlvdSAnICtcbiAgICAgICAgJ3Nob3VsZCBjb25zaWRlciBzZXR0aW5nIHRoZSB2YWx1ZSBpbnN0ZWFkIHVzaW5nIGAkZWxlbWVudC52YWwoKWAuJ1xuICAgICAgKTtcbiAgICB9XG5cbiAgICB2YXIgZGF0YSA9IFtdO1xuXG4gICAgdGhpcy5kYXRhQWRhcHRlci5jdXJyZW50KGZ1bmN0aW9uIChjdXJyZW50RGF0YSkge1xuICAgICAgZGF0YSA9IGN1cnJlbnREYXRhO1xuICAgIH0pO1xuXG4gICAgcmV0dXJuIGRhdGE7XG4gIH07XG5cbiAgU2VsZWN0Mi5wcm90b3R5cGUudmFsID0gZnVuY3Rpb24gKGFyZ3MpIHtcbiAgICBpZiAodGhpcy5vcHRpb25zLmdldCgnZGVidWcnKSAmJiB3aW5kb3cuY29uc29sZSAmJiBjb25zb2xlLndhcm4pIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgJ1NlbGVjdDI6IFRoZSBgc2VsZWN0MihcInZhbFwiKWAgbWV0aG9kIGhhcyBiZWVuIGRlcHJlY2F0ZWQgYW5kIHdpbGwgYmUnICtcbiAgICAgICAgJyByZW1vdmVkIGluIGxhdGVyIFNlbGVjdDIgdmVyc2lvbnMuIFVzZSAkZWxlbWVudC52YWwoKSBpbnN0ZWFkLidcbiAgICAgICk7XG4gICAgfVxuXG4gICAgaWYgKGFyZ3MgPT0gbnVsbCB8fCBhcmdzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMuJGVsZW1lbnQudmFsKCk7XG4gICAgfVxuXG4gICAgdmFyIG5ld1ZhbCA9IGFyZ3NbMF07XG5cbiAgICBpZiAoJC5pc0FycmF5KG5ld1ZhbCkpIHtcbiAgICAgIG5ld1ZhbCA9ICQubWFwKG5ld1ZhbCwgZnVuY3Rpb24gKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqLnRvU3RyaW5nKCk7XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLiRlbGVtZW50LnZhbChuZXdWYWwpLnRyaWdnZXIoJ2NoYW5nZScpO1xuICB9O1xuXG4gIFNlbGVjdDIucHJvdG90eXBlLmRlc3Ryb3kgPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy4kY29udGFpbmVyLnJlbW92ZSgpO1xuXG4gICAgaWYgKHRoaXMuJGVsZW1lbnRbMF0uZGV0YWNoRXZlbnQpIHtcbiAgICAgIHRoaXMuJGVsZW1lbnRbMF0uZGV0YWNoRXZlbnQoJ29ucHJvcGVydHljaGFuZ2UnLCB0aGlzLl9zeW5jQSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX29ic2VydmVyICE9IG51bGwpIHtcbiAgICAgIHRoaXMuX29ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgICAgIHRoaXMuX29ic2VydmVyID0gbnVsbDtcbiAgICB9IGVsc2UgaWYgKHRoaXMuJGVsZW1lbnRbMF0ucmVtb3ZlRXZlbnRMaXN0ZW5lcikge1xuICAgICAgdGhpcy4kZWxlbWVudFswXVxuICAgICAgICAucmVtb3ZlRXZlbnRMaXN0ZW5lcignRE9NQXR0ck1vZGlmaWVkJywgdGhpcy5fc3luY0EsIGZhbHNlKTtcbiAgICAgIHRoaXMuJGVsZW1lbnRbMF1cbiAgICAgICAgLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ0RPTU5vZGVJbnNlcnRlZCcsIHRoaXMuX3N5bmNTLCBmYWxzZSk7XG4gICAgICB0aGlzLiRlbGVtZW50WzBdXG4gICAgICAgIC5yZW1vdmVFdmVudExpc3RlbmVyKCdET01Ob2RlUmVtb3ZlZCcsIHRoaXMuX3N5bmNTLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgdGhpcy5fc3luY0EgPSBudWxsO1xuICAgIHRoaXMuX3N5bmNTID0gbnVsbDtcblxuICAgIHRoaXMuJGVsZW1lbnQub2ZmKCcuc2VsZWN0MicpO1xuICAgIHRoaXMuJGVsZW1lbnQuYXR0cigndGFiaW5kZXgnLFxuICAgIFV0aWxzLkdldERhdGEodGhpcy4kZWxlbWVudFswXSwgJ29sZC10YWJpbmRleCcpKTtcblxuICAgIHRoaXMuJGVsZW1lbnQucmVtb3ZlQ2xhc3MoJ3NlbGVjdDItaGlkZGVuLWFjY2Vzc2libGUnKTtcbiAgICB0aGlzLiRlbGVtZW50LmF0dHIoJ2FyaWEtaGlkZGVuJywgJ2ZhbHNlJyk7XG4gICAgVXRpbHMuUmVtb3ZlRGF0YSh0aGlzLiRlbGVtZW50WzBdKTtcbiAgICB0aGlzLiRlbGVtZW50LnJlbW92ZURhdGEoJ3NlbGVjdDInKTtcblxuICAgIHRoaXMuZGF0YUFkYXB0ZXIuZGVzdHJveSgpO1xuICAgIHRoaXMuc2VsZWN0aW9uLmRlc3Ryb3koKTtcbiAgICB0aGlzLmRyb3Bkb3duLmRlc3Ryb3koKTtcbiAgICB0aGlzLnJlc3VsdHMuZGVzdHJveSgpO1xuXG4gICAgdGhpcy5kYXRhQWRhcHRlciA9IG51bGw7XG4gICAgdGhpcy5zZWxlY3Rpb24gPSBudWxsO1xuICAgIHRoaXMuZHJvcGRvd24gPSBudWxsO1xuICAgIHRoaXMucmVzdWx0cyA9IG51bGw7XG4gIH07XG5cbiAgU2VsZWN0Mi5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKCkge1xuICAgIHZhciAkY29udGFpbmVyID0gJChcbiAgICAgICc8c3BhbiBjbGFzcz1cInNlbGVjdDIgc2VsZWN0Mi1jb250YWluZXJcIj4nICtcbiAgICAgICAgJzxzcGFuIGNsYXNzPVwic2VsZWN0aW9uXCI+PC9zcGFuPicgK1xuICAgICAgICAnPHNwYW4gY2xhc3M9XCJkcm9wZG93bi13cmFwcGVyXCIgYXJpYS1oaWRkZW49XCJ0cnVlXCI+PC9zcGFuPicgK1xuICAgICAgJzwvc3Bhbj4nXG4gICAgKTtcblxuICAgICRjb250YWluZXIuYXR0cignZGlyJywgdGhpcy5vcHRpb25zLmdldCgnZGlyJykpO1xuXG4gICAgdGhpcy4kY29udGFpbmVyID0gJGNvbnRhaW5lcjtcblxuICAgIHRoaXMuJGNvbnRhaW5lci5hZGRDbGFzcygnc2VsZWN0Mi1jb250YWluZXItLScgKyB0aGlzLm9wdGlvbnMuZ2V0KCd0aGVtZScpKTtcblxuICAgIFV0aWxzLlN0b3JlRGF0YSgkY29udGFpbmVyWzBdLCAnZWxlbWVudCcsIHRoaXMuJGVsZW1lbnQpO1xuXG4gICAgcmV0dXJuICRjb250YWluZXI7XG4gIH07XG5cbiAgcmV0dXJuIFNlbGVjdDI7XG59KTtcblxuUzIuZGVmaW5lKCdqcXVlcnktbW91c2V3aGVlbCcsW1xuICAnanF1ZXJ5J1xuXSwgZnVuY3Rpb24gKCQpIHtcbiAgLy8gVXNlZCB0byBzaGltIGpRdWVyeS5tb3VzZXdoZWVsIGZvciBub24tZnVsbCBidWlsZHMuXG4gIHJldHVybiAkO1xufSk7XG5cblMyLmRlZmluZSgnanF1ZXJ5LnNlbGVjdDInLFtcbiAgJ2pxdWVyeScsXG4gICdqcXVlcnktbW91c2V3aGVlbCcsXG5cbiAgJy4vc2VsZWN0Mi9jb3JlJyxcbiAgJy4vc2VsZWN0Mi9kZWZhdWx0cycsXG4gICcuL3NlbGVjdDIvdXRpbHMnXG5dLCBmdW5jdGlvbiAoJCwgXywgU2VsZWN0MiwgRGVmYXVsdHMsIFV0aWxzKSB7XG4gIGlmICgkLmZuLnNlbGVjdDIgPT0gbnVsbCkge1xuICAgIC8vIEFsbCBtZXRob2RzIHRoYXQgc2hvdWxkIHJldHVybiB0aGUgZWxlbWVudFxuICAgIHZhciB0aGlzTWV0aG9kcyA9IFsnb3BlbicsICdjbG9zZScsICdkZXN0cm95J107XG5cbiAgICAkLmZuLnNlbGVjdDIgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuICAgICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cbiAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgaW5zdGFuY2VPcHRpb25zID0gJC5leHRlbmQodHJ1ZSwge30sIG9wdGlvbnMpO1xuXG4gICAgICAgICAgdmFyIGluc3RhbmNlID0gbmV3IFNlbGVjdDIoJCh0aGlzKSwgaW5zdGFuY2VPcHRpb25zKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiBvcHRpb25zID09PSAnc3RyaW5nJykge1xuICAgICAgICB2YXIgcmV0O1xuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG5cbiAgICAgICAgdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBVdGlscy5HZXREYXRhKHRoaXMsICdzZWxlY3QyJyk7XG5cbiAgICAgICAgICBpZiAoaW5zdGFuY2UgPT0gbnVsbCAmJiB3aW5kb3cuY29uc29sZSAmJiBjb25zb2xlLmVycm9yKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKFxuICAgICAgICAgICAgICAnVGhlIHNlbGVjdDIoXFwnJyArIG9wdGlvbnMgKyAnXFwnKSBtZXRob2Qgd2FzIGNhbGxlZCBvbiBhbiAnICtcbiAgICAgICAgICAgICAgJ2VsZW1lbnQgdGhhdCBpcyBub3QgdXNpbmcgU2VsZWN0Mi4nXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldCA9IGluc3RhbmNlW29wdGlvbnNdLmFwcGx5KGluc3RhbmNlLCBhcmdzKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgd2Ugc2hvdWxkIGJlIHJldHVybmluZyBgdGhpc2BcbiAgICAgICAgaWYgKCQuaW5BcnJheShvcHRpb25zLCB0aGlzTWV0aG9kcykgPiAtMSkge1xuICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJldDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBhcmd1bWVudHMgZm9yIFNlbGVjdDI6ICcgKyBvcHRpb25zKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgaWYgKCQuZm4uc2VsZWN0Mi5kZWZhdWx0cyA9PSBudWxsKSB7XG4gICAgJC5mbi5zZWxlY3QyLmRlZmF1bHRzID0gRGVmYXVsdHM7XG4gIH1cblxuICByZXR1cm4gU2VsZWN0Mjtcbn0pO1xuXG4gIC8vIFJldHVybiB0aGUgQU1EIGxvYWRlciBjb25maWd1cmF0aW9uIHNvIGl0IGNhbiBiZSB1c2VkIG91dHNpZGUgb2YgdGhpcyBmaWxlXG4gIHJldHVybiB7XG4gICAgZGVmaW5lOiBTMi5kZWZpbmUsXG4gICAgcmVxdWlyZTogUzIucmVxdWlyZVxuICB9O1xufSgpKTtcblxuICAvLyBBdXRvbG9hZCB0aGUgalF1ZXJ5IGJpbmRpbmdzXG4gIC8vIFdlIGtub3cgdGhhdCBhbGwgb2YgdGhlIG1vZHVsZXMgZXhpc3QgYWJvdmUgdGhpcywgc28gd2UncmUgc2FmZVxuICB2YXIgc2VsZWN0MiA9IFMyLnJlcXVpcmUoJ2pxdWVyeS5zZWxlY3QyJyk7XG5cbiAgLy8gSG9sZCB0aGUgQU1EIG1vZHVsZSByZWZlcmVuY2VzIG9uIHRoZSBqUXVlcnkgZnVuY3Rpb24gdGhhdCB3YXMganVzdCBsb2FkZWRcbiAgLy8gVGhpcyBhbGxvd3MgU2VsZWN0MiB0byB1c2UgdGhlIGludGVybmFsIGxvYWRlciBvdXRzaWRlIG9mIHRoaXMgZmlsZSwgc3VjaFxuICAvLyBhcyBpbiB0aGUgbGFuZ3VhZ2UgZmlsZXMuXG4gIGpRdWVyeS5mbi5zZWxlY3QyLmFtZCA9IFMyO1xuXG4gIC8vIFJldHVybiB0aGUgU2VsZWN0MiBpbnN0YW5jZSBmb3IgYW55b25lIHdobyBpcyBpbXBvcnRpbmcgaXQuXG4gIHJldHVybiBzZWxlY3QyO1xufSkpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvc2VsZWN0Mi9kaXN0L2pzL3NlbGVjdDIuanNcbi8vIG1vZHVsZSBpZCA9IDEzM1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKG1vZHVsZSkge1xyXG5cdGlmKCFtb2R1bGUud2VicGFja1BvbHlmaWxsKSB7XHJcblx0XHRtb2R1bGUuZGVwcmVjYXRlID0gZnVuY3Rpb24oKSB7fTtcclxuXHRcdG1vZHVsZS5wYXRocyA9IFtdO1xyXG5cdFx0Ly8gbW9kdWxlLnBhcmVudCA9IHVuZGVmaW5lZCBieSBkZWZhdWx0XHJcblx0XHRpZighbW9kdWxlLmNoaWxkcmVuKSBtb2R1bGUuY2hpbGRyZW4gPSBbXTtcclxuXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShtb2R1bGUsIFwibG9hZGVkXCIsIHtcclxuXHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcclxuXHRcdFx0Z2V0OiBmdW5jdGlvbigpIHtcclxuXHRcdFx0XHRyZXR1cm4gbW9kdWxlLmw7XHJcblx0XHRcdH1cclxuXHRcdH0pO1xyXG5cdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KG1vZHVsZSwgXCJpZFwiLCB7XHJcblx0XHRcdGVudW1lcmFibGU6IHRydWUsXHJcblx0XHRcdGdldDogZnVuY3Rpb24oKSB7XHJcblx0XHRcdFx0cmV0dXJuIG1vZHVsZS5pO1xyXG5cdFx0XHR9XHJcblx0XHR9KTtcclxuXHRcdG1vZHVsZS53ZWJwYWNrUG9seWZpbGwgPSAxO1xyXG5cdH1cclxuXHRyZXR1cm4gbW9kdWxlO1xyXG59O1xyXG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAod2VicGFjaykvYnVpbGRpbi9tb2R1bGUuanNcbi8vIG1vZHVsZSBpZCA9IDEzNFxuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCJ2YXIgbWFwID0ge1xuXHRcIi4vYWZcIjogNSxcblx0XCIuL2FmLmpzXCI6IDUsXG5cdFwiLi9hclwiOiA2LFxuXHRcIi4vYXItZHpcIjogNyxcblx0XCIuL2FyLWR6LmpzXCI6IDcsXG5cdFwiLi9hci1rd1wiOiA4LFxuXHRcIi4vYXIta3cuanNcIjogOCxcblx0XCIuL2FyLWx5XCI6IDksXG5cdFwiLi9hci1seS5qc1wiOiA5LFxuXHRcIi4vYXItbWFcIjogMTAsXG5cdFwiLi9hci1tYS5qc1wiOiAxMCxcblx0XCIuL2FyLXNhXCI6IDExLFxuXHRcIi4vYXItc2EuanNcIjogMTEsXG5cdFwiLi9hci10blwiOiAxMixcblx0XCIuL2FyLXRuLmpzXCI6IDEyLFxuXHRcIi4vYXIuanNcIjogNixcblx0XCIuL2F6XCI6IDEzLFxuXHRcIi4vYXouanNcIjogMTMsXG5cdFwiLi9iZVwiOiAxNCxcblx0XCIuL2JlLmpzXCI6IDE0LFxuXHRcIi4vYmdcIjogMTUsXG5cdFwiLi9iZy5qc1wiOiAxNSxcblx0XCIuL2JtXCI6IDE2LFxuXHRcIi4vYm0uanNcIjogMTYsXG5cdFwiLi9iblwiOiAxNyxcblx0XCIuL2JuLmpzXCI6IDE3LFxuXHRcIi4vYm9cIjogMTgsXG5cdFwiLi9iby5qc1wiOiAxOCxcblx0XCIuL2JyXCI6IDE5LFxuXHRcIi4vYnIuanNcIjogMTksXG5cdFwiLi9ic1wiOiAyMCxcblx0XCIuL2JzLmpzXCI6IDIwLFxuXHRcIi4vY2FcIjogMjEsXG5cdFwiLi9jYS5qc1wiOiAyMSxcblx0XCIuL2NzXCI6IDIyLFxuXHRcIi4vY3MuanNcIjogMjIsXG5cdFwiLi9jdlwiOiAyMyxcblx0XCIuL2N2LmpzXCI6IDIzLFxuXHRcIi4vY3lcIjogMjQsXG5cdFwiLi9jeS5qc1wiOiAyNCxcblx0XCIuL2RhXCI6IDI1LFxuXHRcIi4vZGEuanNcIjogMjUsXG5cdFwiLi9kZVwiOiAyNixcblx0XCIuL2RlLWF0XCI6IDI3LFxuXHRcIi4vZGUtYXQuanNcIjogMjcsXG5cdFwiLi9kZS1jaFwiOiAyOCxcblx0XCIuL2RlLWNoLmpzXCI6IDI4LFxuXHRcIi4vZGUuanNcIjogMjYsXG5cdFwiLi9kdlwiOiAyOSxcblx0XCIuL2R2LmpzXCI6IDI5LFxuXHRcIi4vZWxcIjogMzAsXG5cdFwiLi9lbC5qc1wiOiAzMCxcblx0XCIuL2VuLWF1XCI6IDMxLFxuXHRcIi4vZW4tYXUuanNcIjogMzEsXG5cdFwiLi9lbi1jYVwiOiAzMixcblx0XCIuL2VuLWNhLmpzXCI6IDMyLFxuXHRcIi4vZW4tZ2JcIjogMzMsXG5cdFwiLi9lbi1nYi5qc1wiOiAzMyxcblx0XCIuL2VuLWllXCI6IDM0LFxuXHRcIi4vZW4taWUuanNcIjogMzQsXG5cdFwiLi9lbi1uelwiOiAzNSxcblx0XCIuL2VuLW56LmpzXCI6IDM1LFxuXHRcIi4vZW9cIjogMzYsXG5cdFwiLi9lby5qc1wiOiAzNixcblx0XCIuL2VzXCI6IDM3LFxuXHRcIi4vZXMtZG9cIjogMzgsXG5cdFwiLi9lcy1kby5qc1wiOiAzOCxcblx0XCIuL2VzLXVzXCI6IDM5LFxuXHRcIi4vZXMtdXMuanNcIjogMzksXG5cdFwiLi9lcy5qc1wiOiAzNyxcblx0XCIuL2V0XCI6IDQwLFxuXHRcIi4vZXQuanNcIjogNDAsXG5cdFwiLi9ldVwiOiA0MSxcblx0XCIuL2V1LmpzXCI6IDQxLFxuXHRcIi4vZmFcIjogNDIsXG5cdFwiLi9mYS5qc1wiOiA0Mixcblx0XCIuL2ZpXCI6IDQzLFxuXHRcIi4vZmkuanNcIjogNDMsXG5cdFwiLi9mb1wiOiA0NCxcblx0XCIuL2ZvLmpzXCI6IDQ0LFxuXHRcIi4vZnJcIjogNDUsXG5cdFwiLi9mci1jYVwiOiA0Nixcblx0XCIuL2ZyLWNhLmpzXCI6IDQ2LFxuXHRcIi4vZnItY2hcIjogNDcsXG5cdFwiLi9mci1jaC5qc1wiOiA0Nyxcblx0XCIuL2ZyLmpzXCI6IDQ1LFxuXHRcIi4vZnlcIjogNDgsXG5cdFwiLi9meS5qc1wiOiA0OCxcblx0XCIuL2dkXCI6IDQ5LFxuXHRcIi4vZ2QuanNcIjogNDksXG5cdFwiLi9nbFwiOiA1MCxcblx0XCIuL2dsLmpzXCI6IDUwLFxuXHRcIi4vZ29tLWxhdG5cIjogNTEsXG5cdFwiLi9nb20tbGF0bi5qc1wiOiA1MSxcblx0XCIuL2d1XCI6IDUyLFxuXHRcIi4vZ3UuanNcIjogNTIsXG5cdFwiLi9oZVwiOiA1Myxcblx0XCIuL2hlLmpzXCI6IDUzLFxuXHRcIi4vaGlcIjogNTQsXG5cdFwiLi9oaS5qc1wiOiA1NCxcblx0XCIuL2hyXCI6IDU1LFxuXHRcIi4vaHIuanNcIjogNTUsXG5cdFwiLi9odVwiOiA1Nixcblx0XCIuL2h1LmpzXCI6IDU2LFxuXHRcIi4vaHktYW1cIjogNTcsXG5cdFwiLi9oeS1hbS5qc1wiOiA1Nyxcblx0XCIuL2lkXCI6IDU4LFxuXHRcIi4vaWQuanNcIjogNTgsXG5cdFwiLi9pc1wiOiA1OSxcblx0XCIuL2lzLmpzXCI6IDU5LFxuXHRcIi4vaXRcIjogNjAsXG5cdFwiLi9pdC5qc1wiOiA2MCxcblx0XCIuL2phXCI6IDYxLFxuXHRcIi4vamEuanNcIjogNjEsXG5cdFwiLi9qdlwiOiA2Mixcblx0XCIuL2p2LmpzXCI6IDYyLFxuXHRcIi4va2FcIjogNjMsXG5cdFwiLi9rYS5qc1wiOiA2Myxcblx0XCIuL2trXCI6IDY0LFxuXHRcIi4va2suanNcIjogNjQsXG5cdFwiLi9rbVwiOiA2NSxcblx0XCIuL2ttLmpzXCI6IDY1LFxuXHRcIi4va25cIjogNjYsXG5cdFwiLi9rbi5qc1wiOiA2Nixcblx0XCIuL2tvXCI6IDY3LFxuXHRcIi4va28uanNcIjogNjcsXG5cdFwiLi9reVwiOiA2OCxcblx0XCIuL2t5LmpzXCI6IDY4LFxuXHRcIi4vbGJcIjogNjksXG5cdFwiLi9sYi5qc1wiOiA2OSxcblx0XCIuL2xvXCI6IDcwLFxuXHRcIi4vbG8uanNcIjogNzAsXG5cdFwiLi9sdFwiOiA3MSxcblx0XCIuL2x0LmpzXCI6IDcxLFxuXHRcIi4vbHZcIjogNzIsXG5cdFwiLi9sdi5qc1wiOiA3Mixcblx0XCIuL21lXCI6IDczLFxuXHRcIi4vbWUuanNcIjogNzMsXG5cdFwiLi9taVwiOiA3NCxcblx0XCIuL21pLmpzXCI6IDc0LFxuXHRcIi4vbWtcIjogNzUsXG5cdFwiLi9tay5qc1wiOiA3NSxcblx0XCIuL21sXCI6IDc2LFxuXHRcIi4vbWwuanNcIjogNzYsXG5cdFwiLi9tclwiOiA3Nyxcblx0XCIuL21yLmpzXCI6IDc3LFxuXHRcIi4vbXNcIjogNzgsXG5cdFwiLi9tcy1teVwiOiA3OSxcblx0XCIuL21zLW15LmpzXCI6IDc5LFxuXHRcIi4vbXMuanNcIjogNzgsXG5cdFwiLi9tdFwiOiA4MCxcblx0XCIuL210LmpzXCI6IDgwLFxuXHRcIi4vbXlcIjogODEsXG5cdFwiLi9teS5qc1wiOiA4MSxcblx0XCIuL25iXCI6IDgyLFxuXHRcIi4vbmIuanNcIjogODIsXG5cdFwiLi9uZVwiOiA4Myxcblx0XCIuL25lLmpzXCI6IDgzLFxuXHRcIi4vbmxcIjogODQsXG5cdFwiLi9ubC1iZVwiOiA4NSxcblx0XCIuL25sLWJlLmpzXCI6IDg1LFxuXHRcIi4vbmwuanNcIjogODQsXG5cdFwiLi9ublwiOiA4Nixcblx0XCIuL25uLmpzXCI6IDg2LFxuXHRcIi4vcGEtaW5cIjogODcsXG5cdFwiLi9wYS1pbi5qc1wiOiA4Nyxcblx0XCIuL3BsXCI6IDg4LFxuXHRcIi4vcGwuanNcIjogODgsXG5cdFwiLi9wdFwiOiA4OSxcblx0XCIuL3B0LWJyXCI6IDkwLFxuXHRcIi4vcHQtYnIuanNcIjogOTAsXG5cdFwiLi9wdC5qc1wiOiA4OSxcblx0XCIuL3JvXCI6IDkxLFxuXHRcIi4vcm8uanNcIjogOTEsXG5cdFwiLi9ydVwiOiA5Mixcblx0XCIuL3J1LmpzXCI6IDkyLFxuXHRcIi4vc2RcIjogOTMsXG5cdFwiLi9zZC5qc1wiOiA5Myxcblx0XCIuL3NlXCI6IDk0LFxuXHRcIi4vc2UuanNcIjogOTQsXG5cdFwiLi9zaVwiOiA5NSxcblx0XCIuL3NpLmpzXCI6IDk1LFxuXHRcIi4vc2tcIjogOTYsXG5cdFwiLi9zay5qc1wiOiA5Nixcblx0XCIuL3NsXCI6IDk3LFxuXHRcIi4vc2wuanNcIjogOTcsXG5cdFwiLi9zcVwiOiA5OCxcblx0XCIuL3NxLmpzXCI6IDk4LFxuXHRcIi4vc3JcIjogOTksXG5cdFwiLi9zci1jeXJsXCI6IDEwMCxcblx0XCIuL3NyLWN5cmwuanNcIjogMTAwLFxuXHRcIi4vc3IuanNcIjogOTksXG5cdFwiLi9zc1wiOiAxMDEsXG5cdFwiLi9zcy5qc1wiOiAxMDEsXG5cdFwiLi9zdlwiOiAxMDIsXG5cdFwiLi9zdi5qc1wiOiAxMDIsXG5cdFwiLi9zd1wiOiAxMDMsXG5cdFwiLi9zdy5qc1wiOiAxMDMsXG5cdFwiLi90YVwiOiAxMDQsXG5cdFwiLi90YS5qc1wiOiAxMDQsXG5cdFwiLi90ZVwiOiAxMDUsXG5cdFwiLi90ZS5qc1wiOiAxMDUsXG5cdFwiLi90ZXRcIjogMTA2LFxuXHRcIi4vdGV0LmpzXCI6IDEwNixcblx0XCIuL3RoXCI6IDEwNyxcblx0XCIuL3RoLmpzXCI6IDEwNyxcblx0XCIuL3RsLXBoXCI6IDEwOCxcblx0XCIuL3RsLXBoLmpzXCI6IDEwOCxcblx0XCIuL3RsaFwiOiAxMDksXG5cdFwiLi90bGguanNcIjogMTA5LFxuXHRcIi4vdHJcIjogMTEwLFxuXHRcIi4vdHIuanNcIjogMTEwLFxuXHRcIi4vdHpsXCI6IDExMSxcblx0XCIuL3R6bC5qc1wiOiAxMTEsXG5cdFwiLi90em1cIjogMTEyLFxuXHRcIi4vdHptLWxhdG5cIjogMTEzLFxuXHRcIi4vdHptLWxhdG4uanNcIjogMTEzLFxuXHRcIi4vdHptLmpzXCI6IDExMixcblx0XCIuL3VrXCI6IDExNCxcblx0XCIuL3VrLmpzXCI6IDExNCxcblx0XCIuL3VyXCI6IDExNSxcblx0XCIuL3VyLmpzXCI6IDExNSxcblx0XCIuL3V6XCI6IDExNixcblx0XCIuL3V6LWxhdG5cIjogMTE3LFxuXHRcIi4vdXotbGF0bi5qc1wiOiAxMTcsXG5cdFwiLi91ei5qc1wiOiAxMTYsXG5cdFwiLi92aVwiOiAxMTgsXG5cdFwiLi92aS5qc1wiOiAxMTgsXG5cdFwiLi94LXBzZXVkb1wiOiAxMTksXG5cdFwiLi94LXBzZXVkby5qc1wiOiAxMTksXG5cdFwiLi95b1wiOiAxMjAsXG5cdFwiLi95by5qc1wiOiAxMjAsXG5cdFwiLi96aC1jblwiOiAxMjEsXG5cdFwiLi96aC1jbi5qc1wiOiAxMjEsXG5cdFwiLi96aC1oa1wiOiAxMjIsXG5cdFwiLi96aC1oay5qc1wiOiAxMjIsXG5cdFwiLi96aC10d1wiOiAxMjMsXG5cdFwiLi96aC10dy5qc1wiOiAxMjNcbn07XG5mdW5jdGlvbiB3ZWJwYWNrQ29udGV4dChyZXEpIHtcblx0cmV0dXJuIF9fd2VicGFja19yZXF1aXJlX18od2VicGFja0NvbnRleHRSZXNvbHZlKHJlcSkpO1xufTtcbmZ1bmN0aW9uIHdlYnBhY2tDb250ZXh0UmVzb2x2ZShyZXEpIHtcblx0dmFyIGlkID0gbWFwW3JlcV07XG5cdGlmKCEoaWQgKyAxKSkgLy8gY2hlY2sgZm9yIG51bWJlciBvciBzdHJpbmdcblx0XHR0aHJvdyBuZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiICsgcmVxICsgXCInLlwiKTtcblx0cmV0dXJuIGlkO1xufTtcbndlYnBhY2tDb250ZXh0LmtleXMgPSBmdW5jdGlvbiB3ZWJwYWNrQ29udGV4dEtleXMoKSB7XG5cdHJldHVybiBPYmplY3Qua2V5cyhtYXApO1xufTtcbndlYnBhY2tDb250ZXh0LnJlc29sdmUgPSB3ZWJwYWNrQ29udGV4dFJlc29sdmU7XG5tb2R1bGUuZXhwb3J0cyA9IHdlYnBhY2tDb250ZXh0O1xud2VicGFja0NvbnRleHQuaWQgPSAxMzU7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvbW9tZW50L2xvY2FsZSBeXFwuXFwvLiokXG4vLyBtb2R1bGUgaWQgPSAxMzVcbi8vIG1vZHVsZSBjaHVua3MgPSAwIiwiLyohIHZlcnNpb24gOiA0LjE3LjQ3XHJcbiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cclxuIGJvb3RzdHJhcC1kYXRldGltZWpzXHJcbiBodHRwczovL2dpdGh1Yi5jb20vRW9uYXNkYW4vYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyXHJcbiBDb3B5cmlnaHQgKGMpIDIwMTUgSm9uYXRoYW4gUGV0ZXJzb25cclxuID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxyXG4gKi9cclxuLypcclxuIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxyXG5cclxuIENvcHlyaWdodCAoYykgMjAxNSBKb25hdGhhbiBQZXRlcnNvblxyXG5cclxuIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcclxuIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcclxuIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcclxuIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcclxuIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xyXG4gZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcclxuXHJcbiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpblxyXG4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXHJcblxyXG4gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxyXG4gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXHJcbiBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcclxuIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVJcclxuIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sXHJcbiBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXHJcbiBUSEUgU09GVFdBUkUuXHJcbiAqL1xyXG4vKmdsb2JhbCBkZWZpbmU6ZmFsc2UgKi9cclxuLypnbG9iYWwgZXhwb3J0czpmYWxzZSAqL1xyXG4vKmdsb2JhbCByZXF1aXJlOmZhbHNlICovXHJcbi8qZ2xvYmFsIGpRdWVyeTpmYWxzZSAqL1xyXG4vKmdsb2JhbCBtb21lbnQ6ZmFsc2UgKi9cclxuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XHJcbiAgICAndXNlIHN0cmljdCc7XHJcbiAgICBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XHJcbiAgICAgICAgLy8gQU1EIGlzIHVzZWQgLSBSZWdpc3RlciBhcyBhbiBhbm9ueW1vdXMgbW9kdWxlLlxyXG4gICAgICAgIGRlZmluZShbJ2pxdWVyeScsICdtb21lbnQnXSwgZmFjdG9yeSk7XHJcbiAgICB9IGVsc2UgaWYgKHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0Jykge1xyXG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKCdqcXVlcnknKSwgcmVxdWlyZSgnbW9tZW50JykpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBOZWl0aGVyIEFNRCBub3IgQ29tbW9uSlMgdXNlZC4gVXNlIGdsb2JhbCB2YXJpYWJsZXMuXHJcbiAgICAgICAgaWYgKHR5cGVvZiBqUXVlcnkgPT09ICd1bmRlZmluZWQnKSB7XHJcbiAgICAgICAgICAgIHRocm93ICdib290c3RyYXAtZGF0ZXRpbWVwaWNrZXIgcmVxdWlyZXMgalF1ZXJ5IHRvIGJlIGxvYWRlZCBmaXJzdCc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0eXBlb2YgbW9tZW50ID09PSAndW5kZWZpbmVkJykge1xyXG4gICAgICAgICAgICB0aHJvdyAnYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyIHJlcXVpcmVzIE1vbWVudC5qcyB0byBiZSBsb2FkZWQgZmlyc3QnO1xyXG4gICAgICAgIH1cclxuICAgICAgICBmYWN0b3J5KGpRdWVyeSwgbW9tZW50KTtcclxuICAgIH1cclxufShmdW5jdGlvbiAoJCwgbW9tZW50KSB7XHJcbiAgICAndXNlIHN0cmljdCc7XHJcbiAgICBpZiAoIW1vbWVudCkge1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyIHJlcXVpcmVzIE1vbWVudC5qcyB0byBiZSBsb2FkZWQgZmlyc3QnKTtcclxuICAgIH1cclxuXHJcbiAgICB2YXIgZGF0ZVRpbWVQaWNrZXIgPSBmdW5jdGlvbiAoZWxlbWVudCwgb3B0aW9ucykge1xyXG4gICAgICAgIHZhciBwaWNrZXIgPSB7fSxcclxuICAgICAgICAgICAgZGF0ZSxcclxuICAgICAgICAgICAgdmlld0RhdGUsXHJcbiAgICAgICAgICAgIHVuc2V0ID0gdHJ1ZSxcclxuICAgICAgICAgICAgaW5wdXQsXHJcbiAgICAgICAgICAgIGNvbXBvbmVudCA9IGZhbHNlLFxyXG4gICAgICAgICAgICB3aWRnZXQgPSBmYWxzZSxcclxuICAgICAgICAgICAgdXNlMjRIb3VycyxcclxuICAgICAgICAgICAgbWluVmlld01vZGVOdW1iZXIgPSAwLFxyXG4gICAgICAgICAgICBhY3R1YWxGb3JtYXQsXHJcbiAgICAgICAgICAgIHBhcnNlRm9ybWF0cyxcclxuICAgICAgICAgICAgY3VycmVudFZpZXdNb2RlLFxyXG4gICAgICAgICAgICBkYXRlUGlja2VyTW9kZXMgPSBbXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzTmFtZTogJ2RheXMnLFxyXG4gICAgICAgICAgICAgICAgICAgIG5hdkZuYzogJ00nLFxyXG4gICAgICAgICAgICAgICAgICAgIG5hdlN0ZXA6IDFcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2xzTmFtZTogJ21vbnRocycsXHJcbiAgICAgICAgICAgICAgICAgICAgbmF2Rm5jOiAneScsXHJcbiAgICAgICAgICAgICAgICAgICAgbmF2U3RlcDogMVxyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgICAgICBjbHNOYW1lOiAneWVhcnMnLFxyXG4gICAgICAgICAgICAgICAgICAgIG5hdkZuYzogJ3knLFxyXG4gICAgICAgICAgICAgICAgICAgIG5hdlN0ZXA6IDEwXHJcbiAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICAgIGNsc05hbWU6ICdkZWNhZGVzJyxcclxuICAgICAgICAgICAgICAgICAgICBuYXZGbmM6ICd5JyxcclxuICAgICAgICAgICAgICAgICAgICBuYXZTdGVwOiAxMDBcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgXSxcclxuICAgICAgICAgICAgdmlld01vZGVzID0gWydkYXlzJywgJ21vbnRocycsICd5ZWFycycsICdkZWNhZGVzJ10sXHJcbiAgICAgICAgICAgIHZlcnRpY2FsTW9kZXMgPSBbJ3RvcCcsICdib3R0b20nLCAnYXV0byddLFxyXG4gICAgICAgICAgICBob3Jpem9udGFsTW9kZXMgPSBbJ2xlZnQnLCAncmlnaHQnLCAnYXV0byddLFxyXG4gICAgICAgICAgICB0b29sYmFyUGxhY2VtZW50cyA9IFsnZGVmYXVsdCcsICd0b3AnLCAnYm90dG9tJ10sXHJcbiAgICAgICAgICAgIGtleU1hcCA9IHtcclxuICAgICAgICAgICAgICAgICd1cCc6IDM4LFxyXG4gICAgICAgICAgICAgICAgMzg6ICd1cCcsXHJcbiAgICAgICAgICAgICAgICAnZG93bic6IDQwLFxyXG4gICAgICAgICAgICAgICAgNDA6ICdkb3duJyxcclxuICAgICAgICAgICAgICAgICdsZWZ0JzogMzcsXHJcbiAgICAgICAgICAgICAgICAzNzogJ2xlZnQnLFxyXG4gICAgICAgICAgICAgICAgJ3JpZ2h0JzogMzksXHJcbiAgICAgICAgICAgICAgICAzOTogJ3JpZ2h0JyxcclxuICAgICAgICAgICAgICAgICd0YWInOiA5LFxyXG4gICAgICAgICAgICAgICAgOTogJ3RhYicsXHJcbiAgICAgICAgICAgICAgICAnZXNjYXBlJzogMjcsXHJcbiAgICAgICAgICAgICAgICAyNzogJ2VzY2FwZScsXHJcbiAgICAgICAgICAgICAgICAnZW50ZXInOiAxMyxcclxuICAgICAgICAgICAgICAgIDEzOiAnZW50ZXInLFxyXG4gICAgICAgICAgICAgICAgJ3BhZ2VVcCc6IDMzLFxyXG4gICAgICAgICAgICAgICAgMzM6ICdwYWdlVXAnLFxyXG4gICAgICAgICAgICAgICAgJ3BhZ2VEb3duJzogMzQsXHJcbiAgICAgICAgICAgICAgICAzNDogJ3BhZ2VEb3duJyxcclxuICAgICAgICAgICAgICAgICdzaGlmdCc6IDE2LFxyXG4gICAgICAgICAgICAgICAgMTY6ICdzaGlmdCcsXHJcbiAgICAgICAgICAgICAgICAnY29udHJvbCc6IDE3LFxyXG4gICAgICAgICAgICAgICAgMTc6ICdjb250cm9sJyxcclxuICAgICAgICAgICAgICAgICdzcGFjZSc6IDMyLFxyXG4gICAgICAgICAgICAgICAgMzI6ICdzcGFjZScsXHJcbiAgICAgICAgICAgICAgICAndCc6IDg0LFxyXG4gICAgICAgICAgICAgICAgODQ6ICd0JyxcclxuICAgICAgICAgICAgICAgICdkZWxldGUnOiA0NixcclxuICAgICAgICAgICAgICAgIDQ2OiAnZGVsZXRlJ1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBrZXlTdGF0ZSA9IHt9LFxyXG5cclxuICAgICAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbiAgICAgICAgICAgICAqXHJcbiAgICAgICAgICAgICAqIFByaXZhdGUgZnVuY3Rpb25zXHJcbiAgICAgICAgICAgICAqXHJcbiAgICAgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcbiAgICAgICAgICAgIGhhc1RpbWVab25lID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG1vbWVudC50eiAhPT0gdW5kZWZpbmVkICYmIG9wdGlvbnMudGltZVpvbmUgIT09IHVuZGVmaW5lZCAmJiBvcHRpb25zLnRpbWVab25lICE9PSBudWxsICYmIG9wdGlvbnMudGltZVpvbmUgIT09ICcnO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgZ2V0TW9tZW50ID0gZnVuY3Rpb24gKGQpIHtcclxuICAgICAgICAgICAgICAgIHZhciByZXR1cm5Nb21lbnQ7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGQgPT09IHVuZGVmaW5lZCB8fCBkID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50KCk7IC8vVE9ETyBzaG91bGQgdGhpcyB1c2UgZm9ybWF0PyBhbmQgbG9jYWxlP1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChtb21lbnQuaXNEYXRlKGQpIHx8IG1vbWVudC5pc01vbWVudChkKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBkYXRlIHRoYXQgaXMgcGFzc2VkIGluIGlzIGFscmVhZHkgYSBEYXRlKCkgb3IgbW9tZW50KCkgb2JqZWN0LFxyXG4gICAgICAgICAgICAgICAgICAgIC8vIHBhc3MgaXQgZGlyZWN0bHkgdG8gbW9tZW50LlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybk1vbWVudCA9IG1vbWVudChkKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaGFzVGltZVpvbmUoKSkgeyAvLyBUaGVyZSBpcyBhIHN0cmluZyB0byBwYXJzZSBhbmQgYSBkZWZhdWx0IHRpbWUgem9uZVxyXG4gICAgICAgICAgICAgICAgICAgIC8vIHBhcnNlIHdpdGggdGhlIHR6IGZ1bmN0aW9uIHdoaWNoIHRha2VzIGEgZGVmYXVsdCB0aW1lIHpvbmUgaWYgaXQgaXMgbm90IGluIHRoZSBmb3JtYXQgc3RyaW5nXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuTW9tZW50ID0gbW9tZW50LnR6KGQsIHBhcnNlRm9ybWF0cywgb3B0aW9ucy51c2VTdHJpY3QsIG9wdGlvbnMudGltZVpvbmUpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQgPSBtb21lbnQoZCwgcGFyc2VGb3JtYXRzLCBvcHRpb25zLnVzZVN0cmljdCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGhhc1RpbWVab25lKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm5Nb21lbnQudHoob3B0aW9ucy50aW1lWm9uZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJldHVybk1vbWVudDtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGlzRW5hYmxlZCA9IGZ1bmN0aW9uIChncmFudWxhcml0eSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBncmFudWxhcml0eSAhPT0gJ3N0cmluZycgfHwgZ3JhbnVsYXJpdHkubGVuZ3RoID4gMSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2lzRW5hYmxlZCBleHBlY3RzIGEgc2luZ2xlIGNoYXJhY3RlciBzdHJpbmcgcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGdyYW51bGFyaXR5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAneSc6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhY3R1YWxGb3JtYXQuaW5kZXhPZignWScpICE9PSAtMTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdNJzpcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFjdHVhbEZvcm1hdC5pbmRleE9mKCdNJykgIT09IC0xO1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2QnOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignZCcpICE9PSAtMTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdoJzpcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdIJzpcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFjdHVhbEZvcm1hdC50b0xvd2VyQ2FzZSgpLmluZGV4T2YoJ2gnKSAhPT0gLTE7XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnbSc6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBhY3R1YWxGb3JtYXQuaW5kZXhPZignbScpICE9PSAtMTtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlICdzJzpcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGFjdHVhbEZvcm1hdC5pbmRleE9mKCdzJykgIT09IC0xO1xyXG4gICAgICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGhhc1RpbWUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gKGlzRW5hYmxlZCgnaCcpIHx8IGlzRW5hYmxlZCgnbScpIHx8IGlzRW5hYmxlZCgncycpKTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGhhc0RhdGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gKGlzRW5hYmxlZCgneScpIHx8IGlzRW5hYmxlZCgnTScpIHx8IGlzRW5hYmxlZCgnZCcpKTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGdldERhdGVQaWNrZXJUZW1wbGF0ZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciBoZWFkVGVtcGxhdGUgPSAkKCc8dGhlYWQ+JylcclxuICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8dHI+JylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHRoPicpLmFkZENsYXNzKCdwcmV2JykuYXR0cignZGF0YS1hY3Rpb24nLCAncHJldmlvdXMnKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3Mob3B0aW9ucy5pY29ucy5wcmV2aW91cykpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8dGg+JykuYWRkQ2xhc3MoJ3BpY2tlci1zd2l0Y2gnKS5hdHRyKCdkYXRhLWFjdGlvbicsICdwaWNrZXJTd2l0Y2gnKS5hdHRyKCdjb2xzcGFuJywgKG9wdGlvbnMuY2FsZW5kYXJXZWVrcyA/ICc2JyA6ICc1JykpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8dGg+JykuYWRkQ2xhc3MoJ25leHQnKS5hdHRyKCdkYXRhLWFjdGlvbicsICduZXh0JylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKG9wdGlvbnMuaWNvbnMubmV4dCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICAgICAgICBjb250VGVtcGxhdGUgPSAkKCc8dGJvZHk+JylcclxuICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8dHI+JylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHRkPicpLmF0dHIoJ2NvbHNwYW4nLCAob3B0aW9ucy5jYWxlbmRhcldlZWtzID8gJzgnIDogJzcnKSkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgICAgIHJldHVybiBbXHJcbiAgICAgICAgICAgICAgICAgICAgJCgnPGRpdj4nKS5hZGRDbGFzcygnZGF0ZXBpY2tlci1kYXlzJylcclxuICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKGhlYWRUZW1wbGF0ZSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHRib2R5PicpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICAgICAgICAkKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyLW1vbnRocycpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZChoZWFkVGVtcGxhdGUuY2xvbmUoKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoY29udFRlbXBsYXRlLmNsb25lKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApLFxyXG4gICAgICAgICAgICAgICAgICAgICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2RhdGVwaWNrZXIteWVhcnMnKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoaGVhZFRlbXBsYXRlLmNsb25lKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKGNvbnRUZW1wbGF0ZS5jbG9uZSgpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcclxuICAgICAgICAgICAgICAgICAgICAkKCc8ZGl2PicpLmFkZENsYXNzKCdkYXRlcGlja2VyLWRlY2FkZXMnKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoaGVhZFRlbXBsYXRlLmNsb25lKCkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKGNvbnRUZW1wbGF0ZS5jbG9uZSgpKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxyXG4gICAgICAgICAgICAgICAgXTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGdldFRpbWVQaWNrZXJNYWluVGVtcGxhdGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdG9wUm93ID0gJCgnPHRyPicpLFxyXG4gICAgICAgICAgICAgICAgICAgIG1pZGRsZVJvdyA9ICQoJzx0cj4nKSxcclxuICAgICAgICAgICAgICAgICAgICBib3R0b21Sb3cgPSAkKCc8dHI+Jyk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGlzRW5hYmxlZCgnaCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdG9wUm93LmFwcGVuZCgkKCc8dGQ+JylcclxuICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHsgaHJlZjogJyMnLCB0YWJpbmRleDogJy0xJywgJ3RpdGxlJzogb3B0aW9ucy50b29sdGlwcy5pbmNyZW1lbnRIb3VyIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdpbmNyZW1lbnRIb3VycycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyhvcHRpb25zLmljb25zLnVwKSkpKTtcclxuICAgICAgICAgICAgICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLWhvdXInKS5hdHRyKHsgJ2RhdGEtdGltZS1jb21wb25lbnQnOiAnaG91cnMnLCAndGl0bGUnOiBvcHRpb25zLnRvb2x0aXBzLnBpY2tIb3VyIH0pLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3Nob3dIb3VycycpKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tUm93LmFwcGVuZCgkKCc8dGQ+JylcclxuICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHsgaHJlZjogJyMnLCB0YWJpbmRleDogJy0xJywgJ3RpdGxlJzogb3B0aW9ucy50b29sdGlwcy5kZWNyZW1lbnRIb3VyIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdkZWNyZW1lbnRIb3VycycpLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyhvcHRpb25zLmljb25zLmRvd24pKSkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKGlzRW5hYmxlZCgnbScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzRW5hYmxlZCgnaCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvcFJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1pZGRsZVJvdy5hcHBlbmQoJCgnPHRkPicpLmFkZENsYXNzKCdzZXBhcmF0b3InKS5odG1sKCc6JykpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzxhPicpLmF0dHIoeyBocmVmOiAnIycsIHRhYmluZGV4OiAnLTEnLCAndGl0bGUnOiBvcHRpb25zLnRvb2x0aXBzLmluY3JlbWVudE1pbnV0ZSB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnaW5jcmVtZW50TWludXRlcycpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKG9wdGlvbnMuaWNvbnMudXApKSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIG1pZGRsZVJvdy5hcHBlbmQoJCgnPHRkPicpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItbWludXRlJykuYXR0cih7ICdkYXRhLXRpbWUtY29tcG9uZW50JzogJ21pbnV0ZXMnLCAndGl0bGUnOiBvcHRpb25zLnRvb2x0aXBzLnBpY2tNaW51dGUgfSkuYXR0cignZGF0YS1hY3Rpb24nLCAnc2hvd01pbnV0ZXMnKSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbVJvdy5hcHBlbmQoJCgnPHRkPicpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPGE+JykuYXR0cih7IGhyZWY6ICcjJywgdGFiaW5kZXg6ICctMScsICd0aXRsZSc6IG9wdGlvbnMudG9vbHRpcHMuZGVjcmVtZW50TWludXRlIH0pLmFkZENsYXNzKCdidG4nKS5hdHRyKCdkYXRhLWFjdGlvbicsICdkZWNyZW1lbnRNaW51dGVzJylcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHNwYW4+JykuYWRkQ2xhc3Mob3B0aW9ucy5pY29ucy5kb3duKSkpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChpc0VuYWJsZWQoJ3MnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0VuYWJsZWQoJ20nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0b3BSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKS5hZGRDbGFzcygnc2VwYXJhdG9yJykuaHRtbCgnOicpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYm90dG9tUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdG9wUm93LmFwcGVuZCgkKCc8dGQ+JylcclxuICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8YT4nKS5hdHRyKHsgaHJlZjogJyMnLCB0YWJpbmRleDogJy0xJywgJ3RpdGxlJzogb3B0aW9ucy50b29sdGlwcy5pbmNyZW1lbnRTZWNvbmQgfSkuYWRkQ2xhc3MoJ2J0bicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ2luY3JlbWVudFNlY29uZHMnKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyhvcHRpb25zLmljb25zLnVwKSkpKTtcclxuICAgICAgICAgICAgICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKCd0aW1lcGlja2VyLXNlY29uZCcpLmF0dHIoeyAnZGF0YS10aW1lLWNvbXBvbmVudCc6ICdzZWNvbmRzJywgJ3RpdGxlJzogb3B0aW9ucy50b29sdGlwcy5waWNrU2Vjb25kIH0pLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3Nob3dTZWNvbmRzJykpKTtcclxuICAgICAgICAgICAgICAgICAgICBib3R0b21Sb3cuYXBwZW5kKCQoJzx0ZD4nKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzxhPicpLmF0dHIoeyBocmVmOiAnIycsIHRhYmluZGV4OiAnLTEnLCAndGl0bGUnOiBvcHRpb25zLnRvb2x0aXBzLmRlY3JlbWVudFNlY29uZCB9KS5hZGRDbGFzcygnYnRuJykuYXR0cignZGF0YS1hY3Rpb24nLCAnZGVjcmVtZW50U2Vjb25kcycpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKG9wdGlvbnMuaWNvbnMuZG93bikpKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKCF1c2UyNEhvdXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdG9wUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpKTtcclxuICAgICAgICAgICAgICAgICAgICBtaWRkbGVSb3cuYXBwZW5kKCQoJzx0ZD4nKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzxidXR0b24+JykuYWRkQ2xhc3MoJ2J0biBidG4tcHJpbWFyeScpLmF0dHIoeyAnZGF0YS1hY3Rpb24nOiAndG9nZ2xlUGVyaW9kJywgdGFiaW5kZXg6ICctMScsICd0aXRsZSc6IG9wdGlvbnMudG9vbHRpcHMudG9nZ2xlUGVyaW9kIH0pKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgYm90dG9tUm93LmFwcGVuZCgkKCc8dGQ+JykuYWRkQ2xhc3MoJ3NlcGFyYXRvcicpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gJCgnPGRpdj4nKS5hZGRDbGFzcygndGltZXBpY2tlci1waWNrZXInKVxyXG4gICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKFt0b3BSb3csIG1pZGRsZVJvdywgYm90dG9tUm93XSkpO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgZ2V0VGltZVBpY2tlclRlbXBsYXRlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIGhvdXJzVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItaG91cnMnKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAuYXBwZW5kKCQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJykpLFxyXG4gICAgICAgICAgICAgICAgICAgIG1pbnV0ZXNWaWV3ID0gJCgnPGRpdj4nKS5hZGRDbGFzcygndGltZXBpY2tlci1taW51dGVzJylcclxuICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZCgkKCc8dGFibGU+JykuYWRkQ2xhc3MoJ3RhYmxlLWNvbmRlbnNlZCcpKSxcclxuICAgICAgICAgICAgICAgICAgICBzZWNvbmRzVmlldyA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ3RpbWVwaWNrZXItc2Vjb25kcycpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQoJCgnPHRhYmxlPicpLmFkZENsYXNzKCd0YWJsZS1jb25kZW5zZWQnKSksXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0ID0gW2dldFRpbWVQaWNrZXJNYWluVGVtcGxhdGUoKV07XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGlzRW5hYmxlZCgnaCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0LnB1c2goaG91cnNWaWV3KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChpc0VuYWJsZWQoJ20nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldC5wdXNoKG1pbnV0ZXNWaWV3KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChpc0VuYWJsZWQoJ3MnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldC5wdXNoKHNlY29uZHNWaWV3KTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcmV0O1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgZ2V0VG9vbGJhciA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciByb3cgPSBbXTtcclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNob3dUb2RheUJ1dHRvbikge1xyXG4gICAgICAgICAgICAgICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7ICdkYXRhLWFjdGlvbic6ICd0b2RheScsICd0aXRsZSc6IG9wdGlvbnMudG9vbHRpcHMudG9kYXkgfSkuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKG9wdGlvbnMuaWNvbnMudG9kYXkpKSkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKCFvcHRpb25zLnNpZGVCeVNpZGUgJiYgaGFzRGF0ZSgpICYmIGhhc1RpbWUoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7ICdkYXRhLWFjdGlvbic6ICd0b2dnbGVQaWNrZXInLCAndGl0bGUnOiBvcHRpb25zLnRvb2x0aXBzLnNlbGVjdFRpbWUgfSkuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKG9wdGlvbnMuaWNvbnMudGltZSkpKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5zaG93Q2xlYXIpIHtcclxuICAgICAgICAgICAgICAgICAgICByb3cucHVzaCgkKCc8dGQ+JykuYXBwZW5kKCQoJzxhPicpLmF0dHIoeyAnZGF0YS1hY3Rpb24nOiAnY2xlYXInLCAndGl0bGUnOiBvcHRpb25zLnRvb2x0aXBzLmNsZWFyIH0pLmFwcGVuZCgkKCc8c3Bhbj4nKS5hZGRDbGFzcyhvcHRpb25zLmljb25zLmNsZWFyKSkpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNob3dDbG9zZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJvdy5wdXNoKCQoJzx0ZD4nKS5hcHBlbmQoJCgnPGE+JykuYXR0cih7ICdkYXRhLWFjdGlvbic6ICdjbG9zZScsICd0aXRsZSc6IG9wdGlvbnMudG9vbHRpcHMuY2xvc2UgfSkuYXBwZW5kKCQoJzxzcGFuPicpLmFkZENsYXNzKG9wdGlvbnMuaWNvbnMuY2xvc2UpKSkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICQoJzx0YWJsZT4nKS5hZGRDbGFzcygndGFibGUtY29uZGVuc2VkJykuYXBwZW5kKCQoJzx0Ym9keT4nKS5hcHBlbmQoJCgnPHRyPicpLmFwcGVuZChyb3cpKSk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBnZXRUZW1wbGF0ZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciB0ZW1wbGF0ZSA9ICQoJzxkaXY+JykuYWRkQ2xhc3MoJ2Jvb3RzdHJhcC1kYXRldGltZXBpY2tlci13aWRnZXQgZHJvcGRvd24tbWVudScpLFxyXG4gICAgICAgICAgICAgICAgICAgIGRhdGVWaWV3ID0gJCgnPGRpdj4nKS5hZGRDbGFzcygnZGF0ZXBpY2tlcicpLmFwcGVuZChnZXREYXRlUGlja2VyVGVtcGxhdGUoKSksXHJcbiAgICAgICAgICAgICAgICAgICAgdGltZVZpZXcgPSAkKCc8ZGl2PicpLmFkZENsYXNzKCd0aW1lcGlja2VyJykuYXBwZW5kKGdldFRpbWVQaWNrZXJUZW1wbGF0ZSgpKSxcclxuICAgICAgICAgICAgICAgICAgICBjb250ZW50ID0gJCgnPHVsPicpLmFkZENsYXNzKCdsaXN0LXVuc3R5bGVkJyksXHJcbiAgICAgICAgICAgICAgICAgICAgdG9vbGJhciA9ICQoJzxsaT4nKS5hZGRDbGFzcygncGlja2VyLXN3aXRjaCcgKyAob3B0aW9ucy5jb2xsYXBzZSA/ICcgYWNjb3JkaW9uLXRvZ2dsZScgOiAnJykpLmFwcGVuZChnZXRUb29sYmFyKCkpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmlubGluZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlLnJlbW92ZUNsYXNzKCdkcm9wZG93bi1tZW51Jyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHVzZTI0SG91cnMpIHtcclxuICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5hZGRDbGFzcygndXNldHdlbnR5Zm91cicpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChpc0VuYWJsZWQoJ3MnKSAmJiAhdXNlMjRIb3Vycykge1xyXG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFkZENsYXNzKCd3aWRlcicpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnNpZGVCeVNpZGUgJiYgaGFzRGF0ZSgpICYmIGhhc1RpbWUoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFkZENsYXNzKCd0aW1lcGlja2VyLXNicycpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICd0b3AnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBsYXRlLmFwcGVuZCh0b29sYmFyKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdGVtcGxhdGUuYXBwZW5kKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAkKCc8ZGl2PicpLmFkZENsYXNzKCdyb3cnKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLmFwcGVuZChkYXRlVmlldy5hZGRDbGFzcygnY29sLW1kLTYnKSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5hcHBlbmQodGltZVZpZXcuYWRkQ2xhc3MoJ2NvbC1tZC02JykpXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAnYm90dG9tJykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZW1wbGF0ZS5hcHBlbmQodG9vbGJhcik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0ZW1wbGF0ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy50b29sYmFyUGxhY2VtZW50ID09PSAndG9wJykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKHRvb2xiYXIpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKGhhc0RhdGUoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKCQoJzxsaT4nKS5hZGRDbGFzcygob3B0aW9ucy5jb2xsYXBzZSAmJiBoYXNUaW1lKCkgPyAnY29sbGFwc2UgaW4nIDogJycpKS5hcHBlbmQoZGF0ZVZpZXcpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICdkZWZhdWx0Jykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKHRvb2xiYXIpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKGhhc1RpbWUoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnRlbnQuYXBwZW5kKCQoJzxsaT4nKS5hZGRDbGFzcygob3B0aW9ucy5jb2xsYXBzZSAmJiBoYXNEYXRlKCkgPyAnY29sbGFwc2UnIDogJycpKS5hcHBlbmQodGltZVZpZXcpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQgPT09ICdib3R0b20nKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29udGVudC5hcHBlbmQodG9vbGJhcik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGVtcGxhdGUuYXBwZW5kKGNvbnRlbnQpO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgZGF0YVRvT3B0aW9ucyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciBlRGF0YSxcclxuICAgICAgICAgICAgICAgICAgICBkYXRhT3B0aW9ucyA9IHt9O1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmlzKCdpbnB1dCcpIHx8IG9wdGlvbnMuaW5saW5lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZURhdGEgPSBlbGVtZW50LmRhdGEoKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZURhdGEgPSBlbGVtZW50LmZpbmQoJ2lucHV0JykuZGF0YSgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChlRGF0YS5kYXRlT3B0aW9ucyAmJiBlRGF0YS5kYXRlT3B0aW9ucyBpbnN0YW5jZW9mIE9iamVjdCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGRhdGFPcHRpb25zID0gJC5leHRlbmQodHJ1ZSwgZGF0YU9wdGlvbnMsIGVEYXRhLmRhdGVPcHRpb25zKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAkLmVhY2gob3B0aW9ucywgZnVuY3Rpb24gKGtleSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBhdHRyaWJ1dGVOYW1lID0gJ2RhdGUnICsga2V5LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsga2V5LnNsaWNlKDEpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChlRGF0YVthdHRyaWJ1dGVOYW1lXSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFPcHRpb25zW2tleV0gPSBlRGF0YVthdHRyaWJ1dGVOYW1lXTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBkYXRhT3B0aW9ucztcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIHBsYWNlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIHBvc2l0aW9uID0gKGNvbXBvbmVudCB8fCBlbGVtZW50KS5wb3NpdGlvbigpLFxyXG4gICAgICAgICAgICAgICAgICAgIG9mZnNldCA9IChjb21wb25lbnQgfHwgZWxlbWVudCkub2Zmc2V0KCksXHJcbiAgICAgICAgICAgICAgICAgICAgdmVydGljYWwgPSBvcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsLFxyXG4gICAgICAgICAgICAgICAgICAgIGhvcml6b250YWwgPSBvcHRpb25zLndpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwsXHJcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50O1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLndpZGdldFBhcmVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudCA9IG9wdGlvbnMud2lkZ2V0UGFyZW50LmFwcGVuZCh3aWRnZXQpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlbGVtZW50LmlzKCdpbnB1dCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50ID0gZWxlbWVudC5hZnRlcih3aWRnZXQpLnBhcmVudCgpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmlubGluZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHBhcmVudCA9IGVsZW1lbnQuYXBwZW5kKHdpZGdldCk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBwYXJlbnQgPSBlbGVtZW50O1xyXG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuY2hpbGRyZW4oKS5maXJzdCgpLmFmdGVyKHdpZGdldCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gVG9wIGFuZCBib3R0b20gbG9naWNcclxuICAgICAgICAgICAgICAgIGlmICh2ZXJ0aWNhbCA9PT0gJ2F1dG8nKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG9mZnNldC50b3AgKyB3aWRnZXQuaGVpZ2h0KCkgKiAxLjUgPj0gJCh3aW5kb3cpLmhlaWdodCgpICsgJCh3aW5kb3cpLnNjcm9sbFRvcCgpICYmXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHdpZGdldC5oZWlnaHQoKSArIGVsZW1lbnQub3V0ZXJIZWlnaHQoKSA8IG9mZnNldC50b3ApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmVydGljYWwgPSAndG9wJztcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB2ZXJ0aWNhbCA9ICdib3R0b20nO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAvLyBMZWZ0IGFuZCByaWdodCBsb2dpY1xyXG4gICAgICAgICAgICAgICAgaWYgKGhvcml6b250YWwgPT09ICdhdXRvJykge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChwYXJlbnQud2lkdGgoKSA8IG9mZnNldC5sZWZ0ICsgd2lkZ2V0Lm91dGVyV2lkdGgoKSAvIDIgJiZcclxuICAgICAgICAgICAgICAgICAgICAgICAgb2Zmc2V0LmxlZnQgKyB3aWRnZXQub3V0ZXJXaWR0aCgpID4gJCh3aW5kb3cpLndpZHRoKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaG9yaXpvbnRhbCA9ICdyaWdodCc7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaG9yaXpvbnRhbCA9ICdsZWZ0JztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHZlcnRpY2FsID09PSAndG9wJykge1xyXG4gICAgICAgICAgICAgICAgICAgIHdpZGdldC5hZGRDbGFzcygndG9wJykucmVtb3ZlQ2xhc3MoJ2JvdHRvbScpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB3aWRnZXQuYWRkQ2xhc3MoJ2JvdHRvbScpLnJlbW92ZUNsYXNzKCd0b3AnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoaG9yaXpvbnRhbCA9PT0gJ3JpZ2h0Jykge1xyXG4gICAgICAgICAgICAgICAgICAgIHdpZGdldC5hZGRDbGFzcygncHVsbC1yaWdodCcpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB3aWRnZXQucmVtb3ZlQ2xhc3MoJ3B1bGwtcmlnaHQnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAvLyBmaW5kIHRoZSBmaXJzdCBwYXJlbnQgZWxlbWVudCB0aGF0IGhhcyBhIG5vbi1zdGF0aWMgY3NzIHBvc2l0aW9uaW5nXHJcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50LmNzcygncG9zaXRpb24nKSA9PT0gJ3N0YXRpYycpIHtcclxuICAgICAgICAgICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnQucGFyZW50cygpLmZpbHRlcihmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkKHRoaXMpLmNzcygncG9zaXRpb24nKSAhPT0gJ3N0YXRpYyc7XHJcbiAgICAgICAgICAgICAgICAgICAgfSkuZmlyc3QoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAocGFyZW50Lmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZGF0ZXRpbWVwaWNrZXIgY29tcG9uZW50IHNob3VsZCBiZSBwbGFjZWQgd2l0aGluIGEgbm9uLXN0YXRpYyBwb3NpdGlvbmVkIGNvbnRhaW5lcicpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHdpZGdldC5jc3Moe1xyXG4gICAgICAgICAgICAgICAgICAgIHRvcDogdmVydGljYWwgPT09ICd0b3AnID8gJ2F1dG8nIDogcG9zaXRpb24udG9wICsgZWxlbWVudC5vdXRlckhlaWdodCgpLFxyXG4gICAgICAgICAgICAgICAgICAgIGJvdHRvbTogdmVydGljYWwgPT09ICd0b3AnID8gcGFyZW50Lm91dGVySGVpZ2h0KCkgLSAocGFyZW50ID09PSBlbGVtZW50ID8gMCA6IHBvc2l0aW9uLnRvcCkgOiAnYXV0bycsXHJcbiAgICAgICAgICAgICAgICAgICAgbGVmdDogaG9yaXpvbnRhbCA9PT0gJ2xlZnQnID8gKHBhcmVudCA9PT0gZWxlbWVudCA/IDAgOiBwb3NpdGlvbi5sZWZ0KSA6ICdhdXRvJyxcclxuICAgICAgICAgICAgICAgICAgICByaWdodDogaG9yaXpvbnRhbCA9PT0gJ2xlZnQnID8gJ2F1dG8nIDogcGFyZW50Lm91dGVyV2lkdGgoKSAtIGVsZW1lbnQub3V0ZXJXaWR0aCgpIC0gKHBhcmVudCA9PT0gZWxlbWVudCA/IDAgOiBwb3NpdGlvbi5sZWZ0KVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBub3RpZnlFdmVudCA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZS50eXBlID09PSAnZHAuY2hhbmdlJyAmJiAoKGUuZGF0ZSAmJiBlLmRhdGUuaXNTYW1lKGUub2xkRGF0ZSkpIHx8ICghZS5kYXRlICYmICFlLm9sZERhdGUpKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGVsZW1lbnQudHJpZ2dlcihlKTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIHZpZXdVcGRhdGUgPSBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGUgPT09ICd5Jykge1xyXG4gICAgICAgICAgICAgICAgICAgIGUgPSAnWVlZWSc7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBub3RpZnlFdmVudCh7XHJcbiAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2RwLnVwZGF0ZScsXHJcbiAgICAgICAgICAgICAgICAgICAgY2hhbmdlOiBlLFxyXG4gICAgICAgICAgICAgICAgICAgIHZpZXdEYXRlOiB2aWV3RGF0ZS5jbG9uZSgpXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIHNob3dNb2RlID0gZnVuY3Rpb24gKGRpcikge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoZGlyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgobWluVmlld01vZGVOdW1iZXIsIE1hdGgubWluKDMsIGN1cnJlbnRWaWV3TW9kZSArIGRpcikpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgd2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyID4gZGl2JykuaGlkZSgpLmZpbHRlcignLmRhdGVwaWNrZXItJyArIGRhdGVQaWNrZXJNb2Rlc1tjdXJyZW50Vmlld01vZGVdLmNsc05hbWUpLnNob3coKTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGZpbGxEb3cgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgcm93ID0gJCgnPHRyPicpLFxyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnREYXRlID0gdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCd3Jykuc3RhcnRPZignZCcpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmNhbGVuZGFyV2Vla3MgPT09IHRydWUpIHtcclxuICAgICAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCQoJzx0aD4nKS5hZGRDbGFzcygnY3cnKS50ZXh0KCcjJykpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHdoaWxlIChjdXJyZW50RGF0ZS5pc0JlZm9yZSh2aWV3RGF0ZS5jbG9uZSgpLmVuZE9mKCd3JykpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcm93LmFwcGVuZCgkKCc8dGg+JykuYWRkQ2xhc3MoJ2RvdycpLnRleHQoY3VycmVudERhdGUuZm9ybWF0KCdkZCcpKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudERhdGUuYWRkKDEsICdkJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB3aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItZGF5cyB0aGVhZCcpLmFwcGVuZChyb3cpO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgaXNJbkRpc2FibGVkRGF0ZXMgPSBmdW5jdGlvbiAodGVzdERhdGUpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmRpc2FibGVkRGF0ZXNbdGVzdERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID09PSB0cnVlO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgaXNJbkVuYWJsZWREYXRlcyA9IGZ1bmN0aW9uICh0ZXN0RGF0ZSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMuZW5hYmxlZERhdGVzW3Rlc3REYXRlLmZvcm1hdCgnWVlZWS1NTS1ERCcpXSA9PT0gdHJ1ZTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGlzSW5EaXNhYmxlZEhvdXJzID0gZnVuY3Rpb24gKHRlc3REYXRlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5kaXNhYmxlZEhvdXJzW3Rlc3REYXRlLmZvcm1hdCgnSCcpXSA9PT0gdHJ1ZTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGlzSW5FbmFibGVkSG91cnMgPSBmdW5jdGlvbiAodGVzdERhdGUpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmVuYWJsZWRIb3Vyc1t0ZXN0RGF0ZS5mb3JtYXQoJ0gnKV0gPT09IHRydWU7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBpc1ZhbGlkID0gZnVuY3Rpb24gKHRhcmdldE1vbWVudCwgZ3JhbnVsYXJpdHkpIHtcclxuICAgICAgICAgICAgICAgIGlmICghdGFyZ2V0TW9tZW50LmlzVmFsaWQoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmRpc2FibGVkRGF0ZXMgJiYgZ3JhbnVsYXJpdHkgPT09ICdkJyAmJiBpc0luRGlzYWJsZWREYXRlcyh0YXJnZXRNb21lbnQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZW5hYmxlZERhdGVzICYmIGdyYW51bGFyaXR5ID09PSAnZCcgJiYgIWlzSW5FbmFibGVkRGF0ZXModGFyZ2V0TW9tZW50KSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLm1pbkRhdGUgJiYgdGFyZ2V0TW9tZW50LmlzQmVmb3JlKG9wdGlvbnMubWluRGF0ZSwgZ3JhbnVsYXJpdHkpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMubWF4RGF0ZSAmJiB0YXJnZXRNb21lbnQuaXNBZnRlcihvcHRpb25zLm1heERhdGUsIGdyYW51bGFyaXR5KSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCAmJiBncmFudWxhcml0eSA9PT0gJ2QnICYmIG9wdGlvbnMuZGF5c09mV2Vla0Rpc2FibGVkLmluZGV4T2YodGFyZ2V0TW9tZW50LmRheSgpKSAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5kaXNhYmxlZEhvdXJzICYmIChncmFudWxhcml0eSA9PT0gJ2gnIHx8IGdyYW51bGFyaXR5ID09PSAnbScgfHwgZ3JhbnVsYXJpdHkgPT09ICdzJykgJiYgaXNJbkRpc2FibGVkSG91cnModGFyZ2V0TW9tZW50KSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmVuYWJsZWRIb3VycyAmJiAoZ3JhbnVsYXJpdHkgPT09ICdoJyB8fCBncmFudWxhcml0eSA9PT0gJ20nIHx8IGdyYW51bGFyaXR5ID09PSAncycpICYmICFpc0luRW5hYmxlZEhvdXJzKHRhcmdldE1vbWVudCkpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgJiYgKGdyYW51bGFyaXR5ID09PSAnaCcgfHwgZ3JhbnVsYXJpdHkgPT09ICdtJyB8fCBncmFudWxhcml0eSA9PT0gJ3MnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBmb3VuZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICQuZWFjaChvcHRpb25zLmRpc2FibGVkVGltZUludGVydmFscywgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFyZ2V0TW9tZW50LmlzQmV0d2Vlbih0aGlzWzBdLCB0aGlzWzFdKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm91bmQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGZvdW5kKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGZpbGxNb250aHMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgc3BhbnMgPSBbXSxcclxuICAgICAgICAgICAgICAgICAgICBtb250aHNTaG9ydCA9IHZpZXdEYXRlLmNsb25lKCkuc3RhcnRPZigneScpLnN0YXJ0T2YoJ2QnKTtcclxuICAgICAgICAgICAgICAgIHdoaWxlIChtb250aHNTaG9ydC5pc1NhbWUodmlld0RhdGUsICd5JykpIHtcclxuICAgICAgICAgICAgICAgICAgICBzcGFucy5wdXNoKCQoJzxzcGFuPicpLmF0dHIoJ2RhdGEtYWN0aW9uJywgJ3NlbGVjdE1vbnRoJykuYWRkQ2xhc3MoJ21vbnRoJykudGV4dChtb250aHNTaG9ydC5mb3JtYXQoJ01NTScpKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgbW9udGhzU2hvcnQuYWRkKDEsICdNJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB3aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItbW9udGhzIHRkJykuZW1wdHkoKS5hcHBlbmQoc3BhbnMpO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgdXBkYXRlTW9udGhzID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIG1vbnRoc1ZpZXcgPSB3aWRnZXQuZmluZCgnLmRhdGVwaWNrZXItbW9udGhzJyksXHJcbiAgICAgICAgICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlciA9IG1vbnRoc1ZpZXcuZmluZCgndGgnKSxcclxuICAgICAgICAgICAgICAgICAgICBtb250aHMgPSBtb250aHNWaWV3LmZpbmQoJ3Rib2R5JykuZmluZCgnc3BhbicpO1xyXG5cclxuICAgICAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMCkuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgb3B0aW9ucy50b29sdGlwcy5wcmV2WWVhcik7XHJcbiAgICAgICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyLmVxKDEpLmF0dHIoJ3RpdGxlJywgb3B0aW9ucy50b29sdGlwcy5zZWxlY3RZZWFyKTtcclxuICAgICAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMikuZmluZCgnc3BhbicpLmF0dHIoJ3RpdGxlJywgb3B0aW9ucy50b29sdGlwcy5uZXh0WWVhcik7XHJcblxyXG4gICAgICAgICAgICAgICAgbW9udGhzVmlldy5maW5kKCcuZGlzYWJsZWQnKS5yZW1vdmVDbGFzcygnZGlzYWJsZWQnKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWQodmlld0RhdGUuY2xvbmUoKS5zdWJ0cmFjdCgxLCAneScpLCAneScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbW9udGhzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBtb250aHNWaWV3SGVhZGVyLmVxKDEpLnRleHQodmlld0RhdGUueWVhcigpKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWQodmlld0RhdGUuY2xvbmUoKS5hZGQoMSwgJ3knKSwgJ3knKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIG1vbnRoc1ZpZXdIZWFkZXIuZXEoMikuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbW9udGhzLnJlbW92ZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgICAgIGlmIChkYXRlLmlzU2FtZSh2aWV3RGF0ZSwgJ3knKSAmJiAhdW5zZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICBtb250aHMuZXEoZGF0ZS5tb250aCgpKS5hZGRDbGFzcygnYWN0aXZlJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbW9udGhzLmVhY2goZnVuY3Rpb24gKGluZGV4KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkKHZpZXdEYXRlLmNsb25lKCkubW9udGgoaW5kZXgpLCAnTScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICQodGhpcykuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICB1cGRhdGVZZWFycyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciB5ZWFyc1ZpZXcgPSB3aWRnZXQuZmluZCgnLmRhdGVwaWNrZXIteWVhcnMnKSxcclxuICAgICAgICAgICAgICAgICAgICB5ZWFyc1ZpZXdIZWFkZXIgPSB5ZWFyc1ZpZXcuZmluZCgndGgnKSxcclxuICAgICAgICAgICAgICAgICAgICBzdGFydFllYXIgPSB2aWV3RGF0ZS5jbG9uZSgpLnN1YnRyYWN0KDUsICd5JyksXHJcbiAgICAgICAgICAgICAgICAgICAgZW5kWWVhciA9IHZpZXdEYXRlLmNsb25lKCkuYWRkKDYsICd5JyksXHJcbiAgICAgICAgICAgICAgICAgICAgaHRtbCA9ICcnO1xyXG5cclxuICAgICAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgwKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCBvcHRpb25zLnRvb2x0aXBzLnByZXZEZWNhZGUpO1xyXG4gICAgICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDEpLmF0dHIoJ3RpdGxlJywgb3B0aW9ucy50b29sdGlwcy5zZWxlY3REZWNhZGUpO1xyXG4gICAgICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDIpLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIG9wdGlvbnMudG9vbHRpcHMubmV4dERlY2FkZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgeWVhcnNWaWV3LmZpbmQoJy5kaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLm1pbkRhdGUgJiYgb3B0aW9ucy5taW5EYXRlLmlzQWZ0ZXIoc3RhcnRZZWFyLCAneScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgeWVhcnNWaWV3SGVhZGVyLmVxKDApLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgxKS50ZXh0KHN0YXJ0WWVhci55ZWFyKCkgKyAnLScgKyBlbmRZZWFyLnllYXIoKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMubWF4RGF0ZSAmJiBvcHRpb25zLm1heERhdGUuaXNCZWZvcmUoZW5kWWVhciwgJ3knKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHllYXJzVmlld0hlYWRlci5lcSgyKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB3aGlsZSAoIXN0YXJ0WWVhci5pc0FmdGVyKGVuZFllYXIsICd5JykpIHtcclxuICAgICAgICAgICAgICAgICAgICBodG1sICs9ICc8c3BhbiBkYXRhLWFjdGlvbj1cInNlbGVjdFllYXJcIiBjbGFzcz1cInllYXInICsgKHN0YXJ0WWVhci5pc1NhbWUoZGF0ZSwgJ3knKSAmJiAhdW5zZXQgPyAnIGFjdGl2ZScgOiAnJykgKyAoIWlzVmFsaWQoc3RhcnRZZWFyLCAneScpID8gJyBkaXNhYmxlZCcgOiAnJykgKyAnXCI+JyArIHN0YXJ0WWVhci55ZWFyKCkgKyAnPC9zcGFuPic7XHJcbiAgICAgICAgICAgICAgICAgICAgc3RhcnRZZWFyLmFkZCgxLCAneScpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHllYXJzVmlldy5maW5kKCd0ZCcpLmh0bWwoaHRtbCk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICB1cGRhdGVEZWNhZGVzID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIGRlY2FkZXNWaWV3ID0gd2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyLWRlY2FkZXMnKSxcclxuICAgICAgICAgICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlciA9IGRlY2FkZXNWaWV3LmZpbmQoJ3RoJyksXHJcbiAgICAgICAgICAgICAgICAgICAgc3RhcnREZWNhZGUgPSBtb21lbnQoeyB5OiB2aWV3RGF0ZS55ZWFyKCkgLSAodmlld0RhdGUueWVhcigpICUgMTAwKSAtIDEgfSksXHJcbiAgICAgICAgICAgICAgICAgICAgZW5kRGVjYWRlID0gc3RhcnREZWNhZGUuY2xvbmUoKS5hZGQoMTAwLCAneScpLFxyXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0ZWRBdCA9IHN0YXJ0RGVjYWRlLmNsb25lKCksXHJcbiAgICAgICAgICAgICAgICAgICAgbWluRGF0ZURlY2FkZSA9IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgICAgIG1heERhdGVEZWNhZGUgPSBmYWxzZSxcclxuICAgICAgICAgICAgICAgICAgICBlbmREZWNhZGVZZWFyLFxyXG4gICAgICAgICAgICAgICAgICAgIGh0bWwgPSAnJztcclxuXHJcbiAgICAgICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgwKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCBvcHRpb25zLnRvb2x0aXBzLnByZXZDZW50dXJ5KTtcclxuICAgICAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyLmVxKDIpLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIG9wdGlvbnMudG9vbHRpcHMubmV4dENlbnR1cnkpO1xyXG5cclxuICAgICAgICAgICAgICAgIGRlY2FkZXNWaWV3LmZpbmQoJy5kaXNhYmxlZCcpLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChzdGFydERlY2FkZS5pc1NhbWUobW9tZW50KHsgeTogMTkwMCB9KSkgfHwgKG9wdGlvbnMubWluRGF0ZSAmJiBvcHRpb25zLm1pbkRhdGUuaXNBZnRlcihzdGFydERlY2FkZSwgJ3knKSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgwKS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgxKS50ZXh0KHN0YXJ0RGVjYWRlLnllYXIoKSArICctJyArIGVuZERlY2FkZS55ZWFyKCkpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChzdGFydERlY2FkZS5pc1NhbWUobW9tZW50KHsgeTogMjAwMCB9KSkgfHwgKG9wdGlvbnMubWF4RGF0ZSAmJiBvcHRpb25zLm1heERhdGUuaXNCZWZvcmUoZW5kRGVjYWRlLCAneScpKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGRlY2FkZXNWaWV3SGVhZGVyLmVxKDIpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHdoaWxlICghc3RhcnREZWNhZGUuaXNBZnRlcihlbmREZWNhZGUsICd5JykpIHtcclxuICAgICAgICAgICAgICAgICAgICBlbmREZWNhZGVZZWFyID0gc3RhcnREZWNhZGUueWVhcigpICsgMTI7XHJcbiAgICAgICAgICAgICAgICAgICAgbWluRGF0ZURlY2FkZSA9IG9wdGlvbnMubWluRGF0ZSAmJiBvcHRpb25zLm1pbkRhdGUuaXNBZnRlcihzdGFydERlY2FkZSwgJ3knKSAmJiBvcHRpb25zLm1pbkRhdGUueWVhcigpIDw9IGVuZERlY2FkZVllYXI7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF4RGF0ZURlY2FkZSA9IG9wdGlvbnMubWF4RGF0ZSAmJiBvcHRpb25zLm1heERhdGUuaXNBZnRlcihzdGFydERlY2FkZSwgJ3knKSAmJiBvcHRpb25zLm1heERhdGUueWVhcigpIDw9IGVuZERlY2FkZVllYXI7XHJcbiAgICAgICAgICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4gZGF0YS1hY3Rpb249XCJzZWxlY3REZWNhZGVcIiBjbGFzcz1cImRlY2FkZScgKyAoZGF0ZS5pc0FmdGVyKHN0YXJ0RGVjYWRlKSAmJiBkYXRlLnllYXIoKSA8PSBlbmREZWNhZGVZZWFyID8gJyBhY3RpdmUnIDogJycpICtcclxuICAgICAgICAgICAgICAgICAgICAgICAgKCFpc1ZhbGlkKHN0YXJ0RGVjYWRlLCAneScpICYmICFtaW5EYXRlRGVjYWRlICYmICFtYXhEYXRlRGVjYWRlID8gJyBkaXNhYmxlZCcgOiAnJykgKyAnXCIgZGF0YS1zZWxlY3Rpb249XCInICsgKHN0YXJ0RGVjYWRlLnllYXIoKSArIDYpICsgJ1wiPicgKyAoc3RhcnREZWNhZGUueWVhcigpICsgMSkgKyAnIC0gJyArIChzdGFydERlY2FkZS55ZWFyKCkgKyAxMikgKyAnPC9zcGFuPic7XHJcbiAgICAgICAgICAgICAgICAgICAgc3RhcnREZWNhZGUuYWRkKDEyLCAneScpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaHRtbCArPSAnPHNwYW4+PC9zcGFuPjxzcGFuPjwvc3Bhbj48c3Bhbj48L3NwYW4+JzsgLy9wdXNoIHRoZSBkYW5nbGluZyBibG9jayBvdmVyLCBhdCBsZWFzdCB0aGlzIHdheSBpdCdzIGV2ZW5cclxuXHJcbiAgICAgICAgICAgICAgICBkZWNhZGVzVmlldy5maW5kKCd0ZCcpLmh0bWwoaHRtbCk7XHJcbiAgICAgICAgICAgICAgICBkZWNhZGVzVmlld0hlYWRlci5lcSgxKS50ZXh0KChzdGFydGVkQXQueWVhcigpICsgMSkgKyAnLScgKyAoc3RhcnREZWNhZGUueWVhcigpKSk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBmaWxsRGF0ZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciBkYXlzVmlldyA9IHdpZGdldC5maW5kKCcuZGF0ZXBpY2tlci1kYXlzJyksXHJcbiAgICAgICAgICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIgPSBkYXlzVmlldy5maW5kKCd0aCcpLFxyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnREYXRlLFxyXG4gICAgICAgICAgICAgICAgICAgIGh0bWwgPSBbXSxcclxuICAgICAgICAgICAgICAgICAgICByb3csXHJcbiAgICAgICAgICAgICAgICAgICAgY2xzTmFtZXMgPSBbXSxcclxuICAgICAgICAgICAgICAgICAgICBpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICghaGFzRGF0ZSgpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDApLmZpbmQoJ3NwYW4nKS5hdHRyKCd0aXRsZScsIG9wdGlvbnMudG9vbHRpcHMucHJldk1vbnRoKTtcclxuICAgICAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDEpLmF0dHIoJ3RpdGxlJywgb3B0aW9ucy50b29sdGlwcy5zZWxlY3RNb250aCk7XHJcbiAgICAgICAgICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgyKS5maW5kKCdzcGFuJykuYXR0cigndGl0bGUnLCBvcHRpb25zLnRvb2x0aXBzLm5leHRNb250aCk7XHJcblxyXG4gICAgICAgICAgICAgICAgZGF5c1ZpZXcuZmluZCgnLmRpc2FibGVkJykucmVtb3ZlQ2xhc3MoJ2Rpc2FibGVkJyk7XHJcbiAgICAgICAgICAgICAgICBkYXlzVmlld0hlYWRlci5lcSgxKS50ZXh0KHZpZXdEYXRlLmZvcm1hdChvcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQpKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWQodmlld0RhdGUuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnTScpLCAnTScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGF5c1ZpZXdIZWFkZXIuZXEoMCkuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoIWlzVmFsaWQodmlld0RhdGUuY2xvbmUoKS5hZGQoMSwgJ00nKSwgJ00nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGRheXNWaWV3SGVhZGVyLmVxKDIpLmFkZENsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGN1cnJlbnREYXRlID0gdmlld0RhdGUuY2xvbmUoKS5zdGFydE9mKCdNJykuc3RhcnRPZigndycpLnN0YXJ0T2YoJ2QnKTtcclxuXHJcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNDI7IGkrKykgeyAvL2Fsd2F5cyBkaXNwbGF5IDQyIGRheXMgKHNob3VsZCBzaG93IDYgd2Vla3MpXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLndlZWtkYXkoKSA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByb3cgPSAkKCc8dHI+Jyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLmNhbGVuZGFyV2Vla3MpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvdy5hcHBlbmQoJzx0ZCBjbGFzcz1cImN3XCI+JyArIGN1cnJlbnREYXRlLndlZWsoKSArICc8L3RkPicpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGh0bWwucHVzaChyb3cpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBjbHNOYW1lcyA9IFsnZGF5J107XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmlzQmVmb3JlKHZpZXdEYXRlLCAnTScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsc05hbWVzLnB1c2goJ29sZCcpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVudERhdGUuaXNBZnRlcih2aWV3RGF0ZSwgJ00nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjbHNOYW1lcy5wdXNoKCduZXcnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmlzU2FtZShkYXRlLCAnZCcpICYmICF1bnNldCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjbHNOYW1lcy5wdXNoKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpc1ZhbGlkKGN1cnJlbnREYXRlLCAnZCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsc05hbWVzLnB1c2goJ2Rpc2FibGVkJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50RGF0ZS5pc1NhbWUoZ2V0TW9tZW50KCksICdkJykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xzTmFtZXMucHVzaCgndG9kYXknKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnREYXRlLmRheSgpID09PSAwIHx8IGN1cnJlbnREYXRlLmRheSgpID09PSA2KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsc05hbWVzLnB1c2goJ3dlZWtlbmQnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgbm90aWZ5RXZlbnQoe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZHAuY2xhc3NpZnknLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRlOiBjdXJyZW50RGF0ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NOYW1lczogY2xzTmFtZXNcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICByb3cuYXBwZW5kKCc8dGQgZGF0YS1hY3Rpb249XCJzZWxlY3REYXlcIiBkYXRhLWRheT1cIicgKyBjdXJyZW50RGF0ZS5mb3JtYXQoJ0wnKSArICdcIiBjbGFzcz1cIicgKyBjbHNOYW1lcy5qb2luKCcgJykgKyAnXCI+JyArIGN1cnJlbnREYXRlLmRhdGUoKSArICc8L3RkPicpO1xyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnREYXRlLmFkZCgxLCAnZCcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGRheXNWaWV3LmZpbmQoJ3Rib2R5JykuZW1wdHkoKS5hcHBlbmQoaHRtbCk7XHJcblxyXG4gICAgICAgICAgICAgICAgdXBkYXRlTW9udGhzKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgdXBkYXRlWWVhcnMoKTtcclxuXHJcbiAgICAgICAgICAgICAgICB1cGRhdGVEZWNhZGVzKCk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBmaWxsSG91cnMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdGFibGUgPSB3aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItaG91cnMgdGFibGUnKSxcclxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SG91ciA9IHZpZXdEYXRlLmNsb25lKCkuc3RhcnRPZignZCcpLFxyXG4gICAgICAgICAgICAgICAgICAgIGh0bWwgPSBbXSxcclxuICAgICAgICAgICAgICAgICAgICByb3cgPSAkKCc8dHI+Jyk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHZpZXdEYXRlLmhvdXIoKSA+IDExICYmICF1c2UyNEhvdXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudEhvdXIuaG91cigxMik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB3aGlsZSAoY3VycmVudEhvdXIuaXNTYW1lKHZpZXdEYXRlLCAnZCcpICYmICh1c2UyNEhvdXJzIHx8ICh2aWV3RGF0ZS5ob3VyKCkgPCAxMiAmJiBjdXJyZW50SG91ci5ob3VyKCkgPCAxMikgfHwgdmlld0RhdGUuaG91cigpID4gMTEpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRIb3VyLmhvdXIoKSAlIDQgPT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBodG1sLnB1c2gocm93KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGRhdGEtYWN0aW9uPVwic2VsZWN0SG91clwiIGNsYXNzPVwiaG91cicgKyAoIWlzVmFsaWQoY3VycmVudEhvdXIsICdoJykgPyAnIGRpc2FibGVkJyA6ICcnKSArICdcIj4nICsgY3VycmVudEhvdXIuZm9ybWF0KHVzZTI0SG91cnMgPyAnSEgnIDogJ2hoJykgKyAnPC90ZD4nKTtcclxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50SG91ci5hZGQoMSwgJ2gnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRhYmxlLmVtcHR5KCkuYXBwZW5kKGh0bWwpO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgZmlsbE1pbnV0ZXMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdGFibGUgPSB3aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItbWludXRlcyB0YWJsZScpLFxyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRNaW51dGUgPSB2aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ2gnKSxcclxuICAgICAgICAgICAgICAgICAgICBodG1sID0gW10sXHJcbiAgICAgICAgICAgICAgICAgICAgcm93ID0gJCgnPHRyPicpLFxyXG4gICAgICAgICAgICAgICAgICAgIHN0ZXAgPSBvcHRpb25zLnN0ZXBwaW5nID09PSAxID8gNSA6IG9wdGlvbnMuc3RlcHBpbmc7XHJcblxyXG4gICAgICAgICAgICAgICAgd2hpbGUgKHZpZXdEYXRlLmlzU2FtZShjdXJyZW50TWludXRlLCAnaCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRNaW51dGUubWludXRlKCkgJSAoc3RlcCAqIDQpID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvdyA9ICQoJzx0cj4nKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaHRtbC5wdXNoKHJvdyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHJvdy5hcHBlbmQoJzx0ZCBkYXRhLWFjdGlvbj1cInNlbGVjdE1pbnV0ZVwiIGNsYXNzPVwibWludXRlJyArICghaXNWYWxpZChjdXJyZW50TWludXRlLCAnbScpID8gJyBkaXNhYmxlZCcgOiAnJykgKyAnXCI+JyArIGN1cnJlbnRNaW51dGUuZm9ybWF0KCdtbScpICsgJzwvdGQ+Jyk7XHJcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudE1pbnV0ZS5hZGQoc3RlcCwgJ20nKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHRhYmxlLmVtcHR5KCkuYXBwZW5kKGh0bWwpO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgZmlsbFNlY29uZHMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdGFibGUgPSB3aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItc2Vjb25kcyB0YWJsZScpLFxyXG4gICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTZWNvbmQgPSB2aWV3RGF0ZS5jbG9uZSgpLnN0YXJ0T2YoJ20nKSxcclxuICAgICAgICAgICAgICAgICAgICBodG1sID0gW10sXHJcbiAgICAgICAgICAgICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xyXG5cclxuICAgICAgICAgICAgICAgIHdoaWxlICh2aWV3RGF0ZS5pc1NhbWUoY3VycmVudFNlY29uZCwgJ20nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50U2Vjb25kLnNlY29uZCgpICUgMjAgPT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcm93ID0gJCgnPHRyPicpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBodG1sLnB1c2gocm93KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgcm93LmFwcGVuZCgnPHRkIGRhdGEtYWN0aW9uPVwic2VsZWN0U2Vjb25kXCIgY2xhc3M9XCJzZWNvbmQnICsgKCFpc1ZhbGlkKGN1cnJlbnRTZWNvbmQsICdzJykgPyAnIGRpc2FibGVkJyA6ICcnKSArICdcIj4nICsgY3VycmVudFNlY29uZC5mb3JtYXQoJ3NzJykgKyAnPC90ZD4nKTtcclxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2Vjb25kLmFkZCg1LCAncycpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHRhYmxlLmVtcHR5KCkuYXBwZW5kKGh0bWwpO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgZmlsbFRpbWUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdG9nZ2xlLCBuZXdEYXRlLCB0aW1lQ29tcG9uZW50cyA9IHdpZGdldC5maW5kKCcudGltZXBpY2tlciBzcGFuW2RhdGEtdGltZS1jb21wb25lbnRdJyk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKCF1c2UyNEhvdXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdG9nZ2xlID0gd2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIFtkYXRhLWFjdGlvbj10b2dnbGVQZXJpb2RdJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgbmV3RGF0ZSA9IGRhdGUuY2xvbmUoKS5hZGQoKGRhdGUuaG91cnMoKSA+PSAxMikgPyAtMTIgOiAxMiwgJ2gnKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdG9nZ2xlLnRleHQoZGF0ZS5mb3JtYXQoJ0EnKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkKG5ld0RhdGUsICdoJykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdG9nZ2xlLnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvZ2dsZS5hZGRDbGFzcygnZGlzYWJsZWQnKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB0aW1lQ29tcG9uZW50cy5maWx0ZXIoJ1tkYXRhLXRpbWUtY29tcG9uZW50PWhvdXJzXScpLnRleHQoZGF0ZS5mb3JtYXQodXNlMjRIb3VycyA/ICdISCcgOiAnaGgnKSk7XHJcbiAgICAgICAgICAgICAgICB0aW1lQ29tcG9uZW50cy5maWx0ZXIoJ1tkYXRhLXRpbWUtY29tcG9uZW50PW1pbnV0ZXNdJykudGV4dChkYXRlLmZvcm1hdCgnbW0nKSk7XHJcbiAgICAgICAgICAgICAgICB0aW1lQ29tcG9uZW50cy5maWx0ZXIoJ1tkYXRhLXRpbWUtY29tcG9uZW50PXNlY29uZHNdJykudGV4dChkYXRlLmZvcm1hdCgnc3MnKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgZmlsbEhvdXJzKCk7XHJcbiAgICAgICAgICAgICAgICBmaWxsTWludXRlcygpO1xyXG4gICAgICAgICAgICAgICAgZmlsbFNlY29uZHMoKTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIHVwZGF0ZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIGlmICghd2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZmlsbERhdGUoKTtcclxuICAgICAgICAgICAgICAgIGZpbGxUaW1lKCk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBzZXRWYWx1ZSA9IGZ1bmN0aW9uICh0YXJnZXRNb21lbnQpIHtcclxuICAgICAgICAgICAgICAgIHZhciBvbGREYXRlID0gdW5zZXQgPyBudWxsIDogZGF0ZTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBjYXNlIG9mIGNhbGxpbmcgc2V0VmFsdWUobnVsbCBvciBmYWxzZSlcclxuICAgICAgICAgICAgICAgIGlmICghdGFyZ2V0TW9tZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdW5zZXQgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGlucHV0LnZhbCgnJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5kYXRhKCdkYXRlJywgJycpO1xyXG4gICAgICAgICAgICAgICAgICAgIG5vdGlmeUV2ZW50KHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2RwLmNoYW5nZScsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHRhcmdldE1vbWVudCA9IHRhcmdldE1vbWVudC5jbG9uZSgpLmxvY2FsZShvcHRpb25zLmxvY2FsZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGhhc1RpbWVab25lKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRNb21lbnQudHoob3B0aW9ucy50aW1lWm9uZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuc3RlcHBpbmcgIT09IDEpIHtcclxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRNb21lbnQubWludXRlcygoTWF0aC5yb3VuZCh0YXJnZXRNb21lbnQubWludXRlcygpIC8gb3B0aW9ucy5zdGVwcGluZykgKiBvcHRpb25zLnN0ZXBwaW5nKSkuc2Vjb25kcygwKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKG9wdGlvbnMubWluRGF0ZSAmJiB0YXJnZXRNb21lbnQuaXNCZWZvcmUob3B0aW9ucy5taW5EYXRlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXRNb21lbnQuYWRkKG9wdGlvbnMuc3RlcHBpbmcsICdtaW51dGVzJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkKHRhcmdldE1vbWVudCkpIHtcclxuICAgICAgICAgICAgICAgICAgICBkYXRlID0gdGFyZ2V0TW9tZW50O1xyXG4gICAgICAgICAgICAgICAgICAgIHZpZXdEYXRlID0gZGF0ZS5jbG9uZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlucHV0LnZhbChkYXRlLmZvcm1hdChhY3R1YWxGb3JtYXQpKTtcclxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50LmRhdGEoJ2RhdGUnLCBkYXRlLmZvcm1hdChhY3R1YWxGb3JtYXQpKTtcclxuICAgICAgICAgICAgICAgICAgICB1bnNldCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIG5vdGlmeUV2ZW50KHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2RwLmNoYW5nZScsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IGRhdGUuY2xvbmUoKSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgb2xkRGF0ZTogb2xkRGF0ZVxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbnMua2VlcEludmFsaWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXQudmFsKHVuc2V0ID8gJycgOiBkYXRlLmZvcm1hdChhY3R1YWxGb3JtYXQpKTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBub3RpZnlFdmVudCh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZHAuY2hhbmdlJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRhdGU6IHRhcmdldE1vbWVudCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9sZERhdGU6IG9sZERhdGVcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIG5vdGlmeUV2ZW50KHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ2RwLmVycm9yJyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0ZTogdGFyZ2V0TW9tZW50LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvbGREYXRlOiBvbGREYXRlXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogSGlkZXMgdGhlIHdpZGdldC4gUG9zc2libHkgd2lsbCBlbWl0IGRwLmhpZGVcclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIGhpZGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdHJhbnNpdGlvbmluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgaWYgKCF3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy8gSWdub3JlIGV2ZW50IGlmIGluIHRoZSBtaWRkbGUgb2YgYSBwaWNrZXIgdHJhbnNpdGlvblxyXG4gICAgICAgICAgICAgICAgd2lkZ2V0LmZpbmQoJy5jb2xsYXBzZScpLmVhY2goZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBjb2xsYXBzZURhdGEgPSAkKHRoaXMpLmRhdGEoJ2NvbGxhcHNlJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGNvbGxhcHNlRGF0YSAmJiBjb2xsYXBzZURhdGEudHJhbnNpdGlvbmluZykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2l0aW9uaW5nID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgaWYgKHRyYW5zaXRpb25pbmcpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKGNvbXBvbmVudCAmJiBjb21wb25lbnQuaGFzQ2xhc3MoJ2J0bicpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50LnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHdpZGdldC5oaWRlKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgJCh3aW5kb3cpLm9mZigncmVzaXplJywgcGxhY2UpO1xyXG4gICAgICAgICAgICAgICAgd2lkZ2V0Lm9mZignY2xpY2snLCAnW2RhdGEtYWN0aW9uXScpO1xyXG4gICAgICAgICAgICAgICAgd2lkZ2V0Lm9mZignbW91c2Vkb3duJywgZmFsc2UpO1xyXG5cclxuICAgICAgICAgICAgICAgIHdpZGdldC5yZW1vdmUoKTtcclxuICAgICAgICAgICAgICAgIHdpZGdldCA9IGZhbHNlO1xyXG5cclxuICAgICAgICAgICAgICAgIG5vdGlmeUV2ZW50KHtcclxuICAgICAgICAgICAgICAgICAgICB0eXBlOiAnZHAuaGlkZScsXHJcbiAgICAgICAgICAgICAgICAgICAgZGF0ZTogZGF0ZS5jbG9uZSgpXHJcbiAgICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICBpbnB1dC5ibHVyKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgdmlld0RhdGUgPSBkYXRlLmNsb25lKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGNsZWFyID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgc2V0VmFsdWUobnVsbCk7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBwYXJzZUlucHV0RGF0ZSA9IGZ1bmN0aW9uIChpbnB1dERhdGUpIHtcclxuICAgICAgICAgICAgICAgIGlmIChvcHRpb25zLnBhcnNlSW5wdXREYXRlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIW1vbWVudC5pc01vbWVudChpbnB1dERhdGUpIHx8IGlucHV0RGF0ZSBpbnN0YW5jZW9mIERhdGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXREYXRlID0gZ2V0TW9tZW50KGlucHV0RGF0ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpbnB1dERhdGUgPSBvcHRpb25zLnBhcnNlSW5wdXREYXRlKGlucHV0RGF0ZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAvL2lucHV0RGF0ZS5sb2NhbGUob3B0aW9ucy5sb2NhbGUpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGlucHV0RGF0ZTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICAgICAgICAgKlxyXG4gICAgICAgICAgICAgKiBXaWRnZXQgVUkgaW50ZXJhY3Rpb24gZnVuY3Rpb25zXHJcbiAgICAgICAgICAgICAqXHJcbiAgICAgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuICAgICAgICAgICAgYWN0aW9ucyA9IHtcclxuICAgICAgICAgICAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbmF2Rm5jID0gZGF0ZVBpY2tlck1vZGVzW2N1cnJlbnRWaWV3TW9kZV0ubmF2Rm5jO1xyXG4gICAgICAgICAgICAgICAgICAgIHZpZXdEYXRlLmFkZChkYXRlUGlja2VyTW9kZXNbY3VycmVudFZpZXdNb2RlXS5uYXZTdGVwLCBuYXZGbmMpO1xyXG4gICAgICAgICAgICAgICAgICAgIGZpbGxEYXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdmlld1VwZGF0ZShuYXZGbmMpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICBwcmV2aW91czogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBuYXZGbmMgPSBkYXRlUGlja2VyTW9kZXNbY3VycmVudFZpZXdNb2RlXS5uYXZGbmM7XHJcbiAgICAgICAgICAgICAgICAgICAgdmlld0RhdGUuc3VidHJhY3QoZGF0ZVBpY2tlck1vZGVzW2N1cnJlbnRWaWV3TW9kZV0ubmF2U3RlcCwgbmF2Rm5jKTtcclxuICAgICAgICAgICAgICAgICAgICBmaWxsRGF0ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIHZpZXdVcGRhdGUobmF2Rm5jKTtcclxuICAgICAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAgICAgcGlja2VyU3dpdGNoOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc2hvd01vZGUoMSk7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIHNlbGVjdE1vbnRoOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBtb250aCA9ICQoZS50YXJnZXQpLmNsb3Nlc3QoJ3Rib2R5JykuZmluZCgnc3BhbicpLmluZGV4KCQoZS50YXJnZXQpKTtcclxuICAgICAgICAgICAgICAgICAgICB2aWV3RGF0ZS5tb250aChtb250aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWaWV3TW9kZSA9PT0gbWluVmlld01vZGVOdW1iZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VmFsdWUoZGF0ZS5jbG9uZSgpLnllYXIodmlld0RhdGUueWVhcigpKS5tb250aCh2aWV3RGF0ZS5tb250aCgpKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucy5pbmxpbmUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dNb2RlKC0xKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsbERhdGUoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdmlld1VwZGF0ZSgnTScpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICBzZWxlY3RZZWFyOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gcGFyc2VJbnQoJChlLnRhcmdldCkudGV4dCgpLCAxMCkgfHwgMDtcclxuICAgICAgICAgICAgICAgICAgICB2aWV3RGF0ZS55ZWFyKHllYXIpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChjdXJyZW50Vmlld01vZGUgPT09IG1pblZpZXdNb2RlTnVtYmVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlKGRhdGUuY2xvbmUoKS55ZWFyKHZpZXdEYXRlLnllYXIoKSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW9wdGlvbnMuaW5saW5lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoaWRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzaG93TW9kZSgtMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGxEYXRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHZpZXdVcGRhdGUoJ1lZWVknKTtcclxuICAgICAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAgICAgc2VsZWN0RGVjYWRlOiBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciB5ZWFyID0gcGFyc2VJbnQoJChlLnRhcmdldCkuZGF0YSgnc2VsZWN0aW9uJyksIDEwKSB8fCAwO1xyXG4gICAgICAgICAgICAgICAgICAgIHZpZXdEYXRlLnllYXIoeWVhcik7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWaWV3TW9kZSA9PT0gbWluVmlld01vZGVOdW1iZXIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VmFsdWUoZGF0ZS5jbG9uZSgpLnllYXIodmlld0RhdGUueWVhcigpKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucy5pbmxpbmUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZGUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dNb2RlKC0xKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZmlsbERhdGUoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgdmlld1VwZGF0ZSgnWVlZWScpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICBzZWxlY3REYXk6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGRheSA9IHZpZXdEYXRlLmNsb25lKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCQoZS50YXJnZXQpLmlzKCcub2xkJykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGF5LnN1YnRyYWN0KDEsICdNJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGlmICgkKGUudGFyZ2V0KS5pcygnLm5ldycpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRheS5hZGQoMSwgJ00nKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgc2V0VmFsdWUoZGF5LmRhdGUocGFyc2VJbnQoJChlLnRhcmdldCkudGV4dCgpLCAxMCkpKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIWhhc1RpbWUoKSAmJiAhb3B0aW9ucy5rZWVwT3BlbiAmJiAhb3B0aW9ucy5pbmxpbmUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaGlkZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAgICAgaW5jcmVtZW50SG91cnM6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3RGF0ZSA9IGRhdGUuY2xvbmUoKS5hZGQoMSwgJ2gnKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZChuZXdEYXRlLCAnaCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlKG5ld0RhdGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAgICAgaW5jcmVtZW50TWludXRlczogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdEYXRlID0gZGF0ZS5jbG9uZSgpLmFkZChvcHRpb25zLnN0ZXBwaW5nLCAnbScpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkKG5ld0RhdGUsICdtJykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VmFsdWUobmV3RGF0ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICBpbmNyZW1lbnRTZWNvbmRzOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0RhdGUgPSBkYXRlLmNsb25lKCkuYWRkKDEsICdzJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWQobmV3RGF0ZSwgJ3MnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShuZXdEYXRlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIGRlY3JlbWVudEhvdXJzOiBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld0RhdGUgPSBkYXRlLmNsb25lKCkuc3VidHJhY3QoMSwgJ2gnKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZChuZXdEYXRlLCAnaCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlKG5ld0RhdGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAgICAgZGVjcmVtZW50TWludXRlczogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBuZXdEYXRlID0gZGF0ZS5jbG9uZSgpLnN1YnRyYWN0KG9wdGlvbnMuc3RlcHBpbmcsICdtJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWQobmV3RGF0ZSwgJ20nKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShuZXdEYXRlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIGRlY3JlbWVudFNlY29uZHM6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3RGF0ZSA9IGRhdGUuY2xvbmUoKS5zdWJ0cmFjdCgxLCAncycpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ZhbGlkKG5ld0RhdGUsICdzJykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VmFsdWUobmV3RGF0ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICB0b2dnbGVQZXJpb2Q6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShkYXRlLmNsb25lKCkuYWRkKChkYXRlLmhvdXJzKCkgPj0gMTIpID8gLTEyIDogMTIsICdoJykpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICB0b2dnbGVQaWNrZXI6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyICR0aGlzID0gJChlLnRhcmdldCksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICRwYXJlbnQgPSAkdGhpcy5jbG9zZXN0KCd1bCcpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBleHBhbmRlZCA9ICRwYXJlbnQuZmluZCgnLmluJyksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlZCA9ICRwYXJlbnQuZmluZCgnLmNvbGxhcHNlOm5vdCguaW4pJyksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbGxhcHNlRGF0YTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGV4cGFuZGVkICYmIGV4cGFuZGVkLmxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb2xsYXBzZURhdGEgPSBleHBhbmRlZC5kYXRhKCdjb2xsYXBzZScpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29sbGFwc2VEYXRhICYmIGNvbGxhcHNlRGF0YS50cmFuc2l0aW9uaW5nKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGV4cGFuZGVkLmNvbGxhcHNlKSB7IC8vIGlmIGNvbGxhcHNlIHBsdWdpbiBpcyBhdmFpbGFibGUgdGhyb3VnaCBib290c3RyYXAuanMgdGhlbiB1c2UgaXRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGFuZGVkLmNvbGxhcHNlKCdoaWRlJyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbG9zZWQuY29sbGFwc2UoJ3Nob3cnKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gb3RoZXJ3aXNlIGp1c3QgdG9nZ2xlIGluIGNsYXNzIG9uIHRoZSB0d28gdmlld3NcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cGFuZGVkLnJlbW92ZUNsYXNzKCdpbicpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VkLmFkZENsYXNzKCdpbicpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkdGhpcy5pcygnc3BhbicpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy50b2dnbGVDbGFzcyhvcHRpb25zLmljb25zLnRpbWUgKyAnICcgKyBvcHRpb25zLmljb25zLmRhdGUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMuZmluZCgnc3BhbicpLnRvZ2dsZUNsYXNzKG9wdGlvbnMuaWNvbnMudGltZSArICcgJyArIG9wdGlvbnMuaWNvbnMuZGF0ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5PVEU6IHVuY29tbWVudCBpZiB0b2dnbGVkIHN0YXRlIHdpbGwgYmUgcmVzdG9yZWQgaW4gc2hvdygpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vaWYgKGNvbXBvbmVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyAgICBjb21wb25lbnQuZmluZCgnc3BhbicpLnRvZ2dsZUNsYXNzKG9wdGlvbnMuaWNvbnMudGltZSArICcgJyArIG9wdGlvbnMuaWNvbnMuZGF0ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAgICAgc2hvd1BpY2tlcjogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHdpZGdldC5maW5kKCcudGltZXBpY2tlciA+IGRpdjpub3QoLnRpbWVwaWNrZXItcGlja2VyKScpLmhpZGUoKTtcclxuICAgICAgICAgICAgICAgICAgICB3aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuc2hvdygpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICBzaG93SG91cnM6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICB3aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuaGlkZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIHdpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1ob3VycycpLnNob3coKTtcclxuICAgICAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAgICAgc2hvd01pbnV0ZXM6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgICAgICB3aWRnZXQuZmluZCgnLnRpbWVwaWNrZXIgLnRpbWVwaWNrZXItcGlja2VyJykuaGlkZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIHdpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1taW51dGVzJykuc2hvdygpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgICAgICBzaG93U2Vjb25kczogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHdpZGdldC5maW5kKCcudGltZXBpY2tlciAudGltZXBpY2tlci1waWNrZXInKS5oaWRlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgd2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyIC50aW1lcGlja2VyLXNlY29uZHMnKS5zaG93KCk7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIHNlbGVjdEhvdXI6IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIGhvdXIgPSBwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF1c2UyNEhvdXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkYXRlLmhvdXJzKCkgPj0gMTIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChob3VyICE9PSAxMikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhvdXIgKz0gMTI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaG91ciA9PT0gMTIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBob3VyID0gMDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShkYXRlLmNsb25lKCkuaG91cnMoaG91cikpO1xyXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbnMuc2hvd1BpY2tlci5jYWxsKHBpY2tlcik7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIHNlbGVjdE1pbnV0ZTogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShkYXRlLmNsb25lKCkubWludXRlcyhwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbnMuc2hvd1BpY2tlci5jYWxsKHBpY2tlcik7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIHNlbGVjdFNlY29uZDogZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShkYXRlLmNsb25lKCkuc2Vjb25kcyhwYXJzZUludCgkKGUudGFyZ2V0KS50ZXh0KCksIDEwKSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIGFjdGlvbnMuc2hvd1BpY2tlci5jYWxsKHBpY2tlcik7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIGNsZWFyOiBjbGVhcixcclxuXHJcbiAgICAgICAgICAgICAgICB0b2RheTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciB0b2RheXNEYXRlID0gZ2V0TW9tZW50KCk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWQodG9kYXlzRGF0ZSwgJ2QnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZSh0b2RheXNEYXRlKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgICAgIGNsb3NlOiBoaWRlXHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBkb0FjdGlvbiA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoJChlLmN1cnJlbnRUYXJnZXQpLmlzKCcuZGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGFjdGlvbnNbJChlLmN1cnJlbnRUYXJnZXQpLmRhdGEoJ2FjdGlvbicpXS5hcHBseShwaWNrZXIsIGFyZ3VtZW50cyk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICAvKipcclxuICAgICAgICAgICAgICogU2hvd3MgdGhlIHdpZGdldC4gUG9zc2libHkgd2lsbCBlbWl0IGRwLnNob3cgYW5kIGRwLmNoYW5nZVxyXG4gICAgICAgICAgICAgKi9cclxuICAgICAgICAgICAgc2hvdyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciBjdXJyZW50TW9tZW50LFxyXG4gICAgICAgICAgICAgICAgICAgIHVzZUN1cnJlbnRHcmFudWxhcml0eSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ3llYXInOiBmdW5jdGlvbiAobSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG0ubW9udGgoMCkuZGF0ZSgxKS5ob3VycygwKS5zZWNvbmRzKDApLm1pbnV0ZXMoMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICdtb250aCc6IGZ1bmN0aW9uIChtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbS5kYXRlKDEpLmhvdXJzKDApLnNlY29uZHMoMCkubWludXRlcygwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ2RheSc6IGZ1bmN0aW9uIChtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbS5ob3VycygwKS5zZWNvbmRzKDApLm1pbnV0ZXMoMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICdob3VyJzogZnVuY3Rpb24gKG0pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBtLnNlY29uZHMoMCkubWludXRlcygwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ21pbnV0ZSc6IGZ1bmN0aW9uIChtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbS5zZWNvbmRzKDApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoaW5wdXQucHJvcCgnZGlzYWJsZWQnKSB8fCAoIW9wdGlvbnMuaWdub3JlUmVhZG9ubHkgJiYgaW5wdXQucHJvcCgncmVhZG9ubHknKSkgfHwgd2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChpbnB1dC52YWwoKSAhPT0gdW5kZWZpbmVkICYmIGlucHV0LnZhbCgpLnRyaW0oKS5sZW5ndGggIT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZShwYXJzZUlucHV0RGF0ZShpbnB1dC52YWwoKS50cmltKCkpKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodW5zZXQgJiYgb3B0aW9ucy51c2VDdXJyZW50ICYmIChvcHRpb25zLmlubGluZSB8fCAoaW5wdXQuaXMoJ2lucHV0JykgJiYgaW5wdXQudmFsKCkudHJpbSgpLmxlbmd0aCA9PT0gMCkpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudE1vbWVudCA9IGdldE1vbWVudCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb3B0aW9ucy51c2VDdXJyZW50ID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50TW9tZW50ID0gdXNlQ3VycmVudEdyYW51bGFyaXR5W29wdGlvbnMudXNlQ3VycmVudF0oY3VycmVudE1vbWVudCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHNldFZhbHVlKGN1cnJlbnRNb21lbnQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgd2lkZ2V0ID0gZ2V0VGVtcGxhdGUoKTtcclxuXHJcbiAgICAgICAgICAgICAgICBmaWxsRG93KCk7XHJcbiAgICAgICAgICAgICAgICBmaWxsTW9udGhzKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgd2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyLWhvdXJzJykuaGlkZSgpO1xyXG4gICAgICAgICAgICAgICAgd2lkZ2V0LmZpbmQoJy50aW1lcGlja2VyLW1pbnV0ZXMnKS5oaWRlKCk7XHJcbiAgICAgICAgICAgICAgICB3aWRnZXQuZmluZCgnLnRpbWVwaWNrZXItc2Vjb25kcycpLmhpZGUoKTtcclxuXHJcbiAgICAgICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgICAgIHNob3dNb2RlKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgJCh3aW5kb3cpLm9uKCdyZXNpemUnLCBwbGFjZSk7XHJcbiAgICAgICAgICAgICAgICB3aWRnZXQub24oJ2NsaWNrJywgJ1tkYXRhLWFjdGlvbl0nLCBkb0FjdGlvbik7IC8vIHRoaXMgaGFuZGxlcyBjbGlja3Mgb24gdGhlIHdpZGdldFxyXG4gICAgICAgICAgICAgICAgd2lkZ2V0Lm9uKCdtb3VzZWRvd24nLCBmYWxzZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGNvbXBvbmVudCAmJiBjb21wb25lbnQuaGFzQ2xhc3MoJ2J0bicpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50LnRvZ2dsZUNsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHBsYWNlKCk7XHJcbiAgICAgICAgICAgICAgICB3aWRnZXQuc2hvdygpO1xyXG4gICAgICAgICAgICAgICAgaWYgKG9wdGlvbnMuZm9jdXNPblNob3cgJiYgIWlucHV0LmlzKCc6Zm9jdXMnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGlucHV0LmZvY3VzKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbm90aWZ5RXZlbnQoe1xyXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkcC5zaG93J1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgLyoqXHJcbiAgICAgICAgICAgICAqIFNob3dzIG9yIGhpZGVzIHRoZSB3aWRnZXRcclxuICAgICAgICAgICAgICovXHJcbiAgICAgICAgICAgIHRvZ2dsZSA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAod2lkZ2V0ID8gaGlkZSgpIDogc2hvdygpKTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGtleWRvd24gPSBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAgICAgdmFyIGhhbmRsZXIgPSBudWxsLFxyXG4gICAgICAgICAgICAgICAgICAgIGluZGV4LFxyXG4gICAgICAgICAgICAgICAgICAgIGluZGV4MixcclxuICAgICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5cyA9IFtdLFxyXG4gICAgICAgICAgICAgICAgICAgIHByZXNzZWRNb2RpZmllcnMgPSB7fSxcclxuICAgICAgICAgICAgICAgICAgICBjdXJyZW50S2V5ID0gZS53aGljaCxcclxuICAgICAgICAgICAgICAgICAgICBrZXlCaW5kS2V5cyxcclxuICAgICAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkLFxyXG4gICAgICAgICAgICAgICAgICAgIHByZXNzZWQgPSAncCc7XHJcblxyXG4gICAgICAgICAgICAgICAga2V5U3RhdGVbY3VycmVudEtleV0gPSBwcmVzc2VkO1xyXG5cclxuICAgICAgICAgICAgICAgIGZvciAoaW5kZXggaW4ga2V5U3RhdGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoa2V5U3RhdGUuaGFzT3duUHJvcGVydHkoaW5kZXgpICYmIGtleVN0YXRlW2luZGV4XSA9PT0gcHJlc3NlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwcmVzc2VkS2V5cy5wdXNoKGluZGV4KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBhcnNlSW50KGluZGV4LCAxMCkgIT09IGN1cnJlbnRLZXkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByZXNzZWRNb2RpZmllcnNbaW5kZXhdID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBmb3IgKGluZGV4IGluIG9wdGlvbnMua2V5QmluZHMpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9ucy5rZXlCaW5kcy5oYXNPd25Qcm9wZXJ0eShpbmRleCkgJiYgdHlwZW9mIChvcHRpb25zLmtleUJpbmRzW2luZGV4XSkgPT09ICdmdW5jdGlvbicpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAga2V5QmluZEtleXMgPSBpbmRleC5zcGxpdCgnICcpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoa2V5QmluZEtleXMubGVuZ3RoID09PSBwcmVzc2VkS2V5cy5sZW5ndGggJiYga2V5TWFwW2N1cnJlbnRLZXldID09PSBrZXlCaW5kS2V5c1trZXlCaW5kS2V5cy5sZW5ndGggLSAxXSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWxsTW9kaWZpZXJzUHJlc3NlZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGluZGV4MiA9IGtleUJpbmRLZXlzLmxlbmd0aCAtIDI7IGluZGV4MiA+PSAwOyBpbmRleDItLSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghKGtleU1hcFtrZXlCaW5kS2V5c1tpbmRleDJdXSBpbiBwcmVzc2VkTW9kaWZpZXJzKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbGxNb2RpZmllcnNQcmVzc2VkID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbGxNb2RpZmllcnNQcmVzc2VkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGFuZGxlciA9IG9wdGlvbnMua2V5QmluZHNbaW5kZXhdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChoYW5kbGVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaGFuZGxlci5jYWxsKHBpY2tlciwgd2lkZ2V0KTtcclxuICAgICAgICAgICAgICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGtleXVwID0gZnVuY3Rpb24gKGUpIHtcclxuICAgICAgICAgICAgICAgIGtleVN0YXRlW2Uud2hpY2hdID0gJ3InO1xyXG4gICAgICAgICAgICAgICAgZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGNoYW5nZSA9IGZ1bmN0aW9uIChlKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgdmFsID0gJChlLnRhcmdldCkudmFsKCkudHJpbSgpLFxyXG4gICAgICAgICAgICAgICAgICAgIHBhcnNlZERhdGUgPSB2YWwgPyBwYXJzZUlucHV0RGF0ZSh2YWwpIDogbnVsbDtcclxuICAgICAgICAgICAgICAgIHNldFZhbHVlKHBhcnNlZERhdGUpO1xyXG4gICAgICAgICAgICAgICAgZS5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24oKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfSxcclxuXHJcbiAgICAgICAgICAgIGF0dGFjaERhdGVQaWNrZXJFbGVtZW50RXZlbnRzID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgaW5wdXQub24oe1xyXG4gICAgICAgICAgICAgICAgICAgICdjaGFuZ2UnOiBjaGFuZ2UsXHJcbiAgICAgICAgICAgICAgICAgICAgJ2JsdXInOiBvcHRpb25zLmRlYnVnID8gJycgOiBoaWRlLFxyXG4gICAgICAgICAgICAgICAgICAgICdrZXlkb3duJzoga2V5ZG93bixcclxuICAgICAgICAgICAgICAgICAgICAna2V5dXAnOiBrZXl1cCxcclxuICAgICAgICAgICAgICAgICAgICAnZm9jdXMnOiBvcHRpb25zLmFsbG93SW5wdXRUb2dnbGUgPyBzaG93IDogJydcclxuICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmlzKCdpbnB1dCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQub24oe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAnZm9jdXMnOiBzaG93XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGNvbXBvbmVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudC5vbignY2xpY2snLCB0b2dnbGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbXBvbmVudC5vbignbW91c2Vkb3duJywgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgZGV0YWNoRGF0ZVBpY2tlckVsZW1lbnRFdmVudHMgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICBpbnB1dC5vZmYoe1xyXG4gICAgICAgICAgICAgICAgICAgICdjaGFuZ2UnOiBjaGFuZ2UsXHJcbiAgICAgICAgICAgICAgICAgICAgJ2JsdXInOiBibHVyLFxyXG4gICAgICAgICAgICAgICAgICAgICdrZXlkb3duJzoga2V5ZG93bixcclxuICAgICAgICAgICAgICAgICAgICAna2V5dXAnOiBrZXl1cCxcclxuICAgICAgICAgICAgICAgICAgICAnZm9jdXMnOiBvcHRpb25zLmFsbG93SW5wdXRUb2dnbGUgPyBoaWRlIDogJydcclxuICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LmlzKCdpbnB1dCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQub2ZmKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgJ2ZvY3VzJzogc2hvd1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChjb21wb25lbnQpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb21wb25lbnQub2ZmKCdjbGljaycsIHRvZ2dsZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29tcG9uZW50Lm9mZignbW91c2Vkb3duJywgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgaW5kZXhHaXZlbkRhdGVzID0gZnVuY3Rpb24gKGdpdmVuRGF0ZXNBcnJheSkge1xyXG4gICAgICAgICAgICAgICAgLy8gU3RvcmUgZ2l2ZW4gZW5hYmxlZERhdGVzIGFuZCBkaXNhYmxlZERhdGVzIGFzIGtleXMuXHJcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHdheSB3ZSBjYW4gY2hlY2sgdGhlaXIgZXhpc3RlbmNlIGluIE8oMSkgdGltZSBpbnN0ZWFkIG9mIGxvb3BpbmcgdGhyb3VnaCB3aG9sZSBhcnJheS5cclxuICAgICAgICAgICAgICAgIC8vIChmb3IgZXhhbXBsZTogb3B0aW9ucy5lbmFibGVkRGF0ZXNbJzIwMTQtMDItMjcnXSA9PT0gdHJ1ZSlcclxuICAgICAgICAgICAgICAgIHZhciBnaXZlbkRhdGVzSW5kZXhlZCA9IHt9O1xyXG4gICAgICAgICAgICAgICAgJC5lYWNoKGdpdmVuRGF0ZXNBcnJheSwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHZhciBkRGF0ZSA9IHBhcnNlSW5wdXREYXRlKHRoaXMpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChkRGF0ZS5pc1ZhbGlkKCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZ2l2ZW5EYXRlc0luZGV4ZWRbZERhdGUuZm9ybWF0KCdZWVlZLU1NLUREJyldID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIHJldHVybiAoT2JqZWN0LmtleXMoZ2l2ZW5EYXRlc0luZGV4ZWQpLmxlbmd0aCkgPyBnaXZlbkRhdGVzSW5kZXhlZCA6IGZhbHNlO1xyXG4gICAgICAgICAgICB9LFxyXG5cclxuICAgICAgICAgICAgaW5kZXhHaXZlbkhvdXJzID0gZnVuY3Rpb24gKGdpdmVuSG91cnNBcnJheSkge1xyXG4gICAgICAgICAgICAgICAgLy8gU3RvcmUgZ2l2ZW4gZW5hYmxlZEhvdXJzIGFuZCBkaXNhYmxlZEhvdXJzIGFzIGtleXMuXHJcbiAgICAgICAgICAgICAgICAvLyBUaGlzIHdheSB3ZSBjYW4gY2hlY2sgdGhlaXIgZXhpc3RlbmNlIGluIE8oMSkgdGltZSBpbnN0ZWFkIG9mIGxvb3BpbmcgdGhyb3VnaCB3aG9sZSBhcnJheS5cclxuICAgICAgICAgICAgICAgIC8vIChmb3IgZXhhbXBsZTogb3B0aW9ucy5lbmFibGVkSG91cnNbJzIwMTQtMDItMjcnXSA9PT0gdHJ1ZSlcclxuICAgICAgICAgICAgICAgIHZhciBnaXZlbkhvdXJzSW5kZXhlZCA9IHt9O1xyXG4gICAgICAgICAgICAgICAgJC5lYWNoKGdpdmVuSG91cnNBcnJheSwgZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGdpdmVuSG91cnNJbmRleGVkW3RoaXNdID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIChPYmplY3Qua2V5cyhnaXZlbkhvdXJzSW5kZXhlZCkubGVuZ3RoKSA/IGdpdmVuSG91cnNJbmRleGVkIDogZmFsc2U7XHJcbiAgICAgICAgICAgIH0sXHJcblxyXG4gICAgICAgICAgICBpbml0Rm9ybWF0dGluZyA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciBmb3JtYXQgPSBvcHRpb25zLmZvcm1hdCB8fCAnTCBMVCc7XHJcblxyXG4gICAgICAgICAgICAgICAgYWN0dWFsRm9ybWF0ID0gZm9ybWF0LnJlcGxhY2UoLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KExUU3xMVHxMTD9MP0w/fGx7MSw0fSkvZywgZnVuY3Rpb24gKGZvcm1hdElucHV0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdmFyIG5ld2lucHV0ID0gZGF0ZS5sb2NhbGVEYXRhKCkubG9uZ0RhdGVGb3JtYXQoZm9ybWF0SW5wdXQpIHx8IGZvcm1hdElucHV0O1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuZXdpbnB1dC5yZXBsYWNlKC8oXFxbW15cXFtdKlxcXSl8KFxcXFwpPyhMVFN8TFR8TEw/TD9MP3xsezEsNH0pL2csIGZ1bmN0aW9uIChmb3JtYXRJbnB1dDIpIHsgLy90ZW1wIGZpeCBmb3IgIzc0MFxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF0ZS5sb2NhbGVEYXRhKCkubG9uZ0RhdGVGb3JtYXQoZm9ybWF0SW5wdXQyKSB8fCBmb3JtYXRJbnB1dDI7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuXHJcblxyXG4gICAgICAgICAgICAgICAgcGFyc2VGb3JtYXRzID0gb3B0aW9ucy5leHRyYUZvcm1hdHMgPyBvcHRpb25zLmV4dHJhRm9ybWF0cy5zbGljZSgpIDogW107XHJcbiAgICAgICAgICAgICAgICBpZiAocGFyc2VGb3JtYXRzLmluZGV4T2YoZm9ybWF0KSA8IDAgJiYgcGFyc2VGb3JtYXRzLmluZGV4T2YoYWN0dWFsRm9ybWF0KSA8IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBwYXJzZUZvcm1hdHMucHVzaChhY3R1YWxGb3JtYXQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHVzZTI0SG91cnMgPSAoYWN0dWFsRm9ybWF0LnRvTG93ZXJDYXNlKCkuaW5kZXhPZignYScpIDwgMSAmJiBhY3R1YWxGb3JtYXQucmVwbGFjZSgvXFxbLio/XFxdL2csICcnKS5pbmRleE9mKCdoJykgPCAxKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoaXNFbmFibGVkKCd5JykpIHtcclxuICAgICAgICAgICAgICAgICAgICBtaW5WaWV3TW9kZU51bWJlciA9IDI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoaXNFbmFibGVkKCdNJykpIHtcclxuICAgICAgICAgICAgICAgICAgICBtaW5WaWV3TW9kZU51bWJlciA9IDE7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoaXNFbmFibGVkKCdkJykpIHtcclxuICAgICAgICAgICAgICAgICAgICBtaW5WaWV3TW9kZU51bWJlciA9IDA7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgobWluVmlld01vZGVOdW1iZXIsIGN1cnJlbnRWaWV3TW9kZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKCF1bnNldCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHNldFZhbHVlKGRhdGUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcclxuICAgICAgICAgKlxyXG4gICAgICAgICAqIFB1YmxpYyBBUEkgZnVuY3Rpb25zXHJcbiAgICAgICAgICogPT09PT09PT09PT09PT09PT09PT09XHJcbiAgICAgICAgICpcclxuICAgICAgICAgKiBJbXBvcnRhbnQ6IERvIG5vdCBleHBvc2UgZGlyZWN0IHJlZmVyZW5jZXMgdG8gcHJpdmF0ZSBvYmplY3RzIG9yIHRoZSBvcHRpb25zXHJcbiAgICAgICAgICogb2JqZWN0IHRvIHRoZSBvdXRlciB3b3JsZC4gQWx3YXlzIHJldHVybiBhIGNsb25lIHdoZW4gcmV0dXJuaW5nIHZhbHVlcyBvciBtYWtlXHJcbiAgICAgICAgICogYSBjbG9uZSB3aGVuIHNldHRpbmcgYSBwcml2YXRlIHZhcmlhYmxlLlxyXG4gICAgICAgICAqXHJcbiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xyXG4gICAgICAgIHBpY2tlci5kZXN0cm95ID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAvLy88c3VtbWFyeT5EZXN0cm95cyB0aGUgd2lkZ2V0IGFuZCByZW1vdmVzIGFsbCBhdHRhY2hlZCBldmVudCBsaXN0ZW5lcnM8L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIGhpZGUoKTtcclxuICAgICAgICAgICAgZGV0YWNoRGF0ZVBpY2tlckVsZW1lbnRFdmVudHMoKTtcclxuICAgICAgICAgICAgZWxlbWVudC5yZW1vdmVEYXRhKCdEYXRlVGltZVBpY2tlcicpO1xyXG4gICAgICAgICAgICBlbGVtZW50LnJlbW92ZURhdGEoJ2RhdGUnKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIudG9nZ2xlID0gdG9nZ2xlO1xyXG5cclxuICAgICAgICBwaWNrZXIuc2hvdyA9IHNob3c7XHJcblxyXG4gICAgICAgIHBpY2tlci5oaWRlID0gaGlkZTtcclxuXHJcbiAgICAgICAgcGlja2VyLmRpc2FibGUgPSBmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgIC8vLzxzdW1tYXJ5PkRpc2FibGVzIHRoZSBpbnB1dCBlbGVtZW50LCB0aGUgY29tcG9uZW50IGlzIGF0dGFjaGVkIHRvLCBieSBhZGRpbmcgYSBkaXNhYmxlZD1cInRydWVcIiBhdHRyaWJ1dGUgdG8gaXQuXHJcbiAgICAgICAgICAgIC8vL0lmIHRoZSB3aWRnZXQgd2FzIHZpc2libGUgYmVmb3JlIHRoYXQgY2FsbCBpdCBpcyBoaWRkZW4uIFBvc3NpYmx5IGVtaXRzIGRwLmhpZGU8L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIGhpZGUoKTtcclxuICAgICAgICAgICAgaWYgKGNvbXBvbmVudCAmJiBjb21wb25lbnQuaGFzQ2xhc3MoJ2J0bicpKSB7XHJcbiAgICAgICAgICAgICAgICBjb21wb25lbnQuYWRkQ2xhc3MoJ2Rpc2FibGVkJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaW5wdXQucHJvcCgnZGlzYWJsZWQnLCB0cnVlKTtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIuZW5hYmxlID0gZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAvLy88c3VtbWFyeT5FbmFibGVzIHRoZSBpbnB1dCBlbGVtZW50LCB0aGUgY29tcG9uZW50IGlzIGF0dGFjaGVkIHRvLCBieSByZW1vdmluZyBkaXNhYmxlZCBhdHRyaWJ1dGUgZnJvbSBpdC48L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIGlmIChjb21wb25lbnQgJiYgY29tcG9uZW50Lmhhc0NsYXNzKCdidG4nKSkge1xyXG4gICAgICAgICAgICAgICAgY29tcG9uZW50LnJlbW92ZUNsYXNzKCdkaXNhYmxlZCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlucHV0LnByb3AoJ2Rpc2FibGVkJywgZmFsc2UpO1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5pZ25vcmVSZWFkb25seSA9IGZ1bmN0aW9uIChpZ25vcmVSZWFkb25seSkge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMuaWdub3JlUmVhZG9ubHk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBpZ25vcmVSZWFkb25seSAhPT0gJ2Jvb2xlYW4nKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdpZ25vcmVSZWFkb25seSAoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcHRpb25zLmlnbm9yZVJlYWRvbmx5ID0gaWdub3JlUmVhZG9ubHk7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLm9wdGlvbnMgPSBmdW5jdGlvbiAobmV3T3B0aW9ucykge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHRydWUsIHt9LCBvcHRpb25zKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCEobmV3T3B0aW9ucyBpbnN0YW5jZW9mIE9iamVjdCkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbnMoKSBvcHRpb25zIHBhcmFtZXRlciBzaG91bGQgYmUgYW4gb2JqZWN0Jyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgJC5leHRlbmQodHJ1ZSwgb3B0aW9ucywgbmV3T3B0aW9ucyk7XHJcbiAgICAgICAgICAgICQuZWFjaChvcHRpb25zLCBmdW5jdGlvbiAoa2V5LCB2YWx1ZSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHBpY2tlcltrZXldICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBwaWNrZXJba2V5XSh2YWx1ZSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ29wdGlvbiAnICsga2V5ICsgJyBpcyBub3QgcmVjb2duaXplZCEnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmRhdGUgPSBmdW5jdGlvbiAobmV3RGF0ZSkge1xyXG4gICAgICAgICAgICAvLy88c2lnbmF0dXJlIGhlbHBLZXl3b3JkPVwiJC5mbi5kYXRldGltZXBpY2tlci5kYXRlXCI+XHJcbiAgICAgICAgICAgIC8vLzxzdW1tYXJ5PlJldHVybnMgdGhlIGNvbXBvbmVudCdzIG1vZGVsIGN1cnJlbnQgZGF0ZSwgYSBtb21lbnQgb2JqZWN0IG9yIG51bGwgaWYgbm90IHNldC48L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIC8vLzxyZXR1cm5zIHR5cGU9XCJNb21lbnRcIj5kYXRlLmNsb25lKCk8L3JldHVybnM+XHJcbiAgICAgICAgICAgIC8vLzwvc2lnbmF0dXJlPlxyXG4gICAgICAgICAgICAvLy88c2lnbmF0dXJlPlxyXG4gICAgICAgICAgICAvLy88c3VtbWFyeT5TZXRzIHRoZSBjb21wb25lbnRzIG1vZGVsIGN1cnJlbnQgbW9tZW50IHRvIGl0LiBQYXNzaW5nIGEgbnVsbCB2YWx1ZSB1bnNldHMgdGhlIGNvbXBvbmVudHMgbW9kZWwgY3VycmVudCBtb21lbnQuIFBhcnNpbmcgb2YgdGhlIG5ld0RhdGUgcGFyYW1ldGVyIGlzIG1hZGUgdXNpbmcgbW9tZW50IGxpYnJhcnkgd2l0aCB0aGUgb3B0aW9ucy5mb3JtYXQgYW5kIG9wdGlvbnMudXNlU3RyaWN0IGNvbXBvbmVudHMgY29uZmlndXJhdGlvbi48L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIC8vLzxwYXJhbSBuYW1lPVwibmV3RGF0ZVwiIGxvY2lkPVwiJC5mbi5kYXRldGltZXBpY2tlci5kYXRlX3A6bmV3RGF0ZVwiPlRha2VzIHN0cmluZywgRGF0ZSwgbW9tZW50LCBudWxsIHBhcmFtZXRlci48L3BhcmFtPlxyXG4gICAgICAgICAgICAvLy88L3NpZ25hdHVyZT5cclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIGlmICh1bnNldCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRhdGUuY2xvbmUoKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKG5ld0RhdGUgIT09IG51bGwgJiYgdHlwZW9mIG5ld0RhdGUgIT09ICdzdHJpbmcnICYmICFtb21lbnQuaXNNb21lbnQobmV3RGF0ZSkgJiYgIShuZXdEYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RhdGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgW251bGwsIHN0cmluZywgbW9tZW50IG9yIERhdGVdJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHNldFZhbHVlKG5ld0RhdGUgPT09IG51bGwgPyBudWxsIDogcGFyc2VJbnB1dERhdGUobmV3RGF0ZSkpO1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5mb3JtYXQgPSBmdW5jdGlvbiAobmV3Rm9ybWF0KSB7XHJcbiAgICAgICAgICAgIC8vLzxzdW1tYXJ5PnRlc3Qgc3U8L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIC8vLzxwYXJhbSBuYW1lPVwibmV3Rm9ybWF0XCI+aW5mbyBhYm91dCBwYXJhPC9wYXJhbT5cclxuICAgICAgICAgICAgLy8vPHJldHVybnMgdHlwZT1cInN0cmluZ3xib29sZWFuXCI+cmV0dXJucyBmb288L3JldHVybnM+XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5mb3JtYXQ7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICgodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ3N0cmluZycpICYmICgodHlwZW9mIG5ld0Zvcm1hdCAhPT0gJ2Jvb2xlYW4nKSB8fCAobmV3Rm9ybWF0ICE9PSBmYWxzZSkpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdmb3JtYXQoKSBleHBlY3RzIGEgc3RyaW5nIG9yIGJvb2xlYW46ZmFsc2UgcGFyYW1ldGVyICcgKyBuZXdGb3JtYXQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLmZvcm1hdCA9IG5ld0Zvcm1hdDtcclxuICAgICAgICAgICAgaWYgKGFjdHVhbEZvcm1hdCkge1xyXG4gICAgICAgICAgICAgICAgaW5pdEZvcm1hdHRpbmcoKTsgLy8gcmVpbml0IGZvcm1hdHRpbmdcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci50aW1lWm9uZSA9IGZ1bmN0aW9uIChuZXdab25lKSB7XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy50aW1lWm9uZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBuZXdab25lICE9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbmV3Wm9uZSgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMudGltZVpvbmUgPSBuZXdab25lO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIuZGF5Vmlld0hlYWRlckZvcm1hdCA9IGZ1bmN0aW9uIChuZXdGb3JtYXQpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmRheVZpZXdIZWFkZXJGb3JtYXQ7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbmV3Rm9ybWF0ICE9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGF5Vmlld0hlYWRlckZvcm1hdCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMuZGF5Vmlld0hlYWRlckZvcm1hdCA9IG5ld0Zvcm1hdDtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIuZXh0cmFGb3JtYXRzID0gZnVuY3Rpb24gKGZvcm1hdHMpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmV4dHJhRm9ybWF0cztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGZvcm1hdHMgIT09IGZhbHNlICYmICEoZm9ybWF0cyBpbnN0YW5jZW9mIEFycmF5KSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZXh0cmFGb3JtYXRzKCkgZXhwZWN0cyBhbiBhcnJheSBvciBmYWxzZSBwYXJhbWV0ZXInKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgb3B0aW9ucy5leHRyYUZvcm1hdHMgPSBmb3JtYXRzO1xyXG4gICAgICAgICAgICBpZiAocGFyc2VGb3JtYXRzKSB7XHJcbiAgICAgICAgICAgICAgICBpbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXQgZm9ybWF0dGluZ1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmRpc2FibGVkRGF0ZXMgPSBmdW5jdGlvbiAoZGF0ZXMpIHtcclxuICAgICAgICAgICAgLy8vPHNpZ25hdHVyZSBoZWxwS2V5d29yZD1cIiQuZm4uZGF0ZXRpbWVwaWNrZXIuZGlzYWJsZWREYXRlc1wiPlxyXG4gICAgICAgICAgICAvLy88c3VtbWFyeT5SZXR1cm5zIGFuIGFycmF5IHdpdGggdGhlIGN1cnJlbnRseSBzZXQgZGlzYWJsZWQgZGF0ZXMgb24gdGhlIGNvbXBvbmVudC48L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIC8vLzxyZXR1cm5zIHR5cGU9XCJhcnJheVwiPm9wdGlvbnMuZGlzYWJsZWREYXRlczwvcmV0dXJucz5cclxuICAgICAgICAgICAgLy8vPC9zaWduYXR1cmU+XHJcbiAgICAgICAgICAgIC8vLzxzaWduYXR1cmU+XHJcbiAgICAgICAgICAgIC8vLzxzdW1tYXJ5PlNldHRpbmcgdGhpcyB0YWtlcyBwcmVjZWRlbmNlIG92ZXIgb3B0aW9ucy5taW5EYXRlLCBvcHRpb25zLm1heERhdGUgY29uZmlndXJhdGlvbi4gQWxzbyBjYWxsaW5nIHRoaXMgZnVuY3Rpb24gcmVtb3ZlcyB0aGUgY29uZmlndXJhdGlvbiBvZlxyXG4gICAgICAgICAgICAvLy9vcHRpb25zLmVuYWJsZWREYXRlcyBpZiBzdWNoIGV4aXN0Ljwvc3VtbWFyeT5cclxuICAgICAgICAgICAgLy8vPHBhcmFtIG5hbWU9XCJkYXRlc1wiIGxvY2lkPVwiJC5mbi5kYXRldGltZXBpY2tlci5kaXNhYmxlZERhdGVzX3A6ZGF0ZXNcIj5UYWtlcyBhbiBbIHN0cmluZyBvciBEYXRlIG9yIG1vbWVudCBdIG9mIHZhbHVlcyBhbmQgYWxsb3dzIHRoZSB1c2VyIHRvIHNlbGVjdCBvbmx5IGZyb20gdGhvc2UgZGF5cy48L3BhcmFtPlxyXG4gICAgICAgICAgICAvLy88L3NpZ25hdHVyZT5cclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAob3B0aW9ucy5kaXNhYmxlZERhdGVzID8gJC5leHRlbmQoe30sIG9wdGlvbnMuZGlzYWJsZWREYXRlcykgOiBvcHRpb25zLmRpc2FibGVkRGF0ZXMpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoIWRhdGVzKSB7XHJcbiAgICAgICAgICAgICAgICBvcHRpb25zLmRpc2FibGVkRGF0ZXMgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgIHVwZGF0ZSgpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoIShkYXRlcyBpbnN0YW5jZW9mIEFycmF5KSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGlzYWJsZWREYXRlcygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy5kaXNhYmxlZERhdGVzID0gaW5kZXhHaXZlbkRhdGVzKGRhdGVzKTtcclxuICAgICAgICAgICAgb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSBmYWxzZTtcclxuICAgICAgICAgICAgdXBkYXRlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmVuYWJsZWREYXRlcyA9IGZ1bmN0aW9uIChkYXRlcykge1xyXG4gICAgICAgICAgICAvLy88c2lnbmF0dXJlIGhlbHBLZXl3b3JkPVwiJC5mbi5kYXRldGltZXBpY2tlci5lbmFibGVkRGF0ZXNcIj5cclxuICAgICAgICAgICAgLy8vPHN1bW1hcnk+UmV0dXJucyBhbiBhcnJheSB3aXRoIHRoZSBjdXJyZW50bHkgc2V0IGVuYWJsZWQgZGF0ZXMgb24gdGhlIGNvbXBvbmVudC48L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIC8vLzxyZXR1cm5zIHR5cGU9XCJhcnJheVwiPm9wdGlvbnMuZW5hYmxlZERhdGVzPC9yZXR1cm5zPlxyXG4gICAgICAgICAgICAvLy88L3NpZ25hdHVyZT5cclxuICAgICAgICAgICAgLy8vPHNpZ25hdHVyZT5cclxuICAgICAgICAgICAgLy8vPHN1bW1hcnk+U2V0dGluZyB0aGlzIHRha2VzIHByZWNlZGVuY2Ugb3ZlciBvcHRpb25zLm1pbkRhdGUsIG9wdGlvbnMubWF4RGF0ZSBjb25maWd1cmF0aW9uLiBBbHNvIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiByZW1vdmVzIHRoZSBjb25maWd1cmF0aW9uIG9mIG9wdGlvbnMuZGlzYWJsZWREYXRlcyBpZiBzdWNoIGV4aXN0Ljwvc3VtbWFyeT5cclxuICAgICAgICAgICAgLy8vPHBhcmFtIG5hbWU9XCJkYXRlc1wiIGxvY2lkPVwiJC5mbi5kYXRldGltZXBpY2tlci5lbmFibGVkRGF0ZXNfcDpkYXRlc1wiPlRha2VzIGFuIFsgc3RyaW5nIG9yIERhdGUgb3IgbW9tZW50IF0gb2YgdmFsdWVzIGFuZCBhbGxvd3MgdGhlIHVzZXIgdG8gc2VsZWN0IG9ubHkgZnJvbSB0aG9zZSBkYXlzLjwvcGFyYW0+XHJcbiAgICAgICAgICAgIC8vLzwvc2lnbmF0dXJlPlxyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIChvcHRpb25zLmVuYWJsZWREYXRlcyA/ICQuZXh0ZW5kKHt9LCBvcHRpb25zLmVuYWJsZWREYXRlcykgOiBvcHRpb25zLmVuYWJsZWREYXRlcyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghZGF0ZXMpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMuZW5hYmxlZERhdGVzID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCEoZGF0ZXMgaW5zdGFuY2VvZiBBcnJheSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuYWJsZWREYXRlcygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy5lbmFibGVkRGF0ZXMgPSBpbmRleEdpdmVuRGF0ZXMoZGF0ZXMpO1xyXG4gICAgICAgICAgICBvcHRpb25zLmRpc2FibGVkRGF0ZXMgPSBmYWxzZTtcclxuICAgICAgICAgICAgdXBkYXRlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmRheXNPZldlZWtEaXNhYmxlZCA9IGZ1bmN0aW9uIChkYXlzT2ZXZWVrRGlzYWJsZWQpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZC5zcGxpY2UoMCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICgodHlwZW9mIGRheXNPZldlZWtEaXNhYmxlZCA9PT0gJ2Jvb2xlYW4nKSAmJiAhZGF5c09mV2Vla0Rpc2FibGVkKSB7XHJcbiAgICAgICAgICAgICAgICBvcHRpb25zLmRheXNPZldlZWtEaXNhYmxlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgdXBkYXRlKCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoIShkYXlzT2ZXZWVrRGlzYWJsZWQgaW5zdGFuY2VvZiBBcnJheSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2RheXNPZldlZWtEaXNhYmxlZCgpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy5kYXlzT2ZXZWVrRGlzYWJsZWQgPSBkYXlzT2ZXZWVrRGlzYWJsZWQucmVkdWNlKGZ1bmN0aW9uIChwcmV2aW91c1ZhbHVlLCBjdXJyZW50VmFsdWUpIHtcclxuICAgICAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSA9IHBhcnNlSW50KGN1cnJlbnRWYWx1ZSwgMTApO1xyXG4gICAgICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA+IDYgfHwgY3VycmVudFZhbHVlIDwgMCB8fCBpc05hTihjdXJyZW50VmFsdWUpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHByZXZpb3VzVmFsdWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNWYWx1ZS5pbmRleE9mKGN1cnJlbnRWYWx1ZSkgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcHJldmlvdXNWYWx1ZS5wdXNoKGN1cnJlbnRWYWx1ZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldmlvdXNWYWx1ZTtcclxuICAgICAgICAgICAgfSwgW10pLnNvcnQoKTtcclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMudXNlQ3VycmVudCAmJiAhb3B0aW9ucy5rZWVwSW52YWxpZCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcclxuICAgICAgICAgICAgICAgIHdoaWxlICghaXNWYWxpZChkYXRlLCAnZCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGF0ZS5hZGQoMSwgJ2QnKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDMxKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAzMSB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBzZXRWYWx1ZShkYXRlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIubWF4RGF0ZSA9IGZ1bmN0aW9uIChtYXhEYXRlKSB7XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5tYXhEYXRlID8gb3B0aW9ucy5tYXhEYXRlLmNsb25lKCkgOiBvcHRpb25zLm1heERhdGU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICgodHlwZW9mIG1heERhdGUgPT09ICdib29sZWFuJykgJiYgbWF4RGF0ZSA9PT0gZmFsc2UpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMubWF4RGF0ZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgdXBkYXRlKCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG1heERhdGUgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAobWF4RGF0ZSA9PT0gJ25vdycgfHwgbWF4RGF0ZSA9PT0gJ21vbWVudCcpIHtcclxuICAgICAgICAgICAgICAgICAgICBtYXhEYXRlID0gZ2V0TW9tZW50KCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHZhciBwYXJzZWREYXRlID0gcGFyc2VJbnB1dERhdGUobWF4RGF0ZSk7XHJcblxyXG4gICAgICAgICAgICBpZiAoIXBhcnNlZERhdGUuaXNWYWxpZCgpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdtYXhEYXRlKCkgQ291bGQgbm90IHBhcnNlIGRhdGUgcGFyYW1ldGVyOiAnICsgbWF4RGF0ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMubWluRGF0ZSAmJiBwYXJzZWREYXRlLmlzQmVmb3JlKG9wdGlvbnMubWluRGF0ZSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21heERhdGUoKSBkYXRlIHBhcmFtZXRlciBpcyBiZWZvcmUgb3B0aW9ucy5taW5EYXRlOiAnICsgcGFyc2VkRGF0ZS5mb3JtYXQoYWN0dWFsRm9ybWF0KSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy5tYXhEYXRlID0gcGFyc2VkRGF0ZTtcclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMudXNlQ3VycmVudCAmJiAhb3B0aW9ucy5rZWVwSW52YWxpZCAmJiBkYXRlLmlzQWZ0ZXIobWF4RGF0ZSkpIHtcclxuICAgICAgICAgICAgICAgIHNldFZhbHVlKG9wdGlvbnMubWF4RGF0ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHZpZXdEYXRlLmlzQWZ0ZXIocGFyc2VkRGF0ZSkpIHtcclxuICAgICAgICAgICAgICAgIHZpZXdEYXRlID0gcGFyc2VkRGF0ZS5jbG9uZSgpLnN1YnRyYWN0KG9wdGlvbnMuc3RlcHBpbmcsICdtJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdXBkYXRlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLm1pbkRhdGUgPSBmdW5jdGlvbiAobWluRGF0ZSkge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMubWluRGF0ZSA/IG9wdGlvbnMubWluRGF0ZS5jbG9uZSgpIDogb3B0aW9ucy5taW5EYXRlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoKHR5cGVvZiBtaW5EYXRlID09PSAnYm9vbGVhbicpICYmIG1pbkRhdGUgPT09IGZhbHNlKSB7XHJcbiAgICAgICAgICAgICAgICBvcHRpb25zLm1pbkRhdGUgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgIHVwZGF0ZSgpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBtaW5EYXRlID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG1pbkRhdGUgPT09ICdub3cnIHx8IG1pbkRhdGUgPT09ICdtb21lbnQnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWluRGF0ZSA9IGdldE1vbWVudCgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHBhcnNlSW5wdXREYXRlKG1pbkRhdGUpO1xyXG5cclxuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignbWluRGF0ZSgpIENvdWxkIG5vdCBwYXJzZSBkYXRlIHBhcmFtZXRlcjogJyArIG1pbkRhdGUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChvcHRpb25zLm1heERhdGUgJiYgcGFyc2VkRGF0ZS5pc0FmdGVyKG9wdGlvbnMubWF4RGF0ZSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ21pbkRhdGUoKSBkYXRlIHBhcmFtZXRlciBpcyBhZnRlciBvcHRpb25zLm1heERhdGU6ICcgKyBwYXJzZWREYXRlLmZvcm1hdChhY3R1YWxGb3JtYXQpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcHRpb25zLm1pbkRhdGUgPSBwYXJzZWREYXRlO1xyXG4gICAgICAgICAgICBpZiAob3B0aW9ucy51c2VDdXJyZW50ICYmICFvcHRpb25zLmtlZXBJbnZhbGlkICYmIGRhdGUuaXNCZWZvcmUobWluRGF0ZSkpIHtcclxuICAgICAgICAgICAgICAgIHNldFZhbHVlKG9wdGlvbnMubWluRGF0ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHZpZXdEYXRlLmlzQmVmb3JlKHBhcnNlZERhdGUpKSB7XHJcbiAgICAgICAgICAgICAgICB2aWV3RGF0ZSA9IHBhcnNlZERhdGUuY2xvbmUoKS5hZGQob3B0aW9ucy5zdGVwcGluZywgJ20nKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIuZGVmYXVsdERhdGUgPSBmdW5jdGlvbiAoZGVmYXVsdERhdGUpIHtcclxuICAgICAgICAgICAgLy8vPHNpZ25hdHVyZSBoZWxwS2V5d29yZD1cIiQuZm4uZGF0ZXRpbWVwaWNrZXIuZGVmYXVsdERhdGVcIj5cclxuICAgICAgICAgICAgLy8vPHN1bW1hcnk+UmV0dXJucyBhIG1vbWVudCB3aXRoIHRoZSBvcHRpb25zLmRlZmF1bHREYXRlIG9wdGlvbiBjb25maWd1cmF0aW9uIG9yIGZhbHNlIGlmIG5vdCBzZXQ8L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIC8vLzxyZXR1cm5zIHR5cGU9XCJNb21lbnRcIj5kYXRlLmNsb25lKCk8L3JldHVybnM+XHJcbiAgICAgICAgICAgIC8vLzwvc2lnbmF0dXJlPlxyXG4gICAgICAgICAgICAvLy88c2lnbmF0dXJlPlxyXG4gICAgICAgICAgICAvLy88c3VtbWFyeT5XaWxsIHNldCB0aGUgcGlja2VyJ3MgaW5pdGFsIGRhdGUuIElmIGEgYm9vbGVhbjpmYWxzZSB2YWx1ZSBpcyBwYXNzZWQgdGhlIG9wdGlvbnMuZGVmYXVsdERhdGUgcGFyYW1ldGVyIGlzIGNsZWFyZWQuPC9zdW1tYXJ5PlxyXG4gICAgICAgICAgICAvLy88cGFyYW0gbmFtZT1cImRlZmF1bHREYXRlXCIgbG9jaWQ9XCIkLmZuLmRhdGV0aW1lcGlja2VyLmRlZmF1bHREYXRlX3A6ZGVmYXVsdERhdGVcIj5UYWtlcyBhIHN0cmluZywgRGF0ZSwgbW9tZW50LCBib29sZWFuOmZhbHNlPC9wYXJhbT5cclxuICAgICAgICAgICAgLy8vPC9zaWduYXR1cmU+XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5kZWZhdWx0RGF0ZSA/IG9wdGlvbnMuZGVmYXVsdERhdGUuY2xvbmUoKSA6IG9wdGlvbnMuZGVmYXVsdERhdGU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCFkZWZhdWx0RGF0ZSkge1xyXG4gICAgICAgICAgICAgICAgb3B0aW9ucy5kZWZhdWx0RGF0ZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBkZWZhdWx0RGF0ZSA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgICAgIGlmIChkZWZhdWx0RGF0ZSA9PT0gJ25vdycgfHwgZGVmYXVsdERhdGUgPT09ICdtb21lbnQnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdERhdGUgPSBnZXRNb21lbnQoKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdERhdGUgPSBnZXRNb21lbnQoZGVmYXVsdERhdGUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB2YXIgcGFyc2VkRGF0ZSA9IHBhcnNlSW5wdXREYXRlKGRlZmF1bHREYXRlKTtcclxuICAgICAgICAgICAgaWYgKCFwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVmYXVsdERhdGUoKSBDb3VsZCBub3QgcGFyc2UgZGF0ZSBwYXJhbWV0ZXI6ICcgKyBkZWZhdWx0RGF0ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCFpc1ZhbGlkKHBhcnNlZERhdGUpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkZWZhdWx0RGF0ZSgpIGRhdGUgcGFzc2VkIGlzIGludmFsaWQgYWNjb3JkaW5nIHRvIGNvbXBvbmVudCBzZXR1cCB2YWxpZGF0aW9ucycpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLmRlZmF1bHREYXRlID0gcGFyc2VkRGF0ZTtcclxuXHJcbiAgICAgICAgICAgIGlmICgob3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiBvcHRpb25zLmlubGluZSkgfHwgaW5wdXQudmFsKCkudHJpbSgpID09PSAnJykge1xyXG4gICAgICAgICAgICAgICAgc2V0VmFsdWUob3B0aW9ucy5kZWZhdWx0RGF0ZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIubG9jYWxlID0gZnVuY3Rpb24gKGxvY2FsZSkge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMubG9jYWxlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoIW1vbWVudC5sb2NhbGVEYXRhKGxvY2FsZSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2xvY2FsZSgpIGxvY2FsZSAnICsgbG9jYWxlICsgJyBpcyBub3QgbG9hZGVkIGZyb20gbW9tZW50IGxvY2FsZXMhJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMubG9jYWxlID0gbG9jYWxlO1xyXG4gICAgICAgICAgICBkYXRlLmxvY2FsZShvcHRpb25zLmxvY2FsZSk7XHJcbiAgICAgICAgICAgIHZpZXdEYXRlLmxvY2FsZShvcHRpb25zLmxvY2FsZSk7XHJcblxyXG4gICAgICAgICAgICBpZiAoYWN0dWFsRm9ybWF0KSB7XHJcbiAgICAgICAgICAgICAgICBpbml0Rm9ybWF0dGluZygpOyAvLyByZWluaXQgZm9ybWF0dGluZ1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgIGhpZGUoKTtcclxuICAgICAgICAgICAgICAgIHNob3coKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5zdGVwcGluZyA9IGZ1bmN0aW9uIChzdGVwcGluZykge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMuc3RlcHBpbmc7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHN0ZXBwaW5nID0gcGFyc2VJbnQoc3RlcHBpbmcsIDEwKTtcclxuICAgICAgICAgICAgaWYgKGlzTmFOKHN0ZXBwaW5nKSB8fCBzdGVwcGluZyA8IDEpIHtcclxuICAgICAgICAgICAgICAgIHN0ZXBwaW5nID0gMTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcHRpb25zLnN0ZXBwaW5nID0gc3RlcHBpbmc7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLnVzZUN1cnJlbnQgPSBmdW5jdGlvbiAodXNlQ3VycmVudCkge1xyXG4gICAgICAgICAgICB2YXIgdXNlQ3VycmVudE9wdGlvbnMgPSBbJ3llYXInLCAnbW9udGgnLCAnZGF5JywgJ2hvdXInLCAnbWludXRlJ107XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy51c2VDdXJyZW50O1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoKHR5cGVvZiB1c2VDdXJyZW50ICE9PSAnYm9vbGVhbicpICYmICh0eXBlb2YgdXNlQ3VycmVudCAhPT0gJ3N0cmluZycpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd1c2VDdXJyZW50KCkgZXhwZWN0cyBhIGJvb2xlYW4gb3Igc3RyaW5nIHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdXNlQ3VycmVudCA9PT0gJ3N0cmluZycgJiYgdXNlQ3VycmVudE9wdGlvbnMuaW5kZXhPZih1c2VDdXJyZW50LnRvTG93ZXJDYXNlKCkpID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlQ3VycmVudCgpIGV4cGVjdHMgYSBzdHJpbmcgcGFyYW1ldGVyIG9mICcgKyB1c2VDdXJyZW50T3B0aW9ucy5qb2luKCcsICcpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcHRpb25zLnVzZUN1cnJlbnQgPSB1c2VDdXJyZW50O1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5jb2xsYXBzZSA9IGZ1bmN0aW9uIChjb2xsYXBzZSkge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMuY29sbGFwc2U7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY29sbGFwc2UgIT09ICdib29sZWFuJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignY29sbGFwc2UoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5jb2xsYXBzZSA9PT0gY29sbGFwc2UpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy5jb2xsYXBzZSA9IGNvbGxhcHNlO1xyXG4gICAgICAgICAgICBpZiAod2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICBoaWRlKCk7XHJcbiAgICAgICAgICAgICAgICBzaG93KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIuaWNvbnMgPSBmdW5jdGlvbiAoaWNvbnMpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgb3B0aW9ucy5pY29ucyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghKGljb25zIGluc3RhbmNlb2YgT2JqZWN0KSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaWNvbnMoKSBleHBlY3RzIHBhcmFtZXRlciB0byBiZSBhbiBPYmplY3QnKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAkLmV4dGVuZChvcHRpb25zLmljb25zLCBpY29ucyk7XHJcbiAgICAgICAgICAgIGlmICh3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgIGhpZGUoKTtcclxuICAgICAgICAgICAgICAgIHNob3coKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci50b29sdGlwcyA9IGZ1bmN0aW9uICh0b29sdGlwcykge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuICQuZXh0ZW5kKHt9LCBvcHRpb25zLnRvb2x0aXBzKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCEodG9vbHRpcHMgaW5zdGFuY2VvZiBPYmplY3QpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCd0b29sdGlwcygpIGV4cGVjdHMgcGFyYW1ldGVyIHRvIGJlIGFuIE9iamVjdCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICQuZXh0ZW5kKG9wdGlvbnMudG9vbHRpcHMsIHRvb2x0aXBzKTtcclxuICAgICAgICAgICAgaWYgKHdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgaGlkZSgpO1xyXG4gICAgICAgICAgICAgICAgc2hvdygpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLnVzZVN0cmljdCA9IGZ1bmN0aW9uICh1c2VTdHJpY3QpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLnVzZVN0cmljdDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiB1c2VTdHJpY3QgIT09ICdib29sZWFuJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndXNlU3RyaWN0KCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy51c2VTdHJpY3QgPSB1c2VTdHJpY3Q7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLnNpZGVCeVNpZGUgPSBmdW5jdGlvbiAoc2lkZUJ5U2lkZSkge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMuc2lkZUJ5U2lkZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzaWRlQnlTaWRlICE9PSAnYm9vbGVhbicpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3NpZGVCeVNpZGUoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcHRpb25zLnNpZGVCeVNpZGUgPSBzaWRlQnlTaWRlO1xyXG4gICAgICAgICAgICBpZiAod2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICBoaWRlKCk7XHJcbiAgICAgICAgICAgICAgICBzaG93KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIudmlld01vZGUgPSBmdW5jdGlvbiAodmlld01vZGUpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLnZpZXdNb2RlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHZpZXdNb2RlICE9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmlld01vZGUoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodmlld01vZGVzLmluZGV4T2Yodmlld01vZGUpID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndmlld01vZGUoKSBwYXJhbWV0ZXIgbXVzdCBiZSBvbmUgb2YgKCcgKyB2aWV3TW9kZXMuam9pbignLCAnKSArICcpIHZhbHVlJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMudmlld01vZGUgPSB2aWV3TW9kZTtcclxuICAgICAgICAgICAgY3VycmVudFZpZXdNb2RlID0gTWF0aC5tYXgodmlld01vZGVzLmluZGV4T2Yodmlld01vZGUpLCBtaW5WaWV3TW9kZU51bWJlcik7XHJcblxyXG4gICAgICAgICAgICBzaG93TW9kZSgpO1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci50b29sYmFyUGxhY2VtZW50ID0gZnVuY3Rpb24gKHRvb2xiYXJQbGFjZW1lbnQpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLnRvb2xiYXJQbGFjZW1lbnQ7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdG9vbGJhclBsYWNlbWVudCAhPT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Rvb2xiYXJQbGFjZW1lbnQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0b29sYmFyUGxhY2VtZW50cy5pbmRleE9mKHRvb2xiYXJQbGFjZW1lbnQpID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigndG9vbGJhclBsYWNlbWVudCgpIHBhcmFtZXRlciBtdXN0IGJlIG9uZSBvZiAoJyArIHRvb2xiYXJQbGFjZW1lbnRzLmpvaW4oJywgJykgKyAnKSB2YWx1ZScpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wdGlvbnMudG9vbGJhclBsYWNlbWVudCA9IHRvb2xiYXJQbGFjZW1lbnQ7XHJcblxyXG4gICAgICAgICAgICBpZiAod2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICBoaWRlKCk7XHJcbiAgICAgICAgICAgICAgICBzaG93KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIud2lkZ2V0UG9zaXRpb25pbmcgPSBmdW5jdGlvbiAod2lkZ2V0UG9zaXRpb25pbmcpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAkLmV4dGVuZCh7fSwgb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICgoe30pLnRvU3RyaW5nLmNhbGwod2lkZ2V0UG9zaXRpb25pbmcpICE9PSAnW29iamVjdCBPYmplY3RdJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSBleHBlY3RzIGFuIG9iamVjdCB2YXJpYWJsZScpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh3aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHdpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwgIT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSBob3Jpem9udGFsIHZhcmlhYmxlIG11c3QgYmUgYSBzdHJpbmcnKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHdpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWwgPSB3aWRnZXRQb3NpdGlvbmluZy5ob3Jpem9udGFsLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgICAgICAgICAgICBpZiAoaG9yaXpvbnRhbE1vZGVzLmluZGV4T2Yod2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbCkgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSBleHBlY3RzIGhvcml6b250YWwgcGFyYW1ldGVyIHRvIGJlIG9uZSBvZiAoJyArIGhvcml6b250YWxNb2Rlcy5qb2luKCcsICcpICsgJyknKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIG9wdGlvbnMud2lkZ2V0UG9zaXRpb25pbmcuaG9yaXpvbnRhbCA9IHdpZGdldFBvc2l0aW9uaW5nLmhvcml6b250YWw7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHdpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHdpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsICE9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBvc2l0aW9uaW5nKCkgdmVydGljYWwgdmFyaWFibGUgbXVzdCBiZSBhIHN0cmluZycpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgd2lkZ2V0UG9zaXRpb25pbmcudmVydGljYWwgPSB3aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbC50b0xvd2VyQ2FzZSgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHZlcnRpY2FsTW9kZXMuaW5kZXhPZih3aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCkgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignd2lkZ2V0UG9zaXRpb25pbmcoKSBleHBlY3RzIHZlcnRpY2FsIHBhcmFtZXRlciB0byBiZSBvbmUgb2YgKCcgKyB2ZXJ0aWNhbE1vZGVzLmpvaW4oJywgJykgKyAnKScpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgb3B0aW9ucy53aWRnZXRQb3NpdGlvbmluZy52ZXJ0aWNhbCA9IHdpZGdldFBvc2l0aW9uaW5nLnZlcnRpY2FsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHVwZGF0ZSgpO1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5jYWxlbmRhcldlZWtzID0gZnVuY3Rpb24gKGNhbGVuZGFyV2Vla3MpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmNhbGVuZGFyV2Vla3M7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2FsZW5kYXJXZWVrcyAhPT0gJ2Jvb2xlYW4nKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdjYWxlbmRhcldlZWtzKCkgZXhwZWN0cyBwYXJhbWV0ZXIgdG8gYmUgYSBib29sZWFuIHZhbHVlJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMuY2FsZW5kYXJXZWVrcyA9IGNhbGVuZGFyV2Vla3M7XHJcbiAgICAgICAgICAgIHVwZGF0ZSgpO1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5zaG93VG9kYXlCdXR0b24gPSBmdW5jdGlvbiAoc2hvd1RvZGF5QnV0dG9uKSB7XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5zaG93VG9kYXlCdXR0b247XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygc2hvd1RvZGF5QnV0dG9uICE9PSAnYm9vbGVhbicpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3Nob3dUb2RheUJ1dHRvbigpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLnNob3dUb2RheUJ1dHRvbiA9IHNob3dUb2RheUJ1dHRvbjtcclxuICAgICAgICAgICAgaWYgKHdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgaGlkZSgpO1xyXG4gICAgICAgICAgICAgICAgc2hvdygpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLnNob3dDbGVhciA9IGZ1bmN0aW9uIChzaG93Q2xlYXIpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLnNob3dDbGVhcjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzaG93Q2xlYXIgIT09ICdib29sZWFuJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc2hvd0NsZWFyKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMuc2hvd0NsZWFyID0gc2hvd0NsZWFyO1xyXG4gICAgICAgICAgICBpZiAod2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICBoaWRlKCk7XHJcbiAgICAgICAgICAgICAgICBzaG93KCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIud2lkZ2V0UGFyZW50ID0gZnVuY3Rpb24gKHdpZGdldFBhcmVudCkge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMud2lkZ2V0UGFyZW50O1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHdpZGdldFBhcmVudCA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgICAgIHdpZGdldFBhcmVudCA9ICQod2lkZ2V0UGFyZW50KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHdpZGdldFBhcmVudCAhPT0gbnVsbCAmJiAodHlwZW9mIHdpZGdldFBhcmVudCAhPT0gJ3N0cmluZycgJiYgISh3aWRnZXRQYXJlbnQgaW5zdGFuY2VvZiAkKSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3dpZGdldFBhcmVudCgpIGV4cGVjdHMgYSBzdHJpbmcgb3IgYSBqUXVlcnkgb2JqZWN0IHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLndpZGdldFBhcmVudCA9IHdpZGdldFBhcmVudDtcclxuICAgICAgICAgICAgaWYgKHdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgaGlkZSgpO1xyXG4gICAgICAgICAgICAgICAgc2hvdygpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmtlZXBPcGVuID0gZnVuY3Rpb24gKGtlZXBPcGVuKSB7XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5rZWVwT3BlbjtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBrZWVwT3BlbiAhPT0gJ2Jvb2xlYW4nKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdrZWVwT3BlbigpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLmtlZXBPcGVuID0ga2VlcE9wZW47XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmZvY3VzT25TaG93ID0gZnVuY3Rpb24gKGZvY3VzT25TaG93KSB7XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gb3B0aW9ucy5mb2N1c09uU2hvdztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBmb2N1c09uU2hvdyAhPT0gJ2Jvb2xlYW4nKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdmb2N1c09uU2hvdygpIGV4cGVjdHMgYSBib29sZWFuIHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLmZvY3VzT25TaG93ID0gZm9jdXNPblNob3c7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmlubGluZSA9IGZ1bmN0aW9uIChpbmxpbmUpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmlubGluZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBpbmxpbmUgIT09ICdib29sZWFuJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignaW5saW5lKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMuaW5saW5lID0gaW5saW5lO1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5jbGVhciA9IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgY2xlYXIoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIua2V5QmluZHMgPSBmdW5jdGlvbiAoa2V5QmluZHMpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmtleUJpbmRzO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLmtleUJpbmRzID0ga2V5QmluZHM7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmdldE1vbWVudCA9IGZ1bmN0aW9uIChkKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBnZXRNb21lbnQoZCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmRlYnVnID0gZnVuY3Rpb24gKGRlYnVnKSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZGVidWcgIT09ICdib29sZWFuJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGVidWcoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgb3B0aW9ucy5kZWJ1ZyA9IGRlYnVnO1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5hbGxvd0lucHV0VG9nZ2xlID0gZnVuY3Rpb24gKGFsbG93SW5wdXRUb2dnbGUpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmFsbG93SW5wdXRUb2dnbGU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgYWxsb3dJbnB1dFRvZ2dsZSAhPT0gJ2Jvb2xlYW4nKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdhbGxvd0lucHV0VG9nZ2xlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMuYWxsb3dJbnB1dFRvZ2dsZSA9IGFsbG93SW5wdXRUb2dnbGU7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLnNob3dDbG9zZSA9IGZ1bmN0aW9uIChzaG93Q2xvc2UpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLnNob3dDbG9zZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzaG93Q2xvc2UgIT09ICdib29sZWFuJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignc2hvd0Nsb3NlKCkgZXhwZWN0cyBhIGJvb2xlYW4gcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG9wdGlvbnMuc2hvd0Nsb3NlID0gc2hvd0Nsb3NlO1xyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5rZWVwSW52YWxpZCA9IGZ1bmN0aW9uIChrZWVwSW52YWxpZCkge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9wdGlvbnMua2VlcEludmFsaWQ7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Yga2VlcEludmFsaWQgIT09ICdib29sZWFuJykge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcigna2VlcEludmFsaWQoKSBleHBlY3RzIGEgYm9vbGVhbiBwYXJhbWV0ZXInKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBvcHRpb25zLmtlZXBJbnZhbGlkID0ga2VlcEludmFsaWQ7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcGlja2VyLmRhdGVwaWNrZXJJbnB1dCA9IGZ1bmN0aW9uIChkYXRlcGlja2VySW5wdXQpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLmRhdGVwaWNrZXJJbnB1dDtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBkYXRlcGlja2VySW5wdXQgIT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkYXRlcGlja2VySW5wdXQoKSBleHBlY3RzIGEgc3RyaW5nIHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLmRhdGVwaWNrZXJJbnB1dCA9IGRhdGVwaWNrZXJJbnB1dDtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIucGFyc2VJbnB1dERhdGUgPSBmdW5jdGlvbiAocGFyc2VJbnB1dERhdGUpIHtcclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBvcHRpb25zLnBhcnNlSW5wdXREYXRlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHBhcnNlSW5wdXREYXRlICE9PSAnZnVuY3Rpb24nKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdwYXJzZUlucHV0RGF0ZSgpIHNob2x1ZCBiZSBhcyBmdW5jdGlvbicpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBvcHRpb25zLnBhcnNlSW5wdXREYXRlID0gcGFyc2VJbnB1dERhdGU7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHBpY2tlci5kaXNhYmxlZFRpbWVJbnRlcnZhbHMgPSBmdW5jdGlvbiAoZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSB7XHJcbiAgICAgICAgICAgIC8vLzxzaWduYXR1cmUgaGVscEtleXdvcmQ9XCIkLmZuLmRhdGV0aW1lcGlja2VyLmRpc2FibGVkVGltZUludGVydmFsc1wiPlxyXG4gICAgICAgICAgICAvLy88c3VtbWFyeT5SZXR1cm5zIGFuIGFycmF5IHdpdGggdGhlIGN1cnJlbnRseSBzZXQgZGlzYWJsZWQgZGF0ZXMgb24gdGhlIGNvbXBvbmVudC48L3N1bW1hcnk+XHJcbiAgICAgICAgICAgIC8vLzxyZXR1cm5zIHR5cGU9XCJhcnJheVwiPm9wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzPC9yZXR1cm5zPlxyXG4gICAgICAgICAgICAvLy88L3NpZ25hdHVyZT5cclxuICAgICAgICAgICAgLy8vPHNpZ25hdHVyZT5cclxuICAgICAgICAgICAgLy8vPHN1bW1hcnk+U2V0dGluZyB0aGlzIHRha2VzIHByZWNlZGVuY2Ugb3ZlciBvcHRpb25zLm1pbkRhdGUsIG9wdGlvbnMubWF4RGF0ZSBjb25maWd1cmF0aW9uLiBBbHNvIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiByZW1vdmVzIHRoZSBjb25maWd1cmF0aW9uIG9mXHJcbiAgICAgICAgICAgIC8vL29wdGlvbnMuZW5hYmxlZERhdGVzIGlmIHN1Y2ggZXhpc3QuPC9zdW1tYXJ5PlxyXG4gICAgICAgICAgICAvLy88cGFyYW0gbmFtZT1cImRhdGVzXCIgbG9jaWQ9XCIkLmZuLmRhdGV0aW1lcGlja2VyLmRpc2FibGVkVGltZUludGVydmFsc19wOmRhdGVzXCI+VGFrZXMgYW4gWyBzdHJpbmcgb3IgRGF0ZSBvciBtb21lbnQgXSBvZiB2YWx1ZXMgYW5kIGFsbG93cyB0aGUgdXNlciB0byBzZWxlY3Qgb25seSBmcm9tIHRob3NlIGRheXMuPC9wYXJhbT5cclxuICAgICAgICAgICAgLy8vPC9zaWduYXR1cmU+XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gKG9wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID8gJC5leHRlbmQoe30sIG9wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKSA6IG9wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCFkaXNhYmxlZFRpbWVJbnRlcnZhbHMpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCEoZGlzYWJsZWRUaW1lSW50ZXJ2YWxzIGluc3RhbmNlb2YgQXJyYXkpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdkaXNhYmxlZFRpbWVJbnRlcnZhbHMoKSBleHBlY3RzIGFuIGFycmF5IHBhcmFtZXRlcicpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9wdGlvbnMuZGlzYWJsZWRUaW1lSW50ZXJ2YWxzID0gZGlzYWJsZWRUaW1lSW50ZXJ2YWxzO1xyXG4gICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIuZGlzYWJsZWRIb3VycyA9IGZ1bmN0aW9uIChob3Vycykge1xyXG4gICAgICAgICAgICAvLy88c2lnbmF0dXJlIGhlbHBLZXl3b3JkPVwiJC5mbi5kYXRldGltZXBpY2tlci5kaXNhYmxlZEhvdXJzXCI+XHJcbiAgICAgICAgICAgIC8vLzxzdW1tYXJ5PlJldHVybnMgYW4gYXJyYXkgd2l0aCB0aGUgY3VycmVudGx5IHNldCBkaXNhYmxlZCBob3VycyBvbiB0aGUgY29tcG9uZW50Ljwvc3VtbWFyeT5cclxuICAgICAgICAgICAgLy8vPHJldHVybnMgdHlwZT1cImFycmF5XCI+b3B0aW9ucy5kaXNhYmxlZEhvdXJzPC9yZXR1cm5zPlxyXG4gICAgICAgICAgICAvLy88L3NpZ25hdHVyZT5cclxuICAgICAgICAgICAgLy8vPHNpZ25hdHVyZT5cclxuICAgICAgICAgICAgLy8vPHN1bW1hcnk+U2V0dGluZyB0aGlzIHRha2VzIHByZWNlZGVuY2Ugb3ZlciBvcHRpb25zLm1pbkRhdGUsIG9wdGlvbnMubWF4RGF0ZSBjb25maWd1cmF0aW9uLiBBbHNvIGNhbGxpbmcgdGhpcyBmdW5jdGlvbiByZW1vdmVzIHRoZSBjb25maWd1cmF0aW9uIG9mXHJcbiAgICAgICAgICAgIC8vL29wdGlvbnMuZW5hYmxlZEhvdXJzIGlmIHN1Y2ggZXhpc3QuPC9zdW1tYXJ5PlxyXG4gICAgICAgICAgICAvLy88cGFyYW0gbmFtZT1cImhvdXJzXCIgbG9jaWQ9XCIkLmZuLmRhdGV0aW1lcGlja2VyLmRpc2FibGVkSG91cnNfcDpob3Vyc1wiPlRha2VzIGFuIFsgaW50IF0gb2YgdmFsdWVzIGFuZCBkaXNhbGxvd3MgdGhlIHVzZXIgdG8gc2VsZWN0IG9ubHkgZnJvbSB0aG9zZSBob3Vycy48L3BhcmFtPlxyXG4gICAgICAgICAgICAvLy88L3NpZ25hdHVyZT5cclxuICAgICAgICAgICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAob3B0aW9ucy5kaXNhYmxlZEhvdXJzID8gJC5leHRlbmQoe30sIG9wdGlvbnMuZGlzYWJsZWRIb3VycykgOiBvcHRpb25zLmRpc2FibGVkSG91cnMpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoIWhvdXJzKSB7XHJcbiAgICAgICAgICAgICAgICBvcHRpb25zLmRpc2FibGVkSG91cnMgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgIHVwZGF0ZSgpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoIShob3VycyBpbnN0YW5jZW9mIEFycmF5KSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignZGlzYWJsZWRIb3VycygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy5kaXNhYmxlZEhvdXJzID0gaW5kZXhHaXZlbkhvdXJzKGhvdXJzKTtcclxuICAgICAgICAgICAgb3B0aW9ucy5lbmFibGVkSG91cnMgPSBmYWxzZTtcclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMudXNlQ3VycmVudCAmJiAhb3B0aW9ucy5rZWVwSW52YWxpZCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcclxuICAgICAgICAgICAgICAgIHdoaWxlICghaXNWYWxpZChkYXRlLCAnaCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGF0ZS5hZGQoMSwgJ2gnKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDI0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAyNCB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBzZXRWYWx1ZShkYXRlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBwaWNrZXIuZW5hYmxlZEhvdXJzID0gZnVuY3Rpb24gKGhvdXJzKSB7XHJcbiAgICAgICAgICAgIC8vLzxzaWduYXR1cmUgaGVscEtleXdvcmQ9XCIkLmZuLmRhdGV0aW1lcGlja2VyLmVuYWJsZWRIb3Vyc1wiPlxyXG4gICAgICAgICAgICAvLy88c3VtbWFyeT5SZXR1cm5zIGFuIGFycmF5IHdpdGggdGhlIGN1cnJlbnRseSBzZXQgZW5hYmxlZCBob3VycyBvbiB0aGUgY29tcG9uZW50Ljwvc3VtbWFyeT5cclxuICAgICAgICAgICAgLy8vPHJldHVybnMgdHlwZT1cImFycmF5XCI+b3B0aW9ucy5lbmFibGVkSG91cnM8L3JldHVybnM+XHJcbiAgICAgICAgICAgIC8vLzwvc2lnbmF0dXJlPlxyXG4gICAgICAgICAgICAvLy88c2lnbmF0dXJlPlxyXG4gICAgICAgICAgICAvLy88c3VtbWFyeT5TZXR0aW5nIHRoaXMgdGFrZXMgcHJlY2VkZW5jZSBvdmVyIG9wdGlvbnMubWluRGF0ZSwgb3B0aW9ucy5tYXhEYXRlIGNvbmZpZ3VyYXRpb24uIEFsc28gY2FsbGluZyB0aGlzIGZ1bmN0aW9uIHJlbW92ZXMgdGhlIGNvbmZpZ3VyYXRpb24gb2Ygb3B0aW9ucy5kaXNhYmxlZEhvdXJzIGlmIHN1Y2ggZXhpc3QuPC9zdW1tYXJ5PlxyXG4gICAgICAgICAgICAvLy88cGFyYW0gbmFtZT1cImhvdXJzXCIgbG9jaWQ9XCIkLmZuLmRhdGV0aW1lcGlja2VyLmVuYWJsZWRIb3Vyc19wOmhvdXJzXCI+VGFrZXMgYW4gWyBpbnQgXSBvZiB2YWx1ZXMgYW5kIGFsbG93cyB0aGUgdXNlciB0byBzZWxlY3Qgb25seSBmcm9tIHRob3NlIGhvdXJzLjwvcGFyYW0+XHJcbiAgICAgICAgICAgIC8vLzwvc2lnbmF0dXJlPlxyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIChvcHRpb25zLmVuYWJsZWRIb3VycyA/ICQuZXh0ZW5kKHt9LCBvcHRpb25zLmVuYWJsZWRIb3VycykgOiBvcHRpb25zLmVuYWJsZWRIb3Vycyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghaG91cnMpIHtcclxuICAgICAgICAgICAgICAgIG9wdGlvbnMuZW5hYmxlZEhvdXJzID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKCEoaG91cnMgaW5zdGFuY2VvZiBBcnJheSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2VuYWJsZWRIb3VycygpIGV4cGVjdHMgYW4gYXJyYXkgcGFyYW1ldGVyJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb3B0aW9ucy5lbmFibGVkSG91cnMgPSBpbmRleEdpdmVuSG91cnMoaG91cnMpO1xyXG4gICAgICAgICAgICBvcHRpb25zLmRpc2FibGVkSG91cnMgPSBmYWxzZTtcclxuICAgICAgICAgICAgaWYgKG9wdGlvbnMudXNlQ3VycmVudCAmJiAhb3B0aW9ucy5rZWVwSW52YWxpZCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIHRyaWVzID0gMDtcclxuICAgICAgICAgICAgICAgIHdoaWxlICghaXNWYWxpZChkYXRlLCAnaCcpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGF0ZS5hZGQoMSwgJ2gnKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodHJpZXMgPT09IDI0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93ICdUcmllZCAyNCB0aW1lcyB0byBmaW5kIGEgdmFsaWQgZGF0ZSc7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIHRyaWVzKys7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBzZXRWYWx1ZShkYXRlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB1cGRhdGUoKTtcclxuICAgICAgICAgICAgcmV0dXJuIHBpY2tlcjtcclxuICAgICAgICB9O1xyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFJldHVybnMgdGhlIGNvbXBvbmVudCdzIG1vZGVsIGN1cnJlbnQgdmlld0RhdGUsIGEgbW9tZW50IG9iamVjdCBvciBudWxsIGlmIG5vdCBzZXQuIFBhc3NpbmcgYSBudWxsIHZhbHVlIHVuc2V0cyB0aGUgY29tcG9uZW50cyBtb2RlbCBjdXJyZW50IG1vbWVudC4gUGFyc2luZyBvZiB0aGUgbmV3RGF0ZSBwYXJhbWV0ZXIgaXMgbWFkZSB1c2luZyBtb21lbnQgbGlicmFyeSB3aXRoIHRoZSBvcHRpb25zLmZvcm1hdCBhbmQgb3B0aW9ucy51c2VTdHJpY3QgY29tcG9uZW50cyBjb25maWd1cmF0aW9uLlxyXG4gICAgICAgICAqIEBwYXJhbSB7VGFrZXMgc3RyaW5nLCB2aWV3RGF0ZSwgbW9tZW50LCBudWxsIHBhcmFtZXRlci59IG5ld0RhdGVcclxuICAgICAgICAgKiBAcmV0dXJucyB7dmlld0RhdGUuY2xvbmUoKX1cclxuICAgICAgICAgKi9cclxuICAgICAgICBwaWNrZXIudmlld0RhdGUgPSBmdW5jdGlvbiAobmV3RGF0ZSkge1xyXG4gICAgICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHZpZXdEYXRlLmNsb25lKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghbmV3RGF0ZSkge1xyXG4gICAgICAgICAgICAgICAgdmlld0RhdGUgPSBkYXRlLmNsb25lKCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcGlja2VyO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG5ld0RhdGUgIT09ICdzdHJpbmcnICYmICFtb21lbnQuaXNNb21lbnQobmV3RGF0ZSkgJiYgIShuZXdEYXRlIGluc3RhbmNlb2YgRGF0ZSkpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ3ZpZXdEYXRlKCkgcGFyYW1ldGVyIG11c3QgYmUgb25lIG9mIFtzdHJpbmcsIG1vbWVudCBvciBEYXRlXScpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB2aWV3RGF0ZSA9IHBhcnNlSW5wdXREYXRlKG5ld0RhdGUpO1xyXG4gICAgICAgICAgICB2aWV3VXBkYXRlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLy8gaW5pdGlhbGl6aW5nIGVsZW1lbnQgYW5kIGNvbXBvbmVudCBhdHRyaWJ1dGVzXHJcbiAgICAgICAgaWYgKGVsZW1lbnQuaXMoJ2lucHV0JykpIHtcclxuICAgICAgICAgICAgaW5wdXQgPSBlbGVtZW50O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGlucHV0ID0gZWxlbWVudC5maW5kKG9wdGlvbnMuZGF0ZXBpY2tlcklucHV0KTtcclxuICAgICAgICAgICAgaWYgKGlucHV0Lmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgaW5wdXQgPSBlbGVtZW50LmZpbmQoJ2lucHV0Jyk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoIWlucHV0LmlzKCdpbnB1dCcpKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NTUyBjbGFzcyBcIicgKyBvcHRpb25zLmRhdGVwaWNrZXJJbnB1dCArICdcIiBjYW5ub3QgYmUgYXBwbGllZCB0byBub24gaW5wdXQgZWxlbWVudCcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoZWxlbWVudC5oYXNDbGFzcygnaW5wdXQtZ3JvdXAnKSkge1xyXG4gICAgICAgICAgICAvLyBpbiBjYXNlIHRoZXJlIGlzIG1vcmUgdGhlbiBvbmUgJ2lucHV0LWdyb3VwLWFkZG9uJyBJc3N1ZSAjNDhcclxuICAgICAgICAgICAgaWYgKGVsZW1lbnQuZmluZCgnLmRhdGVwaWNrZXJidXR0b24nKS5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgIGNvbXBvbmVudCA9IGVsZW1lbnQuZmluZCgnLmlucHV0LWdyb3VwLWFkZG9uJyk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBjb21wb25lbnQgPSBlbGVtZW50LmZpbmQoJy5kYXRlcGlja2VyYnV0dG9uJyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghb3B0aW9ucy5pbmxpbmUgJiYgIWlucHV0LmlzKCdpbnB1dCcpKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ291bGQgbm90IGluaXRpYWxpemUgRGF0ZVRpbWVQaWNrZXIgd2l0aG91dCBhbiBpbnB1dCBlbGVtZW50Jyk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTZXQgZGVmYXVsdHMgZm9yIGRhdGUgaGVyZSBub3cgaW5zdGVhZCBvZiBpbiB2YXIgZGVjbGFyYXRpb25cclxuICAgICAgICBkYXRlID0gZ2V0TW9tZW50KCk7XHJcbiAgICAgICAgdmlld0RhdGUgPSBkYXRlLmNsb25lKCk7XHJcblxyXG4gICAgICAgICQuZXh0ZW5kKHRydWUsIG9wdGlvbnMsIGRhdGFUb09wdGlvbnMoKSk7XHJcblxyXG4gICAgICAgIHBpY2tlci5vcHRpb25zKG9wdGlvbnMpO1xyXG5cclxuICAgICAgICBpbml0Rm9ybWF0dGluZygpO1xyXG5cclxuICAgICAgICBhdHRhY2hEYXRlUGlja2VyRWxlbWVudEV2ZW50cygpO1xyXG5cclxuICAgICAgICBpZiAoaW5wdXQucHJvcCgnZGlzYWJsZWQnKSkge1xyXG4gICAgICAgICAgICBwaWNrZXIuZGlzYWJsZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoaW5wdXQuaXMoJ2lucHV0JykgJiYgaW5wdXQudmFsKCkudHJpbSgpLmxlbmd0aCAhPT0gMCkge1xyXG4gICAgICAgICAgICBzZXRWYWx1ZShwYXJzZUlucHV0RGF0ZShpbnB1dC52YWwoKS50cmltKCkpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgZWxzZSBpZiAob3B0aW9ucy5kZWZhdWx0RGF0ZSAmJiBpbnB1dC5hdHRyKCdwbGFjZWhvbGRlcicpID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgc2V0VmFsdWUob3B0aW9ucy5kZWZhdWx0RGF0ZSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChvcHRpb25zLmlubGluZSkge1xyXG4gICAgICAgICAgICBzaG93KCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBwaWNrZXI7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gICAgICpcclxuICAgICAqIGpRdWVyeSBwbHVnaW4gY29uc3RydWN0b3IgYW5kIGRlZmF1bHRzIG9iamVjdFxyXG4gICAgICpcclxuICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuXHJcbiAgICAvKipcclxuICAgICogU2VlIChodHRwOi8vanF1ZXJ5LmNvbS8pLlxyXG4gICAgKiBAbmFtZSBqUXVlcnlcclxuICAgICogQGNsYXNzXHJcbiAgICAqIFNlZSB0aGUgalF1ZXJ5IExpYnJhcnkgIChodHRwOi8vanF1ZXJ5LmNvbS8pIGZvciBmdWxsIGRldGFpbHMuICBUaGlzIGp1c3RcclxuICAgICogZG9jdW1lbnRzIHRoZSBmdW5jdGlvbiBhbmQgY2xhc3NlcyB0aGF0IGFyZSBhZGRlZCB0byBqUXVlcnkgYnkgdGhpcyBwbHVnLWluLlxyXG4gICAgKi9cclxuICAgIC8qKlxyXG4gICAgICogU2VlIChodHRwOi8vanF1ZXJ5LmNvbS8pXHJcbiAgICAgKiBAbmFtZSBmblxyXG4gICAgICogQGNsYXNzXHJcbiAgICAgKiBTZWUgdGhlIGpRdWVyeSBMaWJyYXJ5ICAoaHR0cDovL2pxdWVyeS5jb20vKSBmb3IgZnVsbCBkZXRhaWxzLiAgVGhpcyBqdXN0XHJcbiAgICAgKiBkb2N1bWVudHMgdGhlIGZ1bmN0aW9uIGFuZCBjbGFzc2VzIHRoYXQgYXJlIGFkZGVkIHRvIGpRdWVyeSBieSB0aGlzIHBsdWctaW4uXHJcbiAgICAgKiBAbWVtYmVyT2YgalF1ZXJ5XHJcbiAgICAgKi9cclxuICAgIC8qKlxyXG4gICAgICogU2hvdyBjb21tZW50c1xyXG4gICAgICogQGNsYXNzIGRhdGV0aW1lcGlja2VyXHJcbiAgICAgKiBAbWVtYmVyT2YgalF1ZXJ5LmZuXHJcbiAgICAgKi9cclxuICAgICQuZm4uZGF0ZXRpbWVwaWNrZXIgPSBmdW5jdGlvbiAob3B0aW9ucykge1xyXG4gICAgICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xyXG5cclxuICAgICAgICB2YXIgYXJncyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSksXHJcbiAgICAgICAgICAgIGlzSW5zdGFuY2UgPSB0cnVlLFxyXG4gICAgICAgICAgICB0aGlzTWV0aG9kcyA9IFsnZGVzdHJveScsICdoaWRlJywgJ3Nob3cnLCAndG9nZ2xlJ10sXHJcbiAgICAgICAgICAgIHJldHVyblZhbHVlO1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIG9wdGlvbnMgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVhY2goZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgdmFyICR0aGlzID0gJCh0aGlzKSxcclxuICAgICAgICAgICAgICAgICAgICBfb3B0aW9ucztcclxuICAgICAgICAgICAgICAgIGlmICghJHRoaXMuZGF0YSgnRGF0ZVRpbWVQaWNrZXInKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIGNyZWF0ZSBhIHByaXZhdGUgY29weSBvZiB0aGUgZGVmYXVsdHMgb2JqZWN0XHJcbiAgICAgICAgICAgICAgICAgICAgX29wdGlvbnMgPSAkLmV4dGVuZCh0cnVlLCB7fSwgJC5mbi5kYXRldGltZXBpY2tlci5kZWZhdWx0cywgb3B0aW9ucyk7XHJcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuZGF0YSgnRGF0ZVRpbWVQaWNrZXInLCBkYXRlVGltZVBpY2tlcigkdGhpcywgX29wdGlvbnMpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb3B0aW9ucyA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgdGhpcy5lYWNoKGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHZhciAkdGhpcyA9ICQodGhpcyksXHJcbiAgICAgICAgICAgICAgICAgICAgaW5zdGFuY2UgPSAkdGhpcy5kYXRhKCdEYXRlVGltZVBpY2tlcicpO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFpbnN0YW5jZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYm9vdHN0cmFwLWRhdGV0aW1lcGlja2VyKFwiJyArIG9wdGlvbnMgKyAnXCIpIG1ldGhvZCB3YXMgY2FsbGVkIG9uIGFuIGVsZW1lbnQgdGhhdCBpcyBub3QgdXNpbmcgRGF0ZVRpbWVQaWNrZXInKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICByZXR1cm5WYWx1ZSA9IGluc3RhbmNlW29wdGlvbnNdLmFwcGx5KGluc3RhbmNlLCBhcmdzKTtcclxuICAgICAgICAgICAgICAgIGlzSW5zdGFuY2UgPSByZXR1cm5WYWx1ZSA9PT0gaW5zdGFuY2U7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgaWYgKGlzSW5zdGFuY2UgfHwgJC5pbkFycmF5KG9wdGlvbnMsIHRoaXNNZXRob2RzKSA+IC0xKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHJldHVyblZhbHVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCBhcmd1bWVudHMgZm9yIERhdGVUaW1lUGlja2VyOiAnICsgb3B0aW9ucyk7XHJcbiAgICB9O1xyXG5cclxuICAgICQuZm4uZGF0ZXRpbWVwaWNrZXIuZGVmYXVsdHMgPSB7XHJcbiAgICAgICAgdGltZVpvbmU6ICcnLFxyXG4gICAgICAgIGZvcm1hdDogZmFsc2UsXHJcbiAgICAgICAgZGF5Vmlld0hlYWRlckZvcm1hdDogJ01NTU0gWVlZWScsXHJcbiAgICAgICAgZXh0cmFGb3JtYXRzOiBmYWxzZSxcclxuICAgICAgICBzdGVwcGluZzogMSxcclxuICAgICAgICBtaW5EYXRlOiBmYWxzZSxcclxuICAgICAgICBtYXhEYXRlOiBmYWxzZSxcclxuICAgICAgICB1c2VDdXJyZW50OiB0cnVlLFxyXG4gICAgICAgIGNvbGxhcHNlOiB0cnVlLFxyXG4gICAgICAgIGxvY2FsZTogbW9tZW50LmxvY2FsZSgpLFxyXG4gICAgICAgIGRlZmF1bHREYXRlOiBmYWxzZSxcclxuICAgICAgICBkaXNhYmxlZERhdGVzOiBmYWxzZSxcclxuICAgICAgICBlbmFibGVkRGF0ZXM6IGZhbHNlLFxyXG4gICAgICAgIGljb25zOiB7XHJcbiAgICAgICAgICAgIHRpbWU6ICdnbHlwaGljb24gZ2x5cGhpY29uLXRpbWUnLFxyXG4gICAgICAgICAgICBkYXRlOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1jYWxlbmRhcicsXHJcbiAgICAgICAgICAgIHVwOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1jaGV2cm9uLXVwJyxcclxuICAgICAgICAgICAgZG93bjogJ2dseXBoaWNvbiBnbHlwaGljb24tY2hldnJvbi1kb3duJyxcclxuICAgICAgICAgICAgcHJldmlvdXM6ICdnbHlwaGljb24gZ2x5cGhpY29uLWNoZXZyb24tbGVmdCcsXHJcbiAgICAgICAgICAgIG5leHQ6ICdnbHlwaGljb24gZ2x5cGhpY29uLWNoZXZyb24tcmlnaHQnLFxyXG4gICAgICAgICAgICB0b2RheTogJ2dseXBoaWNvbiBnbHlwaGljb24tc2NyZWVuc2hvdCcsXHJcbiAgICAgICAgICAgIGNsZWFyOiAnZ2x5cGhpY29uIGdseXBoaWNvbi10cmFzaCcsXHJcbiAgICAgICAgICAgIGNsb3NlOiAnZ2x5cGhpY29uIGdseXBoaWNvbi1yZW1vdmUnXHJcbiAgICAgICAgfSxcclxuICAgICAgICB0b29sdGlwczoge1xyXG4gICAgICAgICAgICB0b2RheTogJ0dvIHRvIHRvZGF5JyxcclxuICAgICAgICAgICAgY2xlYXI6ICdDbGVhciBzZWxlY3Rpb24nLFxyXG4gICAgICAgICAgICBjbG9zZTogJ0Nsb3NlIHRoZSBwaWNrZXInLFxyXG4gICAgICAgICAgICBzZWxlY3RNb250aDogJ1NlbGVjdCBNb250aCcsXHJcbiAgICAgICAgICAgIHByZXZNb250aDogJ1ByZXZpb3VzIE1vbnRoJyxcclxuICAgICAgICAgICAgbmV4dE1vbnRoOiAnTmV4dCBNb250aCcsXHJcbiAgICAgICAgICAgIHNlbGVjdFllYXI6ICdTZWxlY3QgWWVhcicsXHJcbiAgICAgICAgICAgIHByZXZZZWFyOiAnUHJldmlvdXMgWWVhcicsXHJcbiAgICAgICAgICAgIG5leHRZZWFyOiAnTmV4dCBZZWFyJyxcclxuICAgICAgICAgICAgc2VsZWN0RGVjYWRlOiAnU2VsZWN0IERlY2FkZScsXHJcbiAgICAgICAgICAgIHByZXZEZWNhZGU6ICdQcmV2aW91cyBEZWNhZGUnLFxyXG4gICAgICAgICAgICBuZXh0RGVjYWRlOiAnTmV4dCBEZWNhZGUnLFxyXG4gICAgICAgICAgICBwcmV2Q2VudHVyeTogJ1ByZXZpb3VzIENlbnR1cnknLFxyXG4gICAgICAgICAgICBuZXh0Q2VudHVyeTogJ05leHQgQ2VudHVyeScsXHJcbiAgICAgICAgICAgIHBpY2tIb3VyOiAnUGljayBIb3VyJyxcclxuICAgICAgICAgICAgaW5jcmVtZW50SG91cjogJ0luY3JlbWVudCBIb3VyJyxcclxuICAgICAgICAgICAgZGVjcmVtZW50SG91cjogJ0RlY3JlbWVudCBIb3VyJyxcclxuICAgICAgICAgICAgcGlja01pbnV0ZTogJ1BpY2sgTWludXRlJyxcclxuICAgICAgICAgICAgaW5jcmVtZW50TWludXRlOiAnSW5jcmVtZW50IE1pbnV0ZScsXHJcbiAgICAgICAgICAgIGRlY3JlbWVudE1pbnV0ZTogJ0RlY3JlbWVudCBNaW51dGUnLFxyXG4gICAgICAgICAgICBwaWNrU2Vjb25kOiAnUGljayBTZWNvbmQnLFxyXG4gICAgICAgICAgICBpbmNyZW1lbnRTZWNvbmQ6ICdJbmNyZW1lbnQgU2Vjb25kJyxcclxuICAgICAgICAgICAgZGVjcmVtZW50U2Vjb25kOiAnRGVjcmVtZW50IFNlY29uZCcsXHJcbiAgICAgICAgICAgIHRvZ2dsZVBlcmlvZDogJ1RvZ2dsZSBQZXJpb2QnLFxyXG4gICAgICAgICAgICBzZWxlY3RUaW1lOiAnU2VsZWN0IFRpbWUnXHJcbiAgICAgICAgfSxcclxuICAgICAgICB1c2VTdHJpY3Q6IGZhbHNlLFxyXG4gICAgICAgIHNpZGVCeVNpZGU6IGZhbHNlLFxyXG4gICAgICAgIGRheXNPZldlZWtEaXNhYmxlZDogZmFsc2UsXHJcbiAgICAgICAgY2FsZW5kYXJXZWVrczogZmFsc2UsXHJcbiAgICAgICAgdmlld01vZGU6ICdkYXlzJyxcclxuICAgICAgICB0b29sYmFyUGxhY2VtZW50OiAnZGVmYXVsdCcsXHJcbiAgICAgICAgc2hvd1RvZGF5QnV0dG9uOiBmYWxzZSxcclxuICAgICAgICBzaG93Q2xlYXI6IGZhbHNlLFxyXG4gICAgICAgIHNob3dDbG9zZTogZmFsc2UsXHJcbiAgICAgICAgd2lkZ2V0UG9zaXRpb25pbmc6IHtcclxuICAgICAgICAgICAgaG9yaXpvbnRhbDogJ2F1dG8nLFxyXG4gICAgICAgICAgICB2ZXJ0aWNhbDogJ2F1dG8nXHJcbiAgICAgICAgfSxcclxuICAgICAgICB3aWRnZXRQYXJlbnQ6IG51bGwsXHJcbiAgICAgICAgaWdub3JlUmVhZG9ubHk6IGZhbHNlLFxyXG4gICAgICAgIGtlZXBPcGVuOiBmYWxzZSxcclxuICAgICAgICBmb2N1c09uU2hvdzogdHJ1ZSxcclxuICAgICAgICBpbmxpbmU6IGZhbHNlLFxyXG4gICAgICAgIGtlZXBJbnZhbGlkOiBmYWxzZSxcclxuICAgICAgICBkYXRlcGlja2VySW5wdXQ6ICcuZGF0ZXBpY2tlcmlucHV0JyxcclxuICAgICAgICBrZXlCaW5kczoge1xyXG4gICAgICAgICAgICB1cDogZnVuY3Rpb24gKHdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuZGF0ZSgpIHx8IHRoaXMuZ2V0TW9tZW50KCk7XHJcbiAgICAgICAgICAgICAgICBpZiAod2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDcsICdkJykpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCh0aGlzLnN0ZXBwaW5nKCksICdtJykpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBkb3duOiBmdW5jdGlvbiAod2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2hvdygpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHZhciBkID0gdGhpcy5kYXRlKCkgfHwgdGhpcy5nZXRNb21lbnQoKTtcclxuICAgICAgICAgICAgICAgIGlmICh3aWRnZXQuZmluZCgnLmRhdGVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuYWRkKDcsICdkJykpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KHRoaXMuc3RlcHBpbmcoKSwgJ20nKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICdjb250cm9sIHVwJzogZnVuY3Rpb24gKHdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuZGF0ZSgpIHx8IHRoaXMuZ2V0TW9tZW50KCk7XHJcbiAgICAgICAgICAgICAgICBpZiAod2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICd5JykpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnaCcpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgJ2NvbnRyb2wgZG93bic6IGZ1bmN0aW9uICh3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgIGlmICghd2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLmRhdGUoKSB8fCB0aGlzLmdldE1vbWVudCgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHdpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ3knKSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShkLmNsb25lKCkuc3VidHJhY3QoMSwgJ2gnKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIGxlZnQ6IGZ1bmN0aW9uICh3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgIGlmICghd2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLmRhdGUoKSB8fCB0aGlzLmdldE1vbWVudCgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHdpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5zdWJ0cmFjdCgxLCAnZCcpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgcmlnaHQ6IGZ1bmN0aW9uICh3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgIGlmICghd2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgdmFyIGQgPSB0aGlzLmRhdGUoKSB8fCB0aGlzLmdldE1vbWVudCgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKHdpZGdldC5maW5kKCcuZGF0ZXBpY2tlcicpLmlzKCc6dmlzaWJsZScpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKGQuY2xvbmUoKS5hZGQoMSwgJ2QnKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIHBhZ2VVcDogZnVuY3Rpb24gKHdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuZGF0ZSgpIHx8IHRoaXMuZ2V0TW9tZW50KCk7XHJcbiAgICAgICAgICAgICAgICBpZiAod2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLnN1YnRyYWN0KDEsICdNJykpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBwYWdlRG93bjogZnVuY3Rpb24gKHdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF3aWRnZXQpIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB2YXIgZCA9IHRoaXMuZGF0ZSgpIHx8IHRoaXMuZ2V0TW9tZW50KCk7XHJcbiAgICAgICAgICAgICAgICBpZiAod2lkZ2V0LmZpbmQoJy5kYXRlcGlja2VyJykuaXMoJzp2aXNpYmxlJykpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoZC5jbG9uZSgpLmFkZCgxLCAnTScpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgZW50ZXI6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBlc2NhcGU6IGZ1bmN0aW9uICgpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuaGlkZSgpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAvL3RhYjogZnVuY3Rpb24gKHdpZGdldCkgeyAvL3RoaXMgYnJlYWsgdGhlIGZsb3cgb2YgdGhlIGZvcm0uIGRpc2FibGluZyBmb3Igbm93XHJcbiAgICAgICAgICAgIC8vICAgIHZhciB0b2dnbGUgPSB3aWRnZXQuZmluZCgnLnBpY2tlci1zd2l0Y2ggYVtkYXRhLWFjdGlvbj1cInRvZ2dsZVBpY2tlclwiXScpO1xyXG4gICAgICAgICAgICAvLyAgICBpZih0b2dnbGUubGVuZ3RoID4gMCkgdG9nZ2xlLmNsaWNrKCk7XHJcbiAgICAgICAgICAgIC8vfSxcclxuICAgICAgICAgICAgJ2NvbnRyb2wgc3BhY2UnOiBmdW5jdGlvbiAod2lkZ2V0KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXdpZGdldCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmICh3aWRnZXQuZmluZCgnLnRpbWVwaWNrZXInKS5pcygnOnZpc2libGUnKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHdpZGdldC5maW5kKCcuYnRuW2RhdGEtYWN0aW9uPVwidG9nZ2xlUGVyaW9kXCJdJykuY2xpY2soKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgdDogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlKHRoaXMuZ2V0TW9tZW50KCkpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAnZGVsZXRlJzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhcigpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuICAgICAgICBkZWJ1ZzogZmFsc2UsXHJcbiAgICAgICAgYWxsb3dJbnB1dFRvZ2dsZTogZmFsc2UsXHJcbiAgICAgICAgZGlzYWJsZWRUaW1lSW50ZXJ2YWxzOiBmYWxzZSxcclxuICAgICAgICBkaXNhYmxlZEhvdXJzOiBmYWxzZSxcclxuICAgICAgICBlbmFibGVkSG91cnM6IGZhbHNlLFxyXG4gICAgICAgIHZpZXdEYXRlOiBmYWxzZVxyXG4gICAgfTtcclxuXHJcbiAgICByZXR1cm4gJC5mbi5kYXRldGltZXBpY2tlcjtcclxufSkpO1xyXG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9lb25hc2Rhbi1ib290c3RyYXAtZGF0ZXRpbWVwaWNrZXIvc3JjL2pzL2Jvb3RzdHJhcC1kYXRldGltZXBpY2tlci5qc1xuLy8gbW9kdWxlIGlkID0gMTM2XG4vLyBtb2R1bGUgY2h1bmtzID0gMCIsIi8qIVxuXHRDb2xvcmJveCAxLjYuNFxuXHRsaWNlbnNlOiBNSVRcblx0aHR0cDovL3d3dy5qYWNrbG1vb3JlLmNvbS9jb2xvcmJveFxuKi9cbihmdW5jdGlvbiAoJCwgZG9jdW1lbnQsIHdpbmRvdykge1xuXHR2YXJcblx0Ly8gRGVmYXVsdCBzZXR0aW5ncyBvYmplY3QuXG5cdC8vIFNlZSBodHRwOi8vamFja2xtb29yZS5jb20vY29sb3Jib3ggZm9yIGRldGFpbHMuXG5cdGRlZmF1bHRzID0ge1xuXHRcdC8vIGRhdGEgc291cmNlc1xuXHRcdGh0bWw6IGZhbHNlLFxuXHRcdHBob3RvOiBmYWxzZSxcblx0XHRpZnJhbWU6IGZhbHNlLFxuXHRcdGlubGluZTogZmFsc2UsXG5cblx0XHQvLyBiZWhhdmlvciBhbmQgYXBwZWFyYW5jZVxuXHRcdHRyYW5zaXRpb246IFwiZWxhc3RpY1wiLFxuXHRcdHNwZWVkOiAzMDAsXG5cdFx0ZmFkZU91dDogMzAwLFxuXHRcdHdpZHRoOiBmYWxzZSxcblx0XHRpbml0aWFsV2lkdGg6IFwiNjAwXCIsXG5cdFx0aW5uZXJXaWR0aDogZmFsc2UsXG5cdFx0bWF4V2lkdGg6IGZhbHNlLFxuXHRcdGhlaWdodDogZmFsc2UsXG5cdFx0aW5pdGlhbEhlaWdodDogXCI0NTBcIixcblx0XHRpbm5lckhlaWdodDogZmFsc2UsXG5cdFx0bWF4SGVpZ2h0OiBmYWxzZSxcblx0XHRzY2FsZVBob3RvczogdHJ1ZSxcblx0XHRzY3JvbGxpbmc6IHRydWUsXG5cdFx0b3BhY2l0eTogMC45LFxuXHRcdHByZWxvYWRpbmc6IHRydWUsXG5cdFx0Y2xhc3NOYW1lOiBmYWxzZSxcblx0XHRvdmVybGF5Q2xvc2U6IHRydWUsXG5cdFx0ZXNjS2V5OiB0cnVlLFxuXHRcdGFycm93S2V5OiB0cnVlLFxuXHRcdHRvcDogZmFsc2UsXG5cdFx0Ym90dG9tOiBmYWxzZSxcblx0XHRsZWZ0OiBmYWxzZSxcblx0XHRyaWdodDogZmFsc2UsXG5cdFx0Zml4ZWQ6IGZhbHNlLFxuXHRcdGRhdGE6IHVuZGVmaW5lZCxcblx0XHRjbG9zZUJ1dHRvbjogdHJ1ZSxcblx0XHRmYXN0SWZyYW1lOiB0cnVlLFxuXHRcdG9wZW46IGZhbHNlLFxuXHRcdHJlcG9zaXRpb246IHRydWUsXG5cdFx0bG9vcDogdHJ1ZSxcblx0XHRzbGlkZXNob3c6IGZhbHNlLFxuXHRcdHNsaWRlc2hvd0F1dG86IHRydWUsXG5cdFx0c2xpZGVzaG93U3BlZWQ6IDI1MDAsXG5cdFx0c2xpZGVzaG93U3RhcnQ6IFwic3RhcnQgc2xpZGVzaG93XCIsXG5cdFx0c2xpZGVzaG93U3RvcDogXCJzdG9wIHNsaWRlc2hvd1wiLFxuXHRcdHBob3RvUmVnZXg6IC9cXC4oZ2lmfHBuZ3xqcChlfGd8ZWcpfGJtcHxpY298d2VicHxqeHJ8c3ZnKSgoI3xcXD8pLiopPyQvaSxcblxuXHRcdC8vIGFsdGVybmF0ZSBpbWFnZSBwYXRocyBmb3IgaGlnaC1yZXMgZGlzcGxheXNcblx0XHRyZXRpbmFJbWFnZTogZmFsc2UsXG5cdFx0cmV0aW5hVXJsOiBmYWxzZSxcblx0XHRyZXRpbmFTdWZmaXg6ICdAMnguJDEnLFxuXG5cdFx0Ly8gaW50ZXJuYXRpb25hbGl6YXRpb25cblx0XHRjdXJyZW50OiBcImltYWdlIHtjdXJyZW50fSBvZiB7dG90YWx9XCIsXG5cdFx0cHJldmlvdXM6IFwicHJldmlvdXNcIixcblx0XHRuZXh0OiBcIm5leHRcIixcblx0XHRjbG9zZTogXCJjbG9zZVwiLFxuXHRcdHhockVycm9yOiBcIlRoaXMgY29udGVudCBmYWlsZWQgdG8gbG9hZC5cIixcblx0XHRpbWdFcnJvcjogXCJUaGlzIGltYWdlIGZhaWxlZCB0byBsb2FkLlwiLFxuXG5cdFx0Ly8gYWNjZXNzYmlsaXR5XG5cdFx0cmV0dXJuRm9jdXM6IHRydWUsXG5cdFx0dHJhcEZvY3VzOiB0cnVlLFxuXG5cdFx0Ly8gY2FsbGJhY2tzXG5cdFx0b25PcGVuOiBmYWxzZSxcblx0XHRvbkxvYWQ6IGZhbHNlLFxuXHRcdG9uQ29tcGxldGU6IGZhbHNlLFxuXHRcdG9uQ2xlYW51cDogZmFsc2UsXG5cdFx0b25DbG9zZWQ6IGZhbHNlLFxuXG5cdFx0cmVsOiBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiB0aGlzLnJlbDtcblx0XHR9LFxuXHRcdGhyZWY6IGZ1bmN0aW9uKCkge1xuXHRcdFx0Ly8gdXNpbmcgdGhpcy5ocmVmIHdvdWxkIGdpdmUgdGhlIGFic29sdXRlIHVybCwgd2hlbiB0aGUgaHJlZiBtYXkgaGF2ZSBiZWVuIGludGVkZWQgYXMgYSBzZWxlY3RvciAoZS5nLiAnI2NvbnRhaW5lcicpXG5cdFx0XHRyZXR1cm4gJCh0aGlzKS5hdHRyKCdocmVmJyk7XG5cdFx0fSxcblx0XHR0aXRsZTogZnVuY3Rpb24oKSB7XG5cdFx0XHRyZXR1cm4gdGhpcy50aXRsZTtcblx0XHR9LFxuXHRcdGNyZWF0ZUltZzogZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgaW1nID0gbmV3IEltYWdlKCk7XG5cdFx0XHR2YXIgYXR0cnMgPSAkKHRoaXMpLmRhdGEoJ2Nib3gtaW1nLWF0dHJzJyk7XG5cblx0XHRcdGlmICh0eXBlb2YgYXR0cnMgPT09ICdvYmplY3QnKSB7XG5cdFx0XHRcdCQuZWFjaChhdHRycywgZnVuY3Rpb24oa2V5LCB2YWwpe1xuXHRcdFx0XHRcdGltZ1trZXldID0gdmFsO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0cmV0dXJuIGltZztcblx0XHR9LFxuXHRcdGNyZWF0ZUlmcmFtZTogZnVuY3Rpb24oKSB7XG5cdFx0XHR2YXIgaWZyYW1lID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaWZyYW1lJyk7XG5cdFx0XHR2YXIgYXR0cnMgPSAkKHRoaXMpLmRhdGEoJ2Nib3gtaWZyYW1lLWF0dHJzJyk7XG5cblx0XHRcdGlmICh0eXBlb2YgYXR0cnMgPT09ICdvYmplY3QnKSB7XG5cdFx0XHRcdCQuZWFjaChhdHRycywgZnVuY3Rpb24oa2V5LCB2YWwpe1xuXHRcdFx0XHRcdGlmcmFtZVtrZXldID0gdmFsO1xuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCdmcmFtZUJvcmRlcicgaW4gaWZyYW1lKSB7XG5cdFx0XHRcdGlmcmFtZS5mcmFtZUJvcmRlciA9IDA7XG5cdFx0XHR9XG5cdFx0XHRpZiAoJ2FsbG93VHJhbnNwYXJlbmN5JyBpbiBpZnJhbWUpIHtcblx0XHRcdFx0aWZyYW1lLmFsbG93VHJhbnNwYXJlbmN5ID0gXCJ0cnVlXCI7XG5cdFx0XHR9XG5cdFx0XHRpZnJhbWUubmFtZSA9IChuZXcgRGF0ZSgpKS5nZXRUaW1lKCk7IC8vIGdpdmUgdGhlIGlmcmFtZSBhIHVuaXF1ZSBuYW1lIHRvIHByZXZlbnQgY2FjaGluZ1xuXHRcdFx0aWZyYW1lLmFsbG93RnVsbHNjcmVlbiA9IHRydWU7XG5cblx0XHRcdHJldHVybiBpZnJhbWU7XG5cdFx0fVxuXHR9LFxuXG5cdC8vIEFic3RyYWN0aW5nIHRoZSBIVE1MIGFuZCBldmVudCBpZGVudGlmaWVycyBmb3IgZWFzeSByZWJyYW5kaW5nXG5cdGNvbG9yYm94ID0gJ2NvbG9yYm94Jyxcblx0cHJlZml4ID0gJ2Nib3gnLFxuXHRib3hFbGVtZW50ID0gcHJlZml4ICsgJ0VsZW1lbnQnLFxuXG5cdC8vIEV2ZW50c1xuXHRldmVudF9vcGVuID0gcHJlZml4ICsgJ19vcGVuJyxcblx0ZXZlbnRfbG9hZCA9IHByZWZpeCArICdfbG9hZCcsXG5cdGV2ZW50X2NvbXBsZXRlID0gcHJlZml4ICsgJ19jb21wbGV0ZScsXG5cdGV2ZW50X2NsZWFudXAgPSBwcmVmaXggKyAnX2NsZWFudXAnLFxuXHRldmVudF9jbG9zZWQgPSBwcmVmaXggKyAnX2Nsb3NlZCcsXG5cdGV2ZW50X3B1cmdlID0gcHJlZml4ICsgJ19wdXJnZScsXG5cblx0Ly8gQ2FjaGVkIGpRdWVyeSBPYmplY3QgVmFyaWFibGVzXG5cdCRvdmVybGF5LFxuXHQkYm94LFxuXHQkd3JhcCxcblx0JGNvbnRlbnQsXG5cdCR0b3BCb3JkZXIsXG5cdCRsZWZ0Qm9yZGVyLFxuXHQkcmlnaHRCb3JkZXIsXG5cdCRib3R0b21Cb3JkZXIsXG5cdCRyZWxhdGVkLFxuXHQkd2luZG93LFxuXHQkbG9hZGVkLFxuXHQkbG9hZGluZ0JheSxcblx0JGxvYWRpbmdPdmVybGF5LFxuXHQkdGl0bGUsXG5cdCRjdXJyZW50LFxuXHQkc2xpZGVzaG93LFxuXHQkbmV4dCxcblx0JHByZXYsXG5cdCRjbG9zZSxcblx0JGdyb3VwQ29udHJvbHMsXG5cdCRldmVudHMgPSAkKCc8YS8+JyksIC8vICQoe30pIHdvdWxkIGJlIHByZWZlcmVkLCBidXQgdGhlcmUgaXMgYW4gaXNzdWUgd2l0aCBqUXVlcnkgMS40LjJcblxuXHQvLyBWYXJpYWJsZXMgZm9yIGNhY2hlZCB2YWx1ZXMgb3IgdXNlIGFjcm9zcyBtdWx0aXBsZSBmdW5jdGlvbnNcblx0c2V0dGluZ3MsXG5cdGludGVyZmFjZUhlaWdodCxcblx0aW50ZXJmYWNlV2lkdGgsXG5cdGxvYWRlZEhlaWdodCxcblx0bG9hZGVkV2lkdGgsXG5cdGluZGV4LFxuXHRwaG90byxcblx0b3Blbixcblx0YWN0aXZlLFxuXHRjbG9zaW5nLFxuXHRsb2FkaW5nVGltZXIsXG5cdHB1YmxpY01ldGhvZCxcblx0ZGl2ID0gXCJkaXZcIixcblx0cmVxdWVzdHMgPSAwLFxuXHRwcmV2aW91c0NTUyA9IHt9LFxuXHRpbml0O1xuXG5cdC8vICoqKioqKioqKioqKioqKipcblx0Ly8gSEVMUEVSIEZVTkNUSU9OU1xuXHQvLyAqKioqKioqKioqKioqKioqXG5cblx0Ly8gQ29udmVuaWVuY2UgZnVuY3Rpb24gZm9yIGNyZWF0aW5nIG5ldyBqUXVlcnkgb2JqZWN0c1xuXHRmdW5jdGlvbiAkdGFnKHRhZywgaWQsIGNzcykge1xuXHRcdHZhciBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCh0YWcpO1xuXG5cdFx0aWYgKGlkKSB7XG5cdFx0XHRlbGVtZW50LmlkID0gcHJlZml4ICsgaWQ7XG5cdFx0fVxuXG5cdFx0aWYgKGNzcykge1xuXHRcdFx0ZWxlbWVudC5zdHlsZS5jc3NUZXh0ID0gY3NzO1xuXHRcdH1cblxuXHRcdHJldHVybiAkKGVsZW1lbnQpO1xuXHR9XG5cblx0Ly8gR2V0IHRoZSB3aW5kb3cgaGVpZ2h0IHVzaW5nIGlubmVySGVpZ2h0IHdoZW4gYXZhaWxhYmxlIHRvIGF2b2lkIGFuIGlzc3VlIHdpdGggaU9TXG5cdC8vIGh0dHA6Ly9idWdzLmpxdWVyeS5jb20vdGlja2V0LzY3MjRcblx0ZnVuY3Rpb24gd2luaGVpZ2h0KCkge1xuXHRcdHJldHVybiB3aW5kb3cuaW5uZXJIZWlnaHQgPyB3aW5kb3cuaW5uZXJIZWlnaHQgOiAkKHdpbmRvdykuaGVpZ2h0KCk7XG5cdH1cblxuXHRmdW5jdGlvbiBTZXR0aW5ncyhlbGVtZW50LCBvcHRpb25zKSB7XG5cdFx0aWYgKG9wdGlvbnMgIT09IE9iamVjdChvcHRpb25zKSkge1xuXHRcdFx0b3B0aW9ucyA9IHt9O1xuXHRcdH1cblxuXHRcdHRoaXMuY2FjaGUgPSB7fTtcblx0XHR0aGlzLmVsID0gZWxlbWVudDtcblxuXHRcdHRoaXMudmFsdWUgPSBmdW5jdGlvbihrZXkpIHtcblx0XHRcdHZhciBkYXRhQXR0cjtcblxuXHRcdFx0aWYgKHRoaXMuY2FjaGVba2V5XSA9PT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdGRhdGFBdHRyID0gJCh0aGlzLmVsKS5hdHRyKCdkYXRhLWNib3gtJytrZXkpO1xuXG5cdFx0XHRcdGlmIChkYXRhQXR0ciAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0dGhpcy5jYWNoZVtrZXldID0gZGF0YUF0dHI7XG5cdFx0XHRcdH0gZWxzZSBpZiAob3B0aW9uc1trZXldICE9PSB1bmRlZmluZWQpIHtcblx0XHRcdFx0XHR0aGlzLmNhY2hlW2tleV0gPSBvcHRpb25zW2tleV07XG5cdFx0XHRcdH0gZWxzZSBpZiAoZGVmYXVsdHNba2V5XSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0XHRcdFx0dGhpcy5jYWNoZVtrZXldID0gZGVmYXVsdHNba2V5XTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdGhpcy5jYWNoZVtrZXldO1xuXHRcdH07XG5cblx0XHR0aGlzLmdldCA9IGZ1bmN0aW9uKGtleSkge1xuXHRcdFx0dmFyIHZhbHVlID0gdGhpcy52YWx1ZShrZXkpO1xuXHRcdFx0cmV0dXJuICQuaXNGdW5jdGlvbih2YWx1ZSkgPyB2YWx1ZS5jYWxsKHRoaXMuZWwsIHRoaXMpIDogdmFsdWU7XG5cdFx0fTtcblx0fVxuXG5cdC8vIERldGVybWluZSB0aGUgbmV4dCBhbmQgcHJldmlvdXMgbWVtYmVycyBpbiBhIGdyb3VwLlxuXHRmdW5jdGlvbiBnZXRJbmRleChpbmNyZW1lbnQpIHtcblx0XHR2YXJcblx0XHRtYXggPSAkcmVsYXRlZC5sZW5ndGgsXG5cdFx0bmV3SW5kZXggPSAoaW5kZXggKyBpbmNyZW1lbnQpICUgbWF4O1xuXG5cdFx0cmV0dXJuIChuZXdJbmRleCA8IDApID8gbWF4ICsgbmV3SW5kZXggOiBuZXdJbmRleDtcblx0fVxuXG5cdC8vIENvbnZlcnQgJyUnIGFuZCAncHgnIHZhbHVlcyB0byBpbnRlZ2Vyc1xuXHRmdW5jdGlvbiBzZXRTaXplKHNpemUsIGRpbWVuc2lvbikge1xuXHRcdHJldHVybiBNYXRoLnJvdW5kKCgvJS8udGVzdChzaXplKSA/ICgoZGltZW5zaW9uID09PSAneCcgPyAkd2luZG93LndpZHRoKCkgOiB3aW5oZWlnaHQoKSkgLyAxMDApIDogMSkgKiBwYXJzZUludChzaXplLCAxMCkpO1xuXHR9XG5cblx0Ly8gQ2hlY2tzIGFuIGhyZWYgdG8gc2VlIGlmIGl0IGlzIGEgcGhvdG8uXG5cdC8vIFRoZXJlIGlzIGEgZm9yY2UgcGhvdG8gb3B0aW9uIChwaG90bzogdHJ1ZSkgZm9yIGhyZWZzIHRoYXQgY2Fubm90IGJlIG1hdGNoZWQgYnkgdGhlIHJlZ2V4LlxuXHRmdW5jdGlvbiBpc0ltYWdlKHNldHRpbmdzLCB1cmwpIHtcblx0XHRyZXR1cm4gc2V0dGluZ3MuZ2V0KCdwaG90bycpIHx8IHNldHRpbmdzLmdldCgncGhvdG9SZWdleCcpLnRlc3QodXJsKTtcblx0fVxuXG5cdGZ1bmN0aW9uIHJldGluYVVybChzZXR0aW5ncywgdXJsKSB7XG5cdFx0cmV0dXJuIHNldHRpbmdzLmdldCgncmV0aW5hVXJsJykgJiYgd2luZG93LmRldmljZVBpeGVsUmF0aW8gPiAxID8gdXJsLnJlcGxhY2Uoc2V0dGluZ3MuZ2V0KCdwaG90b1JlZ2V4JyksIHNldHRpbmdzLmdldCgncmV0aW5hU3VmZml4JykpIDogdXJsO1xuXHR9XG5cblx0ZnVuY3Rpb24gdHJhcEZvY3VzKGUpIHtcblx0XHRpZiAoJ2NvbnRhaW5zJyBpbiAkYm94WzBdICYmICEkYm94WzBdLmNvbnRhaW5zKGUudGFyZ2V0KSAmJiBlLnRhcmdldCAhPT0gJG92ZXJsYXlbMF0pIHtcblx0XHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cdFx0XHQkYm94LmZvY3VzKCk7XG5cdFx0fVxuXHR9XG5cblx0ZnVuY3Rpb24gc2V0Q2xhc3Moc3RyKSB7XG5cdFx0aWYgKHNldENsYXNzLnN0ciAhPT0gc3RyKSB7XG5cdFx0XHQkYm94LmFkZCgkb3ZlcmxheSkucmVtb3ZlQ2xhc3Moc2V0Q2xhc3Muc3RyKS5hZGRDbGFzcyhzdHIpO1xuXHRcdFx0c2V0Q2xhc3Muc3RyID0gc3RyO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIGdldFJlbGF0ZWQocmVsKSB7XG5cdFx0aW5kZXggPSAwO1xuXG5cdFx0aWYgKHJlbCAmJiByZWwgIT09IGZhbHNlICYmIHJlbCAhPT0gJ25vZm9sbG93Jykge1xuXHRcdFx0JHJlbGF0ZWQgPSAkKCcuJyArIGJveEVsZW1lbnQpLmZpbHRlcihmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHZhciBvcHRpb25zID0gJC5kYXRhKHRoaXMsIGNvbG9yYm94KTtcblx0XHRcdFx0dmFyIHNldHRpbmdzID0gbmV3IFNldHRpbmdzKHRoaXMsIG9wdGlvbnMpO1xuXHRcdFx0XHRyZXR1cm4gKHNldHRpbmdzLmdldCgncmVsJykgPT09IHJlbCk7XG5cdFx0XHR9KTtcblx0XHRcdGluZGV4ID0gJHJlbGF0ZWQuaW5kZXgoc2V0dGluZ3MuZWwpO1xuXG5cdFx0XHQvLyBDaGVjayBkaXJlY3QgY2FsbHMgdG8gQ29sb3Jib3guXG5cdFx0XHRpZiAoaW5kZXggPT09IC0xKSB7XG5cdFx0XHRcdCRyZWxhdGVkID0gJHJlbGF0ZWQuYWRkKHNldHRpbmdzLmVsKTtcblx0XHRcdFx0aW5kZXggPSAkcmVsYXRlZC5sZW5ndGggLSAxO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHQkcmVsYXRlZCA9ICQoc2V0dGluZ3MuZWwpO1xuXHRcdH1cblx0fVxuXG5cdGZ1bmN0aW9uIHRyaWdnZXIoZXZlbnQpIHtcblx0XHQvLyBmb3IgZXh0ZXJuYWwgdXNlXG5cdFx0JChkb2N1bWVudCkudHJpZ2dlcihldmVudCk7XG5cdFx0Ly8gZm9yIGludGVybmFsIHVzZVxuXHRcdCRldmVudHMudHJpZ2dlckhhbmRsZXIoZXZlbnQpO1xuXHR9XG5cblx0dmFyIHNsaWRlc2hvdyA9IChmdW5jdGlvbigpe1xuXHRcdHZhciBhY3RpdmUsXG5cdFx0XHRjbGFzc05hbWUgPSBwcmVmaXggKyBcIlNsaWRlc2hvd19cIixcblx0XHRcdGNsaWNrID0gXCJjbGljay5cIiArIHByZWZpeCxcblx0XHRcdHRpbWVPdXQ7XG5cblx0XHRmdW5jdGlvbiBjbGVhciAoKSB7XG5cdFx0XHRjbGVhclRpbWVvdXQodGltZU91dCk7XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gc2V0KCkge1xuXHRcdFx0aWYgKHNldHRpbmdzLmdldCgnbG9vcCcpIHx8ICRyZWxhdGVkW2luZGV4ICsgMV0pIHtcblx0XHRcdFx0Y2xlYXIoKTtcblx0XHRcdFx0dGltZU91dCA9IHNldFRpbWVvdXQocHVibGljTWV0aG9kLm5leHQsIHNldHRpbmdzLmdldCgnc2xpZGVzaG93U3BlZWQnKSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gc3RhcnQoKSB7XG5cdFx0XHQkc2xpZGVzaG93XG5cdFx0XHRcdC5odG1sKHNldHRpbmdzLmdldCgnc2xpZGVzaG93U3RvcCcpKVxuXHRcdFx0XHQudW5iaW5kKGNsaWNrKVxuXHRcdFx0XHQub25lKGNsaWNrLCBzdG9wKTtcblxuXHRcdFx0JGV2ZW50c1xuXHRcdFx0XHQuYmluZChldmVudF9jb21wbGV0ZSwgc2V0KVxuXHRcdFx0XHQuYmluZChldmVudF9sb2FkLCBjbGVhcik7XG5cblx0XHRcdCRib3gucmVtb3ZlQ2xhc3MoY2xhc3NOYW1lICsgXCJvZmZcIikuYWRkQ2xhc3MoY2xhc3NOYW1lICsgXCJvblwiKTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiBzdG9wKCkge1xuXHRcdFx0Y2xlYXIoKTtcblxuXHRcdFx0JGV2ZW50c1xuXHRcdFx0XHQudW5iaW5kKGV2ZW50X2NvbXBsZXRlLCBzZXQpXG5cdFx0XHRcdC51bmJpbmQoZXZlbnRfbG9hZCwgY2xlYXIpO1xuXG5cdFx0XHQkc2xpZGVzaG93XG5cdFx0XHRcdC5odG1sKHNldHRpbmdzLmdldCgnc2xpZGVzaG93U3RhcnQnKSlcblx0XHRcdFx0LnVuYmluZChjbGljaylcblx0XHRcdFx0Lm9uZShjbGljaywgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHB1YmxpY01ldGhvZC5uZXh0KCk7XG5cdFx0XHRcdFx0c3RhcnQoKTtcblx0XHRcdFx0fSk7XG5cblx0XHRcdCRib3gucmVtb3ZlQ2xhc3MoY2xhc3NOYW1lICsgXCJvblwiKS5hZGRDbGFzcyhjbGFzc05hbWUgKyBcIm9mZlwiKTtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiByZXNldCgpIHtcblx0XHRcdGFjdGl2ZSA9IGZhbHNlO1xuXHRcdFx0JHNsaWRlc2hvdy5oaWRlKCk7XG5cdFx0XHRjbGVhcigpO1xuXHRcdFx0JGV2ZW50c1xuXHRcdFx0XHQudW5iaW5kKGV2ZW50X2NvbXBsZXRlLCBzZXQpXG5cdFx0XHRcdC51bmJpbmQoZXZlbnRfbG9hZCwgY2xlYXIpO1xuXHRcdFx0JGJveC5yZW1vdmVDbGFzcyhjbGFzc05hbWUgKyBcIm9mZiBcIiArIGNsYXNzTmFtZSArIFwib25cIik7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIGZ1bmN0aW9uKCl7XG5cdFx0XHRpZiAoYWN0aXZlKSB7XG5cdFx0XHRcdGlmICghc2V0dGluZ3MuZ2V0KCdzbGlkZXNob3cnKSkge1xuXHRcdFx0XHRcdCRldmVudHMudW5iaW5kKGV2ZW50X2NsZWFudXAsIHJlc2V0KTtcblx0XHRcdFx0XHRyZXNldCgpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRpZiAoc2V0dGluZ3MuZ2V0KCdzbGlkZXNob3cnKSAmJiAkcmVsYXRlZFsxXSkge1xuXHRcdFx0XHRcdGFjdGl2ZSA9IHRydWU7XG5cdFx0XHRcdFx0JGV2ZW50cy5vbmUoZXZlbnRfY2xlYW51cCwgcmVzZXQpO1xuXHRcdFx0XHRcdGlmIChzZXR0aW5ncy5nZXQoJ3NsaWRlc2hvd0F1dG8nKSkge1xuXHRcdFx0XHRcdFx0c3RhcnQoKTtcblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0c3RvcCgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHQkc2xpZGVzaG93LnNob3coKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH07XG5cblx0fSgpKTtcblxuXG5cdGZ1bmN0aW9uIGxhdW5jaChlbGVtZW50KSB7XG5cdFx0dmFyIG9wdGlvbnM7XG5cblx0XHRpZiAoIWNsb3NpbmcpIHtcblxuXHRcdFx0b3B0aW9ucyA9ICQoZWxlbWVudCkuZGF0YShjb2xvcmJveCk7XG5cblx0XHRcdHNldHRpbmdzID0gbmV3IFNldHRpbmdzKGVsZW1lbnQsIG9wdGlvbnMpO1xuXG5cdFx0XHRnZXRSZWxhdGVkKHNldHRpbmdzLmdldCgncmVsJykpO1xuXG5cdFx0XHRpZiAoIW9wZW4pIHtcblx0XHRcdFx0b3BlbiA9IGFjdGl2ZSA9IHRydWU7IC8vIFByZXZlbnRzIHRoZSBwYWdlLWNoYW5nZSBhY3Rpb24gZnJvbSBxdWV1aW5nIHVwIGlmIHRoZSB2aXNpdG9yIGhvbGRzIGRvd24gdGhlIGxlZnQgb3IgcmlnaHQga2V5cy5cblxuXHRcdFx0XHRzZXRDbGFzcyhzZXR0aW5ncy5nZXQoJ2NsYXNzTmFtZScpKTtcblxuXHRcdFx0XHQvLyBTaG93IGNvbG9yYm94IHNvIHRoZSBzaXplcyBjYW4gYmUgY2FsY3VsYXRlZCBpbiBvbGRlciB2ZXJzaW9ucyBvZiBqUXVlcnlcblx0XHRcdFx0JGJveC5jc3Moe3Zpc2liaWxpdHk6J2hpZGRlbicsIGRpc3BsYXk6J2Jsb2NrJywgb3BhY2l0eTonJ30pO1xuXG5cdFx0XHRcdCRsb2FkZWQgPSAkdGFnKGRpdiwgJ0xvYWRlZENvbnRlbnQnLCAnd2lkdGg6MDsgaGVpZ2h0OjA7IG92ZXJmbG93OmhpZGRlbjsgdmlzaWJpbGl0eTpoaWRkZW4nKTtcblx0XHRcdFx0JGNvbnRlbnQuY3NzKHt3aWR0aDonJywgaGVpZ2h0OicnfSkuYXBwZW5kKCRsb2FkZWQpO1xuXG5cdFx0XHRcdC8vIENhY2hlIHZhbHVlcyBuZWVkZWQgZm9yIHNpemUgY2FsY3VsYXRpb25zXG5cdFx0XHRcdGludGVyZmFjZUhlaWdodCA9ICR0b3BCb3JkZXIuaGVpZ2h0KCkgKyAkYm90dG9tQm9yZGVyLmhlaWdodCgpICsgJGNvbnRlbnQub3V0ZXJIZWlnaHQodHJ1ZSkgLSAkY29udGVudC5oZWlnaHQoKTtcblx0XHRcdFx0aW50ZXJmYWNlV2lkdGggPSAkbGVmdEJvcmRlci53aWR0aCgpICsgJHJpZ2h0Qm9yZGVyLndpZHRoKCkgKyAkY29udGVudC5vdXRlcldpZHRoKHRydWUpIC0gJGNvbnRlbnQud2lkdGgoKTtcblx0XHRcdFx0bG9hZGVkSGVpZ2h0ID0gJGxvYWRlZC5vdXRlckhlaWdodCh0cnVlKTtcblx0XHRcdFx0bG9hZGVkV2lkdGggPSAkbG9hZGVkLm91dGVyV2lkdGgodHJ1ZSk7XG5cblx0XHRcdFx0Ly8gT3BlbnMgaW5pdGFsIGVtcHR5IENvbG9yYm94IHByaW9yIHRvIGNvbnRlbnQgYmVpbmcgbG9hZGVkLlxuXHRcdFx0XHR2YXIgaW5pdGlhbFdpZHRoID0gc2V0U2l6ZShzZXR0aW5ncy5nZXQoJ2luaXRpYWxXaWR0aCcpLCAneCcpO1xuXHRcdFx0XHR2YXIgaW5pdGlhbEhlaWdodCA9IHNldFNpemUoc2V0dGluZ3MuZ2V0KCdpbml0aWFsSGVpZ2h0JyksICd5Jyk7XG5cdFx0XHRcdHZhciBtYXhXaWR0aCA9IHNldHRpbmdzLmdldCgnbWF4V2lkdGgnKTtcblx0XHRcdFx0dmFyIG1heEhlaWdodCA9IHNldHRpbmdzLmdldCgnbWF4SGVpZ2h0Jyk7XG5cblx0XHRcdFx0c2V0dGluZ3MudyA9IE1hdGgubWF4KChtYXhXaWR0aCAhPT0gZmFsc2UgPyBNYXRoLm1pbihpbml0aWFsV2lkdGgsIHNldFNpemUobWF4V2lkdGgsICd4JykpIDogaW5pdGlhbFdpZHRoKSAtIGxvYWRlZFdpZHRoIC0gaW50ZXJmYWNlV2lkdGgsIDApO1xuXHRcdFx0XHRzZXR0aW5ncy5oID0gTWF0aC5tYXgoKG1heEhlaWdodCAhPT0gZmFsc2UgPyBNYXRoLm1pbihpbml0aWFsSGVpZ2h0LCBzZXRTaXplKG1heEhlaWdodCwgJ3knKSkgOiBpbml0aWFsSGVpZ2h0KSAtIGxvYWRlZEhlaWdodCAtIGludGVyZmFjZUhlaWdodCwgMCk7XG5cblx0XHRcdFx0JGxvYWRlZC5jc3Moe3dpZHRoOicnLCBoZWlnaHQ6c2V0dGluZ3MuaH0pO1xuXHRcdFx0XHRwdWJsaWNNZXRob2QucG9zaXRpb24oKTtcblxuXHRcdFx0XHR0cmlnZ2VyKGV2ZW50X29wZW4pO1xuXHRcdFx0XHRzZXR0aW5ncy5nZXQoJ29uT3BlbicpO1xuXG5cdFx0XHRcdCRncm91cENvbnRyb2xzLmFkZCgkdGl0bGUpLmhpZGUoKTtcblxuXHRcdFx0XHQkYm94LmZvY3VzKCk7XG5cblx0XHRcdFx0aWYgKHNldHRpbmdzLmdldCgndHJhcEZvY3VzJykpIHtcblx0XHRcdFx0XHQvLyBDb25maW5lIGZvY3VzIHRvIHRoZSBtb2RhbFxuXHRcdFx0XHRcdC8vIFVzZXMgZXZlbnQgY2FwdHVyaW5nIHRoYXQgaXMgbm90IHN1cHBvcnRlZCBpbiBJRTgtXG5cdFx0XHRcdFx0aWYgKGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIpIHtcblxuXHRcdFx0XHRcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0cmFwRm9jdXMsIHRydWUpO1xuXG5cdFx0XHRcdFx0XHQkZXZlbnRzLm9uZShldmVudF9jbG9zZWQsIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0ZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0cmFwRm9jdXMsIHRydWUpO1xuXHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gUmV0dXJuIGZvY3VzIG9uIGNsb3Npbmdcblx0XHRcdFx0aWYgKHNldHRpbmdzLmdldCgncmV0dXJuRm9jdXMnKSkge1xuXHRcdFx0XHRcdCRldmVudHMub25lKGV2ZW50X2Nsb3NlZCwgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0JChzZXR0aW5ncy5lbCkuZm9jdXMoKTtcblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHR2YXIgb3BhY2l0eSA9IHBhcnNlRmxvYXQoc2V0dGluZ3MuZ2V0KCdvcGFjaXR5JykpO1xuXHRcdFx0JG92ZXJsYXkuY3NzKHtcblx0XHRcdFx0b3BhY2l0eTogb3BhY2l0eSA9PT0gb3BhY2l0eSA/IG9wYWNpdHkgOiAnJyxcblx0XHRcdFx0Y3Vyc29yOiBzZXR0aW5ncy5nZXQoJ292ZXJsYXlDbG9zZScpID8gJ3BvaW50ZXInIDogJycsXG5cdFx0XHRcdHZpc2liaWxpdHk6ICd2aXNpYmxlJ1xuXHRcdFx0fSkuc2hvdygpO1xuXG5cdFx0XHRpZiAoc2V0dGluZ3MuZ2V0KCdjbG9zZUJ1dHRvbicpKSB7XG5cdFx0XHRcdCRjbG9zZS5odG1sKHNldHRpbmdzLmdldCgnY2xvc2UnKSkuYXBwZW5kVG8oJGNvbnRlbnQpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0JGNsb3NlLmFwcGVuZFRvKCc8ZGl2Lz4nKTsgLy8gcmVwbGFjZSB3aXRoIC5kZXRhY2goKSB3aGVuIGRyb3BwaW5nIGpRdWVyeSA8IDEuNFxuXHRcdFx0fVxuXG5cdFx0XHRsb2FkKCk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gQ29sb3Jib3gncyBtYXJrdXAgbmVlZHMgdG8gYmUgYWRkZWQgdG8gdGhlIERPTSBwcmlvciB0byBiZWluZyBjYWxsZWRcblx0Ly8gc28gdGhhdCB0aGUgYnJvd3NlciB3aWxsIGdvIGFoZWFkIGFuZCBsb2FkIHRoZSBDU1MgYmFja2dyb3VuZCBpbWFnZXMuXG5cdGZ1bmN0aW9uIGFwcGVuZEhUTUwoKSB7XG5cdFx0aWYgKCEkYm94KSB7XG5cdFx0XHRpbml0ID0gZmFsc2U7XG5cdFx0XHQkd2luZG93ID0gJCh3aW5kb3cpO1xuXHRcdFx0JGJveCA9ICR0YWcoZGl2KS5hdHRyKHtcblx0XHRcdFx0aWQ6IGNvbG9yYm94LFxuXHRcdFx0XHQnY2xhc3MnOiAkLnN1cHBvcnQub3BhY2l0eSA9PT0gZmFsc2UgPyBwcmVmaXggKyAnSUUnIDogJycsIC8vIGNsYXNzIGZvciBvcHRpb25hbCBJRTggJiBsb3dlciB0YXJnZXRlZCBDU1MuXG5cdFx0XHRcdHJvbGU6ICdkaWFsb2cnLFxuXHRcdFx0XHR0YWJpbmRleDogJy0xJ1xuXHRcdFx0fSkuaGlkZSgpO1xuXHRcdFx0JG92ZXJsYXkgPSAkdGFnKGRpdiwgXCJPdmVybGF5XCIpLmhpZGUoKTtcblx0XHRcdCRsb2FkaW5nT3ZlcmxheSA9ICQoWyR0YWcoZGl2LCBcIkxvYWRpbmdPdmVybGF5XCIpWzBdLCR0YWcoZGl2LCBcIkxvYWRpbmdHcmFwaGljXCIpWzBdXSk7XG5cdFx0XHQkd3JhcCA9ICR0YWcoZGl2LCBcIldyYXBwZXJcIik7XG5cdFx0XHQkY29udGVudCA9ICR0YWcoZGl2LCBcIkNvbnRlbnRcIikuYXBwZW5kKFxuXHRcdFx0XHQkdGl0bGUgPSAkdGFnKGRpdiwgXCJUaXRsZVwiKSxcblx0XHRcdFx0JGN1cnJlbnQgPSAkdGFnKGRpdiwgXCJDdXJyZW50XCIpLFxuXHRcdFx0XHQkcHJldiA9ICQoJzxidXR0b24gdHlwZT1cImJ1dHRvblwiLz4nKS5hdHRyKHtpZDpwcmVmaXgrJ1ByZXZpb3VzJ30pLFxuXHRcdFx0XHQkbmV4dCA9ICQoJzxidXR0b24gdHlwZT1cImJ1dHRvblwiLz4nKS5hdHRyKHtpZDpwcmVmaXgrJ05leHQnfSksXG5cdFx0XHRcdCRzbGlkZXNob3cgPSAkKCc8YnV0dG9uIHR5cGU9XCJidXR0b25cIi8+JykuYXR0cih7aWQ6cHJlZml4KydTbGlkZXNob3cnfSksXG5cdFx0XHRcdCRsb2FkaW5nT3ZlcmxheVxuXHRcdFx0KTtcblxuXHRcdFx0JGNsb3NlID0gJCgnPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIvPicpLmF0dHIoe2lkOnByZWZpeCsnQ2xvc2UnfSk7XG5cblx0XHRcdCR3cmFwLmFwcGVuZCggLy8gVGhlIDN4MyBHcmlkIHRoYXQgbWFrZXMgdXAgQ29sb3Jib3hcblx0XHRcdFx0JHRhZyhkaXYpLmFwcGVuZChcblx0XHRcdFx0XHQkdGFnKGRpdiwgXCJUb3BMZWZ0XCIpLFxuXHRcdFx0XHRcdCR0b3BCb3JkZXIgPSAkdGFnKGRpdiwgXCJUb3BDZW50ZXJcIiksXG5cdFx0XHRcdFx0JHRhZyhkaXYsIFwiVG9wUmlnaHRcIilcblx0XHRcdFx0KSxcblx0XHRcdFx0JHRhZyhkaXYsIGZhbHNlLCAnY2xlYXI6bGVmdCcpLmFwcGVuZChcblx0XHRcdFx0XHQkbGVmdEJvcmRlciA9ICR0YWcoZGl2LCBcIk1pZGRsZUxlZnRcIiksXG5cdFx0XHRcdFx0JGNvbnRlbnQsXG5cdFx0XHRcdFx0JHJpZ2h0Qm9yZGVyID0gJHRhZyhkaXYsIFwiTWlkZGxlUmlnaHRcIilcblx0XHRcdFx0KSxcblx0XHRcdFx0JHRhZyhkaXYsIGZhbHNlLCAnY2xlYXI6bGVmdCcpLmFwcGVuZChcblx0XHRcdFx0XHQkdGFnKGRpdiwgXCJCb3R0b21MZWZ0XCIpLFxuXHRcdFx0XHRcdCRib3R0b21Cb3JkZXIgPSAkdGFnKGRpdiwgXCJCb3R0b21DZW50ZXJcIiksXG5cdFx0XHRcdFx0JHRhZyhkaXYsIFwiQm90dG9tUmlnaHRcIilcblx0XHRcdFx0KVxuXHRcdFx0KS5maW5kKCdkaXYgZGl2JykuY3NzKHsnZmxvYXQnOiAnbGVmdCd9KTtcblxuXHRcdFx0JGxvYWRpbmdCYXkgPSAkdGFnKGRpdiwgZmFsc2UsICdwb3NpdGlvbjphYnNvbHV0ZTsgd2lkdGg6OTk5OXB4OyB2aXNpYmlsaXR5OmhpZGRlbjsgZGlzcGxheTpub25lOyBtYXgtd2lkdGg6bm9uZTsnKTtcblxuXHRcdFx0JGdyb3VwQ29udHJvbHMgPSAkbmV4dC5hZGQoJHByZXYpLmFkZCgkY3VycmVudCkuYWRkKCRzbGlkZXNob3cpO1xuXHRcdH1cblx0XHRpZiAoZG9jdW1lbnQuYm9keSAmJiAhJGJveC5wYXJlbnQoKS5sZW5ndGgpIHtcblx0XHRcdCQoZG9jdW1lbnQuYm9keSkuYXBwZW5kKCRvdmVybGF5LCAkYm94LmFwcGVuZCgkd3JhcCwgJGxvYWRpbmdCYXkpKTtcblx0XHR9XG5cdH1cblxuXHQvLyBBZGQgQ29sb3Jib3gncyBldmVudCBiaW5kaW5nc1xuXHRmdW5jdGlvbiBhZGRCaW5kaW5ncygpIHtcblx0XHRmdW5jdGlvbiBjbGlja0hhbmRsZXIoZSkge1xuXHRcdFx0Ly8gaWdub3JlIG5vbi1sZWZ0LW1vdXNlLWNsaWNrcyBhbmQgY2xpY2tzIG1vZGlmaWVkIHdpdGggY3RybCAvIGNvbW1hbmQsIHNoaWZ0LCBvciBhbHQuXG5cdFx0XHQvLyBTZWU6IGh0dHA6Ly9qYWNrbG1vb3JlLmNvbS9ub3Rlcy9jbGljay1ldmVudHMvXG5cdFx0XHRpZiAoIShlLndoaWNoID4gMSB8fCBlLnNoaWZ0S2V5IHx8IGUuYWx0S2V5IHx8IGUubWV0YUtleSB8fCBlLmN0cmxLZXkpKSB7XG5cdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0bGF1bmNoKHRoaXMpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICgkYm94KSB7XG5cdFx0XHRpZiAoIWluaXQpIHtcblx0XHRcdFx0aW5pdCA9IHRydWU7XG5cblx0XHRcdFx0Ly8gQW5vbnltb3VzIGZ1bmN0aW9ucyBoZXJlIGtlZXAgdGhlIHB1YmxpYyBtZXRob2QgZnJvbSBiZWluZyBjYWNoZWQsIHRoZXJlYnkgYWxsb3dpbmcgdGhlbSB0byBiZSByZWRlZmluZWQgb24gdGhlIGZseS5cblx0XHRcdFx0JG5leHQuY2xpY2soZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHB1YmxpY01ldGhvZC5uZXh0KCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHQkcHJldi5jbGljayhmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0cHVibGljTWV0aG9kLnByZXYoKTtcblx0XHRcdFx0fSk7XG5cdFx0XHRcdCRjbG9zZS5jbGljayhmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0cHVibGljTWV0aG9kLmNsb3NlKCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0XHQkb3ZlcmxheS5jbGljayhmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0aWYgKHNldHRpbmdzLmdldCgnb3ZlcmxheUNsb3NlJykpIHtcblx0XHRcdFx0XHRcdHB1YmxpY01ldGhvZC5jbG9zZSgpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gS2V5IEJpbmRpbmdzXG5cdFx0XHRcdCQoZG9jdW1lbnQpLmJpbmQoJ2tleWRvd24uJyArIHByZWZpeCwgZnVuY3Rpb24gKGUpIHtcblx0XHRcdFx0XHR2YXIga2V5ID0gZS5rZXlDb2RlO1xuXHRcdFx0XHRcdGlmIChvcGVuICYmIHNldHRpbmdzLmdldCgnZXNjS2V5JykgJiYga2V5ID09PSAyNykge1xuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdFx0cHVibGljTWV0aG9kLmNsb3NlKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGlmIChvcGVuICYmIHNldHRpbmdzLmdldCgnYXJyb3dLZXknKSAmJiAkcmVsYXRlZFsxXSAmJiAhZS5hbHRLZXkpIHtcblx0XHRcdFx0XHRcdGlmIChrZXkgPT09IDM3KSB7XG5cdFx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdFx0JHByZXYuY2xpY2soKTtcblx0XHRcdFx0XHRcdH0gZWxzZSBpZiAoa2V5ID09PSAzOSkge1xuXHRcdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0XHRcdCRuZXh0LmNsaWNrKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRpZiAoJC5pc0Z1bmN0aW9uKCQuZm4ub24pKSB7XG5cdFx0XHRcdFx0Ly8gRm9yIGpRdWVyeSAxLjcrXG5cdFx0XHRcdFx0JChkb2N1bWVudCkub24oJ2NsaWNrLicrcHJlZml4LCAnLicrYm94RWxlbWVudCwgY2xpY2tIYW5kbGVyKTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHQvLyBGb3IgalF1ZXJ5IDEuMy54IC0+IDEuNi54XG5cdFx0XHRcdFx0Ly8gVGhpcyBjb2RlIGlzIG5ldmVyIHJlYWNoZWQgaW4galF1ZXJ5IDEuOSwgc28gZG8gbm90IGNvbnRhY3QgbWUgYWJvdXQgJ2xpdmUnIGJlaW5nIHJlbW92ZWQuXG5cdFx0XHRcdFx0Ly8gVGhpcyBpcyBub3QgaGVyZSBmb3IgalF1ZXJ5IDEuOSwgaXQncyBoZXJlIGZvciBsZWdhY3kgdXNlcnMuXG5cdFx0XHRcdFx0JCgnLicrYm94RWxlbWVudCkubGl2ZSgnY2xpY2suJytwcmVmaXgsIGNsaWNrSGFuZGxlcik7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiB0cnVlO1xuXHRcdH1cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH1cblxuXHQvLyBEb24ndCBkbyBhbnl0aGluZyBpZiBDb2xvcmJveCBhbHJlYWR5IGV4aXN0cy5cblx0aWYgKCRbY29sb3Jib3hdKSB7XG5cdFx0cmV0dXJuO1xuXHR9XG5cblx0Ly8gQXBwZW5kIHRoZSBIVE1MIHdoZW4gdGhlIERPTSBsb2Fkc1xuXHQkKGFwcGVuZEhUTUwpO1xuXG5cblx0Ly8gKioqKioqKioqKioqKioqKlxuXHQvLyBQVUJMSUMgRlVOQ1RJT05TXG5cdC8vIFVzYWdlIGZvcm1hdDogJC5jb2xvcmJveC5jbG9zZSgpO1xuXHQvLyBVc2FnZSBmcm9tIHdpdGhpbiBhbiBpZnJhbWU6IHBhcmVudC5qUXVlcnkuY29sb3Jib3guY2xvc2UoKTtcblx0Ly8gKioqKioqKioqKioqKioqKlxuXG5cdHB1YmxpY01ldGhvZCA9ICQuZm5bY29sb3Jib3hdID0gJFtjb2xvcmJveF0gPSBmdW5jdGlvbiAob3B0aW9ucywgY2FsbGJhY2spIHtcblx0XHR2YXIgc2V0dGluZ3M7XG5cdFx0dmFyICRvYmogPSB0aGlzO1xuXG5cdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblx0XHRpZiAoJC5pc0Z1bmN0aW9uKCRvYmopKSB7IC8vIGFzc3VtZSBhIGNhbGwgdG8gJC5jb2xvcmJveFxuXHRcdFx0JG9iaiA9ICQoJzxhLz4nKTtcblx0XHRcdG9wdGlvbnMub3BlbiA9IHRydWU7XG5cdFx0fVxuXG5cdFx0aWYgKCEkb2JqWzBdKSB7IC8vIGNvbG9yYm94IGJlaW5nIGFwcGxpZWQgdG8gZW1wdHkgY29sbGVjdGlvblxuXHRcdFx0cmV0dXJuICRvYmo7XG5cdFx0fVxuXG5cdFx0YXBwZW5kSFRNTCgpO1xuXG5cdFx0aWYgKGFkZEJpbmRpbmdzKCkpIHtcblxuXHRcdFx0aWYgKGNhbGxiYWNrKSB7XG5cdFx0XHRcdG9wdGlvbnMub25Db21wbGV0ZSA9IGNhbGxiYWNrO1xuXHRcdFx0fVxuXG5cdFx0XHQkb2JqLmVhY2goZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR2YXIgb2xkID0gJC5kYXRhKHRoaXMsIGNvbG9yYm94KSB8fCB7fTtcblx0XHRcdFx0JC5kYXRhKHRoaXMsIGNvbG9yYm94LCAkLmV4dGVuZChvbGQsIG9wdGlvbnMpKTtcblx0XHRcdH0pLmFkZENsYXNzKGJveEVsZW1lbnQpO1xuXG5cdFx0XHRzZXR0aW5ncyA9IG5ldyBTZXR0aW5ncygkb2JqWzBdLCBvcHRpb25zKTtcblxuXHRcdFx0aWYgKHNldHRpbmdzLmdldCgnb3BlbicpKSB7XG5cdFx0XHRcdGxhdW5jaCgkb2JqWzBdKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gJG9iajtcblx0fTtcblxuXHRwdWJsaWNNZXRob2QucG9zaXRpb24gPSBmdW5jdGlvbiAoc3BlZWQsIGxvYWRlZENhbGxiYWNrKSB7XG5cdFx0dmFyXG5cdFx0Y3NzLFxuXHRcdHRvcCA9IDAsXG5cdFx0bGVmdCA9IDAsXG5cdFx0b2Zmc2V0ID0gJGJveC5vZmZzZXQoKSxcblx0XHRzY3JvbGxUb3AsXG5cdFx0c2Nyb2xsTGVmdDtcblxuXHRcdCR3aW5kb3cudW5iaW5kKCdyZXNpemUuJyArIHByZWZpeCk7XG5cblx0XHQvLyByZW1vdmUgdGhlIG1vZGFsIHNvIHRoYXQgaXQgZG9lc24ndCBpbmZsdWVuY2UgdGhlIGRvY3VtZW50IHdpZHRoL2hlaWdodFxuXHRcdCRib3guY3NzKHt0b3A6IC05ZTQsIGxlZnQ6IC05ZTR9KTtcblxuXHRcdHNjcm9sbFRvcCA9ICR3aW5kb3cuc2Nyb2xsVG9wKCk7XG5cdFx0c2Nyb2xsTGVmdCA9ICR3aW5kb3cuc2Nyb2xsTGVmdCgpO1xuXG5cdFx0aWYgKHNldHRpbmdzLmdldCgnZml4ZWQnKSkge1xuXHRcdFx0b2Zmc2V0LnRvcCAtPSBzY3JvbGxUb3A7XG5cdFx0XHRvZmZzZXQubGVmdCAtPSBzY3JvbGxMZWZ0O1xuXHRcdFx0JGJveC5jc3Moe3Bvc2l0aW9uOiAnZml4ZWQnfSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRvcCA9IHNjcm9sbFRvcDtcblx0XHRcdGxlZnQgPSBzY3JvbGxMZWZ0O1xuXHRcdFx0JGJveC5jc3Moe3Bvc2l0aW9uOiAnYWJzb2x1dGUnfSk7XG5cdFx0fVxuXG5cdFx0Ly8ga2VlcHMgdGhlIHRvcCBhbmQgbGVmdCBwb3NpdGlvbnMgd2l0aGluIHRoZSBicm93c2VyJ3Mgdmlld3BvcnQuXG5cdFx0aWYgKHNldHRpbmdzLmdldCgncmlnaHQnKSAhPT0gZmFsc2UpIHtcblx0XHRcdGxlZnQgKz0gTWF0aC5tYXgoJHdpbmRvdy53aWR0aCgpIC0gc2V0dGluZ3MudyAtIGxvYWRlZFdpZHRoIC0gaW50ZXJmYWNlV2lkdGggLSBzZXRTaXplKHNldHRpbmdzLmdldCgncmlnaHQnKSwgJ3gnKSwgMCk7XG5cdFx0fSBlbHNlIGlmIChzZXR0aW5ncy5nZXQoJ2xlZnQnKSAhPT0gZmFsc2UpIHtcblx0XHRcdGxlZnQgKz0gc2V0U2l6ZShzZXR0aW5ncy5nZXQoJ2xlZnQnKSwgJ3gnKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0bGVmdCArPSBNYXRoLnJvdW5kKE1hdGgubWF4KCR3aW5kb3cud2lkdGgoKSAtIHNldHRpbmdzLncgLSBsb2FkZWRXaWR0aCAtIGludGVyZmFjZVdpZHRoLCAwKSAvIDIpO1xuXHRcdH1cblxuXHRcdGlmIChzZXR0aW5ncy5nZXQoJ2JvdHRvbScpICE9PSBmYWxzZSkge1xuXHRcdFx0dG9wICs9IE1hdGgubWF4KHdpbmhlaWdodCgpIC0gc2V0dGluZ3MuaCAtIGxvYWRlZEhlaWdodCAtIGludGVyZmFjZUhlaWdodCAtIHNldFNpemUoc2V0dGluZ3MuZ2V0KCdib3R0b20nKSwgJ3knKSwgMCk7XG5cdFx0fSBlbHNlIGlmIChzZXR0aW5ncy5nZXQoJ3RvcCcpICE9PSBmYWxzZSkge1xuXHRcdFx0dG9wICs9IHNldFNpemUoc2V0dGluZ3MuZ2V0KCd0b3AnKSwgJ3knKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dG9wICs9IE1hdGgucm91bmQoTWF0aC5tYXgod2luaGVpZ2h0KCkgLSBzZXR0aW5ncy5oIC0gbG9hZGVkSGVpZ2h0IC0gaW50ZXJmYWNlSGVpZ2h0LCAwKSAvIDIpO1xuXHRcdH1cblxuXHRcdCRib3guY3NzKHt0b3A6IG9mZnNldC50b3AsIGxlZnQ6IG9mZnNldC5sZWZ0LCB2aXNpYmlsaXR5Oid2aXNpYmxlJ30pO1xuXG5cdFx0Ly8gdGhpcyBnaXZlcyB0aGUgd3JhcHBlciBwbGVudHkgb2YgYnJlYXRoaW5nIHJvb20gc28gaXQncyBmbG9hdGVkIGNvbnRlbnRzIGNhbiBtb3ZlIGFyb3VuZCBzbW9vdGhseSxcblx0XHQvLyBidXQgaXQgaGFzIHRvIGJlIHNocmFuayBkb3duIGFyb3VuZCB0aGUgc2l6ZSBvZiBkaXYjY29sb3Jib3ggd2hlbiBpdCdzIGRvbmUuICBJZiBub3QsXG5cdFx0Ly8gaXQgY2FuIGludm9rZSBhbiBvYnNjdXJlIElFIGJ1ZyB3aGVuIHVzaW5nIGlmcmFtZXMuXG5cdFx0JHdyYXBbMF0uc3R5bGUud2lkdGggPSAkd3JhcFswXS5zdHlsZS5oZWlnaHQgPSBcIjk5OTlweFwiO1xuXG5cdFx0ZnVuY3Rpb24gbW9kYWxEaW1lbnNpb25zKCkge1xuXHRcdFx0JHRvcEJvcmRlclswXS5zdHlsZS53aWR0aCA9ICRib3R0b21Cb3JkZXJbMF0uc3R5bGUud2lkdGggPSAkY29udGVudFswXS5zdHlsZS53aWR0aCA9IChwYXJzZUludCgkYm94WzBdLnN0eWxlLndpZHRoLDEwKSAtIGludGVyZmFjZVdpZHRoKSsncHgnO1xuXHRcdFx0JGNvbnRlbnRbMF0uc3R5bGUuaGVpZ2h0ID0gJGxlZnRCb3JkZXJbMF0uc3R5bGUuaGVpZ2h0ID0gJHJpZ2h0Qm9yZGVyWzBdLnN0eWxlLmhlaWdodCA9IChwYXJzZUludCgkYm94WzBdLnN0eWxlLmhlaWdodCwxMCkgLSBpbnRlcmZhY2VIZWlnaHQpKydweCc7XG5cdFx0fVxuXG5cdFx0Y3NzID0ge3dpZHRoOiBzZXR0aW5ncy53ICsgbG9hZGVkV2lkdGggKyBpbnRlcmZhY2VXaWR0aCwgaGVpZ2h0OiBzZXR0aW5ncy5oICsgbG9hZGVkSGVpZ2h0ICsgaW50ZXJmYWNlSGVpZ2h0LCB0b3A6IHRvcCwgbGVmdDogbGVmdH07XG5cblx0XHQvLyBzZXR0aW5nIHRoZSBzcGVlZCB0byAwIGlmIHRoZSBjb250ZW50IGhhc24ndCBjaGFuZ2VkIHNpemUgb3IgcG9zaXRpb25cblx0XHRpZiAoc3BlZWQpIHtcblx0XHRcdHZhciB0ZW1wU3BlZWQgPSAwO1xuXHRcdFx0JC5lYWNoKGNzcywgZnVuY3Rpb24oaSl7XG5cdFx0XHRcdGlmIChjc3NbaV0gIT09IHByZXZpb3VzQ1NTW2ldKSB7XG5cdFx0XHRcdFx0dGVtcFNwZWVkID0gc3BlZWQ7XG5cdFx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdHNwZWVkID0gdGVtcFNwZWVkO1xuXHRcdH1cblxuXHRcdHByZXZpb3VzQ1NTID0gY3NzO1xuXG5cdFx0aWYgKCFzcGVlZCkge1xuXHRcdFx0JGJveC5jc3MoY3NzKTtcblx0XHR9XG5cblx0XHQkYm94LmRlcXVldWUoKS5hbmltYXRlKGNzcywge1xuXHRcdFx0ZHVyYXRpb246IHNwZWVkIHx8IDAsXG5cdFx0XHRjb21wbGV0ZTogZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRtb2RhbERpbWVuc2lvbnMoKTtcblxuXHRcdFx0XHRhY3RpdmUgPSBmYWxzZTtcblxuXHRcdFx0XHQvLyBzaHJpbmsgdGhlIHdyYXBwZXIgZG93biB0byBleGFjdGx5IHRoZSBzaXplIG9mIGNvbG9yYm94IHRvIGF2b2lkIGEgYnVnIGluIElFJ3MgaWZyYW1lIGltcGxlbWVudGF0aW9uLlxuXHRcdFx0XHQkd3JhcFswXS5zdHlsZS53aWR0aCA9IChzZXR0aW5ncy53ICsgbG9hZGVkV2lkdGggKyBpbnRlcmZhY2VXaWR0aCkgKyBcInB4XCI7XG5cdFx0XHRcdCR3cmFwWzBdLnN0eWxlLmhlaWdodCA9IChzZXR0aW5ncy5oICsgbG9hZGVkSGVpZ2h0ICsgaW50ZXJmYWNlSGVpZ2h0KSArIFwicHhcIjtcblxuXHRcdFx0XHRpZiAoc2V0dGluZ3MuZ2V0KCdyZXBvc2l0aW9uJykpIHtcblx0XHRcdFx0XHRzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHsgIC8vIHNtYWxsIGRlbGF5IGJlZm9yZSBiaW5kaW5nIG9ucmVzaXplIGR1ZSB0byBhbiBJRTggYnVnLlxuXHRcdFx0XHRcdFx0JHdpbmRvdy5iaW5kKCdyZXNpemUuJyArIHByZWZpeCwgcHVibGljTWV0aG9kLnBvc2l0aW9uKTtcblx0XHRcdFx0XHR9LCAxKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmICgkLmlzRnVuY3Rpb24obG9hZGVkQ2FsbGJhY2spKSB7XG5cdFx0XHRcdFx0bG9hZGVkQ2FsbGJhY2soKTtcblx0XHRcdFx0fVxuXHRcdFx0fSxcblx0XHRcdHN0ZXA6IG1vZGFsRGltZW5zaW9uc1xuXHRcdH0pO1xuXHR9O1xuXG5cdHB1YmxpY01ldGhvZC5yZXNpemUgPSBmdW5jdGlvbiAob3B0aW9ucykge1xuXHRcdHZhciBzY3JvbGx0b3A7XG5cblx0XHRpZiAob3Blbikge1xuXHRcdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblx0XHRcdGlmIChvcHRpb25zLndpZHRoKSB7XG5cdFx0XHRcdHNldHRpbmdzLncgPSBzZXRTaXplKG9wdGlvbnMud2lkdGgsICd4JykgLSBsb2FkZWRXaWR0aCAtIGludGVyZmFjZVdpZHRoO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAob3B0aW9ucy5pbm5lcldpZHRoKSB7XG5cdFx0XHRcdHNldHRpbmdzLncgPSBzZXRTaXplKG9wdGlvbnMuaW5uZXJXaWR0aCwgJ3gnKTtcblx0XHRcdH1cblxuXHRcdFx0JGxvYWRlZC5jc3Moe3dpZHRoOiBzZXR0aW5ncy53fSk7XG5cblx0XHRcdGlmIChvcHRpb25zLmhlaWdodCkge1xuXHRcdFx0XHRzZXR0aW5ncy5oID0gc2V0U2l6ZShvcHRpb25zLmhlaWdodCwgJ3knKSAtIGxvYWRlZEhlaWdodCAtIGludGVyZmFjZUhlaWdodDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKG9wdGlvbnMuaW5uZXJIZWlnaHQpIHtcblx0XHRcdFx0c2V0dGluZ3MuaCA9IHNldFNpemUob3B0aW9ucy5pbm5lckhlaWdodCwgJ3knKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCFvcHRpb25zLmlubmVySGVpZ2h0ICYmICFvcHRpb25zLmhlaWdodCkge1xuXHRcdFx0XHRzY3JvbGx0b3AgPSAkbG9hZGVkLnNjcm9sbFRvcCgpO1xuXHRcdFx0XHQkbG9hZGVkLmNzcyh7aGVpZ2h0OiBcImF1dG9cIn0pO1xuXHRcdFx0XHRzZXR0aW5ncy5oID0gJGxvYWRlZC5oZWlnaHQoKTtcblx0XHRcdH1cblxuXHRcdFx0JGxvYWRlZC5jc3Moe2hlaWdodDogc2V0dGluZ3MuaH0pO1xuXG5cdFx0XHRpZihzY3JvbGx0b3ApIHtcblx0XHRcdFx0JGxvYWRlZC5zY3JvbGxUb3Aoc2Nyb2xsdG9wKTtcblx0XHRcdH1cblxuXHRcdFx0cHVibGljTWV0aG9kLnBvc2l0aW9uKHNldHRpbmdzLmdldCgndHJhbnNpdGlvbicpID09PSBcIm5vbmVcIiA/IDAgOiBzZXR0aW5ncy5nZXQoJ3NwZWVkJykpO1xuXHRcdH1cblx0fTtcblxuXHRwdWJsaWNNZXRob2QucHJlcCA9IGZ1bmN0aW9uIChvYmplY3QpIHtcblx0XHRpZiAoIW9wZW4pIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgY2FsbGJhY2ssIHNwZWVkID0gc2V0dGluZ3MuZ2V0KCd0cmFuc2l0aW9uJykgPT09IFwibm9uZVwiID8gMCA6IHNldHRpbmdzLmdldCgnc3BlZWQnKTtcblxuXHRcdCRsb2FkZWQucmVtb3ZlKCk7XG5cblx0XHQkbG9hZGVkID0gJHRhZyhkaXYsICdMb2FkZWRDb250ZW50JykuYXBwZW5kKG9iamVjdCk7XG5cblx0XHRmdW5jdGlvbiBnZXRXaWR0aCgpIHtcblx0XHRcdHNldHRpbmdzLncgPSBzZXR0aW5ncy53IHx8ICRsb2FkZWQud2lkdGgoKTtcblx0XHRcdHNldHRpbmdzLncgPSBzZXR0aW5ncy5tdyAmJiBzZXR0aW5ncy5tdyA8IHNldHRpbmdzLncgPyBzZXR0aW5ncy5tdyA6IHNldHRpbmdzLnc7XG5cdFx0XHRyZXR1cm4gc2V0dGluZ3Mudztcblx0XHR9XG5cdFx0ZnVuY3Rpb24gZ2V0SGVpZ2h0KCkge1xuXHRcdFx0c2V0dGluZ3MuaCA9IHNldHRpbmdzLmggfHwgJGxvYWRlZC5oZWlnaHQoKTtcblx0XHRcdHNldHRpbmdzLmggPSBzZXR0aW5ncy5taCAmJiBzZXR0aW5ncy5taCA8IHNldHRpbmdzLmggPyBzZXR0aW5ncy5taCA6IHNldHRpbmdzLmg7XG5cdFx0XHRyZXR1cm4gc2V0dGluZ3MuaDtcblx0XHR9XG5cblx0XHQkbG9hZGVkLmhpZGUoKVxuXHRcdC5hcHBlbmRUbygkbG9hZGluZ0JheS5zaG93KCkpLy8gY29udGVudCBoYXMgdG8gYmUgYXBwZW5kZWQgdG8gdGhlIERPTSBmb3IgYWNjdXJhdGUgc2l6ZSBjYWxjdWxhdGlvbnMuXG5cdFx0LmNzcyh7d2lkdGg6IGdldFdpZHRoKCksIG92ZXJmbG93OiBzZXR0aW5ncy5nZXQoJ3Njcm9sbGluZycpID8gJ2F1dG8nIDogJ2hpZGRlbid9KVxuXHRcdC5jc3Moe2hlaWdodDogZ2V0SGVpZ2h0KCl9KS8vIHNldHMgdGhlIGhlaWdodCBpbmRlcGVuZGVudGx5IGZyb20gdGhlIHdpZHRoIGluIGNhc2UgdGhlIG5ldyB3aWR0aCBpbmZsdWVuY2VzIHRoZSB2YWx1ZSBvZiBoZWlnaHQuXG5cdFx0LnByZXBlbmRUbygkY29udGVudCk7XG5cblx0XHQkbG9hZGluZ0JheS5oaWRlKCk7XG5cblx0XHQvLyBmbG9hdGluZyB0aGUgSU1HIHJlbW92ZXMgdGhlIGJvdHRvbSBsaW5lLWhlaWdodCBhbmQgZml4ZWQgYSBwcm9ibGVtIHdoZXJlIElFIG1pc2NhbGN1bGF0ZXMgdGhlIHdpZHRoIG9mIHRoZSBwYXJlbnQgZWxlbWVudCBhcyAxMDAlIG9mIHRoZSBkb2N1bWVudCB3aWR0aC5cblxuXHRcdCQocGhvdG8pLmNzcyh7J2Zsb2F0JzogJ25vbmUnfSk7XG5cblx0XHRzZXRDbGFzcyhzZXR0aW5ncy5nZXQoJ2NsYXNzTmFtZScpKTtcblxuXHRcdGNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0dmFyIHRvdGFsID0gJHJlbGF0ZWQubGVuZ3RoLFxuXHRcdFx0XHRpZnJhbWUsXG5cdFx0XHRcdGNvbXBsZXRlO1xuXG5cdFx0XHRpZiAoIW9wZW4pIHtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRmdW5jdGlvbiByZW1vdmVGaWx0ZXIoKSB7IC8vIE5lZWRlZCBmb3IgSUU4IGluIHZlcnNpb25zIG9mIGpRdWVyeSBwcmlvciB0byAxLjcuMlxuXHRcdFx0XHRpZiAoJC5zdXBwb3J0Lm9wYWNpdHkgPT09IGZhbHNlKSB7XG5cdFx0XHRcdFx0JGJveFswXS5zdHlsZS5yZW1vdmVBdHRyaWJ1dGUoJ2ZpbHRlcicpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdGNvbXBsZXRlID0gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRjbGVhclRpbWVvdXQobG9hZGluZ1RpbWVyKTtcblx0XHRcdFx0JGxvYWRpbmdPdmVybGF5LmhpZGUoKTtcblx0XHRcdFx0dHJpZ2dlcihldmVudF9jb21wbGV0ZSk7XG5cdFx0XHRcdHNldHRpbmdzLmdldCgnb25Db21wbGV0ZScpO1xuXHRcdFx0fTtcblxuXG5cdFx0XHQkdGl0bGUuaHRtbChzZXR0aW5ncy5nZXQoJ3RpdGxlJykpLnNob3coKTtcblx0XHRcdCRsb2FkZWQuc2hvdygpO1xuXG5cdFx0XHRpZiAodG90YWwgPiAxKSB7IC8vIGhhbmRsZSBncm91cGluZ1xuXHRcdFx0XHRpZiAodHlwZW9mIHNldHRpbmdzLmdldCgnY3VycmVudCcpID09PSBcInN0cmluZ1wiKSB7XG5cdFx0XHRcdFx0JGN1cnJlbnQuaHRtbChzZXR0aW5ncy5nZXQoJ2N1cnJlbnQnKS5yZXBsYWNlKCd7Y3VycmVudH0nLCBpbmRleCArIDEpLnJlcGxhY2UoJ3t0b3RhbH0nLCB0b3RhbCkpLnNob3coKTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdCRuZXh0WyhzZXR0aW5ncy5nZXQoJ2xvb3AnKSB8fCBpbmRleCA8IHRvdGFsIC0gMSkgPyBcInNob3dcIiA6IFwiaGlkZVwiXSgpLmh0bWwoc2V0dGluZ3MuZ2V0KCduZXh0JykpO1xuXHRcdFx0XHQkcHJldlsoc2V0dGluZ3MuZ2V0KCdsb29wJykgfHwgaW5kZXgpID8gXCJzaG93XCIgOiBcImhpZGVcIl0oKS5odG1sKHNldHRpbmdzLmdldCgncHJldmlvdXMnKSk7XG5cblx0XHRcdFx0c2xpZGVzaG93KCk7XG5cblx0XHRcdFx0Ly8gUHJlbG9hZHMgaW1hZ2VzIHdpdGhpbiBhIHJlbCBncm91cFxuXHRcdFx0XHRpZiAoc2V0dGluZ3MuZ2V0KCdwcmVsb2FkaW5nJykpIHtcblx0XHRcdFx0XHQkLmVhY2goW2dldEluZGV4KC0xKSwgZ2V0SW5kZXgoMSldLCBmdW5jdGlvbigpe1xuXHRcdFx0XHRcdFx0dmFyIGltZyxcblx0XHRcdFx0XHRcdFx0aSA9ICRyZWxhdGVkW3RoaXNdLFxuXHRcdFx0XHRcdFx0XHRzZXR0aW5ncyA9IG5ldyBTZXR0aW5ncyhpLCAkLmRhdGEoaSwgY29sb3Jib3gpKSxcblx0XHRcdFx0XHRcdFx0c3JjID0gc2V0dGluZ3MuZ2V0KCdocmVmJyk7XG5cblx0XHRcdFx0XHRcdGlmIChzcmMgJiYgaXNJbWFnZShzZXR0aW5ncywgc3JjKSkge1xuXHRcdFx0XHRcdFx0XHRzcmMgPSByZXRpbmFVcmwoc2V0dGluZ3MsIHNyYyk7XG5cdFx0XHRcdFx0XHRcdGltZyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2ltZycpO1xuXHRcdFx0XHRcdFx0XHRpbWcuc3JjID0gc3JjO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHQkZ3JvdXBDb250cm9scy5oaWRlKCk7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzZXR0aW5ncy5nZXQoJ2lmcmFtZScpKSB7XG5cblx0XHRcdFx0aWZyYW1lID0gc2V0dGluZ3MuZ2V0KCdjcmVhdGVJZnJhbWUnKTtcblxuXHRcdFx0XHRpZiAoIXNldHRpbmdzLmdldCgnc2Nyb2xsaW5nJykpIHtcblx0XHRcdFx0XHRpZnJhbWUuc2Nyb2xsaW5nID0gXCJub1wiO1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0JChpZnJhbWUpXG5cdFx0XHRcdFx0LmF0dHIoe1xuXHRcdFx0XHRcdFx0c3JjOiBzZXR0aW5ncy5nZXQoJ2hyZWYnKSxcblx0XHRcdFx0XHRcdCdjbGFzcyc6IHByZWZpeCArICdJZnJhbWUnXG5cdFx0XHRcdFx0fSlcblx0XHRcdFx0XHQub25lKCdsb2FkJywgY29tcGxldGUpXG5cdFx0XHRcdFx0LmFwcGVuZFRvKCRsb2FkZWQpO1xuXG5cdFx0XHRcdCRldmVudHMub25lKGV2ZW50X3B1cmdlLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0aWZyYW1lLnNyYyA9IFwiLy9hYm91dDpibGFua1wiO1xuXHRcdFx0XHR9KTtcblxuXHRcdFx0XHRpZiAoc2V0dGluZ3MuZ2V0KCdmYXN0SWZyYW1lJykpIHtcblx0XHRcdFx0XHQkKGlmcmFtZSkudHJpZ2dlcignbG9hZCcpO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRjb21wbGV0ZSgpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoc2V0dGluZ3MuZ2V0KCd0cmFuc2l0aW9uJykgPT09ICdmYWRlJykge1xuXHRcdFx0XHQkYm94LmZhZGVUbyhzcGVlZCwgMSwgcmVtb3ZlRmlsdGVyKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJlbW92ZUZpbHRlcigpO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0XHRpZiAoc2V0dGluZ3MuZ2V0KCd0cmFuc2l0aW9uJykgPT09ICdmYWRlJykge1xuXHRcdFx0JGJveC5mYWRlVG8oc3BlZWQsIDAsIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0cHVibGljTWV0aG9kLnBvc2l0aW9uKDAsIGNhbGxiYWNrKTtcblx0XHRcdH0pO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRwdWJsaWNNZXRob2QucG9zaXRpb24oc3BlZWQsIGNhbGxiYWNrKTtcblx0XHR9XG5cdH07XG5cblx0ZnVuY3Rpb24gbG9hZCAoKSB7XG5cdFx0dmFyIGhyZWYsIHNldFJlc2l6ZSwgcHJlcCA9IHB1YmxpY01ldGhvZC5wcmVwLCAkaW5saW5lLCByZXF1ZXN0ID0gKytyZXF1ZXN0cztcblxuXHRcdGFjdGl2ZSA9IHRydWU7XG5cblx0XHRwaG90byA9IGZhbHNlO1xuXG5cdFx0dHJpZ2dlcihldmVudF9wdXJnZSk7XG5cdFx0dHJpZ2dlcihldmVudF9sb2FkKTtcblx0XHRzZXR0aW5ncy5nZXQoJ29uTG9hZCcpO1xuXG5cdFx0c2V0dGluZ3MuaCA9IHNldHRpbmdzLmdldCgnaGVpZ2h0JykgP1xuXHRcdFx0XHRzZXRTaXplKHNldHRpbmdzLmdldCgnaGVpZ2h0JyksICd5JykgLSBsb2FkZWRIZWlnaHQgLSBpbnRlcmZhY2VIZWlnaHQgOlxuXHRcdFx0XHRzZXR0aW5ncy5nZXQoJ2lubmVySGVpZ2h0JykgJiYgc2V0U2l6ZShzZXR0aW5ncy5nZXQoJ2lubmVySGVpZ2h0JyksICd5Jyk7XG5cblx0XHRzZXR0aW5ncy53ID0gc2V0dGluZ3MuZ2V0KCd3aWR0aCcpID9cblx0XHRcdFx0c2V0U2l6ZShzZXR0aW5ncy5nZXQoJ3dpZHRoJyksICd4JykgLSBsb2FkZWRXaWR0aCAtIGludGVyZmFjZVdpZHRoIDpcblx0XHRcdFx0c2V0dGluZ3MuZ2V0KCdpbm5lcldpZHRoJykgJiYgc2V0U2l6ZShzZXR0aW5ncy5nZXQoJ2lubmVyV2lkdGgnKSwgJ3gnKTtcblxuXHRcdC8vIFNldHMgdGhlIG1pbmltdW0gZGltZW5zaW9ucyBmb3IgdXNlIGluIGltYWdlIHNjYWxpbmdcblx0XHRzZXR0aW5ncy5tdyA9IHNldHRpbmdzLnc7XG5cdFx0c2V0dGluZ3MubWggPSBzZXR0aW5ncy5oO1xuXG5cdFx0Ly8gUmUtZXZhbHVhdGUgdGhlIG1pbmltdW0gd2lkdGggYW5kIGhlaWdodCBiYXNlZCBvbiBtYXhXaWR0aCBhbmQgbWF4SGVpZ2h0IHZhbHVlcy5cblx0XHQvLyBJZiB0aGUgd2lkdGggb3IgaGVpZ2h0IGV4Y2VlZCB0aGUgbWF4V2lkdGggb3IgbWF4SGVpZ2h0LCB1c2UgdGhlIG1heGltdW0gdmFsdWVzIGluc3RlYWQuXG5cdFx0aWYgKHNldHRpbmdzLmdldCgnbWF4V2lkdGgnKSkge1xuXHRcdFx0c2V0dGluZ3MubXcgPSBzZXRTaXplKHNldHRpbmdzLmdldCgnbWF4V2lkdGgnKSwgJ3gnKSAtIGxvYWRlZFdpZHRoIC0gaW50ZXJmYWNlV2lkdGg7XG5cdFx0XHRzZXR0aW5ncy5tdyA9IHNldHRpbmdzLncgJiYgc2V0dGluZ3MudyA8IHNldHRpbmdzLm13ID8gc2V0dGluZ3MudyA6IHNldHRpbmdzLm13O1xuXHRcdH1cblx0XHRpZiAoc2V0dGluZ3MuZ2V0KCdtYXhIZWlnaHQnKSkge1xuXHRcdFx0c2V0dGluZ3MubWggPSBzZXRTaXplKHNldHRpbmdzLmdldCgnbWF4SGVpZ2h0JyksICd5JykgLSBsb2FkZWRIZWlnaHQgLSBpbnRlcmZhY2VIZWlnaHQ7XG5cdFx0XHRzZXR0aW5ncy5taCA9IHNldHRpbmdzLmggJiYgc2V0dGluZ3MuaCA8IHNldHRpbmdzLm1oID8gc2V0dGluZ3MuaCA6IHNldHRpbmdzLm1oO1xuXHRcdH1cblxuXHRcdGhyZWYgPSBzZXR0aW5ncy5nZXQoJ2hyZWYnKTtcblxuXHRcdGxvYWRpbmdUaW1lciA9IHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXHRcdFx0JGxvYWRpbmdPdmVybGF5LnNob3coKTtcblx0XHR9LCAxMDApO1xuXG5cdFx0aWYgKHNldHRpbmdzLmdldCgnaW5saW5lJykpIHtcblx0XHRcdHZhciAkdGFyZ2V0ID0gJChocmVmKS5lcSgwKTtcblx0XHRcdC8vIEluc2VydHMgYW4gZW1wdHkgcGxhY2Vob2xkZXIgd2hlcmUgaW5saW5lIGNvbnRlbnQgaXMgYmVpbmcgcHVsbGVkIGZyb20uXG5cdFx0XHQvLyBBbiBldmVudCBpcyBib3VuZCB0byBwdXQgaW5saW5lIGNvbnRlbnQgYmFjayB3aGVuIENvbG9yYm94IGNsb3NlcyBvciBsb2FkcyBuZXcgY29udGVudC5cblx0XHRcdCRpbmxpbmUgPSAkKCc8ZGl2PicpLmhpZGUoKS5pbnNlcnRCZWZvcmUoJHRhcmdldCk7XG5cblx0XHRcdCRldmVudHMub25lKGV2ZW50X3B1cmdlLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdCRpbmxpbmUucmVwbGFjZVdpdGgoJHRhcmdldCk7XG5cdFx0XHR9KTtcblxuXHRcdFx0cHJlcCgkdGFyZ2V0KTtcblx0XHR9IGVsc2UgaWYgKHNldHRpbmdzLmdldCgnaWZyYW1lJykpIHtcblx0XHRcdC8vIElGcmFtZSBlbGVtZW50IHdvbid0IGJlIGFkZGVkIHRvIHRoZSBET00gdW50aWwgaXQgaXMgcmVhZHkgdG8gYmUgZGlzcGxheWVkLFxuXHRcdFx0Ly8gdG8gYXZvaWQgcHJvYmxlbXMgd2l0aCBET00tcmVhZHkgSlMgdGhhdCBtaWdodCBiZSB0cnlpbmcgdG8gcnVuIGluIHRoYXQgaWZyYW1lLlxuXHRcdFx0cHJlcChcIiBcIik7XG5cdFx0fSBlbHNlIGlmIChzZXR0aW5ncy5nZXQoJ2h0bWwnKSkge1xuXHRcdFx0cHJlcChzZXR0aW5ncy5nZXQoJ2h0bWwnKSk7XG5cdFx0fSBlbHNlIGlmIChpc0ltYWdlKHNldHRpbmdzLCBocmVmKSkge1xuXG5cdFx0XHRocmVmID0gcmV0aW5hVXJsKHNldHRpbmdzLCBocmVmKTtcblxuXHRcdFx0cGhvdG8gPSBzZXR0aW5ncy5nZXQoJ2NyZWF0ZUltZycpO1xuXG5cdFx0XHQkKHBob3RvKVxuXHRcdFx0LmFkZENsYXNzKHByZWZpeCArICdQaG90bycpXG5cdFx0XHQuYmluZCgnZXJyb3IuJytwcmVmaXgsZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRwcmVwKCR0YWcoZGl2LCAnRXJyb3InKS5odG1sKHNldHRpbmdzLmdldCgnaW1nRXJyb3InKSkpO1xuXHRcdFx0fSlcblx0XHRcdC5vbmUoJ2xvYWQnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdGlmIChyZXF1ZXN0ICE9PSByZXF1ZXN0cykge1xuXHRcdFx0XHRcdHJldHVybjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEEgc21hbGwgcGF1c2UgYmVjYXVzZSBzb21lIGJyb3dzZXJzIHdpbGwgb2NjYXNzaW9uYWx5IHJlcG9ydCBhXG5cdFx0XHRcdC8vIGltZy53aWR0aCBhbmQgaW1nLmhlaWdodCBvZiB6ZXJvIGltbWVkaWF0ZWx5IGFmdGVyIHRoZSBpbWcub25sb2FkIGZpcmVzXG5cdFx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcblx0XHRcdFx0XHR2YXIgcGVyY2VudDtcblxuXHRcdFx0XHRcdGlmIChzZXR0aW5ncy5nZXQoJ3JldGluYUltYWdlJykgJiYgd2luZG93LmRldmljZVBpeGVsUmF0aW8gPiAxKSB7XG5cdFx0XHRcdFx0XHRwaG90by5oZWlnaHQgPSBwaG90by5oZWlnaHQgLyB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbztcblx0XHRcdFx0XHRcdHBob3RvLndpZHRoID0gcGhvdG8ud2lkdGggLyB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbztcblx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRpZiAoc2V0dGluZ3MuZ2V0KCdzY2FsZVBob3RvcycpKSB7XG5cdFx0XHRcdFx0XHRzZXRSZXNpemUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRcdHBob3RvLmhlaWdodCAtPSBwaG90by5oZWlnaHQgKiBwZXJjZW50O1xuXHRcdFx0XHRcdFx0XHRwaG90by53aWR0aCAtPSBwaG90by53aWR0aCAqIHBlcmNlbnQ7XG5cdFx0XHRcdFx0XHR9O1xuXHRcdFx0XHRcdFx0aWYgKHNldHRpbmdzLm13ICYmIHBob3RvLndpZHRoID4gc2V0dGluZ3MubXcpIHtcblx0XHRcdFx0XHRcdFx0cGVyY2VudCA9IChwaG90by53aWR0aCAtIHNldHRpbmdzLm13KSAvIHBob3RvLndpZHRoO1xuXHRcdFx0XHRcdFx0XHRzZXRSZXNpemUoKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdGlmIChzZXR0aW5ncy5taCAmJiBwaG90by5oZWlnaHQgPiBzZXR0aW5ncy5taCkge1xuXHRcdFx0XHRcdFx0XHRwZXJjZW50ID0gKHBob3RvLmhlaWdodCAtIHNldHRpbmdzLm1oKSAvIHBob3RvLmhlaWdodDtcblx0XHRcdFx0XHRcdFx0c2V0UmVzaXplKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0aWYgKHNldHRpbmdzLmgpIHtcblx0XHRcdFx0XHRcdHBob3RvLnN0eWxlLm1hcmdpblRvcCA9IE1hdGgubWF4KHNldHRpbmdzLm1oIC0gcGhvdG8uaGVpZ2h0LCAwKSAvIDIgKyAncHgnO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICgkcmVsYXRlZFsxXSAmJiAoc2V0dGluZ3MuZ2V0KCdsb29wJykgfHwgJHJlbGF0ZWRbaW5kZXggKyAxXSkpIHtcblx0XHRcdFx0XHRcdHBob3RvLnN0eWxlLmN1cnNvciA9ICdwb2ludGVyJztcblxuXHRcdFx0XHRcdFx0JChwaG90bykuYmluZCgnY2xpY2suJytwcmVmaXgsIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdFx0cHVibGljTWV0aG9kLm5leHQoKTtcblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHBob3RvLnN0eWxlLndpZHRoID0gcGhvdG8ud2lkdGggKyAncHgnO1xuXHRcdFx0XHRcdHBob3RvLnN0eWxlLmhlaWdodCA9IHBob3RvLmhlaWdodCArICdweCc7XG5cdFx0XHRcdFx0cHJlcChwaG90byk7XG5cdFx0XHRcdH0sIDEpO1xuXHRcdFx0fSk7XG5cblx0XHRcdHBob3RvLnNyYyA9IGhyZWY7XG5cblx0XHR9IGVsc2UgaWYgKGhyZWYpIHtcblx0XHRcdCRsb2FkaW5nQmF5LmxvYWQoaHJlZiwgc2V0dGluZ3MuZ2V0KCdkYXRhJyksIGZ1bmN0aW9uIChkYXRhLCBzdGF0dXMpIHtcblx0XHRcdFx0aWYgKHJlcXVlc3QgPT09IHJlcXVlc3RzKSB7XG5cdFx0XHRcdFx0cHJlcChzdGF0dXMgPT09ICdlcnJvcicgPyAkdGFnKGRpdiwgJ0Vycm9yJykuaHRtbChzZXR0aW5ncy5nZXQoJ3hockVycm9yJykpIDogJCh0aGlzKS5jb250ZW50cygpKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXHR9XG5cblx0Ly8gTmF2aWdhdGVzIHRvIHRoZSBuZXh0IHBhZ2UvaW1hZ2UgaW4gYSBzZXQuXG5cdHB1YmxpY01ldGhvZC5uZXh0ID0gZnVuY3Rpb24gKCkge1xuXHRcdGlmICghYWN0aXZlICYmICRyZWxhdGVkWzFdICYmIChzZXR0aW5ncy5nZXQoJ2xvb3AnKSB8fCAkcmVsYXRlZFtpbmRleCArIDFdKSkge1xuXHRcdFx0aW5kZXggPSBnZXRJbmRleCgxKTtcblx0XHRcdGxhdW5jaCgkcmVsYXRlZFtpbmRleF0pO1xuXHRcdH1cblx0fTtcblxuXHRwdWJsaWNNZXRob2QucHJldiA9IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIWFjdGl2ZSAmJiAkcmVsYXRlZFsxXSAmJiAoc2V0dGluZ3MuZ2V0KCdsb29wJykgfHwgaW5kZXgpKSB7XG5cdFx0XHRpbmRleCA9IGdldEluZGV4KC0xKTtcblx0XHRcdGxhdW5jaCgkcmVsYXRlZFtpbmRleF0pO1xuXHRcdH1cblx0fTtcblxuXHQvLyBOb3RlOiB0byB1c2UgdGhpcyB3aXRoaW4gYW4gaWZyYW1lIHVzZSB0aGUgZm9sbG93aW5nIGZvcm1hdDogcGFyZW50LmpRdWVyeS5jb2xvcmJveC5jbG9zZSgpO1xuXHRwdWJsaWNNZXRob2QuY2xvc2UgPSBmdW5jdGlvbiAoKSB7XG5cdFx0aWYgKG9wZW4gJiYgIWNsb3NpbmcpIHtcblxuXHRcdFx0Y2xvc2luZyA9IHRydWU7XG5cdFx0XHRvcGVuID0gZmFsc2U7XG5cdFx0XHR0cmlnZ2VyKGV2ZW50X2NsZWFudXApO1xuXHRcdFx0c2V0dGluZ3MuZ2V0KCdvbkNsZWFudXAnKTtcblx0XHRcdCR3aW5kb3cudW5iaW5kKCcuJyArIHByZWZpeCk7XG5cdFx0XHQkb3ZlcmxheS5mYWRlVG8oc2V0dGluZ3MuZ2V0KCdmYWRlT3V0JykgfHwgMCwgMCk7XG5cblx0XHRcdCRib3guc3RvcCgpLmZhZGVUbyhzZXR0aW5ncy5nZXQoJ2ZhZGVPdXQnKSB8fCAwLCAwLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdCRib3guaGlkZSgpO1xuXHRcdFx0XHQkb3ZlcmxheS5oaWRlKCk7XG5cdFx0XHRcdHRyaWdnZXIoZXZlbnRfcHVyZ2UpO1xuXHRcdFx0XHQkbG9hZGVkLnJlbW92ZSgpO1xuXG5cdFx0XHRcdHNldFRpbWVvdXQoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdGNsb3NpbmcgPSBmYWxzZTtcblx0XHRcdFx0XHR0cmlnZ2VyKGV2ZW50X2Nsb3NlZCk7XG5cdFx0XHRcdFx0c2V0dGluZ3MuZ2V0KCdvbkNsb3NlZCcpO1xuXHRcdFx0XHR9LCAxKTtcblx0XHRcdH0pO1xuXHRcdH1cblx0fTtcblxuXHQvLyBSZW1vdmVzIGNoYW5nZXMgQ29sb3Jib3ggbWFkZSB0byB0aGUgZG9jdW1lbnQsIGJ1dCBkb2VzIG5vdCByZW1vdmUgdGhlIHBsdWdpbi5cblx0cHVibGljTWV0aG9kLnJlbW92ZSA9IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoISRib3gpIHsgcmV0dXJuOyB9XG5cblx0XHQkYm94LnN0b3AoKTtcblx0XHQkW2NvbG9yYm94XS5jbG9zZSgpO1xuXHRcdCRib3guc3RvcChmYWxzZSwgdHJ1ZSkucmVtb3ZlKCk7XG5cdFx0JG92ZXJsYXkucmVtb3ZlKCk7XG5cdFx0Y2xvc2luZyA9IGZhbHNlO1xuXHRcdCRib3ggPSBudWxsO1xuXHRcdCQoJy4nICsgYm94RWxlbWVudClcblx0XHRcdC5yZW1vdmVEYXRhKGNvbG9yYm94KVxuXHRcdFx0LnJlbW92ZUNsYXNzKGJveEVsZW1lbnQpO1xuXG5cdFx0JChkb2N1bWVudCkudW5iaW5kKCdjbGljay4nK3ByZWZpeCkudW5iaW5kKCdrZXlkb3duLicrcHJlZml4KTtcblx0fTtcblxuXHQvLyBBIG1ldGhvZCBmb3IgZmV0Y2hpbmcgdGhlIGN1cnJlbnQgZWxlbWVudCBDb2xvcmJveCBpcyByZWZlcmVuY2luZy5cblx0Ly8gcmV0dXJucyBhIGpRdWVyeSBvYmplY3QuXG5cdHB1YmxpY01ldGhvZC5lbGVtZW50ID0gZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiAkKHNldHRpbmdzLmVsKTtcblx0fTtcblxuXHRwdWJsaWNNZXRob2Quc2V0dGluZ3MgPSBkZWZhdWx0cztcblxufShqUXVlcnksIGRvY3VtZW50LCB3aW5kb3cpKTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2pxdWVyeS1jb2xvcmJveC9qcXVlcnkuY29sb3Jib3guanNcbi8vIG1vZHVsZSBpZCA9IDEzN1xuLy8gbW9kdWxlIGNodW5rcyA9IDAiLCIvKiFcblx0V2hlZWx6b29tIDMuMS4yXG5cdGxpY2Vuc2U6IE1JVFxuXHRodHRwOi8vd3d3LmphY2tsbW9vcmUuY29tL3doZWVsem9vbVxuKi9cbndpbmRvdy53aGVlbHpvb20gPSAoZnVuY3Rpb24oKXtcblx0dmFyIGRlZmF1bHRzID0ge1xuXHRcdHpvb206IDAuMTAsXG5cdFx0bWF4Wm9vbTogZmFsc2UsXG5cdH07XG5cblx0dmFyIGNhbnZhcyA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2NhbnZhcycpO1xuXG5cdHZhciBtYWluID0gZnVuY3Rpb24oaW1nLCBvcHRpb25zKXtcblx0XHRpZiAoIWltZyB8fCAhaW1nLm5vZGVOYW1lIHx8IGltZy5ub2RlTmFtZSAhPT0gJ0lNRycpIHsgcmV0dXJuOyB9XG5cblx0XHR2YXIgc2V0dGluZ3MgPSB7fTtcblx0XHR2YXIgd2lkdGg7XG5cdFx0dmFyIGhlaWdodDtcblx0XHR2YXIgYmdXaWR0aDtcblx0XHR2YXIgYmdIZWlnaHQ7XG5cdFx0dmFyIGJnUG9zWDtcblx0XHR2YXIgYmdQb3NZO1xuXHRcdHZhciBwcmV2aW91c0V2ZW50O1xuXHRcdHZhciBjYWNoZWREYXRhVXJsO1xuXG5cdFx0ZnVuY3Rpb24gc2V0U3JjVG9CYWNrZ3JvdW5kKGltZykge1xuXHRcdFx0aW1nLnN0eWxlLmJhY2tncm91bmRJbWFnZSA9ICd1cmwoXCInK2ltZy5zcmMrJ1wiKSc7XG5cdFx0XHRpbWcuc3R5bGUuYmFja2dyb3VuZFJlcGVhdCA9ICduby1yZXBlYXQnO1xuXHRcdFx0Y2FudmFzLndpZHRoID0gaW1nLm5hdHVyYWxXaWR0aDtcblx0XHRcdGNhbnZhcy5oZWlnaHQgPSBpbWcubmF0dXJhbEhlaWdodDtcblx0XHRcdGNhY2hlZERhdGFVcmwgPSBjYW52YXMudG9EYXRhVVJMKCk7XG5cdFx0XHRpbWcuc3JjID0gY2FjaGVkRGF0YVVybDtcblx0XHR9XG5cblx0XHRmdW5jdGlvbiB1cGRhdGVCZ1N0eWxlKCkge1xuXHRcdFx0aWYgKGJnUG9zWCA+IDApIHtcblx0XHRcdFx0YmdQb3NYID0gMDtcblx0XHRcdH0gZWxzZSBpZiAoYmdQb3NYIDwgd2lkdGggLSBiZ1dpZHRoKSB7XG5cdFx0XHRcdGJnUG9zWCA9IHdpZHRoIC0gYmdXaWR0aDtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGJnUG9zWSA+IDApIHtcblx0XHRcdFx0YmdQb3NZID0gMDtcblx0XHRcdH0gZWxzZSBpZiAoYmdQb3NZIDwgaGVpZ2h0IC0gYmdIZWlnaHQpIHtcblx0XHRcdFx0YmdQb3NZID0gaGVpZ2h0IC0gYmdIZWlnaHQ7XG5cdFx0XHR9XG5cblx0XHRcdGltZy5zdHlsZS5iYWNrZ3JvdW5kU2l6ZSA9IGJnV2lkdGgrJ3B4ICcrYmdIZWlnaHQrJ3B4Jztcblx0XHRcdGltZy5zdHlsZS5iYWNrZ3JvdW5kUG9zaXRpb24gPSBiZ1Bvc1grJ3B4ICcrYmdQb3NZKydweCc7XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gcmVzZXQoKSB7XG5cdFx0XHRiZ1dpZHRoID0gd2lkdGg7XG5cdFx0XHRiZ0hlaWdodCA9IGhlaWdodDtcblx0XHRcdGJnUG9zWCA9IGJnUG9zWSA9IDA7XG5cdFx0XHR1cGRhdGVCZ1N0eWxlKCk7XG5cdFx0fVxuXG5cdFx0ZnVuY3Rpb24gb253aGVlbChlKSB7XG5cdFx0XHR2YXIgZGVsdGFZID0gMDtcblxuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG5cdFx0XHRpZiAoZS5kZWx0YVkpIHsgLy8gRmlyZUZveCAxNysgKElFOSssIENocm9tZSAzMSs/KVxuXHRcdFx0XHRkZWx0YVkgPSBlLmRlbHRhWTtcblx0XHRcdH0gZWxzZSBpZiAoZS53aGVlbERlbHRhKSB7XG5cdFx0XHRcdGRlbHRhWSA9IC1lLndoZWVsRGVsdGE7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEFzIGZhciBhcyBJIGtub3csIHRoZXJlIGlzIG5vIGdvb2QgY3Jvc3MtYnJvd3NlciB3YXkgdG8gZ2V0IHRoZSBjdXJzb3IgcG9zaXRpb24gcmVsYXRpdmUgdG8gdGhlIGV2ZW50IHRhcmdldC5cblx0XHRcdC8vIFdlIGhhdmUgdG8gY2FsY3VsYXRlIHRoZSB0YXJnZXQgZWxlbWVudCdzIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudCwgYW5kIHN1YnRyYWNrIHRoYXQgZnJvbSB0aGVcblx0XHRcdC8vIGN1cnNvcidzIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBkb2N1bWVudC5cblx0XHRcdHZhciByZWN0ID0gaW1nLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXHRcdFx0dmFyIG9mZnNldFggPSBlLnBhZ2VYIC0gcmVjdC5sZWZ0IC0gd2luZG93LnBhZ2VYT2Zmc2V0O1xuXHRcdFx0dmFyIG9mZnNldFkgPSBlLnBhZ2VZIC0gcmVjdC50b3AgLSB3aW5kb3cucGFnZVlPZmZzZXQ7XG5cblx0XHRcdC8vIFJlY29yZCB0aGUgb2Zmc2V0IGJldHdlZW4gdGhlIGJnIGVkZ2UgYW5kIGN1cnNvcjpcblx0XHRcdHZhciBiZ0N1cnNvclggPSBvZmZzZXRYIC0gYmdQb3NYO1xuXHRcdFx0dmFyIGJnQ3Vyc29yWSA9IG9mZnNldFkgLSBiZ1Bvc1k7XG5cdFx0XHRcblx0XHRcdC8vIFVzZSB0aGUgcHJldmlvdXMgb2Zmc2V0IHRvIGdldCB0aGUgcGVyY2VudCBvZmZzZXQgYmV0d2VlbiB0aGUgYmcgZWRnZSBhbmQgY3Vyc29yOlxuXHRcdFx0dmFyIGJnUmF0aW9YID0gYmdDdXJzb3JYL2JnV2lkdGg7XG5cdFx0XHR2YXIgYmdSYXRpb1kgPSBiZ0N1cnNvclkvYmdIZWlnaHQ7XG5cblx0XHRcdC8vIFVwZGF0ZSB0aGUgYmcgc2l6ZTpcblx0XHRcdGlmIChkZWx0YVkgPCAwKSB7XG5cdFx0XHRcdGJnV2lkdGggKz0gYmdXaWR0aCpzZXR0aW5ncy56b29tO1xuXHRcdFx0XHRiZ0hlaWdodCArPSBiZ0hlaWdodCpzZXR0aW5ncy56b29tO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0YmdXaWR0aCAtPSBiZ1dpZHRoKnNldHRpbmdzLnpvb207XG5cdFx0XHRcdGJnSGVpZ2h0IC09IGJnSGVpZ2h0KnNldHRpbmdzLnpvb207XG5cdFx0XHR9XG5cblx0XHRcdGlmIChzZXR0aW5ncy5tYXhab29tKSB7XG5cdFx0XHRcdGJnV2lkdGggPSBNYXRoLm1pbih3aWR0aCpzZXR0aW5ncy5tYXhab29tLCBiZ1dpZHRoKTtcblx0XHRcdFx0YmdIZWlnaHQgPSBNYXRoLm1pbihoZWlnaHQqc2V0dGluZ3MubWF4Wm9vbSwgYmdIZWlnaHQpO1xuXHRcdFx0fVxuXG5cdFx0XHQvLyBUYWtlIHRoZSBwZXJjZW50IG9mZnNldCBhbmQgYXBwbHkgaXQgdG8gdGhlIG5ldyBzaXplOlxuXHRcdFx0YmdQb3NYID0gb2Zmc2V0WCAtIChiZ1dpZHRoICogYmdSYXRpb1gpO1xuXHRcdFx0YmdQb3NZID0gb2Zmc2V0WSAtIChiZ0hlaWdodCAqIGJnUmF0aW9ZKTtcblxuXHRcdFx0Ly8gUHJldmVudCB6b29taW5nIG91dCBiZXlvbmQgdGhlIHN0YXJ0aW5nIHNpemVcblx0XHRcdGlmIChiZ1dpZHRoIDw9IHdpZHRoIHx8IGJnSGVpZ2h0IDw9IGhlaWdodCkge1xuXHRcdFx0XHRyZXNldCgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dXBkYXRlQmdTdHlsZSgpO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGRyYWcoZSkge1xuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0YmdQb3NYICs9IChlLnBhZ2VYIC0gcHJldmlvdXNFdmVudC5wYWdlWCk7XG5cdFx0XHRiZ1Bvc1kgKz0gKGUucGFnZVkgLSBwcmV2aW91c0V2ZW50LnBhZ2VZKTtcblx0XHRcdHByZXZpb3VzRXZlbnQgPSBlO1xuXHRcdFx0dXBkYXRlQmdTdHlsZSgpO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIHJlbW92ZURyYWcoKSB7XG5cdFx0XHRkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgcmVtb3ZlRHJhZyk7XG5cdFx0XHRkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBkcmFnKTtcblx0XHR9XG5cblx0XHQvLyBNYWtlIHRoZSBiYWNrZ3JvdW5kIGRyYWdnYWJsZVxuXHRcdGZ1bmN0aW9uIGRyYWdnYWJsZShlKSB7XG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRwcmV2aW91c0V2ZW50ID0gZTtcblx0XHRcdGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIGRyYWcpO1xuXHRcdFx0ZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIHJlbW92ZURyYWcpO1xuXHRcdH1cblxuXHRcdGZ1bmN0aW9uIGxvYWQoKSB7XG5cdFx0XHRpZiAoaW1nLnNyYyA9PT0gY2FjaGVkRGF0YVVybCkgcmV0dXJuO1xuXG5cdFx0XHR2YXIgY29tcHV0ZWRTdHlsZSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKGltZywgbnVsbCk7XG5cblx0XHRcdHdpZHRoID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS53aWR0aCwgMTApO1xuXHRcdFx0aGVpZ2h0ID0gcGFyc2VJbnQoY29tcHV0ZWRTdHlsZS5oZWlnaHQsIDEwKTtcblx0XHRcdGJnV2lkdGggPSB3aWR0aDtcblx0XHRcdGJnSGVpZ2h0ID0gaGVpZ2h0O1xuXHRcdFx0YmdQb3NYID0gMDtcblx0XHRcdGJnUG9zWSA9IDA7XG5cblx0XHRcdHNldFNyY1RvQmFja2dyb3VuZChpbWcpO1xuXG5cdFx0XHRpbWcuc3R5bGUuYmFja2dyb3VuZFNpemUgPSAgd2lkdGgrJ3B4ICcraGVpZ2h0KydweCc7XG5cdFx0XHRpbWcuc3R5bGUuYmFja2dyb3VuZFBvc2l0aW9uID0gJzAgMCc7XG5cdFx0XHRpbWcuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWx6b29tLnJlc2V0JywgcmVzZXQpO1xuXG5cdFx0XHRpbWcuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBvbndoZWVsKTtcblx0XHRcdGltZy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCBkcmFnZ2FibGUpO1xuXHRcdH1cblxuXHRcdHZhciBkZXN0cm95ID0gZnVuY3Rpb24gKG9yaWdpbmFsUHJvcGVydGllcykge1xuXHRcdFx0aW1nLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3doZWVsem9vbS5kZXN0cm95JywgZGVzdHJveSk7XG5cdFx0XHRpbWcucmVtb3ZlRXZlbnRMaXN0ZW5lcignd2hlZWx6b29tLnJlc2V0JywgcmVzZXQpO1xuXHRcdFx0aW1nLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBsb2FkKTtcblx0XHRcdGltZy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgcmVtb3ZlRHJhZyk7XG5cdFx0XHRpbWcucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgZHJhZyk7XG5cdFx0XHRpbWcucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgZHJhZ2dhYmxlKTtcblx0XHRcdGltZy5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIG9ud2hlZWwpO1xuXG5cdFx0XHRpbWcuc3R5bGUuYmFja2dyb3VuZEltYWdlID0gb3JpZ2luYWxQcm9wZXJ0aWVzLmJhY2tncm91bmRJbWFnZTtcblx0XHRcdGltZy5zdHlsZS5iYWNrZ3JvdW5kUmVwZWF0ID0gb3JpZ2luYWxQcm9wZXJ0aWVzLmJhY2tncm91bmRSZXBlYXQ7XG5cdFx0XHRpbWcuc3JjID0gb3JpZ2luYWxQcm9wZXJ0aWVzLnNyYztcblx0XHR9LmJpbmQobnVsbCwge1xuXHRcdFx0YmFja2dyb3VuZEltYWdlOiBpbWcuc3R5bGUuYmFja2dyb3VuZEltYWdlLFxuXHRcdFx0YmFja2dyb3VuZFJlcGVhdDogaW1nLnN0eWxlLmJhY2tncm91bmRSZXBlYXQsXG5cdFx0XHRzcmM6IGltZy5zcmNcblx0XHR9KTtcblxuXHRcdGltZy5hZGRFdmVudExpc3RlbmVyKCd3aGVlbHpvb20uZGVzdHJveScsIGRlc3Ryb3kpO1xuXG5cdFx0b3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG5cblx0XHRPYmplY3Qua2V5cyhkZWZhdWx0cykuZm9yRWFjaChmdW5jdGlvbihrZXkpe1xuXHRcdFx0c2V0dGluZ3Nba2V5XSA9IG9wdGlvbnNba2V5XSAhPT0gdW5kZWZpbmVkID8gb3B0aW9uc1trZXldIDogZGVmYXVsdHNba2V5XTtcblx0XHR9KTtcblxuXHRcdGlmIChpbWcuY29tcGxldGUpIHtcblx0XHRcdGxvYWQoKTtcblx0XHR9XG5cblx0XHRpbWcuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsIGxvYWQpO1xuXHR9O1xuXG5cdC8vIERvIG5vdGhpbmcgaW4gSUU4XG5cdGlmICh0eXBlb2Ygd2luZG93LmdldENvbXB1dGVkU3R5bGUgIT09ICdmdW5jdGlvbicpIHtcblx0XHRyZXR1cm4gZnVuY3Rpb24oZWxlbWVudHMpIHtcblx0XHRcdHJldHVybiBlbGVtZW50cztcblx0XHR9O1xuXHR9IGVsc2Uge1xuXHRcdHJldHVybiBmdW5jdGlvbihlbGVtZW50cywgb3B0aW9ucykge1xuXHRcdFx0aWYgKGVsZW1lbnRzICYmIGVsZW1lbnRzLmxlbmd0aCkge1xuXHRcdFx0XHRBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKGVsZW1lbnRzLCBtYWluLCBvcHRpb25zKTtcblx0XHRcdH0gZWxzZSBpZiAoZWxlbWVudHMgJiYgZWxlbWVudHMubm9kZU5hbWUpIHtcblx0XHRcdFx0bWFpbihlbGVtZW50cywgb3B0aW9ucyk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZWxlbWVudHM7XG5cdFx0fTtcblx0fVxufSgpKTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy93aGVlbHpvb20vd2hlZWx6b29tLmpzXG4vLyBtb2R1bGUgaWQgPSAxMzhcbi8vIG1vZHVsZSBjaHVua3MgPSAwIl0sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file
diff --git a/public/assets-2.0.0/js/webtrees.js b/public/assets-2.0.0/js/webtrees.js
new file mode 100644
index 0000000000..396249bee4
--- /dev/null
+++ b/public/assets-2.0.0/js/webtrees.js
@@ -0,0 +1,998 @@
+/**
+ * webtrees: online genealogy
+ * Copyright (C) 2017 webtrees development team
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+'use strict';
+
+// "rtl" on right-to-left pages.
+
+var textDirection = $('html').attr('dir');
+
+function expand_layer(sid) {
+ $('#' + sid + '_img').toggleClass('icon-plus icon-minus');
+ $('#' + sid).slideToggle('fast');
+ $('#' + sid + '-alt').toggle(); // hide something when we show the layer - and vice-versa
+ return false;
+}
+
+// Accept the changes to a record - and reload the page
+function accept_changes(xref) {
+ $.post('action.php', {
+ action: 'accept-changes',
+ xref: xref,
+ ged: WT_GEDCOM
+ }, function () {
+ location.reload();
+ });
+ return false;
+}
+
+// Reject the changes to a record - and reload the page
+function reject_changes(xref) {
+ $.post('action.php', {
+ action: 'reject-changes',
+ xref: xref,
+ ged: WT_GEDCOM
+ }, function () {
+ location.reload();
+ });
+ return false;
+}
+
+// Delete a record - and reload the page
+function delete_record(message, xref, gedcom) {
+ if (confirm(message)) {
+ $.post('action.php', {
+ action: 'delete-record',
+ xref: xref,
+ ged: typeof gedcom === 'undefined' ? WT_GEDCOM : gedcom
+ }, function () {
+ location.reload();
+ });
+ }
+ return false;
+}
+
+// Delete a fact - and reload the page
+function delete_fact(message, xref, fact_id) {
+ if (confirm(message)) {
+ $.post('action.php', {
+ action: 'delete-fact',
+ xref: xref,
+ fact_id: fact_id,
+ ged: WT_GEDCOM
+ }, function () {
+ location.reload();
+ });
+ }
+ return false;
+}
+
+// Remove links from one record to another - and reload the page
+function unlink_media(message, source, target) {
+ if (confirm(message)) {
+ $.post('action.php', {
+ action: 'unlink-media',
+ source: source,
+ target: target,
+ ged: WT_GEDCOM
+ }, function () {
+ location.reload();
+ });
+ }
+ return false;
+}
+
+// Copy a fact to the clipboard
+function copy_fact(xref, fact_id) {
+ $.post('action.php', {
+ action: 'copy-fact',
+ xref: xref,
+ fact_id: fact_id,
+ ged: WT_GEDCOM
+ }, function () {
+ location.reload();
+ });
+ return false;
+}
+
+// Paste a fact from the clipboard
+function paste_fact(xref, element) {
+ $.post('action.php', {
+ action: 'paste-fact',
+ xref: xref,
+ fact_id: $(element).val(), // element is the <select> containing the option
+ ged: WT_GEDCOM
+ }, function () {
+ location.reload();
+ });
+ return false;
+}
+
+// Delete a user - and reload the page
+function delete_user(message, user_id) {
+ if (confirm(message)) {
+ $.post('action.php', {
+ action: 'delete-user',
+ user_id: user_id
+ }, function () {
+ location.reload();
+ });
+ }
+ return false;
+}
+
+// Masquerade as another user - and reload the page.
+function masquerade(user_id) {
+ $.post('action.php', {
+ action: 'masquerade',
+ user_id: user_id
+ }, function () {
+ location.reload();
+ });
+ return false;
+}
+
+var pastefield;
+function addmedia_links(field, iid, iname) {
+ pastefield = field;
+ insertRowToTable(iid, iname);
+ return false;
+}
+
+function valid_date(datefield) {
+ var months = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'];
+ var hijri_months = ['MUHAR', 'SAFAR', 'RABIA', 'RABIT', 'JUMAA', 'JUMAT', 'RAJAB', 'SHAAB', 'RAMAD', 'SHAWW', 'DHUAQ', 'DHUAH'];
+ var hebrew_months = ['TSH', 'CSH', 'KSL', 'TVT', 'SHV', 'ADR', 'ADS', 'NSN', 'IYR', 'SVN', 'TMZ', 'AAV', 'ELL'];
+ var french_months = ['VEND', 'BRUM', 'FRIM', 'NIVO', 'PLUV', 'VENT', 'GERM', 'FLOR', 'PRAI', 'MESS', 'THER', 'FRUC', 'COMP'];
+ var jalali_months = ['FARVA', 'ORDIB', 'KHORD', 'TIR', 'MORDA', 'SHAHR', 'MEHR', 'ABAN', 'AZAR', 'DEY', 'BAHMA', 'ESFAN'];
+
+ var datestr = datefield.value;
+ // if a date has a date phrase marked by () this has to be excluded from altering
+ var datearr = datestr.split('(');
+ var datephrase = '';
+ if (datearr.length > 1) {
+ datestr = datearr[0];
+ datephrase = datearr[1];
+ }
+
+ // Gedcom dates are upper case
+ datestr = datestr.toUpperCase();
+ // Gedcom dates have no leading/trailing/repeated whitespace
+ datestr = datestr.replace(/\s+/, ' ');
+ datestr = datestr.replace(/(^\s)|(\s$)/, '');
+ // Gedcom dates have spaces between letters and digits, e.g. "01JAN2000" => "01 JAN 2000"
+ datestr = datestr.replace(/(\d)([A-Z])/, '$1 $2');
+ datestr = datestr.replace(/([A-Z])(\d)/, '$1 $2');
+
+ // Shortcut for quarter format, "Q1 1900" => "BET JAN 1900 AND MAR 1900". See [ 1509083 ]
+ if (datestr.match(/^Q ([1-4]) (\d\d\d\d)$/)) {
+ datestr = 'BET ' + months[RegExp.$1 * 3 - 3] + ' ' + RegExp.$2 + ' AND ' + months[RegExp.$1 * 3 - 1] + ' ' + RegExp.$2;
+ }
+
+ // Shortcut for @#Dxxxxx@ 01 01 1400, etc.
+ if (datestr.match(/^(@#DHIJRI@|HIJRI)( \d?\d )(\d?\d)( \d?\d?\d?\d)$/)) {
+ datestr = '@#DHIJRI@' + RegExp.$2 + hijri_months[parseInt(RegExp.$3, 10) - 1] + RegExp.$4;
+ }
+ if (datestr.match(/^(@#DJALALI@|JALALI)( \d?\d )(\d?\d)( \d?\d?\d?\d)$/)) {
+ datestr = '@#DJALALI@' + RegExp.$2 + jalali_months[parseInt(RegExp.$3, 10) - 1] + RegExp.$4;
+ }
+ if (datestr.match(/^(@#DHEBREW@|HEBREW)( \d?\d )(\d?\d)( \d?\d?\d?\d)$/)) {
+ datestr = '@#DHEBREW@' + RegExp.$2 + hebrew_months[parseInt(RegExp.$3, 10) - 1] + RegExp.$4;
+ }
+ if (datestr.match(/^(@#DFRENCH R@|FRENCH)( \d?\d )(\d?\d)( \d?\d?\d?\d)$/)) {
+ datestr = '@#DFRENCH R@' + RegExp.$2 + french_months[parseInt(RegExp.$3, 10) - 1] + RegExp.$4;
+ }
+
+ // e.g. 17.11.1860, 03/04/2005 or 1999-12-31. Use locale settings where DMY order is ambiguous.
+ var qsearch = /^([^\d]*)(\d+)[^\d](\d+)[^\d](\d+)$/i;
+ if (qsearch.exec(datestr)) {
+ var f0 = RegExp.$1;
+ var f1 = parseInt(RegExp.$2, 10);
+ var f2 = parseInt(RegExp.$3, 10);
+ var f3 = parseInt(RegExp.$4, 10);
+ var dmy = 'DMY';
+ if (typeof locale_date_format !== 'undefined') {
+ if (locale_date_format === 'MDY' || locale_date_format === 'YMD') {
+ dmy = locale_date_format;
+ }
+ }
+ var yyyy = new Date().getFullYear();
+ var yy = yyyy % 100;
+ var cc = yyyy - yy;
+ if (dmy === 'DMY' && f1 <= 31 && f2 <= 12 || f1 > 13 && f1 <= 31 && f2 <= 12 && f3 > 31) {
+ datestr = f0 + f1 + ' ' + months[f2 - 1] + ' ' + (f3 >= 100 ? f3 : f3 <= yy ? f3 + cc : f3 + cc - 100);
+ } else {
+ if (dmy === 'MDY' && f1 <= 12 && f2 <= 31 || f2 > 13 && f2 <= 31 && f1 <= 12 && f3 > 31) {
+ datestr = f0 + f2 + ' ' + months[f1 - 1] + ' ' + (f3 >= 100 ? f3 : f3 <= yy ? f3 + cc : f3 + cc - 100);
+ } else {
+ if (dmy === 'YMD' && f2 <= 12 && f3 <= 31 || f3 > 13 && f3 <= 31 && f2 <= 12 && f1 > 31) {
+ datestr = f0 + f3 + ' ' + months[f2 - 1] + ' ' + (f1 >= 100 ? f1 : f1 <= yy ? f1 + cc : f1 + cc - 100);
+ }
+ }
+ }
+ }
+
+ // Shortcuts for date ranges
+ datestr = datestr.replace(/^[>]([\w ]+)$/, 'AFT $1');
+ datestr = datestr.replace(/^[<]([\w ]+)$/, 'BEF $1');
+ datestr = datestr.replace(/^([\w ]+)[-]$/, 'FROM $1');
+ datestr = datestr.replace(/^[-]([\w ]+)$/, 'TO $1');
+ datestr = datestr.replace(/^[~]([\w ]+)$/, 'ABT $1');
+ datestr = datestr.replace(/^[*]([\w ]+)$/, 'EST $1');
+ datestr = datestr.replace(/^[#]([\w ]+)$/, 'CAL $1');
+ datestr = datestr.replace(/^([\w ]+) ?- ?([\w ]+)$/, 'BET $1 AND $2');
+ datestr = datestr.replace(/^([\w ]+) ?~ ?([\w ]+)$/, 'FROM $1 TO $2');
+
+ // Convert full months to short months
+ datestr = datestr.replace(/(JANUARY)/, 'JAN');
+ datestr = datestr.replace(/(FEBRUARY)/, 'FEB');
+ datestr = datestr.replace(/(MARCH)/, 'MAR');
+ datestr = datestr.replace(/(APRIL)/, 'APR');
+ datestr = datestr.replace(/(MAY)/, 'MAY');
+ datestr = datestr.replace(/(JUNE)/, 'JUN');
+ datestr = datestr.replace(/(JULY)/, 'JUL');
+ datestr = datestr.replace(/(AUGUST)/, 'AUG');
+ datestr = datestr.replace(/(SEPTEMBER)/, 'SEP');
+ datestr = datestr.replace(/(OCTOBER)/, 'OCT');
+ datestr = datestr.replace(/(NOVEMBER)/, 'NOV');
+ datestr = datestr.replace(/(DECEMBER)/, 'DEC');
+
+ // Americans frequently enter dates as SEP 20, 1999
+ // No need to internationalise this, as this is an english-language issue
+ datestr = datestr.replace(/(JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)\.? (\d\d?)[, ]+(\d\d\d\d)/, '$2 $1 $3');
+
+ // Apply leading zero to day numbers
+ datestr = datestr.replace(/(^| )(\d [A-Z]{3,5} \d{4})/, '$10$2');
+
+ if (datephrase) {
+ datestr = datestr + ' (' + datephrase;
+ }
+ // Only update it if is has been corrected - otherwise input focus
+ // moves to the end of the field unnecessarily
+ if (datefield.value !== datestr) {
+ datefield.value = datestr;
+ }
+}
+
+var menutimeouts = [];
+
+function show_submenu(elementid, parentid) {
+ var pagewidth = document.body.scrollWidth + document.documentElement.scrollLeft;
+ var element = document.getElementById(elementid);
+
+ if (element && element.style) {
+ if (document.all) {
+ pagewidth = document.body.offsetWidth;
+ } else {
+ pagewidth = document.body.scrollWidth + document.documentElement.scrollLeft - 55;
+ if (textDirection === 'rtl') {
+ boxright = element.offsetLeft + element.offsetWidth + 10;
+ }
+ }
+
+ // -- make sure the submenu is the size of the largest child
+ var maxwidth = 0;
+ var count = element.childNodes.length;
+ for (var i = 0; i < count; i++) {
+ var child = element.childNodes[i];
+ if (child.offsetWidth > maxwidth + 5) {
+ maxwidth = child.offsetWidth;
+ }
+ }
+ if (element.offsetWidth < maxwidth) {
+ element.style.width = maxwidth + 'px';
+ }
+ var pelement, boxright;
+ pelement = document.getElementById(parentid);
+ if (pelement) {
+ element.style.left = pelement.style.left;
+ boxright = element.offsetLeft + element.offsetWidth + 10;
+ if (boxright > pagewidth) {
+ var menuleft = pagewidth - element.offsetWidth;
+ element.style.left = menuleft + 'px';
+ }
+ }
+
+ if (element.offsetLeft < 0) {
+ element.style.left = '0px';
+ }
+
+ // -- put scrollbars on really long menus
+ if (element.offsetHeight > 500) {
+ element.style.height = '400px';
+ element.style.overflow = 'auto';
+ }
+
+ element.style.visibility = 'visible';
+ }
+ clearTimeout(menutimeouts[elementid]);
+ menutimeouts[elementid] = null;
+}
+
+function hide_submenu(elementid) {
+ if (typeof menutimeouts[elementid] !== 'number') {
+ return;
+ }
+ var element = document.getElementById(elementid);
+ if (element && element.style) {
+ element.style.visibility = 'hidden';
+ }
+ clearTimeout(menutimeouts[elementid]);
+ menutimeouts[elementid] = null;
+}
+
+function timeout_submenu(elementid) {
+ if (typeof menutimeouts[elementid] !== 'number') {
+ menutimeouts[elementid] = setTimeout("hide_submenu('" + elementid + "')", 100);
+ }
+}
+
+function statusDisable(sel) {
+ var cbox = document.getElementById(sel);
+ cbox.checked = false;
+ cbox.disabled = true;
+}
+
+function statusEnable(sel) {
+ var cbox = document.getElementById(sel);
+ cbox.disabled = false;
+}
+
+function statusChecked(sel) {
+ var cbox = document.getElementById(sel);
+ cbox.checked = true;
+}
+
+var monthLabels = [];
+monthLabels[1] = 'January';
+monthLabels[2] = 'February';
+monthLabels[3] = 'March';
+monthLabels[4] = 'April';
+monthLabels[5] = 'May';
+monthLabels[6] = 'June';
+monthLabels[7] = 'July';
+monthLabels[8] = 'August';
+monthLabels[9] = 'September';
+monthLabels[10] = 'October';
+monthLabels[11] = 'November';
+monthLabels[12] = 'December';
+
+var monthShort = [];
+monthShort[1] = 'JAN';
+monthShort[2] = 'FEB';
+monthShort[3] = 'MAR';
+monthShort[4] = 'APR';
+monthShort[5] = 'MAY';
+monthShort[6] = 'JUN';
+monthShort[7] = 'JUL';
+monthShort[8] = 'AUG';
+monthShort[9] = 'SEP';
+monthShort[10] = 'OCT';
+monthShort[11] = 'NOV';
+monthShort[12] = 'DEC';
+
+var daysOfWeek = [];
+daysOfWeek[0] = 'S';
+daysOfWeek[1] = 'M';
+daysOfWeek[2] = 'T';
+daysOfWeek[3] = 'W';
+daysOfWeek[4] = 'T';
+daysOfWeek[5] = 'F';
+daysOfWeek[6] = 'S';
+
+var weekStart = 0;
+
+function cal_setMonthNames(jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec) {
+ monthLabels[1] = jan;
+ monthLabels[2] = feb;
+ monthLabels[3] = mar;
+ monthLabels[4] = apr;
+ monthLabels[5] = may;
+ monthLabels[6] = jun;
+ monthLabels[7] = jul;
+ monthLabels[8] = aug;
+ monthLabels[9] = sep;
+ monthLabels[10] = oct;
+ monthLabels[11] = nov;
+ monthLabels[12] = dec;
+}
+
+function cal_setDayHeaders(sun, mon, tue, wed, thu, fri, sat) {
+ daysOfWeek[0] = sun;
+ daysOfWeek[1] = mon;
+ daysOfWeek[2] = tue;
+ daysOfWeek[3] = wed;
+ daysOfWeek[4] = thu;
+ daysOfWeek[5] = fri;
+ daysOfWeek[6] = sat;
+}
+
+function cal_setWeekStart(day) {
+ if (day >= 0 && day < 7) {
+ weekStart = day;
+ }
+}
+
+function calendarWidget(dateDivId, dateFieldId) {
+ var dateDiv = document.getElementById(dateDivId);
+ var dateField = document.getElementById(dateFieldId);
+
+ if (dateDiv.style.visibility === 'visible') {
+ dateDiv.style.visibility = 'hidden';
+ return false;
+ }
+ if (dateDiv.style.visibility === 'show') {
+ dateDiv.style.visibility = 'hide';
+ return false;
+ }
+
+ /* Javascript calendar functions only work with precise gregorian dates "D M Y" or "Y" */
+ var greg_regex = /((\d+ (JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC) )?\d+)/i;
+ var date;
+ if (greg_regex.exec(dateField.value)) {
+ date = new Date(RegExp.$1);
+ } else {
+ date = new Date();
+ }
+
+ dateDiv.innerHTML = cal_generateSelectorContent(dateFieldId, dateDivId, date);
+ if (dateDiv.style.visibility === 'hidden') {
+ dateDiv.style.visibility = 'visible';
+ return false;
+ }
+ if (dateDiv.style.visibility === 'hide') {
+ dateDiv.style.visibility = 'show';
+ return false;
+ }
+
+ return false;
+}
+
+function cal_generateSelectorContent(dateFieldId, dateDivId, date) {
+ var i, j;
+ var content = '<table border="1"><tr>';
+ content += '<td><select class="form-control" id="' + dateFieldId + '_daySelect" onchange="return cal_updateCalendar(\'' + dateFieldId + '\', \'' + dateDivId + '\');">';
+ for (i = 1; i < 32; i++) {
+ content += '<option value="' + i + '"';
+ if (date.getDate() === i) {
+ content += ' selected="selected"';
+ }
+ content += '>' + i + '</option>';
+ }
+ content += '</select></td>';
+ content += '<td><select class="form-control" id="' + dateFieldId + '_monSelect" onchange="return cal_updateCalendar(\'' + dateFieldId + '\', \'' + dateDivId + '\');">';
+ for (i = 1; i < 13; i++) {
+ content += '<option value="' + i + '"';
+ if (date.getMonth() + 1 === i) {
+ content += ' selected="selected"';
+ }
+ content += '>' + monthLabels[i] + '</option>';
+ }
+ content += '</select></td>';
+ content += '<td><input class="form-control" type="text" id="' + dateFieldId + '_yearInput" size="5" value="' + date.getFullYear() + '" onchange="return cal_updateCalendar(\'' + dateFieldId + '\', \'' + dateDivId + '\');" /></td></tr>';
+ content += '<tr><td colspan="3">';
+ content += '<table width="100%">';
+ content += '<tr>';
+ j = weekStart;
+ for (i = 0; i < 7; i++) {
+ content += '<td ';
+ content += 'class="descriptionbox"';
+ content += '>';
+ content += daysOfWeek[j];
+ content += '</td>';
+ j++;
+ if (j > 6) {
+ j = 0;
+ }
+ }
+ content += '</tr>';
+
+ var tdate = new Date(date.getFullYear(), date.getMonth(), 1);
+ var day = tdate.getDay();
+ day = day - weekStart;
+ var daymilli = 1000 * 60 * 60 * 24;
+ tdate = tdate.getTime() - day * daymilli + daymilli / 2;
+ tdate = new Date(tdate);
+
+ for (j = 0; j < 6; j++) {
+ content += '<tr>';
+ for (i = 0; i < 7; i++) {
+ content += '<td ';
+ if (tdate.getMonth() === date.getMonth()) {
+ if (tdate.getDate() === date.getDate()) {
+ content += 'class="descriptionbox"';
+ } else {
+ content += 'class="optionbox"';
+ }
+ } else {
+ content += 'style="background-color:#EAEAEA; border: solid #AAAAAA 1px;"';
+ }
+ content += '><a href="#" onclick="return cal_dateClicked(\'' + dateFieldId + '\', \'' + dateDivId + '\', ' + tdate.getFullYear() + ', ' + tdate.getMonth() + ', ' + tdate.getDate() + ');">';
+ content += tdate.getDate();
+ content += '</a></td>';
+ var datemilli = tdate.getTime() + daymilli;
+ tdate = new Date(datemilli);
+ }
+ content += '</tr>';
+ }
+ content += '</table>';
+ content += '</td></tr>';
+ content += '</table>';
+
+ return content;
+}
+
+function cal_setDateField(dateFieldId, year, month, day) {
+ var dateField = document.getElementById(dateFieldId);
+ if (!dateField) {
+ return false;
+ }
+ if (day < 10) {
+ day = '0' + day;
+ }
+ dateField.value = day + ' ' + monthShort[month + 1] + ' ' + year;
+ return false;
+}
+
+function cal_updateCalendar(dateFieldId, dateDivId) {
+ var dateSel = document.getElementById(dateFieldId + '_daySelect');
+ if (!dateSel) {
+ return false;
+ }
+ var monthSel = document.getElementById(dateFieldId + '_monSelect');
+ if (!monthSel) {
+ return false;
+ }
+ var yearInput = document.getElementById(dateFieldId + '_yearInput');
+ if (!yearInput) {
+ return false;
+ }
+
+ var month = parseInt(monthSel.options[monthSel.selectedIndex].value, 10);
+ month = month - 1;
+
+ var date = new Date(yearInput.value, month, dateSel.options[dateSel.selectedIndex].value);
+ cal_setDateField(dateFieldId, date.getFullYear(), date.getMonth(), date.getDate());
+
+ var dateDiv = document.getElementById(dateDivId);
+ if (!dateDiv) {
+ alert('no dateDiv ' + dateDivId);
+ return false;
+ }
+ dateDiv.innerHTML = cal_generateSelectorContent(dateFieldId, dateDivId, date);
+
+ return false;
+}
+
+function cal_dateClicked(dateFieldId, dateDivId, year, month, day) {
+ cal_setDateField(dateFieldId, year, month, day);
+ calendarWidget(dateDivId, dateFieldId);
+ return false;
+}
+
+function openerpasteid(id) {
+ if (window.opener.paste_id) {
+ window.opener.paste_id(id);
+ }
+ window.close();
+}
+
+function paste_id(value) {
+ pastefield.value = value;
+}
+
+function pastename(name) {
+ if (nameElement) {
+ nameElement.innerHTML = name;
+ }
+ if (remElement) {
+ remElement.style.display = 'block';
+ }
+}
+
+function paste_char(value) {
+ if (document.selection) {
+ // IE
+ pastefield.focus();
+ document.selection.createRange().text = value;
+ } else if (pastefield.selectionStart || pastefield.selectionStart === 0) {
+ // Mozilla/Chrome/Safari
+ pastefield.value = pastefield.value.substring(0, pastefield.selectionStart) + value + pastefield.value.substring(pastefield.selectionEnd, pastefield.value.length);
+ pastefield.selectionStart = pastefield.selectionEnd = pastefield.selectionStart + value.length;
+ } else {
+ // Fallback? - just append
+ pastefield.value += value;
+ }
+
+ if (pastefield.id === 'NPFX' || pastefield.id === 'GIVN' || pastefield.id === 'SPFX' || pastefield.id === 'SURN' || pastefield.id === 'NSFX') {
+ updatewholename();
+ }
+}
+
+function ilinkitem(mediaid, type, ged) {
+ ged = typeof ged === 'undefined' ? WT_GEDCOM : ged;
+ window.open('inverselink.php?mediaid=' + encodeURIComponent(mediaid) + '&linkto=' + encodeURIComponent(type) + '&ged=' + encodeURIComponent(ged), '_blank', find_window_specs);
+ return false;
+}
+
+/**
+ * Persistant checkbox options to hide/show extra data.
+
+ * @param checkbox_id
+ * @param data_selector
+ */
+function persistent_toggle(checkbox_id, data_selector) {
+ var checkbox = document.getElementById(checkbox_id);
+ var elements = document.querySelectorAll(data_selector);
+ var display = localStorage.getItem(checkbox_id);
+
+ if (!checkbox) {
+ return;
+ }
+
+ if (display !== '') {
+ display = 'none';
+ }
+
+ checkbox.checked = display === '';
+ for (var i = 0; i < elements.length; ++i) {
+ elements[i].style.display = display;
+ }
+
+ checkbox.addEventListener('click', function () {
+ console.log(display);
+ display = display === '' ? 'none' : '';
+ localStorage.setItem(checkbox_id, display);
+ for (var i = 0; i < elements.length; ++i) {
+ elements[i].style.display = display;
+ }
+ });
+}
+
+function valid_lati_long(field, pos, neg) {
+ // valid LATI or LONG according to Gedcom standard
+ // pos (+) : N or E
+ // neg (-) : S or W
+ var txt = field.value.toUpperCase();
+ txt = txt.replace(/(^\s*)|(\s*$)/g, ''); // trim
+ txt = txt.replace(/ /g, ':'); // N12 34 ==> N12.34
+ txt = txt.replace(/\+/g, ''); // +17.1234 ==> 17.1234
+ txt = txt.replace(/-/g, neg); // -0.5698 ==> W0.5698
+ txt = txt.replace(/,/g, '.'); // 0,5698 ==> 0.5698
+ // 0°34'11 ==> 0:34:11
+ txt = txt.replace(/\u00b0/g, ':'); // °
+ txt = txt.replace(/\u0027/g, ':'); // '
+ // 0:34:11.2W ==> W0.5698
+ txt = txt.replace(/^([0-9]+):([0-9]+):([0-9.]+)(.*)/g, function ($0, $1, $2, $3, $4) {
+ var n = parseFloat($1);
+ n += $2 / 60;
+ n += $3 / 3600;
+ n = Math.round(n * 1E4) / 1E4;
+ return $4 + n;
+ });
+ // 0:34W ==> W0.5667
+ txt = txt.replace(/^([0-9]+):([0-9]+)(.*)/g, function ($0, $1, $2, $3) {
+ var n = parseFloat($1);
+ n += $2 / 60;
+ n = Math.round(n * 1E4) / 1E4;
+ return $3 + n;
+ });
+ // 0.5698W ==> W0.5698
+ txt = txt.replace(/(.*)([N|S|E|W]+)$/g, '$2$1');
+ // 17.1234 ==> N17.1234
+ if (txt && txt.charAt(0) !== neg && txt.charAt(0) !== pos) {
+ txt = pos + txt;
+ }
+ field.value = txt;
+}
+
+// This is the default way for webtrees to show image galleries.
+// Custom themes may use a different viewer.
+function activate_colorbox(config) {
+ $.extend($.colorbox.settings, {
+ // Don't scroll window with document
+ fixed: true,
+ current: '',
+ previous: '\uF048',
+ next: '\uF051',
+ slideshowStart: '\uF04B',
+ slideshowStop: '\uF04C',
+ close: '\uF00D'
+ });
+ if (config) {
+ $.extend($.colorbox.settings, config);
+ }
+
+ // Trigger an event when we click on an (any) image
+ $('body').on('click', 'a.gallery', function () {
+ // Enable colorbox for images
+ $('a[type^=image].gallery').colorbox({
+ photo: true,
+ maxWidth: '95%',
+ maxHeight: '95%',
+ rel: 'gallery', // Turn all images on the page into a slideshow
+ slideshow: true,
+ slideshowAuto: false,
+ // Add wheelzoom to the displayed image
+ onComplete: function onComplete() {
+ // Disable click on image triggering next image
+ // https://github.com/jackmoore/colorbox/issues/668
+ $('.cboxPhoto').unbind('click');
+
+ wheelzoom(document.querySelectorAll('.cboxPhoto'));
+ }
+ });
+
+ // Enable colorbox for audio using <audio></audio>, where supported
+ // $('html.video a[type^=video].gallery').colorbox({
+ // rel: 'nofollow' // Slideshows are just for images
+ // });
+
+ // Enable colorbox for video using <video></video>, where supported
+ // $('html.audio a[type^=audio].gallery').colorbox({
+ // rel: 'nofollow', // Slideshows are just for images
+ // });
+
+ // Allow all other media types remain as download links
+ });
+}
+
+// Initialize autocomplete elements.
+function autocomplete(selector) {
+ // Use typeahead/bloodhound for autocomplete
+ $(selector).each(function () {
+ $(this).typeahead(null, {
+ display: 'value',
+ source: new Bloodhound({
+ datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
+ queryTokenizer: Bloodhound.tokenizers.whitespace,
+ remote: {
+ url: this.dataset.autocompleteUrl,
+ wildcard: 'QUERY'
+ }
+ })
+ });
+ });
+}
+
+/* Show / Hide event data for boxes used on charts and elsewhere */
+$('body').on('click', '.iconz', function (e) {
+ 'use strict';
+
+ e.stopPropagation();
+
+ var wrapper = $(this).closest('.person_box_template'),
+ inout = wrapper.find('.inout'),
+ inout2 = wrapper.find('.inout2'),
+ namedef = wrapper.find('.namedef'),
+ basestyle = wrapper.attr('class').match(/(box-style[0-2])/)[1];
+
+ function showDetails() {
+ wrapper.parent().css('z-index', 100);
+ toggleExpanded();
+ namedef.addClass('nameZoom');
+ inout2.hide(0, function () {
+ inout.slideDown();
+ });
+ }
+
+ function hideDetails() {
+ inout.slideUp(function () {
+ inout2.show(0);
+ namedef.removeClass('nameZoom');
+ toggleExpanded();
+ wrapper.parent().css('z-index', '');
+ });
+ }
+
+ function toggleExpanded() {
+ wrapper.toggleClass(function () {
+ return basestyle + ' ' + basestyle + '-expanded';
+ });
+ }
+
+ if (!inout.text().length) {
+ wrapper.css('cursor', 'progress');
+ inout.load('expand_view.php?pid=' + wrapper.data('pid'), function () {
+ wrapper.css('cursor', '');
+ showDetails();
+ });
+ } else {
+ if (wrapper.hasClass(basestyle)) {
+ showDetails();
+ } else {
+ hideDetails();
+ }
+ }
+ wrapper.find('.iconz').toggleClass('icon-zoomin icon-zoomout');
+});
+
+/**
+ * Insert text at the current cursor position in an input field.
+ *
+ * @param e The input element.
+ * @param t The text to insert.
+ */
+function insertTextAtCursor(e, t) {
+ var scrollTop = e.scrollTop;
+ var selectionStart = e.selectionStart;
+ var prefix = e.value.substring(0, selectionStart);
+ var suffix = e.value.substring(e.selectionEnd, e.value.length);
+ e.value = prefix + t + suffix;
+ e.selectionStart = selectionStart + t.length;
+ e.selectionEnd = e.selectionStart;
+ e.focus();
+ e.scrollTop = scrollTop;
+}
+
+// Initialisation
+$(function () {
+ // Send the CSRF token on all AJAX requests
+ $.ajaxSetup({
+ headers: {
+ 'X-CSRF-TOKEN': $('meta[name=csrf]').attr('content')
+ }
+ });
+
+ // Page elements that load automaticaly via AJAX.
+ // This prevents bad robots from crawling resource-intensive pages.
+ $("[data-ajax-url]").each(function () {
+ $(this).load($(this).data('ajaxUrl'));
+ });
+
+ // Bootstrap tabs - load content dynamically using AJAX
+ $('a[data-toggle="tab"][data-href]').on('show.bs.tab', function () {
+ $(this.getAttribute('href') + ':empty').load($(this).data('href'));
+ });
+
+ // Select2 - format entries in the select list
+ function templateOptionForSelect2(data) {
+ if (data.loading) {
+ // If we're waiting for the server, this will be a "waiting..." message
+ return data.text;
+ } else {
+ // The response from the server is already in HTML, so no need to format it here.
+ return data.text;
+ }
+ }
+
+ // Autocomplete
+ autocomplete('input[data-autocomplete-url]');
+
+ // Select2 - activate autocomplete fields
+ $('select.select2').select2({
+ // Do not escape.
+ escapeMarkup: function escapeMarkup(x) {
+ return x;
+ }
+ // Same formatting for both selections and rsult
+ //templateResult: templateOptionForSelect2,
+ //templateSelection: templateOptionForSelect2
+ });
+
+ // If we clear the select (using the "X" button), we need an empty
+ // value (rather than no value at all) for inputs with name="array[]"
+ $('select.select2').on('select2:unselect', function (evt) {
+ $(evt.delegateTarget).append('<option value="" selected="selected"></option>');
+ });
+
+ // Datatables - locale aware sorting
+ $.fn.dataTableExt.oSort['text-asc'] = function (x, y) {
+ return x.localeCompare(y, document.documentElement.lang, { 'sensitivity': 'base' });
+ };
+ $.fn.dataTableExt.oSort['text-desc'] = function (x, y) {
+ return y.localeCompare(x, document.documentElement.lang, { 'sensitivity': 'base' });
+ };
+
+ // DataTables - start hidden to prevent FOUC.
+ $('table.datatables').each(function () {
+ $(this).DataTable();$(this).show();
+ });
+
+ // Create a new record while editing an existing one.
+ // Paste the XREF and description into the Select2 element.
+ $('.wt-modal-create-record').on('show.bs.modal', function (event) {
+ // Find the element ID that needs to be updated with the new value.
+ $('form', $(this)).data('element-id', $(event.relatedTarget).data('element-id'));
+ $('form .form-group input:first', $(this)).focus();
+ });
+
+ // Submit the modal form using AJAX, and paste the returned record ID/NAME into the parent form.
+ $('.wt-modal-create-record form').on('submit', function (event) {
+ event.preventDefault();
+ var elementId = $(this).data('element-id');
+ $.ajax({
+ url: 'action.php',
+ type: 'POST',
+ data: new FormData(this),
+ async: false,
+ cache: false,
+ contentType: false,
+ processData: false,
+ success: function success(data) {
+ $('#' + elementId).select2().empty().append(new Option(data.text, data.id)).val(data.id).trigger('change');
+ },
+ failure: function failure(data) {
+ alert(data.error_message);
+ }
+ });
+ // Clear the form
+ this.reset();
+ // Close the modal
+ $(this).closest('.wt-modal-create-record').modal('hide');
+ });
+
+ // Activate the langauge selection menu.
+ $('.menu-language').on('click', '[data-language]', function () {
+ $.post('action.php', {
+ action: 'language',
+ language: $(this).data('language')
+ }, function () {
+ window.location.reload();
+ });
+
+ return false;
+ });
+
+ // Activate the theme selection menu.
+ $('.menu-theme').on('click', '[data-theme]', function () {
+ $.post('action.php', {
+ action: 'theme',
+ theme: $(this).data('theme')
+ }, function () {
+ window.location.reload();
+ });
+
+ return false;
+ });
+
+ // Activate the on-screen keyboard
+ var osk_focus_element;
+ $('.wt-osk-trigger').click(function () {
+ // When a user clicks the icon, set focus to the corresponding input
+ osk_focus_element = document.getElementById($(this).data('id'));
+ osk_focus_element.focus();
+ $('.wt-osk').show();
+ });
+ $(document).on('focusin', ':input', function () {
+ // When an element gains focus, remember it.
+ osk_focus_element = this;
+ });
+ $('.wt-osk-script-button').change(function () {
+ $('.wt-osk-script').prop('hidden', true);
+ $('.wt-osk-script-' + $(this).data('script')).prop('hidden', false);
+ });
+ $('.wt-osk-shift-button').click(function () {
+ document.querySelector('.wt-osk-keys').classList.toggle('shifted');
+ });
+ $('.wt-osk-keys').on('click', '.wt-osk-key', function () {
+ var key = $(this).contents().get(0).nodeValue;
+ var shift_state = $('.wt-osk-shift-button').hasClass('active');
+ var shift_key = $('sup', this)[0];
+ if (shift_state && shift_key !== undefined) {
+ key = shift_key.innerText;
+ }
+ if (osk_focus_element !== null) {
+ var cursorPos = osk_focus_element.selectionStart;
+ var v = osk_focus_element.value;
+ var textBefore = v.substring(0, cursorPos);
+ var textAfter = v.substring(cursorPos, v.length);
+ osk_focus_element.value = textBefore + key + textAfter;
+ if ($('.wt-osk-pin-button').hasClass('active') === false) {
+ $('.wt-osk').hide();
+ }
+ }
+ });
+}); \ No newline at end of file