Created
October 14, 2015 07:37
-
-
Save saukap/a607d619df3dd73f2882 to your computer and use it in GitHub Desktop.
vega datalib.js for generating externs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.dl = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | |
},{}],2:[function(require,module,exports){ | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
factory((global.dsv = {})); | |
}(this, function (exports) { 'use strict'; | |
var dsv = function(delimiter) { | |
var reFormat = new RegExp("[\"" + delimiter + "\n]"), | |
delimiterCode = delimiter.charCodeAt(0); | |
function parse(text, f) { | |
var o; | |
return parseRows(text, function(row, i) { | |
if (o) return o(row, i - 1); | |
var a = new Function("d", "return {" + row.map(function(name, i) { | |
return JSON.stringify(name) + ": d[" + i + "]"; | |
}).join(",") + "}"); | |
o = f ? function(row, i) { return f(a(row), i); } : a; | |
}); | |
} | |
function parseRows(text, f) { | |
var EOL = {}, // sentinel value for end-of-line | |
EOF = {}, // sentinel value for end-of-file | |
rows = [], // output rows | |
N = text.length, | |
I = 0, // current character index | |
n = 0, // the current line number | |
t, // the current token | |
eol; // is the current token followed by EOL? | |
function token() { | |
if (I >= N) return EOF; // special case: end of file | |
if (eol) return eol = false, EOL; // special case: end of line | |
// special case: quotes | |
var j = I; | |
if (text.charCodeAt(j) === 34) { | |
var i = j; | |
while (i++ < N) { | |
if (text.charCodeAt(i) === 34) { | |
if (text.charCodeAt(i + 1) !== 34) break; | |
++i; | |
} | |
} | |
I = i + 2; | |
var c = text.charCodeAt(i + 1); | |
if (c === 13) { | |
eol = true; | |
if (text.charCodeAt(i + 2) === 10) ++I; | |
} else if (c === 10) { | |
eol = true; | |
} | |
return text.slice(j + 1, i).replace(/""/g, "\""); | |
} | |
// common case: find next delimiter or newline | |
while (I < N) { | |
var c = text.charCodeAt(I++), k = 1; | |
if (c === 10) eol = true; // \n | |
else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n | |
else if (c !== delimiterCode) continue; | |
return text.slice(j, I - k); | |
} | |
// special case: last token before EOF | |
return text.slice(j); | |
} | |
while ((t = token()) !== EOF) { | |
var a = []; | |
while (t !== EOL && t !== EOF) { | |
a.push(t); | |
t = token(); | |
} | |
if (f && (a = f(a, n++)) == null) continue; | |
rows.push(a); | |
} | |
return rows; | |
} | |
function format(rows) { | |
if (Array.isArray(rows[0])) return formatRows(rows); // deprecated; use formatRows | |
var fieldSet = Object.create(null), fields = []; | |
// Compute unique fields in order of discovery. | |
rows.forEach(function(row) { | |
for (var field in row) { | |
if (!((field += "") in fieldSet)) { | |
fields.push(fieldSet[field] = field); | |
} | |
} | |
}); | |
return [fields.map(formatValue).join(delimiter)].concat(rows.map(function(row) { | |
return fields.map(function(field) { | |
return formatValue(row[field]); | |
}).join(delimiter); | |
})).join("\n"); | |
} | |
function formatRows(rows) { | |
return rows.map(formatRow).join("\n"); | |
} | |
function formatRow(row) { | |
return row.map(formatValue).join(delimiter); | |
} | |
function formatValue(text) { | |
return reFormat.test(text) ? "\"" + text.replace(/\"/g, "\"\"") + "\"" : text; | |
} | |
return { | |
parse: parse, | |
parseRows: parseRows, | |
format: format, | |
formatRows: formatRows | |
}; | |
} | |
exports.csv = dsv(","); | |
exports.tsv = dsv("\t"); | |
exports.dsv = dsv; | |
})); | |
},{}],3:[function(require,module,exports){ | |
if (typeof Map === "undefined") { | |
Map = function() { this.clear(); }; | |
Map.prototype = { | |
set: function(k, v) { this._[k] = v; return this; }, | |
get: function(k) { return this._[k]; }, | |
has: function(k) { return k in this._; }, | |
delete: function(k) { return k in this._ && delete this._[k]; }, | |
clear: function() { this._ = Object.create(null); }, | |
get size() { var n = 0; for (var k in this._) ++n; return n; }, | |
forEach: function(c) { for (var k in this._) c(this._[k], k, this); } | |
}; | |
} else (function() { | |
var m = new Map; | |
if (m.set(0, 0) !== m) { | |
m = m.set; | |
Map.prototype.set = function() { m.apply(this, arguments); return this; }; | |
} | |
})(); | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
factory((global.format = {})); | |
}(this, function (exports) { 'use strict'; | |
var zhCn = { | |
decimal: ".", | |
thousands: ",", | |
grouping: [3], | |
currency: ["¥", ""] | |
}; | |
var ruRu = { | |
decimal: ",", | |
thousands: "\xa0", | |
grouping: [3], | |
currency: ["", "\xa0руб."] | |
}; | |
var ptBr = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["R$", ""] | |
}; | |
var plPl = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["", "zł"] | |
}; | |
var nlNl = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["€\xa0", ""] | |
}; | |
var mkMk = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["", "\xa0ден."] | |
}; | |
var itIt = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["€", ""] | |
}; | |
var heIl = { | |
decimal: ".", | |
thousands: ",", | |
grouping: [3], | |
currency: ["₪", ""] | |
}; | |
var frFr = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["", "\xa0€"] | |
}; | |
var frCa = { | |
decimal: ",", | |
thousands: "\xa0", | |
grouping: [3], | |
currency: ["", "$"] | |
}; | |
var fiFi = { | |
decimal: ",", | |
thousands: "\xa0", | |
grouping: [3], | |
currency: ["", "\xa0€"] | |
}; | |
var esEs = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["", "\xa0€"] | |
}; | |
var enUs = { | |
decimal: ".", | |
thousands: ",", | |
grouping: [3], | |
currency: ["$", ""] | |
}; | |
var enGb = { | |
decimal: ".", | |
thousands: ",", | |
grouping: [3], | |
currency: ["£", ""] | |
}; | |
var enCa = { | |
decimal: ".", | |
thousands: ",", | |
grouping: [3], | |
currency: ["$", ""] | |
}; | |
var deDe = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["", "\xa0€"] | |
}; | |
var caEs = { | |
decimal: ",", | |
thousands: ".", | |
grouping: [3], | |
currency: ["", "\xa0€"] | |
}; | |
// Computes the decimal coefficient and exponent of the specified number x with | |
// significant digits p, where x is positive and p is in [1, 21] or undefined. | |
// For example, formatDecimal(1.23) returns ["123", 0]. | |
function formatDecimal(x, p) { | |
if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity | |
var i, coefficient = x.slice(0, i); | |
// The string returned by toExponential either has the form \d\.\d+e[-+]\d+ | |
// (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3). | |
return [ | |
coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient, | |
+x.slice(i + 1) | |
]; | |
} | |
function exponent(x) { | |
return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN; | |
} | |
var prefixExponent; | |
function formatPrefixAuto(x, p) { | |
var d = formatDecimal(x, p); | |
if (!d) return x + ""; | |
var coefficient = d[0], | |
exponent = d[1], | |
i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, | |
n = coefficient.length; | |
return i === n ? coefficient | |
: i > n ? coefficient + new Array(i - n + 1).join("0") | |
: i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i) | |
: "0." + new Array(1 - i).join("0") + formatDecimal(x, p + i - 1)[0]; // less than 1y! | |
} | |
function formatRounded(x, p) { | |
var d = formatDecimal(x, p); | |
if (!d) return x + ""; | |
var coefficient = d[0], | |
exponent = d[1]; | |
return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient | |
: coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1) | |
: coefficient + new Array(exponent - coefficient.length + 2).join("0"); | |
} | |
function formatDefault(x, p) { | |
x = x.toPrecision(p); | |
out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) { | |
switch (x[i]) { | |
case ".": i0 = i1 = i; break; | |
case "0": if (i0 === 0) i0 = i; i1 = i; break; | |
case "e": break out; | |
default: if (i0 > 0) i0 = 0; break; | |
} | |
} | |
return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x; | |
} | |
var formatTypes = { | |
"": formatDefault, | |
"%": function(x, p) { return (x * 100).toFixed(p); }, | |
"b": function(x) { return Math.round(x).toString(2); }, | |
"c": function(x) { return x + ""; }, | |
"d": function(x) { return Math.round(x).toString(10); }, | |
"e": function(x, p) { return x.toExponential(p); }, | |
"f": function(x, p) { return x.toFixed(p); }, | |
"g": function(x, p) { return x.toPrecision(p); }, | |
"o": function(x) { return Math.round(x).toString(8); }, | |
"p": function(x, p) { return formatRounded(x * 100, p); }, | |
"r": formatRounded, | |
"s": formatPrefixAuto, | |
"X": function(x) { return Math.round(x).toString(16).toUpperCase(); }, | |
"x": function(x) { return Math.round(x).toString(16); } | |
}; | |
// [[fill]align][sign][symbol][0][width][,][.precision][type] | |
var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i; | |
function formatSpecifier(specifier) { | |
return new FormatSpecifier(specifier); | |
} | |
function FormatSpecifier(specifier) { | |
if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier); | |
var match, | |
fill = match[1] || " ", | |
align = match[2] || ">", | |
sign = match[3] || "-", | |
symbol = match[4] || "", | |
zero = !!match[5], | |
width = match[6] && +match[6], | |
comma = !!match[7], | |
precision = match[8] && +match[8].slice(1), | |
type = match[9] || ""; | |
// The "n" type is an alias for ",g". | |
if (type === "n") comma = true, type = "g"; | |
// Map invalid types to the default format. | |
else if (!formatTypes[type]) type = ""; | |
// If zero fill is specified, padding goes after sign and before digits. | |
if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "="; | |
this.fill = fill; | |
this.align = align; | |
this.sign = sign; | |
this.symbol = symbol; | |
this.zero = zero; | |
this.width = width; | |
this.comma = comma; | |
this.precision = precision; | |
this.type = type; | |
} | |
FormatSpecifier.prototype.toString = function() { | |
return this.fill | |
+ this.align | |
+ this.sign | |
+ this.symbol | |
+ (this.zero ? "0" : "") | |
+ (this.width == null ? "" : Math.max(1, this.width | 0)) | |
+ (this.comma ? "," : "") | |
+ (this.precision == null ? "" : "." + Math.max(0, this.precision | 0)) | |
+ this.type; | |
}; | |
function formatGroup(grouping, thousands) { | |
return function(value, width) { | |
var i = value.length, | |
t = [], | |
j = 0, | |
g = grouping[0], | |
length = 0; | |
while (i > 0 && g > 0) { | |
if (length + g + 1 > width) g = Math.max(1, width - length); | |
t.push(value.substring(i -= g, i + g)); | |
if ((length += g + 1) > width) break; | |
g = grouping[j = (j + 1) % grouping.length]; | |
} | |
return t.reverse().join(thousands); | |
}; | |
} | |
var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"]; | |
function identity(x) { | |
return x; | |
} | |
function locale(locale) { | |
var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity, | |
currency = locale.currency, | |
decimal = locale.decimal; | |
function format(specifier) { | |
specifier = formatSpecifier(specifier); | |
var fill = specifier.fill, | |
align = specifier.align, | |
sign = specifier.sign, | |
symbol = specifier.symbol, | |
zero = specifier.zero, | |
width = specifier.width, | |
comma = specifier.comma, | |
precision = specifier.precision, | |
type = specifier.type; | |
// Compute the prefix and suffix. | |
// For SI-prefix, the suffix is lazily computed. | |
var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "", | |
suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : ""; | |
// What format function should we use? | |
// Is this an integer type? | |
// Can this type generate exponential notation? | |
var formatType = formatTypes[type], | |
maybeSuffix = !type || /[defgprs%]/.test(type); | |
// Set the default precision if not specified, | |
// or clamp the specified precision to the supported range. | |
// For significant precision, it must be in [1, 21]. | |
// For fixed precision, it must be in [0, 20]. | |
precision = precision == null ? (type ? 6 : 12) | |
: /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision)) | |
: Math.max(0, Math.min(20, precision)); | |
return function(value) { | |
var valuePrefix = prefix, | |
valueSuffix = suffix; | |
if (type === "c") { | |
valueSuffix = formatType(value) + valueSuffix; | |
value = ""; | |
} else { | |
value = +value; | |
// Convert negative to positive, and compute the prefix. | |
// Note that -0 is not less than 0, but 1 / -0 is! | |
var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true); | |
// Perform the initial formatting. | |
value = formatType(value, precision); | |
// Compute the prefix and suffix. | |
valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix; | |
valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : ""); | |
// Break the formatted value into the integer “value” part that can be | |
// grouped, and fractional or exponential “suffix” part that is not. | |
if (maybeSuffix) { | |
var i = -1, n = value.length, c; | |
while (++i < n) { | |
if (c = value.charCodeAt(i), 48 > c || c > 57) { | |
valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix; | |
value = value.slice(0, i); | |
break; | |
} | |
} | |
} | |
} | |
// If the fill character is not "0", grouping is applied before padding. | |
if (comma && !zero) value = group(value, Infinity); | |
// Compute the padding. | |
var length = valuePrefix.length + value.length + valueSuffix.length, | |
padding = length < width ? new Array(width - length + 1).join(fill) : ""; | |
// If the fill character is "0", grouping is applied after padding. | |
if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = ""; | |
// Reconstruct the final output based on the desired alignment. | |
switch (align) { | |
case "<": return valuePrefix + value + valueSuffix + padding; | |
case "=": return valuePrefix + padding + value + valueSuffix; | |
case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length); | |
} | |
return padding + valuePrefix + value + valueSuffix; | |
}; | |
} | |
function formatPrefix(specifier, value) { | |
var f = format((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)), | |
e = Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3, | |
k = Math.pow(10, -e), | |
prefix = prefixes[8 + e / 3]; | |
return function(value) { | |
return f(k * value) + prefix; | |
}; | |
} | |
return { | |
format: format, | |
formatPrefix: formatPrefix | |
}; | |
} | |
function precisionRound(step, max) { | |
return Math.max(0, exponent(Math.abs(max)) - exponent(Math.abs(step))) + 1; | |
} | |
function precisionPrefix(step, value) { | |
return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent(value) / 3))) * 3 - exponent(Math.abs(step))); | |
} | |
function precisionFixed(step) { | |
return Math.max(0, -exponent(Math.abs(step))); | |
} | |
var localeDefinitions = (new Map) | |
.set("ca-ES", caEs) | |
.set("de-DE", deDe) | |
.set("en-CA", enCa) | |
.set("en-GB", enGb) | |
.set("en-US", enUs) | |
.set("es-ES", esEs) | |
.set("fi-FI", fiFi) | |
.set("fr-CA", frCa) | |
.set("fr-FR", frFr) | |
.set("he-IL", heIl) | |
.set("it-IT", itIt) | |
.set("mk-MK", mkMk) | |
.set("nl-NL", nlNl) | |
.set("pl-PL", plPl) | |
.set("pt-BR", ptBr) | |
.set("ru-RU", ruRu) | |
.set("zh-CN", zhCn); | |
var defaultLocale = locale(enUs); | |
exports.format = defaultLocale.format; | |
exports.formatPrefix = defaultLocale.formatPrefix; | |
function localeFormat(definition) { | |
if (typeof definition === "string") { | |
definition = localeDefinitions.get(definition); | |
if (!definition) return null; | |
} | |
return locale(definition); | |
} | |
; | |
exports.localeFormat = localeFormat; | |
exports.formatSpecifier = formatSpecifier; | |
exports.precisionFixed = precisionFixed; | |
exports.precisionPrefix = precisionPrefix; | |
exports.precisionRound = precisionRound; | |
})); | |
},{}],4:[function(require,module,exports){ | |
if (typeof Map === "undefined") { | |
Map = function() { this.clear(); }; | |
Map.prototype = { | |
set: function(k, v) { this._[k] = v; return this; }, | |
get: function(k) { return this._[k]; }, | |
has: function(k) { return k in this._; }, | |
delete: function(k) { return k in this._ && delete this._[k]; }, | |
clear: function() { this._ = Object.create(null); }, | |
get size() { var n = 0; for (var k in this._) ++n; return n; }, | |
forEach: function(c) { for (var k in this._) c(this._[k], k, this); } | |
}; | |
} else (function() { | |
var m = new Map; | |
if (m.set(0, 0) !== m) { | |
m = m.set; | |
Map.prototype.set = function() { m.apply(this, arguments); return this; }; | |
} | |
})(); | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
factory((global.timeFormat = {})); | |
}(this, function (exports) { 'use strict'; | |
var zhCn = { | |
dateTime: "%a %b %e %X %Y", | |
date: "%Y/%-m/%-d", | |
time: "%H:%M:%S", | |
periods: ["上午", "下午"], | |
days: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], | |
shortDays: ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"], | |
months: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"], | |
shortMonths: ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"] | |
}; | |
var ruRu = { | |
dateTime: "%A, %e %B %Y г. %X", | |
date: "%d.%m.%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["воскресенье", "понедельник", "вторник", "среда", "четверг", "пятница", "суббота"], | |
shortDays: ["вс", "пн", "вт", "ср", "чт", "пт", "сб"], | |
months: ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"], | |
shortMonths: ["янв", "фев", "мар", "апр", "май", "июн", "июл", "авг", "сен", "окт", "ноя", "дек"] | |
}; | |
var ptBr = { | |
dateTime: "%A, %e de %B de %Y. %X", | |
date: "%d/%m/%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"], | |
shortDays: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"], | |
months: ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"], | |
shortMonths: ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"] | |
}; | |
var plPl = { | |
dateTime: "%A, %e %B %Y, %X", | |
date: "%d/%m/%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], // unused | |
days: ["Niedziela", "Poniedziałek", "Wtorek", "Środa", "Czwartek", "Piątek", "Sobota"], | |
shortDays: ["Niedz.", "Pon.", "Wt.", "Śr.", "Czw.", "Pt.", "Sob."], | |
months: ["Styczeń", "Luty", "Marzec", "Kwiecień", "Maj", "Czerwiec", "Lipiec", "Sierpień", "Wrzesień", "Październik", "Listopad", "Grudzień"], | |
shortMonths: ["Stycz.", "Luty", "Marz.", "Kwie.", "Maj", "Czerw.", "Lipc.", "Sierp.", "Wrz.", "Paźdz.", "Listop.", "Grudz."]/* In Polish language abbraviated months are not commonly used so there is a dispute about the proper abbraviations. */ | |
}; | |
var nlNl = { | |
dateTime: "%a %e %B %Y %T", | |
date: "%d-%m-%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], // unused | |
days: ["zondag", "maandag", "dinsdag", "woensdag", "donderdag", "vrijdag", "zaterdag"], | |
shortDays: ["zo", "ma", "di", "wo", "do", "vr", "za"], | |
months: ["januari", "februari", "maart", "april", "mei", "juni", "juli", "augustus", "september", "oktober", "november", "december"], | |
shortMonths: ["jan", "feb", "mrt", "apr", "mei", "jun", "jul", "aug", "sep", "okt", "nov", "dec"] | |
}; | |
var mkMk = { | |
dateTime: "%A, %e %B %Y г. %X", | |
date: "%d.%m.%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["недела", "понеделник", "вторник", "среда", "четврток", "петок", "сабота"], | |
shortDays: ["нед", "пон", "вто", "сре", "чет", "пет", "саб"], | |
months: ["јануари", "февруари", "март", "април", "мај", "јуни", "јули", "август", "септември", "октомври", "ноември", "декември"], | |
shortMonths: ["јан", "фев", "мар", "апр", "мај", "јун", "јул", "авг", "сеп", "окт", "ное", "дек"] | |
}; | |
var itIt = { | |
dateTime: "%A %e %B %Y, %X", | |
date: "%d/%m/%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], // unused | |
days: ["Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"], | |
shortDays: ["Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"], | |
months: ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno", "Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"], | |
shortMonths: ["Gen", "Feb", "Mar", "Apr", "Mag", "Giu", "Lug", "Ago", "Set", "Ott", "Nov", "Dic"] | |
}; | |
var heIl = { | |
dateTime: "%A, %e ב%B %Y %X", | |
date: "%d.%m.%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["ראשון", "שני", "שלישי", "רביעי", "חמישי", "שישי", "שבת"], | |
shortDays: ["א׳", "ב׳", "ג׳", "ד׳", "ה׳", "ו׳", "ש׳"], | |
months: ["ינואר", "פברואר", "מרץ", "אפריל", "מאי", "יוני", "יולי", "אוגוסט", "ספטמבר", "אוקטובר", "נובמבר", "דצמבר"], | |
shortMonths: ["ינו׳", "פבר׳", "מרץ", "אפר׳", "מאי", "יוני", "יולי", "אוג׳", "ספט׳", "אוק׳", "נוב׳", "דצמ׳"] | |
}; | |
var frFr = { | |
dateTime: "%A, le %e %B %Y, %X", | |
date: "%d/%m/%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], // unused | |
days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"], | |
shortDays: ["dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."], | |
months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"], | |
shortMonths: ["janv.", "févr.", "mars", "avr.", "mai", "juin", "juil.", "août", "sept.", "oct.", "nov.", "déc."] | |
}; | |
var frCa = { | |
dateTime: "%a %e %b %Y %X", | |
date: "%Y-%m-%d", | |
time: "%H:%M:%S", | |
periods: ["", ""], | |
days: ["dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"], | |
shortDays: ["dim", "lun", "mar", "mer", "jeu", "ven", "sam"], | |
months: ["janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"], | |
shortMonths: ["jan", "fév", "mar", "avr", "mai", "jui", "jul", "aoû", "sep", "oct", "nov", "déc"] | |
}; | |
var fiFi = { | |
dateTime: "%A, %-d. %Bta %Y klo %X", | |
date: "%-d.%-m.%Y", | |
time: "%H:%M:%S", | |
periods: ["a.m.", "p.m."], | |
days: ["sunnuntai", "maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai"], | |
shortDays: ["Su", "Ma", "Ti", "Ke", "To", "Pe", "La"], | |
months: ["tammikuu", "helmikuu", "maaliskuu", "huhtikuu", "toukokuu", "kesäkuu", "heinäkuu", "elokuu", "syyskuu", "lokakuu", "marraskuu", "joulukuu"], | |
shortMonths: ["Tammi", "Helmi", "Maalis", "Huhti", "Touko", "Kesä", "Heinä", "Elo", "Syys", "Loka", "Marras", "Joulu"] | |
}; | |
var esEs = { | |
dateTime: "%A, %e de %B de %Y, %X", | |
date: "%d/%m/%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"], | |
shortDays: ["dom", "lun", "mar", "mié", "jue", "vie", "sáb"], | |
months: ["enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"], | |
shortMonths: ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"] | |
}; | |
var enUs = { | |
dateTime: "%a %b %e %X %Y", | |
date: "%m/%d/%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], | |
shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], | |
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], | |
shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] | |
}; | |
var enGb = { | |
dateTime: "%a %e %b %X %Y", | |
date: "%d/%m/%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], | |
shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], | |
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], | |
shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] | |
}; | |
var enCa = { | |
dateTime: "%a %b %e %X %Y", | |
date: "%Y-%m-%d", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], | |
shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], | |
months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], | |
shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] | |
}; | |
var deDe = { | |
dateTime: "%A, der %e. %B %Y, %X", | |
date: "%d.%m.%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], // unused | |
days: ["Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"], | |
shortDays: ["So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"], | |
months: ["Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"], | |
shortMonths: ["Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"] | |
}; | |
var caEs = { | |
dateTime: "%A, %e de %B de %Y, %X", | |
date: "%d/%m/%Y", | |
time: "%H:%M:%S", | |
periods: ["AM", "PM"], | |
days: ["diumenge", "dilluns", "dimarts", "dimecres", "dijous", "divendres", "dissabte"], | |
shortDays: ["dg.", "dl.", "dt.", "dc.", "dj.", "dv.", "ds."], | |
months: ["gener", "febrer", "març", "abril", "maig", "juny", "juliol", "agost", "setembre", "octubre", "novembre", "desembre"], | |
shortMonths: ["gen.", "febr.", "març", "abr.", "maig", "juny", "jul.", "ag.", "set.", "oct.", "nov.", "des."] | |
}; | |
var t0 = new Date; | |
var t1 = new Date; | |
function newInterval(floori, offseti, count) { | |
function interval(date) { | |
return floori(date = new Date(+date)), date; | |
} | |
interval.floor = interval; | |
interval.round = function(date) { | |
var d0 = new Date(+date), | |
d1 = new Date(date - 1); | |
floori(d0), floori(d1), offseti(d1, 1); | |
return date - d0 < d1 - date ? d0 : d1; | |
}; | |
interval.ceil = function(date) { | |
return floori(date = new Date(date - 1)), offseti(date, 1), date; | |
}; | |
interval.offset = function(date, step) { | |
return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; | |
}; | |
interval.range = function(start, stop, step) { | |
var range = []; | |
start = new Date(start - 1); | |
stop = new Date(+stop); | |
step = step == null ? 1 : Math.floor(step); | |
if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date | |
offseti(start, 1), floori(start); | |
if (start < stop) range.push(new Date(+start)); | |
while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start)); | |
return range; | |
}; | |
interval.filter = function(test) { | |
return newInterval(function(date) { | |
while (floori(date), !test(date)) date.setTime(date - 1); | |
}, function(date, step) { | |
while (--step >= 0) while (offseti(date, 1), !test(date)); | |
}); | |
}; | |
if (count) interval.count = function(start, end) { | |
t0.setTime(+start), t1.setTime(+end); | |
floori(t0), floori(t1); | |
return Math.floor(count(t0, t1)); | |
}; | |
return interval; | |
} | |
var day = newInterval(function(date) { | |
date.setHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setDate(date.getDate() + step); | |
}, function(start, end) { | |
return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5; | |
}); | |
function weekday(i) { | |
return newInterval(function(date) { | |
date.setHours(0, 0, 0, 0); | |
date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); | |
}, function(date, step) { | |
date.setDate(date.getDate() + step * 7); | |
}, function(start, end) { | |
return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5; | |
}); | |
} | |
var sunday = weekday(0); | |
var monday = weekday(1); | |
var year = newInterval(function(date) { | |
date.setHours(0, 0, 0, 0); | |
date.setMonth(0, 1); | |
}, function(date, step) { | |
date.setFullYear(date.getFullYear() + step); | |
}, function(start, end) { | |
return end.getFullYear() - start.getFullYear(); | |
}); | |
var utcDay = newInterval(function(date) { | |
date.setUTCHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setUTCDate(date.getUTCDate() + step); | |
}, function(start, end) { | |
return (end - start) / 864e5; | |
}); | |
function utcWeekday(i) { | |
return newInterval(function(date) { | |
date.setUTCHours(0, 0, 0, 0); | |
date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); | |
}, function(date, step) { | |
date.setUTCDate(date.getUTCDate() + step * 7); | |
}, function(start, end) { | |
return (end - start) / 6048e5; | |
}); | |
} | |
var utcSunday = utcWeekday(0); | |
var utcMonday = utcWeekday(1); | |
var utcYear = newInterval(function(date) { | |
date.setUTCHours(0, 0, 0, 0); | |
date.setUTCMonth(0, 1); | |
}, function(date, step) { | |
date.setUTCFullYear(date.getUTCFullYear() + step); | |
}, function(start, end) { | |
return end.getUTCFullYear() - start.getUTCFullYear(); | |
}); | |
function localDate(d) { | |
if (0 <= d.y && d.y < 100) { | |
var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L); | |
date.setFullYear(d.y); | |
return date; | |
} | |
return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L); | |
} | |
function utcDate(d) { | |
if (0 <= d.y && d.y < 100) { | |
var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L)); | |
date.setUTCFullYear(d.y); | |
return date; | |
} | |
return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L)); | |
} | |
function newYear(y) { | |
return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0}; | |
} | |
function locale(locale) { | |
var locale_dateTime = locale.dateTime, | |
locale_date = locale.date, | |
locale_time = locale.time, | |
locale_periods = locale.periods, | |
locale_weekdays = locale.days, | |
locale_shortWeekdays = locale.shortDays, | |
locale_months = locale.months, | |
locale_shortMonths = locale.shortMonths; | |
var periodLookup = formatLookup(locale_periods), | |
weekdayRe = formatRe(locale_weekdays), | |
weekdayLookup = formatLookup(locale_weekdays), | |
shortWeekdayRe = formatRe(locale_shortWeekdays), | |
shortWeekdayLookup = formatLookup(locale_shortWeekdays), | |
monthRe = formatRe(locale_months), | |
monthLookup = formatLookup(locale_months), | |
shortMonthRe = formatRe(locale_shortMonths), | |
shortMonthLookup = formatLookup(locale_shortMonths); | |
var formats = { | |
"a": formatShortWeekday, | |
"A": formatWeekday, | |
"b": formatShortMonth, | |
"B": formatMonth, | |
"c": null, | |
"d": formatDayOfMonth, | |
"e": formatDayOfMonth, | |
"H": formatHour24, | |
"I": formatHour12, | |
"j": formatDayOfYear, | |
"L": formatMilliseconds, | |
"m": formatMonthNumber, | |
"M": formatMinutes, | |
"p": formatPeriod, | |
"S": formatSeconds, | |
"U": formatWeekNumberSunday, | |
"w": formatWeekdayNumber, | |
"W": formatWeekNumberMonday, | |
"x": null, | |
"X": null, | |
"y": formatYear, | |
"Y": formatFullYear, | |
"Z": formatZone, | |
"%": formatLiteralPercent | |
}; | |
var utcFormats = { | |
"a": formatUTCShortWeekday, | |
"A": formatUTCWeekday, | |
"b": formatUTCShortMonth, | |
"B": formatUTCMonth, | |
"c": null, | |
"d": formatUTCDayOfMonth, | |
"e": formatUTCDayOfMonth, | |
"H": formatUTCHour24, | |
"I": formatUTCHour12, | |
"j": formatUTCDayOfYear, | |
"L": formatUTCMilliseconds, | |
"m": formatUTCMonthNumber, | |
"M": formatUTCMinutes, | |
"p": formatUTCPeriod, | |
"S": formatUTCSeconds, | |
"U": formatUTCWeekNumberSunday, | |
"w": formatUTCWeekdayNumber, | |
"W": formatUTCWeekNumberMonday, | |
"x": null, | |
"X": null, | |
"y": formatUTCYear, | |
"Y": formatUTCFullYear, | |
"Z": formatUTCZone, | |
"%": formatLiteralPercent | |
}; | |
var parses = { | |
"a": parseShortWeekday, | |
"A": parseWeekday, | |
"b": parseShortMonth, | |
"B": parseMonth, | |
"c": parseLocaleDateTime, | |
"d": parseDayOfMonth, | |
"e": parseDayOfMonth, | |
"H": parseHour24, | |
"I": parseHour24, | |
"j": parseDayOfYear, | |
"L": parseMilliseconds, | |
"m": parseMonthNumber, | |
"M": parseMinutes, | |
"p": parsePeriod, | |
"S": parseSeconds, | |
"U": parseWeekNumberSunday, | |
"w": parseWeekdayNumber, | |
"W": parseWeekNumberMonday, | |
"x": parseLocaleDate, | |
"X": parseLocaleTime, | |
"y": parseYear, | |
"Y": parseFullYear, | |
"Z": parseZone, | |
"%": parseLiteralPercent | |
}; | |
// These recursive directive definitions must be deferred. | |
formats.x = newFormat(locale_date, formats); | |
formats.X = newFormat(locale_time, formats); | |
formats.c = newFormat(locale_dateTime, formats); | |
utcFormats.x = newFormat(locale_date, utcFormats); | |
utcFormats.X = newFormat(locale_time, utcFormats); | |
utcFormats.c = newFormat(locale_dateTime, utcFormats); | |
function newFormat(specifier, formats) { | |
return function(date) { | |
var string = [], | |
i = -1, | |
j = 0, | |
n = specifier.length, | |
c, | |
pad, | |
format; | |
while (++i < n) { | |
if (specifier.charCodeAt(i) === 37) { | |
string.push(specifier.slice(j, i)); | |
if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i); | |
if (format = formats[c]) c = format(date, pad == null ? (c === "e" ? " " : "0") : pad); | |
string.push(c); | |
j = i + 1; | |
} | |
} | |
string.push(specifier.slice(j, i)); | |
return string.join(""); | |
}; | |
} | |
function newParse(specifier, newDate) { | |
return function(string) { | |
var d = newYear(1900), | |
i = parseSpecifier(d, specifier, string, 0); | |
if (i != string.length) return null; | |
// The am-pm flag is 0 for AM, and 1 for PM. | |
if ("p" in d) d.H = d.H % 12 + d.p * 12; | |
// If a time zone is specified, all fields are interpreted as UTC and then | |
// offset according to the specified time zone. | |
if ("Z" in d) { | |
if ("w" in d && ("W" in d || "U" in d)) { | |
var day = utcDate(newYear(d.y)).getUTCDay(); | |
if ("W" in d) d.U = d.W, d.w = (d.w + 6) % 7, --day; | |
d.m = 0; | |
d.d = d.w + d.U * 7 - (day + 6) % 7; | |
} | |
d.H += d.Z / 100 | 0; | |
d.M += d.Z % 100; | |
return utcDate(d); | |
} | |
// Otherwise, all fields are in local time. | |
if ("w" in d && ("W" in d || "U" in d)) { | |
var day = newDate(newYear(d.y)).getDay(); | |
if ("W" in d) d.U = d.W, d.w = (d.w + 6) % 7, --day; | |
d.m = 0; | |
d.d = d.w + d.U * 7 - (day + 6) % 7; | |
} | |
return newDate(d); | |
}; | |
} | |
function parseSpecifier(d, specifier, string, j) { | |
var i = 0, | |
n = specifier.length, | |
m = string.length, | |
c, | |
parse; | |
while (i < n) { | |
if (j >= m) return -1; | |
c = specifier.charCodeAt(i++); | |
if (c === 37) { | |
c = specifier.charAt(i++); | |
parse = parses[c in pads ? specifier.charAt(i++) : c]; | |
if (!parse || ((j = parse(d, string, j)) < 0)) return -1; | |
} else if (c != string.charCodeAt(j++)) { | |
return -1; | |
} | |
} | |
return j; | |
} | |
function parseShortWeekday(d, string, i) { | |
var n = shortWeekdayRe.exec(string.slice(i)); | |
return n ? (d.w = shortWeekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
} | |
function parseWeekday(d, string, i) { | |
var n = weekdayRe.exec(string.slice(i)); | |
return n ? (d.w = weekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
} | |
function parseShortMonth(d, string, i) { | |
var n = shortMonthRe.exec(string.slice(i)); | |
return n ? (d.m = shortMonthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
} | |
function parseMonth(d, string, i) { | |
var n = monthRe.exec(string.slice(i)); | |
return n ? (d.m = monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1; | |
} | |
function parseLocaleDateTime(d, string, i) { | |
return parseSpecifier(d, locale_dateTime, string, i); | |
} | |
function parseLocaleDate(d, string, i) { | |
return parseSpecifier(d, locale_date, string, i); | |
} | |
function parseLocaleTime(d, string, i) { | |
return parseSpecifier(d, locale_time, string, i); | |
} | |
function parsePeriod(d, string, i) { | |
var n = periodLookup.get(string.slice(i, i += 2).toLowerCase()); | |
return n == null ? -1 : (d.p = n, i); | |
} | |
function formatShortWeekday(d) { | |
return locale_shortWeekdays[d.getDay()]; | |
} | |
function formatWeekday(d) { | |
return locale_weekdays[d.getDay()]; | |
} | |
function formatShortMonth(d) { | |
return locale_shortMonths[d.getMonth()]; | |
} | |
function formatMonth(d) { | |
return locale_months[d.getMonth()]; | |
} | |
function formatPeriod(d) { | |
return locale_periods[+(d.getHours() >= 12)]; | |
} | |
function formatUTCShortWeekday(d) { | |
return locale_shortWeekdays[d.getUTCDay()]; | |
} | |
function formatUTCWeekday(d) { | |
return locale_weekdays[d.getUTCDay()]; | |
} | |
function formatUTCShortMonth(d) { | |
return locale_shortMonths[d.getUTCMonth()]; | |
} | |
function formatUTCMonth(d) { | |
return locale_months[d.getUTCMonth()]; | |
} | |
function formatUTCPeriod(d) { | |
return locale_periods[+(d.getUTCHours() >= 12)]; | |
} | |
return { | |
format: function(specifier) { | |
var f = newFormat(specifier += "", formats); | |
f.parse = newParse(specifier, localDate); | |
f.toString = function() { return specifier; }; | |
return f; | |
}, | |
utcFormat: function(specifier) { | |
var f = newFormat(specifier += "", utcFormats); | |
f.parse = newParse(specifier, utcDate); | |
f.toString = function() { return specifier; }; | |
return f; | |
} | |
}; | |
} | |
var pads = {"-": "", "_": " ", "0": "0"}; | |
var numberRe = /^\s*\d+/; | |
var percentRe = /^%/; | |
var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g; | |
function pad(value, fill, width) { | |
var sign = value < 0 ? "-" : "", | |
string = (sign ? -value : value) + "", | |
length = string.length; | |
return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string); | |
} | |
function requote(s) { | |
return s.replace(requoteRe, "\\$&"); | |
} | |
function formatRe(names) { | |
return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i"); | |
} | |
function formatLookup(names) { | |
var map = new Map, i = -1, n = names.length; | |
while (++i < n) map.set(names[i].toLowerCase(), i); | |
return map; | |
} | |
function parseWeekdayNumber(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 1)); | |
return n ? (d.w = +n[0], i + n[0].length) : -1; | |
} | |
function parseWeekNumberSunday(d, string, i) { | |
var n = numberRe.exec(string.slice(i)); | |
return n ? (d.U = +n[0], i + n[0].length) : -1; | |
} | |
function parseWeekNumberMonday(d, string, i) { | |
var n = numberRe.exec(string.slice(i)); | |
return n ? (d.W = +n[0], i + n[0].length) : -1; | |
} | |
function parseFullYear(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 4)); | |
return n ? (d.y = +n[0], i + n[0].length) : -1; | |
} | |
function parseYear(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1; | |
} | |
function parseZone(d, string, i) { | |
return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) | |
? (d.Z = -string, i + 5) // sign differs from getTimezoneOffset! | |
: -1; | |
} | |
function parseMonthNumber(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.m = n[0] - 1, i + n[0].length) : -1; | |
} | |
function parseDayOfMonth(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.d = +n[0], i + n[0].length) : -1; | |
} | |
function parseDayOfYear(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 3)); | |
return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1; | |
} | |
function parseHour24(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.H = +n[0], i + n[0].length) : -1; | |
} | |
function parseMinutes(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.M = +n[0], i + n[0].length) : -1; | |
} | |
function parseSeconds(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 2)); | |
return n ? (d.S = +n[0], i + n[0].length) : -1; | |
} | |
function parseMilliseconds(d, string, i) { | |
var n = numberRe.exec(string.slice(i, i + 3)); | |
return n ? (d.L = +n[0], i + n[0].length) : -1; | |
} | |
function parseLiteralPercent(d, string, i) { | |
var n = percentRe.exec(string.slice(i, i + 1)); | |
return n ? i + n[0].length : -1; | |
} | |
function formatDayOfMonth(d, p) { | |
return pad(d.getDate(), p, 2); | |
} | |
function formatHour24(d, p) { | |
return pad(d.getHours(), p, 2); | |
} | |
function formatHour12(d, p) { | |
return pad(d.getHours() % 12 || 12, p, 2); | |
} | |
function formatDayOfYear(d, p) { | |
return pad(1 + day.count(year(d), d), p, 3); | |
} | |
function formatMilliseconds(d, p) { | |
return pad(d.getMilliseconds(), p, 3); | |
} | |
function formatMonthNumber(d, p) { | |
return pad(d.getMonth() + 1, p, 2); | |
} | |
function formatMinutes(d, p) { | |
return pad(d.getMinutes(), p, 2); | |
} | |
function formatSeconds(d, p) { | |
return pad(d.getSeconds(), p, 2); | |
} | |
function formatWeekNumberSunday(d, p) { | |
return pad(sunday.count(year(d), d), p, 2); | |
} | |
function formatWeekdayNumber(d) { | |
return d.getDay(); | |
} | |
function formatWeekNumberMonday(d, p) { | |
return pad(monday.count(year(d), d), p, 2); | |
} | |
function formatYear(d, p) { | |
return pad(d.getFullYear() % 100, p, 2); | |
} | |
function formatFullYear(d, p) { | |
return pad(d.getFullYear() % 10000, p, 4); | |
} | |
function formatZone(d) { | |
var z = d.getTimezoneOffset(); | |
return (z > 0 ? "-" : (z *= -1, "+")) | |
+ pad(z / 60 | 0, "0", 2) | |
+ pad(z % 60, "0", 2); | |
} | |
function formatUTCDayOfMonth(d, p) { | |
return pad(d.getUTCDate(), p, 2); | |
} | |
function formatUTCHour24(d, p) { | |
return pad(d.getUTCHours(), p, 2); | |
} | |
function formatUTCHour12(d, p) { | |
return pad(d.getUTCHours() % 12 || 12, p, 2); | |
} | |
function formatUTCDayOfYear(d, p) { | |
return pad(1 + utcDay.count(utcYear(d), d), p, 3); | |
} | |
function formatUTCMilliseconds(d, p) { | |
return pad(d.getUTCMilliseconds(), p, 3); | |
} | |
function formatUTCMonthNumber(d, p) { | |
return pad(d.getUTCMonth() + 1, p, 2); | |
} | |
function formatUTCMinutes(d, p) { | |
return pad(d.getUTCMinutes(), p, 2); | |
} | |
function formatUTCSeconds(d, p) { | |
return pad(d.getUTCSeconds(), p, 2); | |
} | |
function formatUTCWeekNumberSunday(d, p) { | |
return pad(utcSunday.count(utcYear(d), d), p, 2); | |
} | |
function formatUTCWeekdayNumber(d) { | |
return d.getUTCDay(); | |
} | |
function formatUTCWeekNumberMonday(d, p) { | |
return pad(utcMonday.count(utcYear(d), d), p, 2); | |
} | |
function formatUTCYear(d, p) { | |
return pad(d.getUTCFullYear() % 100, p, 2); | |
} | |
function formatUTCFullYear(d, p) { | |
return pad(d.getUTCFullYear() % 10000, p, 4); | |
} | |
function formatUTCZone() { | |
return "+0000"; | |
} | |
function formatLiteralPercent() { | |
return "%"; | |
} | |
var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ"; | |
function formatIsoNative(date) { | |
return date.toISOString(); | |
} | |
formatIsoNative.parse = function(string) { | |
var date = new Date(string); | |
return isNaN(date) ? null : date; | |
}; | |
formatIsoNative.toString = function() { | |
return isoSpecifier; | |
}; | |
var formatIso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") | |
? formatIsoNative | |
: enUs.utcFormat(isoSpecifier); | |
var isoFormat = formatIso; | |
var localeDefinitions = (new Map) | |
.set("ca-ES", caEs) | |
.set("de-DE", deDe) | |
.set("en-CA", enCa) | |
.set("en-GB", enGb) | |
.set("en-US", enUs) | |
.set("es-ES", esEs) | |
.set("fi-FI", fiFi) | |
.set("fr-CA", frCa) | |
.set("fr-FR", frFr) | |
.set("he-IL", heIl) | |
.set("it-IT", itIt) | |
.set("mk-MK", mkMk) | |
.set("nl-NL", nlNl) | |
.set("pl-PL", plPl) | |
.set("pt-BR", ptBr) | |
.set("ru-RU", ruRu) | |
.set("zh-CN", zhCn); | |
var defaultLocale = locale(enUs); | |
exports.format = defaultLocale.format; | |
exports.utcFormat = defaultLocale.utcFormat; | |
function localeFormat(definition) { | |
if (typeof definition === "string") { | |
definition = localeDefinitions.get(definition); | |
if (!definition) return null; | |
} | |
return locale(definition); | |
} | |
; | |
exports.localeFormat = localeFormat; | |
exports.isoFormat = isoFormat; | |
})); | |
},{}],5:[function(require,module,exports){ | |
(function (global, factory) { | |
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : | |
typeof define === 'function' && define.amd ? define(['exports'], factory) : | |
factory((global.time = {})); | |
}(this, function (exports) { 'use strict'; | |
var t1 = new Date; | |
var t0 = new Date; | |
function newInterval(floori, offseti, count) { | |
function interval(date) { | |
return floori(date = new Date(+date)), date; | |
} | |
interval.floor = interval; | |
interval.round = function(date) { | |
var d0 = new Date(+date), | |
d1 = new Date(date - 1); | |
floori(d0), floori(d1), offseti(d1, 1); | |
return date - d0 < d1 - date ? d0 : d1; | |
}; | |
interval.ceil = function(date) { | |
return floori(date = new Date(date - 1)), offseti(date, 1), date; | |
}; | |
interval.offset = function(date, step) { | |
return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date; | |
}; | |
interval.range = function(start, stop, step) { | |
var range = []; | |
start = new Date(start - 1); | |
stop = new Date(+stop); | |
step = step == null ? 1 : Math.floor(step); | |
if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date | |
offseti(start, 1), floori(start); | |
if (start < stop) range.push(new Date(+start)); | |
while (offseti(start, step), floori(start), start < stop) range.push(new Date(+start)); | |
return range; | |
}; | |
interval.filter = function(test) { | |
return newInterval(function(date) { | |
while (floori(date), !test(date)) date.setTime(date - 1); | |
}, function(date, step) { | |
while (--step >= 0) while (offseti(date, 1), !test(date)); | |
}); | |
}; | |
if (count) interval.count = function(start, end) { | |
t0.setTime(+start), t1.setTime(+end); | |
floori(t0), floori(t1); | |
return Math.floor(count(t0, t1)); | |
}; | |
return interval; | |
} | |
var second = newInterval(function(date) { | |
date.setMilliseconds(0); | |
}, function(date, step) { | |
date.setTime(+date + step * 1e3); | |
}, function(start, end) { | |
return (end - start) / 1e3; | |
}); | |
exports.seconds = second.range; | |
var minute = newInterval(function(date) { | |
date.setSeconds(0, 0); | |
}, function(date, step) { | |
date.setTime(+date + step * 6e4); | |
}, function(start, end) { | |
return (end - start) / 6e4; | |
}); | |
exports.minutes = minute.range; | |
var hour = newInterval(function(date) { | |
date.setMinutes(0, 0, 0); | |
}, function(date, step) { | |
date.setTime(+date + step * 36e5); | |
}, function(start, end) { | |
return (end - start) / 36e5; | |
}); | |
exports.hours = hour.range; | |
var day = newInterval(function(date) { | |
date.setHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setDate(date.getDate() + step); | |
}, function(start, end) { | |
return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 864e5; | |
}); | |
exports.days = day.range; | |
function weekday(i) { | |
return newInterval(function(date) { | |
date.setHours(0, 0, 0, 0); | |
date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7); | |
}, function(date, step) { | |
date.setDate(date.getDate() + step * 7); | |
}, function(start, end) { | |
return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * 6e4) / 6048e5; | |
}); | |
} | |
exports.sunday = weekday(0); | |
exports.sundays = exports.sunday.range; | |
exports.monday = weekday(1); | |
exports.mondays = exports.monday.range; | |
exports.tuesday = weekday(2); | |
exports.tuesdays = exports.tuesday.range; | |
exports.wednesday = weekday(3); | |
exports.wednesdays = exports.wednesday.range; | |
exports.thursday = weekday(4); | |
exports.thursdays = exports.thursday.range; | |
exports.friday = weekday(5); | |
exports.fridays = exports.friday.range; | |
exports.saturday = weekday(6); | |
exports.saturdays = exports.saturday.range; | |
var week = exports.sunday; | |
exports.weeks = week.range; | |
var month = newInterval(function(date) { | |
date.setHours(0, 0, 0, 0); | |
date.setDate(1); | |
}, function(date, step) { | |
date.setMonth(date.getMonth() + step); | |
}, function(start, end) { | |
return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12; | |
}); | |
exports.months = month.range; | |
var year = newInterval(function(date) { | |
date.setHours(0, 0, 0, 0); | |
date.setMonth(0, 1); | |
}, function(date, step) { | |
date.setFullYear(date.getFullYear() + step); | |
}, function(start, end) { | |
return end.getFullYear() - start.getFullYear(); | |
}); | |
exports.years = year.range; | |
var utcSecond = newInterval(function(date) { | |
date.setUTCMilliseconds(0); | |
}, function(date, step) { | |
date.setTime(+date + step * 1e3); | |
}, function(start, end) { | |
return (end - start) / 1e3; | |
}); | |
exports.utcSeconds = utcSecond.range; | |
var utcMinute = newInterval(function(date) { | |
date.setUTCSeconds(0, 0); | |
}, function(date, step) { | |
date.setTime(+date + step * 6e4); | |
}, function(start, end) { | |
return (end - start) / 6e4; | |
}); | |
exports.utcMinutes = utcMinute.range; | |
var utcHour = newInterval(function(date) { | |
date.setUTCMinutes(0, 0, 0); | |
}, function(date, step) { | |
date.setTime(+date + step * 36e5); | |
}, function(start, end) { | |
return (end - start) / 36e5; | |
}); | |
exports.utcHours = utcHour.range; | |
var utcDay = newInterval(function(date) { | |
date.setUTCHours(0, 0, 0, 0); | |
}, function(date, step) { | |
date.setUTCDate(date.getUTCDate() + step); | |
}, function(start, end) { | |
return (end - start) / 864e5; | |
}); | |
exports.utcDays = utcDay.range; | |
function utcWeekday(i) { | |
return newInterval(function(date) { | |
date.setUTCHours(0, 0, 0, 0); | |
date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7); | |
}, function(date, step) { | |
date.setUTCDate(date.getUTCDate() + step * 7); | |
}, function(start, end) { | |
return (end - start) / 6048e5; | |
}); | |
} | |
exports.utcSunday = utcWeekday(0); | |
exports.utcSundays = exports.utcSunday.range; | |
exports.utcMonday = utcWeekday(1); | |
exports.utcMondays = exports.utcMonday.range; | |
exports.utcTuesday = utcWeekday(2); | |
exports.utcTuesdays = exports.utcTuesday.range; | |
exports.utcWednesday = utcWeekday(3); | |
exports.utcWednesdays = exports.utcWednesday.range; | |
exports.utcThursday = utcWeekday(4); | |
exports.utcThursdays = exports.utcThursday.range; | |
exports.utcFriday = utcWeekday(5); | |
exports.utcFridays = exports.utcFriday.range; | |
exports.utcSaturday = utcWeekday(6); | |
exports.utcSaturdays = exports.utcSaturday.range; | |
var utcWeek = exports.utcSunday; | |
exports.utcWeeks = utcWeek.range; | |
var utcMonth = newInterval(function(date) { | |
date.setUTCHours(0, 0, 0, 0); | |
date.setUTCDate(1); | |
}, function(date, step) { | |
date.setUTCMonth(date.getUTCMonth() + step); | |
}, function(start, end) { | |
return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12; | |
}); | |
exports.utcMonths = utcMonth.range; | |
var utcYear = newInterval(function(date) { | |
date.setUTCHours(0, 0, 0, 0); | |
date.setUTCMonth(0, 1); | |
}, function(date, step) { | |
date.setUTCFullYear(date.getUTCFullYear() + step); | |
}, function(start, end) { | |
return end.getUTCFullYear() - start.getUTCFullYear(); | |
}); | |
exports.utcYears = utcYear.range; | |
exports.interval = newInterval; | |
exports.second = second; | |
exports.minute = minute; | |
exports.hour = hour; | |
exports.day = day; | |
exports.week = week; | |
exports.month = month; | |
exports.year = year; | |
exports.utcSecond = utcSecond; | |
exports.utcMinute = utcMinute; | |
exports.utcHour = utcHour; | |
exports.utcDay = utcDay; | |
exports.utcWeek = utcWeek; | |
exports.utcMonth = utcMonth; | |
exports.utcYear = utcYear; | |
})); | |
},{}],6:[function(require,module,exports){ | |
var util = require('../util'), | |
Measures = require('./measures'), | |
Collector = require('./collector'); | |
function Aggregator() { | |
this._cells = {}; | |
this._aggr = []; | |
this._stream = false; | |
} | |
var Flags = Aggregator.Flags = { | |
ADD_CELL: 1, | |
MOD_CELL: 2 | |
}; | |
var proto = Aggregator.prototype; | |
// Parameters | |
proto.stream = function(v) { | |
if (v == null) return this._stream; | |
this._stream = !!v; | |
this._aggr = []; | |
return this; | |
}; | |
// key accessor to use for streaming removes | |
proto.key = function(key) { | |
if (key == null) return this._key; | |
this._key = util.$(key); | |
return this; | |
}; | |
// Input: array of objects of the form | |
// {name: string, get: function} | |
proto.groupby = function(dims) { | |
this._dims = util.array(dims).map(function(d, i) { | |
d = util.isString(d) ? {name: d, get: util.$(d)} | |
: util.isFunction(d) ? {name: util.name(d) || d.name || ('_' + i), get: d} | |
: (d.name && util.isFunction(d.get)) ? d : null; | |
if (d == null) throw 'Invalid groupby argument: ' + d; | |
return d; | |
}); | |
return this.clear(); | |
}; | |
// Input: array of objects of the form | |
// {name: string, ops: [string, ...]} | |
proto.summarize = function(fields) { | |
fields = summarize_args(fields); | |
this._count = true; | |
var aggr = (this._aggr = []), | |
m, f, i, j, op, as, get; | |
for (i=0; i<fields.length; ++i) { | |
for (j=0, m=[], f=fields[i]; j<f.ops.length; ++j) { | |
op = f.ops[j]; | |
if (op !== 'count') this._count = false; | |
as = (f.as && f.as[j]) || (op + (f.name==='*' ? '' : '_'+f.name)); | |
m.push(Measures[op](as)); | |
} | |
get = f.get && util.$(f.get) || | |
(f.name === '*' ? util.identity : util.$(f.name)); | |
aggr.push({ | |
name: f.name, | |
measures: Measures.create( | |
m, | |
this._stream, // streaming remove flag | |
get, // input tuple getter | |
this._assign) // output tuple setter | |
}); | |
} | |
return this.clear(); | |
}; | |
// Convenience method to summarize by count | |
proto.count = function() { | |
return this.summarize({'*':'count'}); | |
}; | |
// Override to perform custom tuple value assignment | |
proto._assign = function(object, name, value) { | |
object[name] = value; | |
}; | |
function summarize_args(fields) { | |
if (util.isArray(fields)) { return fields; } | |
if (fields == null) { return []; } | |
var a = [], name, ops; | |
for (name in fields) { | |
ops = util.array(fields[name]); | |
a.push({name: name, ops: ops}); | |
} | |
return a; | |
} | |
// Cell Management | |
proto.clear = function() { | |
return (this._cells = {}, this); | |
}; | |
proto._cellkey = function(x) { | |
var d = this._dims, | |
n = d.length, i, | |
k = String(d[0].get(x)); | |
for (i=1; i<n; ++i) { | |
k += '|' + d[i].get(x); | |
} | |
return k; | |
}; | |
proto._cell = function(x) { | |
var key = this._dims.length ? this._cellkey(x) : ''; | |
return this._cells[key] || (this._cells[key] = this._newcell(x, key)); | |
}; | |
proto._newcell = function(x, key) { | |
var cell = { | |
num: 0, | |
tuple: this._newtuple(x, key), | |
flag: Flags.ADD_CELL, | |
aggs: {} | |
}; | |
var aggr = this._aggr, i; | |
for (i=0; i<aggr.length; ++i) { | |
cell.aggs[aggr[i].name] = new aggr[i].measures(cell, cell.tuple); | |
} | |
if (cell.collect) { | |
cell.data = new Collector(this._key); | |
} | |
return cell; | |
}; | |
proto._newtuple = function(x) { | |
var dims = this._dims, | |
t = {}, i, n; | |
for (i=0, n=dims.length; i<n; ++i) { | |
t[dims[i].name] = dims[i].get(x); | |
} | |
return this._ingest(t); | |
}; | |
// Override to perform custom tuple ingestion | |
proto._ingest = util.identity; | |
// Process Tuples | |
proto._add = function(x) { | |
var cell = this._cell(x), | |
aggr = this._aggr, i; | |
cell.num += 1; | |
if (!this._count) { // skip if count-only | |
if (cell.collect) cell.data.add(x); | |
for (i=0; i<aggr.length; ++i) { | |
cell.aggs[aggr[i].name].add(x); | |
} | |
} | |
cell.flag |= Flags.MOD_CELL; | |
if (this._on_add) this._on_add(x, cell); | |
}; | |
proto._rem = function(x) { | |
var cell = this._cell(x), | |
aggr = this._aggr, i; | |
cell.num -= 1; | |
if (!this._count) { // skip if count-only | |
if (cell.collect) cell.data.rem(x); | |
for (i=0; i<aggr.length; ++i) { | |
cell.aggs[aggr[i].name].rem(x); | |
} | |
} | |
cell.flag |= Flags.MOD_CELL; | |
if (this._on_rem) this._on_rem(x, cell); | |
}; | |
proto._mod = function(curr, prev) { | |
var cell0 = this._cell(prev), | |
cell1 = this._cell(curr), | |
aggr = this._aggr, i; | |
if (cell0 !== cell1) { | |
cell0.num -= 1; | |
cell1.num += 1; | |
if (cell0.collect) cell0.data.rem(prev); | |
if (cell1.collect) cell1.data.add(curr); | |
} else if (cell0.collect && !util.isObject(curr)) { | |
cell0.data.rem(prev); | |
cell0.data.add(curr); | |
} | |
for (i=0; i<aggr.length; ++i) { | |
cell0.aggs[aggr[i].name].rem(prev); | |
cell1.aggs[aggr[i].name].add(curr); | |
} | |
cell0.flag |= Flags.MOD_CELL; | |
cell1.flag |= Flags.MOD_CELL; | |
if (this._on_mod) this._on_mod(curr, prev, cell0, cell1); | |
}; | |
proto.result = function() { | |
var result = [], | |
aggr = this._aggr, | |
cell, i, k; | |
for (k in this._cells) { | |
cell = this._cells[k]; | |
if (cell.num > 0) { | |
// consolidate collector values | |
if (cell.collect) { | |
cell.data.values(); | |
} | |
// update tuple properties | |
for (i=0; i<aggr.length; ++i) { | |
cell.aggs[aggr[i].name].set(); | |
} | |
// add output tuple | |
result.push(cell.tuple); | |
} else { | |
delete this._cells[k]; | |
} | |
cell.flag = 0; | |
} | |
this._rems = false; | |
return result; | |
}; | |
proto.changes = function(output) { | |
var changes = output || {add:[], rem:[], mod:[]}, | |
aggr = this._aggr, | |
cell, flag, i, k; | |
for (k in this._cells) { | |
cell = this._cells[k]; | |
flag = cell.flag; | |
// consolidate collector values | |
if (cell.collect) { | |
cell.data.values(); | |
} | |
// update tuple properties | |
for (i=0; i<aggr.length; ++i) { | |
cell.aggs[aggr[i].name].set(); | |
} | |
// organize output tuples | |
if (cell.num <= 0) { | |
changes.rem.push(cell.tuple); // if (flag === Flags.MOD_CELL) { ?? | |
delete this._cells[k]; | |
if (this._on_drop) this._on_drop(cell); | |
} else { | |
if (this._on_keep) this._on_keep(cell); | |
if (flag & Flags.ADD_CELL) { | |
changes.add.push(cell.tuple); | |
} else if (flag & Flags.MOD_CELL) { | |
changes.mod.push(cell.tuple); | |
} | |
} | |
cell.flag = 0; | |
} | |
this._rems = false; | |
return changes; | |
}; | |
proto.execute = function(input) { | |
return this.clear().insert(input).result(); | |
}; | |
proto.insert = function(input) { | |
this._consolidate(); | |
for (var i=0; i<input.length; ++i) { | |
this._add(input[i]); | |
} | |
return this; | |
}; | |
proto.remove = function(input) { | |
if (!this._stream) { | |
throw 'Aggregator not configured for streaming removes.' + | |
' Call stream(true) prior to calling summarize.'; | |
} | |
for (var i=0; i<input.length; ++i) { | |
this._rem(input[i]); | |
} | |
this._rems = true; | |
return this; | |
}; | |
// consolidate removals | |
proto._consolidate = function() { | |
if (!this._rems) return; | |
for (var k in this._cells) { | |
if (this._cells[k].collect) { | |
this._cells[k].data.values(); | |
} | |
} | |
this._rems = false; | |
}; | |
module.exports = Aggregator; | |
},{"../util":28,"./collector":7,"./measures":9}],7:[function(require,module,exports){ | |
var util = require('../util'); | |
var stats = require('../stats'); | |
var REM = '__dl_rem__'; | |
function Collector(key) { | |
this._add = []; | |
this._rem = []; | |
this._key = key || null; | |
this._last = null; | |
} | |
var proto = Collector.prototype; | |
proto.add = function(v) { | |
this._add.push(v); | |
}; | |
proto.rem = function(v) { | |
this._rem.push(v); | |
}; | |
proto.values = function() { | |
this._get = null; | |
if (this._rem.length === 0) return this._add; | |
var a = this._add, | |
r = this._rem, | |
k = this._key, | |
x = Array(a.length - r.length), | |
i, j, n, m; | |
if (!util.isObject(r[0])) { | |
// processing raw values | |
m = stats.count.map(r); | |
for (i=0, j=0, n=a.length; i<n; ++i) { | |
if (m[a[i]] > 0) { | |
m[a[i]] -= 1; | |
} else { | |
x[j++] = a[i]; | |
} | |
} | |
} else if (k) { | |
// has unique key field, so use that | |
m = util.toMap(r, k); | |
for (i=0, j=0, n=a.length; i<n; ++i) { | |
if (!m.hasOwnProperty(k(a[i]))) { x[j++] = a[i]; } | |
} | |
} else { | |
// no unique key, mark tuples directly | |
for (i=0, n=r.length; i<n; ++i) { | |
r[i][REM] = 1; | |
} | |
for (i=0, j=0, n=a.length; i<n; ++i) { | |
if (!a[i][REM]) { x[j++] = a[i]; } | |
} | |
for (i=0, n=r.length; i<n; ++i) { | |
delete r[i][REM]; | |
} | |
} | |
this._rem = []; | |
return (this._add = x); | |
}; | |
// memoizing statistics methods | |
proto.extent = function(get) { | |
if (this._get !== get || !this._ext) { | |
var v = this.values(), | |
i = stats.extent.index(v, get); | |
this._ext = [v[i[0]], v[i[1]]]; | |
this._get = get; | |
} | |
return this._ext; | |
}; | |
proto.argmin = function(get) { | |
return this.extent(get)[0]; | |
}; | |
proto.argmax = function(get) { | |
return this.extent(get)[1]; | |
}; | |
proto.min = function(get) { | |
var m = this.extent(get)[0]; | |
return m ? get(m) : +Infinity; | |
}; | |
proto.max = function(get) { | |
var m = this.extent(get)[1]; | |
return m ? get(m) : -Infinity; | |
}; | |
proto.quartile = function(get) { | |
if (this._get !== get || !this._q) { | |
this._q = stats.quartile(this.values(), get); | |
this._get = get; | |
} | |
return this._q; | |
}; | |
proto.q1 = function(get) { | |
return this.quartile(get)[0]; | |
}; | |
proto.q2 = function(get) { | |
return this.quartile(get)[1]; | |
}; | |
proto.q3 = function(get) { | |
return this.quartile(get)[2]; | |
}; | |
module.exports = Collector; | |
},{"../stats":25,"../util":28}],8:[function(require,module,exports){ | |
var util = require('../util'); | |
var Aggregator = require('./aggregator'); | |
module.exports = function() { | |
// flatten arguments into a single array | |
var args = [].reduce.call(arguments, function(a, x) { | |
return a.concat(util.array(x)); | |
}, []); | |
// create and return an aggregator | |
return new Aggregator() | |
.groupby(args) | |
.summarize({'*':'values'}); | |
}; | |
},{"../util":28,"./aggregator":6}],9:[function(require,module,exports){ | |
var util = require('../util'); | |
var types = { | |
'values': measure({ | |
name: 'values', | |
init: 'cell.collect = true;', | |
set: 'cell.data.values()', idx: -1 | |
}), | |
'count': measure({ | |
name: 'count', | |
set: 'cell.num' | |
}), | |
'missing': measure({ | |
name: 'missing', | |
set: 'this.missing' | |
}), | |
'valid': measure({ | |
name: 'valid', | |
set: 'this.valid' | |
}), | |
'sum': measure({ | |
name: 'sum', | |
init: 'this.sum = 0;', | |
add: 'this.sum += v;', | |
rem: 'this.sum -= v;', | |
set: 'this.sum' | |
}), | |
'mean': measure({ | |
name: 'mean', | |
init: 'this.mean = 0;', | |
add: 'var d = v - this.mean; this.mean += d / this.valid;', | |
rem: 'var d = v - this.mean; this.mean -= this.valid ? d / this.valid : this.mean;', | |
set: 'this.mean' | |
}), | |
'average': measure({ | |
name: 'average', | |
set: 'this.mean', | |
req: ['mean'], idx: 1 | |
}), | |
'variance': measure({ | |
name: 'variance', | |
init: 'this.dev = 0;', | |
add: 'this.dev += d * (v - this.mean);', | |
rem: 'this.dev -= d * (v - this.mean);', | |
set: 'this.valid > 1 ? this.dev / (this.valid-1) : 0', | |
req: ['mean'], idx: 1 | |
}), | |
'variancep': measure({ | |
name: 'variancep', | |
set: 'this.valid > 1 ? this.dev / this.valid : 0', | |
req: ['variance'], idx: 2 | |
}), | |
'stdev': measure({ | |
name: 'stdev', | |
set: 'this.valid > 1 ? Math.sqrt(this.dev / (this.valid-1)) : 0', | |
req: ['variance'], idx: 2 | |
}), | |
'stdevp': measure({ | |
name: 'stdevp', | |
set: 'this.valid > 1 ? Math.sqrt(this.dev / this.valid) : 0', | |
req: ['variance'], idx: 2 | |
}), | |
'median': measure({ | |
name: 'median', | |
set: 'cell.data.q2(this.get)', | |
req: ['values'], idx: 3 | |
}), | |
'q1': measure({ | |
name: 'q1', | |
set: 'cell.data.q1(this.get)', | |
req: ['values'], idx: 3 | |
}), | |
'q3': measure({ | |
name: 'q3', | |
set: 'cell.data.q3(this.get)', | |
req: ['values'], idx: 3 | |
}), | |
'distinct': measure({ | |
name: 'distinct', | |
set: 'this.distinct(cell.data.values(), this.get)', | |
req: ['values'], idx: 3 | |
}), | |
'argmin': measure({ | |
name: 'argmin', | |
add: 'if (v < this.min) this.argmin = t;', | |
rem: 'if (v <= this.min) this.argmin = null;', | |
set: 'this.argmin = this.argmin || cell.data.argmin(this.get)', | |
req: ['min'], str: ['values'], idx: 3 | |
}), | |
'argmax': measure({ | |
name: 'argmax', | |
add: 'if (v > this.max) this.argmax = t;', | |
rem: 'if (v >= this.max) this.argmax = null;', | |
set: 'this.argmax = this.argmax || cell.data.argmax(this.get)', | |
req: ['max'], str: ['values'], idx: 3 | |
}), | |
'min': measure({ | |
name: 'min', | |
init: 'this.min = +Infinity;', | |
add: 'if (v < this.min) this.min = v;', | |
rem: 'if (v <= this.min) this.min = NaN;', | |
set: 'this.min = (isNaN(this.min) ? cell.data.min(this.get) : this.min)', | |
str: ['values'], idx: 4 | |
}), | |
'max': measure({ | |
name: 'max', | |
init: 'this.max = -Infinity;', | |
add: 'if (v > this.max) this.max = v;', | |
rem: 'if (v >= this.max) this.max = NaN;', | |
set: 'this.max = (isNaN(this.max) ? cell.data.max(this.get) : this.max)', | |
str: ['values'], idx: 4 | |
}), | |
'modeskew': measure({ | |
name: 'modeskew', | |
set: 'this.dev===0 ? 0 : (this.mean - cell.data.q2(this.get)) / Math.sqrt(this.dev/(this.valid-1))', | |
req: ['mean', 'stdev', 'median'], idx: 5 | |
}) | |
}; | |
function measure(base) { | |
return function(out) { | |
var m = util.extend({init:'', add:'', rem:'', idx:0}, base); | |
m.out = out || base.name; | |
return m; | |
}; | |
} | |
function resolve(agg, stream) { | |
function collect(m, a) { | |
function helper(r) { if (!m[r]) collect(m, m[r] = types[r]()); } | |
if (a.req) a.req.forEach(helper); | |
if (stream && a.str) a.str.forEach(helper); | |
return m; | |
} | |
var map = agg.reduce( | |
collect, | |
agg.reduce(function(m, a) { return (m[a.name] = a, m); }, {}) | |
); | |
return util.vals(map).sort(function(a, b) { return a.idx - b.idx; }); | |
} | |
function create(agg, stream, accessor, mutator) { | |
var all = resolve(agg, stream), | |
ctr = 'this.cell = cell; this.tuple = t; this.valid = 0; this.missing = 0;', | |
add = 'if (v==null) this.missing++; if (!this.isValid(v)) return; ++this.valid;', | |
rem = 'if (v==null) this.missing--; if (!this.isValid(v)) return; --this.valid;', | |
set = 'var t = this.tuple; var cell = this.cell;'; | |
all.forEach(function(a) { | |
if (a.idx < 0) { | |
ctr = a.init + ctr; | |
add = a.add + add; | |
rem = a.rem + rem; | |
} else { | |
ctr += a.init; | |
add += a.add; | |
rem += a.rem; | |
} | |
}); | |
agg.slice() | |
.sort(function(a, b) { return a.idx - b.idx; }) | |
.forEach(function(a) { | |
set += 'this.assign(t,\''+a.out+'\','+a.set+');'; | |
}); | |
set += 'return t;'; | |
/* jshint evil: true */ | |
ctr = Function('cell', 't', ctr); | |
ctr.prototype.assign = mutator; | |
ctr.prototype.add = Function('t', 'var v = this.get(t);' + add); | |
ctr.prototype.rem = Function('t', 'var v = this.get(t);' + rem); | |
ctr.prototype.set = Function(set); | |
ctr.prototype.get = accessor; | |
ctr.prototype.distinct = require('../stats').count.distinct; | |
ctr.prototype.isValid = util.isValid; | |
ctr.fields = agg.map(util.$('out')); | |
return ctr; | |
} | |
types.create = create; | |
module.exports = types; | |
},{"../stats":25,"../util":28}],10:[function(require,module,exports){ | |
var util = require('../util'), | |
time = require('../time'), | |
EPSILON = 1e-15; | |
function bins(opt) { | |
if (!opt) { throw Error("Missing binning options."); } | |
// determine range | |
var maxb = opt.maxbins || 15, | |
base = opt.base || 10, | |
logb = Math.log(base), | |
div = opt.div || [5, 2], | |
min = opt.min, | |
max = opt.max, | |
span = max - min, | |
step, level, minstep, precision, v, i, eps; | |
if (opt.step) { | |
// if step size is explicitly given, use that | |
step = opt.step; | |
} else if (opt.steps) { | |
// if provided, limit choice to acceptable step sizes | |
step = opt.steps[Math.min( | |
opt.steps.length - 1, | |
bisect(opt.steps, span/maxb, 0, opt.steps.length) | |
)]; | |
} else { | |
// else use span to determine step size | |
level = Math.ceil(Math.log(maxb) / logb); | |
minstep = opt.minstep || 0; | |
step = Math.max( | |
minstep, | |
Math.pow(base, Math.round(Math.log(span) / logb) - level) | |
); | |
// increase step size if too many bins | |
do { step *= base; } while (Math.ceil(span/step) > maxb); | |
// decrease step size if allowed | |
for (i=0; i<div.length; ++i) { | |
v = step / div[i]; | |
if (v >= minstep && span / v <= maxb) step = v; | |
} | |
} | |
// update precision, min and max | |
v = Math.log(step); | |
precision = v >= 0 ? 0 : ~~(-v / logb) + 1; | |
eps = Math.pow(base, -precision - 1); | |
min = Math.min(min, Math.floor(min / step + eps) * step); | |
max = Math.ceil(max / step) * step; | |
return { | |
start: min, | |
stop: max, | |
step: step, | |
unit: {precision: precision}, | |
value: value, | |
index: index | |
}; | |
} | |
function bisect(a, x, lo, hi) { | |
while (lo < hi) { | |
var mid = lo + hi >>> 1; | |
if (util.cmp(a[mid], x) < 0) { lo = mid + 1; } | |
else { hi = mid; } | |
} | |
return lo; | |
} | |
function value(v) { | |
return this.step * Math.floor(v / this.step + EPSILON); | |
} | |
function index(v) { | |
return Math.floor((v - this.start) / this.step + EPSILON); | |
} | |
function date_value(v) { | |
return this.unit.date(value.call(this, v)); | |
} | |
function date_index(v) { | |
return index.call(this, this.unit.unit(v)); | |
} | |
bins.date = function(opt) { | |
if (!opt) { throw Error("Missing date binning options."); } | |
// find time step, then bin | |
var units = opt.utc ? time.utc : time, | |
dmin = opt.min, | |
dmax = opt.max, | |
maxb = opt.maxbins || 20, | |
minb = opt.minbins || 4, | |
span = (+dmax) - (+dmin), | |
unit = opt.unit ? units[opt.unit] : units.find(span, minb, maxb), | |
spec = bins({ | |
min: unit.min != null ? unit.min : unit.unit(dmin), | |
max: unit.max != null ? unit.max : unit.unit(dmax), | |
maxbins: maxb, | |
minstep: unit.minstep, | |
steps: unit.step | |
}); | |
spec.unit = unit; | |
spec.index = date_index; | |
if (!opt.raw) spec.value = date_value; | |
return spec; | |
}; | |
module.exports = bins; | |
},{"../time":27,"../util":28}],11:[function(require,module,exports){ | |
var bins = require('./bins'), | |
gen = require('../generate'), | |
type = require('../import/type'), | |
util = require('../util'), | |
stats = require('../stats'); | |
var qtype = { | |
'integer': 1, | |
'number': 1, | |
'date': 1 | |
}; | |
function $bin(values, f, opt) { | |
opt = options(values, f, opt); | |
var b = spec(opt); | |
return !b ? (opt.accessor || util.identity) : | |
util.$func('bin', b.unit.unit ? | |
function(x) { return b.value(b.unit.unit(x)); } : | |
function(x) { return b.value(x); } | |
)(opt.accessor); | |
} | |
function histogram(values, f, opt) { | |
opt = options(values, f, opt); | |
var b = spec(opt); | |
return b ? | |
numerical(values, opt.accessor, b) : | |
categorical(values, opt.accessor, opt && opt.sort); | |
} | |
function spec(opt) { | |
var t = opt.type, b = null; | |
if (t == null || qtype[t]) { | |
if (t === 'integer' && opt.minstep == null) opt.minstep = 1; | |
b = (t === 'date') ? bins.date(opt) : bins(opt); | |
} | |
return b; | |
} | |
function options() { | |
var a = arguments, | |
i = 0, | |
values = util.isArray(a[i]) ? a[i++] : null, | |
f = util.isFunction(a[i]) || util.isString(a[i]) ? util.$(a[i++]) : null, | |
opt = util.extend({}, a[i]); | |
if (values) { | |
opt.type = opt.type || type(values, f); | |
if (qtype[opt.type]) { | |
var ext = stats.extent(values, f); | |
opt = util.extend({min: ext[0], max: ext[1]}, opt); | |
} | |
} | |
if (f) { opt.accessor = f; } | |
return opt; | |
} | |
function numerical(values, f, b) { | |
var h = gen.range(b.start, b.stop + b.step/2, b.step) | |
.map(function(v) { return {value: b.value(v), count: 0}; }); | |
for (var i=0, v, j; i<values.length; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) { | |
j = b.index(v); | |
if (j < 0 || j >= h.length || !isFinite(j)) continue; | |
h[j].count += 1; | |
} | |
} | |
h.bins = b; | |
return h; | |
} | |
function categorical(values, f, sort) { | |
var u = stats.unique(values, f), | |
c = stats.count.map(values, f); | |
return u.map(function(k) { return {value: k, count: c[k]}; }) | |
.sort(util.comparator(sort ? '-count' : '+value')); | |
} | |
module.exports = { | |
$bin: $bin, | |
histogram: histogram | |
}; | |
},{"../generate":13,"../import/type":22,"../stats":25,"../util":28,"./bins":10}],12:[function(require,module,exports){ | |
var d3_time = require('d3-time'), | |
d3_timeF = require('d3-time-format'), | |
d3_numberF = require('d3-format'), | |
numberF = d3_numberF, // defaults to EN-US | |
timeF = d3_timeF; // defaults to EN-US | |
function numberLocale(l) { | |
var f = d3_numberF.localeFormat(l); | |
if (f == null) throw Error('Unrecognized locale: ' + l); | |
numberF = f; | |
} | |
function timeLocale(l) { | |
var f = d3_timeF.localeFormat(l); | |
if (f == null) throw Error('Unrecognized locale: ' + l); | |
timeF = f; | |
} | |
module.exports = { | |
// Update number formatter to use provided locale configuration. | |
// For more see https://github.com/d3/d3-format | |
numberLocale: numberLocale, | |
number: function(f) { return numberF.format(f); }, | |
numberPrefix: function(f, v) { return numberF.formatPrefix(f, v); }, | |
// Update time formatter to use provided locale configuration. | |
// For more see https://github.com/d3/d3-time-format | |
timeLocale: timeLocale, | |
time: function(f) { return timeF.format(f); }, | |
utc: function(f) { return timeF.utcFormat(f); }, | |
// Set number and time locale simultaneously. | |
locale: function(l) { numberLocale(l); timeLocale(l); }, | |
// automatic formatting functions | |
auto: { | |
number: numberAutoFormat, | |
time: function() { return timeAutoFormat(); }, | |
utc: function() { return utcAutoFormat(); } | |
} | |
}; | |
var e10 = Math.sqrt(50), | |
e5 = Math.sqrt(10), | |
e2 = Math.sqrt(2); | |
function intervals(domain, count) { | |
if (!domain.length) domain = [0]; | |
if (count == null) count = 10; | |
var start = domain[0], | |
stop = domain[domain.length - 1]; | |
if (stop < start) { error = stop; stop = start; start = error; } | |
var span = (stop - start) || (count = 1, start || stop || 1), | |
step = Math.pow(10, Math.floor(Math.log(span / count) / Math.LN10)), | |
error = span / count / step; | |
// Filter ticks to get closer to the desired count. | |
if (error >= e10) step *= 10; | |
else if (error >= e5) step *= 5; | |
else if (error >= e2) step *= 2; | |
// Round start and stop values to step interval. | |
return [ | |
Math.ceil(start / step) * step, | |
Math.floor(stop / step) * step + step / 2, // inclusive | |
step | |
]; | |
} | |
function numberAutoFormat(domain, count, f) { | |
var range = intervals(domain, count); | |
if (f == null) { | |
f = ',.' + d3_numberF.precisionFixed(range[2]) + 'f'; | |
} else { | |
switch (f = d3_numberF.formatSpecifier(f), f.type) { | |
case 's': { | |
var value = Math.max(Math.abs(range[0]), Math.abs(range[1])); | |
if (f.precision == null) f.precision = d3_numberF.precisionPrefix(range[2], value); | |
return numberF.formatPrefix(f, value); | |
} | |
case '': | |
case 'e': | |
case 'g': | |
case 'p': | |
case 'r': { | |
if (f.precision == null) f.precision = d3_numberF.precisionRound(range[2], Math.max(Math.abs(range[0]), Math.abs(range[1]))) - (f.type === 'e'); | |
break; | |
} | |
case 'f': | |
case '%': { | |
if (f.precision == null) f.precision = d3_numberF.precisionFixed(range[2]) - (f.type === '%') * 2; | |
break; | |
} | |
} | |
} | |
return numberF.format(f); | |
} | |
function timeAutoFormat() { | |
var f = timeF.format, | |
formatMillisecond = f('.%L'), | |
formatSecond = f(':%S'), | |
formatMinute = f('%I:%M'), | |
formatHour = f('%I %p'), | |
formatDay = f('%a %d'), | |
formatWeek = f('%b %d'), | |
formatMonth = f('%B'), | |
formatYear = f('%Y'); | |
return function(date) { | |
var d = +date; | |
return (d3_time.second(date) < d ? formatMillisecond | |
: d3_time.minute(date) < d ? formatSecond | |
: d3_time.hour(date) < d ? formatMinute | |
: d3_time.day(date) < d ? formatHour | |
: d3_time.month(date) < d ? | |
(d3_time.week(date) < d ? formatDay : formatWeek) | |
: d3_time.year(date) < d ? formatMonth | |
: formatYear)(date); | |
}; | |
} | |
function utcAutoFormat() { | |
var f = timeF.utcFormat, | |
formatMillisecond = f('.%L'), | |
formatSecond = f(':%S'), | |
formatMinute = f('%I:%M'), | |
formatHour = f('%I %p'), | |
formatDay = f('%a %d'), | |
formatWeek = f('%b %d'), | |
formatMonth = f('%B'), | |
formatYear = f('%Y'); | |
return function(date) { | |
var d = +date; | |
return (d3_time.utcSecond(date) < d ? formatMillisecond | |
: d3_time.utcMinute(date) < d ? formatSecond | |
: d3_time.utcHour(date) < d ? formatMinute | |
: d3_time.utcDay(date) < d ? formatHour | |
: d3_time.utcMonth(date) < d ? | |
(d3_time.utcWeek(date) < d ? formatDay : formatWeek) | |
: d3_time.utcYear(date) < d ? formatMonth | |
: formatYear)(date); | |
}; | |
} | |
},{"d3-format":3,"d3-time":5,"d3-time-format":4}],13:[function(require,module,exports){ | |
var gen = module.exports = {}; | |
gen.repeat = function(val, n) { | |
var a = Array(n), i; | |
for (i=0; i<n; ++i) a[i] = val; | |
return a; | |
}; | |
gen.zeros = function(n) { | |
return gen.repeat(0, n); | |
}; | |
gen.range = function(start, stop, step) { | |
if (arguments.length < 3) { | |
step = 1; | |
if (arguments.length < 2) { | |
stop = start; | |
start = 0; | |
} | |
} | |
if ((stop - start) / step == Infinity) throw new Error('Infinite range'); | |
var range = [], i = -1, j; | |
if (step < 0) while ((j = start + step * ++i) > stop) range.push(j); | |
else while ((j = start + step * ++i) < stop) range.push(j); | |
return range; | |
}; | |
gen.random = {}; | |
gen.random.uniform = function(min, max) { | |
if (max === undefined) { | |
max = min === undefined ? 1 : min; | |
min = 0; | |
} | |
var d = max - min; | |
var f = function() { | |
return min + d * Math.random(); | |
}; | |
f.samples = function(n) { return gen.zeros(n).map(f); }; | |
return f; | |
}; | |
gen.random.integer = function(a, b) { | |
if (b === undefined) { | |
b = a; | |
a = 0; | |
} | |
var d = b - a; | |
var f = function() { | |
return a + Math.floor(d * Math.random()); | |
}; | |
f.samples = function(n) { return gen.zeros(n).map(f); }; | |
return f; | |
}; | |
gen.random.normal = function(mean, stdev) { | |
mean = mean || 0; | |
stdev = stdev || 1; | |
var next; | |
var f = function() { | |
var x = 0, y = 0, rds, c; | |
if (next !== undefined) { | |
x = next; | |
next = undefined; | |
return x; | |
} | |
do { | |
x = Math.random()*2-1; | |
y = Math.random()*2-1; | |
rds = x*x + y*y; | |
} while (rds === 0 || rds > 1); | |
c = Math.sqrt(-2*Math.log(rds)/rds); // Box-Muller transform | |
next = mean + y*c*stdev; | |
return mean + x*c*stdev; | |
}; | |
f.samples = function(n) { return gen.zeros(n).map(f); }; | |
return f; | |
}; | |
},{}],14:[function(require,module,exports){ | |
var util = require('../../util'); | |
var d3_dsv = require('d3-dsv'); | |
function dsv(data, format) { | |
if (data) { | |
var h = format.header; | |
data = (h ? h.join(format.delimiter) + '\n' : '') + data; | |
} | |
return d3_dsv.dsv(format.delimiter).parse(data); | |
} | |
dsv.delimiter = function(delim) { | |
var fmt = {delimiter: delim}; | |
return function(data, format) { | |
return dsv(data, format ? util.extend(format, fmt) : fmt); | |
}; | |
}; | |
module.exports = dsv; | |
},{"../../util":28,"d3-dsv":2}],15:[function(require,module,exports){ | |
var dsv = require('./dsv'); | |
module.exports = { | |
json: require('./json'), | |
topojson: require('./topojson'), | |
treejson: require('./treejson'), | |
dsv: dsv, | |
csv: dsv.delimiter(','), | |
tsv: dsv.delimiter('\t') | |
}; | |
},{"./dsv":14,"./json":16,"./topojson":17,"./treejson":18}],16:[function(require,module,exports){ | |
var util = require('../../util'); | |
module.exports = function(data, format) { | |
var d = util.isObject(data) && !util.isBuffer(data) ? | |
data : JSON.parse(data); | |
if (format && format.property) { | |
d = util.accessor(format.property)(d); | |
} | |
return d; | |
}; | |
},{"../../util":28}],17:[function(require,module,exports){ | |
(function (global){ | |
var json = require('./json'); | |
var reader = function(data, format) { | |
var topojson = reader.topojson; | |
if (topojson == null) { throw Error('TopoJSON library not loaded.'); } | |
var t = json(data, format), obj; | |
if (format && format.feature) { | |
if ((obj = t.objects[format.feature])) { | |
return topojson.feature(t, obj).features; | |
} else { | |
throw Error('Invalid TopoJSON object: ' + format.feature); | |
} | |
} else if (format && format.mesh) { | |
if ((obj = t.objects[format.mesh])) { | |
return [topojson.mesh(t, t.objects[format.mesh])]; | |
} else { | |
throw Error('Invalid TopoJSON object: ' + format.mesh); | |
} | |
} else { | |
throw Error('Missing TopoJSON feature or mesh parameter.'); | |
} | |
}; | |
reader.topojson = (typeof window !== "undefined" ? window['topojson'] : typeof global !== "undefined" ? global['topojson'] : null); | |
module.exports = reader; | |
}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"./json":16}],18:[function(require,module,exports){ | |
var json = require('./json'); | |
module.exports = function(data, format) { | |
data = json(data, format); | |
return toTable(data, (format && format.children)); | |
}; | |
function toTable(root, childrenField) { | |
childrenField = childrenField || 'children'; | |
var table = []; | |
function visit(node) { | |
table.push(node); | |
var children = node[childrenField]; | |
if (children) { | |
for (var i=0; i<children.length; ++i) { | |
visit(children[i], node); | |
} | |
} | |
} | |
visit(root, null); | |
return (table.root = root, table); | |
} | |
},{"./json":16}],19:[function(require,module,exports){ | |
// Matches absolute URLs with optional protocol | |
// https://... file://... //... | |
var protocol_re = /^([A-Za-z]+:)?\/\//; | |
// Special treatment in node.js for the file: protocol | |
var fileProtocol = 'file://'; | |
// Validate and cleanup URL to ensure that it is allowed to be accessed | |
// Returns cleaned up URL, or false if access is not allowed | |
function sanitizeUrl(opt) { | |
var url = opt.url; | |
if (!url && opt.file) { return fileProtocol + opt.file; } | |
// In case this is a relative url (has no host), prepend opt.baseURL | |
if (opt.baseURL && !protocol_re.test(url)) { | |
if (!startsWith(url, '/') && opt.baseURL[opt.baseURL.length-1] !== '/') { | |
url = '/' + url; // Ensure that there is a slash between the baseURL (e.g. hostname) and url | |
} | |
url = opt.baseURL + url; | |
} | |
// relative protocol, starts with '//' | |
if (!load.useXHR && startsWith(url, '//')) { | |
url = (opt.defaultProtocol || 'http') + ':' + url; | |
} | |
// If opt.domainWhiteList is set, only allows url, whose hostname | |
// * Is the same as the origin (window.location.hostname) | |
// * Equals one of the values in the whitelist | |
// * Is a proper subdomain of one of the values in the whitelist | |
if (opt.domainWhiteList) { | |
var domain, origin; | |
if (load.useXHR) { | |
var a = document.createElement('a'); | |
a.href = url; | |
// From http://stackoverflow.com/questions/736513/how-do-i-parse-a-url-into-hostname-and-path-in-javascript | |
// IE doesn't populate all link properties when setting .href with a relative URL, | |
// however .href will return an absolute URL which then can be used on itself | |
// to populate these additional fields. | |
if (a.host === '') { | |
a.href = a.href; | |
} | |
domain = a.hostname.toLowerCase(); | |
origin = window.location.hostname; | |
} else { | |
// relative protocol is broken: https://github.com/defunctzombie/node-url/issues/5 | |
var parts = require('url').parse(url); | |
domain = parts.hostname; | |
origin = null; | |
} | |
if (origin !== domain) { | |
var whiteListed = opt.domainWhiteList.some(function(d) { | |
var idx = domain.length - d.length; | |
return d === domain || | |
(idx > 1 && domain[idx-1] === '.' && domain.lastIndexOf(d) === idx); | |
}); | |
if (!whiteListed) { | |
throw 'URL is not whitelisted: ' + url; | |
} | |
} | |
} | |
return url; | |
} | |
function load(opt, callback) { | |
var error = callback || function(e) { throw e; }, url; | |
try { | |
url = load.sanitizeUrl(opt); // enable override | |
} catch (err) { | |
error(err); | |
return; | |
} | |
if (!url) { | |
error('Invalid URL: ' + opt.url); | |
} else if (load.useXHR) { | |
// on client, use xhr | |
return xhr(url, callback); | |
} else if (startsWith(url, fileProtocol)) { | |
// on server, if url starts with 'file://', strip it and load from file | |
return file(url.slice(fileProtocol.length), callback); | |
} else if (url.indexOf('://') < 0) { // TODO better protocol check? | |
// on server, if no protocol assume file | |
return file(url, callback); | |
} else { | |
// for regular URLs on server | |
return http(url, callback); | |
} | |
} | |
function xhrHasResponse(request) { | |
var type = request.responseType; | |
return type && type !== 'text' ? | |
request.response : // null on error | |
request.responseText; // '' on error | |
} | |
function xhr(url, callback) { | |
var async = !!callback; | |
var request = new XMLHttpRequest(); | |
// If IE does not support CORS, use XDomainRequest (copied from d3.xhr) | |
if (this.XDomainRequest && | |
!('withCredentials' in request) && | |
/^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest(); | |
function respond() { | |
var status = request.status; | |
if (!status && xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) { | |
callback(null, request.responseText); | |
} else { | |
callback(request, null); | |
} | |
} | |
if (async) { | |
if ('onload' in request) { | |
request.onload = request.onerror = respond; | |
} else { | |
request.onreadystatechange = function() { | |
if (request.readyState > 3) respond(); | |
}; | |
} | |
} | |
request.open('GET', url, async); | |
request.send(); | |
if (!async && xhrHasResponse(request)) { | |
return request.responseText; | |
} | |
} | |
function file(filename, callback) { | |
var fs = require('fs'); | |
if (!callback) { | |
return fs.readFileSync(filename, 'utf8'); | |
} | |
fs.readFile(filename, callback); | |
} | |
function http(url, callback) { | |
if (!callback) { | |
return require('sync-request')('GET', url).getBody(); | |
} | |
var options = {url: url, encoding: null, gzip: true}; | |
require('request')(options, function(error, response, body) { | |
if (!error && response.statusCode === 200) { | |
callback(null, body); | |
} else { | |
error = error || | |
'Load failed with response code ' + response.statusCode + '.'; | |
callback(error, null); | |
} | |
}); | |
} | |
function startsWith(string, searchString) { | |
return string == null ? false : string.lastIndexOf(searchString, 0) === 0; | |
} | |
load.sanitizeUrl = sanitizeUrl; | |
load.useXHR = (typeof XMLHttpRequest !== 'undefined'); | |
module.exports = load; | |
},{"fs":1,"request":1,"sync-request":1,"url":1}],20:[function(require,module,exports){ | |
var util = require('../util'); | |
var type = require('./type'); | |
var formats = require('./formats'); | |
function read(data, format) { | |
var type = (format && format.type) || 'json'; | |
data = formats[type](data, format); | |
if (format && format.parse) parse(data, format.parse); | |
return data; | |
} | |
function parse(data, types) { | |
var cols, parsers, d, i, j, clen, len = data.length; | |
types = (types==='auto') ? type.inferAll(data) : util.duplicate(types); | |
cols = util.keys(types); | |
parsers = cols.map(function(c) { return type.parsers[types[c]]; }); | |
for (i=0, clen=cols.length; i<len; ++i) { | |
d = data[i]; | |
for (j=0; j<clen; ++j) { | |
d[cols[j]] = parsers[j](d[cols[j]]); | |
} | |
} | |
type.annotation(data, types); | |
} | |
read.formats = formats; | |
module.exports = read; | |
},{"../util":28,"./formats":15,"./type":22}],21:[function(require,module,exports){ | |
var util = require('../util'); | |
var load = require('./load'); | |
var read = require('./read'); | |
module.exports = util | |
.keys(read.formats) | |
.reduce(function(out, type) { | |
out[type] = function(opt, format, callback) { | |
// process arguments | |
if (util.isString(opt)) { opt = {url: opt}; } | |
if (arguments.length === 2 && util.isFunction(format)) { | |
callback = format; | |
format = undefined; | |
} | |
// set up read format | |
format = util.extend({parse: 'auto'}, format); | |
format.type = type; | |
// load data | |
var data = load(opt, callback ? function(error, data) { | |
if (error) { callback(error, null); return; } | |
try { | |
// data loaded, now parse it (async) | |
data = read(data, format); | |
callback(null, data); | |
} catch (e) { | |
callback(e, null); | |
} | |
} : undefined); | |
// data loaded, now parse it (sync) | |
if (!callback) return read(data, format); | |
}; | |
return out; | |
}, {}); | |
},{"../util":28,"./load":19,"./read":20}],22:[function(require,module,exports){ | |
var util = require('../util'); | |
var TYPES = '__types__'; | |
var PARSERS = { | |
boolean: util.boolean, | |
integer: util.number, | |
number: util.number, | |
date: util.date, | |
string: function(x) { return x==='' ? null : x; } | |
}; | |
var TESTS = { | |
boolean: function(x) { return x==='true' || x==='false' || util.isBoolean(x); }, | |
integer: function(x) { return TESTS.number(x) && (x=+x) === ~~x; }, | |
number: function(x) { return !isNaN(+x) && !util.isDate(x); }, | |
date: function(x) { return !isNaN(Date.parse(x)); } | |
}; | |
function annotation(data, types) { | |
if (!types) return data && data[TYPES] || null; | |
data[TYPES] = types; | |
} | |
function type(values, f) { | |
f = util.$(f); | |
var v, i, n; | |
// if data array has type annotations, use them | |
if (values[TYPES]) { | |
v = f(values[TYPES]); | |
if (util.isString(v)) return v; | |
} | |
for (i=0, n=values.length; !util.isValid(v) && i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
} | |
return util.isDate(v) ? 'date' : | |
util.isNumber(v) ? 'number' : | |
util.isBoolean(v) ? 'boolean' : | |
util.isString(v) ? 'string' : null; | |
} | |
function typeAll(data, fields) { | |
if (!data.length) return; | |
fields = fields || util.keys(data[0]); | |
return fields.reduce(function(types, f) { | |
return (types[f] = type(data, f), types); | |
}, {}); | |
} | |
function infer(values, f) { | |
f = util.$(f); | |
var i, j, v; | |
// types to test for, in precedence order | |
var types = ['boolean', 'integer', 'number', 'date']; | |
for (i=0; i<values.length; ++i) { | |
// get next value to test | |
v = f ? f(values[i]) : values[i]; | |
// test value against remaining types | |
for (j=0; j<types.length; ++j) { | |
if (util.isValid(v) && !TESTS[types[j]](v)) { | |
types.splice(j, 1); | |
j -= 1; | |
} | |
} | |
// if no types left, return 'string' | |
if (types.length === 0) return 'string'; | |
} | |
return types[0]; | |
} | |
function inferAll(data, fields) { | |
fields = fields || util.keys(data[0]); | |
return fields.reduce(function(types, f) { | |
types[f] = infer(data, f); | |
return types; | |
}, {}); | |
} | |
type.annotation = annotation; | |
type.all = typeAll; | |
type.infer = infer; | |
type.inferAll = inferAll; | |
type.parsers = PARSERS; | |
module.exports = type; | |
},{"../util":28}],23:[function(require,module,exports){ | |
var util = require('./util'); | |
var dl = { | |
version: '1.4.6', | |
load: require('./import/load'), | |
read: require('./import/read'), | |
type: require('./import/type'), | |
Aggregator: require('./aggregate/aggregator'), | |
groupby: require('./aggregate/groupby'), | |
bins: require('./bins/bins'), | |
$bin: require('./bins/histogram').$bin, | |
histogram: require('./bins/histogram').histogram, | |
format: require('./format'), | |
print: require('./print'), | |
template: require('./template'), | |
time: require('./time') | |
}; | |
util.extend(dl, util); | |
util.extend(dl, require('./generate')); | |
util.extend(dl, require('./stats')); | |
util.extend(dl, require('./import/readers')); | |
module.exports = dl; | |
},{"./aggregate/aggregator":6,"./aggregate/groupby":8,"./bins/bins":10,"./bins/histogram":11,"./format":12,"./generate":13,"./import/load":19,"./import/read":20,"./import/readers":21,"./import/type":22,"./print":24,"./stats":25,"./template":26,"./time":27,"./util":28}],24:[function(require,module,exports){ | |
var util = require('./util'); | |
var type = require('./import/type'); | |
var stats = require('./stats'); | |
var template = require('./template'); | |
var FMT = { | |
'date': '|time:"%m/%d/%Y %H:%M:%S"', | |
'number': '|number:".4f"', | |
'integer': '|number:"d"' | |
}; | |
var POS = { | |
'number': 'left', | |
'integer': 'left' | |
}; | |
module.exports.table = function(data, opt) { | |
opt = util.extend({separator:' ', minwidth: 8, maxwidth: 15}, opt); | |
var fields = opt.fields || util.keys(data[0]), | |
types = type.all(data); | |
if (opt.start || opt.limit) { | |
var a = opt.start || 0, | |
b = opt.limit ? a + opt.limit : data.length; | |
data = data.slice(a, b); | |
} | |
// determine char width of fields | |
var lens = fields.map(function(name) { | |
var format = FMT[types[name]] || '', | |
t = template('{{' + name + format + '}}'), | |
l = stats.max(data, function(x) { return t(x).length; }); | |
l = Math.max(Math.min(name.length, opt.minwidth), l); | |
return opt.maxwidth > 0 ? Math.min(l, opt.maxwidth) : l; | |
}); | |
// print header row | |
var head = fields.map(function(name, i) { | |
return util.truncate(util.pad(name, lens[i], 'center'), lens[i]); | |
}).join(opt.separator); | |
// build template function for each row | |
var tmpl = template(fields.map(function(name, i) { | |
return '{{' + | |
name + | |
(FMT[types[name]] || '') + | |
('|pad:' + lens[i] + ',' + (POS[types[name]] || 'right')) + | |
('|truncate:' + lens[i]) + | |
'}}'; | |
}).join(opt.separator)); | |
// print table | |
return head + "\n" + data.map(tmpl).join('\n'); | |
}; | |
module.exports.summary = function(s) { | |
s = s ? s.__summary__ ? s : stats.summary(s) : this; | |
var str = [], i, n; | |
for (i=0, n=s.length; i<n; ++i) { | |
str.push('-- ' + s[i].field + ' --'); | |
if (s[i].type === 'string' || s[i].distinct < 10) { | |
str.push(printCategoricalProfile(s[i])); | |
} else { | |
str.push(printQuantitativeProfile(s[i])); | |
} | |
str.push(''); | |
} | |
return str.join('\n'); | |
}; | |
function printQuantitativeProfile(p) { | |
return [ | |
'valid: ' + p.valid, | |
'missing: ' + p.missing, | |
'distinct: ' + p.distinct, | |
'min: ' + p.min, | |
'max: ' + p.max, | |
'median: ' + p.median, | |
'mean: ' + p.mean, | |
'stdev: ' + p.stdev, | |
'modeskew: ' + p.modeskew | |
].join('\n'); | |
} | |
function printCategoricalProfile(p) { | |
var list = [ | |
'valid: ' + p.valid, | |
'missing: ' + p.missing, | |
'distinct: ' + p.distinct, | |
'top values: ' | |
]; | |
var u = p.unique; | |
var top = util.keys(u) | |
.sort(function(a,b) { return u[b] - u[a]; }) | |
.slice(0, 6) | |
.map(function(v) { return ' \'' + v + '\' (' + u[v] + ')'; }); | |
return list.concat(top).join('\n'); | |
} | |
},{"./import/type":22,"./stats":25,"./template":26,"./util":28}],25:[function(require,module,exports){ | |
var util = require('./util'); | |
var type = require('./import/type'); | |
var gen = require('./generate'); | |
var stats = {}; | |
// Collect unique values. | |
// Output: an array of unique values, in first-observed order | |
stats.unique = function(values, f, results) { | |
f = util.$(f); | |
results = results || []; | |
var u = {}, v, i, n; | |
for (i=0, n=values.length; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (v in u) continue; | |
u[v] = 1; | |
results.push(v); | |
} | |
return results; | |
}; | |
// Return the length of the input array. | |
stats.count = function(values) { | |
return values && values.length || 0; | |
}; | |
// Count the number of non-null, non-undefined, non-NaN values. | |
stats.count.valid = function(values, f) { | |
f = util.$(f); | |
var v, i, n, valid = 0; | |
for (i=0, n=values.length; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) valid += 1; | |
} | |
return valid; | |
}; | |
// Count the number of null or undefined values. | |
stats.count.missing = function(values, f) { | |
f = util.$(f); | |
var v, i, n, count = 0; | |
for (i=0, n=values.length; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (v == null) count += 1; | |
} | |
return count; | |
}; | |
// Count the number of distinct values. | |
// Null, undefined and NaN are each considered distinct values. | |
stats.count.distinct = function(values, f) { | |
f = util.$(f); | |
var u = {}, v, i, n, count = 0; | |
for (i=0, n=values.length; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (v in u) continue; | |
u[v] = 1; | |
count += 1; | |
} | |
return count; | |
}; | |
// Construct a map from distinct values to occurrence counts. | |
stats.count.map = function(values, f) { | |
f = util.$(f); | |
var map = {}, v, i, n; | |
for (i=0, n=values.length; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
map[v] = (v in map) ? map[v] + 1 : 1; | |
} | |
return map; | |
}; | |
// Compute the median of an array of numbers. | |
stats.median = function(values, f) { | |
if (f) values = values.map(util.$(f)); | |
values = values.filter(util.isValid).sort(util.cmp); | |
return stats.quantile(values, 0.5); | |
}; | |
// Computes the quartile boundaries of an array of numbers. | |
stats.quartile = function(values, f) { | |
if (f) values = values.map(util.$(f)); | |
values = values.filter(util.isValid).sort(util.cmp); | |
var q = stats.quantile; | |
return [q(values, 0.25), q(values, 0.50), q(values, 0.75)]; | |
}; | |
// Compute the quantile of a sorted array of numbers. | |
// Adapted from the D3.js implementation. | |
stats.quantile = function(values, f, p) { | |
if (p === undefined) { p = f; f = util.identity; } | |
f = util.$(f); | |
var H = (values.length - 1) * p + 1, | |
h = Math.floor(H), | |
v = +f(values[h - 1]), | |
e = H - h; | |
return e ? v + e * (f(values[h]) - v) : v; | |
}; | |
// Compute the sum of an array of numbers. | |
stats.sum = function(values, f) { | |
f = util.$(f); | |
for (var sum=0, i=0, n=values.length, v; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) sum += v; | |
} | |
return sum; | |
}; | |
// Compute the mean (average) of an array of numbers. | |
stats.mean = function(values, f) { | |
f = util.$(f); | |
var mean = 0, delta, i, n, c, v; | |
for (i=0, c=0, n=values.length; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) { | |
delta = v - mean; | |
mean = mean + delta / (++c); | |
} | |
} | |
return mean; | |
}; | |
// Compute the sample variance of an array of numbers. | |
stats.variance = function(values, f) { | |
f = util.$(f); | |
if (!util.isArray(values) || values.length < 2) return 0; | |
var mean = 0, M2 = 0, delta, i, c, v; | |
for (i=0, c=0; i<values.length; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) { | |
delta = v - mean; | |
mean = mean + delta / (++c); | |
M2 = M2 + delta * (v - mean); | |
} | |
} | |
M2 = M2 / (c - 1); | |
return M2; | |
}; | |
// Compute the sample standard deviation of an array of numbers. | |
stats.stdev = function(values, f) { | |
return Math.sqrt(stats.variance(values, f)); | |
}; | |
// Compute the Pearson mode skewness ((median-mean)/stdev) of an array of numbers. | |
stats.modeskew = function(values, f) { | |
var avg = stats.mean(values, f), | |
med = stats.median(values, f), | |
std = stats.stdev(values, f); | |
return std === 0 ? 0 : (avg - med) / std; | |
}; | |
// Find the minimum value in an array. | |
stats.min = function(values, f) { | |
return stats.extent(values, f)[0]; | |
}; | |
// Find the maximum value in an array. | |
stats.max = function(values, f) { | |
return stats.extent(values, f)[1]; | |
}; | |
// Find the minimum and maximum of an array of values. | |
stats.extent = function(values, f) { | |
f = util.$(f); | |
var a, b, v, i, n = values.length; | |
for (i=0; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) { a = b = v; break; } | |
} | |
for (; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) { | |
if (v < a) a = v; | |
if (v > b) b = v; | |
} | |
} | |
return [a, b]; | |
}; | |
// Find the integer indices of the minimum and maximum values. | |
stats.extent.index = function(values, f) { | |
f = util.$(f); | |
var x = -1, y = -1, a, b, v, i, n = values.length; | |
for (i=0; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) { a = b = v; x = y = i; break; } | |
} | |
for (; i<n; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
if (util.isValid(v)) { | |
if (v < a) { a = v; x = i; } | |
if (v > b) { b = v; y = i; } | |
} | |
} | |
return [x, y]; | |
}; | |
// Compute the dot product of two arrays of numbers. | |
stats.dot = function(values, a, b) { | |
var sum = 0, i, v; | |
if (!b) { | |
if (values.length !== a.length) { | |
throw Error('Array lengths must match.'); | |
} | |
for (i=0; i<values.length; ++i) { | |
v = values[i] * a[i]; | |
if (v === v) sum += v; | |
} | |
} else { | |
a = util.$(a); | |
b = util.$(b); | |
for (i=0; i<values.length; ++i) { | |
v = a(values[i]) * b(values[i]); | |
if (v === v) sum += v; | |
} | |
} | |
return sum; | |
}; | |
// Compute ascending rank scores for an array of values. | |
// Ties are assigned their collective mean rank. | |
stats.rank = function(values, f) { | |
f = util.$(f) || util.identity; | |
var a = values.map(function(v, i) { | |
return {idx: i, val: f(v)}; | |
}) | |
.sort(util.comparator('val')); | |
var n = values.length, | |
r = Array(n), | |
tie = -1, p = {}, i, v, mu; | |
for (i=0; i<n; ++i) { | |
v = a[i].val; | |
if (tie < 0 && p === v) { | |
tie = i - 1; | |
} else if (tie > -1 && p !== v) { | |
mu = 1 + (i-1 + tie) / 2; | |
for (; tie<i; ++tie) r[a[tie].idx] = mu; | |
tie = -1; | |
} | |
r[a[i].idx] = i + 1; | |
p = v; | |
} | |
if (tie > -1) { | |
mu = 1 + (n-1 + tie) / 2; | |
for (; tie<n; ++tie) r[a[tie].idx] = mu; | |
} | |
return r; | |
}; | |
// Compute the sample Pearson product-moment correlation of two arrays of numbers. | |
stats.cor = function(values, a, b) { | |
var fn = b; | |
b = fn ? values.map(util.$(b)) : a; | |
a = fn ? values.map(util.$(a)) : values; | |
var dot = stats.dot(a, b), | |
mua = stats.mean(a), | |
mub = stats.mean(b), | |
sda = stats.stdev(a), | |
sdb = stats.stdev(b), | |
n = values.length; | |
return (dot - n*mua*mub) / ((n-1) * sda * sdb); | |
}; | |
// Compute the Spearman rank correlation of two arrays of values. | |
stats.cor.rank = function(values, a, b) { | |
var ra = b ? stats.rank(values, util.$(a)) : stats.rank(values), | |
rb = b ? stats.rank(values, util.$(b)) : stats.rank(a), | |
n = values.length, i, s, d; | |
for (i=0, s=0; i<n; ++i) { | |
d = ra[i] - rb[i]; | |
s += d * d; | |
} | |
return 1 - 6*s / (n * (n*n-1)); | |
}; | |
// Compute the distance correlation of two arrays of numbers. | |
// http://en.wikipedia.org/wiki/Distance_correlation | |
stats.cor.dist = function(values, a, b) { | |
var X = b ? values.map(util.$(a)) : values, | |
Y = b ? values.map(util.$(b)) : a; | |
var A = stats.dist.mat(X), | |
B = stats.dist.mat(Y), | |
n = A.length, | |
i, aa, bb, ab; | |
for (i=0, aa=0, bb=0, ab=0; i<n; ++i) { | |
aa += A[i]*A[i]; | |
bb += B[i]*B[i]; | |
ab += A[i]*B[i]; | |
} | |
return Math.sqrt(ab / Math.sqrt(aa*bb)); | |
}; | |
// Compute the vector distance between two arrays of numbers. | |
// Default is Euclidean (exp=2) distance, configurable via exp argument. | |
stats.dist = function(values, a, b, exp) { | |
var f = util.isFunction(b) || util.isString(b), | |
X = values, | |
Y = f ? values : a, | |
e = f ? exp : b, | |
L2 = e === 2 || e == null, | |
n = values.length, s = 0, d, i; | |
if (f) { | |
a = util.$(a); | |
b = util.$(b); | |
} | |
for (i=0; i<n; ++i) { | |
d = f ? (a(X[i])-b(Y[i])) : (X[i]-Y[i]); | |
s += L2 ? d*d : Math.pow(Math.abs(d), e); | |
} | |
return L2 ? Math.sqrt(s) : Math.pow(s, 1/e); | |
}; | |
// Construct a mean-centered distance matrix for an array of numbers. | |
stats.dist.mat = function(X) { | |
var n = X.length, | |
m = n*n, | |
A = Array(m), | |
R = gen.zeros(n), | |
M = 0, v, i, j; | |
for (i=0; i<n; ++i) { | |
A[i*n+i] = 0; | |
for (j=i+1; j<n; ++j) { | |
A[i*n+j] = (v = Math.abs(X[i] - X[j])); | |
A[j*n+i] = v; | |
R[i] += v; | |
R[j] += v; | |
} | |
} | |
for (i=0; i<n; ++i) { | |
M += R[i]; | |
R[i] /= n; | |
} | |
M /= m; | |
for (i=0; i<n; ++i) { | |
for (j=i; j<n; ++j) { | |
A[i*n+j] += M - R[i] - R[j]; | |
A[j*n+i] = A[i*n+j]; | |
} | |
} | |
return A; | |
}; | |
// Compute the Shannon entropy (log base 2) of an array of counts. | |
stats.entropy = function(counts, f) { | |
f = util.$(f); | |
var i, p, s = 0, H = 0, n = counts.length; | |
for (i=0; i<n; ++i) { | |
s += (f ? f(counts[i]) : counts[i]); | |
} | |
if (s === 0) return 0; | |
for (i=0; i<n; ++i) { | |
p = (f ? f(counts[i]) : counts[i]) / s; | |
if (p) H += p * Math.log(p); | |
} | |
return -H / Math.LN2; | |
}; | |
// Compute the mutual information between two discrete variables. | |
// Returns an array of the form [MI, MI_distance] | |
// MI_distance is defined as 1 - I(a,b) / H(a,b). | |
// http://en.wikipedia.org/wiki/Mutual_information | |
stats.mutual = function(values, a, b, counts) { | |
var x = counts ? values.map(util.$(a)) : values, | |
y = counts ? values.map(util.$(b)) : a, | |
z = counts ? values.map(util.$(counts)) : b; | |
var px = {}, | |
py = {}, | |
n = z.length, | |
s = 0, I = 0, H = 0, p, t, i; | |
for (i=0; i<n; ++i) { | |
px[x[i]] = 0; | |
py[y[i]] = 0; | |
} | |
for (i=0; i<n; ++i) { | |
px[x[i]] += z[i]; | |
py[y[i]] += z[i]; | |
s += z[i]; | |
} | |
t = 1 / (s * Math.LN2); | |
for (i=0; i<n; ++i) { | |
if (z[i] === 0) continue; | |
p = (s * z[i]) / (px[x[i]] * py[y[i]]); | |
I += z[i] * t * Math.log(p); | |
H += z[i] * t * Math.log(z[i]/s); | |
} | |
return [I, 1 + I/H]; | |
}; | |
// Compute the mutual information between two discrete variables. | |
stats.mutual.info = function(values, a, b, counts) { | |
return stats.mutual(values, a, b, counts)[0]; | |
}; | |
// Compute the mutual information distance between two discrete variables. | |
// MI_distance is defined as 1 - I(a,b) / H(a,b). | |
stats.mutual.dist = function(values, a, b, counts) { | |
return stats.mutual(values, a, b, counts)[1]; | |
}; | |
// Compute a profile of summary statistics for a variable. | |
stats.profile = function(values, f) { | |
var mean = 0, | |
valid = 0, | |
missing = 0, | |
distinct = 0, | |
min = null, | |
max = null, | |
M2 = 0, | |
vals = [], | |
u = {}, delta, sd, i, v, x; | |
// compute summary stats | |
for (i=0; i<values.length; ++i) { | |
v = f ? f(values[i]) : values[i]; | |
// update unique values | |
u[v] = (v in u) ? u[v] + 1 : (distinct += 1, 1); | |
if (v == null) { | |
++missing; | |
} else if (util.isValid(v)) { | |
// update stats | |
x = (typeof v === 'string') ? v.length : v; | |
if (min===null || x < min) min = x; | |
if (max===null || x > max) max = x; | |
delta = x - mean; | |
mean = mean + delta / (++valid); | |
M2 = M2 + delta * (x - mean); | |
vals.push(x); | |
} | |
} | |
M2 = M2 / (valid - 1); | |
sd = Math.sqrt(M2); | |
// sort values for median and iqr | |
vals.sort(util.cmp); | |
return { | |
type: type(values, f), | |
unique: u, | |
count: values.length, | |
valid: valid, | |
missing: missing, | |
distinct: distinct, | |
min: min, | |
max: max, | |
mean: mean, | |
stdev: sd, | |
median: (v = stats.quantile(vals, 0.5)), | |
q1: stats.quantile(vals, 0.25), | |
q3: stats.quantile(vals, 0.75), | |
modeskew: sd === 0 ? 0 : (mean - v) / sd | |
}; | |
}; | |
// Compute profiles for all variables in a data set. | |
stats.summary = function(data, fields) { | |
fields = fields || util.keys(data[0]); | |
var s = fields.map(function(f) { | |
var p = stats.profile(data, util.$(f)); | |
return (p.field = f, p); | |
}); | |
return (s.__summary__ = true, s); | |
}; | |
module.exports = stats; | |
},{"./generate":13,"./import/type":22,"./util":28}],26:[function(require,module,exports){ | |
var util = require('./util'), | |
format = require('./format'); | |
var context = { | |
formats: [], | |
format_map: {}, | |
truncate: util.truncate, | |
pad: util.pad | |
}; | |
function template(text) { | |
var src = source(text, 'd'); | |
src = 'var __t; return ' + src + ';'; | |
/* jshint evil: true */ | |
return (new Function('d', src)).bind(context); | |
} | |
template.source = source; | |
template.context = context; | |
module.exports = template; | |
// Clear cache of format objects. | |
// This can *break* prior template functions, so invoke with care! | |
template.clearFormatCache = function() { | |
context.formats = []; | |
context.format_map = {}; | |
}; | |
// Generate property access code for use within template source. | |
// object: the name of the object (variable) containing template data | |
// property: the property access string, verbatim from template tag | |
template.property = function(object, property) { | |
var src = util.field(property).map(util.str).join(']['); | |
return object + '[' + src + ']'; | |
}; | |
// Generate source code for a template function. | |
// text: the template text | |
// variable: the name of the data object variable ('obj' by default) | |
// properties: optional hash for collecting all accessed properties | |
function source(text, variable, properties) { | |
variable = variable || 'obj'; | |
var index = 0; | |
var src = '\''; | |
var regex = template_re; | |
// Compile the template source, escaping string literals appropriately. | |
text.replace(regex, function(match, interpolate, offset) { | |
src += text | |
.slice(index, offset) | |
.replace(template_escaper, template_escapeChar); | |
index = offset + match.length; | |
if (interpolate) { | |
src += '\'\n+((__t=(' + | |
template_var(interpolate, variable, properties) + | |
'))==null?\'\':__t)+\n\''; | |
} | |
// Adobe VMs need the match returned to produce the correct offest. | |
return match; | |
}); | |
return src + '\''; | |
} | |
function template_var(text, variable, properties) { | |
var filters = text.match(filter_re); | |
var prop = filters.shift().trim(); | |
var stringCast = true; | |
function strcall(fn) { | |
fn = fn || ''; | |
if (stringCast) { | |
stringCast = false; | |
src = 'String(' + src + ')' + fn; | |
} else { | |
src += fn; | |
} | |
return src; | |
} | |
function date() { | |
return '(typeof ' + src + '==="number"?new Date('+src+'):'+src+')'; | |
} | |
function number_format(fmt, key) { | |
a = template_format(args[0], key, fmt); | |
stringCast = false; | |
src = 'this.formats['+a+']('+src+')'; | |
} | |
function time_format(fmt, key) { | |
a = template_format(args[0], key, fmt); | |
stringCast = false; | |
src = 'this.formats['+a+']('+date()+')'; | |
} | |
if (properties) properties[prop] = 1; | |
var src = template.property(variable, prop); | |
for (var i=0; i<filters.length; ++i) { | |
var f = filters[i], args = null, pidx, a, b; | |
if ((pidx=f.indexOf(':')) > 0) { | |
f = f.slice(0, pidx); | |
args = filters[i].slice(pidx+1) | |
.match(args_re) | |
.map(function(s) { return s.trim(); }); | |
} | |
f = f.trim(); | |
switch (f) { | |
case 'length': | |
strcall('.length'); | |
break; | |
case 'lower': | |
strcall('.toLowerCase()'); | |
break; | |
case 'upper': | |
strcall('.toUpperCase()'); | |
break; | |
case 'lower-locale': | |
strcall('.toLocaleLowerCase()'); | |
break; | |
case 'upper-locale': | |
strcall('.toLocaleUpperCase()'); | |
break; | |
case 'trim': | |
strcall('.trim()'); | |
break; | |
case 'left': | |
a = util.number(args[0]); | |
strcall('.slice(0,' + a + ')'); | |
break; | |
case 'right': | |
a = util.number(args[0]); | |
strcall('.slice(-' + a +')'); | |
break; | |
case 'mid': | |
a = util.number(args[0]); | |
b = a + util.number(args[1]); | |
strcall('.slice(+'+a+','+b+')'); | |
break; | |
case 'slice': | |
a = util.number(args[0]); | |
strcall('.slice('+ a + | |
(args.length > 1 ? ',' + util.number(args[1]) : '') + | |
')'); | |
break; | |
case 'truncate': | |
a = util.number(args[0]); | |
b = args[1]; | |
b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b; | |
src = 'this.truncate(' + strcall() + ',' + a + ',\'' + b + '\')'; | |
break; | |
case 'pad': | |
a = util.number(args[0]); | |
b = args[1]; | |
b = (b!=='left' && b!=='middle' && b!=='center') ? 'right' : b; | |
src = 'this.pad(' + strcall() + ',' + a + ',\'' + b + '\')'; | |
break; | |
case 'number': | |
number_format(format.number, 'number'); | |
break; | |
case 'time': | |
time_format(format.time, 'time'); | |
break; | |
case 'time-utc': | |
time_format(format.utc, 'time-utc'); | |
break; | |
default: | |
throw Error('Unrecognized template filter: ' + f); | |
} | |
} | |
return src; | |
} | |
var template_re = /\{\{(.+?)\}\}|$/g, | |
filter_re = /(?:"[^"]*"|\'[^\']*\'|[^\|"]+|[^\|\']+)+/g, | |
args_re = /(?:"[^"]*"|\'[^\']*\'|[^,"]+|[^,\']+)+/g; | |
// Certain characters need to be escaped so that they can be put into a | |
// string literal. | |
var template_escapes = { | |
'\'': '\'', | |
'\\': '\\', | |
'\r': 'r', | |
'\n': 'n', | |
'\u2028': 'u2028', | |
'\u2029': 'u2029' | |
}; | |
var template_escaper = /\\|'|\r|\n|\u2028|\u2029/g; | |
function template_escapeChar(match) { | |
return '\\' + template_escapes[match]; | |
} | |
function template_format(pattern, key, fmt) { | |
if ((pattern[0] === '\'' && pattern[pattern.length-1] === '\'') || | |
(pattern[0] === '"' && pattern[pattern.length-1] === '"')) { | |
pattern = pattern.slice(1, -1); | |
} else { | |
throw Error('Format pattern must be quoted: ' + pattern); | |
} | |
key = key + ':' + pattern; | |
if (!context.format_map[key]) { | |
var f = fmt(pattern); | |
var i = context.formats.length; | |
context.formats.push(f); | |
context.format_map[key] = i; | |
} | |
return context.format_map[key]; | |
} | |
},{"./format":12,"./util":28}],27:[function(require,module,exports){ | |
var d3_time = require('d3-time'); | |
var tempDate = new Date(), | |
baseDate = new Date(0, 0, 1).setFullYear(0), // Jan 1, 0 AD | |
utcBaseDate = new Date(Date.UTC(0, 0, 1)).setUTCFullYear(0); | |
function date(d) { | |
return (tempDate.setTime(+d), tempDate); | |
} | |
// create a time unit entry | |
function entry(type, date, unit, step, min, max) { | |
var e = { | |
type: type, | |
date: date, | |
unit: unit | |
}; | |
if (step) { | |
e.step = step; | |
} else { | |
e.minstep = 1; | |
} | |
if (min != null) e.min = min; | |
if (max != null) e.max = max; | |
return e; | |
} | |
function create(type, unit, base, step, min, max) { | |
return entry(type, | |
function(d) { return unit.offset(base, d); }, | |
function(d) { return unit.count(base, d); }, | |
step, min, max); | |
} | |
var locale = [ | |
create('second', d3_time.second, baseDate), | |
create('minute', d3_time.minute, baseDate), | |
create('hour', d3_time.hour, baseDate), | |
create('day', d3_time.day, baseDate, [1, 7]), | |
create('month', d3_time.month, baseDate, [1, 3, 6]), | |
create('year', d3_time.year, baseDate), | |
// periodic units | |
entry('seconds', | |
function(d) { return new Date(1970, 0, 1, 0, 0, d); }, | |
function(d) { return date(d).getSeconds(); }, | |
null, 0, 59 | |
), | |
entry('minutes', | |
function(d) { return new Date(1970, 0, 1, 0, d); }, | |
function(d) { return date(d).getMinutes(); }, | |
null, 0, 59 | |
), | |
entry('hours', | |
function(d) { return new Date(1970, 0, 1, d); }, | |
function(d) { return date(d).getHours(); }, | |
null, 0, 23 | |
), | |
entry('weekdays', | |
function(d) { return new Date(1970, 0, 4+d); }, | |
function(d) { return date(d).getDay(); }, | |
[1], 0, 6 | |
), | |
entry('dates', | |
function(d) { return new Date(1970, 0, d); }, | |
function(d) { return date(d).getDate(); }, | |
[1], 1, 31 | |
), | |
entry('months', | |
function(d) { return new Date(1970, d % 12, 1); }, | |
function(d) { return date(d).getMonth(); }, | |
[1], 0, 11 | |
) | |
]; | |
var utc = [ | |
create('second', d3_time.utcSecond, utcBaseDate), | |
create('minute', d3_time.utcMinute, utcBaseDate), | |
create('hour', d3_time.utcHour, utcBaseDate), | |
create('day', d3_time.utcDay, utcBaseDate, [1, 7]), | |
create('month', d3_time.utcMonth, utcBaseDate, [1, 3, 6]), | |
create('year', d3_time.utcYear, utcBaseDate), | |
// periodic units | |
entry('seconds', | |
function(d) { return new Date(Date.UTC(1970, 0, 1, 0, 0, d)); }, | |
function(d) { return date(d).getUTCSeconds(); }, | |
null, 0, 59 | |
), | |
entry('minutes', | |
function(d) { return new Date(Date.UTC(1970, 0, 1, 0, d)); }, | |
function(d) { return date(d).getUTCMinutes(); }, | |
null, 0, 59 | |
), | |
entry('hours', | |
function(d) { return new Date(Date.UTC(1970, 0, 1, d)); }, | |
function(d) { return date(d).getUTCHours(); }, | |
null, 0, 23 | |
), | |
entry('weekdays', | |
function(d) { return new Date(Date.UTC(1970, 0, 4+d)); }, | |
function(d) { return date(d).getUTCDay(); }, | |
[1], 0, 6 | |
), | |
entry('dates', | |
function(d) { return new Date(Date.UTC(1970, 0, d)); }, | |
function(d) { return date(d).getUTCDate(); }, | |
[1], 1, 31 | |
), | |
entry('months', | |
function(d) { return new Date(Date.UTC(1970, d % 12, 1)); }, | |
function(d) { return date(d).getUTCMonth(); }, | |
[1], 0, 11 | |
) | |
]; | |
var STEPS = [ | |
[31536e6, 5], // 1-year | |
[7776e6, 4], // 3-month | |
[2592e6, 4], // 1-month | |
[12096e5, 3], // 2-week | |
[6048e5, 3], // 1-week | |
[1728e5, 3], // 2-day | |
[864e5, 3], // 1-day | |
[432e5, 2], // 12-hour | |
[216e5, 2], // 6-hour | |
[108e5, 2], // 3-hour | |
[36e5, 2], // 1-hour | |
[18e5, 1], // 30-minute | |
[9e5, 1], // 15-minute | |
[3e5, 1], // 5-minute | |
[6e4, 1], // 1-minute | |
[3e4, 0], // 30-second | |
[15e3, 0], // 15-second | |
[5e3, 0], // 5-second | |
[1e3, 0] // 1-second | |
]; | |
function find(units, span, minb, maxb) { | |
var step = STEPS[0], i, n, bins; | |
for (i=1, n=STEPS.length; i<n; ++i) { | |
step = STEPS[i]; | |
if (span > step[0]) { | |
bins = span / step[0]; | |
if (bins > maxb) { | |
return units[STEPS[i-1][1]]; | |
} | |
if (bins >= minb) { | |
return units[step[1]]; | |
} | |
} | |
} | |
return units[STEPS[n-1][1]]; | |
} | |
function toUnitMap(units) { | |
var map = {}, i, n; | |
for (i=0, n=units.length; i<n; ++i) { | |
map[units[i].type] = units[i]; | |
} | |
map.find = function(span, minb, maxb) { | |
return find(units, span, minb, maxb); | |
}; | |
return map; | |
} | |
module.exports = toUnitMap(locale); | |
module.exports.utc = toUnitMap(utc); | |
},{"d3-time":5}],28:[function(require,module,exports){ | |
var buffer = require('buffer'), | |
time = require('./time'), | |
utc = time.utc; | |
var u = module.exports = {}; | |
// utility functions | |
var FNAME = '__name__'; | |
u.namedfunc = function(name, f) { return (f[FNAME] = name, f); }; | |
u.name = function(f) { return f==null ? null : f[FNAME]; }; | |
u.identity = function(x) { return x; }; | |
u.true = u.namedfunc('true', function() { return true; }); | |
u.false = u.namedfunc('false', function() { return false; }); | |
u.duplicate = function(obj) { | |
return JSON.parse(JSON.stringify(obj)); | |
}; | |
u.equal = function(a, b) { | |
return JSON.stringify(a) === JSON.stringify(b); | |
}; | |
u.extend = function(obj) { | |
for (var x, name, i=1, len=arguments.length; i<len; ++i) { | |
x = arguments[i]; | |
for (name in x) { obj[name] = x[name]; } | |
} | |
return obj; | |
}; | |
u.length = function(x) { | |
return x != null && x.length != null ? x.length : null; | |
}; | |
u.keys = function(x) { | |
var keys = [], k; | |
for (k in x) keys.push(k); | |
return keys; | |
}; | |
u.vals = function(x) { | |
var vals = [], k; | |
for (k in x) vals.push(x[k]); | |
return vals; | |
}; | |
u.toMap = function(list, f) { | |
return (f = u.$(f)) ? | |
list.reduce(function(obj, x) { return (obj[f(x)] = 1, obj); }, {}) : | |
list.reduce(function(obj, x) { return (obj[x] = 1, obj); }, {}); | |
}; | |
u.keystr = function(values) { | |
// use to ensure consistent key generation across modules | |
var n = values.length; | |
if (!n) return ''; | |
for (var s=String(values[0]), i=1; i<n; ++i) { | |
s += '|' + String(values[i]); | |
} | |
return s; | |
}; | |
// type checking functions | |
var toString = Object.prototype.toString; | |
u.isObject = function(obj) { | |
return obj === Object(obj); | |
}; | |
u.isFunction = function(obj) { | |
return toString.call(obj) === '[object Function]'; | |
}; | |
u.isString = function(obj) { | |
return typeof value === 'string' || toString.call(obj) === '[object String]'; | |
}; | |
u.isArray = Array.isArray || function(obj) { | |
return toString.call(obj) === '[object Array]'; | |
}; | |
u.isNumber = function(obj) { | |
return typeof obj === 'number' || toString.call(obj) === '[object Number]'; | |
}; | |
u.isBoolean = function(obj) { | |
return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; | |
}; | |
u.isDate = function(obj) { | |
return toString.call(obj) === '[object Date]'; | |
}; | |
u.isValid = function(obj) { | |
return obj != null && obj === obj; | |
}; | |
u.isBuffer = (buffer.Buffer && buffer.Buffer.isBuffer) || u.false; | |
// type coercion functions | |
u.number = function(s) { | |
return s == null || s === '' ? null : +s; | |
}; | |
u.boolean = function(s) { | |
return s == null || s === '' ? null : s==='false' ? false : !!s; | |
}; | |
u.date = function(s) { | |
return s == null || s === '' ? null : Date.parse(s); | |
}; | |
u.array = function(x) { | |
return x != null ? (u.isArray(x) ? x : [x]) : []; | |
}; | |
u.str = function(x) { | |
return u.isArray(x) ? '[' + x.map(u.str) + ']' | |
: u.isObject(x) ? JSON.stringify(x) | |
: u.isString(x) ? ('\''+util_escape_str(x)+'\'') : x; | |
}; | |
var escape_str_re = /(^|[^\\])'/g; | |
function util_escape_str(x) { | |
return x.replace(escape_str_re, '$1\\\''); | |
} | |
// data access functions | |
var field_re = /\[(.*?)\]|[^.\[]+/g; | |
u.field = function(f) { | |
return String(f).match(field_re).map(function(d) { | |
return d[0] !== '[' ? d : | |
d[1] !== "'" && d[1] !== '"' ? d.slice(1, -1) : | |
d.slice(2, -2).replace(/\\(["'])/g, '$1'); | |
}); | |
}; | |
u.accessor = function(f) { | |
var s; | |
return f==null || u.isFunction(f) ? f : | |
u.namedfunc(f, (s = u.field(f)).length > 1 ? | |
function(x) { return s.reduce(function(x,f) { return x[f]; }, x); } : | |
function(x) { return x[f]; } | |
); | |
}; | |
// short-cut for accessor | |
u.$ = u.accessor; | |
u.mutator = function(f) { | |
var s; | |
return u.isString(f) && (s=u.field(f)).length > 1 ? | |
function(x, v) { | |
for (var i=0; i<s.length-1; ++i) x = x[s[i]]; | |
x[s[i]] = v; | |
} : | |
function(x, v) { x[f] = v; }; | |
}; | |
u.$func = function(name, op) { | |
return function(f) { | |
f = u.$(f) || u.identity; | |
var n = name + (u.name(f) ? '_'+u.name(f) : ''); | |
return u.namedfunc(n, function(d) { return op(f(d)); }); | |
}; | |
}; | |
u.$valid = u.$func('valid', u.isValid); | |
u.$length = u.$func('length', u.length); | |
u.$in = function(f, values) { | |
f = u.$(f); | |
var map = u.isArray(values) ? u.toMap(values) : values; | |
return function(d) { return !!map[f(d)]; }; | |
}; | |
u.$year = u.$func('year', time.year.unit); | |
u.$month = u.$func('month', time.months.unit); | |
u.$date = u.$func('date', time.dates.unit); | |
u.$day = u.$func('day', time.weekdays.unit); | |
u.$hour = u.$func('hour', time.hours.unit); | |
u.$minute = u.$func('minute', time.minutes.unit); | |
u.$second = u.$func('second', time.seconds.unit); | |
u.$utcYear = u.$func('utcYear', utc.year.unit); | |
u.$utcMonth = u.$func('utcMonth', utc.months.unit); | |
u.$utcDate = u.$func('utcDate', utc.dates.unit); | |
u.$utcDay = u.$func('utcDay', utc.weekdays.unit); | |
u.$utcHour = u.$func('utcHour', utc.hours.unit); | |
u.$utcMinute = u.$func('utcMinute', utc.minutes.unit); | |
u.$utcSecond = u.$func('utcSecond', utc.seconds.unit); | |
// comparison / sorting functions | |
u.comparator = function(sort) { | |
var sign = []; | |
if (sort === undefined) sort = []; | |
sort = u.array(sort).map(function(f) { | |
var s = 1; | |
if (f[0] === '-') { s = -1; f = f.slice(1); } | |
else if (f[0] === '+') { s = +1; f = f.slice(1); } | |
sign.push(s); | |
return u.accessor(f); | |
}); | |
return function(a,b) { | |
var i, n, f, x, y; | |
for (i=0, n=sort.length; i<n; ++i) { | |
f = sort[i]; x = f(a); y = f(b); | |
if (x < y) return -1 * sign[i]; | |
if (x > y) return sign[i]; | |
} | |
return 0; | |
}; | |
}; | |
u.cmp = function(a, b) { | |
if (a < b) { | |
return -1; | |
} else if (a > b) { | |
return 1; | |
} else if (a >= b) { | |
return 0; | |
} else if (a === null) { | |
return -1; | |
} else if (b === null) { | |
return 1; | |
} | |
return NaN; | |
}; | |
u.numcmp = function(a, b) { return a - b; }; | |
u.stablesort = function(array, sortBy, keyFn) { | |
var indices = array.reduce(function(idx, v, i) { | |
return (idx[keyFn(v)] = i, idx); | |
}, {}); | |
array.sort(function(a, b) { | |
var sa = sortBy(a), | |
sb = sortBy(b); | |
return sa < sb ? -1 : sa > sb ? 1 | |
: (indices[keyFn(a)] - indices[keyFn(b)]); | |
}); | |
return array; | |
}; | |
// string functions | |
u.pad = function(s, length, pos, padchar) { | |
padchar = padchar || " "; | |
var d = length - s.length; | |
if (d <= 0) return s; | |
switch (pos) { | |
case 'left': | |
return strrep(d, padchar) + s; | |
case 'middle': | |
case 'center': | |
return strrep(Math.floor(d/2), padchar) + | |
s + strrep(Math.ceil(d/2), padchar); | |
default: | |
return s + strrep(d, padchar); | |
} | |
}; | |
function strrep(n, str) { | |
var s = "", i; | |
for (i=0; i<n; ++i) s += str; | |
return s; | |
} | |
u.truncate = function(s, length, pos, word, ellipsis) { | |
var len = s.length; | |
if (len <= length) return s; | |
ellipsis = ellipsis !== undefined ? String(ellipsis) : '\u2026'; | |
var l = Math.max(0, length - ellipsis.length); | |
switch (pos) { | |
case 'left': | |
return ellipsis + (word ? truncateOnWord(s,l,1) : s.slice(len-l)); | |
case 'middle': | |
case 'center': | |
var l1 = Math.ceil(l/2), l2 = Math.floor(l/2); | |
return (word ? truncateOnWord(s,l1) : s.slice(0,l1)) + | |
ellipsis + (word ? truncateOnWord(s,l2,1) : s.slice(len-l2)); | |
default: | |
return (word ? truncateOnWord(s,l) : s.slice(0,l)) + ellipsis; | |
} | |
}; | |
function truncateOnWord(s, len, rev) { | |
var cnt = 0, tok = s.split(truncate_word_re); | |
if (rev) { | |
s = (tok = tok.reverse()) | |
.filter(function(w) { cnt += w.length; return cnt <= len; }) | |
.reverse(); | |
} else { | |
s = tok.filter(function(w) { cnt += w.length; return cnt <= len; }); | |
} | |
return s.length ? s.join('').trim() : tok[0].slice(0, len); | |
} | |
var truncate_word_re = /([\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF])/; | |
},{"./time":27,"buffer":1}]},{},[23])(23) | |
}); | |
//# sourceMappingURL=data:application/json;charset:utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1yZXNvbHZlL2VtcHR5LmpzIiwibm9kZV9tb2R1bGVzL2QzLWRzdi9idWlsZC9kc3YuanMiLCJub2RlX21vZHVsZXMvZDMtZm9ybWF0L2J1aWxkL2Zvcm1hdC5qcyIsIm5vZGVfbW9kdWxlcy9kMy10aW1lLWZvcm1hdC9idWlsZC90aW1lRm9ybWF0LmpzIiwibm9kZV9tb2R1bGVzL2QzLXRpbWUvYnVpbGQvdGltZS5qcyIsInNyYy9hZ2dyZWdhdGUvYWdncmVnYXRvci5qcyIsInNyYy9hZ2dyZWdhdGUvY29sbGVjdG9yLmpzIiwic3JjL2FnZ3JlZ2F0ZS9ncm91cGJ5LmpzIiwic3JjL2FnZ3JlZ2F0ZS9tZWFzdXJlcy5qcyIsInNyYy9iaW5zL2JpbnMuanMiLCJzcmMvYmlucy9oaXN0b2dyYW0uanMiLCJzcmMvZm9ybWF0LmpzIiwic3JjL2dlbmVyYXRlLmpzIiwic3JjL2ltcG9ydC9mb3JtYXRzL2Rzdi5qcyIsInNyYy9pbXBvcnQvZm9ybWF0cy9pbmRleC5qcyIsInNyYy9pbXBvcnQvZm9ybWF0cy9qc29uLmpzIiwic3JjL2ltcG9ydC9mb3JtYXRzL3RvcG9qc29uLmpzIiwic3JjL2ltcG9ydC9mb3JtYXRzL3RyZWVqc29uLmpzIiwic3JjL2ltcG9ydC9sb2FkLmpzIiwic3JjL2ltcG9ydC9yZWFkLmpzIiwic3JjL2ltcG9ydC9yZWFkZXJzLmpzIiwic3JjL2ltcG9ydC90eXBlLmpzIiwic3JjL2luZGV4LmpzIiwic3JjL3ByaW50LmpzIiwic3JjL3N0YXRzLmpzIiwic3JjL3RlbXBsYXRlLmpzIiwic3JjL3RpbWUuanMiLCJzcmMvdXRpbC5qcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBOztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMTRCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNoU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbFRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNiQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3RUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzFCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZlQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLG51bGwsIihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcbiAgZmFjdG9yeSgoZ2xvYmFsLmRzdiA9IHt9KSk7XG59KHRoaXMsIGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxuICB2YXIgZHN2ID0gZnVuY3Rpb24oZGVsaW1pdGVyKSB7XG4gICAgdmFyIHJlRm9ybWF0ID0gbmV3IFJlZ0V4cChcIltcXFwiXCIgKyBkZWxpbWl0ZXIgKyBcIlxcbl1cIiksXG4gICAgICAgIGRlbGltaXRlckNvZGUgPSBkZWxpbWl0ZXIuY2hhckNvZGVBdCgwKTtcblxuICAgIGZ1bmN0aW9uIHBhcnNlKHRleHQsIGYpIHtcbiAgICAgIHZhciBvO1xuICAgICAgcmV0dXJuIHBhcnNlUm93cyh0ZXh0LCBmdW5jdGlvbihyb3csIGkpIHtcbiAgICAgICAgaWYgKG8pIHJldHVybiBvKHJvdywgaSAtIDEpO1xuICAgICAgICB2YXIgYSA9IG5ldyBGdW5jdGlvbihcImRcIiwgXCJyZXR1cm4ge1wiICsgcm93Lm1hcChmdW5jdGlvbihuYW1lLCBpKSB7XG4gICAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG5hbWUpICsgXCI6IGRbXCIgKyBpICsgXCJdXCI7XG4gICAgICAgIH0pLmpvaW4oXCIsXCIpICsgXCJ9XCIpO1xuICAgICAgICBvID0gZiA/IGZ1bmN0aW9uKHJvdywgaSkgeyByZXR1cm4gZihhKHJvdyksIGkpOyB9IDogYTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhcnNlUm93cyh0ZXh0LCBmKSB7XG4gICAgICB2YXIgRU9MID0ge30sIC8vIHNlbnRpbmVsIHZhbHVlIGZvciBlbmQtb2YtbGluZVxuICAgICAgICAgIEVPRiA9IHt9LCAvLyBzZW50aW5lbCB2YWx1ZSBmb3IgZW5kLW9mLWZpbGVcbiAgICAgICAgICByb3dzID0gW10sIC8vIG91dHB1dCByb3dzXG4gICAgICAgICAgTiA9IHRleHQubGVuZ3RoLFxuICAgICAgICAgIEkgPSAwLCAvLyBjdXJyZW50IGNoYXJhY3RlciBpbmRleFxuICAgICAgICAgIG4gPSAwLCAvLyB0aGUgY3VycmVudCBsaW5lIG51bWJlclxuICAgICAgICAgIHQsIC8vIHRoZSBjdXJyZW50IHRva2VuXG4gICAgICAgICAgZW9sOyAvLyBpcyB0aGUgY3VycmVudCB0b2tlbiBmb2xsb3dlZCBieSBFT0w/XG5cbiAgICAgIGZ1bmN0aW9uIHRva2VuKCkge1xuICAgICAgICBpZiAoSSA+PSBOKSByZXR1cm4gRU9GOyAvLyBzcGVjaWFsIGNhc2U6IGVuZCBvZiBmaWxlXG4gICAgICAgIGlmIChlb2wpIHJldHVybiBlb2wgPSBmYWxzZSwgRU9MOyAvLyBzcGVjaWFsIGNhc2U6IGVuZCBvZiBsaW5lXG5cbiAgICAgICAgLy8gc3BlY2lhbCBjYXNlOiBxdW90ZXNcbiAgICAgICAgdmFyIGogPSBJO1xuICAgICAgICBpZiAodGV4dC5jaGFyQ29kZUF0KGopID09PSAzNCkge1xuICAgICAgICAgIHZhciBpID0gajtcbiAgICAgICAgICB3aGlsZSAoaSsrIDwgTikge1xuICAgICAgICAgICAgaWYgKHRleHQuY2hhckNvZGVBdChpKSA9PT0gMzQpIHtcbiAgICAgICAgICAgICAgaWYgKHRleHQuY2hhckNvZGVBdChpICsgMSkgIT09IDM0KSBicmVhaztcbiAgICAgICAgICAgICAgKytpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBJID0gaSArIDI7XG4gICAgICAgICAgdmFyIGMgPSB0ZXh0LmNoYXJDb2RlQXQoaSArIDEpO1xuICAgICAgICAgIGlmIChjID09PSAxMykge1xuICAgICAgICAgICAgZW9sID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICh0ZXh0LmNoYXJDb2RlQXQoaSArIDIpID09PSAxMCkgKytJO1xuICAgICAgICAgIH0gZWxzZSBpZiAoYyA9PT0gMTApIHtcbiAgICAgICAgICAgIGVvbCA9IHRydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiB0ZXh0LnNsaWNlKGogKyAxLCBpKS5yZXBsYWNlKC9cIlwiL2csIFwiXFxcIlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGNvbW1vbiBjYXNlOiBmaW5kIG5leHQgZGVsaW1pdGVyIG9yIG5ld2xpbmVcbiAgICAgICAgd2hpbGUgKEkgPCBOKSB7XG4gICAgICAgICAgdmFyIGMgPSB0ZXh0LmNoYXJDb2RlQXQoSSsrKSwgayA9IDE7XG4gICAgICAgICAgaWYgKGMgPT09IDEwKSBlb2wgPSB0cnVlOyAvLyBcXG5cbiAgICAgICAgICBlbHNlIGlmIChjID09PSAxMykgeyBlb2wgPSB0cnVlOyBpZiAodGV4dC5jaGFyQ29kZUF0KEkpID09PSAxMCkgKytJLCArK2s7IH0gLy8gXFxyfFxcclxcblxuICAgICAgICAgIGVsc2UgaWYgKGMgIT09IGRlbGltaXRlckNvZGUpIGNvbnRpbnVlO1xuICAgICAgICAgIHJldHVybiB0ZXh0LnNsaWNlKGosIEkgLSBrKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHNwZWNpYWwgY2FzZTogbGFzdCB0b2tlbiBiZWZvcmUgRU9GXG4gICAgICAgIHJldHVybiB0ZXh0LnNsaWNlKGopO1xuICAgICAgfVxuXG4gICAgICB3aGlsZSAoKHQgPSB0b2tlbigpKSAhPT0gRU9GKSB7XG4gICAgICAgIHZhciBhID0gW107XG4gICAgICAgIHdoaWxlICh0ICE9PSBFT0wgJiYgdCAhPT0gRU9GKSB7XG4gICAgICAgICAgYS5wdXNoKHQpO1xuICAgICAgICAgIHQgPSB0b2tlbigpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChmICYmIChhID0gZihhLCBuKyspKSA9PSBudWxsKSBjb250aW51ZTtcbiAgICAgICAgcm93cy5wdXNoKGEpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcm93cztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmb3JtYXQocm93cykge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkocm93c1swXSkpIHJldHVybiBmb3JtYXRSb3dzKHJvd3MpOyAvLyBkZXByZWNhdGVkOyB1c2UgZm9ybWF0Um93c1xuICAgICAgdmFyIGZpZWxkU2V0ID0gT2JqZWN0LmNyZWF0ZShudWxsKSwgZmllbGRzID0gW107XG5cbiAgICAgIC8vIENvbXB1dGUgdW5pcXVlIGZpZWxkcyBpbiBvcmRlciBvZiBkaXNjb3ZlcnkuXG4gICAgICByb3dzLmZvckVhY2goZnVuY3Rpb24ocm93KSB7XG4gICAgICAgIGZvciAodmFyIGZpZWxkIGluIHJvdykge1xuICAgICAgICAgIGlmICghKChmaWVsZCArPSBcIlwiKSBpbiBmaWVsZFNldCkpIHtcbiAgICAgICAgICAgIGZpZWxkcy5wdXNoKGZpZWxkU2V0W2ZpZWxkXSA9IGZpZWxkKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuXG4gICAgICByZXR1cm4gW2ZpZWxkcy5tYXAoZm9ybWF0VmFsdWUpLmpvaW4oZGVsaW1pdGVyKV0uY29uY2F0KHJvd3MubWFwKGZ1bmN0aW9uKHJvdykge1xuICAgICAgICByZXR1cm4gZmllbGRzLm1hcChmdW5jdGlvbihmaWVsZCkge1xuICAgICAgICAgIHJldHVybiBmb3JtYXRWYWx1ZShyb3dbZmllbGRdKTtcbiAgICAgICAgfSkuam9pbihkZWxpbWl0ZXIpO1xuICAgICAgfSkpLmpvaW4oXCJcXG5cIik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0Um93cyhyb3dzKSB7XG4gICAgICByZXR1cm4gcm93cy5tYXAoZm9ybWF0Um93KS5qb2luKFwiXFxuXCIpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGZvcm1hdFJvdyhyb3cpIHtcbiAgICAgIHJldHVybiByb3cubWFwKGZvcm1hdFZhbHVlKS5qb2luKGRlbGltaXRlcik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0VmFsdWUodGV4dCkge1xuICAgICAgcmV0dXJuIHJlRm9ybWF0LnRlc3QodGV4dCkgPyBcIlxcXCJcIiArIHRleHQucmVwbGFjZSgvXFxcIi9nLCBcIlxcXCJcXFwiXCIpICsgXCJcXFwiXCIgOiB0ZXh0O1xuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBwYXJzZTogcGFyc2UsXG4gICAgICBwYXJzZVJvd3M6IHBhcnNlUm93cyxcbiAgICAgIGZvcm1hdDogZm9ybWF0LFxuICAgICAgZm9ybWF0Um93czogZm9ybWF0Um93c1xuICAgIH07XG4gIH1cblxuICBleHBvcnRzLmNzdiA9IGRzdihcIixcIik7XG4gIGV4cG9ydHMudHN2ID0gZHN2KFwiXFx0XCIpO1xuXG4gIGV4cG9ydHMuZHN2ID0gZHN2O1xuXG59KSk7IiwiaWYgKHR5cGVvZiBNYXAgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgTWFwID0gZnVuY3Rpb24oKSB7IHRoaXMuY2xlYXIoKTsgfTtcbiAgTWFwLnByb3RvdHlwZSA9IHtcbiAgICBzZXQ6IGZ1bmN0aW9uKGssIHYpIHsgdGhpcy5fW2tdID0gdjsgcmV0dXJuIHRoaXM7IH0sXG4gICAgZ2V0OiBmdW5jdGlvbihrKSB7IHJldHVybiB0aGlzLl9ba107IH0sXG4gICAgaGFzOiBmdW5jdGlvbihrKSB7IHJldHVybiBrIGluIHRoaXMuXzsgfSxcbiAgICBkZWxldGU6IGZ1bmN0aW9uKGspIHsgcmV0dXJuIGsgaW4gdGhpcy5fICYmIGRlbGV0ZSB0aGlzLl9ba107IH0sXG4gICAgY2xlYXI6IGZ1bmN0aW9uKCkgeyB0aGlzLl8gPSBPYmplY3QuY3JlYXRlKG51bGwpOyB9LFxuICAgIGdldCBzaXplKCkgeyB2YXIgbiA9IDA7IGZvciAodmFyIGsgaW4gdGhpcy5fKSArK247IHJldHVybiBuOyB9LFxuICAgIGZvckVhY2g6IGZ1bmN0aW9uKGMpIHsgZm9yICh2YXIgayBpbiB0aGlzLl8pIGModGhpcy5fW2tdLCBrLCB0aGlzKTsgfVxuICB9O1xufSBlbHNlIChmdW5jdGlvbigpIHtcbiAgdmFyIG0gPSBuZXcgTWFwO1xuICBpZiAobS5zZXQoMCwgMCkgIT09IG0pIHtcbiAgICBtID0gbS5zZXQ7XG4gICAgTWFwLnByb3RvdHlwZS5zZXQgPSBmdW5jdGlvbigpIHsgbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpOyByZXR1cm4gdGhpczsgfTtcbiAgfVxufSkoKTtcblxuKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuICBmYWN0b3J5KChnbG9iYWwuZm9ybWF0ID0ge30pKTtcbn0odGhpcywgZnVuY3Rpb24gKGV4cG9ydHMpIHsgJ3VzZSBzdHJpY3QnO1xuXG4gIHZhciB6aENuID0ge1xuICAgIGRlY2ltYWw6IFwiLlwiLFxuICAgIHRob3VzYW5kczogXCIsXCIsXG4gICAgZ3JvdXBpbmc6IFszXSxcbiAgICBjdXJyZW5jeTogW1wiwqVcIiwgXCJcIl1cbiAgfTtcblxuICB2YXIgcnVSdSA9IHtcbiAgICBkZWNpbWFsOiBcIixcIixcbiAgICB0aG91c2FuZHM6IFwiXFx4YTBcIixcbiAgICBncm91cGluZzogWzNdLFxuICAgIGN1cnJlbmN5OiBbXCJcIiwgXCJcXHhhMNGA0YPQsS5cIl1cbiAgfTtcblxuICB2YXIgcHRCciA9IHtcbiAgICBkZWNpbWFsOiBcIixcIixcbiAgICB0aG91c2FuZHM6IFwiLlwiLFxuICAgIGdyb3VwaW5nOiBbM10sXG4gICAgY3VycmVuY3k6IFtcIlIkXCIsIFwiXCJdXG4gIH07XG5cbiAgdmFyIHBsUGwgPSB7XG4gICAgZGVjaW1hbDogXCIsXCIsXG4gICAgdGhvdXNhbmRzOiBcIi5cIixcbiAgICBncm91cGluZzogWzNdLFxuICAgIGN1cnJlbmN5OiBbXCJcIiwgXCJ6xYJcIl1cbiAgfTtcblxuICB2YXIgbmxObCA9IHtcbiAgICBkZWNpbWFsOiBcIixcIixcbiAgICB0aG91c2FuZHM6IFwiLlwiLFxuICAgIGdyb3VwaW5nOiBbM10sXG4gICAgY3VycmVuY3k6IFtcIuKCrFxceGEwXCIsIFwiXCJdXG4gIH07XG5cbiAgdmFyIG1rTWsgPSB7XG4gICAgZGVjaW1hbDogXCIsXCIsXG4gICAgdGhvdXNhbmRzOiBcIi5cIixcbiAgICBncm91cGluZzogWzNdLFxuICAgIGN1cnJlbmN5OiBbXCJcIiwgXCJcXHhhMNC00LXQvS5cIl1cbiAgfTtcblxuICB2YXIgaXRJdCA9IHtcbiAgICBkZWNpbWFsOiBcIixcIixcbiAgICB0aG91c2FuZHM6IFwiLlwiLFxuICAgIGdyb3VwaW5nOiBbM10sXG4gICAgY3VycmVuY3k6IFtcIuKCrFwiLCBcIlwiXVxuICB9O1xuXG4gIHZhciBoZUlsID0ge1xuICAgIGRlY2ltYWw6IFwiLlwiLFxuICAgIHRob3VzYW5kczogXCIsXCIsXG4gICAgZ3JvdXBpbmc6IFszXSxcbiAgICBjdXJyZW5jeTogW1wi4oKqXCIsIFwiXCJdXG4gIH07XG5cbiAgdmFyIGZyRnIgPSB7XG4gICAgZGVjaW1hbDogXCIsXCIsXG4gICAgdGhvdXNhbmRzOiBcIi5cIixcbiAgICBncm91cGluZzogWzNdLFxuICAgIGN1cnJlbmN5OiBbXCJcIiwgXCJcXHhhMOKCrFwiXVxuICB9O1xuXG4gIHZhciBmckNhID0ge1xuICAgIGRlY2ltYWw6IFwiLFwiLFxuICAgIHRob3VzYW5kczogXCJcXHhhMFwiLFxuICAgIGdyb3VwaW5nOiBbM10sXG4gICAgY3VycmVuY3k6IFtcIlwiLCBcIiRcIl1cbiAgfTtcblxuICB2YXIgZmlGaSA9IHtcbiAgICBkZWNpbWFsOiBcIixcIixcbiAgICB0aG91c2FuZHM6IFwiXFx4YTBcIixcbiAgICBncm91cGluZzogWzNdLFxuICAgIGN1cnJlbmN5OiBbXCJcIiwgXCJcXHhhMOKCrFwiXVxuICB9O1xuXG4gIHZhciBlc0VzID0ge1xuICAgIGRlY2ltYWw6IFwiLFwiLFxuICAgIHRob3VzYW5kczogXCIuXCIsXG4gICAgZ3JvdXBpbmc6IFszXSxcbiAgICBjdXJyZW5jeTogW1wiXCIsIFwiXFx4YTDigqxcIl1cbiAgfTtcblxuICB2YXIgZW5VcyA9IHtcbiAgICBkZWNpbWFsOiBcIi5cIixcbiAgICB0aG91c2FuZHM6IFwiLFwiLFxuICAgIGdyb3VwaW5nOiBbM10sXG4gICAgY3VycmVuY3k6IFtcIiRcIiwgXCJcIl1cbiAgfTtcblxuICB2YXIgZW5HYiA9IHtcbiAgICBkZWNpbWFsOiBcIi5cIixcbiAgICB0aG91c2FuZHM6IFwiLFwiLFxuICAgIGdyb3VwaW5nOiBbM10sXG4gICAgY3VycmVuY3k6IFtcIsKjXCIsIFwiXCJdXG4gIH07XG5cbiAgdmFyIGVuQ2EgPSB7XG4gICAgZGVjaW1hbDogXCIuXCIsXG4gICAgdGhvdXNhbmRzOiBcIixcIixcbiAgICBncm91cGluZzogWzNdLFxuICAgIGN1cnJlbmN5OiBbXCIkXCIsIFwiXCJdXG4gIH07XG5cbiAgdmFyIGRlRGUgPSB7XG4gICAgZGVjaW1hbDogXCIsXCIsXG4gICAgdGhvdXNhbmRzOiBcIi5cIixcbiAgICBncm91cGluZzogWzNdLFxuICAgIGN1cnJlbmN5OiBbXCJcIiwgXCJcXHhhMOKCrFwiXVxuICB9O1xuXG4gIHZhciBjYUVzID0ge1xuICAgIGRlY2ltYWw6IFwiLFwiLFxuICAgIHRob3VzYW5kczogXCIuXCIsXG4gICAgZ3JvdXBpbmc6IFszXSxcbiAgICBjdXJyZW5jeTogW1wiXCIsIFwiXFx4YTDigqxcIl1cbiAgfTtcblxuXG4gIC8vIENvbXB1dGVzIHRoZSBkZWNpbWFsIGNvZWZmaWNpZW50IGFuZCBleHBvbmVudCBvZiB0aGUgc3BlY2lmaWVkIG51bWJlciB4IHdpdGhcbiAgLy8gc2lnbmlmaWNhbnQgZGlnaXRzIHAsIHdoZXJlIHggaXMgcG9zaXRpdmUgYW5kIHAgaXMgaW4gWzEsIDIxXSBvciB1bmRlZmluZWQuXG4gIC8vIEZvciBleGFtcGxlLCBmb3JtYXREZWNpbWFsKDEuMjMpIHJldHVybnMgW1wiMTIzXCIsIDBdLlxuICBmdW5jdGlvbiBmb3JtYXREZWNpbWFsKHgsIHApIHtcbiAgICBpZiAoKGkgPSAoeCA9IHAgPyB4LnRvRXhwb25lbnRpYWwocCAtIDEpIDogeC50b0V4cG9uZW50aWFsKCkpLmluZGV4T2YoXCJlXCIpKSA8IDApIHJldHVybiBudWxsOyAvLyBOYU4sIMKxSW5maW5pdHlcbiAgICB2YXIgaSwgY29lZmZpY2llbnQgPSB4LnNsaWNlKDAsIGkpO1xuXG4gICAgLy8gVGhlIHN0cmluZyByZXR1cm5lZCBieSB0b0V4cG9uZW50aWFsIGVpdGhlciBoYXMgdGhlIGZvcm0gXFxkXFwuXFxkK2VbLStdXFxkK1xuICAgIC8vIChlLmcuLCAxLjJlKzMpIG9yIHRoZSBmb3JtIFxcZGVbLStdXFxkKyAoZS5nLiwgMWUrMykuXG4gICAgcmV0dXJuIFtcbiAgICAgIGNvZWZmaWNpZW50Lmxlbmd0aCA+IDEgPyBjb2VmZmljaWVudFswXSArIGNvZWZmaWNpZW50LnNsaWNlKDIpIDogY29lZmZpY2llbnQsXG4gICAgICAreC5zbGljZShpICsgMSlcbiAgICBdO1xuICB9XG5cbiAgZnVuY3Rpb24gZXhwb25lbnQoeCkge1xuICAgIHJldHVybiB4ID0gZm9ybWF0RGVjaW1hbChNYXRoLmFicyh4KSksIHggPyB4WzFdIDogTmFOO1xuICB9XG5cbiAgdmFyIHByZWZpeEV4cG9uZW50O1xuXG4gIGZ1bmN0aW9uIGZvcm1hdFByZWZpeEF1dG8oeCwgcCkge1xuICAgIHZhciBkID0gZm9ybWF0RGVjaW1hbCh4LCBwKTtcbiAgICBpZiAoIWQpIHJldHVybiB4ICsgXCJcIjtcbiAgICB2YXIgY29lZmZpY2llbnQgPSBkWzBdLFxuICAgICAgICBleHBvbmVudCA9IGRbMV0sXG4gICAgICAgIGkgPSBleHBvbmVudCAtIChwcmVmaXhFeHBvbmVudCA9IE1hdGgubWF4KC04LCBNYXRoLm1pbig4LCBNYXRoLmZsb29yKGV4cG9uZW50IC8gMykpKSAqIDMpICsgMSxcbiAgICAgICAgbiA9IGNvZWZmaWNpZW50Lmxlbmd0aDtcbiAgICByZXR1cm4gaSA9PT0gbiA/IGNvZWZmaWNpZW50XG4gICAgICAgIDogaSA+IG4gPyBjb2VmZmljaWVudCArIG5ldyBBcnJheShpIC0gbiArIDEpLmpvaW4oXCIwXCIpXG4gICAgICAgIDogaSA+IDAgPyBjb2VmZmljaWVudC5zbGljZSgwLCBpKSArIFwiLlwiICsgY29lZmZpY2llbnQuc2xpY2UoaSlcbiAgICAgICAgOiBcIjAuXCIgKyBuZXcgQXJyYXkoMSAtIGkpLmpvaW4oXCIwXCIpICsgZm9ybWF0RGVjaW1hbCh4LCBwICsgaSAtIDEpWzBdOyAvLyBsZXNzIHRoYW4gMXkhXG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRSb3VuZGVkKHgsIHApIHtcbiAgICB2YXIgZCA9IGZvcm1hdERlY2ltYWwoeCwgcCk7XG4gICAgaWYgKCFkKSByZXR1cm4geCArIFwiXCI7XG4gICAgdmFyIGNvZWZmaWNpZW50ID0gZFswXSxcbiAgICAgICAgZXhwb25lbnQgPSBkWzFdO1xuICAgIHJldHVybiBleHBvbmVudCA8IDAgPyBcIjAuXCIgKyBuZXcgQXJyYXkoLWV4cG9uZW50KS5qb2luKFwiMFwiKSArIGNvZWZmaWNpZW50XG4gICAgICAgIDogY29lZmZpY2llbnQubGVuZ3RoID4gZXhwb25lbnQgKyAxID8gY29lZmZpY2llbnQuc2xpY2UoMCwgZXhwb25lbnQgKyAxKSArIFwiLlwiICsgY29lZmZpY2llbnQuc2xpY2UoZXhwb25lbnQgKyAxKVxuICAgICAgICA6IGNvZWZmaWNpZW50ICsgbmV3IEFycmF5KGV4cG9uZW50IC0gY29lZmZpY2llbnQubGVuZ3RoICsgMikuam9pbihcIjBcIik7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXREZWZhdWx0KHgsIHApIHtcbiAgICB4ID0geC50b1ByZWNpc2lvbihwKTtcblxuICAgIG91dDogZm9yICh2YXIgbiA9IHgubGVuZ3RoLCBpID0gMSwgaTAgPSAtMSwgaTE7IGkgPCBuOyArK2kpIHtcbiAgICAgIHN3aXRjaCAoeFtpXSkge1xuICAgICAgICBjYXNlIFwiLlwiOiBpMCA9IGkxID0gaTsgYnJlYWs7XG4gICAgICAgIGNhc2UgXCIwXCI6IGlmIChpMCA9PT0gMCkgaTAgPSBpOyBpMSA9IGk7IGJyZWFrO1xuICAgICAgICBjYXNlIFwiZVwiOiBicmVhayBvdXQ7XG4gICAgICAgIGRlZmF1bHQ6IGlmIChpMCA+IDApIGkwID0gMDsgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGkwID4gMCA/IHguc2xpY2UoMCwgaTApICsgeC5zbGljZShpMSArIDEpIDogeDtcbiAgfVxuXG4gIHZhciBmb3JtYXRUeXBlcyA9IHtcbiAgICBcIlwiOiBmb3JtYXREZWZhdWx0LFxuICAgIFwiJVwiOiBmdW5jdGlvbih4LCBwKSB7IHJldHVybiAoeCAqIDEwMCkudG9GaXhlZChwKTsgfSxcbiAgICBcImJcIjogZnVuY3Rpb24oeCkgeyByZXR1cm4gTWF0aC5yb3VuZCh4KS50b1N0cmluZygyKTsgfSxcbiAgICBcImNcIjogZnVuY3Rpb24oeCkgeyByZXR1cm4geCArIFwiXCI7IH0sXG4gICAgXCJkXCI6IGZ1bmN0aW9uKHgpIHsgcmV0dXJuIE1hdGgucm91bmQoeCkudG9TdHJpbmcoMTApOyB9LFxuICAgIFwiZVwiOiBmdW5jdGlvbih4LCBwKSB7IHJldHVybiB4LnRvRXhwb25lbnRpYWwocCk7IH0sXG4gICAgXCJmXCI6IGZ1bmN0aW9uKHgsIHApIHsgcmV0dXJuIHgudG9GaXhlZChwKTsgfSxcbiAgICBcImdcIjogZnVuY3Rpb24oeCwgcCkgeyByZXR1cm4geC50b1ByZWNpc2lvbihwKTsgfSxcbiAgICBcIm9cIjogZnVuY3Rpb24oeCkgeyByZXR1cm4gTWF0aC5yb3VuZCh4KS50b1N0cmluZyg4KTsgfSxcbiAgICBcInBcIjogZnVuY3Rpb24oeCwgcCkgeyByZXR1cm4gZm9ybWF0Um91bmRlZCh4ICogMTAwLCBwKTsgfSxcbiAgICBcInJcIjogZm9ybWF0Um91bmRlZCxcbiAgICBcInNcIjogZm9ybWF0UHJlZml4QXV0byxcbiAgICBcIlhcIjogZnVuY3Rpb24oeCkgeyByZXR1cm4gTWF0aC5yb3VuZCh4KS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTsgfSxcbiAgICBcInhcIjogZnVuY3Rpb24oeCkgeyByZXR1cm4gTWF0aC5yb3VuZCh4KS50b1N0cmluZygxNik7IH1cbiAgfTtcblxuXG4gIC8vIFtbZmlsbF1hbGlnbl1bc2lnbl1bc3ltYm9sXVswXVt3aWR0aF1bLF1bLnByZWNpc2lvbl1bdHlwZV1cbiAgdmFyIHJlID0gL14oPzooLik/KFs8Pj1eXSkpPyhbK1xcLVxcKCBdKT8oWyQjXSk/KDApPyhcXGQrKT8oLCk/KFxcLlxcZCspPyhbYS16JV0pPyQvaTtcblxuICBmdW5jdGlvbiBmb3JtYXRTcGVjaWZpZXIoc3BlY2lmaWVyKSB7XG4gICAgcmV0dXJuIG5ldyBGb3JtYXRTcGVjaWZpZXIoc3BlY2lmaWVyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIEZvcm1hdFNwZWNpZmllcihzcGVjaWZpZXIpIHtcbiAgICBpZiAoIShtYXRjaCA9IHJlLmV4ZWMoc3BlY2lmaWVyKSkpIHRocm93IG5ldyBFcnJvcihcImludmFsaWQgZm9ybWF0OiBcIiArIHNwZWNpZmllcik7XG5cbiAgICB2YXIgbWF0Y2gsXG4gICAgICAgIGZpbGwgPSBtYXRjaFsxXSB8fCBcIiBcIixcbiAgICAgICAgYWxpZ24gPSBtYXRjaFsyXSB8fCBcIj5cIixcbiAgICAgICAgc2lnbiA9IG1hdGNoWzNdIHx8IFwiLVwiLFxuICAgICAgICBzeW1ib2wgPSBtYXRjaFs0XSB8fCBcIlwiLFxuICAgICAgICB6ZXJvID0gISFtYXRjaFs1XSxcbiAgICAgICAgd2lkdGggPSBtYXRjaFs2XSAmJiArbWF0Y2hbNl0sXG4gICAgICAgIGNvbW1hID0gISFtYXRjaFs3XSxcbiAgICAgICAgcHJlY2lzaW9uID0gbWF0Y2hbOF0gJiYgK21hdGNoWzhdLnNsaWNlKDEpLFxuICAgICAgICB0eXBlID0gbWF0Y2hbOV0gfHwgXCJcIjtcblxuICAgIC8vIFRoZSBcIm5cIiB0eXBlIGlzIGFuIGFsaWFzIGZvciBcIixnXCIuXG4gICAgaWYgKHR5cGUgPT09IFwiblwiKSBjb21tYSA9IHRydWUsIHR5cGUgPSBcImdcIjtcblxuICAgIC8vIE1hcCBpbnZhbGlkIHR5cGVzIHRvIHRoZSBkZWZhdWx0IGZvcm1hdC5cbiAgICBlbHNlIGlmICghZm9ybWF0VHlwZXNbdHlwZV0pIHR5cGUgPSBcIlwiO1xuXG4gICAgLy8gSWYgemVybyBmaWxsIGlzIHNwZWNpZmllZCwgcGFkZGluZyBnb2VzIGFmdGVyIHNpZ24gYW5kIGJlZm9yZSBkaWdpdHMuXG4gICAgaWYgKHplcm8gfHwgKGZpbGwgPT09IFwiMFwiICYmIGFsaWduID09PSBcIj1cIikpIHplcm8gPSB0cnVlLCBmaWxsID0gXCIwXCIsIGFsaWduID0gXCI9XCI7XG5cbiAgICB0aGlzLmZpbGwgPSBmaWxsO1xuICAgIHRoaXMuYWxpZ24gPSBhbGlnbjtcbiAgICB0aGlzLnNpZ24gPSBzaWduO1xuICAgIHRoaXMuc3ltYm9sID0gc3ltYm9sO1xuICAgIHRoaXMuemVybyA9IHplcm87XG4gICAgdGhpcy53aWR0aCA9IHdpZHRoO1xuICAgIHRoaXMuY29tbWEgPSBjb21tYTtcbiAgICB0aGlzLnByZWNpc2lvbiA9IHByZWNpc2lvbjtcbiAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICB9XG5cbiAgRm9ybWF0U3BlY2lmaWVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmZpbGxcbiAgICAgICAgKyB0aGlzLmFsaWduXG4gICAgICAgICsgdGhpcy5zaWduXG4gICAgICAgICsgdGhpcy5zeW1ib2xcbiAgICAgICAgKyAodGhpcy56ZXJvID8gXCIwXCIgOiBcIlwiKVxuICAgICAgICArICh0aGlzLndpZHRoID09IG51bGwgPyBcIlwiIDogTWF0aC5tYXgoMSwgdGhpcy53aWR0aCB8IDApKVxuICAgICAgICArICh0aGlzLmNvbW1hID8gXCIsXCIgOiBcIlwiKVxuICAgICAgICArICh0aGlzLnByZWNpc2lvbiA9PSBudWxsID8gXCJcIiA6IFwiLlwiICsgTWF0aC5tYXgoMCwgdGhpcy5wcmVjaXNpb24gfCAwKSlcbiAgICAgICAgKyB0aGlzLnR5cGU7XG4gIH07XG5cbiAgZnVuY3Rpb24gZm9ybWF0R3JvdXAoZ3JvdXBpbmcsIHRob3VzYW5kcykge1xuICAgIHJldHVybiBmdW5jdGlvbih2YWx1ZSwgd2lkdGgpIHtcbiAgICAgIHZhciBpID0gdmFsdWUubGVuZ3RoLFxuICAgICAgICAgIHQgPSBbXSxcbiAgICAgICAgICBqID0gMCxcbiAgICAgICAgICBnID0gZ3JvdXBpbmdbMF0sXG4gICAgICAgICAgbGVuZ3RoID0gMDtcblxuICAgICAgd2hpbGUgKGkgPiAwICYmIGcgPiAwKSB7XG4gICAgICAgIGlmIChsZW5ndGggKyBnICsgMSA+IHdpZHRoKSBnID0gTWF0aC5tYXgoMSwgd2lkdGggLSBsZW5ndGgpO1xuICAgICAgICB0LnB1c2godmFsdWUuc3Vic3RyaW5nKGkgLT0gZywgaSArIGcpKTtcbiAgICAgICAgaWYgKChsZW5ndGggKz0gZyArIDEpID4gd2lkdGgpIGJyZWFrO1xuICAgICAgICBnID0gZ3JvdXBpbmdbaiA9IChqICsgMSkgJSBncm91cGluZy5sZW5ndGhdO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdC5yZXZlcnNlKCkuam9pbih0aG91c2FuZHMpO1xuICAgIH07XG4gIH1cblxuICB2YXIgcHJlZml4ZXMgPSBbXCJ5XCIsXCJ6XCIsXCJhXCIsXCJmXCIsXCJwXCIsXCJuXCIsXCLCtVwiLFwibVwiLFwiXCIsXCJrXCIsXCJNXCIsXCJHXCIsXCJUXCIsXCJQXCIsXCJFXCIsXCJaXCIsXCJZXCJdO1xuXG4gIGZ1bmN0aW9uIGlkZW50aXR5KHgpIHtcbiAgICByZXR1cm4geDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGxvY2FsZShsb2NhbGUpIHtcbiAgICB2YXIgZ3JvdXAgPSBsb2NhbGUuZ3JvdXBpbmcgJiYgbG9jYWxlLnRob3VzYW5kcyA/IGZvcm1hdEdyb3VwKGxvY2FsZS5ncm91cGluZywgbG9jYWxlLnRob3VzYW5kcykgOiBpZGVudGl0eSxcbiAgICAgICAgY3VycmVuY3kgPSBsb2NhbGUuY3VycmVuY3ksXG4gICAgICAgIGRlY2ltYWwgPSBsb2NhbGUuZGVjaW1hbDtcblxuICAgIGZ1bmN0aW9uIGZvcm1hdChzcGVjaWZpZXIpIHtcbiAgICAgIHNwZWNpZmllciA9IGZvcm1hdFNwZWNpZmllcihzcGVjaWZpZXIpO1xuXG4gICAgICB2YXIgZmlsbCA9IHNwZWNpZmllci5maWxsLFxuICAgICAgICAgIGFsaWduID0gc3BlY2lmaWVyLmFsaWduLFxuICAgICAgICAgIHNpZ24gPSBzcGVjaWZpZXIuc2lnbixcbiAgICAgICAgICBzeW1ib2wgPSBzcGVjaWZpZXIuc3ltYm9sLFxuICAgICAgICAgIHplcm8gPSBzcGVjaWZpZXIuemVybyxcbiAgICAgICAgICB3aWR0aCA9IHNwZWNpZmllci53aWR0aCxcbiAgICAgICAgICBjb21tYSA9IHNwZWNpZmllci5jb21tYSxcbiAgICAgICAgICBwcmVjaXNpb24gPSBzcGVjaWZpZXIucHJlY2lzaW9uLFxuICAgICAgICAgIHR5cGUgPSBzcGVjaWZpZXIudHlwZTtcblxuICAgICAgLy8gQ29tcHV0ZSB0aGUgcHJlZml4IGFuZCBzdWZmaXguXG4gICAgICAvLyBGb3IgU0ktcHJlZml4LCB0aGUgc3VmZml4IGlzIGxhemlseSBjb21wdXRlZC5cbiAgICAgIHZhciBwcmVmaXggPSBzeW1ib2wgPT09IFwiJFwiID8gY3VycmVuY3lbMF0gOiBzeW1ib2wgPT09IFwiI1wiICYmIC9bYm94WF0vLnRlc3QodHlwZSkgPyBcIjBcIiArIHR5cGUudG9Mb3dlckNhc2UoKSA6IFwiXCIsXG4gICAgICAgICAgc3VmZml4ID0gc3ltYm9sID09PSBcIiRcIiA/IGN1cnJlbmN5WzFdIDogL1slcF0vLnRlc3QodHlwZSkgPyBcIiVcIiA6IFwiXCI7XG5cbiAgICAgIC8vIFdoYXQgZm9ybWF0IGZ1bmN0aW9uIHNob3VsZCB3ZSB1c2U/XG4gICAgICAvLyBJcyB0aGlzIGFuIGludGVnZXIgdHlwZT9cbiAgICAgIC8vIENhbiB0aGlzIHR5cGUgZ2VuZXJhdGUgZXhwb25lbnRpYWwgbm90YXRpb24/XG4gICAgICB2YXIgZm9ybWF0VHlwZSA9IGZvcm1hdFR5cGVzW3R5cGVdLFxuICAgICAgICAgIG1heWJlU3VmZml4ID0gIXR5cGUgfHwgL1tkZWZncHJzJV0vLnRlc3QodHlwZSk7XG5cbiAgICAgIC8vIFNldCB0aGUgZGVmYXVsdCBwcmVjaXNpb24gaWYgbm90IHNwZWNpZmllZCxcbiAgICAgIC8vIG9yIGNsYW1wIHRoZSBzcGVjaWZpZWQgcHJlY2lzaW9uIHRvIHRoZSBzdXBwb3J0ZWQgcmFuZ2UuXG4gICAgICAvLyBGb3Igc2lnbmlmaWNhbnQgcHJlY2lzaW9uLCBpdCBtdXN0IGJlIGluIFsxLCAyMV0uXG4gICAgICAvLyBGb3IgZml4ZWQgcHJlY2lzaW9uLCBpdCBtdXN0IGJlIGluIFswLCAyMF0uXG4gICAgICBwcmVjaXNpb24gPSBwcmVjaXNpb24gPT0gbnVsbCA/ICh0eXBlID8gNiA6IDEyKVxuICAgICAgICAgIDogL1tncHJzXS8udGVzdCh0eXBlKSA/IE1hdGgubWF4KDEsIE1hdGgubWluKDIxLCBwcmVjaXNpb24pKVxuICAgICAgICAgIDogTWF0aC5tYXgoMCwgTWF0aC5taW4oMjAsIHByZWNpc2lvbikpO1xuXG4gICAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgdmFyIHZhbHVlUHJlZml4ID0gcHJlZml4LFxuICAgICAgICAgICAgdmFsdWVTdWZmaXggPSBzdWZmaXg7XG5cbiAgICAgICAgaWYgKHR5cGUgPT09IFwiY1wiKSB7XG4gICAgICAgICAgdmFsdWVTdWZmaXggPSBmb3JtYXRUeXBlKHZhbHVlKSArIHZhbHVlU3VmZml4O1xuICAgICAgICAgIHZhbHVlID0gXCJcIjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB2YWx1ZSA9ICt2YWx1ZTtcblxuICAgICAgICAgIC8vIENvbnZlcnQgbmVnYXRpdmUgdG8gcG9zaXRpdmUsIGFuZCBjb21wdXRlIHRoZSBwcmVmaXguXG4gICAgICAgICAgLy8gTm90ZSB0aGF0IC0wIGlzIG5vdCBsZXNzIHRoYW4gMCwgYnV0IDEgLyAtMCBpcyFcbiAgICAgICAgICB2YXIgdmFsdWVOZWdhdGl2ZSA9ICh2YWx1ZSA8IDAgfHwgMSAvIHZhbHVlIDwgMCkgJiYgKHZhbHVlICo9IC0xLCB0cnVlKTtcblxuICAgICAgICAgIC8vIFBlcmZvcm0gdGhlIGluaXRpYWwgZm9ybWF0dGluZy5cbiAgICAgICAgICB2YWx1ZSA9IGZvcm1hdFR5cGUodmFsdWUsIHByZWNpc2lvbik7XG5cbiAgICAgICAgICAvLyBDb21wdXRlIHRoZSBwcmVmaXggYW5kIHN1ZmZpeC5cbiAgICAgICAgICB2YWx1ZVByZWZpeCA9ICh2YWx1ZU5lZ2F0aXZlID8gKHNpZ24gPT09IFwiKFwiID8gc2lnbiA6IFwiLVwiKSA6IHNpZ24gPT09IFwiLVwiIHx8IHNpZ24gPT09IFwiKFwiID8gXCJcIiA6IHNpZ24pICsgdmFsdWVQcmVmaXg7XG4gICAgICAgICAgdmFsdWVTdWZmaXggPSB2YWx1ZVN1ZmZpeCArICh0eXBlID09PSBcInNcIiA/IHByZWZpeGVzWzggKyBwcmVmaXhFeHBvbmVudCAvIDNdIDogXCJcIikgKyAodmFsdWVOZWdhdGl2ZSAmJiBzaWduID09PSBcIihcIiA/IFwiKVwiIDogXCJcIik7XG5cbiAgICAgICAgICAvLyBCcmVhayB0aGUgZm9ybWF0dGVkIHZhbHVlIGludG8gdGhlIGludGVnZXIg4oCcdmFsdWXigJ0gcGFydCB0aGF0IGNhbiBiZVxuICAgICAgICAgIC8vIGdyb3VwZWQsIGFuZCBmcmFjdGlvbmFsIG9yIGV4cG9uZW50aWFsIOKAnHN1ZmZpeOKAnSBwYXJ0IHRoYXQgaXMgbm90LlxuICAgICAgICAgIGlmIChtYXliZVN1ZmZpeCkge1xuICAgICAgICAgICAgdmFyIGkgPSAtMSwgbiA9IHZhbHVlLmxlbmd0aCwgYztcbiAgICAgICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgICAgIGlmIChjID0gdmFsdWUuY2hhckNvZGVBdChpKSwgNDggPiBjIHx8IGMgPiA1Nykge1xuICAgICAgICAgICAgICAgIHZhbHVlU3VmZml4ID0gKGMgPT09IDQ2ID8gZGVjaW1hbCArIHZhbHVlLnNsaWNlKGkgKyAxKSA6IHZhbHVlLnNsaWNlKGkpKSArIHZhbHVlU3VmZml4O1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUuc2xpY2UoMCwgaSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgZmlsbCBjaGFyYWN0ZXIgaXMgbm90IFwiMFwiLCBncm91cGluZyBpcyBhcHBsaWVkIGJlZm9yZSBwYWRkaW5nLlxuICAgICAgICBpZiAoY29tbWEgJiYgIXplcm8pIHZhbHVlID0gZ3JvdXAodmFsdWUsIEluZmluaXR5KTtcblxuICAgICAgICAvLyBDb21wdXRlIHRoZSBwYWRkaW5nLlxuICAgICAgICB2YXIgbGVuZ3RoID0gdmFsdWVQcmVmaXgubGVuZ3RoICsgdmFsdWUubGVuZ3RoICsgdmFsdWVTdWZmaXgubGVuZ3RoLFxuICAgICAgICAgICAgcGFkZGluZyA9IGxlbmd0aCA8IHdpZHRoID8gbmV3IEFycmF5KHdpZHRoIC0gbGVuZ3RoICsgMSkuam9pbihmaWxsKSA6IFwiXCI7XG5cbiAgICAgICAgLy8gSWYgdGhlIGZpbGwgY2hhcmFjdGVyIGlzIFwiMFwiLCBncm91cGluZyBpcyBhcHBsaWVkIGFmdGVyIHBhZGRpbmcuXG4gICAgICAgIGlmIChjb21tYSAmJiB6ZXJvKSB2YWx1ZSA9IGdyb3VwKHBhZGRpbmcgKyB2YWx1ZSwgcGFkZGluZy5sZW5ndGggPyB3aWR0aCAtIHZhbHVlU3VmZml4Lmxlbmd0aCA6IEluZmluaXR5KSwgcGFkZGluZyA9IFwiXCI7XG5cbiAgICAgICAgLy8gUmVjb25zdHJ1Y3QgdGhlIGZpbmFsIG91dHB1dCBiYXNlZCBvbiB0aGUgZGVzaXJlZCBhbGlnbm1lbnQuXG4gICAgICAgIHN3aXRjaCAoYWxpZ24pIHtcbiAgICAgICAgICBjYXNlIFwiPFwiOiByZXR1cm4gdmFsdWVQcmVmaXggKyB2YWx1ZSArIHZhbHVlU3VmZml4ICsgcGFkZGluZztcbiAgICAgICAgICBjYXNlIFwiPVwiOiByZXR1cm4gdmFsdWVQcmVmaXggKyBwYWRkaW5nICsgdmFsdWUgKyB2YWx1ZVN1ZmZpeDtcbiAgICAgICAgICBjYXNlIFwiXlwiOiByZXR1cm4gcGFkZGluZy5zbGljZSgwLCBsZW5ndGggPSBwYWRkaW5nLmxlbmd0aCA+PiAxKSArIHZhbHVlUHJlZml4ICsgdmFsdWUgKyB2YWx1ZVN1ZmZpeCArIHBhZGRpbmcuc2xpY2UobGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcGFkZGluZyArIHZhbHVlUHJlZml4ICsgdmFsdWUgKyB2YWx1ZVN1ZmZpeDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0UHJlZml4KHNwZWNpZmllciwgdmFsdWUpIHtcbiAgICAgIHZhciBmID0gZm9ybWF0KChzcGVjaWZpZXIgPSBmb3JtYXRTcGVjaWZpZXIoc3BlY2lmaWVyKSwgc3BlY2lmaWVyLnR5cGUgPSBcImZcIiwgc3BlY2lmaWVyKSksXG4gICAgICAgICAgZSA9IE1hdGgubWF4KC04LCBNYXRoLm1pbig4LCBNYXRoLmZsb29yKGV4cG9uZW50KHZhbHVlKSAvIDMpKSkgKiAzLFxuICAgICAgICAgIGsgPSBNYXRoLnBvdygxMCwgLWUpLFxuICAgICAgICAgIHByZWZpeCA9IHByZWZpeGVzWzggKyBlIC8gM107XG4gICAgICByZXR1cm4gZnVuY3Rpb24odmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIGYoayAqIHZhbHVlKSArIHByZWZpeDtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGZvcm1hdDogZm9ybWF0LFxuICAgICAgZm9ybWF0UHJlZml4OiBmb3JtYXRQcmVmaXhcbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gcHJlY2lzaW9uUm91bmQoc3RlcCwgbWF4KSB7XG4gICAgcmV0dXJuIE1hdGgubWF4KDAsIGV4cG9uZW50KE1hdGguYWJzKG1heCkpIC0gZXhwb25lbnQoTWF0aC5hYnMoc3RlcCkpKSArIDE7XG4gIH1cblxuICBmdW5jdGlvbiBwcmVjaXNpb25QcmVmaXgoc3RlcCwgdmFsdWUpIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgTWF0aC5tYXgoLTgsIE1hdGgubWluKDgsIE1hdGguZmxvb3IoZXhwb25lbnQodmFsdWUpIC8gMykpKSAqIDMgLSBleHBvbmVudChNYXRoLmFicyhzdGVwKSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gcHJlY2lzaW9uRml4ZWQoc3RlcCkge1xuICAgIHJldHVybiBNYXRoLm1heCgwLCAtZXhwb25lbnQoTWF0aC5hYnMoc3RlcCkpKTtcbiAgfVxuXG4gIHZhciBsb2NhbGVEZWZpbml0aW9ucyA9IChuZXcgTWFwKVxuICAgICAgLnNldChcImNhLUVTXCIsIGNhRXMpXG4gICAgICAuc2V0KFwiZGUtREVcIiwgZGVEZSlcbiAgICAgIC5zZXQoXCJlbi1DQVwiLCBlbkNhKVxuICAgICAgLnNldChcImVuLUdCXCIsIGVuR2IpXG4gICAgICAuc2V0KFwiZW4tVVNcIiwgZW5VcylcbiAgICAgIC5zZXQoXCJlcy1FU1wiLCBlc0VzKVxuICAgICAgLnNldChcImZpLUZJXCIsIGZpRmkpXG4gICAgICAuc2V0KFwiZnItQ0FcIiwgZnJDYSlcbiAgICAgIC5zZXQoXCJmci1GUlwiLCBmckZyKVxuICAgICAgLnNldChcImhlLUlMXCIsIGhlSWwpXG4gICAgICAuc2V0KFwiaXQtSVRcIiwgaXRJdClcbiAgICAgIC5zZXQoXCJtay1NS1wiLCBta01rKVxuICAgICAgLnNldChcIm5sLU5MXCIsIG5sTmwpXG4gICAgICAuc2V0KFwicGwtUExcIiwgcGxQbClcbiAgICAgIC5zZXQoXCJwdC1CUlwiLCBwdEJyKVxuICAgICAgLnNldChcInJ1LVJVXCIsIHJ1UnUpXG4gICAgICAuc2V0KFwiemgtQ05cIiwgemhDbik7XG5cbiAgdmFyIGRlZmF1bHRMb2NhbGUgPSBsb2NhbGUoZW5Vcyk7XG4gIGV4cG9ydHMuZm9ybWF0ID0gZGVmYXVsdExvY2FsZS5mb3JtYXQ7XG4gIGV4cG9ydHMuZm9ybWF0UHJlZml4ID0gZGVmYXVsdExvY2FsZS5mb3JtYXRQcmVmaXg7XG5cbiAgZnVuY3Rpb24gbG9jYWxlRm9ybWF0KGRlZmluaXRpb24pIHtcbiAgICBpZiAodHlwZW9mIGRlZmluaXRpb24gPT09IFwic3RyaW5nXCIpIHtcbiAgICAgIGRlZmluaXRpb24gPSBsb2NhbGVEZWZpbml0aW9ucy5nZXQoZGVmaW5pdGlvbik7XG4gICAgICBpZiAoIWRlZmluaXRpb24pIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gbG9jYWxlKGRlZmluaXRpb24pO1xuICB9XG4gIDtcblxuICBleHBvcnRzLmxvY2FsZUZvcm1hdCA9IGxvY2FsZUZvcm1hdDtcbiAgZXhwb3J0cy5mb3JtYXRTcGVjaWZpZXIgPSBmb3JtYXRTcGVjaWZpZXI7XG4gIGV4cG9ydHMucHJlY2lzaW9uRml4ZWQgPSBwcmVjaXNpb25GaXhlZDtcbiAgZXhwb3J0cy5wcmVjaXNpb25QcmVmaXggPSBwcmVjaXNpb25QcmVmaXg7XG4gIGV4cG9ydHMucHJlY2lzaW9uUm91bmQgPSBwcmVjaXNpb25Sb3VuZDtcblxufSkpOyIsImlmICh0eXBlb2YgTWFwID09PSBcInVuZGVmaW5lZFwiKSB7XG4gIE1hcCA9IGZ1bmN0aW9uKCkgeyB0aGlzLmNsZWFyKCk7IH07XG4gIE1hcC5wcm90b3R5cGUgPSB7XG4gICAgc2V0OiBmdW5jdGlvbihrLCB2KSB7IHRoaXMuX1trXSA9IHY7IHJldHVybiB0aGlzOyB9LFxuICAgIGdldDogZnVuY3Rpb24oaykgeyByZXR1cm4gdGhpcy5fW2tdOyB9LFxuICAgIGhhczogZnVuY3Rpb24oaykgeyByZXR1cm4gayBpbiB0aGlzLl87IH0sXG4gICAgZGVsZXRlOiBmdW5jdGlvbihrKSB7IHJldHVybiBrIGluIHRoaXMuXyAmJiBkZWxldGUgdGhpcy5fW2tdOyB9LFxuICAgIGNsZWFyOiBmdW5jdGlvbigpIHsgdGhpcy5fID0gT2JqZWN0LmNyZWF0ZShudWxsKTsgfSxcbiAgICBnZXQgc2l6ZSgpIHsgdmFyIG4gPSAwOyBmb3IgKHZhciBrIGluIHRoaXMuXykgKytuOyByZXR1cm4gbjsgfSxcbiAgICBmb3JFYWNoOiBmdW5jdGlvbihjKSB7IGZvciAodmFyIGsgaW4gdGhpcy5fKSBjKHRoaXMuX1trXSwgaywgdGhpcyk7IH1cbiAgfTtcbn0gZWxzZSAoZnVuY3Rpb24oKSB7XG4gIHZhciBtID0gbmV3IE1hcDtcbiAgaWYgKG0uc2V0KDAsIDApICE9PSBtKSB7XG4gICAgbSA9IG0uc2V0O1xuICAgIE1hcC5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24oKSB7IG0uYXBwbHkodGhpcywgYXJndW1lbnRzKTsgcmV0dXJuIHRoaXM7IH07XG4gIH1cbn0pKCk7XG5cbihmdW5jdGlvbiAoZ2xvYmFsLCBmYWN0b3J5KSB7XG4gIHR5cGVvZiBleHBvcnRzID09PSAnb2JqZWN0JyAmJiB0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyA/IGZhY3RvcnkoZXhwb3J0cykgOlxuICB0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQgPyBkZWZpbmUoWydleHBvcnRzJ10sIGZhY3RvcnkpIDpcbiAgZmFjdG9yeSgoZ2xvYmFsLnRpbWVGb3JtYXQgPSB7fSkpO1xufSh0aGlzLCBmdW5jdGlvbiAoZXhwb3J0cykgeyAndXNlIHN0cmljdCc7XG5cbiAgdmFyIHpoQ24gPSB7XG4gICAgZGF0ZVRpbWU6IFwiJWEgJWIgJWUgJVggJVlcIixcbiAgICBkYXRlOiBcIiVZLyUtbS8lLWRcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wi5LiK5Y2IXCIsIFwi5LiL5Y2IXCJdLFxuICAgIGRheXM6IFtcIuaYn+acn+aXpVwiLCBcIuaYn+acn+S4gFwiLCBcIuaYn+acn+S6jFwiLCBcIuaYn+acn+S4iVwiLCBcIuaYn+acn+Wbm1wiLCBcIuaYn+acn+S6lFwiLCBcIuaYn+acn+WFrVwiXSxcbiAgICBzaG9ydERheXM6IFtcIuaYn+acn+aXpVwiLCBcIuaYn+acn+S4gFwiLCBcIuaYn+acn+S6jFwiLCBcIuaYn+acn+S4iVwiLCBcIuaYn+acn+Wbm1wiLCBcIuaYn+acn+S6lFwiLCBcIuaYn+acn+WFrVwiXSxcbiAgICBtb250aHM6IFtcIuS4gOaciFwiLCBcIuS6jOaciFwiLCBcIuS4ieaciFwiLCBcIuWbm+aciFwiLCBcIuS6lOaciFwiLCBcIuWFreaciFwiLCBcIuS4g+aciFwiLCBcIuWFq+aciFwiLCBcIuS5neaciFwiLCBcIuWNgeaciFwiLCBcIuWNgeS4gOaciFwiLCBcIuWNgeS6jOaciFwiXSxcbiAgICBzaG9ydE1vbnRoczogW1wi5LiA5pyIXCIsIFwi5LqM5pyIXCIsIFwi5LiJ5pyIXCIsIFwi5Zub5pyIXCIsIFwi5LqU5pyIXCIsIFwi5YWt5pyIXCIsIFwi5LiD5pyIXCIsIFwi5YWr5pyIXCIsIFwi5Lmd5pyIXCIsIFwi5Y2B5pyIXCIsIFwi5Y2B5LiA5pyIXCIsIFwi5Y2B5LqM5pyIXCJdXG4gIH07XG5cbiAgdmFyIHJ1UnUgPSB7XG4gICAgZGF0ZVRpbWU6IFwiJUEsICVlICVCICVZINCzLiAlWFwiLFxuICAgIGRhdGU6IFwiJWQuJW0uJVlcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wiQU1cIiwgXCJQTVwiXSxcbiAgICBkYXlzOiBbXCLQstC+0YHQutGA0LXRgdC10L3RjNC1XCIsIFwi0L/QvtC90LXQtNC10LvRjNC90LjQulwiLCBcItCy0YLQvtGA0L3QuNC6XCIsIFwi0YHRgNC10LTQsFwiLCBcItGH0LXRgtCy0LXRgNCzXCIsIFwi0L/Rj9GC0L3QuNGG0LBcIiwgXCLRgdGD0LHQsdC+0YLQsFwiXSxcbiAgICBzaG9ydERheXM6IFtcItCy0YFcIiwgXCLQv9C9XCIsIFwi0LLRglwiLCBcItGB0YBcIiwgXCLRh9GCXCIsIFwi0L/RglwiLCBcItGB0LFcIl0sXG4gICAgbW9udGhzOiBbXCLRj9C90LLQsNGA0Y9cIiwgXCLRhNC10LLRgNCw0LvRj1wiLCBcItC80LDRgNGC0LBcIiwgXCLQsNC/0YDQtdC70Y9cIiwgXCLQvNCw0Y9cIiwgXCLQuNGO0L3Rj1wiLCBcItC40Y7Qu9GPXCIsIFwi0LDQstCz0YPRgdGC0LBcIiwgXCLRgdC10L3RgtGP0LHRgNGPXCIsIFwi0L7QutGC0Y/QsdGA0Y9cIiwgXCLQvdC+0Y/QsdGA0Y9cIiwgXCLQtNC10LrQsNCx0YDRj1wiXSxcbiAgICBzaG9ydE1vbnRoczogW1wi0Y/QvdCyXCIsIFwi0YTQtdCyXCIsIFwi0LzQsNGAXCIsIFwi0LDQv9GAXCIsIFwi0LzQsNC5XCIsIFwi0LjRjtC9XCIsIFwi0LjRjtC7XCIsIFwi0LDQstCzXCIsIFwi0YHQtdC9XCIsIFwi0L7QutGCXCIsIFwi0L3QvtGPXCIsIFwi0LTQtdC6XCJdXG4gIH07XG5cbiAgdmFyIHB0QnIgPSB7XG4gICAgZGF0ZVRpbWU6IFwiJUEsICVlIGRlICVCIGRlICVZLiAlWFwiLFxuICAgIGRhdGU6IFwiJWQvJW0vJVlcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wiQU1cIiwgXCJQTVwiXSxcbiAgICBkYXlzOiBbXCJEb21pbmdvXCIsIFwiU2VndW5kYVwiLCBcIlRlcsOnYVwiLCBcIlF1YXJ0YVwiLCBcIlF1aW50YVwiLCBcIlNleHRhXCIsIFwiU8OhYmFkb1wiXSxcbiAgICBzaG9ydERheXM6IFtcIkRvbVwiLCBcIlNlZ1wiLCBcIlRlclwiLCBcIlF1YVwiLCBcIlF1aVwiLCBcIlNleFwiLCBcIlPDoWJcIl0sXG4gICAgbW9udGhzOiBbXCJKYW5laXJvXCIsIFwiRmV2ZXJlaXJvXCIsIFwiTWFyw6dvXCIsIFwiQWJyaWxcIiwgXCJNYWlvXCIsIFwiSnVuaG9cIiwgXCJKdWxob1wiLCBcIkFnb3N0b1wiLCBcIlNldGVtYnJvXCIsIFwiT3V0dWJyb1wiLCBcIk5vdmVtYnJvXCIsIFwiRGV6ZW1icm9cIl0sXG4gICAgc2hvcnRNb250aHM6IFtcIkphblwiLCBcIkZldlwiLCBcIk1hclwiLCBcIkFiclwiLCBcIk1haVwiLCBcIkp1blwiLCBcIkp1bFwiLCBcIkFnb1wiLCBcIlNldFwiLCBcIk91dFwiLCBcIk5vdlwiLCBcIkRlelwiXVxuICB9O1xuXG4gIHZhciBwbFBsID0ge1xuICAgIGRhdGVUaW1lOiBcIiVBLCAlZSAlQiAlWSwgJVhcIixcbiAgICBkYXRlOiBcIiVkLyVtLyVZXCIsXG4gICAgdGltZTogXCIlSDolTTolU1wiLFxuICAgIHBlcmlvZHM6IFtcIkFNXCIsIFwiUE1cIl0sIC8vIHVudXNlZFxuICAgIGRheXM6IFtcIk5pZWR6aWVsYVwiLCBcIlBvbmllZHppYcWCZWtcIiwgXCJXdG9yZWtcIiwgXCLFmnJvZGFcIiwgXCJDendhcnRla1wiLCBcIlBpxIV0ZWtcIiwgXCJTb2JvdGFcIl0sXG4gICAgc2hvcnREYXlzOiBbXCJOaWVkei5cIiwgXCJQb24uXCIsIFwiV3QuXCIsIFwixZpyLlwiLCBcIkN6dy5cIiwgXCJQdC5cIiwgXCJTb2IuXCJdLFxuICAgIG1vbnRoczogW1wiU3R5Y3plxYRcIiwgXCJMdXR5XCIsIFwiTWFyemVjXCIsIFwiS3dpZWNpZcWEXCIsIFwiTWFqXCIsIFwiQ3plcndpZWNcIiwgXCJMaXBpZWNcIiwgXCJTaWVycGllxYRcIiwgXCJXcnplc2llxYRcIiwgXCJQYcW6ZHppZXJuaWtcIiwgXCJMaXN0b3BhZFwiLCBcIkdydWR6aWXFhFwiXSxcbiAgICBzaG9ydE1vbnRoczogW1wiU3R5Y3ouXCIsIFwiTHV0eVwiLCBcIk1hcnouXCIsIFwiS3dpZS5cIiwgXCJNYWpcIiwgXCJDemVydy5cIiwgXCJMaXBjLlwiLCBcIlNpZXJwLlwiLCBcIldyei5cIiwgXCJQYcW6ZHouXCIsIFwiTGlzdG9wLlwiLCBcIkdydWR6LlwiXS8qIEluIFBvbGlzaCBsYW5ndWFnZSBhYmJyYXZpYXRlZCBtb250aHMgYXJlIG5vdCBjb21tb25seSB1c2VkIHNvIHRoZXJlIGlzIGEgZGlzcHV0ZSBhYm91dCB0aGUgcHJvcGVyIGFiYnJhdmlhdGlvbnMuICovXG4gIH07XG5cbiAgdmFyIG5sTmwgPSB7XG4gICAgZGF0ZVRpbWU6IFwiJWEgJWUgJUIgJVkgJVRcIixcbiAgICBkYXRlOiBcIiVkLSVtLSVZXCIsXG4gICAgdGltZTogXCIlSDolTTolU1wiLFxuICAgIHBlcmlvZHM6IFtcIkFNXCIsIFwiUE1cIl0sIC8vIHVudXNlZFxuICAgIGRheXM6IFtcInpvbmRhZ1wiLCBcIm1hYW5kYWdcIiwgXCJkaW5zZGFnXCIsIFwid29lbnNkYWdcIiwgXCJkb25kZXJkYWdcIiwgXCJ2cmlqZGFnXCIsIFwiemF0ZXJkYWdcIl0sXG4gICAgc2hvcnREYXlzOiBbXCJ6b1wiLCBcIm1hXCIsIFwiZGlcIiwgXCJ3b1wiLCBcImRvXCIsIFwidnJcIiwgXCJ6YVwiXSxcbiAgICBtb250aHM6IFtcImphbnVhcmlcIiwgXCJmZWJydWFyaVwiLCBcIm1hYXJ0XCIsIFwiYXByaWxcIiwgXCJtZWlcIiwgXCJqdW5pXCIsIFwianVsaVwiLCBcImF1Z3VzdHVzXCIsIFwic2VwdGVtYmVyXCIsIFwib2t0b2JlclwiLCBcIm5vdmVtYmVyXCIsIFwiZGVjZW1iZXJcIl0sXG4gICAgc2hvcnRNb250aHM6IFtcImphblwiLCBcImZlYlwiLCBcIm1ydFwiLCBcImFwclwiLCBcIm1laVwiLCBcImp1blwiLCBcImp1bFwiLCBcImF1Z1wiLCBcInNlcFwiLCBcIm9rdFwiLCBcIm5vdlwiLCBcImRlY1wiXVxuICB9O1xuXG4gIHZhciBta01rID0ge1xuICAgIGRhdGVUaW1lOiBcIiVBLCAlZSAlQiAlWSDQsy4gJVhcIixcbiAgICBkYXRlOiBcIiVkLiVtLiVZXCIsXG4gICAgdGltZTogXCIlSDolTTolU1wiLFxuICAgIHBlcmlvZHM6IFtcIkFNXCIsIFwiUE1cIl0sXG4gICAgZGF5czogW1wi0L3QtdC00LXQu9CwXCIsIFwi0L/QvtC90LXQtNC10LvQvdC40LpcIiwgXCLQstGC0L7RgNC90LjQulwiLCBcItGB0YDQtdC00LBcIiwgXCLRh9C10YLQstGA0YLQvtC6XCIsIFwi0L/QtdGC0L7QulwiLCBcItGB0LDQsdC+0YLQsFwiXSxcbiAgICBzaG9ydERheXM6IFtcItC90LXQtFwiLCBcItC/0L7QvVwiLCBcItCy0YLQvlwiLCBcItGB0YDQtVwiLCBcItGH0LXRglwiLCBcItC/0LXRglwiLCBcItGB0LDQsVwiXSxcbiAgICBtb250aHM6IFtcItGY0LDQvdGD0LDRgNC4XCIsIFwi0YTQtdCy0YDRg9Cw0YDQuFwiLCBcItC80LDRgNGCXCIsIFwi0LDQv9GA0LjQu1wiLCBcItC80LDRmFwiLCBcItGY0YPQvdC4XCIsIFwi0ZjRg9C70LhcIiwgXCLQsNCy0LPRg9GB0YJcIiwgXCLRgdC10L/RgtC10LzQstGA0LhcIiwgXCLQvtC60YLQvtC80LLRgNC4XCIsIFwi0L3QvtC10LzQstGA0LhcIiwgXCLQtNC10LrQtdC80LLRgNC4XCJdLFxuICAgIHNob3J0TW9udGhzOiBbXCLRmNCw0L1cIiwgXCLRhNC10LJcIiwgXCLQvNCw0YBcIiwgXCLQsNC/0YBcIiwgXCLQvNCw0ZhcIiwgXCLRmNGD0L1cIiwgXCLRmNGD0LtcIiwgXCLQsNCy0LNcIiwgXCLRgdC10L9cIiwgXCLQvtC60YJcIiwgXCLQvdC+0LVcIiwgXCLQtNC10LpcIl1cbiAgfTtcblxuICB2YXIgaXRJdCA9IHtcbiAgICBkYXRlVGltZTogXCIlQSAlZSAlQiAlWSwgJVhcIixcbiAgICBkYXRlOiBcIiVkLyVtLyVZXCIsXG4gICAgdGltZTogXCIlSDolTTolU1wiLFxuICAgIHBlcmlvZHM6IFtcIkFNXCIsIFwiUE1cIl0sIC8vIHVudXNlZFxuICAgIGRheXM6IFtcIkRvbWVuaWNhXCIsIFwiTHVuZWTDrFwiLCBcIk1hcnRlZMOsXCIsIFwiTWVyY29sZWTDrFwiLCBcIkdpb3ZlZMOsXCIsIFwiVmVuZXJkw6xcIiwgXCJTYWJhdG9cIl0sXG4gICAgc2hvcnREYXlzOiBbXCJEb21cIiwgXCJMdW5cIiwgXCJNYXJcIiwgXCJNZXJcIiwgXCJHaW9cIiwgXCJWZW5cIiwgXCJTYWJcIl0sXG4gICAgbW9udGhzOiBbXCJHZW5uYWlvXCIsIFwiRmViYnJhaW9cIiwgXCJNYXJ6b1wiLCBcIkFwcmlsZVwiLCBcIk1hZ2dpb1wiLCBcIkdpdWdub1wiLCBcIkx1Z2xpb1wiLCBcIkFnb3N0b1wiLCBcIlNldHRlbWJyZVwiLCBcIk90dG9icmVcIiwgXCJOb3ZlbWJyZVwiLCBcIkRpY2VtYnJlXCJdLFxuICAgIHNob3J0TW9udGhzOiBbXCJHZW5cIiwgXCJGZWJcIiwgXCJNYXJcIiwgXCJBcHJcIiwgXCJNYWdcIiwgXCJHaXVcIiwgXCJMdWdcIiwgXCJBZ29cIiwgXCJTZXRcIiwgXCJPdHRcIiwgXCJOb3ZcIiwgXCJEaWNcIl1cbiAgfTtcblxuICB2YXIgaGVJbCA9IHtcbiAgICBkYXRlVGltZTogXCIlQSwgJWUg15ElQiAlWSAlWFwiLFxuICAgIGRhdGU6IFwiJWQuJW0uJVlcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wiQU1cIiwgXCJQTVwiXSxcbiAgICBkYXlzOiBbXCLXqNeQ16nXldefXCIsIFwi16nXoNeZXCIsIFwi16nXnNeZ16nXmVwiLCBcIteo15HXmdei15lcIiwgXCLXl9ee15nXqdeZXCIsIFwi16nXmdep15lcIiwgXCLXqdeR16pcIl0sXG4gICAgc2hvcnREYXlzOiBbXCLXkNezXCIsIFwi15HXs1wiLCBcIteS17NcIiwgXCLXk9ezXCIsIFwi15TXs1wiLCBcIteV17NcIiwgXCLXqdezXCJdLFxuICAgIG1vbnRoczogW1wi15nXoNeV15DXqFwiLCBcItek15HXqNeV15DXqFwiLCBcItee16jXpVwiLCBcIteQ16TXqNeZ15xcIiwgXCLXnteQ15lcIiwgXCLXmdeV16DXmVwiLCBcIteZ15XXnNeZXCIsIFwi15DXldeS15XXodeYXCIsIFwi16HXpNeY157XkdeoXCIsIFwi15DXlden15jXldeR16hcIiwgXCLXoNeV15HXnteR16hcIiwgXCLXk9em157XkdeoXCJdLFxuICAgIHNob3J0TW9udGhzOiBbXCLXmdeg15XXs1wiLCBcItek15HXqNezXCIsIFwi157XqNelXCIsIFwi15DXpNeo17NcIiwgXCLXnteQ15lcIiwgXCLXmdeV16DXmVwiLCBcIteZ15XXnNeZXCIsIFwi15DXldeS17NcIiwgXCLXodek15jXs1wiLCBcIteQ15XXp9ezXCIsIFwi16DXldeR17NcIiwgXCLXk9em157Xs1wiXVxuICB9O1xuXG4gIHZhciBmckZyID0ge1xuICAgIGRhdGVUaW1lOiBcIiVBLCBsZSAlZSAlQiAlWSwgJVhcIixcbiAgICBkYXRlOiBcIiVkLyVtLyVZXCIsXG4gICAgdGltZTogXCIlSDolTTolU1wiLFxuICAgIHBlcmlvZHM6IFtcIkFNXCIsIFwiUE1cIl0sIC8vIHVudXNlZFxuICAgIGRheXM6IFtcImRpbWFuY2hlXCIsIFwibHVuZGlcIiwgXCJtYXJkaVwiLCBcIm1lcmNyZWRpXCIsIFwiamV1ZGlcIiwgXCJ2ZW5kcmVkaVwiLCBcInNhbWVkaVwiXSxcbiAgICBzaG9ydERheXM6IFtcImRpbS5cIiwgXCJsdW4uXCIsIFwibWFyLlwiLCBcIm1lci5cIiwgXCJqZXUuXCIsIFwidmVuLlwiLCBcInNhbS5cIl0sXG4gICAgbW9udGhzOiBbXCJqYW52aWVyXCIsIFwiZsOpdnJpZXJcIiwgXCJtYXJzXCIsIFwiYXZyaWxcIiwgXCJtYWlcIiwgXCJqdWluXCIsIFwianVpbGxldFwiLCBcImFvw7t0XCIsIFwic2VwdGVtYnJlXCIsIFwib2N0b2JyZVwiLCBcIm5vdmVtYnJlXCIsIFwiZMOpY2VtYnJlXCJdLFxuICAgIHNob3J0TW9udGhzOiBbXCJqYW52LlwiLCBcImbDqXZyLlwiLCBcIm1hcnNcIiwgXCJhdnIuXCIsIFwibWFpXCIsIFwianVpblwiLCBcImp1aWwuXCIsIFwiYW/Du3RcIiwgXCJzZXB0LlwiLCBcIm9jdC5cIiwgXCJub3YuXCIsIFwiZMOpYy5cIl1cbiAgfTtcblxuICB2YXIgZnJDYSA9IHtcbiAgICBkYXRlVGltZTogXCIlYSAlZSAlYiAlWSAlWFwiLFxuICAgIGRhdGU6IFwiJVktJW0tJWRcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wiXCIsIFwiXCJdLFxuICAgIGRheXM6IFtcImRpbWFuY2hlXCIsIFwibHVuZGlcIiwgXCJtYXJkaVwiLCBcIm1lcmNyZWRpXCIsIFwiamV1ZGlcIiwgXCJ2ZW5kcmVkaVwiLCBcInNhbWVkaVwiXSxcbiAgICBzaG9ydERheXM6IFtcImRpbVwiLCBcImx1blwiLCBcIm1hclwiLCBcIm1lclwiLCBcImpldVwiLCBcInZlblwiLCBcInNhbVwiXSxcbiAgICBtb250aHM6IFtcImphbnZpZXJcIiwgXCJmw6l2cmllclwiLCBcIm1hcnNcIiwgXCJhdnJpbFwiLCBcIm1haVwiLCBcImp1aW5cIiwgXCJqdWlsbGV0XCIsIFwiYW/Du3RcIiwgXCJzZXB0ZW1icmVcIiwgXCJvY3RvYnJlXCIsIFwibm92ZW1icmVcIiwgXCJkw6ljZW1icmVcIl0sXG4gICAgc2hvcnRNb250aHM6IFtcImphblwiLCBcImbDqXZcIiwgXCJtYXJcIiwgXCJhdnJcIiwgXCJtYWlcIiwgXCJqdWlcIiwgXCJqdWxcIiwgXCJhb8O7XCIsIFwic2VwXCIsIFwib2N0XCIsIFwibm92XCIsIFwiZMOpY1wiXVxuICB9O1xuXG4gIHZhciBmaUZpID0ge1xuICAgIGRhdGVUaW1lOiBcIiVBLCAlLWQuICVCdGEgJVkga2xvICVYXCIsXG4gICAgZGF0ZTogXCIlLWQuJS1tLiVZXCIsXG4gICAgdGltZTogXCIlSDolTTolU1wiLFxuICAgIHBlcmlvZHM6IFtcImEubS5cIiwgXCJwLm0uXCJdLFxuICAgIGRheXM6IFtcInN1bm51bnRhaVwiLCBcIm1hYW5hbnRhaVwiLCBcInRpaXN0YWlcIiwgXCJrZXNraXZpaWtrb1wiLCBcInRvcnN0YWlcIiwgXCJwZXJqYW50YWlcIiwgXCJsYXVhbnRhaVwiXSxcbiAgICBzaG9ydERheXM6IFtcIlN1XCIsIFwiTWFcIiwgXCJUaVwiLCBcIktlXCIsIFwiVG9cIiwgXCJQZVwiLCBcIkxhXCJdLFxuICAgIG1vbnRoczogW1widGFtbWlrdXVcIiwgXCJoZWxtaWt1dVwiLCBcIm1hYWxpc2t1dVwiLCBcImh1aHRpa3V1XCIsIFwidG91a29rdXVcIiwgXCJrZXPDpGt1dVwiLCBcImhlaW7DpGt1dVwiLCBcImVsb2t1dVwiLCBcInN5eXNrdXVcIiwgXCJsb2tha3V1XCIsIFwibWFycmFza3V1XCIsIFwiam91bHVrdXVcIl0sXG4gICAgc2hvcnRNb250aHM6IFtcIlRhbW1pXCIsIFwiSGVsbWlcIiwgXCJNYWFsaXNcIiwgXCJIdWh0aVwiLCBcIlRvdWtvXCIsIFwiS2Vzw6RcIiwgXCJIZWluw6RcIiwgXCJFbG9cIiwgXCJTeXlzXCIsIFwiTG9rYVwiLCBcIk1hcnJhc1wiLCBcIkpvdWx1XCJdXG4gIH07XG5cbiAgdmFyIGVzRXMgPSB7XG4gICAgZGF0ZVRpbWU6IFwiJUEsICVlIGRlICVCIGRlICVZLCAlWFwiLFxuICAgIGRhdGU6IFwiJWQvJW0vJVlcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wiQU1cIiwgXCJQTVwiXSxcbiAgICBkYXlzOiBbXCJkb21pbmdvXCIsIFwibHVuZXNcIiwgXCJtYXJ0ZXNcIiwgXCJtacOpcmNvbGVzXCIsIFwianVldmVzXCIsIFwidmllcm5lc1wiLCBcInPDoWJhZG9cIl0sXG4gICAgc2hvcnREYXlzOiBbXCJkb21cIiwgXCJsdW5cIiwgXCJtYXJcIiwgXCJtacOpXCIsIFwianVlXCIsIFwidmllXCIsIFwic8OhYlwiXSxcbiAgICBtb250aHM6IFtcImVuZXJvXCIsIFwiZmVicmVyb1wiLCBcIm1hcnpvXCIsIFwiYWJyaWxcIiwgXCJtYXlvXCIsIFwianVuaW9cIiwgXCJqdWxpb1wiLCBcImFnb3N0b1wiLCBcInNlcHRpZW1icmVcIiwgXCJvY3R1YnJlXCIsIFwibm92aWVtYnJlXCIsIFwiZGljaWVtYnJlXCJdLFxuICAgIHNob3J0TW9udGhzOiBbXCJlbmVcIiwgXCJmZWJcIiwgXCJtYXJcIiwgXCJhYnJcIiwgXCJtYXlcIiwgXCJqdW5cIiwgXCJqdWxcIiwgXCJhZ29cIiwgXCJzZXBcIiwgXCJvY3RcIiwgXCJub3ZcIiwgXCJkaWNcIl1cbiAgfTtcblxuICB2YXIgZW5VcyA9IHtcbiAgICBkYXRlVGltZTogXCIlYSAlYiAlZSAlWCAlWVwiLFxuICAgIGRhdGU6IFwiJW0vJWQvJVlcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wiQU1cIiwgXCJQTVwiXSxcbiAgICBkYXlzOiBbXCJTdW5kYXlcIiwgXCJNb25kYXlcIiwgXCJUdWVzZGF5XCIsIFwiV2VkbmVzZGF5XCIsIFwiVGh1cnNkYXlcIiwgXCJGcmlkYXlcIiwgXCJTYXR1cmRheVwiXSxcbiAgICBzaG9ydERheXM6IFtcIlN1blwiLCBcIk1vblwiLCBcIlR1ZVwiLCBcIldlZFwiLCBcIlRodVwiLCBcIkZyaVwiLCBcIlNhdFwiXSxcbiAgICBtb250aHM6IFtcIkphbnVhcnlcIiwgXCJGZWJydWFyeVwiLCBcIk1hcmNoXCIsIFwiQXByaWxcIiwgXCJNYXlcIiwgXCJKdW5lXCIsIFwiSnVseVwiLCBcIkF1Z3VzdFwiLCBcIlNlcHRlbWJlclwiLCBcIk9jdG9iZXJcIiwgXCJOb3ZlbWJlclwiLCBcIkRlY2VtYmVyXCJdLFxuICAgIHNob3J0TW9udGhzOiBbXCJKYW5cIiwgXCJGZWJcIiwgXCJNYXJcIiwgXCJBcHJcIiwgXCJNYXlcIiwgXCJKdW5cIiwgXCJKdWxcIiwgXCJBdWdcIiwgXCJTZXBcIiwgXCJPY3RcIiwgXCJOb3ZcIiwgXCJEZWNcIl1cbiAgfTtcblxuICB2YXIgZW5HYiA9IHtcbiAgICBkYXRlVGltZTogXCIlYSAlZSAlYiAlWCAlWVwiLFxuICAgIGRhdGU6IFwiJWQvJW0vJVlcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wiQU1cIiwgXCJQTVwiXSxcbiAgICBkYXlzOiBbXCJTdW5kYXlcIiwgXCJNb25kYXlcIiwgXCJUdWVzZGF5XCIsIFwiV2VkbmVzZGF5XCIsIFwiVGh1cnNkYXlcIiwgXCJGcmlkYXlcIiwgXCJTYXR1cmRheVwiXSxcbiAgICBzaG9ydERheXM6IFtcIlN1blwiLCBcIk1vblwiLCBcIlR1ZVwiLCBcIldlZFwiLCBcIlRodVwiLCBcIkZyaVwiLCBcIlNhdFwiXSxcbiAgICBtb250aHM6IFtcIkphbnVhcnlcIiwgXCJGZWJydWFyeVwiLCBcIk1hcmNoXCIsIFwiQXByaWxcIiwgXCJNYXlcIiwgXCJKdW5lXCIsIFwiSnVseVwiLCBcIkF1Z3VzdFwiLCBcIlNlcHRlbWJlclwiLCBcIk9jdG9iZXJcIiwgXCJOb3ZlbWJlclwiLCBcIkRlY2VtYmVyXCJdLFxuICAgIHNob3J0TW9udGhzOiBbXCJKYW5cIiwgXCJGZWJcIiwgXCJNYXJcIiwgXCJBcHJcIiwgXCJNYXlcIiwgXCJKdW5cIiwgXCJKdWxcIiwgXCJBdWdcIiwgXCJTZXBcIiwgXCJPY3RcIiwgXCJOb3ZcIiwgXCJEZWNcIl1cbiAgfTtcblxuICB2YXIgZW5DYSA9IHtcbiAgICBkYXRlVGltZTogXCIlYSAlYiAlZSAlWCAlWVwiLFxuICAgIGRhdGU6IFwiJVktJW0tJWRcIixcbiAgICB0aW1lOiBcIiVIOiVNOiVTXCIsXG4gICAgcGVyaW9kczogW1wiQU1cIiwgXCJQTVwiXSxcbiAgICBkYXlzOiBbXCJTdW5kYXlcIiwgXCJNb25kYXlcIiwgXCJUdWVzZGF5XCIsIFwiV2VkbmVzZGF5XCIsIFwiVGh1cnNkYXlcIiwgXCJGcmlkYXlcIiwgXCJTYXR1cmRheVwiXSxcbiAgICBzaG9ydERheXM6IFtcIlN1blwiLCBcIk1vblwiLCBcIlR1ZVwiLCBcIldlZFwiLCBcIlRodVwiLCBcIkZyaVwiLCBcIlNhdFwiXSxcbiAgICBtb250aHM6IFtcIkphbnVhcnlcIiwgXCJGZWJydWFyeVwiLCBcIk1hcmNoXCIsIFwiQXByaWxcIiwgXCJNYXlcIiwgXCJKdW5lXCIsIFwiSnVseVwiLCBcIkF1Z3VzdFwiLCBcIlNlcHRlbWJlclwiLCBcIk9jdG9iZXJcIiwgXCJOb3ZlbWJlclwiLCBcIkRlY2VtYmVyXCJdLFxuICAgIHNob3J0TW9udGhzOiBbXCJKYW5cIiwgXCJGZWJcIiwgXCJNYXJcIiwgXCJBcHJcIiwgXCJNYXlcIiwgXCJKdW5cIiwgXCJKdWxcIiwgXCJBdWdcIiwgXCJTZXBcIiwgXCJPY3RcIiwgXCJOb3ZcIiwgXCJEZWNcIl1cbiAgfTtcblxuICB2YXIgZGVEZSA9IHtcbiAgICBkYXRlVGltZTogXCIlQSwgZGVyICVlLiAlQiAlWSwgJVhcIixcbiAgICBkYXRlOiBcIiVkLiVtLiVZXCIsXG4gICAgdGltZTogXCIlSDolTTolU1wiLFxuICAgIHBlcmlvZHM6IFtcIkFNXCIsIFwiUE1cIl0sIC8vIHVudXNlZFxuICAgIGRheXM6IFtcIlNvbm50YWdcIiwgXCJNb250YWdcIiwgXCJEaWVuc3RhZ1wiLCBcIk1pdHR3b2NoXCIsIFwiRG9ubmVyc3RhZ1wiLCBcIkZyZWl0YWdcIiwgXCJTYW1zdGFnXCJdLFxuICAgIHNob3J0RGF5czogW1wiU29cIiwgXCJNb1wiLCBcIkRpXCIsIFwiTWlcIiwgXCJEb1wiLCBcIkZyXCIsIFwiU2FcIl0sXG4gICAgbW9udGhzOiBbXCJKYW51YXJcIiwgXCJGZWJydWFyXCIsIFwiTcOkcnpcIiwgXCJBcHJpbFwiLCBcIk1haVwiLCBcIkp1bmlcIiwgXCJKdWxpXCIsIFwiQXVndXN0XCIsIFwiU2VwdGVtYmVyXCIsIFwiT2t0b2JlclwiLCBcIk5vdmVtYmVyXCIsIFwiRGV6ZW1iZXJcIl0sXG4gICAgc2hvcnRNb250aHM6IFtcIkphblwiLCBcIkZlYlwiLCBcIk1yelwiLCBcIkFwclwiLCBcIk1haVwiLCBcIkp1blwiLCBcIkp1bFwiLCBcIkF1Z1wiLCBcIlNlcFwiLCBcIk9rdFwiLCBcIk5vdlwiLCBcIkRlelwiXVxuICB9O1xuXG4gIHZhciBjYUVzID0ge1xuICAgIGRhdGVUaW1lOiBcIiVBLCAlZSBkZSAlQiBkZSAlWSwgJVhcIixcbiAgICBkYXRlOiBcIiVkLyVtLyVZXCIsXG4gICAgdGltZTogXCIlSDolTTolU1wiLFxuICAgIHBlcmlvZHM6IFtcIkFNXCIsIFwiUE1cIl0sXG4gICAgZGF5czogW1wiZGl1bWVuZ2VcIiwgXCJkaWxsdW5zXCIsIFwiZGltYXJ0c1wiLCBcImRpbWVjcmVzXCIsIFwiZGlqb3VzXCIsIFwiZGl2ZW5kcmVzXCIsIFwiZGlzc2FidGVcIl0sXG4gICAgc2hvcnREYXlzOiBbXCJkZy5cIiwgXCJkbC5cIiwgXCJkdC5cIiwgXCJkYy5cIiwgXCJkai5cIiwgXCJkdi5cIiwgXCJkcy5cIl0sXG4gICAgbW9udGhzOiBbXCJnZW5lclwiLCBcImZlYnJlclwiLCBcIm1hcsOnXCIsIFwiYWJyaWxcIiwgXCJtYWlnXCIsIFwianVueVwiLCBcImp1bGlvbFwiLCBcImFnb3N0XCIsIFwic2V0ZW1icmVcIiwgXCJvY3R1YnJlXCIsIFwibm92ZW1icmVcIiwgXCJkZXNlbWJyZVwiXSxcbiAgICBzaG9ydE1vbnRoczogW1wiZ2VuLlwiLCBcImZlYnIuXCIsIFwibWFyw6dcIiwgXCJhYnIuXCIsIFwibWFpZ1wiLCBcImp1bnlcIiwgXCJqdWwuXCIsIFwiYWcuXCIsIFwic2V0LlwiLCBcIm9jdC5cIiwgXCJub3YuXCIsIFwiZGVzLlwiXVxuICB9O1xuXG4gIHZhciB0MCA9IG5ldyBEYXRlO1xuICB2YXIgdDEgPSBuZXcgRGF0ZTtcblxuICBmdW5jdGlvbiBuZXdJbnRlcnZhbChmbG9vcmksIG9mZnNldGksIGNvdW50KSB7XG5cbiAgICBmdW5jdGlvbiBpbnRlcnZhbChkYXRlKSB7XG4gICAgICByZXR1cm4gZmxvb3JpKGRhdGUgPSBuZXcgRGF0ZSgrZGF0ZSkpLCBkYXRlO1xuICAgIH1cblxuICAgIGludGVydmFsLmZsb29yID0gaW50ZXJ2YWw7XG5cbiAgICBpbnRlcnZhbC5yb3VuZCA9IGZ1bmN0aW9uKGRhdGUpIHtcbiAgICAgIHZhciBkMCA9IG5ldyBEYXRlKCtkYXRlKSxcbiAgICAgICAgICBkMSA9IG5ldyBEYXRlKGRhdGUgLSAxKTtcbiAgICAgIGZsb29yaShkMCksIGZsb29yaShkMSksIG9mZnNldGkoZDEsIDEpO1xuICAgICAgcmV0dXJuIGRhdGUgLSBkMCA8IGQxIC0gZGF0ZSA/IGQwIDogZDE7XG4gICAgfTtcblxuICAgIGludGVydmFsLmNlaWwgPSBmdW5jdGlvbihkYXRlKSB7XG4gICAgICByZXR1cm4gZmxvb3JpKGRhdGUgPSBuZXcgRGF0ZShkYXRlIC0gMSkpLCBvZmZzZXRpKGRhdGUsIDEpLCBkYXRlO1xuICAgIH07XG5cbiAgICBpbnRlcnZhbC5vZmZzZXQgPSBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgICByZXR1cm4gb2Zmc2V0aShkYXRlID0gbmV3IERhdGUoK2RhdGUpLCBzdGVwID09IG51bGwgPyAxIDogTWF0aC5mbG9vcihzdGVwKSksIGRhdGU7XG4gICAgfTtcblxuICAgIGludGVydmFsLnJhbmdlID0gZnVuY3Rpb24oc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgICAgIHZhciByYW5nZSA9IFtdO1xuICAgICAgc3RhcnQgPSBuZXcgRGF0ZShzdGFydCAtIDEpO1xuICAgICAgc3RvcCA9IG5ldyBEYXRlKCtzdG9wKTtcbiAgICAgIHN0ZXAgPSBzdGVwID09IG51bGwgPyAxIDogTWF0aC5mbG9vcihzdGVwKTtcbiAgICAgIGlmICghKHN0YXJ0IDwgc3RvcCkgfHwgIShzdGVwID4gMCkpIHJldHVybiByYW5nZTsgLy8gYWxzbyBoYW5kbGVzIEludmFsaWQgRGF0ZVxuICAgICAgb2Zmc2V0aShzdGFydCwgMSksIGZsb29yaShzdGFydCk7XG4gICAgICBpZiAoc3RhcnQgPCBzdG9wKSByYW5nZS5wdXNoKG5ldyBEYXRlKCtzdGFydCkpO1xuICAgICAgd2hpbGUgKG9mZnNldGkoc3RhcnQsIHN0ZXApLCBmbG9vcmkoc3RhcnQpLCBzdGFydCA8IHN0b3ApIHJhbmdlLnB1c2gobmV3IERhdGUoK3N0YXJ0KSk7XG4gICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfTtcblxuICAgIGludGVydmFsLmZpbHRlciA9IGZ1bmN0aW9uKHRlc3QpIHtcbiAgICAgIHJldHVybiBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgIHdoaWxlIChmbG9vcmkoZGF0ZSksICF0ZXN0KGRhdGUpKSBkYXRlLnNldFRpbWUoZGF0ZSAtIDEpO1xuICAgICAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgICAgICB3aGlsZSAoLS1zdGVwID49IDApIHdoaWxlIChvZmZzZXRpKGRhdGUsIDEpLCAhdGVzdChkYXRlKSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgaWYgKGNvdW50KSBpbnRlcnZhbC5jb3VudCA9IGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICAgIHQwLnNldFRpbWUoK3N0YXJ0KSwgdDEuc2V0VGltZSgrZW5kKTtcbiAgICAgIGZsb29yaSh0MCksIGZsb29yaSh0MSk7XG4gICAgICByZXR1cm4gTWF0aC5mbG9vcihjb3VudCh0MCwgdDEpKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGludGVydmFsO1xuICB9XG5cbiAgdmFyIGRheSA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpICsgc3RlcCk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gKGVuZCAtIHN0YXJ0IC0gKGVuZC5nZXRUaW1lem9uZU9mZnNldCgpIC0gc3RhcnQuZ2V0VGltZXpvbmVPZmZzZXQoKSkgKiA2ZTQpIC8gODY0ZTU7XG4gIH0pO1xuXG4gIGZ1bmN0aW9uIHdlZWtkYXkoaSkge1xuICAgIHJldHVybiBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgICBkYXRlLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICAgICAgZGF0ZS5zZXREYXRlKGRhdGUuZ2V0RGF0ZSgpIC0gKGRhdGUuZ2V0RGF5KCkgKyA3IC0gaSkgJSA3KTtcbiAgICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgICBkYXRlLnNldERhdGUoZGF0ZS5nZXREYXRlKCkgKyBzdGVwICogNyk7XG4gICAgfSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgICAgcmV0dXJuIChlbmQgLSBzdGFydCAtIChlbmQuZ2V0VGltZXpvbmVPZmZzZXQoKSAtIHN0YXJ0LmdldFRpbWV6b25lT2Zmc2V0KCkpICogNmU0KSAvIDYwNDhlNTtcbiAgICB9KTtcbiAgfVxuXG4gIHZhciBzdW5kYXkgPSB3ZWVrZGF5KDApO1xuICB2YXIgbW9uZGF5ID0gd2Vla2RheSgxKTtcblxuICB2YXIgeWVhciA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldEhvdXJzKDAsIDAsIDAsIDApO1xuICAgIGRhdGUuc2V0TW9udGgoMCwgMSk7XG4gIH0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgICBkYXRlLnNldEZ1bGxZZWFyKGRhdGUuZ2V0RnVsbFllYXIoKSArIHN0ZXApO1xuICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgcmV0dXJuIGVuZC5nZXRGdWxsWWVhcigpIC0gc3RhcnQuZ2V0RnVsbFllYXIoKTtcbiAgfSk7XG5cbiAgdmFyIHV0Y0RheSA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldFVUQ0hvdXJzKDAsIDAsIDAsIDApO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXRVVENEYXRlKGRhdGUuZ2V0VVRDRGF0ZSgpICsgc3RlcCk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIDg2NGU1O1xuICB9KTtcblxuICBmdW5jdGlvbiB1dGNXZWVrZGF5KGkpIHtcbiAgICByZXR1cm4gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgICAgZGF0ZS5zZXRVVENIb3VycygwLCAwLCAwLCAwKTtcbiAgICAgIGRhdGUuc2V0VVRDRGF0ZShkYXRlLmdldFVUQ0RhdGUoKSAtIChkYXRlLmdldFVUQ0RheSgpICsgNyAtIGkpICUgNyk7XG4gICAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgICAgZGF0ZS5zZXRVVENEYXRlKGRhdGUuZ2V0VVRDRGF0ZSgpICsgc3RlcCAqIDcpO1xuICAgIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICAgIHJldHVybiAoZW5kIC0gc3RhcnQpIC8gNjA0OGU1O1xuICAgIH0pO1xuICB9XG5cbiAgdmFyIHV0Y1N1bmRheSA9IHV0Y1dlZWtkYXkoMCk7XG4gIHZhciB1dGNNb25kYXkgPSB1dGNXZWVrZGF5KDEpO1xuXG4gIHZhciB1dGNZZWFyID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIGRhdGUuc2V0VVRDSG91cnMoMCwgMCwgMCwgMCk7XG4gICAgZGF0ZS5zZXRVVENNb250aCgwLCAxKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgIGRhdGUuc2V0VVRDRnVsbFllYXIoZGF0ZS5nZXRVVENGdWxsWWVhcigpICsgc3RlcCk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gZW5kLmdldFVUQ0Z1bGxZZWFyKCkgLSBzdGFydC5nZXRVVENGdWxsWWVhcigpO1xuICB9KTtcblxuICBmdW5jdGlvbiBsb2NhbERhdGUoZCkge1xuICAgIGlmICgwIDw9IGQueSAmJiBkLnkgPCAxMDApIHtcbiAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoLTEsIGQubSwgZC5kLCBkLkgsIGQuTSwgZC5TLCBkLkwpO1xuICAgICAgZGF0ZS5zZXRGdWxsWWVhcihkLnkpO1xuICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfVxuICAgIHJldHVybiBuZXcgRGF0ZShkLnksIGQubSwgZC5kLCBkLkgsIGQuTSwgZC5TLCBkLkwpO1xuICB9XG5cbiAgZnVuY3Rpb24gdXRjRGF0ZShkKSB7XG4gICAgaWYgKDAgPD0gZC55ICYmIGQueSA8IDEwMCkge1xuICAgICAgdmFyIGRhdGUgPSBuZXcgRGF0ZShEYXRlLlVUQygtMSwgZC5tLCBkLmQsIGQuSCwgZC5NLCBkLlMsIGQuTCkpO1xuICAgICAgZGF0ZS5zZXRVVENGdWxsWWVhcihkLnkpO1xuICAgICAgcmV0dXJuIGRhdGU7XG4gICAgfVxuICAgIHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQyhkLnksIGQubSwgZC5kLCBkLkgsIGQuTSwgZC5TLCBkLkwpKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIG5ld1llYXIoeSkge1xuICAgIHJldHVybiB7eTogeSwgbTogMCwgZDogMSwgSDogMCwgTTogMCwgUzogMCwgTDogMH07XG4gIH1cblxuICBmdW5jdGlvbiBsb2NhbGUobG9jYWxlKSB7XG4gICAgdmFyIGxvY2FsZV9kYXRlVGltZSA9IGxvY2FsZS5kYXRlVGltZSxcbiAgICAgICAgbG9jYWxlX2RhdGUgPSBsb2NhbGUuZGF0ZSxcbiAgICAgICAgbG9jYWxlX3RpbWUgPSBsb2NhbGUudGltZSxcbiAgICAgICAgbG9jYWxlX3BlcmlvZHMgPSBsb2NhbGUucGVyaW9kcyxcbiAgICAgICAgbG9jYWxlX3dlZWtkYXlzID0gbG9jYWxlLmRheXMsXG4gICAgICAgIGxvY2FsZV9zaG9ydFdlZWtkYXlzID0gbG9jYWxlLnNob3J0RGF5cyxcbiAgICAgICAgbG9jYWxlX21vbnRocyA9IGxvY2FsZS5tb250aHMsXG4gICAgICAgIGxvY2FsZV9zaG9ydE1vbnRocyA9IGxvY2FsZS5zaG9ydE1vbnRocztcblxuICAgIHZhciBwZXJpb2RMb29rdXAgPSBmb3JtYXRMb29rdXAobG9jYWxlX3BlcmlvZHMpLFxuICAgICAgICB3ZWVrZGF5UmUgPSBmb3JtYXRSZShsb2NhbGVfd2Vla2RheXMpLFxuICAgICAgICB3ZWVrZGF5TG9va3VwID0gZm9ybWF0TG9va3VwKGxvY2FsZV93ZWVrZGF5cyksXG4gICAgICAgIHNob3J0V2Vla2RheVJlID0gZm9ybWF0UmUobG9jYWxlX3Nob3J0V2Vla2RheXMpLFxuICAgICAgICBzaG9ydFdlZWtkYXlMb29rdXAgPSBmb3JtYXRMb29rdXAobG9jYWxlX3Nob3J0V2Vla2RheXMpLFxuICAgICAgICBtb250aFJlID0gZm9ybWF0UmUobG9jYWxlX21vbnRocyksXG4gICAgICAgIG1vbnRoTG9va3VwID0gZm9ybWF0TG9va3VwKGxvY2FsZV9tb250aHMpLFxuICAgICAgICBzaG9ydE1vbnRoUmUgPSBmb3JtYXRSZShsb2NhbGVfc2hvcnRNb250aHMpLFxuICAgICAgICBzaG9ydE1vbnRoTG9va3VwID0gZm9ybWF0TG9va3VwKGxvY2FsZV9zaG9ydE1vbnRocyk7XG5cbiAgICB2YXIgZm9ybWF0cyA9IHtcbiAgICAgIFwiYVwiOiBmb3JtYXRTaG9ydFdlZWtkYXksXG4gICAgICBcIkFcIjogZm9ybWF0V2Vla2RheSxcbiAgICAgIFwiYlwiOiBmb3JtYXRTaG9ydE1vbnRoLFxuICAgICAgXCJCXCI6IGZvcm1hdE1vbnRoLFxuICAgICAgXCJjXCI6IG51bGwsXG4gICAgICBcImRcIjogZm9ybWF0RGF5T2ZNb250aCxcbiAgICAgIFwiZVwiOiBmb3JtYXREYXlPZk1vbnRoLFxuICAgICAgXCJIXCI6IGZvcm1hdEhvdXIyNCxcbiAgICAgIFwiSVwiOiBmb3JtYXRIb3VyMTIsXG4gICAgICBcImpcIjogZm9ybWF0RGF5T2ZZZWFyLFxuICAgICAgXCJMXCI6IGZvcm1hdE1pbGxpc2Vjb25kcyxcbiAgICAgIFwibVwiOiBmb3JtYXRNb250aE51bWJlcixcbiAgICAgIFwiTVwiOiBmb3JtYXRNaW51dGVzLFxuICAgICAgXCJwXCI6IGZvcm1hdFBlcmlvZCxcbiAgICAgIFwiU1wiOiBmb3JtYXRTZWNvbmRzLFxuICAgICAgXCJVXCI6IGZvcm1hdFdlZWtOdW1iZXJTdW5kYXksXG4gICAgICBcIndcIjogZm9ybWF0V2Vla2RheU51bWJlcixcbiAgICAgIFwiV1wiOiBmb3JtYXRXZWVrTnVtYmVyTW9uZGF5LFxuICAgICAgXCJ4XCI6IG51bGwsXG4gICAgICBcIlhcIjogbnVsbCxcbiAgICAgIFwieVwiOiBmb3JtYXRZZWFyLFxuICAgICAgXCJZXCI6IGZvcm1hdEZ1bGxZZWFyLFxuICAgICAgXCJaXCI6IGZvcm1hdFpvbmUsXG4gICAgICBcIiVcIjogZm9ybWF0TGl0ZXJhbFBlcmNlbnRcbiAgICB9O1xuXG4gICAgdmFyIHV0Y0Zvcm1hdHMgPSB7XG4gICAgICBcImFcIjogZm9ybWF0VVRDU2hvcnRXZWVrZGF5LFxuICAgICAgXCJBXCI6IGZvcm1hdFVUQ1dlZWtkYXksXG4gICAgICBcImJcIjogZm9ybWF0VVRDU2hvcnRNb250aCxcbiAgICAgIFwiQlwiOiBmb3JtYXRVVENNb250aCxcbiAgICAgIFwiY1wiOiBudWxsLFxuICAgICAgXCJkXCI6IGZvcm1hdFVUQ0RheU9mTW9udGgsXG4gICAgICBcImVcIjogZm9ybWF0VVRDRGF5T2ZNb250aCxcbiAgICAgIFwiSFwiOiBmb3JtYXRVVENIb3VyMjQsXG4gICAgICBcIklcIjogZm9ybWF0VVRDSG91cjEyLFxuICAgICAgXCJqXCI6IGZvcm1hdFVUQ0RheU9mWWVhcixcbiAgICAgIFwiTFwiOiBmb3JtYXRVVENNaWxsaXNlY29uZHMsXG4gICAgICBcIm1cIjogZm9ybWF0VVRDTW9udGhOdW1iZXIsXG4gICAgICBcIk1cIjogZm9ybWF0VVRDTWludXRlcyxcbiAgICAgIFwicFwiOiBmb3JtYXRVVENQZXJpb2QsXG4gICAgICBcIlNcIjogZm9ybWF0VVRDU2Vjb25kcyxcbiAgICAgIFwiVVwiOiBmb3JtYXRVVENXZWVrTnVtYmVyU3VuZGF5LFxuICAgICAgXCJ3XCI6IGZvcm1hdFVUQ1dlZWtkYXlOdW1iZXIsXG4gICAgICBcIldcIjogZm9ybWF0VVRDV2Vla051bWJlck1vbmRheSxcbiAgICAgIFwieFwiOiBudWxsLFxuICAgICAgXCJYXCI6IG51bGwsXG4gICAgICBcInlcIjogZm9ybWF0VVRDWWVhcixcbiAgICAgIFwiWVwiOiBmb3JtYXRVVENGdWxsWWVhcixcbiAgICAgIFwiWlwiOiBmb3JtYXRVVENab25lLFxuICAgICAgXCIlXCI6IGZvcm1hdExpdGVyYWxQZXJjZW50XG4gICAgfTtcblxuICAgIHZhciBwYXJzZXMgPSB7XG4gICAgICBcImFcIjogcGFyc2VTaG9ydFdlZWtkYXksXG4gICAgICBcIkFcIjogcGFyc2VXZWVrZGF5LFxuICAgICAgXCJiXCI6IHBhcnNlU2hvcnRNb250aCxcbiAgICAgIFwiQlwiOiBwYXJzZU1vbnRoLFxuICAgICAgXCJjXCI6IHBhcnNlTG9jYWxlRGF0ZVRpbWUsXG4gICAgICBcImRcIjogcGFyc2VEYXlPZk1vbnRoLFxuICAgICAgXCJlXCI6IHBhcnNlRGF5T2ZNb250aCxcbiAgICAgIFwiSFwiOiBwYXJzZUhvdXIyNCxcbiAgICAgIFwiSVwiOiBwYXJzZUhvdXIyNCxcbiAgICAgIFwialwiOiBwYXJzZURheU9mWWVhcixcbiAgICAgIFwiTFwiOiBwYXJzZU1pbGxpc2Vjb25kcyxcbiAgICAgIFwibVwiOiBwYXJzZU1vbnRoTnVtYmVyLFxuICAgICAgXCJNXCI6IHBhcnNlTWludXRlcyxcbiAgICAgIFwicFwiOiBwYXJzZVBlcmlvZCxcbiAgICAgIFwiU1wiOiBwYXJzZVNlY29uZHMsXG4gICAgICBcIlVcIjogcGFyc2VXZWVrTnVtYmVyU3VuZGF5LFxuICAgICAgXCJ3XCI6IHBhcnNlV2Vla2RheU51bWJlcixcbiAgICAgIFwiV1wiOiBwYXJzZVdlZWtOdW1iZXJNb25kYXksXG4gICAgICBcInhcIjogcGFyc2VMb2NhbGVEYXRlLFxuICAgICAgXCJYXCI6IHBhcnNlTG9jYWxlVGltZSxcbiAgICAgIFwieVwiOiBwYXJzZVllYXIsXG4gICAgICBcIllcIjogcGFyc2VGdWxsWWVhcixcbiAgICAgIFwiWlwiOiBwYXJzZVpvbmUsXG4gICAgICBcIiVcIjogcGFyc2VMaXRlcmFsUGVyY2VudFxuICAgIH07XG5cbiAgICAvLyBUaGVzZSByZWN1cnNpdmUgZGlyZWN0aXZlIGRlZmluaXRpb25zIG11c3QgYmUgZGVmZXJyZWQuXG4gICAgZm9ybWF0cy54ID0gbmV3Rm9ybWF0KGxvY2FsZV9kYXRlLCBmb3JtYXRzKTtcbiAgICBmb3JtYXRzLlggPSBuZXdGb3JtYXQobG9jYWxlX3RpbWUsIGZvcm1hdHMpO1xuICAgIGZvcm1hdHMuYyA9IG5ld0Zvcm1hdChsb2NhbGVfZGF0ZVRpbWUsIGZvcm1hdHMpO1xuICAgIHV0Y0Zvcm1hdHMueCA9IG5ld0Zvcm1hdChsb2NhbGVfZGF0ZSwgdXRjRm9ybWF0cyk7XG4gICAgdXRjRm9ybWF0cy5YID0gbmV3Rm9ybWF0KGxvY2FsZV90aW1lLCB1dGNGb3JtYXRzKTtcbiAgICB1dGNGb3JtYXRzLmMgPSBuZXdGb3JtYXQobG9jYWxlX2RhdGVUaW1lLCB1dGNGb3JtYXRzKTtcblxuICAgIGZ1bmN0aW9uIG5ld0Zvcm1hdChzcGVjaWZpZXIsIGZvcm1hdHMpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgIHZhciBzdHJpbmcgPSBbXSxcbiAgICAgICAgICAgIGkgPSAtMSxcbiAgICAgICAgICAgIGogPSAwLFxuICAgICAgICAgICAgbiA9IHNwZWNpZmllci5sZW5ndGgsXG4gICAgICAgICAgICBjLFxuICAgICAgICAgICAgcGFkLFxuICAgICAgICAgICAgZm9ybWF0O1xuXG4gICAgICAgIHdoaWxlICgrK2kgPCBuKSB7XG4gICAgICAgICAgaWYgKHNwZWNpZmllci5jaGFyQ29kZUF0KGkpID09PSAzNykge1xuICAgICAgICAgICAgc3RyaW5nLnB1c2goc3BlY2lmaWVyLnNsaWNlKGosIGkpKTtcbiAgICAgICAgICAgIGlmICgocGFkID0gcGFkc1tjID0gc3BlY2lmaWVyLmNoYXJBdCgrK2kpXSkgIT0gbnVsbCkgYyA9IHNwZWNpZmllci5jaGFyQXQoKytpKTtcbiAgICAgICAgICAgIGlmIChmb3JtYXQgPSBmb3JtYXRzW2NdKSBjID0gZm9ybWF0KGRhdGUsIHBhZCA9PSBudWxsID8gKGMgPT09IFwiZVwiID8gXCIgXCIgOiBcIjBcIikgOiBwYWQpO1xuICAgICAgICAgICAgc3RyaW5nLnB1c2goYyk7XG4gICAgICAgICAgICBqID0gaSArIDE7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc3RyaW5nLnB1c2goc3BlY2lmaWVyLnNsaWNlKGosIGkpKTtcbiAgICAgICAgcmV0dXJuIHN0cmluZy5qb2luKFwiXCIpO1xuICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBuZXdQYXJzZShzcGVjaWZpZXIsIG5ld0RhdGUpIHtcbiAgICAgIHJldHVybiBmdW5jdGlvbihzdHJpbmcpIHtcbiAgICAgICAgdmFyIGQgPSBuZXdZZWFyKDE5MDApLFxuICAgICAgICAgICAgaSA9IHBhcnNlU3BlY2lmaWVyKGQsIHNwZWNpZmllciwgc3RyaW5nLCAwKTtcbiAgICAgICAgaWYgKGkgIT0gc3RyaW5nLmxlbmd0aCkgcmV0dXJuIG51bGw7XG5cbiAgICAgICAgLy8gVGhlIGFtLXBtIGZsYWcgaXMgMCBmb3IgQU0sIGFuZCAxIGZvciBQTS5cbiAgICAgICAgaWYgKFwicFwiIGluIGQpIGQuSCA9IGQuSCAlIDEyICsgZC5wICogMTI7XG5cbiAgICAgICAgLy8gSWYgYSB0aW1lIHpvbmUgaXMgc3BlY2lmaWVkLCBhbGwgZmllbGRzIGFyZSBpbnRlcnByZXRlZCBhcyBVVEMgYW5kIHRoZW5cbiAgICAgICAgLy8gb2Zmc2V0IGFjY29yZGluZyB0byB0aGUgc3BlY2lmaWVkIHRpbWUgem9uZS5cbiAgICAgICAgaWYgKFwiWlwiIGluIGQpIHtcbiAgICAgICAgICBpZiAoXCJ3XCIgaW4gZCAmJiAoXCJXXCIgaW4gZCB8fCBcIlVcIiBpbiBkKSkge1xuICAgICAgICAgICAgdmFyIGRheSA9IHV0Y0RhdGUobmV3WWVhcihkLnkpKS5nZXRVVENEYXkoKTtcbiAgICAgICAgICAgIGlmIChcIldcIiBpbiBkKSBkLlUgPSBkLlcsIGQudyA9IChkLncgKyA2KSAlIDcsIC0tZGF5O1xuICAgICAgICAgICAgZC5tID0gMDtcbiAgICAgICAgICAgIGQuZCA9IGQudyArIGQuVSAqIDcgLSAoZGF5ICsgNikgJSA3O1xuICAgICAgICAgIH1cbiAgICAgICAgICBkLkggKz0gZC5aIC8gMTAwIHwgMDtcbiAgICAgICAgICBkLk0gKz0gZC5aICUgMTAwO1xuICAgICAgICAgIHJldHVybiB1dGNEYXRlKGQpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gT3RoZXJ3aXNlLCBhbGwgZmllbGRzIGFyZSBpbiBsb2NhbCB0aW1lLlxuICAgICAgICBpZiAoXCJ3XCIgaW4gZCAmJiAoXCJXXCIgaW4gZCB8fCBcIlVcIiBpbiBkKSkge1xuICAgICAgICAgIHZhciBkYXkgPSBuZXdEYXRlKG5ld1llYXIoZC55KSkuZ2V0RGF5KCk7XG4gICAgICAgICAgaWYgKFwiV1wiIGluIGQpIGQuVSA9IGQuVywgZC53ID0gKGQudyArIDYpICUgNywgLS1kYXk7XG4gICAgICAgICAgZC5tID0gMDtcbiAgICAgICAgICBkLmQgPSBkLncgKyBkLlUgKiA3IC0gKGRheSArIDYpICUgNztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3RGF0ZShkKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VTcGVjaWZpZXIoZCwgc3BlY2lmaWVyLCBzdHJpbmcsIGopIHtcbiAgICAgIHZhciBpID0gMCxcbiAgICAgICAgICBuID0gc3BlY2lmaWVyLmxlbmd0aCxcbiAgICAgICAgICBtID0gc3RyaW5nLmxlbmd0aCxcbiAgICAgICAgICBjLFxuICAgICAgICAgIHBhcnNlO1xuXG4gICAgICB3aGlsZSAoaSA8IG4pIHtcbiAgICAgICAgaWYgKGogPj0gbSkgcmV0dXJuIC0xO1xuICAgICAgICBjID0gc3BlY2lmaWVyLmNoYXJDb2RlQXQoaSsrKTtcbiAgICAgICAgaWYgKGMgPT09IDM3KSB7XG4gICAgICAgICAgYyA9IHNwZWNpZmllci5jaGFyQXQoaSsrKTtcbiAgICAgICAgICBwYXJzZSA9IHBhcnNlc1tjIGluIHBhZHMgPyBzcGVjaWZpZXIuY2hhckF0KGkrKykgOiBjXTtcbiAgICAgICAgICBpZiAoIXBhcnNlIHx8ICgoaiA9IHBhcnNlKGQsIHN0cmluZywgaikpIDwgMCkpIHJldHVybiAtMTtcbiAgICAgICAgfSBlbHNlIGlmIChjICE9IHN0cmluZy5jaGFyQ29kZUF0KGorKykpIHtcbiAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGo7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VTaG9ydFdlZWtkYXkoZCwgc3RyaW5nLCBpKSB7XG4gICAgICB2YXIgbiA9IHNob3J0V2Vla2RheVJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgICAgIHJldHVybiBuID8gKGQudyA9IHNob3J0V2Vla2RheUxvb2t1cC5nZXQoblswXS50b0xvd2VyQ2FzZSgpKSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhcnNlV2Vla2RheShkLCBzdHJpbmcsIGkpIHtcbiAgICAgIHZhciBuID0gd2Vla2RheVJlLmV4ZWMoc3RyaW5nLnNsaWNlKGkpKTtcbiAgICAgIHJldHVybiBuID8gKGQudyA9IHdlZWtkYXlMb29rdXAuZ2V0KG5bMF0udG9Mb3dlckNhc2UoKSksIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzZVNob3J0TW9udGgoZCwgc3RyaW5nLCBpKSB7XG4gICAgICB2YXIgbiA9IHNob3J0TW9udGhSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgICByZXR1cm4gbiA/IChkLm0gPSBzaG9ydE1vbnRoTG9va3VwLmdldChuWzBdLnRvTG93ZXJDYXNlKCkpLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VNb250aChkLCBzdHJpbmcsIGkpIHtcbiAgICAgIHZhciBuID0gbW9udGhSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgICByZXR1cm4gbiA/IChkLm0gPSBtb250aExvb2t1cC5nZXQoblswXS50b0xvd2VyQ2FzZSgpKSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhcnNlTG9jYWxlRGF0ZVRpbWUoZCwgc3RyaW5nLCBpKSB7XG4gICAgICByZXR1cm4gcGFyc2VTcGVjaWZpZXIoZCwgbG9jYWxlX2RhdGVUaW1lLCBzdHJpbmcsIGkpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHBhcnNlTG9jYWxlRGF0ZShkLCBzdHJpbmcsIGkpIHtcbiAgICAgIHJldHVybiBwYXJzZVNwZWNpZmllcihkLCBsb2NhbGVfZGF0ZSwgc3RyaW5nLCBpKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzZUxvY2FsZVRpbWUoZCwgc3RyaW5nLCBpKSB7XG4gICAgICByZXR1cm4gcGFyc2VTcGVjaWZpZXIoZCwgbG9jYWxlX3RpbWUsIHN0cmluZywgaSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcGFyc2VQZXJpb2QoZCwgc3RyaW5nLCBpKSB7XG4gICAgICB2YXIgbiA9IHBlcmlvZExvb2t1cC5nZXQoc3RyaW5nLnNsaWNlKGksIGkgKz0gMikudG9Mb3dlckNhc2UoKSk7XG4gICAgICByZXR1cm4gbiA9PSBudWxsID8gLTEgOiAoZC5wID0gbiwgaSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0U2hvcnRXZWVrZGF5KGQpIHtcbiAgICAgIHJldHVybiBsb2NhbGVfc2hvcnRXZWVrZGF5c1tkLmdldERheSgpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmb3JtYXRXZWVrZGF5KGQpIHtcbiAgICAgIHJldHVybiBsb2NhbGVfd2Vla2RheXNbZC5nZXREYXkoKV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0U2hvcnRNb250aChkKSB7XG4gICAgICByZXR1cm4gbG9jYWxlX3Nob3J0TW9udGhzW2QuZ2V0TW9udGgoKV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0TW9udGgoZCkge1xuICAgICAgcmV0dXJuIGxvY2FsZV9tb250aHNbZC5nZXRNb250aCgpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmb3JtYXRQZXJpb2QoZCkge1xuICAgICAgcmV0dXJuIGxvY2FsZV9wZXJpb2RzWysoZC5nZXRIb3VycygpID49IDEyKV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0VVRDU2hvcnRXZWVrZGF5KGQpIHtcbiAgICAgIHJldHVybiBsb2NhbGVfc2hvcnRXZWVrZGF5c1tkLmdldFVUQ0RheSgpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmb3JtYXRVVENXZWVrZGF5KGQpIHtcbiAgICAgIHJldHVybiBsb2NhbGVfd2Vla2RheXNbZC5nZXRVVENEYXkoKV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0VVRDU2hvcnRNb250aChkKSB7XG4gICAgICByZXR1cm4gbG9jYWxlX3Nob3J0TW9udGhzW2QuZ2V0VVRDTW9udGgoKV07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZm9ybWF0VVRDTW9udGgoZCkge1xuICAgICAgcmV0dXJuIGxvY2FsZV9tb250aHNbZC5nZXRVVENNb250aCgpXTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmb3JtYXRVVENQZXJpb2QoZCkge1xuICAgICAgcmV0dXJuIGxvY2FsZV9wZXJpb2RzWysoZC5nZXRVVENIb3VycygpID49IDEyKV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGZvcm1hdDogZnVuY3Rpb24oc3BlY2lmaWVyKSB7XG4gICAgICAgIHZhciBmID0gbmV3Rm9ybWF0KHNwZWNpZmllciArPSBcIlwiLCBmb3JtYXRzKTtcbiAgICAgICAgZi5wYXJzZSA9IG5ld1BhcnNlKHNwZWNpZmllciwgbG9jYWxEYXRlKTtcbiAgICAgICAgZi50b1N0cmluZyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gc3BlY2lmaWVyOyB9O1xuICAgICAgICByZXR1cm4gZjtcbiAgICAgIH0sXG4gICAgICB1dGNGb3JtYXQ6IGZ1bmN0aW9uKHNwZWNpZmllcikge1xuICAgICAgICB2YXIgZiA9IG5ld0Zvcm1hdChzcGVjaWZpZXIgKz0gXCJcIiwgdXRjRm9ybWF0cyk7XG4gICAgICAgIGYucGFyc2UgPSBuZXdQYXJzZShzcGVjaWZpZXIsIHV0Y0RhdGUpO1xuICAgICAgICBmLnRvU3RyaW5nID0gZnVuY3Rpb24oKSB7IHJldHVybiBzcGVjaWZpZXI7IH07XG4gICAgICAgIHJldHVybiBmO1xuICAgICAgfVxuICAgIH07XG4gIH1cblxuICB2YXIgcGFkcyA9IHtcIi1cIjogXCJcIiwgXCJfXCI6IFwiIFwiLCBcIjBcIjogXCIwXCJ9O1xuICB2YXIgbnVtYmVyUmUgPSAvXlxccypcXGQrLztcbiAgdmFyIHBlcmNlbnRSZSA9IC9eJS87XG4gIHZhciByZXF1b3RlUmUgPSAvW1xcXFxcXF5cXCRcXCpcXCtcXD9cXHxcXFtcXF1cXChcXClcXC5cXHtcXH1dL2c7XG5cbiAgZnVuY3Rpb24gcGFkKHZhbHVlLCBmaWxsLCB3aWR0aCkge1xuICAgIHZhciBzaWduID0gdmFsdWUgPCAwID8gXCItXCIgOiBcIlwiLFxuICAgICAgICBzdHJpbmcgPSAoc2lnbiA/IC12YWx1ZSA6IHZhbHVlKSArIFwiXCIsXG4gICAgICAgIGxlbmd0aCA9IHN0cmluZy5sZW5ndGg7XG4gICAgcmV0dXJuIHNpZ24gKyAobGVuZ3RoIDwgd2lkdGggPyBuZXcgQXJyYXkod2lkdGggLSBsZW5ndGggKyAxKS5qb2luKGZpbGwpICsgc3RyaW5nIDogc3RyaW5nKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlcXVvdGUocykge1xuICAgIHJldHVybiBzLnJlcGxhY2UocmVxdW90ZVJlLCBcIlxcXFwkJlwiKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFJlKG5hbWVzKSB7XG4gICAgcmV0dXJuIG5ldyBSZWdFeHAoXCJeKD86XCIgKyBuYW1lcy5tYXAocmVxdW90ZSkuam9pbihcInxcIikgKyBcIilcIiwgXCJpXCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0TG9va3VwKG5hbWVzKSB7XG4gICAgdmFyIG1hcCA9IG5ldyBNYXAsIGkgPSAtMSwgbiA9IG5hbWVzLmxlbmd0aDtcbiAgICB3aGlsZSAoKytpIDwgbikgbWFwLnNldChuYW1lc1tpXS50b0xvd2VyQ2FzZSgpLCBpKTtcbiAgICByZXR1cm4gbWFwO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VXZWVrZGF5TnVtYmVyKGQsIHN0cmluZywgaSkge1xuICAgIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDEpKTtcbiAgICByZXR1cm4gbiA/IChkLncgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VXZWVrTnVtYmVyU3VuZGF5KGQsIHN0cmluZywgaSkge1xuICAgIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSkpO1xuICAgIHJldHVybiBuID8gKGQuVSA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZVdlZWtOdW1iZXJNb25kYXkoZCwgc3RyaW5nLCBpKSB7XG4gICAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpKSk7XG4gICAgcmV0dXJuIG4gPyAoZC5XID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlRnVsbFllYXIoZCwgc3RyaW5nLCBpKSB7XG4gICAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgNCkpO1xuICAgIHJldHVybiBuID8gKGQueSA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZVllYXIoZCwgc3RyaW5nLCBpKSB7XG4gICAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMikpO1xuICAgIHJldHVybiBuID8gKGQueSA9ICtuWzBdICsgKCtuWzBdID4gNjggPyAxOTAwIDogMjAwMCksIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlWm9uZShkLCBzdHJpbmcsIGkpIHtcbiAgICByZXR1cm4gL15bKy1dXFxkezR9JC8udGVzdChzdHJpbmcgPSBzdHJpbmcuc2xpY2UoaSwgaSArIDUpKVxuICAgICAgICA/IChkLlogPSAtc3RyaW5nLCBpICsgNSkgLy8gc2lnbiBkaWZmZXJzIGZyb20gZ2V0VGltZXpvbmVPZmZzZXQhXG4gICAgICAgIDogLTE7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZU1vbnRoTnVtYmVyKGQsIHN0cmluZywgaSkge1xuICAgIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDIpKTtcbiAgICByZXR1cm4gbiA/IChkLm0gPSBuWzBdIC0gMSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VEYXlPZk1vbnRoKGQsIHN0cmluZywgaSkge1xuICAgIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDIpKTtcbiAgICByZXR1cm4gbiA/IChkLmQgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VEYXlPZlllYXIoZCwgc3RyaW5nLCBpKSB7XG4gICAgdmFyIG4gPSBudW1iZXJSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMykpO1xuICAgIHJldHVybiBuID8gKGQubSA9IDAsIGQuZCA9ICtuWzBdLCBpICsgblswXS5sZW5ndGgpIDogLTE7XG4gIH1cblxuICBmdW5jdGlvbiBwYXJzZUhvdXIyNChkLCBzdHJpbmcsIGkpIHtcbiAgICB2YXIgbiA9IG51bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAyKSk7XG4gICAgcmV0dXJuIG4gPyAoZC5IID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlTWludXRlcyhkLCBzdHJpbmcsIGkpIHtcbiAgICB2YXIgbiA9IG51bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAyKSk7XG4gICAgcmV0dXJuIG4gPyAoZC5NID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlU2Vjb25kcyhkLCBzdHJpbmcsIGkpIHtcbiAgICB2YXIgbiA9IG51bWJlclJlLmV4ZWMoc3RyaW5nLnNsaWNlKGksIGkgKyAyKSk7XG4gICAgcmV0dXJuIG4gPyAoZC5TID0gK25bMF0sIGkgKyBuWzBdLmxlbmd0aCkgOiAtMTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHBhcnNlTWlsbGlzZWNvbmRzKGQsIHN0cmluZywgaSkge1xuICAgIHZhciBuID0gbnVtYmVyUmUuZXhlYyhzdHJpbmcuc2xpY2UoaSwgaSArIDMpKTtcbiAgICByZXR1cm4gbiA/IChkLkwgPSArblswXSwgaSArIG5bMF0ubGVuZ3RoKSA6IC0xO1xuICB9XG5cbiAgZnVuY3Rpb24gcGFyc2VMaXRlcmFsUGVyY2VudChkLCBzdHJpbmcsIGkpIHtcbiAgICB2YXIgbiA9IHBlcmNlbnRSZS5leGVjKHN0cmluZy5zbGljZShpLCBpICsgMSkpO1xuICAgIHJldHVybiBuID8gaSArIG5bMF0ubGVuZ3RoIDogLTE7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXREYXlPZk1vbnRoKGQsIHApIHtcbiAgICByZXR1cm4gcGFkKGQuZ2V0RGF0ZSgpLCBwLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdEhvdXIyNChkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChkLmdldEhvdXJzKCksIHAsIDIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0SG91cjEyKGQsIHApIHtcbiAgICByZXR1cm4gcGFkKGQuZ2V0SG91cnMoKSAlIDEyIHx8IDEyLCBwLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdERheU9mWWVhcihkLCBwKSB7XG4gICAgcmV0dXJuIHBhZCgxICsgZGF5LmNvdW50KHllYXIoZCksIGQpLCBwLCAzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdE1pbGxpc2Vjb25kcyhkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChkLmdldE1pbGxpc2Vjb25kcygpLCBwLCAzKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdE1vbnRoTnVtYmVyKGQsIHApIHtcbiAgICByZXR1cm4gcGFkKGQuZ2V0TW9udGgoKSArIDEsIHAsIDIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0TWludXRlcyhkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChkLmdldE1pbnV0ZXMoKSwgcCwgMik7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRTZWNvbmRzKGQsIHApIHtcbiAgICByZXR1cm4gcGFkKGQuZ2V0U2Vjb25kcygpLCBwLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFdlZWtOdW1iZXJTdW5kYXkoZCwgcCkge1xuICAgIHJldHVybiBwYWQoc3VuZGF5LmNvdW50KHllYXIoZCksIGQpLCBwLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFdlZWtkYXlOdW1iZXIoZCkge1xuICAgIHJldHVybiBkLmdldERheSgpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0V2Vla051bWJlck1vbmRheShkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChtb25kYXkuY291bnQoeWVhcihkKSwgZCksIHAsIDIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0WWVhcihkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChkLmdldEZ1bGxZZWFyKCkgJSAxMDAsIHAsIDIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0RnVsbFllYXIoZCwgcCkge1xuICAgIHJldHVybiBwYWQoZC5nZXRGdWxsWWVhcigpICUgMTAwMDAsIHAsIDQpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0Wm9uZShkKSB7XG4gICAgdmFyIHogPSBkLmdldFRpbWV6b25lT2Zmc2V0KCk7XG4gICAgcmV0dXJuICh6ID4gMCA/IFwiLVwiIDogKHogKj0gLTEsIFwiK1wiKSlcbiAgICAgICAgKyBwYWQoeiAvIDYwIHwgMCwgXCIwXCIsIDIpXG4gICAgICAgICsgcGFkKHogJSA2MCwgXCIwXCIsIDIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0VVRDRGF5T2ZNb250aChkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChkLmdldFVUQ0RhdGUoKSwgcCwgMik7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRVVENIb3VyMjQoZCwgcCkge1xuICAgIHJldHVybiBwYWQoZC5nZXRVVENIb3VycygpLCBwLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ0hvdXIxMihkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChkLmdldFVUQ0hvdXJzKCkgJSAxMiB8fCAxMiwgcCwgMik7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRVVENEYXlPZlllYXIoZCwgcCkge1xuICAgIHJldHVybiBwYWQoMSArIHV0Y0RheS5jb3VudCh1dGNZZWFyKGQpLCBkKSwgcCwgMyk7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRVVENNaWxsaXNlY29uZHMoZCwgcCkge1xuICAgIHJldHVybiBwYWQoZC5nZXRVVENNaWxsaXNlY29uZHMoKSwgcCwgMyk7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRVVENNb250aE51bWJlcihkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChkLmdldFVUQ01vbnRoKCkgKyAxLCBwLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ01pbnV0ZXMoZCwgcCkge1xuICAgIHJldHVybiBwYWQoZC5nZXRVVENNaW51dGVzKCksIHAsIDIpO1xuICB9XG5cbiAgZnVuY3Rpb24gZm9ybWF0VVRDU2Vjb25kcyhkLCBwKSB7XG4gICAgcmV0dXJuIHBhZChkLmdldFVUQ1NlY29uZHMoKSwgcCwgMik7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRVVENXZWVrTnVtYmVyU3VuZGF5KGQsIHApIHtcbiAgICByZXR1cm4gcGFkKHV0Y1N1bmRheS5jb3VudCh1dGNZZWFyKGQpLCBkKSwgcCwgMik7XG4gIH1cblxuICBmdW5jdGlvbiBmb3JtYXRVVENXZWVrZGF5TnVtYmVyKGQpIHtcbiAgICByZXR1cm4gZC5nZXRVVENEYXkoKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ1dlZWtOdW1iZXJNb25kYXkoZCwgcCkge1xuICAgIHJldHVybiBwYWQodXRjTW9uZGF5LmNvdW50KHV0Y1llYXIoZCksIGQpLCBwLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ1llYXIoZCwgcCkge1xuICAgIHJldHVybiBwYWQoZC5nZXRVVENGdWxsWWVhcigpICUgMTAwLCBwLCAyKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ0Z1bGxZZWFyKGQsIHApIHtcbiAgICByZXR1cm4gcGFkKGQuZ2V0VVRDRnVsbFllYXIoKSAlIDEwMDAwLCBwLCA0KTtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdFVUQ1pvbmUoKSB7XG4gICAgcmV0dXJuIFwiKzAwMDBcIjtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZvcm1hdExpdGVyYWxQZXJjZW50KCkge1xuICAgIHJldHVybiBcIiVcIjtcbiAgfVxuXG4gIHZhciBpc29TcGVjaWZpZXIgPSBcIiVZLSVtLSVkVCVIOiVNOiVTLiVMWlwiO1xuXG4gIGZ1bmN0aW9uIGZvcm1hdElzb05hdGl2ZShkYXRlKSB7XG4gICAgcmV0dXJuIGRhdGUudG9JU09TdHJpbmcoKTtcbiAgfVxuXG4gIGZvcm1hdElzb05hdGl2ZS5wYXJzZSA9IGZ1bmN0aW9uKHN0cmluZykge1xuICAgIHZhciBkYXRlID0gbmV3IERhdGUoc3RyaW5nKTtcbiAgICByZXR1cm4gaXNOYU4oZGF0ZSkgPyBudWxsIDogZGF0ZTtcbiAgfTtcblxuICBmb3JtYXRJc29OYXRpdmUudG9TdHJpbmcgPSBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gaXNvU3BlY2lmaWVyO1xuICB9O1xuXG4gIHZhciBmb3JtYXRJc28gPSBEYXRlLnByb3RvdHlwZS50b0lTT1N0cmluZyAmJiArbmV3IERhdGUoXCIyMDAwLTAxLTAxVDAwOjAwOjAwLjAwMFpcIilcbiAgICAgID8gZm9ybWF0SXNvTmF0aXZlXG4gICAgICA6IGVuVXMudXRjRm9ybWF0KGlzb1NwZWNpZmllcik7XG5cbiAgdmFyIGlzb0Zvcm1hdCA9IGZvcm1hdElzbztcblxuICB2YXIgbG9jYWxlRGVmaW5pdGlvbnMgPSAobmV3IE1hcClcbiAgICAgIC5zZXQoXCJjYS1FU1wiLCBjYUVzKVxuICAgICAgLnNldChcImRlLURFXCIsIGRlRGUpXG4gICAgICAuc2V0KFwiZW4tQ0FcIiwgZW5DYSlcbiAgICAgIC5zZXQoXCJlbi1HQlwiLCBlbkdiKVxuICAgICAgLnNldChcImVuLVVTXCIsIGVuVXMpXG4gICAgICAuc2V0KFwiZXMtRVNcIiwgZXNFcylcbiAgICAgIC5zZXQoXCJmaS1GSVwiLCBmaUZpKVxuICAgICAgLnNldChcImZyLUNBXCIsIGZyQ2EpXG4gICAgICAuc2V0KFwiZnItRlJcIiwgZnJGcilcbiAgICAgIC5zZXQoXCJoZS1JTFwiLCBoZUlsKVxuICAgICAgLnNldChcIml0LUlUXCIsIGl0SXQpXG4gICAgICAuc2V0KFwibWstTUtcIiwgbWtNaylcbiAgICAgIC5zZXQoXCJubC1OTFwiLCBubE5sKVxuICAgICAgLnNldChcInBsLVBMXCIsIHBsUGwpXG4gICAgICAuc2V0KFwicHQtQlJcIiwgcHRCcilcbiAgICAgIC5zZXQoXCJydS1SVVwiLCBydVJ1KVxuICAgICAgLnNldChcInpoLUNOXCIsIHpoQ24pO1xuXG4gIHZhciBkZWZhdWx0TG9jYWxlID0gbG9jYWxlKGVuVXMpO1xuICBleHBvcnRzLmZvcm1hdCA9IGRlZmF1bHRMb2NhbGUuZm9ybWF0O1xuICBleHBvcnRzLnV0Y0Zvcm1hdCA9IGRlZmF1bHRMb2NhbGUudXRjRm9ybWF0O1xuXG4gIGZ1bmN0aW9uIGxvY2FsZUZvcm1hdChkZWZpbml0aW9uKSB7XG4gICAgaWYgKHR5cGVvZiBkZWZpbml0aW9uID09PSBcInN0cmluZ1wiKSB7XG4gICAgICBkZWZpbml0aW9uID0gbG9jYWxlRGVmaW5pdGlvbnMuZ2V0KGRlZmluaXRpb24pO1xuICAgICAgaWYgKCFkZWZpbml0aW9uKSByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIGxvY2FsZShkZWZpbml0aW9uKTtcbiAgfVxuICA7XG5cbiAgZXhwb3J0cy5sb2NhbGVGb3JtYXQgPSBsb2NhbGVGb3JtYXQ7XG4gIGV4cG9ydHMuaXNvRm9ybWF0ID0gaXNvRm9ybWF0O1xuXG59KSk7IiwiKGZ1bmN0aW9uIChnbG9iYWwsIGZhY3RvcnkpIHtcbiAgdHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnID8gZmFjdG9yeShleHBvcnRzKSA6XG4gIHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCA/IGRlZmluZShbJ2V4cG9ydHMnXSwgZmFjdG9yeSkgOlxuICBmYWN0b3J5KChnbG9iYWwudGltZSA9IHt9KSk7XG59KHRoaXMsIGZ1bmN0aW9uIChleHBvcnRzKSB7ICd1c2Ugc3RyaWN0JztcblxuICB2YXIgdDEgPSBuZXcgRGF0ZTtcblxuICB2YXIgdDAgPSBuZXcgRGF0ZTtcblxuICBmdW5jdGlvbiBuZXdJbnRlcnZhbChmbG9vcmksIG9mZnNldGksIGNvdW50KSB7XG5cbiAgICBmdW5jdGlvbiBpbnRlcnZhbChkYXRlKSB7XG4gICAgICByZXR1cm4gZmxvb3JpKGRhdGUgPSBuZXcgRGF0ZSgrZGF0ZSkpLCBkYXRlO1xuICAgIH1cblxuICAgIGludGVydmFsLmZsb29yID0gaW50ZXJ2YWw7XG5cbiAgICBpbnRlcnZhbC5yb3VuZCA9IGZ1bmN0aW9uKGRhdGUpIHtcbiAgICAgIHZhciBkMCA9IG5ldyBEYXRlKCtkYXRlKSxcbiAgICAgICAgICBkMSA9IG5ldyBEYXRlKGRhdGUgLSAxKTtcbiAgICAgIGZsb29yaShkMCksIGZsb29yaShkMSksIG9mZnNldGkoZDEsIDEpO1xuICAgICAgcmV0dXJuIGRhdGUgLSBkMCA8IGQxIC0gZGF0ZSA/IGQwIDogZDE7XG4gICAgfTtcblxuICAgIGludGVydmFsLmNlaWwgPSBmdW5jdGlvbihkYXRlKSB7XG4gICAgICByZXR1cm4gZmxvb3JpKGRhdGUgPSBuZXcgRGF0ZShkYXRlIC0gMSkpLCBvZmZzZXRpKGRhdGUsIDEpLCBkYXRlO1xuICAgIH07XG5cbiAgICBpbnRlcnZhbC5vZmZzZXQgPSBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgICByZXR1cm4gb2Zmc2V0aShkYXRlID0gbmV3IERhdGUoK2RhdGUpLCBzdGVwID09IG51bGwgPyAxIDogTWF0aC5mbG9vcihzdGVwKSksIGRhdGU7XG4gICAgfTtcblxuICAgIGludGVydmFsLnJhbmdlID0gZnVuY3Rpb24oc3RhcnQsIHN0b3AsIHN0ZXApIHtcbiAgICAgIHZhciByYW5nZSA9IFtdO1xuICAgICAgc3RhcnQgPSBuZXcgRGF0ZShzdGFydCAtIDEpO1xuICAgICAgc3RvcCA9IG5ldyBEYXRlKCtzdG9wKTtcbiAgICAgIHN0ZXAgPSBzdGVwID09IG51bGwgPyAxIDogTWF0aC5mbG9vcihzdGVwKTtcbiAgICAgIGlmICghKHN0YXJ0IDwgc3RvcCkgfHwgIShzdGVwID4gMCkpIHJldHVybiByYW5nZTsgLy8gYWxzbyBoYW5kbGVzIEludmFsaWQgRGF0ZVxuICAgICAgb2Zmc2V0aShzdGFydCwgMSksIGZsb29yaShzdGFydCk7XG4gICAgICBpZiAoc3RhcnQgPCBzdG9wKSByYW5nZS5wdXNoKG5ldyBEYXRlKCtzdGFydCkpO1xuICAgICAgd2hpbGUgKG9mZnNldGkoc3RhcnQsIHN0ZXApLCBmbG9vcmkoc3RhcnQpLCBzdGFydCA8IHN0b3ApIHJhbmdlLnB1c2gobmV3IERhdGUoK3N0YXJ0KSk7XG4gICAgICByZXR1cm4gcmFuZ2U7XG4gICAgfTtcblxuICAgIGludGVydmFsLmZpbHRlciA9IGZ1bmN0aW9uKHRlc3QpIHtcbiAgICAgIHJldHVybiBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgICAgIHdoaWxlIChmbG9vcmkoZGF0ZSksICF0ZXN0KGRhdGUpKSBkYXRlLnNldFRpbWUoZGF0ZSAtIDEpO1xuICAgICAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgICAgICB3aGlsZSAoLS1zdGVwID49IDApIHdoaWxlIChvZmZzZXRpKGRhdGUsIDEpLCAhdGVzdChkYXRlKSk7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgaWYgKGNvdW50KSBpbnRlcnZhbC5jb3VudCA9IGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICAgIHQwLnNldFRpbWUoK3N0YXJ0KSwgdDEuc2V0VGltZSgrZW5kKTtcbiAgICAgIGZsb29yaSh0MCksIGZsb29yaSh0MSk7XG4gICAgICByZXR1cm4gTWF0aC5mbG9vcihjb3VudCh0MCwgdDEpKTtcbiAgICB9O1xuXG4gICAgcmV0dXJuIGludGVydmFsO1xuICB9XG5cbiAgdmFyIHNlY29uZCA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldE1pbGxpc2Vjb25kcygwKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgIGRhdGUuc2V0VGltZSgrZGF0ZSArIHN0ZXAgKiAxZTMpO1xuICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgcmV0dXJuIChlbmQgLSBzdGFydCkgLyAxZTM7XG4gIH0pO1xuXG4gIGV4cG9ydHMuc2Vjb25kcyA9IHNlY29uZC5yYW5nZTtcblxuICB2YXIgbWludXRlID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIGRhdGUuc2V0U2Vjb25kcygwLCAwKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgIGRhdGUuc2V0VGltZSgrZGF0ZSArIHN0ZXAgKiA2ZTQpO1xuICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgcmV0dXJuIChlbmQgLSBzdGFydCkgLyA2ZTQ7XG4gIH0pO1xuXG4gIGV4cG9ydHMubWludXRlcyA9IG1pbnV0ZS5yYW5nZTtcblxuICB2YXIgaG91ciA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldE1pbnV0ZXMoMCwgMCwgMCk7XG4gIH0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgICBkYXRlLnNldFRpbWUoK2RhdGUgKyBzdGVwICogMzZlNSk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIDM2ZTU7XG4gIH0pO1xuXG4gIGV4cG9ydHMuaG91cnMgPSBob3VyLnJhbmdlO1xuXG4gIHZhciBkYXkgPSBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgZGF0ZS5zZXRIb3VycygwLCAwLCAwLCAwKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgIGRhdGUuc2V0RGF0ZShkYXRlLmdldERhdGUoKSArIHN0ZXApO1xuICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgcmV0dXJuIChlbmQgLSBzdGFydCAtIChlbmQuZ2V0VGltZXpvbmVPZmZzZXQoKSAtIHN0YXJ0LmdldFRpbWV6b25lT2Zmc2V0KCkpICogNmU0KSAvIDg2NGU1O1xuICB9KTtcblxuICBleHBvcnRzLmRheXMgPSBkYXkucmFuZ2U7XG5cbiAgZnVuY3Rpb24gd2Vla2RheShpKSB7XG4gICAgcmV0dXJuIG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICAgIGRhdGUuc2V0SG91cnMoMCwgMCwgMCwgMCk7XG4gICAgICBkYXRlLnNldERhdGUoZGF0ZS5nZXREYXRlKCkgLSAoZGF0ZS5nZXREYXkoKSArIDcgLSBpKSAlIDcpO1xuICAgIH0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgICAgIGRhdGUuc2V0RGF0ZShkYXRlLmdldERhdGUoKSArIHN0ZXAgKiA3KTtcbiAgICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgICByZXR1cm4gKGVuZCAtIHN0YXJ0IC0gKGVuZC5nZXRUaW1lem9uZU9mZnNldCgpIC0gc3RhcnQuZ2V0VGltZXpvbmVPZmZzZXQoKSkgKiA2ZTQpIC8gNjA0OGU1O1xuICAgIH0pO1xuICB9XG5cbiAgZXhwb3J0cy5zdW5kYXkgPSB3ZWVrZGF5KDApO1xuXG4gIGV4cG9ydHMuc3VuZGF5cyA9IGV4cG9ydHMuc3VuZGF5LnJhbmdlO1xuXG4gIGV4cG9ydHMubW9uZGF5ID0gd2Vla2RheSgxKTtcblxuICBleHBvcnRzLm1vbmRheXMgPSBleHBvcnRzLm1vbmRheS5yYW5nZTtcblxuICBleHBvcnRzLnR1ZXNkYXkgPSB3ZWVrZGF5KDIpO1xuXG4gIGV4cG9ydHMudHVlc2RheXMgPSBleHBvcnRzLnR1ZXNkYXkucmFuZ2U7XG5cbiAgZXhwb3J0cy53ZWRuZXNkYXkgPSB3ZWVrZGF5KDMpO1xuXG4gIGV4cG9ydHMud2VkbmVzZGF5cyA9IGV4cG9ydHMud2VkbmVzZGF5LnJhbmdlO1xuXG4gIGV4cG9ydHMudGh1cnNkYXkgPSB3ZWVrZGF5KDQpO1xuXG4gIGV4cG9ydHMudGh1cnNkYXlzID0gZXhwb3J0cy50aHVyc2RheS5yYW5nZTtcblxuICBleHBvcnRzLmZyaWRheSA9IHdlZWtkYXkoNSk7XG5cbiAgZXhwb3J0cy5mcmlkYXlzID0gZXhwb3J0cy5mcmlkYXkucmFuZ2U7XG5cbiAgZXhwb3J0cy5zYXR1cmRheSA9IHdlZWtkYXkoNik7XG5cbiAgZXhwb3J0cy5zYXR1cmRheXMgPSBleHBvcnRzLnNhdHVyZGF5LnJhbmdlO1xuXG4gIHZhciB3ZWVrID0gZXhwb3J0cy5zdW5kYXk7XG5cbiAgZXhwb3J0cy53ZWVrcyA9IHdlZWsucmFuZ2U7XG5cbiAgdmFyIG1vbnRoID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIGRhdGUuc2V0SG91cnMoMCwgMCwgMCwgMCk7XG4gICAgZGF0ZS5zZXREYXRlKDEpO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXRNb250aChkYXRlLmdldE1vbnRoKCkgKyBzdGVwKTtcbiAgfSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgIHJldHVybiBlbmQuZ2V0TW9udGgoKSAtIHN0YXJ0LmdldE1vbnRoKCkgKyAoZW5kLmdldEZ1bGxZZWFyKCkgLSBzdGFydC5nZXRGdWxsWWVhcigpKSAqIDEyO1xuICB9KTtcblxuICBleHBvcnRzLm1vbnRocyA9IG1vbnRoLnJhbmdlO1xuXG4gIHZhciB5ZWFyID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIGRhdGUuc2V0SG91cnMoMCwgMCwgMCwgMCk7XG4gICAgZGF0ZS5zZXRNb250aCgwLCAxKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgIGRhdGUuc2V0RnVsbFllYXIoZGF0ZS5nZXRGdWxsWWVhcigpICsgc3RlcCk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gZW5kLmdldEZ1bGxZZWFyKCkgLSBzdGFydC5nZXRGdWxsWWVhcigpO1xuICB9KTtcblxuICBleHBvcnRzLnllYXJzID0geWVhci5yYW5nZTtcblxuICB2YXIgdXRjU2Vjb25kID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIGRhdGUuc2V0VVRDTWlsbGlzZWNvbmRzKDApO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXRUaW1lKCtkYXRlICsgc3RlcCAqIDFlMyk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIDFlMztcbiAgfSk7XG5cbiAgZXhwb3J0cy51dGNTZWNvbmRzID0gdXRjU2Vjb25kLnJhbmdlO1xuXG4gIHZhciB1dGNNaW51dGUgPSBuZXdJbnRlcnZhbChmdW5jdGlvbihkYXRlKSB7XG4gICAgZGF0ZS5zZXRVVENTZWNvbmRzKDAsIDApO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXRUaW1lKCtkYXRlICsgc3RlcCAqIDZlNCk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIDZlNDtcbiAgfSk7XG5cbiAgZXhwb3J0cy51dGNNaW51dGVzID0gdXRjTWludXRlLnJhbmdlO1xuXG4gIHZhciB1dGNIb3VyID0gbmV3SW50ZXJ2YWwoZnVuY3Rpb24oZGF0ZSkge1xuICAgIGRhdGUuc2V0VVRDTWludXRlcygwLCAwLCAwKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgIGRhdGUuc2V0VGltZSgrZGF0ZSArIHN0ZXAgKiAzNmU1KTtcbiAgfSwgZnVuY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgIHJldHVybiAoZW5kIC0gc3RhcnQpIC8gMzZlNTtcbiAgfSk7XG5cbiAgZXhwb3J0cy51dGNIb3VycyA9IHV0Y0hvdXIucmFuZ2U7XG5cbiAgdmFyIHV0Y0RheSA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldFVUQ0hvdXJzKDAsIDAsIDAsIDApO1xuICB9LCBmdW5jdGlvbihkYXRlLCBzdGVwKSB7XG4gICAgZGF0ZS5zZXRVVENEYXRlKGRhdGUuZ2V0VVRDRGF0ZSgpICsgc3RlcCk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIDg2NGU1O1xuICB9KTtcblxuICBleHBvcnRzLnV0Y0RheXMgPSB1dGNEYXkucmFuZ2U7XG5cbiAgZnVuY3Rpb24gdXRjV2Vla2RheShpKSB7XG4gICAgcmV0dXJuIG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICAgIGRhdGUuc2V0VVRDSG91cnMoMCwgMCwgMCwgMCk7XG4gICAgICBkYXRlLnNldFVUQ0RhdGUoZGF0ZS5nZXRVVENEYXRlKCkgLSAoZGF0ZS5nZXRVVENEYXkoKSArIDcgLSBpKSAlIDcpO1xuICAgIH0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgICAgIGRhdGUuc2V0VVRDRGF0ZShkYXRlLmdldFVUQ0RhdGUoKSArIHN0ZXAgKiA3KTtcbiAgICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIDYwNDhlNTtcbiAgICB9KTtcbiAgfVxuXG4gIGV4cG9ydHMudXRjU3VuZGF5ID0gdXRjV2Vla2RheSgwKTtcblxuICBleHBvcnRzLnV0Y1N1bmRheXMgPSBleHBvcnRzLnV0Y1N1bmRheS5yYW5nZTtcblxuICBleHBvcnRzLnV0Y01vbmRheSA9IHV0Y1dlZWtkYXkoMSk7XG5cbiAgZXhwb3J0cy51dGNNb25kYXlzID0gZXhwb3J0cy51dGNNb25kYXkucmFuZ2U7XG5cbiAgZXhwb3J0cy51dGNUdWVzZGF5ID0gdXRjV2Vla2RheSgyKTtcblxuICBleHBvcnRzLnV0Y1R1ZXNkYXlzID0gZXhwb3J0cy51dGNUdWVzZGF5LnJhbmdlO1xuXG4gIGV4cG9ydHMudXRjV2VkbmVzZGF5ID0gdXRjV2Vla2RheSgzKTtcblxuICBleHBvcnRzLnV0Y1dlZG5lc2RheXMgPSBleHBvcnRzLnV0Y1dlZG5lc2RheS5yYW5nZTtcblxuICBleHBvcnRzLnV0Y1RodXJzZGF5ID0gdXRjV2Vla2RheSg0KTtcblxuICBleHBvcnRzLnV0Y1RodXJzZGF5cyA9IGV4cG9ydHMudXRjVGh1cnNkYXkucmFuZ2U7XG5cbiAgZXhwb3J0cy51dGNGcmlkYXkgPSB1dGNXZWVrZGF5KDUpO1xuXG4gIGV4cG9ydHMudXRjRnJpZGF5cyA9IGV4cG9ydHMudXRjRnJpZGF5LnJhbmdlO1xuXG4gIGV4cG9ydHMudXRjU2F0dXJkYXkgPSB1dGNXZWVrZGF5KDYpO1xuXG4gIGV4cG9ydHMudXRjU2F0dXJkYXlzID0gZXhwb3J0cy51dGNTYXR1cmRheS5yYW5nZTtcblxuICB2YXIgdXRjV2VlayA9IGV4cG9ydHMudXRjU3VuZGF5O1xuXG4gIGV4cG9ydHMudXRjV2Vla3MgPSB1dGNXZWVrLnJhbmdlO1xuXG4gIHZhciB1dGNNb250aCA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldFVUQ0hvdXJzKDAsIDAsIDAsIDApO1xuICAgIGRhdGUuc2V0VVRDRGF0ZSgxKTtcbiAgfSwgZnVuY3Rpb24oZGF0ZSwgc3RlcCkge1xuICAgIGRhdGUuc2V0VVRDTW9udGgoZGF0ZS5nZXRVVENNb250aCgpICsgc3RlcCk7XG4gIH0sIGZ1bmN0aW9uKHN0YXJ0LCBlbmQpIHtcbiAgICByZXR1cm4gZW5kLmdldFVUQ01vbnRoKCkgLSBzdGFydC5nZXRVVENNb250aCgpICsgKGVuZC5nZXRVVENGdWxsWWVhcigpIC0gc3RhcnQuZ2V0VVRDRnVsbFllYXIoKSkgKiAxMjtcbiAgfSk7XG5cbiAgZXhwb3J0cy51dGNNb250aHMgPSB1dGNNb250aC5yYW5nZTtcblxuICB2YXIgdXRjWWVhciA9IG5ld0ludGVydmFsKGZ1bmN0aW9uKGRhdGUpIHtcbiAgICBkYXRlLnNldFVUQ0hvdXJzKDAsIDAsIDAsIDApO1xuICAgIGRhdGUuc2V0VVRDTW9udGgoMCwgMSk7XG4gIH0sIGZ1bmN0aW9uKGRhdGUsIHN0ZXApIHtcbiAgICBkYXRlLnNldFVUQ0Z1bGxZZWFyKGRhdGUuZ2V0VVRDRnVsbFllYXIoKSArIHN0ZXApO1xuICB9LCBmdW5jdGlvbihzdGFydCwgZW5kKSB7XG4gICAgcmV0dXJuIGVuZC5nZXRVVENGdWxsWWVhcigpIC0gc3RhcnQuZ2V0VVRDRnVsbFllYXIoKTtcbiAgfSk7XG5cbiAgZXhwb3J0cy51dGNZZWFycyA9IHV0Y1llYXIucmFuZ2U7XG5cbiAgZXhwb3J0cy5pbnRlcnZhbCA9IG5ld0ludGVydmFsO1xuICBleHBvcnRzLnNlY29uZCA9IHNlY29uZDtcbiAgZXhwb3J0cy5taW51dGUgPSBtaW51dGU7XG4gIGV4cG9ydHMuaG91ciA9IGhvdXI7XG4gIGV4cG9ydHMuZGF5ID0gZGF5O1xuICBleHBvcnRzLndlZWsgPSB3ZWVrO1xuICBleHBvcnRzLm1vbnRoID0gbW9udGg7XG4gIGV4cG9ydHMueWVhciA9IHllYXI7XG4gIGV4cG9ydHMudXRjU2Vjb25kID0gdXRjU2Vjb25kO1xuICBleHBvcnRzLnV0Y01pbnV0ZSA9IHV0Y01pbnV0ZTtcbiAgZXhwb3J0cy51dGNIb3VyID0gdXRjSG91cjtcbiAgZXhwb3J0cy51dGNEYXkgPSB1dGNEYXk7XG4gIGV4cG9ydHMudXRjV2VlayA9IHV0Y1dlZWs7XG4gIGV4cG9ydHMudXRjTW9udGggPSB1dGNNb250aDtcbiAgZXhwb3J0cy51dGNZZWFyID0gdXRjWWVhcjtcblxufSkpOyIsInZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICAgIE1lYXN1cmVzID0gcmVxdWlyZSgnLi9tZWFzdXJlcycpLFxuICAgIENvbGxlY3RvciA9IHJlcXVpcmUoJy4vY29sbGVjdG9yJyk7XG5cbmZ1bmN0aW9uIEFnZ3JlZ2F0b3IoKSB7XG4gIHRoaXMuX2NlbGxzID0ge307XG4gIHRoaXMuX2FnZ3IgPSBbXTtcbiAgdGhpcy5fc3RyZWFtID0gZmFsc2U7XG59XG5cbnZhciBGbGFncyA9IEFnZ3JlZ2F0b3IuRmxhZ3MgPSB7XG4gIEFERF9DRUxMOiAxLFxuICBNT0RfQ0VMTDogMlxufTtcblxudmFyIHByb3RvID0gQWdncmVnYXRvci5wcm90b3R5cGU7XG5cbi8vIFBhcmFtZXRlcnNcblxucHJvdG8uc3RyZWFtID0gZnVuY3Rpb24odikge1xuICBpZiAodiA9PSBudWxsKSByZXR1cm4gdGhpcy5fc3RyZWFtO1xuICB0aGlzLl9zdHJlYW0gPSAhIXY7XG4gIHRoaXMuX2FnZ3IgPSBbXTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vLyBrZXkgYWNjZXNzb3IgdG8gdXNlIGZvciBzdHJlYW1pbmcgcmVtb3Zlc1xucHJvdG8ua2V5ID0gZnVuY3Rpb24oa2V5KSB7XG4gIGlmIChrZXkgPT0gbnVsbCkgcmV0dXJuIHRoaXMuX2tleTtcbiAgdGhpcy5fa2V5ID0gdXRpbC4kKGtleSk7XG4gIHJldHVybiB0aGlzO1xufTtcblxuLy8gSW5wdXQ6IGFycmF5IG9mIG9iamVjdHMgb2YgdGhlIGZvcm1cbi8vIHtuYW1lOiBzdHJpbmcsIGdldDogZnVuY3Rpb259XG5wcm90by5ncm91cGJ5ID0gZnVuY3Rpb24oZGltcykge1xuICB0aGlzLl9kaW1zID0gdXRpbC5hcnJheShkaW1zKS5tYXAoZnVuY3Rpb24oZCwgaSkge1xuICAgIGQgPSB1dGlsLmlzU3RyaW5nKGQpID8ge25hbWU6IGQsIGdldDogdXRpbC4kKGQpfVxuICAgICAgOiB1dGlsLmlzRnVuY3Rpb24oZCkgPyB7bmFtZTogdXRpbC5uYW1lKGQpIHx8IGQubmFtZSB8fCAoJ18nICsgaSksIGdldDogZH1cbiAgICAgIDogKGQubmFtZSAmJiB1dGlsLmlzRnVuY3Rpb24oZC5nZXQpKSA/IGQgOiBudWxsO1xuICAgIGlmIChkID09IG51bGwpIHRocm93ICdJbnZhbGlkIGdyb3VwYnkgYXJndW1lbnQ6ICcgKyBkO1xuICAgIHJldHVybiBkO1xuICB9KTtcbiAgcmV0dXJuIHRoaXMuY2xlYXIoKTtcbn07XG5cbi8vIElucHV0OiBhcnJheSBvZiBvYmplY3RzIG9mIHRoZSBmb3JtXG4vLyB7bmFtZTogc3RyaW5nLCBvcHM6IFtzdHJpbmcsIC4uLl19XG5wcm90by5zdW1tYXJpemUgPSBmdW5jdGlvbihmaWVsZHMpIHtcbiAgZmllbGRzID0gc3VtbWFyaXplX2FyZ3MoZmllbGRzKTtcbiAgdGhpcy5fY291bnQgPSB0cnVlO1xuICB2YXIgYWdnciA9ICh0aGlzLl9hZ2dyID0gW10pLFxuICAgICAgbSwgZiwgaSwgaiwgb3AsIGFzLCBnZXQ7XG5cbiAgZm9yIChpPTA7IGk8ZmllbGRzLmxlbmd0aDsgKytpKSB7XG4gICAgZm9yIChqPTAsIG09W10sIGY9ZmllbGRzW2ldOyBqPGYub3BzLmxlbmd0aDsgKytqKSB7XG4gICAgICBvcCA9IGYub3BzW2pdO1xuICAgICAgaWYgKG9wICE9PSAnY291bnQnKSB0aGlzLl9jb3VudCA9IGZhbHNlO1xuICAgICAgYXMgPSAoZi5hcyAmJiBmLmFzW2pdKSB8fCAob3AgKyAoZi5uYW1lPT09JyonID8gJycgOiAnXycrZi5uYW1lKSk7XG4gICAgICBtLnB1c2goTWVhc3VyZXNbb3BdKGFzKSk7XG4gICAgfVxuICAgIGdldCA9IGYuZ2V0ICYmIHV0aWwuJChmLmdldCkgfHxcbiAgICAgIChmLm5hbWUgPT09ICcqJyA/IHV0aWwuaWRlbnRpdHkgOiB1dGlsLiQoZi5uYW1lKSk7XG4gICAgYWdnci5wdXNoKHtcbiAgICAgIG5hbWU6IGYubmFtZSxcbiAgICAgIG1lYXN1cmVzOiBNZWFzdXJlcy5jcmVhdGUoXG4gICAgICAgIG0sXG4gICAgICAgIHRoaXMuX3N0cmVhbSwgLy8gc3RyZWFtaW5nIHJlbW92ZSBmbGFnXG4gICAgICAgIGdldCwgICAgICAgICAgLy8gaW5wdXQgdHVwbGUgZ2V0dGVyXG4gICAgICAgIHRoaXMuX2Fzc2lnbikgLy8gb3V0cHV0IHR1cGxlIHNldHRlclxuICAgIH0pO1xuICB9XG4gIHJldHVybiB0aGlzLmNsZWFyKCk7XG59O1xuXG4vLyBDb252ZW5pZW5jZSBtZXRob2QgdG8gc3VtbWFyaXplIGJ5IGNvdW50XG5wcm90by5jb3VudCA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gdGhpcy5zdW1tYXJpemUoeycqJzonY291bnQnfSk7XG59O1xuXG4vLyBPdmVycmlkZSB0byBwZXJmb3JtIGN1c3RvbSB0dXBsZSB2YWx1ZSBhc3NpZ25tZW50XG5wcm90by5fYXNzaWduID0gZnVuY3Rpb24ob2JqZWN0LCBuYW1lLCB2YWx1ZSkge1xuICBvYmplY3RbbmFtZV0gPSB2YWx1ZTtcbn07XG5cbmZ1bmN0aW9uIHN1bW1hcml6ZV9hcmdzKGZpZWxkcykge1xuICBpZiAodXRpbC5pc0FycmF5KGZpZWxkcykpIHsgcmV0dXJuIGZpZWxkczsgfVxuICBpZiAoZmllbGRzID09IG51bGwpIHsgcmV0dXJuIFtdOyB9XG4gIHZhciBhID0gW10sIG5hbWUsIG9wcztcbiAgZm9yIChuYW1lIGluIGZpZWxkcykge1xuICAgIG9wcyA9IHV0aWwuYXJyYXkoZmllbGRzW25hbWVdKTtcbiAgICBhLnB1c2goe25hbWU6IG5hbWUsIG9wczogb3BzfSk7XG4gIH1cbiAgcmV0dXJuIGE7XG59XG5cbi8vIENlbGwgTWFuYWdlbWVudFxuXG5wcm90by5jbGVhciA9IGZ1bmN0aW9uKCkge1xuICByZXR1cm4gKHRoaXMuX2NlbGxzID0ge30sIHRoaXMpO1xufTtcblxucHJvdG8uX2NlbGxrZXkgPSBmdW5jdGlvbih4KSB7XG4gIHZhciBkID0gdGhpcy5fZGltcyxcbiAgICAgIG4gPSBkLmxlbmd0aCwgaSxcbiAgICAgIGsgPSBTdHJpbmcoZFswXS5nZXQoeCkpO1xuICBmb3IgKGk9MTsgaTxuOyArK2kpIHtcbiAgICBrICs9ICd8JyArIGRbaV0uZ2V0KHgpO1xuICB9XG4gIHJldHVybiBrO1xufTtcblxucHJvdG8uX2NlbGwgPSBmdW5jdGlvbih4KSB7XG4gIHZhciBrZXkgPSB0aGlzLl9kaW1zLmxlbmd0aCA/IHRoaXMuX2NlbGxrZXkoeCkgOiAnJztcbiAgcmV0dXJuIHRoaXMuX2NlbGxzW2tleV0gfHwgKHRoaXMuX2NlbGxzW2tleV0gPSB0aGlzLl9uZXdjZWxsKHgsIGtleSkpO1xufTtcblxucHJvdG8uX25ld2NlbGwgPSBmdW5jdGlvbih4LCBrZXkpIHtcbiAgdmFyIGNlbGwgPSB7XG4gICAgbnVtOiAgIDAsXG4gICAgdHVwbGU6IHRoaXMuX25ld3R1cGxlKHgsIGtleSksXG4gICAgZmxhZzogIEZsYWdzLkFERF9DRUxMLFxuICAgIGFnZ3M6ICB7fVxuICB9O1xuXG4gIHZhciBhZ2dyID0gdGhpcy5fYWdnciwgaTtcbiAgZm9yIChpPTA7IGk8YWdnci5sZW5ndGg7ICsraSkge1xuICAgIGNlbGwuYWdnc1thZ2dyW2ldLm5hbWVdID0gbmV3IGFnZ3JbaV0ubWVhc3VyZXMoY2VsbCwgY2VsbC50dXBsZSk7XG4gIH1cbiAgaWYgKGNlbGwuY29sbGVjdCkge1xuICAgIGNlbGwuZGF0YSA9IG5ldyBDb2xsZWN0b3IodGhpcy5fa2V5KTtcbiAgfVxuICByZXR1cm4gY2VsbDtcbn07XG5cbnByb3RvLl9uZXd0dXBsZSA9IGZ1bmN0aW9uKHgpIHtcbiAgdmFyIGRpbXMgPSB0aGlzLl9kaW1zLFxuICAgICAgdCA9IHt9LCBpLCBuO1xuICBmb3IgKGk9MCwgbj1kaW1zLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICB0W2RpbXNbaV0ubmFtZV0gPSBkaW1zW2ldLmdldCh4KTtcbiAgfVxuICByZXR1cm4gdGhpcy5faW5nZXN0KHQpO1xufTtcblxuLy8gT3ZlcnJpZGUgdG8gcGVyZm9ybSBjdXN0b20gdHVwbGUgaW5nZXN0aW9uXG5wcm90by5faW5nZXN0ID0gdXRpbC5pZGVudGl0eTtcblxuLy8gUHJvY2VzcyBUdXBsZXNcblxucHJvdG8uX2FkZCA9IGZ1bmN0aW9uKHgpIHtcbiAgdmFyIGNlbGwgPSB0aGlzLl9jZWxsKHgpLFxuICAgICAgYWdnciA9IHRoaXMuX2FnZ3IsIGk7XG5cbiAgY2VsbC5udW0gKz0gMTtcbiAgaWYgKCF0aGlzLl9jb3VudCkgeyAvLyBza2lwIGlmIGNvdW50LW9ubHlcbiAgICBpZiAoY2VsbC5jb2xsZWN0KSBjZWxsLmRhdGEuYWRkKHgpO1xuICAgIGZvciAoaT0wOyBpPGFnZ3IubGVuZ3RoOyArK2kpIHtcbiAgICAgIGNlbGwuYWdnc1thZ2dyW2ldLm5hbWVdLmFkZCh4KTtcbiAgICB9XG4gIH1cbiAgY2VsbC5mbGFnIHw9IEZsYWdzLk1PRF9DRUxMO1xuICBpZiAodGhpcy5fb25fYWRkKSB0aGlzLl9vbl9hZGQoeCwgY2VsbCk7XG59O1xuXG5wcm90by5fcmVtID0gZnVuY3Rpb24oeCkge1xuICB2YXIgY2VsbCA9IHRoaXMuX2NlbGwoeCksXG4gICAgICBhZ2dyID0gdGhpcy5fYWdnciwgaTtcblxuICBjZWxsLm51bSAtPSAxO1xuICBpZiAoIXRoaXMuX2NvdW50KSB7IC8vIHNraXAgaWYgY291bnQtb25seVxuICAgIGlmIChjZWxsLmNvbGxlY3QpIGNlbGwuZGF0YS5yZW0oeCk7XG4gICAgZm9yIChpPTA7IGk8YWdnci5sZW5ndGg7ICsraSkge1xuICAgICAgY2VsbC5hZ2dzW2FnZ3JbaV0ubmFtZV0ucmVtKHgpO1xuICAgIH1cbiAgfVxuICBjZWxsLmZsYWcgfD0gRmxhZ3MuTU9EX0NFTEw7XG4gIGlmICh0aGlzLl9vbl9yZW0pIHRoaXMuX29uX3JlbSh4LCBjZWxsKTtcbn07XG5cbnByb3RvLl9tb2QgPSBmdW5jdGlvbihjdXJyLCBwcmV2KSB7XG4gIHZhciBjZWxsMCA9IHRoaXMuX2NlbGwocHJldiksXG4gICAgICBjZWxsMSA9IHRoaXMuX2NlbGwoY3VyciksXG4gICAgICBhZ2dyID0gdGhpcy5fYWdnciwgaTtcblxuICBpZiAoY2VsbDAgIT09IGNlbGwxKSB7XG4gICAgY2VsbDAubnVtIC09IDE7XG4gICAgY2VsbDEubnVtICs9IDE7XG4gICAgaWYgKGNlbGwwLmNvbGxlY3QpIGNlbGwwLmRhdGEucmVtKHByZXYpO1xuICAgIGlmIChjZWxsMS5jb2xsZWN0KSBjZWxsMS5kYXRhLmFkZChjdXJyKTtcbiAgfSBlbHNlIGlmIChjZWxsMC5jb2xsZWN0ICYmICF1dGlsLmlzT2JqZWN0KGN1cnIpKSB7XG4gICAgY2VsbDAuZGF0YS5yZW0ocHJldik7XG4gICAgY2VsbDAuZGF0YS5hZGQoY3Vycik7XG4gIH1cblxuICBmb3IgKGk9MDsgaTxhZ2dyLmxlbmd0aDsgKytpKSB7XG4gICAgY2VsbDAuYWdnc1thZ2dyW2ldLm5hbWVdLnJlbShwcmV2KTtcbiAgICBjZWxsMS5hZ2dzW2FnZ3JbaV0ubmFtZV0uYWRkKGN1cnIpO1xuICB9XG4gIGNlbGwwLmZsYWcgfD0gRmxhZ3MuTU9EX0NFTEw7XG4gIGNlbGwxLmZsYWcgfD0gRmxhZ3MuTU9EX0NFTEw7XG4gIGlmICh0aGlzLl9vbl9tb2QpIHRoaXMuX29uX21vZChjdXJyLCBwcmV2LCBjZWxsMCwgY2VsbDEpO1xufTtcblxucHJvdG8ucmVzdWx0ID0gZnVuY3Rpb24oKSB7XG4gIHZhciByZXN1bHQgPSBbXSxcbiAgICAgIGFnZ3IgPSB0aGlzLl9hZ2dyLFxuICAgICAgY2VsbCwgaSwgaztcblxuICBmb3IgKGsgaW4gdGhpcy5fY2VsbHMpIHtcbiAgICBjZWxsID0gdGhpcy5fY2VsbHNba107XG4gICAgaWYgKGNlbGwubnVtID4gMCkge1xuICAgICAgLy8gY29uc29saWRhdGUgY29sbGVjdG9yIHZhbHVlc1xuICAgICAgaWYgKGNlbGwuY29sbGVjdCkge1xuICAgICAgICBjZWxsLmRhdGEudmFsdWVzKCk7XG4gICAgICB9XG4gICAgICAvLyB1cGRhdGUgdHVwbGUgcHJvcGVydGllc1xuICAgICAgZm9yIChpPTA7IGk8YWdnci5sZW5ndGg7ICsraSkge1xuICAgICAgICBjZWxsLmFnZ3NbYWdncltpXS5uYW1lXS5zZXQoKTtcbiAgICAgIH1cbiAgICAgIC8vIGFkZCBvdXRwdXQgdHVwbGVcbiAgICAgIHJlc3VsdC5wdXNoKGNlbGwudHVwbGUpO1xuICAgIH0gZWxzZSB7XG4gICAgICBkZWxldGUgdGhpcy5fY2VsbHNba107XG4gICAgfVxuICAgIGNlbGwuZmxhZyA9IDA7XG4gIH1cblxuICB0aGlzLl9yZW1zID0gZmFsc2U7XG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5wcm90by5jaGFuZ2VzID0gZnVuY3Rpb24ob3V0cHV0KSB7XG4gIHZhciBjaGFuZ2VzID0gb3V0cHV0IHx8IHthZGQ6W10sIHJlbTpbXSwgbW9kOltdfSxcbiAgICAgIGFnZ3IgPSB0aGlzLl9hZ2dyLFxuICAgICAgY2VsbCwgZmxhZywgaSwgaztcblxuICBmb3IgKGsgaW4gdGhpcy5fY2VsbHMpIHtcbiAgICBjZWxsID0gdGhpcy5fY2VsbHNba107XG4gICAgZmxhZyA9IGNlbGwuZmxhZztcblxuICAgIC8vIGNvbnNvbGlkYXRlIGNvbGxlY3RvciB2YWx1ZXNcbiAgICBpZiAoY2VsbC5jb2xsZWN0KSB7XG4gICAgICBjZWxsLmRhdGEudmFsdWVzKCk7XG4gICAgfVxuXG4gICAgLy8gdXBkYXRlIHR1cGxlIHByb3BlcnRpZXNcbiAgICBmb3IgKGk9MDsgaTxhZ2dyLmxlbmd0aDsgKytpKSB7XG4gICAgICBjZWxsLmFnZ3NbYWdncltpXS5uYW1lXS5zZXQoKTtcbiAgICB9XG5cbiAgICAvLyBvcmdhbml6ZSBvdXRwdXQgdHVwbGVzXG4gICAgaWYgKGNlbGwubnVtIDw9IDApIHtcbiAgICAgIGNoYW5nZXMucmVtLnB1c2goY2VsbC50dXBsZSk7IC8vIGlmIChmbGFnID09PSBGbGFncy5NT0RfQ0VMTCkgeyA/P1xuICAgICAgZGVsZXRlIHRoaXMuX2NlbGxzW2tdO1xuICAgICAgaWYgKHRoaXMuX29uX2Ryb3ApIHRoaXMuX29uX2Ryb3AoY2VsbCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICh0aGlzLl9vbl9rZWVwKSB0aGlzLl9vbl9rZWVwKGNlbGwpO1xuICAgICAgaWYgKGZsYWcgJiBGbGFncy5BRERfQ0VMTCkge1xuICAgICAgICBjaGFuZ2VzLmFkZC5wdXNoKGNlbGwudHVwbGUpO1xuICAgICAgfSBlbHNlIGlmIChmbGFnICYgRmxhZ3MuTU9EX0NFTEwpIHtcbiAgICAgICAgY2hhbmdlcy5tb2QucHVzaChjZWxsLnR1cGxlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjZWxsLmZsYWcgPSAwO1xuICB9XG5cbiAgdGhpcy5fcmVtcyA9IGZhbHNlO1xuICByZXR1cm4gY2hhbmdlcztcbn07XG5cbnByb3RvLmV4ZWN1dGUgPSBmdW5jdGlvbihpbnB1dCkge1xuICByZXR1cm4gdGhpcy5jbGVhcigpLmluc2VydChpbnB1dCkucmVzdWx0KCk7XG59O1xuXG5wcm90by5pbnNlcnQgPSBmdW5jdGlvbihpbnB1dCkge1xuICB0aGlzLl9jb25zb2xpZGF0ZSgpO1xuICBmb3IgKHZhciBpPTA7IGk8aW5wdXQubGVuZ3RoOyArK2kpIHtcbiAgICB0aGlzLl9hZGQoaW5wdXRbaV0pO1xuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxucHJvdG8ucmVtb3ZlID0gZnVuY3Rpb24oaW5wdXQpIHtcbiAgaWYgKCF0aGlzLl9zdHJlYW0pIHtcbiAgICB0aHJvdyAnQWdncmVnYXRvciBub3QgY29uZmlndXJlZCBmb3Igc3RyZWFtaW5nIHJlbW92ZXMuJyArXG4gICAgICAnIENhbGwgc3RyZWFtKHRydWUpIHByaW9yIHRvIGNhbGxpbmcgc3VtbWFyaXplLic7XG4gIH1cbiAgZm9yICh2YXIgaT0wOyBpPGlucHV0Lmxlbmd0aDsgKytpKSB7XG4gICAgdGhpcy5fcmVtKGlucHV0W2ldKTtcbiAgfVxuICB0aGlzLl9yZW1zID0gdHJ1ZTtcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vLyBjb25zb2xpZGF0ZSByZW1vdmFsc1xucHJvdG8uX2NvbnNvbGlkYXRlID0gZnVuY3Rpb24oKSB7XG4gIGlmICghdGhpcy5fcmVtcykgcmV0dXJuO1xuICBmb3IgKHZhciBrIGluIHRoaXMuX2NlbGxzKSB7XG4gICAgaWYgKHRoaXMuX2NlbGxzW2tdLmNvbGxlY3QpIHtcbiAgICAgIHRoaXMuX2NlbGxzW2tdLmRhdGEudmFsdWVzKCk7XG4gICAgfVxuICB9XG4gIHRoaXMuX3JlbXMgPSBmYWxzZTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQWdncmVnYXRvcjsiLCJ2YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKTtcbnZhciBzdGF0cyA9IHJlcXVpcmUoJy4uL3N0YXRzJyk7XG5cbnZhciBSRU0gPSAnX19kbF9yZW1fXyc7XG5cbmZ1bmN0aW9uIENvbGxlY3RvcihrZXkpIHtcbiAgdGhpcy5fYWRkID0gW107XG4gIHRoaXMuX3JlbSA9IFtdO1xuICB0aGlzLl9rZXkgPSBrZXkgfHwgbnVsbDtcbiAgdGhpcy5fbGFzdCA9IG51bGw7XG59XG5cbnZhciBwcm90byA9IENvbGxlY3Rvci5wcm90b3R5cGU7XG5cbnByb3RvLmFkZCA9IGZ1bmN0aW9uKHYpIHtcbiAgdGhpcy5fYWRkLnB1c2godik7XG59O1xuXG5wcm90by5yZW0gPSBmdW5jdGlvbih2KSB7XG4gIHRoaXMuX3JlbS5wdXNoKHYpO1xufTtcblxucHJvdG8udmFsdWVzID0gZnVuY3Rpb24oKSB7XG4gIHRoaXMuX2dldCA9IG51bGw7XG4gIGlmICh0aGlzLl9yZW0ubGVuZ3RoID09PSAwKSByZXR1cm4gdGhpcy5fYWRkO1xuXG4gIHZhciBhID0gdGhpcy5fYWRkLFxuICAgICAgciA9IHRoaXMuX3JlbSxcbiAgICAgIGsgPSB0aGlzLl9rZXksXG4gICAgICB4ID0gQXJyYXkoYS5sZW5ndGggLSByLmxlbmd0aCksXG4gICAgICBpLCBqLCBuLCBtO1xuXG4gIGlmICghdXRpbC5pc09iamVjdChyWzBdKSkge1xuICAgIC8vIHByb2Nlc3NpbmcgcmF3IHZhbHVlc1xuICAgIG0gPSBzdGF0cy5jb3VudC5tYXAocik7XG4gICAgZm9yIChpPTAsIGo9MCwgbj1hLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICAgIGlmIChtW2FbaV1dID4gMCkge1xuICAgICAgICBtW2FbaV1dIC09IDE7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB4W2orK10gPSBhW2ldO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChrKSB7XG4gICAgLy8gaGFzIHVuaXF1ZSBrZXkgZmllbGQsIHNvIHVzZSB0aGF0XG4gICAgbSA9IHV0aWwudG9NYXAociwgayk7XG4gICAgZm9yIChpPTAsIGo9MCwgbj1hLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICAgIGlmICghbS5oYXNPd25Qcm9wZXJ0eShrKGFbaV0pKSkgeyB4W2orK10gPSBhW2ldOyB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIG5vIHVuaXF1ZSBrZXksIG1hcmsgdHVwbGVzIGRpcmVjdGx5XG4gICAgZm9yIChpPTAsIG49ci5sZW5ndGg7IGk8bjsgKytpKSB7XG4gICAgICByW2ldW1JFTV0gPSAxO1xuICAgIH1cbiAgICBmb3IgKGk9MCwgaj0wLCBuPWEubGVuZ3RoOyBpPG47ICsraSkge1xuICAgICAgaWYgKCFhW2ldW1JFTV0pIHsgeFtqKytdID0gYVtpXTsgfVxuICAgIH1cbiAgICBmb3IgKGk9MCwgbj1yLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICAgIGRlbGV0ZSByW2ldW1JFTV07XG4gICAgfVxuICB9XG5cbiAgdGhpcy5fcmVtID0gW107XG4gIHJldHVybiAodGhpcy5fYWRkID0geCk7XG59O1xuXG4vLyBtZW1vaXppbmcgc3RhdGlzdGljcyBtZXRob2RzXG5cbnByb3RvLmV4dGVudCA9IGZ1bmN0aW9uKGdldCkge1xuICBpZiAodGhpcy5fZ2V0ICE9PSBnZXQgfHwgIXRoaXMuX2V4dCkge1xuICAgIHZhciB2ID0gdGhpcy52YWx1ZXMoKSxcbiAgICAgICAgaSA9IHN0YXRzLmV4dGVudC5pbmRleCh2LCBnZXQpO1xuICAgIHRoaXMuX2V4dCA9IFt2W2lbMF1dLCB2W2lbMV1dXTtcbiAgICB0aGlzLl9nZXQgPSBnZXQ7ICAgIFxuICB9XG4gIHJldHVybiB0aGlzLl9leHQ7XG59O1xuXG5wcm90by5hcmdtaW4gPSBmdW5jdGlvbihnZXQpIHtcbiAgcmV0dXJuIHRoaXMuZXh0ZW50KGdldClbMF07XG59O1xuXG5wcm90by5hcmdtYXggPSBmdW5jdGlvbihnZXQpIHtcbiAgcmV0dXJuIHRoaXMuZXh0ZW50KGdldClbMV07XG59O1xuXG5wcm90by5taW4gPSBmdW5jdGlvbihnZXQpIHtcbiAgdmFyIG0gPSB0aGlzLmV4dGVudChnZXQpWzBdO1xuICByZXR1cm4gbSA/IGdldChtKSA6ICtJbmZpbml0eTtcbn07XG5cbnByb3RvLm1heCA9IGZ1bmN0aW9uKGdldCkge1xuICB2YXIgbSA9IHRoaXMuZXh0ZW50KGdldClbMV07XG4gIHJldHVybiBtID8gZ2V0KG0pIDogLUluZmluaXR5O1xufTtcblxucHJvdG8ucXVhcnRpbGUgPSBmdW5jdGlvbihnZXQpIHtcbiAgaWYgKHRoaXMuX2dldCAhPT0gZ2V0IHx8ICF0aGlzLl9xKSB7XG4gICAgdGhpcy5fcSA9IHN0YXRzLnF1YXJ0aWxlKHRoaXMudmFsdWVzKCksIGdldCk7XG4gICAgdGhpcy5fZ2V0ID0gZ2V0OyAgICBcbiAgfVxuICByZXR1cm4gdGhpcy5fcTtcbn07XG5cbnByb3RvLnExID0gZnVuY3Rpb24oZ2V0KSB7XG4gIHJldHVybiB0aGlzLnF1YXJ0aWxlKGdldClbMF07XG59O1xuXG5wcm90by5xMiA9IGZ1bmN0aW9uKGdldCkge1xuICByZXR1cm4gdGhpcy5xdWFydGlsZShnZXQpWzFdO1xufTtcblxucHJvdG8ucTMgPSBmdW5jdGlvbihnZXQpIHtcbiAgcmV0dXJuIHRoaXMucXVhcnRpbGUoZ2V0KVsyXTtcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQ29sbGVjdG9yO1xuIiwidmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG52YXIgQWdncmVnYXRvciA9IHJlcXVpcmUoJy4vYWdncmVnYXRvcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKCkge1xuICAvLyBmbGF0dGVuIGFyZ3VtZW50cyBpbnRvIGEgc2luZ2xlIGFycmF5XG4gIHZhciBhcmdzID0gW10ucmVkdWNlLmNhbGwoYXJndW1lbnRzLCBmdW5jdGlvbihhLCB4KSB7XG4gICAgcmV0dXJuIGEuY29uY2F0KHV0aWwuYXJyYXkoeCkpO1xuICB9LCBbXSk7XG4gIC8vIGNyZWF0ZSBhbmQgcmV0dXJuIGFuIGFnZ3JlZ2F0b3JcbiAgcmV0dXJuIG5ldyBBZ2dyZWdhdG9yKClcbiAgICAuZ3JvdXBieShhcmdzKVxuICAgIC5zdW1tYXJpemUoeycqJzondmFsdWVzJ30pO1xufTtcbiIsInZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xuXG52YXIgdHlwZXMgPSB7XG4gICd2YWx1ZXMnOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAndmFsdWVzJyxcbiAgICBpbml0OiAnY2VsbC5jb2xsZWN0ID0gdHJ1ZTsnLFxuICAgIHNldDogICdjZWxsLmRhdGEudmFsdWVzKCknLCBpZHg6IC0xXG4gIH0pLFxuICAnY291bnQnOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAnY291bnQnLFxuICAgIHNldDogICdjZWxsLm51bSdcbiAgfSksXG4gICdtaXNzaW5nJzogbWVhc3VyZSh7XG4gICAgbmFtZTogJ21pc3NpbmcnLFxuICAgIHNldDogICd0aGlzLm1pc3NpbmcnXG4gIH0pLFxuICAndmFsaWQnOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAndmFsaWQnLFxuICAgIHNldDogICd0aGlzLnZhbGlkJ1xuICB9KSxcbiAgJ3N1bSc6IG1lYXN1cmUoe1xuICAgIG5hbWU6ICdzdW0nLFxuICAgIGluaXQ6ICd0aGlzLnN1bSA9IDA7JyxcbiAgICBhZGQ6ICAndGhpcy5zdW0gKz0gdjsnLFxuICAgIHJlbTogICd0aGlzLnN1bSAtPSB2OycsXG4gICAgc2V0OiAgJ3RoaXMuc3VtJ1xuICB9KSxcbiAgJ21lYW4nOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAnbWVhbicsXG4gICAgaW5pdDogJ3RoaXMubWVhbiA9IDA7JyxcbiAgICBhZGQ6ICAndmFyIGQgPSB2IC0gdGhpcy5tZWFuOyB0aGlzLm1lYW4gKz0gZCAvIHRoaXMudmFsaWQ7JyxcbiAgICByZW06ICAndmFyIGQgPSB2IC0gdGhpcy5tZWFuOyB0aGlzLm1lYW4gLT0gdGhpcy52YWxpZCA/IGQgLyB0aGlzLnZhbGlkIDogdGhpcy5tZWFuOycsXG4gICAgc2V0OiAgJ3RoaXMubWVhbidcbiAgfSksXG4gICdhdmVyYWdlJzogbWVhc3VyZSh7XG4gICAgbmFtZTogJ2F2ZXJhZ2UnLFxuICAgIHNldDogICd0aGlzLm1lYW4nLFxuICAgIHJlcTogIFsnbWVhbiddLCBpZHg6IDFcbiAgfSksXG4gICd2YXJpYW5jZSc6IG1lYXN1cmUoe1xuICAgIG5hbWU6ICd2YXJpYW5jZScsXG4gICAgaW5pdDogJ3RoaXMuZGV2ID0gMDsnLFxuICAgIGFkZDogICd0aGlzLmRldiArPSBkICogKHYgLSB0aGlzLm1lYW4pOycsXG4gICAgcmVtOiAgJ3RoaXMuZGV2IC09IGQgKiAodiAtIHRoaXMubWVhbik7JyxcbiAgICBzZXQ6ICAndGhpcy52YWxpZCA+IDEgPyB0aGlzLmRldiAvICh0aGlzLnZhbGlkLTEpIDogMCcsXG4gICAgcmVxOiAgWydtZWFuJ10sIGlkeDogMVxuICB9KSxcbiAgJ3ZhcmlhbmNlcCc6IG1lYXN1cmUoe1xuICAgIG5hbWU6ICd2YXJpYW5jZXAnLFxuICAgIHNldDogICd0aGlzLnZhbGlkID4gMSA/IHRoaXMuZGV2IC8gdGhpcy52YWxpZCA6IDAnLFxuICAgIHJlcTogIFsndmFyaWFuY2UnXSwgaWR4OiAyXG4gIH0pLFxuICAnc3RkZXYnOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAnc3RkZXYnLFxuICAgIHNldDogICd0aGlzLnZhbGlkID4gMSA/IE1hdGguc3FydCh0aGlzLmRldiAvICh0aGlzLnZhbGlkLTEpKSA6IDAnLFxuICAgIHJlcTogIFsndmFyaWFuY2UnXSwgaWR4OiAyXG4gIH0pLFxuICAnc3RkZXZwJzogbWVhc3VyZSh7XG4gICAgbmFtZTogJ3N0ZGV2cCcsXG4gICAgc2V0OiAgJ3RoaXMudmFsaWQgPiAxID8gTWF0aC5zcXJ0KHRoaXMuZGV2IC8gdGhpcy52YWxpZCkgOiAwJyxcbiAgICByZXE6ICBbJ3ZhcmlhbmNlJ10sIGlkeDogMlxuICB9KSxcbiAgJ21lZGlhbic6IG1lYXN1cmUoe1xuICAgIG5hbWU6ICdtZWRpYW4nLFxuICAgIHNldDogICdjZWxsLmRhdGEucTIodGhpcy5nZXQpJyxcbiAgICByZXE6ICBbJ3ZhbHVlcyddLCBpZHg6IDNcbiAgfSksXG4gICdxMSc6IG1lYXN1cmUoe1xuICAgIG5hbWU6ICdxMScsXG4gICAgc2V0OiAgJ2NlbGwuZGF0YS5xMSh0aGlzLmdldCknLFxuICAgIHJlcTogIFsndmFsdWVzJ10sIGlkeDogM1xuICB9KSxcbiAgJ3EzJzogbWVhc3VyZSh7XG4gICAgbmFtZTogJ3EzJyxcbiAgICBzZXQ6ICAnY2VsbC5kYXRhLnEzKHRoaXMuZ2V0KScsXG4gICAgcmVxOiAgWyd2YWx1ZXMnXSwgaWR4OiAzXG4gIH0pLFxuICAnZGlzdGluY3QnOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAnZGlzdGluY3QnLFxuICAgIHNldDogICd0aGlzLmRpc3RpbmN0KGNlbGwuZGF0YS52YWx1ZXMoKSwgdGhpcy5nZXQpJyxcbiAgICByZXE6ICBbJ3ZhbHVlcyddLCBpZHg6IDNcbiAgfSksXG4gICdhcmdtaW4nOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAnYXJnbWluJyxcbiAgICBhZGQ6ICAnaWYgKHYgPCB0aGlzLm1pbikgdGhpcy5hcmdtaW4gPSB0OycsXG4gICAgcmVtOiAgJ2lmICh2IDw9IHRoaXMubWluKSB0aGlzLmFyZ21pbiA9IG51bGw7JyxcbiAgICBzZXQ6ICAndGhpcy5hcmdtaW4gPSB0aGlzLmFyZ21pbiB8fCBjZWxsLmRhdGEuYXJnbWluKHRoaXMuZ2V0KScsXG4gICAgcmVxOiAgWydtaW4nXSwgc3RyOiBbJ3ZhbHVlcyddLCBpZHg6IDNcbiAgfSksXG4gICdhcmdtYXgnOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAnYXJnbWF4JyxcbiAgICBhZGQ6ICAnaWYgKHYgPiB0aGlzLm1heCkgdGhpcy5hcmdtYXggPSB0OycsXG4gICAgcmVtOiAgJ2lmICh2ID49IHRoaXMubWF4KSB0aGlzLmFyZ21heCA9IG51bGw7JyxcbiAgICBzZXQ6ICAndGhpcy5hcmdtYXggPSB0aGlzLmFyZ21heCB8fCBjZWxsLmRhdGEuYXJnbWF4KHRoaXMuZ2V0KScsXG4gICAgcmVxOiAgWydtYXgnXSwgc3RyOiBbJ3ZhbHVlcyddLCBpZHg6IDNcbiAgfSksXG4gICdtaW4nOiBtZWFzdXJlKHtcbiAgICBuYW1lOiAnbWluJyxcbiAgICBpbml0OiAndGhpcy5taW4gPSArSW5maW5pdHk7JyxcbiAgICBhZGQ6ICAnaWYgKHYgPCB0aGlzLm1pbikgdGhpcy5taW4gPSB2OycsXG4gICAgcmVtOiAgJ2lmICh2IDw9IHRoaXMubWluKSB0aGlzLm1pbiA9IE5hTjsnLFxuICAgIHNldDogICd0aGlzLm1pbiA9IChpc05hTih0aGlzLm1pbikgPyBjZWxsLmRhdGEubWluKHRoaXMuZ2V0KSA6IHRoaXMubWluKScsXG4gICAgc3RyOiAgWyd2YWx1ZXMnXSwgaWR4OiA0XG4gIH0pLFxuICAnbWF4JzogbWVhc3VyZSh7XG4gICAgbmFtZTogJ21heCcsXG4gICAgaW5pdDogJ3RoaXMubWF4ID0gLUluZmluaXR5OycsXG4gICAgYWRkOiAgJ2lmICh2ID4gdGhpcy5tYXgpIHRoaXMubWF4ID0gdjsnLFxuICAgIHJlbTogICdpZiAodiA+PSB0aGlzLm1heCkgdGhpcy5tYXggPSBOYU47JyxcbiAgICBzZXQ6ICAndGhpcy5tYXggPSAoaXNOYU4odGhpcy5tYXgpID8gY2VsbC5kYXRhLm1heCh0aGlzLmdldCkgOiB0aGlzLm1heCknLFxuICAgIHN0cjogIFsndmFsdWVzJ10sIGlkeDogNFxuICB9KSxcbiAgJ21vZGVza2V3JzogbWVhc3VyZSh7XG4gICAgbmFtZTogJ21vZGVza2V3JyxcbiAgICBzZXQ6ICAndGhpcy5kZXY9PT0wID8gMCA6ICh0aGlzLm1lYW4gLSBjZWxsLmRhdGEucTIodGhpcy5nZXQpKSAvIE1hdGguc3FydCh0aGlzLmRldi8odGhpcy52YWxpZC0xKSknLFxuICAgIHJlcTogIFsnbWVhbicsICdzdGRldicsICdtZWRpYW4nXSwgaWR4OiA1XG4gIH0pXG59O1xuXG5mdW5jdGlvbiBtZWFzdXJlKGJhc2UpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKG91dCkge1xuICAgIHZhciBtID0gdXRpbC5leHRlbmQoe2luaXQ6JycsIGFkZDonJywgcmVtOicnLCBpZHg6MH0sIGJhc2UpO1xuICAgIG0ub3V0ID0gb3V0IHx8IGJhc2UubmFtZTtcbiAgICByZXR1cm4gbTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZShhZ2csIHN0cmVhbSkge1xuICBmdW5jdGlvbiBjb2xsZWN0KG0sIGEpIHtcbiAgICBmdW5jdGlvbiBoZWxwZXIocikgeyBpZiAoIW1bcl0pIGNvbGxlY3QobSwgbVtyXSA9IHR5cGVzW3JdKCkpOyB9XG4gICAgaWYgKGEucmVxKSBhLnJlcS5mb3JFYWNoKGhlbHBlcik7XG4gICAgaWYgKHN0cmVhbSAmJiBhLnN0cikgYS5zdHIuZm9yRWFjaChoZWxwZXIpO1xuICAgIHJldHVybiBtO1xuICB9XG4gIHZhciBtYXAgPSBhZ2cucmVkdWNlKFxuICAgIGNvbGxlY3QsXG4gICAgYWdnLnJlZHVjZShmdW5jdGlvbihtLCBhKSB7IHJldHVybiAobVthLm5hbWVdID0gYSwgbSk7IH0sIHt9KVxuICApO1xuICByZXR1cm4gdXRpbC52YWxzKG1hcCkuc29ydChmdW5jdGlvbihhLCBiKSB7IHJldHVybiBhLmlkeCAtIGIuaWR4OyB9KTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlKGFnZywgc3RyZWFtLCBhY2Nlc3NvciwgbXV0YXRvcikge1xuICB2YXIgYWxsID0gcmVzb2x2ZShhZ2csIHN0cmVhbSksXG4gICAgICBjdHIgPSAndGhpcy5jZWxsID0gY2VsbDsgdGhpcy50dXBsZSA9IHQ7IHRoaXMudmFsaWQgPSAwOyB0aGlzLm1pc3NpbmcgPSAwOycsXG4gICAgICBhZGQgPSAnaWYgKHY9PW51bGwpIHRoaXMubWlzc2luZysrOyBpZiAoIXRoaXMuaXNWYWxpZCh2KSkgcmV0dXJuOyArK3RoaXMudmFsaWQ7JyxcbiAgICAgIHJlbSA9ICdpZiAodj09bnVsbCkgdGhpcy5taXNzaW5nLS07IGlmICghdGhpcy5pc1ZhbGlkKHYpKSByZXR1cm47IC0tdGhpcy52YWxpZDsnLFxuICAgICAgc2V0ID0gJ3ZhciB0ID0gdGhpcy50dXBsZTsgdmFyIGNlbGwgPSB0aGlzLmNlbGw7JztcblxuICBhbGwuZm9yRWFjaChmdW5jdGlvbihhKSB7XG4gICAgaWYgKGEuaWR4IDwgMCkge1xuICAgICAgY3RyID0gYS5pbml0ICsgY3RyO1xuICAgICAgYWRkID0gYS5hZGQgKyBhZGQ7XG4gICAgICByZW0gPSBhLnJlbSArIHJlbTtcbiAgICB9IGVsc2Uge1xuICAgICAgY3RyICs9IGEuaW5pdDtcbiAgICAgIGFkZCArPSBhLmFkZDtcbiAgICAgIHJlbSArPSBhLnJlbTtcbiAgICB9XG4gIH0pO1xuICBhZ2cuc2xpY2UoKVxuICAgIC5zb3J0KGZ1bmN0aW9uKGEsIGIpIHsgcmV0dXJuIGEuaWR4IC0gYi5pZHg7IH0pXG4gICAgLmZvckVhY2goZnVuY3Rpb24oYSkge1xuICAgICAgc2V0ICs9ICd0aGlzLmFzc2lnbih0LFxcJycrYS5vdXQrJ1xcJywnK2Euc2V0KycpOyc7XG4gICAgfSk7XG4gIHNldCArPSAncmV0dXJuIHQ7JztcblxuICAvKiBqc2hpbnQgZXZpbDogdHJ1ZSAqL1xuICBjdHIgPSBGdW5jdGlvbignY2VsbCcsICd0JywgY3RyKTtcbiAgY3RyLnByb3RvdHlwZS5hc3NpZ24gPSBtdXRhdG9yO1xuICBjdHIucHJvdG90eXBlLmFkZCA9IEZ1bmN0aW9uKCd0JywgJ3ZhciB2ID0gdGhpcy5nZXQodCk7JyArIGFkZCk7XG4gIGN0ci5wcm90b3R5cGUucmVtID0gRnVuY3Rpb24oJ3QnLCAndmFyIHYgPSB0aGlzLmdldCh0KTsnICsgcmVtKTtcbiAgY3RyLnByb3RvdHlwZS5zZXQgPSBGdW5jdGlvbihzZXQpO1xuICBjdHIucHJvdG90eXBlLmdldCA9IGFjY2Vzc29yO1xuICBjdHIucHJvdG90eXBlLmRpc3RpbmN0ID0gcmVxdWlyZSgnLi4vc3RhdHMnKS5jb3VudC5kaXN0aW5jdDtcbiAgY3RyLnByb3RvdHlwZS5pc1ZhbGlkID0gdXRpbC5pc1ZhbGlkO1xuICBjdHIuZmllbGRzID0gYWdnLm1hcCh1dGlsLiQoJ291dCcpKTtcbiAgcmV0dXJuIGN0cjtcbn1cblxudHlwZXMuY3JlYXRlID0gY3JlYXRlO1xubW9kdWxlLmV4cG9ydHMgPSB0eXBlczsiLCJ2YXIgdXRpbCA9IHJlcXVpcmUoJy4uL3V0aWwnKSxcbiAgICB0aW1lID0gcmVxdWlyZSgnLi4vdGltZScpLFxuICAgIEVQU0lMT04gPSAxZS0xNTtcblxuZnVuY3Rpb24gYmlucyhvcHQpIHtcbiAgaWYgKCFvcHQpIHsgdGhyb3cgRXJyb3IoXCJNaXNzaW5nIGJpbm5pbmcgb3B0aW9ucy5cIik7IH1cblxuICAvLyBkZXRlcm1pbmUgcmFuZ2VcbiAgdmFyIG1heGIgPSBvcHQubWF4YmlucyB8fCAxNSxcbiAgICAgIGJhc2UgPSBvcHQuYmFzZSB8fCAxMCxcbiAgICAgIGxvZ2IgPSBNYXRoLmxvZyhiYXNlKSxcbiAgICAgIGRpdiA9IG9wdC5kaXYgfHwgWzUsIDJdLCAgICAgIFxuICAgICAgbWluID0gb3B0Lm1pbixcbiAgICAgIG1heCA9IG9wdC5tYXgsXG4gICAgICBzcGFuID0gbWF4IC0gbWluLFxuICAgICAgc3RlcCwgbGV2ZWwsIG1pbnN0ZXAsIHByZWNpc2lvbiwgdiwgaSwgZXBzO1xuXG4gIGlmIChvcHQuc3RlcCkge1xuICAgIC8vIGlmIHN0ZXAgc2l6ZSBpcyBleHBsaWNpdGx5IGdpdmVuLCB1c2UgdGhhdFxuICAgIHN0ZXAgPSBvcHQuc3RlcDtcbiAgfSBlbHNlIGlmIChvcHQuc3RlcHMpIHtcbiAgICAvLyBpZiBwcm92aWRlZCwgbGltaXQgY2hvaWNlIHRvIGFjY2VwdGFibGUgc3RlcCBzaXplc1xuICAgIHN0ZXAgPSBvcHQuc3RlcHNbTWF0aC5taW4oXG4gICAgICBvcHQuc3RlcHMubGVuZ3RoIC0gMSxcbiAgICAgIGJpc2VjdChvcHQuc3RlcHMsIHNwYW4vbWF4YiwgMCwgb3B0LnN0ZXBzLmxlbmd0aClcbiAgICApXTtcbiAgfSBlbHNlIHtcbiAgICAvLyBlbHNlIHVzZSBzcGFuIHRvIGRldGVybWluZSBzdGVwIHNpemVcbiAgICBsZXZlbCA9IE1hdGguY2VpbChNYXRoLmxvZyhtYXhiKSAvIGxvZ2IpO1xuICAgIG1pbnN0ZXAgPSBvcHQubWluc3RlcCB8fCAwO1xuICAgIHN0ZXAgPSBNYXRoLm1heChcbiAgICAgIG1pbnN0ZXAsXG4gICAgICBNYXRoLnBvdyhiYXNlLCBNYXRoLnJvdW5kKE1hdGgubG9nKHNwYW4pIC8gbG9nYikgLSBsZXZlbClcbiAgICApO1xuICAgIFxuICAgIC8vIGluY3JlYXNlIHN0ZXAgc2l6ZSBpZiB0b28gbWFueSBiaW5zXG4gICAgZG8geyBzdGVwICo9IGJhc2U7IH0gd2hpbGUgKE1hdGguY2VpbChzcGFuL3N0ZXApID4gbWF4Yik7XG5cbiAgICAvLyBkZWNyZWFzZSBzdGVwIHNpemUgaWYgYWxsb3dlZFxuICAgIGZvciAoaT0wOyBpPGRpdi5sZW5ndGg7ICsraSkge1xuICAgICAgdiA9IHN0ZXAgLyBkaXZbaV07XG4gICAgICBpZiAodiA+PSBtaW5zdGVwICYmIHNwYW4gLyB2IDw9IG1heGIpIHN0ZXAgPSB2O1xuICAgIH1cbiAgfVxuXG4gIC8vIHVwZGF0ZSBwcmVjaXNpb24sIG1pbiBhbmQgbWF4XG4gIHYgPSBNYXRoLmxvZyhzdGVwKTtcbiAgcHJlY2lzaW9uID0gdiA+PSAwID8gMCA6IH5+KC12IC8gbG9nYikgKyAxO1xuICBlcHMgPSBNYXRoLnBvdyhiYXNlLCAtcHJlY2lzaW9uIC0gMSk7XG4gIG1pbiA9IE1hdGgubWluKG1pbiwgTWF0aC5mbG9vcihtaW4gLyBzdGVwICsgZXBzKSAqIHN0ZXApO1xuICBtYXggPSBNYXRoLmNlaWwobWF4IC8gc3RlcCkgKiBzdGVwO1xuXG4gIHJldHVybiB7XG4gICAgc3RhcnQ6IG1pbixcbiAgICBzdG9wOiAgbWF4LFxuICAgIHN0ZXA6ICBzdGVwLFxuICAgIHVuaXQ6ICB7cHJlY2lzaW9uOiBwcmVjaXNpb259LFxuICAgIHZhbHVlOiB2YWx1ZSxcbiAgICBpbmRleDogaW5kZXhcbiAgfTtcbn1cblxuZnVuY3Rpb24gYmlzZWN0KGEsIHgsIGxvLCBoaSkge1xuICB3aGlsZSAobG8gPCBoaSkge1xuICAgIHZhciBtaWQgPSBsbyArIGhpID4+PiAxO1xuICAgIGlmICh1dGlsLmNtcChhW21pZF0sIHgpIDwgMCkgeyBsbyA9IG1pZCArIDE7IH1cbiAgICBlbHNlIHsgaGkgPSBtaWQ7IH1cbiAgfVxuICByZXR1cm4gbG87XG59XG5cbmZ1bmN0aW9uIHZhbHVlKHYpIHtcbiAgcmV0dXJuIHRoaXMuc3RlcCAqIE1hdGguZmxvb3IodiAvIHRoaXMuc3RlcCArIEVQU0lMT04pO1xufVxuXG5mdW5jdGlvbiBpbmRleCh2KSB7XG4gIHJldHVybiBNYXRoLmZsb29yKCh2IC0gdGhpcy5zdGFydCkgLyB0aGlzLnN0ZXAgKyBFUFNJTE9OKTtcbn1cblxuZnVuY3Rpb24gZGF0ZV92YWx1ZSh2KSB7XG4gIHJldHVybiB0aGlzLnVuaXQuZGF0ZSh2YWx1ZS5jYWxsKHRoaXMsIHYpKTtcbn1cblxuZnVuY3Rpb24gZGF0ZV9pbmRleCh2KSB7XG4gIHJldHVybiBpbmRleC5jYWxsKHRoaXMsIHRoaXMudW5pdC51bml0KHYpKTtcbn1cblxuYmlucy5kYXRlID0gZnVuY3Rpb24ob3B0KSB7XG4gIGlmICghb3B0KSB7IHRocm93IEVycm9yKFwiTWlzc2luZyBkYXRlIGJpbm5pbmcgb3B0aW9ucy5cIik7IH1cblxuICAvLyBmaW5kIHRpbWUgc3RlcCwgdGhlbiBiaW5cbiAgdmFyIHVuaXRzID0gb3B0LnV0YyA/IHRpbWUudXRjIDogdGltZSxcbiAgICAgIGRtaW4gPSBvcHQubWluLFxuICAgICAgZG1heCA9IG9wdC5tYXgsXG4gICAgICBtYXhiID0gb3B0Lm1heGJpbnMgfHwgMjAsXG4gICAgICBtaW5iID0gb3B0Lm1pbmJpbnMgfHwgNCxcbiAgICAgIHNwYW4gPSAoK2RtYXgpIC0gKCtkbWluKSxcbiAgICAgIHVuaXQgPSBvcHQudW5pdCA/IHVuaXRzW29wdC51bml0XSA6IHVuaXRzLmZpbmQoc3BhbiwgbWluYiwgbWF4YiksXG4gICAgICBzcGVjID0gYmlucyh7XG4gICAgICAgIG1pbjogICAgIHVuaXQubWluICE9IG51bGwgPyB1bml0Lm1pbiA6IHVuaXQudW5pdChkbWluKSxcbiAgICAgICAgbWF4OiAgICAgdW5pdC5tYXggIT0gbnVsbCA/IHVuaXQubWF4IDogdW5pdC51bml0KGRtYXgpLFxuICAgICAgICBtYXhiaW5zOiBtYXhiLFxuICAgICAgICBtaW5zdGVwOiB1bml0Lm1pbnN0ZXAsXG4gICAgICAgIHN0ZXBzOiAgIHVuaXQuc3RlcFxuICAgICAgfSk7XG5cbiAgc3BlYy51bml0ID0gdW5pdDtcbiAgc3BlYy5pbmRleCA9IGRhdGVfaW5kZXg7XG4gIGlmICghb3B0LnJhdykgc3BlYy52YWx1ZSA9IGRhdGVfdmFsdWU7XG4gIHJldHVybiBzcGVjO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBiaW5zO1xuIiwidmFyIGJpbnMgPSByZXF1aXJlKCcuL2JpbnMnKSxcbiAgICBnZW4gID0gcmVxdWlyZSgnLi4vZ2VuZXJhdGUnKSxcbiAgICB0eXBlID0gcmVxdWlyZSgnLi4vaW1wb3J0L3R5cGUnKSxcbiAgICB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpLFxuICAgIHN0YXRzID0gcmVxdWlyZSgnLi4vc3RhdHMnKTtcblxudmFyIHF0eXBlID0ge1xuICAnaW50ZWdlcic6IDEsXG4gICdudW1iZXInOiAxLFxuICAnZGF0ZSc6IDFcbn07XG5cbmZ1bmN0aW9uICRiaW4odmFsdWVzLCBmLCBvcHQpIHtcbiAgb3B0ID0gb3B0aW9ucyh2YWx1ZXMsIGYsIG9wdCk7XG4gIHZhciBiID0gc3BlYyhvcHQpO1xuICByZXR1cm4gIWIgPyAob3B0LmFjY2Vzc29yIHx8IHV0aWwuaWRlbnRpdHkpIDpcbiAgICB1dGlsLiRmdW5jKCdiaW4nLCBiLnVuaXQudW5pdCA/XG4gICAgICBmdW5jdGlvbih4KSB7IHJldHVybiBiLnZhbHVlKGIudW5pdC51bml0KHgpKTsgfSA6XG4gICAgICBmdW5jdGlvbih4KSB7IHJldHVybiBiLnZhbHVlKHgpOyB9XG4gICAgKShvcHQuYWNjZXNzb3IpO1xufVxuXG5mdW5jdGlvbiBoaXN0b2dyYW0odmFsdWVzLCBmLCBvcHQpIHtcbiAgb3B0ID0gb3B0aW9ucyh2YWx1ZXMsIGYsIG9wdCk7XG4gIHZhciBiID0gc3BlYyhvcHQpO1xuICByZXR1cm4gYiA/XG4gICAgbnVtZXJpY2FsKHZhbHVlcywgb3B0LmFjY2Vzc29yLCBiKSA6XG4gICAgY2F0ZWdvcmljYWwodmFsdWVzLCBvcHQuYWNjZXNzb3IsIG9wdCAmJiBvcHQuc29ydCk7XG59XG5cbmZ1bmN0aW9uIHNwZWMob3B0KSB7XG4gIHZhciB0ID0gb3B0LnR5cGUsIGIgPSBudWxsO1xuICBpZiAodCA9PSBudWxsIHx8IHF0eXBlW3RdKSB7XG4gICAgaWYgKHQgPT09ICdpbnRlZ2VyJyAmJiBvcHQubWluc3RlcCA9PSBudWxsKSBvcHQubWluc3RlcCA9IDE7XG4gICAgYiA9ICh0ID09PSAnZGF0ZScpID8gYmlucy5kYXRlKG9wdCkgOiBiaW5zKG9wdCk7XG4gIH1cbiAgcmV0dXJuIGI7XG59XG5cbmZ1bmN0aW9uIG9wdGlvbnMoKSB7XG4gIHZhciBhID0gYXJndW1lbnRzLFxuICAgICAgaSA9IDAsXG4gICAgICB2YWx1ZXMgPSB1dGlsLmlzQXJyYXkoYVtpXSkgPyBhW2krK10gOiBudWxsLFxuICAgICAgZiA9IHV0aWwuaXNGdW5jdGlvbihhW2ldKSB8fCB1dGlsLmlzU3RyaW5nKGFbaV0pID8gdXRpbC4kKGFbaSsrXSkgOiBudWxsLFxuICAgICAgb3B0ID0gdXRpbC5leHRlbmQoe30sIGFbaV0pO1xuICBcbiAgaWYgKHZhbHVlcykge1xuICAgIG9wdC50eXBlID0gb3B0LnR5cGUgfHwgdHlwZSh2YWx1ZXMsIGYpO1xuICAgIGlmIChxdHlwZVtvcHQudHlwZV0pIHtcbiAgICAgIHZhciBleHQgPSBzdGF0cy5leHRlbnQodmFsdWVzLCBmKTtcbiAgICAgIG9wdCA9IHV0aWwuZXh0ZW5kKHttaW46IGV4dFswXSwgbWF4OiBleHRbMV19LCBvcHQpO1xuICAgIH1cbiAgfVxuICBpZiAoZikgeyBvcHQuYWNjZXNzb3IgPSBmOyB9XG4gIHJldHVybiBvcHQ7XG59XG5cbmZ1bmN0aW9uIG51bWVyaWNhbCh2YWx1ZXMsIGYsIGIpIHtcbiAgdmFyIGggPSBnZW4ucmFuZ2UoYi5zdGFydCwgYi5zdG9wICsgYi5zdGVwLzIsIGIuc3RlcClcbiAgICAubWFwKGZ1bmN0aW9uKHYpIHsgcmV0dXJuIHt2YWx1ZTogYi52YWx1ZSh2KSwgY291bnQ6IDB9OyB9KTtcblxuICBmb3IgKHZhciBpPTAsIHYsIGo7IGk8dmFsdWVzLmxlbmd0aDsgKytpKSB7XG4gICAgdiA9IGYgPyBmKHZhbHVlc1tpXSkgOiB2YWx1ZXNbaV07XG4gICAgaWYgKHV0aWwuaXNWYWxpZCh2KSkge1xuICAgICAgaiA9IGIuaW5kZXgodik7XG4gICAgICBpZiAoaiA8IDAgfHwgaiA+PSBoLmxlbmd0aCB8fCAhaXNGaW5pdGUoaikpIGNvbnRpbnVlO1xuICAgICAgaFtqXS5jb3VudCArPSAxO1xuICAgIH1cbiAgfVxuICBoLmJpbnMgPSBiO1xuICByZXR1cm4gaDtcbn1cblxuZnVuY3Rpb24gY2F0ZWdvcmljYWwodmFsdWVzLCBmLCBzb3J0KSB7XG4gIHZhciB1ID0gc3RhdHMudW5pcXVlKHZhbHVlcywgZiksXG4gICAgICBjID0gc3RhdHMuY291bnQubWFwKHZhbHVlcywgZik7XG4gIHJldHVybiB1Lm1hcChmdW5jdGlvbihrKSB7IHJldHVybiB7dmFsdWU6IGssIGNvdW50OiBjW2tdfTsgfSlcbiAgICAuc29ydCh1dGlsLmNvbXBhcmF0b3Ioc29ydCA/ICctY291bnQnIDogJyt2YWx1ZScpKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICRiaW46ICRiaW4sXG4gIGhpc3RvZ3JhbTogaGlzdG9ncmFtXG59OyIsInZhciBkM190aW1lID0gcmVxdWlyZSgnZDMtdGltZScpLFxuICAgIGQzX3RpbWVGID0gcmVxdWlyZSgnZDMtdGltZS1mb3JtYXQnKSxcbiAgICBkM19udW1iZXJGID0gcmVxdWlyZSgnZDMtZm9ybWF0JyksXG4gICAgbnVtYmVyRiA9IGQzX251bWJlckYsIC8vIGRlZmF1bHRzIHRvIEVOLVVTXG4gICAgdGltZUYgPSBkM190aW1lRjsgICAgIC8vIGRlZmF1bHRzIHRvIEVOLVVTXG5cbmZ1bmN0aW9uIG51bWJlckxvY2FsZShsKSB7XG4gIHZhciBmID0gZDNfbnVtYmVyRi5sb2NhbGVGb3JtYXQobCk7XG4gIGlmIChmID09IG51bGwpIHRocm93IEVycm9yKCdVbnJlY29nbml6ZWQgbG9jYWxlOiAnICsgbCk7XG4gIG51bWJlckYgPSBmO1xufVxuXG5mdW5jdGlvbiB0aW1lTG9jYWxlKGwpIHtcbiAgdmFyIGYgPSBkM190aW1lRi5sb2NhbGVGb3JtYXQobCk7XG4gIGlmIChmID09IG51bGwpIHRocm93IEVycm9yKCdVbnJlY29nbml6ZWQgbG9jYWxlOiAnICsgbCk7XG4gIHRpbWVGID0gZjtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIC8vIFVwZGF0ZSBudW1iZXIgZm9ybWF0dGVyIHRvIHVzZSBwcm92aWRlZCBsb2NhbGUgY29uZmlndXJhdGlvbi5cbiAgLy8gRm9yIG1vcmUgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9kMy9kMy1mb3JtYXRcbiAgbnVtYmVyTG9jYWxlOiBudW1iZXJMb2NhbGUsXG4gIG51bWJlcjogICAgICAgZnVuY3Rpb24oZikgeyByZXR1cm4gbnVtYmVyRi5mb3JtYXQoZik7IH0sXG4gIG51bWJlclByZWZpeDogZnVuY3Rpb24oZiwgdikgeyByZXR1cm4gbnVtYmVyRi5mb3JtYXRQcmVmaXgoZiwgdik7IH0sXG5cbiAgLy8gVXBkYXRlIHRpbWUgZm9ybWF0dGVyIHRvIHVzZSBwcm92aWRlZCBsb2NhbGUgY29uZmlndXJhdGlvbi5cbiAgLy8gRm9yIG1vcmUgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9kMy9kMy10aW1lLWZvcm1hdFxuICB0aW1lTG9jYWxlOiAgIHRpbWVMb2NhbGUsXG4gIHRpbWU6ICAgICAgICAgZnVuY3Rpb24oZikgeyByZXR1cm4gdGltZUYuZm9ybWF0KGYpOyB9LCAgXG4gIHV0YzogICAgICAgICAgZnVuY3Rpb24oZikgeyByZXR1cm4gdGltZUYudXRjRm9ybWF0KGYpOyB9LFxuXG4gIC8vIFNldCBudW1iZXIgYW5kIHRpbWUgbG9jYWxlIHNpbXVsdGFuZW91c2x5LlxuICBsb2NhbGU6ICAgICAgIGZ1bmN0aW9uKGwpIHsgbnVtYmVyTG9jYWxlKGwpOyB0aW1lTG9jYWxlKGwpOyB9LFxuXG4gIC8vIGF1dG9tYXRpYyBmb3JtYXR0aW5nIGZ1bmN0aW9uc1xuICBhdXRvOiB7XG4gICAgbnVtYmVyOiAgIG51bWJlckF1dG9Gb3JtYXQsXG4gICAgdGltZTogICAgIGZ1bmN0aW9uKCkgeyByZXR1cm4gdGltZUF1dG9Gb3JtYXQoKTsgfSxcbiAgICB1dGM6ICAgICAgZnVuY3Rpb24oKSB7IHJldHVybiB1dGNBdXRvRm9ybWF0KCk7IH1cbiAgfVxufTtcblxudmFyIGUxMCA9IE1hdGguc3FydCg1MCksXG4gICAgZTUgPSBNYXRoLnNxcnQoMTApLFxuICAgIGUyID0gTWF0aC5zcXJ0KDIpO1xuXG5mdW5jdGlvbiBpbnRlcnZhbHMoZG9tYWluLCBjb3VudCkge1xuICBpZiAoIWRvbWFpbi5sZW5ndGgpIGRvbWFpbiA9IFswXTtcbiAgaWYgKGNvdW50ID09IG51bGwpIGNvdW50ID0gMTA7XG5cbiAgdmFyIHN0YXJ0ID0gZG9tYWluWzBdLFxuICAgICAgc3RvcCA9IGRvbWFpbltkb21haW4ubGVuZ3RoIC0gMV07XG5cbiAgaWYgKHN0b3AgPCBzdGFydCkgeyBlcnJvciA9IHN0b3A7IHN0b3AgPSBzdGFydDsgc3RhcnQgPSBlcnJvcjsgfVxuXG4gIHZhciBzcGFuID0gKHN0b3AgLSBzdGFydCkgfHwgKGNvdW50ID0gMSwgc3RhcnQgfHwgc3RvcCB8fCAxKSxcbiAgICAgIHN0ZXAgPSBNYXRoLnBvdygxMCwgTWF0aC5mbG9vcihNYXRoLmxvZyhzcGFuIC8gY291bnQpIC8gTWF0aC5MTjEwKSksXG4gICAgICBlcnJvciA9IHNwYW4gLyBjb3VudCAvIHN0ZXA7XG5cbiAgLy8gRmlsdGVyIHRpY2tzIHRvIGdldCBjbG9zZXIgdG8gdGhlIGRlc2lyZWQgY291bnQuXG4gIGlmIChlcnJvciA+PSBlMTApIHN0ZXAgKj0gMTA7XG4gIGVsc2UgaWYgKGVycm9yID49IGU1KSBzdGVwICo9IDU7XG4gIGVsc2UgaWYgKGVycm9yID49IGUyKSBzdGVwICo9IDI7XG5cbiAgLy8gUm91bmQgc3RhcnQgYW5kIHN0b3AgdmFsdWVzIHRvIHN0ZXAgaW50ZXJ2YWwuXG4gIHJldHVybiBbXG4gICAgTWF0aC5jZWlsKHN0YXJ0IC8gc3RlcCkgKiBzdGVwLFxuICAgIE1hdGguZmxvb3Ioc3RvcCAvIHN0ZXApICogc3RlcCArIHN0ZXAgLyAyLCAvLyBpbmNsdXNpdmVcbiAgICBzdGVwXG4gIF07XG59XG5cbmZ1bmN0aW9uIG51bWJlckF1dG9Gb3JtYXQoZG9tYWluLCBjb3VudCwgZikge1xuICB2YXIgcmFuZ2UgPSBpbnRlcnZhbHMoZG9tYWluLCBjb3VudCk7XG4gIGlmIChmID09IG51bGwpIHtcbiAgICBmID0gJywuJyArIGQzX251bWJlckYucHJlY2lzaW9uRml4ZWQocmFuZ2VbMl0pICsgJ2YnO1xuICB9IGVsc2Uge1xuICAgIHN3aXRjaCAoZiA9IGQzX251bWJlckYuZm9ybWF0U3BlY2lmaWVyKGYpLCBmLnR5cGUpIHtcbiAgICAgIGNhc2UgJ3MnOiB7XG4gICAgICAgIHZhciB2YWx1ZSA9IE1hdGgubWF4KE1hdGguYWJzKHJhbmdlWzBdKSwgTWF0aC5hYnMocmFuZ2VbMV0pKTtcbiAgICAgICAgaWYgKGYucHJlY2lzaW9uID09IG51bGwpIGYucHJlY2lzaW9uID0gZDNfbnVtYmVyRi5wcmVjaXNpb25QcmVmaXgocmFuZ2VbMl0sIHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIG51bWJlckYuZm9ybWF0UHJlZml4KGYsIHZhbHVlKTtcbiAgICAgIH1cbiAgICAgIGNhc2UgJyc6XG4gICAgICBjYXNlICdlJzpcbiAgICAgIGNhc2UgJ2cnOlxuICAgICAgY2FzZSAncCc6XG4gICAgICBjYXNlICdyJzoge1xuICAgICAgICBpZiAoZi5wcmVjaXNpb24gPT0gbnVsbCkgZi5wcmVjaXNpb24gPSBkM19udW1iZXJGLnByZWNpc2lvblJvdW5kKHJhbmdlWzJdLCBNYXRoLm1heChNYXRoLmFicyhyYW5nZVswXSksIE1hdGguYWJzKHJhbmdlWzFdKSkpIC0gKGYudHlwZSA9PT0gJ2UnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdmJzpcbiAgICAgIGNhc2UgJyUnOiB7XG4gICAgICAgIGlmIChmLnByZWNpc2lvbiA9PSBudWxsKSBmLnByZWNpc2lvbiA9IGQzX251bWJlckYucHJlY2lzaW9uRml4ZWQocmFuZ2VbMl0pIC0gKGYudHlwZSA9PT0gJyUnKSAqIDI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICByZXR1cm4gbnVtYmVyRi5mb3JtYXQoZik7XG59XG5cbmZ1bmN0aW9uIHRpbWVBdXRvRm9ybWF0KCkge1xuICB2YXIgZiA9IHRpbWVGLmZvcm1hdCxcbiAgICAgIGZvcm1hdE1pbGxpc2Vjb25kID0gZignLiVMJyksXG4gICAgICBmb3JtYXRTZWNvbmQgPSBmKCc6JVMnKSxcbiAgICAgIGZvcm1hdE1pbnV0ZSA9IGYoJyVJOiVNJyksXG4gICAgICBmb3JtYXRIb3VyID0gZignJUkgJXAnKSxcbiAgICAgIGZvcm1hdERheSA9IGYoJyVhICVkJyksXG4gICAgICBmb3JtYXRXZWVrID0gZignJWIgJWQnKSxcbiAgICAgIGZvcm1hdE1vbnRoID0gZignJUInKSxcbiAgICAgIGZvcm1hdFllYXIgPSBmKCclWScpO1xuXG4gIHJldHVybiBmdW5jdGlvbihkYXRlKSB7XG4gICAgdmFyIGQgPSArZGF0ZTtcbiAgICByZXR1cm4gKGQzX3RpbWUuc2Vjb25kKGRhdGUpIDwgZCA/IGZvcm1hdE1pbGxpc2Vjb25kXG4gICAgICAgIDogZDNfdGltZS5taW51dGUoZGF0ZSkgPCBkID8gZm9ybWF0U2Vjb25kXG4gICAgICAgIDogZDNfdGltZS5ob3VyKGRhdGUpIDwgZCA/IGZvcm1hdE1pbnV0ZVxuICAgICAgICA6IGQzX3RpbWUuZGF5KGRhdGUpIDwgZCA/IGZvcm1hdEhvdXJcbiAgICAgICAgOiBkM190aW1lLm1vbnRoKGRhdGUpIDwgZCA/XG4gICAgICAgICAgKGQzX3RpbWUud2VlayhkYXRlKSA8IGQgPyBmb3JtYXREYXkgOiBmb3JtYXRXZWVrKVxuICAgICAgICA6IGQzX3RpbWUueWVhcihkYXRlKSA8IGQgPyBmb3JtYXRNb250aFxuICAgICAgICA6IGZvcm1hdFllYXIpKGRhdGUpO1xuICB9O1xufVxuXG5mdW5jdGlvbiB1dGNBdXRvRm9ybWF0KCkge1xuICB2YXIgZiA9IHRpbWVGLnV0Y0Zvcm1hdCxcbiAgICAgIGZvcm1hdE1pbGxpc2Vjb25kID0gZignLiVMJyksXG4gICAgICBmb3JtYXRTZWNvbmQgPSBmKCc6JVMnKSxcbiAgICAgIGZvcm1hdE1pbnV0ZSA9IGYoJyVJOiVNJyksXG4gICAgICBmb3JtYXRIb3VyID0gZignJUkgJXAnKSxcbiAgICAgIGZvcm1hdERheSA9IGYoJyVhICVkJyksXG4gICAgICBmb3JtYXRXZWVrID0gZignJWIgJWQnKSxcbiAgICAgIGZvcm1hdE1vbnRoID0gZignJUInKSxcbiAgICAgIGZvcm1hdFllYXIgPSBmKCclWScpO1xuXG4gIHJldHVybiBmdW5jdGlvbihkYXRlKSB7XG4gICAgdmFyIGQgPSArZGF0ZTtcbiAgICByZXR1cm4gKGQzX3RpbWUudXRjU2Vjb25kKGRhdGUpIDwgZCA/IGZvcm1hdE1pbGxpc2Vjb25kXG4gICAgICAgIDogZDNfdGltZS51dGNNaW51dGUoZGF0ZSkgPCBkID8gZm9ybWF0U2Vjb25kXG4gICAgICAgIDogZDNfdGltZS51dGNIb3VyKGRhdGUpIDwgZCA/IGZvcm1hdE1pbnV0ZVxuICAgICAgICA6IGQzX3RpbWUudXRjRGF5KGRhdGUpIDwgZCA/IGZvcm1hdEhvdXJcbiAgICAgICAgOiBkM190aW1lLnV0Y01vbnRoKGRhdGUpIDwgZCA/XG4gICAgICAgICAgKGQzX3RpbWUudXRjV2VlayhkYXRlKSA8IGQgPyBmb3JtYXREYXkgOiBmb3JtYXRXZWVrKVxuICAgICAgICA6IGQzX3RpbWUudXRjWWVhcihkYXRlKSA8IGQgPyBmb3JtYXRNb250aFxuICAgICAgICA6IGZvcm1hdFllYXIpKGRhdGUpO1xuICB9O1xufVxuIiwidmFyIGdlbiA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbmdlbi5yZXBlYXQgPSBmdW5jdGlvbih2YWwsIG4pIHtcbiAgdmFyIGEgPSBBcnJheShuKSwgaTtcbiAgZm9yIChpPTA7IGk8bjsgKytpKSBhW2ldID0gdmFsO1xuICByZXR1cm4gYTtcbn07XG5cbmdlbi56ZXJvcyA9IGZ1bmN0aW9uKG4pIHtcbiAgcmV0dXJuIGdlbi5yZXBlYXQoMCwgbik7XG59O1xuXG5nZW4ucmFuZ2UgPSBmdW5jdGlvbihzdGFydCwgc3RvcCwgc3RlcCkge1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDMpIHtcbiAgICBzdGVwID0gMTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA8IDIpIHtcbiAgICAgIHN0b3AgPSBzdGFydDtcbiAgICAgIHN0YXJ0ID0gMDtcbiAgICB9XG4gIH1cbiAgaWYgKChzdG9wIC0gc3RhcnQpIC8gc3RlcCA9PSBJbmZpbml0eSkgdGhyb3cgbmV3IEVycm9yKCdJbmZpbml0ZSByYW5nZScpO1xuICB2YXIgcmFuZ2UgPSBbXSwgaSA9IC0xLCBqO1xuICBpZiAoc3RlcCA8IDApIHdoaWxlICgoaiA9IHN0YXJ0ICsgc3RlcCAqICsraSkgPiBzdG9wKSByYW5nZS5wdXNoKGopO1xuICBlbHNlIHdoaWxlICgoaiA9IHN0YXJ0ICsgc3RlcCAqICsraSkgPCBzdG9wKSByYW5nZS5wdXNoKGopO1xuICByZXR1cm4gcmFuZ2U7XG59O1xuXG5nZW4ucmFuZG9tID0ge307XG5cbmdlbi5yYW5kb20udW5pZm9ybSA9IGZ1bmN0aW9uKG1pbiwgbWF4KSB7XG4gIGlmIChtYXggPT09IHVuZGVmaW5lZCkge1xuICAgIG1heCA9IG1pbiA9PT0gdW5kZWZpbmVkID8gMSA6IG1pbjtcbiAgICBtaW4gPSAwO1xuICB9XG4gIHZhciBkID0gbWF4IC0gbWluO1xuICB2YXIgZiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBtaW4gKyBkICogTWF0aC5yYW5kb20oKTtcbiAgfTtcbiAgZi5zYW1wbGVzID0gZnVuY3Rpb24obikgeyByZXR1cm4gZ2VuLnplcm9zKG4pLm1hcChmKTsgfTtcbiAgcmV0dXJuIGY7XG59O1xuXG5nZW4ucmFuZG9tLmludGVnZXIgPSBmdW5jdGlvbihhLCBiKSB7XG4gIGlmIChiID09PSB1bmRlZmluZWQpIHtcbiAgICBiID0gYTtcbiAgICBhID0gMDtcbiAgfVxuICB2YXIgZCA9IGIgLSBhO1xuICB2YXIgZiA9IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBhICsgTWF0aC5mbG9vcihkICogTWF0aC5yYW5kb20oKSk7XG4gIH07XG4gIGYuc2FtcGxlcyA9IGZ1bmN0aW9uKG4pIHsgcmV0dXJuIGdlbi56ZXJvcyhuKS5tYXAoZik7IH07XG4gIHJldHVybiBmO1xufTtcblxuZ2VuLnJhbmRvbS5ub3JtYWwgPSBmdW5jdGlvbihtZWFuLCBzdGRldikge1xuICBtZWFuID0gbWVhbiB8fCAwO1xuICBzdGRldiA9IHN0ZGV2IHx8IDE7XG4gIHZhciBuZXh0O1xuICB2YXIgZiA9IGZ1bmN0aW9uKCkge1xuICAgIHZhciB4ID0gMCwgeSA9IDAsIHJkcywgYztcbiAgICBpZiAobmV4dCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB4ID0gbmV4dDtcbiAgICAgIG5leHQgPSB1bmRlZmluZWQ7XG4gICAgICByZXR1cm4geDtcbiAgICB9XG4gICAgZG8ge1xuICAgICAgeCA9IE1hdGgucmFuZG9tKCkqMi0xO1xuICAgICAgeSA9IE1hdGgucmFuZG9tKCkqMi0xO1xuICAgICAgcmRzID0geCp4ICsgeSp5O1xuICAgIH0gd2hpbGUgKHJkcyA9PT0gMCB8fCByZHMgPiAxKTtcbiAgICBjID0gTWF0aC5zcXJ0KC0yKk1hdGgubG9nKHJkcykvcmRzKTsgLy8gQm94LU11bGxlciB0cmFuc2Zvcm1cbiAgICBuZXh0ID0gbWVhbiArIHkqYypzdGRldjtcbiAgICByZXR1cm4gbWVhbiArIHgqYypzdGRldjtcbiAgfTtcbiAgZi5zYW1wbGVzID0gZnVuY3Rpb24obikgeyByZXR1cm4gZ2VuLnplcm9zKG4pLm1hcChmKTsgfTtcbiAgcmV0dXJuIGY7XG59OyIsInZhciB1dGlsID0gcmVxdWlyZSgnLi4vLi4vdXRpbCcpO1xudmFyIGQzX2RzdiA9IHJlcXVpcmUoJ2QzLWRzdicpO1xuXG5mdW5jdGlvbiBkc3YoZGF0YSwgZm9ybWF0KSB7XG4gIGlmIChkYXRhKSB7XG4gICAgdmFyIGggPSBmb3JtYXQuaGVhZGVyO1xuICAgIGRhdGEgPSAoaCA/IGguam9pbihmb3JtYXQuZGVsaW1pdGVyKSArICdcXG4nIDogJycpICsgZGF0YTtcbiAgfVxuICByZXR1cm4gZDNfZHN2LmRzdihmb3JtYXQuZGVsaW1pdGVyKS5wYXJzZShkYXRhKTtcbn1cblxuZHN2LmRlbGltaXRlciA9IGZ1bmN0aW9uKGRlbGltKSB7XG4gIHZhciBmbXQgPSB7ZGVsaW1pdGVyOiBkZWxpbX07XG4gIHJldHVybiBmdW5jdGlvbihkYXRhLCBmb3JtYXQpIHtcbiAgICByZXR1cm4gZHN2KGRhdGEsIGZvcm1hdCA/IHV0aWwuZXh0ZW5kKGZvcm1hdCwgZm10KSA6IGZtdCk7XG4gIH07XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IGRzdjsiLCJ2YXIgZHN2ID0gcmVxdWlyZSgnLi9kc3YnKTtcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGpzb246IHJlcXVpcmUoJy4vanNvbicpLFxuICB0b3BvanNvbjogcmVxdWlyZSgnLi90b3BvanNvbicpLFxuICB0cmVlanNvbjogcmVxdWlyZSgnLi90cmVlanNvbicpLFxuICBkc3Y6IGRzdixcbiAgY3N2OiBkc3YuZGVsaW1pdGVyKCcsJyksXG4gIHRzdjogZHN2LmRlbGltaXRlcignXFx0Jylcbn07IiwidmFyIHV0aWwgPSByZXF1aXJlKCcuLi8uLi91dGlsJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZGF0YSwgZm9ybWF0KSB7XG4gIHZhciBkID0gdXRpbC5pc09iamVjdChkYXRhKSAmJiAhdXRpbC5pc0J1ZmZlcihkYXRhKSA/XG4gICAgZGF0YSA6IEpTT04ucGFyc2UoZGF0YSk7XG4gIGlmIChmb3JtYXQgJiYgZm9ybWF0LnByb3BlcnR5KSB7XG4gICAgZCA9IHV0aWwuYWNjZXNzb3IoZm9ybWF0LnByb3BlcnR5KShkKTtcbiAgfVxuICByZXR1cm4gZDtcbn07XG4iLCJ2YXIganNvbiA9IHJlcXVpcmUoJy4vanNvbicpO1xuXG52YXIgcmVhZGVyID0gZnVuY3Rpb24oZGF0YSwgZm9ybWF0KSB7XG4gIHZhciB0b3BvanNvbiA9IHJlYWRlci50b3BvanNvbjtcbiAgaWYgKHRvcG9qc29uID09IG51bGwpIHsgdGhyb3cgRXJyb3IoJ1RvcG9KU09OIGxpYnJhcnkgbm90IGxvYWRlZC4nKTsgfVxuXG4gIHZhciB0ID0ganNvbihkYXRhLCBmb3JtYXQpLCBvYmo7XG5cbiAgaWYgKGZvcm1hdCAmJiBmb3JtYXQuZmVhdHVyZSkge1xuICAgIGlmICgob2JqID0gdC5vYmplY3RzW2Zvcm1hdC5mZWF0dXJlXSkpIHtcbiAgICAgIHJldHVybiB0b3BvanNvbi5mZWF0dXJlKHQsIG9iaikuZmVhdHVyZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IEVycm9yKCdJbnZhbGlkIFRvcG9KU09OIG9iamVjdDogJyArIGZvcm1hdC5mZWF0dXJlKTtcbiAgICB9XG4gIH0gZWxzZSBpZiAoZm9ybWF0ICYmIGZvcm1hdC5tZXNoKSB7XG4gICAgaWYgKChvYmogPSB0Lm9iamVjdHNbZm9ybWF0Lm1lc2hdKSkge1xuICAgICAgcmV0dXJuIFt0b3BvanNvbi5tZXNoKHQsIHQub2JqZWN0c1tmb3JtYXQubWVzaF0pXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgRXJyb3IoJ0ludmFsaWQgVG9wb0pTT04gb2JqZWN0OiAnICsgZm9ybWF0Lm1lc2gpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBFcnJvcignTWlzc2luZyBUb3BvSlNPTiBmZWF0dXJlIG9yIG1lc2ggcGFyYW1ldGVyLicpO1xuICB9XG59O1xuXG5yZWFkZXIudG9wb2pzb24gPSAodHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvd1sndG9wb2pzb24nXSA6IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWxbJ3RvcG9qc29uJ10gOiBudWxsKTtcbm1vZHVsZS5leHBvcnRzID0gcmVhZGVyOyIsInZhciBqc29uID0gcmVxdWlyZSgnLi9qc29uJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24oZGF0YSwgZm9ybWF0KSB7XG4gIGRhdGEgPSBqc29uKGRhdGEsIGZvcm1hdCk7XG4gIHJldHVybiB0b1RhYmxlKGRhdGEsIChmb3JtYXQgJiYgZm9ybWF0LmNoaWxkcmVuKSk7XG59O1xuXG5mdW5jdGlvbiB0b1RhYmxlKHJvb3QsIGNoaWxkcmVuRmllbGQpIHtcbiAgY2hpbGRyZW5GaWVsZCA9IGNoaWxkcmVuRmllbGQgfHwgJ2NoaWxkcmVuJztcbiAgdmFyIHRhYmxlID0gW107XG4gIFxuICBmdW5jdGlvbiB2aXNpdChub2RlKSB7XG4gICAgdGFibGUucHVzaChub2RlKTtcbiAgICB2YXIgY2hpbGRyZW4gPSBub2RlW2NoaWxkcmVuRmllbGRdO1xuICAgIGlmIChjaGlsZHJlbikge1xuICAgICAgZm9yICh2YXIgaT0wOyBpPGNoaWxkcmVuLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIHZpc2l0KGNoaWxkcmVuW2ldLCBub2RlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgXG4gIHZpc2l0KHJvb3QsIG51bGwpO1xuICByZXR1cm4gKHRhYmxlLnJvb3QgPSByb290LCB0YWJsZSk7XG59IiwiLy8gTWF0Y2hlcyBhYnNvbHV0ZSBVUkxzIHdpdGggb3B0aW9uYWwgcHJvdG9jb2xcbi8vICAgaHR0cHM6Ly8uLi4gICAgZmlsZTovLy4uLiAgICAvLy4uLlxudmFyIHByb3RvY29sX3JlID0gL14oW0EtWmEtel0rOik/XFwvXFwvLztcblxuLy8gU3BlY2lhbCB0cmVhdG1lbnQgaW4gbm9kZS5qcyBmb3IgdGhlIGZpbGU6IHByb3RvY29sXG52YXIgZmlsZVByb3RvY29sID0gJ2ZpbGU6Ly8nO1xuXG4vLyBWYWxpZGF0ZSBhbmQgY2xlYW51cCBVUkwgdG8gZW5zdXJlIHRoYXQgaXQgaXMgYWxsb3dlZCB0byBiZSBhY2Nlc3NlZFxuLy8gUmV0dXJucyBjbGVhbmVkIHVwIFVSTCwgb3IgZmFsc2UgaWYgYWNjZXNzIGlzIG5vdCBhbGxvd2VkXG5mdW5jdGlvbiBzYW5pdGl6ZVVybChvcHQpIHtcbiAgdmFyIHVybCA9IG9wdC51cmw7XG4gIGlmICghdXJsICYmIG9wdC5maWxlKSB7IHJldHVybiBmaWxlUHJvdG9jb2wgKyBvcHQuZmlsZTsgfVxuXG4gIC8vIEluIGNhc2UgdGhpcyBpcyBhIHJlbGF0aXZlIHVybCAoaGFzIG5vIGhvc3QpLCBwcmVwZW5kIG9wdC5iYXNlVVJMXG4gIGlmIChvcHQuYmFzZVVSTCAmJiAhcHJvdG9jb2xfcmUudGVzdCh1cmwpKSB7XG4gICAgaWYgKCFzdGFydHNXaXRoKHVybCwgJy8nKSAmJiBvcHQuYmFzZVVSTFtvcHQuYmFzZVVSTC5sZW5ndGgtMV0gIT09ICcvJykge1xuICAgICAgdXJsID0gJy8nICsgdXJsOyAvLyBFbnN1cmUgdGhhdCB0aGVyZSBpcyBhIHNsYXNoIGJldHdlZW4gdGhlIGJhc2VVUkwgKGUuZy4gaG9zdG5hbWUpIGFuZCB1cmxcbiAgICB9XG4gICAgdXJsID0gb3B0LmJhc2VVUkwgKyB1cmw7XG4gIH1cbiAgLy8gcmVsYXRpdmUgcHJvdG9jb2wsIHN0YXJ0cyB3aXRoICcvLydcbiAgaWYgKCFsb2FkLnVzZVhIUiAmJiBzdGFydHNXaXRoKHVybCwgJy8vJykpIHtcbiAgICB1cmwgPSAob3B0LmRlZmF1bHRQcm90b2NvbCB8fCAnaHR0cCcpICsgJzonICsgdXJsO1xuICB9XG4gIC8vIElmIG9wdC5kb21haW5XaGl0ZUxpc3QgaXMgc2V0LCBvbmx5IGFsbG93cyB1cmwsIHdob3NlIGhvc3RuYW1lXG4gIC8vICogSXMgdGhlIHNhbWUgYXMgdGhlIG9yaWdpbiAod2luZG93LmxvY2F0aW9uLmhvc3RuYW1lKVxuICAvLyAqIEVxdWFscyBvbmUgb2YgdGhlIHZhbHVlcyBpbiB0aGUgd2hpdGVsaXN0XG4gIC8vICogSXMgYSBwcm9wZXIgc3ViZG9tYWluIG9mIG9uZSBvZiB0aGUgdmFsdWVzIGluIHRoZSB3aGl0ZWxpc3RcbiAgaWYgKG9wdC5kb21haW5XaGl0ZUxpc3QpIHtcbiAgICB2YXIgZG9tYWluLCBvcmlnaW47XG4gICAgaWYgKGxvYWQudXNlWEhSKSB7XG4gICAgICB2YXIgYSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcbiAgICAgIGEuaHJlZiA9IHVybDtcbiAgICAgIC8vIEZyb20gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy83MzY1MTMvaG93LWRvLWktcGFyc2UtYS11cmwtaW50by1ob3N0bmFtZS1hbmQtcGF0aC1pbi1qYXZhc2NyaXB0XG4gICAgICAvLyBJRSBkb2Vzbid0IHBvcHVsYXRlIGFsbCBsaW5rIHByb3BlcnRpZXMgd2hlbiBzZXR0aW5nIC5ocmVmIHdpdGggYSByZWxhdGl2ZSBVUkwsXG4gICAgICAvLyBob3dldmVyIC5ocmVmIHdpbGwgcmV0dXJuIGFuIGFic29sdXRlIFVSTCB3aGljaCB0aGVuIGNhbiBiZSB1c2VkIG9uIGl0c2VsZlxuICAgICAgLy8gdG8gcG9wdWxhdGUgdGhlc2UgYWRkaXRpb25hbCBmaWVsZHMuXG4gICAgICBpZiAoYS5ob3N0ID09PSAnJykge1xuICAgICAgICBhLmhyZWYgPSBhLmhyZWY7XG4gICAgICB9XG4gICAgICBkb21haW4gPSBhLmhvc3RuYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICBvcmlnaW4gPSB3aW5kb3cubG9jYXRpb24uaG9zdG5hbWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIHJlbGF0aXZlIHByb3RvY29sIGlzIGJyb2tlbjogaHR0cHM6Ly9naXRodWIuY29tL2RlZnVuY3R6b21iaWUvbm9kZS11cmwvaXNzdWVzLzVcbiAgICAgIHZhciBwYXJ0cyA9IHJlcXVpcmUoJ3VybCcpLnBhcnNlKHVybCk7XG4gICAgICBkb21haW4gPSBwYXJ0cy5ob3N0bmFtZTtcbiAgICAgIG9yaWdpbiA9IG51bGw7XG4gICAgfVxuXG4gICAgaWYgKG9yaWdpbiAhPT0gZG9tYWluKSB7XG4gICAgICB2YXIgd2hpdGVMaXN0ZWQgPSBvcHQuZG9tYWluV2hpdGVMaXN0LnNvbWUoZnVuY3Rpb24oZCkge1xuICAgICAgICB2YXIgaWR4ID0gZG9tYWluLmxlbmd0aCAtIGQubGVuZ3RoO1xuICAgICAgICByZXR1cm4gZCA9PT0gZG9tYWluIHx8XG4gICAgICAgICAgKGlkeCA+IDEgJiYgZG9tYWluW2lkeC0xXSA9PT0gJy4nICYmIGRvbWFpbi5sYXN0SW5kZXhPZihkKSA9PT0gaWR4KTtcbiAgICAgIH0pO1xuICAgICAgaWYgKCF3aGl0ZUxpc3RlZCkge1xuICAgICAgICB0aHJvdyAnVVJMIGlzIG5vdCB3aGl0ZWxpc3RlZDogJyArIHVybDtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHVybDtcbn1cblxuZnVuY3Rpb24gbG9hZChvcHQsIGNhbGxiYWNrKSB7XG4gIHZhciBlcnJvciA9IGNhbGxiYWNrIHx8IGZ1bmN0aW9uKGUpIHsgdGhyb3cgZTsgfSwgdXJsO1xuXG4gIHRyeSB7XG4gICAgdXJsID0gbG9hZC5zYW5pdGl6ZVVybChvcHQpOyAvLyBlbmFibGUgb3ZlcnJpZGVcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgZXJyb3IoZXJyKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoIXVybCkge1xuICAgIGVycm9yKCdJbnZhbGlkIFVSTDogJyArIG9wdC51cmwpO1xuICB9IGVsc2UgaWYgKGxvYWQudXNlWEhSKSB7XG4gICAgLy8gb24gY2xpZW50LCB1c2UgeGhyXG4gICAgcmV0dXJuIHhocih1cmwsIGNhbGxiYWNrKTtcbiAgfSBlbHNlIGlmIChzdGFydHNXaXRoKHVybCwgZmlsZVByb3RvY29sKSkge1xuICAgIC8vIG9uIHNlcnZlciwgaWYgdXJsIHN0YXJ0cyB3aXRoICdmaWxlOi8vJywgc3RyaXAgaXQgYW5kIGxvYWQgZnJvbSBmaWxlXG4gICAgcmV0dXJuIGZpbGUodXJsLnNsaWNlKGZpbGVQcm90b2NvbC5sZW5ndGgpLCBjYWxsYmFjayk7XG4gIH0gZWxzZSBpZiAodXJsLmluZGV4T2YoJzovLycpIDwgMCkgeyAvLyBUT0RPIGJldHRlciBwcm90b2NvbCBjaGVjaz9cbiAgICAvLyBvbiBzZXJ2ZXIsIGlmIG5vIHByb3RvY29sIGFzc3VtZSBmaWxlXG4gICAgcmV0dXJuIGZpbGUodXJsLCBjYWxsYmFjayk7XG4gIH0gZWxzZSB7XG4gICAgLy8gZm9yIHJlZ3VsYXIgVVJMcyBvbiBzZXJ2ZXJcbiAgICByZXR1cm4gaHR0cCh1cmwsIGNhbGxiYWNrKTtcbiAgfVxufVxuXG5mdW5jdGlvbiB4aHJIYXNSZXNwb25zZShyZXF1ZXN0KSB7XG4gIHZhciB0eXBlID0gcmVxdWVzdC5yZXNwb25zZVR5cGU7XG4gIHJldHVybiB0eXBlICYmIHR5cGUgIT09ICd0ZXh0JyA/XG4gICAgcmVxdWVzdC5yZXNwb25zZSA6IC8vIG51bGwgb24gZXJyb3JcbiAgICByZXF1ZXN0LnJlc3BvbnNlVGV4dDsgLy8gJycgb24gZXJyb3Jcbn1cblxuZnVuY3Rpb24geGhyKHVybCwgY2FsbGJhY2spIHtcbiAgdmFyIGFzeW5jID0gISFjYWxsYmFjaztcbiAgdmFyIHJlcXVlc3QgPSBuZXcgWE1MSHR0cFJlcXVlc3QoKTtcbiAgLy8gSWYgSUUgZG9lcyBub3Qgc3VwcG9ydCBDT1JTLCB1c2UgWERvbWFpblJlcXVlc3QgKGNvcGllZCBmcm9tIGQzLnhocilcbiAgaWYgKHRoaXMuWERvbWFpblJlcXVlc3QgJiZcbiAgICAgICEoJ3dpdGhDcmVkZW50aWFscycgaW4gcmVxdWVzdCkgJiZcbiAgICAgIC9eKGh0dHAocyk/Oik/XFwvXFwvLy50ZXN0KHVybCkpIHJlcXVlc3QgPSBuZXcgWERvbWFpblJlcXVlc3QoKTtcblxuICBmdW5jdGlvbiByZXNwb25kKCkge1xuICAgIHZhciBzdGF0dXMgPSByZXF1ZXN0LnN0YXR1cztcbiAgICBpZiAoIXN0YXR1cyAmJiB4aHJIYXNSZXNwb25zZShyZXF1ZXN0KSB8fCBzdGF0dXMgPj0gMjAwICYmIHN0YXR1cyA8IDMwMCB8fCBzdGF0dXMgPT09IDMwNCkge1xuICAgICAgY2FsbGJhY2sobnVsbCwgcmVxdWVzdC5yZXNwb25zZVRleHQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBjYWxsYmFjayhyZXF1ZXN0LCBudWxsKTtcbiAgICB9XG4gIH1cblxuICBpZiAoYXN5bmMpIHtcbiAgICBpZiAoJ29ubG9hZCcgaW4gcmVxdWVzdCkge1xuICAgICAgcmVxdWVzdC5vbmxvYWQgPSByZXF1ZXN0Lm9uZXJyb3IgPSByZXNwb25kO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXF1ZXN0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAocmVxdWVzdC5yZWFkeVN0YXRlID4gMykgcmVzcG9uZCgpO1xuICAgICAgfTtcbiAgICB9XG4gIH1cbiAgXG4gIHJlcXVlc3Qub3BlbignR0VUJywgdXJsLCBhc3luYyk7XG4gIHJlcXVlc3Quc2VuZCgpO1xuICBcbiAgaWYgKCFhc3luYyAmJiB4aHJIYXNSZXNwb25zZShyZXF1ZXN0KSkge1xuICAgIHJldHVybiByZXF1ZXN0LnJlc3BvbnNlVGV4dDtcbiAgfVxufVxuXG5mdW5jdGlvbiBmaWxlKGZpbGVuYW1lLCBjYWxsYmFjaykge1xuICB2YXIgZnMgPSByZXF1aXJlKCdmcycpO1xuICBpZiAoIWNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIGZzLnJlYWRGaWxlU3luYyhmaWxlbmFtZSwgJ3V0ZjgnKTtcbiAgfVxuICBmcy5yZWFkRmlsZShmaWxlbmFtZSwgY2FsbGJhY2spO1xufVxuXG5mdW5jdGlvbiBodHRwKHVybCwgY2FsbGJhY2spIHtcbiAgaWYgKCFjYWxsYmFjaykge1xuICAgIHJldHVybiByZXF1aXJlKCdzeW5jLXJlcXVlc3QnKSgnR0VUJywgdXJsKS5nZXRCb2R5KCk7XG4gIH1cbiAgXG4gIHZhciBvcHRpb25zID0ge3VybDogdXJsLCBlbmNvZGluZzogbnVsbCwgZ3ppcDogdHJ1ZX07XG4gIHJlcXVpcmUoJ3JlcXVlc3QnKShvcHRpb25zLCBmdW5jdGlvbihlcnJvciwgcmVzcG9uc2UsIGJvZHkpIHtcbiAgICBpZiAoIWVycm9yICYmIHJlc3BvbnNlLnN0YXR1c0NvZGUgPT09IDIwMCkge1xuICAgICAgY2FsbGJhY2sobnVsbCwgYm9keSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVycm9yID0gZXJyb3IgfHxcbiAgICAgICAgJ0xvYWQgZmFpbGVkIHdpdGggcmVzcG9uc2UgY29kZSAnICsgcmVzcG9uc2Uuc3RhdHVzQ29kZSArICcuJztcbiAgICAgIGNhbGxiYWNrKGVycm9yLCBudWxsKTtcbiAgICB9XG4gIH0pO1xufVxuXG5mdW5jdGlvbiBzdGFydHNXaXRoKHN0cmluZywgc2VhcmNoU3RyaW5nKSB7XG4gIHJldHVybiBzdHJpbmcgPT0gbnVsbCA/IGZhbHNlIDogc3RyaW5nLmxhc3RJbmRleE9mKHNlYXJjaFN0cmluZywgMCkgPT09IDA7XG59XG5cbmxvYWQuc2FuaXRpemVVcmwgPSBzYW5pdGl6ZVVybDtcblxubG9hZC51c2VYSFIgPSAodHlwZW9mIFhNTEh0dHBSZXF1ZXN0ICE9PSAndW5kZWZpbmVkJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gbG9hZDtcbiIsInZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xudmFyIHR5cGUgPSByZXF1aXJlKCcuL3R5cGUnKTtcbnZhciBmb3JtYXRzID0gcmVxdWlyZSgnLi9mb3JtYXRzJyk7XG5cbmZ1bmN0aW9uIHJlYWQoZGF0YSwgZm9ybWF0KSB7XG4gIHZhciB0eXBlID0gKGZvcm1hdCAmJiBmb3JtYXQudHlwZSkgfHwgJ2pzb24nO1xuICBkYXRhID0gZm9ybWF0c1t0eXBlXShkYXRhLCBmb3JtYXQpO1xuICBpZiAoZm9ybWF0ICYmIGZvcm1hdC5wYXJzZSkgcGFyc2UoZGF0YSwgZm9ybWF0LnBhcnNlKTtcbiAgcmV0dXJuIGRhdGE7XG59XG5cbmZ1bmN0aW9uIHBhcnNlKGRhdGEsIHR5cGVzKSB7XG4gIHZhciBjb2xzLCBwYXJzZXJzLCBkLCBpLCBqLCBjbGVuLCBsZW4gPSBkYXRhLmxlbmd0aDtcblxuICB0eXBlcyA9ICh0eXBlcz09PSdhdXRvJykgPyB0eXBlLmluZmVyQWxsKGRhdGEpIDogdXRpbC5kdXBsaWNhdGUodHlwZXMpO1xuICBjb2xzID0gdXRpbC5rZXlzKHR5cGVzKTtcbiAgcGFyc2VycyA9IGNvbHMubWFwKGZ1bmN0aW9uKGMpIHsgcmV0dXJuIHR5cGUucGFyc2Vyc1t0eXBlc1tjXV07IH0pO1xuXG4gIGZvciAoaT0wLCBjbGVuPWNvbHMubGVuZ3RoOyBpPGxlbjsgKytpKSB7XG4gICAgZCA9IGRhdGFbaV07XG4gICAgZm9yIChqPTA7IGo8Y2xlbjsgKytqKSB7XG4gICAgICBkW2NvbHNbal1dID0gcGFyc2Vyc1tqXShkW2NvbHNbal1dKTtcbiAgICB9XG4gIH1cbiAgdHlwZS5hbm5vdGF0aW9uKGRhdGEsIHR5cGVzKTtcbn1cblxucmVhZC5mb3JtYXRzID0gZm9ybWF0cztcbm1vZHVsZS5leHBvcnRzID0gcmVhZDtcbiIsInZhciB1dGlsID0gcmVxdWlyZSgnLi4vdXRpbCcpO1xudmFyIGxvYWQgPSByZXF1aXJlKCcuL2xvYWQnKTtcbnZhciByZWFkID0gcmVxdWlyZSgnLi9yZWFkJyk7XG5cbm1vZHVsZS5leHBvcnRzID0gdXRpbFxuICAua2V5cyhyZWFkLmZvcm1hdHMpXG4gIC5yZWR1Y2UoZnVuY3Rpb24ob3V0LCB0eXBlKSB7XG4gICAgb3V0W3R5cGVdID0gZnVuY3Rpb24ob3B0LCBmb3JtYXQsIGNhbGxiYWNrKSB7XG4gICAgICAvLyBwcm9jZXNzIGFyZ3VtZW50c1xuICAgICAgaWYgKHV0aWwuaXNTdHJpbmcob3B0KSkgeyBvcHQgPSB7dXJsOiBvcHR9OyB9XG4gICAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMiAmJiB1dGlsLmlzRnVuY3Rpb24oZm9ybWF0KSkge1xuICAgICAgICBjYWxsYmFjayA9IGZvcm1hdDtcbiAgICAgICAgZm9ybWF0ID0gdW5kZWZpbmVkO1xuICAgICAgfVxuXG4gICAgICAvLyBzZXQgdXAgcmVhZCBmb3JtYXRcbiAgICAgIGZvcm1hdCA9IHV0aWwuZXh0ZW5kKHtwYXJzZTogJ2F1dG8nfSwgZm9ybWF0KTtcbiAgICAgIGZvcm1hdC50eXBlID0gdHlwZTtcblxuICAgICAgLy8gbG9hZCBkYXRhXG4gICAgICB2YXIgZGF0YSA9IGxvYWQob3B0LCBjYWxsYmFjayA/IGZ1bmN0aW9uKGVycm9yLCBkYXRhKSB7XG4gICAgICAgIGlmIChlcnJvcikgeyBjYWxsYmFjayhlcnJvciwgbnVsbCk7IHJldHVybjsgfVxuICAgICAgICB0cnkge1xuICAgICAgICAgIC8vIGRhdGEgbG9hZGVkLCBub3cgcGFyc2UgaXQgKGFzeW5jKVxuICAgICAgICAgIGRhdGEgPSByZWFkKGRhdGEsIGZvcm1hdCk7XG4gICAgICAgICAgY2FsbGJhY2sobnVsbCwgZGF0YSk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjYWxsYmFjayhlLCBudWxsKTtcbiAgICAgICAgfVxuICAgICAgfSA6IHVuZGVmaW5lZCk7XG4gICAgICBcbiAgICAgIC8vIGRhdGEgbG9hZGVkLCBub3cgcGFyc2UgaXQgKHN5bmMpXG4gICAgICBpZiAoIWNhbGxiYWNrKSByZXR1cm4gcmVhZChkYXRhLCBmb3JtYXQpO1xuICAgIH07XG4gICAgcmV0dXJuIG91dDtcbiAgfSwge30pO1xuIiwidmFyIHV0aWwgPSByZXF1aXJlKCcuLi91dGlsJyk7XG5cbnZhciBUWVBFUyA9ICdfX3R5cGVzX18nO1xuXG52YXIgUEFSU0VSUyA9IHtcbiAgYm9vbGVhbjogdXRpbC5ib29sZWFuLFxuICBpbnRlZ2VyOiB1dGlsLm51bWJlcixcbiAgbnVtYmVyOiAgdXRpbC5udW1iZXIsXG4gIGRhdGU6ICAgIHV0aWwuZGF0ZSxcbiAgc3RyaW5nOiAgZnVuY3Rpb24oeCkgeyByZXR1cm4geD09PScnID8gbnVsbCA6IHg7IH1cbn07XG5cbnZhciBURVNUUyA9IHtcbiAgYm9vbGVhbjogZnVuY3Rpb24oeCkgeyByZXR1cm4geD09PSd0cnVlJyB8fCB4PT09J2ZhbHNlJyB8fCB1dGlsLmlzQm9vbGVhbih4KTsgfSxcbiAgaW50ZWdlcjogZnVuY3Rpb24oeCkgeyByZXR1cm4gVEVTVFMubnVtYmVyKHgpICYmICh4PSt4KSA9PT0gfn54OyB9LFxuICBudW1iZXI6IGZ1bmN0aW9uKHgpIHsgcmV0dXJuICFpc05hTigreCkgJiYgIXV0aWwuaXNEYXRlKHgpOyB9LFxuICBkYXRlOiBmdW5jdGlvbih4KSB7IHJldHVybiAhaXNOYU4oRGF0ZS5wYXJzZSh4KSk7IH1cbn07XG5cbmZ1bmN0aW9uIGFubm90YXRpb24oZGF0YSwgdHlwZXMpIHtcbiAgaWYgKCF0eXBlcykgcmV0dXJuIGRhdGEgJiYgZGF0YVtUWVBFU10gfHwgbnVsbDtcbiAgZGF0YVtUWVBFU10gPSB0eXBlcztcbn1cblxuZnVuY3Rpb24gdHlwZSh2YWx1ZXMsIGYpIHtcbiAgZiA9IHV0aWwuJChmKTtcbiAgdmFyIHYsIGksIG47XG5cbiAgLy8gaWYgZGF0YSBhcnJheSBoYXMgdHlwZSBhbm5vdGF0aW9ucywgdXNlIHRoZW1cbiAgaWYgKHZhbHVlc1tUWVBFU10pIHtcbiAgICB2ID0gZih2YWx1ZXNbVFlQRVNdKTtcbiAgICBpZiAodXRpbC5pc1N0cmluZyh2KSkgcmV0dXJuIHY7XG4gIH1cblxuICBmb3IgKGk9MCwgbj12YWx1ZXMubGVuZ3RoOyAhdXRpbC5pc1ZhbGlkKHYpICYmIGk8bjsgKytpKSB7XG4gICAgdiA9IGYgPyBmKHZhbHVlc1tpXSkgOiB2YWx1ZXNbaV07XG4gIH1cblxuICByZXR1cm4gdXRpbC5pc0RhdGUodikgPyAnZGF0ZScgOlxuICAgIHV0aWwuaXNOdW1iZXIodikgICAgPyAnbnVtYmVyJyA6XG4gICAgdXRpbC5pc0Jvb2xlYW4odikgICA/ICdib29sZWFuJyA6XG4gICAgdXRpbC5pc1N0cmluZyh2KSAgICA/ICdzdHJpbmcnIDogbnVsbDtcbn1cblxuZnVuY3Rpb24gdHlwZUFsbChkYXRhLCBmaWVsZHMpIHtcbiAgaWYgKCFkYXRhLmxlbmd0aCkgcmV0dXJuO1xuICBmaWVsZHMgPSBmaWVsZHMgfHwgdXRpbC5rZXlzKGRhdGFbMF0pO1xuICByZXR1cm4gZmllbGRzLnJlZHVjZShmdW5jdGlvbih0eXBlcywgZikge1xuICAgIHJldHVybiAodHlwZXNbZl0gPSB0eXBlKGRhdGEsIGYpLCB0eXBlcyk7XG4gIH0sIHt9KTtcbn1cblxuZnVuY3Rpb24gaW5mZXIodmFsdWVzLCBmKSB7XG4gIGYgPSB1dGlsLiQoZik7XG4gIHZhciBpLCBqLCB2O1xuXG4gIC8vIHR5cGVzIHRvIHRlc3QgZm9yLCBpbiBwcmVjZWRlbmNlIG9yZGVyXG4gIHZhciB0eXBlcyA9IFsnYm9vbGVhbicsICdpbnRlZ2VyJywgJ251bWJlcicsICdkYXRlJ107XG5cbiAgZm9yIChpPTA7IGk8dmFsdWVzLmxlbmd0aDsgKytpKSB7XG4gICAgLy8gZ2V0IG5leHQgdmFsdWUgdG8gdGVzdFxuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuICAgIC8vIHRlc3QgdmFsdWUgYWdhaW5zdCByZW1haW5pbmcgdHlwZXNcbiAgICBmb3IgKGo9MDsgajx0eXBlcy5sZW5ndGg7ICsraikge1xuICAgICAgaWYgKHV0aWwuaXNWYWxpZCh2KSAmJiAhVEVTVFNbdHlwZXNbal1dKHYpKSB7XG4gICAgICAgIHR5cGVzLnNwbGljZShqLCAxKTtcbiAgICAgICAgaiAtPSAxO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBpZiBubyB0eXBlcyBsZWZ0LCByZXR1cm4gJ3N0cmluZydcbiAgICBpZiAodHlwZXMubGVuZ3RoID09PSAwKSByZXR1cm4gJ3N0cmluZyc7XG4gIH1cblxuICByZXR1cm4gdHlwZXNbMF07XG59XG5cbmZ1bmN0aW9uIGluZmVyQWxsKGRhdGEsIGZpZWxkcykge1xuICBmaWVsZHMgPSBmaWVsZHMgfHwgdXRpbC5rZXlzKGRhdGFbMF0pO1xuICByZXR1cm4gZmllbGRzLnJlZHVjZShmdW5jdGlvbih0eXBlcywgZikge1xuICAgIHR5cGVzW2ZdID0gaW5mZXIoZGF0YSwgZik7XG4gICAgcmV0dXJuIHR5cGVzO1xuICB9LCB7fSk7XG59XG5cbnR5cGUuYW5ub3RhdGlvbiA9IGFubm90YXRpb247XG50eXBlLmFsbCA9IHR5cGVBbGw7XG50eXBlLmluZmVyID0gaW5mZXI7XG50eXBlLmluZmVyQWxsID0gaW5mZXJBbGw7XG50eXBlLnBhcnNlcnMgPSBQQVJTRVJTO1xubW9kdWxlLmV4cG9ydHMgPSB0eXBlOyIsInZhciB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG5cbnZhciBkbCA9IHtcbiAgdmVyc2lvbjogICAgJzEuNC42JyxcbiAgbG9hZDogICAgICAgcmVxdWlyZSgnLi9pbXBvcnQvbG9hZCcpLFxuICByZWFkOiAgICAgICByZXF1aXJlKCcuL2ltcG9ydC9yZWFkJyksXG4gIHR5cGU6ICAgICAgIHJlcXVpcmUoJy4vaW1wb3J0L3R5cGUnKSxcbiAgQWdncmVnYXRvcjogcmVxdWlyZSgnLi9hZ2dyZWdhdGUvYWdncmVnYXRvcicpLFxuICBncm91cGJ5OiAgICByZXF1aXJlKCcuL2FnZ3JlZ2F0ZS9ncm91cGJ5JyksXG4gIGJpbnM6ICAgICAgIHJlcXVpcmUoJy4vYmlucy9iaW5zJyksXG4gICRiaW46ICAgICAgIHJlcXVpcmUoJy4vYmlucy9oaXN0b2dyYW0nKS4kYmluLFxuICBoaXN0b2dyYW06ICByZXF1aXJlKCcuL2JpbnMvaGlzdG9ncmFtJykuaGlzdG9ncmFtLFxuICBmb3JtYXQ6ICAgICByZXF1aXJlKCcuL2Zvcm1hdCcpLFxuICBwcmludDogICAgICByZXF1aXJlKCcuL3ByaW50JyksXG4gIHRlbXBsYXRlOiAgIHJlcXVpcmUoJy4vdGVtcGxhdGUnKSxcbiAgdGltZTogICAgICAgcmVxdWlyZSgnLi90aW1lJylcbn07XG5cbnV0aWwuZXh0ZW5kKGRsLCB1dGlsKTtcbnV0aWwuZXh0ZW5kKGRsLCByZXF1aXJlKCcuL2dlbmVyYXRlJykpO1xudXRpbC5leHRlbmQoZGwsIHJlcXVpcmUoJy4vc3RhdHMnKSk7XG51dGlsLmV4dGVuZChkbCwgcmVxdWlyZSgnLi9pbXBvcnQvcmVhZGVycycpKTtcblxubW9kdWxlLmV4cG9ydHMgPSBkbDsiLCJ2YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpO1xudmFyIHR5cGUgPSByZXF1aXJlKCcuL2ltcG9ydC90eXBlJyk7XG52YXIgc3RhdHMgPSByZXF1aXJlKCcuL3N0YXRzJyk7XG52YXIgdGVtcGxhdGUgPSByZXF1aXJlKCcuL3RlbXBsYXRlJyk7XG5cbnZhciBGTVQgPSB7XG4gICdkYXRlJzogICAgJ3x0aW1lOlwiJW0vJWQvJVkgJUg6JU06JVNcIicsXG4gICdudW1iZXInOiAgJ3xudW1iZXI6XCIuNGZcIicsXG4gICdpbnRlZ2VyJzogJ3xudW1iZXI6XCJkXCInXG59O1xuXG52YXIgUE9TID0ge1xuICAnbnVtYmVyJzogICdsZWZ0JyxcbiAgJ2ludGVnZXInOiAnbGVmdCdcbn07XG5cbm1vZHVsZS5leHBvcnRzLnRhYmxlID0gZnVuY3Rpb24oZGF0YSwgb3B0KSB7XG4gIG9wdCA9IHV0aWwuZXh0ZW5kKHtzZXBhcmF0b3I6JyAnLCBtaW53aWR0aDogOCwgbWF4d2lkdGg6IDE1fSwgb3B0KTtcbiAgdmFyIGZpZWxkcyA9IG9wdC5maWVsZHMgfHwgdXRpbC5rZXlzKGRhdGFbMF0pLFxuICAgICAgdHlwZXMgPSB0eXBlLmFsbChkYXRhKTtcblxuICBpZiAob3B0LnN0YXJ0IHx8IG9wdC5saW1pdCkge1xuICAgIHZhciBhID0gb3B0LnN0YXJ0IHx8IDAsXG4gICAgICAgIGIgPSBvcHQubGltaXQgPyBhICsgb3B0LmxpbWl0IDogZGF0YS5sZW5ndGg7XG4gICAgZGF0YSA9IGRhdGEuc2xpY2UoYSwgYik7XG4gIH1cblxuICAvLyBkZXRlcm1pbmUgY2hhciB3aWR0aCBvZiBmaWVsZHNcbiAgdmFyIGxlbnMgPSBmaWVsZHMubWFwKGZ1bmN0aW9uKG5hbWUpIHtcbiAgICB2YXIgZm9ybWF0ID0gRk1UW3R5cGVzW25hbWVdXSB8fCAnJyxcbiAgICAgICAgdCA9IHRlbXBsYXRlKCd7eycgKyBuYW1lICsgZm9ybWF0ICsgJ319JyksXG4gICAgICAgIGwgPSBzdGF0cy5tYXgoZGF0YSwgZnVuY3Rpb24oeCkgeyByZXR1cm4gdCh4KS5sZW5ndGg7IH0pO1xuICAgIGwgPSBNYXRoLm1heChNYXRoLm1pbihuYW1lLmxlbmd0aCwgb3B0Lm1pbndpZHRoKSwgbCk7XG4gICAgcmV0dXJuIG9wdC5tYXh3aWR0aCA+IDAgPyBNYXRoLm1pbihsLCBvcHQubWF4d2lkdGgpIDogbDtcbiAgfSk7XG5cbiAgLy8gcHJpbnQgaGVhZGVyIHJvd1xuICB2YXIgaGVhZCA9IGZpZWxkcy5tYXAoZnVuY3Rpb24obmFtZSwgaSkge1xuICAgIHJldHVybiB1dGlsLnRydW5jYXRlKHV0aWwucGFkKG5hbWUsIGxlbnNbaV0sICdjZW50ZXInKSwgbGVuc1tpXSk7XG4gIH0pLmpvaW4ob3B0LnNlcGFyYXRvcik7XG5cbiAgLy8gYnVpbGQgdGVtcGxhdGUgZnVuY3Rpb24gZm9yIGVhY2ggcm93XG4gIHZhciB0bXBsID0gdGVtcGxhdGUoZmllbGRzLm1hcChmdW5jdGlvbihuYW1lLCBpKSB7XG4gICAgcmV0dXJuICd7eycgK1xuICAgICAgbmFtZSArXG4gICAgICAoRk1UW3R5cGVzW25hbWVdXSB8fCAnJykgK1xuICAgICAgKCd8cGFkOicgKyBsZW5zW2ldICsgJywnICsgKFBPU1t0eXBlc1tuYW1lXV0gfHwgJ3JpZ2h0JykpICtcbiAgICAgICgnfHRydW5jYXRlOicgKyBsZW5zW2ldKSArXG4gICAgJ319JztcbiAgfSkuam9pbihvcHQuc2VwYXJhdG9yKSk7XG5cbiAgLy8gcHJpbnQgdGFibGVcbiAgcmV0dXJuIGhlYWQgKyBcIlxcblwiICsgZGF0YS5tYXAodG1wbCkuam9pbignXFxuJyk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cy5zdW1tYXJ5ID0gZnVuY3Rpb24ocykge1xuICBzID0gcyA/IHMuX19zdW1tYXJ5X18gPyBzIDogc3RhdHMuc3VtbWFyeShzKSA6IHRoaXM7XG4gIHZhciBzdHIgPSBbXSwgaSwgbjtcbiAgZm9yIChpPTAsIG49cy5sZW5ndGg7IGk8bjsgKytpKSB7XG4gICAgc3RyLnB1c2goJy0tICcgKyBzW2ldLmZpZWxkICsgJyAtLScpO1xuICAgIGlmIChzW2ldLnR5cGUgPT09ICdzdHJpbmcnIHx8IHNbaV0uZGlzdGluY3QgPCAxMCkge1xuICAgICAgc3RyLnB1c2gocHJpbnRDYXRlZ29yaWNhbFByb2ZpbGUoc1tpXSkpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdHIucHVzaChwcmludFF1YW50aXRhdGl2ZVByb2ZpbGUoc1tpXSkpO1xuICAgIH1cbiAgICBzdHIucHVzaCgnJyk7XG4gIH1cbiAgcmV0dXJuIHN0ci5qb2luKCdcXG4nKTtcbn07XG5cbmZ1bmN0aW9uIHByaW50UXVhbnRpdGF0aXZlUHJvZmlsZShwKSB7XG4gIHJldHVybiBbXG4gICAgJ3ZhbGlkOiAgICAnICsgcC52YWxpZCxcbiAgICAnbWlzc2luZzogICcgKyBwLm1pc3NpbmcsXG4gICAgJ2Rpc3RpbmN0OiAnICsgcC5kaXN0aW5jdCxcbiAgICAnbWluOiAgICAgICcgKyBwLm1pbixcbiAgICAnbWF4OiAgICAgICcgKyBwLm1heCxcbiAgICAnbWVkaWFuOiAgICcgKyBwLm1lZGlhbixcbiAgICAnbWVhbjogICAgICcgKyBwLm1lYW4sXG4gICAgJ3N0ZGV2OiAgICAnICsgcC5zdGRldixcbiAgICAnbW9kZXNrZXc6ICcgKyBwLm1vZGVza2V3XG4gIF0uam9pbignXFxuJyk7XG59XG5cbmZ1bmN0aW9uIHByaW50Q2F0ZWdvcmljYWxQcm9maWxlKHApIHtcbiAgdmFyIGxpc3QgPSBbXG4gICAgJ3ZhbGlkOiAgICAnICsgcC52YWxpZCxcbiAgICAnbWlzc2luZzogICcgKyBwLm1pc3NpbmcsXG4gICAgJ2Rpc3RpbmN0OiAnICsgcC5kaXN0aW5jdCxcbiAgICAndG9wIHZhbHVlczogJ1xuICBdO1xuICB2YXIgdSA9IHAudW5pcXVlO1xuICB2YXIgdG9wID0gdXRpbC5rZXlzKHUpXG4gICAgLnNvcnQoZnVuY3Rpb24oYSxiKSB7IHJldHVybiB1W2JdIC0gdVthXTsgfSlcbiAgICAuc2xpY2UoMCwgNilcbiAgICAubWFwKGZ1bmN0aW9uKHYpIHsgcmV0dXJuICcgXFwnJyArIHYgKyAnXFwnICgnICsgdVt2XSArICcpJzsgfSk7XG4gIHJldHVybiBsaXN0LmNvbmNhdCh0b3ApLmpvaW4oJ1xcbicpO1xufSIsInZhciB1dGlsID0gcmVxdWlyZSgnLi91dGlsJyk7XG52YXIgdHlwZSA9IHJlcXVpcmUoJy4vaW1wb3J0L3R5cGUnKTtcbnZhciBnZW4gPSByZXF1aXJlKCcuL2dlbmVyYXRlJyk7XG52YXIgc3RhdHMgPSB7fTtcblxuLy8gQ29sbGVjdCB1bmlxdWUgdmFsdWVzLlxuLy8gT3V0cHV0OiBhbiBhcnJheSBvZiB1bmlxdWUgdmFsdWVzLCBpbiBmaXJzdC1vYnNlcnZlZCBvcmRlclxuc3RhdHMudW5pcXVlID0gZnVuY3Rpb24odmFsdWVzLCBmLCByZXN1bHRzKSB7XG4gIGYgPSB1dGlsLiQoZik7XG4gIHJlc3VsdHMgPSByZXN1bHRzIHx8IFtdO1xuICB2YXIgdSA9IHt9LCB2LCBpLCBuO1xuICBmb3IgKGk9MCwgbj12YWx1ZXMubGVuZ3RoOyBpPG47ICsraSkge1xuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuICAgIGlmICh2IGluIHUpIGNvbnRpbnVlO1xuICAgIHVbdl0gPSAxO1xuICAgIHJlc3VsdHMucHVzaCh2KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0cztcbn07XG5cbi8vIFJldHVybiB0aGUgbGVuZ3RoIG9mIHRoZSBpbnB1dCBhcnJheS5cbnN0YXRzLmNvdW50ID0gZnVuY3Rpb24odmFsdWVzKSB7XG4gIHJldHVybiB2YWx1ZXMgJiYgdmFsdWVzLmxlbmd0aCB8fCAwO1xufTtcblxuLy8gQ291bnQgdGhlIG51bWJlciBvZiBub24tbnVsbCwgbm9uLXVuZGVmaW5lZCwgbm9uLU5hTiB2YWx1ZXMuXG5zdGF0cy5jb3VudC52YWxpZCA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICBmID0gdXRpbC4kKGYpO1xuICB2YXIgdiwgaSwgbiwgdmFsaWQgPSAwO1xuICBmb3IgKGk9MCwgbj12YWx1ZXMubGVuZ3RoOyBpPG47ICsraSkge1xuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuICAgIGlmICh1dGlsLmlzVmFsaWQodikpIHZhbGlkICs9IDE7XG4gIH1cbiAgcmV0dXJuIHZhbGlkO1xufTtcblxuLy8gQ291bnQgdGhlIG51bWJlciBvZiBudWxsIG9yIHVuZGVmaW5lZCB2YWx1ZXMuXG5zdGF0cy5jb3VudC5taXNzaW5nID0gZnVuY3Rpb24odmFsdWVzLCBmKSB7XG4gIGYgPSB1dGlsLiQoZik7XG4gIHZhciB2LCBpLCBuLCBjb3VudCA9IDA7XG4gIGZvciAoaT0wLCBuPXZhbHVlcy5sZW5ndGg7IGk8bjsgKytpKSB7XG4gICAgdiA9IGYgPyBmKHZhbHVlc1tpXSkgOiB2YWx1ZXNbaV07XG4gICAgaWYgKHYgPT0gbnVsbCkgY291bnQgKz0gMTtcbiAgfVxuICByZXR1cm4gY291bnQ7XG59O1xuXG4vLyBDb3VudCB0aGUgbnVtYmVyIG9mIGRpc3RpbmN0IHZhbHVlcy5cbi8vIE51bGwsIHVuZGVmaW5lZCBhbmQgTmFOIGFyZSBlYWNoIGNvbnNpZGVyZWQgZGlzdGluY3QgdmFsdWVzLlxuc3RhdHMuY291bnQuZGlzdGluY3QgPSBmdW5jdGlvbih2YWx1ZXMsIGYpIHtcbiAgZiA9IHV0aWwuJChmKTtcbiAgdmFyIHUgPSB7fSwgdiwgaSwgbiwgY291bnQgPSAwO1xuICBmb3IgKGk9MCwgbj12YWx1ZXMubGVuZ3RoOyBpPG47ICsraSkge1xuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuICAgIGlmICh2IGluIHUpIGNvbnRpbnVlO1xuICAgIHVbdl0gPSAxO1xuICAgIGNvdW50ICs9IDE7XG4gIH1cbiAgcmV0dXJuIGNvdW50O1xufTtcblxuLy8gQ29uc3RydWN0IGEgbWFwIGZyb20gZGlzdGluY3QgdmFsdWVzIHRvIG9jY3VycmVuY2UgY291bnRzLlxuc3RhdHMuY291bnQubWFwID0gZnVuY3Rpb24odmFsdWVzLCBmKSB7XG4gIGYgPSB1dGlsLiQoZik7XG4gIHZhciBtYXAgPSB7fSwgdiwgaSwgbjtcbiAgZm9yIChpPTAsIG49dmFsdWVzLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICB2ID0gZiA/IGYodmFsdWVzW2ldKSA6IHZhbHVlc1tpXTtcbiAgICBtYXBbdl0gPSAodiBpbiBtYXApID8gbWFwW3ZdICsgMSA6IDE7XG4gIH1cbiAgcmV0dXJuIG1hcDtcbn07XG5cbi8vIENvbXB1dGUgdGhlIG1lZGlhbiBvZiBhbiBhcnJheSBvZiBudW1iZXJzLlxuc3RhdHMubWVkaWFuID0gZnVuY3Rpb24odmFsdWVzLCBmKSB7XG4gIGlmIChmKSB2YWx1ZXMgPSB2YWx1ZXMubWFwKHV0aWwuJChmKSk7XG4gIHZhbHVlcyA9IHZhbHVlcy5maWx0ZXIodXRpbC5pc1ZhbGlkKS5zb3J0KHV0aWwuY21wKTtcbiAgcmV0dXJuIHN0YXRzLnF1YW50aWxlKHZhbHVlcywgMC41KTtcbn07XG5cbi8vIENvbXB1dGVzIHRoZSBxdWFydGlsZSBib3VuZGFyaWVzIG9mIGFuIGFycmF5IG9mIG51bWJlcnMuXG5zdGF0cy5xdWFydGlsZSA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICBpZiAoZikgdmFsdWVzID0gdmFsdWVzLm1hcCh1dGlsLiQoZikpO1xuICB2YWx1ZXMgPSB2YWx1ZXMuZmlsdGVyKHV0aWwuaXNWYWxpZCkuc29ydCh1dGlsLmNtcCk7XG4gIHZhciBxID0gc3RhdHMucXVhbnRpbGU7XG4gIHJldHVybiBbcSh2YWx1ZXMsIDAuMjUpLCBxKHZhbHVlcywgMC41MCksIHEodmFsdWVzLCAwLjc1KV07XG59O1xuXG4vLyBDb21wdXRlIHRoZSBxdWFudGlsZSBvZiBhIHNvcnRlZCBhcnJheSBvZiBudW1iZXJzLlxuLy8gQWRhcHRlZCBmcm9tIHRoZSBEMy5qcyBpbXBsZW1lbnRhdGlvbi5cbnN0YXRzLnF1YW50aWxlID0gZnVuY3Rpb24odmFsdWVzLCBmLCBwKSB7XG4gIGlmIChwID09PSB1bmRlZmluZWQpIHsgcCA9IGY7IGYgPSB1dGlsLmlkZW50aXR5OyB9XG4gIGYgPSB1dGlsLiQoZik7XG4gIHZhciBIID0gKHZhbHVlcy5sZW5ndGggLSAxKSAqIHAgKyAxLFxuICAgICAgaCA9IE1hdGguZmxvb3IoSCksXG4gICAgICB2ID0gK2YodmFsdWVzW2ggLSAxXSksXG4gICAgICBlID0gSCAtIGg7XG4gIHJldHVybiBlID8gdiArIGUgKiAoZih2YWx1ZXNbaF0pIC0gdikgOiB2O1xufTtcblxuLy8gQ29tcHV0ZSB0aGUgc3VtIG9mIGFuIGFycmF5IG9mIG51bWJlcnMuXG5zdGF0cy5zdW0gPSBmdW5jdGlvbih2YWx1ZXMsIGYpIHtcbiAgZiA9IHV0aWwuJChmKTtcbiAgZm9yICh2YXIgc3VtPTAsIGk9MCwgbj12YWx1ZXMubGVuZ3RoLCB2OyBpPG47ICsraSkge1xuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuICAgIGlmICh1dGlsLmlzVmFsaWQodikpIHN1bSArPSB2O1xuICB9XG4gIHJldHVybiBzdW07XG59O1xuXG4vLyBDb21wdXRlIHRoZSBtZWFuIChhdmVyYWdlKSBvZiBhbiBhcnJheSBvZiBudW1iZXJzLlxuc3RhdHMubWVhbiA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICBmID0gdXRpbC4kKGYpO1xuICB2YXIgbWVhbiA9IDAsIGRlbHRhLCBpLCBuLCBjLCB2O1xuICBmb3IgKGk9MCwgYz0wLCBuPXZhbHVlcy5sZW5ndGg7IGk8bjsgKytpKSB7XG4gICAgdiA9IGYgPyBmKHZhbHVlc1tpXSkgOiB2YWx1ZXNbaV07XG4gICAgaWYgKHV0aWwuaXNWYWxpZCh2KSkge1xuICAgICAgZGVsdGEgPSB2IC0gbWVhbjtcbiAgICAgIG1lYW4gPSBtZWFuICsgZGVsdGEgLyAoKytjKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG1lYW47XG59O1xuXG4vLyBDb21wdXRlIHRoZSBzYW1wbGUgdmFyaWFuY2Ugb2YgYW4gYXJyYXkgb2YgbnVtYmVycy5cbnN0YXRzLnZhcmlhbmNlID0gZnVuY3Rpb24odmFsdWVzLCBmKSB7XG4gIGYgPSB1dGlsLiQoZik7XG4gIGlmICghdXRpbC5pc0FycmF5KHZhbHVlcykgfHwgdmFsdWVzLmxlbmd0aCA8IDIpIHJldHVybiAwO1xuICB2YXIgbWVhbiA9IDAsIE0yID0gMCwgZGVsdGEsIGksIGMsIHY7XG4gIGZvciAoaT0wLCBjPTA7IGk8dmFsdWVzLmxlbmd0aDsgKytpKSB7XG4gICAgdiA9IGYgPyBmKHZhbHVlc1tpXSkgOiB2YWx1ZXNbaV07XG4gICAgaWYgKHV0aWwuaXNWYWxpZCh2KSkge1xuICAgICAgZGVsdGEgPSB2IC0gbWVhbjtcbiAgICAgIG1lYW4gPSBtZWFuICsgZGVsdGEgLyAoKytjKTtcbiAgICAgIE0yID0gTTIgKyBkZWx0YSAqICh2IC0gbWVhbik7XG4gICAgfVxuICB9XG4gIE0yID0gTTIgLyAoYyAtIDEpO1xuICByZXR1cm4gTTI7XG59O1xuXG4vLyBDb21wdXRlIHRoZSBzYW1wbGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIGFuIGFycmF5IG9mIG51bWJlcnMuXG5zdGF0cy5zdGRldiA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICByZXR1cm4gTWF0aC5zcXJ0KHN0YXRzLnZhcmlhbmNlKHZhbHVlcywgZikpO1xufTtcblxuLy8gQ29tcHV0ZSB0aGUgUGVhcnNvbiBtb2RlIHNrZXduZXNzICgobWVkaWFuLW1lYW4pL3N0ZGV2KSBvZiBhbiBhcnJheSBvZiBudW1iZXJzLlxuc3RhdHMubW9kZXNrZXcgPSBmdW5jdGlvbih2YWx1ZXMsIGYpIHtcbiAgdmFyIGF2ZyA9IHN0YXRzLm1lYW4odmFsdWVzLCBmKSxcbiAgICAgIG1lZCA9IHN0YXRzLm1lZGlhbih2YWx1ZXMsIGYpLFxuICAgICAgc3RkID0gc3RhdHMuc3RkZXYodmFsdWVzLCBmKTtcbiAgcmV0dXJuIHN0ZCA9PT0gMCA/IDAgOiAoYXZnIC0gbWVkKSAvIHN0ZDtcbn07XG5cbi8vIEZpbmQgdGhlIG1pbmltdW0gdmFsdWUgaW4gYW4gYXJyYXkuXG5zdGF0cy5taW4gPSBmdW5jdGlvbih2YWx1ZXMsIGYpIHtcbiAgcmV0dXJuIHN0YXRzLmV4dGVudCh2YWx1ZXMsIGYpWzBdO1xufTtcblxuLy8gRmluZCB0aGUgbWF4aW11bSB2YWx1ZSBpbiBhbiBhcnJheS5cbnN0YXRzLm1heCA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICByZXR1cm4gc3RhdHMuZXh0ZW50KHZhbHVlcywgZilbMV07XG59O1xuXG4vLyBGaW5kIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIG9mIGFuIGFycmF5IG9mIHZhbHVlcy5cbnN0YXRzLmV4dGVudCA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICBmID0gdXRpbC4kKGYpO1xuICB2YXIgYSwgYiwgdiwgaSwgbiA9IHZhbHVlcy5sZW5ndGg7XG4gIGZvciAoaT0wOyBpPG47ICsraSkge1xuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuICAgIGlmICh1dGlsLmlzVmFsaWQodikpIHsgYSA9IGIgPSB2OyBicmVhazsgfVxuICB9XG4gIGZvciAoOyBpPG47ICsraSkge1xuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuICAgIGlmICh1dGlsLmlzVmFsaWQodikpIHtcbiAgICAgIGlmICh2IDwgYSkgYSA9IHY7XG4gICAgICBpZiAodiA+IGIpIGIgPSB2O1xuICAgIH1cbiAgfVxuICByZXR1cm4gW2EsIGJdO1xufTtcblxuLy8gRmluZCB0aGUgaW50ZWdlciBpbmRpY2VzIG9mIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlcy5cbnN0YXRzLmV4dGVudC5pbmRleCA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICBmID0gdXRpbC4kKGYpO1xuICB2YXIgeCA9IC0xLCB5ID0gLTEsIGEsIGIsIHYsIGksIG4gPSB2YWx1ZXMubGVuZ3RoO1xuICBmb3IgKGk9MDsgaTxuOyArK2kpIHtcbiAgICB2ID0gZiA/IGYodmFsdWVzW2ldKSA6IHZhbHVlc1tpXTtcbiAgICBpZiAodXRpbC5pc1ZhbGlkKHYpKSB7IGEgPSBiID0gdjsgeCA9IHkgPSBpOyBicmVhazsgfVxuICB9XG4gIGZvciAoOyBpPG47ICsraSkge1xuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuICAgIGlmICh1dGlsLmlzVmFsaWQodikpIHtcbiAgICAgIGlmICh2IDwgYSkgeyBhID0gdjsgeCA9IGk7IH1cbiAgICAgIGlmICh2ID4gYikgeyBiID0gdjsgeSA9IGk7IH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIFt4LCB5XTtcbn07XG5cbi8vIENvbXB1dGUgdGhlIGRvdCBwcm9kdWN0IG9mIHR3byBhcnJheXMgb2YgbnVtYmVycy5cbnN0YXRzLmRvdCA9IGZ1bmN0aW9uKHZhbHVlcywgYSwgYikge1xuICB2YXIgc3VtID0gMCwgaSwgdjtcbiAgaWYgKCFiKSB7XG4gICAgaWYgKHZhbHVlcy5sZW5ndGggIT09IGEubGVuZ3RoKSB7XG4gICAgICB0aHJvdyBFcnJvcignQXJyYXkgbGVuZ3RocyBtdXN0IG1hdGNoLicpO1xuICAgIH1cbiAgICBmb3IgKGk9MDsgaTx2YWx1ZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgIHYgPSB2YWx1ZXNbaV0gKiBhW2ldO1xuICAgICAgaWYgKHYgPT09IHYpIHN1bSArPSB2O1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBhID0gdXRpbC4kKGEpO1xuICAgIGIgPSB1dGlsLiQoYik7XG4gICAgZm9yIChpPTA7IGk8dmFsdWVzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2ID0gYSh2YWx1ZXNbaV0pICogYih2YWx1ZXNbaV0pO1xuICAgICAgaWYgKHYgPT09IHYpIHN1bSArPSB2O1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3VtO1xufTtcblxuLy8gQ29tcHV0ZSBhc2NlbmRpbmcgcmFuayBzY29yZXMgZm9yIGFuIGFycmF5IG9mIHZhbHVlcy5cbi8vIFRpZXMgYXJlIGFzc2lnbmVkIHRoZWlyIGNvbGxlY3RpdmUgbWVhbiByYW5rLlxuc3RhdHMucmFuayA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICBmID0gdXRpbC4kKGYpIHx8IHV0aWwuaWRlbnRpdHk7XG4gIHZhciBhID0gdmFsdWVzLm1hcChmdW5jdGlvbih2LCBpKSB7XG4gICAgICByZXR1cm4ge2lkeDogaSwgdmFsOiBmKHYpfTtcbiAgICB9KVxuICAgIC5zb3J0KHV0aWwuY29tcGFyYXRvcigndmFsJykpO1xuXG4gIHZhciBuID0gdmFsdWVzLmxlbmd0aCxcbiAgICAgIHIgPSBBcnJheShuKSxcbiAgICAgIHRpZSA9IC0xLCBwID0ge30sIGksIHYsIG11O1xuXG4gIGZvciAoaT0wOyBpPG47ICsraSkge1xuICAgIHYgPSBhW2ldLnZhbDtcbiAgICBpZiAodGllIDwgMCAmJiBwID09PSB2KSB7XG4gICAgICB0aWUgPSBpIC0gMTtcbiAgICB9IGVsc2UgaWYgKHRpZSA+IC0xICYmIHAgIT09IHYpIHtcbiAgICAgIG11ID0gMSArIChpLTEgKyB0aWUpIC8gMjtcbiAgICAgIGZvciAoOyB0aWU8aTsgKyt0aWUpIHJbYVt0aWVdLmlkeF0gPSBtdTtcbiAgICAgIHRpZSA9IC0xO1xuICAgIH1cbiAgICByW2FbaV0uaWR4XSA9IGkgKyAxO1xuICAgIHAgPSB2O1xuICB9XG5cbiAgaWYgKHRpZSA+IC0xKSB7XG4gICAgbXUgPSAxICsgKG4tMSArIHRpZSkgLyAyO1xuICAgIGZvciAoOyB0aWU8bjsgKyt0aWUpIHJbYVt0aWVdLmlkeF0gPSBtdTtcbiAgfVxuXG4gIHJldHVybiByO1xufTtcblxuLy8gQ29tcHV0ZSB0aGUgc2FtcGxlIFBlYXJzb24gcHJvZHVjdC1tb21lbnQgY29ycmVsYXRpb24gb2YgdHdvIGFycmF5cyBvZiBudW1iZXJzLlxuc3RhdHMuY29yID0gZnVuY3Rpb24odmFsdWVzLCBhLCBiKSB7XG4gIHZhciBmbiA9IGI7XG4gIGIgPSBmbiA/IHZhbHVlcy5tYXAodXRpbC4kKGIpKSA6IGE7XG4gIGEgPSBmbiA/IHZhbHVlcy5tYXAodXRpbC4kKGEpKSA6IHZhbHVlcztcblxuICB2YXIgZG90ID0gc3RhdHMuZG90KGEsIGIpLFxuICAgICAgbXVhID0gc3RhdHMubWVhbihhKSxcbiAgICAgIG11YiA9IHN0YXRzLm1lYW4oYiksXG4gICAgICBzZGEgPSBzdGF0cy5zdGRldihhKSxcbiAgICAgIHNkYiA9IHN0YXRzLnN0ZGV2KGIpLFxuICAgICAgbiA9IHZhbHVlcy5sZW5ndGg7XG5cbiAgcmV0dXJuIChkb3QgLSBuKm11YSptdWIpIC8gKChuLTEpICogc2RhICogc2RiKTtcbn07XG5cbi8vIENvbXB1dGUgdGhlIFNwZWFybWFuIHJhbmsgY29ycmVsYXRpb24gb2YgdHdvIGFycmF5cyBvZiB2YWx1ZXMuXG5zdGF0cy5jb3IucmFuayA9IGZ1bmN0aW9uKHZhbHVlcywgYSwgYikge1xuICB2YXIgcmEgPSBiID8gc3RhdHMucmFuayh2YWx1ZXMsIHV0aWwuJChhKSkgOiBzdGF0cy5yYW5rKHZhbHVlcyksXG4gICAgICByYiA9IGIgPyBzdGF0cy5yYW5rKHZhbHVlcywgdXRpbC4kKGIpKSA6IHN0YXRzLnJhbmsoYSksXG4gICAgICBuID0gdmFsdWVzLmxlbmd0aCwgaSwgcywgZDtcblxuICBmb3IgKGk9MCwgcz0wOyBpPG47ICsraSkge1xuICAgIGQgPSByYVtpXSAtIHJiW2ldO1xuICAgIHMgKz0gZCAqIGQ7XG4gIH1cblxuICByZXR1cm4gMSAtIDYqcyAvIChuICogKG4qbi0xKSk7XG59O1xuXG4vLyBDb21wdXRlIHRoZSBkaXN0YW5jZSBjb3JyZWxhdGlvbiBvZiB0d28gYXJyYXlzIG9mIG51bWJlcnMuXG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Rpc3RhbmNlX2NvcnJlbGF0aW9uXG5zdGF0cy5jb3IuZGlzdCA9IGZ1bmN0aW9uKHZhbHVlcywgYSwgYikge1xuICB2YXIgWCA9IGIgPyB2YWx1ZXMubWFwKHV0aWwuJChhKSkgOiB2YWx1ZXMsXG4gICAgICBZID0gYiA/IHZhbHVlcy5tYXAodXRpbC4kKGIpKSA6IGE7XG5cbiAgdmFyIEEgPSBzdGF0cy5kaXN0Lm1hdChYKSxcbiAgICAgIEIgPSBzdGF0cy5kaXN0Lm1hdChZKSxcbiAgICAgIG4gPSBBLmxlbmd0aCxcbiAgICAgIGksIGFhLCBiYiwgYWI7XG5cbiAgZm9yIChpPTAsIGFhPTAsIGJiPTAsIGFiPTA7IGk8bjsgKytpKSB7XG4gICAgYWEgKz0gQVtpXSpBW2ldO1xuICAgIGJiICs9IEJbaV0qQltpXTtcbiAgICBhYiArPSBBW2ldKkJbaV07XG4gIH1cblxuICByZXR1cm4gTWF0aC5zcXJ0KGFiIC8gTWF0aC5zcXJ0KGFhKmJiKSk7XG59O1xuXG4vLyBDb21wdXRlIHRoZSB2ZWN0b3IgZGlzdGFuY2UgYmV0d2VlbiB0d28gYXJyYXlzIG9mIG51bWJlcnMuXG4vLyBEZWZhdWx0IGlzIEV1Y2xpZGVhbiAoZXhwPTIpIGRpc3RhbmNlLCBjb25maWd1cmFibGUgdmlhIGV4cCBhcmd1bWVudC5cbnN0YXRzLmRpc3QgPSBmdW5jdGlvbih2YWx1ZXMsIGEsIGIsIGV4cCkge1xuICB2YXIgZiA9IHV0aWwuaXNGdW5jdGlvbihiKSB8fCB1dGlsLmlzU3RyaW5nKGIpLFxuICAgICAgWCA9IHZhbHVlcyxcbiAgICAgIFkgPSBmID8gdmFsdWVzIDogYSxcbiAgICAgIGUgPSBmID8gZXhwIDogYixcbiAgICAgIEwyID0gZSA9PT0gMiB8fCBlID09IG51bGwsXG4gICAgICBuID0gdmFsdWVzLmxlbmd0aCwgcyA9IDAsIGQsIGk7XG4gIGlmIChmKSB7XG4gICAgYSA9IHV0aWwuJChhKTtcbiAgICBiID0gdXRpbC4kKGIpO1xuICB9XG4gIGZvciAoaT0wOyBpPG47ICsraSkge1xuICAgIGQgPSBmID8gKGEoWFtpXSktYihZW2ldKSkgOiAoWFtpXS1ZW2ldKTtcbiAgICBzICs9IEwyID8gZCpkIDogTWF0aC5wb3coTWF0aC5hYnMoZCksIGUpO1xuICB9XG4gIHJldHVybiBMMiA/IE1hdGguc3FydChzKSA6IE1hdGgucG93KHMsIDEvZSk7XG59O1xuXG4vLyBDb25zdHJ1Y3QgYSBtZWFuLWNlbnRlcmVkIGRpc3RhbmNlIG1hdHJpeCBmb3IgYW4gYXJyYXkgb2YgbnVtYmVycy5cbnN0YXRzLmRpc3QubWF0ID0gZnVuY3Rpb24oWCkge1xuICB2YXIgbiA9IFgubGVuZ3RoLFxuICAgICAgbSA9IG4qbixcbiAgICAgIEEgPSBBcnJheShtKSxcbiAgICAgIFIgPSBnZW4uemVyb3MobiksXG4gICAgICBNID0gMCwgdiwgaSwgajtcblxuICBmb3IgKGk9MDsgaTxuOyArK2kpIHtcbiAgICBBW2kqbitpXSA9IDA7XG4gICAgZm9yIChqPWkrMTsgajxuOyArK2opIHtcbiAgICAgIEFbaSpuK2pdID0gKHYgPSBNYXRoLmFicyhYW2ldIC0gWFtqXSkpO1xuICAgICAgQVtqKm4raV0gPSB2O1xuICAgICAgUltpXSArPSB2O1xuICAgICAgUltqXSArPSB2O1xuICAgIH1cbiAgfVxuXG4gIGZvciAoaT0wOyBpPG47ICsraSkge1xuICAgIE0gKz0gUltpXTtcbiAgICBSW2ldIC89IG47XG4gIH1cbiAgTSAvPSBtO1xuXG4gIGZvciAoaT0wOyBpPG47ICsraSkge1xuICAgIGZvciAoaj1pOyBqPG47ICsraikge1xuICAgICAgQVtpKm4ral0gKz0gTSAtIFJbaV0gLSBSW2pdO1xuICAgICAgQVtqKm4raV0gPSBBW2kqbitqXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gQTtcbn07XG5cbi8vIENvbXB1dGUgdGhlIFNoYW5ub24gZW50cm9weSAobG9nIGJhc2UgMikgb2YgYW4gYXJyYXkgb2YgY291bnRzLlxuc3RhdHMuZW50cm9weSA9IGZ1bmN0aW9uKGNvdW50cywgZikge1xuICBmID0gdXRpbC4kKGYpO1xuICB2YXIgaSwgcCwgcyA9IDAsIEggPSAwLCBuID0gY291bnRzLmxlbmd0aDtcbiAgZm9yIChpPTA7IGk8bjsgKytpKSB7XG4gICAgcyArPSAoZiA/IGYoY291bnRzW2ldKSA6IGNvdW50c1tpXSk7XG4gIH1cbiAgaWYgKHMgPT09IDApIHJldHVybiAwO1xuICBmb3IgKGk9MDsgaTxuOyArK2kpIHtcbiAgICBwID0gKGYgPyBmKGNvdW50c1tpXSkgOiBjb3VudHNbaV0pIC8gcztcbiAgICBpZiAocCkgSCArPSBwICogTWF0aC5sb2cocCk7XG4gIH1cbiAgcmV0dXJuIC1IIC8gTWF0aC5MTjI7XG59O1xuXG4vLyBDb21wdXRlIHRoZSBtdXR1YWwgaW5mb3JtYXRpb24gYmV0d2VlbiB0d28gZGlzY3JldGUgdmFyaWFibGVzLlxuLy8gUmV0dXJucyBhbiBhcnJheSBvZiB0aGUgZm9ybSBbTUksIE1JX2Rpc3RhbmNlXSBcbi8vIE1JX2Rpc3RhbmNlIGlzIGRlZmluZWQgYXMgMSAtIEkoYSxiKSAvIEgoYSxiKS5cbi8vIGh0dHA6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvTXV0dWFsX2luZm9ybWF0aW9uXG5zdGF0cy5tdXR1YWwgPSBmdW5jdGlvbih2YWx1ZXMsIGEsIGIsIGNvdW50cykge1xuICB2YXIgeCA9IGNvdW50cyA/IHZhbHVlcy5tYXAodXRpbC4kKGEpKSA6IHZhbHVlcyxcbiAgICAgIHkgPSBjb3VudHMgPyB2YWx1ZXMubWFwKHV0aWwuJChiKSkgOiBhLFxuICAgICAgeiA9IGNvdW50cyA/IHZhbHVlcy5tYXAodXRpbC4kKGNvdW50cykpIDogYjtcblxuICB2YXIgcHggPSB7fSxcbiAgICAgIHB5ID0ge30sXG4gICAgICBuID0gei5sZW5ndGgsXG4gICAgICBzID0gMCwgSSA9IDAsIEggPSAwLCBwLCB0LCBpO1xuXG4gIGZvciAoaT0wOyBpPG47ICsraSkge1xuICAgIHB4W3hbaV1dID0gMDtcbiAgICBweVt5W2ldXSA9IDA7XG4gIH1cblxuICBmb3IgKGk9MDsgaTxuOyArK2kpIHtcbiAgICBweFt4W2ldXSArPSB6W2ldO1xuICAgIHB5W3lbaV1dICs9IHpbaV07XG4gICAgcyArPSB6W2ldO1xuICB9XG5cbiAgdCA9IDEgLyAocyAqIE1hdGguTE4yKTtcbiAgZm9yIChpPTA7IGk8bjsgKytpKSB7XG4gICAgaWYgKHpbaV0gPT09IDApIGNvbnRpbnVlO1xuICAgIHAgPSAocyAqIHpbaV0pIC8gKHB4W3hbaV1dICogcHlbeVtpXV0pO1xuICAgIEkgKz0geltpXSAqIHQgKiBNYXRoLmxvZyhwKTtcbiAgICBIICs9IHpbaV0gKiB0ICogTWF0aC5sb2coeltpXS9zKTtcbiAgfVxuXG4gIHJldHVybiBbSSwgMSArIEkvSF07XG59O1xuXG4vLyBDb21wdXRlIHRoZSBtdXR1YWwgaW5mb3JtYXRpb24gYmV0d2VlbiB0d28gZGlzY3JldGUgdmFyaWFibGVzLlxuc3RhdHMubXV0dWFsLmluZm8gPSBmdW5jdGlvbih2YWx1ZXMsIGEsIGIsIGNvdW50cykge1xuICByZXR1cm4gc3RhdHMubXV0dWFsKHZhbHVlcywgYSwgYiwgY291bnRzKVswXTtcbn07XG5cbi8vIENvbXB1dGUgdGhlIG11dHVhbCBpbmZvcm1hdGlvbiBkaXN0YW5jZSBiZXR3ZWVuIHR3byBkaXNjcmV0ZSB2YXJpYWJsZXMuXG4vLyBNSV9kaXN0YW5jZSBpcyBkZWZpbmVkIGFzIDEgLSBJKGEsYikgLyBIKGEsYikuXG5zdGF0cy5tdXR1YWwuZGlzdCA9IGZ1bmN0aW9uKHZhbHVlcywgYSwgYiwgY291bnRzKSB7XG4gIHJldHVybiBzdGF0cy5tdXR1YWwodmFsdWVzLCBhLCBiLCBjb3VudHMpWzFdO1xufTtcblxuLy8gQ29tcHV0ZSBhIHByb2ZpbGUgb2Ygc3VtbWFyeSBzdGF0aXN0aWNzIGZvciBhIHZhcmlhYmxlLlxuc3RhdHMucHJvZmlsZSA9IGZ1bmN0aW9uKHZhbHVlcywgZikge1xuICB2YXIgbWVhbiA9IDAsXG4gICAgICB2YWxpZCA9IDAsXG4gICAgICBtaXNzaW5nID0gMCxcbiAgICAgIGRpc3RpbmN0ID0gMCxcbiAgICAgIG1pbiA9IG51bGwsXG4gICAgICBtYXggPSBudWxsLFxuICAgICAgTTIgPSAwLFxuICAgICAgdmFscyA9IFtdLFxuICAgICAgdSA9IHt9LCBkZWx0YSwgc2QsIGksIHYsIHg7XG5cbiAgLy8gY29tcHV0ZSBzdW1tYXJ5IHN0YXRzXG4gIGZvciAoaT0wOyBpPHZhbHVlcy5sZW5ndGg7ICsraSkge1xuICAgIHYgPSBmID8gZih2YWx1ZXNbaV0pIDogdmFsdWVzW2ldO1xuXG4gICAgLy8gdXBkYXRlIHVuaXF1ZSB2YWx1ZXNcbiAgICB1W3ZdID0gKHYgaW4gdSkgPyB1W3ZdICsgMSA6IChkaXN0aW5jdCArPSAxLCAxKTtcblxuICAgIGlmICh2ID09IG51bGwpIHtcbiAgICAgICsrbWlzc2luZztcbiAgICB9IGVsc2UgaWYgKHV0aWwuaXNWYWxpZCh2KSkge1xuICAgICAgLy8gdXBkYXRlIHN0YXRzXG4gICAgICB4ID0gKHR5cGVvZiB2ID09PSAnc3RyaW5nJykgPyB2Lmxlbmd0aCA6IHY7XG4gICAgICBpZiAobWluPT09bnVsbCB8fCB4IDwgbWluKSBtaW4gPSB4O1xuICAgICAgaWYgKG1heD09PW51bGwgfHwgeCA+IG1heCkgbWF4ID0geDtcbiAgICAgIGRlbHRhID0geCAtIG1lYW47XG4gICAgICBtZWFuID0gbWVhbiArIGRlbHRhIC8gKCsrdmFsaWQpO1xuICAgICAgTTIgPSBNMiArIGRlbHRhICogKHggLSBtZWFuKTtcbiAgICAgIHZhbHMucHVzaCh4KTtcbiAgICB9XG4gIH1cbiAgTTIgPSBNMiAvICh2YWxpZCAtIDEpO1xuICBzZCA9IE1hdGguc3FydChNMik7XG5cbiAgLy8gc29ydCB2YWx1ZXMgZm9yIG1lZGlhbiBhbmQgaXFyXG4gIHZhbHMuc29ydCh1dGlsLmNtcCk7XG5cbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAgICAgdHlwZSh2YWx1ZXMsIGYpLFxuICAgIHVuaXF1ZTogICB1LFxuICAgIGNvdW50OiAgICB2YWx1ZXMubGVuZ3RoLFxuICAgIHZhbGlkOiAgICB2YWxpZCxcbiAgICBtaXNzaW5nOiAgbWlzc2luZyxcbiAgICBkaXN0aW5jdDogZGlzdGluY3QsXG4gICAgbWluOiAgICAgIG1pbixcbiAgICBtYXg6ICAgICAgbWF4LFxuICAgIG1lYW46ICAgICBtZWFuLFxuICAgIHN0ZGV2OiAgICBzZCxcbiAgICBtZWRpYW46ICAgKHYgPSBzdGF0cy5xdWFudGlsZSh2YWxzLCAwLjUpKSxcbiAgICBxMTogICAgICAgc3RhdHMucXVhbnRpbGUodmFscywgMC4yNSksXG4gICAgcTM6ICAgICAgIHN0YXRzLnF1YW50aWxlKHZhbHMsIDAuNzUpLFxuICAgIG1vZGVza2V3OiBzZCA9PT0gMCA/IDAgOiAobWVhbiAtIHYpIC8gc2RcbiAgfTtcbn07XG5cbi8vIENvbXB1dGUgcHJvZmlsZXMgZm9yIGFsbCB2YXJpYWJsZXMgaW4gYSBkYXRhIHNldC5cbnN0YXRzLnN1bW1hcnkgPSBmdW5jdGlvbihkYXRhLCBmaWVsZHMpIHtcbiAgZmllbGRzID0gZmllbGRzIHx8IHV0aWwua2V5cyhkYXRhWzBdKTtcbiAgdmFyIHMgPSBmaWVsZHMubWFwKGZ1bmN0aW9uKGYpIHtcbiAgICB2YXIgcCA9IHN0YXRzLnByb2ZpbGUoZGF0YSwgdXRpbC4kKGYpKTtcbiAgICByZXR1cm4gKHAuZmllbGQgPSBmLCBwKTtcbiAgfSk7XG4gIHJldHVybiAocy5fX3N1bW1hcnlfXyA9IHRydWUsIHMpO1xufTtcblxubW9kdWxlLmV4cG9ydHMgPSBzdGF0czsiLCJ2YXIgdXRpbCA9IHJlcXVpcmUoJy4vdXRpbCcpLFxuICAgIGZvcm1hdCA9IHJlcXVpcmUoJy4vZm9ybWF0Jyk7XG5cbnZhciBjb250ZXh0ID0ge1xuICBmb3JtYXRzOiAgICBbXSxcbiAgZm9ybWF0X21hcDoge30sXG4gIHRydW5jYXRlOiAgIHV0aWwudHJ1bmNhdGUsXG4gIHBhZDogICAgICAgIHV0aWwucGFkXG59O1xuXG5mdW5jdGlvbiB0ZW1wbGF0ZSh0ZXh0KSB7XG4gIHZhciBzcmMgPSBzb3VyY2UodGV4dCwgJ2QnKTtcbiAgc3JjID0gJ3ZhciBfX3Q7IHJldHVybiAnICsgc3JjICsgJzsnO1xuXG4gIC8qIGpzaGludCBldmlsOiB0cnVlICovXG4gIHJldHVybiAobmV3IEZ1bmN0aW9uKCdkJywgc3JjKSkuYmluZChjb250ZXh0KTtcbn1cblxudGVtcGxhdGUuc291cmNlID0gc291cmNlO1xudGVtcGxhdGUuY29udGV4dCA9IGNvbnRleHQ7XG5tb2R1bGUuZXhwb3J0cyA9IHRlbXBsYXRlO1xuXG4vLyBDbGVhciBjYWNoZSBvZiBmb3JtYXQgb2JqZWN0cy5cbi8vIFRoaXMgY2FuICpicmVhayogcHJpb3IgdGVtcGxhdGUgZnVuY3Rpb25zLCBzbyBpbnZva2Ugd2l0aCBjYXJlIVxudGVtcGxhdGUuY2xlYXJGb3JtYXRDYWNoZSA9IGZ1bmN0aW9uKCkge1xuICBjb250ZXh0LmZvcm1hdHMgPSBbXTtcbiAgY29udGV4dC5mb3JtYXRfbWFwID0ge307XG59O1xuXG4vLyBHZW5lcmF0ZSBwcm9wZXJ0eSBhY2Nlc3MgY29kZSBmb3IgdXNlIHdpdGhpbiB0ZW1wbGF0ZSBzb3VyY2UuXG4vLyBvYmplY3Q6IHRoZSBuYW1lIG9mIHRoZSBvYmplY3QgKHZhcmlhYmxlKSBjb250YWluaW5nIHRlbXBsYXRlIGRhdGFcbi8vIHByb3BlcnR5OiB0aGUgcHJvcGVydHkgYWNjZXNzIHN0cmluZywgdmVyYmF0aW0gZnJvbSB0ZW1wbGF0ZSB0YWdcbnRlbXBsYXRlLnByb3BlcnR5ID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkge1xuICB2YXIgc3JjID0gdXRpbC5maWVsZChwcm9wZXJ0eSkubWFwKHV0aWwuc3RyKS5qb2luKCddWycpO1xuICByZXR1cm4gb2JqZWN0ICsgJ1snICsgc3JjICsgJ10nO1xufTtcblxuLy8gR2VuZXJhdGUgc291cmNlIGNvZGUgZm9yIGEgdGVtcGxhdGUgZnVuY3Rpb24uXG4vLyB0ZXh0OiB0aGUgdGVtcGxhdGUgdGV4dFxuLy8gdmFyaWFibGU6IHRoZSBuYW1lIG9mIHRoZSBkYXRhIG9iamVjdCB2YXJpYWJsZSAoJ29iaicgYnkgZGVmYXVsdClcbi8vIHByb3BlcnRpZXM6IG9wdGlvbmFsIGhhc2ggZm9yIGNvbGxlY3RpbmcgYWxsIGFjY2Vzc2VkIHByb3BlcnRpZXNcbmZ1bmN0aW9uIHNvdXJjZSh0ZXh0LCB2YXJpYWJsZSwgcHJvcGVydGllcykge1xuICB2YXJpYWJsZSA9IHZhcmlhYmxlIHx8ICdvYmonO1xuICB2YXIgaW5kZXggPSAwO1xuICB2YXIgc3JjID0gJ1xcJyc7XG4gIHZhciByZWdleCA9IHRlbXBsYXRlX3JlO1xuXG4gIC8vIENvbXBpbGUgdGhlIHRlbXBsYXRlIHNvdXJjZSwgZXNjYXBpbmcgc3RyaW5nIGxpdGVyYWxzIGFwcHJvcHJpYXRlbHkuXG4gIHRleHQucmVwbGFjZShyZWdleCwgZnVuY3Rpb24obWF0Y2gsIGludGVycG9sYXRlLCBvZmZzZXQpIHtcbiAgICBzcmMgKz0gdGV4dFxuICAgICAgLnNsaWNlKGluZGV4LCBvZmZzZXQpXG4gICAgICAucmVwbGFjZSh0ZW1wbGF0ZV9lc2NhcGVyLCB0ZW1wbGF0ZV9lc2NhcGVDaGFyKTtcbiAgICBpbmRleCA9IG9mZnNldCArIG1hdGNoLmxlbmd0aDtcblxuICAgIGlmIChpbnRlcnBvbGF0ZSkge1xuICAgICAgc3JjICs9ICdcXCdcXG4rKChfX3Q9KCcgK1xuICAgICAgICB0ZW1wbGF0ZV92YXIoaW50ZXJwb2xhdGUsIHZhcmlhYmxlLCBwcm9wZXJ0aWVzKSArXG4gICAgICAgICcpKT09bnVsbD9cXCdcXCc6X190KStcXG5cXCcnO1xuICAgIH1cblxuICAgIC8vIEFkb2JlIFZNcyBuZWVkIHRoZSBtYXRjaCByZXR1cm5lZCB0byBwcm9kdWNlIHRoZSBjb3JyZWN0IG9mZmVzdC5cbiAgICByZXR1cm4gbWF0Y2g7XG4gIH0pO1xuICByZXR1cm4gc3JjICsgJ1xcJyc7XG59XG5cbmZ1bmN0aW9uIHRlbXBsYXRlX3Zhcih0ZXh0LCB2YXJpYWJsZSwgcHJvcGVydGllcykge1xuICB2YXIgZmlsdGVycyA9IHRleHQubWF0Y2goZmlsdGVyX3JlKTtcbiAgdmFyIHByb3AgPSBmaWx0ZXJzLnNoaWZ0KCkudHJpbSgpO1xuICB2YXIgc3RyaW5nQ2FzdCA9IHRydWU7XG5cbiAgZnVuY3Rpb24gc3RyY2FsbChmbikge1xuICAgIGZuID0gZm4gfHwgJyc7XG4gICAgaWYgKHN0cmluZ0Nhc3QpIHtcbiAgICAgIHN0cmluZ0Nhc3QgPSBmYWxzZTtcbiAgICAgIHNyYyA9ICdTdHJpbmcoJyArIHNyYyArICcpJyArIGZuO1xuICAgIH0gZWxzZSB7XG4gICAgICBzcmMgKz0gZm47XG4gICAgfVxuICAgIHJldHVybiBzcmM7XG4gIH1cblxuICBmdW5jdGlvbiBkYXRlKCkge1xuICAgIHJldHVybiAnKHR5cGVvZiAnICsgc3JjICsgJz09PVwibnVtYmVyXCI/bmV3IERhdGUoJytzcmMrJyk6JytzcmMrJyknO1xuICB9XG5cbiAgZnVuY3Rpb24gbnVtYmVyX2Zvcm1hdChmbXQsIGtleSkge1xuICAgIGEgPSB0ZW1wbGF0ZV9mb3JtYXQoYXJnc1swXSwga2V5LCBmbXQpO1xuICAgIHN0cmluZ0Nhc3QgPSBmYWxzZTtcbiAgICBzcmMgPSAndGhpcy5mb3JtYXRzWycrYSsnXSgnK3NyYysnKSc7XG4gIH1cbiAgXG4gIGZ1bmN0aW9uIHRpbWVfZm9ybWF0KGZtdCwga2V5KSB7XG4gICAgYSA9IHRlbXBsYXRlX2Zvcm1hdChhcmdzWzBdLCBrZXksIGZtdCk7XG4gICAgc3RyaW5nQ2FzdCA9IGZhbHNlO1xuICAgIHNyYyA9ICd0aGlzLmZvcm1hdHNbJythKyddKCcrZGF0ZSgpKycpJztcbiAgfVxuXG4gIGlmIChwcm9wZXJ0aWVzKSBwcm9wZXJ0aWVzW3Byb3BdID0gMTtcbiAgdmFyIHNyYyA9IHRlbXBsYXRlLnByb3BlcnR5KHZhcmlhYmxlLCBwcm9wKTtcblxuICBmb3IgKHZhciBpPTA7IGk8ZmlsdGVycy5sZW5ndGg7ICsraSkge1xuICAgIHZhciBmID0gZmlsdGVyc1tpXSwgYXJncyA9IG51bGwsIHBpZHgsIGEsIGI7XG5cbiAgICBpZiAoKHBpZHg9Zi5pbmRleE9mKCc6JykpID4gMCkge1xuICAgICAgZiA9IGYuc2xpY2UoMCwgcGlkeCk7XG4gICAgICBhcmdzID0gZmlsdGVyc1tpXS5zbGljZShwaWR4KzEpXG4gICAgICAgIC5tYXRjaChhcmdzX3JlKVxuICAgICAgICAubWFwKGZ1bmN0aW9uKHMpIHsgcmV0dXJuIHMudHJpbSgpOyB9KTtcbiAgICB9XG4gICAgZiA9IGYudHJpbSgpO1xuXG4gICAgc3dpdGNoIChmKSB7XG4gICAgICBjYXNlICdsZW5ndGgnOlxuICAgICAgICBzdHJjYWxsKCcubGVuZ3RoJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbG93ZXInOlxuICAgICAgICBzdHJjYWxsKCcudG9Mb3dlckNhc2UoKScpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3VwcGVyJzpcbiAgICAgICAgc3RyY2FsbCgnLnRvVXBwZXJDYXNlKCknKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdsb3dlci1sb2NhbGUnOlxuICAgICAgICBzdHJjYWxsKCcudG9Mb2NhbGVMb3dlckNhc2UoKScpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3VwcGVyLWxvY2FsZSc6XG4gICAgICAgIHN0cmNhbGwoJy50b0xvY2FsZVVwcGVyQ2FzZSgpJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndHJpbSc6XG4gICAgICAgIHN0cmNhbGwoJy50cmltKCknKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdsZWZ0JzpcbiAgICAgICAgYSA9IHV0aWwubnVtYmVyKGFyZ3NbMF0pO1xuICAgICAgICBzdHJjYWxsKCcuc2xpY2UoMCwnICsgYSArICcpJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAncmlnaHQnOlxuICAgICAgICBhID0gdXRpbC5udW1iZXIoYXJnc1swXSk7XG4gICAgICAgIHN0cmNhbGwoJy5zbGljZSgtJyArIGEgKycpJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnbWlkJzpcbiAgICAgICAgYSA9IHV0aWwubnVtYmVyKGFyZ3NbMF0pO1xuICAgICAgICBiID0gYSArIHV0aWwubnVtYmVyKGFyZ3NbMV0pO1xuICAgICAgICBzdHJjYWxsKCcuc2xpY2UoKycrYSsnLCcrYisnKScpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3NsaWNlJzpcbiAgICAgICAgYSA9IHV0aWwubnVtYmVyKGFyZ3NbMF0pO1xuICAgICAgICBzdHJjYWxsKCcuc2xpY2UoJysgYSArXG4gICAgICAgICAgKGFyZ3MubGVuZ3RoID4gMSA/ICcsJyArIHV0aWwubnVtYmVyKGFyZ3NbMV0pIDogJycpICtcbiAgICAgICAgICAnKScpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3RydW5jYXRlJzpcbiAgICAgICAgYSA9IHV0aWwubnVtYmVyKGFyZ3NbMF0pO1xuICAgICAgICBiID0gYXJnc1sxXTtcbiAgICAgICAgYiA9IChiIT09J2xlZnQnICYmIGIhPT0nbWlkZGxlJyAmJiBiIT09J2NlbnRlcicpID8gJ3JpZ2h0JyA6IGI7XG4gICAgICAgIHNyYyA9ICd0aGlzLnRydW5jYXRlKCcgKyBzdHJjYWxsKCkgKyAnLCcgKyBhICsgJyxcXCcnICsgYiArICdcXCcpJztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdwYWQnOlxuICAgICAgICBhID0gdXRpbC5udW1iZXIoYXJnc1swXSk7XG4gICAgICAgIGIgPSBhcmdzWzFdO1xuICAgICAgICBiID0gKGIhPT0nbGVmdCcgJiYgYiE9PSdtaWRkbGUnICYmIGIhPT0nY2VudGVyJykgPyAncmlnaHQnIDogYjtcbiAgICAgICAgc3JjID0gJ3RoaXMucGFkKCcgKyBzdHJjYWxsKCkgKyAnLCcgKyBhICsgJyxcXCcnICsgYiArICdcXCcpJztcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdudW1iZXInOlxuICAgICAgICBudW1iZXJfZm9ybWF0KGZvcm1hdC5udW1iZXIsICdudW1iZXInKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0aW1lJzpcbiAgICAgICAgdGltZV9mb3JtYXQoZm9ybWF0LnRpbWUsICd0aW1lJyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndGltZS11dGMnOlxuICAgICAgICB0aW1lX2Zvcm1hdChmb3JtYXQudXRjLCAndGltZS11dGMnKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBFcnJvcignVW5yZWNvZ25pemVkIHRlbXBsYXRlIGZpbHRlcjogJyArIGYpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBzcmM7XG59XG5cbnZhciB0ZW1wbGF0ZV9yZSA9IC9cXHtcXHsoLis/KVxcfVxcfXwkL2csXG4gICAgZmlsdGVyX3JlID0gLyg/OlwiW15cIl0qXCJ8XFwnW15cXCddKlxcJ3xbXlxcfFwiXSt8W15cXHxcXCddKykrL2csXG4gICAgYXJnc19yZSA9IC8oPzpcIlteXCJdKlwifFxcJ1teXFwnXSpcXCd8W14sXCJdK3xbXixcXCddKykrL2c7XG5cbi8vIENlcnRhaW4gY2hhcmFjdGVycyBuZWVkIHRvIGJlIGVzY2FwZWQgc28gdGhhdCB0aGV5IGNhbiBiZSBwdXQgaW50byBhXG4vLyBzdHJpbmcgbGl0ZXJhbC5cbnZhciB0ZW1wbGF0ZV9lc2NhcGVzID0ge1xuICAnXFwnJzogICAgICdcXCcnLFxuICAnXFxcXCc6ICAgICAnXFxcXCcsXG4gICdcXHInOiAgICAgJ3InLFxuICAnXFxuJzogICAgICduJyxcbiAgJ1xcdTIwMjgnOiAndTIwMjgnLFxuICAnXFx1MjAyOSc6ICd1MjAyOSdcbn07XG5cbnZhciB0ZW1wbGF0ZV9lc2NhcGVyID0gL1xcXFx8J3xcXHJ8XFxufFxcdTIwMjh8XFx1MjAyOS9nO1xuXG5mdW5jdGlvbiB0ZW1wbGF0ZV9lc2NhcGVDaGFyKG1hdGNoKSB7XG4gIHJldHVybiAnXFxcXCcgKyB0ZW1wbGF0ZV9lc2NhcGVzW21hdGNoXTtcbn1cblxuZnVuY3Rpb24gdGVtcGxhdGVfZm9ybWF0KHBhdHRlcm4sIGtleSwgZm10KSB7XG4gIGlmICgocGF0dGVyblswXSA9PT0gJ1xcJycgJiYgcGF0dGVybltwYXR0ZXJuLmxlbmd0aC0xXSA9PT0gJ1xcJycpIHx8XG4gICAgICAocGF0dGVyblswXSA9PT0gJ1wiJyAgJiYgcGF0dGVybltwYXR0ZXJuLmxlbmd0aC0xXSA9PT0gJ1wiJykpIHtcbiAgICBwYXR0ZXJuID0gcGF0dGVybi5zbGljZSgxLCAtMSk7XG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgRXJyb3IoJ0Zvcm1hdCBwYXR0ZXJuIG11c3QgYmUgcXVvdGVkOiAnICsgcGF0dGVybik7XG4gIH1cbiAga2V5ID0ga2V5ICsgJzonICsgcGF0dGVybjtcbiAgaWYgKCFjb250ZXh0LmZvcm1hdF9tYXBba2V5XSkge1xuICAgIHZhciBmID0gZm10KHBhdHRlcm4pO1xuICAgIHZhciBpID0gY29udGV4dC5mb3JtYXRzLmxlbmd0aDtcbiAgICBjb250ZXh0LmZvcm1hdHMucHVzaChmKTtcbiAgICBjb250ZXh0LmZvcm1hdF9tYXBba2V5XSA9IGk7XG4gIH1cbiAgcmV0dXJuIGNvbnRleHQuZm9ybWF0X21hcFtrZXldO1xufVxuIiwidmFyIGQzX3RpbWUgPSByZXF1aXJlKCdkMy10aW1lJyk7XG5cbnZhciB0ZW1wRGF0ZSA9IG5ldyBEYXRlKCksXG4gICAgYmFzZURhdGUgPSBuZXcgRGF0ZSgwLCAwLCAxKS5zZXRGdWxsWWVhcigwKSwgLy8gSmFuIDEsIDAgQURcbiAgICB1dGNCYXNlRGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKDAsIDAsIDEpKS5zZXRVVENGdWxsWWVhcigwKTtcblxuZnVuY3Rpb24gZGF0ZShkKSB7XG4gIHJldHVybiAodGVtcERhdGUuc2V0VGltZSgrZCksIHRlbXBEYXRlKTtcbn1cblxuLy8gY3JlYXRlIGEgdGltZSB1bml0IGVudHJ5XG5mdW5jdGlvbiBlbnRyeSh0eXBlLCBkYXRlLCB1bml0LCBzdGVwLCBtaW4sIG1heCkge1xuICB2YXIgZSA9IHtcbiAgICB0eXBlOiB0eXBlLFxuICAgIGRhdGU6IGRhdGUsXG4gICAgdW5pdDogdW5pdFxuICB9O1xuICBpZiAoc3RlcCkge1xuICAgIGUuc3RlcCA9IHN0ZXA7XG4gIH0gZWxzZSB7XG4gICAgZS5taW5zdGVwID0gMTtcbiAgfVxuICBpZiAobWluICE9IG51bGwpIGUubWluID0gbWluO1xuICBpZiAobWF4ICE9IG51bGwpIGUubWF4ID0gbWF4O1xuICByZXR1cm4gZTtcbn1cblxuZnVuY3Rpb24gY3JlYXRlKHR5cGUsIHVuaXQsIGJhc2UsIHN0ZXAsIG1pbiwgbWF4KSB7XG4gIHJldHVybiBlbnRyeSh0eXBlLFxuICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIHVuaXQub2Zmc2V0KGJhc2UsIGQpOyB9LFxuICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIHVuaXQuY291bnQoYmFzZSwgZCk7IH0sXG4gICAgc3RlcCwgbWluLCBtYXgpO1xufVxuXG52YXIgbG9jYWxlID0gW1xuICBjcmVhdGUoJ3NlY29uZCcsIGQzX3RpbWUuc2Vjb25kLCBiYXNlRGF0ZSksXG4gIGNyZWF0ZSgnbWludXRlJywgZDNfdGltZS5taW51dGUsIGJhc2VEYXRlKSxcbiAgY3JlYXRlKCdob3VyJywgICBkM190aW1lLmhvdXIsICAgYmFzZURhdGUpLFxuICBjcmVhdGUoJ2RheScsICAgIGQzX3RpbWUuZGF5LCAgICBiYXNlRGF0ZSwgWzEsIDddKSxcbiAgY3JlYXRlKCdtb250aCcsICBkM190aW1lLm1vbnRoLCAgYmFzZURhdGUsIFsxLCAzLCA2XSksXG4gIGNyZWF0ZSgneWVhcicsICAgZDNfdGltZS55ZWFyLCAgIGJhc2VEYXRlKSxcblxuICAvLyBwZXJpb2RpYyB1bml0c1xuICBlbnRyeSgnc2Vjb25kcycsXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gbmV3IERhdGUoMTk3MCwgMCwgMSwgMCwgMCwgZCk7IH0sXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gZGF0ZShkKS5nZXRTZWNvbmRzKCk7IH0sXG4gICAgbnVsbCwgMCwgNTlcbiAgKSxcbiAgZW50cnkoJ21pbnV0ZXMnLFxuICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIG5ldyBEYXRlKDE5NzAsIDAsIDEsIDAsIGQpOyB9LFxuICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRhdGUoZCkuZ2V0TWludXRlcygpOyB9LFxuICAgIG51bGwsIDAsIDU5XG4gICksXG4gIGVudHJ5KCdob3VycycsXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gbmV3IERhdGUoMTk3MCwgMCwgMSwgZCk7IH0sXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gZGF0ZShkKS5nZXRIb3VycygpOyB9LFxuICAgIG51bGwsIDAsIDIzXG4gICksXG4gIGVudHJ5KCd3ZWVrZGF5cycsXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gbmV3IERhdGUoMTk3MCwgMCwgNCtkKTsgfSxcbiAgICBmdW5jdGlvbihkKSB7IHJldHVybiBkYXRlKGQpLmdldERheSgpOyB9LFxuICAgIFsxXSwgMCwgNlxuICApLFxuICBlbnRyeSgnZGF0ZXMnLFxuICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIG5ldyBEYXRlKDE5NzAsIDAsIGQpOyB9LFxuICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRhdGUoZCkuZ2V0RGF0ZSgpOyB9LFxuICAgIFsxXSwgMSwgMzFcbiAgKSxcbiAgZW50cnkoJ21vbnRocycsXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gbmV3IERhdGUoMTk3MCwgZCAlIDEyLCAxKTsgfSxcbiAgICBmdW5jdGlvbihkKSB7IHJldHVybiBkYXRlKGQpLmdldE1vbnRoKCk7IH0sXG4gICAgWzFdLCAwLCAxMVxuICApXG5dO1xuXG52YXIgdXRjID0gW1xuICBjcmVhdGUoJ3NlY29uZCcsIGQzX3RpbWUudXRjU2Vjb25kLCB1dGNCYXNlRGF0ZSksXG4gIGNyZWF0ZSgnbWludXRlJywgZDNfdGltZS51dGNNaW51dGUsIHV0Y0Jhc2VEYXRlKSxcbiAgY3JlYXRlKCdob3VyJywgICBkM190aW1lLnV0Y0hvdXIsICAgdXRjQmFzZURhdGUpLFxuICBjcmVhdGUoJ2RheScsICAgIGQzX3RpbWUudXRjRGF5LCAgICB1dGNCYXNlRGF0ZSwgWzEsIDddKSxcbiAgY3JlYXRlKCdtb250aCcsICBkM190aW1lLnV0Y01vbnRoLCAgdXRjQmFzZURhdGUsIFsxLCAzLCA2XSksXG4gIGNyZWF0ZSgneWVhcicsICAgZDNfdGltZS51dGNZZWFyLCAgIHV0Y0Jhc2VEYXRlKSxcblxuICAvLyBwZXJpb2RpYyB1bml0c1xuICBlbnRyeSgnc2Vjb25kcycsXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gbmV3IERhdGUoRGF0ZS5VVEMoMTk3MCwgMCwgMSwgMCwgMCwgZCkpOyB9LFxuICAgIGZ1bmN0aW9uKGQpIHsgcmV0dXJuIGRhdGUoZCkuZ2V0VVRDU2Vjb25kcygpOyB9LFxuICAgIG51bGwsIDAsIDU5XG4gICksXG4gIGVudHJ5KCdtaW51dGVzJyxcbiAgICBmdW5jdGlvbihkKSB7IHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQygxOTcwLCAwLCAxLCAwLCBkKSk7IH0sXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gZGF0ZShkKS5nZXRVVENNaW51dGVzKCk7IH0sXG4gICAgbnVsbCwgMCwgNTlcbiAgKSxcbiAgZW50cnkoJ2hvdXJzJyxcbiAgICBmdW5jdGlvbihkKSB7IHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQygxOTcwLCAwLCAxLCBkKSk7IH0sXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gZGF0ZShkKS5nZXRVVENIb3VycygpOyB9LFxuICAgIG51bGwsIDAsIDIzXG4gICksXG4gIGVudHJ5KCd3ZWVrZGF5cycsXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gbmV3IERhdGUoRGF0ZS5VVEMoMTk3MCwgMCwgNCtkKSk7IH0sXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gZGF0ZShkKS5nZXRVVENEYXkoKTsgfSxcbiAgICBbMV0sIDAsIDZcbiAgKSxcbiAgZW50cnkoJ2RhdGVzJyxcbiAgICBmdW5jdGlvbihkKSB7IHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQygxOTcwLCAwLCBkKSk7IH0sXG4gICAgZnVuY3Rpb24oZCkgeyByZXR1cm4gZGF0ZShkKS5nZXRVVENEYXRlKCk7IH0sXG4gICAgWzFdLCAxLCAzMVxuICApLFxuICBlbnRyeSgnbW9udGhzJyxcbiAgICBmdW5jdGlvbihkKSB7IHJldHVybiBuZXcgRGF0ZShEYXRlLlVUQygxOTcwLCBkICUgMTIsIDEpKTsgfSxcbiAgICBmdW5jdGlvbihkKSB7IHJldHVybiBkYXRlKGQpLmdldFVUQ01vbnRoKCk7IH0sXG4gICAgWzFdLCAwLCAxMVxuICApXG5dO1xuXG52YXIgU1RFUFMgPSBbXG4gIFszMTUzNmU2LCA1XSwgIC8vIDEteWVhclxuICBbNzc3NmU2LCA0XSwgICAvLyAzLW1vbnRoXG4gIFsyNTkyZTYsIDRdLCAgIC8vIDEtbW9udGhcbiAgWzEyMDk2ZTUsIDNdLCAgLy8gMi13ZWVrXG4gIFs2MDQ4ZTUsIDNdLCAgIC8vIDEtd2Vla1xuICBbMTcyOGU1LCAzXSwgICAvLyAyLWRheVxuICBbODY0ZTUsIDNdLCAgICAvLyAxLWRheVxuICBbNDMyZTUsIDJdLCAgICAvLyAxMi1ob3VyXG4gIFsyMTZlNSwgMl0sICAgIC8vIDYtaG91clxuICBbMTA4ZTUsIDJdLCAgICAvLyAzLWhvdXJcbiAgWzM2ZTUsIDJdLCAgICAgLy8gMS1ob3VyXG4gIFsxOGU1LCAxXSwgICAgIC8vIDMwLW1pbnV0ZVxuICBbOWU1LCAxXSwgICAgICAvLyAxNS1taW51dGVcbiAgWzNlNSwgMV0sICAgICAgLy8gNS1taW51dGVcbiAgWzZlNCwgMV0sICAgICAgLy8gMS1taW51dGVcbiAgWzNlNCwgMF0sICAgICAgLy8gMzAtc2Vjb25kXG4gIFsxNWUzLCAwXSwgICAgIC8vIDE1LXNlY29uZFxuICBbNWUzLCAwXSwgICAgICAvLyA1LXNlY29uZFxuICBbMWUzLCAwXSAgICAgICAvLyAxLXNlY29uZFxuXTtcblxuZnVuY3Rpb24gZmluZCh1bml0cywgc3BhbiwgbWluYiwgbWF4Yikge1xuICB2YXIgc3RlcCA9IFNURVBTWzBdLCBpLCBuLCBiaW5zO1xuXG4gIGZvciAoaT0xLCBuPVNURVBTLmxlbmd0aDsgaTxuOyArK2kpIHtcbiAgICBzdGVwID0gU1RFUFNbaV07XG4gICAgaWYgKHNwYW4gPiBzdGVwWzBdKSB7XG4gICAgICBiaW5zID0gc3BhbiAvIHN0ZXBbMF07XG4gICAgICBpZiAoYmlucyA+IG1heGIpIHtcbiAgICAgICAgcmV0dXJuIHVuaXRzW1NURVBTW2ktMV1bMV1dO1xuICAgICAgfVxuICAgICAgaWYgKGJpbnMgPj0gbWluYikge1xuICAgICAgICByZXR1cm4gdW5pdHNbc3RlcFsxXV07XG4gICAgICB9XG4gICAgfVxuICB9XG4gIHJldHVybiB1bml0c1tTVEVQU1tuLTFdWzFdXTtcbn1cblxuZnVuY3Rpb24gdG9Vbml0TWFwKHVuaXRzKSB7XG4gIHZhciBtYXAgPSB7fSwgaSwgbjtcbiAgZm9yIChpPTAsIG49dW5pdHMubGVuZ3RoOyBpPG47ICsraSkge1xuICAgIG1hcFt1bml0c1tpXS50eXBlXSA9IHVuaXRzW2ldO1xuICB9XG4gIG1hcC5maW5kID0gZnVuY3Rpb24oc3BhbiwgbWluYiwgbWF4Yikge1xuICAgIHJldHVybiBmaW5kKHVuaXRzLCBzcGFuLCBtaW5iLCBtYXhiKTtcbiAgfTtcbiAgcmV0dXJuIG1hcDtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB0b1VuaXRNYXAobG9jYWxlKTtcbm1vZHVsZS5leHBvcnRzLnV0YyA9IHRvVW5pdE1hcCh1dGMpO1xuIiwidmFyIGJ1ZmZlciA9IHJlcXVpcmUoJ2J1ZmZlcicpLFxuICAgIHRpbWUgPSByZXF1aXJlKCcuL3RpbWUnKSxcbiAgICB1dGMgPSB0aW1lLnV0YztcblxudmFyIHUgPSBtb2R1bGUuZXhwb3J0cyA9IHt9O1xuXG4vLyB1dGlsaXR5IGZ1bmN0aW9uc1xuXG52YXIgRk5BTUUgPSAnX19uYW1lX18nO1xuXG51Lm5hbWVkZnVuYyA9IGZ1bmN0aW9uKG5hbWUsIGYpIHsgcmV0dXJuIChmW0ZOQU1FXSA9IG5hbWUsIGYpOyB9O1xuXG51Lm5hbWUgPSBmdW5jdGlvbihmKSB7IHJldHVybiBmPT1udWxsID8gbnVsbCA6IGZbRk5BTUVdOyB9O1xuXG51LmlkZW50aXR5ID0gZnVuY3Rpb24oeCkgeyByZXR1cm4geDsgfTtcblxudS50cnVlID0gdS5uYW1lZGZ1bmMoJ3RydWUnLCBmdW5jdGlvbigpIHsgcmV0dXJuIHRydWU7IH0pO1xuXG51LmZhbHNlID0gdS5uYW1lZGZ1bmMoJ2ZhbHNlJywgZnVuY3Rpb24oKSB7IHJldHVybiBmYWxzZTsgfSk7XG5cbnUuZHVwbGljYXRlID0gZnVuY3Rpb24ob2JqKSB7XG4gIHJldHVybiBKU09OLnBhcnNlKEpTT04uc3RyaW5naWZ5KG9iaikpO1xufTtcblxudS5lcXVhbCA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGEpID09PSBKU09OLnN0cmluZ2lmeShiKTtcbn07XG5cbnUuZXh0ZW5kID0gZnVuY3Rpb24ob2JqKSB7XG4gIGZvciAodmFyIHgsIG5hbWUsIGk9MSwgbGVuPWFyZ3VtZW50cy5sZW5ndGg7IGk8bGVuOyArK2kpIHtcbiAgICB4ID0gYXJndW1lbnRzW2ldO1xuICAgIGZvciAobmFtZSBpbiB4KSB7IG9ialtuYW1lXSA9IHhbbmFtZV07IH1cbiAgfVxuICByZXR1cm4gb2JqO1xufTtcblxudS5sZW5ndGggPSBmdW5jdGlvbih4KSB7XG4gIHJldHVybiB4ICE9IG51bGwgJiYgeC5sZW5ndGggIT0gbnVsbCA/IHgubGVuZ3RoIDogbnVsbDtcbn07XG5cbnUua2V5cyA9IGZ1bmN0aW9uKHgpIHtcbiAgdmFyIGtleXMgPSBbXSwgaztcbiAgZm9yIChrIGluIHgpIGtleXMucHVzaChrKTtcbiAgcmV0dXJuIGtleXM7XG59O1xuXG51LnZhbHMgPSBmdW5jdGlvbih4KSB7XG4gIHZhciB2YWxzID0gW10sIGs7XG4gIGZvciAoayBpbiB4KSB2YWxzLnB1c2goeFtrXSk7XG4gIHJldHVybiB2YWxzO1xufTtcblxudS50b01hcCA9IGZ1bmN0aW9uKGxpc3QsIGYpIHtcbiAgcmV0dXJuIChmID0gdS4kKGYpKSA/XG4gICAgbGlzdC5yZWR1Y2UoZnVuY3Rpb24ob2JqLCB4KSB7IHJldHVybiAob2JqW2YoeCldID0gMSwgb2JqKTsgfSwge30pIDpcbiAgICBsaXN0LnJlZHVjZShmdW5jdGlvbihvYmosIHgpIHsgcmV0dXJuIChvYmpbeF0gPSAxLCBvYmopOyB9LCB7fSk7XG59O1xuXG51LmtleXN0ciA9IGZ1bmN0aW9uKHZhbHVlcykge1xuICAvLyB1c2UgdG8gZW5zdXJlIGNvbnNpc3RlbnQga2V5IGdlbmVyYXRpb24gYWNyb3NzIG1vZHVsZXNcbiAgdmFyIG4gPSB2YWx1ZXMubGVuZ3RoO1xuICBpZiAoIW4pIHJldHVybiAnJztcbiAgZm9yICh2YXIgcz1TdHJpbmcodmFsdWVzWzBdKSwgaT0xOyBpPG47ICsraSkge1xuICAgIHMgKz0gJ3wnICsgU3RyaW5nKHZhbHVlc1tpXSk7XG4gIH1cbiAgcmV0dXJuIHM7XG59O1xuXG4vLyB0eXBlIGNoZWNraW5nIGZ1bmN0aW9uc1xuXG52YXIgdG9TdHJpbmcgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xuXG51LmlzT2JqZWN0ID0gZnVuY3Rpb24ob2JqKSB7XG4gIHJldHVybiBvYmogPT09IE9iamVjdChvYmopO1xufTtcblxudS5pc0Z1bmN0aW9uID0gZnVuY3Rpb24ob2JqKSB7XG4gIHJldHVybiB0b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG59O1xuXG51LmlzU3RyaW5nID0gZnVuY3Rpb24ob2JqKSB7XG4gIHJldHVybiB0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgU3RyaW5nXSc7XG59O1xuXG51LmlzQXJyYXkgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uKG9iaikge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBBcnJheV0nO1xufTtcblxudS5pc051bWJlciA9IGZ1bmN0aW9uKG9iaikge1xuICByZXR1cm4gdHlwZW9mIG9iaiA9PT0gJ251bWJlcicgfHwgdG9TdHJpbmcuY2FsbChvYmopID09PSAnW29iamVjdCBOdW1iZXJdJztcbn07XG5cbnUuaXNCb29sZWFuID0gZnVuY3Rpb24ob2JqKSB7XG4gIHJldHVybiBvYmogPT09IHRydWUgfHwgb2JqID09PSBmYWxzZSB8fCB0b1N0cmluZy5jYWxsKG9iaikgPT0gJ1tvYmplY3QgQm9vbGVhbl0nO1xufTtcblxudS5pc0RhdGUgPSBmdW5jdGlvbihvYmopIHtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufTtcblxudS5pc1ZhbGlkID0gZnVuY3Rpb24ob2JqKSB7XG4gIHJldHVybiBvYmogIT0gbnVsbCAmJiBvYmogPT09IG9iajtcbn07XG5cbnUuaXNCdWZmZXIgPSAoYnVmZmVyLkJ1ZmZlciAmJiBidWZmZXIuQnVmZmVyLmlzQnVmZmVyKSB8fCB1LmZhbHNlO1xuXG4vLyB0eXBlIGNvZXJjaW9uIGZ1bmN0aW9uc1xuXG51Lm51bWJlciA9IGZ1bmN0aW9uKHMpIHtcbiAgcmV0dXJuIHMgPT0gbnVsbCB8fCBzID09PSAnJyA/IG51bGwgOiArcztcbn07XG5cbnUuYm9vbGVhbiA9IGZ1bmN0aW9uKHMpIHtcbiAgcmV0dXJuIHMgPT0gbnVsbCB8fCBzID09PSAnJyA/IG51bGwgOiBzPT09J2ZhbHNlJyA/IGZhbHNlIDogISFzO1xufTtcblxudS5kYXRlID0gZnVuY3Rpb24ocykge1xuICByZXR1cm4gcyA9PSBudWxsIHx8IHMgPT09ICcnID8gbnVsbCA6IERhdGUucGFyc2Uocyk7XG59O1xuXG51LmFycmF5ID0gZnVuY3Rpb24oeCkge1xuICByZXR1cm4geCAhPSBudWxsID8gKHUuaXNBcnJheSh4KSA/IHggOiBbeF0pIDogW107XG59O1xuXG51LnN0ciA9IGZ1bmN0aW9uKHgpIHtcbiAgcmV0dXJuIHUuaXNBcnJheSh4KSA/ICdbJyArIHgubWFwKHUuc3RyKSArICddJ1xuICAgIDogdS5pc09iamVjdCh4KSA/IEpTT04uc3RyaW5naWZ5KHgpXG4gICAgOiB1LmlzU3RyaW5nKHgpID8gKCdcXCcnK3V0aWxfZXNjYXBlX3N0cih4KSsnXFwnJykgOiB4O1xufTtcblxudmFyIGVzY2FwZV9zdHJfcmUgPSAvKF58W15cXFxcXSknL2c7XG5cbmZ1bmN0aW9uIHV0aWxfZXNjYXBlX3N0cih4KSB7XG4gIHJldHVybiB4LnJlcGxhY2UoZXNjYXBlX3N0cl9yZSwgJyQxXFxcXFxcJycpO1xufVxuXG4vLyBkYXRhIGFjY2VzcyBmdW5jdGlvbnNcblxudmFyIGZpZWxkX3JlID0gL1xcWyguKj8pXFxdfFteLlxcW10rL2c7XG5cbnUuZmllbGQgPSBmdW5jdGlvbihmKSB7XG4gIHJldHVybiBTdHJpbmcoZikubWF0Y2goZmllbGRfcmUpLm1hcChmdW5jdGlvbihkKSB7XG4gICAgcmV0dXJuIGRbMF0gIT09ICdbJyA/IGQgOlxuICAgICAgZFsxXSAhPT0gXCInXCIgJiYgZFsxXSAhPT0gJ1wiJyA/IGQuc2xpY2UoMSwgLTEpIDpcbiAgICAgIGQuc2xpY2UoMiwgLTIpLnJlcGxhY2UoL1xcXFwoW1wiJ10pL2csICckMScpO1xuICB9KTtcbn07XG5cbnUuYWNjZXNzb3IgPSBmdW5jdGlvbihmKSB7XG4gIHZhciBzO1xuICByZXR1cm4gZj09bnVsbCB8fCB1LmlzRnVuY3Rpb24oZikgPyBmIDpcbiAgICB1Lm5hbWVkZnVuYyhmLCAocyA9IHUuZmllbGQoZikpLmxlbmd0aCA+IDEgP1xuICAgICAgZnVuY3Rpb24oeCkgeyByZXR1cm4gcy5yZWR1Y2UoZnVuY3Rpb24oeCxmKSB7IHJldHVybiB4W2ZdOyB9LCB4KTsgfSA6XG4gICAgICBmdW5jdGlvbih4KSB7IHJldHVybiB4W2ZdOyB9XG4gICAgKTtcbn07XG5cbi8vIHNob3J0LWN1dCBmb3IgYWNjZXNzb3JcbnUuJCA9IHUuYWNjZXNzb3I7XG5cbnUubXV0YXRvciA9IGZ1bmN0aW9uKGYpIHtcbiAgdmFyIHM7XG4gIHJldHVybiB1LmlzU3RyaW5nKGYpICYmIChzPXUuZmllbGQoZikpLmxlbmd0aCA+IDEgP1xuICAgIGZ1bmN0aW9uKHgsIHYpIHtcbiAgICAgIGZvciAodmFyIGk9MDsgaTxzLmxlbmd0aC0xOyArK2kpIHggPSB4W3NbaV1dO1xuICAgICAgeFtzW2ldXSA9IHY7XG4gICAgfSA6XG4gICAgZnVuY3Rpb24oeCwgdikgeyB4W2ZdID0gdjsgfTtcbn07XG5cblxudS4kZnVuYyA9IGZ1bmN0aW9uKG5hbWUsIG9wKSB7XG4gIHJldHVybiBmdW5jdGlvbihmKSB7XG4gICAgZiA9IHUuJChmKSB8fCB1LmlkZW50aXR5O1xuICAgIHZhciBuID0gbmFtZSArICh1Lm5hbWUoZikgPyAnXycrdS5uYW1lKGYpIDogJycpO1xuICAgIHJldHVybiB1Lm5hbWVkZnVuYyhuLCBmdW5jdGlvbihkKSB7IHJldHVybiBvcChmKGQpKTsgfSk7XG4gIH07XG59O1xuXG51LiR2YWxpZCAgPSB1LiRmdW5jKCd2YWxpZCcsIHUuaXNWYWxpZCk7XG51LiRsZW5ndGggPSB1LiRmdW5jKCdsZW5ndGgnLCB1Lmxlbmd0aCk7XG5cbnUuJGluID0gZnVuY3Rpb24oZiwgdmFsdWVzKSB7XG4gIGYgPSB1LiQoZik7XG4gIHZhciBtYXAgPSB1LmlzQXJyYXkodmFsdWVzKSA/IHUudG9NYXAodmFsdWVzKSA6IHZhbHVlcztcbiAgcmV0dXJuIGZ1bmN0aW9uKGQpIHsgcmV0dXJuICEhbWFwW2YoZCldOyB9O1xufTtcblxudS4keWVhciAgID0gdS4kZnVuYygneWVhcicsIHRpbWUueWVhci51bml0KTtcbnUuJG1vbnRoICA9IHUuJGZ1bmMoJ21vbnRoJywgdGltZS5tb250aHMudW5pdCk7XG51LiRkYXRlICAgPSB1LiRmdW5jKCdkYXRlJywgdGltZS5kYXRlcy51bml0KTtcbnUuJGRheSAgICA9IHUuJGZ1bmMoJ2RheScsIHRpbWUud2Vla2RheXMudW5pdCk7XG51LiRob3VyICAgPSB1LiRmdW5jKCdob3VyJywgdGltZS5ob3Vycy51bml0KTtcbnUuJG1pbnV0ZSA9IHUuJGZ1bmMoJ21pbnV0ZScsIHRpbWUubWludXRlcy51bml0KTtcbnUuJHNlY29uZCA9IHUuJGZ1bmMoJ3NlY29uZCcsIHRpbWUuc2Vjb25kcy51bml0KTtcblxudS4kdXRjWWVhciAgID0gdS4kZnVuYygndXRjWWVhcicsIHV0Yy55ZWFyLnVuaXQpO1xudS4kdXRjTW9udGggID0gdS4kZnVuYygndXRjTW9udGgnLCB1dGMubW9udGhzLnVuaXQpO1xudS4kdXRjRGF0ZSAgID0gdS4kZnVuYygndXRjRGF0ZScsIHV0Yy5kYXRlcy51bml0KTtcbnUuJHV0Y0RheSAgICA9IHUuJGZ1bmMoJ3V0Y0RheScsIHV0Yy53ZWVrZGF5cy51bml0KTtcbnUuJHV0Y0hvdXIgICA9IHUuJGZ1bmMoJ3V0Y0hvdXInLCB1dGMuaG91cnMudW5pdCk7XG51LiR1dGNNaW51dGUgPSB1LiRmdW5jKCd1dGNNaW51dGUnLCB1dGMubWludXRlcy51bml0KTtcbnUuJHV0Y1NlY29uZCA9IHUuJGZ1bmMoJ3V0Y1NlY29uZCcsIHV0Yy5zZWNvbmRzLnVuaXQpO1xuXG4vLyBjb21wYXJpc29uIC8gc29ydGluZyBmdW5jdGlvbnNcblxudS5jb21wYXJhdG9yID0gZnVuY3Rpb24oc29ydCkge1xuICB2YXIgc2lnbiA9IFtdO1xuICBpZiAoc29ydCA9PT0gdW5kZWZpbmVkKSBzb3J0ID0gW107XG4gIHNvcnQgPSB1LmFycmF5KHNvcnQpLm1hcChmdW5jdGlvbihmKSB7XG4gICAgdmFyIHMgPSAxO1xuICAgIGlmICAgICAgKGZbMF0gPT09ICctJykgeyBzID0gLTE7IGYgPSBmLnNsaWNlKDEpOyB9XG4gICAgZWxzZSBpZiAoZlswXSA9PT0gJysnKSB7IHMgPSArMTsgZiA9IGYuc2xpY2UoMSk7IH1cbiAgICBzaWduLnB1c2gocyk7XG4gICAgcmV0dXJuIHUuYWNjZXNzb3IoZik7XG4gIH0pO1xuICByZXR1cm4gZnVuY3Rpb24oYSxiKSB7XG4gICAgdmFyIGksIG4sIGYsIHgsIHk7XG4gICAgZm9yIChpPTAsIG49c29ydC5sZW5ndGg7IGk8bjsgKytpKSB7XG4gICAgICBmID0gc29ydFtpXTsgeCA9IGYoYSk7IHkgPSBmKGIpO1xuICAgICAgaWYgKHggPCB5KSByZXR1cm4gLTEgKiBzaWduW2ldO1xuICAgICAgaWYgKHggPiB5KSByZXR1cm4gc2lnbltpXTtcbiAgICB9XG4gICAgcmV0dXJuIDA7XG4gIH07XG59O1xuXG51LmNtcCA9IGZ1bmN0aW9uKGEsIGIpIHtcbiAgaWYgKGEgPCBiKSB7XG4gICAgcmV0dXJuIC0xO1xuICB9IGVsc2UgaWYgKGEgPiBiKSB7XG4gICAgcmV0dXJuIDE7XG4gIH0gZWxzZSBpZiAoYSA+PSBiKSB7XG4gICAgcmV0dXJuIDA7XG4gIH0gZWxzZSBpZiAoYSA9PT0gbnVsbCkge1xuICAgIHJldHVybiAtMTtcbiAgfSBlbHNlIGlmIChiID09PSBudWxsKSB7XG4gICAgcmV0dXJuIDE7XG4gIH1cbiAgcmV0dXJuIE5hTjtcbn07XG5cbnUubnVtY21wID0gZnVuY3Rpb24oYSwgYikgeyByZXR1cm4gYSAtIGI7IH07XG5cbnUuc3RhYmxlc29ydCA9IGZ1bmN0aW9uKGFycmF5LCBzb3J0QnksIGtleUZuKSB7XG4gIHZhciBpbmRpY2VzID0gYXJyYXkucmVkdWNlKGZ1bmN0aW9uKGlkeCwgdiwgaSkge1xuICAgIHJldHVybiAoaWR4W2tleUZuKHYpXSA9IGksIGlkeCk7XG4gIH0sIHt9KTtcblxuICBhcnJheS5zb3J0KGZ1bmN0aW9uKGEsIGIpIHtcbiAgICB2YXIgc2EgPSBzb3J0QnkoYSksXG4gICAgICAgIHNiID0gc29ydEJ5KGIpO1xuICAgIHJldHVybiBzYSA8IHNiID8gLTEgOiBzYSA+IHNiID8gMVxuICAgICAgICAgOiAoaW5kaWNlc1trZXlGbihhKV0gLSBpbmRpY2VzW2tleUZuKGIpXSk7XG4gIH0pO1xuXG4gIHJldHVybiBhcnJheTtcbn07XG5cblxuLy8gc3RyaW5nIGZ1bmN0aW9uc1xuXG51LnBhZCA9IGZ1bmN0aW9uKHMsIGxlbmd0aCwgcG9zLCBwYWRjaGFyKSB7XG4gIHBhZGNoYXIgPSBwYWRjaGFyIHx8IFwiIFwiO1xuICB2YXIgZCA9IGxlbmd0aCAtIHMubGVuZ3RoO1xuICBpZiAoZCA8PSAwKSByZXR1cm4gcztcbiAgc3dpdGNoIChwb3MpIHtcbiAgICBjYXNlICdsZWZ0JzpcbiAgICAgIHJldHVybiBzdHJyZXAoZCwgcGFkY2hhcikgKyBzO1xuICAgIGNhc2UgJ21pZGRsZSc6XG4gICAgY2FzZSAnY2VudGVyJzpcbiAgICAgIHJldHVybiBzdHJyZXAoTWF0aC5mbG9vcihkLzIpLCBwYWRjaGFyKSArXG4gICAgICAgICBzICsgc3RycmVwKE1hdGguY2VpbChkLzIpLCBwYWRjaGFyKTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIHMgKyBzdHJyZXAoZCwgcGFkY2hhcik7XG4gIH1cbn07XG5cbmZ1bmN0aW9uIHN0cnJlcChuLCBzdHIpIHtcbiAgdmFyIHMgPSBcIlwiLCBpO1xuICBmb3IgKGk9MDsgaTxuOyArK2kpIHMgKz0gc3RyO1xuICByZXR1cm4gcztcbn1cblxudS50cnVuY2F0ZSA9IGZ1bmN0aW9uKHMsIGxlbmd0aCwgcG9zLCB3b3JkLCBlbGxpcHNpcykge1xuICB2YXIgbGVuID0gcy5sZW5ndGg7XG4gIGlmIChsZW4gPD0gbGVuZ3RoKSByZXR1cm4gcztcbiAgZWxsaXBzaXMgPSBlbGxpcHNpcyAhPT0gdW5kZWZpbmVkID8gU3RyaW5nKGVsbGlwc2lzKSA6ICdcXHUyMDI2JztcbiAgdmFyIGwgPSBNYXRoLm1heCgwLCBsZW5ndGggLSBlbGxpcHNpcy5sZW5ndGgpO1xuXG4gIHN3aXRjaCAocG9zKSB7XG4gICAgY2FzZSAnbGVmdCc6XG4gICAgICByZXR1cm4gZWxsaXBzaXMgKyAod29yZCA/IHRydW5jYXRlT25Xb3JkKHMsbCwxKSA6IHMuc2xpY2UobGVuLWwpKTtcbiAgICBjYXNlICdtaWRkbGUnOlxuICAgIGNhc2UgJ2NlbnRlcic6XG4gICAgICB2YXIgbDEgPSBNYXRoLmNlaWwobC8yKSwgbDIgPSBNYXRoLmZsb29yKGwvMik7XG4gICAgICByZXR1cm4gKHdvcmQgPyB0cnVuY2F0ZU9uV29yZChzLGwxKSA6IHMuc2xpY2UoMCxsMSkpICtcbiAgICAgICAgZWxsaXBzaXMgKyAod29yZCA/IHRydW5jYXRlT25Xb3JkKHMsbDIsMSkgOiBzLnNsaWNlKGxlbi1sMikpO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gKHdvcmQgPyB0cnVuY2F0ZU9uV29yZChzLGwpIDogcy5zbGljZSgwLGwpKSArIGVsbGlwc2lzO1xuICB9XG59O1xuXG5mdW5jdGlvbiB0cnVuY2F0ZU9uV29yZChzLCBsZW4sIHJldikge1xuICB2YXIgY250ID0gMCwgdG9rID0gcy5zcGxpdCh0cnVuY2F0ZV93b3JkX3JlKTtcbiAgaWYgKHJldikge1xuICAgIHMgPSAodG9rID0gdG9rLnJldmVyc2UoKSlcbiAgICAgIC5maWx0ZXIoZnVuY3Rpb24odykgeyBjbnQgKz0gdy5sZW5ndGg7IHJldHVybiBjbnQgPD0gbGVuOyB9KVxuICAgICAgLnJldmVyc2UoKTtcbiAgfSBlbHNlIHtcbiAgICBzID0gdG9rLmZpbHRlcihmdW5jdGlvbih3KSB7IGNudCArPSB3Lmxlbmd0aDsgcmV0dXJuIGNudCA8PSBsZW47IH0pO1xuICB9XG4gIHJldHVybiBzLmxlbmd0aCA/IHMuam9pbignJykudHJpbSgpIDogdG9rWzBdLnNsaWNlKDAsIGxlbik7XG59XG5cbnZhciB0cnVuY2F0ZV93b3JkX3JlID0gLyhbXFx1MDAwOVxcdTAwMEFcXHUwMDBCXFx1MDAwQ1xcdTAwMERcXHUwMDIwXFx1MDBBMFxcdTE2ODBcXHUxODBFXFx1MjAwMFxcdTIwMDFcXHUyMDAyXFx1MjAwM1xcdTIwMDRcXHUyMDA1XFx1MjAwNlxcdTIwMDdcXHUyMDA4XFx1MjAwOVxcdTIwMEFcXHUyMDJGXFx1MjA1RlxcdTIwMjhcXHUyMDI5XFx1MzAwMFxcdUZFRkZdKS87XG4iXX0= |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment