Skip to content

Instantly share code, notes, and snippets.

@ceremcem
Created September 1, 2020 12:22
Show Gist options
  • Save ceremcem/f378161ac6a3c9a224567b6e06c7080c to your computer and use it in GitHub Desktop.
Save ceremcem/f378161ac6a3c9a224567b6e06c7080c to your computer and use it in GitHub Desktop.
template.ls bundled with Rollup (has a problem)
This file has been truncated, but you can view the full file.
'use strict';
var util = require('util');
var os = require('os');
var buffer = require('buffer');
var crypto = require('crypto');
var tty = require('tty');
var fs$1 = require('fs');
var net = require('net');
var ractive = require('ractive');
var path = require('path');
var preludeLs = require('prelude-ls');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
var buffer__default = /*#__PURE__*/_interopDefaultLegacy(buffer);
var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
var tty__default = /*#__PURE__*/_interopDefaultLegacy(tty);
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs$1);
var net__default = /*#__PURE__*/_interopDefaultLegacy(net);
var ractive__default = /*#__PURE__*/_interopDefaultLegacy(ractive);
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
var preludeLs__default = /*#__PURE__*/_interopDefaultLegacy(preludeLs);
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, basedir, module) {
return module = {
path: basedir,
exports: {},
require: function (path, base) {
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base);
}
}, fn(module, module.exports), module.exports;
}
function getCjsExportFromNamespace (n) {
return n && n['default'] || n;
}
function commonjsRequire () {
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs');
}
var styles_1 = createCommonjsModule(function (module) {
/*
The MIT License (MIT)
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
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 styles = {};
module['exports'] = styles;
var codes = {
reset: [0, 0],
bold: [1, 22],
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29],
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
gray: [90, 39],
grey: [90, 39],
brightRed: [91, 39],
brightGreen: [92, 39],
brightYellow: [93, 39],
brightBlue: [94, 39],
brightMagenta: [95, 39],
brightCyan: [96, 39],
brightWhite: [97, 39],
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49],
bgGray: [100, 49],
bgGrey: [100, 49],
bgBrightRed: [101, 49],
bgBrightGreen: [102, 49],
bgBrightYellow: [103, 49],
bgBrightBlue: [104, 49],
bgBrightMagenta: [105, 49],
bgBrightCyan: [106, 49],
bgBrightWhite: [107, 49],
// legacy styles for colors pre v1.0.0
blackBG: [40, 49],
redBG: [41, 49],
greenBG: [42, 49],
yellowBG: [43, 49],
blueBG: [44, 49],
magentaBG: [45, 49],
cyanBG: [46, 49],
whiteBG: [47, 49],
};
Object.keys(codes).forEach(function(key) {
var val = codes[key];
var style = styles[key] = [];
style.open = '\u001b[' + val[0] + 'm';
style.close = '\u001b[' + val[1] + 'm';
});
});
/*
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
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 hasFlag = function(flag, argv) {
argv = argv || process.argv;
var terminatorPos = argv.indexOf('--');
var prefix = /^-{1,2}/.test(flag) ? '' : '--';
var pos = argv.indexOf(prefix + flag);
return pos !== -1 && (terminatorPos === -1 ? true : pos < terminatorPos);
};
var env = process.env;
var forceColor = void 0;
if (hasFlag('no-color') || hasFlag('no-colors') || hasFlag('color=false')) {
forceColor = false;
} else if (hasFlag('color') || hasFlag('colors') || hasFlag('color=true')
|| hasFlag('color=always')) {
forceColor = true;
}
if ('FORCE_COLOR' in env) {
forceColor = env.FORCE_COLOR.length === 0
|| parseInt(env.FORCE_COLOR, 10) !== 0;
}
function translateLevel(level) {
if (level === 0) {
return false;
}
return {
level: level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3,
};
}
function supportsColor(stream) {
if (forceColor === false) {
return 0;
}
if (hasFlag('color=16m') || hasFlag('color=full')
|| hasFlag('color=truecolor')) {
return 3;
}
if (hasFlag('color=256')) {
return 2;
}
if (stream && !stream.isTTY && forceColor !== true) {
return 0;
}
var min = forceColor ? 1 : 0;
if (process.platform === 'win32') {
// Node.js 7.5.0 is the first version of Node.js to include a patch to
// libuv that enables 256 color output on Windows. Anything earlier and it
// won't work. However, here we target Node.js 8 at minimum as it is an LTS
// release, and Node.js 7 is not. Windows 10 build 10586 is the first
// Windows release that supports 256 colors. Windows 10 build 14931 is the
// first release that supports 16m/TrueColor.
var osRelease = os__default['default'].release().split('.');
if (Number(process.versions.node.split('.')[0]) >= 8
&& Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
return Number(osRelease[2]) >= 14931 ? 3 : 2;
}
return 1;
}
if ('CI' in env) {
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI'].some(function(sign) {
return sign in env;
}) || env.CI_NAME === 'codeship') {
return 1;
}
return min;
}
if ('TEAMCITY_VERSION' in env) {
return (/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0
);
}
if ('TERM_PROGRAM' in env) {
var version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
switch (env.TERM_PROGRAM) {
case 'iTerm.app':
return version >= 3 ? 3 : 2;
case 'Hyper':
return 3;
case 'Apple_Terminal':
return 2;
// No default
}
}
if (/-256(color)?$/i.test(env.TERM)) {
return 2;
}
if (/^screen|^xterm|^vt100|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
return 1;
}
if ('COLORTERM' in env) {
return 1;
}
if (env.TERM === 'dumb') {
return min;
}
return min;
}
function getSupportLevel(stream) {
var level = supportsColor(stream);
return translateLevel(level);
}
var supportsColors = {
supportsColor: getSupportLevel,
stdout: getSupportLevel(process.stdout),
stderr: getSupportLevel(process.stderr),
};
var trap = createCommonjsModule(function (module) {
module['exports'] = function runTheTrap(text, options) {
var result = '';
text = text || 'Run the trap, drop the bass';
text = text.split('');
var trap = {
a: ['\u0040', '\u0104', '\u023a', '\u0245', '\u0394', '\u039b', '\u0414'],
b: ['\u00df', '\u0181', '\u0243', '\u026e', '\u03b2', '\u0e3f'],
c: ['\u00a9', '\u023b', '\u03fe'],
d: ['\u00d0', '\u018a', '\u0500', '\u0501', '\u0502', '\u0503'],
e: ['\u00cb', '\u0115', '\u018e', '\u0258', '\u03a3', '\u03be', '\u04bc',
'\u0a6c'],
f: ['\u04fa'],
g: ['\u0262'],
h: ['\u0126', '\u0195', '\u04a2', '\u04ba', '\u04c7', '\u050a'],
i: ['\u0f0f'],
j: ['\u0134'],
k: ['\u0138', '\u04a0', '\u04c3', '\u051e'],
l: ['\u0139'],
m: ['\u028d', '\u04cd', '\u04ce', '\u0520', '\u0521', '\u0d69'],
n: ['\u00d1', '\u014b', '\u019d', '\u0376', '\u03a0', '\u048a'],
o: ['\u00d8', '\u00f5', '\u00f8', '\u01fe', '\u0298', '\u047a', '\u05dd',
'\u06dd', '\u0e4f'],
p: ['\u01f7', '\u048e'],
q: ['\u09cd'],
r: ['\u00ae', '\u01a6', '\u0210', '\u024c', '\u0280', '\u042f'],
s: ['\u00a7', '\u03de', '\u03df', '\u03e8'],
t: ['\u0141', '\u0166', '\u0373'],
u: ['\u01b1', '\u054d'],
v: ['\u05d8'],
w: ['\u0428', '\u0460', '\u047c', '\u0d70'],
x: ['\u04b2', '\u04fe', '\u04fc', '\u04fd'],
y: ['\u00a5', '\u04b0', '\u04cb'],
z: ['\u01b5', '\u0240'],
};
text.forEach(function(c) {
c = c.toLowerCase();
var chars = trap[c] || [' '];
var rand = Math.floor(Math.random() * chars.length);
if (typeof trap[c] !== 'undefined') {
result += trap[c][rand];
} else {
result += c;
}
});
return result;
};
});
var zalgo = createCommonjsModule(function (module) {
// please no
module['exports'] = function zalgo(text, options) {
text = text || ' he is here ';
var soul = {
'up': [
'̍', '̎', '̄', '̅',
'̿', '̑', '̆', '̐',
'͒', '͗', '͑', '̇',
'̈', '̊', '͂', '̓',
'̈', '͊', '͋', '͌',
'̃', '̂', '̌', '͐',
'̀', '́', '̋', '̏',
'̒', '̓', '̔', '̽',
'̉', 'ͣ', 'ͤ', 'ͥ',
'ͦ', 'ͧ', 'ͨ', 'ͩ',
'ͪ', 'ͫ', 'ͬ', 'ͭ',
'ͮ', 'ͯ', '̾', '͛',
'͆', '̚',
],
'down': [
'̖', '̗', '̘', '̙',
'̜', '̝', '̞', '̟',
'̠', '̤', '̥', '̦',
'̩', '̪', '̫', '̬',
'̭', '̮', '̯', '̰',
'̱', '̲', '̳', '̹',
'̺', '̻', '̼', 'ͅ',
'͇', '͈', '͉', '͍',
'͎', '͓', '͔', '͕',
'͖', '͙', '͚', '̣',
],
'mid': [
'̕', '̛', '̀', '́',
'͘', '̡', '̢', '̧',
'̨', '̴', '̵', '̶',
'͜', '͝', '͞',
'͟', '͠', '͢', '̸',
'̷', '͡', ' ҉',
],
};
var all = [].concat(soul.up, soul.down, soul.mid);
function randomNumber(range) {
var r = Math.floor(Math.random() * range);
return r;
}
function isChar(character) {
var bool = false;
all.filter(function(i) {
bool = (i === character);
});
return bool;
}
function heComes(text, options) {
var result = '';
var counts;
var l;
options = options || {};
options['up'] =
typeof options['up'] !== 'undefined' ? options['up'] : true;
options['mid'] =
typeof options['mid'] !== 'undefined' ? options['mid'] : true;
options['down'] =
typeof options['down'] !== 'undefined' ? options['down'] : true;
options['size'] =
typeof options['size'] !== 'undefined' ? options['size'] : 'maxi';
text = text.split('');
for (l in text) {
if (isChar(l)) {
continue;
}
result = result + text[l];
counts = {'up': 0, 'down': 0, 'mid': 0};
switch (options.size) {
case 'mini':
counts.up = randomNumber(8);
counts.mid = randomNumber(2);
counts.down = randomNumber(8);
break;
case 'maxi':
counts.up = randomNumber(16) + 3;
counts.mid = randomNumber(4) + 1;
counts.down = randomNumber(64) + 3;
break;
default:
counts.up = randomNumber(8) + 1;
counts.mid = randomNumber(6) / 2;
counts.down = randomNumber(8) + 1;
break;
}
var arr = ['up', 'mid', 'down'];
for (var d in arr) {
var index = arr[d];
for (var i = 0; i <= counts[index]; i++) {
if (options[index]) {
result = result + soul[index][randomNumber(soul[index].length)];
}
}
}
}
return result;
}
// don't summon him
return heComes(text, options);
};
});
var america = createCommonjsModule(function (module) {
module['exports'] = function(colors) {
return function(letter, i, exploded) {
if (letter === ' ') return letter;
switch (i%3) {
case 0: return colors.red(letter);
case 1: return colors.white(letter);
case 2: return colors.blue(letter);
}
};
};
});
var zebra = createCommonjsModule(function (module) {
module['exports'] = function(colors) {
return function(letter, i, exploded) {
return i % 2 === 0 ? letter : colors.inverse(letter);
};
};
});
var rainbow = createCommonjsModule(function (module) {
module['exports'] = function(colors) {
// RoY G BiV
var rainbowColors = ['red', 'yellow', 'green', 'blue', 'magenta'];
return function(letter, i, exploded) {
if (letter === ' ') {
return letter;
} else {
return colors[rainbowColors[i++ % rainbowColors.length]](letter);
}
};
};
});
var random = createCommonjsModule(function (module) {
module['exports'] = function(colors) {
var available = ['underline', 'inverse', 'grey', 'yellow', 'red', 'green',
'blue', 'white', 'cyan', 'magenta', 'brightYellow', 'brightRed',
'brightGreen', 'brightBlue', 'brightWhite', 'brightCyan', 'brightMagenta'];
return function(letter, i, exploded) {
return letter === ' ' ? letter :
colors[
available[Math.round(Math.random() * (available.length - 2))]
](letter);
};
};
});
var colors_1 = createCommonjsModule(function (module) {
/*
The MIT License (MIT)
Original Library
- Copyright (c) Marak Squires
Additional functionality
- Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
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 colors = {};
module['exports'] = colors;
colors.themes = {};
var ansiStyles = colors.styles = styles_1;
var defineProps = Object.defineProperties;
var newLineRegex = new RegExp(/[\r\n]+/g);
colors.supportsColor = supportsColors.supportsColor;
if (typeof colors.enabled === 'undefined') {
colors.enabled = colors.supportsColor() !== false;
}
colors.enable = function() {
colors.enabled = true;
};
colors.disable = function() {
colors.enabled = false;
};
colors.stripColors = colors.strip = function(str) {
return ('' + str).replace(/\x1B\[\d+m/g, '');
};
// eslint-disable-next-line no-unused-vars
var stylize = colors.stylize = function stylize(str, style) {
if (!colors.enabled) {
return str+'';
}
var styleMap = ansiStyles[style];
// Stylize should work for non-ANSI styles, too
if(!styleMap && style in colors){
// Style maps like trap operate as functions on strings;
// they don't have properties like open or close.
return colors[style](str);
}
return styleMap.open + str + styleMap.close;
};
var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
var escapeStringRegexp = function(str) {
if (typeof str !== 'string') {
throw new TypeError('Expected a string');
}
return str.replace(matchOperatorsRe, '\\$&');
};
function build(_styles) {
var builder = function builder() {
return applyStyle.apply(builder, arguments);
};
builder._styles = _styles;
// __proto__ is used because we must return a function, but there is
// no way to create a function with a different prototype.
builder.__proto__ = proto;
return builder;
}
var styles = (function() {
var ret = {};
ansiStyles.grey = ansiStyles.gray;
Object.keys(ansiStyles).forEach(function(key) {
ansiStyles[key].closeRe =
new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g');
ret[key] = {
get: function() {
return build(this._styles.concat(key));
},
};
});
return ret;
})();
var proto = defineProps(function colors() {}, styles);
function applyStyle() {
var args = Array.prototype.slice.call(arguments);
var str = args.map(function(arg) {
// Use weak equality check so we can colorize null/undefined in safe mode
if (arg != null && arg.constructor === String) {
return arg;
} else {
return util__default['default'].inspect(arg);
}
}).join(' ');
if (!colors.enabled || !str) {
return str;
}
var newLinesPresent = str.indexOf('\n') != -1;
var nestedStyles = this._styles;
var i = nestedStyles.length;
while (i--) {
var code = ansiStyles[nestedStyles[i]];
str = code.open + str.replace(code.closeRe, code.open) + code.close;
if (newLinesPresent) {
str = str.replace(newLineRegex, function(match) {
return code.close + match + code.open;
});
}
}
return str;
}
colors.setTheme = function(theme) {
if (typeof theme === 'string') {
console.log('colors.setTheme now only accepts an object, not a string. ' +
'If you are trying to set a theme from a file, it is now your (the ' +
'caller\'s) responsibility to require the file. The old syntax ' +
'looked like colors.setTheme(__dirname + ' +
'\'/../themes/generic-logging.js\'); The new syntax looks like '+
'colors.setTheme(require(__dirname + ' +
'\'/../themes/generic-logging.js\'));');
return;
}
for (var style in theme) {
(function(style) {
colors[style] = function(str) {
if (typeof theme[style] === 'object') {
var out = str;
for (var i in theme[style]) {
out = colors[theme[style][i]](out);
}
return out;
}
return colors[theme[style]](str);
};
})(style);
}
};
function init() {
var ret = {};
Object.keys(styles).forEach(function(name) {
ret[name] = {
get: function() {
return build([name]);
},
};
});
return ret;
}
var sequencer = function sequencer(map, str) {
var exploded = str.split('');
exploded = exploded.map(map);
return exploded.join('');
};
// custom formatter methods
colors.trap = trap;
colors.zalgo = zalgo;
// maps
colors.maps = {};
colors.maps.america = america(colors);
colors.maps.zebra = zebra(colors);
colors.maps.rainbow = rainbow(colors);
colors.maps.random = random(colors);
for (var map in colors.maps) {
(function(map) {
colors[map] = function(str) {
return sequencer(colors.maps[map], str);
};
})(map);
}
defineProps(colors, init());
});
var extendStringPrototype = createCommonjsModule(function (module) {
module['exports'] = function() {
//
// Extends prototype of native string object to allow for "foo".red syntax
//
var addProperty = function(color, func) {
String.prototype.__defineGetter__(color, func);
};
addProperty('strip', function() {
return colors_1.strip(this);
});
addProperty('stripColors', function() {
return colors_1.strip(this);
});
addProperty('trap', function() {
return colors_1.trap(this);
});
addProperty('zalgo', function() {
return colors_1.zalgo(this);
});
addProperty('zebra', function() {
return colors_1.zebra(this);
});
addProperty('rainbow', function() {
return colors_1.rainbow(this);
});
addProperty('random', function() {
return colors_1.random(this);
});
addProperty('america', function() {
return colors_1.america(this);
});
//
// Iterate through all default styles and colors
//
var x = Object.keys(colors_1.styles);
x.forEach(function(style) {
addProperty(style, function() {
return colors_1.stylize(this, style);
});
});
function applyTheme(theme) {
//
// Remark: This is a list of methods that exist
// on String that you should not overwrite.
//
var stringPrototypeBlacklist = [
'__defineGetter__', '__defineSetter__', '__lookupGetter__',
'__lookupSetter__', 'charAt', 'constructor', 'hasOwnProperty',
'isPrototypeOf', 'propertyIsEnumerable', 'toLocaleString', 'toString',
'valueOf', 'charCodeAt', 'indexOf', 'lastIndexOf', 'length',
'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice',
'split', 'substring', 'toLocaleLowerCase', 'toLocaleUpperCase',
'toLowerCase', 'toUpperCase', 'trim', 'trimLeft', 'trimRight',
];
Object.keys(theme).forEach(function(prop) {
if (stringPrototypeBlacklist.indexOf(prop) !== -1) {
console.log('warn: '.red + ('String.prototype' + prop).magenta +
' is probably something you don\'t want to override. ' +
'Ignoring style name');
} else {
if (typeof(theme[prop]) === 'string') {
colors_1[prop] = colors_1[theme[prop]];
addProperty(prop, function() {
return colors_1[prop](this);
});
} else {
var themePropApplicator = function(str) {
var ret = str || this;
for (var t = 0; t < theme[prop].length; t++) {
ret = colors_1[theme[prop][t]](ret);
}
return ret;
};
addProperty(prop, themePropApplicator);
colors_1[prop] = function(str) {
return themePropApplicator(str);
};
}
}
});
}
colors_1.setTheme = function(theme) {
if (typeof theme === 'string') {
console.log('colors.setTheme now only accepts an object, not a string. ' +
'If you are trying to set a theme from a file, it is now your (the ' +
'caller\'s) responsibility to require the file. The old syntax ' +
'looked like colors.setTheme(__dirname + ' +
'\'/../themes/generic-logging.js\'); The new syntax looks like '+
'colors.setTheme(require(__dirname + ' +
'\'/../themes/generic-logging.js\'));');
return;
} else {
applyTheme(theme);
}
};
};
});
var lib = createCommonjsModule(function (module) {
module['exports'] = colors_1;
// Remark: By default, colors will add style properties to String.prototype.
//
// If you don't wish to extend String.prototype, you can do this instead and
// native String will not be touched:
//
// var colors = require('colors/safe);
// colors.red("foo")
//
//
extendStringPrototype();
});
var moment = createCommonjsModule(function (module, exports) {
(function (global, factory) {
module.exports = factory() ;
}(commonjsGlobal, (function () {
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 hasOwnProp(a, b) {
return Object.prototype.hasOwnProperty.call(a, b);
}
function isObjectEmpty(obj) {
if (Object.getOwnPropertyNames) {
return Object.getOwnPropertyNames(obj).length === 0;
} else {
var k;
for (k in obj) {
if (hasOwnProp(obj, 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 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,
invalidEra: null,
invalidMonth: null,
invalidFormat: false,
userInvalidated: false,
iso: false,
parsedDateParts: [],
era: null,
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),
len = t.length >>> 0,
i;
for (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),
parsedParts = some.call(flags.parsedDateParts, function (i) {
return i != null;
}),
isNowValid =
!isNaN(m._d.getTime()) &&
flags.overflow < 0 &&
!flags.empty &&
!flags.invalidEra &&
!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 = []),
updateInProgress = false;
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;
}
// 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 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 = [],
arg,
i,
key;
for (i = 0; i < arguments.length; i++) {
arg = '';
if (typeof arguments[i] === 'object') {
arg += '\n[' + i + '] ';
for (key in arguments[0]) {
if (hasOwnProp(arguments[0], key)) {
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 (
(typeof Function !== 'undefined' && input instanceof Function) ||
Object.prototype.toString.call(input) === '[object Function]'
);
}
function set(config) {
var prop, i;
for (i in config) {
if (hasOwnProp(config, i)) {
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;
}
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?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,
localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
formatFunctions = {},
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 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
.match(formattingTokens)
.map(function (tok) {
if (
tok === 'MMMM' ||
tok === 'MM' ||
tok === 'DD' ||
tok === 'dddd'
) {
return tok.slice(1);
}
return tok;
})
.join('');
return this._longDateFormat[key];
}
var defaultInvalidDate = 'Invalid date';
function invalidDate() {
return this._invalidDate;
}
var defaultOrdinal = '%d',
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',
w: 'a week',
ww: '%d weeks',
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 = [],
u;
for (u in unitsObj) {
if (hasOwnProp(unitsObj, u)) {
units.push({ unit: u, priority: priorities[u] });
}
}
units.sort(function (a, b) {
return a.priority - b.priority;
});
return units;
}
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
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;
}
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
) {
value = toInt(value);
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),
i;
for (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;
}
var match1 = /\d/, // 0 - 9
match2 = /\d\d/, // 00 - 99
match3 = /\d{3}/, // 000 - 999
match4 = /\d{4}/, // 0000 - 9999
match6 = /[+-]?\d{6}/, // -999999 - 999999
match1to2 = /\d\d?/, // 0 - 99
match3to4 = /\d\d\d\d?/, // 999 - 9999
match5to6 = /\d\d\d\d\d\d?/, // 99999 - 999999
match1to3 = /\d{1,3}/, // 0 - 999
match1to4 = /\d{1,4}/, // 0 - 9999
match1to6 = /[+-]?\d{1,6}/, // -999999 - 999999
matchUnsigned = /\d+/, // 0 - inf
matchSigned = /[+-]?\d+/, // -inf - inf
matchOffset = /Z|[+-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi, // +00 -00 +00:00 -00:00 +0000 -0000 or Z
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
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,
regexes;
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,
MONTH = 1,
DATE = 2,
HOUR = 3,
MINUTE = 4,
SECOND = 5,
MILLISECOND = 6,
WEEK = 7,
WEEKDAY = 8;
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 defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split(
'_'
),
defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split(
'_'
),
MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,
defaultMonthsShortRegex = matchWord,
defaultMonthsRegex = matchWord;
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()];
}
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());
}
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;
}
}
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'
);
}
// FORMATTING
addFormatToken('Y', 0, 0, function () {
var y = this.year();
return y <= 9999 ? zeroFill(y, 4) : '+' + 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;
}
// 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 createDate(y, m, d, h, M, s, ms) {
// can't just apply() to create a date:
// https://stackoverflow.com/q/181348
var date;
// the date constructor remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
date = new Date(y + 400, m, d, h, M, s, ms);
if (isFinite(date.getFullYear())) {
date.setFullYear(y);
}
} else {
date = new Date(y, m, d, h, M, s, ms);
}
return date;
}
function createUTCDate(y) {
var date, args;
// the Date.UTC function remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
args = Array.prototype.slice.call(arguments);
// preserve leap years using a full 400 year cycle, then reset
args[0] = y + 400;
date = new Date(Date.UTC.apply(null, args));
if (isFinite(date.getUTCFullYear())) {
date.setUTCFullYear(y);
}
} else {
date = new Date(Date.UTC.apply(null, arguments));
}
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 6th 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
function shiftWeekdays(ws, n) {
return ws.slice(n, 7).concat(ws.slice(0, n));
}
var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split(
'_'
),
defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
defaultWeekdaysRegex = matchWord,
defaultWeekdaysShortRegex = matchWord,
defaultWeekdaysMinRegex = matchWord;
function localeWeekdays(m, format) {
var weekdays = isArray(this._weekdays)
? this._weekdays
: this._weekdays[
m && m !== true && this._weekdays.isFormat.test(format)
? 'format'
: 'standalone'
];
return m === true
? shiftWeekdays(weekdays, this._week.dow)
: m
? weekdays[m.day()]
: weekdays;
}
function localeWeekdaysShort(m) {
return m === true
? shiftWeekdays(this._weekdaysShort, this._week.dow)
: m
? this._weekdaysShort[m.day()]
: this._weekdaysShort;
}
function localeWeekdaysMin(m) {
return m === true
? shiftWeekdays(this._weekdaysMin, this._week.dow)
: 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;
}
}
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;
}
}
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;
}
}
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 = regexEscape(this.weekdaysMin(mom, ''));
shortp = regexEscape(this.weekdaysShort(mom, ''));
longp = regexEscape(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);
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,
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,
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,
// Setting the hour should keep the time, because the user explicitly
// specified which hour they want. So trying to maintain the same hour (in
// a new timezone) makes sense. Adding/subtracting hours does not follow
// this rule.
getSetHour = makeGetSet('Hours', true);
function localeMeridiem(hours, minutes, isLower) {
if (hours > 11) {
return isLower ? 'pm' : 'PM';
} else {
return isLower ? 'am' : 'AM';
}
}
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 = {},
localeFamilies = {},
globalLocale;
function commonPrefix(arr1, arr2) {
var i,
minl = Math.min(arr1.length, arr2.length);
for (i = 0; i < minl; i += 1) {
if (arr1[i] !== arr2[i]) {
return i;
}
}
return minl;
}
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 &&
commonPrefix(split, next) >= j - 1
) {
//the next array item is better than a shallower substring of this one
break;
}
j--;
}
i++;
}
return globalLocale;
}
function loadLocale(name) {
var oldLocale = null,
aliasedRequire;
// TODO: Find a better way to register and load all the locales in Node
if (
locales[name] === undefined &&
'object' !== 'undefined' &&
module &&
module.exports
) {
try {
oldLocale = globalLocale._abbr;
aliasedRequire = commonjsRequire;
aliasedRequire('./locale/' + name);
getSetGlobalLocale(oldLocale);
} catch (e) {
// mark as not found to avoid repeating expensive file require call causing high CPU
// when trying to find en-US, en_US, en-us for every format call
locales[name] = null; // null means not found
}
}
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;
} else {
if (typeof console !== 'undefined' && console.warn) {
//warn user if arguments are passed but the locale could not be set
console.warn(
'Locale ' + key + ' not found. Did you forget to load it?'
);
}
}
}
return globalLocale._abbr;
}
function defineLocale(name, config) {
if (config !== null) {
var locale,
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 {
locale = loadLocale(config.parentLocale);
if (locale != null) {
parentConfig = locale._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;
if (locales[name] != null && locales[name].parentLocale != null) {
// Update existing child locale in-place to avoid memory-leaks
locales[name].set(mergeConfigs(locales[name]._config, config));
} else {
// MERGE
tmpLocale = loadLocale(name);
if (tmpLocale != null) {
parentConfig = tmpLocale._config;
}
config = mergeConfigs(parentConfig, config);
if (tmpLocale == null) {
// updateLocale is called for creating a new locale
// Set abbr so it will have a name (getters return
// undefined otherwise).
config.abbr = name;
}
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;
if (name === getSetGlobalLocale()) {
getSetGlobalLocale(name);
}
} 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,
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;
}
// 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)?)?$/,
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)?)?$/,
tzRegex = /Z|[+-]\d\d(?::?\d\d)?/,
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}/],
['GGGG[W]WWE', /\d{4}W\d{3}/],
['GGGG[W]WW', /\d{4}W\d{2}/, false],
['YYYYDDD', /\d{7}/],
['YYYYMM', /\d{6}/, false],
['YYYY', /\d{4}/, false],
],
// iso time formats and regexes
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/],
],
aspNetJsonRegex = /^\/?Date\((-?\d+)/i,
// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
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}))$/,
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,
};
// 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;
}
}
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, ' ')
.replace(/^\s\s*/, '')
.replace(/\s\s*$/, '');
}
function checkWeekday(weekdayStr, parsedInput, config) {
if (weekdayStr) {
// TODO: Replace the vanilla JS Date object with an independent 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;
}
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),
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)),
parsedArray;
if (match) {
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 1) ASP.NET, 2) ISO, 3) RFC 2822 formats, or 4) optional fallback if parsing isn't strict
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;
}
if (config._strict) {
config._isValid = false;
} else {
// 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' : ''));
}
);
// 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, curWeek;
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;
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 beginning of week
weekday = w.e + dow;
if (w.e < 0 || w.e > 6) {
weekdayOverflow = true;
}
} else {
// default to beginning 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;
}
}
// 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,
era;
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];
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
);
// handle era
era = getParsingFlags(config).era;
if (era !== null) {
config._a[YEAR] = config._locale.erasConvertYear(era, config._a[YEAR]);
}
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,
validFormatFound,
bestFormatIsValid = false;
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;
validFormatFound = false;
tempConfig = copyConfig({}, config);
if (config._useUTC != null) {
tempConfig._useUTC = config._useUTC;
}
tempConfig._f = config._f[i];
configFromStringAndFormat(tempConfig);
if (isValid(tempConfig)) {
validFormatFound = true;
}
// 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 (!bestFormatIsValid) {
if (
scoreToBeat == null ||
currentScore < scoreToBeat ||
validFormatFound
) {
scoreToBeat = currentScore;
bestMoment = tempConfig;
if (validFormatFound) {
bestFormatIsValid = true;
}
}
} else {
if (currentScore < scoreToBeat) {
scoreToBeat = currentScore;
bestMoment = tempConfig;
}
}
}
extend(config, bestMoment || tempConfig);
}
function configFromObject(config) {
if (config._d) {
return;
}
var i = normalizeObjectUnits(config._i),
dayOrDate = i.day === undefined ? i.date : i.day;
config._a = map(
[i.year, i.month, dayOrDate, 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 (format === true || format === false) {
strict = format;
format = undefined;
}
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();
}
}
),
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) {
var key,
unitHasDecimal = false,
i;
for (key in m) {
if (
hasOwnProp(m, key) &&
!(
indexOf.call(ordering, key) !== -1 &&
(m[key] == null || !isNaN(m[key]))
)
) {
return false;
}
}
for (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 || normalizedInput.isoWeek || 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);
}
}
// 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;
}
// FORMATTING
function offset(token, separator) {
addFormatToken(token, 0, 0, function () {
var offset = this.utcOffset(),
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),
chunk,
parts,
minutes;
if (matches === null) {
return null;
}
chunk = matches[matches.length - 1] || [];
parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
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());
}
// 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 = {},
other;
copyConfig(c, this);
c = prepareConfig(c);
if (c._a) {
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
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) || !isNaN(+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 : 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;
}
if (isDuration(input) && hasOwnProp(input, '_isValid')) {
ret._isValid = input._isValid;
}
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 = {};
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;
}
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'),
subtract = createAdder(-1, 'subtract');
function isString(input) {
return typeof input === 'string' || input instanceof String;
}
// type MomentInput = Moment | Date | string | number | (number | string)[] | MomentInputObject | void; // null | undefined
function isMomentInput(input) {
return (
isMoment(input) ||
isDate(input) ||
isString(input) ||
isNumber(input) ||
isNumberOrStringArray(input) ||
isMomentInputObject(input) ||
input === null ||
input === undefined
);
}
function isMomentInputObject(input) {
var objectTest = isObject(input) && !isObjectEmpty(input),
propertyTest = false,
properties = [
'years',
'year',
'y',
'months',
'month',
'M',
'days',
'day',
'd',
'dates',
'date',
'D',
'hours',
'hour',
'h',
'minutes',
'minute',
'm',
'seconds',
'second',
's',
'milliseconds',
'millisecond',
'ms',
],
i,
property;
for (i = 0; i < properties.length; i += 1) {
property = properties[i];
propertyTest = propertyTest || hasOwnProp(input, property);
}
return objectTest && propertyTest;
}
function isNumberOrStringArray(input) {
var arrayTest = isArray(input),
dataTypeTest = false;
if (arrayTest) {
dataTypeTest =
input.filter(function (item) {
return !isNumber(item) && isString(input);
}).length === 0;
}
return arrayTest && dataTypeTest;
}
function isCalendarSpec(input) {
var objectTest = isObject(input) && !isObjectEmpty(input),
propertyTest = false,
properties = [
'sameDay',
'nextDay',
'lastDay',
'nextWeek',
'lastWeek',
'sameElse',
],
i,
property;
for (i = 0; i < properties.length; i += 1) {
property = properties[i];
propertyTest = propertyTest || hasOwnProp(input, property);
}
return objectTest && propertyTest;
}
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) {
// Support for single parameter, formats only overload to the calendar function
if (arguments.length === 1) {
if (isMomentInput(arguments[0])) {
time = arguments[0];
formats = undefined;
} else if (isCalendarSpec(arguments[0])) {
formats = arguments[0];
time = undefined;
}
}
// 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',
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(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(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) {
var localFrom = isMoment(from) ? from : createLocal(from),
localTo = isMoment(to) ? to : createLocal(to);
if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
return false;
}
inclusivity = inclusivity || '()';
return (
(inclusivity[0] === '('
? this.isAfter(localFrom, units)
: !this.isBefore(localFrom, units)) &&
(inclusivity[1] === ')'
? this.isBefore(localTo, units)
: !this.isAfter(localTo, 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, 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) {
if (a.date() < b.date()) {
// end-of-month calculations work correct when the start month has more
// days than the end month.
return -monthDiff(b, a);
}
// 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,
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.valueOf() + this.utcOffset() * 60 * 1000)
.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',
zone = '',
prefix,
year,
datetime,
suffix;
if (!this.isLocal()) {
func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
zone = 'Z';
}
prefix = '[' + func + '("]';
year = 0 <= this.year() && this.year() <= 9999 ? 'YYYY' : 'YYYYYY';
datetime = '-MM-DD[T]HH:mm:ss.SSS';
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;
}
var MS_PER_SECOND = 1000,
MS_PER_MINUTE = 60 * MS_PER_SECOND,
MS_PER_HOUR = 60 * MS_PER_MINUTE,
MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
// actual modulo - handles negative numbers (for dates before 1970):
function mod$1(dividend, divisor) {
return ((dividend % divisor) + divisor) % divisor;
}
function localStartOfDate(y, m, d) {
// the date constructor remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
return new Date(y + 400, m, d) - MS_PER_400_YEARS;
} else {
return new Date(y, m, d).valueOf();
}
}
function utcStartOfDate(y, m, d) {
// Date.UTC remaps years 0-99 to 1900-1999
if (y < 100 && y >= 0) {
// preserve leap years using a full 400 year cycle, then reset
return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
} else {
return Date.UTC(y, m, d);
}
}
function startOf(units) {
var time, startOfDate;
units = normalizeUnits(units);
if (units === undefined || units === 'millisecond' || !this.isValid()) {
return this;
}
startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
switch (units) {
case 'year':
time = startOfDate(this.year(), 0, 1);
break;
case 'quarter':
time = startOfDate(
this.year(),
this.month() - (this.month() % 3),
1
);
break;
case 'month':
time = startOfDate(this.year(), this.month(), 1);
break;
case 'week':
time = startOfDate(
this.year(),
this.month(),
this.date() - this.weekday()
);
break;
case 'isoWeek':
time = startOfDate(
this.year(),
this.month(),
this.date() - (this.isoWeekday() - 1)
);
break;
case 'day':
case 'date':
time = startOfDate(this.year(), this.month(), this.date());
break;
case 'hour':
time = this._d.valueOf();
time -= mod$1(
time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
MS_PER_HOUR
);
break;
case 'minute':
time = this._d.valueOf();
time -= mod$1(time, MS_PER_MINUTE);
break;
case 'second':
time = this._d.valueOf();
time -= mod$1(time, MS_PER_SECOND);
break;
}
this._d.setTime(time);
hooks.updateOffset(this, true);
return this;
}
function endOf(units) {
var time, startOfDate;
units = normalizeUnits(units);
if (units === undefined || units === 'millisecond' || !this.isValid()) {
return this;
}
startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
switch (units) {
case 'year':
time = startOfDate(this.year() + 1, 0, 1) - 1;
break;
case 'quarter':
time =
startOfDate(
this.year(),
this.month() - (this.month() % 3) + 3,
1
) - 1;
break;
case 'month':
time = startOfDate(this.year(), this.month() + 1, 1) - 1;
break;
case 'week':
time =
startOfDate(
this.year(),
this.month(),
this.date() - this.weekday() + 7
) - 1;
break;
case 'isoWeek':
time =
startOfDate(
this.year(),
this.month(),
this.date() - (this.isoWeekday() - 1) + 7
) - 1;
break;
case 'day':
case 'date':
time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
break;
case 'hour':
time = this._d.valueOf();
time +=
MS_PER_HOUR -
mod$1(
time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE),
MS_PER_HOUR
) -
1;
break;
case 'minute':
time = this._d.valueOf();
time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
break;
case 'second':
time = this._d.valueOf();
time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
break;
}
this._d.setTime(time);
hooks.updateOffset(this, true);
return this;
}
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,
};
}
addFormatToken('N', 0, 0, 'eraAbbr');
addFormatToken('NN', 0, 0, 'eraAbbr');
addFormatToken('NNN', 0, 0, 'eraAbbr');
addFormatToken('NNNN', 0, 0, 'eraName');
addFormatToken('NNNNN', 0, 0, 'eraNarrow');
addFormatToken('y', ['y', 1], 'yo', 'eraYear');
addFormatToken('y', ['yy', 2], 0, 'eraYear');
addFormatToken('y', ['yyy', 3], 0, 'eraYear');
addFormatToken('y', ['yyyy', 4], 0, 'eraYear');
addRegexToken('N', matchEraAbbr);
addRegexToken('NN', matchEraAbbr);
addRegexToken('NNN', matchEraAbbr);
addRegexToken('NNNN', matchEraName);
addRegexToken('NNNNN', matchEraNarrow);
addParseToken(['N', 'NN', 'NNN', 'NNNN', 'NNNNN'], function (
input,
array,
config,
token
) {
var era = config._locale.erasParse(input, token, config._strict);
if (era) {
getParsingFlags(config).era = era;
} else {
getParsingFlags(config).invalidEra = input;
}
});
addRegexToken('y', matchUnsigned);
addRegexToken('yy', matchUnsigned);
addRegexToken('yyy', matchUnsigned);
addRegexToken('yyyy', matchUnsigned);
addRegexToken('yo', matchEraYearOrdinal);
addParseToken(['y', 'yy', 'yyy', 'yyyy'], YEAR);
addParseToken(['yo'], function (input, array, config, token) {
var match;
if (config._locale._eraYearOrdinalRegex) {
match = input.match(config._locale._eraYearOrdinalRegex);
}
if (config._locale.eraYearOrdinalParse) {
array[YEAR] = config._locale.eraYearOrdinalParse(input, match);
} else {
array[YEAR] = parseInt(input, 10);
}
});
function localeEras(m, format) {
var i,
l,
date,
eras = this._eras || getLocale('en')._eras;
for (i = 0, l = eras.length; i < l; ++i) {
switch (typeof eras[i].since) {
case 'string':
// truncate time
date = hooks(eras[i].since).startOf('day');
eras[i].since = date.valueOf();
break;
}
switch (typeof eras[i].until) {
case 'undefined':
eras[i].until = +Infinity;
break;
case 'string':
// truncate time
date = hooks(eras[i].until).startOf('day').valueOf();
eras[i].until = date.valueOf();
break;
}
}
return eras;
}
function localeErasParse(eraName, format, strict) {
var i,
l,
eras = this.eras(),
name,
abbr,
narrow;
eraName = eraName.toUpperCase();
for (i = 0, l = eras.length; i < l; ++i) {
name = eras[i].name.toUpperCase();
abbr = eras[i].abbr.toUpperCase();
narrow = eras[i].narrow.toUpperCase();
if (strict) {
switch (format) {
case 'N':
case 'NN':
case 'NNN':
if (abbr === eraName) {
return eras[i];
}
break;
case 'NNNN':
if (name === eraName) {
return eras[i];
}
break;
case 'NNNNN':
if (narrow === eraName) {
return eras[i];
}
break;
}
} else if ([name, abbr, narrow].indexOf(eraName) >= 0) {
return eras[i];
}
}
}
function localeErasConvertYear(era, year) {
var dir = era.since <= era.until ? +1 : -1;
if (year === undefined) {
return hooks(era.since).year();
} else {
return hooks(era.since).year() + (year - era.offset) * dir;
}
}
function getEraName() {
var i,
l,
val,
eras = this.localeData().eras();
for (i = 0, l = eras.length; i < l; ++i) {
// truncate time
val = this.startOf('day').valueOf();
if (eras[i].since <= val && val <= eras[i].until) {
return eras[i].name;
}
if (eras[i].until <= val && val <= eras[i].since) {
return eras[i].name;
}
}
return '';
}
function getEraNarrow() {
var i,
l,
val,
eras = this.localeData().eras();
for (i = 0, l = eras.length; i < l; ++i) {
// truncate time
val = this.startOf('day').valueOf();
if (eras[i].since <= val && val <= eras[i].until) {
return eras[i].narrow;
}
if (eras[i].until <= val && val <= eras[i].since) {
return eras[i].narrow;
}
}
return '';
}
function getEraAbbr() {
var i,
l,
val,
eras = this.localeData().eras();
for (i = 0, l = eras.length; i < l; ++i) {
// truncate time
val = this.startOf('day').valueOf();
if (eras[i].since <= val && val <= eras[i].until) {
return eras[i].abbr;
}
if (eras[i].until <= val && val <= eras[i].since) {
return eras[i].abbr;
}
}
return '';
}
function getEraYear() {
var i,
l,
dir,
val,
eras = this.localeData().eras();
for (i = 0, l = eras.length; i < l; ++i) {
dir = eras[i].since <= eras[i].until ? +1 : -1;
// truncate time
val = this.startOf('day').valueOf();
if (
(eras[i].since <= val && val <= eras[i].until) ||
(eras[i].until <= val && val <= eras[i].since)
) {
return (
(this.year() - hooks(eras[i].since).year()) * dir +
eras[i].offset
);
}
}
return this.year();
}
function erasNameRegex(isStrict) {
if (!hasOwnProp(this, '_erasNameRegex')) {
computeErasParse.call(this);
}
return isStrict ? this._erasNameRegex : this._erasRegex;
}
function erasAbbrRegex(isStrict) {
if (!hasOwnProp(this, '_erasAbbrRegex')) {
computeErasParse.call(this);
}
return isStrict ? this._erasAbbrRegex : this._erasRegex;
}
function erasNarrowRegex(isStrict) {
if (!hasOwnProp(this, '_erasNarrowRegex')) {
computeErasParse.call(this);
}
return isStrict ? this._erasNarrowRegex : this._erasRegex;
}
function matchEraAbbr(isStrict, locale) {
return locale.erasAbbrRegex(isStrict);
}
function matchEraName(isStrict, locale) {
return locale.erasNameRegex(isStrict);
}
function matchEraNarrow(isStrict, locale) {
return locale.erasNarrowRegex(isStrict);
}
function matchEraYearOrdinal(isStrict, locale) {
return locale._eraYearOrdinalRegex || matchUnsigned;
}
function computeErasParse() {
var abbrPieces = [],
namePieces = [],
narrowPieces = [],
mixedPieces = [],
i,
l,
eras = this.eras();
for (i = 0, l = eras.length; i < l; ++i) {
namePieces.push(regexEscape(eras[i].name));
abbrPieces.push(regexEscape(eras[i].abbr));
narrowPieces.push(regexEscape(eras[i].narrow));
mixedPieces.push(regexEscape(eras[i].name));
mixedPieces.push(regexEscape(eras[i].abbr));
mixedPieces.push(regexEscape(eras[i].narrow));
}
this._erasRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
this._erasNameRegex = new RegExp('^(' + namePieces.join('|') + ')', 'i');
this._erasAbbrRegex = new RegExp('^(' + abbrPieces.join('|') + ')', 'i');
this._erasNarrowRegex = new RegExp(
'^(' + narrowPieces.join('|') + ')',
'i'
);
}
// 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 getISOWeeksInISOWeekYear() {
return weeksInYear(this.isoWeekYear(), 1, 4);
}
function getWeeksInYear() {
var weekInfo = this.localeData()._week;
return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
}
function getWeeksInWeekYear() {
var weekInfo = this.localeData()._week;
return weeksInYear(this.weekYear(), 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');
// PRIORITY
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, getSetMillisecond;
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);
}
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;
if (typeof Symbol !== 'undefined' && Symbol.for != null) {
proto[Symbol.for('nodejs.util.inspect.custom')] = function () {
return 'Moment<' + this.format() + '>';
};
}
proto.toJSON = toJSON;
proto.toString = toString;
proto.unix = unix;
proto.valueOf = valueOf;
proto.creationData = creationData;
proto.eraName = getEraName;
proto.eraNarrow = getEraNarrow;
proto.eraAbbr = getEraAbbr;
proto.eraYear = getEraYear;
proto.year = getSetYear;
proto.isLeapYear = getIsLeapYear;
proto.weekYear = getSetWeekYear;
proto.isoWeekYear = getSetISOWeekYear;
proto.quarter = proto.quarters = getSetQuarter;
proto.month = getSetMonth;
proto.daysInMonth = getDaysInMonth;
proto.week = proto.weeks = getSetWeek;
proto.isoWeek = proto.isoWeeks = getSetISOWeek;
proto.weeksInYear = getWeeksInYear;
proto.weeksInWeekYear = getWeeksInWeekYear;
proto.isoWeeksInYear = getISOWeeksInYear;
proto.isoWeeksInISOWeekYear = getISOWeeksInISOWeekYear;
proto.date = getSetDayOfMonth;
proto.day = proto.days = getSetDayOfWeek;
proto.weekday = getSetLocaleDayOfWeek;
proto.isoWeekday = getSetISODayOfWeek;
proto.dayOfYear = getSetDayOfYear;
proto.hour = proto.hours = getSetHour;
proto.minute = proto.minutes = getSetMinute;
proto.second = proto.seconds = getSetSecond;
proto.millisecond = proto.milliseconds = getSetMillisecond;
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;
proto.zoneAbbr = getZoneAbbr;
proto.zoneName = getZoneName;
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;
proto$1.eras = localeEras;
proto$1.erasParse = localeErasParse;
proto$1.erasConvertYear = localeErasConvertYear;
proto$1.erasAbbrRegex = erasAbbrRegex;
proto$1.erasNameRegex = erasNameRegex;
proto$1.erasNarrowRegex = erasNarrowRegex;
proto$1.months = localeMonths;
proto$1.monthsShort = localeMonthsShort;
proto$1.monthsParse = localeMonthsParse;
proto$1.monthsRegex = monthsRegex;
proto$1.monthsShortRegex = monthsShortRegex;
proto$1.week = localeWeek;
proto$1.firstDayOfYear = localeFirstDayOfYear;
proto$1.firstDayOfWeek = localeFirstDayOfWeek;
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;
proto$1.isPM = localeIsPM;
proto$1.meridiem = localeMeridiem;
function get$1(format, index, field, setter) {
var locale = getLocale(),
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,
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,
i,
out = [];
if (index != null) {
return get$1(format, (index + shift) % 7, field, 'day');
}
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', {
eras: [
{
since: '0001-01-01',
until: +Infinity,
offset: 1,
name: 'Anno Domini',
narrow: 'AD',
abbr: 'AD',
},
{
since: '0000-12-31',
until: -Infinity,
offset: 1,
name: 'Before Christ',
narrow: 'BC',
abbr: 'BC',
},
],
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,
days = this._days,
months = this._months,
data = this._data,
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,
months,
milliseconds = this._milliseconds;
units = normalizeUnits(units);
if (units === 'month' || units === 'quarter' || units === 'year') {
days = this._days + milliseconds / 864e5;
months = this._months + daysToMonths(days);
switch (units) {
case 'month':
return months;
case 'quarter':
return months / 3;
case 'year':
return 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'),
asSeconds = makeAs('s'),
asMinutes = makeAs('m'),
asHours = makeAs('h'),
asDays = makeAs('d'),
asWeeks = makeAs('w'),
asMonths = makeAs('M'),
asQuarters = makeAs('Q'),
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'),
seconds = makeGetter('seconds'),
minutes = makeGetter('minutes'),
hours = makeGetter('hours'),
days = makeGetter('days'),
months = makeGetter('months'),
years = makeGetter('years');
function weeks() {
return absFloor(this.days() / 7);
}
var round = Math.round,
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/week
w: null, // weeks 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, thresholds, locale) {
var duration = createDuration(posNegDuration).abs(),
seconds = round(duration.as('s')),
minutes = round(duration.as('m')),
hours = round(duration.as('h')),
days = round(duration.as('d')),
months = round(duration.as('M')),
weeks = round(duration.as('w')),
years = round(duration.as('y')),
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]);
if (thresholds.w != null) {
a =
a ||
(weeks <= 1 && ['w']) ||
(weeks < thresholds.w && ['ww', weeks]);
}
a = a ||
(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(argWithSuffix, argThresholds) {
if (!this.isValid()) {
return this.localeData().invalidDate();
}
var withSuffix = false,
th = thresholds,
locale,
output;
if (typeof argWithSuffix === 'object') {
argThresholds = argWithSuffix;
argWithSuffix = false;
}
if (typeof argWithSuffix === 'boolean') {
withSuffix = argWithSuffix;
}
if (typeof argThresholds === 'object') {
th = Object.assign({}, thresholds, argThresholds);
if (argThresholds.s != null && argThresholds.ss == null) {
th.ss = argThresholds.s - 1;
}
}
locale = this.localeData();
output = relativeTime$1(this, !withSuffix, th, 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,
days = abs$1(this._days),
months = abs$1(this._months),
minutes,
hours,
years,
s,
total = this.asSeconds(),
totalSign,
ymSign,
daysSign,
hmsSign;
if (!total) {
// this is the same as C#'s (Noda) and python (isodate)...
// but not other JS (goog.date)
return 'P0D';
}
// 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
s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
totalSign = total < 0 ? '-' : '';
ymSign = sign(this._months) !== sign(total) ? '-' : '';
daysSign = sign(this._days) !== sign(total) ? '-' : '';
hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
return (
totalSign +
'P' +
(years ? ymSign + years + 'Y' : '') +
(months ? ymSign + months + 'M' : '') +
(days ? daysSign + days + 'D' : '') +
(hours || minutes || seconds ? 'T' : '') +
(hours ? hmsSign + hours + 'H' : '') +
(minutes ? hmsSign + minutes + 'M' : '') +
(seconds ? 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.asQuarters = asQuarters;
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;
proto$2.toIsoString = deprecate(
'toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)',
toISOString$1
);
proto$2.lang = lang;
// 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) * 1000);
});
addParseToken('x', function (input, array, config) {
config._d = new Date(toInt(input));
});
//! moment.js
hooks.version = '2.27.0';
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: 'GGGG-[W]WW', // <input type="week" />
MONTH: 'YYYY-MM', // <input type="month" />
};
return hooks;
})));
});
// Generated by LiveScript 1.6.0
var apply, curry, flip, fix, over, memoize, toString$ = {}.toString;
apply = curry$(function(f, list){
return f.apply(null, list);
});
curry = function(f){
return curry$(f);
};
flip = curry$(function(f, x, y){
return f(y, x);
});
fix = function(f){
return function(g){
return function(){
return f(g(g)).apply(null, arguments);
};
}(function(g){
return function(){
return f(g(g)).apply(null, arguments);
};
});
};
over = curry$(function(f, g, x, y){
return f(g(x), g(y));
});
memoize = function(f){
var memo;
memo = {};
return function(){
var args, res$, i$, to$, key, arg;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
key = (function(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = args).length; i$ < len$; ++i$) {
arg = ref$[i$];
results$.push(arg + toString$.call(arg).slice(8, -1));
}
return results$;
}()).join('');
return memo[key] = key in memo
? memo[key]
: f.apply(null, args);
};
};
var Func = {
curry: curry,
flip: flip,
fix: fix,
apply: apply,
over: over,
memoize: memoize
};
function curry$(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
// Generated by LiveScript 1.6.0
var each, map, compact, filter, reject, remove, partition, find, head, first, tail, last, initial, empty, reverse, unique, uniqueBy, fold, foldl, fold1, foldl1, foldr, foldr1, unfoldr, concat, concatMap, flatten, difference, intersection, union, countBy, groupBy, andList, orList, any, all, sort, sortWith, sortBy, sum, product, mean, average, maximum, minimum, maximumBy, minimumBy, scan, scanl, scan1, scanl1, scanr, scanr1, slice, take, drop, splitAt, takeWhile, dropWhile, span, breakList, zip, zipWith, zipAll, zipAllWith, at, elemIndex, elemIndices, findIndex, findIndices, toString$$1 = {}.toString;
each = curry$$1(function(f, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
f(x);
}
return xs;
});
map = curry$$1(function(f, xs){
var i$, len$, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
results$.push(f(x));
}
return results$;
});
compact = function(xs){
var i$, len$, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (x) {
results$.push(x);
}
}
return results$;
};
filter = curry$$1(function(f, xs){
var i$, len$, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (f(x)) {
results$.push(x);
}
}
return results$;
});
reject = curry$$1(function(f, xs){
var i$, len$, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (!f(x)) {
results$.push(x);
}
}
return results$;
});
remove = curry$$1(function(el, xs){
var i, x$;
i = elemIndex(el, xs);
x$ = xs.slice();
if (i != null) {
x$.splice(i, 1);
}
return x$;
});
partition = curry$$1(function(f, xs){
var passed, failed, i$, len$, x;
passed = [];
failed = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
(f(x) ? passed : failed).push(x);
}
return [passed, failed];
});
find = curry$$1(function(f, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (f(x)) {
return x;
}
}
});
head = first = function(xs){
return xs[0];
};
tail = function(xs){
if (!xs.length) {
return;
}
return xs.slice(1);
};
last = function(xs){
return xs[xs.length - 1];
};
initial = function(xs){
if (!xs.length) {
return;
}
return xs.slice(0, -1);
};
empty = function(xs){
return !xs.length;
};
reverse = function(xs){
return xs.concat().reverse();
};
unique = function(xs){
var result, i$, len$, x;
result = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (!in$(x, result)) {
result.push(x);
}
}
return result;
};
uniqueBy = curry$$1(function(f, xs){
var seen, i$, len$, x, val, results$ = [];
seen = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
val = f(x);
if (in$(val, seen)) {
continue;
}
seen.push(val);
results$.push(x);
}
return results$;
});
fold = foldl = curry$$1(function(f, memo, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
memo = f(memo, x);
}
return memo;
});
fold1 = foldl1 = curry$$1(function(f, xs){
return fold(f, xs[0], xs.slice(1));
});
foldr = curry$$1(function(f, memo, xs){
var i$, x;
for (i$ = xs.length - 1; i$ >= 0; --i$) {
x = xs[i$];
memo = f(x, memo);
}
return memo;
});
foldr1 = curry$$1(function(f, xs){
return foldr(f, xs[xs.length - 1], xs.slice(0, -1));
});
unfoldr = curry$$1(function(f, b){
var result, x, that;
result = [];
x = b;
while ((that = f(x)) != null) {
result.push(that[0]);
x = that[1];
}
return result;
});
concat = function(xss){
return [].concat.apply([], xss);
};
concatMap = curry$$1(function(f, xs){
var x;
return [].concat.apply([], (function(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
x = ref$[i$];
results$.push(f(x));
}
return results$;
}()));
});
flatten = function(xs){
var x;
return [].concat.apply([], (function(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
x = ref$[i$];
if (toString$$1.call(x).slice(8, -1) === 'Array') {
results$.push(flatten(x));
} else {
results$.push(x);
}
}
return results$;
}()));
};
difference = function(xs){
var yss, res$, i$, to$, results, len$, x, j$, len1$, ys;
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
yss = res$;
results = [];
outer: for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
for (j$ = 0, len1$ = yss.length; j$ < len1$; ++j$) {
ys = yss[j$];
if (in$(x, ys)) {
continue outer;
}
}
results.push(x);
}
return results;
};
intersection = function(xs){
var yss, res$, i$, to$, results, len$, x, j$, len1$, ys;
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
yss = res$;
results = [];
outer: for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
for (j$ = 0, len1$ = yss.length; j$ < len1$; ++j$) {
ys = yss[j$];
if (!in$(x, ys)) {
continue outer;
}
}
results.push(x);
}
return results;
};
union = function(){
var xss, res$, i$, to$, results, len$, xs, j$, len1$, x;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
xss = res$;
results = [];
for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
xs = xss[i$];
for (j$ = 0, len1$ = xs.length; j$ < len1$; ++j$) {
x = xs[j$];
if (!in$(x, results)) {
results.push(x);
}
}
}
return results;
};
countBy = curry$$1(function(f, xs){
var results, i$, len$, x, key;
results = {};
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
key = f(x);
if (key in results) {
results[key] += 1;
} else {
results[key] = 1;
}
}
return results;
});
groupBy = curry$$1(function(f, xs){
var results, i$, len$, x, key;
results = {};
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
key = f(x);
if (key in results) {
results[key].push(x);
} else {
results[key] = [x];
}
}
return results;
});
andList = function(xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (!x) {
return false;
}
}
return true;
};
orList = function(xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (x) {
return true;
}
}
return false;
};
any = curry$$1(function(f, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (f(x)) {
return true;
}
}
return false;
});
all = curry$$1(function(f, xs){
var i$, len$, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
if (!f(x)) {
return false;
}
}
return true;
});
sort = function(xs){
return xs.concat().sort(function(x, y){
if (x > y) {
return 1;
} else if (x < y) {
return -1;
} else {
return 0;
}
});
};
sortWith = curry$$1(function(f, xs){
return xs.concat().sort(f);
});
sortBy = curry$$1(function(f, xs){
return xs.concat().sort(function(x, y){
if (f(x) > f(y)) {
return 1;
} else if (f(x) < f(y)) {
return -1;
} else {
return 0;
}
});
});
sum = function(xs){
var result, i$, len$, x;
result = 0;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
result += x;
}
return result;
};
product = function(xs){
var result, i$, len$, x;
result = 1;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
result *= x;
}
return result;
};
mean = average = function(xs){
var sum, i$, len$, x;
sum = 0;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
x = xs[i$];
sum += x;
}
return sum / xs.length;
};
maximum = function(xs){
var max, i$, ref$, len$, x;
max = xs[0];
for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
x = ref$[i$];
if (x > max) {
max = x;
}
}
return max;
};
minimum = function(xs){
var min, i$, ref$, len$, x;
min = xs[0];
for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
x = ref$[i$];
if (x < min) {
min = x;
}
}
return min;
};
maximumBy = curry$$1(function(f, xs){
var max, i$, ref$, len$, x;
max = xs[0];
for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
x = ref$[i$];
if (f(x) > f(max)) {
max = x;
}
}
return max;
});
minimumBy = curry$$1(function(f, xs){
var min, i$, ref$, len$, x;
min = xs[0];
for (i$ = 0, len$ = (ref$ = xs.slice(1)).length; i$ < len$; ++i$) {
x = ref$[i$];
if (f(x) < f(min)) {
min = x;
}
}
return min;
});
scan = scanl = curry$$1(function(f, memo, xs){
var last, x;
last = memo;
return [memo].concat((function(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = xs).length; i$ < len$; ++i$) {
x = ref$[i$];
results$.push(last = f(last, x));
}
return results$;
}()));
});
scan1 = scanl1 = curry$$1(function(f, xs){
if (!xs.length) {
return;
}
return scan(f, xs[0], xs.slice(1));
});
scanr = curry$$1(function(f, memo, xs){
xs = xs.concat().reverse();
return scan(f, memo, xs).reverse();
});
scanr1 = curry$$1(function(f, xs){
if (!xs.length) {
return;
}
xs = xs.concat().reverse();
return scan(f, xs[0], xs.slice(1)).reverse();
});
slice = curry$$1(function(x, y, xs){
return xs.slice(x, y);
});
take = curry$$1(function(n, xs){
if (n <= 0) {
return xs.slice(0, 0);
} else {
return xs.slice(0, n);
}
});
drop = curry$$1(function(n, xs){
if (n <= 0) {
return xs;
} else {
return xs.slice(n);
}
});
splitAt = curry$$1(function(n, xs){
return [take(n, xs), drop(n, xs)];
});
takeWhile = curry$$1(function(p, xs){
var len, i;
len = xs.length;
if (!len) {
return xs;
}
i = 0;
while (i < len && p(xs[i])) {
i += 1;
}
return xs.slice(0, i);
});
dropWhile = curry$$1(function(p, xs){
var len, i;
len = xs.length;
if (!len) {
return xs;
}
i = 0;
while (i < len && p(xs[i])) {
i += 1;
}
return xs.slice(i);
});
span = curry$$1(function(p, xs){
return [takeWhile(p, xs), dropWhile(p, xs)];
});
breakList = curry$$1(function(p, xs){
return span(compose$(p, not$), xs);
});
zip = curry$$1(function(xs, ys){
var result, len, i$, len$, i, x;
result = [];
len = ys.length;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (i === len) {
break;
}
result.push([x, ys[i]]);
}
return result;
});
zipWith = curry$$1(function(f, xs, ys){
var result, len, i$, len$, i, x;
result = [];
len = ys.length;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (i === len) {
break;
}
result.push(f(x, ys[i]));
}
return result;
});
zipAll = function(){
var xss, res$, i$, to$, minLength, len$, xs, ref$, i, lresult$, j$, results$ = [];
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
xss = res$;
minLength = undefined;
for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
xs = xss[i$];
minLength <= (ref$ = xs.length) || (minLength = ref$);
}
for (i$ = 0; i$ < minLength; ++i$) {
i = i$;
lresult$ = [];
for (j$ = 0, len$ = xss.length; j$ < len$; ++j$) {
xs = xss[j$];
lresult$.push(xs[i]);
}
results$.push(lresult$);
}
return results$;
};
zipAllWith = function(f){
var xss, res$, i$, to$, minLength, len$, xs, ref$, i, results$ = [];
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
xss = res$;
minLength = undefined;
for (i$ = 0, len$ = xss.length; i$ < len$; ++i$) {
xs = xss[i$];
minLength <= (ref$ = xs.length) || (minLength = ref$);
}
for (i$ = 0; i$ < minLength; ++i$) {
i = i$;
results$.push(f.apply(null, (fn$())));
}
return results$;
function fn$(){
var i$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = xss).length; i$ < len$; ++i$) {
xs = ref$[i$];
results$.push(xs[i]);
}
return results$;
}
};
at = curry$$1(function(n, xs){
if (n < 0) {
return xs[xs.length + n];
} else {
return xs[n];
}
});
elemIndex = curry$$1(function(el, xs){
var i$, len$, i, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (x === el) {
return i;
}
}
});
elemIndices = curry$$1(function(el, xs){
var i$, len$, i, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (x === el) {
results$.push(i);
}
}
return results$;
});
findIndex = curry$$1(function(f, xs){
var i$, len$, i, x;
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (f(x)) {
return i;
}
}
});
findIndices = curry$$1(function(f, xs){
var i$, len$, i, x, results$ = [];
for (i$ = 0, len$ = xs.length; i$ < len$; ++i$) {
i = i$;
x = xs[i$];
if (f(x)) {
results$.push(i);
}
}
return results$;
});
var List = {
each: each,
map: map,
filter: filter,
compact: compact,
reject: reject,
remove: remove,
partition: partition,
find: find,
head: head,
first: first,
tail: tail,
last: last,
initial: initial,
empty: empty,
reverse: reverse,
difference: difference,
intersection: intersection,
union: union,
countBy: countBy,
groupBy: groupBy,
fold: fold,
fold1: fold1,
foldl: foldl,
foldl1: foldl1,
foldr: foldr,
foldr1: foldr1,
unfoldr: unfoldr,
andList: andList,
orList: orList,
any: any,
all: all,
unique: unique,
uniqueBy: uniqueBy,
sort: sort,
sortWith: sortWith,
sortBy: sortBy,
sum: sum,
product: product,
mean: mean,
average: average,
concat: concat,
concatMap: concatMap,
flatten: flatten,
maximum: maximum,
minimum: minimum,
maximumBy: maximumBy,
minimumBy: minimumBy,
scan: scan,
scan1: scan1,
scanl: scanl,
scanl1: scanl1,
scanr: scanr,
scanr1: scanr1,
slice: slice,
take: take,
drop: drop,
splitAt: splitAt,
takeWhile: takeWhile,
dropWhile: dropWhile,
span: span,
breakList: breakList,
zip: zip,
zipWith: zipWith,
zipAll: zipAll,
zipAllWith: zipAllWith,
at: at,
elemIndex: elemIndex,
elemIndices: elemIndices,
findIndex: findIndex,
findIndices: findIndices
};
function curry$$1(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
function in$(x, xs){
var i = -1, l = xs.length >>> 0;
while (++i < l) if (x === xs[i]) return true;
return false;
}
function compose$() {
var functions = arguments;
return function() {
var i, result;
result = functions[0].apply(this, arguments);
for (i = 1; i < functions.length; ++i) {
result = functions[i](result);
}
return result;
};
}
function not$(x){ return !x; }
// Generated by LiveScript 1.6.0
var values, keys, pairsToObj, objToPairs, listsToObj, objToLists, empty$1, each$1, map$1, compact$1, filter$1, reject$1, partition$1, find$1;
values = function(object){
var i$, x, results$ = [];
for (i$ in object) {
x = object[i$];
results$.push(x);
}
return results$;
};
keys = function(object){
var x, results$ = [];
for (x in object) {
results$.push(x);
}
return results$;
};
pairsToObj = function(object){
var i$, len$, x, resultObj$ = {};
for (i$ = 0, len$ = object.length; i$ < len$; ++i$) {
x = object[i$];
resultObj$[x[0]] = x[1];
}
return resultObj$;
};
objToPairs = function(object){
var key, value, results$ = [];
for (key in object) {
value = object[key];
results$.push([key, value]);
}
return results$;
};
listsToObj = curry$$2(function(keys, values){
var i$, len$, i, key, resultObj$ = {};
for (i$ = 0, len$ = keys.length; i$ < len$; ++i$) {
i = i$;
key = keys[i$];
resultObj$[key] = values[i];
}
return resultObj$;
});
objToLists = function(object){
var keys, values, key, value;
keys = [];
values = [];
for (key in object) {
value = object[key];
keys.push(key);
values.push(value);
}
return [keys, values];
};
empty$1 = function(object){
var x;
for (x in object) {
return false;
}
return true;
};
each$1 = curry$$2(function(f, object){
var i$, x;
for (i$ in object) {
x = object[i$];
f(x);
}
return object;
});
map$1 = curry$$2(function(f, object){
var k, x, resultObj$ = {};
for (k in object) {
x = object[k];
resultObj$[k] = f(x);
}
return resultObj$;
});
compact$1 = function(object){
var k, x, resultObj$ = {};
for (k in object) {
x = object[k];
if (x) {
resultObj$[k] = x;
}
}
return resultObj$;
};
filter$1 = curry$$2(function(f, object){
var k, x, resultObj$ = {};
for (k in object) {
x = object[k];
if (f(x)) {
resultObj$[k] = x;
}
}
return resultObj$;
});
reject$1 = curry$$2(function(f, object){
var k, x, resultObj$ = {};
for (k in object) {
x = object[k];
if (!f(x)) {
resultObj$[k] = x;
}
}
return resultObj$;
});
partition$1 = curry$$2(function(f, object){
var passed, failed, k, x;
passed = {};
failed = {};
for (k in object) {
x = object[k];
(f(x) ? passed : failed)[k] = x;
}
return [passed, failed];
});
find$1 = curry$$2(function(f, object){
var i$, x;
for (i$ in object) {
x = object[i$];
if (f(x)) {
return x;
}
}
});
var Obj = {
values: values,
keys: keys,
pairsToObj: pairsToObj,
objToPairs: objToPairs,
listsToObj: listsToObj,
objToLists: objToLists,
empty: empty$1,
each: each$1,
map: map$1,
filter: filter$1,
compact: compact$1,
reject: reject$1,
partition: partition$1,
find: find$1
};
function curry$$2(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
// Generated by LiveScript 1.6.0
var split, join, lines, unlines, words, unwords, chars, unchars, reverse$1, repeat, capitalize, camelize, dasherize;
split = curry$$3(function(sep, str){
return str.split(sep);
});
join = curry$$3(function(sep, xs){
return xs.join(sep);
});
lines = function(str){
if (!str.length) {
return [];
}
return str.split('\n');
};
unlines = function(it){
return it.join('\n');
};
words = function(str){
if (!str.length) {
return [];
}
return str.split(/[ ]+/);
};
unwords = function(it){
return it.join(' ');
};
chars = function(it){
return it.split('');
};
unchars = function(it){
return it.join('');
};
reverse$1 = function(str){
return str.split('').reverse().join('');
};
repeat = curry$$3(function(n, str){
var result, i$;
result = '';
for (i$ = 0; i$ < n; ++i$) {
result += str;
}
return result;
});
capitalize = function(str){
return str.charAt(0).toUpperCase() + str.slice(1);
};
camelize = function(it){
return it.replace(/[-_]+(.)?/g, function(arg$, c){
return (c != null ? c : '').toUpperCase();
});
};
dasherize = function(str){
return str.replace(/([^-A-Z])([A-Z]+)/g, function(arg$, lower, upper){
return lower + "-" + (upper.length > 1
? upper
: upper.toLowerCase());
}).replace(/^([A-Z]+)/, function(arg$, upper){
if (upper.length > 1) {
return upper + "-";
} else {
return upper.toLowerCase();
}
});
};
var Str = {
split: split,
join: join,
lines: lines,
unlines: unlines,
words: words,
unwords: unwords,
chars: chars,
unchars: unchars,
reverse: reverse$1,
repeat: repeat,
capitalize: capitalize,
camelize: camelize,
dasherize: dasherize
};
function curry$$3(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
// Generated by LiveScript 1.6.0
var max, min, negate, abs, signum, quot, rem, div, mod, recip, pi, tau, exp, sqrt, ln, pow, sin, tan, cos, asin, acos, atan, atan2, truncate, round, ceiling, floor, isItNaN, even, odd, gcd, lcm;
max = curry$$4(function(x$, y$){
return x$ > y$ ? x$ : y$;
});
min = curry$$4(function(x$, y$){
return x$ < y$ ? x$ : y$;
});
negate = function(x){
return -x;
};
abs = Math.abs;
signum = function(x){
if (x < 0) {
return -1;
} else if (x > 0) {
return 1;
} else {
return 0;
}
};
quot = curry$$4(function(x, y){
return ~~(x / y);
});
rem = curry$$4(function(x$, y$){
return x$ % y$;
});
div = curry$$4(function(x, y){
return Math.floor(x / y);
});
mod = curry$$4(function(x$, y$){
var ref$;
return ((x$) % (ref$ = y$) + ref$) % ref$;
});
recip = (function(it){
return 1 / it;
});
pi = Math.PI;
tau = pi * 2;
exp = Math.exp;
sqrt = Math.sqrt;
ln = Math.log;
pow = curry$$4(function(x$, y$){
return Math.pow(x$, y$);
});
sin = Math.sin;
tan = Math.tan;
cos = Math.cos;
asin = Math.asin;
acos = Math.acos;
atan = Math.atan;
atan2 = curry$$4(function(x, y){
return Math.atan2(x, y);
});
truncate = function(x){
return ~~x;
};
round = Math.round;
ceiling = Math.ceil;
floor = Math.floor;
isItNaN = function(x){
return x !== x;
};
even = function(x){
return x % 2 === 0;
};
odd = function(x){
return x % 2 !== 0;
};
gcd = curry$$4(function(x, y){
var z;
x = Math.abs(x);
y = Math.abs(y);
while (y !== 0) {
z = x % y;
x = y;
y = z;
}
return x;
});
lcm = curry$$4(function(x, y){
return Math.abs(Math.floor(x / gcd(x, y) * y));
});
var Num = {
max: max,
min: min,
negate: negate,
abs: abs,
signum: signum,
quot: quot,
rem: rem,
div: div,
mod: mod,
recip: recip,
pi: pi,
tau: tau,
exp: exp,
sqrt: sqrt,
ln: ln,
pow: pow,
sin: sin,
tan: tan,
cos: cos,
acos: acos,
asin: asin,
atan: atan,
atan2: atan2,
truncate: truncate,
round: round,
ceiling: ceiling,
floor: floor,
isItNaN: isItNaN,
even: even,
odd: odd,
gcd: gcd,
lcm: lcm
};
function curry$$4(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
// Generated by LiveScript 1.6.0
var Func$1, List$1, Obj$1, Str$1, Num$1, id, isType, replicate, prelude, toString$$2 = {}.toString;
Func$1 = Func;
List$1 = List;
Obj$1 = Obj;
Str$1 = Str;
Num$1 = Num;
id = function(x){
return x;
};
isType = curry$$5(function(type, x){
return toString$$2.call(x).slice(8, -1) === type;
});
replicate = curry$$5(function(n, x){
var i$, results$ = [];
for (i$ = 0; i$ < n; ++i$) {
results$.push(x);
}
return results$;
});
Str$1.empty = List$1.empty;
Str$1.slice = List$1.slice;
Str$1.take = List$1.take;
Str$1.drop = List$1.drop;
Str$1.splitAt = List$1.splitAt;
Str$1.takeWhile = List$1.takeWhile;
Str$1.dropWhile = List$1.dropWhile;
Str$1.span = List$1.span;
Str$1.breakStr = List$1.breakList;
prelude = {
Func: Func$1,
List: List$1,
Obj: Obj$1,
Str: Str$1,
Num: Num$1,
id: id,
isType: isType,
replicate: replicate
};
prelude.each = List$1.each;
prelude.map = List$1.map;
prelude.filter = List$1.filter;
prelude.compact = List$1.compact;
prelude.reject = List$1.reject;
prelude.partition = List$1.partition;
prelude.find = List$1.find;
prelude.head = List$1.head;
prelude.first = List$1.first;
prelude.tail = List$1.tail;
prelude.last = List$1.last;
prelude.initial = List$1.initial;
prelude.empty = List$1.empty;
prelude.reverse = List$1.reverse;
prelude.difference = List$1.difference;
prelude.intersection = List$1.intersection;
prelude.union = List$1.union;
prelude.countBy = List$1.countBy;
prelude.groupBy = List$1.groupBy;
prelude.fold = List$1.fold;
prelude.foldl = List$1.foldl;
prelude.fold1 = List$1.fold1;
prelude.foldl1 = List$1.foldl1;
prelude.foldr = List$1.foldr;
prelude.foldr1 = List$1.foldr1;
prelude.unfoldr = List$1.unfoldr;
prelude.andList = List$1.andList;
prelude.orList = List$1.orList;
prelude.any = List$1.any;
prelude.all = List$1.all;
prelude.unique = List$1.unique;
prelude.uniqueBy = List$1.uniqueBy;
prelude.sort = List$1.sort;
prelude.sortWith = List$1.sortWith;
prelude.sortBy = List$1.sortBy;
prelude.sum = List$1.sum;
prelude.product = List$1.product;
prelude.mean = List$1.mean;
prelude.average = List$1.average;
prelude.concat = List$1.concat;
prelude.concatMap = List$1.concatMap;
prelude.flatten = List$1.flatten;
prelude.maximum = List$1.maximum;
prelude.minimum = List$1.minimum;
prelude.maximumBy = List$1.maximumBy;
prelude.minimumBy = List$1.minimumBy;
prelude.scan = List$1.scan;
prelude.scanl = List$1.scanl;
prelude.scan1 = List$1.scan1;
prelude.scanl1 = List$1.scanl1;
prelude.scanr = List$1.scanr;
prelude.scanr1 = List$1.scanr1;
prelude.slice = List$1.slice;
prelude.take = List$1.take;
prelude.drop = List$1.drop;
prelude.splitAt = List$1.splitAt;
prelude.takeWhile = List$1.takeWhile;
prelude.dropWhile = List$1.dropWhile;
prelude.span = List$1.span;
prelude.breakList = List$1.breakList;
prelude.zip = List$1.zip;
prelude.zipWith = List$1.zipWith;
prelude.zipAll = List$1.zipAll;
prelude.zipAllWith = List$1.zipAllWith;
prelude.at = List$1.at;
prelude.elemIndex = List$1.elemIndex;
prelude.elemIndices = List$1.elemIndices;
prelude.findIndex = List$1.findIndex;
prelude.findIndices = List$1.findIndices;
prelude.apply = Func$1.apply;
prelude.curry = Func$1.curry;
prelude.flip = Func$1.flip;
prelude.fix = Func$1.fix;
prelude.over = Func$1.over;
prelude.split = Str$1.split;
prelude.join = Str$1.join;
prelude.lines = Str$1.lines;
prelude.unlines = Str$1.unlines;
prelude.words = Str$1.words;
prelude.unwords = Str$1.unwords;
prelude.chars = Str$1.chars;
prelude.unchars = Str$1.unchars;
prelude.repeat = Str$1.repeat;
prelude.capitalize = Str$1.capitalize;
prelude.camelize = Str$1.camelize;
prelude.dasherize = Str$1.dasherize;
prelude.values = Obj$1.values;
prelude.keys = Obj$1.keys;
prelude.pairsToObj = Obj$1.pairsToObj;
prelude.objToPairs = Obj$1.objToPairs;
prelude.listsToObj = Obj$1.listsToObj;
prelude.objToLists = Obj$1.objToLists;
prelude.max = Num$1.max;
prelude.min = Num$1.min;
prelude.negate = Num$1.negate;
prelude.abs = Num$1.abs;
prelude.signum = Num$1.signum;
prelude.quot = Num$1.quot;
prelude.rem = Num$1.rem;
prelude.div = Num$1.div;
prelude.mod = Num$1.mod;
prelude.recip = Num$1.recip;
prelude.pi = Num$1.pi;
prelude.tau = Num$1.tau;
prelude.exp = Num$1.exp;
prelude.sqrt = Num$1.sqrt;
prelude.ln = Num$1.ln;
prelude.pow = Num$1.pow;
prelude.sin = Num$1.sin;
prelude.tan = Num$1.tan;
prelude.cos = Num$1.cos;
prelude.acos = Num$1.acos;
prelude.asin = Num$1.asin;
prelude.atan = Num$1.atan;
prelude.atan2 = Num$1.atan2;
prelude.truncate = Num$1.truncate;
prelude.round = Num$1.round;
prelude.ceiling = Num$1.ceiling;
prelude.floor = Num$1.floor;
prelude.isItNaN = Num$1.isItNaN;
prelude.even = Num$1.even;
prelude.odd = Num$1.odd;
prelude.gcd = Num$1.gcd;
prelude.lcm = Num$1.lcm;
prelude.VERSION = '1.2.1';
var lib$1 = prelude;
function curry$$5(f, bound){
var context,
_curry = function(args) {
return f.length > 1 ? function(){
var params = args ? args.concat() : [];
context = bound ? context || this : this;
return params.push.apply(params, arguments) <
f.length && arguments.length ?
_curry.call(context, params) : f.apply(context, params);
} : f;
};
return _curry();
}
var eventEmitter = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, reject, maximum, map, EventEmitter, out$ = exports || commonjsGlobal, toString$ = {}.toString;
ref$ = lib$1, reject = ref$.reject, maximum = ref$.maximum, map = ref$.map;
out$.EventEmitter = EventEmitter = (function(){
EventEmitter.displayName = 'EventEmitter';
function EventEmitter(){
this._events = {};
this._one_time_events = {};
}
EventEmitter.prototype.once = function(type, callback){
var addListener, name, this$ = this;
addListener = function(type, callback){
if (toString$.call(this$._one_time_events[type]).slice(8, -1) !== 'Array') {
this$._one_time_events[type] = [];
}
return this$._one_time_events[type].push(callback.bind(this$));
};
switch (toString$.call(type).slice(8, -1)) {
case 'String':
addListener(type, callback);
break;
case 'Object':
for (name in type) {
callback = type[name];
addListener(name, callback);
}
}
};
EventEmitter.prototype.on = function(type, id, callback){
"usage:\n\n with simple string name:\n\n .on 'name', fn\n\n or with an object:\n\n .on do\n 'name1': fn\n 'name2': fn2";
var _id, addListener, control, name, this$ = this;
if (toString$.call(id).slice(8, -1) === 'Function') {
callback = id;
_id = maximum(
map(parseInt)(
(function(){
var i$, x$, ref$, len$, results$ = [];
for (i$ = 0, len$ = (ref$ = this._events).length; i$ < len$; ++i$) {
x$ = ref$[i$];
results$.push(x$.id);
}
return results$;
}.call(this))));
id = (_id || 0) + 1;
}
addListener = function(type, id, callback){
var ref$;
((ref$ = this$._events)[type] || (ref$[type] = [])).push({
id: id,
cb: callback.bind(this$)
});
return {
cancel: function(){
return this$.cancel(id);
}
};
};
control = null;
switch (toString$.call(type).slice(8, -1)) {
case 'String':
control = addListener(type, id, callback);
break;
case 'Object':
for (name in type) {
callback = type[name];
addListener(name, id, callback);
}
}
return control;
};
EventEmitter.prototype.off = function(type){
return this._events[type] = [];
};
EventEmitter.prototype.cancel = function(id){
var type, ref$, listeners, i, listener;
for (type in ref$ = this._events) {
listeners = ref$[type];
for (i in listeners) {
listener = listeners[i];
if (listener.id === id) {
listeners.splice(i, 1);
break;
}
}
}
};
EventEmitter.prototype.trigger = function(type){
"usage:\n\n .trigger \"eventName\", ...x\n";
var args, res$, i$, to$, that, len$, ref$, i, handler, results$ = [];
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
if (that = this._events[type]) {
for (i$ = 0, len$ = that.length; i$ < len$; ++i$) {
(fn$.call(this, that[i$]));
}
}
if (that = this._one_time_events[type]) {
for (i$ = 0, len$ = (ref$ = (fn1$())).length; i$ < len$; ++i$) {
i = ref$[i$];
handler = that.shift();
results$.push(handler.apply(null, args));
}
return results$;
}
function fn$(handler){
setImmediate(function(){
return handler.cb.apply(handler, args);
});
}
function fn1$(){
var i$, to$, results$ = [];
for (i$ = 1, to$ = that.length; i$ <= to$; ++i$) {
results$.push(i$);
}
return results$;
}
};
EventEmitter.prototype.hasListener = function(ev){
var that, i$, x$, len$;
if (that = this._events[ev]) {
for (i$ = 0, len$ = that.length; i$ < len$; ++i$) {
x$ = that[i$];
if (toString$.call(x$.cb).slice(8, -1) === 'Function') {
return true;
}
}
}
return false;
};
return EventEmitter;
}());
});
var logger = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, green, gray, yellow, magenta, bgRed, bgYellow, cyan, bgCyan, bgGreen, moment$1, map, EventEmitter, NEED_STACK_TRACE, fmt, startTime, alignLeft, getTimestamp, getPrefix, IS_NODE, LogManager, Logger, out$ = exports || commonjsGlobal, slice$ = [].slice, arrayFrom$ = Array.from || function(x){return slice$.call(x);}, toString$ = {}.toString;
ref$ = lib, green = ref$.green, gray = ref$.gray, yellow = ref$.yellow, magenta = ref$.magenta, bgRed = ref$.bgRed, bgYellow = ref$.bgYellow, cyan = ref$.cyan, bgCyan = ref$.bgCyan, bgGreen = ref$.bgGreen;
moment$1 = moment;
map = lib$1.map;
EventEmitter = eventEmitter.EventEmitter;
NEED_STACK_TRACE = false;
fmt = 'HH:mm:ss.SSS';
startTime = new moment$1;
alignLeft = function(width, inp){
var x;
return x = (inp + repeatString$(" ", width)).slice(0, width);
};
getTimestamp = function(){
return (new moment$1).format(fmt);
};
getPrefix = function(_source, color){
var padded;
if (!color) {
color = gray;
}
padded = alignLeft(15, _source + "");
return color("[" + getTimestamp() + "]") + (" " + padded + " :");
};
IS_NODE = function(){
var isNode;
isNode = false;
if (typeof process === 'object') {
if (typeof process.versions === 'object') {
if (typeof process.versions.node !== 'undefined') {
isNode = true;
}
}
}
return isNode;
}();
LogManager = (function(superclass){
var prototype = extend$((import$(LogManager, superclass).displayName = 'LogManager', LogManager), superclass).prototype, constructor = LogManager;
constructor.instance = null;
function LogManager(){
if (constructor.instance) {
return constructor.instance;
}
LogManager.superclass.call(this);
constructor.instance = this;
this.loggers = [];
}
LogManager.prototype.register = function(ctx){
return this.loggers.push(ctx);
};
return LogManager;
}(EventEmitter));
out$.Logger = Logger = (function(superclass){
var prototype = extend$((import$(Logger, superclass).displayName = 'Logger', Logger), superclass).prototype;
function Logger(sourceName, opts){
this.debug = bind$(this, 'debug', prototype);
this.todo = bind$(this, 'todo', prototype);
this.info = bind$(this, 'info', prototype);
this.warn = bind$(this, 'warn', prototype);
this.err = bind$(this, 'err', prototype);
this.success = bind$(this, 'success', prototype);
this.log = bind$(this, 'log', prototype);
Logger.superclass.call(this);
this.name = sourceName;
this.mgr = new LogManager();
this.prefix = null;
this.error = this.err;
}
Logger.prototype.getPrefix = function(color){
return getPrefix((this.prefix ? this.prefix + "/" : '') + "" + this.name, color);
};
Logger.prototype.log = function(){
var args, res$, i$, to$, prefix, ref$, _args, my, len$, arg, log;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
prefix = getPrefix(this.name);
if (IS_NODE) {
return (ref$ = console.log).call.apply(ref$, [console, prefix].concat(arrayFrom$(args)));
} else {
_args = [];
my = "%c";
for (i$ = 0, len$ = (ref$ = [prefix].concat(args)).length; i$ < len$; ++i$) {
arg = ref$[i$];
_args.push(arg);
my += " " + (toString$.call(arg).slice(8, -1) === 'String'
? "%s"
: toString$.call(arg).slice(8, -1) === 'Number' ? "%d" : "%O");
}
if (NEED_STACK_TRACE) {
console.groupCollapsed.apply(console, [my, "font-weight: normal;"].concat(arrayFrom$(_args)));
console.trace(prefix);
return console.groupEnd();
} else {
log = Function.prototype.bind.call(console.log, console);
return log.call.apply(log, [console, my, "font-weight: normal;"].concat(arrayFrom$(_args)));
}
}
};
Logger.prototype.success = function(){
var args, res$, i$, to$;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
return console.log.apply(console, [this.getPrefix(bgGreen)].concat(args));
};
Logger.prototype.err = function(){
var args, res$, i$, to$, ref$;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
console.error.apply(console, [this.getPrefix(bgRed)].concat(args));
this.trigger.apply(this, ['err'].concat(arrayFrom$(args)));
return (ref$ = this.mgr).trigger.apply(ref$, ['err'].concat(arrayFrom$(args)));
};
Logger.prototype.warn = function(){
var args, res$, i$, to$;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
return console.warn.apply(console, [this.getPrefix(bgYellow), yellow('[WARNING]')].concat(args));
};
Logger.prototype.info = function(){
var args, res$, i$, to$;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
return console.info.apply(console, [this.getPrefix(), cyan('[I]')].concat(args));
};
Logger.prototype.todo = function(){
var args, res$, i$, to$;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
return console.warn.apply(console, [this.getPrefix(), magenta('[TODO]')].concat(args));
};
Logger.prototype.debug = function(){
var args, res$, i$, to$;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
return console.warn.apply(console, [this.getPrefix(), yellow('[D]')].concat(args));
};
return Logger;
}(EventEmitter));
function repeatString$(str, n){
for (var r = ''; n > 0; (n >>= 1) && (str += str)) if (n & 1) r += str;
return r;
}
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
function bind$(obj, key, target){
return function(){ return (target || obj)[key].apply(obj, arguments) };
}
});
(function (global, undefined$1) {
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$1, 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 commonjsGlobal === "undefined" ? commonjsGlobal : commonjsGlobal : self));
var sleep_1 = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var sleep, clearTimer, out$ = exports || commonjsGlobal;
out$.sleep = sleep = function(ms, f){
return setTimeout(f, ms);
};
out$.clearTimer = clearTimer = function(x){
return clearInterval(x);
};
});
var isBrowser = typeof window !== 'undefined';
var environment = {
isBrowser: isBrowser
};
var Processor = function Processor(options){
this.selfOptions = options || {};
this.pipes = {};
};
Processor.prototype.options = function(options) {
if (options) {
this.selfOptions = options;
}
return this.selfOptions;
};
Processor.prototype.pipe = function(name, pipe) {
if (typeof name === 'string') {
if (typeof pipe === 'undefined') {
return this.pipes[name];
} else {
this.pipes[name] = pipe;
}
}
if (name && name.name) {
pipe = name;
if (pipe.processor === this) { return pipe; }
this.pipes[pipe.name] = pipe;
}
pipe.processor = this;
return pipe;
};
Processor.prototype.process = function(input, pipe) {
var context = input;
context.options = this.options();
var nextPipe = pipe || input.pipe || 'default';
var lastPipe, lastContext;
while (nextPipe) {
if (typeof context.nextAfterChildren !== 'undefined') {
// children processed and coming back to parent
context.next = context.nextAfterChildren;
context.nextAfterChildren = null;
}
if (typeof nextPipe === 'string') {
nextPipe = this.pipe(nextPipe);
}
nextPipe.process(context);
lastContext = context;
lastPipe = nextPipe;
nextPipe = null;
if (context) {
if (context.next) {
context = context.next;
nextPipe = lastContext.nextPipe || context.pipe || lastPipe;
}
}
}
return context.hasResult ? context.result : undefined;
};
var Processor_1 = Processor;
var processor = {
Processor: Processor_1
};
var Pipe = function Pipe(name) {
this.name = name;
this.filters = [];
};
Pipe.prototype.process = function(input) {
if (!this.processor) {
throw new Error('add this pipe to a processor before using it');
}
var debug = this.debug;
var length = this.filters.length;
var context = input;
for (var index = 0; index < length; index++) {
var filter = this.filters[index];
if (debug) {
this.log('filter: ' + filter.filterName);
}
filter(context);
if (typeof context === 'object' && context.exiting) {
context.exiting = false;
break;
}
}
if (!context.next && this.resultCheck) {
this.resultCheck(context);
}
};
Pipe.prototype.log = function(msg) {
console.log('[jsondiffpatch] ' + this.name + ' pipe, ' + msg);
};
Pipe.prototype.append = function() {
this.filters.push.apply(this.filters, arguments);
return this;
};
Pipe.prototype.prepend = function() {
this.filters.unshift.apply(this.filters, arguments);
return this;
};
Pipe.prototype.indexOf = function(filterName) {
if (!filterName) {
throw new Error('a filter name is required');
}
for (var index = 0; index < this.filters.length; index++) {
var filter = this.filters[index];
if (filter.filterName === filterName) {
return index;
}
}
throw new Error('filter not found: ' + filterName);
};
Pipe.prototype.list = function() {
var names = [];
for (var index = 0; index < this.filters.length; index++) {
var filter = this.filters[index];
names.push(filter.filterName);
}
return names;
};
Pipe.prototype.after = function(filterName) {
var index = this.indexOf(filterName);
var params = Array.prototype.slice.call(arguments, 1);
if (!params.length) {
throw new Error('a filter is required');
}
params.unshift(index + 1, 0);
Array.prototype.splice.apply(this.filters, params);
return this;
};
Pipe.prototype.before = function(filterName) {
var index = this.indexOf(filterName);
var params = Array.prototype.slice.call(arguments, 1);
if (!params.length) {
throw new Error('a filter is required');
}
params.unshift(index, 0);
Array.prototype.splice.apply(this.filters, params);
return this;
};
Pipe.prototype.replace = function(filterName) {
var index = this.indexOf(filterName);
var params = Array.prototype.slice.call(arguments, 1);
if (!params.length) {
throw new Error('a filter is required');
}
params.unshift(index, 1);
Array.prototype.splice.apply(this.filters, params);
return this;
};
Pipe.prototype.remove = function(filterName) {
var index = this.indexOf(filterName);
this.filters.splice(index, 1);
return this;
};
Pipe.prototype.clear = function() {
this.filters.length = 0;
return this;
};
Pipe.prototype.shouldHaveResult = function(should) {
if (should === false) {
this.resultCheck = null;
return;
}
if (this.resultCheck) {
return;
}
var pipe = this;
this.resultCheck = function(context) {
if (!context.hasResult) {
console.log(context);
var error = new Error(pipe.name + ' failed');
error.noResult = true;
throw error;
}
};
return this;
};
var Pipe_1 = Pipe;
var pipe = {
Pipe: Pipe_1
};
var Pipe$1 = pipe.Pipe;
var Context = function Context(){
};
Context.prototype.setResult = function(result) {
this.result = result;
this.hasResult = true;
return this;
};
Context.prototype.exit = function() {
this.exiting = true;
return this;
};
Context.prototype.switchTo = function(next, pipe) {
if (typeof next === 'string' || next instanceof Pipe$1) {
this.nextPipe = next;
} else {
this.next = next;
if (pipe) {
this.nextPipe = pipe;
}
}
return this;
};
Context.prototype.push = function(child, name) {
child.parent = this;
if (typeof name !== 'undefined') {
child.childName = name;
}
child.root = this.root || this;
child.options = child.options || this.options;
if (!this.children) {
this.children = [child];
this.nextAfterChildren = this.next || null;
this.next = child;
} else {
this.children[this.children.length - 1].next = child;
this.children.push(child);
}
child.next = this;
return this;
};
var Context_1 = Context;
var context = {
Context: Context_1
};
var isArray = (typeof Array.isArray === 'function') ?
// use native function
Array.isArray :
// use instanceof operator
function(a) {
return a instanceof Array;
};
function cloneRegExp(re) {
var regexMatch = /^\/(.*)\/([gimyu]*)$/.exec(re.toString());
return new RegExp(regexMatch[1], regexMatch[2]);
}
function clone(arg) {
if (typeof arg !== 'object') {
return arg;
}
if (arg === null) {
return null;
}
if (isArray(arg)) {
return arg.map(clone);
}
if (arg instanceof Date) {
return new Date(arg.getTime());
}
if (arg instanceof RegExp) {
return cloneRegExp(arg);
}
var cloned = {};
for (var name in arg) {
if (Object.prototype.hasOwnProperty.call(arg, name)) {
cloned[name] = clone(arg[name]);
}
}
return cloned;
}
var clone_1 = clone;
var Context$1 = context.Context;
var DiffContext = function DiffContext(left, right) {
this.left = left;
this.right = right;
this.pipe = 'diff';
};
DiffContext.prototype = new Context$1();
DiffContext.prototype.setResult = function(result) {
if (this.options.cloneDiffValues && typeof result === 'object') {
var clone = typeof this.options.cloneDiffValues === 'function' ?
this.options.cloneDiffValues : clone_1;
if (typeof result[0] === 'object') {
result[0] = clone(result[0]);
}
if (typeof result[1] === 'object') {
result[1] = clone(result[1]);
}
}
return Context$1.prototype.setResult.apply(this, arguments);
};
var DiffContext_1 = DiffContext;
var diff = {
DiffContext: DiffContext_1
};
var Context$2 = context.Context;
var PatchContext = function PatchContext(left, delta) {
this.left = left;
this.delta = delta;
this.pipe = 'patch';
};
PatchContext.prototype = new Context$2();
var PatchContext_1 = PatchContext;
var patch = {
PatchContext: PatchContext_1
};
var Context$3 = context.Context;
var ReverseContext = function ReverseContext(delta) {
this.delta = delta;
this.pipe = 'reverse';
};
ReverseContext.prototype = new Context$3();
var ReverseContext_1 = ReverseContext;
var reverse$2 = {
ReverseContext: ReverseContext_1
};
var isArray$1 = (typeof Array.isArray === 'function') ?
// use native function
Array.isArray :
// use instanceof operator
function(a) {
return a instanceof Array;
};
var diffFilter = function trivialMatchesDiffFilter(context) {
if (context.left === context.right) {
context.setResult(undefined).exit();
return;
}
if (typeof context.left === 'undefined') {
if (typeof context.right === 'function') {
throw new Error('functions are not supported');
}
context.setResult([context.right]).exit();
return;
}
if (typeof context.right === 'undefined') {
context.setResult([context.left, 0, 0]).exit();
return;
}
if (typeof context.left === 'function' || typeof context.right === 'function') {
throw new Error('functions are not supported');
}
context.leftType = context.left === null ? 'null' : typeof context.left;
context.rightType = context.right === null ? 'null' : typeof context.right;
if (context.leftType !== context.rightType) {
context.setResult([context.left, context.right]).exit();
return;
}
if (context.leftType === 'boolean' || context.leftType === 'number') {
context.setResult([context.left, context.right]).exit();
return;
}
if (context.leftType === 'object') {
context.leftIsArray = isArray$1(context.left);
}
if (context.rightType === 'object') {
context.rightIsArray = isArray$1(context.right);
}
if (context.leftIsArray !== context.rightIsArray) {
context.setResult([context.left, context.right]).exit();
return;
}
if (context.left instanceof RegExp) {
if (context.right instanceof RegExp) {
context.setResult([context.left.toString(), context.right.toString()]).exit();
} else {
context.setResult([context.left, context.right]).exit();
return;
}
}
};
diffFilter.filterName = 'trivial';
var patchFilter = function trivialMatchesPatchFilter(context) {
if (typeof context.delta === 'undefined') {
context.setResult(context.left).exit();
return;
}
context.nested = !isArray$1(context.delta);
if (context.nested) {
return;
}
if (context.delta.length === 1) {
context.setResult(context.delta[0]).exit();
return;
}
if (context.delta.length === 2) {
if (context.left instanceof RegExp) {
var regexArgs = /^\/(.*)\/([gimyu]+)$/.exec(context.delta[1]);
if (regexArgs) {
context.setResult(new RegExp(regexArgs[1], regexArgs[2])).exit();
return;
}
}
context.setResult(context.delta[1]).exit();
return;
}
if (context.delta.length === 3 && context.delta[2] === 0) {
context.setResult(undefined).exit();
return;
}
};
patchFilter.filterName = 'trivial';
var reverseFilter = function trivialReferseFilter(context) {
if (typeof context.delta === 'undefined') {
context.setResult(context.delta).exit();
return;
}
context.nested = !isArray$1(context.delta);
if (context.nested) {
return;
}
if (context.delta.length === 1) {
context.setResult([context.delta[0], 0, 0]).exit();
return;
}
if (context.delta.length === 2) {
context.setResult([context.delta[1], context.delta[0]]).exit();
return;
}
if (context.delta.length === 3 && context.delta[2] === 0) {
context.setResult([context.delta[0]]).exit();
return;
}
};
reverseFilter.filterName = 'trivial';
var diffFilter_1 = diffFilter;
var patchFilter_1 = patchFilter;
var reverseFilter_1 = reverseFilter;
var trivial = {
diffFilter: diffFilter_1,
patchFilter: patchFilter_1,
reverseFilter: reverseFilter_1
};
var DiffContext$1 = diff.DiffContext;
var PatchContext$1 = patch.PatchContext;
var ReverseContext$1 = reverse$2.ReverseContext;
var collectChildrenDiffFilter = function collectChildrenDiffFilter(context) {
if (!context || !context.children) {
return;
}
var length = context.children.length;
var child;
var result = context.result;
for (var index = 0; index < length; index++) {
child = context.children[index];
if (typeof child.result === 'undefined') {
continue;
}
result = result || {};
result[child.childName] = child.result;
}
if (result && context.leftIsArray) {
result._t = 'a';
}
context.setResult(result).exit();
};
collectChildrenDiffFilter.filterName = 'collectChildren';
var objectsDiffFilter = function objectsDiffFilter(context) {
if (context.leftIsArray || context.leftType !== 'object') {
return;
}
var name, child, propertyFilter = context.options.propertyFilter;
for (name in context.left) {
if (!Object.prototype.hasOwnProperty.call(context.left, name)) {
continue;
}
if (propertyFilter && !propertyFilter(name, context)) {
continue;
}
child = new DiffContext$1(context.left[name], context.right[name]);
context.push(child, name);
}
for (name in context.right) {
if (!Object.prototype.hasOwnProperty.call(context.right, name)) {
continue;
}
if (propertyFilter && !propertyFilter(name, context)) {
continue;
}
if (typeof context.left[name] === 'undefined') {
child = new DiffContext$1(undefined, context.right[name]);
context.push(child, name);
}
}
if (!context.children || context.children.length === 0) {
context.setResult(undefined).exit();
return;
}
context.exit();
};
objectsDiffFilter.filterName = 'objects';
var patchFilter$1 = function nestedPatchFilter(context) {
if (!context.nested) {
return;
}
if (context.delta._t) {
return;
}
var name, child;
for (name in context.delta) {
child = new PatchContext$1(context.left[name], context.delta[name]);
context.push(child, name);
}
context.exit();
};
patchFilter$1.filterName = 'objects';
var collectChildrenPatchFilter = function collectChildrenPatchFilter(context) {
if (!context || !context.children) {
return;
}
if (context.delta._t) {
return;
}
var length = context.children.length;
var child;
for (var index = 0; index < length; index++) {
child = context.children[index];
if (Object.prototype.hasOwnProperty.call(context.left, child.childName) && child.result === undefined) {
delete context.left[child.childName];
} else if (context.left[child.childName] !== child.result) {
context.left[child.childName] = child.result;
}
}
context.setResult(context.left).exit();
};
collectChildrenPatchFilter.filterName = 'collectChildren';
var reverseFilter$1 = function nestedReverseFilter(context) {
if (!context.nested) {
return;
}
if (context.delta._t) {
return;
}
var name, child;
for (name in context.delta) {
child = new ReverseContext$1(context.delta[name]);
context.push(child, name);
}
context.exit();
};
reverseFilter$1.filterName = 'objects';
var collectChildrenReverseFilter = function collectChildrenReverseFilter(context) {
if (!context || !context.children) {
return;
}
if (context.delta._t) {
return;
}
var length = context.children.length;
var child;
var delta = {};
for (var index = 0; index < length; index++) {
child = context.children[index];
if (delta[child.childName] !== child.result) {
delta[child.childName] = child.result;
}
}
context.setResult(delta).exit();
};
collectChildrenReverseFilter.filterName = 'collectChildren';
var collectChildrenDiffFilter_1 = collectChildrenDiffFilter;
var objectsDiffFilter_1 = objectsDiffFilter;
var patchFilter_1$1 = patchFilter$1;
var collectChildrenPatchFilter_1 = collectChildrenPatchFilter;
var reverseFilter_1$1 = reverseFilter$1;
var collectChildrenReverseFilter_1 = collectChildrenReverseFilter;
var nested = {
collectChildrenDiffFilter: collectChildrenDiffFilter_1,
objectsDiffFilter: objectsDiffFilter_1,
patchFilter: patchFilter_1$1,
collectChildrenPatchFilter: collectChildrenPatchFilter_1,
reverseFilter: reverseFilter_1$1,
collectChildrenReverseFilter: collectChildrenReverseFilter_1
};
/*
LCS implementation that supports arrays or strings
reference: http://en.wikipedia.org/wiki/Longest_common_subsequence_problem
*/
var defaultMatch = function(array1, array2, index1, index2) {
return array1[index1] === array2[index2];
};
var lengthMatrix = function(array1, array2, match, context) {
var len1 = array1.length;
var len2 = array2.length;
var x, y;
// initialize empty matrix of len1+1 x len2+1
var matrix = [len1 + 1];
for (x = 0; x < len1 + 1; x++) {
matrix[x] = [len2 + 1];
for (y = 0; y < len2 + 1; y++) {
matrix[x][y] = 0;
}
}
matrix.match = match;
// save sequence lengths for each coordinate
for (x = 1; x < len1 + 1; x++) {
for (y = 1; y < len2 + 1; y++) {
if (match(array1, array2, x - 1, y - 1, context)) {
matrix[x][y] = matrix[x - 1][y - 1] + 1;
} else {
matrix[x][y] = Math.max(matrix[x - 1][y], matrix[x][y - 1]);
}
}
}
return matrix;
};
var backtrack = function(matrix, array1, array2, index1, index2, context) {
if (index1 === 0 || index2 === 0) {
return {
sequence: [],
indices1: [],
indices2: []
};
}
if (matrix.match(array1, array2, index1 - 1, index2 - 1, context)) {
var subsequence = backtrack(matrix, array1, array2, index1 - 1, index2 - 1, context);
subsequence.sequence.push(array1[index1 - 1]);
subsequence.indices1.push(index1 - 1);
subsequence.indices2.push(index2 - 1);
return subsequence;
}
if (matrix[index1][index2 - 1] > matrix[index1 - 1][index2]) {
return backtrack(matrix, array1, array2, index1, index2 - 1, context);
} else {
return backtrack(matrix, array1, array2, index1 - 1, index2, context);
}
};
var get = function(array1, array2, match, context) {
context = context || {};
var matrix = lengthMatrix(array1, array2, match || defaultMatch, context);
var result = backtrack(matrix, array1, array2, array1.length, array2.length, context);
if (typeof array1 === 'string' && typeof array2 === 'string') {
result.sequence = result.sequence.join('');
}
return result;
};
var get_1 = get;
var lcs = {
get: get_1
};
var DiffContext$2 = diff.DiffContext;
var PatchContext$2 = patch.PatchContext;
var ReverseContext$2 = reverse$2.ReverseContext;
var ARRAY_MOVE = 3;
var isArray$2 = (typeof Array.isArray === 'function') ?
// use native function
Array.isArray :
// use instanceof operator
function(a) {
return a instanceof Array;
};
var arrayIndexOf = typeof Array.prototype.indexOf === 'function' ?
function(array, item) {
return array.indexOf(item);
} : function(array, item) {
var length = array.length;
for (var i = 0; i < length; i++) {
if (array[i] === item) {
return i;
}
}
return -1;
};
function arraysHaveMatchByRef(array1, array2, len1, len2) {
for (var index1 = 0; index1 < len1; index1++) {
var val1 = array1[index1];
for (var index2 = 0; index2 < len2; index2++) {
var val2 = array2[index2];
if (index1 !== index2 && val1 === val2) {
return true;
}
}
}
}
function matchItems(array1, array2, index1, index2, context) {
var value1 = array1[index1];
var value2 = array2[index2];
if (value1 === value2) {
return true;
}
if (typeof value1 !== 'object' || typeof value2 !== 'object') {
return false;
}
var objectHash = context.objectHash;
if (!objectHash) {
// no way to match objects was provided, try match by position
return context.matchByPosition && index1 === index2;
}
var hash1;
var hash2;
if (typeof index1 === 'number') {
context.hashCache1 = context.hashCache1 || [];
hash1 = context.hashCache1[index1];
if (typeof hash1 === 'undefined') {
context.hashCache1[index1] = hash1 = objectHash(value1, index1);
}
} else {
hash1 = objectHash(value1);
}
if (typeof hash1 === 'undefined') {
return false;
}
if (typeof index2 === 'number') {
context.hashCache2 = context.hashCache2 || [];
hash2 = context.hashCache2[index2];
if (typeof hash2 === 'undefined') {
context.hashCache2[index2] = hash2 = objectHash(value2, index2);
}
} else {
hash2 = objectHash(value2);
}
if (typeof hash2 === 'undefined') {
return false;
}
return hash1 === hash2;
}
var diffFilter$1 = function arraysDiffFilter(context) {
if (!context.leftIsArray) {
return;
}
var matchContext = {
objectHash: context.options && context.options.objectHash,
matchByPosition: context.options && context.options.matchByPosition
};
var commonHead = 0;
var commonTail = 0;
var index;
var index1;
var index2;
var array1 = context.left;
var array2 = context.right;
var len1 = array1.length;
var len2 = array2.length;
var child;
if (len1 > 0 && len2 > 0 && !matchContext.objectHash &&
typeof matchContext.matchByPosition !== 'boolean') {
matchContext.matchByPosition = !arraysHaveMatchByRef(array1, array2, len1, len2);
}
// separate common head
while (commonHead < len1 && commonHead < len2 &&
matchItems(array1, array2, commonHead, commonHead, matchContext)) {
index = commonHead;
child = new DiffContext$2(context.left[index], context.right[index]);
context.push(child, index);
commonHead++;
}
// separate common tail
while (commonTail + commonHead < len1 && commonTail + commonHead < len2 &&
matchItems(array1, array2, len1 - 1 - commonTail, len2 - 1 - commonTail, matchContext)) {
index1 = len1 - 1 - commonTail;
index2 = len2 - 1 - commonTail;
child = new DiffContext$2(context.left[index1], context.right[index2]);
context.push(child, index2);
commonTail++;
}
var result;
if (commonHead + commonTail === len1) {
if (len1 === len2) {
// arrays are identical
context.setResult(undefined).exit();
return;
}
// trivial case, a block (1 or more consecutive items) was added
result = result || {
_t: 'a'
};
for (index = commonHead; index < len2 - commonTail; index++) {
result[index] = [array2[index]];
}
context.setResult(result).exit();
return;
}
if (commonHead + commonTail === len2) {
// trivial case, a block (1 or more consecutive items) was removed
result = result || {
_t: 'a'
};
for (index = commonHead; index < len1 - commonTail; index++) {
result['_' + index] = [array1[index], 0, 0];
}
context.setResult(result).exit();
return;
}
// reset hash cache
delete matchContext.hashCache1;
delete matchContext.hashCache2;
// diff is not trivial, find the LCS (Longest Common Subsequence)
var trimmed1 = array1.slice(commonHead, len1 - commonTail);
var trimmed2 = array2.slice(commonHead, len2 - commonTail);
var seq = lcs.get(
trimmed1, trimmed2,
matchItems,
matchContext
);
var removedItems = [];
result = result || {
_t: 'a'
};
for (index = commonHead; index < len1 - commonTail; index++) {
if (arrayIndexOf(seq.indices1, index - commonHead) < 0) {
// removed
result['_' + index] = [array1[index], 0, 0];
removedItems.push(index);
}
}
var detectMove = true;
if (context.options && context.options.arrays && context.options.arrays.detectMove === false) {
detectMove = false;
}
var includeValueOnMove = false;
if (context.options && context.options.arrays && context.options.arrays.includeValueOnMove) {
includeValueOnMove = true;
}
var removedItemsLength = removedItems.length;
for (index = commonHead; index < len2 - commonTail; index++) {
var indexOnArray2 = arrayIndexOf(seq.indices2, index - commonHead);
if (indexOnArray2 < 0) {
// added, try to match with a removed item and register as position move
var isMove = false;
if (detectMove && removedItemsLength > 0) {
for (var removeItemIndex1 = 0; removeItemIndex1 < removedItemsLength; removeItemIndex1++) {
index1 = removedItems[removeItemIndex1];
if (matchItems(trimmed1, trimmed2, index1 - commonHead,
index - commonHead, matchContext)) {
// store position move as: [originalValue, newPosition, ARRAY_MOVE]
result['_' + index1].splice(1, 2, index, ARRAY_MOVE);
if (!includeValueOnMove) {
// don't include moved value on diff, to save bytes
result['_' + index1][0] = '';
}
index2 = index;
child = new DiffContext$2(context.left[index1], context.right[index2]);
context.push(child, index2);
removedItems.splice(removeItemIndex1, 1);
isMove = true;
break;
}
}
}
if (!isMove) {
// added
result[index] = [array2[index]];
}
} else {
// match, do inner diff
index1 = seq.indices1[indexOnArray2] + commonHead;
index2 = seq.indices2[indexOnArray2] + commonHead;
child = new DiffContext$2(context.left[index1], context.right[index2]);
context.push(child, index2);
}
}
context.setResult(result).exit();
};
diffFilter$1.filterName = 'arrays';
var compare = {
numerically: function(a, b) {
return a - b;
},
numericallyBy: function(name) {
return function(a, b) {
return a[name] - b[name];
};
}
};
var patchFilter$2 = function nestedPatchFilter(context) {
if (!context.nested) {
return;
}
if (context.delta._t !== 'a') {
return;
}
var index, index1;
var delta = context.delta;
var array = context.left;
// first, separate removals, insertions and modifications
var toRemove = [];
var toInsert = [];
var toModify = [];
for (index in delta) {
if (index !== '_t') {
if (index[0] === '_') {
// removed item from original array
if (delta[index][2] === 0 || delta[index][2] === ARRAY_MOVE) {
toRemove.push(parseInt(index.slice(1), 10));
} else {
throw new Error('only removal or move can be applied at original array indices' +
', invalid diff type: ' + delta[index][2]);
}
} else {
if (delta[index].length === 1) {
// added item at new array
toInsert.push({
index: parseInt(index, 10),
value: delta[index][0]
});
} else {
// modified item at new array
toModify.push({
index: parseInt(index, 10),
delta: delta[index]
});
}
}
}
}
// remove items, in reverse order to avoid sawing our own floor
toRemove = toRemove.sort(compare.numerically);
for (index = toRemove.length - 1; index >= 0; index--) {
index1 = toRemove[index];
var indexDiff = delta['_' + index1];
var removedValue = array.splice(index1, 1)[0];
if (indexDiff[2] === ARRAY_MOVE) {
// reinsert later
toInsert.push({
index: indexDiff[1],
value: removedValue
});
}
}
// insert items, in reverse order to avoid moving our own floor
toInsert = toInsert.sort(compare.numericallyBy('index'));
var toInsertLength = toInsert.length;
for (index = 0; index < toInsertLength; index++) {
var insertion = toInsert[index];
array.splice(insertion.index, 0, insertion.value);
}
// apply modifications
var toModifyLength = toModify.length;
var child;
if (toModifyLength > 0) {
for (index = 0; index < toModifyLength; index++) {
var modification = toModify[index];
child = new PatchContext$2(context.left[modification.index], modification.delta);
context.push(child, modification.index);
}
}
if (!context.children) {
context.setResult(context.left).exit();
return;
}
context.exit();
};
patchFilter$2.filterName = 'arrays';
var collectChildrenPatchFilter$1 = function collectChildrenPatchFilter(context) {
if (!context || !context.children) {
return;
}
if (context.delta._t !== 'a') {
return;
}
var length = context.children.length;
var child;
for (var index = 0; index < length; index++) {
child = context.children[index];
context.left[child.childName] = child.result;
}
context.setResult(context.left).exit();
};
collectChildrenPatchFilter$1.filterName = 'arraysCollectChildren';
var reverseFilter$2 = function arraysReverseFilter(context) {
if (!context.nested) {
if (context.delta[2] === ARRAY_MOVE) {
context.newName = '_' + context.delta[1];
context.setResult([context.delta[0], parseInt(context.childName.substr(1), 10), ARRAY_MOVE]).exit();
}
return;
}
if (context.delta._t !== 'a') {
return;
}
var name, child;
for (name in context.delta) {
if (name === '_t') {
continue;
}
child = new ReverseContext$2(context.delta[name]);
context.push(child, name);
}
context.exit();
};
reverseFilter$2.filterName = 'arrays';
var reverseArrayDeltaIndex = function(delta, index, itemDelta) {
if (typeof index === 'string' && index[0] === '_') {
return parseInt(index.substr(1), 10);
} else if (isArray$2(itemDelta) && itemDelta[2] === 0) {
return '_' + index;
}
var reverseIndex = +index;
for (var deltaIndex in delta) {
var deltaItem = delta[deltaIndex];
if (isArray$2(deltaItem)) {
if (deltaItem[2] === ARRAY_MOVE) {
var moveFromIndex = parseInt(deltaIndex.substr(1), 10);
var moveToIndex = deltaItem[1];
if (moveToIndex === +index) {
return moveFromIndex;
}
if (moveFromIndex <= reverseIndex && moveToIndex > reverseIndex) {
reverseIndex++;
} else if (moveFromIndex >= reverseIndex && moveToIndex < reverseIndex) {
reverseIndex--;
}
} else if (deltaItem[2] === 0) {
var deleteIndex = parseInt(deltaIndex.substr(1), 10);
if (deleteIndex <= reverseIndex) {
reverseIndex++;
}
} else if (deltaItem.length === 1 && deltaIndex <= reverseIndex) {
reverseIndex--;
}
}
}
return reverseIndex;
};
var collectChildrenReverseFilter$1 = function collectChildrenReverseFilter(context) {
if (!context || !context.children) {
return;
}
if (context.delta._t !== 'a') {
return;
}
var length = context.children.length;
var child;
var delta = {
_t: 'a'
};
for (var index = 0; index < length; index++) {
child = context.children[index];
var name = child.newName;
if (typeof name === 'undefined') {
name = reverseArrayDeltaIndex(context.delta, child.childName, child.result);
}
if (delta[name] !== child.result) {
delta[name] = child.result;
}
}
context.setResult(delta).exit();
};
collectChildrenReverseFilter$1.filterName = 'arraysCollectChildren';
var diffFilter_1$1 = diffFilter$1;
var patchFilter_1$2 = patchFilter$2;
var collectChildrenPatchFilter_1$1 = collectChildrenPatchFilter$1;
var reverseFilter_1$2 = reverseFilter$2;
var collectChildrenReverseFilter_1$1 = collectChildrenReverseFilter$1;
var arrays = {
diffFilter: diffFilter_1$1,
patchFilter: patchFilter_1$2,
collectChildrenPatchFilter: collectChildrenPatchFilter_1$1,
reverseFilter: reverseFilter_1$2,
collectChildrenReverseFilter: collectChildrenReverseFilter_1$1
};
var diffFilter$2 = function datesDiffFilter(context) {
if (context.left instanceof Date) {
if (context.right instanceof Date) {
if (context.left.getTime() !== context.right.getTime()) {
context.setResult([context.left, context.right]);
} else {
context.setResult(undefined);
}
} else {
context.setResult([context.left, context.right]);
}
context.exit();
} else if (context.right instanceof Date) {
context.setResult([context.left, context.right]).exit();
}
};
diffFilter$2.filterName = 'dates';
var diffFilter_1$2 = diffFilter$2;
var dates = {
diffFilter: diffFilter_1$2
};
/* global diff_match_patch */
var TEXT_DIFF = 2;
var DEFAULT_MIN_LENGTH = 60;
var cachedDiffPatch = null;
var getDiffMatchPatch = function(required) {
/*jshint camelcase: false */
if (!cachedDiffPatch) {
var instance;
if (typeof diff_match_patch !== 'undefined') {
// already loaded, probably a browser
instance = typeof diff_match_patch === 'function' ?
new diff_match_patch() : new diff_match_patch.diff_match_patch();
} else if (typeof commonjsRequire === 'function') {
try {
var dmpModuleName = 'diff_match_patch_uncompressed';
var dmp = commonjsRequire('../../public/external/' + dmpModuleName);
instance = new dmp.diff_match_patch();
} catch (err) {
instance = null;
}
}
if (!instance) {
if (!required) {
return null;
}
var error = new Error('text diff_match_patch library not found');
error.diff_match_patch_not_found = true;
throw error;
}
cachedDiffPatch = {
diff: function(txt1, txt2) {
return instance.patch_toText(instance.patch_make(txt1, txt2));
},
patch: function(txt1, patch) {
var results = instance.patch_apply(instance.patch_fromText(patch), txt1);
for (var i = 0; i < results[1].length; i++) {
if (!results[1][i]) {
var error = new Error('text patch failed');
error.textPatchFailed = true;
}
}
return results[0];
}
};
}
return cachedDiffPatch;
};
var diffFilter$3 = function textsDiffFilter(context) {
if (context.leftType !== 'string') {
return;
}
var minLength = (context.options && context.options.textDiff &&
context.options.textDiff.minLength) || DEFAULT_MIN_LENGTH;
if (context.left.length < minLength ||
context.right.length < minLength) {
context.setResult([context.left, context.right]).exit();
return;
}
// large text, try to use a text-diff algorithm
var diffMatchPatch = getDiffMatchPatch();
if (!diffMatchPatch) {
// diff-match-patch library not available, fallback to regular string replace
context.setResult([context.left, context.right]).exit();
return;
}
var diff = diffMatchPatch.diff;
context.setResult([diff(context.left, context.right), 0, TEXT_DIFF]).exit();
};
diffFilter$3.filterName = 'texts';
var patchFilter$3 = function textsPatchFilter(context) {
if (context.nested) {
return;
}
if (context.delta[2] !== TEXT_DIFF) {
return;
}
// text-diff, use a text-patch algorithm
var patch = getDiffMatchPatch(true).patch;
context.setResult(patch(context.left, context.delta[0])).exit();
};
patchFilter$3.filterName = 'texts';
var textDeltaReverse = function(delta) {
var i, l, lines, line, lineTmp, header = null,
headerRegex = /^@@ +\-(\d+),(\d+) +\+(\d+),(\d+) +@@$/,
lineHeader;
lines = delta.split('\n');
for (i = 0, l = lines.length; i < l; i++) {
line = lines[i];
var lineStart = line.slice(0, 1);
if (lineStart === '@') {
header = headerRegex.exec(line);
lineHeader = i;
// fix header
lines[lineHeader] = '@@ -' + header[3] + ',' + header[4] + ' +' + header[1] + ',' + header[2] + ' @@';
} else if (lineStart === '+') {
lines[i] = '-' + lines[i].slice(1);
if (lines[i - 1].slice(0, 1) === '+') {
// swap lines to keep default order (-+)
lineTmp = lines[i];
lines[i] = lines[i - 1];
lines[i - 1] = lineTmp;
}
} else if (lineStart === '-') {
lines[i] = '+' + lines[i].slice(1);
}
}
return lines.join('\n');
};
var reverseFilter$3 = function textsReverseFilter(context) {
if (context.nested) {
return;
}
if (context.delta[2] !== TEXT_DIFF) {
return;
}
// text-diff, use a text-diff algorithm
context.setResult([textDeltaReverse(context.delta[0]), 0, TEXT_DIFF]).exit();
};
reverseFilter$3.filterName = 'texts';
var diffFilter_1$3 = diffFilter$3;
var patchFilter_1$3 = patchFilter$3;
var reverseFilter_1$3 = reverseFilter$3;
var texts = {
diffFilter: diffFilter_1$3,
patchFilter: patchFilter_1$3,
reverseFilter: reverseFilter_1$3
};
var Processor$1 = processor.Processor;
var Pipe$2 = pipe.Pipe;
var DiffContext$3 = diff.DiffContext;
var PatchContext$3 = patch.PatchContext;
var ReverseContext$3 = reverse$2.ReverseContext;
var DiffPatcher = function DiffPatcher(options) {
this.processor = new Processor$1(options);
this.processor.pipe(new Pipe$2('diff').append(
nested.collectChildrenDiffFilter,
trivial.diffFilter,
dates.diffFilter,
texts.diffFilter,
nested.objectsDiffFilter,
arrays.diffFilter
).shouldHaveResult());
this.processor.pipe(new Pipe$2('patch').append(
nested.collectChildrenPatchFilter,
arrays.collectChildrenPatchFilter,
trivial.patchFilter,
texts.patchFilter,
nested.patchFilter,
arrays.patchFilter
).shouldHaveResult());
this.processor.pipe(new Pipe$2('reverse').append(
nested.collectChildrenReverseFilter,
arrays.collectChildrenReverseFilter,
trivial.reverseFilter,
texts.reverseFilter,
nested.reverseFilter,
arrays.reverseFilter
).shouldHaveResult());
};
DiffPatcher.prototype.options = function() {
return this.processor.options.apply(this.processor, arguments);
};
DiffPatcher.prototype.diff = function(left, right) {
return this.processor.process(new DiffContext$3(left, right));
};
DiffPatcher.prototype.patch = function(left, delta) {
return this.processor.process(new PatchContext$3(left, delta));
};
DiffPatcher.prototype.reverse = function(delta) {
return this.processor.process(new ReverseContext$3(delta));
};
DiffPatcher.prototype.unpatch = function(right, delta) {
return this.patch(right, this.reverse(delta));
};
DiffPatcher.prototype.clone = function(value) {
return clone_1(value);
};
var DiffPatcher_1 = DiffPatcher;
var diffpatcher = {
DiffPatcher: DiffPatcher_1
};
// use as 2nd parameter for JSON.parse to revive Date instances
var dateReviver = function dateReviver(key, value) {
var parts;
if (typeof value === 'string') {
parts = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d*))?(Z|([+\-])(\d{2}):(\d{2}))$/.exec(value);
if (parts) {
return new Date(Date.UTC(+parts[1], +parts[2] - 1, +parts[3], +parts[4], +parts[5], +parts[6], +(parts[7] || 0)));
}
}
return value;
};
var main = createCommonjsModule(function (module, exports) {
var DiffPatcher = diffpatcher.DiffPatcher;
exports.DiffPatcher = DiffPatcher;
exports.create = function(options){
return new DiffPatcher(options);
};
exports.dateReviver = dateReviver;
var defaultInstance;
exports.diff = function() {
if (!defaultInstance) {
defaultInstance = new DiffPatcher();
}
return defaultInstance.diff.apply(defaultInstance, arguments);
};
exports.patch = function() {
if (!defaultInstance) {
defaultInstance = new DiffPatcher();
}
return defaultInstance.patch.apply(defaultInstance, arguments);
};
exports.unpatch = function() {
if (!defaultInstance) {
defaultInstance = new DiffPatcher();
}
return defaultInstance.unpatch.apply(defaultInstance, arguments);
};
exports.reverse = function() {
if (!defaultInstance) {
defaultInstance = new DiffPatcher();
}
return defaultInstance.reverse.apply(defaultInstance, arguments);
};
exports.clone = function() {
if (!defaultInstance) {
defaultInstance = new DiffPatcher();
}
return defaultInstance.clone.apply(defaultInstance, arguments);
};
if (environment.isBrowser) {
exports.homepage = '{{package-homepage}}';
exports.version = '{{package-version}}';
} else {
var packageInfo = commonjsRequire();
exports.homepage = packageInfo.homepage;
exports.version = packageInfo.version;
var formatters = commonjsRequire();
exports.formatters = formatters;
// shortcut for console
exports.console = formatters.console;
}
});
var packing = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var CloneError, clone, jsondiffpatch, diff, out$ = exports || commonjsGlobal, toString$ = {}.toString;
out$.pack = pack;
function pack(x){
return JSON.stringify(x, function(key, val){
if (toString$.call(val).slice(8, -1) === 'Function') {
return val + '';
}
return val;
});
}
out$.unpack = unpack;
function unpack(x){
return JSON.parse(x);
}
out$.CloneError = CloneError = (function(superclass){
var prototype = extend$((import$(CloneError, superclass).displayName = 'CloneError', CloneError), superclass).prototype;
function CloneError(message, argument){
this.message = message;
this.argument = argument;
CloneError.superclass.apply(this, arguments);
Error.captureStackTrace(this, CloneError);
}
return CloneError;
}(Error));
out$.clone = clone = function(x){
var ref$;
if ((ref$ = toString$.call(x).slice(8, -1)) === 'Object' || ref$ === 'Array') {
return unpack(pack(x));
} else {
throw new CloneError("argument must be object or array, supplied: " + pack(x), x);
}
};
jsondiffpatch = main;
out$.diff = diff = function(a, b){
return jsondiffpatch.diff(a, b);
};
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
var merge_1 = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var pack, basedOn, tests, start, testCount, i$, name, test, ref$, result, expected, out$ = exports || commonjsGlobal, toString$ = {}.toString;
pack = packing.pack;
/** /
export merge = (obj1, obj2) ->
if (typeof! obj1 is \Array) and (typeof! obj2 is \Array)
for i in obj2
try
for j in obj1
throw if pack(i) is pack(j)
# append if item is not found in first one
obj1.push i
return obj1
else
for p of obj2
try
throw if typeof! obj2[p] isnt \Object
throw if typeof! obj1[p] isnt \Object
# go on if and only if right hand is object
obj1[p] `merge` obj2[p]
catch
if Array.isArray obj1[p]
# array, merge with current one
for i, j of obj2[p]
try
for a in obj1[p]
throw if pack(a) is pack(j)
obj1[p].push j
else if obj2[p] isnt void
obj1[p] = obj2[p]
else
delete obj1[p]
obj1
/**/
out$.merge = merge;
function merge(obj1, obj2){
var i$, len$, i, j$, len1$, j, p, tObj1, ref$;
if (toString$.call(obj1).slice(8, -1) === 'Array' && toString$.call(obj2).slice(8, -1) === 'Array') {
for (i$ = 0, len$ = obj2.length; i$ < len$; ++i$) {
i = obj2[i$];
try {
for (j$ = 0, len1$ = obj1.length; j$ < len1$; ++j$) {
j = obj1[j$];
if (pack(i) === pack(j)) {
throw null;
}
}
obj1.push(i);
} catch (e$) {}
}
return obj1;
} else {
for (p in obj2) {
tObj1 = toString$.call(obj1[p]).slice(8, -1);
if ((ref$ = toString$.call(obj2[p]).slice(8, -1)) === 'Object' || ref$ === 'Array') {
if (tObj1 === 'Object' || tObj1 === 'Array') {
merge(obj1[p], obj2[p]);
} else {
obj1[p] = obj2[p];
}
} else {
if (obj2[p] !== void 8) {
obj1[p] = obj2[p];
} else {
delete obj1[p];
}
}
}
return obj1;
}
}
/* */
out$.mergeAll = mergeAll;
function mergeAll(obj1){
var sources, res$, i$, to$, len$, obj2;
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
sources = res$;
for (i$ = 0, len$ = sources.length; i$ < len$; ++i$) {
obj2 = sources[i$];
merge(obj1, obj2);
}
return obj1;
}
out$.basedOn = basedOn = function(a, b){
return merge(b || {}, a || {});
};
tests = {
'simple merge': function(){
var a, b, result, expected;
a = {
a: 1,
b: 2
};
b = {
c: 5
};
result = merge(a, b);
expected = {
a: 1,
b: 2,
c: 5
};
return {
result: result,
expected: expected
};
},
'simple merge2': function(){
var a, b, result, expected;
a = {
a: 1,
b: 2,
c: {
ca: 1,
cb: 2
}
};
b = {
c: {
cb: 5
}
};
result = merge(a, b);
expected = {
a: 1,
b: 2,
c: {
ca: 1,
cb: 5
}
};
return {
result: result,
expected: expected
};
},
'merge lists': function(){
var a, b, result, expected;
a = {
a: 1,
b: 2,
c: [1, 2]
};
b = {
b: 8,
c: [1, 4]
};
result = merge(a, b);
expected = {
a: 1,
b: 8,
c: [1, 2, 4]
};
return {
result: result,
expected: expected
};
},
'merge lists2': function(){
var a, b, result, expected;
a = {
a: 1,
b: 2,
c: ['hello', 'world']
};
b = {
b: 8,
c: ['hi', 'world']
};
result = merge(a, b);
expected = {
a: 1,
b: 8,
c: ['hello', 'world', 'hi']
};
return {
result: result,
expected: expected
};
},
'merge lists of objects': function(){
var a, b, result, expected;
a = {
a: 1,
b: 2,
c: [
{
a: 1,
b: 2
}, {
a: 3,
b: 4
}
]
};
b = {
b: 8,
c: [
{
a: 1,
b: 2
}, {
a: 5,
b: 6
}
]
};
result = merge(a, b);
expected = {
a: 1,
b: 8,
c: [
{
a: 1,
b: 2
}, {
a: 3,
b: 4
}, {
a: 5,
b: 6
}
]
};
return {
result: result,
expected: expected
};
},
'merge lists of objects2': function(){
var x, y, result, expected;
x = [
{
a: 1,
b: 2
}, {
a: 3,
b: 4
}
];
y = [
{
a: 5,
b: 6
}, {
a: 7,
b: 8
}, {
a: 9,
b: 10
}, {
a: 11,
b: 12
}
];
result = merge(x, y);
expected = [
{
a: 1,
b: 2
}, {
a: 3,
b: 4
}, {
a: 5,
b: 6
}, {
a: 7,
b: 8
}, {
a: 9,
b: 10
}, {
a: 11,
b: 12
}
];
return {
result: result,
expected: expected
};
},
'deleting something': function(){
var a, result, expected;
a = {
a: 1,
b: 2,
c: {
ca: 11,
cb: 2
}
};
result = merge(a, {
c: void 8
});
expected = {
a: 1,
b: 2
};
return {
result: result,
expected: expected
};
},
'force overwrite': function(){
var a, b, result, expected;
a = {
a: 1,
b: 2,
c: {
ca: 11,
cb: 2
}
};
b = {
c: {
cb: 5
}
};
result = mergeAll(a, {
c: void 8
}, b);
expected = {
a: 1,
b: 2,
c: {
cb: 5
}
};
return {
result: result,
expected: expected
};
},
'merging object with functions': function(){
var a, b, result, expected;
a = {
a: 1,
b: 2,
c: {
ca: 11,
cb: 2
}
};
b = {
c: {
cb: function(x){
return x;
}
}
};
result = merge(a, b);
expected = {
a: 1,
b: 2,
c: {
ca: 11,
cb: function(x){
return x;
}
}
};
return {
result: result,
expected: expected
};
},
'Field or method does not already exist, and cant create it on String': function(){
var a, b, result, expected;
a = {
a: 1,
b: 2,
c: "hey"
};
b = {
c: {
cb: "aa"
}
};
result = merge(a, b);
expected = {
a: 1,
b: 2,
c: {
cb: "aa"
}
};
return {
result: result,
expected: expected
};
}
};
start = Date.now();
testCount = 1;
for (i$ = 0; i$ <= testCount; ++i$) {
for (name in tests) {
test = tests[name];
ref$ = test(), result = ref$.result, expected = ref$.expected;
if (pack(expected) !== pack(result)) {
console.log("merge test failed test: ", name);
console.log("EXPECTED: ", expected);
console.log("RESULT : ", result);
throw "Test failed in merge.ls!, test: " + name;
}
}
}
if (testCount > 1) {
console.log("Merge tests took: " + (Date.now() - start) + " milliseconds...");
}
});
var ipToHex_1 = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var reverse, hex, ipToHex, out$ = exports || commonjsGlobal;
reverse = lib$1.reverse;
out$.hex = hex = function(n){
return n.toString(16).toUpperCase();
};
out$.ipToHex = ipToHex = function(ip){
var i, result, i$, ref$, len$, part;
i = 0;
result = 0;
for (i$ = 0, len$ = (ref$ = reverse(ip.split('.'))).length; i$ < len$; ++i$) {
part = ref$[i$];
result += part * Math.pow(256, i++);
}
return hex(result);
};
});
// Generated by LiveScript 1.6.0
var Logger, EventEmitter, sleep, ref$, pack, unpack, clone$1, diff$1, merge, basedOn, ipToHex, hex;
Logger = logger.Logger;
EventEmitter = eventEmitter.EventEmitter;
sleep = sleep_1.sleep;
ref$ = packing, pack = ref$.pack, unpack = ref$.unpack, clone$1 = ref$.clone, diff$1 = ref$.diff;
ref$ = merge_1, merge = ref$.merge, basedOn = ref$.basedOn;
ref$ = ipToHex_1, ipToHex = ref$.ipToHex, hex = ref$.hex;
var lib$2 = {
Logger: Logger,
EventEmitter: EventEmitter,
sleep: sleep,
pack: pack,
unpack: unpack,
clone: clone$1,
diff: diff$1,
merge: merge,
basedOn: basedOn,
ipToHex: ipToHex,
hex: hex
};
var debugTools = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var brief, out$ = exports || commonjsGlobal;
out$.brief = brief = function(msg){
var s, k, v, dataStr;
s = {};
for (k in msg) {
v = msg[k];
if (k === 'data') {
continue;
}
s[k] = v;
}
if (msg.data) {
dataStr = JSON.stringify(msg.data);
s.data = dataStr.length > 70
? "..." + dataStr.length + "..."
: msg.data;
}
if (msg.permissions) {
s.permissions = "..." + msg.permissions.length + "...";
}
return s;
};
});
var topicMatch_1 = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, max, split, splitDot, topicMatch, testTopicMatch, out$ = exports || commonjsGlobal, toString$ = {}.toString;
ref$ = lib$1, max = ref$.max, split = ref$.split;
splitDot = split('.');
out$.topicMatch = topicMatch = function(topics, keypaths, opts){
var asArray, i$, ref$, len$, topic, j$, ref1$, len1$, keypath, topicArr, keypathArr, e, k$, ref2$, len2$, index, topicPart, keypathPart;
opts == null && (opts = {});
if (!(topics != null && keypaths != null)) {
return false;
}
asArray = function(x){
if (toString$.call(x).slice(8, -1) === 'String') {
return x.trim().split(' ');
} else {
return x;
}
};
for (i$ = 0, len$ = (ref$ = asArray(
topics)).length; i$ < len$; ++i$) {
topic = ref$[i$];
for (j$ = 0, len1$ = (ref1$ = asArray(
keypaths)).length; j$ < len1$; ++j$) {
keypath = ref1$[j$];
try {
if ('**' === topic || '**' === keypath) {
if (opts.debug) {
console.log("topic is **, immediately matches with anything");
}
return true;
}
try {
topicArr = splitDot(topic);
keypathArr = splitDot(keypath);
} catch (e$) {
e = e$;
console.error("both topic and keypath should be string.");
return false;
}
for (k$ = 0, len2$ = (ref2$ = (fn$())).length; k$ < len2$; ++k$) {
index = ref2$[k$];
topicPart = (fn1$());
keypathPart = (fn2$());
if (opts.debug) {
console.log("topic-part: " + topicPart + ", keypath-part: " + keypathPart);
}
if ('*' === keypathPart || '*' === topicPart) {
if (undefined === keypathPart || undefined === topicPart) {
if (opts.debug) {
console.log("returning false because there is no command to look for match");
}
throw null;
}
continue;
}
if ('**' !== keypathPart && '**' !== topicPart) {
if (undefined === keypathPart || undefined === topicPart) {
if (opts.debug) {
console.log("returning false because there is no command to look for match");
}
throw null;
}
}
if ('**' === keypathPart || '**' === topicPart) {
if (opts.debug) {
console.log("returning true because '**' will match with anything.");
}
return true;
}
if (topicPart !== keypathPart) {
throw "not matching";
}
}
if (opts.debug) {
console.log("no condition broke the match.");
}
return true;
} catch (e$) {}
}
}
return false;
function fn$(){
var i$, to$, results$ = [];
for (i$ = 0, to$ = max(topicArr.length, keypathArr.length); i$ < to$; ++i$) {
results$.push(i$);
}
return results$;
}
function fn1$(){
try {
return topicArr[index];
} catch (e$) {}
}
function fn2$(){
try {
return keypathArr[index];
} catch (e$) {}
}
};
(testTopicMatch = function(){
/*
** will match with anything, including null
*/
var examples, num, example, result, results$ = [];
examples = [
{
topic: "foo.bar",
keypath: "foo.*",
expected: true
}, {
topic: "*.bar",
keypath: "foo.*",
expected: true
}, {
topic: "foo.bar",
keypath: "baz.bar",
expected: false
}, {
topic: "foo.bar",
keypath: "baz.bar foo.*",
expected: true
}, {
topic: "foo.bar",
keypath: "foo.*.*",
expected: false
}, {
topic: "foo.*.bar",
keypath: "foo.*",
expected: false
}, {
topic: "foo.**",
keypath: "foo",
expected: true
}, {
topic: "@foo",
keypath: ['@foo.**', '@bar.**'],
expected: true
}, {
topic: ['@bar.**', '@foo-bar.**'],
keypath: "@foo-bar",
expected: true
}, {
topic: "foo.*.**",
keypath: "foo.bar.baz",
expected: true
}, {
topic: "foo.*.**",
keypath: "foo.bar",
expected: true
}, {
topic: "foo.*.**",
keypath: "foo.bar.baz.qux",
expected: true
}, {
topic: "foo.**",
keypath: "foo.bar.baz.qux",
expected: true
}, {
topic: "foo.**",
keypath: "*.bar.baz.qux",
expected: true
}, {
topic: "foo.bar",
keypath: "*.*",
expected: true
}, {
topic: "foo.bar",
keypath: "*",
expected: false
}, {
topic: "*",
keypath: "foo.bar",
expected: false
}, {
topic: "foo.bar",
keypath: "**",
expected: true
}, {
topic: "*",
keypath: "*",
expected: true
}, {
topic: "**",
keypath: "*",
expected: true
}, {
topic: "*",
keypath: "**",
expected: true
}, {
topic: "**",
keypath: "**",
expected: true
}, {
topic: "*.*",
keypath: "**",
expected: true
}, {
topic: "**",
keypath: "*.*",
expected: true
}
];
for (num in examples) {
example = examples[num];
result = topicMatch(example.topic, example.keypath);
if (result !== example.expected) {
console.log("Test failed in #" + num + ", re-running in debug mode: ");
console.log("comparing if '" + example.topic + "' matches with '" + example.keypath + "' expecting: " + example.expected);
console.log("---------------------------------------------------");
topicMatch(example.topic, example.keypath, {
debug: true
});
console.log("---------------------------------------------------");
results$.push(process.exit(1));
}
}
return results$;
})();
});
var actorManager = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, reject, find, routeMatch, Logger, sleep, hex, brief, ActorManager, out$ = exports || commonjsGlobal, slice$ = [].slice, arrayFrom$ = Array.from || function(x){return slice$.call(x);};
ref$ = lib$1, reject = ref$.reject, find = ref$.find;
routeMatch = topicMatch_1.topicMatch;
ref$ = lib$2, Logger = ref$.Logger, sleep = ref$.sleep, hex = ref$.hex;
brief = debugTools.brief;
out$.ActorManager = ActorManager = (function(){
ActorManager.displayName = 'ActorManager';
var constructor = ActorManager;
ActorManager.instance = null;
function ActorManager(){
if (constructor.instance) {
return constructor.instance;
}
constructor.instance = this;
this.actorUid = 1;
this.actors = [];
this.managerId = hex(
Date.now());
this.log = new Logger("ActorMan." + this.managerId);
}
ActorManager.prototype.nextActorId = function(){
return "a" + (this.actorUid++) + "-" + this.managerId;
};
ActorManager.prototype.registerActor = function(actor){
if (!find(function(it){
return it.id === actor.id;
}, this.actors)) {
return this.actors.push(actor);
}
};
ActorManager.prototype.findActor = function(id){
if (!id) {
throw 'id is required!';
}
return find(function(it){
return it.id === id;
}, this.actors);
};
ActorManager.prototype.deregisterActor = function(actor){
return this.actors = reject(function(it){
return it.id === actor.id;
}, this.actors);
};
ActorManager.prototype.distribute = function(msg, sender){
var dueDate, i$, ref$, len$, actor, that, delay, results$ = [];
if (msg.debug) {
this.log.debug("Distributing message: ", brief(msg));
}
dueDate = Date.now();
for (i$ = 0, len$ = (ref$ = this.actors).length; i$ < len$; ++i$) {
actor = ref$[i$];
if (actor.id !== sender) {
if (routeMatch(msg.to, actor.subscriptions)) {
if (that = msg._exclude) {
if (that === actor.id) {
continue;
}
delete msg._exclude;
}
delay = Date.now() - dueDate;
if (delay > 10) {
this.log.warn("System load is high? Message is delivered after " + delay + "ms");
}
results$.push(actor._inbox(msg));
} else {
results$.push(null);
}
}
}
return results$;
};
ActorManager.prototype.kill = function(){
var args, res$, i$, to$, ref$, len$, actor, results$ = [];
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
for (i$ = 0, len$ = (ref$ = this.actors).length; i$ < len$; ++i$) {
actor = ref$[i$];
results$.push(actor.trigger.apply(actor, ['kill'].concat(arrayFrom$(args))));
}
return results$;
};
return ActorManager;
}());
});
// Generated by LiveScript 1.6.0
var ref$$1, sleep$1, Logger$1, getFormattedDate, slice$ = [].slice, arrayFrom$ = Array.from || function(x){return slice$.call(x);};
try {
ref$$1 = lib$2, sleep$1 = ref$$1.sleep, Logger$1 = ref$$1.Logger;
} catch (e$) {
sleep$1 = function(ms, f){
return setTimeout(f, ms);
};
getFormattedDate = function(){
var d;
d = new Date;
return d.getFullYear() + "-" + (d.getMonth() + 1) + "-" + d.getDate() + " " + d.getHours() + ":" + d.getMinutes() + ":" + d.getSeconds() + "." + d.getMilliseconds();
};
Logger$1 = (function(){
Logger.displayName = 'Logger';
function Logger(name){
this.name = name;
}
Logger.prototype.log = function(){
return console.log.apply(console, ['[', getFormattedDate(), ']', this.name + ":"].concat(arrayFrom$(arguments)));
};
return Logger;
}());
}
var deps = {
sleep: sleep$1,
Logger: Logger$1
};
var signal = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, sleep, Logger, isItNaN, Signal, out$ = exports || commonjsGlobal, toString$ = {}.toString, slice$ = [].slice, arrayFrom$ = Array.from || function(x){return slice$.call(x);};
ref$ = deps, sleep = ref$.sleep, Logger = ref$.Logger;
isItNaN = lib$1.isItNaN;
out$.Signal = Signal = (function(){
Signal.displayName = 'Signal';
function Signal(opts){
opts == null && (opts = {});
if (opts.debug) {
this.debug = true;
}
this.name = opts.name || 'Signal';
this.log = new Logger(this.name);
this.response = [];
this.callback = {
ctx: null,
handler: null
};
if (this.debug) {
this.log.debug("Initialized new signal.");
}
this.reusable = opts.reusable;
this.reset();
}
Signal.prototype.cancel = function(){
return this.reset();
};
Signal.prototype.reset = function(){
if (!this.reusable) {
delete this.callback.handler;
delete this.callback.ctx;
}
this.shouldRun = false;
try {
clearTimeout(this.timer);
} catch (e$) {}
this.timer = void 8;
return this.skipNext = false;
};
Object.defineProperty(Signal.prototype, 'waiting', {
get: function(){
var ref$;
return toString$.call((ref$ = this.callback) != null ? ref$.handler : void 8).slice(8, -1) === 'Function';
},
configurable: true,
enumerable: true
});
Signal.prototype.fire = function(error){
var ref$, params, ref1$, handler, ctx, t0, err, this$ = this;
if (toString$.call((ref$ = this.callback) != null ? ref$.handler : void 8).slice(8, -1) !== 'Function') {
return;
}
params = !this.error
? this.response
: [];
ref1$ = this.callback, handler = ref1$.handler, ctx = ref1$.ctx;
t0 = Date.now();
err = this.error;
return setImmediate(function(){
this$.reset();
handler.call.apply(handler, [ctx, err].concat(arrayFrom$(params)));
if (this$.debug) {
this$.log.debug("...signal has been fired.");
}
if (Date.now() - t0 > 100) {
return this$.log.warn("System seems busy now? Actual firing took place after " + (Date.now() - t0) + "ms");
}
});
};
Signal.prototype.wait = function(timeout, callback){
if (toString$.call(timeout).slice(8, -1) === 'Function') {
callback = timeout;
timeout = 0;
}
if (this.waiting) {
this.log.error("Can not wait over and over, skipping this one.");
return;
}
this.callback = {
ctx: this,
handler: callback
};
if (!isItNaN(timeout)) {
if (timeout > 0) {
this.timeout = timeout;
if (this.debug) {
this.log.info("Heartbeating! timeout: " + this.timeout);
}
this.heartbeat();
}
}
if (this.shouldRun) {
return this.fire();
}
};
Signal.prototype.skipNextGo = function(){
return this.skipNext = true;
};
Signal.prototype.clear = function(){
return this.shouldRun = false;
};
Signal.prototype.go = function(err){
var args, res$, i$, to$;
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
if (this.skipNext) {
this.skipNext = false;
return;
}
this.shouldRun = true;
this.response = args;
this.error = err;
if (this.waiting) {
return this.fire();
}
};
Signal.prototype.heartbeat = function(duration){
var this$ = this;
if (duration > 0) {
this.timeout = duration;
}
try {
clearTimeout(this.timer);
} catch (e$) {}
return this.timer = sleep(this.timeout, function(){
if (this$.waiting) {
this$.shouldRun = true;
if (this$.debug) {
this$.log.log("firing with timeout! timeout: " + this$.timeout);
}
if (toString$.call(this$.timeoutHandler).slice(8, -1) === 'Function') {
return this$.timeoutHandler();
} else {
this$.error = 'TIMEOUT';
return this$.fire();
}
}
});
};
Signal.prototype.onTimeout = function(callback){
return this.timeoutHandler = callback;
};
return Signal;
}());
});
var signalBranch = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var Signal, SignalBranch, out$ = exports || commonjsGlobal;
Signal = signal.Signal;
out$.SignalBranch = SignalBranch = (function(){
SignalBranch.displayName = 'SignalBranch';
function SignalBranch(opts){
opts == null && (opts = {});
this.timeout = opts.timeout || -1;
this.count = 0;
this.main = new Signal;
this.signals = [];
this.error = null;
this.branches = [];
}
SignalBranch.prototype.cancel = function(){
var i, results$ = [];
this.main.cancel();
this.main = null;
for (i in this.signals) {
this.signals[i].cancel();
results$.push(this.signals[i] = null);
}
return results$;
};
SignalBranch.prototype.add = function(opts){
var timeout, name, signal, this$ = this;
timeout = (opts != null ? opts.timeout : void 8) || this.timeout;
name = (opts != null ? opts.name : void 8) || this.count + "";
signal = new Signal({
name: name
});
this.signals.push(signal);
this.count++;
signal.wait(timeout, function(err){
var that;
if (that = err) {
this$.error = that;
}
if (--this$.count === 0) {
return this$.main.go(this$.error);
}
});
return signal;
};
SignalBranch.prototype.joined = function(callback){
var err, this$ = this;
if (this.count === 0) {
this.main.go(err = null);
}
return this.main.wait(this.timeout, function(err){
var i$, x$, ref$, len$;
for (i$ = 0, len$ = (ref$ = this$.signals).length; i$ < len$; ++i$) {
x$ = ref$[i$];
if (x$.error) {
if (!err) {
err = {};
}
err.signals = true;
}
x$.clear();
}
return callback(err, this$.signals);
});
};
return SignalBranch;
}());
});
// Generated by LiveScript 1.6.0
var Signal$1, SignalBranch;
Signal$1 = signal.Signal;
SignalBranch = signalBranch.SignalBranch;
var signal$1 = {
Signal: Signal$1,
SignalBranch: SignalBranch
};
commonjsGlobal.Signal = Signal$1;
commonjsGlobal.SignalBranch = SignalBranch;
var request = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var merge, out$ = exports || commonjsGlobal, toString$ = {}.toString;
merge = lib$2.merge;
import$(out$, {
sendRequest: function(opts, data, callback){
var meta, timeout, that, seq, requestId, enveloped, partHandler, completeHandler, lastPartSent, regPartHandlers, responseSignal, error, message, mergeMethodManual, requestDate, this$ = this;
meta = {};
timeout = 5000;
if (toString$.call(opts).slice(8, -1) === 'String') {
meta.to = opts;
} else {
meta.to = opts.topic || opts.route || opts.to;
if (that = opts.timeout) {
timeout = that;
}
}
seq = this.msgSeq++;
requestId = seq + "";
meta.part = this.getNextPartId(opts.part, requestId);
if (opts.debug) {
meta.debug = true;
}
if (toString$.call(data).slice(8, -1) === 'Function') {
callback = data;
data = null;
}
enveloped = (meta.from = this.me, meta.seq = seq, meta.data = data, meta.req = true, meta.timestamp = Date.now(), meta);
this.subscribe(meta.to);
partHandler = function(){};
completeHandler = function(){};
lastPartSent = false;
regPartHandlers = {
onPart: function(func){
return partHandler = func;
},
onReceive: function(func){
return completeHandler = func;
},
sendPart: function(data, lastPart){
var msg;
lastPart == null && (lastPart = true);
if (lastPartSent) {
this$.log.err("Last part is already sent.");
return;
}
msg = (enveloped.data = data, enveloped);
msg.part = this$.getNextPartId(!lastPart, requestId);
this$.log.log("Sending next part with id: ", msg.part);
this$.sendEnveloped(msg);
if (lastPart) {
return lastPartSent = true;
}
}
};
responseSignal = new Signal({
debug: enveloped.debug,
name: "ReqSig:" + enveloped.seq
});
this.requestQueue[requestId] = responseSignal;
error = null;
message = {};
mergeMethodManual = false;
requestDate = Date.now();
(function lo(op){
responseSignal.clear();
return responseSignal.wait(timeout, function(err, msg){
if (err) {
error = err;
return op();
} else {
partHandler(msg);
if (requestDate != null) {
if (requestDate + 200 < Date.now()) {
this$.log.debug("First response is too late for seq:" + enveloped.seq + " latency:" + (Date.now() - requestDate) + "ms, req: ", enveloped);
}
requestDate = undefined;
}
if (msg.timeout) {
if (enveloped.debug) {
this$.log.debug("New timeout is set from target: " + msg.timeout + "ms for request seq: " + enveloped.seq);
}
timeout = msg.timeout;
}
if (msg.merge != null && msg.merge === false) {
mergeMethodManual = true;
}
if (!mergeMethodManual) {
merge(message, msg);
}
if (msg.part == null || msg.part < 0) {
/*
if not msg.part?
@log.debug "this was a single part response."
else
@log.debug "this was the last part of the message chain."
*/
return op();
}
}
return lo(op);
});
})(function(){
if (this$._state.killFinished) {
this$.log.warn("Got response activity after killed?", error, message);
return;
}
if (!callback) {
if (error === 'TIMEOUT') {
this$.log.warn("Request is timed out. Timeout was " + timeout + "ms, seq: " + enveloped.seq + ". req was:", brief(enveloped));
}
}
this$.unsubscribe(meta.to);
delete this$.requestQueue[requestId];
if (mergeMethodManual) {
error = "Merge method is set to manual. We can't concat the messages.";
}
completeHandler(error, message);
if (toString$.call(callback).slice(8, -1) === 'Function') {
return callback(error, message);
}
});
if (meta.debug) {
this.log.debug("Sending request seq: " + enveloped.seq);
}
this.sendEnveloped(enveloped);
return regPartHandlers;
}
});
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
var actor = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, sleep, pack, EventEmitter, Logger, merge, brief, ActorManager, split, flatten, keys, unique, isItNaN, routeMatch, request$1, TopicTypeError, LAST_PART, messageOwner, Actor, A1, A2, out$ = exports || commonjsGlobal, toString$ = {}.toString;
ref$ = lib$2, sleep = ref$.sleep, pack = ref$.pack, EventEmitter = ref$.EventEmitter, Logger = ref$.Logger, merge = ref$.merge;
brief = debugTools.brief;
ActorManager = actorManager.ActorManager;
ref$ = lib$1, split = ref$.split, flatten = ref$.flatten, keys = ref$.keys, unique = ref$.unique, isItNaN = ref$.isItNaN;
routeMatch = topicMatch_1.topicMatch;
request$1 = request;
out$.TopicTypeError = TopicTypeError = (function(superclass){
var prototype = extend$((import$(TopicTypeError, superclass).displayName = 'TopicTypeError', TopicTypeError), superclass).prototype;
function TopicTypeError(message, route){
this.message = message;
this.route = route;
TopicTypeError.superclass.apply(this, arguments);
Error.captureStackTrace(this, TopicTypeError);
this.type = 'TopicTypeError';
}
return TopicTypeError;
}(Error));
LAST_PART = -1;
messageOwner = function(it){
var ref$;
return (ref$ = it.to.split('.'))[ref$.length - 1];
};
out$.Actor = Actor = (function(superclass){
var prototype = extend$((import$(Actor, superclass).displayName = 'Actor', Actor), superclass).prototype;
importAll$(prototype, arguments[1]);
function Actor(name, opts){
this.send = bind$(this, 'send', prototype);
Actor.superclass.call(this);
this.mgr = new ActorManager();
this.id = this.mgr.nextActorId();
this.me = this.id;
this.name = name || this.id;
this.log = new Logger(this.name);
this.msgSeq = 0;
this.subscriptions = [this.me];
this.requestQueue = {};
this._route_handlers = {};
this._state = {};
this._partial_msg_states = {};
this._request_concat_cache = {};
this._last_login = 0;
this.mgr.registerActor(this);
if (toString$.call(this.action).slice(8, -1) === 'Function') {
this.action();
}
}
Actor.prototype.setName = function(name){
this.name = name;
return this.log.name = name;
};
Actor.prototype.subscribe = function(routes){
var i$, ref$, len$, route, results$ = [];
for (i$ = 0, len$ = (ref$ = unique(flatten([routes]))).length; i$ < len$; ++i$) {
route = ref$[i$];
results$.push(this.subscriptions.push(route));
}
return results$;
};
Actor.prototype.unsubscribe = function(route){
return this.subscriptions.splice(this.subscriptions.indexOf(route), 1);
};
Actor.prototype.send = function(route, data){
var enveloped;
if (toString$.call(route).slice(8, -1) === 'String') {
route = {
to: route
};
}
enveloped = import$({
from: this.me,
data: data,
seq: this.msgSeq++
}, route);
return this.sendEnveloped(enveloped);
};
Actor.prototype.getNextPartId = function(autoinc, msgId){
var nextPart;
nextPart = undefined;
if (autoinc) {
if (this._partial_msg_states[msgId] == null) {
this._partial_msg_states[msgId] = 0;
}
nextPart = this._partial_msg_states[msgId]++;
} else {
if (this._partial_msg_states[msgId] != null) {
delete this._partial_msg_states[msgId];
nextPart = LAST_PART;
}
}
return nextPart;
};
Actor.prototype.sendResponse = function(req, meta, data){
var enveloped;
if (!req.req) {
this.log.err("No request is required, doing nothing.");
debugger;
return;
}
if (toString$.call(data).slice(8, -1) === 'Undefined') {
data = meta;
meta = {};
}
meta.part = this.getNextPartId(meta.part, req.from + "." + req.seq);
enveloped = import$({
from: this.me,
to: req.from,
seq: this.msgSeq++,
data: data,
re: req.seq,
resToken: req.resToken,
debug: req.debug
}, meta);
if (req.debug || meta.debug) {
this.log.debug("sending the response for request: ", brief(enveloped));
}
return this.sendEnveloped(enveloped);
};
Actor.prototype._inbox = function(msg){
var this$ = this;
if (this.debug || msg.debug) {
this.log.debug("Got msg to inbox: ", brief(msg));
}
if (this._state.killFinished) {
debugger;
}
msg.permissions = msg.permissions || [];
return setImmediate(function(){
var ref$;
if (msg.re != null && messageOwner(msg) === this$.me) {
if (this$.requestQueue[msg.re]) {
if (this$.debug || msg.debug) {
this$.log.debug("We were expecting this response: ", msg);
this$.log.debug("Current request queue: ", keys(this$.requestQueue));
}
if ((ref$ = this$.requestQueue[msg.re]) != null) {
ref$.go(null, msg);
}
} else {
this$.log.err("This is not a message we were expecting (or interested in)?is it timed out already? I'm " + this$.me + ")", msg);
if (this$.debug) {
this$.log.warn("Current request queue: ", this$.requestQueue);
}
}
return;
}
if ('data' in msg) {
this$.trigger('data', msg);
}
return this$.trigger('receive', msg);
});
};
Actor.prototype.onTopic = function(route, handler){
var ref$, this$ = this;
if (!route) {
throw "Need a route.";
}
if (!in$(route, this.subscriptions)) {
this.subscribe(route);
}
this.on('data', function(msg){
var requestId;
if (routeMatch(msg.to, route)) {
if (msg.req && msg.part != null) {
this$.sendResponse(msg, {
part: true,
ack: true
}, null);
requestId = msg.from + "." + msg.seq;
if (!this$._request_concat_cache[requestId]) {
this$._request_concat_cache[requestId] = function(){
var message;
message = {};
return function(msg){
var ref$, ref1$;
merge(message, msg);
if (msg.part === LAST_PART) {
handler.call(this$, message);
return ref1$ = (ref$ = this$._request_concat_cache)[requestId], delete ref$[requestId], ref1$;
}
};
}();
}
return this$._request_concat_cache[requestId](msg);
} else {
return handler.call(this$, msg);
}
}
});
return ((ref$ = this._route_handlers)[route] || (ref$[route] = [])).push(handler);
};
Actor.prototype.triggerTopic = function(route){
var args, res$, i$, to$, that, len$, handler, results$ = [];
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
if (that = this._route_handlers[route]) {
for (i$ = 0, len$ = that.length; i$ < len$; ++i$) {
handler = that[i$];
results$.push(handler.apply(null, args));
}
return results$;
} else {
return this.log.debug("No such route handler found: " + route);
}
};
Actor.prototype.onceTopic = function(route, handler){
var this$ = this;
if (!in$(route, this.subscriptions)) {
this.subscribe(route);
}
return this.once('data', function(msg){
if (routeMatch(msg.to, route)) {
handler(msg);
return this$.unsubscribe(route);
}
});
};
Actor.prototype.sendEnveloped = function(msg){
var this$ = this;
if (!(msg.to || 'auth' in msg)) {
debugger;
return this.log.err("send-enveloped: Message has no route. Not sending.", msg);
}
setImmediate(function(){
if (!msg.timestamp) {
msg.timestamp = Date.now();
}
if (this$.debug) {
this$.log.debug("sending message: ", msg);
}
return this$.mgr.distribute(msg, this$.id);
});
};
Actor.prototype.kill = function(reason){
var id, ref$, signal;
if (!this._state.killStarted) {
this._state.killStarted = true;
this.mgr.deregisterActor(this);
for (id in ref$ = this.requestQueue) {
signal = ref$[id];
signal.reset();
delete this.requestQueue[id];
}
this.trigger('kill', reason);
return this._state.killFinished = true;
}
};
Actor.prototype.onEveryLogin = function(callback){
var minPeriod, this$ = this;
minPeriod = 1000;
this.onTopic('app.dcs.connect', function(msg){
if (this$._last_login + minPeriod < Date.now()) {
callback(msg);
return this$._last_login = Date.now();
}
});
return this.sendRequest('app.dcs.update', function(err, msg){
if (!err && (msg != null && msg.data)) {
if (this$._last_login + minPeriod < Date.now()) {
callback(msg);
return this$._last_login = Date.now();
}
}
});
};
return Actor;
}(EventEmitter, request$1));
if (commonjsRequire.main === module) {
console.log("initializing actor test");
new (A1 = (function(superclass){
var prototype = extend$((import$(A1, superclass).displayName = 'A1', A1), superclass).prototype;
A1.prototype.action = function(){
var this$ = this;
return this.onTopic("hello", function(msg){
return this$.log.log("received hello message", msg);
});
};
function A1(){
A1.superclass.apply(this, arguments);
}
return A1;
}(Actor)));
new (A2 = (function(superclass){
var prototype = extend$((import$(A2, superclass).displayName = 'A2', A2), superclass).prototype;
A2.prototype.action = function(){
var this$ = this;
this.onTopic("hello", function(msg){
return this$.log.err("received hello message", msg);
});
return this.send("hello", {
hello: 'there'
});
};
function A2(){
A2.superclass.apply(this, arguments);
}
return A2;
}(Actor)));
}
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
function bind$(obj, key, target){
return function(){ return (target || obj)[key].apply(obj, arguments) };
}
function importAll$(obj, src){
for (var key in src) obj[key] = src[key];
return obj;
}
function in$(x, xs){
var i = -1, l = xs.length >>> 0;
while (++i < l) if (x === xs[i]) return true;
return false;
}
});
var filters = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var sleep, FpsExec, out$ = exports || commonjsGlobal, toString$ = {}.toString;
sleep = lib$2.sleep;
out$.FpsExec = FpsExec = (function(){
FpsExec.displayName = 'FpsExec';
var prototype = FpsExec.prototype;
function FpsExec(opts){
var fps, this$ = this instanceof ctor$ ? this : new ctor$;
opts == null && (opts = 20);
fps = toString$.call(opts).slice(8, -1) === 'Number' ? opts : void 8;
this$.debug = (function(){
try {
return opts.debug;
} catch (e$) {}
}());
this$.period = opts.period || 1000 / fps;
this$.timer = null;
this$.lastExec = 0;
this$.paused = false;
return this$;
} function ctor$(){} ctor$.prototype = prototype;
FpsExec.prototype.now = function(){
return new Date().getTime();
};
FpsExec.prototype.pause = function(){
return this.paused = true;
};
FpsExec.prototype.resume = function(){
var that;
if ((that = this._fn) != null) {
that.apply(null, this._args);
this._fn = null;
}
return this.paused = false;
};
FpsExec.prototype.exec = function(func){
var args, res$, i$, to$, timeToExec, this$ = this;
res$ = [];
for (i$ = 1, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
timeToExec = this.period - (this.now() - this.lastExec);
if (timeToExec < 0) {
timeToExec = 0;
}
try {
clearTimeout(this.timer);
if (this.debug) {
console.info("FpsExec is skipping an execution.");
}
} catch (e$) {}
return this.timer = sleep(timeToExec, function(){
if (!this$.paused) {
func.apply(null, args);
return this$.lastExec = this$.now();
} else {
this$._fn = func;
return this$._args = args;
}
});
};
return FpsExec;
}());
/*
x = new FpsExec 15fps
# or
x = new FpsExec period: 3000ms
### Example Output:
[13:39:26.587] DbLogger : Read something: 10487
[13:39:27.089] DbLogger : Read something: 10488
[13:39:27.590] DbLogger : Read something: 10489
[13:39:28.087] DbLogger : This is going to be recorded: 10489
[13:39:28.091] DbLogger : Read something: 10490
[13:39:28.591] DbLogger : Read something: 10491
[13:39:29.092] DbLogger : Read something: 10492
[13:39:29.593] DbLogger : Read something: 10493
[13:39:30.091] DbLogger : This is going to be recorded: 10493
[13:39:30.093] DbLogger : Read something: 10494
[13:39:30.594] DbLogger : Read something: 10495
[13:39:31.094] DbLogger : Read something: 10496
[13:39:31.593] DbLogger : Read something: 10497
[13:39:32.093] DbLogger : This is going to be recorded: 10497
[13:39:32.096] DbLogger : Read something: 10498
[13:39:32.597] DbLogger : Read something: 10499
[13:39:33.098] DbLogger : Read something: 10500
[13:39:33.598] DbLogger : Read something: 10501
[13:39:34.096] DbLogger : This is going to be recorded: 10501
[13:39:34.099] DbLogger : Read something: 10502
[13:39:34.599] DbLogger : Read something: 10503
[13:39:35.100] DbLogger : Read something: 10504
[13:39:35.601] DbLogger : Read something: 10505
[13:39:36.099] DbLogger : This is going to be recorded: 10505
*/
});
var inherits_browser = createCommonjsModule(function (module) {
if (typeof Object.create === 'function') {
// implementation from standard node.js 'util' module
module.exports = function inherits(ctor, superCtor) {
if (superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
}
};
} else {
// old school shim for old browsers
module.exports = function inherits(ctor, superCtor) {
if (superCtor) {
ctor.super_ = superCtor;
var TempCtor = function () {};
TempCtor.prototype = superCtor.prototype;
ctor.prototype = new TempCtor();
ctor.prototype.constructor = ctor;
}
};
}
});
var inherits = createCommonjsModule(function (module) {
try {
var util = util__default['default'];
/* istanbul ignore next */
if (typeof util.inherits !== 'function') throw '';
module.exports = util.inherits;
} catch (e) {
/* istanbul ignore next */
module.exports = inherits_browser;
}
});
var safeBuffer = createCommonjsModule(function (module, exports) {
/* eslint-disable node/no-deprecated-api */
var Buffer = buffer__default['default'].Buffer;
// alternative to using Object.keys for old browsers
function copyProps (src, dst) {
for (var key in src) {
dst[key] = src[key];
}
}
if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) {
module.exports = buffer__default['default'];
} else {
// Copy properties from require('buffer')
copyProps(buffer__default['default'], exports);
exports.Buffer = SafeBuffer;
}
function SafeBuffer (arg, encodingOrOffset, length) {
return Buffer(arg, encodingOrOffset, length)
}
// Copy static methods from Buffer
copyProps(Buffer, SafeBuffer);
SafeBuffer.from = function (arg, encodingOrOffset, length) {
if (typeof arg === 'number') {
throw new TypeError('Argument must not be a number')
}
return Buffer(arg, encodingOrOffset, length)
};
SafeBuffer.alloc = function (size, fill, encoding) {
if (typeof size !== 'number') {
throw new TypeError('Argument must be a number')
}
var buf = Buffer(size);
if (fill !== undefined) {
if (typeof encoding === 'string') {
buf.fill(fill, encoding);
} else {
buf.fill(fill);
}
} else {
buf.fill(0);
}
return buf
};
SafeBuffer.allocUnsafe = function (size) {
if (typeof size !== 'number') {
throw new TypeError('Argument must be a number')
}
return Buffer(size)
};
SafeBuffer.allocUnsafeSlow = function (size) {
if (typeof size !== 'number') {
throw new TypeError('Argument must be a number')
}
return buffer__default['default'].SlowBuffer(size)
};
});
var Buffer = safeBuffer.Buffer;
// prototype class for hash functions
function Hash (blockSize, finalSize) {
this._block = Buffer.alloc(blockSize);
this._finalSize = finalSize;
this._blockSize = blockSize;
this._len = 0;
}
Hash.prototype.update = function (data, enc) {
if (typeof data === 'string') {
enc = enc || 'utf8';
data = Buffer.from(data, enc);
}
var block = this._block;
var blockSize = this._blockSize;
var length = data.length;
var accum = this._len;
for (var offset = 0; offset < length;) {
var assigned = accum % blockSize;
var remainder = Math.min(length - offset, blockSize - assigned);
for (var i = 0; i < remainder; i++) {
block[assigned + i] = data[offset + i];
}
accum += remainder;
offset += remainder;
if ((accum % blockSize) === 0) {
this._update(block);
}
}
this._len += length;
return this
};
Hash.prototype.digest = function (enc) {
var rem = this._len % this._blockSize;
this._block[rem] = 0x80;
// zero (rem + 1) trailing bits, where (rem + 1) is the smallest
// non-negative solution to the equation (length + 1 + (rem + 1)) === finalSize mod blockSize
this._block.fill(0, rem + 1);
if (rem >= this._finalSize) {
this._update(this._block);
this._block.fill(0);
}
var bits = this._len * 8;
// uint32
if (bits <= 0xffffffff) {
this._block.writeUInt32BE(bits, this._blockSize - 4);
// uint64
} else {
var lowBits = (bits & 0xffffffff) >>> 0;
var highBits = (bits - lowBits) / 0x100000000;
this._block.writeUInt32BE(highBits, this._blockSize - 8);
this._block.writeUInt32BE(lowBits, this._blockSize - 4);
}
this._update(this._block);
var hash = this._hash();
return enc ? hash.toString(enc) : hash
};
Hash.prototype._update = function () {
throw new Error('_update must be implemented by subclass')
};
var hash = Hash;
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-0, as defined
* in FIPS PUB 180-1
* This source code is derived from sha1.js of the same repository.
* The difference between SHA-0 and SHA-1 is just a bitwise rotate left
* operation was added.
*/
var Buffer$1 = safeBuffer.Buffer;
var K = [
0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0
];
var W = new Array(80);
function Sha () {
this.init();
this._w = W;
hash.call(this, 64, 56);
}
inherits(Sha, hash);
Sha.prototype.init = function () {
this._a = 0x67452301;
this._b = 0xefcdab89;
this._c = 0x98badcfe;
this._d = 0x10325476;
this._e = 0xc3d2e1f0;
return this
};
function rotl5 (num) {
return (num << 5) | (num >>> 27)
}
function rotl30 (num) {
return (num << 30) | (num >>> 2)
}
function ft (s, b, c, d) {
if (s === 0) return (b & c) | ((~b) & d)
if (s === 2) return (b & c) | (b & d) | (c & d)
return b ^ c ^ d
}
Sha.prototype._update = function (M) {
var W = this._w;
var a = this._a | 0;
var b = this._b | 0;
var c = this._c | 0;
var d = this._d | 0;
var e = this._e | 0;
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4);
for (; i < 80; ++i) W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16];
for (var j = 0; j < 80; ++j) {
var s = ~~(j / 20);
var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0;
e = d;
d = c;
c = rotl30(b);
b = a;
a = t;
}
this._a = (a + this._a) | 0;
this._b = (b + this._b) | 0;
this._c = (c + this._c) | 0;
this._d = (d + this._d) | 0;
this._e = (e + this._e) | 0;
};
Sha.prototype._hash = function () {
var H = Buffer$1.allocUnsafe(20);
H.writeInt32BE(this._a | 0, 0);
H.writeInt32BE(this._b | 0, 4);
H.writeInt32BE(this._c | 0, 8);
H.writeInt32BE(this._d | 0, 12);
H.writeInt32BE(this._e | 0, 16);
return H
};
var sha = Sha;
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
var Buffer$2 = safeBuffer.Buffer;
var K$1 = [
0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0
];
var W$1 = new Array(80);
function Sha1 () {
this.init();
this._w = W$1;
hash.call(this, 64, 56);
}
inherits(Sha1, hash);
Sha1.prototype.init = function () {
this._a = 0x67452301;
this._b = 0xefcdab89;
this._c = 0x98badcfe;
this._d = 0x10325476;
this._e = 0xc3d2e1f0;
return this
};
function rotl1 (num) {
return (num << 1) | (num >>> 31)
}
function rotl5$1 (num) {
return (num << 5) | (num >>> 27)
}
function rotl30$1 (num) {
return (num << 30) | (num >>> 2)
}
function ft$1 (s, b, c, d) {
if (s === 0) return (b & c) | ((~b) & d)
if (s === 2) return (b & c) | (b & d) | (c & d)
return b ^ c ^ d
}
Sha1.prototype._update = function (M) {
var W = this._w;
var a = this._a | 0;
var b = this._b | 0;
var c = this._c | 0;
var d = this._d | 0;
var e = this._e | 0;
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4);
for (; i < 80; ++i) W[i] = rotl1(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]);
for (var j = 0; j < 80; ++j) {
var s = ~~(j / 20);
var t = (rotl5$1(a) + ft$1(s, b, c, d) + e + W[j] + K$1[s]) | 0;
e = d;
d = c;
c = rotl30$1(b);
b = a;
a = t;
}
this._a = (a + this._a) | 0;
this._b = (b + this._b) | 0;
this._c = (c + this._c) | 0;
this._d = (d + this._d) | 0;
this._e = (e + this._e) | 0;
};
Sha1.prototype._hash = function () {
var H = Buffer$2.allocUnsafe(20);
H.writeInt32BE(this._a | 0, 0);
H.writeInt32BE(this._b | 0, 4);
H.writeInt32BE(this._c | 0, 8);
H.writeInt32BE(this._d | 0, 12);
H.writeInt32BE(this._e | 0, 16);
return H
};
var sha1 = Sha1;
/**
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
* in FIPS 180-2
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
*/
var Buffer$3 = safeBuffer.Buffer;
var K$2 = [
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2
];
var W$2 = new Array(64);
function Sha256 () {
this.init();
this._w = W$2; // new Array(64)
hash.call(this, 64, 56);
}
inherits(Sha256, hash);
Sha256.prototype.init = function () {
this._a = 0x6a09e667;
this._b = 0xbb67ae85;
this._c = 0x3c6ef372;
this._d = 0xa54ff53a;
this._e = 0x510e527f;
this._f = 0x9b05688c;
this._g = 0x1f83d9ab;
this._h = 0x5be0cd19;
return this
};
function ch (x, y, z) {
return z ^ (x & (y ^ z))
}
function maj (x, y, z) {
return (x & y) | (z & (x | y))
}
function sigma0 (x) {
return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10)
}
function sigma1 (x) {
return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7)
}
function gamma0 (x) {
return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3)
}
function gamma1 (x) {
return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10)
}
Sha256.prototype._update = function (M) {
var W = this._w;
var a = this._a | 0;
var b = this._b | 0;
var c = this._c | 0;
var d = this._d | 0;
var e = this._e | 0;
var f = this._f | 0;
var g = this._g | 0;
var h = this._h | 0;
for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4);
for (; i < 64; ++i) W[i] = (gamma1(W[i - 2]) + W[i - 7] + gamma0(W[i - 15]) + W[i - 16]) | 0;
for (var j = 0; j < 64; ++j) {
var T1 = (h + sigma1(e) + ch(e, f, g) + K$2[j] + W[j]) | 0;
var T2 = (sigma0(a) + maj(a, b, c)) | 0;
h = g;
g = f;
f = e;
e = (d + T1) | 0;
d = c;
c = b;
b = a;
a = (T1 + T2) | 0;
}
this._a = (a + this._a) | 0;
this._b = (b + this._b) | 0;
this._c = (c + this._c) | 0;
this._d = (d + this._d) | 0;
this._e = (e + this._e) | 0;
this._f = (f + this._f) | 0;
this._g = (g + this._g) | 0;
this._h = (h + this._h) | 0;
};
Sha256.prototype._hash = function () {
var H = Buffer$3.allocUnsafe(32);
H.writeInt32BE(this._a, 0);
H.writeInt32BE(this._b, 4);
H.writeInt32BE(this._c, 8);
H.writeInt32BE(this._d, 12);
H.writeInt32BE(this._e, 16);
H.writeInt32BE(this._f, 20);
H.writeInt32BE(this._g, 24);
H.writeInt32BE(this._h, 28);
return H
};
var sha256 = Sha256;
/**
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined
* in FIPS 180-2
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
*
*/
var Buffer$4 = safeBuffer.Buffer;
var W$3 = new Array(64);
function Sha224 () {
this.init();
this._w = W$3; // new Array(64)
hash.call(this, 64, 56);
}
inherits(Sha224, sha256);
Sha224.prototype.init = function () {
this._a = 0xc1059ed8;
this._b = 0x367cd507;
this._c = 0x3070dd17;
this._d = 0xf70e5939;
this._e = 0xffc00b31;
this._f = 0x68581511;
this._g = 0x64f98fa7;
this._h = 0xbefa4fa4;
return this
};
Sha224.prototype._hash = function () {
var H = Buffer$4.allocUnsafe(28);
H.writeInt32BE(this._a, 0);
H.writeInt32BE(this._b, 4);
H.writeInt32BE(this._c, 8);
H.writeInt32BE(this._d, 12);
H.writeInt32BE(this._e, 16);
H.writeInt32BE(this._f, 20);
H.writeInt32BE(this._g, 24);
return H
};
var sha224 = Sha224;
var Buffer$5 = safeBuffer.Buffer;
var K$3 = [
0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd,
0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc,
0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019,
0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118,
0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe,
0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2,
0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1,
0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694,
0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3,
0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65,
0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483,
0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5,
0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210,
0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4,
0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725,
0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70,
0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926,
0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df,
0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8,
0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b,
0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001,
0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30,
0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910,
0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8,
0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53,
0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8,
0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb,
0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3,
0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60,
0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec,
0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9,
0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b,
0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207,
0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178,
0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6,
0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b,
0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493,
0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c,
0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a,
0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817
];
var W$4 = new Array(160);
function Sha512 () {
this.init();
this._w = W$4;
hash.call(this, 128, 112);
}
inherits(Sha512, hash);
Sha512.prototype.init = function () {
this._ah = 0x6a09e667;
this._bh = 0xbb67ae85;
this._ch = 0x3c6ef372;
this._dh = 0xa54ff53a;
this._eh = 0x510e527f;
this._fh = 0x9b05688c;
this._gh = 0x1f83d9ab;
this._hh = 0x5be0cd19;
this._al = 0xf3bcc908;
this._bl = 0x84caa73b;
this._cl = 0xfe94f82b;
this._dl = 0x5f1d36f1;
this._el = 0xade682d1;
this._fl = 0x2b3e6c1f;
this._gl = 0xfb41bd6b;
this._hl = 0x137e2179;
return this
};
function Ch (x, y, z) {
return z ^ (x & (y ^ z))
}
function maj$1 (x, y, z) {
return (x & y) | (z & (x | y))
}
function sigma0$1 (x, xl) {
return (x >>> 28 | xl << 4) ^ (xl >>> 2 | x << 30) ^ (xl >>> 7 | x << 25)
}
function sigma1$1 (x, xl) {
return (x >>> 14 | xl << 18) ^ (x >>> 18 | xl << 14) ^ (xl >>> 9 | x << 23)
}
function Gamma0 (x, xl) {
return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7)
}
function Gamma0l (x, xl) {
return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7 | xl << 25)
}
function Gamma1 (x, xl) {
return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6)
}
function Gamma1l (x, xl) {
return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6 | xl << 26)
}
function getCarry (a, b) {
return (a >>> 0) < (b >>> 0) ? 1 : 0
}
Sha512.prototype._update = function (M) {
var W = this._w;
var ah = this._ah | 0;
var bh = this._bh | 0;
var ch = this._ch | 0;
var dh = this._dh | 0;
var eh = this._eh | 0;
var fh = this._fh | 0;
var gh = this._gh | 0;
var hh = this._hh | 0;
var al = this._al | 0;
var bl = this._bl | 0;
var cl = this._cl | 0;
var dl = this._dl | 0;
var el = this._el | 0;
var fl = this._fl | 0;
var gl = this._gl | 0;
var hl = this._hl | 0;
for (var i = 0; i < 32; i += 2) {
W[i] = M.readInt32BE(i * 4);
W[i + 1] = M.readInt32BE(i * 4 + 4);
}
for (; i < 160; i += 2) {
var xh = W[i - 15 * 2];
var xl = W[i - 15 * 2 + 1];
var gamma0 = Gamma0(xh, xl);
var gamma0l = Gamma0l(xl, xh);
xh = W[i - 2 * 2];
xl = W[i - 2 * 2 + 1];
var gamma1 = Gamma1(xh, xl);
var gamma1l = Gamma1l(xl, xh);
// W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16]
var Wi7h = W[i - 7 * 2];
var Wi7l = W[i - 7 * 2 + 1];
var Wi16h = W[i - 16 * 2];
var Wi16l = W[i - 16 * 2 + 1];
var Wil = (gamma0l + Wi7l) | 0;
var Wih = (gamma0 + Wi7h + getCarry(Wil, gamma0l)) | 0;
Wil = (Wil + gamma1l) | 0;
Wih = (Wih + gamma1 + getCarry(Wil, gamma1l)) | 0;
Wil = (Wil + Wi16l) | 0;
Wih = (Wih + Wi16h + getCarry(Wil, Wi16l)) | 0;
W[i] = Wih;
W[i + 1] = Wil;
}
for (var j = 0; j < 160; j += 2) {
Wih = W[j];
Wil = W[j + 1];
var majh = maj$1(ah, bh, ch);
var majl = maj$1(al, bl, cl);
var sigma0h = sigma0$1(ah, al);
var sigma0l = sigma0$1(al, ah);
var sigma1h = sigma1$1(eh, el);
var sigma1l = sigma1$1(el, eh);
// t1 = h + sigma1 + ch + K[j] + W[j]
var Kih = K$3[j];
var Kil = K$3[j + 1];
var chh = Ch(eh, fh, gh);
var chl = Ch(el, fl, gl);
var t1l = (hl + sigma1l) | 0;
var t1h = (hh + sigma1h + getCarry(t1l, hl)) | 0;
t1l = (t1l + chl) | 0;
t1h = (t1h + chh + getCarry(t1l, chl)) | 0;
t1l = (t1l + Kil) | 0;
t1h = (t1h + Kih + getCarry(t1l, Kil)) | 0;
t1l = (t1l + Wil) | 0;
t1h = (t1h + Wih + getCarry(t1l, Wil)) | 0;
// t2 = sigma0 + maj
var t2l = (sigma0l + majl) | 0;
var t2h = (sigma0h + majh + getCarry(t2l, sigma0l)) | 0;
hh = gh;
hl = gl;
gh = fh;
gl = fl;
fh = eh;
fl = el;
el = (dl + t1l) | 0;
eh = (dh + t1h + getCarry(el, dl)) | 0;
dh = ch;
dl = cl;
ch = bh;
cl = bl;
bh = ah;
bl = al;
al = (t1l + t2l) | 0;
ah = (t1h + t2h + getCarry(al, t1l)) | 0;
}
this._al = (this._al + al) | 0;
this._bl = (this._bl + bl) | 0;
this._cl = (this._cl + cl) | 0;
this._dl = (this._dl + dl) | 0;
this._el = (this._el + el) | 0;
this._fl = (this._fl + fl) | 0;
this._gl = (this._gl + gl) | 0;
this._hl = (this._hl + hl) | 0;
this._ah = (this._ah + ah + getCarry(this._al, al)) | 0;
this._bh = (this._bh + bh + getCarry(this._bl, bl)) | 0;
this._ch = (this._ch + ch + getCarry(this._cl, cl)) | 0;
this._dh = (this._dh + dh + getCarry(this._dl, dl)) | 0;
this._eh = (this._eh + eh + getCarry(this._el, el)) | 0;
this._fh = (this._fh + fh + getCarry(this._fl, fl)) | 0;
this._gh = (this._gh + gh + getCarry(this._gl, gl)) | 0;
this._hh = (this._hh + hh + getCarry(this._hl, hl)) | 0;
};
Sha512.prototype._hash = function () {
var H = Buffer$5.allocUnsafe(64);
function writeInt64BE (h, l, offset) {
H.writeInt32BE(h, offset);
H.writeInt32BE(l, offset + 4);
}
writeInt64BE(this._ah, this._al, 0);
writeInt64BE(this._bh, this._bl, 8);
writeInt64BE(this._ch, this._cl, 16);
writeInt64BE(this._dh, this._dl, 24);
writeInt64BE(this._eh, this._el, 32);
writeInt64BE(this._fh, this._fl, 40);
writeInt64BE(this._gh, this._gl, 48);
writeInt64BE(this._hh, this._hl, 56);
return H
};
var sha512 = Sha512;
var Buffer$6 = safeBuffer.Buffer;
var W$5 = new Array(160);
function Sha384 () {
this.init();
this._w = W$5;
hash.call(this, 128, 112);
}
inherits(Sha384, sha512);
Sha384.prototype.init = function () {
this._ah = 0xcbbb9d5d;
this._bh = 0x629a292a;
this._ch = 0x9159015a;
this._dh = 0x152fecd8;
this._eh = 0x67332667;
this._fh = 0x8eb44a87;
this._gh = 0xdb0c2e0d;
this._hh = 0x47b5481d;
this._al = 0xc1059ed8;
this._bl = 0x367cd507;
this._cl = 0x3070dd17;
this._dl = 0xf70e5939;
this._el = 0xffc00b31;
this._fl = 0x68581511;
this._gl = 0x64f98fa7;
this._hl = 0xbefa4fa4;
return this
};
Sha384.prototype._hash = function () {
var H = Buffer$6.allocUnsafe(48);
function writeInt64BE (h, l, offset) {
H.writeInt32BE(h, offset);
H.writeInt32BE(l, offset + 4);
}
writeInt64BE(this._ah, this._al, 0);
writeInt64BE(this._bh, this._bl, 8);
writeInt64BE(this._ch, this._cl, 16);
writeInt64BE(this._dh, this._dl, 24);
writeInt64BE(this._eh, this._el, 32);
writeInt64BE(this._fh, this._fl, 40);
return H
};
var sha384 = Sha384;
var sha_js = createCommonjsModule(function (module) {
var exports = module.exports = function SHA (algorithm) {
algorithm = algorithm.toLowerCase();
var Algorithm = exports[algorithm];
if (!Algorithm) throw new Error(algorithm + ' is not supported (we accept pull requests)')
return new Algorithm()
};
exports.sha = sha;
exports.sha1 = sha1;
exports.sha224 = sha224;
exports.sha256 = sha256;
exports.sha384 = sha384;
exports.sha512 = sha512;
});
var authHelpers = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var createHash, hashPasswd, AuthError, out$ = exports || commonjsGlobal;
createHash = sha_js;
out$.hashPasswd = hashPasswd = function(passwd){
var sha512;
sha512 = createHash('sha512');
return sha512.update(passwd, 'utf-8').digest('hex');
};
out$.AuthError = AuthError = (function(superclass){
var prototype = extend$((import$(AuthError, superclass).displayName = 'AuthError', AuthError), superclass).prototype;
function AuthError(message){
this.message = message;
AuthError.superclass.apply(this, arguments);
Error.captureStackTrace(this, AuthError);
this.type = 'AuthError';
}
return AuthError;
}(Error));
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
var authRequest = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var Signal, ref$, sleep, pack, clone, EventEmitter, Logger, red, green, yellow, bgRed, bgYellow, hashPasswd, topicMatch, keys, join, AuthRequest, out$ = exports || commonjsGlobal;
Signal = signal$1.Signal;
ref$ = lib$2, sleep = ref$.sleep, pack = ref$.pack, clone = ref$.clone, EventEmitter = ref$.EventEmitter, Logger = ref$.Logger;
ref$ = lib, red = ref$.red, green = ref$.green, yellow = ref$.yellow, bgRed = ref$.bgRed, bgYellow = ref$.bgYellow;
hashPasswd = authHelpers.hashPasswd;
topicMatch = topicMatch_1.topicMatch;
ref$ = lib$1, keys = ref$.keys, join = ref$.join;
out$.AuthRequest = AuthRequest = (function(){
AuthRequest.displayName = 'AuthRequest';
var constructor = AuthRequest;
AuthRequest.i = 0;
function AuthRequest(name){
this.log = new Logger(name || "AuthRequest." + (constructor.i++));
this.replySignal = new Signal();
}
AuthRequest.prototype.inbox = function(msg){
return this.replySignal.go(null, msg);
};
AuthRequest.prototype.login = function(_credentials, callback){
var credentials, err, this$ = this;
_credentials == null && (_credentials = {});
credentials = clone(_credentials);
if (credentials.password) {
credentials.password = hashPasswd(credentials.password);
} else if (credentials.token != null) {
this.log.info("token is: ", credentials);
if (credentials.token.length < 10) {
err = "Token seems empty, not attempting to login.";
this.log.log(err);
callback(err = "Not a valid token", null);
return;
}
}
this.log.log("Trying to authenticate with", keys(credentials).join(', '));
if (keys(credentials).length === 0) {
this.log.warn("Credentials empty! (why? is server restarted?)");
callback(err = "EMPTY_CREDENTIALS");
return;
}
this.write({
auth: credentials
});
this.replySignal.clear();
return this.replySignal.wait(3000, function(err, res){
var that, ref$, ref1$, ref2$;
if (that = res != null ? (ref$ = res.auth) != null ? (ref1$ = ref$.session) != null ? ref1$.token : void 8 : void 8 : void 8) {
this$.token = that;
}
return callback(err || (res != null ? (ref2$ = res.auth) != null ? ref2$.error : void 8 : void 8), res);
});
};
AuthRequest.prototype.logout = function(callback){
var this$ = this;
this.write(this.addToken({
auth: {
logout: true
}
}));
return this.replySignal.wait(3000, function(err, msg){
if (!err && msg.auth.logout === 'ok') {
this$.log.log("clearing token from AuthRequest cache");
this$.token = null;
}
return callback(err, msg);
});
};
AuthRequest.prototype.addToken = function(msg){
return msg.token = this.token, msg;
};
return AuthRequest;
}());
});
var uuid4 = createCommonjsModule(function (module, exports) {
var uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
exports = module.exports = genUUID;
exports.valid = isUUID;
function genUUID(callback) {
if (typeof callback !== "function") {
var rnd = crypto__default['default'].randomBytes(16);
rnd[6] = (rnd[6] & 0x0f) | 0x40;
rnd[8] = (rnd[8] & 0x3f) | 0x80;
rnd = rnd.toString("hex").match(/(.{8})(.{4})(.{4})(.{4})(.{12})/);
rnd.shift();
return rnd.join("-");
}
crypto__default['default'].randomBytes(16, function(err, rnd) {
if (err) return callback(err);
try {
rnd[6] = (rnd[6] & 0x0f) | 0x40;
rnd[8] = (rnd[8] & 0x3f) | 0x80;
rnd = rnd.toString("hex").match(/(.{8})(.{4})(.{4})(.{4})(.{12})/);
rnd.shift();
return callback(null, rnd.join("-"));
} catch (err2) {
return callback(err2);
}
});
}
function isUUID(uuid) {
return uuidPattern.test(uuid);
}
});
var errors = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var CodingError, out$ = exports || commonjsGlobal;
out$.CodingError = CodingError = (function(superclass){
var prototype = extend$((import$(CodingError, superclass).displayName = 'CodingError', CodingError), superclass).prototype;
function CodingError(message){
this.message = message;
CodingError.superclass.apply(this, arguments);
Error.captureStackTrace(this, CodingError);
this.type = 'CodingError';
}
return CodingError;
}(Error));
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
var authHandler = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, sleep, Logger, pack, EventEmitter, uuid4$1, red, green, yellow, bgRed, bgYellow, bgGreen, bgCyan, hashPasswd, AuthError, topicMatch, CodingError, SessionCache, AuthHandler, out$ = exports || commonjsGlobal;
ref$ = lib$2, sleep = ref$.sleep, Logger = ref$.Logger, pack = ref$.pack, EventEmitter = ref$.EventEmitter;
uuid4$1 = uuid4;
ref$ = lib, red = ref$.red, green = ref$.green, yellow = ref$.yellow, bgRed = ref$.bgRed, bgYellow = ref$.bgYellow, bgGreen = ref$.bgGreen, bgCyan = ref$.bgCyan;
ref$ = authHelpers, hashPasswd = ref$.hashPasswd, AuthError = ref$.AuthError;
topicMatch = topicMatch_1.topicMatch;
CodingError = errors.CodingError;
SessionCache = (function(){
SessionCache.displayName = 'SessionCache';
var constructor = SessionCache;
SessionCache.cache = {};
SessionCache.instance = null;
function SessionCache(){
if (constructor.instance) {
return constructor.instance;
}
constructor.instance = this;
this.log = new Logger('SessionCache');
this.log.log(green("SessionCache is initialized", pack(constructor.cache)));
}
SessionCache.prototype.add = function(session){
this.log.log(green("Adding session for " + session.user, yellow(session.token)));
return constructor.cache[session.token] = session;
};
SessionCache.prototype.get = function(token){
return constructor.cache[token];
};
SessionCache.prototype.drop = function(token){
var ref$, ref1$;
this.log.log(yellow("Dropping session for user: " + constructor.cache[token].user + " token: " + token));
return ref1$ = (ref$ = constructor.cache)[token], delete ref$[token], ref1$;
};
return SessionCache;
}());
out$.AuthHandler = AuthHandler = (function(superclass){
var prototype = extend$((import$(AuthHandler, superclass).displayName = 'AuthHandler', AuthHandler), superclass).prototype, constructor = AuthHandler;
AuthHandler.loginDelay = 10;
AuthHandler.i = 0;
function AuthHandler(db, name){
var this$ = this;
db != null || (function(){
throw new CodingError("AuthDB instance is required.");
}());
AuthHandler.superclass.call(this);
this.log = new Logger(name || "AuthHandler." + (constructor.i++));
this.sessionCache = new SessionCache();
this.on('check-auth', function(msg){
var user, e, ref$, foundSession;
if (msg.debug) {
this$.log.log("Processing authentication message", msg);
}
if ('user' in msg.auth) {
try {
user = db.get(msg.auth.user);
if (user.passwdHash === msg.auth.password) {
this$.session = {
token: uuid4$1(),
user: msg.auth.user,
date: Date.now(),
routes: user.routes,
permissions: user.permissions
};
this$.sessionCache.add(this$.session);
this$.log.log(bgGreen("new Login: " + msg.auth.user + " (" + this$.session.token + ")"));
this$.log.log("(...sending with " + constructor.loginDelay + "ms delay)");
this$.trigger('login', this$.session);
return sleep(constructor.loginDelay, function(){
return this$.trigger('to-client', {
auth: {
session: this$.session
}
});
});
} else {
this$.log.err("wrong password, tried:" + msg.auth.user + ", " + msg.auth.password);
return this$.trigger('to-client', {
auth: {
error: "wrong password"
}
});
}
} catch (e$) {
e = e$;
this$.log.err("user \"" + msg.auth.user + "\" is not found. err: ", e);
return this$.trigger('to-client', {
auth: {
error: e
}
});
}
} else if ('logout' in msg.auth) {
if (!this$.sessionCache.get(msg.token)) {
this$.log.log(bgYellow("No user found with the following token: " + msg.token + " "));
this$.trigger('to-client', {
auth: {
logout: 'ok',
error: "no such user found"
}
});
return this$.trigger('logout');
} else {
this$.log.log("logging out for " + pack(this$.sessionCache.get(msg.token)));
this$.sessionCache.drop(msg.token);
this$.trigger('to-client', {
auth: {
logout: 'ok'
}
});
return this$.trigger('logout');
}
} else if ('token' in msg.auth) {
this$.log.log("Attempting to login with token: ", pack(msg.auth));
if (((ref$ = this$.sessionCache.get(msg.auth.token)) != null ? ref$.token : void 8) === msg.auth.token) {
foundSession = this$.sessionCache.get(msg.auth.token);
this$.log.log(bgCyan("User \"" + foundSession.user + "\" has been logged in with token."));
this$.trigger('login', foundSession);
return sleep(constructor.loginDelay, function(){
return this$.trigger('to-client', {
auth: {
session: foundSession
}
});
});
} else {
this$.log.log(bgYellow("client doesn't seem to be logged in yet."));
return sleep(constructor.loginDelay, function(){
return this$.trigger('to-client', {
auth: {
session: {
logout: 'yes'
}
}
});
});
}
} else {
return this$.log.err(yellow("Can not determine which auth request this was: ", pack(msg)));
}
});
}
AuthHandler.prototype.checkRoutes = function(msg){
var session, i$, x$, ref$, len$;
session = this.sessionCache.get(msg.token);
if (session) {
for (i$ = 0, len$ = (ref$ = session.routes).length; i$ < len$; ++i$) {
x$ = ref$[i$];
if (topicMatch(x$, msg.to)) {
delete msg.token;
return msg;
}
}
if (msg.re != null) {
delete msg.token;
return msg;
}
}
return this.log.err(bgRed("filter-incoming dropping unauthorized message!"), (function(){
throw new AuthError('unauthorized message route');
}()));
};
AuthHandler.prototype.modifySender = function(msg){
var session;
session = this.sessionCache.get(msg.token);
if (!session) {
throw new AuthError("No appropriate session is found.");
}
msg.from = "@" + session.user + "." + msg.from;
return msg;
};
AuthHandler.prototype.addCtx = function(msg){
var session;
session = this.sessionCache.get(msg.token);
msg.permissions = session.permissions;
msg.user = session.user;
return msg;
};
return AuthHandler;
}(EventEmitter));
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
// Generated by LiveScript 1.6.0
var ref$$2, sleep$2, pack$1, unpack$1, Logger$2, clone$2, brief$1, AuthRequest, Signal$2, Actor, topicMatch, AuthHandler;
ref$$2 = lib$2, sleep$2 = ref$$2.sleep, pack$1 = ref$$2.pack, unpack$1 = ref$$2.unpack, Logger$2 = ref$$2.Logger, clone$2 = ref$$2.clone;
brief$1 = debugTools.brief;
AuthRequest = authRequest.AuthRequest;
Signal$2 = signal$1.Signal;
Actor = actor.Actor;
topicMatch = topicMatch_1.topicMatch;
AuthHandler = authHandler.AuthHandler;
var deps$1 = {
sleep: sleep$2,
pack: pack$1,
unpack: unpack$1,
clone: clone$2,
Logger: Logger$2,
AuthRequest: AuthRequest,
AuthHandler: AuthHandler,
topicMatch: topicMatch,
Actor: Actor,
Signal: Signal$2,
brief: brief$1
};
var helpers = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, sleep, pack, unpack, Logger, clone, split, flatten, splitAt, compact, MessageBinder, out$ = exports || commonjsGlobal, toString$ = {}.toString;
ref$ = lib$2, sleep = ref$.sleep, pack = ref$.pack, unpack = ref$.unpack, Logger = ref$.Logger, clone = ref$.clone;
ref$ = lib$1, split = ref$.split, flatten = ref$.flatten, splitAt = ref$.splitAt, compact = ref$.compact;
function unpackTelegrams(data){
"Search for valid JSON telegrams recursively";
var boundary, ref$, _first, _rest, nextSize, _firstTelegram, that, restTelegram, restStr, a, packets;
boundary = data.indexOf('}{');
ref$ = compact(splitAt(boundary + 1, data)), _first = ref$[0], _rest = ref$[1];
nextSize = 0;
try {
_firstTelegram = unpack(_first);
} catch (e$) {
return [[], data, nextSize];
}
if (that = _firstTelegram != null ? _firstTelegram.size : void 8) {
nextSize = that;
_firstTelegram = null;
}
restTelegram = [];
restStr = '';
if (_rest) {
ref$ = unpackTelegrams(_rest), restTelegram = ref$[0], restStr = ref$[1], a = ref$[2];
if (nextSize > 0 && restTelegram.length > 0) {
nextSize = 0;
}
}
packets = compact(flatten([_firstTelegram, restTelegram]));
return [packets, restStr, nextSize];
}
out$.MessageBinder = MessageBinder = (function(){
MessageBinder.displayName = 'MessageBinder';
function MessageBinder(){
this.log = new Logger('MessageBinder');
this.i = 0;
this.cache = "";
this.heartbeat = 0;
this.timeout = 1400;
this.maxTry = 1200;
this.nextSize = 0;
}
MessageBinder.prototype.append = function(data){
var ref$, res, y, size;
if (toString$.call(data).slice(8, -1) === 'Uint8Array') {
data = data.toString();
}
if (this.heartbeat < Date.now() - this.timeout) {
this.cache = '';
this.i = 0;
this.nextSize = 0;
}
this.cache += data;
if (this.nextSize > 0) {
if (this.cache.length < this.nextSize) {
return [];
} else {
this.nextSize = 0;
}
}
this.i++;
if (this.i > this.maxTry) {
this.log.err("Caching isn't enough, giving up.");
this.i = 0;
this.cache = data;
this.nextSize = 0;
}
this.heartbeat = Date.now();
ref$ = unpackTelegrams(this.cache), res = ref$[0], y = ref$[1], size = ref$[2];
if (size > 0) {
this.nextSize = size;
}
this.cache = y;
this.i = 0;
return res;
};
return MessageBinder;
}());
});
var client = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, AuthRequest, sleep, pack, unpack, Signal, Actor, topicMatch, clone, brief, split, flatten, splitAt, empty, reject, MessageBinder, ProxyClient, out$ = exports || commonjsGlobal, toString$ = {}.toString;
ref$ = deps$1, AuthRequest = ref$.AuthRequest, sleep = ref$.sleep, pack = ref$.pack, unpack = ref$.unpack, Signal = ref$.Signal, Actor = ref$.Actor, topicMatch = ref$.topicMatch, clone = ref$.clone, brief = ref$.brief;
ref$ = lib$1, split = ref$.split, flatten = ref$.flatten, splitAt = ref$.splitAt, empty = ref$.empty, reject = ref$.reject;
MessageBinder = helpers.MessageBinder;
out$.ProxyClient = ProxyClient = (function(superclass){
var prototype = extend$((import$(ProxyClient, superclass).displayName = 'ProxyClient', ProxyClient), superclass).prototype;
function ProxyClient(transport, opts){
this.transport = transport;
this.opts = opts;
ProxyClient.superclass.call(this, this.opts.name || 'ProxyClient');
}
ProxyClient.prototype.action = function(){
var x$, totalDelay, y$, this$ = this;
this.role = 'client';
this.connected = false;
this.session = null;
this._transport_busy = false;
x$ = this.auth = new AuthRequest(this.name);
x$.write = function(msg){
return this$.transport.write(pack(msg));
};
this.onTopic('app.dcs.update', function(msg){
var debug;
debug = false;
if (debug) {
this$.log.debug("Received connection status update: ", msg);
}
return this$.sendResponse(msg, {
debug: debug
}, this$.session);
});
this.on('disconnect', function(){
this$.subscriptions = reject(function(it){
var ref$;
return topicMatch(it, (ref$ = this$.session) != null ? ref$.routes : void 8);
}, this$.subscriptions);
this$.session = null;
return this$.send('app.dcs.disconnect');
});
this.on('connect', function(){
return this$.trigger('_login');
});
this.on('receive', function(msg){
if (!topicMatch(msg.to, "app.**")) {
if (!topicMatch(msg.to, this$.subscriptions)) {
this$.log.err("Possible coding error: We don't have a route for: ", msg);
this$.log.info("Our subscriptions: ", this$.subscriptions);
this$.sendResponse(msg, {
err: "How come the ProxyClient is subscribed a topicthat it has no rights to send? This is a DCS malfunction."
});
return;
}
if (this$._transport_busy) {
this$.log.err("Transport was busy, we shouldn't try to send ", msg);
this$.log.info("...will retry to write to transport in 500ms.");
debugger;
sleep(500, function(){
return this$.trigger('receive', msg);
});
return;
}
this$._transport_busy = true;
this$.transport.write(
function(s){
if (msg.debug) {
this$.log.debug("Sending " + msg.seq + "->" + msg.to + " size: " + s.length);
}
return pack({
size: s.length
}) + s;
}(
pack(
this$.auth.addToken(
function(m){
var responseId;
if (m.debug) {
this$.log.debug("Forwarding DCS to transport: ", brief(m));
}
if (m.re != null) {
responseId = m.to + "";
if (m.part == null || m.part === -1) {
this$.unsubscribe(responseId);
}
}
return m;
}(
msg)))));
if (msg.debug) {
this$.log.debug("Data is sent.");
}
return this$._transport_busy = false;
}
});
this.m = new MessageBinder();
totalDelay = 0;
y$ = this.transport;
y$.on('connect', function(){
this$.connected = true;
return this$.log.success("My transport is connected, re-logging-in.");
});
y$.on('disconnect', function(){
this$.connected = false;
return this$.log.warn("My transport is disconnected.");
});
y$.on("data", function(data){
var t0, x, i$, len$, msg, responseRoute, that, msg2;
t0 = Date.now();
x = this$.m.append(data);
totalDelay = totalDelay + (Date.now() - t0);
for (i$ = 0, len$ = x.length; i$ < len$; ++i$) {
msg = x[i$];
if (totalDelay > 100) {
this$.log.debug("....time spent for concatenating: " + totalDelay + "ms");
}
totalDelay = 0;
if ('auth' in msg) {
this$.auth.inbox(msg);
} else {
if (msg.debug) {
this$.log.debug("Forwarding Transport to DCS:", brief(msg));
}
if (msg.req) {
responseRoute = msg.from + "";
if (msg.debug) {
this$.log.debug("Transient subscription to response route: " + responseRoute);
}
this$.subscribe(responseRoute);
}
if (msg.re != null) {
msg.to = msg.to.replace("@" + this$.session.user + ".", '');
if (that = this$.mgr.findActor(msg.to)) {
that._inbox(msg);
}
if (msg.cc) {
msg2 = clone(msg);
msg2.to = msg.cc;
msg2._exclude = msg.to;
this$.sendEnveloped(msg2);
}
return;
}
this$.sendEnveloped(msg);
}
}
});
return y$;
};
Object.defineProperty(ProxyClient.prototype, 'connected', {
get: function(){
return this._connected;
},
set: function(curr){
var prev;
prev = this._connected;
this._connected = curr;
if (curr && !prev) {
this.trigger('connect');
}
if (!curr && prev) {
this.trigger('disconnect');
}
},
configurable: true,
enumerable: true
});
ProxyClient.prototype.login = function(credentials, callback){
var this$ = this;
if (toString$.call(credentials).slice(8, -1) === 'Function') {
callback = credentials;
credentials = null;
} else if (!callback) {
callback = function(err, res){
var ref$;
if (err) {
return this$.log.err("Something went wrong while login: ", pack(err));
} else if ((ref$ = res.auth) != null && ref$.error) {
return this$.log.err("Wrong credentials?");
} else {
return this$.log.success("Logged in into the DCS network.");
}
};
}
this.off('_login');
this.on('_login', function(opts){
this$.log.log("sending credentials...");
return this$.auth.login(credentials, function(err, res){
var error, ref$, ref1$, ref2$, i$, x$, ref3$, len$, ref4$;
error = err || (res != null ? (ref$ = res.auth) != null ? ref$.error : void 8 : void 8) || (res != null ? (ref1$ = res.auth) != null ? (ref2$ = ref1$.session) != null ? ref2$.logout : void 8 : void 8 : void 8) === 'yes';
if (!error) {
this$.session = (function(){
try {
return res.auth.session;
} catch (e$) {
this.log.error("FIXME: We have empty session: ", res);
return {};
}
}.call(this$));
this$.subscriptions = this$.subscriptions.concat(this$.session.routes);
this$.log.info("Remote route subscriptions: ");
for (i$ = 0, len$ = (ref3$ = flatten([this$.subscriptions])).length; i$ < len$; ++i$) {
x$ = ref3$[i$];
this$.log.info("-> " + x$);
}
this$.log.info("Emitting app.dcs.connect");
this$.send('app.dcs.connect', this$.session);
this$.trigger('logged-in', this$.session, function(){
var ref$;
return credentials = {
token: (ref$ = this$.session) != null ? ref$.token : void 8
};
});
} else {
this$.connected = false;
}
if ((res != null ? (ref3$ = res.auth) != null ? (ref4$ = ref3$.session) != null ? ref4$.logout : void 8 : void 8 : void 8) === 'yes') {
this$.trigger('kicked-out');
}
return callback(error, res);
});
});
if (this.connected) {
return this.trigger('_login');
}
};
ProxyClient.prototype.logout = function(callback){
var this$ = this;
return this.auth.logout(function(err, res){
var reason, ref$;
this$.log.info("Logged out; err, res: ", err, res);
reason = res != null ? (ref$ = res.auth) != null ? ref$.error : void 8 : void 8;
this$.trigger('logged-out', reason);
return callback(err, res);
});
};
return ProxyClient;
}(Actor));
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
/**
* Helpers.
*/
var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var w = d * 7;
var y = d * 365.25;
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @param {String|Number} val
* @param {Object} [options]
* @throws {Error} throw an error if val is not a non-empty string or a number
* @return {String|Number}
* @api public
*/
var ms = function(val, options) {
options = options || {};
var type = typeof val;
if (type === 'string' && val.length > 0) {
return parse(val);
} else if (type === 'number' && isFinite(val)) {
return options.long ? fmtLong(val) : fmtShort(val);
}
throw new Error(
'val is not a non-empty string or a valid number. val=' +
JSON.stringify(val)
);
};
/**
* Parse the given `str` and return milliseconds.
*
* @param {String} str
* @return {Number}
* @api private
*/
function parse(str) {
str = String(str);
if (str.length > 100) {
return;
}
var match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(
str
);
if (!match) {
return;
}
var n = parseFloat(match[1]);
var type = (match[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'yrs':
case 'yr':
case 'y':
return n * y;
case 'weeks':
case 'week':
case 'w':
return n * w;
case 'days':
case 'day':
case 'd':
return n * d;
case 'hours':
case 'hour':
case 'hrs':
case 'hr':
case 'h':
return n * h;
case 'minutes':
case 'minute':
case 'mins':
case 'min':
case 'm':
return n * m;
case 'seconds':
case 'second':
case 'secs':
case 'sec':
case 's':
return n * s;
case 'milliseconds':
case 'millisecond':
case 'msecs':
case 'msec':
case 'ms':
return n;
default:
return undefined;
}
}
/**
* Short format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function fmtShort(ms) {
var msAbs = Math.abs(ms);
if (msAbs >= d) {
return Math.round(ms / d) + 'd';
}
if (msAbs >= h) {
return Math.round(ms / h) + 'h';
}
if (msAbs >= m) {
return Math.round(ms / m) + 'm';
}
if (msAbs >= s) {
return Math.round(ms / s) + 's';
}
return ms + 'ms';
}
/**
* Long format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function fmtLong(ms) {
var msAbs = Math.abs(ms);
if (msAbs >= d) {
return plural(ms, msAbs, d, 'day');
}
if (msAbs >= h) {
return plural(ms, msAbs, h, 'hour');
}
if (msAbs >= m) {
return plural(ms, msAbs, m, 'minute');
}
if (msAbs >= s) {
return plural(ms, msAbs, s, 'second');
}
return ms + ' ms';
}
/**
* Pluralization helper.
*/
function plural(ms, msAbs, n, name) {
var isPlural = msAbs >= n * 1.5;
return Math.round(ms / n) + ' ' + name + (isPlural ? 's' : '');
}
var debug = createCommonjsModule(function (module, exports) {
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = createDebug.debug = createDebug['default'] = createDebug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = ms;
/**
* The currently active debug mode names, and names to skip.
*/
exports.names = [];
exports.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lower or upper-case letter, i.e. "n" and "N".
*/
exports.formatters = {};
/**
* Previous log timestamp.
*/
var prevTime;
/**
* Select a color.
* @param {String} namespace
* @return {Number}
* @api private
*/
function selectColor(namespace) {
var hash = 0, i;
for (i in namespace) {
hash = ((hash << 5) - hash) + namespace.charCodeAt(i);
hash |= 0; // Convert to 32bit integer
}
return exports.colors[Math.abs(hash) % exports.colors.length];
}
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/
function createDebug(namespace) {
function debug() {
// disabled?
if (!debug.enabled) return;
var self = debug;
// set `diff` timestamp
var curr = +new Date();
var ms = curr - (prevTime || curr);
self.diff = ms;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
// turn the `arguments` into a proper Array
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
args[0] = exports.coerce(args[0]);
if ('string' !== typeof args[0]) {
// anything else let's inspect with %O
args.unshift('%O');
}
// apply any `formatters` transformations
var index = 0;
args[0] = args[0].replace(/%([a-zA-Z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = exports.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(self, val);
// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
// apply env-specific formatting (colors, etc.)
exports.formatArgs.call(self, args);
var logFn = debug.log || exports.log || console.log.bind(console);
logFn.apply(self, args);
}
debug.namespace = namespace;
debug.enabled = exports.enabled(namespace);
debug.useColors = exports.useColors();
debug.color = selectColor(namespace);
// env-specific initialization logic for debug instances
if ('function' === typeof exports.init) {
exports.init(debug);
}
return debug;
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
exports.save(namespaces);
exports.names = [];
exports.skips = [];
var split = (typeof namespaces === 'string' ? namespaces : '').split(/[\s,]+/);
var len = split.length;
for (var i = 0; i < len; i++) {
if (!split[i]) continue; // ignore empty strings
namespaces = split[i].replace(/\*/g, '.*?');
if (namespaces[0] === '-') {
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
} else {
exports.names.push(new RegExp('^' + namespaces + '$'));
}
}
}
/**
* Disable debug output.
*
* @api public
*/
function disable() {
exports.enable('');
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
function enabled(name) {
var i, len;
for (i = 0, len = exports.skips.length; i < len; i++) {
if (exports.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = exports.names.length; i < len; i++) {
if (exports.names[i].test(name)) {
return true;
}
}
return false;
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
});
var browser = createCommonjsModule(function (module, exports) {
/**
* This is the web browser implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = debug;
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = 'undefined' != typeof chrome
&& 'undefined' != typeof chrome.storage
? chrome.storage.local
: localstorage();
/**
* Colors.
*/
exports.colors = [
'lightseagreen',
'forestgreen',
'goldenrod',
'dodgerblue',
'darkorchid',
'crimson'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
function useColors() {
// NB: In an Electron preload script, document will be defined but not fully
// initialized. Since we know we're in Chrome, we'll just detect this case
// explicitly
if (typeof window !== 'undefined' && window.process && window.process.type === 'renderer') {
return true;
}
// is webkit? http://stackoverflow.com/a/16459606/376773
// document is undefined in react-native: https://github.com/facebook/react-native/pull/1632
return (typeof document !== 'undefined' && document.documentElement && document.documentElement.style && document.documentElement.style.WebkitAppearance) ||
// is firebug? http://stackoverflow.com/a/398120/376773
(typeof window !== 'undefined' && window.console && (window.console.firebug || (window.console.exception && window.console.table))) ||
// is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31) ||
// double check webkit in userAgent just in case we are in a worker
(typeof navigator !== 'undefined' && navigator.userAgent && navigator.userAgent.toLowerCase().match(/applewebkit\/(\d+)/));
}
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
exports.formatters.j = function(v) {
try {
return JSON.stringify(v);
} catch (err) {
return '[UnexpectedJSONParseError]: ' + err.message;
}
};
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs(args) {
var useColors = this.useColors;
args[0] = (useColors ? '%c' : '')
+ this.namespace
+ (useColors ? ' %c' : ' ')
+ args[0]
+ (useColors ? '%c ' : ' ')
+ '+' + exports.humanize(this.diff);
if (!useColors) return;
var c = 'color: ' + this.color;
args.splice(1, 0, c, 'color: inherit');
// the final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
var index = 0;
var lastC = 0;
args[0].replace(/%[a-zA-Z%]/g, function(match) {
if ('%%' === match) return;
index++;
if ('%c' === match) {
// we only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
}
/**
* Invokes `console.log()` when available.
* No-op when `console.log` is not a "function".
*
* @api public
*/
function log() {
// this hackery is required for IE8/9, where
// the `console.log` function doesn't have 'apply'
return 'object' === typeof console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (null == namespaces) {
exports.storage.removeItem('debug');
} else {
exports.storage.debug = namespaces;
}
} catch(e) {}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
var r;
try {
r = exports.storage.debug;
} catch(e) {}
// If debug isn't set in LS, and we're in Electron, try to load $DEBUG
if (!r && typeof process !== 'undefined' && 'env' in process) {
r = process.env.DEBUG;
}
return r;
}
/**
* Enable namespaces listed in `localStorage.debug` initially.
*/
exports.enable(load());
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*
* @return {LocalStorage}
* @api private
*/
function localstorage() {
try {
return window.localStorage;
} catch (e) {}
}
});
var node = createCommonjsModule(function (module, exports) {
/**
* Module dependencies.
*/
/**
* This is the Node.js implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = debug;
exports.init = init;
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
/**
* Colors.
*/
exports.colors = [6, 2, 3, 4, 5, 1];
/**
* Build up the default `inspectOpts` object from the environment variables.
*
* $ DEBUG_COLORS=no DEBUG_DEPTH=10 DEBUG_SHOW_HIDDEN=enabled node script.js
*/
exports.inspectOpts = Object.keys(process.env).filter(function (key) {
return /^debug_/i.test(key);
}).reduce(function (obj, key) {
// camel-case
var prop = key
.substring(6)
.toLowerCase()
.replace(/_([a-z])/g, function (_, k) { return k.toUpperCase() });
// coerce string value into JS value
var val = process.env[key];
if (/^(yes|on|true|enabled)$/i.test(val)) val = true;
else if (/^(no|off|false|disabled)$/i.test(val)) val = false;
else if (val === 'null') val = null;
else val = Number(val);
obj[prop] = val;
return obj;
}, {});
/**
* The file descriptor to write the `debug()` calls to.
* Set the `DEBUG_FD` env variable to override with another value. i.e.:
*
* $ DEBUG_FD=3 node script.js 3>debug.log
*/
var fd = parseInt(process.env.DEBUG_FD, 10) || 2;
if (1 !== fd && 2 !== fd) {
util__default['default'].deprecate(function(){}, 'except for stderr(2) and stdout(1), any other usage of DEBUG_FD is deprecated. Override debug.log if you want to use a different log function (https://git.io/debug_fd)')();
}
var stream = 1 === fd ? process.stdout :
2 === fd ? process.stderr :
createWritableStdioStream(fd);
/**
* Is stdout a TTY? Colored output is enabled when `true`.
*/
function useColors() {
return 'colors' in exports.inspectOpts
? Boolean(exports.inspectOpts.colors)
: tty__default['default'].isatty(fd);
}
/**
* Map %o to `util.inspect()`, all on a single line.
*/
exports.formatters.o = function(v) {
this.inspectOpts.colors = this.useColors;
return util__default['default'].inspect(v, this.inspectOpts)
.split('\n').map(function(str) {
return str.trim()
}).join(' ');
};
/**
* Map %o to `util.inspect()`, allowing multiple lines if needed.
*/
exports.formatters.O = function(v) {
this.inspectOpts.colors = this.useColors;
return util__default['default'].inspect(v, this.inspectOpts);
};
/**
* Adds ANSI color escape codes if enabled.
*
* @api public
*/
function formatArgs(args) {
var name = this.namespace;
var useColors = this.useColors;
if (useColors) {
var c = this.color;
var prefix = ' \u001b[3' + c + ';1m' + name + ' ' + '\u001b[0m';
args[0] = prefix + args[0].split('\n').join('\n' + prefix);
args.push('\u001b[3' + c + 'm+' + exports.humanize(this.diff) + '\u001b[0m');
} else {
args[0] = new Date().toUTCString()
+ ' ' + name + ' ' + args[0];
}
}
/**
* Invokes `util.format()` with the specified arguments and writes to `stream`.
*/
function log() {
return stream.write(util__default['default'].format.apply(util__default['default'], arguments) + '\n');
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
if (null == namespaces) {
// If you set a process.env field to null or undefined, it gets cast to the
// string 'null' or 'undefined'. Just delete instead.
delete process.env.DEBUG;
} else {
process.env.DEBUG = namespaces;
}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
return process.env.DEBUG;
}
/**
* Copied from `node/src/node.js`.
*
* XXX: It's lame that node doesn't expose this API out-of-the-box. It also
* relies on the undocumented `tty_wrap.guessHandleType()` which is also lame.
*/
function createWritableStdioStream (fd) {
var stream;
var tty_wrap = process.binding('tty_wrap');
// Note stream._type is used for test-module-load-list.js
switch (tty_wrap.guessHandleType(fd)) {
case 'TTY':
stream = new tty__default['default'].WriteStream(fd);
stream._type = 'tty';
// Hack to have stream not keep the event loop alive.
// See https://github.com/joyent/node/issues/1726
if (stream._handle && stream._handle.unref) {
stream._handle.unref();
}
break;
case 'FILE':
var fs = fs__default['default'];
stream = new fs.SyncWriteStream(fd, { autoClose: false });
stream._type = 'fs';
break;
case 'PIPE':
case 'TCP':
var net = net__default['default'];
stream = new net.Socket({
fd: fd,
readable: false,
writable: true
});
// FIXME Should probably have an option in net.Socket to create a
// stream from an existing fd which is writable only. But for now
// we'll just add this hack and set the `readable` member to false.
// Test: ./node test/fixtures/echo.js < /etc/passwd
stream.readable = false;
stream.read = null;
stream._type = 'pipe';
// FIXME Hack to have stream not keep the event loop alive.
// See https://github.com/joyent/node/issues/1726
if (stream._handle && stream._handle.unref) {
stream._handle.unref();
}
break;
default:
// Probably an error on in uv_guess_handle()
throw new Error('Implement me. Unknown stream file type!');
}
// For supporting legacy API we put the FD here.
stream.fd = fd;
stream._isStdio = true;
return stream;
}
/**
* Init logic for `debug` instances.
*
* Create a new `inspectOpts` object in case `useColors` is set
* differently for a particular `debug` instance.
*/
function init (debug) {
debug.inspectOpts = {};
var keys = Object.keys(exports.inspectOpts);
for (var i = 0; i < keys.length; i++) {
debug.inspectOpts[keys[i]] = exports.inspectOpts[keys[i]];
}
}
/**
* Enable namespaces listed in `process.env.DEBUG` initially.
*/
exports.enable(load());
});
var src = createCommonjsModule(function (module) {
/**
* Detect Electron renderer process, which is node, but we should
* treat as a browser.
*/
if (typeof process !== 'undefined' && process.type === 'renderer') {
module.exports = browser;
} else {
module.exports = node;
}
});
let debug$1 = src('net-reconnect');
class NetReconnect {
constructor (socket, options) {
this._socket = socket;
this._options = options;
this._retryTime = options.retryTime || 1000;
this._retryAlways = options.retryAlways || false;
this._keepAliveDelay = Math.max(options.keepAliveDelay, 1000) || 1000;
this._keepAliveInterval = Math.max(options.keepAliveInterval, 1000) || 1000;
this._keepAliveProbes = Math.max(Math.min(options.keepAliveProbes, 1), 20) || 1;
this._closing = false;
this._socket.on('connect', this._onConnect.bind(this));
this._socket.on('close', this._onClose.bind(this));
this._socket.on('error', this._onError.bind(this));
}
static apply (socket, options) {
return new NetReconnect(socket, options)
}
_reconnect () {
debug$1('reconnecting in %d', this._retryTime);
setTimeout(function () {
this._socket.connect(this._options);
}.bind(this), this._retryTime);
}
_onConnect () {
if (this._closing) {
return
}
this._socket.setKeepAlive(true, this._keepAliveDelay);
debug$1('online');
}
_onClose (hadError) {
if (this._closing) {
return
}
debug$1('offline');
this._state = 'offline';
if (!hadError) {
debug$1('connection closed on purpose');
if (this._retryAlways) {
debug$1('retryAlways flag active, reconnecting');
this._reconnect();
return
} else {
debug$1('not reconnecting');
return
}
}
debug$1('connection closed with errors, reconnecting');
this._reconnect();
}
_onError () {
if (this._closing) {
return
}
debug$1('error');
}
end () {
debug$1('closing socket permanently');
this._closing = true;
this._socket.removeListener('connect', this._onConnect);
this._socket.removeListener('close', this._onClose);
this._socket.removeListener('error', this._onError);
return this._socket.end.apply(this._socket, arguments)
}
}
var src$1 = NetReconnect;
var tcp = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var Reconnect, net, ref$, yellow, green, red, blue, bgGreen, bgRed, sleep, Logger, EventEmitter, TcpHandlerTransport, TcpTransport, logger, x$, transport, i, out$ = exports || commonjsGlobal, toString$ = {}.toString;
Reconnect = src$1;
net = net__default['default'];
ref$ = lib, yellow = ref$.yellow, green = ref$.green, red = ref$.red, blue = ref$.blue, bgGreen = ref$.bgGreen, bgRed = ref$.bgRed;
ref$ = lib$2, sleep = ref$.sleep, Logger = ref$.Logger, EventEmitter = ref$.EventEmitter;
out$.TcpHandlerTransport = TcpHandlerTransport = (function(superclass){
var prototype = extend$((import$(TcpHandlerTransport, superclass).displayName = 'TcpHandlerTransport', TcpHandlerTransport), superclass).prototype;
function TcpHandlerTransport(orig){
var x$, this$ = this;
this.orig = orig;
TcpHandlerTransport.superclass.call(this);
x$ = this.orig;
x$.on('end', function(){
return this$.trigger('disconnect');
});
x$.on('error', function(){
return this$.trigger('disconnect');
});
x$.on('data', function(data){
return this$.trigger('data', data);
});
}
TcpHandlerTransport.prototype.write = function(data){
return this.orig.write(data);
};
return TcpHandlerTransport;
}(EventEmitter));
out$.TcpTransport = TcpTransport = (function(superclass){
var prototype = extend$((import$(TcpTransport, superclass).displayName = 'TcpTransport', TcpTransport), superclass).prototype;
function TcpTransport(opts){
var x$, this$ = this;
opts == null && (opts = {});
TcpTransport.superclass.call(this);
this.opts = {
host: opts.host || "localhost",
port: opts.port || 5523,
retryAlways: true
};
this.log = new Logger('TCP_Transport');
this.socket = new net.Socket();
Reconnect.apply(this.socket, this.opts);
this.connected = false;
x$ = this.socket;
x$.setKeepAlive(true, 1000);
x$.setTimeout(1000);
x$.on('connect', function(){
return this$.connected = true;
});
x$.on('close', function(){
return this$.connected = false;
});
x$.on('data', function(data){
return this$.trigger('data', data);
});
x$.on('end', function(){
return this$.connected = false;
});
x$.on('error', function(err){
return this$.connected = false;
});
if (!opts.manualStart) {
this.start();
}
}
Object.defineProperty(TcpTransport.prototype, 'connected', {
get: function(){
return this._connected;
},
set: function(val){
var prev;
prev = this._connected;
this._connected = val;
if (!val && prev) {
this.trigger('disconnect');
}
if (val && !prev) {
this.trigger('connect');
}
},
configurable: true,
enumerable: true
});
TcpTransport.prototype.start = function(){
return this.socket.connect(this.opts);
};
TcpTransport.prototype.write = function(data, callback){
var e;
if (toString$.call(callback).slice(8, -1) !== 'Function') {
callback = function(){};
}
if (this.connected) {
try {
return this.socket.write(data, function(){
var err;
return callback(err = null);
});
} catch (e$) {
e = e$;
console.log("there is error again: ", e);
throw null;
}
} else {
return callback({
message: 'not connected'
/* disabling, because this will likely cause memory leak
* for long disconnections
resolved: (callback) ~>
@once \connect, callback
*/
});
}
};
return TcpTransport;
}(EventEmitter));
if (commonjsRequire.main === module) {
logger = new Logger('APP');
x$ = transport = new TcpTransport({
host: 'localhost',
port: 1234
});
x$.on('connect', function(){
return logger.log("transport connected");
});
x$.on('data', function(frame){
return logger.log("frame received:", frame.toString());
});
x$.on('disconnect', function(){
return logger.log("transport disconnected ");
});
i = 0;
(function lo(op){
var payload;
payload = "sending incremental data: " + i;
logger.log(payload);
return transport.write(payload + "\n", function(err){
if (err) {
logger.err("something went wrong while writing");
return sleep(1000, function(){
return lo(op);
});
} else {
if (++i > 10) {
return op();
}
return sleep(2000, function(){
return lo(op);
});
}
});
})(function(){
return logger.log("End of tests.");
});
}
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
var client$1 = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ProxyClient, TcpTransport, sleep, DcsTcpClient, out$ = exports || commonjsGlobal;
ProxyClient = client.ProxyClient;
TcpTransport = tcp.TcpTransport;
sleep = deps$1.sleep;
out$.DcsTcpClient = DcsTcpClient = (function(superclass){
var prototype = extend$((import$(DcsTcpClient, superclass).displayName = 'DcsTcpClient', DcsTcpClient), superclass).prototype;
function DcsTcpClient(opts){
var transport, this$ = this;
this.opts = opts != null
? opts
: {};
this.opts.port || (function(){
throw "DcsTcpClient: Port is required.";
}());
transport = new TcpTransport({
host: this.opts.host || '127.0.0.1',
port: this.opts.port
});
DcsTcpClient.superclass.call(this, transport, {
name: 'TcpDcsClient',
forgetPassword: false
});
this.on('connect', function(){
return this$.log.info("Connected to server...");
});
this.onTopic('app.dcs.connect', function(msg){
return this$.log.info("Tcp Client is logged in into the DCS network.");
});
this.on('disconnect', function(){
this$.log.info("Disconnected.");
this$.log.info("ProxyClient will try to reconnect.");
return sleep(3000, function(){
return this$.trigger('_login');
});
});
}
return DcsTcpClient;
}(ProxyClient));
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
var ioProxyClient = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var Actor, sleep, FpsExec, topicMatch, _x, uuid4, IoProxyClient, out$ = exports || commonjsGlobal, toString$ = {}.toString;
Actor = actor.Actor;
sleep = sleep_1.sleep;
FpsExec = filters.FpsExec;
topicMatch = topicMatch_1.topicMatch;
_x = 0;
uuid4 = function(){
return "some-random-" + (_x++);
};
out$.IoProxyClient = IoProxyClient = (function(superclass){
var prototype = extend$((import$(IoProxyClient, superclass).displayName = 'IoProxyClient', IoProxyClient), superclass).prototype;
function IoProxyClient(opts){
var update, this$ = this;
opts == null && (opts = {});
this.route = opts.route || (function(){
throw "route is required.";
}());
this.timeout = opts.timeout || 1000;
IoProxyClient.superclass.call(this, this.route);
this.fps = new FpsExec(opts.fps || 20, this);
this.value = undefined;
this.lastUpdate = 0;
this.debug = opts.debug;
this.onTopic(this.route + "", function(msg){
var that, value;
if (that = msg.data.err) {
return this$.trigger('error', {
message: that
});
} else {
value = msg.data.val;
if (JSON.stringify(value) !== JSON.stringify(this$.value)) {
this$.trigger('change', value);
if (toString$.call(value).slice(8, -1) === 'Boolean') {
if (this$.value === false && value === true) {
this$.trigger('r-edge');
}
if (this$.value === true && value === false) {
this$.trigger('f-edge');
}
}
}
this$.lastUpdate = Date.now();
this$.value = value;
return this$.trigger('read', value, msg);
}
});
update = function(callback){
if (!callback) {
callback = function(){};
}
return this$.sendRequest({
route: this$.route + "",
timeout: this$.timeout
}, {
update: true
}, function(err, msg){
if (err || msg.err) {
this$.trigger('error', {
message: err
});
return callback(err);
} else {
this$.triggerTopic(this$.route + "", msg);
return callback(null);
}
});
};
this.onEveryLogin(function(msg){
var retryLimit;
retryLimit = 3;
return function lo(op){
return update(function(err){
if (err) {
retryLimit--;
if (retryLimit === 0) {
return op();
}
this$.log.warn("Update error, retrying... (left: " + retryLimit + ")");
return sleep(1000, function(){
return lo(op);
});
} else {
return op();
}
});
}(function(){});
});
}
IoProxyClient.prototype.rEdge = function(callback){
this.once('r-edge', callback);
};
IoProxyClient.prototype.fEdge = function(callback){
this.once('f-edge', callback);
};
IoProxyClient.prototype.when = function(filterFunc, callback){
var name, this$ = this;
name = uuid4();
this.on('change', name, function(value){
if (filterFunc(value)) {
return setImmediate(function(){
callback(value);
return this$.cancel(name);
});
}
});
};
IoProxyClient.prototype.write = function(value, callback){
var this$ = this;
this.fps.exec(function(){
this$.fps.pause();
return this$.filteredWrite(value, function(){
var args, res$, i$, to$, that;
res$ = [];
for (i$ = 0, to$ = arguments.length; i$ < to$; ++i$) {
res$.push(arguments[i$]);
}
args = res$;
this$.fps.resume();
if ((that = callback) != null) {
return that.apply(null, args);
}
});
});
};
IoProxyClient.prototype.read = function(callback){
this.sendRequest({
route: this.route,
timeout: this.timeout,
debug: this.debug
}, {
read: true
}, function(err, msg){
return callback(err, msg);
});
};
IoProxyClient.prototype.filteredWrite = function(value, callback){
var this$ = this;
this.sendRequest({
route: this.route,
timeout: this.timeout,
debug: this.debug
}, {
val: value
}, function(err, msg){
var error;
error = err || (msg != null ? msg.data.err : void 8);
if (!err) {
this$.value = msg.data.res;
}
if (toString$.call(callback).slice(8, -1) === 'Function') {
return callback(error);
}
});
};
return IoProxyClient;
}(Actor));
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
var keypath = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var getKeypath, setKeypath, deleteKeypath, out$ = exports || commonjsGlobal;
out$.getKeypath = getKeypath = function(obj, keypath){
var res, i$, ref$, len$, k;
res = obj;
if (keypath) {
for (i$ = 0, len$ = (ref$ = keypath.split('.')).length; i$ < len$; ++i$) {
k = ref$[i$];
res = (fn$());
}
}
return res;
function fn$(){
try {
return res[k];
} catch (e$) {
return null;
}
}
};
out$.setKeypath = setKeypath = function(obj, keypath, value){
var _set, path;
_set = function(_obj, _keypath){
var k;
if (_keypath.length === 0) {
return _obj;
}
k = _keypath.shift();
if (_keypath.length === 0) {
return _obj[k] = value;
} else {
if (!_obj[k]) {
_obj[k] = {};
}
_set(_obj[k], _keypath);
}
return _obj;
};
path = (keypath != null ? keypath.split('.') : void 8) || [];
return _set(obj, path);
};
out$.deleteKeypath = deleteKeypath = function(obj, keypath){
var _keypath, firstProp, lastProp, tmp, i$, x$, len$, ref$, key, results$ = [];
if (keypath) {
_keypath = keypath.split('.');
firstProp = _keypath.shift();
lastProp = _keypath.pop();
tmp = obj[firstProp];
for (i$ = 0, len$ = _keypath.length; i$ < len$; ++i$) {
x$ = _keypath[i$];
tmp = tmp[x$];
}
if (lastProp in tmp) {
return ref$ = tmp[lastProp], delete tmp[lastProp], ref$;
} else {
throw "no such key";
}
} else {
for (key in obj) {
results$.push((ref$ = obj[key], delete obj[key], ref$));
}
return results$;
}
};
});
var memoryMap = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var ref$, split, keys, map, getKeypath, CodingError, bitTest, bitWrite, dec2bin, splitBits, dataTypes, IoHandle, parseIoAddr, makeIoAddr, BlockRead, out$ = exports || commonjsGlobal, toString$ = {}.toString;
ref$ = lib$1, split = ref$.split, keys = ref$.keys, map = ref$.map;
getKeypath = keypath.getKeypath;
CodingError = errors.CodingError;
function hex2float (a) {return (a & 0x7fffff | 0x800000) * 1.0 / Math.pow(2,23) * Math.pow(2, ((a>>23 & 0xff) - 127))}
function bit_test(num, bit){
return ((num>>bit) % 2 != 0)
}
function bit_set(num, bit){
return num | 1<<bit;
}
function bit_clear(num, bit){
return num & ~(1<<bit);
}
out$.bitTest = bitTest = bit_test;
out$.bitWrite = bitWrite = function(source, bitNum, value){
if (value) {
return bit_set(source, bitNum);
} else {
return bit_clear(source, bitNum);
}
};
out$.dec2bin = dec2bin = function(dec){
'dec2bin(1); // 1\ndec2bin(-1); // 11111111111111111111111111111111\ndec2bin(256); // 100000000\ndec2bin(-256); // 11111111111111111111111100000000';
return dec >>> 0 .toString(2);
};
// taken from https://stackoverflow.com/a/1268377/1952991
function zeroPad(num, numZeros) {
var n = Math.abs(num);
var zeros = Math.max(0, numZeros - Math.floor(n).toString().length );
var zeroString = Math.pow(10,zeros).toString().substr(1);
if( num < 0 ) {
zeroString = '-' + zeroString;
}
return zeroString+n;
}
out$.zeroPad = zeroPad;
out$.splitBits = splitBits = function(input){
var bin, zpad8;
bin = (+input).toString(2);
zpad8 = function(it){
return ("00000000" + it).slice(-8);
};
return function(it){
return it.split("").reverse().map(function(it){
return parseInt(
it.trim());
});
}(
zpad8(
bin));
};
dataTypes = {
int: function(x){
return parseInt(x);
},
hex: function(x){
return x.toString(16).toUpperCase();
},
hexf: hex2float,
mili: (function(it){
return it / 1000;
}),
bool: Boolean
};
out$.IoHandle = IoHandle = (function(){
'This class adds some useful methods to an IO object, such as: \n\n .get-meaningful(raw-value): Returns meaningful value\n regarding to the @type. ';
IoHandle.displayName = 'IoHandle';
function IoHandle(opts, route){
var k, v;
opts == null && (opts = {});
for (k in opts) {
v = opts[k];
this[k] = v;
}
this.route = route;
this.id = this.route;
}
IoHandle.prototype.getMeaningful = function(value){
if (toString$.call(this.converter).slice(8, -1)) {
return this.converter(value);
} else {
if (!this.type) {
throw Error('unimplemented');
}
return dataTypes[this.type](value);
}
};
IoHandle.prototype.registerConverter = function(converter){
return this.converter = converter;
};
return IoHandle;
}());
out$.parseIoAddr = parseIoAddr = function(fullName){
var ref$, prefix, byte, bitSep, bit, parsed;
ref$ = fullName.split(/(\d+)/), prefix = ref$[0], byte = ref$[1], bitSep = ref$[2], bit = ref$[3];
parsed = {
prefix: prefix,
byte: parseInt(byte),
bit: bitSep ? parseInt(bit) : null,
bool: bitSep ? true : false
};
return parsed;
};
out$.makeIoAddr = makeIoAddr = function(prefix, byte, bit){
return prefix + "" + byte + (bit ? "." + bit : void 8);
};
out$.BlockRead = BlockRead = (function(){
BlockRead.displayName = 'BlockRead';
function BlockRead(opts){
this.prefix = opts.prefix;
this.from = opts.from;
this.count = opts.count;
this.bits0 = [];
this.bits = [];
this.handlers = {};
}
Object.defineProperty(BlockRead.prototype, 'readParams', {
get: function(){
return [this.prefix, this.from, this.count];
},
configurable: true,
enumerable: true
});
BlockRead.prototype.addHandler = function(name, handler){
if (name in this.handlers) {
return console.error(name + " is already registered, not registering again.");
} else {
return this.handlers[name] = handler;
}
};
BlockRead.prototype.distribute = function(arr){
var i$, x$, len$, i, j, ref$, addr, ref1$, err;
this.bits.length = 0;
for (i$ = 0, len$ = arr.length; i$ < len$; ++i$) {
x$ = arr[i$];
this.bits.push(splitBits(x$));
}
for (i in this.bits) {
for (j in this.bits[i]) {
if (this.bits[i][j] !== ((ref$ = this.bits0[i]) != null ? ref$[j] : void 8)) {
addr = makeIoAddr(this.prefix, i, j);
if (typeof (ref1$ = this.handlers)[addr] == 'function') {
ref1$[addr](err = null, this.bits[i][j]);
}
}
}
}
this.bits0 = JSON.parse(JSON.stringify(this.bits));
};
return BlockRead;
}());
});
var ioProxyHandler = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var Actor, EventEmitter, sleep, Logger, CodingError, IoHandle, IoProxyHandler, out$ = exports || commonjsGlobal;
Actor = actor.Actor;
EventEmitter = eventEmitter.EventEmitter;
sleep = sleep_1.sleep;
Logger = logger.Logger;
CodingError = errors.CodingError;
IoHandle = memoryMap.IoHandle;
out$.IoProxyHandler = IoProxyHandler = (function(superclass){
var prototype = extend$((import$(IoProxyHandler, superclass).displayName = 'IoProxyHandler', IoProxyHandler), superclass).prototype;
function IoProxyHandler(handle, _route, driver){
var ref$, route, prev, age, broadcastValue, responseValue, this$ = this;
if (!driver) {
driver = _route;
_route = null;
if ((handle != null ? (ref$ = handle.constructor) != null ? ref$.name : void 8 : void 8) !== 'IoHandle') {
throw new CodingError("handle should be an instance of IoHandle class");
}
} else {
handle = new IoHandle(handle, _route);
}
if (!driver) {
throw new CodingError("Driver must be provided");
}
if (!(route = handle.route)) {
throw new CodingError("A route MUST be provided to IoProxyHandler.");
}
IoProxyHandler.superclass.call(this, route);
prev = null;
age = 0;
broadcastValue = function(err, value){
this$.send(this$.name + "", {
err: err,
val: value
});
if (!err && value !== prev) {
prev = value;
return age = Date.now();
}
};
responseValue = function(msg){
return function(err, value){
this$.sendResponse(msg, {
err: err,
val: value
});
if (!err && value !== prev) {
prev = value;
return age = Date.now();
}
};
};
this.on('read', function(handle, respond){
return driver.read(handle, function(err, value){
return respond(err, value);
});
});
this.on('write', function(handle, value, respond){
return driver.write(handle, value, function(err){
return respond(err);
});
});
driver.initHandle(handle, broadcastValue);
this.onTopic(route, function(msg){
var newValue, maxAge, err, value;
if ('val' in msg.data) {
newValue = msg.data.val;
return this$.trigger('write', handle, newValue, function(err){
var meta, data;
meta = {
cc: this$.name + ""
};
data = {
err: err
};
if (!err) {
data.val = newValue;
prev = newValue;
}
return this$.sendResponse(msg, meta, data);
});
} else if ('update' in msg.data) {
maxAge = 10 * 60000;
if (maxAge + age < Date.now()) {
return this$.trigger('read', handle, responseValue(msg));
} else {
return responseValue(msg)(err = null, value = prev);
}
} else {
return this$.trigger('read', handle, responseValue(msg));
}
});
this.onEveryLogin(function(msg){
return this$.trigger('_try_broadcast_state');
});
driver.on('connect', function(){
return this$.trigger('_try_broadcast_state');
});
driver.on('disconnect', function(){
var err;
return broadcastValue(err = "Target is disconnected.");
});
driver.on('data', function(table){
var value, err;
if (handle.id in table) {
value = table[handle.id];
if (value !== prev) {
return broadcastValue(err = null, value);
}
}
});
this.on('_try_broadcast_state', function(){
if (driver.connected) {
return this$.trigger('read', handle, broadcastValue);
} else {
return this$.log.info("Driver is not connected, skipping broadcasting.");
}
});
if (!driver.starting || !driver.started) {
driver.start();
}
}
return IoProxyHandler;
}(Actor));
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
var driverAbstract = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var EventEmitter, Logger, DriverAbstract, out$ = exports || commonjsGlobal;
EventEmitter = eventEmitter.EventEmitter;
Logger = logger.Logger;
out$.DriverAbstract = DriverAbstract = (function(superclass){
var prototype = extend$((import$(DriverAbstract, superclass).displayName = 'DriverAbstract', DriverAbstract), superclass).prototype;
function DriverAbstract(){
var implementedBy;
DriverAbstract.superclass.call(this);
this._queue = [];
this.io = {};
this.logger = new Logger(implementedBy = this.constructor.name);
}
DriverAbstract.prototype.initHandle = function(handle, broadcast){
throw Error('unimplemented');
};
DriverAbstract.prototype.write = function(handle, value, respond){
throw Error('unimplemented');
};
DriverAbstract.prototype._exec_sequential = function(func){
var i$, res$, j$;
res$ = [];
for (j$ = 1 < (i$ = arguments.length - 1) ? 1 : (i$ = 1); j$ < i$; ++j$) {
res$.push(arguments[j$]);
}
this._queue.push(arguments);
throw Error('unimplemented');
};
DriverAbstract.prototype.read = function(handle, respond){
throw Error('unimplemented');
};
DriverAbstract.prototype.start = function(){
this.starting = true;
this.logger.log("Driver immediately started.");
return this.connected = true;
};
Object.defineProperty(DriverAbstract.prototype, 'connected', {
get: function(){
return this._connected;
},
set: function(val){
if (val === true) {
this._connected = true;
this.started = true;
this.trigger('connect');
} else {
this._connected = false;
this.started = false;
this.starting = false;
this.trigger('disconnect');
}
},
configurable: true,
enumerable: true
});
return DriverAbstract;
}(EventEmitter));
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
});
// Generated by LiveScript 1.6.0
var Actor$1, FpsExec, ref$$3, Signal$3, SignalBranch$1, DcsTcpClient, EventEmitter$1, Logger$3, sleep$3, merge$1, pack$2, unpack$2, clone$3, diff$2, topicMatch$1, IoProxyClient, IoProxyHandler, DriverAbstract;
Actor$1 = actor.Actor;
FpsExec = filters.FpsExec;
ref$$3 = signal$1, Signal$3 = ref$$3.Signal, SignalBranch$1 = ref$$3.SignalBranch;
/* if dependencies of the followings are optionally installed,
then they shouldn't be included by default.
require! './services/couch-dcs/client': {CouchDcsClient}
require! './services/couch-dcs/server': {CouchDcsServer}
*/
DcsTcpClient = client$1.DcsTcpClient;
ref$$3 = lib$2, EventEmitter$1 = ref$$3.EventEmitter, Logger$3 = ref$$3.Logger, sleep$3 = ref$$3.sleep, merge$1 = ref$$3.merge, pack$2 = ref$$3.pack, unpack$2 = ref$$3.unpack, clone$3 = ref$$3.clone, diff$2 = ref$$3.diff;
topicMatch$1 = topicMatch_1.topicMatch;
IoProxyClient = ioProxyClient.IoProxyClient;
IoProxyHandler = ioProxyHandler.IoProxyHandler;
DriverAbstract = driverAbstract.DriverAbstract;
var dcs = {
Actor: Actor$1,
FpsExec: FpsExec,
Signal: Signal$3,
SignalBranch: SignalBranch$1,
DcsTcpClient: DcsTcpClient,
EventEmitter: EventEmitter$1,
Logger: Logger$3,
sleep: sleep$3,
merge: merge$1,
pack: pack$2,
unpack: unpack$2,
clone: clone$3,
diff: diff$2,
IoProxyClient: IoProxyClient,
IoProxyHandler: IoProxyHandler,
DriverAbstract: DriverAbstract,
topicMatch: topicMatch$1
};
var config = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var webserverPort, dcsPort, defaultPassword, out$ = exports || commonjsGlobal;
out$.webserverPort = webserverPort = 4013;
out$.dcsPort = dcsPort = 4014;
out$.defaultPassword = defaultPassword = "nCEqCyoyreg05ts4WmsVrPmPpw0dwt93";
});
var ractiveTemplate = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var Ractive, compile, ractiveCompile, out$ = exports || commonjsGlobal;
Ractive = ractive__default['default'];
Ractive.DEBUG = false;
compile = function(template, data){
var instance;
template == null && (template = "");
data == null && (data = {});
instance = new Ractive({
template: Ractive.parse(template, {
textOnlyMode: true,
preserveWhitespace: true
}),
data: data
});
return instance.toHTML();
};
/*
compile2 = (template="", data={}) ->
[prefix, postfix] = <[ <pre> </pre> ]>
instance = new Ractive do
template: prefix + template + postfix
data: data
return instance.toHTML!.slice(prefix.length, -postfix.length)
*/
out$.ractiveCompile = ractiveCompile = compile;
});
var readdirSyncRecursive_1 = createCommonjsModule(function (module, exports) {
// Generated by LiveScript 1.6.0
var fs, path, out$ = exports || commonjsGlobal;
fs = fs__default['default'];
path = path__default['default'];
out$.readdirSyncRecursive = readdirSyncRecursive;
function readdirSyncRecursive(dir, files, arg$){
var sub, f, i$, len$, file;
files == null && (files = []);
sub = (arg$ != null
? arg$
: {}).sub;
f = fs.readdirSync(dir);
for (i$ = 0, len$ = f.length; i$ < len$; ++i$) {
file = f[i$];
if (fs.statSync(dir + "/" + file).isDirectory()) {
files = readdirSyncRecursive(dir + "/" + file, files, {
sub: path.join(sub || '', file)
});
} else {
files.push(path.join(sub || '', file));
}
}
return files;
}
});
var supportedMcus = [
{
chibiDef: "STM32F030x6",
mcuCode: "STM32F030C6Tx",
stmGlob: "STM32F030C6Tx"
},
{
chibiDef: "STM32F030x8",
mcuCode: "STM32F030C8Tx",
stmGlob: "STM32F030C8Tx"
},
{
chibiDef: "STM32F030xC",
mcuCode: "STM32F030CCTx",
stmGlob: "STM32F030CCTx"
},
{
chibiDef: "STM32F030x4",
mcuCode: "STM32F030F4Px",
stmGlob: "STM32F030F4Px"
},
{
chibiDef: "STM32F030x6",
mcuCode: "STM32F030K6Tx",
stmGlob: "STM32F030K6Tx"
},
{
chibiDef: "STM32F030x8",
mcuCode: "STM32F030R8Tx",
stmGlob: "STM32F030R8Tx"
},
{
chibiDef: "STM32F030xC",
mcuCode: "STM32F030RCTx",
stmGlob: "STM32F030RCTx"
},
{
chibiDef: "STM32F031x6",
mcuCode: "STM32F031C6Tx",
stmGlob: "STM32F031C(4-6)Tx"
},
{
chibiDef: "STM32F031x6",
mcuCode: "STM32F031E6Yx",
stmGlob: "STM32F031E6Yx"
},
{
chibiDef: "STM32F031x6",
mcuCode: "STM32F031F6Px",
stmGlob: "STM32F031F(4-6)Px"
},
{
chibiDef: "STM32F031x6",
mcuCode: "STM32F031G6Ux",
stmGlob: "STM32F031G(4-6)Ux"
},
{
chibiDef: "STM32F031x6",
mcuCode: "STM32F031K6Ux",
stmGlob: "STM32F031K(4-6)Ux"
},
{
chibiDef: "STM32F031x6",
mcuCode: "STM32F031K6Tx",
stmGlob: "STM32F031K6Tx"
},
{
chibiDef: "STM32F038xx",
mcuCode: "STM32F038C6Tx",
stmGlob: "STM32F038C6Tx"
},
{
chibiDef: "STM32F038xx",
mcuCode: "STM32F038E6Yx",
stmGlob: "STM32F038E6Yx"
},
{
chibiDef: "STM32F038xx",
mcuCode: "STM32F038F6Px",
stmGlob: "STM32F038F6Px"
},
{
chibiDef: "STM32F038xx",
mcuCode: "STM32F038G6Ux",
stmGlob: "STM32F038G6Ux"
},
{
chibiDef: "STM32F038xx",
mcuCode: "STM32F038K6Ux",
stmGlob: "STM32F038K6Ux"
},
{
chibiDef: "STM32F042x6",
mcuCode: "STM32F042C6Tx",
stmGlob: "STM32F042C(4-6)Tx"
},
{
chibiDef: "STM32F042x6",
mcuCode: "STM32F042C6Ux",
stmGlob: "STM32F042C(4-6)Ux"
},
{
chibiDef: "STM32F042x6",
mcuCode: "STM32F042F6Px",
stmGlob: "STM32F042F6Px"
},
{
chibiDef: "STM32F042x6",
mcuCode: "STM32F042G6Ux",
stmGlob: "STM32F042G(4-6)Ux"
},
{
chibiDef: "STM32F042x6",
mcuCode: "STM32F042K6Tx",
stmGlob: "STM32F042K(4-6)Tx"
},
{
chibiDef: "STM32F042x6",
mcuCode: "STM32F042K6Ux",
stmGlob: "STM32F042K(4-6)Ux"
},
{
chibiDef: "STM32F042x6",
mcuCode: "STM32F042T6Yx",
stmGlob: "STM32F042T6Yx"
},
{
chibiDef: "STM32F048xx",
mcuCode: "STM32F048C6Ux",
stmGlob: "STM32F048C6Ux"
},
{
chibiDef: "STM32F048xx",
mcuCode: "STM32F048G6Ux",
stmGlob: "STM32F048G6Ux"
},
{
chibiDef: "STM32F048xx",
mcuCode: "STM32F048T6Yx",
stmGlob: "STM32F048T6Yx"
},
{
chibiDef: "STM32F051x8",
mcuCode: "STM32F051C8Tx",
stmGlob: "STM32F051C8Tx"
},
{
chibiDef: "STM32F051x8",
mcuCode: "STM32F051C8Ux",
stmGlob: "STM32F051C8Ux"
},
{
chibiDef: "STM32F051x8",
mcuCode: "STM32F051K8Tx",
stmGlob: "STM32F051K8Tx"
},
{
chibiDef: "STM32F051x8",
mcuCode: "STM32F051K8Ux",
stmGlob: "STM32F051K8Ux"
},
{
chibiDef: "STM32F051x8",
mcuCode: "STM32F051R8Hx",
stmGlob: "STM32F051R8Hx"
},
{
chibiDef: "STM32F051x8",
mcuCode: "STM32F051R8Tx",
stmGlob: "STM32F051R8Tx"
},
{
chibiDef: "STM32F051x8",
mcuCode: "STM32F051T8Yx",
stmGlob: "STM32F051T8Yx"
},
{
chibiDef: "STM32F058xx",
mcuCode: "STM32F058C8Ux",
stmGlob: "STM32F058C8Ux"
},
{
chibiDef: "STM32F058xx",
mcuCode: "STM32F058R8Hx",
stmGlob: "STM32F058R8Hx"
},
{
chibiDef: "STM32F058xx",
mcuCode: "STM32F058R8Tx",
stmGlob: "STM32F058R8Tx"
},
{
chibiDef: "STM32F058xx",
mcuCode: "STM32F058T8Yx",
stmGlob: "STM32F058T8Yx"
},
{
chibiDef: "STM32F070x6",
mcuCode: "STM32F070C6Tx",
stmGlob: "STM32F070C6Tx"
},
{
chibiDef: "STM32F070xB",
mcuCode: "STM32F070CBTx",
stmGlob: "STM32F070CBTx"
},
{
chibiDef: "STM32F070x6",
mcuCode: "STM32F070F6Px",
stmGlob: "STM32F070F6Px"
},
{
chibiDef: "STM32F070xB",
mcuCode: "STM32F070RBTx",
stmGlob: "STM32F070RBTx"
},
{
chibiDef: "STM32F071xB",
mcuCode: "STM32F071CBTx",
stmGlob: "STM32F071C(8-B)Tx"
},
{
chibiDef: "STM32F071xB",
mcuCode: "STM32F071CBUx",
stmGlob: "STM32F071C(8-B)Ux"
},
{
chibiDef: "STM32F071xB",
mcuCode: "STM32F071CBYx",
stmGlob: "STM32F071CBYx"
},
{
chibiDef: "STM32F071xB",
mcuCode: "STM32F071RBTx",
stmGlob: "STM32F071RBTx"
},
{
chibiDef: "STM32F071xB",
mcuCode: "STM32F071VBHx",
stmGlob: "STM32F071V(8-B)Hx"
},
{
chibiDef: "STM32F071xB",
mcuCode: "STM32F071VBTx",
stmGlob: "STM32F071V(8-B)Tx"
},
{
chibiDef: "STM32F072xB",
mcuCode: "STM32F072CBTx",
stmGlob: "STM32F072C(8-B)Tx"
},
{
chibiDef: "STM32F072xB",
mcuCode: "STM32F072CBUx",
stmGlob: "STM32F072C(8-B)Ux"
},
{
chibiDef: "STM32F072xB",
mcuCode: "STM32F072CBYx",
stmGlob: "STM32F072CBYx"
},
{
chibiDef: "STM32F072xB",
mcuCode: "STM32F072RBTx",
stmGlob: "STM32F072R(8-B)Tx"
},
{
chibiDef: "STM32F072xB",
mcuCode: "STM32F072RBHx",
stmGlob: "STM32F072RBHx"
},
{
chibiDef: "STM32F072xB",
mcuCode: "STM32F072RBIx",
stmGlob: "STM32F072RBIx"
},
{
chibiDef: "STM32F072xB",
mcuCode: "STM32F072VBHx",
stmGlob: "STM32F072V(8-B)Hx"
},
{
chibiDef: "STM32F072xB",
mcuCode: "STM32F072VBTx",
stmGlob: "STM32F072V(8-B)Tx"
},
{
chibiDef: "STM32F078xx",
mcuCode: "STM32F078CBTx",
stmGlob: "STM32F078CBTx"
},
{
chibiDef: "STM32F078xx",
mcuCode: "STM32F078CBUx",
stmGlob: "STM32F078CBUx"
},
{
chibiDef: "STM32F078xx",
mcuCode: "STM32F078CBYx",
stmGlob: "STM32F078CBYx"
},
{
chibiDef: "STM32F078xx",
mcuCode: "STM32F078RBHx",
stmGlob: "STM32F078RBHx"
},
{
chibiDef: "STM32F078xx",
mcuCode: "STM32F078RBTx",
stmGlob: "STM32F078RBTx"
},
{
chibiDef: "STM32F078xx",
mcuCode: "STM32F078VBHx",
stmGlob: "STM32F078VBHx"
},
{
chibiDef: "STM32F078xx",
mcuCode: "STM32F078VBTx",
stmGlob: "STM32F078VBTx"
},
{
chibiDef: "STM32F091xC",
mcuCode: "STM32F091CCTx",
stmGlob: "STM32F091C(B-C)Tx"
},
{
chibiDef: "STM32F091xC",
mcuCode: "STM32F091CCUx",
stmGlob: "STM32F091C(B-C)Ux"
},
{
chibiDef: "STM32F091xC",
mcuCode: "STM32F091RCTx",
stmGlob: "STM32F091R(B-C)Tx"
},
{
chibiDef: "STM32F091xC",
mcuCode: "STM32F091RCHx",
stmGlob: "STM32F091RCHx"
},
{
chibiDef: "STM32F091xC",
mcuCode: "STM32F091RCYx",
stmGlob: "STM32F091RCYx"
},
{
chibiDef: "STM32F091xC",
mcuCode: "STM32F091VCTx",
stmGlob: "STM32F091V(B-C)Tx"
},
{
chibiDef: "STM32F091xC",
mcuCode: "STM32F091VCHx",
stmGlob: "STM32F091VCHx"
},
{
chibiDef: "STM32F098xx",
mcuCode: "STM32F098CCTx",
stmGlob: "STM32F098CCTx"
},
{
chibiDef: "STM32F098xx",
mcuCode: "STM32F098CCUx",
stmGlob: "STM32F098CCUx"
},
{
chibiDef: "STM32F098xx",
mcuCode: "STM32F098RCHx",
stmGlob: "STM32F098RCHx"
},
{
chibiDef: "STM32F098xx",
mcuCode: "STM32F098RCTx",
stmGlob: "STM32F098RCTx"
},
{
chibiDef: "STM32F098xx",
mcuCode: "STM32F098RCYx",
stmGlob: "STM32F098RCYx"
},
{
chibiDef: "STM32F098xx",
mcuCode: "STM32F098VCHx",
stmGlob: "STM32F098VCHx"
},
{
chibiDef: "STM32F098xx",
mcuCode: "STM32F098VCTx",
stmGlob: "STM32F098VCTx"
},
{
chibiDef: "STM32F100xB",
mcuCode: "STM32F100CBTx",
stmGlob: "STM32F100C(8-B)Tx"
},
{
chibiDef: "STM32F100xB",
mcuCode: "STM32F100RBHx",
stmGlob: "STM32F100R(8-B)Hx"
},
{
chibiDef: "STM32F100xB",
mcuCode: "STM32F100RBTx",
stmGlob: "STM32F100R(8-B)Tx"
},
{
chibiDef: "STM32F100xE",
mcuCode: "STM32F100RETx",
stmGlob: "STM32F100R(C-D-E)Tx"
},
{
chibiDef: "STM32F100xB",
mcuCode: "STM32F100VBTx",
stmGlob: "STM32F100V(8-B)Tx"
},
{
chibiDef: "STM32F100xE",
mcuCode: "STM32F100VETx",
stmGlob: "STM32F100V(C-D-E)Tx"
},
{
chibiDef: "STM32F100xE",
mcuCode: "STM32F100ZETx",
stmGlob: "STM32F100Z(C-D-E)Tx"
},
{
chibiDef: "STM32F101x6",
mcuCode: "STM32F101C6Tx",
stmGlob: "STM32F101C(4-6)Tx"
},
{
chibiDef: "STM32F101xB",
mcuCode: "STM32F101CBTx",
stmGlob: "STM32F101C(8-B)Tx"
},
{
chibiDef: "STM32F101xB",
mcuCode: "STM32F101CBUx",
stmGlob: "STM32F101C(8-B)Ux"
},
{
chibiDef: "STM32F101x6",
mcuCode: "STM32F101R6Tx",
stmGlob: "STM32F101R(4-6)Tx"
},
{
chibiDef: "STM32F101xB",
mcuCode: "STM32F101RBTx",
stmGlob: "STM32F101R(8-B)Tx"
},
{
chibiDef: "STM32F101xB",
mcuCode: "STM32F101RBHx",
stmGlob: "STM32F101RBHx"
},
{
chibiDef: "STM32F101xE",
mcuCode: "STM32F101RETx",
stmGlob: "STM32F101R(C-D-E)Tx"
},
{
chibiDef: "STM32F101xG",
mcuCode: "STM32F101RGTx",
stmGlob: "STM32F101R(F-G)Tx"
},
{
chibiDef: "STM32F101x6",
mcuCode: "STM32F101T6Ux",
stmGlob: "STM32F101T(4-6)Ux"
},
{
chibiDef: "STM32F101xB",
mcuCode: "STM32F101TBUx",
stmGlob: "STM32F101T(8-B)Ux"
},
{
chibiDef: "STM32F101xB",
mcuCode: "STM32F101VBTx",
stmGlob: "STM32F101V(8-B)Tx"
},
{
chibiDef: "STM32F101xE",
mcuCode: "STM32F101VETx",
stmGlob: "STM32F101V(C-D-E)Tx"
},
{
chibiDef: "STM32F101xG",
mcuCode: "STM32F101VGTx",
stmGlob: "STM32F101V(F-G)Tx"
},
{
chibiDef: "STM32F101xE",
mcuCode: "STM32F101ZETx",
stmGlob: "STM32F101Z(C-D-E)Tx"
},
{
chibiDef: "STM32F101xG",
mcuCode: "STM32F101ZGTx",
stmGlob: "STM32F101Z(F-G)Tx"
},
{
chibiDef: "STM32F102x6",
mcuCode: "STM32F102C6Tx",
stmGlob: "STM32F102C(4-6)Tx"
},
{
chibiDef: "STM32F102xB",
mcuCode: "STM32F102CBTx",
stmGlob: "STM32F102C(8-B)Tx"
},
{
chibiDef: "STM32F102x6",
mcuCode: "STM32F102R6Tx",
stmGlob: "STM32F102R(4-6)Tx"
},
{
chibiDef: "STM32F102xB",
mcuCode: "STM32F102RBTx",
stmGlob: "STM32F102R(8-B)Tx"
},
{
chibiDef: "STM32F103x6",
mcuCode: "STM32F103C6Tx",
stmGlob: "STM32F103C(4-6)Tx"
},
{
chibiDef: "STM32F103x6",
mcuCode: "STM32F103C6Ux",
stmGlob: "STM32F103C6Ux"
},
{
chibiDef: "STM32F103xB",
mcuCode: "STM32F103CBTx",
stmGlob: "STM32F103C(8-B)Tx"
},
{
chibiDef: "STM32F103xB",
mcuCode: "STM32F103CBUx",
stmGlob: "STM32F103CBUx"
},
{
chibiDef: "STM32F103x6",
mcuCode: "STM32F103R6Hx",
stmGlob: "STM32F103R(4-6)Hx"
},
{
chibiDef: "STM32F103x6",
mcuCode: "STM32F103R6Tx",
stmGlob: "STM32F103R(4-6)Tx"
},
{
chibiDef: "STM32F103xB",
mcuCode: "STM32F103RBHx",
stmGlob: "STM32F103R(8-B)Hx"
},
{
chibiDef: "STM32F103xB",
mcuCode: "STM32F103RBTx",
stmGlob: "STM32F103R(8-B)Tx"
},
{
chibiDef: "STM32F103xE",
mcuCode: "STM32F103RETx",
stmGlob: "STM32F103R(C-D-E)Tx"
},
{
chibiDef: "STM32F103xE",
mcuCode: "STM32F103REYx",
stmGlob: "STM32F103R(C-D-E)Yx"
},
{
chibiDef: "STM32F103xG",
mcuCode: "STM32F103RGTx",
stmGlob: "STM32F103R(F-G)Tx"
},
{
chibiDef: "STM32F103x6",
mcuCode: "STM32F103T6Ux",
stmGlob: "STM32F103T(4-6)Ux"
},
{
chibiDef: "STM32F103xB",
mcuCode: "STM32F103TBUx",
stmGlob: "STM32F103T(8-B)Ux"
},
{
chibiDef: "STM32F103xB",
mcuCode: "STM32F103VBHx",
stmGlob: "STM32F103V(8-B)Hx"
},
{
chibiDef: "STM32F103xB",
mcuCode: "STM32F103VBTx",
stmGlob: "STM32F103V(8-B)Tx"
},
{
chibiDef: "STM32F103xB",
mcuCode: "STM32F103VBIx",
stmGlob: "STM32F103VBIx"
},
{
chibiDef: "STM32F103xE",
mcuCode: "STM32F103VEHx",
stmGlob: "STM32F103V(C-D-E)Hx"
},
{
chibiDef: "STM32F103xE",
mcuCode: "STM32F103VETx",
stmGlob: "STM32F103V(C-D-E)Tx"
},
{
chibiDef: "STM32F103xG",
mcuCode: "STM32F103VGTx",
stmGlob: "STM32F103V(F-G)Tx"
},
{
chibiDef: "STM32F103xE",
mcuCode: "STM32F103ZEHx",
stmGlob: "STM32F103Z(C-D-E)Hx"
},
{
chibiDef: "STM32F103xE",
mcuCode: "STM32F103ZETx",
stmGlob: "STM32F103Z(C-D-E)Tx"
},
{
chibiDef: "STM32F103xG",
mcuCode: "STM32F103ZGHx",
stmGlob: "STM32F103Z(F-G)Hx"
},
{
chibiDef: "STM32F103xG",
mcuCode: "STM32F103ZGTx",
stmGlob: "STM32F103Z(F-G)Tx"
},
{
chibiDef: "STM32F105xC",
mcuCode: "STM32F105RCTx",
stmGlob: "STM32F105R(8-B-C)Tx"
},
{
chibiDef: "STM32F105xC",
mcuCode: "STM32F105VCTx",
stmGlob: "STM32F105V(8-B-C)Tx"
},
{
chibiDef: "STM32F107xC",
mcuCode: "STM32F107RCTx",
stmGlob: "STM32F107R(B-C)Tx"
},
{
chibiDef: "STM32F107xC",
mcuCode: "STM32F107VCTx",
stmGlob: "STM32F107V(B-C)Tx"
},
{
chibiDef: "STM32F107xC",
mcuCode: "STM32F107VCHx",
stmGlob: "STM32F107VCHx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205RBTx",
stmGlob: "STM32F205R(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205RCTx",
stmGlob: "STM32F205R(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205RETx",
stmGlob: "STM32F205R(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205RFTx",
stmGlob: "STM32F205R(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205RGTx",
stmGlob: "STM32F205R(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205REYx",
stmGlob: "STM32F205R(E-G)Yx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205RGYx",
stmGlob: "STM32F205R(E-G)Yx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205RGEx",
stmGlob: "STM32F205RGEx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205VBTx",
stmGlob: "STM32F205V(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205VCTx",
stmGlob: "STM32F205V(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205VETx",
stmGlob: "STM32F205V(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205VFTx",
stmGlob: "STM32F205V(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205VGTx",
stmGlob: "STM32F205V(B-C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205ZCTx",
stmGlob: "STM32F205Z(C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205ZETx",
stmGlob: "STM32F205Z(C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205ZFTx",
stmGlob: "STM32F205Z(C-E-F-G)Tx"
},
{
chibiDef: "STM32F205xx",
mcuCode: "STM32F205ZGTx",
stmGlob: "STM32F205Z(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207ICHx",
stmGlob: "STM32F207I(C-E-F-G)Hx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207IEHx",
stmGlob: "STM32F207I(C-E-F-G)Hx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207IFHx",
stmGlob: "STM32F207I(C-E-F-G)Hx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207IGHx",
stmGlob: "STM32F207I(C-E-F-G)Hx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207ICTx",
stmGlob: "STM32F207I(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207IETx",
stmGlob: "STM32F207I(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207IFTx",
stmGlob: "STM32F207I(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207IGTx",
stmGlob: "STM32F207I(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207VCTx",
stmGlob: "STM32F207V(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207VETx",
stmGlob: "STM32F207V(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207VFTx",
stmGlob: "STM32F207V(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207VGTx",
stmGlob: "STM32F207V(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207ZCTx",
stmGlob: "STM32F207Z(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207ZETx",
stmGlob: "STM32F207Z(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207ZFTx",
stmGlob: "STM32F207Z(C-E-F-G)Tx"
},
{
chibiDef: "STM32F207xx",
mcuCode: "STM32F207ZGTx",
stmGlob: "STM32F207Z(C-E-F-G)Tx"
},
{
chibiDef: "STM32F215xx",
mcuCode: "STM32F215RETx",
stmGlob: "STM32F215R(E-G)Tx"
},
{
chibiDef: "STM32F215xx",
mcuCode: "STM32F215RGTx",
stmGlob: "STM32F215R(E-G)Tx"
},
{
chibiDef: "STM32F215xx",
mcuCode: "STM32F215VETx",
stmGlob: "STM32F215V(E-G)Tx"
},
{
chibiDef: "STM32F215xx",
mcuCode: "STM32F215VGTx",
stmGlob: "STM32F215V(E-G)Tx"
},
{
chibiDef: "STM32F215xx",
mcuCode: "STM32F215ZETx",
stmGlob: "STM32F215Z(E-G)Tx"
},
{
chibiDef: "STM32F215xx",
mcuCode: "STM32F215ZGTx",
stmGlob: "STM32F215Z(E-G)Tx"
},
{
chibiDef: "STM32F217xx",
mcuCode: "STM32F217IEHx",
stmGlob: "STM32F217I(E-G)Hx"
},
{
chibiDef: "STM32F217xx",
mcuCode: "STM32F217IGHx",
stmGlob: "STM32F217I(E-G)Hx"
},
{
chibiDef: "STM32F217xx",
mcuCode: "STM32F217IETx",
stmGlob: "STM32F217I(E-G)Tx"
},
{
chibiDef: "STM32F217xx",
mcuCode: "STM32F217IGTx",
stmGlob: "STM32F217I(E-G)Tx"
},
{
chibiDef: "STM32F217xx",
mcuCode: "STM32F217VETx",
stmGlob: "STM32F217V(E-G)Tx"
},
{
chibiDef: "STM32F217xx",
mcuCode: "STM32F217VGTx",
stmGlob: "STM32F217V(E-G)Tx"
},
{
chibiDef: "STM32F217xx",
mcuCode: "STM32F217ZETx",
stmGlob: "STM32F217Z(E-G)Tx"
},
{
chibiDef: "STM32F217xx",
mcuCode: "STM32F217ZGTx",
stmGlob: "STM32F217Z(E-G)Tx"
},
{
chibiDef: "STM32F301x8",
mcuCode: "STM32F301C8Tx",
stmGlob: "STM32F301C(6-8)Tx"
},
{
chibiDef: "STM32F301x8",
mcuCode: "STM32F301C8Yx",
stmGlob: "STM32F301C8Yx"
},
{
chibiDef: "STM32F301x8",
mcuCode: "STM32F301K8Tx",
stmGlob: "STM32F301K(6-8)Tx"
},
{
chibiDef: "STM32F301x8",
mcuCode: "STM32F301K8Ux",
stmGlob: "STM32F301K(6-8)Ux"
},
{
chibiDef: "STM32F301x8",
mcuCode: "STM32F301R8Tx",
stmGlob: "STM32F301R(6-8)Tx"
},
{
chibiDef: "STM32F302x8",
mcuCode: "STM32F302C8Tx",
stmGlob: "STM32F302C(6-8)Tx"
},
{
chibiDef: "STM32F302x8",
mcuCode: "STM32F302C8Yx",
stmGlob: "STM32F302C8Yx"
},
{
chibiDef: "STM32F302xC",
mcuCode: "STM32F302CCTx",
stmGlob: "STM32F302C(B-C)Tx"
},
{
chibiDef: "STM32F302x8",
mcuCode: "STM32F302K8Ux",
stmGlob: "STM32F302K(6-8)Ux"
},
{
chibiDef: "STM32F302x8",
mcuCode: "STM32F302R8Tx",
stmGlob: "STM32F302R(6-8)Tx"
},
{
chibiDef: "STM32F302xC",
mcuCode: "STM32F302RCTx",
stmGlob: "STM32F302R(B-C)Tx"
},
{
chibiDef: "STM32F302xE",
mcuCode: "STM32F302RETx",
stmGlob: "STM32F302R(D-E)Tx"
},
{
chibiDef: "STM32F302xC",
mcuCode: "STM32F302VCTx",
stmGlob: "STM32F302V(B-C)Tx"
},
{
chibiDef: "STM32F302xC",
mcuCode: "STM32F302VCYx",
stmGlob: "STM32F302VCYx"
},
{
chibiDef: "STM32F302xE",
mcuCode: "STM32F302VEHx",
stmGlob: "STM32F302V(D-E)Hx"
},
{
chibiDef: "STM32F302xE",
mcuCode: "STM32F302VETx",
stmGlob: "STM32F302V(D-E)Tx"
},
{
chibiDef: "STM32F302xE",
mcuCode: "STM32F302ZETx",
stmGlob: "STM32F302Z(D-E)Tx"
},
{
chibiDef: "STM32F303x8",
mcuCode: "STM32F303C8Tx",
stmGlob: "STM32F303C(6-8)Tx"
},
{
chibiDef: "STM32F303x8",
mcuCode: "STM32F303C8Yx",
stmGlob: "STM32F303C8Yx"
},
{
chibiDef: "STM32F303xC",
mcuCode: "STM32F303CCTx",
stmGlob: "STM32F303C(B-C)Tx"
},
{
chibiDef: "STM32F303x8",
mcuCode: "STM32F303K8Tx",
stmGlob: "STM32F303K(6-8)Tx"
},
{
chibiDef: "STM32F303x8",
mcuCode: "STM32F303K8Ux",
stmGlob: "STM32F303K(6-8)Ux"
},
{
chibiDef: "STM32F303x8",
mcuCode: "STM32F303R8Tx",
stmGlob: "STM32F303R(6-8)Tx"
},
{
chibiDef: "STM32F303xC",
mcuCode: "STM32F303RCTx",
stmGlob: "STM32F303R(B-C)Tx"
},
{
chibiDef: "STM32F303xE",
mcuCode: "STM32F303RETx",
stmGlob: "STM32F303R(D-E)Tx"
},
{
chibiDef: "STM32F303xC",
mcuCode: "STM32F303VCTx",
stmGlob: "STM32F303V(B-C)Tx"
},
{
chibiDef: "STM32F303xC",
mcuCode: "STM32F303VCYx",
stmGlob: "STM32F303VCYx"
},
{
chibiDef: "STM32F303xE",
mcuCode: "STM32F303VEHx",
stmGlob: "STM32F303V(D-E)Hx"
},
{
chibiDef: "STM32F303xE",
mcuCode: "STM32F303VETx",
stmGlob: "STM32F303V(D-E)Tx"
},
{
chibiDef: "STM32F303xE",
mcuCode: "STM32F303VEYx",
stmGlob: "STM32F303VEYx"
},
{
chibiDef: "STM32F303xE",
mcuCode: "STM32F303ZETx",
stmGlob: "STM32F303Z(D-E)Tx"
},
{
chibiDef: "STM32F318x8",
mcuCode: "STM32F318C8Tx",
stmGlob: "STM32F318C8Tx"
},
{
chibiDef: "STM32F318x8",
mcuCode: "STM32F318C8Yx",
stmGlob: "STM32F318C8Yx"
},
{
chibiDef: "STM32F318x8",
mcuCode: "STM32F318K8Ux",
stmGlob: "STM32F318K8Ux"
},
{
chibiDef: "STM32F328x8",
mcuCode: "STM32F328C8Tx",
stmGlob: "STM32F328C8Tx"
},
{
chibiDef: "STM32F334x8",
mcuCode: "STM32F334C8Tx",
stmGlob: "STM32F334C(4-6-8)Tx"
},
{
chibiDef: "STM32F334x8",
mcuCode: "STM32F334C8Yx",
stmGlob: "STM32F334C8Yx"
},
{
chibiDef: "STM32F334x8",
mcuCode: "STM32F334K8Tx",
stmGlob: "STM32F334K(4-6-8)Tx"
},
{
chibiDef: "STM32F334x8",
mcuCode: "STM32F334K8Ux",
stmGlob: "STM32F334K(4-6-8)Ux"
},
{
chibiDef: "STM32F334x8",
mcuCode: "STM32F334R8Tx",
stmGlob: "STM32F334R(6-8)Tx"
},
{
chibiDef: "STM32F358xC",
mcuCode: "STM32F358CCTx",
stmGlob: "STM32F358CCTx"
},
{
chibiDef: "STM32F358xC",
mcuCode: "STM32F358RCTx",
stmGlob: "STM32F358RCTx"
},
{
chibiDef: "STM32F358xC",
mcuCode: "STM32F358VCTx",
stmGlob: "STM32F358VCTx"
},
{
chibiDef: "STM32F373xC",
mcuCode: "STM32F373CCTx",
stmGlob: "STM32F373C(8-B-C)Tx"
},
{
chibiDef: "STM32F373xC",
mcuCode: "STM32F373RCTx",
stmGlob: "STM32F373R(8-B-C)Tx"
},
{
chibiDef: "STM32F373xC",
mcuCode: "STM32F373VCHx",
stmGlob: "STM32F373V(8-B-C)Hx"
},
{
chibiDef: "STM32F373xC",
mcuCode: "STM32F373VCTx",
stmGlob: "STM32F373V(8-B-C)Tx"
},
{
chibiDef: "STM32F378xx",
mcuCode: "STM32F378CCTx",
stmGlob: "STM32F378CCTx"
},
{
chibiDef: "STM32F378xx",
mcuCode: "STM32F378RCTx",
stmGlob: "STM32F378RCTx"
},
{
chibiDef: "STM32F378xx",
mcuCode: "STM32F378RCYx",
stmGlob: "STM32F378RCYx"
},
{
chibiDef: "STM32F378xx",
mcuCode: "STM32F378VCHx",
stmGlob: "STM32F378VCHx"
},
{
chibiDef: "STM32F378xx",
mcuCode: "STM32F378VCTx",
stmGlob: "STM32F378VCTx"
},
{
chibiDef: "STM32F398xx",
mcuCode: "STM32F398VETx",
stmGlob: "STM32F398VETx"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401CBUx",
stmGlob: "STM32F401C(B-C)Ux"
},
{
chibiDef: "STM32F401xC",
mcuCode: "STM32F401CCUx",
stmGlob: "STM32F401C(B-C)Ux"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401CBYx",
stmGlob: "STM32F401C(B-C)Yx"
},
{
chibiDef: "STM32F401xC",
mcuCode: "STM32F401CCYx",
stmGlob: "STM32F401C(B-C)Yx"
},
{
chibiDef: "STM32F401xC",
mcuCode: "STM32F401CCFx",
stmGlob: "STM32F401CCFx"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401CDUx",
stmGlob: "STM32F401C(D-E)Ux"
},
{
chibiDef: "STM32F401xE",
mcuCode: "STM32F401CEUx",
stmGlob: "STM32F401C(D-E)Ux"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401CDYx",
stmGlob: "STM32F401C(D-E)Yx"
},
{
chibiDef: "STM32F401xE",
mcuCode: "STM32F401CEYx",
stmGlob: "STM32F401C(D-E)Yx"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401RBTx",
stmGlob: "STM32F401R(B-C)Tx"
},
{
chibiDef: "STM32F401xC",
mcuCode: "STM32F401RCTx",
stmGlob: "STM32F401R(B-C)Tx"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401RDTx",
stmGlob: "STM32F401R(D-E)Tx"
},
{
chibiDef: "STM32F401xE",
mcuCode: "STM32F401RETx",
stmGlob: "STM32F401R(D-E)Tx"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401VBHx",
stmGlob: "STM32F401V(B-C)Hx"
},
{
chibiDef: "STM32F401xC",
mcuCode: "STM32F401VCHx",
stmGlob: "STM32F401V(B-C)Hx"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401VBTx",
stmGlob: "STM32F401V(B-C)Tx"
},
{
chibiDef: "STM32F401xC",
mcuCode: "STM32F401VCTx",
stmGlob: "STM32F401V(B-C)Tx"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401VDHx",
stmGlob: "STM32F401V(D-E)Hx"
},
{
chibiDef: "STM32F401xE",
mcuCode: "STM32F401VEHx",
stmGlob: "STM32F401V(D-E)Hx"
},
{
chibiDef: "STM32F401xx",
mcuCode: "STM32F401VDTx",
stmGlob: "STM32F401V(D-E)Tx"
},
{
chibiDef: "STM32F401xE",
mcuCode: "STM32F401VETx",
stmGlob: "STM32F401V(D-E)Tx"
},
{
chibiDef: "STM32F405xx",
mcuCode: "STM32F405OEYx",
stmGlob: "STM32F405O(E-G)Yx"
},
{
chibiDef: "STM32F405xx",
mcuCode: "STM32F405OGYx",
stmGlob: "STM32F405O(E-G)Yx"
},
{
chibiDef: "STM32F405xx",
mcuCode: "STM32F405RGTx",
stmGlob: "STM32F405RGTx"
},
{
chibiDef: "STM32F405xx",
mcuCode: "STM32F405VGTx",
stmGlob: "STM32F405VGTx"
},
{
chibiDef: "STM32F405xx",
mcuCode: "STM32F405ZGTx",
stmGlob: "STM32F405ZGTx"
},
{
chibiDef: "STM32F407xx",
mcuCode: "STM32F407IEHx",
stmGlob: "STM32F407I(E-G)Hx"
},
{
chibiDef: "STM32F407xx",
mcuCode: "STM32F407IGHx",
stmGlob: "STM32F407I(E-G)Hx"
},
{
chibiDef: "STM32F407xx",
mcuCode: "STM32F407IETx",
stmGlob: "STM32F407I(E-G)Tx"
},
{
chibiDef: "STM32F407xx",
mcuCode: "STM32F407IGTx",
stmGlob: "STM32F407I(E-G)Tx"
},
{
chibiDef: "STM32F407xx",
mcuCode: "STM32F407VETx",
stmGlob: "STM32F407V(E-G)Tx"
},
{
chibiDef: "STM32F407xx",
mcuCode: "STM32F407VGTx",
stmGlob: "STM32F407V(E-G)Tx"
},
{
chibiDef: "STM32F407xx",
mcuCode: "STM32F407ZETx",
stmGlob: "STM32F407Z(E-G)Tx"
},
{
chibiDef: "STM32F407xx",
mcuCode: "STM32F407ZGTx",
stmGlob: "STM32F407Z(E-G)Tx"
},
{
chibiDef: "STM32F410Cx",
mcuCode: "STM32F410C8Tx",
stmGlob: "STM32F410C(8-B)Tx"
},
{
chibiDef: "STM32F410Cx",
mcuCode: "STM32F410CBTx",
stmGlob: "STM32F410C(8-B)Tx"
},
{
chibiDef: "STM32F410Cx",
mcuCode: "STM32F410C8Ux",
stmGlob: "STM32F410C(8-B)Ux"
},
{
chibiDef: "STM32F410Cx",
mcuCode: "STM32F410CBUx",
stmGlob: "STM32F410C(8-B)Ux"
},
{
chibiDef: "STM32F410Rx",
mcuCode: "STM32F410R8Ix",
stmGlob: "STM32F410R(8-B)Ix"
},
{
chibiDef: "STM32F410Rx",
mcuCode: "STM32F410RBIx",
stmGlob: "STM32F410R(8-B)Ix"
},
{
chibiDef: "STM32F410Rx",
mcuCode: "STM32F410R8Tx",
stmGlob: "STM32F410R(8-B)Tx"
},
{
chibiDef: "STM32F410Rx",
mcuCode: "STM32F410RBTx",
stmGlob: "STM32F410R(8-B)Tx"
},
{
chibiDef: "STM32F410Tx",
mcuCode: "STM32F410T8Yx",
stmGlob: "STM32F410T(8-B)Yx"
},
{
chibiDef: "STM32F410Tx",
mcuCode: "STM32F410TBYx",
stmGlob: "STM32F410T(8-B)Yx"
},
{
chibiDef: "STM32F411xx",
mcuCode: "STM32F411CCUx",
stmGlob: "STM32F411C(C-E)Ux"
},
{
chibiDef: "STM32F411xE",
mcuCode: "STM32F411CEUx",
stmGlob: "STM32F411C(C-E)Ux"
},
{
chibiDef: "STM32F411xx",
mcuCode: "STM32F411CCYx",
stmGlob: "STM32F411C(C-E)Yx"
},
{
chibiDef: "STM32F411xE",
mcuCode: "STM32F411CEYx",
stmGlob: "STM32F411C(C-E)Yx"
},
{
chibiDef: "STM32F411xx",
mcuCode: "STM32F411RCTx",
stmGlob: "STM32F411R(C-E)Tx"
},
{
chibiDef: "STM32F411xE",
mcuCode: "STM32F411RETx",
stmGlob: "STM32F411R(C-E)Tx"
},
{
chibiDef: "STM32F411xx",
mcuCode: "STM32F411VCHx",
stmGlob: "STM32F411V(C-E)Hx"
},
{
chibiDef: "STM32F411xE",
mcuCode: "STM32F411VEHx",
stmGlob: "STM32F411V(C-E)Hx"
},
{
chibiDef: "STM32F411xx",
mcuCode: "STM32F411VCTx",
stmGlob: "STM32F411V(C-E)Tx"
},
{
chibiDef: "STM32F411xE",
mcuCode: "STM32F411VETx",
stmGlob: "STM32F411V(C-E)Tx"
},
{
chibiDef: "STM32F412Cx",
mcuCode: "STM32F412CEUx",
stmGlob: "STM32F412C(E-G)Ux"
},
{
chibiDef: "STM32F412Cx",
mcuCode: "STM32F412CGUx",
stmGlob: "STM32F412C(E-G)Ux"
},
{
chibiDef: "STM32F412Rx",
mcuCode: "STM32F412RETx",
stmGlob: "STM32F412R(E-G)Tx"
},
{
chibiDef: "STM32F412Rx",
mcuCode: "STM32F412RGTx",
stmGlob: "STM32F412R(E-G)Tx"
},
{
chibiDef: "STM32F412Rx",
mcuCode: "STM32F412REYxP",
stmGlob: "STM32F412R(E-G)YxP"
},
{
chibiDef: "STM32F412Rx",
mcuCode: "STM32F412RGYxP",
stmGlob: "STM32F412R(E-G)YxP"
},
{
chibiDef: "STM32F412Rx",
mcuCode: "STM32F412REYx",
stmGlob: "STM32F412R(E-G)Yx"
},
{
chibiDef: "STM32F412Rx",
mcuCode: "STM32F412RGYx",
stmGlob: "STM32F412R(E-G)Yx"
},
{
chibiDef: "STM32F412Vx",
mcuCode: "STM32F412VEHx",
stmGlob: "STM32F412V(E-G)Hx"
},
{
chibiDef: "STM32F412Vx",
mcuCode: "STM32F412VGHx",
stmGlob: "STM32F412V(E-G)Hx"
},
{
chibiDef: "STM32F412Vx",
mcuCode: "STM32F412VETx",
stmGlob: "STM32F412V(E-G)Tx"
},
{
chibiDef: "STM32F412Vx",
mcuCode: "STM32F412VGTx",
stmGlob: "STM32F412V(E-G)Tx"
},
{
chibiDef: "STM32F412Zx",
mcuCode: "STM32F412ZEJx",
stmGlob: "STM32F412Z(E-G)Jx"
},
{
chibiDef: "STM32F412Zx",
mcuCode: "STM32F412ZGJx",
stmGlob: "STM32F412Z(E-G)Jx"
},
{
chibiDef: "STM32F412Zx",
mcuCode: "STM32F412ZETx",
stmGlob: "STM32F412Z(E-G)Tx"
},
{
chibiDef: "STM32F412Zx",
mcuCode: "STM32F412ZGTx",
stmGlob: "STM32F412Z(E-G)Tx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413CGUx",
stmGlob: "STM32F413C(G-H)Ux"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413CHUx",
stmGlob: "STM32F413C(G-H)Ux"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413MGYx",
stmGlob: "STM32F413M(G-H)Yx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413MHYx",
stmGlob: "STM32F413M(G-H)Yx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413RGTx",
stmGlob: "STM32F413R(G-H)Tx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413RHTx",
stmGlob: "STM32F413R(G-H)Tx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413VGHx",
stmGlob: "STM32F413V(G-H)Hx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413VHHx",
stmGlob: "STM32F413V(G-H)Hx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413VGTx",
stmGlob: "STM32F413V(G-H)Tx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413VHTx",
stmGlob: "STM32F413V(G-H)Tx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413ZGJx",
stmGlob: "STM32F413Z(G-H)Jx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413ZHJx",
stmGlob: "STM32F413Z(G-H)Jx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413ZGTx",
stmGlob: "STM32F413Z(G-H)Tx"
},
{
chibiDef: "STM32F40_41xxx",
mcuCode: "STM32F413ZHTx",
stmGlob: "STM32F413Z(G-H)Tx"
},
{
chibiDef: "STM32F415xx",
mcuCode: "STM32F415OGYx",
stmGlob: "STM32F415OGYx"
},
{
chibiDef: "STM32F415xx",
mcuCode: "STM32F415RGTx",
stmGlob: "STM32F415RGTx"
},
{
chibiDef: "STM32F415xx",
mcuCode: "STM32F415VGTx",
stmGlob: "STM32F415VGTx"
},
{
chibiDef: "STM32F415xx",
mcuCode: "STM32F415ZGTx",
stmGlob: "STM32F415ZGTx"
},
{
chibiDef: "STM32F417xx",
mcuCode: "STM32F417IEHx",
stmGlob: "STM32F417I(E-G)Hx"
},
{
chibiDef: "STM32F417xx",
mcuCode: "STM32F417IGHx",
stmGlob: "STM32F417I(E-G)Hx"
},
{
chibiDef: "STM32F417xx",
mcuCode: "STM32F417IETx",
stmGlob: "STM32F417I(E-G)Tx"
},
{
chibiDef: "STM32F417xx",
mcuCode: "STM32F417IGTx",
stmGlob: "STM32F417I(E-G)Tx"
},
{
chibiDef: "STM32F417xx",
mcuCode: "STM32F417VETx",
stmGlob: "STM32F417V(E-G)Tx"
},
{
chibiDef: "STM32F417xx",
mcuCode: "STM32F417VGTx",
stmGlob: "STM32F417V(E-G)Tx"
},
{
chibiDef: "STM32F417xx",
mcuCode: "STM32F417ZETx",
stmGlob: "STM32F417Z(E-G)Tx"
},
{
chibiDef: "STM32F417xx",
mcuCode: "STM32F417ZGTx",
stmGlob: "STM32F417Z(E-G)Tx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427AGHx",
stmGlob: "STM32F427A(G-I)Hx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427AIHx",
stmGlob: "STM32F427A(G-I)Hx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427IGHx",
stmGlob: "STM32F427I(G-I)Hx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427IIHx",
stmGlob: "STM32F427I(G-I)Hx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427IGTx",
stmGlob: "STM32F427I(G-I)Tx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427IITx",
stmGlob: "STM32F427I(G-I)Tx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427VGTx",
stmGlob: "STM32F427V(G-I)Tx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427VITx",
stmGlob: "STM32F427V(G-I)Tx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427ZGTx",
stmGlob: "STM32F427Z(G-I)Tx"
},
{
chibiDef: "STM32F427xx",
mcuCode: "STM32F427ZITx",
stmGlob: "STM32F427Z(G-I)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429AGHx",
stmGlob: "STM32F429A(G-I)Hx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429AIHx",
stmGlob: "STM32F429A(G-I)Hx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429BETx",
stmGlob: "STM32F429B(E-G-I)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429BGTx",
stmGlob: "STM32F429B(E-G-I)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429BITx",
stmGlob: "STM32F429B(E-G-I)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429IEHx",
stmGlob: "STM32F429I(E-G-I)Hx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429IGHx",
stmGlob: "STM32F429I(E-G-I)Hx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429IIHx",
stmGlob: "STM32F429I(E-G-I)Hx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429IETx",
stmGlob: "STM32F429I(E-G)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429IGTx",
stmGlob: "STM32F429I(E-G)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429IITx",
stmGlob: "STM32F429IITx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429NEHx",
stmGlob: "STM32F429N(E-G)Hx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429NGHx",
stmGlob: "STM32F429N(E-G)Hx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429NIHx",
stmGlob: "STM32F429NIHx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429VETx",
stmGlob: "STM32F429V(E-G)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429VGTx",
stmGlob: "STM32F429V(E-G)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429VITx",
stmGlob: "STM32F429VITx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429ZETx",
stmGlob: "STM32F429Z(E-G)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429ZGTx",
stmGlob: "STM32F429Z(E-G)Tx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429ZGYx",
stmGlob: "STM32F429ZGYx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429ZITx",
stmGlob: "STM32F429ZITx"
},
{
chibiDef: "STM32F429xx",
mcuCode: "STM32F429ZIYx",
stmGlob: "STM32F429ZIYx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437AIHx",
stmGlob: "STM32F437AIHx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437IGHx",
stmGlob: "STM32F437I(G-I)Hx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437IIHx",
stmGlob: "STM32F437I(G-I)Hx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437IGTx",
stmGlob: "STM32F437I(G-I)Tx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437IITx",
stmGlob: "STM32F437I(G-I)Tx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437VGTx",
stmGlob: "STM32F437V(G-I)Tx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437VITx",
stmGlob: "STM32F437V(G-I)Tx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437ZGTx",
stmGlob: "STM32F437Z(G-I)Tx"
},
{
chibiDef: "STM32F437xx",
mcuCode: "STM32F437ZITx",
stmGlob: "STM32F437Z(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439AIHx",
stmGlob: "STM32F439AIHx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439BGTx",
stmGlob: "STM32F439B(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439BITx",
stmGlob: "STM32F439B(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439IGHx",
stmGlob: "STM32F439I(G-I)Hx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439IIHx",
stmGlob: "STM32F439I(G-I)Hx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439IGTx",
stmGlob: "STM32F439I(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439IITx",
stmGlob: "STM32F439I(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439NGHx",
stmGlob: "STM32F439N(G-I)Hx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439NIHx",
stmGlob: "STM32F439N(G-I)Hx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439VGTx",
stmGlob: "STM32F439V(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439VITx",
stmGlob: "STM32F439V(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439ZGTx",
stmGlob: "STM32F439Z(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439ZITx",
stmGlob: "STM32F439Z(G-I)Tx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439ZGYx",
stmGlob: "STM32F439Z(G-I)Yx"
},
{
chibiDef: "STM32F439xx",
mcuCode: "STM32F439ZIYx",
stmGlob: "STM32F439Z(G-I)Yx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446MCYx",
stmGlob: "STM32F446M(C-E)Yx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446MEYx",
stmGlob: "STM32F446M(C-E)Yx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446RCTx",
stmGlob: "STM32F446R(C-E)Tx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446RETx",
stmGlob: "STM32F446R(C-E)Tx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446VCTx",
stmGlob: "STM32F446V(C-E)Tx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446VETx",
stmGlob: "STM32F446V(C-E)Tx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446ZCHx",
stmGlob: "STM32F446Z(C-E)Hx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446ZEHx",
stmGlob: "STM32F446Z(C-E)Hx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446ZCJx",
stmGlob: "STM32F446Z(C-E)Jx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446ZEJx",
stmGlob: "STM32F446Z(C-E)Jx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446ZCTx",
stmGlob: "STM32F446Z(C-E)Tx"
},
{
chibiDef: "STM32F446xx",
mcuCode: "STM32F446ZETx",
stmGlob: "STM32F446Z(C-E)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469AEHx",
stmGlob: "STM32F469A(E-G-I)Hx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469AGHx",
stmGlob: "STM32F469A(E-G-I)Hx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469AIHx",
stmGlob: "STM32F469A(E-G-I)Hx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469AEYx",
stmGlob: "STM32F469A(E-G-I)Yx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469AGYx",
stmGlob: "STM32F469A(E-G-I)Yx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469AIYx",
stmGlob: "STM32F469A(E-G-I)Yx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469BETx",
stmGlob: "STM32F469B(E-G-I)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469BGTx",
stmGlob: "STM32F469B(E-G-I)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469BITx",
stmGlob: "STM32F469B(E-G-I)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469IEHx",
stmGlob: "STM32F469I(E-G-I)Hx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469IGHx",
stmGlob: "STM32F469I(E-G-I)Hx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469IIHx",
stmGlob: "STM32F469I(E-G-I)Hx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469IETx",
stmGlob: "STM32F469I(E-G)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469IGTx",
stmGlob: "STM32F469I(E-G)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469IITx",
stmGlob: "STM32F469IITx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469NEHx",
stmGlob: "STM32F469N(E-G)Hx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469NGHx",
stmGlob: "STM32F469N(E-G)Hx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469NIHx",
stmGlob: "STM32F469NIHx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469VETx",
stmGlob: "STM32F469V(E-G)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469VGTx",
stmGlob: "STM32F469V(E-G)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469VITx",
stmGlob: "STM32F469VITx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469ZETx",
stmGlob: "STM32F469Z(E-G)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469ZGTx",
stmGlob: "STM32F469Z(E-G)Tx"
},
{
chibiDef: "STM32F469xx",
mcuCode: "STM32F469ZITx",
stmGlob: "STM32F469ZITx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479AGHx",
stmGlob: "STM32F479A(G-I)Hx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479AIHx",
stmGlob: "STM32F479A(G-I)Hx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479AGYx",
stmGlob: "STM32F479A(G-I)Yx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479AIYx",
stmGlob: "STM32F479A(G-I)Yx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479BGTx",
stmGlob: "STM32F479B(G-I)Tx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479BITx",
stmGlob: "STM32F479B(G-I)Tx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479IGHx",
stmGlob: "STM32F479I(G-I)Hx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479IIHx",
stmGlob: "STM32F479I(G-I)Hx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479IGTx",
stmGlob: "STM32F479I(G-I)Tx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479IITx",
stmGlob: "STM32F479I(G-I)Tx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479NGHx",
stmGlob: "STM32F479N(G-I)Hx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479NIHx",
stmGlob: "STM32F479N(G-I)Hx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479VGTx",
stmGlob: "STM32F479V(G-I)Tx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479VITx",
stmGlob: "STM32F479V(G-I)Tx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479ZGTx",
stmGlob: "STM32F479Z(G-I)Tx"
},
{
chibiDef: "STM32F479xx",
mcuCode: "STM32F479ZITx",
stmGlob: "STM32F479Z(G-I)Tx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722ICKx",
stmGlob: "STM32F722I(C-E)Kx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722IEKx",
stmGlob: "STM32F722I(C-E)Kx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722ICTx",
stmGlob: "STM32F722I(C-E)Tx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722IETx",
stmGlob: "STM32F722I(C-E)Tx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722RCTx",
stmGlob: "STM32F722R(C-E)Tx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722RETx",
stmGlob: "STM32F722R(C-E)Tx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722VCTx",
stmGlob: "STM32F722V(C-E)Tx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722VETx",
stmGlob: "STM32F722V(C-E)Tx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722ZCTx",
stmGlob: "STM32F722Z(C-E)Tx"
},
{
chibiDef: "STM32F722xx",
mcuCode: "STM32F722ZETx",
stmGlob: "STM32F722Z(C-E)Tx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723ICKx",
stmGlob: "STM32F723I(C-E)Kx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723IEKx",
stmGlob: "STM32F723I(C-E)Kx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723ICTx",
stmGlob: "STM32F723I(C-E)Tx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723IETx",
stmGlob: "STM32F723I(C-E)Tx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723VCTx",
stmGlob: "STM32F723V(C-E)Tx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723VETx",
stmGlob: "STM32F723V(C-E)Tx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723VCYx",
stmGlob: "STM32F723V(C-E)Yx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723VEYx",
stmGlob: "STM32F723V(C-E)Yx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723ZCIx",
stmGlob: "STM32F723Z(C-E)Ix"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723ZEIx",
stmGlob: "STM32F723Z(C-E)Ix"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723ZCTx",
stmGlob: "STM32F723Z(C-E)Tx"
},
{
chibiDef: "STM32F723xx",
mcuCode: "STM32F723ZETx",
stmGlob: "STM32F723Z(C-E)Tx"
},
{
chibiDef: "STM32F732xx",
mcuCode: "STM32F732IEKx",
stmGlob: "STM32F732IEKx"
},
{
chibiDef: "STM32F732xx",
mcuCode: "STM32F732IETx",
stmGlob: "STM32F732IETx"
},
{
chibiDef: "STM32F732xx",
mcuCode: "STM32F732RETx",
stmGlob: "STM32F732RETx"
},
{
chibiDef: "STM32F732xx",
mcuCode: "STM32F732VETx",
stmGlob: "STM32F732VETx"
},
{
chibiDef: "STM32F732xx",
mcuCode: "STM32F732ZETx",
stmGlob: "STM32F732ZETx"
},
{
chibiDef: "STM32F733xx",
mcuCode: "STM32F733IEKx",
stmGlob: "STM32F733IEKx"
},
{
chibiDef: "STM32F733xx",
mcuCode: "STM32F733IETx",
stmGlob: "STM32F733IETx"
},
{
chibiDef: "STM32F733xx",
mcuCode: "STM32F733VETx",
stmGlob: "STM32F733VETx"
},
{
chibiDef: "STM32F733xx",
mcuCode: "STM32F733VEYx",
stmGlob: "STM32F733VEYx"
},
{
chibiDef: "STM32F733xx",
mcuCode: "STM32F733ZEIx",
stmGlob: "STM32F733ZEIx"
},
{
chibiDef: "STM32F733xx",
mcuCode: "STM32F733ZETx",
stmGlob: "STM32F733ZETx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745IEKx",
stmGlob: "STM32F745I(E-G)Kx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745IGKx",
stmGlob: "STM32F745I(E-G)Kx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745IETx",
stmGlob: "STM32F745I(E-G)Tx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745IGTx",
stmGlob: "STM32F745I(E-G)Tx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745VEHx",
stmGlob: "STM32F745V(E-G)Hx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745VGHx",
stmGlob: "STM32F745V(E-G)Hx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745VETx",
stmGlob: "STM32F745V(E-G)Tx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745VGTx",
stmGlob: "STM32F745V(E-G)Tx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745ZETx",
stmGlob: "STM32F745Z(E-G)Tx"
},
{
chibiDef: "STM32F745xx",
mcuCode: "STM32F745ZGTx",
stmGlob: "STM32F745Z(E-G)Tx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746BETx",
stmGlob: "STM32F746B(E-G)Tx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746BGTx",
stmGlob: "STM32F746B(E-G)Tx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746IEKx",
stmGlob: "STM32F746I(E-G)Kx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746IGKx",
stmGlob: "STM32F746I(E-G)Kx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746IETx",
stmGlob: "STM32F746IETx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746IGTx",
stmGlob: "STM32F746IGTx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746NEHx",
stmGlob: "STM32F746NEHx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746NGHx",
stmGlob: "STM32F746NGHx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746VEHx",
stmGlob: "STM32F746V(E-G)Hx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746VGHx",
stmGlob: "STM32F746V(E-G)Hx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746VETx",
stmGlob: "STM32F746VETx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746VGTx",
stmGlob: "STM32F746VGTx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746ZEYx",
stmGlob: "STM32F746Z(E-G)Yx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746ZGYx",
stmGlob: "STM32F746Z(E-G)Yx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746ZETx",
stmGlob: "STM32F746ZETx"
},
{
chibiDef: "STM32F746xx",
mcuCode: "STM32F746ZGTx",
stmGlob: "STM32F746ZGTx"
},
{
chibiDef: "STM32F756xx",
mcuCode: "STM32F756BGTx",
stmGlob: "STM32F756BGTx"
},
{
chibiDef: "STM32F756xx",
mcuCode: "STM32F756IGKx",
stmGlob: "STM32F756IGKx"
},
{
chibiDef: "STM32F756xx",
mcuCode: "STM32F756IGTx",
stmGlob: "STM32F756IGTx"
},
{
chibiDef: "STM32F756xx",
mcuCode: "STM32F756NGHx",
stmGlob: "STM32F756NGHx"
},
{
chibiDef: "STM32F756xx",
mcuCode: "STM32F756VGHx",
stmGlob: "STM32F756VGHx"
},
{
chibiDef: "STM32F756xx",
mcuCode: "STM32F756VGTx",
stmGlob: "STM32F756VGTx"
},
{
chibiDef: "STM32F756xx",
mcuCode: "STM32F756ZGTx",
stmGlob: "STM32F756ZGTx"
},
{
chibiDef: "STM32F756xx",
mcuCode: "STM32F756ZGYx",
stmGlob: "STM32F756ZGYx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767BGTx",
stmGlob: "STM32F767B(G-I)Tx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767BITx",
stmGlob: "STM32F767B(G-I)Tx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767IGKx",
stmGlob: "STM32F767I(G-I)Kx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767IIKx",
stmGlob: "STM32F767I(G-I)Kx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767IGTx",
stmGlob: "STM32F767I(G-I)Tx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767IITx",
stmGlob: "STM32F767I(G-I)Tx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767NGHx",
stmGlob: "STM32F767N(G-I)Hx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767NIHx",
stmGlob: "STM32F767N(G-I)Hx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767VGHx",
stmGlob: "STM32F767VGHx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767VGTx",
stmGlob: "STM32F767VGTx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767VIHx",
stmGlob: "STM32F767VIHx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767VITx",
stmGlob: "STM32F767VITx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767ZGTx",
stmGlob: "STM32F767ZGTx"
},
{
chibiDef: "STM32F767xx",
mcuCode: "STM32F767ZITx",
stmGlob: "STM32F767ZITx"
},
{
chibiDef: "STM32F769xx",
mcuCode: "STM32F769AGYx",
stmGlob: "STM32F769A(G-I)Yx"
},
{
chibiDef: "STM32F769xx",
mcuCode: "STM32F769AIYx",
stmGlob: "STM32F769A(G-I)Yx"
},
{
chibiDef: "STM32F769xx",
mcuCode: "STM32F769BGTx",
stmGlob: "STM32F769B(G-I)Tx"
},
{
chibiDef: "STM32F769xx",
mcuCode: "STM32F769BITx",
stmGlob: "STM32F769B(G-I)Tx"
},
{
chibiDef: "STM32F769xx",
mcuCode: "STM32F769IGTx",
stmGlob: "STM32F769IGTx"
},
{
chibiDef: "STM32F769xx",
mcuCode: "STM32F769IITx",
stmGlob: "STM32F769IITx"
},
{
chibiDef: "STM32F769xx",
mcuCode: "STM32F769NGHx",
stmGlob: "STM32F769NGHx"
},
{
chibiDef: "STM32F769xx",
mcuCode: "STM32F769NIHx",
stmGlob: "STM32F769NIHx"
},
{
chibiDef: "STM32F777xx",
mcuCode: "STM32F777BITx",
stmGlob: "STM32F777BITx"
},
{
chibiDef: "STM32F777xx",
mcuCode: "STM32F777IIKx",
stmGlob: "STM32F777IIKx"
},
{
chibiDef: "STM32F777xx",
mcuCode: "STM32F777IITx",
stmGlob: "STM32F777IITx"
},
{
chibiDef: "STM32F777xx",
mcuCode: "STM32F777NIHx",
stmGlob: "STM32F777NIHx"
},
{
chibiDef: "STM32F777xx",
mcuCode: "STM32F777VIHx",
stmGlob: "STM32F777VIHx"
},
{
chibiDef: "STM32F777xx",
mcuCode: "STM32F777VITx",
stmGlob: "STM32F777VITx"
},
{
chibiDef: "STM32F777xx",
mcuCode: "STM32F777ZITx",
stmGlob: "STM32F777ZITx"
},
{
chibiDef: "STM32F779xx",
mcuCode: "STM32F779AIYx",
stmGlob: "STM32F779AIYx"
},
{
chibiDef: "STM32F779xx",
mcuCode: "STM32F779BITx",
stmGlob: "STM32F779BITx"
},
{
chibiDef: "STM32F779xx",
mcuCode: "STM32F779IITx",
stmGlob: "STM32F779IITx"
},
{
chibiDef: "STM32F779xx",
mcuCode: "STM32F779NIHx",
stmGlob: "STM32F779NIHx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743AGIx",
stmGlob: "STM32H743A(G-I)Ix"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743AIIx",
stmGlob: "STM32H743A(G-I)Ix"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743BGTx",
stmGlob: "STM32H743BGTx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743BITx",
stmGlob: "STM32H743BITx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743IGKx",
stmGlob: "STM32H743IGKx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743IGTx",
stmGlob: "STM32H743IGTx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743IIKx",
stmGlob: "STM32H743IIKx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743IITx",
stmGlob: "STM32H743IITx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743VGHx",
stmGlob: "STM32H743V(G-I)Hx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743VIHx",
stmGlob: "STM32H743V(G-I)Hx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743VGTx",
stmGlob: "STM32H743VGTx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743VITx",
stmGlob: "STM32H743VITx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743XGHx",
stmGlob: "STM32H743XGHx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743XIHx",
stmGlob: "STM32H743XIHx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743ZGTx",
stmGlob: "STM32H743ZGTx"
},
{
chibiDef: "STM32H743xx",
mcuCode: "STM32H743ZITx",
stmGlob: "STM32H743ZITx"
},
{
chibiDef: "STM32H753xx",
mcuCode: "STM32H753AIIx",
stmGlob: "STM32H753AIIx"
},
{
chibiDef: "STM32H753xx",
mcuCode: "STM32H753BITx",
stmGlob: "STM32H753BITx"
},
{
chibiDef: "STM32H753xx",
mcuCode: "STM32H753IIKx",
stmGlob: "STM32H753IIKx"
},
{
chibiDef: "STM32H753xx",
mcuCode: "STM32H753IITx",
stmGlob: "STM32H753IITx"
},
{
chibiDef: "STM32H753xx",
mcuCode: "STM32H753VIHx",
stmGlob: "STM32H753VIHx"
},
{
chibiDef: "STM32H753xx",
mcuCode: "STM32H753VITx",
stmGlob: "STM32H753VITx"
},
{
chibiDef: "STM32H753xx",
mcuCode: "STM32H753XIHx",
stmGlob: "STM32H753XIHx"
},
{
chibiDef: "STM32H753xx",
mcuCode: "STM32H753ZITx",
stmGlob: "STM32H753ZITx"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011D3Px",
stmGlob: "STM32L011D(3-4)Px"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011D4Px",
stmGlob: "STM32L011D(3-4)Px"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011E3Yx",
stmGlob: "STM32L011E(3-4)Yx"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011E4Yx",
stmGlob: "STM32L011E(3-4)Yx"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011F3Px",
stmGlob: "STM32L011F(3-4)Px"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011F4Px",
stmGlob: "STM32L011F(3-4)Px"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011F3Ux",
stmGlob: "STM32L011F(3-4)Ux"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011F4Ux",
stmGlob: "STM32L011F(3-4)Ux"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011G3Ux",
stmGlob: "STM32L011G(3-4)Ux"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011G4Ux",
stmGlob: "STM32L011G(3-4)Ux"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011K3Tx",
stmGlob: "STM32L011K(3-4)Tx"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011K4Tx",
stmGlob: "STM32L011K(3-4)Tx"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011K3Ux",
stmGlob: "STM32L011K(3-4)Ux"
},
{
chibiDef: "STM32L011xx",
mcuCode: "STM32L011K4Ux",
stmGlob: "STM32L011K(3-4)Ux"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031C4Tx",
stmGlob: "STM32L031C(4-6)Tx"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031C6Tx",
stmGlob: "STM32L031C(4-6)Tx"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031C4Ux",
stmGlob: "STM32L031C(4-6)Ux"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031C6Ux",
stmGlob: "STM32L031C(4-6)Ux"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031E4Yx",
stmGlob: "STM32L031E(4-6)Yx"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031E6Yx",
stmGlob: "STM32L031E(4-6)Yx"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031F4Px",
stmGlob: "STM32L031F(4-6)Px"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031F6Px",
stmGlob: "STM32L031F(4-6)Px"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031G4Ux",
stmGlob: "STM32L031G(4-6)Ux"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031G6Ux",
stmGlob: "STM32L031G(4-6)Ux"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031G6UxS",
stmGlob: "STM32L031G6UxS"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031K4Tx",
stmGlob: "STM32L031K(4-6)Tx"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031K6Tx",
stmGlob: "STM32L031K(4-6)Tx"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031K4Ux",
stmGlob: "STM32L031K(4-6)Ux"
},
{
chibiDef: "STM32L031xx",
mcuCode: "STM32L031K6Ux",
stmGlob: "STM32L031K(4-6)Ux"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051C6Tx",
stmGlob: "STM32L051C(6-8)Tx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051C8Tx",
stmGlob: "STM32L051C(6-8)Tx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051C6Ux",
stmGlob: "STM32L051C(6-8)Ux"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051C8Ux",
stmGlob: "STM32L051C(6-8)Ux"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051K6Tx",
stmGlob: "STM32L051K(6-8)Tx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051K8Tx",
stmGlob: "STM32L051K(6-8)Tx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051K6Ux",
stmGlob: "STM32L051K(6-8)Ux"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051K8Ux",
stmGlob: "STM32L051K(6-8)Ux"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051R6Hx",
stmGlob: "STM32L051R(6-8)Hx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051R8Hx",
stmGlob: "STM32L051R(6-8)Hx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051R6Tx",
stmGlob: "STM32L051R(6-8)Tx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051R8Tx",
stmGlob: "STM32L051R(6-8)Tx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051T6Yx",
stmGlob: "STM32L051T(6-8)Yx"
},
{
chibiDef: "STM32L051xx",
mcuCode: "STM32L051T8Yx",
stmGlob: "STM32L051T(6-8)Yx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052C6Tx",
stmGlob: "STM32L052C(6-8)Tx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052C8Tx",
stmGlob: "STM32L052C(6-8)Tx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052C6Ux",
stmGlob: "STM32L052C(6-8)Ux"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052C8Ux",
stmGlob: "STM32L052C(6-8)Ux"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052K6Tx",
stmGlob: "STM32L052K(6-8)Tx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052K8Tx",
stmGlob: "STM32L052K(6-8)Tx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052K6Ux",
stmGlob: "STM32L052K(6-8)Ux"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052K8Ux",
stmGlob: "STM32L052K(6-8)Ux"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052R6Hx",
stmGlob: "STM32L052R(6-8)Hx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052R8Hx",
stmGlob: "STM32L052R(6-8)Hx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052R6Tx",
stmGlob: "STM32L052R(6-8)Tx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052R8Tx",
stmGlob: "STM32L052R(6-8)Tx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052T6Yx",
stmGlob: "STM32L052T(6-8)Yx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052T8Yx",
stmGlob: "STM32L052T(6-8)Yx"
},
{
chibiDef: "STM32L052xx",
mcuCode: "STM32L052T8Fx",
stmGlob: "STM32L052T8Fx"
},
{
chibiDef: "STM32L053xx",
mcuCode: "STM32L053C6Tx",
stmGlob: "STM32L053C(6-8)Tx"
},
{
chibiDef: "STM32L053xx",
mcuCode: "STM32L053C8Tx",
stmGlob: "STM32L053C(6-8)Tx"
},
{
chibiDef: "STM32L053xx",
mcuCode: "STM32L053C6Ux",
stmGlob: "STM32L053C(6-8)Ux"
},
{
chibiDef: "STM32L053xx",
mcuCode: "STM32L053C8Ux",
stmGlob: "STM32L053C(6-8)Ux"
},
{
chibiDef: "STM32L053xx",
mcuCode: "STM32L053R6Hx",
stmGlob: "STM32L053R(6-8)Hx"
},
{
chibiDef: "STM32L053xx",
mcuCode: "STM32L053R8Hx",
stmGlob: "STM32L053R(6-8)Hx"
},
{
chibiDef: "STM32L053xx",
mcuCode: "STM32L053R6Tx",
stmGlob: "STM32L053R(6-8)Tx"
},
{
chibiDef: "STM32L053xx",
mcuCode: "STM32L053R8Tx",
stmGlob: "STM32L053R(6-8)Tx"
},
{
chibiDef: "STM32L062xx",
mcuCode: "STM32L062C8Ux",
stmGlob: "STM32L062C8Ux"
},
{
chibiDef: "STM32L062xx",
mcuCode: "STM32L062K8Tx",
stmGlob: "STM32L062K8Tx"
},
{
chibiDef: "STM32L062xx",
mcuCode: "STM32L062K8Ux",
stmGlob: "STM32L062K8Ux"
},
{
chibiDef: "STM32L063xx",
mcuCode: "STM32L063C8Tx",
stmGlob: "STM32L063C8Tx"
},
{
chibiDef: "STM32L063xx",
mcuCode: "STM32L063C8Ux",
stmGlob: "STM32L063C8Ux"
},
{
chibiDef: "STM32L063xx",
mcuCode: "STM32L063R8Tx",
stmGlob: "STM32L063R8Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071C8Tx",
stmGlob: "STM32L071C8Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071C8Ux",
stmGlob: "STM32L071C8Ux"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071CBTx",
stmGlob: "STM32L071C(B-Z)Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071CZTx",
stmGlob: "STM32L071C(B-Z)Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071CBUx",
stmGlob: "STM32L071C(B-Z)Ux"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071CZUx",
stmGlob: "STM32L071C(B-Z)Ux"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071CBYx",
stmGlob: "STM32L071C(B-Z)Yx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071CZYx",
stmGlob: "STM32L071C(B-Z)Yx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071K8Ux",
stmGlob: "STM32L071K8Ux"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071KBTx",
stmGlob: "STM32L071K(B-Z)Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071KZTx",
stmGlob: "STM32L071K(B-Z)Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071KBUx",
stmGlob: "STM32L071K(B-Z)Ux"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071KZUx",
stmGlob: "STM32L071K(B-Z)Ux"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071RBHx",
stmGlob: "STM32L071R(B-Z)Hx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071RZHx",
stmGlob: "STM32L071R(B-Z)Hx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071RBTx",
stmGlob: "STM32L071R(B-Z)Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071RZTx",
stmGlob: "STM32L071R(B-Z)Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071V8Ix",
stmGlob: "STM32L071V8Ix"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071V8Tx",
stmGlob: "STM32L071V8Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071VBIx",
stmGlob: "STM32L071V(B-Z)Ix"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071VZIx",
stmGlob: "STM32L071V(B-Z)Ix"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071VBTx",
stmGlob: "STM32L071V(B-Z)Tx"
},
{
chibiDef: "STM32L071xx",
mcuCode: "STM32L071VZTx",
stmGlob: "STM32L071V(B-Z)Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072CBTx",
stmGlob: "STM32L072C(B-Z)Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072CZTx",
stmGlob: "STM32L072C(B-Z)Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072CBUx",
stmGlob: "STM32L072C(B-Z)Ux"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072CZUx",
stmGlob: "STM32L072C(B-Z)Ux"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072CBYx",
stmGlob: "STM32L072C(B-Z)Yx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072CZYx",
stmGlob: "STM32L072C(B-Z)Yx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072CZEx",
stmGlob: "STM32L072CZEx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072KBTx",
stmGlob: "STM32L072K(B-Z)Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072KZTx",
stmGlob: "STM32L072K(B-Z)Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072KBUx",
stmGlob: "STM32L072K(B-Z)Ux"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072KZUx",
stmGlob: "STM32L072K(B-Z)Ux"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072RBHx",
stmGlob: "STM32L072R(B-Z)Hx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072RZHx",
stmGlob: "STM32L072R(B-Z)Hx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072RBIx",
stmGlob: "STM32L072R(B-Z)Ix"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072RZIx",
stmGlob: "STM32L072R(B-Z)Ix"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072RBTx",
stmGlob: "STM32L072R(B-Z)Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072RZTx",
stmGlob: "STM32L072R(B-Z)Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072V8Ix",
stmGlob: "STM32L072V8Ix"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072V8Tx",
stmGlob: "STM32L072V8Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072VBIx",
stmGlob: "STM32L072V(B-Z)Ix"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072VZIx",
stmGlob: "STM32L072V(B-Z)Ix"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072VBTx",
stmGlob: "STM32L072V(B-Z)Tx"
},
{
chibiDef: "STM32L072xx",
mcuCode: "STM32L072VZTx",
stmGlob: "STM32L072V(B-Z)Tx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073CBTx",
stmGlob: "STM32L073C(B-Z)Tx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073CZTx",
stmGlob: "STM32L073C(B-Z)Tx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073CBUx",
stmGlob: "STM32L073C(B-Z)Ux"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073CZUx",
stmGlob: "STM32L073C(B-Z)Ux"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073RBHx",
stmGlob: "STM32L073R(B-Z)Hx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073RZHx",
stmGlob: "STM32L073R(B-Z)Hx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073RBTx",
stmGlob: "STM32L073R(B-Z)Tx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073RZTx",
stmGlob: "STM32L073R(B-Z)Tx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073RZIx",
stmGlob: "STM32L073RZIx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073V8Ix",
stmGlob: "STM32L073V8Ix"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073V8Tx",
stmGlob: "STM32L073V8Tx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073VBIx",
stmGlob: "STM32L073V(B-Z)Ix"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073VZIx",
stmGlob: "STM32L073V(B-Z)Ix"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073VBTx",
stmGlob: "STM32L073V(B-Z)Tx"
},
{
chibiDef: "STM32L073xx",
mcuCode: "STM32L073VZTx",
stmGlob: "STM32L073V(B-Z)Tx"
},
{
chibiDef: "STM32L100xB",
mcuCode: "STM32L100RBTxA",
stmGlob: "STM32L100R(8-B)TxA"
},
{
chibiDef: "STM32L100xB",
mcuCode: "STM32L100RBTx",
stmGlob: "STM32L100R(8-B)Tx"
},
{
chibiDef: "STM32L100xC",
mcuCode: "STM32L100RCTx",
stmGlob: "STM32L100RCTx"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151CBTxA",
stmGlob: "STM32L151C(6-8-B)TxA"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151CBTx",
stmGlob: "STM32L151C(6-8-B)Tx"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151CBUxA",
stmGlob: "STM32L151C(6-8-B)UxA"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151CBUx",
stmGlob: "STM32L151C(6-8-B)Ux"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151CCTx",
stmGlob: "STM32L151CCTx"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151CCUx",
stmGlob: "STM32L151CCUx"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151QCHx",
stmGlob: "STM32L151QCHx"
},
{
chibiDef: "STM32L151xD",
mcuCode: "STM32L151QDHx",
stmGlob: "STM32L151QDHx"
},
{
chibiDef: "STM32L151xE",
mcuCode: "STM32L151QEHx",
stmGlob: "STM32L151QEHx"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151RBHxA",
stmGlob: "STM32L151R(6-8-B)HxA"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151RBHx",
stmGlob: "STM32L151R(6-8-B)Hx"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151RBTxA",
stmGlob: "STM32L151R(6-8-B)TxA"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151RBTx",
stmGlob: "STM32L151R(6-8-B)Tx"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151RCTxA",
stmGlob: "STM32L151RCTxA"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151RCTx",
stmGlob: "STM32L151RCTx"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151RCYx",
stmGlob: "STM32L151RCYx"
},
{
chibiDef: "STM32L151xD",
mcuCode: "STM32L151RDTx",
stmGlob: "STM32L151RDTx"
},
{
chibiDef: "STM32L151xD",
mcuCode: "STM32L151RDYx",
stmGlob: "STM32L151RDYx"
},
{
chibiDef: "STM32L151xE",
mcuCode: "STM32L151RETx",
stmGlob: "STM32L151RETx"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151UCYx",
stmGlob: "STM32L151UCYx"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151VBHxA",
stmGlob: "STM32L151V(8-B)HxA"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151VBHx",
stmGlob: "STM32L151V(8-B)Hx"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151VBTxA",
stmGlob: "STM32L151V(8-B)TxA"
},
{
chibiDef: "STM32L151xB",
mcuCode: "STM32L151VBTx",
stmGlob: "STM32L151V(8-B)Tx"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151VCHx",
stmGlob: "STM32L151VCHx"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151VCTxA",
stmGlob: "STM32L151VCTxA"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151VCTx",
stmGlob: "STM32L151VCTx"
},
{
chibiDef: "STM32L151xD",
mcuCode: "STM32L151VDTx",
stmGlob: "STM32L151VDTx"
},
{
chibiDef: "STM32L151xD",
mcuCode: "STM32L151VDTxX",
stmGlob: "STM32L151VDTxX"
},
{
chibiDef: "STM32L151xD",
mcuCode: "STM32L151VDYxX",
stmGlob: "STM32L151VDYxX"
},
{
chibiDef: "STM32L151xE",
mcuCode: "STM32L151VETx",
stmGlob: "STM32L151VETx"
},
{
chibiDef: "STM32L151xE",
mcuCode: "STM32L151VEYx",
stmGlob: "STM32L151VEYx"
},
{
chibiDef: "STM32L151xC",
mcuCode: "STM32L151ZCTx",
stmGlob: "STM32L151ZCTx"
},
{
chibiDef: "STM32L151xD",
mcuCode: "STM32L151ZDTx",
stmGlob: "STM32L151ZDTx"
},
{
chibiDef: "STM32L151xE",
mcuCode: "STM32L151ZETx",
stmGlob: "STM32L151ZETx"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152CBTxA",
stmGlob: "STM32L152C(6-8-B)TxA"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152CBTx",
stmGlob: "STM32L152C(6-8-B)Tx"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152CBUxA",
stmGlob: "STM32L152C(6-8-B)UxA"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152CBUx",
stmGlob: "STM32L152C(6-8-B)Ux"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152CCTx",
stmGlob: "STM32L152CCTx"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152CCUx",
stmGlob: "STM32L152CCUx"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152QCHx",
stmGlob: "STM32L152QCHx"
},
{
chibiDef: "STM32L152xD",
mcuCode: "STM32L152QDHx",
stmGlob: "STM32L152QDHx"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152RBHxA",
stmGlob: "STM32L152R(6-8-B)HxA"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152RBHx",
stmGlob: "STM32L152R(6-8-B)Hx"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152RBTxA",
stmGlob: "STM32L152R(6-8-B)TxA"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152RBTx",
stmGlob: "STM32L152R(6-8-B)Tx"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152RCTxA",
stmGlob: "STM32L152RCTxA"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152RCTx",
stmGlob: "STM32L152RCTx"
},
{
chibiDef: "STM32L152xD",
mcuCode: "STM32L152RDTx",
stmGlob: "STM32L152RDTx"
},
{
chibiDef: "STM32L152xD",
mcuCode: "STM32L152RDYx",
stmGlob: "STM32L152RDYx"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152UCYx",
stmGlob: "STM32L152UCYx"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152VBHxA",
stmGlob: "STM32L152V(8-B)HxA"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152VBHx",
stmGlob: "STM32L152V(8-B)Hx"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152VBTxA",
stmGlob: "STM32L152V(8-B)TxA"
},
{
chibiDef: "STM32L152xB",
mcuCode: "STM32L152VBTx",
stmGlob: "STM32L152V(8-B)Tx"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152VCHx",
stmGlob: "STM32L152VCHx"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152VCTxA",
stmGlob: "STM32L152VCTxA"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152VCTx",
stmGlob: "STM32L152VCTx"
},
{
chibiDef: "STM32L152xD",
mcuCode: "STM32L152VDTx",
stmGlob: "STM32L152VDTx"
},
{
chibiDef: "STM32L152xD",
mcuCode: "STM32L152VDTxX",
stmGlob: "STM32L152VDTxX"
},
{
chibiDef: "STM32L152xC",
mcuCode: "STM32L152ZCTx",
stmGlob: "STM32L152ZCTx"
},
{
chibiDef: "STM32L152xD",
mcuCode: "STM32L152ZDTx",
stmGlob: "STM32L152ZDTx"
},
{
chibiDef: "STM32L162xC",
mcuCode: "STM32L162QCHx",
stmGlob: "STM32L162QCHx"
},
{
chibiDef: "STM32L162xD",
mcuCode: "STM32L162QDHx",
stmGlob: "STM32L162QDHx"
},
{
chibiDef: "STM32L162xC",
mcuCode: "STM32L162RCTxA",
stmGlob: "STM32L162RCTxA"
},
{
chibiDef: "STM32L162xC",
mcuCode: "STM32L162RCTx",
stmGlob: "STM32L162RCTx"
},
{
chibiDef: "STM32L162xD",
mcuCode: "STM32L162RDTx",
stmGlob: "STM32L162RDTx"
},
{
chibiDef: "STM32L162xD",
mcuCode: "STM32L162RDYx",
stmGlob: "STM32L162RDYx"
},
{
chibiDef: "STM32L162xE",
mcuCode: "STM32L162RETx",
stmGlob: "STM32L162RETx"
},
{
chibiDef: "STM32L162xC",
mcuCode: "STM32L162VCHx",
stmGlob: "STM32L162VCHx"
},
{
chibiDef: "STM32L162xC",
mcuCode: "STM32L162VCTxA",
stmGlob: "STM32L162VCTxA"
},
{
chibiDef: "STM32L162xC",
mcuCode: "STM32L162VCTx",
stmGlob: "STM32L162VCTx"
},
{
chibiDef: "STM32L162xD",
mcuCode: "STM32L162VDTx",
stmGlob: "STM32L162VDTx"
},
{
chibiDef: "STM32L162xD",
mcuCode: "STM32L162VDYxX",
stmGlob: "STM32L162VDYxX"
},
{
chibiDef: "STM32L162xE",
mcuCode: "STM32L162VETx",
stmGlob: "STM32L162VETx"
},
{
chibiDef: "STM32L162xE",
mcuCode: "STM32L162VEYx",
stmGlob: "STM32L162VEYx"
},
{
chibiDef: "STM32L162xC",
mcuCode: "STM32L162ZCTx",
stmGlob: "STM32L162ZCTx"
},
{
chibiDef: "STM32L162xD",
mcuCode: "STM32L162ZDTx",
stmGlob: "STM32L162ZDTx"
},
{
chibiDef: "STM32L162xE",
mcuCode: "STM32L162ZETx",
stmGlob: "STM32L162ZETx"
},
{
chibiDef: "STM32L432xx",
mcuCode: "STM32L432KBUx",
stmGlob: "STM32L432K(B-C)Ux"
},
{
chibiDef: "STM32L432xx",
mcuCode: "STM32L432KCUx",
stmGlob: "STM32L432K(B-C)Ux"
},
{
chibiDef: "STM32L443xx",
mcuCode: "STM32L443CCTx",
stmGlob: "STM32L443CCTx"
},
{
chibiDef: "STM32L443xx",
mcuCode: "STM32L443CCUx",
stmGlob: "STM32L443CCUx"
},
{
chibiDef: "STM32L443xx",
mcuCode: "STM32L443CCYx",
stmGlob: "STM32L443CCYx"
},
{
chibiDef: "STM32L443xx",
mcuCode: "STM32L443RCIx",
stmGlob: "STM32L443RCIx"
},
{
chibiDef: "STM32L443xx",
mcuCode: "STM32L443RCTx",
stmGlob: "STM32L443RCTx"
},
{
chibiDef: "STM32L443xx",
mcuCode: "STM32L443RCYx",
stmGlob: "STM32L443RCYx"
},
{
chibiDef: "STM32L443xx",
mcuCode: "STM32L443VCIx",
stmGlob: "STM32L443VCIx"
},
{
chibiDef: "STM32L443xx",
mcuCode: "STM32L443VCTx",
stmGlob: "STM32L443VCTx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476JEYx",
stmGlob: "STM32L476J(E-G)Yx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476JGYx",
stmGlob: "STM32L476J(E-G)Yx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476JGYxP",
stmGlob: "STM32L476JGYxP"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476MEYx",
stmGlob: "STM32L476M(E-G)Yx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476MGYx",
stmGlob: "STM32L476M(E-G)Yx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476QEIx",
stmGlob: "STM32L476Q(E-G)Ix"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476QGIx",
stmGlob: "STM32L476Q(E-G)Ix"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476RCTx",
stmGlob: "STM32L476R(C-E-G)Tx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476RETx",
stmGlob: "STM32L476R(C-E-G)Tx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476RGTx",
stmGlob: "STM32L476R(C-E-G)Tx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476VCTx",
stmGlob: "STM32L476V(C-E-G)Tx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476VETx",
stmGlob: "STM32L476V(C-E-G)Tx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476VGTx",
stmGlob: "STM32L476V(C-E-G)Tx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476ZETx",
stmGlob: "STM32L476Z(E-G)Tx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476ZGTx",
stmGlob: "STM32L476Z(E-G)Tx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476ZGJx",
stmGlob: "STM32L476ZGJx"
},
{
chibiDef: "STM32L476xx",
mcuCode: "STM32L476ZGTxP",
stmGlob: "STM32L476ZGTxP"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496AEIx",
stmGlob: "STM32L496A(E-G)Ix"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496AGIx",
stmGlob: "STM32L496A(E-G)Ix"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496AGIxP",
stmGlob: "STM32L496AGIxP"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496QEIx",
stmGlob: "STM32L496Q(E-G)Ix"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496QGIx",
stmGlob: "STM32L496Q(E-G)Ix"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496QGIxP",
stmGlob: "STM32L496QGIxP"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496RETx",
stmGlob: "STM32L496R(E-G)Tx"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496RGTx",
stmGlob: "STM32L496R(E-G)Tx"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496RGTxP",
stmGlob: "STM32L496RGTxP"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496VETx",
stmGlob: "STM32L496V(E-G)Tx"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496VGTx",
stmGlob: "STM32L496V(E-G)Tx"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496VGTxP",
stmGlob: "STM32L496VGTxP"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496VGYxP",
stmGlob: "STM32L496VGYxP"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496VGYx",
stmGlob: "STM32L496VGYx"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496WGYxP",
stmGlob: "STM32L496WGYxP"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496ZETx",
stmGlob: "STM32L496Z(E-G)Tx"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496ZGTx",
stmGlob: "STM32L496Z(E-G)Tx"
},
{
chibiDef: "STM32L496xx",
mcuCode: "STM32L496ZGTxP",
stmGlob: "STM32L496ZGTxP"
}
];
var supportedMcus$1 = /*#__PURE__*/Object.freeze({
__proto__: null,
'default': supportedMcus
});
var require$$5 = getCjsExportFromNamespace(supportedMcus$1);
// Generated by LiveScript 1.6.0
var ref$$4, DcsTcpClient$1, Actor$2, SignalBranch$2, config$1, fs, ractiveCompile, readdirSyncRecursive, supportedMcus$2, find$2, map$2, pairsToObj$1, TemplateEngine;
ref$$4 = dcs, DcsTcpClient$1 = ref$$4.DcsTcpClient, Actor$2 = ref$$4.Actor, SignalBranch$2 = ref$$4.SignalBranch;
config$1 = config;
fs = fs__default['default'];
ractiveCompile = ractiveTemplate.ractiveCompile;
readdirSyncRecursive = readdirSyncRecursive_1.readdirSyncRecursive;
supportedMcus$2 = require$$5;
ref$$4 = preludeLs__default['default'], find$2 = ref$$4.find, map$2 = ref$$4.map, pairsToObj$1 = ref$$4.pairsToObj;
new (TemplateEngine = (function(superclass){
var prototype = extend$((import$(TemplateEngine, superclass).displayName = 'TemplateEngine', TemplateEngine), superclass).prototype;
TemplateEngine.prototype.action = function(){
var this$ = this;
return this.onTopic('@templating.get', function(msg){
var configOrig, data, mcu, ref$, pinout, response, b, s, dir, templates;
configOrig = JSON.stringify(msg.data.config, null, 2);
data = {};
for (mcu in ref$ = msg.data.config) {
pinout = ref$[mcu];
data["mcu"] = find$2(fn$, supportedMcus$2);
data["pinout"] = pinout;
}
response = {};
b = new SignalBranch$2;
if (data.mcu) {
s = b.add();
dir = "./hw-template";
templates = readdirSyncRecursive(dir);
this$.sendRequest("@datasheet.mcu-info", {
id: mcu
}, function(err, res){
var e, pinNames, pin, ref$, pinout, ref1$, i$, len$, template, file, compiled;
if (e = err || res.error) {
return s.go(e);
}
pinNames = pairsToObj$1(
map$2(function(it){
return [it.Position, it.Name.replace(/-.+/, '')];
})(
map$2(function(it){
return it._attributes;
})(
res.data.info.Pin)));
for (pin in ref$ = data.pinout) {
pinout = ref$[pin];
pinout.pinName = pinNames[pin];
pinout.ioName = pinNames[pin] + "_" + pinout.peripheral.type.toUpperCase();
pinout.af = (ref1$ = pinout.peripheral.type) !== 'din' && ref1$ !== 'dout';
pinout.gpioPort = "GPIO" + pinNames[pin][1].toUpperCase();
}
/*********************************************************
data.pinout = {
pin-number:
peripheral: # Object
id: String, peripheral id, eg. "din" or "pwm-1.3", see webapps/main/stm/peripheral-defs.ls
name: String, Human readable name
stm: String, STM type, eg. GPIO
type: String, peripheral type, eg. din for Digital Input
config: # Object, Configuration regarding to @peripheral.type
pin-name: eg. PA1
io-name: eg. PA1_PWM
gpio-port: eg. GPIOA
*********************************************************/
for (i$ = 0, len$ = (ref$ = templates).length; i$ < len$; ++i$) {
template = ref$[i$];
file = fs.readFileSync(dir + "/" + template, "utf-8");
compiled = ractiveCompile(file, data);
response[template] = compiled;
}
response["config.json"] = configOrig;
return s.go();
});
} else {
response["error"] = "Unknown MCU: " + mcu;
}
return b.joined(function(){
this$.log.log("Requested hardware definition.");
return this$.sendResponse(msg, response);
});
function fn$(it){
return it.stmGlob === mcu;
}
});
};
function TemplateEngine(){
TemplateEngine.superclass.apply(this, arguments);
}
return TemplateEngine;
}(Actor$2)));
new DcsTcpClient$1({
port: config$1.dcsPort
}).login({
user: "templating",
password: "1234"
});
function extend$(sub, sup){
function fun(){} fun.prototype = (sub.superclass = sup).prototype;
(sub.prototype = new fun).constructor = sub;
if (typeof sup.extended == 'function') sup.extended(sub);
return sub;
}
function import$(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
}
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiX190ZW1wbGF0ZS5scy5qcyIsInNvdXJjZXMiOlsiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvY29sb3JzL2xpYi9zdHlsZXMuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9jb2xvcnMvbGliL3N5c3RlbS9oYXMtZmxhZy5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2NvbG9ycy9saWIvc3lzdGVtL3N1cHBvcnRzLWNvbG9ycy5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2NvbG9ycy9saWIvY3VzdG9tL3RyYXAuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9jb2xvcnMvbGliL2N1c3RvbS96YWxnby5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2NvbG9ycy9saWIvbWFwcy9hbWVyaWNhLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvY29sb3JzL2xpYi9tYXBzL3plYnJhLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvY29sb3JzL2xpYi9tYXBzL3JhaW5ib3cuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9jb2xvcnMvbGliL21hcHMvcmFuZG9tLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvY29sb3JzL2xpYi9jb2xvcnMuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9jb2xvcnMvbGliL2V4dGVuZFN0cmluZ1Byb3RvdHlwZS5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2NvbG9ycy9saWIvaW5kZXguanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9tb21lbnQvbW9tZW50LmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvcHJlbHVkZS1scy9saWIvRnVuYy5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL3ByZWx1ZGUtbHMvbGliL0xpc3QuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9wcmVsdWRlLWxzL2xpYi9PYmouanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9wcmVsdWRlLWxzL2xpYi9TdHIuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9wcmVsdWRlLWxzL2xpYi9OdW0uanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9wcmVsdWRlLWxzL2xpYi9pbmRleC5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3MvbGliL2V2ZW50LWVtaXR0ZXIubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL2xpYi9sb2dnZXIubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9zZXRpbW1lZGlhdGUvc2V0SW1tZWRpYXRlLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9saWIvc2xlZXAubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9qc29uZGlmZnBhdGNoL3NyYy9lbnZpcm9ubWVudC5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2pzb25kaWZmcGF0Y2gvc3JjL3Byb2Nlc3Nvci5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2pzb25kaWZmcGF0Y2gvc3JjL3BpcGUuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9qc29uZGlmZnBhdGNoL3NyYy9jb250ZXh0cy9jb250ZXh0LmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvanNvbmRpZmZwYXRjaC9zcmMvY2xvbmUuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9qc29uZGlmZnBhdGNoL3NyYy9jb250ZXh0cy9kaWZmLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvanNvbmRpZmZwYXRjaC9zcmMvY29udGV4dHMvcGF0Y2guanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9qc29uZGlmZnBhdGNoL3NyYy9jb250ZXh0cy9yZXZlcnNlLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvanNvbmRpZmZwYXRjaC9zcmMvZmlsdGVycy90cml2aWFsLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvanNvbmRpZmZwYXRjaC9zcmMvZmlsdGVycy9uZXN0ZWQuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9qc29uZGlmZnBhdGNoL3NyYy9maWx0ZXJzL2xjcy5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2pzb25kaWZmcGF0Y2gvc3JjL2ZpbHRlcnMvYXJyYXlzLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvanNvbmRpZmZwYXRjaC9zcmMvZmlsdGVycy9kYXRlcy5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2pzb25kaWZmcGF0Y2gvc3JjL2ZpbHRlcnMvdGV4dHMuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9qc29uZGlmZnBhdGNoL3NyYy9kaWZmcGF0Y2hlci5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2pzb25kaWZmcGF0Y2gvc3JjL2RhdGUtcmV2aXZlci5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL2pzb25kaWZmcGF0Y2gvc3JjL21haW4uanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL2xpYi9wYWNraW5nLmxzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9saWIvbWVyZ2UubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL2xpYi9pcC10by1oZXgubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL2xpYi9pbmRleC5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3MvbGliL2RlYnVnLXRvb2xzLmxzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9zcmMvdG9waWMtbWF0Y2gubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL3NyYy9hY3Rvci9hY3Rvci1tYW5hZ2VyLmxzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9zcmMvc2lnbmFsL2RlcHMubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL3NyYy9zaWduYWwvc3JjL3NpZ25hbC5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvc3JjL3NpZ25hbC9zcmMvc2lnbmFsLWJyYW5jaC5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvc3JjL3NpZ25hbC9pbmRleC5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvc3JjL2FjdG9yL3JlcXVlc3QubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL3NyYy9hY3Rvci9pbmRleC5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvc3JjL2ZpbHRlcnMubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9pbmhlcml0cy9pbmhlcml0c19icm93c2VyLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvaW5oZXJpdHMvaW5oZXJpdHMuanMiLCIuLi8uLi9ub2RlX21vZHVsZXMvc2FmZS1idWZmZXIvaW5kZXguanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9zaGEuanMvaGFzaC5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL3NoYS5qcy9zaGEuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9zaGEuanMvc2hhMS5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL3NoYS5qcy9zaGEyNTYuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9zaGEuanMvc2hhMjI0LmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9ub2RlX21vZHVsZXMvc2hhLmpzL3NoYTUxMi5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvbm9kZV9tb2R1bGVzL3NoYS5qcy9zaGEzODQuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy9zaGEuanMvaW5kZXguanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL3NyYy9hdXRoLWhlbHBlcnMubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL3NyYy9hdXRoLXJlcXVlc3QubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL25vZGVfbW9kdWxlcy91dWlkNC9pbmRleC5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvc3JjL2Vycm9ycy5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvc3JjL2F1dGgtaGFuZGxlci5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3Mvc2VydmljZXMvZGNzLXByb3h5L2RlcHMubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL3NlcnZpY2VzL2Rjcy1wcm94eS9wcm90b2NvbC1hY3Rvci9oZWxwZXJzLmxzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9zZXJ2aWNlcy9kY3MtcHJveHkvcHJvdG9jb2wtYWN0b3IvY2xpZW50LmxzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9zZXJ2aWNlcy9jb3VjaC1kY3Mvbm9kZV9tb2R1bGVzL21zL2luZGV4LmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy90cmFuc3BvcnRzL3RjcC9ub2RlX21vZHVsZXMvZGVidWcvc3JjL2RlYnVnLmpzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy90cmFuc3BvcnRzL3RjcC9ub2RlX21vZHVsZXMvZGVidWcvc3JjL2Jyb3dzZXIuanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL3RyYW5zcG9ydHMvdGNwL25vZGVfbW9kdWxlcy9kZWJ1Zy9zcmMvbm9kZS5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3MvdHJhbnNwb3J0cy90Y3Avbm9kZV9tb2R1bGVzL2RlYnVnL3NyYy9pbmRleC5qcyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3MvdHJhbnNwb3J0cy90Y3Avbm9kZV9tb2R1bGVzL25vZGUtbmV0LXJlY29ubmVjdC9zcmMvaW5kZXguanMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL3RyYW5zcG9ydHMvdGNwL2luZGV4LmxzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9zZXJ2aWNlcy9kY3MtcHJveHkvdGNwL2NsaWVudC5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3MvcHJveHktYWN0b3JzL2lvLXByb3h5L2lvLXByb3h5LWNsaWVudC5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3MvbGliL2tleXBhdGgubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL2xpYi9tZW1vcnktbWFwLmxzIiwiLi4vLi4vc2NhZGEuanMvbGliL2Rjcy9wcm94eS1hY3RvcnMvaW8tcHJveHkvaW8tcHJveHktaGFuZGxlci5scyIsIi4uLy4uL3NjYWRhLmpzL2xpYi9kY3MvZHJpdmVycy9kcml2ZXItYWJzdHJhY3QvaW5kZXgubHMiLCIuLi8uLi9zY2FkYS5qcy9saWIvZGNzL2luZGV4LmxzIiwiLi4vLi4vY29uZmlnLmxzIiwicmFjdGl2ZS10ZW1wbGF0ZS5scyIsInJlYWRkaXItc3luYy1yZWN1cnNpdmUubHMiLCJ0ZW1wbGF0ZS5scyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuVGhlIE1JVCBMaWNlbnNlIChNSVQpXG5cbkNvcHlyaWdodCAoYykgU2luZHJlIFNvcmh1cyA8c2luZHJlc29yaHVzQGdtYWlsLmNvbT4gKHNpbmRyZXNvcmh1cy5jb20pXG5cblBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbm9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbmluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbnRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbmFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG5JTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbkZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbk9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cblRIRSBTT0ZUV0FSRS5cblxuKi9cblxudmFyIHN0eWxlcyA9IHt9O1xubW9kdWxlWydleHBvcnRzJ10gPSBzdHlsZXM7XG5cbnZhciBjb2RlcyA9IHtcbiAgcmVzZXQ6IFswLCAwXSxcblxuICBib2xkOiBbMSwgMjJdLFxuICBkaW06IFsyLCAyMl0sXG4gIGl0YWxpYzogWzMsIDIzXSxcbiAgdW5kZXJsaW5lOiBbNCwgMjRdLFxuICBpbnZlcnNlOiBbNywgMjddLFxuICBoaWRkZW46IFs4LCAyOF0sXG4gIHN0cmlrZXRocm91Z2g6IFs5LCAyOV0sXG5cbiAgYmxhY2s6IFszMCwgMzldLFxuICByZWQ6IFszMSwgMzldLFxuICBncmVlbjogWzMyLCAzOV0sXG4gIHllbGxvdzogWzMzLCAzOV0sXG4gIGJsdWU6IFszNCwgMzldLFxuICBtYWdlbnRhOiBbMzUsIDM5XSxcbiAgY3lhbjogWzM2LCAzOV0sXG4gIHdoaXRlOiBbMzcsIDM5XSxcbiAgZ3JheTogWzkwLCAzOV0sXG4gIGdyZXk6IFs5MCwgMzldLFxuXG4gIGJyaWdodFJlZDogWzkxLCAzOV0sXG4gIGJyaWdodEdyZWVuOiBbOTIsIDM5XSxcbiAgYnJpZ2h0WWVsbG93OiBbOTMsIDM5XSxcbiAgYnJpZ2h0Qmx1ZTogWzk0LCAzOV0sXG4gIGJyaWdodE1hZ2VudGE6IFs5NSwgMzldLFxuICBicmlnaHRDeWFuOiBbOTYsIDM5XSxcbiAgYnJpZ2h0V2hpdGU6IFs5NywgMzldLFxuXG4gIGJnQmxhY2s6IFs0MCwgNDldLFxuICBiZ1JlZDogWzQxLCA0OV0sXG4gIGJnR3JlZW46IFs0MiwgNDldLFxuICBiZ1llbGxvdzogWzQzLCA0OV0sXG4gIGJnQmx1ZTogWzQ0LCA0OV0sXG4gIGJnTWFnZW50YTogWzQ1LCA0OV0sXG4gIGJnQ3lhbjogWzQ2LCA0OV0sXG4gIGJnV2hpdGU6IFs0NywgNDldLFxuICBiZ0dyYXk6IFsxMDAsIDQ5XSxcbiAgYmdHcmV5OiBbMTAwLCA0OV0sXG5cbiAgYmdCcmlnaHRSZWQ6IFsxMDEsIDQ5XSxcbiAgYmdCcmlnaHRHcmVlbjogWzEwMiwgNDldLFxuICBiZ0JyaWdodFllbGxvdzogWzEwMywgNDldLFxuICBiZ0JyaWdodEJsdWU6IFsxMDQsIDQ5XSxcbiAgYmdCcmlnaHRNYWdlbnRhOiBbMTA1LCA0OV0sXG4gIGJnQnJpZ2h0Q3lhbjogWzEwNiwgNDldLFxuICBiZ0JyaWdodFdoaXRlOiBbMTA3LCA0OV0sXG5cbiAgLy8gbGVnYWN5IHN0eWxlcyBmb3IgY29sb3JzIHByZSB2MS4wLjBcbiAgYmxhY2tCRzogWzQwLCA0OV0sXG4gIHJlZEJHOiBbNDEsIDQ5XSxcbiAgZ3JlZW5CRzogWzQyLCA0OV0sXG4gIHllbGxvd0JHOiBbNDMsIDQ5XSxcbiAgYmx1ZUJHOiBbNDQsIDQ5XSxcbiAgbWFnZW50YUJHOiBbNDUsIDQ5XSxcbiAgY3lhbkJHOiBbNDYsIDQ5XSxcbiAgd2hpdGVCRzogWzQ3LCA0OV0sXG5cbn07XG5cbk9iamVjdC5rZXlzKGNvZGVzKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICB2YXIgdmFsID0gY29kZXNba2V5XTtcbiAgdmFyIHN0eWxlID0gc3R5bGVzW2tleV0gPSBbXTtcbiAgc3R5bGUub3BlbiA9ICdcXHUwMDFiWycgKyB2YWxbMF0gKyAnbSc7XG4gIHN0eWxlLmNsb3NlID0gJ1xcdTAwMWJbJyArIHZhbFsxXSArICdtJztcbn0pO1xuIiwiLypcbk1JVCBMaWNlbnNlXG5cbkNvcHlyaWdodCAoYykgU2luZHJlIFNvcmh1cyA8c2luZHJlc29yaHVzQGdtYWlsLmNvbT4gKHNpbmRyZXNvcmh1cy5jb20pXG5cblBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHkgb2ZcbnRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW5cbnRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG9cbnVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzXG5vZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG9cbnNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW4gYWxsXG5jb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG5JTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbkZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbk9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG5TT0ZUV0FSRS5cbiovXG5cbid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbihmbGFnLCBhcmd2KSB7XG4gIGFyZ3YgPSBhcmd2IHx8IHByb2Nlc3MuYXJndjtcblxuICB2YXIgdGVybWluYXRvclBvcyA9IGFyZ3YuaW5kZXhPZignLS0nKTtcbiAgdmFyIHByZWZpeCA9IC9eLXsxLDJ9Ly50ZXN0KGZsYWcpID8gJycgOiAnLS0nO1xuICB2YXIgcG9zID0gYXJndi5pbmRleE9mKHByZWZpeCArIGZsYWcpO1xuXG4gIHJldHVybiBwb3MgIT09IC0xICYmICh0ZXJtaW5hdG9yUG9zID09PSAtMSA/IHRydWUgOiBwb3MgPCB0ZXJtaW5hdG9yUG9zKTtcbn07XG4iLCIvKlxuVGhlIE1JVCBMaWNlbnNlIChNSVQpXG5cbkNvcHlyaWdodCAoYykgU2luZHJlIFNvcmh1cyA8c2luZHJlc29yaHVzQGdtYWlsLmNvbT4gKHNpbmRyZXNvcmh1cy5jb20pXG5cblBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbm9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbmluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbnRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbmFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG5JTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbkZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbk9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cblRIRSBTT0ZUV0FSRS5cblxuKi9cblxuJ3VzZSBzdHJpY3QnO1xuXG52YXIgb3MgPSByZXF1aXJlKCdvcycpO1xudmFyIGhhc0ZsYWcgPSByZXF1aXJlKCcuL2hhcy1mbGFnLmpzJyk7XG5cbnZhciBlbnYgPSBwcm9jZXNzLmVudjtcblxudmFyIGZvcmNlQ29sb3IgPSB2b2lkIDA7XG5pZiAoaGFzRmxhZygnbm8tY29sb3InKSB8fCBoYXNGbGFnKCduby1jb2xvcnMnKSB8fCBoYXNGbGFnKCdjb2xvcj1mYWxzZScpKSB7XG4gIGZvcmNlQ29sb3IgPSBmYWxzZTtcbn0gZWxzZSBpZiAoaGFzRmxhZygnY29sb3InKSB8fCBoYXNGbGFnKCdjb2xvcnMnKSB8fCBoYXNGbGFnKCdjb2xvcj10cnVlJylcbiAgICAgICAgICAgfHwgaGFzRmxhZygnY29sb3I9YWx3YXlzJykpIHtcbiAgZm9yY2VDb2xvciA9IHRydWU7XG59XG5pZiAoJ0ZPUkNFX0NPTE9SJyBpbiBlbnYpIHtcbiAgZm9yY2VDb2xvciA9IGVudi5GT1JDRV9DT0xPUi5sZW5ndGggPT09IDBcbiAgICB8fCBwYXJzZUludChlbnYuRk9SQ0VfQ09MT1IsIDEwKSAhPT0gMDtcbn1cblxuZnVuY3Rpb24gdHJhbnNsYXRlTGV2ZWwobGV2ZWwpIHtcbiAgaWYgKGxldmVsID09PSAwKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBsZXZlbDogbGV2ZWwsXG4gICAgaGFzQmFzaWM6IHRydWUsXG4gICAgaGFzMjU2OiBsZXZlbCA+PSAyLFxuICAgIGhhczE2bTogbGV2ZWwgPj0gMyxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc3VwcG9ydHNDb2xvcihzdHJlYW0pIHtcbiAgaWYgKGZvcmNlQ29sb3IgPT09IGZhbHNlKSB7XG4gICAgcmV0dXJuIDA7XG4gIH1cblxuICBpZiAoaGFzRmxhZygnY29sb3I9MTZtJykgfHwgaGFzRmxhZygnY29sb3I9ZnVsbCcpXG4gICAgICB8fCBoYXNGbGFnKCdjb2xvcj10cnVlY29sb3InKSkge1xuICAgIHJldHVybiAzO1xuICB9XG5cbiAgaWYgKGhhc0ZsYWcoJ2NvbG9yPTI1NicpKSB7XG4gICAgcmV0dXJuIDI7XG4gIH1cblxuICBpZiAoc3RyZWFtICYmICFzdHJlYW0uaXNUVFkgJiYgZm9yY2VDb2xvciAhPT0gdHJ1ZSkge1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgdmFyIG1pbiA9IGZvcmNlQ29sb3IgPyAxIDogMDtcblxuICBpZiAocHJvY2Vzcy5wbGF0Zm9ybSA9PT0gJ3dpbjMyJykge1xuICAgIC8vIE5vZGUuanMgNy41LjAgaXMgdGhlIGZpcnN0IHZlcnNpb24gb2YgTm9kZS5qcyB0byBpbmNsdWRlIGEgcGF0Y2ggdG9cbiAgICAvLyBsaWJ1diB0aGF0IGVuYWJsZXMgMjU2IGNvbG9yIG91dHB1dCBvbiBXaW5kb3dzLiBBbnl0aGluZyBlYXJsaWVyIGFuZCBpdFxuICAgIC8vIHdvbid0IHdvcmsuIEhvd2V2ZXIsIGhlcmUgd2UgdGFyZ2V0IE5vZGUuanMgOCBhdCBtaW5pbXVtIGFzIGl0IGlzIGFuIExUU1xuICAgIC8vIHJlbGVhc2UsIGFuZCBOb2RlLmpzIDcgaXMgbm90LiBXaW5kb3dzIDEwIGJ1aWxkIDEwNTg2IGlzIHRoZSBmaXJzdFxuICAgIC8vIFdpbmRvd3MgcmVsZWFzZSB0aGF0IHN1cHBvcnRzIDI1NiBjb2xvcnMuIFdpbmRvd3MgMTAgYnVpbGQgMTQ5MzEgaXMgdGhlXG4gICAgLy8gZmlyc3QgcmVsZWFzZSB0aGF0IHN1cHBvcnRzIDE2bS9UcnVlQ29sb3IuXG4gICAgdmFyIG9zUmVsZWFzZSA9IG9zLnJlbGVhc2UoKS5zcGxpdCgnLicpO1xuICAgIGlmIChOdW1iZXIocHJvY2Vzcy52ZXJzaW9ucy5ub2RlLnNwbGl0KCcuJylbMF0pID49IDhcbiAgICAgICAgJiYgTnVtYmVyKG9zUmVsZWFzZVswXSkgPj0gMTAgJiYgTnVtYmVyKG9zUmVsZWFzZVsyXSkgPj0gMTA1ODYpIHtcbiAgICAgIHJldHVybiBOdW1iZXIob3NSZWxlYXNlWzJdKSA+PSAxNDkzMSA/IDMgOiAyO1xuICAgIH1cblxuICAgIHJldHVybiAxO1xuICB9XG5cbiAgaWYgKCdDSScgaW4gZW52KSB7XG4gICAgaWYgKFsnVFJBVklTJywgJ0NJUkNMRUNJJywgJ0FQUFZFWU9SJywgJ0dJVExBQl9DSSddLnNvbWUoZnVuY3Rpb24oc2lnbikge1xuICAgICAgcmV0dXJuIHNpZ24gaW4gZW52O1xuICAgIH0pIHx8IGVudi5DSV9OQU1FID09PSAnY29kZXNoaXAnKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gbWluO1xuICB9XG5cbiAgaWYgKCdURUFNQ0lUWV9WRVJTSU9OJyBpbiBlbnYpIHtcbiAgICByZXR1cm4gKC9eKDlcXC4oMCpbMS05XVxcZCopXFwufFxcZHsyLH1cXC4pLy50ZXN0KGVudi5URUFNQ0lUWV9WRVJTSU9OKSA/IDEgOiAwXG4gICAgKTtcbiAgfVxuXG4gIGlmICgnVEVSTV9QUk9HUkFNJyBpbiBlbnYpIHtcbiAgICB2YXIgdmVyc2lvbiA9IHBhcnNlSW50KChlbnYuVEVSTV9QUk9HUkFNX1ZFUlNJT04gfHwgJycpLnNwbGl0KCcuJylbMF0sIDEwKTtcblxuICAgIHN3aXRjaCAoZW52LlRFUk1fUFJPR1JBTSkge1xuICAgICAgY2FzZSAnaVRlcm0uYXBwJzpcbiAgICAgICAgcmV0dXJuIHZlcnNpb24gPj0gMyA/IDMgOiAyO1xuICAgICAgY2FzZSAnSHlwZXInOlxuICAgICAgICByZXR1cm4gMztcbiAgICAgIGNhc2UgJ0FwcGxlX1Rlcm1pbmFsJzpcbiAgICAgICAgcmV0dXJuIDI7XG4gICAgICAvLyBObyBkZWZhdWx0XG4gICAgfVxuICB9XG5cbiAgaWYgKC8tMjU2KGNvbG9yKT8kL2kudGVzdChlbnYuVEVSTSkpIHtcbiAgICByZXR1cm4gMjtcbiAgfVxuXG4gIGlmICgvXnNjcmVlbnxeeHRlcm18XnZ0MTAwfF5yeHZ0fGNvbG9yfGFuc2l8Y3lnd2lufGxpbnV4L2kudGVzdChlbnYuVEVSTSkpIHtcbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIGlmICgnQ09MT1JURVJNJyBpbiBlbnYpIHtcbiAgICByZXR1cm4gMTtcbiAgfVxuXG4gIGlmIChlbnYuVEVSTSA9PT0gJ2R1bWInKSB7XG4gICAgcmV0dXJuIG1pbjtcbiAgfVxuXG4gIHJldHVybiBtaW47XG59XG5cbmZ1bmN0aW9uIGdldFN1cHBvcnRMZXZlbChzdHJlYW0pIHtcbiAgdmFyIGxldmVsID0gc3VwcG9ydHNDb2xvcihzdHJlYW0pO1xuICByZXR1cm4gdHJhbnNsYXRlTGV2ZWwobGV2ZWwpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgc3VwcG9ydHNDb2xvcjogZ2V0U3VwcG9ydExldmVsLFxuICBzdGRvdXQ6IGdldFN1cHBvcnRMZXZlbChwcm9jZXNzLnN0ZG91dCksXG4gIHN0ZGVycjogZ2V0U3VwcG9ydExldmVsKHByb2Nlc3Muc3RkZXJyKSxcbn07XG4iLCJtb2R1bGVbJ2V4cG9ydHMnXSA9IGZ1bmN0aW9uIHJ1blRoZVRyYXAodGV4dCwgb3B0aW9ucykge1xuICB2YXIgcmVzdWx0ID0gJyc7XG4gIHRleHQgPSB0ZXh0IHx8ICdSdW4gdGhlIHRyYXAsIGRyb3AgdGhlIGJhc3MnO1xuICB0ZXh0ID0gdGV4dC5zcGxpdCgnJyk7XG4gIHZhciB0cmFwID0ge1xuICAgIGE6IFsnXFx1MDA0MCcsICdcXHUwMTA0JywgJ1xcdTAyM2EnLCAnXFx1MDI0NScsICdcXHUwMzk0JywgJ1xcdTAzOWInLCAnXFx1MDQxNCddLFxuICAgIGI6IFsnXFx1MDBkZicsICdcXHUwMTgxJywgJ1xcdTAyNDMnLCAnXFx1MDI2ZScsICdcXHUwM2IyJywgJ1xcdTBlM2YnXSxcbiAgICBjOiBbJ1xcdTAwYTknLCAnXFx1MDIzYicsICdcXHUwM2ZlJ10sXG4gICAgZDogWydcXHUwMGQwJywgJ1xcdTAxOGEnLCAnXFx1MDUwMCcsICdcXHUwNTAxJywgJ1xcdTA1MDInLCAnXFx1MDUwMyddLFxuICAgIGU6IFsnXFx1MDBjYicsICdcXHUwMTE1JywgJ1xcdTAxOGUnLCAnXFx1MDI1OCcsICdcXHUwM2EzJywgJ1xcdTAzYmUnLCAnXFx1MDRiYycsXG4gICAgICAnXFx1MGE2YyddLFxuICAgIGY6IFsnXFx1MDRmYSddLFxuICAgIGc6IFsnXFx1MDI2MiddLFxuICAgIGg6IFsnXFx1MDEyNicsICdcXHUwMTk1JywgJ1xcdTA0YTInLCAnXFx1MDRiYScsICdcXHUwNGM3JywgJ1xcdTA1MGEnXSxcbiAgICBpOiBbJ1xcdTBmMGYnXSxcbiAgICBqOiBbJ1xcdTAxMzQnXSxcbiAgICBrOiBbJ1xcdTAxMzgnLCAnXFx1MDRhMCcsICdcXHUwNGMzJywgJ1xcdTA1MWUnXSxcbiAgICBsOiBbJ1xcdTAxMzknXSxcbiAgICBtOiBbJ1xcdTAyOGQnLCAnXFx1MDRjZCcsICdcXHUwNGNlJywgJ1xcdTA1MjAnLCAnXFx1MDUyMScsICdcXHUwZDY5J10sXG4gICAgbjogWydcXHUwMGQxJywgJ1xcdTAxNGInLCAnXFx1MDE5ZCcsICdcXHUwMzc2JywgJ1xcdTAzYTAnLCAnXFx1MDQ4YSddLFxuICAgIG86IFsnXFx1MDBkOCcsICdcXHUwMGY1JywgJ1xcdTAwZjgnLCAnXFx1MDFmZScsICdcXHUwMjk4JywgJ1xcdTA0N2EnLCAnXFx1MDVkZCcsXG4gICAgICAnXFx1MDZkZCcsICdcXHUwZTRmJ10sXG4gICAgcDogWydcXHUwMWY3JywgJ1xcdTA0OGUnXSxcbiAgICBxOiBbJ1xcdTA5Y2QnXSxcbiAgICByOiBbJ1xcdTAwYWUnLCAnXFx1MDFhNicsICdcXHUwMjEwJywgJ1xcdTAyNGMnLCAnXFx1MDI4MCcsICdcXHUwNDJmJ10sXG4gICAgczogWydcXHUwMGE3JywgJ1xcdTAzZGUnLCAnXFx1MDNkZicsICdcXHUwM2U4J10sXG4gICAgdDogWydcXHUwMTQxJywgJ1xcdTAxNjYnLCAnXFx1MDM3MyddLFxuICAgIHU6IFsnXFx1MDFiMScsICdcXHUwNTRkJ10sXG4gICAgdjogWydcXHUwNWQ4J10sXG4gICAgdzogWydcXHUwNDI4JywgJ1xcdTA0NjAnLCAnXFx1MDQ3YycsICdcXHUwZDcwJ10sXG4gICAgeDogWydcXHUwNGIyJywgJ1xcdTA0ZmUnLCAnXFx1MDRmYycsICdcXHUwNGZkJ10sXG4gICAgeTogWydcXHUwMGE1JywgJ1xcdTA0YjAnLCAnXFx1MDRjYiddLFxuICAgIHo6IFsnXFx1MDFiNScsICdcXHUwMjQwJ10sXG4gIH07XG4gIHRleHQuZm9yRWFjaChmdW5jdGlvbihjKSB7XG4gICAgYyA9IGMudG9Mb3dlckNhc2UoKTtcbiAgICB2YXIgY2hhcnMgPSB0cmFwW2NdIHx8IFsnICddO1xuICAgIHZhciByYW5kID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogY2hhcnMubGVuZ3RoKTtcbiAgICBpZiAodHlwZW9mIHRyYXBbY10gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICByZXN1bHQgKz0gdHJhcFtjXVtyYW5kXTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzdWx0ICs9IGM7XG4gICAgfVxuICB9KTtcbiAgcmV0dXJuIHJlc3VsdDtcbn07XG4iLCIvLyBwbGVhc2Ugbm9cbm1vZHVsZVsnZXhwb3J0cyddID0gZnVuY3Rpb24gemFsZ28odGV4dCwgb3B0aW9ucykge1xuICB0ZXh0ID0gdGV4dCB8fCAnICAgaGUgaXMgaGVyZSAgICc7XG4gIHZhciBzb3VsID0ge1xuICAgICd1cCc6IFtcbiAgICAgICfMjScsICfMjicsICfMhCcsICfMhScsXG4gICAgICAnzL8nLCAnzJEnLCAnzIYnLCAnzJAnLFxuICAgICAgJ82SJywgJ82XJywgJ82RJywgJ8yHJyxcbiAgICAgICfMiCcsICfMiicsICfNgicsICfMkycsXG4gICAgICAnzIgnLCAnzYonLCAnzYsnLCAnzYwnLFxuICAgICAgJ8yDJywgJ8yCJywgJ8yMJywgJ82QJyxcbiAgICAgICfMgCcsICfMgScsICfMiycsICfMjycsXG4gICAgICAnzJInLCAnzJMnLCAnzJQnLCAnzL0nLFxuICAgICAgJ8yJJywgJ82jJywgJ82kJywgJ82lJyxcbiAgICAgICfNpicsICfNpycsICfNqCcsICfNqScsXG4gICAgICAnzaonLCAnzasnLCAnzawnLCAnza0nLFxuICAgICAgJ82uJywgJ82vJywgJ8y+JywgJ82bJyxcbiAgICAgICfNhicsICfMmicsXG4gICAgXSxcbiAgICAnZG93bic6IFtcbiAgICAgICfMlicsICfMlycsICfMmCcsICfMmScsXG4gICAgICAnzJwnLCAnzJ0nLCAnzJ4nLCAnzJ8nLFxuICAgICAgJ8ygJywgJ8ykJywgJ8ylJywgJ8ymJyxcbiAgICAgICfMqScsICfMqicsICfMqycsICfMrCcsXG4gICAgICAnzK0nLCAnzK4nLCAnzK8nLCAnzLAnLFxuICAgICAgJ8yxJywgJ8yyJywgJ8yzJywgJ8y5JyxcbiAgICAgICfMuicsICfMuycsICfMvCcsICfNhScsXG4gICAgICAnzYcnLCAnzYgnLCAnzYknLCAnzY0nLFxuICAgICAgJ82OJywgJ82TJywgJ82UJywgJ82VJyxcbiAgICAgICfNlicsICfNmScsICfNmicsICfMoycsXG4gICAgXSxcbiAgICAnbWlkJzogW1xuICAgICAgJ8yVJywgJ8ybJywgJ8yAJywgJ8yBJyxcbiAgICAgICfNmCcsICfMoScsICfMoicsICfMpycsXG4gICAgICAnzKgnLCAnzLQnLCAnzLUnLCAnzLYnLFxuICAgICAgJ82cJywgJ82dJywgJ82eJyxcbiAgICAgICfNnycsICfNoCcsICfNoicsICfMuCcsXG4gICAgICAnzLcnLCAnzaEnLCAnINKJJyxcbiAgICBdLFxuICB9O1xuICB2YXIgYWxsID0gW10uY29uY2F0KHNvdWwudXAsIHNvdWwuZG93biwgc291bC5taWQpO1xuXG4gIGZ1bmN0aW9uIHJhbmRvbU51bWJlcihyYW5nZSkge1xuICAgIHZhciByID0gTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogcmFuZ2UpO1xuICAgIHJldHVybiByO1xuICB9XG5cbiAgZnVuY3Rpb24gaXNDaGFyKGNoYXJhY3Rlcikge1xuICAgIHZhciBib29sID0gZmFsc2U7XG4gICAgYWxsLmZpbHRlcihmdW5jdGlvbihpKSB7XG4gICAgICBib29sID0gKGkgPT09IGNoYXJhY3Rlcik7XG4gICAgfSk7XG4gICAgcmV0dXJuIGJvb2w7XG4gIH1cblxuXG4gIGZ1bmN0aW9uIGhlQ29tZXModGV4dCwgb3B0aW9ucykge1xuICAgIHZhciByZXN1bHQgPSAnJztcbiAgICB2YXIgY291bnRzO1xuICAgIHZhciBsO1xuICAgIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuICAgIG9wdGlvbnNbJ3VwJ10gPVxuICAgICAgdHlwZW9mIG9wdGlvbnNbJ3VwJ10gIT09ICd1bmRlZmluZWQnID8gb3B0aW9uc1sndXAnXSA6IHRydWU7XG4gICAgb3B0aW9uc1snbWlkJ10gPVxuICAgICAgdHlwZW9mIG9wdGlvbnNbJ21pZCddICE9PSAndW5kZWZpbmVkJyA/IG9wdGlvbnNbJ21pZCddIDogdHJ1ZTtcbiAgICBvcHRpb25zWydkb3duJ10gPVxuICAgICAgdHlwZW9mIG9wdGlvbnNbJ2Rvd24nXSAhPT0gJ3VuZGVmaW5lZCcgPyBvcHRpb25zWydkb3duJ10gOiB0cnVlO1xuICAgIG9wdGlvbnNbJ3NpemUnXSA9XG4gICAgICB0eXBlb2Ygb3B0aW9uc1snc2l6ZSddICE9PSAndW5kZWZpbmVkJyA/IG9wdGlvbnNbJ3NpemUnXSA6ICdtYXhpJztcbiAgICB0ZXh0ID0gdGV4dC5zcGxpdCgnJyk7XG4gICAgZm9yIChsIGluIHRleHQpIHtcbiAgICAgIGlmIChpc0NoYXIobCkpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICByZXN1bHQgPSByZXN1bHQgKyB0ZXh0W2xdO1xuICAgICAgY291bnRzID0geyd1cCc6IDAsICdkb3duJzogMCwgJ21pZCc6IDB9O1xuICAgICAgc3dpdGNoIChvcHRpb25zLnNpemUpIHtcbiAgICAgICAgY2FzZSAnbWluaSc6XG4gICAgICAgICAgY291bnRzLnVwID0gcmFuZG9tTnVtYmVyKDgpO1xuICAgICAgICAgIGNvdW50cy5taWQgPSByYW5kb21OdW1iZXIoMik7XG4gICAgICAgICAgY291bnRzLmRvd24gPSByYW5kb21OdW1iZXIoOCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ21heGknOlxuICAgICAgICAgIGNvdW50cy51cCA9IHJhbmRvbU51bWJlcigxNikgKyAzO1xuICAgICAgICAgIGNvdW50cy5taWQgPSByYW5kb21OdW1iZXIoNCkgKyAxO1xuICAgICAgICAgIGNvdW50cy5kb3duID0gcmFuZG9tTnVtYmVyKDY0KSArIDM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgY291bnRzLnVwID0gcmFuZG9tTnVtYmVyKDgpICsgMTtcbiAgICAgICAgICBjb3VudHMubWlkID0gcmFuZG9tTnVtYmVyKDYpIC8gMjtcbiAgICAgICAgICBjb3VudHMuZG93biA9IHJhbmRvbU51bWJlcig4KSArIDE7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIHZhciBhcnIgPSBbJ3VwJywgJ21pZCcsICdkb3duJ107XG4gICAgICBmb3IgKHZhciBkIGluIGFycikge1xuICAgICAgICB2YXIgaW5kZXggPSBhcnJbZF07XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDw9IGNvdW50c1tpbmRleF07IGkrKykge1xuICAgICAgICAgIGlmIChvcHRpb25zW2luZGV4XSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0ICsgc291bFtpbmRleF1bcmFuZG9tTnVtYmVyKHNvdWxbaW5kZXhdLmxlbmd0aCldO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIC8vIGRvbid0IHN1bW1vbiBoaW1cbiAgcmV0dXJuIGhlQ29tZXModGV4dCwgb3B0aW9ucyk7XG59O1xuXG4iLCJtb2R1bGVbJ2V4cG9ydHMnXSA9IGZ1bmN0aW9uKGNvbG9ycykge1xuICByZXR1cm4gZnVuY3Rpb24obGV0dGVyLCBpLCBleHBsb2RlZCkge1xuICAgIGlmIChsZXR0ZXIgPT09ICcgJykgcmV0dXJuIGxldHRlcjtcbiAgICBzd2l0Y2ggKGklMykge1xuICAgICAgY2FzZSAwOiByZXR1cm4gY29sb3JzLnJlZChsZXR0ZXIpO1xuICAgICAgY2FzZSAxOiByZXR1cm4gY29sb3JzLndoaXRlKGxldHRlcik7XG4gICAgICBjYXNlIDI6IHJldHVybiBjb2xvcnMuYmx1ZShsZXR0ZXIpO1xuICAgIH1cbiAgfTtcbn07XG4iLCJtb2R1bGVbJ2V4cG9ydHMnXSA9IGZ1bmN0aW9uKGNvbG9ycykge1xuICByZXR1cm4gZnVuY3Rpb24obGV0dGVyLCBpLCBleHBsb2RlZCkge1xuICAgIHJldHVybiBpICUgMiA9PT0gMCA/IGxldHRlciA6IGNvbG9ycy5pbnZlcnNlKGxldHRlcik7XG4gIH07XG59O1xuIiwibW9kdWxlWydleHBvcnRzJ10gPSBmdW5jdGlvbihjb2xvcnMpIHtcbiAgLy8gUm9ZIEcgQmlWXG4gIHZhciByYWluYm93Q29sb3JzID0gWydyZWQnLCAneWVsbG93JywgJ2dyZWVuJywgJ2JsdWUnLCAnbWFnZW50YSddO1xuICByZXR1cm4gZnVuY3Rpb24obGV0dGVyLCBpLCBleHBsb2RlZCkge1xuICAgIGlmIChsZXR0ZXIgPT09ICcgJykge1xuICAgICAgcmV0dXJuIGxldHRlcjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGNvbG9yc1tyYWluYm93Q29sb3JzW2krKyAlIHJhaW5ib3dDb2xvcnMubGVuZ3RoXV0obGV0dGVyKTtcbiAgICB9XG4gIH07XG59O1xuXG4iLCJtb2R1bGVbJ2V4cG9ydHMnXSA9IGZ1bmN0aW9uKGNvbG9ycykge1xuICB2YXIgYXZhaWxhYmxlID0gWyd1bmRlcmxpbmUnLCAnaW52ZXJzZScsICdncmV5JywgJ3llbGxvdycsICdyZWQnLCAnZ3JlZW4nLFxuICAgICdibHVlJywgJ3doaXRlJywgJ2N5YW4nLCAnbWFnZW50YScsICdicmlnaHRZZWxsb3cnLCAnYnJpZ2h0UmVkJyxcbiAgICAnYnJpZ2h0R3JlZW4nLCAnYnJpZ2h0Qmx1ZScsICdicmlnaHRXaGl0ZScsICdicmlnaHRDeWFuJywgJ2JyaWdodE1hZ2VudGEnXTtcbiAgcmV0dXJuIGZ1bmN0aW9uKGxldHRlciwgaSwgZXhwbG9kZWQpIHtcbiAgICByZXR1cm4gbGV0dGVyID09PSAnICcgPyBsZXR0ZXIgOlxuICAgICAgY29sb3JzW1xuICAgICAgICAgIGF2YWlsYWJsZVtNYXRoLnJvdW5kKE1hdGgucmFuZG9tKCkgKiAoYXZhaWxhYmxlLmxlbmd0aCAtIDIpKV1cbiAgICAgIF0obGV0dGVyKTtcbiAgfTtcbn07XG4iLCIvKlxuXG5UaGUgTUlUIExpY2Vuc2UgKE1JVClcblxuT3JpZ2luYWwgTGlicmFyeVxuICAtIENvcHlyaWdodCAoYykgTWFyYWsgU3F1aXJlc1xuXG5BZGRpdGlvbmFsIGZ1bmN0aW9uYWxpdHlcbiAtIENvcHlyaWdodCAoYykgU2luZHJlIFNvcmh1cyA8c2luZHJlc29yaHVzQGdtYWlsLmNvbT4gKHNpbmRyZXNvcmh1cy5jb20pXG5cblBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhIGNvcHlcbm9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcbmluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHNcbnRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGxcbmNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xuZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmcgY29uZGl0aW9uczpcblxuVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWQgaW5cbmFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG5JTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbkZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbk9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU5cblRIRSBTT0ZUV0FSRS5cblxuKi9cblxudmFyIGNvbG9ycyA9IHt9O1xubW9kdWxlWydleHBvcnRzJ10gPSBjb2xvcnM7XG5cbmNvbG9ycy50aGVtZXMgPSB7fTtcblxudmFyIHV0aWwgPSByZXF1aXJlKCd1dGlsJyk7XG52YXIgYW5zaVN0eWxlcyA9IGNvbG9ycy5zdHlsZXMgPSByZXF1aXJlKCcuL3N0eWxlcycpO1xudmFyIGRlZmluZVByb3BzID0gT2JqZWN0LmRlZmluZVByb3BlcnRpZXM7XG52YXIgbmV3TGluZVJlZ2V4ID0gbmV3IFJlZ0V4cCgvW1xcclxcbl0rL2cpO1xuXG5jb2xvcnMuc3VwcG9ydHNDb2xvciA9IHJlcXVpcmUoJy4vc3lzdGVtL3N1cHBvcnRzLWNvbG9ycycpLnN1cHBvcnRzQ29sb3I7XG5cbmlmICh0eXBlb2YgY29sb3JzLmVuYWJsZWQgPT09ICd1bmRlZmluZWQnKSB7XG4gIGNvbG9ycy5lbmFibGVkID0gY29sb3JzLnN1cHBvcnRzQ29sb3IoKSAhPT0gZmFsc2U7XG59XG5cbmNvbG9ycy5lbmFibGUgPSBmdW5jdGlvbigpIHtcbiAgY29sb3JzLmVuYWJsZWQgPSB0cnVlO1xufTtcblxuY29sb3JzLmRpc2FibGUgPSBmdW5jdGlvbigpIHtcbiAgY29sb3JzLmVuYWJsZWQgPSBmYWxzZTtcbn07XG5cbmNvbG9ycy5zdHJpcENvbG9ycyA9IGNvbG9ycy5zdHJpcCA9IGZ1bmN0aW9uKHN0cikge1xuICByZXR1cm4gKCcnICsgc3RyKS5yZXBsYWNlKC9cXHgxQlxcW1xcZCttL2csICcnKTtcbn07XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bnVzZWQtdmFyc1xudmFyIHN0eWxpemUgPSBjb2xvcnMuc3R5bGl6ZSA9IGZ1bmN0aW9uIHN0eWxpemUoc3RyLCBzdHlsZSkge1xuICBpZiAoIWNvbG9ycy5lbmFibGVkKSB7XG4gICAgcmV0dXJuIHN0cisnJztcbiAgfVxuXG4gIHZhciBzdHlsZU1hcCA9IGFuc2lTdHlsZXNbc3R5bGVdO1xuXG4gIC8vIFN0eWxpemUgc2hvdWxkIHdvcmsgZm9yIG5vbi1BTlNJIHN0eWxlcywgdG9vXG4gIGlmKCFzdHlsZU1hcCAmJiBzdHlsZSBpbiBjb2xvcnMpe1xuICAgIC8vIFN0eWxlIG1hcHMgbGlrZSB0cmFwIG9wZXJhdGUgYXMgZnVuY3Rpb25zIG9uIHN0cmluZ3M7XG4gICAgLy8gdGhleSBkb24ndCBoYXZlIHByb3BlcnRpZXMgbGlrZSBvcGVuIG9yIGNsb3NlLlxuICAgIHJldHVybiBjb2xvcnNbc3R5bGVdKHN0cik7XG4gIH1cblxuICByZXR1cm4gc3R5bGVNYXAub3BlbiArIHN0ciArIHN0eWxlTWFwLmNsb3NlO1xufTtcblxudmFyIG1hdGNoT3BlcmF0b3JzUmUgPSAvW3xcXFxce30oKVtcXF1eJCsqPy5dL2c7XG52YXIgZXNjYXBlU3RyaW5nUmVnZXhwID0gZnVuY3Rpb24oc3RyKSB7XG4gIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0V4cGVjdGVkIGEgc3RyaW5nJyk7XG4gIH1cbiAgcmV0dXJuIHN0ci5yZXBsYWNlKG1hdGNoT3BlcmF0b3JzUmUsICdcXFxcJCYnKTtcbn07XG5cbmZ1bmN0aW9uIGJ1aWxkKF9zdHlsZXMpIHtcbiAgdmFyIGJ1aWxkZXIgPSBmdW5jdGlvbiBidWlsZGVyKCkge1xuICAgIHJldHVybiBhcHBseVN0eWxlLmFwcGx5KGJ1aWxkZXIsIGFyZ3VtZW50cyk7XG4gIH07XG4gIGJ1aWxkZXIuX3N0eWxlcyA9IF9zdHlsZXM7XG4gIC8vIF9fcHJvdG9fXyBpcyB1c2VkIGJlY2F1c2Ugd2UgbXVzdCByZXR1cm4gYSBmdW5jdGlvbiwgYnV0IHRoZXJlIGlzXG4gIC8vIG5vIHdheSB0byBjcmVhdGUgYSBmdW5jdGlvbiB3aXRoIGEgZGlmZmVyZW50IHByb3RvdHlwZS5cbiAgYnVpbGRlci5fX3Byb3RvX18gPSBwcm90bztcbiAgcmV0dXJuIGJ1aWxkZXI7XG59XG5cbnZhciBzdHlsZXMgPSAoZnVuY3Rpb24oKSB7XG4gIHZhciByZXQgPSB7fTtcbiAgYW5zaVN0eWxlcy5ncmV5ID0gYW5zaVN0eWxlcy5ncmF5O1xuICBPYmplY3Qua2V5cyhhbnNpU3R5bGVzKS5mb3JFYWNoKGZ1bmN0aW9uKGtleSkge1xuICAgIGFuc2lTdHlsZXNba2V5XS5jbG9zZVJlID1cbiAgICAgIG5ldyBSZWdFeHAoZXNjYXBlU3RyaW5nUmVnZXhwKGFuc2lTdHlsZXNba2V5XS5jbG9zZSksICdnJyk7XG4gICAgcmV0W2tleV0gPSB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gYnVpbGQodGhpcy5fc3R5bGVzLmNvbmNhdChrZXkpKTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfSk7XG4gIHJldHVybiByZXQ7XG59KSgpO1xuXG52YXIgcHJvdG8gPSBkZWZpbmVQcm9wcyhmdW5jdGlvbiBjb2xvcnMoKSB7fSwgc3R5bGVzKTtcblxuZnVuY3Rpb24gYXBwbHlTdHlsZSgpIHtcbiAgdmFyIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXG4gIHZhciBzdHIgPSBhcmdzLm1hcChmdW5jdGlvbihhcmcpIHtcbiAgICAvLyBVc2Ugd2VhayBlcXVhbGl0eSBjaGVjayBzbyB3ZSBjYW4gY29sb3JpemUgbnVsbC91bmRlZmluZWQgaW4gc2FmZSBtb2RlXG4gICAgaWYgKGFyZyAhPSBudWxsICYmIGFyZy5jb25zdHJ1Y3RvciA9PT0gU3RyaW5nKSB7XG4gICAgICByZXR1cm4gYXJnO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdXRpbC5pbnNwZWN0KGFyZyk7XG4gICAgfVxuICB9KS5qb2luKCcgJyk7XG5cbiAgaWYgKCFjb2xvcnMuZW5hYmxlZCB8fCAhc3RyKSB7XG4gICAgcmV0dXJuIHN0cjtcbiAgfVxuXG4gIHZhciBuZXdMaW5lc1ByZXNlbnQgPSBzdHIuaW5kZXhPZignXFxuJykgIT0gLTE7XG5cbiAgdmFyIG5lc3RlZFN0eWxlcyA9IHRoaXMuX3N0eWxlcztcblxuICB2YXIgaSA9IG5lc3RlZFN0eWxlcy5sZW5ndGg7XG4gIHdoaWxlIChpLS0pIHtcbiAgICB2YXIgY29kZSA9IGFuc2lTdHlsZXNbbmVzdGVkU3R5bGVzW2ldXTtcbiAgICBzdHIgPSBjb2RlLm9wZW4gKyBzdHIucmVwbGFjZShjb2RlLmNsb3NlUmUsIGNvZGUub3BlbikgKyBjb2RlLmNsb3NlO1xuICAgIGlmIChuZXdMaW5lc1ByZXNlbnQpIHtcbiAgICAgIHN0ciA9IHN0ci5yZXBsYWNlKG5ld0xpbmVSZWdleCwgZnVuY3Rpb24obWF0Y2gpIHtcbiAgICAgICAgcmV0dXJuIGNvZGUuY2xvc2UgKyBtYXRjaCArIGNvZGUub3BlbjtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzdHI7XG59XG5cbmNvbG9ycy5zZXRUaGVtZSA9IGZ1bmN0aW9uKHRoZW1lKSB7XG4gIGlmICh0eXBlb2YgdGhlbWUgPT09ICdzdHJpbmcnKSB7XG4gICAgY29uc29sZS5sb2coJ2NvbG9ycy5zZXRUaGVtZSBub3cgb25seSBhY2NlcHRzIGFuIG9iamVjdCwgbm90IGEgc3RyaW5nLiAgJyArXG4gICAgICAnSWYgeW91IGFyZSB0cnlpbmcgdG8gc2V0IGEgdGhlbWUgZnJvbSBhIGZpbGUsIGl0IGlzIG5vdyB5b3VyICh0aGUgJyArXG4gICAgICAnY2FsbGVyXFwncykgcmVzcG9uc2liaWxpdHkgdG8gcmVxdWlyZSB0aGUgZmlsZS4gIFRoZSBvbGQgc3ludGF4ICcgK1xuICAgICAgJ2xvb2tlZCBsaWtlIGNvbG9ycy5zZXRUaGVtZShfX2Rpcm5hbWUgKyAnICtcbiAgICAgICdcXCcvLi4vdGhlbWVzL2dlbmVyaWMtbG9nZ2luZy5qc1xcJyk7IFRoZSBuZXcgc3ludGF4IGxvb2tzIGxpa2UgJytcbiAgICAgICdjb2xvcnMuc2V0VGhlbWUocmVxdWlyZShfX2Rpcm5hbWUgKyAnICtcbiAgICAgICdcXCcvLi4vdGhlbWVzL2dlbmVyaWMtbG9nZ2luZy5qc1xcJykpOycpO1xuICAgIHJldHVybjtcbiAgfVxuICBmb3IgKHZhciBzdHlsZSBpbiB0aGVtZSkge1xuICAgIChmdW5jdGlvbihzdHlsZSkge1xuICAgICAgY29sb3JzW3N0eWxlXSA9IGZ1bmN0aW9uKHN0cikge1xuICAgICAgICBpZiAodHlwZW9mIHRoZW1lW3N0eWxlXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICB2YXIgb3V0ID0gc3RyO1xuICAgICAgICAgIGZvciAodmFyIGkgaW4gdGhlbWVbc3R5bGVdKSB7XG4gICAgICAgICAgICBvdXQgPSBjb2xvcnNbdGhlbWVbc3R5bGVdW2ldXShvdXQpO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gb3V0O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb2xvcnNbdGhlbWVbc3R5bGVdXShzdHIpO1xuICAgICAgfTtcbiAgICB9KShzdHlsZSk7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGluaXQoKSB7XG4gIHZhciByZXQgPSB7fTtcbiAgT2JqZWN0LmtleXMoc3R5bGVzKS5mb3JFYWNoKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICByZXRbbmFtZV0gPSB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gYnVpbGQoW25hbWVdKTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfSk7XG4gIHJldHVybiByZXQ7XG59XG5cbnZhciBzZXF1ZW5jZXIgPSBmdW5jdGlvbiBzZXF1ZW5jZXIobWFwLCBzdHIpIHtcbiAgdmFyIGV4cGxvZGVkID0gc3RyLnNwbGl0KCcnKTtcbiAgZXhwbG9kZWQgPSBleHBsb2RlZC5tYXAobWFwKTtcbiAgcmV0dXJuIGV4cGxvZGVkLmpvaW4oJycpO1xufTtcblxuLy8gY3VzdG9tIGZvcm1hdHRlciBtZXRob2RzXG5jb2xvcnMudHJhcCA9IHJlcXVpcmUoJy4vY3VzdG9tL3RyYXAnKTtcbmNvbG9ycy56YWxnbyA9IHJlcXVpcmUoJy4vY3VzdG9tL3phbGdvJyk7XG5cbi8vIG1hcHNcbmNvbG9ycy5tYXBzID0ge307XG5jb2xvcnMubWFwcy5hbWVyaWNhID0gcmVxdWlyZSgnLi9tYXBzL2FtZXJpY2EnKShjb2xvcnMpO1xuY29sb3JzLm1hcHMuemVicmEgPSByZXF1aXJlKCcuL21hcHMvemVicmEnKShjb2xvcnMpO1xuY29sb3JzLm1hcHMucmFpbmJvdyA9IHJlcXVpcmUoJy4vbWFwcy9yYWluYm93JykoY29sb3JzKTtcbmNvbG9ycy5tYXBzLnJhbmRvbSA9IHJlcXVpcmUoJy4vbWFwcy9yYW5kb20nKShjb2xvcnMpO1xuXG5mb3IgKHZhciBtYXAgaW4gY29sb3JzLm1hcHMpIHtcbiAgKGZ1bmN0aW9uKG1hcCkge1xuICAgIGNvbG9yc1ttYXBdID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgICByZXR1cm4gc2VxdWVuY2VyKGNvbG9ycy5tYXBzW21hcF0sIHN0cik7XG4gICAgfTtcbiAgfSkobWFwKTtcbn1cblxuZGVmaW5lUHJvcHMoY29sb3JzLCBpbml0KCkpO1xuIiwidmFyIGNvbG9ycyA9IHJlcXVpcmUoJy4vY29sb3JzJyk7XG5cbm1vZHVsZVsnZXhwb3J0cyddID0gZnVuY3Rpb24oKSB7XG4gIC8vXG4gIC8vIEV4dGVuZHMgcHJvdG90eXBlIG9mIG5hdGl2ZSBzdHJpbmcgb2JqZWN0IHRvIGFsbG93IGZvciBcImZvb1wiLnJlZCBzeW50YXhcbiAgLy9cbiAgdmFyIGFkZFByb3BlcnR5ID0gZnVuY3Rpb24oY29sb3IsIGZ1bmMpIHtcbiAgICBTdHJpbmcucHJvdG90eXBlLl9fZGVmaW5lR2V0dGVyX18oY29sb3IsIGZ1bmMpO1xuICB9O1xuXG4gIGFkZFByb3BlcnR5KCdzdHJpcCcsIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBjb2xvcnMuc3RyaXAodGhpcyk7XG4gIH0pO1xuXG4gIGFkZFByb3BlcnR5KCdzdHJpcENvbG9ycycsIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBjb2xvcnMuc3RyaXAodGhpcyk7XG4gIH0pO1xuXG4gIGFkZFByb3BlcnR5KCd0cmFwJywgZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIGNvbG9ycy50cmFwKHRoaXMpO1xuICB9KTtcblxuICBhZGRQcm9wZXJ0eSgnemFsZ28nLCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gY29sb3JzLnphbGdvKHRoaXMpO1xuICB9KTtcblxuICBhZGRQcm9wZXJ0eSgnemVicmEnLCBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gY29sb3JzLnplYnJhKHRoaXMpO1xuICB9KTtcblxuICBhZGRQcm9wZXJ0eSgncmFpbmJvdycsIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBjb2xvcnMucmFpbmJvdyh0aGlzKTtcbiAgfSk7XG5cbiAgYWRkUHJvcGVydHkoJ3JhbmRvbScsIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBjb2xvcnMucmFuZG9tKHRoaXMpO1xuICB9KTtcblxuICBhZGRQcm9wZXJ0eSgnYW1lcmljYScsIGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBjb2xvcnMuYW1lcmljYSh0aGlzKTtcbiAgfSk7XG5cbiAgLy9cbiAgLy8gSXRlcmF0ZSB0aHJvdWdoIGFsbCBkZWZhdWx0IHN0eWxlcyBhbmQgY29sb3JzXG4gIC8vXG4gIHZhciB4ID0gT2JqZWN0LmtleXMoY29sb3JzLnN0eWxlcyk7XG4gIHguZm9yRWFjaChmdW5jdGlvbihzdHlsZSkge1xuICAgIGFkZFByb3BlcnR5KHN0eWxlLCBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBjb2xvcnMuc3R5bGl6ZSh0aGlzLCBzdHlsZSk7XG4gICAgfSk7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIGFwcGx5VGhlbWUodGhlbWUpIHtcbiAgICAvL1xuICAgIC8vIFJlbWFyazogVGhpcyBpcyBhIGxpc3Qgb2YgbWV0aG9kcyB0aGF0IGV4aXN0XG4gICAgLy8gb24gU3RyaW5nIHRoYXQgeW91IHNob3VsZCBub3Qgb3ZlcndyaXRlLlxuICAgIC8vXG4gICAgdmFyIHN0cmluZ1Byb3RvdHlwZUJsYWNrbGlzdCA9IFtcbiAgICAgICdfX2RlZmluZUdldHRlcl9fJywgJ19fZGVmaW5lU2V0dGVyX18nLCAnX19sb29rdXBHZXR0ZXJfXycsXG4gICAgICAnX19sb29rdXBTZXR0ZXJfXycsICdjaGFyQXQnLCAnY29uc3RydWN0b3InLCAnaGFzT3duUHJvcGVydHknLFxuICAgICAgJ2lzUHJvdG90eXBlT2YnLCAncHJvcGVydHlJc0VudW1lcmFibGUnLCAndG9Mb2NhbGVTdHJpbmcnLCAndG9TdHJpbmcnLFxuICAgICAgJ3ZhbHVlT2YnLCAnY2hhckNvZGVBdCcsICdpbmRleE9mJywgJ2xhc3RJbmRleE9mJywgJ2xlbmd0aCcsXG4gICAgICAnbG9jYWxlQ29tcGFyZScsICdtYXRjaCcsICdyZXBlYXQnLCAncmVwbGFjZScsICdzZWFyY2gnLCAnc2xpY2UnLFxuICAgICAgJ3NwbGl0JywgJ3N1YnN0cmluZycsICd0b0xvY2FsZUxvd2VyQ2FzZScsICd0b0xvY2FsZVVwcGVyQ2FzZScsXG4gICAgICAndG9Mb3dlckNhc2UnLCAndG9VcHBlckNhc2UnLCAndHJpbScsICd0cmltTGVmdCcsICd0cmltUmlnaHQnLFxuICAgIF07XG5cbiAgICBPYmplY3Qua2V5cyh0aGVtZSkuZm9yRWFjaChmdW5jdGlvbihwcm9wKSB7XG4gICAgICBpZiAoc3RyaW5nUHJvdG90eXBlQmxhY2tsaXN0LmluZGV4T2YocHJvcCkgIT09IC0xKSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCd3YXJuOiAnLnJlZCArICgnU3RyaW5nLnByb3RvdHlwZScgKyBwcm9wKS5tYWdlbnRhICtcbiAgICAgICAgICAnIGlzIHByb2JhYmx5IHNvbWV0aGluZyB5b3UgZG9uXFwndCB3YW50IHRvIG92ZXJyaWRlLiAgJyArXG4gICAgICAgICAgJ0lnbm9yaW5nIHN0eWxlIG5hbWUnKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0eXBlb2YodGhlbWVbcHJvcF0pID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbG9yc1twcm9wXSA9IGNvbG9yc1t0aGVtZVtwcm9wXV07XG4gICAgICAgICAgYWRkUHJvcGVydHkocHJvcCwgZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICByZXR1cm4gY29sb3JzW3Byb3BdKHRoaXMpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHZhciB0aGVtZVByb3BBcHBsaWNhdG9yID0gZnVuY3Rpb24oc3RyKSB7XG4gICAgICAgICAgICB2YXIgcmV0ID0gc3RyIHx8IHRoaXM7XG4gICAgICAgICAgICBmb3IgKHZhciB0ID0gMDsgdCA8IHRoZW1lW3Byb3BdLmxlbmd0aDsgdCsrKSB7XG4gICAgICAgICAgICAgIHJldCA9IGNvbG9yc1t0aGVtZVtwcm9wXVt0XV0ocmV0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXQ7XG4gICAgICAgICAgfTtcbiAgICAgICAgICBhZGRQcm9wZXJ0eShwcm9wLCB0aGVtZVByb3BBcHBsaWNhdG9yKTtcbiAgICAgICAgICBjb2xvcnNbcHJvcF0gPSBmdW5jdGlvbihzdHIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGVtZVByb3BBcHBsaWNhdG9yKHN0cik7XG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICB9XG5cbiAgY29sb3JzLnNldFRoZW1lID0gZnVuY3Rpb24odGhlbWUpIHtcbiAgICBpZiAodHlwZW9mIHRoZW1lID09PSAnc3RyaW5nJykge1xuICAgICAgY29uc29sZS5sb2coJ2NvbG9ycy5zZXRUaGVtZSBub3cgb25seSBhY2NlcHRzIGFuIG9iamVjdCwgbm90IGEgc3RyaW5nLiAnICtcbiAgICAgICAgJ0lmIHlvdSBhcmUgdHJ5aW5nIHRvIHNldCBhIHRoZW1lIGZyb20gYSBmaWxlLCBpdCBpcyBub3cgeW91ciAodGhlICcgK1xuICAgICAgICAnY2FsbGVyXFwncykgcmVzcG9uc2liaWxpdHkgdG8gcmVxdWlyZSB0aGUgZmlsZS4gIFRoZSBvbGQgc3ludGF4ICcgK1xuICAgICAgICAnbG9va2VkIGxpa2UgY29sb3JzLnNldFRoZW1lKF9fZGlybmFtZSArICcgK1xuICAgICAgICAnXFwnLy4uL3RoZW1lcy9nZW5lcmljLWxvZ2dpbmcuanNcXCcpOyBUaGUgbmV3IHN5bnRheCBsb29rcyBsaWtlICcrXG4gICAgICAgICdjb2xvcnMuc2V0VGhlbWUocmVxdWlyZShfX2Rpcm5hbWUgKyAnICtcbiAgICAgICAgJ1xcJy8uLi90aGVtZXMvZ2VuZXJpYy1sb2dnaW5nLmpzXFwnKSk7Jyk7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIHtcbiAgICAgIGFwcGx5VGhlbWUodGhlbWUpO1xuICAgIH1cbiAgfTtcbn07XG4iLCJ2YXIgY29sb3JzID0gcmVxdWlyZSgnLi9jb2xvcnMnKTtcbm1vZHVsZVsnZXhwb3J0cyddID0gY29sb3JzO1xuXG4vLyBSZW1hcms6IEJ5IGRlZmF1bHQsIGNvbG9ycyB3aWxsIGFkZCBzdHlsZSBwcm9wZXJ0aWVzIHRvIFN0cmluZy5wcm90b3R5cGUuXG4vL1xuLy8gSWYgeW91IGRvbid0IHdpc2ggdG8gZXh0ZW5kIFN0cmluZy5wcm90b3R5cGUsIHlvdSBjYW4gZG8gdGhpcyBpbnN0ZWFkIGFuZFxuLy8gbmF0aXZlIFN0cmluZyB3aWxsIG5vdCBiZSB0b3VjaGVkOlxuLy9cbi8vICAgdmFyIGNvbG9ycyA9IHJlcXVpcmUoJ2NvbG9ycy9zYWZlKTtcbi8vICAgY29sb3JzLnJlZChcImZvb1wiKVxuLy9cbi8vXG5yZXF1aXJlKCcuL2V4dGVuZFN0cmluZ1Byb3RvdHlwZScpKCk7XG4iLCIvLyEgbW9tZW50LmpzXG4vLyEgdmVyc2lvbiA6IDIuMjcuMFxuLy8hIGF1dGhvcnMgOiBUaW0gV29vZCwgSXNrcmVuIENoZXJuZXYsIE1vbWVudC5qcyBjb250cmlidXRvcnNcbi8vISBsaWNlbnNlIDogTUlUXG4vLyEgbW9tZW50anMuY29tXG5cbjsoZnVuY3Rpb24gKGdsb2JhbCwgZmFjdG9yeSkge1xuICAgIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeSgpIDpcbiAgICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoZmFjdG9yeSkgOlxuICAgIGdsb2JhbC5tb21lbnQgPSBmYWN0b3J5KClcbn0odGhpcywgKGZ1bmN0aW9uICgpIHsgJ3VzZSBzdHJpY3QnO1xuXG4gICAgdmFyIGhvb2tDYWxsYmFjaztcblxuICAgIGZ1bmN0aW9uIGhvb2tzKCkge1xuICAgICAgICByZXR1cm4gaG9va0NhbGxiYWNrLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgfVxuXG4gICAgLy8gVGhpcyBpcyBkb25lIHRvIHJlZ2lzdGVyIHRoZSBtZXRob2QgY2FsbGVkIHdpdGggbW9tZW50KClcbiAgICAvLyB3aXRob3V0IGNyZWF0aW5nIGNpcmN1bGFyIGRlcGVuZGVuY2llcy5cbiAgICBmdW5jdGlvbiBzZXRIb29rQ2FsbGJhY2soY2FsbGJhY2spIHtcbiAgICAgICAgaG9va0NhbGxiYWNrID0gY2FsbGJhY2s7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNBcnJheShpbnB1dCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgaW5wdXQgaW5zdGFuY2VvZiBBcnJheSB8fFxuICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgQXJyYXldJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzT2JqZWN0KGlucHV0KSB7XG4gICAgICAgIC8vIElFOCB3aWxsIHRyZWF0IHVuZGVmaW5lZCBhbmQgbnVsbCBhcyBvYmplY3QgaWYgaXQgd2Fzbid0IGZvclxuICAgICAgICAvLyBpbnB1dCAhPSBudWxsXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICBpbnB1dCAhPSBudWxsICYmXG4gICAgICAgICAgICBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaW5wdXQpID09PSAnW29iamVjdCBPYmplY3RdJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhc093blByb3AoYSwgYikge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGEsIGIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzT2JqZWN0RW1wdHkob2JqKSB7XG4gICAgICAgIGlmIChPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcykge1xuICAgICAgICAgICAgcmV0dXJuIE9iamVjdC5nZXRPd25Qcm9wZXJ0eU5hbWVzKG9iaikubGVuZ3RoID09PSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGs7XG4gICAgICAgICAgICBmb3IgKGsgaW4gb2JqKSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc093blByb3Aob2JqLCBrKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1VuZGVmaW5lZChpbnB1dCkge1xuICAgICAgICByZXR1cm4gaW5wdXQgPT09IHZvaWQgMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc051bWJlcihpbnB1dCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgTnVtYmVyXSdcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0RhdGUoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgIGlucHV0IGluc3RhbmNlb2YgRGF0ZSB8fFxuICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgRGF0ZV0nXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFwKGFyciwgZm4pIHtcbiAgICAgICAgdmFyIHJlcyA9IFtdLFxuICAgICAgICAgICAgaTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGFyci5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgcmVzLnB1c2goZm4oYXJyW2ldLCBpKSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleHRlbmQoYSwgYikge1xuICAgICAgICBmb3IgKHZhciBpIGluIGIpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wKGIsIGkpKSB7XG4gICAgICAgICAgICAgICAgYVtpXSA9IGJbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFzT3duUHJvcChiLCAndG9TdHJpbmcnKSkge1xuICAgICAgICAgICAgYS50b1N0cmluZyA9IGIudG9TdHJpbmc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaGFzT3duUHJvcChiLCAndmFsdWVPZicpKSB7XG4gICAgICAgICAgICBhLnZhbHVlT2YgPSBiLnZhbHVlT2Y7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVVVEMoaW5wdXQsIGZvcm1hdCwgbG9jYWxlLCBzdHJpY3QpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsT3JVVEMoaW5wdXQsIGZvcm1hdCwgbG9jYWxlLCBzdHJpY3QsIHRydWUpLnV0YygpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlZmF1bHRQYXJzaW5nRmxhZ3MoKSB7XG4gICAgICAgIC8vIFdlIG5lZWQgdG8gZGVlcCBjbG9uZSB0aGlzIG9iamVjdC5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGVtcHR5OiBmYWxzZSxcbiAgICAgICAgICAgIHVudXNlZFRva2VuczogW10sXG4gICAgICAgICAgICB1bnVzZWRJbnB1dDogW10sXG4gICAgICAgICAgICBvdmVyZmxvdzogLTIsXG4gICAgICAgICAgICBjaGFyc0xlZnRPdmVyOiAwLFxuICAgICAgICAgICAgbnVsbElucHV0OiBmYWxzZSxcbiAgICAgICAgICAgIGludmFsaWRFcmE6IG51bGwsXG4gICAgICAgICAgICBpbnZhbGlkTW9udGg6IG51bGwsXG4gICAgICAgICAgICBpbnZhbGlkRm9ybWF0OiBmYWxzZSxcbiAgICAgICAgICAgIHVzZXJJbnZhbGlkYXRlZDogZmFsc2UsXG4gICAgICAgICAgICBpc286IGZhbHNlLFxuICAgICAgICAgICAgcGFyc2VkRGF0ZVBhcnRzOiBbXSxcbiAgICAgICAgICAgIGVyYTogbnVsbCxcbiAgICAgICAgICAgIG1lcmlkaWVtOiBudWxsLFxuICAgICAgICAgICAgcmZjMjgyMjogZmFsc2UsXG4gICAgICAgICAgICB3ZWVrZGF5TWlzbWF0Y2g6IGZhbHNlLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFBhcnNpbmdGbGFncyhtKSB7XG4gICAgICAgIGlmIChtLl9wZiA9PSBudWxsKSB7XG4gICAgICAgICAgICBtLl9wZiA9IGRlZmF1bHRQYXJzaW5nRmxhZ3MoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbS5fcGY7XG4gICAgfVxuXG4gICAgdmFyIHNvbWU7XG4gICAgaWYgKEFycmF5LnByb3RvdHlwZS5zb21lKSB7XG4gICAgICAgIHNvbWUgPSBBcnJheS5wcm90b3R5cGUuc29tZTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBzb21lID0gZnVuY3Rpb24gKGZ1bikge1xuICAgICAgICAgICAgdmFyIHQgPSBPYmplY3QodGhpcyksXG4gICAgICAgICAgICAgICAgbGVuID0gdC5sZW5ndGggPj4+IDAsXG4gICAgICAgICAgICAgICAgaTtcblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGkgaW4gdCAmJiBmdW4uY2FsbCh0aGlzLCB0W2ldLCBpLCB0KSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc1ZhbGlkKG0pIHtcbiAgICAgICAgaWYgKG0uX2lzVmFsaWQgPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGZsYWdzID0gZ2V0UGFyc2luZ0ZsYWdzKG0pLFxuICAgICAgICAgICAgICAgIHBhcnNlZFBhcnRzID0gc29tZS5jYWxsKGZsYWdzLnBhcnNlZERhdGVQYXJ0cywgZnVuY3Rpb24gKGkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGkgIT0gbnVsbDtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICBpc05vd1ZhbGlkID1cbiAgICAgICAgICAgICAgICAgICAgIWlzTmFOKG0uX2QuZ2V0VGltZSgpKSAmJlxuICAgICAgICAgICAgICAgICAgICBmbGFncy5vdmVyZmxvdyA8IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgIWZsYWdzLmVtcHR5ICYmXG4gICAgICAgICAgICAgICAgICAgICFmbGFncy5pbnZhbGlkRXJhICYmXG4gICAgICAgICAgICAgICAgICAgICFmbGFncy5pbnZhbGlkTW9udGggJiZcbiAgICAgICAgICAgICAgICAgICAgIWZsYWdzLmludmFsaWRXZWVrZGF5ICYmXG4gICAgICAgICAgICAgICAgICAgICFmbGFncy53ZWVrZGF5TWlzbWF0Y2ggJiZcbiAgICAgICAgICAgICAgICAgICAgIWZsYWdzLm51bGxJbnB1dCAmJlxuICAgICAgICAgICAgICAgICAgICAhZmxhZ3MuaW52YWxpZEZvcm1hdCAmJlxuICAgICAgICAgICAgICAgICAgICAhZmxhZ3MudXNlckludmFsaWRhdGVkICYmXG4gICAgICAgICAgICAgICAgICAgICghZmxhZ3MubWVyaWRpZW0gfHwgKGZsYWdzLm1lcmlkaWVtICYmIHBhcnNlZFBhcnRzKSk7XG5cbiAgICAgICAgICAgIGlmIChtLl9zdHJpY3QpIHtcbiAgICAgICAgICAgICAgICBpc05vd1ZhbGlkID1cbiAgICAgICAgICAgICAgICAgICAgaXNOb3dWYWxpZCAmJlxuICAgICAgICAgICAgICAgICAgICBmbGFncy5jaGFyc0xlZnRPdmVyID09PSAwICYmXG4gICAgICAgICAgICAgICAgICAgIGZsYWdzLnVudXNlZFRva2Vucy5sZW5ndGggPT09IDAgJiZcbiAgICAgICAgICAgICAgICAgICAgZmxhZ3MuYmlnSG91ciA9PT0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoT2JqZWN0LmlzRnJvemVuID09IG51bGwgfHwgIU9iamVjdC5pc0Zyb3plbihtKSkge1xuICAgICAgICAgICAgICAgIG0uX2lzVmFsaWQgPSBpc05vd1ZhbGlkO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaXNOb3dWYWxpZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbS5faXNWYWxpZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVJbnZhbGlkKGZsYWdzKSB7XG4gICAgICAgIHZhciBtID0gY3JlYXRlVVRDKE5hTik7XG4gICAgICAgIGlmIChmbGFncyAhPSBudWxsKSB7XG4gICAgICAgICAgICBleHRlbmQoZ2V0UGFyc2luZ0ZsYWdzKG0pLCBmbGFncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MobSkudXNlckludmFsaWRhdGVkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBtO1xuICAgIH1cblxuICAgIC8vIFBsdWdpbnMgdGhhdCBhZGQgcHJvcGVydGllcyBzaG91bGQgYWxzbyBhZGQgdGhlIGtleSBoZXJlIChudWxsIHZhbHVlKSxcbiAgICAvLyBzbyB3ZSBjYW4gcHJvcGVybHkgY2xvbmUgb3Vyc2VsdmVzLlxuICAgIHZhciBtb21lbnRQcm9wZXJ0aWVzID0gKGhvb2tzLm1vbWVudFByb3BlcnRpZXMgPSBbXSksXG4gICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSBmYWxzZTtcblxuICAgIGZ1bmN0aW9uIGNvcHlDb25maWcodG8sIGZyb20pIHtcbiAgICAgICAgdmFyIGksIHByb3AsIHZhbDtcblxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2lzQU1vbWVudE9iamVjdCkpIHtcbiAgICAgICAgICAgIHRvLl9pc0FNb21lbnRPYmplY3QgPSBmcm9tLl9pc0FNb21lbnRPYmplY3Q7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9pKSkge1xuICAgICAgICAgICAgdG8uX2kgPSBmcm9tLl9pO1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fZikpIHtcbiAgICAgICAgICAgIHRvLl9mID0gZnJvbS5fZjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2wpKSB7XG4gICAgICAgICAgICB0by5fbCA9IGZyb20uX2w7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9zdHJpY3QpKSB7XG4gICAgICAgICAgICB0by5fc3RyaWN0ID0gZnJvbS5fc3RyaWN0O1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fdHptKSkge1xuICAgICAgICAgICAgdG8uX3R6bSA9IGZyb20uX3R6bTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzVW5kZWZpbmVkKGZyb20uX2lzVVRDKSkge1xuICAgICAgICAgICAgdG8uX2lzVVRDID0gZnJvbS5faXNVVEM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9vZmZzZXQpKSB7XG4gICAgICAgICAgICB0by5fb2Zmc2V0ID0gZnJvbS5fb2Zmc2V0O1xuICAgICAgICB9XG4gICAgICAgIGlmICghaXNVbmRlZmluZWQoZnJvbS5fcGYpKSB7XG4gICAgICAgICAgICB0by5fcGYgPSBnZXRQYXJzaW5nRmxhZ3MoZnJvbSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZChmcm9tLl9sb2NhbGUpKSB7XG4gICAgICAgICAgICB0by5fbG9jYWxlID0gZnJvbS5fbG9jYWxlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG1vbWVudFByb3BlcnRpZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IG1vbWVudFByb3BlcnRpZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBwcm9wID0gbW9tZW50UHJvcGVydGllc1tpXTtcbiAgICAgICAgICAgICAgICB2YWwgPSBmcm9tW3Byb3BdO1xuICAgICAgICAgICAgICAgIGlmICghaXNVbmRlZmluZWQodmFsKSkge1xuICAgICAgICAgICAgICAgICAgICB0b1twcm9wXSA9IHZhbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdG87XG4gICAgfVxuXG4gICAgLy8gTW9tZW50IHByb3RvdHlwZSBvYmplY3RcbiAgICBmdW5jdGlvbiBNb21lbnQoY29uZmlnKSB7XG4gICAgICAgIGNvcHlDb25maWcodGhpcywgY29uZmlnKTtcbiAgICAgICAgdGhpcy5fZCA9IG5ldyBEYXRlKGNvbmZpZy5fZCAhPSBudWxsID8gY29uZmlnLl9kLmdldFRpbWUoKSA6IE5hTik7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuX2QgPSBuZXcgRGF0ZShOYU4pO1xuICAgICAgICB9XG4gICAgICAgIC8vIFByZXZlbnQgaW5maW5pdGUgbG9vcCBpbiBjYXNlIHVwZGF0ZU9mZnNldCBjcmVhdGVzIG5ldyBtb21lbnRcbiAgICAgICAgLy8gb2JqZWN0cy5cbiAgICAgICAgaWYgKHVwZGF0ZUluUHJvZ3Jlc3MgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICB1cGRhdGVJblByb2dyZXNzID0gdHJ1ZTtcbiAgICAgICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzKTtcbiAgICAgICAgICAgIHVwZGF0ZUluUHJvZ3Jlc3MgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzTW9tZW50KG9iaikge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgb2JqIGluc3RhbmNlb2YgTW9tZW50IHx8IChvYmogIT0gbnVsbCAmJiBvYmouX2lzQU1vbWVudE9iamVjdCAhPSBudWxsKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHdhcm4obXNnKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIGhvb2tzLnN1cHByZXNzRGVwcmVjYXRpb25XYXJuaW5ncyA9PT0gZmFsc2UgJiZcbiAgICAgICAgICAgIHR5cGVvZiBjb25zb2xlICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgY29uc29sZS53YXJuXG4gICAgICAgICkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKCdEZXByZWNhdGlvbiB3YXJuaW5nOiAnICsgbXNnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlcHJlY2F0ZShtc2csIGZuKSB7XG4gICAgICAgIHZhciBmaXJzdFRpbWUgPSB0cnVlO1xuXG4gICAgICAgIHJldHVybiBleHRlbmQoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaG9va3MuZGVwcmVjYXRpb25IYW5kbGVyKG51bGwsIG1zZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZmlyc3RUaW1lKSB7XG4gICAgICAgICAgICAgICAgdmFyIGFyZ3MgPSBbXSxcbiAgICAgICAgICAgICAgICAgICAgYXJnLFxuICAgICAgICAgICAgICAgICAgICBpLFxuICAgICAgICAgICAgICAgICAgICBrZXk7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBhcmcgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBhcmd1bWVudHNbaV0gPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhcmcgKz0gJ1xcblsnICsgaSArICddICc7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGtleSBpbiBhcmd1bWVudHNbMF0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaGFzT3duUHJvcChhcmd1bWVudHNbMF0sIGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXJnICs9IGtleSArICc6ICcgKyBhcmd1bWVudHNbMF1ba2V5XSArICcsICc7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJnLnNsaWNlKDAsIC0yKTsgLy8gUmVtb3ZlIHRyYWlsaW5nIGNvbW1hIGFuZCBzcGFjZVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXJnID0gYXJndW1lbnRzW2ldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGFyZ3MucHVzaChhcmcpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB3YXJuKFxuICAgICAgICAgICAgICAgICAgICBtc2cgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ1xcbkFyZ3VtZW50czogJyArXG4gICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmdzKS5qb2luKCcnKSArXG4gICAgICAgICAgICAgICAgICAgICAgICAnXFxuJyArXG4gICAgICAgICAgICAgICAgICAgICAgICBuZXcgRXJyb3IoKS5zdGFja1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgZmlyc3RUaW1lID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgICAgfSwgZm4pO1xuICAgIH1cblxuICAgIHZhciBkZXByZWNhdGlvbnMgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGRlcHJlY2F0ZVNpbXBsZShuYW1lLCBtc2cpIHtcbiAgICAgICAgaWYgKGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciAhPSBudWxsKSB7XG4gICAgICAgICAgICBob29rcy5kZXByZWNhdGlvbkhhbmRsZXIobmFtZSwgbXNnKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWRlcHJlY2F0aW9uc1tuYW1lXSkge1xuICAgICAgICAgICAgd2Fybihtc2cpO1xuICAgICAgICAgICAgZGVwcmVjYXRpb25zW25hbWVdID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGhvb2tzLnN1cHByZXNzRGVwcmVjYXRpb25XYXJuaW5ncyA9IGZhbHNlO1xuICAgIGhvb2tzLmRlcHJlY2F0aW9uSGFuZGxlciA9IG51bGw7XG5cbiAgICBmdW5jdGlvbiBpc0Z1bmN0aW9uKGlucHV0KSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAodHlwZW9mIEZ1bmN0aW9uICE9PSAndW5kZWZpbmVkJyAmJiBpbnB1dCBpbnN0YW5jZW9mIEZ1bmN0aW9uKSB8fFxuICAgICAgICAgICAgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgRnVuY3Rpb25dJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldChjb25maWcpIHtcbiAgICAgICAgdmFyIHByb3AsIGk7XG4gICAgICAgIGZvciAoaSBpbiBjb25maWcpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wKGNvbmZpZywgaSkpIHtcbiAgICAgICAgICAgICAgICBwcm9wID0gY29uZmlnW2ldO1xuICAgICAgICAgICAgICAgIGlmIChpc0Z1bmN0aW9uKHByb3ApKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXNbaV0gPSBwcm9wO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXNbJ18nICsgaV0gPSBwcm9wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9jb25maWcgPSBjb25maWc7XG4gICAgICAgIC8vIExlbmllbnQgb3JkaW5hbCBwYXJzaW5nIGFjY2VwdHMganVzdCBhIG51bWJlciBpbiBhZGRpdGlvbiB0b1xuICAgICAgICAvLyBudW1iZXIgKyAocG9zc2libHkpIHN0dWZmIGNvbWluZyBmcm9tIF9kYXlPZk1vbnRoT3JkaW5hbFBhcnNlLlxuICAgICAgICAvLyBUT0RPOiBSZW1vdmUgXCJvcmRpbmFsUGFyc2VcIiBmYWxsYmFjayBpbiBuZXh0IG1ham9yIHJlbGVhc2UuXG4gICAgICAgIHRoaXMuX2RheU9mTW9udGhPcmRpbmFsUGFyc2VMZW5pZW50ID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICh0aGlzLl9kYXlPZk1vbnRoT3JkaW5hbFBhcnNlLnNvdXJjZSB8fCB0aGlzLl9vcmRpbmFsUGFyc2Uuc291cmNlKSArXG4gICAgICAgICAgICAgICAgJ3wnICtcbiAgICAgICAgICAgICAgICAvXFxkezEsMn0vLnNvdXJjZVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmdlQ29uZmlncyhwYXJlbnRDb25maWcsIGNoaWxkQ29uZmlnKSB7XG4gICAgICAgIHZhciByZXMgPSBleHRlbmQoe30sIHBhcmVudENvbmZpZyksXG4gICAgICAgICAgICBwcm9wO1xuICAgICAgICBmb3IgKHByb3AgaW4gY2hpbGRDb25maWcpIHtcbiAgICAgICAgICAgIGlmIChoYXNPd25Qcm9wKGNoaWxkQ29uZmlnLCBwcm9wKSkge1xuICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChwYXJlbnRDb25maWdbcHJvcF0pICYmIGlzT2JqZWN0KGNoaWxkQ29uZmlnW3Byb3BdKSkge1xuICAgICAgICAgICAgICAgICAgICByZXNbcHJvcF0gPSB7fTtcbiAgICAgICAgICAgICAgICAgICAgZXh0ZW5kKHJlc1twcm9wXSwgcGFyZW50Q29uZmlnW3Byb3BdKTtcbiAgICAgICAgICAgICAgICAgICAgZXh0ZW5kKHJlc1twcm9wXSwgY2hpbGRDb25maWdbcHJvcF0pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hpbGRDb25maWdbcHJvcF0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXNbcHJvcF0gPSBjaGlsZENvbmZpZ1twcm9wXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgcmVzW3Byb3BdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBmb3IgKHByb3AgaW4gcGFyZW50Q29uZmlnKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgaGFzT3duUHJvcChwYXJlbnRDb25maWcsIHByb3ApICYmXG4gICAgICAgICAgICAgICAgIWhhc093blByb3AoY2hpbGRDb25maWcsIHByb3ApICYmXG4gICAgICAgICAgICAgICAgaXNPYmplY3QocGFyZW50Q29uZmlnW3Byb3BdKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgLy8gbWFrZSBzdXJlIGNoYW5nZXMgdG8gcHJvcGVydGllcyBkb24ndCBtb2RpZnkgcGFyZW50IGNvbmZpZ1xuICAgICAgICAgICAgICAgIHJlc1twcm9wXSA9IGV4dGVuZCh7fSwgcmVzW3Byb3BdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIExvY2FsZShjb25maWcpIHtcbiAgICAgICAgaWYgKGNvbmZpZyAhPSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLnNldChjb25maWcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgdmFyIGtleXM7XG5cbiAgICBpZiAoT2JqZWN0LmtleXMpIHtcbiAgICAgICAga2V5cyA9IE9iamVjdC5rZXlzO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGtleXMgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgICAgICByZXMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoaSBpbiBvYmopIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzT3duUHJvcChvYmosIGkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcy5wdXNoKGkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRDYWxlbmRhciA9IHtcbiAgICAgICAgc2FtZURheTogJ1tUb2RheSBhdF0gTFQnLFxuICAgICAgICBuZXh0RGF5OiAnW1RvbW9ycm93IGF0XSBMVCcsXG4gICAgICAgIG5leHRXZWVrOiAnZGRkZCBbYXRdIExUJyxcbiAgICAgICAgbGFzdERheTogJ1tZZXN0ZXJkYXkgYXRdIExUJyxcbiAgICAgICAgbGFzdFdlZWs6ICdbTGFzdF0gZGRkZCBbYXRdIExUJyxcbiAgICAgICAgc2FtZUVsc2U6ICdMJyxcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gY2FsZW5kYXIoa2V5LCBtb20sIG5vdykge1xuICAgICAgICB2YXIgb3V0cHV0ID0gdGhpcy5fY2FsZW5kYXJba2V5XSB8fCB0aGlzLl9jYWxlbmRhclsnc2FtZUVsc2UnXTtcbiAgICAgICAgcmV0dXJuIGlzRnVuY3Rpb24ob3V0cHV0KSA/IG91dHB1dC5jYWxsKG1vbSwgbm93KSA6IG91dHB1dDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB6ZXJvRmlsbChudW1iZXIsIHRhcmdldExlbmd0aCwgZm9yY2VTaWduKSB7XG4gICAgICAgIHZhciBhYnNOdW1iZXIgPSAnJyArIE1hdGguYWJzKG51bWJlciksXG4gICAgICAgICAgICB6ZXJvc1RvRmlsbCA9IHRhcmdldExlbmd0aCAtIGFic051bWJlci5sZW5ndGgsXG4gICAgICAgICAgICBzaWduID0gbnVtYmVyID49IDA7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAoc2lnbiA/IChmb3JjZVNpZ24gPyAnKycgOiAnJykgOiAnLScpICtcbiAgICAgICAgICAgIE1hdGgucG93KDEwLCBNYXRoLm1heCgwLCB6ZXJvc1RvRmlsbCkpLnRvU3RyaW5nKCkuc3Vic3RyKDEpICtcbiAgICAgICAgICAgIGFic051bWJlclxuICAgICAgICApO1xuICAgIH1cblxuICAgIHZhciBmb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KFtIaF1tbShzcyk/fE1vfE1NP00/TT98RG98REREb3xERD9EP0Q/fGRkZD9kP3xkbz98d1tvfHddP3xXW298V10/fFFvP3xOezEsNX18WVlZWVlZfFlZWVlZfFlZWVl8WVl8eXsyLDR9fHlvP3xnZyhnZ2c/KT98R0coR0dHPyk/fGV8RXxhfEF8aGg/fEhIP3xraz98bW0/fHNzP3xTezEsOX18eHxYfHp6P3xaWj98LikvZyxcbiAgICAgICAgbG9jYWxGb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KExUU3xMVHxMTD9MP0w/fGx7MSw0fSkvZyxcbiAgICAgICAgZm9ybWF0RnVuY3Rpb25zID0ge30sXG4gICAgICAgIGZvcm1hdFRva2VuRnVuY3Rpb25zID0ge307XG5cbiAgICAvLyB0b2tlbjogICAgJ00nXG4gICAgLy8gcGFkZGVkOiAgIFsnTU0nLCAyXVxuICAgIC8vIG9yZGluYWw6ICAnTW8nXG4gICAgLy8gY2FsbGJhY2s6IGZ1bmN0aW9uICgpIHsgdGhpcy5tb250aCgpICsgMSB9XG4gICAgZnVuY3Rpb24gYWRkRm9ybWF0VG9rZW4odG9rZW4sIHBhZGRlZCwgb3JkaW5hbCwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGZ1bmMgPSBjYWxsYmFjaztcbiAgICAgICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGZ1bmMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGJhY2tdKCk7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIGlmICh0b2tlbikge1xuICAgICAgICAgICAgZm9ybWF0VG9rZW5GdW5jdGlvbnNbdG9rZW5dID0gZnVuYztcbiAgICAgICAgfVxuICAgICAgICBpZiAocGFkZGVkKSB7XG4gICAgICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1twYWRkZWRbMF1dID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB6ZXJvRmlsbChmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksIHBhZGRlZFsxXSwgcGFkZGVkWzJdKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9yZGluYWwpIHtcbiAgICAgICAgICAgIGZvcm1hdFRva2VuRnVuY3Rpb25zW29yZGluYWxdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5vcmRpbmFsKFxuICAgICAgICAgICAgICAgICAgICBmdW5jLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyksXG4gICAgICAgICAgICAgICAgICAgIHRva2VuXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZW1vdmVGb3JtYXR0aW5nVG9rZW5zKGlucHV0KSB7XG4gICAgICAgIGlmIChpbnB1dC5tYXRjaCgvXFxbW1xcc1xcU10vKSkge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL15cXFt8XFxdJC9nLCAnJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL1xcXFwvZywgJycpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VGb3JtYXRGdW5jdGlvbihmb3JtYXQpIHtcbiAgICAgICAgdmFyIGFycmF5ID0gZm9ybWF0Lm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIGxlbmd0aDtcblxuICAgICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBhcnJheS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGZvcm1hdFRva2VuRnVuY3Rpb25zW2FycmF5W2ldXSkge1xuICAgICAgICAgICAgICAgIGFycmF5W2ldID0gZm9ybWF0VG9rZW5GdW5jdGlvbnNbYXJyYXlbaV1dO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhcnJheVtpXSA9IHJlbW92ZUZvcm1hdHRpbmdUb2tlbnMoYXJyYXlbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtb20pIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSAnJyxcbiAgICAgICAgICAgICAgICBpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0ICs9IGlzRnVuY3Rpb24oYXJyYXlbaV0pXG4gICAgICAgICAgICAgICAgICAgID8gYXJyYXlbaV0uY2FsbChtb20sIGZvcm1hdClcbiAgICAgICAgICAgICAgICAgICAgOiBhcnJheVtpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvdXRwdXQ7XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy8gZm9ybWF0IGRhdGUgdXNpbmcgbmF0aXZlIGRhdGUgb2JqZWN0XG4gICAgZnVuY3Rpb24gZm9ybWF0TW9tZW50KG0sIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW0uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gbS5sb2NhbGVEYXRhKCkuaW52YWxpZERhdGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvcm1hdCA9IGV4cGFuZEZvcm1hdChmb3JtYXQsIG0ubG9jYWxlRGF0YSgpKTtcbiAgICAgICAgZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0gPVxuICAgICAgICAgICAgZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0gfHwgbWFrZUZvcm1hdEZ1bmN0aW9uKGZvcm1hdCk7XG5cbiAgICAgICAgcmV0dXJuIGZvcm1hdEZ1bmN0aW9uc1tmb3JtYXRdKG0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4cGFuZEZvcm1hdChmb3JtYXQsIGxvY2FsZSkge1xuICAgICAgICB2YXIgaSA9IDU7XG5cbiAgICAgICAgZnVuY3Rpb24gcmVwbGFjZUxvbmdEYXRlRm9ybWF0VG9rZW5zKGlucHV0KSB7XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxlLmxvbmdEYXRlRm9ybWF0KGlucHV0KSB8fCBpbnB1dDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy5sYXN0SW5kZXggPSAwO1xuICAgICAgICB3aGlsZSAoaSA+PSAwICYmIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKFxuICAgICAgICAgICAgICAgIGxvY2FsRm9ybWF0dGluZ1Rva2VucyxcbiAgICAgICAgICAgICAgICByZXBsYWNlTG9uZ0RhdGVGb3JtYXRUb2tlbnNcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBsb2NhbEZvcm1hdHRpbmdUb2tlbnMubGFzdEluZGV4ID0gMDtcbiAgICAgICAgICAgIGkgLT0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb25nRGF0ZUZvcm1hdCA9IHtcbiAgICAgICAgTFRTOiAnaDptbTpzcyBBJyxcbiAgICAgICAgTFQ6ICdoOm1tIEEnLFxuICAgICAgICBMOiAnTU0vREQvWVlZWScsXG4gICAgICAgIExMOiAnTU1NTSBELCBZWVlZJyxcbiAgICAgICAgTExMOiAnTU1NTSBELCBZWVlZIGg6bW0gQScsXG4gICAgICAgIExMTEw6ICdkZGRkLCBNTU1NIEQsIFlZWVkgaDptbSBBJyxcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9uZ0RhdGVGb3JtYXQoa2V5KSB7XG4gICAgICAgIHZhciBmb3JtYXQgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldLFxuICAgICAgICAgICAgZm9ybWF0VXBwZXIgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXkudG9VcHBlckNhc2UoKV07XG5cbiAgICAgICAgaWYgKGZvcm1hdCB8fCAhZm9ybWF0VXBwZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBmb3JtYXQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldID0gZm9ybWF0VXBwZXJcbiAgICAgICAgICAgIC5tYXRjaChmb3JtYXR0aW5nVG9rZW5zKVxuICAgICAgICAgICAgLm1hcChmdW5jdGlvbiAodG9rKSB7XG4gICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICB0b2sgPT09ICdNTU1NJyB8fFxuICAgICAgICAgICAgICAgICAgICB0b2sgPT09ICdNTScgfHxcbiAgICAgICAgICAgICAgICAgICAgdG9rID09PSAnREQnIHx8XG4gICAgICAgICAgICAgICAgICAgIHRvayA9PT0gJ2RkZGQnXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0b2suc2xpY2UoMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiB0b2s7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmpvaW4oJycpO1xuXG4gICAgICAgIHJldHVybiB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0SW52YWxpZERhdGUgPSAnSW52YWxpZCBkYXRlJztcblxuICAgIGZ1bmN0aW9uIGludmFsaWREYXRlKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faW52YWxpZERhdGU7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRPcmRpbmFsID0gJyVkJyxcbiAgICAgICAgZGVmYXVsdERheU9mTW9udGhPcmRpbmFsUGFyc2UgPSAvXFxkezEsMn0vO1xuXG4gICAgZnVuY3Rpb24gb3JkaW5hbChudW1iZXIpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX29yZGluYWwucmVwbGFjZSgnJWQnLCBudW1iZXIpO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0UmVsYXRpdmVUaW1lID0ge1xuICAgICAgICBmdXR1cmU6ICdpbiAlcycsXG4gICAgICAgIHBhc3Q6ICclcyBhZ28nLFxuICAgICAgICBzOiAnYSBmZXcgc2Vjb25kcycsXG4gICAgICAgIHNzOiAnJWQgc2Vjb25kcycsXG4gICAgICAgIG06ICdhIG1pbnV0ZScsXG4gICAgICAgIG1tOiAnJWQgbWludXRlcycsXG4gICAgICAgIGg6ICdhbiBob3VyJyxcbiAgICAgICAgaGg6ICclZCBob3VycycsXG4gICAgICAgIGQ6ICdhIGRheScsXG4gICAgICAgIGRkOiAnJWQgZGF5cycsXG4gICAgICAgIHc6ICdhIHdlZWsnLFxuICAgICAgICB3dzogJyVkIHdlZWtzJyxcbiAgICAgICAgTTogJ2EgbW9udGgnLFxuICAgICAgICBNTTogJyVkIG1vbnRocycsXG4gICAgICAgIHk6ICdhIHllYXInLFxuICAgICAgICB5eTogJyVkIHllYXJzJyxcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcmVsYXRpdmVUaW1lKG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSkge1xuICAgICAgICB2YXIgb3V0cHV0ID0gdGhpcy5fcmVsYXRpdmVUaW1lW3N0cmluZ107XG4gICAgICAgIHJldHVybiBpc0Z1bmN0aW9uKG91dHB1dClcbiAgICAgICAgICAgID8gb3V0cHV0KG51bWJlciwgd2l0aG91dFN1ZmZpeCwgc3RyaW5nLCBpc0Z1dHVyZSlcbiAgICAgICAgICAgIDogb3V0cHV0LnJlcGxhY2UoLyVkL2ksIG51bWJlcik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFzdEZ1dHVyZShkaWZmLCBvdXRwdXQpIHtcbiAgICAgICAgdmFyIGZvcm1hdCA9IHRoaXMuX3JlbGF0aXZlVGltZVtkaWZmID4gMCA/ICdmdXR1cmUnIDogJ3Bhc3QnXTtcbiAgICAgICAgcmV0dXJuIGlzRnVuY3Rpb24oZm9ybWF0KSA/IGZvcm1hdChvdXRwdXQpIDogZm9ybWF0LnJlcGxhY2UoLyVzL2ksIG91dHB1dCk7XG4gICAgfVxuXG4gICAgdmFyIGFsaWFzZXMgPSB7fTtcblxuICAgIGZ1bmN0aW9uIGFkZFVuaXRBbGlhcyh1bml0LCBzaG9ydGhhbmQpIHtcbiAgICAgICAgdmFyIGxvd2VyQ2FzZSA9IHVuaXQudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgYWxpYXNlc1tsb3dlckNhc2VdID0gYWxpYXNlc1tsb3dlckNhc2UgKyAncyddID0gYWxpYXNlc1tzaG9ydGhhbmRdID0gdW5pdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub3JtYWxpemVVbml0cyh1bml0cykge1xuICAgICAgICByZXR1cm4gdHlwZW9mIHVuaXRzID09PSAnc3RyaW5nJ1xuICAgICAgICAgICAgPyBhbGlhc2VzW3VuaXRzXSB8fCBhbGlhc2VzW3VuaXRzLnRvTG93ZXJDYXNlKCldXG4gICAgICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub3JtYWxpemVPYmplY3RVbml0cyhpbnB1dE9iamVjdCkge1xuICAgICAgICB2YXIgbm9ybWFsaXplZElucHV0ID0ge30sXG4gICAgICAgICAgICBub3JtYWxpemVkUHJvcCxcbiAgICAgICAgICAgIHByb3A7XG5cbiAgICAgICAgZm9yIChwcm9wIGluIGlucHV0T2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcChpbnB1dE9iamVjdCwgcHJvcCkpIHtcbiAgICAgICAgICAgICAgICBub3JtYWxpemVkUHJvcCA9IG5vcm1hbGl6ZVVuaXRzKHByb3ApO1xuICAgICAgICAgICAgICAgIGlmIChub3JtYWxpemVkUHJvcCkge1xuICAgICAgICAgICAgICAgICAgICBub3JtYWxpemVkSW5wdXRbbm9ybWFsaXplZFByb3BdID0gaW5wdXRPYmplY3RbcHJvcF07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRJbnB1dDtcbiAgICB9XG5cbiAgICB2YXIgcHJpb3JpdGllcyA9IHt9O1xuXG4gICAgZnVuY3Rpb24gYWRkVW5pdFByaW9yaXR5KHVuaXQsIHByaW9yaXR5KSB7XG4gICAgICAgIHByaW9yaXRpZXNbdW5pdF0gPSBwcmlvcml0eTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRQcmlvcml0aXplZFVuaXRzKHVuaXRzT2JqKSB7XG4gICAgICAgIHZhciB1bml0cyA9IFtdLFxuICAgICAgICAgICAgdTtcbiAgICAgICAgZm9yICh1IGluIHVuaXRzT2JqKSB7XG4gICAgICAgICAgICBpZiAoaGFzT3duUHJvcCh1bml0c09iaiwgdSkpIHtcbiAgICAgICAgICAgICAgICB1bml0cy5wdXNoKHsgdW5pdDogdSwgcHJpb3JpdHk6IHByaW9yaXRpZXNbdV0gfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdW5pdHMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGEucHJpb3JpdHkgLSBiLnByaW9yaXR5O1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHVuaXRzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzTGVhcFllYXIoeWVhcikge1xuICAgICAgICByZXR1cm4gKHllYXIgJSA0ID09PSAwICYmIHllYXIgJSAxMDAgIT09IDApIHx8IHllYXIgJSA0MDAgPT09IDA7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWJzRmxvb3IobnVtYmVyKSB7XG4gICAgICAgIGlmIChudW1iZXIgPCAwKSB7XG4gICAgICAgICAgICAvLyAtMCAtPiAwXG4gICAgICAgICAgICByZXR1cm4gTWF0aC5jZWlsKG51bWJlcikgfHwgMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKG51bWJlcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b0ludChhcmd1bWVudEZvckNvZXJjaW9uKSB7XG4gICAgICAgIHZhciBjb2VyY2VkTnVtYmVyID0gK2FyZ3VtZW50Rm9yQ29lcmNpb24sXG4gICAgICAgICAgICB2YWx1ZSA9IDA7XG5cbiAgICAgICAgaWYgKGNvZXJjZWROdW1iZXIgIT09IDAgJiYgaXNGaW5pdGUoY29lcmNlZE51bWJlcikpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYWJzRmxvb3IoY29lcmNlZE51bWJlcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZUdldFNldCh1bml0LCBrZWVwVGltZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHNldCQxKHRoaXMsIHVuaXQsIHZhbHVlKTtcbiAgICAgICAgICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywga2VlcFRpbWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZ2V0KHRoaXMsIHVuaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldChtb20sIHVuaXQpIHtcbiAgICAgICAgcmV0dXJuIG1vbS5pc1ZhbGlkKClcbiAgICAgICAgICAgID8gbW9tLl9kWydnZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArIHVuaXRdKClcbiAgICAgICAgICAgIDogTmFOO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldCQxKG1vbSwgdW5pdCwgdmFsdWUpIHtcbiAgICAgICAgaWYgKG1vbS5pc1ZhbGlkKCkgJiYgIWlzTmFOKHZhbHVlKSkge1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHVuaXQgPT09ICdGdWxsWWVhcicgJiZcbiAgICAgICAgICAgICAgICBpc0xlYXBZZWFyKG1vbS55ZWFyKCkpICYmXG4gICAgICAgICAgICAgICAgbW9tLm1vbnRoKCkgPT09IDEgJiZcbiAgICAgICAgICAgICAgICBtb20uZGF0ZSgpID09PSAyOVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0b0ludCh2YWx1ZSk7XG4gICAgICAgICAgICAgICAgbW9tLl9kWydzZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArIHVuaXRdKFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgbW9tLm1vbnRoKCksXG4gICAgICAgICAgICAgICAgICAgIGRheXNJbk1vbnRoKHZhbHVlLCBtb20ubW9udGgoKSlcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtb20uX2RbJ3NldCcgKyAobW9tLl9pc1VUQyA/ICdVVEMnIDogJycpICsgdW5pdF0odmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gc3RyaW5nR2V0KHVuaXRzKSB7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW3VuaXRzXSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0cmluZ1NldCh1bml0cywgdmFsdWUpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB1bml0cyA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplT2JqZWN0VW5pdHModW5pdHMpO1xuICAgICAgICAgICAgdmFyIHByaW9yaXRpemVkID0gZ2V0UHJpb3JpdGl6ZWRVbml0cyh1bml0cyksXG4gICAgICAgICAgICAgICAgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBwcmlvcml0aXplZC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIHRoaXNbcHJpb3JpdGl6ZWRbaV0udW5pdF0odW5pdHNbcHJpb3JpdGl6ZWRbaV0udW5pdF0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG4gICAgICAgICAgICBpZiAoaXNGdW5jdGlvbih0aGlzW3VuaXRzXSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpc1t1bml0c10odmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIHZhciBtYXRjaDEgPSAvXFxkLywgLy8gICAgICAgMCAtIDlcbiAgICAgICAgbWF0Y2gyID0gL1xcZFxcZC8sIC8vICAgICAgMDAgLSA5OVxuICAgICAgICBtYXRjaDMgPSAvXFxkezN9LywgLy8gICAgIDAwMCAtIDk5OVxuICAgICAgICBtYXRjaDQgPSAvXFxkezR9LywgLy8gICAgMDAwMCAtIDk5OTlcbiAgICAgICAgbWF0Y2g2ID0gL1srLV0/XFxkezZ9LywgLy8gLTk5OTk5OSAtIDk5OTk5OVxuICAgICAgICBtYXRjaDF0bzIgPSAvXFxkXFxkPy8sIC8vICAgICAgIDAgLSA5OVxuICAgICAgICBtYXRjaDN0bzQgPSAvXFxkXFxkXFxkXFxkPy8sIC8vICAgICA5OTkgLSA5OTk5XG4gICAgICAgIG1hdGNoNXRvNiA9IC9cXGRcXGRcXGRcXGRcXGRcXGQ/LywgLy8gICA5OTk5OSAtIDk5OTk5OVxuICAgICAgICBtYXRjaDF0bzMgPSAvXFxkezEsM30vLCAvLyAgICAgICAwIC0gOTk5XG4gICAgICAgIG1hdGNoMXRvNCA9IC9cXGR7MSw0fS8sIC8vICAgICAgIDAgLSA5OTk5XG4gICAgICAgIG1hdGNoMXRvNiA9IC9bKy1dP1xcZHsxLDZ9LywgLy8gLTk5OTk5OSAtIDk5OTk5OVxuICAgICAgICBtYXRjaFVuc2lnbmVkID0gL1xcZCsvLCAvLyAgICAgICAwIC0gaW5mXG4gICAgICAgIG1hdGNoU2lnbmVkID0gL1srLV0/XFxkKy8sIC8vICAgIC1pbmYgLSBpbmZcbiAgICAgICAgbWF0Y2hPZmZzZXQgPSAvWnxbKy1dXFxkXFxkOj9cXGRcXGQvZ2ksIC8vICswMDowMCAtMDA6MDAgKzAwMDAgLTAwMDAgb3IgWlxuICAgICAgICBtYXRjaFNob3J0T2Zmc2V0ID0gL1p8WystXVxcZFxcZCg/Ojo/XFxkXFxkKT8vZ2ksIC8vICswMCAtMDAgKzAwOjAwIC0wMDowMCArMDAwMCAtMDAwMCBvciBaXG4gICAgICAgIG1hdGNoVGltZXN0YW1wID0gL1srLV0/XFxkKyhcXC5cXGR7MSwzfSk/LywgLy8gMTIzNDU2Nzg5IDEyMzQ1Njc4OS4xMjNcbiAgICAgICAgLy8gYW55IHdvcmQgKG9yIHR3bykgY2hhcmFjdGVycyBvciBudW1iZXJzIGluY2x1ZGluZyB0d28vdGhyZWUgd29yZCBtb250aCBpbiBhcmFiaWMuXG4gICAgICAgIC8vIGluY2x1ZGVzIHNjb3R0aXNoIGdhZWxpYyB0d28gd29yZCBhbmQgaHlwaGVuYXRlZCBtb250aHNcbiAgICAgICAgbWF0Y2hXb3JkID0gL1swLTldezAsMjU2fVsnYS16XFx1MDBBMC1cXHUwNUZGXFx1MDcwMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRjA3XFx1RkYxMC1cXHVGRkVGXXsxLDI1Nn18W1xcdTA2MDAtXFx1MDZGRlxcL117MSwyNTZ9KFxccyo/W1xcdTA2MDAtXFx1MDZGRl17MSwyNTZ9KXsxLDJ9L2ksXG4gICAgICAgIHJlZ2V4ZXM7XG5cbiAgICByZWdleGVzID0ge307XG5cbiAgICBmdW5jdGlvbiBhZGRSZWdleFRva2VuKHRva2VuLCByZWdleCwgc3RyaWN0UmVnZXgpIHtcbiAgICAgICAgcmVnZXhlc1t0b2tlbl0gPSBpc0Z1bmN0aW9uKHJlZ2V4KVxuICAgICAgICAgICAgPyByZWdleFxuICAgICAgICAgICAgOiBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZURhdGEpIHtcbiAgICAgICAgICAgICAgICAgIHJldHVybiBpc1N0cmljdCAmJiBzdHJpY3RSZWdleCA/IHN0cmljdFJlZ2V4IDogcmVnZXg7XG4gICAgICAgICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0UGFyc2VSZWdleEZvclRva2VuKHRva2VuLCBjb25maWcpIHtcbiAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHJlZ2V4ZXMsIHRva2VuKSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBSZWdFeHAodW5lc2NhcGVGb3JtYXQodG9rZW4pKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZWdleGVzW3Rva2VuXShjb25maWcuX3N0cmljdCwgY29uZmlnLl9sb2NhbGUpO1xuICAgIH1cblxuICAgIC8vIENvZGUgZnJvbSBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM1NjE0OTMvaXMtdGhlcmUtYS1yZWdleHAtZXNjYXBlLWZ1bmN0aW9uLWluLWphdmFzY3JpcHRcbiAgICBmdW5jdGlvbiB1bmVzY2FwZUZvcm1hdChzKSB7XG4gICAgICAgIHJldHVybiByZWdleEVzY2FwZShcbiAgICAgICAgICAgIHNcbiAgICAgICAgICAgICAgICAucmVwbGFjZSgnXFxcXCcsICcnKVxuICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcKFxcWyl8XFxcXChcXF0pfFxcWyhbXlxcXVxcW10qKVxcXXxcXFxcKC4pL2csIGZ1bmN0aW9uIChcbiAgICAgICAgICAgICAgICAgICAgbWF0Y2hlZCxcbiAgICAgICAgICAgICAgICAgICAgcDEsXG4gICAgICAgICAgICAgICAgICAgIHAyLFxuICAgICAgICAgICAgICAgICAgICBwMyxcbiAgICAgICAgICAgICAgICAgICAgcDRcbiAgICAgICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHAxIHx8IHAyIHx8IHAzIHx8IHA0O1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVnZXhFc2NhcGUocykge1xuICAgICAgICByZXR1cm4gcy5yZXBsYWNlKC9bLVxcL1xcXFxeJCorPy4oKXxbXFxde31dL2csICdcXFxcJCYnKTtcbiAgICB9XG5cbiAgICB2YXIgdG9rZW5zID0ge307XG5cbiAgICBmdW5jdGlvbiBhZGRQYXJzZVRva2VuKHRva2VuLCBjYWxsYmFjaykge1xuICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgIGZ1bmMgPSBjYWxsYmFjaztcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIHRva2VuID0gW3Rva2VuXTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNOdW1iZXIoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBmdW5jID0gZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICAgICAgICAgIGFycmF5W2NhbGxiYWNrXSA9IHRvSW50KGlucHV0KTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IHRva2VuLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0b2tlbnNbdG9rZW5baV1dID0gZnVuYztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFdlZWtQYXJzZVRva2VuKHRva2VuLCBjYWxsYmFjaykge1xuICAgICAgICBhZGRQYXJzZVRva2VuKHRva2VuLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcsIHRva2VuKSB7XG4gICAgICAgICAgICBjb25maWcuX3cgPSBjb25maWcuX3cgfHwge307XG4gICAgICAgICAgICBjYWxsYmFjayhpbnB1dCwgY29uZmlnLl93LCBjb25maWcsIHRva2VuKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkVGltZVRvQXJyYXlGcm9tVG9rZW4odG9rZW4sIGlucHV0LCBjb25maWcpIHtcbiAgICAgICAgaWYgKGlucHV0ICE9IG51bGwgJiYgaGFzT3duUHJvcCh0b2tlbnMsIHRva2VuKSkge1xuICAgICAgICAgICAgdG9rZW5zW3Rva2VuXShpbnB1dCwgY29uZmlnLl9hLCBjb25maWcsIHRva2VuKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBZRUFSID0gMCxcbiAgICAgICAgTU9OVEggPSAxLFxuICAgICAgICBEQVRFID0gMixcbiAgICAgICAgSE9VUiA9IDMsXG4gICAgICAgIE1JTlVURSA9IDQsXG4gICAgICAgIFNFQ09ORCA9IDUsXG4gICAgICAgIE1JTExJU0VDT05EID0gNixcbiAgICAgICAgV0VFSyA9IDcsXG4gICAgICAgIFdFRUtEQVkgPSA4O1xuXG4gICAgZnVuY3Rpb24gbW9kKG4sIHgpIHtcbiAgICAgICAgcmV0dXJuICgobiAlIHgpICsgeCkgJSB4O1xuICAgIH1cblxuICAgIHZhciBpbmRleE9mO1xuXG4gICAgaWYgKEFycmF5LnByb3RvdHlwZS5pbmRleE9mKSB7XG4gICAgICAgIGluZGV4T2YgPSBBcnJheS5wcm90b3R5cGUuaW5kZXhPZjtcbiAgICB9IGVsc2Uge1xuICAgICAgICBpbmRleE9mID0gZnVuY3Rpb24gKG8pIHtcbiAgICAgICAgICAgIC8vIEkga25vd1xuICAgICAgICAgICAgdmFyIGk7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdGhpcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzW2ldID09PSBvKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiAtMTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkYXlzSW5Nb250aCh5ZWFyLCBtb250aCkge1xuICAgICAgICBpZiAoaXNOYU4oeWVhcikgfHwgaXNOYU4obW9udGgpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtb2RNb250aCA9IG1vZChtb250aCwgMTIpO1xuICAgICAgICB5ZWFyICs9IChtb250aCAtIG1vZE1vbnRoKSAvIDEyO1xuICAgICAgICByZXR1cm4gbW9kTW9udGggPT09IDFcbiAgICAgICAgICAgID8gaXNMZWFwWWVhcih5ZWFyKVxuICAgICAgICAgICAgICAgID8gMjlcbiAgICAgICAgICAgICAgICA6IDI4XG4gICAgICAgICAgICA6IDMxIC0gKChtb2RNb250aCAlIDcpICUgMik7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ00nLCBbJ01NJywgMl0sICdNbycsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9udGgoKSArIDE7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignTU1NJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzU2hvcnQodGhpcywgZm9ybWF0KTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdNTU1NJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubW9udGhzKHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ21vbnRoJywgJ00nKTtcblxuICAgIC8vIFBSSU9SSVRZXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ21vbnRoJywgOCk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdNJywgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdNTScsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbiAgICBhZGRSZWdleFRva2VuKCdNTU0nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLm1vbnRoc1Nob3J0UmVnZXgoaXNTdHJpY3QpO1xuICAgIH0pO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ01NTU0nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLm1vbnRoc1JlZ2V4KGlzU3RyaWN0KTtcbiAgICB9KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydNJywgJ01NJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgYXJyYXlbTU9OVEhdID0gdG9JbnQoaW5wdXQpIC0gMTtcbiAgICB9KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydNTU0nLCAnTU1NTSddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcsIHRva2VuKSB7XG4gICAgICAgIHZhciBtb250aCA9IGNvbmZpZy5fbG9jYWxlLm1vbnRoc1BhcnNlKGlucHV0LCB0b2tlbiwgY29uZmlnLl9zdHJpY3QpO1xuICAgICAgICAvLyBpZiB3ZSBkaWRuJ3QgZmluZCBhIG1vbnRoIG5hbWUsIG1hcmsgdGhlIGRhdGUgYXMgaW52YWxpZC5cbiAgICAgICAgaWYgKG1vbnRoICE9IG51bGwpIHtcbiAgICAgICAgICAgIGFycmF5W01PTlRIXSA9IG1vbnRoO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZE1vbnRoID0gaW5wdXQ7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIExPQ0FMRVNcblxuICAgIHZhciBkZWZhdWx0TG9jYWxlTW9udGhzID0gJ0phbnVhcnlfRmVicnVhcnlfTWFyY2hfQXByaWxfTWF5X0p1bmVfSnVseV9BdWd1c3RfU2VwdGVtYmVyX09jdG9iZXJfTm92ZW1iZXJfRGVjZW1iZXInLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIGRlZmF1bHRMb2NhbGVNb250aHNTaG9ydCA9ICdKYW5fRmViX01hcl9BcHJfTWF5X0p1bl9KdWxfQXVnX1NlcF9PY3RfTm92X0RlYycuc3BsaXQoXG4gICAgICAgICAgICAnXydcbiAgICAgICAgKSxcbiAgICAgICAgTU9OVEhTX0lOX0ZPUk1BVCA9IC9EW29EXT8oXFxbW15cXFtcXF1dKlxcXXxcXHMpK01NTU0/LyxcbiAgICAgICAgZGVmYXVsdE1vbnRoc1Nob3J0UmVnZXggPSBtYXRjaFdvcmQsXG4gICAgICAgIGRlZmF1bHRNb250aHNSZWdleCA9IG1hdGNoV29yZDtcblxuICAgIGZ1bmN0aW9uIGxvY2FsZU1vbnRocyhtLCBmb3JtYXQpIHtcbiAgICAgICAgaWYgKCFtKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNBcnJheSh0aGlzLl9tb250aHMpXG4gICAgICAgICAgICAgICAgPyB0aGlzLl9tb250aHNcbiAgICAgICAgICAgICAgICA6IHRoaXMuX21vbnRoc1snc3RhbmRhbG9uZSddO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc0FycmF5KHRoaXMuX21vbnRocylcbiAgICAgICAgICAgID8gdGhpcy5fbW9udGhzW20ubW9udGgoKV1cbiAgICAgICAgICAgIDogdGhpcy5fbW9udGhzW1xuICAgICAgICAgICAgICAgICAgKHRoaXMuX21vbnRocy5pc0Zvcm1hdCB8fCBNT05USFNfSU5fRk9STUFUKS50ZXN0KGZvcm1hdClcbiAgICAgICAgICAgICAgICAgICAgICA/ICdmb3JtYXQnXG4gICAgICAgICAgICAgICAgICAgICAgOiAnc3RhbmRhbG9uZSdcbiAgICAgICAgICAgICAgXVttLm1vbnRoKCldO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvY2FsZU1vbnRoc1Nob3J0KG0sIGZvcm1hdCkge1xuICAgICAgICBpZiAoIW0pIHtcbiAgICAgICAgICAgIHJldHVybiBpc0FycmF5KHRoaXMuX21vbnRoc1Nob3J0KVxuICAgICAgICAgICAgICAgID8gdGhpcy5fbW9udGhzU2hvcnRcbiAgICAgICAgICAgICAgICA6IHRoaXMuX21vbnRoc1Nob3J0WydzdGFuZGFsb25lJ107XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlzQXJyYXkodGhpcy5fbW9udGhzU2hvcnQpXG4gICAgICAgICAgICA/IHRoaXMuX21vbnRoc1Nob3J0W20ubW9udGgoKV1cbiAgICAgICAgICAgIDogdGhpcy5fbW9udGhzU2hvcnRbXG4gICAgICAgICAgICAgICAgICBNT05USFNfSU5fRk9STUFULnRlc3QoZm9ybWF0KSA/ICdmb3JtYXQnIDogJ3N0YW5kYWxvbmUnXG4gICAgICAgICAgICAgIF1bbS5tb250aCgpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBoYW5kbGVTdHJpY3RQYXJzZShtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgaWksXG4gICAgICAgICAgICBtb20sXG4gICAgICAgICAgICBsbGMgPSBtb250aE5hbWUudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgaWYgKCF0aGlzLl9tb250aHNQYXJzZSkge1xuICAgICAgICAgICAgLy8gdGhpcyBpcyBub3QgdXNlZFxuICAgICAgICAgICAgdGhpcy5fbW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fc2hvcnRNb250aHNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDEyOyArK2kpIHtcbiAgICAgICAgICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIGldKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlW2ldID0gdGhpcy5tb250aHNTaG9ydChcbiAgICAgICAgICAgICAgICAgICAgbW9tLFxuICAgICAgICAgICAgICAgICAgICAnJ1xuICAgICAgICAgICAgICAgICkudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb25nTW9udGhzUGFyc2VbaV0gPSB0aGlzLm1vbnRocyhtb20sICcnKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0cmljdCkge1xuICAgICAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ01NTScpIHtcbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydE1vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX2xvbmdNb250aHNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ01NTScpIHtcbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydE1vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9sb25nTW9udGhzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbG9uZ01vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9zaG9ydE1vbnRoc1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVNb250aHNQYXJzZShtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgICAgIHZhciBpLCBtb20sIHJlZ2V4O1xuXG4gICAgICAgIGlmICh0aGlzLl9tb250aHNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gaGFuZGxlU3RyaWN0UGFyc2UuY2FsbCh0aGlzLCBtb250aE5hbWUsIGZvcm1hdCwgc3RyaWN0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGhpcy5fbW9udGhzUGFyc2UpIHtcbiAgICAgICAgICAgIHRoaXMuX21vbnRoc1BhcnNlID0gW107XG4gICAgICAgICAgICB0aGlzLl9sb25nTW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0TW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRPRE86IGFkZCBzb3J0aW5nXG4gICAgICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgbW9udGggKG9yIGFiYnIpIGlzIGEgcHJlZml4IG9mIGFub3RoZXJcbiAgICAgICAgLy8gc2VlIHNvcnRpbmcgaW4gY29tcHV0ZU1vbnRoc1BhcnNlXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcbiAgICAgICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgaV0pO1xuICAgICAgICAgICAgaWYgKHN0cmljdCAmJiAhdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbG9uZ01vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgICAgICAgJ14nICsgdGhpcy5tb250aHMobW9tLCAnJykucmVwbGFjZSgnLicsICcnKSArICckJyxcbiAgICAgICAgICAgICAgICAgICAgJ2knXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zaG9ydE1vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgICAgICAgJ14nICsgdGhpcy5tb250aHNTaG9ydChtb20sICcnKS5yZXBsYWNlKCcuJywgJycpICsgJyQnLFxuICAgICAgICAgICAgICAgICAgICAnaSdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFzdHJpY3QgJiYgIXRoaXMuX21vbnRoc1BhcnNlW2ldKSB7XG4gICAgICAgICAgICAgICAgcmVnZXggPVxuICAgICAgICAgICAgICAgICAgICAnXicgKyB0aGlzLm1vbnRocyhtb20sICcnKSArICd8XicgKyB0aGlzLm1vbnRoc1Nob3J0KG1vbSwgJycpO1xuICAgICAgICAgICAgICAgIHRoaXMuX21vbnRoc1BhcnNlW2ldID0gbmV3IFJlZ0V4cChyZWdleC5yZXBsYWNlKCcuJywgJycpLCAnaScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdGVzdCB0aGUgcmVnZXhcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBzdHJpY3QgJiZcbiAgICAgICAgICAgICAgICBmb3JtYXQgPT09ICdNTU1NJyAmJlxuICAgICAgICAgICAgICAgIHRoaXMuX2xvbmdNb250aHNQYXJzZVtpXS50ZXN0KG1vbnRoTmFtZSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICBzdHJpY3QgJiZcbiAgICAgICAgICAgICAgICBmb3JtYXQgPT09ICdNTU0nICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fc2hvcnRNb250aHNQYXJzZVtpXS50ZXN0KG1vbnRoTmFtZSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmICghc3RyaWN0ICYmIHRoaXMuX21vbnRoc1BhcnNlW2ldLnRlc3QobW9udGhOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gc2V0TW9udGgobW9tLCB2YWx1ZSkge1xuICAgICAgICB2YXIgZGF5T2ZNb250aDtcblxuICAgICAgICBpZiAoIW1vbS5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIC8vIE5vIG9wXG4gICAgICAgICAgICByZXR1cm4gbW9tO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGlmICgvXlxcZCskLy50ZXN0KHZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdG9JbnQodmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IG1vbS5sb2NhbGVEYXRhKCkubW9udGhzUGFyc2UodmFsdWUpO1xuICAgICAgICAgICAgICAgIC8vIFRPRE86IEFub3RoZXIgc2lsZW50IGZhaWx1cmU/XG4gICAgICAgICAgICAgICAgaWYgKCFpc051bWJlcih2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1vbTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBkYXlPZk1vbnRoID0gTWF0aC5taW4obW9tLmRhdGUoKSwgZGF5c0luTW9udGgobW9tLnllYXIoKSwgdmFsdWUpKTtcbiAgICAgICAgbW9tLl9kWydzZXQnICsgKG1vbS5faXNVVEMgPyAnVVRDJyA6ICcnKSArICdNb250aCddKHZhbHVlLCBkYXlPZk1vbnRoKTtcbiAgICAgICAgcmV0dXJuIG1vbTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTZXRNb250aCh2YWx1ZSkge1xuICAgICAgICBpZiAodmFsdWUgIT0gbnVsbCkge1xuICAgICAgICAgICAgc2V0TW9udGgodGhpcywgdmFsdWUpO1xuICAgICAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KHRoaXMsIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0KHRoaXMsICdNb250aCcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0RGF5c0luTW9udGgoKSB7XG4gICAgICAgIHJldHVybiBkYXlzSW5Nb250aCh0aGlzLnllYXIoKSwgdGhpcy5tb250aCgpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb250aHNTaG9ydFJlZ2V4KGlzU3RyaWN0KSB7XG4gICAgICAgIGlmICh0aGlzLl9tb250aHNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX21vbnRoc1Nob3J0UmVnZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNTaG9ydFJlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNTaG9ydFJlZ2V4ID0gZGVmYXVsdE1vbnRoc1Nob3J0UmVnZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleCAmJiBpc1N0cmljdFxuICAgICAgICAgICAgICAgID8gdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleFxuICAgICAgICAgICAgICAgIDogdGhpcy5fbW9udGhzU2hvcnRSZWdleDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vbnRoc1JlZ2V4KGlzU3RyaWN0KSB7XG4gICAgICAgIGlmICh0aGlzLl9tb250aHNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19tb250aHNSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgY29tcHV0ZU1vbnRoc1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX21vbnRoc1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNSZWdleCA9IGRlZmF1bHRNb250aHNSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNTdHJpY3RSZWdleCAmJiBpc1N0cmljdFxuICAgICAgICAgICAgICAgID8gdGhpcy5fbW9udGhzU3RyaWN0UmVnZXhcbiAgICAgICAgICAgICAgICA6IHRoaXMuX21vbnRoc1JlZ2V4O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZU1vbnRoc1BhcnNlKCkge1xuICAgICAgICBmdW5jdGlvbiBjbXBMZW5SZXYoYSwgYikge1xuICAgICAgICAgICAgcmV0dXJuIGIubGVuZ3RoIC0gYS5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgc2hvcnRQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIGxvbmdQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIG1peGVkUGllY2VzID0gW10sXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgbW9tO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICAgICAgLy8gbWFrZSB0aGUgcmVnZXggaWYgd2UgZG9uJ3QgaGF2ZSBpdCBhbHJlYWR5XG4gICAgICAgICAgICBtb20gPSBjcmVhdGVVVEMoWzIwMDAsIGldKTtcbiAgICAgICAgICAgIHNob3J0UGllY2VzLnB1c2godGhpcy5tb250aHNTaG9ydChtb20sICcnKSk7XG4gICAgICAgICAgICBsb25nUGllY2VzLnB1c2godGhpcy5tb250aHMobW9tLCAnJykpO1xuICAgICAgICAgICAgbWl4ZWRQaWVjZXMucHVzaCh0aGlzLm1vbnRocyhtb20sICcnKSk7XG4gICAgICAgICAgICBtaXhlZFBpZWNlcy5wdXNoKHRoaXMubW9udGhzU2hvcnQobW9tLCAnJykpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgbW9udGggKG9yIGFiYnIpIGlzIGEgcHJlZml4IG9mIGFub3RoZXIgaXRcbiAgICAgICAgLy8gd2lsbCBtYXRjaCB0aGUgbG9uZ2VyIHBpZWNlLlxuICAgICAgICBzaG9ydFBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIGxvbmdQaWVjZXMuc29ydChjbXBMZW5SZXYpO1xuICAgICAgICBtaXhlZFBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCAxMjsgaSsrKSB7XG4gICAgICAgICAgICBzaG9ydFBpZWNlc1tpXSA9IHJlZ2V4RXNjYXBlKHNob3J0UGllY2VzW2ldKTtcbiAgICAgICAgICAgIGxvbmdQaWVjZXNbaV0gPSByZWdleEVzY2FwZShsb25nUGllY2VzW2ldKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMjQ7IGkrKykge1xuICAgICAgICAgICAgbWl4ZWRQaWVjZXNbaV0gPSByZWdleEVzY2FwZShtaXhlZFBpZWNlc1tpXSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9tb250aHNSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIG1peGVkUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICAgICAgdGhpcy5fbW9udGhzU2hvcnRSZWdleCA9IHRoaXMuX21vbnRoc1JlZ2V4O1xuICAgICAgICB0aGlzLl9tb250aHNTdHJpY3RSZWdleCA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAnXignICsgbG9uZ1BpZWNlcy5qb2luKCd8JykgKyAnKScsXG4gICAgICAgICAgICAnaSdcbiAgICAgICAgKTtcbiAgICAgICAgdGhpcy5fbW9udGhzU2hvcnRTdHJpY3RSZWdleCA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAnXignICsgc2hvcnRQaWVjZXMuam9pbignfCcpICsgJyknLFxuICAgICAgICAgICAgJ2knXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ1knLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB5ID0gdGhpcy55ZWFyKCk7XG4gICAgICAgIHJldHVybiB5IDw9IDk5OTkgPyB6ZXJvRmlsbCh5LCA0KSA6ICcrJyArIHk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbigwLCBbJ1lZJywgMl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueWVhcigpICUgMTAwO1xuICAgIH0pO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydZWVlZJywgNF0sIDAsICd5ZWFyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydZWVlZWScsIDVdLCAwLCAneWVhcicpO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnWVlZWVlZJywgNiwgdHJ1ZV0sIDAsICd5ZWFyJyk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ3llYXInLCAneScpO1xuXG4gICAgLy8gUFJJT1JJVElFU1xuXG4gICAgYWRkVW5pdFByaW9yaXR5KCd5ZWFyJywgMSk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdZJywgbWF0Y2hTaWduZWQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1lZJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ1lZWVknLCBtYXRjaDF0bzQsIG1hdGNoNCk7XG4gICAgYWRkUmVnZXhUb2tlbignWVlZWVknLCBtYXRjaDF0bzYsIG1hdGNoNik7XG4gICAgYWRkUmVnZXhUb2tlbignWVlZWVlZJywgbWF0Y2gxdG82LCBtYXRjaDYpO1xuXG4gICAgYWRkUGFyc2VUb2tlbihbJ1lZWVlZJywgJ1lZWVlZWSddLCBZRUFSKTtcbiAgICBhZGRQYXJzZVRva2VuKCdZWVlZJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICBhcnJheVtZRUFSXSA9XG4gICAgICAgICAgICBpbnB1dC5sZW5ndGggPT09IDIgPyBob29rcy5wYXJzZVR3b0RpZ2l0WWVhcihpbnB1dCkgOiB0b0ludChpbnB1dCk7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbignWVknLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgICAgIGFycmF5W1lFQVJdID0gaG9va3MucGFyc2VUd29EaWdpdFllYXIoaW5wdXQpO1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oJ1knLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5KSB7XG4gICAgICAgIGFycmF5W1lFQVJdID0gcGFyc2VJbnQoaW5wdXQsIDEwKTtcbiAgICB9KTtcblxuICAgIC8vIEhFTFBFUlNcblxuICAgIGZ1bmN0aW9uIGRheXNJblllYXIoeWVhcikge1xuICAgICAgICByZXR1cm4gaXNMZWFwWWVhcih5ZWFyKSA/IDM2NiA6IDM2NTtcbiAgICB9XG5cbiAgICAvLyBIT09LU1xuXG4gICAgaG9va3MucGFyc2VUd29EaWdpdFllYXIgPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIHRvSW50KGlucHV0KSArICh0b0ludChpbnB1dCkgPiA2OCA/IDE5MDAgOiAyMDAwKTtcbiAgICB9O1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgdmFyIGdldFNldFllYXIgPSBtYWtlR2V0U2V0KCdGdWxsWWVhcicsIHRydWUpO1xuXG4gICAgZnVuY3Rpb24gZ2V0SXNMZWFwWWVhcigpIHtcbiAgICAgICAgcmV0dXJuIGlzTGVhcFllYXIodGhpcy55ZWFyKCkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZURhdGUoeSwgbSwgZCwgaCwgTSwgcywgbXMpIHtcbiAgICAgICAgLy8gY2FuJ3QganVzdCBhcHBseSgpIHRvIGNyZWF0ZSBhIGRhdGU6XG4gICAgICAgIC8vIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vcS8xODEzNDhcbiAgICAgICAgdmFyIGRhdGU7XG4gICAgICAgIC8vIHRoZSBkYXRlIGNvbnN0cnVjdG9yIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgICAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDApIHtcbiAgICAgICAgICAgIC8vIHByZXNlcnZlIGxlYXAgeWVhcnMgdXNpbmcgYSBmdWxsIDQwMCB5ZWFyIGN5Y2xlLCB0aGVuIHJlc2V0XG4gICAgICAgICAgICBkYXRlID0gbmV3IERhdGUoeSArIDQwMCwgbSwgZCwgaCwgTSwgcywgbXMpO1xuICAgICAgICAgICAgaWYgKGlzRmluaXRlKGRhdGUuZ2V0RnVsbFllYXIoKSkpIHtcbiAgICAgICAgICAgICAgICBkYXRlLnNldEZ1bGxZZWFyKHkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZGF0ZSA9IG5ldyBEYXRlKHksIG0sIGQsIGgsIE0sIHMsIG1zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVVUQ0RhdGUoeSkge1xuICAgICAgICB2YXIgZGF0ZSwgYXJncztcbiAgICAgICAgLy8gdGhlIERhdGUuVVRDIGZ1bmN0aW9uIHJlbWFwcyB5ZWFycyAwLTk5IHRvIDE5MDAtMTk5OVxuICAgICAgICBpZiAoeSA8IDEwMCAmJiB5ID49IDApIHtcbiAgICAgICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuICAgICAgICAgICAgLy8gcHJlc2VydmUgbGVhcCB5ZWFycyB1c2luZyBhIGZ1bGwgNDAwIHllYXIgY3ljbGUsIHRoZW4gcmVzZXRcbiAgICAgICAgICAgIGFyZ3NbMF0gPSB5ICsgNDAwO1xuICAgICAgICAgICAgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDLmFwcGx5KG51bGwsIGFyZ3MpKTtcbiAgICAgICAgICAgIGlmIChpc0Zpbml0ZShkYXRlLmdldFVUQ0Z1bGxZZWFyKCkpKSB7XG4gICAgICAgICAgICAgICAgZGF0ZS5zZXRVVENGdWxsWWVhcih5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQy5hcHBseShudWxsLCBhcmd1bWVudHMpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkYXRlO1xuICAgIH1cblxuICAgIC8vIHN0YXJ0LW9mLWZpcnN0LXdlZWsgLSBzdGFydC1vZi15ZWFyXG4gICAgZnVuY3Rpb24gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSB7XG4gICAgICAgIHZhciAvLyBmaXJzdC13ZWVrIGRheSAtLSB3aGljaCBqYW51YXJ5IGlzIGFsd2F5cyBpbiB0aGUgZmlyc3Qgd2VlayAoNCBmb3IgaXNvLCAxIGZvciBvdGhlcilcbiAgICAgICAgICAgIGZ3ZCA9IDcgKyBkb3cgLSBkb3ksXG4gICAgICAgICAgICAvLyBmaXJzdC13ZWVrIGRheSBsb2NhbCB3ZWVrZGF5IC0tIHdoaWNoIGxvY2FsIHdlZWtkYXkgaXMgZndkXG4gICAgICAgICAgICBmd2RsdyA9ICg3ICsgY3JlYXRlVVRDRGF0ZSh5ZWFyLCAwLCBmd2QpLmdldFVUQ0RheSgpIC0gZG93KSAlIDc7XG5cbiAgICAgICAgcmV0dXJuIC1md2RsdyArIGZ3ZCAtIDE7XG4gICAgfVxuXG4gICAgLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPX3dlZWtfZGF0ZSNDYWxjdWxhdGluZ19hX2RhdGVfZ2l2ZW5fdGhlX3llYXIuMkNfd2Vla19udW1iZXJfYW5kX3dlZWtkYXlcbiAgICBmdW5jdGlvbiBkYXlPZlllYXJGcm9tV2Vla3MoeWVhciwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpIHtcbiAgICAgICAgdmFyIGxvY2FsV2Vla2RheSA9ICg3ICsgd2Vla2RheSAtIGRvdykgJSA3LFxuICAgICAgICAgICAgd2Vla09mZnNldCA9IGZpcnN0V2Vla09mZnNldCh5ZWFyLCBkb3csIGRveSksXG4gICAgICAgICAgICBkYXlPZlllYXIgPSAxICsgNyAqICh3ZWVrIC0gMSkgKyBsb2NhbFdlZWtkYXkgKyB3ZWVrT2Zmc2V0LFxuICAgICAgICAgICAgcmVzWWVhcixcbiAgICAgICAgICAgIHJlc0RheU9mWWVhcjtcblxuICAgICAgICBpZiAoZGF5T2ZZZWFyIDw9IDApIHtcbiAgICAgICAgICAgIHJlc1llYXIgPSB5ZWFyIC0gMTtcbiAgICAgICAgICAgIHJlc0RheU9mWWVhciA9IGRheXNJblllYXIocmVzWWVhcikgKyBkYXlPZlllYXI7XG4gICAgICAgIH0gZWxzZSBpZiAoZGF5T2ZZZWFyID4gZGF5c0luWWVhcih5ZWFyKSkge1xuICAgICAgICAgICAgcmVzWWVhciA9IHllYXIgKyAxO1xuICAgICAgICAgICAgcmVzRGF5T2ZZZWFyID0gZGF5T2ZZZWFyIC0gZGF5c0luWWVhcih5ZWFyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc1llYXIgPSB5ZWFyO1xuICAgICAgICAgICAgcmVzRGF5T2ZZZWFyID0gZGF5T2ZZZWFyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHllYXI6IHJlc1llYXIsXG4gICAgICAgICAgICBkYXlPZlllYXI6IHJlc0RheU9mWWVhcixcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB3ZWVrT2ZZZWFyKG1vbSwgZG93LCBkb3kpIHtcbiAgICAgICAgdmFyIHdlZWtPZmZzZXQgPSBmaXJzdFdlZWtPZmZzZXQobW9tLnllYXIoKSwgZG93LCBkb3kpLFxuICAgICAgICAgICAgd2VlayA9IE1hdGguZmxvb3IoKG1vbS5kYXlPZlllYXIoKSAtIHdlZWtPZmZzZXQgLSAxKSAvIDcpICsgMSxcbiAgICAgICAgICAgIHJlc1dlZWssXG4gICAgICAgICAgICByZXNZZWFyO1xuXG4gICAgICAgIGlmICh3ZWVrIDwgMSkge1xuICAgICAgICAgICAgcmVzWWVhciA9IG1vbS55ZWFyKCkgLSAxO1xuICAgICAgICAgICAgcmVzV2VlayA9IHdlZWsgKyB3ZWVrc0luWWVhcihyZXNZZWFyLCBkb3csIGRveSk7XG4gICAgICAgIH0gZWxzZSBpZiAod2VlayA+IHdlZWtzSW5ZZWFyKG1vbS55ZWFyKCksIGRvdywgZG95KSkge1xuICAgICAgICAgICAgcmVzV2VlayA9IHdlZWsgLSB3ZWVrc0luWWVhcihtb20ueWVhcigpLCBkb3csIGRveSk7XG4gICAgICAgICAgICByZXNZZWFyID0gbW9tLnllYXIoKSArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXNZZWFyID0gbW9tLnllYXIoKTtcbiAgICAgICAgICAgIHJlc1dlZWsgPSB3ZWVrO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHdlZWs6IHJlc1dlZWssXG4gICAgICAgICAgICB5ZWFyOiByZXNZZWFyLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHdlZWtzSW5ZZWFyKHllYXIsIGRvdywgZG95KSB7XG4gICAgICAgIHZhciB3ZWVrT2Zmc2V0ID0gZmlyc3RXZWVrT2Zmc2V0KHllYXIsIGRvdywgZG95KSxcbiAgICAgICAgICAgIHdlZWtPZmZzZXROZXh0ID0gZmlyc3RXZWVrT2Zmc2V0KHllYXIgKyAxLCBkb3csIGRveSk7XG4gICAgICAgIHJldHVybiAoZGF5c0luWWVhcih5ZWFyKSAtIHdlZWtPZmZzZXQgKyB3ZWVrT2Zmc2V0TmV4dCkgLyA3O1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCd3JywgWyd3dycsIDJdLCAnd28nLCAnd2VlaycpO1xuICAgIGFkZEZvcm1hdFRva2VuKCdXJywgWydXVycsIDJdLCAnV28nLCAnaXNvV2VlaycpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCd3ZWVrJywgJ3cnKTtcbiAgICBhZGRVbml0QWxpYXMoJ2lzb1dlZWsnLCAnVycpO1xuXG4gICAgLy8gUFJJT1JJVElFU1xuXG4gICAgYWRkVW5pdFByaW9yaXR5KCd3ZWVrJywgNSk7XG4gICAgYWRkVW5pdFByaW9yaXR5KCdpc29XZWVrJywgNSk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCd3JywgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCd3dycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcbiAgICBhZGRSZWdleFRva2VuKCdXJywgbWF0Y2gxdG8yKTtcbiAgICBhZGRSZWdleFRva2VuKCdXVycsIG1hdGNoMXRvMiwgbWF0Y2gyKTtcblxuICAgIGFkZFdlZWtQYXJzZVRva2VuKFsndycsICd3dycsICdXJywgJ1dXJ10sIGZ1bmN0aW9uIChcbiAgICAgICAgaW5wdXQsXG4gICAgICAgIHdlZWssXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgdG9rZW5cbiAgICApIHtcbiAgICAgICAgd2Vla1t0b2tlbi5zdWJzdHIoMCwgMSldID0gdG9JbnQoaW5wdXQpO1xuICAgIH0pO1xuXG4gICAgLy8gSEVMUEVSU1xuXG4gICAgLy8gTE9DQUxFU1xuXG4gICAgZnVuY3Rpb24gbG9jYWxlV2Vlayhtb20pIHtcbiAgICAgICAgcmV0dXJuIHdlZWtPZlllYXIobW9tLCB0aGlzLl93ZWVrLmRvdywgdGhpcy5fd2Vlay5kb3kpLndlZWs7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb2NhbGVXZWVrID0ge1xuICAgICAgICBkb3c6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICBkb3k6IDYsIC8vIFRoZSB3ZWVrIHRoYXQgY29udGFpbnMgSmFuIDZ0aCBpcyB0aGUgZmlyc3Qgd2VlayBvZiB0aGUgeWVhci5cbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gbG9jYWxlRmlyc3REYXlPZldlZWsoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl93ZWVrLmRvdztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVGaXJzdERheU9mWWVhcigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWsuZG95O1xuICAgIH1cblxuICAgIC8vIE1PTUVOVFNcblxuICAgIGZ1bmN0aW9uIGdldFNldFdlZWsoaW5wdXQpIHtcbiAgICAgICAgdmFyIHdlZWsgPSB0aGlzLmxvY2FsZURhdGEoKS53ZWVrKHRoaXMpO1xuICAgICAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IHdlZWsgOiB0aGlzLmFkZCgoaW5wdXQgLSB3ZWVrKSAqIDcsICdkJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0SVNPV2VlayhpbnB1dCkge1xuICAgICAgICB2YXIgd2VlayA9IHdlZWtPZlllYXIodGhpcywgMSwgNCkud2VlaztcbiAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB3ZWVrIDogdGhpcy5hZGQoKGlucHV0IC0gd2VlaykgKiA3LCAnZCcpO1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdkJywgMCwgJ2RvJywgJ2RheScpO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ2RkJywgMCwgMCwgZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkud2Vla2RheXNNaW4odGhpcywgZm9ybWF0KTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdkZGQnLCAwLCAwLCBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS53ZWVrZGF5c1Nob3J0KHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignZGRkZCcsIDAsIDAsIGZ1bmN0aW9uIChmb3JtYXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLndlZWtkYXlzKHRoaXMsIGZvcm1hdCk7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignZScsIDAsIDAsICd3ZWVrZGF5Jyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ0UnLCAwLCAwLCAnaXNvV2Vla2RheScpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCdkYXknLCAnZCcpO1xuICAgIGFkZFVuaXRBbGlhcygnd2Vla2RheScsICdlJyk7XG4gICAgYWRkVW5pdEFsaWFzKCdpc29XZWVrZGF5JywgJ0UnKTtcblxuICAgIC8vIFBSSU9SSVRZXG4gICAgYWRkVW5pdFByaW9yaXR5KCdkYXknLCAxMSk7XG4gICAgYWRkVW5pdFByaW9yaXR5KCd3ZWVrZGF5JywgMTEpO1xuICAgIGFkZFVuaXRQcmlvcml0eSgnaXNvV2Vla2RheScsIDExKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ2QnLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2UnLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0UnLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2RkJywgZnVuY3Rpb24gKGlzU3RyaWN0LCBsb2NhbGUpIHtcbiAgICAgICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c01pblJlZ2V4KGlzU3RyaWN0KTtcbiAgICB9KTtcbiAgICBhZGRSZWdleFRva2VuKCdkZGQnLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLndlZWtkYXlzU2hvcnRSZWdleChpc1N0cmljdCk7XG4gICAgfSk7XG4gICAgYWRkUmVnZXhUb2tlbignZGRkZCcsIGZ1bmN0aW9uIChpc1N0cmljdCwgbG9jYWxlKSB7XG4gICAgICAgIHJldHVybiBsb2NhbGUud2Vla2RheXNSZWdleChpc1N0cmljdCk7XG4gICAgfSk7XG5cbiAgICBhZGRXZWVrUGFyc2VUb2tlbihbJ2RkJywgJ2RkZCcsICdkZGRkJ10sIGZ1bmN0aW9uIChpbnB1dCwgd2VlaywgY29uZmlnLCB0b2tlbikge1xuICAgICAgICB2YXIgd2Vla2RheSA9IGNvbmZpZy5fbG9jYWxlLndlZWtkYXlzUGFyc2UoaW5wdXQsIHRva2VuLCBjb25maWcuX3N0cmljdCk7XG4gICAgICAgIC8vIGlmIHdlIGRpZG4ndCBnZXQgYSB3ZWVrZGF5IG5hbWUsIG1hcmsgdGhlIGRhdGUgYXMgaW52YWxpZFxuICAgICAgICBpZiAod2Vla2RheSAhPSBudWxsKSB7XG4gICAgICAgICAgICB3ZWVrLmQgPSB3ZWVrZGF5O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuaW52YWxpZFdlZWtkYXkgPSBpbnB1dDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgYWRkV2Vla1BhcnNlVG9rZW4oWydkJywgJ2UnLCAnRSddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICAgICAgd2Vla1t0b2tlbl0gPSB0b0ludChpbnB1dCk7XG4gICAgfSk7XG5cbiAgICAvLyBIRUxQRVJTXG5cbiAgICBmdW5jdGlvbiBwYXJzZVdlZWtkYXkoaW5wdXQsIGxvY2FsZSkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpc05hTihpbnB1dCkpIHtcbiAgICAgICAgICAgIHJldHVybiBwYXJzZUludChpbnB1dCwgMTApO1xuICAgICAgICB9XG5cbiAgICAgICAgaW5wdXQgPSBsb2NhbGUud2Vla2RheXNQYXJzZShpbnB1dCk7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzZUlzb1dlZWtkYXkoaW5wdXQsIGxvY2FsZSkge1xuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgcmV0dXJuIGxvY2FsZS53ZWVrZGF5c1BhcnNlKGlucHV0KSAlIDcgfHwgNztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNOYU4oaW5wdXQpID8gbnVsbCA6IGlucHV0O1xuICAgIH1cblxuICAgIC8vIExPQ0FMRVNcbiAgICBmdW5jdGlvbiBzaGlmdFdlZWtkYXlzKHdzLCBuKSB7XG4gICAgICAgIHJldHVybiB3cy5zbGljZShuLCA3KS5jb25jYXQod3Muc2xpY2UoMCwgbikpO1xuICAgIH1cblxuICAgIHZhciBkZWZhdWx0TG9jYWxlV2Vla2RheXMgPSAnU3VuZGF5X01vbmRheV9UdWVzZGF5X1dlZG5lc2RheV9UaHVyc2RheV9GcmlkYXlfU2F0dXJkYXknLnNwbGl0KFxuICAgICAgICAgICAgJ18nXG4gICAgICAgICksXG4gICAgICAgIGRlZmF1bHRMb2NhbGVXZWVrZGF5c1Nob3J0ID0gJ1N1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdCcuc3BsaXQoJ18nKSxcbiAgICAgICAgZGVmYXVsdExvY2FsZVdlZWtkYXlzTWluID0gJ1N1X01vX1R1X1dlX1RoX0ZyX1NhJy5zcGxpdCgnXycpLFxuICAgICAgICBkZWZhdWx0V2Vla2RheXNSZWdleCA9IG1hdGNoV29yZCxcbiAgICAgICAgZGVmYXVsdFdlZWtkYXlzU2hvcnRSZWdleCA9IG1hdGNoV29yZCxcbiAgICAgICAgZGVmYXVsdFdlZWtkYXlzTWluUmVnZXggPSBtYXRjaFdvcmQ7XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVXZWVrZGF5cyhtLCBmb3JtYXQpIHtcbiAgICAgICAgdmFyIHdlZWtkYXlzID0gaXNBcnJheSh0aGlzLl93ZWVrZGF5cylcbiAgICAgICAgICAgID8gdGhpcy5fd2Vla2RheXNcbiAgICAgICAgICAgIDogdGhpcy5fd2Vla2RheXNbXG4gICAgICAgICAgICAgICAgICBtICYmIG0gIT09IHRydWUgJiYgdGhpcy5fd2Vla2RheXMuaXNGb3JtYXQudGVzdChmb3JtYXQpXG4gICAgICAgICAgICAgICAgICAgICAgPyAnZm9ybWF0J1xuICAgICAgICAgICAgICAgICAgICAgIDogJ3N0YW5kYWxvbmUnXG4gICAgICAgICAgICAgIF07XG4gICAgICAgIHJldHVybiBtID09PSB0cnVlXG4gICAgICAgICAgICA/IHNoaWZ0V2Vla2RheXMod2Vla2RheXMsIHRoaXMuX3dlZWsuZG93KVxuICAgICAgICAgICAgOiBtXG4gICAgICAgICAgICA/IHdlZWtkYXlzW20uZGF5KCldXG4gICAgICAgICAgICA6IHdlZWtkYXlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvY2FsZVdlZWtkYXlzU2hvcnQobSkge1xuICAgICAgICByZXR1cm4gbSA9PT0gdHJ1ZVxuICAgICAgICAgICAgPyBzaGlmdFdlZWtkYXlzKHRoaXMuX3dlZWtkYXlzU2hvcnQsIHRoaXMuX3dlZWsuZG93KVxuICAgICAgICAgICAgOiBtXG4gICAgICAgICAgICA/IHRoaXMuX3dlZWtkYXlzU2hvcnRbbS5kYXkoKV1cbiAgICAgICAgICAgIDogdGhpcy5fd2Vla2RheXNTaG9ydDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVXZWVrZGF5c01pbihtKSB7XG4gICAgICAgIHJldHVybiBtID09PSB0cnVlXG4gICAgICAgICAgICA/IHNoaWZ0V2Vla2RheXModGhpcy5fd2Vla2RheXNNaW4sIHRoaXMuX3dlZWsuZG93KVxuICAgICAgICAgICAgOiBtXG4gICAgICAgICAgICA/IHRoaXMuX3dlZWtkYXlzTWluW20uZGF5KCldXG4gICAgICAgICAgICA6IHRoaXMuX3dlZWtkYXlzTWluO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGhhbmRsZVN0cmljdFBhcnNlJDEod2Vla2RheU5hbWUsIGZvcm1hdCwgc3RyaWN0KSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgaWksXG4gICAgICAgICAgICBtb20sXG4gICAgICAgICAgICBsbGMgPSB3ZWVrZGF5TmFtZS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICBpZiAoIXRoaXMuX3dlZWtkYXlzUGFyc2UpIHtcbiAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSA9IFtdO1xuICAgICAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZSA9IFtdO1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgKytpKSB7XG4gICAgICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCAxXSkuZGF5KGkpO1xuICAgICAgICAgICAgICAgIHRoaXMuX21pbldlZWtkYXlzUGFyc2VbaV0gPSB0aGlzLndlZWtkYXlzTWluKFxuICAgICAgICAgICAgICAgICAgICBtb20sXG4gICAgICAgICAgICAgICAgICAgICcnXG4gICAgICAgICAgICAgICAgKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZVtpXSA9IHRoaXMud2Vla2RheXNTaG9ydChcbiAgICAgICAgICAgICAgICAgICAgbW9tLFxuICAgICAgICAgICAgICAgICAgICAnJ1xuICAgICAgICAgICAgICAgICkudG9Mb2NhbGVMb3dlckNhc2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1BhcnNlW2ldID0gdGhpcy53ZWVrZGF5cyhtb20sICcnKS50b0xvY2FsZUxvd2VyQ2FzZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0cmljdCkge1xuICAgICAgICAgICAgaWYgKGZvcm1hdCA9PT0gJ2RkZGQnKSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fd2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICdkZGQnKSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGlpICE9PSAtMSA/IGlpIDogbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChmb3JtYXQgPT09ICdkZGRkJykge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3dlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICBpZiAoaWkgIT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fbWluV2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQgPT09ICdkZGQnKSB7XG4gICAgICAgICAgICAgICAgaWkgPSBpbmRleE9mLmNhbGwodGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl93ZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIGlmIChpaSAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGlpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpaSA9IGluZGV4T2YuY2FsbCh0aGlzLl9taW5XZWVrZGF5c1BhcnNlLCBsbGMpO1xuICAgICAgICAgICAgICAgIHJldHVybiBpaSAhPT0gLTEgPyBpaSA6IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX21pbldlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3dlZWtkYXlzUGFyc2UsIGxsYyk7XG4gICAgICAgICAgICAgICAgaWYgKGlpICE9PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaWk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlpID0gaW5kZXhPZi5jYWxsKHRoaXMuX3Nob3J0V2Vla2RheXNQYXJzZSwgbGxjKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gaWkgIT09IC0xID8gaWkgOiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbG9jYWxlV2Vla2RheXNQYXJzZSh3ZWVrZGF5TmFtZSwgZm9ybWF0LCBzdHJpY3QpIHtcbiAgICAgICAgdmFyIGksIG1vbSwgcmVnZXg7XG5cbiAgICAgICAgaWYgKHRoaXMuX3dlZWtkYXlzUGFyc2VFeGFjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGhhbmRsZVN0cmljdFBhcnNlJDEuY2FsbCh0aGlzLCB3ZWVrZGF5TmFtZSwgZm9ybWF0LCBzdHJpY3QpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0aGlzLl93ZWVrZGF5c1BhcnNlKSB7XG4gICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1BhcnNlID0gW107XG4gICAgICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlID0gW107XG4gICAgICAgICAgICB0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuX2Z1bGxXZWVrZGF5c1BhcnNlID0gW107XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcblxuICAgICAgICAgICAgbW9tID0gY3JlYXRlVVRDKFsyMDAwLCAxXSkuZGF5KGkpO1xuICAgICAgICAgICAgaWYgKHN0cmljdCAmJiAhdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2VbaV0pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9mdWxsV2Vla2RheXNQYXJzZVtpXSA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAgICAgICAgICdeJyArIHRoaXMud2Vla2RheXMobW9tLCAnJykucmVwbGFjZSgnLicsICdcXFxcLj8nKSArICckJyxcbiAgICAgICAgICAgICAgICAgICAgJ2knXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zaG9ydFdlZWtkYXlzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgICAgICAgICAnXicgKyB0aGlzLndlZWtkYXlzU2hvcnQobW9tLCAnJykucmVwbGFjZSgnLicsICdcXFxcLj8nKSArICckJyxcbiAgICAgICAgICAgICAgICAgICAgJ2knXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9taW5XZWVrZGF5c1BhcnNlW2ldID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICAgICAgICAgJ14nICsgdGhpcy53ZWVrZGF5c01pbihtb20sICcnKS5yZXBsYWNlKCcuJywgJ1xcXFwuPycpICsgJyQnLFxuICAgICAgICAgICAgICAgICAgICAnaSdcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLl93ZWVrZGF5c1BhcnNlW2ldKSB7XG4gICAgICAgICAgICAgICAgcmVnZXggPVxuICAgICAgICAgICAgICAgICAgICAnXicgK1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndlZWtkYXlzKG1vbSwgJycpICtcbiAgICAgICAgICAgICAgICAgICAgJ3xeJyArXG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2Vla2RheXNTaG9ydChtb20sICcnKSArXG4gICAgICAgICAgICAgICAgICAgICd8XicgK1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpO1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2VbaV0gPSBuZXcgUmVnRXhwKHJlZ2V4LnJlcGxhY2UoJy4nLCAnJyksICdpJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyB0ZXN0IHRoZSByZWdleFxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIHN0cmljdCAmJlxuICAgICAgICAgICAgICAgIGZvcm1hdCA9PT0gJ2RkZGQnICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fZnVsbFdlZWtkYXlzUGFyc2VbaV0udGVzdCh3ZWVrZGF5TmFtZSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICAgICAgICBzdHJpY3QgJiZcbiAgICAgICAgICAgICAgICBmb3JtYXQgPT09ICdkZGQnICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fc2hvcnRXZWVrZGF5c1BhcnNlW2ldLnRlc3Qod2Vla2RheU5hbWUpXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgICAgICAgICAgc3RyaWN0ICYmXG4gICAgICAgICAgICAgICAgZm9ybWF0ID09PSAnZGQnICYmXG4gICAgICAgICAgICAgICAgdGhpcy5fbWluV2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCFzdHJpY3QgJiYgdGhpcy5fd2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgZnVuY3Rpb24gZ2V0U2V0RGF5T2ZXZWVrKGlucHV0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsID8gdGhpcyA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZGF5ID0gdGhpcy5faXNVVEMgPyB0aGlzLl9kLmdldFVUQ0RheSgpIDogdGhpcy5fZC5nZXREYXkoKTtcbiAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlucHV0ID0gcGFyc2VXZWVrZGF5KGlucHV0LCB0aGlzLmxvY2FsZURhdGEoKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoaW5wdXQgLSBkYXksICdkJyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gZGF5O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0TG9jYWxlRGF5T2ZXZWVrKGlucHV0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsID8gdGhpcyA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgd2Vla2RheSA9ICh0aGlzLmRheSgpICsgNyAtIHRoaXMubG9jYWxlRGF0YSgpLl93ZWVrLmRvdykgJSA3O1xuICAgICAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IHdlZWtkYXkgOiB0aGlzLmFkZChpbnB1dCAtIHdlZWtkYXksICdkJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0SVNPRGF5T2ZXZWVrKGlucHV0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsID8gdGhpcyA6IE5hTjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGJlaGF2ZXMgdGhlIHNhbWUgYXMgbW9tZW50I2RheSBleGNlcHRcbiAgICAgICAgLy8gYXMgYSBnZXR0ZXIsIHJldHVybnMgNyBpbnN0ZWFkIG9mIDAgKDEtNyByYW5nZSBpbnN0ZWFkIG9mIDAtNilcbiAgICAgICAgLy8gYXMgYSBzZXR0ZXIsIHN1bmRheSBzaG91bGQgYmVsb25nIHRvIHRoZSBwcmV2aW91cyB3ZWVrLlxuXG4gICAgICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgICAgICB2YXIgd2Vla2RheSA9IHBhcnNlSXNvV2Vla2RheShpbnB1dCwgdGhpcy5sb2NhbGVEYXRhKCkpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF5KHRoaXMuZGF5KCkgJSA3ID8gd2Vla2RheSA6IHdlZWtkYXkgLSA3KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRheSgpIHx8IDc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB3ZWVrZGF5c1JlZ2V4KGlzU3RyaWN0KSB7XG4gICAgICAgIGlmICh0aGlzLl93ZWVrZGF5c1BhcnNlRXhhY3QpIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzUmVnZXgnKSkge1xuICAgICAgICAgICAgICAgIGNvbXB1dGVXZWVrZGF5c1BhcnNlLmNhbGwodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNTdHJpY3QpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzUmVnZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl93ZWVrZGF5c1JlZ2V4ID0gZGVmYXVsdFdlZWtkYXlzUmVnZXg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleCAmJiBpc1N0cmljdFxuICAgICAgICAgICAgICAgID8gdGhpcy5fd2Vla2RheXNTdHJpY3RSZWdleFxuICAgICAgICAgICAgICAgIDogdGhpcy5fd2Vla2RheXNSZWdleDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHdlZWtkYXlzU2hvcnRSZWdleChpc1N0cmljdCkge1xuICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU2hvcnRTdHJpY3RSZWdleDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzU2hvcnRSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX3dlZWtkYXlzU2hvcnRSZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4ID0gZGVmYXVsdFdlZWtkYXlzU2hvcnRSZWdleDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggJiYgaXNTdHJpY3RcbiAgICAgICAgICAgICAgICA/IHRoaXMuX3dlZWtkYXlzU2hvcnRTdHJpY3RSZWdleFxuICAgICAgICAgICAgICAgIDogdGhpcy5fd2Vla2RheXNTaG9ydFJlZ2V4O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gd2Vla2RheXNNaW5SZWdleChpc1N0cmljdCkge1xuICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZUV4YWN0KSB7XG4gICAgICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ193ZWVrZGF5c1JlZ2V4JykpIHtcbiAgICAgICAgICAgICAgICBjb21wdXRlV2Vla2RheXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXg7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl93ZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKCFoYXNPd25Qcm9wKHRoaXMsICdfd2Vla2RheXNNaW5SZWdleCcpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNNaW5SZWdleCA9IGRlZmF1bHRXZWVrZGF5c01pblJlZ2V4O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXggJiYgaXNTdHJpY3RcbiAgICAgICAgICAgICAgICA/IHRoaXMuX3dlZWtkYXlzTWluU3RyaWN0UmVnZXhcbiAgICAgICAgICAgICAgICA6IHRoaXMuX3dlZWtkYXlzTWluUmVnZXg7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb21wdXRlV2Vla2RheXNQYXJzZSgpIHtcbiAgICAgICAgZnVuY3Rpb24gY21wTGVuUmV2KGEsIGIpIHtcbiAgICAgICAgICAgIHJldHVybiBiLmxlbmd0aCAtIGEubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIG1pblBpZWNlcyA9IFtdLFxuICAgICAgICAgICAgc2hvcnRQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIGxvbmdQaWVjZXMgPSBbXSxcbiAgICAgICAgICAgIG1peGVkUGllY2VzID0gW10sXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgbW9tLFxuICAgICAgICAgICAgbWlucCxcbiAgICAgICAgICAgIHNob3J0cCxcbiAgICAgICAgICAgIGxvbmdwO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcbiAgICAgICAgICAgIG1vbSA9IGNyZWF0ZVVUQyhbMjAwMCwgMV0pLmRheShpKTtcbiAgICAgICAgICAgIG1pbnAgPSByZWdleEVzY2FwZSh0aGlzLndlZWtkYXlzTWluKG1vbSwgJycpKTtcbiAgICAgICAgICAgIHNob3J0cCA9IHJlZ2V4RXNjYXBlKHRoaXMud2Vla2RheXNTaG9ydChtb20sICcnKSk7XG4gICAgICAgICAgICBsb25ncCA9IHJlZ2V4RXNjYXBlKHRoaXMud2Vla2RheXMobW9tLCAnJykpO1xuICAgICAgICAgICAgbWluUGllY2VzLnB1c2gobWlucCk7XG4gICAgICAgICAgICBzaG9ydFBpZWNlcy5wdXNoKHNob3J0cCk7XG4gICAgICAgICAgICBsb25nUGllY2VzLnB1c2gobG9uZ3ApO1xuICAgICAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChtaW5wKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2goc2hvcnRwKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2gobG9uZ3ApO1xuICAgICAgICB9XG4gICAgICAgIC8vIFNvcnRpbmcgbWFrZXMgc3VyZSBpZiBvbmUgd2Vla2RheSAob3IgYWJicikgaXMgYSBwcmVmaXggb2YgYW5vdGhlciBpdFxuICAgICAgICAvLyB3aWxsIG1hdGNoIHRoZSBsb25nZXIgcGllY2UuXG4gICAgICAgIG1pblBpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIHNob3J0UGllY2VzLnNvcnQoY21wTGVuUmV2KTtcbiAgICAgICAgbG9uZ1BpZWNlcy5zb3J0KGNtcExlblJldik7XG4gICAgICAgIG1peGVkUGllY2VzLnNvcnQoY21wTGVuUmV2KTtcblxuICAgICAgICB0aGlzLl93ZWVrZGF5c1JlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgbWl4ZWRQaWVjZXMuam9pbignfCcpICsgJyknLCAnaScpO1xuICAgICAgICB0aGlzLl93ZWVrZGF5c1Nob3J0UmVnZXggPSB0aGlzLl93ZWVrZGF5c1JlZ2V4O1xuICAgICAgICB0aGlzLl93ZWVrZGF5c01pblJlZ2V4ID0gdGhpcy5fd2Vla2RheXNSZWdleDtcblxuICAgICAgICB0aGlzLl93ZWVrZGF5c1N0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICdeKCcgKyBsb25nUGllY2VzLmpvaW4oJ3wnKSArICcpJyxcbiAgICAgICAgICAgICdpJ1xuICAgICAgICApO1xuICAgICAgICB0aGlzLl93ZWVrZGF5c1Nob3J0U3RyaWN0UmVnZXggPSBuZXcgUmVnRXhwKFxuICAgICAgICAgICAgJ14oJyArIHNob3J0UGllY2VzLmpvaW4oJ3wnKSArICcpJyxcbiAgICAgICAgICAgICdpJ1xuICAgICAgICApO1xuICAgICAgICB0aGlzLl93ZWVrZGF5c01pblN0cmljdFJlZ2V4ID0gbmV3IFJlZ0V4cChcbiAgICAgICAgICAgICdeKCcgKyBtaW5QaWVjZXMuam9pbignfCcpICsgJyknLFxuICAgICAgICAgICAgJ2knXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgZnVuY3Rpb24gaEZvcm1hdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaG91cnMoKSAlIDEyIHx8IDEyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGtGb3JtYXQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmhvdXJzKCkgfHwgMjQ7XG4gICAgfVxuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ0gnLCBbJ0hIJywgMl0sIDAsICdob3VyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ2gnLCBbJ2hoJywgMl0sIDAsIGhGb3JtYXQpO1xuICAgIGFkZEZvcm1hdFRva2VuKCdrJywgWydraycsIDJdLCAwLCBrRm9ybWF0KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdobW0nLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAnJyArIGhGb3JtYXQuYXBwbHkodGhpcykgKyB6ZXJvRmlsbCh0aGlzLm1pbnV0ZXMoKSwgMik7XG4gICAgfSk7XG5cbiAgICBhZGRGb3JtYXRUb2tlbignaG1tc3MnLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAnJyArXG4gICAgICAgICAgICBoRm9ybWF0LmFwcGx5KHRoaXMpICtcbiAgICAgICAgICAgIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKSArXG4gICAgICAgICAgICB6ZXJvRmlsbCh0aGlzLnNlY29uZHMoKSwgMilcbiAgICAgICAgKTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdIbW0nLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiAnJyArIHRoaXMuaG91cnMoKSArIHplcm9GaWxsKHRoaXMubWludXRlcygpLCAyKTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCdIbW1zcycsIDAsIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICcnICtcbiAgICAgICAgICAgIHRoaXMuaG91cnMoKSArXG4gICAgICAgICAgICB6ZXJvRmlsbCh0aGlzLm1pbnV0ZXMoKSwgMikgK1xuICAgICAgICAgICAgemVyb0ZpbGwodGhpcy5zZWNvbmRzKCksIDIpXG4gICAgICAgICk7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBtZXJpZGllbSh0b2tlbiwgbG93ZXJjYXNlKSB7XG4gICAgICAgIGFkZEZvcm1hdFRva2VuKHRva2VuLCAwLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkubWVyaWRpZW0oXG4gICAgICAgICAgICAgICAgdGhpcy5ob3VycygpLFxuICAgICAgICAgICAgICAgIHRoaXMubWludXRlcygpLFxuICAgICAgICAgICAgICAgIGxvd2VyY2FzZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgbWVyaWRpZW0oJ2EnLCB0cnVlKTtcbiAgICBtZXJpZGllbSgnQScsIGZhbHNlKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnaG91cicsICdoJyk7XG5cbiAgICAvLyBQUklPUklUWVxuICAgIGFkZFVuaXRQcmlvcml0eSgnaG91cicsIDEzKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGZ1bmN0aW9uIG1hdGNoTWVyaWRpZW0oaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLl9tZXJpZGllbVBhcnNlO1xuICAgIH1cblxuICAgIGFkZFJlZ2V4VG9rZW4oJ2EnLCBtYXRjaE1lcmlkaWVtKTtcbiAgICBhZGRSZWdleFRva2VuKCdBJywgbWF0Y2hNZXJpZGllbSk7XG4gICAgYWRkUmVnZXhUb2tlbignSCcsIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignaCcsIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignaycsIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignSEgnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbignaGgnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbigna2snLCBtYXRjaDF0bzIsIG1hdGNoMik7XG5cbiAgICBhZGRSZWdleFRva2VuKCdobW0nLCBtYXRjaDN0bzQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2htbXNzJywgbWF0Y2g1dG82KTtcbiAgICBhZGRSZWdleFRva2VuKCdIbW0nLCBtYXRjaDN0bzQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0htbXNzJywgbWF0Y2g1dG82KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydIJywgJ0hIJ10sIEhPVVIpO1xuICAgIGFkZFBhcnNlVG9rZW4oWydrJywgJ2trJ10sIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICB2YXIga0lucHV0ID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICBhcnJheVtIT1VSXSA9IGtJbnB1dCA9PT0gMjQgPyAwIDoga0lucHV0O1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oWydhJywgJ0EnXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZy5faXNQbSA9IGNvbmZpZy5fbG9jYWxlLmlzUE0oaW5wdXQpO1xuICAgICAgICBjb25maWcuX21lcmlkaWVtID0gaW5wdXQ7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbihbJ2gnLCAnaGgnXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID0gdHJ1ZTtcbiAgICB9KTtcbiAgICBhZGRQYXJzZVRva2VuKCdobW0nLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgdmFyIHBvcyA9IGlucHV0Lmxlbmd0aCAtIDI7XG4gICAgICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvcykpO1xuICAgICAgICBhcnJheVtNSU5VVEVdID0gdG9JbnQoaW5wdXQuc3Vic3RyKHBvcykpO1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID0gdHJ1ZTtcbiAgICB9KTtcbiAgICBhZGRQYXJzZVRva2VuKCdobW1zcycsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICB2YXIgcG9zMSA9IGlucHV0Lmxlbmd0aCAtIDQsXG4gICAgICAgICAgICBwb3MyID0gaW5wdXQubGVuZ3RoIC0gMjtcbiAgICAgICAgYXJyYXlbSE9VUl0gPSB0b0ludChpbnB1dC5zdWJzdHIoMCwgcG9zMSkpO1xuICAgICAgICBhcnJheVtNSU5VVEVdID0gdG9JbnQoaW5wdXQuc3Vic3RyKHBvczEsIDIpKTtcbiAgICAgICAgYXJyYXlbU0VDT05EXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MyKSk7XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmJpZ0hvdXIgPSB0cnVlO1xuICAgIH0pO1xuICAgIGFkZFBhcnNlVG9rZW4oJ0htbScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICB2YXIgcG9zID0gaW5wdXQubGVuZ3RoIC0gMjtcbiAgICAgICAgYXJyYXlbSE9VUl0gPSB0b0ludChpbnB1dC5zdWJzdHIoMCwgcG9zKSk7XG4gICAgICAgIGFycmF5W01JTlVURV0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zKSk7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbignSG1tc3MnLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgdmFyIHBvczEgPSBpbnB1dC5sZW5ndGggLSA0LFxuICAgICAgICAgICAgcG9zMiA9IGlucHV0Lmxlbmd0aCAtIDI7XG4gICAgICAgIGFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQuc3Vic3RyKDAsIHBvczEpKTtcbiAgICAgICAgYXJyYXlbTUlOVVRFXSA9IHRvSW50KGlucHV0LnN1YnN0cihwb3MxLCAyKSk7XG4gICAgICAgIGFycmF5W1NFQ09ORF0gPSB0b0ludChpbnB1dC5zdWJzdHIocG9zMikpO1xuICAgIH0pO1xuXG4gICAgLy8gTE9DQUxFU1xuXG4gICAgZnVuY3Rpb24gbG9jYWxlSXNQTShpbnB1dCkge1xuICAgICAgICAvLyBJRTggUXVpcmtzIE1vZGUgJiBJRTcgU3RhbmRhcmRzIE1vZGUgZG8gbm90IGFsbG93IGFjY2Vzc2luZyBzdHJpbmdzIGxpa2UgYXJyYXlzXG4gICAgICAgIC8vIFVzaW5nIGNoYXJBdCBzaG91bGQgYmUgbW9yZSBjb21wYXRpYmxlLlxuICAgICAgICByZXR1cm4gKGlucHV0ICsgJycpLnRvTG93ZXJDYXNlKCkuY2hhckF0KDApID09PSAncCc7XG4gICAgfVxuXG4gICAgdmFyIGRlZmF1bHRMb2NhbGVNZXJpZGllbVBhcnNlID0gL1thcF1cXC4/bT9cXC4/L2ksXG4gICAgICAgIC8vIFNldHRpbmcgdGhlIGhvdXIgc2hvdWxkIGtlZXAgdGhlIHRpbWUsIGJlY2F1c2UgdGhlIHVzZXIgZXhwbGljaXRseVxuICAgICAgICAvLyBzcGVjaWZpZWQgd2hpY2ggaG91ciB0aGV5IHdhbnQuIFNvIHRyeWluZyB0byBtYWludGFpbiB0aGUgc2FtZSBob3VyIChpblxuICAgICAgICAvLyBhIG5ldyB0aW1lem9uZSkgbWFrZXMgc2Vuc2UuIEFkZGluZy9zdWJ0cmFjdGluZyBob3VycyBkb2VzIG5vdCBmb2xsb3dcbiAgICAgICAgLy8gdGhpcyBydWxlLlxuICAgICAgICBnZXRTZXRIb3VyID0gbWFrZUdldFNldCgnSG91cnMnLCB0cnVlKTtcblxuICAgIGZ1bmN0aW9uIGxvY2FsZU1lcmlkaWVtKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgIGlmIChob3VycyA+IDExKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMb3dlciA/ICdwbScgOiAnUE0nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGlzTG93ZXIgPyAnYW0nIDogJ0FNJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBiYXNlQ29uZmlnID0ge1xuICAgICAgICBjYWxlbmRhcjogZGVmYXVsdENhbGVuZGFyLFxuICAgICAgICBsb25nRGF0ZUZvcm1hdDogZGVmYXVsdExvbmdEYXRlRm9ybWF0LFxuICAgICAgICBpbnZhbGlkRGF0ZTogZGVmYXVsdEludmFsaWREYXRlLFxuICAgICAgICBvcmRpbmFsOiBkZWZhdWx0T3JkaW5hbCxcbiAgICAgICAgZGF5T2ZNb250aE9yZGluYWxQYXJzZTogZGVmYXVsdERheU9mTW9udGhPcmRpbmFsUGFyc2UsXG4gICAgICAgIHJlbGF0aXZlVGltZTogZGVmYXVsdFJlbGF0aXZlVGltZSxcblxuICAgICAgICBtb250aHM6IGRlZmF1bHRMb2NhbGVNb250aHMsXG4gICAgICAgIG1vbnRoc1Nob3J0OiBkZWZhdWx0TG9jYWxlTW9udGhzU2hvcnQsXG5cbiAgICAgICAgd2VlazogZGVmYXVsdExvY2FsZVdlZWssXG5cbiAgICAgICAgd2Vla2RheXM6IGRlZmF1bHRMb2NhbGVXZWVrZGF5cyxcbiAgICAgICAgd2Vla2RheXNNaW46IGRlZmF1bHRMb2NhbGVXZWVrZGF5c01pbixcbiAgICAgICAgd2Vla2RheXNTaG9ydDogZGVmYXVsdExvY2FsZVdlZWtkYXlzU2hvcnQsXG5cbiAgICAgICAgbWVyaWRpZW1QYXJzZTogZGVmYXVsdExvY2FsZU1lcmlkaWVtUGFyc2UsXG4gICAgfTtcblxuICAgIC8vIGludGVybmFsIHN0b3JhZ2UgZm9yIGxvY2FsZSBjb25maWcgZmlsZXNcbiAgICB2YXIgbG9jYWxlcyA9IHt9LFxuICAgICAgICBsb2NhbGVGYW1pbGllcyA9IHt9LFxuICAgICAgICBnbG9iYWxMb2NhbGU7XG5cbiAgICBmdW5jdGlvbiBjb21tb25QcmVmaXgoYXJyMSwgYXJyMikge1xuICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgIG1pbmwgPSBNYXRoLm1pbihhcnIxLmxlbmd0aCwgYXJyMi5sZW5ndGgpO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbWlubDsgaSArPSAxKSB7XG4gICAgICAgICAgICBpZiAoYXJyMVtpXSAhPT0gYXJyMltpXSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtaW5sO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZUxvY2FsZShrZXkpIHtcbiAgICAgICAgcmV0dXJuIGtleSA/IGtleS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoJ18nLCAnLScpIDoga2V5O1xuICAgIH1cblxuICAgIC8vIHBpY2sgdGhlIGxvY2FsZSBmcm9tIHRoZSBhcnJheVxuICAgIC8vIHRyeSBbJ2VuLWF1JywgJ2VuLWdiJ10gYXMgJ2VuLWF1JywgJ2VuLWdiJywgJ2VuJywgYXMgaW4gbW92ZSB0aHJvdWdoIHRoZSBsaXN0IHRyeWluZyBlYWNoXG4gICAgLy8gc3Vic3RyaW5nIGZyb20gbW9zdCBzcGVjaWZpYyB0byBsZWFzdCwgYnV0IG1vdmUgdG8gdGhlIG5leHQgYXJyYXkgaXRlbSBpZiBpdCdzIGEgbW9yZSBzcGVjaWZpYyB2YXJpYW50IHRoYW4gdGhlIGN1cnJlbnQgcm9vdFxuICAgIGZ1bmN0aW9uIGNob29zZUxvY2FsZShuYW1lcykge1xuICAgICAgICB2YXIgaSA9IDAsXG4gICAgICAgICAgICBqLFxuICAgICAgICAgICAgbmV4dCxcbiAgICAgICAgICAgIGxvY2FsZSxcbiAgICAgICAgICAgIHNwbGl0O1xuXG4gICAgICAgIHdoaWxlIChpIDwgbmFtZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICBzcGxpdCA9IG5vcm1hbGl6ZUxvY2FsZShuYW1lc1tpXSkuc3BsaXQoJy0nKTtcbiAgICAgICAgICAgIGogPSBzcGxpdC5sZW5ndGg7XG4gICAgICAgICAgICBuZXh0ID0gbm9ybWFsaXplTG9jYWxlKG5hbWVzW2kgKyAxXSk7XG4gICAgICAgICAgICBuZXh0ID0gbmV4dCA/IG5leHQuc3BsaXQoJy0nKSA6IG51bGw7XG4gICAgICAgICAgICB3aGlsZSAoaiA+IDApIHtcbiAgICAgICAgICAgICAgICBsb2NhbGUgPSBsb2FkTG9jYWxlKHNwbGl0LnNsaWNlKDAsIGopLmpvaW4oJy0nKSk7XG4gICAgICAgICAgICAgICAgaWYgKGxvY2FsZSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbG9jYWxlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIG5leHQgJiZcbiAgICAgICAgICAgICAgICAgICAgbmV4dC5sZW5ndGggPj0gaiAmJlxuICAgICAgICAgICAgICAgICAgICBjb21tb25QcmVmaXgoc3BsaXQsIG5leHQpID49IGogLSAxXG4gICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vdGhlIG5leHQgYXJyYXkgaXRlbSBpcyBiZXR0ZXIgdGhhbiBhIHNoYWxsb3dlciBzdWJzdHJpbmcgb2YgdGhpcyBvbmVcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGotLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZ2xvYmFsTG9jYWxlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvYWRMb2NhbGUobmFtZSkge1xuICAgICAgICB2YXIgb2xkTG9jYWxlID0gbnVsbCxcbiAgICAgICAgICAgIGFsaWFzZWRSZXF1aXJlO1xuICAgICAgICAvLyBUT0RPOiBGaW5kIGEgYmV0dGVyIHdheSB0byByZWdpc3RlciBhbmQgbG9hZCBhbGwgdGhlIGxvY2FsZXMgaW4gTm9kZVxuICAgICAgICBpZiAoXG4gICAgICAgICAgICBsb2NhbGVzW25hbWVdID09PSB1bmRlZmluZWQgJiZcbiAgICAgICAgICAgIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICBtb2R1bGUgJiZcbiAgICAgICAgICAgIG1vZHVsZS5leHBvcnRzXG4gICAgICAgICkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBvbGRMb2NhbGUgPSBnbG9iYWxMb2NhbGUuX2FiYnI7XG4gICAgICAgICAgICAgICAgYWxpYXNlZFJlcXVpcmUgPSByZXF1aXJlO1xuICAgICAgICAgICAgICAgIGFsaWFzZWRSZXF1aXJlKCcuL2xvY2FsZS8nICsgbmFtZSk7XG4gICAgICAgICAgICAgICAgZ2V0U2V0R2xvYmFsTG9jYWxlKG9sZExvY2FsZSk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgLy8gbWFyayBhcyBub3QgZm91bmQgdG8gYXZvaWQgcmVwZWF0aW5nIGV4cGVuc2l2ZSBmaWxlIHJlcXVpcmUgY2FsbCBjYXVzaW5nIGhpZ2ggQ1BVXG4gICAgICAgICAgICAgICAgLy8gd2hlbiB0cnlpbmcgdG8gZmluZCBlbi1VUywgZW5fVVMsIGVuLXVzIGZvciBldmVyeSBmb3JtYXQgY2FsbFxuICAgICAgICAgICAgICAgIGxvY2FsZXNbbmFtZV0gPSBudWxsOyAvLyBudWxsIG1lYW5zIG5vdCBmb3VuZFxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsb2NhbGVzW25hbWVdO1xuICAgIH1cblxuICAgIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBsb2FkIGxvY2FsZSBhbmQgdGhlbiBzZXQgdGhlIGdsb2JhbCBsb2NhbGUuICBJZlxuICAgIC8vIG5vIGFyZ3VtZW50cyBhcmUgcGFzc2VkIGluLCBpdCB3aWxsIHNpbXBseSByZXR1cm4gdGhlIGN1cnJlbnQgZ2xvYmFsXG4gICAgLy8gbG9jYWxlIGtleS5cbiAgICBmdW5jdGlvbiBnZXRTZXRHbG9iYWxMb2NhbGUoa2V5LCB2YWx1ZXMpIHtcbiAgICAgICAgdmFyIGRhdGE7XG4gICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgIGlmIChpc1VuZGVmaW5lZCh2YWx1ZXMpKSB7XG4gICAgICAgICAgICAgICAgZGF0YSA9IGdldExvY2FsZShrZXkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkYXRhID0gZGVmaW5lTG9jYWxlKGtleSwgdmFsdWVzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGRhdGEpIHtcbiAgICAgICAgICAgICAgICAvLyBtb21lbnQuZHVyYXRpb24uX2xvY2FsZSA9IG1vbWVudC5fbG9jYWxlID0gZGF0YTtcbiAgICAgICAgICAgICAgICBnbG9iYWxMb2NhbGUgPSBkYXRhO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGNvbnNvbGUgIT09ICd1bmRlZmluZWQnICYmIGNvbnNvbGUud2Fybikge1xuICAgICAgICAgICAgICAgICAgICAvL3dhcm4gdXNlciBpZiBhcmd1bWVudHMgYXJlIHBhc3NlZCBidXQgdGhlIGxvY2FsZSBjb3VsZCBub3QgYmUgc2V0XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICAgICAgICAgICAgICAgICdMb2NhbGUgJyArIGtleSArICcgbm90IGZvdW5kLiBEaWQgeW91IGZvcmdldCB0byBsb2FkIGl0PydcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZ2xvYmFsTG9jYWxlLl9hYmJyO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRlZmluZUxvY2FsZShuYW1lLCBjb25maWcpIHtcbiAgICAgICAgaWYgKGNvbmZpZyAhPT0gbnVsbCkge1xuICAgICAgICAgICAgdmFyIGxvY2FsZSxcbiAgICAgICAgICAgICAgICBwYXJlbnRDb25maWcgPSBiYXNlQ29uZmlnO1xuICAgICAgICAgICAgY29uZmlnLmFiYnIgPSBuYW1lO1xuICAgICAgICAgICAgaWYgKGxvY2FsZXNbbmFtZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRlcHJlY2F0ZVNpbXBsZShcbiAgICAgICAgICAgICAgICAgICAgJ2RlZmluZUxvY2FsZU92ZXJyaWRlJyxcbiAgICAgICAgICAgICAgICAgICAgJ3VzZSBtb21lbnQudXBkYXRlTG9jYWxlKGxvY2FsZU5hbWUsIGNvbmZpZykgdG8gY2hhbmdlICcgK1xuICAgICAgICAgICAgICAgICAgICAgICAgJ2FuIGV4aXN0aW5nIGxvY2FsZS4gbW9tZW50LmRlZmluZUxvY2FsZShsb2NhbGVOYW1lLCAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdjb25maWcpIHNob3VsZCBvbmx5IGJlIHVzZWQgZm9yIGNyZWF0aW5nIGEgbmV3IGxvY2FsZSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdTZWUgaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9kZWZpbmUtbG9jYWxlLyBmb3IgbW9yZSBpbmZvLidcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIHBhcmVudENvbmZpZyA9IGxvY2FsZXNbbmFtZV0uX2NvbmZpZztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29uZmlnLnBhcmVudExvY2FsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKGxvY2FsZXNbY29uZmlnLnBhcmVudExvY2FsZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBwYXJlbnRDb25maWcgPSBsb2NhbGVzW2NvbmZpZy5wYXJlbnRMb2NhbGVdLl9jb25maWc7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgbG9jYWxlID0gbG9hZExvY2FsZShjb25maWcucGFyZW50TG9jYWxlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxvY2FsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRDb25maWcgPSBsb2NhbGUuX2NvbmZpZztcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghbG9jYWxlRmFtaWxpZXNbY29uZmlnLnBhcmVudExvY2FsZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsb2NhbGVGYW1pbGllc1tjb25maWcucGFyZW50TG9jYWxlXSA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgbG9jYWxlRmFtaWxpZXNbY29uZmlnLnBhcmVudExvY2FsZV0ucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25maWc6IGNvbmZpZyxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsb2NhbGVzW25hbWVdID0gbmV3IExvY2FsZShtZXJnZUNvbmZpZ3MocGFyZW50Q29uZmlnLCBjb25maWcpKTtcblxuICAgICAgICAgICAgaWYgKGxvY2FsZUZhbWlsaWVzW25hbWVdKSB7XG4gICAgICAgICAgICAgICAgbG9jYWxlRmFtaWxpZXNbbmFtZV0uZm9yRWFjaChmdW5jdGlvbiAoeCkge1xuICAgICAgICAgICAgICAgICAgICBkZWZpbmVMb2NhbGUoeC5uYW1lLCB4LmNvbmZpZyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGJhY2t3YXJkcyBjb21wYXQgZm9yIG5vdzogYWxzbyBzZXQgdGhlIGxvY2FsZVxuICAgICAgICAgICAgLy8gbWFrZSBzdXJlIHdlIHNldCB0aGUgbG9jYWxlIEFGVEVSIGFsbCBjaGlsZCBsb2NhbGVzIGhhdmUgYmVlblxuICAgICAgICAgICAgLy8gY3JlYXRlZCwgc28gd2Ugd29uJ3QgZW5kIHVwIHdpdGggdGhlIGNoaWxkIGxvY2FsZSBzZXQuXG4gICAgICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG5cbiAgICAgICAgICAgIHJldHVybiBsb2NhbGVzW25hbWVdO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gdXNlZnVsIGZvciB0ZXN0aW5nXG4gICAgICAgICAgICBkZWxldGUgbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXBkYXRlTG9jYWxlKG5hbWUsIGNvbmZpZykge1xuICAgICAgICBpZiAoY29uZmlnICE9IG51bGwpIHtcbiAgICAgICAgICAgIHZhciBsb2NhbGUsXG4gICAgICAgICAgICAgICAgdG1wTG9jYWxlLFxuICAgICAgICAgICAgICAgIHBhcmVudENvbmZpZyA9IGJhc2VDb25maWc7XG5cbiAgICAgICAgICAgIGlmIChsb2NhbGVzW25hbWVdICE9IG51bGwgJiYgbG9jYWxlc1tuYW1lXS5wYXJlbnRMb2NhbGUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBleGlzdGluZyBjaGlsZCBsb2NhbGUgaW4tcGxhY2UgdG8gYXZvaWQgbWVtb3J5LWxlYWtzXG4gICAgICAgICAgICAgICAgbG9jYWxlc1tuYW1lXS5zZXQobWVyZ2VDb25maWdzKGxvY2FsZXNbbmFtZV0uX2NvbmZpZywgY29uZmlnKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIE1FUkdFXG4gICAgICAgICAgICAgICAgdG1wTG9jYWxlID0gbG9hZExvY2FsZShuYW1lKTtcbiAgICAgICAgICAgICAgICBpZiAodG1wTG9jYWxlICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Q29uZmlnID0gdG1wTG9jYWxlLl9jb25maWc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbmZpZyA9IG1lcmdlQ29uZmlncyhwYXJlbnRDb25maWcsIGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgaWYgKHRtcExvY2FsZSA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIHVwZGF0ZUxvY2FsZSBpcyBjYWxsZWQgZm9yIGNyZWF0aW5nIGEgbmV3IGxvY2FsZVxuICAgICAgICAgICAgICAgICAgICAvLyBTZXQgYWJiciBzbyBpdCB3aWxsIGhhdmUgYSBuYW1lIChnZXR0ZXJzIHJldHVyblxuICAgICAgICAgICAgICAgICAgICAvLyB1bmRlZmluZWQgb3RoZXJ3aXNlKS5cbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLmFiYnIgPSBuYW1lO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsb2NhbGUgPSBuZXcgTG9jYWxlKGNvbmZpZyk7XG4gICAgICAgICAgICAgICAgbG9jYWxlLnBhcmVudExvY2FsZSA9IGxvY2FsZXNbbmFtZV07XG4gICAgICAgICAgICAgICAgbG9jYWxlc1tuYW1lXSA9IGxvY2FsZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gYmFja3dhcmRzIGNvbXBhdCBmb3Igbm93OiBhbHNvIHNldCB0aGUgbG9jYWxlXG4gICAgICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBwYXNzIG51bGwgZm9yIGNvbmZpZyB0byB1bnVwZGF0ZSwgdXNlZnVsIGZvciB0ZXN0c1xuICAgICAgICAgICAgaWYgKGxvY2FsZXNbbmFtZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGlmIChsb2NhbGVzW25hbWVdLnBhcmVudExvY2FsZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgICAgIGxvY2FsZXNbbmFtZV0gPSBsb2NhbGVzW25hbWVdLnBhcmVudExvY2FsZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgPT09IGdldFNldEdsb2JhbExvY2FsZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGUobmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGxvY2FsZXNbbmFtZV0gIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBkZWxldGUgbG9jYWxlc1tuYW1lXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGxvY2FsZXNbbmFtZV07XG4gICAgfVxuXG4gICAgLy8gcmV0dXJucyBsb2NhbGUgZGF0YVxuICAgIGZ1bmN0aW9uIGdldExvY2FsZShrZXkpIHtcbiAgICAgICAgdmFyIGxvY2FsZTtcblxuICAgICAgICBpZiAoa2V5ICYmIGtleS5fbG9jYWxlICYmIGtleS5fbG9jYWxlLl9hYmJyKSB7XG4gICAgICAgICAgICBrZXkgPSBrZXkuX2xvY2FsZS5fYWJicjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgha2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gZ2xvYmFsTG9jYWxlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpc0FycmF5KGtleSkpIHtcbiAgICAgICAgICAgIC8vc2hvcnQtY2lyY3VpdCBldmVyeXRoaW5nIGVsc2VcbiAgICAgICAgICAgIGxvY2FsZSA9IGxvYWRMb2NhbGUoa2V5KTtcbiAgICAgICAgICAgIGlmIChsb2NhbGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9jYWxlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAga2V5ID0gW2tleV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2hvb3NlTG9jYWxlKGtleSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdExvY2FsZXMoKSB7XG4gICAgICAgIHJldHVybiBrZXlzKGxvY2FsZXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNoZWNrT3ZlcmZsb3cobSkge1xuICAgICAgICB2YXIgb3ZlcmZsb3csXG4gICAgICAgICAgICBhID0gbS5fYTtcblxuICAgICAgICBpZiAoYSAmJiBnZXRQYXJzaW5nRmxhZ3MobSkub3ZlcmZsb3cgPT09IC0yKSB7XG4gICAgICAgICAgICBvdmVyZmxvdyA9XG4gICAgICAgICAgICAgICAgYVtNT05USF0gPCAwIHx8IGFbTU9OVEhdID4gMTFcbiAgICAgICAgICAgICAgICAgICAgPyBNT05USFxuICAgICAgICAgICAgICAgICAgICA6IGFbREFURV0gPCAxIHx8IGFbREFURV0gPiBkYXlzSW5Nb250aChhW1lFQVJdLCBhW01PTlRIXSlcbiAgICAgICAgICAgICAgICAgICAgPyBEQVRFXG4gICAgICAgICAgICAgICAgICAgIDogYVtIT1VSXSA8IDAgfHxcbiAgICAgICAgICAgICAgICAgICAgICBhW0hPVVJdID4gMjQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAoYVtIT1VSXSA9PT0gMjQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKGFbTUlOVVRFXSAhPT0gMCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYVtTRUNPTkRdICE9PSAwIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhW01JTExJU0VDT05EXSAhPT0gMCkpXG4gICAgICAgICAgICAgICAgICAgID8gSE9VUlxuICAgICAgICAgICAgICAgICAgICA6IGFbTUlOVVRFXSA8IDAgfHwgYVtNSU5VVEVdID4gNTlcbiAgICAgICAgICAgICAgICAgICAgPyBNSU5VVEVcbiAgICAgICAgICAgICAgICAgICAgOiBhW1NFQ09ORF0gPCAwIHx8IGFbU0VDT05EXSA+IDU5XG4gICAgICAgICAgICAgICAgICAgID8gU0VDT05EXG4gICAgICAgICAgICAgICAgICAgIDogYVtNSUxMSVNFQ09ORF0gPCAwIHx8IGFbTUlMTElTRUNPTkRdID4gOTk5XG4gICAgICAgICAgICAgICAgICAgID8gTUlMTElTRUNPTkRcbiAgICAgICAgICAgICAgICAgICAgOiAtMTtcblxuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhtKS5fb3ZlcmZsb3dEYXlPZlllYXIgJiZcbiAgICAgICAgICAgICAgICAob3ZlcmZsb3cgPCBZRUFSIHx8IG92ZXJmbG93ID4gREFURSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIG92ZXJmbG93ID0gREFURTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChnZXRQYXJzaW5nRmxhZ3MobSkuX292ZXJmbG93V2Vla3MgJiYgb3ZlcmZsb3cgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgb3ZlcmZsb3cgPSBXRUVLO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdldFBhcnNpbmdGbGFncyhtKS5fb3ZlcmZsb3dXZWVrZGF5ICYmIG92ZXJmbG93ID09PSAtMSkge1xuICAgICAgICAgICAgICAgIG92ZXJmbG93ID0gV0VFS0RBWTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKG0pLm92ZXJmbG93ID0gb3ZlcmZsb3c7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbTtcbiAgICB9XG5cbiAgICAvLyBpc28gODYwMSByZWdleFxuICAgIC8vIDAwMDAtMDAtMDAgMDAwMC1XMDAgb3IgMDAwMC1XMDAtMCArIFQgKyAwMCBvciAwMDowMCBvciAwMDowMDowMCBvciAwMDowMDowMC4wMDAgKyArMDA6MDAgb3IgKzAwMDAgb3IgKzAwKVxuICAgIHZhciBleHRlbmRlZElzb1JlZ2V4ID0gL15cXHMqKCg/OlsrLV1cXGR7Nn18XFxkezR9KS0oPzpcXGRcXGQtXFxkXFxkfFdcXGRcXGQtXFxkfFdcXGRcXGR8XFxkXFxkXFxkfFxcZFxcZCkpKD86KFR8ICkoXFxkXFxkKD86OlxcZFxcZCg/OjpcXGRcXGQoPzpbLixdXFxkKyk/KT8pPykoWystXVxcZFxcZCg/Ojo/XFxkXFxkKT98XFxzKlopPyk/JC8sXG4gICAgICAgIGJhc2ljSXNvUmVnZXggPSAvXlxccyooKD86WystXVxcZHs2fXxcXGR7NH0pKD86XFxkXFxkXFxkXFxkfFdcXGRcXGRcXGR8V1xcZFxcZHxcXGRcXGRcXGR8XFxkXFxkfCkpKD86KFR8ICkoXFxkXFxkKD86XFxkXFxkKD86XFxkXFxkKD86Wy4sXVxcZCspPyk/KT8pKFsrLV1cXGRcXGQoPzo6P1xcZFxcZCk/fFxccypaKT8pPyQvLFxuICAgICAgICB0elJlZ2V4ID0gL1p8WystXVxcZFxcZCg/Ojo/XFxkXFxkKT8vLFxuICAgICAgICBpc29EYXRlcyA9IFtcbiAgICAgICAgICAgIFsnWVlZWVlZLU1NLUREJywgL1srLV1cXGR7Nn0tXFxkXFxkLVxcZFxcZC9dLFxuICAgICAgICAgICAgWydZWVlZLU1NLUREJywgL1xcZHs0fS1cXGRcXGQtXFxkXFxkL10sXG4gICAgICAgICAgICBbJ0dHR0ctW1ddV1ctRScsIC9cXGR7NH0tV1xcZFxcZC1cXGQvXSxcbiAgICAgICAgICAgIFsnR0dHRy1bV11XVycsIC9cXGR7NH0tV1xcZFxcZC8sIGZhbHNlXSxcbiAgICAgICAgICAgIFsnWVlZWS1EREQnLCAvXFxkezR9LVxcZHszfS9dLFxuICAgICAgICAgICAgWydZWVlZLU1NJywgL1xcZHs0fS1cXGRcXGQvLCBmYWxzZV0sXG4gICAgICAgICAgICBbJ1lZWVlZWU1NREQnLCAvWystXVxcZHsxMH0vXSxcbiAgICAgICAgICAgIFsnWVlZWU1NREQnLCAvXFxkezh9L10sXG4gICAgICAgICAgICBbJ0dHR0dbV11XV0UnLCAvXFxkezR9V1xcZHszfS9dLFxuICAgICAgICAgICAgWydHR0dHW1ddV1cnLCAvXFxkezR9V1xcZHsyfS8sIGZhbHNlXSxcbiAgICAgICAgICAgIFsnWVlZWURERCcsIC9cXGR7N30vXSxcbiAgICAgICAgICAgIFsnWVlZWU1NJywgL1xcZHs2fS8sIGZhbHNlXSxcbiAgICAgICAgICAgIFsnWVlZWScsIC9cXGR7NH0vLCBmYWxzZV0sXG4gICAgICAgIF0sXG4gICAgICAgIC8vIGlzbyB0aW1lIGZvcm1hdHMgYW5kIHJlZ2V4ZXNcbiAgICAgICAgaXNvVGltZXMgPSBbXG4gICAgICAgICAgICBbJ0hIOm1tOnNzLlNTU1MnLCAvXFxkXFxkOlxcZFxcZDpcXGRcXGRcXC5cXGQrL10sXG4gICAgICAgICAgICBbJ0hIOm1tOnNzLFNTU1MnLCAvXFxkXFxkOlxcZFxcZDpcXGRcXGQsXFxkKy9dLFxuICAgICAgICAgICAgWydISDptbTpzcycsIC9cXGRcXGQ6XFxkXFxkOlxcZFxcZC9dLFxuICAgICAgICAgICAgWydISDptbScsIC9cXGRcXGQ6XFxkXFxkL10sXG4gICAgICAgICAgICBbJ0hIbW1zcy5TU1NTJywgL1xcZFxcZFxcZFxcZFxcZFxcZFxcLlxcZCsvXSxcbiAgICAgICAgICAgIFsnSEhtbXNzLFNTU1MnLCAvXFxkXFxkXFxkXFxkXFxkXFxkLFxcZCsvXSxcbiAgICAgICAgICAgIFsnSEhtbXNzJywgL1xcZFxcZFxcZFxcZFxcZFxcZC9dLFxuICAgICAgICAgICAgWydISG1tJywgL1xcZFxcZFxcZFxcZC9dLFxuICAgICAgICAgICAgWydISCcsIC9cXGRcXGQvXSxcbiAgICAgICAgXSxcbiAgICAgICAgYXNwTmV0SnNvblJlZ2V4ID0gL15cXC8/RGF0ZVxcKCgtP1xcZCspL2ksXG4gICAgICAgIC8vIFJGQyAyODIyIHJlZ2V4OiBGb3IgZGV0YWlscyBzZWUgaHR0cHM6Ly90b29scy5pZXRmLm9yZy9odG1sL3JmYzI4MjIjc2VjdGlvbi0zLjNcbiAgICAgICAgcmZjMjgyMiA9IC9eKD86KE1vbnxUdWV8V2VkfFRodXxGcml8U2F0fFN1biksP1xccyk/KFxcZHsxLDJ9KVxccyhKYW58RmVifE1hcnxBcHJ8TWF5fEp1bnxKdWx8QXVnfFNlcHxPY3R8Tm92fERlYylcXHMoXFxkezIsNH0pXFxzKFxcZFxcZCk6KFxcZFxcZCkoPzo6KFxcZFxcZCkpP1xccyg/OihVVHxHTVR8W0VDTVBdW1NEXVQpfChbWnpdKXwoWystXVxcZHs0fSkpJC8sXG4gICAgICAgIG9ic09mZnNldHMgPSB7XG4gICAgICAgICAgICBVVDogMCxcbiAgICAgICAgICAgIEdNVDogMCxcbiAgICAgICAgICAgIEVEVDogLTQgKiA2MCxcbiAgICAgICAgICAgIEVTVDogLTUgKiA2MCxcbiAgICAgICAgICAgIENEVDogLTUgKiA2MCxcbiAgICAgICAgICAgIENTVDogLTYgKiA2MCxcbiAgICAgICAgICAgIE1EVDogLTYgKiA2MCxcbiAgICAgICAgICAgIE1TVDogLTcgKiA2MCxcbiAgICAgICAgICAgIFBEVDogLTcgKiA2MCxcbiAgICAgICAgICAgIFBTVDogLTggKiA2MCxcbiAgICAgICAgfTtcblxuICAgIC8vIGRhdGUgZnJvbSBpc28gZm9ybWF0XG4gICAgZnVuY3Rpb24gY29uZmlnRnJvbUlTTyhjb25maWcpIHtcbiAgICAgICAgdmFyIGksXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgc3RyaW5nID0gY29uZmlnLl9pLFxuICAgICAgICAgICAgbWF0Y2ggPSBleHRlbmRlZElzb1JlZ2V4LmV4ZWMoc3RyaW5nKSB8fCBiYXNpY0lzb1JlZ2V4LmV4ZWMoc3RyaW5nKSxcbiAgICAgICAgICAgIGFsbG93VGltZSxcbiAgICAgICAgICAgIGRhdGVGb3JtYXQsXG4gICAgICAgICAgICB0aW1lRm9ybWF0LFxuICAgICAgICAgICAgdHpGb3JtYXQ7XG5cbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5pc28gPSB0cnVlO1xuXG4gICAgICAgICAgICBmb3IgKGkgPSAwLCBsID0gaXNvRGF0ZXMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlzb0RhdGVzW2ldWzFdLmV4ZWMobWF0Y2hbMV0pKSB7XG4gICAgICAgICAgICAgICAgICAgIGRhdGVGb3JtYXQgPSBpc29EYXRlc1tpXVswXTtcbiAgICAgICAgICAgICAgICAgICAgYWxsb3dUaW1lID0gaXNvRGF0ZXNbaV1bMl0gIT09IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGF0ZUZvcm1hdCA9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLl9pc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG1hdGNoWzNdKSB7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMCwgbCA9IGlzb1RpbWVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNvVGltZXNbaV1bMV0uZXhlYyhtYXRjaFszXSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIG1hdGNoWzJdIHNob3VsZCBiZSAnVCcgb3Igc3BhY2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVGb3JtYXQgPSAobWF0Y2hbMl0gfHwgJyAnKSArIGlzb1RpbWVzW2ldWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRpbWVGb3JtYXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghYWxsb3dUaW1lICYmIHRpbWVGb3JtYXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtYXRjaFs0XSkge1xuICAgICAgICAgICAgICAgIGlmICh0elJlZ2V4LmV4ZWMobWF0Y2hbNF0pKSB7XG4gICAgICAgICAgICAgICAgICAgIHR6Rm9ybWF0ID0gJ1onO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uZmlnLl9mID0gZGF0ZUZvcm1hdCArICh0aW1lRm9ybWF0IHx8ICcnKSArICh0ekZvcm1hdCB8fCAnJyk7XG4gICAgICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGV4dHJhY3RGcm9tUkZDMjgyMlN0cmluZ3MoXG4gICAgICAgIHllYXJTdHIsXG4gICAgICAgIG1vbnRoU3RyLFxuICAgICAgICBkYXlTdHIsXG4gICAgICAgIGhvdXJTdHIsXG4gICAgICAgIG1pbnV0ZVN0cixcbiAgICAgICAgc2Vjb25kU3RyXG4gICAgKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBbXG4gICAgICAgICAgICB1bnRydW5jYXRlWWVhcih5ZWFyU3RyKSxcbiAgICAgICAgICAgIGRlZmF1bHRMb2NhbGVNb250aHNTaG9ydC5pbmRleE9mKG1vbnRoU3RyKSxcbiAgICAgICAgICAgIHBhcnNlSW50KGRheVN0ciwgMTApLFxuICAgICAgICAgICAgcGFyc2VJbnQoaG91clN0ciwgMTApLFxuICAgICAgICAgICAgcGFyc2VJbnQobWludXRlU3RyLCAxMCksXG4gICAgICAgIF07XG5cbiAgICAgICAgaWYgKHNlY29uZFN0cikge1xuICAgICAgICAgICAgcmVzdWx0LnB1c2gocGFyc2VJbnQoc2Vjb25kU3RyLCAxMCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1bnRydW5jYXRlWWVhcih5ZWFyU3RyKSB7XG4gICAgICAgIHZhciB5ZWFyID0gcGFyc2VJbnQoeWVhclN0ciwgMTApO1xuICAgICAgICBpZiAoeWVhciA8PSA0OSkge1xuICAgICAgICAgICAgcmV0dXJuIDIwMDAgKyB5ZWFyO1xuICAgICAgICB9IGVsc2UgaWYgKHllYXIgPD0gOTk5KSB7XG4gICAgICAgICAgICByZXR1cm4gMTkwMCArIHllYXI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHllYXI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHJlcHJvY2Vzc1JGQzI4MjIocykge1xuICAgICAgICAvLyBSZW1vdmUgY29tbWVudHMgYW5kIGZvbGRpbmcgd2hpdGVzcGFjZSBhbmQgcmVwbGFjZSBtdWx0aXBsZS1zcGFjZXMgd2l0aCBhIHNpbmdsZSBzcGFjZVxuICAgICAgICByZXR1cm4gc1xuICAgICAgICAgICAgLnJlcGxhY2UoL1xcKFteKV0qXFwpfFtcXG5cXHRdL2csICcgJylcbiAgICAgICAgICAgIC5yZXBsYWNlKC8oXFxzXFxzKykvZywgJyAnKVxuICAgICAgICAgICAgLnJlcGxhY2UoL15cXHNcXHMqLywgJycpXG4gICAgICAgICAgICAucmVwbGFjZSgvXFxzXFxzKiQvLCAnJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2hlY2tXZWVrZGF5KHdlZWtkYXlTdHIsIHBhcnNlZElucHV0LCBjb25maWcpIHtcbiAgICAgICAgaWYgKHdlZWtkYXlTdHIpIHtcbiAgICAgICAgICAgIC8vIFRPRE86IFJlcGxhY2UgdGhlIHZhbmlsbGEgSlMgRGF0ZSBvYmplY3Qgd2l0aCBhbiBpbmRlcGVuZGVudCBkYXktb2Ytd2VlayBjaGVjay5cbiAgICAgICAgICAgIHZhciB3ZWVrZGF5UHJvdmlkZWQgPSBkZWZhdWx0TG9jYWxlV2Vla2RheXNTaG9ydC5pbmRleE9mKHdlZWtkYXlTdHIpLFxuICAgICAgICAgICAgICAgIHdlZWtkYXlBY3R1YWwgPSBuZXcgRGF0ZShcbiAgICAgICAgICAgICAgICAgICAgcGFyc2VkSW5wdXRbMF0sXG4gICAgICAgICAgICAgICAgICAgIHBhcnNlZElucHV0WzFdLFxuICAgICAgICAgICAgICAgICAgICBwYXJzZWRJbnB1dFsyXVxuICAgICAgICAgICAgICAgICkuZ2V0RGF5KCk7XG4gICAgICAgICAgICBpZiAod2Vla2RheVByb3ZpZGVkICE9PSB3ZWVrZGF5QWN0dWFsKSB7XG4gICAgICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykud2Vla2RheU1pc21hdGNoID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBjb25maWcuX2lzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2FsY3VsYXRlT2Zmc2V0KG9ic09mZnNldCwgbWlsaXRhcnlPZmZzZXQsIG51bU9mZnNldCkge1xuICAgICAgICBpZiAob2JzT2Zmc2V0KSB7XG4gICAgICAgICAgICByZXR1cm4gb2JzT2Zmc2V0c1tvYnNPZmZzZXRdO1xuICAgICAgICB9IGVsc2UgaWYgKG1pbGl0YXJ5T2Zmc2V0KSB7XG4gICAgICAgICAgICAvLyB0aGUgb25seSBhbGxvd2VkIG1pbGl0YXJ5IHR6IGlzIFpcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGhtID0gcGFyc2VJbnQobnVtT2Zmc2V0LCAxMCksXG4gICAgICAgICAgICAgICAgbSA9IGhtICUgMTAwLFxuICAgICAgICAgICAgICAgIGggPSAoaG0gLSBtKSAvIDEwMDtcbiAgICAgICAgICAgIHJldHVybiBoICogNjAgKyBtO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZGF0ZSBhbmQgdGltZSBmcm9tIHJlZiAyODIyIGZvcm1hdFxuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21SRkMyODIyKGNvbmZpZykge1xuICAgICAgICB2YXIgbWF0Y2ggPSByZmMyODIyLmV4ZWMocHJlcHJvY2Vzc1JGQzI4MjIoY29uZmlnLl9pKSksXG4gICAgICAgICAgICBwYXJzZWRBcnJheTtcbiAgICAgICAgaWYgKG1hdGNoKSB7XG4gICAgICAgICAgICBwYXJzZWRBcnJheSA9IGV4dHJhY3RGcm9tUkZDMjgyMlN0cmluZ3MoXG4gICAgICAgICAgICAgICAgbWF0Y2hbNF0sXG4gICAgICAgICAgICAgICAgbWF0Y2hbM10sXG4gICAgICAgICAgICAgICAgbWF0Y2hbMl0sXG4gICAgICAgICAgICAgICAgbWF0Y2hbNV0sXG4gICAgICAgICAgICAgICAgbWF0Y2hbNl0sXG4gICAgICAgICAgICAgICAgbWF0Y2hbN11cbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICBpZiAoIWNoZWNrV2Vla2RheShtYXRjaFsxXSwgcGFyc2VkQXJyYXksIGNvbmZpZykpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbmZpZy5fYSA9IHBhcnNlZEFycmF5O1xuICAgICAgICAgICAgY29uZmlnLl90em0gPSBjYWxjdWxhdGVPZmZzZXQobWF0Y2hbOF0sIG1hdGNoWzldLCBtYXRjaFsxMF0pO1xuXG4gICAgICAgICAgICBjb25maWcuX2QgPSBjcmVhdGVVVENEYXRlLmFwcGx5KG51bGwsIGNvbmZpZy5fYSk7XG4gICAgICAgICAgICBjb25maWcuX2Quc2V0VVRDTWludXRlcyhjb25maWcuX2QuZ2V0VVRDTWludXRlcygpIC0gY29uZmlnLl90em0pO1xuXG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5yZmMyODIyID0gdHJ1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gZGF0ZSBmcm9tIDEpIEFTUC5ORVQsIDIpIElTTywgMykgUkZDIDI4MjIgZm9ybWF0cywgb3IgNCkgb3B0aW9uYWwgZmFsbGJhY2sgaWYgcGFyc2luZyBpc24ndCBzdHJpY3RcbiAgICBmdW5jdGlvbiBjb25maWdGcm9tU3RyaW5nKGNvbmZpZykge1xuICAgICAgICB2YXIgbWF0Y2hlZCA9IGFzcE5ldEpzb25SZWdleC5leGVjKGNvbmZpZy5faSk7XG4gICAgICAgIGlmIChtYXRjaGVkICE9PSBudWxsKSB7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZSgrbWF0Y2hlZFsxXSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25maWdGcm9tSVNPKGNvbmZpZyk7XG4gICAgICAgIGlmIChjb25maWcuX2lzVmFsaWQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBkZWxldGUgY29uZmlnLl9pc1ZhbGlkO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uZmlnRnJvbVJGQzI4MjIoY29uZmlnKTtcbiAgICAgICAgaWYgKGNvbmZpZy5faXNWYWxpZCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGRlbGV0ZSBjb25maWcuX2lzVmFsaWQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnLl9zdHJpY3QpIHtcbiAgICAgICAgICAgIGNvbmZpZy5faXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gRmluYWwgYXR0ZW1wdCwgdXNlIElucHV0IEZhbGxiYWNrXG4gICAgICAgICAgICBob29rcy5jcmVhdGVGcm9tSW5wdXRGYWxsYmFjayhjb25maWcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgaG9va3MuY3JlYXRlRnJvbUlucHV0RmFsbGJhY2sgPSBkZXByZWNhdGUoXG4gICAgICAgICd2YWx1ZSBwcm92aWRlZCBpcyBub3QgaW4gYSByZWNvZ25pemVkIFJGQzI4MjIgb3IgSVNPIGZvcm1hdC4gbW9tZW50IGNvbnN0cnVjdGlvbiBmYWxscyBiYWNrIHRvIGpzIERhdGUoKSwgJyArXG4gICAgICAgICAgICAnd2hpY2ggaXMgbm90IHJlbGlhYmxlIGFjcm9zcyBhbGwgYnJvd3NlcnMgYW5kIHZlcnNpb25zLiBOb24gUkZDMjgyMi9JU08gZGF0ZSBmb3JtYXRzIGFyZSAnICtcbiAgICAgICAgICAgICdkaXNjb3VyYWdlZCBhbmQgd2lsbCBiZSByZW1vdmVkIGluIGFuIHVwY29taW5nIG1ham9yIHJlbGVhc2UuIFBsZWFzZSByZWZlciB0byAnICtcbiAgICAgICAgICAgICdodHRwOi8vbW9tZW50anMuY29tL2d1aWRlcy8jL3dhcm5pbmdzL2pzLWRhdGUvIGZvciBtb3JlIGluZm8uJyxcbiAgICAgICAgZnVuY3Rpb24gKGNvbmZpZykge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoY29uZmlnLl9pICsgKGNvbmZpZy5fdXNlVVRDID8gJyBVVEMnIDogJycpKTtcbiAgICAgICAgfVxuICAgICk7XG5cbiAgICAvLyBQaWNrIHRoZSBmaXJzdCBkZWZpbmVkIG9mIHR3byBvciB0aHJlZSBhcmd1bWVudHMuXG4gICAgZnVuY3Rpb24gZGVmYXVsdHMoYSwgYiwgYykge1xuICAgICAgICBpZiAoYSAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gYTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYiAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gYjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjdXJyZW50RGF0ZUFycmF5KGNvbmZpZykge1xuICAgICAgICAvLyBob29rcyBpcyBhY3R1YWxseSB0aGUgZXhwb3J0ZWQgbW9tZW50IG9iamVjdFxuICAgICAgICB2YXIgbm93VmFsdWUgPSBuZXcgRGF0ZShob29rcy5ub3coKSk7XG4gICAgICAgIGlmIChjb25maWcuX3VzZVVUQykge1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICBub3dWYWx1ZS5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICAgICAgICAgIG5vd1ZhbHVlLmdldFVUQ01vbnRoKCksXG4gICAgICAgICAgICAgICAgbm93VmFsdWUuZ2V0VVRDRGF0ZSgpLFxuICAgICAgICAgICAgXTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gW25vd1ZhbHVlLmdldEZ1bGxZZWFyKCksIG5vd1ZhbHVlLmdldE1vbnRoKCksIG5vd1ZhbHVlLmdldERhdGUoKV07XG4gICAgfVxuXG4gICAgLy8gY29udmVydCBhbiBhcnJheSB0byBhIGRhdGUuXG4gICAgLy8gdGhlIGFycmF5IHNob3VsZCBtaXJyb3IgdGhlIHBhcmFtZXRlcnMgYmVsb3dcbiAgICAvLyBub3RlOiBhbGwgdmFsdWVzIHBhc3QgdGhlIHllYXIgYXJlIG9wdGlvbmFsIGFuZCB3aWxsIGRlZmF1bHQgdG8gdGhlIGxvd2VzdCBwb3NzaWJsZSB2YWx1ZS5cbiAgICAvLyBbeWVhciwgbW9udGgsIGRheSAsIGhvdXIsIG1pbnV0ZSwgc2Vjb25kLCBtaWxsaXNlY29uZF1cbiAgICBmdW5jdGlvbiBjb25maWdGcm9tQXJyYXkoY29uZmlnKSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgZGF0ZSxcbiAgICAgICAgICAgIGlucHV0ID0gW10sXG4gICAgICAgICAgICBjdXJyZW50RGF0ZSxcbiAgICAgICAgICAgIGV4cGVjdGVkV2Vla2RheSxcbiAgICAgICAgICAgIHllYXJUb1VzZTtcblxuICAgICAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjdXJyZW50RGF0ZSA9IGN1cnJlbnREYXRlQXJyYXkoY29uZmlnKTtcblxuICAgICAgICAvL2NvbXB1dGUgZGF5IG9mIHRoZSB5ZWFyIGZyb20gd2Vla3MgYW5kIHdlZWtkYXlzXG4gICAgICAgIGlmIChjb25maWcuX3cgJiYgY29uZmlnLl9hW0RBVEVdID09IG51bGwgJiYgY29uZmlnLl9hW01PTlRIXSA9PSBudWxsKSB7XG4gICAgICAgICAgICBkYXlPZlllYXJGcm9tV2Vla0luZm8oY29uZmlnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vaWYgdGhlIGRheSBvZiB0aGUgeWVhciBpcyBzZXQsIGZpZ3VyZSBvdXQgd2hhdCBpdCBpc1xuICAgICAgICBpZiAoY29uZmlnLl9kYXlPZlllYXIgIT0gbnVsbCkge1xuICAgICAgICAgICAgeWVhclRvVXNlID0gZGVmYXVsdHMoY29uZmlnLl9hW1lFQVJdLCBjdXJyZW50RGF0ZVtZRUFSXSk7XG5cbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBjb25maWcuX2RheU9mWWVhciA+IGRheXNJblllYXIoeWVhclRvVXNlKSB8fFxuICAgICAgICAgICAgICAgIGNvbmZpZy5fZGF5T2ZZZWFyID09PSAwXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5fb3ZlcmZsb3dEYXlPZlllYXIgPSB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRlID0gY3JlYXRlVVRDRGF0ZSh5ZWFyVG9Vc2UsIDAsIGNvbmZpZy5fZGF5T2ZZZWFyKTtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtNT05USF0gPSBkYXRlLmdldFVUQ01vbnRoKCk7XG4gICAgICAgICAgICBjb25maWcuX2FbREFURV0gPSBkYXRlLmdldFVUQ0RhdGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlZmF1bHQgdG8gY3VycmVudCBkYXRlLlxuICAgICAgICAvLyAqIGlmIG5vIHllYXIsIG1vbnRoLCBkYXkgb2YgbW9udGggYXJlIGdpdmVuLCBkZWZhdWx0IHRvIHRvZGF5XG4gICAgICAgIC8vICogaWYgZGF5IG9mIG1vbnRoIGlzIGdpdmVuLCBkZWZhdWx0IG1vbnRoIGFuZCB5ZWFyXG4gICAgICAgIC8vICogaWYgbW9udGggaXMgZ2l2ZW4sIGRlZmF1bHQgb25seSB5ZWFyXG4gICAgICAgIC8vICogaWYgeWVhciBpcyBnaXZlbiwgZG9uJ3QgZGVmYXVsdCBhbnl0aGluZ1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMyAmJiBjb25maWcuX2FbaV0gPT0gbnVsbDsgKytpKSB7XG4gICAgICAgICAgICBjb25maWcuX2FbaV0gPSBpbnB1dFtpXSA9IGN1cnJlbnREYXRlW2ldO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gWmVybyBvdXQgd2hhdGV2ZXIgd2FzIG5vdCBkZWZhdWx0ZWQsIGluY2x1ZGluZyB0aW1lXG4gICAgICAgIGZvciAoOyBpIDwgNzsgaSsrKSB7XG4gICAgICAgICAgICBjb25maWcuX2FbaV0gPSBpbnB1dFtpXSA9XG4gICAgICAgICAgICAgICAgY29uZmlnLl9hW2ldID09IG51bGwgPyAoaSA9PT0gMiA/IDEgOiAwKSA6IGNvbmZpZy5fYVtpXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrIGZvciAyNDowMDowMC4wMDBcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgY29uZmlnLl9hW0hPVVJdID09PSAyNCAmJlxuICAgICAgICAgICAgY29uZmlnLl9hW01JTlVURV0gPT09IDAgJiZcbiAgICAgICAgICAgIGNvbmZpZy5fYVtTRUNPTkRdID09PSAwICYmXG4gICAgICAgICAgICBjb25maWcuX2FbTUlMTElTRUNPTkRdID09PSAwXG4gICAgICAgICkge1xuICAgICAgICAgICAgY29uZmlnLl9uZXh0RGF5ID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtIT1VSXSA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBjb25maWcuX2QgPSAoY29uZmlnLl91c2VVVEMgPyBjcmVhdGVVVENEYXRlIDogY3JlYXRlRGF0ZSkuYXBwbHkoXG4gICAgICAgICAgICBudWxsLFxuICAgICAgICAgICAgaW5wdXRcbiAgICAgICAgKTtcbiAgICAgICAgZXhwZWN0ZWRXZWVrZGF5ID0gY29uZmlnLl91c2VVVENcbiAgICAgICAgICAgID8gY29uZmlnLl9kLmdldFVUQ0RheSgpXG4gICAgICAgICAgICA6IGNvbmZpZy5fZC5nZXREYXkoKTtcblxuICAgICAgICAvLyBBcHBseSB0aW1lem9uZSBvZmZzZXQgZnJvbSBpbnB1dC4gVGhlIGFjdHVhbCB1dGNPZmZzZXQgY2FuIGJlIGNoYW5nZWRcbiAgICAgICAgLy8gd2l0aCBwYXJzZVpvbmUuXG4gICAgICAgIGlmIChjb25maWcuX3R6bSAhPSBudWxsKSB7XG4gICAgICAgICAgICBjb25maWcuX2Quc2V0VVRDTWludXRlcyhjb25maWcuX2QuZ2V0VVRDTWludXRlcygpIC0gY29uZmlnLl90em0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbmZpZy5fbmV4dERheSkge1xuICAgICAgICAgICAgY29uZmlnLl9hW0hPVVJdID0gMjQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBjaGVjayBmb3IgbWlzbWF0Y2hpbmcgZGF5IG9mIHdlZWtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgY29uZmlnLl93ICYmXG4gICAgICAgICAgICB0eXBlb2YgY29uZmlnLl93LmQgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICBjb25maWcuX3cuZCAhPT0gZXhwZWN0ZWRXZWVrZGF5XG4gICAgICAgICkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykud2Vla2RheU1pc21hdGNoID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRheU9mWWVhckZyb21XZWVrSW5mbyhjb25maWcpIHtcbiAgICAgICAgdmFyIHcsIHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSwgdGVtcCwgd2Vla2RheU92ZXJmbG93LCBjdXJXZWVrO1xuXG4gICAgICAgIHcgPSBjb25maWcuX3c7XG4gICAgICAgIGlmICh3LkdHICE9IG51bGwgfHwgdy5XICE9IG51bGwgfHwgdy5FICE9IG51bGwpIHtcbiAgICAgICAgICAgIGRvdyA9IDE7XG4gICAgICAgICAgICBkb3kgPSA0O1xuXG4gICAgICAgICAgICAvLyBUT0RPOiBXZSBuZWVkIHRvIHRha2UgdGhlIGN1cnJlbnQgaXNvV2Vla1llYXIsIGJ1dCB0aGF0IGRlcGVuZHMgb25cbiAgICAgICAgICAgIC8vIGhvdyB3ZSBpbnRlcnByZXQgbm93IChsb2NhbCwgdXRjLCBmaXhlZCBvZmZzZXQpLiBTbyBjcmVhdGVcbiAgICAgICAgICAgIC8vIGEgbm93IHZlcnNpb24gb2YgY3VycmVudCBjb25maWcgKHRha2UgbG9jYWwvdXRjL29mZnNldCBmbGFncywgYW5kXG4gICAgICAgICAgICAvLyBjcmVhdGUgbm93KS5cbiAgICAgICAgICAgIHdlZWtZZWFyID0gZGVmYXVsdHMoXG4gICAgICAgICAgICAgICAgdy5HRyxcbiAgICAgICAgICAgICAgICBjb25maWcuX2FbWUVBUl0sXG4gICAgICAgICAgICAgICAgd2Vla09mWWVhcihjcmVhdGVMb2NhbCgpLCAxLCA0KS55ZWFyXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgd2VlayA9IGRlZmF1bHRzKHcuVywgMSk7XG4gICAgICAgICAgICB3ZWVrZGF5ID0gZGVmYXVsdHMody5FLCAxKTtcbiAgICAgICAgICAgIGlmICh3ZWVrZGF5IDwgMSB8fCB3ZWVrZGF5ID4gNykge1xuICAgICAgICAgICAgICAgIHdlZWtkYXlPdmVyZmxvdyA9IHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkb3cgPSBjb25maWcuX2xvY2FsZS5fd2Vlay5kb3c7XG4gICAgICAgICAgICBkb3kgPSBjb25maWcuX2xvY2FsZS5fd2Vlay5kb3k7XG5cbiAgICAgICAgICAgIGN1cldlZWsgPSB3ZWVrT2ZZZWFyKGNyZWF0ZUxvY2FsKCksIGRvdywgZG95KTtcblxuICAgICAgICAgICAgd2Vla1llYXIgPSBkZWZhdWx0cyh3LmdnLCBjb25maWcuX2FbWUVBUl0sIGN1cldlZWsueWVhcik7XG5cbiAgICAgICAgICAgIC8vIERlZmF1bHQgdG8gY3VycmVudCB3ZWVrLlxuICAgICAgICAgICAgd2VlayA9IGRlZmF1bHRzKHcudywgY3VyV2Vlay53ZWVrKTtcblxuICAgICAgICAgICAgaWYgKHcuZCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgLy8gd2Vla2RheSAtLSBsb3cgZGF5IG51bWJlcnMgYXJlIGNvbnNpZGVyZWQgbmV4dCB3ZWVrXG4gICAgICAgICAgICAgICAgd2Vla2RheSA9IHcuZDtcbiAgICAgICAgICAgICAgICBpZiAod2Vla2RheSA8IDAgfHwgd2Vla2RheSA+IDYpIHtcbiAgICAgICAgICAgICAgICAgICAgd2Vla2RheU92ZXJmbG93ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHcuZSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgLy8gbG9jYWwgd2Vla2RheSAtLSBjb3VudGluZyBzdGFydHMgZnJvbSBiZWdpbm5pbmcgb2Ygd2Vla1xuICAgICAgICAgICAgICAgIHdlZWtkYXkgPSB3LmUgKyBkb3c7XG4gICAgICAgICAgICAgICAgaWYgKHcuZSA8IDAgfHwgdy5lID4gNikge1xuICAgICAgICAgICAgICAgICAgICB3ZWVrZGF5T3ZlcmZsb3cgPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gZGVmYXVsdCB0byBiZWdpbm5pbmcgb2Ygd2Vla1xuICAgICAgICAgICAgICAgIHdlZWtkYXkgPSBkb3c7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHdlZWsgPCAxIHx8IHdlZWsgPiB3ZWVrc0luWWVhcih3ZWVrWWVhciwgZG93LCBkb3kpKSB7XG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5fb3ZlcmZsb3dXZWVrcyA9IHRydWU7XG4gICAgICAgIH0gZWxzZSBpZiAod2Vla2RheU92ZXJmbG93ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLl9vdmVyZmxvd1dlZWtkYXkgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGVtcCA9IGRheU9mWWVhckZyb21XZWVrcyh3ZWVrWWVhciwgd2Vlaywgd2Vla2RheSwgZG93LCBkb3kpO1xuICAgICAgICAgICAgY29uZmlnLl9hW1lFQVJdID0gdGVtcC55ZWFyO1xuICAgICAgICAgICAgY29uZmlnLl9kYXlPZlllYXIgPSB0ZW1wLmRheU9mWWVhcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNvbnN0YW50IHRoYXQgcmVmZXJzIHRvIHRoZSBJU08gc3RhbmRhcmRcbiAgICBob29rcy5JU09fODYwMSA9IGZ1bmN0aW9uICgpIHt9O1xuXG4gICAgLy8gY29uc3RhbnQgdGhhdCByZWZlcnMgdG8gdGhlIFJGQyAyODIyIGZvcm1cbiAgICBob29rcy5SRkNfMjgyMiA9IGZ1bmN0aW9uICgpIHt9O1xuXG4gICAgLy8gZGF0ZSBmcm9tIHN0cmluZyBhbmQgZm9ybWF0IHN0cmluZ1xuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21TdHJpbmdBbmRGb3JtYXQoY29uZmlnKSB7XG4gICAgICAgIC8vIFRPRE86IE1vdmUgdGhpcyB0byBhbm90aGVyIHBhcnQgb2YgdGhlIGNyZWF0aW9uIGZsb3cgdG8gcHJldmVudCBjaXJjdWxhciBkZXBzXG4gICAgICAgIGlmIChjb25maWcuX2YgPT09IGhvb2tzLklTT184NjAxKSB7XG4gICAgICAgICAgICBjb25maWdGcm9tSVNPKGNvbmZpZyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmZpZy5fZiA9PT0gaG9va3MuUkZDXzI4MjIpIHtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21SRkMyODIyKGNvbmZpZyk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uZmlnLl9hID0gW107XG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmVtcHR5ID0gdHJ1ZTtcblxuICAgICAgICAvLyBUaGlzIGFycmF5IGlzIHVzZWQgdG8gbWFrZSBhIERhdGUsIGVpdGhlciB3aXRoIGBuZXcgRGF0ZWAgb3IgYERhdGUuVVRDYFxuICAgICAgICB2YXIgc3RyaW5nID0gJycgKyBjb25maWcuX2ksXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgcGFyc2VkSW5wdXQsXG4gICAgICAgICAgICB0b2tlbnMsXG4gICAgICAgICAgICB0b2tlbixcbiAgICAgICAgICAgIHNraXBwZWQsXG4gICAgICAgICAgICBzdHJpbmdMZW5ndGggPSBzdHJpbmcubGVuZ3RoLFxuICAgICAgICAgICAgdG90YWxQYXJzZWRJbnB1dExlbmd0aCA9IDAsXG4gICAgICAgICAgICBlcmE7XG5cbiAgICAgICAgdG9rZW5zID1cbiAgICAgICAgICAgIGV4cGFuZEZvcm1hdChjb25maWcuX2YsIGNvbmZpZy5fbG9jYWxlKS5tYXRjaChmb3JtYXR0aW5nVG9rZW5zKSB8fCBbXTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICB0b2tlbiA9IHRva2Vuc1tpXTtcbiAgICAgICAgICAgIHBhcnNlZElucHV0ID0gKHN0cmluZy5tYXRjaChnZXRQYXJzZVJlZ2V4Rm9yVG9rZW4odG9rZW4sIGNvbmZpZykpIHx8XG4gICAgICAgICAgICAgICAgW10pWzBdO1xuICAgICAgICAgICAgaWYgKHBhcnNlZElucHV0KSB7XG4gICAgICAgICAgICAgICAgc2tpcHBlZCA9IHN0cmluZy5zdWJzdHIoMCwgc3RyaW5nLmluZGV4T2YocGFyc2VkSW5wdXQpKTtcbiAgICAgICAgICAgICAgICBpZiAoc2tpcHBlZC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnVudXNlZElucHV0LnB1c2goc2tpcHBlZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHN0cmluZyA9IHN0cmluZy5zbGljZShcbiAgICAgICAgICAgICAgICAgICAgc3RyaW5nLmluZGV4T2YocGFyc2VkSW5wdXQpICsgcGFyc2VkSW5wdXQubGVuZ3RoXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB0b3RhbFBhcnNlZElucHV0TGVuZ3RoICs9IHBhcnNlZElucHV0Lmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGRvbid0IHBhcnNlIGlmIGl0J3Mgbm90IGEga25vd24gdG9rZW5cbiAgICAgICAgICAgIGlmIChmb3JtYXRUb2tlbkZ1bmN0aW9uc1t0b2tlbl0pIHtcbiAgICAgICAgICAgICAgICBpZiAocGFyc2VkSW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuZW1wdHkgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS51bnVzZWRUb2tlbnMucHVzaCh0b2tlbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFkZFRpbWVUb0FycmF5RnJvbVRva2VuKHRva2VuLCBwYXJzZWRJbnB1dCwgY29uZmlnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY29uZmlnLl9zdHJpY3QgJiYgIXBhcnNlZElucHV0KSB7XG4gICAgICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykudW51c2VkVG9rZW5zLnB1c2godG9rZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gYWRkIHJlbWFpbmluZyB1bnBhcnNlZCBpbnB1dCBsZW5ndGggdG8gdGhlIHN0cmluZ1xuICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5jaGFyc0xlZnRPdmVyID1cbiAgICAgICAgICAgIHN0cmluZ0xlbmd0aCAtIHRvdGFsUGFyc2VkSW5wdXRMZW5ndGg7XG4gICAgICAgIGlmIChzdHJpbmcubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykudW51c2VkSW5wdXQucHVzaChzdHJpbmcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gY2xlYXIgXzEyaCBmbGFnIGlmIGhvdXIgaXMgPD0gMTJcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgY29uZmlnLl9hW0hPVVJdIDw9IDEyICYmXG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5iaWdIb3VyID09PSB0cnVlICYmXG4gICAgICAgICAgICBjb25maWcuX2FbSE9VUl0gPiAwXG4gICAgICAgICkge1xuICAgICAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykuYmlnSG91ciA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLnBhcnNlZERhdGVQYXJ0cyA9IGNvbmZpZy5fYS5zbGljZSgwKTtcbiAgICAgICAgZ2V0UGFyc2luZ0ZsYWdzKGNvbmZpZykubWVyaWRpZW0gPSBjb25maWcuX21lcmlkaWVtO1xuICAgICAgICAvLyBoYW5kbGUgbWVyaWRpZW1cbiAgICAgICAgY29uZmlnLl9hW0hPVVJdID0gbWVyaWRpZW1GaXhXcmFwKFxuICAgICAgICAgICAgY29uZmlnLl9sb2NhbGUsXG4gICAgICAgICAgICBjb25maWcuX2FbSE9VUl0sXG4gICAgICAgICAgICBjb25maWcuX21lcmlkaWVtXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8gaGFuZGxlIGVyYVxuICAgICAgICBlcmEgPSBnZXRQYXJzaW5nRmxhZ3MoY29uZmlnKS5lcmE7XG4gICAgICAgIGlmIChlcmEgIT09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtZRUFSXSA9IGNvbmZpZy5fbG9jYWxlLmVyYXNDb252ZXJ0WWVhcihlcmEsIGNvbmZpZy5fYVtZRUFSXSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25maWdGcm9tQXJyYXkoY29uZmlnKTtcbiAgICAgICAgY2hlY2tPdmVyZmxvdyhjb25maWcpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1lcmlkaWVtRml4V3JhcChsb2NhbGUsIGhvdXIsIG1lcmlkaWVtKSB7XG4gICAgICAgIHZhciBpc1BtO1xuXG4gICAgICAgIGlmIChtZXJpZGllbSA9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBub3RoaW5nIHRvIGRvXG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobG9jYWxlLm1lcmlkaWVtSG91ciAhPSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxlLm1lcmlkaWVtSG91cihob3VyLCBtZXJpZGllbSk7XG4gICAgICAgIH0gZWxzZSBpZiAobG9jYWxlLmlzUE0gIT0gbnVsbCkge1xuICAgICAgICAgICAgLy8gRmFsbGJhY2tcbiAgICAgICAgICAgIGlzUG0gPSBsb2NhbGUuaXNQTShtZXJpZGllbSk7XG4gICAgICAgICAgICBpZiAoaXNQbSAmJiBob3VyIDwgMTIpIHtcbiAgICAgICAgICAgICAgICBob3VyICs9IDEyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFpc1BtICYmIGhvdXIgPT09IDEyKSB7XG4gICAgICAgICAgICAgICAgaG91ciA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaG91cjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgbm90IHN1cHBvc2VkIHRvIGhhcHBlblxuICAgICAgICAgICAgcmV0dXJuIGhvdXI7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBkYXRlIGZyb20gc3RyaW5nIGFuZCBhcnJheSBvZiBmb3JtYXQgc3RyaW5nc1xuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21TdHJpbmdBbmRBcnJheShjb25maWcpIHtcbiAgICAgICAgdmFyIHRlbXBDb25maWcsXG4gICAgICAgICAgICBiZXN0TW9tZW50LFxuICAgICAgICAgICAgc2NvcmVUb0JlYXQsXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgY3VycmVudFNjb3JlLFxuICAgICAgICAgICAgdmFsaWRGb3JtYXRGb3VuZCxcbiAgICAgICAgICAgIGJlc3RGb3JtYXRJc1ZhbGlkID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKGNvbmZpZy5fZi5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmludmFsaWRGb3JtYXQgPSB0cnVlO1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoTmFOKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBjb25maWcuX2YubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGN1cnJlbnRTY29yZSA9IDA7XG4gICAgICAgICAgICB2YWxpZEZvcm1hdEZvdW5kID0gZmFsc2U7XG4gICAgICAgICAgICB0ZW1wQ29uZmlnID0gY29weUNvbmZpZyh7fSwgY29uZmlnKTtcbiAgICAgICAgICAgIGlmIChjb25maWcuX3VzZVVUQyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgdGVtcENvbmZpZy5fdXNlVVRDID0gY29uZmlnLl91c2VVVEM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0ZW1wQ29uZmlnLl9mID0gY29uZmlnLl9mW2ldO1xuICAgICAgICAgICAgY29uZmlnRnJvbVN0cmluZ0FuZEZvcm1hdCh0ZW1wQ29uZmlnKTtcblxuICAgICAgICAgICAgaWYgKGlzVmFsaWQodGVtcENvbmZpZykpIHtcbiAgICAgICAgICAgICAgICB2YWxpZEZvcm1hdEZvdW5kID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgYW55IGlucHV0IHRoYXQgd2FzIG5vdCBwYXJzZWQgYWRkIGEgcGVuYWx0eSBmb3IgdGhhdCBmb3JtYXRcbiAgICAgICAgICAgIGN1cnJlbnRTY29yZSArPSBnZXRQYXJzaW5nRmxhZ3ModGVtcENvbmZpZykuY2hhcnNMZWZ0T3ZlcjtcblxuICAgICAgICAgICAgLy9vciB0b2tlbnNcbiAgICAgICAgICAgIGN1cnJlbnRTY29yZSArPSBnZXRQYXJzaW5nRmxhZ3ModGVtcENvbmZpZykudW51c2VkVG9rZW5zLmxlbmd0aCAqIDEwO1xuXG4gICAgICAgICAgICBnZXRQYXJzaW5nRmxhZ3ModGVtcENvbmZpZykuc2NvcmUgPSBjdXJyZW50U2NvcmU7XG5cbiAgICAgICAgICAgIGlmICghYmVzdEZvcm1hdElzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgICAgIHNjb3JlVG9CZWF0ID09IG51bGwgfHxcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudFNjb3JlIDwgc2NvcmVUb0JlYXQgfHxcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRGb3JtYXRGb3VuZFxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICBzY29yZVRvQmVhdCA9IGN1cnJlbnRTY29yZTtcbiAgICAgICAgICAgICAgICAgICAgYmVzdE1vbWVudCA9IHRlbXBDb25maWc7XG4gICAgICAgICAgICAgICAgICAgIGlmICh2YWxpZEZvcm1hdEZvdW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBiZXN0Rm9ybWF0SXNWYWxpZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50U2NvcmUgPCBzY29yZVRvQmVhdCkge1xuICAgICAgICAgICAgICAgICAgICBzY29yZVRvQmVhdCA9IGN1cnJlbnRTY29yZTtcbiAgICAgICAgICAgICAgICAgICAgYmVzdE1vbWVudCA9IHRlbXBDb25maWc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZXh0ZW5kKGNvbmZpZywgYmVzdE1vbWVudCB8fCB0ZW1wQ29uZmlnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb25maWdGcm9tT2JqZWN0KGNvbmZpZykge1xuICAgICAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaSA9IG5vcm1hbGl6ZU9iamVjdFVuaXRzKGNvbmZpZy5faSksXG4gICAgICAgICAgICBkYXlPckRhdGUgPSBpLmRheSA9PT0gdW5kZWZpbmVkID8gaS5kYXRlIDogaS5kYXk7XG4gICAgICAgIGNvbmZpZy5fYSA9IG1hcChcbiAgICAgICAgICAgIFtpLnllYXIsIGkubW9udGgsIGRheU9yRGF0ZSwgaS5ob3VyLCBpLm1pbnV0ZSwgaS5zZWNvbmQsIGkubWlsbGlzZWNvbmRdLFxuICAgICAgICAgICAgZnVuY3Rpb24gKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiBvYmogJiYgcGFyc2VJbnQob2JqLCAxMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICk7XG5cbiAgICAgICAgY29uZmlnRnJvbUFycmF5KGNvbmZpZyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlRnJvbUNvbmZpZyhjb25maWcpIHtcbiAgICAgICAgdmFyIHJlcyA9IG5ldyBNb21lbnQoY2hlY2tPdmVyZmxvdyhwcmVwYXJlQ29uZmlnKGNvbmZpZykpKTtcbiAgICAgICAgaWYgKHJlcy5fbmV4dERheSkge1xuICAgICAgICAgICAgLy8gQWRkaW5nIGlzIHNtYXJ0IGVub3VnaCBhcm91bmQgRFNUXG4gICAgICAgICAgICByZXMuYWRkKDEsICdkJyk7XG4gICAgICAgICAgICByZXMuX25leHREYXkgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHByZXBhcmVDb25maWcoY29uZmlnKSB7XG4gICAgICAgIHZhciBpbnB1dCA9IGNvbmZpZy5faSxcbiAgICAgICAgICAgIGZvcm1hdCA9IGNvbmZpZy5fZjtcblxuICAgICAgICBjb25maWcuX2xvY2FsZSA9IGNvbmZpZy5fbG9jYWxlIHx8IGdldExvY2FsZShjb25maWcuX2wpO1xuXG4gICAgICAgIGlmIChpbnB1dCA9PT0gbnVsbCB8fCAoZm9ybWF0ID09PSB1bmRlZmluZWQgJiYgaW5wdXQgPT09ICcnKSkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUludmFsaWQoeyBudWxsSW5wdXQ6IHRydWUgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgY29uZmlnLl9pID0gaW5wdXQgPSBjb25maWcuX2xvY2FsZS5wcmVwYXJzZShpbnB1dCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaXNNb21lbnQoaW5wdXQpKSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE1vbWVudChjaGVja092ZXJmbG93KGlucHV0KSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNEYXRlKGlucHV0KSkge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gaW5wdXQ7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShmb3JtYXQpKSB7XG4gICAgICAgICAgICBjb25maWdGcm9tU3RyaW5nQW5kQXJyYXkoY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIGlmIChmb3JtYXQpIHtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21TdHJpbmdBbmRGb3JtYXQoY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbmZpZ0Zyb21JbnB1dChjb25maWcpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpc1ZhbGlkKGNvbmZpZykpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbmZpZ0Zyb21JbnB1dChjb25maWcpIHtcbiAgICAgICAgdmFyIGlucHV0ID0gY29uZmlnLl9pO1xuICAgICAgICBpZiAoaXNVbmRlZmluZWQoaW5wdXQpKSB7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShob29rcy5ub3coKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNEYXRlKGlucHV0KSkge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoaW5wdXQudmFsdWVPZigpKTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25maWdGcm9tU3RyaW5nKGNvbmZpZyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcnJheShpbnB1dCkpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fYSA9IG1hcChpbnB1dC5zbGljZSgwKSwgZnVuY3Rpb24gKG9iaikge1xuICAgICAgICAgICAgICAgIHJldHVybiBwYXJzZUludChvYmosIDEwKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgY29uZmlnRnJvbUFycmF5KGNvbmZpZyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNPYmplY3QoaW5wdXQpKSB7XG4gICAgICAgICAgICBjb25maWdGcm9tT2JqZWN0KGNvbmZpZyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNOdW1iZXIoaW5wdXQpKSB7XG4gICAgICAgICAgICAvLyBmcm9tIG1pbGxpc2Vjb25kc1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoaW5wdXQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaG9va3MuY3JlYXRlRnJvbUlucHV0RmFsbGJhY2soY29uZmlnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNyZWF0ZUxvY2FsT3JVVEMoaW5wdXQsIGZvcm1hdCwgbG9jYWxlLCBzdHJpY3QsIGlzVVRDKSB7XG4gICAgICAgIHZhciBjID0ge307XG5cbiAgICAgICAgaWYgKGZvcm1hdCA9PT0gdHJ1ZSB8fCBmb3JtYXQgPT09IGZhbHNlKSB7XG4gICAgICAgICAgICBzdHJpY3QgPSBmb3JtYXQ7XG4gICAgICAgICAgICBmb3JtYXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobG9jYWxlID09PSB0cnVlIHx8IGxvY2FsZSA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHN0cmljdCA9IGxvY2FsZTtcbiAgICAgICAgICAgIGxvY2FsZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIChpc09iamVjdChpbnB1dCkgJiYgaXNPYmplY3RFbXB0eShpbnB1dCkpIHx8XG4gICAgICAgICAgICAoaXNBcnJheShpbnB1dCkgJiYgaW5wdXQubGVuZ3RoID09PSAwKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGlucHV0ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIC8vIG9iamVjdCBjb25zdHJ1Y3Rpb24gbXVzdCBiZSBkb25lIHRoaXMgd2F5LlxuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vbW9tZW50L21vbWVudC9pc3N1ZXMvMTQyM1xuICAgICAgICBjLl9pc0FNb21lbnRPYmplY3QgPSB0cnVlO1xuICAgICAgICBjLl91c2VVVEMgPSBjLl9pc1VUQyA9IGlzVVRDO1xuICAgICAgICBjLl9sID0gbG9jYWxlO1xuICAgICAgICBjLl9pID0gaW5wdXQ7XG4gICAgICAgIGMuX2YgPSBmb3JtYXQ7XG4gICAgICAgIGMuX3N0cmljdCA9IHN0cmljdDtcblxuICAgICAgICByZXR1cm4gY3JlYXRlRnJvbUNvbmZpZyhjKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVMb2NhbChpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCkge1xuICAgICAgICByZXR1cm4gY3JlYXRlTG9jYWxPclVUQyhpbnB1dCwgZm9ybWF0LCBsb2NhbGUsIHN0cmljdCwgZmFsc2UpO1xuICAgIH1cblxuICAgIHZhciBwcm90b3R5cGVNaW4gPSBkZXByZWNhdGUoXG4gICAgICAgICAgICAnbW9tZW50KCkubWluIGlzIGRlcHJlY2F0ZWQsIHVzZSBtb21lbnQubWF4IGluc3RlYWQuIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvbWluLW1heC8nLFxuICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBvdGhlciA9IGNyZWF0ZUxvY2FsLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNWYWxpZCgpICYmIG90aGVyLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3RoZXIgPCB0aGlzID8gdGhpcyA6IG90aGVyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjcmVhdGVJbnZhbGlkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICApLFxuICAgICAgICBwcm90b3R5cGVNYXggPSBkZXByZWNhdGUoXG4gICAgICAgICAgICAnbW9tZW50KCkubWF4IGlzIGRlcHJlY2F0ZWQsIHVzZSBtb21lbnQubWluIGluc3RlYWQuIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvbWluLW1heC8nLFxuICAgICAgICAgICAgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciBvdGhlciA9IGNyZWF0ZUxvY2FsLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNWYWxpZCgpICYmIG90aGVyLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gb3RoZXIgPiB0aGlzID8gdGhpcyA6IG90aGVyO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjcmVhdGVJbnZhbGlkKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICApO1xuXG4gICAgLy8gUGljayBhIG1vbWVudCBtIGZyb20gbW9tZW50cyBzbyB0aGF0IG1bZm5dKG90aGVyKSBpcyB0cnVlIGZvciBhbGxcbiAgICAvLyBvdGhlci4gVGhpcyByZWxpZXMgb24gdGhlIGZ1bmN0aW9uIGZuIHRvIGJlIHRyYW5zaXRpdmUuXG4gICAgLy9cbiAgICAvLyBtb21lbnRzIHNob3VsZCBlaXRoZXIgYmUgYW4gYXJyYXkgb2YgbW9tZW50IG9iamVjdHMgb3IgYW4gYXJyYXksIHdob3NlXG4gICAgLy8gZmlyc3QgZWxlbWVudCBpcyBhbiBhcnJheSBvZiBtb21lbnQgb2JqZWN0cy5cbiAgICBmdW5jdGlvbiBwaWNrQnkoZm4sIG1vbWVudHMpIHtcbiAgICAgICAgdmFyIHJlcywgaTtcbiAgICAgICAgaWYgKG1vbWVudHMubGVuZ3RoID09PSAxICYmIGlzQXJyYXkobW9tZW50c1swXSkpIHtcbiAgICAgICAgICAgIG1vbWVudHMgPSBtb21lbnRzWzBdO1xuICAgICAgICB9XG4gICAgICAgIGlmICghbW9tZW50cy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVMb2NhbCgpO1xuICAgICAgICB9XG4gICAgICAgIHJlcyA9IG1vbWVudHNbMF07XG4gICAgICAgIGZvciAoaSA9IDE7IGkgPCBtb21lbnRzLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBpZiAoIW1vbWVudHNbaV0uaXNWYWxpZCgpIHx8IG1vbWVudHNbaV1bZm5dKHJlcykpIHtcbiAgICAgICAgICAgICAgICByZXMgPSBtb21lbnRzW2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogVXNlIFtdLnNvcnQgaW5zdGVhZD9cbiAgICBmdW5jdGlvbiBtaW4oKSB7XG4gICAgICAgIHZhciBhcmdzID0gW10uc2xpY2UuY2FsbChhcmd1bWVudHMsIDApO1xuXG4gICAgICAgIHJldHVybiBwaWNrQnkoJ2lzQmVmb3JlJywgYXJncyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWF4KCkge1xuICAgICAgICB2YXIgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcblxuICAgICAgICByZXR1cm4gcGlja0J5KCdpc0FmdGVyJywgYXJncyk7XG4gICAgfVxuXG4gICAgdmFyIG5vdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIERhdGUubm93ID8gRGF0ZS5ub3coKSA6ICtuZXcgRGF0ZSgpO1xuICAgIH07XG5cbiAgICB2YXIgb3JkZXJpbmcgPSBbXG4gICAgICAgICd5ZWFyJyxcbiAgICAgICAgJ3F1YXJ0ZXInLFxuICAgICAgICAnbW9udGgnLFxuICAgICAgICAnd2VlaycsXG4gICAgICAgICdkYXknLFxuICAgICAgICAnaG91cicsXG4gICAgICAgICdtaW51dGUnLFxuICAgICAgICAnc2Vjb25kJyxcbiAgICAgICAgJ21pbGxpc2Vjb25kJyxcbiAgICBdO1xuXG4gICAgZnVuY3Rpb24gaXNEdXJhdGlvblZhbGlkKG0pIHtcbiAgICAgICAgdmFyIGtleSxcbiAgICAgICAgICAgIHVuaXRIYXNEZWNpbWFsID0gZmFsc2UsXG4gICAgICAgICAgICBpO1xuICAgICAgICBmb3IgKGtleSBpbiBtKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgaGFzT3duUHJvcChtLCBrZXkpICYmXG4gICAgICAgICAgICAgICAgIShcbiAgICAgICAgICAgICAgICAgICAgaW5kZXhPZi5jYWxsKG9yZGVyaW5nLCBrZXkpICE9PSAtMSAmJlxuICAgICAgICAgICAgICAgICAgICAobVtrZXldID09IG51bGwgfHwgIWlzTmFOKG1ba2V5XSkpXG4gICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IG9yZGVyaW5nLmxlbmd0aDsgKytpKSB7XG4gICAgICAgICAgICBpZiAobVtvcmRlcmluZ1tpXV0pIHtcbiAgICAgICAgICAgICAgICBpZiAodW5pdEhhc0RlY2ltYWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOyAvLyBvbmx5IGFsbG93IG5vbi1pbnRlZ2VycyBmb3Igc21hbGxlc3QgdW5pdFxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocGFyc2VGbG9hdChtW29yZGVyaW5nW2ldXSkgIT09IHRvSW50KG1bb3JkZXJpbmdbaV1dKSkge1xuICAgICAgICAgICAgICAgICAgICB1bml0SGFzRGVjaW1hbCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNWYWxpZCQxKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNWYWxpZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGVJbnZhbGlkJDEoKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVEdXJhdGlvbihOYU4pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIER1cmF0aW9uKGR1cmF0aW9uKSB7XG4gICAgICAgIHZhciBub3JtYWxpemVkSW5wdXQgPSBub3JtYWxpemVPYmplY3RVbml0cyhkdXJhdGlvbiksXG4gICAgICAgICAgICB5ZWFycyA9IG5vcm1hbGl6ZWRJbnB1dC55ZWFyIHx8IDAsXG4gICAgICAgICAgICBxdWFydGVycyA9IG5vcm1hbGl6ZWRJbnB1dC5xdWFydGVyIHx8IDAsXG4gICAgICAgICAgICBtb250aHMgPSBub3JtYWxpemVkSW5wdXQubW9udGggfHwgMCxcbiAgICAgICAgICAgIHdlZWtzID0gbm9ybWFsaXplZElucHV0LndlZWsgfHwgbm9ybWFsaXplZElucHV0Lmlzb1dlZWsgfHwgMCxcbiAgICAgICAgICAgIGRheXMgPSBub3JtYWxpemVkSW5wdXQuZGF5IHx8IDAsXG4gICAgICAgICAgICBob3VycyA9IG5vcm1hbGl6ZWRJbnB1dC5ob3VyIHx8IDAsXG4gICAgICAgICAgICBtaW51dGVzID0gbm9ybWFsaXplZElucHV0Lm1pbnV0ZSB8fCAwLFxuICAgICAgICAgICAgc2Vjb25kcyA9IG5vcm1hbGl6ZWRJbnB1dC5zZWNvbmQgfHwgMCxcbiAgICAgICAgICAgIG1pbGxpc2Vjb25kcyA9IG5vcm1hbGl6ZWRJbnB1dC5taWxsaXNlY29uZCB8fCAwO1xuXG4gICAgICAgIHRoaXMuX2lzVmFsaWQgPSBpc0R1cmF0aW9uVmFsaWQobm9ybWFsaXplZElucHV0KTtcblxuICAgICAgICAvLyByZXByZXNlbnRhdGlvbiBmb3IgZGF0ZUFkZFJlbW92ZVxuICAgICAgICB0aGlzLl9taWxsaXNlY29uZHMgPVxuICAgICAgICAgICAgK21pbGxpc2Vjb25kcyArXG4gICAgICAgICAgICBzZWNvbmRzICogMWUzICsgLy8gMTAwMFxuICAgICAgICAgICAgbWludXRlcyAqIDZlNCArIC8vIDEwMDAgKiA2MFxuICAgICAgICAgICAgaG91cnMgKiAxMDAwICogNjAgKiA2MDsgLy91c2luZyAxMDAwICogNjAgKiA2MCBpbnN0ZWFkIG9mIDM2ZTUgdG8gYXZvaWQgZmxvYXRpbmcgcG9pbnQgcm91bmRpbmcgZXJyb3JzIGh0dHBzOi8vZ2l0aHViLmNvbS9tb21lbnQvbW9tZW50L2lzc3Vlcy8yOTc4XG4gICAgICAgIC8vIEJlY2F1c2Ugb2YgZGF0ZUFkZFJlbW92ZSB0cmVhdHMgMjQgaG91cnMgYXMgZGlmZmVyZW50IGZyb20gYVxuICAgICAgICAvLyBkYXkgd2hlbiB3b3JraW5nIGFyb3VuZCBEU1QsIHdlIG5lZWQgdG8gc3RvcmUgdGhlbSBzZXBhcmF0ZWx5XG4gICAgICAgIHRoaXMuX2RheXMgPSArZGF5cyArIHdlZWtzICogNztcbiAgICAgICAgLy8gSXQgaXMgaW1wb3NzaWJsZSB0byB0cmFuc2xhdGUgbW9udGhzIGludG8gZGF5cyB3aXRob3V0IGtub3dpbmdcbiAgICAgICAgLy8gd2hpY2ggbW9udGhzIHlvdSBhcmUgYXJlIHRhbGtpbmcgYWJvdXQsIHNvIHdlIGhhdmUgdG8gc3RvcmVcbiAgICAgICAgLy8gaXQgc2VwYXJhdGVseS5cbiAgICAgICAgdGhpcy5fbW9udGhzID0gK21vbnRocyArIHF1YXJ0ZXJzICogMyArIHllYXJzICogMTI7XG5cbiAgICAgICAgdGhpcy5fZGF0YSA9IHt9O1xuXG4gICAgICAgIHRoaXMuX2xvY2FsZSA9IGdldExvY2FsZSgpO1xuXG4gICAgICAgIHRoaXMuX2J1YmJsZSgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzRHVyYXRpb24ob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogaW5zdGFuY2VvZiBEdXJhdGlvbjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhYnNSb3VuZChudW1iZXIpIHtcbiAgICAgICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLnJvdW5kKC0xICogbnVtYmVyKSAqIC0xO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGgucm91bmQobnVtYmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNvbXBhcmUgdHdvIGFycmF5cywgcmV0dXJuIHRoZSBudW1iZXIgb2YgZGlmZmVyZW5jZXNcbiAgICBmdW5jdGlvbiBjb21wYXJlQXJyYXlzKGFycmF5MSwgYXJyYXkyLCBkb250Q29udmVydCkge1xuICAgICAgICB2YXIgbGVuID0gTWF0aC5taW4oYXJyYXkxLmxlbmd0aCwgYXJyYXkyLmxlbmd0aCksXG4gICAgICAgICAgICBsZW5ndGhEaWZmID0gTWF0aC5hYnMoYXJyYXkxLmxlbmd0aCAtIGFycmF5Mi5sZW5ndGgpLFxuICAgICAgICAgICAgZGlmZnMgPSAwLFxuICAgICAgICAgICAgaTtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgKGRvbnRDb252ZXJ0ICYmIGFycmF5MVtpXSAhPT0gYXJyYXkyW2ldKSB8fFxuICAgICAgICAgICAgICAgICghZG9udENvbnZlcnQgJiYgdG9JbnQoYXJyYXkxW2ldKSAhPT0gdG9JbnQoYXJyYXkyW2ldKSlcbiAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGRpZmZzKys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGRpZmZzICsgbGVuZ3RoRGlmZjtcbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBmdW5jdGlvbiBvZmZzZXQodG9rZW4sIHNlcGFyYXRvcikge1xuICAgICAgICBhZGRGb3JtYXRUb2tlbih0b2tlbiwgMCwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG9mZnNldCA9IHRoaXMudXRjT2Zmc2V0KCksXG4gICAgICAgICAgICAgICAgc2lnbiA9ICcrJztcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwKSB7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gLW9mZnNldDtcbiAgICAgICAgICAgICAgICBzaWduID0gJy0nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICBzaWduICtcbiAgICAgICAgICAgICAgICB6ZXJvRmlsbCh+fihvZmZzZXQgLyA2MCksIDIpICtcbiAgICAgICAgICAgICAgICBzZXBhcmF0b3IgK1xuICAgICAgICAgICAgICAgIHplcm9GaWxsKH5+b2Zmc2V0ICUgNjAsIDIpXG4gICAgICAgICAgICApO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBvZmZzZXQoJ1onLCAnOicpO1xuICAgIG9mZnNldCgnWlonLCAnJyk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdaJywgbWF0Y2hTaG9ydE9mZnNldCk7XG4gICAgYWRkUmVnZXhUb2tlbignWlonLCBtYXRjaFNob3J0T2Zmc2V0KTtcbiAgICBhZGRQYXJzZVRva2VuKFsnWicsICdaWiddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgY29uZmlnLl91c2VVVEMgPSB0cnVlO1xuICAgICAgICBjb25maWcuX3R6bSA9IG9mZnNldEZyb21TdHJpbmcobWF0Y2hTaG9ydE9mZnNldCwgaW5wdXQpO1xuICAgIH0pO1xuXG4gICAgLy8gSEVMUEVSU1xuXG4gICAgLy8gdGltZXpvbmUgY2h1bmtlclxuICAgIC8vICcrMTA6MDAnID4gWycxMCcsICAnMDAnXVxuICAgIC8vICctMTUzMCcgID4gWyctMTUnLCAnMzAnXVxuICAgIHZhciBjaHVua09mZnNldCA9IC8oW1xcK1xcLV18XFxkXFxkKS9naTtcblxuICAgIGZ1bmN0aW9uIG9mZnNldEZyb21TdHJpbmcobWF0Y2hlciwgc3RyaW5nKSB7XG4gICAgICAgIHZhciBtYXRjaGVzID0gKHN0cmluZyB8fCAnJykubWF0Y2gobWF0Y2hlciksXG4gICAgICAgICAgICBjaHVuayxcbiAgICAgICAgICAgIHBhcnRzLFxuICAgICAgICAgICAgbWludXRlcztcblxuICAgICAgICBpZiAobWF0Y2hlcyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBjaHVuayA9IG1hdGNoZXNbbWF0Y2hlcy5sZW5ndGggLSAxXSB8fCBbXTtcbiAgICAgICAgcGFydHMgPSAoY2h1bmsgKyAnJykubWF0Y2goY2h1bmtPZmZzZXQpIHx8IFsnLScsIDAsIDBdO1xuICAgICAgICBtaW51dGVzID0gKyhwYXJ0c1sxXSAqIDYwKSArIHRvSW50KHBhcnRzWzJdKTtcblxuICAgICAgICByZXR1cm4gbWludXRlcyA9PT0gMCA/IDAgOiBwYXJ0c1swXSA9PT0gJysnID8gbWludXRlcyA6IC1taW51dGVzO1xuICAgIH1cblxuICAgIC8vIFJldHVybiBhIG1vbWVudCBmcm9tIGlucHV0LCB0aGF0IGlzIGxvY2FsL3V0Yy96b25lIGVxdWl2YWxlbnQgdG8gbW9kZWwuXG4gICAgZnVuY3Rpb24gY2xvbmVXaXRoT2Zmc2V0KGlucHV0LCBtb2RlbCkge1xuICAgICAgICB2YXIgcmVzLCBkaWZmO1xuICAgICAgICBpZiAobW9kZWwuX2lzVVRDKSB7XG4gICAgICAgICAgICByZXMgPSBtb2RlbC5jbG9uZSgpO1xuICAgICAgICAgICAgZGlmZiA9XG4gICAgICAgICAgICAgICAgKGlzTW9tZW50KGlucHV0KSB8fCBpc0RhdGUoaW5wdXQpXG4gICAgICAgICAgICAgICAgICAgID8gaW5wdXQudmFsdWVPZigpXG4gICAgICAgICAgICAgICAgICAgIDogY3JlYXRlTG9jYWwoaW5wdXQpLnZhbHVlT2YoKSkgLSByZXMudmFsdWVPZigpO1xuICAgICAgICAgICAgLy8gVXNlIGxvdy1sZXZlbCBhcGksIGJlY2F1c2UgdGhpcyBmbiBpcyBsb3ctbGV2ZWwgYXBpLlxuICAgICAgICAgICAgcmVzLl9kLnNldFRpbWUocmVzLl9kLnZhbHVlT2YoKSArIGRpZmYpO1xuICAgICAgICAgICAgaG9va3MudXBkYXRlT2Zmc2V0KHJlcywgZmFsc2UpO1xuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVMb2NhbChpbnB1dCkubG9jYWwoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldERhdGVPZmZzZXQobSkge1xuICAgICAgICAvLyBPbiBGaXJlZm94LjI0IERhdGUjZ2V0VGltZXpvbmVPZmZzZXQgcmV0dXJucyBhIGZsb2F0aW5nIHBvaW50LlxuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vbW9tZW50L21vbWVudC9wdWxsLzE4NzFcbiAgICAgICAgcmV0dXJuIC1NYXRoLnJvdW5kKG0uX2QuZ2V0VGltZXpvbmVPZmZzZXQoKSk7XG4gICAgfVxuXG4gICAgLy8gSE9PS1NcblxuICAgIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgd2hlbmV2ZXIgYSBtb21lbnQgaXMgbXV0YXRlZC5cbiAgICAvLyBJdCBpcyBpbnRlbmRlZCB0byBrZWVwIHRoZSBvZmZzZXQgaW4gc3luYyB3aXRoIHRoZSB0aW1lem9uZS5cbiAgICBob29rcy51cGRhdGVPZmZzZXQgPSBmdW5jdGlvbiAoKSB7fTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIC8vIGtlZXBMb2NhbFRpbWUgPSB0cnVlIG1lYW5zIG9ubHkgY2hhbmdlIHRoZSB0aW1lem9uZSwgd2l0aG91dFxuICAgIC8vIGFmZmVjdGluZyB0aGUgbG9jYWwgaG91ci4gU28gNTozMToyNiArMDMwMCAtLVt1dGNPZmZzZXQoMiwgdHJ1ZSldLS0+XG4gICAgLy8gNTozMToyNiArMDIwMCBJdCBpcyBwb3NzaWJsZSB0aGF0IDU6MzE6MjYgZG9lc24ndCBleGlzdCB3aXRoIG9mZnNldFxuICAgIC8vICswMjAwLCBzbyB3ZSBhZGp1c3QgdGhlIHRpbWUgYXMgbmVlZGVkLCB0byBiZSB2YWxpZC5cbiAgICAvL1xuICAgIC8vIEtlZXBpbmcgdGhlIHRpbWUgYWN0dWFsbHkgYWRkcy9zdWJ0cmFjdHMgKG9uZSBob3VyKVxuICAgIC8vIGZyb20gdGhlIGFjdHVhbCByZXByZXNlbnRlZCB0aW1lLiBUaGF0IGlzIHdoeSB3ZSBjYWxsIHVwZGF0ZU9mZnNldFxuICAgIC8vIGEgc2Vjb25kIHRpbWUuIEluIGNhc2UgaXQgd2FudHMgdXMgdG8gY2hhbmdlIHRoZSBvZmZzZXQgYWdhaW5cbiAgICAvLyBfY2hhbmdlSW5Qcm9ncmVzcyA9PSB0cnVlIGNhc2UsIHRoZW4gd2UgaGF2ZSB0byBhZGp1c3QsIGJlY2F1c2VcbiAgICAvLyB0aGVyZSBpcyBubyBzdWNoIHRpbWUgaW4gdGhlIGdpdmVuIHRpbWV6b25lLlxuICAgIGZ1bmN0aW9uIGdldFNldE9mZnNldChpbnB1dCwga2VlcExvY2FsVGltZSwga2VlcE1pbnV0ZXMpIHtcbiAgICAgICAgdmFyIG9mZnNldCA9IHRoaXMuX29mZnNldCB8fCAwLFxuICAgICAgICAgICAgbG9jYWxBZGp1c3Q7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCAhPSBudWxsID8gdGhpcyA6IE5hTjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBpbnB1dCA9IG9mZnNldEZyb21TdHJpbmcobWF0Y2hTaG9ydE9mZnNldCwgaW5wdXQpO1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKE1hdGguYWJzKGlucHV0KSA8IDE2ICYmICFrZWVwTWludXRlcykge1xuICAgICAgICAgICAgICAgIGlucHV0ID0gaW5wdXQgKiA2MDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5faXNVVEMgJiYga2VlcExvY2FsVGltZSkge1xuICAgICAgICAgICAgICAgIGxvY2FsQWRqdXN0ID0gZ2V0RGF0ZU9mZnNldCh0aGlzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuX29mZnNldCA9IGlucHV0O1xuICAgICAgICAgICAgdGhpcy5faXNVVEMgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKGxvY2FsQWRqdXN0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmFkZChsb2NhbEFkanVzdCwgJ20nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvZmZzZXQgIT09IGlucHV0KSB7XG4gICAgICAgICAgICAgICAgaWYgKCFrZWVwTG9jYWxUaW1lIHx8IHRoaXMuX2NoYW5nZUluUHJvZ3Jlc3MpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkU3VidHJhY3QoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLFxuICAgICAgICAgICAgICAgICAgICAgICAgY3JlYXRlRHVyYXRpb24oaW5wdXQgLSBvZmZzZXQsICdtJyksXG4gICAgICAgICAgICAgICAgICAgICAgICAxLFxuICAgICAgICAgICAgICAgICAgICAgICAgZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKCF0aGlzLl9jaGFuZ2VJblByb2dyZXNzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NoYW5nZUluUHJvZ3Jlc3MgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NoYW5nZUluUHJvZ3Jlc3MgPSBudWxsO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzVVRDID8gb2Zmc2V0IDogZ2V0RGF0ZU9mZnNldCh0aGlzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldFNldFpvbmUoaW5wdXQsIGtlZXBMb2NhbFRpbWUpIHtcbiAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaW5wdXQgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgaW5wdXQgPSAtaW5wdXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMudXRjT2Zmc2V0KGlucHV0LCBrZWVwTG9jYWxUaW1lKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gLXRoaXMudXRjT2Zmc2V0KCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRPZmZzZXRUb1VUQyhrZWVwTG9jYWxUaW1lKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnV0Y09mZnNldCgwLCBrZWVwTG9jYWxUaW1lKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBzZXRPZmZzZXRUb0xvY2FsKGtlZXBMb2NhbFRpbWUpIHtcbiAgICAgICAgaWYgKHRoaXMuX2lzVVRDKSB7XG4gICAgICAgICAgICB0aGlzLnV0Y09mZnNldCgwLCBrZWVwTG9jYWxUaW1lKTtcbiAgICAgICAgICAgIHRoaXMuX2lzVVRDID0gZmFsc2U7XG5cbiAgICAgICAgICAgIGlmIChrZWVwTG9jYWxUaW1lKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zdWJ0cmFjdChnZXREYXRlT2Zmc2V0KHRoaXMpLCAnbScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldE9mZnNldFRvUGFyc2VkT2Zmc2V0KCkge1xuICAgICAgICBpZiAodGhpcy5fdHptICE9IG51bGwpIHtcbiAgICAgICAgICAgIHRoaXMudXRjT2Zmc2V0KHRoaXMuX3R6bSwgZmFsc2UsIHRydWUpO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiB0aGlzLl9pID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgdmFyIHRab25lID0gb2Zmc2V0RnJvbVN0cmluZyhtYXRjaE9mZnNldCwgdGhpcy5faSk7XG4gICAgICAgICAgICBpZiAodFpvbmUgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMudXRjT2Zmc2V0KHRab25lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQoMCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaGFzQWxpZ25lZEhvdXJPZmZzZXQoaW5wdXQpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlucHV0ID0gaW5wdXQgPyBjcmVhdGVMb2NhbChpbnB1dCkudXRjT2Zmc2V0KCkgOiAwO1xuXG4gICAgICAgIHJldHVybiAodGhpcy51dGNPZmZzZXQoKSAtIGlucHV0KSAlIDYwID09PSAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzRGF5bGlnaHRTYXZpbmdUaW1lKCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQoKSA+IHRoaXMuY2xvbmUoKS5tb250aCgwKS51dGNPZmZzZXQoKSB8fFxuICAgICAgICAgICAgdGhpcy51dGNPZmZzZXQoKSA+IHRoaXMuY2xvbmUoKS5tb250aCg1KS51dGNPZmZzZXQoKVxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzRGF5bGlnaHRTYXZpbmdUaW1lU2hpZnRlZCgpIHtcbiAgICAgICAgaWYgKCFpc1VuZGVmaW5lZCh0aGlzLl9pc0RTVFNoaWZ0ZWQpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNEU1RTaGlmdGVkO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGMgPSB7fSxcbiAgICAgICAgICAgIG90aGVyO1xuXG4gICAgICAgIGNvcHlDb25maWcoYywgdGhpcyk7XG4gICAgICAgIGMgPSBwcmVwYXJlQ29uZmlnKGMpO1xuXG4gICAgICAgIGlmIChjLl9hKSB7XG4gICAgICAgICAgICBvdGhlciA9IGMuX2lzVVRDID8gY3JlYXRlVVRDKGMuX2EpIDogY3JlYXRlTG9jYWwoYy5fYSk7XG4gICAgICAgICAgICB0aGlzLl9pc0RTVFNoaWZ0ZWQgPVxuICAgICAgICAgICAgICAgIHRoaXMuaXNWYWxpZCgpICYmIGNvbXBhcmVBcnJheXMoYy5fYSwgb3RoZXIudG9BcnJheSgpKSA+IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9pc0RTVFNoaWZ0ZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLl9pc0RTVFNoaWZ0ZWQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNMb2NhbCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gIXRoaXMuX2lzVVRDIDogZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNVdGNPZmZzZXQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMuX2lzVVRDIDogZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNVdGMoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzVmFsaWQoKSA/IHRoaXMuX2lzVVRDICYmIHRoaXMuX29mZnNldCA9PT0gMCA6IGZhbHNlO1xuICAgIH1cblxuICAgIC8vIEFTUC5ORVQganNvbiBkYXRlIGZvcm1hdCByZWdleFxuICAgIHZhciBhc3BOZXRSZWdleCA9IC9eKC18XFwrKT8oPzooXFxkKilbLiBdKT8oXFxkKyk6KFxcZCspKD86OihcXGQrKShcXC5cXGQqKT8pPyQvLFxuICAgICAgICAvLyBmcm9tIGh0dHA6Ly9kb2NzLmNsb3N1cmUtbGlicmFyeS5nb29nbGVjb2RlLmNvbS9naXQvY2xvc3VyZV9nb29nX2RhdGVfZGF0ZS5qcy5zb3VyY2UuaHRtbFxuICAgICAgICAvLyBzb21ld2hhdCBtb3JlIGluIGxpbmUgd2l0aCA0LjQuMy4yIDIwMDQgc3BlYywgYnV0IGFsbG93cyBkZWNpbWFsIGFueXdoZXJlXG4gICAgICAgIC8vIGFuZCBmdXJ0aGVyIG1vZGlmaWVkIHRvIGFsbG93IGZvciBzdHJpbmdzIGNvbnRhaW5pbmcgYm90aCB3ZWVrIGFuZCBkYXlcbiAgICAgICAgaXNvUmVnZXggPSAvXigtfFxcKyk/UCg/OihbLStdP1swLTksLl0qKVkpPyg/OihbLStdP1swLTksLl0qKU0pPyg/OihbLStdP1swLTksLl0qKVcpPyg/OihbLStdP1swLTksLl0qKUQpPyg/OlQoPzooWy0rXT9bMC05LC5dKilIKT8oPzooWy0rXT9bMC05LC5dKilNKT8oPzooWy0rXT9bMC05LC5dKilTKT8pPyQvO1xuXG4gICAgZnVuY3Rpb24gY3JlYXRlRHVyYXRpb24oaW5wdXQsIGtleSkge1xuICAgICAgICB2YXIgZHVyYXRpb24gPSBpbnB1dCxcbiAgICAgICAgICAgIC8vIG1hdGNoaW5nIGFnYWluc3QgcmVnZXhwIGlzIGV4cGVuc2l2ZSwgZG8gaXQgb24gZGVtYW5kXG4gICAgICAgICAgICBtYXRjaCA9IG51bGwsXG4gICAgICAgICAgICBzaWduLFxuICAgICAgICAgICAgcmV0LFxuICAgICAgICAgICAgZGlmZlJlcztcblxuICAgICAgICBpZiAoaXNEdXJhdGlvbihpbnB1dCkpIHtcbiAgICAgICAgICAgIGR1cmF0aW9uID0ge1xuICAgICAgICAgICAgICAgIG1zOiBpbnB1dC5fbWlsbGlzZWNvbmRzLFxuICAgICAgICAgICAgICAgIGQ6IGlucHV0Ll9kYXlzLFxuICAgICAgICAgICAgICAgIE06IGlucHV0Ll9tb250aHMsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2UgaWYgKGlzTnVtYmVyKGlucHV0KSB8fCAhaXNOYU4oK2lucHV0KSkge1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7fTtcbiAgICAgICAgICAgIGlmIChrZXkpIHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbltrZXldID0gK2lucHV0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbi5taWxsaXNlY29uZHMgPSAraW5wdXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoKG1hdGNoID0gYXNwTmV0UmVnZXguZXhlYyhpbnB1dCkpKSB7XG4gICAgICAgICAgICBzaWduID0gbWF0Y2hbMV0gPT09ICctJyA/IC0xIDogMTtcbiAgICAgICAgICAgIGR1cmF0aW9uID0ge1xuICAgICAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICAgICAgZDogdG9JbnQobWF0Y2hbREFURV0pICogc2lnbixcbiAgICAgICAgICAgICAgICBoOiB0b0ludChtYXRjaFtIT1VSXSkgKiBzaWduLFxuICAgICAgICAgICAgICAgIG06IHRvSW50KG1hdGNoW01JTlVURV0pICogc2lnbixcbiAgICAgICAgICAgICAgICBzOiB0b0ludChtYXRjaFtTRUNPTkRdKSAqIHNpZ24sXG4gICAgICAgICAgICAgICAgbXM6IHRvSW50KGFic1JvdW5kKG1hdGNoW01JTExJU0VDT05EXSAqIDEwMDApKSAqIHNpZ24sIC8vIHRoZSBtaWxsaXNlY29uZCBkZWNpbWFsIHBvaW50IGlzIGluY2x1ZGVkIGluIHRoZSBtYXRjaFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmICgobWF0Y2ggPSBpc29SZWdleC5leGVjKGlucHV0KSkpIHtcbiAgICAgICAgICAgIHNpZ24gPSBtYXRjaFsxXSA9PT0gJy0nID8gLTEgOiAxO1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgeTogcGFyc2VJc28obWF0Y2hbMl0sIHNpZ24pLFxuICAgICAgICAgICAgICAgIE06IHBhcnNlSXNvKG1hdGNoWzNdLCBzaWduKSxcbiAgICAgICAgICAgICAgICB3OiBwYXJzZUlzbyhtYXRjaFs0XSwgc2lnbiksXG4gICAgICAgICAgICAgICAgZDogcGFyc2VJc28obWF0Y2hbNV0sIHNpZ24pLFxuICAgICAgICAgICAgICAgIGg6IHBhcnNlSXNvKG1hdGNoWzZdLCBzaWduKSxcbiAgICAgICAgICAgICAgICBtOiBwYXJzZUlzbyhtYXRjaFs3XSwgc2lnbiksXG4gICAgICAgICAgICAgICAgczogcGFyc2VJc28obWF0Y2hbOF0sIHNpZ24pLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfSBlbHNlIGlmIChkdXJhdGlvbiA9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBjaGVja3MgZm9yIG51bGwgb3IgdW5kZWZpbmVkXG4gICAgICAgICAgICBkdXJhdGlvbiA9IHt9O1xuICAgICAgICB9IGVsc2UgaWYgKFxuICAgICAgICAgICAgdHlwZW9mIGR1cmF0aW9uID09PSAnb2JqZWN0JyAmJlxuICAgICAgICAgICAgKCdmcm9tJyBpbiBkdXJhdGlvbiB8fCAndG8nIGluIGR1cmF0aW9uKVxuICAgICAgICApIHtcbiAgICAgICAgICAgIGRpZmZSZXMgPSBtb21lbnRzRGlmZmVyZW5jZShcbiAgICAgICAgICAgICAgICBjcmVhdGVMb2NhbChkdXJhdGlvbi5mcm9tKSxcbiAgICAgICAgICAgICAgICBjcmVhdGVMb2NhbChkdXJhdGlvbi50bylcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIGR1cmF0aW9uID0ge307XG4gICAgICAgICAgICBkdXJhdGlvbi5tcyA9IGRpZmZSZXMubWlsbGlzZWNvbmRzO1xuICAgICAgICAgICAgZHVyYXRpb24uTSA9IGRpZmZSZXMubW9udGhzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0ID0gbmV3IER1cmF0aW9uKGR1cmF0aW9uKTtcblxuICAgICAgICBpZiAoaXNEdXJhdGlvbihpbnB1dCkgJiYgaGFzT3duUHJvcChpbnB1dCwgJ19sb2NhbGUnKSkge1xuICAgICAgICAgICAgcmV0Ll9sb2NhbGUgPSBpbnB1dC5fbG9jYWxlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzRHVyYXRpb24oaW5wdXQpICYmIGhhc093blByb3AoaW5wdXQsICdfaXNWYWxpZCcpKSB7XG4gICAgICAgICAgICByZXQuX2lzVmFsaWQgPSBpbnB1dC5faXNWYWxpZDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgfVxuXG4gICAgY3JlYXRlRHVyYXRpb24uZm4gPSBEdXJhdGlvbi5wcm90b3R5cGU7XG4gICAgY3JlYXRlRHVyYXRpb24uaW52YWxpZCA9IGNyZWF0ZUludmFsaWQkMTtcblxuICAgIGZ1bmN0aW9uIHBhcnNlSXNvKGlucCwgc2lnbikge1xuICAgICAgICAvLyBXZSdkIG5vcm1hbGx5IHVzZSB+fmlucCBmb3IgdGhpcywgYnV0IHVuZm9ydHVuYXRlbHkgaXQgYWxzb1xuICAgICAgICAvLyBjb252ZXJ0cyBmbG9hdHMgdG8gaW50cy5cbiAgICAgICAgLy8gaW5wIG1heSBiZSB1bmRlZmluZWQsIHNvIGNhcmVmdWwgY2FsbGluZyByZXBsYWNlIG9uIGl0LlxuICAgICAgICB2YXIgcmVzID0gaW5wICYmIHBhcnNlRmxvYXQoaW5wLnJlcGxhY2UoJywnLCAnLicpKTtcbiAgICAgICAgLy8gYXBwbHkgc2lnbiB3aGlsZSB3ZSdyZSBhdCBpdFxuICAgICAgICByZXR1cm4gKGlzTmFOKHJlcykgPyAwIDogcmVzKSAqIHNpZ247XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcG9zaXRpdmVNb21lbnRzRGlmZmVyZW5jZShiYXNlLCBvdGhlcikge1xuICAgICAgICB2YXIgcmVzID0ge307XG5cbiAgICAgICAgcmVzLm1vbnRocyA9XG4gICAgICAgICAgICBvdGhlci5tb250aCgpIC0gYmFzZS5tb250aCgpICsgKG90aGVyLnllYXIoKSAtIGJhc2UueWVhcigpKSAqIDEyO1xuICAgICAgICBpZiAoYmFzZS5jbG9uZSgpLmFkZChyZXMubW9udGhzLCAnTScpLmlzQWZ0ZXIob3RoZXIpKSB7XG4gICAgICAgICAgICAtLXJlcy5tb250aHM7XG4gICAgICAgIH1cblxuICAgICAgICByZXMubWlsbGlzZWNvbmRzID0gK290aGVyIC0gK2Jhc2UuY2xvbmUoKS5hZGQocmVzLm1vbnRocywgJ00nKTtcblxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1vbWVudHNEaWZmZXJlbmNlKGJhc2UsIG90aGVyKSB7XG4gICAgICAgIHZhciByZXM7XG4gICAgICAgIGlmICghKGJhc2UuaXNWYWxpZCgpICYmIG90aGVyLmlzVmFsaWQoKSkpIHtcbiAgICAgICAgICAgIHJldHVybiB7IG1pbGxpc2Vjb25kczogMCwgbW9udGhzOiAwIH07XG4gICAgICAgIH1cblxuICAgICAgICBvdGhlciA9IGNsb25lV2l0aE9mZnNldChvdGhlciwgYmFzZSk7XG4gICAgICAgIGlmIChiYXNlLmlzQmVmb3JlKG90aGVyKSkge1xuICAgICAgICAgICAgcmVzID0gcG9zaXRpdmVNb21lbnRzRGlmZmVyZW5jZShiYXNlLCBvdGhlcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXMgPSBwb3NpdGl2ZU1vbWVudHNEaWZmZXJlbmNlKG90aGVyLCBiYXNlKTtcbiAgICAgICAgICAgIHJlcy5taWxsaXNlY29uZHMgPSAtcmVzLm1pbGxpc2Vjb25kcztcbiAgICAgICAgICAgIHJlcy5tb250aHMgPSAtcmVzLm1vbnRocztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfVxuXG4gICAgLy8gVE9ETzogcmVtb3ZlICduYW1lJyBhcmcgYWZ0ZXIgZGVwcmVjYXRpb24gaXMgcmVtb3ZlZFxuICAgIGZ1bmN0aW9uIGNyZWF0ZUFkZGVyKGRpcmVjdGlvbiwgbmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKHZhbCwgcGVyaW9kKSB7XG4gICAgICAgICAgICB2YXIgZHVyLCB0bXA7XG4gICAgICAgICAgICAvL2ludmVydCB0aGUgYXJndW1lbnRzLCBidXQgY29tcGxhaW4gYWJvdXQgaXRcbiAgICAgICAgICAgIGlmIChwZXJpb2QgIT09IG51bGwgJiYgIWlzTmFOKCtwZXJpb2QpKSB7XG4gICAgICAgICAgICAgICAgZGVwcmVjYXRlU2ltcGxlKFxuICAgICAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgICAgICAnbW9tZW50KCkuJyArXG4gICAgICAgICAgICAgICAgICAgICAgICBuYW1lICtcbiAgICAgICAgICAgICAgICAgICAgICAgICcocGVyaW9kLCBudW1iZXIpIGlzIGRlcHJlY2F0ZWQuIFBsZWFzZSB1c2UgbW9tZW50KCkuJyArXG4gICAgICAgICAgICAgICAgICAgICAgICBuYW1lICtcbiAgICAgICAgICAgICAgICAgICAgICAgICcobnVtYmVyLCBwZXJpb2QpLiAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICdTZWUgaHR0cDovL21vbWVudGpzLmNvbS9ndWlkZXMvIy93YXJuaW5ncy9hZGQtaW52ZXJ0ZWQtcGFyYW0vIGZvciBtb3JlIGluZm8uJ1xuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgdG1wID0gdmFsO1xuICAgICAgICAgICAgICAgIHZhbCA9IHBlcmlvZDtcbiAgICAgICAgICAgICAgICBwZXJpb2QgPSB0bXA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGR1ciA9IGNyZWF0ZUR1cmF0aW9uKHZhbCwgcGVyaW9kKTtcbiAgICAgICAgICAgIGFkZFN1YnRyYWN0KHRoaXMsIGR1ciwgZGlyZWN0aW9uKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFkZFN1YnRyYWN0KG1vbSwgZHVyYXRpb24sIGlzQWRkaW5nLCB1cGRhdGVPZmZzZXQpIHtcbiAgICAgICAgdmFyIG1pbGxpc2Vjb25kcyA9IGR1cmF0aW9uLl9taWxsaXNlY29uZHMsXG4gICAgICAgICAgICBkYXlzID0gYWJzUm91bmQoZHVyYXRpb24uX2RheXMpLFxuICAgICAgICAgICAgbW9udGhzID0gYWJzUm91bmQoZHVyYXRpb24uX21vbnRocyk7XG5cbiAgICAgICAgaWYgKCFtb20uaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICAvLyBObyBvcFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdXBkYXRlT2Zmc2V0ID0gdXBkYXRlT2Zmc2V0ID09IG51bGwgPyB0cnVlIDogdXBkYXRlT2Zmc2V0O1xuXG4gICAgICAgIGlmIChtb250aHMpIHtcbiAgICAgICAgICAgIHNldE1vbnRoKG1vbSwgZ2V0KG1vbSwgJ01vbnRoJykgKyBtb250aHMgKiBpc0FkZGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGRheXMpIHtcbiAgICAgICAgICAgIHNldCQxKG1vbSwgJ0RhdGUnLCBnZXQobW9tLCAnRGF0ZScpICsgZGF5cyAqIGlzQWRkaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobWlsbGlzZWNvbmRzKSB7XG4gICAgICAgICAgICBtb20uX2Quc2V0VGltZShtb20uX2QudmFsdWVPZigpICsgbWlsbGlzZWNvbmRzICogaXNBZGRpbmcpO1xuICAgICAgICB9XG4gICAgICAgIGlmICh1cGRhdGVPZmZzZXQpIHtcbiAgICAgICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldChtb20sIGRheXMgfHwgbW9udGhzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBhZGQgPSBjcmVhdGVBZGRlcigxLCAnYWRkJyksXG4gICAgICAgIHN1YnRyYWN0ID0gY3JlYXRlQWRkZXIoLTEsICdzdWJ0cmFjdCcpO1xuXG4gICAgZnVuY3Rpb24gaXNTdHJpbmcoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycgfHwgaW5wdXQgaW5zdGFuY2VvZiBTdHJpbmc7XG4gICAgfVxuXG4gICAgLy8gdHlwZSBNb21lbnRJbnB1dCA9IE1vbWVudCB8IERhdGUgfCBzdHJpbmcgfCBudW1iZXIgfCAobnVtYmVyIHwgc3RyaW5nKVtdIHwgTW9tZW50SW5wdXRPYmplY3QgfCB2b2lkOyAvLyBudWxsIHwgdW5kZWZpbmVkXG4gICAgZnVuY3Rpb24gaXNNb21lbnRJbnB1dChpbnB1dCkge1xuICAgICAgICByZXR1cm4gKFxuICAgICAgICAgICAgaXNNb21lbnQoaW5wdXQpIHx8XG4gICAgICAgICAgICBpc0RhdGUoaW5wdXQpIHx8XG4gICAgICAgICAgICBpc1N0cmluZyhpbnB1dCkgfHxcbiAgICAgICAgICAgIGlzTnVtYmVyKGlucHV0KSB8fFxuICAgICAgICAgICAgaXNOdW1iZXJPclN0cmluZ0FycmF5KGlucHV0KSB8fFxuICAgICAgICAgICAgaXNNb21lbnRJbnB1dE9iamVjdChpbnB1dCkgfHxcbiAgICAgICAgICAgIGlucHV0ID09PSBudWxsIHx8XG4gICAgICAgICAgICBpbnB1dCA9PT0gdW5kZWZpbmVkXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNNb21lbnRJbnB1dE9iamVjdChpbnB1dCkge1xuICAgICAgICB2YXIgb2JqZWN0VGVzdCA9IGlzT2JqZWN0KGlucHV0KSAmJiAhaXNPYmplY3RFbXB0eShpbnB1dCksXG4gICAgICAgICAgICBwcm9wZXJ0eVRlc3QgPSBmYWxzZSxcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSBbXG4gICAgICAgICAgICAgICAgJ3llYXJzJyxcbiAgICAgICAgICAgICAgICAneWVhcicsXG4gICAgICAgICAgICAgICAgJ3knLFxuICAgICAgICAgICAgICAgICdtb250aHMnLFxuICAgICAgICAgICAgICAgICdtb250aCcsXG4gICAgICAgICAgICAgICAgJ00nLFxuICAgICAgICAgICAgICAgICdkYXlzJyxcbiAgICAgICAgICAgICAgICAnZGF5JyxcbiAgICAgICAgICAgICAgICAnZCcsXG4gICAgICAgICAgICAgICAgJ2RhdGVzJyxcbiAgICAgICAgICAgICAgICAnZGF0ZScsXG4gICAgICAgICAgICAgICAgJ0QnLFxuICAgICAgICAgICAgICAgICdob3VycycsXG4gICAgICAgICAgICAgICAgJ2hvdXInLFxuICAgICAgICAgICAgICAgICdoJyxcbiAgICAgICAgICAgICAgICAnbWludXRlcycsXG4gICAgICAgICAgICAgICAgJ21pbnV0ZScsXG4gICAgICAgICAgICAgICAgJ20nLFxuICAgICAgICAgICAgICAgICdzZWNvbmRzJyxcbiAgICAgICAgICAgICAgICAnc2Vjb25kJyxcbiAgICAgICAgICAgICAgICAncycsXG4gICAgICAgICAgICAgICAgJ21pbGxpc2Vjb25kcycsXG4gICAgICAgICAgICAgICAgJ21pbGxpc2Vjb25kJyxcbiAgICAgICAgICAgICAgICAnbXMnLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICBwcm9wZXJ0eTtcblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgcHJvcGVydGllcy5sZW5ndGg7IGkgKz0gMSkge1xuICAgICAgICAgICAgcHJvcGVydHkgPSBwcm9wZXJ0aWVzW2ldO1xuICAgICAgICAgICAgcHJvcGVydHlUZXN0ID0gcHJvcGVydHlUZXN0IHx8IGhhc093blByb3AoaW5wdXQsIHByb3BlcnR5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvYmplY3RUZXN0ICYmIHByb3BlcnR5VGVzdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc051bWJlck9yU3RyaW5nQXJyYXkoaW5wdXQpIHtcbiAgICAgICAgdmFyIGFycmF5VGVzdCA9IGlzQXJyYXkoaW5wdXQpLFxuICAgICAgICAgICAgZGF0YVR5cGVUZXN0ID0gZmFsc2U7XG4gICAgICAgIGlmIChhcnJheVRlc3QpIHtcbiAgICAgICAgICAgIGRhdGFUeXBlVGVzdCA9XG4gICAgICAgICAgICAgICAgaW5wdXQuZmlsdGVyKGZ1bmN0aW9uIChpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAhaXNOdW1iZXIoaXRlbSkgJiYgaXNTdHJpbmcoaW5wdXQpO1xuICAgICAgICAgICAgICAgIH0pLmxlbmd0aCA9PT0gMDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXJyYXlUZXN0ICYmIGRhdGFUeXBlVGVzdDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0NhbGVuZGFyU3BlYyhpbnB1dCkge1xuICAgICAgICB2YXIgb2JqZWN0VGVzdCA9IGlzT2JqZWN0KGlucHV0KSAmJiAhaXNPYmplY3RFbXB0eShpbnB1dCksXG4gICAgICAgICAgICBwcm9wZXJ0eVRlc3QgPSBmYWxzZSxcbiAgICAgICAgICAgIHByb3BlcnRpZXMgPSBbXG4gICAgICAgICAgICAgICAgJ3NhbWVEYXknLFxuICAgICAgICAgICAgICAgICduZXh0RGF5JyxcbiAgICAgICAgICAgICAgICAnbGFzdERheScsXG4gICAgICAgICAgICAgICAgJ25leHRXZWVrJyxcbiAgICAgICAgICAgICAgICAnbGFzdFdlZWsnLFxuICAgICAgICAgICAgICAgICdzYW1lRWxzZScsXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIHByb3BlcnR5O1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBwcm9wZXJ0aWVzLmxlbmd0aDsgaSArPSAxKSB7XG4gICAgICAgICAgICBwcm9wZXJ0eSA9IHByb3BlcnRpZXNbaV07XG4gICAgICAgICAgICBwcm9wZXJ0eVRlc3QgPSBwcm9wZXJ0eVRlc3QgfHwgaGFzT3duUHJvcChpbnB1dCwgcHJvcGVydHkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG9iamVjdFRlc3QgJiYgcHJvcGVydHlUZXN0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldENhbGVuZGFyRm9ybWF0KG15TW9tZW50LCBub3cpIHtcbiAgICAgICAgdmFyIGRpZmYgPSBteU1vbWVudC5kaWZmKG5vdywgJ2RheXMnLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIGRpZmYgPCAtNlxuICAgICAgICAgICAgPyAnc2FtZUVsc2UnXG4gICAgICAgICAgICA6IGRpZmYgPCAtMVxuICAgICAgICAgICAgPyAnbGFzdFdlZWsnXG4gICAgICAgICAgICA6IGRpZmYgPCAwXG4gICAgICAgICAgICA/ICdsYXN0RGF5J1xuICAgICAgICAgICAgOiBkaWZmIDwgMVxuICAgICAgICAgICAgPyAnc2FtZURheSdcbiAgICAgICAgICAgIDogZGlmZiA8IDJcbiAgICAgICAgICAgID8gJ25leHREYXknXG4gICAgICAgICAgICA6IGRpZmYgPCA3XG4gICAgICAgICAgICA/ICduZXh0V2VlaydcbiAgICAgICAgICAgIDogJ3NhbWVFbHNlJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjYWxlbmRhciQxKHRpbWUsIGZvcm1hdHMpIHtcbiAgICAgICAgLy8gU3VwcG9ydCBmb3Igc2luZ2xlIHBhcmFtZXRlciwgZm9ybWF0cyBvbmx5IG92ZXJsb2FkIHRvIHRoZSBjYWxlbmRhciBmdW5jdGlvblxuICAgICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgaWYgKGlzTW9tZW50SW5wdXQoYXJndW1lbnRzWzBdKSkge1xuICAgICAgICAgICAgICAgIHRpbWUgPSBhcmd1bWVudHNbMF07XG4gICAgICAgICAgICAgICAgZm9ybWF0cyA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaXNDYWxlbmRhclNwZWMoYXJndW1lbnRzWzBdKSkge1xuICAgICAgICAgICAgICAgIGZvcm1hdHMgPSBhcmd1bWVudHNbMF07XG4gICAgICAgICAgICAgICAgdGltZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvLyBXZSB3YW50IHRvIGNvbXBhcmUgdGhlIHN0YXJ0IG9mIHRvZGF5LCB2cyB0aGlzLlxuICAgICAgICAvLyBHZXR0aW5nIHN0YXJ0LW9mLXRvZGF5IGRlcGVuZHMgb24gd2hldGhlciB3ZSdyZSBsb2NhbC91dGMvb2Zmc2V0IG9yIG5vdC5cbiAgICAgICAgdmFyIG5vdyA9IHRpbWUgfHwgY3JlYXRlTG9jYWwoKSxcbiAgICAgICAgICAgIHNvZCA9IGNsb25lV2l0aE9mZnNldChub3csIHRoaXMpLnN0YXJ0T2YoJ2RheScpLFxuICAgICAgICAgICAgZm9ybWF0ID0gaG9va3MuY2FsZW5kYXJGb3JtYXQodGhpcywgc29kKSB8fCAnc2FtZUVsc2UnLFxuICAgICAgICAgICAgb3V0cHV0ID1cbiAgICAgICAgICAgICAgICBmb3JtYXRzICYmXG4gICAgICAgICAgICAgICAgKGlzRnVuY3Rpb24oZm9ybWF0c1tmb3JtYXRdKVxuICAgICAgICAgICAgICAgICAgICA/IGZvcm1hdHNbZm9ybWF0XS5jYWxsKHRoaXMsIG5vdylcbiAgICAgICAgICAgICAgICAgICAgOiBmb3JtYXRzW2Zvcm1hdF0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdChcbiAgICAgICAgICAgIG91dHB1dCB8fCB0aGlzLmxvY2FsZURhdGEoKS5jYWxlbmRhcihmb3JtYXQsIHRoaXMsIGNyZWF0ZUxvY2FsKG5vdykpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xvbmUoKSB7XG4gICAgICAgIHJldHVybiBuZXcgTW9tZW50KHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzQWZ0ZXIoaW5wdXQsIHVuaXRzKSB7XG4gICAgICAgIHZhciBsb2NhbElucHV0ID0gaXNNb21lbnQoaW5wdXQpID8gaW5wdXQgOiBjcmVhdGVMb2NhbChpbnB1dCk7XG4gICAgICAgIGlmICghKHRoaXMuaXNWYWxpZCgpICYmIGxvY2FsSW5wdXQuaXNWYWxpZCgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpIHx8ICdtaWxsaXNlY29uZCc7XG4gICAgICAgIGlmICh1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVPZigpID4gbG9jYWxJbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbG9jYWxJbnB1dC52YWx1ZU9mKCkgPCB0aGlzLmNsb25lKCkuc3RhcnRPZih1bml0cykudmFsdWVPZigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNCZWZvcmUoaW5wdXQsIHVuaXRzKSB7XG4gICAgICAgIHZhciBsb2NhbElucHV0ID0gaXNNb21lbnQoaW5wdXQpID8gaW5wdXQgOiBjcmVhdGVMb2NhbChpbnB1dCk7XG4gICAgICAgIGlmICghKHRoaXMuaXNWYWxpZCgpICYmIGxvY2FsSW5wdXQuaXNWYWxpZCgpKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpIHx8ICdtaWxsaXNlY29uZCc7XG4gICAgICAgIGlmICh1bml0cyA9PT0gJ21pbGxpc2Vjb25kJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsdWVPZigpIDwgbG9jYWxJbnB1dC52YWx1ZU9mKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmVuZE9mKHVuaXRzKS52YWx1ZU9mKCkgPCBsb2NhbElucHV0LnZhbHVlT2YoKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzQmV0d2Vlbihmcm9tLCB0bywgdW5pdHMsIGluY2x1c2l2aXR5KSB7XG4gICAgICAgIHZhciBsb2NhbEZyb20gPSBpc01vbWVudChmcm9tKSA/IGZyb20gOiBjcmVhdGVMb2NhbChmcm9tKSxcbiAgICAgICAgICAgIGxvY2FsVG8gPSBpc01vbWVudCh0bykgPyB0byA6IGNyZWF0ZUxvY2FsKHRvKTtcbiAgICAgICAgaWYgKCEodGhpcy5pc1ZhbGlkKCkgJiYgbG9jYWxGcm9tLmlzVmFsaWQoKSAmJiBsb2NhbFRvLmlzVmFsaWQoKSkpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpbmNsdXNpdml0eSA9IGluY2x1c2l2aXR5IHx8ICcoKSc7XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAoaW5jbHVzaXZpdHlbMF0gPT09ICcoJ1xuICAgICAgICAgICAgICAgID8gdGhpcy5pc0FmdGVyKGxvY2FsRnJvbSwgdW5pdHMpXG4gICAgICAgICAgICAgICAgOiAhdGhpcy5pc0JlZm9yZShsb2NhbEZyb20sIHVuaXRzKSkgJiZcbiAgICAgICAgICAgIChpbmNsdXNpdml0eVsxXSA9PT0gJyknXG4gICAgICAgICAgICAgICAgPyB0aGlzLmlzQmVmb3JlKGxvY2FsVG8sIHVuaXRzKVxuICAgICAgICAgICAgICAgIDogIXRoaXMuaXNBZnRlcihsb2NhbFRvLCB1bml0cykpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNTYW1lKGlucHV0LCB1bml0cykge1xuICAgICAgICB2YXIgbG9jYWxJbnB1dCA9IGlzTW9tZW50KGlucHV0KSA/IGlucHV0IDogY3JlYXRlTG9jYWwoaW5wdXQpLFxuICAgICAgICAgICAgaW5wdXRNcztcbiAgICAgICAgaWYgKCEodGhpcy5pc1ZhbGlkKCkgJiYgbG9jYWxJbnB1dC5pc1ZhbGlkKCkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cykgfHwgJ21pbGxpc2Vjb25kJztcbiAgICAgICAgaWYgKHVuaXRzID09PSAnbWlsbGlzZWNvbmQnKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWx1ZU9mKCkgPT09IGxvY2FsSW5wdXQudmFsdWVPZigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaW5wdXRNcyA9IGxvY2FsSW5wdXQudmFsdWVPZigpO1xuICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICB0aGlzLmNsb25lKCkuc3RhcnRPZih1bml0cykudmFsdWVPZigpIDw9IGlucHV0TXMgJiZcbiAgICAgICAgICAgICAgICBpbnB1dE1zIDw9IHRoaXMuY2xvbmUoKS5lbmRPZih1bml0cykudmFsdWVPZigpXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNTYW1lT3JBZnRlcihpbnB1dCwgdW5pdHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNTYW1lKGlucHV0LCB1bml0cykgfHwgdGhpcy5pc0FmdGVyKGlucHV0LCB1bml0cyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaXNTYW1lT3JCZWZvcmUoaW5wdXQsIHVuaXRzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzU2FtZShpbnB1dCwgdW5pdHMpIHx8IHRoaXMuaXNCZWZvcmUoaW5wdXQsIHVuaXRzKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkaWZmKGlucHV0LCB1bml0cywgYXNGbG9hdCkge1xuICAgICAgICB2YXIgdGhhdCwgem9uZURlbHRhLCBvdXRwdXQ7XG5cbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoYXQgPSBjbG9uZVdpdGhPZmZzZXQoaW5wdXQsIHRoaXMpO1xuXG4gICAgICAgIGlmICghdGhhdC5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cblxuICAgICAgICB6b25lRGVsdGEgPSAodGhhdC51dGNPZmZzZXQoKSAtIHRoaXMudXRjT2Zmc2V0KCkpICogNmU0O1xuXG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuXG4gICAgICAgIHN3aXRjaCAodW5pdHMpIHtcbiAgICAgICAgICAgIGNhc2UgJ3llYXInOlxuICAgICAgICAgICAgICAgIG91dHB1dCA9IG1vbnRoRGlmZih0aGlzLCB0aGF0KSAvIDEyO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbW9udGgnOlxuICAgICAgICAgICAgICAgIG91dHB1dCA9IG1vbnRoRGlmZih0aGlzLCB0aGF0KTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3F1YXJ0ZXInOlxuICAgICAgICAgICAgICAgIG91dHB1dCA9IG1vbnRoRGlmZih0aGlzLCB0aGF0KSAvIDM7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzZWNvbmQnOlxuICAgICAgICAgICAgICAgIG91dHB1dCA9ICh0aGlzIC0gdGhhdCkgLyAxZTM7XG4gICAgICAgICAgICAgICAgYnJlYWs7IC8vIDEwMDBcbiAgICAgICAgICAgIGNhc2UgJ21pbnV0ZSc6XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKHRoaXMgLSB0aGF0KSAvIDZlNDtcbiAgICAgICAgICAgICAgICBicmVhazsgLy8gMTAwMCAqIDYwXG4gICAgICAgICAgICBjYXNlICdob3VyJzpcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAodGhpcyAtIHRoYXQpIC8gMzZlNTtcbiAgICAgICAgICAgICAgICBicmVhazsgLy8gMTAwMCAqIDYwICogNjBcbiAgICAgICAgICAgIGNhc2UgJ2RheSc6XG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKHRoaXMgLSB0aGF0IC0gem9uZURlbHRhKSAvIDg2NGU1O1xuICAgICAgICAgICAgICAgIGJyZWFrOyAvLyAxMDAwICogNjAgKiA2MCAqIDI0LCBuZWdhdGUgZHN0XG4gICAgICAgICAgICBjYXNlICd3ZWVrJzpcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSAodGhpcyAtIHRoYXQgLSB6b25lRGVsdGEpIC8gNjA0OGU1O1xuICAgICAgICAgICAgICAgIGJyZWFrOyAvLyAxMDAwICogNjAgKiA2MCAqIDI0ICogNywgbmVnYXRlIGRzdFxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSB0aGlzIC0gdGhhdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBhc0Zsb2F0ID8gb3V0cHV0IDogYWJzRmxvb3Iob3V0cHV0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb250aERpZmYoYSwgYikge1xuICAgICAgICBpZiAoYS5kYXRlKCkgPCBiLmRhdGUoKSkge1xuICAgICAgICAgICAgLy8gZW5kLW9mLW1vbnRoIGNhbGN1bGF0aW9ucyB3b3JrIGNvcnJlY3Qgd2hlbiB0aGUgc3RhcnQgbW9udGggaGFzIG1vcmVcbiAgICAgICAgICAgIC8vIGRheXMgdGhhbiB0aGUgZW5kIG1vbnRoLlxuICAgICAgICAgICAgcmV0dXJuIC1tb250aERpZmYoYiwgYSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gZGlmZmVyZW5jZSBpbiBtb250aHNcbiAgICAgICAgdmFyIHdob2xlTW9udGhEaWZmID0gKGIueWVhcigpIC0gYS55ZWFyKCkpICogMTIgKyAoYi5tb250aCgpIC0gYS5tb250aCgpKSxcbiAgICAgICAgICAgIC8vIGIgaXMgaW4gKGFuY2hvciAtIDEgbW9udGgsIGFuY2hvciArIDEgbW9udGgpXG4gICAgICAgICAgICBhbmNob3IgPSBhLmNsb25lKCkuYWRkKHdob2xlTW9udGhEaWZmLCAnbW9udGhzJyksXG4gICAgICAgICAgICBhbmNob3IyLFxuICAgICAgICAgICAgYWRqdXN0O1xuXG4gICAgICAgIGlmIChiIC0gYW5jaG9yIDwgMCkge1xuICAgICAgICAgICAgYW5jaG9yMiA9IGEuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYgLSAxLCAnbW9udGhzJyk7XG4gICAgICAgICAgICAvLyBsaW5lYXIgYWNyb3NzIHRoZSBtb250aFxuICAgICAgICAgICAgYWRqdXN0ID0gKGIgLSBhbmNob3IpIC8gKGFuY2hvciAtIGFuY2hvcjIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYW5jaG9yMiA9IGEuY2xvbmUoKS5hZGQod2hvbGVNb250aERpZmYgKyAxLCAnbW9udGhzJyk7XG4gICAgICAgICAgICAvLyBsaW5lYXIgYWNyb3NzIHRoZSBtb250aFxuICAgICAgICAgICAgYWRqdXN0ID0gKGIgLSBhbmNob3IpIC8gKGFuY2hvcjIgLSBhbmNob3IpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9jaGVjayBmb3IgbmVnYXRpdmUgemVybywgcmV0dXJuIHplcm8gaWYgbmVnYXRpdmUgemVyb1xuICAgICAgICByZXR1cm4gLSh3aG9sZU1vbnRoRGlmZiArIGFkanVzdCkgfHwgMDtcbiAgICB9XG5cbiAgICBob29rcy5kZWZhdWx0Rm9ybWF0ID0gJ1lZWVktTU0tRERUSEg6bW06c3NaJztcbiAgICBob29rcy5kZWZhdWx0Rm9ybWF0VXRjID0gJ1lZWVktTU0tRERUSEg6bW06c3NbWl0nO1xuXG4gICAgZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNsb25lKCkubG9jYWxlKCdlbicpLmZvcm1hdCgnZGRkIE1NTSBERCBZWVlZIEhIOm1tOnNzIFtHTVRdWlonKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b0lTT1N0cmluZyhrZWVwT2Zmc2V0KSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHZhciB1dGMgPSBrZWVwT2Zmc2V0ICE9PSB0cnVlLFxuICAgICAgICAgICAgbSA9IHV0YyA/IHRoaXMuY2xvbmUoKS51dGMoKSA6IHRoaXM7XG4gICAgICAgIGlmIChtLnllYXIoKSA8IDAgfHwgbS55ZWFyKCkgPiA5OTk5KSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0TW9tZW50KFxuICAgICAgICAgICAgICAgIG0sXG4gICAgICAgICAgICAgICAgdXRjXG4gICAgICAgICAgICAgICAgICAgID8gJ1lZWVlZWS1NTS1ERFtUXUhIOm1tOnNzLlNTU1taXSdcbiAgICAgICAgICAgICAgICAgICAgOiAnWVlZWVlZLU1NLUREW1RdSEg6bW06c3MuU1NTWidcbiAgICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzRnVuY3Rpb24oRGF0ZS5wcm90b3R5cGUudG9JU09TdHJpbmcpKSB7XG4gICAgICAgICAgICAvLyBuYXRpdmUgaW1wbGVtZW50YXRpb24gaXMgfjUweCBmYXN0ZXIsIHVzZSBpdCB3aGVuIHdlIGNhblxuICAgICAgICAgICAgaWYgKHV0Yykge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnRvRGF0ZSgpLnRvSVNPU3RyaW5nKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGF0ZSh0aGlzLnZhbHVlT2YoKSArIHRoaXMudXRjT2Zmc2V0KCkgKiA2MCAqIDEwMDApXG4gICAgICAgICAgICAgICAgICAgIC50b0lTT1N0cmluZygpXG4gICAgICAgICAgICAgICAgICAgIC5yZXBsYWNlKCdaJywgZm9ybWF0TW9tZW50KG0sICdaJykpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmb3JtYXRNb21lbnQoXG4gICAgICAgICAgICBtLFxuICAgICAgICAgICAgdXRjID8gJ1lZWVktTU0tRERbVF1ISDptbTpzcy5TU1NbWl0nIDogJ1lZWVktTU0tRERbVF1ISDptbTpzcy5TU1NaJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIGh1bWFuIHJlYWRhYmxlIHJlcHJlc2VudGF0aW9uIG9mIGEgbW9tZW50IHRoYXQgY2FuXG4gICAgICogYWxzbyBiZSBldmFsdWF0ZWQgdG8gZ2V0IGEgbmV3IG1vbWVudCB3aGljaCBpcyB0aGUgc2FtZVxuICAgICAqXG4gICAgICogQGxpbmsgaHR0cHM6Ly9ub2RlanMub3JnL2Rpc3QvbGF0ZXN0L2RvY3MvYXBpL3V0aWwuaHRtbCN1dGlsX2N1c3RvbV9pbnNwZWN0X2Z1bmN0aW9uX29uX29iamVjdHNcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpbnNwZWN0KCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gJ21vbWVudC5pbnZhbGlkKC8qICcgKyB0aGlzLl9pICsgJyAqLyknO1xuICAgICAgICB9XG4gICAgICAgIHZhciBmdW5jID0gJ21vbWVudCcsXG4gICAgICAgICAgICB6b25lID0gJycsXG4gICAgICAgICAgICBwcmVmaXgsXG4gICAgICAgICAgICB5ZWFyLFxuICAgICAgICAgICAgZGF0ZXRpbWUsXG4gICAgICAgICAgICBzdWZmaXg7XG4gICAgICAgIGlmICghdGhpcy5pc0xvY2FsKCkpIHtcbiAgICAgICAgICAgIGZ1bmMgPSB0aGlzLnV0Y09mZnNldCgpID09PSAwID8gJ21vbWVudC51dGMnIDogJ21vbWVudC5wYXJzZVpvbmUnO1xuICAgICAgICAgICAgem9uZSA9ICdaJztcbiAgICAgICAgfVxuICAgICAgICBwcmVmaXggPSAnWycgKyBmdW5jICsgJyhcIl0nO1xuICAgICAgICB5ZWFyID0gMCA8PSB0aGlzLnllYXIoKSAmJiB0aGlzLnllYXIoKSA8PSA5OTk5ID8gJ1lZWVknIDogJ1lZWVlZWSc7XG4gICAgICAgIGRhdGV0aW1lID0gJy1NTS1ERFtUXUhIOm1tOnNzLlNTUyc7XG4gICAgICAgIHN1ZmZpeCA9IHpvbmUgKyAnW1wiKV0nO1xuXG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdChwcmVmaXggKyB5ZWFyICsgZGF0ZXRpbWUgKyBzdWZmaXgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZvcm1hdChpbnB1dFN0cmluZykge1xuICAgICAgICBpZiAoIWlucHV0U3RyaW5nKSB7XG4gICAgICAgICAgICBpbnB1dFN0cmluZyA9IHRoaXMuaXNVdGMoKVxuICAgICAgICAgICAgICAgID8gaG9va3MuZGVmYXVsdEZvcm1hdFV0Y1xuICAgICAgICAgICAgICAgIDogaG9va3MuZGVmYXVsdEZvcm1hdDtcbiAgICAgICAgfVxuICAgICAgICB2YXIgb3V0cHV0ID0gZm9ybWF0TW9tZW50KHRoaXMsIGlucHV0U3RyaW5nKTtcbiAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLnBvc3Rmb3JtYXQob3V0cHV0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmcm9tKHRpbWUsIHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy5pc1ZhbGlkKCkgJiZcbiAgICAgICAgICAgICgoaXNNb21lbnQodGltZSkgJiYgdGltZS5pc1ZhbGlkKCkpIHx8IGNyZWF0ZUxvY2FsKHRpbWUpLmlzVmFsaWQoKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgICByZXR1cm4gY3JlYXRlRHVyYXRpb24oeyB0bzogdGhpcywgZnJvbTogdGltZSB9KVxuICAgICAgICAgICAgICAgIC5sb2NhbGUodGhpcy5sb2NhbGUoKSlcbiAgICAgICAgICAgICAgICAuaHVtYW5pemUoIXdpdGhvdXRTdWZmaXgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmcm9tTm93KHdpdGhvdXRTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZnJvbShjcmVhdGVMb2NhbCgpLCB3aXRob3V0U3VmZml4KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0byh0aW1lLCB3aXRob3V0U3VmZml4KSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAgIHRoaXMuaXNWYWxpZCgpICYmXG4gICAgICAgICAgICAoKGlzTW9tZW50KHRpbWUpICYmIHRpbWUuaXNWYWxpZCgpKSB8fCBjcmVhdGVMb2NhbCh0aW1lKS5pc1ZhbGlkKCkpXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHsgZnJvbTogdGhpcywgdG86IHRpbWUgfSlcbiAgICAgICAgICAgICAgICAubG9jYWxlKHRoaXMubG9jYWxlKCkpXG4gICAgICAgICAgICAgICAgLmh1bWFuaXplKCF3aXRob3V0U3VmZml4KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxvY2FsZURhdGEoKS5pbnZhbGlkRGF0ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdG9Ob3cod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gdGhpcy50byhjcmVhdGVMb2NhbCgpLCB3aXRob3V0U3VmZml4KTtcbiAgICB9XG5cbiAgICAvLyBJZiBwYXNzZWQgYSBsb2NhbGUga2V5LCBpdCB3aWxsIHNldCB0aGUgbG9jYWxlIGZvciB0aGlzXG4gICAgLy8gaW5zdGFuY2UuICBPdGhlcndpc2UsIGl0IHdpbGwgcmV0dXJuIHRoZSBsb2NhbGUgY29uZmlndXJhdGlvblxuICAgIC8vIHZhcmlhYmxlcyBmb3IgdGhpcyBpbnN0YW5jZS5cbiAgICBmdW5jdGlvbiBsb2NhbGUoa2V5KSB7XG4gICAgICAgIHZhciBuZXdMb2NhbGVEYXRhO1xuXG4gICAgICAgIGlmIChrZXkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xvY2FsZS5fYWJicjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG5ld0xvY2FsZURhdGEgPSBnZXRMb2NhbGUoa2V5KTtcbiAgICAgICAgICAgIGlmIChuZXdMb2NhbGVEYXRhICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2NhbGUgPSBuZXdMb2NhbGVEYXRhO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgbGFuZyA9IGRlcHJlY2F0ZShcbiAgICAgICAgJ21vbWVudCgpLmxhbmcoKSBpcyBkZXByZWNhdGVkLiBJbnN0ZWFkLCB1c2UgbW9tZW50KCkubG9jYWxlRGF0YSgpIHRvIGdldCB0aGUgbGFuZ3VhZ2UgY29uZmlndXJhdGlvbi4gVXNlIG1vbWVudCgpLmxvY2FsZSgpIHRvIGNoYW5nZSBsYW5ndWFnZXMuJyxcbiAgICAgICAgZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGUoa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICk7XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVEYXRhKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbG9jYWxlO1xuICAgIH1cblxuICAgIHZhciBNU19QRVJfU0VDT05EID0gMTAwMCxcbiAgICAgICAgTVNfUEVSX01JTlVURSA9IDYwICogTVNfUEVSX1NFQ09ORCxcbiAgICAgICAgTVNfUEVSX0hPVVIgPSA2MCAqIE1TX1BFUl9NSU5VVEUsXG4gICAgICAgIE1TX1BFUl80MDBfWUVBUlMgPSAoMzY1ICogNDAwICsgOTcpICogMjQgKiBNU19QRVJfSE9VUjtcblxuICAgIC8vIGFjdHVhbCBtb2R1bG8gLSBoYW5kbGVzIG5lZ2F0aXZlIG51bWJlcnMgKGZvciBkYXRlcyBiZWZvcmUgMTk3MCk6XG4gICAgZnVuY3Rpb24gbW9kJDEoZGl2aWRlbmQsIGRpdmlzb3IpIHtcbiAgICAgICAgcmV0dXJuICgoZGl2aWRlbmQgJSBkaXZpc29yKSArIGRpdmlzb3IpICUgZGl2aXNvcjtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbFN0YXJ0T2ZEYXRlKHksIG0sIGQpIHtcbiAgICAgICAgLy8gdGhlIGRhdGUgY29uc3RydWN0b3IgcmVtYXBzIHllYXJzIDAtOTkgdG8gMTkwMC0xOTk5XG4gICAgICAgIGlmICh5IDwgMTAwICYmIHkgPj0gMCkge1xuICAgICAgICAgICAgLy8gcHJlc2VydmUgbGVhcCB5ZWFycyB1c2luZyBhIGZ1bGwgNDAwIHllYXIgY3ljbGUsIHRoZW4gcmVzZXRcbiAgICAgICAgICAgIHJldHVybiBuZXcgRGF0ZSh5ICsgNDAwLCBtLCBkKSAtIE1TX1BFUl80MDBfWUVBUlM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IERhdGUoeSwgbSwgZCkudmFsdWVPZigpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdXRjU3RhcnRPZkRhdGUoeSwgbSwgZCkge1xuICAgICAgICAvLyBEYXRlLlVUQyByZW1hcHMgeWVhcnMgMC05OSB0byAxOTAwLTE5OTlcbiAgICAgICAgaWYgKHkgPCAxMDAgJiYgeSA+PSAwKSB7XG4gICAgICAgICAgICAvLyBwcmVzZXJ2ZSBsZWFwIHllYXJzIHVzaW5nIGEgZnVsbCA0MDAgeWVhciBjeWNsZSwgdGhlbiByZXNldFxuICAgICAgICAgICAgcmV0dXJuIERhdGUuVVRDKHkgKyA0MDAsIG0sIGQpIC0gTVNfUEVSXzQwMF9ZRUFSUztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBEYXRlLlVUQyh5LCBtLCBkKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0YXJ0T2YodW5pdHMpIHtcbiAgICAgICAgdmFyIHRpbWUsIHN0YXJ0T2ZEYXRlO1xuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICAgICAgaWYgKHVuaXRzID09PSB1bmRlZmluZWQgfHwgdW5pdHMgPT09ICdtaWxsaXNlY29uZCcgfHwgIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXJ0T2ZEYXRlID0gdGhpcy5faXNVVEMgPyB1dGNTdGFydE9mRGF0ZSA6IGxvY2FsU3RhcnRPZkRhdGU7XG5cbiAgICAgICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICAgICAgY2FzZSAneWVhcic6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpLCAwLCAxKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3F1YXJ0ZXInOlxuICAgICAgICAgICAgICAgIHRpbWUgPSBzdGFydE9mRGF0ZShcbiAgICAgICAgICAgICAgICAgICAgdGhpcy55ZWFyKCksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubW9udGgoKSAtICh0aGlzLm1vbnRoKCkgJSAzKSxcbiAgICAgICAgICAgICAgICAgICAgMVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdtb250aCc6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpLCB0aGlzLm1vbnRoKCksIDEpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnd2Vlayc6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnllYXIoKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tb250aCgpLFxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRhdGUoKSAtIHRoaXMud2Vla2RheSgpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2lzb1dlZWsnOlxuICAgICAgICAgICAgICAgIHRpbWUgPSBzdGFydE9mRGF0ZShcbiAgICAgICAgICAgICAgICAgICAgdGhpcy55ZWFyKCksXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubW9udGgoKSxcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKCkgLSAodGhpcy5pc29XZWVrZGF5KCkgLSAxKVxuICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkYXknOlxuICAgICAgICAgICAgY2FzZSAnZGF0ZSc6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpLCB0aGlzLm1vbnRoKCksIHRoaXMuZGF0ZSgpKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2hvdXInOlxuICAgICAgICAgICAgICAgIHRpbWUgPSB0aGlzLl9kLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICB0aW1lIC09IG1vZCQxKFxuICAgICAgICAgICAgICAgICAgICB0aW1lICsgKHRoaXMuX2lzVVRDID8gMCA6IHRoaXMudXRjT2Zmc2V0KCkgKiBNU19QRVJfTUlOVVRFKSxcbiAgICAgICAgICAgICAgICAgICAgTVNfUEVSX0hPVVJcbiAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbWludXRlJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gdGhpcy5fZC52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgdGltZSAtPSBtb2QkMSh0aW1lLCBNU19QRVJfTUlOVVRFKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3NlY29uZCc6XG4gICAgICAgICAgICAgICAgdGltZSA9IHRoaXMuX2QudmFsdWVPZigpO1xuICAgICAgICAgICAgICAgIHRpbWUgLT0gbW9kJDEodGltZSwgTVNfUEVSX1NFQ09ORCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9kLnNldFRpbWUodGltZSk7XG4gICAgICAgIGhvb2tzLnVwZGF0ZU9mZnNldCh0aGlzLCB0cnVlKTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZW5kT2YodW5pdHMpIHtcbiAgICAgICAgdmFyIHRpbWUsIHN0YXJ0T2ZEYXRlO1xuICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICAgICAgaWYgKHVuaXRzID09PSB1bmRlZmluZWQgfHwgdW5pdHMgPT09ICdtaWxsaXNlY29uZCcgfHwgIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHN0YXJ0T2ZEYXRlID0gdGhpcy5faXNVVEMgPyB1dGNTdGFydE9mRGF0ZSA6IGxvY2FsU3RhcnRPZkRhdGU7XG5cbiAgICAgICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICAgICAgY2FzZSAneWVhcic6XG4gICAgICAgICAgICAgICAgdGltZSA9IHN0YXJ0T2ZEYXRlKHRoaXMueWVhcigpICsgMSwgMCwgMSkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAncXVhcnRlcic6XG4gICAgICAgICAgICAgICAgdGltZSA9XG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0T2ZEYXRlKFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy55ZWFyKCksXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm1vbnRoKCkgLSAodGhpcy5tb250aCgpICUgMykgKyAzLFxuICAgICAgICAgICAgICAgICAgICAgICAgMVxuICAgICAgICAgICAgICAgICAgICApIC0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ21vbnRoJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gc3RhcnRPZkRhdGUodGhpcy55ZWFyKCksIHRoaXMubW9udGgoKSArIDEsIDEpIC0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ3dlZWsnOlxuICAgICAgICAgICAgICAgIHRpbWUgPVxuICAgICAgICAgICAgICAgICAgICBzdGFydE9mRGF0ZShcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMueWVhcigpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5tb250aCgpLFxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5kYXRlKCkgLSB0aGlzLndlZWtkYXkoKSArIDdcbiAgICAgICAgICAgICAgICAgICAgKSAtIDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdpc29XZWVrJzpcbiAgICAgICAgICAgICAgICB0aW1lID1cbiAgICAgICAgICAgICAgICAgICAgc3RhcnRPZkRhdGUoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnllYXIoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubW9udGgoKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGF0ZSgpIC0gKHRoaXMuaXNvV2Vla2RheSgpIC0gMSkgKyA3XG4gICAgICAgICAgICAgICAgICAgICkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZGF5JzpcbiAgICAgICAgICAgIGNhc2UgJ2RhdGUnOlxuICAgICAgICAgICAgICAgIHRpbWUgPSBzdGFydE9mRGF0ZSh0aGlzLnllYXIoKSwgdGhpcy5tb250aCgpLCB0aGlzLmRhdGUoKSArIDEpIC0gMTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ2hvdXInOlxuICAgICAgICAgICAgICAgIHRpbWUgPSB0aGlzLl9kLnZhbHVlT2YoKTtcbiAgICAgICAgICAgICAgICB0aW1lICs9XG4gICAgICAgICAgICAgICAgICAgIE1TX1BFUl9IT1VSIC1cbiAgICAgICAgICAgICAgICAgICAgbW9kJDEoXG4gICAgICAgICAgICAgICAgICAgICAgICB0aW1lICsgKHRoaXMuX2lzVVRDID8gMCA6IHRoaXMudXRjT2Zmc2V0KCkgKiBNU19QRVJfTUlOVVRFKSxcbiAgICAgICAgICAgICAgICAgICAgICAgIE1TX1BFUl9IT1VSXG4gICAgICAgICAgICAgICAgICAgICkgLVxuICAgICAgICAgICAgICAgICAgICAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbWludXRlJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gdGhpcy5fZC52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgdGltZSArPSBNU19QRVJfTUlOVVRFIC0gbW9kJDEodGltZSwgTVNfUEVSX01JTlVURSkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnc2Vjb25kJzpcbiAgICAgICAgICAgICAgICB0aW1lID0gdGhpcy5fZC52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgdGltZSArPSBNU19QRVJfU0VDT05EIC0gbW9kJDEodGltZSwgTVNfUEVSX1NFQ09ORCkgLSAxO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZC5zZXRUaW1lKHRpbWUpO1xuICAgICAgICBob29rcy51cGRhdGVPZmZzZXQodGhpcywgdHJ1ZSk7XG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZhbHVlT2YoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9kLnZhbHVlT2YoKSAtICh0aGlzLl9vZmZzZXQgfHwgMCkgKiA2MDAwMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1bml4KCkge1xuICAgICAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLnZhbHVlT2YoKSAvIDEwMDApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvRGF0ZSgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBEYXRlKHRoaXMudmFsdWVPZigpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b0FycmF5KCkge1xuICAgICAgICB2YXIgbSA9IHRoaXM7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICBtLnllYXIoKSxcbiAgICAgICAgICAgIG0ubW9udGgoKSxcbiAgICAgICAgICAgIG0uZGF0ZSgpLFxuICAgICAgICAgICAgbS5ob3VyKCksXG4gICAgICAgICAgICBtLm1pbnV0ZSgpLFxuICAgICAgICAgICAgbS5zZWNvbmQoKSxcbiAgICAgICAgICAgIG0ubWlsbGlzZWNvbmQoKSxcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB0b09iamVjdCgpIHtcbiAgICAgICAgdmFyIG0gPSB0aGlzO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeWVhcnM6IG0ueWVhcigpLFxuICAgICAgICAgICAgbW9udGhzOiBtLm1vbnRoKCksXG4gICAgICAgICAgICBkYXRlOiBtLmRhdGUoKSxcbiAgICAgICAgICAgIGhvdXJzOiBtLmhvdXJzKCksXG4gICAgICAgICAgICBtaW51dGVzOiBtLm1pbnV0ZXMoKSxcbiAgICAgICAgICAgIHNlY29uZHM6IG0uc2Vjb25kcygpLFxuICAgICAgICAgICAgbWlsbGlzZWNvbmRzOiBtLm1pbGxpc2Vjb25kcygpLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvSlNPTigpIHtcbiAgICAgICAgLy8gbmV3IERhdGUoTmFOKS50b0pTT04oKSA9PT0gbnVsbFxuICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyB0aGlzLnRvSVNPU3RyaW5nKCkgOiBudWxsO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzVmFsaWQkMigpIHtcbiAgICAgICAgcmV0dXJuIGlzVmFsaWQodGhpcyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2luZ0ZsYWdzKCkge1xuICAgICAgICByZXR1cm4gZXh0ZW5kKHt9LCBnZXRQYXJzaW5nRmxhZ3ModGhpcykpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGludmFsaWRBdCgpIHtcbiAgICAgICAgcmV0dXJuIGdldFBhcnNpbmdGbGFncyh0aGlzKS5vdmVyZmxvdztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGlvbkRhdGEoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpbnB1dDogdGhpcy5faSxcbiAgICAgICAgICAgIGZvcm1hdDogdGhpcy5fZixcbiAgICAgICAgICAgIGxvY2FsZTogdGhpcy5fbG9jYWxlLFxuICAgICAgICAgICAgaXNVVEM6IHRoaXMuX2lzVVRDLFxuICAgICAgICAgICAgc3RyaWN0OiB0aGlzLl9zdHJpY3QsXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ04nLCAwLCAwLCAnZXJhQWJicicpO1xuICAgIGFkZEZvcm1hdFRva2VuKCdOTicsIDAsIDAsICdlcmFBYmJyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ05OTicsIDAsIDAsICdlcmFBYmJyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ05OTk4nLCAwLCAwLCAnZXJhTmFtZScpO1xuICAgIGFkZEZvcm1hdFRva2VuKCdOTk5OTicsIDAsIDAsICdlcmFOYXJyb3cnKTtcblxuICAgIGFkZEZvcm1hdFRva2VuKCd5JywgWyd5JywgMV0sICd5bycsICdlcmFZZWFyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ3knLCBbJ3l5JywgMl0sIDAsICdlcmFZZWFyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ3knLCBbJ3l5eScsIDNdLCAwLCAnZXJhWWVhcicpO1xuICAgIGFkZEZvcm1hdFRva2VuKCd5JywgWyd5eXl5JywgNF0sIDAsICdlcmFZZWFyJyk7XG5cbiAgICBhZGRSZWdleFRva2VuKCdOJywgbWF0Y2hFcmFBYmJyKTtcbiAgICBhZGRSZWdleFRva2VuKCdOTicsIG1hdGNoRXJhQWJicik7XG4gICAgYWRkUmVnZXhUb2tlbignTk5OJywgbWF0Y2hFcmFBYmJyKTtcbiAgICBhZGRSZWdleFRva2VuKCdOTk5OJywgbWF0Y2hFcmFOYW1lKTtcbiAgICBhZGRSZWdleFRva2VuKCdOTk5OTicsIG1hdGNoRXJhTmFycm93KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydOJywgJ05OJywgJ05OTicsICdOTk5OJywgJ05OTk5OJ10sIGZ1bmN0aW9uIChcbiAgICAgICAgaW5wdXQsXG4gICAgICAgIGFycmF5LFxuICAgICAgICBjb25maWcsXG4gICAgICAgIHRva2VuXG4gICAgKSB7XG4gICAgICAgIHZhciBlcmEgPSBjb25maWcuX2xvY2FsZS5lcmFzUGFyc2UoaW5wdXQsIHRva2VuLCBjb25maWcuX3N0cmljdCk7XG4gICAgICAgIGlmIChlcmEpIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmVyYSA9IGVyYTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGdldFBhcnNpbmdGbGFncyhjb25maWcpLmludmFsaWRFcmEgPSBpbnB1dDtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgYWRkUmVnZXhUb2tlbigneScsIG1hdGNoVW5zaWduZWQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ3l5JywgbWF0Y2hVbnNpZ25lZCk7XG4gICAgYWRkUmVnZXhUb2tlbigneXl5JywgbWF0Y2hVbnNpZ25lZCk7XG4gICAgYWRkUmVnZXhUb2tlbigneXl5eScsIG1hdGNoVW5zaWduZWQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ3lvJywgbWF0Y2hFcmFZZWFyT3JkaW5hbCk7XG5cbiAgICBhZGRQYXJzZVRva2VuKFsneScsICd5eScsICd5eXknLCAneXl5eSddLCBZRUFSKTtcbiAgICBhZGRQYXJzZVRva2VuKFsneW8nXSwgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnLCB0b2tlbikge1xuICAgICAgICB2YXIgbWF0Y2g7XG4gICAgICAgIGlmIChjb25maWcuX2xvY2FsZS5fZXJhWWVhck9yZGluYWxSZWdleCkge1xuICAgICAgICAgICAgbWF0Y2ggPSBpbnB1dC5tYXRjaChjb25maWcuX2xvY2FsZS5fZXJhWWVhck9yZGluYWxSZWdleCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY29uZmlnLl9sb2NhbGUuZXJhWWVhck9yZGluYWxQYXJzZSkge1xuICAgICAgICAgICAgYXJyYXlbWUVBUl0gPSBjb25maWcuX2xvY2FsZS5lcmFZZWFyT3JkaW5hbFBhcnNlKGlucHV0LCBtYXRjaCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhcnJheVtZRUFSXSA9IHBhcnNlSW50KGlucHV0LCAxMCk7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIGZ1bmN0aW9uIGxvY2FsZUVyYXMobSwgZm9ybWF0KSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgbCxcbiAgICAgICAgICAgIGRhdGUsXG4gICAgICAgICAgICBlcmFzID0gdGhpcy5fZXJhcyB8fCBnZXRMb2NhbGUoJ2VuJykuX2VyYXM7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBlcmFzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgc3dpdGNoICh0eXBlb2YgZXJhc1tpXS5zaW5jZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3N0cmluZyc6XG4gICAgICAgICAgICAgICAgICAgIC8vIHRydW5jYXRlIHRpbWVcbiAgICAgICAgICAgICAgICAgICAgZGF0ZSA9IGhvb2tzKGVyYXNbaV0uc2luY2UpLnN0YXJ0T2YoJ2RheScpO1xuICAgICAgICAgICAgICAgICAgICBlcmFzW2ldLnNpbmNlID0gZGF0ZS52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzd2l0Y2ggKHR5cGVvZiBlcmFzW2ldLnVudGlsKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAndW5kZWZpbmVkJzpcbiAgICAgICAgICAgICAgICAgICAgZXJhc1tpXS51bnRpbCA9ICtJbmZpbml0eTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgICAgICAgICAgICAgICAgLy8gdHJ1bmNhdGUgdGltZVxuICAgICAgICAgICAgICAgICAgICBkYXRlID0gaG9va3MoZXJhc1tpXS51bnRpbCkuc3RhcnRPZignZGF5JykudmFsdWVPZigpO1xuICAgICAgICAgICAgICAgICAgICBlcmFzW2ldLnVudGlsID0gZGF0ZS52YWx1ZU9mKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlcmFzO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxvY2FsZUVyYXNQYXJzZShlcmFOYW1lLCBmb3JtYXQsIHN0cmljdCkge1xuICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgIGwsXG4gICAgICAgICAgICBlcmFzID0gdGhpcy5lcmFzKCksXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgYWJicixcbiAgICAgICAgICAgIG5hcnJvdztcbiAgICAgICAgZXJhTmFtZSA9IGVyYU5hbWUudG9VcHBlckNhc2UoKTtcblxuICAgICAgICBmb3IgKGkgPSAwLCBsID0gZXJhcy5sZW5ndGg7IGkgPCBsOyArK2kpIHtcbiAgICAgICAgICAgIG5hbWUgPSBlcmFzW2ldLm5hbWUudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIGFiYnIgPSBlcmFzW2ldLmFiYnIudG9VcHBlckNhc2UoKTtcbiAgICAgICAgICAgIG5hcnJvdyA9IGVyYXNbaV0ubmFycm93LnRvVXBwZXJDYXNlKCk7XG5cbiAgICAgICAgICAgIGlmIChzdHJpY3QpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGZvcm1hdCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlICdOJzpcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAnTk4nOlxuICAgICAgICAgICAgICAgICAgICBjYXNlICdOTk4nOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGFiYnIgPT09IGVyYU5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJhc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ05OTk4nOlxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5hbWUgPT09IGVyYU5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJhc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ05OTk5OJzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuYXJyb3cgPT09IGVyYU5hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJhc1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAoW25hbWUsIGFiYnIsIG5hcnJvd10uaW5kZXhPZihlcmFOYW1lKSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVyYXNbaV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsb2NhbGVFcmFzQ29udmVydFllYXIoZXJhLCB5ZWFyKSB7XG4gICAgICAgIHZhciBkaXIgPSBlcmEuc2luY2UgPD0gZXJhLnVudGlsID8gKzEgOiAtMTtcbiAgICAgICAgaWYgKHllYXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGhvb2tzKGVyYS5zaW5jZSkueWVhcigpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIGhvb2tzKGVyYS5zaW5jZSkueWVhcigpICsgKHllYXIgLSBlcmEub2Zmc2V0KSAqIGRpcjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEVyYU5hbWUoKSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgbCxcbiAgICAgICAgICAgIHZhbCxcbiAgICAgICAgICAgIGVyYXMgPSB0aGlzLmxvY2FsZURhdGEoKS5lcmFzKCk7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBlcmFzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgLy8gdHJ1bmNhdGUgdGltZVxuICAgICAgICAgICAgdmFsID0gdGhpcy5zdGFydE9mKCdkYXknKS52YWx1ZU9mKCk7XG5cbiAgICAgICAgICAgIGlmIChlcmFzW2ldLnNpbmNlIDw9IHZhbCAmJiB2YWwgPD0gZXJhc1tpXS51bnRpbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlcmFzW2ldLm5hbWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZXJhc1tpXS51bnRpbCA8PSB2YWwgJiYgdmFsIDw9IGVyYXNbaV0uc2luY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXJhc1tpXS5uYW1lO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEVyYU5hcnJvdygpIHtcbiAgICAgICAgdmFyIGksXG4gICAgICAgICAgICBsLFxuICAgICAgICAgICAgdmFsLFxuICAgICAgICAgICAgZXJhcyA9IHRoaXMubG9jYWxlRGF0YSgpLmVyYXMoKTtcbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGVyYXMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICAvLyB0cnVuY2F0ZSB0aW1lXG4gICAgICAgICAgICB2YWwgPSB0aGlzLnN0YXJ0T2YoJ2RheScpLnZhbHVlT2YoKTtcblxuICAgICAgICAgICAgaWYgKGVyYXNbaV0uc2luY2UgPD0gdmFsICYmIHZhbCA8PSBlcmFzW2ldLnVudGlsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVyYXNbaV0ubmFycm93O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVyYXNbaV0udW50aWwgPD0gdmFsICYmIHZhbCA8PSBlcmFzW2ldLnNpbmNlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVyYXNbaV0ubmFycm93O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEVyYUFiYnIoKSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgbCxcbiAgICAgICAgICAgIHZhbCxcbiAgICAgICAgICAgIGVyYXMgPSB0aGlzLmxvY2FsZURhdGEoKS5lcmFzKCk7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBlcmFzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgLy8gdHJ1bmNhdGUgdGltZVxuICAgICAgICAgICAgdmFsID0gdGhpcy5zdGFydE9mKCdkYXknKS52YWx1ZU9mKCk7XG5cbiAgICAgICAgICAgIGlmIChlcmFzW2ldLnNpbmNlIDw9IHZhbCAmJiB2YWwgPD0gZXJhc1tpXS51bnRpbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBlcmFzW2ldLmFiYnI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZXJhc1tpXS51bnRpbCA8PSB2YWwgJiYgdmFsIDw9IGVyYXNbaV0uc2luY2UpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXJhc1tpXS5hYmJyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEVyYVllYXIoKSB7XG4gICAgICAgIHZhciBpLFxuICAgICAgICAgICAgbCxcbiAgICAgICAgICAgIGRpcixcbiAgICAgICAgICAgIHZhbCxcbiAgICAgICAgICAgIGVyYXMgPSB0aGlzLmxvY2FsZURhdGEoKS5lcmFzKCk7XG4gICAgICAgIGZvciAoaSA9IDAsIGwgPSBlcmFzLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgICAgICAgICAgZGlyID0gZXJhc1tpXS5zaW5jZSA8PSBlcmFzW2ldLnVudGlsID8gKzEgOiAtMTtcblxuICAgICAgICAgICAgLy8gdHJ1bmNhdGUgdGltZVxuICAgICAgICAgICAgdmFsID0gdGhpcy5zdGFydE9mKCdkYXknKS52YWx1ZU9mKCk7XG5cbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAoZXJhc1tpXS5zaW5jZSA8PSB2YWwgJiYgdmFsIDw9IGVyYXNbaV0udW50aWwpIHx8XG4gICAgICAgICAgICAgICAgKGVyYXNbaV0udW50aWwgPD0gdmFsICYmIHZhbCA8PSBlcmFzW2ldLnNpbmNlKVxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgKHRoaXMueWVhcigpIC0gaG9va3MoZXJhc1tpXS5zaW5jZSkueWVhcigpKSAqIGRpciArXG4gICAgICAgICAgICAgICAgICAgIGVyYXNbaV0ub2Zmc2V0XG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnllYXIoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBlcmFzTmFtZVJlZ2V4KGlzU3RyaWN0KSB7XG4gICAgICAgIGlmICghaGFzT3duUHJvcCh0aGlzLCAnX2VyYXNOYW1lUmVnZXgnKSkge1xuICAgICAgICAgICAgY29tcHV0ZUVyYXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc1N0cmljdCA/IHRoaXMuX2VyYXNOYW1lUmVnZXggOiB0aGlzLl9lcmFzUmVnZXg7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXJhc0FiYnJSZWdleChpc1N0cmljdCkge1xuICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19lcmFzQWJiclJlZ2V4JykpIHtcbiAgICAgICAgICAgIGNvbXB1dGVFcmFzUGFyc2UuY2FsbCh0aGlzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNTdHJpY3QgPyB0aGlzLl9lcmFzQWJiclJlZ2V4IDogdGhpcy5fZXJhc1JlZ2V4O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGVyYXNOYXJyb3dSZWdleChpc1N0cmljdCkge1xuICAgICAgICBpZiAoIWhhc093blByb3AodGhpcywgJ19lcmFzTmFycm93UmVnZXgnKSkge1xuICAgICAgICAgICAgY29tcHV0ZUVyYXNQYXJzZS5jYWxsKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpc1N0cmljdCA/IHRoaXMuX2VyYXNOYXJyb3dSZWdleCA6IHRoaXMuX2VyYXNSZWdleDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYXRjaEVyYUFiYnIoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLmVyYXNBYmJyUmVnZXgoaXNTdHJpY3QpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1hdGNoRXJhTmFtZShpc1N0cmljdCwgbG9jYWxlKSB7XG4gICAgICAgIHJldHVybiBsb2NhbGUuZXJhc05hbWVSZWdleChpc1N0cmljdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWF0Y2hFcmFOYXJyb3coaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLmVyYXNOYXJyb3dSZWdleChpc1N0cmljdCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWF0Y2hFcmFZZWFyT3JkaW5hbChpc1N0cmljdCwgbG9jYWxlKSB7XG4gICAgICAgIHJldHVybiBsb2NhbGUuX2VyYVllYXJPcmRpbmFsUmVnZXggfHwgbWF0Y2hVbnNpZ25lZDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb21wdXRlRXJhc1BhcnNlKCkge1xuICAgICAgICB2YXIgYWJiclBpZWNlcyA9IFtdLFxuICAgICAgICAgICAgbmFtZVBpZWNlcyA9IFtdLFxuICAgICAgICAgICAgbmFycm93UGllY2VzID0gW10sXG4gICAgICAgICAgICBtaXhlZFBpZWNlcyA9IFtdLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIGwsXG4gICAgICAgICAgICBlcmFzID0gdGhpcy5lcmFzKCk7XG5cbiAgICAgICAgZm9yIChpID0gMCwgbCA9IGVyYXMubGVuZ3RoOyBpIDwgbDsgKytpKSB7XG4gICAgICAgICAgICBuYW1lUGllY2VzLnB1c2gocmVnZXhFc2NhcGUoZXJhc1tpXS5uYW1lKSk7XG4gICAgICAgICAgICBhYmJyUGllY2VzLnB1c2gocmVnZXhFc2NhcGUoZXJhc1tpXS5hYmJyKSk7XG4gICAgICAgICAgICBuYXJyb3dQaWVjZXMucHVzaChyZWdleEVzY2FwZShlcmFzW2ldLm5hcnJvdykpO1xuXG4gICAgICAgICAgICBtaXhlZFBpZWNlcy5wdXNoKHJlZ2V4RXNjYXBlKGVyYXNbaV0ubmFtZSkpO1xuICAgICAgICAgICAgbWl4ZWRQaWVjZXMucHVzaChyZWdleEVzY2FwZShlcmFzW2ldLmFiYnIpKTtcbiAgICAgICAgICAgIG1peGVkUGllY2VzLnB1c2gocmVnZXhFc2NhcGUoZXJhc1tpXS5uYXJyb3cpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2VyYXNSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIG1peGVkUGllY2VzLmpvaW4oJ3wnKSArICcpJywgJ2knKTtcbiAgICAgICAgdGhpcy5fZXJhc05hbWVSZWdleCA9IG5ldyBSZWdFeHAoJ14oJyArIG5hbWVQaWVjZXMuam9pbignfCcpICsgJyknLCAnaScpO1xuICAgICAgICB0aGlzLl9lcmFzQWJiclJlZ2V4ID0gbmV3IFJlZ0V4cCgnXignICsgYWJiclBpZWNlcy5qb2luKCd8JykgKyAnKScsICdpJyk7XG4gICAgICAgIHRoaXMuX2VyYXNOYXJyb3dSZWdleCA9IG5ldyBSZWdFeHAoXG4gICAgICAgICAgICAnXignICsgbmFycm93UGllY2VzLmpvaW4oJ3wnKSArICcpJyxcbiAgICAgICAgICAgICdpJ1xuICAgICAgICApO1xuICAgIH1cblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnZ2cnLCAyXSwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy53ZWVrWWVhcigpICUgMTAwO1xuICAgIH0pO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydHRycsIDJdLCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmlzb1dlZWtZZWFyKCkgJSAxMDA7XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBhZGRXZWVrWWVhckZvcm1hdFRva2VuKHRva2VuLCBnZXR0ZXIpIHtcbiAgICAgICAgYWRkRm9ybWF0VG9rZW4oMCwgW3Rva2VuLCB0b2tlbi5sZW5ndGhdLCAwLCBnZXR0ZXIpO1xuICAgIH1cblxuICAgIGFkZFdlZWtZZWFyRm9ybWF0VG9rZW4oJ2dnZ2cnLCAnd2Vla1llYXInKTtcbiAgICBhZGRXZWVrWWVhckZvcm1hdFRva2VuKCdnZ2dnZycsICd3ZWVrWWVhcicpO1xuICAgIGFkZFdlZWtZZWFyRm9ybWF0VG9rZW4oJ0dHR0cnLCAnaXNvV2Vla1llYXInKTtcbiAgICBhZGRXZWVrWWVhckZvcm1hdFRva2VuKCdHR0dHRycsICdpc29XZWVrWWVhcicpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCd3ZWVrWWVhcicsICdnZycpO1xuICAgIGFkZFVuaXRBbGlhcygnaXNvV2Vla1llYXInLCAnR0cnKTtcblxuICAgIC8vIFBSSU9SSVRZXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ3dlZWtZZWFyJywgMSk7XG4gICAgYWRkVW5pdFByaW9yaXR5KCdpc29XZWVrWWVhcicsIDEpO1xuXG4gICAgLy8gUEFSU0lOR1xuXG4gICAgYWRkUmVnZXhUb2tlbignRycsIG1hdGNoU2lnbmVkKTtcbiAgICBhZGRSZWdleFRva2VuKCdnJywgbWF0Y2hTaWduZWQpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0dHJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ2dnJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0dHR0cnLCBtYXRjaDF0bzQsIG1hdGNoNCk7XG4gICAgYWRkUmVnZXhUb2tlbignZ2dnZycsIG1hdGNoMXRvNCwgbWF0Y2g0KTtcbiAgICBhZGRSZWdleFRva2VuKCdHR0dHRycsIG1hdGNoMXRvNiwgbWF0Y2g2KTtcbiAgICBhZGRSZWdleFRva2VuKCdnZ2dnZycsIG1hdGNoMXRvNiwgbWF0Y2g2KTtcblxuICAgIGFkZFdlZWtQYXJzZVRva2VuKFsnZ2dnZycsICdnZ2dnZycsICdHR0dHJywgJ0dHR0dHJ10sIGZ1bmN0aW9uIChcbiAgICAgICAgaW5wdXQsXG4gICAgICAgIHdlZWssXG4gICAgICAgIGNvbmZpZyxcbiAgICAgICAgdG9rZW5cbiAgICApIHtcbiAgICAgICAgd2Vla1t0b2tlbi5zdWJzdHIoMCwgMildID0gdG9JbnQoaW5wdXQpO1xuICAgIH0pO1xuXG4gICAgYWRkV2Vla1BhcnNlVG9rZW4oWydnZycsICdHRyddLCBmdW5jdGlvbiAoaW5wdXQsIHdlZWssIGNvbmZpZywgdG9rZW4pIHtcbiAgICAgICAgd2Vla1t0b2tlbl0gPSBob29rcy5wYXJzZVR3b0RpZ2l0WWVhcihpbnB1dCk7XG4gICAgfSk7XG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICBmdW5jdGlvbiBnZXRTZXRXZWVrWWVhcihpbnB1dCkge1xuICAgICAgICByZXR1cm4gZ2V0U2V0V2Vla1llYXJIZWxwZXIuY2FsbChcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICBpbnB1dCxcbiAgICAgICAgICAgIHRoaXMud2VlaygpLFxuICAgICAgICAgICAgdGhpcy53ZWVrZGF5KCksXG4gICAgICAgICAgICB0aGlzLmxvY2FsZURhdGEoKS5fd2Vlay5kb3csXG4gICAgICAgICAgICB0aGlzLmxvY2FsZURhdGEoKS5fd2Vlay5kb3lcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRTZXRJU09XZWVrWWVhcihpbnB1dCkge1xuICAgICAgICByZXR1cm4gZ2V0U2V0V2Vla1llYXJIZWxwZXIuY2FsbChcbiAgICAgICAgICAgIHRoaXMsXG4gICAgICAgICAgICBpbnB1dCxcbiAgICAgICAgICAgIHRoaXMuaXNvV2VlaygpLFxuICAgICAgICAgICAgdGhpcy5pc29XZWVrZGF5KCksXG4gICAgICAgICAgICAxLFxuICAgICAgICAgICAgNFxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldElTT1dlZWtzSW5ZZWFyKCkge1xuICAgICAgICByZXR1cm4gd2Vla3NJblllYXIodGhpcy55ZWFyKCksIDEsIDQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldElTT1dlZWtzSW5JU09XZWVrWWVhcigpIHtcbiAgICAgICAgcmV0dXJuIHdlZWtzSW5ZZWFyKHRoaXMuaXNvV2Vla1llYXIoKSwgMSwgNCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0V2Vla3NJblllYXIoKSB7XG4gICAgICAgIHZhciB3ZWVrSW5mbyA9IHRoaXMubG9jYWxlRGF0YSgpLl93ZWVrO1xuICAgICAgICByZXR1cm4gd2Vla3NJblllYXIodGhpcy55ZWFyKCksIHdlZWtJbmZvLmRvdywgd2Vla0luZm8uZG95KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRXZWVrc0luV2Vla1llYXIoKSB7XG4gICAgICAgIHZhciB3ZWVrSW5mbyA9IHRoaXMubG9jYWxlRGF0YSgpLl93ZWVrO1xuICAgICAgICByZXR1cm4gd2Vla3NJblllYXIodGhpcy53ZWVrWWVhcigpLCB3ZWVrSW5mby5kb3csIHdlZWtJbmZvLmRveSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZ2V0U2V0V2Vla1llYXJIZWxwZXIoaW5wdXQsIHdlZWssIHdlZWtkYXksIGRvdywgZG95KSB7XG4gICAgICAgIHZhciB3ZWVrc1RhcmdldDtcbiAgICAgICAgaWYgKGlucHV0ID09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB3ZWVrT2ZZZWFyKHRoaXMsIGRvdywgZG95KS55ZWFyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgd2Vla3NUYXJnZXQgPSB3ZWVrc0luWWVhcihpbnB1dCwgZG93LCBkb3kpO1xuICAgICAgICAgICAgaWYgKHdlZWsgPiB3ZWVrc1RhcmdldCkge1xuICAgICAgICAgICAgICAgIHdlZWsgPSB3ZWVrc1RhcmdldDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzZXRXZWVrQWxsLmNhbGwodGhpcywgaW5wdXQsIHdlZWssIHdlZWtkYXksIGRvdywgZG95KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNldFdlZWtBbGwod2Vla1llYXIsIHdlZWssIHdlZWtkYXksIGRvdywgZG95KSB7XG4gICAgICAgIHZhciBkYXlPZlllYXJEYXRhID0gZGF5T2ZZZWFyRnJvbVdlZWtzKHdlZWtZZWFyLCB3ZWVrLCB3ZWVrZGF5LCBkb3csIGRveSksXG4gICAgICAgICAgICBkYXRlID0gY3JlYXRlVVRDRGF0ZShkYXlPZlllYXJEYXRhLnllYXIsIDAsIGRheU9mWWVhckRhdGEuZGF5T2ZZZWFyKTtcblxuICAgICAgICB0aGlzLnllYXIoZGF0ZS5nZXRVVENGdWxsWWVhcigpKTtcbiAgICAgICAgdGhpcy5tb250aChkYXRlLmdldFVUQ01vbnRoKCkpO1xuICAgICAgICB0aGlzLmRhdGUoZGF0ZS5nZXRVVENEYXRlKCkpO1xuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbignUScsIDAsICdRbycsICdxdWFydGVyJyk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ3F1YXJ0ZXInLCAnUScpO1xuXG4gICAgLy8gUFJJT1JJVFlcblxuICAgIGFkZFVuaXRQcmlvcml0eSgncXVhcnRlcicsIDcpO1xuXG4gICAgLy8gUEFSU0lOR1xuXG4gICAgYWRkUmVnZXhUb2tlbignUScsIG1hdGNoMSk7XG4gICAgYWRkUGFyc2VUb2tlbignUScsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXkpIHtcbiAgICAgICAgYXJyYXlbTU9OVEhdID0gKHRvSW50KGlucHV0KSAtIDEpICogMztcbiAgICB9KTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIGZ1bmN0aW9uIGdldFNldFF1YXJ0ZXIoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGxcbiAgICAgICAgICAgID8gTWF0aC5jZWlsKCh0aGlzLm1vbnRoKCkgKyAxKSAvIDMpXG4gICAgICAgICAgICA6IHRoaXMubW9udGgoKGlucHV0IC0gMSkgKiAzICsgKHRoaXMubW9udGgoKSAlIDMpKTtcbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbignRCcsIFsnREQnLCAyXSwgJ0RvJywgJ2RhdGUnKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnZGF0ZScsICdEJyk7XG5cbiAgICAvLyBQUklPUklUWVxuICAgIGFkZFVuaXRQcmlvcml0eSgnZGF0ZScsIDkpO1xuXG4gICAgLy8gUEFSU0lOR1xuXG4gICAgYWRkUmVnZXhUb2tlbignRCcsIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignREQnLCBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbignRG8nLCBmdW5jdGlvbiAoaXNTdHJpY3QsIGxvY2FsZSkge1xuICAgICAgICAvLyBUT0RPOiBSZW1vdmUgXCJvcmRpbmFsUGFyc2VcIiBmYWxsYmFjayBpbiBuZXh0IG1ham9yIHJlbGVhc2UuXG4gICAgICAgIHJldHVybiBpc1N0cmljdFxuICAgICAgICAgICAgPyBsb2NhbGUuX2RheU9mTW9udGhPcmRpbmFsUGFyc2UgfHwgbG9jYWxlLl9vcmRpbmFsUGFyc2VcbiAgICAgICAgICAgIDogbG9jYWxlLl9kYXlPZk1vbnRoT3JkaW5hbFBhcnNlTGVuaWVudDtcbiAgICB9KTtcblxuICAgIGFkZFBhcnNlVG9rZW4oWydEJywgJ0REJ10sIERBVEUpO1xuICAgIGFkZFBhcnNlVG9rZW4oJ0RvJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSkge1xuICAgICAgICBhcnJheVtEQVRFXSA9IHRvSW50KGlucHV0Lm1hdGNoKG1hdGNoMXRvMilbMF0pO1xuICAgIH0pO1xuXG4gICAgLy8gTU9NRU5UU1xuXG4gICAgdmFyIGdldFNldERheU9mTW9udGggPSBtYWtlR2V0U2V0KCdEYXRlJywgdHJ1ZSk7XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbignREREJywgWydEREREJywgM10sICdERERvJywgJ2RheU9mWWVhcicpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCdkYXlPZlllYXInLCAnREREJyk7XG5cbiAgICAvLyBQUklPUklUWVxuICAgIGFkZFVuaXRQcmlvcml0eSgnZGF5T2ZZZWFyJywgNCk7XG5cbiAgICAvLyBQQVJTSU5HXG5cbiAgICBhZGRSZWdleFRva2VuKCdEREQnLCBtYXRjaDF0bzMpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ0REREQnLCBtYXRjaDMpO1xuICAgIGFkZFBhcnNlVG9rZW4oWydEREQnLCAnRERERCddLCBmdW5jdGlvbiAoaW5wdXQsIGFycmF5LCBjb25maWcpIHtcbiAgICAgICAgY29uZmlnLl9kYXlPZlllYXIgPSB0b0ludChpbnB1dCk7XG4gICAgfSk7XG5cbiAgICAvLyBIRUxQRVJTXG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICBmdW5jdGlvbiBnZXRTZXREYXlPZlllYXIoaW5wdXQpIHtcbiAgICAgICAgdmFyIGRheU9mWWVhciA9XG4gICAgICAgICAgICBNYXRoLnJvdW5kKFxuICAgICAgICAgICAgICAgICh0aGlzLmNsb25lKCkuc3RhcnRPZignZGF5JykgLSB0aGlzLmNsb25lKCkuc3RhcnRPZigneWVhcicpKSAvIDg2NGU1XG4gICAgICAgICAgICApICsgMTtcbiAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyBkYXlPZlllYXIgOiB0aGlzLmFkZChpbnB1dCAtIGRheU9mWWVhciwgJ2QnKTtcbiAgICB9XG5cbiAgICAvLyBGT1JNQVRUSU5HXG5cbiAgICBhZGRGb3JtYXRUb2tlbignbScsIFsnbW0nLCAyXSwgMCwgJ21pbnV0ZScpO1xuXG4gICAgLy8gQUxJQVNFU1xuXG4gICAgYWRkVW5pdEFsaWFzKCdtaW51dGUnLCAnbScpO1xuXG4gICAgLy8gUFJJT1JJVFlcblxuICAgIGFkZFVuaXRQcmlvcml0eSgnbWludXRlJywgMTQpO1xuXG4gICAgLy8gUEFSU0lOR1xuXG4gICAgYWRkUmVnZXhUb2tlbignbScsIG1hdGNoMXRvMik7XG4gICAgYWRkUmVnZXhUb2tlbignbW0nLCBtYXRjaDF0bzIsIG1hdGNoMik7XG4gICAgYWRkUGFyc2VUb2tlbihbJ20nLCAnbW0nXSwgTUlOVVRFKTtcblxuICAgIC8vIE1PTUVOVFNcblxuICAgIHZhciBnZXRTZXRNaW51dGUgPSBtYWtlR2V0U2V0KCdNaW51dGVzJywgZmFsc2UpO1xuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ3MnLCBbJ3NzJywgMl0sIDAsICdzZWNvbmQnKTtcblxuICAgIC8vIEFMSUFTRVNcblxuICAgIGFkZFVuaXRBbGlhcygnc2Vjb25kJywgJ3MnKTtcblxuICAgIC8vIFBSSU9SSVRZXG5cbiAgICBhZGRVbml0UHJpb3JpdHkoJ3NlY29uZCcsIDE1KTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ3MnLCBtYXRjaDF0bzIpO1xuICAgIGFkZFJlZ2V4VG9rZW4oJ3NzJywgbWF0Y2gxdG8yLCBtYXRjaDIpO1xuICAgIGFkZFBhcnNlVG9rZW4oWydzJywgJ3NzJ10sIFNFQ09ORCk7XG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICB2YXIgZ2V0U2V0U2Vjb25kID0gbWFrZUdldFNldCgnU2Vjb25kcycsIGZhbHNlKTtcblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCdTJywgMCwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gfn4odGhpcy5taWxsaXNlY29uZCgpIC8gMTAwKTtcbiAgICB9KTtcblxuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1MnLCAyXSwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gfn4odGhpcy5taWxsaXNlY29uZCgpIC8gMTApO1xuICAgIH0pO1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydTU1MnLCAzXSwgMCwgJ21pbGxpc2Vjb25kJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydTU1NTJywgNF0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWlsbGlzZWNvbmQoKSAqIDEwO1xuICAgIH0pO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1MnLCA1XSwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTAwO1xuICAgIH0pO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTJywgNl0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWlsbGlzZWNvbmQoKSAqIDEwMDA7XG4gICAgfSk7XG4gICAgYWRkRm9ybWF0VG9rZW4oMCwgWydTU1NTU1NTJywgN10sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWlsbGlzZWNvbmQoKSAqIDEwMDAwO1xuICAgIH0pO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTU1MnLCA4XSwgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5taWxsaXNlY29uZCgpICogMTAwMDAwO1xuICAgIH0pO1xuICAgIGFkZEZvcm1hdFRva2VuKDAsIFsnU1NTU1NTU1NTJywgOV0sIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubWlsbGlzZWNvbmQoKSAqIDEwMDAwMDA7XG4gICAgfSk7XG5cbiAgICAvLyBBTElBU0VTXG5cbiAgICBhZGRVbml0QWxpYXMoJ21pbGxpc2Vjb25kJywgJ21zJyk7XG5cbiAgICAvLyBQUklPUklUWVxuXG4gICAgYWRkVW5pdFByaW9yaXR5KCdtaWxsaXNlY29uZCcsIDE2KTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ1MnLCBtYXRjaDF0bzMsIG1hdGNoMSk7XG4gICAgYWRkUmVnZXhUb2tlbignU1MnLCBtYXRjaDF0bzMsIG1hdGNoMik7XG4gICAgYWRkUmVnZXhUb2tlbignU1NTJywgbWF0Y2gxdG8zLCBtYXRjaDMpO1xuXG4gICAgdmFyIHRva2VuLCBnZXRTZXRNaWxsaXNlY29uZDtcbiAgICBmb3IgKHRva2VuID0gJ1NTU1MnOyB0b2tlbi5sZW5ndGggPD0gOTsgdG9rZW4gKz0gJ1MnKSB7XG4gICAgICAgIGFkZFJlZ2V4VG9rZW4odG9rZW4sIG1hdGNoVW5zaWduZWQpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhcnNlTXMoaW5wdXQsIGFycmF5KSB7XG4gICAgICAgIGFycmF5W01JTExJU0VDT05EXSA9IHRvSW50KCgnMC4nICsgaW5wdXQpICogMTAwMCk7XG4gICAgfVxuXG4gICAgZm9yICh0b2tlbiA9ICdTJzsgdG9rZW4ubGVuZ3RoIDw9IDk7IHRva2VuICs9ICdTJykge1xuICAgICAgICBhZGRQYXJzZVRva2VuKHRva2VuLCBwYXJzZU1zKTtcbiAgICB9XG5cbiAgICBnZXRTZXRNaWxsaXNlY29uZCA9IG1ha2VHZXRTZXQoJ01pbGxpc2Vjb25kcycsIGZhbHNlKTtcblxuICAgIC8vIEZPUk1BVFRJTkdcblxuICAgIGFkZEZvcm1hdFRva2VuKCd6JywgMCwgMCwgJ3pvbmVBYmJyJyk7XG4gICAgYWRkRm9ybWF0VG9rZW4oJ3p6JywgMCwgMCwgJ3pvbmVOYW1lJyk7XG5cbiAgICAvLyBNT01FTlRTXG5cbiAgICBmdW5jdGlvbiBnZXRab25lQWJicigpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzVVRDID8gJ1VUQycgOiAnJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBnZXRab25lTmFtZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzVVRDID8gJ0Nvb3JkaW5hdGVkIFVuaXZlcnNhbCBUaW1lJyA6ICcnO1xuICAgIH1cblxuICAgIHZhciBwcm90byA9IE1vbWVudC5wcm90b3R5cGU7XG5cbiAgICBwcm90by5hZGQgPSBhZGQ7XG4gICAgcHJvdG8uY2FsZW5kYXIgPSBjYWxlbmRhciQxO1xuICAgIHByb3RvLmNsb25lID0gY2xvbmU7XG4gICAgcHJvdG8uZGlmZiA9IGRpZmY7XG4gICAgcHJvdG8uZW5kT2YgPSBlbmRPZjtcbiAgICBwcm90by5mb3JtYXQgPSBmb3JtYXQ7XG4gICAgcHJvdG8uZnJvbSA9IGZyb207XG4gICAgcHJvdG8uZnJvbU5vdyA9IGZyb21Ob3c7XG4gICAgcHJvdG8udG8gPSB0bztcbiAgICBwcm90by50b05vdyA9IHRvTm93O1xuICAgIHByb3RvLmdldCA9IHN0cmluZ0dldDtcbiAgICBwcm90by5pbnZhbGlkQXQgPSBpbnZhbGlkQXQ7XG4gICAgcHJvdG8uaXNBZnRlciA9IGlzQWZ0ZXI7XG4gICAgcHJvdG8uaXNCZWZvcmUgPSBpc0JlZm9yZTtcbiAgICBwcm90by5pc0JldHdlZW4gPSBpc0JldHdlZW47XG4gICAgcHJvdG8uaXNTYW1lID0gaXNTYW1lO1xuICAgIHByb3RvLmlzU2FtZU9yQWZ0ZXIgPSBpc1NhbWVPckFmdGVyO1xuICAgIHByb3RvLmlzU2FtZU9yQmVmb3JlID0gaXNTYW1lT3JCZWZvcmU7XG4gICAgcHJvdG8uaXNWYWxpZCA9IGlzVmFsaWQkMjtcbiAgICBwcm90by5sYW5nID0gbGFuZztcbiAgICBwcm90by5sb2NhbGUgPSBsb2NhbGU7XG4gICAgcHJvdG8ubG9jYWxlRGF0YSA9IGxvY2FsZURhdGE7XG4gICAgcHJvdG8ubWF4ID0gcHJvdG90eXBlTWF4O1xuICAgIHByb3RvLm1pbiA9IHByb3RvdHlwZU1pbjtcbiAgICBwcm90by5wYXJzaW5nRmxhZ3MgPSBwYXJzaW5nRmxhZ3M7XG4gICAgcHJvdG8uc2V0ID0gc3RyaW5nU2V0O1xuICAgIHByb3RvLnN0YXJ0T2YgPSBzdGFydE9mO1xuICAgIHByb3RvLnN1YnRyYWN0ID0gc3VidHJhY3Q7XG4gICAgcHJvdG8udG9BcnJheSA9IHRvQXJyYXk7XG4gICAgcHJvdG8udG9PYmplY3QgPSB0b09iamVjdDtcbiAgICBwcm90by50b0RhdGUgPSB0b0RhdGU7XG4gICAgcHJvdG8udG9JU09TdHJpbmcgPSB0b0lTT1N0cmluZztcbiAgICBwcm90by5pbnNwZWN0ID0gaW5zcGVjdDtcbiAgICBpZiAodHlwZW9mIFN5bWJvbCAhPT0gJ3VuZGVmaW5lZCcgJiYgU3ltYm9sLmZvciAhPSBudWxsKSB7XG4gICAgICAgIHByb3RvW1N5bWJvbC5mb3IoJ25vZGVqcy51dGlsLmluc3BlY3QuY3VzdG9tJyldID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICdNb21lbnQ8JyArIHRoaXMuZm9ybWF0KCkgKyAnPic7XG4gICAgICAgIH07XG4gICAgfVxuICAgIHByb3RvLnRvSlNPTiA9IHRvSlNPTjtcbiAgICBwcm90by50b1N0cmluZyA9IHRvU3RyaW5nO1xuICAgIHByb3RvLnVuaXggPSB1bml4O1xuICAgIHByb3RvLnZhbHVlT2YgPSB2YWx1ZU9mO1xuICAgIHByb3RvLmNyZWF0aW9uRGF0YSA9IGNyZWF0aW9uRGF0YTtcbiAgICBwcm90by5lcmFOYW1lID0gZ2V0RXJhTmFtZTtcbiAgICBwcm90by5lcmFOYXJyb3cgPSBnZXRFcmFOYXJyb3c7XG4gICAgcHJvdG8uZXJhQWJiciA9IGdldEVyYUFiYnI7XG4gICAgcHJvdG8uZXJhWWVhciA9IGdldEVyYVllYXI7XG4gICAgcHJvdG8ueWVhciA9IGdldFNldFllYXI7XG4gICAgcHJvdG8uaXNMZWFwWWVhciA9IGdldElzTGVhcFllYXI7XG4gICAgcHJvdG8ud2Vla1llYXIgPSBnZXRTZXRXZWVrWWVhcjtcbiAgICBwcm90by5pc29XZWVrWWVhciA9IGdldFNldElTT1dlZWtZZWFyO1xuICAgIHByb3RvLnF1YXJ0ZXIgPSBwcm90by5xdWFydGVycyA9IGdldFNldFF1YXJ0ZXI7XG4gICAgcHJvdG8ubW9udGggPSBnZXRTZXRNb250aDtcbiAgICBwcm90by5kYXlzSW5Nb250aCA9IGdldERheXNJbk1vbnRoO1xuICAgIHByb3RvLndlZWsgPSBwcm90by53ZWVrcyA9IGdldFNldFdlZWs7XG4gICAgcHJvdG8uaXNvV2VlayA9IHByb3RvLmlzb1dlZWtzID0gZ2V0U2V0SVNPV2VlaztcbiAgICBwcm90by53ZWVrc0luWWVhciA9IGdldFdlZWtzSW5ZZWFyO1xuICAgIHByb3RvLndlZWtzSW5XZWVrWWVhciA9IGdldFdlZWtzSW5XZWVrWWVhcjtcbiAgICBwcm90by5pc29XZWVrc0luWWVhciA9IGdldElTT1dlZWtzSW5ZZWFyO1xuICAgIHByb3RvLmlzb1dlZWtzSW5JU09XZWVrWWVhciA9IGdldElTT1dlZWtzSW5JU09XZWVrWWVhcjtcbiAgICBwcm90by5kYXRlID0gZ2V0U2V0RGF5T2ZNb250aDtcbiAgICBwcm90by5kYXkgPSBwcm90by5kYXlzID0gZ2V0U2V0RGF5T2ZXZWVrO1xuICAgIHByb3RvLndlZWtkYXkgPSBnZXRTZXRMb2NhbGVEYXlPZldlZWs7XG4gICAgcHJvdG8uaXNvV2Vla2RheSA9IGdldFNldElTT0RheU9mV2VlaztcbiAgICBwcm90by5kYXlPZlllYXIgPSBnZXRTZXREYXlPZlllYXI7XG4gICAgcHJvdG8uaG91ciA9IHByb3RvLmhvdXJzID0gZ2V0U2V0SG91cjtcbiAgICBwcm90by5taW51dGUgPSBwcm90by5taW51dGVzID0gZ2V0U2V0TWludXRlO1xuICAgIHByb3RvLnNlY29uZCA9IHByb3RvLnNlY29uZHMgPSBnZXRTZXRTZWNvbmQ7XG4gICAgcHJvdG8ubWlsbGlzZWNvbmQgPSBwcm90by5taWxsaXNlY29uZHMgPSBnZXRTZXRNaWxsaXNlY29uZDtcbiAgICBwcm90by51dGNPZmZzZXQgPSBnZXRTZXRPZmZzZXQ7XG4gICAgcHJvdG8udXRjID0gc2V0T2Zmc2V0VG9VVEM7XG4gICAgcHJvdG8ubG9jYWwgPSBzZXRPZmZzZXRUb0xvY2FsO1xuICAgIHByb3RvLnBhcnNlWm9uZSA9IHNldE9mZnNldFRvUGFyc2VkT2Zmc2V0O1xuICAgIHByb3RvLmhhc0FsaWduZWRIb3VyT2Zmc2V0ID0gaGFzQWxpZ25lZEhvdXJPZmZzZXQ7XG4gICAgcHJvdG8uaXNEU1QgPSBpc0RheWxpZ2h0U2F2aW5nVGltZTtcbiAgICBwcm90by5pc0xvY2FsID0gaXNMb2NhbDtcbiAgICBwcm90by5pc1V0Y09mZnNldCA9IGlzVXRjT2Zmc2V0O1xuICAgIHByb3RvLmlzVXRjID0gaXNVdGM7XG4gICAgcHJvdG8uaXNVVEMgPSBpc1V0YztcbiAgICBwcm90by56b25lQWJiciA9IGdldFpvbmVBYmJyO1xuICAgIHByb3RvLnpvbmVOYW1lID0gZ2V0Wm9uZU5hbWU7XG4gICAgcHJvdG8uZGF0ZXMgPSBkZXByZWNhdGUoXG4gICAgICAgICdkYXRlcyBhY2Nlc3NvciBpcyBkZXByZWNhdGVkLiBVc2UgZGF0ZSBpbnN0ZWFkLicsXG4gICAgICAgIGdldFNldERheU9mTW9udGhcbiAgICApO1xuICAgIHByb3RvLm1vbnRocyA9IGRlcHJlY2F0ZShcbiAgICAgICAgJ21vbnRocyBhY2Nlc3NvciBpcyBkZXByZWNhdGVkLiBVc2UgbW9udGggaW5zdGVhZCcsXG4gICAgICAgIGdldFNldE1vbnRoXG4gICAgKTtcbiAgICBwcm90by55ZWFycyA9IGRlcHJlY2F0ZShcbiAgICAgICAgJ3llYXJzIGFjY2Vzc29yIGlzIGRlcHJlY2F0ZWQuIFVzZSB5ZWFyIGluc3RlYWQnLFxuICAgICAgICBnZXRTZXRZZWFyXG4gICAgKTtcbiAgICBwcm90by56b25lID0gZGVwcmVjYXRlKFxuICAgICAgICAnbW9tZW50KCkuem9uZSBpcyBkZXByZWNhdGVkLCB1c2UgbW9tZW50KCkudXRjT2Zmc2V0IGluc3RlYWQuIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3Mvem9uZS8nLFxuICAgICAgICBnZXRTZXRab25lXG4gICAgKTtcbiAgICBwcm90by5pc0RTVFNoaWZ0ZWQgPSBkZXByZWNhdGUoXG4gICAgICAgICdpc0RTVFNoaWZ0ZWQgaXMgZGVwcmVjYXRlZC4gU2VlIGh0dHA6Ly9tb21lbnRqcy5jb20vZ3VpZGVzLyMvd2FybmluZ3MvZHN0LXNoaWZ0ZWQvIGZvciBtb3JlIGluZm9ybWF0aW9uJyxcbiAgICAgICAgaXNEYXlsaWdodFNhdmluZ1RpbWVTaGlmdGVkXG4gICAgKTtcblxuICAgIGZ1bmN0aW9uIGNyZWF0ZVVuaXgoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUxvY2FsKGlucHV0ICogMTAwMCk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY3JlYXRlSW5ab25lKCkge1xuICAgICAgICByZXR1cm4gY3JlYXRlTG9jYWwuYXBwbHkobnVsbCwgYXJndW1lbnRzKS5wYXJzZVpvbmUoKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwcmVQYXJzZVBvc3RGb3JtYXQoc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBzdHJpbmc7XG4gICAgfVxuXG4gICAgdmFyIHByb3RvJDEgPSBMb2NhbGUucHJvdG90eXBlO1xuXG4gICAgcHJvdG8kMS5jYWxlbmRhciA9IGNhbGVuZGFyO1xuICAgIHByb3RvJDEubG9uZ0RhdGVGb3JtYXQgPSBsb25nRGF0ZUZvcm1hdDtcbiAgICBwcm90byQxLmludmFsaWREYXRlID0gaW52YWxpZERhdGU7XG4gICAgcHJvdG8kMS5vcmRpbmFsID0gb3JkaW5hbDtcbiAgICBwcm90byQxLnByZXBhcnNlID0gcHJlUGFyc2VQb3N0Rm9ybWF0O1xuICAgIHByb3RvJDEucG9zdGZvcm1hdCA9IHByZVBhcnNlUG9zdEZvcm1hdDtcbiAgICBwcm90byQxLnJlbGF0aXZlVGltZSA9IHJlbGF0aXZlVGltZTtcbiAgICBwcm90byQxLnBhc3RGdXR1cmUgPSBwYXN0RnV0dXJlO1xuICAgIHByb3RvJDEuc2V0ID0gc2V0O1xuICAgIHByb3RvJDEuZXJhcyA9IGxvY2FsZUVyYXM7XG4gICAgcHJvdG8kMS5lcmFzUGFyc2UgPSBsb2NhbGVFcmFzUGFyc2U7XG4gICAgcHJvdG8kMS5lcmFzQ29udmVydFllYXIgPSBsb2NhbGVFcmFzQ29udmVydFllYXI7XG4gICAgcHJvdG8kMS5lcmFzQWJiclJlZ2V4ID0gZXJhc0FiYnJSZWdleDtcbiAgICBwcm90byQxLmVyYXNOYW1lUmVnZXggPSBlcmFzTmFtZVJlZ2V4O1xuICAgIHByb3RvJDEuZXJhc05hcnJvd1JlZ2V4ID0gZXJhc05hcnJvd1JlZ2V4O1xuXG4gICAgcHJvdG8kMS5tb250aHMgPSBsb2NhbGVNb250aHM7XG4gICAgcHJvdG8kMS5tb250aHNTaG9ydCA9IGxvY2FsZU1vbnRoc1Nob3J0O1xuICAgIHByb3RvJDEubW9udGhzUGFyc2UgPSBsb2NhbGVNb250aHNQYXJzZTtcbiAgICBwcm90byQxLm1vbnRoc1JlZ2V4ID0gbW9udGhzUmVnZXg7XG4gICAgcHJvdG8kMS5tb250aHNTaG9ydFJlZ2V4ID0gbW9udGhzU2hvcnRSZWdleDtcbiAgICBwcm90byQxLndlZWsgPSBsb2NhbGVXZWVrO1xuICAgIHByb3RvJDEuZmlyc3REYXlPZlllYXIgPSBsb2NhbGVGaXJzdERheU9mWWVhcjtcbiAgICBwcm90byQxLmZpcnN0RGF5T2ZXZWVrID0gbG9jYWxlRmlyc3REYXlPZldlZWs7XG5cbiAgICBwcm90byQxLndlZWtkYXlzID0gbG9jYWxlV2Vla2RheXM7XG4gICAgcHJvdG8kMS53ZWVrZGF5c01pbiA9IGxvY2FsZVdlZWtkYXlzTWluO1xuICAgIHByb3RvJDEud2Vla2RheXNTaG9ydCA9IGxvY2FsZVdlZWtkYXlzU2hvcnQ7XG4gICAgcHJvdG8kMS53ZWVrZGF5c1BhcnNlID0gbG9jYWxlV2Vla2RheXNQYXJzZTtcblxuICAgIHByb3RvJDEud2Vla2RheXNSZWdleCA9IHdlZWtkYXlzUmVnZXg7XG4gICAgcHJvdG8kMS53ZWVrZGF5c1Nob3J0UmVnZXggPSB3ZWVrZGF5c1Nob3J0UmVnZXg7XG4gICAgcHJvdG8kMS53ZWVrZGF5c01pblJlZ2V4ID0gd2Vla2RheXNNaW5SZWdleDtcblxuICAgIHByb3RvJDEuaXNQTSA9IGxvY2FsZUlzUE07XG4gICAgcHJvdG8kMS5tZXJpZGllbSA9IGxvY2FsZU1lcmlkaWVtO1xuXG4gICAgZnVuY3Rpb24gZ2V0JDEoZm9ybWF0LCBpbmRleCwgZmllbGQsIHNldHRlcikge1xuICAgICAgICB2YXIgbG9jYWxlID0gZ2V0TG9jYWxlKCksXG4gICAgICAgICAgICB1dGMgPSBjcmVhdGVVVEMoKS5zZXQoc2V0dGVyLCBpbmRleCk7XG4gICAgICAgIHJldHVybiBsb2NhbGVbZmllbGRdKHV0YywgZm9ybWF0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaXN0TW9udGhzSW1wbChmb3JtYXQsIGluZGV4LCBmaWVsZCkge1xuICAgICAgICBpZiAoaXNOdW1iZXIoZm9ybWF0KSkge1xuICAgICAgICAgICAgaW5kZXggPSBmb3JtYXQ7XG4gICAgICAgICAgICBmb3JtYXQgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICBmb3JtYXQgPSBmb3JtYXQgfHwgJyc7XG5cbiAgICAgICAgaWYgKGluZGV4ICE9IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBnZXQkMShmb3JtYXQsIGluZGV4LCBmaWVsZCwgJ21vbnRoJyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgIG91dCA9IFtdO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKykge1xuICAgICAgICAgICAgb3V0W2ldID0gZ2V0JDEoZm9ybWF0LCBpLCBmaWVsZCwgJ21vbnRoJyk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG5cbiAgICAvLyAoKVxuICAgIC8vICg1KVxuICAgIC8vIChmbXQsIDUpXG4gICAgLy8gKGZtdClcbiAgICAvLyAodHJ1ZSlcbiAgICAvLyAodHJ1ZSwgNSlcbiAgICAvLyAodHJ1ZSwgZm10LCA1KVxuICAgIC8vICh0cnVlLCBmbXQpXG4gICAgZnVuY3Rpb24gbGlzdFdlZWtkYXlzSW1wbChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgsIGZpZWxkKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbG9jYWxlU29ydGVkID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgIGlmIChpc051bWJlcihmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgaW5kZXggPSBmb3JtYXQ7XG4gICAgICAgICAgICAgICAgZm9ybWF0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBmb3JtYXQgPSBmb3JtYXQgfHwgJyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3JtYXQgPSBsb2NhbGVTb3J0ZWQ7XG4gICAgICAgICAgICBpbmRleCA9IGZvcm1hdDtcbiAgICAgICAgICAgIGxvY2FsZVNvcnRlZCA9IGZhbHNlO1xuXG4gICAgICAgICAgICBpZiAoaXNOdW1iZXIoZm9ybWF0KSkge1xuICAgICAgICAgICAgICAgIGluZGV4ID0gZm9ybWF0O1xuICAgICAgICAgICAgICAgIGZvcm1hdCA9IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9ybWF0ID0gZm9ybWF0IHx8ICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGxvY2FsZSA9IGdldExvY2FsZSgpLFxuICAgICAgICAgICAgc2hpZnQgPSBsb2NhbGVTb3J0ZWQgPyBsb2NhbGUuX3dlZWsuZG93IDogMCxcbiAgICAgICAgICAgIGksXG4gICAgICAgICAgICBvdXQgPSBbXTtcblxuICAgICAgICBpZiAoaW5kZXggIT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIGdldCQxKGZvcm1hdCwgKGluZGV4ICsgc2hpZnQpICUgNywgZmllbGQsICdkYXknKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCA3OyBpKyspIHtcbiAgICAgICAgICAgIG91dFtpXSA9IGdldCQxKGZvcm1hdCwgKGkgKyBzaGlmdCkgJSA3LCBmaWVsZCwgJ2RheScpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdE1vbnRocyhmb3JtYXQsIGluZGV4KSB7XG4gICAgICAgIHJldHVybiBsaXN0TW9udGhzSW1wbChmb3JtYXQsIGluZGV4LCAnbW9udGhzJyk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbGlzdE1vbnRoc1Nob3J0KGZvcm1hdCwgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIGxpc3RNb250aHNJbXBsKGZvcm1hdCwgaW5kZXgsICdtb250aHNTaG9ydCcpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpc3RXZWVrZGF5cyhsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIGxpc3RXZWVrZGF5c0ltcGwobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4LCAnd2Vla2RheXMnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBsaXN0V2Vla2RheXNTaG9ydChsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIGxpc3RXZWVrZGF5c0ltcGwobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4LCAnd2Vla2RheXNTaG9ydCcpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxpc3RXZWVrZGF5c01pbihsb2NhbGVTb3J0ZWQsIGZvcm1hdCwgaW5kZXgpIHtcbiAgICAgICAgcmV0dXJuIGxpc3RXZWVrZGF5c0ltcGwobG9jYWxlU29ydGVkLCBmb3JtYXQsIGluZGV4LCAnd2Vla2RheXNNaW4nKTtcbiAgICB9XG5cbiAgICBnZXRTZXRHbG9iYWxMb2NhbGUoJ2VuJywge1xuICAgICAgICBlcmFzOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgc2luY2U6ICcwMDAxLTAxLTAxJyxcbiAgICAgICAgICAgICAgICB1bnRpbDogK0luZmluaXR5LFxuICAgICAgICAgICAgICAgIG9mZnNldDogMSxcbiAgICAgICAgICAgICAgICBuYW1lOiAnQW5ubyBEb21pbmknLFxuICAgICAgICAgICAgICAgIG5hcnJvdzogJ0FEJyxcbiAgICAgICAgICAgICAgICBhYmJyOiAnQUQnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBzaW5jZTogJzAwMDAtMTItMzEnLFxuICAgICAgICAgICAgICAgIHVudGlsOiAtSW5maW5pdHksXG4gICAgICAgICAgICAgICAgb2Zmc2V0OiAxLFxuICAgICAgICAgICAgICAgIG5hbWU6ICdCZWZvcmUgQ2hyaXN0JyxcbiAgICAgICAgICAgICAgICBuYXJyb3c6ICdCQycsXG4gICAgICAgICAgICAgICAgYWJicjogJ0JDJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIGRheU9mTW9udGhPcmRpbmFsUGFyc2U6IC9cXGR7MSwyfSh0aHxzdHxuZHxyZCkvLFxuICAgICAgICBvcmRpbmFsOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICB2YXIgYiA9IG51bWJlciAlIDEwLFxuICAgICAgICAgICAgICAgIG91dHB1dCA9XG4gICAgICAgICAgICAgICAgICAgIHRvSW50KChudW1iZXIgJSAxMDApIC8gMTApID09PSAxXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICd0aCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogYiA9PT0gMVxuICAgICAgICAgICAgICAgICAgICAgICAgPyAnc3QnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGIgPT09IDJcbiAgICAgICAgICAgICAgICAgICAgICAgID8gJ25kJ1xuICAgICAgICAgICAgICAgICAgICAgICAgOiBiID09PSAzXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICdyZCdcbiAgICAgICAgICAgICAgICAgICAgICAgIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBTaWRlIGVmZmVjdCBpbXBvcnRzXG5cbiAgICBob29rcy5sYW5nID0gZGVwcmVjYXRlKFxuICAgICAgICAnbW9tZW50LmxhbmcgaXMgZGVwcmVjYXRlZC4gVXNlIG1vbWVudC5sb2NhbGUgaW5zdGVhZC4nLFxuICAgICAgICBnZXRTZXRHbG9iYWxMb2NhbGVcbiAgICApO1xuICAgIGhvb2tzLmxhbmdEYXRhID0gZGVwcmVjYXRlKFxuICAgICAgICAnbW9tZW50LmxhbmdEYXRhIGlzIGRlcHJlY2F0ZWQuIFVzZSBtb21lbnQubG9jYWxlRGF0YSBpbnN0ZWFkLicsXG4gICAgICAgIGdldExvY2FsZVxuICAgICk7XG5cbiAgICB2YXIgbWF0aEFicyA9IE1hdGguYWJzO1xuXG4gICAgZnVuY3Rpb24gYWJzKCkge1xuICAgICAgICB2YXIgZGF0YSA9IHRoaXMuX2RhdGE7XG5cbiAgICAgICAgdGhpcy5fbWlsbGlzZWNvbmRzID0gbWF0aEFicyh0aGlzLl9taWxsaXNlY29uZHMpO1xuICAgICAgICB0aGlzLl9kYXlzID0gbWF0aEFicyh0aGlzLl9kYXlzKTtcbiAgICAgICAgdGhpcy5fbW9udGhzID0gbWF0aEFicyh0aGlzLl9tb250aHMpO1xuXG4gICAgICAgIGRhdGEubWlsbGlzZWNvbmRzID0gbWF0aEFicyhkYXRhLm1pbGxpc2Vjb25kcyk7XG4gICAgICAgIGRhdGEuc2Vjb25kcyA9IG1hdGhBYnMoZGF0YS5zZWNvbmRzKTtcbiAgICAgICAgZGF0YS5taW51dGVzID0gbWF0aEFicyhkYXRhLm1pbnV0ZXMpO1xuICAgICAgICBkYXRhLmhvdXJzID0gbWF0aEFicyhkYXRhLmhvdXJzKTtcbiAgICAgICAgZGF0YS5tb250aHMgPSBtYXRoQWJzKGRhdGEubW9udGhzKTtcbiAgICAgICAgZGF0YS55ZWFycyA9IG1hdGhBYnMoZGF0YS55ZWFycyk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYWRkU3VidHJhY3QkMShkdXJhdGlvbiwgaW5wdXQsIHZhbHVlLCBkaXJlY3Rpb24pIHtcbiAgICAgICAgdmFyIG90aGVyID0gY3JlYXRlRHVyYXRpb24oaW5wdXQsIHZhbHVlKTtcblxuICAgICAgICBkdXJhdGlvbi5fbWlsbGlzZWNvbmRzICs9IGRpcmVjdGlvbiAqIG90aGVyLl9taWxsaXNlY29uZHM7XG4gICAgICAgIGR1cmF0aW9uLl9kYXlzICs9IGRpcmVjdGlvbiAqIG90aGVyLl9kYXlzO1xuICAgICAgICBkdXJhdGlvbi5fbW9udGhzICs9IGRpcmVjdGlvbiAqIG90aGVyLl9tb250aHM7XG5cbiAgICAgICAgcmV0dXJuIGR1cmF0aW9uLl9idWJibGUoKTtcbiAgICB9XG5cbiAgICAvLyBzdXBwb3J0cyBvbmx5IDIuMC1zdHlsZSBhZGQoMSwgJ3MnKSBvciBhZGQoZHVyYXRpb24pXG4gICAgZnVuY3Rpb24gYWRkJDEoaW5wdXQsIHZhbHVlKSB7XG4gICAgICAgIHJldHVybiBhZGRTdWJ0cmFjdCQxKHRoaXMsIGlucHV0LCB2YWx1ZSwgMSk7XG4gICAgfVxuXG4gICAgLy8gc3VwcG9ydHMgb25seSAyLjAtc3R5bGUgc3VidHJhY3QoMSwgJ3MnKSBvciBzdWJ0cmFjdChkdXJhdGlvbilcbiAgICBmdW5jdGlvbiBzdWJ0cmFjdCQxKGlucHV0LCB2YWx1ZSkge1xuICAgICAgICByZXR1cm4gYWRkU3VidHJhY3QkMSh0aGlzLCBpbnB1dCwgdmFsdWUsIC0xKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhYnNDZWlsKG51bWJlcikge1xuICAgICAgICBpZiAobnVtYmVyIDwgMCkge1xuICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IobnVtYmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmNlaWwobnVtYmVyKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGJ1YmJsZSgpIHtcbiAgICAgICAgdmFyIG1pbGxpc2Vjb25kcyA9IHRoaXMuX21pbGxpc2Vjb25kcyxcbiAgICAgICAgICAgIGRheXMgPSB0aGlzLl9kYXlzLFxuICAgICAgICAgICAgbW9udGhzID0gdGhpcy5fbW9udGhzLFxuICAgICAgICAgICAgZGF0YSA9IHRoaXMuX2RhdGEsXG4gICAgICAgICAgICBzZWNvbmRzLFxuICAgICAgICAgICAgbWludXRlcyxcbiAgICAgICAgICAgIGhvdXJzLFxuICAgICAgICAgICAgeWVhcnMsXG4gICAgICAgICAgICBtb250aHNGcm9tRGF5cztcblxuICAgICAgICAvLyBpZiB3ZSBoYXZlIGEgbWl4IG9mIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSB2YWx1ZXMsIGJ1YmJsZSBkb3duIGZpcnN0XG4gICAgICAgIC8vIGNoZWNrOiBodHRwczovL2dpdGh1Yi5jb20vbW9tZW50L21vbWVudC9pc3N1ZXMvMjE2NlxuICAgICAgICBpZiAoXG4gICAgICAgICAgICAhKFxuICAgICAgICAgICAgICAgIChtaWxsaXNlY29uZHMgPj0gMCAmJiBkYXlzID49IDAgJiYgbW9udGhzID49IDApIHx8XG4gICAgICAgICAgICAgICAgKG1pbGxpc2Vjb25kcyA8PSAwICYmIGRheXMgPD0gMCAmJiBtb250aHMgPD0gMClcbiAgICAgICAgICAgIClcbiAgICAgICAgKSB7XG4gICAgICAgICAgICBtaWxsaXNlY29uZHMgKz0gYWJzQ2VpbChtb250aHNUb0RheXMobW9udGhzKSArIGRheXMpICogODY0ZTU7XG4gICAgICAgICAgICBkYXlzID0gMDtcbiAgICAgICAgICAgIG1vbnRocyA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgZm9sbG93aW5nIGNvZGUgYnViYmxlcyB1cCB2YWx1ZXMsIHNlZSB0aGUgdGVzdHMgZm9yXG4gICAgICAgIC8vIGV4YW1wbGVzIG9mIHdoYXQgdGhhdCBtZWFucy5cbiAgICAgICAgZGF0YS5taWxsaXNlY29uZHMgPSBtaWxsaXNlY29uZHMgJSAxMDAwO1xuXG4gICAgICAgIHNlY29uZHMgPSBhYnNGbG9vcihtaWxsaXNlY29uZHMgLyAxMDAwKTtcbiAgICAgICAgZGF0YS5zZWNvbmRzID0gc2Vjb25kcyAlIDYwO1xuXG4gICAgICAgIG1pbnV0ZXMgPSBhYnNGbG9vcihzZWNvbmRzIC8gNjApO1xuICAgICAgICBkYXRhLm1pbnV0ZXMgPSBtaW51dGVzICUgNjA7XG5cbiAgICAgICAgaG91cnMgPSBhYnNGbG9vcihtaW51dGVzIC8gNjApO1xuICAgICAgICBkYXRhLmhvdXJzID0gaG91cnMgJSAyNDtcblxuICAgICAgICBkYXlzICs9IGFic0Zsb29yKGhvdXJzIC8gMjQpO1xuXG4gICAgICAgIC8vIGNvbnZlcnQgZGF5cyB0byBtb250aHNcbiAgICAgICAgbW9udGhzRnJvbURheXMgPSBhYnNGbG9vcihkYXlzVG9Nb250aHMoZGF5cykpO1xuICAgICAgICBtb250aHMgKz0gbW9udGhzRnJvbURheXM7XG4gICAgICAgIGRheXMgLT0gYWJzQ2VpbChtb250aHNUb0RheXMobW9udGhzRnJvbURheXMpKTtcblxuICAgICAgICAvLyAxMiBtb250aHMgLT4gMSB5ZWFyXG4gICAgICAgIHllYXJzID0gYWJzRmxvb3IobW9udGhzIC8gMTIpO1xuICAgICAgICBtb250aHMgJT0gMTI7XG5cbiAgICAgICAgZGF0YS5kYXlzID0gZGF5cztcbiAgICAgICAgZGF0YS5tb250aHMgPSBtb250aHM7XG4gICAgICAgIGRhdGEueWVhcnMgPSB5ZWFycztcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkYXlzVG9Nb250aHMoZGF5cykge1xuICAgICAgICAvLyA0MDAgeWVhcnMgaGF2ZSAxNDYwOTcgZGF5cyAodGFraW5nIGludG8gYWNjb3VudCBsZWFwIHllYXIgcnVsZXMpXG4gICAgICAgIC8vIDQwMCB5ZWFycyBoYXZlIDEyIG1vbnRocyA9PT0gNDgwMFxuICAgICAgICByZXR1cm4gKGRheXMgKiA0ODAwKSAvIDE0NjA5NztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtb250aHNUb0RheXMobW9udGhzKSB7XG4gICAgICAgIC8vIHRoZSByZXZlcnNlIG9mIGRheXNUb01vbnRoc1xuICAgICAgICByZXR1cm4gKG1vbnRocyAqIDE0NjA5NykgLyA0ODAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGFzKHVuaXRzKSB7XG4gICAgICAgIGlmICghdGhpcy5pc1ZhbGlkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGRheXMsXG4gICAgICAgICAgICBtb250aHMsXG4gICAgICAgICAgICBtaWxsaXNlY29uZHMgPSB0aGlzLl9taWxsaXNlY29uZHM7XG5cbiAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG5cbiAgICAgICAgaWYgKHVuaXRzID09PSAnbW9udGgnIHx8IHVuaXRzID09PSAncXVhcnRlcicgfHwgdW5pdHMgPT09ICd5ZWFyJykge1xuICAgICAgICAgICAgZGF5cyA9IHRoaXMuX2RheXMgKyBtaWxsaXNlY29uZHMgLyA4NjRlNTtcbiAgICAgICAgICAgIG1vbnRocyA9IHRoaXMuX21vbnRocyArIGRheXNUb01vbnRocyhkYXlzKTtcbiAgICAgICAgICAgIHN3aXRjaCAodW5pdHMpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdtb250aCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtb250aHM7XG4gICAgICAgICAgICAgICAgY2FzZSAncXVhcnRlcic6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBtb250aHMgLyAzO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3llYXInOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbW9udGhzIC8gMTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBoYW5kbGUgbWlsbGlzZWNvbmRzIHNlcGFyYXRlbHkgYmVjYXVzZSBvZiBmbG9hdGluZyBwb2ludCBtYXRoIGVycm9ycyAoaXNzdWUgIzE4NjcpXG4gICAgICAgICAgICBkYXlzID0gdGhpcy5fZGF5cyArIE1hdGgucm91bmQobW9udGhzVG9EYXlzKHRoaXMuX21vbnRocykpO1xuICAgICAgICAgICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICAgICAgICAgIGNhc2UgJ3dlZWsnOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZGF5cyAvIDcgKyBtaWxsaXNlY29uZHMgLyA2MDQ4ZTU7XG4gICAgICAgICAgICAgICAgY2FzZSAnZGF5JzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRheXMgKyBtaWxsaXNlY29uZHMgLyA4NjRlNTtcbiAgICAgICAgICAgICAgICBjYXNlICdob3VyJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRheXMgKiAyNCArIG1pbGxpc2Vjb25kcyAvIDM2ZTU7XG4gICAgICAgICAgICAgICAgY2FzZSAnbWludXRlJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRheXMgKiAxNDQwICsgbWlsbGlzZWNvbmRzIC8gNmU0O1xuICAgICAgICAgICAgICAgIGNhc2UgJ3NlY29uZCc6XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXlzICogODY0MDAgKyBtaWxsaXNlY29uZHMgLyAxMDAwO1xuICAgICAgICAgICAgICAgIC8vIE1hdGguZmxvb3IgcHJldmVudHMgZmxvYXRpbmcgcG9pbnQgbWF0aCBlcnJvcnMgaGVyZVxuICAgICAgICAgICAgICAgIGNhc2UgJ21pbGxpc2Vjb25kJzpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1hdGguZmxvb3IoZGF5cyAqIDg2NGU1KSArIG1pbGxpc2Vjb25kcztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gdW5pdCAnICsgdW5pdHMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gVE9ETzogVXNlIHRoaXMuYXMoJ21zJyk/XG4gICAgZnVuY3Rpb24gdmFsdWVPZiQxKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gTmFOO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0aGlzLl9taWxsaXNlY29uZHMgK1xuICAgICAgICAgICAgdGhpcy5fZGF5cyAqIDg2NGU1ICtcbiAgICAgICAgICAgICh0aGlzLl9tb250aHMgJSAxMikgKiAyNTkyZTYgK1xuICAgICAgICAgICAgdG9JbnQodGhpcy5fbW9udGhzIC8gMTIpICogMzE1MzZlNlxuICAgICAgICApO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VBcyhhbGlhcykge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuYXMoYWxpYXMpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHZhciBhc01pbGxpc2Vjb25kcyA9IG1ha2VBcygnbXMnKSxcbiAgICAgICAgYXNTZWNvbmRzID0gbWFrZUFzKCdzJyksXG4gICAgICAgIGFzTWludXRlcyA9IG1ha2VBcygnbScpLFxuICAgICAgICBhc0hvdXJzID0gbWFrZUFzKCdoJyksXG4gICAgICAgIGFzRGF5cyA9IG1ha2VBcygnZCcpLFxuICAgICAgICBhc1dlZWtzID0gbWFrZUFzKCd3JyksXG4gICAgICAgIGFzTW9udGhzID0gbWFrZUFzKCdNJyksXG4gICAgICAgIGFzUXVhcnRlcnMgPSBtYWtlQXMoJ1EnKSxcbiAgICAgICAgYXNZZWFycyA9IG1ha2VBcygneScpO1xuXG4gICAgZnVuY3Rpb24gY2xvbmUkMSgpIHtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUR1cmF0aW9uKHRoaXMpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldCQyKHVuaXRzKSB7XG4gICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgPyB0aGlzW3VuaXRzICsgJ3MnXSgpIDogTmFOO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VHZXR0ZXIobmFtZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNWYWxpZCgpID8gdGhpcy5fZGF0YVtuYW1lXSA6IE5hTjtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICB2YXIgbWlsbGlzZWNvbmRzID0gbWFrZUdldHRlcignbWlsbGlzZWNvbmRzJyksXG4gICAgICAgIHNlY29uZHMgPSBtYWtlR2V0dGVyKCdzZWNvbmRzJyksXG4gICAgICAgIG1pbnV0ZXMgPSBtYWtlR2V0dGVyKCdtaW51dGVzJyksXG4gICAgICAgIGhvdXJzID0gbWFrZUdldHRlcignaG91cnMnKSxcbiAgICAgICAgZGF5cyA9IG1ha2VHZXR0ZXIoJ2RheXMnKSxcbiAgICAgICAgbW9udGhzID0gbWFrZUdldHRlcignbW9udGhzJyksXG4gICAgICAgIHllYXJzID0gbWFrZUdldHRlcigneWVhcnMnKTtcblxuICAgIGZ1bmN0aW9uIHdlZWtzKCkge1xuICAgICAgICByZXR1cm4gYWJzRmxvb3IodGhpcy5kYXlzKCkgLyA3KTtcbiAgICB9XG5cbiAgICB2YXIgcm91bmQgPSBNYXRoLnJvdW5kLFxuICAgICAgICB0aHJlc2hvbGRzID0ge1xuICAgICAgICAgICAgc3M6IDQ0LCAvLyBhIGZldyBzZWNvbmRzIHRvIHNlY29uZHNcbiAgICAgICAgICAgIHM6IDQ1LCAvLyBzZWNvbmRzIHRvIG1pbnV0ZVxuICAgICAgICAgICAgbTogNDUsIC8vIG1pbnV0ZXMgdG8gaG91clxuICAgICAgICAgICAgaDogMjIsIC8vIGhvdXJzIHRvIGRheVxuICAgICAgICAgICAgZDogMjYsIC8vIGRheXMgdG8gbW9udGgvd2Vla1xuICAgICAgICAgICAgdzogbnVsbCwgLy8gd2Vla3MgdG8gbW9udGhcbiAgICAgICAgICAgIE06IDExLCAvLyBtb250aHMgdG8geWVhclxuICAgICAgICB9O1xuXG4gICAgLy8gaGVscGVyIGZ1bmN0aW9uIGZvciBtb21lbnQuZm4uZnJvbSwgbW9tZW50LmZuLmZyb21Ob3csIGFuZCBtb21lbnQuZHVyYXRpb24uZm4uaHVtYW5pemVcbiAgICBmdW5jdGlvbiBzdWJzdGl0dXRlVGltZUFnbyhzdHJpbmcsIG51bWJlciwgd2l0aG91dFN1ZmZpeCwgaXNGdXR1cmUsIGxvY2FsZSkge1xuICAgICAgICByZXR1cm4gbG9jYWxlLnJlbGF0aXZlVGltZShudW1iZXIgfHwgMSwgISF3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZWxhdGl2ZVRpbWUkMShwb3NOZWdEdXJhdGlvbiwgd2l0aG91dFN1ZmZpeCwgdGhyZXNob2xkcywgbG9jYWxlKSB7XG4gICAgICAgIHZhciBkdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uKHBvc05lZ0R1cmF0aW9uKS5hYnMoKSxcbiAgICAgICAgICAgIHNlY29uZHMgPSByb3VuZChkdXJhdGlvbi5hcygncycpKSxcbiAgICAgICAgICAgIG1pbnV0ZXMgPSByb3VuZChkdXJhdGlvbi5hcygnbScpKSxcbiAgICAgICAgICAgIGhvdXJzID0gcm91bmQoZHVyYXRpb24uYXMoJ2gnKSksXG4gICAgICAgICAgICBkYXlzID0gcm91bmQoZHVyYXRpb24uYXMoJ2QnKSksXG4gICAgICAgICAgICBtb250aHMgPSByb3VuZChkdXJhdGlvbi5hcygnTScpKSxcbiAgICAgICAgICAgIHdlZWtzID0gcm91bmQoZHVyYXRpb24uYXMoJ3cnKSksXG4gICAgICAgICAgICB5ZWFycyA9IHJvdW5kKGR1cmF0aW9uLmFzKCd5JykpLFxuICAgICAgICAgICAgYSA9XG4gICAgICAgICAgICAgICAgKHNlY29uZHMgPD0gdGhyZXNob2xkcy5zcyAmJiBbJ3MnLCBzZWNvbmRzXSkgfHxcbiAgICAgICAgICAgICAgICAoc2Vjb25kcyA8IHRocmVzaG9sZHMucyAmJiBbJ3NzJywgc2Vjb25kc10pIHx8XG4gICAgICAgICAgICAgICAgKG1pbnV0ZXMgPD0gMSAmJiBbJ20nXSkgfHxcbiAgICAgICAgICAgICAgICAobWludXRlcyA8IHRocmVzaG9sZHMubSAmJiBbJ21tJywgbWludXRlc10pIHx8XG4gICAgICAgICAgICAgICAgKGhvdXJzIDw9IDEgJiYgWydoJ10pIHx8XG4gICAgICAgICAgICAgICAgKGhvdXJzIDwgdGhyZXNob2xkcy5oICYmIFsnaGgnLCBob3Vyc10pIHx8XG4gICAgICAgICAgICAgICAgKGRheXMgPD0gMSAmJiBbJ2QnXSkgfHxcbiAgICAgICAgICAgICAgICAoZGF5cyA8IHRocmVzaG9sZHMuZCAmJiBbJ2RkJywgZGF5c10pO1xuXG4gICAgICAgIGlmICh0aHJlc2hvbGRzLncgIT0gbnVsbCkge1xuICAgICAgICAgICAgYSA9XG4gICAgICAgICAgICAgICAgYSB8fFxuICAgICAgICAgICAgICAgICh3ZWVrcyA8PSAxICYmIFsndyddKSB8fFxuICAgICAgICAgICAgICAgICh3ZWVrcyA8IHRocmVzaG9sZHMudyAmJiBbJ3d3Jywgd2Vla3NdKTtcbiAgICAgICAgfVxuICAgICAgICBhID0gYSB8fFxuICAgICAgICAgICAgKG1vbnRocyA8PSAxICYmIFsnTSddKSB8fFxuICAgICAgICAgICAgKG1vbnRocyA8IHRocmVzaG9sZHMuTSAmJiBbJ01NJywgbW9udGhzXSkgfHxcbiAgICAgICAgICAgICh5ZWFycyA8PSAxICYmIFsneSddKSB8fCBbJ3l5JywgeWVhcnNdO1xuXG4gICAgICAgIGFbMl0gPSB3aXRob3V0U3VmZml4O1xuICAgICAgICBhWzNdID0gK3Bvc05lZ0R1cmF0aW9uID4gMDtcbiAgICAgICAgYVs0XSA9IGxvY2FsZTtcbiAgICAgICAgcmV0dXJuIHN1YnN0aXR1dGVUaW1lQWdvLmFwcGx5KG51bGwsIGEpO1xuICAgIH1cblxuICAgIC8vIFRoaXMgZnVuY3Rpb24gYWxsb3dzIHlvdSB0byBzZXQgdGhlIHJvdW5kaW5nIGZ1bmN0aW9uIGZvciByZWxhdGl2ZSB0aW1lIHN0cmluZ3NcbiAgICBmdW5jdGlvbiBnZXRTZXRSZWxhdGl2ZVRpbWVSb3VuZGluZyhyb3VuZGluZ0Z1bmN0aW9uKSB7XG4gICAgICAgIGlmIChyb3VuZGluZ0Z1bmN0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiByb3VuZDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHJvdW5kaW5nRnVuY3Rpb24gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIHJvdW5kID0gcm91bmRpbmdGdW5jdGlvbjtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIGFsbG93cyB5b3UgdG8gc2V0IGEgdGhyZXNob2xkIGZvciByZWxhdGl2ZSB0aW1lIHN0cmluZ3NcbiAgICBmdW5jdGlvbiBnZXRTZXRSZWxhdGl2ZVRpbWVUaHJlc2hvbGQodGhyZXNob2xkLCBsaW1pdCkge1xuICAgICAgICBpZiAodGhyZXNob2xkc1t0aHJlc2hvbGRdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobGltaXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIHRocmVzaG9sZHNbdGhyZXNob2xkXTtcbiAgICAgICAgfVxuICAgICAgICB0aHJlc2hvbGRzW3RocmVzaG9sZF0gPSBsaW1pdDtcbiAgICAgICAgaWYgKHRocmVzaG9sZCA9PT0gJ3MnKSB7XG4gICAgICAgICAgICB0aHJlc2hvbGRzLnNzID0gbGltaXQgLSAxO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGh1bWFuaXplKGFyZ1dpdGhTdWZmaXgsIGFyZ1RocmVzaG9sZHMpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubG9jYWxlRGF0YSgpLmludmFsaWREYXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgd2l0aFN1ZmZpeCA9IGZhbHNlLFxuICAgICAgICAgICAgdGggPSB0aHJlc2hvbGRzLFxuICAgICAgICAgICAgbG9jYWxlLFxuICAgICAgICAgICAgb3V0cHV0O1xuXG4gICAgICAgIGlmICh0eXBlb2YgYXJnV2l0aFN1ZmZpeCA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgICAgIGFyZ1RocmVzaG9sZHMgPSBhcmdXaXRoU3VmZml4O1xuICAgICAgICAgICAgYXJnV2l0aFN1ZmZpeCA9IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgYXJnV2l0aFN1ZmZpeCA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgICB3aXRoU3VmZml4ID0gYXJnV2l0aFN1ZmZpeDtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIGFyZ1RocmVzaG9sZHMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICB0aCA9IE9iamVjdC5hc3NpZ24oe30sIHRocmVzaG9sZHMsIGFyZ1RocmVzaG9sZHMpO1xuICAgICAgICAgICAgaWYgKGFyZ1RocmVzaG9sZHMucyAhPSBudWxsICYmIGFyZ1RocmVzaG9sZHMuc3MgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoLnNzID0gYXJnVGhyZXNob2xkcy5zIC0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGxvY2FsZSA9IHRoaXMubG9jYWxlRGF0YSgpO1xuICAgICAgICBvdXRwdXQgPSByZWxhdGl2ZVRpbWUkMSh0aGlzLCAhd2l0aFN1ZmZpeCwgdGgsIGxvY2FsZSk7XG5cbiAgICAgICAgaWYgKHdpdGhTdWZmaXgpIHtcbiAgICAgICAgICAgIG91dHB1dCA9IGxvY2FsZS5wYXN0RnV0dXJlKCt0aGlzLCBvdXRwdXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGxvY2FsZS5wb3N0Zm9ybWF0KG91dHB1dCk7XG4gICAgfVxuXG4gICAgdmFyIGFicyQxID0gTWF0aC5hYnM7XG5cbiAgICBmdW5jdGlvbiBzaWduKHgpIHtcbiAgICAgICAgcmV0dXJuICh4ID4gMCkgLSAoeCA8IDApIHx8ICt4O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHRvSVNPU3RyaW5nJDEoKSB7XG4gICAgICAgIC8vIGZvciBJU08gc3RyaW5ncyB3ZSBkbyBub3QgdXNlIHRoZSBub3JtYWwgYnViYmxpbmcgcnVsZXM6XG4gICAgICAgIC8vICAqIG1pbGxpc2Vjb25kcyBidWJibGUgdXAgdW50aWwgdGhleSBiZWNvbWUgaG91cnNcbiAgICAgICAgLy8gICogZGF5cyBkbyBub3QgYnViYmxlIGF0IGFsbFxuICAgICAgICAvLyAgKiBtb250aHMgYnViYmxlIHVwIHVudGlsIHRoZXkgYmVjb21lIHllYXJzXG4gICAgICAgIC8vIFRoaXMgaXMgYmVjYXVzZSB0aGVyZSBpcyBubyBjb250ZXh0LWZyZWUgY29udmVyc2lvbiBiZXR3ZWVuIGhvdXJzIGFuZCBkYXlzXG4gICAgICAgIC8vICh0aGluayBvZiBjbG9jayBjaGFuZ2VzKVxuICAgICAgICAvLyBhbmQgYWxzbyBub3QgYmV0d2VlbiBkYXlzIGFuZCBtb250aHMgKDI4LTMxIGRheXMgcGVyIG1vbnRoKVxuICAgICAgICBpZiAoIXRoaXMuaXNWYWxpZCgpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sb2NhbGVEYXRhKCkuaW52YWxpZERhdGUoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBzZWNvbmRzID0gYWJzJDEodGhpcy5fbWlsbGlzZWNvbmRzKSAvIDEwMDAsXG4gICAgICAgICAgICBkYXlzID0gYWJzJDEodGhpcy5fZGF5cyksXG4gICAgICAgICAgICBtb250aHMgPSBhYnMkMSh0aGlzLl9tb250aHMpLFxuICAgICAgICAgICAgbWludXRlcyxcbiAgICAgICAgICAgIGhvdXJzLFxuICAgICAgICAgICAgeWVhcnMsXG4gICAgICAgICAgICBzLFxuICAgICAgICAgICAgdG90YWwgPSB0aGlzLmFzU2Vjb25kcygpLFxuICAgICAgICAgICAgdG90YWxTaWduLFxuICAgICAgICAgICAgeW1TaWduLFxuICAgICAgICAgICAgZGF5c1NpZ24sXG4gICAgICAgICAgICBobXNTaWduO1xuXG4gICAgICAgIGlmICghdG90YWwpIHtcbiAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHNhbWUgYXMgQyMncyAoTm9kYSkgYW5kIHB5dGhvbiAoaXNvZGF0ZSkuLi5cbiAgICAgICAgICAgIC8vIGJ1dCBub3Qgb3RoZXIgSlMgKGdvb2cuZGF0ZSlcbiAgICAgICAgICAgIHJldHVybiAnUDBEJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDM2MDAgc2Vjb25kcyAtPiA2MCBtaW51dGVzIC0+IDEgaG91clxuICAgICAgICBtaW51dGVzID0gYWJzRmxvb3Ioc2Vjb25kcyAvIDYwKTtcbiAgICAgICAgaG91cnMgPSBhYnNGbG9vcihtaW51dGVzIC8gNjApO1xuICAgICAgICBzZWNvbmRzICU9IDYwO1xuICAgICAgICBtaW51dGVzICU9IDYwO1xuXG4gICAgICAgIC8vIDEyIG1vbnRocyAtPiAxIHllYXJcbiAgICAgICAgeWVhcnMgPSBhYnNGbG9vcihtb250aHMgLyAxMik7XG4gICAgICAgIG1vbnRocyAlPSAxMjtcblxuICAgICAgICAvLyBpbnNwaXJlZCBieSBodHRwczovL2dpdGh1Yi5jb20vZG9yZGlsbGUvbW9tZW50LWlzb2R1cmF0aW9uL2Jsb2IvbWFzdGVyL21vbWVudC5pc29kdXJhdGlvbi5qc1xuICAgICAgICBzID0gc2Vjb25kcyA/IHNlY29uZHMudG9GaXhlZCgzKS5yZXBsYWNlKC9cXC4/MCskLywgJycpIDogJyc7XG5cbiAgICAgICAgdG90YWxTaWduID0gdG90YWwgPCAwID8gJy0nIDogJyc7XG4gICAgICAgIHltU2lnbiA9IHNpZ24odGhpcy5fbW9udGhzKSAhPT0gc2lnbih0b3RhbCkgPyAnLScgOiAnJztcbiAgICAgICAgZGF5c1NpZ24gPSBzaWduKHRoaXMuX2RheXMpICE9PSBzaWduKHRvdGFsKSA/ICctJyA6ICcnO1xuICAgICAgICBobXNTaWduID0gc2lnbih0aGlzLl9taWxsaXNlY29uZHMpICE9PSBzaWduKHRvdGFsKSA/ICctJyA6ICcnO1xuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICB0b3RhbFNpZ24gK1xuICAgICAgICAgICAgJ1AnICtcbiAgICAgICAgICAgICh5ZWFycyA/IHltU2lnbiArIHllYXJzICsgJ1knIDogJycpICtcbiAgICAgICAgICAgIChtb250aHMgPyB5bVNpZ24gKyBtb250aHMgKyAnTScgOiAnJykgK1xuICAgICAgICAgICAgKGRheXMgPyBkYXlzU2lnbiArIGRheXMgKyAnRCcgOiAnJykgK1xuICAgICAgICAgICAgKGhvdXJzIHx8IG1pbnV0ZXMgfHwgc2Vjb25kcyA/ICdUJyA6ICcnKSArXG4gICAgICAgICAgICAoaG91cnMgPyBobXNTaWduICsgaG91cnMgKyAnSCcgOiAnJykgK1xuICAgICAgICAgICAgKG1pbnV0ZXMgPyBobXNTaWduICsgbWludXRlcyArICdNJyA6ICcnKSArXG4gICAgICAgICAgICAoc2Vjb25kcyA/IGhtc1NpZ24gKyBzICsgJ1MnIDogJycpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgdmFyIHByb3RvJDIgPSBEdXJhdGlvbi5wcm90b3R5cGU7XG5cbiAgICBwcm90byQyLmlzVmFsaWQgPSBpc1ZhbGlkJDE7XG4gICAgcHJvdG8kMi5hYnMgPSBhYnM7XG4gICAgcHJvdG8kMi5hZGQgPSBhZGQkMTtcbiAgICBwcm90byQyLnN1YnRyYWN0ID0gc3VidHJhY3QkMTtcbiAgICBwcm90byQyLmFzID0gYXM7XG4gICAgcHJvdG8kMi5hc01pbGxpc2Vjb25kcyA9IGFzTWlsbGlzZWNvbmRzO1xuICAgIHByb3RvJDIuYXNTZWNvbmRzID0gYXNTZWNvbmRzO1xuICAgIHByb3RvJDIuYXNNaW51dGVzID0gYXNNaW51dGVzO1xuICAgIHByb3RvJDIuYXNIb3VycyA9IGFzSG91cnM7XG4gICAgcHJvdG8kMi5hc0RheXMgPSBhc0RheXM7XG4gICAgcHJvdG8kMi5hc1dlZWtzID0gYXNXZWVrcztcbiAgICBwcm90byQyLmFzTW9udGhzID0gYXNNb250aHM7XG4gICAgcHJvdG8kMi5hc1F1YXJ0ZXJzID0gYXNRdWFydGVycztcbiAgICBwcm90byQyLmFzWWVhcnMgPSBhc1llYXJzO1xuICAgIHByb3RvJDIudmFsdWVPZiA9IHZhbHVlT2YkMTtcbiAgICBwcm90byQyLl9idWJibGUgPSBidWJibGU7XG4gICAgcHJvdG8kMi5jbG9uZSA9IGNsb25lJDE7XG4gICAgcHJvdG8kMi5nZXQgPSBnZXQkMjtcbiAgICBwcm90byQyLm1pbGxpc2Vjb25kcyA9IG1pbGxpc2Vjb25kcztcbiAgICBwcm90byQyLnNlY29uZHMgPSBzZWNvbmRzO1xuICAgIHByb3RvJDIubWludXRlcyA9IG1pbnV0ZXM7XG4gICAgcHJvdG8kMi5ob3VycyA9IGhvdXJzO1xuICAgIHByb3RvJDIuZGF5cyA9IGRheXM7XG4gICAgcHJvdG8kMi53ZWVrcyA9IHdlZWtzO1xuICAgIHByb3RvJDIubW9udGhzID0gbW9udGhzO1xuICAgIHByb3RvJDIueWVhcnMgPSB5ZWFycztcbiAgICBwcm90byQyLmh1bWFuaXplID0gaHVtYW5pemU7XG4gICAgcHJvdG8kMi50b0lTT1N0cmluZyA9IHRvSVNPU3RyaW5nJDE7XG4gICAgcHJvdG8kMi50b1N0cmluZyA9IHRvSVNPU3RyaW5nJDE7XG4gICAgcHJvdG8kMi50b0pTT04gPSB0b0lTT1N0cmluZyQxO1xuICAgIHByb3RvJDIubG9jYWxlID0gbG9jYWxlO1xuICAgIHByb3RvJDIubG9jYWxlRGF0YSA9IGxvY2FsZURhdGE7XG5cbiAgICBwcm90byQyLnRvSXNvU3RyaW5nID0gZGVwcmVjYXRlKFxuICAgICAgICAndG9Jc29TdHJpbmcoKSBpcyBkZXByZWNhdGVkLiBQbGVhc2UgdXNlIHRvSVNPU3RyaW5nKCkgaW5zdGVhZCAobm90aWNlIHRoZSBjYXBpdGFscyknLFxuICAgICAgICB0b0lTT1N0cmluZyQxXG4gICAgKTtcbiAgICBwcm90byQyLmxhbmcgPSBsYW5nO1xuXG4gICAgLy8gRk9STUFUVElOR1xuXG4gICAgYWRkRm9ybWF0VG9rZW4oJ1gnLCAwLCAwLCAndW5peCcpO1xuICAgIGFkZEZvcm1hdFRva2VuKCd4JywgMCwgMCwgJ3ZhbHVlT2YnKTtcblxuICAgIC8vIFBBUlNJTkdcblxuICAgIGFkZFJlZ2V4VG9rZW4oJ3gnLCBtYXRjaFNpZ25lZCk7XG4gICAgYWRkUmVnZXhUb2tlbignWCcsIG1hdGNoVGltZXN0YW1wKTtcbiAgICBhZGRQYXJzZVRva2VuKCdYJywgZnVuY3Rpb24gKGlucHV0LCBhcnJheSwgY29uZmlnKSB7XG4gICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKHBhcnNlRmxvYXQoaW5wdXQpICogMTAwMCk7XG4gICAgfSk7XG4gICAgYWRkUGFyc2VUb2tlbigneCcsIGZ1bmN0aW9uIChpbnB1dCwgYXJyYXksIGNvbmZpZykge1xuICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZSh0b0ludChpbnB1dCkpO1xuICAgIH0pO1xuXG4gICAgLy8hIG1vbWVudC5qc1xuXG4gICAgaG9va3MudmVyc2lvbiA9ICcyLjI3LjAnO1xuXG4gICAgc2V0SG9va0NhbGxiYWNrKGNyZWF0ZUxvY2FsKTtcblxuICAgIGhvb2tzLmZuID0gcHJvdG87XG4gICAgaG9va3MubWluID0gbWluO1xuICAgIGhvb2tzLm1heCA9IG1heDtcbiAgICBob29rcy5ub3cgPSBub3c7XG4gICAgaG9va3MudXRjID0gY3JlYXRlVVRDO1xuICAgIGhvb2tzLnVuaXggPSBjcmVhdGVVbml4O1xuICAgIGhvb2tzLm1vbnRocyA9IGxpc3RNb250aHM7XG4gICAgaG9va3MuaXNEYXRlID0gaXNEYXRlO1xuICAgIGhvb2tzLmxvY2FsZSA9IGdldFNldEdsb2JhbExvY2FsZTtcbiAgICBob29rcy5pbnZhbGlkID0gY3JlYXRlSW52YWxpZDtcbiAgICBob29rcy5kdXJhdGlvbiA9IGNyZWF0ZUR1cmF0aW9uO1xuICAgIGhvb2tzLmlzTW9tZW50ID0gaXNNb21lbnQ7XG4gICAgaG9va3Mud2Vla2RheXMgPSBsaXN0V2Vla2RheXM7XG4gICAgaG9va3MucGFyc2Vab25lID0gY3JlYXRlSW5ab25lO1xuICAgIGhvb2tzLmxvY2FsZURhdGEgPSBnZXRMb2NhbGU7XG4gICAgaG9va3MuaXNEdXJhdGlvbiA9IGlzRHVyYXRpb247XG4gICAgaG9va3MubW9udGhzU2hvcnQgPSBsaXN0TW9udGhzU2hvcnQ7XG4gICAgaG9va3Mud2Vla2RheXNNaW4gPSBsaXN0V2Vla2RheXNNaW47XG4gICAgaG9va3MuZGVmaW5lTG9jYWxlID0gZGVmaW5lTG9jYWxlO1xuICAgIGhvb2tzLnVwZGF0ZUxvY2FsZSA9IHVwZGF0ZUxvY2FsZTtcbiAgICBob29rcy5sb2NhbGVzID0gbGlzdExvY2FsZXM7XG4gICAgaG9va3Mud2Vla2RheXNTaG9ydCA9IGxpc3RXZWVrZGF5c1Nob3J0O1xuICAgIGhvb2tzLm5vcm1hbGl6ZVVuaXRzID0gbm9ybWFsaXplVW5pdHM7XG4gICAgaG9va3MucmVsYXRpdmVUaW1lUm91bmRpbmcgPSBnZXRTZXRSZWxhdGl2ZVRpbWVSb3VuZGluZztcbiAgICBob29rcy5yZWxhdGl2ZVRpbWVUaHJlc2hvbGQgPSBnZXRTZXRSZWxhdGl2ZVRpbWVUaHJlc2hvbGQ7XG4gICAgaG9va3MuY2FsZW5kYXJGb3JtYXQgPSBnZXRDYWxlbmRhckZvcm1hdDtcbiAgICBob29rcy5wcm90b3R5cGUgPSBwcm90bztcblxuICAgIC8vIGN1cnJlbnRseSBIVE1MNSBpbnB1dCB0eXBlIG9ubHkgc3VwcG9ydHMgMjQtaG91ciBmb3JtYXRzXG4gICAgaG9va3MuSFRNTDVfRk1UID0ge1xuICAgICAgICBEQVRFVElNRV9MT0NBTDogJ1lZWVktTU0tRERUSEg6bW0nLCAvLyA8aW5wdXQgdHlwZT1cImRhdGV0aW1lLWxvY2FsXCIgLz5cbiAgICAgICAgREFURVRJTUVfTE9DQUxfU0VDT05EUzogJ1lZWVktTU0tRERUSEg6bW06c3MnLCAvLyA8aW5wdXQgdHlwZT1cImRhdGV0aW1lLWxvY2FsXCIgc3RlcD1cIjFcIiAvPlxuICAgICAgICBEQVRFVElNRV9MT0NBTF9NUzogJ1lZWVktTU0tRERUSEg6bW06c3MuU1NTJywgLy8gPGlucHV0IHR5cGU9XCJkYXRldGltZS1sb2NhbFwiIHN0ZXA9XCIwLjAwMVwiIC8+XG4gICAgICAgIERBVEU6ICdZWVlZLU1NLUREJywgLy8gPGlucHV0IHR5cGU9XCJkYXRlXCIgLz5cbiAgICAgICAgVElNRTogJ0hIOm1tJywgLy8gPGlucHV0IHR5cGU9XCJ0aW1lXCIgLz5cbiAgICAgICAgVElNRV9TRUNPTkRTOiAnSEg6bW06c3MnLCAvLyA8aW5wdXQgdHlwZT1cInRpbWVcIiBzdGVwPVwiMVwiIC8+XG4gICAgICAgIFRJTUVfTVM6ICdISDptbTpzcy5TU1MnLCAvLyA8aW5wdXQgdHlwZT1cInRpbWVcIiBzdGVwPVwiMC4wMDFcIiAvPlxuICAgICAgICBXRUVLOiAnR0dHRy1bV11XVycsIC8vIDxpbnB1dCB0eXBlPVwid2Vla1wiIC8+XG4gICAgICAgIE1PTlRIOiAnWVlZWS1NTScsIC8vIDxpbnB1dCB0eXBlPVwibW9udGhcIiAvPlxuICAgIH07XG5cbiAgICByZXR1cm4gaG9va3M7XG5cbn0pKSk7XG4iLCIvLyBHZW5lcmF0ZWQgYnkgTGl2ZVNjcmlwdCAxLjYuMFxudmFyIGFwcGx5LCBjdXJyeSwgZmxpcCwgZml4LCBvdmVyLCBtZW1vaXplLCB0b1N0cmluZyQgPSB7fS50b1N0cmluZztcbmFwcGx5ID0gY3VycnkkKGZ1bmN0aW9uKGYsIGxpc3Qpe1xuICByZXR1cm4gZi5hcHBseShudWxsLCBsaXN0KTtcbn0pO1xuY3VycnkgPSBmdW5jdGlvbihmKXtcbiAgcmV0dXJuIGN1cnJ5JChmKTtcbn07XG5mbGlwID0gY3VycnkkKGZ1bmN0aW9uKGYsIHgsIHkpe1xuICByZXR1cm4gZih5LCB4KTtcbn0pO1xuZml4ID0gZnVuY3Rpb24oZil7XG4gIHJldHVybiBmdW5jdGlvbihnKXtcbiAgICByZXR1cm4gZnVuY3Rpb24oKXtcbiAgICAgIHJldHVybiBmKGcoZykpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfShmdW5jdGlvbihnKXtcbiAgICByZXR1cm4gZnVuY3Rpb24oKXtcbiAgICAgIHJldHVybiBmKGcoZykpLmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgfTtcbiAgfSk7XG59O1xub3ZlciA9IGN1cnJ5JChmdW5jdGlvbihmLCBnLCB4LCB5KXtcbiAgcmV0dXJuIGYoZyh4KSwgZyh5KSk7XG59KTtcbm1lbW9pemUgPSBmdW5jdGlvbihmKXtcbiAgdmFyIG1lbW87XG4gIG1lbW8gPSB7fTtcbiAgcmV0dXJuIGZ1bmN0aW9uKCl7XG4gICAgdmFyIGFyZ3MsIHJlcyQsIGkkLCB0byQsIGtleSwgYXJnO1xuICAgIHJlcyQgPSBbXTtcbiAgICBmb3IgKGkkID0gMCwgdG8kID0gYXJndW1lbnRzLmxlbmd0aDsgaSQgPCB0byQ7ICsraSQpIHtcbiAgICAgIHJlcyQucHVzaChhcmd1bWVudHNbaSRdKTtcbiAgICB9XG4gICAgYXJncyA9IHJlcyQ7XG4gICAga2V5ID0gKGZ1bmN0aW9uKCl7XG4gICAgICB2YXIgaSQsIHJlZiQsIGxlbiQsIHJlc3VsdHMkID0gW107XG4gICAgICBmb3IgKGkkID0gMCwgbGVuJCA9IChyZWYkID0gYXJncykubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICAgICAgYXJnID0gcmVmJFtpJF07XG4gICAgICAgIHJlc3VsdHMkLnB1c2goYXJnICsgdG9TdHJpbmckLmNhbGwoYXJnKS5zbGljZSg4LCAtMSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdHMkO1xuICAgIH0oKSkuam9pbignJyk7XG4gICAgcmV0dXJuIG1lbW9ba2V5XSA9IGtleSBpbiBtZW1vXG4gICAgICA/IG1lbW9ba2V5XVxuICAgICAgOiBmLmFwcGx5KG51bGwsIGFyZ3MpO1xuICB9O1xufTtcbm1vZHVsZS5leHBvcnRzID0ge1xuICBjdXJyeTogY3VycnksXG4gIGZsaXA6IGZsaXAsXG4gIGZpeDogZml4LFxuICBhcHBseTogYXBwbHksXG4gIG92ZXI6IG92ZXIsXG4gIG1lbW9pemU6IG1lbW9pemVcbn07XG5mdW5jdGlvbiBjdXJyeSQoZiwgYm91bmQpe1xuICB2YXIgY29udGV4dCxcbiAgX2N1cnJ5ID0gZnVuY3Rpb24oYXJncykge1xuICAgIHJldHVybiBmLmxlbmd0aCA+IDEgPyBmdW5jdGlvbigpe1xuICAgICAgdmFyIHBhcmFtcyA9IGFyZ3MgPyBhcmdzLmNvbmNhdCgpIDogW107XG4gICAgICBjb250ZXh0ID0gYm91bmQgPyBjb250ZXh0IHx8IHRoaXMgOiB0aGlzO1xuICAgICAgcmV0dXJuIHBhcmFtcy5wdXNoLmFwcGx5KHBhcmFtcywgYXJndW1lbnRzKSA8XG4gICAgICAgICAgZi5sZW5ndGggJiYgYXJndW1lbnRzLmxlbmd0aCA/XG4gICAgICAgIF9jdXJyeS5jYWxsKGNvbnRleHQsIHBhcmFtcykgOiBmLmFwcGx5KGNvbnRleHQsIHBhcmFtcyk7XG4gICAgfSA6IGY7XG4gIH07XG4gIHJldHVybiBfY3VycnkoKTtcbn0iLCIvLyBHZW5lcmF0ZWQgYnkgTGl2ZVNjcmlwdCAxLjYuMFxudmFyIGVhY2gsIG1hcCwgY29tcGFjdCwgZmlsdGVyLCByZWplY3QsIHJlbW92ZSwgcGFydGl0aW9uLCBmaW5kLCBoZWFkLCBmaXJzdCwgdGFpbCwgbGFzdCwgaW5pdGlhbCwgZW1wdHksIHJldmVyc2UsIHVuaXF1ZSwgdW5pcXVlQnksIGZvbGQsIGZvbGRsLCBmb2xkMSwgZm9sZGwxLCBmb2xkciwgZm9sZHIxLCB1bmZvbGRyLCBjb25jYXQsIGNvbmNhdE1hcCwgZmxhdHRlbiwgZGlmZmVyZW5jZSwgaW50ZXJzZWN0aW9uLCB1bmlvbiwgY291bnRCeSwgZ3JvdXBCeSwgYW5kTGlzdCwgb3JMaXN0LCBhbnksIGFsbCwgc29ydCwgc29ydFdpdGgsIHNvcnRCeSwgc3VtLCBwcm9kdWN0LCBtZWFuLCBhdmVyYWdlLCBtYXhpbXVtLCBtaW5pbXVtLCBtYXhpbXVtQnksIG1pbmltdW1CeSwgc2Nhbiwgc2NhbmwsIHNjYW4xLCBzY2FubDEsIHNjYW5yLCBzY2FucjEsIHNsaWNlLCB0YWtlLCBkcm9wLCBzcGxpdEF0LCB0YWtlV2hpbGUsIGRyb3BXaGlsZSwgc3BhbiwgYnJlYWtMaXN0LCB6aXAsIHppcFdpdGgsIHppcEFsbCwgemlwQWxsV2l0aCwgYXQsIGVsZW1JbmRleCwgZWxlbUluZGljZXMsIGZpbmRJbmRleCwgZmluZEluZGljZXMsIHRvU3RyaW5nJCA9IHt9LnRvU3RyaW5nO1xuZWFjaCA9IGN1cnJ5JChmdW5jdGlvbihmLCB4cyl7XG4gIHZhciBpJCwgbGVuJCwgeDtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgZih4KTtcbiAgfVxuICByZXR1cm4geHM7XG59KTtcbm1hcCA9IGN1cnJ5JChmdW5jdGlvbihmLCB4cyl7XG4gIHZhciBpJCwgbGVuJCwgeCwgcmVzdWx0cyQgPSBbXTtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgcmVzdWx0cyQucHVzaChmKHgpKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0cyQ7XG59KTtcbmNvbXBhY3QgPSBmdW5jdGlvbih4cyl7XG4gIHZhciBpJCwgbGVuJCwgeCwgcmVzdWx0cyQgPSBbXTtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgaWYgKHgpIHtcbiAgICAgIHJlc3VsdHMkLnB1c2goeCk7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRzJDtcbn07XG5maWx0ZXIgPSBjdXJyeSQoZnVuY3Rpb24oZiwgeHMpe1xuICB2YXIgaSQsIGxlbiQsIHgsIHJlc3VsdHMkID0gW107XG4gIGZvciAoaSQgPSAwLCBsZW4kID0geHMubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICB4ID0geHNbaSRdO1xuICAgIGlmIChmKHgpKSB7XG4gICAgICByZXN1bHRzJC5wdXNoKHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0cyQ7XG59KTtcbnJlamVjdCA9IGN1cnJ5JChmdW5jdGlvbihmLCB4cyl7XG4gIHZhciBpJCwgbGVuJCwgeCwgcmVzdWx0cyQgPSBbXTtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgaWYgKCFmKHgpKSB7XG4gICAgICByZXN1bHRzJC5wdXNoKHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0cyQ7XG59KTtcbnJlbW92ZSA9IGN1cnJ5JChmdW5jdGlvbihlbCwgeHMpe1xuICB2YXIgaSwgeCQ7XG4gIGkgPSBlbGVtSW5kZXgoZWwsIHhzKTtcbiAgeCQgPSB4cy5zbGljZSgpO1xuICBpZiAoaSAhPSBudWxsKSB7XG4gICAgeCQuc3BsaWNlKGksIDEpO1xuICB9XG4gIHJldHVybiB4JDtcbn0pO1xucGFydGl0aW9uID0gY3VycnkkKGZ1bmN0aW9uKGYsIHhzKXtcbiAgdmFyIHBhc3NlZCwgZmFpbGVkLCBpJCwgbGVuJCwgeDtcbiAgcGFzc2VkID0gW107XG4gIGZhaWxlZCA9IFtdO1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHhzW2kkXTtcbiAgICAoZih4KSA/IHBhc3NlZCA6IGZhaWxlZCkucHVzaCh4KTtcbiAgfVxuICByZXR1cm4gW3Bhc3NlZCwgZmFpbGVkXTtcbn0pO1xuZmluZCA9IGN1cnJ5JChmdW5jdGlvbihmLCB4cyl7XG4gIHZhciBpJCwgbGVuJCwgeDtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgaWYgKGYoeCkpIHtcbiAgICAgIHJldHVybiB4O1xuICAgIH1cbiAgfVxufSk7XG5oZWFkID0gZmlyc3QgPSBmdW5jdGlvbih4cyl7XG4gIHJldHVybiB4c1swXTtcbn07XG50YWlsID0gZnVuY3Rpb24oeHMpe1xuICBpZiAoIXhzLmxlbmd0aCkge1xuICAgIHJldHVybjtcbiAgfVxuICByZXR1cm4geHMuc2xpY2UoMSk7XG59O1xubGFzdCA9IGZ1bmN0aW9uKHhzKXtcbiAgcmV0dXJuIHhzW3hzLmxlbmd0aCAtIDFdO1xufTtcbmluaXRpYWwgPSBmdW5jdGlvbih4cyl7XG4gIGlmICgheHMubGVuZ3RoKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHJldHVybiB4cy5zbGljZSgwLCAtMSk7XG59O1xuZW1wdHkgPSBmdW5jdGlvbih4cyl7XG4gIHJldHVybiAheHMubGVuZ3RoO1xufTtcbnJldmVyc2UgPSBmdW5jdGlvbih4cyl7XG4gIHJldHVybiB4cy5jb25jYXQoKS5yZXZlcnNlKCk7XG59O1xudW5pcXVlID0gZnVuY3Rpb24oeHMpe1xuICB2YXIgcmVzdWx0LCBpJCwgbGVuJCwgeDtcbiAgcmVzdWx0ID0gW107XG4gIGZvciAoaSQgPSAwLCBsZW4kID0geHMubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICB4ID0geHNbaSRdO1xuICAgIGlmICghaW4kKHgsIHJlc3VsdCkpIHtcbiAgICAgIHJlc3VsdC5wdXNoKHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcbnVuaXF1ZUJ5ID0gY3VycnkkKGZ1bmN0aW9uKGYsIHhzKXtcbiAgdmFyIHNlZW4sIGkkLCBsZW4kLCB4LCB2YWwsIHJlc3VsdHMkID0gW107XG4gIHNlZW4gPSBbXTtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgdmFsID0gZih4KTtcbiAgICBpZiAoaW4kKHZhbCwgc2VlbikpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBzZWVuLnB1c2godmFsKTtcbiAgICByZXN1bHRzJC5wdXNoKHgpO1xuICB9XG4gIHJldHVybiByZXN1bHRzJDtcbn0pO1xuZm9sZCA9IGZvbGRsID0gY3VycnkkKGZ1bmN0aW9uKGYsIG1lbW8sIHhzKXtcbiAgdmFyIGkkLCBsZW4kLCB4O1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHhzW2kkXTtcbiAgICBtZW1vID0gZihtZW1vLCB4KTtcbiAgfVxuICByZXR1cm4gbWVtbztcbn0pO1xuZm9sZDEgPSBmb2xkbDEgPSBjdXJyeSQoZnVuY3Rpb24oZiwgeHMpe1xuICByZXR1cm4gZm9sZChmLCB4c1swXSwgeHMuc2xpY2UoMSkpO1xufSk7XG5mb2xkciA9IGN1cnJ5JChmdW5jdGlvbihmLCBtZW1vLCB4cyl7XG4gIHZhciBpJCwgeDtcbiAgZm9yIChpJCA9IHhzLmxlbmd0aCAtIDE7IGkkID49IDA7IC0taSQpIHtcbiAgICB4ID0geHNbaSRdO1xuICAgIG1lbW8gPSBmKHgsIG1lbW8pO1xuICB9XG4gIHJldHVybiBtZW1vO1xufSk7XG5mb2xkcjEgPSBjdXJyeSQoZnVuY3Rpb24oZiwgeHMpe1xuICByZXR1cm4gZm9sZHIoZiwgeHNbeHMubGVuZ3RoIC0gMV0sIHhzLnNsaWNlKDAsIC0xKSk7XG59KTtcbnVuZm9sZHIgPSBjdXJyeSQoZnVuY3Rpb24oZiwgYil7XG4gIHZhciByZXN1bHQsIHgsIHRoYXQ7XG4gIHJlc3VsdCA9IFtdO1xuICB4ID0gYjtcbiAgd2hpbGUgKCh0aGF0ID0gZih4KSkgIT0gbnVsbCkge1xuICAgIHJlc3VsdC5wdXNoKHRoYXRbMF0pO1xuICAgIHggPSB0aGF0WzFdO1xuICB9XG4gIHJldHVybiByZXN1bHQ7XG59KTtcbmNvbmNhdCA9IGZ1bmN0aW9uKHhzcyl7XG4gIHJldHVybiBbXS5jb25jYXQuYXBwbHkoW10sIHhzcyk7XG59O1xuY29uY2F0TWFwID0gY3VycnkkKGZ1bmN0aW9uKGYsIHhzKXtcbiAgdmFyIHg7XG4gIHJldHVybiBbXS5jb25jYXQuYXBwbHkoW10sIChmdW5jdGlvbigpe1xuICAgIHZhciBpJCwgcmVmJCwgbGVuJCwgcmVzdWx0cyQgPSBbXTtcbiAgICBmb3IgKGkkID0gMCwgbGVuJCA9IChyZWYkID0geHMpLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgICB4ID0gcmVmJFtpJF07XG4gICAgICByZXN1bHRzJC5wdXNoKGYoeCkpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0cyQ7XG4gIH0oKSkpO1xufSk7XG5mbGF0dGVuID0gZnVuY3Rpb24oeHMpe1xuICB2YXIgeDtcbiAgcmV0dXJuIFtdLmNvbmNhdC5hcHBseShbXSwgKGZ1bmN0aW9uKCl7XG4gICAgdmFyIGkkLCByZWYkLCBsZW4kLCByZXN1bHRzJCA9IFtdO1xuICAgIGZvciAoaSQgPSAwLCBsZW4kID0gKHJlZiQgPSB4cykubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICAgIHggPSByZWYkW2kkXTtcbiAgICAgIGlmICh0b1N0cmluZyQuY2FsbCh4KS5zbGljZSg4LCAtMSkgPT09ICdBcnJheScpIHtcbiAgICAgICAgcmVzdWx0cyQucHVzaChmbGF0dGVuKHgpKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdHMkLnB1c2goeCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzJDtcbiAgfSgpKSk7XG59O1xuZGlmZmVyZW5jZSA9IGZ1bmN0aW9uKHhzKXtcbiAgdmFyIHlzcywgcmVzJCwgaSQsIHRvJCwgcmVzdWx0cywgbGVuJCwgeCwgaiQsIGxlbjEkLCB5cztcbiAgcmVzJCA9IFtdO1xuICBmb3IgKGkkID0gMSwgdG8kID0gYXJndW1lbnRzLmxlbmd0aDsgaSQgPCB0byQ7ICsraSQpIHtcbiAgICByZXMkLnB1c2goYXJndW1lbnRzW2kkXSk7XG4gIH1cbiAgeXNzID0gcmVzJDtcbiAgcmVzdWx0cyA9IFtdO1xuICBvdXRlcjogZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgZm9yIChqJCA9IDAsIGxlbjEkID0geXNzLmxlbmd0aDsgaiQgPCBsZW4xJDsgKytqJCkge1xuICAgICAgeXMgPSB5c3NbaiRdO1xuICAgICAgaWYgKGluJCh4LCB5cykpIHtcbiAgICAgICAgY29udGludWUgb3V0ZXI7XG4gICAgICB9XG4gICAgfVxuICAgIHJlc3VsdHMucHVzaCh4KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0cztcbn07XG5pbnRlcnNlY3Rpb24gPSBmdW5jdGlvbih4cyl7XG4gIHZhciB5c3MsIHJlcyQsIGkkLCB0byQsIHJlc3VsdHMsIGxlbiQsIHgsIGokLCBsZW4xJCwgeXM7XG4gIHJlcyQgPSBbXTtcbiAgZm9yIChpJCA9IDEsIHRvJCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkkIDwgdG8kOyArK2kkKSB7XG4gICAgcmVzJC5wdXNoKGFyZ3VtZW50c1tpJF0pO1xuICB9XG4gIHlzcyA9IHJlcyQ7XG4gIHJlc3VsdHMgPSBbXTtcbiAgb3V0ZXI6IGZvciAoaSQgPSAwLCBsZW4kID0geHMubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICB4ID0geHNbaSRdO1xuICAgIGZvciAoaiQgPSAwLCBsZW4xJCA9IHlzcy5sZW5ndGg7IGokIDwgbGVuMSQ7ICsraiQpIHtcbiAgICAgIHlzID0geXNzW2okXTtcbiAgICAgIGlmICghaW4kKHgsIHlzKSkge1xuICAgICAgICBjb250aW51ZSBvdXRlcjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmVzdWx0cy5wdXNoKHgpO1xuICB9XG4gIHJldHVybiByZXN1bHRzO1xufTtcbnVuaW9uID0gZnVuY3Rpb24oKXtcbiAgdmFyIHhzcywgcmVzJCwgaSQsIHRvJCwgcmVzdWx0cywgbGVuJCwgeHMsIGokLCBsZW4xJCwgeDtcbiAgcmVzJCA9IFtdO1xuICBmb3IgKGkkID0gMCwgdG8kID0gYXJndW1lbnRzLmxlbmd0aDsgaSQgPCB0byQ7ICsraSQpIHtcbiAgICByZXMkLnB1c2goYXJndW1lbnRzW2kkXSk7XG4gIH1cbiAgeHNzID0gcmVzJDtcbiAgcmVzdWx0cyA9IFtdO1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzcy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHhzID0geHNzW2kkXTtcbiAgICBmb3IgKGokID0gMCwgbGVuMSQgPSB4cy5sZW5ndGg7IGokIDwgbGVuMSQ7ICsraiQpIHtcbiAgICAgIHggPSB4c1tqJF07XG4gICAgICBpZiAoIWluJCh4LCByZXN1bHRzKSkge1xuICAgICAgICByZXN1bHRzLnB1c2goeCk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRzO1xufTtcbmNvdW50QnkgPSBjdXJyeSQoZnVuY3Rpb24oZiwgeHMpe1xuICB2YXIgcmVzdWx0cywgaSQsIGxlbiQsIHgsIGtleTtcbiAgcmVzdWx0cyA9IHt9O1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHhzW2kkXTtcbiAgICBrZXkgPSBmKHgpO1xuICAgIGlmIChrZXkgaW4gcmVzdWx0cykge1xuICAgICAgcmVzdWx0c1trZXldICs9IDE7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJlc3VsdHNba2V5XSA9IDE7XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRzO1xufSk7XG5ncm91cEJ5ID0gY3VycnkkKGZ1bmN0aW9uKGYsIHhzKXtcbiAgdmFyIHJlc3VsdHMsIGkkLCBsZW4kLCB4LCBrZXk7XG4gIHJlc3VsdHMgPSB7fTtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAga2V5ID0gZih4KTtcbiAgICBpZiAoa2V5IGluIHJlc3VsdHMpIHtcbiAgICAgIHJlc3VsdHNba2V5XS5wdXNoKHgpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXN1bHRzW2tleV0gPSBbeF07XG4gICAgfVxuICB9XG4gIHJldHVybiByZXN1bHRzO1xufSk7XG5hbmRMaXN0ID0gZnVuY3Rpb24oeHMpe1xuICB2YXIgaSQsIGxlbiQsIHg7XG4gIGZvciAoaSQgPSAwLCBsZW4kID0geHMubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICB4ID0geHNbaSRdO1xuICAgIGlmICgheCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn07XG5vckxpc3QgPSBmdW5jdGlvbih4cyl7XG4gIHZhciBpJCwgbGVuJCwgeDtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgaWYgKHgpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmFsc2U7XG59O1xuYW55ID0gY3VycnkkKGZ1bmN0aW9uKGYsIHhzKXtcbiAgdmFyIGkkLCBsZW4kLCB4O1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHhzW2kkXTtcbiAgICBpZiAoZih4KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn0pO1xuYWxsID0gY3VycnkkKGZ1bmN0aW9uKGYsIHhzKXtcbiAgdmFyIGkkLCBsZW4kLCB4O1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHhzW2kkXTtcbiAgICBpZiAoIWYoeCkpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHRydWU7XG59KTtcbnNvcnQgPSBmdW5jdGlvbih4cyl7XG4gIHJldHVybiB4cy5jb25jYXQoKS5zb3J0KGZ1bmN0aW9uKHgsIHkpe1xuICAgIGlmICh4ID4geSkge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfSBlbHNlIGlmICh4IDwgeSkge1xuICAgICAgcmV0dXJuIC0xO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xufTtcbnNvcnRXaXRoID0gY3VycnkkKGZ1bmN0aW9uKGYsIHhzKXtcbiAgcmV0dXJuIHhzLmNvbmNhdCgpLnNvcnQoZik7XG59KTtcbnNvcnRCeSA9IGN1cnJ5JChmdW5jdGlvbihmLCB4cyl7XG4gIHJldHVybiB4cy5jb25jYXQoKS5zb3J0KGZ1bmN0aW9uKHgsIHkpe1xuICAgIGlmIChmKHgpID4gZih5KSkge1xuICAgICAgcmV0dXJuIDE7XG4gICAgfSBlbHNlIGlmIChmKHgpIDwgZih5KSkge1xuICAgICAgcmV0dXJuIC0xO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG4gIH0pO1xufSk7XG5zdW0gPSBmdW5jdGlvbih4cyl7XG4gIHZhciByZXN1bHQsIGkkLCBsZW4kLCB4O1xuICByZXN1bHQgPSAwO1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHhzW2kkXTtcbiAgICByZXN1bHQgKz0geDtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcbnByb2R1Y3QgPSBmdW5jdGlvbih4cyl7XG4gIHZhciByZXN1bHQsIGkkLCBsZW4kLCB4O1xuICByZXN1bHQgPSAxO1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHhzW2kkXTtcbiAgICByZXN1bHQgKj0geDtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcbm1lYW4gPSBhdmVyYWdlID0gZnVuY3Rpb24oeHMpe1xuICB2YXIgc3VtLCBpJCwgbGVuJCwgeDtcbiAgc3VtID0gMDtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSB4c1tpJF07XG4gICAgc3VtICs9IHg7XG4gIH1cbiAgcmV0dXJuIHN1bSAvIHhzLmxlbmd0aDtcbn07XG5tYXhpbXVtID0gZnVuY3Rpb24oeHMpe1xuICB2YXIgbWF4LCBpJCwgcmVmJCwgbGVuJCwgeDtcbiAgbWF4ID0geHNbMF07XG4gIGZvciAoaSQgPSAwLCBsZW4kID0gKHJlZiQgPSB4cy5zbGljZSgxKSkubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICB4ID0gcmVmJFtpJF07XG4gICAgaWYgKHggPiBtYXgpIHtcbiAgICAgIG1heCA9IHg7XG4gICAgfVxuICB9XG4gIHJldHVybiBtYXg7XG59O1xubWluaW11bSA9IGZ1bmN0aW9uKHhzKXtcbiAgdmFyIG1pbiwgaSQsIHJlZiQsIGxlbiQsIHg7XG4gIG1pbiA9IHhzWzBdO1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IChyZWYkID0geHMuc2xpY2UoMSkpLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHJlZiRbaSRdO1xuICAgIGlmICh4IDwgbWluKSB7XG4gICAgICBtaW4gPSB4O1xuICAgIH1cbiAgfVxuICByZXR1cm4gbWluO1xufTtcbm1heGltdW1CeSA9IGN1cnJ5JChmdW5jdGlvbihmLCB4cyl7XG4gIHZhciBtYXgsIGkkLCByZWYkLCBsZW4kLCB4O1xuICBtYXggPSB4c1swXTtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSAocmVmJCA9IHhzLnNsaWNlKDEpKS5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIHggPSByZWYkW2kkXTtcbiAgICBpZiAoZih4KSA+IGYobWF4KSkge1xuICAgICAgbWF4ID0geDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG1heDtcbn0pO1xubWluaW11bUJ5ID0gY3VycnkkKGZ1bmN0aW9uKGYsIHhzKXtcbiAgdmFyIG1pbiwgaSQsIHJlZiQsIGxlbiQsIHg7XG4gIG1pbiA9IHhzWzBdO1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IChyZWYkID0geHMuc2xpY2UoMSkpLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeCA9IHJlZiRbaSRdO1xuICAgIGlmIChmKHgpIDwgZihtaW4pKSB7XG4gICAgICBtaW4gPSB4O1xuICAgIH1cbiAgfVxuICByZXR1cm4gbWluO1xufSk7XG5zY2FuID0gc2NhbmwgPSBjdXJyeSQoZnVuY3Rpb24oZiwgbWVtbywgeHMpe1xuICB2YXIgbGFzdCwgeDtcbiAgbGFzdCA9IG1lbW87XG4gIHJldHVybiBbbWVtb10uY29uY2F0KChmdW5jdGlvbigpe1xuICAgIHZhciBpJCwgcmVmJCwgbGVuJCwgcmVzdWx0cyQgPSBbXTtcbiAgICBmb3IgKGkkID0gMCwgbGVuJCA9IChyZWYkID0geHMpLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgICB4ID0gcmVmJFtpJF07XG4gICAgICByZXN1bHRzJC5wdXNoKGxhc3QgPSBmKGxhc3QsIHgpKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdHMkO1xuICB9KCkpKTtcbn0pO1xuc2NhbjEgPSBzY2FubDEgPSBjdXJyeSQoZnVuY3Rpb24oZiwgeHMpe1xuICBpZiAoIXhzLmxlbmd0aCkge1xuICAgIHJldHVybjtcbiAgfVxuICByZXR1cm4gc2NhbihmLCB4c1swXSwgeHMuc2xpY2UoMSkpO1xufSk7XG5zY2FuciA9IGN1cnJ5JChmdW5jdGlvbihmLCBtZW1vLCB4cyl7XG4gIHhzID0geHMuY29uY2F0KCkucmV2ZXJzZSgpO1xuICByZXR1cm4gc2NhbihmLCBtZW1vLCB4cykucmV2ZXJzZSgpO1xufSk7XG5zY2FucjEgPSBjdXJyeSQoZnVuY3Rpb24oZiwgeHMpe1xuICBpZiAoIXhzLmxlbmd0aCkge1xuICAgIHJldHVybjtcbiAgfVxuICB4cyA9IHhzLmNvbmNhdCgpLnJldmVyc2UoKTtcbiAgcmV0dXJuIHNjYW4oZiwgeHNbMF0sIHhzLnNsaWNlKDEpKS5yZXZlcnNlKCk7XG59KTtcbnNsaWNlID0gY3VycnkkKGZ1bmN0aW9uKHgsIHksIHhzKXtcbiAgcmV0dXJuIHhzLnNsaWNlKHgsIHkpO1xufSk7XG50YWtlID0gY3VycnkkKGZ1bmN0aW9uKG4sIHhzKXtcbiAgaWYgKG4gPD0gMCkge1xuICAgIHJldHVybiB4cy5zbGljZSgwLCAwKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4geHMuc2xpY2UoMCwgbik7XG4gIH1cbn0pO1xuZHJvcCA9IGN1cnJ5JChmdW5jdGlvbihuLCB4cyl7XG4gIGlmIChuIDw9IDApIHtcbiAgICByZXR1cm4geHM7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHhzLnNsaWNlKG4pO1xuICB9XG59KTtcbnNwbGl0QXQgPSBjdXJyeSQoZnVuY3Rpb24obiwgeHMpe1xuICByZXR1cm4gW3Rha2UobiwgeHMpLCBkcm9wKG4sIHhzKV07XG59KTtcbnRha2VXaGlsZSA9IGN1cnJ5JChmdW5jdGlvbihwLCB4cyl7XG4gIHZhciBsZW4sIGk7XG4gIGxlbiA9IHhzLmxlbmd0aDtcbiAgaWYgKCFsZW4pIHtcbiAgICByZXR1cm4geHM7XG4gIH1cbiAgaSA9IDA7XG4gIHdoaWxlIChpIDwgbGVuICYmIHAoeHNbaV0pKSB7XG4gICAgaSArPSAxO1xuICB9XG4gIHJldHVybiB4cy5zbGljZSgwLCBpKTtcbn0pO1xuZHJvcFdoaWxlID0gY3VycnkkKGZ1bmN0aW9uKHAsIHhzKXtcbiAgdmFyIGxlbiwgaTtcbiAgbGVuID0geHMubGVuZ3RoO1xuICBpZiAoIWxlbikge1xuICAgIHJldHVybiB4cztcbiAgfVxuICBpID0gMDtcbiAgd2hpbGUgKGkgPCBsZW4gJiYgcCh4c1tpXSkpIHtcbiAgICBpICs9IDE7XG4gIH1cbiAgcmV0dXJuIHhzLnNsaWNlKGkpO1xufSk7XG5zcGFuID0gY3VycnkkKGZ1bmN0aW9uKHAsIHhzKXtcbiAgcmV0dXJuIFt0YWtlV2hpbGUocCwgeHMpLCBkcm9wV2hpbGUocCwgeHMpXTtcbn0pO1xuYnJlYWtMaXN0ID0gY3VycnkkKGZ1bmN0aW9uKHAsIHhzKXtcbiAgcmV0dXJuIHNwYW4oY29tcG9zZSQocCwgbm90JCksIHhzKTtcbn0pO1xuemlwID0gY3VycnkkKGZ1bmN0aW9uKHhzLCB5cyl7XG4gIHZhciByZXN1bHQsIGxlbiwgaSQsIGxlbiQsIGksIHg7XG4gIHJlc3VsdCA9IFtdO1xuICBsZW4gPSB5cy5sZW5ndGg7XG4gIGZvciAoaSQgPSAwLCBsZW4kID0geHMubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICBpID0gaSQ7XG4gICAgeCA9IHhzW2kkXTtcbiAgICBpZiAoaSA9PT0gbGVuKSB7XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgcmVzdWx0LnB1c2goW3gsIHlzW2ldXSk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuemlwV2l0aCA9IGN1cnJ5JChmdW5jdGlvbihmLCB4cywgeXMpe1xuICB2YXIgcmVzdWx0LCBsZW4sIGkkLCBsZW4kLCBpLCB4O1xuICByZXN1bHQgPSBbXTtcbiAgbGVuID0geXMubGVuZ3RoO1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgaSA9IGkkO1xuICAgIHggPSB4c1tpJF07XG4gICAgaWYgKGkgPT09IGxlbikge1xuICAgICAgYnJlYWs7XG4gICAgfVxuICAgIHJlc3VsdC5wdXNoKGYoeCwgeXNbaV0pKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufSk7XG56aXBBbGwgPSBmdW5jdGlvbigpe1xuICB2YXIgeHNzLCByZXMkLCBpJCwgdG8kLCBtaW5MZW5ndGgsIGxlbiQsIHhzLCByZWYkLCBpLCBscmVzdWx0JCwgaiQsIHJlc3VsdHMkID0gW107XG4gIHJlcyQgPSBbXTtcbiAgZm9yIChpJCA9IDAsIHRvJCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkkIDwgdG8kOyArK2kkKSB7XG4gICAgcmVzJC5wdXNoKGFyZ3VtZW50c1tpJF0pO1xuICB9XG4gIHhzcyA9IHJlcyQ7XG4gIG1pbkxlbmd0aCA9IHVuZGVmaW5lZDtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4c3MubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICB4cyA9IHhzc1tpJF07XG4gICAgbWluTGVuZ3RoIDw9IChyZWYkID0geHMubGVuZ3RoKSB8fCAobWluTGVuZ3RoID0gcmVmJCk7XG4gIH1cbiAgZm9yIChpJCA9IDA7IGkkIDwgbWluTGVuZ3RoOyArK2kkKSB7XG4gICAgaSA9IGkkO1xuICAgIGxyZXN1bHQkID0gW107XG4gICAgZm9yIChqJCA9IDAsIGxlbiQgPSB4c3MubGVuZ3RoOyBqJCA8IGxlbiQ7ICsraiQpIHtcbiAgICAgIHhzID0geHNzW2okXTtcbiAgICAgIGxyZXN1bHQkLnB1c2goeHNbaV0pO1xuICAgIH1cbiAgICByZXN1bHRzJC5wdXNoKGxyZXN1bHQkKTtcbiAgfVxuICByZXR1cm4gcmVzdWx0cyQ7XG59O1xuemlwQWxsV2l0aCA9IGZ1bmN0aW9uKGYpe1xuICB2YXIgeHNzLCByZXMkLCBpJCwgdG8kLCBtaW5MZW5ndGgsIGxlbiQsIHhzLCByZWYkLCBpLCByZXN1bHRzJCA9IFtdO1xuICByZXMkID0gW107XG4gIGZvciAoaSQgPSAxLCB0byQgPSBhcmd1bWVudHMubGVuZ3RoOyBpJCA8IHRvJDsgKytpJCkge1xuICAgIHJlcyQucHVzaChhcmd1bWVudHNbaSRdKTtcbiAgfVxuICB4c3MgPSByZXMkO1xuICBtaW5MZW5ndGggPSB1bmRlZmluZWQ7XG4gIGZvciAoaSQgPSAwLCBsZW4kID0geHNzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgeHMgPSB4c3NbaSRdO1xuICAgIG1pbkxlbmd0aCA8PSAocmVmJCA9IHhzLmxlbmd0aCkgfHwgKG1pbkxlbmd0aCA9IHJlZiQpO1xuICB9XG4gIGZvciAoaSQgPSAwOyBpJCA8IG1pbkxlbmd0aDsgKytpJCkge1xuICAgIGkgPSBpJDtcbiAgICByZXN1bHRzJC5wdXNoKGYuYXBwbHkobnVsbCwgKGZuJCgpKSkpO1xuICB9XG4gIHJldHVybiByZXN1bHRzJDtcbiAgZnVuY3Rpb24gZm4kKCl7XG4gICAgdmFyIGkkLCByZWYkLCBsZW4kLCByZXN1bHRzJCA9IFtdO1xuICAgIGZvciAoaSQgPSAwLCBsZW4kID0gKHJlZiQgPSB4c3MpLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgICB4cyA9IHJlZiRbaSRdO1xuICAgICAgcmVzdWx0cyQucHVzaCh4c1tpXSk7XG4gICAgfVxuICAgIHJldHVybiByZXN1bHRzJDtcbiAgfVxufTtcbmF0ID0gY3VycnkkKGZ1bmN0aW9uKG4sIHhzKXtcbiAgaWYgKG4gPCAwKSB7XG4gICAgcmV0dXJuIHhzW3hzLmxlbmd0aCArIG5dO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB4c1tuXTtcbiAgfVxufSk7XG5lbGVtSW5kZXggPSBjdXJyeSQoZnVuY3Rpb24oZWwsIHhzKXtcbiAgdmFyIGkkLCBsZW4kLCBpLCB4O1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgaSA9IGkkO1xuICAgIHggPSB4c1tpJF07XG4gICAgaWYgKHggPT09IGVsKSB7XG4gICAgICByZXR1cm4gaTtcbiAgICB9XG4gIH1cbn0pO1xuZWxlbUluZGljZXMgPSBjdXJyeSQoZnVuY3Rpb24oZWwsIHhzKXtcbiAgdmFyIGkkLCBsZW4kLCBpLCB4LCByZXN1bHRzJCA9IFtdO1xuICBmb3IgKGkkID0gMCwgbGVuJCA9IHhzLmxlbmd0aDsgaSQgPCBsZW4kOyArK2kkKSB7XG4gICAgaSA9IGkkO1xuICAgIHggPSB4c1tpJF07XG4gICAgaWYgKHggPT09IGVsKSB7XG4gICAgICByZXN1bHRzJC5wdXNoKGkpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0cyQ7XG59KTtcbmZpbmRJbmRleCA9IGN1cnJ5JChmdW5jdGlvbihmLCB4cyl7XG4gIHZhciBpJCwgbGVuJCwgaSwgeDtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSB4cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIGkgPSBpJDtcbiAgICB4ID0geHNbaSRdO1xuICAgIGlmIChmKHgpKSB7XG4gICAgICByZXR1cm4gaTtcbiAgICB9XG4gIH1cbn0pO1xuZmluZEluZGljZXMgPSBjdXJyeSQoZnVuY3Rpb24oZiwgeHMpe1xuICB2YXIgaSQsIGxlbiQsIGksIHgsIHJlc3VsdHMkID0gW107XG4gIGZvciAoaSQgPSAwLCBsZW4kID0geHMubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICBpID0gaSQ7XG4gICAgeCA9IHhzW2kkXTtcbiAgICBpZiAoZih4KSkge1xuICAgICAgcmVzdWx0cyQucHVzaChpKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdHMkO1xufSk7XG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgZWFjaDogZWFjaCxcbiAgbWFwOiBtYXAsXG4gIGZpbHRlcjogZmlsdGVyLFxuICBjb21wYWN0OiBjb21wYWN0LFxuICByZWplY3Q6IHJlamVjdCxcbiAgcmVtb3ZlOiByZW1vdmUsXG4gIHBhcnRpdGlvbjogcGFydGl0aW9uLFxuICBmaW5kOiBmaW5kLFxuICBoZWFkOiBoZWFkLFxuICBmaXJzdDogZmlyc3QsXG4gIHRhaWw6IHRhaWwsXG4gIGxhc3Q6IGxhc3QsXG4gIGluaXRpYWw6IGluaXRpYWwsXG4gIGVtcHR5OiBlbXB0eSxcbiAgcmV2ZXJzZTogcmV2ZXJzZSxcbiAgZGlmZmVyZW5jZTogZGlmZmVyZW5jZSxcbiAgaW50ZXJzZWN0aW9uOiBpbnRlcnNlY3Rpb24sXG4gIHVuaW9uOiB1bmlvbixcbiAgY291bnRCeTogY291bnRCeSxcbiAgZ3JvdXBCeTogZ3JvdXBCeSxcbiAgZm9sZDogZm9sZCxcbiAgZm9sZDE6IGZvbGQxLFxuICBmb2xkbDogZm9sZGwsXG4gIGZvbGRsMTogZm9sZGwxLFxuICBmb2xkcjogZm9sZHIsXG4gIGZvbGRyMTogZm9sZHIxLFxuICB1bmZvbGRyOiB1bmZvbGRyLFxuICBhbmRMaXN0OiBhbmRMaXN0LFxuICBvckxpc3Q6IG9yTGlzdCxcbiAgYW55OiBhbnksXG4gIGFsbDogYWxsLFxuICB1bmlxdWU6IHVuaXF1ZSxcbiAgdW5pcXVlQnk6IHVuaXF1ZUJ5LFxuICBzb3J0OiBzb3J0LFxuICBzb3J0V2l0aDogc29ydFdpdGgsXG4gIHNvcnRCeTogc29ydEJ5LFxuICBzdW06IHN1bSxcbiAgcHJvZHVjdDogcHJvZHVjdCxcbiAgbWVhbjogbWVhbixcbiAgYXZlcmFnZTogYXZlcmFnZSxcbiAgY29uY2F0OiBjb25jYXQsXG4gIGNvbmNhdE1hcDogY29uY2F0TWFwLFxuICBmbGF0dGVuOiBmbGF0dGVuLFxuICBtYXhpbXVtOiBtYXhpbXVtLFxuICBtaW5pbXVtOiBtaW5pbXVtLFxuICBtYXhpbXVtQnk6IG1heGltdW1CeSxcbiAgbWluaW11bUJ5OiBtaW5pbXVtQnksXG4gIHNjYW46IHNjYW4sXG4gIHNjYW4xOiBzY2FuMSxcbiAgc2Nhbmw6IHNjYW5sLFxuICBzY2FubDE6IHNjYW5sMSxcbiAgc2NhbnI6IHNjYW5yLFxuICBzY2FucjE6IHNjYW5yMSxcbiAgc2xpY2U6IHNsaWNlLFxuICB0YWtlOiB0YWtlLFxuICBkcm9wOiBkcm9wLFxuICBzcGxpdEF0OiBzcGxpdEF0LFxuICB0YWtlV2hpbGU6IHRha2VXaGlsZSxcbiAgZHJvcFdoaWxlOiBkcm9wV2hpbGUsXG4gIHNwYW46IHNwYW4sXG4gIGJyZWFrTGlzdDogYnJlYWtMaXN0LFxuICB6aXA6IHppcCxcbiAgemlwV2l0aDogemlwV2l0aCxcbiAgemlwQWxsOiB6aXBBbGwsXG4gIHppcEFsbFdpdGg6IHppcEFsbFdpdGgsXG4gIGF0OiBhdCxcbiAgZWxlbUluZGV4OiBlbGVtSW5kZXgsXG4gIGVsZW1JbmRpY2VzOiBlbGVtSW5kaWNlcyxcbiAgZmluZEluZGV4OiBmaW5kSW5kZXgsXG4gIGZpbmRJbmRpY2VzOiBmaW5kSW5kaWNlc1xufTtcbmZ1bmN0aW9uIGN1cnJ5JChmLCBib3VuZCl7XG4gIHZhciBjb250ZXh0LFxuICBfY3VycnkgPSBmdW5jdGlvbihhcmdzKSB7XG4gICAgcmV0dXJuIGYubGVuZ3RoID4gMSA/IGZ1bmN0aW9uKCl7XG4gICAgICB2YXIgcGFyYW1zID0gYXJncyA/IGFyZ3MuY29uY2F0KCkgOiBbXTtcbiAgICAgIGNvbnRleHQgPSBib3VuZCA/IGNvbnRleHQgfHwgdGhpcyA6IHRoaXM7XG4gICAgICByZXR1cm4gcGFyYW1zLnB1c2guYXBwbHkocGFyYW1zLCBhcmd1bWVudHMpIDxcbiAgICAgICAgICBmLmxlbmd0aCAmJiBhcmd1bWVudHMubGVuZ3RoID9cbiAgICAgICAgX2N1cnJ5LmNhbGwoY29udGV4dCwgcGFyYW1zKSA6IGYuYXBwbHkoY29udGV4dCwgcGFyYW1zKTtcbiAgICB9IDogZjtcbiAgfTtcbiAgcmV0dXJuIF9jdXJyeSgpO1xufVxuZnVuY3Rpb24gaW4kKHgsIHhzKXtcbiAgdmFyIGkgPSAtMSwgbCA9IHhzLmxlbmd0aCA+Pj4gMDtcbiAgd2hpbGUgKCsraSA8IGwpIGlmICh4ID09PSB4c1tpXSkgcmV0dXJuIHRydWU7XG4gIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGNvbXBvc2UkKCkge1xuICB2YXIgZnVuY3Rpb25zID0gYXJndW1lbnRzO1xuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgdmFyIGksIHJlc3VsdDtcbiAgICByZXN1bHQgPSBmdW5jdGlvbnNbMF0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICBmb3IgKGkgPSAxOyBpIDwgZnVuY3Rpb25zLmxlbmd0aDsgKytpKSB7XG4gICAgICByZXN1bHQgPSBmdW5jdGlvbnNbaV0ocmVzdWx0KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfTtcbn1cbmZ1bmN0aW9uIG5vdCQoeCl7IHJldHVybiAheDsgfSIsIi8vIEdlbmVyYXRlZCBieSBMaXZlU2NyaXB0IDEuNi4wXG52YXIgdmFsdWVzLCBrZXlzLCBwYWlyc1RvT2JqLCBvYmpUb1BhaXJzLCBsaXN0c1RvT2JqLCBvYmpUb0xpc3RzLCBlbXB0eSwgZWFjaCwgbWFwLCBjb21wYWN0LCBmaWx0ZXIsIHJlamVjdCwgcGFydGl0aW9uLCBmaW5kO1xudmFsdWVzID0gZnVuY3Rpb24ob2JqZWN0KXtcbiAgdmFyIGkkLCB4LCByZXN1bHRzJCA9IFtdO1xuICBmb3IgKGkkIGluIG9iamVjdCkge1xuICAgIHggPSBvYmplY3RbaSRdO1xuICAgIHJlc3VsdHMkLnB1c2goeCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdHMkO1xufTtcbmtleXMgPSBmdW5jdGlvbihvYmplY3Qpe1xuICB2YXIgeCwgcmVzdWx0cyQgPSBbXTtcbiAgZm9yICh4IGluIG9iamVjdCkge1xuICAgIHJlc3VsdHMkLnB1c2goeCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdHMkO1xufTtcbnBhaXJzVG9PYmogPSBmdW5jdGlvbihvYmplY3Qpe1xuICB2YXIgaSQsIGxlbiQsIHgsIHJlc3VsdE9iaiQgPSB7fTtcbiAgZm9yIChpJCA9IDAsIGxlbiQgPSBvYmplY3QubGVuZ3RoOyBpJCA8IGxlbiQ7ICsraSQpIHtcbiAgICB4ID0gb2JqZWN0W2kkXTtcbiAgICByZXN1bHRPYmokW3hbMF1dID0geFsxXTtcbiAgfVxuICByZXR1cm4gcmVzdWx0T2JqJDtcbn07XG5vYmpUb1BhaXJzID0gZnVuY3Rpb24ob2JqZWN0KXtcbiAgdmFyIGtleSwgdmFsdWUsIHJlc3VsdHMkID0gW107XG4gIGZvciAoa2V5IGluIG9iamVjdCkge1xuICAgIHZhbHVlID0gb2JqZWN0W2tleV07XG4gICAgcmVzdWx0cyQucHVzaChba2V5LCB2YWx1ZV0pO1xuICB9XG4gIHJldHVybiByZXN1bHRzJDtcbn07XG5saXN0c1RvT2JqID0gY3VycnkkKGZ1bmN0aW9uKGtleXMsIHZhbHVlcyl7XG4gIHZhciBpJCwgbGVuJCwgaSwga2V5LCByZXN1bHRPYmokID0ge307XG4gIGZvciAoaSQgPSAwLCBsZW4kID0ga2V5cy5sZW5ndGg7IGkkIDwgbGVuJDsgKytpJCkge1xuICAgIGkgPSBpJDtcbiAgICBrZXkgPSBrZXlzW2kkXTtcbiAgICByZXN1bHRPYmokW2tleV0gPSB2YWx1ZXNbaV07XG4gIH1cbiAgcmV0dXJuIHJlc3VsdE9iaiQ7XG59KTtcbm9ialRvTGlzdHMgPSBmdW5jdGlvbihvYmplY3Qpe1xuICB2YXIga2V5cywgdmFsdWVzLCBrZXksIHZhbHVlO1xuICBrZXlzID0gW107XG4gIHZhbHVlcyA9IFtdO1xuICBmb3IgKGtleSBpbiBvYmplY3QpIHtcbiAgICB2YWx1ZSA9IG9iamVjdFtrZXldO1xuICAgIGtleXMucHVzaChrZXkpO1xuICAgIHZhbHVlcy5wdXNoKHZhbHVlKTtcbiAgfVxuICByZXR1cm4gW2tleXMsIHZhbHVlc107XG59O1xuZW1wdHkgPSBmdW5jdGlvbihvYmplY3Qpe1xuICB2YXIgeDtcbiAgZm9yICh4IGluIG9iamVjdCkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHJ1ZTtcbn07XG5lYWNoID0gY3VycnkkKGZ1bmN0aW9uKGYsIG9iamVjdCl7XG4gIHZhciBpJCwgeDtcbiAgZm9yIChpJCBpbiBvYmplY3QpIHtcbiAgICB4ID0gb2JqZWN0W2kkXTtcbiAgICBmKHgpO1xuICB9XG4gIHJldHVybiBvYmplY3Q7XG59KTtcbm1hcCA9IGN1cnJ5JChmdW5jdGlvbihmLCBvYmplY3Qpe1xuICB2YXIgaywgeCwgcmVzdWx0T2JqJCA9IHt9O1xuICBmb3IgKGsgaW4gb2JqZWN0KSB7XG4gICAgeCA9IG9iamVjdFtrXTtcbiAgICByZXN1bHRPYmokW2tdID0gZih4KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0T2JqJDtcbn0pO1xuY29tcGFjdCA9IGZ1bmN0aW9uKG9iamVjdCl7XG4gIHZhciBrLCB4LCByZXN1bHRPYmokID0ge307XG4gIGZvciAoayBpbiBvYmplY3QpIHtcbiAgICB4ID0gb2JqZWN0W2tdO1xuICAgIGlmICh4KSB7XG4gICAgICByZXN1bHRPYmokW2tdID0geDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdE9iaiQ7XG59O1xuZmlsdGVyID0gY3VycnkkKGZ1bmN0aW9uKGYsIG9iamVjdCl7XG4gIHZhciBrLCB4LCByZXN1bHRPYmokID0ge307XG4gIGZvciAoayBpbiBvYmplY3QpIHtcbiAgICB4ID0gb2JqZWN0W2tdO1xuICAgIGlmIChmKHgpKSB7XG4gICAgICByZXN1bHRPYmokW2tdID0geDtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJlc3VsdE9iaiQ7XG59KTtcbnJlamVjdCA9IGN1cnJ5JChmdW5jdGlvbihmLCBvYmplY3Qpe1xuICB2YXIgaywgeCwgcmVzdWx0T2JqJCA9IHt9O1xuICBmb3IgKGsgaW4gb2JqZWN0KSB7XG4gICAgeCA9IG9iamVjdFtrXTtcbiAgICBpZiAoIWYoeCkpIHtcbiAgICAgIHJlc3VsdE9iaiRba10gPSB4O1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmVzdWx0T2JqJDtcbn0pO1xucGFydGl0aW9uID0gY3VycnkkKGZ1bmN0aW9uKGYsIG9iamVjdCl7XG4gIHZhciBwYXNzZWQsIGZhaWxlZCwgaywgeDtcbiAgcGFzc2VkID0ge307XG4gIGZhaWxlZCA9IHt9O1xuICBmb3IgKGsgaW4gb2JqZWN0KSB7XG4gICAgeCA9IG9iamVjdFtrXTtcbiAgICAoZih4KSA/IHBhc3NlZCA6IGZhaWxlZClba10gPSB4O1xuICB9XG4gIHJldHVybiBbcGFzc2VkLCBmYWlsZWRdO1xufSk7XG5maW5kID0gY3VycnkkKGZ1bmN0aW9uKGYsIG9iamVjdCl7XG4gIHZhciBpJCwgeDtcbiAgZm9yIChpJCBpbiBvYmplY3QpIHtcbiAgICB4ID0gb2JqZWN0W2kkXTtcbiAgICBpZiAoZih4KSkge1xuICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICB9XG59KTtcbm1vZHVsZS5leHBvcnRzID0ge1xuICB2YWx1ZXM6IHZhbHVlcyxcbiAga2V5czoga2V5cyxcbiAgcGFpcnNUb09iajogcGFpcnNUb09iaixcbiAgb2JqVG9QYWlyczogb2JqVG9QYWlycyxcbiAgbGlzdHNUb09iajogbGlzdHNUb09iaixcbiAgb2JqVG9MaXN0czogb2JqVG9MaXN0cyxcbiAgZW1wdHk6IGVtcHR5LFxuICBlYWNoOiBlYWNoLFxuICBtYXA6IG1hcCxcbiAgZmlsdGVyOiBmaWx0ZXIsXG4gIGNvbXBhY3Q6IGNvbXBhY3QsXG4gIHJlamVjdDogcmVqZWN0LFxuICBwYXJ0aXRpb246IHBhcnRpdGlvbixcbiAgZmluZDogZmluZFxufTtcbmZ1bmN0aW9uIGN1cnJ5JChmLCBib3VuZCl7XG4gIHZhciBjb250ZXh0LFxuICBfY3VycnkgPSBmdW5jdGlvbihhcmdzKSB7XG4gICAgcmV0dXJuIGYubGVuZ3RoID4gMSA/IGZ1bmN0aW9uKCl7XG4gICAgICB2YXIgcGFyYW1zID0gYXJncyA/IGFyZ3MuY29uY2F0KCkgOiBbXTtcbiAgICAgIGNvbnRleHQgPSBib3VuZCA/IGNvbnRleHQgfHwgdGhpcyA6IHRoaXM7XG4gICAgICByZXR1cm4gcGFyYW1zLnB1c2guYXBwbHkocGFyYW1zLCBhcmd1bWVudHMpIDxcbiAgICAgICAgICBmLmxlbmd0aCAmJiBhcmd1bWVudHMubGVuZ3RoID9cbiAgICAgICAgX2N1cnJ5LmNhbGwoY29udGV4dCwgcGFyYW1zKSA6IGYuYXBwbHkoY29udGV4dCwgcGFyYW1zKTtcbiAgICB9IDogZjtcbiAgfTtcbiAgcmV0dXJuIF9jdXJyeSgpO1xufSIsIi8vIEdlbmVyYXRlZCBieSBMaXZlU2NyaXB0IDEuNi4wXG52YXIgc3BsaXQsIGpvaW4sIGxpbmVzLCB1bmxpbmVzLCB3b3JkcywgdW53b3JkcywgY2hhcnMsIHVuY2hhcnMsIHJldmVyc2UsIHJlcGVhdCwgY2FwaXRhbGl6ZSwgY2FtZWxpemUsIGRhc2hlcml6ZTtcbnNwbGl0ID0gY3VycnkkKGZ1bmN0aW9uKHNlcCwgc3RyKXtcbiAgcmV0dXJuIHN0ci5zcGxpdChzZXApO1xufSk7XG5qb2luID0gY3VycnkkKGZ1bmN0aW9uKHNlcCwgeHMpe1xuICByZXR1cm4geHMuam9pbihzZXApO1xufSk7XG5saW5lcyA9IGZ1bmN0aW9uKHN0cil7XG4gIGlmICghc3RyLmxlbmd0aCkge1xuICAgIHJldHVybiBbXTtcbiAgfVxuICByZXR1cm4gc3RyLnNwbGl0KCdcXG4nKTtcbn07XG51bmxpbmVzID0gZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gaXQuam9pbignXFxuJyk7XG59O1xud29yZHMgPSBmdW5jdGlvbihzdHIpe1xuICBpZiAoIXN0ci5sZW5ndGgpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgcmV0dXJuIHN0ci5zcGxpdCgvWyBdKy8pO1xufTtcbnVud29yZHMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpdC5qb2luKCcgJyk7XG59O1xuY2hhcnMgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpdC5zcGxpdCgnJyk7XG59O1xudW5jaGFycyA9IGZ1bmN0aW9uKGl0KXtcbiAgcmV0dXJuIGl0LmpvaW4oJycpO1xufTtcbnJldmVyc2UgPSBmdW5jdGlvbihzdHIpe1xuICByZXR1cm4gc3RyLnNwbGl0KCcnKS5yZXZlcnNlKCkuam9pbignJyk7XG59O1xucmVwZWF0ID0gY3VycnkkKGZ1bmN0aW9uKG4sIHN0cil7XG4gIHZhciByZXN1bHQsIGkkO1xuICByZXN1bHQgPSAnJztcbiAgZm9yIChpJCA9IDA7IGkkIDwgbjsgKytpJCkge1xuICAgIHJlc3VsdCArPSBzdHI7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn0pO1xuY2FwaXRhbGl6ZSA9IGZ1bmN0aW9uKHN0cil7XG4gIHJldHVybiBzdHIuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBzdHIuc2xpY2UoMSk7XG59O1xuY2FtZWxpemUgPSBmdW5jdGlvbihpdCl7XG4gIHJldHVybiBpdC5yZXBsYWNlKC9bLV9dKyguKT8vZywgZnVuY3Rpb24oYXJnJCwgYyl7XG4gICAgcmV0dXJuIChjICE9IG51bGwgPyBjIDogJycpLnRvVXBwZXJDYXNlKCk7XG4gIH0pO1xufTtcbmRhc2hlcml6ZSA9IGZ1bmN0aW9uKHN0cil7XG4gIHJldHVybiBzdHIucmVwbGFjZSgvKFteLUEtWl0pKFtBLVpdKykvZywgZnVuY3Rpb24oYXJnJCwgbG93ZXIsIHVwcGVyKXtcbiAgICByZXR1cm4gbG93ZXIgKyBcIi1cIiArICh1cHBlci5sZW5ndGggPiAxXG4gICAgICA/IHVwcGVyXG4gICAgICA6IHVwcGVyLnRvTG93ZXJDYXNlKCkpO1xuICB9KS5yZXBsYWNlKC9eKFtBLVpdKykvLCBmdW5jdGlvbihhcmckLCB1cHBlcil7XG4gICAgaWYgKHVwcGVyLmxlbmd0aCA+IDEpIHtcbiAgICAgIHJldHVybiB1cHBlciArIFwiLVwiO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdXBwZXIudG9Mb3dlckNhc2UoKTtcbiAgICB9XG4gIH0pO1xufTtcbm1vZHVsZS5leHBvcnRzID0ge1xuICBzcGxpdDogc3BsaXQsXG4gIGpvaW46IGpvaW4sXG4gIGxpbmVzOiBsaW5lcyxcbiAgdW5saW5lczogdW5saW5lcyxcbiAgd29yZHM6IHdvcmRzLFxuICB1bndvcmRzOiB1bndvcmRzLFxuICBjaGFyczogY2hhcnMsXG4gIHVuY2hhcnM6IHVuY2hhcnMsXG4gIHJldmVyc2U6IHJldmVyc2UsXG4gIHJlcGVhdDogcmVwZWF0LFxuICBjYXBpdGFsaXplOiBjYXBpdGFsaXplLFxuICBjYW1lbGl6ZTogY2FtZWxpemUsXG4gIGRhc2hlcml6ZTogZGFzaGVyaXplXG59O1xuZnVuY3Rpb24gY3VycnkkKGYsIGJvdW5kKXtcbiAgdmFyIGNvbnRleHQsXG4gIF9jdXJyeSA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICByZXR1cm4gZi5sZW5ndGggPiAxID8gZnVuY3Rpb24oKXtcbiAgICAgIHZhciBwYXJhbXMgPSBhcmdzID8gYXJncy5jb25jYXQoKSA6IFtdO1xuICAgICAgY29udGV4dCA9IGJvdW5kID8gY29udGV4dCB8fCB0aGlzIDogdGhpcztcbiAgICAgIHJldHVybiBwYXJhbXMucHVzaC5hcHBseShwYXJhbXMsIGFyZ3VtZW50cykgPFxuICAgICAgICAgIGYubGVuZ3RoICYmIGFyZ3VtZW50cy5sZW5ndGggP1xuICAgICAgICBfY3VycnkuY2FsbChjb250ZXh0LCBwYXJhbXMpIDogZi5hcHBseShjb250ZXh0LCBwYXJhbXMpO1xuICAgIH0gOiBmO1xuICB9O1xuICByZXR1cm4gX2N1cnJ5KCk7XG59IiwiLy8gR2VuZXJhdGVkIGJ5IExpdmVTY3JpcHQgMS42LjBcbnZhciBtYXgsIG1pbiwgbmVnYXRlLCBhYnMsIHNpZ251bSwgcXVvdCwgcmVtLCBkaXYsIG1vZCwgcmVjaXAsIHBpLCB0YXUsIGV4cCwgc3FydCwgbG4sIHBvdywgc2luLCB0YW4sIGNvcywgYXNpbiwgYWNvcywgYXRhbiwgYXRhbjIsIHRydW5jYXRlLCByb3VuZCwgY2VpbGluZywgZmxvb3IsIGlzSXROYU4sIGV2ZW4sIG9kZCwgZ2NkLCBsY207XG5tYXggPSBjdXJyeSQoZnVuY3Rpb24oeCQsIHkkKXtcbiAgcmV0dXJuIHgkID4geSQgPyB4JCA6IHkkO1xufSk7XG5taW4gPSBjdXJyeSQoZnVuY3Rpb24oeCQsIHkkKXtcbiAgcmV0dXJuIHgkIDwgeSQgPyB4JCA6IHkkO1xufSk7XG5uZWdhdGUgPSBmdW5jdGlvbih4KXtcbiAgcmV0dXJuIC14O1xufTtcbmFicyA9IE1hdGguYWJzO1xuc2lnbnVtID0gZnVuY3Rpb24oeCl7XG4gIGlmICh4IDwgMCkge1xuICAgIHJldHVybiAtMTtcbiAgfSBlbHNlIGlmICh4ID4gMCkge1xuICAgIHJldHVybiAxO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiAwO1xuICB9XG59O1xucXVvdCA9IGN1cnJ5JChmdW5jdGlvbih4LCB5KXtcbiAgcmV0dXJuIH5+KHggLyB5KTtcbn0pO1xucmVtID0gY3VycnkkKGZ1bmN0aW9uKHgkLCB5JCl7XG4gIHJldHVybiB4JCAlIHkkO1xufSk7XG5kaXYgPSBjdXJyeSQoZnVuY3Rpb24oeCwgeSl7XG4gIHJldHVybiBNYXRoLmZsb29yKHggLyB5KTtcbn0pO1xubW9kID0gY3VycnkkKGZ1bmN0aW9uKHgkLCB5JCl7XG4gIHZhciByZWYkO1xuICByZXR1cm4gKCh4JCkgJSAocmVmJCA9IHkkKSArIHJlZiQpICUgcmVmJDtcbn0pO1xucmVjaXAgPSAoZnVuY3Rpb24oaXQpe1xuICByZXR1cm4gMSAvIGl0O1xufSk7XG5waSA9IE1hdGguUEk7XG50YXUgPSBwaSAqIDI7XG5leHAgPSBNYXRoLmV4cDtcbnNxcnQgPSBNYXRoLnNxcnQ7XG5sbiA9IE1hdGgubG9nO1xucG93ID0gY3VycnkkKGZ1bmN0aW9uKHgkLCB5JCl7XG4gIHJldHVybiBNYXRoLnBvdyh4JCwgeSQpO1xufSk7XG5zaW4gPSBNYXRoLnNpbjtcbnRhbiA9IE1hdGgudGFuO1xuY29zID0gTWF0aC5jb3M7XG5hc2luID0gTWF0aC5hc2luO1xuYWNvcyA9IE1hdGguYWNvcztcbmF0YW4gPSBNYXRoLmF0YW47XG5hdGFuMiA9IGN1cnJ5JChmdW5jdGlvbih4LCB5KXtcbiAgcmV0dXJuIE1hdGguYXRhbjIoeCwgeSk7XG59KTtcbnRydW5jYXRlID0gZnVuY3Rpb24oeCl7XG4gIHJldHVybiB+fng7XG59O1xucm91bmQgPSBNYXRoLnJvdW5kO1xuY2VpbGluZyA9IE1hdGguY2VpbDtcbmZsb29yID0gTWF0aC5mbG9vcjtcbmlzSXROYU4gPSBmdW5jdGlvbih4KXtcbiAgcmV0dXJuIHggIT09IHg7XG59O1xuZXZlbiA9IGZ1bmN0aW9uKHgpe1xuICByZXR1cm4geCAlIDIgPT09IDA7XG59O1xub2RkID0gZnVuY3Rpb24oeCl7XG4gIHJldHVybiB4ICUgMiAhPT0gMDtcbn07XG5nY2QgPSBjdXJyeSQoZnVuY3Rpb24oeCwgeSl7XG4gIHZhciB6O1xuICB4ID0gTWF0aC5hYnMoeCk7XG4gIHkgPSBNYXRoLmFicyh5KTtcbiAgd2hpbGUgKHkgIT09IDApIHtcbiAgICB6ID0geCAlIHk7XG4gICAgeCA9IHk7XG4gICAgeSA9IHo7XG4gIH1cbiAgcmV0dXJuIHg7XG59KTtcbmxjbSA9IGN1cnJ5JChmdW5jdGlvbih4LCB5KXtcbiAgcmV0dXJuIE1hdGguYWJzKE1hdGguZmxvb3IoeCAvIGdjZCh4LCB5KSAqIHkpKTtcbn0pO1xubW9kdWxlLmV4cG9ydHMgPSB7XG4gIG1heDogbWF4LFxuICBtaW46IG1pbixcbiAgbmVnYXRlOiBuZWdhdGUsXG4gIGFiczogYWJzLFxuICBzaWdudW06IHNpZ251bSxcbiAgcXVvdDogcXVvdCxcbiAgcmVtOiByZW0sXG4gIGRpdjogZGl2LFxuICBtb2Q6IG1vZCxcbiAgcmVjaXA6IHJlY2lwLFxuICBwaTogcGksXG4gIHRhdTogdGF1LFxuICBleHA6IGV4cCxcbiAgc3FydDogc3FydCxcbiAgbG46IGxuLFxuICBwb3c6IHBvdyxcbiAgc2luOiBzaW4sXG4gIHRhbjogdGFuLFxuICBjb3M6IGNvcyxcbiAgYWNvczogYWNvcyxcbiAgYXNpbjogYXNpbixcbiAgYXRhbjogYXRhbixcbiAgYXRhbjI6IGF0YW4yLFxuICB0cnVuY2F0ZTogdHJ1bmNhdGUsXG4gIHJvdW5kOiByb3VuZCxcbiAgY2VpbGluZzogY2VpbGluZyxcbiAgZmxvb3I6IGZsb29yLFxuICBpc0l0TmFOOiBpc0l0TmFOLFxuICBldmVuOiBldmVuLFxuICBvZGQ6IG9kZCxcbiAgZ2NkOiBnY2QsXG4gIGxjbTogbGNtXG59O1xuZnVuY3Rpb24gY3VycnkkKGYsIGJvdW5kKXtcbiAgdmFyIGNvbnRleHQsXG4gIF9jdXJyeSA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICByZXR1cm4gZi5sZW5ndGggPiAxID8gZnVuY3Rpb24oKXtcbiAgICAgIHZhciBwYXJhbXMgPSBhcmdzID8gYXJncy5jb25jYXQoKSA6IFtdO1xuICAgICAgY29udGV4dCA9IGJvdW5kID8gY29udGV4dCB8fCB0aGlzIDogdGhpcztcbiAgICAgIHJldHVybiBwYXJhbXMucHVzaC5hcHBseShwYXJhbXMsIGFyZ3VtZW50cykgPFxuICAgICAgICAgIGYubGVuZ3RoICYmIGFyZ3VtZW50cy5sZW5ndGggP1xuICAgICAgICBfY3VycnkuY2FsbChjb250ZXh0LCBwYXJhbXMpIDogZi5hcHBseShjb250ZXh0LCBwYXJhbXMpO1xuICAgIH0gOiBmO1xuICB9O1xuICByZXR1cm4gX2N1cnJ5KCk7XG59IiwiLy8gR2VuZXJhdGVkIGJ5IExpdmVTY3JpcHQgMS42LjBcbnZhciBGdW5jLCBMaXN0LCBPYmosIFN0ciwgTnVtLCBpZCwgaXNUeXBlLCByZXBsaWNhdGUsIHByZWx1ZGUsIHRvU3RyaW5nJCA9IHt9LnRvU3RyaW5nO1xuRnVuYyA9IHJlcXVpcmUoJy4vRnVuYy5qcycpO1xuTGlzdCA9IHJlcXVpcmUoJy4vTGlzdC5qcycpO1xuT2JqID0gcmVxdWlyZSgnLi9PYmouanMnKTtcblN0ciA9IHJlcXVpcmUoJy4vU3RyLmpzJyk7XG5OdW0gPSByZXF1aXJlKCcuL051bS5qcycpO1xuaWQgPSBmdW5jdGlvbih4KXtcbiAgcmV0dXJuIHg7XG59O1xuaXNUeXBlID0gY3VycnkkKGZ1bmN0aW9uKHR5cGUsIHgpe1xuICByZXR1cm4gdG9TdHJpbmckLmNhbGwoeCkuc2xpY2UoOCwgLTEpID09PSB0eXBlO1xufSk7XG5yZXBsaWNhdGUgPSBjdXJyeSQoZnVuY3Rpb24obiwgeCl7XG4gIHZhciBpJCwgcmVzdWx0cyQgPSBbXTtcbiAgZm9yIChpJCA9IDA7IGkkIDwgbjsgKytpJCkge1xuICAgIHJlc3VsdHMkLnB1c2goeCk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdHMkO1xufSk7XG5TdHIuZW1wdHkgPSBMaXN0LmVtcHR5O1xuU3RyLnNsaWNlID0gTGlzdC5zbGljZTtcblN0ci50YWtlID0gTGlzdC50YWtlO1xuU3RyLmRyb3AgPSBMaXN0LmRyb3A7XG5TdHIuc3BsaXRBdCA9IExpc3Quc3BsaXRBdDtcblN0ci50YWtlV2hpbGUgPSBMaXN0LnRha2VXaGlsZTtcblN0ci5kcm9wV2hpbGUgPSBMaXN0LmRyb3BXaGlsZTtcblN0ci5zcGFuID0gTGlzdC5zcGFuO1xuU3RyLmJyZWFrU3RyID0gTGlzdC5icmVha0xpc3Q7XG5wcmVsdWRlID0ge1xuICBGdW5jOiBGdW5jLFxuICBMaXN0OiBMaXN0LFxuICBPYmo6IE9iaixcbiAgU3RyOiBTdHIsXG4gIE51bTogTnVtLFxuICBpZDogaWQsXG4gIGlzVHlwZTogaXNUeXBlLFxuICByZXBsaWNhdGU6IHJlcGxpY2F0ZVxufTtcbnByZWx1ZGUuZWFjaCA9IExpc3QuZWFjaDtcbnByZWx1ZGUubWFwID0gTGlzdC5tYXA7XG5wcmVsdWRlLmZpbHRlciA9IExpc3QuZmlsdGVyO1xucHJlbHVkZS5jb21wYWN0ID0gTGlzdC5jb21wYWN0O1xucHJlbHVkZS5yZWplY3QgPSBMaXN0LnJlamVjdDtcbnByZWx1ZGUucGFydGl0aW9uID0gTGlzdC5wYXJ0aXRpb247XG5wcmVsdWRlLmZpbmQgPSBMaXN0LmZpbmQ7XG5wcmVsdWRlLmhlYWQgPSBMaXN0LmhlYWQ7XG5wcmVsdWRlLmZpcnN0ID0gTGlzdC5maXJzdDtcbnByZWx1ZGUudGFpbCA9IExpc3QudGFpbDtcbnByZWx1ZGUubGFzdCA9IExpc3QubGFzdDtcbnByZWx1ZGUuaW5pdGlhbCA9IExpc3QuaW5pdGlhbDtcbnByZWx1ZGUuZW1wdHkgPSBMaXN0LmVtcHR5O1xucHJlbHVkZS5yZXZlcnNlID0gTGlzdC5yZXZlcnNlO1xucHJlbHVkZS5kaWZmZXJlbmNlID0gTGlzdC5kaWZmZXJlbmNlO1xucHJlbHVkZS5pbnRlcnNlY3Rpb24gPSBMaXN0LmludGVyc2VjdGlvbjtcbnByZWx1ZGUudW5pb24gPSBMaXN0LnVuaW9uO1xucHJlbHVkZS5jb3VudEJ5ID0gTGlzdC5jb3VudEJ5O1xucHJlbHVkZS5ncm91cEJ5ID0gTGlzdC5ncm91cEJ5O1xucHJlbHVkZS5mb2xkID0gTGlzdC5mb2xkO1xucHJlbHVkZS5mb2xkbCA9IExpc3QuZm9sZGw7XG5wcmVsdWRlLmZvbGQxID0gTGlzdC5mb2xkMTtcbnByZWx1ZGUuZm9sZGwxID0gTGlzdC5mb2xkbDE7XG5wcmVsdWRlLmZvbGRyID0gTGlzdC5mb2xkcjtcbnByZWx1ZGUuZm9sZHIxID0gTGlzdC5mb2xkcjE7XG5wcmVsdWRlLnVuZm9sZHIgPSBMaXN0LnVuZm9sZHI7XG5wcmVsdWRlLmFuZExpc3QgPSBMaXN0LmFuZExpc3Q7XG5wcmVsdWRlLm9yTGlzdCA9IExpc3Qub3JMaXN0O1xucHJlbHVkZS5hbnkgPSBMaXN0LmFueTtcbnByZWx1ZGUuYWxsID0gTGlzdC5hbGw7XG5wcmVsdWRlLnVuaXF1ZSA9IExpc3QudW5pcXVlO1xucHJlbHVkZS51bmlxdWVCeSA9IExpc3QudW5pcXVlQnk7XG5wcmVsdWRlLnNvcnQgPSBMaXN0LnNvcnQ7XG5wcmVsdWRlLnNvcnRXaXRoID0gTGlzdC5zb3J0V2l0aDtcbnByZWx1ZGUuc29ydEJ5ID0gTGlzdC5zb3J0Qnk7XG5wcmVsdWRlLnN1bSA9IExpc3Quc3VtO1xucHJlbHVkZS5wcm9kdWN0ID0gTGlzdC5wcm9kdWN0O1xucHJlbHVkZS5tZWFuID0gTGlzdC5tZWFuO1xucHJlbHVkZS5hdmVyYWdlID0gTGlzdC5hdmVyYWdlO1xucHJlbHVkZS5jb25jYXQgPSBMaXN0LmNvbmNhdDtcbnByZWx1ZGUuY29uY2F0TWFwID0gTGlzdC5jb25jYXRNYXA7XG5wcmVsdWRlLmZsYXR0ZW4gPSBMaXN0LmZsYXR0ZW47XG5wcmVsdWRlLm1heGltdW0gPSBMaXN0Lm1heGltdW07XG5wcmVsdWRlLm1pbmltdW0gPSBMaXN0Lm1pbmltdW07XG5wcmVsdWRlLm1heGltdW1CeSA9IExpc3QubWF4aW11bUJ5O1xucHJlbHVkZS5taW5pbXVtQnkgPSBMaXN0Lm1pbmltdW1CeTtcbnByZWx1ZGUuc2NhbiA9IExpc3Quc2NhbjtcbnByZWx1ZGUuc2NhbmwgPSBMaXN0LnNjYW5sO1xucHJlbHVkZS5zY2FuMSA9IExpc3Quc2NhbjE7XG5wcmVsdWRlLnNjYW5sMSA9IExpc3Quc2NhbmwxO1xucHJlbHVkZS5zY2FuciA9IExpc3Quc2NhbnI7XG5wcmVsdWRlLnNjYW5yMSA9IExpc3Quc2NhbnIxO1xucHJlbHVkZS5zbGljZSA9IExpc3Quc2xpY2U7XG5wcmVsdWRlLnRha2UgPSBMaXN0LnRha2U7XG5wcmVsdWRlLmRyb3AgPSBMaXN0LmRyb3A7XG5wcmVsdWRlLnNwbGl0QXQgPSBMaXN0LnNwbGl0QXQ7XG5wcmVsdWRlLnRha2VXaGlsZSA9IExpc3QudGFrZVdoaWxlO1xucHJlbHVkZS5kcm9wV2hpbGUgPSBMaXN0LmRyb3BXaGlsZTtcbnByZWx1ZGUuc3BhbiA9IExpc3Quc3BhbjtcbnByZWx1ZGUuYnJlYWtMaXN0ID0gTGlzdC5icmVha0xpc3Q7XG5wcmVsdWRlLnppcCA9IExpc3QuemlwO1xucHJlbHVkZS56aXBXaXRoID0gTGlzdC56aXBXaXRoO1xucHJlbHVkZS56aXBBbGwgPSBMaXN0LnppcEFsbDtcbnByZWx1ZGUuemlwQWxsV2l0aCA9IExpc3QuemlwQWxsV2l0aDtcbnByZWx1ZGUuYXQgPSBMaXN0LmF0O1xucHJlbHVkZS5lbGVtSW5kZXggPSBMaXN0LmVsZW1JbmRleDtcbnByZWx1ZGUuZWxlbUluZGljZXMgPSBMaXN0LmVsZW1JbmRpY2VzO1xucHJlbHVkZS5maW5kSW5kZXggPSBMaXN0LmZpbmRJbmRleDtcbnByZWx1ZGUuZmluZEluZGljZXMgPSBMaXN0LmZpbmRJbmRpY2VzO1xucHJlbHVkZS5hcHBseSA9IEZ1bmMuYXBwbHk7XG5wcmVsdWRlLmN1cnJ5ID0gRnVuYy5jdXJyeTtcbnByZWx1ZGUuZmxpcCA9IEZ1bmMuZmxpcDtcbnByZWx1ZGUuZml4ID0gRnVuYy5maXg7XG5wcmVsdWRlLm92ZXIgPSBGdW5jLm92ZXI7XG5wcmVsdWRlLnNwbGl0ID0gU3RyLnNwbGl0O1xucHJlbHVkZS5qb2luID0gU3RyLmpvaW47XG5wcmVsdWRlLmxpbmVzID0gU3RyLmxpbmVzO1xucHJlbHVkZS51bmxpbmVzID0gU3RyLnVubGluZXM7XG5wcmVsdWRlLndvcmRzID0gU3RyLndvcmRzO1xucHJlbHVkZS51bndvcmRzID0gU3RyLnVud29yZHM7XG5wcmVsdWRlLmNoYXJzID0gU3RyLmNoYXJzO1xucHJlbHVkZS51bmNoYXJzID0gU3RyLnVuY2hhcnM7XG5wcmVsdWRlLnJlcGVhdCA9IFN0ci5yZXBlYXQ7XG5wcmVsdWRlLmNhcGl0YWxpemUgPSBTdHIuY2FwaXRhbGl6ZTtcbnByZWx1ZGUuY2FtZWxpemUgPSBTdHIuY2FtZWxpemU7XG5wcmVsdWRlLmRhc2hlcml6ZSA9IFN0ci5kYXNoZXJpemU7XG5wcmVsdWRlLnZhbHVlcyA9IE9iai52YWx1ZXM7XG5wcmVsdWRlLmtleXMgPSBPYmoua2V5cztcbnByZWx1ZGUucGFpcnNUb09iaiA9IE9iai5wYWlyc1RvT2JqO1xucHJlbHVkZS5vYmpUb1BhaXJzID0gT2JqLm9ialRvUGFpcnM7XG5wcmVsdWRlLmxpc3RzVG9PYmogPSBPYmoubGlzdHNUb09iajtcbnByZWx1ZGUub2JqVG9MaXN0cyA9IE9iai5vYmpUb0xpc3RzO1xucHJlbHVkZS5tYXggPSBOdW0ubWF4O1xucHJlbHVkZS5taW4gPSBOdW0ubWluO1xucHJlbHVkZS5uZWdhdGUgPSBOdW0ubmVnYXRlO1xucHJlbHVkZS5hYnMgPSBOdW0uYWJzO1xucHJlbHVkZS5zaWdudW0gPSBOdW0uc2lnbnVtO1xucHJlbHVkZS5xdW90ID0gTnVtLnF1b3Q7XG5wcmVsdWRlLnJlbSA9IE51bS5yZW07XG5wcmVsdWRlLmRpdiA9IE51bS5kaXY7XG5wcmVsdWRlLm1vZCA9IE51bS5tb2Q7XG5wcmVsdWRlLnJlY2lwID0gTnVtLnJlY2lwO1xucHJlbHVkZS5waSA9IE51bS5waTtcbnByZWx1ZGUudGF1ID0gTnVtLnRhdTtcbnByZWx1ZGUuZXhwID0gTnVtLmV4cDtcbnByZWx1ZGUuc3FydCA9IE51bS5zcXJ0O1xucHJlbHVkZS5sbiA9IE51bS5sbjtcbnByZWx1ZGUucG93ID0gTnVtLnBvdztcbnByZWx1ZGUuc2luID0gTnVtLnNpbjtcbnByZWx1ZGUudGFuID0gTnVtLnRhbjtcbnByZWx1ZGUuY29zID0gTnVtLmNvcztcbnByZWx1ZGUuYWNvcyA9IE51bS5hY29zO1xucHJlbHVkZS5hc2luID0gTnVtLmFzaW47XG5wcmVsdWRlLmF0YW4gPSBOdW0uYXRhbjtcbnByZWx1ZGUuYXRhbjIgPSBOdW0uYXRhbjI7XG5wcmVsdWRlLnRydW5jYXRlID0gTnVtLnRydW5jYXRlO1xucHJlbHVkZS5yb3VuZCA9IE51bS5yb3VuZDtcbnByZWx1ZGUuY2VpbGluZyA9IE51bS5jZWlsaW5nO1xucHJlbHVkZS5mbG9vciA9IE51bS5mbG9vcjtcbnByZWx1ZGUuaXNJdE5hTiA9IE51bS5pc0l0TmFOO1xucHJlbHVkZS5ldmVuID0gTnVtLmV2ZW47XG5wcmVsdWRlLm9kZCA9IE51bS5vZGQ7XG5wcmVsdWRlLmdjZCA9IE51bS5nY2Q7XG5wcmVsdWRlLmxjbSA9IE51bS5sY207XG5wcmVsdWRlLlZFUlNJT04gPSAnMS4yLjEnO1xubW9kdWxlLmV4cG9ydHMgPSBwcmVsdWRlO1xuZnVuY3Rpb24gY3VycnkkKGYsIGJvdW5kKXtcbiAgdmFyIGNvbnRleHQsXG4gIF9jdXJyeSA9IGZ1bmN0aW9uKGFyZ3MpIHtcbiAgICByZXR1cm4gZi5sZW5ndGggPiAxID8gZnVuY3Rpb24oKXtcbiAgICAgIHZhciBwYXJhbXMgPSBhcmdzID8gYXJncy5jb25jYXQoKSA6IFtdO1xuICAgICAgY29udGV4dCA9IGJvdW5kID8gY29udGV4dCB8fCB0aGlzIDogdGhpcztcbiAgICAgIHJldHVybiBwYXJhbXMucHVzaC5hcHBseShwYXJhbXMsIGFyZ3VtZW50cykgPFxuICAgICAgICAgIGYubGVuZ3RoICYmIGFyZ3VtZW50cy5sZW5ndGggP1xuICAgICAgICBfY3VycnkuY2FsbChjb250ZXh0LCBwYXJhbXMpIDogZi5hcHBseShjb250ZXh0LCBwYXJhbXMpO1xuICAgIH0gOiBmO1xuICB9O1xuICByZXR1cm4gX2N1cnJ5KCk7XG59IiwicmVxdWlyZSEgJ3ByZWx1ZGUtbHMnOiB7cmVqZWN0LCBtYXhpbXVtLCBtYXB9XG5cblxuZXhwb3J0IGNsYXNzIEV2ZW50RW1pdHRlclxuICAgIC0+XG4gICAgICAgIEBfZXZlbnRzID0ge31cbiAgICAgICAgQF9vbmVfdGltZV9ldmVudHMgPSB7fVxuXG4gICAgb25jZTogKHR5cGUsIGNhbGxiYWNrKSAhLT5cbiAgICAgICAgYWRkLWxpc3RlbmVyID0gKHR5cGUsIGNhbGxiYWNrKSB+PlxuICAgICAgICAgICAgaWYgdHlwZW9mISBAX29uZV90aW1lX2V2ZW50c1t0eXBlXSBpc250IFxcQXJyYXlcbiAgICAgICAgICAgICAgICBAX29uZV90aW1lX2V2ZW50c1t0eXBlXSA9IFtdXG4gICAgICAgICAgICBAX29uZV90aW1lX2V2ZW50c1t0eXBlXS5wdXNoIGNhbGxiYWNrLmJpbmQgdGhpc1xuXG4gICAgICAgIHN3aXRjaCB0eXBlb2YhIHR5cGVcbiAgICAgICAgICAgIHdoZW4gXFxTdHJpbmcgPT5cbiAgICAgICAgICAgICAgICBhZGQtbGlzdGVuZXIgdHlwZSwgY2FsbGJhY2tcbiAgICAgICAgICAgIHdoZW4gXFxPYmplY3QgPT5cbiAgICAgICAgICAgICAgICBmb3IgbmFtZSwgY2FsbGJhY2sgb2YgdHlwZVxuICAgICAgICAgICAgICAgICAgICBhZGQtbGlzdGVuZXIgbmFtZSwgY2FsbGJhY2tcblxuXG4gICAgb246ICh0eXBlLCBpZCwgY2FsbGJhY2spIC0+XG4gICAgICAgIFwiXCJcIlxuICAgICAgICB1c2FnZTpcblxuICAgICAgICAgICAgd2l0aCBzaW1wbGUgc3RyaW5nIG5hbWU6XG5cbiAgICAgICAgICAgICAgICAub24gJ25hbWUnLCBmblxuXG4gICAgICAgICAgICBvciB3aXRoIGFuIG9iamVjdDpcblxuICAgICAgICAgICAgICAgIC5vbiBkb1xuICAgICAgICAgICAgICAgICAgICAnbmFtZTEnOiBmblxuICAgICAgICAgICAgICAgICAgICAnbmFtZTInOiBmbjJcbiAgICAgICAgXCJcIlwiXG4gICAgICAgIGlmIHR5cGVvZiEgaWQgaXMgXFxGdW5jdGlvblxuICAgICAgICAgICAgY2FsbGJhY2sgPSBpZFxuICAgICAgICAgICAgX2lkID0gWy4uaWQgZm9yIEBfZXZlbnRzXVxuICAgICAgICAgICAgICAgIHw+IG1hcCBwYXJzZS1pbnQgXG4gICAgICAgICAgICAgICAgfD4gbWF4aW11bSBcbiAgICAgICAgICAgIGlkID0gKF9pZCBvciAwKSArIDFcblxuICAgICAgICBhZGQtbGlzdGVuZXIgPSAodHlwZSwgaWQsIGNhbGxiYWNrKSB+PlxuICAgICAgICAgICAgQF9ldmVudHNbXVt0eXBlXS5wdXNoIHtpZCwgY2I6IGNhbGxiYWNrLmJpbmQgdGhpc31cbiAgICAgICAgICAgIHJldHVybiBcbiAgICAgICAgICAgICAgICBjYW5jZWw6IH4+IFxuICAgICAgICAgICAgICAgICAgICBAY2FuY2VsIGlkXG5cbiAgICAgICAgY29udHJvbCA9IG51bGwgXG4gICAgICAgIHN3aXRjaCB0eXBlb2YhIHR5cGVcbiAgICAgICAgICAgIHdoZW4gXFxTdHJpbmcgPT5cbiAgICAgICAgICAgICAgICBjb250cm9sID0gYWRkLWxpc3RlbmVyIHR5cGUsIGlkLCBjYWxsYmFja1xuICAgICAgICAgICAgd2hlbiBcXE9iamVjdCA9PlxuICAgICAgICAgICAgICAgIGZvciBuYW1lLCBjYWxsYmFjayBvZiB0eXBlXG4gICAgICAgICAgICAgICAgICAgIGFkZC1saXN0ZW5lciBuYW1lLCBpZCwgY2FsbGJhY2tcbiAgICAgICAgcmV0dXJuIGNvbnRyb2wgXG5cbiAgICBvZmY6ICh0eXBlKSAtPlxuICAgICAgICBAX2V2ZW50c1t0eXBlXSA9IFtdXG5cbiAgICBjYW5jZWw6IChpZCkgIS0+XG4gICAgICAgICMgcmVtb3ZlIGEgaGFuZGxlciB3aXRoIGEgc3BlY2lmaWMgaWQgZnJvbSBAX2V2ZW50c1xuICAgICAgICBmb3IgdHlwZSwgbGlzdGVuZXJzIG9mIEBfZXZlbnRzXG4gICAgICAgICAgICBmb3IgaSwgbGlzdGVuZXIgb2YgbGlzdGVuZXJzXG4gICAgICAgICAgICAgICAgaWYgbGlzdGVuZXIuaWQgaXMgaWRcbiAgICAgICAgICAgICAgICAgICAgbGlzdGVuZXJzLnNwbGljZSBpLCAxXG4gICAgICAgICAgICAgICAgICAgICNjb25zb2xlLmxvZyBcInJlbW92aW5nICN7aWR9IGZyb20gdHlwZTogI3t0eXBlfVwiXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrXG5cbiAgICB0cmlnZ2VyOiAodHlwZSwgLi4uYXJncykgLT5cbiAgICAgICAgXCJcIlwiXG4gICAgICAgIHVzYWdlOlxuXG4gICAgICAgICAgICAudHJpZ2dlciBcImV2ZW50TmFtZVwiLCAuLi54XG5cbiAgICAgICAgXCJcIlwiXG4gICAgICAgIGlmIEBfZXZlbnRzW3R5cGVdXG4gICAgICAgICAgICBmb3IgbGV0IGhhbmRsZXIgaW4gdGhhdFxuICAgICAgICAgICAgICAgIDx+IHNldC1pbW1lZGlhdGVcbiAgICAgICAgICAgICAgICBoYW5kbGVyLmNiIC4uLmFyZ3NcblxuICAgICAgICBpZiBAX29uZV90aW1lX2V2ZW50c1t0eXBlXVxuICAgICAgICAgICAgZm9yIGkgaW4gWzEgdG8gdGhhdC5sZW5ndGhdXG4gICAgICAgICAgICAgICAgaGFuZGxlciA9IHRoYXQuc2hpZnQhXG4gICAgICAgICAgICAgICAgaGFuZGxlciAuLi5hcmdzXG5cbiAgICBoYXMtbGlzdGVuZXI6IChldikgLT5cbiAgICAgICAgaWYgQF9ldmVudHNbZXZdXG4gICAgICAgICAgICBmb3IgdGhhdFxuICAgICAgICAgICAgICAgIGlmIHR5cGVvZiEgLi5jYiBpcyBcXEZ1bmN0aW9uXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgICAgIHJldHVybiBmYWxzZVxuIiwiIyBmb3IgZGVidWdnaW5nIHB1cnBvc2VzXG5yZXF1aXJlISBjb2xvcnM6IHtcbiAgICBncmVlbiwgZ3JheSwgeWVsbG93LCBtYWdlbnRhXG4gICAgYmctcmVkLCBiZy15ZWxsb3csIGN5YW4sIGJnLWN5YW4sIGJnLWdyZWVuXG59XG5yZXF1aXJlISBtb21lbnRcbnJlcXVpcmUhICdwcmVsdWRlLWxzJzoge21hcH1cbnJlcXVpcmUhICcuL2V2ZW50LWVtaXR0ZXInOiB7RXZlbnRFbWl0dGVyfVxuXG5cbk5FRURfU1RBQ0tfVFJBQ0UgPSBub1xuXG5mbXQgPSAnSEg6bW06c3MuU1NTJ1xuXG5zdGFydC10aW1lID0gbmV3IG1vbWVudFxuXG5hbGlnbi1sZWZ0ID0gKHdpZHRoLCBpbnApIC0+XG4gICAgeCA9IChpbnAgKyBcIiBcIiAqIHdpZHRoKS5zbGljZSAwLCB3aWR0aFxuXG5nZXQtdGltZXN0YW1wID0gLT5cbiAgICAjIGN1cnJlbnQgdGltZVxuICAgIChuZXcgbW9tZW50KS5mb3JtYXQgZm10XG5cbiAgICAjIGRpZmZlcmVudGlhbCB0aW1lXG4gICAgI21vbWVudC51dGMobW9tZW50KChuZXcgbW9tZW50KSwgZm10KS5kaWZmKG1vbWVudChzdGFydFRpbWUsIGZtdCkpKS5mb3JtYXQoZm10KVxuXG5nZXQtcHJlZml4ID0gKF9zb3VyY2UsIGNvbG9yKSAtPlxuICAgIGNvbG9yID0gZ3JheSB1bmxlc3MgY29sb3JcbiAgICBwYWRkZWQgPSBhbGlnbi1sZWZ0IDE1LCBcIiN7X3NvdXJjZX1cIlxuICAgIChjb2xvciBcIlsje2dldC10aW1lc3RhbXAhfV1cIikgKyBcIiAje3BhZGRlZH0gOlwiXG5cbklTX05PREUgPSBkbyAtPlxuICAgIGlzTm9kZSA9IG5vXG4gICAgaWYgdHlwZW9mIHByb2Nlc3MgaXMgXFxvYmplY3RcbiAgICAgICAgaWYgdHlwZW9mIHByb2Nlc3MudmVyc2lvbnMgaXMgXFxvYmplY3RcbiAgICAgICAgICAgIGlmIHR5cGVvZiBwcm9jZXNzLnZlcnNpb25zLm5vZGUgaXNudCBcXHVuZGVmaW5lZFxuICAgICAgICAgICAgICAgIGlzTm9kZSA9IHllc1xuICAgIHJldHVybiBpc05vZGVcblxuY2xhc3MgTG9nTWFuYWdlciBleHRlbmRzIEV2ZW50RW1pdHRlclxuICAgIEBAaW5zdGFuY2UgPSBudWxsXG4gICAgLT5cbiAgICAgICAgcmV0dXJuIEBAaW5zdGFuY2UgaWYgQEBpbnN0YW5jZVxuICAgICAgICBzdXBlciFcbiAgICAgICAgQEBpbnN0YW5jZSA6PSB0aGlzXG4gICAgICAgIEBsb2dnZXJzID0gW11cblxuICAgIHJlZ2lzdGVyOiAoY3R4KSAtPlxuICAgICAgICBAbG9nZ2Vycy5wdXNoIGN0eFxuXG5cbmV4cG9ydCBjbGFzcyBMb2dnZXIgZXh0ZW5kcyBFdmVudEVtaXR0ZXJcbiAgICAoc291cmNlLW5hbWUsIG9wdHM9e30pIC0+XG4gICAgICAgIHN1cGVyIVxuICAgICAgICBAbmFtZSA9IHNvdXJjZS1uYW1lXG4gICAgICAgIEBtZ3IgPSBuZXcgTG9nTWFuYWdlciFcbiAgICAgICAgQHByZWZpeCA9IG51bGxcbiAgICAgICAgQGVycm9yID0gQGVyclxuXG4gICAgZ2V0LXByZWZpeDogKGNvbG9yKSAtPlxuICAgICAgICBnZXQtcHJlZml4IChcIiN7aWYgQHByZWZpeCA9PiBcIiN7QHByZWZpeH0vXCIgZWxzZSAnJ30je0BuYW1lfVwiKSwgY29sb3JcblxuICAgIGxvZzogKC4uLmFyZ3MpIH4+XG4gICAgICAgIHByZWZpeCA9IGdldC1wcmVmaXggQG5hbWVcbiAgICAgICAgaWYgSVNfTk9ERVxuICAgICAgICAgICAgY29uc29sZS5sb2cuY2FsbCBjb25zb2xlLCBwcmVmaXgsIC4uLmFyZ3NcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgX2FyZ3MgPSBbXVxuICAgICAgICAgICAgbXkgPSBcIiVjXCJcbiAgICAgICAgICAgIGZvciBhcmcgaW4gW3ByZWZpeF0gKysgYXJnc1xuICAgICAgICAgICAgICAgIF9hcmdzLnB1c2ggYXJnXG4gICAgICAgICAgICAgICAgbXkgKz0gXCIgXCIgKyBpZiB0eXBlb2YhIGFyZyBpcyBcXFN0cmluZ1xuICAgICAgICAgICAgICAgICAgICBcIiVzXCJcbiAgICAgICAgICAgICAgICBlbHNlIGlmIHR5cGVvZiEgYXJnIGlzIFxcTnVtYmVyXG4gICAgICAgICAgICAgICAgICAgIFwiJWRcIlxuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgXCIlT1wiXG5cbiAgICAgICAgICAgIGlmIE5FRURfU1RBQ0tfVFJBQ0VcbiAgICAgICAgICAgICAgICBjb25zb2xlLmdyb3VwLWNvbGxhcHNlZCBteSwgXCJmb250LXdlaWdodDogbm9ybWFsO1wiIC4uLl9hcmdzXG4gICAgICAgICAgICAgICAgY29uc29sZS50cmFjZSBwcmVmaXhcbiAgICAgICAgICAgICAgICBjb25zb2xlLmdyb3VwLWVuZCFcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBsb2cgPSBGdW5jdGlvbi5wcm90b3R5cGUuYmluZC5jYWxsKGNvbnNvbGUubG9nLCBjb25zb2xlKVxuICAgICAgICAgICAgICAgIGxvZy5jYWxsIGNvbnNvbGUsIG15LCBcImZvbnQtd2VpZ2h0OiBub3JtYWw7XCIgLi4uX2FyZ3NcblxuICAgIHN1Y2Nlc3M6ICguLi5hcmdzKSB+PlxuICAgICAgICBjb25zb2xlLmxvZy5hcHBseSBjb25zb2xlLCAoW0BnZXQtcHJlZml4IGJnLWdyZWVuXSArKyBhcmdzKVxuXG4gICAgZXJyOiAoLi4uYXJncykgfj5cbiAgICAgICAgY29uc29sZS5lcnJvci5hcHBseSBjb25zb2xlLCAoW0BnZXQtcHJlZml4IGJnLXJlZF0gKysgYXJncylcbiAgICAgICAgQHRyaWdnZXIgXFxlcnIsIC4uLmFyZ3NcbiAgICAgICAgQG1nci50cmlnZ2VyIFxcZXJyLCAuLi5hcmdzXG5cbiAgICB3YXJuOiAoLi4uYXJncykgfj5cbiAgICAgICAgY29uc29sZS53YXJuLmFwcGx5IGNvbnNvbGUsIFtAZ2V0LXByZWZpeChiZy15ZWxsb3cpLCB5ZWxsb3coJ1tXQVJOSU5HXScpXSArKyBhcmdzXG5cbiAgICBpbmZvOiAoLi4uYXJncykgfj5cbiAgICAgICAgY29uc29sZS5pbmZvLmFwcGx5IGNvbnNvbGUsIFtAZ2V0LXByZWZpeCEsIGN5YW4oJ1tJXScpXSArKyBhcmdzXG5cbiAgICB0b2RvOiAoLi4uYXJncykgfj5cbiAgICAgICAgY29uc29sZS53YXJuLmFwcGx5IGNvbnNvbGUsIFtAZ2V0LXByZWZpeCEsIG1hZ2VudGEoJ1tUT0RPXScpXSArKyBhcmdzXG5cbiAgICBkZWJ1ZzogKC4uLmFyZ3MpIH4+XG4gICAgICAgIGNvbnNvbGUud2Fybi5hcHBseSBjb25zb2xlLCBbQGdldC1wcmVmaXghLCB5ZWxsb3coJ1tEXScpXSArKyBhcmdzXG4iLCIoZnVuY3Rpb24gKGdsb2JhbCwgdW5kZWZpbmVkKSB7XG4gICAgXCJ1c2Ugc3RyaWN0XCI7XG5cbiAgICBpZiAoZ2xvYmFsLnNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdmFyIG5leHRIYW5kbGUgPSAxOyAvLyBTcGVjIHNheXMgZ3JlYXRlciB0aGFuIHplcm9cbiAgICB2YXIgdGFza3NCeUhhbmRsZSA9IHt9O1xuICAgIHZhciBjdXJyZW50bHlSdW5uaW5nQVRhc2sgPSBmYWxzZTtcbiAgICB2YXIgZG9jID0gZ2xvYmFsLmRvY3VtZW50O1xuICAgIHZhciByZWdpc3RlckltbWVkaWF0ZTtcblxuICAgIGZ1bmN0aW9uIHNldEltbWVkaWF0ZShjYWxsYmFjaykge1xuICAgICAgLy8gQ2FsbGJhY2sgY2FuIGVpdGhlciBiZSBhIGZ1bmN0aW9uIG9yIGEgc3RyaW5nXG4gICAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgY2FsbGJhY2sgPSBuZXcgRnVuY3Rpb24oXCJcIiArIGNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICAgIC8vIENvcHkgZnVuY3Rpb24gYXJndW1lbnRzXG4gICAgICB2YXIgYXJncyA9IG5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoIC0gMSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3MubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICBhcmdzW2ldID0gYXJndW1lbnRzW2kgKyAxXTtcbiAgICAgIH1cbiAgICAgIC8vIFN0b3JlIGFuZCByZWdpc3RlciB0aGUgdGFza1xuICAgICAgdmFyIHRhc2sgPSB7IGNhbGxiYWNrOiBjYWxsYmFjaywgYXJnczogYXJncyB9O1xuICAgICAgdGFza3NCeUhhbmRsZVtuZXh0SGFuZGxlXSA9IHRhc2s7XG4gICAgICByZWdpc3RlckltbWVkaWF0ZShuZXh0SGFuZGxlKTtcbiAgICAgIHJldHVybiBuZXh0SGFuZGxlKys7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2xlYXJJbW1lZGlhdGUoaGFuZGxlKSB7XG4gICAgICAgIGRlbGV0ZSB0YXNrc0J5SGFuZGxlW2hhbmRsZV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcnVuKHRhc2spIHtcbiAgICAgICAgdmFyIGNhbGxiYWNrID0gdGFzay5jYWxsYmFjaztcbiAgICAgICAgdmFyIGFyZ3MgPSB0YXNrLmFyZ3M7XG4gICAgICAgIHN3aXRjaCAoYXJncy5sZW5ndGgpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgY2FsbGJhY2soKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICBjYWxsYmFjayhhcmdzWzBdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICBjYWxsYmFjayhhcmdzWzBdLCBhcmdzWzFdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICBjYWxsYmFjayhhcmdzWzBdLCBhcmdzWzFdLCBhcmdzWzJdKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgY2FsbGJhY2suYXBwbHkodW5kZWZpbmVkLCBhcmdzKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcnVuSWZQcmVzZW50KGhhbmRsZSkge1xuICAgICAgICAvLyBGcm9tIHRoZSBzcGVjOiBcIldhaXQgdW50aWwgYW55IGludm9jYXRpb25zIG9mIHRoaXMgYWxnb3JpdGhtIHN0YXJ0ZWQgYmVmb3JlIHRoaXMgb25lIGhhdmUgY29tcGxldGVkLlwiXG4gICAgICAgIC8vIFNvIGlmIHdlJ3JlIGN1cnJlbnRseSBydW5uaW5nIGEgdGFzaywgd2UnbGwgbmVlZCB0byBkZWxheSB0aGlzIGludm9jYXRpb24uXG4gICAgICAgIGlmIChjdXJyZW50bHlSdW5uaW5nQVRhc2spIHtcbiAgICAgICAgICAgIC8vIERlbGF5IGJ5IGRvaW5nIGEgc2V0VGltZW91dC4gc2V0SW1tZWRpYXRlIHdhcyB0cmllZCBpbnN0ZWFkLCBidXQgaW4gRmlyZWZveCA3IGl0IGdlbmVyYXRlZCBhXG4gICAgICAgICAgICAvLyBcInRvbyBtdWNoIHJlY3Vyc2lvblwiIGVycm9yLlxuICAgICAgICAgICAgc2V0VGltZW91dChydW5JZlByZXNlbnQsIDAsIGhhbmRsZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YXIgdGFzayA9IHRhc2tzQnlIYW5kbGVbaGFuZGxlXTtcbiAgICAgICAgICAgIGlmICh0YXNrKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudGx5UnVubmluZ0FUYXNrID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBydW4odGFzayk7XG4gICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJJbW1lZGlhdGUoaGFuZGxlKTtcbiAgICAgICAgICAgICAgICAgICAgY3VycmVudGx5UnVubmluZ0FUYXNrID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5zdGFsbE5leHRUaWNrSW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIHJlZ2lzdGVySW1tZWRpYXRlID0gZnVuY3Rpb24oaGFuZGxlKSB7XG4gICAgICAgICAgICBwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uICgpIHsgcnVuSWZQcmVzZW50KGhhbmRsZSk7IH0pO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNhblVzZVBvc3RNZXNzYWdlKCkge1xuICAgICAgICAvLyBUaGUgdGVzdCBhZ2FpbnN0IGBpbXBvcnRTY3JpcHRzYCBwcmV2ZW50cyB0aGlzIGltcGxlbWVudGF0aW9uIGZyb20gYmVpbmcgaW5zdGFsbGVkIGluc2lkZSBhIHdlYiB3b3JrZXIsXG4gICAgICAgIC8vIHdoZXJlIGBnbG9iYWwucG9zdE1lc3NhZ2VgIG1lYW5zIHNvbWV0aGluZyBjb21wbGV0ZWx5IGRpZmZlcmVudCBhbmQgY2FuJ3QgYmUgdXNlZCBmb3IgdGhpcyBwdXJwb3NlLlxuICAgICAgICBpZiAoZ2xvYmFsLnBvc3RNZXNzYWdlICYmICFnbG9iYWwuaW1wb3J0U2NyaXB0cykge1xuICAgICAgICAgICAgdmFyIHBvc3RNZXNzYWdlSXNBc3luY2hyb25vdXMgPSB0cnVlO1xuICAgICAgICAgICAgdmFyIG9sZE9uTWVzc2FnZSA9IGdsb2JhbC5vbm1lc3NhZ2U7XG4gICAgICAgICAgICBnbG9iYWwub25tZXNzYWdlID0gZnVuY3Rpb24oKSB7XG4gICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2VJc0FzeW5jaHJvbm91cyA9IGZhbHNlO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGdsb2JhbC5wb3N0TWVzc2FnZShcIlwiLCBcIipcIik7XG4gICAgICAgICAgICBnbG9iYWwub25tZXNzYWdlID0gb2xkT25NZXNzYWdlO1xuICAgICAgICAgICAgcmV0dXJuIHBvc3RNZXNzYWdlSXNBc3luY2hyb25vdXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsUG9zdE1lc3NhZ2VJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgLy8gSW5zdGFsbHMgYW4gZXZlbnQgaGFuZGxlciBvbiBgZ2xvYmFsYCBmb3IgdGhlIGBtZXNzYWdlYCBldmVudDogc2VlXG4gICAgICAgIC8vICogaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4vRE9NL3dpbmRvdy5wb3N0TWVzc2FnZVxuICAgICAgICAvLyAqIGh0dHA6Ly93d3cud2hhdHdnLm9yZy9zcGVjcy93ZWItYXBwcy9jdXJyZW50LXdvcmsvbXVsdGlwYWdlL2NvbW1zLmh0bWwjY3Jvc3NEb2N1bWVudE1lc3NhZ2VzXG5cbiAgICAgICAgdmFyIG1lc3NhZ2VQcmVmaXggPSBcInNldEltbWVkaWF0ZSRcIiArIE1hdGgucmFuZG9tKCkgKyBcIiRcIjtcbiAgICAgICAgdmFyIG9uR2xvYmFsTWVzc2FnZSA9IGZ1bmN0aW9uKGV2ZW50KSB7XG4gICAgICAgICAgICBpZiAoZXZlbnQuc291cmNlID09PSBnbG9iYWwgJiZcbiAgICAgICAgICAgICAgICB0eXBlb2YgZXZlbnQuZGF0YSA9PT0gXCJzdHJpbmdcIiAmJlxuICAgICAgICAgICAgICAgIGV2ZW50LmRhdGEuaW5kZXhPZihtZXNzYWdlUHJlZml4KSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJ1bklmUHJlc2VudCgrZXZlbnQuZGF0YS5zbGljZShtZXNzYWdlUHJlZml4Lmxlbmd0aCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIGlmIChnbG9iYWwuYWRkRXZlbnRMaXN0ZW5lcikge1xuICAgICAgICAgICAgZ2xvYmFsLmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIG9uR2xvYmFsTWVzc2FnZSwgZmFsc2UpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2xvYmFsLmF0dGFjaEV2ZW50KFwib25tZXNzYWdlXCIsIG9uR2xvYmFsTWVzc2FnZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZWdpc3RlckltbWVkaWF0ZSA9IGZ1bmN0aW9uKGhhbmRsZSkge1xuICAgICAgICAgICAgZ2xvYmFsLnBvc3RNZXNzYWdlKG1lc3NhZ2VQcmVmaXggKyBoYW5kbGUsIFwiKlwiKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbnN0YWxsTWVzc2FnZUNoYW5uZWxJbXBsZW1lbnRhdGlvbigpIHtcbiAgICAgICAgdmFyIGNoYW5uZWwgPSBuZXcgTWVzc2FnZUNoYW5uZWwoKTtcbiAgICAgICAgY2hhbm5lbC5wb3J0MS5vbm1lc3NhZ2UgPSBmdW5jdGlvbihldmVudCkge1xuICAgICAgICAgICAgdmFyIGhhbmRsZSA9IGV2ZW50LmRhdGE7XG4gICAgICAgICAgICBydW5JZlByZXNlbnQoaGFuZGxlKTtcbiAgICAgICAgfTtcblxuICAgICAgICByZWdpc3RlckltbWVkaWF0ZSA9IGZ1bmN0aW9uKGhhbmRsZSkge1xuICAgICAgICAgICAgY2hhbm5lbC5wb3J0Mi5wb3N0TWVzc2FnZShoYW5kbGUpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxSZWFkeVN0YXRlQ2hhbmdlSW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIHZhciBodG1sID0gZG9jLmRvY3VtZW50RWxlbWVudDtcbiAgICAgICAgcmVnaXN0ZXJJbW1lZGlhdGUgPSBmdW5jdGlvbihoYW5kbGUpIHtcbiAgICAgICAgICAgIC8vIENyZWF0ZSBhIDxzY3JpcHQ+IGVsZW1lbnQ7IGl0cyByZWFkeXN0YXRlY2hhbmdlIGV2ZW50IHdpbGwgYmUgZmlyZWQgYXN5bmNocm9ub3VzbHkgb25jZSBpdCBpcyBpbnNlcnRlZFxuICAgICAgICAgICAgLy8gaW50byB0aGUgZG9jdW1lbnQuIERvIHNvLCB0aHVzIHF1ZXVpbmcgdXAgdGhlIHRhc2suIFJlbWVtYmVyIHRvIGNsZWFuIHVwIG9uY2UgaXQncyBiZWVuIGNhbGxlZC5cbiAgICAgICAgICAgIHZhciBzY3JpcHQgPSBkb2MuY3JlYXRlRWxlbWVudChcInNjcmlwdFwiKTtcbiAgICAgICAgICAgIHNjcmlwdC5vbnJlYWR5c3RhdGVjaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcnVuSWZQcmVzZW50KGhhbmRsZSk7XG4gICAgICAgICAgICAgICAgc2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IG51bGw7XG4gICAgICAgICAgICAgICAgaHRtbC5yZW1vdmVDaGlsZChzY3JpcHQpO1xuICAgICAgICAgICAgICAgIHNjcmlwdCA9IG51bGw7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaHRtbC5hcHBlbmRDaGlsZChzY3JpcHQpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGluc3RhbGxTZXRUaW1lb3V0SW1wbGVtZW50YXRpb24oKSB7XG4gICAgICAgIHJlZ2lzdGVySW1tZWRpYXRlID0gZnVuY3Rpb24oaGFuZGxlKSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KHJ1bklmUHJlc2VudCwgMCwgaGFuZGxlKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBJZiBzdXBwb3J0ZWQsIHdlIHNob3VsZCBhdHRhY2ggdG8gdGhlIHByb3RvdHlwZSBvZiBnbG9iYWwsIHNpbmNlIHRoYXQgaXMgd2hlcmUgc2V0VGltZW91dCBldCBhbC4gbGl2ZS5cbiAgICB2YXIgYXR0YWNoVG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YgJiYgT2JqZWN0LmdldFByb3RvdHlwZU9mKGdsb2JhbCk7XG4gICAgYXR0YWNoVG8gPSBhdHRhY2hUbyAmJiBhdHRhY2hUby5zZXRUaW1lb3V0ID8gYXR0YWNoVG8gOiBnbG9iYWw7XG5cbiAgICAvLyBEb24ndCBnZXQgZm9vbGVkIGJ5IGUuZy4gYnJvd3NlcmlmeSBlbnZpcm9ubWVudHMuXG4gICAgaWYgKHt9LnRvU3RyaW5nLmNhbGwoZ2xvYmFsLnByb2Nlc3MpID09PSBcIltvYmplY3QgcHJvY2Vzc11cIikge1xuICAgICAgICAvLyBGb3IgTm9kZS5qcyBiZWZvcmUgMC45XG4gICAgICAgIGluc3RhbGxOZXh0VGlja0ltcGxlbWVudGF0aW9uKCk7XG5cbiAgICB9IGVsc2UgaWYgKGNhblVzZVBvc3RNZXNzYWdlKCkpIHtcbiAgICAgICAgLy8gRm9yIG5vbi1JRTEwIG1vZGVybiBicm93c2Vyc1xuICAgICAgICBpbnN0YWxsUG9zdE1lc3NhZ2VJbXBsZW1lbnRhdGlvbigpO1xuXG4gICAgfSBlbHNlIGlmIChnbG9iYWwuTWVzc2FnZUNoYW5uZWwpIHtcbiAgICAgICAgLy8gRm9yIHdlYiB3b3JrZXJzLCB3aGVyZSBzdXBwb3J0ZWRcbiAgICAgICAgaW5zdGFsbE1lc3NhZ2VDaGFubmVsSW1wbGVtZW50YXRpb24oKTtcblxuICAgIH0gZWxzZSBpZiAoZG9jICYmIFwib25yZWFkeXN0YXRlY2hhbmdlXCIgaW4gZG9jLmNyZWF0ZUVsZW1lbnQoXCJzY3JpcHRcIikpIHtcbiAgICAgICAgLy8gRm9yIElFIDbigJM4XG4gICAgICAgIGluc3RhbGxSZWFkeVN0YXRlQ2hhbmdlSW1wbGVtZW50YXRpb24oKTtcblxuICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIEZvciBvbGRlciBicm93c2Vyc1xuICAgICAgICBpbnN0YWxsU2V0VGltZW91dEltcGxlbWVudGF0aW9uKCk7XG4gICAgfVxuXG4gICAgYXR0YWNoVG8uc2V0SW1tZWRpYXRlID0gc2V0SW1tZWRpYXRlO1xuICAgIGF0dGFjaFRvLmNsZWFySW1tZWRpYXRlID0gY2xlYXJJbW1lZGlhdGU7XG59KHR5cGVvZiBzZWxmID09PSBcInVuZGVmaW5lZFwiID8gdHlwZW9mIGdsb2JhbCA9PT0gXCJ1bmRlZmluZWRcIiA/IHRoaXMgOiBnbG9iYWwgOiBzZWxmKSk7XG4iLCJleHBvcnQgc2xlZXAgPSAobXMsIGYpIC0+IHNldC10aW1lb3V0IGYsIG1zXG5leHBvcnQgY2xlYXItdGltZXIgPSAoeCkgLT4gY2xlYXItaW50ZXJ2YWwgeFxucmVxdWlyZShcInNldGltbWVkaWF0ZVwiKVxuIiwiXG5leHBvcnRzLmlzQnJvd3NlciA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnO1xuIiwiXG52YXIgUHJvY2Vzc29yID0gZnVuY3Rpb24gUHJvY2Vzc29yKG9wdGlvbnMpe1xuICB0aGlzLnNlbGZPcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcbiAgdGhpcy5waXBlcyA9IHt9O1xufTtcblxuUHJvY2Vzc29yLnByb3RvdHlwZS5vcHRpb25zID0gZnVuY3Rpb24ob3B0aW9ucykge1xuICBpZiAob3B0aW9ucykge1xuICAgIHRoaXMuc2VsZk9wdGlvbnMgPSBvcHRpb25zO1xuICB9XG4gIHJldHVybiB0aGlzLnNlbGZPcHRpb25zO1xufTtcblxuUHJvY2Vzc29yLnByb3RvdHlwZS5waXBlID0gZnVuY3Rpb24obmFtZSwgcGlwZSkge1xuICBpZiAodHlwZW9mIG5hbWUgPT09ICdzdHJpbmcnKSB7XG4gICAgaWYgKHR5cGVvZiBwaXBlID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuIHRoaXMucGlwZXNbbmFtZV07XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucGlwZXNbbmFtZV0gPSBwaXBlO1xuICAgIH1cbiAgfVxuICBpZiAobmFtZSAmJiBuYW1lLm5hbWUpIHtcbiAgICBwaXBlID0gbmFtZTtcbiAgICBpZiAocGlwZS5wcm9jZXNzb3IgPT09IHRoaXMpIHsgcmV0dXJuIHBpcGU7IH1cbiAgICB0aGlzLnBpcGVzW3BpcGUubmFtZV0gPSBwaXBlO1xuICB9XG4gIHBpcGUucHJvY2Vzc29yID0gdGhpcztcbiAgcmV0dXJuIHBpcGU7XG59O1xuXG5Qcm9jZXNzb3IucHJvdG90eXBlLnByb2Nlc3MgPSBmdW5jdGlvbihpbnB1dCwgcGlwZSkge1xuICB2YXIgY29udGV4dCA9IGlucHV0O1xuICBjb250ZXh0Lm9wdGlvbnMgPSB0aGlzLm9wdGlvbnMoKTtcbiAgdmFyIG5leHRQaXBlID0gcGlwZSB8fCBpbnB1dC5waXBlIHx8ICdkZWZhdWx0JztcbiAgdmFyIGxhc3RQaXBlLCBsYXN0Q29udGV4dDtcbiAgd2hpbGUgKG5leHRQaXBlKSB7XG4gICAgaWYgKHR5cGVvZiBjb250ZXh0Lm5leHRBZnRlckNoaWxkcmVuICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgLy8gY2hpbGRyZW4gcHJvY2Vzc2VkIGFuZCBjb21pbmcgYmFjayB0byBwYXJlbnRcbiAgICAgIGNvbnRleHQubmV4dCA9IGNvbnRleHQubmV4dEFmdGVyQ2hpbGRyZW47XG4gICAgICBjb250ZXh0Lm5leHRBZnRlckNoaWxkcmVuID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG5leHRQaXBlID09PSAnc3RyaW5nJykge1xuICAgICAgbmV4dFBpcGUgPSB0aGlzLnBpcGUobmV4dFBpcGUpO1xuICAgIH1cbiAgICBuZXh0UGlwZS5wcm9jZXNzKGNvbnRleHQpO1xuICAgIGxhc3RDb250ZXh0ID0gY29udGV4dDtcbiAgICBsYXN0UGlwZSA9IG5leHRQaXBlO1xuICAgIG5leHRQaXBlID0gbnVsbDtcbiAgICBpZiAoY29udGV4dCkge1xuICAgICAgaWYgKGNvbnRleHQubmV4dCkge1xuICAgICAgICBjb250ZXh0ID0gY29udGV4dC5uZXh0O1xuICAgICAgICBuZXh0UGlwZSA9IGxhc3RDb250ZXh0Lm5leHRQaXBlIHx8IGNvbnRleHQucGlwZSB8fCBsYXN0UGlwZTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGNvbnRleHQuaGFzUmVzdWx0ID8gY29udGV4dC5yZXN1bHQgOiB1bmRlZmluZWQ7XG59O1xuXG5leHBvcnRzLlByb2Nlc3NvciA9IFByb2Nlc3NvcjtcbiIsInZhciBQaXBlID0gZnVuY3Rpb24gUGlwZShuYW1lKSB7XG4gIHRoaXMubmFtZSA9IG5hbWU7XG4gIHRoaXMuZmlsdGVycyA9IFtdO1xufTtcblxuUGlwZS5wcm90b3R5cGUucHJvY2VzcyA9IGZ1bmN0aW9uKGlucHV0KSB7XG4gIGlmICghdGhpcy5wcm9jZXNzb3IpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2FkZCB0aGlzIHBpcGUgdG8gYSBwcm9jZXNzb3IgYmVmb3JlIHVzaW5nIGl0Jyk7XG4gIH1cbiAgdmFyIGRlYnVnID0gdGhpcy5kZWJ1ZztcbiAgdmFyIGxlbmd0aCA9IHRoaXMuZmlsdGVycy5sZW5ndGg7XG4gIHZhciBjb250ZXh0ID0gaW5wdXQ7XG4gIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICB2YXIgZmlsdGVyID0gdGhpcy5maWx0ZXJzW2luZGV4XTtcbiAgICBpZiAoZGVidWcpIHtcbiAgICAgIHRoaXMubG9nKCdmaWx0ZXI6ICcgKyBmaWx0ZXIuZmlsdGVyTmFtZSk7XG4gICAgfVxuICAgIGZpbHRlcihjb250ZXh0KTtcbiAgICBpZiAodHlwZW9mIGNvbnRleHQgPT09ICdvYmplY3QnICYmIGNvbnRleHQuZXhpdGluZykge1xuICAgICAgY29udGV4dC5leGl0aW5nID0gZmFsc2U7XG4gICAgICBicmVhaztcbiAgICB9XG4gIH1cbiAgaWYgKCFjb250ZXh0Lm5leHQgJiYgdGhpcy5yZXN1bHRDaGVjaykge1xuICAgIHRoaXMucmVzdWx0Q2hlY2soY29udGV4dCk7XG4gIH1cbn07XG5cblBpcGUucHJvdG90eXBlLmxvZyA9IGZ1bmN0aW9uKG1zZykge1xuICBjb25zb2xlLmxvZygnW2pzb25kaWZmcGF0Y2hdICcgKyB0aGlzLm5hbWUgKyAnIHBpcGUsICcgKyBtc2cpO1xufTtcblxuUGlwZS5wcm90b3R5cGUuYXBwZW5kID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZmlsdGVycy5wdXNoLmFwcGx5KHRoaXMuZmlsdGVycywgYXJndW1lbnRzKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5QaXBlLnByb3RvdHlwZS5wcmVwZW5kID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuZmlsdGVycy51bnNoaWZ0LmFwcGx5KHRoaXMuZmlsdGVycywgYXJndW1lbnRzKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5QaXBlLnByb3RvdHlwZS5pbmRleE9mID0gZnVuY3Rpb24oZmlsdGVyTmFtZSkge1xuICBpZiAoIWZpbHRlck5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2EgZmlsdGVyIG5hbWUgaXMgcmVxdWlyZWQnKTtcbiAgfVxuICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgdGhpcy5maWx0ZXJzLmxlbmd0aDsgaW5kZXgrKykge1xuICAgIHZhciBmaWx0ZXIgPSB0aGlzLmZpbHRlcnNbaW5kZXhdO1xuICAgIGlmIChmaWx0ZXIuZmlsdGVyTmFtZSA9PT0gZmlsdGVyTmFtZSkge1xuICAgICAgcmV0dXJuIGluZGV4O1xuICAgIH1cbiAgfVxuICB0aHJvdyBuZXcgRXJyb3IoJ2ZpbHRlciBub3QgZm91bmQ6ICcgKyBmaWx0ZXJOYW1lKTtcbn07XG5cblBpcGUucHJvdG90eXBlLmxpc3QgPSBmdW5jdGlvbigpIHtcbiAgdmFyIG5hbWVzID0gW107XG4gIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCB0aGlzLmZpbHRlcnMubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgdmFyIGZpbHRlciA9IHRoaXMuZmlsdGVyc1tpbmRleF07XG4gICAgbmFtZXMucHVzaChmaWx0ZXIuZmlsdGVyTmFtZSk7XG4gIH1cbiAgcmV0dXJuIG5hbWVzO1xufTtcblxuUGlwZS5wcm90b3R5cGUuYWZ0ZXIgPSBmdW5jdGlvbihmaWx0ZXJOYW1lKSB7XG4gIHZhciBpbmRleCA9IHRoaXMuaW5kZXhPZihmaWx0ZXJOYW1lKTtcbiAgdmFyIHBhcmFtcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gIGlmICghcGFyYW1zLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignYSBmaWx0ZXIgaXMgcmVxdWlyZWQnKTtcbiAgfVxuICBwYXJhbXMudW5zaGlmdChpbmRleCArIDEsIDApO1xuICBBcnJheS5wcm90b3R5cGUuc3BsaWNlLmFwcGx5KHRoaXMuZmlsdGVycywgcGFyYW1zKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5QaXBlLnByb3RvdHlwZS5iZWZvcmUgPSBmdW5jdGlvbihmaWx0ZXJOYW1lKSB7XG4gIHZhciBpbmRleCA9IHRoaXMuaW5kZXhPZihmaWx0ZXJOYW1lKTtcbiAgdmFyIHBhcmFtcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gIGlmICghcGFyYW1zLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignYSBmaWx0ZXIgaXMgcmVxdWlyZWQnKTtcbiAgfVxuICBwYXJhbXMudW5zaGlmdChpbmRleCwgMCk7XG4gIEFycmF5LnByb3RvdHlwZS5zcGxpY2UuYXBwbHkodGhpcy5maWx0ZXJzLCBwYXJhbXMpO1xuICByZXR1cm4gdGhpcztcbn07XG5cblBpcGUucHJvdG90eXBlLnJlcGxhY2UgPSBmdW5jdGlvbihmaWx0ZXJOYW1lKSB7XG4gIHZhciBpbmRleCA9IHRoaXMuaW5kZXhPZihmaWx0ZXJOYW1lKTtcbiAgdmFyIHBhcmFtcyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSk7XG4gIGlmICghcGFyYW1zLmxlbmd0aCkge1xuICAgIHRocm93IG5ldyBFcnJvcignYSBmaWx0ZXIgaXMgcmVxdWlyZWQnKTtcbiAgfVxuICBwYXJhbXMudW5zaGlmdChpbmRleCwgMSk7XG4gIEFycmF5LnByb3RvdHlwZS5zcGxpY2UuYXBwbHkodGhpcy5maWx0ZXJzLCBwYXJhbXMpO1xuICByZXR1cm4gdGhpcztcbn07XG5cblBpcGUucHJvdG90eXBlLnJlbW92ZSA9IGZ1bmN0aW9uKGZpbHRlck5hbWUpIHtcbiAgdmFyIGluZGV4ID0gdGhpcy5pbmRleE9mKGZpbHRlck5hbWUpO1xuICB0aGlzLmZpbHRlcnMuc3BsaWNlKGluZGV4LCAxKTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5QaXBlLnByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uKCkge1xuICB0aGlzLmZpbHRlcnMubGVuZ3RoID0gMDtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5QaXBlLnByb3RvdHlwZS5zaG91bGRIYXZlUmVzdWx0ID0gZnVuY3Rpb24oc2hvdWxkKSB7XG4gIGlmIChzaG91bGQgPT09IGZhbHNlKSB7XG4gICAgdGhpcy5yZXN1bHRDaGVjayA9IG51bGw7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0aGlzLnJlc3VsdENoZWNrKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBwaXBlID0gdGhpcztcbiAgdGhpcy5yZXN1bHRDaGVjayA9IGZ1bmN0aW9uKGNvbnRleHQpIHtcbiAgICBpZiAoIWNvbnRleHQuaGFzUmVzdWx0KSB7XG4gICAgICBjb25zb2xlLmxvZyhjb250ZXh0KTtcbiAgICAgIHZhciBlcnJvciA9IG5ldyBFcnJvcihwaXBlLm5hbWUgKyAnIGZhaWxlZCcpO1xuICAgICAgZXJyb3Iubm9SZXN1bHQgPSB0cnVlO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICB9O1xuICByZXR1cm4gdGhpcztcbn07XG5cbmV4cG9ydHMuUGlwZSA9IFBpcGU7XG4iLCJcbnZhciBQaXBlID0gcmVxdWlyZSgnLi4vcGlwZScpLlBpcGU7XG5cbnZhciBDb250ZXh0ID0gZnVuY3Rpb24gQ29udGV4dCgpe1xufTtcblxuQ29udGV4dC5wcm90b3R5cGUuc2V0UmVzdWx0ID0gZnVuY3Rpb24ocmVzdWx0KSB7XG5cdHRoaXMucmVzdWx0ID0gcmVzdWx0O1xuXHR0aGlzLmhhc1Jlc3VsdCA9IHRydWU7XG5cdHJldHVybiB0aGlzO1xufTtcblxuQ29udGV4dC5wcm90b3R5cGUuZXhpdCA9IGZ1bmN0aW9uKCkge1xuXHR0aGlzLmV4aXRpbmcgPSB0cnVlO1xuXHRyZXR1cm4gdGhpcztcbn07XG5cbkNvbnRleHQucHJvdG90eXBlLnN3aXRjaFRvID0gZnVuY3Rpb24obmV4dCwgcGlwZSkge1xuXHRpZiAodHlwZW9mIG5leHQgPT09ICdzdHJpbmcnIHx8IG5leHQgaW5zdGFuY2VvZiBQaXBlKSB7XG5cdFx0dGhpcy5uZXh0UGlwZSA9IG5leHQ7XG5cdH0gZWxzZSB7XG5cdFx0dGhpcy5uZXh0ID0gbmV4dDtcblx0XHRpZiAocGlwZSkge1xuXHRcdFx0dGhpcy5uZXh0UGlwZSA9IHBpcGU7XG5cdFx0fVxuXHR9XG5cdHJldHVybiB0aGlzO1xufTtcblxuQ29udGV4dC5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uKGNoaWxkLCBuYW1lKSB7XG5cdGNoaWxkLnBhcmVudCA9IHRoaXM7XG5cdGlmICh0eXBlb2YgbmFtZSAhPT0gJ3VuZGVmaW5lZCcpIHtcblx0XHRjaGlsZC5jaGlsZE5hbWUgPSBuYW1lO1xuXHR9XG5cdGNoaWxkLnJvb3QgPSB0aGlzLnJvb3QgfHwgdGhpcztcblx0Y2hpbGQub3B0aW9ucyA9IGNoaWxkLm9wdGlvbnMgfHwgdGhpcy5vcHRpb25zO1xuXHRpZiAoIXRoaXMuY2hpbGRyZW4pIHtcblx0XHR0aGlzLmNoaWxkcmVuID0gW2NoaWxkXTtcblx0XHR0aGlzLm5leHRBZnRlckNoaWxkcmVuID0gdGhpcy5uZXh0IHx8IG51bGw7XG5cdFx0dGhpcy5uZXh0ID0gY2hpbGQ7XG5cdH0gZWxzZSB7XG5cdFx0dGhpcy5jaGlsZHJlblt0aGlzLmNoaWxkcmVuLmxlbmd0aCAtIDFdLm5leHQgPSBjaGlsZDtcblx0XHR0aGlzLmNoaWxkcmVuLnB1c2goY2hpbGQpO1xuXHR9XG5cdGNoaWxkLm5leHQgPSB0aGlzO1xuXHRyZXR1cm4gdGhpcztcbn07XG5cbmV4cG9ydHMuQ29udGV4dCA9IENvbnRleHQ7XG4iLCJcbnZhciBpc0FycmF5ID0gKHR5cGVvZiBBcnJheS5pc0FycmF5ID09PSAnZnVuY3Rpb24nKSA/XG4gIC8vIHVzZSBuYXRpdmUgZnVuY3Rpb25cbiAgQXJyYXkuaXNBcnJheSA6XG4gIC8vIHVzZSBpbnN0YW5jZW9mIG9wZXJhdG9yXG4gIGZ1bmN0aW9uKGEpIHtcbiAgICByZXR1cm4gYSBpbnN0YW5jZW9mIEFycmF5O1xuICB9O1xuXG5mdW5jdGlvbiBjbG9uZVJlZ0V4cChyZSkge1xuICB2YXIgcmVnZXhNYXRjaCA9IC9eXFwvKC4qKVxcLyhbZ2lteXVdKikkLy5leGVjKHJlLnRvU3RyaW5nKCkpO1xuICByZXR1cm4gbmV3IFJlZ0V4cChyZWdleE1hdGNoWzFdLCByZWdleE1hdGNoWzJdKTtcbn1cblxuZnVuY3Rpb24gY2xvbmUoYXJnKSB7XG4gIGlmICh0eXBlb2YgYXJnICE9PSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBhcmc7XG4gIH1cbiAgaWYgKGFyZyA9PT0gbnVsbCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG4gIGlmIChpc0FycmF5KGFyZykpIHtcbiAgICByZXR1cm4gYXJnLm1hcChjbG9uZSk7XG4gIH1cbiAgaWYgKGFyZyBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICByZXR1cm4gbmV3IERhdGUoYXJnLmdldFRpbWUoKSk7XG4gIH1cbiAgaWYgKGFyZyBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgIHJldHVybiBjbG9uZVJlZ0V4cChhcmcpO1xuICB9XG4gIHZhciBjbG9uZWQgPSB7fTtcbiAgZm9yICh2YXIgbmFtZSBpbiBhcmcpIHtcbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGFyZywgbmFtZSkpIHtcbiAgICAgIGNsb25lZFtuYW1lXSA9IGNsb25lKGFyZ1tuYW1lXSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBjbG9uZWQ7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gY2xvbmU7XG4iLCJ2YXIgQ29udGV4dCA9IHJlcXVpcmUoJy4vY29udGV4dCcpLkNvbnRleHQ7XG52YXIgZGVmYXVsdENsb25lID0gcmVxdWlyZSgnLi4vY2xvbmUnKTtcblxudmFyIERpZmZDb250ZXh0ID0gZnVuY3Rpb24gRGlmZkNvbnRleHQobGVmdCwgcmlnaHQpIHtcbiAgdGhpcy5sZWZ0ID0gbGVmdDtcbiAgdGhpcy5yaWdodCA9IHJpZ2h0O1xuICB0aGlzLnBpcGUgPSAnZGlmZic7XG59O1xuXG5EaWZmQ29udGV4dC5wcm90b3R5cGUgPSBuZXcgQ29udGV4dCgpO1xuXG5EaWZmQ29udGV4dC5wcm90b3R5cGUuc2V0UmVzdWx0ID0gZnVuY3Rpb24ocmVzdWx0KSB7XG4gIGlmICh0aGlzLm9wdGlvbnMuY2xvbmVEaWZmVmFsdWVzICYmIHR5cGVvZiByZXN1bHQgPT09ICdvYmplY3QnKSB7XG4gICAgdmFyIGNsb25lID0gdHlwZW9mIHRoaXMub3B0aW9ucy5jbG9uZURpZmZWYWx1ZXMgPT09ICdmdW5jdGlvbicgP1xuICAgICAgdGhpcy5vcHRpb25zLmNsb25lRGlmZlZhbHVlcyA6IGRlZmF1bHRDbG9uZTtcbiAgICBpZiAodHlwZW9mIHJlc3VsdFswXSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIHJlc3VsdFswXSA9IGNsb25lKHJlc3VsdFswXSk7XG4gICAgfVxuICAgIGlmICh0eXBlb2YgcmVzdWx0WzFdID09PSAnb2JqZWN0Jykge1xuICAgICAgcmVzdWx0WzFdID0gY2xvbmUocmVzdWx0WzFdKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIENvbnRleHQucHJvdG90eXBlLnNldFJlc3VsdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufTtcblxuZXhwb3J0cy5EaWZmQ29udGV4dCA9IERpZmZDb250ZXh0O1xuIiwidmFyIENvbnRleHQgPSByZXF1aXJlKCcuL2NvbnRleHQnKS5Db250ZXh0O1xuXG52YXIgUGF0Y2hDb250ZXh0ID0gZnVuY3Rpb24gUGF0Y2hDb250ZXh0KGxlZnQsIGRlbHRhKSB7XG4gIHRoaXMubGVmdCA9IGxlZnQ7XG4gIHRoaXMuZGVsdGEgPSBkZWx0YTtcbiAgdGhpcy5waXBlID0gJ3BhdGNoJztcbn07XG5cblBhdGNoQ29udGV4dC5wcm90b3R5cGUgPSBuZXcgQ29udGV4dCgpO1xuXG5leHBvcnRzLlBhdGNoQ29udGV4dCA9IFBhdGNoQ29udGV4dDtcbiIsInZhciBDb250ZXh0ID0gcmVxdWlyZSgnLi9jb250ZXh0JykuQ29udGV4dDtcblxudmFyIFJldmVyc2VDb250ZXh0ID0gZnVuY3Rpb24gUmV2ZXJzZUNvbnRleHQoZGVsdGEpIHtcbiAgdGhpcy5kZWx0YSA9IGRlbHRhO1xuICB0aGlzLnBpcGUgPSAncmV2ZXJzZSc7XG59O1xuXG5SZXZlcnNlQ29udGV4dC5wcm90b3R5cGUgPSBuZXcgQ29udGV4dCgpO1xuXG5leHBvcnRzLlJldmVyc2VDb250ZXh0ID0gUmV2ZXJzZUNvbnRleHQ7XG4iLCJ2YXIgaXNBcnJheSA9ICh0eXBlb2YgQXJyYXkuaXNBcnJheSA9PT0gJ2Z1bmN0aW9uJykgP1xuICAvLyB1c2UgbmF0aXZlIGZ1bmN0aW9uXG4gIEFycmF5LmlzQXJyYXkgOlxuICAvLyB1c2UgaW5zdGFuY2VvZiBvcGVyYXRvclxuICBmdW5jdGlvbihhKSB7XG4gICAgcmV0dXJuIGEgaW5zdGFuY2VvZiBBcnJheTtcbiAgfTtcblxudmFyIGRpZmZGaWx0ZXIgPSBmdW5jdGlvbiB0cml2aWFsTWF0Y2hlc0RpZmZGaWx0ZXIoY29udGV4dCkge1xuICBpZiAoY29udGV4dC5sZWZ0ID09PSBjb250ZXh0LnJpZ2h0KSB7XG4gICAgY29udGV4dC5zZXRSZXN1bHQodW5kZWZpbmVkKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0eXBlb2YgY29udGV4dC5sZWZ0ID09PSAndW5kZWZpbmVkJykge1xuICAgIGlmICh0eXBlb2YgY29udGV4dC5yaWdodCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdmdW5jdGlvbnMgYXJlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICB9XG4gICAgY29udGV4dC5zZXRSZXN1bHQoW2NvbnRleHQucmlnaHRdKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmICh0eXBlb2YgY29udGV4dC5yaWdodCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5sZWZ0LCAwLCAwXSkuZXhpdCgpO1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAodHlwZW9mIGNvbnRleHQubGVmdCA9PT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgY29udGV4dC5yaWdodCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBFcnJvcignZnVuY3Rpb25zIGFyZSBub3Qgc3VwcG9ydGVkJyk7XG4gIH1cbiAgY29udGV4dC5sZWZ0VHlwZSA9IGNvbnRleHQubGVmdCA9PT0gbnVsbCA/ICdudWxsJyA6IHR5cGVvZiBjb250ZXh0LmxlZnQ7XG4gIGNvbnRleHQucmlnaHRUeXBlID0gY29udGV4dC5yaWdodCA9PT0gbnVsbCA/ICdudWxsJyA6IHR5cGVvZiBjb250ZXh0LnJpZ2h0O1xuICBpZiAoY29udGV4dC5sZWZ0VHlwZSAhPT0gY29udGV4dC5yaWdodFR5cGUpIHtcbiAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5sZWZ0LCBjb250ZXh0LnJpZ2h0XSkuZXhpdCgpO1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoY29udGV4dC5sZWZ0VHlwZSA9PT0gJ2Jvb2xlYW4nIHx8IGNvbnRleHQubGVmdFR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgY29udGV4dC5zZXRSZXN1bHQoW2NvbnRleHQubGVmdCwgY29udGV4dC5yaWdodF0pLmV4aXQoKTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGNvbnRleHQubGVmdFR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgY29udGV4dC5sZWZ0SXNBcnJheSA9IGlzQXJyYXkoY29udGV4dC5sZWZ0KTtcbiAgfVxuICBpZiAoY29udGV4dC5yaWdodFR5cGUgPT09ICdvYmplY3QnKSB7XG4gICAgY29udGV4dC5yaWdodElzQXJyYXkgPSBpc0FycmF5KGNvbnRleHQucmlnaHQpO1xuICB9XG4gIGlmIChjb250ZXh0LmxlZnRJc0FycmF5ICE9PSBjb250ZXh0LnJpZ2h0SXNBcnJheSkge1xuICAgIGNvbnRleHQuc2V0UmVzdWx0KFtjb250ZXh0LmxlZnQsIGNvbnRleHQucmlnaHRdKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKGNvbnRleHQubGVmdCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgIGlmIChjb250ZXh0LnJpZ2h0IGluc3RhbmNlb2YgUmVnRXhwKSB7XG4gICAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5sZWZ0LnRvU3RyaW5nKCksIGNvbnRleHQucmlnaHQudG9TdHJpbmcoKV0pLmV4aXQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29udGV4dC5zZXRSZXN1bHQoW2NvbnRleHQubGVmdCwgY29udGV4dC5yaWdodF0pLmV4aXQoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cbn07XG5kaWZmRmlsdGVyLmZpbHRlck5hbWUgPSAndHJpdmlhbCc7XG5cbnZhciBwYXRjaEZpbHRlciA9IGZ1bmN0aW9uIHRyaXZpYWxNYXRjaGVzUGF0Y2hGaWx0ZXIoY29udGV4dCkge1xuICBpZiAodHlwZW9mIGNvbnRleHQuZGVsdGEgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgY29udGV4dC5zZXRSZXN1bHQoY29udGV4dC5sZWZ0KS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnRleHQubmVzdGVkID0gIWlzQXJyYXkoY29udGV4dC5kZWx0YSk7XG4gIGlmIChjb250ZXh0Lm5lc3RlZCkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoY29udGV4dC5kZWx0YS5sZW5ndGggPT09IDEpIHtcbiAgICBjb250ZXh0LnNldFJlc3VsdChjb250ZXh0LmRlbHRhWzBdKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChjb250ZXh0LmRlbHRhLmxlbmd0aCA9PT0gMikge1xuICAgIGlmIChjb250ZXh0LmxlZnQgaW5zdGFuY2VvZiBSZWdFeHApIHtcbiAgICAgIHZhciByZWdleEFyZ3MgPSAvXlxcLyguKilcXC8oW2dpbXl1XSspJC8uZXhlYyhjb250ZXh0LmRlbHRhWzFdKTtcbiAgICAgIGlmIChyZWdleEFyZ3MpIHtcbiAgICAgICAgY29udGV4dC5zZXRSZXN1bHQobmV3IFJlZ0V4cChyZWdleEFyZ3NbMV0sIHJlZ2V4QXJnc1syXSkpLmV4aXQoKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH1cbiAgICBjb250ZXh0LnNldFJlc3VsdChjb250ZXh0LmRlbHRhWzFdKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChjb250ZXh0LmRlbHRhLmxlbmd0aCA9PT0gMyAmJiBjb250ZXh0LmRlbHRhWzJdID09PSAwKSB7XG4gICAgY29udGV4dC5zZXRSZXN1bHQodW5kZWZpbmVkKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG59O1xucGF0Y2hGaWx0ZXIuZmlsdGVyTmFtZSA9ICd0cml2aWFsJztcblxudmFyIHJldmVyc2VGaWx0ZXIgPSBmdW5jdGlvbiB0cml2aWFsUmVmZXJzZUZpbHRlcihjb250ZXh0KSB7XG4gIGlmICh0eXBlb2YgY29udGV4dC5kZWx0YSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBjb250ZXh0LnNldFJlc3VsdChjb250ZXh0LmRlbHRhKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnRleHQubmVzdGVkID0gIWlzQXJyYXkoY29udGV4dC5kZWx0YSk7XG4gIGlmIChjb250ZXh0Lm5lc3RlZCkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoY29udGV4dC5kZWx0YS5sZW5ndGggPT09IDEpIHtcbiAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5kZWx0YVswXSwgMCwgMF0pLmV4aXQoKTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGNvbnRleHQuZGVsdGEubGVuZ3RoID09PSAyKSB7XG4gICAgY29udGV4dC5zZXRSZXN1bHQoW2NvbnRleHQuZGVsdGFbMV0sIGNvbnRleHQuZGVsdGFbMF1dKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChjb250ZXh0LmRlbHRhLmxlbmd0aCA9PT0gMyAmJiBjb250ZXh0LmRlbHRhWzJdID09PSAwKSB7XG4gICAgY29udGV4dC5zZXRSZXN1bHQoW2NvbnRleHQuZGVsdGFbMF1dKS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG59O1xucmV2ZXJzZUZpbHRlci5maWx0ZXJOYW1lID0gJ3RyaXZpYWwnO1xuXG5leHBvcnRzLmRpZmZGaWx0ZXIgPSBkaWZmRmlsdGVyO1xuZXhwb3J0cy5wYXRjaEZpbHRlciA9IHBhdGNoRmlsdGVyO1xuZXhwb3J0cy5yZXZlcnNlRmlsdGVyID0gcmV2ZXJzZUZpbHRlcjtcbiIsInZhciBEaWZmQ29udGV4dCA9IHJlcXVpcmUoJy4uL2NvbnRleHRzL2RpZmYnKS5EaWZmQ29udGV4dDtcbnZhciBQYXRjaENvbnRleHQgPSByZXF1aXJlKCcuLi9jb250ZXh0cy9wYXRjaCcpLlBhdGNoQ29udGV4dDtcbnZhciBSZXZlcnNlQ29udGV4dCA9IHJlcXVpcmUoJy4uL2NvbnRleHRzL3JldmVyc2UnKS5SZXZlcnNlQ29udGV4dDtcblxudmFyIGNvbGxlY3RDaGlsZHJlbkRpZmZGaWx0ZXIgPSBmdW5jdGlvbiBjb2xsZWN0Q2hpbGRyZW5EaWZmRmlsdGVyKGNvbnRleHQpIHtcbiAgaWYgKCFjb250ZXh0IHx8ICFjb250ZXh0LmNoaWxkcmVuKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBsZW5ndGggPSBjb250ZXh0LmNoaWxkcmVuLmxlbmd0aDtcbiAgdmFyIGNoaWxkO1xuICB2YXIgcmVzdWx0ID0gY29udGV4dC5yZXN1bHQ7XG4gIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICBjaGlsZCA9IGNvbnRleHQuY2hpbGRyZW5baW5kZXhdO1xuICAgIGlmICh0eXBlb2YgY2hpbGQucmVzdWx0ID09PSAndW5kZWZpbmVkJykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHJlc3VsdCA9IHJlc3VsdCB8fCB7fTtcbiAgICByZXN1bHRbY2hpbGQuY2hpbGROYW1lXSA9IGNoaWxkLnJlc3VsdDtcbiAgfVxuICBpZiAocmVzdWx0ICYmIGNvbnRleHQubGVmdElzQXJyYXkpIHtcbiAgICByZXN1bHQuX3QgPSAnYSc7XG4gIH1cbiAgY29udGV4dC5zZXRSZXN1bHQocmVzdWx0KS5leGl0KCk7XG59O1xuY29sbGVjdENoaWxkcmVuRGlmZkZpbHRlci5maWx0ZXJOYW1lID0gJ2NvbGxlY3RDaGlsZHJlbic7XG5cbnZhciBvYmplY3RzRGlmZkZpbHRlciA9IGZ1bmN0aW9uIG9iamVjdHNEaWZmRmlsdGVyKGNvbnRleHQpIHtcbiAgaWYgKGNvbnRleHQubGVmdElzQXJyYXkgfHwgY29udGV4dC5sZWZ0VHlwZSAhPT0gJ29iamVjdCcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICB2YXIgbmFtZSwgY2hpbGQsIHByb3BlcnR5RmlsdGVyID0gY29udGV4dC5vcHRpb25zLnByb3BlcnR5RmlsdGVyO1xuICBmb3IgKG5hbWUgaW4gY29udGV4dC5sZWZ0KSB7XG4gICAgaWYgKCFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoY29udGV4dC5sZWZ0LCBuYW1lKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChwcm9wZXJ0eUZpbHRlciAmJiAhcHJvcGVydHlGaWx0ZXIobmFtZSwgY29udGV4dCkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBjaGlsZCA9IG5ldyBEaWZmQ29udGV4dChjb250ZXh0LmxlZnRbbmFtZV0sIGNvbnRleHQucmlnaHRbbmFtZV0pO1xuICAgIGNvbnRleHQucHVzaChjaGlsZCwgbmFtZSk7XG4gIH1cbiAgZm9yIChuYW1lIGluIGNvbnRleHQucmlnaHQpIHtcbiAgICBpZiAoIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChjb250ZXh0LnJpZ2h0LCBuYW1lKSkge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChwcm9wZXJ0eUZpbHRlciAmJiAhcHJvcGVydHlGaWx0ZXIobmFtZSwgY29udGV4dCkpIHtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAodHlwZW9mIGNvbnRleHQubGVmdFtuYW1lXSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGNoaWxkID0gbmV3IERpZmZDb250ZXh0KHVuZGVmaW5lZCwgY29udGV4dC5yaWdodFtuYW1lXSk7XG4gICAgICBjb250ZXh0LnB1c2goY2hpbGQsIG5hbWUpO1xuICAgIH1cbiAgfVxuXG4gIGlmICghY29udGV4dC5jaGlsZHJlbiB8fCBjb250ZXh0LmNoaWxkcmVuLmxlbmd0aCA9PT0gMCkge1xuICAgIGNvbnRleHQuc2V0UmVzdWx0KHVuZGVmaW5lZCkuZXhpdCgpO1xuICAgIHJldHVybjtcbiAgfVxuICBjb250ZXh0LmV4aXQoKTtcbn07XG5vYmplY3RzRGlmZkZpbHRlci5maWx0ZXJOYW1lID0gJ29iamVjdHMnO1xuXG52YXIgcGF0Y2hGaWx0ZXIgPSBmdW5jdGlvbiBuZXN0ZWRQYXRjaEZpbHRlcihjb250ZXh0KSB7XG4gIGlmICghY29udGV4dC5uZXN0ZWQpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGNvbnRleHQuZGVsdGEuX3QpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIG5hbWUsIGNoaWxkO1xuICBmb3IgKG5hbWUgaW4gY29udGV4dC5kZWx0YSkge1xuICAgIGNoaWxkID0gbmV3IFBhdGNoQ29udGV4dChjb250ZXh0LmxlZnRbbmFtZV0sIGNvbnRleHQuZGVsdGFbbmFtZV0pO1xuICAgIGNvbnRleHQucHVzaChjaGlsZCwgbmFtZSk7XG4gIH1cbiAgY29udGV4dC5leGl0KCk7XG59O1xucGF0Y2hGaWx0ZXIuZmlsdGVyTmFtZSA9ICdvYmplY3RzJztcblxudmFyIGNvbGxlY3RDaGlsZHJlblBhdGNoRmlsdGVyID0gZnVuY3Rpb24gY29sbGVjdENoaWxkcmVuUGF0Y2hGaWx0ZXIoY29udGV4dCkge1xuICBpZiAoIWNvbnRleHQgfHwgIWNvbnRleHQuY2hpbGRyZW4pIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGNvbnRleHQuZGVsdGEuX3QpIHtcbiAgICByZXR1cm47XG4gIH1cbiAgdmFyIGxlbmd0aCA9IGNvbnRleHQuY2hpbGRyZW4ubGVuZ3RoO1xuICB2YXIgY2hpbGQ7XG4gIGZvciAodmFyIGluZGV4ID0gMDsgaW5kZXggPCBsZW5ndGg7IGluZGV4KyspIHtcbiAgICBjaGlsZCA9IGNvbnRleHQuY2hpbGRyZW5baW5kZXhdO1xuICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoY29udGV4dC5sZWZ0LCBjaGlsZC5jaGlsZE5hbWUpICYmIGNoaWxkLnJlc3VsdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBkZWxldGUgY29udGV4dC5sZWZ0W2NoaWxkLmNoaWxkTmFtZV07XG4gICAgfSBlbHNlIGlmIChjb250ZXh0LmxlZnRbY2hpbGQuY2hpbGROYW1lXSAhPT0gY2hpbGQucmVzdWx0KSB7XG4gICAgICBjb250ZXh0LmxlZnRbY2hpbGQuY2hpbGROYW1lXSA9IGNoaWxkLnJlc3VsdDtcbiAgICB9XG4gIH1cbiAgY29udGV4dC5zZXRSZXN1bHQoY29udGV4dC5sZWZ0KS5leGl0KCk7XG59O1xuY29sbGVjdENoaWxkcmVuUGF0Y2hGaWx0ZXIuZmlsdGVyTmFtZSA9ICdjb2xsZWN0Q2hpbGRyZW4nO1xuXG52YXIgcmV2ZXJzZUZpbHRlciA9IGZ1bmN0aW9uIG5lc3RlZFJldmVyc2VGaWx0ZXIoY29udGV4dCkge1xuICBpZiAoIWNvbnRleHQubmVzdGVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChjb250ZXh0LmRlbHRhLl90KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBuYW1lLCBjaGlsZDtcbiAgZm9yIChuYW1lIGluIGNvbnRleHQuZGVsdGEpIHtcbiAgICBjaGlsZCA9IG5ldyBSZXZlcnNlQ29udGV4dChjb250ZXh0LmRlbHRhW25hbWVdKTtcbiAgICBjb250ZXh0LnB1c2goY2hpbGQsIG5hbWUpO1xuICB9XG4gIGNvbnRleHQuZXhpdCgpO1xufTtcbnJldmVyc2VGaWx0ZXIuZmlsdGVyTmFtZSA9ICdvYmplY3RzJztcblxudmFyIGNvbGxlY3RDaGlsZHJlblJldmVyc2VGaWx0ZXIgPSBmdW5jdGlvbiBjb2xsZWN0Q2hpbGRyZW5SZXZlcnNlRmlsdGVyKGNvbnRleHQpIHtcbiAgaWYgKCFjb250ZXh0IHx8ICFjb250ZXh0LmNoaWxkcmVuKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChjb250ZXh0LmRlbHRhLl90KSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBsZW5ndGggPSBjb250ZXh0LmNoaWxkcmVuLmxlbmd0aDtcbiAgdmFyIGNoaWxkO1xuICB2YXIgZGVsdGEgPSB7fTtcbiAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgIGNoaWxkID0gY29udGV4dC5jaGlsZHJlbltpbmRleF07XG4gICAgaWYgKGRlbHRhW2NoaWxkLmNoaWxkTmFtZV0gIT09IGNoaWxkLnJlc3VsdCkge1xuICAgICAgZGVsdGFbY2hpbGQuY2hpbGROYW1lXSA9IGNoaWxkLnJlc3VsdDtcbiAgICB9XG4gIH1cbiAgY29udGV4dC5zZXRSZXN1bHQoZGVsdGEpLmV4aXQoKTtcbn07XG5jb2xsZWN0Q2hpbGRyZW5SZXZlcnNlRmlsdGVyLmZpbHRlck5hbWUgPSAnY29sbGVjdENoaWxkcmVuJztcblxuZXhwb3J0cy5jb2xsZWN0Q2hpbGRyZW5EaWZmRmlsdGVyID0gY29sbGVjdENoaWxkcmVuRGlmZkZpbHRlcjtcbmV4cG9ydHMub2JqZWN0c0RpZmZGaWx0ZXIgPSBvYmplY3RzRGlmZkZpbHRlcjtcbmV4cG9ydHMucGF0Y2hGaWx0ZXIgPSBwYXRjaEZpbHRlcjtcbmV4cG9ydHMuY29sbGVjdENoaWxkcmVuUGF0Y2hGaWx0ZXIgPSBjb2xsZWN0Q2hpbGRyZW5QYXRjaEZpbHRlcjtcbmV4cG9ydHMucmV2ZXJzZUZpbHRlciA9IHJldmVyc2VGaWx0ZXI7XG5leHBvcnRzLmNvbGxlY3RDaGlsZHJlblJldmVyc2VGaWx0ZXIgPSBjb2xsZWN0Q2hpbGRyZW5SZXZlcnNlRmlsdGVyO1xuIiwiLypcblxuTENTIGltcGxlbWVudGF0aW9uIHRoYXQgc3VwcG9ydHMgYXJyYXlzIG9yIHN0cmluZ3NcblxucmVmZXJlbmNlOiBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0xvbmdlc3RfY29tbW9uX3N1YnNlcXVlbmNlX3Byb2JsZW1cblxuKi9cblxudmFyIGRlZmF1bHRNYXRjaCA9IGZ1bmN0aW9uKGFycmF5MSwgYXJyYXkyLCBpbmRleDEsIGluZGV4Mikge1xuICByZXR1cm4gYXJyYXkxW2luZGV4MV0gPT09IGFycmF5MltpbmRleDJdO1xufTtcblxudmFyIGxlbmd0aE1hdHJpeCA9IGZ1bmN0aW9uKGFycmF5MSwgYXJyYXkyLCBtYXRjaCwgY29udGV4dCkge1xuICB2YXIgbGVuMSA9IGFycmF5MS5sZW5ndGg7XG4gIHZhciBsZW4yID0gYXJyYXkyLmxlbmd0aDtcbiAgdmFyIHgsIHk7XG5cbiAgLy8gaW5pdGlhbGl6ZSBlbXB0eSBtYXRyaXggb2YgbGVuMSsxIHggbGVuMisxXG4gIHZhciBtYXRyaXggPSBbbGVuMSArIDFdO1xuICBmb3IgKHggPSAwOyB4IDwgbGVuMSArIDE7IHgrKykge1xuICAgIG1hdHJpeFt4XSA9IFtsZW4yICsgMV07XG4gICAgZm9yICh5ID0gMDsgeSA8IGxlbjIgKyAxOyB5KyspIHtcbiAgICAgIG1hdHJpeFt4XVt5XSA9IDA7XG4gICAgfVxuICB9XG4gIG1hdHJpeC5tYXRjaCA9IG1hdGNoO1xuICAvLyBzYXZlIHNlcXVlbmNlIGxlbmd0aHMgZm9yIGVhY2ggY29vcmRpbmF0ZVxuICBmb3IgKHggPSAxOyB4IDwgbGVuMSArIDE7IHgrKykge1xuICAgIGZvciAoeSA9IDE7IHkgPCBsZW4yICsgMTsgeSsrKSB7XG4gICAgICBpZiAobWF0Y2goYXJyYXkxLCBhcnJheTIsIHggLSAxLCB5IC0gMSwgY29udGV4dCkpIHtcbiAgICAgICAgbWF0cml4W3hdW3ldID0gbWF0cml4W3ggLSAxXVt5IC0gMV0gKyAxO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWF0cml4W3hdW3ldID0gTWF0aC5tYXgobWF0cml4W3ggLSAxXVt5XSwgbWF0cml4W3hdW3kgLSAxXSk7XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiBtYXRyaXg7XG59O1xuXG52YXIgYmFja3RyYWNrID0gZnVuY3Rpb24obWF0cml4LCBhcnJheTEsIGFycmF5MiwgaW5kZXgxLCBpbmRleDIsIGNvbnRleHQpIHtcbiAgaWYgKGluZGV4MSA9PT0gMCB8fCBpbmRleDIgPT09IDApIHtcbiAgICByZXR1cm4ge1xuICAgICAgc2VxdWVuY2U6IFtdLFxuICAgICAgaW5kaWNlczE6IFtdLFxuICAgICAgaW5kaWNlczI6IFtdXG4gICAgfTtcbiAgfVxuXG4gIGlmIChtYXRyaXgubWF0Y2goYXJyYXkxLCBhcnJheTIsIGluZGV4MSAtIDEsIGluZGV4MiAtIDEsIGNvbnRleHQpKSB7XG4gICAgdmFyIHN1YnNlcXVlbmNlID0gYmFja3RyYWNrKG1hdHJpeCwgYXJyYXkxLCBhcnJheTIsIGluZGV4MSAtIDEsIGluZGV4MiAtIDEsIGNvbnRleHQpO1xuICAgIHN1YnNlcXVlbmNlLnNlcXVlbmNlLnB1c2goYXJyYXkxW2luZGV4MSAtIDFdKTtcbiAgICBzdWJzZXF1ZW5jZS5pbmRpY2VzMS5wdXNoKGluZGV4MSAtIDEpO1xuICAgIHN1YnNlcXVlbmNlLmluZGljZXMyLnB1c2goaW5kZXgyIC0gMSk7XG4gICAgcmV0dXJuIHN1YnNlcXVlbmNlO1xuICB9XG5cbiAgaWYgKG1hdHJpeFtpbmRleDFdW2luZGV4MiAtIDFdID4gbWF0cml4W2luZGV4MSAtIDFdW2luZGV4Ml0pIHtcbiAgICByZXR1cm4gYmFja3RyYWNrKG1hdHJpeCwgYXJyYXkxLCBhcnJheTIsIGluZGV4MSwgaW5kZXgyIC0gMSwgY29udGV4dCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGJhY2t0cmFjayhtYXRyaXgsIGFycmF5MSwgYXJyYXkyLCBpbmRleDEgLSAxLCBpbmRleDIsIGNvbnRleHQpO1xuICB9XG59O1xuXG52YXIgZ2V0ID0gZnVuY3Rpb24oYXJyYXkxLCBhcnJheTIsIG1hdGNoLCBjb250ZXh0KSB7XG4gIGNvbnRleHQgPSBjb250ZXh0IHx8IHt9O1xuICB2YXIgbWF0cml4ID0gbGVuZ3RoTWF0cml4KGFycmF5MSwgYXJyYXkyLCBtYXRjaCB8fCBkZWZhdWx0TWF0Y2gsIGNvbnRleHQpO1xuICB2YXIgcmVzdWx0ID0gYmFja3RyYWNrKG1hdHJpeCwgYXJyYXkxLCBhcnJheTIsIGFycmF5MS5sZW5ndGgsIGFycmF5Mi5sZW5ndGgsIGNvbnRleHQpO1xuICBpZiAodHlwZW9mIGFycmF5MSA9PT0gJ3N0cmluZycgJiYgdHlwZW9mIGFycmF5MiA9PT0gJ3N0cmluZycpIHtcbiAgICByZXN1bHQuc2VxdWVuY2UgPSByZXN1bHQuc2VxdWVuY2Uuam9pbignJyk7XG4gIH1cbiAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbmV4cG9ydHMuZ2V0ID0gZ2V0O1xuIiwidmFyIERpZmZDb250ZXh0ID0gcmVxdWlyZSgnLi4vY29udGV4dHMvZGlmZicpLkRpZmZDb250ZXh0O1xudmFyIFBhdGNoQ29udGV4dCA9IHJlcXVpcmUoJy4uL2NvbnRleHRzL3BhdGNoJykuUGF0Y2hDb250ZXh0O1xudmFyIFJldmVyc2VDb250ZXh0ID0gcmVxdWlyZSgnLi4vY29udGV4dHMvcmV2ZXJzZScpLlJldmVyc2VDb250ZXh0O1xuXG52YXIgbGNzID0gcmVxdWlyZSgnLi9sY3MnKTtcblxudmFyIEFSUkFZX01PVkUgPSAzO1xuXG52YXIgaXNBcnJheSA9ICh0eXBlb2YgQXJyYXkuaXNBcnJheSA9PT0gJ2Z1bmN0aW9uJykgP1xuICAvLyB1c2UgbmF0aXZlIGZ1bmN0aW9uXG4gIEFycmF5LmlzQXJyYXkgOlxuICAvLyB1c2UgaW5zdGFuY2VvZiBvcGVyYXRvclxuICBmdW5jdGlvbihhKSB7XG4gICAgcmV0dXJuIGEgaW5zdGFuY2VvZiBBcnJheTtcbiAgfTtcblxudmFyIGFycmF5SW5kZXhPZiA9IHR5cGVvZiBBcnJheS5wcm90b3R5cGUuaW5kZXhPZiA9PT0gJ2Z1bmN0aW9uJyA/XG4gIGZ1bmN0aW9uKGFycmF5LCBpdGVtKSB7XG4gICAgcmV0dXJuIGFycmF5LmluZGV4T2YoaXRlbSk7XG4gIH0gOiBmdW5jdGlvbihhcnJheSwgaXRlbSkge1xuICAgIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGg7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGFycmF5W2ldID09PSBpdGVtKSB7XG4gICAgICAgIHJldHVybiBpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gLTE7XG4gIH07XG5cbmZ1bmN0aW9uIGFycmF5c0hhdmVNYXRjaEJ5UmVmKGFycmF5MSwgYXJyYXkyLCBsZW4xLCBsZW4yKSB7XG4gIGZvciAodmFyIGluZGV4MSA9IDA7IGluZGV4MSA8IGxlbjE7IGluZGV4MSsrKSB7XG4gICAgdmFyIHZhbDEgPSBhcnJheTFbaW5kZXgxXTtcbiAgICBmb3IgKHZhciBpbmRleDIgPSAwOyBpbmRleDIgPCBsZW4yOyBpbmRleDIrKykge1xuICAgICAgdmFyIHZhbDIgPSBhcnJheTJbaW5kZXgyXTtcbiAgICAgIGlmIChpbmRleDEgIT09IGluZGV4MiAmJiB2YWwxID09PSB2YWwyKSB7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaEl0ZW1zKGFycmF5MSwgYXJyYXkyLCBpbmRleDEsIGluZGV4MiwgY29udGV4dCkge1xuICB2YXIgdmFsdWUxID0gYXJyYXkxW2luZGV4MV07XG4gIHZhciB2YWx1ZTIgPSBhcnJheTJbaW5kZXgyXTtcbiAgaWYgKHZhbHVlMSA9PT0gdmFsdWUyKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgaWYgKHR5cGVvZiB2YWx1ZTEgIT09ICdvYmplY3QnIHx8IHR5cGVvZiB2YWx1ZTIgIT09ICdvYmplY3QnKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHZhciBvYmplY3RIYXNoID0gY29udGV4dC5vYmplY3RIYXNoO1xuICBpZiAoIW9iamVjdEhhc2gpIHtcbiAgICAvLyBubyB3YXkgdG8gbWF0Y2ggb2JqZWN0cyB3YXMgcHJvdmlkZWQsIHRyeSBtYXRjaCBieSBwb3NpdGlvblxuICAgIHJldHVybiBjb250ZXh0Lm1hdGNoQnlQb3NpdGlvbiAmJiBpbmRleDEgPT09IGluZGV4MjtcbiAgfVxuICB2YXIgaGFzaDE7XG4gIHZhciBoYXNoMjtcbiAgaWYgKHR5cGVvZiBpbmRleDEgPT09ICdudW1iZXInKSB7XG4gICAgY29udGV4dC5oYXNoQ2FjaGUxID0gY29udGV4dC5oYXNoQ2FjaGUxIHx8IFtdO1xuICAgIGhhc2gxID0gY29udGV4dC5oYXNoQ2FjaGUxW2luZGV4MV07XG4gICAgaWYgKHR5cGVvZiBoYXNoMSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGNvbnRleHQuaGFzaENhY2hlMVtpbmRleDFdID0gaGFzaDEgPSBvYmplY3RIYXNoKHZhbHVlMSwgaW5kZXgxKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaGFzaDEgPSBvYmplY3RIYXNoKHZhbHVlMSk7XG4gIH1cbiAgaWYgKHR5cGVvZiBoYXNoMSA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKHR5cGVvZiBpbmRleDIgPT09ICdudW1iZXInKSB7XG4gICAgY29udGV4dC5oYXNoQ2FjaGUyID0gY29udGV4dC5oYXNoQ2FjaGUyIHx8IFtdO1xuICAgIGhhc2gyID0gY29udGV4dC5oYXNoQ2FjaGUyW2luZGV4Ml07XG4gICAgaWYgKHR5cGVvZiBoYXNoMiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIGNvbnRleHQuaGFzaENhY2hlMltpbmRleDJdID0gaGFzaDIgPSBvYmplY3RIYXNoKHZhbHVlMiwgaW5kZXgyKTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgaGFzaDIgPSBvYmplY3RIYXNoKHZhbHVlMik7XG4gIH1cbiAgaWYgKHR5cGVvZiBoYXNoMiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIGhhc2gxID09PSBoYXNoMjtcbn1cblxudmFyIGRpZmZGaWx0ZXIgPSBmdW5jdGlvbiBhcnJheXNEaWZmRmlsdGVyKGNvbnRleHQpIHtcbiAgaWYgKCFjb250ZXh0LmxlZnRJc0FycmF5KSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdmFyIG1hdGNoQ29udGV4dCA9IHtcbiAgICBvYmplY3RIYXNoOiBjb250ZXh0Lm9wdGlvbnMgJiYgY29udGV4dC5vcHRpb25zLm9iamVjdEhhc2gsXG4gICAgbWF0Y2hCeVBvc2l0aW9uOiBjb250ZXh0Lm9wdGlvbnMgJiYgY29udGV4dC5vcHRpb25zLm1hdGNoQnlQb3NpdGlvblxuICB9O1xuICB2YXIgY29tbW9uSGVhZCA9IDA7XG4gIHZhciBjb21tb25UYWlsID0gMDtcbiAgdmFyIGluZGV4O1xuICB2YXIgaW5kZXgxO1xuICB2YXIgaW5kZXgyO1xuICB2YXIgYXJyYXkxID0gY29udGV4dC5sZWZ0O1xuICB2YXIgYXJyYXkyID0gY29udGV4dC5yaWdodDtcbiAgdmFyIGxlbjEgPSBhcnJheTEubGVuZ3RoO1xuICB2YXIgbGVuMiA9IGFycmF5Mi5sZW5ndGg7XG5cbiAgdmFyIGNoaWxkO1xuXG4gIGlmIChsZW4xID4gMCAmJiBsZW4yID4gMCAmJiAhbWF0Y2hDb250ZXh0Lm9iamVjdEhhc2ggJiZcbiAgICB0eXBlb2YgbWF0Y2hDb250ZXh0Lm1hdGNoQnlQb3NpdGlvbiAhPT0gJ2Jvb2xlYW4nKSB7XG4gICAgbWF0Y2hDb250ZXh0Lm1hdGNoQnlQb3NpdGlvbiA9ICFhcnJheXNIYXZlTWF0Y2hCeVJlZihhcnJheTEsIGFycmF5MiwgbGVuMSwgbGVuMik7XG4gIH1cblxuICAvLyBzZXBhcmF0ZSBjb21tb24gaGVhZFxuICB3aGlsZSAoY29tbW9uSGVhZCA8IGxlbjEgJiYgY29tbW9uSGVhZCA8IGxlbjIgJiZcbiAgICBtYXRjaEl0ZW1zKGFycmF5MSwgYXJyYXkyLCBjb21tb25IZWFkLCBjb21tb25IZWFkLCBtYXRjaENvbnRleHQpKSB7XG4gICAgaW5kZXggPSBjb21tb25IZWFkO1xuICAgIGNoaWxkID0gbmV3IERpZmZDb250ZXh0KGNvbnRleHQubGVmdFtpbmRleF0sIGNvbnRleHQucmlnaHRbaW5kZXhdKTtcbiAgICBjb250ZXh0LnB1c2goY2hpbGQsIGluZGV4KTtcbiAgICBjb21tb25IZWFkKys7XG4gIH1cbiAgLy8gc2VwYXJhdGUgY29tbW9uIHRhaWxcbiAgd2hpbGUgKGNvbW1vblRhaWwgKyBjb21tb25IZWFkIDwgbGVuMSAmJiBjb21tb25UYWlsICsgY29tbW9uSGVhZCA8IGxlbjIgJiZcbiAgICBtYXRjaEl0ZW1zKGFycmF5MSwgYXJyYXkyLCBsZW4xIC0gMSAtIGNvbW1vblRhaWwsIGxlbjIgLSAxIC0gY29tbW9uVGFpbCwgbWF0Y2hDb250ZXh0KSkge1xuICAgIGluZGV4MSA9IGxlbjEgLSAxIC0gY29tbW9uVGFpbDtcbiAgICBpbmRleDIgPSBsZW4yIC0gMSAtIGNvbW1vblRhaWw7XG4gICAgY2hpbGQgPSBuZXcgRGlmZkNvbnRleHQoY29udGV4dC5sZWZ0W2luZGV4MV0sIGNvbnRleHQucmlnaHRbaW5kZXgyXSk7XG4gICAgY29udGV4dC5wdXNoKGNoaWxkLCBpbmRleDIpO1xuICAgIGNvbW1vblRhaWwrKztcbiAgfVxuICB2YXIgcmVzdWx0O1xuICBpZiAoY29tbW9uSGVhZCArIGNvbW1vblRhaWwgPT09IGxlbjEpIHtcbiAgICBpZiAobGVuMSA9PT0gbGVuMikge1xuICAgICAgLy8gYXJyYXlzIGFyZSBpZGVudGljYWxcbiAgICAgIGNvbnRleHQuc2V0UmVzdWx0KHVuZGVmaW5lZCkuZXhpdCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICAvLyB0cml2aWFsIGNhc2UsIGEgYmxvY2sgKDEgb3IgbW9yZSBjb25zZWN1dGl2ZSBpdGVtcykgd2FzIGFkZGVkXG4gICAgcmVzdWx0ID0gcmVzdWx0IHx8IHtcbiAgICAgIF90OiAnYSdcbiAgICB9O1xuICAgIGZvciAoaW5kZXggPSBjb21tb25IZWFkOyBpbmRleCA8IGxlbjIgLSBjb21tb25UYWlsOyBpbmRleCsrKSB7XG4gICAgICByZXN1bHRbaW5kZXhdID0gW2FycmF5MltpbmRleF1dO1xuICAgIH1cbiAgICBjb250ZXh0LnNldFJlc3VsdChyZXN1bHQpLmV4aXQoKTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGNvbW1vbkhlYWQgKyBjb21tb25UYWlsID09PSBsZW4yKSB7XG4gICAgLy8gdHJpdmlhbCBjYXNlLCBhIGJsb2NrICgxIG9yIG1vcmUgY29uc2VjdXRpdmUgaXRlbXMpIHdhcyByZW1vdmVkXG4gICAgcmVzdWx0ID0gcmVzdWx0IHx8IHtcbiAgICAgIF90OiAnYSdcbiAgICB9O1xuICAgIGZvciAoaW5kZXggPSBjb21tb25IZWFkOyBpbmRleCA8IGxlbjEgLSBjb21tb25UYWlsOyBpbmRleCsrKSB7XG4gICAgICByZXN1bHRbJ18nICsgaW5kZXhdID0gW2FycmF5MVtpbmRleF0sIDAsIDBdO1xuICAgIH1cbiAgICBjb250ZXh0LnNldFJlc3VsdChyZXN1bHQpLmV4aXQoKTtcbiAgICByZXR1cm47XG4gIH1cbiAgLy8gcmVzZXQgaGFzaCBjYWNoZVxuICBkZWxldGUgbWF0Y2hDb250ZXh0Lmhhc2hDYWNoZTE7XG4gIGRlbGV0ZSBtYXRjaENvbnRleHQuaGFzaENhY2hlMjtcblxuICAvLyBkaWZmIGlzIG5vdCB0cml2aWFsLCBmaW5kIHRoZSBMQ1MgKExvbmdlc3QgQ29tbW9uIFN1YnNlcXVlbmNlKVxuICB2YXIgdHJpbW1lZDEgPSBhcnJheTEuc2xpY2UoY29tbW9uSGVhZCwgbGVuMSAtIGNvbW1vblRhaWwpO1xuICB2YXIgdHJpbW1lZDIgPSBhcnJheTIuc2xpY2UoY29tbW9uSGVhZCwgbGVuMiAtIGNvbW1vblRhaWwpO1xuICB2YXIgc2VxID0gbGNzLmdldChcbiAgICB0cmltbWVkMSwgdHJpbW1lZDIsXG4gICAgbWF0Y2hJdGVtcyxcbiAgICBtYXRjaENvbnRleHRcbiAgKTtcbiAgdmFyIHJlbW92ZWRJdGVtcyA9IFtdO1xuICByZXN1bHQgPSByZXN1bHQgfHwge1xuICAgIF90OiAnYSdcbiAgfTtcbiAgZm9yIChpbmRleCA9IGNvbW1vbkhlYWQ7IGluZGV4IDwgbGVuMSAtIGNvbW1vblRhaWw7IGluZGV4KyspIHtcbiAgICBpZiAoYXJyYXlJbmRleE9mKHNlcS5pbmRpY2VzMSwgaW5kZXggLSBjb21tb25IZWFkKSA8IDApIHtcbiAgICAgIC8vIHJlbW92ZWRcbiAgICAgIHJlc3VsdFsnXycgKyBpbmRleF0gPSBbYXJyYXkxW2luZGV4XSwgMCwgMF07XG4gICAgICByZW1vdmVkSXRlbXMucHVzaChpbmRleCk7XG4gICAgfVxuICB9XG5cbiAgdmFyIGRldGVjdE1vdmUgPSB0cnVlO1xuICBpZiAoY29udGV4dC5vcHRpb25zICYmIGNvbnRleHQub3B0aW9ucy5hcnJheXMgJiYgY29udGV4dC5vcHRpb25zLmFycmF5cy5kZXRlY3RNb3ZlID09PSBmYWxzZSkge1xuICAgIGRldGVjdE1vdmUgPSBmYWxzZTtcbiAgfVxuICB2YXIgaW5jbHVkZVZhbHVlT25Nb3ZlID0gZmFsc2U7XG4gIGlmIChjb250ZXh0Lm9wdGlvbnMgJiYgY29udGV4dC5vcHRpb25zLmFycmF5cyAmJiBjb250ZXh0Lm9wdGlvbnMuYXJyYXlzLmluY2x1ZGVWYWx1ZU9uTW92ZSkge1xuICAgIGluY2x1ZGVWYWx1ZU9uTW92ZSA9IHRydWU7XG4gIH1cblxuICB2YXIgcmVtb3ZlZEl0ZW1zTGVuZ3RoID0gcmVtb3ZlZEl0ZW1zLmxlbmd0aDtcbiAgZm9yIChpbmRleCA9IGNvbW1vbkhlYWQ7IGluZGV4IDwgbGVuMiAtIGNvbW1vblRhaWw7IGluZGV4KyspIHtcbiAgICB2YXIgaW5kZXhPbkFycmF5MiA9IGFycmF5SW5kZXhPZihzZXEuaW5kaWNlczIsIGluZGV4IC0gY29tbW9uSGVhZCk7XG4gICAgaWYgKGluZGV4T25BcnJheTIgPCAwKSB7XG4gICAgICAvLyBhZGRlZCwgdHJ5IHRvIG1hdGNoIHdpdGggYSByZW1vdmVkIGl0ZW0gYW5kIHJlZ2lzdGVyIGFzIHBvc2l0aW9uIG1vdmVcbiAgICAgIHZhciBpc01vdmUgPSBmYWxzZTtcbiAgICAgIGlmIChkZXRlY3RNb3ZlICYmIHJlbW92ZWRJdGVtc0xlbmd0aCA+IDApIHtcbiAgICAgICAgZm9yICh2YXIgcmVtb3ZlSXRlbUluZGV4MSA9IDA7IHJlbW92ZUl0ZW1JbmRleDEgPCByZW1vdmVkSXRlbXNMZW5ndGg7IHJlbW92ZUl0ZW1JbmRleDErKykge1xuICAgICAgICAgIGluZGV4MSA9IHJlbW92ZWRJdGVtc1tyZW1vdmVJdGVtSW5kZXgxXTtcbiAgICAgICAgICBpZiAobWF0Y2hJdGVtcyh0cmltbWVkMSwgdHJpbW1lZDIsIGluZGV4MSAtIGNvbW1vbkhlYWQsXG4gICAgICAgICAgICBpbmRleCAtIGNvbW1vbkhlYWQsIG1hdGNoQ29udGV4dCkpIHtcbiAgICAgICAgICAgIC8vIHN0b3JlIHBvc2l0aW9uIG1vdmUgYXM6IFtvcmlnaW5hbFZhbHVlLCBuZXdQb3NpdGlvbiwgQVJSQVlfTU9WRV1cbiAgICAgICAgICAgIHJlc3VsdFsnXycgKyBpbmRleDFdLnNwbGljZSgxLCAyLCBpbmRleCwgQVJSQVlfTU9WRSk7XG4gICAgICAgICAgICBpZiAoIWluY2x1ZGVWYWx1ZU9uTW92ZSkge1xuICAgICAgICAgICAgICAvLyBkb24ndCBpbmNsdWRlIG1vdmVkIHZhbHVlIG9uIGRpZmYsIHRvIHNhdmUgYnl0ZXNcbiAgICAgICAgICAgICAgcmVzdWx0WydfJyArIGluZGV4MV1bMF0gPSAnJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaW5kZXgyID0gaW5kZXg7XG4gICAgICAgICAgICBjaGlsZCA9IG5ldyBEaWZmQ29udGV4dChjb250ZXh0LmxlZnRbaW5kZXgxXSwgY29udGV4dC5yaWdodFtpbmRleDJdKTtcbiAgICAgICAgICAgIGNvbnRleHQucHVzaChjaGlsZCwgaW5kZXgyKTtcbiAgICAgICAgICAgIHJlbW92ZWRJdGVtcy5zcGxpY2UocmVtb3ZlSXRlbUluZGV4MSwgMSk7XG4gICAgICAgICAgICBpc01vdmUgPSB0cnVlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoIWlzTW92ZSkge1xuICAgICAgICAvLyBhZGRlZFxuICAgICAgICByZXN1bHRbaW5kZXhdID0gW2FycmF5MltpbmRleF1dO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBtYXRjaCwgZG8gaW5uZXIgZGlmZlxuICAgICAgaW5kZXgxID0gc2VxLmluZGljZXMxW2luZGV4T25BcnJheTJdICsgY29tbW9uSGVhZDtcbiAgICAgIGluZGV4MiA9IHNlcS5pbmRpY2VzMltpbmRleE9uQXJyYXkyXSArIGNvbW1vbkhlYWQ7XG4gICAgICBjaGlsZCA9IG5ldyBEaWZmQ29udGV4dChjb250ZXh0LmxlZnRbaW5kZXgxXSwgY29udGV4dC5yaWdodFtpbmRleDJdKTtcbiAgICAgIGNvbnRleHQucHVzaChjaGlsZCwgaW5kZXgyKTtcbiAgICB9XG4gIH1cblxuICBjb250ZXh0LnNldFJlc3VsdChyZXN1bHQpLmV4aXQoKTtcblxufTtcbmRpZmZGaWx0ZXIuZmlsdGVyTmFtZSA9ICdhcnJheXMnO1xuXG52YXIgY29tcGFyZSA9IHtcbiAgbnVtZXJpY2FsbHk6IGZ1bmN0aW9uKGEsIGIpIHtcbiAgICByZXR1cm4gYSAtIGI7XG4gIH0sXG4gIG51bWVyaWNhbGx5Qnk6IGZ1bmN0aW9uKG5hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24oYSwgYikge1xuICAgICAgcmV0dXJuIGFbbmFtZV0gLSBiW25hbWVdO1xuICAgIH07XG4gIH1cbn07XG5cbnZhciBwYXRjaEZpbHRlciA9IGZ1bmN0aW9uIG5lc3RlZFBhdGNoRmlsdGVyKGNvbnRleHQpIHtcbiAgaWYgKCFjb250ZXh0Lm5lc3RlZCkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoY29udGV4dC5kZWx0YS5fdCAhPT0gJ2EnKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBpbmRleCwgaW5kZXgxO1xuXG4gIHZhciBkZWx0YSA9IGNvbnRleHQuZGVsdGE7XG4gIHZhciBhcnJheSA9IGNvbnRleHQubGVmdDtcblxuICAvLyBmaXJzdCwgc2VwYXJhdGUgcmVtb3ZhbHMsIGluc2VydGlvbnMgYW5kIG1vZGlmaWNhdGlvbnNcbiAgdmFyIHRvUmVtb3ZlID0gW107XG4gIHZhciB0b0luc2VydCA9IFtdO1xuICB2YXIgdG9Nb2RpZnkgPSBbXTtcbiAgZm9yIChpbmRleCBpbiBkZWx0YSkge1xuICAgIGlmIChpbmRleCAhPT0gJ190Jykge1xuICAgICAgaWYgKGluZGV4WzBdID09PSAnXycpIHtcbiAgICAgICAgLy8gcmVtb3ZlZCBpdGVtIGZyb20gb3JpZ2luYWwgYXJyYXlcbiAgICAgICAgaWYgKGRlbHRhW2luZGV4XVsyXSA9PT0gMCB8fCBkZWx0YVtpbmRleF1bMl0gPT09IEFSUkFZX01PVkUpIHtcbiAgICAgICAgICB0b1JlbW92ZS5wdXNoKHBhcnNlSW50KGluZGV4LnNsaWNlKDEpLCAxMCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRocm93IG5ldyBFcnJvcignb25seSByZW1vdmFsIG9yIG1vdmUgY2FuIGJlIGFwcGxpZWQgYXQgb3JpZ2luYWwgYXJyYXkgaW5kaWNlcycgK1xuICAgICAgICAgICAgJywgaW52YWxpZCBkaWZmIHR5cGU6ICcgKyBkZWx0YVtpbmRleF1bMl0pO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoZGVsdGFbaW5kZXhdLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgIC8vIGFkZGVkIGl0ZW0gYXQgbmV3IGFycmF5XG4gICAgICAgICAgdG9JbnNlcnQucHVzaCh7XG4gICAgICAgICAgICBpbmRleDogcGFyc2VJbnQoaW5kZXgsIDEwKSxcbiAgICAgICAgICAgIHZhbHVlOiBkZWx0YVtpbmRleF1bMF1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBtb2RpZmllZCBpdGVtIGF0IG5ldyBhcnJheVxuICAgICAgICAgIHRvTW9kaWZ5LnB1c2goe1xuICAgICAgICAgICAgaW5kZXg6IHBhcnNlSW50KGluZGV4LCAxMCksXG4gICAgICAgICAgICBkZWx0YTogZGVsdGFbaW5kZXhdXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvLyByZW1vdmUgaXRlbXMsIGluIHJldmVyc2Ugb3JkZXIgdG8gYXZvaWQgc2F3aW5nIG91ciBvd24gZmxvb3JcbiAgdG9SZW1vdmUgPSB0b1JlbW92ZS5zb3J0KGNvbXBhcmUubnVtZXJpY2FsbHkpO1xuICBmb3IgKGluZGV4ID0gdG9SZW1vdmUubGVuZ3RoIC0gMTsgaW5kZXggPj0gMDsgaW5kZXgtLSkge1xuICAgIGluZGV4MSA9IHRvUmVtb3ZlW2luZGV4XTtcbiAgICB2YXIgaW5kZXhEaWZmID0gZGVsdGFbJ18nICsgaW5kZXgxXTtcbiAgICB2YXIgcmVtb3ZlZFZhbHVlID0gYXJyYXkuc3BsaWNlKGluZGV4MSwgMSlbMF07XG4gICAgaWYgKGluZGV4RGlmZlsyXSA9PT0gQVJSQVlfTU9WRSkge1xuICAgICAgLy8gcmVpbnNlcnQgbGF0ZXJcbiAgICAgIHRvSW5zZXJ0LnB1c2goe1xuICAgICAgICBpbmRleDogaW5kZXhEaWZmWzFdLFxuICAgICAgICB2YWx1ZTogcmVtb3ZlZFZhbHVlXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvLyBpbnNlcnQgaXRlbXMsIGluIHJldmVyc2Ugb3JkZXIgdG8gYXZvaWQgbW92aW5nIG91ciBvd24gZmxvb3JcbiAgdG9JbnNlcnQgPSB0b0luc2VydC5zb3J0KGNvbXBhcmUubnVtZXJpY2FsbHlCeSgnaW5kZXgnKSk7XG4gIHZhciB0b0luc2VydExlbmd0aCA9IHRvSW5zZXJ0Lmxlbmd0aDtcbiAgZm9yIChpbmRleCA9IDA7IGluZGV4IDwgdG9JbnNlcnRMZW5ndGg7IGluZGV4KyspIHtcbiAgICB2YXIgaW5zZXJ0aW9uID0gdG9JbnNlcnRbaW5kZXhdO1xuICAgIGFycmF5LnNwbGljZShpbnNlcnRpb24uaW5kZXgsIDAsIGluc2VydGlvbi52YWx1ZSk7XG4gIH1cblxuICAvLyBhcHBseSBtb2RpZmljYXRpb25zXG4gIHZhciB0b01vZGlmeUxlbmd0aCA9IHRvTW9kaWZ5Lmxlbmd0aDtcbiAgdmFyIGNoaWxkO1xuICBpZiAodG9Nb2RpZnlMZW5ndGggPiAwKSB7XG4gICAgZm9yIChpbmRleCA9IDA7IGluZGV4IDwgdG9Nb2RpZnlMZW5ndGg7IGluZGV4KyspIHtcbiAgICAgIHZhciBtb2RpZmljYXRpb24gPSB0b01vZGlmeVtpbmRleF07XG4gICAgICBjaGlsZCA9IG5ldyBQYXRjaENvbnRleHQoY29udGV4dC5sZWZ0W21vZGlmaWNhdGlvbi5pbmRleF0sIG1vZGlmaWNhdGlvbi5kZWx0YSk7XG4gICAgICBjb250ZXh0LnB1c2goY2hpbGQsIG1vZGlmaWNhdGlvbi5pbmRleCk7XG4gICAgfVxuICB9XG5cbiAgaWYgKCFjb250ZXh0LmNoaWxkcmVuKSB7XG4gICAgY29udGV4dC5zZXRSZXN1bHQoY29udGV4dC5sZWZ0KS5leGl0KCk7XG4gICAgcmV0dXJuO1xuICB9XG4gIGNvbnRleHQuZXhpdCgpO1xufTtcbnBhdGNoRmlsdGVyLmZpbHRlck5hbWUgPSAnYXJyYXlzJztcblxudmFyIGNvbGxlY3RDaGlsZHJlblBhdGNoRmlsdGVyID0gZnVuY3Rpb24gY29sbGVjdENoaWxkcmVuUGF0Y2hGaWx0ZXIoY29udGV4dCkge1xuICBpZiAoIWNvbnRleHQgfHwgIWNvbnRleHQuY2hpbGRyZW4pIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGNvbnRleHQuZGVsdGEuX3QgIT09ICdhJykge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgbGVuZ3RoID0gY29udGV4dC5jaGlsZHJlbi5sZW5ndGg7XG4gIHZhciBjaGlsZDtcbiAgZm9yICh2YXIgaW5kZXggPSAwOyBpbmRleCA8IGxlbmd0aDsgaW5kZXgrKykge1xuICAgIGNoaWxkID0gY29udGV4dC5jaGlsZHJlbltpbmRleF07XG4gICAgY29udGV4dC5sZWZ0W2NoaWxkLmNoaWxkTmFtZV0gPSBjaGlsZC5yZXN1bHQ7XG4gIH1cbiAgY29udGV4dC5zZXRSZXN1bHQoY29udGV4dC5sZWZ0KS5leGl0KCk7XG59O1xuY29sbGVjdENoaWxkcmVuUGF0Y2hGaWx0ZXIuZmlsdGVyTmFtZSA9ICdhcnJheXNDb2xsZWN0Q2hpbGRyZW4nO1xuXG52YXIgcmV2ZXJzZUZpbHRlciA9IGZ1bmN0aW9uIGFycmF5c1JldmVyc2VGaWx0ZXIoY29udGV4dCkge1xuICBpZiAoIWNvbnRleHQubmVzdGVkKSB7XG4gICAgaWYgKGNvbnRleHQuZGVsdGFbMl0gPT09IEFSUkFZX01PVkUpIHtcbiAgICAgIGNvbnRleHQubmV3TmFtZSA9ICdfJyArIGNvbnRleHQuZGVsdGFbMV07XG4gICAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5kZWx0YVswXSwgcGFyc2VJbnQoY29udGV4dC5jaGlsZE5hbWUuc3Vic3RyKDEpLCAxMCksIEFSUkFZX01PVkVdKS5leGl0KCk7XG4gICAgfVxuICAgIHJldHVybjtcbiAgfVxuICBpZiAoY29udGV4dC5kZWx0YS5fdCAhPT0gJ2EnKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHZhciBuYW1lLCBjaGlsZDtcbiAgZm9yIChuYW1lIGluIGNvbnRleHQuZGVsdGEpIHtcbiAgICBpZiAobmFtZSA9PT0gJ190Jykge1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGNoaWxkID0gbmV3IFJldmVyc2VDb250ZXh0KGNvbnRleHQuZGVsdGFbbmFtZV0pO1xuICAgIGNvbnRleHQucHVzaChjaGlsZCwgbmFtZSk7XG4gIH1cbiAgY29udGV4dC5leGl0KCk7XG59O1xucmV2ZXJzZUZpbHRlci5maWx0ZXJOYW1lID0gJ2FycmF5cyc7XG5cbnZhciByZXZlcnNlQXJyYXlEZWx0YUluZGV4ID0gZnVuY3Rpb24oZGVsdGEsIGluZGV4LCBpdGVtRGVsdGEpIHtcbiAgaWYgKHR5cGVvZiBpbmRleCA9PT0gJ3N0cmluZycgJiYgaW5kZXhbMF0gPT09ICdfJykge1xuICAgIHJldHVybiBwYXJzZUludChpbmRleC5zdWJzdHIoMSksIDEwKTtcbiAgfSBlbHNlIGlmIChpc0FycmF5KGl0ZW1EZWx0YSkgJiYgaXRlbURlbHRhWzJdID09PSAwKSB7XG4gICAgcmV0dXJuICdfJyArIGluZGV4O1xuICB9XG5cbiAgdmFyIHJldmVyc2VJbmRleCA9ICtpbmRleDtcbiAgZm9yICh2YXIgZGVsdGFJbmRleCBpbiBkZWx0YSkge1xuICAgIHZhciBkZWx0YUl0ZW0gPSBkZWx0YVtkZWx0YUluZGV4XTtcbiAgICBpZiAoaXNBcnJheShkZWx0YUl0ZW0pKSB7XG4gICAgICBpZiAoZGVsdGFJdGVtWzJdID09PSBBUlJBWV9NT1ZFKSB7XG4gICAgICAgIHZhciBtb3ZlRnJvbUluZGV4ID0gcGFyc2VJbnQoZGVsdGFJbmRleC5zdWJzdHIoMSksIDEwKTtcbiAgICAgICAgdmFyIG1vdmVUb0luZGV4ID0gZGVsdGFJdGVtWzFdO1xuICAgICAgICBpZiAobW92ZVRvSW5kZXggPT09ICtpbmRleCkge1xuICAgICAgICAgIHJldHVybiBtb3ZlRnJvbUluZGV4O1xuICAgICAgICB9XG4gICAgICAgIGlmIChtb3ZlRnJvbUluZGV4IDw9IHJldmVyc2VJbmRleCAmJiBtb3ZlVG9JbmRleCA+IHJldmVyc2VJbmRleCkge1xuICAgICAgICAgIHJldmVyc2VJbmRleCsrO1xuICAgICAgICB9IGVsc2UgaWYgKG1vdmVGcm9tSW5kZXggPj0gcmV2ZXJzZUluZGV4ICYmIG1vdmVUb0luZGV4IDwgcmV2ZXJzZUluZGV4KSB7XG4gICAgICAgICAgcmV2ZXJzZUluZGV4LS07XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoZGVsdGFJdGVtWzJdID09PSAwKSB7XG4gICAgICAgIHZhciBkZWxldGVJbmRleCA9IHBhcnNlSW50KGRlbHRhSW5kZXguc3Vic3RyKDEpLCAxMCk7XG4gICAgICAgIGlmIChkZWxldGVJbmRleCA8PSByZXZlcnNlSW5kZXgpIHtcbiAgICAgICAgICByZXZlcnNlSW5kZXgrKztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChkZWx0YUl0ZW0ubGVuZ3RoID09PSAxICYmIGRlbHRhSW5kZXggPD0gcmV2ZXJzZUluZGV4KSB7XG4gICAgICAgIHJldmVyc2VJbmRleC0tO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXZlcnNlSW5kZXg7XG59O1xuXG52YXIgY29sbGVjdENoaWxkcmVuUmV2ZXJzZUZpbHRlciA9IGZ1bmN0aW9uIGNvbGxlY3RDaGlsZHJlblJldmVyc2VGaWx0ZXIoY29udGV4dCkge1xuICBpZiAoIWNvbnRleHQgfHwgIWNvbnRleHQuY2hpbGRyZW4pIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKGNvbnRleHQuZGVsdGEuX3QgIT09ICdhJykge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgbGVuZ3RoID0gY29udGV4dC5jaGlsZHJlbi5sZW5ndGg7XG4gIHZhciBjaGlsZDtcbiAgdmFyIGRlbHRhID0ge1xuICAgIF90OiAnYSdcbiAgfTtcblxuICBmb3IgKHZhciBpbmRleCA9IDA7IGluZGV4IDwgbGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgY2hpbGQgPSBjb250ZXh0LmNoaWxkcmVuW2luZGV4XTtcbiAgICB2YXIgbmFtZSA9IGNoaWxkLm5ld05hbWU7XG4gICAgaWYgKHR5cGVvZiBuYW1lID09PSAndW5kZWZpbmVkJykge1xuICAgICAgbmFtZSA9IHJldmVyc2VBcnJheURlbHRhSW5kZXgoY29udGV4dC5kZWx0YSwgY2hpbGQuY2hpbGROYW1lLCBjaGlsZC5yZXN1bHQpO1xuICAgIH1cbiAgICBpZiAoZGVsdGFbbmFtZV0gIT09IGNoaWxkLnJlc3VsdCkge1xuICAgICAgZGVsdGFbbmFtZV0gPSBjaGlsZC5yZXN1bHQ7XG4gICAgfVxuICB9XG4gIGNvbnRleHQuc2V0UmVzdWx0KGRlbHRhKS5leGl0KCk7XG59O1xuY29sbGVjdENoaWxkcmVuUmV2ZXJzZUZpbHRlci5maWx0ZXJOYW1lID0gJ2FycmF5c0NvbGxlY3RDaGlsZHJlbic7XG5cbmV4cG9ydHMuZGlmZkZpbHRlciA9IGRpZmZGaWx0ZXI7XG5leHBvcnRzLnBhdGNoRmlsdGVyID0gcGF0Y2hGaWx0ZXI7XG5leHBvcnRzLmNvbGxlY3RDaGlsZHJlblBhdGNoRmlsdGVyID0gY29sbGVjdENoaWxkcmVuUGF0Y2hGaWx0ZXI7XG5leHBvcnRzLnJldmVyc2VGaWx0ZXIgPSByZXZlcnNlRmlsdGVyO1xuZXhwb3J0cy5jb2xsZWN0Q2hpbGRyZW5SZXZlcnNlRmlsdGVyID0gY29sbGVjdENoaWxkcmVuUmV2ZXJzZUZpbHRlcjtcbiIsInZhciBkaWZmRmlsdGVyID0gZnVuY3Rpb24gZGF0ZXNEaWZmRmlsdGVyKGNvbnRleHQpIHtcbiAgaWYgKGNvbnRleHQubGVmdCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICBpZiAoY29udGV4dC5yaWdodCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgIGlmIChjb250ZXh0LmxlZnQuZ2V0VGltZSgpICE9PSBjb250ZXh0LnJpZ2h0LmdldFRpbWUoKSkge1xuICAgICAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5sZWZ0LCBjb250ZXh0LnJpZ2h0XSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb250ZXh0LnNldFJlc3VsdCh1bmRlZmluZWQpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5sZWZ0LCBjb250ZXh0LnJpZ2h0XSk7XG4gICAgfVxuICAgIGNvbnRleHQuZXhpdCgpO1xuICB9IGVsc2UgaWYgKGNvbnRleHQucmlnaHQgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgY29udGV4dC5zZXRSZXN1bHQoW2NvbnRleHQubGVmdCwgY29udGV4dC5yaWdodF0pLmV4aXQoKTtcbiAgfVxufTtcbmRpZmZGaWx0ZXIuZmlsdGVyTmFtZSA9ICdkYXRlcyc7XG5cbmV4cG9ydHMuZGlmZkZpbHRlciA9IGRpZmZGaWx0ZXI7XG4iLCIvKiBnbG9iYWwgZGlmZl9tYXRjaF9wYXRjaCAqL1xudmFyIFRFWFRfRElGRiA9IDI7XG52YXIgREVGQVVMVF9NSU5fTEVOR1RIID0gNjA7XG52YXIgY2FjaGVkRGlmZlBhdGNoID0gbnVsbDtcblxudmFyIGdldERpZmZNYXRjaFBhdGNoID0gZnVuY3Rpb24ocmVxdWlyZWQpIHtcbiAgLypqc2hpbnQgY2FtZWxjYXNlOiBmYWxzZSAqL1xuXG4gIGlmICghY2FjaGVkRGlmZlBhdGNoKSB7XG4gICAgdmFyIGluc3RhbmNlO1xuICAgIGlmICh0eXBlb2YgZGlmZl9tYXRjaF9wYXRjaCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgIC8vIGFscmVhZHkgbG9hZGVkLCBwcm9iYWJseSBhIGJyb3dzZXJcbiAgICAgIGluc3RhbmNlID0gdHlwZW9mIGRpZmZfbWF0Y2hfcGF0Y2ggPT09ICdmdW5jdGlvbicgP1xuICAgICAgICBuZXcgZGlmZl9tYXRjaF9wYXRjaCgpIDogbmV3IGRpZmZfbWF0Y2hfcGF0Y2guZGlmZl9tYXRjaF9wYXRjaCgpO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIHZhciBkbXBNb2R1bGVOYW1lID0gJ2RpZmZfbWF0Y2hfcGF0Y2hfdW5jb21wcmVzc2VkJztcbiAgICAgICAgdmFyIGRtcCA9IHJlcXVpcmUoJy4uLy4uL3B1YmxpYy9leHRlcm5hbC8nICsgZG1wTW9kdWxlTmFtZSk7XG4gICAgICAgIGluc3RhbmNlID0gbmV3IGRtcC5kaWZmX21hdGNoX3BhdGNoKCk7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgaW5zdGFuY2UgPSBudWxsO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWluc3RhbmNlKSB7XG4gICAgICBpZiAoIXJlcXVpcmVkKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgICAgfVxuICAgICAgdmFyIGVycm9yID0gbmV3IEVycm9yKCd0ZXh0IGRpZmZfbWF0Y2hfcGF0Y2ggbGlicmFyeSBub3QgZm91bmQnKTtcbiAgICAgIGVycm9yLmRpZmZfbWF0Y2hfcGF0Y2hfbm90X2ZvdW5kID0gdHJ1ZTtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH1cbiAgICBjYWNoZWREaWZmUGF0Y2ggPSB7XG4gICAgICBkaWZmOiBmdW5jdGlvbih0eHQxLCB0eHQyKSB7XG4gICAgICAgIHJldHVybiBpbnN0YW5jZS5wYXRjaF90b1RleHQoaW5zdGFuY2UucGF0Y2hfbWFrZSh0eHQxLCB0eHQyKSk7XG4gICAgICB9LFxuICAgICAgcGF0Y2g6IGZ1bmN0aW9uKHR4dDEsIHBhdGNoKSB7XG4gICAgICAgIHZhciByZXN1bHRzID0gaW5zdGFuY2UucGF0Y2hfYXBwbHkoaW5zdGFuY2UucGF0Y2hfZnJvbVRleHQocGF0Y2gpLCB0eHQxKTtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCByZXN1bHRzWzFdLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKCFyZXN1bHRzWzFdW2ldKSB7XG4gICAgICAgICAgICB2YXIgZXJyb3IgPSBuZXcgRXJyb3IoJ3RleHQgcGF0Y2ggZmFpbGVkJyk7XG4gICAgICAgICAgICBlcnJvci50ZXh0UGF0Y2hGYWlsZWQgPSB0cnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzdWx0c1swXTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG4gIHJldHVybiBjYWNoZWREaWZmUGF0Y2g7XG59O1xuXG52YXIgZGlmZkZpbHRlciA9IGZ1bmN0aW9uIHRleHRzRGlmZkZpbHRlcihjb250ZXh0KSB7XG4gIGlmIChjb250ZXh0LmxlZnRUeXBlICE9PSAnc3RyaW5nJykge1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgbWluTGVuZ3RoID0gKGNvbnRleHQub3B0aW9ucyAmJiBjb250ZXh0Lm9wdGlvbnMudGV4dERpZmYgJiZcbiAgICBjb250ZXh0Lm9wdGlvbnMudGV4dERpZmYubWluTGVuZ3RoKSB8fCBERUZBVUxUX01JTl9MRU5HVEg7XG4gIGlmIChjb250ZXh0LmxlZnQubGVuZ3RoIDwgbWluTGVuZ3RoIHx8XG4gICAgY29udGV4dC5yaWdodC5sZW5ndGggPCBtaW5MZW5ndGgpIHtcbiAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5sZWZ0LCBjb250ZXh0LnJpZ2h0XSkuZXhpdCgpO1xuICAgIHJldHVybjtcbiAgfVxuICAvLyBsYXJnZSB0ZXh0LCB0cnkgdG8gdXNlIGEgdGV4dC1kaWZmIGFsZ29yaXRobVxuICB2YXIgZGlmZk1hdGNoUGF0Y2ggPSBnZXREaWZmTWF0Y2hQYXRjaCgpO1xuICBpZiAoIWRpZmZNYXRjaFBhdGNoKSB7XG4gICAgLy8gZGlmZi1tYXRjaC1wYXRjaCBsaWJyYXJ5IG5vdCBhdmFpbGFibGUsIGZhbGxiYWNrIHRvIHJlZ3VsYXIgc3RyaW5nIHJlcGxhY2VcbiAgICBjb250ZXh0LnNldFJlc3VsdChbY29udGV4dC5sZWZ0LCBjb250ZXh0LnJpZ2h0XSkuZXhpdCgpO1xuICAgIHJldHVybjtcbiAgfVxuICB2YXIgZGlmZiA9IGRpZmZNYXRjaFBhdGNoLmRpZmY7XG4gIGNvbnRleHQuc2V0UmVzdWx0KFtkaWZmKGNvbnRleHQubGVmdCwgY29udGV4dC5yaWdodCksIDAsIFRFWFRfRElGRl0pLmV4aXQoKTtcbn07XG5kaWZmRmlsdGVyLmZpbHRlck5hbWUgPSAndGV4dHMnO1xuXG52YXIgcGF0Y2hGaWx0ZXIgPSBmdW5jdGlvbiB0ZXh0c1BhdGNoRmlsdGVyKGNvbnRleHQpIHtcbiAgaWYgKGNvbnRleHQubmVzdGVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChjb250ZXh0LmRlbHRhWzJdICE9PSBURVhUX0RJRkYpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICAvLyB0ZXh0LWRpZmYsIHVzZSBhIHRleHQtcGF0Y2ggYWxnb3JpdGhtXG4gIHZhciBwYXRjaCA9IGdldERpZmZNYXRjaFBhdGNoKHRydWUpLnBhdGNoO1xuICBjb250ZXh0LnNldFJlc3VsdChwYXRjaChjb250ZXh0LmxlZnQsIGNvbnRleHQuZGVsdGFbMF0pKS5leGl0KCk7XG59O1xucGF0Y2hGaWx0ZXIuZmlsdGVyTmFtZSA9ICd0ZXh0cyc7XG5cbnZhciB0ZXh0RGVsdGFSZXZlcnNlID0gZnVuY3Rpb24oZGVsdGEpIHtcbiAgdmFyIGksIGwsIGxpbmVzLCBsaW5lLCBsaW5lVG1wLCBoZWFkZXIgPSBudWxsLFxuICAgIGhlYWRlclJlZ2V4ID0gL15AQCArXFwtKFxcZCspLChcXGQrKSArXFwrKFxcZCspLChcXGQrKSArQEAkLyxcbiAgICBsaW5lSGVhZGVyLCBsaW5lQWRkLCBsaW5lUmVtb3ZlO1xuICBsaW5lcyA9IGRlbHRhLnNwbGl0KCdcXG4nKTtcbiAgZm9yIChpID0gMCwgbCA9IGxpbmVzLmxlbmd0aDsgaSA8IGw7IGkrKykge1xuICAgIGxpbmUgPSBsaW5lc1tpXTtcbiAgICB2YXIgbGluZVN0YXJ0ID0gbGluZS5zbGljZSgwLCAxKTtcbiAgICBpZiAobGluZVN0YXJ0ID09PSAnQCcpIHtcbiAgICAgIGhlYWRlciA9IGhlYWRlclJlZ2V4LmV4ZWMobGluZSk7XG4gICAgICBsaW5lSGVhZGVyID0gaTtcbiAgICAgIGxpbmVBZGQgPSBudWxsO1xuICAgICAgbGluZVJlbW92ZSA9IG51bGw7XG5cbiAgICAgIC8vIGZpeCBoZWFkZXJcbiAgICAgIGxpbmVzW2xpbmVIZWFkZXJdID0gJ0BAIC0nICsgaGVhZGVyWzNdICsgJywnICsgaGVhZGVyWzRdICsgJyArJyArIGhlYWRlclsxXSArICcsJyArIGhlYWRlclsyXSArICcgQEAnO1xuICAgIH0gZWxzZSBpZiAobGluZVN0YXJ0ID09PSAnKycpIHtcbiAgICAgIGxpbmVBZGQgPSBpO1xuICAgICAgbGluZXNbaV0gPSAnLScgKyBsaW5lc1tpXS5zbGljZSgxKTtcbiAgICAgIGlmIChsaW5lc1tpIC0gMV0uc2xpY2UoMCwgMSkgPT09ICcrJykge1xuICAgICAgICAvLyBzd2FwIGxpbmVzIHRvIGtlZXAgZGVmYXVsdCBvcmRlciAoLSspXG4gICAgICAgIGxpbmVUbXAgPSBsaW5lc1tpXTtcbiAgICAgICAgbGluZXNbaV0gPSBsaW5lc1tpIC0gMV07XG4gICAgICAgIGxpbmVzW2kgLSAxXSA9IGxpbmVUbXA7XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChsaW5lU3RhcnQgPT09ICctJykge1xuICAgICAgbGluZVJlbW92ZSA9IGk7XG4gICAgICBsaW5lc1tpXSA9ICcrJyArIGxpbmVzW2ldLnNsaWNlKDEpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG59O1xuXG52YXIgcmV2ZXJzZUZpbHRlciA9IGZ1bmN0aW9uIHRleHRzUmV2ZXJzZUZpbHRlcihjb250ZXh0KSB7XG4gIGlmIChjb250ZXh0Lm5lc3RlZCkge1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoY29udGV4dC5kZWx0YVsyXSAhPT0gVEVYVF9ESUZGKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gdGV4dC1kaWZmLCB1c2UgYSB0ZXh0LWRpZmYgYWxnb3JpdGhtXG4gIGNvbnRleHQuc2V0UmVzdWx0KFt0ZXh0RGVsdGFSZXZlcnNlKGNvbnRleHQuZGVsdGFbMF0pLCAwLCBURVhUX0RJRkZdKS5leGl0KCk7XG59O1xucmV2ZXJzZUZpbHRlci5maWx0ZXJOYW1lID0gJ3RleHRzJztcblxuZXhwb3J0cy5kaWZmRmlsdGVyID0gZGlmZkZpbHRlcjtcbmV4cG9ydHMucGF0Y2hGaWx0ZXIgPSBwYXRjaEZpbHRlcjtcbmV4cG9ydHMucmV2ZXJzZUZpbHRlciA9IHJldmVyc2VGaWx0ZXI7XG4iLCJ2YXIgUHJvY2Vzc29yID0gcmVxdWlyZSgnLi9wcm9jZXNzb3InKS5Qcm9jZXNzb3I7XG52YXIgUGlwZSA9IHJlcXVpcmUoJy4vcGlwZScpLlBpcGU7XG52YXIgRGlmZkNvbnRleHQgPSByZXF1aXJlKCcuL2NvbnRleHRzL2RpZmYnKS5EaWZmQ29udGV4dDtcbnZhciBQYXRjaENvbnRleHQgPSByZXF1aXJlKCcuL2NvbnRleHRzL3BhdGNoJykuUGF0Y2hDb250ZXh0O1xudmFyIFJldmVyc2VDb250ZXh0ID0gcmVxdWlyZSgnLi9jb250ZXh0cy9yZXZlcnNlJykuUmV2ZXJzZUNvbnRleHQ7XG5cbnZhciBjbG9uZSA9IHJlcXVpcmUoJy4vY2xvbmUnKTtcblxudmFyIHRyaXZpYWwgPSByZXF1aXJlKCcuL2ZpbHRlcnMvdHJpdmlhbCcpO1xudmFyIG5lc3RlZCA9IHJlcXVpcmUoJy4vZmlsdGVycy9uZXN0ZWQnKTtcbnZhciBhcnJheXMgPSByZXF1aXJlKCcuL2ZpbHRlcnMvYXJyYXlzJyk7XG52YXIgZGF0ZXMgPSByZXF1aXJlKCcuL2ZpbHRlcnMvZGF0ZXMnKTtcbnZhciB0ZXh0cyA9IHJlcXVpcmUoJy4vZmlsdGVycy90ZXh0cycpO1xuXG52YXIgRGlmZlBhdGNoZXIgPSBmdW5jdGlvbiBEaWZmUGF0Y2hlcihvcHRpb25zKSB7XG4gIHRoaXMucHJvY2Vzc29yID0gbmV3IFByb2Nlc3NvcihvcHRpb25zKTtcbiAgdGhpcy5wcm9jZXNzb3IucGlwZShuZXcgUGlwZSgnZGlmZicpLmFwcGVuZChcbiAgICBuZXN0ZWQuY29sbGVjdENoaWxkcmVuRGlmZkZpbHRlcixcbiAgICB0cml2aWFsLmRpZmZGaWx0ZXIsXG4gICAgZGF0ZXMuZGlmZkZpbHRlcixcbiAgICB0ZXh0cy5kaWZmRmlsdGVyLFxuICAgIG5lc3RlZC5vYmplY3RzRGlmZkZpbHRlcixcbiAgICBhcnJheXMuZGlmZkZpbHRlclxuICApLnNob3VsZEhhdmVSZXN1bHQoKSk7XG4gIHRoaXMucHJvY2Vzc29yLnBpcGUobmV3IFBpcGUoJ3BhdGNoJykuYXBwZW5kKFxuICAgIG5lc3RlZC5jb2xsZWN0Q2hpbGRyZW5QYXRjaEZpbHRlcixcbiAgICBhcnJheXMuY29sbGVjdENoaWxkcmVuUGF0Y2hGaWx0ZXIsXG4gICAgdHJpdmlhbC5wYXRjaEZpbHRlcixcbiAgICB0ZXh0cy5wYXRjaEZpbHRlcixcbiAgICBuZXN0ZWQucGF0Y2hGaWx0ZXIsXG4gICAgYXJyYXlzLnBhdGNoRmlsdGVyXG4gICkuc2hvdWxkSGF2ZVJlc3VsdCgpKTtcbiAgdGhpcy5wcm9jZXNzb3IucGlwZShuZXcgUGlwZSgncmV2ZXJzZScpLmFwcGVuZChcbiAgICBuZXN0ZWQuY29sbGVjdENoaWxkcmVuUmV2ZXJzZUZpbHRlcixcbiAgICBhcnJheXMuY29sbGVjdENoaWxkcmVuUmV2ZXJzZUZpbHRlcixcbiAgICB0cml2aWFsLnJldmVyc2VGaWx0ZXIsXG4gICAgdGV4dHMucmV2ZXJzZUZpbHRlcixcbiAgICBuZXN0ZWQucmV2ZXJzZUZpbHRlcixcbiAgICBhcnJheXMucmV2ZXJzZUZpbHRlclxuICApLnNob3VsZEhhdmVSZXN1bHQoKSk7XG59O1xuXG5EaWZmUGF0Y2hlci5wcm90b3R5cGUub3B0aW9ucyA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5wcm9jZXNzb3Iub3B0aW9ucy5hcHBseSh0aGlzLnByb2Nlc3NvciwgYXJndW1lbnRzKTtcbn07XG5cbkRpZmZQYXRjaGVyLnByb3RvdHlwZS5kaWZmID0gZnVuY3Rpb24obGVmdCwgcmlnaHQpIHtcbiAgcmV0dXJuIHRoaXMucHJvY2Vzc29yLnByb2Nlc3MobmV3IERpZmZDb250ZXh0KGxlZnQsIHJpZ2h0KSk7XG59O1xuXG5EaWZmUGF0Y2hlci5wcm90b3R5cGUucGF0Y2ggPSBmdW5jdGlvbihsZWZ0LCBkZWx0YSkge1xuICByZXR1cm4gdGhpcy5wcm9jZXNzb3IucHJvY2VzcyhuZXcgUGF0Y2hDb250ZXh0KGxlZnQsIGRlbHRhKSk7XG59O1xuXG5EaWZmUGF0Y2hlci5wcm90b3R5cGUucmV2ZXJzZSA9IGZ1bmN0aW9uKGRlbHRhKSB7XG4gIHJldHVybiB0aGlzLnByb2Nlc3Nvci5wcm9jZXNzKG5ldyBSZXZlcnNlQ29udGV4dChkZWx0YSkpO1xufTtcblxuRGlmZlBhdGNoZXIucHJvdG90eXBlLnVucGF0Y2ggPSBmdW5jdGlvbihyaWdodCwgZGVsdGEpIHtcbiAgcmV0dXJuIHRoaXMucGF0Y2gocmlnaHQsIHRoaXMucmV2ZXJzZShkZWx0YSkpO1xufTtcblxuRGlmZlBhdGNoZXIucHJvdG90eXBlLmNsb25lID0gZnVuY3Rpb24odmFsdWUpIHtcbiAgcmV0dXJuIGNsb25lKHZhbHVlKTtcbn07XG5cbmV4cG9ydHMuRGlmZlBhdGNoZXIgPSBEaWZmUGF0Y2hlcjtcbiIsIi8vIHVzZSBhcyAybmQgcGFyYW1ldGVyIGZvciBKU09OLnBhcnNlIHRvIHJldml2ZSBEYXRlIGluc3RhbmNlc1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBkYXRlUmV2aXZlcihrZXksIHZhbHVlKSB7XG4gIHZhciBwYXJ0cztcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICBwYXJ0cyA9IC9eKFxcZHs0fSktKFxcZHsyfSktKFxcZHsyfSlUKFxcZHsyfSk6KFxcZHsyfSk6KFxcZHsyfSkoPzpcXC4oXFxkKikpPyhafChbK1xcLV0pKFxcZHsyfSk6KFxcZHsyfSkpJC8uZXhlYyh2YWx1ZSk7XG4gICAgaWYgKHBhcnRzKSB7XG4gICAgICByZXR1cm4gbmV3IERhdGUoRGF0ZS5VVEMoK3BhcnRzWzFdLCArcGFydHNbMl0gLSAxLCArcGFydHNbM10sICtwYXJ0c1s0XSwgK3BhcnRzWzVdLCArcGFydHNbNl0sICsocGFydHNbN10gfHwgMCkpKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHZhbHVlO1xufTtcbiIsIlxudmFyIGVudmlyb25tZW50ID0gcmVxdWlyZSgnLi9lbnZpcm9ubWVudCcpO1xuXG52YXIgRGlmZlBhdGNoZXIgPSByZXF1aXJlKCcuL2RpZmZwYXRjaGVyJykuRGlmZlBhdGNoZXI7XG5leHBvcnRzLkRpZmZQYXRjaGVyID0gRGlmZlBhdGNoZXI7XG5cbmV4cG9ydHMuY3JlYXRlID0gZnVuY3Rpb24ob3B0aW9ucyl7XG4gIHJldHVybiBuZXcgRGlmZlBhdGNoZXIob3B0aW9ucyk7XG59O1xuXG5leHBvcnRzLmRhdGVSZXZpdmVyID0gcmVxdWlyZSgnLi9kYXRlLXJldml2ZXInKTtcblxudmFyIGRlZmF1bHRJbnN0YW5jZTtcblxuZXhwb3J0cy5kaWZmID0gZnVuY3Rpb24oKSB7XG4gIGlmICghZGVmYXVsdEluc3RhbmNlKSB7XG4gICAgZGVmYXVsdEluc3RhbmNlID0gbmV3IERpZmZQYXRjaGVyKCk7XG4gIH1cbiAgcmV0dXJuIGRlZmF1bHRJbnN0YW5jZS5kaWZmLmFwcGx5KGRlZmF1bHRJbnN0YW5jZSwgYXJndW1lbnRzKTtcbn07XG5cbmV4cG9ydHMucGF0Y2ggPSBmdW5jdGlvbigpIHtcbiAgaWYgKCFkZWZhdWx0SW5zdGFuY2UpIHtcbiAgICBkZWZhdWx0SW5zdGFuY2UgPSBuZXcgRGlmZlBhdGNoZXIoKTtcbiAgfVxuICByZXR1cm4gZGVmYXVsdEluc3RhbmNlLnBhdGNoLmFwcGx5KGRlZmF1bHRJbnN0YW5jZSwgYXJndW1lbnRzKTtcbn07XG5cbmV4cG9ydHMudW5wYXRjaCA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIWRlZmF1bHRJbnN0YW5jZSkge1xuICAgIGRlZmF1bHRJbnN0YW5jZSA9IG5ldyBEaWZmUGF0Y2hlcigpO1xuICB9XG4gIHJldHVybiBkZWZhdWx0SW5zdGFuY2UudW5wYXRjaC5hcHBseShkZWZhdWx0SW5zdGFuY2UsIGFyZ3VtZW50cyk7XG59O1xuXG5leHBvcnRzLnJldmVyc2UgPSBmdW5jdGlvbigpIHtcbiAgaWYgKCFkZWZhdWx0SW5zdGFuY2UpIHtcbiAgICBkZWZhdWx0SW5zdGFuY2UgPSBuZXcgRGlmZlBhdGNoZXIoKTtcbiAgfVxuICByZXR1cm4gZGVmYXVsdEluc3RhbmNlLnJldmVyc2UuYXBwbHkoZGVmYXVsdEluc3RhbmNlLCBhcmd1bWVudHMpO1xufTtcblxuZXhwb3J0cy5jbG9uZSA9IGZ1bmN0aW9uKCkge1xuICBpZiAoIWRlZmF1bHRJbnN0YW5jZSkge1xuICAgIGRlZmF1bHRJbnN0YW5jZSA9IG5ldyBEaWZmUGF0Y2hlcigpO1xuICB9XG4gIHJldHVybiBkZWZhdWx0SW5zdGFuY2UuY2xvbmUuYXBwbHkoZGVmYXVsdEluc3RhbmNlLCBhcmd1bWVudHMpO1xufTtcblxuXG5pZiAoZW52aXJvbm1lbnQuaXNCcm93c2VyKSB7XG4gIGV4cG9ydHMuaG9tZXBhZ2UgPSAne3twYWNrYWdlLWhvbWVwYWdlfX0nO1xuICBleHBvcnRzLnZlcnNpb24gPSAne3twYWNrYWdlLXZlcnNpb259fSc7XG59IGVsc2Uge1xuICB2YXIgcGFja2FnZUluZm9Nb2R1bGVOYW1lID0gJy4uL3BhY2thZ2UuanNvbic7XG4gIHZhciBwYWNrYWdlSW5mbyA9IHJlcXVpcmUocGFja2FnZUluZm9Nb2R1bGVOYW1lKTtcbiAgZXhwb3J0cy5ob21lcGFnZSA9IHBhY2thZ2VJbmZvLmhvbWVwYWdlO1xuICBleHBvcnRzLnZlcnNpb24gPSBwYWNrYWdlSW5mby52ZXJzaW9uO1xuXG4gIHZhciBmb3JtYXR0ZXJNb2R1bGVOYW1lID0gJy4vZm9ybWF0dGVycyc7XG4gIHZhciBmb3JtYXR0ZXJzID0gcmVxdWlyZShmb3JtYXR0ZXJNb2R1bGVOYW1lKTtcbiAgZXhwb3J0cy5mb3JtYXR0ZXJzID0gZm9ybWF0dGVycztcbiAgLy8gc2hvcnRjdXQgZm9yIGNvbnNvbGVcbiAgZXhwb3J0cy5jb25zb2xlID0gZm9ybWF0dGVycy5jb25zb2xlO1xufVxuIiwiZXhwb3J0IGZ1bmN0aW9uIHBhY2sgeFxuICAgIEpTT04uc3RyaW5naWZ5IHgsIChrZXksIHZhbCkgLT5cbiAgICAgICAgaWYgdHlwZW9mISB2YWwgaXMgXFxGdW5jdGlvblxuICAgICAgICAgICAgcmV0dXJuIHZhbCArICcnICAjIGltcGxpY2l0bHkgY29udmVydCB0byBzdHJpbmdcbiAgICAgICAgI2Vsc2UgaWYgdmFsIGlzIHVuZGVmaW5lZCAgPT4gcmV0dXJuIG51bGwgIyBETyBOT1QgRE8gVEhBVCFcbiAgICAgICAgdmFsXG5cbmV4cG9ydCBmdW5jdGlvbiB1bnBhY2sgeFxuICAgIEpTT04ucGFyc2UgeFxuXG5leHBvcnQgY2xhc3MgQ2xvbmVFcnJvciBleHRlbmRzIEVycm9yXG4gICAgKEBtZXNzYWdlLCBAYXJndW1lbnQpIC0+XG4gICAgICAgIHN1cGVyIC4uLlxuICAgICAgICBFcnJvci5jYXB0dXJlU3RhY2tUcmFjZSh0aGlzLCBDbG9uZUVycm9yKVxuXG5cbmV4cG9ydCBjbG9uZSA9ICh4KSAtPlxuICAgIGlmIHR5cGVvZiEgeCBpbiA8WyBPYmplY3QgQXJyYXkgXT5cbiAgICAgICAgdW5wYWNrIHBhY2sgeFxuICAgIGVsc2VcbiAgICAgICAgdGhyb3cgbmV3IENsb25lRXJyb3IgXCJhcmd1bWVudCBtdXN0IGJlIG9iamVjdCBvciBhcnJheSwgc3VwcGxpZWQ6ICN7cGFjayB4fVwiLCB4XG5cblxucmVxdWlyZSEgXFxqc29uZGlmZnBhdGNoXG5cbmV4cG9ydCBkaWZmID0gKGEsIGIpIC0+XG4gICAganNvbmRpZmZwYXRjaC5kaWZmIGEsIGJcbiIsInJlcXVpcmUhICcuL3BhY2tpbmcnOiB7cGFja31cblxuLyoqIC9cbmV4cG9ydCBtZXJnZSA9IChvYmoxLCBvYmoyKSAtPlxuICAgIGlmICh0eXBlb2YhIG9iajEgaXMgXFxBcnJheSkgYW5kICh0eXBlb2YhIG9iajIgaXMgXFxBcnJheSlcbiAgICAgICAgZm9yIGkgaW4gb2JqMlxuICAgICAgICAgICAgdHJ5XG4gICAgICAgICAgICAgICAgZm9yIGogaW4gb2JqMVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBpZiBwYWNrKGkpIGlzIHBhY2soailcbiAgICAgICAgICAgICAgICAjIGFwcGVuZCBpZiBpdGVtIGlzIG5vdCBmb3VuZCBpbiBmaXJzdCBvbmVcbiAgICAgICAgICAgICAgICBvYmoxLnB1c2ggaVxuICAgICAgICByZXR1cm4gb2JqMVxuICAgIGVsc2VcbiAgICAgICAgZm9yIHAgb2Ygb2JqMlxuICAgICAgICAgICAgdHJ5XG4gICAgICAgICAgICAgICAgdGhyb3cgaWYgdHlwZW9mISBvYmoyW3BdIGlzbnQgXFxPYmplY3RcbiAgICAgICAgICAgICAgICB0aHJvdyBpZiB0eXBlb2YhIG9iajFbcF0gaXNudCBcXE9iamVjdFxuICAgICAgICAgICAgICAgICMgZ28gb24gaWYgYW5kIG9ubHkgaWYgcmlnaHQgaGFuZCBpcyBvYmplY3RcbiAgICAgICAgICAgICAgICBvYmoxW3BdIGBtZXJnZWAgb2JqMltwXVxuICAgICAgICAgICAgY2F0Y2hcbiAgICAgICAgICAgICAgICBpZiBBcnJheS5pc0FycmF5IG9iajFbcF1cbiAgICAgICAgICAgICAgICAgICAgIyBhcnJheSwgbWVyZ2Ugd2l0aCBjdXJyZW50IG9uZVxuICAgICAgICAgICAgICAgICAgICBmb3IgaSwgaiBvZiBvYmoyW3BdXG4gICAgICAgICAgICAgICAgICAgICAgICB0cnlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgYSBpbiBvYmoxW3BdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGlmIHBhY2soYSkgaXMgcGFjayhqKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9iajFbcF0ucHVzaCBqXG4gICAgICAgICAgICAgICAgZWxzZSBpZiBvYmoyW3BdIGlzbnQgdm9pZFxuICAgICAgICAgICAgICAgICAgICBvYmoxW3BdID0gb2JqMltwXVxuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG9iajFbcF1cbiAgICAgICAgb2JqMVxuXG4vKiovXG5cbmV4cG9ydCBmdW5jdGlvbiBtZXJnZSBvYmoxLCBvYmoyXG4gICAgaWYgKHR5cGVvZiEgb2JqMSBpcyBcXEFycmF5KSBhbmQgKHR5cGVvZiEgb2JqMiBpcyBcXEFycmF5KVxuICAgICAgICBmb3IgaSBpbiBvYmoyXG4gICAgICAgICAgICB0cnlcbiAgICAgICAgICAgICAgICBmb3IgaiBpbiBvYmoxXG4gICAgICAgICAgICAgICAgICAgIHRocm93IGlmIHBhY2soaSkgaXMgcGFjayhqKVxuICAgICAgICAgICAgICAgICMgYXBwZW5kIGlmIGl0ZW0gaXMgbm90IGZvdW5kIGluIGZpcnN0IG9uZVxuICAgICAgICAgICAgICAgIG9iajEucHVzaCBpXG4gICAgICAgIHJldHVybiBvYmoxXG4gICAgZWxzZVxuICAgICAgICBmb3IgcCBvZiBvYmoyXG4gICAgICAgICAgICB0LW9iajEgPSB0eXBlb2YhIG9iajFbcF1cbiAgICAgICAgICAgIGlmIHR5cGVvZiEgb2JqMltwXSBpbiA8WyBPYmplY3QgQXJyYXkgXT5cbiAgICAgICAgICAgICAgICBpZiB0LW9iajEgaW4gPFsgT2JqZWN0IEFycmF5IF0+XG4gICAgICAgICAgICAgICAgICAgIG9iajFbcF0gYG1lcmdlYCBvYmoyW3BdXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBvYmoxW3BdID0gb2JqMltwXVxuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIGlmIG9iajJbcF0gaXNudCB2b2lkXG4gICAgICAgICAgICAgICAgICAgIG9iajFbcF0gPSBvYmoyW3BdXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgb2JqMVtwXVxuICAgICAgICBvYmoxXG4vKiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlLWFsbCAob2JqMSwgLi4uc291cmNlcylcbiAgICBmb3Igb2JqMiBpbiBzb3VyY2VzXG4gICAgICAgICMgbWVyZ2UgcmVzdCBvbmUgYnkgb25lXG4gICAgICAgIG9iajEgYG1lcmdlYCBvYmoyXG4gICAgb2JqMVxuXG5cblxuZXhwb3J0IGJhc2VkLW9uID0gKGEsIGIpIC0+XG4gICAgIyBpbnZlcnNlIGFyZ3VtZW50IG9yZGVyIG9mIG1lcmdlXG4gICAgKGIgb3Ige30pIGBtZXJnZWAgKGEgb3Ige30pXG5cblxudGVzdHMgPVxuICAgICdzaW1wbGUgbWVyZ2UnOiAtPlxuICAgICAgICBhPVxuICAgICAgICAgIGE6IDFcbiAgICAgICAgICBiOiAyXG5cbiAgICAgICAgYj1cbiAgICAgICAgICBjOiA1XG5cbiAgICAgICAgcmVzdWx0ID0gYSBgbWVyZ2VgIGJcblxuICAgICAgICBleHBlY3RlZCA9XG4gICAgICAgICAgICBhOiAxXG4gICAgICAgICAgICBiOiAyXG4gICAgICAgICAgICBjOiA1XG5cbiAgICAgICAge3Jlc3VsdCwgZXhwZWN0ZWR9XG5cbiAgICAnc2ltcGxlIG1lcmdlMic6IC0+XG4gICAgICAgIGE9XG4gICAgICAgICAgYTogMVxuICAgICAgICAgIGI6IDJcbiAgICAgICAgICBjOlxuICAgICAgICAgICAgY2E6IDFcbiAgICAgICAgICAgIGNiOiAyXG4gICAgICAgIGI9XG4gICAgICAgICAgYzpcbiAgICAgICAgICAgIGNiOiA1XG5cbiAgICAgICAgcmVzdWx0ID0gYSBgbWVyZ2VgIGJcblxuICAgICAgICBleHBlY3RlZCA9XG4gICAgICAgICAgICBhOiAxXG4gICAgICAgICAgICBiOiAyXG4gICAgICAgICAgICBjOlxuICAgICAgICAgICAgICAgIGNhOiAxXG4gICAgICAgICAgICAgICAgY2I6IDVcblxuICAgICAgICB7cmVzdWx0LCBleHBlY3RlZH1cblxuICAgICdtZXJnZSBsaXN0cyc6IC0+XG4gICAgICAgIGE9XG4gICAgICAgICAgYTogMVxuICAgICAgICAgIGI6IDJcbiAgICAgICAgICBjOiBbMSwgMl1cbiAgICAgICAgYj1cbiAgICAgICAgICBiOiA4XG4gICAgICAgICAgYzogWzEsIDRdXG5cbiAgICAgICAgcmVzdWx0ID0gYSBgbWVyZ2VgIGJcblxuICAgICAgICBleHBlY3RlZCA9XG4gICAgICAgICAgICBhOiAxXG4gICAgICAgICAgICBiOiA4XG4gICAgICAgICAgICBjOiBbMSwgMiwgNF1cblxuICAgICAgICB7cmVzdWx0LCBleHBlY3RlZH1cblxuXG4gICAgJ21lcmdlIGxpc3RzMic6IC0+XG4gICAgICAgIGE9XG4gICAgICAgICAgYTogMVxuICAgICAgICAgIGI6IDJcbiAgICAgICAgICBjOiBbJ2hlbGxvJywgJ3dvcmxkJ11cbiAgICAgICAgYj1cbiAgICAgICAgICBiOiA4XG4gICAgICAgICAgYzogWydoaScsICd3b3JsZCddXG5cbiAgICAgICAgcmVzdWx0ID0gYSBgbWVyZ2VgIGJcblxuICAgICAgICBleHBlY3RlZCA9XG4gICAgICAgICAgICBhOiAxXG4gICAgICAgICAgICBiOiA4XG4gICAgICAgICAgICBjOiBbJ2hlbGxvJywgJ3dvcmxkJywgJ2hpJ11cblxuICAgICAgICB7cmVzdWx0LCBleHBlY3RlZH1cblxuICAgICdtZXJnZSBsaXN0cyBvZiBvYmplY3RzJzogLT5cbiAgICAgICAgYT1cbiAgICAgICAgICBhOiAxXG4gICAgICAgICAgYjogMlxuICAgICAgICAgIGM6IFt7YTogMSwgYjogMn0sIHthOiAzLCBiOiA0fV1cbiAgICAgICAgYj1cbiAgICAgICAgICBiOiA4XG4gICAgICAgICAgYzogW3thOiAxLCBiOiAyfSwge2E6IDUsIGI6IDZ9XVxuXG4gICAgICAgIHJlc3VsdCA9IGEgYG1lcmdlYCBiXG5cbiAgICAgICAgZXhwZWN0ZWQgPVxuICAgICAgICAgICAgYTogMVxuICAgICAgICAgICAgYjogOFxuICAgICAgICAgICAgYzogW3thOiAxLCBiOiAyfSwge2E6IDMsIGI6IDR9LCB7YTogNSwgYjogNn1dXG5cbiAgICAgICAge3Jlc3VsdCwgZXhwZWN0ZWR9XG5cbiAgICAnbWVyZ2UgbGlzdHMgb2Ygb2JqZWN0czInOiAtPlxuICAgICAgICB4ID1cbiAgICAgICAgICAgICogYTogMVxuICAgICAgICAgICAgICBiOiAyXG4gICAgICAgICAgICAqIGE6IDNcbiAgICAgICAgICAgICAgYjogNFxuXG4gICAgICAgIHkgPVxuICAgICAgICAgICAgKiBhOiA1XG4gICAgICAgICAgICAgIGI6IDZcbiAgICAgICAgICAgICogYTogN1xuICAgICAgICAgICAgICBiOiA4XG4gICAgICAgICAgICAqIGE6IDlcbiAgICAgICAgICAgICAgYjogMTBcbiAgICAgICAgICAgICogYTogMTFcbiAgICAgICAgICAgICAgYjogMTJcblxuICAgICAgICByZXN1bHQgPSB4IGBtZXJnZWAgeVxuXG4gICAgICAgIGV4cGVjdGVkID1cbiAgICAgICAgICAgICogYTogMVxuICAgICAgICAgICAgICBiOiAyXG4gICAgICAgICAgICAqIGE6IDNcbiAgICAgICAgICAgICAgYjogNFxuICAgICAgICAgICAgKiBhOiA1XG4gICAgICAgICAgICAgIGI6IDZcbiAgICAgICAgICAgICogYTogN1xuICAgICAgICAgICAgICBiOiA4XG4gICAgICAgICAgICAqIGE6IDlcbiAgICAgICAgICAgICAgYjogMTBcbiAgICAgICAgICAgICogYTogMTFcbiAgICAgICAgICAgICAgYjogMTJcblxuICAgICAgICB7cmVzdWx0LCBleHBlY3RlZH1cblxuICAgICdkZWxldGluZyBzb21ldGhpbmcnOiAtPlxuICAgICAgICBhPVxuICAgICAgICAgIGE6IDFcbiAgICAgICAgICBiOiAyXG4gICAgICAgICAgYzpcbiAgICAgICAgICAgIGNhOiAxMVxuICAgICAgICAgICAgY2I6IDJcblxuICAgICAgICByZXN1bHQgPSBtZXJnZSBhLCB7Yzogdm9pZH1cblxuICAgICAgICBleHBlY3RlZCA9XG4gICAgICAgICAgICBhOiAxXG4gICAgICAgICAgICBiOiAyXG5cbiAgICAgICAge3Jlc3VsdCwgZXhwZWN0ZWR9XG4gICAgJ2ZvcmNlIG92ZXJ3cml0ZSc6IC0+XG4gICAgICAgIGE9XG4gICAgICAgICAgYTogMVxuICAgICAgICAgIGI6IDJcbiAgICAgICAgICBjOlxuICAgICAgICAgICAgY2E6IDExXG4gICAgICAgICAgICBjYjogMlxuICAgICAgICBiPVxuICAgICAgICAgIGM6ICAjIGRvIG5vdCBtZXJnZSwgZm9yY2Ugb3ZlcndyaXRlXG4gICAgICAgICAgICBjYjogNVxuXG4gICAgICAgIHJlc3VsdCA9IG1lcmdlLWFsbCBhLCB7Yzogdm9pZH0sIGJcblxuICAgICAgICBleHBlY3RlZCA9XG4gICAgICAgICAgICBhOiAxXG4gICAgICAgICAgICBiOiAyXG4gICAgICAgICAgICBjOlxuICAgICAgICAgICAgICAgIGNiOiA1XG5cbiAgICAgICAge3Jlc3VsdCwgZXhwZWN0ZWR9XG5cbiAgICAnbWVyZ2luZyBvYmplY3Qgd2l0aCBmdW5jdGlvbnMnOiAtPlxuICAgICAgICBhPVxuICAgICAgICAgIGE6IDFcbiAgICAgICAgICBiOiAyXG4gICAgICAgICAgYzpcbiAgICAgICAgICAgIGNhOiAxMVxuICAgICAgICAgICAgY2I6IDJcbiAgICAgICAgYj1cbiAgICAgICAgICBjOlxuICAgICAgICAgICAgY2I6ICh4KSAtPiB4XG5cbiAgICAgICAgcmVzdWx0ID0gbWVyZ2UgYSwgYlxuXG4gICAgICAgIGV4cGVjdGVkID1cbiAgICAgICAgICAgIGE6IDFcbiAgICAgICAgICAgIGI6IDJcbiAgICAgICAgICAgIGM6XG4gICAgICAgICAgICAgICAgY2E6IDExXG4gICAgICAgICAgICAgICAgY2I6ICh4KSAtPiB4XG5cbiAgICAgICAge3Jlc3VsdCwgZXhwZWN0ZWR9XG5cbiAgICAnRmllbGQgb3IgbWV0aG9kIGRvZXMgbm90IGFscmVhZHkgZXhpc3QsIGFuZCBjYW50IGNyZWF0ZSBpdCBvbiBTdHJpbmcnOiAtPlxuICAgICAgICBhPVxuICAgICAgICAgIGE6IDFcbiAgICAgICAgICBiOiAyXG4gICAgICAgICAgYzogXCJoZXlcIlxuICAgICAgICBiPVxuICAgICAgICAgIGM6XG4gICAgICAgICAgICBjYjogXCJhYVwiXG5cbiAgICAgICAgcmVzdWx0ID0gbWVyZ2UgYSwgYlxuXG4gICAgICAgIGV4cGVjdGVkID1cbiAgICAgICAgICAgIGE6IDFcbiAgICAgICAgICAgIGI6IDJcbiAgICAgICAgICAgIGM6XG4gICAgICAgICAgICAgICAgY2I6IFwiYWFcIlxuXG4gICAgICAgIHtyZXN1bHQsIGV4cGVjdGVkfVxuXG5zdGFydCA9IERhdGUubm93IVxudGVzdC1jb3VudCA9IDEgICMgdXNlIDVfMDAwIGZvciBhIHNpZ25pZmljaWFudCBhbW91bnQgb2YgdGltZVxuZm9yIGkgZnJvbSAwIHRvIHRlc3QtY291bnRcbiAgICBmb3IgbmFtZSwgdGVzdCBvZiB0ZXN0c1xuICAgICAgICB7cmVzdWx0LCBleHBlY3RlZH0gPSB0ZXN0IVxuICAgICAgICBpZiBwYWNrKGV4cGVjdGVkKSBpc250IHBhY2socmVzdWx0KVxuICAgICAgICAgICAgY29uc29sZS5sb2cgXCJtZXJnZSB0ZXN0IGZhaWxlZCB0ZXN0OiBcIiwgbmFtZVxuICAgICAgICAgICAgY29uc29sZS5sb2cgXCJFWFBFQ1RFRDogXCIsIGV4cGVjdGVkXG4gICAgICAgICAgICBjb25zb2xlLmxvZyBcIlJFU1VMVCAgOiBcIiwgcmVzdWx0XG4gICAgICAgICAgICB0aHJvdyBcIlRlc3QgZmFpbGVkIGluIG1lcmdlLmxzISwgdGVzdDogI3tuYW1lfVwiXG5cbmlmIHRlc3QtY291bnQgPiAxXG4gICAgY29uc29sZS5sb2cgXCJNZXJnZSB0ZXN0cyB0b29rOiAje0RhdGUubm93ISAtIHN0YXJ0fSBtaWxsaXNlY29uZHMuLi5cIlxuIiwicmVxdWlyZSEgJ3ByZWx1ZGUtbHMnOiB7cmV2ZXJzZX1cblxuZXhwb3J0IGhleCA9IChuKSAtPiBuLnRvLXN0cmluZyAxNiAudG8tdXBwZXItY2FzZSFcblxuZXhwb3J0IGlwLXRvLWhleCA9IChpcCkgLT5cbiAgICBpID0gMFxuICAgIHJlc3VsdCA9IDBcbiAgICBmb3IgcGFydCBpbiByZXZlcnNlIGlwLnNwbGl0ICcuJ1xuICAgICAgICByZXN1bHQgKz0gcGFydCAqICgyNTYqKmkrKylcblxuICAgIGhleCByZXN1bHRcbiIsInJlcXVpcmUhICcuL2xvZ2dlcic6IHtMb2dnZXJ9XG5yZXF1aXJlISAnLi9ldmVudC1lbWl0dGVyJzoge0V2ZW50RW1pdHRlcn1cbnJlcXVpcmUhICcuL3NsZWVwJzoge3NsZWVwfVxucmVxdWlyZSEgJy4vcGFja2luZyc6IHtwYWNrLCB1bnBhY2ssIGNsb25lLCBkaWZmfVxucmVxdWlyZSEgJy4vbWVyZ2UnOiB7bWVyZ2UsIGJhc2VkLW9ufVxucmVxdWlyZSEgJy4vaXAtdG8taGV4Jzoge2lwLXRvLWhleCwgaGV4fVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBMb2dnZXJcbiAgICBFdmVudEVtaXR0ZXJcbiAgICBzbGVlcFxuICAgIHBhY2ssIHVucGFjaywgY2xvbmUsIGRpZmZcbiAgICBtZXJnZSwgYmFzZWQtb25cbiAgICBpcC10by1oZXgsIGhleFxufVxuIiwiZXhwb3J0IGJyaWVmID0gKG1zZykgLT5cbiAgICBzID0ge31cbiAgICBmb3IgaywgdiBvZiBtc2dcbiAgICAgICAgY29udGludWUgaWYgayBpcyBcXGRhdGFcbiAgICAgICAgc1trXSA9IHZcbiAgICBpZiBtc2cuZGF0YVxuICAgICAgICBkYXRhLXN0ciA9IEpTT04uc3RyaW5naWZ5IG1zZy5kYXRhXG4gICAgICAgIHMuZGF0YSA9IGlmIGRhdGEtc3RyLmxlbmd0aCA+IDcwXG4gICAgICAgICAgICBcIi4uLiN7ZGF0YS1zdHIubGVuZ3RofS4uLlwiXG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIG1zZy5kYXRhXG4gICAgaWYgbXNnLnBlcm1pc3Npb25zXG4gICAgICAgIHMucGVybWlzc2lvbnMgPSBcIi4uLiN7bXNnLnBlcm1pc3Npb25zLmxlbmd0aH0uLi5cIlxuICAgIHJldHVybiBzXG4iLCJyZXF1aXJlISAncHJlbHVkZS1scyc6IHttYXgsIHNwbGl0fVxuXG5zcGxpdC1kb3QgPSBzcGxpdCAnLidcblxuZXhwb3J0IHRvcGljLW1hdGNoID0gKHRvcGljcywga2V5cGF0aHMsIG9wdHM9e30pIC0+XG4gICAgIyByZXR1cm5zIHRydWUgaWYga2V5cGF0aCBmaXRzIGludG8gdG9waWNcbiAgICAjIGVsc2UsIHJldHVybiBmYWxzZVxuICAgIHVubGVzcyB0b3BpY3M/IGFuZCBrZXlwYXRocz9cbiAgICAgICAgIyBib3RoIHNob3VsZCBiZSBkaWZmZXJlbnQgZnJvbSB1bmRlZmluZWRcbiAgICAgICAgcmV0dXJuIG5vXG5cbiAgICBhcy1hcnJheSA9ICh4KSAtPlxuICAgICAgICBpZiB0eXBlb2YhIHggaXMgXFxTdHJpbmcgdGhlbiB4LnRyaW0hLnNwbGl0ICcgJyBlbHNlIHhcblxuICAgIGZvciB0b3BpYyBpbiB0b3BpY3MgfD4gYXMtYXJyYXlcbiAgICAgICAgZm9yIGtleXBhdGggaW4ga2V5cGF0aHMgfD4gYXMtYXJyYXlcbiAgICAgICAgICAgIHRyeVxuICAgICAgICAgICAgICAgIGlmICcqKicgaW4gW3RvcGljLCBrZXlwYXRoXVxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyBcInRvcGljIGlzICoqLCBpbW1lZGlhdGVseSBtYXRjaGVzIHdpdGggYW55dGhpbmdcIiBpZiBvcHRzLmRlYnVnXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB5ZXNcbiAgICAgICAgICAgICAgICB0cnlcbiAgICAgICAgICAgICAgICAgICAgdG9waWMtYXJyID0gc3BsaXQtZG90IHRvcGljXG4gICAgICAgICAgICAgICAgICAgIGtleXBhdGgtYXJyID0gc3BsaXQtZG90IGtleXBhdGhcbiAgICAgICAgICAgICAgICBjYXRjaFxuICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yIFwiYm90aCB0b3BpYyBhbmQga2V5cGF0aCBzaG91bGQgYmUgc3RyaW5nLlwiXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBub1xuXG4gICAgICAgICAgICAgICAgZm9yIGluZGV4IGluIFt0aWwgbWF4KHRvcGljLWFyci5sZW5ndGgsIGtleXBhdGgtYXJyLmxlbmd0aCldXG4gICAgICAgICAgICAgICAgICAgIHRvcGljLXBhcnQgPSB0cnkgdG9waWMtYXJyW2luZGV4XVxuICAgICAgICAgICAgICAgICAgICBrZXlwYXRoLXBhcnQgPSB0cnkga2V5cGF0aC1hcnJbaW5kZXhdXG5cbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2cgXCJ0b3BpYy1wYXJ0OiAje3RvcGljLXBhcnR9LCBrZXlwYXRoLXBhcnQ6ICN7a2V5cGF0aC1wYXJ0fVwiIGlmIG9wdHMuZGVidWdcblxuICAgICAgICAgICAgICAgICAgICBpZiAnKicgaW4gW2tleXBhdGgtcGFydCwgdG9waWMtcGFydF1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIHVuZGVmaW5lZCBpbiBba2V5cGF0aC1wYXJ0LCB0b3BpYy1wYXJ0XVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nIFwicmV0dXJuaW5nIGZhbHNlIGJlY2F1c2UgdGhlcmUgaXMgbm8gY29tbWFuZCB0byBsb29rIGZvciBtYXRjaFwiIGlmIG9wdHMuZGVidWdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvd1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWVcblxuICAgICAgICAgICAgICAgICAgICB1bmxlc3MgJyoqJyBpbiBba2V5cGF0aC1wYXJ0LCB0b3BpYy1wYXJ0XVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgdW5kZWZpbmVkIGluIFtrZXlwYXRoLXBhcnQsIHRvcGljLXBhcnRdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2cgXCJyZXR1cm5pbmcgZmFsc2UgYmVjYXVzZSB0aGVyZSBpcyBubyBjb21tYW5kIHRvIGxvb2sgZm9yIG1hdGNoXCIgaWYgb3B0cy5kZWJ1Z1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocm93XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgJyoqJyBpbiBba2V5cGF0aC1wYXJ0LCB0b3BpYy1wYXJ0XVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2cgXCJyZXR1cm5pbmcgdHJ1ZSBiZWNhdXNlICcqKicgd2lsbCBtYXRjaCB3aXRoIGFueXRoaW5nLlwiIGlmIG9wdHMuZGVidWdcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlXG5cbiAgICAgICAgICAgICAgICAgICAgaWYgdG9waWMtcGFydCBpc250IGtleXBhdGgtcGFydFxuICAgICAgICAgICAgICAgICAgICAgICAgI2NvbnNvbGUubG9nIFwidG9waWMtcGFydDogI3t0b3BpYy1wYXJ0fSwga2V5cGF0aC1wYXJ0OiAje2tleXBhdGgtcGFydH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJub3QgbWF0Y2hpbmdcIlxuXG5cbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyBcIm5vIGNvbmRpdGlvbiBicm9rZSB0aGUgbWF0Y2guXCIgaWYgb3B0cy5kZWJ1Z1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlXG4gICAgcmV0dXJuIGZhbHNlXG5cblxuZG8gdGVzdC10b3BpYy1tYXRjaCA9IC0+XG5cbiAgICAjIGZvcm1hdDpcbiAgICAjIG1lc3NhZ2UuY29tbWFuZC5jb21tYW5kLmNvbW1hbmQuLi4uXG4gICAgLypcblxuICAgICoqIHdpbGwgbWF0Y2ggd2l0aCBhbnl0aGluZywgaW5jbHVkaW5nIG51bGxcblxuICAgICovXG5cbiAgICBleGFtcGxlcyA9XG4gICAgICAgICMgc2ltcGxlIG1hdGNoZXNcbiAgICAgICAgKiB0b3BpYzogXCJmb28uYmFyXCIsIGtleXBhdGg6IFwiZm9vLipcIiwgZXhwZWN0ZWQ6IHRydWVcbiAgICAgICAgKiB0b3BpYzogXCIqLmJhclwiLCBrZXlwYXRoOiBcImZvby4qXCIsIGV4cGVjdGVkOiB0cnVlXG4gICAgICAgICogdG9waWM6IFwiZm9vLmJhclwiLCBrZXlwYXRoOiBcImJhei5iYXJcIiwgZXhwZWN0ZWQ6IGZhbHNlXG5cbiAgICAgICAgIyBtdWx0aSBtYXRjaFxuICAgICAgICAqIHRvcGljOiBcImZvby5iYXJcIiwga2V5cGF0aDogXCJiYXouYmFyIGZvby4qXCIsIGV4cGVjdGVkOiB0cnVlXG5cbiAgICAgICAgIyBhbnkgZm9vIG1lc3NhZ2VzIHRoYXQgY29udGFpbnMgZXhhY3RseSB0d28gbGV2ZWwgZGVlcCBjb21tYW5kc1xuICAgICAgICAqIHRvcGljOiBcImZvby5iYXJcIiwga2V5cGF0aDogXCJmb28uKi4qXCIsIGV4cGVjdGVkOiBmYWxzZVxuXG4gICAgICAgICMgcHVibGlzaCBleGFjdGx5IDMgbGV2ZWwgZGVlcCB0b3BpY3MsIHN1YnNjcmliZSB0byBmb28gbWVzc2FnZXNcbiAgICAgICAgIyB0aGF0IGFyZSBvbmx5IG9uZSBsZXZlbCBkZWVwLlxuICAgICAgICAqIHRvcGljOiBcImZvby4qLmJhclwiLCBrZXlwYXRoOiBcImZvby4qXCIsIGV4cGVjdGVkOiBmYWxzZVxuXG4gICAgICAgICogdG9waWM6IFwiZm9vLioqXCIsIGtleXBhdGg6IFwiZm9vXCIsIGV4cGVjdGVkOiB0cnVlXG4gICAgICAgICogdG9waWM6IFwiQGZvb1wiLCBrZXlwYXRoOiA8WyBAZm9vLioqIEBiYXIuKiogXT4sIGV4cGVjdGVkOiB0cnVlXG4gICAgICAgICogdG9waWM6IDxbIEBiYXIuKiogQGZvby1iYXIuKiogXT4sIGtleXBhdGg6IFwiQGZvby1iYXJcIiBleHBlY3RlZDogdHJ1ZVxuXG4gICAgICAgICMgZmlyc3Q6IGFueSBmb28gbWVzc2FnZXMgdGhhdCBjb250YWlucyB0d28gb3IgbW9yZSBjb21tYW5kc1xuICAgICAgICAqIHRvcGljOiBcImZvby4qLioqXCIsIGtleXBhdGg6IFwiZm9vLmJhci5iYXpcIiwgZXhwZWN0ZWQ6IHRydWVcbiAgICAgICAgKiB0b3BpYzogXCJmb28uKi4qKlwiLCBrZXlwYXRoOiBcImZvby5iYXJcIiwgZXhwZWN0ZWQ6IHRydWVcbiAgICAgICAgKiB0b3BpYzogXCJmb28uKi4qKlwiLCBrZXlwYXRoOiBcImZvby5iYXIuYmF6LnF1eFwiLCBleHBlY3RlZDogdHJ1ZVxuXG4gICAgICAgICogdG9waWM6IFwiZm9vLioqXCIsIGtleXBhdGg6IFwiZm9vLmJhci5iYXoucXV4XCIsIGV4cGVjdGVkOiB0cnVlXG4gICAgICAgICogdG9waWM6IFwiZm9vLioqXCIsIGtleXBhdGg6IFwiKi5iYXIuYmF6LnF1eFwiLCBleHBlY3RlZDogdHJ1ZVxuXG4gICAgICAgICogdG9waWM6IFwiZm9vLmJhclwiLCBrZXlwYXRoOiBcIiouKlwiLCBleHBlY3RlZDogdHJ1ZVxuICAgICAgICAqIHRvcGljOiBcImZvby5iYXJcIiwga2V5cGF0aDogXCIqXCIsIGV4cGVjdGVkOiBmYWxzZVxuICAgICAgICAqIHRvcGljOiBcIipcIiwga2V5cGF0aDogXCJmb28uYmFyXCIsIGV4cGVjdGVkOiBmYWxzZVxuICAgICAgICAqIHRvcGljOiBcImZvby5iYXJcIiwga2V5cGF0aDogXCIqKlwiLCBleHBlY3RlZDogdHJ1ZVxuXG4gICAgICAgICogdG9waWM6IFwiKlwiLCBrZXlwYXRoOiBcIipcIiwgZXhwZWN0ZWQ6IHRydWVcbiAgICAgICAgKiB0b3BpYzogXCIqKlwiLCBrZXlwYXRoOiBcIipcIiwgZXhwZWN0ZWQ6IHRydWVcbiAgICAgICAgKiB0b3BpYzogXCIqXCIsIGtleXBhdGg6IFwiKipcIiwgZXhwZWN0ZWQ6IHRydWVcbiAgICAgICAgKiB0b3BpYzogXCIqKlwiLCBrZXlwYXRoOiBcIioqXCIsIGV4cGVjdGVkOiB0cnVlXG4gICAgICAgICogdG9waWM6IFwiKi4qXCIsIGtleXBhdGg6IFwiKipcIiwgZXhwZWN0ZWQ6IHRydWVcbiAgICAgICAgKiB0b3BpYzogXCIqKlwiLCBrZXlwYXRoOiBcIiouKlwiLCBleHBlY3RlZDogdHJ1ZVxuXG4gICAgZm9yIG51bSBvZiBleGFtcGxlc1xuICAgICAgICBleGFtcGxlID0gZXhhbXBsZXNbbnVtXVxuICAgICAgICByZXN1bHQgPSBleGFtcGxlLnRvcGljIGB0b3BpYy1tYXRjaGAgZXhhbXBsZS5rZXlwYXRoXG4gICAgICAgIGlmIHJlc3VsdCBpc250IGV4YW1wbGUuZXhwZWN0ZWRcbiAgICAgICAgICAgIGNvbnNvbGUubG9nIFwiVGVzdCBmYWlsZWQgaW4gXFwjI3tudW19LCByZS1ydW5uaW5nIGluIGRlYnVnIG1vZGU6IFwiXG4gICAgICAgICAgICBjb25zb2xlLmxvZyBcImNvbXBhcmluZyBpZiAnI3tleGFtcGxlLnRvcGljfScgbWF0Y2hlcyB3aXRoICcje2V4YW1wbGUua2V5cGF0aH0nIGV4cGVjdGluZzogI3tleGFtcGxlLmV4cGVjdGVkfVwiXG4gICAgICAgICAgICBjb25zb2xlLmxvZyBcIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVwiXG4gICAgICAgICAgICB0b3BpYy1tYXRjaCBleGFtcGxlLnRvcGljLCBleGFtcGxlLmtleXBhdGgsIHsrZGVidWd9XG4gICAgICAgICAgICBjb25zb2xlLmxvZyBcIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVwiXG4gICAgICAgICAgICBwcm9jZXNzLmV4aXQgMVxuIiwicmVxdWlyZSEgJ3ByZWx1ZGUtbHMnOiB7cmVqZWN0LCBmaW5kfVxucmVxdWlyZSEgJy4uL3RvcGljLW1hdGNoJzoge3RvcGljLW1hdGNoOiByb3V0ZS1tYXRjaH1cbnJlcXVpcmUhICcuLi8uLi9saWInOiB7TG9nZ2VyLCBzbGVlcCwgaGV4fVxucmVxdWlyZSEgJy4uLy4uL2xpYi9kZWJ1Zy10b29scyc6IHticmllZn1cblxuXG5leHBvcnQgY2xhc3MgQWN0b3JNYW5hZ2VyXG4gICAgQGluc3RhbmNlID0gbnVsbFxuICAgIC0+XG4gICAgICAgICMgTWFrZSB0aGlzIGNsYXNzIFNpbmdsZXRvblxuICAgICAgICByZXR1cm4gQEBpbnN0YW5jZSBpZiBAQGluc3RhbmNlXG4gICAgICAgIEBAaW5zdGFuY2UgPSB0aGlzXG4gICAgICAgIEBhY3Rvci11aWQgPSAxICMgZmlyc3QgYWN0b3IgaWRcbiAgICAgICAgQGFjdG9ycyA9IFtdXG4gICAgICAgIEBtYW5hZ2VyLWlkID0gRGF0ZS5ub3chIHw+IGhleFxuICAgICAgICBAbG9nID0gbmV3IExvZ2dlciBcIkFjdG9yTWFuLiN7QG1hbmFnZXItaWR9XCJcblxuICAgIG5leHQtYWN0b3ItaWQ6IC0+XG4gICAgICAgIFwiYSN7QGFjdG9yLXVpZCsrfS0je0BtYW5hZ2VyLWlkfVwiXG5cbiAgICByZWdpc3Rlci1hY3RvcjogKGFjdG9yKSAtPlxuICAgICAgICB1bmxlc3MgZmluZCAoLmlkIGlzIGFjdG9yLmlkKSwgQGFjdG9yc1xuICAgICAgICAgICAgQGFjdG9ycy5wdXNoIGFjdG9yXG5cbiAgICBmaW5kLWFjdG9yOiAoaWQpIC0+XG4gICAgICAgIHRocm93ICdpZCBpcyByZXF1aXJlZCEnIHVubGVzcyBpZFxuICAgICAgICByZXR1cm4gZmluZCAoLmlkIGlzIGlkKSwgQGFjdG9yc1xuXG4gICAgZGVyZWdpc3Rlci1hY3RvcjogKGFjdG9yKSAtPlxuICAgICAgICBAYWN0b3JzID0gcmVqZWN0ICguaWQgaXMgYWN0b3IuaWQpLCBAYWN0b3JzXG5cbiAgICBkaXN0cmlidXRlOiAobXNnLCBzZW5kZXIpIC0+XG4gICAgICAgIGlmIG1zZy5kZWJ1ZyA9PiBAbG9nLmRlYnVnIFwiRGlzdHJpYnV0aW5nIG1lc3NhZ2U6IFwiLCBicmllZiBtc2dcbiAgICAgICAgZHVlLWRhdGUgPSBEYXRlLm5vdyFcbiAgICAgICAgZm9yIGFjdG9yIGluIEBhY3RvcnMgd2hlbiBhY3Rvci5pZCBpc250IHNlbmRlclxuICAgICAgICAgICAgI0Bsb2cubG9nIFwibG9va2luZyBmb3IgI3ttc2cudG99IHRvIGJlIG1hdGNoZWQgaW4gI3thY3Rvci5zdWJzY3JpcHRpb25zfVwiXG4gICAgICAgICAgICBpZiBtc2cudG8gYHJvdXRlLW1hdGNoYCBhY3Rvci5zdWJzY3JpcHRpb25zXG4gICAgICAgICAgICAgICAgaWYgbXNnLl9leGNsdWRlXG4gICAgICAgICAgICAgICAgICAgIGlmIHRoYXQgaXMgYWN0b3IuaWQgPT4gY29udGludWVcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG1zZy5fZXhjbHVkZVxuICAgICAgICAgICAgICAgICNAbG9nLmxvZyBcInB1dHRpbmcgbWVzc2FnZTogI3ttc2cuZnJvbX0uI3ttc2cuc2VxfSAtPiBhY3RvcjogI3thY3Rvci5pZH1cIiwgYWN0b3Iuc3Vic2NyaXB0aW9ucy5qb2luKCcsJylcbiAgICAgICAgICAgICAgICBkZWxheSA9IERhdGUubm93ISAtIGR1ZS1kYXRlXG4gICAgICAgICAgICAgICAgaWYgZGVsYXkgPiAxMG1zXG4gICAgICAgICAgICAgICAgICAgIEBsb2cud2FybiBcIlN5c3RlbSBsb2FkIGlzIGhpZ2g/IE1lc3NhZ2UgaXMgZGVsaXZlcmVkIGFmdGVyICN7ZGVsYXl9bXNcIlxuICAgICAgICAgICAgICAgIGFjdG9yLl9pbmJveCBtc2dcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAjQGxvZy53YXJuIFwiZHJvcHBpbmcgYXMgcm91dGVzIGFyZSBub3QgbWF0Y2hlZDogI3ttc2cudG99IHZzLiAje3JvdXRlfVwiXG4gICAgICAgICAgICAgICAgbnVsbFxuXG4gICAga2lsbDogKC4uLmFyZ3MpIC0+XG4gICAgICAgIGZvciBhY3RvciBpbiBAYWN0b3JzXG4gICAgICAgICAgICBhY3Rvci50cmlnZ2VyIFxca2lsbCwgLi4uYXJnc1xuIiwidHJ5IFxuICAgIHJlcXVpcmUhICcuLi8uLi9saWInOiB7c2xlZXAsIExvZ2dlcn1cbmNhdGNoIFxuICAgIHNsZWVwID0gKG1zLCBmKSAtPiBzZXQtdGltZW91dCBmLCBtc1xuICAgIGdldC1mb3JtYXR0ZWQtZGF0ZSA9IC0+IFxuICAgICAgICBkID0gbmV3IERhdGUgXG4gICAgICAgIFwiI3tkLmdldEZ1bGxZZWFyIX0tI3tkLmdldE1vbnRoISArIDF9LSN7ZC5nZXREYXRlIX0gI3tkLmdldEhvdXJzIX06I3tkLmdldE1pbnV0ZXMhfToje2QuZ2V0U2Vjb25kcyF9LiN7ZC5nZXRNaWxsaXNlY29uZHMhfVwiXG5cbiAgICBjbGFzcyBMb2dnZXJcbiAgICAgICAgKEBuYW1lKSAtPiBcblxuICAgICAgICBsb2c6IC0+XG4gICAgICAgICAgICBjb25zb2xlLmxvZyAuLi5bJ1snLCBnZXRGb3JtYXR0ZWREYXRlKCksICddJywgXCIje0BuYW1lfTpcIiwgLi4uYXJndW1lbnRzXVxuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBzbGVlcCwgTG9nZ2VyXG59XG4iLCJyZXF1aXJlISAnLi4vZGVwcyc6IHtzbGVlcCwgTG9nZ2VyfVxucmVxdWlyZSEgJ3ByZWx1ZGUtbHMnOiB7aXMtaXQtTmFOfVxuXG5leHBvcnQgY2xhc3MgU2lnbmFsXG4gICAgKG9wdHM9e30pIC0+XG4gICAgICAgIGlmIG9wdHMuZGVidWdcbiAgICAgICAgICAgIEBkZWJ1ZyA9IHllc1xuICAgICAgICBAbmFtZSA9IG9wdHMubmFtZSBvciBcXFNpZ25hbFxuICAgICAgICBAbG9nID0gbmV3IExvZ2dlciBAbmFtZVxuICAgICAgICBAcmVzcG9uc2UgPSBbXVxuICAgICAgICBAY2FsbGJhY2sgPSB7Y3R4OiBudWxsLCBoYW5kbGVyOiBudWxsfVxuICAgICAgICBpZiBAZGVidWcgPT4gQGxvZy5kZWJ1ZyBcIkluaXRpYWxpemVkIG5ldyBzaWduYWwuXCJcbiAgICAgICAgQHJldXNhYmxlID0gb3B0cy5yZXVzYWJsZSAjIHJldXNlIHRoZSBgd2FpdCBoYW5kbGVyYCBiZXR3ZWVuIGBmaXJlYHMgXG4gICAgICAgIEByZXNldCFcblxuICAgIGNhbmNlbDogLT5cbiAgICAgICAgQHJlc2V0IVxuXG4gICAgcmVzZXQ6IC0+XG4gICAgICAgICMgY2xlYXIgZXZlcnl0aGluZyBsaWtlIHRoZSBvYmplY3QgaXNcbiAgICAgICAgIyBpbml0aWFsaXplZCBmb3IgdGhlIGZpcnN0IHRpbWVcbiAgICAgICAgI0Bsb2cuZGVidWcgXCJSZXNldHRpbmcgc2lnbmFsLlwiXG4gICAgICAgIHVubGVzcyBAcmV1c2FibGVcbiAgICAgICAgICAgIGRlbGV0ZSBAY2FsbGJhY2suaGFuZGxlclxuICA
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment