Skip to content

Instantly share code, notes, and snippets.

@hfitzwater
Created July 27, 2017 16:59
Show Gist options
  • Save hfitzwater/cd6e40309a4995d0026dbd59fb960fc1 to your computer and use it in GitHub Desktop.
Save hfitzwater/cd6e40309a4995d0026dbd59fb960fc1 to your computer and use it in GitHub Desktop.
requirebin sketch
// Welcome! require() some modules from npm (like you were using browserify)
// and then hit Run Code to run your code on the right side.
// Modules get downloaded from browserify-cdn and bundled in your browser.
let fecha = require('fecha');
let moment = require('moment');
require('datejs'); // modifies Date
console.log( moment );
const FORMAT = {
DASH: 'MM-DD-YYYY',
SLASH: 'MM/DD/YYYY',
NATA_DASH: 'DD-MM-YYYY',
NATA_SLASH: 'DD/MM/YYYY'
};
const TESTS = [
'11111111111',
'asdfasdfasdf',
'01/55/2017',
'01/01/2017'
];
function testGroup( tests, format ) {
console.log( format );
console.log( '----------------');
console.log( 'FECHA' );
tests.forEach( t => {
testFecha( t, format );
});
console.log( 'MOMENT' );
tests.forEach( t => {
testMoment( t, format );
});
console.log( 'DATEJS' );
tests.forEach( t => {
testDatejs( t, format );
});
console.log( '\n\n');
}
function testFecha( str, format ) {
let d = fecha.parse( str, format );
console.log( ' ' + str, d );
}
function testMoment( str, format ) {
let d = moment( str, format, true );
console.log( ' ' + d.isValid() );
}
function testDatejs( str, format ) {
let d = Date.parse( str, format );
console.log( ' ' + d );
}
Object.keys(FORMAT).forEach( key => {
testGroup( TESTS, FORMAT[key] );
});
setTimeout(function(){
;require=(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})({"fecha":[function(require,module,exports){
(function (main) {
'use strict';
/**
* Parse or format dates
* @class fecha
*/
var fecha = {};
var token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
var twoDigits = /\d\d?/;
var threeDigits = /\d{3}/;
var fourDigits = /\d{4}/;
var word = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
var noop = function () {
};
function shorten(arr, sLen) {
var newArr = [];
for (var i = 0, len = arr.length; i < len; i++) {
newArr.push(arr[i].substr(0, sLen));
}
return newArr;
}
function monthUpdate(arrName) {
return function (d, v, i18n) {
var index = i18n[arrName].indexOf(v.charAt(0).toUpperCase() + v.substr(1).toLowerCase());
if (~index) {
d.month = index;
}
};
}
function pad(val, len) {
val = String(val);
len = len || 2;
while (val.length < len) {
val = '0' + val;
}
return val;
}
var dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var monthNamesShort = shorten(monthNames, 3);
var dayNamesShort = shorten(dayNames, 3);
fecha.i18n = {
dayNamesShort: dayNamesShort,
dayNames: dayNames,
monthNamesShort: monthNamesShort,
monthNames: monthNames,
amPm: ['am', 'pm'],
DoFn: function DoFn(D) {
return D + ['th', 'st', 'nd', 'rd'][D % 10 > 3 ? 0 : (D - D % 10 !== 10) * D % 10];
}
};
var formatFlags = {
D: function(dateObj) {
return dateObj.getDate();
},
DD: function(dateObj) {
return pad(dateObj.getDate());
},
Do: function(dateObj, i18n) {
return i18n.DoFn(dateObj.getDate());
},
d: function(dateObj) {
return dateObj.getDay();
},
dd: function(dateObj) {
return pad(dateObj.getDay());
},
ddd: function(dateObj, i18n) {
return i18n.dayNamesShort[dateObj.getDay()];
},
dddd: function(dateObj, i18n) {
return i18n.dayNames[dateObj.getDay()];
},
M: function(dateObj) {
return dateObj.getMonth() + 1;
},
MM: function(dateObj) {
return pad(dateObj.getMonth() + 1);
},
MMM: function(dateObj, i18n) {
return i18n.monthNamesShort[dateObj.getMonth()];
},
MMMM: function(dateObj, i18n) {
return i18n.monthNames[dateObj.getMonth()];
},
YY: function(dateObj) {
return String(dateObj.getFullYear()).substr(2);
},
YYYY: function(dateObj) {
return dateObj.getFullYear();
},
h: function(dateObj) {
return dateObj.getHours() % 12 || 12;
},
hh: function(dateObj) {
return pad(dateObj.getHours() % 12 || 12);
},
H: function(dateObj) {
return dateObj.getHours();
},
HH: function(dateObj) {
return pad(dateObj.getHours());
},
m: function(dateObj) {
return dateObj.getMinutes();
},
mm: function(dateObj) {
return pad(dateObj.getMinutes());
},
s: function(dateObj) {
return dateObj.getSeconds();
},
ss: function(dateObj) {
return pad(dateObj.getSeconds());
},
S: function(dateObj) {
return Math.round(dateObj.getMilliseconds() / 100);
},
SS: function(dateObj) {
return pad(Math.round(dateObj.getMilliseconds() / 10), 2);
},
SSS: function(dateObj) {
return pad(dateObj.getMilliseconds(), 3);
},
a: function(dateObj, i18n) {
return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1];
},
A: function(dateObj, i18n) {
return dateObj.getHours() < 12 ? i18n.amPm[0].toUpperCase() : i18n.amPm[1].toUpperCase();
},
ZZ: function(dateObj) {
var o = dateObj.getTimezoneOffset();
return (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4);
}
};
var parseFlags = {
D: [twoDigits, function (d, v) {
d.day = v;
}],
Do: [new RegExp(twoDigits.source + word.source), function (d, v) {
d.day = parseInt(v, 10);
}],
M: [twoDigits, function (d, v) {
d.month = v - 1;
}],
YY: [twoDigits, function (d, v) {
var da = new Date(), cent = +('' + da.getFullYear()).substr(0, 2);
d.year = '' + (v > 68 ? cent - 1 : cent) + v;
}],
h: [twoDigits, function (d, v) {
d.hour = v;
}],
m: [twoDigits, function (d, v) {
d.minute = v;
}],
s: [twoDigits, function (d, v) {
d.second = v;
}],
YYYY: [fourDigits, function (d, v) {
d.year = v;
}],
S: [/\d/, function (d, v) {
d.millisecond = v * 100;
}],
SS: [/\d{2}/, function (d, v) {
d.millisecond = v * 10;
}],
SSS: [threeDigits, function (d, v) {
d.millisecond = v;
}],
d: [twoDigits, noop],
ddd: [word, noop],
MMM: [word, monthUpdate('monthNamesShort')],
MMMM: [word, monthUpdate('monthNames')],
a: [word, function (d, v, i18n) {
var val = v.toLowerCase();
if (val === i18n.amPm[0]) {
d.isPm = false;
} else if (val === i18n.amPm[1]) {
d.isPm = true;
}
}],
ZZ: [/[\+\-]\d\d:?\d\d/, function (d, v) {
var parts = (v + '').match(/([\+\-]|\d\d)/gi), minutes;
if (parts) {
minutes = +(parts[1] * 60) + parseInt(parts[2], 10);
d.timezoneOffset = parts[0] === '+' ? minutes : -minutes;
}
}]
};
parseFlags.dd = parseFlags.d;
parseFlags.dddd = parseFlags.ddd;
parseFlags.DD = parseFlags.D;
parseFlags.mm = parseFlags.m;
parseFlags.hh = parseFlags.H = parseFlags.HH = parseFlags.h;
parseFlags.MM = parseFlags.M;
parseFlags.ss = parseFlags.s;
parseFlags.A = parseFlags.a;
// Some common format strings
fecha.masks = {
'default': 'ddd MMM DD YYYY HH:mm:ss',
shortDate: 'M/D/YY',
mediumDate: 'MMM D, YYYY',
longDate: 'MMMM D, YYYY',
fullDate: 'dddd, MMMM D, YYYY',
shortTime: 'HH:mm',
mediumTime: 'HH:mm:ss',
longTime: 'HH:mm:ss.SSS'
};
/***
* Format a date
* @method format
* @param {Date|number} dateObj
* @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
*/
fecha.format = function (dateObj, mask, i18nSettings) {
var i18n = i18nSettings || fecha.i18n;
if (typeof dateObj === 'number') {
dateObj = new Date(dateObj);
}
if (Object.prototype.toString.call(dateObj) !== '[object Date]' || isNaN(dateObj.getTime())) {
throw new Error('Invalid Date in fecha.format');
}
mask = fecha.masks[mask] || mask || fecha.masks['default'];
return mask.replace(token, function ($0) {
return $0 in formatFlags ? formatFlags[$0](dateObj, i18n) : $0.slice(1, $0.length - 1);
});
};
/**
* Parse a date string into an object, changes - into /
* @method parse
* @param {string} dateStr Date string
* @param {string} format Date parse format
* @returns {Date|boolean}
*/
fecha.parse = function (dateStr, format, i18nSettings) {
var i18n = i18nSettings || fecha.i18n;
if (typeof format !== 'string') {
throw new Error('Invalid format in fecha.parse');
}
format = fecha.masks[format] || format;
// Avoid regular expression denial of service, fail early for really long strings
// https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
if (dateStr.length > 1000) {
return false;
}
var isValid = true;
var dateInfo = {};
format.replace(token, function ($0) {
if (parseFlags[$0]) {
var info = parseFlags[$0];
var index = dateStr.search(info[0]);
if (!~index) {
isValid = false;
} else {
dateStr.replace(info[0], function (result) {
info[1](dateInfo, result, i18n);
dateStr = dateStr.substr(index + result.length);
return result;
});
}
}
return parseFlags[$0] ? '' : $0.slice(1, $0.length - 1);
});
if (!isValid) {
return false;
}
var today = new Date();
if (dateInfo.isPm === true && dateInfo.hour != null && +dateInfo.hour !== 12) {
dateInfo.hour = +dateInfo.hour + 12;
} else if (dateInfo.isPm === false && +dateInfo.hour === 12) {
dateInfo.hour = 0;
}
var date;
if (dateInfo.timezoneOffset != null) {
dateInfo.minute = +(dateInfo.minute || 0) - +dateInfo.timezoneOffset;
date = new Date(Date.UTC(dateInfo.year || today.getFullYear(), dateInfo.month || 0, dateInfo.day || 1,
dateInfo.hour || 0, dateInfo.minute || 0, dateInfo.second || 0, dateInfo.millisecond || 0));
} else {
date = new Date(dateInfo.year || today.getFullYear(), dateInfo.month || 0, dateInfo.day || 1,
dateInfo.hour || 0, dateInfo.minute || 0, dateInfo.second || 0, dateInfo.millisecond || 0);
}
return date;
};
/* istanbul ignore next */
if (typeof module !== 'undefined' && module.exports) {
module.exports = fecha;
} else if (typeof define === 'function' && define.amd) {
define(function () {
return fecha;
});
} else {
main.fecha = fecha;
}
})(this);
},{}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsImZlY2hhIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBO0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIihmdW5jdGlvbiAobWFpbikge1xuICAndXNlIHN0cmljdCc7XG5cbiAgLyoqXG4gICAqIFBhcnNlIG9yIGZvcm1hdCBkYXRlc1xuICAgKiBAY2xhc3MgZmVjaGFcbiAgICovXG4gIHZhciBmZWNoYSA9IHt9O1xuICB2YXIgdG9rZW4gPSAvZHsxLDR9fE17MSw0fXxZWSg/OllZKT98U3sxLDN9fERvfFpafChbSGhNc0RtXSlcXDE/fFthQV18XCJbXlwiXSpcInwnW14nXSonL2c7XG4gIHZhciB0d29EaWdpdHMgPSAvXFxkXFxkPy87XG4gIHZhciB0aHJlZURpZ2l0cyA9IC9cXGR7M30vO1xuICB2YXIgZm91ckRpZ2l0cyA9IC9cXGR7NH0vO1xuICB2YXIgd29yZCA9IC9bMC05XSpbJ2EtelxcdTAwQTAtXFx1MDVGRlxcdTA3MDAtXFx1RDdGRlxcdUY5MDAtXFx1RkRDRlxcdUZERjAtXFx1RkZFRl0rfFtcXHUwNjAwLVxcdTA2RkZcXC9dKyhcXHMqP1tcXHUwNjAwLVxcdTA2RkZdKyl7MSwyfS9pO1xuICB2YXIgbm9vcCA9IGZ1bmN0aW9uICgpIHtcbiAgfTtcblxuICBmdW5jdGlvbiBzaG9ydGVuKGFyciwgc0xlbikge1xuICAgIHZhciBuZXdBcnIgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMCwgbGVuID0gYXJyLmxlbmd0aDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBuZXdBcnIucHVzaChhcnJbaV0uc3Vic3RyKDAsIHNMZW4pKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld0FycjtcbiAgfVxuXG4gIGZ1bmN0aW9uIG1vbnRoVXBkYXRlKGFyck5hbWUpIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGQsIHYsIGkxOG4pIHtcbiAgICAgIHZhciBpbmRleCA9IGkxOG5bYXJyTmFtZV0uaW5kZXhPZih2LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgdi5zdWJzdHIoMSkudG9Mb3dlckNhc2UoKSk7XG4gICAgICBpZiAofmluZGV4KSB7XG4gICAgICAgIGQubW9udGggPSBpbmRleDtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgZnVuY3Rpb24gcGFkKHZhbCwgbGVuKSB7XG4gICAgdmFsID0gU3RyaW5nKHZhbCk7XG4gICAgbGVuID0gbGVuIHx8IDI7XG4gICAgd2hpbGUgKHZhbC5sZW5ndGggPCBsZW4pIHtcbiAgICAgIHZhbCA9ICcwJyArIHZhbDtcbiAgICB9XG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIHZhciBkYXlOYW1lcyA9IFsnU3VuZGF5JywgJ01vbmRheScsICdUdWVzZGF5JywgJ1dlZG5lc2RheScsICdUaHVyc2RheScsICdGcmlkYXknLCAnU2F0dXJkYXknXTtcbiAgdmFyIG1vbnRoTmFtZXMgPSBbJ0phbnVhcnknLCAnRmVicnVhcnknLCAnTWFyY2gnLCAnQXByaWwnLCAnTWF5JywgJ0p1bmUnLCAnSnVseScsICdBdWd1c3QnLCAnU2VwdGVtYmVyJywgJ09jdG9iZXInLCAnTm92ZW1iZXInLCAnRGVjZW1iZXInXTtcbiAgdmFyIG1vbnRoTmFtZXNTaG9ydCA9IHNob3J0ZW4obW9udGhOYW1lcywgMyk7XG4gIHZhciBkYXlOYW1lc1Nob3J0ID0gc2hvcnRlbihkYXlOYW1lcywgMyk7XG4gIGZlY2hhLmkxOG4gPSB7XG4gICAgZGF5TmFtZXNTaG9ydDogZGF5TmFtZXNTaG9ydCxcbiAgICBkYXlOYW1lczogZGF5TmFtZXMsXG4gICAgbW9udGhOYW1lc1Nob3J0OiBtb250aE5hbWVzU2hvcnQsXG4gICAgbW9udGhOYW1lczogbW9udGhOYW1lcyxcbiAgICBhbVBtOiBbJ2FtJywgJ3BtJ10sXG4gICAgRG9GbjogZnVuY3Rpb24gRG9GbihEKSB7XG4gICAgICByZXR1cm4gRCArIFsndGgnLCAnc3QnLCAnbmQnLCAncmQnXVtEICUgMTAgPiAzID8gMCA6IChEIC0gRCAlIDEwICE9PSAxMCkgKiBEICUgMTBdO1xuICAgIH1cbiAgfTtcblxuICB2YXIgZm9ybWF0RmxhZ3MgPSB7XG4gICAgRDogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgcmV0dXJuIGRhdGVPYmouZ2V0RGF0ZSgpO1xuICAgIH0sXG4gICAgREQ6IGZ1bmN0aW9uKGRhdGVPYmopIHtcbiAgICAgIHJldHVybiBwYWQoZGF0ZU9iai5nZXREYXRlKCkpO1xuICAgIH0sXG4gICAgRG86IGZ1bmN0aW9uKGRhdGVPYmosIGkxOG4pIHtcbiAgICAgIHJldHVybiBpMThuLkRvRm4oZGF0ZU9iai5nZXREYXRlKCkpO1xuICAgIH0sXG4gICAgZDogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgcmV0dXJuIGRhdGVPYmouZ2V0RGF5KCk7XG4gICAgfSxcbiAgICBkZDogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgcmV0dXJuIHBhZChkYXRlT2JqLmdldERheSgpKTtcbiAgICB9LFxuICAgIGRkZDogZnVuY3Rpb24oZGF0ZU9iaiwgaTE4bikge1xuICAgICAgcmV0dXJuIGkxOG4uZGF5TmFtZXNTaG9ydFtkYXRlT2JqLmdldERheSgpXTtcbiAgICB9LFxuICAgIGRkZGQ6IGZ1bmN0aW9uKGRhdGVPYmosIGkxOG4pIHtcbiAgICAgIHJldHVybiBpMThuLmRheU5hbWVzW2RhdGVPYmouZ2V0RGF5KCldO1xuICAgIH0sXG4gICAgTTogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgcmV0dXJuIGRhdGVPYmouZ2V0TW9udGgoKSArIDE7XG4gICAgfSxcbiAgICBNTTogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgcmV0dXJuIHBhZChkYXRlT2JqLmdldE1vbnRoKCkgKyAxKTtcbiAgICB9LFxuICAgIE1NTTogZnVuY3Rpb24oZGF0ZU9iaiwgaTE4bikge1xuICAgICAgcmV0dXJuIGkxOG4ubW9udGhOYW1lc1Nob3J0W2RhdGVPYmouZ2V0TW9udGgoKV07XG4gICAgfSxcbiAgICBNTU1NOiBmdW5jdGlvbihkYXRlT2JqLCBpMThuKSB7XG4gICAgICByZXR1cm4gaTE4bi5tb250aE5hbWVzW2RhdGVPYmouZ2V0TW9udGgoKV07XG4gICAgfSxcbiAgICBZWTogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgcmV0dXJuIFN0cmluZyhkYXRlT2JqLmdldEZ1bGxZZWFyKCkpLnN1YnN0cigyKTtcbiAgICB9LFxuICAgIFlZWVk6IGZ1bmN0aW9uKGRhdGVPYmopIHtcbiAgICAgIHJldHVybiBkYXRlT2JqLmdldEZ1bGxZZWFyKCk7XG4gICAgfSxcbiAgICBoOiBmdW5jdGlvbihkYXRlT2JqKSB7XG4gICAgICByZXR1cm4gZGF0ZU9iai5nZXRIb3VycygpICUgMTIgfHwgMTI7XG4gICAgfSxcbiAgICBoaDogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgcmV0dXJuIHBhZChkYXRlT2JqLmdldEhvdXJzKCkgJSAxMiB8fCAxMik7XG4gICAgfSxcbiAgICBIOiBmdW5jdGlvbihkYXRlT2JqKSB7XG4gICAgICByZXR1cm4gZGF0ZU9iai5nZXRIb3VycygpO1xuICAgIH0sXG4gICAgSEg6IGZ1bmN0aW9uKGRhdGVPYmopIHtcbiAgICAgIHJldHVybiBwYWQoZGF0ZU9iai5nZXRIb3VycygpKTtcbiAgICB9LFxuICAgIG06IGZ1bmN0aW9uKGRhdGVPYmopIHtcbiAgICAgIHJldHVybiBkYXRlT2JqLmdldE1pbnV0ZXMoKTtcbiAgICB9LFxuICAgIG1tOiBmdW5jdGlvbihkYXRlT2JqKSB7XG4gICAgICByZXR1cm4gcGFkKGRhdGVPYmouZ2V0TWludXRlcygpKTtcbiAgICB9LFxuICAgIHM6IGZ1bmN0aW9uKGRhdGVPYmopIHtcbiAgICAgIHJldHVybiBkYXRlT2JqLmdldFNlY29uZHMoKTtcbiAgICB9LFxuICAgIHNzOiBmdW5jdGlvbihkYXRlT2JqKSB7XG4gICAgICByZXR1cm4gcGFkKGRhdGVPYmouZ2V0U2Vjb25kcygpKTtcbiAgICB9LFxuICAgIFM6IGZ1bmN0aW9uKGRhdGVPYmopIHtcbiAgICAgIHJldHVybiBNYXRoLnJvdW5kKGRhdGVPYmouZ2V0TWlsbGlzZWNvbmRzKCkgLyAxMDApO1xuICAgIH0sXG4gICAgU1M6IGZ1bmN0aW9uKGRhdGVPYmopIHtcbiAgICAgIHJldHVybiBwYWQoTWF0aC5yb3VuZChkYXRlT2JqLmdldE1pbGxpc2Vjb25kcygpIC8gMTApLCAyKTtcbiAgICB9LFxuICAgIFNTUzogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgcmV0dXJuIHBhZChkYXRlT2JqLmdldE1pbGxpc2Vjb25kcygpLCAzKTtcbiAgICB9LFxuICAgIGE6IGZ1bmN0aW9uKGRhdGVPYmosIGkxOG4pIHtcbiAgICAgIHJldHVybiBkYXRlT2JqLmdldEhvdXJzKCkgPCAxMiA/IGkxOG4uYW1QbVswXSA6IGkxOG4uYW1QbVsxXTtcbiAgICB9LFxuICAgIEE6IGZ1bmN0aW9uKGRhdGVPYmosIGkxOG4pIHtcbiAgICAgIHJldHVybiBkYXRlT2JqLmdldEhvdXJzKCkgPCAxMiA/IGkxOG4uYW1QbVswXS50b1VwcGVyQ2FzZSgpIDogaTE4bi5hbVBtWzFdLnRvVXBwZXJDYXNlKCk7XG4gICAgfSxcbiAgICBaWjogZnVuY3Rpb24oZGF0ZU9iaikge1xuICAgICAgdmFyIG8gPSBkYXRlT2JqLmdldFRpbWV6b25lT2Zmc2V0KCk7XG4gICAgICByZXR1cm4gKG8gPiAwID8gJy0nIDogJysnKSArIHBhZChNYXRoLmZsb29yKE1hdGguYWJzKG8pIC8gNjApICogMTAwICsgTWF0aC5hYnMobykgJSA2MCwgNCk7XG4gICAgfVxuICB9O1xuXG4gIHZhciBwYXJzZUZsYWdzID0ge1xuICAgIEQ6IFt0d29EaWdpdHMsIGZ1bmN0aW9uIChkLCB2KSB7XG4gICAgICBkLmRheSA9IHY7XG4gICAgfV0sXG4gICAgRG86IFtuZXcgUmVnRXhwKHR3b0RpZ2l0cy5zb3VyY2UgKyB3b3JkLnNvdXJjZSksIGZ1bmN0aW9uIChkLCB2KSB7XG4gICAgICBkLmRheSA9IHBhcnNlSW50KHYsIDEwKTtcbiAgICB9XSxcbiAgICBNOiBbdHdvRGlnaXRzLCBmdW5jdGlvbiAoZCwgdikge1xuICAgICAgZC5tb250aCA9IHYgLSAxO1xuICAgIH1dLFxuICAgIFlZOiBbdHdvRGlnaXRzLCBmdW5jdGlvbiAoZCwgdikge1xuICAgICAgdmFyIGRhID0gbmV3IERhdGUoKSwgY2VudCA9ICsoJycgKyBkYS5nZXRGdWxsWWVhcigpKS5zdWJzdHIoMCwgMik7XG4gICAgICBkLnllYXIgPSAnJyArICh2ID4gNjggPyBjZW50IC0gMSA6IGNlbnQpICsgdjtcbiAgICB9XSxcbiAgICBoOiBbdHdvRGlnaXRzLCBmdW5jdGlvbiAoZCwgdikge1xuICAgICAgZC5ob3VyID0gdjtcbiAgICB9XSxcbiAgICBtOiBbdHdvRGlnaXRzLCBmdW5jdGlvbiAoZCwgdikge1xuICAgICAgZC5taW51dGUgPSB2O1xuICAgIH1dLFxuICAgIHM6IFt0d29EaWdpdHMsIGZ1bmN0aW9uIChkLCB2KSB7XG4gICAgICBkLnNlY29uZCA9IHY7XG4gICAgfV0sXG4gICAgWVlZWTogW2ZvdXJEaWdpdHMsIGZ1bmN0aW9uIChkLCB2KSB7XG4gICAgICBkLnllYXIgPSB2O1xuICAgIH1dLFxuICAgIFM6IFsvXFxkLywgZnVuY3Rpb24gKGQsIHYpIHtcbiAgICAgIGQubWlsbGlzZWNvbmQgPSB2ICogMTAwO1xuICAgIH1dLFxuICAgIFNTOiBbL1xcZHsyfS8sIGZ1bmN0aW9uIChkLCB2KSB7XG4gICAgICBkLm1pbGxpc2Vjb25kID0gdiAqIDEwO1xuICAgIH1dLFxuICAgIFNTUzogW3RocmVlRGlnaXRzLCBmdW5jdGlvbiAoZCwgdikge1xuICAgICAgZC5taWxsaXNlY29uZCA9IHY7XG4gICAgfV0sXG4gICAgZDogW3R3b0RpZ2l0cywgbm9vcF0sXG4gICAgZGRkOiBbd29yZCwgbm9vcF0sXG4gICAgTU1NOiBbd29yZCwgbW9udGhVcGRhdGUoJ21vbnRoTmFtZXNTaG9ydCcpXSxcbiAgICBNTU1NOiBbd29yZCwgbW9udGhVcGRhdGUoJ21vbnRoTmFtZXMnKV0sXG4gICAgYTogW3dvcmQsIGZ1bmN0aW9uIChkLCB2LCBpMThuKSB7XG4gICAgICB2YXIgdmFsID0gdi50b0xvd2VyQ2FzZSgpO1xuICAgICAgaWYgKHZhbCA9PT0gaTE4bi5hbVBtWzBdKSB7XG4gICAgICAgIGQuaXNQbSA9IGZhbHNlO1xuICAgICAgfSBlbHNlIGlmICh2YWwgPT09IGkxOG4uYW1QbVsxXSkge1xuICAgICAgICBkLmlzUG0gPSB0cnVlO1xuICAgICAgfVxuICAgIH1dLFxuICAgIFpaOiBbL1tcXCtcXC1dXFxkXFxkOj9cXGRcXGQvLCBmdW5jdGlvbiAoZCwgdikge1xuICAgICAgdmFyIHBhcnRzID0gKHYgKyAnJykubWF0Y2goLyhbXFwrXFwtXXxcXGRcXGQpL2dpKSwgbWludXRlcztcblxuICAgICAgaWYgKHBhcnRzKSB7XG4gICAgICAgIG1pbnV0ZXMgPSArKHBhcnRzWzFdICogNjApICsgcGFyc2VJbnQocGFydHNbMl0sIDEwKTtcbiAgICAgICAgZC50aW1lem9uZU9mZnNldCA9IHBhcnRzWzBdID09PSAnKycgPyBtaW51dGVzIDogLW1pbnV0ZXM7XG4gICAgICB9XG4gICAgfV1cbiAgfTtcbiAgcGFyc2VGbGFncy5kZCA9IHBhcnNlRmxhZ3MuZDtcbiAgcGFyc2VGbGFncy5kZGRkID0gcGFyc2VGbGFncy5kZGQ7XG4gIHBhcnNlRmxhZ3MuREQgPSBwYXJzZUZsYWdzLkQ7XG4gIHBhcnNlRmxhZ3MubW0gPSBwYXJzZUZsYWdzLm07XG4gIHBhcnNlRmxhZ3MuaGggPSBwYXJzZUZsYWdzLkggPSBwYXJzZUZsYWdzLkhIID0gcGFyc2VGbGFncy5oO1xuICBwYXJzZUZsYWdzLk1NID0gcGFyc2VGbGFncy5NO1xuICBwYXJzZUZsYWdzLnNzID0gcGFyc2VGbGFncy5zO1xuICBwYXJzZUZsYWdzLkEgPSBwYXJzZUZsYWdzLmE7XG5cblxuICAvLyBTb21lIGNvbW1vbiBmb3JtYXQgc3RyaW5nc1xuICBmZWNoYS5tYXNrcyA9IHtcbiAgICAnZGVmYXVsdCc6ICdkZGQgTU1NIEREIFlZWVkgSEg6bW06c3MnLFxuICAgIHNob3J0RGF0ZTogJ00vRC9ZWScsXG4gICAgbWVkaXVtRGF0ZTogJ01NTSBELCBZWVlZJyxcbiAgICBsb25nRGF0ZTogJ01NTU0gRCwgWVlZWScsXG4gICAgZnVsbERhdGU6ICdkZGRkLCBNTU1NIEQsIFlZWVknLFxuICAgIHNob3J0VGltZTogJ0hIOm1tJyxcbiAgICBtZWRpdW1UaW1lOiAnSEg6bW06c3MnLFxuICAgIGxvbmdUaW1lOiAnSEg6bW06c3MuU1NTJ1xuICB9O1xuXG4gIC8qKipcbiAgICogRm9ybWF0IGEgZGF0ZVxuICAgKiBAbWV0aG9kIGZvcm1hdFxuICAgKiBAcGFyYW0ge0RhdGV8bnVtYmVyfSBkYXRlT2JqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBtYXNrIEZvcm1hdCBvZiB0aGUgZGF0ZSwgaS5lLiAnbW0tZGQteXknIG9yICdzaG9ydERhdGUnXG4gICAqL1xuICBmZWNoYS5mb3JtYXQgPSBmdW5jdGlvbiAoZGF0ZU9iaiwgbWFzaywgaTE4blNldHRpbmdzKSB7XG4gICAgdmFyIGkxOG4gPSBpMThuU2V0dGluZ3MgfHwgZmVjaGEuaTE4bjtcblxuICAgIGlmICh0eXBlb2YgZGF0ZU9iaiA9PT0gJ251bWJlcicpIHtcbiAgICAgIGRhdGVPYmogPSBuZXcgRGF0ZShkYXRlT2JqKTtcbiAgICB9XG5cbiAgICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGRhdGVPYmopICE9PSAnW29iamVjdCBEYXRlXScgfHwgaXNOYU4oZGF0ZU9iai5nZXRUaW1lKCkpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgRGF0ZSBpbiBmZWNoYS5mb3JtYXQnKTtcbiAgICB9XG5cbiAgICBtYXNrID0gZmVjaGEubWFza3NbbWFza10gfHwgbWFzayB8fCBmZWNoYS5tYXNrc1snZGVmYXVsdCddO1xuXG4gICAgcmV0dXJuIG1hc2sucmVwbGFjZSh0b2tlbiwgZnVuY3Rpb24gKCQwKSB7XG4gICAgICByZXR1cm4gJDAgaW4gZm9ybWF0RmxhZ3MgPyBmb3JtYXRGbGFnc1skMF0oZGF0ZU9iaiwgaTE4bikgOiAkMC5zbGljZSgxLCAkMC5sZW5ndGggLSAxKTtcbiAgICB9KTtcbiAgfTtcblxuICAvKipcbiAgICogUGFyc2UgYSBkYXRlIHN0cmluZyBpbnRvIGFuIG9iamVjdCwgY2hhbmdlcyAtIGludG8gL1xuICAgKiBAbWV0aG9kIHBhcnNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBkYXRlU3RyIERhdGUgc3RyaW5nXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgRGF0ZSBwYXJzZSBmb3JtYXRcbiAgICogQHJldHVybnMge0RhdGV8Ym9vbGVhbn1cbiAgICovXG4gIGZlY2hhLnBhcnNlID0gZnVuY3Rpb24gKGRhdGVTdHIsIGZvcm1hdCwgaTE4blNldHRpbmdzKSB7XG4gICAgdmFyIGkxOG4gPSBpMThuU2V0dGluZ3MgfHwgZmVjaGEuaTE4bjtcblxuICAgIGlmICh0eXBlb2YgZm9ybWF0ICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGZvcm1hdCBpbiBmZWNoYS5wYXJzZScpO1xuICAgIH1cblxuICAgIGZvcm1hdCA9IGZlY2hhLm1hc2tzW2Zvcm1hdF0gfHwgZm9ybWF0O1xuXG4gICAgLy8gQXZvaWQgcmVndWxhciBleHByZXNzaW9uIGRlbmlhbCBvZiBzZXJ2aWNlLCBmYWlsIGVhcmx5IGZvciByZWFsbHkgbG9uZyBzdHJpbmdzXG4gICAgLy8gaHR0cHM6Ly93d3cub3dhc3Aub3JnL2luZGV4LnBocC9SZWd1bGFyX2V4cHJlc3Npb25fRGVuaWFsX29mX1NlcnZpY2VfLV9SZURvU1xuICAgIGlmIChkYXRlU3RyLmxlbmd0aCA+IDEwMDApIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB2YXIgaXNWYWxpZCA9IHRydWU7XG4gICAgdmFyIGRhdGVJbmZvID0ge307XG4gICAgZm9ybWF0LnJlcGxhY2UodG9rZW4sIGZ1bmN0aW9uICgkMCkge1xuICAgICAgaWYgKHBhcnNlRmxhZ3NbJDBdKSB7XG4gICAgICAgIHZhciBpbmZvID0gcGFyc2VGbGFnc1skMF07XG4gICAgICAgIHZhciBpbmRleCA9IGRhdGVTdHIuc2VhcmNoKGluZm9bMF0pO1xuICAgICAgICBpZiAoIX5pbmRleCkge1xuICAgICAgICAgIGlzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkYXRlU3RyLnJlcGxhY2UoaW5mb1swXSwgZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgaW5mb1sxXShkYXRlSW5mbywgcmVzdWx0LCBpMThuKTtcbiAgICAgICAgICAgIGRhdGVTdHIgPSBkYXRlU3RyLnN1YnN0cihpbmRleCArIHJlc3VsdC5sZW5ndGgpO1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcGFyc2VGbGFnc1skMF0gPyAnJyA6ICQwLnNsaWNlKDEsICQwLmxlbmd0aCAtIDEpO1xuICAgIH0pO1xuXG4gICAgaWYgKCFpc1ZhbGlkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdmFyIHRvZGF5ID0gbmV3IERhdGUoKTtcbiAgICBpZiAoZGF0ZUluZm8uaXNQbSA9PT0gdHJ1ZSAmJiBkYXRlSW5mby5ob3VyICE9IG51bGwgJiYgK2RhdGVJbmZvLmhvdXIgIT09IDEyKSB7XG4gICAgICBkYXRlSW5mby5ob3VyID0gK2RhdGVJbmZvLmhvdXIgKyAxMjtcbiAgICB9IGVsc2UgaWYgKGRhdGVJbmZvLmlzUG0gPT09IGZhbHNlICYmICtkYXRlSW5mby5ob3VyID09PSAxMikge1xuICAgICAgZGF0ZUluZm8uaG91ciA9IDA7XG4gICAgfVxuXG4gICAgdmFyIGRhdGU7XG4gICAgaWYgKGRhdGVJbmZvLnRpbWV6b25lT2Zmc2V0ICE9IG51bGwpIHtcbiAgICAgIGRhdGVJbmZvLm1pbnV0ZSA9ICsoZGF0ZUluZm8ubWludXRlIHx8IDApIC0gK2RhdGVJbmZvLnRpbWV6b25lT2Zmc2V0O1xuICAgICAgZGF0ZSA9IG5ldyBEYXRlKERhdGUuVVRDKGRhdGVJbmZvLnllYXIgfHwgdG9kYXkuZ2V0RnVsbFllYXIoKSwgZGF0ZUluZm8ubW9udGggfHwgMCwgZGF0ZUluZm8uZGF5IHx8IDEsXG4gICAgICAgIGRhdGVJbmZvLmhvdXIgfHwgMCwgZGF0ZUluZm8ubWludXRlIHx8IDAsIGRhdGVJbmZvLnNlY29uZCB8fCAwLCBkYXRlSW5mby5taWxsaXNlY29uZCB8fCAwKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRhdGUgPSBuZXcgRGF0ZShkYXRlSW5mby55ZWFyIHx8IHRvZGF5LmdldEZ1bGxZZWFyKCksIGRhdGVJbmZvLm1vbnRoIHx8IDAsIGRhdGVJbmZvLmRheSB8fCAxLFxuICAgICAgICBkYXRlSW5mby5ob3VyIHx8IDAsIGRhdGVJbmZvLm1pbnV0ZSB8fCAwLCBkYXRlSW5mby5zZWNvbmQgfHwgMCwgZGF0ZUluZm8ubWlsbGlzZWNvbmQgfHwgMCk7XG4gICAgfVxuICAgIHJldHVybiBkYXRlO1xuICB9O1xuXG4gIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cykge1xuICAgIG1vZHVsZS5leHBvcnRzID0gZmVjaGE7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gJ2Z1bmN0aW9uJyAmJiBkZWZpbmUuYW1kKSB7XG4gICAgZGVmaW5lKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBmZWNoYTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBtYWluLmZlY2hhID0gZmVjaGE7XG4gIH1cbn0pKHRoaXMpO1xuIl19
require=(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})({"moment":[function(require,module,exports){
//! moment.js
//! version : 2.3.0
//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
//! license : MIT
//! momentjs.com
(function (undefined) {
/************************************
Constants
************************************/
var moment,
VERSION = "2.3.0",
round = Math.round,
i,
YEAR = 0,
MONTH = 1,
DATE = 2,
HOUR = 3,
MINUTE = 4,
SECOND = 5,
MILLISECOND = 6,
// internal storage for language config files
languages = {},
// check for nodeJS
hasModule = (typeof module !== 'undefined' && module.exports),
// ASP.NET json date format regex
aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
// format tokens
formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,
localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
// parsing token regexes
parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
parseTokenThreeDigits = /\d{3}/, // 000 - 999
parseTokenFourDigits = /\d{1,4}/, // 0 - 9999
parseTokenSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
parseTokenT = /T/i, // T (ISO seperator)
parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
// preliminary iso regex
// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000)
isoRegex = /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?$/,
isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
isoDates = [
'YYYY-MM-DD',
'GGGG-[W]WW',
'GGGG-[W]WW-E',
'YYYY-DDD'
],
// iso time formats and regexes
isoTimes = [
['HH:mm:ss.S', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
['HH:mm', /(T| )\d\d:\d\d/],
['HH', /(T| )\d\d/]
],
// timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
parseTimezoneChunker = /([\+\-]|\d\d)/gi,
// getter and setter names
proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
unitMillisecondFactors = {
'Milliseconds' : 1,
'Seconds' : 1e3,
'Minutes' : 6e4,
'Hours' : 36e5,
'Days' : 864e5,
'Months' : 2592e6,
'Years' : 31536e6
},
unitAliases = {
ms : 'millisecond',
s : 'second',
m : 'minute',
h : 'hour',
d : 'day',
D : 'date',
w : 'week',
W : 'isoWeek',
M : 'month',
y : 'year',
DDD : 'dayOfYear',
e : 'weekday',
E : 'isoWeekday',
gg: 'weekYear',
GG: 'isoWeekYear'
},
camelFunctions = {
dayofyear : 'dayOfYear',
isoweekday : 'isoWeekday',
isoweek : 'isoWeek',
weekyear : 'weekYear',
isoweekyear : 'isoWeekYear',
},
// format function strings
formatFunctions = {},
// tokens to ordinalize and pad
ordinalizeTokens = 'DDD w W M D d'.split(' '),
paddedTokens = 'M D H h m s w W'.split(' '),
formatTokenFunctions = {
M : function () {
return this.month() + 1;
},
MMM : function (format) {
return this.lang().monthsShort(this, format);
},
MMMM : function (format) {
return this.lang().months(this, format);
},
D : function () {
return this.date();
},
DDD : function () {
return this.dayOfYear();
},
d : function () {
return this.day();
},
dd : function (format) {
return this.lang().weekdaysMin(this, format);
},
ddd : function (format) {
return this.lang().weekdaysShort(this, format);
},
dddd : function (format) {
return this.lang().weekdays(this, format);
},
w : function () {
return this.week();
},
W : function () {
return this.isoWeek();
},
YY : function () {
return leftZeroFill(this.year() % 100, 2);
},
YYYY : function () {
return leftZeroFill(this.year(), 4);
},
YYYYY : function () {
return leftZeroFill(this.year(), 5);
},
gg : function () {
return leftZeroFill(this.weekYear() % 100, 2);
},
gggg : function () {
return this.weekYear();
},
ggggg : function () {
return leftZeroFill(this.weekYear(), 5);
},
GG : function () {
return leftZeroFill(this.isoWeekYear() % 100, 2);
},
GGGG : function () {
return this.isoWeekYear();
},
GGGGG : function () {
return leftZeroFill(this.isoWeekYear(), 5);
},
e : function () {
return this.weekday();
},
E : function () {
return this.isoWeekday();
},
a : function () {
return this.lang().meridiem(this.hours(), this.minutes(), true);
},
A : function () {
return this.lang().meridiem(this.hours(), this.minutes(), false);
},
H : function () {
return this.hours();
},
h : function () {
return this.hours() % 12 || 12;
},
m : function () {
return this.minutes();
},
s : function () {
return this.seconds();
},
S : function () {
return toInt(this.milliseconds() / 100);
},
SS : function () {
return leftZeroFill(toInt(this.milliseconds() / 10), 2);
},
SSS : function () {
return leftZeroFill(this.milliseconds(), 3);
},
Z : function () {
var a = -this.zone(),
b = "+";
if (a < 0) {
a = -a;
b = "-";
}
return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
},
ZZ : function () {
var a = -this.zone(),
b = "+";
if (a < 0) {
a = -a;
b = "-";
}
return b + leftZeroFill(toInt(10 * a / 6), 4);
},
z : function () {
return this.zoneAbbr();
},
zz : function () {
return this.zoneName();
},
X : function () {
return this.unix();
}
},
lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
function padToken(func, count) {
return function (a) {
return leftZeroFill(func.call(this, a), count);
};
}
function ordinalizeToken(func, period) {
return function (a) {
return this.lang().ordinal(func.call(this, a), period);
};
}
while (ordinalizeTokens.length) {
i = ordinalizeTokens.pop();
formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
}
while (paddedTokens.length) {
i = paddedTokens.pop();
formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
}
formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
/************************************
Constructors
************************************/
function Language() {
}
// Moment prototype object
function Moment(config) {
checkOverflow(config);
extend(this, config);
}
// Duration Constructor
function Duration(duration) {
var normalizedInput = normalizeObjectUnits(duration),
years = normalizedInput.year || 0,
months = normalizedInput.month || 0,
weeks = normalizedInput.week || 0,
days = normalizedInput.day || 0,
hours = normalizedInput.hour || 0,
minutes = normalizedInput.minute || 0,
seconds = normalizedInput.second || 0,
milliseconds = normalizedInput.millisecond || 0;
// store reference to input for deterministic cloning
this._input = duration;
// representation for dateAddRemove
this._milliseconds = +milliseconds +
seconds * 1e3 + // 1000
minutes * 6e4 + // 1000 * 60
hours * 36e5; // 1000 * 60 * 60
// Because of dateAddRemove treats 24 hours as different from a
// day when working around DST, we need to store them separately
this._days = +days +
weeks * 7;
// It is impossible translate months into days without knowing
// which months you are are talking about, so we have to store
// it separately.
this._months = +months +
years * 12;
this._data = {};
this._bubble();
}
/************************************
Helpers
************************************/
function extend(a, b) {
for (var i in b) {
if (b.hasOwnProperty(i)) {
a[i] = b[i];
}
}
if (b.hasOwnProperty("toString")) {
a.toString = b.toString;
}
if (b.hasOwnProperty("valueOf")) {
a.valueOf = b.valueOf;
}
return a;
}
function absRound(number) {
if (number < 0) {
return Math.ceil(number);
} else {
return Math.floor(number);
}
}
// left zero fill a number
// see http://jsperf.com/left-zero-filling for performance comparison
function leftZeroFill(number, targetLength) {
var output = number + '';
while (output.length < targetLength) {
output = '0' + output;
}
return output;
}
// helper function for _.addTime and _.subtractTime
function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
var milliseconds = duration._milliseconds,
days = duration._days,
months = duration._months,
minutes,
hours;
if (milliseconds) {
mom._d.setTime(+mom._d + milliseconds * isAdding);
}
// store the minutes and hours so we can restore them
if (days || months) {
minutes = mom.minute();
hours = mom.hour();
}
if (days) {
mom.date(mom.date() + days * isAdding);
}
if (months) {
mom.month(mom.month() + months * isAdding);
}
if (milliseconds && !ignoreUpdateOffset) {
moment.updateOffset(mom);
}
// restore the minutes and hours after possibly changing dst
if (days || months) {
mom.minute(minutes);
mom.hour(hours);
}
}
// check if is an array
function isArray(input) {
return Object.prototype.toString.call(input) === '[object Array]';
}
function isDate(input) {
return Object.prototype.toString.call(input) === '[object Date]';
}
// compare two arrays, return the number of differences
function compareArrays(array1, array2, dontConvert) {
var len = Math.min(array1.length, array2.length),
lengthDiff = Math.abs(array1.length - array2.length),
diffs = 0,
i;
for (i = 0; i < len; i++) {
if ((dontConvert && array1[i] !== array2[i]) ||
(!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
diffs++;
}
}
return diffs + lengthDiff;
}
function normalizeUnits(units) {
if (units) {
var lowered = units.toLowerCase().replace(/(.)s$/, '$1');
units = unitAliases[units] || camelFunctions[lowered] || lowered;
}
return units;
}
function normalizeObjectUnits(inputObject) {
var normalizedInput = {},
normalizedProp,
prop,
index;
for (prop in inputObject) {
if (inputObject.hasOwnProperty(prop)) {
normalizedProp = normalizeUnits(prop);
if (normalizedProp) {
normalizedInput[normalizedProp] = inputObject[prop];
}
}
}
return normalizedInput;
}
function makeList(field) {
var count, setter;
if (field.indexOf('week') === 0) {
count = 7;
setter = 'day';
}
else if (field.indexOf('month') === 0) {
count = 12;
setter = 'month';
}
else {
return;
}
moment[field] = function (format, index) {
var i, getter,
method = moment.fn._lang[field],
results = [];
if (typeof format === 'number') {
index = format;
format = undefined;
}
getter = function (i) {
var m = moment().utc().set(setter, i);
return method.call(moment.fn._lang, m, format || '');
};
if (index) {
return getter(index);
}
else {
for (i = 0; i < count; i++) {
results.push(getter(i));
}
return results;
}
};
}
function toInt(argumentForCoercion) {
var coercedNumber = +argumentForCoercion,
value = 0;
if (coercedNumber !== 0 && isFinite(coercedNumber)) {
if (coercedNumber >= 0) {
value = Math.floor(coercedNumber);
} else {
value = Math.ceil(coercedNumber);
}
}
return value;
}
function daysInMonth(year, month) {
return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
}
function daysInYear(year) {
return isLeapYear(year) ? 366 : 365;
}
function isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
function checkOverflow(m) {
var overflow;
if (m._a && m._pf.overflow === -2) {
overflow =
m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
-1;
if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
overflow = DATE;
}
m._pf.overflow = overflow;
}
}
function initializeParsingFlags(config) {
config._pf = {
empty : false,
unusedTokens : [],
unusedInput : [],
overflow : -2,
charsLeftOver : 0,
nullInput : false,
invalidMonth : null,
invalidFormat : false,
userInvalidated : false
};
}
function isValid(m) {
if (m._isValid == null) {
m._isValid = !isNaN(m._d.getTime()) &&
m._pf.overflow < 0 &&
!m._pf.empty &&
!m._pf.invalidMonth &&
!m._pf.nullInput &&
!m._pf.invalidFormat &&
!m._pf.userInvalidated;
if (m._strict) {
m._isValid = m._isValid &&
m._pf.charsLeftOver === 0 &&
m._pf.unusedTokens.length === 0;
}
}
return m._isValid;
}
function normalizeLanguage(key) {
return key ? key.toLowerCase().replace('_', '-') : key;
}
/************************************
Languages
************************************/
extend(Language.prototype, {
set : function (config) {
var prop, i;
for (i in config) {
prop = config[i];
if (typeof prop === 'function') {
this[i] = prop;
} else {
this['_' + i] = prop;
}
}
},
_months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
months : function (m) {
return this._months[m.month()];
},
_monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
monthsShort : function (m) {
return this._monthsShort[m.month()];
},
monthsParse : function (monthName) {
var i, mom, regex;
if (!this._monthsParse) {
this._monthsParse = [];
}
for (i = 0; i < 12; i++) {
// make the regex if we don't have it already
if (!this._monthsParse[i]) {
mom = moment.utc([2000, i]);
regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
}
// test the regex
if (this._monthsParse[i].test(monthName)) {
return i;
}
}
},
_weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
weekdays : function (m) {
return this._weekdays[m.day()];
},
_weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
weekdaysShort : function (m) {
return this._weekdaysShort[m.day()];
},
_weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
weekdaysMin : function (m) {
return this._weekdaysMin[m.day()];
},
weekdaysParse : function (weekdayName) {
var i, mom, regex;
if (!this._weekdaysParse) {
this._weekdaysParse = [];
}
for (i = 0; i < 7; i++) {
// make the regex if we don't have it already
if (!this._weekdaysParse[i]) {
mom = moment([2000, 1]).day(i);
regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
}
// test the regex
if (this._weekdaysParse[i].test(weekdayName)) {
return i;
}
}
},
_longDateFormat : {
LT : "h:mm A",
L : "MM/DD/YYYY",
LL : "MMMM D YYYY",
LLL : "MMMM D YYYY LT",
LLLL : "dddd, MMMM D YYYY LT"
},
longDateFormat : function (key) {
var output = this._longDateFormat[key];
if (!output && this._longDateFormat[key.toUpperCase()]) {
output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
return val.slice(1);
});
this._longDateFormat[key] = output;
}
return output;
},
isPM : function (input) {
// IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
// Using charAt should be more compatible.
return ((input + '').toLowerCase().charAt(0) === 'p');
},
_meridiemParse : /[ap]\.?m?\.?/i,
meridiem : function (hours, minutes, isLower) {
if (hours > 11) {
return isLower ? 'pm' : 'PM';
} else {
return isLower ? 'am' : 'AM';
}
},
_calendar : {
sameDay : '[Today at] LT',
nextDay : '[Tomorrow at] LT',
nextWeek : 'dddd [at] LT',
lastDay : '[Yesterday at] LT',
lastWeek : '[Last] dddd [at] LT',
sameElse : 'L'
},
calendar : function (key, mom) {
var output = this._calendar[key];
return typeof output === 'function' ? output.apply(mom) : output;
},
_relativeTime : {
future : "in %s",
past : "%s ago",
s : "a few seconds",
m : "a minute",
mm : "%d minutes",
h : "an hour",
hh : "%d hours",
d : "a day",
dd : "%d days",
M : "a month",
MM : "%d months",
y : "a year",
yy : "%d years"
},
relativeTime : function (number, withoutSuffix, string, isFuture) {
var output = this._relativeTime[string];
return (typeof output === 'function') ?
output(number, withoutSuffix, string, isFuture) :
output.replace(/%d/i, number);
},
pastFuture : function (diff, output) {
var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
},
ordinal : function (number) {
return this._ordinal.replace("%d", number);
},
_ordinal : "%d",
preparse : function (string) {
return string;
},
postformat : function (string) {
return string;
},
week : function (mom) {
return weekOfYear(mom, this._week.dow, this._week.doy).week;
},
_week : {
dow : 0, // Sunday is the first day of the week.
doy : 6 // The week that contains Jan 1st is the first week of the year.
},
_invalidDate: 'Invalid date',
invalidDate: function () {
return this._invalidDate;
}
});
// Loads a language definition into the `languages` cache. The function
// takes a key and optionally values. If not in the browser and no values
// are provided, it will load the language file module. As a convenience,
// this function also returns the language values.
function loadLang(key, values) {
values.abbr = key;
if (!languages[key]) {
languages[key] = new Language();
}
languages[key].set(values);
return languages[key];
}
// Remove a language from the `languages` cache. Mostly useful in tests.
function unloadLang(key) {
delete languages[key];
}
// Determines which language definition to use and returns it.
//
// With no parameters, it will return the global language. If you
// pass in a language key, such as 'en', it will return the
// definition for 'en', so long as 'en' has already been loaded using
// moment.lang.
function getLangDefinition(key) {
var i = 0, j, lang, next, split,
get = function (k) {
if (!languages[k] && hasModule) {
try {
require('./lang/' + k);
} catch (e) { }
}
return languages[k];
};
if (!key) {
return moment.fn._lang;
}
if (!isArray(key)) {
//short-circuit everything else
lang = get(key);
if (lang) {
return lang;
}
key = [key];
}
//pick the language from the array
//try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
//substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
while (i < key.length) {
split = normalizeLanguage(key[i]).split('-');
j = split.length;
next = normalizeLanguage(key[i + 1]);
next = next ? next.split('-') : null;
while (j > 0) {
lang = get(split.slice(0, j).join('-'));
if (lang) {
return lang;
}
if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
//the next array item is better than a shallower substring of this one
break;
}
j--;
}
i++;
}
return moment.fn._lang;
}
/************************************
Formatting
************************************/
function removeFormattingTokens(input) {
if (input.match(/\[[\s\S]/)) {
return input.replace(/^\[|\]$/g, "");
}
return input.replace(/\\/g, "");
}
function makeFormatFunction(format) {
var array = format.match(formattingTokens), i, length;
for (i = 0, length = array.length; i < length; i++) {
if (formatTokenFunctions[array[i]]) {
array[i] = formatTokenFunctions[array[i]];
} else {
array[i] = removeFormattingTokens(array[i]);
}
}
return function (mom) {
var output = "";
for (i = 0; i < length; i++) {
output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
}
return output;
};
}
// format date using native date object
function formatMoment(m, format) {
if (!m.isValid()) {
return m.lang().invalidDate();
}
format = expandFormat(format, m.lang());
if (!formatFunctions[format]) {
formatFunctions[format] = makeFormatFunction(format);
}
return formatFunctions[format](m);
}
function expandFormat(format, lang) {
var i = 5;
function replaceLongDateFormatTokens(input) {
return lang.longDateFormat(input) || input;
}
localFormattingTokens.lastIndex = 0;
while (i >= 0 && localFormattingTokens.test(format)) {
format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
localFormattingTokens.lastIndex = 0;
i -= 1;
}
return format;
}
/************************************
Parsing
************************************/
// get the regex to find the next token
function getParseRegexForToken(token, config) {
var a;
switch (token) {
case 'DDDD':
return parseTokenThreeDigits;
case 'YYYY':
case 'GGGG':
case 'gggg':
return parseTokenFourDigits;
case 'YYYYY':
case 'GGGGG':
case 'ggggg':
return parseTokenSixDigits;
case 'S':
case 'SS':
case 'SSS':
case 'DDD':
return parseTokenOneToThreeDigits;
case 'MMM':
case 'MMMM':
case 'dd':
case 'ddd':
case 'dddd':
return parseTokenWord;
case 'a':
case 'A':
return getLangDefinition(config._l)._meridiemParse;
case 'X':
return parseTokenTimestampMs;
case 'Z':
case 'ZZ':
return parseTokenTimezone;
case 'T':
return parseTokenT;
case 'MM':
case 'DD':
case 'YY':
case 'GG':
case 'gg':
case 'HH':
case 'hh':
case 'mm':
case 'ss':
case 'M':
case 'D':
case 'd':
case 'H':
case 'h':
case 'm':
case 's':
case 'w':
case 'ww':
case 'W':
case 'WW':
case 'e':
case 'E':
return parseTokenOneOrTwoDigits;
default :
a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
return a;
}
}
function timezoneMinutesFromString(string) {
var tzchunk = (parseTokenTimezone.exec(string) || [])[0],
parts = (tzchunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
minutes = +(parts[1] * 60) + toInt(parts[2]);
return parts[0] === '+' ? -minutes : minutes;
}
// function to convert string input to date
function addTimeToArrayFromToken(token, input, config) {
var a, datePartArray = config._a;
switch (token) {
// MONTH
case 'M' : // fall through to MM
case 'MM' :
if (input != null) {
datePartArray[MONTH] = toInt(input) - 1;
}
break;
case 'MMM' : // fall through to MMMM
case 'MMMM' :
a = getLangDefinition(config._l).monthsParse(input);
// if we didn't find a month name, mark the date as invalid.
if (a != null) {
datePartArray[MONTH] = a;
} else {
config._pf.invalidMonth = input;
}
break;
// DAY OF MONTH
case 'D' : // fall through to DD
case 'DD' :
if (input != null) {
datePartArray[DATE] = toInt(input);
}
break;
// DAY OF YEAR
case 'DDD' : // fall through to DDDD
case 'DDDD' :
if (input != null) {
config._dayOfYear = toInt(input);
}
break;
// YEAR
case 'YY' :
datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
break;
case 'YYYY' :
case 'YYYYY' :
datePartArray[YEAR] = toInt(input);
break;
// AM / PM
case 'a' : // fall through to A
case 'A' :
config._isPm = getLangDefinition(config._l).isPM(input);
break;
// 24 HOUR
case 'H' : // fall through to hh
case 'HH' : // fall through to hh
case 'h' : // fall through to hh
case 'hh' :
datePartArray[HOUR] = toInt(input);
break;
// MINUTE
case 'm' : // fall through to mm
case 'mm' :
datePartArray[MINUTE] = toInt(input);
break;
// SECOND
case 's' : // fall through to ss
case 'ss' :
datePartArray[SECOND] = toInt(input);
break;
// MILLISECOND
case 'S' :
case 'SS' :
case 'SSS' :
datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
break;
// UNIX TIMESTAMP WITH MS
case 'X':
config._d = new Date(parseFloat(input) * 1000);
break;
// TIMEZONE
case 'Z' : // fall through to ZZ
case 'ZZ' :
config._useUTC = true;
config._tzm = timezoneMinutesFromString(input);
break;
case 'w':
case 'ww':
case 'W':
case 'WW':
case 'd':
case 'dd':
case 'ddd':
case 'dddd':
case 'e':
case 'E':
token = token.substr(0, 1);
/* falls through */
case 'gg':
case 'gggg':
case 'GG':
case 'GGGG':
case 'GGGGG':
token = token.substr(0, 2);
if (input) {
config._w = config._w || {};
config._w[token] = input;
}
break;
}
}
// convert an array to a date.
// the array should mirror the parameters below
// note: all values past the year are optional and will default to the lowest possible value.
// [year, month, day , hour, minute, second, millisecond]
function dateFromConfig(config) {
var i, date, input = [], currentDate,
yearToUse, fixYear, w, temp, lang, weekday, week;
if (config._d) {
return;
}
currentDate = currentDateArray(config);
//compute day of the year from weeks and weekdays
if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
fixYear = function (val) {
return val ?
(val.length < 3 ? (parseInt(val, 10) > 68 ? '19' + val : '20' + val) : val) :
(config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]);
};
w = config._w;
if (w.GG != null || w.W != null || w.E != null) {
temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1);
}
else {
lang = getLangDefinition(config._l);
weekday = w.d != null ? parseWeekday(w.d, lang) :
(w.e != null ? parseInt(w.e, 10) + lang._week.dow : 0);
week = parseInt(w.w, 10) || 1;
//if we're parsing 'd', then the low day numbers may be next week
if (w.d != null && weekday < lang._week.dow) {
week++;
}
temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow);
}
config._a[YEAR] = temp.year;
config._dayOfYear = temp.dayOfYear;
}
//if the day of the year is set, figure out what it is
if (config._dayOfYear) {
yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
if (config._dayOfYear > daysInYear(yearToUse)) {
config._pf._overflowDayOfYear = true;
}
date = makeUTCDate(yearToUse, 0, config._dayOfYear);
config._a[MONTH] = date.getUTCMonth();
config._a[DATE] = date.getUTCDate();
}
// Default to current date.
// * if no year, month, day of month are given, default to today
// * if day of month is given, default month and year
// * if month is given, default only year
// * if year is given, don't default anything
for (i = 0; i < 3 && config._a[i] == null; ++i) {
config._a[i] = input[i] = currentDate[i];
}
// Zero out whatever was not defaulted, including time
for (; i < 7; i++) {
config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
}
// add the offsets to the time to be parsed so that we can have a clean array for checking isValid
input[HOUR] += toInt((config._tzm || 0) / 60);
input[MINUTE] += toInt((config._tzm || 0) % 60);
config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
}
function dateFromObject(config) {
var normalizedInput;
if (config._d) {
return;
}
normalizedInput = normalizeObjectUnits(config._i);
config._a = [
normalizedInput.year,
normalizedInput.month,
normalizedInput.day,
normalizedInput.hour,
normalizedInput.minute,
normalizedInput.second,
normalizedInput.millisecond
];
dateFromConfig(config);
}
function currentDateArray(config) {
var now = new Date();
if (config._useUTC) {
return [
now.getUTCFullYear(),
now.getUTCMonth(),
now.getUTCDate()
];
} else {
return [now.getFullYear(), now.getMonth(), now.getDate()];
}
}
// date from string and format string
function makeDateFromStringAndFormat(config) {
config._a = [];
config._pf.empty = true;
// This array is used to make a Date, either with `new Date` or `Date.UTC`
var lang = getLangDefinition(config._l),
string = '' + config._i,
i, parsedInput, tokens, token, skipped,
stringLength = string.length,
totalParsedInputLength = 0;
tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
for (i = 0; i < tokens.length; i++) {
token = tokens[i];
parsedInput = (getParseRegexForToken(token, config).exec(string) || [])[0];
if (parsedInput) {
skipped = string.substr(0, string.indexOf(parsedInput));
if (skipped.length > 0) {
config._pf.unusedInput.push(skipped);
}
string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
totalParsedInputLength += parsedInput.length;
}
// don't parse if it's not a known token
if (formatTokenFunctions[token]) {
if (parsedInput) {
config._pf.empty = false;
}
else {
config._pf.unusedTokens.push(token);
}
addTimeToArrayFromToken(token, parsedInput, config);
}
else if (config._strict && !parsedInput) {
config._pf.unusedTokens.push(token);
}
}
// add remaining unparsed input length to the string
config._pf.charsLeftOver = stringLength - totalParsedInputLength;
if (string.length > 0) {
config._pf.unusedInput.push(string);
}
// handle am pm
if (config._isPm && config._a[HOUR] < 12) {
config._a[HOUR] += 12;
}
// if is 12 am, change hours to 0
if (config._isPm === false && config._a[HOUR] === 12) {
config._a[HOUR] = 0;
}
dateFromConfig(config);
checkOverflow(config);
}
function unescapeFormat(s) {
return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
return p1 || p2 || p3 || p4;
});
}
// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
function regexpEscape(s) {
return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
}
// date from string and array of format strings
function makeDateFromStringAndArray(config) {
var tempConfig,
bestMoment,
scoreToBeat,
i,
currentScore;
if (config._f.length === 0) {
config._pf.invalidFormat = true;
config._d = new Date(NaN);
return;
}
for (i = 0; i < config._f.length; i++) {
currentScore = 0;
tempConfig = extend({}, config);
initializeParsingFlags(tempConfig);
tempConfig._f = config._f[i];
makeDateFromStringAndFormat(tempConfig);
if (!isValid(tempConfig)) {
continue;
}
// if there is any input that was not parsed add a penalty for that format
currentScore += tempConfig._pf.charsLeftOver;
//or tokens
currentScore += tempConfig._pf.unusedTokens.length * 10;
tempConfig._pf.score = currentScore;
if (scoreToBeat == null || currentScore < scoreToBeat) {
scoreToBeat = currentScore;
bestMoment = tempConfig;
}
}
extend(config, bestMoment || tempConfig);
}
// date from iso format
function makeDateFromString(config) {
var i,
string = config._i,
match = isoRegex.exec(string);
if (match) {
for (i = 4; i > 0; i--) {
if (match[i]) {
// match[5] should be "T" or undefined
config._f = isoDates[i - 1] + (match[6] || " ");
break;
}
}
for (i = 0; i < 4; i++) {
if (isoTimes[i][1].exec(string)) {
config._f += isoTimes[i][0];
break;
}
}
if (parseTokenTimezone.exec(string)) {
config._f += " Z";
}
makeDateFromStringAndFormat(config);
}
else {
config._d = new Date(string);
}
}
function makeDateFromInput(config) {
var input = config._i,
matched = aspNetJsonRegex.exec(input);
if (input === undefined) {
config._d = new Date();
} else if (matched) {
config._d = new Date(+matched[1]);
} else if (typeof input === 'string') {
makeDateFromString(config);
} else if (isArray(input)) {
config._a = input.slice(0);
dateFromConfig(config);
} else if (isDate(input)) {
config._d = new Date(+input);
} else if (typeof(input) === 'object') {
dateFromObject(config);
} else {
config._d = new Date(input);
}
}
function makeDate(y, m, d, h, M, s, ms) {
//can't just apply() to create a date:
//http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
var date = new Date(y, m, d, h, M, s, ms);
//the date constructor doesn't accept years < 1970
if (y < 1970) {
date.setFullYear(y);
}
return date;
}
function makeUTCDate(y) {
var date = new Date(Date.UTC.apply(null, arguments));
if (y < 1970) {
date.setUTCFullYear(y);
}
return date;
}
function parseWeekday(input, language) {
if (typeof input === 'string') {
if (!isNaN(input)) {
input = parseInt(input, 10);
}
else {
input = language.weekdaysParse(input);
if (typeof input !== 'number') {
return null;
}
}
}
return input;
}
/************************************
Relative Time
************************************/
// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
}
function relativeTime(milliseconds, withoutSuffix, lang) {
var seconds = round(Math.abs(milliseconds) / 1000),
minutes = round(seconds / 60),
hours = round(minutes / 60),
days = round(hours / 24),
years = round(days / 365),
args = seconds < 45 && ['s', seconds] ||
minutes === 1 && ['m'] ||
minutes < 45 && ['mm', minutes] ||
hours === 1 && ['h'] ||
hours < 22 && ['hh', hours] ||
days === 1 && ['d'] ||
days <= 25 && ['dd', days] ||
days <= 45 && ['M'] ||
days < 345 && ['MM', round(days / 30)] ||
years === 1 && ['y'] || ['yy', years];
args[2] = withoutSuffix;
args[3] = milliseconds > 0;
args[4] = lang;
return substituteTimeAgo.apply({}, args);
}
/************************************
Week of Year
************************************/
// firstDayOfWeek 0 = sun, 6 = sat
// the day of the week that starts the week
// (usually sunday or monday)
// firstDayOfWeekOfYear 0 = sun, 6 = sat
// the first week is the week that contains the first
// of this day of the week
// (eg. ISO weeks use thursday (4))
function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
var end = firstDayOfWeekOfYear - firstDayOfWeek,
daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
adjustedMoment;
if (daysToDayOfWeek > end) {
daysToDayOfWeek -= 7;
}
if (daysToDayOfWeek < end - 7) {
daysToDayOfWeek += 7;
}
adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
return {
week: Math.ceil(adjustedMoment.dayOfYear() / 7),
year: adjustedMoment.year()
};
}
//http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
var d = new Date(Date.UTC(year, 0)).getUTCDay(),
daysToAdd, dayOfYear;
weekday = weekday != null ? weekday : firstDayOfWeek;
daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0);
dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
return {
year: dayOfYear > 0 ? year : year - 1,
dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear
};
}
/************************************
Top Level Functions
************************************/
function makeMoment(config) {
var input = config._i,
format = config._f;
if (typeof config._pf === 'undefined') {
initializeParsingFlags(config);
}
if (input === null) {
return moment.invalid({nullInput: true});
}
if (typeof input === 'string') {
config._i = input = getLangDefinition().preparse(input);
}
if (moment.isMoment(input)) {
config = extend({}, input);
config._d = new Date(+input._d);
} else if (format) {
if (isArray(format)) {
makeDateFromStringAndArray(config);
} else {
makeDateFromStringAndFormat(config);
}
} else {
makeDateFromInput(config);
}
return new Moment(config);
}
moment = function (input, format, lang, strict) {
if (typeof(lang) === "boolean") {
strict = lang;
lang = undefined;
}
return makeMoment({
_i : input,
_f : format,
_l : lang,
_strict : strict,
_isUTC : false
});
};
// creating with utc
moment.utc = function (input, format, lang, strict) {
var m;
if (typeof(lang) === "boolean") {
strict = lang;
lang = undefined;
}
m = makeMoment({
_useUTC : true,
_isUTC : true,
_l : lang,
_i : input,
_f : format,
_strict : strict
}).utc();
return m;
};
// creating with unix timestamp (in seconds)
moment.unix = function (input) {
return moment(input * 1000);
};
// duration
moment.duration = function (input, key) {
var isDuration = moment.isDuration(input),
isNumber = (typeof input === 'number'),
duration = (isDuration ? input._input : (isNumber ? {} : input)),
// matching against regexp is expensive, do it on demand
match = null,
sign,
ret,
parseIso,
timeEmpty,
dateTimeEmpty;
if (isNumber) {
if (key) {
duration[key] = input;
} else {
duration.milliseconds = input;
}
} else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
sign = (match[1] === "-") ? -1 : 1;
duration = {
y: 0,
d: toInt(match[DATE]) * sign,
h: toInt(match[HOUR]) * sign,
m: toInt(match[MINUTE]) * sign,
s: toInt(match[SECOND]) * sign,
ms: toInt(match[MILLISECOND]) * sign
};
} else if (!!(match = isoDurationRegex.exec(input))) {
sign = (match[1] === "-") ? -1 : 1;
parseIso = function (inp) {
// We'd normally use ~~inp for this, but unfortunately it also
// converts floats to ints.
// inp may be undefined, so careful calling replace on it.
var res = inp && parseFloat(inp.replace(',', '.'));
// apply sign while we're at it
return (isNaN(res) ? 0 : res) * sign;
};
duration = {
y: parseIso(match[2]),
M: parseIso(match[3]),
d: parseIso(match[4]),
h: parseIso(match[5]),
m: parseIso(match[6]),
s: parseIso(match[7]),
w: parseIso(match[8])
};
}
ret = new Duration(duration);
if (isDuration && input.hasOwnProperty('_lang')) {
ret._lang = input._lang;
}
return ret;
};
// version number
moment.version = VERSION;
// default format
moment.defaultFormat = isoFormat;
// This function will be called whenever a moment is mutated.
// It is intended to keep the offset in sync with the timezone.
moment.updateOffset = function () {};
// This function will load languages and then set the global language. If
// no arguments are passed in, it will simply return the current global
// language key.
moment.lang = function (key, values) {
var r;
if (!key) {
return moment.fn._lang._abbr;
}
if (values) {
loadLang(normalizeLanguage(key), values);
} else if (values === null) {
unloadLang(key);
key = 'en';
} else if (!languages[key]) {
getLangDefinition(key);
}
r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
return r._abbr;
};
// returns language data
moment.langData = function (key) {
if (key && key._lang && key._lang._abbr) {
key = key._lang._abbr;
}
return getLangDefinition(key);
};
// compare moment object
moment.isMoment = function (obj) {
return obj instanceof Moment;
};
// for typechecking Duration objects
moment.isDuration = function (obj) {
return obj instanceof Duration;
};
for (i = lists.length - 1; i >= 0; --i) {
makeList(lists[i]);
}
moment.normalizeUnits = function (units) {
return normalizeUnits(units);
};
moment.invalid = function (flags) {
var m = moment.utc(NaN);
if (flags != null) {
extend(m._pf, flags);
}
else {
m._pf.userInvalidated = true;
}
return m;
};
moment.parseZone = function (input) {
return moment(input).parseZone();
};
/************************************
Moment Prototype
************************************/
extend(moment.fn = Moment.prototype, {
clone : function () {
return moment(this);
},
valueOf : function () {
return +this._d + ((this._offset || 0) * 60000);
},
unix : function () {
return Math.floor(+this / 1000);
},
toString : function () {
return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
},
toDate : function () {
return this._offset ? new Date(+this) : this._d;
},
toISOString : function () {
return formatMoment(moment(this).utc(), 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
},
toArray : function () {
var m = this;
return [
m.year(),
m.month(),
m.date(),
m.hours(),
m.minutes(),
m.seconds(),
m.milliseconds()
];
},
isValid : function () {
return isValid(this);
},
isDSTShifted : function () {
if (this._a) {
return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
}
return false;
},
parsingFlags : function () {
return extend({}, this._pf);
},
invalidAt: function () {
return this._pf.overflow;
},
utc : function () {
return this.zone(0);
},
local : function () {
this.zone(0);
this._isUTC = false;
return this;
},
format : function (inputString) {
var output = formatMoment(this, inputString || moment.defaultFormat);
return this.lang().postformat(output);
},
add : function (input, val) {
var dur;
// switch args to support add('s', 1) and add(1, 's')
if (typeof input === 'string') {
dur = moment.duration(+val, input);
} else {
dur = moment.duration(input, val);
}
addOrSubtractDurationFromMoment(this, dur, 1);
return this;
},
subtract : function (input, val) {
var dur;
// switch args to support subtract('s', 1) and subtract(1, 's')
if (typeof input === 'string') {
dur = moment.duration(+val, input);
} else {
dur = moment.duration(input, val);
}
addOrSubtractDurationFromMoment(this, dur, -1);
return this;
},
diff : function (input, units, asFloat) {
var that = this._isUTC ? moment(input).zone(this._offset || 0) : moment(input).local(),
zoneDiff = (this.zone() - that.zone()) * 6e4,
diff, output;
units = normalizeUnits(units);
if (units === 'year' || units === 'month') {
// average number of days in the months in the given dates
diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
// difference in months
output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
// adjust by taking difference in days, average number of days
// and dst in the given months.
output += ((this - moment(this).startOf('month')) -
(that - moment(that).startOf('month'))) / diff;
// same as above but with zones, to negate all dst
output -= ((this.zone() - moment(this).startOf('month').zone()) -
(that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
if (units === 'year') {
output = output / 12;
}
} else {
diff = (this - that);
output = units === 'second' ? diff / 1e3 : // 1000
units === 'minute' ? diff / 6e4 : // 1000 * 60
units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
diff;
}
return asFloat ? output : absRound(output);
},
from : function (time, withoutSuffix) {
return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
},
fromNow : function (withoutSuffix) {
return this.from(moment(), withoutSuffix);
},
calendar : function () {
var diff = this.diff(moment().zone(this.zone()).startOf('day'), 'days', true),
format = diff < -6 ? 'sameElse' :
diff < -1 ? 'lastWeek' :
diff < 0 ? 'lastDay' :
diff < 1 ? 'sameDay' :
diff < 2 ? 'nextDay' :
diff < 7 ? 'nextWeek' : 'sameElse';
return this.format(this.lang().calendar(format, this));
},
isLeapYear : function () {
return isLeapYear(this.year());
},
isDST : function () {
return (this.zone() < this.clone().month(0).zone() ||
this.zone() < this.clone().month(5).zone());
},
day : function (input) {
var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
if (input != null) {
input = parseWeekday(input, this.lang());
return this.add({ d : input - day });
} else {
return day;
}
},
month : function (input) {
var utc = this._isUTC ? 'UTC' : '',
dayOfMonth;
if (input != null) {
if (typeof input === 'string') {
input = this.lang().monthsParse(input);
if (typeof input !== 'number') {
return this;
}
}
dayOfMonth = this.date();
this.date(1);
this._d['set' + utc + 'Month'](input);
this.date(Math.min(dayOfMonth, this.daysInMonth()));
moment.updateOffset(this);
return this;
} else {
return this._d['get' + utc + 'Month']();
}
},
startOf: function (units) {
units = normalizeUnits(units);
// the following switch intentionally omits break keywords
// to utilize falling through the cases.
switch (units) {
case 'year':
this.month(0);
/* falls through */
case 'month':
this.date(1);
/* falls through */
case 'week':
case 'isoWeek':
case 'day':
this.hours(0);
/* falls through */
case 'hour':
this.minutes(0);
/* falls through */
case 'minute':
this.seconds(0);
/* falls through */
case 'second':
this.milliseconds(0);
/* falls through */
}
// weeks are a special case
if (units === 'week') {
this.weekday(0);
} else if (units === 'isoWeek') {
this.isoWeekday(1);
}
return this;
},
endOf: function (units) {
units = normalizeUnits(units);
return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
},
isAfter: function (input, units) {
units = typeof units !== 'undefined' ? units : 'millisecond';
return +this.clone().startOf(units) > +moment(input).startOf(units);
},
isBefore: function (input, units) {
units = typeof units !== 'undefined' ? units : 'millisecond';
return +this.clone().startOf(units) < +moment(input).startOf(units);
},
isSame: function (input, units) {
units = typeof units !== 'undefined' ? units : 'millisecond';
return +this.clone().startOf(units) === +moment(input).startOf(units);
},
min: function (other) {
other = moment.apply(null, arguments);
return other < this ? this : other;
},
max: function (other) {
other = moment.apply(null, arguments);
return other > this ? this : other;
},
zone : function (input) {
var offset = this._offset || 0;
if (input != null) {
if (typeof input === "string") {
input = timezoneMinutesFromString(input);
}
if (Math.abs(input) < 16) {
input = input * 60;
}
this._offset = input;
this._isUTC = true;
if (offset !== input) {
addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
}
} else {
return this._isUTC ? offset : this._d.getTimezoneOffset();
}
return this;
},
zoneAbbr : function () {
return this._isUTC ? "UTC" : "";
},
zoneName : function () {
return this._isUTC ? "Coordinated Universal Time" : "";
},
parseZone : function () {
if (typeof this._i === 'string') {
this.zone(this._i);
}
return this;
},
hasAlignedHourOffset : function (input) {
if (!input) {
input = 0;
}
else {
input = moment(input).zone();
}
return (this.zone() - input) % 60 === 0;
},
daysInMonth : function () {
return daysInMonth(this.year(), this.month());
},
dayOfYear : function (input) {
var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
},
weekYear : function (input) {
var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
return input == null ? year : this.add("y", (input - year));
},
isoWeekYear : function (input) {
var year = weekOfYear(this, 1, 4).year;
return input == null ? year : this.add("y", (input - year));
},
week : function (input) {
var week = this.lang().week(this);
return input == null ? week : this.add("d", (input - week) * 7);
},
isoWeek : function (input) {
var week = weekOfYear(this, 1, 4).week;
return input == null ? week : this.add("d", (input - week) * 7);
},
weekday : function (input) {
var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
return input == null ? weekday : this.add("d", input - weekday);
},
isoWeekday : function (input) {
// behaves the same as moment#day except
// as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
// as a setter, sunday should belong to the previous week.
return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
},
get : function (units) {
units = normalizeUnits(units);
return this[units]();
},
set : function (units, value) {
units = normalizeUnits(units);
if (typeof this[units] === 'function') {
this[units](value);
}
return this;
},
// If passed a language key, it will set the language for this
// instance. Otherwise, it will return the language configuration
// variables for this instance.
lang : function (key) {
if (key === undefined) {
return this._lang;
} else {
this._lang = getLangDefinition(key);
return this;
}
}
});
// helper for adding shortcuts
function makeGetterAndSetter(name, key) {
moment.fn[name] = moment.fn[name + 's'] = function (input) {
var utc = this._isUTC ? 'UTC' : '';
if (input != null) {
this._d['set' + utc + key](input);
moment.updateOffset(this);
return this;
} else {
return this._d['get' + utc + key]();
}
};
}
// loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
for (i = 0; i < proxyGettersAndSetters.length; i ++) {
makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
}
// add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
makeGetterAndSetter('year', 'FullYear');
// add plural methods
moment.fn.days = moment.fn.day;
moment.fn.months = moment.fn.month;
moment.fn.weeks = moment.fn.week;
moment.fn.isoWeeks = moment.fn.isoWeek;
// add aliased format methods
moment.fn.toJSON = moment.fn.toISOString;
/************************************
Duration Prototype
************************************/
extend(moment.duration.fn = Duration.prototype, {
_bubble : function () {
var milliseconds = this._milliseconds,
days = this._days,
months = this._months,
data = this._data,
seconds, minutes, hours, years;
// The following code bubbles up values, see the tests for
// examples of what that means.
data.milliseconds = milliseconds % 1000;
seconds = absRound(milliseconds / 1000);
data.seconds = seconds % 60;
minutes = absRound(seconds / 60);
data.minutes = minutes % 60;
hours = absRound(minutes / 60);
data.hours = hours % 24;
days += absRound(hours / 24);
data.days = days % 30;
months += absRound(days / 30);
data.months = months % 12;
years = absRound(months / 12);
data.years = years;
},
weeks : function () {
return absRound(this.days() / 7);
},
valueOf : function () {
return this._milliseconds +
this._days * 864e5 +
(this._months % 12) * 2592e6 +
toInt(this._months / 12) * 31536e6;
},
humanize : function (withSuffix) {
var difference = +this,
output = relativeTime(difference, !withSuffix, this.lang());
if (withSuffix) {
output = this.lang().pastFuture(difference, output);
}
return this.lang().postformat(output);
},
add : function (input, val) {
// supports only 2.0-style add(1, 's') or add(moment)
var dur = moment.duration(input, val);
this._milliseconds += dur._milliseconds;
this._days += dur._days;
this._months += dur._months;
this._bubble();
return this;
},
subtract : function (input, val) {
var dur = moment.duration(input, val);
this._milliseconds -= dur._milliseconds;
this._days -= dur._days;
this._months -= dur._months;
this._bubble();
return this;
},
get : function (units) {
units = normalizeUnits(units);
return this[units.toLowerCase() + 's']();
},
as : function (units) {
units = normalizeUnits(units);
return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
},
lang : moment.fn.lang,
toIsoString : function () {
// inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
var years = Math.abs(this.years()),
months = Math.abs(this.months()),
days = Math.abs(this.days()),
hours = Math.abs(this.hours()),
minutes = Math.abs(this.minutes()),
seconds = Math.abs(this.seconds() + this.milliseconds() / 1000);
if (!this.asSeconds()) {
// this is the same as C#'s (Noda) and python (isodate)...
// but not other JS (goog.date)
return 'P0D';
}
return (this.asSeconds() < 0 ? '-' : '') +
'P' +
(years ? years + 'Y' : '') +
(months ? months + 'M' : '') +
(days ? days + 'D' : '') +
((hours || minutes || seconds) ? 'T' : '') +
(hours ? hours + 'H' : '') +
(minutes ? minutes + 'M' : '') +
(seconds ? seconds + 'S' : '');
}
});
function makeDurationGetter(name) {
moment.duration.fn[name] = function () {
return this._data[name];
};
}
function makeDurationAsGetter(name, factor) {
moment.duration.fn['as' + name] = function () {
return +this / factor;
};
}
for (i in unitMillisecondFactors) {
if (unitMillisecondFactors.hasOwnProperty(i)) {
makeDurationAsGetter(i, unitMillisecondFactors[i]);
makeDurationGetter(i.toLowerCase());
}
}
makeDurationAsGetter('Weeks', 6048e5);
moment.duration.fn.asMonths = function () {
return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
};
/************************************
Default Lang
************************************/
// Set default language, other languages will inherit from English.
moment.lang('en', {
ordinal : function (number) {
var b = number % 10,
output = (toInt(number % 100 / 10) === 1) ? 'th' :
(b === 1) ? 'st' :
(b === 2) ? 'nd' :
(b === 3) ? 'rd' : 'th';
return number + output;
}
});
/* EMBED_LANGUAGES */
/************************************
Exposing Moment
************************************/
function makeGlobal() {
/*global ender:false */
if (typeof ender === 'undefined') {
// here, `this` means `window` in the browser, or `global` on the server
// add `moment` as a global object via a string identifier,
// for Closure Compiler "advanced" mode
this['moment'] = moment;
}
}
// CommonJS module is defined
if (hasModule) {
module.exports = moment;
makeGlobal();
} else if (typeof define === "function" && define.amd) {
define("moment", function (require, exports, module) {
if (module.config().noGlobal !== true) {
makeGlobal();
}
return moment;
});
} else {
makeGlobal();
}
}).call(this);
},{}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsIm1vbWVudCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwiZmlsZSI6ImdlbmVyYXRlZC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzQ29udGVudCI6WyIoZnVuY3Rpb24gZSh0LG4scil7ZnVuY3Rpb24gcyhvLHUpe2lmKCFuW29dKXtpZighdFtvXSl7dmFyIGE9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtpZighdSYmYSlyZXR1cm4gYShvLCEwKTtpZihpKXJldHVybiBpKG8sITApO3ZhciBmPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIrbytcIidcIik7dGhyb3cgZi5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGZ9dmFyIGw9bltvXT17ZXhwb3J0czp7fX07dFtvXVswXS5jYWxsKGwuZXhwb3J0cyxmdW5jdGlvbihlKXt2YXIgbj10W29dWzFdW2VdO3JldHVybiBzKG4/bjplKX0sbCxsLmV4cG9ydHMsZSx0LG4scil9cmV0dXJuIG5bb10uZXhwb3J0c312YXIgaT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2Zvcih2YXIgbz0wO288ci5sZW5ndGg7bysrKXMocltvXSk7cmV0dXJuIHN9KSIsIi8vISBtb21lbnQuanNcbi8vISB2ZXJzaW9uIDogMi4zLjBcbi8vISBhdXRob3JzIDogVGltIFdvb2QsIElza3JlbiBDaGVybmV2LCBNb21lbnQuanMgY29udHJpYnV0b3JzXG4vLyEgbGljZW5zZSA6IE1JVFxuLy8hIG1vbWVudGpzLmNvbVxuXG4oZnVuY3Rpb24gKHVuZGVmaW5lZCkge1xuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICBDb25zdGFudHNcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgICB2YXIgbW9tZW50LFxuICAgICAgICBWRVJTSU9OID0gXCIyLjMuMFwiLFxuICAgICAgICByb3VuZCA9IE1hdGgucm91bmQsXG4gICAgICAgIGksXG5cbiAgICAgICAgWUVBUiA9IDAsXG4gICAgICAgIE1PTlRIID0gMSxcbiAgICAgICAgREFURSA9IDIsXG4gICAgICAgIEhPVVIgPSAzLFxuICAgICAgICBNSU5VVEUgPSA0LFxuICAgICAgICBTRUNPTkQgPSA1LFxuICAgICAgICBNSUxMSVNFQ09ORCA9IDYsXG5cbiAgICAgICAgLy8gaW50ZXJuYWwgc3RvcmFnZSBmb3IgbGFuZ3VhZ2UgY29uZmlnIGZpbGVzXG4gICAgICAgIGxhbmd1YWdlcyA9IHt9LFxuXG4gICAgICAgIC8vIGNoZWNrIGZvciBub2RlSlNcbiAgICAgICAgaGFzTW9kdWxlID0gKHR5cGVvZiBtb2R1bGUgIT09ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzKSxcblxuICAgICAgICAvLyBBU1AuTkVUIGpzb24gZGF0ZSBmb3JtYXQgcmVnZXhcbiAgICAgICAgYXNwTmV0SnNvblJlZ2V4ID0gL15cXC8/RGF0ZVxcKChcXC0/XFxkKykvaSxcbiAgICAgICAgYXNwTmV0VGltZVNwYW5Kc29uUmVnZXggPSAvKFxcLSk/KD86KFxcZCopXFwuKT8oXFxkKylcXDooXFxkKykoPzpcXDooXFxkKylcXC4/KFxcZHszfSk/KT8vLFxuXG4gICAgICAgIC8vIGZyb20gaHR0cDovL2RvY3MuY2xvc3VyZS1saWJyYXJ5Lmdvb2dsZWNvZGUuY29tL2dpdC9jbG9zdXJlX2dvb2dfZGF0ZV9kYXRlLmpzLnNvdXJjZS5odG1sXG4gICAgICAgIC8vIHNvbWV3aGF0IG1vcmUgaW4gbGluZSB3aXRoIDQuNC4zLjIgMjAwNCBzcGVjLCBidXQgYWxsb3dzIGRlY2ltYWwgYW55d2hlcmVcbiAgICAgICAgaXNvRHVyYXRpb25SZWdleCA9IC9eKC0pP1AoPzooPzooWzAtOSwuXSopWSk/KD86KFswLTksLl0qKU0pPyg/OihbMC05LC5dKilEKT8oPzpUKD86KFswLTksLl0qKUgpPyg/OihbMC05LC5dKilNKT8oPzooWzAtOSwuXSopUyk/KT98KFswLTksLl0qKVcpJC8sXG5cbiAgICAgICAgLy8gZm9ybWF0IHRva2Vuc1xuICAgICAgICBmb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KE1vfE1NP00/TT98RG98REREb3xERD9EP0Q/fGRkZD9kP3xkbz98d1tvfHddP3xXW298V10/fFlZWVlZfFlZWVl8WVl8Z2coZ2dnPyk/fEdHKEdHRz8pP3xlfEV8YXxBfGhoP3xISD98bW0/fHNzP3xTUz9TP3xYfHp6P3xaWj98LikvZyxcbiAgICAgICAgbG9jYWxGb3JtYXR0aW5nVG9rZW5zID0gLyhcXFtbXlxcW10qXFxdKXwoXFxcXCk/KExUfExMP0w/TD98bHsxLDR9KS9nLFxuXG4gICAgICAgIC8vIHBhcnNpbmcgdG9rZW4gcmVnZXhlc1xuICAgICAgICBwYXJzZVRva2VuT25lT3JUd29EaWdpdHMgPSAvXFxkXFxkPy8sIC8vIDAgLSA5OVxuICAgICAgICBwYXJzZVRva2VuT25lVG9UaHJlZURpZ2l0cyA9IC9cXGR7MSwzfS8sIC8vIDAgLSA5OTlcbiAgICAgICAgcGFyc2VUb2tlblRocmVlRGlnaXRzID0gL1xcZHszfS8sIC8vIDAwMCAtIDk5OVxuICAgICAgICBwYXJzZVRva2VuRm91ckRpZ2l0cyA9IC9cXGR7MSw0fS8sIC8vIDAgLSA5OTk5XG4gICAgICAgIHBhcnNlVG9rZW5TaXhEaWdpdHMgPSAvWytcXC1dP1xcZHsxLDZ9LywgLy8gLTk5OSw5OTkgLSA5OTksOTk5XG4gICAgICAgIHBhcnNlVG9rZW5Xb3JkID0gL1swLTldKlsnYS16XFx1MDBBMC1cXHUwNUZGXFx1MDcwMC1cXHVEN0ZGXFx1RjkwMC1cXHVGRENGXFx1RkRGMC1cXHVGRkVGXSt8W1xcdTA2MDAtXFx1MDZGRlxcL10rKFxccyo/W1xcdTA2MDAtXFx1MDZGRl0rKXsxLDJ9L2ksIC8vIGFueSB3b3JkIChvciB0d28pIGNoYXJhY3RlcnMgb3IgbnVtYmVycyBpbmNsdWRpbmcgdHdvL3RocmVlIHdvcmQgbW9udGggaW4gYXJhYmljLlxuICAgICAgICBwYXJzZVRva2VuVGltZXpvbmUgPSAvWnxbXFwrXFwtXVxcZFxcZDo/XFxkXFxkL2ksIC8vICswMDowMCAtMDA6MDAgKzAwMDAgLTAwMDAgb3IgWlxuICAgICAgICBwYXJzZVRva2VuVCA9IC9UL2ksIC8vIFQgKElTTyBzZXBlcmF0b3IpXG4gICAgICAgIHBhcnNlVG9rZW5UaW1lc3RhbXBNcyA9IC9bXFwrXFwtXT9cXGQrKFxcLlxcZHsxLDN9KT8vLCAvLyAxMjM0NTY3ODkgMTIzNDU2Nzg5LjEyM1xuXG4gICAgICAgIC8vIHByZWxpbWluYXJ5IGlzbyByZWdleFxuICAgICAgICAvLyAwMDAwLTAwLTAwIDAwMDAtVzAwIG9yIDAwMDAtVzAwLTAgKyBUICsgMDAgb3IgMDA6MDAgb3IgMDA6MDA6MDAgb3IgMDA6MDA6MDAuMDAwICsgKzAwOjAwIG9yICswMDAwKVxuICAgICAgICBpc29SZWdleCA9IC9eXFxzKlxcZHs0fS0oPzooXFxkXFxkLVxcZFxcZCl8KFdcXGRcXGQkKXwoV1xcZFxcZC1cXGQpfChcXGRcXGRcXGQpKSgoVHwgKShcXGRcXGQoOlxcZFxcZCg6XFxkXFxkKFxcLlxcZFxcZD9cXGQ/KT8pPyk/KT8oW1xcK1xcLV1cXGRcXGQ6P1xcZFxcZCk/KT8kLyxcblxuICAgICAgICBpc29Gb3JtYXQgPSAnWVlZWS1NTS1ERFRISDptbTpzc1onLFxuXG4gICAgICAgIGlzb0RhdGVzID0gW1xuICAgICAgICAgICAgJ1lZWVktTU0tREQnLFxuICAgICAgICAgICAgJ0dHR0ctW1ddV1cnLFxuICAgICAgICAgICAgJ0dHR0ctW1ddV1ctRScsXG4gICAgICAgICAgICAnWVlZWS1EREQnXG4gICAgICAgIF0sXG5cbiAgICAgICAgLy8gaXNvIHRpbWUgZm9ybWF0cyBhbmQgcmVnZXhlc1xuICAgICAgICBpc29UaW1lcyA9IFtcbiAgICAgICAgICAgIFsnSEg6bW06c3MuUycsIC8oVHwgKVxcZFxcZDpcXGRcXGQ6XFxkXFxkXFwuXFxkezEsM30vXSxcbiAgICAgICAgICAgIFsnSEg6bW06c3MnLCAvKFR8IClcXGRcXGQ6XFxkXFxkOlxcZFxcZC9dLFxuICAgICAgICAgICAgWydISDptbScsIC8oVHwgKVxcZFxcZDpcXGRcXGQvXSxcbiAgICAgICAgICAgIFsnSEgnLCAvKFR8IClcXGRcXGQvXVxuICAgICAgICBdLFxuXG4gICAgICAgIC8vIHRpbWV6b25lIGNodW5rZXIgXCIrMTA6MDBcIiA+IFtcIjEwXCIsIFwiMDBcIl0gb3IgXCItMTUzMFwiID4gW1wiLTE1XCIsIFwiMzBcIl1cbiAgICAgICAgcGFyc2VUaW1lem9uZUNodW5rZXIgPSAvKFtcXCtcXC1dfFxcZFxcZCkvZ2ksXG5cbiAgICAgICAgLy8gZ2V0dGVyIGFuZCBzZXR0ZXIgbmFtZXNcbiAgICAgICAgcHJveHlHZXR0ZXJzQW5kU2V0dGVycyA9ICdEYXRlfEhvdXJzfE1pbnV0ZXN8U2Vjb25kc3xNaWxsaXNlY29uZHMnLnNwbGl0KCd8JyksXG4gICAgICAgIHVuaXRNaWxsaXNlY29uZEZhY3RvcnMgPSB7XG4gICAgICAgICAgICAnTWlsbGlzZWNvbmRzJyA6IDEsXG4gICAgICAgICAgICAnU2Vjb25kcycgOiAxZTMsXG4gICAgICAgICAgICAnTWludXRlcycgOiA2ZTQsXG4gICAgICAgICAgICAnSG91cnMnIDogMzZlNSxcbiAgICAgICAgICAgICdEYXlzJyA6IDg2NGU1LFxuICAgICAgICAgICAgJ01vbnRocycgOiAyNTkyZTYsXG4gICAgICAgICAgICAnWWVhcnMnIDogMzE1MzZlNlxuICAgICAgICB9LFxuXG4gICAgICAgIHVuaXRBbGlhc2VzID0ge1xuICAgICAgICAgICAgbXMgOiAnbWlsbGlzZWNvbmQnLFxuICAgICAgICAgICAgcyA6ICdzZWNvbmQnLFxuICAgICAgICAgICAgbSA6ICdtaW51dGUnLFxuICAgICAgICAgICAgaCA6ICdob3VyJyxcbiAgICAgICAgICAgIGQgOiAnZGF5JyxcbiAgICAgICAgICAgIEQgOiAnZGF0ZScsXG4gICAgICAgICAgICB3IDogJ3dlZWsnLFxuICAgICAgICAgICAgVyA6ICdpc29XZWVrJyxcbiAgICAgICAgICAgIE0gOiAnbW9udGgnLFxuICAgICAgICAgICAgeSA6ICd5ZWFyJyxcbiAgICAgICAgICAgIERERCA6ICdkYXlPZlllYXInLFxuICAgICAgICAgICAgZSA6ICd3ZWVrZGF5JyxcbiAgICAgICAgICAgIEUgOiAnaXNvV2Vla2RheScsXG4gICAgICAgICAgICBnZzogJ3dlZWtZZWFyJyxcbiAgICAgICAgICAgIEdHOiAnaXNvV2Vla1llYXInXG4gICAgICAgIH0sXG5cbiAgICAgICAgY2FtZWxGdW5jdGlvbnMgPSB7XG4gICAgICAgICAgICBkYXlvZnllYXIgOiAnZGF5T2ZZZWFyJyxcbiAgICAgICAgICAgIGlzb3dlZWtkYXkgOiAnaXNvV2Vla2RheScsXG4gICAgICAgICAgICBpc293ZWVrIDogJ2lzb1dlZWsnLFxuICAgICAgICAgICAgd2Vla3llYXIgOiAnd2Vla1llYXInLFxuICAgICAgICAgICAgaXNvd2Vla3llYXIgOiAnaXNvV2Vla1llYXInLFxuICAgICAgICB9LFxuXG4gICAgICAgIC8vIGZvcm1hdCBmdW5jdGlvbiBzdHJpbmdzXG4gICAgICAgIGZvcm1hdEZ1bmN0aW9ucyA9IHt9LFxuXG4gICAgICAgIC8vIHRva2VucyB0byBvcmRpbmFsaXplIGFuZCBwYWRcbiAgICAgICAgb3JkaW5hbGl6ZVRva2VucyA9ICdEREQgdyBXIE0gRCBkJy5zcGxpdCgnICcpLFxuICAgICAgICBwYWRkZWRUb2tlbnMgPSAnTSBEIEggaCBtIHMgdyBXJy5zcGxpdCgnICcpLFxuXG4gICAgICAgIGZvcm1hdFRva2VuRnVuY3Rpb25zID0ge1xuICAgICAgICAgICAgTSAgICA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5tb250aCgpICsgMTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBNTU0gIDogZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxhbmcoKS5tb250aHNTaG9ydCh0aGlzLCBmb3JtYXQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIE1NTU0gOiBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFuZygpLm1vbnRocyh0aGlzLCBmb3JtYXQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEQgICAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF0ZSgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIERERCAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZGF5T2ZZZWFyKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZCAgICA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kYXkoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZCAgIDogZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxhbmcoKS53ZWVrZGF5c01pbih0aGlzLCBmb3JtYXQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRkZCAgOiBmdW5jdGlvbiAoZm9ybWF0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFuZygpLndlZWtkYXlzU2hvcnQodGhpcywgZm9ybWF0KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZGRkIDogZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmxhbmcoKS53ZWVrZGF5cyh0aGlzLCBmb3JtYXQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHcgICAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMud2VlaygpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFcgICAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNvV2VlaygpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFlZICAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRaZXJvRmlsbCh0aGlzLnllYXIoKSAlIDEwMCwgMik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgWVlZWSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMueWVhcigpLCA0KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBZWVlZWSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMueWVhcigpLCA1KTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZyAgIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0WmVyb0ZpbGwodGhpcy53ZWVrWWVhcigpICUgMTAwLCAyKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZ2dnIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLndlZWtZZWFyKCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2dnZ2cgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRaZXJvRmlsbCh0aGlzLndlZWtZZWFyKCksIDUpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEdHICAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGxlZnRaZXJvRmlsbCh0aGlzLmlzb1dlZWtZZWFyKCkgJSAxMDAsIDIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEdHR0cgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaXNvV2Vla1llYXIoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBHR0dHRyA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMuaXNvV2Vla1llYXIoKSwgNSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy53ZWVrZGF5KCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgRSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5pc29XZWVrZGF5KCk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYSAgICA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5sYW5nKCkubWVyaWRpZW0odGhpcy5ob3VycygpLCB0aGlzLm1pbnV0ZXMoKSwgdHJ1ZSk7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgQSAgICA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5sYW5nKCkubWVyaWRpZW0odGhpcy5ob3VycygpLCB0aGlzLm1pbnV0ZXMoKSwgZmFsc2UpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEggICAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaG91cnMoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoICAgIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmhvdXJzKCkgJSAxMiB8fCAxMjtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtICAgIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm1pbnV0ZXMoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzICAgIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnNlY29uZHMoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBTICAgIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0b0ludCh0aGlzLm1pbGxpc2Vjb25kcygpIC8gMTAwKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBTUyAgIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBsZWZ0WmVyb0ZpbGwodG9JbnQodGhpcy5taWxsaXNlY29uZHMoKSAvIDEwKSwgMik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgU1NTICA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKHRoaXMubWlsbGlzZWNvbmRzKCksIDMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFogICAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIGEgPSAtdGhpcy56b25lKCksXG4gICAgICAgICAgICAgICAgICAgIGIgPSBcIitcIjtcbiAgICAgICAgICAgICAgICBpZiAoYSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgYSA9IC1hO1xuICAgICAgICAgICAgICAgICAgICBiID0gXCItXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBiICsgbGVmdFplcm9GaWxsKHRvSW50KGEgLyA2MCksIDIpICsgXCI6XCIgKyBsZWZ0WmVyb0ZpbGwodG9JbnQoYSkgJSA2MCwgMik7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgWlogICA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgYSA9IC10aGlzLnpvbmUoKSxcbiAgICAgICAgICAgICAgICAgICAgYiA9IFwiK1wiO1xuICAgICAgICAgICAgICAgIGlmIChhIDwgMCkge1xuICAgICAgICAgICAgICAgICAgICBhID0gLWE7XG4gICAgICAgICAgICAgICAgICAgIGIgPSBcIi1cIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGIgKyBsZWZ0WmVyb0ZpbGwodG9JbnQoMTAgKiBhIC8gNiksIDQpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHogOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuem9uZUFiYnIoKTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB6eiA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy56b25lTmFtZSgpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFggICAgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudW5peCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuXG4gICAgICAgIGxpc3RzID0gWydtb250aHMnLCAnbW9udGhzU2hvcnQnLCAnd2Vla2RheXMnLCAnd2Vla2RheXNTaG9ydCcsICd3ZWVrZGF5c01pbiddO1xuXG4gICAgZnVuY3Rpb24gcGFkVG9rZW4oZnVuYywgY291bnQpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChhKSB7XG4gICAgICAgICAgICByZXR1cm4gbGVmdFplcm9GaWxsKGZ1bmMuY2FsbCh0aGlzLCBhKSwgY291bnQpO1xuICAgICAgICB9O1xuICAgIH1cbiAgICBmdW5jdGlvbiBvcmRpbmFsaXplVG9rZW4oZnVuYywgcGVyaW9kKSB7XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiAoYSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGFuZygpLm9yZGluYWwoZnVuYy5jYWxsKHRoaXMsIGEpLCBwZXJpb2QpO1xuICAgICAgICB9O1xuICAgIH1cblxuICAgIHdoaWxlIChvcmRpbmFsaXplVG9rZW5zLmxlbmd0aCkge1xuICAgICAgICBpID0gb3JkaW5hbGl6ZVRva2Vucy5wb3AoKTtcbiAgICAgICAgZm9ybWF0VG9rZW5GdW5jdGlvbnNbaSArICdvJ10gPSBvcmRpbmFsaXplVG9rZW4oZm9ybWF0VG9rZW5GdW5jdGlvbnNbaV0sIGkpO1xuICAgIH1cbiAgICB3aGlsZSAocGFkZGVkVG9rZW5zLmxlbmd0aCkge1xuICAgICAgICBpID0gcGFkZGVkVG9rZW5zLnBvcCgpO1xuICAgICAgICBmb3JtYXRUb2tlbkZ1bmN0aW9uc1tpICsgaV0gPSBwYWRUb2tlbihmb3JtYXRUb2tlbkZ1bmN0aW9uc1tpXSwgMik7XG4gICAgfVxuICAgIGZvcm1hdFRva2VuRnVuY3Rpb25zLkREREQgPSBwYWRUb2tlbihmb3JtYXRUb2tlbkZ1bmN0aW9ucy5EREQsIDMpO1xuXG5cbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgIENvbnN0cnVjdG9yc1xuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuICAgIGZ1bmN0aW9uIExhbmd1YWdlKCkge1xuXG4gICAgfVxuXG4gICAgLy8gTW9tZW50IHByb3RvdHlwZSBvYmplY3RcbiAgICBmdW5jdGlvbiBNb21lbnQoY29uZmlnKSB7XG4gICAgICAgIGNoZWNrT3ZlcmZsb3coY29uZmlnKTtcbiAgICAgICAgZXh0ZW5kKHRoaXMsIGNvbmZpZyk7XG4gICAgfVxuXG4gICAgLy8gRHVyYXRpb24gQ29uc3RydWN0b3JcbiAgICBmdW5jdGlvbiBEdXJhdGlvbihkdXJhdGlvbikge1xuICAgICAgICB2YXIgbm9ybWFsaXplZElucHV0ID0gbm9ybWFsaXplT2JqZWN0VW5pdHMoZHVyYXRpb24pLFxuICAgICAgICAgICAgeWVhcnMgPSBub3JtYWxpemVkSW5wdXQueWVhciB8fCAwLFxuICAgICAgICAgICAgbW9udGhzID0gbm9ybWFsaXplZElucHV0Lm1vbnRoIHx8IDAsXG4gICAgICAgICAgICB3ZWVrcyA9IG5vcm1hbGl6ZWRJbnB1dC53ZWVrIHx8IDAsXG4gICAgICAgICAgICBkYXlzID0gbm9ybWFsaXplZElucHV0LmRheSB8fCAwLFxuICAgICAgICAgICAgaG91cnMgPSBub3JtYWxpemVkSW5wdXQuaG91ciB8fCAwLFxuICAgICAgICAgICAgbWludXRlcyA9IG5vcm1hbGl6ZWRJbnB1dC5taW51dGUgfHwgMCxcbiAgICAgICAgICAgIHNlY29uZHMgPSBub3JtYWxpemVkSW5wdXQuc2Vjb25kIHx8IDAsXG4gICAgICAgICAgICBtaWxsaXNlY29uZHMgPSBub3JtYWxpemVkSW5wdXQubWlsbGlzZWNvbmQgfHwgMDtcblxuICAgICAgICAvLyBzdG9yZSByZWZlcmVuY2UgdG8gaW5wdXQgZm9yIGRldGVybWluaXN0aWMgY2xvbmluZ1xuICAgICAgICB0aGlzLl9pbnB1dCA9IGR1cmF0aW9uO1xuXG4gICAgICAgIC8vIHJlcHJlc2VudGF0aW9uIGZvciBkYXRlQWRkUmVtb3ZlXG4gICAgICAgIHRoaXMuX21pbGxpc2Vjb25kcyA9ICttaWxsaXNlY29uZHMgK1xuICAgICAgICAgICAgc2Vjb25kcyAqIDFlMyArIC8vIDEwMDBcbiAgICAgICAgICAgIG1pbnV0ZXMgKiA2ZTQgKyAvLyAxMDAwICogNjBcbiAgICAgICAgICAgIGhvdXJzICogMzZlNTsgLy8gMTAwMCAqIDYwICogNjBcbiAgICAgICAgLy8gQmVjYXVzZSBvZiBkYXRlQWRkUmVtb3ZlIHRyZWF0cyAyNCBob3VycyBhcyBkaWZmZXJlbnQgZnJvbSBhXG4gICAgICAgIC8vIGRheSB3aGVuIHdvcmtpbmcgYXJvdW5kIERTVCwgd2UgbmVlZCB0byBzdG9yZSB0aGVtIHNlcGFyYXRlbHlcbiAgICAgICAgdGhpcy5fZGF5cyA9ICtkYXlzICtcbiAgICAgICAgICAgIHdlZWtzICogNztcbiAgICAgICAgLy8gSXQgaXMgaW1wb3NzaWJsZSB0cmFuc2xhdGUgbW9udGhzIGludG8gZGF5cyB3aXRob3V0IGtub3dpbmdcbiAgICAgICAgLy8gd2hpY2ggbW9udGhzIHlvdSBhcmUgYXJlIHRhbGtpbmcgYWJvdXQsIHNvIHdlIGhhdmUgdG8gc3RvcmVcbiAgICAgICAgLy8gaXQgc2VwYXJhdGVseS5cbiAgICAgICAgdGhpcy5fbW9udGhzID0gK21vbnRocyArXG4gICAgICAgICAgICB5ZWFycyAqIDEyO1xuXG4gICAgICAgIHRoaXMuX2RhdGEgPSB7fTtcblxuICAgICAgICB0aGlzLl9idWJibGUoKTtcbiAgICB9XG5cbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgIEhlbHBlcnNcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cblxuICAgIGZ1bmN0aW9uIGV4dGVuZChhLCBiKSB7XG4gICAgICAgIGZvciAodmFyIGkgaW4gYikge1xuICAgICAgICAgICAgaWYgKGIuaGFzT3duUHJvcGVydHkoaSkpIHtcbiAgICAgICAgICAgICAgICBhW2ldID0gYltpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChiLmhhc093blByb3BlcnR5KFwidG9TdHJpbmdcIikpIHtcbiAgICAgICAgICAgIGEudG9TdHJpbmcgPSBiLnRvU3RyaW5nO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGIuaGFzT3duUHJvcGVydHkoXCJ2YWx1ZU9mXCIpKSB7XG4gICAgICAgICAgICBhLnZhbHVlT2YgPSBiLnZhbHVlT2Y7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhYnNSb3VuZChudW1iZXIpIHtcbiAgICAgICAgaWYgKG51bWJlciA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmNlaWwobnVtYmVyKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKG51bWJlcik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBsZWZ0IHplcm8gZmlsbCBhIG51bWJlclxuICAgIC8vIHNlZSBodHRwOi8vanNwZXJmLmNvbS9sZWZ0LXplcm8tZmlsbGluZyBmb3IgcGVyZm9ybWFuY2UgY29tcGFyaXNvblxuICAgIGZ1bmN0aW9uIGxlZnRaZXJvRmlsbChudW1iZXIsIHRhcmdldExlbmd0aCkge1xuICAgICAgICB2YXIgb3V0cHV0ID0gbnVtYmVyICsgJyc7XG4gICAgICAgIHdoaWxlIChvdXRwdXQubGVuZ3RoIDwgdGFyZ2V0TGVuZ3RoKSB7XG4gICAgICAgICAgICBvdXRwdXQgPSAnMCcgKyBvdXRwdXQ7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICB9XG5cbiAgICAvLyBoZWxwZXIgZnVuY3Rpb24gZm9yIF8uYWRkVGltZSBhbmQgXy5zdWJ0cmFjdFRpbWVcbiAgICBmdW5jdGlvbiBhZGRPclN1YnRyYWN0RHVyYXRpb25Gcm9tTW9tZW50KG1vbSwgZHVyYXRpb24sIGlzQWRkaW5nLCBpZ25vcmVVcGRhdGVPZmZzZXQpIHtcbiAgICAgICAgdmFyIG1pbGxpc2Vjb25kcyA9IGR1cmF0aW9uLl9taWxsaXNlY29uZHMsXG4gICAgICAgICAgICBkYXlzID0gZHVyYXRpb24uX2RheXMsXG4gICAgICAgICAgICBtb250aHMgPSBkdXJhdGlvbi5fbW9udGhzLFxuICAgICAgICAgICAgbWludXRlcyxcbiAgICAgICAgICAgIGhvdXJzO1xuXG4gICAgICAgIGlmIChtaWxsaXNlY29uZHMpIHtcbiAgICAgICAgICAgIG1vbS5fZC5zZXRUaW1lKCttb20uX2QgKyBtaWxsaXNlY29uZHMgKiBpc0FkZGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gc3RvcmUgdGhlIG1pbnV0ZXMgYW5kIGhvdXJzIHNvIHdlIGNhbiByZXN0b3JlIHRoZW1cbiAgICAgICAgaWYgKGRheXMgfHwgbW9udGhzKSB7XG4gICAgICAgICAgICBtaW51dGVzID0gbW9tLm1pbnV0ZSgpO1xuICAgICAgICAgICAgaG91cnMgPSBtb20uaG91cigpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChkYXlzKSB7XG4gICAgICAgICAgICBtb20uZGF0ZShtb20uZGF0ZSgpICsgZGF5cyAqIGlzQWRkaW5nKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobW9udGhzKSB7XG4gICAgICAgICAgICBtb20ubW9udGgobW9tLm1vbnRoKCkgKyBtb250aHMgKiBpc0FkZGluZyk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1pbGxpc2Vjb25kcyAmJiAhaWdub3JlVXBkYXRlT2Zmc2V0KSB7XG4gICAgICAgICAgICBtb21lbnQudXBkYXRlT2Zmc2V0KG1vbSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gcmVzdG9yZSB0aGUgbWludXRlcyBhbmQgaG91cnMgYWZ0ZXIgcG9zc2libHkgY2hhbmdpbmcgZHN0XG4gICAgICAgIGlmIChkYXlzIHx8IG1vbnRocykge1xuICAgICAgICAgICAgbW9tLm1pbnV0ZShtaW51dGVzKTtcbiAgICAgICAgICAgIG1vbS5ob3VyKGhvdXJzKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNoZWNrIGlmIGlzIGFuIGFycmF5XG4gICAgZnVuY3Rpb24gaXNBcnJheShpbnB1dCkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGlucHV0KSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0RhdGUoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChpbnB1dCkgPT09ICdbb2JqZWN0IERhdGVdJztcbiAgICB9XG5cbiAgICAvLyBjb21wYXJlIHR3byBhcnJheXMsIHJldHVybiB0aGUgbnVtYmVyIG9mIGRpZmZlcmVuY2VzXG4gICAgZnVuY3Rpb24gY29tcGFyZUFycmF5cyhhcnJheTEsIGFycmF5MiwgZG9udENvbnZlcnQpIHtcbiAgICAgICAgdmFyIGxlbiA9IE1hdGgubWluKGFycmF5MS5sZW5ndGgsIGFycmF5Mi5sZW5ndGgpLFxuICAgICAgICAgICAgbGVuZ3RoRGlmZiA9IE1hdGguYWJzKGFycmF5MS5sZW5ndGggLSBhcnJheTIubGVuZ3RoKSxcbiAgICAgICAgICAgIGRpZmZzID0gMCxcbiAgICAgICAgICAgIGk7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKykge1xuICAgICAgICAgICAgaWYgKChkb250Q29udmVydCAmJiBhcnJheTFbaV0gIT09IGFycmF5MltpXSkgfHxcbiAgICAgICAgICAgICAgICAoIWRvbnRDb252ZXJ0ICYmIHRvSW50KGFycmF5MVtpXSkgIT09IHRvSW50KGFycmF5MltpXSkpKSB7XG4gICAgICAgICAgICAgICAgZGlmZnMrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGlmZnMgKyBsZW5ndGhEaWZmO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZVVuaXRzKHVuaXRzKSB7XG4gICAgICAgIGlmICh1bml0cykge1xuICAgICAgICAgICAgdmFyIGxvd2VyZWQgPSB1bml0cy50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoLyguKXMkLywgJyQxJyk7XG4gICAgICAgICAgICB1bml0cyA9IHVuaXRBbGlhc2VzW3VuaXRzXSB8fCBjYW1lbEZ1bmN0aW9uc1tsb3dlcmVkXSB8fCBsb3dlcmVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB1bml0cztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub3JtYWxpemVPYmplY3RVbml0cyhpbnB1dE9iamVjdCkge1xuICAgICAgICB2YXIgbm9ybWFsaXplZElucHV0ID0ge30sXG4gICAgICAgICAgICBub3JtYWxpemVkUHJvcCxcbiAgICAgICAgICAgIHByb3AsXG4gICAgICAgICAgICBpbmRleDtcblxuICAgICAgICBmb3IgKHByb3AgaW4gaW5wdXRPYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChpbnB1dE9iamVjdC5oYXNPd25Qcm9wZXJ0eShwcm9wKSkge1xuICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRQcm9wID0gbm9ybWFsaXplVW5pdHMocHJvcCk7XG4gICAgICAgICAgICAgICAgaWYgKG5vcm1hbGl6ZWRQcm9wKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vcm1hbGl6ZWRJbnB1dFtub3JtYWxpemVkUHJvcF0gPSBpbnB1dE9iamVjdFtwcm9wXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbm9ybWFsaXplZElucHV0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VMaXN0KGZpZWxkKSB7XG4gICAgICAgIHZhciBjb3VudCwgc2V0dGVyO1xuXG4gICAgICAgIGlmIChmaWVsZC5pbmRleE9mKCd3ZWVrJykgPT09IDApIHtcbiAgICAgICAgICAgIGNvdW50ID0gNztcbiAgICAgICAgICAgIHNldHRlciA9ICdkYXknO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGZpZWxkLmluZGV4T2YoJ21vbnRoJykgPT09IDApIHtcbiAgICAgICAgICAgIGNvdW50ID0gMTI7XG4gICAgICAgICAgICBzZXR0ZXIgPSAnbW9udGgnO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgbW9tZW50W2ZpZWxkXSA9IGZ1bmN0aW9uIChmb3JtYXQsIGluZGV4KSB7XG4gICAgICAgICAgICB2YXIgaSwgZ2V0dGVyLFxuICAgICAgICAgICAgICAgIG1ldGhvZCA9IG1vbWVudC5mbi5fbGFuZ1tmaWVsZF0sXG4gICAgICAgICAgICAgICAgcmVzdWx0cyA9IFtdO1xuXG4gICAgICAgICAgICBpZiAodHlwZW9mIGZvcm1hdCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICBpbmRleCA9IGZvcm1hdDtcbiAgICAgICAgICAgICAgICBmb3JtYXQgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGdldHRlciA9IGZ1bmN0aW9uIChpKSB7XG4gICAgICAgICAgICAgICAgdmFyIG0gPSBtb21lbnQoKS51dGMoKS5zZXQoc2V0dGVyLCBpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbWV0aG9kLmNhbGwobW9tZW50LmZuLl9sYW5nLCBtLCBmb3JtYXQgfHwgJycpO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgaWYgKGluZGV4KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGdldHRlcihpbmRleCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goZ2V0dGVyKGkpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdHM7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdG9JbnQoYXJndW1lbnRGb3JDb2VyY2lvbikge1xuICAgICAgICB2YXIgY29lcmNlZE51bWJlciA9ICthcmd1bWVudEZvckNvZXJjaW9uLFxuICAgICAgICAgICAgdmFsdWUgPSAwO1xuXG4gICAgICAgIGlmIChjb2VyY2VkTnVtYmVyICE9PSAwICYmIGlzRmluaXRlKGNvZXJjZWROdW1iZXIpKSB7XG4gICAgICAgICAgICBpZiAoY29lcmNlZE51bWJlciA+PSAwKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBNYXRoLmZsb29yKGNvZXJjZWROdW1iZXIpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IE1hdGguY2VpbChjb2VyY2VkTnVtYmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkYXlzSW5Nb250aCh5ZWFyLCBtb250aCkge1xuICAgICAgICByZXR1cm4gbmV3IERhdGUoRGF0ZS5VVEMoeWVhciwgbW9udGggKyAxLCAwKSkuZ2V0VVRDRGF0ZSgpO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGRheXNJblllYXIoeWVhcikge1xuICAgICAgICByZXR1cm4gaXNMZWFwWWVhcih5ZWFyKSA/IDM2NiA6IDM2NTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpc0xlYXBZZWFyKHllYXIpIHtcbiAgICAgICAgcmV0dXJuICh5ZWFyICUgNCA9PT0gMCAmJiB5ZWFyICUgMTAwICE9PSAwKSB8fCB5ZWFyICUgNDAwID09PSAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNoZWNrT3ZlcmZsb3cobSkge1xuICAgICAgICB2YXIgb3ZlcmZsb3c7XG4gICAgICAgIGlmIChtLl9hICYmIG0uX3BmLm92ZXJmbG93ID09PSAtMikge1xuICAgICAgICAgICAgb3ZlcmZsb3cgPVxuICAgICAgICAgICAgICAgIG0uX2FbTU9OVEhdIDwgMCB8fCBtLl9hW01PTlRIXSA+IDExID8gTU9OVEggOlxuICAgICAgICAgICAgICAgIG0uX2FbREFURV0gPCAxIHx8IG0uX2FbREFURV0gPiBkYXlzSW5Nb250aChtLl9hW1lFQVJdLCBtLl9hW01PTlRIXSkgPyBEQVRFIDpcbiAgICAgICAgICAgICAgICBtLl9hW0hPVVJdIDwgMCB8fCBtLl9hW0hPVVJdID4gMjMgPyBIT1VSIDpcbiAgICAgICAgICAgICAgICBtLl9hW01JTlVURV0gPCAwIHx8IG0uX2FbTUlOVVRFXSA+IDU5ID8gTUlOVVRFIDpcbiAgICAgICAgICAgICAgICBtLl9hW1NFQ09ORF0gPCAwIHx8IG0uX2FbU0VDT05EXSA+IDU5ID8gU0VDT05EIDpcbiAgICAgICAgICAgICAgICBtLl9hW01JTExJU0VDT05EXSA8IDAgfHwgbS5fYVtNSUxMSVNFQ09ORF0gPiA5OTkgPyBNSUxMSVNFQ09ORCA6XG4gICAgICAgICAgICAgICAgLTE7XG5cbiAgICAgICAgICAgIGlmIChtLl9wZi5fb3ZlcmZsb3dEYXlPZlllYXIgJiYgKG92ZXJmbG93IDwgWUVBUiB8fCBvdmVyZmxvdyA+IERBVEUpKSB7XG4gICAgICAgICAgICAgICAgb3ZlcmZsb3cgPSBEQVRFO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBtLl9wZi5vdmVyZmxvdyA9IG92ZXJmbG93O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5pdGlhbGl6ZVBhcnNpbmdGbGFncyhjb25maWcpIHtcbiAgICAgICAgY29uZmlnLl9wZiA9IHtcbiAgICAgICAgICAgIGVtcHR5IDogZmFsc2UsXG4gICAgICAgICAgICB1bnVzZWRUb2tlbnMgOiBbXSxcbiAgICAgICAgICAgIHVudXNlZElucHV0IDogW10sXG4gICAgICAgICAgICBvdmVyZmxvdyA6IC0yLFxuICAgICAgICAgICAgY2hhcnNMZWZ0T3ZlciA6IDAsXG4gICAgICAgICAgICBudWxsSW5wdXQgOiBmYWxzZSxcbiAgICAgICAgICAgIGludmFsaWRNb250aCA6IG51bGwsXG4gICAgICAgICAgICBpbnZhbGlkRm9ybWF0IDogZmFsc2UsXG4gICAgICAgICAgICB1c2VySW52YWxpZGF0ZWQgOiBmYWxzZVxuICAgICAgICB9O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGlzVmFsaWQobSkge1xuICAgICAgICBpZiAobS5faXNWYWxpZCA9PSBudWxsKSB7XG4gICAgICAgICAgICBtLl9pc1ZhbGlkID0gIWlzTmFOKG0uX2QuZ2V0VGltZSgpKSAmJlxuICAgICAgICAgICAgICAgIG0uX3BmLm92ZXJmbG93IDwgMCAmJlxuICAgICAgICAgICAgICAgICFtLl9wZi5lbXB0eSAmJlxuICAgICAgICAgICAgICAgICFtLl9wZi5pbnZhbGlkTW9udGggJiZcbiAgICAgICAgICAgICAgICAhbS5fcGYubnVsbElucHV0ICYmXG4gICAgICAgICAgICAgICAgIW0uX3BmLmludmFsaWRGb3JtYXQgJiZcbiAgICAgICAgICAgICAgICAhbS5fcGYudXNlckludmFsaWRhdGVkO1xuXG4gICAgICAgICAgICBpZiAobS5fc3RyaWN0KSB7XG4gICAgICAgICAgICAgICAgbS5faXNWYWxpZCA9IG0uX2lzVmFsaWQgJiZcbiAgICAgICAgICAgICAgICAgICAgbS5fcGYuY2hhcnNMZWZ0T3ZlciA9PT0gMCAmJlxuICAgICAgICAgICAgICAgICAgICBtLl9wZi51bnVzZWRUb2tlbnMubGVuZ3RoID09PSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBtLl9pc1ZhbGlkO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIG5vcm1hbGl6ZUxhbmd1YWdlKGtleSkge1xuICAgICAgICByZXR1cm4ga2V5ID8ga2V5LnRvTG93ZXJDYXNlKCkucmVwbGFjZSgnXycsICctJykgOiBrZXk7XG4gICAgfVxuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICBMYW5ndWFnZXNcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cblxuICAgIGV4dGVuZChMYW5ndWFnZS5wcm90b3R5cGUsIHtcblxuICAgICAgICBzZXQgOiBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgICAgICB2YXIgcHJvcCwgaTtcbiAgICAgICAgICAgIGZvciAoaSBpbiBjb25maWcpIHtcbiAgICAgICAgICAgICAgICBwcm9wID0gY29uZmlnW2ldO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgcHJvcCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICB0aGlzW2ldID0gcHJvcDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzWydfJyArIGldID0gcHJvcDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgX21vbnRocyA6IFwiSmFudWFyeV9GZWJydWFyeV9NYXJjaF9BcHJpbF9NYXlfSnVuZV9KdWx5X0F1Z3VzdF9TZXB0ZW1iZXJfT2N0b2Jlcl9Ob3ZlbWJlcl9EZWNlbWJlclwiLnNwbGl0KFwiX1wiKSxcbiAgICAgICAgbW9udGhzIDogZnVuY3Rpb24gKG0pIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tb250aHNbbS5tb250aCgpXTtcbiAgICAgICAgfSxcblxuICAgICAgICBfbW9udGhzU2hvcnQgOiBcIkphbl9GZWJfTWFyX0Fwcl9NYXlfSnVuX0p1bF9BdWdfU2VwX09jdF9Ob3ZfRGVjXCIuc3BsaXQoXCJfXCIpLFxuICAgICAgICBtb250aHNTaG9ydCA6IGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbW9udGhzU2hvcnRbbS5tb250aCgpXTtcbiAgICAgICAgfSxcblxuICAgICAgICBtb250aHNQYXJzZSA6IGZ1bmN0aW9uIChtb250aE5hbWUpIHtcbiAgICAgICAgICAgIHZhciBpLCBtb20sIHJlZ2V4O1xuXG4gICAgICAgICAgICBpZiAoIXRoaXMuX21vbnRoc1BhcnNlKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fbW9udGhzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgICAgICAgICAvLyBtYWtlIHRoZSByZWdleCBpZiB3ZSBkb24ndCBoYXZlIGl0IGFscmVhZHlcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX21vbnRoc1BhcnNlW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgIG1vbSA9IG1vbWVudC51dGMoWzIwMDAsIGldKTtcbiAgICAgICAgICAgICAgICAgICAgcmVnZXggPSAnXicgKyB0aGlzLm1vbnRocyhtb20sICcnKSArICd8XicgKyB0aGlzLm1vbnRoc1Nob3J0KG1vbSwgJycpO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9tb250aHNQYXJzZVtpXSA9IG5ldyBSZWdFeHAocmVnZXgucmVwbGFjZSgnLicsICcnKSwgJ2knKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gdGVzdCB0aGUgcmVnZXhcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fbW9udGhzUGFyc2VbaV0udGVzdChtb250aE5hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBfd2Vla2RheXMgOiBcIlN1bmRheV9Nb25kYXlfVHVlc2RheV9XZWRuZXNkYXlfVGh1cnNkYXlfRnJpZGF5X1NhdHVyZGF5XCIuc3BsaXQoXCJfXCIpLFxuICAgICAgICB3ZWVrZGF5cyA6IGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNbbS5kYXkoKV07XG4gICAgICAgIH0sXG5cbiAgICAgICAgX3dlZWtkYXlzU2hvcnQgOiBcIlN1bl9Nb25fVHVlX1dlZF9UaHVfRnJpX1NhdFwiLnNwbGl0KFwiX1wiKSxcbiAgICAgICAgd2Vla2RheXNTaG9ydCA6IGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNTaG9ydFttLmRheSgpXTtcbiAgICAgICAgfSxcblxuICAgICAgICBfd2Vla2RheXNNaW4gOiBcIlN1X01vX1R1X1dlX1RoX0ZyX1NhXCIuc3BsaXQoXCJfXCIpLFxuICAgICAgICB3ZWVrZGF5c01pbiA6IGZ1bmN0aW9uIChtKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fd2Vla2RheXNNaW5bbS5kYXkoKV07XG4gICAgICAgIH0sXG5cbiAgICAgICAgd2Vla2RheXNQYXJzZSA6IGZ1bmN0aW9uICh3ZWVrZGF5TmFtZSkge1xuICAgICAgICAgICAgdmFyIGksIG1vbSwgcmVnZXg7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5fd2Vla2RheXNQYXJzZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3dlZWtkYXlzUGFyc2UgPSBbXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDc7IGkrKykge1xuICAgICAgICAgICAgICAgIC8vIG1ha2UgdGhlIHJlZ2V4IGlmIHdlIGRvbid0IGhhdmUgaXQgYWxyZWFkeVxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fd2Vla2RheXNQYXJzZVtpXSkge1xuICAgICAgICAgICAgICAgICAgICBtb20gPSBtb21lbnQoWzIwMDAsIDFdKS5kYXkoaSk7XG4gICAgICAgICAgICAgICAgICAgIHJlZ2V4ID0gJ14nICsgdGhpcy53ZWVrZGF5cyhtb20sICcnKSArICd8XicgKyB0aGlzLndlZWtkYXlzU2hvcnQobW9tLCAnJykgKyAnfF4nICsgdGhpcy53ZWVrZGF5c01pbihtb20sICcnKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fd2Vla2RheXNQYXJzZVtpXSA9IG5ldyBSZWdFeHAocmVnZXgucmVwbGFjZSgnLicsICcnKSwgJ2knKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gdGVzdCB0aGUgcmVnZXhcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fd2Vla2RheXNQYXJzZVtpXS50ZXN0KHdlZWtkYXlOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgX2xvbmdEYXRlRm9ybWF0IDoge1xuICAgICAgICAgICAgTFQgOiBcImg6bW0gQVwiLFxuICAgICAgICAgICAgTCA6IFwiTU0vREQvWVlZWVwiLFxuICAgICAgICAgICAgTEwgOiBcIk1NTU0gRCBZWVlZXCIsXG4gICAgICAgICAgICBMTEwgOiBcIk1NTU0gRCBZWVlZIExUXCIsXG4gICAgICAgICAgICBMTExMIDogXCJkZGRkLCBNTU1NIEQgWVlZWSBMVFwiXG4gICAgICAgIH0sXG4gICAgICAgIGxvbmdEYXRlRm9ybWF0IDogZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgdmFyIG91dHB1dCA9IHRoaXMuX2xvbmdEYXRlRm9ybWF0W2tleV07XG4gICAgICAgICAgICBpZiAoIW91dHB1dCAmJiB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXkudG9VcHBlckNhc2UoKV0pIHtcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXkudG9VcHBlckNhc2UoKV0ucmVwbGFjZSgvTU1NTXxNTXxERHxkZGRkL2csIGZ1bmN0aW9uICh2YWwpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbC5zbGljZSgxKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLl9sb25nRGF0ZUZvcm1hdFtrZXldID0gb3V0cHV0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgICAgfSxcblxuICAgICAgICBpc1BNIDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICAvLyBJRTggUXVpcmtzIE1vZGUgJiBJRTcgU3RhbmRhcmRzIE1vZGUgZG8gbm90IGFsbG93IGFjY2Vzc2luZyBzdHJpbmdzIGxpa2UgYXJyYXlzXG4gICAgICAgICAgICAvLyBVc2luZyBjaGFyQXQgc2hvdWxkIGJlIG1vcmUgY29tcGF0aWJsZS5cbiAgICAgICAgICAgIHJldHVybiAoKGlucHV0ICsgJycpLnRvTG93ZXJDYXNlKCkuY2hhckF0KDApID09PSAncCcpO1xuICAgICAgICB9LFxuXG4gICAgICAgIF9tZXJpZGllbVBhcnNlIDogL1thcF1cXC4/bT9cXC4/L2ksXG4gICAgICAgIG1lcmlkaWVtIDogZnVuY3Rpb24gKGhvdXJzLCBtaW51dGVzLCBpc0xvd2VyKSB7XG4gICAgICAgICAgICBpZiAoaG91cnMgPiAxMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ3BtJyA6ICdQTSc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc0xvd2VyID8gJ2FtJyA6ICdBTSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgX2NhbGVuZGFyIDoge1xuICAgICAgICAgICAgc2FtZURheSA6ICdbVG9kYXkgYXRdIExUJyxcbiAgICAgICAgICAgIG5leHREYXkgOiAnW1RvbW9ycm93IGF0XSBMVCcsXG4gICAgICAgICAgICBuZXh0V2VlayA6ICdkZGRkIFthdF0gTFQnLFxuICAgICAgICAgICAgbGFzdERheSA6ICdbWWVzdGVyZGF5IGF0XSBMVCcsXG4gICAgICAgICAgICBsYXN0V2VlayA6ICdbTGFzdF0gZGRkZCBbYXRdIExUJyxcbiAgICAgICAgICAgIHNhbWVFbHNlIDogJ0wnXG4gICAgICAgIH0sXG4gICAgICAgIGNhbGVuZGFyIDogZnVuY3Rpb24gKGtleSwgbW9tKSB7XG4gICAgICAgICAgICB2YXIgb3V0cHV0ID0gdGhpcy5fY2FsZW5kYXJba2V5XTtcbiAgICAgICAgICAgIHJldHVybiB0eXBlb2Ygb3V0cHV0ID09PSAnZnVuY3Rpb24nID8gb3V0cHV0LmFwcGx5KG1vbSkgOiBvdXRwdXQ7XG4gICAgICAgIH0sXG5cbiAgICAgICAgX3JlbGF0aXZlVGltZSA6IHtcbiAgICAgICAgICAgIGZ1dHVyZSA6IFwiaW4gJXNcIixcbiAgICAgICAgICAgIHBhc3QgOiBcIiVzIGFnb1wiLFxuICAgICAgICAgICAgcyA6IFwiYSBmZXcgc2Vjb25kc1wiLFxuICAgICAgICAgICAgbSA6IFwiYSBtaW51dGVcIixcbiAgICAgICAgICAgIG1tIDogXCIlZCBtaW51dGVzXCIsXG4gICAgICAgICAgICBoIDogXCJhbiBob3VyXCIsXG4gICAgICAgICAgICBoaCA6IFwiJWQgaG91cnNcIixcbiAgICAgICAgICAgIGQgOiBcImEgZGF5XCIsXG4gICAgICAgICAgICBkZCA6IFwiJWQgZGF5c1wiLFxuICAgICAgICAgICAgTSA6IFwiYSBtb250aFwiLFxuICAgICAgICAgICAgTU0gOiBcIiVkIG1vbnRoc1wiLFxuICAgICAgICAgICAgeSA6IFwiYSB5ZWFyXCIsXG4gICAgICAgICAgICB5eSA6IFwiJWQgeWVhcnNcIlxuICAgICAgICB9LFxuICAgICAgICByZWxhdGl2ZVRpbWUgOiBmdW5jdGlvbiAobnVtYmVyLCB3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKSB7XG4gICAgICAgICAgICB2YXIgb3V0cHV0ID0gdGhpcy5fcmVsYXRpdmVUaW1lW3N0cmluZ107XG4gICAgICAgICAgICByZXR1cm4gKHR5cGVvZiBvdXRwdXQgPT09ICdmdW5jdGlvbicpID9cbiAgICAgICAgICAgICAgICBvdXRwdXQobnVtYmVyLCB3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKSA6XG4gICAgICAgICAgICAgICAgb3V0cHV0LnJlcGxhY2UoLyVkL2ksIG51bWJlcik7XG4gICAgICAgIH0sXG4gICAgICAgIHBhc3RGdXR1cmUgOiBmdW5jdGlvbiAoZGlmZiwgb3V0cHV0KSB7XG4gICAgICAgICAgICB2YXIgZm9ybWF0ID0gdGhpcy5fcmVsYXRpdmVUaW1lW2RpZmYgPiAwID8gJ2Z1dHVyZScgOiAncGFzdCddO1xuICAgICAgICAgICAgcmV0dXJuIHR5cGVvZiBmb3JtYXQgPT09ICdmdW5jdGlvbicgPyBmb3JtYXQob3V0cHV0KSA6IGZvcm1hdC5yZXBsYWNlKC8lcy9pLCBvdXRwdXQpO1xuICAgICAgICB9LFxuXG4gICAgICAgIG9yZGluYWwgOiBmdW5jdGlvbiAobnVtYmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3JkaW5hbC5yZXBsYWNlKFwiJWRcIiwgbnVtYmVyKTtcbiAgICAgICAgfSxcbiAgICAgICAgX29yZGluYWwgOiBcIiVkXCIsXG5cbiAgICAgICAgcHJlcGFyc2UgOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgICB9LFxuXG4gICAgICAgIHBvc3Rmb3JtYXQgOiBmdW5jdGlvbiAoc3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gc3RyaW5nO1xuICAgICAgICB9LFxuXG4gICAgICAgIHdlZWsgOiBmdW5jdGlvbiAobW9tKSB7XG4gICAgICAgICAgICByZXR1cm4gd2Vla09mWWVhcihtb20sIHRoaXMuX3dlZWsuZG93LCB0aGlzLl93ZWVrLmRveSkud2VlaztcbiAgICAgICAgfSxcblxuICAgICAgICBfd2VlayA6IHtcbiAgICAgICAgICAgIGRvdyA6IDAsIC8vIFN1bmRheSBpcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuICAgICAgICAgICAgZG95IDogNiAgLy8gVGhlIHdlZWsgdGhhdCBjb250YWlucyBKYW4gMXN0IGlzIHRoZSBmaXJzdCB3ZWVrIG9mIHRoZSB5ZWFyLlxuICAgICAgICB9LFxuXG4gICAgICAgIF9pbnZhbGlkRGF0ZTogJ0ludmFsaWQgZGF0ZScsXG4gICAgICAgIGludmFsaWREYXRlOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faW52YWxpZERhdGU7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIExvYWRzIGEgbGFuZ3VhZ2UgZGVmaW5pdGlvbiBpbnRvIHRoZSBgbGFuZ3VhZ2VzYCBjYWNoZS4gIFRoZSBmdW5jdGlvblxuICAgIC8vIHRha2VzIGEga2V5IGFuZCBvcHRpb25hbGx5IHZhbHVlcy4gIElmIG5vdCBpbiB0aGUgYnJvd3NlciBhbmQgbm8gdmFsdWVzXG4gICAgLy8gYXJlIHByb3ZpZGVkLCBpdCB3aWxsIGxvYWQgdGhlIGxhbmd1YWdlIGZpbGUgbW9kdWxlLiAgQXMgYSBjb252ZW5pZW5jZSxcbiAgICAvLyB0aGlzIGZ1bmN0aW9uIGFsc28gcmV0dXJucyB0aGUgbGFuZ3VhZ2UgdmFsdWVzLlxuICAgIGZ1bmN0aW9uIGxvYWRMYW5nKGtleSwgdmFsdWVzKSB7XG4gICAgICAgIHZhbHVlcy5hYmJyID0ga2V5O1xuICAgICAgICBpZiAoIWxhbmd1YWdlc1trZXldKSB7XG4gICAgICAgICAgICBsYW5ndWFnZXNba2V5XSA9IG5ldyBMYW5ndWFnZSgpO1xuICAgICAgICB9XG4gICAgICAgIGxhbmd1YWdlc1trZXldLnNldCh2YWx1ZXMpO1xuICAgICAgICByZXR1cm4gbGFuZ3VhZ2VzW2tleV07XG4gICAgfVxuXG4gICAgLy8gUmVtb3ZlIGEgbGFuZ3VhZ2UgZnJvbSB0aGUgYGxhbmd1YWdlc2AgY2FjaGUuIE1vc3RseSB1c2VmdWwgaW4gdGVzdHMuXG4gICAgZnVuY3Rpb24gdW5sb2FkTGFuZyhrZXkpIHtcbiAgICAgICAgZGVsZXRlIGxhbmd1YWdlc1trZXldO1xuICAgIH1cblxuICAgIC8vIERldGVybWluZXMgd2hpY2ggbGFuZ3VhZ2UgZGVmaW5pdGlvbiB0byB1c2UgYW5kIHJldHVybnMgaXQuXG4gICAgLy9cbiAgICAvLyBXaXRoIG5vIHBhcmFtZXRlcnMsIGl0IHdpbGwgcmV0dXJuIHRoZSBnbG9iYWwgbGFuZ3VhZ2UuICBJZiB5b3VcbiAgICAvLyBwYXNzIGluIGEgbGFuZ3VhZ2Uga2V5LCBzdWNoIGFzICdlbicsIGl0IHdpbGwgcmV0dXJuIHRoZVxuICAgIC8vIGRlZmluaXRpb24gZm9yICdlbicsIHNvIGxvbmcgYXMgJ2VuJyBoYXMgYWxyZWFkeSBiZWVuIGxvYWRlZCB1c2luZ1xuICAgIC8vIG1vbWVudC5sYW5nLlxuICAgIGZ1bmN0aW9uIGdldExhbmdEZWZpbml0aW9uKGtleSkge1xuICAgICAgICB2YXIgaSA9IDAsIGosIGxhbmcsIG5leHQsIHNwbGl0LFxuICAgICAgICAgICAgZ2V0ID0gZnVuY3Rpb24gKGspIHtcbiAgICAgICAgICAgICAgICBpZiAoIWxhbmd1YWdlc1trXSAmJiBoYXNNb2R1bGUpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmUoJy4vbGFuZy8nICsgayk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHsgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gbGFuZ3VhZ2VzW2tdO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICBpZiAoIWtleSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbWVudC5mbi5fbGFuZztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNBcnJheShrZXkpKSB7XG4gICAgICAgICAgICAvL3Nob3J0LWNpcmN1aXQgZXZlcnl0aGluZyBlbHNlXG4gICAgICAgICAgICBsYW5nID0gZ2V0KGtleSk7XG4gICAgICAgICAgICBpZiAobGFuZykge1xuICAgICAgICAgICAgICAgIHJldHVybiBsYW5nO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAga2V5ID0gW2tleV07XG4gICAgICAgIH1cblxuICAgICAgICAvL3BpY2sgdGhlIGxhbmd1YWdlIGZyb20gdGhlIGFycmF5XG4gICAgICAgIC8vdHJ5IFsnZW4tYXUnLCAnZW4tZ2InXSBhcyAnZW4tYXUnLCAnZW4tZ2InLCAnZW4nLCBhcyBpbiBtb3ZlIHRocm91Z2ggdGhlIGxpc3QgdHJ5aW5nIGVhY2hcbiAgICAgICAgLy9zdWJzdHJpbmcgZnJvbSBtb3N0IHNwZWNpZmljIHRvIGxlYXN0LCBidXQgbW92ZSB0byB0aGUgbmV4dCBhcnJheSBpdGVtIGlmIGl0J3MgYSBtb3JlIHNwZWNpZmljIHZhcmlhbnQgdGhhbiB0aGUgY3VycmVudCByb290XG4gICAgICAgIHdoaWxlIChpIDwga2V5Lmxlbmd0aCkge1xuICAgICAgICAgICAgc3BsaXQgPSBub3JtYWxpemVMYW5ndWFnZShrZXlbaV0pLnNwbGl0KCctJyk7XG4gICAgICAgICAgICBqID0gc3BsaXQubGVuZ3RoO1xuICAgICAgICAgICAgbmV4dCA9IG5vcm1hbGl6ZUxhbmd1YWdlKGtleVtpICsgMV0pO1xuICAgICAgICAgICAgbmV4dCA9IG5leHQgPyBuZXh0LnNwbGl0KCctJykgOiBudWxsO1xuICAgICAgICAgICAgd2hpbGUgKGogPiAwKSB7XG4gICAgICAgICAgICAgICAgbGFuZyA9IGdldChzcGxpdC5zbGljZSgwLCBqKS5qb2luKCctJykpO1xuICAgICAgICAgICAgICAgIGlmIChsYW5nKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBsYW5nO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAobmV4dCAmJiBuZXh0Lmxlbmd0aCA+PSBqICYmIGNvbXBhcmVBcnJheXMoc3BsaXQsIG5leHQsIHRydWUpID49IGogLSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vdGhlIG5leHQgYXJyYXkgaXRlbSBpcyBiZXR0ZXIgdGhhbiBhIHNoYWxsb3dlciBzdWJzdHJpbmcgb2YgdGhpcyBvbmVcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGotLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGkrKztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbW9tZW50LmZuLl9sYW5nO1xuICAgIH1cblxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgICAgRm9ybWF0dGluZ1xuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuXG4gICAgZnVuY3Rpb24gcmVtb3ZlRm9ybWF0dGluZ1Rva2VucyhpbnB1dCkge1xuICAgICAgICBpZiAoaW5wdXQubWF0Y2goL1xcW1tcXHNcXFNdLykpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dC5yZXBsYWNlKC9eXFxbfFxcXSQvZywgXCJcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGlucHV0LnJlcGxhY2UoL1xcXFwvZywgXCJcIik7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZUZvcm1hdEZ1bmN0aW9uKGZvcm1hdCkge1xuICAgICAgICB2YXIgYXJyYXkgPSBmb3JtYXQubWF0Y2goZm9ybWF0dGluZ1Rva2VucyksIGksIGxlbmd0aDtcblxuICAgICAgICBmb3IgKGkgPSAwLCBsZW5ndGggPSBhcnJheS5sZW5ndGg7IGkgPCBsZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgaWYgKGZvcm1hdFRva2VuRnVuY3Rpb25zW2FycmF5W2ldXSkge1xuICAgICAgICAgICAgICAgIGFycmF5W2ldID0gZm9ybWF0VG9rZW5GdW5jdGlvbnNbYXJyYXlbaV1dO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBhcnJheVtpXSA9IHJlbW92ZUZvcm1hdHRpbmdUb2tlbnMoYXJyYXlbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChtb20pIHtcbiAgICAgICAgICAgIHZhciBvdXRwdXQgPSBcIlwiO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0ICs9IGFycmF5W2ldIGluc3RhbmNlb2YgRnVuY3Rpb24gPyBhcnJheVtpXS5jYWxsKG1vbSwgZm9ybWF0KSA6IGFycmF5W2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG91dHB1dDtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBmb3JtYXQgZGF0ZSB1c2luZyBuYXRpdmUgZGF0ZSBvYmplY3RcbiAgICBmdW5jdGlvbiBmb3JtYXRNb21lbnQobSwgZm9ybWF0KSB7XG5cbiAgICAgICAgaWYgKCFtLmlzVmFsaWQoKSkge1xuICAgICAgICAgICAgcmV0dXJuIG0ubGFuZygpLmludmFsaWREYXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBmb3JtYXQgPSBleHBhbmRGb3JtYXQoZm9ybWF0LCBtLmxhbmcoKSk7XG5cbiAgICAgICAgaWYgKCFmb3JtYXRGdW5jdGlvbnNbZm9ybWF0XSkge1xuICAgICAgICAgICAgZm9ybWF0RnVuY3Rpb25zW2Zvcm1hdF0gPSBtYWtlRm9ybWF0RnVuY3Rpb24oZm9ybWF0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmb3JtYXRGdW5jdGlvbnNbZm9ybWF0XShtKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBleHBhbmRGb3JtYXQoZm9ybWF0LCBsYW5nKSB7XG4gICAgICAgIHZhciBpID0gNTtcblxuICAgICAgICBmdW5jdGlvbiByZXBsYWNlTG9uZ0RhdGVGb3JtYXRUb2tlbnMoaW5wdXQpIHtcbiAgICAgICAgICAgIHJldHVybiBsYW5nLmxvbmdEYXRlRm9ybWF0KGlucHV0KSB8fCBpbnB1dDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy5sYXN0SW5kZXggPSAwO1xuICAgICAgICB3aGlsZSAoaSA+PSAwICYmIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy50ZXN0KGZvcm1hdCkpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9IGZvcm1hdC5yZXBsYWNlKGxvY2FsRm9ybWF0dGluZ1Rva2VucywgcmVwbGFjZUxvbmdEYXRlRm9ybWF0VG9rZW5zKTtcbiAgICAgICAgICAgIGxvY2FsRm9ybWF0dGluZ1Rva2Vucy5sYXN0SW5kZXggPSAwO1xuICAgICAgICAgICAgaSAtPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZvcm1hdDtcbiAgICB9XG5cblxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgICAgUGFyc2luZ1xuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuXG4gICAgLy8gZ2V0IHRoZSByZWdleCB0byBmaW5kIHRoZSBuZXh0IHRva2VuXG4gICAgZnVuY3Rpb24gZ2V0UGFyc2VSZWdleEZvclRva2VuKHRva2VuLCBjb25maWcpIHtcbiAgICAgICAgdmFyIGE7XG4gICAgICAgIHN3aXRjaCAodG9rZW4pIHtcbiAgICAgICAgY2FzZSAnRERERCc6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VUb2tlblRocmVlRGlnaXRzO1xuICAgICAgICBjYXNlICdZWVlZJzpcbiAgICAgICAgY2FzZSAnR0dHRyc6XG4gICAgICAgIGNhc2UgJ2dnZ2cnOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlVG9rZW5Gb3VyRGlnaXRzO1xuICAgICAgICBjYXNlICdZWVlZWSc6XG4gICAgICAgIGNhc2UgJ0dHR0dHJzpcbiAgICAgICAgY2FzZSAnZ2dnZ2cnOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlVG9rZW5TaXhEaWdpdHM7XG4gICAgICAgIGNhc2UgJ1MnOlxuICAgICAgICBjYXNlICdTUyc6XG4gICAgICAgIGNhc2UgJ1NTUyc6XG4gICAgICAgIGNhc2UgJ0RERCc6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VUb2tlbk9uZVRvVGhyZWVEaWdpdHM7XG4gICAgICAgIGNhc2UgJ01NTSc6XG4gICAgICAgIGNhc2UgJ01NTU0nOlxuICAgICAgICBjYXNlICdkZCc6XG4gICAgICAgIGNhc2UgJ2RkZCc6XG4gICAgICAgIGNhc2UgJ2RkZGQnOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlVG9rZW5Xb3JkO1xuICAgICAgICBjYXNlICdhJzpcbiAgICAgICAgY2FzZSAnQSc6XG4gICAgICAgICAgICByZXR1cm4gZ2V0TGFuZ0RlZmluaXRpb24oY29uZmlnLl9sKS5fbWVyaWRpZW1QYXJzZTtcbiAgICAgICAgY2FzZSAnWCc6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VUb2tlblRpbWVzdGFtcE1zO1xuICAgICAgICBjYXNlICdaJzpcbiAgICAgICAgY2FzZSAnWlonOlxuICAgICAgICAgICAgcmV0dXJuIHBhcnNlVG9rZW5UaW1lem9uZTtcbiAgICAgICAgY2FzZSAnVCc6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VUb2tlblQ7XG4gICAgICAgIGNhc2UgJ01NJzpcbiAgICAgICAgY2FzZSAnREQnOlxuICAgICAgICBjYXNlICdZWSc6XG4gICAgICAgIGNhc2UgJ0dHJzpcbiAgICAgICAgY2FzZSAnZ2cnOlxuICAgICAgICBjYXNlICdISCc6XG4gICAgICAgIGNhc2UgJ2hoJzpcbiAgICAgICAgY2FzZSAnbW0nOlxuICAgICAgICBjYXNlICdzcyc6XG4gICAgICAgIGNhc2UgJ00nOlxuICAgICAgICBjYXNlICdEJzpcbiAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgIGNhc2UgJ0gnOlxuICAgICAgICBjYXNlICdoJzpcbiAgICAgICAgY2FzZSAnbSc6XG4gICAgICAgIGNhc2UgJ3MnOlxuICAgICAgICBjYXNlICd3JzpcbiAgICAgICAgY2FzZSAnd3cnOlxuICAgICAgICBjYXNlICdXJzpcbiAgICAgICAgY2FzZSAnV1cnOlxuICAgICAgICBjYXNlICdlJzpcbiAgICAgICAgY2FzZSAnRSc6XG4gICAgICAgICAgICByZXR1cm4gcGFyc2VUb2tlbk9uZU9yVHdvRGlnaXRzO1xuICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgIGEgPSBuZXcgUmVnRXhwKHJlZ2V4cEVzY2FwZSh1bmVzY2FwZUZvcm1hdCh0b2tlbi5yZXBsYWNlKCdcXFxcJywgJycpKSwgXCJpXCIpKTtcbiAgICAgICAgICAgIHJldHVybiBhO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdGltZXpvbmVNaW51dGVzRnJvbVN0cmluZyhzdHJpbmcpIHtcbiAgICAgICAgdmFyIHR6Y2h1bmsgPSAocGFyc2VUb2tlblRpbWV6b25lLmV4ZWMoc3RyaW5nKSB8fCBbXSlbMF0sXG4gICAgICAgICAgICBwYXJ0cyA9ICh0emNodW5rICsgJycpLm1hdGNoKHBhcnNlVGltZXpvbmVDaHVua2VyKSB8fCBbJy0nLCAwLCAwXSxcbiAgICAgICAgICAgIG1pbnV0ZXMgPSArKHBhcnRzWzFdICogNjApICsgdG9JbnQocGFydHNbMl0pO1xuXG4gICAgICAgIHJldHVybiBwYXJ0c1swXSA9PT0gJysnID8gLW1pbnV0ZXMgOiBtaW51dGVzO1xuICAgIH1cblxuICAgIC8vIGZ1bmN0aW9uIHRvIGNvbnZlcnQgc3RyaW5nIGlucHV0IHRvIGRhdGVcbiAgICBmdW5jdGlvbiBhZGRUaW1lVG9BcnJheUZyb21Ub2tlbih0b2tlbiwgaW5wdXQsIGNvbmZpZykge1xuICAgICAgICB2YXIgYSwgZGF0ZVBhcnRBcnJheSA9IGNvbmZpZy5fYTtcblxuICAgICAgICBzd2l0Y2ggKHRva2VuKSB7XG4gICAgICAgIC8vIE1PTlRIXG4gICAgICAgIGNhc2UgJ00nIDogLy8gZmFsbCB0aHJvdWdoIHRvIE1NXG4gICAgICAgIGNhc2UgJ01NJyA6XG4gICAgICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRhdGVQYXJ0QXJyYXlbTU9OVEhdID0gdG9JbnQoaW5wdXQpIC0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdNTU0nIDogLy8gZmFsbCB0aHJvdWdoIHRvIE1NTU1cbiAgICAgICAgY2FzZSAnTU1NTScgOlxuICAgICAgICAgICAgYSA9IGdldExhbmdEZWZpbml0aW9uKGNvbmZpZy5fbCkubW9udGhzUGFyc2UoaW5wdXQpO1xuICAgICAgICAgICAgLy8gaWYgd2UgZGlkbid0IGZpbmQgYSBtb250aCBuYW1lLCBtYXJrIHRoZSBkYXRlIGFzIGludmFsaWQuXG4gICAgICAgICAgICBpZiAoYSAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtNT05USF0gPSBhO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25maWcuX3BmLmludmFsaWRNb250aCA9IGlucHV0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vIERBWSBPRiBNT05USFxuICAgICAgICBjYXNlICdEJyA6IC8vIGZhbGwgdGhyb3VnaCB0byBERFxuICAgICAgICBjYXNlICdERCcgOlxuICAgICAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBkYXRlUGFydEFycmF5W0RBVEVdID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vIERBWSBPRiBZRUFSXG4gICAgICAgIGNhc2UgJ0RERCcgOiAvLyBmYWxsIHRocm91Z2ggdG8gRERERFxuICAgICAgICBjYXNlICdEREREJyA6XG4gICAgICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5fZGF5T2ZZZWFyID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgLy8gWUVBUlxuICAgICAgICBjYXNlICdZWScgOlxuICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtZRUFSXSA9IHRvSW50KGlucHV0KSArICh0b0ludChpbnB1dCkgPiA2OCA/IDE5MDAgOiAyMDAwKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdZWVlZJyA6XG4gICAgICAgIGNhc2UgJ1lZWVlZJyA6XG4gICAgICAgICAgICBkYXRlUGFydEFycmF5W1lFQVJdID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vIEFNIC8gUE1cbiAgICAgICAgY2FzZSAnYScgOiAvLyBmYWxsIHRocm91Z2ggdG8gQVxuICAgICAgICBjYXNlICdBJyA6XG4gICAgICAgICAgICBjb25maWcuX2lzUG0gPSBnZXRMYW5nRGVmaW5pdGlvbihjb25maWcuX2wpLmlzUE0oaW5wdXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vIDI0IEhPVVJcbiAgICAgICAgY2FzZSAnSCcgOiAvLyBmYWxsIHRocm91Z2ggdG8gaGhcbiAgICAgICAgY2FzZSAnSEgnIDogLy8gZmFsbCB0aHJvdWdoIHRvIGhoXG4gICAgICAgIGNhc2UgJ2gnIDogLy8gZmFsbCB0aHJvdWdoIHRvIGhoXG4gICAgICAgIGNhc2UgJ2hoJyA6XG4gICAgICAgICAgICBkYXRlUGFydEFycmF5W0hPVVJdID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vIE1JTlVURVxuICAgICAgICBjYXNlICdtJyA6IC8vIGZhbGwgdGhyb3VnaCB0byBtbVxuICAgICAgICBjYXNlICdtbScgOlxuICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtNSU5VVEVdID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vIFNFQ09ORFxuICAgICAgICBjYXNlICdzJyA6IC8vIGZhbGwgdGhyb3VnaCB0byBzc1xuICAgICAgICBjYXNlICdzcycgOlxuICAgICAgICAgICAgZGF0ZVBhcnRBcnJheVtTRUNPTkRdID0gdG9JbnQoaW5wdXQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIC8vIE1JTExJU0VDT05EXG4gICAgICAgIGNhc2UgJ1MnIDpcbiAgICAgICAgY2FzZSAnU1MnIDpcbiAgICAgICAgY2FzZSAnU1NTJyA6XG4gICAgICAgICAgICBkYXRlUGFydEFycmF5W01JTExJU0VDT05EXSA9IHRvSW50KCgnMC4nICsgaW5wdXQpICogMTAwMCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgLy8gVU5JWCBUSU1FU1RBTVAgV0lUSCBNU1xuICAgICAgICBjYXNlICdYJzpcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKHBhcnNlRmxvYXQoaW5wdXQpICogMTAwMCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgLy8gVElNRVpPTkVcbiAgICAgICAgY2FzZSAnWicgOiAvLyBmYWxsIHRocm91Z2ggdG8gWlpcbiAgICAgICAgY2FzZSAnWlonIDpcbiAgICAgICAgICAgIGNvbmZpZy5fdXNlVVRDID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbmZpZy5fdHptID0gdGltZXpvbmVNaW51dGVzRnJvbVN0cmluZyhpbnB1dCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAndyc6XG4gICAgICAgIGNhc2UgJ3d3JzpcbiAgICAgICAgY2FzZSAnVyc6XG4gICAgICAgIGNhc2UgJ1dXJzpcbiAgICAgICAgY2FzZSAnZCc6XG4gICAgICAgIGNhc2UgJ2RkJzpcbiAgICAgICAgY2FzZSAnZGRkJzpcbiAgICAgICAgY2FzZSAnZGRkZCc6XG4gICAgICAgIGNhc2UgJ2UnOlxuICAgICAgICBjYXNlICdFJzpcbiAgICAgICAgICAgIHRva2VuID0gdG9rZW4uc3Vic3RyKDAsIDEpO1xuICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICBjYXNlICdnZyc6XG4gICAgICAgIGNhc2UgJ2dnZ2cnOlxuICAgICAgICBjYXNlICdHRyc6XG4gICAgICAgIGNhc2UgJ0dHR0cnOlxuICAgICAgICBjYXNlICdHR0dHRyc6XG4gICAgICAgICAgICB0b2tlbiA9IHRva2VuLnN1YnN0cigwLCAyKTtcbiAgICAgICAgICAgIGlmIChpbnB1dCkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5fdyA9IGNvbmZpZy5fdyB8fCB7fTtcbiAgICAgICAgICAgICAgICBjb25maWcuX3dbdG9rZW5dID0gaW5wdXQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIGNvbnZlcnQgYW4gYXJyYXkgdG8gYSBkYXRlLlxuICAgIC8vIHRoZSBhcnJheSBzaG91bGQgbWlycm9yIHRoZSBwYXJhbWV0ZXJzIGJlbG93XG4gICAgLy8gbm90ZTogYWxsIHZhbHVlcyBwYXN0IHRoZSB5ZWFyIGFyZSBvcHRpb25hbCBhbmQgd2lsbCBkZWZhdWx0IHRvIHRoZSBsb3dlc3QgcG9zc2libGUgdmFsdWUuXG4gICAgLy8gW3llYXIsIG1vbnRoLCBkYXkgLCBob3VyLCBtaW51dGUsIHNlY29uZCwgbWlsbGlzZWNvbmRdXG4gICAgZnVuY3Rpb24gZGF0ZUZyb21Db25maWcoY29uZmlnKSB7XG4gICAgICAgIHZhciBpLCBkYXRlLCBpbnB1dCA9IFtdLCBjdXJyZW50RGF0ZSxcbiAgICAgICAgICAgIHllYXJUb1VzZSwgZml4WWVhciwgdywgdGVtcCwgbGFuZywgd2Vla2RheSwgd2VlaztcblxuICAgICAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjdXJyZW50RGF0ZSA9IGN1cnJlbnREYXRlQXJyYXkoY29uZmlnKTtcblxuICAgICAgICAvL2NvbXB1dGUgZGF5IG9mIHRoZSB5ZWFyIGZyb20gd2Vla3MgYW5kIHdlZWtkYXlzXG4gICAgICAgIGlmIChjb25maWcuX3cgJiYgY29uZmlnLl9hW0RBVEVdID09IG51bGwgJiYgY29uZmlnLl9hW01PTlRIXSA9PSBudWxsKSB7XG4gICAgICAgICAgICBmaXhZZWFyID0gZnVuY3Rpb24gKHZhbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2YWwgP1xuICAgICAgICAgICAgICAgICAgKHZhbC5sZW5ndGggPCAzID8gKHBhcnNlSW50KHZhbCwgMTApID4gNjggPyAnMTknICsgdmFsIDogJzIwJyArIHZhbCkgOiB2YWwpIDpcbiAgICAgICAgICAgICAgICAgIChjb25maWcuX2FbWUVBUl0gPT0gbnVsbCA/IG1vbWVudCgpLndlZWtZZWFyKCkgOiBjb25maWcuX2FbWUVBUl0pO1xuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgdyA9IGNvbmZpZy5fdztcbiAgICAgICAgICAgIGlmICh3LkdHICE9IG51bGwgfHwgdy5XICE9IG51bGwgfHwgdy5FICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICB0ZW1wID0gZGF5T2ZZZWFyRnJvbVdlZWtzKGZpeFllYXIody5HRyksIHcuVyB8fCAxLCB3LkUsIDQsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgbGFuZyA9IGdldExhbmdEZWZpbml0aW9uKGNvbmZpZy5fbCk7XG4gICAgICAgICAgICAgICAgd2Vla2RheSA9IHcuZCAhPSBudWxsID8gIHBhcnNlV2Vla2RheSh3LmQsIGxhbmcpIDpcbiAgICAgICAgICAgICAgICAgICh3LmUgIT0gbnVsbCA/ICBwYXJzZUludCh3LmUsIDEwKSArIGxhbmcuX3dlZWsuZG93IDogMCk7XG5cbiAgICAgICAgICAgICAgICB3ZWVrID0gcGFyc2VJbnQody53LCAxMCkgfHwgMTtcblxuICAgICAgICAgICAgICAgIC8vaWYgd2UncmUgcGFyc2luZyAnZCcsIHRoZW4gdGhlIGxvdyBkYXkgbnVtYmVycyBtYXkgYmUgbmV4dCB3ZWVrXG4gICAgICAgICAgICAgICAgaWYgKHcuZCAhPSBudWxsICYmIHdlZWtkYXkgPCBsYW5nLl93ZWVrLmRvdykge1xuICAgICAgICAgICAgICAgICAgICB3ZWVrKys7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGVtcCA9IGRheU9mWWVhckZyb21XZWVrcyhmaXhZZWFyKHcuZ2cpLCB3ZWVrLCB3ZWVrZGF5LCBsYW5nLl93ZWVrLmRveSwgbGFuZy5fd2Vlay5kb3cpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25maWcuX2FbWUVBUl0gPSB0ZW1wLnllYXI7XG4gICAgICAgICAgICBjb25maWcuX2RheU9mWWVhciA9IHRlbXAuZGF5T2ZZZWFyO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9pZiB0aGUgZGF5IG9mIHRoZSB5ZWFyIGlzIHNldCwgZmlndXJlIG91dCB3aGF0IGl0IGlzXG4gICAgICAgIGlmIChjb25maWcuX2RheU9mWWVhcikge1xuICAgICAgICAgICAgeWVhclRvVXNlID0gY29uZmlnLl9hW1lFQVJdID09IG51bGwgPyBjdXJyZW50RGF0ZVtZRUFSXSA6IGNvbmZpZy5fYVtZRUFSXTtcblxuICAgICAgICAgICAgaWYgKGNvbmZpZy5fZGF5T2ZZZWFyID4gZGF5c0luWWVhcih5ZWFyVG9Vc2UpKSB7XG4gICAgICAgICAgICAgICAgY29uZmlnLl9wZi5fb3ZlcmZsb3dEYXlPZlllYXIgPSB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBkYXRlID0gbWFrZVVUQ0RhdGUoeWVhclRvVXNlLCAwLCBjb25maWcuX2RheU9mWWVhcik7XG4gICAgICAgICAgICBjb25maWcuX2FbTU9OVEhdID0gZGF0ZS5nZXRVVENNb250aCgpO1xuICAgICAgICAgICAgY29uZmlnLl9hW0RBVEVdID0gZGF0ZS5nZXRVVENEYXRlKCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWZhdWx0IHRvIGN1cnJlbnQgZGF0ZS5cbiAgICAgICAgLy8gKiBpZiBubyB5ZWFyLCBtb250aCwgZGF5IG9mIG1vbnRoIGFyZSBnaXZlbiwgZGVmYXVsdCB0byB0b2RheVxuICAgICAgICAvLyAqIGlmIGRheSBvZiBtb250aCBpcyBnaXZlbiwgZGVmYXVsdCBtb250aCBhbmQgeWVhclxuICAgICAgICAvLyAqIGlmIG1vbnRoIGlzIGdpdmVuLCBkZWZhdWx0IG9ubHkgeWVhclxuICAgICAgICAvLyAqIGlmIHllYXIgaXMgZ2l2ZW4sIGRvbid0IGRlZmF1bHQgYW55dGhpbmdcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDMgJiYgY29uZmlnLl9hW2ldID09IG51bGw7ICsraSkge1xuICAgICAgICAgICAgY29uZmlnLl9hW2ldID0gaW5wdXRbaV0gPSBjdXJyZW50RGF0ZVtpXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFplcm8gb3V0IHdoYXRldmVyIHdhcyBub3QgZGVmYXVsdGVkLCBpbmNsdWRpbmcgdGltZVxuICAgICAgICBmb3IgKDsgaSA8IDc7IGkrKykge1xuICAgICAgICAgICAgY29uZmlnLl9hW2ldID0gaW5wdXRbaV0gPSAoY29uZmlnLl9hW2ldID09IG51bGwpID8gKGkgPT09IDIgPyAxIDogMCkgOiBjb25maWcuX2FbaV07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBhZGQgdGhlIG9mZnNldHMgdG8gdGhlIHRpbWUgdG8gYmUgcGFyc2VkIHNvIHRoYXQgd2UgY2FuIGhhdmUgYSBjbGVhbiBhcnJheSBmb3IgY2hlY2tpbmcgaXNWYWxpZFxuICAgICAgICBpbnB1dFtIT1VSXSArPSB0b0ludCgoY29uZmlnLl90em0gfHwgMCkgLyA2MCk7XG4gICAgICAgIGlucHV0W01JTlVURV0gKz0gdG9JbnQoKGNvbmZpZy5fdHptIHx8IDApICUgNjApO1xuXG4gICAgICAgIGNvbmZpZy5fZCA9IChjb25maWcuX3VzZVVUQyA/IG1ha2VVVENEYXRlIDogbWFrZURhdGUpLmFwcGx5KG51bGwsIGlucHV0KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBkYXRlRnJvbU9iamVjdChjb25maWcpIHtcbiAgICAgICAgdmFyIG5vcm1hbGl6ZWRJbnB1dDtcblxuICAgICAgICBpZiAoY29uZmlnLl9kKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBub3JtYWxpemVkSW5wdXQgPSBub3JtYWxpemVPYmplY3RVbml0cyhjb25maWcuX2kpO1xuICAgICAgICBjb25maWcuX2EgPSBbXG4gICAgICAgICAgICBub3JtYWxpemVkSW5wdXQueWVhcixcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRJbnB1dC5tb250aCxcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRJbnB1dC5kYXksXG4gICAgICAgICAgICBub3JtYWxpemVkSW5wdXQuaG91cixcbiAgICAgICAgICAgIG5vcm1hbGl6ZWRJbnB1dC5taW51dGUsXG4gICAgICAgICAgICBub3JtYWxpemVkSW5wdXQuc2Vjb25kLFxuICAgICAgICAgICAgbm9ybWFsaXplZElucHV0Lm1pbGxpc2Vjb25kXG4gICAgICAgIF07XG5cbiAgICAgICAgZGF0ZUZyb21Db25maWcoY29uZmlnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjdXJyZW50RGF0ZUFycmF5KGNvbmZpZykge1xuICAgICAgICB2YXIgbm93ID0gbmV3IERhdGUoKTtcbiAgICAgICAgaWYgKGNvbmZpZy5fdXNlVVRDKSB7XG4gICAgICAgICAgICByZXR1cm4gW1xuICAgICAgICAgICAgICAgIG5vdy5nZXRVVENGdWxsWWVhcigpLFxuICAgICAgICAgICAgICAgIG5vdy5nZXRVVENNb250aCgpLFxuICAgICAgICAgICAgICAgIG5vdy5nZXRVVENEYXRlKClcbiAgICAgICAgICAgIF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gW25vdy5nZXRGdWxsWWVhcigpLCBub3cuZ2V0TW9udGgoKSwgbm93LmdldERhdGUoKV07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBkYXRlIGZyb20gc3RyaW5nIGFuZCBmb3JtYXQgc3RyaW5nXG4gICAgZnVuY3Rpb24gbWFrZURhdGVGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZykge1xuXG4gICAgICAgIGNvbmZpZy5fYSA9IFtdO1xuICAgICAgICBjb25maWcuX3BmLmVtcHR5ID0gdHJ1ZTtcblxuICAgICAgICAvLyBUaGlzIGFycmF5IGlzIHVzZWQgdG8gbWFrZSBhIERhdGUsIGVpdGhlciB3aXRoIGBuZXcgRGF0ZWAgb3IgYERhdGUuVVRDYFxuICAgICAgICB2YXIgbGFuZyA9IGdldExhbmdEZWZpbml0aW9uKGNvbmZpZy5fbCksXG4gICAgICAgICAgICBzdHJpbmcgPSAnJyArIGNvbmZpZy5faSxcbiAgICAgICAgICAgIGksIHBhcnNlZElucHV0LCB0b2tlbnMsIHRva2VuLCBza2lwcGVkLFxuICAgICAgICAgICAgc3RyaW5nTGVuZ3RoID0gc3RyaW5nLmxlbmd0aCxcbiAgICAgICAgICAgIHRvdGFsUGFyc2VkSW5wdXRMZW5ndGggPSAwO1xuXG4gICAgICAgIHRva2VucyA9IGV4cGFuZEZvcm1hdChjb25maWcuX2YsIGxhbmcpLm1hdGNoKGZvcm1hdHRpbmdUb2tlbnMpIHx8IFtdO1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHRva2VuID0gdG9rZW5zW2ldO1xuICAgICAgICAgICAgcGFyc2VkSW5wdXQgPSAoZ2V0UGFyc2VSZWdleEZvclRva2VuKHRva2VuLCBjb25maWcpLmV4ZWMoc3RyaW5nKSB8fCBbXSlbMF07XG4gICAgICAgICAgICBpZiAocGFyc2VkSW5wdXQpIHtcbiAgICAgICAgICAgICAgICBza2lwcGVkID0gc3RyaW5nLnN1YnN0cigwLCBzdHJpbmcuaW5kZXhPZihwYXJzZWRJbnB1dCkpO1xuICAgICAgICAgICAgICAgIGlmIChza2lwcGVkLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLl9wZi51bnVzZWRJbnB1dC5wdXNoKHNraXBwZWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBzdHJpbmcgPSBzdHJpbmcuc2xpY2Uoc3RyaW5nLmluZGV4T2YocGFyc2VkSW5wdXQpICsgcGFyc2VkSW5wdXQubGVuZ3RoKTtcbiAgICAgICAgICAgICAgICB0b3RhbFBhcnNlZElucHV0TGVuZ3RoICs9IHBhcnNlZElucHV0Lmxlbmd0aDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIGRvbid0IHBhcnNlIGlmIGl0J3Mgbm90IGEga25vd24gdG9rZW5cbiAgICAgICAgICAgIGlmIChmb3JtYXRUb2tlbkZ1bmN0aW9uc1t0b2tlbl0pIHtcbiAgICAgICAgICAgICAgICBpZiAocGFyc2VkSW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLl9wZi5lbXB0eSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlnLl9wZi51bnVzZWRUb2tlbnMucHVzaCh0b2tlbik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGFkZFRpbWVUb0FycmF5RnJvbVRva2VuKHRva2VuLCBwYXJzZWRJbnB1dCwgY29uZmlnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKGNvbmZpZy5fc3RyaWN0ICYmICFwYXJzZWRJbnB1dCkge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5fcGYudW51c2VkVG9rZW5zLnB1c2godG9rZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gYWRkIHJlbWFpbmluZyB1bnBhcnNlZCBpbnB1dCBsZW5ndGggdG8gdGhlIHN0cmluZ1xuICAgICAgICBjb25maWcuX3BmLmNoYXJzTGVmdE92ZXIgPSBzdHJpbmdMZW5ndGggLSB0b3RhbFBhcnNlZElucHV0TGVuZ3RoO1xuICAgICAgICBpZiAoc3RyaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIGNvbmZpZy5fcGYudW51c2VkSW5wdXQucHVzaChzdHJpbmcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gaGFuZGxlIGFtIHBtXG4gICAgICAgIGlmIChjb25maWcuX2lzUG0gJiYgY29uZmlnLl9hW0hPVVJdIDwgMTIpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fYVtIT1VSXSArPSAxMjtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiBpcyAxMiBhbSwgY2hhbmdlIGhvdXJzIHRvIDBcbiAgICAgICAgaWYgKGNvbmZpZy5faXNQbSA9PT0gZmFsc2UgJiYgY29uZmlnLl9hW0hPVVJdID09PSAxMikge1xuICAgICAgICAgICAgY29uZmlnLl9hW0hPVVJdID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGRhdGVGcm9tQ29uZmlnKGNvbmZpZyk7XG4gICAgICAgIGNoZWNrT3ZlcmZsb3coY29uZmlnKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB1bmVzY2FwZUZvcm1hdChzKSB7XG4gICAgICAgIHJldHVybiBzLnJlcGxhY2UoL1xcXFwoXFxbKXxcXFxcKFxcXSl8XFxbKFteXFxdXFxbXSopXFxdfFxcXFwoLikvZywgZnVuY3Rpb24gKG1hdGNoZWQsIHAxLCBwMiwgcDMsIHA0KSB7XG4gICAgICAgICAgICByZXR1cm4gcDEgfHwgcDIgfHwgcDMgfHwgcDQ7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8vIENvZGUgZnJvbSBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzM1NjE0OTMvaXMtdGhlcmUtYS1yZWdleHAtZXNjYXBlLWZ1bmN0aW9uLWluLWphdmFzY3JpcHRcbiAgICBmdW5jdGlvbiByZWdleHBFc2NhcGUocykge1xuICAgICAgICByZXR1cm4gcy5yZXBsYWNlKC9bLVxcL1xcXFxeJCorPy4oKXxbXFxde31dL2csICdcXFxcJCYnKTtcbiAgICB9XG5cbiAgICAvLyBkYXRlIGZyb20gc3RyaW5nIGFuZCBhcnJheSBvZiBmb3JtYXQgc3RyaW5nc1xuICAgIGZ1bmN0aW9uIG1ha2VEYXRlRnJvbVN0cmluZ0FuZEFycmF5KGNvbmZpZykge1xuICAgICAgICB2YXIgdGVtcENvbmZpZyxcbiAgICAgICAgICAgIGJlc3RNb21lbnQsXG5cbiAgICAgICAgICAgIHNjb3JlVG9CZWF0LFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgIGN1cnJlbnRTY29yZTtcblxuICAgICAgICBpZiAoY29uZmlnLl9mLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgY29uZmlnLl9wZi5pbnZhbGlkRm9ybWF0ID0gdHJ1ZTtcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKE5hTik7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgY29uZmlnLl9mLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjdXJyZW50U2NvcmUgPSAwO1xuICAgICAgICAgICAgdGVtcENvbmZpZyA9IGV4dGVuZCh7fSwgY29uZmlnKTtcbiAgICAgICAgICAgIGluaXRpYWxpemVQYXJzaW5nRmxhZ3ModGVtcENvbmZpZyk7XG4gICAgICAgICAgICB0ZW1wQ29uZmlnLl9mID0gY29uZmlnLl9mW2ldO1xuICAgICAgICAgICAgbWFrZURhdGVGcm9tU3RyaW5nQW5kRm9ybWF0KHRlbXBDb25maWcpO1xuXG4gICAgICAgICAgICBpZiAoIWlzVmFsaWQodGVtcENvbmZpZykpIHtcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgYW55IGlucHV0IHRoYXQgd2FzIG5vdCBwYXJzZWQgYWRkIGEgcGVuYWx0eSBmb3IgdGhhdCBmb3JtYXRcbiAgICAgICAgICAgIGN1cnJlbnRTY29yZSArPSB0ZW1wQ29uZmlnLl9wZi5jaGFyc0xlZnRPdmVyO1xuXG4gICAgICAgICAgICAvL29yIHRva2Vuc1xuICAgICAgICAgICAgY3VycmVudFNjb3JlICs9IHRlbXBDb25maWcuX3BmLnVudXNlZFRva2Vucy5sZW5ndGggKiAxMDtcblxuICAgICAgICAgICAgdGVtcENvbmZpZy5fcGYuc2NvcmUgPSBjdXJyZW50U2NvcmU7XG5cbiAgICAgICAgICAgIGlmIChzY29yZVRvQmVhdCA9PSBudWxsIHx8IGN1cnJlbnRTY29yZSA8IHNjb3JlVG9CZWF0KSB7XG4gICAgICAgICAgICAgICAgc2NvcmVUb0JlYXQgPSBjdXJyZW50U2NvcmU7XG4gICAgICAgICAgICAgICAgYmVzdE1vbWVudCA9IHRlbXBDb25maWc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBleHRlbmQoY29uZmlnLCBiZXN0TW9tZW50IHx8IHRlbXBDb25maWcpO1xuICAgIH1cblxuICAgIC8vIGRhdGUgZnJvbSBpc28gZm9ybWF0XG4gICAgZnVuY3Rpb24gbWFrZURhdGVGcm9tU3RyaW5nKGNvbmZpZykge1xuICAgICAgICB2YXIgaSxcbiAgICAgICAgICAgIHN0cmluZyA9IGNvbmZpZy5faSxcbiAgICAgICAgICAgIG1hdGNoID0gaXNvUmVnZXguZXhlYyhzdHJpbmcpO1xuXG4gICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgZm9yIChpID0gNDsgaSA+IDA7IGktLSkge1xuICAgICAgICAgICAgICAgIGlmIChtYXRjaFtpXSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBtYXRjaFs1XSBzaG91bGQgYmUgXCJUXCIgb3IgdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5fZiA9IGlzb0RhdGVzW2kgLSAxXSArIChtYXRjaFs2XSB8fCBcIiBcIik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNvVGltZXNbaV1bMV0uZXhlYyhzdHJpbmcpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbmZpZy5fZiArPSBpc29UaW1lc1tpXVswXTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHBhcnNlVG9rZW5UaW1lem9uZS5leGVjKHN0cmluZykpIHtcbiAgICAgICAgICAgICAgICBjb25maWcuX2YgKz0gXCIgWlwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbWFrZURhdGVGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25maWcuX2QgPSBuZXcgRGF0ZShzdHJpbmcpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gbWFrZURhdGVGcm9tSW5wdXQoY29uZmlnKSB7XG4gICAgICAgIHZhciBpbnB1dCA9IGNvbmZpZy5faSxcbiAgICAgICAgICAgIG1hdGNoZWQgPSBhc3BOZXRKc29uUmVnZXguZXhlYyhpbnB1dCk7XG5cbiAgICAgICAgaWYgKGlucHV0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKCk7XG4gICAgICAgIH0gZWxzZSBpZiAobWF0Y2hlZCkge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoK21hdGNoZWRbMV0pO1xuICAgICAgICB9IGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIG1ha2VEYXRlRnJvbVN0cmluZyhjb25maWcpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJyYXkoaW5wdXQpKSB7XG4gICAgICAgICAgICBjb25maWcuX2EgPSBpbnB1dC5zbGljZSgwKTtcbiAgICAgICAgICAgIGRhdGVGcm9tQ29uZmlnKGNvbmZpZyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNEYXRlKGlucHV0KSkge1xuICAgICAgICAgICAgY29uZmlnLl9kID0gbmV3IERhdGUoK2lucHV0KTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YoaW5wdXQpID09PSAnb2JqZWN0Jykge1xuICAgICAgICAgICAgZGF0ZUZyb21PYmplY3QoY29uZmlnKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKGlucHV0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIG1ha2VEYXRlKHksIG0sIGQsIGgsIE0sIHMsIG1zKSB7XG4gICAgICAgIC8vY2FuJ3QganVzdCBhcHBseSgpIHRvIGNyZWF0ZSBhIGRhdGU6XG4gICAgICAgIC8vaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xODEzNDgvaW5zdGFudGlhdGluZy1hLWphdmFzY3JpcHQtb2JqZWN0LWJ5LWNhbGxpbmctcHJvdG90eXBlLWNvbnN0cnVjdG9yLWFwcGx5XG4gICAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoeSwgbSwgZCwgaCwgTSwgcywgbXMpO1xuXG4gICAgICAgIC8vdGhlIGRhdGUgY29uc3RydWN0b3IgZG9lc24ndCBhY2NlcHQgeWVhcnMgPCAxOTcwXG4gICAgICAgIGlmICh5IDwgMTk3MCkge1xuICAgICAgICAgICAgZGF0ZS5zZXRGdWxsWWVhcih5KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlVVRDRGF0ZSh5KSB7XG4gICAgICAgIHZhciBkYXRlID0gbmV3IERhdGUoRGF0ZS5VVEMuYXBwbHkobnVsbCwgYXJndW1lbnRzKSk7XG4gICAgICAgIGlmICh5IDwgMTk3MCkge1xuICAgICAgICAgICAgZGF0ZS5zZXRVVENGdWxsWWVhcih5KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZGF0ZTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBwYXJzZVdlZWtkYXkoaW5wdXQsIGxhbmd1YWdlKSB7XG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBpZiAoIWlzTmFOKGlucHV0KSkge1xuICAgICAgICAgICAgICAgIGlucHV0ID0gcGFyc2VJbnQoaW5wdXQsIDEwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGlucHV0ID0gbGFuZ3VhZ2Uud2Vla2RheXNQYXJzZShpbnB1dCk7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbnB1dDtcbiAgICB9XG5cbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgIFJlbGF0aXZlIFRpbWVcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cblxuICAgIC8vIGhlbHBlciBmdW5jdGlvbiBmb3IgbW9tZW50LmZuLmZyb20sIG1vbWVudC5mbi5mcm9tTm93LCBhbmQgbW9tZW50LmR1cmF0aW9uLmZuLmh1bWFuaXplXG4gICAgZnVuY3Rpb24gc3Vic3RpdHV0ZVRpbWVBZ28oc3RyaW5nLCBudW1iZXIsIHdpdGhvdXRTdWZmaXgsIGlzRnV0dXJlLCBsYW5nKSB7XG4gICAgICAgIHJldHVybiBsYW5nLnJlbGF0aXZlVGltZShudW1iZXIgfHwgMSwgISF3aXRob3V0U3VmZml4LCBzdHJpbmcsIGlzRnV0dXJlKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZWxhdGl2ZVRpbWUobWlsbGlzZWNvbmRzLCB3aXRob3V0U3VmZml4LCBsYW5nKSB7XG4gICAgICAgIHZhciBzZWNvbmRzID0gcm91bmQoTWF0aC5hYnMobWlsbGlzZWNvbmRzKSAvIDEwMDApLFxuICAgICAgICAgICAgbWludXRlcyA9IHJvdW5kKHNlY29uZHMgLyA2MCksXG4gICAgICAgICAgICBob3VycyA9IHJvdW5kKG1pbnV0ZXMgLyA2MCksXG4gICAgICAgICAgICBkYXlzID0gcm91bmQoaG91cnMgLyAyNCksXG4gICAgICAgICAgICB5ZWFycyA9IHJvdW5kKGRheXMgLyAzNjUpLFxuICAgICAgICAgICAgYXJncyA9IHNlY29uZHMgPCA0NSAmJiBbJ3MnLCBzZWNvbmRzXSB8fFxuICAgICAgICAgICAgICAgIG1pbnV0ZXMgPT09IDEgJiYgWydtJ10gfHxcbiAgICAgICAgICAgICAgICBtaW51dGVzIDwgNDUgJiYgWydtbScsIG1pbnV0ZXNdIHx8XG4gICAgICAgICAgICAgICAgaG91cnMgPT09IDEgJiYgWydoJ10gfHxcbiAgICAgICAgICAgICAgICBob3VycyA8IDIyICYmIFsnaGgnLCBob3Vyc10gfHxcbiAgICAgICAgICAgICAgICBkYXlzID09PSAxICYmIFsnZCddIHx8XG4gICAgICAgICAgICAgICAgZGF5cyA8PSAyNSAmJiBbJ2RkJywgZGF5c10gfHxcbiAgICAgICAgICAgICAgICBkYXlzIDw9IDQ1ICYmIFsnTSddIHx8XG4gICAgICAgICAgICAgICAgZGF5cyA8IDM0NSAmJiBbJ01NJywgcm91bmQoZGF5cyAvIDMwKV0gfHxcbiAgICAgICAgICAgICAgICB5ZWFycyA9PT0gMSAmJiBbJ3knXSB8fCBbJ3l5JywgeWVhcnNdO1xuICAgICAgICBhcmdzWzJdID0gd2l0aG91dFN1ZmZpeDtcbiAgICAgICAgYXJnc1szXSA9IG1pbGxpc2Vjb25kcyA+IDA7XG4gICAgICAgIGFyZ3NbNF0gPSBsYW5nO1xuICAgICAgICByZXR1cm4gc3Vic3RpdHV0ZVRpbWVBZ28uYXBwbHkoe30sIGFyZ3MpO1xuICAgIH1cblxuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICBXZWVrIG9mIFllYXJcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cblxuICAgIC8vIGZpcnN0RGF5T2ZXZWVrICAgICAgIDAgPSBzdW4sIDYgPSBzYXRcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgICB0aGUgZGF5IG9mIHRoZSB3ZWVrIHRoYXQgc3RhcnRzIHRoZSB3ZWVrXG4gICAgLy8gICAgICAgICAgICAgICAgICAgICAgKHVzdWFsbHkgc3VuZGF5IG9yIG1vbmRheSlcbiAgICAvLyBmaXJzdERheU9mV2Vla09mWWVhciAwID0gc3VuLCA2ID0gc2F0XG4gICAgLy8gICAgICAgICAgICAgICAgICAgICAgdGhlIGZpcnN0IHdlZWsgaXMgdGhlIHdlZWsgdGhhdCBjb250YWlucyB0aGUgZmlyc3RcbiAgICAvLyAgICAgICAgICAgICAgICAgICAgICBvZiB0aGlzIGRheSBvZiB0aGUgd2Vla1xuICAgIC8vICAgICAgICAgICAgICAgICAgICAgIChlZy4gSVNPIHdlZWtzIHVzZSB0aHVyc2RheSAoNCkpXG4gICAgZnVuY3Rpb24gd2Vla09mWWVhcihtb20sIGZpcnN0RGF5T2ZXZWVrLCBmaXJzdERheU9mV2Vla09mWWVhcikge1xuICAgICAgICB2YXIgZW5kID0gZmlyc3REYXlPZldlZWtPZlllYXIgLSBmaXJzdERheU9mV2VlayxcbiAgICAgICAgICAgIGRheXNUb0RheU9mV2VlayA9IGZpcnN0RGF5T2ZXZWVrT2ZZZWFyIC0gbW9tLmRheSgpLFxuICAgICAgICAgICAgYWRqdXN0ZWRNb21lbnQ7XG5cblxuICAgICAgICBpZiAoZGF5c1RvRGF5T2ZXZWVrID4gZW5kKSB7XG4gICAgICAgICAgICBkYXlzVG9EYXlPZldlZWsgLT0gNztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkYXlzVG9EYXlPZldlZWsgPCBlbmQgLSA3KSB7XG4gICAgICAgICAgICBkYXlzVG9EYXlPZldlZWsgKz0gNztcbiAgICAgICAgfVxuXG4gICAgICAgIGFkanVzdGVkTW9tZW50ID0gbW9tZW50KG1vbSkuYWRkKCdkJywgZGF5c1RvRGF5T2ZXZWVrKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHdlZWs6IE1hdGguY2VpbChhZGp1c3RlZE1vbWVudC5kYXlPZlllYXIoKSAvIDcpLFxuICAgICAgICAgICAgeWVhcjogYWRqdXN0ZWRNb21lbnQueWVhcigpXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLy9odHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lTT193ZWVrX2RhdGUjQ2FsY3VsYXRpbmdfYV9kYXRlX2dpdmVuX3RoZV95ZWFyLjJDX3dlZWtfbnVtYmVyX2FuZF93ZWVrZGF5XG4gICAgZnVuY3Rpb24gZGF5T2ZZZWFyRnJvbVdlZWtzKHllYXIsIHdlZWssIHdlZWtkYXksIGZpcnN0RGF5T2ZXZWVrT2ZZZWFyLCBmaXJzdERheU9mV2Vlaykge1xuICAgICAgICB2YXIgZCA9IG5ldyBEYXRlKERhdGUuVVRDKHllYXIsIDApKS5nZXRVVENEYXkoKSxcbiAgICAgICAgICAgIGRheXNUb0FkZCwgZGF5T2ZZZWFyO1xuXG4gICAgICAgIHdlZWtkYXkgPSB3ZWVrZGF5ICE9IG51bGwgPyB3ZWVrZGF5IDogZmlyc3REYXlPZldlZWs7XG4gICAgICAgIGRheXNUb0FkZCA9IGZpcnN0RGF5T2ZXZWVrIC0gZCArIChkID4gZmlyc3REYXlPZldlZWtPZlllYXIgPyA3IDogMCk7XG4gICAgICAgIGRheU9mWWVhciA9IDcgKiAod2VlayAtIDEpICsgKHdlZWtkYXkgLSBmaXJzdERheU9mV2VlaykgKyBkYXlzVG9BZGQgKyAxO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB5ZWFyOiBkYXlPZlllYXIgPiAwID8geWVhciA6IHllYXIgLSAxLFxuICAgICAgICAgICAgZGF5T2ZZZWFyOiBkYXlPZlllYXIgPiAwID8gIGRheU9mWWVhciA6IGRheXNJblllYXIoeWVhciAtIDEpICsgZGF5T2ZZZWFyXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICBUb3AgTGV2ZWwgRnVuY3Rpb25zXG4gICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gICAgZnVuY3Rpb24gbWFrZU1vbWVudChjb25maWcpIHtcbiAgICAgICAgdmFyIGlucHV0ID0gY29uZmlnLl9pLFxuICAgICAgICAgICAgZm9ybWF0ID0gY29uZmlnLl9mO1xuXG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnLl9wZiA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIGluaXRpYWxpemVQYXJzaW5nRmxhZ3MoY29uZmlnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpbnB1dCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbWVudC5pbnZhbGlkKHtudWxsSW5wdXQ6IHRydWV9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25maWcuX2kgPSBpbnB1dCA9IGdldExhbmdEZWZpbml0aW9uKCkucHJlcGFyc2UoaW5wdXQpO1xuICAgICAgICB9XG5cblxuICAgICAgICBpZiAobW9tZW50LmlzTW9tZW50KGlucHV0KSkge1xuICAgICAgICAgICAgY29uZmlnID0gZXh0ZW5kKHt9LCBpbnB1dCk7XG5cbiAgICAgICAgICAgIGNvbmZpZy5fZCA9IG5ldyBEYXRlKCtpbnB1dC5fZCk7XG4gICAgICAgIH0gZWxzZSBpZiAoZm9ybWF0KSB7XG4gICAgICAgICAgICBpZiAoaXNBcnJheShmb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgbWFrZURhdGVGcm9tU3RyaW5nQW5kQXJyYXkoY29uZmlnKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbWFrZURhdGVGcm9tU3RyaW5nQW5kRm9ybWF0KGNvbmZpZyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtYWtlRGF0ZUZyb21JbnB1dChjb25maWcpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG5ldyBNb21lbnQoY29uZmlnKTtcbiAgICB9XG5cbiAgICBtb21lbnQgPSBmdW5jdGlvbiAoaW5wdXQsIGZvcm1hdCwgbGFuZywgc3RyaWN0KSB7XG4gICAgICAgIGlmICh0eXBlb2YobGFuZykgPT09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgICAgICBzdHJpY3QgPSBsYW5nO1xuICAgICAgICAgICAgbGFuZyA9IHVuZGVmaW5lZDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbWFrZU1vbWVudCh7XG4gICAgICAgICAgICBfaSA6IGlucHV0LFxuICAgICAgICAgICAgX2YgOiBmb3JtYXQsXG4gICAgICAgICAgICBfbCA6IGxhbmcsXG4gICAgICAgICAgICBfc3RyaWN0IDogc3RyaWN0LFxuICAgICAgICAgICAgX2lzVVRDIDogZmFsc2VcbiAgICAgICAgfSk7XG4gICAgfTtcblxuICAgIC8vIGNyZWF0aW5nIHdpdGggdXRjXG4gICAgbW9tZW50LnV0YyA9IGZ1bmN0aW9uIChpbnB1dCwgZm9ybWF0LCBsYW5nLCBzdHJpY3QpIHtcbiAgICAgICAgdmFyIG07XG5cbiAgICAgICAgaWYgKHR5cGVvZihsYW5nKSA9PT0gXCJib29sZWFuXCIpIHtcbiAgICAgICAgICAgIHN0cmljdCA9IGxhbmc7XG4gICAgICAgICAgICBsYW5nID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIG0gPSBtYWtlTW9tZW50KHtcbiAgICAgICAgICAgIF91c2VVVEMgOiB0cnVlLFxuICAgICAgICAgICAgX2lzVVRDIDogdHJ1ZSxcbiAgICAgICAgICAgIF9sIDogbGFuZyxcbiAgICAgICAgICAgIF9pIDogaW5wdXQsXG4gICAgICAgICAgICBfZiA6IGZvcm1hdCxcbiAgICAgICAgICAgIF9zdHJpY3QgOiBzdHJpY3RcbiAgICAgICAgfSkudXRjKCk7XG5cbiAgICAgICAgcmV0dXJuIG07XG4gICAgfTtcblxuICAgIC8vIGNyZWF0aW5nIHdpdGggdW5peCB0aW1lc3RhbXAgKGluIHNlY29uZHMpXG4gICAgbW9tZW50LnVuaXggPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgcmV0dXJuIG1vbWVudChpbnB1dCAqIDEwMDApO1xuICAgIH07XG5cbiAgICAvLyBkdXJhdGlvblxuICAgIG1vbWVudC5kdXJhdGlvbiA9IGZ1bmN0aW9uIChpbnB1dCwga2V5KSB7XG4gICAgICAgIHZhciBpc0R1cmF0aW9uID0gbW9tZW50LmlzRHVyYXRpb24oaW5wdXQpLFxuICAgICAgICAgICAgaXNOdW1iZXIgPSAodHlwZW9mIGlucHV0ID09PSAnbnVtYmVyJyksXG4gICAgICAgICAgICBkdXJhdGlvbiA9IChpc0R1cmF0aW9uID8gaW5wdXQuX2lucHV0IDogKGlzTnVtYmVyID8ge30gOiBpbnB1dCkpLFxuICAgICAgICAgICAgLy8gbWF0Y2hpbmcgYWdhaW5zdCByZWdleHAgaXMgZXhwZW5zaXZlLCBkbyBpdCBvbiBkZW1hbmRcbiAgICAgICAgICAgIG1hdGNoID0gbnVsbCxcbiAgICAgICAgICAgIHNpZ24sXG4gICAgICAgICAgICByZXQsXG4gICAgICAgICAgICBwYXJzZUlzbyxcbiAgICAgICAgICAgIHRpbWVFbXB0eSxcbiAgICAgICAgICAgIGRhdGVUaW1lRW1wdHk7XG5cbiAgICAgICAgaWYgKGlzTnVtYmVyKSB7XG4gICAgICAgICAgICBpZiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgZHVyYXRpb25ba2V5XSA9IGlucHV0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkdXJhdGlvbi5taWxsaXNlY29uZHMgPSBpbnB1dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICghIShtYXRjaCA9IGFzcE5ldFRpbWVTcGFuSnNvblJlZ2V4LmV4ZWMoaW5wdXQpKSkge1xuICAgICAgICAgICAgc2lnbiA9IChtYXRjaFsxXSA9PT0gXCItXCIpID8gLTEgOiAxO1xuICAgICAgICAgICAgZHVyYXRpb24gPSB7XG4gICAgICAgICAgICAgICAgeTogMCxcbiAgICAgICAgICAgICAgICBkOiB0b0ludChtYXRjaFtEQVRFXSkgKiBzaWduLFxuICAgICAgICAgICAgICAgIGg6IHRvSW50KG1hdGNoW0hPVVJdKSAqIHNpZ24sXG4gICAgICAgICAgICAgICAgbTogdG9JbnQobWF0Y2hbTUlOVVRFXSkgKiBzaWduLFxuICAgICAgICAgICAgICAgIHM6IHRvSW50KG1hdGNoW1NFQ09ORF0pICogc2lnbixcbiAgICAgICAgICAgICAgICBtczogdG9JbnQobWF0Y2hbTUlMTElTRUNPTkRdKSAqIHNpZ25cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0gZWxzZSBpZiAoISEobWF0Y2ggPSBpc29EdXJhdGlvblJlZ2V4LmV4ZWMoaW5wdXQpKSkge1xuICAgICAgICAgICAgc2lnbiA9IChtYXRjaFsxXSA9PT0gXCItXCIpID8gLTEgOiAxO1xuICAgICAgICAgICAgcGFyc2VJc28gPSBmdW5jdGlvbiAoaW5wKSB7XG4gICAgICAgICAgICAgICAgLy8gV2UnZCBub3JtYWxseSB1c2Ugfn5pbnAgZm9yIHRoaXMsIGJ1dCB1bmZvcnR1bmF0ZWx5IGl0IGFsc29cbiAgICAgICAgICAgICAgICAvLyBjb252ZXJ0cyBmbG9hdHMgdG8gaW50cy5cbiAgICAgICAgICAgICAgICAvLyBpbnAgbWF5IGJlIHVuZGVmaW5lZCwgc28gY2FyZWZ1bCBjYWxsaW5nIHJlcGxhY2Ugb24gaXQuXG4gICAgICAgICAgICAgICAgdmFyIHJlcyA9IGlucCAmJiBwYXJzZUZsb2F0KGlucC5yZXBsYWNlKCcsJywgJy4nKSk7XG4gICAgICAgICAgICAgICAgLy8gYXBwbHkgc2lnbiB3aGlsZSB3ZSdyZSBhdCBpdFxuICAgICAgICAgICAgICAgIHJldHVybiAoaXNOYU4ocmVzKSA/IDAgOiByZXMpICogc2lnbjtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBkdXJhdGlvbiA9IHtcbiAgICAgICAgICAgICAgICB5OiBwYXJzZUlzbyhtYXRjaFsyXSksXG4gICAgICAgICAgICAgICAgTTogcGFyc2VJc28obWF0Y2hbM10pLFxuICAgICAgICAgICAgICAgIGQ6IHBhcnNlSXNvKG1hdGNoWzRdKSxcbiAgICAgICAgICAgICAgICBoOiBwYXJzZUlzbyhtYXRjaFs1XSksXG4gICAgICAgICAgICAgICAgbTogcGFyc2VJc28obWF0Y2hbNl0pLFxuICAgICAgICAgICAgICAgIHM6IHBhcnNlSXNvKG1hdGNoWzddKSxcbiAgICAgICAgICAgICAgICB3OiBwYXJzZUlzbyhtYXRjaFs4XSlcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cblxuICAgICAgICByZXQgPSBuZXcgRHVyYXRpb24oZHVyYXRpb24pO1xuXG4gICAgICAgIGlmIChpc0R1cmF0aW9uICYmIGlucHV0Lmhhc093blByb3BlcnR5KCdfbGFuZycpKSB7XG4gICAgICAgICAgICByZXQuX2xhbmcgPSBpbnB1dC5fbGFuZztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXQ7XG4gICAgfTtcblxuICAgIC8vIHZlcnNpb24gbnVtYmVyXG4gICAgbW9tZW50LnZlcnNpb24gPSBWRVJTSU9OO1xuXG4gICAgLy8gZGVmYXVsdCBmb3JtYXRcbiAgICBtb21lbnQuZGVmYXVsdEZvcm1hdCA9IGlzb0Zvcm1hdDtcblxuICAgIC8vIFRoaXMgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQgd2hlbmV2ZXIgYSBtb21lbnQgaXMgbXV0YXRlZC5cbiAgICAvLyBJdCBpcyBpbnRlbmRlZCB0byBrZWVwIHRoZSBvZmZzZXQgaW4gc3luYyB3aXRoIHRoZSB0aW1lem9uZS5cbiAgICBtb21lbnQudXBkYXRlT2Zmc2V0ID0gZnVuY3Rpb24gKCkge307XG5cbiAgICAvLyBUaGlzIGZ1bmN0aW9uIHdpbGwgbG9hZCBsYW5ndWFnZXMgYW5kIHRoZW4gc2V0IHRoZSBnbG9iYWwgbGFuZ3VhZ2UuICBJZlxuICAgIC8vIG5vIGFyZ3VtZW50cyBhcmUgcGFzc2VkIGluLCBpdCB3aWxsIHNpbXBseSByZXR1cm4gdGhlIGN1cnJlbnQgZ2xvYmFsXG4gICAgLy8gbGFuZ3VhZ2Uga2V5LlxuICAgIG1vbWVudC5sYW5nID0gZnVuY3Rpb24gKGtleSwgdmFsdWVzKSB7XG4gICAgICAgIHZhciByO1xuICAgICAgICBpZiAoIWtleSkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbWVudC5mbi5fbGFuZy5fYWJicjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodmFsdWVzKSB7XG4gICAgICAgICAgICBsb2FkTGFuZyhub3JtYWxpemVMYW5ndWFnZShrZXkpLCB2YWx1ZXMpO1xuICAgICAgICB9IGVsc2UgaWYgKHZhbHVlcyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgdW5sb2FkTGFuZyhrZXkpO1xuICAgICAgICAgICAga2V5ID0gJ2VuJztcbiAgICAgICAgfSBlbHNlIGlmICghbGFuZ3VhZ2VzW2tleV0pIHtcbiAgICAgICAgICAgIGdldExhbmdEZWZpbml0aW9uKGtleSk7XG4gICAgICAgIH1cbiAgICAgICAgciA9IG1vbWVudC5kdXJhdGlvbi5mbi5fbGFuZyA9IG1vbWVudC5mbi5fbGFuZyA9IGdldExhbmdEZWZpbml0aW9uKGtleSk7XG4gICAgICAgIHJldHVybiByLl9hYmJyO1xuICAgIH07XG5cbiAgICAvLyByZXR1cm5zIGxhbmd1YWdlIGRhdGFcbiAgICBtb21lbnQubGFuZ0RhdGEgPSBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIGlmIChrZXkgJiYga2V5Ll9sYW5nICYmIGtleS5fbGFuZy5fYWJicikge1xuICAgICAgICAgICAga2V5ID0ga2V5Ll9sYW5nLl9hYmJyO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBnZXRMYW5nRGVmaW5pdGlvbihrZXkpO1xuICAgIH07XG5cbiAgICAvLyBjb21wYXJlIG1vbWVudCBvYmplY3RcbiAgICBtb21lbnQuaXNNb21lbnQgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICAgIHJldHVybiBvYmogaW5zdGFuY2VvZiBNb21lbnQ7XG4gICAgfTtcblxuICAgIC8vIGZvciB0eXBlY2hlY2tpbmcgRHVyYXRpb24gb2JqZWN0c1xuICAgIG1vbWVudC5pc0R1cmF0aW9uID0gZnVuY3Rpb24gKG9iaikge1xuICAgICAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgRHVyYXRpb247XG4gICAgfTtcblxuICAgIGZvciAoaSA9IGxpc3RzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICAgIG1ha2VMaXN0KGxpc3RzW2ldKTtcbiAgICB9XG5cbiAgICBtb21lbnQubm9ybWFsaXplVW5pdHMgPSBmdW5jdGlvbiAodW5pdHMpIHtcbiAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICB9O1xuXG4gICAgbW9tZW50LmludmFsaWQgPSBmdW5jdGlvbiAoZmxhZ3MpIHtcbiAgICAgICAgdmFyIG0gPSBtb21lbnQudXRjKE5hTik7XG4gICAgICAgIGlmIChmbGFncyAhPSBudWxsKSB7XG4gICAgICAgICAgICBleHRlbmQobS5fcGYsIGZsYWdzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG0uX3BmLnVzZXJJbnZhbGlkYXRlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbTtcbiAgICB9O1xuXG4gICAgbW9tZW50LnBhcnNlWm9uZSA9IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICByZXR1cm4gbW9tZW50KGlucHV0KS5wYXJzZVpvbmUoKTtcbiAgICB9O1xuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICBNb21lbnQgUHJvdG90eXBlXG4gICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5cbiAgICBleHRlbmQobW9tZW50LmZuID0gTW9tZW50LnByb3RvdHlwZSwge1xuXG4gICAgICAgIGNsb25lIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIG1vbWVudCh0aGlzKTtcbiAgICAgICAgfSxcblxuICAgICAgICB2YWx1ZU9mIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuICt0aGlzLl9kICsgKCh0aGlzLl9vZmZzZXQgfHwgMCkgKiA2MDAwMCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgdW5peCA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBNYXRoLmZsb29yKCt0aGlzIC8gMTAwMCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgdG9TdHJpbmcgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jbG9uZSgpLmxhbmcoJ2VuJykuZm9ybWF0KFwiZGRkIE1NTSBERCBZWVlZIEhIOm1tOnNzIFtHTVRdWlpcIik7XG4gICAgICAgIH0sXG5cbiAgICAgICAgdG9EYXRlIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX29mZnNldCA/IG5ldyBEYXRlKCt0aGlzKSA6IHRoaXMuX2Q7XG4gICAgICAgIH0sXG5cbiAgICAgICAgdG9JU09TdHJpbmcgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0TW9tZW50KG1vbWVudCh0aGlzKS51dGMoKSwgJ1lZWVktTU0tRERbVF1ISDptbTpzcy5TU1NbWl0nKTtcbiAgICAgICAgfSxcblxuICAgICAgICB0b0FycmF5IDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIG0gPSB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICAgICBtLnllYXIoKSxcbiAgICAgICAgICAgICAgICBtLm1vbnRoKCksXG4gICAgICAgICAgICAgICAgbS5kYXRlKCksXG4gICAgICAgICAgICAgICAgbS5ob3VycygpLFxuICAgICAgICAgICAgICAgIG0ubWludXRlcygpLFxuICAgICAgICAgICAgICAgIG0uc2Vjb25kcygpLFxuICAgICAgICAgICAgICAgIG0ubWlsbGlzZWNvbmRzKClcbiAgICAgICAgICAgIF07XG4gICAgICAgIH0sXG5cbiAgICAgICAgaXNWYWxpZCA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBpc1ZhbGlkKHRoaXMpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGlzRFNUU2hpZnRlZCA6IGZ1bmN0aW9uICgpIHtcblxuICAgICAgICAgICAgaWYgKHRoaXMuX2EpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5pc1ZhbGlkKCkgJiYgY29tcGFyZUFycmF5cyh0aGlzLl9hLCAodGhpcy5faXNVVEMgPyBtb21lbnQudXRjKHRoaXMuX2EpIDogbW9tZW50KHRoaXMuX2EpKS50b0FycmF5KCkpID4gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9LFxuXG4gICAgICAgIHBhcnNpbmdGbGFncyA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBleHRlbmQoe30sIHRoaXMuX3BmKTtcbiAgICAgICAgfSxcblxuICAgICAgICBpbnZhbGlkQXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9wZi5vdmVyZmxvdztcbiAgICAgICAgfSxcblxuICAgICAgICB1dGMgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy56b25lKDApO1xuICAgICAgICB9LFxuXG4gICAgICAgIGxvY2FsIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhpcy56b25lKDApO1xuICAgICAgICAgICAgdGhpcy5faXNVVEMgPSBmYWxzZTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZvcm1hdCA6IGZ1bmN0aW9uIChpbnB1dFN0cmluZykge1xuICAgICAgICAgICAgdmFyIG91dHB1dCA9IGZvcm1hdE1vbWVudCh0aGlzLCBpbnB1dFN0cmluZyB8fCBtb21lbnQuZGVmYXVsdEZvcm1hdCk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5sYW5nKCkucG9zdGZvcm1hdChvdXRwdXQpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGFkZCA6IGZ1bmN0aW9uIChpbnB1dCwgdmFsKSB7XG4gICAgICAgICAgICB2YXIgZHVyO1xuICAgICAgICAgICAgLy8gc3dpdGNoIGFyZ3MgdG8gc3VwcG9ydCBhZGQoJ3MnLCAxKSBhbmQgYWRkKDEsICdzJylcbiAgICAgICAgICAgIGlmICh0eXBlb2YgaW5wdXQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICAgICAgZHVyID0gbW9tZW50LmR1cmF0aW9uKCt2YWwsIGlucHV0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZHVyID0gbW9tZW50LmR1cmF0aW9uKGlucHV0LCB2YWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYWRkT3JTdWJ0cmFjdER1cmF0aW9uRnJvbU1vbWVudCh0aGlzLCBkdXIsIDEpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG5cbiAgICAgICAgc3VidHJhY3QgOiBmdW5jdGlvbiAoaW5wdXQsIHZhbCkge1xuICAgICAgICAgICAgdmFyIGR1cjtcbiAgICAgICAgICAgIC8vIHN3aXRjaCBhcmdzIHRvIHN1cHBvcnQgc3VidHJhY3QoJ3MnLCAxKSBhbmQgc3VidHJhY3QoMSwgJ3MnKVxuICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgICAgICBkdXIgPSBtb21lbnQuZHVyYXRpb24oK3ZhbCwgaW5wdXQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkdXIgPSBtb21lbnQuZHVyYXRpb24oaW5wdXQsIHZhbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhZGRPclN1YnRyYWN0RHVyYXRpb25Gcm9tTW9tZW50KHRoaXMsIGR1ciwgLTEpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGlmZiA6IGZ1bmN0aW9uIChpbnB1dCwgdW5pdHMsIGFzRmxvYXQpIHtcbiAgICAgICAgICAgIHZhciB0aGF0ID0gdGhpcy5faXNVVEMgPyBtb21lbnQoaW5wdXQpLnpvbmUodGhpcy5fb2Zmc2V0IHx8IDApIDogbW9tZW50KGlucHV0KS5sb2NhbCgpLFxuICAgICAgICAgICAgICAgIHpvbmVEaWZmID0gKHRoaXMuem9uZSgpIC0gdGhhdC56b25lKCkpICogNmU0LFxuICAgICAgICAgICAgICAgIGRpZmYsIG91dHB1dDtcblxuICAgICAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG5cbiAgICAgICAgICAgIGlmICh1bml0cyA9PT0gJ3llYXInIHx8IHVuaXRzID09PSAnbW9udGgnKSB7XG4gICAgICAgICAgICAgICAgLy8gYXZlcmFnZSBudW1iZXIgb2YgZGF5cyBpbiB0aGUgbW9udGhzIGluIHRoZSBnaXZlbiBkYXRlc1xuICAgICAgICAgICAgICAgIGRpZmYgPSAodGhpcy5kYXlzSW5Nb250aCgpICsgdGhhdC5kYXlzSW5Nb250aCgpKSAqIDQzMmU1OyAvLyAyNCAqIDYwICogNjAgKiAxMDAwIC8gMlxuICAgICAgICAgICAgICAgIC8vIGRpZmZlcmVuY2UgaW4gbW9udGhzXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKCh0aGlzLnllYXIoKSAtIHRoYXQueWVhcigpKSAqIDEyKSArICh0aGlzLm1vbnRoKCkgLSB0aGF0Lm1vbnRoKCkpO1xuICAgICAgICAgICAgICAgIC8vIGFkanVzdCBieSB0YWtpbmcgZGlmZmVyZW5jZSBpbiBkYXlzLCBhdmVyYWdlIG51bWJlciBvZiBkYXlzXG4gICAgICAgICAgICAgICAgLy8gYW5kIGRzdCBpbiB0aGUgZ2l2ZW4gbW9udGhzLlxuICAgICAgICAgICAgICAgIG91dHB1dCArPSAoKHRoaXMgLSBtb21lbnQodGhpcykuc3RhcnRPZignbW9udGgnKSkgLVxuICAgICAgICAgICAgICAgICAgICAgICAgKHRoYXQgLSBtb21lbnQodGhhdCkuc3RhcnRPZignbW9udGgnKSkpIC8gZGlmZjtcbiAgICAgICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aXRoIHpvbmVzLCB0byBuZWdhdGUgYWxsIGRzdFxuICAgICAgICAgICAgICAgIG91dHB1dCAtPSAoKHRoaXMuem9uZSgpIC0gbW9tZW50KHRoaXMpLnN0YXJ0T2YoJ21vbnRoJykuem9uZSgpKSAtXG4gICAgICAgICAgICAgICAgICAgICAgICAodGhhdC56b25lKCkgLSBtb21lbnQodGhhdCkuc3RhcnRPZignbW9udGgnKS56b25lKCkpKSAqIDZlNCAvIGRpZmY7XG4gICAgICAgICAgICAgICAgaWYgKHVuaXRzID09PSAneWVhcicpIHtcbiAgICAgICAgICAgICAgICAgICAgb3V0cHV0ID0gb3V0cHV0IC8gMTI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBkaWZmID0gKHRoaXMgLSB0aGF0KTtcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSB1bml0cyA9PT0gJ3NlY29uZCcgPyBkaWZmIC8gMWUzIDogLy8gMTAwMFxuICAgICAgICAgICAgICAgICAgICB1bml0cyA9PT0gJ21pbnV0ZScgPyBkaWZmIC8gNmU0IDogLy8gMTAwMCAqIDYwXG4gICAgICAgICAgICAgICAgICAgIHVuaXRzID09PSAnaG91cicgPyBkaWZmIC8gMzZlNSA6IC8vIDEwMDAgKiA2MCAqIDYwXG4gICAgICAgICAgICAgICAgICAgIHVuaXRzID09PSAnZGF5JyA/IChkaWZmIC0gem9uZURpZmYpIC8gODY0ZTUgOiAvLyAxMDAwICogNjAgKiA2MCAqIDI0LCBuZWdhdGUgZHN0XG4gICAgICAgICAgICAgICAgICAgIHVuaXRzID09PSAnd2VlaycgPyAoZGlmZiAtIHpvbmVEaWZmKSAvIDYwNDhlNSA6IC8vIDEwMDAgKiA2MCAqIDYwICogMjQgKiA3LCBuZWdhdGUgZHN0XG4gICAgICAgICAgICAgICAgICAgIGRpZmY7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gYXNGbG9hdCA/IG91dHB1dCA6IGFic1JvdW5kKG91dHB1dCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgZnJvbSA6IGZ1bmN0aW9uICh0aW1lLCB3aXRob3V0U3VmZml4KSB7XG4gICAgICAgICAgICByZXR1cm4gbW9tZW50LmR1cmF0aW9uKHRoaXMuZGlmZih0aW1lKSkubGFuZyh0aGlzLmxhbmcoKS5fYWJicikuaHVtYW5pemUoIXdpdGhvdXRTdWZmaXgpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGZyb21Ob3cgOiBmdW5jdGlvbiAod2l0aG91dFN1ZmZpeCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZnJvbShtb21lbnQoKSwgd2l0aG91dFN1ZmZpeCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgY2FsZW5kYXIgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgZGlmZiA9IHRoaXMuZGlmZihtb21lbnQoKS56b25lKHRoaXMuem9uZSgpKS5zdGFydE9mKCdkYXknKSwgJ2RheXMnLCB0cnVlKSxcbiAgICAgICAgICAgICAgICBmb3JtYXQgPSBkaWZmIDwgLTYgPyAnc2FtZUVsc2UnIDpcbiAgICAgICAgICAgICAgICBkaWZmIDwgLTEgPyAnbGFzdFdlZWsnIDpcbiAgICAgICAgICAgICAgICBkaWZmIDwgMCA/ICdsYXN0RGF5JyA6XG4gICAgICAgICAgICAgICAgZGlmZiA8IDEgPyAnc2FtZURheScgOlxuICAgICAgICAgICAgICAgIGRpZmYgPCAyID8gJ25leHREYXknIDpcbiAgICAgICAgICAgICAgICBkaWZmIDwgNyA/ICduZXh0V2VlaycgOiAnc2FtZUVsc2UnO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0KHRoaXMubGFuZygpLmNhbGVuZGFyKGZvcm1hdCwgdGhpcykpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGlzTGVhcFllYXIgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gaXNMZWFwWWVhcih0aGlzLnllYXIoKSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgaXNEU1QgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuem9uZSgpIDwgdGhpcy5jbG9uZSgpLm1vbnRoKDApLnpvbmUoKSB8fFxuICAgICAgICAgICAgICAgIHRoaXMuem9uZSgpIDwgdGhpcy5jbG9uZSgpLm1vbnRoKDUpLnpvbmUoKSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgZGF5IDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICB2YXIgZGF5ID0gdGhpcy5faXNVVEMgPyB0aGlzLl9kLmdldFVUQ0RheSgpIDogdGhpcy5fZC5nZXREYXkoKTtcbiAgICAgICAgICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaW5wdXQgPSBwYXJzZVdlZWtkYXkoaW5wdXQsIHRoaXMubGFuZygpKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQoeyBkIDogaW5wdXQgLSBkYXkgfSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiBkYXk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgbW9udGggOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHZhciB1dGMgPSB0aGlzLl9pc1VUQyA/ICdVVEMnIDogJycsXG4gICAgICAgICAgICAgICAgZGF5T2ZNb250aDtcblxuICAgICAgICAgICAgaWYgKGlucHV0ICE9IG51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGlucHV0ID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dCA9IHRoaXMubGFuZygpLm1vbnRoc1BhcnNlKGlucHV0KTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZGF5T2ZNb250aCA9IHRoaXMuZGF0ZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZSgxKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9kWydzZXQnICsgdXRjICsgJ01vbnRoJ10oaW5wdXQpO1xuICAgICAgICAgICAgICAgIHRoaXMuZGF0ZShNYXRoLm1pbihkYXlPZk1vbnRoLCB0aGlzLmRheXNJbk1vbnRoKCkpKTtcblxuICAgICAgICAgICAgICAgIG1vbWVudC51cGRhdGVPZmZzZXQodGhpcyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9kWydnZXQnICsgdXRjICsgJ01vbnRoJ10oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBzdGFydE9mOiBmdW5jdGlvbiAodW5pdHMpIHtcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICAgICAgLy8gdGhlIGZvbGxvd2luZyBzd2l0Y2ggaW50ZW50aW9uYWxseSBvbWl0cyBicmVhayBrZXl3b3Jkc1xuICAgICAgICAgICAgLy8gdG8gdXRpbGl6ZSBmYWxsaW5nIHRocm91Z2ggdGhlIGNhc2VzLlxuICAgICAgICAgICAgc3dpdGNoICh1bml0cykge1xuICAgICAgICAgICAgY2FzZSAneWVhcic6XG4gICAgICAgICAgICAgICAgdGhpcy5tb250aCgwKTtcbiAgICAgICAgICAgICAgICAvKiBmYWxscyB0aHJvdWdoICovXG4gICAgICAgICAgICBjYXNlICdtb250aCc6XG4gICAgICAgICAgICAgICAgdGhpcy5kYXRlKDEpO1xuICAgICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgICAgICAgIGNhc2UgJ3dlZWsnOlxuICAgICAgICAgICAgY2FzZSAnaXNvV2Vlayc6XG4gICAgICAgICAgICBjYXNlICdkYXknOlxuICAgICAgICAgICAgICAgIHRoaXMuaG91cnMoMCk7XG4gICAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgY2FzZSAnaG91cic6XG4gICAgICAgICAgICAgICAgdGhpcy5taW51dGVzKDApO1xuICAgICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgICAgICAgIGNhc2UgJ21pbnV0ZSc6XG4gICAgICAgICAgICAgICAgdGhpcy5zZWNvbmRzKDApO1xuICAgICAgICAgICAgICAgIC8qIGZhbGxzIHRocm91Z2ggKi9cbiAgICAgICAgICAgIGNhc2UgJ3NlY29uZCc6XG4gICAgICAgICAgICAgICAgdGhpcy5taWxsaXNlY29uZHMoMCk7XG4gICAgICAgICAgICAgICAgLyogZmFsbHMgdGhyb3VnaCAqL1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB3ZWVrcyBhcmUgYSBzcGVjaWFsIGNhc2VcbiAgICAgICAgICAgIGlmICh1bml0cyA9PT0gJ3dlZWsnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy53ZWVrZGF5KDApO1xuICAgICAgICAgICAgfSBlbHNlIGlmICh1bml0cyA9PT0gJ2lzb1dlZWsnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5pc29XZWVrZGF5KDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICBlbmRPZjogZnVuY3Rpb24gKHVuaXRzKSB7XG4gICAgICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnN0YXJ0T2YodW5pdHMpLmFkZCgodW5pdHMgPT09ICdpc29XZWVrJyA/ICd3ZWVrJyA6IHVuaXRzKSwgMSkuc3VidHJhY3QoJ21zJywgMSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgaXNBZnRlcjogZnVuY3Rpb24gKGlucHV0LCB1bml0cykge1xuICAgICAgICAgICAgdW5pdHMgPSB0eXBlb2YgdW5pdHMgIT09ICd1bmRlZmluZWQnID8gdW5pdHMgOiAnbWlsbGlzZWNvbmQnO1xuICAgICAgICAgICAgcmV0dXJuICt0aGlzLmNsb25lKCkuc3RhcnRPZih1bml0cykgPiArbW9tZW50KGlucHV0KS5zdGFydE9mKHVuaXRzKTtcbiAgICAgICAgfSxcblxuICAgICAgICBpc0JlZm9yZTogZnVuY3Rpb24gKGlucHV0LCB1bml0cykge1xuICAgICAgICAgICAgdW5pdHMgPSB0eXBlb2YgdW5pdHMgIT09ICd1bmRlZmluZWQnID8gdW5pdHMgOiAnbWlsbGlzZWNvbmQnO1xuICAgICAgICAgICAgcmV0dXJuICt0aGlzLmNsb25lKCkuc3RhcnRPZih1bml0cykgPCArbW9tZW50KGlucHV0KS5zdGFydE9mKHVuaXRzKTtcbiAgICAgICAgfSxcblxuICAgICAgICBpc1NhbWU6IGZ1bmN0aW9uIChpbnB1dCwgdW5pdHMpIHtcbiAgICAgICAgICAgIHVuaXRzID0gdHlwZW9mIHVuaXRzICE9PSAndW5kZWZpbmVkJyA/IHVuaXRzIDogJ21pbGxpc2Vjb25kJztcbiAgICAgICAgICAgIHJldHVybiArdGhpcy5jbG9uZSgpLnN0YXJ0T2YodW5pdHMpID09PSArbW9tZW50KGlucHV0KS5zdGFydE9mKHVuaXRzKTtcbiAgICAgICAgfSxcblxuICAgICAgICBtaW46IGZ1bmN0aW9uIChvdGhlcikge1xuICAgICAgICAgICAgb3RoZXIgPSBtb21lbnQuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcbiAgICAgICAgICAgIHJldHVybiBvdGhlciA8IHRoaXMgPyB0aGlzIDogb3RoZXI7XG4gICAgICAgIH0sXG5cbiAgICAgICAgbWF4OiBmdW5jdGlvbiAob3RoZXIpIHtcbiAgICAgICAgICAgIG90aGVyID0gbW9tZW50LmFwcGx5KG51bGwsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICByZXR1cm4gb3RoZXIgPiB0aGlzID8gdGhpcyA6IG90aGVyO1xuICAgICAgICB9LFxuXG4gICAgICAgIHpvbmUgOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHZhciBvZmZzZXQgPSB0aGlzLl9vZmZzZXQgfHwgMDtcbiAgICAgICAgICAgIGlmIChpbnB1dCAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBpbnB1dCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dCA9IHRpbWV6b25lTWludXRlc0Zyb21TdHJpbmcoaW5wdXQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoTWF0aC5hYnMoaW5wdXQpIDwgMTYpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXQgPSBpbnB1dCAqIDYwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLl9vZmZzZXQgPSBpbnB1dDtcbiAgICAgICAgICAgICAgICB0aGlzLl9pc1VUQyA9IHRydWU7XG4gICAgICAgICAgICAgICAgaWYgKG9mZnNldCAhPT0gaW5wdXQpIHtcbiAgICAgICAgICAgICAgICAgICAgYWRkT3JTdWJ0cmFjdER1cmF0aW9uRnJvbU1vbWVudCh0aGlzLCBtb21lbnQuZHVyYXRpb24ob2Zmc2V0IC0gaW5wdXQsICdtJyksIDEsIHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2lzVVRDID8gb2Zmc2V0IDogdGhpcy5fZC5nZXRUaW1lem9uZU9mZnNldCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG5cbiAgICAgICAgem9uZUFiYnIgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5faXNVVEMgPyBcIlVUQ1wiIDogXCJcIjtcbiAgICAgICAgfSxcblxuICAgICAgICB6b25lTmFtZSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9pc1VUQyA/IFwiQ29vcmRpbmF0ZWQgVW5pdmVyc2FsIFRpbWVcIiA6IFwiXCI7XG4gICAgICAgIH0sXG5cbiAgICAgICAgcGFyc2Vab25lIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLl9pID09PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgICAgIHRoaXMuem9uZSh0aGlzLl9pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuXG4gICAgICAgIGhhc0FsaWduZWRIb3VyT2Zmc2V0IDogZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgICAgICBpZiAoIWlucHV0KSB7XG4gICAgICAgICAgICAgICAgaW5wdXQgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgaW5wdXQgPSBtb21lbnQoaW5wdXQpLnpvbmUoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuICh0aGlzLnpvbmUoKSAtIGlucHV0KSAlIDYwID09PSAwO1xuICAgICAgICB9LFxuXG4gICAgICAgIGRheXNJbk1vbnRoIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIGRheXNJbk1vbnRoKHRoaXMueWVhcigpLCB0aGlzLm1vbnRoKCkpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGRheU9mWWVhciA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgdmFyIGRheU9mWWVhciA9IHJvdW5kKChtb21lbnQodGhpcykuc3RhcnRPZignZGF5JykgLSBtb21lbnQodGhpcykuc3RhcnRPZigneWVhcicpKSAvIDg2NGU1KSArIDE7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IGRheU9mWWVhciA6IHRoaXMuYWRkKFwiZFwiLCAoaW5wdXQgLSBkYXlPZlllYXIpKTtcbiAgICAgICAgfSxcblxuICAgICAgICB3ZWVrWWVhciA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgdmFyIHllYXIgPSB3ZWVrT2ZZZWFyKHRoaXMsIHRoaXMubGFuZygpLl93ZWVrLmRvdywgdGhpcy5sYW5nKCkuX3dlZWsuZG95KS55ZWFyO1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB5ZWFyIDogdGhpcy5hZGQoXCJ5XCIsIChpbnB1dCAtIHllYXIpKTtcbiAgICAgICAgfSxcblxuICAgICAgICBpc29XZWVrWWVhciA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgdmFyIHllYXIgPSB3ZWVrT2ZZZWFyKHRoaXMsIDEsIDQpLnllYXI7XG4gICAgICAgICAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IHllYXIgOiB0aGlzLmFkZChcInlcIiwgKGlucHV0IC0geWVhcikpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHdlZWsgOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHZhciB3ZWVrID0gdGhpcy5sYW5nKCkud2Vlayh0aGlzKTtcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2VlayA6IHRoaXMuYWRkKFwiZFwiLCAoaW5wdXQgLSB3ZWVrKSAqIDcpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGlzb1dlZWsgOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHZhciB3ZWVrID0gd2Vla09mWWVhcih0aGlzLCAxLCA0KS53ZWVrO1xuICAgICAgICAgICAgcmV0dXJuIGlucHV0ID09IG51bGwgPyB3ZWVrIDogdGhpcy5hZGQoXCJkXCIsIChpbnB1dCAtIHdlZWspICogNyk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgd2Vla2RheSA6IGZ1bmN0aW9uIChpbnB1dCkge1xuICAgICAgICAgICAgdmFyIHdlZWtkYXkgPSAodGhpcy5kYXkoKSArIDcgLSB0aGlzLmxhbmcoKS5fd2Vlay5kb3cpICUgNztcbiAgICAgICAgICAgIHJldHVybiBpbnB1dCA9PSBudWxsID8gd2Vla2RheSA6IHRoaXMuYWRkKFwiZFwiLCBpbnB1dCAtIHdlZWtkYXkpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGlzb1dlZWtkYXkgOiBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIC8vIGJlaGF2ZXMgdGhlIHNhbWUgYXMgbW9tZW50I2RheSBleGNlcHRcbiAgICAgICAgICAgIC8vIGFzIGEgZ2V0dGVyLCByZXR1cm5zIDcgaW5zdGVhZCBvZiAwICgxLTcgcmFuZ2UgaW5zdGVhZCBvZiAwLTYpXG4gICAgICAgICAgICAvLyBhcyBhIHNldHRlciwgc3VuZGF5IHNob3VsZCBiZWxvbmcgdG8gdGhlIHByZXZpb3VzIHdlZWsuXG4gICAgICAgICAgICByZXR1cm4gaW5wdXQgPT0gbnVsbCA/IHRoaXMuZGF5KCkgfHwgNyA6IHRoaXMuZGF5KHRoaXMuZGF5KCkgJSA3ID8gaW5wdXQgOiBpbnB1dCAtIDcpO1xuICAgICAgICB9LFxuXG4gICAgICAgIGdldCA6IGZ1bmN0aW9uICh1bml0cykge1xuICAgICAgICAgICAgdW5pdHMgPSBub3JtYWxpemVVbml0cyh1bml0cyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpc1t1bml0c10oKTtcbiAgICAgICAgfSxcblxuICAgICAgICBzZXQgOiBmdW5jdGlvbiAodW5pdHMsIHZhbHVlKSB7XG4gICAgICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpc1t1bml0c10gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICB0aGlzW3VuaXRzXSh2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfSxcblxuICAgICAgICAvLyBJZiBwYXNzZWQgYSBsYW5ndWFnZSBrZXksIGl0IHdpbGwgc2V0IHRoZSBsYW5ndWFnZSBmb3IgdGhpc1xuICAgICAgICAvLyBpbnN0YW5jZS4gIE90aGVyd2lzZSwgaXQgd2lsbCByZXR1cm4gdGhlIGxhbmd1YWdlIGNvbmZpZ3VyYXRpb25cbiAgICAgICAgLy8gdmFyaWFibGVzIGZvciB0aGlzIGluc3RhbmNlLlxuICAgICAgICBsYW5nIDogZnVuY3Rpb24gKGtleSkge1xuICAgICAgICAgICAgaWYgKGtleSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xhbmc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX2xhbmcgPSBnZXRMYW5nRGVmaW5pdGlvbihrZXkpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICAvLyBoZWxwZXIgZm9yIGFkZGluZyBzaG9ydGN1dHNcbiAgICBmdW5jdGlvbiBtYWtlR2V0dGVyQW5kU2V0dGVyKG5hbWUsIGtleSkge1xuICAgICAgICBtb21lbnQuZm5bbmFtZV0gPSBtb21lbnQuZm5bbmFtZSArICdzJ10gPSBmdW5jdGlvbiAoaW5wdXQpIHtcbiAgICAgICAgICAgIHZhciB1dGMgPSB0aGlzLl9pc1VUQyA/ICdVVEMnIDogJyc7XG4gICAgICAgICAgICBpZiAoaW5wdXQgIT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2RbJ3NldCcgKyB1dGMgKyBrZXldKGlucHV0KTtcbiAgICAgICAgICAgICAgICBtb21lbnQudXBkYXRlT2Zmc2V0KHRoaXMpO1xuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZFsnZ2V0JyArIHV0YyArIGtleV0oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvLyBsb29wIHRocm91Z2ggYW5kIGFkZCBzaG9ydGN1dHMgKE1vbnRoLCBEYXRlLCBIb3VycywgTWludXRlcywgU2Vjb25kcywgTWlsbGlzZWNvbmRzKVxuICAgIGZvciAoaSA9IDA7IGkgPCBwcm94eUdldHRlcnNBbmRTZXR0ZXJzLmxlbmd0aDsgaSArKykge1xuICAgICAgICBtYWtlR2V0dGVyQW5kU2V0dGVyKHByb3h5R2V0dGVyc0FuZFNldHRlcnNbaV0udG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9zJC8sICcnKSwgcHJveHlHZXR0ZXJzQW5kU2V0dGVyc1tpXSk7XG4gICAgfVxuXG4gICAgLy8gYWRkIHNob3J0Y3V0IGZvciB5ZWFyICh1c2VzIGRpZmZlcmVudCBzeW50YXggdGhhbiB0aGUgZ2V0dGVyL3NldHRlciAneWVhcicgPT0gJ0Z1bGxZZWFyJylcbiAgICBtYWtlR2V0dGVyQW5kU2V0dGVyKCd5ZWFyJywgJ0Z1bGxZZWFyJyk7XG5cbiAgICAvLyBhZGQgcGx1cmFsIG1ldGhvZHNcbiAgICBtb21lbnQuZm4uZGF5cyA9IG1vbWVudC5mbi5kYXk7XG4gICAgbW9tZW50LmZuLm1vbnRocyA9IG1vbWVudC5mbi5tb250aDtcbiAgICBtb21lbnQuZm4ud2Vla3MgPSBtb21lbnQuZm4ud2VlaztcbiAgICBtb21lbnQuZm4uaXNvV2Vla3MgPSBtb21lbnQuZm4uaXNvV2VlaztcblxuICAgIC8vIGFkZCBhbGlhc2VkIGZvcm1hdCBtZXRob2RzXG4gICAgbW9tZW50LmZuLnRvSlNPTiA9IG1vbWVudC5mbi50b0lTT1N0cmluZztcblxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgICAgRHVyYXRpb24gUHJvdG90eXBlXG4gICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG5cbiAgICBleHRlbmQobW9tZW50LmR1cmF0aW9uLmZuID0gRHVyYXRpb24ucHJvdG90eXBlLCB7XG5cbiAgICAgICAgX2J1YmJsZSA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBtaWxsaXNlY29uZHMgPSB0aGlzLl9taWxsaXNlY29uZHMsXG4gICAgICAgICAgICAgICAgZGF5cyA9IHRoaXMuX2RheXMsXG4gICAgICAgICAgICAgICAgbW9udGhzID0gdGhpcy5fbW9udGhzLFxuICAgICAgICAgICAgICAgIGRhdGEgPSB0aGlzLl9kYXRhLFxuICAgICAgICAgICAgICAgIHNlY29uZHMsIG1pbnV0ZXMsIGhvdXJzLCB5ZWFycztcblxuICAgICAgICAgICAgLy8gVGhlIGZvbGxvd2luZyBjb2RlIGJ1YmJsZXMgdXAgdmFsdWVzLCBzZWUgdGhlIHRlc3RzIGZvclxuICAgICAgICAgICAgLy8gZXhhbXBsZXMgb2Ygd2hhdCB0aGF0IG1lYW5zLlxuICAgICAgICAgICAgZGF0YS5taWxsaXNlY29uZHMgPSBtaWxsaXNlY29uZHMgJSAxMDAwO1xuXG4gICAgICAgICAgICBzZWNvbmRzID0gYWJzUm91bmQobWlsbGlzZWNvbmRzIC8gMTAwMCk7XG4gICAgICAgICAgICBkYXRhLnNlY29uZHMgPSBzZWNvbmRzICUgNjA7XG5cbiAgICAgICAgICAgIG1pbnV0ZXMgPSBhYnNSb3VuZChzZWNvbmRzIC8gNjApO1xuICAgICAgICAgICAgZGF0YS5taW51dGVzID0gbWludXRlcyAlIDYwO1xuXG4gICAgICAgICAgICBob3VycyA9IGFic1JvdW5kKG1pbnV0ZXMgLyA2MCk7XG4gICAgICAgICAgICBkYXRhLmhvdXJzID0gaG91cnMgJSAyNDtcblxuICAgICAgICAgICAgZGF5cyArPSBhYnNSb3VuZChob3VycyAvIDI0KTtcbiAgICAgICAgICAgIGRhdGEuZGF5cyA9IGRheXMgJSAzMDtcblxuICAgICAgICAgICAgbW9udGhzICs9IGFic1JvdW5kKGRheXMgLyAzMCk7XG4gICAgICAgICAgICBkYXRhLm1vbnRocyA9IG1vbnRocyAlIDEyO1xuXG4gICAgICAgICAgICB5ZWFycyA9IGFic1JvdW5kKG1vbnRocyAvIDEyKTtcbiAgICAgICAgICAgIGRhdGEueWVhcnMgPSB5ZWFycztcbiAgICAgICAgfSxcblxuICAgICAgICB3ZWVrcyA6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBhYnNSb3VuZCh0aGlzLmRheXMoKSAvIDcpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHZhbHVlT2YgOiBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbWlsbGlzZWNvbmRzICtcbiAgICAgICAgICAgICAgdGhpcy5fZGF5cyAqIDg2NGU1ICtcbiAgICAgICAgICAgICAgKHRoaXMuX21vbnRocyAlIDEyKSAqIDI1OTJlNiArXG4gICAgICAgICAgICAgIHRvSW50KHRoaXMuX21vbnRocyAvIDEyKSAqIDMxNTM2ZTY7XG4gICAgICAgIH0sXG5cbiAgICAgICAgaHVtYW5pemUgOiBmdW5jdGlvbiAod2l0aFN1ZmZpeCkge1xuICAgICAgICAgICAgdmFyIGRpZmZlcmVuY2UgPSArdGhpcyxcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSByZWxhdGl2ZVRpbWUoZGlmZmVyZW5jZSwgIXdpdGhTdWZmaXgsIHRoaXMubGFuZygpKTtcblxuICAgICAgICAgICAgaWYgKHdpdGhTdWZmaXgpIHtcbiAgICAgICAgICAgICAgICBvdXRwdXQgPSB0aGlzLmxhbmcoKS5wYXN0RnV0dXJlKGRpZmZlcmVuY2UsIG91dHB1dCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmxhbmcoKS5wb3N0Zm9ybWF0KG91dHB1dCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgYWRkIDogZnVuY3Rpb24gKGlucHV0LCB2YWwpIHtcbiAgICAgICAgICAgIC8vIHN1cHBvcnRzIG9ubHkgMi4wLXN0eWxlIGFkZCgxLCAncycpIG9yIGFkZChtb21lbnQpXG4gICAgICAgICAgICB2YXIgZHVyID0gbW9tZW50LmR1cmF0aW9uKGlucHV0LCB2YWwpO1xuXG4gICAgICAgICAgICB0aGlzLl9taWxsaXNlY29uZHMgKz0gZHVyLl9taWxsaXNlY29uZHM7XG4gICAgICAgICAgICB0aGlzLl9kYXlzICs9IGR1ci5fZGF5cztcbiAgICAgICAgICAgIHRoaXMuX21vbnRocyArPSBkdXIuX21vbnRocztcblxuICAgICAgICAgICAgdGhpcy5fYnViYmxlKCk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9LFxuXG4gICAgICAgIHN1YnRyYWN0IDogZnVuY3Rpb24gKGlucHV0LCB2YWwpIHtcbiAgICAgICAgICAgIHZhciBkdXIgPSBtb21lbnQuZHVyYXRpb24oaW5wdXQsIHZhbCk7XG5cbiAgICAgICAgICAgIHRoaXMuX21pbGxpc2Vjb25kcyAtPSBkdXIuX21pbGxpc2Vjb25kcztcbiAgICAgICAgICAgIHRoaXMuX2RheXMgLT0gZHVyLl9kYXlzO1xuICAgICAgICAgICAgdGhpcy5fbW9udGhzIC09IGR1ci5fbW9udGhzO1xuXG4gICAgICAgICAgICB0aGlzLl9idWJibGUoKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH0sXG5cbiAgICAgICAgZ2V0IDogZnVuY3Rpb24gKHVuaXRzKSB7XG4gICAgICAgICAgICB1bml0cyA9IG5vcm1hbGl6ZVVuaXRzKHVuaXRzKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzW3VuaXRzLnRvTG93ZXJDYXNlKCkgKyAncyddKCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgYXMgOiBmdW5jdGlvbiAodW5pdHMpIHtcbiAgICAgICAgICAgIHVuaXRzID0gbm9ybWFsaXplVW5pdHModW5pdHMpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXNbJ2FzJyArIHVuaXRzLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgdW5pdHMuc2xpY2UoMSkgKyAncyddKCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgbGFuZyA6IG1vbWVudC5mbi5sYW5nLFxuXG4gICAgICAgIHRvSXNvU3RyaW5nIDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgLy8gaW5zcGlyZWQgYnkgaHR0cHM6Ly9naXRodWIuY29tL2RvcmRpbGxlL21vbWVudC1pc29kdXJhdGlvbi9ibG9iL21hc3Rlci9tb21lbnQuaXNvZHVyYXRpb24uanNcbiAgICAgICAgICAgIHZhciB5ZWFycyA9IE1hdGguYWJzKHRoaXMueWVhcnMoKSksXG4gICAgICAgICAgICAgICAgbW9udGhzID0gTWF0aC5hYnModGhpcy5tb250aHMoKSksXG4gICAgICAgICAgICAgICAgZGF5cyA9IE1hdGguYWJzKHRoaXMuZGF5cygpKSxcbiAgICAgICAgICAgICAgICBob3VycyA9IE1hdGguYWJzKHRoaXMuaG91cnMoKSksXG4gICAgICAgICAgICAgICAgbWludXRlcyA9IE1hdGguYWJzKHRoaXMubWludXRlcygpKSxcbiAgICAgICAgICAgICAgICBzZWNvbmRzID0gTWF0aC5hYnModGhpcy5zZWNvbmRzKCkgKyB0aGlzLm1pbGxpc2Vjb25kcygpIC8gMTAwMCk7XG5cbiAgICAgICAgICAgIGlmICghdGhpcy5hc1NlY29uZHMoKSkge1xuICAgICAgICAgICAgICAgIC8vIHRoaXMgaXMgdGhlIHNhbWUgYXMgQyMncyAoTm9kYSkgYW5kIHB5dGhvbiAoaXNvZGF0ZSkuLi5cbiAgICAgICAgICAgICAgICAvLyBidXQgbm90IG90aGVyIEpTIChnb29nLmRhdGUpXG4gICAgICAgICAgICAgICAgcmV0dXJuICdQMEQnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gKHRoaXMuYXNTZWNvbmRzKCkgPCAwID8gJy0nIDogJycpICtcbiAgICAgICAgICAgICAgICAnUCcgK1xuICAgICAgICAgICAgICAgICh5ZWFycyA/IHllYXJzICsgJ1knIDogJycpICtcbiAgICAgICAgICAgICAgICAobW9udGhzID8gbW9udGhzICsgJ00nIDogJycpICtcbiAgICAgICAgICAgICAgICAoZGF5cyA/IGRheXMgKyAnRCcgOiAnJykgK1xuICAgICAgICAgICAgICAgICgoaG91cnMgfHwgbWludXRlcyB8fCBzZWNvbmRzKSA/ICdUJyA6ICcnKSArXG4gICAgICAgICAgICAgICAgKGhvdXJzID8gaG91cnMgKyAnSCcgOiAnJykgK1xuICAgICAgICAgICAgICAgIChtaW51dGVzID8gbWludXRlcyArICdNJyA6ICcnKSArXG4gICAgICAgICAgICAgICAgKHNlY29uZHMgPyBzZWNvbmRzICsgJ1MnIDogJycpO1xuICAgICAgICB9XG4gICAgfSk7XG5cbiAgICBmdW5jdGlvbiBtYWtlRHVyYXRpb25HZXR0ZXIobmFtZSkge1xuICAgICAgICBtb21lbnQuZHVyYXRpb24uZm5bbmFtZV0gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fZGF0YVtuYW1lXTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBtYWtlRHVyYXRpb25Bc0dldHRlcihuYW1lLCBmYWN0b3IpIHtcbiAgICAgICAgbW9tZW50LmR1cmF0aW9uLmZuWydhcycgKyBuYW1lXSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiArdGhpcyAvIGZhY3RvcjtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICBmb3IgKGkgaW4gdW5pdE1pbGxpc2Vjb25kRmFjdG9ycykge1xuICAgICAgICBpZiAodW5pdE1pbGxpc2Vjb25kRmFjdG9ycy5oYXNPd25Qcm9wZXJ0eShpKSkge1xuICAgICAgICAgICAgbWFrZUR1cmF0aW9uQXNHZXR0ZXIoaSwgdW5pdE1pbGxpc2Vjb25kRmFjdG9yc1tpXSk7XG4gICAgICAgICAgICBtYWtlRHVyYXRpb25HZXR0ZXIoaS50b0xvd2VyQ2FzZSgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIG1ha2VEdXJhdGlvbkFzR2V0dGVyKCdXZWVrcycsIDYwNDhlNSk7XG4gICAgbW9tZW50LmR1cmF0aW9uLmZuLmFzTW9udGhzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gKCt0aGlzIC0gdGhpcy55ZWFycygpICogMzE1MzZlNikgLyAyNTkyZTYgKyB0aGlzLnllYXJzKCkgKiAxMjtcbiAgICB9O1xuXG5cbiAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgIERlZmF1bHQgTGFuZ1xuICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cblxuXG4gICAgLy8gU2V0IGRlZmF1bHQgbGFuZ3VhZ2UsIG90aGVyIGxhbmd1YWdlcyB3aWxsIGluaGVyaXQgZnJvbSBFbmdsaXNoLlxuICAgIG1vbWVudC5sYW5nKCdlbicsIHtcbiAgICAgICAgb3JkaW5hbCA6IGZ1bmN0aW9uIChudW1iZXIpIHtcbiAgICAgICAgICAgIHZhciBiID0gbnVtYmVyICUgMTAsXG4gICAgICAgICAgICAgICAgb3V0cHV0ID0gKHRvSW50KG51bWJlciAlIDEwMCAvIDEwKSA9PT0gMSkgPyAndGgnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMSkgPyAnc3QnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMikgPyAnbmQnIDpcbiAgICAgICAgICAgICAgICAoYiA9PT0gMykgPyAncmQnIDogJ3RoJztcbiAgICAgICAgICAgIHJldHVybiBudW1iZXIgKyBvdXRwdXQ7XG4gICAgICAgIH1cbiAgICB9KTtcblxuICAgIC8qIEVNQkVEX0xBTkdVQUdFUyAqL1xuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICBFeHBvc2luZyBNb21lbnRcbiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgICBmdW5jdGlvbiBtYWtlR2xvYmFsKCkge1xuICAgICAgICAvKmdsb2JhbCBlbmRlcjpmYWxzZSAqL1xuICAgICAgICBpZiAodHlwZW9mIGVuZGVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgLy8gaGVyZSwgYHRoaXNgIG1lYW5zIGB3aW5kb3dgIGluIHRoZSBicm93c2VyLCBvciBgZ2xvYmFsYCBvbiB0aGUgc2VydmVyXG4gICAgICAgICAgICAvLyBhZGQgYG1vbWVudGAgYXMgYSBnbG9iYWwgb2JqZWN0IHZpYSBhIHN0cmluZyBpZGVudGlmaWVyLFxuICAgICAgICAgICAgLy8gZm9yIENsb3N1cmUgQ29tcGlsZXIgXCJhZHZhbmNlZFwiIG1vZGVcbiAgICAgICAgICAgIHRoaXNbJ21vbWVudCddID0gbW9tZW50O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ29tbW9uSlMgbW9kdWxlIGlzIGRlZmluZWRcbiAgICBpZiAoaGFzTW9kdWxlKSB7XG4gICAgICAgIG1vZHVsZS5leHBvcnRzID0gbW9tZW50O1xuICAgICAgICBtYWtlR2xvYmFsKCk7XG4gICAgfSBlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgICBkZWZpbmUoXCJtb21lbnRcIiwgZnVuY3Rpb24gKHJlcXVpcmUsIGV4cG9ydHMsIG1vZHVsZSkge1xuICAgICAgICAgICAgaWYgKG1vZHVsZS5jb25maWcoKS5ub0dsb2JhbCAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIG1ha2VHbG9iYWwoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIG1vbWVudDtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgbWFrZUdsb2JhbCgpO1xuICAgIH1cbn0pLmNhbGwodGhpcyk7XG4iXX0=
require=(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){
(function () {
var $D = Date,
$P = $D.prototype,
p = function (s, l) {
if (!l) {
l = 2;
}
return ("000" + s).slice(l * -1);
};
var validateConfigObject = function (obj) {
var result = {}, self = this, prop, testFunc;
testFunc = function (prop, func, value) {
if (prop === "day") {
var month = (obj.month !== undefined) ? obj.month : self.getMonth();
var year = (obj.year !== undefined) ? obj.year : self.getFullYear();
return $D[func](value, year, month);
} else {
return $D[func](value);
}
};
for (prop in obj) {
if (hasOwnProperty.call(obj, prop)) {
var func = "validate" + prop.charAt(0).toUpperCase() + prop.slice(1);
if ($D[func] && obj[prop] !== null && testFunc(prop, func, obj[prop])) {
result[prop] = obj[prop];
}
}
}
return result;
};
/**
* Resets the time of this Date object to 12:00 AM (00:00), which is the start of the day.
* @param {Boolean} .clone() this date instance before clearing Time
* @return {Date} this
*/
$P.clearTime = function () {
this.setHours(0);
this.setMinutes(0);
this.setSeconds(0);
this.setMilliseconds(0);
return this;
};
/**
* Resets the time of this Date object to the current time ('now').
* @return {Date} this
*/
$P.setTimeToNow = function () {
var n = new Date();
this.setHours(n.getHours());
this.setMinutes(n.getMinutes());
this.setSeconds(n.getSeconds());
this.setMilliseconds(n.getMilliseconds());
return this;
};
/**
* Returns a new Date object that is an exact date and time copy of the original instance.
* @return {Date} A new Date instance
*/
$P.clone = function () {
return new Date(this.getTime());
};
/**
* Compares this instance to a Date object and returns an number indication of their relative values.
* @param {Date} Date object to compare [Required]
* @return {Number} -1 = this is lessthan date. 0 = values are equal. 1 = this is greaterthan date.
*/
$P.compareTo = function (date) {
return Date.compare(this, date);
};
/**
* Compares this instance to another Date object and returns true if they are equal.
* @param {Date} Date object to compare. If no date to compare, new Date() [now] is used.
* @return {Boolean} true if dates are equal. false if they are not equal.
*/
$P.equals = function (date) {
return Date.equals(this, (date !== undefined ? date : new Date()));
};
/**
* Determines if this instance is between a range of two dates or equal to either the start or end dates.
* @param {Date} Start of range [Required]
* @param {Date} End of range [Required]
* @return {Boolean} true is this is between or equal to the start and end dates, else false
*/
$P.between = function (start, end) {
return this.getTime() >= start.getTime() && this.getTime() <= end.getTime();
};
/**
* Determines if this date occurs after the date to compare to.
* @param {Date} Date object to compare. If no date to compare, new Date() ("now") is used.
* @return {Boolean} true if this date instance is greater than the date to compare to (or "now"), otherwise false.
*/
$P.isAfter = function (date) {
return this.compareTo(date || new Date()) === 1;
};
/**
* Determines if this date occurs before the date to compare to.
* @param {Date} Date object to compare. If no date to compare, new Date() ("now") is used.
* @return {Boolean} true if this date instance is less than the date to compare to (or "now").
*/
$P.isBefore = function (date) {
return (this.compareTo(date || new Date()) === -1);
};
/**
* Determines if the current Date instance occurs today.
* @return {Boolean} true if this date instance is 'today', otherwise false.
*/
/**
* Determines if the current Date instance occurs on the same Date as the supplied 'date'.
* If no 'date' to compare to is provided, the current Date instance is compared to 'today'.
* @param {date} Date object to compare. If no date to compare, the current Date ("now") is used.
* @return {Boolean} true if this Date instance occurs on the same Day as the supplied 'date'.
*/
$P.isToday = $P.isSameDay = function (date) {
return this.clone().clearTime().equals((date || new Date()).clone().clearTime());
};
/**
* Adds the specified number of milliseconds to this instance.
* @param {Number} The number of milliseconds to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addMilliseconds = function (value) {
if (!value) { return this; }
this.setTime(this.getTime() + value * 1);
return this;
};
/**
* Adds the specified number of seconds to this instance.
* @param {Number} The number of seconds to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addSeconds = function (value) {
if (!value) { return this; }
return this.addMilliseconds(value * 1000);
};
/**
* Adds the specified number of seconds to this instance.
* @param {Number} The number of seconds to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addMinutes = function (value) {
if (!value) { return this; }
return this.addMilliseconds(value * 60000); // 60*1000
};
/**
* Adds the specified number of hours to this instance.
* @param {Number} The number of hours to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addHours = function (value) {
if (!value) { return this; }
return this.addMilliseconds(value * 3600000); // 60*60*1000
};
/**
* Adds the specified number of days to this instance.
* @param {Number} The number of days to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addDays = function (value) {
if (!value) { return this; }
this.setDate(this.getDate() + value * 1);
return this;
};
/**
* Adds the specified number of weekdays (ie - not sat or sun) to this instance.
* @param {Number} The number of days to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addWeekdays = function (value) {
if (!value) { return this; }
var day = this.getDay();
var weeks = (Math.ceil(Math.abs(value)/7));
if (day === 0 || day === 6) {
if (value > 0) {
this.next().monday();
this.addDays(-1);
day = this.getDay();
}
}
if (value < 0) {
while (value < 0) {
this.addDays(-1);
day = this.getDay();
if (day !== 0 && day !== 6) {
value++;
}
}
return this;
} else if (value > 5 || (6-day) <= value) {
value = value + (weeks * 2);
}
return this.addDays(value);
};
/**
* Adds the specified number of weeks to this instance.
* @param {Number} The number of weeks to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addWeeks = function (value) {
if (!value) { return this; }
return this.addDays(value * 7);
};
/**
* Adds the specified number of months to this instance.
* @param {Number} The number of months to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addMonths = function (value) {
if (!value) { return this; }
var n = this.getDate();
this.setDate(1);
this.setMonth(this.getMonth() + value * 1);
this.setDate(Math.min(n, $D.getDaysInMonth(this.getFullYear(), this.getMonth())));
return this;
};
$P.addQuarters = function (value) {
if (!value) { return this; }
// note this will take you to the same point in the quarter as you are now.
// i.e. - if you are 15 days into the quarter you'll be 15 days into the resulting one.
// bonus: this allows adding fractional quarters
return this.addMonths(value * 3);
};
/**
* Adds the specified number of years to this instance.
* @param {Number} The number of years to add. The number can be positive or negative [Required]
* @return {Date} this
*/
$P.addYears = function (value) {
if (!value) { return this; }
return this.addMonths(value * 12);
};
/**
* Adds (or subtracts) to the value of the years, months, weeks, days, hours, minutes, seconds, milliseconds of the date instance using given configuration object. Positive and Negative values allowed.
* Example
<pre><code>
Date.today().add( { days: 1, months: 1 } )
new Date().add( { years: -1 } )
</code></pre>
* @param {Object} Configuration object containing attributes (months, days, etc.)
* @return {Date} this
*/
$P.add = function (config) {
if (typeof config === "number") {
this._orient = config;
return this;
}
var x = config;
if (x.day) {
// If we should be a different date than today (eg: for 'tomorrow -1d', etc).
// Should only effect parsing, not direct usage (eg, Finish and FinishExact)
if ((x.day - this.getDate()) !== 0) {
this.setDate(x.day);
}
}
if (x.milliseconds) {
this.addMilliseconds(x.milliseconds);
}
if (x.seconds) {
this.addSeconds(x.seconds);
}
if (x.minutes) {
this.addMinutes(x.minutes);
}
if (x.hours) {
this.addHours(x.hours);
}
if (x.weeks) {
this.addWeeks(x.weeks);
}
if (x.months) {
this.addMonths(x.months);
}
if (x.years) {
this.addYears(x.years);
}
if (x.days) {
this.addDays(x.days);
}
return this;
};
/**
* Get the week number. Week one (1) is the week which contains the first Thursday of the year. Monday is considered the first day of the week.
* The .getWeek() function does NOT convert the date to UTC. The local datetime is used.
* Please use .getISOWeek() to get the week of the UTC converted date.
* @return {Number} 1 to 53
*/
$P.getWeek = function (utc) {
// Create a copy of this date object
var self, target = new Date(this.valueOf());
if (utc) {
target.addMinutes(target.getTimezoneOffset());
self = target.clone();
} else {
self = this;
}
// ISO week date weeks start on monday
// so correct the day number
var dayNr = (self.getDay() + 6) % 7;
// ISO 8601 states that week 1 is the week
// with the first thursday of that year.
// Set the target date to the thursday in the target week
target.setDate(target.getDate() - dayNr + 3);
// Store the millisecond value of the target date
var firstThursday = target.valueOf();
// Set the target to the first thursday of the year
// First set the target to january first
target.setMonth(0, 1);
// Not a thursday? Correct the date to the next thursday
if (target.getDay() !== 4) {
target.setMonth(0, 1 + ((4 - target.getDay()) + 7) % 7);
}
// The weeknumber is the number of weeks between the
// first thursday of the year and the thursday in the target week
return 1 + Math.ceil((firstThursday - target) / 604800000); // 604800000 = 7 * 24 * 3600 * 1000
};
/**
* Get the ISO 8601 week number. Week one ("01") is the week which contains the first Thursday of the year. Monday is considered the first day of the week.
* The .getISOWeek() function does convert the date to it's UTC value. Please use .getWeek() to get the week of the local date.
* @return {String} "01" to "53"
*/
$P.getISOWeek = function () {
return p(this.getWeek(true));
};
/**
* Moves the date to Monday of the week set. Week one (1) is the week which contains the first Thursday of the year.
* @param {Number} A Number (1 to 53) that represents the week of the year.
* @return {Date} this
*/
$P.setWeek = function (n) {
if ((n - this.getWeek()) === 0) {
if (this.getDay() !== 1) {
return this.moveToDayOfWeek(1, (this.getDay() > 1 ? -1 : 1));
} else {
return this;
}
} else {
return this.moveToDayOfWeek(1, (this.getDay() > 1 ? -1 : 1)).addWeeks(n - this.getWeek());
}
};
$P.setQuarter = function (qtr) {
var month = Math.abs(((qtr-1) * 3) + 1);
return this.setMonth(month, 1);
};
$P.getQuarter = function () {
return Date.getQuarter(this);
};
$P.getDaysLeftInQuarter = function () {
return Date.getDaysLeftInQuarter(this);
};
/**
* Moves the date to the next n'th occurrence of the dayOfWeek starting from the beginning of the month. The number (-1) is a magic number and will return the last occurrence of the dayOfWeek in the month.
* @param {Number} The dayOfWeek to move to
* @param {Number} The n'th occurrence to move to. Use (-1) to return the last occurrence in the month
* @return {Date} this
*/
$P.moveToNthOccurrence = function (dayOfWeek, occurrence) {
if (dayOfWeek === "Weekday") {
if (occurrence > 0) {
this.moveToFirstDayOfMonth();
if (this.is().weekday()) {
occurrence -= 1;
}
} else if (occurrence < 0) {
this.moveToLastDayOfMonth();
if (this.is().weekday()) {
occurrence += 1;
}
} else {
return this;
}
return this.addWeekdays(occurrence);
}
var shift = 0;
if (occurrence > 0) {
shift = occurrence - 1;
}
else if (occurrence === -1) {
this.moveToLastDayOfMonth();
if (this.getDay() !== dayOfWeek) {
this.moveToDayOfWeek(dayOfWeek, -1);
}
return this;
}
return this.moveToFirstDayOfMonth().addDays(-1).moveToDayOfWeek(dayOfWeek, +1).addWeeks(shift);
};
var moveToN = function (getFunc, addFunc, nVal) {
return function (value, orient) {
var diff = (value - this[getFunc]() + nVal * (orient || +1)) % nVal;
return this[addFunc]((diff === 0) ? diff += nVal * (orient || +1) : diff);
};
};
/**
* Move to the next or last dayOfWeek based on the orient value.
* @param {Number} The dayOfWeek to move to
* @param {Number} Forward (+1) or Back (-1). Defaults to +1. [Optional]
* @return {Date} this
*/
$P.moveToDayOfWeek = moveToN("getDay", "addDays", 7);
/**
* Move to the next or last month based on the orient value.
* @param {Number} The month to move to. 0 = January, 11 = December
* @param {Number} Forward (+1) or Back (-1). Defaults to +1. [Optional]
* @return {Date} this
*/
$P.moveToMonth = moveToN("getMonth", "addMonths", 12);
/**
* Get the Ordinate of the current day ("th", "st", "rd").
* @return {String}
*/
$P.getOrdinate = function () {
var num = this.getDate();
return ord(num);
};
/**
* Get the Ordinal day (numeric day number) of the year, adjusted for leap year.
* @return {Number} 1 through 365 (366 in leap years)
*/
$P.getOrdinalNumber = function () {
return Math.ceil((this.clone().clearTime() - new Date(this.getFullYear(), 0, 1)) / 86400000) + 1;
};
/**
* Get the time zone abbreviation of the current date.
* @return {String} The abbreviated time zone name (e.g. "EST")
*/
$P.getTimezone = function () {
return $D.getTimezoneAbbreviation(this.getUTCOffset(), this.isDaylightSavingTime());
};
$P.setTimezoneOffset = function (offset) {
var here = this.getTimezoneOffset(), there = Number(offset) * -6 / 10;
return (there || there === 0) ? this.addMinutes(there - here) : this;
};
$P.setTimezone = function (offset) {
return this.setTimezoneOffset($D.getTimezoneOffset(offset));
};
/**
* Indicates whether Daylight Saving Time is observed in the current time zone.
* @return {Boolean} true|false
*/
$P.hasDaylightSavingTime = function () {
return (Date.today().set({month: 0, day: 1}).getTimezoneOffset() !== Date.today().set({month: 6, day: 1}).getTimezoneOffset());
};
/**
* Indicates whether this Date instance is within the Daylight Saving Time range for the current time zone.
* @return {Boolean} true|false
*/
$P.isDaylightSavingTime = function () {
return Date.today().set({month: 0, day: 1}).getTimezoneOffset() !== this.getTimezoneOffset();
};
/**
* Get the offset from UTC of the current date.
* @return {String} The 4-character offset string prefixed with + or - (e.g. "-0500")
*/
$P.getUTCOffset = function (offset) {
var n = (offset || this.getTimezoneOffset()) * -10 / 6, r;
if (n < 0) {
r = (n - 10000).toString();
return r.charAt(0) + r.substr(2);
} else {
r = (n + 10000).toString();
return "+" + r.substr(1);
}
};
/**
* Returns the number of milliseconds between this date and date.
* @param {Date} Defaults to now
* @return {Number} The diff in milliseconds
*/
$P.getElapsed = function (date) {
return (date || new Date()) - this;
};
/**
* Set the value of year, month, day, hour, minute, second, millisecond of date instance using given configuration object.
* Example
<pre><code>
Date.today().set( { day: 20, month: 1 } )
new Date().set( { millisecond: 0 } )
</code></pre>
*
* @param {Object} Configuration object containing attributes (month, day, etc.)
* @return {Date} this
*/
$P.set = function (config) {
config = validateConfigObject.call(this, config);
var key;
for (key in config) {
if (hasOwnProperty.call(config, key)) {
var name = key.charAt(0).toUpperCase() + key.slice(1);
var addFunc, getFunc;
if (key !== "week" && key !== "month" && key !== "timezone" && key !== "timezoneOffset") {
name += "s";
}
addFunc = "add" + name;
getFunc = "get" + name;
if (key === "month") {
addFunc = addFunc + "s";
} else if (key === "year"){
getFunc = "getFullYear";
}
if (key !== "day" && key !== "timezone" && key !== "timezoneOffset" && key !== "week" && key !== "hour") {
this[addFunc](config[key] - this[getFunc]());
} else if ( key === "timezone"|| key === "timezoneOffset" || key === "week" || key === "hour") {
this["set"+name](config[key]);
}
}
}
// day has to go last because you can't validate the day without first knowing the month
if (config.day) {
this.addDays(config.day - this.getDate());
}
return this;
};
/**
* Moves the date to the first day of the month.
* @return {Date} this
*/
$P.moveToFirstDayOfMonth = function () {
return this.set({ day: 1 });
};
/**
* Moves the date to the last day of the month.
* @return {Date} this
*/
$P.moveToLastDayOfMonth = function () {
return this.set({ day: $D.getDaysInMonth(this.getFullYear(), this.getMonth())});
};
/**
* Converts the value of the current Date object to its equivalent string representation.
* Format Specifiers
* CUSTOM DATE AND TIME FORMAT STRINGS
* Format Description Example
* ------ --------------------------------------------------------------------------- -----------------------
* s The seconds of the minute between 0-59. "0" to "59"
* ss The seconds of the minute with leading zero if required. "00" to "59"
*
* m The minute of the hour between 0-59. "0" or "59"
* mm The minute of the hour with leading zero if required. "00" or "59"
*
* h The hour of the day between 1-12. "1" to "12"
* hh The hour of the day with leading zero if required. "01" to "12"
*
* H The hour of the day between 0-23. "0" to "23"
* HH The hour of the day with leading zero if required. "00" to "23"
*
* d The day of the month between 1 and 31. "1" to "31"
* dd The day of the month with leading zero if required. "01" to "31"
* ddd Abbreviated day name. Date.CultureInfo.abbreviatedDayNames. "Mon" to "Sun"
* dddd The full day name. Date.CultureInfo.dayNames. "Monday" to "Sunday"
*
* M The month of the year between 1-12. "1" to "12"
* MM The month of the year with leading zero if required. "01" to "12"
* MMM Abbreviated month name. Date.CultureInfo.abbreviatedMonthNames. "Jan" to "Dec"
* MMMM The full month name. Date.CultureInfo.monthNames. "January" to "December"
*
* yy The year as a two-digit number. "99" or "08"
* yyyy The full four digit year. "1999" or "2008"
*
* t Displays the first character of the A.M./P.M. designator. "A" or "P"
* Date.CultureInfo.amDesignator or Date.CultureInfo.pmDesignator
* tt Displays the A.M./P.M. designator. "AM" or "PM"
* Date.CultureInfo.amDesignator or Date.CultureInfo.pmDesignator
*
* S The ordinal suffix ("st, "nd", "rd" or "th") of the current day. "st, "nd", "rd" or "th"
*
* STANDARD DATE AND TIME FORMAT STRINGS
* Format Description Example
*------ --------------------------------------------------------------------------- -----------------------
* d The CultureInfo shortDate Format Pattern "M/d/yyyy"
* D The CultureInfo longDate Format Pattern "dddd, MMMM dd, yyyy"
* F The CultureInfo fullDateTime Format Pattern "dddd, MMMM dd, yyyy h:mm:ss tt"
* m The CultureInfo monthDay Format Pattern "MMMM dd"
* r The CultureInfo rfc1123 Format Pattern "ddd, dd MMM yyyy HH:mm:ss GMT"
* s The CultureInfo sortableDateTime Format Pattern "yyyy-MM-ddTHH:mm:ss"
* t The CultureInfo shortTime Format Pattern "h:mm tt"
* T The CultureInfo longTime Format Pattern "h:mm:ss tt"
* u The CultureInfo universalSortableDateTime Format Pattern "yyyy-MM-dd HH:mm:ssZ"
* y The CultureInfo yearMonth Format Pattern "MMMM, yyyy"
*
* @param {String} A format string consisting of one or more format spcifiers [Optional].
* @return {String} A string representation of the current Date object.
*/
var ord = function (n) {
switch (n * 1) {
case 1:
case 21:
case 31:
return "st";
case 2:
case 22:
return "nd";
case 3:
case 23:
return "rd";
default:
return "th";
}
};
var parseStandardFormats = function (format) {
var y, c = Date.CultureInfo.formatPatterns;
switch (format) {
case "d":
return this.toString(c.shortDate);
case "D":
return this.toString(c.longDate);
case "F":
return this.toString(c.fullDateTime);
case "m":
return this.toString(c.monthDay);
case "r":
case "R":
y = this.clone().addMinutes(this.getTimezoneOffset());
return y.toString(c.rfc1123) + " GMT";
case "s":
return this.toString(c.sortableDateTime);
case "t":
return this.toString(c.shortTime);
case "T":
return this.toString(c.longTime);
case "u":
y = this.clone().addMinutes(this.getTimezoneOffset());
return y.toString(c.universalSortableDateTime);
case "y":
return this.toString(c.yearMonth);
default:
return false;
}
};
var parseFormatStringsClosure = function (context) {
return function (m) {
if (m.charAt(0) === "\\") {
return m.replace("\\", "");
}
switch (m) {
case "hh":
return p(context.getHours() < 13 ? (context.getHours() === 0 ? 12 : context.getHours()) : (context.getHours() - 12));
case "h":
return context.getHours() < 13 ? (context.getHours() === 0 ? 12 : context.getHours()) : (context.getHours() - 12);
case "HH":
return p(context.getHours());
case "H":
return context.getHours();
case "mm":
return p(context.getMinutes());
case "m":
return context.getMinutes();
case "ss":
return p(context.getSeconds());
case "s":
return context.getSeconds();
case "yyyy":
return p(context.getFullYear(), 4);
case "yy":
return p(context.getFullYear());
case "y":
return context.getFullYear();
case "E":
case "dddd":
return Date.CultureInfo.dayNames[context.getDay()];
case "ddd":
return Date.CultureInfo.abbreviatedDayNames[context.getDay()];
case "dd":
return p(context.getDate());
case "d":
return context.getDate();
case "MMMM":
return Date.CultureInfo.monthNames[context.getMonth()];
case "MMM":
return Date.CultureInfo.abbreviatedMonthNames[context.getMonth()];
case "MM":
return p((context.getMonth() + 1));
case "M":
return context.getMonth() + 1;
case "t":
return context.getHours() < 12 ? Date.CultureInfo.amDesignator.substring(0, 1) : Date.CultureInfo.pmDesignator.substring(0, 1);
case "tt":
return context.getHours() < 12 ? Date.CultureInfo.amDesignator : Date.CultureInfo.pmDesignator;
case "S":
return ord(context.getDate());
case "W":
return context.getWeek();
case "WW":
return context.getISOWeek();
case "Q":
return "Q" + context.getQuarter();
case "q":
return String(context.getQuarter());
case "z":
return context.getTimezone();
case "Z":
case "X":
return Date.getTimezoneOffset(context.getTimezone());
case "ZZ": // Timezone offset in seconds
return context.getTimezoneOffset() * -60;
case "u":
return context.getDay();
case "L":
return ($D.isLeapYear(context.getFullYear())) ? 1 : 0;
case "B":
// Swatch Internet Time (.beats)
return "@"+((context.getUTCSeconds() + (context.getUTCMinutes()*60) + ((context.getUTCHours()+1)*3600))/86.4);
default:
return m;
}
};
};
$P.toString = function (format, ignoreStandards) {
// Standard Date and Time Format Strings. Formats pulled from CultureInfo file and
// may vary by culture.
if (!ignoreStandards && format && format.length === 1) {
output = parseStandardFormats.call(this, format);
if (output) {
return output;
}
}
var parseFormatStrings = parseFormatStringsClosure(this);
return format ? format.replace(/((\\)?(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|S|q|Q|WW?W?W?)(?![^\[]*\]))/g, parseFormatStrings).replace(/\[|\]/g, "") : this._toString();
};
}());
},{}],2:[function(require,module,exports){
(function () {
var $D = Date,
$P = $D.prototype,
p = function (s, l) {
if (!l) {
l = 2;
}
return ("000" + s).slice(l * -1);
};
if (typeof window !== "undefined" && typeof window.console !== "undefined" && typeof window.console.log !== "undefined") {
$D.console = console; // used only to raise non-critical errors if available
} else {
// set mock so we don't give errors.
$D.console = {
log: function(){},
error: function(){}
};
}
$D.Config = $D.Config || {};
$D.initOverloads = function() {
/**
* Overload of Date.now. Allows an alternate call for Date.now where it returns the
* current Date as an object rather than just milliseconds since the Unix Epoch.
*
* Also provides an implementation of now() for browsers (IE<9) that don't have it.
*
* Backwards compatible so with work with either:
* Date.now() [returns ms]
* or
* Date.now(true) [returns Date]
*/
if (!$D.now) {
$D._now = function now() {
return new Date().getTime();
};
} else if (!$D._now) {
$D._now = $D.now;
}
$D.now = function (returnObj) {
if (returnObj) {
return $D.present();
} else {
return $D._now();
}
};
if ( !$P.toISOString ) {
$P.toISOString = function() {
return this.getUTCFullYear() +
"-" + p(this.getUTCMonth() + 1) +
"-" + p(this.getUTCDate()) +
"T" + p(this.getUTCHours()) +
":" + p(this.getUTCMinutes()) +
":" + p(this.getUTCSeconds()) +
"." + String( (this.getUTCMilliseconds()/1000).toFixed(3)).slice(2, 5) +
"Z";
};
}
// private
if ( $P._toString === undefined ){
$P._toString = $P.toString;
}
};
$D.initOverloads();
/**
* Gets a date that is set to the current date. The time is set to the start of the day (00:00 or 12:00 AM).
* @return {Date} The current date.
*/
$D.today = function () {
return new Date().clearTime();
};
/**
* Gets a date that is set to the current date and time (same as new Date, but chainable)
* @return {Date} The current date.
*/
$D.present = function () {
return new Date();
};
/**
* Compares the first date to the second date and returns an number indication of their relative values.
* @param {Date} First Date object to compare [Required].
* @param {Date} Second Date object to compare to [Required].
* @return {Number} -1 = date1 is lessthan date2. 0 = values are equal. 1 = date1 is greaterthan date2.
*/
$D.compare = function (date1, date2) {
if (isNaN(date1) || isNaN(date2)) {
throw new Error(date1 + " - " + date2);
} else if (date1 instanceof Date && date2 instanceof Date) {
return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0;
} else {
throw new TypeError(date1 + " - " + date2);
}
};
/**
* Compares the first Date object to the second Date object and returns true if they are equal.
* @param {Date} First Date object to compare [Required]
* @param {Date} Second Date object to compare to [Required]
* @return {Boolean} true if dates are equal. false if they are not equal.
*/
$D.equals = function (date1, date2) {
return (date1.compareTo(date2) === 0);
};
/**
* Gets the language appropriate day name when given the day number(0-6)
* eg - 0 == Sunday
* @return {String} The day name
*/
$D.getDayName = function (n) {
return Date.CultureInfo.dayNames[n];
};
/**
* Gets the day number (0-6) if given a CultureInfo specific string which is a valid dayName, abbreviatedDayName or shortestDayName (two char).
* @param {String} The name of the day (eg. "Monday, "Mon", "tuesday", "tue", "We", "we").
* @return {Number} The day number
*/
$D.getDayNumberFromName = function (name) {
var n = Date.CultureInfo.dayNames, m = Date.CultureInfo.abbreviatedDayNames, o = Date.CultureInfo.shortestDayNames, s = name.toLowerCase();
for (var i = 0; i < n.length; i++) {
if (n[i].toLowerCase() === s || m[i].toLowerCase() === s || o[i].toLowerCase() === s) {
return i;
}
}
return -1;
};
/**
* Gets the month number (0-11) if given a Culture Info specific string which is a valid monthName or abbreviatedMonthName.
* @param {String} The name of the month (eg. "February, "Feb", "october", "oct").
* @return {Number} The day number
*/
$D.getMonthNumberFromName = function (name) {
var n = Date.CultureInfo.monthNames, m = Date.CultureInfo.abbreviatedMonthNames, s = name.toLowerCase();
for (var i = 0; i < n.length; i++) {
if (n[i].toLowerCase() === s || m[i].toLowerCase() === s) {
return i;
}
}
return -1;
};
/**
* Gets the language appropriate month name when given the month number(0-11)
* eg - 0 == January
* @return {String} The month name
*/
$D.getMonthName = function (n) {
return Date.CultureInfo.monthNames[n];
};
/**
* Determines if the current date instance is within a LeapYear.
* @param {Number} The year.
* @return {Boolean} true if date is within a LeapYear, otherwise false.
*/
$D.isLeapYear = function (year) {
return ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0);
};
/**
* Gets the number of days in the month, given a year and month value. Automatically corrects for LeapYear.
* @param {Number} The year.
* @param {Number} The month (0-11).
* @return {Number} The number of days in the month.
*/
$D.getDaysInMonth = function (year, month) {
if (!month && $D.validateMonth(year)) {
month = year;
year = Date.today().getFullYear();
}
return [31, ($D.isLeapYear(year) ? 29 : 28), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month];
};
$P.getDaysInMonth = function () {
return $D.getDaysInMonth(this.getFullYear(), this.getMonth());
};
$D.getTimezoneAbbreviation = function (offset, dst) {
var p, n = (dst || false) ? Date.CultureInfo.abbreviatedTimeZoneDST : Date.CultureInfo.abbreviatedTimeZoneStandard;
for (p in n) {
if (n.hasOwnProperty(p)) {
if (n[p] === offset) {
return p;
}
}
}
return null;
};
$D.getTimezoneOffset = function (name, dst) {
var i, a =[], z = Date.CultureInfo.timezones;
if (!name) { name = (new Date()).getTimezone();}
for (i = 0; i < z.length; i++) {
if (z[i].name === name.toUpperCase()) {
a.push(i);
}
}
if (!z[a[0]]) {
return null;
}
if (a.length === 1 || !dst) {
return z[a[0]].offset;
} else {
for (i=0; i < a.length; i++) {
if (z[a[i]].dst) {
return z[a[i]].offset;
}
}
}
};
$D.getQuarter = function (d) {
d = d || new Date(); // If no date supplied, use today
var q = [1,2,3,4];
return q[Math.floor(d.getMonth() / 3)]; // ~~~ is a bitwise op. Faster than Math.floor
};
$D.getDaysLeftInQuarter = function (d) {
d = d || new Date();
var qEnd = new Date(d);
qEnd.setMonth(qEnd.getMonth() + 3 - qEnd.getMonth() % 3, 0);
return Math.floor((qEnd - d) / 8.64e7);
};
// private
var validate = function (n, min, max, name) {
name = name ? name : "Object";
if (typeof n === "undefined") {
return false;
} else if (typeof n !== "number") {
throw new TypeError(n + " is not a Number.");
} else if (n < min || n > max) {
// As failing validation is *not* an exceptional circumstance
// lets not throw a RangeError Exception here.
// It's semantically correct but it's not sensible.
return false;
}
return true;
};
/**
* Validates the number is within an acceptable range for milliseconds [0-999].
* @param {Number} The number to check if within range.
* @return {Boolean} true if within range, otherwise false.
*/
$D.validateMillisecond = function (value) {
return validate(value, 0, 999, "millisecond");
};
/**
* Validates the number is within an acceptable range for seconds [0-59].
* @param {Number} The number to check if within range.
* @return {Boolean} true if within range, otherwise false.
*/
$D.validateSecond = function (value) {
return validate(value, 0, 59, "second");
};
/**
* Validates the number is within an acceptable range for minutes [0-59].
* @param {Number} The number to check if within range.
* @return {Boolean} true if within range, otherwise false.
*/
$D.validateMinute = function (value) {
return validate(value, 0, 59, "minute");
};
/**
* Validates the number is within an acceptable range for hours [0-23].
* @param {Number} The number to check if within range.
* @return {Boolean} true if within range, otherwise false.
*/
$D.validateHour = function (value) {
return validate(value, 0, 23, "hour");
};
/**
* Validates the number is within an acceptable range for the days in a month [0-MaxDaysInMonth].
* @param {Number} The number to check if within range.
* @return {Boolean} true if within range, otherwise false.
*/
$D.validateDay = function (value, year, month) {
if (year === undefined || year === null || month === undefined || month === null) { return false;}
return validate(value, 1, $D.getDaysInMonth(year, month), "day");
};
/**
* Validates the number is within an acceptable range for months [0-11].
* @param {Number} The number to check if within range.
* @return {Boolean} true if within range, otherwise false.
*/
$D.validateWeek = function (value) {
return validate(value, 0, 53, "week");
};
/**
* Validates the number is within an acceptable range for months [0-11].
* @param {Number} The number to check if within range.
* @return {Boolean} true if within range, otherwise false.
*/
$D.validateMonth = function (value) {
return validate(value, 0, 11, "month");
};
/**
* Validates the number is within an acceptable range for years.
* @param {Number} The number to check if within range.
* @return {Boolean} true if within range, otherwise false.
*/
$D.validateYear = function (value) {
/**
* Per ECMAScript spec the range of times supported by Date objects is
* exactly -100,000,000 days to +100,000,000 days measured relative to
* midnight at the beginning of 01 January, 1970 UTC.
* This gives a range of 8,640,000,000,000,000 milliseconds to either
* side of 01 January, 1970 UTC.
*
* Earliest possible date: Tue, 20 Apr 271,822 B.C. 00:00:00 UTC
* Latest possible date: Sat, 13 Sep 275,760 00:00:00 UTC
*/
return validate(value, -271822, 275760, "year");
};
$D.validateTimezone = function(value) {
var timezones = {"ACDT":1,"ACST":1,"ACT":1,"ADT":1,"AEDT":1,"AEST":1,"AFT":1,"AKDT":1,"AKST":1,"AMST":1,"AMT":1,"ART":1,"AST":1,"AWDT":1,"AWST":1,"AZOST":1,"AZT":1,"BDT":1,"BIOT":1,"BIT":1,"BOT":1,"BRT":1,"BST":1,"BTT":1,"CAT":1,"CCT":1,"CDT":1,"CEDT":1,"CEST":1,"CET":1,"CHADT":1,"CHAST":1,"CHOT":1,"ChST":1,"CHUT":1,"CIST":1,"CIT":1,"CKT":1,"CLST":1,"CLT":1,"COST":1,"COT":1,"CST":1,"CT":1,"CVT":1,"CWST":1,"CXT":1,"DAVT":1,"DDUT":1,"DFT":1,"EASST":1,"EAST":1,"EAT":1,"ECT":1,"EDT":1,"EEDT":1,"EEST":1,"EET":1,"EGST":1,"EGT":1,"EIT":1,"EST":1,"FET":1,"FJT":1,"FKST":1,"FKT":1,"FNT":1,"GALT":1,"GAMT":1,"GET":1,"GFT":1,"GILT":1,"GIT":1,"GMT":1,"GST":1,"GYT":1,"HADT":1,"HAEC":1,"HAST":1,"HKT":1,"HMT":1,"HOVT":1,"HST":1,"ICT":1,"IDT":1,"IOT":1,"IRDT":1,"IRKT":1,"IRST":1,"IST":1,"JST":1,"KGT":1,"KOST":1,"KRAT":1,"KST":1,"LHST":1,"LINT":1,"MAGT":1,"MART":1,"MAWT":1,"MDT":1,"MET":1,"MEST":1,"MHT":1,"MIST":1,"MIT":1,"MMT":1,"MSK":1,"MST":1,"MUT":1,"MVT":1,"MYT":1,"NCT":1,"NDT":1,"NFT":1,"NPT":1,"NST":1,"NT":1,"NUT":1,"NZDT":1,"NZST":1,"OMST":1,"ORAT":1,"PDT":1,"PET":1,"PETT":1,"PGT":1,"PHOT":1,"PHT":1,"PKT":1,"PMDT":1,"PMST":1,"PONT":1,"PST":1,"PYST":1,"PYT":1,"RET":1,"ROTT":1,"SAKT":1,"SAMT":1,"SAST":1,"SBT":1,"SCT":1,"SGT":1,"SLST":1,"SRT":1,"SST":1,"SYOT":1,"TAHT":1,"THA":1,"TFT":1,"TJT":1,"TKT":1,"TLT":1,"TMT":1,"TOT":1,"TVT":1,"UCT":1,"ULAT":1,"UTC":1,"UYST":1,"UYT":1,"UZT":1,"VET":1,"VLAT":1,"VOLT":1,"VOST":1,"VUT":1,"WAKT":1,"WAST":1,"WAT":1,"WEDT":1,"WEST":1,"WET":1,"WST":1,"YAKT":1,"YEKT":1,"Z":1};
return (timezones[value] === 1);
};
$D.validateTimezoneOffset= function(value) {
// timezones go from +14hrs to -12hrs, the +X hours are negative offsets.
return (value > -841 && value < 721);
};
}());
},{}],3:[function(require,module,exports){
(function () {
var $D = Date,
$P = $D.prototype,
// $C = $D.CultureInfo, // not used atm
p = function (s, l) {
if (!l) {
l = 2;
}
return ("000" + s).slice(l * -1);
};
/**
* Converts a PHP format string to Java/.NET format string.
* A PHP format string can be used with ._format or .format.
* A Java/.NET format string can be used with .toString().
* The .parseExact function will only accept a Java/.NET format string
*
* Example
* var f1 = "%m/%d/%y"
* var f2 = Date.normalizeFormat(f1); // "MM/dd/yy"
*
* new Date().format(f1); // "04/13/08"
* new Date()._format(f1); // "04/13/08"
* new Date().toString(f2); // "04/13/08"
*
* var date = Date.parseExact("04/13/08", f2); // Sun Apr 13 2008
*
* @param {String} A PHP format string consisting of one or more format spcifiers.
* @return {String} The PHP format converted to a Java/.NET format string.
*/
var normalizerSubstitutions = {
"d" : "dd",
"%d": "dd",
"D" : "ddd",
"%a": "ddd",
"j" : "dddd",
"l" : "dddd",
"%A": "dddd",
"S" : "S",
"F" : "MMMM",
"%B": "MMMM",
"m" : "MM",
"%m": "MM",
"M" : "MMM",
"%b": "MMM",
"%h": "MMM",
"n" : "M",
"Y" : "yyyy",
"%Y": "yyyy",
"y" : "yy",
"%y": "yy",
"g" : "h",
"%I": "h",
"G" : "H",
"h" : "hh",
"H" : "HH",
"%H": "HH",
"i" : "mm",
"%M": "mm",
"s" : "ss",
"%S": "ss",
"%r": "hh:mm tt",
"%R": "H:mm",
"%T": "H:mm:ss",
"%X": "t",
"%x": "d",
"%e": "d",
"%D": "MM/dd/yy",
"%n": "\\n",
"%t": "\\t",
"e" : "z",
"T" : "z",
"%z": "z",
"%Z": "z",
"Z" : "ZZ",
"N" : "u",
"w" : "u",
"%w": "u",
"W" : "W",
"%V": "W"
};
var normalizer = {
substitutes: function (m) {
return normalizerSubstitutions[m];
},
interpreted: function (m, x) {
var y;
switch (m) {
case "%u":
return x.getDay() + 1;
case "z":
return x.getOrdinalNumber();
case "%j":
return p(x.getOrdinalNumber(), 3);
case "%U":
var d1 = x.clone().set({month: 0, day: 1}).addDays(-1).moveToDayOfWeek(0),
d2 = x.clone().addDays(1).moveToDayOfWeek(0, -1);
return (d2 < d1) ? "00" : p((d2.getOrdinalNumber() - d1.getOrdinalNumber()) / 7 + 1);
case "%W":
return p(x.getWeek());
case "t":
return $D.getDaysInMonth(x.getFullYear(), x.getMonth());
case "o":
case "%G":
return x.setWeek(x.getISOWeek()).toString("yyyy");
case "%g":
return x._format("%G").slice(-2);
case "a":
case "%p":
return t("tt").toLowerCase();
case "A":
return t("tt").toUpperCase();
case "u":
return p(x.getMilliseconds(), 3);
case "I":
return (x.isDaylightSavingTime()) ? 1 : 0;
case "O":
return x.getUTCOffset();
case "P":
y = x.getUTCOffset();
return y.substring(0, y.length - 2) + ":" + y.substring(y.length - 2);
case "B":
var now = new Date();
return Math.floor(((now.getHours() * 3600) + (now.getMinutes() * 60) + now.getSeconds() + (now.getTimezoneOffset() + 60) * 60) / 86.4);
case "c":
return x.toISOString().replace(/\"/g, "");
case "U":
return $D.strtotime("now");
case "%c":
return t("d") + " " + t("t");
case "%C":
return Math.floor(x.getFullYear() / 100 + 1);
}
},
shouldOverrideDefaults: function (m) {
switch (m) {
case "%e":
return true;
default:
return false;
}
},
parse: function (m, context) {
var formatString, c = context || new Date();
formatString = normalizer.substitutes(m);
if (formatString) {
return formatString;
}
formatString = normalizer.interpreted(m, c);
if (formatString) {
return formatString;
} else {
return m;
}
}
};
$D.normalizeFormat = function (format, context) {
return format.replace(/(%|\\)?.|%%/g, function(t){
return normalizer.parse(t, context);
});
};
/**
* Format a local Unix timestamp according to locale settings
*
* Example:
* Date.strftime("%m/%d/%y", new Date()); // "04/13/08"
* Date.strftime("c", "2008-04-13T17:52:03Z"); // "04/13/08"
*
* @param {String} A format string consisting of one or more format spcifiers [Optional].
* @param {Number|String} The number representing the number of seconds that have elapsed since January 1, 1970 (local time).
* @return {String} A string representation of the current Date object.
*/
$D.strftime = function (format, time) {
var d = Date.parse(time);
return d._format(format);
};
/**
* Parse any textual datetime description into a Unix timestamp.
* A Unix timestamp is the number of seconds that have elapsed since January 1, 1970 (midnight UTC/GMT).
*
* Example:
* Date.strtotime("04/13/08"); // 1208044800
* Date.strtotime("1970-01-01T00:00:00Z"); // 0
*
* @param {String} A format string consisting of one or more format spcifiers [Optional].
* @param {Object} A string or date object.
* @return {String} A string representation of the current Date object.
*/
$D.strtotime = function (time) {
var d = $D.parse(time);
return Math.round($D.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds()) / 1000);
};
/**
* Converts the value of the current Date object to its equivalent string representation using a PHP/Unix style of date format specifiers.
* Format Specifiers
* Format Description Example
* ------ --------------------------------------------------------------------------- -----------------------
* %a abbreviated weekday name according to the current localed "Mon" through "Sun"
* %A full weekday name according to the current localed "Sunday" through "Saturday"
* %b abbreviated month name according to the current localed "Jan" through "Dec"
* %B full month name according to the current locale "January" through "December"
* %c preferred date and time representation for the current locale "4/13/2008 12:33 PM"
* %C century number (the year divided by 100 and truncated to an integer) "00" to "99"
* %d day of the month as a decimal number "01" to "31"
* %D same as %m/%d/%y "04/13/08"
* %e day of the month as a decimal number, a single digit is preceded by a space "1" to "31"
* %g like %G, but without the century "08"
* %G The 4-digit year corresponding to the ISO week number (see %V). "2008"
* This has the same format and value as %Y, except that if the ISO week number
* belongs to the previous or next year, that year is used instead.
* %h same as %b "Jan" through "Dec"
* %H hour as a decimal number using a 24-hour clock. "00" to "23"
* %I hour as a decimal number using a 12-hour clock. "01" to "12"
* %j day of the year as a decimal number. "001" to "366"
* %m month as a decimal number. "01" to "12"
* %M minute as a decimal number. "00" to "59"
* %n newline character "\n"
* %p either "am" or "pm" according to the given time value, or the "am" or "pm"
* corresponding strings for the current locale.
* %r time in a.m. and p.m. notation "8:44 PM"
* %R time in 24 hour notation "20:44"
* %S second as a decimal number "00" to "59"
* %t tab character "\t"
* %T current time, equal to %H:%M:%S "12:49:11"
* %u weekday as a decimal number ["1", "7"], with "1" representing Monday "1" to "7"
* %U week number of the current year as a decimal number, starting with the "0" to ("52" or "53")
* first Sunday as the first day of the first week
* %V The ISO 8601:1988 week number of the current year as a decimal number, "00" to ("52" or "53")
* range 01 to 53, where week 1 is the first week that has at least 4 days
* in the current year, and with Monday as the first day of the week.
* (Use %G or %g for the year component that corresponds to the week number
* for the specified timestamp.)
* %W week number of the current year as a decimal number, starting with the "00" to ("52" or "53")
* first Monday as the first day of the first week
* %w day of the week as a decimal, Sunday being "0" "0" to "6"
* %x preferred date representation for the current locale without the time "4/13/2008"
* %X preferred time representation for the current locale without the date "12:53:05"
* %y year as a decimal number without a century "00" "99"
* %Y year as a decimal number including the century "2008"
* %Z time zone or name or abbreviation "UTC", "EST", "PST"
* %z same as %Z
* %% a literal "%" characters "%"
* d Day of the month, 2 digits with leading zeros "01" to "31"
* D A textual representation of a day, three letters "Mon" through "Sun"
* j Day of the month without leading zeros "1" to "31"
* l A full textual representation of the day of the week (lowercase "L") "Sunday" through "Saturday"
* N ISO-8601 numeric representation of the day of the week (added in PHP 5.1.0) "1" (for Monday) through "7" (for Sunday)
* S English ordinal suffix for the day of the month, 2 characters "st", "nd", "rd" or "th". Works well with j
* w Numeric representation of the day of the week "0" (for Sunday) through "6" (for Saturday)
* z The day of the year (starting from "0") "0" through "365"
* W ISO-8601 week number of year, weeks starting on Monday "00" to ("52" or "53")
* F A full textual representation of a month, such as January or March "January" through "December"
* m Numeric representation of a month, with leading zeros "01" through "12"
* M A short textual representation of a month, three letters "Jan" through "Dec"
* n Numeric representation of a month, without leading zeros "1" through "12"
* t Number of days in the given month "28" through "31"
* L Whether it's a leap year "1" if it is a leap year, "0" otherwise
* o ISO-8601 year number. This has the same value as Y, except that if the "2008"
* ISO week number (W) belongs to the previous or next year, that year
* is used instead.
* Y A full numeric representation of a year, 4 digits "2008"
* y A two digit representation of a year "08"
* a Lowercase Ante meridiem and Post meridiem "am" or "pm"
* A Uppercase Ante meridiem and Post meridiem "AM" or "PM"
* B Swatch Internet time "000" through "999"
* g 12-hour format of an hour without leading zeros "1" through "12"
* G 24-hour format of an hour without leading zeros "0" through "23"
* h 12-hour format of an hour with leading zeros "01" through "12"
* H 24-hour format of an hour with leading zeros "00" through "23"
* i Minutes with leading zeros "00" to "59"
* s Seconds, with leading zeros "00" through "59"
* u Milliseconds "54321"
* e Timezone identifier "UTC", "EST", "PST"
* I Whether or not the date is in daylight saving time (uppercase i) "1" if Daylight Saving Time, "0" otherwise
* O Difference to Greenwich time (GMT) in hours "+0200", "-0600"
* P Difference to Greenwich time (GMT) with colon between hours and minutes "+02:00", "-06:00"
* T Timezone abbreviation "UTC", "EST", "PST"
* Z Timezone offset in seconds. The offset for timezones west of UTC is "-43200" through "50400"
* always negative, and for those east of UTC is always positive.
* c ISO 8601 date "2004-02-12T15:19:21+00:00"
* r RFC 2822 formatted date "Thu, 21 Dec 2000 16:01:07 +0200"
* U Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT) "0"
* @param {String} A format string consisting of one or more format spcifiers [Optional].
* @return {String} A string representation of the current Date object.
*/
var formatReplace = function (context) {
return function (m) {
var formatString, override = false;
if (m.charAt(0) === "\\" || m.substring(0, 2) === "%%") {
return m.replace("\\", "").replace("%%", "%");
}
override = normalizer.shouldOverrideDefaults(m);
formatString = $D.normalizeFormat(m, context);
if (formatString) {
return context.toString(formatString, override);
}
};
};
$P._format = function (format) {
var formatter = formatReplace(this);
if (!format) {
return this._toString();
} else {
return format.replace(/(%|\\)?.|%%/g, formatter);
}
};
if (!$P.format) {
$P.format = $P._format;
}
}());
},{}],4:[function(require,module,exports){
(function () {
"use strict";
Date.Parsing = {
Exception: function (s) {
this.message = "Parse error at '" + s.substring(0, 10) + " ...'";
}
};
var $P = Date.Parsing;
var dayOffsets = {
standard: [0,31,59,90,120,151,181,212,243,273,304,334],
leap: [0,31,60,91,121,152,182,213,244,274,305,335]
};
$P.isLeapYear = function(year) {
return ((year % 4 === 0) && (year % 100 !== 0)) || (year % 400 === 0);
};
var utils = {
multiReplace : function (str, hash ) {
var key;
for (key in hash) {
if (Object.prototype.hasOwnProperty.call(hash, key)) {
var regex;
if (typeof hash[key] === "function") {
} else {
regex = (hash[key] instanceof RegExp) ? hash[key] : new RegExp(hash[key], "g");
}
str = str.replace(regex, key);
}
}
return str;
},
getDayOfYearFromWeek : function (obj) {
var d, jan4, offset;
obj.weekDay = (!obj.weekDay && obj.weekDay !== 0) ? 1 : obj.weekDay;
d = new Date(obj.year, 0, 4);
jan4 = d.getDay() === 0 ? 7 : d.getDay(); // JS is 0 indexed on Sunday.
offset = jan4+3;
obj.dayOfYear = ((obj.week * 7) + (obj.weekDay === 0 ? 7 : obj.weekDay))-offset;
return obj;
},
getDayOfYear : function (obj, dayOffset) {
if (!obj.dayOfYear) {
obj = utils.getDayOfYearFromWeek(obj);
}
for (var i=0;i <= dayOffset.length;i++) {
if (obj.dayOfYear < dayOffset[i] || i === dayOffset.length) {
obj.day = obj.day ? obj.day : (obj.dayOfYear - dayOffset[i-1]);
break;
} else {
obj.month = i;
}
}
return obj;
},
adjustForTimeZone : function (obj, date) {
var offset;
if (obj.zone.toUpperCase() === "Z" || (obj.zone_hours === 0 && obj.zone_minutes === 0)) {
// it's UTC/GML so work out the current timeszone offset
offset = -date.getTimezoneOffset();
} else {
offset = (obj.zone_hours*60) + (obj.zone_minutes || 0);
if (obj.zone_sign === "+") {
offset *= -1;
}
offset -= date.getTimezoneOffset();
}
date.setMinutes(date.getMinutes()+offset);
return date;
},
setDefaults : function (obj) {
obj.year = obj.year || Date.today().getFullYear();
obj.hours = obj.hours || 0;
obj.minutes = obj.minutes || 0;
obj.seconds = obj.seconds || 0;
obj.milliseconds = obj.milliseconds || 0;
if (!(!obj.month && (obj.week || obj.dayOfYear))) {
// if we have a month, or if we don't but don't have the day calculation data
obj.month = obj.month || 0;
obj.day = obj.day || 1;
}
return obj;
},
dataNum: function (data, mod, explict, postProcess) {
var dataNum = data*1;
if (mod) {
if (postProcess) {
return data ? mod(data)*1 : data;
} else {
return data ? mod(dataNum) : data;
}
} else if (!explict){
return data ? dataNum : data;
} else {
return (data && typeof data !== "undefined") ? dataNum : data;
}
},
timeDataProcess: function (obj) {
var timeObj = {};
for (var x in obj.data) {
if (obj.data.hasOwnProperty(x)) {
timeObj[x] = obj.ignore[x] ? obj.data[x] : utils.dataNum(obj.data[x], obj.mods[x], obj.explict[x], obj.postProcess[x]);
}
}
if (obj.data.secmins) {
obj.data.secmins = obj.data.secmins.replace(",", ".") * 60;
if (!timeObj.minutes) {
timeObj.minutes = obj.data.secmins;
} else if (!timeObj.seconds) {
timeObj.seconds = obj.data.secmins;
}
delete obj.secmins;
}
return timeObj;
},
buildTimeObjectFromData: function (data) {
var time = utils.timeDataProcess({
data: {
year : data[1],
month : data[5],
day : data[7],
week : data[8],
dayOfYear : data[10],
hours : data[15],
zone_hours : data[23],
zone_minutes : data[24],
zone : data[21],
zone_sign : data[22],
weekDay : data[9],
minutes: data[16],
seconds: data[19],
milliseconds: data[20],
secmins: data[18]
},
mods: {
month: function(data) {
return data-1;
},
weekDay: function (data) {
data = Math.abs(data);
return (data === 7 ? 0 : data);
},
minutes: function (data) {
return data.replace(":","");
},
seconds: function (data) {
return Math.floor( (data.replace(":","").replace(",","."))*1 );
},
milliseconds: function (data) {
return (data.replace(",",".")*1000);
}
},
postProcess: {
minutes: true,
seconds: true,
milliseconds: true
},
explict: {
zone_hours: true,
zone_minutes: true
},
ignore: {
zone: true,
zone_sign: true,
secmins: true
}
});
return time;
},
addToHash: function (hash, keys, data) {
keys = keys;
data = data;
var len = keys.length;
for (var i = 0; i < len; i++) {
hash[keys[i]] = data[i];
}
return hash;
},
combineRegex: function (r1, r2) {
return new RegExp("(("+r1.source+")\\s("+r2.source+"))");
},
getDateNthString: function(add, last, inc){
if (add) {
return Date.today().addDays(inc).toString("d");
} else if (last) {
return Date.today().last()[inc]().toString("d");
}
},
buildRegexData: function (array) {
var arr = [];
var len = array.length;
for (var i=0; i < len; i++) {
if (Object.prototype.toString.call(array[i]) === '[object Array]') { // oldIE compat version of Array.isArray
arr.push(this.combineRegex(array[i][0], array[i][1]));
} else {
arr.push(array[i]);
}
}
return arr;
}
};
$P.processTimeObject = function (obj) {
var date, dayOffset;
utils.setDefaults(obj);
dayOffset = ($P.isLeapYear(obj.year)) ? dayOffsets.leap : dayOffsets.standard;
if (!obj.month && (obj.week || obj.dayOfYear)) {
utils.getDayOfYear(obj, dayOffset);
} else {
obj.dayOfYear = dayOffset[obj.month] + obj.day;
}
date = new Date(obj.year, obj.month, obj.day, obj.hours, obj.minutes, obj.seconds, obj.milliseconds);
if (obj.zone) {
utils.adjustForTimeZone(obj, date); // adjust (and calculate) for timezone
}
return date;
};
$P.ISO = {
regex : /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(\3([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-3])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-4])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?(\17[0-5]\d([\.,]\d+)?)?\s?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/,
parse : function (s) {
var time, data = s.match(this.regex);
if (!data || !data.length) {
return null;
}
time = utils.buildTimeObjectFromData(data);
if (!time.year || (!time.year && (!time.month && !time.day) && (!time.week && !time.dayOfYear)) ) {
return null;
}
return $P.processTimeObject(time);
}
};
$P.Numeric = {
isNumeric: function (e){return!isNaN(parseFloat(e))&&isFinite(e);},
regex: /\b([0-1]?[0-9])([0-3]?[0-9])([0-2]?[0-9]?[0-9][0-9])\b/i,
parse: function (s) {
var data, i,
time = {},
order = Date.CultureInfo.dateElementOrder.split("");
if (!(this.isNumeric(s)) || // if it's non-numeric OR
(s[0] === "+" && s[0] === "-")) { // It's an arithmatic string (eg +/-1000)
return null;
}
if (s.length < 5 && s.indexOf(".") < 0 && s.indexOf("/") < 0) { // assume it's just a year.
time.year = s;
return $P.processTimeObject(time);
}
data = s.match(this.regex);
if (!data || !data.length) {
return null;
}
for (i=0; i < order.length; i++) {
switch(order[i]) {
case "d":
time.day = data[i+1];
break;
case "m":
time.month = (data[i+1]-1);
break;
case "y":
time.year = data[i+1];
break;
}
}
return $P.processTimeObject(time);
}
};
$P.Normalizer = {
regexData: function () {
var $R = Date.CultureInfo.regexPatterns;
return utils.buildRegexData([
$R.tomorrow,
$R.yesterday,
[$R.past, $R.mon],
[$R.past, $R.tue],
[$R.past, $R.wed],
[$R.past, $R.thu],
[$R.past, $R.fri],
[$R.past, $R.sat],
[$R.past, $R.sun]
]);
},
basicReplaceHash : function() {
var $R = Date.CultureInfo.regexPatterns;
return {
"January": $R.jan.source,
"February": $R.feb,
"March": $R.mar,
"April": $R.apr,
"May": $R.may,
"June": $R.jun,
"July": $R.jul,
"August": $R.aug,
"September": $R.sep,
"October": $R.oct,
"November": $R.nov,
"December": $R.dec,
"": /\bat\b/gi,
" ": /\s{2,}/,
"am": $R.inTheMorning,
"9am": $R.thisMorning,
"pm": $R.inTheEvening,
"7pm":$R.thisEvening
};
},
keys : function(){
return [
utils.getDateNthString(true, false, 1), // tomorrow
utils.getDateNthString(true, false, -1), // yesterday
utils.getDateNthString(false, true, "monday"), //last mon
utils.getDateNthString(false, true, "tuesday"), //last tues
utils.getDateNthString(false, true, "wednesday"), //last wed
utils.getDateNthString(false, true, "thursday"), //last thurs
utils.getDateNthString(false, true, "friday"), //last fri
utils.getDateNthString(false, true, "saturday"), //last sat
utils.getDateNthString(false, true, "sunday") //last sun
];
},
buildRegexFunctions: function () {
var $R = Date.CultureInfo.regexPatterns;
var __ = Date.i18n.__;
var tomorrowRE = new RegExp("(\\b\\d\\d?("+__("AM")+"|"+__("PM")+")? )("+$R.tomorrow.source.slice(1)+")", "i"); // adapted tomorrow regex for AM PM relative dates
var todayRE = new RegExp($R.today.source + "(?!\\s*([+-]))\\b"); // today, but excludes the math operators (eg "today + 2h")
this.replaceFuncs = [
[todayRE, function (full) {
return (full.length > 1) ? Date.today().toString("d") : full;
}],
[tomorrowRE,
function(full, m1) {
var t = Date.today().addDays(1).toString("d");
return (t + " " + m1);
}],
[$R.amThisMorning, function(str, am){return am;}],
[$R.pmThisEvening, function(str, pm){return pm;}]
];
},
buildReplaceData: function () {
this.buildRegexFunctions();
this.replaceHash = utils.addToHash(this.basicReplaceHash(), this.keys(), this.regexData());
},
stringReplaceFuncs: function (s) {
for (var i=0; i < this.replaceFuncs.length; i++) {
s = s.replace(this.replaceFuncs[i][0], this.replaceFuncs[i][1]);
}
return s;
},
parse: function (s) {
s = this.stringReplaceFuncs(s);
s = utils.multiReplace(s, this.replaceHash);
try {
var n = s.split(/([\s\-\.\,\/\x27]+)/);
if (n.length === 3 &&
$P.Numeric.isNumeric(n[0]) &&
$P.Numeric.isNumeric(n[2]) &&
(n[2].length >= 4)) {
// ok, so we're dealing with x/year. But that's not a full date.
// This fixes wonky dateElementOrder parsing when set to dmy order.
if (Date.CultureInfo.dateElementOrder[0] === "d") {
s = "1/" + n[0] + "/" + n[2]; // set to 1st of month and normalize the seperator
}
}
} catch (e) {}
return s;
}
};
$P.Normalizer.buildReplaceData();
}());
},{}],5:[function(require,module,exports){
(function () {
var $D = Date;
var lang = Date.CultureStrings ? Date.CultureStrings.lang : null;
var loggedKeys = {}; // for debug purposes.
var getText = {
getFromKey: function (key, countryCode) {
var output;
if (Date.CultureStrings && Date.CultureStrings[countryCode] && Date.CultureStrings[countryCode][key]) {
output = Date.CultureStrings[countryCode][key];
} else {
output = getText.buildFromDefault(key);
}
if (key.charAt(0) === "/") { // Assume it's a regex
output = getText.buildFromRegex(key, countryCode);
}
return output;
},
getFromObjectValues: function (obj, countryCode) {
var key, output = {};
for(key in obj) {
if (obj.hasOwnProperty(key)) {
output[key] = getText.getFromKey(obj[key], countryCode);
}
}
return output;
},
getFromObjectKeys: function (obj, countryCode) {
var key, output = {};
for(key in obj) {
if (obj.hasOwnProperty(key)) {
output[getText.getFromKey(key, countryCode)] = obj[key];
}
}
return output;
},
getFromArray: function (arr, countryCode) {
var output = [];
for (var i=0; i < arr.length; i++){
if (i in arr) {
output[i] = getText.getFromKey(arr[i], countryCode);
}
}
return output;
},
buildFromDefault: function (key) {
var output, length, split, last;
switch(key) {
case "name":
output = "en-US";
break;
case "englishName":
output = "English (United States)";
break;
case "nativeName":
output = "English (United States)";
break;
case "twoDigitYearMax":
output = 2049;
break;
case "firstDayOfWeek":
output = 0;
break;
default:
output = key;
split = key.split("_");
length = split.length;
if (length > 1 && key.charAt(0) !== "/") {
// if the key isn't a regex and it has a split.
last = split[(length - 1)].toLowerCase();
if (last === "initial" || last === "abbr") {
output = split[0];
}
}
break;
}
return output;
},
buildFromRegex: function (key, countryCode) {
var output;
if (Date.CultureStrings && Date.CultureStrings[countryCode] && Date.CultureStrings[countryCode][key]) {
output = new RegExp(Date.CultureStrings[countryCode][key], "i");
} else {
output = new RegExp(key.replace(new RegExp("/", "g"),""), "i");
}
return output;
}
};
var shallowMerge = function (obj1, obj2) {
for (var attrname in obj2) {
if (obj2.hasOwnProperty(attrname)) {
obj1[attrname] = obj2[attrname];
}
}
};
var __ = function (key, language) {
var countryCode = (language) ? language : lang;
loggedKeys[key] = key;
if (typeof key === "object") {
if (key instanceof Array) {
return getText.getFromArray(key, countryCode);
} else {
return getText.getFromObjectKeys(key, countryCode);
}
} else {
return getText.getFromKey(key, countryCode);
}
};
var loadI18nScript = function (code) {
// paatterned after jQuery's getScript.
var url = Date.Config.i18n + code + ".js";
var head = document.getElementsByTagName("head")[0] || document.documentElement;
var script = document.createElement("script");
script.src = url;
var completed = false;
var events = {
done: function (){} // placeholder function
};
// Attach handlers for all browsers
script.onload = script.onreadystatechange = function() {
if ( !completed && (!this.readyState || this.readyState === "loaded" || this.readyState === "complete") ) {
events.done();
head.removeChild(script);
}
};
setTimeout(function() {
head.insertBefore(script, head.firstChild);
}, 0); // allows return to execute first
return {
done: function (cb) {
events.done = function() {
if (cb) {
setTimeout(cb,0);
}
};
}
};
};
var buildInfo = {
buildFromMethodHash: function (obj) {
var key;
for(key in obj) {
if (obj.hasOwnProperty(key)) {
obj[key] = buildInfo[obj[key]]();
}
}
return obj;
},
timeZoneDST: function () {
var DST = {
"CHADT": "+1345",
"NZDT": "+1300",
"AEDT": "+1100",
"ACDT": "+1030",
"AZST": "+0500",
"IRDT": "+0430",
"EEST": "+0300",
"CEST": "+0200",
"BST": "+0100",
"PMDT": "-0200",
"ADT": "-0300",
"NDT": "-0230",
"EDT": "-0400",
"CDT": "-0500",
"MDT": "-0600",
"PDT": "-0700",
"AKDT": "-0800",
"HADT": "-0900"
};
return __(DST);
},
timeZoneStandard: function () {
var standard = {
"LINT": "+1400",
"TOT": "+1300",
"CHAST": "+1245",
"NZST": "+1200",
"NFT": "+1130",
"SBT": "+1100",
"AEST": "+1000",
"ACST": "+0930",
"JST": "+0900",
"CWST": "+0845",
"CT": "+0800",
"ICT": "+0700",
"MMT": "+0630",
"BST": "+0600",
"NPT": "+0545",
"IST": "+0530",
"PKT": "+0500",
"AFT": "+0430",
"MSK": "+0400",
"IRST": "+0330",
"FET": "+0300",
"EET": "+0200",
"CET": "+0100",
"GMT": "+0000",
"UTC": "+0000",
"CVT": "-0100",
"GST": "-0200",
"BRT": "-0300",
"NST": "-0330",
"AST": "-0400",
"EST": "-0500",
"CST": "-0600",
"MST": "-0700",
"PST": "-0800",
"AKST": "-0900",
"MIT": "-0930",
"HST": "-1000",
"SST": "-1100",
"BIT": "-1200"
};
return __(standard);
},
timeZones: function (data) {
var zone;
data.timezones = [];
for (zone in data.abbreviatedTimeZoneStandard) {
if (data.abbreviatedTimeZoneStandard.hasOwnProperty(zone)) {
data.timezones.push({ name: zone, offset: data.abbreviatedTimeZoneStandard[zone]});
}
}
for (zone in data.abbreviatedTimeZoneDST) {
if (data.abbreviatedTimeZoneDST.hasOwnProperty(zone)) {
data.timezones.push({ name: zone, offset: data.abbreviatedTimeZoneDST[zone], dst: true});
}
}
return data.timezones;
},
days: function () {
return __(["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]);
},
dayAbbr: function () {
return __(["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]);
},
dayShortNames: function () {
return __(["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]);
},
dayFirstLetters: function () {
return __(["S_Sun_Initial", "M_Mon_Initial", "T_Tues_Initial", "W_Wed_Initial", "T_Thu_Initial", "F_Fri_Initial", "S_Sat_Initial"]);
},
months: function () {
return __(["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]);
},
monthAbbr: function () {
return __(["Jan_Abbr", "Feb_Abbr", "Mar_Abbr", "Apr_Abbr", "May_Abbr", "Jun_Abbr", "Jul_Abbr", "Aug_Abbr", "Sep_Abbr", "Oct_Abbr", "Nov_Abbr", "Dec_Abbr"]);
},
formatPatterns: function () {
return getText.getFromObjectValues({
shortDate: "M/d/yyyy",
longDate: "dddd, MMMM dd, yyyy",
shortTime: "h:mm tt",
longTime: "h:mm:ss tt",
fullDateTime: "dddd, MMMM dd, yyyy h:mm:ss tt",
sortableDateTime: "yyyy-MM-ddTHH:mm:ss",
universalSortableDateTime: "yyyy-MM-dd HH:mm:ssZ",
rfc1123: "ddd, dd MMM yyyy HH:mm:ss",
monthDay: "MMMM dd",
yearMonth: "MMMM, yyyy"
}, Date.i18n.currentLanguage());
},
regex: function () {
return getText.getFromObjectValues({
inTheMorning: "/( in the )(morn(ing)?)\\b/",
thisMorning: "/(this )(morn(ing)?)\\b/",
amThisMorning: "/(\b\\d(am)? )(this )(morn(ing)?)/",
inTheEvening: "/( in the )(even(ing)?)\\b/",
thisEvening: "/(this )(even(ing)?)\\b/",
pmThisEvening: "/(\b\\d(pm)? )(this )(even(ing)?)/",
jan: "/jan(uary)?/",
feb: "/feb(ruary)?/",
mar: "/mar(ch)?/",
apr: "/apr(il)?/",
may: "/may/",
jun: "/jun(e)?/",
jul: "/jul(y)?/",
aug: "/aug(ust)?/",
sep: "/sep(t(ember)?)?/",
oct: "/oct(ober)?/",
nov: "/nov(ember)?/",
dec: "/dec(ember)?/",
sun: "/^su(n(day)?)?/",
mon: "/^mo(n(day)?)?/",
tue: "/^tu(e(s(day)?)?)?/",
wed: "/^we(d(nesday)?)?/",
thu: "/^th(u(r(s(day)?)?)?)?/",
fri: "/fr(i(day)?)?/",
sat: "/^sa(t(urday)?)?/",
future: "/^next/",
past: "/^last|past|prev(ious)?/",
add: "/^(\\+|aft(er)?|from|hence)/",
subtract: "/^(\\-|bef(ore)?|ago)/",
yesterday: "/^yes(terday)?/",
today: "/^t(od(ay)?)?/",
tomorrow: "/^tom(orrow)?/",
now: "/^n(ow)?/",
millisecond: "/^ms|milli(second)?s?/",
second: "/^sec(ond)?s?/",
minute: "/^mn|min(ute)?s?/",
hour: "/^h(our)?s?/",
week: "/^w(eek)?s?/",
month: "/^m(onth)?s?/",
day: "/^d(ay)?s?/",
year: "/^y(ear)?s?/",
shortMeridian: "/^(a|p)/",
longMeridian: "/^(a\\.?m?\\.?|p\\.?m?\\.?)/",
timezone: "/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\\s*(\\+|\\-)\\s*\\d\\d\\d\\d?)|gmt|utc)/",
ordinalSuffix: "/^\\s*(st|nd|rd|th)/",
timeContext: "/^\\s*(\\:|a(?!u|p)|p)/"
}, Date.i18n.currentLanguage());
}
};
var CultureInfo = function () {
var info = getText.getFromObjectValues({
name: "name",
englishName: "englishName",
nativeName: "nativeName",
amDesignator: "AM",
pmDesignator: "PM",
firstDayOfWeek: "firstDayOfWeek",
twoDigitYearMax: "twoDigitYearMax",
dateElementOrder: "mdy"
}, Date.i18n.currentLanguage());
var constructedInfo = buildInfo.buildFromMethodHash({
dayNames: "days",
abbreviatedDayNames: "dayAbbr",
shortestDayNames: "dayShortNames",
firstLetterDayNames: "dayFirstLetters",
monthNames: "months",
abbreviatedMonthNames: "monthAbbr",
formatPatterns: "formatPatterns",
regexPatterns: "regex",
abbreviatedTimeZoneDST: "timeZoneDST",
abbreviatedTimeZoneStandard: "timeZoneStandard"
});
shallowMerge(info, constructedInfo);
buildInfo.timeZones(info);
return info;
};
$D.i18n = {
__: function (key, lang) {
return __(key, lang);
},
currentLanguage: function () {
return lang || "en-US";
},
setLanguage: function (code, force, cb) {
var async = false;
if (force || code === "en-US" || (!!Date.CultureStrings && !!Date.CultureStrings[code])) {
lang = code;
Date.CultureStrings = Date.CultureStrings || {};
Date.CultureStrings.lang = code;
Date.CultureInfo = new CultureInfo();
} else {
if (!(!!Date.CultureStrings && !!Date.CultureStrings[code])) {
if (typeof exports !== "undefined" && this.exports !== exports) {
// we're in a Node enviroment, load it using require
try {
require("../i18n/" + code + ".js");
lang = code;
Date.CultureStrings.lang = code;
Date.CultureInfo = new CultureInfo();
} catch (e) {
// var str = "The language for '" + code + "' could not be loaded by Node. It likely does not exist.";
throw new Error("The DateJS IETF language tag '" + code + "' could not be loaded by Node. It likely does not exist.");
}
} else if (Date.Config && Date.Config.i18n) {
// we know the location of the files, so lets load them
async = true;
loadI18nScript(code).done(function(){
lang = code;
Date.CultureStrings = Date.CultureStrings || {};
Date.CultureStrings.lang = code;
Date.CultureInfo = new CultureInfo();
$D.Parsing.Normalizer.buildReplaceData(); // because this is async
if ($D.Grammar) {
$D.Grammar.buildGrammarFormats(); // so we can parse those strings...
}
if (cb) {
setTimeout(cb,0);
}
});
} else {
Date.console.error("The DateJS IETF language tag '" + code + "' is not available and has not been loaded.");
return false;
}
}
}
$D.Parsing.Normalizer.buildReplaceData(); // rebuild normalizer strings
if ($D.Grammar) {
$D.Grammar.buildGrammarFormats(); // so we can parse those strings...
}
if (!async && cb) {
setTimeout(cb,0);
}
},
getLoggedKeys: function () {
return loggedKeys;
},
updateCultureInfo: function () {
Date.CultureInfo = new CultureInfo();
}
};
$D.i18n.updateCultureInfo(); // run automatically
}());
},{}],6:[function(require,module,exports){
(function () {
var $D = Date;
/**
* @desc Converts the specified string value into its JavaScript Date equivalent using CultureInfo specific format information.
*
* Example
<pre><code>
///////////
// Dates //
///////////
// 15-Oct-2004
var d1 = Date.parse("10/15/2004");
// 15-Oct-2004
var d1 = Date.parse("15-Oct-2004");
// 15-Oct-2004
var d1 = Date.parse("2004.10.15");
//Fri Oct 15, 2004
var d1 = Date.parse("Fri Oct 15, 2004");
///////////
// Times //
///////////
// Today at 10 PM.
var d1 = Date.parse("10 PM");
// Today at 10:30 PM.
var d1 = Date.parse("10:30 P.M.");
// Today at 6 AM.
var d1 = Date.parse("06am");
/////////////////////
// Dates and Times //
/////////////////////
// 8-July-2004 @ 10:30 PM
var d1 = Date.parse("July 8th, 2004, 10:30 PM");
// 1-July-2004 @ 10:30 PM
var d1 = Date.parse("2004-07-01T22:30:00");
////////////////////
// Relative Dates //
////////////////////
// Returns today's date. The string "today" is culture specific.
var d1 = Date.parse("today");
// Returns yesterday's date. The string "yesterday" is culture specific.
var d1 = Date.parse("yesterday");
// Returns the date of the next thursday.
var d1 = Date.parse("Next thursday");
// Returns the date of the most previous monday.
var d1 = Date.parse("last monday");
// Returns today's day + one year.
var d1 = Date.parse("next year");
///////////////
// Date Math //
///////////////
// Today + 2 days
var d1 = Date.parse("t+2");
// Today + 2 days
var d1 = Date.parse("today + 2 days");
// Today + 3 months
var d1 = Date.parse("t+3m");
// Today - 1 year
var d1 = Date.parse("today - 1 year");
// Today - 1 year
var d1 = Date.parse("t-1y");
/////////////////////////////
// Partial Dates and Times //
/////////////////////////////
// July 15th of this year.
var d1 = Date.parse("July 15");
// 15th day of current day and year.
var d1 = Date.parse("15");
// July 1st of current year at 10pm.
var d1 = Date.parse("7/1 10pm");
</code></pre>
*
* @param {String} The string value to convert into a Date object [Required]
* @return {Date} A Date object or null if the string cannot be converted into a Date.
*/
var parseUtils = {
removeOrds: function (s) {
ords = s.match(/\b(\d+)(?:st|nd|rd|th)\b/); // find ordinal matches
s = ((ords && ords.length === 2) ? s.replace(ords[0], ords[1]) : s);
return s;
},
grammarParser: function (s) {
var r = null;
try {
r = $D.Grammar.start.call({}, s.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1"));
} catch (e) {
return null;
}
return ((r[1].length === 0) ? r[0] : null);
},
nativeFallback: function(s) {
var t;
try {
// ok we haven't parsed it, last ditch attempt with the built-in parser.
t = Date._parse(s);
return (t || t === 0) ? new Date(t) : null;
} catch (e) {
return null;
}
}
};
function parse (s) {
var d;
if (!s) {
return null;
}
if (s instanceof Date) {
return s.clone();
}
if (s.length >= 4 && s.charAt(0) !== "0" && s.charAt(0) !== "+"&& s.charAt(0) !== "-") { // ie: 2004 will pass, 0800 won't.
// Start with specific formats
d = $D.Parsing.ISO.parse(s) || $D.Parsing.Numeric.parse(s);
}
if (d instanceof Date && !isNaN(d.getTime())) {
return d;
} else {
// find ordinal dates (1st, 3rd, 8th, etc and remove them as they cause parsing issues)
s = $D.Parsing.Normalizer.parse(parseUtils.removeOrds(s));
d = parseUtils.grammarParser(s);
if (d !== null) {
return d;
} else {
return parseUtils.nativeFallback(s);
}
}
}
if (!$D._parse) {
$D._parse = $D.parse;
}
$D.parse = parse;
Date.getParseFunction = function (fx) {
var fns = Date.Grammar.allformats(fx);
return function (s) {
var r = null;
for (var i = 0; i < fns.length; i++) {
try {
r = fns[i].call({}, s);
} catch (e) {
continue;
}
if (r[1].length === 0) {
return r[0];
}
}
return null;
};
};
/**
* Converts the specified string value into its JavaScript Date equivalent using the specified format {String} or formats {Array} and the CultureInfo specific format information.
* The format of the string value must match one of the supplied formats exactly.
*
* Example
<pre><code>
// 15-Oct-2004
var d1 = Date.parseExact("10/15/2004", "M/d/yyyy");
// 15-Oct-2004
var d1 = Date.parse("15-Oct-2004", "M-ddd-yyyy");
// 15-Oct-2004
var d1 = Date.parse("2004.10.15", "yyyy.MM.dd");
// Multiple formats
var d1 = Date.parseExact("10/15/2004", ["M/d/yyyy", "MMMM d, yyyy"]);
</code></pre>
*
* @param {String} The string value to convert into a Date object [Required].
* @param {Object} The expected format {String} or an array of expected formats {Array} of the date string [Required].
* @return {Date} A Date object or null if the string cannot be converted into a Date.
*/
$D.parseExact = function (s, fx) {
return $D.getParseFunction(fx)(s);
};
}());
},{}],7:[function(require,module,exports){
(function () {
var $D = Date;
$D.Grammar = {};
var _ = $D.Parsing.Operators, g = $D.Grammar, t = $D.Translator, _fn;
// Allow rolling up into general purpose rules
_fn = function () {
return _.each(_.any.apply(null, arguments), _.not(g.ctoken2("timeContext")));
};
g.datePartDelimiter = _.rtoken(/^([\s\-\.\,\/\x27]+)/);
g.timePartDelimiter = _.stoken(":");
g.whiteSpace = _.rtoken(/^\s*/);
g.generalDelimiter = _.rtoken(/^(([\s\,]|at|@|on)+)/);
var _C = {};
g.ctoken = function (keys) {
var fn = _C[keys];
if (! fn) {
var c = Date.CultureInfo.regexPatterns;
var kx = keys.split(/\s+/), px = [];
for (var i = 0; i < kx.length ; i++) {
px.push(_.replace(_.rtoken(c[kx[i]]), kx[i]));
}
fn = _C[keys] = _.any.apply(null, px);
}
return fn;
};
g.ctoken2 = function (key) {
return _.rtoken(Date.CultureInfo.regexPatterns[key]);
};
var cacheProcessRtoken = function (key, token, type, eachToken) {
if (eachToken) {
g[key] = _.cache(_.process(_.each(_.rtoken(token),_.optional(g.ctoken2(eachToken))), type));
} else {
g[key] = _.cache(_.process(_.rtoken(token), type));
}
};
var cacheProcessCtoken = function (token, type) {
return _.cache(_.process(g.ctoken2(token), type));
};
var _F = {}; //function cache
var _get = function (f) {
_F[f] = (_F[f] || g.format(f)[0]);
return _F[f];
};
g.allformats = function (fx) {
var rx = [];
if (fx instanceof Array) {
for (var i = 0; i < fx.length; i++) {
rx.push(_get(fx[i]));
}
} else {
rx.push(_get(fx));
}
return rx;
};
g.formats = function (fx) {
if (fx instanceof Array) {
var rx = [];
for (var i = 0 ; i < fx.length ; i++) {
rx.push(_get(fx[i]));
}
return _.any.apply(null, rx);
} else {
return _get(fx);
}
};
var grammarFormats = {
timeFormats: function(){
var i,
RTokenKeys = [
"h",
"hh",
"H",
"HH",
"m",
"mm",
"s",
"ss",
"ss.s",
"z",
"zz"
],
RToken = [
/^(0[0-9]|1[0-2]|[1-9])/,
/^(0[0-9]|1[0-2])/,
/^([0-1][0-9]|2[0-3]|[0-9])/,
/^([0-1][0-9]|2[0-3])/,
/^([0-5][0-9]|[0-9])/,
/^[0-5][0-9]/,
/^([0-5][0-9]|[0-9])/,
/^[0-5][0-9]/,
/^[0-5][0-9]\.[0-9]{1,3}/,
/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/,
/^((\+|\-)\s*\d\d\d\d)|((\+|\-)\d\d\:?\d\d)/
],
tokens = [
t.hour,
t.hour,
t.hour,
t.minute,
t.minute,
t.second,
t.second,
t.secondAndMillisecond,
t.timezone,
t.timezone,
t.timezone
];
for (i=0; i < RTokenKeys.length; i++) {
cacheProcessRtoken(RTokenKeys[i], RToken[i], tokens[i]);
}
g.hms = _.cache(_.sequence([g.H, g.m, g.s], g.timePartDelimiter));
g.t = cacheProcessCtoken("shortMeridian", t.meridian);
g.tt = cacheProcessCtoken("longMeridian", t.meridian);
g.zzz = cacheProcessCtoken("timezone", t.timezone);
g.timeSuffix = _.each(_.ignore(g.whiteSpace), _.set([ g.tt, g.zzz ]));
g.time = _.each(_.optional(_.ignore(_.stoken("T"))), g.hms, g.timeSuffix);
},
dateFormats: function () {
// pre-loaded rules for different date part order preferences
var _setfn = function () {
return _.set(arguments, g.datePartDelimiter);
};
var i,
RTokenKeys = [
"d",
"dd",
"M",
"MM",
"y",
"yy",
"yyy",
"yyyy"
],
RToken = [
/^([0-2]\d|3[0-1]|\d)/,
/^([0-2]\d|3[0-1])/,
/^(1[0-2]|0\d|\d)/,
/^(1[0-2]|0\d)/,
/^(\d+)/,
/^(\d\d)/,
/^(\d\d?\d?\d?)/,
/^(\d\d\d\d)/
],
tokens = [
t.day,
t.day,
t.month,
t.month,
t.year,
t.year,
t.year,
t.year
],
eachToken = [
"ordinalSuffix",
"ordinalSuffix"
];
for (i=0; i < RTokenKeys.length; i++) {
cacheProcessRtoken(RTokenKeys[i], RToken[i], tokens[i], eachToken[i]);
}
g.MMM = g.MMMM = _.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"), t.month));
g.ddd = g.dddd = _.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),
function (s) {
return function () {
this.weekday = s;
};
}
));
g.day = _fn(g.d, g.dd);
g.month = _fn(g.M, g.MMM);
g.year = _fn(g.yyyy, g.yy);
g.mdy = _setfn(g.ddd, g.month, g.day, g.year);
g.ymd = _setfn(g.ddd, g.year, g.month, g.day);
g.dmy = _setfn(g.ddd, g.day, g.month, g.year);
g.date = function (s) {
return ((g[Date.CultureInfo.dateElementOrder] || g.mdy).call(this, s));
};
},
relative: function () {
// relative date / time expressions
g.orientation = _.process(g.ctoken("past future"),
function (s) {
return function () {
this.orient = s;
};
}
);
g.operator = _.process(g.ctoken("add subtract"),
function (s) {
return function () {
this.operator = s;
};
}
);
g.rday = _.process(g.ctoken("yesterday tomorrow today now"), t.rday);
g.unit = _.process(g.ctoken("second minute hour day week month year"),
function (s) {
return function () {
this.unit = s;
};
}
);
}
};
g.buildGrammarFormats = function () {
// these need to be rebuilt every time the language changes.
_C = {};
grammarFormats.timeFormats();
grammarFormats.dateFormats();
grammarFormats.relative();
g.value = _.process(_.rtoken(/^([-+]?\d+)?(st|nd|rd|th)?/),
function (s) {
return function () {
this.value = s.replace(/\D/g, "");
};
}
);
g.expression = _.set([g.rday, g.operator, g.value, g.unit, g.orientation, g.ddd, g.MMM ]);
g.format = _.process(_.many(
_.any(
// translate format specifiers into grammar rules
_.process(
_.rtoken(/^(dd?d?d?(?!e)|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),
function (fmt) {
if (g[fmt]) {
return g[fmt];
} else {
throw $D.Parsing.Exception(fmt);
}
}
),
// translate separator tokens into token rules
_.process(_.rtoken(/^[^dMyhHmstz]+/), // all legal separators
function (s) {
return _.ignore(_.stoken(s));
}
)
)
),
// construct the parser ...
function (rules) {
return _.process(_.each.apply(null, rules), t.finishExact);
}
);
// starting rule for general purpose grammar
g._start = _.process(_.set([ g.date, g.time, g.expression ],
g.generalDelimiter, g.whiteSpace), t.finish);
};
g.buildGrammarFormats();
// parsing date format specifiers - ex: "h:m:s tt"
// this little guy will generate a custom parser based
// on the format string, ex: g.format("h:m:s tt")
// check for these formats first
g._formats = g.formats([
"\"yyyy-MM-ddTHH:mm:ssZ\"",
"yyyy-MM-ddTHH:mm:ss.sz",
"yyyy-MM-ddTHH:mm:ssZ",
"yyyy-MM-ddTHH:mm:ssz",
"yyyy-MM-ddTHH:mm:ss",
"yyyy-MM-ddTHH:mmZ",
"yyyy-MM-ddTHH:mmz",
"yyyy-MM-ddTHH:mm",
"ddd, MMM dd, yyyy H:mm:ss tt",
"ddd MMM d yyyy HH:mm:ss zzz",
"MMddyyyy",
"ddMMyyyy",
"Mddyyyy",
"ddMyyyy",
"Mdyyyy",
"dMyyyy",
"yyyy",
"Mdyy",
"dMyy",
"d"
]);
// real starting rule: tries selected formats first,
// then general purpose rule
g.start = function (s) {
try {
var r = g._formats.call({}, s);
if (r[1].length === 0) {
return r;
}
} catch (e) {}
return g._start.call({}, s);
};
}());
},{}],8:[function(require,module,exports){
(function () {
var $P = Date.Parsing;
var _ = $P.Operators = {
//
// Tokenizers
//
rtoken: function (r) { // regex token
return function (s) {
var mx = s.match(r);
if (mx) {
return ([ mx[0], s.substring(mx[0].length) ]);
} else {
throw new $P.Exception(s);
}
};
},
token: function () { // whitespace-eating token
return function (s) {
return _.rtoken(new RegExp("^\\s*" + s + "\\s*"))(s);
};
},
stoken: function (s) { // string token
return _.rtoken(new RegExp("^" + s));
},
// Atomic Operators
until: function (p) {
return function (s) {
var qx = [], rx = null;
while (s.length) {
try {
rx = p.call(this, s);
} catch (e) {
qx.push(rx[0]);
s = rx[1];
continue;
}
break;
}
return [ qx, s ];
};
},
many: function (p) {
return function (s) {
var rx = [], r = null;
while (s.length) {
try {
r = p.call(this, s);
} catch (e) {
return [ rx, s ];
}
rx.push(r[0]);
s = r[1];
}
return [ rx, s ];
};
},
// generator operators -- see below
optional: function (p) {
return function (s) {
var r = null;
try {
r = p.call(this, s);
} catch (e) {
return [ null, s ];
}
return [ r[0], r[1] ];
};
},
not: function (p) {
return function (s) {
try {
p.call(this, s);
} catch (e) {
return [null, s];
}
throw new $P.Exception(s);
};
},
ignore: function (p) {
return p ?
function (s) {
var r = null;
r = p.call(this, s);
return [null, r[1]];
} : null;
},
product: function () {
var px = arguments[0],
qx = Array.prototype.slice.call(arguments, 1), rx = [];
for (var i = 0 ; i < px.length ; i++) {
rx.push(_.each(px[i], qx));
}
return rx;
},
cache: function (rule) {
var cache = {}, cache_length = 0, cache_keys = [], CACHE_MAX = Date.Config.CACHE_MAX || 100000, r = null;
var cacheCheck = function () {
if (cache_length === CACHE_MAX) {
// kill several keys, don't want to have to do this all the time...
for (var i=0; i < 10; i++) {
var key = cache_keys.shift();
if (key) {
delete cache[key];
cache_length--;
}
}
}
};
return function (s) {
cacheCheck();
try {
r = cache[s] = (cache[s] || rule.call(this, s));
} catch (e) {
r = cache[s] = e;
}
cache_length++;
cache_keys.push(s);
if (r instanceof $P.Exception) {
throw r;
} else {
return r;
}
};
},
// vector operators -- see below
any: function () {
var px = arguments;
return function (s) {
var r = null;
for (var i = 0; i < px.length; i++) {
if (px[i] == null) {
continue;
}
try {
r = (px[i].call(this, s));
} catch (e) {
r = null;
}
if (r) {
return r;
}
}
throw new $P.Exception(s);
};
},
each: function () {
var px = arguments;
return function (s) {
var rx = [], r = null;
for (var i = 0; i < px.length ; i++) {
if (px[i] == null) {
continue;
}
try {
r = (px[i].call(this, s));
} catch (e) {
throw new $P.Exception(s);
}
rx.push(r[0]);
s = r[1];
}
return [ rx, s];
};
},
all: function () {
var px = arguments, _ = _;
return _.each(_.optional(px));
},
// delimited operators
sequence: function (px, d, c) {
d = d || _.rtoken(/^\s*/);
c = c || null;
if (px.length === 1) {
return px[0];
}
return function (s) {
var r = null, q = null;
var rx = [];
for (var i = 0; i < px.length ; i++) {
try {
r = px[i].call(this, s);
} catch (e) {
break;
}
rx.push(r[0]);
try {
q = d.call(this, r[1]);
} catch (ex) {
q = null;
break;
}
s = q[1];
}
if (!r) {
throw new $P.Exception(s);
}
if (q) {
throw new $P.Exception(q[1]);
}
if (c) {
try {
r = c.call(this, r[1]);
} catch (ey) {
throw new $P.Exception(r[1]);
}
}
return [ rx, (r?r[1]:s) ];
};
},
//
// Composite Operators
//
between: function (d1, p, d2) {
d2 = d2 || d1;
var _fn = _.each(_.ignore(d1), p, _.ignore(d2));
return function (s) {
var rx = _fn.call(this, s);
return [[rx[0][0], r[0][2]], rx[1]];
};
},
list: function (p, d, c) {
d = d || _.rtoken(/^\s*/);
c = c || null;
return (p instanceof Array ?
_.each(_.product(p.slice(0, -1), _.ignore(d)), p.slice(-1), _.ignore(c)) :
_.each(_.many(_.each(p, _.ignore(d))), px, _.ignore(c)));
},
set: function (px, d, c) {
d = d || _.rtoken(/^\s*/);
c = c || null;
return function (s) {
// r is the current match, best the current 'best' match
// which means it parsed the most amount of input
var r = null, p = null, q = null, rx = null, best = [[], s], last = false;
// go through the rules in the given set
for (var i = 0; i < px.length ; i++) {
// last is a flag indicating whether this must be the last element
// if there is only 1 element, then it MUST be the last one
q = null;
p = null;
r = null;
last = (px.length === 1);
// first, we try simply to match the current pattern
// if not, try the next pattern
try {
r = px[i].call(this, s);
} catch (e) {
continue;
}
// since we are matching against a set of elements, the first
// thing to do is to add r[0] to matched elements
rx = [[r[0]], r[1]];
// if we matched and there is still input to parse and
// we don't already know this is the last element,
// we're going to next check for the delimiter ...
// if there's none, or if there's no input left to parse
// than this must be the last element after all ...
if (r[1].length > 0 && ! last) {
try {
q = d.call(this, r[1]);
} catch (ex) {
last = true;
}
} else {
last = true;
}
// if we parsed the delimiter and now there's no more input,
// that means we shouldn't have parsed the delimiter at all
// so don't update r and mark this as the last element ...
if (!last && q[1].length === 0) {
last = true;
}
// so, if this isn't the last element, we're going to see if
// we can get any more matches from the remaining (unmatched)
// elements ...
if (!last) {
// build a list of the remaining rules we can match against,
// i.e., all but the one we just matched against
var qx = [];
for (var j = 0; j < px.length ; j++) {
if (i !== j) {
qx.push(px[j]);
}
}
// now invoke recursively set with the remaining input
// note that we don't include the closing delimiter ...
// we'll check for that ourselves at the end
p = _.set(qx, d).call(this, q[1]);
// if we got a non-empty set as a result ...
// (otw rx already contains everything we want to match)
if (p[0].length > 0) {
// update current result, which is stored in rx ...
// basically, pick up the remaining text from p[1]
// and concat the result from p[0] so that we don't
// get endless nesting ...
rx[0] = rx[0].concat(p[0]);
rx[1] = p[1];
}
}
// at this point, rx either contains the last matched element
// or the entire matched set that starts with this element.
// now we just check to see if this variation is better than
// our best so far, in terms of how much of the input is parsed
if (rx[1].length < best[1].length) {
best = rx;
}
// if we've parsed all the input, then we're finished
if (best[1].length === 0) {
break;
}
}
// so now we've either gone through all the patterns trying them
// as the initial match; or we found one that parsed the entire
// input string ...
// if best has no matches, just return empty set ...
if (best[0].length === 0) {
return best;
}
// if a closing delimiter is provided, then we have to check it also
if (c) {
// we try this even if there is no remaining input because the pattern
// may well be optional or match empty input ...
try {
q = c.call(this, best[1]);
} catch (ey) {
throw new $P.Exception(best[1]);
}
// it parsed ... be sure to update the best match remaining input
best[1] = q[1];
}
// if we're here, either there was no closing delimiter or we parsed it
// so now we have the best match; just return it!
return best;
};
},
forward: function (gr, fname) {
return function (s) {
return gr[fname].call(this, s);
};
},
//
// Translation Operators
//
replace: function (rule, repl) {
return function (s) {
var r = rule.call(this, s);
return [repl, r[1]];
};
},
process: function (rule, fn) {
return function (s) {
var r = rule.call(this, s);
return [fn.call(this, r[0]), r[1]];
};
},
min: function (min, rule) {
return function (s) {
var rx = rule.call(this, s);
if (rx[0].length < min) {
throw new $P.Exception(s);
}
return rx;
};
}
};
// Generator Operators And Vector Operators
// Generators are operators that have a signature of F(R) => R,
// taking a given rule and returning another rule, such as
// ignore, which parses a given rule and throws away the result.
// Vector operators are those that have a signature of F(R1,R2,...) => R,
// take a list of rules and returning a new rule, such as each.
// Generator operators are converted (via the following _generator
// function) into functions that can also take a list or array of rules
// and return an array of new rules as though the function had been
// called on each rule in turn (which is what actually happens).
// This allows generators to be used with vector operators more easily.
// Example:
// each(ignore(foo, bar)) instead of each(ignore(foo), ignore(bar))
// This also turns generators into vector operators, which allows
// constructs like:
// not(cache(foo, bar))
var _generator = function (op) {
function gen() {
var args = null, rx = [], px, i;
if (arguments.length > 1) {
args = Array.prototype.slice.call(arguments);
} else if (arguments[0] instanceof Array) {
args = arguments[0];
}
if (args) {
px = args.shift();
if (px.length > 0) {
args.unshift(px[i]);
rx.push(op.apply(null, args));
args.shift();
return rx;
}
} else {
return op.apply(null, arguments);
}
}
return gen;
};
var gx = "optional not ignore cache".split(/\s/);
for (var i = 0 ; i < gx.length ; i++) {
_[gx[i]] = _generator(_[gx[i]]);
}
var _vector = function (op) {
return function () {
if (arguments[0] instanceof Array) {
return op.apply(null, arguments[0]);
} else {
return op.apply(null, arguments);
}
};
};
var vx = "each any all".split(/\s/);
for (var j = 0 ; j < vx.length ; j++) {
_[vx[j]] = _vector(_[vx[j]]);
}
}());
},{}],9:[function(require,module,exports){
(function () {
var $D = Date;
var flattenAndCompact = function (ax) {
var rx = [];
for (var i = 0; i < ax.length; i++) {
if (ax[i] instanceof Array) {
rx = rx.concat(flattenAndCompact(ax[i]));
} else {
if (ax[i]) {
rx.push(ax[i]);
}
}
}
return rx;
};
var parseMeridian = function () {
if (this.meridian && (this.hour || this.hour === 0)) {
if (this.meridian === "a" && this.hour > 11 && Date.Config.strict24hr){
throw "Invalid hour and meridian combination";
} else if (this.meridian === "p" && this.hour < 12 && Date.Config.strict24hr){
throw "Invalid hour and meridian combination";
} else if (this.meridian === "p" && this.hour < 12) {
this.hour = this.hour + 12;
} else if (this.meridian === "a" && this.hour === 12) {
this.hour = 0;
}
}
};
var setDefaults = function () {
var now = new Date();
if ((this.hour || this.minute) && (!this.month && !this.year && !this.day)) {
this.day = now.getDate();
}
if (!this.year) {
this.year = now.getFullYear();
}
if (!this.month && this.month !== 0) {
this.month = now.getMonth();
}
if (!this.day) {
this.day = 1;
}
if (!this.hour) {
this.hour = 0;
}
if (!this.minute) {
this.minute = 0;
}
if (!this.second) {
this.second = 0;
}
if (!this.millisecond) {
this.millisecond = 0;
}
};
var finishUtils = {
getToday: function () {
if (this.now || "hour minute second".indexOf(this.unit) !== -1) {
return new Date();
} else {
return $D.today();
}
},
setDaysFromWeekday: function (today, orient){
var gap;
orient = orient || 1;
this.unit = "day";
gap = ($D.getDayNumberFromName(this.weekday) - today.getDay());
this.days = gap ? ((gap + (orient * 7)) % 7) : (orient * 7);
return this;
},
setMonthsFromMonth: function (today, orient) {
var gap;
orient = orient || 1;
this.unit = "month";
gap = (this.month - today.getMonth());
this.months = gap ? ((gap + (orient * 12)) % 12) : (orient * 12);
this.month = null;
return this;
},
setDMYFromWeekday: function () {
var d = Date[this.weekday]();
this.day = d.getDate();
if (!this.month) {
this.month = d.getMonth();
}
this.year = d.getFullYear();
return this;
},
setUnitValue: function (orient) {
if (!this.value && this.operator && this.operator !== null && this[this.unit + "s"] && this[this.unit + "s"] !== null) {
this[this.unit + "s"] = this[this.unit + "s"] + ((this.operator === "add") ? 1 : -1) + (this.value||0) * orient;
} else if (this[this.unit + "s"] == null || this.operator != null) {
if (!this.value) {
this.value = 1;
}
this[this.unit + "s"] = this.value * orient;
}
},
generateDateFromWeeks: function () {
var weekday = (this.weekday !== undefined) ? this.weekday : "today";
var d = Date[weekday]().addWeeks(this.weeks);
if (this.now) {
d.setTimeToNow();
}
return d;
}
};
$D.Translator = {
hour: function (s) {
return function () {
this.hour = Number(s);
};
},
minute: function (s) {
return function () {
this.minute = Number(s);
};
},
second: function (s) {
return function () {
this.second = Number(s);
};
},
/* for ss.s format */
secondAndMillisecond: function (s) {
return function () {
var mx = s.match(/^([0-5][0-9])\.([0-9]{1,3})/);
this.second = Number(mx[1]);
this.millisecond = Number(mx[2]);
};
},
meridian: function (s) {
return function () {
this.meridian = s.slice(0, 1).toLowerCase();
};
},
timezone: function (s) {
return function () {
var n = s.replace(/[^\d\+\-]/g, "");
if (n.length) {
this.timezoneOffset = Number(n);
} else {
this.timezone = s.toLowerCase();
}
};
},
day: function (x) {
var s = x[0];
return function () {
this.day = Number(s.match(/\d+/)[0]);
if (this.day < 1) {
throw "invalid day";
}
};
},
month: function (s) {
return function () {
this.month = (s.length === 3) ? "jan feb mar apr may jun jul aug sep oct nov dec".indexOf(s)/4 : Number(s) - 1;
if (this.month < 0) {
throw "invalid month";
}
};
},
year: function (s) {
return function () {
var n = Number(s);
this.year = ((s.length > 2) ? n :
(n + (((n + 2000) < Date.CultureInfo.twoDigitYearMax) ? 2000 : 1900)));
};
},
rday: function (s) {
return function () {
switch (s) {
case "yesterday":
this.days = -1;
break;
case "tomorrow":
this.days = 1;
break;
case "today":
this.days = 0;
break;
case "now":
this.days = 0;
this.now = true;
break;
}
};
},
finishExact: function (x) {
var d;
x = (x instanceof Array) ? x : [x];
for (var i = 0 ; i < x.length ; i++) {
if (x[i]) {
x[i].call(this);
}
}
setDefaults.call(this);
parseMeridian.call(this);
if (this.day > $D.getDaysInMonth(this.year, this.month)) {
throw new RangeError(this.day + " is not a valid value for days.");
}
d = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
if (this.year < 100) {
d.setFullYear(this.year); // means years less that 100 are process correctly. JS will parse it otherwise as 1900-1999.
}
if (this.timezone) {
d.set({ timezone: this.timezone });
} else if (this.timezoneOffset) {
d.set({ timezoneOffset: this.timezoneOffset });
}
return d;
},
finish: function (x) {
var today, expression, orient, temp;
x = (x instanceof Array) ? flattenAndCompact(x) : [ x ];
if (x.length === 0) {
return null;
}
for (var i = 0 ; i < x.length ; i++) {
if (typeof x[i] === "function") {
x[i].call(this);
}
}
if (this.now && !this.unit && !this.operator) {
return new Date();
} else {
today = finishUtils.getToday.call(this);
}
expression = !!(this.days && this.days !== null || this.orient || this.operator);
orient = ((this.orient === "past" || this.operator === "subtract") ? -1 : 1);
if (this.month && this.unit === "week") {
this.value = this.month + 1;
delete this.month;
delete this.day;
}
if ((this.month || this.month === 0) && "year day hour minute second".indexOf(this.unit) !== -1) {
if (!this.value) {
this.value = this.month + 1;
}
this.month = null;
expression = true;
}
if (!expression && this.weekday && !this.day && !this.days) {
finishUtils.setDMYFromWeekday.call(this);
}
if (expression && this.weekday && this.unit !== "month" && this.unit !== "week") {
finishUtils.setDaysFromWeekday.call(this, today, orient);
}
if (this.weekday && this.unit !== "week" && !this.day && !this.days) {
temp = Date[this.weekday]();
this.day = temp.getDate();
if (temp.getMonth() !== today.getMonth()) {
this.month = temp.getMonth();
}
}
if (this.month && this.unit === "day" && this.operator) {
if (!this.value) {
this.value = (this.month + 1);
}
this.month = null;
}
if (this.value != null && this.month != null && this.year != null) {
this.day = this.value * 1;
}
if (this.month && !this.day && this.value) {
today.set({ day: this.value * 1 });
if (!expression) {
this.day = this.value * 1;
}
}
if (!this.month && this.value && this.unit === "month" && !this.now) {
this.month = this.value;
expression = true;
}
if (expression && (this.month || this.month === 0) && this.unit !== "year") {
finishUtils.setMonthsFromMonth.call(this, today, orient);
}
if (!this.unit) {
this.unit = "day";
}
finishUtils.setUnitValue.call(this, orient);
parseMeridian.call(this);
if ((this.month || this.month === 0) && !this.day) {
this.day = 1;
}
if (!this.orient && !this.operator && this.unit === "week" && this.value && !this.day && !this.month) {
return Date.today().setWeek(this.value);
}
if (this.unit === "week" && this.weeks && !this.day && !this.month) {
return finishUtils.generateDateFromWeeks.call(this);
}
if (expression && this.timezone && this.day && this.days) {
this.day = this.days;
}
if (expression){
today.add(this);
} else {
today.set(this);
}
if (this.timezone) {
this.timezone = this.timezone.toUpperCase();
var offset = $D.getTimezoneOffset(this.timezone);
var timezone;
if (today.hasDaylightSavingTime()) {
// lets check that we're being sane with timezone setting
timezone = $D.getTimezoneAbbreviation(offset, today.isDaylightSavingTime());
if (timezone !== this.timezone) {
// bugger, we're in a place where things like EST vs EDT matters.
if (today.isDaylightSavingTime()) {
today.addHours(-1);
} else {
today.addHours(1);
}
}
}
today.setTimezoneOffset(offset);
}
return today;
}
};
}());
},{}],10:[function(require,module,exports){
/*************************************************************
* SugarPak - Domain Specific Language - Syntactical Sugar *
*************************************************************/
(function () {
var $D = Date, $P = $D.prototype, $N = Number.prototype;
// private
$P._orient = +1;
// private
$P._nth = null;
// private
$P._is = false;
// private
$P._same = false;
// private
$P._isSecond = false;
// private
$N._dateElement = "days";
/**
* Moves the date to the next instance of a date as specified by the subsequent date element function (eg. .day(), .month()), month name function (eg. .january(), .jan()) or day name function (eg. .friday(), fri()).
* Example
<pre><code>
Date.today().next().friday();
Date.today().next().fri();
Date.today().next().march();
Date.today().next().mar();
Date.today().next().week();
</code></pre>
*
* @return {Date} date
*/
$P.next = function () {
this._move = true;
this._orient = +1;
return this;
};
/**
* Creates a new Date (Date.today()) and moves the date to the next instance of the date as specified by the subsequent date element function (eg. .day(), .month()), month name function (eg. .january(), .jan()) or day name function (eg. .friday(), fri()).
* Example
<pre><code>
Date.next().friday();
Date.next().fri();
Date.next().march();
Date.next().mar();
Date.next().week();
</code></pre>
*
* @return {Date} date
*/
$D.next = function () {
return $D.today().next();
};
/**
* Moves the date to the previous instance of a date as specified by the subsequent date element function (eg. .day(), .month()), month name function (eg. .january(), .jan()) or day name function (eg. .friday(), fri()).
* Example
<pre><code>
Date.today().last().friday();
Date.today().last().fri();
Date.today().last().march();
Date.today().last().mar();
Date.today().last().week();
</code></pre>
*
* @return {Date} date
*/
$P.last = $P.prev = $P.previous = function () {
this._move = true;
this._orient = -1;
return this;
};
/**
* Creates a new Date (Date.today()) and moves the date to the previous instance of the date as specified by the subsequent date element function (eg. .day(), .month()), month name function (eg. .january(), .jan()) or day name function (eg. .friday(), fri()).
* Example
<pre><code>
Date.last().friday();
Date.last().fri();
Date.previous().march();
Date.prev().mar();
Date.last().week();
</code></pre>
*
* @return {Date} date
*/
$D.last = $D.prev = $D.previous = function () {
return $D.today().last();
};
/**
* Performs a equality check when followed by either a month name, day name or .weekday() function.
* Example
<pre><code>
Date.today().is().friday(); // true|false
Date.today().is().fri();
Date.today().is().march();
Date.today().is().mar();
</code></pre>
*
* @return {Boolean} true|false
*/
$P.is = function () {
this._is = true;
return this;
};
/**
* Determines if two date objects occur on/in exactly the same instance of the subsequent date part function.
* The function .same() must be followed by a date part function (example: .day(), .month(), .year(), etc).
*
* An optional Date can be passed in the date part function. If now date is passed as a parameter, 'Now' is used.
*
* The following example demonstrates how to determine if two dates fall on the exact same day.
*
* Example
<pre><code>
var d1 = Date.today(); // today at 00:00
var d2 = new Date(); // exactly now.
// Do they occur on the same day?
d1.same().day(d2); // true
// Do they occur on the same hour?
d1.same().hour(d2); // false, unless d2 hour is '00' (midnight).
// What if it's the same day, but one year apart?
var nextYear = Date.today().add(1).year();
d1.same().day(nextYear); // false, because the dates must occur on the exact same day.
</code></pre>
*
* Scenario: Determine if a given date occurs during some week period 2 months from now.
*
* Example
<pre><code>
var future = Date.today().add(2).months();
return someDate.same().week(future); // true|false;
</code></pre>
*
* @return {Boolean} true|false
*/
$P.same = function () {
this._same = true;
this._isSecond = false;
return this;
};
/**
* Determines if the current date/time occurs during Today. Must be preceded by the .is() function.
* Example
<pre><code>
someDate.is().today(); // true|false
new Date().is().today(); // true
Date.today().is().today();// true
Date.today().add(-1).day().is().today(); // false
</code></pre>
*
* @return {Boolean} true|false
*/
$P.today = function () {
return this.same().day();
};
/**
* Determines if the current date is a weekday. This function must be preceded by the .is() function.
* Example
<pre><code>
Date.today().is().weekday(); // true|false
</code></pre>
*
* @return {Boolean} true|false
*/
$P.weekday = function () {
if (this._nth) {
return df("Weekday").call(this);
}
if (this._move) {
return this.addWeekdays(this._orient);
}
if (this._is) {
this._is = false;
return (!this.is().sat() && !this.is().sun());
}
return false;
};
/**
* Determines if the current date is on the weekend. This function must be preceded by the .is() function.
* Example
<pre><code>
Date.today().is().weekend(); // true|false
</code></pre>
*
* @return {Boolean} true|false
*/
$P.weekend = function () {
if (this._is) {
this._is = false;
return (this.is().sat() || this.is().sun());
}
return false;
};
/**
* Sets the Time of the current Date instance. A string "6:15 pm" or config object {hour:18, minute:15} are accepted.
* Example
<pre><code>
// Set time to 6:15pm with a String
Date.today().at("6:15pm");
// Set time to 6:15pm with a config object
Date.today().at({hour:18, minute:15});
</code></pre>
*
* @return {Date} date
*/
$P.at = function (time) {
return (typeof time === "string") ? $D.parse(this.toString("d") + " " + time) : this.set(time);
};
/**
* Creates a new Date() and adds this (Number) to the date based on the preceding date element function (eg. second|minute|hour|day|month|year).
* Example
<pre><code>
// Undeclared Numbers must be wrapped with parentheses. Requirment of JavaScript.
(3).days().fromNow();
(6).months().fromNow();
// Declared Number variables do not require parentheses.
var n = 6;
n.months().fromNow();
</code></pre>
*
* @return {Date} A new Date instance
*/
$N.fromNow = $N.after = function (date) {
var c = {};
c[this._dateElement] = this;
return ((!date) ? new Date() : date.clone()).add(c);
};
/**
* Creates a new Date() and subtract this (Number) from the date based on the preceding date element function (eg. second|minute|hour|day|month|year).
* Example
<pre><code>
// Undeclared Numbers must be wrapped with parentheses. Requirment of JavaScript.
(3).days().ago();
(6).months().ago();
// Declared Number variables do not require parentheses.
var n = 6;
n.months().ago();
</code></pre>
*
* @return {Date} A new Date instance
*/
$N.ago = $N.before = function (date) {
var c = {},
s = (this._dateElement[this._dateElement.length-1] !== "s") ? this._dateElement + "s" : this._dateElement;
c[s] = this * -1;
return ((!date) ? new Date() : date.clone()).add(c);
};
// Do NOT modify the following string tokens. These tokens are used to build dynamic functions.
// All culture-specific strings can be found in the CultureInfo files.
var dx = ("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),
mx = ("january february march april may june july august september october november december").split(/\s/),
px = ("Millisecond Second Minute Hour Day Week Month Year Quarter Weekday").split(/\s/),
pxf = ("Milliseconds Seconds Minutes Hours Date Week Month FullYear Quarter").split(/\s/),
nth = ("final first second third fourth fifth").split(/\s/),
de;
/**
* Returns an object literal of all the date parts.
* Example
<pre><code>
var o = new Date().toObject();
// { year: 2008, month: 4, week: 20, day: 13, hour: 18, minute: 9, second: 32, millisecond: 812 }
// The object properties can be referenced directly from the object.
alert(o.day); // alerts "13"
alert(o.year); // alerts "2008"
</code></pre>
*
* @return {Date} An object literal representing the original date object.
*/
$P.toObject = function () {
var o = {};
for (var i = 0; i < px.length; i++) {
if (this["get" + pxf[i]]) {
o[px[i].toLowerCase()] = this["get" + pxf[i]]();
}
}
return o;
};
/**
* Returns a date created from an object literal. Ignores the .week property if set in the config.
* Example
<pre><code>
var o = new Date().toObject();
return Date.fromObject(o); // will return the same date.
var o2 = {month: 1, day: 20, hour: 18}; // birthday party!
Date.fromObject(o2);
</code></pre>
*
* @return {Date} An object literal representing the original date object.
*/
$D.fromObject = function(config) {
config.week = null;
return Date.today().set(config);
};
// Create day name functions and abbreviated day name functions (eg. monday(), friday(), fri()).
var df = function (n) {
return function () {
if (this._is) {
this._is = false;
return this.getDay() === n;
}
if (this._move) { this._move = null; }
if (this._nth !== null) {
// If the .second() function was called earlier, remove the _orient
// from the date, and then continue.
// This is required because 'second' can be used in two different context.
//
// Example
//
// Date.today().add(1).second();
// Date.march().second().monday();
//
// Things get crazy with the following...
// Date.march().add(1).second().second().monday(); // but it works!!
//
if (this._isSecond) {
this.addSeconds(this._orient * -1);
}
// make sure we reset _isSecond
this._isSecond = false;
var ntemp = this._nth;
this._nth = null;
var temp = this.clone().moveToLastDayOfMonth();
this.moveToNthOccurrence(n, ntemp);
if (this > temp) {
throw new RangeError($D.getDayName(n) + " does not occur " + ntemp + " times in the month of " + $D.getMonthName(temp.getMonth()) + " " + temp.getFullYear() + ".");
}
return this;
}
return this.moveToDayOfWeek(n, this._orient);
};
};
var sdf = function (n) {
return function () {
var t = $D.today(), shift = n - t.getDay();
if (n === 0 && Date.CultureInfo.firstDayOfWeek === 1 && t.getDay() !== 0) {
shift = shift + 7;
}
return t.addDays(shift);
};
};
// Create month name functions and abbreviated month name functions (eg. january(), march(), mar()).
var month_instance_functions = function (n) {
return function () {
if (this._is) {
this._is = false;
return this.getMonth() === n;
}
return this.moveToMonth(n, this._orient);
};
};
var month_static_functions = function (n) {
return function () {
return $D.today().set({ month: n, day: 1 });
};
};
var processTerms = function (names, staticFunc, instanceFunc) {
for (var i = 0; i < names.length; i++) {
// Create constant static Name variables.
$D[names[i].toUpperCase()] = $D[names[i].toUpperCase().substring(0, 3)] = i;
// Create Name functions.
$D[names[i]] = $D[names[i].substring(0, 3)] = staticFunc(i);
// Create Name instance functions.
$P[names[i]] = $P[names[i].substring(0, 3)] = instanceFunc(i);
}
};
processTerms(dx, sdf, df);
processTerms(mx, month_static_functions, month_instance_functions);
// Create date element functions and plural date element functions used with Date (eg. day(), days(), months()).
var ef = function (j) {
return function () {
// if the .second() function was called earlier, the _orient
// has alread been added. Just return this and reset _isSecond.
if (this._isSecond) {
this._isSecond = false;
return this;
}
if (this._same) {
this._same = this._is = false;
var o1 = this.toObject(),
o2 = (arguments[0] || new Date()).toObject(),
v = "",
k = j.toLowerCase();
// the substr trick with -1 doesn't work in IE8 or less
k = (k[k.length-1] === "s") ? k.substring(0,k.length-1) : k;
for (var m = (px.length - 1); m > -1; m--) {
v = px[m].toLowerCase();
if (o1[v] !== o2[v]) {
return false;
}
if (k === v) {
break;
}
}
return true;
}
if (j.substring(j.length - 1) !== "s") {
j += "s";
}
if (this._move) { this._move = null; }
return this["add" + j](this._orient);
};
};
var nf = function (n) {
return function () {
this._dateElement = n;
return this;
};
};
for (var k = 0; k < px.length; k++) {
de = px[k].toLowerCase();
if(de !== "weekday") {
// Create date element functions and plural date element functions used with Date (eg. day(), days(), months()).
$P[de] = $P[de + "s"] = ef(px[k]);
// Create date element functions and plural date element functions used with Number (eg. day(), days(), months()).
$N[de] = $N[de + "s"] = nf(de + "s");
}
}
$P._ss = ef("Second");
var nthfn = function (n) {
return function (dayOfWeek) {
if (this._same) {
return this._ss(arguments[0]);
}
if (dayOfWeek || dayOfWeek === 0) {
return this.moveToNthOccurrence(dayOfWeek, n);
}
this._nth = n;
// if the operator is 'second' add the _orient, then deal with it later...
if (n === 2 && (dayOfWeek === undefined || dayOfWeek === null)) {
this._isSecond = true;
return this.addSeconds(this._orient);
}
return this;
};
};
for (var l = 0; l < nth.length; l++) {
$P[nth[l]] = (l === 0) ? nthfn(-1) : nthfn(l);
}
}());
},{}],11:[function(require,module,exports){
(function () {
"use strict";
var attrs = ["years", "months", "days", "hours", "minutes", "seconds", "milliseconds"];
var gFn = function (attr) {
return function () {
return this[attr];
};
};
var sFn = function (attr) {
return function (val) {
this[attr] = val;
return this;
};
};
var addSetFuncs = function (context, attrs) {
for (var i = 0; i < attrs.length ; i++) {
var $a = attrs[i], $b = $a.slice(0, 1).toUpperCase() + $a.slice(1);
context.prototype[$a] = 0;
context.prototype["get" + $b] = gFn($a);
context.prototype["set" + $b] = sFn($a);
}
};
var setMonthsAndYears = function (orient, d1, d2, context) {
function inc() {
d1.addMonths(-orient);
context.months++;
if (context.months === 12) {
context.years++;
context.months = 0;
}
}
if (orient === +1) {
while (d1 > d2) {
inc();
}
} else {
while (d1 < d2) {
inc();
}
}
context.months--;
context.months *= orient;
context.years *= orient;
};
var adjustForDST = function(orient, startDate, endDate) {
var hasDSTMismatch = (false === (startDate.isDaylightSavingTime() === endDate.isDaylightSavingTime()));
if (hasDSTMismatch && orient === 1) {
startDate.addHours(-1);
} else if (hasDSTMismatch) {
startDate.addHours(1);
}
};
/**
* TimePeriod(startDate, endDate);
* TimePeriod(years, months, days, hours, minutes, seconds, milliseconds);
*/
var TimePeriod = function (years, months, days, hours, minutes, seconds, milliseconds) {
if (arguments.length === 7) {
this.set(years, months, days, hours, minutes, seconds, milliseconds);
} else if (arguments.length === 2 && arguments[0] instanceof Date && arguments[1] instanceof Date) {
var startDate = arguments[0].clone();
var endDate = arguments[1].clone();
var orient = (startDate > endDate) ? +1 : -1;
this.dates = {
start: arguments[0].clone(),
end: arguments[1].clone()
};
setMonthsAndYears(orient, startDate, endDate, this);
adjustForDST(orient, startDate, endDate);
// // TODO - adjust for DST
var diff = endDate - startDate;
if (diff !== 0) {
var ts = new TimeSpan(diff);
this.set(this.years, this.months, ts.getDays(), ts.getHours(), ts.getMinutes(), ts.getSeconds(), ts.getMilliseconds());
}
}
return this;
};
// create all the set functions.
addSetFuncs(TimePeriod, attrs);
TimePeriod.prototype.set = function (years, months, days, hours, minutes, seconds, milliseconds){
this.setYears(years || this.getYears());
this.setMonths(months || this.getMonths());
this.setDays(days || this.getDays());
this.setHours(hours || this.getHours());
this.setMinutes(minutes || this.getMinutes());
this.setSeconds(seconds || this.getSeconds());
this.setMilliseconds(milliseconds || this.getMilliseconds());
};
Date.TimePeriod = TimePeriod;
if (typeof window !== "undefined") {
// keeping API compatible for v1.x
window.TimePeriod = TimePeriod;
}
}());
},{}],12:[function(require,module,exports){
(function () {
"use strict";
var gFn = function (attr) {
return function () {
return this[attr];
};
};
var sFn = function (attr) {
return function (val) {
this[attr] = val;
return this;
};
};
var attrs = ["years", "months", "days", "hours", "minutes", "seconds", "milliseconds"];
var addSetFuncs = function (context, attrs) {
for (var i = 0; i < attrs.length ; i++) {
var $a = attrs[i], $b = $a.slice(0, 1).toUpperCase() + $a.slice(1);
context.prototype[$a] = 0;
context.prototype["get" + $b] = gFn($a);
context.prototype["set" + $b] = sFn($a);
}
};
/**
* new TimeSpan(milliseconds);
* new TimeSpan(days, hours, minutes, seconds);
* new TimeSpan(days, hours, minutes, seconds, milliseconds);
*/
var TimeSpan = function (days, hours, minutes, seconds, milliseconds) {
if (arguments.length === 1 && typeof days === "number") {
var orient = (days < 0) ? -1 : +1;
var millsLeft = Math.abs(days);
this.setDays(Math.floor(millsLeft / 86400000) * orient);
millsLeft = millsLeft % 86400000;
this.setHours(Math.floor(millsLeft / 3600000) * orient);
millsLeft = millsLeft % 3600000;
this.setMinutes(Math.floor(millsLeft / 60000) * orient);
millsLeft = millsLeft % 60000;
this.setSeconds(Math.floor(millsLeft / 1000) * orient);
millsLeft = millsLeft % 1000;
this.setMilliseconds(millsLeft * orient);
} else {
this.set(days, hours, minutes, seconds, milliseconds);
}
this.getTotalMilliseconds = function () {
return (this.getDays() * 86400000) +
(this.getHours() * 3600000) +
(this.getMinutes() * 60000) +
(this.getSeconds() * 1000);
};
this.compareTo = function (time) {
var t1 = new Date(1970, 1, 1, this.getHours(), this.getMinutes(), this.getSeconds()), t2;
if (time === null) {
t2 = new Date(1970, 1, 1, 0, 0, 0);
}
else {
t2 = new Date(1970, 1, 1, time.getHours(), time.getMinutes(), time.getSeconds());
}
return (t1 < t2) ? -1 : (t1 > t2) ? 1 : 0;
};
this.equals = function (time) {
return (this.compareTo(time) === 0);
};
this.add = function (time) {
return (time === null) ? this : this.addSeconds(time.getTotalMilliseconds() / 1000);
};
this.subtract = function (time) {
return (time === null) ? this : this.addSeconds(-time.getTotalMilliseconds() / 1000);
};
this.addDays = function (n) {
return new TimeSpan(this.getTotalMilliseconds() + (n * 86400000));
};
this.addHours = function (n) {
return new TimeSpan(this.getTotalMilliseconds() + (n * 3600000));
};
this.addMinutes = function (n) {
return new TimeSpan(this.getTotalMilliseconds() + (n * 60000));
};
this.addSeconds = function (n) {
return new TimeSpan(this.getTotalMilliseconds() + (n * 1000));
};
this.addMilliseconds = function (n) {
return new TimeSpan(this.getTotalMilliseconds() + n);
};
this.get12HourHour = function () {
return (this.getHours() > 12) ? this.getHours() - 12 : (this.getHours() === 0) ? 12 : this.getHours();
};
this.getDesignator = function () {
return (this.getHours() < 12) ? Date.CultureInfo.amDesignator : Date.CultureInfo.pmDesignator;
};
this.toString = function (format) {
this._toString = function () {
if (this.getDays() !== null && this.getDays() > 0) {
return this.getDays() + "." + this.getHours() + ":" + this.p(this.getMinutes()) + ":" + this.p(this.getSeconds());
} else {
return this.getHours() + ":" + this.p(this.getMinutes()) + ":" + this.p(this.getSeconds());
}
};
this.p = function (s) {
return (s.toString().length < 2) ? "0" + s : s;
};
var me = this;
return format ? format.replace(/dd?|HH?|hh?|mm?|ss?|tt?/g,
function (format) {
switch (format) {
case "d":
return me.getDays();
case "dd":
return me.p(me.getDays());
case "H":
return me.getHours();
case "HH":
return me.p(me.getHours());
case "h":
return me.get12HourHour();
case "hh":
return me.p(me.get12HourHour());
case "m":
return me.getMinutes();
case "mm":
return me.p(me.getMinutes());
case "s":
return me.getSeconds();
case "ss":
return me.p(me.getSeconds());
case "t":
return ((me.getHours() < 12) ? Date.CultureInfo.amDesignator : Date.CultureInfo.pmDesignator).substring(0, 1);
case "tt":
return (me.getHours() < 12) ? Date.CultureInfo.amDesignator : Date.CultureInfo.pmDesignator;
}
}
) : this._toString();
};
return this;
};
addSetFuncs(TimeSpan, attrs.slice(2));
TimeSpan.prototype.set = function (days, hours, minutes, seconds, milliseconds){
this.setDays(days || this.getDays());
this.setHours(hours || this.getHours());
this.setMinutes(minutes || this.getMinutes());
this.setSeconds(seconds || this.getSeconds());
this.setMilliseconds(milliseconds || this.getMilliseconds());
};
/**
* Gets the time of day for this date instances.
* @return {TimeSpan} TimeSpan
*/
Date.prototype.getTimeOfDay = function () {
return new TimeSpan(0, this.getHours(), this.getMinutes(), this.getSeconds(), this.getMilliseconds());
};
Date.TimeSpan = TimeSpan;
if (typeof window !== "undefined" ) {
// keeping API compatible for v1.x
window.TimeSpan = TimeSpan;
}
}());
},{}],"datejs":[function(require,module,exports){
/**
* @overview NPM Module index: include all the core modules, I18n files will be loaded on the fly.
* @author Gregory Wild-Smith <gregory@wild-smith.com>
*/
require("./src/core/i18n.js");
require("./src/core/core.js");
require("./src/core/core-prototypes.js");
require("./src/core/sugarpak.js");
require("./src/core/format_parser.js");
require("./src/core/parsing_operators.js");
require("./src/core/parsing_translator.js");
require("./src/core/parsing_grammar.js");
require("./src/core/parser.js");
require("./src/core/extras.js");
require("./src/core/time_period.js");
require("./src/core/time_span.js");
/*
* Notice that there is no model.export or exports. This is not required as it modifies the Date object and it's prototypes.
*/
},{"./src/core/core-prototypes.js":1,"./src/core/core.js":2,"./src/core/extras.js":3,"./src/core/format_parser.js":4,"./src/core/i18n.js":5,"./src/core/parser.js":6,"./src/core/parsing_grammar.js":7,"./src/core/parsing_operators.js":8,"./src/core/parsing_translator.js":9,"./src/core/sugarpak.js":10,"./src/core/time_period.js":11,"./src/core/time_span.js":12}]},{},[])
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL2hvbWUvYWRtaW4vYnJvd3NlcmlmeS1jZG4vbm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL2Jyb3dzZXItcGFjay9fcHJlbHVkZS5qcyIsInNyYy9jb3JlL2NvcmUtcHJvdG90eXBlcy5qcyIsInNyYy9jb3JlL2NvcmUuanMiLCJzcmMvY29yZS9leHRyYXMuanMiLCJzcmMvY29yZS9mb3JtYXRfcGFyc2VyLmpzIiwic3JjL2NvcmUvaTE4bi5qcyIsInNyYy9jb3JlL3BhcnNlci5qcyIsInNyYy9jb3JlL3BhcnNpbmdfZ3JhbW1hci5qcyIsInNyYy9jb3JlL3BhcnNpbmdfb3BlcmF0b3JzLmpzIiwic3JjL2NvcmUvcGFyc2luZ190cmFuc2xhdG9yLmpzIiwic3JjL2NvcmUvc3VnYXJwYWsuanMiLCJzcmMvY29yZS90aW1lX3BlcmlvZC5qcyIsInNyYy9jb3JlL3RpbWVfc3Bhbi5qcyIsImRhdGVqcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2h3QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2VkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6VEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9aQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JUQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdlQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9LQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIGUodCxuLHIpe2Z1bmN0aW9uIHMobyx1KXtpZighbltvXSl7aWYoIXRbb10pe3ZhciBhPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7aWYoIXUmJmEpcmV0dXJuIGEobywhMCk7aWYoaSlyZXR1cm4gaShvLCEwKTt2YXIgZj1uZXcgRXJyb3IoXCJDYW5ub3QgZmluZCBtb2R1bGUgJ1wiK28rXCInXCIpO3Rocm93IGYuY29kZT1cIk1PRFVMRV9OT1RfRk9VTkRcIixmfXZhciBsPW5bb109e2V4cG9ydHM6e319O3Rbb11bMF0uY2FsbChsLmV4cG9ydHMsZnVuY3Rpb24oZSl7dmFyIG49dFtvXVsxXVtlXTtyZXR1cm4gcyhuP246ZSl9LGwsbC5leHBvcnRzLGUsdCxuLHIpfXJldHVybiBuW29dLmV4cG9ydHN9dmFyIGk9dHlwZW9mIHJlcXVpcmU9PVwiZnVuY3Rpb25cIiYmcmVxdWlyZTtmb3IodmFyIG89MDtvPHIubGVuZ3RoO28rKylzKHJbb10pO3JldHVybiBzfSkiLCIoZnVuY3Rpb24gKCkge1xuXHR2YXIgJEQgPSBEYXRlLFxuXHRcdCRQID0gJEQucHJvdG90eXBlLFxuXHRcdHAgPSBmdW5jdGlvbiAocywgbCkge1xuXHRcdFx0aWYgKCFsKSB7XG5cdFx0XHRcdGwgPSAyO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIChcIjAwMFwiICsgcykuc2xpY2UobCAqIC0xKTtcblx0XHR9O1xuXG5cdHZhciB2YWxpZGF0ZUNvbmZpZ09iamVjdCA9IGZ1bmN0aW9uIChvYmopIHtcblx0XHR2YXIgcmVzdWx0ID0ge30sIHNlbGYgPSB0aGlzLCBwcm9wLCB0ZXN0RnVuYztcblx0XHR0ZXN0RnVuYyA9IGZ1bmN0aW9uIChwcm9wLCBmdW5jLCB2YWx1ZSkge1xuXHRcdFx0aWYgKHByb3AgPT09IFwiZGF5XCIpIHtcblx0XHRcdFx0dmFyIG1vbnRoID0gKG9iai5tb250aCAhPT0gdW5kZWZpbmVkKSA/IG9iai5tb250aCA6IHNlbGYuZ2V0TW9udGgoKTtcblx0XHRcdFx0dmFyIHllYXIgPSAob2JqLnllYXIgIT09IHVuZGVmaW5lZCkgPyBvYmoueWVhciA6IHNlbGYuZ2V0RnVsbFllYXIoKTtcblx0XHRcdFx0cmV0dXJuICREW2Z1bmNdKHZhbHVlLCB5ZWFyLCBtb250aCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gJERbZnVuY10odmFsdWUpO1xuXHRcdFx0fVxuXHRcdH07XG5cdFx0Zm9yIChwcm9wIGluIG9iaikge1xuXHRcdFx0aWYgKGhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkge1xuXHRcdFx0XHR2YXIgZnVuYyA9IFwidmFsaWRhdGVcIiArIHByb3AuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBwcm9wLnNsaWNlKDEpO1xuXG5cdFx0XHRcdGlmICgkRFtmdW5jXSAmJiBvYmpbcHJvcF0gIT09IG51bGwgJiYgdGVzdEZ1bmMocHJvcCwgZnVuYywgb2JqW3Byb3BdKSkge1xuXHRcdFx0XHRcdHJlc3VsdFtwcm9wXSA9IG9ialtwcm9wXTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdH1cblx0XHRyZXR1cm4gcmVzdWx0O1xuXHR9O1xuXHQvKipcblx0ICogUmVzZXRzIHRoZSB0aW1lIG9mIHRoaXMgRGF0ZSBvYmplY3QgdG8gMTI6MDAgQU0gKDAwOjAwKSwgd2hpY2ggaXMgdGhlIHN0YXJ0IG9mIHRoZSBkYXkuXG5cdCAqIEBwYXJhbSB7Qm9vbGVhbn0gIC5jbG9uZSgpIHRoaXMgZGF0ZSBpbnN0YW5jZSBiZWZvcmUgY2xlYXJpbmcgVGltZVxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICB0aGlzXG5cdCAqL1xuXHQkUC5jbGVhclRpbWUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5zZXRIb3VycygwKTtcblx0XHR0aGlzLnNldE1pbnV0ZXMoMCk7XG5cdFx0dGhpcy5zZXRTZWNvbmRzKDApO1xuXHRcdHRoaXMuc2V0TWlsbGlzZWNvbmRzKDApO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBSZXNldHMgdGhlIHRpbWUgb2YgdGhpcyBEYXRlIG9iamVjdCB0byB0aGUgY3VycmVudCB0aW1lICgnbm93JykuXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIHRoaXNcblx0ICovXG5cdCRQLnNldFRpbWVUb05vdyA9IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbiA9IG5ldyBEYXRlKCk7XG5cdFx0dGhpcy5zZXRIb3VycyhuLmdldEhvdXJzKCkpO1xuXHRcdHRoaXMuc2V0TWludXRlcyhuLmdldE1pbnV0ZXMoKSk7XG5cdFx0dGhpcy5zZXRTZWNvbmRzKG4uZ2V0U2Vjb25kcygpKTtcblx0XHR0aGlzLnNldE1pbGxpc2Vjb25kcyhuLmdldE1pbGxpc2Vjb25kcygpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fTtcblx0LyoqXG5cdCAqIFJldHVybnMgYSBuZXcgRGF0ZSBvYmplY3QgdGhhdCBpcyBhbiBleGFjdCBkYXRlIGFuZCB0aW1lIGNvcHkgb2YgdGhlIG9yaWdpbmFsIGluc3RhbmNlLlxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICBBIG5ldyBEYXRlIGluc3RhbmNlXG5cdCAqL1xuXHQkUC5jbG9uZSA9IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gbmV3IERhdGUodGhpcy5nZXRUaW1lKCkpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBDb21wYXJlcyB0aGlzIGluc3RhbmNlIHRvIGEgRGF0ZSBvYmplY3QgYW5kIHJldHVybnMgYW4gbnVtYmVyIGluZGljYXRpb24gb2YgdGhlaXIgcmVsYXRpdmUgdmFsdWVzLiAgXG5cdCAqIEBwYXJhbSB7RGF0ZX0gICAgIERhdGUgb2JqZWN0IHRvIGNvbXBhcmUgW1JlcXVpcmVkXVxuXHQgKiBAcmV0dXJuIHtOdW1iZXJ9ICAtMSA9IHRoaXMgaXMgbGVzc3RoYW4gZGF0ZS4gMCA9IHZhbHVlcyBhcmUgZXF1YWwuIDEgPSB0aGlzIGlzIGdyZWF0ZXJ0aGFuIGRhdGUuXG5cdCAqL1xuXHQkUC5jb21wYXJlVG8gPSBmdW5jdGlvbiAoZGF0ZSkge1xuXHRcdHJldHVybiBEYXRlLmNvbXBhcmUodGhpcywgZGF0ZSk7XG5cdH07XG5cblx0LyoqXG5cdCAqIENvbXBhcmVzIHRoaXMgaW5zdGFuY2UgdG8gYW5vdGhlciBEYXRlIG9iamVjdCBhbmQgcmV0dXJucyB0cnVlIGlmIHRoZXkgYXJlIGVxdWFsLiAgXG5cdCAqIEBwYXJhbSB7RGF0ZX0gICAgIERhdGUgb2JqZWN0IHRvIGNvbXBhcmUuIElmIG5vIGRhdGUgdG8gY29tcGFyZSwgbmV3IERhdGUoKSBbbm93XSBpcyB1c2VkLlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIGRhdGVzIGFyZSBlcXVhbC4gZmFsc2UgaWYgdGhleSBhcmUgbm90IGVxdWFsLlxuXHQgKi9cblx0JFAuZXF1YWxzID0gZnVuY3Rpb24gKGRhdGUpIHtcblx0XHRyZXR1cm4gRGF0ZS5lcXVhbHModGhpcywgKGRhdGUgIT09IHVuZGVmaW5lZCA/IGRhdGUgOiBuZXcgRGF0ZSgpKSk7XG5cdH07XG5cblx0LyoqXG5cdCAqIERldGVybWluZXMgaWYgdGhpcyBpbnN0YW5jZSBpcyBiZXR3ZWVuIGEgcmFuZ2Ugb2YgdHdvIGRhdGVzIG9yIGVxdWFsIHRvIGVpdGhlciB0aGUgc3RhcnQgb3IgZW5kIGRhdGVzLlxuXHQgKiBAcGFyYW0ge0RhdGV9ICAgICBTdGFydCBvZiByYW5nZSBbUmVxdWlyZWRdXG5cdCAqIEBwYXJhbSB7RGF0ZX0gICAgIEVuZCBvZiByYW5nZSBbUmVxdWlyZWRdXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaXMgdGhpcyBpcyBiZXR3ZWVuIG9yIGVxdWFsIHRvIHRoZSBzdGFydCBhbmQgZW5kIGRhdGVzLCBlbHNlIGZhbHNlXG5cdCAqL1xuXHQkUC5iZXR3ZWVuID0gZnVuY3Rpb24gKHN0YXJ0LCBlbmQpIHtcblx0XHRyZXR1cm4gdGhpcy5nZXRUaW1lKCkgPj0gc3RhcnQuZ2V0VGltZSgpICYmIHRoaXMuZ2V0VGltZSgpIDw9IGVuZC5nZXRUaW1lKCk7XG5cdH07XG5cblx0LyoqXG5cdCAqIERldGVybWluZXMgaWYgdGhpcyBkYXRlIG9jY3VycyBhZnRlciB0aGUgZGF0ZSB0byBjb21wYXJlIHRvLlxuXHQgKiBAcGFyYW0ge0RhdGV9ICAgICBEYXRlIG9iamVjdCB0byBjb21wYXJlLiBJZiBubyBkYXRlIHRvIGNvbXBhcmUsIG5ldyBEYXRlKCkgKFwibm93XCIpIGlzIHVzZWQuXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgdGhpcyBkYXRlIGluc3RhbmNlIGlzIGdyZWF0ZXIgdGhhbiB0aGUgZGF0ZSB0byBjb21wYXJlIHRvIChvciBcIm5vd1wiKSwgb3RoZXJ3aXNlIGZhbHNlLlxuXHQgKi9cblx0JFAuaXNBZnRlciA9IGZ1bmN0aW9uIChkYXRlKSB7XG5cdFx0cmV0dXJuIHRoaXMuY29tcGFyZVRvKGRhdGUgfHwgbmV3IERhdGUoKSkgPT09IDE7XG5cdH07XG5cblx0LyoqXG5cdCAqIERldGVybWluZXMgaWYgdGhpcyBkYXRlIG9jY3VycyBiZWZvcmUgdGhlIGRhdGUgdG8gY29tcGFyZSB0by5cblx0ICogQHBhcmFtIHtEYXRlfSAgICAgRGF0ZSBvYmplY3QgdG8gY29tcGFyZS4gSWYgbm8gZGF0ZSB0byBjb21wYXJlLCBuZXcgRGF0ZSgpIChcIm5vd1wiKSBpcyB1c2VkLlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHRoaXMgZGF0ZSBpbnN0YW5jZSBpcyBsZXNzIHRoYW4gdGhlIGRhdGUgdG8gY29tcGFyZSB0byAob3IgXCJub3dcIikuXG5cdCAqL1xuXHQkUC5pc0JlZm9yZSA9IGZ1bmN0aW9uIChkYXRlKSB7XG5cdFx0cmV0dXJuICh0aGlzLmNvbXBhcmVUbyhkYXRlIHx8IG5ldyBEYXRlKCkpID09PSAtMSk7XG5cdH07XG5cblx0LyoqXG5cdCAqIERldGVybWluZXMgaWYgdGhlIGN1cnJlbnQgRGF0ZSBpbnN0YW5jZSBvY2N1cnMgdG9kYXkuXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgdGhpcyBkYXRlIGluc3RhbmNlIGlzICd0b2RheScsIG90aGVyd2lzZSBmYWxzZS5cblx0ICovXG5cdFxuXHQvKipcblx0ICogRGV0ZXJtaW5lcyBpZiB0aGUgY3VycmVudCBEYXRlIGluc3RhbmNlIG9jY3VycyBvbiB0aGUgc2FtZSBEYXRlIGFzIHRoZSBzdXBwbGllZCAnZGF0ZScuIFxuXHQgKiBJZiBubyAnZGF0ZScgdG8gY29tcGFyZSB0byBpcyBwcm92aWRlZCwgdGhlIGN1cnJlbnQgRGF0ZSBpbnN0YW5jZSBpcyBjb21wYXJlZCB0byAndG9kYXknLiBcblx0ICogQHBhcmFtIHtkYXRlfSAgICAgRGF0ZSBvYmplY3QgdG8gY29tcGFyZS4gSWYgbm8gZGF0ZSB0byBjb21wYXJlLCB0aGUgY3VycmVudCBEYXRlIChcIm5vd1wiKSBpcyB1c2VkLlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHRoaXMgRGF0ZSBpbnN0YW5jZSBvY2N1cnMgb24gdGhlIHNhbWUgRGF5IGFzIHRoZSBzdXBwbGllZCAnZGF0ZScuXG5cdCAqL1xuXHQkUC5pc1RvZGF5ID0gJFAuaXNTYW1lRGF5ID0gZnVuY3Rpb24gKGRhdGUpIHtcblx0XHRyZXR1cm4gdGhpcy5jbG9uZSgpLmNsZWFyVGltZSgpLmVxdWFscygoZGF0ZSB8fCBuZXcgRGF0ZSgpKS5jbG9uZSgpLmNsZWFyVGltZSgpKTtcblx0fTtcblx0XG5cdC8qKlxuXHQgKiBBZGRzIHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyB0byB0aGlzIGluc3RhbmNlLiBcblx0ICogQHBhcmFtIHtOdW1iZXJ9ICAgVGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgdG8gYWRkLiBUaGUgbnVtYmVyIGNhbiBiZSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBbUmVxdWlyZWRdXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIHRoaXNcblx0ICovXG5cdCRQLmFkZE1pbGxpc2Vjb25kcyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdGlmICghdmFsdWUpIHsgcmV0dXJuIHRoaXM7IH1cblx0XHR0aGlzLnNldFRpbWUodGhpcy5nZXRUaW1lKCkgKyB2YWx1ZSAqIDEpO1xuXHRcdHJldHVybiB0aGlzO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBBZGRzIHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIHNlY29uZHMgdG8gdGhpcyBpbnN0YW5jZS4gXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSAgIFRoZSBudW1iZXIgb2Ygc2Vjb25kcyB0byBhZGQuIFRoZSBudW1iZXIgY2FuIGJlIHBvc2l0aXZlIG9yIG5lZ2F0aXZlIFtSZXF1aXJlZF1cblx0ICogQHJldHVybiB7RGF0ZX0gICAgdGhpc1xuXHQgKi9cblx0JFAuYWRkU2Vjb25kcyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdGlmICghdmFsdWUpIHsgcmV0dXJuIHRoaXM7IH1cblx0XHRyZXR1cm4gdGhpcy5hZGRNaWxsaXNlY29uZHModmFsdWUgKiAxMDAwKTtcblx0fTtcblxuXHQvKipcblx0ICogQWRkcyB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBzZWNvbmRzIHRvIHRoaXMgaW5zdGFuY2UuIFxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgbnVtYmVyIG9mIHNlY29uZHMgdG8gYWRkLiBUaGUgbnVtYmVyIGNhbiBiZSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBbUmVxdWlyZWRdXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIHRoaXNcblx0ICovXG5cdCRQLmFkZE1pbnV0ZXMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0XHRpZiAoIXZhbHVlKSB7IHJldHVybiB0aGlzOyB9XG5cdFx0cmV0dXJuIHRoaXMuYWRkTWlsbGlzZWNvbmRzKHZhbHVlICogNjAwMDApOyAvLyA2MCoxMDAwXG5cdH07XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgaG91cnMgdG8gdGhpcyBpbnN0YW5jZS4gXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSAgIFRoZSBudW1iZXIgb2YgaG91cnMgdG8gYWRkLiBUaGUgbnVtYmVyIGNhbiBiZSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBbUmVxdWlyZWRdXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIHRoaXNcblx0ICovXG5cdCRQLmFkZEhvdXJzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdFx0aWYgKCF2YWx1ZSkgeyByZXR1cm4gdGhpczsgfVxuXHRcdHJldHVybiB0aGlzLmFkZE1pbGxpc2Vjb25kcyh2YWx1ZSAqIDM2MDAwMDApOyAvLyA2MCo2MCoxMDAwXG5cdH07XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIHNwZWNpZmllZCBudW1iZXIgb2YgZGF5cyB0byB0aGlzIGluc3RhbmNlLiBcblx0ICogQHBhcmFtIHtOdW1iZXJ9ICAgVGhlIG51bWJlciBvZiBkYXlzIHRvIGFkZC4gVGhlIG51bWJlciBjYW4gYmUgcG9zaXRpdmUgb3IgbmVnYXRpdmUgW1JlcXVpcmVkXVxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICB0aGlzXG5cdCAqL1xuXHQkUC5hZGREYXlzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdFx0aWYgKCF2YWx1ZSkgeyByZXR1cm4gdGhpczsgfVxuXHRcdHRoaXMuc2V0RGF0ZSh0aGlzLmdldERhdGUoKSArIHZhbHVlICogMSk7XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH07XG5cblx0LyoqXG5cdCAqIEFkZHMgdGhlIHNwZWNpZmllZCBudW1iZXIgb2Ygd2Vla2RheXMgKGllIC0gbm90IHNhdCBvciBzdW4pIHRvIHRoaXMgaW5zdGFuY2UuIFxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgbnVtYmVyIG9mIGRheXMgdG8gYWRkLiBUaGUgbnVtYmVyIGNhbiBiZSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBbUmVxdWlyZWRdXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIHRoaXNcblx0ICovXG5cdCRQLmFkZFdlZWtkYXlzID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdFx0aWYgKCF2YWx1ZSkgeyByZXR1cm4gdGhpczsgfVxuXHRcdHZhciBkYXkgPSB0aGlzLmdldERheSgpO1xuXHRcdHZhciB3ZWVrcyA9IChNYXRoLmNlaWwoTWF0aC5hYnModmFsdWUpLzcpKTtcblx0XHRpZiAoZGF5ID09PSAwIHx8IGRheSA9PT0gNikge1xuXHRcdFx0aWYgKHZhbHVlID4gMCkge1xuXHRcdFx0XHR0aGlzLm5leHQoKS5tb25kYXkoKTtcblx0XHRcdFx0dGhpcy5hZGREYXlzKC0xKTtcblx0XHRcdFx0ZGF5ID0gdGhpcy5nZXREYXkoKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAodmFsdWUgPCAwKSB7XG5cdFx0XHR3aGlsZSAodmFsdWUgPCAwKSB7XG5cdFx0XHRcdHRoaXMuYWRkRGF5cygtMSk7XG5cdFx0XHRcdGRheSA9IHRoaXMuZ2V0RGF5KCk7XG5cdFx0XHRcdGlmIChkYXkgIT09IDAgJiYgZGF5ICE9PSA2KSB7XG5cdFx0XHRcdFx0dmFsdWUrKztcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSBlbHNlIGlmICh2YWx1ZSA+IDUgfHwgKDYtZGF5KSA8PSB2YWx1ZSkge1xuXHRcdFx0dmFsdWUgPSB2YWx1ZSArICh3ZWVrcyAqIDIpO1xuXHRcdH1cblxuXHRcdHJldHVybiB0aGlzLmFkZERheXModmFsdWUpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBBZGRzIHRoZSBzcGVjaWZpZWQgbnVtYmVyIG9mIHdlZWtzIHRvIHRoaXMgaW5zdGFuY2UuIFxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgbnVtYmVyIG9mIHdlZWtzIHRvIGFkZC4gVGhlIG51bWJlciBjYW4gYmUgcG9zaXRpdmUgb3IgbmVnYXRpdmUgW1JlcXVpcmVkXVxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICB0aGlzXG5cdCAqL1xuXHQkUC5hZGRXZWVrcyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdGlmICghdmFsdWUpIHsgcmV0dXJuIHRoaXM7IH1cblx0XHRyZXR1cm4gdGhpcy5hZGREYXlzKHZhbHVlICogNyk7XG5cdH07XG5cblxuXHQvKipcblx0ICogQWRkcyB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBtb250aHMgdG8gdGhpcyBpbnN0YW5jZS4gXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSAgIFRoZSBudW1iZXIgb2YgbW9udGhzIHRvIGFkZC4gVGhlIG51bWJlciBjYW4gYmUgcG9zaXRpdmUgb3IgbmVnYXRpdmUgW1JlcXVpcmVkXVxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICB0aGlzXG5cdCAqL1xuXHQkUC5hZGRNb250aHMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0XHRpZiAoIXZhbHVlKSB7IHJldHVybiB0aGlzOyB9XG5cdFx0dmFyIG4gPSB0aGlzLmdldERhdGUoKTtcblx0XHR0aGlzLnNldERhdGUoMSk7XG5cdFx0dGhpcy5zZXRNb250aCh0aGlzLmdldE1vbnRoKCkgKyB2YWx1ZSAqIDEpO1xuXHRcdHRoaXMuc2V0RGF0ZShNYXRoLm1pbihuLCAkRC5nZXREYXlzSW5Nb250aCh0aGlzLmdldEZ1bGxZZWFyKCksIHRoaXMuZ2V0TW9udGgoKSkpKTtcblx0XHRyZXR1cm4gdGhpcztcblx0fTtcblxuXHQkUC5hZGRRdWFydGVycyA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdGlmICghdmFsdWUpIHsgcmV0dXJuIHRoaXM7IH1cblx0XHQvLyBub3RlIHRoaXMgd2lsbCB0YWtlIHlvdSB0byB0aGUgc2FtZSBwb2ludCBpbiB0aGUgcXVhcnRlciBhcyB5b3UgYXJlIG5vdy5cblx0XHQvLyBpLmUuIC0gaWYgeW91IGFyZSAxNSBkYXlzIGludG8gdGhlIHF1YXJ0ZXIgeW91J2xsIGJlIDE1IGRheXMgaW50byB0aGUgcmVzdWx0aW5nIG9uZS5cblx0XHQvLyBib251czogdGhpcyBhbGxvd3MgYWRkaW5nIGZyYWN0aW9uYWwgcXVhcnRlcnNcblx0XHRyZXR1cm4gdGhpcy5hZGRNb250aHModmFsdWUgKiAzKTtcblx0fTtcblxuXHQvKipcblx0ICogQWRkcyB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiB5ZWFycyB0byB0aGlzIGluc3RhbmNlLiBcblx0ICogQHBhcmFtIHtOdW1iZXJ9ICAgVGhlIG51bWJlciBvZiB5ZWFycyB0byBhZGQuIFRoZSBudW1iZXIgY2FuIGJlIHBvc2l0aXZlIG9yIG5lZ2F0aXZlIFtSZXF1aXJlZF1cblx0ICogQHJldHVybiB7RGF0ZX0gICAgdGhpc1xuXHQgKi9cblx0JFAuYWRkWWVhcnMgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0XHRpZiAoIXZhbHVlKSB7IHJldHVybiB0aGlzOyB9XG5cdFx0cmV0dXJuIHRoaXMuYWRkTW9udGhzKHZhbHVlICogMTIpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBBZGRzIChvciBzdWJ0cmFjdHMpIHRvIHRoZSB2YWx1ZSBvZiB0aGUgeWVhcnMsIG1vbnRocywgd2Vla3MsIGRheXMsIGhvdXJzLCBtaW51dGVzLCBzZWNvbmRzLCBtaWxsaXNlY29uZHMgb2YgdGhlIGRhdGUgaW5zdGFuY2UgdXNpbmcgZ2l2ZW4gY29uZmlndXJhdGlvbiBvYmplY3QuIFBvc2l0aXZlIGFuZCBOZWdhdGl2ZSB2YWx1ZXMgYWxsb3dlZC5cblx0ICogRXhhbXBsZVxuXHQ8cHJlPjxjb2RlPlxuXHREYXRlLnRvZGF5KCkuYWRkKCB7IGRheXM6IDEsIG1vbnRoczogMSB9IClcblx0IFxuXHRuZXcgRGF0ZSgpLmFkZCggeyB5ZWFyczogLTEgfSApXG5cdDwvY29kZT48L3ByZT4gXG5cdCAqIEBwYXJhbSB7T2JqZWN0fSAgIENvbmZpZ3VyYXRpb24gb2JqZWN0IGNvbnRhaW5pbmcgYXR0cmlidXRlcyAobW9udGhzLCBkYXlzLCBldGMuKVxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICB0aGlzXG5cdCAqL1xuXHQkUC5hZGQgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG5cdFx0aWYgKHR5cGVvZiBjb25maWcgPT09IFwibnVtYmVyXCIpIHtcblx0XHRcdHRoaXMuX29yaWVudCA9IGNvbmZpZztcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblx0XHRcblx0XHR2YXIgeCA9IGNvbmZpZztcblxuXHRcdGlmICh4LmRheSkge1xuXHRcdFx0Ly8gSWYgd2Ugc2hvdWxkIGJlIGEgZGlmZmVyZW50IGRhdGUgdGhhbiB0b2RheSAoZWc6IGZvciAndG9tb3Jyb3cgLTFkJywgZXRjKS5cblx0XHRcdC8vIFNob3VsZCBvbmx5IGVmZmVjdCBwYXJzaW5nLCBub3QgZGlyZWN0IHVzYWdlIChlZywgRmluaXNoIGFuZCBGaW5pc2hFeGFjdClcblx0XHRcdGlmICgoeC5kYXkgLSB0aGlzLmdldERhdGUoKSkgIT09IDApIHtcblx0XHRcdFx0dGhpcy5zZXREYXRlKHguZGF5KTtcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKHgubWlsbGlzZWNvbmRzKSB7XG5cdFx0XHR0aGlzLmFkZE1pbGxpc2Vjb25kcyh4Lm1pbGxpc2Vjb25kcyk7XG5cdFx0fVxuXHRcdGlmICh4LnNlY29uZHMpIHtcblx0XHRcdHRoaXMuYWRkU2Vjb25kcyh4LnNlY29uZHMpO1xuXHRcdH1cblx0XHRpZiAoeC5taW51dGVzKSB7XG5cdFx0XHR0aGlzLmFkZE1pbnV0ZXMoeC5taW51dGVzKTtcblx0XHR9XG5cdFx0aWYgKHguaG91cnMpIHtcblx0XHRcdHRoaXMuYWRkSG91cnMoeC5ob3Vycyk7XG5cdFx0fVxuXHRcdGlmICh4LndlZWtzKSB7XG5cdFx0XHR0aGlzLmFkZFdlZWtzKHgud2Vla3MpO1xuXHRcdH1cblx0XHRpZiAoeC5tb250aHMpIHtcblx0XHRcdHRoaXMuYWRkTW9udGhzKHgubW9udGhzKTtcblx0XHR9XG5cdFx0aWYgKHgueWVhcnMpIHtcblx0XHRcdHRoaXMuYWRkWWVhcnMoeC55ZWFycyk7XG5cdFx0fVxuXHRcdGlmICh4LmRheXMpIHtcblx0XHRcdHRoaXMuYWRkRGF5cyh4LmRheXMpO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcztcblx0fTtcblx0XG5cdC8qKlxuXHQgKiBHZXQgdGhlIHdlZWsgbnVtYmVyLiBXZWVrIG9uZSAoMSkgaXMgdGhlIHdlZWsgd2hpY2ggY29udGFpbnMgdGhlIGZpcnN0IFRodXJzZGF5IG9mIHRoZSB5ZWFyLiBNb25kYXkgaXMgY29uc2lkZXJlZCB0aGUgZmlyc3QgZGF5IG9mIHRoZSB3ZWVrLlxuXHQgKiBUaGUgLmdldFdlZWsoKSBmdW5jdGlvbiBkb2VzIE5PVCBjb252ZXJ0IHRoZSBkYXRlIHRvIFVUQy4gVGhlIGxvY2FsIGRhdGV0aW1lIGlzIHVzZWQuIFxuXHQgKiBQbGVhc2UgdXNlIC5nZXRJU09XZWVrKCkgdG8gZ2V0IHRoZSB3ZWVrIG9mIHRoZSBVVEMgY29udmVydGVkIGRhdGUuXG5cdCAqIEByZXR1cm4ge051bWJlcn0gIDEgdG8gNTNcblx0ICovXG5cdCRQLmdldFdlZWsgPSBmdW5jdGlvbiAodXRjKSB7XG5cdFx0Ly8gQ3JlYXRlIGEgY29weSBvZiB0aGlzIGRhdGUgb2JqZWN0ICBcblx0XHR2YXIgc2VsZiwgdGFyZ2V0ID0gbmV3IERhdGUodGhpcy52YWx1ZU9mKCkpO1xuXHRcdGlmICh1dGMpIHtcblx0XHRcdHRhcmdldC5hZGRNaW51dGVzKHRhcmdldC5nZXRUaW1lem9uZU9mZnNldCgpKTtcblx0XHRcdHNlbGYgPSB0YXJnZXQuY2xvbmUoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0c2VsZiA9IHRoaXM7XG5cdFx0fVxuXHRcdC8vIElTTyB3ZWVrIGRhdGUgd2Vla3Mgc3RhcnQgb24gbW9uZGF5ICBcblx0XHQvLyBzbyBjb3JyZWN0IHRoZSBkYXkgbnVtYmVyICBcblx0XHR2YXIgZGF5TnIgPSAoc2VsZi5nZXREYXkoKSArIDYpICUgNztcblx0XHQvLyBJU08gODYwMSBzdGF0ZXMgdGhhdCB3ZWVrIDEgaXMgdGhlIHdlZWsgIFxuXHRcdC8vIHdpdGggdGhlIGZpcnN0IHRodXJzZGF5IG9mIHRoYXQgeWVhci4gIFxuXHRcdC8vIFNldCB0aGUgdGFyZ2V0IGRhdGUgdG8gdGhlIHRodXJzZGF5IGluIHRoZSB0YXJnZXQgd2VlayAgXG5cdFx0dGFyZ2V0LnNldERhdGUodGFyZ2V0LmdldERhdGUoKSAtIGRheU5yICsgMyk7XG5cdFx0Ly8gU3RvcmUgdGhlIG1pbGxpc2Vjb25kIHZhbHVlIG9mIHRoZSB0YXJnZXQgZGF0ZSAgXG5cdFx0dmFyIGZpcnN0VGh1cnNkYXkgPSB0YXJnZXQudmFsdWVPZigpO1xuXHRcdC8vIFNldCB0aGUgdGFyZ2V0IHRvIHRoZSBmaXJzdCB0aHVyc2RheSBvZiB0aGUgeWVhciAgXG5cdFx0Ly8gRmlyc3Qgc2V0IHRoZSB0YXJnZXQgdG8gamFudWFyeSBmaXJzdCAgXG5cdFx0dGFyZ2V0LnNldE1vbnRoKDAsIDEpO1xuXHRcdC8vIE5vdCBhIHRodXJzZGF5PyBDb3JyZWN0IHRoZSBkYXRlIHRvIHRoZSBuZXh0IHRodXJzZGF5ICBcblx0XHRpZiAodGFyZ2V0LmdldERheSgpICE9PSA0KSB7XG5cdFx0XHR0YXJnZXQuc2V0TW9udGgoMCwgMSArICgoNCAtIHRhcmdldC5nZXREYXkoKSkgKyA3KSAlIDcpO1xuXHRcdH1cblx0XHQvLyBUaGUgd2Vla251bWJlciBpcyB0aGUgbnVtYmVyIG9mIHdlZWtzIGJldHdlZW4gdGhlICAgXG5cdFx0Ly8gZmlyc3QgdGh1cnNkYXkgb2YgdGhlIHllYXIgYW5kIHRoZSB0aHVyc2RheSBpbiB0aGUgdGFyZ2V0IHdlZWsgIFxuXHRcdHJldHVybiAxICsgTWF0aC5jZWlsKChmaXJzdFRodXJzZGF5IC0gdGFyZ2V0KSAvIDYwNDgwMDAwMCk7IC8vIDYwNDgwMDAwMCA9IDcgKiAyNCAqIDM2MDAgKiAxMDAwICBcblx0fTtcblx0XG5cdC8qKlxuXHQgKiBHZXQgdGhlIElTTyA4NjAxIHdlZWsgbnVtYmVyLiBXZWVrIG9uZSAoXCIwMVwiKSBpcyB0aGUgd2VlayB3aGljaCBjb250YWlucyB0aGUgZmlyc3QgVGh1cnNkYXkgb2YgdGhlIHllYXIuIE1vbmRheSBpcyBjb25zaWRlcmVkIHRoZSBmaXJzdCBkYXkgb2YgdGhlIHdlZWsuXG5cdCAqIFRoZSAuZ2V0SVNPV2VlaygpIGZ1bmN0aW9uIGRvZXMgY29udmVydCB0aGUgZGF0ZSB0byBpdCdzIFVUQyB2YWx1ZS4gUGxlYXNlIHVzZSAuZ2V0V2VlaygpIHRvIGdldCB0aGUgd2VlayBvZiB0aGUgbG9jYWwgZGF0ZS5cblx0ICogQHJldHVybiB7U3RyaW5nfSAgXCIwMVwiIHRvIFwiNTNcIlxuXHQgKi9cblx0JFAuZ2V0SVNPV2VlayA9IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gcCh0aGlzLmdldFdlZWsodHJ1ZSkpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBNb3ZlcyB0aGUgZGF0ZSB0byBNb25kYXkgb2YgdGhlIHdlZWsgc2V0LiBXZWVrIG9uZSAoMSkgaXMgdGhlIHdlZWsgd2hpY2ggY29udGFpbnMgdGhlIGZpcnN0IFRodXJzZGF5IG9mIHRoZSB5ZWFyLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBBIE51bWJlciAoMSB0byA1MykgdGhhdCByZXByZXNlbnRzIHRoZSB3ZWVrIG9mIHRoZSB5ZWFyLlxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICB0aGlzXG5cdCAqL1xuXHQkUC5zZXRXZWVrID0gZnVuY3Rpb24gKG4pIHtcblx0XHRpZiAoKG4gLSB0aGlzLmdldFdlZWsoKSkgPT09IDApIHtcblx0XHRcdGlmICh0aGlzLmdldERheSgpICE9PSAxKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLm1vdmVUb0RheU9mV2VlaygxLCAodGhpcy5nZXREYXkoKSA+IDEgPyAtMSA6IDEpKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gdGhpcy5tb3ZlVG9EYXlPZldlZWsoMSwgKHRoaXMuZ2V0RGF5KCkgPiAxID8gLTEgOiAxKSkuYWRkV2Vla3MobiAtIHRoaXMuZ2V0V2VlaygpKTtcblx0XHR9XG5cdH07XG5cblx0JFAuc2V0UXVhcnRlciA9IGZ1bmN0aW9uIChxdHIpIHtcblx0XHR2YXIgbW9udGggPSBNYXRoLmFicygoKHF0ci0xKSAqIDMpICsgMSk7XG5cdFx0cmV0dXJuIHRoaXMuc2V0TW9udGgobW9udGgsIDEpO1xuXHR9O1xuXG5cdCRQLmdldFF1YXJ0ZXIgPSBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIERhdGUuZ2V0UXVhcnRlcih0aGlzKTtcblx0fTtcblxuXHQkUC5nZXREYXlzTGVmdEluUXVhcnRlciA9IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gRGF0ZS5nZXREYXlzTGVmdEluUXVhcnRlcih0aGlzKTtcblx0fTtcblxuXHQvKipcblx0ICogTW92ZXMgdGhlIGRhdGUgdG8gdGhlIG5leHQgbid0aCBvY2N1cnJlbmNlIG9mIHRoZSBkYXlPZldlZWsgc3RhcnRpbmcgZnJvbSB0aGUgYmVnaW5uaW5nIG9mIHRoZSBtb250aC4gVGhlIG51bWJlciAoLTEpIGlzIGEgbWFnaWMgbnVtYmVyIGFuZCB3aWxsIHJldHVybiB0aGUgbGFzdCBvY2N1cnJlbmNlIG9mIHRoZSBkYXlPZldlZWsgaW4gdGhlIG1vbnRoLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgZGF5T2ZXZWVrIHRvIG1vdmUgdG9cblx0ICogQHBhcmFtIHtOdW1iZXJ9ICAgVGhlIG4ndGggb2NjdXJyZW5jZSB0byBtb3ZlIHRvLiBVc2UgKC0xKSB0byByZXR1cm4gdGhlIGxhc3Qgb2NjdXJyZW5jZSBpbiB0aGUgbW9udGhcblx0ICogQHJldHVybiB7RGF0ZX0gICAgdGhpc1xuXHQgKi9cblx0JFAubW92ZVRvTnRoT2NjdXJyZW5jZSA9IGZ1bmN0aW9uIChkYXlPZldlZWssIG9jY3VycmVuY2UpIHtcblx0XHRpZiAoZGF5T2ZXZWVrID09PSBcIldlZWtkYXlcIikge1xuXHRcdFx0aWYgKG9jY3VycmVuY2UgPiAwKSB7XG5cdFx0XHRcdHRoaXMubW92ZVRvRmlyc3REYXlPZk1vbnRoKCk7XG5cdFx0XHRcdGlmICh0aGlzLmlzKCkud2Vla2RheSgpKSB7XG5cdFx0XHRcdFx0b2NjdXJyZW5jZSAtPSAxO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKG9jY3VycmVuY2UgPCAwKSB7XG5cdFx0XHRcdHRoaXMubW92ZVRvTGFzdERheU9mTW9udGgoKTtcblx0XHRcdFx0aWYgKHRoaXMuaXMoKS53ZWVrZGF5KCkpIHtcblx0XHRcdFx0XHRvY2N1cnJlbmNlICs9IDE7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiB0aGlzO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHRoaXMuYWRkV2Vla2RheXMob2NjdXJyZW5jZSk7XG5cdFx0fVxuXHRcdHZhciBzaGlmdCA9IDA7XG5cdFx0aWYgKG9jY3VycmVuY2UgPiAwKSB7XG5cdFx0XHRzaGlmdCA9IG9jY3VycmVuY2UgLSAxO1xuXHRcdH1cblx0XHRlbHNlIGlmIChvY2N1cnJlbmNlID09PSAtMSkge1xuXHRcdFx0dGhpcy5tb3ZlVG9MYXN0RGF5T2ZNb250aCgpO1xuXHRcdFx0aWYgKHRoaXMuZ2V0RGF5KCkgIT09IGRheU9mV2Vlaykge1xuXHRcdFx0XHR0aGlzLm1vdmVUb0RheU9mV2VlayhkYXlPZldlZWssIC0xKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH1cblx0XHRyZXR1cm4gdGhpcy5tb3ZlVG9GaXJzdERheU9mTW9udGgoKS5hZGREYXlzKC0xKS5tb3ZlVG9EYXlPZldlZWsoZGF5T2ZXZWVrLCArMSkuYWRkV2Vla3Moc2hpZnQpO1xuXHR9O1xuXG5cblx0dmFyIG1vdmVUb04gPSBmdW5jdGlvbiAoZ2V0RnVuYywgYWRkRnVuYywgblZhbCkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAodmFsdWUsIG9yaWVudCkge1xuXHRcdFx0dmFyIGRpZmYgPSAodmFsdWUgLSB0aGlzW2dldEZ1bmNdKCkgKyBuVmFsICogKG9yaWVudCB8fCArMSkpICUgblZhbDtcblx0XHRcdHJldHVybiB0aGlzW2FkZEZ1bmNdKChkaWZmID09PSAwKSA/IGRpZmYgKz0gblZhbCAqIChvcmllbnQgfHwgKzEpIDogZGlmZik7XG5cdFx0fTtcblx0fTtcblx0LyoqXG5cdCAqIE1vdmUgdG8gdGhlIG5leHQgb3IgbGFzdCBkYXlPZldlZWsgYmFzZWQgb24gdGhlIG9yaWVudCB2YWx1ZS5cblx0ICogQHBhcmFtIHtOdW1iZXJ9ICAgVGhlIGRheU9mV2VlayB0byBtb3ZlIHRvXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSAgIEZvcndhcmQgKCsxKSBvciBCYWNrICgtMSkuIERlZmF1bHRzIHRvICsxLiBbT3B0aW9uYWxdXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIHRoaXNcblx0ICovXG5cdCRQLm1vdmVUb0RheU9mV2VlayA9IG1vdmVUb04oXCJnZXREYXlcIiwgXCJhZGREYXlzXCIsIDcpO1xuXHQvKipcblx0ICogTW92ZSB0byB0aGUgbmV4dCBvciBsYXN0IG1vbnRoIGJhc2VkIG9uIHRoZSBvcmllbnQgdmFsdWUuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSAgIFRoZSBtb250aCB0byBtb3ZlIHRvLiAwID0gSmFudWFyeSwgMTEgPSBEZWNlbWJlclxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBGb3J3YXJkICgrMSkgb3IgQmFjayAoLTEpLiBEZWZhdWx0cyB0byArMS4gW09wdGlvbmFsXVxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICB0aGlzXG5cdCAqL1xuXHQkUC5tb3ZlVG9Nb250aCA9IG1vdmVUb04oXCJnZXRNb250aFwiLCBcImFkZE1vbnRoc1wiLCAxMik7XG5cdC8qKlxuXHQgKiBHZXQgdGhlIE9yZGluYXRlIG9mIHRoZSBjdXJyZW50IGRheSAoXCJ0aFwiLCBcInN0XCIsIFwicmRcIikuXG5cdCAqIEByZXR1cm4ge1N0cmluZ30gXG5cdCAqL1xuXHQkUC5nZXRPcmRpbmF0ZSA9IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgbnVtID0gdGhpcy5nZXREYXRlKCk7XG5cdFx0cmV0dXJuIG9yZChudW0pO1xuXHR9O1xuXHQvKipcblx0ICogR2V0IHRoZSBPcmRpbmFsIGRheSAobnVtZXJpYyBkYXkgbnVtYmVyKSBvZiB0aGUgeWVhciwgYWRqdXN0ZWQgZm9yIGxlYXAgeWVhci5cblx0ICogQHJldHVybiB7TnVtYmVyfSAxIHRocm91Z2ggMzY1ICgzNjYgaW4gbGVhcCB5ZWFycylcblx0ICovXG5cdCRQLmdldE9yZGluYWxOdW1iZXIgPSBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIE1hdGguY2VpbCgodGhpcy5jbG9uZSgpLmNsZWFyVGltZSgpIC0gbmV3IERhdGUodGhpcy5nZXRGdWxsWWVhcigpLCAwLCAxKSkgLyA4NjQwMDAwMCkgKyAxO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIHRpbWUgem9uZSBhYmJyZXZpYXRpb24gb2YgdGhlIGN1cnJlbnQgZGF0ZS5cblx0ICogQHJldHVybiB7U3RyaW5nfSBUaGUgYWJicmV2aWF0ZWQgdGltZSB6b25lIG5hbWUgKGUuZy4gXCJFU1RcIilcblx0ICovXG5cdCRQLmdldFRpbWV6b25lID0gZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiAkRC5nZXRUaW1lem9uZUFiYnJldmlhdGlvbih0aGlzLmdldFVUQ09mZnNldCgpLCB0aGlzLmlzRGF5bGlnaHRTYXZpbmdUaW1lKCkpO1xuXHR9O1xuXG5cdCRQLnNldFRpbWV6b25lT2Zmc2V0ID0gZnVuY3Rpb24gKG9mZnNldCkge1xuXHRcdHZhciBoZXJlID0gdGhpcy5nZXRUaW1lem9uZU9mZnNldCgpLCB0aGVyZSA9IE51bWJlcihvZmZzZXQpICogLTYgLyAxMDtcblx0XHRyZXR1cm4gKHRoZXJlIHx8IHRoZXJlID09PSAwKSA/IHRoaXMuYWRkTWludXRlcyh0aGVyZSAtIGhlcmUpIDogdGhpcztcblx0fTtcblxuXHQkUC5zZXRUaW1lem9uZSA9IGZ1bmN0aW9uIChvZmZzZXQpIHtcblx0XHRyZXR1cm4gdGhpcy5zZXRUaW1lem9uZU9mZnNldCgkRC5nZXRUaW1lem9uZU9mZnNldChvZmZzZXQpKTtcblx0fTtcblxuXHQvKipcblx0ICogSW5kaWNhdGVzIHdoZXRoZXIgRGF5bGlnaHQgU2F2aW5nIFRpbWUgaXMgb2JzZXJ2ZWQgaW4gdGhlIGN1cnJlbnQgdGltZSB6b25lLlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlfGZhbHNlXG5cdCAqL1xuXHQkUC5oYXNEYXlsaWdodFNhdmluZ1RpbWUgPSBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIChEYXRlLnRvZGF5KCkuc2V0KHttb250aDogMCwgZGF5OiAxfSkuZ2V0VGltZXpvbmVPZmZzZXQoKSAhPT0gRGF0ZS50b2RheSgpLnNldCh7bW9udGg6IDYsIGRheTogMX0pLmdldFRpbWV6b25lT2Zmc2V0KCkpO1xuXHR9O1xuXHRcblx0LyoqXG5cdCAqIEluZGljYXRlcyB3aGV0aGVyIHRoaXMgRGF0ZSBpbnN0YW5jZSBpcyB3aXRoaW4gdGhlIERheWxpZ2h0IFNhdmluZyBUaW1lIHJhbmdlIGZvciB0aGUgY3VycmVudCB0aW1lIHpvbmUuXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWV8ZmFsc2Vcblx0ICovXG5cdCRQLmlzRGF5bGlnaHRTYXZpbmdUaW1lID0gZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiBEYXRlLnRvZGF5KCkuc2V0KHttb250aDogMCwgZGF5OiAxfSkuZ2V0VGltZXpvbmVPZmZzZXQoKSAhPT0gdGhpcy5nZXRUaW1lem9uZU9mZnNldCgpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBHZXQgdGhlIG9mZnNldCBmcm9tIFVUQyBvZiB0aGUgY3VycmVudCBkYXRlLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9IFRoZSA0LWNoYXJhY3RlciBvZmZzZXQgc3RyaW5nIHByZWZpeGVkIHdpdGggKyBvciAtIChlLmcuIFwiLTA1MDBcIilcblx0ICovXG5cdCRQLmdldFVUQ09mZnNldCA9IGZ1bmN0aW9uIChvZmZzZXQpIHtcblx0XHR2YXIgbiA9IChvZmZzZXQgfHwgdGhpcy5nZXRUaW1lem9uZU9mZnNldCgpKSAqIC0xMCAvIDYsIHI7XG5cdFx0aWYgKG4gPCAwKSB7XG5cdFx0XHRyID0gKG4gLSAxMDAwMCkudG9TdHJpbmcoKTtcblx0XHRcdHJldHVybiByLmNoYXJBdCgwKSArIHIuc3Vic3RyKDIpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyID0gKG4gKyAxMDAwMCkudG9TdHJpbmcoKTtcblx0XHRcdHJldHVybiBcIitcIiArIHIuc3Vic3RyKDEpO1xuXHRcdH1cblx0fTtcblxuXHQvKipcblx0ICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBiZXR3ZWVuIHRoaXMgZGF0ZSBhbmQgZGF0ZS5cblx0ICogQHBhcmFtIHtEYXRlfSBEZWZhdWx0cyB0byBub3dcblx0ICogQHJldHVybiB7TnVtYmVyfSBUaGUgZGlmZiBpbiBtaWxsaXNlY29uZHNcblx0ICovXG5cdCRQLmdldEVsYXBzZWQgPSBmdW5jdGlvbiAoZGF0ZSkge1xuXHRcdHJldHVybiAoZGF0ZSB8fCBuZXcgRGF0ZSgpKSAtIHRoaXM7XG5cdH07XG5cblx0LyoqXG5cdCAqIFNldCB0aGUgdmFsdWUgb2YgeWVhciwgbW9udGgsIGRheSwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1pbGxpc2Vjb25kIG9mIGRhdGUgaW5zdGFuY2UgdXNpbmcgZ2l2ZW4gY29uZmlndXJhdGlvbiBvYmplY3QuXG5cdCAqIEV4YW1wbGVcblx0PHByZT48Y29kZT5cblx0RGF0ZS50b2RheSgpLnNldCggeyBkYXk6IDIwLCBtb250aDogMSB9IClcblxuXHRuZXcgRGF0ZSgpLnNldCggeyBtaWxsaXNlY29uZDogMCB9IClcblx0PC9jb2RlPjwvcHJlPlxuXHQgKiBcblx0ICogQHBhcmFtIHtPYmplY3R9ICAgQ29uZmlndXJhdGlvbiBvYmplY3QgY29udGFpbmluZyBhdHRyaWJ1dGVzIChtb250aCwgZGF5LCBldGMuKVxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICB0aGlzXG5cdCAqL1xuXHQkUC5zZXQgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG5cdFx0Y29uZmlnID0gdmFsaWRhdGVDb25maWdPYmplY3QuY2FsbCh0aGlzLCBjb25maWcpO1xuXHRcdHZhciBrZXk7XG5cdFx0Zm9yIChrZXkgaW4gY29uZmlnKSB7XG5cdFx0XHRpZiAoaGFzT3duUHJvcGVydHkuY2FsbChjb25maWcsIGtleSkpIHtcblx0XHRcdFx0dmFyIG5hbWUgPSBrZXkuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBrZXkuc2xpY2UoMSk7XG5cdFx0XHRcdHZhciBhZGRGdW5jLCBnZXRGdW5jO1xuXHRcdFx0XHRpZiAoa2V5ICE9PSBcIndlZWtcIiAmJiBrZXkgIT09IFwibW9udGhcIiAmJiBrZXkgIT09IFwidGltZXpvbmVcIiAmJiBrZXkgIT09IFwidGltZXpvbmVPZmZzZXRcIikge1xuXHRcdFx0XHRcdG5hbWUgKz0gXCJzXCI7XG5cdFx0XHRcdH1cblx0XHRcdFx0YWRkRnVuYyA9IFwiYWRkXCIgKyBuYW1lO1xuXHRcdFx0XHRnZXRGdW5jID0gXCJnZXRcIiArIG5hbWU7XG5cdFx0XHRcdGlmIChrZXkgPT09IFwibW9udGhcIikge1xuXHRcdFx0XHRcdGFkZEZ1bmMgPSBhZGRGdW5jICsgXCJzXCI7XG5cdFx0XHRcdH0gZWxzZSBpZiAoa2V5ID09PSBcInllYXJcIil7XG5cdFx0XHRcdFx0Z2V0RnVuYyA9IFwiZ2V0RnVsbFllYXJcIjtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoa2V5ICE9PSBcImRheVwiICYmIGtleSAhPT0gXCJ0aW1lem9uZVwiICYmIGtleSAhPT0gXCJ0aW1lem9uZU9mZnNldFwiICAmJiBrZXkgIT09IFwid2Vla1wiICYmICBrZXkgIT09IFwiaG91clwiKSB7XG5cdFx0XHRcdFx0XHR0aGlzW2FkZEZ1bmNdKGNvbmZpZ1trZXldIC0gdGhpc1tnZXRGdW5jXSgpKTtcblx0XHRcdFx0fSBlbHNlIGlmICgga2V5ID09PSBcInRpbWV6b25lXCJ8fCBrZXkgPT09IFwidGltZXpvbmVPZmZzZXRcIiB8fCBrZXkgPT09IFwid2Vla1wiIHx8IGtleSA9PT0gXCJob3VyXCIpIHtcblx0XHRcdFx0XHR0aGlzW1wic2V0XCIrbmFtZV0oY29uZmlnW2tleV0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdC8vIGRheSBoYXMgdG8gZ28gbGFzdCBiZWNhdXNlIHlvdSBjYW4ndCB2YWxpZGF0ZSB0aGUgZGF5IHdpdGhvdXQgZmlyc3Qga25vd2luZyB0aGUgbW9udGhcblx0XHRpZiAoY29uZmlnLmRheSkge1xuXHRcdFx0dGhpcy5hZGREYXlzKGNvbmZpZy5kYXkgLSB0aGlzLmdldERhdGUoKSk7XG5cdFx0fVxuXHRcdFxuXHRcdHJldHVybiB0aGlzO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBNb3ZlcyB0aGUgZGF0ZSB0byB0aGUgZmlyc3QgZGF5IG9mIHRoZSBtb250aC5cblx0ICogQHJldHVybiB7RGF0ZX0gICAgdGhpc1xuXHQgKi9cblx0JFAubW92ZVRvRmlyc3REYXlPZk1vbnRoID0gZnVuY3Rpb24gKCkge1xuXHRcdHJldHVybiB0aGlzLnNldCh7IGRheTogMSB9KTtcblx0fTtcblxuXHQvKipcblx0ICogTW92ZXMgdGhlIGRhdGUgdG8gdGhlIGxhc3QgZGF5IG9mIHRoZSBtb250aC5cblx0ICogQHJldHVybiB7RGF0ZX0gICAgdGhpc1xuXHQgKi9cblx0JFAubW92ZVRvTGFzdERheU9mTW9udGggPSBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIHRoaXMuc2V0KHsgZGF5OiAkRC5nZXREYXlzSW5Nb250aCh0aGlzLmdldEZ1bGxZZWFyKCksIHRoaXMuZ2V0TW9udGgoKSl9KTtcblx0fTtcblxuXG5cdC8qKlxuXHQgKiBDb252ZXJ0cyB0aGUgdmFsdWUgb2YgdGhlIGN1cnJlbnQgRGF0ZSBvYmplY3QgdG8gaXRzIGVxdWl2YWxlbnQgc3RyaW5nIHJlcHJlc2VudGF0aW9uLlxuXHQgKiBGb3JtYXQgU3BlY2lmaWVyc1xuXHQgKiBDVVNUT00gREFURSBBTkQgVElNRSBGT1JNQVQgU1RSSU5HU1xuXHQgKiBGb3JtYXQgIERlc2NyaXB0aW9uICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRXhhbXBsZVxuXHQgKiAtLS0tLS0gIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblx0ICogcyAgICAgIFRoZSBzZWNvbmRzIG9mIHRoZSBtaW51dGUgYmV0d2VlbiAwLTU5LiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIwXCIgdG8gXCI1OVwiXG5cdCAqIHNzICAgICBUaGUgc2Vjb25kcyBvZiB0aGUgbWludXRlIHdpdGggbGVhZGluZyB6ZXJvIGlmIHJlcXVpcmVkLiAgICAgICAgICAgICAgICAgICAgIFwiMDBcIiB0byBcIjU5XCJcblx0ICogXG5cdCAqIG0gICAgICBUaGUgbWludXRlIG9mIHRoZSBob3VyIGJldHdlZW4gMC01OS4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiMFwiICBvciBcIjU5XCJcblx0ICogbW0gICAgIFRoZSBtaW51dGUgb2YgdGhlIGhvdXIgd2l0aCBsZWFkaW5nIHplcm8gaWYgcmVxdWlyZWQuICAgICAgICAgICAgICAgICAgICAgICAgXCIwMFwiIG9yIFwiNTlcIlxuXHQgKiBcblx0ICogaCAgICAgIFRoZSBob3VyIG9mIHRoZSBkYXkgYmV0d2VlbiAxLTEyLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIxXCIgIHRvIFwiMTJcIlxuXHQgKiBoaCAgICAgVGhlIGhvdXIgb2YgdGhlIGRheSB3aXRoIGxlYWRpbmcgemVybyBpZiByZXF1aXJlZC4gICAgICAgICAgICAgICAgICAgICAgICAgICBcIjAxXCIgdG8gXCIxMlwiXG5cdCAqIFxuXHQgKiBIICAgICAgVGhlIGhvdXIgb2YgdGhlIGRheSBiZXR3ZWVuIDAtMjMuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIjBcIiAgdG8gXCIyM1wiXG5cdCAqIEhIICAgICBUaGUgaG91ciBvZiB0aGUgZGF5IHdpdGggbGVhZGluZyB6ZXJvIGlmIHJlcXVpcmVkLiAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiMDBcIiB0byBcIjIzXCJcblx0ICogXG5cdCAqIGQgICAgICBUaGUgZGF5IG9mIHRoZSBtb250aCBiZXR3ZWVuIDEgYW5kIDMxLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiMVwiICB0byBcIjMxXCJcblx0ICogZGQgICAgIFRoZSBkYXkgb2YgdGhlIG1vbnRoIHdpdGggbGVhZGluZyB6ZXJvIGlmIHJlcXVpcmVkLiAgICAgICAgICAgICAgICAgICAgICAgICAgXCIwMVwiIHRvIFwiMzFcIlxuXHQgKiBkZGQgICAgQWJicmV2aWF0ZWQgZGF5IG5hbWUuIERhdGUuQ3VsdHVyZUluZm8uYWJicmV2aWF0ZWREYXlOYW1lcy4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiTW9uXCIgdG8gXCJTdW5cIiBcblx0ICogZGRkZCAgIFRoZSBmdWxsIGRheSBuYW1lLiBEYXRlLkN1bHR1cmVJbmZvLmRheU5hbWVzLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIk1vbmRheVwiIHRvIFwiU3VuZGF5XCJcblx0ICogXG5cdCAqIE0gICAgICBUaGUgbW9udGggb2YgdGhlIHllYXIgYmV0d2VlbiAxLTEyLiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiMVwiIHRvIFwiMTJcIlxuXHQgKiBNTSAgICAgVGhlIG1vbnRoIG9mIHRoZSB5ZWFyIHdpdGggbGVhZGluZyB6ZXJvIGlmIHJlcXVpcmVkLiAgICAgICAgICAgICAgICAgICAgICAgICBcIjAxXCIgdG8gXCIxMlwiXG5cdCAqIE1NTSAgICBBYmJyZXZpYXRlZCBtb250aCBuYW1lLiBEYXRlLkN1bHR1cmVJbmZvLmFiYnJldmlhdGVkTW9udGhOYW1lcy4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJKYW5cIiB0byBcIkRlY1wiXG5cdCAqIE1NTU0gICBUaGUgZnVsbCBtb250aCBuYW1lLiBEYXRlLkN1bHR1cmVJbmZvLm1vbnRoTmFtZXMuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJKYW51YXJ5XCIgdG8gXCJEZWNlbWJlclwiXG5cdCAqXG5cdCAqIHl5ICAgICBUaGUgeWVhciBhcyBhIHR3by1kaWdpdCBudW1iZXIuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiOTlcIiBvciBcIjA4XCJcblx0ICogeXl5eSAgIFRoZSBmdWxsIGZvdXIgZGlnaXQgeWVhci4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCIxOTk5XCIgb3IgXCIyMDA4XCJcblx0ICogXG5cdCAqIHQgICAgICBEaXNwbGF5cyB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIHRoZSBBLk0uL1AuTS4gZGVzaWduYXRvci4gICAgICAgICAgICAgICAgICAgIFwiQVwiIG9yIFwiUFwiXG5cdCAqXHRcdERhdGUuQ3VsdHVyZUluZm8uYW1EZXNpZ25hdG9yIG9yIERhdGUuQ3VsdHVyZUluZm8ucG1EZXNpZ25hdG9yXG5cdCAqIHR0ICAgICBEaXNwbGF5cyB0aGUgQS5NLi9QLk0uIGRlc2lnbmF0b3IuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiQU1cIiBvciBcIlBNXCJcblx0ICpcdFx0RGF0ZS5DdWx0dXJlSW5mby5hbURlc2lnbmF0b3Igb3IgRGF0ZS5DdWx0dXJlSW5mby5wbURlc2lnbmF0b3Jcblx0ICogXG5cdCAqIFMgICAgICBUaGUgb3JkaW5hbCBzdWZmaXggKFwic3QsIFwibmRcIiwgXCJyZFwiIG9yIFwidGhcIikgb2YgdGhlIGN1cnJlbnQgZGF5LiAgICAgICAgICAgIFwic3QsIFwibmRcIiwgXCJyZFwiIG9yIFwidGhcIlxuXHQgKlxuXHQgKiBTVEFOREFSRCBEQVRFIEFORCBUSU1FIEZPUk1BVCBTVFJJTkdTXG5cdCAqIEZvcm1hdCAgRGVzY3JpcHRpb24gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBFeGFtcGxlXG5cdCAqLS0tLS0tICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cdCAqIGQgICAgICBUaGUgQ3VsdHVyZUluZm8gc2hvcnREYXRlIEZvcm1hdCBQYXR0ZXJuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiTS9kL3l5eXlcIlxuXHQgKiBEICAgICAgVGhlIEN1bHR1cmVJbmZvIGxvbmdEYXRlIEZvcm1hdCBQYXR0ZXJuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRkZGQsIE1NTU0gZGQsIHl5eXlcIlxuXHQgKiBGICAgICAgVGhlIEN1bHR1cmVJbmZvIGZ1bGxEYXRlVGltZSBGb3JtYXQgUGF0dGVybiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImRkZGQsIE1NTU0gZGQsIHl5eXkgaDptbTpzcyB0dFwiXG5cdCAqIG0gICAgICBUaGUgQ3VsdHVyZUluZm8gbW9udGhEYXkgRm9ybWF0IFBhdHRlcm4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiTU1NTSBkZFwiXG5cdCAqIHIgICAgICBUaGUgQ3VsdHVyZUluZm8gcmZjMTEyMyBGb3JtYXQgUGF0dGVybiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwiZGRkLCBkZCBNTU0geXl5eSBISDptbTpzcyBHTVRcIlxuXHQgKiBzICAgICAgVGhlIEN1bHR1cmVJbmZvIHNvcnRhYmxlRGF0ZVRpbWUgRm9ybWF0IFBhdHRlcm4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcInl5eXktTU0tZGRUSEg6bW06c3NcIlxuXHQgKiB0ICAgICAgVGhlIEN1bHR1cmVJbmZvIHNob3J0VGltZSBGb3JtYXQgUGF0dGVybiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImg6bW0gdHRcIlxuXHQgKiBUICAgICAgVGhlIEN1bHR1cmVJbmZvIGxvbmdUaW1lIEZvcm1hdCBQYXR0ZXJuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcImg6bW06c3MgdHRcIlxuXHQgKiB1ICAgICAgVGhlIEN1bHR1cmVJbmZvIHVuaXZlcnNhbFNvcnRhYmxlRGF0ZVRpbWUgRm9ybWF0IFBhdHRlcm4gICAgICAgICAgICAgICAgICAgICBcInl5eXktTU0tZGQgSEg6bW06c3NaXCJcblx0ICogeSAgICAgIFRoZSBDdWx0dXJlSW5mbyB5ZWFyTW9udGggRm9ybWF0IFBhdHRlcm4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgXCJNTU1NLCB5eXl5XCJcblx0ICpcblx0ICogQHBhcmFtIHtTdHJpbmd9ICAgQSBmb3JtYXQgc3RyaW5nIGNvbnNpc3Rpbmcgb2Ygb25lIG9yIG1vcmUgZm9ybWF0IHNwY2lmaWVycyBbT3B0aW9uYWxdLlxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9ICBBIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgY3VycmVudCBEYXRlIG9iamVjdC5cblx0ICovXG5cdFxuXHR2YXIgb3JkID0gZnVuY3Rpb24gKG4pIHtcblx0XHRzd2l0Y2ggKG4gKiAxKSB7XG5cdFx0Y2FzZSAxOlxuXHRcdGNhc2UgMjE6XG5cdFx0Y2FzZSAzMTpcblx0XHRcdHJldHVybiBcInN0XCI7XG5cdFx0Y2FzZSAyOlxuXHRcdGNhc2UgMjI6XG5cdFx0XHRyZXR1cm4gXCJuZFwiO1xuXHRcdGNhc2UgMzpcblx0XHRjYXNlIDIzOlxuXHRcdFx0cmV0dXJuIFwicmRcIjtcblx0XHRkZWZhdWx0OlxuXHRcdFx0cmV0dXJuIFwidGhcIjtcblx0XHR9XG5cdH07XG5cdHZhciBwYXJzZVN0YW5kYXJkRm9ybWF0cyA9IGZ1bmN0aW9uIChmb3JtYXQpIHtcblx0XHR2YXIgeSwgYyA9IERhdGUuQ3VsdHVyZUluZm8uZm9ybWF0UGF0dGVybnM7XG5cdFx0c3dpdGNoIChmb3JtYXQpIHtcblx0XHRcdGNhc2UgXCJkXCI6XG5cdFx0XHRcdHJldHVybiB0aGlzLnRvU3RyaW5nKGMuc2hvcnREYXRlKTtcblx0XHRcdGNhc2UgXCJEXCI6XG5cdFx0XHRcdHJldHVybiB0aGlzLnRvU3RyaW5nKGMubG9uZ0RhdGUpO1xuXHRcdFx0Y2FzZSBcIkZcIjpcblx0XHRcdFx0cmV0dXJuIHRoaXMudG9TdHJpbmcoYy5mdWxsRGF0ZVRpbWUpO1xuXHRcdFx0Y2FzZSBcIm1cIjpcblx0XHRcdFx0cmV0dXJuIHRoaXMudG9TdHJpbmcoYy5tb250aERheSk7XG5cdFx0XHRjYXNlIFwiclwiOlxuXHRcdFx0Y2FzZSBcIlJcIjpcblx0XHRcdFx0eSA9IHRoaXMuY2xvbmUoKS5hZGRNaW51dGVzKHRoaXMuZ2V0VGltZXpvbmVPZmZzZXQoKSk7XG5cdFx0XHRcdHJldHVybiB5LnRvU3RyaW5nKGMucmZjMTEyMykgKyBcIiBHTVRcIjtcblx0XHRcdGNhc2UgXCJzXCI6XG5cdFx0XHRcdHJldHVybiB0aGlzLnRvU3RyaW5nKGMuc29ydGFibGVEYXRlVGltZSk7XG5cdFx0XHRjYXNlIFwidFwiOlxuXHRcdFx0XHRyZXR1cm4gdGhpcy50b1N0cmluZyhjLnNob3J0VGltZSk7XG5cdFx0XHRjYXNlIFwiVFwiOlxuXHRcdFx0XHRyZXR1cm4gdGhpcy50b1N0cmluZyhjLmxvbmdUaW1lKTtcblx0XHRcdGNhc2UgXCJ1XCI6XG5cdFx0XHRcdHkgPSB0aGlzLmNsb25lKCkuYWRkTWludXRlcyh0aGlzLmdldFRpbWV6b25lT2Zmc2V0KCkpO1xuXHRcdFx0XHRyZXR1cm4geS50b1N0cmluZyhjLnVuaXZlcnNhbFNvcnRhYmxlRGF0ZVRpbWUpO1xuXHRcdFx0Y2FzZSBcInlcIjpcblx0XHRcdFx0cmV0dXJuIHRoaXMudG9TdHJpbmcoYy55ZWFyTW9udGgpO1xuXHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fTtcblx0dmFyIHBhcnNlRm9ybWF0U3RyaW5nc0Nsb3N1cmUgPSBmdW5jdGlvbiAoY29udGV4dCkge1xuXHRcdHJldHVybiBmdW5jdGlvbiAobSkge1xuXHRcdFx0aWYgKG0uY2hhckF0KDApID09PSBcIlxcXFxcIikge1xuXHRcdFx0XHRyZXR1cm4gbS5yZXBsYWNlKFwiXFxcXFwiLCBcIlwiKTtcblx0XHRcdH1cblx0XHRcdHN3aXRjaCAobSkge1xuXHRcdFx0XHRjYXNlIFwiaGhcIjpcblx0XHRcdFx0XHRyZXR1cm4gcChjb250ZXh0LmdldEhvdXJzKCkgPCAxMyA/IChjb250ZXh0LmdldEhvdXJzKCkgPT09IDAgPyAxMiA6IGNvbnRleHQuZ2V0SG91cnMoKSkgOiAoY29udGV4dC5nZXRIb3VycygpIC0gMTIpKTtcblx0XHRcdFx0Y2FzZSBcImhcIjpcblx0XHRcdFx0XHRyZXR1cm4gY29udGV4dC5nZXRIb3VycygpIDwgMTMgPyAoY29udGV4dC5nZXRIb3VycygpID09PSAwID8gMTIgOiBjb250ZXh0LmdldEhvdXJzKCkpIDogKGNvbnRleHQuZ2V0SG91cnMoKSAtIDEyKTtcblx0XHRcdFx0Y2FzZSBcIkhIXCI6XG5cdFx0XHRcdFx0cmV0dXJuIHAoY29udGV4dC5nZXRIb3VycygpKTtcblx0XHRcdFx0Y2FzZSBcIkhcIjpcblx0XHRcdFx0XHRyZXR1cm4gY29udGV4dC5nZXRIb3VycygpO1xuXHRcdFx0XHRjYXNlIFwibW1cIjpcblx0XHRcdFx0XHRyZXR1cm4gcChjb250ZXh0LmdldE1pbnV0ZXMoKSk7XG5cdFx0XHRcdGNhc2UgXCJtXCI6XG5cdFx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0TWludXRlcygpO1xuXHRcdFx0XHRjYXNlIFwic3NcIjpcblx0XHRcdFx0XHRyZXR1cm4gcChjb250ZXh0LmdldFNlY29uZHMoKSk7XG5cdFx0XHRcdGNhc2UgXCJzXCI6XG5cdFx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0U2Vjb25kcygpO1xuXHRcdFx0XHRjYXNlIFwieXl5eVwiOlxuXHRcdFx0XHRcdHJldHVybiBwKGNvbnRleHQuZ2V0RnVsbFllYXIoKSwgNCk7XG5cdFx0XHRcdGNhc2UgXCJ5eVwiOlxuXHRcdFx0XHRcdHJldHVybiBwKGNvbnRleHQuZ2V0RnVsbFllYXIoKSk7XG5cdFx0XHRcdGNhc2UgXCJ5XCI6XG5cdFx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0RnVsbFllYXIoKTtcblx0XHRcdFx0Y2FzZSBcIkVcIjpcblx0XHRcdFx0Y2FzZSBcImRkZGRcIjpcblx0XHRcdFx0XHRyZXR1cm4gRGF0ZS5DdWx0dXJlSW5mby5kYXlOYW1lc1tjb250ZXh0LmdldERheSgpXTtcblx0XHRcdFx0Y2FzZSBcImRkZFwiOlxuXHRcdFx0XHRcdHJldHVybiBEYXRlLkN1bHR1cmVJbmZvLmFiYnJldmlhdGVkRGF5TmFtZXNbY29udGV4dC5nZXREYXkoKV07XG5cdFx0XHRcdGNhc2UgXCJkZFwiOlxuXHRcdFx0XHRcdHJldHVybiBwKGNvbnRleHQuZ2V0RGF0ZSgpKTtcblx0XHRcdFx0Y2FzZSBcImRcIjpcblx0XHRcdFx0XHRyZXR1cm4gY29udGV4dC5nZXREYXRlKCk7XG5cdFx0XHRcdGNhc2UgXCJNTU1NXCI6XG5cdFx0XHRcdFx0cmV0dXJuIERhdGUuQ3VsdHVyZUluZm8ubW9udGhOYW1lc1tjb250ZXh0LmdldE1vbnRoKCldO1xuXHRcdFx0XHRjYXNlIFwiTU1NXCI6XG5cdFx0XHRcdFx0cmV0dXJuIERhdGUuQ3VsdHVyZUluZm8uYWJicmV2aWF0ZWRNb250aE5hbWVzW2NvbnRleHQuZ2V0TW9udGgoKV07XG5cdFx0XHRcdGNhc2UgXCJNTVwiOlxuXHRcdFx0XHRcdHJldHVybiBwKChjb250ZXh0LmdldE1vbnRoKCkgKyAxKSk7XG5cdFx0XHRcdGNhc2UgXCJNXCI6XG5cdFx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0TW9udGgoKSArIDE7XG5cdFx0XHRcdGNhc2UgXCJ0XCI6XG5cdFx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0SG91cnMoKSA8IDEyID8gRGF0ZS5DdWx0dXJlSW5mby5hbURlc2lnbmF0b3Iuc3Vic3RyaW5nKDAsIDEpIDogRGF0ZS5DdWx0dXJlSW5mby5wbURlc2lnbmF0b3Iuc3Vic3RyaW5nKDAsIDEpO1xuXHRcdFx0XHRjYXNlIFwidHRcIjpcblx0XHRcdFx0XHRyZXR1cm4gY29udGV4dC5nZXRIb3VycygpIDwgMTIgPyBEYXRlLkN1bHR1cmVJbmZvLmFtRGVzaWduYXRvciA6IERhdGUuQ3VsdHVyZUluZm8ucG1EZXNpZ25hdG9yO1xuXHRcdFx0XHRjYXNlIFwiU1wiOlxuXHRcdFx0XHRcdHJldHVybiBvcmQoY29udGV4dC5nZXREYXRlKCkpO1xuXHRcdFx0XHRjYXNlIFwiV1wiOlxuXHRcdFx0XHRcdHJldHVybiBjb250ZXh0LmdldFdlZWsoKTtcblx0XHRcdFx0Y2FzZSBcIldXXCI6XG5cdFx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0SVNPV2VlaygpO1xuXHRcdFx0XHRjYXNlIFwiUVwiOlxuXHRcdFx0XHRcdHJldHVybiBcIlFcIiArIGNvbnRleHQuZ2V0UXVhcnRlcigpO1xuXHRcdFx0XHRjYXNlIFwicVwiOlxuXHRcdFx0XHRcdHJldHVybiBTdHJpbmcoY29udGV4dC5nZXRRdWFydGVyKCkpO1xuXHRcdFx0XHRjYXNlIFwielwiOlxuXHRcdFx0XHRcdHJldHVybiBjb250ZXh0LmdldFRpbWV6b25lKCk7XG5cdFx0XHRcdGNhc2UgXCJaXCI6XG5cdFx0XHRcdGNhc2UgXCJYXCI6XG5cdFx0XHRcdFx0cmV0dXJuIERhdGUuZ2V0VGltZXpvbmVPZmZzZXQoY29udGV4dC5nZXRUaW1lem9uZSgpKTtcblx0XHRcdFx0Y2FzZSBcIlpaXCI6IC8vIFRpbWV6b25lIG9mZnNldCBpbiBzZWNvbmRzXG5cdFx0XHRcdFx0cmV0dXJuIGNvbnRleHQuZ2V0VGltZXpvbmVPZmZzZXQoKSAqIC02MDtcblx0XHRcdFx0Y2FzZSBcInVcIjpcblx0XHRcdFx0XHRyZXR1cm4gY29udGV4dC5nZXREYXkoKTtcblx0XHRcdFx0Y2FzZSBcIkxcIjpcblx0XHRcdFx0XHRyZXR1cm4gKCRELmlzTGVhcFllYXIoY29udGV4dC5nZXRGdWxsWWVhcigpKSkgPyAxIDogMDtcblx0XHRcdFx0Y2FzZSBcIkJcIjpcblx0XHRcdFx0XHQvLyBTd2F0Y2ggSW50ZXJuZXQgVGltZSAoLmJlYXRzKVxuXHRcdFx0XHRcdHJldHVybiBcIkBcIisoKGNvbnRleHQuZ2V0VVRDU2Vjb25kcygpICsgKGNvbnRleHQuZ2V0VVRDTWludXRlcygpKjYwKSArICgoY29udGV4dC5nZXRVVENIb3VycygpKzEpKjM2MDApKS84Ni40KTtcblx0XHRcdFx0ZGVmYXVsdDpcblx0XHRcdFx0XHRyZXR1cm4gbTtcblx0XHRcdH1cblx0XHR9O1xuXHR9O1xuXHQkUC50b1N0cmluZyA9IGZ1bmN0aW9uIChmb3JtYXQsIGlnbm9yZVN0YW5kYXJkcykge1xuXHRcdFxuXHRcdC8vIFN0YW5kYXJkIERhdGUgYW5kIFRpbWUgRm9ybWF0IFN0cmluZ3MuIEZvcm1hdHMgcHVsbGVkIGZyb20gQ3VsdHVyZUluZm8gZmlsZSBhbmRcblx0XHQvLyBtYXkgdmFyeSBieSBjdWx0dXJlLiBcblx0XHRpZiAoIWlnbm9yZVN0YW5kYXJkcyAmJiBmb3JtYXQgJiYgZm9ybWF0Lmxlbmd0aCA9PT0gMSkge1xuXHRcdFx0b3V0cHV0ID0gcGFyc2VTdGFuZGFyZEZvcm1hdHMuY2FsbCh0aGlzLCBmb3JtYXQpO1xuXHRcdFx0aWYgKG91dHB1dCkge1xuXHRcdFx0XHRyZXR1cm4gb3V0cHV0O1xuXHRcdFx0fVxuXHRcdH1cblx0XHR2YXIgcGFyc2VGb3JtYXRTdHJpbmdzID0gcGFyc2VGb3JtYXRTdHJpbmdzQ2xvc3VyZSh0aGlzKTtcblx0XHRyZXR1cm4gZm9ybWF0ID8gZm9ybWF0LnJlcGxhY2UoLygoXFxcXCk/KGRkP2Q/ZD98TU0/TT9NP3x5eT95P3k/fGhoP3xISD98bW0/fHNzP3x0dD98U3xxfFF8V1c/Vz9XPykoPyFbXlxcW10qXFxdKSkvZywgcGFyc2VGb3JtYXRTdHJpbmdzKS5yZXBsYWNlKC9cXFt8XFxdL2csIFwiXCIpIDogdGhpcy5fdG9TdHJpbmcoKTtcblx0fTtcblxufSgpKTsiLCIoZnVuY3Rpb24gKCkge1xuXHR2YXIgJEQgPSBEYXRlLFxuXHRcdCRQID0gJEQucHJvdG90eXBlLFxuXHRcdHAgPSBmdW5jdGlvbiAocywgbCkge1xuXHRcdFx0aWYgKCFsKSB7XG5cdFx0XHRcdGwgPSAyO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIChcIjAwMFwiICsgcykuc2xpY2UobCAqIC0xKTtcblx0XHR9O1xuXHRcblx0aWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgJiYgdHlwZW9mIHdpbmRvdy5jb25zb2xlICE9PSBcInVuZGVmaW5lZFwiICYmIHR5cGVvZiB3aW5kb3cuY29uc29sZS5sb2cgIT09IFwidW5kZWZpbmVkXCIpIHtcblx0XHQkRC5jb25zb2xlID0gY29uc29sZTsgLy8gdXNlZCBvbmx5IHRvIHJhaXNlIG5vbi1jcml0aWNhbCBlcnJvcnMgaWYgYXZhaWxhYmxlXG5cdH0gZWxzZSB7XG5cdFx0Ly8gc2V0IG1vY2sgc28gd2UgZG9uJ3QgZ2l2ZSBlcnJvcnMuXG5cdFx0JEQuY29uc29sZSA9IHtcblx0XHRcdGxvZzogZnVuY3Rpb24oKXt9LFxuXHRcdFx0ZXJyb3I6IGZ1bmN0aW9uKCl7fVxuXHRcdH07XG5cdH1cblx0JEQuQ29uZmlnID0gJEQuQ29uZmlnIHx8IHt9O1xuXG5cdCRELmluaXRPdmVybG9hZHMgPSBmdW5jdGlvbigpIHtcblx0XHQvKiogXG5cdFx0ICogT3ZlcmxvYWQgb2YgRGF0ZS5ub3cuIEFsbG93cyBhbiBhbHRlcm5hdGUgY2FsbCBmb3IgRGF0ZS5ub3cgd2hlcmUgaXQgcmV0dXJucyB0aGUgXG5cdFx0ICogY3VycmVudCBEYXRlIGFzIGFuIG9iamVjdCByYXRoZXIgdGhhbiBqdXN0IG1pbGxpc2Vjb25kcyBzaW5jZSB0aGUgVW5peCBFcG9jaC5cblx0XHQgKlxuXHRcdCAqIEFsc28gcHJvdmlkZXMgYW4gaW1wbGVtZW50YXRpb24gb2Ygbm93KCkgZm9yIGJyb3dzZXJzIChJRTw5KSB0aGF0IGRvbid0IGhhdmUgaXQuXG5cdFx0ICogXG5cdFx0ICogQmFja3dhcmRzIGNvbXBhdGlibGUgc28gd2l0aCB3b3JrIHdpdGggZWl0aGVyOlxuXHRcdCAqICBEYXRlLm5vdygpIFtyZXR1cm5zIG1zXVxuXHRcdCAqIG9yXG5cdFx0ICogIERhdGUubm93KHRydWUpIFtyZXR1cm5zIERhdGVdXG5cdFx0ICovXG5cdFx0aWYgKCEkRC5ub3cpIHtcblx0XHRcdCRELl9ub3cgPSBmdW5jdGlvbiBub3coKSB7XG5cdFx0XHRcdHJldHVybiBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblx0XHRcdH07XG5cdFx0fSBlbHNlIGlmICghJEQuX25vdykge1xuXHRcdFx0JEQuX25vdyA9ICRELm5vdztcblx0XHR9XG5cblx0XHQkRC5ub3cgPSBmdW5jdGlvbiAocmV0dXJuT2JqKSB7XG5cdFx0XHRpZiAocmV0dXJuT2JqKSB7XG5cdFx0XHRcdHJldHVybiAkRC5wcmVzZW50KCk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gJEQuX25vdygpO1xuXHRcdFx0fVxuXHRcdH07XG5cblx0XHRpZiAoICEkUC50b0lTT1N0cmluZyApIHtcblx0XHRcdCRQLnRvSVNPU3RyaW5nID0gZnVuY3Rpb24oKSB7XG5cdFx0XHRcdHJldHVybiB0aGlzLmdldFVUQ0Z1bGxZZWFyKCkgK1xuXHRcdFx0XHRcIi1cIiArIHAodGhpcy5nZXRVVENNb250aCgpICsgMSkgK1xuXHRcdFx0XHRcIi1cIiArIHAodGhpcy5nZXRVVENEYXRlKCkpICtcblx0XHRcdFx0XCJUXCIgKyBwKHRoaXMuZ2V0VVRDSG91cnMoKSkgK1xuXHRcdFx0XHRcIjpcIiArIHAodGhpcy5nZXRVVENNaW51dGVzKCkpICtcblx0XHRcdFx0XCI6XCIgKyBwKHRoaXMuZ2V0VVRDU2Vjb25kcygpKSArXG5cdFx0XHRcdFwiLlwiICsgU3RyaW5nKCAodGhpcy5nZXRVVENNaWxsaXNlY29uZHMoKS8xMDAwKS50b0ZpeGVkKDMpKS5zbGljZSgyLCA1KSArXG5cdFx0XHRcdFwiWlwiO1xuXHRcdFx0fTtcblx0XHR9XG5cdFx0XG5cdFx0Ly8gcHJpdmF0ZVxuXHRcdGlmICggJFAuX3RvU3RyaW5nID09PSB1bmRlZmluZWQgKXtcblx0XHRcdCRQLl90b1N0cmluZyA9ICRQLnRvU3RyaW5nO1xuXHRcdH1cblxuXHR9O1xuXHQkRC5pbml0T3ZlcmxvYWRzKCk7XG5cblxuXHQvKiogXG5cdCAqIEdldHMgYSBkYXRlIHRoYXQgaXMgc2V0IHRvIHRoZSBjdXJyZW50IGRhdGUuIFRoZSB0aW1lIGlzIHNldCB0byB0aGUgc3RhcnQgb2YgdGhlIGRheSAoMDA6MDAgb3IgMTI6MDAgQU0pLlxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICBUaGUgY3VycmVudCBkYXRlLlxuXHQgKi9cblx0JEQudG9kYXkgPSBmdW5jdGlvbiAoKSB7XG5cdFx0cmV0dXJuIG5ldyBEYXRlKCkuY2xlYXJUaW1lKCk7XG5cdH07XG5cblx0LyoqIFxuXHQgKiBHZXRzIGEgZGF0ZSB0aGF0IGlzIHNldCB0byB0aGUgY3VycmVudCBkYXRlIGFuZCB0aW1lIChzYW1lIGFzIG5ldyBEYXRlLCBidXQgY2hhaW5hYmxlKVxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICBUaGUgY3VycmVudCBkYXRlLlxuXHQgKi9cblx0JEQucHJlc2VudCA9IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gbmV3IERhdGUoKTtcblx0fTtcblxuXHQvKipcblx0ICogQ29tcGFyZXMgdGhlIGZpcnN0IGRhdGUgdG8gdGhlIHNlY29uZCBkYXRlIGFuZCByZXR1cm5zIGFuIG51bWJlciBpbmRpY2F0aW9uIG9mIHRoZWlyIHJlbGF0aXZlIHZhbHVlcy4gIFxuXHQgKiBAcGFyYW0ge0RhdGV9ICAgICBGaXJzdCBEYXRlIG9iamVjdCB0byBjb21wYXJlIFtSZXF1aXJlZF0uXG5cdCAqIEBwYXJhbSB7RGF0ZX0gICAgIFNlY29uZCBEYXRlIG9iamVjdCB0byBjb21wYXJlIHRvIFtSZXF1aXJlZF0uXG5cdCAqIEByZXR1cm4ge051bWJlcn0gIC0xID0gZGF0ZTEgaXMgbGVzc3RoYW4gZGF0ZTIuIDAgPSB2YWx1ZXMgYXJlIGVxdWFsLiAxID0gZGF0ZTEgaXMgZ3JlYXRlcnRoYW4gZGF0ZTIuXG5cdCAqL1xuXHQkRC5jb21wYXJlID0gZnVuY3Rpb24gKGRhdGUxLCBkYXRlMikge1xuXHRcdGlmIChpc05hTihkYXRlMSkgfHwgaXNOYU4oZGF0ZTIpKSB7XG5cdFx0XHR0aHJvdyBuZXcgRXJyb3IoZGF0ZTEgKyBcIiAtIFwiICsgZGF0ZTIpO1xuXHRcdH0gZWxzZSBpZiAoZGF0ZTEgaW5zdGFuY2VvZiBEYXRlICYmIGRhdGUyIGluc3RhbmNlb2YgRGF0ZSkge1xuXHRcdFx0cmV0dXJuIChkYXRlMSA8IGRhdGUyKSA/IC0xIDogKGRhdGUxID4gZGF0ZTIpID8gMSA6IDA7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRocm93IG5ldyBUeXBlRXJyb3IoZGF0ZTEgKyBcIiAtIFwiICsgZGF0ZTIpO1xuXHRcdH1cblx0fTtcblx0XG5cdC8qKlxuXHQgKiBDb21wYXJlcyB0aGUgZmlyc3QgRGF0ZSBvYmplY3QgdG8gdGhlIHNlY29uZCBEYXRlIG9iamVjdCBhbmQgcmV0dXJucyB0cnVlIGlmIHRoZXkgYXJlIGVxdWFsLiAgXG5cdCAqIEBwYXJhbSB7RGF0ZX0gICAgIEZpcnN0IERhdGUgb2JqZWN0IHRvIGNvbXBhcmUgW1JlcXVpcmVkXVxuXHQgKiBAcGFyYW0ge0RhdGV9ICAgICBTZWNvbmQgRGF0ZSBvYmplY3QgdG8gY29tcGFyZSB0byBbUmVxdWlyZWRdXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgZGF0ZXMgYXJlIGVxdWFsLiBmYWxzZSBpZiB0aGV5IGFyZSBub3QgZXF1YWwuXG5cdCAqL1xuXHQkRC5lcXVhbHMgPSBmdW5jdGlvbiAoZGF0ZTEsIGRhdGUyKSB7XG5cdFx0cmV0dXJuIChkYXRlMS5jb21wYXJlVG8oZGF0ZTIpID09PSAwKTtcblx0fTtcblxuXHQvKipcblx0ICogR2V0cyB0aGUgbGFuZ3VhZ2UgYXBwcm9wcmlhdGUgZGF5IG5hbWUgd2hlbiBnaXZlbiB0aGUgZGF5IG51bWJlcigwLTYpXG5cdCAqIGVnIC0gMCA9PSBTdW5kYXlcblx0ICogQHJldHVybiB7U3RyaW5nfSAgVGhlIGRheSBuYW1lXG5cdCAqL1xuXHQkRC5nZXREYXlOYW1lID0gZnVuY3Rpb24gKG4pIHtcblx0XHRyZXR1cm4gRGF0ZS5DdWx0dXJlSW5mby5kYXlOYW1lc1tuXTtcblx0fTtcblxuXHQvKipcblx0ICogR2V0cyB0aGUgZGF5IG51bWJlciAoMC02KSBpZiBnaXZlbiBhIEN1bHR1cmVJbmZvIHNwZWNpZmljIHN0cmluZyB3aGljaCBpcyBhIHZhbGlkIGRheU5hbWUsIGFiYnJldmlhdGVkRGF5TmFtZSBvciBzaG9ydGVzdERheU5hbWUgKHR3byBjaGFyKS5cblx0ICogQHBhcmFtIHtTdHJpbmd9ICAgVGhlIG5hbWUgb2YgdGhlIGRheSAoZWcuIFwiTW9uZGF5LCBcIk1vblwiLCBcInR1ZXNkYXlcIiwgXCJ0dWVcIiwgXCJXZVwiLCBcIndlXCIpLlxuXHQgKiBAcmV0dXJuIHtOdW1iZXJ9ICBUaGUgZGF5IG51bWJlclxuXHQgKi9cblx0JEQuZ2V0RGF5TnVtYmVyRnJvbU5hbWUgPSBmdW5jdGlvbiAobmFtZSkge1xuXHRcdHZhciBuID0gRGF0ZS5DdWx0dXJlSW5mby5kYXlOYW1lcywgbSA9IERhdGUuQ3VsdHVyZUluZm8uYWJicmV2aWF0ZWREYXlOYW1lcywgbyA9IERhdGUuQ3VsdHVyZUluZm8uc2hvcnRlc3REYXlOYW1lcywgcyA9IG5hbWUudG9Mb3dlckNhc2UoKTtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IG4ubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmIChuW2ldLnRvTG93ZXJDYXNlKCkgPT09IHMgfHwgbVtpXS50b0xvd2VyQ2FzZSgpID09PSBzIHx8IG9baV0udG9Mb3dlckNhc2UoKSA9PT0gcykge1xuXHRcdFx0XHRyZXR1cm4gaTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIC0xO1xuXHR9O1xuXHRcblx0LyoqXG5cdCAqIEdldHMgdGhlIG1vbnRoIG51bWJlciAoMC0xMSkgaWYgZ2l2ZW4gYSBDdWx0dXJlIEluZm8gc3BlY2lmaWMgc3RyaW5nIHdoaWNoIGlzIGEgdmFsaWQgbW9udGhOYW1lIG9yIGFiYnJldmlhdGVkTW9udGhOYW1lLlxuXHQgKiBAcGFyYW0ge1N0cmluZ30gICBUaGUgbmFtZSBvZiB0aGUgbW9udGggKGVnLiBcIkZlYnJ1YXJ5LCBcIkZlYlwiLCBcIm9jdG9iZXJcIiwgXCJvY3RcIikuXG5cdCAqIEByZXR1cm4ge051bWJlcn0gIFRoZSBkYXkgbnVtYmVyXG5cdCAqL1xuXHQkRC5nZXRNb250aE51bWJlckZyb21OYW1lID0gZnVuY3Rpb24gKG5hbWUpIHtcblx0XHR2YXIgbiA9IERhdGUuQ3VsdHVyZUluZm8ubW9udGhOYW1lcywgbSA9IERhdGUuQ3VsdHVyZUluZm8uYWJicmV2aWF0ZWRNb250aE5hbWVzLCBzID0gbmFtZS50b0xvd2VyQ2FzZSgpO1xuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgbi5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKG5baV0udG9Mb3dlckNhc2UoKSA9PT0gcyB8fCBtW2ldLnRvTG93ZXJDYXNlKCkgPT09IHMpIHtcblx0XHRcdFx0cmV0dXJuIGk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiAtMTtcblx0fTtcblxuXHQvKipcblx0ICogR2V0cyB0aGUgbGFuZ3VhZ2UgYXBwcm9wcmlhdGUgbW9udGggbmFtZSB3aGVuIGdpdmVuIHRoZSBtb250aCBudW1iZXIoMC0xMSlcblx0ICogZWcgLSAwID09IEphbnVhcnlcblx0ICogQHJldHVybiB7U3RyaW5nfSAgVGhlIG1vbnRoIG5hbWVcblx0ICovXG5cdCRELmdldE1vbnRoTmFtZSA9IGZ1bmN0aW9uIChuKSB7XG5cdFx0cmV0dXJuIERhdGUuQ3VsdHVyZUluZm8ubW9udGhOYW1lc1tuXTtcblx0fTtcblxuXHQvKipcblx0ICogRGV0ZXJtaW5lcyBpZiB0aGUgY3VycmVudCBkYXRlIGluc3RhbmNlIGlzIHdpdGhpbiBhIExlYXBZZWFyLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgeWVhci5cblx0ICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiBkYXRlIGlzIHdpdGhpbiBhIExlYXBZZWFyLCBvdGhlcndpc2UgZmFsc2UuXG5cdCAqL1xuXHQkRC5pc0xlYXBZZWFyID0gZnVuY3Rpb24gKHllYXIpIHtcblx0XHRyZXR1cm4gKCh5ZWFyICUgNCA9PT0gMCAmJiB5ZWFyICUgMTAwICE9PSAwKSB8fCB5ZWFyICUgNDAwID09PSAwKTtcblx0fTtcblxuXHQvKipcblx0ICogR2V0cyB0aGUgbnVtYmVyIG9mIGRheXMgaW4gdGhlIG1vbnRoLCBnaXZlbiBhIHllYXIgYW5kIG1vbnRoIHZhbHVlLiBBdXRvbWF0aWNhbGx5IGNvcnJlY3RzIGZvciBMZWFwWWVhci5cblx0ICogQHBhcmFtIHtOdW1iZXJ9ICAgVGhlIHllYXIuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSAgIFRoZSBtb250aCAoMC0xMSkuXG5cdCAqIEByZXR1cm4ge051bWJlcn0gIFRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGUgbW9udGguXG5cdCAqL1xuXHQkRC5nZXREYXlzSW5Nb250aCA9IGZ1bmN0aW9uICh5ZWFyLCBtb250aCkge1xuXHRcdGlmICghbW9udGggJiYgJEQudmFsaWRhdGVNb250aCh5ZWFyKSkge1xuXHRcdFx0XHRtb250aCA9IHllYXI7XG5cdFx0XHRcdHllYXIgPSBEYXRlLnRvZGF5KCkuZ2V0RnVsbFllYXIoKTtcblx0XHR9XG5cdFx0cmV0dXJuIFszMSwgKCRELmlzTGVhcFllYXIoeWVhcikgPyAyOSA6IDI4KSwgMzEsIDMwLCAzMSwgMzAsIDMxLCAzMSwgMzAsIDMxLCAzMCwgMzFdW21vbnRoXTtcblx0fTtcblxuXHQkUC5nZXREYXlzSW5Nb250aCA9IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gJEQuZ2V0RGF5c0luTW9udGgodGhpcy5nZXRGdWxsWWVhcigpLCB0aGlzLmdldE1vbnRoKCkpO1xuXHR9O1xuIFxuXHQkRC5nZXRUaW1lem9uZUFiYnJldmlhdGlvbiA9IGZ1bmN0aW9uIChvZmZzZXQsIGRzdCkge1xuXHRcdHZhciBwLCBuID0gKGRzdCB8fCBmYWxzZSkgPyBEYXRlLkN1bHR1cmVJbmZvLmFiYnJldmlhdGVkVGltZVpvbmVEU1QgOiBEYXRlLkN1bHR1cmVJbmZvLmFiYnJldmlhdGVkVGltZVpvbmVTdGFuZGFyZDtcblx0XHRmb3IgKHAgaW4gbikge1xuXHRcdFx0aWYgKG4uaGFzT3duUHJvcGVydHkocCkpIHtcblx0XHRcdFx0aWYgKG5bcF0gPT09IG9mZnNldCkge1xuXHRcdFx0XHRcdHJldHVybiBwO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiBudWxsO1xuXHR9O1xuXHRcblx0JEQuZ2V0VGltZXpvbmVPZmZzZXQgPSBmdW5jdGlvbiAobmFtZSwgZHN0KSB7XG5cdFx0dmFyIGksIGEgPVtdLCB6ID0gRGF0ZS5DdWx0dXJlSW5mby50aW1lem9uZXM7XG5cdFx0aWYgKCFuYW1lKSB7IG5hbWUgPSAobmV3IERhdGUoKSkuZ2V0VGltZXpvbmUoKTt9XG5cdFx0Zm9yIChpID0gMDsgaSA8IHoubGVuZ3RoOyBpKyspIHtcblx0XHRcdGlmICh6W2ldLm5hbWUgPT09IG5hbWUudG9VcHBlckNhc2UoKSkge1xuXHRcdFx0XHRhLnB1c2goaSk7XG5cdFx0XHR9XG5cdFx0fVxuXHRcdGlmICghelthWzBdXSkge1xuXHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0fVxuXHRcdGlmIChhLmxlbmd0aCA9PT0gMSB8fCAhZHN0KSB7XG5cdFx0XHRyZXR1cm4gelthWzBdXS5vZmZzZXQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGZvciAoaT0wOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRpZiAoelthW2ldXS5kc3QpIHtcblx0XHRcdFx0XHRyZXR1cm4gelthW2ldXS5vZmZzZXQ7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0JEQuZ2V0UXVhcnRlciA9IGZ1bmN0aW9uIChkKSB7XG5cdFx0ZCA9IGQgfHwgbmV3IERhdGUoKTsgLy8gSWYgbm8gZGF0ZSBzdXBwbGllZCwgdXNlIHRvZGF5XG5cdFx0dmFyIHEgPSBbMSwyLDMsNF07XG5cdFx0cmV0dXJuIHFbTWF0aC5mbG9vcihkLmdldE1vbnRoKCkgLyAzKV07IC8vIH5+fiBpcyBhIGJpdHdpc2Ugb3AuIEZhc3RlciB0aGFuIE1hdGguZmxvb3Jcblx0fTtcblxuXHQkRC5nZXREYXlzTGVmdEluUXVhcnRlciA9IGZ1bmN0aW9uIChkKSB7XG5cdFx0ZCA9IGQgfHwgbmV3IERhdGUoKTtcblx0XHR2YXIgcUVuZCA9IG5ldyBEYXRlKGQpO1xuXHRcdHFFbmQuc2V0TW9udGgocUVuZC5nZXRNb250aCgpICsgMyAtIHFFbmQuZ2V0TW9udGgoKSAlIDMsIDApO1xuXHRcdHJldHVybiBNYXRoLmZsb29yKChxRW5kIC0gZCkgLyA4LjY0ZTcpO1xuXHR9O1xuXG5cdC8vIHByaXZhdGVcblx0dmFyIHZhbGlkYXRlID0gZnVuY3Rpb24gKG4sIG1pbiwgbWF4LCBuYW1lKSB7XG5cdFx0bmFtZSA9IG5hbWUgPyBuYW1lIDogXCJPYmplY3RcIjtcblx0XHRpZiAodHlwZW9mIG4gPT09IFwidW5kZWZpbmVkXCIpIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9IGVsc2UgaWYgKHR5cGVvZiBuICE9PSBcIm51bWJlclwiKSB7XG5cdFx0XHR0aHJvdyBuZXcgVHlwZUVycm9yKG4gKyBcIiBpcyBub3QgYSBOdW1iZXIuXCIpO1xuXHRcdH0gZWxzZSBpZiAobiA8IG1pbiB8fCBuID4gbWF4KSB7XG5cdFx0XHQvLyBBcyBmYWlsaW5nIHZhbGlkYXRpb24gaXMgKm5vdCogYW4gZXhjZXB0aW9uYWwgY2lyY3Vtc3RhbmNlIFxuXHRcdFx0Ly8gbGV0cyBub3QgdGhyb3cgYSBSYW5nZUVycm9yIEV4Y2VwdGlvbiBoZXJlLiBcblx0XHRcdC8vIEl0J3Mgc2VtYW50aWNhbGx5IGNvcnJlY3QgYnV0IGl0J3Mgbm90IHNlbnNpYmxlLlxuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0XHRyZXR1cm4gdHJ1ZTtcblx0fTtcblxuXHQvKipcblx0ICogVmFsaWRhdGVzIHRoZSBudW1iZXIgaXMgd2l0aGluIGFuIGFjY2VwdGFibGUgcmFuZ2UgZm9yIG1pbGxpc2Vjb25kcyBbMC05OTldLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgbnVtYmVyIHRvIGNoZWNrIGlmIHdpdGhpbiByYW5nZS5cblx0ICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiB3aXRoaW4gcmFuZ2UsIG90aGVyd2lzZSBmYWxzZS5cblx0ICovXG5cdCRELnZhbGlkYXRlTWlsbGlzZWNvbmQgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0XHRyZXR1cm4gdmFsaWRhdGUodmFsdWUsIDAsIDk5OSwgXCJtaWxsaXNlY29uZFwiKTtcblx0fTtcblxuXHQvKipcblx0ICogVmFsaWRhdGVzIHRoZSBudW1iZXIgaXMgd2l0aGluIGFuIGFjY2VwdGFibGUgcmFuZ2UgZm9yIHNlY29uZHMgWzAtNTldLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgbnVtYmVyIHRvIGNoZWNrIGlmIHdpdGhpbiByYW5nZS5cblx0ICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiB3aXRoaW4gcmFuZ2UsIG90aGVyd2lzZSBmYWxzZS5cblx0ICovXG5cdCRELnZhbGlkYXRlU2Vjb25kID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdFx0cmV0dXJuIHZhbGlkYXRlKHZhbHVlLCAwLCA1OSwgXCJzZWNvbmRcIik7XG5cdH07XG5cblx0LyoqXG5cdCAqIFZhbGlkYXRlcyB0aGUgbnVtYmVyIGlzIHdpdGhpbiBhbiBhY2NlcHRhYmxlIHJhbmdlIGZvciBtaW51dGVzIFswLTU5XS5cblx0ICogQHBhcmFtIHtOdW1iZXJ9ICAgVGhlIG51bWJlciB0byBjaGVjayBpZiB3aXRoaW4gcmFuZ2UuXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgd2l0aGluIHJhbmdlLCBvdGhlcndpc2UgZmFsc2UuXG5cdCAqL1xuXHQkRC52YWxpZGF0ZU1pbnV0ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdHJldHVybiB2YWxpZGF0ZSh2YWx1ZSwgMCwgNTksIFwibWludXRlXCIpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBWYWxpZGF0ZXMgdGhlIG51bWJlciBpcyB3aXRoaW4gYW4gYWNjZXB0YWJsZSByYW5nZSBmb3IgaG91cnMgWzAtMjNdLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgbnVtYmVyIHRvIGNoZWNrIGlmIHdpdGhpbiByYW5nZS5cblx0ICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiB3aXRoaW4gcmFuZ2UsIG90aGVyd2lzZSBmYWxzZS5cblx0ICovXG5cdCRELnZhbGlkYXRlSG91ciA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuXHRcdHJldHVybiB2YWxpZGF0ZSh2YWx1ZSwgMCwgMjMsIFwiaG91clwiKTtcblx0fTtcblxuXHQvKipcblx0ICogVmFsaWRhdGVzIHRoZSBudW1iZXIgaXMgd2l0aGluIGFuIGFjY2VwdGFibGUgcmFuZ2UgZm9yIHRoZSBkYXlzIGluIGEgbW9udGggWzAtTWF4RGF5c0luTW9udGhdLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgbnVtYmVyIHRvIGNoZWNrIGlmIHdpdGhpbiByYW5nZS5cblx0ICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiB3aXRoaW4gcmFuZ2UsIG90aGVyd2lzZSBmYWxzZS5cblx0ICovXG5cdCRELnZhbGlkYXRlRGF5ID0gZnVuY3Rpb24gKHZhbHVlLCB5ZWFyLCBtb250aCkge1xuXHRcdGlmICh5ZWFyID09PSB1bmRlZmluZWQgfHwgeWVhciA9PT0gbnVsbCB8fCBtb250aCA9PT0gdW5kZWZpbmVkIHx8IG1vbnRoID09PSBudWxsKSB7IHJldHVybiBmYWxzZTt9XG5cdFx0cmV0dXJuIHZhbGlkYXRlKHZhbHVlLCAxLCAkRC5nZXREYXlzSW5Nb250aCh5ZWFyLCBtb250aCksIFwiZGF5XCIpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBWYWxpZGF0ZXMgdGhlIG51bWJlciBpcyB3aXRoaW4gYW4gYWNjZXB0YWJsZSByYW5nZSBmb3IgbW9udGhzIFswLTExXS5cblx0ICogQHBhcmFtIHtOdW1iZXJ9ICAgVGhlIG51bWJlciB0byBjaGVjayBpZiB3aXRoaW4gcmFuZ2UuXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59IHRydWUgaWYgd2l0aGluIHJhbmdlLCBvdGhlcndpc2UgZmFsc2UuXG5cdCAqL1xuXHQkRC52YWxpZGF0ZVdlZWsgPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0XHRyZXR1cm4gdmFsaWRhdGUodmFsdWUsIDAsIDUzLCBcIndlZWtcIik7XG5cdH07XG5cblx0LyoqXG5cdCAqIFZhbGlkYXRlcyB0aGUgbnVtYmVyIGlzIHdpdGhpbiBhbiBhY2NlcHRhYmxlIHJhbmdlIGZvciBtb250aHMgWzAtMTFdLlxuXHQgKiBAcGFyYW0ge051bWJlcn0gICBUaGUgbnVtYmVyIHRvIGNoZWNrIGlmIHdpdGhpbiByYW5nZS5cblx0ICogQHJldHVybiB7Qm9vbGVhbn0gdHJ1ZSBpZiB3aXRoaW4gcmFuZ2UsIG90aGVyd2lzZSBmYWxzZS5cblx0ICovXG5cdCRELnZhbGlkYXRlTW9udGggPSBmdW5jdGlvbiAodmFsdWUpIHtcblx0XHRyZXR1cm4gdmFsaWRhdGUodmFsdWUsIDAsIDExLCBcIm1vbnRoXCIpO1xuXHR9O1xuXG5cdC8qKlxuXHQgKiBWYWxpZGF0ZXMgdGhlIG51bWJlciBpcyB3aXRoaW4gYW4gYWNjZXB0YWJsZSByYW5nZSBmb3IgeWVhcnMuXG5cdCAqIEBwYXJhbSB7TnVtYmVyfSAgIFRoZSBudW1iZXIgdG8gY2hlY2sgaWYgd2l0aGluIHJhbmdlLlxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSB0cnVlIGlmIHdpdGhpbiByYW5nZSwgb3RoZXJ3aXNlIGZhbHNlLlxuXHQgKi9cblx0JEQudmFsaWRhdGVZZWFyID0gZnVuY3Rpb24gKHZhbHVlKSB7XG5cdFx0LyoqXG5cdFx0ICogUGVyIEVDTUFTY3JpcHQgc3BlYyB0aGUgcmFuZ2Ugb2YgdGltZXMgc3VwcG9ydGVkIGJ5IERhdGUgb2JqZWN0cyBpcyBcblx0XHQgKiBleGFjdGx5IC0xMDAsMDAwLDAwMCBkYXlzIHRvICsxMDAsMDAwLDAwMCBkYXlzIG1lYXN1cmVkIHJlbGF0aXZlIHRvIFxuXHRcdCAqIG1pZG5pZ2h0IGF0IHRoZSBiZWdpbm5pbmcgb2YgMDEgSmFudWFyeSwgMTk3MCBVVEMuIFxuXHRcdCAqIFRoaXMgZ2l2ZXMgYSByYW5nZSBvZiA4LDY0MCwwMDAsMDAwLDAwMCwwMDAgbWlsbGlzZWNvbmRzIHRvIGVpdGhlciBcblx0XHQgKiBzaWRlIG9mIDAxIEphbnVhcnksIDE5NzAgVVRDLlxuXHRcdCAqXG5cdFx0ICogRWFybGllc3QgcG9zc2libGUgZGF0ZTogVHVlLCAyMCBBcHIgMjcxLDgyMiBCLkMuIDAwOjAwOjAwIFVUQ1xuXHRcdCAqIExhdGVzdCBwb3NzaWJsZSBkYXRlOiBTYXQsIDEzIFNlcCAyNzUsNzYwIDAwOjAwOjAwIFVUQ1xuXHRcdCAqL1xuXHRcdHJldHVybiB2YWxpZGF0ZSh2YWx1ZSwgLTI3MTgyMiwgMjc1NzYwLCBcInllYXJcIik7XG5cdH07XG5cdCRELnZhbGlkYXRlVGltZXpvbmUgPSBmdW5jdGlvbih2YWx1ZSkge1xuXHRcdHZhciB0aW1lem9uZXMgPSB7XCJBQ0RUXCI6MSxcIkFDU1RcIjoxLFwiQUNUXCI6MSxcIkFEVFwiOjEsXCJBRURUXCI6MSxcIkFFU1RcIjoxLFwiQUZUXCI6MSxcIkFLRFRcIjoxLFwiQUtTVFwiOjEsXCJBTVNUXCI6MSxcIkFNVFwiOjEsXCJBUlRcIjoxLFwiQVNUXCI6MSxcIkFXRFRcIjoxLFwiQVdTVFwiOjEsXCJBWk9TVFwiOjEsXCJBWlRcIjoxLFwiQkRUXCI6MSxcIkJJT1RcIjoxLFwiQklUXCI6MSxcIkJPVFwiOjEsXCJCUlRcIjoxLFwiQlNUXCI6MSxcIkJUVFwiOjEsXCJDQVRcIjoxLFwiQ0NUXCI6MSxcIkNEVFwiOjEsXCJDRURUXCI6MSxcIkNFU1RcIjoxLFwiQ0VUXCI6MSxcIkNIQURUXCI6MSxcIkNIQVNUXCI6MSxcIkNIT1RcIjoxLFwiQ2hTVFwiOjEsXCJDSFVUXCI6MSxcIkNJU1RcIjoxLFwiQ0lUXCI6MSxcIkNLVFwiOjEsXCJDTFNUXCI6MSxcIkNMVFwiOjEsXCJDT1NUXCI6MSxcIkNPVFwiOjEsXCJDU1RcIjoxLFwiQ1RcIjoxLFwiQ1ZUXCI6MSxcIkNXU1RcIjoxLFwiQ1hUXCI6MSxcIkRBVlRcIjoxLFwiRERVVFwiOjEsXCJERlRcIjoxLFwiRUFTU1RcIjoxLFwiRUFTVFwiOjEsXCJFQVRcIjoxLFwiRUNUXCI6MSxcIkVEVFwiOjEsXCJFRURUXCI6MSxcIkVFU1RcIjoxLFwiRUVUXCI6MSxcIkVHU1RcIjoxLFwiRUdUXCI6MSxcIkVJVFwiOjEsXCJFU1RcIjoxLFwiRkVUXCI6MSxcIkZKVFwiOjEsXCJGS1NUXCI6MSxcIkZLVFwiOjEsXCJGTlRcIjoxLFwiR0FMVFwiOjEsXCJHQU1UXCI6MSxcIkdFVFwiOjEsXCJHRlRcIjoxLFwiR0lMVFwiOjEsXCJHSVRcIjoxLFwiR01UXCI6MSxcIkdTVFwiOjEsXCJHWVRcIjoxLFwiSEFEVFwiOjEsXCJIQUVDXCI6MSxcIkhBU1RcIjoxLFwiSEtUXCI6MSxcIkhNVFwiOjEsXCJIT1ZUXCI6MSxcIkhTVFwiOjEsXCJJQ1RcIjoxLFwiSURUXCI6MSxcIklPVFwiOjEsXCJJUkRUXCI6MSxcIklSS1RcIjoxLFwiSVJTVFwiOjEsXCJJU1RcIjoxLFwiSlNUXCI6MSxcIktHVFwiOjEsXCJLT1NUXCI6MSxcIktSQVRcIjoxLFwiS1NUXCI6MSxcIkxIU1RcIjoxLFwiTElOVFwiOjEsXCJNQUdUXCI6MSxcIk1BUlRcIjoxLFwiTUFXVFwiOjEsXCJNRFRcIjoxLFwiTUVUXCI6MSxcIk1FU1RcIjoxLFwiTUhUXCI6MSxcIk1JU1RcIjoxLFwiTUlUXCI6MSxcIk1NVFwiOjEsXCJNU0tcIjoxLFwiTVNUXCI6MSxcIk1VVFwiOjEsXCJNVlRcIjoxLFwiTVlUXCI6MSxcIk5DVFwiOjEsXCJORFRcIjoxLFwiTkZUXCI6MSxcIk5QVFwiOjEsXCJOU1RcIjoxLFwiTlRcIjoxLFwiTlVUXCI6MSxcIk5aRFRcIjoxLFwiTlpTVFwiOjEsXCJPTVNUXCI6MSxcIk9SQVRcIjoxLFwiUERUXCI6MSxcIlBFVFwiOjEsXCJQRVRUXCI6MSxcIlBHVFwiOjEsXCJQSE9UXCI6MSxcIlBIVFwiOjEsXCJQS1RcIjoxLFwiUE1EVFwiOjEsXCJQTVNUXCI6MSxcIlBPTlRcIjoxLFwiUFNUXCI6MSxcIlBZU1RcIjoxLFwiUFlUXCI6MSxcIlJFVFwiOjEsXCJST1RUXCI6MSxcIlNBS1RcIjoxLFwiU0FNVFwiOjEsXCJTQVNUXCI6MSxcIlNCVFwiOjEsXCJTQ1RcIjoxLFwiU0dUXCI6MSxcIlNMU1RcIjoxLFwiU1JUXCI6MSxcIlNTVFwiOjEsXCJTWU9UXCI6MSxcIlRBSFRcIjoxLFwiVEhBXCI6MSxcIlRGVFwiOjEsXCJUSlRcIjoxLFwiVEtUXCI6MSxcIlRMVFwiOjEsXCJUTVRcIjoxLFwiVE9UXCI6MSxcIlRWVFwiOjEsXCJVQ1RcIjoxLFwiVUxBVFwiOjEsXCJVVENcIjoxLFwiVVlTVFwiOjEsXCJVWVRcIjoxLFwiVVpUXCI6MSxcIlZFVFwiOjEsXCJWTEFUXCI6MSxcIlZPTFRcIjoxLFwiVk9TVFwiOjEsXCJWVVRcIjoxLFwiV0FLVFwiOjEsXCJXQVNUXCI6MSxcIldBVFwiOjEsXCJXRURUXCI6MSxcIldFU1RcIjoxLFwiV0VUXCI6MSxcIldTVFwiOjEsXCJZQUtUXCI6MSxcIllFS1RcIjoxLFwiWlwiOjF9O1xuXHRcdHJldHVybiAodGltZXpvbmVzW3ZhbHVlXSA9PT0gMSk7XG5cdH07XG5cdCRELnZhbGlkYXRlVGltZXpvbmVPZmZzZXQ9IGZ1bmN0aW9uKHZhbHVlKSB7XG5cdFx0Ly8gdGltZXpvbmVzIGdvIGZyb20gKzE0aHJzIHRvIC0xMmhycywgdGhlICtYIGhvdXJzIGFyZSBuZWdhdGl2ZSBvZmZzZXRzLlxuXHRcdHJldHVybiAodmFsdWUgPiAtODQxICYmIHZhbHVlIDwgNzIxKTtcblx0fTtcblxufSgpKTtcbiIsIihmdW5jdGlvbiAoKSB7XHJcblx0dmFyICREID0gRGF0ZSxcclxuXHRcdCRQID0gJEQucHJvdG90eXBlLFxyXG5cdFx0Ly8gJEMgPSAkRC5DdWx0dXJlSW5mbywgLy8gbm90IHVzZWQgYXRtXHJcblx0XHRwID0gZnVuY3Rpb24gKHMsIGwpIHtcclxuXHRcdFx0aWYgKCFsKSB7XHJcblx0XHRcdFx0bCA9IDI7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIChcIjAwMFwiICsgcykuc2xpY2UobCAqIC0xKTtcclxuXHRcdH07XHJcblx0LyoqXHJcblx0ICogQ29udmVydHMgYSBQSFAgZm9ybWF0IHN0cmluZyB0byBKYXZhLy5ORVQgZm9ybWF0IHN0cmluZy5cclxuXHQgKiBBIFBIUCBmb3JtYXQgc3RyaW5nIGNhbiBiZSB1c2VkIHdpdGggLl9mb3JtYXQgb3IgLmZvcm1hdC5cclxuXHQgKiBBIEphdmEvLk5FVCBmb3JtYXQgc3RyaW5nIGNhbiBiZSB1c2VkIHdpdGggLnRvU3RyaW5nKCkuXHJcblx0ICogVGhlIC5wYXJzZUV4YWN0IGZ1bmN0aW9uIHdpbGwgb25seSBhY2NlcHQgYSBKYXZhLy5ORVQgZm9ybWF0IHN0cmluZ1xyXG5cdCAqXHJcblx0ICogRXhhbXBsZVxyXG5cdCAqIHZhciBmMSA9IFwiJW0vJWQvJXlcIlxyXG5cdCAqIHZhciBmMiA9IERhdGUubm9ybWFsaXplRm9ybWF0KGYxKTtcdC8vIFwiTU0vZGQveXlcIlxyXG5cdCAqXHJcblx0ICogbmV3IERhdGUoKS5mb3JtYXQoZjEpO1x0Ly8gXCIwNC8xMy8wOFwiXHJcblx0ICogbmV3IERhdGUoKS5fZm9ybWF0KGYxKTtcdC8vIFwiMDQvMTMvMDhcIlxyXG5cdCAqIG5ldyBEYXRlKCkudG9TdHJpbmcoZjIpO1x0Ly8gXCIwNC8xMy8wOFwiXHJcblx0ICpcclxuXHQgKiB2YXIgZGF0ZSA9IERhdGUucGFyc2VFeGFjdChcIjA0LzEzLzA4XCIsIGYyKTsgLy8gU3VuIEFwciAxMyAyMDA4XHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge1N0cmluZ30gICBBIFBIUCBmb3JtYXQgc3RyaW5nIGNvbnNpc3Rpbmcgb2Ygb25lIG9yIG1vcmUgZm9ybWF0IHNwY2lmaWVycy5cclxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9ICBUaGUgUEhQIGZvcm1hdCBjb252ZXJ0ZWQgdG8gYSBKYXZhLy5ORVQgZm9ybWF0IHN0cmluZy5cclxuXHQgKi9cclxuXHQgdmFyIG5vcm1hbGl6ZXJTdWJzdGl0dXRpb25zID0ge1xyXG5cdFx0XCJkXCIgOiBcImRkXCIsXHJcblx0XHRcIiVkXCI6IFwiZGRcIixcclxuXHRcdFwiRFwiIDogXCJkZGRcIixcclxuXHRcdFwiJWFcIjogXCJkZGRcIixcclxuXHRcdFwialwiIDogXCJkZGRkXCIsXHJcblx0XHRcImxcIiA6IFwiZGRkZFwiLFxyXG5cdFx0XCIlQVwiOiBcImRkZGRcIixcclxuXHRcdFwiU1wiIDogXCJTXCIsXHJcblx0XHRcIkZcIiA6IFwiTU1NTVwiLFxyXG5cdFx0XCIlQlwiOiBcIk1NTU1cIixcclxuXHRcdFwibVwiIDogXCJNTVwiLFxyXG5cdFx0XCIlbVwiOiBcIk1NXCIsXHJcblx0XHRcIk1cIiA6IFwiTU1NXCIsXHJcblx0XHRcIiViXCI6IFwiTU1NXCIsXHJcblx0XHRcIiVoXCI6IFwiTU1NXCIsXHJcblx0XHRcIm5cIiA6IFwiTVwiLFxyXG5cdFx0XCJZXCIgOiBcInl5eXlcIixcclxuXHRcdFwiJVlcIjogXCJ5eXl5XCIsXHJcblx0XHRcInlcIiA6IFwieXlcIixcclxuXHRcdFwiJXlcIjogXCJ5eVwiLFxyXG5cdFx0XCJnXCIgOiBcImhcIixcclxuXHRcdFwiJUlcIjogXCJoXCIsXHJcblx0XHRcIkdcIiA6IFwiSFwiLFxyXG5cdFx0XCJoXCIgOiBcImhoXCIsXHJcblx0XHRcIkhcIiA6IFwiSEhcIixcclxuXHRcdFwiJUhcIjogXCJISFwiLFxyXG5cdFx0XCJpXCIgOiBcIm1tXCIsXHJcblx0XHRcIiVNXCI6IFwibW1cIixcclxuXHRcdFwic1wiIDogXCJzc1wiLFxyXG5cdFx0XCIlU1wiOiBcInNzXCIsXHJcblx0XHRcIiVyXCI6IFwiaGg6bW0gdHRcIixcclxuXHRcdFwiJVJcIjogXCJIOm1tXCIsXHJcblx0XHRcIiVUXCI6IFwiSDptbTpzc1wiLFxyXG5cdFx0XCIlWFwiOiBcInRcIixcclxuXHRcdFwiJXhcIjogXCJkXCIsXHJcblx0XHRcIiVlXCI6IFwiZFwiLFxyXG5cdFx0XCIlRFwiOiBcIk1NL2RkL3l5XCIsXHJcblx0XHRcIiVuXCI6IFwiXFxcXG5cIixcclxuXHRcdFwiJXRcIjogXCJcXFxcdFwiLFxyXG5cdFx0XCJlXCIgOiBcInpcIixcclxuXHRcdFwiVFwiIDogXCJ6XCIsXHJcblx0XHRcIiV6XCI6IFwielwiLFxyXG5cdFx0XCIlWlwiOiBcInpcIixcclxuXHRcdFwiWlwiIDogXCJaWlwiLFxyXG5cdFx0XCJOXCIgOiBcInVcIixcclxuXHRcdFwid1wiIDogXCJ1XCIsXHJcblx0XHRcIiV3XCI6IFwidVwiLFxyXG5cdFx0XCJXXCIgOiBcIldcIixcclxuXHRcdFwiJVZcIjogXCJXXCJcclxuXHR9O1xyXG5cdHZhciBub3JtYWxpemVyID0ge1xyXG5cdFx0c3Vic3RpdHV0ZXM6IGZ1bmN0aW9uIChtKSB7XHJcblx0XHRcdHJldHVybiBub3JtYWxpemVyU3Vic3RpdHV0aW9uc1ttXTtcclxuXHRcdH0sXHJcblx0XHRpbnRlcnByZXRlZDogZnVuY3Rpb24gKG0sIHgpIHtcclxuXHRcdFx0dmFyIHk7XHJcblx0XHRcdHN3aXRjaCAobSkge1xyXG5cdFx0XHRcdGNhc2UgXCIldVwiOlxyXG5cdFx0XHRcdFx0cmV0dXJuIHguZ2V0RGF5KCkgKyAxO1xyXG5cdFx0XHRcdGNhc2UgXCJ6XCI6XHJcblx0XHRcdFx0XHRyZXR1cm4geC5nZXRPcmRpbmFsTnVtYmVyKCk7XHJcblx0XHRcdFx0Y2FzZSBcIiVqXCI6XHJcblx0XHRcdFx0XHRyZXR1cm4gcCh4LmdldE9yZGluYWxOdW1iZXIoKSwgMyk7XHJcblx0XHRcdFx0Y2FzZSBcIiVVXCI6XHJcblx0XHRcdFx0XHR2YXIgZDEgPSB4LmNsb25lKCkuc2V0KHttb250aDogMCwgZGF5OiAxfSkuYWRkRGF5cygtMSkubW92ZVRvRGF5T2ZXZWVrKDApLFxyXG5cdFx0XHRcdFx0XHRkMiA9IHguY2xvbmUoKS5hZGREYXlzKDEpLm1vdmVUb0RheU9mV2VlaygwLCAtMSk7XHJcblx0XHRcdFx0XHRyZXR1cm4gKGQyIDwgZDEpID8gXCIwMFwiIDogcCgoZDIuZ2V0T3JkaW5hbE51bWJlcigpIC0gZDEuZ2V0T3JkaW5hbE51bWJlcigpKSAvIDcgKyAxKTtcclxuXHJcblx0XHRcdFx0Y2FzZSBcIiVXXCI6XHJcblx0XHRcdFx0XHRyZXR1cm4gcCh4LmdldFdlZWsoKSk7XHJcblx0XHRcdFx0Y2FzZSBcInRcIjpcclxuXHRcdFx0XHRcdHJldHVybiAkRC5nZXREYXlzSW5Nb250aCh4LmdldEZ1bGxZZWFyKCksIHguZ2V0TW9udGgoKSk7XHJcblx0XHRcdFx0Y2FzZSBcIm9cIjpcclxuXHRcdFx0XHRjYXNlIFwiJUdcIjpcclxuXHRcdFx0XHRcdHJldHVybiB4LnNldFdlZWsoeC5nZXRJU09XZWVrKCkpLnRvU3RyaW5nKFwieXl5eVwiKTtcclxuXHRcdFx0XHRjYXNlIFwiJWdcIjpcclxuXHRcdFx0XHRcdHJldHVybiB4Ll9mb3JtYXQoXCIlR1wiKS5zbGljZSgtMik7XHJcblx0XHRcdFx0Y2FzZSBcImFcIjpcclxuXHRcdFx0XHRjYXNlIFwiJXBcIjpcclxuXHRcdFx0XHRcdHJldHVybiB0KFwidHRcIikudG9Mb3dlckNhc2UoKTtcclxuXHRcdFx0XHRjYXNlIFwiQVwiOlxyXG5cdFx0XHRcdFx0cmV0dXJuIHQoXCJ0dFwiKS50b1VwcGVyQ2FzZSgpO1xyXG5cdFx0XHRcdGNhc2UgXCJ1XCI6XHJcblx0XHRcdFx0XHRyZXR1cm4gcCh4LmdldE1pbGxpc2Vjb25kcygpLCAzKTtcclxuXHRcdFx0XHRjYXNlIFwiSVwiOlxyXG5cdFx0XHRcdFx0cmV0dXJuICh4LmlzRGF5bGlnaHRTYXZpbmdUaW1lKCkpID8gMSA6IDA7XHJcblx0XHRcdFx0Y2FzZSBcIk9cIjpcclxuXHRcdFx0XHRcdHJldHVybiB4LmdldFVUQ09mZnNldCgpO1xyXG5cdFx0XHRcdGNhc2UgXCJQXCI6XHJcblx0XHRcdFx0XHR5ID0geC5nZXRVVENPZmZzZXQoKTtcclxuXHRcdFx0XHRcdHJldHVybiB5LnN1YnN0cmluZygwLCB5Lmxlbmd0aCAtIDIpICsgXCI6XCIgKyB5LnN1YnN0cmluZyh5Lmxlbmd0aCAtIDIpO1xyXG5cdFx0XHRcdGNhc2UgXCJCXCI6XHJcblx0XHRcdFx0XHR2YXIgbm93ID0gbmV3IERhdGUoKTtcclxuXHRcdFx0XHRcdHJldHVybiBNYXRoLmZsb29yKCgobm93LmdldEhvdXJzKCkgKiAzNjAwKSArIChub3cuZ2V0TWludXRlcygpICogNjApICsgbm93LmdldFNlY29uZHMoKSArIChub3cuZ2V0VGltZXpvbmVPZmZzZXQoKSArIDYwKSAqIDYwKSAvIDg2LjQpO1xyXG5cdFx0XHRcdGNhc2UgXCJjXCI6XHJcblx0XHRcdFx0XHRyZXR1cm4geC50b0lTT1N0cmluZygpLnJlcGxhY2UoL1xcXCIvZywgXCJcIik7XHJcblx0XHRcdFx0Y2FzZSBcIlVcIjpcclxuXHRcdFx0XHRcdHJldHVybiAkRC5zdHJ0b3RpbWUoXCJub3dcIik7XHJcblx0XHRcdFx0Y2FzZSBcIiVjXCI6XHJcblx0XHRcdFx0XHRyZXR1cm4gdChcImRcIikgKyBcIiBcIiArIHQoXCJ0XCIpO1xyXG5cdFx0XHRcdGNhc2UgXCIlQ1wiOlxyXG5cdFx0XHRcdFx0cmV0dXJuIE1hdGguZmxvb3IoeC5nZXRGdWxsWWVhcigpIC8gMTAwICsgMSk7XHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblx0XHRzaG91bGRPdmVycmlkZURlZmF1bHRzOiBmdW5jdGlvbiAobSkge1xyXG5cdFx0XHRzd2l0Y2ggKG0pIHtcclxuXHRcdFx0XHRjYXNlIFwiJWVcIjpcclxuXHRcdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHRcdGRlZmF1bHQ6XHJcblx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XHJcblx0XHRcdH1cclxuXHRcdH0sXHJcblx0XHRwYXJzZTogZnVuY3Rpb24gKG0sIGNvbnRleHQpIHtcclxuXHRcdFx0dmFyIGZvcm1hdFN0cmluZywgYyA9IGNvbnRleHQgfHwgbmV3IERhdGUoKTtcclxuXHRcdFx0Zm9ybWF0U3RyaW5nID0gbm9ybWFsaXplci5zdWJzdGl0dXRlcyhtKTtcclxuXHRcdFx0aWYgKGZvcm1hdFN0cmluZykge1xyXG5cdFx0XHRcdHJldHVybiBmb3JtYXRTdHJpbmc7XHJcblx0XHRcdH1cclxuXHRcdFx0Zm9ybWF0U3RyaW5nID0gbm9ybWFsaXplci5pbnRlcnByZXRlZChtLCBjKTtcclxuXHJcblx0XHRcdGlmIChmb3JtYXRTdHJpbmcpIHtcclxuXHRcdFx0XHRyZXR1cm4gZm9ybWF0U3RyaW5nO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHJldHVybiBtO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fTtcclxuXHJcblx0JEQubm9ybWFsaXplRm9ybWF0ID0gZnVuY3Rpb24gKGZvcm1hdCwgY29udGV4dCkge1xyXG5cdFx0cmV0dXJuIGZvcm1hdC5yZXBsYWNlKC8oJXxcXFxcKT8ufCUlL2csIGZ1bmN0aW9uKHQpe1xyXG5cdFx0XHRcdHJldHVybiBub3JtYWxpemVyLnBhcnNlKHQsIGNvbnRleHQpO1xyXG5cdFx0fSk7XHJcblx0fTtcclxuXHQvKipcclxuXHQgKiBGb3JtYXQgYSBsb2NhbCBVbml4IHRpbWVzdGFtcCBhY2NvcmRpbmcgdG8gbG9jYWxlIHNldHRpbmdzXHJcblx0ICpcclxuXHQgKiBFeGFtcGxlOlxyXG5cdCAqIERhdGUuc3RyZnRpbWUoXCIlbS8lZC8leVwiLCBuZXcgRGF0ZSgpKTtcdFx0Ly8gXCIwNC8xMy8wOFwiXHJcblx0ICogRGF0ZS5zdHJmdGltZShcImNcIiwgXCIyMDA4LTA0LTEzVDE3OjUyOjAzWlwiKTtcdC8vIFwiMDQvMTMvMDhcIlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtTdHJpbmd9ICAgQSBmb3JtYXQgc3RyaW5nIGNvbnNpc3Rpbmcgb2Ygb25lIG9yIG1vcmUgZm9ybWF0IHNwY2lmaWVycyBbT3B0aW9uYWxdLlxyXG5cdCAqIEBwYXJhbSB7TnVtYmVyfFN0cmluZ30gICBUaGUgbnVtYmVyIHJlcHJlc2VudGluZyB0aGUgbnVtYmVyIG9mIHNlY29uZHMgdGhhdCBoYXZlIGVsYXBzZWQgc2luY2UgSmFudWFyeSAxLCAxOTcwIChsb2NhbCB0aW1lKS5cclxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9ICBBIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgY3VycmVudCBEYXRlIG9iamVjdC5cclxuXHQgKi9cclxuXHQkRC5zdHJmdGltZSA9IGZ1bmN0aW9uIChmb3JtYXQsIHRpbWUpIHtcclxuXHRcdHZhciBkID0gRGF0ZS5wYXJzZSh0aW1lKTtcclxuXHRcdHJldHVybiBkLl9mb3JtYXQoZm9ybWF0KTtcclxuXHR9O1xyXG5cdC8qKlxyXG5cdCAqIFBhcnNlIGFueSB0ZXh0dWFsIGRhdGV0aW1lIGRlc2NyaXB0aW9uIGludG8gYSBVbml4IHRpbWVzdGFtcC5cclxuXHQgKiBBIFVuaXggdGltZXN0YW1wIGlzIHRoZSBudW1iZXIgb2Ygc2Vjb25kcyB0aGF0IGhhdmUgZWxhcHNlZCBzaW5jZSBKYW51YXJ5IDEsIDE5NzAgKG1pZG5pZ2h0IFVUQy9HTVQpLlxyXG5cdCAqXHJcblx0ICogRXhhbXBsZTpcclxuXHQgKiBEYXRlLnN0cnRvdGltZShcIjA0LzEzLzA4XCIpO1x0XHRcdFx0Ly8gMTIwODA0NDgwMFxyXG5cdCAqIERhdGUuc3RydG90aW1lKFwiMTk3MC0wMS0wMVQwMDowMDowMFpcIik7XHQvLyAwXHJcblx0ICpcclxuXHQgKiBAcGFyYW0ge1N0cmluZ30gICBBIGZvcm1hdCBzdHJpbmcgY29uc2lzdGluZyBvZiBvbmUgb3IgbW9yZSBmb3JtYXQgc3BjaWZpZXJzIFtPcHRpb25hbF0uXHJcblx0ICogQHBhcmFtIHtPYmplY3R9ICAgQSBzdHJpbmcgb3IgZGF0ZSBvYmplY3QuXHJcblx0ICogQHJldHVybiB7U3RyaW5nfSAgQSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGN1cnJlbnQgRGF0ZSBvYmplY3QuXHJcblx0ICovXHJcblx0JEQuc3RydG90aW1lID0gZnVuY3Rpb24gKHRpbWUpIHtcclxuXHRcdHZhciBkID0gJEQucGFyc2UodGltZSk7XHJcblx0XHRyZXR1cm4gTWF0aC5yb3VuZCgkRC5VVEMoZC5nZXRVVENGdWxsWWVhcigpLCBkLmdldFVUQ01vbnRoKCksIGQuZ2V0VVRDRGF0ZSgpLCBkLmdldFVUQ0hvdXJzKCksIGQuZ2V0VVRDTWludXRlcygpLCBkLmdldFVUQ1NlY29uZHMoKSwgZC5nZXRVVENNaWxsaXNlY29uZHMoKSkgLyAxMDAwKTtcclxuXHR9O1xyXG5cdC8qKlxyXG5cdCAqIENvbnZlcnRzIHRoZSB2YWx1ZSBvZiB0aGUgY3VycmVudCBEYXRlIG9iamVjdCB0byBpdHMgZXF1aXZhbGVudCBzdHJpbmcgcmVwcmVzZW50YXRpb24gdXNpbmcgYSBQSFAvVW5peCBzdHlsZSBvZiBkYXRlIGZvcm1hdCBzcGVjaWZpZXJzLlxyXG5cdCAqIEZvcm1hdCBTcGVjaWZpZXJzXHJcblx0ICogRm9ybWF0ICBEZXNjcmlwdGlvblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRFeGFtcGxlXHJcblx0ICogLS0tLS0tICAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cdC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXHJcblx0ICogJWFcdFx0YWJicmV2aWF0ZWQgd2Vla2RheSBuYW1lIGFjY29yZGluZyB0byB0aGUgY3VycmVudCBsb2NhbGVkXHRcdFx0XHRcdFwiTW9uXCIgdGhyb3VnaCBcIlN1blwiXHJcblx0ICogJUFcdFx0ZnVsbCB3ZWVrZGF5IG5hbWUgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IGxvY2FsZWRcdFx0XHRcdFx0XHRcdFwiU3VuZGF5XCIgdGhyb3VnaCBcIlNhdHVyZGF5XCJcclxuXHQgKiAlYlx0XHRhYmJyZXZpYXRlZCBtb250aCBuYW1lIGFjY29yZGluZyB0byB0aGUgY3VycmVudCBsb2NhbGVkXHRcdFx0XHRcdFx0XCJKYW5cIiB0aHJvdWdoIFwiRGVjXCJcclxuXHQgKiAlQlx0XHRmdWxsIG1vbnRoIG5hbWUgYWNjb3JkaW5nIHRvIHRoZSBjdXJyZW50IGxvY2FsZVx0XHRcdFx0XHRcdFx0XHRcIkphbnVhcnlcIiB0aHJvdWdoIFwiRGVjZW1iZXJcIlxyXG5cdCAqICVjXHRcdHByZWZlcnJlZCBkYXRlIGFuZCB0aW1lIHJlcHJlc2VudGF0aW9uIGZvciB0aGUgY3VycmVudCBsb2NhbGVcdFx0XHRcdFwiNC8xMy8yMDA4IDEyOjMzIFBNXCJcclxuXHQgKiAlQ1x0XHRjZW50dXJ5IG51bWJlciAodGhlIHllYXIgZGl2aWRlZCBieSAxMDAgYW5kIHRydW5jYXRlZCB0byBhbiBpbnRlZ2VyKVx0XHRcIjAwXCIgdG8gXCI5OVwiXHJcblx0ICogJWRcdFx0ZGF5IG9mIHRoZSBtb250aCBhcyBhIGRlY2ltYWwgbnVtYmVyXHRcdFx0XHRcdFx0XHRcdFx0XHRcIjAxXCIgdG8gXCIzMVwiXHJcblx0ICogJURcdFx0c2FtZSBhcyAlbS8lZC8leVx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFwiMDQvMTMvMDhcIlxyXG5cdCAqICVlXHRcdGRheSBvZiB0aGUgbW9udGggYXMgYSBkZWNpbWFsIG51bWJlciwgYSBzaW5nbGUgZGlnaXQgaXMgcHJlY2VkZWQgYnkgYSBzcGFjZVx0XCIxXCIgdG8gXCIzMVwiXHJcblx0ICogJWdcdFx0bGlrZSAlRywgYnV0IHdpdGhvdXQgdGhlIGNlbnR1cnlcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCIwOFwiXHJcblx0ICogJUdcdFx0VGhlIDQtZGlnaXQgeWVhciBjb3JyZXNwb25kaW5nIHRvIHRoZSBJU08gd2VlayBudW1iZXIgKHNlZSAlVikuXHRcdFx0XHRcIjIwMDhcIlxyXG5cdCAqXHRcdFRoaXMgaGFzIHRoZSBzYW1lIGZvcm1hdCBhbmQgdmFsdWUgYXMgJVksIGV4Y2VwdCB0aGF0IGlmIHRoZSBJU08gd2VlayBudW1iZXJcclxuXHQgKlx0XHRiZWxvbmdzIHRvIHRoZSBwcmV2aW91cyBvciBuZXh0IHllYXIsIHRoYXQgeWVhciBpcyB1c2VkIGluc3RlYWQuXHJcblx0ICogJWhcdFx0c2FtZSBhcyAlYlx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIkphblwiIHRocm91Z2ggXCJEZWNcIlxyXG5cdCAqICVIXHRcdGhvdXIgYXMgYSBkZWNpbWFsIG51bWJlciB1c2luZyBhIDI0LWhvdXIgY2xvY2suXHRcdFx0XHRcdFx0XHRcdFwiMDBcIiB0byBcIjIzXCJcclxuXHQgKiAlSVx0XHRob3VyIGFzIGEgZGVjaW1hbCBudW1iZXIgdXNpbmcgYSAxMi1ob3VyIGNsb2NrLlx0XHRcdFx0XHRcdFx0XHRcIjAxXCIgdG8gXCIxMlwiXHJcblx0ICogJWpcdFx0ZGF5IG9mIHRoZSB5ZWFyIGFzIGEgZGVjaW1hbCBudW1iZXIuXHRcdFx0XHRcdFx0XHRcdFx0XHRcIjAwMVwiIHRvIFwiMzY2XCJcclxuXHQgKiAlbVx0XHRtb250aCBhcyBhIGRlY2ltYWwgbnVtYmVyLlx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCIwMVwiIHRvIFwiMTJcIlxyXG5cdCAqICVNXHRcdG1pbnV0ZSBhcyBhIGRlY2ltYWwgbnVtYmVyLlx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCIwMFwiIHRvIFwiNTlcIlxyXG5cdCAqICVuXHRcdG5ld2xpbmUgY2hhcmFjdGVyXHRcdFwiXFxuXCJcclxuXHQgKiAlcFx0XHRlaXRoZXIgXCJhbVwiIG9yIFwicG1cIiBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIHRpbWUgdmFsdWUsIG9yIHRoZVx0XHRcdFx0XCJhbVwiIG9yIFwicG1cIlxyXG5cdCAqXHRcdGNvcnJlc3BvbmRpbmcgc3RyaW5ncyBmb3IgdGhlIGN1cnJlbnQgbG9jYWxlLlxyXG5cdCAqICVyXHRcdHRpbWUgaW4gYS5tLiBhbmQgcC5tLiBub3RhdGlvblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFwiODo0NCBQTVwiXHJcblx0ICogJVJcdFx0dGltZSBpbiAyNCBob3VyIG5vdGF0aW9uXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIjIwOjQ0XCJcclxuXHQgKiAlU1x0XHRzZWNvbmQgYXMgYSBkZWNpbWFsIG51bWJlclx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCIwMFwiIHRvIFwiNTlcIlxyXG5cdCAqICV0XHRcdHRhYiBjaGFyYWN0ZXJcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFwiXFx0XCJcclxuXHQgKiAlVFx0XHRjdXJyZW50IHRpbWUsIGVxdWFsIHRvICVIOiVNOiVTXHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCIxMjo0OToxMVwiXHJcblx0ICogJXVcdFx0d2Vla2RheSBhcyBhIGRlY2ltYWwgbnVtYmVyIFtcIjFcIiwgXCI3XCJdLCB3aXRoIFwiMVwiIHJlcHJlc2VudGluZyBNb25kYXlcdFx0XCIxXCIgdG8gXCI3XCJcclxuXHQgKiAlVVx0XHR3ZWVrIG51bWJlciBvZiB0aGUgY3VycmVudCB5ZWFyIGFzIGEgZGVjaW1hbCBudW1iZXIsIHN0YXJ0aW5nIHdpdGggdGhlXHRcdFwiMFwiIHRvIChcIjUyXCIgb3IgXCI1M1wiKVxyXG5cdCAqXHRcdGZpcnN0IFN1bmRheSBhcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSBmaXJzdCB3ZWVrXHJcblx0ICogJVZcdFx0VGhlIElTTyA4NjAxOjE5ODggd2VlayBudW1iZXIgb2YgdGhlIGN1cnJlbnQgeWVhciBhcyBhIGRlY2ltYWwgbnVtYmVyLFx0XHRcIjAwXCIgdG8gKFwiNTJcIiBvciBcIjUzXCIpXHJcblx0ICpcdFx0cmFuZ2UgMDEgdG8gNTMsIHdoZXJlIHdlZWsgMSBpcyB0aGUgZmlyc3Qgd2VlayB0aGF0IGhhcyBhdCBsZWFzdCA0IGRheXNcclxuXHQgKlx0XHRpbiB0aGUgY3VycmVudCB5ZWFyLCBhbmQgd2l0aCBNb25kYXkgYXMgdGhlIGZpcnN0IGRheSBvZiB0aGUgd2Vlay5cclxuXHQgKlx0XHQoVXNlICVHIG9yICVnIGZvciB0aGUgeWVhciBjb21wb25lbnQgdGhhdCBjb3JyZXNwb25kcyB0byB0aGUgd2VlayBudW1iZXJcclxuXHQgKlx0XHRmb3IgdGhlIHNwZWNpZmllZCB0aW1lc3RhbXAuKVxyXG5cdCAqICVXXHRcdHdlZWsgbnVtYmVyIG9mIHRoZSBjdXJyZW50IHllYXIgYXMgYSBkZWNpbWFsIG51bWJlciwgc3RhcnRpbmcgd2l0aCB0aGVcdFx0XCIwMFwiIHRvIChcIjUyXCIgb3IgXCI1M1wiKVxyXG5cdCAqXHRcdGZpcnN0IE1vbmRheSBhcyB0aGUgZmlyc3QgZGF5IG9mIHRoZSBmaXJzdCB3ZWVrXHJcblx0ICogJXdcdFx0ZGF5IG9mIHRoZSB3ZWVrIGFzIGEgZGVjaW1hbCwgU3VuZGF5IGJlaW5nIFwiMFwiXHRcdFx0XHRcdFx0XHRcdFwiMFwiIHRvIFwiNlwiXHJcblx0ICogJXhcdFx0cHJlZmVycmVkIGRhdGUgcmVwcmVzZW50YXRpb24gZm9yIHRoZSBjdXJyZW50IGxvY2FsZSB3aXRob3V0IHRoZSB0aW1lXHRcdFwiNC8xMy8yMDA4XCJcclxuXHQgKiAlWFx0XHRwcmVmZXJyZWQgdGltZSByZXByZXNlbnRhdGlvbiBmb3IgdGhlIGN1cnJlbnQgbG9jYWxlIHdpdGhvdXQgdGhlIGRhdGVcdFx0XCIxMjo1MzowNVwiXHJcblx0ICogJXlcdFx0eWVhciBhcyBhIGRlY2ltYWwgbnVtYmVyIHdpdGhvdXQgYSBjZW50dXJ5XHRcdFx0XHRcdFx0XHRcdFx0XCIwMFwiIFwiOTlcIlxyXG5cdCAqICVZXHRcdHllYXIgYXMgYSBkZWNpbWFsIG51bWJlciBpbmNsdWRpbmcgdGhlIGNlbnR1cnlcdFx0XHRcdFx0XHRcdFx0XCIyMDA4XCJcclxuXHQgKiAlWlx0XHR0aW1lIHpvbmUgb3IgbmFtZSBvciBhYmJyZXZpYXRpb25cdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCJVVENcIiwgXCJFU1RcIiwgXCJQU1RcIlxyXG5cdCAqICV6XHRcdHNhbWUgYXMgJVpcclxuXHQgKiAlJVx0XHRhIGxpdGVyYWwgXCIlXCIgY2hhcmFjdGVyc1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCIlXCJcclxuXHQgKiBkXHRcdERheSBvZiB0aGUgbW9udGgsIDIgZGlnaXRzIHdpdGggbGVhZGluZyB6ZXJvc1x0XHRcdFx0XHRcdFx0XHRcIjAxXCIgdG8gXCIzMVwiXHJcblx0ICogRFx0XHRBIHRleHR1YWwgcmVwcmVzZW50YXRpb24gb2YgYSBkYXksIHRocmVlIGxldHRlcnNcdFx0XHRcdFx0XHRcdFwiTW9uXCIgdGhyb3VnaCBcIlN1blwiXHJcblx0ICogalx0XHREYXkgb2YgdGhlIG1vbnRoIHdpdGhvdXQgbGVhZGluZyB6ZXJvc1x0XHRcdFx0XHRcdFx0XHRcdFx0XCIxXCIgdG8gXCIzMVwiXHJcblx0ICogbFx0XHRBIGZ1bGwgdGV4dHVhbCByZXByZXNlbnRhdGlvbiBvZiB0aGUgZGF5IG9mIHRoZSB3ZWVrIChsb3dlcmNhc2UgXCJMXCIpXHRcdFwiU3VuZGF5XCIgdGhyb3VnaCBcIlNhdHVyZGF5XCJcclxuXHQgKiBOXHRcdElTTy04NjAxIG51bWVyaWMgcmVwcmVzZW50YXRpb24gb2YgdGhlIGRheSBvZiB0aGUgd2VlayAoYWRkZWQgaW4gUEhQIDUuMS4wKVx0XCIxXCIgKGZvciBNb25kYXkpIHRocm91Z2ggXCI3XCIgKGZvciBTdW5kYXkpXHJcblx0ICogU1x0XHRFbmdsaXNoIG9yZGluYWwgc3VmZml4IGZvciB0aGUgZGF5IG9mIHRoZSBtb250aCwgMiBjaGFyYWN0ZXJzXHRcdFx0XHRcInN0XCIsIFwibmRcIiwgXCJyZFwiIG9yIFwidGhcIi4gV29ya3Mgd2VsbCB3aXRoIGpcclxuXHQgKiB3XHRcdE51bWVyaWMgcmVwcmVzZW50YXRpb24gb2YgdGhlIGRheSBvZiB0aGUgd2Vla1x0XHRcdFx0XHRcdFx0XHRcIjBcIiAoZm9yIFN1bmRheSkgdGhyb3VnaCBcIjZcIiAoZm9yIFNhdHVyZGF5KVxyXG5cdCAqIHpcdFx0VGhlIGRheSBvZiB0aGUgeWVhciAoc3RhcnRpbmcgZnJvbSBcIjBcIilcdFx0XHRcdFx0XHRcdFx0XHRcdFwiMFwiIHRocm91Z2ggXCIzNjVcIlxyXG5cdCAqIFdcdFx0SVNPLTg2MDEgd2VlayBudW1iZXIgb2YgeWVhciwgd2Vla3Mgc3RhcnRpbmcgb24gTW9uZGF5XHRcdFx0XHRcdFx0XCIwMFwiIHRvIChcIjUyXCIgb3IgXCI1M1wiKVxyXG5cdCAqIEZcdFx0QSBmdWxsIHRleHR1YWwgcmVwcmVzZW50YXRpb24gb2YgYSBtb250aCwgc3VjaCBhcyBKYW51YXJ5IG9yIE1hcmNoXHRcdFx0XCJKYW51YXJ5XCIgdGhyb3VnaCBcIkRlY2VtYmVyXCJcclxuXHQgKiBtXHRcdE51bWVyaWMgcmVwcmVzZW50YXRpb24gb2YgYSBtb250aCwgd2l0aCBsZWFkaW5nIHplcm9zXHRcdFx0XHRcdFx0XCIwMVwiIHRocm91Z2ggXCIxMlwiXHJcblx0ICogTVx0XHRBIHNob3J0IHRleHR1YWwgcmVwcmVzZW50YXRpb24gb2YgYSBtb250aCwgdGhyZWUgbGV0dGVyc1x0XHRcdFx0XHRcIkphblwiIHRocm91Z2ggXCJEZWNcIlxyXG5cdCAqIG5cdFx0TnVtZXJpYyByZXByZXNlbnRhdGlvbiBvZiBhIG1vbnRoLCB3aXRob3V0IGxlYWRpbmcgemVyb3NcdFx0XHRcdFx0XCIxXCIgdGhyb3VnaCBcIjEyXCJcclxuXHQgKiB0XHRcdE51bWJlciBvZiBkYXlzIGluIHRoZSBnaXZlbiBtb250aFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIjI4XCIgdGhyb3VnaCBcIjMxXCJcclxuXHQgKiBMXHRcdFdoZXRoZXIgaXQncyBhIGxlYXAgeWVhclx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCIxXCIgaWYgaXQgaXMgYSBsZWFwIHllYXIsIFwiMFwiIG90aGVyd2lzZVxyXG5cdCAqIG9cdFx0SVNPLTg2MDEgeWVhciBudW1iZXIuIFRoaXMgaGFzIHRoZSBzYW1lIHZhbHVlIGFzIFksIGV4Y2VwdCB0aGF0IGlmIHRoZVx0XHRcIjIwMDhcIlxyXG5cdCAqXHRcdElTTyB3ZWVrIG51bWJlciAoVykgYmVsb25ncyB0byB0aGUgcHJldmlvdXMgb3IgbmV4dCB5ZWFyLCB0aGF0IHllYXJcclxuXHQgKlx0XHRpcyB1c2VkIGluc3RlYWQuXHJcblx0ICogWVx0XHRBIGZ1bGwgbnVtZXJpYyByZXByZXNlbnRhdGlvbiBvZiBhIHllYXIsIDQgZGlnaXRzXHRcdFx0XHRcdFx0XHRcIjIwMDhcIlxyXG5cdCAqIHlcdFx0QSB0d28gZGlnaXQgcmVwcmVzZW50YXRpb24gb2YgYSB5ZWFyXHRcdFx0XHRcdFx0XHRcdFx0XHRcIjA4XCJcclxuXHQgKiBhXHRcdExvd2VyY2FzZSBBbnRlIG1lcmlkaWVtIGFuZCBQb3N0IG1lcmlkaWVtXHRcdFx0XHRcdFx0XHRcdFx0XCJhbVwiIG9yIFwicG1cIlxyXG5cdCAqIEFcdFx0VXBwZXJjYXNlIEFudGUgbWVyaWRpZW0gYW5kIFBvc3QgbWVyaWRpZW1cdFx0XHRcdFx0XHRcdFx0XHRcIkFNXCIgb3IgXCJQTVwiXHJcblx0ICogQlx0XHRTd2F0Y2ggSW50ZXJuZXQgdGltZVx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIjAwMFwiIHRocm91Z2ggXCI5OTlcIlxyXG5cdCAqIGdcdFx0MTItaG91ciBmb3JtYXQgb2YgYW4gaG91ciB3aXRob3V0IGxlYWRpbmcgemVyb3NcdFx0XHRcdFx0XHRcdFx0XCIxXCIgdGhyb3VnaCBcIjEyXCJcclxuXHQgKiBHXHRcdDI0LWhvdXIgZm9ybWF0IG9mIGFuIGhvdXIgd2l0aG91dCBsZWFkaW5nIHplcm9zXHRcdFx0XHRcdFx0XHRcdFwiMFwiIHRocm91Z2ggXCIyM1wiXHJcblx0ICogaFx0XHQxMi1ob3VyIGZvcm1hdCBvZiBhbiBob3VyIHdpdGggbGVhZGluZyB6ZXJvc1x0XHRcdFx0XHRcdFx0XHRcIjAxXCIgdGhyb3VnaCBcIjEyXCJcclxuXHQgKiBIXHRcdDI0LWhvdXIgZm9ybWF0IG9mIGFuIGhvdXIgd2l0aCBsZWFkaW5nIHplcm9zXHRcdFx0XHRcdFx0XHRcdFwiMDBcIiB0aHJvdWdoIFwiMjNcIlxyXG5cdCAqIGlcdFx0TWludXRlcyB3aXRoIGxlYWRpbmcgemVyb3NcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFwiMDBcIiB0byBcIjU5XCJcclxuXHQgKiBzXHRcdFNlY29uZHMsIHdpdGggbGVhZGluZyB6ZXJvc1x0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XCIwMFwiIHRocm91Z2ggXCI1OVwiXHJcblx0ICogdVx0XHRNaWxsaXNlY29uZHNcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFwiNTQzMjFcIlxyXG5cdCAqIGVcdFx0VGltZXpvbmUgaWRlbnRpZmllclx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFwiVVRDXCIsIFwiRVNUXCIsIFwiUFNUXCJcclxuXHQgKiBJXHRcdFdoZXRoZXIgb3Igbm90IHRoZSBkYXRlIGlzIGluIGRheWxpZ2h0IHNhdmluZyB0aW1lICh1cHBlcmNhc2UgaSlcdFx0XHRcIjFcIiBpZiBEYXlsaWdodCBTYXZpbmcgVGltZSwgXCIwXCIgb3RoZXJ3aXNlXHJcblx0ICogT1x0XHREaWZmZXJlbmNlIHRvIEdyZWVud2ljaCB0aW1lIChHTVQpIGluIGhvdXJzXHRcdFx0XHRcdFx0XHRcdFx0XCIrMDIwMFwiLCBcIi0wNjAwXCJcclxuXHQgKiBQXHRcdERpZmZlcmVuY2UgdG8gR3JlZW53aWNoIHRpbWUgKEdNVCkgd2l0aCBjb2xvbiBiZXR3ZWVuIGhvdXJzIGFuZCBtaW51dGVzXHRcdFwiKzAyOjAwXCIsIFwiLTA2OjAwXCJcclxuXHQgKiBUXHRcdFRpbWV6b25lIGFiYnJldmlhdGlvblx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIlVUQ1wiLCBcIkVTVFwiLCBcIlBTVFwiXHJcblx0ICogWlx0XHRUaW1lem9uZSBvZmZzZXQgaW4gc2Vjb25kcy4gVGhlIG9mZnNldCBmb3IgdGltZXpvbmVzIHdlc3Qgb2YgVVRDIGlzXHRcdFx0XCItNDMyMDBcIiB0aHJvdWdoIFwiNTA0MDBcIlxyXG5cdCAqXHRcdFx0YWx3YXlzIG5lZ2F0aXZlLCBhbmQgZm9yIHRob3NlIGVhc3Qgb2YgVVRDIGlzIGFsd2F5cyBwb3NpdGl2ZS5cclxuXHQgKiBjXHRcdElTTyA4NjAxIGRhdGVcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFwiMjAwNC0wMi0xMlQxNToxOToyMSswMDowMFwiXHJcblx0ICogclx0XHRSRkMgMjgyMiBmb3JtYXR0ZWQgZGF0ZVx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcdFx0XHRcIlRodSwgMjEgRGVjIDIwMDAgMTY6MDE6MDcgKzAyMDBcIlxyXG5cdCAqIFVcdFx0U2Vjb25kcyBzaW5jZSB0aGUgVW5peCBFcG9jaCAoSmFudWFyeSAxIDE5NzAgMDA6MDA6MDAgR01UKVx0XHRcdFx0XHRcIjBcIlxyXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSAgIEEgZm9ybWF0IHN0cmluZyBjb25zaXN0aW5nIG9mIG9uZSBvciBtb3JlIGZvcm1hdCBzcGNpZmllcnMgW09wdGlvbmFsXS5cclxuXHQgKiBAcmV0dXJuIHtTdHJpbmd9ICBBIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGUgY3VycmVudCBEYXRlIG9iamVjdC5cclxuXHQgKi9cclxuXHR2YXIgZm9ybWF0UmVwbGFjZSA9IGZ1bmN0aW9uIChjb250ZXh0KSB7XHJcblx0XHRyZXR1cm4gZnVuY3Rpb24gKG0pIHtcclxuXHRcdFx0dmFyIGZvcm1hdFN0cmluZywgb3ZlcnJpZGUgPSBmYWxzZTtcclxuXHRcdFx0aWYgKG0uY2hhckF0KDApID09PSBcIlxcXFxcIiB8fCBtLnN1YnN0cmluZygwLCAyKSA9PT0gXCIlJVwiKSB7XHJcblx0XHRcdFx0cmV0dXJuIG0ucmVwbGFjZShcIlxcXFxcIiwgXCJcIikucmVwbGFjZShcIiUlXCIsIFwiJVwiKTtcclxuXHRcdFx0fVxyXG5cclxuXHRcdFx0b3ZlcnJpZGUgPSBub3JtYWxpemVyLnNob3VsZE92ZXJyaWRlRGVmYXVsdHMobSk7XHJcblx0XHRcdGZvcm1hdFN0cmluZyA9ICRELm5vcm1hbGl6ZUZvcm1hdChtLCBjb250ZXh0KTtcclxuXHRcdFx0aWYgKGZvcm1hdFN0cmluZykge1xyXG5cdFx0XHRcdHJldHVybiBjb250ZXh0LnRvU3RyaW5nKGZvcm1hdFN0cmluZywgb3ZlcnJpZGUpO1xyXG5cdFx0XHR9XHJcblx0XHR9O1xyXG5cdH07XHJcblx0JFAuX2Zvcm1hdCA9IGZ1bmN0aW9uIChmb3JtYXQpIHtcclxuXHRcdHZhciBmb3JtYXR0ZXIgPSBmb3JtYXRSZXBsYWNlKHRoaXMpO1xyXG5cdFx0aWYgKCFmb3JtYXQpIHtcclxuXHRcdFx0cmV0dXJuIHRoaXMuX3RvU3RyaW5nKCk7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHRyZXR1cm4gZm9ybWF0LnJlcGxhY2UoLyglfFxcXFwpPy58JSUvZywgZm9ybWF0dGVyKTtcclxuXHRcdH1cclxuXHR9O1xyXG5cclxuXHRpZiAoISRQLmZvcm1hdCkge1xyXG5cdFx0JFAuZm9ybWF0ID0gJFAuX2Zvcm1hdDtcclxuXHR9XHJcbn0oKSk7IiwiKGZ1bmN0aW9uICgpIHtcblx0XCJ1c2Ugc3RyaWN0XCI7XG5cdERhdGUuUGFyc2luZyA9IHtcblx0XHRFeGNlcHRpb246IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHR0aGlzLm1lc3NhZ2UgPSBcIlBhcnNlIGVycm9yIGF0ICdcIiArIHMuc3Vic3RyaW5nKDAsIDEwKSArIFwiIC4uLidcIjtcblx0XHR9XG5cdH07XG5cdHZhciAkUCA9IERhdGUuUGFyc2luZztcblx0dmFyIGRheU9mZnNldHMgPSB7XG5cdFx0c3RhbmRhcmQ6IFswLDMxLDU5LDkwLDEyMCwxNTEsMTgxLDIxMiwyNDMsMjczLDMwNCwzMzRdLFxuXHRcdGxlYXA6IFswLDMxLDYwLDkxLDEyMSwxNTIsMTgyLDIxMywyNDQsMjc0LDMwNSwzMzVdXG5cdH07XG5cblx0JFAuaXNMZWFwWWVhciA9IGZ1bmN0aW9uKHllYXIpIHtcblx0XHRyZXR1cm4gKCh5ZWFyICUgNCA9PT0gMCkgJiYgKHllYXIgJSAxMDAgIT09IDApKSB8fCAoeWVhciAlIDQwMCA9PT0gMCk7XG5cdH07XG5cblx0dmFyIHV0aWxzID0ge1xuXHRcdG11bHRpUmVwbGFjZSA6IGZ1bmN0aW9uIChzdHIsIGhhc2ggKSB7XG5cdFx0XHR2YXIga2V5O1xuXHRcdFx0Zm9yIChrZXkgaW4gaGFzaCkge1xuXHRcdFx0XHRpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGhhc2gsIGtleSkpIHtcblx0XHRcdFx0XHR2YXIgcmVnZXg7XG5cdFx0XHRcdFx0aWYgKHR5cGVvZiBoYXNoW2tleV0gPT09IFwiZnVuY3Rpb25cIikge1xuXG5cdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdHJlZ2V4ID0gKGhhc2hba2V5XSBpbnN0YW5jZW9mIFJlZ0V4cCkgPyBoYXNoW2tleV0gOiBuZXcgUmVnRXhwKGhhc2hba2V5XSwgXCJnXCIpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRzdHIgPSBzdHIucmVwbGFjZShyZWdleCwga2V5KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIHN0cjtcblx0XHR9LFxuXHRcdGdldERheU9mWWVhckZyb21XZWVrIDogZnVuY3Rpb24gKG9iaikge1xuXHRcdFx0dmFyIGQsIGphbjQsIG9mZnNldDtcblx0XHRcdG9iai53ZWVrRGF5ID0gKCFvYmoud2Vla0RheSAmJiBvYmoud2Vla0RheSAhPT0gMCkgPyAxIDogb2JqLndlZWtEYXk7XG5cdFx0XHRkID0gbmV3IERhdGUob2JqLnllYXIsIDAsIDQpO1xuXHRcdFx0amFuNCA9IGQuZ2V0RGF5KCkgPT09IDAgPyA3IDogZC5nZXREYXkoKTsgLy8gSlMgaXMgMCBpbmRleGVkIG9uIFN1bmRheS5cblx0XHRcdG9mZnNldCA9IGphbjQrMztcblx0XHRcdG9iai5kYXlPZlllYXIgPSAoKG9iai53ZWVrICogNykgKyAob2JqLndlZWtEYXkgPT09IDAgPyA3IDogb2JqLndlZWtEYXkpKS1vZmZzZXQ7XG5cdFx0XHRyZXR1cm4gb2JqO1xuXHRcdH0sXG5cdFx0Z2V0RGF5T2ZZZWFyIDogZnVuY3Rpb24gKG9iaiwgZGF5T2Zmc2V0KSB7XG5cdFx0XHRpZiAoIW9iai5kYXlPZlllYXIpIHtcblx0XHRcdFx0b2JqID0gdXRpbHMuZ2V0RGF5T2ZZZWFyRnJvbVdlZWsob2JqKTtcblx0XHRcdH1cblx0XHRcdGZvciAodmFyIGk9MDtpIDw9IGRheU9mZnNldC5sZW5ndGg7aSsrKSB7XG5cdFx0XHRcdGlmIChvYmouZGF5T2ZZZWFyIDwgZGF5T2Zmc2V0W2ldIHx8IGkgPT09IGRheU9mZnNldC5sZW5ndGgpIHtcblx0XHRcdFx0XHRvYmouZGF5ID0gb2JqLmRheSA/IG9iai5kYXkgOiAob2JqLmRheU9mWWVhciAtIGRheU9mZnNldFtpLTFdKTtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRvYmoubW9udGggPSBpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gb2JqO1xuXHRcdH0sXG5cdFx0YWRqdXN0Rm9yVGltZVpvbmUgOiBmdW5jdGlvbiAob2JqLCBkYXRlKSB7XG5cdFx0XHR2YXIgb2Zmc2V0O1xuXHRcdFx0aWYgKG9iai56b25lLnRvVXBwZXJDYXNlKCkgPT09IFwiWlwiIHx8IChvYmouem9uZV9ob3VycyA9PT0gMCAmJiBvYmouem9uZV9taW51dGVzID09PSAwKSkge1xuXHRcdFx0XHQvLyBpdCdzIFVUQy9HTUwgc28gd29yayBvdXQgdGhlIGN1cnJlbnQgdGltZXN6b25lIG9mZnNldFxuXHRcdFx0XHRvZmZzZXQgPSAtZGF0ZS5nZXRUaW1lem9uZU9mZnNldCgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0b2Zmc2V0ID0gKG9iai56b25lX2hvdXJzKjYwKSArIChvYmouem9uZV9taW51dGVzIHx8IDApO1xuXHRcdFx0XHRpZiAob2JqLnpvbmVfc2lnbiA9PT0gXCIrXCIpIHtcblx0XHRcdFx0XHRvZmZzZXQgKj0gLTE7XG5cdFx0XHRcdH1cblx0XHRcdFx0b2Zmc2V0IC09IGRhdGUuZ2V0VGltZXpvbmVPZmZzZXQoKTtcblx0XHRcdH1cblx0XHRcdGRhdGUuc2V0TWludXRlcyhkYXRlLmdldE1pbnV0ZXMoKStvZmZzZXQpO1xuXHRcdFx0cmV0dXJuIGRhdGU7XG5cdFx0fSxcblx0XHRzZXREZWZhdWx0cyA6IGZ1bmN0aW9uIChvYmopIHtcblx0XHRcdG9iai55ZWFyID0gb2JqLnllYXIgfHwgRGF0ZS50b2RheSgpLmdldEZ1bGxZZWFyKCk7XG5cdFx0XHRvYmouaG91cnMgPSBvYmouaG91cnMgfHwgMDtcblx0XHRcdG9iai5taW51dGVzID0gb2JqLm1pbnV0ZXMgfHwgMDtcblx0XHRcdG9iai5zZWNvbmRzID0gb2JqLnNlY29uZHMgfHwgMDtcblx0XHRcdG9iai5taWxsaXNlY29uZHMgPSBvYmoubWlsbGlzZWNvbmRzIHx8IDA7XG5cdFx0XHRpZiAoISghb2JqLm1vbnRoICYmIChvYmoud2VlayB8fCBvYmouZGF5T2ZZZWFyKSkpIHtcblx0XHRcdFx0Ly8gaWYgd2UgaGF2ZSBhIG1vbnRoLCBvciBpZiB3ZSBkb24ndCBidXQgZG9uJ3QgaGF2ZSB0aGUgZGF5IGNhbGN1bGF0aW9uIGRhdGFcblx0XHRcdFx0b2JqLm1vbnRoID0gb2JqLm1vbnRoIHx8IDA7XG5cdFx0XHRcdG9iai5kYXkgPSBvYmouZGF5IHx8IDE7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gb2JqO1xuXHRcdH0sXG5cdFx0ZGF0YU51bTogZnVuY3Rpb24gKGRhdGEsIG1vZCwgZXhwbGljdCwgcG9zdFByb2Nlc3MpIHtcblx0XHRcdHZhciBkYXRhTnVtID0gZGF0YSoxO1xuXHRcdFx0aWYgKG1vZCkge1xuXHRcdFx0XHRpZiAocG9zdFByb2Nlc3MpIHtcblx0XHRcdFx0XHRyZXR1cm4gZGF0YSA/IG1vZChkYXRhKSoxIDogZGF0YTtcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRyZXR1cm4gZGF0YSA/IG1vZChkYXRhTnVtKSA6IGRhdGE7XG5cdFx0XHRcdH1cblx0XHRcdH0gZWxzZSBpZiAoIWV4cGxpY3Qpe1xuXHRcdFx0XHRyZXR1cm4gZGF0YSA/IGRhdGFOdW0gOiBkYXRhO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuIChkYXRhICYmIHR5cGVvZiBkYXRhICE9PSBcInVuZGVmaW5lZFwiKSA/IGRhdGFOdW0gOiBkYXRhO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0dGltZURhdGFQcm9jZXNzOiBmdW5jdGlvbiAob2JqKSB7XG5cdFx0XHR2YXIgdGltZU9iaiA9IHt9O1xuXHRcdFx0Zm9yICh2YXIgeCBpbiBvYmouZGF0YSkge1xuXHRcdFx0XHRpZiAob2JqLmRhdGEuaGFzT3duUHJvcGVydHkoeCkpIHtcblx0XHRcdFx0XHR0aW1lT2JqW3hdID0gb2JqLmlnbm9yZVt4XSA/IG9iai5kYXRhW3hdIDogdXRpbHMuZGF0YU51bShvYmouZGF0YVt4XSwgb2JqLm1vZHNbeF0sIG9iai5leHBsaWN0W3hdLCBvYmoucG9zdFByb2Nlc3NbeF0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAob2JqLmRhdGEuc2VjbWlucykge1xuXHRcdFx0XHRvYmouZGF0YS5zZWNtaW5zID0gb2JqLmRhdGEuc2VjbWlucy5yZXBsYWNlKFwiLFwiLCBcIi5cIikgKiA2MDtcblx0XHRcdFx0aWYgKCF0aW1lT2JqLm1pbnV0ZXMpIHtcblx0XHRcdFx0XHR0aW1lT2JqLm1pbnV0ZXMgPSBvYmouZGF0YS5zZWNtaW5zO1xuXHRcdFx0XHR9IGVsc2UgaWYgKCF0aW1lT2JqLnNlY29uZHMpIHtcblx0XHRcdFx0XHR0aW1lT2JqLnNlY29uZHMgPSBvYmouZGF0YS5zZWNtaW5zO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGRlbGV0ZSBvYmouc2VjbWlucztcblx0XHRcdH1cblx0XHRcdHJldHVybiB0aW1lT2JqO1xuXHRcdH0sXG5cdFx0YnVpbGRUaW1lT2JqZWN0RnJvbURhdGE6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHR2YXIgdGltZSA9IHV0aWxzLnRpbWVEYXRhUHJvY2Vzcyh7XG5cdFx0XHRcdGRhdGE6IHtcblx0XHRcdFx0XHR5ZWFyIDogZGF0YVsxXSxcblx0XHRcdFx0XHRtb250aCA6IGRhdGFbNV0sXG5cdFx0XHRcdFx0ZGF5IDogZGF0YVs3XSxcblx0XHRcdFx0XHR3ZWVrIDogZGF0YVs4XSxcblx0XHRcdFx0XHRkYXlPZlllYXIgOiBkYXRhWzEwXSxcblx0XHRcdFx0XHRob3VycyA6IGRhdGFbMTVdLFxuXHRcdFx0XHRcdHpvbmVfaG91cnMgOiBkYXRhWzIzXSxcblx0XHRcdFx0XHR6b25lX21pbnV0ZXMgOiBkYXRhWzI0XSxcblx0XHRcdFx0XHR6b25lIDogZGF0YVsyMV0sXG5cdFx0XHRcdFx0em9uZV9zaWduIDogZGF0YVsyMl0sXG5cdFx0XHRcdFx0d2Vla0RheSA6IGRhdGFbOV0sXG5cdFx0XHRcdFx0bWludXRlczogZGF0YVsxNl0sXG5cdFx0XHRcdFx0c2Vjb25kczogZGF0YVsxOV0sXG5cdFx0XHRcdFx0bWlsbGlzZWNvbmRzOiBkYXRhWzIwXSxcblx0XHRcdFx0XHRzZWNtaW5zOiBkYXRhWzE4XVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRtb2RzOiB7XG5cdFx0XHRcdFx0bW9udGg6IGZ1bmN0aW9uKGRhdGEpIHtcblx0XHRcdFx0XHRcdHJldHVybiBkYXRhLTE7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHR3ZWVrRGF5OiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0XHRcdFx0ZGF0YSA9IE1hdGguYWJzKGRhdGEpO1xuXHRcdFx0XHRcdFx0cmV0dXJuIChkYXRhID09PSA3ID8gMCA6IGRhdGEpO1xuXHRcdFx0XHRcdH0sXG5cdFx0XHRcdFx0bWludXRlczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdFx0XHRcdHJldHVybiBkYXRhLnJlcGxhY2UoXCI6XCIsXCJcIik7XG5cdFx0XHRcdFx0fSxcblx0XHRcdFx0XHRzZWNvbmRzOiBmdW5jdGlvbiAoZGF0YSkge1xuXHRcdFx0XHRcdFx0cmV0dXJuIE1hdGguZmxvb3IoIChkYXRhLnJlcGxhY2UoXCI6XCIsXCJcIikucmVwbGFjZShcIixcIixcIi5cIikpKjEgKTtcblx0XHRcdFx0XHR9LFxuXHRcdFx0XHRcdG1pbGxpc2Vjb25kczogZnVuY3Rpb24gKGRhdGEpIHtcblx0XHRcdFx0XHRcdHJldHVybiAoZGF0YS5yZXBsYWNlKFwiLFwiLFwiLlwiKSoxMDAwKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH0sXG5cdFx0XHRcdHBvc3RQcm9jZXNzOiB7XG5cdFx0XHRcdFx0bWludXRlczogdHJ1ZSxcblx0XHRcdFx0XHRzZWNvbmRzOiB0cnVlLFxuXHRcdFx0XHRcdG1pbGxpc2Vjb25kczogdHJ1ZVxuXHRcdFx0XHR9LFxuXHRcdFx0XHRleHBsaWN0OiB7XG5cdFx0XHRcdFx0em9uZV9ob3VyczogdHJ1ZSxcblx0XHRcdFx0XHR6b25lX21pbnV0ZXM6IHRydWVcblx0XHRcdFx0fSxcblx0XHRcdFx0aWdub3JlOiB7XG5cdFx0XHRcdFx0em9uZTogdHJ1ZSxcblx0XHRcdFx0XHR6b25lX3NpZ246IHRydWUsXG5cdFx0XHRcdFx0c2VjbWluczogdHJ1ZVxuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHRcdHJldHVybiB0aW1lO1xuXHRcdH0sXG5cdFx0YWRkVG9IYXNoOiBmdW5jdGlvbiAoaGFzaCwga2V5cywgZGF0YSkge1xuXHRcdFx0a2V5cyA9IGtleXM7XG5cdFx0XHRkYXRhID0gZGF0YTtcblx0XHRcdHZhciBsZW4gPSBrZXlzLmxlbmd0aDtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpKyspIHtcblx0XHRcdCAgaGFzaFtrZXlzW2ldXSA9IGRhdGFbaV07XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gaGFzaDtcblx0XHR9LFxuXHRcdGNvbWJpbmVSZWdleDogZnVuY3Rpb24gKHIxLCByMikge1xuXHRcdFx0cmV0dXJuIG5ldyBSZWdFeHAoXCIoKFwiK3IxLnNvdXJjZStcIilcXFxccyhcIityMi5zb3VyY2UrXCIpKVwiKTtcblx0XHR9LFxuXHRcdGdldERhdGVOdGhTdHJpbmc6IGZ1bmN0aW9uKGFkZCwgbGFzdCwgaW5jKXtcblx0XHRcdGlmIChhZGQpIHtcblx0XHRcdFx0cmV0dXJuIERhdGUudG9kYXkoKS5hZGREYXlzKGluYykudG9TdHJpbmcoXCJkXCIpO1xuXHRcdFx0fSBlbHNlIGlmIChsYXN0KSB7XG5cdFx0XHRcdHJldHVybiBEYXRlLnRvZGF5KCkubGFzdCgpW2luY10oKS50b1N0cmluZyhcImRcIik7XG5cdFx0XHR9XG5cblx0XHR9LFxuXHRcdGJ1aWxkUmVnZXhEYXRhOiBmdW5jdGlvbiAoYXJyYXkpIHtcblx0XHRcdHZhciBhcnIgPSBbXTtcblx0XHRcdHZhciBsZW4gPSBhcnJheS5sZW5ndGg7XG5cdFx0XHRmb3IgKHZhciBpPTA7IGkgPCBsZW47IGkrKykge1xuXHRcdFx0XHRpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGFycmF5W2ldKSA9PT0gJ1tvYmplY3QgQXJyYXldJykgeyAvLyBvbGRJRSBjb21wYXQgdmVyc2lvbiBvZiBBcnJheS5pc0FycmF5XG5cdFx0XHRcdFx0YXJyLnB1c2godGhpcy5jb21iaW5lUmVnZXgoYXJyYXlbaV1bMF0sIGFycmF5W2ldWzFdKSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0YXJyLnB1c2goYXJyYXlbaV0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gYXJyO1xuXHRcdH1cblx0fTtcblxuXHQkUC5wcm9jZXNzVGltZU9iamVjdCA9IGZ1bmN0aW9uIChvYmopIHtcblx0XHR2YXIgZGF0ZSwgZGF5T2Zmc2V0O1xuXG5cdFx0dXRpbHMuc2V0RGVmYXVsdHMob2JqKTtcblx0XHRkYXlPZmZzZXQgPSAoJFAuaXNMZWFwWWVhcihvYmoueWVhcikpID8gZGF5T2Zmc2V0cy5sZWFwIDogZGF5T2Zmc2V0cy5zdGFuZGFyZDtcblxuXHRcdGlmICghb2JqLm1vbnRoICYmIChvYmoud2VlayB8fCBvYmouZGF5T2ZZZWFyKSkge1xuXHRcdFx0dXRpbHMuZ2V0RGF5T2ZZZWFyKG9iaiwgZGF5T2Zmc2V0KTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0b2JqLmRheU9mWWVhciA9IGRheU9mZnNldFtvYmoubW9udGhdICsgb2JqLmRheTtcblx0XHR9XG5cblx0XHRkYXRlID0gbmV3IERhdGUob2JqLnllYXIsIG9iai5tb250aCwgb2JqLmRheSwgb2JqLmhvdXJzLCBvYmoubWludXRlcywgb2JqLnNlY29uZHMsIG9iai5taWxsaXNlY29uZHMpO1xuXG5cdFx0aWYgKG9iai56b25lKSB7XG5cdFx0XHR1dGlscy5hZGp1c3RGb3JUaW1lWm9uZShvYmosIGRhdGUpOyAvLyBhZGp1c3QgKGFuZCBjYWxjdWxhdGUpIGZvciB0aW1lem9uZVxuXHRcdH1cblx0XHRyZXR1cm4gZGF0ZTtcblx0fTtcblxuXHQkUC5JU08gPSB7XG5cdFx0cmVnZXggOiAvXihbXFwrLV0/XFxkezR9KD8hXFxkezJ9XFxiKSkoKC0/KSgoMFsxLTldfDFbMC0yXSkoXFwzKFsxMl1cXGR8MFsxLTldfDNbMDFdKSk/fFcoWzAtNF1cXGR8NVswLTNdKSgtP1sxLTddKT98KDAwWzEtOV18MFsxLTldXFxkfFsxMl1cXGR7Mn18MyhbMC01XVxcZHw2WzEtNl0pKSkoW1RcXHNdKCgoWzAxXVxcZHwyWzAtNF0pKCg6PylbMC01XVxcZCk/fDI0XFw6PzAwKShbXFwuLF1cXGQrKD8hOikpPyk/KFxcMTdbMC01XVxcZChbXFwuLF1cXGQrKT8pP1xccz8oW3paXXwoW1xcKy1dKShbMDFdXFxkfDJbMC0zXSk6PyhbMC01XVxcZCk/KT8pPyk/JC8sXG5cdFx0cGFyc2UgOiBmdW5jdGlvbiAocykge1xuXHRcdFx0dmFyIHRpbWUsIGRhdGEgPSBzLm1hdGNoKHRoaXMucmVnZXgpO1xuXHRcdFx0aWYgKCFkYXRhIHx8ICFkYXRhLmxlbmd0aCkge1xuXHRcdFx0XHRyZXR1cm4gbnVsbDtcblx0XHRcdH1cblxuXHRcdFx0dGltZSA9IHV0aWxzLmJ1aWxkVGltZU9iamVjdEZyb21EYXRhKGRhdGEpO1xuXG5cdFx0XHRpZiAoIXRpbWUueWVhciB8fCAoIXRpbWUueWVhciAmJiAoIXRpbWUubW9udGggJiYgIXRpbWUuZGF5KSAmJiAoIXRpbWUud2VlayAmJiAhdGltZS5kYXlPZlllYXIpKSApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gJFAucHJvY2Vzc1RpbWVPYmplY3QodGltZSk7XG5cdFx0fVxuXHR9O1xuXG5cdCRQLk51bWVyaWMgPSB7XG5cdFx0aXNOdW1lcmljOiBmdW5jdGlvbiAoZSl7cmV0dXJuIWlzTmFOKHBhcnNlRmxvYXQoZSkpJiZpc0Zpbml0ZShlKTt9LFxuXHRcdHJlZ2V4OiAvXFxiKFswLTFdP1swLTldKShbMC0zXT9bMC05XSkoWzAtMl0/WzAtOV0/WzAtOV1bMC05XSlcXGIvaSxcblx0XHRwYXJzZTogZnVuY3Rpb24gKHMpIHtcblx0XHRcdHZhciBkYXRhLCBpLFxuXHRcdFx0XHR0aW1lID0ge30sXG5cdFx0XHRcdG9yZGVyID0gRGF0ZS5DdWx0dXJlSW5mby5kYXRlRWxlbWVudE9yZGVyLnNwbGl0KFwiXCIpO1xuXHRcdFx0aWYgKCEodGhpcy5pc051bWVyaWMocykpIHx8IC8vIGlmIGl0J3Mgbm9uLW51bWVyaWMgT1Jcblx0XHRcdFx0KHNbMF0gPT09IFwiK1wiICYmIHNbMF0gPT09IFwiLVwiKSkge1x0XHRcdC8vIEl0J3MgYW4gYXJpdGhtYXRpYyBzdHJpbmcgKGVnICsvLTEwMDApXG5cdFx0XHRcdHJldHVybiBudWxsO1xuXHRcdFx0fVxuXHRcdFx0aWYgKHMubGVuZ3RoIDwgNSAmJiBzLmluZGV4T2YoXCIuXCIpIDwgMCAmJiBzLmluZGV4T2YoXCIvXCIpIDwgMCkgeyAvLyBhc3N1bWUgaXQncyBqdXN0IGEgeWVhci5cblx0XHRcdFx0dGltZS55ZWFyID0gcztcblx0XHRcdFx0cmV0dXJuICRQLnByb2Nlc3NUaW1lT2JqZWN0KHRpbWUpO1xuXHRcdFx0fVxuXHRcdFx0ZGF0YSA9IHMubWF0Y2godGhpcy5yZWdleCk7XG5cdFx0XHRpZiAoIWRhdGEgfHwgIWRhdGEubGVuZ3RoKSB7XG5cdFx0XHRcdHJldHVybiBudWxsO1xuXHRcdFx0fVxuXHRcdFx0Zm9yIChpPTA7IGkgPCBvcmRlci5sZW5ndGg7IGkrKykge1xuXHRcdFx0XHRzd2l0Y2gob3JkZXJbaV0pIHtcblx0XHRcdFx0XHRjYXNlIFwiZFwiOlxuXHRcdFx0XHRcdFx0dGltZS5kYXkgPSBkYXRhW2krMV07XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwibVwiOlxuXHRcdFx0XHRcdFx0dGltZS5tb250aCA9IChkYXRhW2krMV0tMSk7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwieVwiOlxuXHRcdFx0XHRcdFx0dGltZS55ZWFyID0gZGF0YVtpKzFdO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdHJldHVybiAkUC5wcm9jZXNzVGltZU9iamVjdCh0aW1lKTtcblx0XHR9XG5cdH07XG5cblx0JFAuTm9ybWFsaXplciA9IHtcblx0XHRyZWdleERhdGE6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciAkUiA9IERhdGUuQ3VsdHVyZUluZm8ucmVnZXhQYXR0ZXJucztcblx0XHRcdHJldHVybiB1dGlscy5idWlsZFJlZ2V4RGF0YShbXG5cdFx0XHRcdCRSLnRvbW9ycm93LFxuXHRcdFx0XHQkUi55ZXN0ZXJkYXksXG5cdFx0XHRcdFskUi5wYXN0LCAkUi5tb25dLFxuXHRcdFx0XHRbJFIucGFzdCwgJFIudHVlXSxcblx0XHRcdFx0WyRSLnBhc3QsICRSLndlZF0sXG5cdFx0XHRcdFskUi5wYXN0LCAkUi50aHVdLFxuXHRcdFx0XHRbJFIucGFzdCwgJFIuZnJpXSxcblx0XHRcdFx0WyRSLnBhc3QsICRSLnNhdF0sXG5cdFx0XHRcdFskUi5wYXN0LCAkUi5zdW5dXG5cdFx0XHRdKTtcblx0XHR9LFxuXHRcdGJhc2ljUmVwbGFjZUhhc2ggOiBmdW5jdGlvbigpIHtcblx0XHRcdHZhciAkUiA9IERhdGUuQ3VsdHVyZUluZm8ucmVnZXhQYXR0ZXJucztcblx0XHRcdHJldHVybiB7XG5cdFx0XHRcdFwiSmFudWFyeVwiOiAkUi5qYW4uc291cmNlLFxuXHRcdFx0XHRcIkZlYnJ1YXJ5XCI6ICRSLmZlYixcblx0XHRcdFx0XCJNYXJjaFwiOiAkUi5tYXIsXG5cdFx0XHRcdFwiQXByaWxcIjogJFIuYXByLFxuXHRcdFx0XHRcIk1heVwiOiAkUi5tYXksXG5cdFx0XHRcdFwiSnVuZVwiOiAkUi5qdW4sXG5cdFx0XHRcdFwiSnVseVwiOiAkUi5qdWwsXG5cdFx0XHRcdFwiQXVndXN0XCI6ICRSLmF1Zyxcblx0XHRcdFx0XCJTZXB0ZW1iZXJcIjogJFIuc2VwLFxuXHRcdFx0XHRcIk9jdG9iZXJcIjogJFIub2N0LFxuXHRcdFx0XHRcIk5vdmVtYmVyXCI6ICRSLm5vdixcblx0XHRcdFx0XCJEZWNlbWJlclwiOiAkUi5kZWMsXG5cdFx0XHRcdFwiXCI6IC9cXGJhdFxcYi9naSxcblx0XHRcdFx0XCIgXCI6IC9cXHN7Mix9Lyxcblx0XHRcdFx0XCJhbVwiOiAkUi5pblRoZU1vcm5pbmcsXG5cdFx0XHRcdFwiOWFtXCI6ICRSLnRoaXNNb3JuaW5nLFxuXHRcdFx0XHRcInBtXCI6ICRSLmluVGhlRXZlbmluZyxcblx0XHRcdFx0XCI3cG1cIjokUi50aGlzRXZlbmluZ1xuXHRcdFx0fTtcblx0XHR9LFxuXHRcdGtleXMgOiBmdW5jdGlvbigpe1xuXHRcdFx0cmV0dXJuIFtcblx0XHRcdFx0dXRpbHMuZ2V0RGF0ZU50aFN0cmluZyh0cnVlLCBmYWxzZSwgMSksXHRcdFx0XHQvLyB0b21vcnJvd1xuXHRcdFx0XHR1dGlscy5nZXREYXRlTnRoU3RyaW5nKHRydWUsIGZhbHNlLCAtMSksXHRcdFx0Ly8geWVzdGVyZGF5XG5cdFx0XHRcdHV0aWxzLmdldERhdGVOdGhTdHJpbmcoZmFsc2UsIHRydWUsIFwibW9uZGF5XCIpLFx0XHQvL2xhc3QgbW9uXG5cdFx0XHRcdHV0aWxzLmdldERhdGVOdGhTdHJpbmcoZmFsc2UsIHRydWUsIFwidHVlc2RheVwiKSxcdFx0Ly9sYXN0IHR1ZXNcblx0XHRcdFx0dXRpbHMuZ2V0RGF0ZU50aFN0cmluZyhmYWxzZSwgdHJ1ZSwgXCJ3ZWRuZXNkYXlcIiksXHQvL2xhc3Qgd2VkXG5cdFx0XHRcdHV0aWxzLmdldERhdGVOdGhTdHJpbmcoZmFsc2UsIHRydWUsIFwidGh1cnNkYXlcIiksXHQvL2xhc3QgdGh1cnNcblx0XHRcdFx0dXRpbHMuZ2V0RGF0ZU50aFN0cmluZyhmYWxzZSwgdHJ1ZSwgXCJmcmlkYXlcIiksXHRcdC8vbGFzdCBmcmlcblx0XHRcdFx0dXRpbHMuZ2V0RGF0ZU50aFN0cmluZyhmYWxzZSwgdHJ1ZSwgXCJzYXR1cmRheVwiKSxcdC8vbGFzdCBzYXRcblx0XHRcdFx0dXRpbHMuZ2V0RGF0ZU50aFN0cmluZyhmYWxzZSwgdHJ1ZSwgXCJzdW5kYXlcIilcdFx0Ly9sYXN0IHN1blxuXHRcdFx0XTtcblx0XHR9LFxuXHRcdGJ1aWxkUmVnZXhGdW5jdGlvbnM6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciAkUiA9IERhdGUuQ3VsdHVyZUluZm8ucmVnZXhQYXR0ZXJucztcblx0XHRcdHZhciBfXyA9IERhdGUuaTE4bi5fXztcblx0XHRcdHZhciB0b21vcnJvd1JFID0gbmV3IFJlZ0V4cChcIihcXFxcYlxcXFxkXFxcXGQ/KFwiK19fKFwiQU1cIikrXCJ8XCIrX18oXCJQTVwiKStcIik/ICkoXCIrJFIudG9tb3Jyb3cuc291cmNlLnNsaWNlKDEpK1wiKVwiLCBcImlcIik7IC8vIGFkYXB0ZWQgdG9tb3Jyb3cgcmVnZXggZm9yIEFNIFBNIHJlbGF0aXZlIGRhdGVzXG5cdFx0XHR2YXIgdG9kYXlSRSA9IG5ldyBSZWdFeHAoJFIudG9kYXkuc291cmNlICsgXCIoPyFcXFxccyooWystXSkpXFxcXGJcIik7IC8vIHRvZGF5LCBidXQgZXhjbHVkZXMgdGhlIG1hdGggb3BlcmF0b3JzIChlZyBcInRvZGF5ICsgMmhcIilcblxuXHRcdFx0dGhpcy5yZXBsYWNlRnVuY3MgPSBbXG5cdFx0XHRcdFt0b2RheVJFLCBmdW5jdGlvbiAoZnVsbCkge1xuXHRcdFx0XHRcdHJldHVybiAoZnVsbC5sZW5ndGggPiAxKSA/IERhdGUudG9kYXkoKS50b1N0cmluZyhcImRcIikgOiBmdWxsO1xuXHRcdFx0XHR9XSxcblx0XHRcdFx0W3RvbW9ycm93UkUsXG5cdFx0XHRcdGZ1bmN0aW9uKGZ1bGwsIG0xKSB7XG5cdFx0XHRcdFx0dmFyIHQgPSBEYXRlLnRvZGF5KCkuYWRkRGF5cygxKS50b1N0cmluZyhcImRcIik7XG5cdFx0XHRcdFx0cmV0dXJuICh0ICsgXCIgXCIgKyBtMSk7XG5cdFx0XHRcdH1dLFxuXHRcdFx0XHRbJFIuYW1UaGlzTW9ybmluZywgZnVuY3Rpb24oc3RyLCBhbSl7cmV0dXJuIGFtO31dLFxuXHRcdFx0XHRbJFIucG1UaGlzRXZlbmluZywgZnVuY3Rpb24oc3RyLCBwbSl7cmV0dXJuIHBtO31dXG5cdFx0XHRdO1xuXG5cdFx0fSxcblx0XHRidWlsZFJlcGxhY2VEYXRhOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHR0aGlzLmJ1aWxkUmVnZXhGdW5jdGlvbnMoKTtcblx0XHRcdHRoaXMucmVwbGFjZUhhc2ggPSB1dGlscy5hZGRUb0hhc2godGhpcy5iYXNpY1JlcGxhY2VIYXNoKCksIHRoaXMua2V5cygpLCB0aGlzLnJlZ2V4RGF0YSgpKTtcblx0XHR9LFxuXHRcdHN0cmluZ1JlcGxhY2VGdW5jczogZnVuY3Rpb24gKHMpIHtcblx0XHRcdGZvciAodmFyIGk9MDsgaSA8IHRoaXMucmVwbGFjZUZ1bmNzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdHMgPSBzLnJlcGxhY2UodGhpcy5yZXBsYWNlRnVuY3NbaV1bMF0sIHRoaXMucmVwbGFjZUZ1bmNzW2ldWzFdKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiBzO1xuXHRcdH0sXG5cdFx0cGFyc2U6IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRzID0gdGhpcy5zdHJpbmdSZXBsYWNlRnVuY3Mocyk7XG5cdFx0XHRzID0gdXRpbHMubXVsdGlSZXBsYWNlKHMsIHRoaXMucmVwbGFjZUhhc2gpO1xuXG5cdFx0XHR0cnkge1xuXHRcdFx0XHR2YXIgbiA9IHMuc3BsaXQoLyhbXFxzXFwtXFwuXFwsXFwvXFx4MjddKykvKTtcblx0XHRcdFx0aWYgKG4ubGVuZ3RoID09PSAzICYmXG5cdFx0XHRcdFx0JFAuTnVtZXJpYy5pc051bWVyaWMoblswXSkgJiZcblx0XHRcdFx0XHQkUC5OdW1lcmljLmlzTnVtZXJpYyhuWzJdKSAmJlxuXHRcdFx0XHRcdChuWzJdLmxlbmd0aCA+PSA0KSkge1xuXHRcdFx0XHRcdFx0Ly8gb2ssIHNvIHdlJ3JlIGRlYWxpbmcgd2l0aCB4L3llYXIuIEJ1dCB0aGF0J3Mgbm90IGEgZnVsbCBkYXRlLlxuXHRcdFx0XHRcdFx0Ly8gVGhpcyBmaXhlcyB3b25reSBkYXRlRWxlbWVudE9yZGVyIHBhcnNpbmcgd2hlbiBzZXQgdG8gZG15IG9yZGVyLlxuXHRcdFx0XHRcdFx0aWYgKERhdGUuQ3VsdHVyZUluZm8uZGF0ZUVsZW1lbnRPcmRlclswXSA9PT0gXCJkXCIpIHtcblx0XHRcdFx0XHRcdFx0cyA9IFwiMS9cIiArIG5bMF0gKyBcIi9cIiArIG5bMl07IC8vIHNldCB0byAxc3Qgb2YgbW9udGggYW5kIG5vcm1hbGl6ZSB0aGUgc2VwZXJhdG9yXG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH0gY2F0Y2ggKGUpIHt9XG5cblx0XHRcdHJldHVybiBzO1xuXHRcdH1cblx0fTtcblx0JFAuTm9ybWFsaXplci5idWlsZFJlcGxhY2VEYXRhKCk7XG59KCkpOyIsIihmdW5jdGlvbiAoKSB7XG5cdHZhciAkRCA9IERhdGU7XG5cdHZhciBsYW5nID0gRGF0ZS5DdWx0dXJlU3RyaW5ncyA/IERhdGUuQ3VsdHVyZVN0cmluZ3MubGFuZyA6IG51bGw7XG5cdHZhciBsb2dnZWRLZXlzID0ge307IC8vIGZvciBkZWJ1ZyBwdXJwb3Nlcy5cblx0dmFyIGdldFRleHQgPSB7XG5cdFx0Z2V0RnJvbUtleTogZnVuY3Rpb24gKGtleSwgY291bnRyeUNvZGUpIHtcblx0XHRcdHZhciBvdXRwdXQ7XG5cdFx0XHRpZiAoRGF0ZS5DdWx0dXJlU3RyaW5ncyAmJiBEYXRlLkN1bHR1cmVTdHJpbmdzW2NvdW50cnlDb2RlXSAmJiBEYXRlLkN1bHR1cmVTdHJpbmdzW2NvdW50cnlDb2RlXVtrZXldKSB7XG5cdFx0XHRcdG91dHB1dCA9IERhdGUuQ3VsdHVyZVN0cmluZ3NbY291bnRyeUNvZGVdW2tleV07XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRvdXRwdXQgPSBnZXRUZXh0LmJ1aWxkRnJvbURlZmF1bHQoa2V5KTtcblx0XHRcdH1cblx0XHRcdGlmIChrZXkuY2hhckF0KDApID09PSBcIi9cIikgeyAvLyBBc3N1bWUgaXQncyBhIHJlZ2V4XG5cdFx0XHRcdG91dHB1dCA9IGdldFRleHQuYnVpbGRGcm9tUmVnZXgoa2V5LCBjb3VudHJ5Q29kZSk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gb3V0cHV0O1xuXHRcdH0sXG5cdFx0Z2V0RnJvbU9iamVjdFZhbHVlczogZnVuY3Rpb24gKG9iaiwgY291bnRyeUNvZGUpIHtcblx0XHRcdHZhciBrZXksIG91dHB1dCA9IHt9O1xuXHRcdFx0Zm9yKGtleSBpbiBvYmopIHtcblx0XHRcdFx0aWYgKG9iai5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG5cdFx0XHRcdFx0b3V0cHV0W2tleV0gPSBnZXRUZXh0LmdldEZyb21LZXkob2JqW2tleV0sIGNvdW50cnlDb2RlKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG91dHB1dDtcblx0XHR9LFxuXHRcdGdldEZyb21PYmplY3RLZXlzOiBmdW5jdGlvbiAob2JqLCBjb3VudHJ5Q29kZSkge1xuXHRcdFx0dmFyIGtleSwgb3V0cHV0ID0ge307XG5cdFx0XHRmb3Ioa2V5IGluIG9iaikge1xuXHRcdFx0XHRpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcblx0XHRcdFx0XHRvdXRwdXRbZ2V0VGV4dC5nZXRGcm9tS2V5KGtleSwgY291bnRyeUNvZGUpXSA9IG9ialtrZXldO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gb3V0cHV0O1xuXHRcdH0sXG5cdFx0Z2V0RnJvbUFycmF5OiBmdW5jdGlvbiAoYXJyLCBjb3VudHJ5Q29kZSkge1xuXHRcdFx0dmFyIG91dHB1dCA9IFtdO1xuXHRcdFx0Zm9yICh2YXIgaT0wOyBpIDwgYXJyLmxlbmd0aDsgaSsrKXtcblx0XHRcdFx0aWYgKGkgaW4gYXJyKSB7XG5cdFx0XHRcdFx0b3V0cHV0W2ldID0gZ2V0VGV4dC5nZXRGcm9tS2V5KGFycltpXSwgY291bnRyeUNvZGUpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gb3V0cHV0O1xuXHRcdH0sXG5cdFx0YnVpbGRGcm9tRGVmYXVsdDogZnVuY3Rpb24gKGtleSkge1xuXHRcdFx0dmFyIG91dHB1dCwgbGVuZ3RoLCBzcGxpdCwgbGFzdDtcblx0XHRcdHN3aXRjaChrZXkpIHtcblx0XHRcdFx0Y2FzZSBcIm5hbWVcIjpcblx0XHRcdFx0XHRvdXRwdXQgPSBcImVuLVVTXCI7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJlbmdsaXNoTmFtZVwiOlxuXHRcdFx0XHRcdG91dHB1dCA9IFwiRW5nbGlzaCAoVW5pdGVkIFN0YXRlcylcIjtcblx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0Y2FzZSBcIm5hdGl2ZU5hbWVcIjpcblx0XHRcdFx0XHRvdXRwdXQgPSBcIkVuZ2xpc2ggKFVuaXRlZCBTdGF0ZXMpXCI7XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdGNhc2UgXCJ0d29EaWdpdFllYXJNYXhcIjpcblx0XHRcdFx0XHRvdXRwdXQgPSAyMDQ5O1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRjYXNlIFwiZmlyc3REYXlPZldlZWtcIjpcblx0XHRcdFx0XHRvdXRwdXQgPSAwO1xuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRkZWZhdWx0OlxuXHRcdFx0XHRcdG91dHB1dCA9IGtleTtcblx0XHRcdFx0XHRzcGxpdCA9IGtleS5zcGxpdChcIl9cIik7XG5cdFx0XHRcdFx0bGVuZ3RoID0gc3BsaXQubGVuZ3RoO1xuXHRcdFx0XHRcdGlmIChsZW5ndGggPiAxICYmIGtleS5jaGFyQXQoMCkgIT09IFwiL1wiKSB7XG5cdFx0XHRcdFx0XHQvLyBpZiB0aGUga2V5IGlzbid0IGEgcmVnZXggYW5kIGl0IGhhcyBhIHNwbGl0LlxuXHRcdFx0XHRcdFx0bGFzdCA9IHNwbGl0WyhsZW5ndGggLSAxKV0udG9Mb3dlckNhc2UoKTtcblx0XHRcdFx0XHRcdGlmIChsYXN0ID09PSBcImluaXRpYWxcIiB8fCBsYXN0ID09PSBcImFiYnJcIikge1xuXHRcdFx0XHRcdFx0XHRvdXRwdXQgPSBzcGxpdFswXTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gb3V0cHV0O1xuXHRcdH0sXG5cdFx0YnVpbGRGcm9tUmVnZXg6IGZ1bmN0aW9uIChrZXksIGNvdW50cnlDb2RlKSB7XG5cdFx0XHR2YXIgb3V0cHV0O1xuXHRcdFx0aWYgKERhdGUuQ3VsdHVyZVN0cmluZ3MgJiYgRGF0ZS5DdWx0dXJlU3RyaW5nc1tjb3VudHJ5Q29kZV0gJiYgRGF0ZS5DdWx0dXJlU3RyaW5nc1tjb3VudHJ5Q29kZV1ba2V5XSkge1xuXHRcdFx0XHRvdXRwdXQgPSBuZXcgUmVnRXhwKERhdGUuQ3VsdHVyZVN0cmluZ3NbY291bnRyeUNvZGVdW2tleV0sIFwiaVwiKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdG91dHB1dCA9IG5ldyBSZWdFeHAoa2V5LnJlcGxhY2UobmV3IFJlZ0V4cChcIi9cIiwgXCJnXCIpLFwiXCIpLCBcImlcIik7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gb3V0cHV0O1xuXHRcdH1cblx0fTtcblxuXHR2YXIgc2hhbGxvd01lcmdlID0gZnVuY3Rpb24gKG9iajEsIG9iajIpIHtcblx0XHRmb3IgKHZhciBhdHRybmFtZSBpbiBvYmoyKSB7XG5cdFx0XHRpZiAob2JqMi5oYXNPd25Qcm9wZXJ0eShhdHRybmFtZSkpIHtcblx0XHRcdFx0b2JqMVthdHRybmFtZV0gPSBvYmoyW2F0dHJuYW1lXTtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0dmFyIF9fID0gZnVuY3Rpb24gKGtleSwgbGFuZ3VhZ2UpIHtcblx0XHR2YXIgY291bnRyeUNvZGUgPSAobGFuZ3VhZ2UpID8gbGFuZ3VhZ2UgOiBsYW5nO1xuXHRcdGxvZ2dlZEtleXNba2V5XSA9IGtleTtcblx0XHRpZiAodHlwZW9mIGtleSA9PT0gXCJvYmplY3RcIikge1xuXHRcdFx0aWYgKGtleSBpbnN0YW5jZW9mIEFycmF5KSB7XG5cdFx0XHRcdHJldHVybiBnZXRUZXh0LmdldEZyb21BcnJheShrZXksIGNvdW50cnlDb2RlKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiBnZXRUZXh0LmdldEZyb21PYmplY3RLZXlzKGtleSwgY291bnRyeUNvZGUpO1xuXHRcdFx0fVxuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gZ2V0VGV4dC5nZXRGcm9tS2V5KGtleSwgY291bnRyeUNvZGUpO1xuXHRcdH1cblx0fTtcblx0XG5cdHZhciBsb2FkSTE4blNjcmlwdCA9IGZ1bmN0aW9uIChjb2RlKSB7XG5cdFx0Ly8gcGFhdHRlcm5lZCBhZnRlciBqUXVlcnkncyBnZXRTY3JpcHQuXG5cdFx0dmFyIHVybCA9IERhdGUuQ29uZmlnLmkxOG4gKyBjb2RlICsgXCIuanNcIjtcblx0XHR2YXIgaGVhZCA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKFwiaGVhZFwiKVswXSB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG5cdFx0dmFyIHNjcmlwdCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzY3JpcHRcIik7XG5cdFx0c2NyaXB0LnNyYyA9IHVybDtcblxuXHRcdHZhciBjb21wbGV0ZWQgPSBmYWxzZTtcblx0XHR2YXIgZXZlbnRzID0ge1xuXHRcdFx0ZG9uZTogZnVuY3Rpb24gKCl7fSAvLyBwbGFjZWhvbGRlciBmdW5jdGlvblxuXHRcdH07XG5cdFx0Ly8gQXR0YWNoIGhhbmRsZXJzIGZvciBhbGwgYnJvd3NlcnNcblx0XHRzY3JpcHQub25sb2FkID0gc2NyaXB0Lm9ucmVhZHlzdGF0ZWNoYW5nZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0aWYgKCAhY29tcGxldGVkICYmICghdGhpcy5yZWFkeVN0YXRlIHx8IHRoaXMucmVhZHlTdGF0ZSA9PT0gXCJsb2FkZWRcIiB8fCB0aGlzLnJlYWR5U3RhdGUgPT09IFwiY29tcGxldGVcIikgKSB7XG5cdFx0XHRcdGV2ZW50cy5kb25lKCk7XG5cdFx0XHRcdGhlYWQucmVtb3ZlQ2hpbGQoc2NyaXB0KTtcblx0XHRcdH1cblx0XHR9O1xuXG5cdFx0c2V0VGltZW91dChmdW5jdGlvbigpIHtcblx0XHRcdGhlYWQuaW5zZXJ0QmVmb3JlKHNjcmlwdCwgaGVhZC5maXJzdENoaWxkKTtcblx0XHR9LCAwKTsgLy8gYWxsb3dzIHJldHVybiB0byBleGVjdXRlIGZpcnN0XG5cdFx0XG5cdFx0cmV0dXJuIHtcblx0XHRcdGRvbmU6IGZ1bmN0aW9uIChjYikge1xuXHRcdFx0XHRldmVudHMuZG9uZSA9IGZ1bmN0aW9uKCkge1xuXHRcdFx0XHRcdGlmIChjYikge1xuXHRcdFx0XHRcdFx0c2V0VGltZW91dChjYiwwKTtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH07XG5cdFx0XHR9XG5cdFx0fTtcblx0fTtcblxuXHR2YXIgYnVpbGRJbmZvID0ge1xuXHRcdGJ1aWxkRnJvbU1ldGhvZEhhc2g6IGZ1bmN0aW9uIChvYmopIHtcblx0XHRcdHZhciBrZXk7XG5cdFx0XHRmb3Ioa2V5IGluIG9iaikge1xuXHRcdFx0XHRpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkpIHtcblx0XHRcdFx0XHRvYmpba2V5XSA9IGJ1aWxkSW5mb1tvYmpba2V5XV0oKTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIG9iajtcblx0XHR9LFxuXHRcdHRpbWVab25lRFNUOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHR2YXIgRFNUID0ge1xuXHRcdFx0XHRcIkNIQURUXCI6IFwiKzEzNDVcIixcblx0XHRcdFx0XCJOWkRUXCI6IFwiKzEzMDBcIixcblx0XHRcdFx0XCJBRURUXCI6IFwiKzExMDBcIixcblx0XHRcdFx0XCJBQ0RUXCI6IFwiKzEwMzBcIixcblx0XHRcdFx0XCJBWlNUXCI6IFwiKzA1MDBcIixcblx0XHRcdFx0XCJJUkRUXCI6IFwiKzA0MzBcIixcblx0XHRcdFx0XCJFRVNUXCI6IFwiKzAzMDBcIixcblx0XHRcdFx0XCJDRVNUXCI6IFwiKzAyMDBcIixcblx0XHRcdFx0XCJCU1RcIjogXCIrMDEwMFwiLFxuXHRcdFx0XHRcIlBNRFRcIjogXCItMDIwMFwiLFxuXHRcdFx0XHRcIkFEVFwiOiBcIi0wMzAwXCIsXG5cdFx0XHRcdFwiTkRUXCI6IFwiLTAyMzBcIixcblx0XHRcdFx0XCJFRFRcIjogXCItMDQwMFwiLFxuXHRcdFx0XHRcIkNEVFwiOiBcIi0wNTAwXCIsXG5cdFx0XHRcdFwiTURUXCI6IFwiLTA2MDBcIixcblx0XHRcdFx0XCJQRFRcIjogXCItMDcwMFwiLFxuXHRcdFx0XHRcIkFLRFRcIjogXCItMDgwMFwiLFxuXHRcdFx0XHRcIkhBRFRcIjogXCItMDkwMFwiXG5cdFx0XHR9O1xuXHRcdFx0cmV0dXJuIF9fKERTVCk7XG5cdFx0fSxcblx0XHR0aW1lWm9uZVN0YW5kYXJkOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHR2YXIgc3RhbmRhcmQgPSB7XG5cdFx0XHRcdFwiTElOVFwiOiBcIisxNDAwXCIsXG5cdFx0XHRcdFwiVE9UXCI6IFwiKzEzMDBcIixcblx0XHRcdFx0XCJDSEFTVFwiOiBcIisxMjQ1XCIsXG5cdFx0XHRcdFwiTlpTVFwiOiBcIisxMjAwXCIsXG5cdFx0XHRcdFwiTkZUXCI6IFwiKzExMzBcIixcblx0XHRcdFx0XCJTQlRcIjogXCIrMTEwMFwiLFxuXHRcdFx0XHRcIkFFU1RcIjogXCIrMTAwMFwiLFxuXHRcdFx0XHRcIkFDU1RcIjogXCIrMDkzMFwiLFxuXHRcdFx0XHRcIkpTVFwiOiBcIiswOTAwXCIsXG5cdFx0XHRcdFwiQ1dTVFwiOiBcIiswODQ1XCIsXG5cdFx0XHRcdFwiQ1RcIjogXCIrMDgwMFwiLFxuXHRcdFx0XHRcIklDVFwiOiBcIiswNzAwXCIsXG5cdFx0XHRcdFwiTU1UXCI6IFwiKzA2MzBcIixcblx0XHRcdFx0XCJCU1RcIjogXCIrMDYwMFwiLFxuXHRcdFx0XHRcIk5QVFwiOiBcIiswNTQ1XCIsXG5cdFx0XHRcdFwiSVNUXCI6IFwiKzA1MzBcIixcblx0XHRcdFx0XCJQS1RcIjogXCIrMDUwMFwiLFxuXHRcdFx0XHRcIkFGVFwiOiBcIiswNDMwXCIsXG5cdFx0XHRcdFwiTVNLXCI6IFwiKzA0MDBcIixcblx0XHRcdFx0XCJJUlNUXCI6IFwiKzAzMzBcIixcblx0XHRcdFx0XCJGRVRcIjogXCIrMDMwMFwiLFxuXHRcdFx0XHRcIkVFVFwiOiBcIiswMjAwXCIsXG5cdFx0XHRcdFwiQ0VUXCI6IFwiKzAxMDBcIixcblx0XHRcdFx0XCJHTVRcIjogXCIrMDAwMFwiLFxuXHRcdFx0XHRcIlVUQ1wiOiBcIiswMDAwXCIsXG5cdFx0XHRcdFwiQ1ZUXCI6IFwiLTAxMDBcIixcblx0XHRcdFx0XCJHU1RcIjogXCItMDIwMFwiLFxuXHRcdFx0XHRcIkJSVFwiOiBcIi0wMzAwXCIsXG5cdFx0XHRcdFwiTlNUXCI6IFwiLTAzMzBcIixcblx0XHRcdFx0XCJBU1RcIjogXCItMDQwMFwiLFxuXHRcdFx0XHRcIkVTVFwiOiBcIi0wNTAwXCIsXG5cdFx0XHRcdFwiQ1NUXCI6IFwiLTA2MDBcIixcblx0XHRcdFx0XCJNU1RcIjogXCItMDcwMFwiLFxuXHRcdFx0XHRcIlBTVFwiOiBcIi0wODAwXCIsXG5cdFx0XHRcdFwiQUtTVFwiOiBcIi0wOTAwXCIsXG5cdFx0XHRcdFwiTUlUXCI6IFwiLTA5MzBcIixcblx0XHRcdFx0XCJIU1RcIjogXCItMTAwMFwiLFxuXHRcdFx0XHRcIlNTVFwiOiBcIi0xMTAwXCIsXG5cdFx0XHRcdFwiQklUXCI6IFwiLTEyMDBcIlxuXHRcdFx0fTtcblx0XHRcdHJldHVybiBfXyhzdGFuZGFyZCk7XG5cdFx0fSxcblx0XHR0aW1lWm9uZXM6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdFx0XHR2YXIgem9uZTtcblx0XHRcdGRhdGEudGltZXpvbmVzID0gW107XG5cdFx0XHRmb3IgKHpvbmUgaW4gZGF0YS5hYmJyZXZpYXRlZFRpbWVab25lU3RhbmRhcmQpIHtcblx0XHRcdFx0aWYgKGRhdGEuYWJicmV2aWF0ZWRUaW1lWm9uZVN0YW5kYXJkLmhhc093blByb3BlcnR5KHpvbmUpKSB7XG5cdFx0XHRcdFx0ZGF0YS50aW1lem9uZXMucHVzaCh7IG5hbWU6IHpvbmUsIG9mZnNldDogZGF0YS5hYmJyZXZpYXRlZFRpbWVab25lU3RhbmRhcmRbem9uZV19KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0Zm9yICh6b25lIGluIGRhdGEuYWJicmV2aWF0ZWRUaW1lWm9uZURTVCkge1xuXHRcdFx0XHRpZiAoZGF0YS5hYmJyZXZpYXRlZFRpbWVab25lRFNULmhhc093blByb3BlcnR5KHpvbmUpKSB7XG5cdFx0XHRcdFx0ZGF0YS50aW1lem9uZXMucHVzaCh7IG5hbWU6IHpvbmUsIG9mZnNldDogZGF0YS5hYmJyZXZpYXRlZFRpbWVab25lRFNUW3pvbmVdLCBkc3Q6IHRydWV9KTtcblx0XHRcdFx0fVxuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGRhdGEudGltZXpvbmVzO1xuXHRcdH0sXG5cdFx0ZGF5czogZnVuY3Rpb24gKCkge1xuXHRcdFx0cmV0dXJuIF9fKFtcIlN1bmRheVwiLCBcIk1vbmRheVwiLCBcIlR1ZXNkYXlcIiwgXCJXZWRuZXNkYXlcIiwgXCJUaHVyc2RheVwiLCBcIkZyaWRheVwiLCBcIlNhdHVyZGF5XCJdKTtcblx0XHR9LFxuXHRcdGRheUFiYnI6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHJldHVybiBfXyhbXCJTdW5cIiwgXCJNb25cIiwgXCJUdWVcIiwgXCJXZWRcIiwgXCJUaHVcIiwgXCJGcmlcIiwgXCJTYXRcIl0pO1xuXHRcdH0sXG5cdFx0ZGF5U2hvcnROYW1lczogZnVuY3Rpb24gKCkge1xuXHRcdFx0cmV0dXJuIF9fKFtcIlN1XCIsIFwiTW9cIiwgXCJUdVwiLCBcIldlXCIsIFwiVGhcIiwgXCJGclwiLCBcIlNhXCJdKTtcblx0XHR9LFxuXHRcdGRheUZpcnN0TGV0dGVyczogZnVuY3Rpb24gKCkge1xuXHRcdFx0cmV0dXJuIF9fKFtcIlNfU3VuX0luaXRpYWxcIiwgXCJNX01vbl9Jbml0aWFsXCIsIFwiVF9UdWVzX0luaXRpYWxcIiwgXCJXX1dlZF9Jbml0aWFsXCIsIFwiVF9UaHVfSW5pdGlhbFwiLCBcIkZfRnJpX0luaXRpYWxcIiwgXCJTX1NhdF9Jbml0aWFsXCJdKTtcblx0XHR9LFxuXHRcdG1vbnRoczogZnVuY3Rpb24gKCkge1xuXHRcdFx0cmV0dXJuIF9fKFtcIkphbnVhcnlcIiwgXCJGZWJydWFyeVwiLCBcIk1hcmNoXCIsIFwiQXByaWxcIiwgXCJNYXlcIiwgXCJKdW5lXCIsIFwiSnVseVwiLCBcIkF1Z3VzdFwiLCBcIlNlcHRlbWJlclwiLCBcIk9jdG9iZXJcIiwgXCJOb3ZlbWJlclwiLCBcIkRlY2VtYmVyXCJdKTtcblx0XHR9LFxuXHRcdG1vbnRoQWJicjogZnVuY3Rpb24gKCkge1xuXHRcdFx0cmV0dXJuIF9fKFtcIkphbl9BYmJyXCIsIFwiRmViX0FiYnJcIiwgXCJNYXJfQWJiclwiLCBcIkFwcl9BYmJyXCIsIFwiTWF5X0FiYnJcIiwgXCJKdW5fQWJiclwiLCBcIkp1bF9BYmJyXCIsIFwiQXVnX0FiYnJcIiwgXCJTZXBfQWJiclwiLCBcIk9jdF9BYmJyXCIsIFwiTm92X0FiYnJcIiwgXCJEZWNfQWJiclwiXSk7XG5cdFx0fSxcblx0XHRmb3JtYXRQYXR0ZXJuczogZnVuY3Rpb24gKCkge1xuXHRcdFx0cmV0dXJuIGdldFRleHQuZ2V0RnJvbU9iamVjdFZhbHVlcyh7XG5cdFx0XHRcdHNob3J0RGF0ZTogXCJNL2QveXl5eVwiLFxuXHRcdFx0XHRsb25nRGF0ZTogXCJkZGRkLCBNTU1NIGRkLCB5eXl5XCIsXG5cdFx0XHRcdHNob3J0VGltZTogXCJoOm1tIHR0XCIsXG5cdFx0XHRcdGxvbmdUaW1lOiBcImg6bW06c3MgdHRcIixcblx0XHRcdFx0ZnVsbERhdGVUaW1lOiBcImRkZGQsIE1NTU0gZGQsIHl5eXkgaDptbTpzcyB0dFwiLFxuXHRcdFx0XHRzb3J0YWJsZURhdGVUaW1lOiBcInl5eXktTU0tZGRUSEg6bW06c3NcIixcblx0XHRcdFx0dW5pdmVyc2FsU29ydGFibGVEYXRlVGltZTogXCJ5eXl5LU1NLWRkIEhIOm1tOnNzWlwiLFxuXHRcdFx0XHRyZmMxMTIzOiBcImRkZCwgZGQgTU1NIHl5eXkgSEg6bW06c3NcIixcblx0XHRcdFx0bW9udGhEYXk6IFwiTU1NTSBkZFwiLFxuXHRcdFx0XHR5ZWFyTW9udGg6IFwiTU1NTSwgeXl5eVwiXG5cdFx0XHR9LCBEYXRlLmkxOG4uY3VycmVudExhbmd1YWdlKCkpO1xuXHRcdH0sXG5cdFx0cmVnZXg6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHJldHVybiBnZXRUZXh0LmdldEZyb21PYmplY3RWYWx1ZXMoe1xuXHRcdFx0XHRpblRoZU1vcm5pbmc6IFwiLyggaW4gdGhlICkobW9ybihpbmcpPylcXFxcYi9cIixcblx0XHRcdFx0dGhpc01vcm5pbmc6IFwiLyh0aGlzICkobW9ybihpbmcpPylcXFxcYi9cIixcblx0XHRcdFx0YW1UaGlzTW9ybmluZzogXCIvKFxcYlxcXFxkKGFtKT8gKSh0aGlzICkobW9ybihpbmcpPykvXCIsXG5cdFx0XHRcdGluVGhlRXZlbmluZzogXCIvKCBpbiB0aGUgKShldmVuKGluZyk/KVxcXFxiL1wiLFxuXHRcdFx0XHR0aGlzRXZlbmluZzogXCIvKHRoaXMgKShldmVuKGluZyk/KVxcXFxiL1wiLFxuXHRcdFx0XHRwbVRoaXNFdmVuaW5nOiBcIi8oXFxiXFxcXGQocG0pPyApKHRoaXMgKShldmVuKGluZyk/KS9cIixcblx0XHRcdFx0amFuOiBcIi9qYW4odWFyeSk/L1wiLFxuXHRcdFx0XHRmZWI6IFwiL2ZlYihydWFyeSk/L1wiLFxuXHRcdFx0XHRtYXI6IFwiL21hcihjaCk/L1wiLFxuXHRcdFx0XHRhcHI6IFwiL2FwcihpbCk/L1wiLFxuXHRcdFx0XHRtYXk6IFwiL21heS9cIixcblx0XHRcdFx0anVuOiBcIi9qdW4oZSk/L1wiLFxuXHRcdFx0XHRqdWw6IFwiL2p1bCh5KT8vXCIsXG5cdFx0XHRcdGF1ZzogXCIvYXVnKHVzdCk/L1wiLFxuXHRcdFx0XHRzZXA6IFwiL3NlcCh0KGVtYmVyKT8pPy9cIixcblx0XHRcdFx0b2N0OiBcIi9vY3Qob2Jlcik/L1wiLFxuXHRcdFx0XHRub3Y6IFwiL25vdihlbWJlcik/L1wiLFxuXHRcdFx0XHRkZWM6IFwiL2RlYyhlbWJlcik/L1wiLFxuXHRcdFx0XHRzdW46IFwiL15zdShuKGRheSk/KT8vXCIsXG5cdFx0XHRcdG1vbjogXCIvXm1vKG4oZGF5KT8pPy9cIixcblx0XHRcdFx0dHVlOiBcIi9edHUoZShzKGRheSk/KT8pPy9cIixcblx0XHRcdFx0d2VkOiBcIi9ed2UoZChuZXNkYXkpPyk/L1wiLFxuXHRcdFx0XHR0aHU6IFwiL150aCh1KHIocyhkYXkpPyk/KT8pPy9cIixcblx0XHRcdFx0ZnJpOiBcIi9mcihpKGRheSk/KT8vXCIsXG5cdFx0XHRcdHNhdDogXCIvXnNhKHQodXJkYXkpPyk/L1wiLFxuXHRcdFx0XHRmdXR1cmU6IFwiL15uZXh0L1wiLFxuXHRcdFx0XHRwYXN0OiBcIi9ebGFzdHxwYXN0fHByZXYoaW91cyk/L1wiLFxuXHRcdFx0XHRhZGQ6IFwiL14oXFxcXCt8YWZ0KGVyKT98ZnJvbXxoZW5jZSkvXCIsXG5cdFx0XHRcdHN1YnRyYWN0OiBcIi9eKFxcXFwtfGJlZihvcmUpP3xhZ28pL1wiLFxuXHRcdFx0XHR5ZXN0ZXJkYXk6IFwiL155ZXModGVyZGF5KT8vXCIsXG5cdFx0XHRcdHRvZGF5OiBcIi9edChvZChheSk/KT8vXCIsXG5cdFx0XHRcdHRvbW9ycm93OiBcIi9edG9tKG9ycm93KT8vXCIsXG5cdFx0XHRcdG5vdzogXCIvXm4ob3cpPy9cIixcblx0XHRcdFx0bWlsbGlzZWNvbmQ6IFwiL15tc3xtaWxsaShzZWNvbmQpP3M/L1wiLFxuXHRcdFx0XHRzZWNvbmQ6IFwiL15zZWMob25kKT9zPy9cIixcblx0XHRcdFx0bWludXRlOiBcIi9ebW58bWluKHV0ZSk/cz8vXCIsXG5cdFx0XHRcdGhvdXI6IFwiL15oKG91cik/cz8vXCIsXG5cdFx0XHRcdHdlZWs6IFwiL153KGVlayk/cz8vXCIsXG5cdFx0XHRcdG1vbnRoOiBcIi9ebShvbnRoKT9zPy9cIixcblx0XHRcdFx0ZGF5OiBcIi9eZChheSk/cz8vXCIsXG5cdFx0XHRcdHllYXI6IFwiL155KGVhcik/cz8vXCIsXG5cdFx0XHRcdHNob3J0TWVyaWRpYW46IFwiL14oYXxwKS9cIixcblx0XHRcdFx0bG9uZ01lcmlkaWFuOiBcIi9eKGFcXFxcLj9tP1xcXFwuP3xwXFxcXC4/bT9cXFxcLj8pL1wiLFxuXHRcdFx0XHR0aW1lem9uZTogXCIvXigoZShzfGQpdHxjKHN8ZCl0fG0oc3xkKXR8cChzfGQpdCl8KChnbXQpP1xcXFxzKihcXFxcK3xcXFxcLSlcXFxccypcXFxcZFxcXFxkXFxcXGRcXFxcZD8pfGdtdHx1dGMpL1wiLFxuXHRcdFx0XHRvcmRpbmFsU3VmZml4OiBcIi9eXFxcXHMqKHN0fG5kfHJkfHRoKS9cIixcblx0XHRcdFx0dGltZUNvbnRleHQ6IFwiL15cXFxccyooXFxcXDp8YSg/IXV8cCl8cCkvXCJcblx0XHRcdH0sIERhdGUuaTE4bi5jdXJyZW50TGFuZ3VhZ2UoKSk7XG5cdFx0fVxuXHR9O1xuXG5cdHZhciBDdWx0dXJlSW5mbyA9IGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgaW5mbyA9IGdldFRleHQuZ2V0RnJvbU9iamVjdFZhbHVlcyh7XG5cdFx0XHRuYW1lOiBcIm5hbWVcIixcblx0XHRcdGVuZ2xpc2hOYW1lOiBcImVuZ2xpc2hOYW1lXCIsXG5cdFx0XHRuYXRpdmVOYW1lOiBcIm5hdGl2ZU5hbWVcIixcblx0XHRcdGFtRGVzaWduYXRvcjogXCJBTVwiLFxuXHRcdFx0cG1EZXNpZ25hdG9yOiBcIlBNXCIsXG5cdFx0XHRmaXJzdERheU9mV2VlazogXCJmaXJzdERheU9mV2Vla1wiLFxuXHRcdFx0dHdvRGlnaXRZZWFyTWF4OiBcInR3b0RpZ2l0WWVhck1heFwiLFxuXHRcdFx0ZGF0ZUVsZW1lbnRPcmRlcjogXCJtZHlcIlxuXHRcdH0sIERhdGUuaTE4bi5jdXJyZW50TGFuZ3VhZ2UoKSk7XG5cblx0XHR2YXIgY29uc3RydWN0ZWRJbmZvID0gYnVpbGRJbmZvLmJ1aWxkRnJvbU1ldGhvZEhhc2goe1xuXHRcdFx0ZGF5TmFtZXM6IFwiZGF5c1wiLFxuXHRcdFx0YWJicmV2aWF0ZWREYXlOYW1lczogXCJkYXlBYmJyXCIsXG5cdFx0XHRzaG9ydGVzdERheU5hbWVzOiBcImRheVNob3J0TmFtZXNcIixcblx0XHRcdGZpcnN0TGV0dGVyRGF5TmFtZXM6IFwiZGF5Rmlyc3RMZXR0ZXJzXCIsXG5cdFx0XHRtb250aE5hbWVzOiBcIm1vbnRoc1wiLFxuXHRcdFx0YWJicmV2aWF0ZWRNb250aE5hbWVzOiBcIm1vbnRoQWJiclwiLFxuXHRcdFx0Zm9ybWF0UGF0dGVybnM6IFwiZm9ybWF0UGF0dGVybnNcIixcblx0XHRcdHJlZ2V4UGF0dGVybnM6IFwicmVnZXhcIixcblx0XHRcdGFiYnJldmlhdGVkVGltZVpvbmVEU1Q6IFwidGltZVpvbmVEU1RcIixcblx0XHRcdGFiYnJldmlhdGVkVGltZVpvbmVTdGFuZGFyZDogXCJ0aW1lWm9uZVN0YW5kYXJkXCJcblx0XHR9KTtcblxuXHRcdHNoYWxsb3dNZXJnZShpbmZvLCBjb25zdHJ1Y3RlZEluZm8pO1xuXHRcdGJ1aWxkSW5mby50aW1lWm9uZXMoaW5mbyk7XG5cdFx0cmV0dXJuIGluZm87XG5cdH07XG5cblx0JEQuaTE4biA9IHtcblx0XHRfXzogZnVuY3Rpb24gKGtleSwgbGFuZykge1xuXHRcdFx0cmV0dXJuIF9fKGtleSwgbGFuZyk7XG5cdFx0fSxcblx0XHRjdXJyZW50TGFuZ3VhZ2U6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHJldHVybiBsYW5nIHx8IFwiZW4tVVNcIjtcblx0XHR9LFxuXHRcdHNldExhbmd1YWdlOiBmdW5jdGlvbiAoY29kZSwgZm9yY2UsIGNiKSB7XG5cdFx0XHR2YXIgYXN5bmMgPSBmYWxzZTtcblx0XHRcdGlmIChmb3JjZSB8fCBjb2RlID09PSBcImVuLVVTXCIgfHwgKCEhRGF0ZS5DdWx0dXJlU3RyaW5ncyAmJiAhIURhdGUuQ3VsdHVyZVN0cmluZ3NbY29kZV0pKSB7XG5cdFx0XHRcdGxhbmcgPSBjb2RlO1xuXHRcdFx0XHREYXRlLkN1bHR1cmVTdHJpbmdzID0gRGF0ZS5DdWx0dXJlU3RyaW5ncyB8fCB7fTtcblx0XHRcdFx0RGF0ZS5DdWx0dXJlU3RyaW5ncy5sYW5nID0gY29kZTtcblx0XHRcdFx0RGF0ZS5DdWx0dXJlSW5mbyA9IG5ldyBDdWx0dXJlSW5mbygpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0aWYgKCEoISFEYXRlLkN1bHR1cmVTdHJpbmdzICYmICEhRGF0ZS5DdWx0dXJlU3RyaW5nc1tjb2RlXSkpIHtcblx0XHRcdFx0XHRpZiAodHlwZW9mIGV4cG9ydHMgIT09IFwidW5kZWZpbmVkXCIgJiYgdGhpcy5leHBvcnRzICE9PSBleHBvcnRzKSB7XG5cdFx0XHRcdFx0XHQvLyB3ZSdyZSBpbiBhIE5vZGUgZW52aXJvbWVudCwgbG9hZCBpdCB1c2luZyByZXF1aXJlXG5cdFx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0XHRyZXF1aXJlKFwiLi4vaTE4bi9cIiArIGNvZGUgKyBcIi5qc1wiKTtcblx0XHRcdFx0XHRcdFx0bGFuZyA9IGNvZGU7XG5cdFx0XHRcdFx0XHRcdERhdGUuQ3VsdHVyZVN0cmluZ3MubGFuZyA9IGNvZGU7XG5cdFx0XHRcdFx0XHRcdERhdGUuQ3VsdHVyZUluZm8gPSBuZXcgQ3VsdHVyZUluZm8oKTtcblx0XHRcdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRcdFx0Ly8gdmFyIHN0ciA9IFwiVGhlIGxhbmd1YWdlIGZvciAnXCIgKyBjb2RlICsgXCInIGNvdWxkIG5vdCBiZSBsb2FkZWQgYnkgTm9kZS4gSXQgbGlrZWx5IGRvZXMgbm90IGV4aXN0LlwiO1xuXHRcdFx0XHRcdFx0XHR0aHJvdyBuZXcgRXJyb3IoXCJUaGUgRGF0ZUpTIElFVEYgbGFuZ3VhZ2UgdGFnICdcIiArIGNvZGUgKyBcIicgY291bGQgbm90IGJlIGxvYWRlZCBieSBOb2RlLiBJdCBsaWtlbHkgZG9lcyBub3QgZXhpc3QuXCIpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0gZWxzZSBpZiAoRGF0ZS5Db25maWcgJiYgRGF0ZS5Db25maWcuaTE4bikge1xuXHRcdFx0XHRcdFx0Ly8gd2Uga25vdyB0aGUgbG9jYXRpb24gb2YgdGhlIGZpbGVzLCBzbyBsZXRzIGxvYWQgdGhlbVx0XHRcdFx0XHRcblx0XHRcdFx0XHRcdGFzeW5jID0gdHJ1ZTtcblx0XHRcdFx0XHRcdGxvYWRJMThuU2NyaXB0KGNvZGUpLmRvbmUoZnVuY3Rpb24oKXtcblx0XHRcdFx0XHRcdFx0bGFuZyA9IGNvZGU7XG5cdFx0XHRcdFx0XHRcdERhdGUuQ3VsdHVyZVN0cmluZ3MgPSBEYXRlLkN1bHR1cmVTdHJpbmdzIHx8IHt9O1xuXHRcdFx0XHRcdFx0XHREYXRlLkN1bHR1cmVTdHJpbmdzLmxhbmcgPSBjb2RlO1xuXHRcdFx0XHRcdFx0XHREYXRlLkN1bHR1cmVJbmZvID0gbmV3IEN1bHR1cmVJbmZvKCk7XG5cdFx0XHRcdFx0XHRcdCRELlBhcnNpbmcuTm9ybWFsaXplci5idWlsZFJlcGxhY2VEYXRhKCk7IC8vIGJlY2F1c2UgdGhpcyBpcyBhc3luY1xuXHRcdFx0XHRcdFx0XHRpZiAoJEQuR3JhbW1hcikge1xuXHRcdFx0XHRcdFx0XHRcdCRELkdyYW1tYXIuYnVpbGRHcmFtbWFyRm9ybWF0cygpOyAvLyBzbyB3ZSBjYW4gcGFyc2UgdGhvc2Ugc3RyaW5ncy4uLlxuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHRcdGlmIChjYikge1xuXHRcdFx0XHRcdFx0XHRcdHNldFRpbWVvdXQoY2IsMCk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHREYXRlLmNvbnNvbGUuZXJyb3IoXCJUaGUgRGF0ZUpTIElFVEYgbGFuZ3VhZ2UgdGFnICdcIiArIGNvZGUgKyBcIicgaXMgbm90IGF2YWlsYWJsZSBhbmQgaGFzIG5vdCBiZWVuIGxvYWRlZC5cIik7XG5cdFx0XHRcdFx0XHRyZXR1cm4gZmFsc2U7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHQkRC5QYXJzaW5nLk5vcm1hbGl6ZXIuYnVpbGRSZXBsYWNlRGF0YSgpOyAvLyByZWJ1aWxkIG5vcm1hbGl6ZXIgc3RyaW5nc1xuXHRcdFx0aWYgKCRELkdyYW1tYXIpIHtcblx0XHRcdFx0JEQuR3JhbW1hci5idWlsZEdyYW1tYXJGb3JtYXRzKCk7IC8vIHNvIHdlIGNhbiBwYXJzZSB0aG9zZSBzdHJpbmdzLi4uXG5cdFx0XHR9XG5cdFx0XHRpZiAoIWFzeW5jICYmIGNiKSB7XG5cdFx0XHRcdHNldFRpbWVvdXQoY2IsMCk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRnZXRMb2dnZWRLZXlzOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRyZXR1cm4gbG9nZ2VkS2V5cztcblx0XHR9LFxuXHRcdHVwZGF0ZUN1bHR1cmVJbmZvOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHREYXRlLkN1bHR1cmVJbmZvID0gbmV3IEN1bHR1cmVJbmZvKCk7XG5cdFx0fVxuXHR9O1xuXHQkRC5pMThuLnVwZGF0ZUN1bHR1cmVJbmZvKCk7IC8vIHJ1biBhdXRvbWF0aWNhbGx5XG59KCkpOyIsIihmdW5jdGlvbiAoKSB7XHJcblx0dmFyICREID0gRGF0ZTtcclxuXHJcblx0LyoqXHJcblx0ICogQGRlc2MgQ29udmVydHMgdGhlIHNwZWNpZmllZCBzdHJpbmcgdmFsdWUgaW50byBpdHMgSmF2YVNjcmlwdCBEYXRlIGVxdWl2YWxlbnQgdXNpbmcgQ3VsdHVyZUluZm8gc3BlY2lmaWMgZm9ybWF0IGluZm9ybWF0aW9uLlxyXG5cdCAqIFxyXG5cdCAqIEV4YW1wbGVcclxuXHQ8cHJlPjxjb2RlPlxyXG5cdC8vLy8vLy8vLy8vXHJcblx0Ly8gRGF0ZXMgLy9cclxuXHQvLy8vLy8vLy8vL1xyXG5cclxuXHQvLyAxNS1PY3QtMjAwNFxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCIxMC8xNS8yMDA0XCIpO1xyXG5cclxuXHQvLyAxNS1PY3QtMjAwNFxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCIxNS1PY3QtMjAwNFwiKTtcclxuXHJcblx0Ly8gMTUtT2N0LTIwMDRcclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwiMjAwNC4xMC4xNVwiKTtcclxuXHJcblx0Ly9GcmkgT2N0IDE1LCAyMDA0XHJcblx0dmFyIGQxID0gRGF0ZS5wYXJzZShcIkZyaSBPY3QgMTUsIDIwMDRcIik7XHJcblxyXG5cdC8vLy8vLy8vLy8vXHJcblx0Ly8gVGltZXMgLy9cclxuXHQvLy8vLy8vLy8vL1xyXG5cclxuXHQvLyBUb2RheSBhdCAxMCBQTS5cclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwiMTAgUE1cIik7XHJcblxyXG5cdC8vIFRvZGF5IGF0IDEwOjMwIFBNLlxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCIxMDozMCBQLk0uXCIpO1xyXG5cclxuXHQvLyBUb2RheSBhdCA2IEFNLlxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCIwNmFtXCIpO1xyXG5cclxuXHQvLy8vLy8vLy8vLy8vLy8vLy8vLy9cclxuXHQvLyBEYXRlcyBhbmQgVGltZXMgLy9cclxuXHQvLy8vLy8vLy8vLy8vLy8vLy8vLy9cclxuXHJcblx0Ly8gOC1KdWx5LTIwMDQgQCAxMDozMCBQTVxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCJKdWx5IDh0aCwgMjAwNCwgMTA6MzAgUE1cIik7XHJcblxyXG5cdC8vIDEtSnVseS0yMDA0IEAgMTA6MzAgUE1cclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwiMjAwNC0wNy0wMVQyMjozMDowMFwiKTtcclxuXHJcblx0Ly8vLy8vLy8vLy8vLy8vLy8vLy9cclxuXHQvLyBSZWxhdGl2ZSBEYXRlcyAvL1xyXG5cdC8vLy8vLy8vLy8vLy8vLy8vLy8vXHJcblxyXG5cdC8vIFJldHVybnMgdG9kYXkncyBkYXRlLiBUaGUgc3RyaW5nIFwidG9kYXlcIiBpcyBjdWx0dXJlIHNwZWNpZmljLlxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCJ0b2RheVwiKTtcclxuXHJcblx0Ly8gUmV0dXJucyB5ZXN0ZXJkYXkncyBkYXRlLiBUaGUgc3RyaW5nIFwieWVzdGVyZGF5XCIgaXMgY3VsdHVyZSBzcGVjaWZpYy5cclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwieWVzdGVyZGF5XCIpO1xyXG5cclxuXHQvLyBSZXR1cm5zIHRoZSBkYXRlIG9mIHRoZSBuZXh0IHRodXJzZGF5LlxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCJOZXh0IHRodXJzZGF5XCIpO1xyXG5cclxuXHQvLyBSZXR1cm5zIHRoZSBkYXRlIG9mIHRoZSBtb3N0IHByZXZpb3VzIG1vbmRheS5cclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwibGFzdCBtb25kYXlcIik7XHJcblxyXG5cdC8vIFJldHVybnMgdG9kYXkncyBkYXkgKyBvbmUgeWVhci5cclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwibmV4dCB5ZWFyXCIpO1xyXG5cclxuXHQvLy8vLy8vLy8vLy8vLy9cclxuXHQvLyBEYXRlIE1hdGggLy9cclxuXHQvLy8vLy8vLy8vLy8vLy9cclxuXHJcblx0Ly8gVG9kYXkgKyAyIGRheXNcclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwidCsyXCIpO1xyXG5cclxuXHQvLyBUb2RheSArIDIgZGF5c1xyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCJ0b2RheSArIDIgZGF5c1wiKTtcclxuXHJcblx0Ly8gVG9kYXkgKyAzIG1vbnRoc1xyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCJ0KzNtXCIpO1xyXG5cclxuXHQvLyBUb2RheSAtIDEgeWVhclxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCJ0b2RheSAtIDEgeWVhclwiKTtcclxuXHJcblx0Ly8gVG9kYXkgLSAxIHllYXJcclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwidC0xeVwiKTsgXHJcblxyXG5cclxuXHQvLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xyXG5cdC8vIFBhcnRpYWwgRGF0ZXMgYW5kIFRpbWVzIC8vXHJcblx0Ly8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy9cclxuXHJcblx0Ly8gSnVseSAxNXRoIG9mIHRoaXMgeWVhci5cclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwiSnVseSAxNVwiKTtcclxuXHJcblx0Ly8gMTV0aCBkYXkgb2YgY3VycmVudCBkYXkgYW5kIHllYXIuXHJcblx0dmFyIGQxID0gRGF0ZS5wYXJzZShcIjE1XCIpO1xyXG5cclxuXHQvLyBKdWx5IDFzdCBvZiBjdXJyZW50IHllYXIgYXQgMTBwbS5cclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwiNy8xIDEwcG1cIik7XHJcblx0PC9jb2RlPjwvcHJlPlxyXG5cdCAqXHJcblx0ICogQHBhcmFtIHtTdHJpbmd9ICAgVGhlIHN0cmluZyB2YWx1ZSB0byBjb252ZXJ0IGludG8gYSBEYXRlIG9iamVjdCBbUmVxdWlyZWRdXHJcblx0ICogQHJldHVybiB7RGF0ZX0gICAgQSBEYXRlIG9iamVjdCBvciBudWxsIGlmIHRoZSBzdHJpbmcgY2Fubm90IGJlIGNvbnZlcnRlZCBpbnRvIGEgRGF0ZS5cclxuXHQgKi9cclxuXHR2YXIgcGFyc2VVdGlscyA9IHtcclxuXHRcdHJlbW92ZU9yZHM6IGZ1bmN0aW9uIChzKSB7XHJcblx0XHRcdG9yZHMgPSBzLm1hdGNoKC9cXGIoXFxkKykoPzpzdHxuZHxyZHx0aClcXGIvKTsgLy8gZmluZCBvcmRpbmFsIG1hdGNoZXNcclxuXHRcdFx0cyA9ICgob3JkcyAmJiBvcmRzLmxlbmd0aCA9PT0gMikgPyBzLnJlcGxhY2Uob3Jkc1swXSwgb3Jkc1sxXSkgOiBzKTtcclxuXHRcdFx0cmV0dXJuIHM7XHJcblx0XHR9LFxyXG5cdFx0Z3JhbW1hclBhcnNlcjogZnVuY3Rpb24gKHMpIHtcclxuXHRcdFx0dmFyIHIgPSBudWxsO1xyXG5cdFx0XHR0cnkge1xyXG5cdFx0XHRcdHIgPSAkRC5HcmFtbWFyLnN0YXJ0LmNhbGwoe30sIHMucmVwbGFjZSgvXlxccyooXFxTKihcXHMrXFxTKykqKVxccyokLywgXCIkMVwiKSk7XHJcblx0XHRcdH0gY2F0Y2ggKGUpIHtcclxuXHRcdFx0XHRyZXR1cm4gbnVsbDtcclxuXHRcdFx0fVxyXG5cdFx0XHRcclxuXHRcdFx0cmV0dXJuICgoclsxXS5sZW5ndGggPT09IDApID8gclswXSA6IG51bGwpO1xyXG5cdFx0fSxcclxuXHRcdG5hdGl2ZUZhbGxiYWNrOiBmdW5jdGlvbihzKSB7XHJcblx0XHRcdHZhciB0O1xyXG5cdFx0XHR0cnkge1xyXG5cdFx0XHRcdC8vIG9rIHdlIGhhdmVuJ3QgcGFyc2VkIGl0LCBsYXN0IGRpdGNoIGF0dGVtcHQgd2l0aCB0aGUgYnVpbHQtaW4gcGFyc2VyLlxyXG5cdFx0XHRcdHQgPSBEYXRlLl9wYXJzZShzKTtcclxuXHRcdFx0XHRyZXR1cm4gKHQgfHwgdCA9PT0gMCkgPyBuZXcgRGF0ZSh0KSA6IG51bGw7XHJcblx0XHRcdH0gY2F0Y2ggKGUpIHtcclxuXHRcdFx0XHRyZXR1cm4gbnVsbDtcclxuXHRcdFx0fVxyXG5cdFx0fVxyXG5cdH07XHJcblx0ZnVuY3Rpb24gcGFyc2UgKHMpIHtcclxuXHRcdHZhciBkO1xyXG5cdFx0aWYgKCFzKSB7XHJcblx0XHRcdHJldHVybiBudWxsO1xyXG5cdFx0fVxyXG5cdFx0aWYgKHMgaW5zdGFuY2VvZiBEYXRlKSB7XHJcblx0XHRcdHJldHVybiBzLmNsb25lKCk7XHJcblx0XHR9XHJcblx0XHRpZiAocy5sZW5ndGggPj0gNCAmJiBzLmNoYXJBdCgwKSAhPT0gXCIwXCIgJiYgcy5jaGFyQXQoMCkgIT09IFwiK1wiJiYgcy5jaGFyQXQoMCkgIT09IFwiLVwiKSB7IC8vIGllOiAyMDA0IHdpbGwgcGFzcywgMDgwMCB3b24ndC5cclxuXHRcdFx0Ly8gIFN0YXJ0IHdpdGggc3BlY2lmaWMgZm9ybWF0c1xyXG5cdFx0XHRkID0gJEQuUGFyc2luZy5JU08ucGFyc2UocykgfHwgJEQuUGFyc2luZy5OdW1lcmljLnBhcnNlKHMpO1xyXG5cdFx0fVxyXG5cdFx0aWYgKGQgaW5zdGFuY2VvZiBEYXRlICYmICFpc05hTihkLmdldFRpbWUoKSkpIHtcclxuXHRcdFx0cmV0dXJuIGQ7XHJcblx0XHR9IGVsc2Uge1xyXG5cdFx0XHQvLyBmaW5kIG9yZGluYWwgZGF0ZXMgKDFzdCwgM3JkLCA4dGgsIGV0YyBhbmQgcmVtb3ZlIHRoZW0gYXMgdGhleSBjYXVzZSBwYXJzaW5nIGlzc3VlcylcclxuXHRcdFx0cyA9ICRELlBhcnNpbmcuTm9ybWFsaXplci5wYXJzZShwYXJzZVV0aWxzLnJlbW92ZU9yZHMocykpO1xyXG5cdFx0XHRkID0gcGFyc2VVdGlscy5ncmFtbWFyUGFyc2VyKHMpO1xyXG5cdFx0XHRpZiAoZCAhPT0gbnVsbCkge1xyXG5cdFx0XHRcdHJldHVybiBkO1xyXG5cdFx0XHR9IGVsc2Uge1xyXG5cdFx0XHRcdHJldHVybiBwYXJzZVV0aWxzLm5hdGl2ZUZhbGxiYWNrKHMpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0fVxyXG5cclxuXHRpZiAoISRELl9wYXJzZSkge1xyXG5cdFx0JEQuX3BhcnNlID0gJEQucGFyc2U7XHJcblx0fVxyXG5cdCRELnBhcnNlID0gcGFyc2U7XHJcblxyXG5cdERhdGUuZ2V0UGFyc2VGdW5jdGlvbiA9IGZ1bmN0aW9uIChmeCkge1xyXG5cdFx0dmFyIGZucyA9IERhdGUuR3JhbW1hci5hbGxmb3JtYXRzKGZ4KTtcclxuXHRcdHJldHVybiBmdW5jdGlvbiAocykge1xyXG5cdFx0XHR2YXIgciA9IG51bGw7XHJcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgZm5zLmxlbmd0aDsgaSsrKSB7XHJcblx0XHRcdFx0dHJ5IHtcclxuXHRcdFx0XHRcdHIgPSBmbnNbaV0uY2FsbCh7fSwgcyk7XHJcblx0XHRcdFx0fSBjYXRjaCAoZSkge1xyXG5cdFx0XHRcdFx0Y29udGludWU7XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdGlmIChyWzFdLmxlbmd0aCA9PT0gMCkge1xyXG5cdFx0XHRcdFx0cmV0dXJuIHJbMF07XHJcblx0XHRcdFx0fVxyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiBudWxsO1xyXG5cdFx0fTtcclxuXHR9O1xyXG5cdFxyXG5cdC8qKlxyXG5cdCAqIENvbnZlcnRzIHRoZSBzcGVjaWZpZWQgc3RyaW5nIHZhbHVlIGludG8gaXRzIEphdmFTY3JpcHQgRGF0ZSBlcXVpdmFsZW50IHVzaW5nIHRoZSBzcGVjaWZpZWQgZm9ybWF0IHtTdHJpbmd9IG9yIGZvcm1hdHMge0FycmF5fSBhbmQgdGhlIEN1bHR1cmVJbmZvIHNwZWNpZmljIGZvcm1hdCBpbmZvcm1hdGlvbi5cclxuXHQgKiBUaGUgZm9ybWF0IG9mIHRoZSBzdHJpbmcgdmFsdWUgbXVzdCBtYXRjaCBvbmUgb2YgdGhlIHN1cHBsaWVkIGZvcm1hdHMgZXhhY3RseS5cclxuXHQgKiBcclxuXHQgKiBFeGFtcGxlXHJcblx0PHByZT48Y29kZT5cclxuXHQvLyAxNS1PY3QtMjAwNFxyXG5cdHZhciBkMSA9IERhdGUucGFyc2VFeGFjdChcIjEwLzE1LzIwMDRcIiwgXCJNL2QveXl5eVwiKTtcclxuXHJcblx0Ly8gMTUtT2N0LTIwMDRcclxuXHR2YXIgZDEgPSBEYXRlLnBhcnNlKFwiMTUtT2N0LTIwMDRcIiwgXCJNLWRkZC15eXl5XCIpO1xyXG5cclxuXHQvLyAxNS1PY3QtMjAwNFxyXG5cdHZhciBkMSA9IERhdGUucGFyc2UoXCIyMDA0LjEwLjE1XCIsIFwieXl5eS5NTS5kZFwiKTtcclxuXHJcblx0Ly8gTXVsdGlwbGUgZm9ybWF0c1xyXG5cdHZhciBkMSA9IERhdGUucGFyc2VFeGFjdChcIjEwLzE1LzIwMDRcIiwgW1wiTS9kL3l5eXlcIiwgXCJNTU1NIGQsIHl5eXlcIl0pO1xyXG5cdDwvY29kZT48L3ByZT5cclxuXHQgKlxyXG5cdCAqIEBwYXJhbSB7U3RyaW5nfSAgIFRoZSBzdHJpbmcgdmFsdWUgdG8gY29udmVydCBpbnRvIGEgRGF0ZSBvYmplY3QgW1JlcXVpcmVkXS5cclxuXHQgKiBAcGFyYW0ge09iamVjdH0gICBUaGUgZXhwZWN0ZWQgZm9ybWF0IHtTdHJpbmd9IG9yIGFuIGFycmF5IG9mIGV4cGVjdGVkIGZvcm1hdHMge0FycmF5fSBvZiB0aGUgZGF0ZSBzdHJpbmcgW1JlcXVpcmVkXS5cclxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICBBIERhdGUgb2JqZWN0IG9yIG51bGwgaWYgdGhlIHN0cmluZyBjYW5ub3QgYmUgY29udmVydGVkIGludG8gYSBEYXRlLlxyXG5cdCAqL1xyXG5cdCRELnBhcnNlRXhhY3QgPSBmdW5jdGlvbiAocywgZngpIHtcclxuXHRcdHJldHVybiAkRC5nZXRQYXJzZUZ1bmN0aW9uKGZ4KShzKTtcclxuXHR9O1xyXG59KCkpO1xyXG4iLCIoZnVuY3Rpb24gKCkge1xuXHR2YXIgJEQgPSBEYXRlO1xuXHQkRC5HcmFtbWFyID0ge307XG5cdHZhciBfID0gJEQuUGFyc2luZy5PcGVyYXRvcnMsIGcgPSAkRC5HcmFtbWFyLCB0ID0gJEQuVHJhbnNsYXRvciwgX2ZuO1xuXHQvLyBBbGxvdyByb2xsaW5nIHVwIGludG8gZ2VuZXJhbCBwdXJwb3NlIHJ1bGVzXG5cdF9mbiA9IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gXy5lYWNoKF8uYW55LmFwcGx5KG51bGwsIGFyZ3VtZW50cyksIF8ubm90KGcuY3Rva2VuMihcInRpbWVDb250ZXh0XCIpKSk7XG5cdH07XG5cdFxuXHRnLmRhdGVQYXJ0RGVsaW1pdGVyID0gXy5ydG9rZW4oL14oW1xcc1xcLVxcLlxcLFxcL1xceDI3XSspLyk7XG5cdGcudGltZVBhcnREZWxpbWl0ZXIgPSBfLnN0b2tlbihcIjpcIik7XG5cdGcud2hpdGVTcGFjZSA9IF8ucnRva2VuKC9eXFxzKi8pO1xuXHRnLmdlbmVyYWxEZWxpbWl0ZXIgPSBfLnJ0b2tlbigvXigoW1xcc1xcLF18YXR8QHxvbikrKS8pO1xuICBcblx0dmFyIF9DID0ge307XG5cdGcuY3Rva2VuID0gZnVuY3Rpb24gKGtleXMpIHtcblx0XHR2YXIgZm4gPSBfQ1trZXlzXTtcblx0XHRpZiAoISBmbikge1xuXHRcdFx0dmFyIGMgPSBEYXRlLkN1bHR1cmVJbmZvLnJlZ2V4UGF0dGVybnM7XG5cdFx0XHR2YXIga3ggPSBrZXlzLnNwbGl0KC9cXHMrLyksIHB4ID0gW107XG5cdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGt4Lmxlbmd0aCA7IGkrKykge1xuXHRcdFx0XHRweC5wdXNoKF8ucmVwbGFjZShfLnJ0b2tlbihjW2t4W2ldXSksIGt4W2ldKSk7XG5cdFx0XHR9XG5cdFx0XHRmbiA9IF9DW2tleXNdID0gXy5hbnkuYXBwbHkobnVsbCwgcHgpO1xuXHRcdH1cblx0XHRyZXR1cm4gZm47XG5cdH07XG5cdGcuY3Rva2VuMiA9IGZ1bmN0aW9uIChrZXkpIHtcblx0XHRyZXR1cm4gXy5ydG9rZW4oRGF0ZS5DdWx0dXJlSW5mby5yZWdleFBhdHRlcm5zW2tleV0pO1xuXHR9O1xuXHR2YXIgY2FjaGVQcm9jZXNzUnRva2VuID0gZnVuY3Rpb24gKGtleSwgdG9rZW4sIHR5cGUsIGVhY2hUb2tlbikge1xuXHRcdGlmIChlYWNoVG9rZW4pIHtcblx0XHRcdGdba2V5XSA9IF8uY2FjaGUoXy5wcm9jZXNzKF8uZWFjaChfLnJ0b2tlbih0b2tlbiksXy5vcHRpb25hbChnLmN0b2tlbjIoZWFjaFRva2VuKSkpLCB0eXBlKSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdGdba2V5XSA9IF8uY2FjaGUoXy5wcm9jZXNzKF8ucnRva2VuKHRva2VuKSwgdHlwZSkpO1xuXHRcdH1cblx0fTtcblx0dmFyIGNhY2hlUHJvY2Vzc0N0b2tlbiA9IGZ1bmN0aW9uICh0b2tlbiwgdHlwZSkge1xuXHRcdHJldHVybiBfLmNhY2hlKF8ucHJvY2VzcyhnLmN0b2tlbjIodG9rZW4pLCB0eXBlKSk7XG5cdH07XG5cdHZhciBfRiA9IHt9OyAvL2Z1bmN0aW9uIGNhY2hlXG5cblx0dmFyIF9nZXQgPSBmdW5jdGlvbiAoZikge1xuXHRcdF9GW2ZdID0gKF9GW2ZdIHx8IGcuZm9ybWF0KGYpWzBdKTtcblx0XHRyZXR1cm4gX0ZbZl07XG5cdH07XG5cblx0Zy5hbGxmb3JtYXRzID0gZnVuY3Rpb24gKGZ4KSB7XG5cdFx0dmFyIHJ4ID0gW107XG5cdFx0aWYgKGZ4IGluc3RhbmNlb2YgQXJyYXkpIHtcblx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgZngubGVuZ3RoOyBpKyspIHtcblx0XHRcdFx0cngucHVzaChfZ2V0KGZ4W2ldKSk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJ4LnB1c2goX2dldChmeCkpO1xuXHRcdH1cblx0XHRyZXR1cm4gcng7XG5cdH07XG4gIFxuXHRnLmZvcm1hdHMgPSBmdW5jdGlvbiAoZngpIHtcblx0XHRpZiAoZnggaW5zdGFuY2VvZiBBcnJheSkge1xuXHRcdFx0dmFyIHJ4ID0gW107XG5cdFx0XHRmb3IgKHZhciBpID0gMCA7IGkgPCBmeC5sZW5ndGggOyBpKyspIHtcblx0XHRcdFx0cngucHVzaChfZ2V0KGZ4W2ldKSk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gXy5hbnkuYXBwbHkobnVsbCwgcngpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRyZXR1cm4gX2dldChmeCk7XG5cdFx0fVxuXHR9O1xuXG5cdHZhciBncmFtbWFyRm9ybWF0cyA9IHtcblx0XHQgdGltZUZvcm1hdHM6IGZ1bmN0aW9uKCl7XG5cdFx0XHR2YXIgaSxcblx0XHRcdFJUb2tlbktleXMgPSBbXG5cdFx0XHRcdFwiaFwiLFxuXHRcdFx0XHRcImhoXCIsXG5cdFx0XHRcdFwiSFwiLFxuXHRcdFx0XHRcIkhIXCIsXG5cdFx0XHRcdFwibVwiLFxuXHRcdFx0XHRcIm1tXCIsXG5cdFx0XHRcdFwic1wiLFxuXHRcdFx0XHRcInNzXCIsXG5cdFx0XHRcdFwic3Muc1wiLFxuXHRcdFx0XHRcInpcIixcblx0XHRcdFx0XCJ6elwiXG5cdFx0XHRdLFxuXHRcdFx0UlRva2VuID0gW1xuXHRcdFx0XHQvXigwWzAtOV18MVswLTJdfFsxLTldKS8sXG5cdFx0XHRcdC9eKDBbMC05XXwxWzAtMl0pLyxcblx0XHRcdFx0L14oWzAtMV1bMC05XXwyWzAtM118WzAtOV0pLyxcblx0XHRcdFx0L14oWzAtMV1bMC05XXwyWzAtM10pLyxcblx0XHRcdFx0L14oWzAtNV1bMC05XXxbMC05XSkvLFxuXHRcdFx0XHQvXlswLTVdWzAtOV0vLFxuXHRcdFx0XHQvXihbMC01XVswLTldfFswLTldKS8sXG5cdFx0XHRcdC9eWzAtNV1bMC05XS8sXG5cdFx0XHRcdC9eWzAtNV1bMC05XVxcLlswLTldezEsM30vLFxuXHRcdFx0XHQvXigoXFwrfFxcLSlcXHMqXFxkXFxkXFxkXFxkKXwoKFxcK3xcXC0pXFxkXFxkXFw6P1xcZFxcZCkvLFxuXHRcdFx0XHQvXigoXFwrfFxcLSlcXHMqXFxkXFxkXFxkXFxkKXwoKFxcK3xcXC0pXFxkXFxkXFw6P1xcZFxcZCkvXG5cdFx0XHRdLFxuXHRcdFx0dG9rZW5zID0gW1xuXHRcdFx0XHR0LmhvdXIsXG5cdFx0XHRcdHQuaG91cixcblx0XHRcdFx0dC5ob3VyLFxuXHRcdFx0XHR0Lm1pbnV0ZSxcblx0XHRcdFx0dC5taW51dGUsXG5cdFx0XHRcdHQuc2Vjb25kLFxuXHRcdFx0XHR0LnNlY29uZCxcblx0XHRcdFx0dC5zZWNvbmRBbmRNaWxsaXNlY29uZCxcblx0XHRcdFx0dC50aW1lem9uZSxcblx0XHRcdFx0dC50aW1lem9uZSxcblx0XHRcdFx0dC50aW1lem9uZVxuXHRcdFx0XTtcblxuXHRcdFx0Zm9yIChpPTA7IGkgPCBSVG9rZW5LZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGNhY2hlUHJvY2Vzc1J0b2tlbihSVG9rZW5LZXlzW2ldLCBSVG9rZW5baV0sIHRva2Vuc1tpXSk7XG5cdFx0XHR9XG5cblx0XHRcdGcuaG1zID0gXy5jYWNoZShfLnNlcXVlbmNlKFtnLkgsIGcubSwgZy5zXSwgZy50aW1lUGFydERlbGltaXRlcikpO1xuXG5cdFx0XHRnLnQgPSBjYWNoZVByb2Nlc3NDdG9rZW4oXCJzaG9ydE1lcmlkaWFuXCIsIHQubWVyaWRpYW4pO1xuXHRcdFx0Zy50dCA9IGNhY2hlUHJvY2Vzc0N0b2tlbihcImxvbmdNZXJpZGlhblwiLCB0Lm1lcmlkaWFuKTtcblx0XHRcdGcuenp6ID0gY2FjaGVQcm9jZXNzQ3Rva2VuKFwidGltZXpvbmVcIiwgdC50aW1lem9uZSk7XG5cblx0XHRcdGcudGltZVN1ZmZpeCA9IF8uZWFjaChfLmlnbm9yZShnLndoaXRlU3BhY2UpLCBfLnNldChbIGcudHQsIGcuenp6IF0pKTtcblx0XHRcdGcudGltZSA9IF8uZWFjaChfLm9wdGlvbmFsKF8uaWdub3JlKF8uc3Rva2VuKFwiVFwiKSkpLCBnLmhtcywgZy50aW1lU3VmZml4KTtcblx0XHQgfSxcblx0XHQgZGF0ZUZvcm1hdHM6IGZ1bmN0aW9uICgpIHtcblx0XHRcdC8vIHByZS1sb2FkZWQgcnVsZXMgZm9yIGRpZmZlcmVudCBkYXRlIHBhcnQgb3JkZXIgcHJlZmVyZW5jZXNcblx0XHRcdHZhciBfc2V0Zm4gPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHJldHVybiAgXy5zZXQoYXJndW1lbnRzLCBnLmRhdGVQYXJ0RGVsaW1pdGVyKTtcblx0XHRcdH07XG5cdFx0XHR2YXIgaSxcblx0XHRcdFJUb2tlbktleXMgPSBbXG5cdFx0XHRcdFwiZFwiLFxuXHRcdFx0XHRcImRkXCIsXG5cdFx0XHRcdFwiTVwiLFxuXHRcdFx0XHRcIk1NXCIsXG5cdFx0XHRcdFwieVwiLFxuXHRcdFx0XHRcInl5XCIsXG5cdFx0XHRcdFwieXl5XCIsXG5cdFx0XHRcdFwieXl5eVwiXG5cdFx0XHRdLFxuXHRcdFx0UlRva2VuID0gW1xuXHRcdFx0XHQvXihbMC0yXVxcZHwzWzAtMV18XFxkKS8sXG5cdFx0XHRcdC9eKFswLTJdXFxkfDNbMC0xXSkvLFxuXHRcdFx0XHQvXigxWzAtMl18MFxcZHxcXGQpLyxcblx0XHRcdFx0L14oMVswLTJdfDBcXGQpLyxcblx0XHRcdFx0L14oXFxkKykvLFxuXHRcdFx0XHQvXihcXGRcXGQpLyxcblx0XHRcdFx0L14oXFxkXFxkP1xcZD9cXGQ/KS8sXG5cdFx0XHRcdC9eKFxcZFxcZFxcZFxcZCkvXG5cdFx0XHRdLFxuXHRcdFx0dG9rZW5zID0gW1xuXHRcdFx0XHR0LmRheSxcblx0XHRcdFx0dC5kYXksXG5cdFx0XHRcdHQubW9udGgsXG5cdFx0XHRcdHQubW9udGgsXG5cdFx0XHRcdHQueWVhcixcblx0XHRcdFx0dC55ZWFyLFxuXHRcdFx0XHR0LnllYXIsXG5cdFx0XHRcdHQueWVhclxuXHRcdFx0XSxcblx0XHRcdGVhY2hUb2tlbiA9IFtcblx0XHRcdFx0XCJvcmRpbmFsU3VmZml4XCIsXG5cdFx0XHRcdFwib3JkaW5hbFN1ZmZpeFwiXG5cdFx0XHRdO1xuXHRcdFx0Zm9yIChpPTA7IGkgPCBSVG9rZW5LZXlzLmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdGNhY2hlUHJvY2Vzc1J0b2tlbihSVG9rZW5LZXlzW2ldLCBSVG9rZW5baV0sIHRva2Vuc1tpXSwgZWFjaFRva2VuW2ldKTtcblx0XHRcdH1cblxuXHRcdFx0Zy5NTU0gPSBnLk1NTU0gPSBfLmNhY2hlKF8ucHJvY2VzcyhnLmN0b2tlbihcImphbiBmZWIgbWFyIGFwciBtYXkganVuIGp1bCBhdWcgc2VwIG9jdCBub3YgZGVjXCIpLCB0Lm1vbnRoKSk7XG5cdFx0XHRnLmRkZCA9IGcuZGRkZCA9IF8uY2FjaGUoXy5wcm9jZXNzKGcuY3Rva2VuKFwic3VuIG1vbiB0dWUgd2VkIHRodSBmcmkgc2F0XCIpLFxuXHRcdFx0XHRmdW5jdGlvbiAocykge1xuXHRcdFx0XHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHR0aGlzLndlZWtkYXkgPSBzO1xuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblx0XHRcdCkpO1xuXG5cdFx0XHRnLmRheSA9IF9mbihnLmQsIGcuZGQpO1xuXHRcdFx0Zy5tb250aCA9IF9mbihnLk0sIGcuTU1NKTtcblx0XHRcdGcueWVhciA9IF9mbihnLnl5eXksIGcueXkpO1xuXG5cdFx0XHRnLm1keSA9IF9zZXRmbihnLmRkZCwgZy5tb250aCwgZy5kYXksIGcueWVhcik7XG5cdFx0XHRnLnltZCA9IF9zZXRmbihnLmRkZCwgZy55ZWFyLCBnLm1vbnRoLCBnLmRheSk7XG5cdFx0XHRnLmRteSA9IF9zZXRmbihnLmRkZCwgZy5kYXksIGcubW9udGgsIGcueWVhcik7XG5cdFx0XHRcdFx0XHRcblx0XHRcdGcuZGF0ZSA9IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRcdHJldHVybiAoKGdbRGF0ZS5DdWx0dXJlSW5mby5kYXRlRWxlbWVudE9yZGVyXSB8fCBnLm1keSkuY2FsbCh0aGlzLCBzKSk7XG5cdFx0XHR9O1xuXHRcdCB9LFxuXHRcdCByZWxhdGl2ZTogZnVuY3Rpb24gKCkge1xuXHRcdFx0Ly8gcmVsYXRpdmUgZGF0ZSAvIHRpbWUgZXhwcmVzc2lvbnNcblx0XHRcdGcub3JpZW50YXRpb24gPSBfLnByb2Nlc3MoZy5jdG9rZW4oXCJwYXN0IGZ1dHVyZVwiKSxcblx0XHRcdFx0ZnVuY3Rpb24gKHMpIHtcblx0XHRcdFx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdFx0dGhpcy5vcmllbnQgPSBzO1xuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblx0XHRcdCk7XG5cblx0XHRcdGcub3BlcmF0b3IgPSBfLnByb2Nlc3MoZy5jdG9rZW4oXCJhZGQgc3VidHJhY3RcIiksXG5cdFx0XHRcdGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdHRoaXMub3BlcmF0b3IgPSBzO1xuXHRcdFx0XHRcdH07XG5cdFx0XHRcdH1cblx0XHRcdCk7XG5cdFx0XHRnLnJkYXkgPSBfLnByb2Nlc3MoZy5jdG9rZW4oXCJ5ZXN0ZXJkYXkgdG9tb3Jyb3cgdG9kYXkgbm93XCIpLCB0LnJkYXkpO1xuXHRcdFx0Zy51bml0ID0gXy5wcm9jZXNzKGcuY3Rva2VuKFwic2Vjb25kIG1pbnV0ZSBob3VyIGRheSB3ZWVrIG1vbnRoIHllYXJcIiksXG5cdFx0XHRcdGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRcdFx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHRcdHRoaXMudW5pdCA9IHM7XG5cdFx0XHRcdFx0fTtcblx0XHRcdFx0fVxuXHRcdFx0KTtcblx0XHQgfVxuXHR9O1xuXG5cdGcuYnVpbGRHcmFtbWFyRm9ybWF0cyA9IGZ1bmN0aW9uICgpIHtcblx0XHQvLyB0aGVzZSBuZWVkIHRvIGJlIHJlYnVpbHQgZXZlcnkgdGltZSB0aGUgbGFuZ3VhZ2UgY2hhbmdlcy5cblx0XHRfQyA9IHt9O1xuXG5cdFx0Z3JhbW1hckZvcm1hdHMudGltZUZvcm1hdHMoKTtcblx0XHRncmFtbWFyRm9ybWF0cy5kYXRlRm9ybWF0cygpO1xuXHRcdGdyYW1tYXJGb3JtYXRzLnJlbGF0aXZlKCk7XG5cblx0XHRcblx0XHRnLnZhbHVlID0gXy5wcm9jZXNzKF8ucnRva2VuKC9eKFstK10/XFxkKyk/KHN0fG5kfHJkfHRoKT8vKSxcblx0XHRcdGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0dGhpcy52YWx1ZSA9IHMucmVwbGFjZSgvXFxEL2csIFwiXCIpO1xuXHRcdFx0XHR9O1xuXHRcdFx0fVxuXHRcdCk7XG5cdFx0Zy5leHByZXNzaW9uID0gXy5zZXQoW2cucmRheSwgZy5vcGVyYXRvciwgZy52YWx1ZSwgZy51bml0LCBnLm9yaWVudGF0aW9uLCBnLmRkZCwgZy5NTU0gXSk7XG5cblx0XHRnLmZvcm1hdCA9IF8ucHJvY2VzcyhfLm1hbnkoXG5cdFx0XHRfLmFueShcblx0XHRcdFx0Ly8gdHJhbnNsYXRlIGZvcm1hdCBzcGVjaWZpZXJzIGludG8gZ3JhbW1hciBydWxlc1xuXHRcdFx0XHRfLnByb2Nlc3MoXG5cdFx0XHRcdFx0Xy5ydG9rZW4oL14oZGQ/ZD9kPyg/IWUpfE1NP00/TT98eXk/eT95P3xoaD98SEg/fG1tP3xzcz98dHQ/fHp6P3o/KS8pLFxuXHRcdFx0XHRcdFx0ZnVuY3Rpb24gKGZtdCkge1xuXHRcdFx0XHRcdFx0XHRpZiAoZ1tmbXRdKSB7XG5cdFx0XHRcdFx0XHRcdFx0cmV0dXJuIGdbZm10XTtcblx0XHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0XHR0aHJvdyAkRC5QYXJzaW5nLkV4Y2VwdGlvbihmbXQpO1xuXHRcdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0KSxcblx0XHRcdFx0XHQvLyB0cmFuc2xhdGUgc2VwYXJhdG9yIHRva2VucyBpbnRvIHRva2VuIHJ1bGVzXG5cdFx0XHRcdFx0Xy5wcm9jZXNzKF8ucnRva2VuKC9eW15kTXloSG1zdHpdKy8pLCAvLyBhbGwgbGVnYWwgc2VwYXJhdG9ycyBcblx0XHRcdFx0XHRcdGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRcdFx0XHRcdHJldHVybiBfLmlnbm9yZShfLnN0b2tlbihzKSk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0KVxuXHRcdFx0XHQpXG5cdFx0XHQpLFxuXHRcdFx0Ly8gY29uc3RydWN0IHRoZSBwYXJzZXIgLi4uXG5cdFx0XHRmdW5jdGlvbiAocnVsZXMpIHtcblx0XHRcdFx0cmV0dXJuIF8ucHJvY2VzcyhfLmVhY2guYXBwbHkobnVsbCwgcnVsZXMpLCB0LmZpbmlzaEV4YWN0KTtcblx0XHRcdH1cblx0XHQpO1xuXG5cdFx0Ly8gc3RhcnRpbmcgcnVsZSBmb3IgZ2VuZXJhbCBwdXJwb3NlIGdyYW1tYXJcblx0XHRnLl9zdGFydCA9IF8ucHJvY2VzcyhfLnNldChbIGcuZGF0ZSwgZy50aW1lLCBnLmV4cHJlc3Npb24gXSxcblx0XHRnLmdlbmVyYWxEZWxpbWl0ZXIsIGcud2hpdGVTcGFjZSksIHQuZmluaXNoKTtcblx0fTtcblxuXHRnLmJ1aWxkR3JhbW1hckZvcm1hdHMoKTtcblx0Ly8gcGFyc2luZyBkYXRlIGZvcm1hdCBzcGVjaWZpZXJzIC0gZXg6IFwiaDptOnMgdHRcIiBcblx0Ly8gdGhpcyBsaXR0bGUgZ3V5IHdpbGwgZ2VuZXJhdGUgYSBjdXN0b20gcGFyc2VyIGJhc2VkXG5cdC8vIG9uIHRoZSBmb3JtYXQgc3RyaW5nLCBleDogZy5mb3JtYXQoXCJoOm06cyB0dFwiKVxuXHQvLyBjaGVjayBmb3IgdGhlc2UgZm9ybWF0cyBmaXJzdFxuXHRnLl9mb3JtYXRzID0gZy5mb3JtYXRzKFtcblx0XHRcIlxcXCJ5eXl5LU1NLWRkVEhIOm1tOnNzWlxcXCJcIixcblx0XHRcInl5eXktTU0tZGRUSEg6bW06c3Muc3pcIixcblx0XHRcInl5eXktTU0tZGRUSEg6bW06c3NaXCIsXG5cdFx0XCJ5eXl5LU1NLWRkVEhIOm1tOnNzelwiLFxuXHRcdFwieXl5eS1NTS1kZFRISDptbTpzc1wiLFxuXHRcdFwieXl5eS1NTS1kZFRISDptbVpcIixcblx0XHRcInl5eXktTU0tZGRUSEg6bW16XCIsXG5cdFx0XCJ5eXl5LU1NLWRkVEhIOm1tXCIsXG5cdFx0XCJkZGQsIE1NTSBkZCwgeXl5eSBIOm1tOnNzIHR0XCIsXG5cdFx0XCJkZGQgTU1NIGQgeXl5eSBISDptbTpzcyB6enpcIixcblx0XHRcIk1NZGR5eXl5XCIsXG5cdFx0XCJkZE1NeXl5eVwiLFxuXHRcdFwiTWRkeXl5eVwiLFxuXHRcdFwiZGRNeXl5eVwiLFxuXHRcdFwiTWR5eXl5XCIsXG5cdFx0XCJkTXl5eXlcIixcblx0XHRcInl5eXlcIixcblx0XHRcIk1keXlcIixcblx0XHRcImRNeXlcIixcblx0XHRcImRcIlxuXHRdKTtcblx0XG5cdC8vIHJlYWwgc3RhcnRpbmcgcnVsZTogdHJpZXMgc2VsZWN0ZWQgZm9ybWF0cyBmaXJzdCwgXG5cdC8vIHRoZW4gZ2VuZXJhbCBwdXJwb3NlIHJ1bGVcblx0Zy5zdGFydCA9IGZ1bmN0aW9uIChzKSB7XG5cdFx0dHJ5IHtcblx0XHRcdHZhciByID0gZy5fZm9ybWF0cy5jYWxsKHt9LCBzKTtcblx0XHRcdGlmIChyWzFdLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0XHRyZXR1cm4gcjtcblx0XHRcdH1cblx0XHR9IGNhdGNoIChlKSB7fVxuXHRcdHJldHVybiBnLl9zdGFydC5jYWxsKHt9LCBzKTtcblx0fTtcbn0oKSk7IiwiKGZ1bmN0aW9uICgpIHtcblx0dmFyICRQID0gRGF0ZS5QYXJzaW5nO1xuXHR2YXIgXyA9ICRQLk9wZXJhdG9ycyA9IHtcblx0XHQvL1xuXHRcdC8vIFRva2VuaXplcnNcblx0XHQvL1xuXHRcdHJ0b2tlbjogZnVuY3Rpb24gKHIpIHsgLy8gcmVnZXggdG9rZW5cblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHR2YXIgbXggPSBzLm1hdGNoKHIpO1xuXHRcdFx0XHRpZiAobXgpIHtcblx0XHRcdFx0XHRyZXR1cm4gKFsgbXhbMF0sIHMuc3Vic3RyaW5nKG14WzBdLmxlbmd0aCkgXSk7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhyb3cgbmV3ICRQLkV4Y2VwdGlvbihzKTtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHR9LFxuXHRcdHRva2VuOiBmdW5jdGlvbiAoKSB7IC8vIHdoaXRlc3BhY2UtZWF0aW5nIHRva2VuXG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKHMpIHtcblx0XHRcdFx0cmV0dXJuIF8ucnRva2VuKG5ldyBSZWdFeHAoXCJeXFxcXHMqXCIgKyBzICsgXCJcXFxccypcIikpKHMpO1xuXHRcdFx0fTtcblx0XHR9LFxuXHRcdHN0b2tlbjogZnVuY3Rpb24gKHMpIHsgLy8gc3RyaW5nIHRva2VuXG5cdFx0XHRyZXR1cm4gXy5ydG9rZW4obmV3IFJlZ0V4cChcIl5cIiArIHMpKTtcblx0XHR9LFxuXG5cdFx0Ly8gQXRvbWljIE9wZXJhdG9yc1xuXG5cdFx0dW50aWw6IGZ1bmN0aW9uIChwKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKHMpIHtcblx0XHRcdFx0dmFyIHF4ID0gW10sIHJ4ID0gbnVsbDtcblx0XHRcdFx0d2hpbGUgKHMubGVuZ3RoKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHJ4ID0gcC5jYWxsKHRoaXMsIHMpO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRcdHF4LnB1c2gocnhbMF0pO1xuXHRcdFx0XHRcdFx0cyA9IHJ4WzFdO1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBbIHF4LCBzIF07XG5cdFx0XHR9O1xuXHRcdH0sXG5cdFx0bWFueTogZnVuY3Rpb24gKHApIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHR2YXIgcnggPSBbXSwgciA9IG51bGw7XG5cdFx0XHRcdHdoaWxlIChzLmxlbmd0aCkge1xuXHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRyID0gcC5jYWxsKHRoaXMsIHMpO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRcdHJldHVybiBbIHJ4LCBzIF07XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdHJ4LnB1c2goclswXSk7XG5cdFx0XHRcdFx0cyA9IHJbMV07XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIFsgcngsIHMgXTtcblx0XHRcdH07XG5cdFx0fSxcblxuXHRcdC8vIGdlbmVyYXRvciBvcGVyYXRvcnMgLS0gc2VlIGJlbG93XG5cdFx0b3B0aW9uYWw6IGZ1bmN0aW9uIChwKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKHMpIHtcblx0XHRcdFx0dmFyIHIgPSBudWxsO1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdHIgPSBwLmNhbGwodGhpcywgcyk7XG5cdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRyZXR1cm4gWyBudWxsLCBzIF07XG5cdFx0XHRcdH1cblx0XHRcdFx0cmV0dXJuIFsgclswXSwgclsxXSBdO1xuXHRcdFx0fTtcblx0XHR9LFxuXHRcdG5vdDogZnVuY3Rpb24gKHApIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdHAuY2FsbCh0aGlzLCBzKTtcblx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdHJldHVybiBbbnVsbCwgc107XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhyb3cgbmV3ICRQLkV4Y2VwdGlvbihzKTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHRpZ25vcmU6IGZ1bmN0aW9uIChwKSB7XG5cdFx0XHRyZXR1cm4gcCA/XG5cdFx0XHRmdW5jdGlvbiAocykge1xuXHRcdFx0XHR2YXIgciA9IG51bGw7XG5cdFx0XHRcdHIgPSBwLmNhbGwodGhpcywgcyk7XG5cdFx0XHRcdHJldHVybiBbbnVsbCwgclsxXV07XG5cdFx0XHR9IDogbnVsbDtcblx0XHR9LFxuXHRcdHByb2R1Y3Q6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciBweCA9IGFyZ3VtZW50c1swXSxcblx0XHRcdHF4ID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAxKSwgcnggPSBbXTtcblx0XHRcdGZvciAodmFyIGkgPSAwIDsgaSA8IHB4Lmxlbmd0aCA7IGkrKykge1xuXHRcdFx0XHRyeC5wdXNoKF8uZWFjaChweFtpXSwgcXgpKTtcblx0XHRcdH1cblx0XHRcdHJldHVybiByeDtcblx0XHR9LFxuXHRcdGNhY2hlOiBmdW5jdGlvbiAocnVsZSkge1xuXHRcdFx0dmFyIGNhY2hlID0ge30sIGNhY2hlX2xlbmd0aCA9IDAsIGNhY2hlX2tleXMgPSBbXSwgQ0FDSEVfTUFYID0gRGF0ZS5Db25maWcuQ0FDSEVfTUFYIHx8IDEwMDAwMCwgciA9IG51bGw7XG5cdFx0XHR2YXIgY2FjaGVDaGVjayA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0aWYgKGNhY2hlX2xlbmd0aCA9PT0gQ0FDSEVfTUFYKSB7XG5cdFx0XHRcdFx0Ly8ga2lsbCBzZXZlcmFsIGtleXMsIGRvbid0IHdhbnQgdG8gaGF2ZSB0byBkbyB0aGlzIGFsbCB0aGUgdGltZS4uLlxuXHRcdFx0XHRcdGZvciAodmFyIGk9MDsgaSA8IDEwOyBpKyspIHtcblx0XHRcdFx0XHRcdHZhciBrZXkgPSBjYWNoZV9rZXlzLnNoaWZ0KCk7XG5cdFx0XHRcdFx0XHRpZiAoa2V5KSB7XG5cdFx0XHRcdFx0XHRcdGRlbGV0ZSBjYWNoZVtrZXldO1xuXHRcdFx0XHRcdFx0XHRjYWNoZV9sZW5ndGgtLTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKHMpIHtcblx0XHRcdFx0Y2FjaGVDaGVjaygpO1xuXHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdHIgPSBjYWNoZVtzXSA9IChjYWNoZVtzXSB8fCBydWxlLmNhbGwodGhpcywgcykpO1xuXHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0ciA9IGNhY2hlW3NdID0gZTtcblx0XHRcdFx0fVxuXHRcdFx0XHRjYWNoZV9sZW5ndGgrKztcblx0XHRcdFx0Y2FjaGVfa2V5cy5wdXNoKHMpO1xuXHRcdFx0XHRpZiAociBpbnN0YW5jZW9mICRQLkV4Y2VwdGlvbikge1xuXHRcdFx0XHRcdHRocm93IHI7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0cmV0dXJuIHI7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fSxcblxuXHRcdC8vIHZlY3RvciBvcGVyYXRvcnMgLS0gc2VlIGJlbG93XG5cdFx0YW55OiBmdW5jdGlvbiAoKSB7XG5cdFx0XHR2YXIgcHggPSBhcmd1bWVudHM7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKHMpIHtcblx0XHRcdFx0dmFyIHIgPSBudWxsO1xuXHRcdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHB4Lmxlbmd0aDsgaSsrKSB7XG5cdFx0XHRcdFx0aWYgKHB4W2ldID09IG51bGwpIHtcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0ciA9IChweFtpXS5jYWxsKHRoaXMsIHMpKTtcblx0XHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0XHRyID0gbnVsbDtcblx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0aWYgKHIpIHtcblx0XHRcdFx0XHRcdHJldHVybiByO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHR0aHJvdyBuZXcgJFAuRXhjZXB0aW9uKHMpO1xuXHRcdFx0fTtcblx0XHR9LFxuXHRcdGVhY2g6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciBweCA9IGFyZ3VtZW50cztcblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHR2YXIgcnggPSBbXSwgciA9IG51bGw7XG5cdFx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcHgubGVuZ3RoIDsgaSsrKSB7XG5cdFx0XHRcdFx0aWYgKHB4W2ldID09IG51bGwpIHtcblx0XHRcdFx0XHRcdGNvbnRpbnVlO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0ciA9IChweFtpXS5jYWxsKHRoaXMsIHMpKTtcblx0XHRcdFx0XHR9IGNhdGNoIChlKSB7XG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgJFAuRXhjZXB0aW9uKHMpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyeC5wdXNoKHJbMF0pO1xuXHRcdFx0XHRcdHMgPSByWzFdO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiBbIHJ4LCBzXTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHRhbGw6IGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciBweCA9IGFyZ3VtZW50cywgXyA9IF87XG5cdFx0XHRyZXR1cm4gXy5lYWNoKF8ub3B0aW9uYWwocHgpKTtcblx0XHR9LFxuXG5cdFx0Ly8gZGVsaW1pdGVkIG9wZXJhdG9yc1xuXHRcdHNlcXVlbmNlOiBmdW5jdGlvbiAocHgsIGQsIGMpIHtcblx0XHRcdGQgPSBkIHx8IF8ucnRva2VuKC9eXFxzKi8pO1xuXHRcdFx0YyA9IGMgfHwgbnVsbDtcblx0XHRcdFxuXHRcdFx0aWYgKHB4Lmxlbmd0aCA9PT0gMSkge1xuXHRcdFx0XHRyZXR1cm4gcHhbMF07XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKHMpIHtcblx0XHRcdFx0dmFyIHIgPSBudWxsLCBxID0gbnVsbDtcblx0XHRcdFx0dmFyIHJ4ID0gW107XG5cdFx0XHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcHgubGVuZ3RoIDsgaSsrKSB7XG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHIgPSBweFtpXS5jYWxsKHRoaXMsIHMpO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKGUpIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRyeC5wdXNoKHJbMF0pO1xuXHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRxID0gZC5jYWxsKHRoaXMsIHJbMV0pO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKGV4KSB7XG5cdFx0XHRcdFx0XHRxID0gbnVsbDtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0XHRzID0gcVsxXTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoIXIpIHtcblx0XHRcdFx0XHR0aHJvdyBuZXcgJFAuRXhjZXB0aW9uKHMpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChxKSB7XG5cdFx0XHRcdFx0dGhyb3cgbmV3ICRQLkV4Y2VwdGlvbihxWzFdKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRpZiAoYykge1xuXHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRyID0gYy5jYWxsKHRoaXMsIHJbMV0pO1xuXHRcdFx0XHRcdH0gY2F0Y2ggKGV5KSB7XG5cdFx0XHRcdFx0XHR0aHJvdyBuZXcgJFAuRXhjZXB0aW9uKHJbMV0pO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHRyZXR1cm4gWyByeCwgKHI/clsxXTpzKSBdO1xuXHRcdFx0fTtcblx0XHR9LFxuXG5cdFx0Ly9cblx0XHQvLyBDb21wb3NpdGUgT3BlcmF0b3JzXG5cdFx0Ly9cblxuXHRcdGJldHdlZW46IGZ1bmN0aW9uIChkMSwgcCwgZDIpIHtcblx0XHRcdGQyID0gZDIgfHwgZDE7XG5cdFx0XHR2YXIgX2ZuID0gXy5lYWNoKF8uaWdub3JlKGQxKSwgcCwgXy5pZ25vcmUoZDIpKTtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHR2YXIgcnggPSBfZm4uY2FsbCh0aGlzLCBzKTtcblx0XHRcdFx0cmV0dXJuIFtbcnhbMF1bMF0sIHJbMF1bMl1dLCByeFsxXV07XG5cdFx0XHR9O1xuXHRcdH0sXG5cdFx0bGlzdDogZnVuY3Rpb24gKHAsIGQsIGMpIHtcblx0XHRcdGQgPSBkIHx8IF8ucnRva2VuKC9eXFxzKi8pO1xuXHRcdFx0YyA9IGMgfHwgbnVsbDtcblx0XHRcdHJldHVybiAocCBpbnN0YW5jZW9mIEFycmF5ID9cblx0XHRcdFx0Xy5lYWNoKF8ucHJvZHVjdChwLnNsaWNlKDAsIC0xKSwgXy5pZ25vcmUoZCkpLCBwLnNsaWNlKC0xKSwgXy5pZ25vcmUoYykpIDpcblx0XHRcdFx0Xy5lYWNoKF8ubWFueShfLmVhY2gocCwgXy5pZ25vcmUoZCkpKSwgcHgsIF8uaWdub3JlKGMpKSk7XG5cdFx0fSxcblx0XHRzZXQ6IGZ1bmN0aW9uIChweCwgZCwgYykge1xuXHRcdFx0ZCA9IGQgfHwgXy5ydG9rZW4oL15cXHMqLyk7XG5cdFx0XHRjID0gYyB8fCBudWxsO1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRcdC8vIHIgaXMgdGhlIGN1cnJlbnQgbWF0Y2gsIGJlc3QgdGhlIGN1cnJlbnQgJ2Jlc3QnIG1hdGNoXG5cdFx0XHRcdC8vIHdoaWNoIG1lYW5zIGl0IHBhcnNlZCB0aGUgbW9zdCBhbW91bnQgb2YgaW5wdXRcblx0XHRcdFx0dmFyIHIgPSBudWxsLCBwID0gbnVsbCwgcSA9IG51bGwsIHJ4ID0gbnVsbCwgYmVzdCA9IFtbXSwgc10sIGxhc3QgPSBmYWxzZTtcblx0XHRcdFx0Ly8gZ28gdGhyb3VnaCB0aGUgcnVsZXMgaW4gdGhlIGdpdmVuIHNldFxuXHRcdFx0XHRmb3IgKHZhciBpID0gMDsgaSA8IHB4Lmxlbmd0aCA7IGkrKykge1xuXG5cdFx0XHRcdFx0Ly8gbGFzdCBpcyBhIGZsYWcgaW5kaWNhdGluZyB3aGV0aGVyIHRoaXMgbXVzdCBiZSB0aGUgbGFzdCBlbGVtZW50XG5cdFx0XHRcdFx0Ly8gaWYgdGhlcmUgaXMgb25seSAxIGVsZW1lbnQsIHRoZW4gaXQgTVVTVCBiZSB0aGUgbGFzdCBvbmVcblx0XHRcdFx0XHRxID0gbnVsbDtcblx0XHRcdFx0XHRwID0gbnVsbDtcblx0XHRcdFx0XHRyID0gbnVsbDtcblx0XHRcdFx0XHRsYXN0ID0gKHB4Lmxlbmd0aCA9PT0gMSk7XG5cdFx0XHRcdFx0Ly8gZmlyc3QsIHdlIHRyeSBzaW1wbHkgdG8gbWF0Y2ggdGhlIGN1cnJlbnQgcGF0dGVyblxuXHRcdFx0XHRcdC8vIGlmIG5vdCwgdHJ5IHRoZSBuZXh0IHBhdHRlcm5cblx0XHRcdFx0XHR0cnkge1xuXHRcdFx0XHRcdFx0ciA9IHB4W2ldLmNhbGwodGhpcywgcyk7XG5cdFx0XHRcdFx0fSBjYXRjaCAoZSkge1xuXHRcdFx0XHRcdFx0Y29udGludWU7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHRcdC8vIHNpbmNlIHdlIGFyZSBtYXRjaGluZyBhZ2FpbnN0IGEgc2V0IG9mIGVsZW1lbnRzLCB0aGUgZmlyc3Rcblx0XHRcdFx0XHQvLyB0aGluZyB0byBkbyBpcyB0byBhZGQgclswXSB0byBtYXRjaGVkIGVsZW1lbnRzXG5cdFx0XHRcdFx0cnggPSBbW3JbMF1dLCByWzFdXTtcblx0XHRcdFx0XHQvLyBpZiB3ZSBtYXRjaGVkIGFuZCB0aGVyZSBpcyBzdGlsbCBpbnB1dCB0byBwYXJzZSBhbmQgXG5cdFx0XHRcdFx0Ly8gd2UgZG9uJ3QgYWxyZWFkeSBrbm93IHRoaXMgaXMgdGhlIGxhc3QgZWxlbWVudCxcblx0XHRcdFx0XHQvLyB3ZSdyZSBnb2luZyB0byBuZXh0IGNoZWNrIGZvciB0aGUgZGVsaW1pdGVyIC4uLlxuXHRcdFx0XHRcdC8vIGlmIHRoZXJlJ3Mgbm9uZSwgb3IgaWYgdGhlcmUncyBubyBpbnB1dCBsZWZ0IHRvIHBhcnNlXG5cdFx0XHRcdFx0Ly8gdGhhbiB0aGlzIG11c3QgYmUgdGhlIGxhc3QgZWxlbWVudCBhZnRlciBhbGwgLi4uXG5cdFx0XHRcdFx0aWYgKHJbMV0ubGVuZ3RoID4gMCAmJiAhIGxhc3QpIHtcblx0XHRcdFx0XHRcdHRyeSB7XG5cdFx0XHRcdFx0XHRcdHEgPSBkLmNhbGwodGhpcywgclsxXSk7XG5cdFx0XHRcdFx0XHR9IGNhdGNoIChleCkge1xuXHRcdFx0XHRcdFx0XHRsYXN0ID0gdHJ1ZTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0bGFzdCA9IHRydWU7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gaWYgd2UgcGFyc2VkIHRoZSBkZWxpbWl0ZXIgYW5kIG5vdyB0aGVyZSdzIG5vIG1vcmUgaW5wdXQsXG5cdFx0XHRcdFx0Ly8gdGhhdCBtZWFucyB3ZSBzaG91bGRuJ3QgaGF2ZSBwYXJzZWQgdGhlIGRlbGltaXRlciBhdCBhbGxcblx0XHRcdFx0XHQvLyBzbyBkb24ndCB1cGRhdGUgciBhbmQgbWFyayB0aGlzIGFzIHRoZSBsYXN0IGVsZW1lbnQgLi4uXG5cdFx0XHRcdFx0aWYgKCFsYXN0ICYmIHFbMV0ubGVuZ3RoID09PSAwKSB7XG5cdFx0XHRcdFx0XHRsYXN0ID0gdHJ1ZTtcblx0XHRcdFx0XHR9XG5cblxuXHRcdFx0XHRcdC8vIHNvLCBpZiB0aGlzIGlzbid0IHRoZSBsYXN0IGVsZW1lbnQsIHdlJ3JlIGdvaW5nIHRvIHNlZSBpZlxuXHRcdFx0XHRcdC8vIHdlIGNhbiBnZXQgYW55IG1vcmUgbWF0Y2hlcyBmcm9tIHRoZSByZW1haW5pbmcgKHVubWF0Y2hlZClcblx0XHRcdFx0XHQvLyBlbGVtZW50cyAuLi5cblx0XHRcdFx0XHRpZiAoIWxhc3QpIHtcblx0XHRcdFx0XHRcdC8vIGJ1aWxkIGEgbGlzdCBvZiB0aGUgcmVtYWluaW5nIHJ1bGVzIHdlIGNhbiBtYXRjaCBhZ2FpbnN0LFxuXHRcdFx0XHRcdFx0Ly8gaS5lLiwgYWxsIGJ1dCB0aGUgb25lIHdlIGp1c3QgbWF0Y2hlZCBhZ2FpbnN0XG5cdFx0XHRcdFx0XHR2YXIgcXggPSBbXTtcblx0XHRcdFx0XHRcdGZvciAodmFyIGogPSAwOyBqIDwgcHgubGVuZ3RoIDsgaisrKSB7XG5cdFx0XHRcdFx0XHRcdGlmIChpICE9PSBqKSB7XG5cdFx0XHRcdFx0XHRcdFx0cXgucHVzaChweFtqXSk7XG5cdFx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0Ly8gbm93IGludm9rZSByZWN1cnNpdmVseSBzZXQgd2l0aCB0aGUgcmVtYWluaW5nIGlucHV0XG5cdFx0XHRcdFx0XHQvLyBub3RlIHRoYXQgd2UgZG9uJ3QgaW5jbHVkZSB0aGUgY2xvc2luZyBkZWxpbWl0ZXIgLi4uXG5cdFx0XHRcdFx0XHQvLyB3ZSdsbCBjaGVjayBmb3IgdGhhdCBvdXJzZWx2ZXMgYXQgdGhlIGVuZFxuXHRcdFx0XHRcdFx0cCA9IF8uc2V0KHF4LCBkKS5jYWxsKHRoaXMsIHFbMV0pO1xuXG5cdFx0XHRcdFx0XHQvLyBpZiB3ZSBnb3QgYSBub24tZW1wdHkgc2V0IGFzIGEgcmVzdWx0IC4uLlxuXHRcdFx0XHRcdFx0Ly8gKG90dyByeCBhbHJlYWR5IGNvbnRhaW5zIGV2ZXJ5dGhpbmcgd2Ugd2FudCB0byBtYXRjaClcblx0XHRcdFx0XHRcdGlmIChwWzBdLmxlbmd0aCA+IDApIHtcblx0XHRcdFx0XHRcdFx0Ly8gdXBkYXRlIGN1cnJlbnQgcmVzdWx0LCB3aGljaCBpcyBzdG9yZWQgaW4gcnggLi4uXG5cdFx0XHRcdFx0XHRcdC8vIGJhc2ljYWxseSwgcGljayB1cCB0aGUgcmVtYWluaW5nIHRleHQgZnJvbSBwWzFdXG5cdFx0XHRcdFx0XHRcdC8vIGFuZCBjb25jYXQgdGhlIHJlc3VsdCBmcm9tIHBbMF0gc28gdGhhdCB3ZSBkb24ndFxuXHRcdFx0XHRcdFx0XHQvLyBnZXQgZW5kbGVzcyBuZXN0aW5nIC4uLlxuXHRcdFx0XHRcdFx0XHRyeFswXSA9IHJ4WzBdLmNvbmNhdChwWzBdKTtcblx0XHRcdFx0XHRcdFx0cnhbMV0gPSBwWzFdO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdC8vIGF0IHRoaXMgcG9pbnQsIHJ4IGVpdGhlciBjb250YWlucyB0aGUgbGFzdCBtYXRjaGVkIGVsZW1lbnRcblx0XHRcdFx0XHQvLyBvciB0aGUgZW50aXJlIG1hdGNoZWQgc2V0IHRoYXQgc3RhcnRzIHdpdGggdGhpcyBlbGVtZW50LlxuXG5cdFx0XHRcdFx0Ly8gbm93IHdlIGp1c3QgY2hlY2sgdG8gc2VlIGlmIHRoaXMgdmFyaWF0aW9uIGlzIGJldHRlciB0aGFuXG5cdFx0XHRcdFx0Ly8gb3VyIGJlc3Qgc28gZmFyLCBpbiB0ZXJtcyBvZiBob3cgbXVjaCBvZiB0aGUgaW5wdXQgaXMgcGFyc2VkXG5cdFx0XHRcdFx0aWYgKHJ4WzFdLmxlbmd0aCA8IGJlc3RbMV0ubGVuZ3RoKSB7XG5cdFx0XHRcdFx0XHRiZXN0ID0gcng7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gaWYgd2UndmUgcGFyc2VkIGFsbCB0aGUgaW5wdXQsIHRoZW4gd2UncmUgZmluaXNoZWRcblx0XHRcdFx0XHRpZiAoYmVzdFsxXS5sZW5ndGggPT09IDApIHtcblx0XHRcdFx0XHRcdGJyZWFrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIHNvIG5vdyB3ZSd2ZSBlaXRoZXIgZ29uZSB0aHJvdWdoIGFsbCB0aGUgcGF0dGVybnMgdHJ5aW5nIHRoZW1cblx0XHRcdFx0Ly8gYXMgdGhlIGluaXRpYWwgbWF0Y2g7IG9yIHdlIGZvdW5kIG9uZSB0aGF0IHBhcnNlZCB0aGUgZW50aXJlXG5cdFx0XHRcdC8vIGlucHV0IHN0cmluZyAuLi5cblxuXHRcdFx0XHQvLyBpZiBiZXN0IGhhcyBubyBtYXRjaGVzLCBqdXN0IHJldHVybiBlbXB0eSBzZXQgLi4uXG5cdFx0XHRcdGlmIChiZXN0WzBdLmxlbmd0aCA9PT0gMCkge1xuXHRcdFx0XHRcdHJldHVybiBiZXN0O1xuXHRcdFx0XHR9XG5cblx0XHRcdFx0Ly8gaWYgYSBjbG9zaW5nIGRlbGltaXRlciBpcyBwcm92aWRlZCwgdGhlbiB3ZSBoYXZlIHRvIGNoZWNrIGl0IGFsc29cblx0XHRcdFx0aWYgKGMpIHtcblx0XHRcdFx0XHQvLyB3ZSB0cnkgdGhpcyBldmVuIGlmIHRoZXJlIGlzIG5vIHJlbWFpbmluZyBpbnB1dCBiZWNhdXNlIHRoZSBwYXR0ZXJuXG5cdFx0XHRcdFx0Ly8gbWF5IHdlbGwgYmUgb3B0aW9uYWwgb3IgbWF0Y2ggZW1wdHkgaW5wdXQgLi4uXG5cdFx0XHRcdFx0dHJ5IHtcblx0XHRcdFx0XHRcdHEgPSBjLmNhbGwodGhpcywgYmVzdFsxXSk7XG5cdFx0XHRcdFx0fSBjYXRjaCAoZXkpIHtcblx0XHRcdFx0XHRcdHRocm93IG5ldyAkUC5FeGNlcHRpb24oYmVzdFsxXSk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gaXQgcGFyc2VkIC4uLiBiZSBzdXJlIHRvIHVwZGF0ZSB0aGUgYmVzdCBtYXRjaCByZW1haW5pbmcgaW5wdXRcblx0XHRcdFx0XHRiZXN0WzFdID0gcVsxXTtcblx0XHRcdFx0fVxuXHRcdFx0XHQvLyBpZiB3ZSdyZSBoZXJlLCBlaXRoZXIgdGhlcmUgd2FzIG5vIGNsb3NpbmcgZGVsaW1pdGVyIG9yIHdlIHBhcnNlZCBpdFxuXHRcdFx0XHQvLyBzbyBub3cgd2UgaGF2ZSB0aGUgYmVzdCBtYXRjaDsganVzdCByZXR1cm4gaXQhXG5cdFx0XHRcdHJldHVybiBiZXN0O1xuXHRcdFx0fTtcblx0XHR9LFxuXHRcdGZvcndhcmQ6IGZ1bmN0aW9uIChnciwgZm5hbWUpIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHRyZXR1cm4gZ3JbZm5hbWVdLmNhbGwodGhpcywgcyk7XG5cdFx0XHR9O1xuXHRcdH0sXG5cblx0XHQvL1xuXHRcdC8vIFRyYW5zbGF0aW9uIE9wZXJhdG9yc1xuXHRcdC8vXG5cdFx0cmVwbGFjZTogZnVuY3Rpb24gKHJ1bGUsIHJlcGwpIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHR2YXIgciA9IHJ1bGUuY2FsbCh0aGlzLCBzKTtcblx0XHRcdFx0cmV0dXJuIFtyZXBsLCByWzFdXTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHRwcm9jZXNzOiBmdW5jdGlvbiAocnVsZSwgZm4pIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHR2YXIgciA9IHJ1bGUuY2FsbCh0aGlzLCBzKTtcblx0XHRcdFx0cmV0dXJuIFtmbi5jYWxsKHRoaXMsIHJbMF0pLCByWzFdXTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHRtaW46IGZ1bmN0aW9uIChtaW4sIHJ1bGUpIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAocykge1xuXHRcdFx0XHR2YXIgcnggPSBydWxlLmNhbGwodGhpcywgcyk7XG5cdFx0XHRcdGlmIChyeFswXS5sZW5ndGggPCBtaW4pIHtcblx0XHRcdFx0XHR0aHJvdyBuZXcgJFAuRXhjZXB0aW9uKHMpO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHJldHVybiByeDtcblx0XHRcdH07XG5cdFx0fVxuXHR9O1xuXHRcblxuXHQvLyBHZW5lcmF0b3IgT3BlcmF0b3JzIEFuZCBWZWN0b3IgT3BlcmF0b3JzXG5cblx0Ly8gR2VuZXJhdG9ycyBhcmUgb3BlcmF0b3JzIHRoYXQgaGF2ZSBhIHNpZ25hdHVyZSBvZiBGKFIpID0+IFIsXG5cdC8vIHRha2luZyBhIGdpdmVuIHJ1bGUgYW5kIHJldHVybmluZyBhbm90aGVyIHJ1bGUsIHN1Y2ggYXMgXG5cdC8vIGlnbm9yZSwgd2hpY2ggcGFyc2VzIGEgZ2l2ZW4gcnVsZSBhbmQgdGhyb3dzIGF3YXkgdGhlIHJlc3VsdC5cblxuXHQvLyBWZWN0b3Igb3BlcmF0b3JzIGFyZSB0aG9zZSB0aGF0IGhhdmUgYSBzaWduYXR1cmUgb2YgRihSMSxSMiwuLi4pID0+IFIsXG5cdC8vIHRha2UgYSBsaXN0IG9mIHJ1bGVzIGFuZCByZXR1cm5pbmcgYSBuZXcgcnVsZSwgc3VjaCBhcyBlYWNoLlxuXG5cdC8vIEdlbmVyYXRvciBvcGVyYXRvcnMgYXJlIGNvbnZlcnRlZCAodmlhIHRoZSBmb2xsb3dpbmcgX2dlbmVyYXRvclxuXHQvLyBmdW5jdGlvbikgaW50byBmdW5jdGlvbnMgdGhhdCBjYW4gYWxzbyB0YWtlIGEgbGlzdCBvciBhcnJheSBvZiBydWxlc1xuXHQvLyBhbmQgcmV0dXJuIGFuIGFycmF5IG9mIG5ldyBydWxlcyBhcyB0aG91Z2ggdGhlIGZ1bmN0aW9uIGhhZCBiZWVuXG5cdC8vIGNhbGxlZCBvbiBlYWNoIHJ1bGUgaW4gdHVybiAod2hpY2ggaXMgd2hhdCBhY3R1YWxseSBoYXBwZW5zKS5cblxuXHQvLyBUaGlzIGFsbG93cyBnZW5lcmF0b3JzIHRvIGJlIHVzZWQgd2l0aCB2ZWN0b3Igb3BlcmF0b3JzIG1vcmUgZWFzaWx5LlxuXHQvLyBFeGFtcGxlOlxuXHQvLyBlYWNoKGlnbm9yZShmb28sIGJhcikpIGluc3RlYWQgb2YgZWFjaChpZ25vcmUoZm9vKSwgaWdub3JlKGJhcikpXG5cblx0Ly8gVGhpcyBhbHNvIHR1cm5zIGdlbmVyYXRvcnMgaW50byB2ZWN0b3Igb3BlcmF0b3JzLCB3aGljaCBhbGxvd3Ncblx0Ly8gY29uc3RydWN0cyBsaWtlOlxuXHQvLyBub3QoY2FjaGUoZm9vLCBiYXIpKVxuXHRcblx0dmFyIF9nZW5lcmF0b3IgPSBmdW5jdGlvbiAob3ApIHtcblx0XHRmdW5jdGlvbiBnZW4oKSB7XG5cdFx0XHR2YXIgYXJncyA9IG51bGwsIHJ4ID0gW10sIHB4LCBpO1xuXHRcdFx0aWYgKGFyZ3VtZW50cy5sZW5ndGggPiAxKSB7XG5cdFx0XHRcdGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMpO1xuXHRcdFx0fSBlbHNlIGlmIChhcmd1bWVudHNbMF0gaW5zdGFuY2VvZiBBcnJheSkge1xuXHRcdFx0XHRhcmdzID0gYXJndW1lbnRzWzBdO1xuXHRcdFx0fVxuXHRcdFx0aWYgKGFyZ3MpIHtcblx0XHRcdFx0cHggPSBhcmdzLnNoaWZ0KCk7XG5cdFx0XHRcdGlmIChweC5sZW5ndGggPiAwKSB7XG5cdFx0XHRcdFx0YXJncy51bnNoaWZ0KHB4W2ldKTtcblx0XHRcdFx0XHRyeC5wdXNoKG9wLmFwcGx5KG51bGwsIGFyZ3MpKTtcblx0XHRcdFx0XHRhcmdzLnNoaWZ0KCk7XG5cdFx0XHRcdFx0cmV0dXJuIHJ4O1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gb3AuYXBwbHkobnVsbCwgYXJndW1lbnRzKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gZ2VuO1xuXHR9O1xuXHRcblx0dmFyIGd4ID0gXCJvcHRpb25hbCBub3QgaWdub3JlIGNhY2hlXCIuc3BsaXQoL1xccy8pO1xuXHRcblx0Zm9yICh2YXIgaSA9IDAgOyBpIDwgZ3gubGVuZ3RoIDsgaSsrKSB7XG5cdFx0X1tneFtpXV0gPSBfZ2VuZXJhdG9yKF9bZ3hbaV1dKTtcblx0fVxuXG5cdHZhciBfdmVjdG9yID0gZnVuY3Rpb24gKG9wKSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0XHRcdGlmIChhcmd1bWVudHNbMF0gaW5zdGFuY2VvZiBBcnJheSkge1xuXHRcdFx0XHRyZXR1cm4gb3AuYXBwbHkobnVsbCwgYXJndW1lbnRzWzBdKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHJldHVybiBvcC5hcHBseShudWxsLCBhcmd1bWVudHMpO1xuXHRcdFx0fVxuXHRcdH07XG5cdH07XG5cdFxuXHR2YXIgdnggPSBcImVhY2ggYW55IGFsbFwiLnNwbGl0KC9cXHMvKTtcblx0XG5cdGZvciAodmFyIGogPSAwIDsgaiA8IHZ4Lmxlbmd0aCA7IGorKykge1xuXHRcdF9bdnhbal1dID0gX3ZlY3RvcihfW3Z4W2pdXSk7XG5cdH1cblx0XG59KCkpOyIsIihmdW5jdGlvbiAoKSB7XG5cdHZhciAkRCA9IERhdGU7XG5cblx0dmFyIGZsYXR0ZW5BbmRDb21wYWN0ID0gZnVuY3Rpb24gKGF4KSB7XG5cdFx0dmFyIHJ4ID0gW107XG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBheC5sZW5ndGg7IGkrKykge1xuXHRcdFx0aWYgKGF4W2ldIGluc3RhbmNlb2YgQXJyYXkpIHtcblx0XHRcdFx0cnggPSByeC5jb25jYXQoZmxhdHRlbkFuZENvbXBhY3QoYXhbaV0pKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdGlmIChheFtpXSkge1xuXHRcdFx0XHRcdHJ4LnB1c2goYXhbaV0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXHRcdHJldHVybiByeDtcblx0fTtcblxuXHR2YXIgcGFyc2VNZXJpZGlhbiA9IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAodGhpcy5tZXJpZGlhbiAmJiAodGhpcy5ob3VyIHx8IHRoaXMuaG91ciA9PT0gMCkpIHtcblx0XHRcdGlmICh0aGlzLm1lcmlkaWFuID09PSBcImFcIiAmJiB0aGlzLmhvdXIgPiAxMSAmJiBEYXRlLkNvbmZpZy5zdHJpY3QyNGhyKXtcblx0XHRcdFx0dGhyb3cgXCJJbnZhbGlkIGhvdXIgYW5kIG1lcmlkaWFuIGNvbWJpbmF0aW9uXCI7XG5cdFx0XHR9IGVsc2UgaWYgKHRoaXMubWVyaWRpYW4gPT09IFwicFwiICYmIHRoaXMuaG91ciA8IDEyICYmIERhdGUuQ29uZmlnLnN0cmljdDI0aHIpe1xuXHRcdFx0XHR0aHJvdyBcIkludmFsaWQgaG91ciBhbmQgbWVyaWRpYW4gY29tYmluYXRpb25cIjtcblx0XHRcdH0gZWxzZSBpZiAodGhpcy5tZXJpZGlhbiA9PT0gXCJwXCIgJiYgdGhpcy5ob3VyIDwgMTIpIHtcblx0XHRcdFx0dGhpcy5ob3VyID0gdGhpcy5ob3VyICsgMTI7XG5cdFx0XHR9IGVsc2UgaWYgKHRoaXMubWVyaWRpYW4gPT09IFwiYVwiICYmIHRoaXMuaG91ciA9PT0gMTIpIHtcblx0XHRcdFx0dGhpcy5ob3VyID0gMDtcblx0XHRcdH1cblx0XHR9XG5cdH07XG5cblx0dmFyIHNldERlZmF1bHRzID0gZnVuY3Rpb24gKCkge1xuXHRcdHZhciBub3cgPSBuZXcgRGF0ZSgpO1xuXHRcdGlmICgodGhpcy5ob3VyIHx8IHRoaXMubWludXRlKSAmJiAoIXRoaXMubW9udGggJiYgIXRoaXMueWVhciAmJiAhdGhpcy5kYXkpKSB7XG5cdFx0XHR0aGlzLmRheSA9IG5vdy5nZXREYXRlKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLnllYXIpIHtcblx0XHRcdHRoaXMueWVhciA9IG5vdy5nZXRGdWxsWWVhcigpO1xuXHRcdH1cblx0XHRcblx0XHRpZiAoIXRoaXMubW9udGggJiYgdGhpcy5tb250aCAhPT0gMCkge1xuXHRcdFx0dGhpcy5tb250aCA9IG5vdy5nZXRNb250aCgpO1xuXHRcdH1cblx0XHRcblx0XHRpZiAoIXRoaXMuZGF5KSB7XG5cdFx0XHR0aGlzLmRheSA9IDE7XG5cdFx0fVxuXHRcdFxuXHRcdGlmICghdGhpcy5ob3VyKSB7XG5cdFx0XHR0aGlzLmhvdXIgPSAwO1xuXHRcdH1cblx0XHRcblx0XHRpZiAoIXRoaXMubWludXRlKSB7XG5cdFx0XHR0aGlzLm1pbnV0ZSA9IDA7XG5cdFx0fVxuXG5cdFx0aWYgKCF0aGlzLnNlY29uZCkge1xuXHRcdFx0dGhpcy5zZWNvbmQgPSAwO1xuXHRcdH1cblx0XHRpZiAoIXRoaXMubWlsbGlzZWNvbmQpIHtcblx0XHRcdHRoaXMubWlsbGlzZWNvbmQgPSAwO1xuXHRcdH1cblx0fTtcblxuXHR2YXIgZmluaXNoVXRpbHMgPSB7XG5cdFx0Z2V0VG9kYXk6IGZ1bmN0aW9uICgpIHtcblx0XHRcdCBpZiAodGhpcy5ub3cgfHwgXCJob3VyIG1pbnV0ZSBzZWNvbmRcIi5pbmRleE9mKHRoaXMudW5pdCkgIT09IC0xKSB7XG5cdFx0XHRcdHJldHVybiBuZXcgRGF0ZSgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmV0dXJuICRELnRvZGF5KCk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRzZXREYXlzRnJvbVdlZWtkYXk6IGZ1bmN0aW9uICh0b2RheSwgb3JpZW50KXtcblx0XHRcdHZhciBnYXA7XG5cdFx0XHRvcmllbnQgPSBvcmllbnQgfHwgMTtcblx0XHRcdHRoaXMudW5pdCA9IFwiZGF5XCI7XG5cdFx0XHRnYXAgPSAoJEQuZ2V0RGF5TnVtYmVyRnJvbU5hbWUodGhpcy53ZWVrZGF5KSAtIHRvZGF5LmdldERheSgpKTtcblx0XHRcdHRoaXMuZGF5cyA9IGdhcCA/ICgoZ2FwICsgKG9yaWVudCAqIDcpKSAlIDcpIDogKG9yaWVudCAqIDcpO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblx0XHRzZXRNb250aHNGcm9tTW9udGg6IGZ1bmN0aW9uICh0b2RheSwgb3JpZW50KSB7XG5cdFx0XHR2YXIgZ2FwO1xuXHRcdFx0b3JpZW50ID0gb3JpZW50IHx8IDE7XG5cdFx0XHR0aGlzLnVuaXQgPSBcIm1vbnRoXCI7XG5cdFx0XHRnYXAgPSAodGhpcy5tb250aCAtIHRvZGF5LmdldE1vbnRoKCkpO1xuXHRcdFx0dGhpcy5tb250aHMgPSBnYXAgPyAoKGdhcCArIChvcmllbnQgKiAxMikpICUgMTIpIDogKG9yaWVudCAqIDEyKTtcblx0XHRcdHRoaXMubW9udGggPSBudWxsO1xuXHRcdFx0cmV0dXJuIHRoaXM7XG5cdFx0fSxcblx0XHRzZXRETVlGcm9tV2Vla2RheTogZnVuY3Rpb24gKCkge1xuXHRcdFx0dmFyIGQgPSBEYXRlW3RoaXMud2Vla2RheV0oKTtcblx0XHRcdHRoaXMuZGF5ID0gZC5nZXREYXRlKCk7XG5cdFx0XHRpZiAoIXRoaXMubW9udGgpIHtcblx0XHRcdFx0dGhpcy5tb250aCA9IGQuZ2V0TW9udGgoKTtcblx0XHRcdH1cblx0XHRcdHRoaXMueWVhciA9IGQuZ2V0RnVsbFllYXIoKTtcblx0XHRcdHJldHVybiB0aGlzO1xuXHRcdH0sXG5cdFx0c2V0VW5pdFZhbHVlOiBmdW5jdGlvbiAob3JpZW50KSB7XG5cdFx0XHRpZiAoIXRoaXMudmFsdWUgJiYgdGhpcy5vcGVyYXRvciAmJiB0aGlzLm9wZXJhdG9yICE9PSBudWxsICYmIHRoaXNbdGhpcy51bml0ICsgXCJzXCJdICYmIHRoaXNbdGhpcy51bml0ICsgXCJzXCJdICE9PSBudWxsKSB7XG5cdFx0XHRcdHRoaXNbdGhpcy51bml0ICsgXCJzXCJdID0gdGhpc1t0aGlzLnVuaXQgKyBcInNcIl0gKyAoKHRoaXMub3BlcmF0b3IgPT09IFwiYWRkXCIpID8gMSA6IC0xKSArICh0aGlzLnZhbHVlfHwwKSAqIG9yaWVudDtcblx0XHRcdH0gZWxzZSBpZiAodGhpc1t0aGlzLnVuaXQgKyBcInNcIl0gPT0gbnVsbCB8fCB0aGlzLm9wZXJhdG9yICE9IG51bGwpIHtcblx0XHRcdFx0aWYgKCF0aGlzLnZhbHVlKSB7XG5cdFx0XHRcdFx0dGhpcy52YWx1ZSA9IDE7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpc1t0aGlzLnVuaXQgKyBcInNcIl0gPSB0aGlzLnZhbHVlICogb3JpZW50O1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0Z2VuZXJhdGVEYXRlRnJvbVdlZWtzOiBmdW5jdGlvbiAoKSB7XG5cdFx0XHR2YXIgd2Vla2RheSA9ICh0aGlzLndlZWtkYXkgIT09IHVuZGVmaW5lZCkgPyB0aGlzLndlZWtkYXkgOiBcInRvZGF5XCI7XG5cdFx0XHR2YXIgZCA9IERhdGVbd2Vla2RheV0oKS5hZGRXZWVrcyh0aGlzLndlZWtzKTtcblx0XHRcdGlmICh0aGlzLm5vdykge1xuXHRcdFx0XHRkLnNldFRpbWVUb05vdygpO1xuXHRcdFx0fVxuXHRcdFx0cmV0dXJuIGQ7XG5cdFx0fVxuXHR9O1xuXG5cdCRELlRyYW5zbGF0b3IgPSB7XG5cdFx0aG91cjogZnVuY3Rpb24gKHMpIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHRoaXMuaG91ciA9IE51bWJlcihzKTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHRtaW51dGU6IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR0aGlzLm1pbnV0ZSA9IE51bWJlcihzKTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHRzZWNvbmQ6IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR0aGlzLnNlY29uZCA9IE51bWJlcihzKTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHQvKiBmb3Igc3MucyBmb3JtYXQgKi9cblx0XHRzZWNvbmRBbmRNaWxsaXNlY29uZDogZnVuY3Rpb24gKHMpIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHZhciBteCA9IHMubWF0Y2goL14oWzAtNV1bMC05XSlcXC4oWzAtOV17MSwzfSkvKTtcblx0XHRcdFx0dGhpcy5zZWNvbmQgPSBOdW1iZXIobXhbMV0pO1xuXHRcdFx0XHR0aGlzLm1pbGxpc2Vjb25kID0gTnVtYmVyKG14WzJdKTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHRtZXJpZGlhbjogZnVuY3Rpb24gKHMpIHtcblx0XHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHRoaXMubWVyaWRpYW4gPSBzLnNsaWNlKDAsIDEpLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHR9O1xuXHRcdH0sXG5cdFx0dGltZXpvbmU6IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR2YXIgbiA9IHMucmVwbGFjZSgvW15cXGRcXCtcXC1dL2csIFwiXCIpO1xuXHRcdFx0XHRpZiAobi5sZW5ndGgpIHtcblx0XHRcdFx0XHR0aGlzLnRpbWV6b25lT2Zmc2V0ID0gTnVtYmVyKG4pO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHRoaXMudGltZXpvbmUgPSBzLnRvTG93ZXJDYXNlKCk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fSxcblx0XHRkYXk6IGZ1bmN0aW9uICh4KSB7XG5cdFx0XHR2YXIgcyA9IHhbMF07XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR0aGlzLmRheSA9IE51bWJlcihzLm1hdGNoKC9cXGQrLylbMF0pO1xuXHRcdFx0XHRpZiAodGhpcy5kYXkgPCAxKSB7XG5cdFx0XHRcdFx0dGhyb3cgXCJpbnZhbGlkIGRheVwiO1xuXHRcdFx0XHR9XG5cdFx0XHR9O1xuXHRcdH0sXG5cdFx0bW9udGg6IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR0aGlzLm1vbnRoID0gKHMubGVuZ3RoID09PSAzKSA/IFwiamFuIGZlYiBtYXIgYXByIG1heSBqdW4ganVsIGF1ZyBzZXAgb2N0IG5vdiBkZWNcIi5pbmRleE9mKHMpLzQgOiBOdW1iZXIocykgLSAxO1xuXHRcdFx0XHRpZiAodGhpcy5tb250aCA8IDApIHtcblx0XHRcdFx0XHR0aHJvdyBcImludmFsaWQgbW9udGhcIjtcblx0XHRcdFx0fVxuXHRcdFx0fTtcblx0XHR9LFxuXHRcdHllYXI6IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR2YXIgbiA9IE51bWJlcihzKTtcblx0XHRcdFx0dGhpcy55ZWFyID0gKChzLmxlbmd0aCA+IDIpID8gbiA6XG5cdFx0XHRcdFx0KG4gKyAoKChuICsgMjAwMCkgPCBEYXRlLkN1bHR1cmVJbmZvLnR3b0RpZ2l0WWVhck1heCkgPyAyMDAwIDogMTkwMCkpKTtcblx0XHRcdH07XG5cdFx0fSxcblx0XHRyZGF5OiBmdW5jdGlvbiAocykge1xuXHRcdFx0cmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0c3dpdGNoIChzKSB7XG5cdFx0XHRcdFx0Y2FzZSBcInllc3RlcmRheVwiOlxuXHRcdFx0XHRcdFx0dGhpcy5kYXlzID0gLTE7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwidG9tb3Jyb3dcIjpcblx0XHRcdFx0XHRcdHRoaXMuZGF5cyA9IDE7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwidG9kYXlcIjpcblx0XHRcdFx0XHRcdHRoaXMuZGF5cyA9IDA7XG5cdFx0XHRcdFx0XHRicmVhaztcblx0XHRcdFx0XHRjYXNlIFwibm93XCI6XG5cdFx0XHRcdFx0XHR0aGlzLmRheXMgPSAwO1xuXHRcdFx0XHRcdFx0dGhpcy5ub3cgPSB0cnVlO1xuXHRcdFx0XHRcdFx0YnJlYWs7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0fSxcblx0XHRmaW5pc2hFeGFjdDogZnVuY3Rpb24gKHgpIHtcblx0XHRcdHZhciBkO1xuXHRcdFx0eCA9ICh4IGluc3RhbmNlb2YgQXJyYXkpID8geCA6IFt4XTtcblxuXHRcdFx0Zm9yICh2YXIgaSA9IDAgOyBpIDwgeC5sZW5ndGggOyBpKyspIHtcblx0XHRcdFx0aWYgKHhbaV0pIHtcblx0XHRcdFx0XHR4W2ldLmNhbGwodGhpcyk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0c2V0RGVmYXVsdHMuY2FsbCh0aGlzKTtcblx0XHRcdHBhcnNlTWVyaWRpYW4uY2FsbCh0aGlzKTtcblxuXHRcdFx0aWYgKHRoaXMuZGF5ID4gJEQuZ2V0RGF5c0luTW9udGgodGhpcy55ZWFyLCB0aGlzLm1vbnRoKSkge1xuXHRcdFx0XHR0aHJvdyBuZXcgUmFuZ2VFcnJvcih0aGlzLmRheSArIFwiIGlzIG5vdCBhIHZhbGlkIHZhbHVlIGZvciBkYXlzLlwiKTtcblx0XHRcdH1cblxuXHRcdFx0ZCA9IG5ldyBEYXRlKHRoaXMueWVhciwgdGhpcy5tb250aCwgdGhpcy5kYXksIHRoaXMuaG91ciwgdGhpcy5taW51dGUsIHRoaXMuc2Vjb25kLCB0aGlzLm1pbGxpc2Vjb25kKTtcblx0XHRcdGlmICh0aGlzLnllYXIgPCAxMDApIHtcblx0XHRcdFx0ZC5zZXRGdWxsWWVhcih0aGlzLnllYXIpOyAvLyBtZWFucyB5ZWFycyBsZXNzIHRoYXQgMTAwIGFyZSBwcm9jZXNzIGNvcnJlY3RseS4gSlMgd2lsbCBwYXJzZSBpdCBvdGhlcndpc2UgYXMgMTkwMC0xOTk5LlxuXHRcdFx0fVxuXHRcdFx0aWYgKHRoaXMudGltZXpvbmUpIHtcblx0XHRcdFx0ZC5zZXQoeyB0aW1lem9uZTogdGhpcy50aW1lem9uZSB9KTtcblx0XHRcdH0gZWxzZSBpZiAodGhpcy50aW1lem9uZU9mZnNldCkge1xuXHRcdFx0XHRkLnNldCh7IHRpbWV6b25lT2Zmc2V0OiB0aGlzLnRpbWV6b25lT2Zmc2V0IH0pO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRyZXR1cm4gZDtcblx0XHR9LFxuXHRcdGZpbmlzaDogZnVuY3Rpb24gKHgpIHtcblx0XHRcdHZhciB0b2RheSwgZXhwcmVzc2lvbiwgb3JpZW50LCB0ZW1wO1xuXG5cdFx0XHR4ID0gKHggaW5zdGFuY2VvZiBBcnJheSkgPyBmbGF0dGVuQW5kQ29tcGFjdCh4KSA6IFsgeCBdO1xuXG5cdFx0XHRpZiAoeC5sZW5ndGggPT09IDApIHtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGZvciAodmFyIGkgPSAwIDsgaSA8IHgubGVuZ3RoIDsgaSsrKSB7XG5cdFx0XHRcdGlmICh0eXBlb2YgeFtpXSA9PT0gXCJmdW5jdGlvblwiKSB7XG5cdFx0XHRcdFx0eFtpXS5jYWxsKHRoaXMpO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHRpZiAodGhpcy5ub3cgJiYgIXRoaXMudW5pdCAmJiAhdGhpcy5vcGVyYXRvcikge1xuXHRcdFx0XHRyZXR1cm4gbmV3IERhdGUoKTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRvZGF5ID0gZmluaXNoVXRpbHMuZ2V0VG9kYXkuY2FsbCh0aGlzKTtcblx0XHRcdH1cblx0XHRcdFxuXHRcdFx0ZXhwcmVzc2lvbiA9ICEhKHRoaXMuZGF5cyAmJiB0aGlzLmRheXMgIT09IG51bGwgfHwgdGhpcy5vcmllbnQgfHwgdGhpcy5vcGVyYXRvcik7XG5cdFx0XHRvcmllbnQgPSAoKHRoaXMub3JpZW50ID09PSBcInBhc3RcIiB8fCB0aGlzLm9wZXJhdG9yID09PSBcInN1YnRyYWN0XCIpID8gLTEgOiAxKTtcblxuXHRcdFx0aWYgKHRoaXMubW9udGggJiYgdGhpcy51bml0ID09PSBcIndlZWtcIikge1xuXHRcdFx0XHR0aGlzLnZhbHVlID0gdGhpcy5tb250aCArIDE7XG5cdFx0XHRcdGRlbGV0ZSB0aGlzLm1vbnRoO1xuXHRcdFx0XHRkZWxldGUgdGhpcy5kYXk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICgodGhpcy5tb250aCB8fCB0aGlzLm1vbnRoID09PSAwKSAmJiBcInllYXIgZGF5IGhvdXIgbWludXRlIHNlY29uZFwiLmluZGV4T2YodGhpcy51bml0KSAhPT0gLTEpIHtcblx0XHRcdFx0aWYgKCF0aGlzLnZhbHVlKSB7XG5cdFx0XHRcdFx0dGhpcy52YWx1ZSA9IHRoaXMubW9udGggKyAxO1xuXHRcdFx0XHR9XG5cdFx0XHRcdHRoaXMubW9udGggPSBudWxsO1xuXHRcdFx0XHRleHByZXNzaW9uID0gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCFleHByZXNzaW9uICYmIHRoaXMud2Vla2RheSAmJiAhdGhpcy5kYXkgJiYgIXRoaXMuZGF5cykge1xuXHRcdFx0XHRmaW5pc2hVdGlscy5zZXRETVlGcm9tV2Vla2RheS5jYWxsKHRoaXMpO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoZXhwcmVzc2lvbiAmJiB0aGlzLndlZWtkYXkgJiYgdGhpcy51bml0ICE9PSBcIm1vbnRoXCIgJiYgdGhpcy51bml0ICE9PSBcIndlZWtcIikge1xuXHRcdFx0XHRmaW5pc2hVdGlscy5zZXREYXlzRnJvbVdlZWtkYXkuY2FsbCh0aGlzLCB0b2RheSwgb3JpZW50KTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKHRoaXMud2Vla2RheSAmJiB0aGlzLnVuaXQgIT09IFwid2Vla1wiICYmICF0aGlzLmRheSAmJiAhdGhpcy5kYXlzKSB7XG5cdFx0XHRcdHRlbXAgPSBEYXRlW3RoaXMud2Vla2RheV0oKTtcblx0XHRcdFx0dGhpcy5kYXkgPSB0ZW1wLmdldERhdGUoKTtcblx0XHRcdFx0aWYgKHRlbXAuZ2V0TW9udGgoKSAhPT0gdG9kYXkuZ2V0TW9udGgoKSkge1xuXHRcdFx0XHRcdHRoaXMubW9udGggPSB0ZW1wLmdldE1vbnRoKCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKHRoaXMubW9udGggJiYgdGhpcy51bml0ID09PSBcImRheVwiICYmIHRoaXMub3BlcmF0b3IpIHtcblx0XHRcdFx0aWYgKCF0aGlzLnZhbHVlKSB7XG5cdFx0XHRcdFx0dGhpcy52YWx1ZSA9ICh0aGlzLm1vbnRoICsgMSk7XG5cdFx0XHRcdH1cblx0XHRcdFx0dGhpcy5tb250aCA9IG51bGw7XG5cdFx0XHR9XG5cblx0XHRcdGlmICh0aGlzLnZhbHVlICE9IG51bGwgJiYgdGhpcy5tb250aCAhPSBudWxsICYmIHRoaXMueWVhciAhPSBudWxsKSB7XG5cdFx0XHRcdHRoaXMuZGF5ID0gdGhpcy52YWx1ZSAqIDE7XG5cdFx0XHR9XG5cblx0XHRcdGlmICh0aGlzLm1vbnRoICYmICF0aGlzLmRheSAmJiB0aGlzLnZhbHVlKSB7XG5cdFx0XHRcdHRvZGF5LnNldCh7IGRheTogdGhpcy52YWx1ZSAqIDEgfSk7XG5cdFx0XHRcdGlmICghZXhwcmVzc2lvbikge1xuXHRcdFx0XHRcdHRoaXMuZGF5ID0gdGhpcy52YWx1ZSAqIDE7XG5cdFx0XHRcdH1cblx0XHRcdH1cblxuXHRcdFx0aWYgKCF0aGlzLm1vbnRoICYmIHRoaXMudmFsdWUgJiYgdGhpcy51bml0ID09PSBcIm1vbnRoXCIgJiYgIXRoaXMubm93KSB7XG5cdFx0XHRcdHRoaXMubW9udGggPSB0aGlzLnZhbHVlO1xuXHRcdFx0XHRleHByZXNzaW9uID0gdHJ1ZTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGV4cHJlc3Npb24gJiYgKHRoaXMubW9udGggfHwgdGhpcy5tb250aCA9PT0gMCkgJiYgdGhpcy51bml0ICE9PSBcInllYXJcIikge1xuXHRcdFx0XHRmaW5pc2hVdGlscy5zZXRNb250aHNGcm9tTW9udGguY2FsbCh0aGlzLCB0b2RheSwgb3JpZW50KTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCF0aGlzLnVuaXQpIHtcblx0XHRcdFx0dGhpcy51bml0ID0gXCJkYXlcIjtcblx0XHRcdH1cblxuXHRcdFx0ZmluaXNoVXRpbHMuc2V0VW5pdFZhbHVlLmNhbGwodGhpcywgb3JpZW50KTtcblx0XHRcdHBhcnNlTWVyaWRpYW4uY2FsbCh0aGlzKTtcblx0XHRcdFxuXHRcdFx0aWYgKCh0aGlzLm1vbnRoIHx8IHRoaXMubW9udGggPT09IDApICYmICF0aGlzLmRheSkge1xuXHRcdFx0XHR0aGlzLmRheSA9IDE7XG5cdFx0XHR9XG5cblx0XHRcdGlmICghdGhpcy5vcmllbnQgJiYgIXRoaXMub3BlcmF0b3IgJiYgdGhpcy51bml0ID09PSBcIndlZWtcIiAmJiB0aGlzLnZhbHVlICYmICF0aGlzLmRheSAmJiAhdGhpcy5tb250aCkge1xuXHRcdFx0XHRyZXR1cm4gRGF0ZS50b2RheSgpLnNldFdlZWsodGhpcy52YWx1ZSk7XG5cdFx0XHR9XG5cblx0XHRcdGlmICh0aGlzLnVuaXQgPT09IFwid2Vla1wiICYmIHRoaXMud2Vla3MgJiYgIXRoaXMuZGF5ICYmICF0aGlzLm1vbnRoKSB7XG5cdFx0XHRcdHJldHVybiBmaW5pc2hVdGlscy5nZW5lcmF0ZURhdGVGcm9tV2Vla3MuY2FsbCh0aGlzKTtcblx0XHRcdH1cblxuXHRcdFx0aWYgKGV4cHJlc3Npb24gJiYgdGhpcy50aW1lem9uZSAmJiB0aGlzLmRheSAmJiB0aGlzLmRheXMpIHtcblx0XHRcdFx0dGhpcy5kYXkgPSB0aGlzLmRheXM7XG5cdFx0XHR9XG5cblx0XHRcdGlmIChleHByZXNzaW9uKXtcblx0XHRcdFx0dG9kYXkuYWRkKHRoaXMpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dG9kYXkuc2V0KHRoaXMpO1xuXHRcdFx0fVxuXHRcdFx0XG5cdFx0XHRpZiAodGhpcy50aW1lem9uZSkge1xuXHRcdFx0XHR0aGlzLnRpbWV6b25lID0gdGhpcy50aW1lem9uZS50b1VwcGVyQ2FzZSgpO1xuXHRcdFx0XHR2YXIgb2Zmc2V0ID0gJEQuZ2V0VGltZXpvbmVPZmZzZXQodGhpcy50aW1lem9uZSk7XG5cdFx0XHRcdHZhciB0aW1lem9uZTtcblx0XHRcdFx0aWYgKHRvZGF5Lmhhc0RheWxpZ2h0U2F2aW5nVGltZSgpKSB7XG5cdFx0XHRcdFx0Ly8gbGV0cyBjaGVjayB0aGF0IHdlJ3JlIGJlaW5nIHNhbmUgd2l0aCB0aW1lem9uZSBzZXR0aW5nXG5cdFx0XHRcdFx0dGltZXpvbmUgPSAkRC5nZXRUaW1lem9uZUFiYnJldmlhdGlvbihvZmZzZXQsIHRvZGF5LmlzRGF5bGlnaHRTYXZpbmdUaW1lKCkpO1xuXHRcdFx0XHRcdGlmICh0aW1lem9uZSAhPT0gdGhpcy50aW1lem9uZSkge1xuXHRcdFx0XHRcdFx0Ly8gYnVnZ2VyLCB3ZSdyZSBpbiBhIHBsYWNlIHdoZXJlIHRoaW5ncyBsaWtlIEVTVCB2cyBFRFQgbWF0dGVycy5cblx0XHRcdFx0XHRcdGlmICh0b2RheS5pc0RheWxpZ2h0U2F2aW5nVGltZSgpKSB7XG5cdFx0XHRcdFx0XHRcdHRvZGF5LmFkZEhvdXJzKC0xKTtcblx0XHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHRcdHRvZGF5LmFkZEhvdXJzKDEpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0XHR0b2RheS5zZXRUaW1lem9uZU9mZnNldChvZmZzZXQpO1xuXHRcdFx0fVxuXG5cdFx0XHRyZXR1cm4gdG9kYXk7XG5cdFx0fVxuXHR9O1xufSgpKTsiLCIvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG4gKiBTdWdhclBhayAtIERvbWFpbiBTcGVjaWZpYyBMYW5ndWFnZSAtICBTeW50YWN0aWNhbCBTdWdhciAgKlxyXG4gKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cclxuIFxyXG4oZnVuY3Rpb24gKCkge1xyXG5cdHZhciAkRCA9IERhdGUsICRQID0gJEQucHJvdG90eXBlLCAkTiA9IE51bWJlci5wcm90b3R5cGU7XHJcblxyXG5cdC8vIHByaXZhdGVcclxuXHQkUC5fb3JpZW50ID0gKzE7XHJcblxyXG5cdC8vIHByaXZhdGVcclxuXHQkUC5fbnRoID0gbnVsbDtcclxuXHJcblx0Ly8gcHJpdmF0ZVxyXG5cdCRQLl9pcyA9IGZhbHNlO1xyXG5cclxuXHQvLyBwcml2YXRlXHJcblx0JFAuX3NhbWUgPSBmYWxzZTtcclxuXHRcclxuXHQvLyBwcml2YXRlXHJcblx0JFAuX2lzU2Vjb25kID0gZmFsc2U7XHJcblxyXG5cdC8vIHByaXZhdGVcclxuXHQkTi5fZGF0ZUVsZW1lbnQgPSBcImRheXNcIjtcclxuXHJcblx0LyoqIFxyXG5cdCAqIE1vdmVzIHRoZSBkYXRlIHRvIHRoZSBuZXh0IGluc3RhbmNlIG9mIGEgZGF0ZSBhcyBzcGVjaWZpZWQgYnkgdGhlIHN1YnNlcXVlbnQgZGF0ZSBlbGVtZW50IGZ1bmN0aW9uIChlZy4gLmRheSgpLCAubW9udGgoKSksIG1vbnRoIG5hbWUgZnVuY3Rpb24gKGVnLiAuamFudWFyeSgpLCAuamFuKCkpIG9yIGRheSBuYW1lIGZ1bmN0aW9uIChlZy4gLmZyaWRheSgpLCBmcmkoKSkuXHJcblx0ICogRXhhbXBsZVxyXG5cdDxwcmU+PGNvZGU+XHJcblx0RGF0ZS50b2RheSgpLm5leHQoKS5mcmlkYXkoKTtcclxuXHREYXRlLnRvZGF5KCkubmV4dCgpLmZyaSgpO1xyXG5cdERhdGUudG9kYXkoKS5uZXh0KCkubWFyY2goKTtcclxuXHREYXRlLnRvZGF5KCkubmV4dCgpLm1hcigpO1xyXG5cdERhdGUudG9kYXkoKS5uZXh0KCkud2VlaygpO1xyXG5cdDwvY29kZT48L3ByZT5cclxuXHQgKiBcclxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICBkYXRlXHJcblx0ICovXHJcblx0JFAubmV4dCA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX21vdmUgPSB0cnVlO1xyXG5cdFx0dGhpcy5fb3JpZW50ID0gKzE7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9O1xyXG5cclxuXHQvKiogXHJcblx0ICogQ3JlYXRlcyBhIG5ldyBEYXRlIChEYXRlLnRvZGF5KCkpIGFuZCBtb3ZlcyB0aGUgZGF0ZSB0byB0aGUgbmV4dCBpbnN0YW5jZSBvZiB0aGUgZGF0ZSBhcyBzcGVjaWZpZWQgYnkgdGhlIHN1YnNlcXVlbnQgZGF0ZSBlbGVtZW50IGZ1bmN0aW9uIChlZy4gLmRheSgpLCAubW9udGgoKSksIG1vbnRoIG5hbWUgZnVuY3Rpb24gKGVnLiAuamFudWFyeSgpLCAuamFuKCkpIG9yIGRheSBuYW1lIGZ1bmN0aW9uIChlZy4gLmZyaWRheSgpLCBmcmkoKSkuXHJcblx0ICogRXhhbXBsZVxyXG5cdDxwcmU+PGNvZGU+XHJcblx0RGF0ZS5uZXh0KCkuZnJpZGF5KCk7XHJcblx0RGF0ZS5uZXh0KCkuZnJpKCk7XHJcblx0RGF0ZS5uZXh0KCkubWFyY2goKTtcclxuXHREYXRlLm5leHQoKS5tYXIoKTtcclxuXHREYXRlLm5leHQoKS53ZWVrKCk7XHJcblx0PC9jb2RlPjwvcHJlPlxyXG5cdCAqIFxyXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIGRhdGVcclxuXHQgKi9cclxuXHQkRC5uZXh0ID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICRELnRvZGF5KCkubmV4dCgpO1xyXG5cdH07XHJcblxyXG5cdC8qKiBcclxuXHQgKiBNb3ZlcyB0aGUgZGF0ZSB0byB0aGUgcHJldmlvdXMgaW5zdGFuY2Ugb2YgYSBkYXRlIGFzIHNwZWNpZmllZCBieSB0aGUgc3Vic2VxdWVudCBkYXRlIGVsZW1lbnQgZnVuY3Rpb24gKGVnLiAuZGF5KCksIC5tb250aCgpKSwgbW9udGggbmFtZSBmdW5jdGlvbiAoZWcuIC5qYW51YXJ5KCksIC5qYW4oKSkgb3IgZGF5IG5hbWUgZnVuY3Rpb24gKGVnLiAuZnJpZGF5KCksIGZyaSgpKS5cclxuXHQgKiBFeGFtcGxlXHJcblx0PHByZT48Y29kZT5cclxuXHREYXRlLnRvZGF5KCkubGFzdCgpLmZyaWRheSgpO1xyXG5cdERhdGUudG9kYXkoKS5sYXN0KCkuZnJpKCk7XHJcblx0RGF0ZS50b2RheSgpLmxhc3QoKS5tYXJjaCgpO1xyXG5cdERhdGUudG9kYXkoKS5sYXN0KCkubWFyKCk7XHJcblx0RGF0ZS50b2RheSgpLmxhc3QoKS53ZWVrKCk7XHJcblx0PC9jb2RlPjwvcHJlPlxyXG5cdCAqICBcclxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICBkYXRlXHJcblx0ICovXHJcblx0JFAubGFzdCA9ICRQLnByZXYgPSAkUC5wcmV2aW91cyA9IGZ1bmN0aW9uICgpIHtcclxuXHRcdHRoaXMuX21vdmUgPSB0cnVlO1xyXG5cdFx0dGhpcy5fb3JpZW50ID0gLTE7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9O1xyXG5cclxuXHQvKiogXHJcblx0ICogQ3JlYXRlcyBhIG5ldyBEYXRlIChEYXRlLnRvZGF5KCkpIGFuZCBtb3ZlcyB0aGUgZGF0ZSB0byB0aGUgcHJldmlvdXMgaW5zdGFuY2Ugb2YgdGhlIGRhdGUgYXMgc3BlY2lmaWVkIGJ5IHRoZSBzdWJzZXF1ZW50IGRhdGUgZWxlbWVudCBmdW5jdGlvbiAoZWcuIC5kYXkoKSwgLm1vbnRoKCkpLCBtb250aCBuYW1lIGZ1bmN0aW9uIChlZy4gLmphbnVhcnkoKSwgLmphbigpKSBvciBkYXkgbmFtZSBmdW5jdGlvbiAoZWcuIC5mcmlkYXkoKSwgZnJpKCkpLlxyXG5cdCAqIEV4YW1wbGVcclxuXHQ8cHJlPjxjb2RlPlxyXG5cdERhdGUubGFzdCgpLmZyaWRheSgpO1xyXG5cdERhdGUubGFzdCgpLmZyaSgpO1xyXG5cdERhdGUucHJldmlvdXMoKS5tYXJjaCgpO1xyXG5cdERhdGUucHJldigpLm1hcigpO1xyXG5cdERhdGUubGFzdCgpLndlZWsoKTtcclxuXHQ8L2NvZGU+PC9wcmU+XHJcblx0ICogIFxyXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIGRhdGVcclxuXHQgKi9cclxuXHQkRC5sYXN0ID0gJEQucHJldiA9ICRELnByZXZpb3VzID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuICRELnRvZGF5KCkubGFzdCgpO1xyXG5cdH07XHJcblxyXG5cdC8qKiBcclxuXHQgKiBQZXJmb3JtcyBhIGVxdWFsaXR5IGNoZWNrIHdoZW4gZm9sbG93ZWQgYnkgZWl0aGVyIGEgbW9udGggbmFtZSwgZGF5IG5hbWUgb3IgLndlZWtkYXkoKSBmdW5jdGlvbi5cclxuXHQgKiBFeGFtcGxlXHJcblx0PHByZT48Y29kZT5cclxuXHREYXRlLnRvZGF5KCkuaXMoKS5mcmlkYXkoKTsgLy8gdHJ1ZXxmYWxzZVxyXG5cdERhdGUudG9kYXkoKS5pcygpLmZyaSgpO1xyXG5cdERhdGUudG9kYXkoKS5pcygpLm1hcmNoKCk7XHJcblx0RGF0ZS50b2RheSgpLmlzKCkubWFyKCk7XHJcblx0PC9jb2RlPjwvcHJlPlxyXG5cdCAqICBcclxuXHQgKiBAcmV0dXJuIHtCb29sZWFufSAgICB0cnVlfGZhbHNlXHJcblx0ICovXHJcblx0JFAuaXMgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLl9pcyA9IHRydWU7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9O1xyXG5cclxuXHQvKiogXHJcblx0ICogRGV0ZXJtaW5lcyBpZiB0d28gZGF0ZSBvYmplY3RzIG9jY3VyIG9uL2luIGV4YWN0bHkgdGhlIHNhbWUgaW5zdGFuY2Ugb2YgdGhlIHN1YnNlcXVlbnQgZGF0ZSBwYXJ0IGZ1bmN0aW9uLlxyXG5cdCAqIFRoZSBmdW5jdGlvbiAuc2FtZSgpIG11c3QgYmUgZm9sbG93ZWQgYnkgYSBkYXRlIHBhcnQgZnVuY3Rpb24gKGV4YW1wbGU6IC5kYXkoKSwgLm1vbnRoKCksIC55ZWFyKCksIGV0YykuXHJcblx0ICpcclxuXHQgKiBBbiBvcHRpb25hbCBEYXRlIGNhbiBiZSBwYXNzZWQgaW4gdGhlIGRhdGUgcGFydCBmdW5jdGlvbi4gSWYgbm93IGRhdGUgaXMgcGFzc2VkIGFzIGEgcGFyYW1ldGVyLCAnTm93JyBpcyB1c2VkLiBcclxuXHQgKlxyXG5cdCAqIFRoZSBmb2xsb3dpbmcgZXhhbXBsZSBkZW1vbnN0cmF0ZXMgaG93IHRvIGRldGVybWluZSBpZiB0d28gZGF0ZXMgZmFsbCBvbiB0aGUgZXhhY3Qgc2FtZSBkYXkuXHJcblx0ICpcclxuXHQgKiBFeGFtcGxlXHJcblx0PHByZT48Y29kZT5cclxuXHR2YXIgZDEgPSBEYXRlLnRvZGF5KCk7IC8vIHRvZGF5IGF0IDAwOjAwXHJcblx0dmFyIGQyID0gbmV3IERhdGUoKTsgICAvLyBleGFjdGx5IG5vdy5cclxuXHJcblx0Ly8gRG8gdGhleSBvY2N1ciBvbiB0aGUgc2FtZSBkYXk/XHJcblx0ZDEuc2FtZSgpLmRheShkMik7IC8vIHRydWVcclxuXHRcclxuXHQvLyBEbyB0aGV5IG9jY3VyIG9uIHRoZSBzYW1lIGhvdXI/XHJcblx0ZDEuc2FtZSgpLmhvdXIoZDIpOyAvLyBmYWxzZSwgdW5sZXNzIGQyIGhvdXIgaXMgJzAwJyAobWlkbmlnaHQpLlxyXG5cdFxyXG5cdC8vIFdoYXQgaWYgaXQncyB0aGUgc2FtZSBkYXksIGJ1dCBvbmUgeWVhciBhcGFydD9cclxuXHR2YXIgbmV4dFllYXIgPSBEYXRlLnRvZGF5KCkuYWRkKDEpLnllYXIoKTtcclxuXHJcblx0ZDEuc2FtZSgpLmRheShuZXh0WWVhcik7IC8vIGZhbHNlLCBiZWNhdXNlIHRoZSBkYXRlcyBtdXN0IG9jY3VyIG9uIHRoZSBleGFjdCBzYW1lIGRheS4gXHJcblx0PC9jb2RlPjwvcHJlPlxyXG5cdCAqXHJcblx0ICogU2NlbmFyaW86IERldGVybWluZSBpZiBhIGdpdmVuIGRhdGUgb2NjdXJzIGR1cmluZyBzb21lIHdlZWsgcGVyaW9kIDIgbW9udGhzIGZyb20gbm93LiBcclxuXHQgKlxyXG5cdCAqIEV4YW1wbGVcclxuXHQ8cHJlPjxjb2RlPlxyXG5cdHZhciBmdXR1cmUgPSBEYXRlLnRvZGF5KCkuYWRkKDIpLm1vbnRocygpO1xyXG5cdHJldHVybiBzb21lRGF0ZS5zYW1lKCkud2VlayhmdXR1cmUpOyAvLyB0cnVlfGZhbHNlO1xyXG5cdDwvY29kZT48L3ByZT5cclxuXHQgKiAgXHJcblx0ICogQHJldHVybiB7Qm9vbGVhbn0gICAgdHJ1ZXxmYWxzZVxyXG5cdCAqL1xyXG5cdCRQLnNhbWUgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHR0aGlzLl9zYW1lID0gdHJ1ZTtcclxuXHRcdHRoaXMuX2lzU2Vjb25kID0gZmFsc2U7XHJcblx0XHRyZXR1cm4gdGhpcztcclxuXHR9O1xyXG5cclxuXHQvKiogXHJcblx0ICogRGV0ZXJtaW5lcyBpZiB0aGUgY3VycmVudCBkYXRlL3RpbWUgb2NjdXJzIGR1cmluZyBUb2RheS4gTXVzdCBiZSBwcmVjZWRlZCBieSB0aGUgLmlzKCkgZnVuY3Rpb24uXHJcblx0ICogRXhhbXBsZVxyXG5cdDxwcmU+PGNvZGU+XHJcblx0c29tZURhdGUuaXMoKS50b2RheSgpOyAgICAvLyB0cnVlfGZhbHNlXHJcblx0bmV3IERhdGUoKS5pcygpLnRvZGF5KCk7ICAvLyB0cnVlXHJcblx0RGF0ZS50b2RheSgpLmlzKCkudG9kYXkoKTsvLyB0cnVlXHJcblx0RGF0ZS50b2RheSgpLmFkZCgtMSkuZGF5KCkuaXMoKS50b2RheSgpOyAvLyBmYWxzZVxyXG5cdDwvY29kZT48L3ByZT5cclxuXHQgKiAgXHJcblx0ICogQHJldHVybiB7Qm9vbGVhbn0gICAgdHJ1ZXxmYWxzZVxyXG5cdCAqL1xyXG5cdCRQLnRvZGF5ID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0cmV0dXJuIHRoaXMuc2FtZSgpLmRheSgpO1xyXG5cdH07XHJcblxyXG5cdC8qKiBcclxuXHQgKiBEZXRlcm1pbmVzIGlmIHRoZSBjdXJyZW50IGRhdGUgaXMgYSB3ZWVrZGF5LiBUaGlzIGZ1bmN0aW9uIG11c3QgYmUgcHJlY2VkZWQgYnkgdGhlIC5pcygpIGZ1bmN0aW9uLlxyXG5cdCAqIEV4YW1wbGVcclxuXHQ8cHJlPjxjb2RlPlxyXG5cdERhdGUudG9kYXkoKS5pcygpLndlZWtkYXkoKTsgLy8gdHJ1ZXxmYWxzZVxyXG5cdDwvY29kZT48L3ByZT5cclxuXHQgKiAgXHJcblx0ICogQHJldHVybiB7Qm9vbGVhbn0gICAgdHJ1ZXxmYWxzZVxyXG5cdCAqL1xyXG5cdCRQLndlZWtkYXkgPSBmdW5jdGlvbiAoKSB7XHJcblx0XHRpZiAodGhpcy5fbnRoKSB7XHJcblx0XHRcdHJldHVybiBkZihcIldlZWtkYXlcIikuY2FsbCh0aGlzKTtcclxuXHRcdH1cclxuXHRcdGlmICh0aGlzLl9tb3ZlKSB7XHJcblx0XHRcdHJldHVybiB0aGlzLmFkZFdlZWtkYXlzKHRoaXMuX29yaWVudCk7XHJcblx0XHR9XHJcblx0XHRpZiAodGhpcy5faXMpIHtcclxuXHRcdFx0dGhpcy5faXMgPSBmYWxzZTtcclxuXHRcdFx0cmV0dXJuICghdGhpcy5pcygpLnNhdCgpICYmICF0aGlzLmlzKCkuc3VuKCkpO1xyXG5cdFx0fVxyXG5cdFx0cmV0dXJuIGZhbHNlO1xyXG5cdH07XHJcblx0LyoqIFxyXG5cdCAqIERldGVybWluZXMgaWYgdGhlIGN1cnJlbnQgZGF0ZSBpcyBvbiB0aGUgd2Vla2VuZC4gVGhpcyBmdW5jdGlvbiBtdXN0IGJlIHByZWNlZGVkIGJ5IHRoZSAuaXMoKSBmdW5jdGlvbi5cclxuXHQgKiBFeGFtcGxlXHJcblx0PHByZT48Y29kZT5cclxuXHREYXRlLnRvZGF5KCkuaXMoKS53ZWVrZW5kKCk7IC8vIHRydWV8ZmFsc2VcclxuXHQ8L2NvZGU+PC9wcmU+XHJcblx0ICogIFxyXG5cdCAqIEByZXR1cm4ge0Jvb2xlYW59ICAgIHRydWV8ZmFsc2VcclxuXHQgKi9cclxuXHQkUC53ZWVrZW5kID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0aWYgKHRoaXMuX2lzKSB7XHJcblx0XHRcdHRoaXMuX2lzID0gZmFsc2U7XHJcblx0XHRcdHJldHVybiAodGhpcy5pcygpLnNhdCgpIHx8IHRoaXMuaXMoKS5zdW4oKSk7XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gZmFsc2U7XHJcblx0fTtcclxuXHJcblx0LyoqIFxyXG5cdCAqIFNldHMgdGhlIFRpbWUgb2YgdGhlIGN1cnJlbnQgRGF0ZSBpbnN0YW5jZS4gQSBzdHJpbmcgXCI2OjE1IHBtXCIgb3IgY29uZmlnIG9iamVjdCB7aG91cjoxOCwgbWludXRlOjE1fSBhcmUgYWNjZXB0ZWQuXHJcblx0ICogRXhhbXBsZVxyXG5cdDxwcmU+PGNvZGU+XHJcblx0Ly8gU2V0IHRpbWUgdG8gNjoxNXBtIHdpdGggYSBTdHJpbmdcclxuXHREYXRlLnRvZGF5KCkuYXQoXCI2OjE1cG1cIik7XHJcblxyXG5cdC8vIFNldCB0aW1lIHRvIDY6MTVwbSB3aXRoIGEgY29uZmlnIG9iamVjdFxyXG5cdERhdGUudG9kYXkoKS5hdCh7aG91cjoxOCwgbWludXRlOjE1fSk7XHJcblx0PC9jb2RlPjwvcHJlPlxyXG5cdCAqICBcclxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICBkYXRlXHJcblx0ICovXHJcblx0JFAuYXQgPSBmdW5jdGlvbiAodGltZSkge1xyXG5cdFx0cmV0dXJuICh0eXBlb2YgdGltZSA9PT0gXCJzdHJpbmdcIikgPyAkRC5wYXJzZSh0aGlzLnRvU3RyaW5nKFwiZFwiKSArIFwiIFwiICsgdGltZSkgOiB0aGlzLnNldCh0aW1lKTtcclxuXHR9O1xyXG5cdFx0XHJcblx0LyoqIFxyXG5cdCAqIENyZWF0ZXMgYSBuZXcgRGF0ZSgpIGFuZCBhZGRzIHRoaXMgKE51bWJlcikgdG8gdGhlIGRhdGUgYmFzZWQgb24gdGhlIHByZWNlZGluZyBkYXRlIGVsZW1lbnQgZnVuY3Rpb24gKGVnLiBzZWNvbmR8bWludXRlfGhvdXJ8ZGF5fG1vbnRofHllYXIpLlxyXG5cdCAqIEV4YW1wbGVcclxuXHQ8cHJlPjxjb2RlPlxyXG5cdC8vIFVuZGVjbGFyZWQgTnVtYmVycyBtdXN0IGJlIHdyYXBwZWQgd2l0aCBwYXJlbnRoZXNlcy4gUmVxdWlybWVudCBvZiBKYXZhU2NyaXB0LlxyXG5cdCgzKS5kYXlzKCkuZnJvbU5vdygpO1xyXG5cdCg2KS5tb250aHMoKS5mcm9tTm93KCk7XHJcblxyXG5cdC8vIERlY2xhcmVkIE51bWJlciB2YXJpYWJsZXMgZG8gbm90IHJlcXVpcmUgcGFyZW50aGVzZXMuIFxyXG5cdHZhciBuID0gNjtcclxuXHRuLm1vbnRocygpLmZyb21Ob3coKTtcclxuXHQ8L2NvZGU+PC9wcmU+XHJcblx0ICogIFxyXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIEEgbmV3IERhdGUgaW5zdGFuY2VcclxuXHQgKi9cclxuXHQkTi5mcm9tTm93ID0gJE4uYWZ0ZXIgPSBmdW5jdGlvbiAoZGF0ZSkge1xyXG5cdFx0dmFyIGMgPSB7fTtcclxuXHRcdGNbdGhpcy5fZGF0ZUVsZW1lbnRdID0gdGhpcztcclxuXHRcdHJldHVybiAoKCFkYXRlKSA/IG5ldyBEYXRlKCkgOiBkYXRlLmNsb25lKCkpLmFkZChjKTtcclxuXHR9O1xyXG5cclxuXHQvKiogXHJcblx0ICogQ3JlYXRlcyBhIG5ldyBEYXRlKCkgYW5kIHN1YnRyYWN0IHRoaXMgKE51bWJlcikgZnJvbSB0aGUgZGF0ZSBiYXNlZCBvbiB0aGUgcHJlY2VkaW5nIGRhdGUgZWxlbWVudCBmdW5jdGlvbiAoZWcuIHNlY29uZHxtaW51dGV8aG91cnxkYXl8bW9udGh8eWVhcikuXHJcblx0ICogRXhhbXBsZVxyXG5cdDxwcmU+PGNvZGU+XHJcblx0Ly8gVW5kZWNsYXJlZCBOdW1iZXJzIG11c3QgYmUgd3JhcHBlZCB3aXRoIHBhcmVudGhlc2VzLiBSZXF1aXJtZW50IG9mIEphdmFTY3JpcHQuXHJcblx0KDMpLmRheXMoKS5hZ28oKTtcclxuXHQoNikubW9udGhzKCkuYWdvKCk7XHJcblxyXG5cdC8vIERlY2xhcmVkIE51bWJlciB2YXJpYWJsZXMgZG8gbm90IHJlcXVpcmUgcGFyZW50aGVzZXMuIFxyXG5cdHZhciBuID0gNjtcclxuXHRuLm1vbnRocygpLmFnbygpO1xyXG5cdDwvY29kZT48L3ByZT5cclxuXHQgKiAgXHJcblx0ICogQHJldHVybiB7RGF0ZX0gICAgQSBuZXcgRGF0ZSBpbnN0YW5jZVxyXG5cdCAqL1xyXG5cdCROLmFnbyA9ICROLmJlZm9yZSA9IGZ1bmN0aW9uIChkYXRlKSB7XHJcblx0XHR2YXIgYyA9IHt9LFxyXG5cdFx0cyA9ICh0aGlzLl9kYXRlRWxlbWVudFt0aGlzLl9kYXRlRWxlbWVudC5sZW5ndGgtMV0gIT09IFwic1wiKSA/IHRoaXMuX2RhdGVFbGVtZW50ICsgXCJzXCIgOiB0aGlzLl9kYXRlRWxlbWVudDtcclxuXHRcdGNbc10gPSB0aGlzICogLTE7XHJcblx0XHRyZXR1cm4gKCghZGF0ZSkgPyBuZXcgRGF0ZSgpIDogZGF0ZS5jbG9uZSgpKS5hZGQoYyk7XHJcblx0fTtcclxuXHJcblx0Ly8gRG8gTk9UIG1vZGlmeSB0aGUgZm9sbG93aW5nIHN0cmluZyB0b2tlbnMuIFRoZXNlIHRva2VucyBhcmUgdXNlZCB0byBidWlsZCBkeW5hbWljIGZ1bmN0aW9ucy5cclxuXHQvLyBBbGwgY3VsdHVyZS1zcGVjaWZpYyBzdHJpbmdzIGNhbiBiZSBmb3VuZCBpbiB0aGUgQ3VsdHVyZUluZm8gZmlsZXMuXHJcblx0dmFyIGR4ID0gKFwic3VuZGF5IG1vbmRheSB0dWVzZGF5IHdlZG5lc2RheSB0aHVyc2RheSBmcmlkYXkgc2F0dXJkYXlcIikuc3BsaXQoL1xccy8pLFxyXG5cdFx0bXggPSAoXCJqYW51YXJ5IGZlYnJ1YXJ5IG1hcmNoIGFwcmlsIG1heSBqdW5lIGp1bHkgYXVndXN0IHNlcHRlbWJlciBvY3RvYmVyIG5vdmVtYmVyIGRlY2VtYmVyXCIpLnNwbGl0KC9cXHMvKSxcclxuXHRcdHB4ID0gKFwiTWlsbGlzZWNvbmQgU2Vjb25kIE1pbnV0ZSBIb3VyIERheSBXZWVrIE1vbnRoIFllYXIgUXVhcnRlciBXZWVrZGF5XCIpLnNwbGl0KC9cXHMvKSxcclxuXHRcdHB4ZiA9IChcIk1pbGxpc2Vjb25kcyBTZWNvbmRzIE1pbnV0ZXMgSG91cnMgRGF0ZSBXZWVrIE1vbnRoIEZ1bGxZZWFyIFF1YXJ0ZXJcIikuc3BsaXQoL1xccy8pLFxyXG5cdFx0bnRoID0gKFwiZmluYWwgZmlyc3Qgc2Vjb25kIHRoaXJkIGZvdXJ0aCBmaWZ0aFwiKS5zcGxpdCgvXFxzLyksXHJcblx0XHRkZTtcclxuXHJcbiAgIC8qKiBcclxuXHQgKiBSZXR1cm5zIGFuIG9iamVjdCBsaXRlcmFsIG9mIGFsbCB0aGUgZGF0ZSBwYXJ0cy5cclxuXHQgKiBFeGFtcGxlXHJcblx0PHByZT48Y29kZT5cclxuXHR2YXIgbyA9IG5ldyBEYXRlKCkudG9PYmplY3QoKTtcclxuXHRcclxuXHQvLyB7IHllYXI6IDIwMDgsIG1vbnRoOiA0LCB3ZWVrOiAyMCwgZGF5OiAxMywgaG91cjogMTgsIG1pbnV0ZTogOSwgc2Vjb25kOiAzMiwgbWlsbGlzZWNvbmQ6IDgxMiB9XHJcblx0XHJcblx0Ly8gVGhlIG9iamVjdCBwcm9wZXJ0aWVzIGNhbiBiZSByZWZlcmVuY2VkIGRpcmVjdGx5IGZyb20gdGhlIG9iamVjdC5cclxuXHRcclxuXHRhbGVydChvLmRheSk7ICAvLyBhbGVydHMgXCIxM1wiXHJcblx0YWxlcnQoby55ZWFyKTsgLy8gYWxlcnRzIFwiMjAwOFwiXHJcblx0PC9jb2RlPjwvcHJlPlxyXG5cdCAqICBcclxuXHQgKiBAcmV0dXJuIHtEYXRlfSAgICBBbiBvYmplY3QgbGl0ZXJhbCByZXByZXNlbnRpbmcgdGhlIG9yaWdpbmFsIGRhdGUgb2JqZWN0LlxyXG5cdCAqL1xyXG5cdCRQLnRvT2JqZWN0ID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0dmFyIG8gPSB7fTtcclxuXHRcdGZvciAodmFyIGkgPSAwOyBpIDwgcHgubGVuZ3RoOyBpKyspIHtcclxuXHRcdFx0aWYgKHRoaXNbXCJnZXRcIiArIHB4ZltpXV0pIHtcclxuXHRcdFx0XHRvW3B4W2ldLnRvTG93ZXJDYXNlKCldID0gdGhpc1tcImdldFwiICsgcHhmW2ldXSgpO1xyXG5cdFx0XHR9XHJcblx0XHR9XHJcblx0XHRyZXR1cm4gbztcclxuXHR9O1xyXG4gICBcclxuICAgLyoqIFxyXG5cdCAqIFJldHVybnMgYSBkYXRlIGNyZWF0ZWQgZnJvbSBhbiBvYmplY3QgbGl0ZXJhbC4gSWdub3JlcyB0aGUgLndlZWsgcHJvcGVydHkgaWYgc2V0IGluIHRoZSBjb25maWcuIFxyXG5cdCAqIEV4YW1wbGVcclxuXHQ8cHJlPjxjb2RlPlxyXG5cdHZhciBvID0gbmV3IERhdGUoKS50b09iamVjdCgpO1xyXG5cdFxyXG5cdHJldHVybiBEYXRlLmZyb21PYmplY3Qobyk7IC8vIHdpbGwgcmV0dXJuIHRoZSBzYW1lIGRhdGUuIFxyXG5cclxuXHR2YXIgbzIgPSB7bW9udGg6IDEsIGRheTogMjAsIGhvdXI6IDE4fTsgLy8gYmlydGhkYXkgcGFydHkhXHJcblx0RGF0ZS5mcm9tT2JqZWN0KG8yKTtcclxuXHQ8L2NvZGU+PC9wcmU+XHJcblx0ICogIFxyXG5cdCAqIEByZXR1cm4ge0RhdGV9ICAgIEFuIG9iamVjdCBsaXRlcmFsIHJlcHJlc2VudGluZyB0aGUgb3JpZ2luYWwgZGF0ZSBvYmplY3QuXHJcblx0ICovXHJcblx0JEQuZnJvbU9iamVjdCA9IGZ1bmN0aW9uKGNvbmZpZykge1xyXG5cdFx0Y29uZmlnLndlZWsgPSBudWxsO1xyXG5cdFx0cmV0dXJuIERhdGUudG9kYXkoKS5zZXQoY29uZmlnKTtcclxuXHR9O1xyXG5cdFx0XHJcblx0Ly8gQ3JlYXRlIGRheSBuYW1lIGZ1bmN0aW9ucyBhbmQgYWJicmV2aWF0ZWQgZGF5IG5hbWUgZnVuY3Rpb25zIChlZy4gbW9uZGF5KCksIGZyaWRheSgpLCBmcmkoKSkuXHJcblx0XHJcblx0dmFyIGRmID0gZnVuY3Rpb24gKG4pIHtcclxuXHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XHJcblx0XHRcdGlmICh0aGlzLl9pcykge1xyXG5cdFx0XHRcdHRoaXMuX2lzID0gZmFsc2U7XHJcblx0XHRcdFx0cmV0dXJuIHRoaXMuZ2V0RGF5KCkgPT09IG47XHJcblx0XHRcdH1cclxuXHRcdFx0aWYgKHRoaXMuX21vdmUpIHsgdGhpcy5fbW92ZSA9IG51bGw7IH1cclxuXHRcdFx0aWYgKHRoaXMuX250aCAhPT0gbnVsbCkge1xyXG5cdFx0XHRcdC8vIElmIHRoZSAuc2Vjb25kKCkgZnVuY3Rpb24gd2FzIGNhbGxlZCBlYXJsaWVyLCByZW1vdmUgdGhlIF9vcmllbnQgXHJcblx0XHRcdFx0Ly8gZnJvbSB0aGUgZGF0ZSwgYW5kIHRoZW4gY29udGludWUuXHJcblx0XHRcdFx0Ly8gVGhpcyBpcyByZXF1aXJlZCBiZWNhdXNlICdzZWNvbmQnIGNhbiBiZSB1c2VkIGluIHR3byBkaWZmZXJlbnQgY29udGV4dC5cclxuXHRcdFx0XHQvLyBcclxuXHRcdFx0XHQvLyBFeGFtcGxlXHJcblx0XHRcdFx0Ly9cclxuXHRcdFx0XHQvLyAgIERhdGUudG9kYXkoKS5hZGQoMSkuc2Vjb25kKCk7XHJcblx0XHRcdFx0Ly8gICBEYXRlLm1hcmNoKCkuc2Vjb25kKCkubW9uZGF5KCk7XHJcblx0XHRcdFx0Ly8gXHJcblx0XHRcdFx0Ly8gVGhpbmdzIGdldCBjcmF6eSB3aXRoIHRoZSBmb2xsb3dpbmcuLi5cclxuXHRcdFx0XHQvLyAgIERhdGUubWFyY2goKS5hZGQoMSkuc2Vjb25kKCkuc2Vjb25kKCkubW9uZGF5KCk7IC8vIGJ1dCBpdCB3b3JrcyEhXHJcblx0XHRcdFx0Ly8gIFxyXG5cdFx0XHRcdGlmICh0aGlzLl9pc1NlY29uZCkge1xyXG5cdFx0XHRcdFx0dGhpcy5hZGRTZWNvbmRzKHRoaXMuX29yaWVudCAqIC0xKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0Ly8gbWFrZSBzdXJlIHdlIHJlc2V0IF9pc1NlY29uZFxyXG5cdFx0XHRcdHRoaXMuX2lzU2Vjb25kID0gZmFsc2U7XHJcblxyXG5cdFx0XHRcdHZhciBudGVtcCA9IHRoaXMuX250aDtcclxuXHRcdFx0XHR0aGlzLl9udGggPSBudWxsO1xyXG5cdFx0XHRcdHZhciB0ZW1wID0gdGhpcy5jbG9uZSgpLm1vdmVUb0xhc3REYXlPZk1vbnRoKCk7XHJcblx0XHRcdFx0dGhpcy5tb3ZlVG9OdGhPY2N1cnJlbmNlKG4sIG50ZW1wKTtcclxuXHRcdFx0XHRpZiAodGhpcyA+IHRlbXApIHtcclxuXHRcdFx0XHRcdHRocm93IG5ldyBSYW5nZUVycm9yKCRELmdldERheU5hbWUobikgKyBcIiBkb2VzIG5vdCBvY2N1ciBcIiArIG50ZW1wICsgXCIgdGltZXMgaW4gdGhlIG1vbnRoIG9mIFwiICsgJEQuZ2V0TW9udGhOYW1lKHRlbXAuZ2V0TW9udGgoKSkgKyBcIiBcIiArIHRlbXAuZ2V0RnVsbFllYXIoKSArIFwiLlwiKTtcclxuXHRcdFx0XHR9XHJcblx0XHRcdFx0cmV0dXJuIHRoaXM7XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIHRoaXMubW92ZVRvRGF5T2ZXZWVrKG4sIHRoaXMuX29yaWVudCk7XHJcblx0XHR9O1xyXG5cdH07XHJcblx0XHJcblx0dmFyIHNkZiA9IGZ1bmN0aW9uIChuKSB7XHJcblx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHR2YXIgdCA9ICRELnRvZGF5KCksIHNoaWZ0ID0gbiAtIHQuZ2V0RGF5KCk7XHJcblx0XHRcdGlmIChuID09PSAwICYmIERhdGUuQ3VsdHVyZUluZm8uZmlyc3REYXlPZldlZWsgPT09IDEgJiYgdC5nZXREYXkoKSAhPT0gMCkge1xyXG5cdFx0XHRcdHNoaWZ0ID0gc2hpZnQgKyA3O1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0LmFkZERheXMoc2hpZnQpO1xyXG5cdFx0fTtcclxuXHR9O1xyXG5cdFxyXG5cclxuXHRcclxuXHQvLyBDcmVhdGUgbW9udGggbmFtZSBmdW5jdGlvbnMgYW5kIGFiYnJldmlhdGVkIG1vbnRoIG5hbWUgZnVuY3Rpb25zIChlZy4gamFudWFyeSgpLCBtYXJjaCgpLCBtYXIoKSkuXHJcblx0dmFyIG1vbnRoX2luc3RhbmNlX2Z1bmN0aW9ucyA9IGZ1bmN0aW9uIChuKSB7XHJcblx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRpZiAodGhpcy5faXMpIHtcclxuXHRcdFx0XHR0aGlzLl9pcyA9IGZhbHNlO1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLmdldE1vbnRoKCkgPT09IG47XHJcblx0XHRcdH1cclxuXHRcdFx0cmV0dXJuIHRoaXMubW92ZVRvTW9udGgobiwgdGhpcy5fb3JpZW50KTtcclxuXHRcdH07XHJcblx0fTtcclxuXHRcclxuXHR2YXIgbW9udGhfc3RhdGljX2Z1bmN0aW9ucyA9IGZ1bmN0aW9uIChuKSB7XHJcblx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRyZXR1cm4gJEQudG9kYXkoKS5zZXQoeyBtb250aDogbiwgZGF5OiAxIH0pO1xyXG5cdFx0fTtcclxuXHR9O1xyXG5cdFxyXG5cdHZhciBwcm9jZXNzVGVybXMgPSBmdW5jdGlvbiAobmFtZXMsIHN0YXRpY0Z1bmMsIGluc3RhbmNlRnVuYykge1xyXG5cdFx0Zm9yICh2YXIgaSA9IDA7IGkgPCBuYW1lcy5sZW5ndGg7IGkrKykge1xyXG5cdFx0XHQvLyBDcmVhdGUgY29uc3RhbnQgc3RhdGljIE5hbWUgdmFyaWFibGVzLlxyXG5cdFx0XHQkRFtuYW1lc1tpXS50b1VwcGVyQ2FzZSgpXSA9ICREW25hbWVzW2ldLnRvVXBwZXJDYXNlKCkuc3Vic3RyaW5nKDAsIDMpXSA9IGk7XHJcblx0XHRcdC8vIENyZWF0ZSBOYW1lIGZ1bmN0aW9ucy5cclxuXHRcdFx0JERbbmFtZXNbaV1dID0gJERbbmFtZXNbaV0uc3Vic3RyaW5nKDAsIDMpXSA9IHN0YXRpY0Z1bmMoaSk7XHJcblx0XHRcdC8vIENyZWF0ZSBOYW1lIGluc3RhbmNlIGZ1bmN0aW9ucy5cclxuXHRcdFx0JFBbbmFtZXNbaV1dID0gJFBbbmFtZXNbaV0uc3Vic3RyaW5nKDAsIDMpXSA9IGluc3RhbmNlRnVuYyhpKTtcclxuXHRcdH1cclxuXHJcblx0fTtcclxuXHJcblx0cHJvY2Vzc1Rlcm1zKGR4LCBzZGYsIGRmKTtcclxuXHRwcm9jZXNzVGVybXMobXgsIG1vbnRoX3N0YXRpY19mdW5jdGlvbnMsIG1vbnRoX2luc3RhbmNlX2Z1bmN0aW9ucyk7XHJcblx0XHJcblx0Ly8gQ3JlYXRlIGRhdGUgZWxlbWVudCBmdW5jdGlvbnMgYW5kIHBsdXJhbCBkYXRlIGVsZW1lbnQgZnVuY3Rpb25zIHVzZWQgd2l0aCBEYXRlIChlZy4gZGF5KCksIGRheXMoKSwgbW9udGhzKCkpLlxyXG5cdHZhciBlZiA9IGZ1bmN0aW9uIChqKSB7XHJcblx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHQvLyBpZiB0aGUgLnNlY29uZCgpIGZ1bmN0aW9uIHdhcyBjYWxsZWQgZWFybGllciwgdGhlIF9vcmllbnQgXHJcblx0XHRcdC8vIGhhcyBhbHJlYWQgYmVlbiBhZGRlZC4gSnVzdCByZXR1cm4gdGhpcyBhbmQgcmVzZXQgX2lzU2Vjb25kLlxyXG5cdFx0XHRpZiAodGhpcy5faXNTZWNvbmQpIHtcclxuXHRcdFx0XHR0aGlzLl9pc1NlY29uZCA9IGZhbHNlO1xyXG5cdFx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0XHR9XHJcblxyXG5cdFx0XHRpZiAodGhpcy5fc2FtZSkge1xyXG5cdFx0XHRcdHRoaXMuX3NhbWUgPSB0aGlzLl9pcyA9IGZhbHNlO1xyXG5cdFx0XHRcdHZhciBvMSA9IHRoaXMudG9PYmplY3QoKSxcclxuXHRcdFx0XHRcdG8yID0gKGFyZ3VtZW50c1swXSB8fCBuZXcgRGF0ZSgpKS50b09iamVjdCgpLFxyXG5cdFx0XHRcdFx0diA9IFwiXCIsXHJcblx0XHRcdFx0XHRrID0gai50b0xvd2VyQ2FzZSgpO1xyXG5cclxuXHRcdFx0XHQvLyB0aGUgc3Vic3RyIHRyaWNrIHdpdGggLTEgZG9lc24ndCB3b3JrIGluIElFOCBvciBsZXNzXHJcblx0XHRcdFx0ayA9IChrW2subGVuZ3RoLTFdID09PSBcInNcIikgPyBrLnN1YnN0cmluZygwLGsubGVuZ3RoLTEpIDogaztcclxuXHRcdFx0XHRcdFxyXG5cdFx0XHRcdGZvciAodmFyIG0gPSAocHgubGVuZ3RoIC0gMSk7IG0gPiAtMTsgbS0tKSB7XHJcblx0XHRcdFx0XHR2ID0gcHhbbV0udG9Mb3dlckNhc2UoKTtcclxuXHRcdFx0XHRcdGlmIChvMVt2XSAhPT0gbzJbdl0pIHtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIGZhbHNlO1xyXG5cdFx0XHRcdFx0fVxyXG5cdFx0XHRcdFx0aWYgKGsgPT09IHYpIHtcclxuXHRcdFx0XHRcdFx0YnJlYWs7XHJcblx0XHRcdFx0XHR9XHJcblx0XHRcdFx0fVxyXG5cdFx0XHRcdHJldHVybiB0cnVlO1xyXG5cdFx0XHR9XHJcblx0XHRcdFxyXG5cdFx0XHRpZiAoai5zdWJzdHJpbmcoai5sZW5ndGggLSAxKSAhPT0gXCJzXCIpIHtcclxuXHRcdFx0XHRqICs9IFwic1wiO1xyXG5cdFx0XHR9XHJcblx0XHRcdGlmICh0aGlzLl9tb3ZlKSB7IHRoaXMuX21vdmUgPSBudWxsOyB9XHJcblx0XHRcdHJldHVybiB0aGlzW1wiYWRkXCIgKyBqXSh0aGlzLl9vcmllbnQpO1xyXG5cdFx0fTtcclxuXHR9O1xyXG5cdFxyXG5cdFxyXG5cdHZhciBuZiA9IGZ1bmN0aW9uIChuKSB7XHJcblx0XHRyZXR1cm4gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHR0aGlzLl9kYXRlRWxlbWVudCA9IG47XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fTtcclxuXHR9O1xyXG4gICBcclxuXHRmb3IgKHZhciBrID0gMDsgayA8IHB4Lmxlbmd0aDsgaysrKSB7XHJcblx0XHRkZSA9IHB4W2tdLnRvTG93ZXJDYXNlKCk7XHJcblx0XHRpZihkZSAhPT0gXCJ3ZWVrZGF5XCIpIHtcclxuXHRcdFx0Ly8gQ3JlYXRlIGRhdGUgZWxlbWVudCBmdW5jdGlvbnMgYW5kIHBsdXJhbCBkYXRlIGVsZW1lbnQgZnVuY3Rpb25zIHVzZWQgd2l0aCBEYXRlIChlZy4gZGF5KCksIGRheXMoKSwgbW9udGhzKCkpLlxyXG5cdFx0XHQkUFtkZV0gPSAkUFtkZSArIFwic1wiXSA9IGVmKHB4W2tdKTtcclxuXHRcdFx0XHJcblx0XHRcdC8vIENyZWF0ZSBkYXRlIGVsZW1lbnQgZnVuY3Rpb25zIGFuZCBwbHVyYWwgZGF0ZSBlbGVtZW50IGZ1bmN0aW9ucyB1c2VkIHdpdGggTnVtYmVyIChlZy4gZGF5KCksIGRheXMoKSwgbW9udGhzKCkpLlxyXG5cdFx0XHQkTltkZV0gPSAkTltkZSArIFwic1wiXSA9IG5mKGRlICsgXCJzXCIpO1xyXG5cdFx0fVxyXG5cdH1cclxuXHRcclxuXHQkUC5fc3MgPSBlZihcIlNlY29uZFwiKTtcclxuXHRcclxuXHR2YXIgbnRoZm4gPSBmdW5jdGlvbiAobikge1xyXG5cdFx0cmV0dXJuIGZ1bmN0aW9uIChkYXlPZldlZWspIHtcclxuXHRcdFx0aWYgKHRoaXMuX3NhbWUpIHtcclxuXHRcdFx0XHRyZXR1cm4gdGhpcy5fc3MoYXJndW1lbnRzWzBdKTtcclxuXHRcdFx0fVxyXG5cdFx0XHRpZiAoZGF5T2ZXZWVrIHx8IGRheU9mV2VlayA9PT0gMCkge1xyXG5cdFx0XHRcdHJldHVybiB0aGlzLm1vdmVUb050aE9jY3VycmVuY2UoZGF5T2ZXZWVrLCBuKTtcclxuXHRcdFx0fVxyXG5cdFx0XHR0aGlzLl9udGggPSBuO1xyXG5cclxuXHRcdFx0Ly8gaWYgdGhlIG9wZXJhdG9yIGlzICdzZWNvbmQnIGFkZCB0aGUgX29yaWVudCwgdGhlbiBkZWFsIHdpdGggaXQgbGF0ZXIuLi5cclxuXHRcdFx0aWYgKG4gPT09IDIgJiYgKGRheU9mV2VlayA9PT0gdW5kZWZpbmVkIHx8IGRheU9mV2VlayA9PT0gbnVsbCkpIHtcclxuXHRcdFx0XHR0aGlzLl9pc1NlY29uZCA9IHRydWU7XHJcblx0XHRcdFx0cmV0dXJuIHRoaXMuYWRkU2Vjb25kcyh0aGlzLl9vcmllbnQpO1xyXG5cdFx0XHR9XHJcblx0XHRcdHJldHVybiB0aGlzO1xyXG5cdFx0fTtcclxuXHR9O1xyXG5cclxuXHRmb3IgKHZhciBsID0gMDsgbCA8IG50aC5sZW5ndGg7IGwrKykge1xyXG5cdFx0JFBbbnRoW2xdXSA9IChsID09PSAwKSA/IG50aGZuKC0xKSA6IG50aGZuKGwpO1xyXG5cdH1cclxufSgpKTtcclxuIiwiKGZ1bmN0aW9uICgpIHtcblx0XCJ1c2Ugc3RyaWN0XCI7XG5cdHZhciBhdHRycyA9IFtcInllYXJzXCIsIFwibW9udGhzXCIsIFwiZGF5c1wiLCBcImhvdXJzXCIsIFwibWludXRlc1wiLCBcInNlY29uZHNcIiwgXCJtaWxsaXNlY29uZHNcIl07XG5cdHZhciBnRm4gPSBmdW5jdGlvbiAoYXR0cikge1xuXHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRyZXR1cm4gdGhpc1thdHRyXTtcblx0XHR9O1xuXHR9O1xuXHRcblx0dmFyIHNGbiA9IGZ1bmN0aW9uIChhdHRyKSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uICh2YWwpIHtcblx0XHRcdHRoaXNbYXR0cl0gPSB2YWw7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9O1xuXHR9O1xuXHR2YXIgYWRkU2V0RnVuY3MgPSBmdW5jdGlvbiAoY29udGV4dCwgYXR0cnMpIHtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGF0dHJzLmxlbmd0aCA7IGkrKykge1xuXHRcdFx0dmFyICRhID0gYXR0cnNbaV0sICRiID0gJGEuc2xpY2UoMCwgMSkudG9VcHBlckNhc2UoKSArICRhLnNsaWNlKDEpO1xuXHRcdFx0Y29udGV4dC5wcm90b3R5cGVbJGFdID0gMDtcblx0XHRcdGNvbnRleHQucHJvdG90eXBlW1wiZ2V0XCIgKyAkYl0gPSBnRm4oJGEpO1xuXHRcdFx0Y29udGV4dC5wcm90b3R5cGVbXCJzZXRcIiArICRiXSA9IHNGbigkYSk7XG5cdFx0fVxuXHR9O1xuXG5cdHZhciBzZXRNb250aHNBbmRZZWFycyA9IGZ1bmN0aW9uIChvcmllbnQsIGQxLCBkMiwgY29udGV4dCkge1xuXHRcdGZ1bmN0aW9uIGluYygpIHtcblx0XHRcdGQxLmFkZE1vbnRocygtb3JpZW50KTtcblx0XHRcdGNvbnRleHQubW9udGhzKys7XG5cdFx0XHRpZiAoY29udGV4dC5tb250aHMgPT09IDEyKSB7XG5cdFx0XHRcdGNvbnRleHQueWVhcnMrKztcblx0XHRcdFx0Y29udGV4dC5tb250aHMgPSAwO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRpZiAob3JpZW50ID09PSArMSkge1xuXHRcdFx0d2hpbGUgKGQxID4gZDIpIHtcblx0XHRcdFx0aW5jKCk7XG5cdFx0XHR9XG5cdFx0fSBlbHNlIHtcblx0XHRcdHdoaWxlIChkMSA8IGQyKSB7XG5cdFx0XHRcdGluYygpO1xuXHRcdFx0fVxuXHRcdH1cblx0XHRjb250ZXh0Lm1vbnRocy0tO1xuXHRcdGNvbnRleHQubW9udGhzICo9IG9yaWVudDtcblx0XHRjb250ZXh0LnllYXJzICo9IG9yaWVudDtcblx0fTtcblxuXHR2YXIgYWRqdXN0Rm9yRFNUID0gZnVuY3Rpb24ob3JpZW50LCBzdGFydERhdGUsIGVuZERhdGUpIHtcblx0XHR2YXIgaGFzRFNUTWlzbWF0Y2ggPSAoZmFsc2UgPT09IChzdGFydERhdGUuaXNEYXlsaWdodFNhdmluZ1RpbWUoKSA9PT0gZW5kRGF0ZS5pc0RheWxpZ2h0U2F2aW5nVGltZSgpKSk7XG5cdFx0aWYgKGhhc0RTVE1pc21hdGNoICYmIG9yaWVudCA9PT0gMSkge1xuXHRcdFx0c3RhcnREYXRlLmFkZEhvdXJzKC0xKTtcblx0XHR9IGVsc2UgaWYgKGhhc0RTVE1pc21hdGNoKSB7XG5cdFx0XHRzdGFydERhdGUuYWRkSG91cnMoMSk7XG5cdFx0fVxuXHR9O1xuXHQvKipcblx0ICogVGltZVBlcmlvZChzdGFydERhdGUsIGVuZERhdGUpO1xuXHQgKiBUaW1lUGVyaW9kKHllYXJzLCBtb250aHMsIGRheXMsIGhvdXJzLCBtaW51dGVzLCBzZWNvbmRzLCBtaWxsaXNlY29uZHMpO1xuXHQgKi9cblx0dmFyIFRpbWVQZXJpb2QgPSBmdW5jdGlvbiAoeWVhcnMsIG1vbnRocywgZGF5cywgaG91cnMsIG1pbnV0ZXMsIHNlY29uZHMsIG1pbGxpc2Vjb25kcykge1xuXHRcdGlmIChhcmd1bWVudHMubGVuZ3RoID09PSA3KSB7XG5cdFx0XHR0aGlzLnNldCh5ZWFycywgbW9udGhzLCBkYXlzLCBob3VycywgbWludXRlcywgc2Vjb25kcywgbWlsbGlzZWNvbmRzKTtcblx0XHR9IGVsc2UgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDIgJiYgYXJndW1lbnRzWzBdIGluc3RhbmNlb2YgRGF0ZSAmJiBhcmd1bWVudHNbMV0gaW5zdGFuY2VvZiBEYXRlKSB7XG5cdFx0XHR2YXIgc3RhcnREYXRlID0gYXJndW1lbnRzWzBdLmNsb25lKCk7XG5cdFx0XHR2YXIgZW5kRGF0ZSA9IGFyZ3VtZW50c1sxXS5jbG9uZSgpO1xuXHRcdFx0dmFyIG9yaWVudCA9IChzdGFydERhdGUgPiBlbmREYXRlKSA/ICsxIDogLTE7XG5cdFx0XHR0aGlzLmRhdGVzID0ge1xuXHRcdFx0XHRzdGFydDogYXJndW1lbnRzWzBdLmNsb25lKCksXG5cdFx0XHRcdGVuZDogYXJndW1lbnRzWzFdLmNsb25lKClcblx0XHRcdH07XG5cblx0XHRcdHNldE1vbnRoc0FuZFllYXJzKG9yaWVudCwgc3RhcnREYXRlLCBlbmREYXRlLCB0aGlzKTtcblx0XHRcdGFkanVzdEZvckRTVChvcmllbnQsIHN0YXJ0RGF0ZSwgZW5kRGF0ZSk7XG5cdFx0XHQvLyAvLyBUT0RPIC0gYWRqdXN0IGZvciBEU1Rcblx0XHRcdHZhciBkaWZmID0gZW5kRGF0ZSAtIHN0YXJ0RGF0ZTtcblx0XHRcdGlmIChkaWZmICE9PSAwKSB7XG5cdFx0XHRcdHZhciB0cyA9IG5ldyBUaW1lU3BhbihkaWZmKTtcblx0XHRcdFx0dGhpcy5zZXQodGhpcy55ZWFycywgdGhpcy5tb250aHMsIHRzLmdldERheXMoKSwgdHMuZ2V0SG91cnMoKSwgdHMuZ2V0TWludXRlcygpLCB0cy5nZXRTZWNvbmRzKCksIHRzLmdldE1pbGxpc2Vjb25kcygpKTtcblx0XHRcdH1cblx0XHR9XG5cdFx0cmV0dXJuIHRoaXM7XG5cdH07XG5cdC8vIGNyZWF0ZSBhbGwgdGhlIHNldCBmdW5jdGlvbnMuXG5cdGFkZFNldEZ1bmNzKFRpbWVQZXJpb2QsIGF0dHJzKTtcblx0VGltZVBlcmlvZC5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKHllYXJzLCBtb250aHMsIGRheXMsIGhvdXJzLCBtaW51dGVzLCBzZWNvbmRzLCBtaWxsaXNlY29uZHMpe1xuXHRcdHRoaXMuc2V0WWVhcnMoeWVhcnMgfHwgdGhpcy5nZXRZZWFycygpKTtcblx0XHR0aGlzLnNldE1vbnRocyhtb250aHMgfHwgdGhpcy5nZXRNb250aHMoKSk7XG5cdFx0dGhpcy5zZXREYXlzKGRheXMgfHwgdGhpcy5nZXREYXlzKCkpO1xuXHRcdHRoaXMuc2V0SG91cnMoaG91cnMgfHwgdGhpcy5nZXRIb3VycygpKTtcblx0XHR0aGlzLnNldE1pbnV0ZXMobWludXRlcyB8fCB0aGlzLmdldE1pbnV0ZXMoKSk7XG5cdFx0dGhpcy5zZXRTZWNvbmRzKHNlY29uZHMgfHwgdGhpcy5nZXRTZWNvbmRzKCkpO1xuXHRcdHRoaXMuc2V0TWlsbGlzZWNvbmRzKG1pbGxpc2Vjb25kcyB8fCB0aGlzLmdldE1pbGxpc2Vjb25kcygpKTtcblx0fTtcblxuXHREYXRlLlRpbWVQZXJpb2QgPSBUaW1lUGVyaW9kO1xuXG5cdGlmICh0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiKSB7XG5cdFx0Ly8ga2VlcGluZyBBUEkgY29tcGF0aWJsZSBmb3IgdjEueCBcblx0XHR3aW5kb3cuVGltZVBlcmlvZCA9IFRpbWVQZXJpb2Q7XG5cdH1cbn0oKSk7IiwiKGZ1bmN0aW9uICgpIHtcblx0XCJ1c2Ugc3RyaWN0XCI7XG5cdHZhciBnRm4gPSBmdW5jdGlvbiAoYXR0cikge1xuXHRcdHJldHVybiBmdW5jdGlvbiAoKSB7XG5cdFx0XHRyZXR1cm4gdGhpc1thdHRyXTtcblx0XHR9O1xuXHR9O1xuXHRcblx0dmFyIHNGbiA9IGZ1bmN0aW9uIChhdHRyKSB7XG5cdFx0cmV0dXJuIGZ1bmN0aW9uICh2YWwpIHtcblx0XHRcdHRoaXNbYXR0cl0gPSB2YWw7XG5cdFx0XHRyZXR1cm4gdGhpcztcblx0XHR9O1xuXHR9O1xuXHR2YXIgYXR0cnMgPSBbXCJ5ZWFyc1wiLCBcIm1vbnRoc1wiLCBcImRheXNcIiwgXCJob3Vyc1wiLCBcIm1pbnV0ZXNcIiwgXCJzZWNvbmRzXCIsIFwibWlsbGlzZWNvbmRzXCJdO1xuXHR2YXIgYWRkU2V0RnVuY3MgPSBmdW5jdGlvbiAoY29udGV4dCwgYXR0cnMpIHtcblx0XHRmb3IgKHZhciBpID0gMDsgaSA8IGF0dHJzLmxlbmd0aCA7IGkrKykge1xuXHRcdFx0dmFyICRhID0gYXR0cnNbaV0sICRiID0gJGEuc2xpY2UoMCwgMSkudG9VcHBlckNhc2UoKSArICRhLnNsaWNlKDEpO1xuXHRcdFx0Y29udGV4dC5wcm90b3R5cGVbJGFdID0gMDtcblx0XHRcdGNvbnRleHQucHJvdG90eXBlW1wiZ2V0XCIgKyAkYl0gPSBnRm4oJGEpO1xuXHRcdFx0Y29udGV4dC5wcm90b3R5cGVbXCJzZXRcIiArICRiXSA9IHNGbigkYSk7XG5cdFx0fVxuXHR9O1xuXHQvKipcblx0ICogbmV3IFRpbWVTcGFuKG1pbGxpc2Vjb25kcyk7XG5cdCAqIG5ldyBUaW1lU3BhbihkYXlzLCBob3VycywgbWludXRlcywgc2Vjb25kcyk7XG5cdCAqIG5ldyBUaW1lU3BhbihkYXlzLCBob3VycywgbWludXRlcywgc2Vjb25kcywgbWlsbGlzZWNvbmRzKTtcblx0ICovXG5cdHZhciBUaW1lU3BhbiA9IGZ1bmN0aW9uIChkYXlzLCBob3VycywgbWludXRlcywgc2Vjb25kcywgbWlsbGlzZWNvbmRzKSB7XG5cdFx0aWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDEgJiYgdHlwZW9mIGRheXMgPT09IFwibnVtYmVyXCIpIHtcblx0XHRcdHZhciBvcmllbnQgPSAoZGF5cyA8IDApID8gLTEgOiArMTtcblx0XHRcdHZhciBtaWxsc0xlZnQgPSBNYXRoLmFicyhkYXlzKTtcblx0XHRcdHRoaXMuc2V0RGF5cyhNYXRoLmZsb29yKG1pbGxzTGVmdCAvIDg2NDAwMDAwKSAqIG9yaWVudCk7XG5cdFx0XHRtaWxsc0xlZnQgPSBtaWxsc0xlZnQgJSA4NjQwMDAwMDtcblx0XHRcdHRoaXMuc2V0SG91cnMoTWF0aC5mbG9vcihtaWxsc0xlZnQgLyAzNjAwMDAwKSAqIG9yaWVudCk7XG5cdFx0XHRtaWxsc0xlZnQgPSBtaWxsc0xlZnQgJSAzNjAwMDAwO1xuXHRcdFx0dGhpcy5zZXRNaW51dGVzKE1hdGguZmxvb3IobWlsbHNMZWZ0IC8gNjAwMDApICogb3JpZW50KTtcblx0XHRcdG1pbGxzTGVmdCA9IG1pbGxzTGVmdCAlIDYwMDAwO1xuXHRcdFx0dGhpcy5zZXRTZWNvbmRzKE1hdGguZmxvb3IobWlsbHNMZWZ0IC8gMTAwMCkgKiBvcmllbnQpO1xuXHRcdFx0bWlsbHNMZWZ0ID0gbWlsbHNMZWZ0ICUgMTAwMDtcblx0XHRcdHRoaXMuc2V0TWlsbGlzZWNvbmRzKG1pbGxzTGVmdCAqIG9yaWVudCk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHRoaXMuc2V0KGRheXMsIGhvdXJzLCBtaW51dGVzLCBzZWNvbmRzLCBtaWxsaXNlY29uZHMpO1xuXHRcdH1cblxuXHRcdHRoaXMuZ2V0VG90YWxNaWxsaXNlY29uZHMgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRyZXR1cm5cdCh0aGlzLmdldERheXMoKSAqIDg2NDAwMDAwKSArXG5cdFx0XHRcdFx0KHRoaXMuZ2V0SG91cnMoKSAqIDM2MDAwMDApICtcblx0XHRcdFx0XHQodGhpcy5nZXRNaW51dGVzKCkgKiA2MDAwMCkgK1xuXHRcdFx0XHRcdCh0aGlzLmdldFNlY29uZHMoKSAqIDEwMDApO1xuXHRcdH07XG5cdFx0XG5cdFx0dGhpcy5jb21wYXJlVG8gPSBmdW5jdGlvbiAodGltZSkge1xuXHRcdFx0dmFyIHQxID0gbmV3IERhdGUoMTk3MCwgMSwgMSwgdGhpcy5nZXRIb3VycygpLCB0aGlzLmdldE1pbnV0ZXMoKSwgdGhpcy5nZXRTZWNvbmRzKCkpLCB0Mjtcblx0XHRcdGlmICh0aW1lID09PSBudWxsKSB7XG5cdFx0XHRcdHQyID0gbmV3IERhdGUoMTk3MCwgMSwgMSwgMCwgMCwgMCk7XG5cdFx0XHR9XG5cdFx0XHRlbHNlIHtcblx0XHRcdFx0dDIgPSBuZXcgRGF0ZSgxOTcwLCAxLCAxLCB0aW1lLmdldEhvdXJzKCksIHRpbWUuZ2V0TWludXRlcygpLCB0aW1lLmdldFNlY29uZHMoKSk7XG5cdFx0XHR9XG5cdFx0XHRyZXR1cm4gKHQxIDwgdDIpID8gLTEgOiAodDEgPiB0MikgPyAxIDogMDtcblx0XHR9O1xuXG5cdFx0dGhpcy5lcXVhbHMgPSBmdW5jdGlvbiAodGltZSkge1xuXHRcdFx0cmV0dXJuICh0aGlzLmNvbXBhcmVUbyh0aW1lKSA9PT0gMCk7XG5cdFx0fTtcblxuXHRcdHRoaXMuYWRkID0gZnVuY3Rpb24gKHRpbWUpIHtcblx0XHRcdHJldHVybiAodGltZSA9PT0gbnVsbCkgPyB0aGlzIDogdGhpcy5hZGRTZWNvbmRzKHRpbWUuZ2V0VG90YWxNaWxsaXNlY29uZHMoKSAvIDEwMDApO1xuXHRcdH07XG5cblx0XHR0aGlzLnN1YnRyYWN0ID0gZnVuY3Rpb24gKHRpbWUpIHtcblx0XHRcdHJldHVybiAodGltZSA9PT0gbnVsbCkgPyB0aGlzIDogdGhpcy5hZGRTZWNvbmRzKC10aW1lLmdldFRvdGFsTWlsbGlzZWNvbmRzKCkgLyAxMDAwKTtcblx0XHR9O1xuXG5cdFx0dGhpcy5hZGREYXlzID0gZnVuY3Rpb24gKG4pIHtcblx0XHRcdHJldHVybiBuZXcgVGltZVNwYW4odGhpcy5nZXRUb3RhbE1pbGxpc2Vjb25kcygpICsgKG4gKiA4NjQwMDAwMCkpO1xuXHRcdH07XG5cblx0XHR0aGlzLmFkZEhvdXJzID0gZnVuY3Rpb24gKG4pIHtcblx0XHRcdHJldHVybiBuZXcgVGltZVNwYW4odGhpcy5nZXRUb3RhbE1pbGxpc2Vjb25kcygpICsgKG4gKiAzNjAwMDAwKSk7XG5cdFx0fTtcblxuXHRcdHRoaXMuYWRkTWludXRlcyA9IGZ1bmN0aW9uIChuKSB7XG5cdFx0XHRyZXR1cm4gbmV3IFRpbWVTcGFuKHRoaXMuZ2V0VG90YWxNaWxsaXNlY29uZHMoKSArIChuICogNjAwMDApKTtcblx0XHR9O1xuXG5cdFx0dGhpcy5hZGRTZWNvbmRzID0gZnVuY3Rpb24gKG4pIHtcblx0XHRcdHJldHVybiBuZXcgVGltZVNwYW4odGhpcy5nZXRUb3RhbE1pbGxpc2Vjb25kcygpICsgKG4gKiAxMDAwKSk7XG5cdFx0fTtcblxuXHRcdHRoaXMuYWRkTWlsbGlzZWNvbmRzID0gZnVuY3Rpb24gKG4pIHtcblx0XHRcdHJldHVybiBuZXcgVGltZVNwYW4odGhpcy5nZXRUb3RhbE1pbGxpc2Vjb25kcygpICsgbik7XG5cdFx0fTtcblxuXHRcdHRoaXMuZ2V0MTJIb3VySG91ciA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdHJldHVybiAodGhpcy5nZXRIb3VycygpID4gMTIpID8gdGhpcy5nZXRIb3VycygpIC0gMTIgOiAodGhpcy5nZXRIb3VycygpID09PSAwKSA/IDEyIDogdGhpcy5nZXRIb3VycygpO1xuXHRcdH07XG5cblx0XHR0aGlzLmdldERlc2lnbmF0b3IgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRyZXR1cm4gKHRoaXMuZ2V0SG91cnMoKSA8IDEyKSA/IERhdGUuQ3VsdHVyZUluZm8uYW1EZXNpZ25hdG9yIDogRGF0ZS5DdWx0dXJlSW5mby5wbURlc2lnbmF0b3I7XG5cdFx0fTtcblxuXHRcdHRoaXMudG9TdHJpbmcgPSBmdW5jdGlvbiAoZm9ybWF0KSB7XG5cdFx0XHR0aGlzLl90b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0aWYgKHRoaXMuZ2V0RGF5cygpICE9PSBudWxsICYmIHRoaXMuZ2V0RGF5cygpID4gMCkge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLmdldERheXMoKSArIFwiLlwiICsgdGhpcy5nZXRIb3VycygpICsgXCI6XCIgKyB0aGlzLnAodGhpcy5nZXRNaW51dGVzKCkpICsgXCI6XCIgKyB0aGlzLnAodGhpcy5nZXRTZWNvbmRzKCkpO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHJldHVybiB0aGlzLmdldEhvdXJzKCkgKyBcIjpcIiArIHRoaXMucCh0aGlzLmdldE1pbnV0ZXMoKSkgKyBcIjpcIiArIHRoaXMucCh0aGlzLmdldFNlY29uZHMoKSk7XG5cdFx0XHRcdH1cblx0XHRcdH07XG5cdFx0XHRcblx0XHRcdHRoaXMucCA9IGZ1bmN0aW9uIChzKSB7XG5cdFx0XHRcdHJldHVybiAocy50b1N0cmluZygpLmxlbmd0aCA8IDIpID8gXCIwXCIgKyBzIDogcztcblx0XHRcdH07XG5cdFx0XHRcblx0XHRcdHZhciBtZSA9IHRoaXM7XG5cdFx0XHRcblx0XHRcdHJldHVybiBmb3JtYXQgPyBmb3JtYXQucmVwbGFjZSgvZGQ/fEhIP3xoaD98bW0/fHNzP3x0dD8vZyxcblx0XHRcdGZ1bmN0aW9uIChmb3JtYXQpIHtcblx0XHRcdFx0c3dpdGNoIChmb3JtYXQpIHtcblx0XHRcdFx0Y2FzZSBcImRcIjpcblx0XHRcdFx0XHRyZXR1cm4gbWUuZ2V0RGF5cygpO1xuXHRcdFx0XHRjYXNlIFwiZGRcIjpcblx0XHRcdFx0XHRyZXR1cm4gbWUucChtZS5nZXREYXlzKCkpO1xuXHRcdFx0XHRjYXNlIFwiSFwiOlxuXHRcdFx0XHRcdHJldHVybiBtZS5nZXRIb3VycygpO1xuXHRcdFx0XHRjYXNlIFwiSEhcIjpcblx0XHRcdFx0XHRyZXR1cm4gbWUucChtZS5nZXRIb3VycygpKTtcblx0XHRcdFx0Y2FzZSBcImhcIjpcblx0XHRcdFx0XHRyZXR1cm4gbWUuZ2V0MTJIb3VySG91cigpO1xuXHRcdFx0XHRjYXNlIFwiaGhcIjpcblx0XHRcdFx0XHRyZXR1cm4gbWUucChtZS5nZXQxMkhvdXJIb3VyKCkpO1xuXHRcdFx0XHRjYXNlIFwibVwiOlxuXHRcdFx0XHRcdHJldHVybiBtZS5nZXRNaW51dGVzKCk7XG5cdFx0XHRcdGNhc2UgXCJtbVwiOlxuXHRcdFx0XHRcdHJldHVybiBtZS5wKG1lLmdldE1pbnV0ZXMoKSk7XG5cdFx0XHRcdGNhc2UgXCJzXCI6XG5cdFx0XHRcdFx0cmV0dXJuIG1lLmdldFNlY29uZHMoKTtcblx0XHRcdFx0Y2FzZSBcInNzXCI6XG5cdFx0XHRcdFx0cmV0dXJuIG1lLnAobWUuZ2V0U2Vjb25kcygpKTtcblx0XHRcdFx0Y2FzZSBcInRcIjpcblx0XHRcdFx0XHRyZXR1cm4gKChtZS5nZXRIb3VycygpIDwgMTIpID8gRGF0ZS5DdWx0dXJlSW5mby5hbURlc2lnbmF0b3IgOiBEYXRlLkN1bHR1cmVJbmZvLnBtRGVzaWduYXRvcikuc3Vic3RyaW5nKDAsIDEpO1xuXHRcdFx0XHRjYXNlIFwidHRcIjpcblx0XHRcdFx0XHRyZXR1cm4gKG1lLmdldEhvdXJzKCkgPCAxMikgPyBEYXRlLkN1bHR1cmVJbmZvLmFtRGVzaWduYXRvciA6IERhdGUuQ3VsdHVyZUluZm8ucG1EZXNpZ25hdG9yO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0XHQpIDogdGhpcy5fdG9TdHJpbmcoKTtcblx0XHR9O1xuXHRcdHJldHVybiB0aGlzO1xuXHR9O1xuXHRhZGRTZXRGdW5jcyhUaW1lU3BhbiwgYXR0cnMuc2xpY2UoMikpO1xuXHRUaW1lU3Bhbi5wcm90b3R5cGUuc2V0ID0gZnVuY3Rpb24gKGRheXMsIGhvdXJzLCBtaW51dGVzLCBzZWNvbmRzLCBtaWxsaXNlY29uZHMpe1xuXHRcdHRoaXMuc2V0RGF5cyhkYXlzIHx8IHRoaXMuZ2V0RGF5cygpKTtcblx0XHR0aGlzLnNldEhvdXJzKGhvdXJzIHx8IHRoaXMuZ2V0SG91cnMoKSk7XG5cdFx0dGhpcy5zZXRNaW51dGVzKG1pbnV0ZXMgfHwgdGhpcy5nZXRNaW51dGVzKCkpO1xuXHRcdHRoaXMuc2V0U2Vjb25kcyhzZWNvbmRzIHx8IHRoaXMuZ2V0U2Vjb25kcygpKTtcblx0XHR0aGlzLnNldE1pbGxpc2Vjb25kcyhtaWxsaXNlY29uZHMgfHwgdGhpcy5nZXRNaWxsaXNlY29uZHMoKSk7XG5cdH07XG5cblxuXHQvKipcblx0ICogR2V0cyB0aGUgdGltZSBvZiBkYXkgZm9yIHRoaXMgZGF0ZSBpbnN0YW5jZXMuIFxuXHQgKiBAcmV0dXJuIHtUaW1lU3Bhbn0gVGltZVNwYW5cblx0ICovXG5cdERhdGUucHJvdG90eXBlLmdldFRpbWVPZkRheSA9IGZ1bmN0aW9uICgpIHtcblx0XHRyZXR1cm4gbmV3IFRpbWVTcGFuKDAsIHRoaXMuZ2V0SG91cnMoKSwgdGhpcy5nZXRNaW51dGVzKCksIHRoaXMuZ2V0U2Vjb25kcygpLCB0aGlzLmdldE1pbGxpc2Vjb25kcygpKTtcblx0fTtcblxuXHREYXRlLlRpbWVTcGFuID0gVGltZVNwYW47XG5cblx0aWYgKHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgKSB7XG5cdFx0Ly8ga2VlcGluZyBBUEkgY29tcGF0aWJsZSBmb3IgdjEueCBcblx0XHR3aW5kb3cuVGltZVNwYW4gPSBUaW1lU3Bhbjtcblx0fVxufSgpKTsiLCIvKipcbiAqIEBvdmVydmlldyBOUE0gTW9kdWxlIGluZGV4OiBpbmNsdWRlIGFsbCB0aGUgY29yZSBtb2R1bGVzLCBJMThuIGZpbGVzIHdpbGwgYmUgbG9hZGVkIG9uIHRoZSBmbHkuXG4gKiBAYXV0aG9yIEdyZWdvcnkgV2lsZC1TbWl0aCA8Z3JlZ29yeUB3aWxkLXNtaXRoLmNvbT5cbiAqL1xucmVxdWlyZShcIi4vc3JjL2NvcmUvaTE4bi5qc1wiKTtcbnJlcXVpcmUoXCIuL3NyYy9jb3JlL2NvcmUuanNcIik7XG5yZXF1aXJlKFwiLi9zcmMvY29yZS9jb3JlLXByb3RvdHlwZXMuanNcIik7XG5yZXF1aXJlKFwiLi9zcmMvY29yZS9zdWdhcnBhay5qc1wiKTtcbnJlcXVpcmUoXCIuL3NyYy9jb3JlL2Zvcm1hdF9wYXJzZXIuanNcIik7XG5yZXF1aXJlKFwiLi9zcmMvY29yZS9wYXJzaW5nX29wZXJhdG9ycy5qc1wiKTtcbnJlcXVpcmUoXCIuL3NyYy9jb3JlL3BhcnNpbmdfdHJhbnNsYXRvci5qc1wiKTtcbnJlcXVpcmUoXCIuL3NyYy9jb3JlL3BhcnNpbmdfZ3JhbW1hci5qc1wiKTtcbnJlcXVpcmUoXCIuL3NyYy9jb3JlL3BhcnNlci5qc1wiKTtcbnJlcXVpcmUoXCIuL3NyYy9jb3JlL2V4dHJhcy5qc1wiKTtcbnJlcXVpcmUoXCIuL3NyYy9jb3JlL3RpbWVfcGVyaW9kLmpzXCIpO1xucmVxdWlyZShcIi4vc3JjL2NvcmUvdGltZV9zcGFuLmpzXCIpO1xuLypcbiAqIE5vdGljZSB0aGF0IHRoZXJlIGlzIG5vIG1vZGVsLmV4cG9ydCBvciBleHBvcnRzLiBUaGlzIGlzIG5vdCByZXF1aXJlZCBhcyBpdCBtb2RpZmllcyB0aGUgRGF0ZSBvYmplY3QgYW5kIGl0J3MgcHJvdG90eXBlcy5cbiAqLyJdfQ==
// Welcome! require() some modules from npm (like you were using browserify)
// and then hit Run Code to run your code on the right side.
// Modules get downloaded from browserify-cdn and bundled in your browser.
let fecha = require('fecha');
let moment = require('moment');
require('datejs'); // modifies Date
console.log( moment );
const FORMAT = {
DASH: 'MM-DD-YYYY',
SLASH: 'MM/DD/YYYY',
NATA_DASH: 'DD-MM-YYYY',
NATA_SLASH: 'DD/MM/YYYY'
};
const TESTS = [
'11111111111',
'asdfasdfasdf',
'01/55/2017',
'01/01/2017'
];
function testGroup( tests, format ) {
console.log( format );
console.log( '----------------');
console.log( 'FECHA' );
tests.forEach( t => {
testFecha( t, format );
});
console.log( 'MOMENT' );
tests.forEach( t => {
testMoment( t, format );
});
console.log( 'DATEJS' );
tests.forEach( t => {
testDatejs( t, format );
});
console.log( '\n\n');
}
function testFecha( str, format ) {
let d = fecha.parse( str, format );
console.log( ' ' + str, d );
}
function testMoment( str, format ) {
let d = moment( str, format, true );
console.log( ' ' + d.isValid() );
}
function testDatejs( str, format ) {
let d = Date.parse( str, format );
console.log( ' ' + d );
}
Object.keys(FORMAT).forEach( key => {
testGroup( TESTS, FORMAT[key] );
});
;}, 0)
{
"name": "requirebin-sketch",
"version": "1.0.0",
"dependencies": {
"fecha": "2.2.0",
"moment": "2.3.0",
"datejs": "1.0.0-rc3"
}
}
<!-- contents of this file will be placed inside the <body> -->
<!-- contents of this file will be placed inside the <head> -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment