Skip to content

Instantly share code, notes, and snippets.

@ms3056
Last active June 20, 2023 06:19
Show Gist options
  • Save ms3056/78771af260ad8d0f8724c8c4a5c7bf97 to your computer and use it in GitHub Desktop.
Save ms3056/78771af260ad8d0f8724c8c4a5c7bf97 to your computer and use it in GitHub Desktop.
Clock plugin for Obsidian
/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// main.ts
var main_exports = {};
__export(main_exports, {
default: () => ClockPlugin
});
module.exports = __toCommonJS(main_exports);
// node_modules/luxon/src/errors.js
var LuxonError = class extends Error {
};
var InvalidDateTimeError = class extends LuxonError {
constructor(reason) {
super(`Invalid DateTime: ${reason.toMessage()}`);
}
};
var InvalidIntervalError = class extends LuxonError {
constructor(reason) {
super(`Invalid Interval: ${reason.toMessage()}`);
}
};
var InvalidDurationError = class extends LuxonError {
constructor(reason) {
super(`Invalid Duration: ${reason.toMessage()}`);
}
};
var ConflictingSpecificationError = class extends LuxonError {
};
var InvalidUnitError = class extends LuxonError {
constructor(unit) {
super(`Invalid unit ${unit}`);
}
};
var InvalidArgumentError = class extends LuxonError {
};
var ZoneIsAbstractError = class extends LuxonError {
constructor() {
super("Zone is an abstract class");
}
};
// node_modules/luxon/src/impl/formats.js
var n = "numeric";
var s = "short";
var l = "long";
var DATE_SHORT = {
year: n,
month: n,
day: n
};
var DATE_MED = {
year: n,
month: s,
day: n
};
var DATE_MED_WITH_WEEKDAY = {
year: n,
month: s,
day: n,
weekday: s
};
var DATE_FULL = {
year: n,
month: l,
day: n
};
var DATE_HUGE = {
year: n,
month: l,
day: n,
weekday: l
};
var TIME_SIMPLE = {
hour: n,
minute: n
};
var TIME_WITH_SECONDS = {
hour: n,
minute: n,
second: n
};
var TIME_WITH_SHORT_OFFSET = {
hour: n,
minute: n,
second: n,
timeZoneName: s
};
var TIME_WITH_LONG_OFFSET = {
hour: n,
minute: n,
second: n,
timeZoneName: l
};
var TIME_24_SIMPLE = {
hour: n,
minute: n,
hourCycle: "h23"
};
var TIME_24_WITH_SECONDS = {
hour: n,
minute: n,
second: n,
hourCycle: "h23"
};
var TIME_24_WITH_SHORT_OFFSET = {
hour: n,
minute: n,
second: n,
hourCycle: "h23",
timeZoneName: s
};
var TIME_24_WITH_LONG_OFFSET = {
hour: n,
minute: n,
second: n,
hourCycle: "h23",
timeZoneName: l
};
var DATETIME_SHORT = {
year: n,
month: n,
day: n,
hour: n,
minute: n
};
var DATETIME_SHORT_WITH_SECONDS = {
year: n,
month: n,
day: n,
hour: n,
minute: n,
second: n
};
var DATETIME_MED = {
year: n,
month: s,
day: n,
hour: n,
minute: n
};
var DATETIME_MED_WITH_SECONDS = {
year: n,
month: s,
day: n,
hour: n,
minute: n,
second: n
};
var DATETIME_MED_WITH_WEEKDAY = {
year: n,
month: s,
day: n,
weekday: s,
hour: n,
minute: n
};
var DATETIME_FULL = {
year: n,
month: l,
day: n,
hour: n,
minute: n,
timeZoneName: s
};
var DATETIME_FULL_WITH_SECONDS = {
year: n,
month: l,
day: n,
hour: n,
minute: n,
second: n,
timeZoneName: s
};
var DATETIME_HUGE = {
year: n,
month: l,
day: n,
weekday: l,
hour: n,
minute: n,
timeZoneName: l
};
var DATETIME_HUGE_WITH_SECONDS = {
year: n,
month: l,
day: n,
weekday: l,
hour: n,
minute: n,
second: n,
timeZoneName: l
};
// node_modules/luxon/src/zone.js
var Zone = class {
/**
* The type of zone
* @abstract
* @type {string}
*/
get type() {
throw new ZoneIsAbstractError();
}
/**
* The name of this zone.
* @abstract
* @type {string}
*/
get name() {
throw new ZoneIsAbstractError();
}
get ianaName() {
return this.name;
}
/**
* Returns whether the offset is known to be fixed for the whole year.
* @abstract
* @type {boolean}
*/
get isUniversal() {
throw new ZoneIsAbstractError();
}
/**
* Returns the offset's common name (such as EST) at the specified timestamp
* @abstract
* @param {number} ts - Epoch milliseconds for which to get the name
* @param {Object} opts - Options to affect the format
* @param {string} opts.format - What style of offset to return. Accepts 'long' or 'short'.
* @param {string} opts.locale - What locale to return the offset name in.
* @return {string}
*/
offsetName(ts, opts) {
throw new ZoneIsAbstractError();
}
/**
* Returns the offset's value as a string
* @abstract
* @param {number} ts - Epoch milliseconds for which to get the offset
* @param {string} format - What style of offset to return.
* Accepts 'narrow', 'short', or 'techie'. Returning '+6', '+06:00', or '+0600' respectively
* @return {string}
*/
formatOffset(ts, format) {
throw new ZoneIsAbstractError();
}
/**
* Return the offset in minutes for this zone at the specified timestamp.
* @abstract
* @param {number} ts - Epoch milliseconds for which to compute the offset
* @return {number}
*/
offset(ts) {
throw new ZoneIsAbstractError();
}
/**
* Return whether this Zone is equal to another zone
* @abstract
* @param {Zone} otherZone - the zone to compare
* @return {boolean}
*/
equals(otherZone) {
throw new ZoneIsAbstractError();
}
/**
* Return whether this Zone is valid.
* @abstract
* @type {boolean}
*/
get isValid() {
throw new ZoneIsAbstractError();
}
};
// node_modules/luxon/src/zones/systemZone.js
var singleton = null;
var SystemZone = class extends Zone {
/**
* Get a singleton instance of the local zone
* @return {SystemZone}
*/
static get instance() {
if (singleton === null) {
singleton = new SystemZone();
}
return singleton;
}
/** @override **/
get type() {
return "system";
}
/** @override **/
get name() {
return new Intl.DateTimeFormat().resolvedOptions().timeZone;
}
/** @override **/
get isUniversal() {
return false;
}
/** @override **/
offsetName(ts, { format, locale }) {
return parseZoneInfo(ts, format, locale);
}
/** @override **/
formatOffset(ts, format) {
return formatOffset(this.offset(ts), format);
}
/** @override **/
offset(ts) {
return -new Date(ts).getTimezoneOffset();
}
/** @override **/
equals(otherZone) {
return otherZone.type === "system";
}
/** @override **/
get isValid() {
return true;
}
};
// node_modules/luxon/src/zones/IANAZone.js
var dtfCache = {};
function makeDTF(zone) {
if (!dtfCache[zone]) {
dtfCache[zone] = new Intl.DateTimeFormat("en-US", {
hour12: false,
timeZone: zone,
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
era: "short"
});
}
return dtfCache[zone];
}
var typeToPos = {
year: 0,
month: 1,
day: 2,
era: 3,
hour: 4,
minute: 5,
second: 6
};
function hackyOffset(dtf, date) {
const formatted = dtf.format(date).replace(/\u200E/g, ""), parsed = /(\d+)\/(\d+)\/(\d+) (AD|BC),? (\d+):(\d+):(\d+)/.exec(formatted), [, fMonth, fDay, fYear, fadOrBc, fHour, fMinute, fSecond] = parsed;
return [fYear, fMonth, fDay, fadOrBc, fHour, fMinute, fSecond];
}
function partsOffset(dtf, date) {
const formatted = dtf.formatToParts(date);
const filled = [];
for (let i = 0; i < formatted.length; i++) {
const { type, value } = formatted[i];
const pos = typeToPos[type];
if (type === "era") {
filled[pos] = value;
} else if (!isUndefined(pos)) {
filled[pos] = parseInt(value, 10);
}
}
return filled;
}
var ianaZoneCache = {};
var IANAZone = class extends Zone {
/**
* @param {string} name - Zone name
* @return {IANAZone}
*/
static create(name) {
if (!ianaZoneCache[name]) {
ianaZoneCache[name] = new IANAZone(name);
}
return ianaZoneCache[name];
}
/**
* Reset local caches. Should only be necessary in testing scenarios.
* @return {void}
*/
static resetCache() {
ianaZoneCache = {};
dtfCache = {};
}
/**
* Returns whether the provided string is a valid specifier. This only checks the string's format, not that the specifier identifies a known zone; see isValidZone for that.
* @param {string} s - The string to check validity on
* @example IANAZone.isValidSpecifier("America/New_York") //=> true
* @example IANAZone.isValidSpecifier("Sport~~blorp") //=> false
* @deprecated This method returns false for some valid IANA names. Use isValidZone instead.
* @return {boolean}
*/
static isValidSpecifier(s2) {
return this.isValidZone(s2);
}
/**
* Returns whether the provided string identifies a real zone
* @param {string} zone - The string to check
* @example IANAZone.isValidZone("America/New_York") //=> true
* @example IANAZone.isValidZone("Fantasia/Castle") //=> false
* @example IANAZone.isValidZone("Sport~~blorp") //=> false
* @return {boolean}
*/
static isValidZone(zone) {
if (!zone) {
return false;
}
try {
new Intl.DateTimeFormat("en-US", { timeZone: zone }).format();
return true;
} catch (e) {
return false;
}
}
constructor(name) {
super();
this.zoneName = name;
this.valid = IANAZone.isValidZone(name);
}
/** @override **/
get type() {
return "iana";
}
/** @override **/
get name() {
return this.zoneName;
}
/** @override **/
get isUniversal() {
return false;
}
/** @override **/
offsetName(ts, { format, locale }) {
return parseZoneInfo(ts, format, locale, this.name);
}
/** @override **/
formatOffset(ts, format) {
return formatOffset(this.offset(ts), format);
}
/** @override **/
offset(ts) {
const date = new Date(ts);
if (isNaN(date))
return NaN;
const dtf = makeDTF(this.name);
let [year, month, day, adOrBc, hour, minute, second] = dtf.formatToParts ? partsOffset(dtf, date) : hackyOffset(dtf, date);
if (adOrBc === "BC") {
year = -Math.abs(year) + 1;
}
const adjustedHour = hour === 24 ? 0 : hour;
const asUTC = objToLocalTS({
year,
month,
day,
hour: adjustedHour,
minute,
second,
millisecond: 0
});
let asTS = +date;
const over = asTS % 1e3;
asTS -= over >= 0 ? over : 1e3 + over;
return (asUTC - asTS) / (60 * 1e3);
}
/** @override **/
equals(otherZone) {
return otherZone.type === "iana" && otherZone.name === this.name;
}
/** @override **/
get isValid() {
return this.valid;
}
};
// node_modules/luxon/src/impl/locale.js
var intlLFCache = {};
function getCachedLF(locString, opts = {}) {
const key = JSON.stringify([locString, opts]);
let dtf = intlLFCache[key];
if (!dtf) {
dtf = new Intl.ListFormat(locString, opts);
intlLFCache[key] = dtf;
}
return dtf;
}
var intlDTCache = {};
function getCachedDTF(locString, opts = {}) {
const key = JSON.stringify([locString, opts]);
let dtf = intlDTCache[key];
if (!dtf) {
dtf = new Intl.DateTimeFormat(locString, opts);
intlDTCache[key] = dtf;
}
return dtf;
}
var intlNumCache = {};
function getCachedINF(locString, opts = {}) {
const key = JSON.stringify([locString, opts]);
let inf = intlNumCache[key];
if (!inf) {
inf = new Intl.NumberFormat(locString, opts);
intlNumCache[key] = inf;
}
return inf;
}
var intlRelCache = {};
function getCachedRTF(locString, opts = {}) {
const { base, ...cacheKeyOpts } = opts;
const key = JSON.stringify([locString, cacheKeyOpts]);
let inf = intlRelCache[key];
if (!inf) {
inf = new Intl.RelativeTimeFormat(locString, opts);
intlRelCache[key] = inf;
}
return inf;
}
var sysLocaleCache = null;
function systemLocale() {
if (sysLocaleCache) {
return sysLocaleCache;
} else {
sysLocaleCache = new Intl.DateTimeFormat().resolvedOptions().locale;
return sysLocaleCache;
}
}
function parseLocaleString(localeStr) {
const xIndex = localeStr.indexOf("-x-");
if (xIndex !== -1) {
localeStr = localeStr.substring(0, xIndex);
}
const uIndex = localeStr.indexOf("-u-");
if (uIndex === -1) {
return [localeStr];
} else {
let options;
let selectedStr;
try {
options = getCachedDTF(localeStr).resolvedOptions();
selectedStr = localeStr;
} catch (e) {
const smaller = localeStr.substring(0, uIndex);
options = getCachedDTF(smaller).resolvedOptions();
selectedStr = smaller;
}
const { numberingSystem, calendar } = options;
return [selectedStr, numberingSystem, calendar];
}
}
function intlConfigString(localeStr, numberingSystem, outputCalendar) {
if (outputCalendar || numberingSystem) {
if (!localeStr.includes("-u-")) {
localeStr += "-u";
}
if (outputCalendar) {
localeStr += `-ca-${outputCalendar}`;
}
if (numberingSystem) {
localeStr += `-nu-${numberingSystem}`;
}
return localeStr;
} else {
return localeStr;
}
}
function mapMonths(f) {
const ms = [];
for (let i = 1; i <= 12; i++) {
const dt = DateTime.utc(2016, i, 1);
ms.push(f(dt));
}
return ms;
}
function mapWeekdays(f) {
const ms = [];
for (let i = 1; i <= 7; i++) {
const dt = DateTime.utc(2016, 11, 13 + i);
ms.push(f(dt));
}
return ms;
}
function listStuff(loc, length, defaultOK, englishFn, intlFn) {
const mode = loc.listingMode(defaultOK);
if (mode === "error") {
return null;
} else if (mode === "en") {
return englishFn(length);
} else {
return intlFn(length);
}
}
function supportsFastNumbers(loc) {
if (loc.numberingSystem && loc.numberingSystem !== "latn") {
return false;
} else {
return loc.numberingSystem === "latn" || !loc.locale || loc.locale.startsWith("en") || new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem === "latn";
}
}
var PolyNumberFormatter = class {
constructor(intl, forceSimple, opts) {
this.padTo = opts.padTo || 0;
this.floor = opts.floor || false;
const { padTo, floor, ...otherOpts } = opts;
if (!forceSimple || Object.keys(otherOpts).length > 0) {
const intlOpts = { useGrouping: false, ...opts };
if (opts.padTo > 0)
intlOpts.minimumIntegerDigits = opts.padTo;
this.inf = getCachedINF(intl, intlOpts);
}
}
format(i) {
if (this.inf) {
const fixed = this.floor ? Math.floor(i) : i;
return this.inf.format(fixed);
} else {
const fixed = this.floor ? Math.floor(i) : roundTo(i, 3);
return padStart(fixed, this.padTo);
}
}
};
var PolyDateFormatter = class {
constructor(dt, intl, opts) {
this.opts = opts;
this.originalZone = void 0;
let z = void 0;
if (this.opts.timeZone) {
this.dt = dt;
} else if (dt.zone.type === "fixed") {
const gmtOffset = -1 * (dt.offset / 60);
const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`;
if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) {
z = offsetZ;
this.dt = dt;
} else {
z = "UTC";
this.dt = dt.offset === 0 ? dt : dt.setZone("UTC").plus({ minutes: dt.offset });
this.originalZone = dt.zone;
}
} else if (dt.zone.type === "system") {
this.dt = dt;
} else if (dt.zone.type === "iana") {
this.dt = dt;
z = dt.zone.name;
} else {
z = "UTC";
this.dt = dt.setZone("UTC").plus({ minutes: dt.offset });
this.originalZone = dt.zone;
}
const intlOpts = { ...this.opts };
intlOpts.timeZone = intlOpts.timeZone || z;
this.dtf = getCachedDTF(intl, intlOpts);
}
format() {
if (this.originalZone) {
return this.formatToParts().map(({ value }) => value).join("");
}
return this.dtf.format(this.dt.toJSDate());
}
formatToParts() {
const parts = this.dtf.formatToParts(this.dt.toJSDate());
if (this.originalZone) {
return parts.map((part) => {
if (part.type === "timeZoneName") {
const offsetName = this.originalZone.offsetName(this.dt.ts, {
locale: this.dt.locale,
format: this.opts.timeZoneName
});
return {
...part,
value: offsetName
};
} else {
return part;
}
});
}
return parts;
}
resolvedOptions() {
return this.dtf.resolvedOptions();
}
};
var PolyRelFormatter = class {
constructor(intl, isEnglish, opts) {
this.opts = { style: "long", ...opts };
if (!isEnglish && hasRelative()) {
this.rtf = getCachedRTF(intl, opts);
}
}
format(count, unit) {
if (this.rtf) {
return this.rtf.format(count, unit);
} else {
return formatRelativeTime(unit, count, this.opts.numeric, this.opts.style !== "long");
}
}
formatToParts(count, unit) {
if (this.rtf) {
return this.rtf.formatToParts(count, unit);
} else {
return [];
}
}
};
var Locale = class {
static fromOpts(opts) {
return Locale.create(opts.locale, opts.numberingSystem, opts.outputCalendar, opts.defaultToEN);
}
static create(locale, numberingSystem, outputCalendar, defaultToEN = false) {
const specifiedLocale = locale || Settings.defaultLocale;
const localeR = specifiedLocale || (defaultToEN ? "en-US" : systemLocale());
const numberingSystemR = numberingSystem || Settings.defaultNumberingSystem;
const outputCalendarR = outputCalendar || Settings.defaultOutputCalendar;
return new Locale(localeR, numberingSystemR, outputCalendarR, specifiedLocale);
}
static resetCache() {
sysLocaleCache = null;
intlDTCache = {};
intlNumCache = {};
intlRelCache = {};
}
static fromObject({ locale, numberingSystem, outputCalendar } = {}) {
return Locale.create(locale, numberingSystem, outputCalendar);
}
constructor(locale, numbering, outputCalendar, specifiedLocale) {
const [parsedLocale, parsedNumberingSystem, parsedOutputCalendar] = parseLocaleString(locale);
this.locale = parsedLocale;
this.numberingSystem = numbering || parsedNumberingSystem || null;
this.outputCalendar = outputCalendar || parsedOutputCalendar || null;
this.intl = intlConfigString(this.locale, this.numberingSystem, this.outputCalendar);
this.weekdaysCache = { format: {}, standalone: {} };
this.monthsCache = { format: {}, standalone: {} };
this.meridiemCache = null;
this.eraCache = {};
this.specifiedLocale = specifiedLocale;
this.fastNumbersCached = null;
}
get fastNumbers() {
if (this.fastNumbersCached == null) {
this.fastNumbersCached = supportsFastNumbers(this);
}
return this.fastNumbersCached;
}
listingMode() {
const isActuallyEn = this.isEnglish();
const hasNoWeirdness = (this.numberingSystem === null || this.numberingSystem === "latn") && (this.outputCalendar === null || this.outputCalendar === "gregory");
return isActuallyEn && hasNoWeirdness ? "en" : "intl";
}
clone(alts) {
if (!alts || Object.getOwnPropertyNames(alts).length === 0) {
return this;
} else {
return Locale.create(
alts.locale || this.specifiedLocale,
alts.numberingSystem || this.numberingSystem,
alts.outputCalendar || this.outputCalendar,
alts.defaultToEN || false
);
}
}
redefaultToEN(alts = {}) {
return this.clone({ ...alts, defaultToEN: true });
}
redefaultToSystem(alts = {}) {
return this.clone({ ...alts, defaultToEN: false });
}
months(length, format = false, defaultOK = true) {
return listStuff(this, length, defaultOK, months, () => {
const intl = format ? { month: length, day: "numeric" } : { month: length }, formatStr = format ? "format" : "standalone";
if (!this.monthsCache[formatStr][length]) {
this.monthsCache[formatStr][length] = mapMonths((dt) => this.extract(dt, intl, "month"));
}
return this.monthsCache[formatStr][length];
});
}
weekdays(length, format = false, defaultOK = true) {
return listStuff(this, length, defaultOK, weekdays, () => {
const intl = format ? { weekday: length, year: "numeric", month: "long", day: "numeric" } : { weekday: length }, formatStr = format ? "format" : "standalone";
if (!this.weekdaysCache[formatStr][length]) {
this.weekdaysCache[formatStr][length] = mapWeekdays(
(dt) => this.extract(dt, intl, "weekday")
);
}
return this.weekdaysCache[formatStr][length];
});
}
meridiems(defaultOK = true) {
return listStuff(
this,
void 0,
defaultOK,
() => meridiems,
() => {
if (!this.meridiemCache) {
const intl = { hour: "numeric", hourCycle: "h12" };
this.meridiemCache = [DateTime.utc(2016, 11, 13, 9), DateTime.utc(2016, 11, 13, 19)].map(
(dt) => this.extract(dt, intl, "dayperiod")
);
}
return this.meridiemCache;
}
);
}
eras(length, defaultOK = true) {
return listStuff(this, length, defaultOK, eras, () => {
const intl = { era: length };
if (!this.eraCache[length]) {
this.eraCache[length] = [DateTime.utc(-40, 1, 1), DateTime.utc(2017, 1, 1)].map(
(dt) => this.extract(dt, intl, "era")
);
}
return this.eraCache[length];
});
}
extract(dt, intlOpts, field) {
const df = this.dtFormatter(dt, intlOpts), results = df.formatToParts(), matching = results.find((m) => m.type.toLowerCase() === field);
return matching ? matching.value : null;
}
numberFormatter(opts = {}) {
return new PolyNumberFormatter(this.intl, opts.forceSimple || this.fastNumbers, opts);
}
dtFormatter(dt, intlOpts = {}) {
return new PolyDateFormatter(dt, this.intl, intlOpts);
}
relFormatter(opts = {}) {
return new PolyRelFormatter(this.intl, this.isEnglish(), opts);
}
listFormatter(opts = {}) {
return getCachedLF(this.intl, opts);
}
isEnglish() {
return this.locale === "en" || this.locale.toLowerCase() === "en-us" || new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us");
}
equals(other) {
return this.locale === other.locale && this.numberingSystem === other.numberingSystem && this.outputCalendar === other.outputCalendar;
}
};
// node_modules/luxon/src/zones/fixedOffsetZone.js
var singleton2 = null;
var FixedOffsetZone = class extends Zone {
/**
* Get a singleton instance of UTC
* @return {FixedOffsetZone}
*/
static get utcInstance() {
if (singleton2 === null) {
singleton2 = new FixedOffsetZone(0);
}
return singleton2;
}
/**
* Get an instance with a specified offset
* @param {number} offset - The offset in minutes
* @return {FixedOffsetZone}
*/
static instance(offset2) {
return offset2 === 0 ? FixedOffsetZone.utcInstance : new FixedOffsetZone(offset2);
}
/**
* Get an instance of FixedOffsetZone from a UTC offset string, like "UTC+6"
* @param {string} s - The offset string to parse
* @example FixedOffsetZone.parseSpecifier("UTC+6")
* @example FixedOffsetZone.parseSpecifier("UTC+06")
* @example FixedOffsetZone.parseSpecifier("UTC-6:00")
* @return {FixedOffsetZone}
*/
static parseSpecifier(s2) {
if (s2) {
const r = s2.match(/^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$/i);
if (r) {
return new FixedOffsetZone(signedOffset(r[1], r[2]));
}
}
return null;
}
constructor(offset2) {
super();
this.fixed = offset2;
}
/** @override **/
get type() {
return "fixed";
}
/** @override **/
get name() {
return this.fixed === 0 ? "UTC" : `UTC${formatOffset(this.fixed, "narrow")}`;
}
get ianaName() {
if (this.fixed === 0) {
return "Etc/UTC";
} else {
return `Etc/GMT${formatOffset(-this.fixed, "narrow")}`;
}
}
/** @override **/
offsetName() {
return this.name;
}
/** @override **/
formatOffset(ts, format) {
return formatOffset(this.fixed, format);
}
/** @override **/
get isUniversal() {
return true;
}
/** @override **/
offset() {
return this.fixed;
}
/** @override **/
equals(otherZone) {
return otherZone.type === "fixed" && otherZone.fixed === this.fixed;
}
/** @override **/
get isValid() {
return true;
}
};
// node_modules/luxon/src/zones/invalidZone.js
var InvalidZone = class extends Zone {
constructor(zoneName) {
super();
this.zoneName = zoneName;
}
/** @override **/
get type() {
return "invalid";
}
/** @override **/
get name() {
return this.zoneName;
}
/** @override **/
get isUniversal() {
return false;
}
/** @override **/
offsetName() {
return null;
}
/** @override **/
formatOffset() {
return "";
}
/** @override **/
offset() {
return NaN;
}
/** @override **/
equals() {
return false;
}
/** @override **/
get isValid() {
return false;
}
};
// node_modules/luxon/src/impl/zoneUtil.js
function normalizeZone(input, defaultZone2) {
let offset2;
if (isUndefined(input) || input === null) {
return defaultZone2;
} else if (input instanceof Zone) {
return input;
} else if (isString(input)) {
const lowered = input.toLowerCase();
if (lowered === "default")
return defaultZone2;
else if (lowered === "local" || lowered === "system")
return SystemZone.instance;
else if (lowered === "utc" || lowered === "gmt")
return FixedOffsetZone.utcInstance;
else
return FixedOffsetZone.parseSpecifier(lowered) || IANAZone.create(input);
} else if (isNumber(input)) {
return FixedOffsetZone.instance(input);
} else if (typeof input === "object" && input.offset && typeof input.offset === "number") {
return input;
} else {
return new InvalidZone(input);
}
}
// node_modules/luxon/src/settings.js
var now = () => Date.now();
var defaultZone = "system";
var defaultLocale = null;
var defaultNumberingSystem = null;
var defaultOutputCalendar = null;
var twoDigitCutoffYear = 60;
var throwOnInvalid;
var Settings = class {
/**
* Get the callback for returning the current timestamp.
* @type {function}
*/
static get now() {
return now;
}
/**
* Set the callback for returning the current timestamp.
* The function should return a number, which will be interpreted as an Epoch millisecond count
* @type {function}
* @example Settings.now = () => Date.now() + 3000 // pretend it is 3 seconds in the future
* @example Settings.now = () => 0 // always pretend it's Jan 1, 1970 at midnight in UTC time
*/
static set now(n2) {
now = n2;
}
/**
* Set the default time zone to create DateTimes in. Does not affect existing instances.
* Use the value "system" to reset this value to the system's time zone.
* @type {string}
*/
static set defaultZone(zone) {
defaultZone = zone;
}
/**
* Get the default time zone object currently used to create DateTimes. Does not affect existing instances.
* The default value is the system's time zone (the one set on the machine that runs this code).
* @type {Zone}
*/
static get defaultZone() {
return normalizeZone(defaultZone, SystemZone.instance);
}
/**
* Get the default locale to create DateTimes with. Does not affect existing instances.
* @type {string}
*/
static get defaultLocale() {
return defaultLocale;
}
/**
* Set the default locale to create DateTimes with. Does not affect existing instances.
* @type {string}
*/
static set defaultLocale(locale) {
defaultLocale = locale;
}
/**
* Get the default numbering system to create DateTimes with. Does not affect existing instances.
* @type {string}
*/
static get defaultNumberingSystem() {
return defaultNumberingSystem;
}
/**
* Set the default numbering system to create DateTimes with. Does not affect existing instances.
* @type {string}
*/
static set defaultNumberingSystem(numberingSystem) {
defaultNumberingSystem = numberingSystem;
}
/**
* Get the default output calendar to create DateTimes with. Does not affect existing instances.
* @type {string}
*/
static get defaultOutputCalendar() {
return defaultOutputCalendar;
}
/**
* Set the default output calendar to create DateTimes with. Does not affect existing instances.
* @type {string}
*/
static set defaultOutputCalendar(outputCalendar) {
defaultOutputCalendar = outputCalendar;
}
/**
* Get the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century.
* @type {number}
*/
static get twoDigitCutoffYear() {
return twoDigitCutoffYear;
}
/**
* Set the cutoff year after which a string encoding a year as two digits is interpreted to occur in the current century.
* @type {number}
* @example Settings.twoDigitCutoffYear = 0 // cut-off year is 0, so all 'yy' are interpretted as current century
* @example Settings.twoDigitCutoffYear = 50 // '49' -> 1949; '50' -> 2050
* @example Settings.twoDigitCutoffYear = 1950 // interpretted as 50
* @example Settings.twoDigitCutoffYear = 2050 // ALSO interpretted as 50
*/
static set twoDigitCutoffYear(cutoffYear) {
twoDigitCutoffYear = cutoffYear % 100;
}
/**
* Get whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
* @type {boolean}
*/
static get throwOnInvalid() {
return throwOnInvalid;
}
/**
* Set whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
* @type {boolean}
*/
static set throwOnInvalid(t) {
throwOnInvalid = t;
}
/**
* Reset Luxon's global caches. Should only be necessary in testing scenarios.
* @return {void}
*/
static resetCaches() {
Locale.resetCache();
IANAZone.resetCache();
}
};
// node_modules/luxon/src/impl/util.js
function isUndefined(o) {
return typeof o === "undefined";
}
function isNumber(o) {
return typeof o === "number";
}
function isInteger(o) {
return typeof o === "number" && o % 1 === 0;
}
function isString(o) {
return typeof o === "string";
}
function isDate(o) {
return Object.prototype.toString.call(o) === "[object Date]";
}
function hasRelative() {
try {
return typeof Intl !== "undefined" && !!Intl.RelativeTimeFormat;
} catch (e) {
return false;
}
}
function maybeArray(thing) {
return Array.isArray(thing) ? thing : [thing];
}
function bestBy(arr, by, compare) {
if (arr.length === 0) {
return void 0;
}
return arr.reduce((best, next) => {
const pair = [by(next), next];
if (!best) {
return pair;
} else if (compare(best[0], pair[0]) === best[0]) {
return best;
} else {
return pair;
}
}, null)[1];
}
function pick(obj, keys) {
return keys.reduce((a, k) => {
a[k] = obj[k];
return a;
}, {});
}
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
function integerBetween(thing, bottom, top) {
return isInteger(thing) && thing >= bottom && thing <= top;
}
function floorMod(x, n2) {
return x - n2 * Math.floor(x / n2);
}
function padStart(input, n2 = 2) {
const isNeg = input < 0;
let padded;
if (isNeg) {
padded = "-" + ("" + -input).padStart(n2, "0");
} else {
padded = ("" + input).padStart(n2, "0");
}
return padded;
}
function parseInteger(string) {
if (isUndefined(string) || string === null || string === "") {
return void 0;
} else {
return parseInt(string, 10);
}
}
function parseFloating(string) {
if (isUndefined(string) || string === null || string === "") {
return void 0;
} else {
return parseFloat(string);
}
}
function parseMillis(fraction) {
if (isUndefined(fraction) || fraction === null || fraction === "") {
return void 0;
} else {
const f = parseFloat("0." + fraction) * 1e3;
return Math.floor(f);
}
}
function roundTo(number, digits, towardZero = false) {
const factor = 10 ** digits, rounder = towardZero ? Math.trunc : Math.round;
return rounder(number * factor) / factor;
}
function isLeapYear(year) {
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
}
function daysInYear(year) {
return isLeapYear(year) ? 366 : 365;
}
function daysInMonth(year, month) {
const modMonth = floorMod(month - 1, 12) + 1, modYear = year + (month - modMonth) / 12;
if (modMonth === 2) {
return isLeapYear(modYear) ? 29 : 28;
} else {
return [31, null, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][modMonth - 1];
}
}
function objToLocalTS(obj) {
let d = Date.UTC(
obj.year,
obj.month - 1,
obj.day,
obj.hour,
obj.minute,
obj.second,
obj.millisecond
);
if (obj.year < 100 && obj.year >= 0) {
d = new Date(d);
d.setUTCFullYear(obj.year, obj.month - 1, obj.day);
}
return +d;
}
function weeksInWeekYear(weekYear) {
const p1 = (weekYear + Math.floor(weekYear / 4) - Math.floor(weekYear / 100) + Math.floor(weekYear / 400)) % 7, last = weekYear - 1, p2 = (last + Math.floor(last / 4) - Math.floor(last / 100) + Math.floor(last / 400)) % 7;
return p1 === 4 || p2 === 3 ? 53 : 52;
}
function untruncateYear(year) {
if (year > 99) {
return year;
} else
return year > Settings.twoDigitCutoffYear ? 1900 + year : 2e3 + year;
}
function parseZoneInfo(ts, offsetFormat, locale, timeZone = null) {
const date = new Date(ts), intlOpts = {
hourCycle: "h23",
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit"
};
if (timeZone) {
intlOpts.timeZone = timeZone;
}
const modified = { timeZoneName: offsetFormat, ...intlOpts };
const parsed = new Intl.DateTimeFormat(locale, modified).formatToParts(date).find((m) => m.type.toLowerCase() === "timezonename");
return parsed ? parsed.value : null;
}
function signedOffset(offHourStr, offMinuteStr) {
let offHour = parseInt(offHourStr, 10);
if (Number.isNaN(offHour)) {
offHour = 0;
}
const offMin = parseInt(offMinuteStr, 10) || 0, offMinSigned = offHour < 0 || Object.is(offHour, -0) ? -offMin : offMin;
return offHour * 60 + offMinSigned;
}
function asNumber(value) {
const numericValue = Number(value);
if (typeof value === "boolean" || value === "" || Number.isNaN(numericValue))
throw new InvalidArgumentError(`Invalid unit value ${value}`);
return numericValue;
}
function normalizeObject(obj, normalizer) {
const normalized = {};
for (const u in obj) {
if (hasOwnProperty(obj, u)) {
const v = obj[u];
if (v === void 0 || v === null)
continue;
normalized[normalizer(u)] = asNumber(v);
}
}
return normalized;
}
function formatOffset(offset2, format) {
const hours = Math.trunc(Math.abs(offset2 / 60)), minutes = Math.trunc(Math.abs(offset2 % 60)), sign = offset2 >= 0 ? "+" : "-";
switch (format) {
case "short":
return `${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;
case "narrow":
return `${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;
case "techie":
return `${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;
default:
throw new RangeError(`Value format ${format} is out of range for property format`);
}
}
function timeObject(obj) {
return pick(obj, ["hour", "minute", "second", "millisecond"]);
}
// node_modules/luxon/src/impl/english.js
var monthsLong = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
];
var monthsShort = [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
];
var monthsNarrow = ["J", "F", "M", "A", "M", "J", "J", "A", "S", "O", "N", "D"];
function months(length) {
switch (length) {
case "narrow":
return [...monthsNarrow];
case "short":
return [...monthsShort];
case "long":
return [...monthsLong];
case "numeric":
return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"];
case "2-digit":
return ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"];
default:
return null;
}
}
var weekdaysLong = [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
];
var weekdaysShort = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
var weekdaysNarrow = ["M", "T", "W", "T", "F", "S", "S"];
function weekdays(length) {
switch (length) {
case "narrow":
return [...weekdaysNarrow];
case "short":
return [...weekdaysShort];
case "long":
return [...weekdaysLong];
case "numeric":
return ["1", "2", "3", "4", "5", "6", "7"];
default:
return null;
}
}
var meridiems = ["AM", "PM"];
var erasLong = ["Before Christ", "Anno Domini"];
var erasShort = ["BC", "AD"];
var erasNarrow = ["B", "A"];
function eras(length) {
switch (length) {
case "narrow":
return [...erasNarrow];
case "short":
return [...erasShort];
case "long":
return [...erasLong];
default:
return null;
}
}
function meridiemForDateTime(dt) {
return meridiems[dt.hour < 12 ? 0 : 1];
}
function weekdayForDateTime(dt, length) {
return weekdays(length)[dt.weekday - 1];
}
function monthForDateTime(dt, length) {
return months(length)[dt.month - 1];
}
function eraForDateTime(dt, length) {
return eras(length)[dt.year < 0 ? 0 : 1];
}
function formatRelativeTime(unit, count, numeric = "always", narrow = false) {
const units = {
years: ["year", "yr."],
quarters: ["quarter", "qtr."],
months: ["month", "mo."],
weeks: ["week", "wk."],
days: ["day", "day", "days"],
hours: ["hour", "hr."],
minutes: ["minute", "min."],
seconds: ["second", "sec."]
};
const lastable = ["hours", "minutes", "seconds"].indexOf(unit) === -1;
if (numeric === "auto" && lastable) {
const isDay = unit === "days";
switch (count) {
case 1:
return isDay ? "tomorrow" : `next ${units[unit][0]}`;
case -1:
return isDay ? "yesterday" : `last ${units[unit][0]}`;
case 0:
return isDay ? "today" : `this ${units[unit][0]}`;
default:
}
}
const isInPast = Object.is(count, -0) || count < 0, fmtValue = Math.abs(count), singular = fmtValue === 1, lilUnits = units[unit], fmtUnit = narrow ? singular ? lilUnits[1] : lilUnits[2] || lilUnits[1] : singular ? units[unit][0] : unit;
return isInPast ? `${fmtValue} ${fmtUnit} ago` : `in ${fmtValue} ${fmtUnit}`;
}
// node_modules/luxon/src/impl/formatter.js
function stringifyTokens(splits, tokenToString) {
let s2 = "";
for (const token of splits) {
if (token.literal) {
s2 += token.val;
} else {
s2 += tokenToString(token.val);
}
}
return s2;
}
var macroTokenToFormatOpts = {
D: DATE_SHORT,
DD: DATE_MED,
DDD: DATE_FULL,
DDDD: DATE_HUGE,
t: TIME_SIMPLE,
tt: TIME_WITH_SECONDS,
ttt: TIME_WITH_SHORT_OFFSET,
tttt: TIME_WITH_LONG_OFFSET,
T: TIME_24_SIMPLE,
TT: TIME_24_WITH_SECONDS,
TTT: TIME_24_WITH_SHORT_OFFSET,
TTTT: TIME_24_WITH_LONG_OFFSET,
f: DATETIME_SHORT,
ff: DATETIME_MED,
fff: DATETIME_FULL,
ffff: DATETIME_HUGE,
F: DATETIME_SHORT_WITH_SECONDS,
FF: DATETIME_MED_WITH_SECONDS,
FFF: DATETIME_FULL_WITH_SECONDS,
FFFF: DATETIME_HUGE_WITH_SECONDS
};
var Formatter = class {
static create(locale, opts = {}) {
return new Formatter(locale, opts);
}
static parseFormat(fmt) {
let current = null, currentFull = "", bracketed = false;
const splits = [];
for (let i = 0; i < fmt.length; i++) {
const c = fmt.charAt(i);
if (c === "'") {
if (currentFull.length > 0) {
splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull });
}
current = null;
currentFull = "";
bracketed = !bracketed;
} else if (bracketed) {
currentFull += c;
} else if (c === current) {
currentFull += c;
} else {
if (currentFull.length > 0) {
splits.push({ literal: /^\s+$/.test(currentFull), val: currentFull });
}
currentFull = c;
current = c;
}
}
if (currentFull.length > 0) {
splits.push({ literal: bracketed || /^\s+$/.test(currentFull), val: currentFull });
}
return splits;
}
static macroTokenToFormatOpts(token) {
return macroTokenToFormatOpts[token];
}
constructor(locale, formatOpts) {
this.opts = formatOpts;
this.loc = locale;
this.systemLoc = null;
}
formatWithSystemDefault(dt, opts) {
if (this.systemLoc === null) {
this.systemLoc = this.loc.redefaultToSystem();
}
const df = this.systemLoc.dtFormatter(dt, { ...this.opts, ...opts });
return df.format();
}
formatDateTime(dt, opts = {}) {
const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts });
return df.format();
}
formatDateTimeParts(dt, opts = {}) {
const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts });
return df.formatToParts();
}
formatInterval(interval, opts = {}) {
const df = this.loc.dtFormatter(interval.start, { ...this.opts, ...opts });
return df.dtf.formatRange(interval.start.toJSDate(), interval.end.toJSDate());
}
resolvedOptions(dt, opts = {}) {
const df = this.loc.dtFormatter(dt, { ...this.opts, ...opts });
return df.resolvedOptions();
}
num(n2, p = 0) {
if (this.opts.forceSimple) {
return padStart(n2, p);
}
const opts = { ...this.opts };
if (p > 0) {
opts.padTo = p;
}
return this.loc.numberFormatter(opts).format(n2);
}
formatDateTimeFromString(dt, fmt) {
const knownEnglish = this.loc.listingMode() === "en", useDateTimeFormatter = this.loc.outputCalendar && this.loc.outputCalendar !== "gregory", string = (opts, extract) => this.loc.extract(dt, opts, extract), formatOffset2 = (opts) => {
if (dt.isOffsetFixed && dt.offset === 0 && opts.allowZ) {
return "Z";
}
return dt.isValid ? dt.zone.formatOffset(dt.ts, opts.format) : "";
}, meridiem = () => knownEnglish ? meridiemForDateTime(dt) : string({ hour: "numeric", hourCycle: "h12" }, "dayperiod"), month = (length, standalone) => knownEnglish ? monthForDateTime(dt, length) : string(standalone ? { month: length } : { month: length, day: "numeric" }, "month"), weekday = (length, standalone) => knownEnglish ? weekdayForDateTime(dt, length) : string(
standalone ? { weekday: length } : { weekday: length, month: "long", day: "numeric" },
"weekday"
), maybeMacro = (token) => {
const formatOpts = Formatter.macroTokenToFormatOpts(token);
if (formatOpts) {
return this.formatWithSystemDefault(dt, formatOpts);
} else {
return token;
}
}, era = (length) => knownEnglish ? eraForDateTime(dt, length) : string({ era: length }, "era"), tokenToString = (token) => {
switch (token) {
case "S":
return this.num(dt.millisecond);
case "u":
case "SSS":
return this.num(dt.millisecond, 3);
case "s":
return this.num(dt.second);
case "ss":
return this.num(dt.second, 2);
case "uu":
return this.num(Math.floor(dt.millisecond / 10), 2);
case "uuu":
return this.num(Math.floor(dt.millisecond / 100));
case "m":
return this.num(dt.minute);
case "mm":
return this.num(dt.minute, 2);
case "h":
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12);
case "hh":
return this.num(dt.hour % 12 === 0 ? 12 : dt.hour % 12, 2);
case "H":
return this.num(dt.hour);
case "HH":
return this.num(dt.hour, 2);
case "Z":
return formatOffset2({ format: "narrow", allowZ: this.opts.allowZ });
case "ZZ":
return formatOffset2({ format: "short", allowZ: this.opts.allowZ });
case "ZZZ":
return formatOffset2({ format: "techie", allowZ: this.opts.allowZ });
case "ZZZZ":
return dt.zone.offsetName(dt.ts, { format: "short", locale: this.loc.locale });
case "ZZZZZ":
return dt.zone.offsetName(dt.ts, { format: "long", locale: this.loc.locale });
case "z":
return dt.zoneName;
case "a":
return meridiem();
case "d":
return useDateTimeFormatter ? string({ day: "numeric" }, "day") : this.num(dt.day);
case "dd":
return useDateTimeFormatter ? string({ day: "2-digit" }, "day") : this.num(dt.day, 2);
case "c":
return this.num(dt.weekday);
case "ccc":
return weekday("short", true);
case "cccc":
return weekday("long", true);
case "ccccc":
return weekday("narrow", true);
case "E":
return this.num(dt.weekday);
case "EEE":
return weekday("short", false);
case "EEEE":
return weekday("long", false);
case "EEEEE":
return weekday("narrow", false);
case "L":
return useDateTimeFormatter ? string({ month: "numeric", day: "numeric" }, "month") : this.num(dt.month);
case "LL":
return useDateTimeFormatter ? string({ month: "2-digit", day: "numeric" }, "month") : this.num(dt.month, 2);
case "LLL":
return month("short", true);
case "LLLL":
return month("long", true);
case "LLLLL":
return month("narrow", true);
case "M":
return useDateTimeFormatter ? string({ month: "numeric" }, "month") : this.num(dt.month);
case "MM":
return useDateTimeFormatter ? string({ month: "2-digit" }, "month") : this.num(dt.month, 2);
case "MMM":
return month("short", false);
case "MMMM":
return month("long", false);
case "MMMMM":
return month("narrow", false);
case "y":
return useDateTimeFormatter ? string({ year: "numeric" }, "year") : this.num(dt.year);
case "yy":
return useDateTimeFormatter ? string({ year: "2-digit" }, "year") : this.num(dt.year.toString().slice(-2), 2);
case "yyyy":
return useDateTimeFormatter ? string({ year: "numeric" }, "year") : this.num(dt.year, 4);
case "yyyyyy":
return useDateTimeFormatter ? string({ year: "numeric" }, "year") : this.num(dt.year, 6);
case "G":
return era("short");
case "GG":
return era("long");
case "GGGGG":
return era("narrow");
case "kk":
return this.num(dt.weekYear.toString().slice(-2), 2);
case "kkkk":
return this.num(dt.weekYear, 4);
case "W":
return this.num(dt.weekNumber);
case "WW":
return this.num(dt.weekNumber, 2);
case "o":
return this.num(dt.ordinal);
case "ooo":
return this.num(dt.ordinal, 3);
case "q":
return this.num(dt.quarter);
case "qq":
return this.num(dt.quarter, 2);
case "X":
return this.num(Math.floor(dt.ts / 1e3));
case "x":
return this.num(dt.ts);
default:
return maybeMacro(token);
}
};
return stringifyTokens(Formatter.parseFormat(fmt), tokenToString);
}
formatDurationFromString(dur, fmt) {
const tokenToField = (token) => {
switch (token[0]) {
case "S":
return "millisecond";
case "s":
return "second";
case "m":
return "minute";
case "h":
return "hour";
case "d":
return "day";
case "w":
return "week";
case "M":
return "month";
case "y":
return "year";
default:
return null;
}
}, tokenToString = (lildur) => (token) => {
const mapped = tokenToField(token);
if (mapped) {
return this.num(lildur.get(mapped), token.length);
} else {
return token;
}
}, tokens = Formatter.parseFormat(fmt), realTokens = tokens.reduce(
(found, { literal, val }) => literal ? found : found.concat(val),
[]
), collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t) => t));
return stringifyTokens(tokens, tokenToString(collapsed));
}
};
// node_modules/luxon/src/impl/invalid.js
var Invalid = class {
constructor(reason, explanation) {
this.reason = reason;
this.explanation = explanation;
}
toMessage() {
if (this.explanation) {
return `${this.reason}: ${this.explanation}`;
} else {
return this.reason;
}
}
};
// node_modules/luxon/src/impl/regexParser.js
var ianaRegex = /[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/;
function combineRegexes(...regexes) {
const full = regexes.reduce((f, r) => f + r.source, "");
return RegExp(`^${full}$`);
}
function combineExtractors(...extractors) {
return (m) => extractors.reduce(
([mergedVals, mergedZone, cursor], ex) => {
const [val, zone, next] = ex(m, cursor);
return [{ ...mergedVals, ...val }, zone || mergedZone, next];
},
[{}, null, 1]
).slice(0, 2);
}
function parse(s2, ...patterns) {
if (s2 == null) {
return [null, null];
}
for (const [regex, extractor] of patterns) {
const m = regex.exec(s2);
if (m) {
return extractor(m);
}
}
return [null, null];
}
function simpleParse(...keys) {
return (match2, cursor) => {
const ret = {};
let i;
for (i = 0; i < keys.length; i++) {
ret[keys[i]] = parseInteger(match2[cursor + i]);
}
return [ret, null, cursor + i];
};
}
var offsetRegex = /(?:(Z)|([+-]\d\d)(?::?(\d\d))?)/;
var isoExtendedZone = `(?:${offsetRegex.source}?(?:\\[(${ianaRegex.source})\\])?)?`;
var isoTimeBaseRegex = /(\d\d)(?::?(\d\d)(?::?(\d\d)(?:[.,](\d{1,30}))?)?)?/;
var isoTimeRegex = RegExp(`${isoTimeBaseRegex.source}${isoExtendedZone}`);
var isoTimeExtensionRegex = RegExp(`(?:T${isoTimeRegex.source})?`);
var isoYmdRegex = /([+-]\d{6}|\d{4})(?:-?(\d\d)(?:-?(\d\d))?)?/;
var isoWeekRegex = /(\d{4})-?W(\d\d)(?:-?(\d))?/;
var isoOrdinalRegex = /(\d{4})-?(\d{3})/;
var extractISOWeekData = simpleParse("weekYear", "weekNumber", "weekDay");
var extractISOOrdinalData = simpleParse("year", "ordinal");
var sqlYmdRegex = /(\d{4})-(\d\d)-(\d\d)/;
var sqlTimeRegex = RegExp(
`${isoTimeBaseRegex.source} ?(?:${offsetRegex.source}|(${ianaRegex.source}))?`
);
var sqlTimeExtensionRegex = RegExp(`(?: ${sqlTimeRegex.source})?`);
function int(match2, pos, fallback) {
const m = match2[pos];
return isUndefined(m) ? fallback : parseInteger(m);
}
function extractISOYmd(match2, cursor) {
const item = {
year: int(match2, cursor),
month: int(match2, cursor + 1, 1),
day: int(match2, cursor + 2, 1)
};
return [item, null, cursor + 3];
}
function extractISOTime(match2, cursor) {
const item = {
hours: int(match2, cursor, 0),
minutes: int(match2, cursor + 1, 0),
seconds: int(match2, cursor + 2, 0),
milliseconds: parseMillis(match2[cursor + 3])
};
return [item, null, cursor + 4];
}
function extractISOOffset(match2, cursor) {
const local = !match2[cursor] && !match2[cursor + 1], fullOffset = signedOffset(match2[cursor + 1], match2[cursor + 2]), zone = local ? null : FixedOffsetZone.instance(fullOffset);
return [{}, zone, cursor + 3];
}
function extractIANAZone(match2, cursor) {
const zone = match2[cursor] ? IANAZone.create(match2[cursor]) : null;
return [{}, zone, cursor + 1];
}
var isoTimeOnly = RegExp(`^T?${isoTimeBaseRegex.source}$`);
var isoDuration = /^-?P(?:(?:(-?\d{1,20}(?:\.\d{1,20})?)Y)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20}(?:\.\d{1,20})?)W)?(?:(-?\d{1,20}(?:\.\d{1,20})?)D)?(?:T(?:(-?\d{1,20}(?:\.\d{1,20})?)H)?(?:(-?\d{1,20}(?:\.\d{1,20})?)M)?(?:(-?\d{1,20})(?:[.,](-?\d{1,20}))?S)?)?)$/;
function extractISODuration(match2) {
const [s2, yearStr, monthStr, weekStr, dayStr, hourStr, minuteStr, secondStr, millisecondsStr] = match2;
const hasNegativePrefix = s2[0] === "-";
const negativeSeconds = secondStr && secondStr[0] === "-";
const maybeNegate = (num, force = false) => num !== void 0 && (force || num && hasNegativePrefix) ? -num : num;
return [
{
years: maybeNegate(parseFloating(yearStr)),
months: maybeNegate(parseFloating(monthStr)),
weeks: maybeNegate(parseFloating(weekStr)),
days: maybeNegate(parseFloating(dayStr)),
hours: maybeNegate(parseFloating(hourStr)),
minutes: maybeNegate(parseFloating(minuteStr)),
seconds: maybeNegate(parseFloating(secondStr), secondStr === "-0"),
milliseconds: maybeNegate(parseMillis(millisecondsStr), negativeSeconds)
}
];
}
var obsOffsets = {
GMT: 0,
EDT: -4 * 60,
EST: -5 * 60,
CDT: -5 * 60,
CST: -6 * 60,
MDT: -6 * 60,
MST: -7 * 60,
PDT: -7 * 60,
PST: -8 * 60
};
function fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
const result = {
year: yearStr.length === 2 ? untruncateYear(parseInteger(yearStr)) : parseInteger(yearStr),
month: monthsShort.indexOf(monthStr) + 1,
day: parseInteger(dayStr),
hour: parseInteger(hourStr),
minute: parseInteger(minuteStr)
};
if (secondStr)
result.second = parseInteger(secondStr);
if (weekdayStr) {
result.weekday = weekdayStr.length > 3 ? weekdaysLong.indexOf(weekdayStr) + 1 : weekdaysShort.indexOf(weekdayStr) + 1;
}
return result;
}
var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|(?:([+-]\d\d)(\d\d)))$/;
function extractRFC2822(match2) {
const [
,
weekdayStr,
dayStr,
monthStr,
yearStr,
hourStr,
minuteStr,
secondStr,
obsOffset,
milOffset,
offHourStr,
offMinuteStr
] = match2, result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
let offset2;
if (obsOffset) {
offset2 = obsOffsets[obsOffset];
} else if (milOffset) {
offset2 = 0;
} else {
offset2 = signedOffset(offHourStr, offMinuteStr);
}
return [result, new FixedOffsetZone(offset2)];
}
function preprocessRFC2822(s2) {
return s2.replace(/\([^()]*\)|[\n\t]/g, " ").replace(/(\s\s+)/g, " ").trim();
}
var rfc1123 = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d\d):(\d\d):(\d\d) GMT$/;
var rfc850 = /^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/;
var ascii = /^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( \d|\d\d) (\d\d):(\d\d):(\d\d) (\d{4})$/;
function extractRFC1123Or850(match2) {
const [, weekdayStr, dayStr, monthStr, yearStr, hourStr, minuteStr, secondStr] = match2, result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
return [result, FixedOffsetZone.utcInstance];
}
function extractASCII(match2) {
const [, weekdayStr, monthStr, dayStr, hourStr, minuteStr, secondStr, yearStr] = match2, result = fromStrings(weekdayStr, yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr);
return [result, FixedOffsetZone.utcInstance];
}
var isoYmdWithTimeExtensionRegex = combineRegexes(isoYmdRegex, isoTimeExtensionRegex);
var isoWeekWithTimeExtensionRegex = combineRegexes(isoWeekRegex, isoTimeExtensionRegex);
var isoOrdinalWithTimeExtensionRegex = combineRegexes(isoOrdinalRegex, isoTimeExtensionRegex);
var isoTimeCombinedRegex = combineRegexes(isoTimeRegex);
var extractISOYmdTimeAndOffset = combineExtractors(
extractISOYmd,
extractISOTime,
extractISOOffset,
extractIANAZone
);
var extractISOWeekTimeAndOffset = combineExtractors(
extractISOWeekData,
extractISOTime,
extractISOOffset,
extractIANAZone
);
var extractISOOrdinalDateAndTime = combineExtractors(
extractISOOrdinalData,
extractISOTime,
extractISOOffset,
extractIANAZone
);
var extractISOTimeAndOffset = combineExtractors(
extractISOTime,
extractISOOffset,
extractIANAZone
);
function parseISODate(s2) {
return parse(
s2,
[isoYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset],
[isoWeekWithTimeExtensionRegex, extractISOWeekTimeAndOffset],
[isoOrdinalWithTimeExtensionRegex, extractISOOrdinalDateAndTime],
[isoTimeCombinedRegex, extractISOTimeAndOffset]
);
}
function parseRFC2822Date(s2) {
return parse(preprocessRFC2822(s2), [rfc2822, extractRFC2822]);
}
function parseHTTPDate(s2) {
return parse(
s2,
[rfc1123, extractRFC1123Or850],
[rfc850, extractRFC1123Or850],
[ascii, extractASCII]
);
}
function parseISODuration(s2) {
return parse(s2, [isoDuration, extractISODuration]);
}
var extractISOTimeOnly = combineExtractors(extractISOTime);
function parseISOTimeOnly(s2) {
return parse(s2, [isoTimeOnly, extractISOTimeOnly]);
}
var sqlYmdWithTimeExtensionRegex = combineRegexes(sqlYmdRegex, sqlTimeExtensionRegex);
var sqlTimeCombinedRegex = combineRegexes(sqlTimeRegex);
var extractISOTimeOffsetAndIANAZone = combineExtractors(
extractISOTime,
extractISOOffset,
extractIANAZone
);
function parseSQL(s2) {
return parse(
s2,
[sqlYmdWithTimeExtensionRegex, extractISOYmdTimeAndOffset],
[sqlTimeCombinedRegex, extractISOTimeOffsetAndIANAZone]
);
}
// node_modules/luxon/src/duration.js
var INVALID = "Invalid Duration";
var lowOrderMatrix = {
weeks: {
days: 7,
hours: 7 * 24,
minutes: 7 * 24 * 60,
seconds: 7 * 24 * 60 * 60,
milliseconds: 7 * 24 * 60 * 60 * 1e3
},
days: {
hours: 24,
minutes: 24 * 60,
seconds: 24 * 60 * 60,
milliseconds: 24 * 60 * 60 * 1e3
},
hours: { minutes: 60, seconds: 60 * 60, milliseconds: 60 * 60 * 1e3 },
minutes: { seconds: 60, milliseconds: 60 * 1e3 },
seconds: { milliseconds: 1e3 }
};
var casualMatrix = {
years: {
quarters: 4,
months: 12,
weeks: 52,
days: 365,
hours: 365 * 24,
minutes: 365 * 24 * 60,
seconds: 365 * 24 * 60 * 60,
milliseconds: 365 * 24 * 60 * 60 * 1e3
},
quarters: {
months: 3,
weeks: 13,
days: 91,
hours: 91 * 24,
minutes: 91 * 24 * 60,
seconds: 91 * 24 * 60 * 60,
milliseconds: 91 * 24 * 60 * 60 * 1e3
},
months: {
weeks: 4,
days: 30,
hours: 30 * 24,
minutes: 30 * 24 * 60,
seconds: 30 * 24 * 60 * 60,
milliseconds: 30 * 24 * 60 * 60 * 1e3
},
...lowOrderMatrix
};
var daysInYearAccurate = 146097 / 400;
var daysInMonthAccurate = 146097 / 4800;
var accurateMatrix = {
years: {
quarters: 4,
months: 12,
weeks: daysInYearAccurate / 7,
days: daysInYearAccurate,
hours: daysInYearAccurate * 24,
minutes: daysInYearAccurate * 24 * 60,
seconds: daysInYearAccurate * 24 * 60 * 60,
milliseconds: daysInYearAccurate * 24 * 60 * 60 * 1e3
},
quarters: {
months: 3,
weeks: daysInYearAccurate / 28,
days: daysInYearAccurate / 4,
hours: daysInYearAccurate * 24 / 4,
minutes: daysInYearAccurate * 24 * 60 / 4,
seconds: daysInYearAccurate * 24 * 60 * 60 / 4,
milliseconds: daysInYearAccurate * 24 * 60 * 60 * 1e3 / 4
},
months: {
weeks: daysInMonthAccurate / 7,
days: daysInMonthAccurate,
hours: daysInMonthAccurate * 24,
minutes: daysInMonthAccurate * 24 * 60,
seconds: daysInMonthAccurate * 24 * 60 * 60,
milliseconds: daysInMonthAccurate * 24 * 60 * 60 * 1e3
},
...lowOrderMatrix
};
var orderedUnits = [
"years",
"quarters",
"months",
"weeks",
"days",
"hours",
"minutes",
"seconds",
"milliseconds"
];
var reverseUnits = orderedUnits.slice(0).reverse();
function clone(dur, alts, clear = false) {
const conf = {
values: clear ? alts.values : { ...dur.values, ...alts.values || {} },
loc: dur.loc.clone(alts.loc),
conversionAccuracy: alts.conversionAccuracy || dur.conversionAccuracy,
matrix: alts.matrix || dur.matrix
};
return new Duration(conf);
}
function antiTrunc(n2) {
return n2 < 0 ? Math.floor(n2) : Math.ceil(n2);
}
function convert(matrix, fromMap, fromUnit, toMap, toUnit) {
const conv = matrix[toUnit][fromUnit], raw = fromMap[fromUnit] / conv, sameSign = Math.sign(raw) === Math.sign(toMap[toUnit]), added = !sameSign && toMap[toUnit] !== 0 && Math.abs(raw) <= 1 ? antiTrunc(raw) : Math.trunc(raw);
toMap[toUnit] += added;
fromMap[fromUnit] -= added * conv;
}
function normalizeValues(matrix, vals) {
reverseUnits.reduce((previous, current) => {
if (!isUndefined(vals[current])) {
if (previous) {
convert(matrix, vals, previous, vals, current);
}
return current;
} else {
return previous;
}
}, null);
}
function removeZeroes(vals) {
const newVals = {};
for (const [key, value] of Object.entries(vals)) {
if (value !== 0) {
newVals[key] = value;
}
}
return newVals;
}
var Duration = class {
/**
* @private
*/
constructor(config) {
const accurate = config.conversionAccuracy === "longterm" || false;
let matrix = accurate ? accurateMatrix : casualMatrix;
if (config.matrix) {
matrix = config.matrix;
}
this.values = config.values;
this.loc = config.loc || Locale.create();
this.conversionAccuracy = accurate ? "longterm" : "casual";
this.invalid = config.invalid || null;
this.matrix = matrix;
this.isLuxonDuration = true;
}
/**
* Create Duration from a number of milliseconds.
* @param {number} count of milliseconds
* @param {Object} opts - options for parsing
* @param {string} [opts.locale='en-US'] - the locale to use
* @param {string} opts.numberingSystem - the numbering system to use
* @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
* @return {Duration}
*/
static fromMillis(count, opts) {
return Duration.fromObject({ milliseconds: count }, opts);
}
/**
* Create a Duration from a JavaScript object with keys like 'years' and 'hours'.
* If this object is empty then a zero milliseconds duration is returned.
* @param {Object} obj - the object to create the DateTime from
* @param {number} obj.years
* @param {number} obj.quarters
* @param {number} obj.months
* @param {number} obj.weeks
* @param {number} obj.days
* @param {number} obj.hours
* @param {number} obj.minutes
* @param {number} obj.seconds
* @param {number} obj.milliseconds
* @param {Object} [opts=[]] - options for creating this Duration
* @param {string} [opts.locale='en-US'] - the locale to use
* @param {string} opts.numberingSystem - the numbering system to use
* @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use
* @param {string} [opts.matrix=Object] - the custom conversion system to use
* @return {Duration}
*/
static fromObject(obj, opts = {}) {
if (obj == null || typeof obj !== "object") {
throw new InvalidArgumentError(
`Duration.fromObject: argument expected to be an object, got ${obj === null ? "null" : typeof obj}`
);
}
return new Duration({
values: normalizeObject(obj, Duration.normalizeUnit),
loc: Locale.fromObject(opts),
conversionAccuracy: opts.conversionAccuracy,
matrix: opts.matrix
});
}
/**
* Create a Duration from DurationLike.
*
* @param {Object | number | Duration} durationLike
* One of:
* - object with keys like 'years' and 'hours'.
* - number representing milliseconds
* - Duration instance
* @return {Duration}
*/
static fromDurationLike(durationLike) {
if (isNumber(durationLike)) {
return Duration.fromMillis(durationLike);
} else if (Duration.isDuration(durationLike)) {
return durationLike;
} else if (typeof durationLike === "object") {
return Duration.fromObject(durationLike);
} else {
throw new InvalidArgumentError(
`Unknown duration argument ${durationLike} of type ${typeof durationLike}`
);
}
}
/**
* Create a Duration from an ISO 8601 duration string.
* @param {string} text - text to parse
* @param {Object} opts - options for parsing
* @param {string} [opts.locale='en-US'] - the locale to use
* @param {string} opts.numberingSystem - the numbering system to use
* @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use
* @param {string} [opts.matrix=Object] - the preset conversion system to use
* @see https://en.wikipedia.org/wiki/ISO_8601#Durations
* @example Duration.fromISO('P3Y6M1W4DT12H30M5S').toObject() //=> { years: 3, months: 6, weeks: 1, days: 4, hours: 12, minutes: 30, seconds: 5 }
* @example Duration.fromISO('PT23H').toObject() //=> { hours: 23 }
* @example Duration.fromISO('P5Y3M').toObject() //=> { years: 5, months: 3 }
* @return {Duration}
*/
static fromISO(text, opts) {
const [parsed] = parseISODuration(text);
if (parsed) {
return Duration.fromObject(parsed, opts);
} else {
return Duration.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`);
}
}
/**
* Create a Duration from an ISO 8601 time string.
* @param {string} text - text to parse
* @param {Object} opts - options for parsing
* @param {string} [opts.locale='en-US'] - the locale to use
* @param {string} opts.numberingSystem - the numbering system to use
* @param {string} [opts.conversionAccuracy='casual'] - the preset conversion system to use
* @param {string} [opts.matrix=Object] - the conversion system to use
* @see https://en.wikipedia.org/wiki/ISO_8601#Times
* @example Duration.fromISOTime('11:22:33.444').toObject() //=> { hours: 11, minutes: 22, seconds: 33, milliseconds: 444 }
* @example Duration.fromISOTime('11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
* @example Duration.fromISOTime('T11:00').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
* @example Duration.fromISOTime('1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
* @example Duration.fromISOTime('T1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
* @return {Duration}
*/
static fromISOTime(text, opts) {
const [parsed] = parseISOTimeOnly(text);
if (parsed) {
return Duration.fromObject(parsed, opts);
} else {
return Duration.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`);
}
}
/**
* Create an invalid Duration.
* @param {string} reason - simple string of why this datetime is invalid. Should not contain parameters or anything else data-dependent
* @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information
* @return {Duration}
*/
static invalid(reason, explanation = null) {
if (!reason) {
throw new InvalidArgumentError("need to specify a reason the Duration is invalid");
}
const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
if (Settings.throwOnInvalid) {
throw new InvalidDurationError(invalid);
} else {
return new Duration({ invalid });
}
}
/**
* @private
*/
static normalizeUnit(unit) {
const normalized = {
year: "years",
years: "years",
quarter: "quarters",
quarters: "quarters",
month: "months",
months: "months",
week: "weeks",
weeks: "weeks",
day: "days",
days: "days",
hour: "hours",
hours: "hours",
minute: "minutes",
minutes: "minutes",
second: "seconds",
seconds: "seconds",
millisecond: "milliseconds",
milliseconds: "milliseconds"
}[unit ? unit.toLowerCase() : unit];
if (!normalized)
throw new InvalidUnitError(unit);
return normalized;
}
/**
* Check if an object is a Duration. Works across context boundaries
* @param {object} o
* @return {boolean}
*/
static isDuration(o) {
return o && o.isLuxonDuration || false;
}
/**
* Get the locale of a Duration, such 'en-GB'
* @type {string}
*/
get locale() {
return this.isValid ? this.loc.locale : null;
}
/**
* Get the numbering system of a Duration, such 'beng'. The numbering system is used when formatting the Duration
*
* @type {string}
*/
get numberingSystem() {
return this.isValid ? this.loc.numberingSystem : null;
}
/**
* Returns a string representation of this Duration formatted according to the specified format string. You may use these tokens:
* * `S` for milliseconds
* * `s` for seconds
* * `m` for minutes
* * `h` for hours
* * `d` for days
* * `w` for weeks
* * `M` for months
* * `y` for years
* Notes:
* * Add padding by repeating the token, e.g. "yy" pads the years to two digits, "hhhh" pads the hours out to four digits
* * Tokens can be escaped by wrapping with single quotes.
* * The duration will be converted to the set of units in the format string using {@link Duration#shiftTo} and the Durations's conversion accuracy setting.
* @param {string} fmt - the format string
* @param {Object} opts - options
* @param {boolean} [opts.floor=true] - floor numerical values
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("y d s") //=> "1 6 2"
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("yy dd sss") //=> "01 06 002"
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toFormat("M S") //=> "12 518402000"
* @return {string}
*/
toFormat(fmt, opts = {}) {
const fmtOpts = {
...opts,
floor: opts.round !== false && opts.floor !== false
};
return this.isValid ? Formatter.create(this.loc, fmtOpts).formatDurationFromString(this, fmt) : INVALID;
}
/**
* Returns a string representation of a Duration with all units included.
* To modify its behavior use the `listStyle` and any Intl.NumberFormat option, though `unitDisplay` is especially relevant.
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat
* @param opts - On option object to override the formatting. Accepts the same keys as the options parameter of the native `Int.NumberFormat` constructor, as well as `listStyle`.
* @example
* ```js
* var dur = Duration.fromObject({ days: 1, hours: 5, minutes: 6 })
* dur.toHuman() //=> '1 day, 5 hours, 6 minutes'
* dur.toHuman({ listStyle: "long" }) //=> '1 day, 5 hours, and 6 minutes'
* dur.toHuman({ unitDisplay: "short" }) //=> '1 day, 5 hr, 6 min'
* ```
*/
toHuman(opts = {}) {
const l2 = orderedUnits.map((unit) => {
const val = this.values[unit];
if (isUndefined(val)) {
return null;
}
return this.loc.numberFormatter({ style: "unit", unitDisplay: "long", ...opts, unit: unit.slice(0, -1) }).format(val);
}).filter((n2) => n2);
return this.loc.listFormatter({ type: "conjunction", style: opts.listStyle || "narrow", ...opts }).format(l2);
}
/**
* Returns a JavaScript object with this Duration's values.
* @example Duration.fromObject({ years: 1, days: 6, seconds: 2 }).toObject() //=> { years: 1, days: 6, seconds: 2 }
* @return {Object}
*/
toObject() {
if (!this.isValid)
return {};
return { ...this.values };
}
/**
* Returns an ISO 8601-compliant string representation of this Duration.
* @see https://en.wikipedia.org/wiki/ISO_8601#Durations
* @example Duration.fromObject({ years: 3, seconds: 45 }).toISO() //=> 'P3YT45S'
* @example Duration.fromObject({ months: 4, seconds: 45 }).toISO() //=> 'P4MT45S'
* @example Duration.fromObject({ months: 5 }).toISO() //=> 'P5M'
* @example Duration.fromObject({ minutes: 5 }).toISO() //=> 'PT5M'
* @example Duration.fromObject({ milliseconds: 6 }).toISO() //=> 'PT0.006S'
* @return {string}
*/
toISO() {
if (!this.isValid)
return null;
let s2 = "P";
if (this.years !== 0)
s2 += this.years + "Y";
if (this.months !== 0 || this.quarters !== 0)
s2 += this.months + this.quarters * 3 + "M";
if (this.weeks !== 0)
s2 += this.weeks + "W";
if (this.days !== 0)
s2 += this.days + "D";
if (this.hours !== 0 || this.minutes !== 0 || this.seconds !== 0 || this.milliseconds !== 0)
s2 += "T";
if (this.hours !== 0)
s2 += this.hours + "H";
if (this.minutes !== 0)
s2 += this.minutes + "M";
if (this.seconds !== 0 || this.milliseconds !== 0)
s2 += roundTo(this.seconds + this.milliseconds / 1e3, 3) + "S";
if (s2 === "P")
s2 += "T0S";
return s2;
}
/**
* Returns an ISO 8601-compliant string representation of this Duration, formatted as a time of day.
* Note that this will return null if the duration is invalid, negative, or equal to or greater than 24 hours.
* @see https://en.wikipedia.org/wiki/ISO_8601#Times
* @param {Object} opts - options
* @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0
* @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0
* @param {boolean} [opts.includePrefix=false] - include the `T` prefix
* @param {string} [opts.format='extended'] - choose between the basic and extended format
* @example Duration.fromObject({ hours: 11 }).toISOTime() //=> '11:00:00.000'
* @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressMilliseconds: true }) //=> '11:00:00'
* @example Duration.fromObject({ hours: 11 }).toISOTime({ suppressSeconds: true }) //=> '11:00'
* @example Duration.fromObject({ hours: 11 }).toISOTime({ includePrefix: true }) //=> 'T11:00:00.000'
* @example Duration.fromObject({ hours: 11 }).toISOTime({ format: 'basic' }) //=> '110000.000'
* @return {string}
*/
toISOTime(opts = {}) {
if (!this.isValid)
return null;
const millis = this.toMillis();
if (millis < 0 || millis >= 864e5)
return null;
opts = {
suppressMilliseconds: false,
suppressSeconds: false,
includePrefix: false,
format: "extended",
...opts
};
const value = this.shiftTo("hours", "minutes", "seconds", "milliseconds");
let fmt = opts.format === "basic" ? "hhmm" : "hh:mm";
if (!opts.suppressSeconds || value.seconds !== 0 || value.milliseconds !== 0) {
fmt += opts.format === "basic" ? "ss" : ":ss";
if (!opts.suppressMilliseconds || value.milliseconds !== 0) {
fmt += ".SSS";
}
}
let str = value.toFormat(fmt);
if (opts.includePrefix) {
str = "T" + str;
}
return str;
}
/**
* Returns an ISO 8601 representation of this Duration appropriate for use in JSON.
* @return {string}
*/
toJSON() {
return this.toISO();
}
/**
* Returns an ISO 8601 representation of this Duration appropriate for use in debugging.
* @return {string}
*/
toString() {
return this.toISO();
}
/**
* Returns an milliseconds value of this Duration.
* @return {number}
*/
toMillis() {
return this.as("milliseconds");
}
/**
* Returns an milliseconds value of this Duration. Alias of {@link toMillis}
* @return {number}
*/
valueOf() {
return this.toMillis();
}
/**
* Make this Duration longer by the specified amount. Return a newly-constructed Duration.
* @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
* @return {Duration}
*/
plus(duration) {
if (!this.isValid)
return this;
const dur = Duration.fromDurationLike(duration), result = {};
for (const k of orderedUnits) {
if (hasOwnProperty(dur.values, k) || hasOwnProperty(this.values, k)) {
result[k] = dur.get(k) + this.get(k);
}
}
return clone(this, { values: result }, true);
}
/**
* Make this Duration shorter by the specified amount. Return a newly-constructed Duration.
* @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
* @return {Duration}
*/
minus(duration) {
if (!this.isValid)
return this;
const dur = Duration.fromDurationLike(duration);
return this.plus(dur.negate());
}
/**
* Scale this Duration by the specified amount. Return a newly-constructed Duration.
* @param {function} fn - The function to apply to each unit. Arity is 1 or 2: the value of the unit and, optionally, the unit name. Must return a number.
* @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits(x => x * 2) //=> { hours: 2, minutes: 60 }
* @example Duration.fromObject({ hours: 1, minutes: 30 }).mapUnits((x, u) => u === "hours" ? x * 2 : x) //=> { hours: 2, minutes: 30 }
* @return {Duration}
*/
mapUnits(fn) {
if (!this.isValid)
return this;
const result = {};
for (const k of Object.keys(this.values)) {
result[k] = asNumber(fn(this.values[k], k));
}
return clone(this, { values: result }, true);
}
/**
* Get the value of unit.
* @param {string} unit - a unit such as 'minute' or 'day'
* @example Duration.fromObject({years: 2, days: 3}).get('years') //=> 2
* @example Duration.fromObject({years: 2, days: 3}).get('months') //=> 0
* @example Duration.fromObject({years: 2, days: 3}).get('days') //=> 3
* @return {number}
*/
get(unit) {
return this[Duration.normalizeUnit(unit)];
}
/**
* "Set" the values of specified units. Return a newly-constructed Duration.
* @param {Object} values - a mapping of units to numbers
* @example dur.set({ years: 2017 })
* @example dur.set({ hours: 8, minutes: 30 })
* @return {Duration}
*/
set(values) {
if (!this.isValid)
return this;
const mixed = { ...this.values, ...normalizeObject(values, Duration.normalizeUnit) };
return clone(this, { values: mixed });
}
/**
* "Set" the locale and/or numberingSystem. Returns a newly-constructed Duration.
* @example dur.reconfigure({ locale: 'en-GB' })
* @return {Duration}
*/
reconfigure({ locale, numberingSystem, conversionAccuracy, matrix } = {}) {
const loc = this.loc.clone({ locale, numberingSystem });
const opts = { loc, matrix, conversionAccuracy };
return clone(this, opts);
}
/**
* Return the length of the duration in the specified unit.
* @param {string} unit - a unit such as 'minutes' or 'days'
* @example Duration.fromObject({years: 1}).as('days') //=> 365
* @example Duration.fromObject({years: 1}).as('months') //=> 12
* @example Duration.fromObject({hours: 60}).as('days') //=> 2.5
* @return {number}
*/
as(unit) {
return this.isValid ? this.shiftTo(unit).get(unit) : NaN;
}
/**
* Reduce this Duration to its canonical representation in its current units.
* @example Duration.fromObject({ years: 2, days: 5000 }).normalize().toObject() //=> { years: 15, days: 255 }
* @example Duration.fromObject({ hours: 12, minutes: -45 }).normalize().toObject() //=> { hours: 11, minutes: 15 }
* @return {Duration}
*/
normalize() {
if (!this.isValid)
return this;
const vals = this.toObject();
normalizeValues(this.matrix, vals);
return clone(this, { values: vals }, true);
}
/**
* Rescale units to its largest representation
* @example Duration.fromObject({ milliseconds: 90000 }).rescale().toObject() //=> { minutes: 1, seconds: 30 }
* @return {Duration}
*/
rescale() {
if (!this.isValid)
return this;
const vals = removeZeroes(this.normalize().shiftToAll().toObject());
return clone(this, { values: vals }, true);
}
/**
* Convert this Duration into its representation in a different set of units.
* @example Duration.fromObject({ hours: 1, seconds: 30 }).shiftTo('minutes', 'milliseconds').toObject() //=> { minutes: 60, milliseconds: 30000 }
* @return {Duration}
*/
shiftTo(...units) {
if (!this.isValid)
return this;
if (units.length === 0) {
return this;
}
units = units.map((u) => Duration.normalizeUnit(u));
const built = {}, accumulated = {}, vals = this.toObject();
let lastUnit;
for (const k of orderedUnits) {
if (units.indexOf(k) >= 0) {
lastUnit = k;
let own = 0;
for (const ak in accumulated) {
own += this.matrix[ak][k] * accumulated[ak];
accumulated[ak] = 0;
}
if (isNumber(vals[k])) {
own += vals[k];
}
const i = Math.trunc(own);
built[k] = i;
accumulated[k] = (own * 1e3 - i * 1e3) / 1e3;
for (const down in vals) {
if (orderedUnits.indexOf(down) > orderedUnits.indexOf(k)) {
convert(this.matrix, vals, down, built, k);
}
}
} else if (isNumber(vals[k])) {
accumulated[k] = vals[k];
}
}
for (const key in accumulated) {
if (accumulated[key] !== 0) {
built[lastUnit] += key === lastUnit ? accumulated[key] : accumulated[key] / this.matrix[lastUnit][key];
}
}
return clone(this, { values: built }, true).normalize();
}
/**
* Shift this Duration to all available units.
* Same as shiftTo("years", "months", "weeks", "days", "hours", "minutes", "seconds", "milliseconds")
* @return {Duration}
*/
shiftToAll() {
if (!this.isValid)
return this;
return this.shiftTo(
"years",
"months",
"weeks",
"days",
"hours",
"minutes",
"seconds",
"milliseconds"
);
}
/**
* Return the negative of this Duration.
* @example Duration.fromObject({ hours: 1, seconds: 30 }).negate().toObject() //=> { hours: -1, seconds: -30 }
* @return {Duration}
*/
negate() {
if (!this.isValid)
return this;
const negated = {};
for (const k of Object.keys(this.values)) {
negated[k] = this.values[k] === 0 ? 0 : -this.values[k];
}
return clone(this, { values: negated }, true);
}
/**
* Get the years.
* @type {number}
*/
get years() {
return this.isValid ? this.values.years || 0 : NaN;
}
/**
* Get the quarters.
* @type {number}
*/
get quarters() {
return this.isValid ? this.values.quarters || 0 : NaN;
}
/**
* Get the months.
* @type {number}
*/
get months() {
return this.isValid ? this.values.months || 0 : NaN;
}
/**
* Get the weeks
* @type {number}
*/
get weeks() {
return this.isValid ? this.values.weeks || 0 : NaN;
}
/**
* Get the days.
* @type {number}
*/
get days() {
return this.isValid ? this.values.days || 0 : NaN;
}
/**
* Get the hours.
* @type {number}
*/
get hours() {
return this.isValid ? this.values.hours || 0 : NaN;
}
/**
* Get the minutes.
* @type {number}
*/
get minutes() {
return this.isValid ? this.values.minutes || 0 : NaN;
}
/**
* Get the seconds.
* @return {number}
*/
get seconds() {
return this.isValid ? this.values.seconds || 0 : NaN;
}
/**
* Get the milliseconds.
* @return {number}
*/
get milliseconds() {
return this.isValid ? this.values.milliseconds || 0 : NaN;
}
/**
* Returns whether the Duration is invalid. Invalid durations are returned by diff operations
* on invalid DateTimes or Intervals.
* @return {boolean}
*/
get isValid() {
return this.invalid === null;
}
/**
* Returns an error code if this Duration became invalid, or null if the Duration is valid
* @return {string}
*/
get invalidReason() {
return this.invalid ? this.invalid.reason : null;
}
/**
* Returns an explanation of why this Duration became invalid, or null if the Duration is valid
* @type {string}
*/
get invalidExplanation() {
return this.invalid ? this.invalid.explanation : null;
}
/**
* Equality check
* Two Durations are equal iff they have the same units and the same values for each unit.
* @param {Duration} other
* @return {boolean}
*/
equals(other) {
if (!this.isValid || !other.isValid) {
return false;
}
if (!this.loc.equals(other.loc)) {
return false;
}
function eq(v1, v2) {
if (v1 === void 0 || v1 === 0)
return v2 === void 0 || v2 === 0;
return v1 === v2;
}
for (const u of orderedUnits) {
if (!eq(this.values[u], other.values[u])) {
return false;
}
}
return true;
}
};
// node_modules/luxon/src/interval.js
var INVALID2 = "Invalid Interval";
function validateStartEnd(start, end) {
if (!start || !start.isValid) {
return Interval.invalid("missing or invalid start");
} else if (!end || !end.isValid) {
return Interval.invalid("missing or invalid end");
} else if (end < start) {
return Interval.invalid(
"end before start",
`The end of an interval must be after its start, but you had start=${start.toISO()} and end=${end.toISO()}`
);
} else {
return null;
}
}
var Interval = class {
/**
* @private
*/
constructor(config) {
this.s = config.start;
this.e = config.end;
this.invalid = config.invalid || null;
this.isLuxonInterval = true;
}
/**
* Create an invalid Interval.
* @param {string} reason - simple string of why this Interval is invalid. Should not contain parameters or anything else data-dependent
* @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information
* @return {Interval}
*/
static invalid(reason, explanation = null) {
if (!reason) {
throw new InvalidArgumentError("need to specify a reason the Interval is invalid");
}
const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
if (Settings.throwOnInvalid) {
throw new InvalidIntervalError(invalid);
} else {
return new Interval({ invalid });
}
}
/**
* Create an Interval from a start DateTime and an end DateTime. Inclusive of the start but not the end.
* @param {DateTime|Date|Object} start
* @param {DateTime|Date|Object} end
* @return {Interval}
*/
static fromDateTimes(start, end) {
const builtStart = friendlyDateTime(start), builtEnd = friendlyDateTime(end);
const validateError = validateStartEnd(builtStart, builtEnd);
if (validateError == null) {
return new Interval({
start: builtStart,
end: builtEnd
});
} else {
return validateError;
}
}
/**
* Create an Interval from a start DateTime and a Duration to extend to.
* @param {DateTime|Date|Object} start
* @param {Duration|Object|number} duration - the length of the Interval.
* @return {Interval}
*/
static after(start, duration) {
const dur = Duration.fromDurationLike(duration), dt = friendlyDateTime(start);
return Interval.fromDateTimes(dt, dt.plus(dur));
}
/**
* Create an Interval from an end DateTime and a Duration to extend backwards to.
* @param {DateTime|Date|Object} end
* @param {Duration|Object|number} duration - the length of the Interval.
* @return {Interval}
*/
static before(end, duration) {
const dur = Duration.fromDurationLike(duration), dt = friendlyDateTime(end);
return Interval.fromDateTimes(dt.minus(dur), dt);
}
/**
* Create an Interval from an ISO 8601 string.
* Accepts `<start>/<end>`, `<start>/<duration>`, and `<duration>/<end>` formats.
* @param {string} text - the ISO string to parse
* @param {Object} [opts] - options to pass {@link DateTime#fromISO} and optionally {@link Duration#fromISO}
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
* @return {Interval}
*/
static fromISO(text, opts) {
const [s2, e] = (text || "").split("/", 2);
if (s2 && e) {
let start, startIsValid;
try {
start = DateTime.fromISO(s2, opts);
startIsValid = start.isValid;
} catch (e2) {
startIsValid = false;
}
let end, endIsValid;
try {
end = DateTime.fromISO(e, opts);
endIsValid = end.isValid;
} catch (e2) {
endIsValid = false;
}
if (startIsValid && endIsValid) {
return Interval.fromDateTimes(start, end);
}
if (startIsValid) {
const dur = Duration.fromISO(e, opts);
if (dur.isValid) {
return Interval.after(start, dur);
}
} else if (endIsValid) {
const dur = Duration.fromISO(s2, opts);
if (dur.isValid) {
return Interval.before(end, dur);
}
}
}
return Interval.invalid("unparsable", `the input "${text}" can't be parsed as ISO 8601`);
}
/**
* Check if an object is an Interval. Works across context boundaries
* @param {object} o
* @return {boolean}
*/
static isInterval(o) {
return o && o.isLuxonInterval || false;
}
/**
* Returns the start of the Interval
* @type {DateTime}
*/
get start() {
return this.isValid ? this.s : null;
}
/**
* Returns the end of the Interval
* @type {DateTime}
*/
get end() {
return this.isValid ? this.e : null;
}
/**
* Returns whether this Interval's end is at least its start, meaning that the Interval isn't 'backwards'.
* @type {boolean}
*/
get isValid() {
return this.invalidReason === null;
}
/**
* Returns an error code if this Interval is invalid, or null if the Interval is valid
* @type {string}
*/
get invalidReason() {
return this.invalid ? this.invalid.reason : null;
}
/**
* Returns an explanation of why this Interval became invalid, or null if the Interval is valid
* @type {string}
*/
get invalidExplanation() {
return this.invalid ? this.invalid.explanation : null;
}
/**
* Returns the length of the Interval in the specified unit.
* @param {string} unit - the unit (such as 'hours' or 'days') to return the length in.
* @return {number}
*/
length(unit = "milliseconds") {
return this.isValid ? this.toDuration(...[unit]).get(unit) : NaN;
}
/**
* Returns the count of minutes, hours, days, months, or years included in the Interval, even in part.
* Unlike {@link Interval#length} this counts sections of the calendar, not periods of time, e.g. specifying 'day'
* asks 'what dates are included in this interval?', not 'how many days long is this interval?'
* @param {string} [unit='milliseconds'] - the unit of time to count.
* @return {number}
*/
count(unit = "milliseconds") {
if (!this.isValid)
return NaN;
const start = this.start.startOf(unit), end = this.end.startOf(unit);
return Math.floor(end.diff(start, unit).get(unit)) + (end.valueOf() !== this.end.valueOf());
}
/**
* Returns whether this Interval's start and end are both in the same unit of time
* @param {string} unit - the unit of time to check sameness on
* @return {boolean}
*/
hasSame(unit) {
return this.isValid ? this.isEmpty() || this.e.minus(1).hasSame(this.s, unit) : false;
}
/**
* Return whether this Interval has the same start and end DateTimes.
* @return {boolean}
*/
isEmpty() {
return this.s.valueOf() === this.e.valueOf();
}
/**
* Return whether this Interval's start is after the specified DateTime.
* @param {DateTime} dateTime
* @return {boolean}
*/
isAfter(dateTime) {
if (!this.isValid)
return false;
return this.s > dateTime;
}
/**
* Return whether this Interval's end is before the specified DateTime.
* @param {DateTime} dateTime
* @return {boolean}
*/
isBefore(dateTime) {
if (!this.isValid)
return false;
return this.e <= dateTime;
}
/**
* Return whether this Interval contains the specified DateTime.
* @param {DateTime} dateTime
* @return {boolean}
*/
contains(dateTime) {
if (!this.isValid)
return false;
return this.s <= dateTime && this.e > dateTime;
}
/**
* "Sets" the start and/or end dates. Returns a newly-constructed Interval.
* @param {Object} values - the values to set
* @param {DateTime} values.start - the starting DateTime
* @param {DateTime} values.end - the ending DateTime
* @return {Interval}
*/
set({ start, end } = {}) {
if (!this.isValid)
return this;
return Interval.fromDateTimes(start || this.s, end || this.e);
}
/**
* Split this Interval at each of the specified DateTimes
* @param {...DateTime} dateTimes - the unit of time to count.
* @return {Array}
*/
splitAt(...dateTimes) {
if (!this.isValid)
return [];
const sorted = dateTimes.map(friendlyDateTime).filter((d) => this.contains(d)).sort(), results = [];
let { s: s2 } = this, i = 0;
while (s2 < this.e) {
const added = sorted[i] || this.e, next = +added > +this.e ? this.e : added;
results.push(Interval.fromDateTimes(s2, next));
s2 = next;
i += 1;
}
return results;
}
/**
* Split this Interval into smaller Intervals, each of the specified length.
* Left over time is grouped into a smaller interval
* @param {Duration|Object|number} duration - The length of each resulting interval.
* @return {Array}
*/
splitBy(duration) {
const dur = Duration.fromDurationLike(duration);
if (!this.isValid || !dur.isValid || dur.as("milliseconds") === 0) {
return [];
}
let { s: s2 } = this, idx = 1, next;
const results = [];
while (s2 < this.e) {
const added = this.start.plus(dur.mapUnits((x) => x * idx));
next = +added > +this.e ? this.e : added;
results.push(Interval.fromDateTimes(s2, next));
s2 = next;
idx += 1;
}
return results;
}
/**
* Split this Interval into the specified number of smaller intervals.
* @param {number} numberOfParts - The number of Intervals to divide the Interval into.
* @return {Array}
*/
divideEqually(numberOfParts) {
if (!this.isValid)
return [];
return this.splitBy(this.length() / numberOfParts).slice(0, numberOfParts);
}
/**
* Return whether this Interval overlaps with the specified Interval
* @param {Interval} other
* @return {boolean}
*/
overlaps(other) {
return this.e > other.s && this.s < other.e;
}
/**
* Return whether this Interval's end is adjacent to the specified Interval's start.
* @param {Interval} other
* @return {boolean}
*/
abutsStart(other) {
if (!this.isValid)
return false;
return +this.e === +other.s;
}
/**
* Return whether this Interval's start is adjacent to the specified Interval's end.
* @param {Interval} other
* @return {boolean}
*/
abutsEnd(other) {
if (!this.isValid)
return false;
return +other.e === +this.s;
}
/**
* Return whether this Interval engulfs the start and end of the specified Interval.
* @param {Interval} other
* @return {boolean}
*/
engulfs(other) {
if (!this.isValid)
return false;
return this.s <= other.s && this.e >= other.e;
}
/**
* Return whether this Interval has the same start and end as the specified Interval.
* @param {Interval} other
* @return {boolean}
*/
equals(other) {
if (!this.isValid || !other.isValid) {
return false;
}
return this.s.equals(other.s) && this.e.equals(other.e);
}
/**
* Return an Interval representing the intersection of this Interval and the specified Interval.
* Specifically, the resulting Interval has the maximum start time and the minimum end time of the two Intervals.
* Returns null if the intersection is empty, meaning, the intervals don't intersect.
* @param {Interval} other
* @return {Interval}
*/
intersection(other) {
if (!this.isValid)
return this;
const s2 = this.s > other.s ? this.s : other.s, e = this.e < other.e ? this.e : other.e;
if (s2 >= e) {
return null;
} else {
return Interval.fromDateTimes(s2, e);
}
}
/**
* Return an Interval representing the union of this Interval and the specified Interval.
* Specifically, the resulting Interval has the minimum start time and the maximum end time of the two Intervals.
* @param {Interval} other
* @return {Interval}
*/
union(other) {
if (!this.isValid)
return this;
const s2 = this.s < other.s ? this.s : other.s, e = this.e > other.e ? this.e : other.e;
return Interval.fromDateTimes(s2, e);
}
/**
* Merge an array of Intervals into a equivalent minimal set of Intervals.
* Combines overlapping and adjacent Intervals.
* @param {Array} intervals
* @return {Array}
*/
static merge(intervals) {
const [found, final] = intervals.sort((a, b) => a.s - b.s).reduce(
([sofar, current], item) => {
if (!current) {
return [sofar, item];
} else if (current.overlaps(item) || current.abutsStart(item)) {
return [sofar, current.union(item)];
} else {
return [sofar.concat([current]), item];
}
},
[[], null]
);
if (final) {
found.push(final);
}
return found;
}
/**
* Return an array of Intervals representing the spans of time that only appear in one of the specified Intervals.
* @param {Array} intervals
* @return {Array}
*/
static xor(intervals) {
let start = null, currentCount = 0;
const results = [], ends = intervals.map((i) => [
{ time: i.s, type: "s" },
{ time: i.e, type: "e" }
]), flattened = Array.prototype.concat(...ends), arr = flattened.sort((a, b) => a.time - b.time);
for (const i of arr) {
currentCount += i.type === "s" ? 1 : -1;
if (currentCount === 1) {
start = i.time;
} else {
if (start && +start !== +i.time) {
results.push(Interval.fromDateTimes(start, i.time));
}
start = null;
}
}
return Interval.merge(results);
}
/**
* Return an Interval representing the span of time in this Interval that doesn't overlap with any of the specified Intervals.
* @param {...Interval} intervals
* @return {Array}
*/
difference(...intervals) {
return Interval.xor([this].concat(intervals)).map((i) => this.intersection(i)).filter((i) => i && !i.isEmpty());
}
/**
* Returns a string representation of this Interval appropriate for debugging.
* @return {string}
*/
toString() {
if (!this.isValid)
return INVALID2;
return `[${this.s.toISO()} \u2013 ${this.e.toISO()})`;
}
/**
* Returns a localized string representing this Interval. Accepts the same options as the
* Intl.DateTimeFormat constructor and any presets defined by Luxon, such as
* {@link DateTime.DATE_FULL} or {@link DateTime.TIME_SIMPLE}. The exact behavior of this method
* is browser-specific, but in general it will return an appropriate representation of the
* Interval in the assigned locale. Defaults to the system's locale if no locale has been
* specified.
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
* @param {Object} [formatOpts=DateTime.DATE_SHORT] - Either a DateTime preset or
* Intl.DateTimeFormat constructor options.
* @param {Object} opts - Options to override the configuration of the start DateTime.
* @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(); //=> 11/7/2022 – 11/8/2022
* @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(DateTime.DATE_FULL); //=> November 7 – 8, 2022
* @example Interval.fromISO('2022-11-07T09:00Z/2022-11-08T09:00Z').toLocaleString(DateTime.DATE_FULL, { locale: 'fr-FR' }); //=> 7–8 novembre 2022
* @example Interval.fromISO('2022-11-07T17:00Z/2022-11-07T19:00Z').toLocaleString(DateTime.TIME_SIMPLE); //=> 6:00 – 8:00 PM
* @example Interval.fromISO('2022-11-07T17:00Z/2022-11-07T19:00Z').toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> Mon, Nov 07, 6:00 – 8:00 p
* @return {string}
*/
toLocaleString(formatOpts = DATE_SHORT, opts = {}) {
return this.isValid ? Formatter.create(this.s.loc.clone(opts), formatOpts).formatInterval(this) : INVALID2;
}
/**
* Returns an ISO 8601-compliant string representation of this Interval.
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
* @param {Object} opts - The same options as {@link DateTime#toISO}
* @return {string}
*/
toISO(opts) {
if (!this.isValid)
return INVALID2;
return `${this.s.toISO(opts)}/${this.e.toISO(opts)}`;
}
/**
* Returns an ISO 8601-compliant string representation of date of this Interval.
* The time components are ignored.
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
* @return {string}
*/
toISODate() {
if (!this.isValid)
return INVALID2;
return `${this.s.toISODate()}/${this.e.toISODate()}`;
}
/**
* Returns an ISO 8601-compliant string representation of time of this Interval.
* The date components are ignored.
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
* @param {Object} opts - The same options as {@link DateTime#toISO}
* @return {string}
*/
toISOTime(opts) {
if (!this.isValid)
return INVALID2;
return `${this.s.toISOTime(opts)}/${this.e.toISOTime(opts)}`;
}
/**
* Returns a string representation of this Interval formatted according to the specified format
* string. **You may not want this.** See {@link Interval#toLocaleString} for a more flexible
* formatting tool.
* @param {string} dateFormat - The format string. This string formats the start and end time.
* See {@link DateTime#toFormat} for details.
* @param {Object} opts - Options.
* @param {string} [opts.separator = ' – '] - A separator to place between the start and end
* representations.
* @return {string}
*/
toFormat(dateFormat, { separator = " \u2013 " } = {}) {
if (!this.isValid)
return INVALID2;
return `${this.s.toFormat(dateFormat)}${separator}${this.e.toFormat(dateFormat)}`;
}
/**
* Return a Duration representing the time spanned by this interval.
* @param {string|string[]} [unit=['milliseconds']] - the unit or units (such as 'hours' or 'days') to include in the duration.
* @param {Object} opts - options that affect the creation of the Duration
* @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
* @example Interval.fromDateTimes(dt1, dt2).toDuration().toObject() //=> { milliseconds: 88489257 }
* @example Interval.fromDateTimes(dt1, dt2).toDuration('days').toObject() //=> { days: 1.0241812152777778 }
* @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes']).toObject() //=> { hours: 24, minutes: 34.82095 }
* @example Interval.fromDateTimes(dt1, dt2).toDuration(['hours', 'minutes', 'seconds']).toObject() //=> { hours: 24, minutes: 34, seconds: 49.257 }
* @example Interval.fromDateTimes(dt1, dt2).toDuration('seconds').toObject() //=> { seconds: 88489.257 }
* @return {Duration}
*/
toDuration(unit, opts) {
if (!this.isValid) {
return Duration.invalid(this.invalidReason);
}
return this.e.diff(this.s, unit, opts);
}
/**
* Run mapFn on the interval start and end, returning a new Interval from the resulting DateTimes
* @param {function} mapFn
* @return {Interval}
* @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.toUTC())
* @example Interval.fromDateTimes(dt1, dt2).mapEndpoints(endpoint => endpoint.plus({ hours: 2 }))
*/
mapEndpoints(mapFn) {
return Interval.fromDateTimes(mapFn(this.s), mapFn(this.e));
}
};
// node_modules/luxon/src/info.js
var Info = class {
/**
* Return whether the specified zone contains a DST.
* @param {string|Zone} [zone='local'] - Zone to check. Defaults to the environment's local zone.
* @return {boolean}
*/
static hasDST(zone = Settings.defaultZone) {
const proto = DateTime.now().setZone(zone).set({ month: 12 });
return !zone.isUniversal && proto.offset !== proto.set({ month: 6 }).offset;
}
/**
* Return whether the specified zone is a valid IANA specifier.
* @param {string} zone - Zone to check
* @return {boolean}
*/
static isValidIANAZone(zone) {
return IANAZone.isValidZone(zone);
}
/**
* Converts the input into a {@link Zone} instance.
*
* * If `input` is already a Zone instance, it is returned unchanged.
* * If `input` is a string containing a valid time zone name, a Zone instance
* with that name is returned.
* * If `input` is a string that doesn't refer to a known time zone, a Zone
* instance with {@link Zone#isValid} == false is returned.
* * If `input is a number, a Zone instance with the specified fixed offset
* in minutes is returned.
* * If `input` is `null` or `undefined`, the default zone is returned.
* @param {string|Zone|number} [input] - the value to be converted
* @return {Zone}
*/
static normalizeZone(input) {
return normalizeZone(input, Settings.defaultZone);
}
/**
* Return an array of standalone month names.
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
* @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long"
* @param {Object} opts - options
* @param {string} [opts.locale] - the locale code
* @param {string} [opts.numberingSystem=null] - the numbering system
* @param {string} [opts.locObj=null] - an existing locale object to use
* @param {string} [opts.outputCalendar='gregory'] - the calendar
* @example Info.months()[0] //=> 'January'
* @example Info.months('short')[0] //=> 'Jan'
* @example Info.months('numeric')[0] //=> '1'
* @example Info.months('short', { locale: 'fr-CA' } )[0] //=> 'janv.'
* @example Info.months('numeric', { locale: 'ar' })[0] //=> '١'
* @example Info.months('long', { outputCalendar: 'islamic' })[0] //=> 'Rabiʻ I'
* @return {Array}
*/
static months(length = "long", { locale = null, numberingSystem = null, locObj = null, outputCalendar = "gregory" } = {}) {
return (locObj || Locale.create(locale, numberingSystem, outputCalendar)).months(length);
}
/**
* Return an array of format month names.
* Format months differ from standalone months in that they're meant to appear next to the day of the month. In some languages, that
* changes the string.
* See {@link Info#months}
* @param {string} [length='long'] - the length of the month representation, such as "numeric", "2-digit", "narrow", "short", "long"
* @param {Object} opts - options
* @param {string} [opts.locale] - the locale code
* @param {string} [opts.numberingSystem=null] - the numbering system
* @param {string} [opts.locObj=null] - an existing locale object to use
* @param {string} [opts.outputCalendar='gregory'] - the calendar
* @return {Array}
*/
static monthsFormat(length = "long", { locale = null, numberingSystem = null, locObj = null, outputCalendar = "gregory" } = {}) {
return (locObj || Locale.create(locale, numberingSystem, outputCalendar)).months(length, true);
}
/**
* Return an array of standalone week names.
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
* @param {string} [length='long'] - the length of the weekday representation, such as "narrow", "short", "long".
* @param {Object} opts - options
* @param {string} [opts.locale] - the locale code
* @param {string} [opts.numberingSystem=null] - the numbering system
* @param {string} [opts.locObj=null] - an existing locale object to use
* @example Info.weekdays()[0] //=> 'Monday'
* @example Info.weekdays('short')[0] //=> 'Mon'
* @example Info.weekdays('short', { locale: 'fr-CA' })[0] //=> 'lun.'
* @example Info.weekdays('short', { locale: 'ar' })[0] //=> 'الاثنين'
* @return {Array}
*/
static weekdays(length = "long", { locale = null, numberingSystem = null, locObj = null } = {}) {
return (locObj || Locale.create(locale, numberingSystem, null)).weekdays(length);
}
/**
* Return an array of format week names.
* Format weekdays differ from standalone weekdays in that they're meant to appear next to more date information. In some languages, that
* changes the string.
* See {@link Info#weekdays}
* @param {string} [length='long'] - the length of the month representation, such as "narrow", "short", "long".
* @param {Object} opts - options
* @param {string} [opts.locale=null] - the locale code
* @param {string} [opts.numberingSystem=null] - the numbering system
* @param {string} [opts.locObj=null] - an existing locale object to use
* @return {Array}
*/
static weekdaysFormat(length = "long", { locale = null, numberingSystem = null, locObj = null } = {}) {
return (locObj || Locale.create(locale, numberingSystem, null)).weekdays(length, true);
}
/**
* Return an array of meridiems.
* @param {Object} opts - options
* @param {string} [opts.locale] - the locale code
* @example Info.meridiems() //=> [ 'AM', 'PM' ]
* @example Info.meridiems({ locale: 'my' }) //=> [ 'နံနက်', 'ညနေ' ]
* @return {Array}
*/
static meridiems({ locale = null } = {}) {
return Locale.create(locale).meridiems();
}
/**
* Return an array of eras, such as ['BC', 'AD']. The locale can be specified, but the calendar system is always Gregorian.
* @param {string} [length='short'] - the length of the era representation, such as "short" or "long".
* @param {Object} opts - options
* @param {string} [opts.locale] - the locale code
* @example Info.eras() //=> [ 'BC', 'AD' ]
* @example Info.eras('long') //=> [ 'Before Christ', 'Anno Domini' ]
* @example Info.eras('long', { locale: 'fr' }) //=> [ 'avant Jésus-Christ', 'après Jésus-Christ' ]
* @return {Array}
*/
static eras(length = "short", { locale = null } = {}) {
return Locale.create(locale, null, "gregory").eras(length);
}
/**
* Return the set of available features in this environment.
* Some features of Luxon are not available in all environments. For example, on older browsers, relative time formatting support is not available. Use this function to figure out if that's the case.
* Keys:
* * `relative`: whether this environment supports relative time formatting
* @example Info.features() //=> { relative: false }
* @return {Object}
*/
static features() {
return { relative: hasRelative() };
}
};
// node_modules/luxon/src/impl/diff.js
function dayDiff(earlier, later) {
const utcDayStart = (dt) => dt.toUTC(0, { keepLocalTime: true }).startOf("day").valueOf(), ms = utcDayStart(later) - utcDayStart(earlier);
return Math.floor(Duration.fromMillis(ms).as("days"));
}
function highOrderDiffs(cursor, later, units) {
const differs = [
["years", (a, b) => b.year - a.year],
["quarters", (a, b) => b.quarter - a.quarter + (b.year - a.year) * 4],
["months", (a, b) => b.month - a.month + (b.year - a.year) * 12],
[
"weeks",
(a, b) => {
const days = dayDiff(a, b);
return (days - days % 7) / 7;
}
],
["days", dayDiff]
];
const results = {};
const earlier = cursor;
let lowestOrder, highWater;
for (const [unit, differ] of differs) {
if (units.indexOf(unit) >= 0) {
lowestOrder = unit;
results[unit] = differ(cursor, later);
highWater = earlier.plus(results);
if (highWater > later) {
results[unit]--;
cursor = earlier.plus(results);
} else {
cursor = highWater;
}
}
}
return [cursor, results, highWater, lowestOrder];
}
function diff_default(earlier, later, units, opts) {
let [cursor, results, highWater, lowestOrder] = highOrderDiffs(earlier, later, units);
const remainingMillis = later - cursor;
const lowerOrderUnits = units.filter(
(u) => ["hours", "minutes", "seconds", "milliseconds"].indexOf(u) >= 0
);
if (lowerOrderUnits.length === 0) {
if (highWater < later) {
highWater = cursor.plus({ [lowestOrder]: 1 });
}
if (highWater !== cursor) {
results[lowestOrder] = (results[lowestOrder] || 0) + remainingMillis / (highWater - cursor);
}
}
const duration = Duration.fromObject(results, opts);
if (lowerOrderUnits.length > 0) {
return Duration.fromMillis(remainingMillis, opts).shiftTo(...lowerOrderUnits).plus(duration);
} else {
return duration;
}
}
// node_modules/luxon/src/impl/digits.js
var numberingSystems = {
arab: "[\u0660-\u0669]",
arabext: "[\u06F0-\u06F9]",
bali: "[\u1B50-\u1B59]",
beng: "[\u09E6-\u09EF]",
deva: "[\u0966-\u096F]",
fullwide: "[\uFF10-\uFF19]",
gujr: "[\u0AE6-\u0AEF]",
hanidec: "[\u3007|\u4E00|\u4E8C|\u4E09|\u56DB|\u4E94|\u516D|\u4E03|\u516B|\u4E5D]",
khmr: "[\u17E0-\u17E9]",
knda: "[\u0CE6-\u0CEF]",
laoo: "[\u0ED0-\u0ED9]",
limb: "[\u1946-\u194F]",
mlym: "[\u0D66-\u0D6F]",
mong: "[\u1810-\u1819]",
mymr: "[\u1040-\u1049]",
orya: "[\u0B66-\u0B6F]",
tamldec: "[\u0BE6-\u0BEF]",
telu: "[\u0C66-\u0C6F]",
thai: "[\u0E50-\u0E59]",
tibt: "[\u0F20-\u0F29]",
latn: "\\d"
};
var numberingSystemsUTF16 = {
arab: [1632, 1641],
arabext: [1776, 1785],
bali: [6992, 7001],
beng: [2534, 2543],
deva: [2406, 2415],
fullwide: [65296, 65303],
gujr: [2790, 2799],
khmr: [6112, 6121],
knda: [3302, 3311],
laoo: [3792, 3801],
limb: [6470, 6479],
mlym: [3430, 3439],
mong: [6160, 6169],
mymr: [4160, 4169],
orya: [2918, 2927],
tamldec: [3046, 3055],
telu: [3174, 3183],
thai: [3664, 3673],
tibt: [3872, 3881]
};
var hanidecChars = numberingSystems.hanidec.replace(/[\[|\]]/g, "").split("");
function parseDigits(str) {
let value = parseInt(str, 10);
if (isNaN(value)) {
value = "";
for (let i = 0; i < str.length; i++) {
const code = str.charCodeAt(i);
if (str[i].search(numberingSystems.hanidec) !== -1) {
value += hanidecChars.indexOf(str[i]);
} else {
for (const key in numberingSystemsUTF16) {
const [min, max] = numberingSystemsUTF16[key];
if (code >= min && code <= max) {
value += code - min;
}
}
}
}
return parseInt(value, 10);
} else {
return value;
}
}
function digitRegex({ numberingSystem }, append = "") {
return new RegExp(`${numberingSystems[numberingSystem || "latn"]}${append}`);
}
// node_modules/luxon/src/impl/tokenParser.js
var MISSING_FTP = "missing Intl.DateTimeFormat.formatToParts support";
function intUnit(regex, post = (i) => i) {
return { regex, deser: ([s2]) => post(parseDigits(s2)) };
}
var NBSP = String.fromCharCode(160);
var spaceOrNBSP = `[ ${NBSP}]`;
var spaceOrNBSPRegExp = new RegExp(spaceOrNBSP, "g");
function fixListRegex(s2) {
return s2.replace(/\./g, "\\.?").replace(spaceOrNBSPRegExp, spaceOrNBSP);
}
function stripInsensitivities(s2) {
return s2.replace(/\./g, "").replace(spaceOrNBSPRegExp, " ").toLowerCase();
}
function oneOf(strings, startIndex) {
if (strings === null) {
return null;
} else {
return {
regex: RegExp(strings.map(fixListRegex).join("|")),
deser: ([s2]) => strings.findIndex((i) => stripInsensitivities(s2) === stripInsensitivities(i)) + startIndex
};
}
}
function offset(regex, groups) {
return { regex, deser: ([, h, m]) => signedOffset(h, m), groups };
}
function simple(regex) {
return { regex, deser: ([s2]) => s2 };
}
function escapeToken(value) {
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
}
function unitForToken(token, loc) {
const one = digitRegex(loc), two = digitRegex(loc, "{2}"), three = digitRegex(loc, "{3}"), four = digitRegex(loc, "{4}"), six = digitRegex(loc, "{6}"), oneOrTwo = digitRegex(loc, "{1,2}"), oneToThree = digitRegex(loc, "{1,3}"), oneToSix = digitRegex(loc, "{1,6}"), oneToNine = digitRegex(loc, "{1,9}"), twoToFour = digitRegex(loc, "{2,4}"), fourToSix = digitRegex(loc, "{4,6}"), literal = (t) => ({ regex: RegExp(escapeToken(t.val)), deser: ([s2]) => s2, literal: true }), unitate = (t) => {
if (token.literal) {
return literal(t);
}
switch (t.val) {
case "G":
return oneOf(loc.eras("short", false), 0);
case "GG":
return oneOf(loc.eras("long", false), 0);
case "y":
return intUnit(oneToSix);
case "yy":
return intUnit(twoToFour, untruncateYear);
case "yyyy":
return intUnit(four);
case "yyyyy":
return intUnit(fourToSix);
case "yyyyyy":
return intUnit(six);
case "M":
return intUnit(oneOrTwo);
case "MM":
return intUnit(two);
case "MMM":
return oneOf(loc.months("short", true, false), 1);
case "MMMM":
return oneOf(loc.months("long", true, false), 1);
case "L":
return intUnit(oneOrTwo);
case "LL":
return intUnit(two);
case "LLL":
return oneOf(loc.months("short", false, false), 1);
case "LLLL":
return oneOf(loc.months("long", false, false), 1);
case "d":
return intUnit(oneOrTwo);
case "dd":
return intUnit(two);
case "o":
return intUnit(oneToThree);
case "ooo":
return intUnit(three);
case "HH":
return intUnit(two);
case "H":
return intUnit(oneOrTwo);
case "hh":
return intUnit(two);
case "h":
return intUnit(oneOrTwo);
case "mm":
return intUnit(two);
case "m":
return intUnit(oneOrTwo);
case "q":
return intUnit(oneOrTwo);
case "qq":
return intUnit(two);
case "s":
return intUnit(oneOrTwo);
case "ss":
return intUnit(two);
case "S":
return intUnit(oneToThree);
case "SSS":
return intUnit(three);
case "u":
return simple(oneToNine);
case "uu":
return simple(oneOrTwo);
case "uuu":
return intUnit(one);
case "a":
return oneOf(loc.meridiems(), 0);
case "kkkk":
return intUnit(four);
case "kk":
return intUnit(twoToFour, untruncateYear);
case "W":
return intUnit(oneOrTwo);
case "WW":
return intUnit(two);
case "E":
case "c":
return intUnit(one);
case "EEE":
return oneOf(loc.weekdays("short", false, false), 1);
case "EEEE":
return oneOf(loc.weekdays("long", false, false), 1);
case "ccc":
return oneOf(loc.weekdays("short", true, false), 1);
case "cccc":
return oneOf(loc.weekdays("long", true, false), 1);
case "Z":
case "ZZ":
return offset(new RegExp(`([+-]${oneOrTwo.source})(?::(${two.source}))?`), 2);
case "ZZZ":
return offset(new RegExp(`([+-]${oneOrTwo.source})(${two.source})?`), 2);
case "z":
return simple(/[a-z_+-/]{1,256}?/i);
case " ":
return simple(/[^\S\n\r]/);
default:
return literal(t);
}
};
const unit = unitate(token) || {
invalidReason: MISSING_FTP
};
unit.token = token;
return unit;
}
var partTypeStyleToTokenVal = {
year: {
"2-digit": "yy",
numeric: "yyyyy"
},
month: {
numeric: "M",
"2-digit": "MM",
short: "MMM",
long: "MMMM"
},
day: {
numeric: "d",
"2-digit": "dd"
},
weekday: {
short: "EEE",
long: "EEEE"
},
dayperiod: "a",
dayPeriod: "a",
hour: {
numeric: "h",
"2-digit": "hh"
},
minute: {
numeric: "m",
"2-digit": "mm"
},
second: {
numeric: "s",
"2-digit": "ss"
},
timeZoneName: {
long: "ZZZZZ",
short: "ZZZ"
}
};
function tokenForPart(part, formatOpts) {
const { type, value } = part;
if (type === "literal") {
const isSpace = /^\s+$/.test(value);
return {
literal: !isSpace,
val: isSpace ? " " : value
};
}
const style = formatOpts[type];
let val = partTypeStyleToTokenVal[type];
if (typeof val === "object") {
val = val[style];
}
if (val) {
return {
literal: false,
val
};
}
return void 0;
}
function buildRegex(units) {
const re = units.map((u) => u.regex).reduce((f, r) => `${f}(${r.source})`, "");
return [`^${re}$`, units];
}
function match(input, regex, handlers) {
const matches = input.match(regex);
if (matches) {
const all = {};
let matchIndex = 1;
for (const i in handlers) {
if (hasOwnProperty(handlers, i)) {
const h = handlers[i], groups = h.groups ? h.groups + 1 : 1;
if (!h.literal && h.token) {
all[h.token.val[0]] = h.deser(matches.slice(matchIndex, matchIndex + groups));
}
matchIndex += groups;
}
}
return [matches, all];
} else {
return [matches, {}];
}
}
function dateTimeFromMatches(matches) {
const toField = (token) => {
switch (token) {
case "S":
return "millisecond";
case "s":
return "second";
case "m":
return "minute";
case "h":
case "H":
return "hour";
case "d":
return "day";
case "o":
return "ordinal";
case "L":
case "M":
return "month";
case "y":
return "year";
case "E":
case "c":
return "weekday";
case "W":
return "weekNumber";
case "k":
return "weekYear";
case "q":
return "quarter";
default:
return null;
}
};
let zone = null;
let specificOffset;
if (!isUndefined(matches.z)) {
zone = IANAZone.create(matches.z);
}
if (!isUndefined(matches.Z)) {
if (!zone) {
zone = new FixedOffsetZone(matches.Z);
}
specificOffset = matches.Z;
}
if (!isUndefined(matches.q)) {
matches.M = (matches.q - 1) * 3 + 1;
}
if (!isUndefined(matches.h)) {
if (matches.h < 12 && matches.a === 1) {
matches.h += 12;
} else if (matches.h === 12 && matches.a === 0) {
matches.h = 0;
}
}
if (matches.G === 0 && matches.y) {
matches.y = -matches.y;
}
if (!isUndefined(matches.u)) {
matches.S = parseMillis(matches.u);
}
const vals = Object.keys(matches).reduce((r, k) => {
const f = toField(k);
if (f) {
r[f] = matches[k];
}
return r;
}, {});
return [vals, zone, specificOffset];
}
var dummyDateTimeCache = null;
function getDummyDateTime() {
if (!dummyDateTimeCache) {
dummyDateTimeCache = DateTime.fromMillis(1555555555555);
}
return dummyDateTimeCache;
}
function maybeExpandMacroToken(token, locale) {
if (token.literal) {
return token;
}
const formatOpts = Formatter.macroTokenToFormatOpts(token.val);
const tokens = formatOptsToTokens(formatOpts, locale);
if (tokens == null || tokens.includes(void 0)) {
return token;
}
return tokens;
}
function expandMacroTokens(tokens, locale) {
return Array.prototype.concat(...tokens.map((t) => maybeExpandMacroToken(t, locale)));
}
function explainFromTokens(locale, input, format) {
const tokens = expandMacroTokens(Formatter.parseFormat(format), locale), units = tokens.map((t) => unitForToken(t, locale)), disqualifyingUnit = units.find((t) => t.invalidReason);
if (disqualifyingUnit) {
return { input, tokens, invalidReason: disqualifyingUnit.invalidReason };
} else {
const [regexString, handlers] = buildRegex(units), regex = RegExp(regexString, "i"), [rawMatches, matches] = match(input, regex, handlers), [result, zone, specificOffset] = matches ? dateTimeFromMatches(matches) : [null, null, void 0];
if (hasOwnProperty(matches, "a") && hasOwnProperty(matches, "H")) {
throw new ConflictingSpecificationError(
"Can't include meridiem when specifying 24-hour format"
);
}
return { input, tokens, regex, rawMatches, matches, result, zone, specificOffset };
}
}
function parseFromTokens(locale, input, format) {
const { result, zone, specificOffset, invalidReason } = explainFromTokens(locale, input, format);
return [result, zone, specificOffset, invalidReason];
}
function formatOptsToTokens(formatOpts, locale) {
if (!formatOpts) {
return null;
}
const formatter = Formatter.create(locale, formatOpts);
const parts = formatter.formatDateTimeParts(getDummyDateTime());
return parts.map((p) => tokenForPart(p, formatOpts));
}
// node_modules/luxon/src/impl/conversions.js
var nonLeapLadder = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
var leapLadder = [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335];
function unitOutOfRange(unit, value) {
return new Invalid(
"unit out of range",
`you specified ${value} (of type ${typeof value}) as a ${unit}, which is invalid`
);
}
function dayOfWeek(year, month, day) {
const d = new Date(Date.UTC(year, month - 1, day));
if (year < 100 && year >= 0) {
d.setUTCFullYear(d.getUTCFullYear() - 1900);
}
const js = d.getUTCDay();
return js === 0 ? 7 : js;
}
function computeOrdinal(year, month, day) {
return day + (isLeapYear(year) ? leapLadder : nonLeapLadder)[month - 1];
}
function uncomputeOrdinal(year, ordinal) {
const table = isLeapYear(year) ? leapLadder : nonLeapLadder, month0 = table.findIndex((i) => i < ordinal), day = ordinal - table[month0];
return { month: month0 + 1, day };
}
function gregorianToWeek(gregObj) {
const { year, month, day } = gregObj, ordinal = computeOrdinal(year, month, day), weekday = dayOfWeek(year, month, day);
let weekNumber = Math.floor((ordinal - weekday + 10) / 7), weekYear;
if (weekNumber < 1) {
weekYear = year - 1;
weekNumber = weeksInWeekYear(weekYear);
} else if (weekNumber > weeksInWeekYear(year)) {
weekYear = year + 1;
weekNumber = 1;
} else {
weekYear = year;
}
return { weekYear, weekNumber, weekday, ...timeObject(gregObj) };
}
function weekToGregorian(weekData) {
const { weekYear, weekNumber, weekday } = weekData, weekdayOfJan4 = dayOfWeek(weekYear, 1, 4), yearInDays = daysInYear(weekYear);
let ordinal = weekNumber * 7 + weekday - weekdayOfJan4 - 3, year;
if (ordinal < 1) {
year = weekYear - 1;
ordinal += daysInYear(year);
} else if (ordinal > yearInDays) {
year = weekYear + 1;
ordinal -= daysInYear(weekYear);
} else {
year = weekYear;
}
const { month, day } = uncomputeOrdinal(year, ordinal);
return { year, month, day, ...timeObject(weekData) };
}
function gregorianToOrdinal(gregData) {
const { year, month, day } = gregData;
const ordinal = computeOrdinal(year, month, day);
return { year, ordinal, ...timeObject(gregData) };
}
function ordinalToGregorian(ordinalData) {
const { year, ordinal } = ordinalData;
const { month, day } = uncomputeOrdinal(year, ordinal);
return { year, month, day, ...timeObject(ordinalData) };
}
function hasInvalidWeekData(obj) {
const validYear = isInteger(obj.weekYear), validWeek = integerBetween(obj.weekNumber, 1, weeksInWeekYear(obj.weekYear)), validWeekday = integerBetween(obj.weekday, 1, 7);
if (!validYear) {
return unitOutOfRange("weekYear", obj.weekYear);
} else if (!validWeek) {
return unitOutOfRange("week", obj.week);
} else if (!validWeekday) {
return unitOutOfRange("weekday", obj.weekday);
} else
return false;
}
function hasInvalidOrdinalData(obj) {
const validYear = isInteger(obj.year), validOrdinal = integerBetween(obj.ordinal, 1, daysInYear(obj.year));
if (!validYear) {
return unitOutOfRange("year", obj.year);
} else if (!validOrdinal) {
return unitOutOfRange("ordinal", obj.ordinal);
} else
return false;
}
function hasInvalidGregorianData(obj) {
const validYear = isInteger(obj.year), validMonth = integerBetween(obj.month, 1, 12), validDay = integerBetween(obj.day, 1, daysInMonth(obj.year, obj.month));
if (!validYear) {
return unitOutOfRange("year", obj.year);
} else if (!validMonth) {
return unitOutOfRange("month", obj.month);
} else if (!validDay) {
return unitOutOfRange("day", obj.day);
} else
return false;
}
function hasInvalidTimeData(obj) {
const { hour, minute, second, millisecond } = obj;
const validHour = integerBetween(hour, 0, 23) || hour === 24 && minute === 0 && second === 0 && millisecond === 0, validMinute = integerBetween(minute, 0, 59), validSecond = integerBetween(second, 0, 59), validMillisecond = integerBetween(millisecond, 0, 999);
if (!validHour) {
return unitOutOfRange("hour", hour);
} else if (!validMinute) {
return unitOutOfRange("minute", minute);
} else if (!validSecond) {
return unitOutOfRange("second", second);
} else if (!validMillisecond) {
return unitOutOfRange("millisecond", millisecond);
} else
return false;
}
// node_modules/luxon/src/datetime.js
var INVALID3 = "Invalid DateTime";
var MAX_DATE = 864e13;
function unsupportedZone(zone) {
return new Invalid("unsupported zone", `the zone "${zone.name}" is not supported`);
}
function possiblyCachedWeekData(dt) {
if (dt.weekData === null) {
dt.weekData = gregorianToWeek(dt.c);
}
return dt.weekData;
}
function clone2(inst, alts) {
const current = {
ts: inst.ts,
zone: inst.zone,
c: inst.c,
o: inst.o,
loc: inst.loc,
invalid: inst.invalid
};
return new DateTime({ ...current, ...alts, old: current });
}
function fixOffset(localTS, o, tz) {
let utcGuess = localTS - o * 60 * 1e3;
const o2 = tz.offset(utcGuess);
if (o === o2) {
return [utcGuess, o];
}
utcGuess -= (o2 - o) * 60 * 1e3;
const o3 = tz.offset(utcGuess);
if (o2 === o3) {
return [utcGuess, o2];
}
return [localTS - Math.min(o2, o3) * 60 * 1e3, Math.max(o2, o3)];
}
function tsToObj(ts, offset2) {
ts += offset2 * 60 * 1e3;
const d = new Date(ts);
return {
year: d.getUTCFullYear(),
month: d.getUTCMonth() + 1,
day: d.getUTCDate(),
hour: d.getUTCHours(),
minute: d.getUTCMinutes(),
second: d.getUTCSeconds(),
millisecond: d.getUTCMilliseconds()
};
}
function objToTS(obj, offset2, zone) {
return fixOffset(objToLocalTS(obj), offset2, zone);
}
function adjustTime(inst, dur) {
const oPre = inst.o, year = inst.c.year + Math.trunc(dur.years), month = inst.c.month + Math.trunc(dur.months) + Math.trunc(dur.quarters) * 3, c = {
...inst.c,
year,
month,
day: Math.min(inst.c.day, daysInMonth(year, month)) + Math.trunc(dur.days) + Math.trunc(dur.weeks) * 7
}, millisToAdd = Duration.fromObject({
years: dur.years - Math.trunc(dur.years),
quarters: dur.quarters - Math.trunc(dur.quarters),
months: dur.months - Math.trunc(dur.months),
weeks: dur.weeks - Math.trunc(dur.weeks),
days: dur.days - Math.trunc(dur.days),
hours: dur.hours,
minutes: dur.minutes,
seconds: dur.seconds,
milliseconds: dur.milliseconds
}).as("milliseconds"), localTS = objToLocalTS(c);
let [ts, o] = fixOffset(localTS, oPre, inst.zone);
if (millisToAdd !== 0) {
ts += millisToAdd;
o = inst.zone.offset(ts);
}
return { ts, o };
}
function parseDataToDateTime(parsed, parsedZone, opts, format, text, specificOffset) {
const { setZone, zone } = opts;
if (parsed && Object.keys(parsed).length !== 0 || parsedZone) {
const interpretationZone = parsedZone || zone, inst = DateTime.fromObject(parsed, {
...opts,
zone: interpretationZone,
specificOffset
});
return setZone ? inst : inst.setZone(zone);
} else {
return DateTime.invalid(
new Invalid("unparsable", `the input "${text}" can't be parsed as ${format}`)
);
}
}
function toTechFormat(dt, format, allowZ = true) {
return dt.isValid ? Formatter.create(Locale.create("en-US"), {
allowZ,
forceSimple: true
}).formatDateTimeFromString(dt, format) : null;
}
function toISODate(o, extended) {
const longFormat = o.c.year > 9999 || o.c.year < 0;
let c = "";
if (longFormat && o.c.year >= 0)
c += "+";
c += padStart(o.c.year, longFormat ? 6 : 4);
if (extended) {
c += "-";
c += padStart(o.c.month);
c += "-";
c += padStart(o.c.day);
} else {
c += padStart(o.c.month);
c += padStart(o.c.day);
}
return c;
}
function toISOTime(o, extended, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone) {
let c = padStart(o.c.hour);
if (extended) {
c += ":";
c += padStart(o.c.minute);
if (o.c.second !== 0 || !suppressSeconds) {
c += ":";
}
} else {
c += padStart(o.c.minute);
}
if (o.c.second !== 0 || !suppressSeconds) {
c += padStart(o.c.second);
if (o.c.millisecond !== 0 || !suppressMilliseconds) {
c += ".";
c += padStart(o.c.millisecond, 3);
}
}
if (includeOffset) {
if (o.isOffsetFixed && o.offset === 0 && !extendedZone) {
c += "Z";
} else if (o.o < 0) {
c += "-";
c += padStart(Math.trunc(-o.o / 60));
c += ":";
c += padStart(Math.trunc(-o.o % 60));
} else {
c += "+";
c += padStart(Math.trunc(o.o / 60));
c += ":";
c += padStart(Math.trunc(o.o % 60));
}
}
if (extendedZone) {
c += "[" + o.zone.ianaName + "]";
}
return c;
}
var defaultUnitValues = {
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0,
millisecond: 0
};
var defaultWeekUnitValues = {
weekNumber: 1,
weekday: 1,
hour: 0,
minute: 0,
second: 0,
millisecond: 0
};
var defaultOrdinalUnitValues = {
ordinal: 1,
hour: 0,
minute: 0,
second: 0,
millisecond: 0
};
var orderedUnits2 = ["year", "month", "day", "hour", "minute", "second", "millisecond"];
var orderedWeekUnits = [
"weekYear",
"weekNumber",
"weekday",
"hour",
"minute",
"second",
"millisecond"
];
var orderedOrdinalUnits = ["year", "ordinal", "hour", "minute", "second", "millisecond"];
function normalizeUnit(unit) {
const normalized = {
year: "year",
years: "year",
month: "month",
months: "month",
day: "day",
days: "day",
hour: "hour",
hours: "hour",
minute: "minute",
minutes: "minute",
quarter: "quarter",
quarters: "quarter",
second: "second",
seconds: "second",
millisecond: "millisecond",
milliseconds: "millisecond",
weekday: "weekday",
weekdays: "weekday",
weeknumber: "weekNumber",
weeksnumber: "weekNumber",
weeknumbers: "weekNumber",
weekyear: "weekYear",
weekyears: "weekYear",
ordinal: "ordinal"
}[unit.toLowerCase()];
if (!normalized)
throw new InvalidUnitError(unit);
return normalized;
}
function quickDT(obj, opts) {
const zone = normalizeZone(opts.zone, Settings.defaultZone), loc = Locale.fromObject(opts), tsNow = Settings.now();
let ts, o;
if (!isUndefined(obj.year)) {
for (const u of orderedUnits2) {
if (isUndefined(obj[u])) {
obj[u] = defaultUnitValues[u];
}
}
const invalid = hasInvalidGregorianData(obj) || hasInvalidTimeData(obj);
if (invalid) {
return DateTime.invalid(invalid);
}
const offsetProvis = zone.offset(tsNow);
[ts, o] = objToTS(obj, offsetProvis, zone);
} else {
ts = tsNow;
}
return new DateTime({ ts, zone, loc, o });
}
function diffRelative(start, end, opts) {
const round = isUndefined(opts.round) ? true : opts.round, format = (c, unit) => {
c = roundTo(c, round || opts.calendary ? 0 : 2, true);
const formatter = end.loc.clone(opts).relFormatter(opts);
return formatter.format(c, unit);
}, differ = (unit) => {
if (opts.calendary) {
if (!end.hasSame(start, unit)) {
return end.startOf(unit).diff(start.startOf(unit), unit).get(unit);
} else
return 0;
} else {
return end.diff(start, unit).get(unit);
}
};
if (opts.unit) {
return format(differ(opts.unit), opts.unit);
}
for (const unit of opts.units) {
const count = differ(unit);
if (Math.abs(count) >= 1) {
return format(count, unit);
}
}
return format(start > end ? -0 : 0, opts.units[opts.units.length - 1]);
}
function lastOpts(argList) {
let opts = {}, args;
if (argList.length > 0 && typeof argList[argList.length - 1] === "object") {
opts = argList[argList.length - 1];
args = Array.from(argList).slice(0, argList.length - 1);
} else {
args = Array.from(argList);
}
return [opts, args];
}
var DateTime = class {
/**
* @access private
*/
constructor(config) {
const zone = config.zone || Settings.defaultZone;
let invalid = config.invalid || (Number.isNaN(config.ts) ? new Invalid("invalid input") : null) || (!zone.isValid ? unsupportedZone(zone) : null);
this.ts = isUndefined(config.ts) ? Settings.now() : config.ts;
let c = null, o = null;
if (!invalid) {
const unchanged = config.old && config.old.ts === this.ts && config.old.zone.equals(zone);
if (unchanged) {
[c, o] = [config.old.c, config.old.o];
} else {
const ot = zone.offset(this.ts);
c = tsToObj(this.ts, ot);
invalid = Number.isNaN(c.year) ? new Invalid("invalid input") : null;
c = invalid ? null : c;
o = invalid ? null : ot;
}
}
this._zone = zone;
this.loc = config.loc || Locale.create();
this.invalid = invalid;
this.weekData = null;
this.c = c;
this.o = o;
this.isLuxonDateTime = true;
}
// CONSTRUCT
/**
* Create a DateTime for the current instant, in the system's time zone.
*
* Use Settings to override these default values if needed.
* @example DateTime.now().toISO() //~> now in the ISO format
* @return {DateTime}
*/
static now() {
return new DateTime({});
}
/**
* Create a local DateTime
* @param {number} [year] - The calendar year. If omitted (as in, call `local()` with no arguments), the current time will be used
* @param {number} [month=1] - The month, 1-indexed
* @param {number} [day=1] - The day of the month, 1-indexed
* @param {number} [hour=0] - The hour of the day, in 24-hour time
* @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59
* @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59
* @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999
* @example DateTime.local() //~> now
* @example DateTime.local({ zone: "America/New_York" }) //~> now, in US east coast time
* @example DateTime.local(2017) //~> 2017-01-01T00:00:00
* @example DateTime.local(2017, 3) //~> 2017-03-01T00:00:00
* @example DateTime.local(2017, 3, 12, { locale: "fr" }) //~> 2017-03-12T00:00:00, with a French locale
* @example DateTime.local(2017, 3, 12, 5) //~> 2017-03-12T05:00:00
* @example DateTime.local(2017, 3, 12, 5, { zone: "utc" }) //~> 2017-03-12T05:00:00, in UTC
* @example DateTime.local(2017, 3, 12, 5, 45) //~> 2017-03-12T05:45:00
* @example DateTime.local(2017, 3, 12, 5, 45, 10) //~> 2017-03-12T05:45:10
* @example DateTime.local(2017, 3, 12, 5, 45, 10, 765) //~> 2017-03-12T05:45:10.765
* @return {DateTime}
*/
static local() {
const [opts, args] = lastOpts(arguments), [year, month, day, hour, minute, second, millisecond] = args;
return quickDT({ year, month, day, hour, minute, second, millisecond }, opts);
}
/**
* Create a DateTime in UTC
* @param {number} [year] - The calendar year. If omitted (as in, call `utc()` with no arguments), the current time will be used
* @param {number} [month=1] - The month, 1-indexed
* @param {number} [day=1] - The day of the month
* @param {number} [hour=0] - The hour of the day, in 24-hour time
* @param {number} [minute=0] - The minute of the hour, meaning a number between 0 and 59
* @param {number} [second=0] - The second of the minute, meaning a number between 0 and 59
* @param {number} [millisecond=0] - The millisecond of the second, meaning a number between 0 and 999
* @param {Object} options - configuration options for the DateTime
* @param {string} [options.locale] - a locale to set on the resulting DateTime instance
* @param {string} [options.outputCalendar] - the output calendar to set on the resulting DateTime instance
* @param {string} [options.numberingSystem] - the numbering system to set on the resulting DateTime instance
* @example DateTime.utc() //~> now
* @example DateTime.utc(2017) //~> 2017-01-01T00:00:00Z
* @example DateTime.utc(2017, 3) //~> 2017-03-01T00:00:00Z
* @example DateTime.utc(2017, 3, 12) //~> 2017-03-12T00:00:00Z
* @example DateTime.utc(2017, 3, 12, 5) //~> 2017-03-12T05:00:00Z
* @example DateTime.utc(2017, 3, 12, 5, 45) //~> 2017-03-12T05:45:00Z
* @example DateTime.utc(2017, 3, 12, 5, 45, { locale: "fr" }) //~> 2017-03-12T05:45:00Z with a French locale
* @example DateTime.utc(2017, 3, 12, 5, 45, 10) //~> 2017-03-12T05:45:10Z
* @example DateTime.utc(2017, 3, 12, 5, 45, 10, 765, { locale: "fr" }) //~> 2017-03-12T05:45:10.765Z with a French locale
* @return {DateTime}
*/
static utc() {
const [opts, args] = lastOpts(arguments), [year, month, day, hour, minute, second, millisecond] = args;
opts.zone = FixedOffsetZone.utcInstance;
return quickDT({ year, month, day, hour, minute, second, millisecond }, opts);
}
/**
* Create a DateTime from a JavaScript Date object. Uses the default zone.
* @param {Date} date - a JavaScript Date object
* @param {Object} options - configuration options for the DateTime
* @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into
* @return {DateTime}
*/
static fromJSDate(date, options = {}) {
const ts = isDate(date) ? date.valueOf() : NaN;
if (Number.isNaN(ts)) {
return DateTime.invalid("invalid input");
}
const zoneToUse = normalizeZone(options.zone, Settings.defaultZone);
if (!zoneToUse.isValid) {
return DateTime.invalid(unsupportedZone(zoneToUse));
}
return new DateTime({
ts,
zone: zoneToUse,
loc: Locale.fromObject(options)
});
}
/**
* Create a DateTime from a number of milliseconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone.
* @param {number} milliseconds - a number of milliseconds since 1970 UTC
* @param {Object} options - configuration options for the DateTime
* @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into
* @param {string} [options.locale] - a locale to set on the resulting DateTime instance
* @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance
* @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance
* @return {DateTime}
*/
static fromMillis(milliseconds, options = {}) {
if (!isNumber(milliseconds)) {
throw new InvalidArgumentError(
`fromMillis requires a numerical input, but received a ${typeof milliseconds} with value ${milliseconds}`
);
} else if (milliseconds < -MAX_DATE || milliseconds > MAX_DATE) {
return DateTime.invalid("Timestamp out of range");
} else {
return new DateTime({
ts: milliseconds,
zone: normalizeZone(options.zone, Settings.defaultZone),
loc: Locale.fromObject(options)
});
}
}
/**
* Create a DateTime from a number of seconds since the epoch (meaning since 1 January 1970 00:00:00 UTC). Uses the default zone.
* @param {number} seconds - a number of seconds since 1970 UTC
* @param {Object} options - configuration options for the DateTime
* @param {string|Zone} [options.zone='local'] - the zone to place the DateTime into
* @param {string} [options.locale] - a locale to set on the resulting DateTime instance
* @param {string} options.outputCalendar - the output calendar to set on the resulting DateTime instance
* @param {string} options.numberingSystem - the numbering system to set on the resulting DateTime instance
* @return {DateTime}
*/
static fromSeconds(seconds, options = {}) {
if (!isNumber(seconds)) {
throw new InvalidArgumentError("fromSeconds requires a numerical input");
} else {
return new DateTime({
ts: seconds * 1e3,
zone: normalizeZone(options.zone, Settings.defaultZone),
loc: Locale.fromObject(options)
});
}
}
/**
* Create a DateTime from a JavaScript object with keys like 'year' and 'hour' with reasonable defaults.
* @param {Object} obj - the object to create the DateTime from
* @param {number} obj.year - a year, such as 1987
* @param {number} obj.month - a month, 1-12
* @param {number} obj.day - a day of the month, 1-31, depending on the month
* @param {number} obj.ordinal - day of the year, 1-365 or 366
* @param {number} obj.weekYear - an ISO week year
* @param {number} obj.weekNumber - an ISO week number, between 1 and 52 or 53, depending on the year
* @param {number} obj.weekday - an ISO weekday, 1-7, where 1 is Monday and 7 is Sunday
* @param {number} obj.hour - hour of the day, 0-23
* @param {number} obj.minute - minute of the hour, 0-59
* @param {number} obj.second - second of the minute, 0-59
* @param {number} obj.millisecond - millisecond of the second, 0-999
* @param {Object} opts - options for creating this DateTime
* @param {string|Zone} [opts.zone='local'] - interpret the numbers in the context of a particular zone. Can take any value taken as the first argument to setZone()
* @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance
* @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
* @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance
* @example DateTime.fromObject({ year: 1982, month: 5, day: 25}).toISODate() //=> '1982-05-25'
* @example DateTime.fromObject({ year: 1982 }).toISODate() //=> '1982-01-01'
* @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }) //~> today at 10:26:06
* @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'utc' }),
* @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'local' })
* @example DateTime.fromObject({ hour: 10, minute: 26, second: 6 }, { zone: 'America/New_York' })
* @example DateTime.fromObject({ weekYear: 2016, weekNumber: 2, weekday: 3 }).toISODate() //=> '2016-01-13'
* @return {DateTime}
*/
static fromObject(obj, opts = {}) {
obj = obj || {};
const zoneToUse = normalizeZone(opts.zone, Settings.defaultZone);
if (!zoneToUse.isValid) {
return DateTime.invalid(unsupportedZone(zoneToUse));
}
const tsNow = Settings.now(), offsetProvis = !isUndefined(opts.specificOffset) ? opts.specificOffset : zoneToUse.offset(tsNow), normalized = normalizeObject(obj, normalizeUnit), containsOrdinal = !isUndefined(normalized.ordinal), containsGregorYear = !isUndefined(normalized.year), containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day), containsGregor = containsGregorYear || containsGregorMD, definiteWeekDef = normalized.weekYear || normalized.weekNumber, loc = Locale.fromObject(opts);
if ((containsGregor || containsOrdinal) && definiteWeekDef) {
throw new ConflictingSpecificationError(
"Can't mix weekYear/weekNumber units with year/month/day or ordinals"
);
}
if (containsGregorMD && containsOrdinal) {
throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day");
}
const useWeekData = definiteWeekDef || normalized.weekday && !containsGregor;
let units, defaultValues, objNow = tsToObj(tsNow, offsetProvis);
if (useWeekData) {
units = orderedWeekUnits;
defaultValues = defaultWeekUnitValues;
objNow = gregorianToWeek(objNow);
} else if (containsOrdinal) {
units = orderedOrdinalUnits;
defaultValues = defaultOrdinalUnitValues;
objNow = gregorianToOrdinal(objNow);
} else {
units = orderedUnits2;
defaultValues = defaultUnitValues;
}
let foundFirst = false;
for (const u of units) {
const v = normalized[u];
if (!isUndefined(v)) {
foundFirst = true;
} else if (foundFirst) {
normalized[u] = defaultValues[u];
} else {
normalized[u] = objNow[u];
}
}
const higherOrderInvalid = useWeekData ? hasInvalidWeekData(normalized) : containsOrdinal ? hasInvalidOrdinalData(normalized) : hasInvalidGregorianData(normalized), invalid = higherOrderInvalid || hasInvalidTimeData(normalized);
if (invalid) {
return DateTime.invalid(invalid);
}
const gregorian = useWeekData ? weekToGregorian(normalized) : containsOrdinal ? ordinalToGregorian(normalized) : normalized, [tsFinal, offsetFinal] = objToTS(gregorian, offsetProvis, zoneToUse), inst = new DateTime({
ts: tsFinal,
zone: zoneToUse,
o: offsetFinal,
loc
});
if (normalized.weekday && containsGregor && obj.weekday !== inst.weekday) {
return DateTime.invalid(
"mismatched weekday",
`you can't specify both a weekday of ${normalized.weekday} and a date of ${inst.toISO()}`
);
}
return inst;
}
/**
* Create a DateTime from an ISO 8601 string
* @param {string} text - the ISO string
* @param {Object} opts - options to affect the creation
* @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the time to this zone
* @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one
* @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance
* @param {string} [opts.outputCalendar] - the output calendar to set on the resulting DateTime instance
* @param {string} [opts.numberingSystem] - the numbering system to set on the resulting DateTime instance
* @example DateTime.fromISO('2016-05-25T09:08:34.123')
* @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00')
* @example DateTime.fromISO('2016-05-25T09:08:34.123+06:00', {setZone: true})
* @example DateTime.fromISO('2016-05-25T09:08:34.123', {zone: 'utc'})
* @example DateTime.fromISO('2016-W05-4')
* @return {DateTime}
*/
static fromISO(text, opts = {}) {
const [vals, parsedZone] = parseISODate(text);
return parseDataToDateTime(vals, parsedZone, opts, "ISO 8601", text);
}
/**
* Create a DateTime from an RFC 2822 string
* @param {string} text - the RFC 2822 string
* @param {Object} opts - options to affect the creation
* @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since the offset is always specified in the string itself, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in.
* @param {boolean} [opts.setZone=false] - override the zone with a fixed-offset zone specified in the string itself, if it specifies one
* @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance
* @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
* @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance
* @example DateTime.fromRFC2822('25 Nov 2016 13:23:12 GMT')
* @example DateTime.fromRFC2822('Fri, 25 Nov 2016 13:23:12 +0600')
* @example DateTime.fromRFC2822('25 Nov 2016 13:23 Z')
* @return {DateTime}
*/
static fromRFC2822(text, opts = {}) {
const [vals, parsedZone] = parseRFC2822Date(text);
return parseDataToDateTime(vals, parsedZone, opts, "RFC 2822", text);
}
/**
* Create a DateTime from an HTTP header date
* @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
* @param {string} text - the HTTP header date
* @param {Object} opts - options to affect the creation
* @param {string|Zone} [opts.zone='local'] - convert the time to this zone. Since HTTP dates are always in UTC, this has no effect on the interpretation of string, merely the zone the resulting DateTime is expressed in.
* @param {boolean} [opts.setZone=false] - override the zone with the fixed-offset zone specified in the string. For HTTP dates, this is always UTC, so this option is equivalent to setting the `zone` option to 'utc', but this option is included for consistency with similar methods.
* @param {string} [opts.locale='system's locale'] - a locale to set on the resulting DateTime instance
* @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
* @param {string} opts.numberingSystem - the numbering system to set on the resulting DateTime instance
* @example DateTime.fromHTTP('Sun, 06 Nov 1994 08:49:37 GMT')
* @example DateTime.fromHTTP('Sunday, 06-Nov-94 08:49:37 GMT')
* @example DateTime.fromHTTP('Sun Nov 6 08:49:37 1994')
* @return {DateTime}
*/
static fromHTTP(text, opts = {}) {
const [vals, parsedZone] = parseHTTPDate(text);
return parseDataToDateTime(vals, parsedZone, opts, "HTTP", opts);
}
/**
* Create a DateTime from an input string and format string.
* Defaults to en-US if no locale has been specified, regardless of the system's locale. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/parsing?id=table-of-tokens).
* @param {string} text - the string to parse
* @param {string} fmt - the format the string is expected to be in (see the link below for the formats)
* @param {Object} opts - options to affect the creation
* @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone
* @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one
* @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale
* @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system
* @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
* @return {DateTime}
*/
static fromFormat(text, fmt, opts = {}) {
if (isUndefined(text) || isUndefined(fmt)) {
throw new InvalidArgumentError("fromFormat requires an input string and a format");
}
const { locale = null, numberingSystem = null } = opts, localeToUse = Locale.fromOpts({
locale,
numberingSystem,
defaultToEN: true
}), [vals, parsedZone, specificOffset, invalid] = parseFromTokens(localeToUse, text, fmt);
if (invalid) {
return DateTime.invalid(invalid);
} else {
return parseDataToDateTime(vals, parsedZone, opts, `format ${fmt}`, text, specificOffset);
}
}
/**
* @deprecated use fromFormat instead
*/
static fromString(text, fmt, opts = {}) {
return DateTime.fromFormat(text, fmt, opts);
}
/**
* Create a DateTime from a SQL date, time, or datetime
* Defaults to en-US if no locale has been specified, regardless of the system's locale
* @param {string} text - the string to parse
* @param {Object} opts - options to affect the creation
* @param {string|Zone} [opts.zone='local'] - use this zone if no offset is specified in the input string itself. Will also convert the DateTime to this zone
* @param {boolean} [opts.setZone=false] - override the zone with a zone specified in the string itself, if it specifies one
* @param {string} [opts.locale='en-US'] - a locale string to use when parsing. Will also set the DateTime to this locale
* @param {string} opts.numberingSystem - the numbering system to use when parsing. Will also set the resulting DateTime to this numbering system
* @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
* @example DateTime.fromSQL('2017-05-15')
* @example DateTime.fromSQL('2017-05-15 09:12:34')
* @example DateTime.fromSQL('2017-05-15 09:12:34.342')
* @example DateTime.fromSQL('2017-05-15 09:12:34.342+06:00')
* @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles')
* @example DateTime.fromSQL('2017-05-15 09:12:34.342 America/Los_Angeles', { setZone: true })
* @example DateTime.fromSQL('2017-05-15 09:12:34.342', { zone: 'America/Los_Angeles' })
* @example DateTime.fromSQL('09:12:34.342')
* @return {DateTime}
*/
static fromSQL(text, opts = {}) {
const [vals, parsedZone] = parseSQL(text);
return parseDataToDateTime(vals, parsedZone, opts, "SQL", text);
}
/**
* Create an invalid DateTime.
* @param {DateTime} reason - simple string of why this DateTime is invalid. Should not contain parameters or anything else data-dependent
* @param {string} [explanation=null] - longer explanation, may include parameters and other useful debugging information
* @return {DateTime}
*/
static invalid(reason, explanation = null) {
if (!reason) {
throw new InvalidArgumentError("need to specify a reason the DateTime is invalid");
}
const invalid = reason instanceof Invalid ? reason : new Invalid(reason, explanation);
if (Settings.throwOnInvalid) {
throw new InvalidDateTimeError(invalid);
} else {
return new DateTime({ invalid });
}
}
/**
* Check if an object is an instance of DateTime. Works across context boundaries
* @param {object} o
* @return {boolean}
*/
static isDateTime(o) {
return o && o.isLuxonDateTime || false;
}
/**
* Produce the format string for a set of options
* @param formatOpts
* @param localeOpts
* @returns {string}
*/
static parseFormatForOpts(formatOpts, localeOpts = {}) {
const tokenList = formatOptsToTokens(formatOpts, Locale.fromObject(localeOpts));
return !tokenList ? null : tokenList.map((t) => t ? t.val : null).join("");
}
/**
* Produce the the fully expanded format token for the locale
* Does NOT quote characters, so quoted tokens will not round trip correctly
* @param fmt
* @param localeOpts
* @returns {string}
*/
static expandFormat(fmt, localeOpts = {}) {
const expanded = expandMacroTokens(Formatter.parseFormat(fmt), Locale.fromObject(localeOpts));
return expanded.map((t) => t.val).join("");
}
// INFO
/**
* Get the value of unit.
* @param {string} unit - a unit such as 'minute' or 'day'
* @example DateTime.local(2017, 7, 4).get('month'); //=> 7
* @example DateTime.local(2017, 7, 4).get('day'); //=> 4
* @return {number}
*/
get(unit) {
return this[unit];
}
/**
* Returns whether the DateTime is valid. Invalid DateTimes occur when:
* * The DateTime was created from invalid calendar information, such as the 13th month or February 30
* * The DateTime was created by an operation on another invalid date
* @type {boolean}
*/
get isValid() {
return this.invalid === null;
}
/**
* Returns an error code if this DateTime is invalid, or null if the DateTime is valid
* @type {string}
*/
get invalidReason() {
return this.invalid ? this.invalid.reason : null;
}
/**
* Returns an explanation of why this DateTime became invalid, or null if the DateTime is valid
* @type {string}
*/
get invalidExplanation() {
return this.invalid ? this.invalid.explanation : null;
}
/**
* Get the locale of a DateTime, such 'en-GB'. The locale is used when formatting the DateTime
*
* @type {string}
*/
get locale() {
return this.isValid ? this.loc.locale : null;
}
/**
* Get the numbering system of a DateTime, such 'beng'. The numbering system is used when formatting the DateTime
*
* @type {string}
*/
get numberingSystem() {
return this.isValid ? this.loc.numberingSystem : null;
}
/**
* Get the output calendar of a DateTime, such 'islamic'. The output calendar is used when formatting the DateTime
*
* @type {string}
*/
get outputCalendar() {
return this.isValid ? this.loc.outputCalendar : null;
}
/**
* Get the time zone associated with this DateTime.
* @type {Zone}
*/
get zone() {
return this._zone;
}
/**
* Get the name of the time zone.
* @type {string}
*/
get zoneName() {
return this.isValid ? this.zone.name : null;
}
/**
* Get the year
* @example DateTime.local(2017, 5, 25).year //=> 2017
* @type {number}
*/
get year() {
return this.isValid ? this.c.year : NaN;
}
/**
* Get the quarter
* @example DateTime.local(2017, 5, 25).quarter //=> 2
* @type {number}
*/
get quarter() {
return this.isValid ? Math.ceil(this.c.month / 3) : NaN;
}
/**
* Get the month (1-12).
* @example DateTime.local(2017, 5, 25).month //=> 5
* @type {number}
*/
get month() {
return this.isValid ? this.c.month : NaN;
}
/**
* Get the day of the month (1-30ish).
* @example DateTime.local(2017, 5, 25).day //=> 25
* @type {number}
*/
get day() {
return this.isValid ? this.c.day : NaN;
}
/**
* Get the hour of the day (0-23).
* @example DateTime.local(2017, 5, 25, 9).hour //=> 9
* @type {number}
*/
get hour() {
return this.isValid ? this.c.hour : NaN;
}
/**
* Get the minute of the hour (0-59).
* @example DateTime.local(2017, 5, 25, 9, 30).minute //=> 30
* @type {number}
*/
get minute() {
return this.isValid ? this.c.minute : NaN;
}
/**
* Get the second of the minute (0-59).
* @example DateTime.local(2017, 5, 25, 9, 30, 52).second //=> 52
* @type {number}
*/
get second() {
return this.isValid ? this.c.second : NaN;
}
/**
* Get the millisecond of the second (0-999).
* @example DateTime.local(2017, 5, 25, 9, 30, 52, 654).millisecond //=> 654
* @type {number}
*/
get millisecond() {
return this.isValid ? this.c.millisecond : NaN;
}
/**
* Get the week year
* @see https://en.wikipedia.org/wiki/ISO_week_date
* @example DateTime.local(2014, 12, 31).weekYear //=> 2015
* @type {number}
*/
get weekYear() {
return this.isValid ? possiblyCachedWeekData(this).weekYear : NaN;
}
/**
* Get the week number of the week year (1-52ish).
* @see https://en.wikipedia.org/wiki/ISO_week_date
* @example DateTime.local(2017, 5, 25).weekNumber //=> 21
* @type {number}
*/
get weekNumber() {
return this.isValid ? possiblyCachedWeekData(this).weekNumber : NaN;
}
/**
* Get the day of the week.
* 1 is Monday and 7 is Sunday
* @see https://en.wikipedia.org/wiki/ISO_week_date
* @example DateTime.local(2014, 11, 31).weekday //=> 4
* @type {number}
*/
get weekday() {
return this.isValid ? possiblyCachedWeekData(this).weekday : NaN;
}
/**
* Get the ordinal (meaning the day of the year)
* @example DateTime.local(2017, 5, 25).ordinal //=> 145
* @type {number|DateTime}
*/
get ordinal() {
return this.isValid ? gregorianToOrdinal(this.c).ordinal : NaN;
}
/**
* Get the human readable short month name, such as 'Oct'.
* Defaults to the system's locale if no locale has been specified
* @example DateTime.local(2017, 10, 30).monthShort //=> Oct
* @type {string}
*/
get monthShort() {
return this.isValid ? Info.months("short", { locObj: this.loc })[this.month - 1] : null;
}
/**
* Get the human readable long month name, such as 'October'.
* Defaults to the system's locale if no locale has been specified
* @example DateTime.local(2017, 10, 30).monthLong //=> October
* @type {string}
*/
get monthLong() {
return this.isValid ? Info.months("long", { locObj: this.loc })[this.month - 1] : null;
}
/**
* Get the human readable short weekday, such as 'Mon'.
* Defaults to the system's locale if no locale has been specified
* @example DateTime.local(2017, 10, 30).weekdayShort //=> Mon
* @type {string}
*/
get weekdayShort() {
return this.isValid ? Info.weekdays("short", { locObj: this.loc })[this.weekday - 1] : null;
}
/**
* Get the human readable long weekday, such as 'Monday'.
* Defaults to the system's locale if no locale has been specified
* @example DateTime.local(2017, 10, 30).weekdayLong //=> Monday
* @type {string}
*/
get weekdayLong() {
return this.isValid ? Info.weekdays("long", { locObj: this.loc })[this.weekday - 1] : null;
}
/**
* Get the UTC offset of this DateTime in minutes
* @example DateTime.now().offset //=> -240
* @example DateTime.utc().offset //=> 0
* @type {number}
*/
get offset() {
return this.isValid ? +this.o : NaN;
}
/**
* Get the short human name for the zone's current offset, for example "EST" or "EDT".
* Defaults to the system's locale if no locale has been specified
* @type {string}
*/
get offsetNameShort() {
if (this.isValid) {
return this.zone.offsetName(this.ts, {
format: "short",
locale: this.locale
});
} else {
return null;
}
}
/**
* Get the long human name for the zone's current offset, for example "Eastern Standard Time" or "Eastern Daylight Time".
* Defaults to the system's locale if no locale has been specified
* @type {string}
*/
get offsetNameLong() {
if (this.isValid) {
return this.zone.offsetName(this.ts, {
format: "long",
locale: this.locale
});
} else {
return null;
}
}
/**
* Get whether this zone's offset ever changes, as in a DST.
* @type {boolean}
*/
get isOffsetFixed() {
return this.isValid ? this.zone.isUniversal : null;
}
/**
* Get whether the DateTime is in a DST.
* @type {boolean}
*/
get isInDST() {
if (this.isOffsetFixed) {
return false;
} else {
return this.offset > this.set({ month: 1, day: 1 }).offset || this.offset > this.set({ month: 5 }).offset;
}
}
/**
* Returns true if this DateTime is in a leap year, false otherwise
* @example DateTime.local(2016).isInLeapYear //=> true
* @example DateTime.local(2013).isInLeapYear //=> false
* @type {boolean}
*/
get isInLeapYear() {
return isLeapYear(this.year);
}
/**
* Returns the number of days in this DateTime's month
* @example DateTime.local(2016, 2).daysInMonth //=> 29
* @example DateTime.local(2016, 3).daysInMonth //=> 31
* @type {number}
*/
get daysInMonth() {
return daysInMonth(this.year, this.month);
}
/**
* Returns the number of days in this DateTime's year
* @example DateTime.local(2016).daysInYear //=> 366
* @example DateTime.local(2013).daysInYear //=> 365
* @type {number}
*/
get daysInYear() {
return this.isValid ? daysInYear(this.year) : NaN;
}
/**
* Returns the number of weeks in this DateTime's year
* @see https://en.wikipedia.org/wiki/ISO_week_date
* @example DateTime.local(2004).weeksInWeekYear //=> 53
* @example DateTime.local(2013).weeksInWeekYear //=> 52
* @type {number}
*/
get weeksInWeekYear() {
return this.isValid ? weeksInWeekYear(this.weekYear) : NaN;
}
/**
* Returns the resolved Intl options for this DateTime.
* This is useful in understanding the behavior of formatting methods
* @param {Object} opts - the same options as toLocaleString
* @return {Object}
*/
resolvedLocaleOptions(opts = {}) {
const { locale, numberingSystem, calendar } = Formatter.create(
this.loc.clone(opts),
opts
).resolvedOptions(this);
return { locale, numberingSystem, outputCalendar: calendar };
}
// TRANSFORM
/**
* "Set" the DateTime's zone to UTC. Returns a newly-constructed DateTime.
*
* Equivalent to {@link DateTime#setZone}('utc')
* @param {number} [offset=0] - optionally, an offset from UTC in minutes
* @param {Object} [opts={}] - options to pass to `setZone()`
* @return {DateTime}
*/
toUTC(offset2 = 0, opts = {}) {
return this.setZone(FixedOffsetZone.instance(offset2), opts);
}
/**
* "Set" the DateTime's zone to the host's local zone. Returns a newly-constructed DateTime.
*
* Equivalent to `setZone('local')`
* @return {DateTime}
*/
toLocal() {
return this.setZone(Settings.defaultZone);
}
/**
* "Set" the DateTime's zone to specified zone. Returns a newly-constructed DateTime.
*
* By default, the setter keeps the underlying time the same (as in, the same timestamp), but the new instance will report different local times and consider DSTs when making computations, as with {@link DateTime#plus}. You may wish to use {@link DateTime#toLocal} and {@link DateTime#toUTC} which provide simple convenience wrappers for commonly used zones.
* @param {string|Zone} [zone='local'] - a zone identifier. As a string, that can be any IANA zone supported by the host environment, or a fixed-offset name of the form 'UTC+3', or the strings 'local' or 'utc'. You may also supply an instance of a {@link DateTime#Zone} class.
* @param {Object} opts - options
* @param {boolean} [opts.keepLocalTime=false] - If true, adjust the underlying time so that the local time stays the same, but in the target zone. You should rarely need this.
* @return {DateTime}
*/
setZone(zone, { keepLocalTime = false, keepCalendarTime = false } = {}) {
zone = normalizeZone(zone, Settings.defaultZone);
if (zone.equals(this.zone)) {
return this;
} else if (!zone.isValid) {
return DateTime.invalid(unsupportedZone(zone));
} else {
let newTS = this.ts;
if (keepLocalTime || keepCalendarTime) {
const offsetGuess = zone.offset(this.ts);
const asObj = this.toObject();
[newTS] = objToTS(asObj, offsetGuess, zone);
}
return clone2(this, { ts: newTS, zone });
}
}
/**
* "Set" the locale, numberingSystem, or outputCalendar. Returns a newly-constructed DateTime.
* @param {Object} properties - the properties to set
* @example DateTime.local(2017, 5, 25).reconfigure({ locale: 'en-GB' })
* @return {DateTime}
*/
reconfigure({ locale, numberingSystem, outputCalendar } = {}) {
const loc = this.loc.clone({ locale, numberingSystem, outputCalendar });
return clone2(this, { loc });
}
/**
* "Set" the locale. Returns a newly-constructed DateTime.
* Just a convenient alias for reconfigure({ locale })
* @example DateTime.local(2017, 5, 25).setLocale('en-GB')
* @return {DateTime}
*/
setLocale(locale) {
return this.reconfigure({ locale });
}
/**
* "Set" the values of specified units. Returns a newly-constructed DateTime.
* You can only set units with this method; for "setting" metadata, see {@link DateTime#reconfigure} and {@link DateTime#setZone}.
* @param {Object} values - a mapping of units to numbers
* @example dt.set({ year: 2017 })
* @example dt.set({ hour: 8, minute: 30 })
* @example dt.set({ weekday: 5 })
* @example dt.set({ year: 2005, ordinal: 234 })
* @return {DateTime}
*/
set(values) {
if (!this.isValid)
return this;
const normalized = normalizeObject(values, normalizeUnit), settingWeekStuff = !isUndefined(normalized.weekYear) || !isUndefined(normalized.weekNumber) || !isUndefined(normalized.weekday), containsOrdinal = !isUndefined(normalized.ordinal), containsGregorYear = !isUndefined(normalized.year), containsGregorMD = !isUndefined(normalized.month) || !isUndefined(normalized.day), containsGregor = containsGregorYear || containsGregorMD, definiteWeekDef = normalized.weekYear || normalized.weekNumber;
if ((containsGregor || containsOrdinal) && definiteWeekDef) {
throw new ConflictingSpecificationError(
"Can't mix weekYear/weekNumber units with year/month/day or ordinals"
);
}
if (containsGregorMD && containsOrdinal) {
throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day");
}
let mixed;
if (settingWeekStuff) {
mixed = weekToGregorian({ ...gregorianToWeek(this.c), ...normalized });
} else if (!isUndefined(normalized.ordinal)) {
mixed = ordinalToGregorian({ ...gregorianToOrdinal(this.c), ...normalized });
} else {
mixed = { ...this.toObject(), ...normalized };
if (isUndefined(normalized.day)) {
mixed.day = Math.min(daysInMonth(mixed.year, mixed.month), mixed.day);
}
}
const [ts, o] = objToTS(mixed, this.o, this.zone);
return clone2(this, { ts, o });
}
/**
* Add a period of time to this DateTime and return the resulting DateTime
*
* Adding hours, minutes, seconds, or milliseconds increases the timestamp by the right number of milliseconds. Adding days, months, or years shifts the calendar, accounting for DSTs and leap years along the way. Thus, `dt.plus({ hours: 24 })` may result in a different time than `dt.plus({ days: 1 })` if there's a DST shift in between.
* @param {Duration|Object|number} duration - The amount to add. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
* @example DateTime.now().plus(123) //~> in 123 milliseconds
* @example DateTime.now().plus({ minutes: 15 }) //~> in 15 minutes
* @example DateTime.now().plus({ days: 1 }) //~> this time tomorrow
* @example DateTime.now().plus({ days: -1 }) //~> this time yesterday
* @example DateTime.now().plus({ hours: 3, minutes: 13 }) //~> in 3 hr, 13 min
* @example DateTime.now().plus(Duration.fromObject({ hours: 3, minutes: 13 })) //~> in 3 hr, 13 min
* @return {DateTime}
*/
plus(duration) {
if (!this.isValid)
return this;
const dur = Duration.fromDurationLike(duration);
return clone2(this, adjustTime(this, dur));
}
/**
* Subtract a period of time to this DateTime and return the resulting DateTime
* See {@link DateTime#plus}
* @param {Duration|Object|number} duration - The amount to subtract. Either a Luxon Duration, a number of milliseconds, the object argument to Duration.fromObject()
@return {DateTime}
*/
minus(duration) {
if (!this.isValid)
return this;
const dur = Duration.fromDurationLike(duration).negate();
return clone2(this, adjustTime(this, dur));
}
/**
* "Set" this DateTime to the beginning of a unit of time.
* @param {string} unit - The unit to go to the beginning of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'.
* @example DateTime.local(2014, 3, 3).startOf('month').toISODate(); //=> '2014-03-01'
* @example DateTime.local(2014, 3, 3).startOf('year').toISODate(); //=> '2014-01-01'
* @example DateTime.local(2014, 3, 3).startOf('week').toISODate(); //=> '2014-03-03', weeks always start on Mondays
* @example DateTime.local(2014, 3, 3, 5, 30).startOf('day').toISOTime(); //=> '00:00.000-05:00'
* @example DateTime.local(2014, 3, 3, 5, 30).startOf('hour').toISOTime(); //=> '05:00:00.000-05:00'
* @return {DateTime}
*/
startOf(unit) {
if (!this.isValid)
return this;
const o = {}, normalizedUnit = Duration.normalizeUnit(unit);
switch (normalizedUnit) {
case "years":
o.month = 1;
case "quarters":
case "months":
o.day = 1;
case "weeks":
case "days":
o.hour = 0;
case "hours":
o.minute = 0;
case "minutes":
o.second = 0;
case "seconds":
o.millisecond = 0;
break;
case "milliseconds":
break;
}
if (normalizedUnit === "weeks") {
o.weekday = 1;
}
if (normalizedUnit === "quarters") {
const q = Math.ceil(this.month / 3);
o.month = (q - 1) * 3 + 1;
}
return this.set(o);
}
/**
* "Set" this DateTime to the end (meaning the last millisecond) of a unit of time
* @param {string} unit - The unit to go to the end of. Can be 'year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', or 'millisecond'.
* @example DateTime.local(2014, 3, 3).endOf('month').toISO(); //=> '2014-03-31T23:59:59.999-05:00'
* @example DateTime.local(2014, 3, 3).endOf('year').toISO(); //=> '2014-12-31T23:59:59.999-05:00'
* @example DateTime.local(2014, 3, 3).endOf('week').toISO(); // => '2014-03-09T23:59:59.999-05:00', weeks start on Mondays
* @example DateTime.local(2014, 3, 3, 5, 30).endOf('day').toISO(); //=> '2014-03-03T23:59:59.999-05:00'
* @example DateTime.local(2014, 3, 3, 5, 30).endOf('hour').toISO(); //=> '2014-03-03T05:59:59.999-05:00'
* @return {DateTime}
*/
endOf(unit) {
return this.isValid ? this.plus({ [unit]: 1 }).startOf(unit).minus(1) : this;
}
// OUTPUT
/**
* Returns a string representation of this DateTime formatted according to the specified format string.
* **You may not want this.** See {@link DateTime#toLocaleString} for a more flexible formatting tool. For a table of tokens and their interpretations, see [here](https://moment.github.io/luxon/#/formatting?id=table-of-tokens).
* Defaults to en-US if no locale has been specified, regardless of the system's locale.
* @param {string} fmt - the format string
* @param {Object} opts - opts to override the configuration options on this DateTime
* @example DateTime.now().toFormat('yyyy LLL dd') //=> '2017 Apr 22'
* @example DateTime.now().setLocale('fr').toFormat('yyyy LLL dd') //=> '2017 avr. 22'
* @example DateTime.now().toFormat('yyyy LLL dd', { locale: "fr" }) //=> '2017 avr. 22'
* @example DateTime.now().toFormat("HH 'hours and' mm 'minutes'") //=> '20 hours and 55 minutes'
* @return {string}
*/
toFormat(fmt, opts = {}) {
return this.isValid ? Formatter.create(this.loc.redefaultToEN(opts)).formatDateTimeFromString(this, fmt) : INVALID3;
}
/**
* Returns a localized string representing this date. Accepts the same options as the Intl.DateTimeFormat constructor and any presets defined by Luxon, such as `DateTime.DATE_FULL` or `DateTime.TIME_SIMPLE`.
* The exact behavior of this method is browser-specific, but in general it will return an appropriate representation
* of the DateTime in the assigned locale.
* Defaults to the system's locale if no locale has been specified
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat
* @param formatOpts {Object} - Intl.DateTimeFormat constructor options and configuration options
* @param {Object} opts - opts to override the configuration options on this DateTime
* @example DateTime.now().toLocaleString(); //=> 4/20/2017
* @example DateTime.now().setLocale('en-gb').toLocaleString(); //=> '20/04/2017'
* @example DateTime.now().toLocaleString(DateTime.DATE_FULL); //=> 'April 20, 2017'
* @example DateTime.now().toLocaleString(DateTime.DATE_FULL, { locale: 'fr' }); //=> '28 août 2022'
* @example DateTime.now().toLocaleString(DateTime.TIME_SIMPLE); //=> '11:32 AM'
* @example DateTime.now().toLocaleString(DateTime.DATETIME_SHORT); //=> '4/20/2017, 11:32 AM'
* @example DateTime.now().toLocaleString({ weekday: 'long', month: 'long', day: '2-digit' }); //=> 'Thursday, April 20'
* @example DateTime.now().toLocaleString({ weekday: 'short', month: 'short', day: '2-digit', hour: '2-digit', minute: '2-digit' }); //=> 'Thu, Apr 20, 11:27 AM'
* @example DateTime.now().toLocaleString({ hour: '2-digit', minute: '2-digit', hourCycle: 'h23' }); //=> '11:32'
* @return {string}
*/
toLocaleString(formatOpts = DATE_SHORT, opts = {}) {
return this.isValid ? Formatter.create(this.loc.clone(opts), formatOpts).formatDateTime(this) : INVALID3;
}
/**
* Returns an array of format "parts", meaning individual tokens along with metadata. This is allows callers to post-process individual sections of the formatted output.
* Defaults to the system's locale if no locale has been specified
* @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat/formatToParts
* @param opts {Object} - Intl.DateTimeFormat constructor options, same as `toLocaleString`.
* @example DateTime.now().toLocaleParts(); //=> [
* //=> { type: 'day', value: '25' },
* //=> { type: 'literal', value: '/' },
* //=> { type: 'month', value: '05' },
* //=> { type: 'literal', value: '/' },
* //=> { type: 'year', value: '1982' }
* //=> ]
*/
toLocaleParts(opts = {}) {
return this.isValid ? Formatter.create(this.loc.clone(opts), opts).formatDateTimeParts(this) : [];
}
/**
* Returns an ISO 8601-compliant string representation of this DateTime
* @param {Object} opts - options
* @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0
* @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0
* @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
* @param {boolean} [opts.extendedZone=false] - add the time zone format extension
* @param {string} [opts.format='extended'] - choose between the basic and extended format
* @example DateTime.utc(1983, 5, 25).toISO() //=> '1982-05-25T00:00:00.000Z'
* @example DateTime.now().toISO() //=> '2017-04-22T20:47:05.335-04:00'
* @example DateTime.now().toISO({ includeOffset: false }) //=> '2017-04-22T20:47:05.335'
* @example DateTime.now().toISO({ format: 'basic' }) //=> '20170422T204705.335-0400'
* @return {string}
*/
toISO({
format = "extended",
suppressSeconds = false,
suppressMilliseconds = false,
includeOffset = true,
extendedZone = false
} = {}) {
if (!this.isValid) {
return null;
}
const ext = format === "extended";
let c = toISODate(this, ext);
c += "T";
c += toISOTime(this, ext, suppressSeconds, suppressMilliseconds, includeOffset, extendedZone);
return c;
}
/**
* Returns an ISO 8601-compliant string representation of this DateTime's date component
* @param {Object} opts - options
* @param {string} [opts.format='extended'] - choose between the basic and extended format
* @example DateTime.utc(1982, 5, 25).toISODate() //=> '1982-05-25'
* @example DateTime.utc(1982, 5, 25).toISODate({ format: 'basic' }) //=> '19820525'
* @return {string}
*/
toISODate({ format = "extended" } = {}) {
if (!this.isValid) {
return null;
}
return toISODate(this, format === "extended");
}
/**
* Returns an ISO 8601-compliant string representation of this DateTime's week date
* @example DateTime.utc(1982, 5, 25).toISOWeekDate() //=> '1982-W21-2'
* @return {string}
*/
toISOWeekDate() {
return toTechFormat(this, "kkkk-'W'WW-c");
}
/**
* Returns an ISO 8601-compliant string representation of this DateTime's time component
* @param {Object} opts - options
* @param {boolean} [opts.suppressMilliseconds=false] - exclude milliseconds from the format if they're 0
* @param {boolean} [opts.suppressSeconds=false] - exclude seconds from the format if they're 0
* @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
* @param {boolean} [opts.extendedZone=true] - add the time zone format extension
* @param {boolean} [opts.includePrefix=false] - include the `T` prefix
* @param {string} [opts.format='extended'] - choose between the basic and extended format
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime() //=> '07:34:19.361Z'
* @example DateTime.utc().set({ hour: 7, minute: 34, seconds: 0, milliseconds: 0 }).toISOTime({ suppressSeconds: true }) //=> '07:34Z'
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ format: 'basic' }) //=> '073419.361Z'
* @example DateTime.utc().set({ hour: 7, minute: 34 }).toISOTime({ includePrefix: true }) //=> 'T07:34:19.361Z'
* @return {string}
*/
toISOTime({
suppressMilliseconds = false,
suppressSeconds = false,
includeOffset = true,
includePrefix = false,
extendedZone = false,
format = "extended"
} = {}) {
if (!this.isValid) {
return null;
}
let c = includePrefix ? "T" : "";
return c + toISOTime(
this,
format === "extended",
suppressSeconds,
suppressMilliseconds,
includeOffset,
extendedZone
);
}
/**
* Returns an RFC 2822-compatible string representation of this DateTime
* @example DateTime.utc(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 +0000'
* @example DateTime.local(2014, 7, 13).toRFC2822() //=> 'Sun, 13 Jul 2014 00:00:00 -0400'
* @return {string}
*/
toRFC2822() {
return toTechFormat(this, "EEE, dd LLL yyyy HH:mm:ss ZZZ", false);
}
/**
* Returns a string representation of this DateTime appropriate for use in HTTP headers. The output is always expressed in GMT.
* Specifically, the string conforms to RFC 1123.
* @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1
* @example DateTime.utc(2014, 7, 13).toHTTP() //=> 'Sun, 13 Jul 2014 00:00:00 GMT'
* @example DateTime.utc(2014, 7, 13, 19).toHTTP() //=> 'Sun, 13 Jul 2014 19:00:00 GMT'
* @return {string}
*/
toHTTP() {
return toTechFormat(this.toUTC(), "EEE, dd LLL yyyy HH:mm:ss 'GMT'");
}
/**
* Returns a string representation of this DateTime appropriate for use in SQL Date
* @example DateTime.utc(2014, 7, 13).toSQLDate() //=> '2014-07-13'
* @return {string}
*/
toSQLDate() {
if (!this.isValid) {
return null;
}
return toISODate(this, true);
}
/**
* Returns a string representation of this DateTime appropriate for use in SQL Time
* @param {Object} opts - options
* @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset.
* @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
* @param {boolean} [opts.includeOffsetSpace=true] - include the space between the time and the offset, such as '05:15:16.345 -04:00'
* @example DateTime.utc().toSQL() //=> '05:15:16.345'
* @example DateTime.now().toSQL() //=> '05:15:16.345 -04:00'
* @example DateTime.now().toSQL({ includeOffset: false }) //=> '05:15:16.345'
* @example DateTime.now().toSQL({ includeZone: false }) //=> '05:15:16.345 America/New_York'
* @return {string}
*/
toSQLTime({ includeOffset = true, includeZone = false, includeOffsetSpace = true } = {}) {
let fmt = "HH:mm:ss.SSS";
if (includeZone || includeOffset) {
if (includeOffsetSpace) {
fmt += " ";
}
if (includeZone) {
fmt += "z";
} else if (includeOffset) {
fmt += "ZZ";
}
}
return toTechFormat(this, fmt, true);
}
/**
* Returns a string representation of this DateTime appropriate for use in SQL DateTime
* @param {Object} opts - options
* @param {boolean} [opts.includeZone=false] - include the zone, such as 'America/New_York'. Overrides includeOffset.
* @param {boolean} [opts.includeOffset=true] - include the offset, such as 'Z' or '-04:00'
* @param {boolean} [opts.includeOffsetSpace=true] - include the space between the time and the offset, such as '05:15:16.345 -04:00'
* @example DateTime.utc(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 Z'
* @example DateTime.local(2014, 7, 13).toSQL() //=> '2014-07-13 00:00:00.000 -04:00'
* @example DateTime.local(2014, 7, 13).toSQL({ includeOffset: false }) //=> '2014-07-13 00:00:00.000'
* @example DateTime.local(2014, 7, 13).toSQL({ includeZone: true }) //=> '2014-07-13 00:00:00.000 America/New_York'
* @return {string}
*/
toSQL(opts = {}) {
if (!this.isValid) {
return null;
}
return `${this.toSQLDate()} ${this.toSQLTime(opts)}`;
}
/**
* Returns a string representation of this DateTime appropriate for debugging
* @return {string}
*/
toString() {
return this.isValid ? this.toISO() : INVALID3;
}
/**
* Returns the epoch milliseconds of this DateTime. Alias of {@link DateTime#toMillis}
* @return {number}
*/
valueOf() {
return this.toMillis();
}
/**
* Returns the epoch milliseconds of this DateTime.
* @return {number}
*/
toMillis() {
return this.isValid ? this.ts : NaN;
}
/**
* Returns the epoch seconds of this DateTime.
* @return {number}
*/
toSeconds() {
return this.isValid ? this.ts / 1e3 : NaN;
}
/**
* Returns the epoch seconds (as a whole number) of this DateTime.
* @return {number}
*/
toUnixInteger() {
return this.isValid ? Math.floor(this.ts / 1e3) : NaN;
}
/**
* Returns an ISO 8601 representation of this DateTime appropriate for use in JSON.
* @return {string}
*/
toJSON() {
return this.toISO();
}
/**
* Returns a BSON serializable equivalent to this DateTime.
* @return {Date}
*/
toBSON() {
return this.toJSDate();
}
/**
* Returns a JavaScript object with this DateTime's year, month, day, and so on.
* @param opts - options for generating the object
* @param {boolean} [opts.includeConfig=false] - include configuration attributes in the output
* @example DateTime.now().toObject() //=> { year: 2017, month: 4, day: 22, hour: 20, minute: 49, second: 42, millisecond: 268 }
* @return {Object}
*/
toObject(opts = {}) {
if (!this.isValid)
return {};
const base = { ...this.c };
if (opts.includeConfig) {
base.outputCalendar = this.outputCalendar;
base.numberingSystem = this.loc.numberingSystem;
base.locale = this.loc.locale;
}
return base;
}
/**
* Returns a JavaScript Date equivalent to this DateTime.
* @return {Date}
*/
toJSDate() {
return new Date(this.isValid ? this.ts : NaN);
}
// COMPARE
/**
* Return the difference between two DateTimes as a Duration.
* @param {DateTime} otherDateTime - the DateTime to compare this one to
* @param {string|string[]} [unit=['milliseconds']] - the unit or array of units (such as 'hours' or 'days') to include in the duration.
* @param {Object} opts - options that affect the creation of the Duration
* @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
* @example
* var i1 = DateTime.fromISO('1982-05-25T09:45'),
* i2 = DateTime.fromISO('1983-10-14T10:30');
* i2.diff(i1).toObject() //=> { milliseconds: 43807500000 }
* i2.diff(i1, 'hours').toObject() //=> { hours: 12168.75 }
* i2.diff(i1, ['months', 'days']).toObject() //=> { months: 16, days: 19.03125 }
* i2.diff(i1, ['months', 'days', 'hours']).toObject() //=> { months: 16, days: 19, hours: 0.75 }
* @return {Duration}
*/
diff(otherDateTime, unit = "milliseconds", opts = {}) {
if (!this.isValid || !otherDateTime.isValid) {
return Duration.invalid("created by diffing an invalid DateTime");
}
const durOpts = { locale: this.locale, numberingSystem: this.numberingSystem, ...opts };
const units = maybeArray(unit).map(Duration.normalizeUnit), otherIsLater = otherDateTime.valueOf() > this.valueOf(), earlier = otherIsLater ? this : otherDateTime, later = otherIsLater ? otherDateTime : this, diffed = diff_default(earlier, later, units, durOpts);
return otherIsLater ? diffed.negate() : diffed;
}
/**
* Return the difference between this DateTime and right now.
* See {@link DateTime#diff}
* @param {string|string[]} [unit=['milliseconds']] - the unit or units units (such as 'hours' or 'days') to include in the duration
* @param {Object} opts - options that affect the creation of the Duration
* @param {string} [opts.conversionAccuracy='casual'] - the conversion system to use
* @return {Duration}
*/
diffNow(unit = "milliseconds", opts = {}) {
return this.diff(DateTime.now(), unit, opts);
}
/**
* Return an Interval spanning between this DateTime and another DateTime
* @param {DateTime} otherDateTime - the other end point of the Interval
* @return {Interval}
*/
until(otherDateTime) {
return this.isValid ? Interval.fromDateTimes(this, otherDateTime) : this;
}
/**
* Return whether this DateTime is in the same unit of time as another DateTime.
* Higher-order units must also be identical for this function to return `true`.
* Note that time zones are **ignored** in this comparison, which compares the **local** calendar time. Use {@link DateTime#setZone} to convert one of the dates if needed.
* @param {DateTime} otherDateTime - the other DateTime
* @param {string} unit - the unit of time to check sameness on
* @example DateTime.now().hasSame(otherDT, 'day'); //~> true if otherDT is in the same current calendar day
* @return {boolean}
*/
hasSame(otherDateTime, unit) {
if (!this.isValid)
return false;
const inputMs = otherDateTime.valueOf();
const adjustedToZone = this.setZone(otherDateTime.zone, { keepLocalTime: true });
return adjustedToZone.startOf(unit) <= inputMs && inputMs <= adjustedToZone.endOf(unit);
}
/**
* Equality check
* Two DateTimes are equal if and only if they represent the same millisecond, have the same zone and location, and are both valid.
* To compare just the millisecond values, use `+dt1 === +dt2`.
* @param {DateTime} other - the other DateTime
* @return {boolean}
*/
equals(other) {
return this.isValid && other.isValid && this.valueOf() === other.valueOf() && this.zone.equals(other.zone) && this.loc.equals(other.loc);
}
/**
* Returns a string representation of a this time relative to now, such as "in two days". Can only internationalize if your
* platform supports Intl.RelativeTimeFormat. Rounds down by default.
* @param {Object} options - options that affect the output
* @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
* @param {string} [options.style="long"] - the style of units, must be "long", "short", or "narrow"
* @param {string|string[]} options.unit - use a specific unit or array of units; if omitted, or an array, the method will pick the best unit. Use an array or one of "years", "quarters", "months", "weeks", "days", "hours", "minutes", or "seconds"
* @param {boolean} [options.round=true] - whether to round the numbers in the output.
* @param {number} [options.padding=0] - padding in milliseconds. This allows you to round up the result if it fits inside the threshold. Don't use in combination with {round: false} because the decimal output will include the padding.
* @param {string} options.locale - override the locale of this DateTime
* @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
* @example DateTime.now().plus({ days: 1 }).toRelative() //=> "in 1 day"
* @example DateTime.now().setLocale("es").toRelative({ days: 1 }) //=> "dentro de 1 día"
* @example DateTime.now().plus({ days: 1 }).toRelative({ locale: "fr" }) //=> "dans 23 heures"
* @example DateTime.now().minus({ days: 2 }).toRelative() //=> "2 days ago"
* @example DateTime.now().minus({ days: 2 }).toRelative({ unit: "hours" }) //=> "48 hours ago"
* @example DateTime.now().minus({ hours: 36 }).toRelative({ round: false }) //=> "1.5 days ago"
*/
toRelative(options = {}) {
if (!this.isValid)
return null;
const base = options.base || DateTime.fromObject({}, { zone: this.zone }), padding = options.padding ? this < base ? -options.padding : options.padding : 0;
let units = ["years", "months", "days", "hours", "minutes", "seconds"];
let unit = options.unit;
if (Array.isArray(options.unit)) {
units = options.unit;
unit = void 0;
}
return diffRelative(base, this.plus(padding), {
...options,
numeric: "always",
units,
unit
});
}
/**
* Returns a string representation of this date relative to today, such as "yesterday" or "next month".
* Only internationalizes on platforms that supports Intl.RelativeTimeFormat.
* @param {Object} options - options that affect the output
* @param {DateTime} [options.base=DateTime.now()] - the DateTime to use as the basis to which this time is compared. Defaults to now.
* @param {string} options.locale - override the locale of this DateTime
* @param {string} options.unit - use a specific unit; if omitted, the method will pick the unit. Use one of "years", "quarters", "months", "weeks", or "days"
* @param {string} options.numberingSystem - override the numberingSystem of this DateTime. The Intl system may choose not to honor this
* @example DateTime.now().plus({ days: 1 }).toRelativeCalendar() //=> "tomorrow"
* @example DateTime.now().setLocale("es").plus({ days: 1 }).toRelative() //=> ""mañana"
* @example DateTime.now().plus({ days: 1 }).toRelativeCalendar({ locale: "fr" }) //=> "demain"
* @example DateTime.now().minus({ days: 2 }).toRelativeCalendar() //=> "2 days ago"
*/
toRelativeCalendar(options = {}) {
if (!this.isValid)
return null;
return diffRelative(options.base || DateTime.fromObject({}, { zone: this.zone }), this, {
...options,
numeric: "auto",
units: ["years", "months", "days"],
calendary: true
});
}
/**
* Return the min of several date times
* @param {...DateTime} dateTimes - the DateTimes from which to choose the minimum
* @return {DateTime} the min DateTime, or undefined if called with no argument
*/
static min(...dateTimes) {
if (!dateTimes.every(DateTime.isDateTime)) {
throw new InvalidArgumentError("min requires all arguments be DateTimes");
}
return bestBy(dateTimes, (i) => i.valueOf(), Math.min);
}
/**
* Return the max of several date times
* @param {...DateTime} dateTimes - the DateTimes from which to choose the maximum
* @return {DateTime} the max DateTime, or undefined if called with no argument
*/
static max(...dateTimes) {
if (!dateTimes.every(DateTime.isDateTime)) {
throw new InvalidArgumentError("max requires all arguments be DateTimes");
}
return bestBy(dateTimes, (i) => i.valueOf(), Math.max);
}
// MISC
/**
* Explain how a string would be parsed by fromFormat()
* @param {string} text - the string to parse
* @param {string} fmt - the format the string is expected to be in (see description)
* @param {Object} options - options taken by fromFormat()
* @return {Object}
*/
static fromFormatExplain(text, fmt, options = {}) {
const { locale = null, numberingSystem = null } = options, localeToUse = Locale.fromOpts({
locale,
numberingSystem,
defaultToEN: true
});
return explainFromTokens(localeToUse, text, fmt);
}
/**
* @deprecated use fromFormatExplain instead
*/
static fromStringExplain(text, fmt, options = {}) {
return DateTime.fromFormatExplain(text, fmt, options);
}
// FORMAT PRESETS
/**
* {@link DateTime#toLocaleString} format like 10/14/1983
* @type {Object}
*/
static get DATE_SHORT() {
return DATE_SHORT;
}
/**
* {@link DateTime#toLocaleString} format like 'Oct 14, 1983'
* @type {Object}
*/
static get DATE_MED() {
return DATE_MED;
}
/**
* {@link DateTime#toLocaleString} format like 'Fri, Oct 14, 1983'
* @type {Object}
*/
static get DATE_MED_WITH_WEEKDAY() {
return DATE_MED_WITH_WEEKDAY;
}
/**
* {@link DateTime#toLocaleString} format like 'October 14, 1983'
* @type {Object}
*/
static get DATE_FULL() {
return DATE_FULL;
}
/**
* {@link DateTime#toLocaleString} format like 'Tuesday, October 14, 1983'
* @type {Object}
*/
static get DATE_HUGE() {
return DATE_HUGE;
}
/**
* {@link DateTime#toLocaleString} format like '09:30 AM'. Only 12-hour if the locale is.
* @type {Object}
*/
static get TIME_SIMPLE() {
return TIME_SIMPLE;
}
/**
* {@link DateTime#toLocaleString} format like '09:30:23 AM'. Only 12-hour if the locale is.
* @type {Object}
*/
static get TIME_WITH_SECONDS() {
return TIME_WITH_SECONDS;
}
/**
* {@link DateTime#toLocaleString} format like '09:30:23 AM EDT'. Only 12-hour if the locale is.
* @type {Object}
*/
static get TIME_WITH_SHORT_OFFSET() {
return TIME_WITH_SHORT_OFFSET;
}
/**
* {@link DateTime#toLocaleString} format like '09:30:23 AM Eastern Daylight Time'. Only 12-hour if the locale is.
* @type {Object}
*/
static get TIME_WITH_LONG_OFFSET() {
return TIME_WITH_LONG_OFFSET;
}
/**
* {@link DateTime#toLocaleString} format like '09:30', always 24-hour.
* @type {Object}
*/
static get TIME_24_SIMPLE() {
return TIME_24_SIMPLE;
}
/**
* {@link DateTime#toLocaleString} format like '09:30:23', always 24-hour.
* @type {Object}
*/
static get TIME_24_WITH_SECONDS() {
return TIME_24_WITH_SECONDS;
}
/**
* {@link DateTime#toLocaleString} format like '09:30:23 EDT', always 24-hour.
* @type {Object}
*/
static get TIME_24_WITH_SHORT_OFFSET() {
return TIME_24_WITH_SHORT_OFFSET;
}
/**
* {@link DateTime#toLocaleString} format like '09:30:23 Eastern Daylight Time', always 24-hour.
* @type {Object}
*/
static get TIME_24_WITH_LONG_OFFSET() {
return TIME_24_WITH_LONG_OFFSET;
}
/**
* {@link DateTime#toLocaleString} format like '10/14/1983, 9:30 AM'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_SHORT() {
return DATETIME_SHORT;
}
/**
* {@link DateTime#toLocaleString} format like '10/14/1983, 9:30:33 AM'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_SHORT_WITH_SECONDS() {
return DATETIME_SHORT_WITH_SECONDS;
}
/**
* {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30 AM'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_MED() {
return DATETIME_MED;
}
/**
* {@link DateTime#toLocaleString} format like 'Oct 14, 1983, 9:30:33 AM'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_MED_WITH_SECONDS() {
return DATETIME_MED_WITH_SECONDS;
}
/**
* {@link DateTime#toLocaleString} format like 'Fri, 14 Oct 1983, 9:30 AM'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_MED_WITH_WEEKDAY() {
return DATETIME_MED_WITH_WEEKDAY;
}
/**
* {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30 AM EDT'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_FULL() {
return DATETIME_FULL;
}
/**
* {@link DateTime#toLocaleString} format like 'October 14, 1983, 9:30:33 AM EDT'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_FULL_WITH_SECONDS() {
return DATETIME_FULL_WITH_SECONDS;
}
/**
* {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30 AM Eastern Daylight Time'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_HUGE() {
return DATETIME_HUGE;
}
/**
* {@link DateTime#toLocaleString} format like 'Friday, October 14, 1983, 9:30:33 AM Eastern Daylight Time'. Only 12-hour if the locale is.
* @type {Object}
*/
static get DATETIME_HUGE_WITH_SECONDS() {
return DATETIME_HUGE_WITH_SECONDS;
}
};
function friendlyDateTime(dateTimeish) {
if (DateTime.isDateTime(dateTimeish)) {
return dateTimeish;
} else if (dateTimeish && dateTimeish.valueOf && isNumber(dateTimeish.valueOf())) {
return DateTime.fromJSDate(dateTimeish);
} else if (dateTimeish && typeof dateTimeish === "object") {
return DateTime.fromObject(dateTimeish);
} else {
throw new InvalidArgumentError(
`Unknown datetime argument: ${dateTimeish}, of type ${typeof dateTimeish}`
);
}
}
// main.ts
var import_obsidian = require("obsidian");
var ClockViewType = "my-clock-view";
var ClockView = class extends import_obsidian.ItemView {
constructor(leaf, plugin) {
super(leaf);
this.plugin = plugin;
this.timeContainer = this.containerEl.createDiv();
this.dateContainer = this.containerEl.createDiv();
this.timezoneContainer = this.containerEl.createDiv();
}
async onOpen() {
this.displayTime();
}
getViewType() {
return ClockViewType;
}
getDisplayText() {
return "Clock";
}
getIcon() {
return "clock";
}
// Omitted onHeaderMenu function as it is commented out
sortTimeZones() {
const currentOffset = DateTime.local().offset;
return this.plugin.settings.timeZonePairs.slice().sort((a, b) => {
const offsetA = parseFloat(a.offset);
const offsetB = parseFloat(b.offset);
const diffA = Math.abs(currentOffset - offsetA);
const diffB = Math.abs(currentOffset - offsetB);
return diffB - diffA;
});
}
displayTime() {
this.timeContainer.empty();
this.dateContainer.empty();
this.timezoneContainer.empty();
const currentTime = DateTime.local().toFormat(
this.plugin.settings.timeFormat
);
this.timeContainer.createEl("h2", {
cls: "time-display",
text: currentTime
});
if (this.plugin.settings.showDate) {
const currentDate = DateTime.local().toFormat(
this.plugin.settings.dateFormat
);
this.dateContainer.createEl("h2", {
cls: "date-display",
text: currentDate
});
}
const sortedTimeZones = this.sortTimeZones();
if (this.plugin.settings.showTimeZone) {
const timezoneContainer = this.timezoneContainer.createEl("div", {
cls: "timezone-container"
});
sortedTimeZones.forEach((entry) => {
if (entry.offset) {
const offset2 = parseFloat(entry.offset);
const timezoneTime = DateTime.utc().plus({ hours: offset2 }).toFormat(this.plugin.settings.timezoneFormat);
const timezonePair = timezoneContainer.createEl("div", {
cls: "timezone-pair"
});
timezonePair.createEl("div", {
cls: "timezone-name",
text: entry.name
});
timezonePair.createEl("div", {
cls: "timezone-time",
text: timezoneTime
});
}
});
}
}
};
var DEFAULT_SETTINGS = {
timeFormat: "HH:mm",
showDate: true,
dateFormat: "EEE - dd",
showTimeZone: true,
timeZonePairs: [{ name: "", offset: "" }],
timezoneFormat: "HH:mm - EEEEE"
};
var ClockPlugin = class extends import_obsidian.Plugin {
async onload() {
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
await this.loadData()
);
this.registerView(
ClockViewType,
(leaf) => this.view = new ClockView(leaf, this)
);
this.addCommand({
id: "clock-open",
name: "Open Clock",
callback: async () => {
let [leaf] = this.app.workspace.getLeavesOfType(ClockViewType);
if (!leaf) {
leaf = this.app.workspace.getRightLeaf(false);
if (leaf) {
await leaf.setViewState({ type: ClockViewType });
} else {
}
}
if (leaf) {
this.app.workspace.revealLeaf(leaf);
}
}
});
if (this.app.workspace.layoutReady) {
await this.initView();
} else {
const checkLayoutInterval = setInterval(async () => {
if (this.app.workspace.layoutReady) {
await this.initView();
clearInterval(checkLayoutInterval);
}
}, 1e3);
}
this.addSettingTab(new ClockSettingTab(this.app, this));
}
onunload() {
this.app.workspace.detachLeavesOfType(ClockViewType);
}
async initView() {
let [leaf] = this.app.workspace.getLeavesOfType(ClockViewType);
if (!leaf) {
leaf = this.app.workspace.getLeaf();
if (leaf) {
await leaf.setViewState({ type: ClockViewType });
} else {
}
}
if (leaf) {
this.app.workspace.revealLeaf(leaf);
}
this.view.displayTime();
setInterval(() => {
this.view.displayTime();
}, 1e3);
}
async saveSettings() {
await this.saveData(this.settings);
}
};
var ClockSettingTab = class extends import_obsidian.PluginSettingTab {
constructor(app, plugin) {
super(app, plugin);
this.plugin = plugin;
}
display() {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl("h1", { text: "Clock Settings" });
let h2El = containerEl.createEl("p", {
text: "Use the Luxon format for all time and date settings: "
});
h2El.createEl("a", {
text: " Luxon Reference",
href: "https://moment.github.io/luxon/docs/manual/formatting.html",
attr: {
target: "_blank"
}
});
let textField;
new import_obsidian.Setting(containerEl).setName("Time format").setDesc(
createFragment((fragment) => {
fragment.append(
"Default Luxon format is ",
fragment.createEl("code", {
text: "HH:mm"
})
);
})
).addText((text) => {
textField = text.setPlaceholder("Enter the time format").setValue(this.plugin.settings.timeFormat);
textField.inputEl.onkeypress = async (e) => {
if (e.key === "Enter") {
e.preventDefault();
this.plugin.settings.timeFormat = textField.inputEl.value;
await this.plugin.saveData(this.plugin.settings);
this.plugin.view.displayTime();
textField.inputEl.blur();
}
};
}).addExtraButton(
(button) => button.setIcon("reset").setTooltip("Reset time format").onClick(async () => {
this.plugin.settings.timeFormat = DEFAULT_SETTINGS.timeFormat;
await this.plugin.saveData(this.plugin.settings);
this.plugin.view.displayTime();
textField.setValue(this.plugin.settings.timeFormat);
})
);
new import_obsidian.Setting(containerEl).setName("Show date").setDesc("Enable to show the date.").addToggle((toggle) => {
toggle.setValue(this.plugin.settings.showDate).onChange(async (value) => {
this.plugin.settings.showDate = value;
await this.plugin.saveData(this.plugin.settings);
const clockView = this.app.workspace.getLeavesOfType("my-clock-view").find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
clockView.view.displayTime();
}
if (value) {
dateFormatSetting.settingEl.style.display = "";
} else {
dateFormatSetting.settingEl.style.display = "none";
}
});
});
let dateFormatSetting = new import_obsidian.Setting(containerEl).setName("Date format").setDesc(
createFragment((fragment) => {
fragment.append(
"Default Luxon format is ",
fragment.createEl("code", {
text: "DDD"
})
);
})
).addText((text) => {
let textField2 = text.setPlaceholder("Enter the date format").setValue(this.plugin.settings.dateFormat);
textField2.inputEl.onkeypress = async (e) => {
if (e.key === "Enter") {
e.preventDefault();
this.plugin.settings.dateFormat = textField2.inputEl.value;
await this.plugin.saveData(this.plugin.settings);
const clockView = this.app.workspace.getLeavesOfType("my-clock-view").find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
clockView.view.displayTime();
}
textField2.inputEl.blur();
}
};
if (!this.plugin.settings.showDate) {
textField2.inputEl.style.display = "none";
}
}).addExtraButton((button) => {
button.setIcon("reset").setTooltip("Reset date format").onClick(async () => {
this.plugin.settings.dateFormat = DEFAULT_SETTINGS.dateFormat;
await this.plugin.saveData(this.plugin.settings);
this.display();
new import_obsidian.Notice("Date Format Reset");
const clockView = this.app.workspace.getLeavesOfType("my-clock-view").find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
clockView.view.displayTime();
}
});
});
new import_obsidian.Setting(containerEl).setName("Show Timezone").setDesc("Enable to show the timezone.").addToggle((toggle) => {
toggle.setValue(this.plugin.settings.showTimeZone).onChange(async (value) => {
this.plugin.settings.showTimeZone = value;
await this.plugin.saveData(this.plugin.settings);
const clockView = this.app.workspace.getLeavesOfType("clock-view").find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
clockView.view.displayTime();
}
timezoneSetting.settingEl.style.display = value ? "" : "none";
timezoneFormatSetting.settingEl.style.display = value ? "" : "none";
});
});
let timezoneSetting = new import_obsidian.Setting(containerEl).setName("Timezone settings").setDesc(
createFragment((fragment) => {
fragment.append(
"Enter your timezone pairs.",
fragment.createEl("a", {
text: " Reference",
href: "https://www.timeanddate.com/time/map/"
}),
fragment.createEl("br"),
fragment.createEl("br"),
"Names and Offset pairs are not validated."
);
})
);
let timezoneSettingDiv = timezoneSetting.settingEl.createEl("div");
if (this.plugin.settings.showTimeZone) {
const table = timezoneSettingDiv.createEl("table");
const headerRow = table.createEl("tr");
headerRow.createEl("th", { text: "Timezone Name" });
headerRow.createEl("th", { text: "Timezone Offset" });
headerRow.createEl("th", { text: "" });
this.plugin.settings.timeZonePairs.forEach((entry, index) => {
const row = table.createEl("tr");
const nameCell = row.createEl("td");
const nameInput = nameCell.createEl("input", {
type: "text",
value: entry.name
});
const saveSettings = async () => {
if (nameInput.value.trim() !== "" && offsetInput.value.trim() !== "") {
this.plugin.settings.timeZonePairs[index].name = nameInput.value;
this.plugin.settings.timeZonePairs[index].offset = offsetInput.value;
await this.plugin.saveSettings();
}
};
nameInput.addEventListener("keydown", async (e) => {
if (e.key === "Enter") {
e.preventDefault();
await saveSettings();
nameInput.blur();
}
});
const offsetCell = row.createEl("td");
const offsetInput = offsetCell.createEl("input", {
type: "text",
value: entry.offset
});
offsetInput.addEventListener("keydown", async (e) => {
if (e.key === "Enter") {
e.preventDefault();
await saveSettings();
offsetInput.blur();
}
});
const buttonsCell = row.createEl("td");
if (index !== 0) {
const deleteButton = buttonsCell.createEl("button", {
text: "-"
});
deleteButton.classList.add("deleteButtonClass");
deleteButton.addEventListener("click", async () => {
this.plugin.settings.timeZonePairs.splice(index, 1);
await this.plugin.saveSettings();
this.display();
});
}
if (index === this.plugin.settings.timeZonePairs.length - 1) {
const addButton = buttonsCell.createEl("button", {
text: "+"
});
addButton.classList.add("addButtonClass");
addButton.addEventListener("click", async () => {
if (this.plugin.settings.timeZonePairs.length < 5) {
this.plugin.settings.timeZonePairs.push({
name: "",
offset: ""
});
this.display();
} else {
new import_obsidian.Notice("Maximum timezone entries added.");
}
});
}
if (index !== 0 && index === this.plugin.settings.timeZonePairs.length - 1) {
buttonsCell.classList.add("twoButtonsClass");
}
});
}
let timezoneFormatField;
let timezoneFormatSetting = new import_obsidian.Setting(containerEl).setName("Timezone Format").setDesc(
createFragment((fragment) => {
fragment.append(
"Default Luxon format is ",
fragment.createEl("code", {
text: "HH:mm - EEEEE"
})
);
})
).addText((text) => {
timezoneFormatField = text.setPlaceholder("Enter the timezone format").setValue(this.plugin.settings.timezoneFormat);
timezoneFormatField.inputEl.onkeypress = async (e) => {
if (e.key === "Enter") {
e.preventDefault();
this.plugin.settings.timezoneFormat = timezoneFormatField.inputEl.value;
await this.plugin.saveData(this.plugin.settings);
const clockView = this.app.workspace.getLeavesOfType("clock-view").find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
clockView.view.displayTime();
}
timezoneFormatField.inputEl.blur();
}
};
}).addExtraButton(
(button) => button.setIcon("reset").setTooltip("Reset timezone format").onClick(async () => {
this.plugin.settings.timezoneFormat = DEFAULT_SETTINGS.timezoneFormat;
await this.plugin.saveData(this.plugin.settings);
this.plugin.view.displayTime();
timezoneFormatField.setValue(
this.plugin.settings.timezoneFormat
);
})
);
dateFormatSetting.settingEl.style.borderTop = "none";
timezoneSetting.settingEl.style.borderTop = "none";
timezoneFormatSetting.settingEl.style.borderTop = "none";
if (!this.plugin.settings.showTimeZone) {
timezoneSetting.settingEl.style.display = "none";
timezoneFormatSetting.settingEl.style.display = "none";
}
}
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibWFpbi50cyIsICJub2RlX21vZHVsZXMvbHV4b24vc3JjL2Vycm9ycy5qcyIsICJub2RlX21vZHVsZXMvbHV4b24vc3JjL2ltcGwvZm9ybWF0cy5qcyIsICJub2RlX21vZHVsZXMvbHV4b24vc3JjL3pvbmUuanMiLCAibm9kZV9tb2R1bGVzL2x1eG9uL3NyYy96b25lcy9zeXN0ZW1ab25lLmpzIiwgIm5vZGVfbW9kdWxlcy9sdXhvbi9zcmMvem9uZXMvSUFOQVpvbmUuanMiLCAibm9kZV9tb2R1bGVzL2x1eG9uL3NyYy9pbXBsL2xvY2FsZS5qcyIsICJub2RlX21vZHVsZXMvbHV4b24vc3JjL3pvbmVzL2ZpeGVkT2Zmc2V0Wm9uZS5qcyIsICJub2RlX21vZHVsZXMvbHV4b24vc3JjL3pvbmVzL2ludmFsaWRab25lLmpzIiwgIm5vZGVfbW9kdWxlcy9sdXhvbi9zcmMvaW1wbC96b25lVXRpbC5qcyIsICJub2RlX21vZHVsZXMvbHV4b24vc3JjL3NldHRpbmdzLmpzIiwgIm5vZGVfbW9kdWxlcy9sdXhvbi9zcmMvaW1wbC91dGlsLmpzIiwgIm5vZGVfbW9kdWxlcy9sdXhvbi9zcmMvaW1wbC9lbmdsaXNoLmpzIiwgIm5vZGVfbW9kdWxlcy9sdXhvbi9zcmMvaW1wbC9mb3JtYXR0ZXIuanMiLCAibm9kZV9tb2R1bGVzL2x1eG9uL3NyYy9pbXBsL2ludmFsaWQuanMiLCAibm9kZV9tb2R1bGVzL2x1eG9uL3NyYy9pbXBsL3JlZ2V4UGFyc2VyLmpzIiwgIm5vZGVfbW9kdWxlcy9sdXhvbi9zcmMvZHVyYXRpb24uanMiLCAibm9kZV9tb2R1bGVzL2x1eG9uL3NyYy9pbnRlcnZhbC5qcyIsICJub2RlX21vZHVsZXMvbHV4b24vc3JjL2luZm8uanMiLCAibm9kZV9tb2R1bGVzL2x1eG9uL3NyYy9pbXBsL2RpZmYuanMiLCAibm9kZV9tb2R1bGVzL2x1eG9uL3NyYy9pbXBsL2RpZ2l0cy5qcyIsICJub2RlX21vZHVsZXMvbHV4b24vc3JjL2ltcGwvdG9rZW5QYXJzZXIuanMiLCAibm9kZV9tb2R1bGVzL2x1eG9uL3NyYy9pbXBsL2NvbnZlcnNpb25zLmpzIiwgIm5vZGVfbW9kdWxlcy9sdXhvbi9zcmMvZGF0ZXRpbWUuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IERhdGVUaW1lLCBJbmZvIH0gZnJvbSBcImx1eG9uXCI7XG5pbXBvcnQge1xuXHRhZGRJY29uLFxuXHRBcHAsXG5cdEl0ZW1WaWV3LFxuXHRNZW51LFxuXHRQbHVnaW4sXG5cdFBsdWdpblNldHRpbmdUYWIsXG5cdFNldHRpbmcsXG5cdFRBYnN0cmFjdEZpbGUsXG5cdFRGaWxlLFxuXHRXb3Jrc3BhY2VMZWFmLFxuXHROb3RpY2UsXG5cdEV4dHJhQnV0dG9uQ29tcG9uZW50LFxuXHRUZXh0Q29tcG9uZW50LFxufSBmcm9tIFwib2JzaWRpYW5cIjtcblxuY29uc3QgQ2xvY2tWaWV3VHlwZSA9IFwibXktY2xvY2stdmlld1wiO1xuXG5jbGFzcyBDbG9ja1ZpZXcgZXh0ZW5kcyBJdGVtVmlldyB7XG5cdHByaXZhdGUgcmVhZG9ubHkgcGx1Z2luOiBDbG9ja1BsdWdpbjtcblx0cHJpdmF0ZSB0aW1lQ29udGFpbmVyOiBIVE1MRWxlbWVudDtcblx0cHJpdmF0ZSBkYXRlQ29udGFpbmVyOiBIVE1MRWxlbWVudDtcblx0cHJpdmF0ZSB0aW1lem9uZUNvbnRhaW5lcjogSFRNTEVsZW1lbnQ7XG5cblx0Y29uc3RydWN0b3IobGVhZjogV29ya3NwYWNlTGVhZiwgcGx1Z2luOiBDbG9ja1BsdWdpbikge1xuXHRcdHN1cGVyKGxlYWYpO1xuXHRcdHRoaXMucGx1Z2luID0gcGx1Z2luO1xuXG5cdFx0Ly8gQ3JlYXRlIGNvbnRhaW5lcnMgZm9yIHRpbWUsIGRhdGUsIGFuZCB0aW1lem9uZVxuXHRcdHRoaXMudGltZUNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyRWwuY3JlYXRlRGl2KCk7XG5cdFx0dGhpcy5kYXRlQ29udGFpbmVyID0gdGhpcy5jb250YWluZXJFbC5jcmVhdGVEaXYoKTtcblx0XHR0aGlzLnRpbWV6b25lQ29udGFpbmVyID0gdGhpcy5jb250YWluZXJFbC5jcmVhdGVEaXYoKTtcblx0fVxuXG5cdHB1YmxpYyBhc3luYyBvbk9wZW4oKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0dGhpcy5kaXNwbGF5VGltZSgpO1xuXHR9XG5cblx0cHVibGljIGdldFZpZXdUeXBlKCk6IHN0cmluZyB7XG5cdFx0cmV0dXJuIENsb2NrVmlld1R5cGU7XG5cdH1cblxuXHRwdWJsaWMgZ2V0RGlzcGxheVRleHQoKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gXCJDbG9ja1wiO1xuXHR9XG5cblx0cHVibGljIGdldEljb24oKTogc3RyaW5nIHtcblx0XHRyZXR1cm4gXCJjbG9ja1wiO1xuXHR9XG5cblx0Ly8gT21pdHRlZCBvbkhlYWRlck1lbnUgZnVuY3Rpb24gYXMgaXQgaXMgY29tbWVudGVkIG91dFxuXG5cdHByaXZhdGUgc29ydFRpbWVab25lcygpOiBUaW1lem9uZVBhaXJbXSB7XG5cdFx0Y29uc3QgY3VycmVudE9mZnNldCA9IERhdGVUaW1lLmxvY2FsKCkub2Zmc2V0O1xuXG5cdFx0Ly8gU29ydCB0aGUgdGltZXpvbmUgcGFpcnMgYmFzZWQgb24gdGhlIGRpZmZlcmVuY2UgZnJvbSB0aGUgY3VycmVudCBvZmZzZXQgaW4gZGVzY2VuZGluZyBvcmRlclxuXHRcdHJldHVybiB0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lWm9uZVBhaXJzLnNsaWNlKCkuc29ydCgoYSwgYikgPT4ge1xuXHRcdFx0Y29uc3Qgb2Zmc2V0QSA9IHBhcnNlRmxvYXQoYS5vZmZzZXQpO1xuXHRcdFx0Y29uc3Qgb2Zmc2V0QiA9IHBhcnNlRmxvYXQoYi5vZmZzZXQpO1xuXG5cdFx0XHRjb25zdCBkaWZmQSA9IE1hdGguYWJzKGN1cnJlbnRPZmZzZXQgLSBvZmZzZXRBKTtcblx0XHRcdGNvbnN0IGRpZmZCID0gTWF0aC5hYnMoY3VycmVudE9mZnNldCAtIG9mZnNldEIpO1xuXG5cdFx0XHRyZXR1cm4gZGlmZkIgLSBkaWZmQTtcblx0XHR9KTtcblx0fVxuXG5cdHB1YmxpYyBkaXNwbGF5VGltZSgpOiB2b2lkIHtcblx0XHR0aGlzLnRpbWVDb250YWluZXIuZW1wdHkoKTtcblx0XHR0aGlzLmRhdGVDb250YWluZXIuZW1wdHkoKTtcblx0XHR0aGlzLnRpbWV6b25lQ29udGFpbmVyLmVtcHR5KCk7XG5cblx0XHQvLyBEaXNwbGF5aW5nIHRpbWUgYmFzZWQgb24gdXNlcidzIGZvcm1hdCBvciBkZWZhdWx0XG5cdFx0Y29uc3QgY3VycmVudFRpbWUgPSBEYXRlVGltZS5sb2NhbCgpLnRvRm9ybWF0KFxuXHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MudGltZUZvcm1hdFxuXHRcdCk7XG5cdFx0dGhpcy50aW1lQ29udGFpbmVyLmNyZWF0ZUVsKFwiaDJcIiwge1xuXHRcdFx0Y2xzOiBcInRpbWUtZGlzcGxheVwiLFxuXHRcdFx0dGV4dDogY3VycmVudFRpbWUsXG5cdFx0fSk7XG5cblx0XHRpZiAodGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd0RhdGUpIHtcblx0XHRcdGNvbnN0IGN1cnJlbnREYXRlID0gRGF0ZVRpbWUubG9jYWwoKS50b0Zvcm1hdChcblx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuZGF0ZUZvcm1hdFxuXHRcdFx0KTtcblx0XHRcdHRoaXMuZGF0ZUNvbnRhaW5lci5jcmVhdGVFbChcImgyXCIsIHtcblx0XHRcdFx0Y2xzOiBcImRhdGUtZGlzcGxheVwiLFxuXHRcdFx0XHR0ZXh0OiBjdXJyZW50RGF0ZSxcblx0XHRcdH0pO1xuXHRcdH1cblxuXHRcdC8vIFNvcnQgdGhlIHRpbWV6b25lIHBhaXJzXG5cdFx0Y29uc3Qgc29ydGVkVGltZVpvbmVzID0gdGhpcy5zb3J0VGltZVpvbmVzKCk7XG5cblx0XHQvLyBVcGRhdGUgdGhlIHRpbWV6b25lIHBhaXJzXG5cdFx0aWYgKHRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dUaW1lWm9uZSkge1xuXHRcdFx0Y29uc3QgdGltZXpvbmVDb250YWluZXIgPSB0aGlzLnRpbWV6b25lQ29udGFpbmVyLmNyZWF0ZUVsKFwiZGl2XCIsIHtcblx0XHRcdFx0Y2xzOiBcInRpbWV6b25lLWNvbnRhaW5lclwiLFxuXHRcdFx0fSk7XG5cblx0XHRcdHNvcnRlZFRpbWVab25lcy5mb3JFYWNoKChlbnRyeSkgPT4ge1xuXHRcdFx0XHRpZiAoZW50cnkub2Zmc2V0KSB7XG5cdFx0XHRcdFx0Y29uc3Qgb2Zmc2V0ID0gcGFyc2VGbG9hdChlbnRyeS5vZmZzZXQpO1xuXHRcdFx0XHRcdGNvbnN0IHRpbWV6b25lVGltZSA9IERhdGVUaW1lLnV0YygpXG5cdFx0XHRcdFx0XHQucGx1cyh7IGhvdXJzOiBvZmZzZXQgfSlcblx0XHRcdFx0XHRcdC50b0Zvcm1hdCh0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lem9uZUZvcm1hdCk7XG5cblx0XHRcdFx0XHQvLyBDcmVhdGluZyB0aW1lem9uZSBwYWlyIGRpdiBhbmQgYXBwZW5kaW5nIG5hbWUgYW5kIHRpbWUgZGl2cyB0byBpdFxuXHRcdFx0XHRcdGNvbnN0IHRpbWV6b25lUGFpciA9IHRpbWV6b25lQ29udGFpbmVyLmNyZWF0ZUVsKFwiZGl2XCIsIHtcblx0XHRcdFx0XHRcdGNsczogXCJ0aW1lem9uZS1wYWlyXCIsXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0dGltZXpvbmVQYWlyLmNyZWF0ZUVsKFwiZGl2XCIsIHtcblx0XHRcdFx0XHRcdGNsczogXCJ0aW1lem9uZS1uYW1lXCIsXG5cdFx0XHRcdFx0XHR0ZXh0OiBlbnRyeS5uYW1lLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdHRpbWV6b25lUGFpci5jcmVhdGVFbChcImRpdlwiLCB7XG5cdFx0XHRcdFx0XHRjbHM6IFwidGltZXpvbmUtdGltZVwiLFxuXHRcdFx0XHRcdFx0dGV4dDogdGltZXpvbmVUaW1lLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdH1cbn1cblxuaW50ZXJmYWNlIFRpbWV6b25lUGFpciB7XG5cdG5hbWU6IHN0cmluZztcblx0b2Zmc2V0OiBzdHJpbmc7XG59XG5cbmludGVyZmFjZSBDbG9ja1NldHRpbmdzIHtcblx0dGltZUZvcm1hdDogc3RyaW5nO1xuXHRzaG93RGF0ZTogYm9vbGVhbjtcblx0ZGF0ZUZvcm1hdDogc3RyaW5nO1xuXHRzaG93VGltZVpvbmU6IGJvb2xlYW47XG5cdHRpbWVab25lUGFpcnM6IFRpbWV6b25lUGFpcltdO1xuXHR0aW1lem9uZUZvcm1hdDogc3RyaW5nO1xufVxuXG5jb25zdCBERUZBVUxUX1NFVFRJTkdTOiBDbG9ja1NldHRpbmdzID0ge1xuXHR0aW1lRm9ybWF0OiBcIkhIOm1tXCIsXG5cdHNob3dEYXRlOiB0cnVlLFxuXHRkYXRlRm9ybWF0OiBcIkVFRSAtIGRkXCIsXG5cdHNob3dUaW1lWm9uZTogdHJ1ZSxcblx0dGltZVpvbmVQYWlyczogW3sgbmFtZTogXCJcIiwgb2Zmc2V0OiBcIlwiIH1dLFxuXHR0aW1lem9uZUZvcm1hdDogXCJISDptbSAtIEVFRUVFXCIsXG59O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDbG9ja1BsdWdpbiBleHRlbmRzIFBsdWdpbiB7XG5cdHB1YmxpYyB2aWV3OiBDbG9ja1ZpZXc7XG5cdHB1YmxpYyBzZXR0aW5nczogQ2xvY2tTZXR0aW5ncztcblxuXHRwdWJsaWMgYXN5bmMgb25sb2FkKCk6IFByb21pc2U8dm9pZD4ge1xuXHRcdC8vIGNvbnNvbGUubG9nKFwiQ2xvY2s6IExvYWRpbmcgcGx1Z2luIHZcIiArIHRoaXMubWFuaWZlc3QudmVyc2lvbik7XG5cblx0XHQvLyBMb2FkIHBsdWdpbiBzZXR0aW5ncywgdXNpbmcgZGVmYXVsdCB2YWx1ZXMgaWYgbm8gc2F2ZWQgc2V0dGluZ3MgYXJlIGZvdW5kXG5cdFx0dGhpcy5zZXR0aW5ncyA9IE9iamVjdC5hc3NpZ24oXG5cdFx0XHR7fSxcblx0XHRcdERFRkFVTFRfU0VUVElOR1MsXG5cdFx0XHRhd2FpdCB0aGlzLmxvYWREYXRhKClcblx0XHQpO1xuXG5cdFx0Ly8gUmVnaXN0ZXIgdGhlIENsb2NrVmlldyB3aXRoIHRoZSBwbHVnaW5cblx0XHR0aGlzLnJlZ2lzdGVyVmlldyhcblx0XHRcdENsb2NrVmlld1R5cGUsXG5cdFx0XHQobGVhZikgPT4gKHRoaXMudmlldyA9IG5ldyBDbG9ja1ZpZXcobGVhZiwgdGhpcykpXG5cdFx0KTtcblxuXHRcdC8vIEFkZCB0aGUgJ09wZW4gQ2xvY2snIGNvbW1hbmQgdG8gb3BlbiB0aGUgQ2xvY2sgcGx1Z2luXG5cdFx0dGhpcy5hZGRDb21tYW5kKHtcblx0XHRcdGlkOiBcImNsb2NrLW9wZW5cIixcblx0XHRcdG5hbWU6IFwiT3BlbiBDbG9ja1wiLFxuXHRcdFx0Y2FsbGJhY2s6IGFzeW5jICgpID0+IHtcblx0XHRcdFx0bGV0IFtsZWFmXSA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRMZWF2ZXNPZlR5cGUoQ2xvY2tWaWV3VHlwZSk7XG5cdFx0XHRcdGlmICghbGVhZikge1xuXHRcdFx0XHRcdGxlYWYgPSB0aGlzLmFwcC53b3Jrc3BhY2UuZ2V0UmlnaHRMZWFmKGZhbHNlKTtcblx0XHRcdFx0XHRpZiAobGVhZikge1xuXHRcdFx0XHRcdFx0YXdhaXQgbGVhZi5zZXRWaWV3U3RhdGUoeyB0eXBlOiBDbG9ja1ZpZXdUeXBlIH0pO1xuXHRcdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0XHQvLyBIYW5kbGUgY2FzZSB3aGVyZSBsZWFmIGlzIG51bGwgb3IgdW5kZWZpbmVkXG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9XG5cdFx0XHRcdGlmIChsZWFmKSB7XG5cdFx0XHRcdFx0dGhpcy5hcHAud29ya3NwYWNlLnJldmVhbExlYWYobGVhZik7XG5cdFx0XHRcdH1cblx0XHRcdH0sXG5cdFx0fSk7XG5cblx0XHQvLyBJbml0aWFsaXplIHRoZSBDbG9jayBwbHVnaW4gdmlld1xuXHRcdGlmICh0aGlzLmFwcC53b3Jrc3BhY2UubGF5b3V0UmVhZHkpIHtcblx0XHRcdGF3YWl0IHRoaXMuaW5pdFZpZXcoKTtcblx0XHR9IGVsc2Uge1xuXHRcdFx0Y29uc3QgY2hlY2tMYXlvdXRJbnRlcnZhbCA9IHNldEludGVydmFsKGFzeW5jICgpID0+IHtcblx0XHRcdFx0aWYgKHRoaXMuYXBwLndvcmtzcGFjZS5sYXlvdXRSZWFkeSkge1xuXHRcdFx0XHRcdGF3YWl0IHRoaXMuaW5pdFZpZXcoKTtcblx0XHRcdFx0XHRjbGVhckludGVydmFsKGNoZWNrTGF5b3V0SW50ZXJ2YWwpO1xuXHRcdFx0XHR9XG5cdFx0XHR9LCAxMDAwKTtcblx0XHR9XG5cblx0XHQvLyBBZGQgdGhlIENsb2NrU2V0dGluZ1RhYiB0byB0aGUgcGx1Z2luJ3Mgc2V0dGluZ3Ncblx0XHR0aGlzLmFkZFNldHRpbmdUYWIobmV3IENsb2NrU2V0dGluZ1RhYih0aGlzLmFwcCwgdGhpcykpO1xuXHR9XG5cblx0cHVibGljIG9udW5sb2FkKCk6IHZvaWQge1xuXHRcdC8vIGNvbnNvbGUubG9nKFwiQ2xvY2s6IFVubG9hZGluZyBwbHVnaW5cIik7XG5cdFx0dGhpcy5hcHAud29ya3NwYWNlLmRldGFjaExlYXZlc09mVHlwZShDbG9ja1ZpZXdUeXBlKTtcblx0fVxuXG5cdHByaXZhdGUgYXN5bmMgaW5pdFZpZXcoKTogUHJvbWlzZTx2b2lkPiB7XG5cdFx0bGV0IFtsZWFmXSA9IHRoaXMuYXBwLndvcmtzcGFjZS5nZXRMZWF2ZXNPZlR5cGUoQ2xvY2tWaWV3VHlwZSk7XG5cdFx0aWYgKCFsZWFmKSB7XG5cdFx0XHRsZWFmID0gdGhpcy5hcHAud29ya3NwYWNlLmdldExlYWYoKTtcblx0XHRcdGlmIChsZWFmKSB7XG5cdFx0XHRcdGF3YWl0IGxlYWYuc2V0Vmlld1N0YXRlKHsgdHlwZTogQ2xvY2tWaWV3VHlwZSB9KTtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdC8vIEhhbmRsZSBjYXNlIHdoZXJlIGxlYWYgaXMgbnVsbCBvciB1bmRlZmluZWRcblx0XHRcdH1cblx0XHR9XG5cdFx0aWYgKGxlYWYpIHtcblx0XHRcdHRoaXMuYXBwLndvcmtzcGFjZS5yZXZlYWxMZWFmKGxlYWYpO1xuXHRcdH1cblx0XHR0aGlzLnZpZXcuZGlzcGxheVRpbWUoKTtcblx0XHRzZXRJbnRlcnZhbCgoKSA9PiB7XG5cdFx0XHR0aGlzLnZpZXcuZGlzcGxheVRpbWUoKTtcblx0XHR9LCAxMDAwKTtcblx0fVxuXG5cdGFzeW5jIHNhdmVTZXR0aW5ncygpOiBQcm9taXNlPHZvaWQ+IHtcblx0XHRhd2FpdCB0aGlzLnNhdmVEYXRhKHRoaXMuc2V0dGluZ3MpO1xuXHR9XG59XG5cbmNsYXNzIENsb2NrU2V0dGluZ1RhYiBleHRlbmRzIFBsdWdpblNldHRpbmdUYWIge1xuXHRwcml2YXRlIHJlYWRvbmx5IHBsdWdpbjogQ2xvY2tQbHVnaW47XG5cblx0Y29uc3RydWN0b3IoYXBwOiBBcHAsIHBsdWdpbjogQ2xvY2tQbHVnaW4pIHtcblx0XHRzdXBlcihhcHAsIHBsdWdpbik7XG5cdFx0dGhpcy5wbHVnaW4gPSBwbHVnaW47XG5cdH1cblxuXHRwdWJsaWMgZGlzcGxheSgpOiB2b2lkIHtcblx0XHRjb25zdCB7IGNvbnRhaW5lckVsIH0gPSB0aGlzO1xuXHRcdGNvbnRhaW5lckVsLmVtcHR5KCk7XG5cdFx0Y29udGFpbmVyRWwuY3JlYXRlRWwoXCJoMVwiLCB7IHRleHQ6IFwiQ2xvY2sgU2V0dGluZ3NcIiB9KTtcblxuXHRcdC8vIEFkZCBhIGxpbmsgdG8gdGhlIEx1eG9uIHJlZmVyZW5jZVxuXHRcdGxldCBoMkVsID0gY29udGFpbmVyRWwuY3JlYXRlRWwoXCJwXCIsIHtcblx0XHRcdHRleHQ6IFwiVXNlIHRoZSBMdXhvbiBmb3JtYXQgZm9yIGFsbCB0aW1lIGFuZCBkYXRlIHNldHRpbmdzOiBcIixcblx0XHR9KTtcblx0XHRoMkVsLmNyZWF0ZUVsKFwiYVwiLCB7XG5cdFx0XHR0ZXh0OiBcIiBMdXhvbiBSZWZlcmVuY2VcIixcblx0XHRcdGhyZWY6IFwiaHR0cHM6Ly9tb21lbnQuZ2l0aHViLmlvL2x1eG9uL2RvY3MvbWFudWFsL2Zvcm1hdHRpbmcuaHRtbFwiLFxuXHRcdFx0YXR0cjoge1xuXHRcdFx0XHR0YXJnZXQ6IFwiX2JsYW5rXCIsXG5cdFx0XHR9LFxuXHRcdH0pO1xuXG5cdFx0bGV0IHRleHRGaWVsZDogVGV4dENvbXBvbmVudDtcblxuXHRcdC8vIFRpbWUgRm9ybWF0IFNldHRpbmdzXG5cdFx0bmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0XHQuc2V0TmFtZShcIlRpbWUgZm9ybWF0XCIpXG5cdFx0XHQuc2V0RGVzYyhcblx0XHRcdFx0Y3JlYXRlRnJhZ21lbnQoKGZyYWdtZW50KSA9PiB7XG5cdFx0XHRcdFx0ZnJhZ21lbnQuYXBwZW5kKFxuXHRcdFx0XHRcdFx0XCJEZWZhdWx0IEx1eG9uIGZvcm1hdCBpcyBcIixcblx0XHRcdFx0XHRcdGZyYWdtZW50LmNyZWF0ZUVsKFwiY29kZVwiLCB7XG5cdFx0XHRcdFx0XHRcdHRleHQ6IFwiSEg6bW1cIixcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fSlcblx0XHRcdClcblx0XHRcdC5hZGRUZXh0KCh0ZXh0KSA9PiB7XG5cdFx0XHRcdHRleHRGaWVsZCA9IHRleHRcblx0XHRcdFx0XHQuc2V0UGxhY2Vob2xkZXIoXCJFbnRlciB0aGUgdGltZSBmb3JtYXRcIilcblx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3MudGltZUZvcm1hdCk7XG5cblx0XHRcdFx0Ly8gT25seSBzYXZlIHRoZSBzZXR0aW5nIHdoZW4gJ0VudGVyJyBpcyBwcmVzc2VkXG5cdFx0XHRcdHRleHRGaWVsZC5pbnB1dEVsLm9ua2V5cHJlc3MgPSBhc3luYyAoZSkgPT4ge1xuXHRcdFx0XHRcdGlmIChlLmtleSA9PT0gXCJFbnRlclwiKSB7XG5cdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lRm9ybWF0ID1cblx0XHRcdFx0XHRcdFx0dGV4dEZpZWxkLmlucHV0RWwudmFsdWU7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlRGF0YSh0aGlzLnBsdWdpbi5zZXR0aW5ncyk7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi52aWV3LmRpc3BsYXlUaW1lKCk7XG5cdFx0XHRcdFx0XHR0ZXh0RmllbGQuaW5wdXRFbC5ibHVyKCk7IC8vIExvc2UgZm9jdXNcblx0XHRcdFx0XHR9XG5cdFx0XHRcdH07XG5cdFx0XHR9KVxuXHRcdFx0LmFkZEV4dHJhQnV0dG9uKChidXR0b24pID0+XG5cdFx0XHRcdGJ1dHRvblxuXHRcdFx0XHRcdC5zZXRJY29uKFwicmVzZXRcIilcblx0XHRcdFx0XHQuc2V0VG9vbHRpcChcIlJlc2V0IHRpbWUgZm9ybWF0XCIpXG5cdFx0XHRcdFx0Lm9uQ2xpY2soYXN5bmMgKCkgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MudGltZUZvcm1hdCA9XG5cdFx0XHRcdFx0XHRcdERFRkFVTFRfU0VUVElOR1MudGltZUZvcm1hdDtcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVEYXRhKHRoaXMucGx1Z2luLnNldHRpbmdzKTtcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnZpZXcuZGlzcGxheVRpbWUoKTtcblxuXHRcdFx0XHRcdFx0Ly8gVXBkYXRlIHRoZSB2YWx1ZSBpbiB0aGUgdGV4dCBmaWVsZCB0byByZWZsZWN0IHRoZSByZXNldCB2YWx1ZVxuXHRcdFx0XHRcdFx0dGV4dEZpZWxkLnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWVGb3JtYXQpO1xuXHRcdFx0XHRcdH0pXG5cdFx0XHQpO1xuXG5cdFx0Ly8gRGF0ZSBGb3JtYXQgU2V0dGluZ3Ncblx0XHRuZXcgU2V0dGluZyhjb250YWluZXJFbClcblx0XHRcdC5zZXROYW1lKFwiU2hvdyBkYXRlXCIpXG5cdFx0XHQuc2V0RGVzYyhcIkVuYWJsZSB0byBzaG93IHRoZSBkYXRlLlwiKVxuXHRcdFx0LmFkZFRvZ2dsZSgodG9nZ2xlKSA9PiB7XG5cdFx0XHRcdHRvZ2dsZVxuXHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy5zaG93RGF0ZSlcblx0XHRcdFx0XHQub25DaGFuZ2UoYXN5bmMgKHZhbHVlKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5zaG93RGF0ZSA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZURhdGEodGhpcy5wbHVnaW4uc2V0dGluZ3MpO1xuXG5cdFx0XHRcdFx0XHRjb25zdCBjbG9ja1ZpZXcgPSB0aGlzLmFwcC53b3Jrc3BhY2Vcblx0XHRcdFx0XHRcdFx0LmdldExlYXZlc09mVHlwZShcIm15LWNsb2NrLXZpZXdcIilcblx0XHRcdFx0XHRcdFx0LmZpbmQoKGxlYWYpID0+IGxlYWYudmlldyBpbnN0YW5jZW9mIENsb2NrVmlldyk7XG5cdFx0XHRcdFx0XHRpZiAoY2xvY2tWaWV3KSB7XG5cdFx0XHRcdFx0XHRcdChjbG9ja1ZpZXcudmlldyBhcyBDbG9ja1ZpZXcpLmRpc3BsYXlUaW1lKCk7IC8vIFVwZGF0ZSB0aGUgY2xvY2sgaW1tZWRpYXRlbHlcblx0XHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdFx0Ly8gU2hvdyBvciBoaWRlIHRoZSBEYXRlIEZvcm1hdCBzZXR0aW5nIGJhc2VkIG9uIHRoZSB0b2dnbGUgdmFsdWVcblx0XHRcdFx0XHRcdGlmICh2YWx1ZSkge1xuXHRcdFx0XHRcdFx0XHRkYXRlRm9ybWF0U2V0dGluZy5zZXR0aW5nRWwuc3R5bGUuZGlzcGxheSA9IFwiXCI7XG5cdFx0XHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdFx0XHRkYXRlRm9ybWF0U2V0dGluZy5zZXR0aW5nRWwuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0fSk7XG5cblx0XHRsZXQgZGF0ZUZvcm1hdFNldHRpbmcgPSBuZXcgU2V0dGluZyhjb250YWluZXJFbClcblx0XHRcdC5zZXROYW1lKFwiRGF0ZSBmb3JtYXRcIilcblx0XHRcdC5zZXREZXNjKFxuXHRcdFx0XHRjcmVhdGVGcmFnbWVudCgoZnJhZ21lbnQpID0+IHtcblx0XHRcdFx0XHRmcmFnbWVudC5hcHBlbmQoXG5cdFx0XHRcdFx0XHRcIkRlZmF1bHQgTHV4b24gZm9ybWF0IGlzIFwiLFxuXHRcdFx0XHRcdFx0ZnJhZ21lbnQuY3JlYXRlRWwoXCJjb2RlXCIsIHtcblx0XHRcdFx0XHRcdFx0dGV4dDogXCJERERcIixcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fSlcblx0XHRcdClcblx0XHRcdC5hZGRUZXh0KCh0ZXh0KSA9PiB7XG5cdFx0XHRcdGxldCB0ZXh0RmllbGQgPSB0ZXh0XG5cdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFwiRW50ZXIgdGhlIGRhdGUgZm9ybWF0XCIpXG5cdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmRhdGVGb3JtYXQpO1xuXG5cdFx0XHRcdHRleHRGaWVsZC5pbnB1dEVsLm9ua2V5cHJlc3MgPSBhc3luYyAoZSkgPT4ge1xuXHRcdFx0XHRcdGlmIChlLmtleSA9PT0gXCJFbnRlclwiKSB7XG5cdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy5kYXRlRm9ybWF0ID1cblx0XHRcdFx0XHRcdFx0dGV4dEZpZWxkLmlucHV0RWwudmFsdWU7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlRGF0YSh0aGlzLnBsdWdpbi5zZXR0aW5ncyk7XG5cdFx0XHRcdFx0XHRjb25zdCBjbG9ja1ZpZXcgPSB0aGlzLmFwcC53b3Jrc3BhY2Vcblx0XHRcdFx0XHRcdFx0LmdldExlYXZlc09mVHlwZShcIm15LWNsb2NrLXZpZXdcIilcblx0XHRcdFx0XHRcdFx0LmZpbmQoKGxlYWYpID0+IGxlYWYudmlldyBpbnN0YW5jZW9mIENsb2NrVmlldyk7XG5cdFx0XHRcdFx0XHRpZiAoY2xvY2tWaWV3KSB7XG5cdFx0XHRcdFx0XHRcdChjbG9ja1ZpZXcudmlldyBhcyBDbG9ja1ZpZXcpLmRpc3BsYXlUaW1lKCk7XG5cdFx0XHRcdFx0XHR9XG5cdFx0XHRcdFx0XHR0ZXh0RmllbGQuaW5wdXRFbC5ibHVyKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdC8vIFNob3cgb3IgaGlkZSB0aGUgc2V0dGluZyBiYXNlZCBvbiB0aGUgJ1Nob3cgRGF0ZScgdG9nZ2xlIHZhbHVlXG5cdFx0XHRcdGlmICghdGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd0RhdGUpIHtcblx0XHRcdFx0XHR0ZXh0RmllbGQuaW5wdXRFbC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG5cdFx0XHRcdH1cblx0XHRcdH0pXG5cdFx0XHQuYWRkRXh0cmFCdXR0b24oKGJ1dHRvbikgPT4ge1xuXHRcdFx0XHRidXR0b25cblx0XHRcdFx0XHQuc2V0SWNvbihcInJlc2V0XCIpXG5cdFx0XHRcdFx0LnNldFRvb2x0aXAoXCJSZXNldCBkYXRlIGZvcm1hdFwiKVxuXHRcdFx0XHRcdC5vbkNsaWNrKGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLmRhdGVGb3JtYXQgPVxuXHRcdFx0XHRcdFx0XHRERUZBVUxUX1NFVFRJTkdTLmRhdGVGb3JtYXQ7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlRGF0YSh0aGlzLnBsdWdpbi5zZXR0aW5ncyk7XG5cdFx0XHRcdFx0XHR0aGlzLmRpc3BsYXkoKTtcblx0XHRcdFx0XHRcdG5ldyBOb3RpY2UoXCJEYXRlIEZvcm1hdCBSZXNldFwiKTtcblxuXHRcdFx0XHRcdFx0Y29uc3QgY2xvY2tWaWV3ID0gdGhpcy5hcHAud29ya3NwYWNlXG5cdFx0XHRcdFx0XHRcdC5nZXRMZWF2ZXNPZlR5cGUoXCJteS1jbG9jay12aWV3XCIpXG5cdFx0XHRcdFx0XHRcdC5maW5kKChsZWFmKSA9PiBsZWFmLnZpZXcgaW5zdGFuY2VvZiBDbG9ja1ZpZXcpO1xuXHRcdFx0XHRcdFx0aWYgKGNsb2NrVmlldykge1xuXHRcdFx0XHRcdFx0XHQoY2xvY2tWaWV3LnZpZXcgYXMgQ2xvY2tWaWV3KS5kaXNwbGF5VGltZSgpO1xuXHRcdFx0XHRcdFx0fVxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0fSk7XG5cblx0XHQvLyBTaG93IFRpbWV6b25lIFRvZ2dsZVxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdFx0LnNldE5hbWUoXCJTaG93IFRpbWV6b25lXCIpXG5cdFx0XHQuc2V0RGVzYyhcIkVuYWJsZSB0byBzaG93IHRoZSB0aW1lem9uZS5cIilcblx0XHRcdC5hZGRUb2dnbGUoKHRvZ2dsZSkgPT4ge1xuXHRcdFx0XHR0b2dnbGVcblx0XHRcdFx0XHQuc2V0VmFsdWUodGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd1RpbWVab25lKVxuXHRcdFx0XHRcdC5vbkNoYW5nZShhc3luYyAodmFsdWUpID0+IHtcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dUaW1lWm9uZSA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZURhdGEodGhpcy5wbHVnaW4uc2V0dGluZ3MpO1xuXHRcdFx0XHRcdFx0Y29uc3QgY2xvY2tWaWV3ID0gdGhpcy5hcHAud29ya3NwYWNlXG5cdFx0XHRcdFx0XHRcdC5nZXRMZWF2ZXNPZlR5cGUoXCJjbG9jay12aWV3XCIpXG5cdFx0XHRcdFx0XHRcdC5maW5kKChsZWFmKSA9PiBsZWFmLnZpZXcgaW5zdGFuY2VvZiBDbG9ja1ZpZXcpO1xuXHRcdFx0XHRcdFx0aWYgKGNsb2NrVmlldykge1xuXHRcdFx0XHRcdFx0XHQoY2xvY2tWaWV3LnZpZXcgYXMgQ2xvY2tWaWV3KS5kaXNwbGF5VGltZSgpOyAvLyBVcGRhdGUgdGhlIGNsb2NrIGltbWVkaWF0ZWx5XG5cdFx0XHRcdFx0XHR9XG5cblx0XHRcdFx0XHRcdC8vIFNob3cgb3IgaGlkZSB0aGUgVGltZXpvbmUgc2V0dGluZ3MgYmFzZWQgb24gdGhlIHRvZ2dsZSB2YWx1ZVxuXHRcdFx0XHRcdFx0dGltZXpvbmVTZXR0aW5nLnNldHRpbmdFbC5zdHlsZS5kaXNwbGF5ID0gdmFsdWVcblx0XHRcdFx0XHRcdFx0PyBcIlwiXG5cdFx0XHRcdFx0XHRcdDogXCJub25lXCI7XG5cdFx0XHRcdFx0XHR0aW1lem9uZUZvcm1hdFNldHRpbmcuc2V0dGluZ0VsLnN0eWxlLmRpc3BsYXkgPSB2YWx1ZVxuXHRcdFx0XHRcdFx0XHQ/IFwiXCJcblx0XHRcdFx0XHRcdFx0OiBcIm5vbmVcIjtcblx0XHRcdFx0XHR9KTtcblx0XHRcdH0pO1xuXG5cdFx0Ly8gVGltZXpvbmUgU2V0dGluZ3Ncblx0XHRsZXQgdGltZXpvbmVTZXR0aW5nID0gbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0XHQuc2V0TmFtZShcIlRpbWV6b25lIHNldHRpbmdzXCIpXG5cdFx0XHQuc2V0RGVzYyhcblx0XHRcdFx0Y3JlYXRlRnJhZ21lbnQoKGZyYWdtZW50KSA9PiB7XG5cdFx0XHRcdFx0ZnJhZ21lbnQuYXBwZW5kKFxuXHRcdFx0XHRcdFx0XCJFbnRlciB5b3VyIHRpbWV6b25lIHBhaXJzLlwiLFxuXHRcdFx0XHRcdFx0ZnJhZ21lbnQuY3JlYXRlRWwoXCJhXCIsIHtcblx0XHRcdFx0XHRcdFx0dGV4dDogXCIgUmVmZXJlbmNlXCIsXG5cdFx0XHRcdFx0XHRcdGhyZWY6IFwiaHR0cHM6Ly93d3cudGltZWFuZGRhdGUuY29tL3RpbWUvbWFwL1wiLFxuXHRcdFx0XHRcdFx0fSksXG5cdFx0XHRcdFx0XHRmcmFnbWVudC5jcmVhdGVFbChcImJyXCIpLFxuXHRcdFx0XHRcdFx0ZnJhZ21lbnQuY3JlYXRlRWwoXCJiclwiKSxcblx0XHRcdFx0XHRcdFwiTmFtZXMgYW5kIE9mZnNldCBwYWlycyBhcmUgbm90IHZhbGlkYXRlZC5cIlxuXHRcdFx0XHRcdCk7XG5cdFx0XHRcdH0pXG5cdFx0XHQpO1xuXG5cdFx0bGV0IHRpbWV6b25lU2V0dGluZ0RpdiA9IHRpbWV6b25lU2V0dGluZy5zZXR0aW5nRWwuY3JlYXRlRWwoXCJkaXZcIik7IC8vIEhlcmUgaXMgd2hlcmUgd2Ugd2lsbCBhdHRhY2ggdGhlIHRhYmxlXG5cblx0XHRpZiAodGhpcy5wbHVnaW4uc2V0dGluZ3Muc2hvd1RpbWVab25lKSB7XG5cdFx0XHRjb25zdCB0YWJsZSA9IHRpbWV6b25lU2V0dGluZ0Rpdi5jcmVhdGVFbChcInRhYmxlXCIpO1xuXHRcdFx0Y29uc3QgaGVhZGVyUm93ID0gdGFibGUuY3JlYXRlRWwoXCJ0clwiKTtcblx0XHRcdGhlYWRlclJvdy5jcmVhdGVFbChcInRoXCIsIHsgdGV4dDogXCJUaW1lem9uZSBOYW1lXCIgfSk7XG5cdFx0XHRoZWFkZXJSb3cuY3JlYXRlRWwoXCJ0aFwiLCB7IHRleHQ6IFwiVGltZXpvbmUgT2Zmc2V0XCIgfSk7XG5cdFx0XHRoZWFkZXJSb3cuY3JlYXRlRWwoXCJ0aFwiLCB7IHRleHQ6IFwiXCIgfSk7XG5cblx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWVab25lUGFpcnMuZm9yRWFjaCgoZW50cnksIGluZGV4KSA9PiB7XG5cdFx0XHRcdGNvbnN0IHJvdyA9IHRhYmxlLmNyZWF0ZUVsKFwidHJcIik7XG5cblx0XHRcdFx0Ly8gVGltZXpvbmUgTmFtZSBpbnB1dCBmaWVsZFxuXHRcdFx0XHRjb25zdCBuYW1lQ2VsbCA9IHJvdy5jcmVhdGVFbChcInRkXCIpO1xuXHRcdFx0XHRjb25zdCBuYW1lSW5wdXQgPSBuYW1lQ2VsbC5jcmVhdGVFbChcImlucHV0XCIsIHtcblx0XHRcdFx0XHR0eXBlOiBcInRleHRcIixcblx0XHRcdFx0XHR2YWx1ZTogZW50cnkubmFtZSxcblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gU2F2ZSB0aGUgc2V0dGluZ3Mgd2hlbiBFbnRlciBpcyBwcmVzc2VkIGluIHRoZSBOYW1lIGlucHV0IGZpZWxkXG5cdFx0XHRcdGNvbnN0IHNhdmVTZXR0aW5ncyA9IGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHRpZiAoXG5cdFx0XHRcdFx0XHRuYW1lSW5wdXQudmFsdWUudHJpbSgpICE9PSBcIlwiICYmXG5cdFx0XHRcdFx0XHRvZmZzZXRJbnB1dC52YWx1ZS50cmltKCkgIT09IFwiXCJcblx0XHRcdFx0XHQpIHtcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWVab25lUGFpcnNbaW5kZXhdLm5hbWUgPVxuXHRcdFx0XHRcdFx0XHRuYW1lSW5wdXQudmFsdWU7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lWm9uZVBhaXJzW2luZGV4XS5vZmZzZXQgPVxuXHRcdFx0XHRcdFx0XHRvZmZzZXRJbnB1dC52YWx1ZTtcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fTtcblxuXHRcdFx0XHRuYW1lSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImtleWRvd25cIiwgYXN5bmMgKGUpID0+IHtcblx0XHRcdFx0XHRpZiAoZS5rZXkgPT09IFwiRW50ZXJcIikge1xuXHRcdFx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0XHRcdFx0YXdhaXQgc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0XHRuYW1lSW5wdXQuYmx1cigpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gVGltZXpvbmUgT2Zmc2V0IGlucHV0IGZpZWxkXG5cdFx0XHRcdGNvbnN0IG9mZnNldENlbGwgPSByb3cuY3JlYXRlRWwoXCJ0ZFwiKTtcblx0XHRcdFx0Y29uc3Qgb2Zmc2V0SW5wdXQgPSBvZmZzZXRDZWxsLmNyZWF0ZUVsKFwiaW5wdXRcIiwge1xuXHRcdFx0XHRcdHR5cGU6IFwidGV4dFwiLFxuXHRcdFx0XHRcdHZhbHVlOiBlbnRyeS5vZmZzZXQsXG5cdFx0XHRcdH0pO1xuXG5cdFx0XHRcdG9mZnNldElucHV0LmFkZEV2ZW50TGlzdGVuZXIoXCJrZXlkb3duXCIsIGFzeW5jIChlKSA9PiB7XG5cdFx0XHRcdFx0aWYgKGUua2V5ID09PSBcIkVudGVyXCIpIHtcblx0XHRcdFx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHRcdFx0XHRcdGF3YWl0IHNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0b2Zmc2V0SW5wdXQuYmx1cigpO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fSk7XG5cblx0XHRcdFx0Ly8gQnV0dG9ucyBmb3IgZGVsZXRpbmcgYW5kIGFkZGluZyB0aW1lem9uZSBlbnRyaWVzXG5cdFx0XHRcdGNvbnN0IGJ1dHRvbnNDZWxsID0gcm93LmNyZWF0ZUVsKFwidGRcIik7XG5cblx0XHRcdFx0aWYgKGluZGV4ICE9PSAwKSB7XG5cdFx0XHRcdFx0Y29uc3QgZGVsZXRlQnV0dG9uID0gYnV0dG9uc0NlbGwuY3JlYXRlRWwoXCJidXR0b25cIiwge1xuXHRcdFx0XHRcdFx0dGV4dDogXCItXCIsXG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0ZGVsZXRlQnV0dG9uLmNsYXNzTGlzdC5hZGQoXCJkZWxldGVCdXR0b25DbGFzc1wiKTtcblx0XHRcdFx0XHRkZWxldGVCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGFzeW5jICgpID0+IHtcblx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWVab25lUGFpcnMuc3BsaWNlKGluZGV4LCAxKTtcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVTZXR0aW5ncygpO1xuXHRcdFx0XHRcdFx0dGhpcy5kaXNwbGF5KCk7XG5cdFx0XHRcdFx0fSk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRpZiAoaW5kZXggPT09IHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWVab25lUGFpcnMubGVuZ3RoIC0gMSkge1xuXHRcdFx0XHRcdGNvbnN0IGFkZEJ1dHRvbiA9IGJ1dHRvbnNDZWxsLmNyZWF0ZUVsKFwiYnV0dG9uXCIsIHtcblx0XHRcdFx0XHRcdHRleHQ6IFwiK1wiLFxuXHRcdFx0XHRcdH0pO1xuXHRcdFx0XHRcdGFkZEJ1dHRvbi5jbGFzc0xpc3QuYWRkKFwiYWRkQnV0dG9uQ2xhc3NcIik7XG5cdFx0XHRcdFx0YWRkQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0XHQvLyBMaW1pdCB0aW1lem9uZSBlbnRyaWVzIHRvIDVcblx0XHRcdFx0XHRcdGlmICh0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lWm9uZVBhaXJzLmxlbmd0aCA8IDUpIHtcblx0XHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MudGltZVpvbmVQYWlycy5wdXNoKHtcblx0XHRcdFx0XHRcdFx0XHRuYW1lOiBcIlwiLFxuXHRcdFx0XHRcdFx0XHRcdG9mZnNldDogXCJcIixcblx0XHRcdFx0XHRcdFx0fSk7XG5cdFx0XHRcdFx0XHRcdHRoaXMuZGlzcGxheSgpO1xuXHRcdFx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHRcdFx0Ly8gTWF4IGVudHJpZXMgcmVhY2hlZFxuXHRcdFx0XHRcdFx0XHRuZXcgTm90aWNlKFwiTWF4aW11bSB0aW1lem9uZSBlbnRyaWVzIGFkZGVkLlwiKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHR9KTtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdGlmIChcblx0XHRcdFx0XHRpbmRleCAhPT0gMCAmJlxuXHRcdFx0XHRcdGluZGV4ID09PSB0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lWm9uZVBhaXJzLmxlbmd0aCAtIDFcblx0XHRcdFx0KSB7XG5cdFx0XHRcdFx0YnV0dG9uc0NlbGwuY2xhc3NMaXN0LmFkZChcInR3b0J1dHRvbnNDbGFzc1wiKTtcblx0XHRcdFx0fVxuXHRcdFx0fSk7XG5cdFx0fVxuXG5cdFx0bGV0IHRpbWV6b25lRm9ybWF0RmllbGQ6IFRleHRDb21wb25lbnQ7XG5cblx0XHRsZXQgdGltZXpvbmVGb3JtYXRTZXR0aW5nID0gbmV3IFNldHRpbmcoY29udGFpbmVyRWwpXG5cdFx0XHQuc2V0TmFtZShcIlRpbWV6b25lIEZvcm1hdFwiKVxuXHRcdFx0LnNldERlc2MoXG5cdFx0XHRcdGNyZWF0ZUZyYWdtZW50KChmcmFnbWVudCkgPT4ge1xuXHRcdFx0XHRcdGZyYWdtZW50LmFwcGVuZChcblx0XHRcdFx0XHRcdFwiRGVmYXVsdCBMdXhvbiBmb3JtYXQgaXMgXCIsXG5cdFx0XHRcdFx0XHRmcmFnbWVudC5jcmVhdGVFbChcImNvZGVcIiwge1xuXHRcdFx0XHRcdFx0XHR0ZXh0OiBcIkhIOm1tIC0gRUVFRUVcIixcblx0XHRcdFx0XHRcdH0pXG5cdFx0XHRcdFx0KTtcblx0XHRcdFx0fSlcblx0XHRcdClcblx0XHRcdC5hZGRUZXh0KCh0ZXh0KSA9PiB7XG5cdFx0XHRcdHRpbWV6b25lRm9ybWF0RmllbGQgPSB0ZXh0XG5cdFx0XHRcdFx0LnNldFBsYWNlaG9sZGVyKFwiRW50ZXIgdGhlIHRpbWV6b25lIGZvcm1hdFwiKVxuXHRcdFx0XHRcdC5zZXRWYWx1ZSh0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lem9uZUZvcm1hdCk7XG5cblx0XHRcdFx0dGltZXpvbmVGb3JtYXRGaWVsZC5pbnB1dEVsLm9ua2V5cHJlc3MgPSBhc3luYyAoZSkgPT4ge1xuXHRcdFx0XHRcdGlmIChlLmtleSA9PT0gXCJFbnRlclwiKSB7XG5cdFx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lem9uZUZvcm1hdCA9XG5cdFx0XHRcdFx0XHRcdHRpbWV6b25lRm9ybWF0RmllbGQuaW5wdXRFbC52YWx1ZTtcblx0XHRcdFx0XHRcdGF3YWl0IHRoaXMucGx1Z2luLnNhdmVEYXRhKHRoaXMucGx1Z2luLnNldHRpbmdzKTtcblx0XHRcdFx0XHRcdGNvbnN0IGNsb2NrVmlldyA9IHRoaXMuYXBwLndvcmtzcGFjZVxuXHRcdFx0XHRcdFx0XHQuZ2V0TGVhdmVzT2ZUeXBlKFwiY2xvY2stdmlld1wiKVxuXHRcdFx0XHRcdFx0XHQuZmluZCgobGVhZikgPT4gbGVhZi52aWV3IGluc3RhbmNlb2YgQ2xvY2tWaWV3KTtcblx0XHRcdFx0XHRcdGlmIChjbG9ja1ZpZXcpIHtcblx0XHRcdFx0XHRcdFx0KGNsb2NrVmlldy52aWV3IGFzIENsb2NrVmlldykuZGlzcGxheVRpbWUoKTtcblx0XHRcdFx0XHRcdH1cblx0XHRcdFx0XHRcdHRpbWV6b25lRm9ybWF0RmllbGQuaW5wdXRFbC5ibHVyKCk7XG5cdFx0XHRcdFx0fVxuXHRcdFx0XHR9O1xuXHRcdFx0fSlcblx0XHRcdC5hZGRFeHRyYUJ1dHRvbigoYnV0dG9uKSA9PlxuXHRcdFx0XHRidXR0b25cblx0XHRcdFx0XHQuc2V0SWNvbihcInJlc2V0XCIpXG5cdFx0XHRcdFx0LnNldFRvb2x0aXAoXCJSZXNldCB0aW1lem9uZSBmb3JtYXRcIilcblx0XHRcdFx0XHQub25DbGljayhhc3luYyAoKSA9PiB7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi5zZXR0aW5ncy50aW1lem9uZUZvcm1hdCA9XG5cdFx0XHRcdFx0XHRcdERFRkFVTFRfU0VUVElOR1MudGltZXpvbmVGb3JtYXQ7XG5cdFx0XHRcdFx0XHRhd2FpdCB0aGlzLnBsdWdpbi5zYXZlRGF0YSh0aGlzLnBsdWdpbi5zZXR0aW5ncyk7XG5cdFx0XHRcdFx0XHR0aGlzLnBsdWdpbi52aWV3LmRpc3BsYXlUaW1lKCk7XG5cblx0XHRcdFx0XHRcdC8vIFVwZGF0ZSB0aGUgdmFsdWUgaW4gdGhlIHRleHQgZmllbGQgdG8gcmVmbGVjdCB0aGUgcmVzZXQgdmFsdWVcblx0XHRcdFx0XHRcdHRpbWV6b25lRm9ybWF0RmllbGQuc2V0VmFsdWUoXG5cdFx0XHRcdFx0XHRcdHRoaXMucGx1Z2luLnNldHRpbmdzLnRpbWV6b25lRm9ybWF0XG5cdFx0XHRcdFx0XHQpO1xuXHRcdFx0XHRcdH0pXG5cdFx0XHQpO1xuXG5cdFx0Ly8gQWRkIHRoZXNlIGxpbmVzIHRvIHJlbW92ZSB0aGUgYm9yZGVyc1xuXHRcdGRhdGVGb3JtYXRTZXR0aW5nLnNldHRpbmdFbC5zdHlsZS5ib3JkZXJUb3AgPSBcIm5vbmVcIjtcblx0XHR0aW1lem9uZVNldHRpbmcuc2V0dGluZ0VsLnN0eWxlLmJvcmRlclRvcCA9IFwibm9uZVwiO1xuXHRcdHRpbWV6b25lRm9ybWF0U2V0dGluZy5zZXR0aW5nRWwuc3R5bGUuYm9yZGVyVG9wID0gXCJub25lXCI7XG5cblx0XHRpZiAoIXRoaXMucGx1Z2luLnNldHRpbmdzLnNob3dUaW1lWm9uZSkge1xuXHRcdFx0dGltZXpvbmVTZXR0aW5nLnNldHRpbmdFbC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG5cdFx0XHR0aW1lem9uZUZvcm1hdFNldHRpbmcuc2V0dGluZ0VsLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcblx0XHR9XG5cdH1cbn1cbiIsICIvLyB0aGVzZSBhcmVuJ3QgcmVhbGx5IHByaXZhdGUsIGJ1dCBub3IgYXJlIHRoZXkgcmVhbGx5IHVzZWZ1bCB0byBkb2N1bWVudFxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIEx1eG9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7fVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjbGFzcyBJbnZhbGlkRGF0ZVRpbWVFcnJvciBleHRlbmRzIEx1eG9uRXJyb3Ige1xuICBjb25zdHJ1Y3RvcihyZWFzb24pIHtcbiAgICBzdXBlcihgSW52YWxpZCBEYXRlVGltZTogJHtyZWFzb24udG9NZXNzYWdlKCl9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY2xhc3MgSW52YWxpZEludGVydmFsRXJyb3IgZXh0ZW5kcyBMdXhvbkVycm9yIHtcbiAgY29uc3RydWN0b3IocmVhc29uKSB7XG4gICAgc3VwZXIoYEludmFsaWQgSW50ZXJ2YWw6ICR7cmVhc29uLnRvTWVzc2FnZSgpfWApO1xuICB9XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNsYXNzIEludmFsaWREdXJhdGlvbkVycm9yIGV4dGVuZHMgTHV4b25FcnJvciB7XG4gIGNvbnN0cnVjdG9yKHJlYXNvbikge1xuICAgIHN1cGVyKGBJbnZhbGlkIER1cmF0aW9uOiAke3JlYXNvbi50b01lc3NhZ2UoKX1gKTtcbiAgfVxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBjbGFzcyBDb25mbGljdGluZ1NwZWNpZmljYXRpb25FcnJvciBleHRlbmRzIEx1eG9uRXJyb3Ige31cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY2xhc3MgSW52YWxpZFVuaXRFcnJvciBleHRlbmRzIEx1eG9uRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcih1bml0KSB7XG4gICAgc3VwZXIoYEludmFsaWQgdW5pdCAke3VuaXR9YCk7XG4gIH1cbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5leHBvcnQgY2xhc3MgSW52YWxpZEFyZ3VtZW50RXJyb3IgZXh0ZW5kcyBMdXhvbkVycm9yIHt9XG5cbi8qKlxuICogQHByaXZhdGVcbiAqL1xuZXhwb3J0IGNsYXNzIFpvbmVJc0Fic3RyYWN0RXJyb3IgZXh0ZW5kcyBMdXhvbkVycm9yIHtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoXCJab25lIGlzIGFuIGFic3RyYWN0IGNsYXNzXCIpO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5cbmNvbnN0IG4gPSBcIm51bWVyaWNcIixcbiAgcyA9IFwic2hvcnRcIixcbiAgbCA9IFwibG9uZ1wiO1xuXG5leHBvcnQgY29uc3QgREFURV9TSE9SVCA9IHtcbiAgeWVhcjogbixcbiAgbW9udGg6IG4sXG4gIGRheTogbixcbn07XG5cbmV4cG9ydCBjb25zdCBEQVRFX01FRCA9IHtcbiAgeWVhcjogbixcbiAgbW9udGg6IHMsXG4gIGRheTogbixcbn07XG5cbmV4cG9ydCBjb25zdCBEQVRFX01FRF9XSVRIX1dFRUtEQVkgPSB7XG4gIHllYXI6IG4sXG4gIG1vbnRoOiBzLFxuICBkYXk6IG4sXG4gIHdlZWtkYXk6IHMsXG59O1xuXG5leHBvcnQgY29uc3QgREFURV9GVUxMID0ge1xuICB5ZWFyOiBuLFxuICBtb250aDogbCxcbiAgZGF5OiBuLFxufTtcblxuZXhwb3J0IGNvbnN0IERBVEVfSFVHRSA9IHtcbiAgeWVhcjogbixcbiAgbW9udGg6IGwsXG4gIGRheTogbixcbiAgd2Vla2RheTogbCxcbn07XG5cbmV4cG9ydCBjb25zdCBUSU1FX1NJTVBMRSA9IHtcbiAgaG91cjogbixcbiAgbWludXRlOiBuLFxufTtcblxuZXhwb3J0IGNvbnN0IFRJTUVfV0lUSF9TRUNPTkRTID0ge1xuICBob3VyOiBuLFxuICBtaW51dGU6IG4sXG4gIHNlY29uZDogbixcbn07XG5cbmV4cG9ydCBjb25zdCBUSU1FX1dJVEhfU0hPUlRfT0ZGU0VUID0ge1xuICBob3VyOiBuLFxuICBtaW51dGU6IG4sXG4gIHNlY29uZDogbixcbiAgdGltZVpvbmVOYW1lOiBzLFxufTtcblxuZXhwb3J0IGNvbnN0IFRJTUVfV0lUSF9MT05HX09GRlNFVCA9IHtcbiAgaG91cjogbixcbiAgbWludXRlOiBuLFxuICBzZWNvbmQ6IG4sXG4gIHRpbWVab25lTmFtZTogbCxcbn07XG5cbmV4cG9ydCBjb25zdCBUSU1FXzI0X1NJTVBMRSA9IHtcbiAgaG91cjogbixcbiAgbWludXRlOiBuLFxuICBob3VyQ3ljbGU6IFwiaDIzXCIsXG59O1xuXG5leHBvcnQgY29uc3QgVElNRV8yNF9XSVRIX1NFQ09ORFMgPSB7XG4gIGhvdXI6IG4sXG4gIG1pbnV0ZTogbixcbiAgc2Vjb25kOiBuLFxuICBob3VyQ3ljbGU6IFwiaDIzXCIsXG59O1xuXG5leHBvcnQgY29uc3QgVElNRV8yNF9XSVRIX1NIT1JUX09GRlNFVCA9IHtcbiAgaG91cjogbixcbiAgbWludXRlOiBuLFxuICBzZWNvbmQ6IG4sXG4gIGhvdXJDeWNsZTogXCJoMjNcIixcbiAgdGltZVpvbmVOYW1lOiBzLFxufTtcblxuZXhwb3J0IGNvbnN0IFRJTUVfMjRfV0lUSF9MT05HX09GRlNFVCA9IHtcbiAgaG91cjogbixcbiAgbWludXRlOiBuLFxuICBzZWNvbmQ6IG4sXG4gIGhvdXJDeWNsZTogXCJoMjNcIixcbiAgdGltZVpvbmVOYW1lOiBsLFxufTtcblxuZXhwb3J0IGNvbnN0IERBVEVUSU1FX1NIT1JUID0ge1xuICB5ZWFyOiBuLFxuICBtb250aDogbixcbiAgZGF5OiBuLFxuICBob3VyOiBuLFxuICBtaW51dGU6IG4sXG59O1xuXG5leHBvcnQgY29uc3QgREFURVRJTUVfU0hPUlRfV0lUSF9TRUNPTkRTID0ge1xuICB5ZWFyOiBuLFxuICBtb250aDogbixcbiAgZGF5OiBuLFxuICBob3VyOiBuLFxuICBtaW51dGU6IG4sXG4gIHNlY29uZDogbixcbn07XG5cbmV4cG9ydCBjb25zdCBEQVRFVElNRV9NRUQgPSB7XG4gIHllYXI6IG4sXG4gIG1vbnRoOiBzLFxuICBkYXk6IG4sXG4gIGhvdXI6IG4sXG4gIG1pbnV0ZTogbixcbn07XG5cbmV4cG9ydCBjb25zdCBEQVRFVElNRV9NRURfV0lUSF9TRUNPTkRTID0ge1xuICB5ZWFyOiBuLFxuICBtb250aDogcyxcbiAgZGF5OiBuLFxuICBob3VyOiBuLFxuICBtaW51dGU6IG4sXG4gIHNlY29uZDogbixcbn07XG5cbmV4cG9ydCBjb25zdCBEQVRFVElNRV9NRURfV0lUSF9XRUVLREFZID0ge1xuICB5ZWFyOiBuLFxuICBtb250aDogcyxcbiAgZGF5OiBuLFxuICB3ZWVrZGF5OiBzLFxuICBob3VyOiBuLFxuICBtaW51dGU6IG4sXG59O1xuXG5leHBvcnQgY29uc3QgREFURVRJTUVfRlVMTCA9IHtcbiAgeWVhcjogbixcbiAgbW9udGg6IGwsXG4gIGRheTogbixcbiAgaG91cjogbixcbiAgbWludXRlOiBuLFxuICB0aW1lWm9uZU5hbWU6IHMsXG59O1xuXG5leHBvcnQgY29uc3QgREFURVRJTUVfRlVMTF9XSVRIX1NFQ09ORFMgPSB7XG4gIHllYXI6IG4sXG4gIG1vbnRoOiBsLFxuICBkYXk6IG4sXG4gIGhvdXI6IG4sXG4gIG1pbnV0ZTogbixcbiAgc2Vjb25kOiBuLFxuICB0aW1lWm9uZU5hbWU6IHMsXG59O1xuXG5leHBvcnQgY29uc3QgREFURVRJTUVfSFVHRSA9IHtcbiAgeWVhcjogbixcbiAgbW9udGg6IGwsXG4gIGRheTogbixcbiAgd2Vla2RheTogbCxcbiAgaG91cjogbixcbiAgbWludXRlOiBuLFxuICB0aW1lWm9uZU5hbWU6IGwsXG59O1xuXG5leHBvcnQgY29uc3QgREFURVRJTUVfSFVHRV9XSVRIX1NFQ09ORFMgPSB7XG4gIHllYXI6IG4sXG4gIG1vbnRoOiBsLFxuICBkYXk6IG4sXG4gIHdlZWtkYXk6IGwsXG4gIGhvdXI6IG4sXG4gIG1pbnV0ZTogbixcbiAgc2Vjb25kOiBuLFxuICB0aW1lWm9uZU5hbWU6IGwsXG59O1xuIiwgImltcG9ydCB7IFpvbmVJc0Fic3RyYWN0RXJyb3IgfSBmcm9tIFwiLi9lcnJvcnMuanNcIjtcblxuLyoqXG4gKiBAaW50ZXJmYWNlXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFpvbmUge1xuICAvKipcbiAgICogVGhlIHR5cGUgb2Ygem9uZVxuICAgKiBAYWJzdHJhY3RcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICovXG4gIGdldCB0eXBlKCkge1xuICAgIHRocm93IG5ldyBab25lSXNBYnN0cmFjdEVycm9yKCk7XG4gIH1cblxuICAvKipcbiAgICogVGhlIG5hbWUgb2YgdGhpcyB6b25lLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICovXG4gIGdldCBuYW1lKCkge1xuICAgIHRocm93IG5ldyBab25lSXNBYnN0cmFjdEVycm9yKCk7XG4gIH1cblxuICBnZXQgaWFuYU5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMubmFtZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIG9mZnNldCBpcyBrbm93biB0byBiZSBmaXhlZCBmb3IgdGhlIHdob2xlIHllYXIuXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICovXG4gIGdldCBpc1VuaXZlcnNhbCgpIHtcbiAgICB0aHJvdyBuZXcgWm9uZUlzQWJzdHJhY3RFcnJvcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG9mZnNldCdzIGNvbW1vbiBuYW1lIChzdWNoIGFzIEVTVCkgYXQgdGhlIHNwZWNpZmllZCB0aW1lc3RhbXBcbiAgICogQGFic3RyYWN0XG4gICAqIEBwYXJhbSB7bnVtYmVyfSB0cyAtIEVwb2NoIG1pbGxpc2Vjb25kcyBmb3Igd2hpY2ggdG8gZ2V0IHRoZSBuYW1lXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gT3B0aW9ucyB0byBhZmZlY3QgdGhlIGZvcm1hdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5mb3JtYXQgLSBXaGF0IHN0eWxlIG9mIG9mZnNldCB0byByZXR1cm4uIEFjY2VwdHMgJ2xvbmcnIG9yICdzaG9ydCcuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLmxvY2FsZSAtIFdoYXQgbG9jYWxlIHRvIHJldHVybiB0aGUgb2Zmc2V0IG5hbWUgaW4uXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIG9mZnNldE5hbWUodHMsIG9wdHMpIHtcbiAgICB0aHJvdyBuZXcgWm9uZUlzQWJzdHJhY3RFcnJvcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG9mZnNldCdzIHZhbHVlIGFzIGEgc3RyaW5nXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge251bWJlcn0gdHMgLSBFcG9jaCBtaWxsaXNlY29uZHMgZm9yIHdoaWNoIHRvIGdldCB0aGUgb2Zmc2V0XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXQgLSBXaGF0IHN0eWxlIG9mIG9mZnNldCB0byByZXR1cm4uXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICBBY2NlcHRzICduYXJyb3cnLCAnc2hvcnQnLCBvciAndGVjaGllJy4gUmV0dXJuaW5nICcrNicsICcrMDY6MDAnLCBvciAnKzA2MDAnIHJlc3BlY3RpdmVseVxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICBmb3JtYXRPZmZzZXQodHMsIGZvcm1hdCkge1xuICAgIHRocm93IG5ldyBab25lSXNBYnN0cmFjdEVycm9yKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBvZmZzZXQgaW4gbWludXRlcyBmb3IgdGhpcyB6b25lIGF0IHRoZSBzcGVjaWZpZWQgdGltZXN0YW1wLlxuICAgKiBAYWJzdHJhY3RcbiAgICogQHBhcmFtIHtudW1iZXJ9IHRzIC0gRXBvY2ggbWlsbGlzZWNvbmRzIGZvciB3aGljaCB0byBjb21wdXRlIHRoZSBvZmZzZXRcbiAgICogQHJldHVybiB7bnVtYmVyfVxuICAgKi9cbiAgb2Zmc2V0KHRzKSB7XG4gICAgdGhyb3cgbmV3IFpvbmVJc0Fic3RyYWN0RXJyb3IoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gd2hldGhlciB0aGlzIFpvbmUgaXMgZXF1YWwgdG8gYW5vdGhlciB6b25lXG4gICAqIEBhYnN0cmFjdFxuICAgKiBAcGFyYW0ge1pvbmV9IG90aGVyWm9uZSAtIHRoZSB6b25lIHRvIGNvbXBhcmVcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIGVxdWFscyhvdGhlclpvbmUpIHtcbiAgICB0aHJvdyBuZXcgWm9uZUlzQWJzdHJhY3RFcnJvcigpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB3aGV0aGVyIHRoaXMgWm9uZSBpcyB2YWxpZC5cbiAgICogQGFic3RyYWN0XG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKi9cbiAgZ2V0IGlzVmFsaWQoKSB7XG4gICAgdGhyb3cgbmV3IFpvbmVJc0Fic3RyYWN0RXJyb3IoKTtcbiAgfVxufVxuIiwgImltcG9ydCB7IGZvcm1hdE9mZnNldCwgcGFyc2Vab25lSW5mbyB9IGZyb20gXCIuLi9pbXBsL3V0aWwuanNcIjtcbmltcG9ydCBab25lIGZyb20gXCIuLi96b25lLmpzXCI7XG5cbmxldCBzaW5nbGV0b24gPSBudWxsO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgdGhlIGxvY2FsIHpvbmUgZm9yIHRoaXMgSmF2YVNjcmlwdCBlbnZpcm9ubWVudC5cbiAqIEBpbXBsZW1lbnRzIHtab25lfVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBTeXN0ZW1ab25lIGV4dGVuZHMgWm9uZSB7XG4gIC8qKlxuICAgKiBHZXQgYSBzaW5nbGV0b24gaW5zdGFuY2Ugb2YgdGhlIGxvY2FsIHpvbmVcbiAgICogQHJldHVybiB7U3lzdGVtWm9uZX1cbiAgICovXG4gIHN0YXRpYyBnZXQgaW5zdGFuY2UoKSB7XG4gICAgaWYgKHNpbmdsZXRvbiA9PT0gbnVsbCkge1xuICAgICAgc2luZ2xldG9uID0gbmV3IFN5c3RlbVpvbmUoKTtcbiAgICB9XG4gICAgcmV0dXJuIHNpbmdsZXRvbjtcbiAgfVxuXG4gIC8qKiBAb3ZlcnJpZGUgKiovXG4gIGdldCB0eXBlKCkge1xuICAgIHJldHVybiBcInN5c3RlbVwiO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgZ2V0IG5hbWUoKSB7XG4gICAgcmV0dXJuIG5ldyBJbnRsLkRhdGVUaW1lRm9ybWF0KCkucmVzb2x2ZWRPcHRpb25zKCkudGltZVpvbmU7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBnZXQgaXNVbml2ZXJzYWwoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgb2Zmc2V0TmFtZSh0cywgeyBmb3JtYXQsIGxvY2FsZSB9KSB7XG4gICAgcmV0dXJuIHBhcnNlWm9uZUluZm8odHMsIGZvcm1hdCwgbG9jYWxlKTtcbiAgfVxuXG4gIC8qKiBAb3ZlcnJpZGUgKiovXG4gIGZvcm1hdE9mZnNldCh0cywgZm9ybWF0KSB7XG4gICAgcmV0dXJuIGZvcm1hdE9mZnNldCh0aGlzLm9mZnNldCh0cyksIGZvcm1hdCk7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBvZmZzZXQodHMpIHtcbiAgICByZXR1cm4gLW5ldyBEYXRlKHRzKS5nZXRUaW1lem9uZU9mZnNldCgpO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgZXF1YWxzKG90aGVyWm9uZSkge1xuICAgIHJldHVybiBvdGhlclpvbmUudHlwZSA9PT0gXCJzeXN0ZW1cIjtcbiAgfVxuXG4gIC8qKiBAb3ZlcnJpZGUgKiovXG4gIGdldCBpc1ZhbGlkKCkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG4iLCAiaW1wb3J0IHsgZm9ybWF0T2Zmc2V0LCBwYXJzZVpvbmVJbmZvLCBpc1VuZGVmaW5lZCwgb2JqVG9Mb2NhbFRTIH0gZnJvbSBcIi4uL2ltcGwvdXRpbC5qc1wiO1xuaW1wb3J0IFpvbmUgZnJvbSBcIi4uL3pvbmUuanNcIjtcblxubGV0IGR0ZkNhY2hlID0ge307XG5mdW5jdGlvbiBtYWtlRFRGKHpvbmUpIHtcbiAgaWYgKCFkdGZDYWNoZVt6b25lXSkge1xuICAgIGR0ZkNhY2hlW3pvbmVdID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQoXCJlbi1VU1wiLCB7XG4gICAgICBob3VyMTI6IGZhbHNlLFxuICAgICAgdGltZVpvbmU6IHpvbmUsXG4gICAgICB5ZWFyOiBcIm51bWVyaWNcIixcbiAgICAgIG1vbnRoOiBcIjItZGlnaXRcIixcbiAgICAgIGRheTogXCIyLWRpZ2l0XCIsXG4gICAgICBob3VyOiBcIjItZGlnaXRcIixcbiAgICAgIG1pbnV0ZTogXCIyLWRpZ2l0XCIsXG4gICAgICBzZWNvbmQ6IFwiMi1kaWdpdFwiLFxuICAgICAgZXJhOiBcInNob3J0XCIsXG4gICAgfSk7XG4gIH1cbiAgcmV0dXJuIGR0ZkNhY2hlW3pvbmVdO1xufVxuXG5jb25zdCB0eXBlVG9Qb3MgPSB7XG4gIHllYXI6IDAsXG4gIG1vbnRoOiAxLFxuICBkYXk6IDIsXG4gIGVyYTogMyxcbiAgaG91cjogNCxcbiAgbWludXRlOiA1LFxuICBzZWNvbmQ6IDYsXG59O1xuXG5mdW5jdGlvbiBoYWNreU9mZnNldChkdGYsIGRhdGUpIHtcbiAgY29uc3QgZm9ybWF0dGVkID0gZHRmLmZvcm1hdChkYXRlKS5yZXBsYWNlKC9cXHUyMDBFL2csIFwiXCIpLFxuICAgIHBhcnNlZCA9IC8oXFxkKylcXC8oXFxkKylcXC8oXFxkKykgKEFEfEJDKSw/IChcXGQrKTooXFxkKyk6KFxcZCspLy5leGVjKGZvcm1hdHRlZCksXG4gICAgWywgZk1vbnRoLCBmRGF5LCBmWWVhciwgZmFkT3JCYywgZkhvdXIsIGZNaW51dGUsIGZTZWNvbmRdID0gcGFyc2VkO1xuICByZXR1cm4gW2ZZZWFyLCBmTW9udGgsIGZEYXksIGZhZE9yQmMsIGZIb3VyLCBmTWludXRlLCBmU2Vjb25kXTtcbn1cblxuZnVuY3Rpb24gcGFydHNPZmZzZXQoZHRmLCBkYXRlKSB7XG4gIGNvbnN0IGZvcm1hdHRlZCA9IGR0Zi5mb3JtYXRUb1BhcnRzKGRhdGUpO1xuICBjb25zdCBmaWxsZWQgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBmb3JtYXR0ZWQubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCB7IHR5cGUsIHZhbHVlIH0gPSBmb3JtYXR0ZWRbaV07XG4gICAgY29uc3QgcG9zID0gdHlwZVRvUG9zW3R5cGVdO1xuXG4gICAgaWYgKHR5cGUgPT09IFwiZXJhXCIpIHtcbiAgICAgIGZpbGxlZFtwb3NdID0gdmFsdWU7XG4gICAgfSBlbHNlIGlmICghaXNVbmRlZmluZWQocG9zKSkge1xuICAgICAgZmlsbGVkW3Bvc10gPSBwYXJzZUludCh2YWx1ZSwgMTApO1xuICAgIH1cbiAgfVxuICByZXR1cm4gZmlsbGVkO1xufVxuXG5sZXQgaWFuYVpvbmVDYWNoZSA9IHt9O1xuLyoqXG4gKiBBIHpvbmUgaWRlbnRpZmllZCBieSBhbiBJQU5BIGlkZW50aWZpZXIsIGxpa2UgQW1lcmljYS9OZXdfWW9ya1xuICogQGltcGxlbWVudHMge1pvbmV9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIElBTkFab25lIGV4dGVuZHMgWm9uZSB7XG4gIC8qKlxuICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZSAtIFpvbmUgbmFtZVxuICAgKiBAcmV0dXJuIHtJQU5BWm9uZX1cbiAgICovXG4gIHN0YXRpYyBjcmVhdGUobmFtZSkge1xuICAgIGlmICghaWFuYVpvbmVDYWNoZVtuYW1lXSkge1xuICAgICAgaWFuYVpvbmVDYWNoZVtuYW1lXSA9IG5ldyBJQU5BWm9uZShuYW1lKTtcbiAgICB9XG4gICAgcmV0dXJuIGlhbmFab25lQ2FjaGVbbmFtZV07XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgbG9jYWwgY2FjaGVzLiBTaG91bGQgb25seSBiZSBuZWNlc3NhcnkgaW4gdGVzdGluZyBzY2VuYXJpb3MuXG4gICAqIEByZXR1cm4ge3ZvaWR9XG4gICAqL1xuICBzdGF0aWMgcmVzZXRDYWNoZSgpIHtcbiAgICBpYW5hWm9uZUNhY2hlID0ge307XG4gICAgZHRmQ2FjaGUgPSB7fTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHByb3ZpZGVkIHN0cmluZyBpcyBhIHZhbGlkIHNwZWNpZmllci4gVGhpcyBvbmx5IGNoZWNrcyB0aGUgc3RyaW5nJ3MgZm9ybWF0LCBub3QgdGhhdCB0aGUgc3BlY2lmaWVyIGlkZW50aWZpZXMgYSBrbm93biB6b25lOyBzZWUgaXNWYWxpZFpvbmUgZm9yIHRoYXQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzIC0gVGhlIHN0cmluZyB0byBjaGVjayB2YWxpZGl0eSBvblxuICAgKiBAZXhhbXBsZSBJQU5BWm9uZS5pc1ZhbGlkU3BlY2lmaWVyKFwiQW1lcmljYS9OZXdfWW9ya1wiKSAvLz0+IHRydWVcbiAgICogQGV4YW1wbGUgSUFOQVpvbmUuaXNWYWxpZFNwZWNpZmllcihcIlNwb3J0fn5ibG9ycFwiKSAvLz0+IGZhbHNlXG4gICAqIEBkZXByZWNhdGVkIFRoaXMgbWV0aG9kIHJldHVybnMgZmFsc2UgZm9yIHNvbWUgdmFsaWQgSUFOQSBuYW1lcy4gVXNlIGlzVmFsaWRab25lIGluc3RlYWQuXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59XG4gICAqL1xuICBzdGF0aWMgaXNWYWxpZFNwZWNpZmllcihzKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZFpvbmUocyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB3aGV0aGVyIHRoZSBwcm92aWRlZCBzdHJpbmcgaWRlbnRpZmllcyBhIHJlYWwgem9uZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gem9uZSAtIFRoZSBzdHJpbmcgdG8gY2hlY2tcbiAgICogQGV4YW1wbGUgSUFOQVpvbmUuaXNWYWxpZFpvbmUoXCJBbWVyaWNhL05ld19Zb3JrXCIpIC8vPT4gdHJ1ZVxuICAgKiBAZXhhbXBsZSBJQU5BWm9uZS5pc1ZhbGlkWm9uZShcIkZhbnRhc2lhL0Nhc3RsZVwiKSAvLz0+IGZhbHNlXG4gICAqIEBleGFtcGxlIElBTkFab25lLmlzVmFsaWRab25lKFwiU3BvcnR+fmJsb3JwXCIpIC8vPT4gZmFsc2VcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBpc1ZhbGlkWm9uZSh6b25lKSB7XG4gICAgaWYgKCF6b25lKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChcImVuLVVTXCIsIHsgdGltZVpvbmU6IHpvbmUgfSkuZm9ybWF0KCk7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgY29uc3RydWN0b3IobmFtZSkge1xuICAgIHN1cGVyKCk7XG4gICAgLyoqIEBwcml2YXRlICoqL1xuICAgIHRoaXMuem9uZU5hbWUgPSBuYW1lO1xuICAgIC8qKiBAcHJpdmF0ZSAqKi9cbiAgICB0aGlzLnZhbGlkID0gSUFOQVpvbmUuaXNWYWxpZFpvbmUobmFtZSk7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBnZXQgdHlwZSgpIHtcbiAgICByZXR1cm4gXCJpYW5hXCI7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBnZXQgbmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy56b25lTmFtZTtcbiAgfVxuXG4gIC8qKiBAb3ZlcnJpZGUgKiovXG4gIGdldCBpc1VuaXZlcnNhbCgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBvZmZzZXROYW1lKHRzLCB7IGZvcm1hdCwgbG9jYWxlIH0pIHtcbiAgICByZXR1cm4gcGFyc2Vab25lSW5mbyh0cywgZm9ybWF0LCBsb2NhbGUsIHRoaXMubmFtZSk7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBmb3JtYXRPZmZzZXQodHMsIGZvcm1hdCkge1xuICAgIHJldHVybiBmb3JtYXRPZmZzZXQodGhpcy5vZmZzZXQodHMpLCBmb3JtYXQpO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgb2Zmc2V0KHRzKSB7XG4gICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKHRzKTtcblxuICAgIGlmIChpc05hTihkYXRlKSkgcmV0dXJuIE5hTjtcblxuICAgIGNvbnN0IGR0ZiA9IG1ha2VEVEYodGhpcy5uYW1lKTtcbiAgICBsZXQgW3llYXIsIG1vbnRoLCBkYXksIGFkT3JCYywgaG91ciwgbWludXRlLCBzZWNvbmRdID0gZHRmLmZvcm1hdFRvUGFydHNcbiAgICAgID8gcGFydHNPZmZzZXQoZHRmLCBkYXRlKVxuICAgICAgOiBoYWNreU9mZnNldChkdGYsIGRhdGUpO1xuXG4gICAgaWYgKGFkT3JCYyA9PT0gXCJCQ1wiKSB7XG4gICAgICB5ZWFyID0gLU1hdGguYWJzKHllYXIpICsgMTtcbiAgICB9XG5cbiAgICAvLyBiZWNhdXNlIHdlJ3JlIHVzaW5nIGhvdXIxMiBhbmQgaHR0cHM6Ly9idWdzLmNocm9taXVtLm9yZy9wL2Nocm9taXVtL2lzc3Vlcy9kZXRhaWw/aWQ9MTAyNTU2NCZjYW49MiZxPSUyMjI0JTNBMDAlMjIlMjBkYXRldGltZWZvcm1hdFxuICAgIGNvbnN0IGFkanVzdGVkSG91ciA9IGhvdXIgPT09IDI0ID8gMCA6IGhvdXI7XG5cbiAgICBjb25zdCBhc1VUQyA9IG9ialRvTG9jYWxUUyh7XG4gICAgICB5ZWFyLFxuICAgICAgbW9udGgsXG4gICAgICBkYXksXG4gICAgICBob3VyOiBhZGp1c3RlZEhvdXIsXG4gICAgICBtaW51dGUsXG4gICAgICBzZWNvbmQsXG4gICAgICBtaWxsaXNlY29uZDogMCxcbiAgICB9KTtcblxuICAgIGxldCBhc1RTID0gK2RhdGU7XG4gICAgY29uc3Qgb3ZlciA9IGFzVFMgJSAxMDAwO1xuICAgIGFzVFMgLT0gb3ZlciA+PSAwID8gb3ZlciA6IDEwMDAgKyBvdmVyO1xuICAgIHJldHVybiAoYXNVVEMgLSBhc1RTKSAvICg2MCAqIDEwMDApO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgZXF1YWxzKG90aGVyWm9uZSkge1xuICAgIHJldHVybiBvdGhlclpvbmUudHlwZSA9PT0gXCJpYW5hXCIgJiYgb3RoZXJab25lLm5hbWUgPT09IHRoaXMubmFtZTtcbiAgfVxuXG4gIC8qKiBAb3ZlcnJpZGUgKiovXG4gIGdldCBpc1ZhbGlkKCkge1xuICAgIHJldHVybiB0aGlzLnZhbGlkO1xuICB9XG59XG4iLCAiaW1wb3J0IHsgcGFkU3RhcnQsIHJvdW5kVG8sIGhhc1JlbGF0aXZlLCBmb3JtYXRPZmZzZXQgfSBmcm9tIFwiLi91dGlsLmpzXCI7XG5pbXBvcnQgKiBhcyBFbmdsaXNoIGZyb20gXCIuL2VuZ2xpc2guanNcIjtcbmltcG9ydCBTZXR0aW5ncyBmcm9tIFwiLi4vc2V0dGluZ3MuanNcIjtcbmltcG9ydCBEYXRlVGltZSBmcm9tIFwiLi4vZGF0ZXRpbWUuanNcIjtcbmltcG9ydCBJQU5BWm9uZSBmcm9tIFwiLi4vem9uZXMvSUFOQVpvbmUuanNcIjtcblxuLy8gdG9kbyAtIHJlbWFwIGNhY2hpbmdcblxubGV0IGludGxMRkNhY2hlID0ge307XG5mdW5jdGlvbiBnZXRDYWNoZWRMRihsb2NTdHJpbmcsIG9wdHMgPSB7fSkge1xuICBjb25zdCBrZXkgPSBKU09OLnN0cmluZ2lmeShbbG9jU3RyaW5nLCBvcHRzXSk7XG4gIGxldCBkdGYgPSBpbnRsTEZDYWNoZVtrZXldO1xuICBpZiAoIWR0Zikge1xuICAgIGR0ZiA9IG5ldyBJbnRsLkxpc3RGb3JtYXQobG9jU3RyaW5nLCBvcHRzKTtcbiAgICBpbnRsTEZDYWNoZVtrZXldID0gZHRmO1xuICB9XG4gIHJldHVybiBkdGY7XG59XG5cbmxldCBpbnRsRFRDYWNoZSA9IHt9O1xuZnVuY3Rpb24gZ2V0Q2FjaGVkRFRGKGxvY1N0cmluZywgb3B0cyA9IHt9KSB7XG4gIGNvbnN0IGtleSA9IEpTT04uc3RyaW5naWZ5KFtsb2NTdHJpbmcsIG9wdHNdKTtcbiAgbGV0IGR0ZiA9IGludGxEVENhY2hlW2tleV07XG4gIGlmICghZHRmKSB7XG4gICAgZHRmID0gbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQobG9jU3RyaW5nLCBvcHRzKTtcbiAgICBpbnRsRFRDYWNoZVtrZXldID0gZHRmO1xuICB9XG4gIHJldHVybiBkdGY7XG59XG5cbmxldCBpbnRsTnVtQ2FjaGUgPSB7fTtcbmZ1bmN0aW9uIGdldENhY2hlZElORihsb2NTdHJpbmcsIG9wdHMgPSB7fSkge1xuICBjb25zdCBrZXkgPSBKU09OLnN0cmluZ2lmeShbbG9jU3RyaW5nLCBvcHRzXSk7XG4gIGxldCBpbmYgPSBpbnRsTnVtQ2FjaGVba2V5XTtcbiAgaWYgKCFpbmYpIHtcbiAgICBpbmYgPSBuZXcgSW50bC5OdW1iZXJGb3JtYXQobG9jU3RyaW5nLCBvcHRzKTtcbiAgICBpbnRsTnVtQ2FjaGVba2V5XSA9IGluZjtcbiAgfVxuICByZXR1cm4gaW5mO1xufVxuXG5sZXQgaW50bFJlbENhY2hlID0ge307XG5mdW5jdGlvbiBnZXRDYWNoZWRSVEYobG9jU3RyaW5nLCBvcHRzID0ge30pIHtcbiAgY29uc3QgeyBiYXNlLCAuLi5jYWNoZUtleU9wdHMgfSA9IG9wdHM7IC8vIGV4Y2x1ZGUgYGJhc2VgIGZyb20gdGhlIG9wdGlvbnNcbiAgY29uc3Qga2V5ID0gSlNPTi5zdHJpbmdpZnkoW2xvY1N0cmluZywgY2FjaGVLZXlPcHRzXSk7XG4gIGxldCBpbmYgPSBpbnRsUmVsQ2FjaGVba2V5XTtcbiAgaWYgKCFpbmYpIHtcbiAgICBpbmYgPSBuZXcgSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXQobG9jU3RyaW5nLCBvcHRzKTtcbiAgICBpbnRsUmVsQ2FjaGVba2V5XSA9IGluZjtcbiAgfVxuICByZXR1cm4gaW5mO1xufVxuXG5sZXQgc3lzTG9jYWxlQ2FjaGUgPSBudWxsO1xuZnVuY3Rpb24gc3lzdGVtTG9jYWxlKCkge1xuICBpZiAoc3lzTG9jYWxlQ2FjaGUpIHtcbiAgICByZXR1cm4gc3lzTG9jYWxlQ2FjaGU7XG4gIH0gZWxzZSB7XG4gICAgc3lzTG9jYWxlQ2FjaGUgPSBuZXcgSW50bC5EYXRlVGltZUZvcm1hdCgpLnJlc29sdmVkT3B0aW9ucygpLmxvY2FsZTtcbiAgICByZXR1cm4gc3lzTG9jYWxlQ2FjaGU7XG4gIH1cbn1cblxuZnVuY3Rpb24gcGFyc2VMb2NhbGVTdHJpbmcobG9jYWxlU3RyKSB7XG4gIC8vIEkgcmVhbGx5IHdhbnQgdG8gYXZvaWQgd3JpdGluZyBhIEJDUCA0NyBwYXJzZXJcbiAgLy8gc2VlLCBlLmcuIGh0dHBzOi8vZ2l0aHViLmNvbS93b29vcm0vYmNwLTQ3XG4gIC8vIEluc3RlYWQsIHdlJ2xsIGRvIHRoaXM6XG5cbiAgLy8gYSkgaWYgdGhlIHN0cmluZyBoYXMgbm8gLXUgZXh0ZW5zaW9ucywganVzdCBsZWF2ZSBpdCBhbG9uZVxuICAvLyBiKSBpZiBpdCBkb2VzLCB1c2UgSW50bCB0byByZXNvbHZlIGV2ZXJ5dGhpbmdcbiAgLy8gYykgaWYgSW50bCBmYWlscywgdHJ5IGFnYWluIHdpdGhvdXQgdGhlIC11XG5cbiAgLy8gcHJpdmF0ZSBzdWJ0YWdzIGFuZCB1bmljb2RlIHN1YnRhZ3MgaGF2ZSBvcmRlcmluZyByZXF1aXJlbWVudHMsXG4gIC8vIGFuZCB3ZSdyZSBub3QgcHJvcGVybHkgcGFyc2luZyB0aGlzLCBzbyBqdXN0IHN0cmlwIG91dCB0aGVcbiAgLy8gcHJpdmF0ZSBvbmVzIGlmIHRoZXkgZXhpc3QuXG4gIGNvbnN0IHhJbmRleCA9IGxvY2FsZVN0ci5pbmRleE9mKFwiLXgtXCIpO1xuICBpZiAoeEluZGV4ICE9PSAtMSkge1xuICAgIGxvY2FsZVN0ciA9IGxvY2FsZVN0ci5zdWJzdHJpbmcoMCwgeEluZGV4KTtcbiAgfVxuXG4gIGNvbnN0IHVJbmRleCA9IGxvY2FsZVN0ci5pbmRleE9mKFwiLXUtXCIpO1xuICBpZiAodUluZGV4ID09PSAtMSkge1xuICAgIHJldHVybiBbbG9jYWxlU3RyXTtcbiAgfSBlbHNlIHtcbiAgICBsZXQgb3B0aW9ucztcbiAgICBsZXQgc2VsZWN0ZWRTdHI7XG4gICAgdHJ5IHtcbiAgICAgIG9wdGlvbnMgPSBnZXRDYWNoZWREVEYobG9jYWxlU3RyKS5yZXNvbHZlZE9wdGlvbnMoKTtcbiAgICAgIHNlbGVjdGVkU3RyID0gbG9jYWxlU3RyO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGNvbnN0IHNtYWxsZXIgPSBsb2NhbGVTdHIuc3Vic3RyaW5nKDAsIHVJbmRleCk7XG4gICAgICBvcHRpb25zID0gZ2V0Q2FjaGVkRFRGKHNtYWxsZXIpLnJlc29sdmVkT3B0aW9ucygpO1xuICAgICAgc2VsZWN0ZWRTdHIgPSBzbWFsbGVyO1xuICAgIH1cblxuICAgIGNvbnN0IHsgbnVtYmVyaW5nU3lzdGVtLCBjYWxlbmRhciB9ID0gb3B0aW9ucztcbiAgICByZXR1cm4gW3NlbGVjdGVkU3RyLCBudW1iZXJpbmdTeXN0ZW0sIGNhbGVuZGFyXTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpbnRsQ29uZmlnU3RyaW5nKGxvY2FsZVN0ciwgbnVtYmVyaW5nU3lzdGVtLCBvdXRwdXRDYWxlbmRhcikge1xuICBpZiAob3V0cHV0Q2FsZW5kYXIgfHwgbnVtYmVyaW5nU3lzdGVtKSB7XG4gICAgaWYgKCFsb2NhbGVTdHIuaW5jbHVkZXMoXCItdS1cIikpIHtcbiAgICAgIGxvY2FsZVN0ciArPSBcIi11XCI7XG4gICAgfVxuXG4gICAgaWYgKG91dHB1dENhbGVuZGFyKSB7XG4gICAgICBsb2NhbGVTdHIgKz0gYC1jYS0ke291dHB1dENhbGVuZGFyfWA7XG4gICAgfVxuXG4gICAgaWYgKG51bWJlcmluZ1N5c3RlbSkge1xuICAgICAgbG9jYWxlU3RyICs9IGAtbnUtJHtudW1iZXJpbmdTeXN0ZW19YDtcbiAgICB9XG4gICAgcmV0dXJuIGxvY2FsZVN0cjtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbG9jYWxlU3RyO1xuICB9XG59XG5cbmZ1bmN0aW9uIG1hcE1vbnRocyhmKSB7XG4gIGNvbnN0IG1zID0gW107XG4gIGZvciAobGV0IGkgPSAxOyBpIDw9IDEyOyBpKyspIHtcbiAgICBjb25zdCBkdCA9IERhdGVUaW1lLnV0YygyMDE2LCBpLCAxKTtcbiAgICBtcy5wdXNoKGYoZHQpKTtcbiAgfVxuICByZXR1cm4gbXM7XG59XG5cbmZ1bmN0aW9uIG1hcFdlZWtkYXlzKGYpIHtcbiAgY29uc3QgbXMgPSBbXTtcbiAgZm9yIChsZXQgaSA9IDE7IGkgPD0gNzsgaSsrKSB7XG4gICAgY29uc3QgZHQgPSBEYXRlVGltZS51dGMoMjAxNiwgMTEsIDEzICsgaSk7XG4gICAgbXMucHVzaChmKGR0KSk7XG4gIH1cbiAgcmV0dXJuIG1zO1xufVxuXG5mdW5jdGlvbiBsaXN0U3R1ZmYobG9jLCBsZW5ndGgsIGRlZmF1bHRPSywgZW5nbGlzaEZuLCBpbnRsRm4pIHtcbiAgY29uc3QgbW9kZSA9IGxvYy5saXN0aW5nTW9kZShkZWZhdWx0T0spO1xuXG4gIGlmIChtb2RlID09PSBcImVycm9yXCIpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSBlbHNlIGlmIChtb2RlID09PSBcImVuXCIpIHtcbiAgICByZXR1cm4gZW5nbGlzaEZuKGxlbmd0aCk7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGludGxGbihsZW5ndGgpO1xuICB9XG59XG5cbmZ1bmN0aW9uIHN1cHBvcnRzRmFzdE51bWJlcnMobG9jKSB7XG4gIGlmIChsb2MubnVtYmVyaW5nU3lzdGVtICYmIGxvYy5udW1iZXJpbmdTeXN0ZW0gIT09IFwibGF0blwiKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiAoXG4gICAgICBsb2MubnVtYmVyaW5nU3lzdGVtID09PSBcImxhdG5cIiB8fFxuICAgICAgIWxvYy5sb2NhbGUgfHxcbiAgICAgIGxvYy5sb2NhbGUuc3RhcnRzV2l0aChcImVuXCIpIHx8XG4gICAgICBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChsb2MuaW50bCkucmVzb2x2ZWRPcHRpb25zKCkubnVtYmVyaW5nU3lzdGVtID09PSBcImxhdG5cIlxuICAgICk7XG4gIH1cbn1cblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5cbmNsYXNzIFBvbHlOdW1iZXJGb3JtYXR0ZXIge1xuICBjb25zdHJ1Y3RvcihpbnRsLCBmb3JjZVNpbXBsZSwgb3B0cykge1xuICAgIHRoaXMucGFkVG8gPSBvcHRzLnBhZFRvIHx8IDA7XG4gICAgdGhpcy5mbG9vciA9IG9wdHMuZmxvb3IgfHwgZmFsc2U7XG5cbiAgICBjb25zdCB7IHBhZFRvLCBmbG9vciwgLi4ub3RoZXJPcHRzIH0gPSBvcHRzO1xuXG4gICAgaWYgKCFmb3JjZVNpbXBsZSB8fCBPYmplY3Qua2V5cyhvdGhlck9wdHMpLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IGludGxPcHRzID0geyB1c2VHcm91cGluZzogZmFsc2UsIC4uLm9wdHMgfTtcbiAgICAgIGlmIChvcHRzLnBhZFRvID4gMCkgaW50bE9wdHMubWluaW11bUludGVnZXJEaWdpdHMgPSBvcHRzLnBhZFRvO1xuICAgICAgdGhpcy5pbmYgPSBnZXRDYWNoZWRJTkYoaW50bCwgaW50bE9wdHMpO1xuICAgIH1cbiAgfVxuXG4gIGZvcm1hdChpKSB7XG4gICAgaWYgKHRoaXMuaW5mKSB7XG4gICAgICBjb25zdCBmaXhlZCA9IHRoaXMuZmxvb3IgPyBNYXRoLmZsb29yKGkpIDogaTtcbiAgICAgIHJldHVybiB0aGlzLmluZi5mb3JtYXQoZml4ZWQpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyB0byBtYXRjaCB0aGUgYnJvd3NlcidzIG51bWJlcmZvcm1hdHRlciBkZWZhdWx0c1xuICAgICAgY29uc3QgZml4ZWQgPSB0aGlzLmZsb29yID8gTWF0aC5mbG9vcihpKSA6IHJvdW5kVG8oaSwgMyk7XG4gICAgICByZXR1cm4gcGFkU3RhcnQoZml4ZWQsIHRoaXMucGFkVG8pO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cblxuY2xhc3MgUG9seURhdGVGb3JtYXR0ZXIge1xuICBjb25zdHJ1Y3RvcihkdCwgaW50bCwgb3B0cykge1xuICAgIHRoaXMub3B0cyA9IG9wdHM7XG4gICAgdGhpcy5vcmlnaW5hbFpvbmUgPSB1bmRlZmluZWQ7XG5cbiAgICBsZXQgeiA9IHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5vcHRzLnRpbWVab25lKSB7XG4gICAgICAvLyBEb24ndCBhcHBseSBhbnkgd29ya2Fyb3VuZHMgaWYgYSB0aW1lWm9uZSBpcyBleHBsaWNpdGx5IHByb3ZpZGVkIGluIG9wdHNcbiAgICAgIHRoaXMuZHQgPSBkdDtcbiAgICB9IGVsc2UgaWYgKGR0LnpvbmUudHlwZSA9PT0gXCJmaXhlZFwiKSB7XG4gICAgICAvLyBVVEMtOCBvciBFdGMvVVRDLTggYXJlIG5vdCBwYXJ0IG9mIHR6ZGF0YSwgb25seSBFdGMvR01UKzggYW5kIHRoZSBsaWtlLlxuICAgICAgLy8gVGhhdCBpcyB3aHkgZml4ZWQtb2Zmc2V0IFRaIGlzIHNldCB0byB0aGF0IHVubGVzcyBpdCBpczpcbiAgICAgIC8vIDEuIFJlcHJlc2VudGluZyBvZmZzZXQgMCB3aGVuIFVUQyBpcyB1c2VkIHRvIG1haW50YWluIHByZXZpb3VzIGJlaGF2aW9yIGFuZCBkb2VzIG5vdCBiZWNvbWUgR01ULlxuICAgICAgLy8gMi4gVW5zdXBwb3J0ZWQgYnkgdGhlIGJyb3dzZXI6XG4gICAgICAvLyAgICAtIHNvbWUgZG8gbm90IHN1cHBvcnQgRXRjL1xuICAgICAgLy8gICAgLSA8IEV0Yy9HTVQtMTQsID4gRXRjL0dNVCsxMiwgYW5kIDMwLW1pbnV0ZSBvciA0NS1taW51dGUgb2Zmc2V0cyBhcmUgbm90IHBhcnQgb2YgdHpkYXRhXG4gICAgICBjb25zdCBnbXRPZmZzZXQgPSAtMSAqIChkdC5vZmZzZXQgLyA2MCk7XG4gICAgICBjb25zdCBvZmZzZXRaID0gZ210T2Zmc2V0ID49IDAgPyBgRXRjL0dNVCske2dtdE9mZnNldH1gIDogYEV0Yy9HTVQke2dtdE9mZnNldH1gO1xuICAgICAgaWYgKGR0Lm9mZnNldCAhPT0gMCAmJiBJQU5BWm9uZS5jcmVhdGUob2Zmc2V0WikudmFsaWQpIHtcbiAgICAgICAgeiA9IG9mZnNldFo7XG4gICAgICAgIHRoaXMuZHQgPSBkdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIE5vdCBhbGwgZml4ZWQtb2Zmc2V0IHpvbmVzIGxpa2UgRXRjLys0OjMwIGFyZSBwcmVzZW50IGluIHR6ZGF0YSBzb1xuICAgICAgICAvLyB3ZSBtYW51YWxseSBhcHBseSB0aGUgb2Zmc2V0IGFuZCBzdWJzdGl0dXRlIHRoZSB6b25lIGFzIG5lZWRlZC5cbiAgICAgICAgeiA9IFwiVVRDXCI7XG4gICAgICAgIHRoaXMuZHQgPSBkdC5vZmZzZXQgPT09IDAgPyBkdCA6IGR0LnNldFpvbmUoXCJVVENcIikucGx1cyh7IG1pbnV0ZXM6IGR0Lm9mZnNldCB9KTtcbiAgICAgICAgdGhpcy5vcmlnaW5hbFpvbmUgPSBkdC56b25lO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZHQuem9uZS50eXBlID09PSBcInN5c3RlbVwiKSB7XG4gICAgICB0aGlzLmR0ID0gZHQ7XG4gICAgfSBlbHNlIGlmIChkdC56b25lLnR5cGUgPT09IFwiaWFuYVwiKSB7XG4gICAgICB0aGlzLmR0ID0gZHQ7XG4gICAgICB6ID0gZHQuem9uZS5uYW1lO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBDdXN0b20gem9uZXMgY2FuIGhhdmUgYW55IG9mZnNldCAvIG9mZnNldE5hbWUgc28gd2UganVzdCBtYW51YWxseVxuICAgICAgLy8gYXBwbHkgdGhlIG9mZnNldCBhbmQgc3Vic3RpdHV0ZSB0aGUgem9uZSBhcyBuZWVkZWQuXG4gICAgICB6ID0gXCJVVENcIjtcbiAgICAgIHRoaXMuZHQgPSBkdC5zZXRab25lKFwiVVRDXCIpLnBsdXMoeyBtaW51dGVzOiBkdC5vZmZzZXQgfSk7XG4gICAgICB0aGlzLm9yaWdpbmFsWm9uZSA9IGR0LnpvbmU7XG4gICAgfVxuXG4gICAgY29uc3QgaW50bE9wdHMgPSB7IC4uLnRoaXMub3B0cyB9O1xuICAgIGludGxPcHRzLnRpbWVab25lID0gaW50bE9wdHMudGltZVpvbmUgfHwgejtcbiAgICB0aGlzLmR0ZiA9IGdldENhY2hlZERURihpbnRsLCBpbnRsT3B0cyk7XG4gIH1cblxuICBmb3JtYXQoKSB7XG4gICAgaWYgKHRoaXMub3JpZ2luYWxab25lKSB7XG4gICAgICAvLyBJZiB3ZSBoYXZlIHRvIHN1YnN0aXR1dGUgaW4gdGhlIGFjdHVhbCB6b25lIG5hbWUsIHdlIGhhdmUgdG8gdXNlXG4gICAgICAvLyBmb3JtYXRUb1BhcnRzIHNvIHRoYXQgdGhlIHRpbWV6b25lIGNhbiBiZSByZXBsYWNlZC5cbiAgICAgIHJldHVybiB0aGlzLmZvcm1hdFRvUGFydHMoKVxuICAgICAgICAubWFwKCh7IHZhbHVlIH0pID0+IHZhbHVlKVxuICAgICAgICAuam9pbihcIlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZHRmLmZvcm1hdCh0aGlzLmR0LnRvSlNEYXRlKCkpO1xuICB9XG5cbiAgZm9ybWF0VG9QYXJ0cygpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHRoaXMuZHRmLmZvcm1hdFRvUGFydHModGhpcy5kdC50b0pTRGF0ZSgpKTtcbiAgICBpZiAodGhpcy5vcmlnaW5hbFpvbmUpIHtcbiAgICAgIHJldHVybiBwYXJ0cy5tYXAoKHBhcnQpID0+IHtcbiAgICAgICAgaWYgKHBhcnQudHlwZSA9PT0gXCJ0aW1lWm9uZU5hbWVcIikge1xuICAgICAgICAgIGNvbnN0IG9mZnNldE5hbWUgPSB0aGlzLm9yaWdpbmFsWm9uZS5vZmZzZXROYW1lKHRoaXMuZHQudHMsIHtcbiAgICAgICAgICAgIGxvY2FsZTogdGhpcy5kdC5sb2NhbGUsXG4gICAgICAgICAgICBmb3JtYXQ6IHRoaXMub3B0cy50aW1lWm9uZU5hbWUsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnBhcnQsXG4gICAgICAgICAgICB2YWx1ZTogb2Zmc2V0TmFtZSxcbiAgICAgICAgICB9O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiBwYXJ0O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHBhcnRzO1xuICB9XG5cbiAgcmVzb2x2ZWRPcHRpb25zKCkge1xuICAgIHJldHVybiB0aGlzLmR0Zi5yZXNvbHZlZE9wdGlvbnMoKTtcbiAgfVxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbmNsYXNzIFBvbHlSZWxGb3JtYXR0ZXIge1xuICBjb25zdHJ1Y3RvcihpbnRsLCBpc0VuZ2xpc2gsIG9wdHMpIHtcbiAgICB0aGlzLm9wdHMgPSB7IHN0eWxlOiBcImxvbmdcIiwgLi4ub3B0cyB9O1xuICAgIGlmICghaXNFbmdsaXNoICYmIGhhc1JlbGF0aXZlKCkpIHtcbiAgICAgIHRoaXMucnRmID0gZ2V0Q2FjaGVkUlRGKGludGwsIG9wdHMpO1xuICAgIH1cbiAgfVxuXG4gIGZvcm1hdChjb3VudCwgdW5pdCkge1xuICAgIGlmICh0aGlzLnJ0Zikge1xuICAgICAgcmV0dXJuIHRoaXMucnRmLmZvcm1hdChjb3VudCwgdW5pdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBFbmdsaXNoLmZvcm1hdFJlbGF0aXZlVGltZSh1bml0LCBjb3VudCwgdGhpcy5vcHRzLm51bWVyaWMsIHRoaXMub3B0cy5zdHlsZSAhPT0gXCJsb25nXCIpO1xuICAgIH1cbiAgfVxuXG4gIGZvcm1hdFRvUGFydHMoY291bnQsIHVuaXQpIHtcbiAgICBpZiAodGhpcy5ydGYpIHtcbiAgICAgIHJldHVybiB0aGlzLnJ0Zi5mb3JtYXRUb1BhcnRzKGNvdW50LCB1bml0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgTG9jYWxlIHtcbiAgc3RhdGljIGZyb21PcHRzKG9wdHMpIHtcbiAgICByZXR1cm4gTG9jYWxlLmNyZWF0ZShvcHRzLmxvY2FsZSwgb3B0cy5udW1iZXJpbmdTeXN0ZW0sIG9wdHMub3V0cHV0Q2FsZW5kYXIsIG9wdHMuZGVmYXVsdFRvRU4pO1xuICB9XG5cbiAgc3RhdGljIGNyZWF0ZShsb2NhbGUsIG51bWJlcmluZ1N5c3RlbSwgb3V0cHV0Q2FsZW5kYXIsIGRlZmF1bHRUb0VOID0gZmFsc2UpIHtcbiAgICBjb25zdCBzcGVjaWZpZWRMb2NhbGUgPSBsb2NhbGUgfHwgU2V0dGluZ3MuZGVmYXVsdExvY2FsZTtcbiAgICAvLyB0aGUgc3lzdGVtIGxvY2FsZSBpcyB1c2VmdWwgZm9yIGh1bWFuIHJlYWRhYmxlIHN0cmluZ3MgYnV0IGFubm95aW5nIGZvciBwYXJzaW5nL2Zvcm1hdHRpbmcga25vd24gZm9ybWF0c1xuICAgIGNvbnN0IGxvY2FsZVIgPSBzcGVjaWZpZWRMb2NhbGUgfHwgKGRlZmF1bHRUb0VOID8gXCJlbi1VU1wiIDogc3lzdGVtTG9jYWxlKCkpO1xuICAgIGNvbnN0IG51bWJlcmluZ1N5c3RlbVIgPSBudW1iZXJpbmdTeXN0ZW0gfHwgU2V0dGluZ3MuZGVmYXVsdE51bWJlcmluZ1N5c3RlbTtcbiAgICBjb25zdCBvdXRwdXRDYWxlbmRhclIgPSBvdXRwdXRDYWxlbmRhciB8fCBTZXR0aW5ncy5kZWZhdWx0T3V0cHV0Q2FsZW5kYXI7XG4gICAgcmV0dXJuIG5ldyBMb2NhbGUobG9jYWxlUiwgbnVtYmVyaW5nU3lzdGVtUiwgb3V0cHV0Q2FsZW5kYXJSLCBzcGVjaWZpZWRMb2NhbGUpO1xuICB9XG5cbiAgc3RhdGljIHJlc2V0Q2FjaGUoKSB7XG4gICAgc3lzTG9jYWxlQ2FjaGUgPSBudWxsO1xuICAgIGludGxEVENhY2hlID0ge307XG4gICAgaW50bE51bUNhY2hlID0ge307XG4gICAgaW50bFJlbENhY2hlID0ge307XG4gIH1cblxuICBzdGF0aWMgZnJvbU9iamVjdCh7IGxvY2FsZSwgbnVtYmVyaW5nU3lzdGVtLCBvdXRwdXRDYWxlbmRhciB9ID0ge30pIHtcbiAgICByZXR1cm4gTG9jYWxlLmNyZWF0ZShsb2NhbGUsIG51bWJlcmluZ1N5c3RlbSwgb3V0cHV0Q2FsZW5kYXIpO1xuICB9XG5cbiAgY29uc3RydWN0b3IobG9jYWxlLCBudW1iZXJpbmcsIG91dHB1dENhbGVuZGFyLCBzcGVjaWZpZWRMb2NhbGUpIHtcbiAgICBjb25zdCBbcGFyc2VkTG9jYWxlLCBwYXJzZWROdW1iZXJpbmdTeXN0ZW0sIHBhcnNlZE91dHB1dENhbGVuZGFyXSA9IHBhcnNlTG9jYWxlU3RyaW5nKGxvY2FsZSk7XG5cbiAgICB0aGlzLmxvY2FsZSA9IHBhcnNlZExvY2FsZTtcbiAgICB0aGlzLm51bWJlcmluZ1N5c3RlbSA9IG51bWJlcmluZyB8fCBwYXJzZWROdW1iZXJpbmdTeXN0ZW0gfHwgbnVsbDtcbiAgICB0aGlzLm91dHB1dENhbGVuZGFyID0gb3V0cHV0Q2FsZW5kYXIgfHwgcGFyc2VkT3V0cHV0Q2FsZW5kYXIgfHwgbnVsbDtcbiAgICB0aGlzLmludGwgPSBpbnRsQ29uZmlnU3RyaW5nKHRoaXMubG9jYWxlLCB0aGlzLm51bWJlcmluZ1N5c3RlbSwgdGhpcy5vdXRwdXRDYWxlbmRhcik7XG5cbiAgICB0aGlzLndlZWtkYXlzQ2FjaGUgPSB7IGZvcm1hdDoge30sIHN0YW5kYWxvbmU6IHt9IH07XG4gICAgdGhpcy5tb250aHNDYWNoZSA9IHsgZm9ybWF0OiB7fSwgc3RhbmRhbG9uZToge30gfTtcbiAgICB0aGlzLm1lcmlkaWVtQ2FjaGUgPSBudWxsO1xuICAgIHRoaXMuZXJhQ2FjaGUgPSB7fTtcblxuICAgIHRoaXMuc3BlY2lmaWVkTG9jYWxlID0gc3BlY2lmaWVkTG9jYWxlO1xuICAgIHRoaXMuZmFzdE51bWJlcnNDYWNoZWQgPSBudWxsO1xuICB9XG5cbiAgZ2V0IGZhc3ROdW1iZXJzKCkge1xuICAgIGlmICh0aGlzLmZhc3ROdW1iZXJzQ2FjaGVkID09IG51bGwpIHtcbiAgICAgIHRoaXMuZmFzdE51bWJlcnNDYWNoZWQgPSBzdXBwb3J0c0Zhc3ROdW1iZXJzKHRoaXMpO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmZhc3ROdW1iZXJzQ2FjaGVkO1xuICB9XG5cbiAgbGlzdGluZ01vZGUoKSB7XG4gICAgY29uc3QgaXNBY3R1YWxseUVuID0gdGhpcy5pc0VuZ2xpc2goKTtcbiAgICBjb25zdCBoYXNOb1dlaXJkbmVzcyA9XG4gICAgICAodGhpcy5udW1iZXJpbmdTeXN0ZW0gPT09IG51bGwgfHwgdGhpcy5udW1iZXJpbmdTeXN0ZW0gPT09IFwibGF0blwiKSAmJlxuICAgICAgKHRoaXMub3V0cHV0Q2FsZW5kYXIgPT09IG51bGwgfHwgdGhpcy5vdXRwdXRDYWxlbmRhciA9PT0gXCJncmVnb3J5XCIpO1xuICAgIHJldHVybiBpc0FjdHVhbGx5RW4gJiYgaGFzTm9XZWlyZG5lc3MgPyBcImVuXCIgOiBcImludGxcIjtcbiAgfVxuXG4gIGNsb25lKGFsdHMpIHtcbiAgICBpZiAoIWFsdHMgfHwgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoYWx0cykubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIExvY2FsZS5jcmVhdGUoXG4gICAgICAgIGFsdHMubG9jYWxlIHx8IHRoaXMuc3BlY2lmaWVkTG9jYWxlLFxuICAgICAgICBhbHRzLm51bWJlcmluZ1N5c3RlbSB8fCB0aGlzLm51bWJlcmluZ1N5c3RlbSxcbiAgICAgICAgYWx0cy5vdXRwdXRDYWxlbmRhciB8fCB0aGlzLm91dHB1dENhbGVuZGFyLFxuICAgICAgICBhbHRzLmRlZmF1bHRUb0VOIHx8IGZhbHNlXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHJlZGVmYXVsdFRvRU4oYWx0cyA9IHt9KSB7XG4gICAgcmV0dXJuIHRoaXMuY2xvbmUoeyAuLi5hbHRzLCBkZWZhdWx0VG9FTjogdHJ1ZSB9KTtcbiAgfVxuXG4gIHJlZGVmYXVsdFRvU3lzdGVtKGFsdHMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLmNsb25lKHsgLi4uYWx0cywgZGVmYXVsdFRvRU46IGZhbHNlIH0pO1xuICB9XG5cbiAgbW9udGhzKGxlbmd0aCwgZm9ybWF0ID0gZmFsc2UsIGRlZmF1bHRPSyA9IHRydWUpIHtcbiAgICByZXR1cm4gbGlzdFN0dWZmKHRoaXMsIGxlbmd0aCwgZGVmYXVsdE9LLCBFbmdsaXNoLm1vbnRocywgKCkgPT4ge1xuICAgICAgY29uc3QgaW50bCA9IGZvcm1hdCA/IHsgbW9udGg6IGxlbmd0aCwgZGF5OiBcIm51bWVyaWNcIiB9IDogeyBtb250aDogbGVuZ3RoIH0sXG4gICAgICAgIGZvcm1hdFN0ciA9IGZvcm1hdCA/IFwiZm9ybWF0XCIgOiBcInN0YW5kYWxvbmVcIjtcbiAgICAgIGlmICghdGhpcy5tb250aHNDYWNoZVtmb3JtYXRTdHJdW2xlbmd0aF0pIHtcbiAgICAgICAgdGhpcy5tb250aHNDYWNoZVtmb3JtYXRTdHJdW2xlbmd0aF0gPSBtYXBNb250aHMoKGR0KSA9PiB0aGlzLmV4dHJhY3QoZHQsIGludGwsIFwibW9udGhcIikpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMubW9udGhzQ2FjaGVbZm9ybWF0U3RyXVtsZW5ndGhdO1xuICAgIH0pO1xuICB9XG5cbiAgd2Vla2RheXMobGVuZ3RoLCBmb3JtYXQgPSBmYWxzZSwgZGVmYXVsdE9LID0gdHJ1ZSkge1xuICAgIHJldHVybiBsaXN0U3R1ZmYodGhpcywgbGVuZ3RoLCBkZWZhdWx0T0ssIEVuZ2xpc2gud2Vla2RheXMsICgpID0+IHtcbiAgICAgIGNvbnN0IGludGwgPSBmb3JtYXRcbiAgICAgICAgICA/IHsgd2Vla2RheTogbGVuZ3RoLCB5ZWFyOiBcIm51bWVyaWNcIiwgbW9udGg6IFwibG9uZ1wiLCBkYXk6IFwibnVtZXJpY1wiIH1cbiAgICAgICAgICA6IHsgd2Vla2RheTogbGVuZ3RoIH0sXG4gICAgICAgIGZvcm1hdFN0ciA9IGZvcm1hdCA/IFwiZm9ybWF0XCIgOiBcInN0YW5kYWxvbmVcIjtcbiAgICAgIGlmICghdGhpcy53ZWVrZGF5c0NhY2hlW2Zvcm1hdFN0cl1bbGVuZ3RoXSkge1xuICAgICAgICB0aGlzLndlZWtkYXlzQ2FjaGVbZm9ybWF0U3RyXVtsZW5ndGhdID0gbWFwV2Vla2RheXMoKGR0KSA9PlxuICAgICAgICAgIHRoaXMuZXh0cmFjdChkdCwgaW50bCwgXCJ3ZWVrZGF5XCIpXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy53ZWVrZGF5c0NhY2hlW2Zvcm1hdFN0cl1bbGVuZ3RoXTtcbiAgICB9KTtcbiAgfVxuXG4gIG1lcmlkaWVtcyhkZWZhdWx0T0sgPSB0cnVlKSB7XG4gICAgcmV0dXJuIGxpc3RTdHVmZihcbiAgICAgIHRoaXMsXG4gICAgICB1bmRlZmluZWQsXG4gICAgICBkZWZhdWx0T0ssXG4gICAgICAoKSA9PiBFbmdsaXNoLm1lcmlkaWVtcyxcbiAgICAgICgpID0+IHtcbiAgICAgICAgLy8gSW4gdGhlb3J5IHRoZXJlIGNvdWxkIGJlIGFyaWJpdHJhcnkgZGF5IHBlcmlvZHMuIFdlJ3JlIGdvbm5hIGFzc3VtZSB0aGVyZSBhcmUgZXhhY3RseSB0d29cbiAgICAgICAgLy8gZm9yIEFNIGFuZCBQTS4gVGhpcyBpcyBwcm9iYWJseSB3cm9uZywgYnV0IGl0J3MgbWFrZXMgcGFyc2luZyB3YXkgZWFzaWVyLlxuICAgICAgICBpZiAoIXRoaXMubWVyaWRpZW1DYWNoZSkge1xuICAgICAgICAgIGNvbnN0IGludGwgPSB7IGhvdXI6IFwibnVtZXJpY1wiLCBob3VyQ3ljbGU6IFwiaDEyXCIgfTtcbiAgICAgICAgICB0aGlzLm1lcmlkaWVtQ2FjaGUgPSBbRGF0ZVRpbWUudXRjKDIwMTYsIDExLCAxMywgOSksIERhdGVUaW1lLnV0YygyMDE2LCAxMSwgMTMsIDE5KV0ubWFwKFxuICAgICAgICAgICAgKGR0KSA9PiB0aGlzLmV4dHJhY3QoZHQsIGludGwsIFwiZGF5cGVyaW9kXCIpXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLm1lcmlkaWVtQ2FjaGU7XG4gICAgICB9XG4gICAgKTtcbiAgfVxuXG4gIGVyYXMobGVuZ3RoLCBkZWZhdWx0T0sgPSB0cnVlKSB7XG4gICAgcmV0dXJuIGxpc3RTdHVmZih0aGlzLCBsZW5ndGgsIGRlZmF1bHRPSywgRW5nbGlzaC5lcmFzLCAoKSA9PiB7XG4gICAgICBjb25zdCBpbnRsID0geyBlcmE6IGxlbmd0aCB9O1xuXG4gICAgICAvLyBUaGlzIGlzIHByb2JsZW1hdGljLiBEaWZmZXJlbnQgY2FsZW5kYXJzIGFyZSBnb2luZyB0byBkZWZpbmUgZXJhcyB0b3RhbGx5IGRpZmZlcmVudGx5LiBXaGF0IEkgbmVlZCBpcyB0aGUgbWluaW11bSBzZXQgb2YgZGF0ZXNcbiAgICAgIC8vIHRvIGRlZmluaXRlbHkgZW51bWVyYXRlIHRoZW0uXG4gICAgICBpZiAoIXRoaXMuZXJhQ2FjaGVbbGVuZ3RoXSkge1xuICAgICAgICB0aGlzLmVyYUNhY2hlW2xlbmd0aF0gPSBbRGF0ZVRpbWUudXRjKC00MCwgMSwgMSksIERhdGVUaW1lLnV0YygyMDE3LCAxLCAxKV0ubWFwKChkdCkgPT5cbiAgICAgICAgICB0aGlzLmV4dHJhY3QoZHQsIGludGwsIFwiZXJhXCIpXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLmVyYUNhY2hlW2xlbmd0aF07XG4gICAgfSk7XG4gIH1cblxuICBleHRyYWN0KGR0LCBpbnRsT3B0cywgZmllbGQpIHtcbiAgICBjb25zdCBkZiA9IHRoaXMuZHRGb3JtYXR0ZXIoZHQsIGludGxPcHRzKSxcbiAgICAgIHJlc3VsdHMgPSBkZi5mb3JtYXRUb1BhcnRzKCksXG4gICAgICBtYXRjaGluZyA9IHJlc3VsdHMuZmluZCgobSkgPT4gbS50eXBlLnRvTG93ZXJDYXNlKCkgPT09IGZpZWxkKTtcbiAgICByZXR1cm4gbWF0Y2hpbmcgPyBtYXRjaGluZy52YWx1ZSA6IG51bGw7XG4gIH1cblxuICBudW1iZXJGb3JtYXR0ZXIob3B0cyA9IHt9KSB7XG4gICAgLy8gdGhpcyBmb3JjZXNpbXBsZSBvcHRpb24gaXMgbmV2ZXIgdXNlZCAodGhlIG9ubHkgY2FsbGVyIHNob3J0LWNpcmN1aXRzIG9uIGl0LCBidXQgaXQgc2VlbXMgc2FmZXIgdG8gbGVhdmUpXG4gICAgLy8gKGluIGNvbnRyYXN0LCB0aGUgcmVzdCBvZiB0aGUgY29uZGl0aW9uIGlzIHVzZWQgaGVhdmlseSlcbiAgICByZXR1cm4gbmV3IFBvbHlOdW1iZXJGb3JtYXR0ZXIodGhpcy5pbnRsLCBvcHRzLmZvcmNlU2ltcGxlIHx8IHRoaXMuZmFzdE51bWJlcnMsIG9wdHMpO1xuICB9XG5cbiAgZHRGb3JtYXR0ZXIoZHQsIGludGxPcHRzID0ge30pIHtcbiAgICByZXR1cm4gbmV3IFBvbHlEYXRlRm9ybWF0dGVyKGR0LCB0aGlzLmludGwsIGludGxPcHRzKTtcbiAgfVxuXG4gIHJlbEZvcm1hdHRlcihvcHRzID0ge30pIHtcbiAgICByZXR1cm4gbmV3IFBvbHlSZWxGb3JtYXR0ZXIodGhpcy5pbnRsLCB0aGlzLmlzRW5nbGlzaCgpLCBvcHRzKTtcbiAgfVxuXG4gIGxpc3RGb3JtYXR0ZXIob3B0cyA9IHt9KSB7XG4gICAgcmV0dXJuIGdldENhY2hlZExGKHRoaXMuaW50bCwgb3B0cyk7XG4gIH1cblxuICBpc0VuZ2xpc2goKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIHRoaXMubG9jYWxlID09PSBcImVuXCIgfHxcbiAgICAgIHRoaXMubG9jYWxlLnRvTG93ZXJDYXNlKCkgPT09IFwiZW4tdXNcIiB8fFxuICAgICAgbmV3IEludGwuRGF0ZVRpbWVGb3JtYXQodGhpcy5pbnRsKS5yZXNvbHZlZE9wdGlvbnMoKS5sb2NhbGUuc3RhcnRzV2l0aChcImVuLXVzXCIpXG4gICAgKTtcbiAgfVxuXG4gIGVxdWFscyhvdGhlcikge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmxvY2FsZSA9PT0gb3RoZXIubG9jYWxlICYmXG4gICAgICB0aGlzLm51bWJlcmluZ1N5c3RlbSA9PT0gb3RoZXIubnVtYmVyaW5nU3lzdGVtICYmXG4gICAgICB0aGlzLm91dHB1dENhbGVuZGFyID09PSBvdGhlci5vdXRwdXRDYWxlbmRhclxuICAgICk7XG4gIH1cbn1cbiIsICJpbXBvcnQgeyBmb3JtYXRPZmZzZXQsIHNpZ25lZE9mZnNldCB9IGZyb20gXCIuLi9pbXBsL3V0aWwuanNcIjtcbmltcG9ydCBab25lIGZyb20gXCIuLi96b25lLmpzXCI7XG5cbmxldCBzaW5nbGV0b24gPSBudWxsO1xuXG4vKipcbiAqIEEgem9uZSB3aXRoIGEgZml4ZWQgb2Zmc2V0IChtZWFuaW5nIG5vIERTVClcbiAqIEBpbXBsZW1lbnRzIHtab25lfVxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBGaXhlZE9mZnNldFpvbmUgZXh0ZW5kcyBab25lIHtcbiAgLyoqXG4gICAqIEdldCBhIHNpbmdsZXRvbiBpbnN0YW5jZSBvZiBVVENcbiAgICogQHJldHVybiB7Rml4ZWRPZmZzZXRab25lfVxuICAgKi9cbiAgc3RhdGljIGdldCB1dGNJbnN0YW5jZSgpIHtcbiAgICBpZiAoc2luZ2xldG9uID09PSBudWxsKSB7XG4gICAgICBzaW5nbGV0b24gPSBuZXcgRml4ZWRPZmZzZXRab25lKDApO1xuICAgIH1cbiAgICByZXR1cm4gc2luZ2xldG9uO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbiBpbnN0YW5jZSB3aXRoIGEgc3BlY2lmaWVkIG9mZnNldFxuICAgKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IC0gVGhlIG9mZnNldCBpbiBtaW51dGVzXG4gICAqIEByZXR1cm4ge0ZpeGVkT2Zmc2V0Wm9uZX1cbiAgICovXG4gIHN0YXRpYyBpbnN0YW5jZShvZmZzZXQpIHtcbiAgICByZXR1cm4gb2Zmc2V0ID09PSAwID8gRml4ZWRPZmZzZXRab25lLnV0Y0luc3RhbmNlIDogbmV3IEZpeGVkT2Zmc2V0Wm9uZShvZmZzZXQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhbiBpbnN0YW5jZSBvZiBGaXhlZE9mZnNldFpvbmUgZnJvbSBhIFVUQyBvZmZzZXQgc3RyaW5nLCBsaWtlIFwiVVRDKzZcIlxuICAgKiBAcGFyYW0ge3N0cmluZ30gcyAtIFRoZSBvZmZzZXQgc3RyaW5nIHRvIHBhcnNlXG4gICAqIEBleGFtcGxlIEZpeGVkT2Zmc2V0Wm9uZS5wYXJzZVNwZWNpZmllcihcIlVUQys2XCIpXG4gICAqIEBleGFtcGxlIEZpeGVkT2Zmc2V0Wm9uZS5wYXJzZVNwZWNpZmllcihcIlVUQyswNlwiKVxuICAgKiBAZXhhbXBsZSBGaXhlZE9mZnNldFpvbmUucGFyc2VTcGVjaWZpZXIoXCJVVEMtNjowMFwiKVxuICAgKiBAcmV0dXJuIHtGaXhlZE9mZnNldFpvbmV9XG4gICAqL1xuICBzdGF0aWMgcGFyc2VTcGVjaWZpZXIocykge1xuICAgIGlmIChzKSB7XG4gICAgICBjb25zdCByID0gcy5tYXRjaCgvXnV0Yyg/OihbKy1dXFxkezEsMn0pKD86OihcXGR7Mn0pKT8pPyQvaSk7XG4gICAgICBpZiAocikge1xuICAgICAgICByZXR1cm4gbmV3IEZpeGVkT2Zmc2V0Wm9uZShzaWduZWRPZmZzZXQoclsxXSwgclsyXSkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKG9mZnNldCkge1xuICAgIHN1cGVyKCk7XG4gICAgLyoqIEBwcml2YXRlICoqL1xuICAgIHRoaXMuZml4ZWQgPSBvZmZzZXQ7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBnZXQgdHlwZSgpIHtcbiAgICByZXR1cm4gXCJmaXhlZFwiO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgZ2V0IG5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMuZml4ZWQgPT09IDAgPyBcIlVUQ1wiIDogYFVUQyR7Zm9ybWF0T2Zmc2V0KHRoaXMuZml4ZWQsIFwibmFycm93XCIpfWA7XG4gIH1cblxuICBnZXQgaWFuYU5hbWUoKSB7XG4gICAgaWYgKHRoaXMuZml4ZWQgPT09IDApIHtcbiAgICAgIHJldHVybiBcIkV0Yy9VVENcIjtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIGBFdGMvR01UJHtmb3JtYXRPZmZzZXQoLXRoaXMuZml4ZWQsIFwibmFycm93XCIpfWA7XG4gICAgfVxuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgb2Zmc2V0TmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5uYW1lO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgZm9ybWF0T2Zmc2V0KHRzLCBmb3JtYXQpIHtcbiAgICByZXR1cm4gZm9ybWF0T2Zmc2V0KHRoaXMuZml4ZWQsIGZvcm1hdCk7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBnZXQgaXNVbml2ZXJzYWwoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBvZmZzZXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuZml4ZWQ7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBlcXVhbHMob3RoZXJab25lKSB7XG4gICAgcmV0dXJuIG90aGVyWm9uZS50eXBlID09PSBcImZpeGVkXCIgJiYgb3RoZXJab25lLmZpeGVkID09PSB0aGlzLmZpeGVkO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgZ2V0IGlzVmFsaWQoKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn1cbiIsICJpbXBvcnQgWm9uZSBmcm9tIFwiLi4vem9uZS5qc1wiO1xuXG4vKipcbiAqIEEgem9uZSB0aGF0IGZhaWxlZCB0byBwYXJzZS4gWW91IHNob3VsZCBuZXZlciBuZWVkIHRvIGluc3RhbnRpYXRlIHRoaXMuXG4gKiBAaW1wbGVtZW50cyB7Wm9uZX1cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgSW52YWxpZFpvbmUgZXh0ZW5kcyBab25lIHtcbiAgY29uc3RydWN0b3Ioem9uZU5hbWUpIHtcbiAgICBzdXBlcigpO1xuICAgIC8qKiAgQHByaXZhdGUgKi9cbiAgICB0aGlzLnpvbmVOYW1lID0gem9uZU5hbWU7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBnZXQgdHlwZSgpIHtcbiAgICByZXR1cm4gXCJpbnZhbGlkXCI7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBnZXQgbmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy56b25lTmFtZTtcbiAgfVxuXG4gIC8qKiBAb3ZlcnJpZGUgKiovXG4gIGdldCBpc1VuaXZlcnNhbCgpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBvZmZzZXROYW1lKCkge1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgZm9ybWF0T2Zmc2V0KCkge1xuICAgIHJldHVybiBcIlwiO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgb2Zmc2V0KCkge1xuICAgIHJldHVybiBOYU47XG4gIH1cblxuICAvKiogQG92ZXJyaWRlICoqL1xuICBlcXVhbHMoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgLyoqIEBvdmVycmlkZSAqKi9cbiAgZ2V0IGlzVmFsaWQoKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG59XG4iLCAiLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5cbmltcG9ydCBab25lIGZyb20gXCIuLi96b25lLmpzXCI7XG5pbXBvcnQgSUFOQVpvbmUgZnJvbSBcIi4uL3pvbmVzL0lBTkFab25lLmpzXCI7XG5pbXBvcnQgRml4ZWRPZmZzZXRab25lIGZyb20gXCIuLi96b25lcy9maXhlZE9mZnNldFpvbmUuanNcIjtcbmltcG9ydCBJbnZhbGlkWm9uZSBmcm9tIFwiLi4vem9uZXMvaW52YWxpZFpvbmUuanNcIjtcblxuaW1wb3J0IHsgaXNVbmRlZmluZWQsIGlzU3RyaW5nLCBpc051bWJlciB9IGZyb20gXCIuL3V0aWwuanNcIjtcbmltcG9ydCBTeXN0ZW1ab25lIGZyb20gXCIuLi96b25lcy9zeXN0ZW1ab25lLmpzXCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBub3JtYWxpemVab25lKGlucHV0LCBkZWZhdWx0Wm9uZSkge1xuICBsZXQgb2Zmc2V0O1xuICBpZiAoaXNVbmRlZmluZWQoaW5wdXQpIHx8IGlucHV0ID09PSBudWxsKSB7XG4gICAgcmV0dXJuIGRlZmF1bHRab25lO1xuICB9IGVsc2UgaWYgKGlucHV0IGluc3RhbmNlb2YgWm9uZSkge1xuICAgIHJldHVybiBpbnB1dDtcbiAgfSBlbHNlIGlmIChpc1N0cmluZyhpbnB1dCkpIHtcbiAgICBjb25zdCBsb3dlcmVkID0gaW5wdXQudG9Mb3dlckNhc2UoKTtcbiAgICBpZiAobG93ZXJlZCA9PT0gXCJkZWZhdWx0XCIpIHJldHVybiBkZWZhdWx0Wm9uZTtcbiAgICBlbHNlIGlmIChsb3dlcmVkID09PSBcImxvY2FsXCIgfHwgbG93ZXJlZCA9PT0gXCJzeXN0ZW1cIikgcmV0dXJuIFN5c3RlbVpvbmUuaW5zdGFuY2U7XG4gICAgZWxzZSBpZiAobG93ZXJlZCA9PT0gXCJ1dGNcIiB8fCBsb3dlcmVkID09PSBcImdtdFwiKSByZXR1cm4gRml4ZWRPZmZzZXRab25lLnV0Y0luc3RhbmNlO1xuICAgIGVsc2UgcmV0dXJuIEZpeGVkT2Zmc2V0Wm9uZS5wYXJzZVNwZWNpZmllcihsb3dlcmVkKSB8fCBJQU5BWm9uZS5jcmVhdGUoaW5wdXQpO1xuICB9IGVsc2UgaWYgKGlzTnVtYmVyKGlucHV0KSkge1xuICAgIHJldHVybiBGaXhlZE9mZnNldFpvbmUuaW5zdGFuY2UoaW5wdXQpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBpbnB1dCA9PT0gXCJvYmplY3RcIiAmJiBpbnB1dC5vZmZzZXQgJiYgdHlwZW9mIGlucHV0Lm9mZnNldCA9PT0gXCJudW1iZXJcIikge1xuICAgIC8vIFRoaXMgaXMgZHVtYiwgYnV0IHRoZSBpbnN0YW5jZW9mIGNoZWNrIGFib3ZlIGRvZXNuJ3Qgc2VlbSB0byByZWFsbHkgd29ya1xuICAgIC8vIHNvIHdlJ3JlIGR1Y2sgY2hlY2tpbmcgaXRcbiAgICByZXR1cm4gaW5wdXQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG5ldyBJbnZhbGlkWm9uZShpbnB1dCk7XG4gIH1cbn1cbiIsICJpbXBvcnQgU3lzdGVtWm9uZSBmcm9tIFwiLi96b25lcy9zeXN0ZW1ab25lLmpzXCI7XG5pbXBvcnQgSUFOQVpvbmUgZnJvbSBcIi4vem9uZXMvSUFOQVpvbmUuanNcIjtcbmltcG9ydCBMb2NhbGUgZnJvbSBcIi4vaW1wbC9sb2NhbGUuanNcIjtcblxuaW1wb3J0IHsgbm9ybWFsaXplWm9uZSB9IGZyb20gXCIuL2ltcGwvem9uZVV0aWwuanNcIjtcblxubGV0IG5vdyA9ICgpID0+IERhdGUubm93KCksXG4gIGRlZmF1bHRab25lID0gXCJzeXN0ZW1cIixcbiAgZGVmYXVsdExvY2FsZSA9IG51bGwsXG4gIGRlZmF1bHROdW1iZXJpbmdTeXN0ZW0gPSBudWxsLFxuICBkZWZhdWx0T3V0cHV0Q2FsZW5kYXIgPSBudWxsLFxuICB0d29EaWdpdEN1dG9mZlllYXIgPSA2MCxcbiAgdGhyb3dPbkludmFsaWQ7XG5cbi8qKlxuICogU2V0dGluZ3MgY29udGFpbnMgc3RhdGljIGdldHRlcnMgYW5kIHNldHRlcnMgdGhhdCBjb250cm9sIEx1eG9uJ3Mgb3ZlcmFsbCBiZWhhdmlvci4gTHV4b24gaXMgYSBzaW1wbGUgbGlicmFyeSB3aXRoIGZldyBvcHRpb25zLCBidXQgdGhlIG9uZXMgaXQgZG9lcyBoYXZlIGxpdmUgaGVyZS5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgY2xhc3MgU2V0dGluZ3Mge1xuICAvKipcbiAgICogR2V0IHRoZSBjYWxsYmFjayBmb3IgcmV0dXJuaW5nIHRoZSBjdXJyZW50IHRpbWVzdGFtcC5cbiAgICogQHR5cGUge2Z1bmN0aW9ufVxuICAgKi9cbiAgc3RhdGljIGdldCBub3coKSB7XG4gICAgcmV0dXJuIG5vdztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGNhbGxiYWNrIGZvciByZXR1cm5pbmcgdGhlIGN1cnJlbnQgdGltZXN0YW1wLlxuICAgKiBUaGUgZnVuY3Rpb24gc2hvdWxkIHJldHVybiBhIG51bWJlciwgd2hpY2ggd2lsbCBiZSBpbnRlcnByZXRlZCBhcyBhbiBFcG9jaCBtaWxsaXNlY29uZCBjb3VudFxuICAgKiBAdHlwZSB7ZnVuY3Rpb259XG4gICAqIEBleGFtcGxlIFNldHRpbmdzLm5vdyA9ICgpID0+IERhdGUubm93KCkgKyAzMDAwIC8vIHByZXRlbmQgaXQgaXMgMyBzZWNvbmRzIGluIHRoZSBmdXR1cmVcbiAgICogQGV4YW1wbGUgU2V0dGluZ3Mubm93ID0gKCkgPT4gMCAvLyBhbHdheXMgcHJldGVuZCBpdCdzIEphbiAxLCAxOTcwIGF0IG1pZG5pZ2h0IGluIFVUQyB0aW1lXG4gICAqL1xuICBzdGF0aWMgc2V0IG5vdyhuKSB7XG4gICAgbm93ID0gbjtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdGhlIGRlZmF1bHQgdGltZSB6b25lIHRvIGNyZWF0ZSBEYXRlVGltZXMgaW4uIERvZXMgbm90IGFmZmVjdCBleGlzdGluZyBpbnN0YW5jZXMuXG4gICAqIFVzZSB0aGUgdmFsdWUgXCJzeXN0ZW1cIiB0byByZXNldCB0aGlzIHZhbHVlIHRvIHRoZSBzeXN0ZW0ncyB0aW1lIHpvbmUuXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBzdGF0aWMgc2V0IGRlZmF1bHRab25lKHpvbmUpIHtcbiAgICBkZWZhdWx0Wm9uZSA9IHpvbmU7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBkZWZhdWx0IHRpbWUgem9uZSBvYmplY3QgY3VycmVudGx5IHVzZWQgdG8gY3JlYXRlIERhdGVUaW1lcy4gRG9lcyBub3QgYWZmZWN0IGV4aXN0aW5nIGluc3RhbmNlcy5cbiAgICogVGhlIGRlZmF1bHQgdmFsdWUgaXMgdGhlIHN5c3RlbSdzIHRpbWUgem9uZSAodGhlIG9uZSBzZXQgb24gdGhlIG1hY2hpbmUgdGhhdCBydW5zIHRoaXMgY29kZSkuXG4gICAqIEB0eXBlIHtab25lfVxuICAgKi9cbiAgc3RhdGljIGdldCBkZWZhdWx0Wm9uZSgpIHtcbiAgICByZXR1cm4gbm9ybWFsaXplWm9uZShkZWZhdWx0Wm9uZSwgU3lzdGVtWm9uZS5pbnN0YW5jZSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBkZWZhdWx0IGxvY2FsZSB0byBjcmVhdGUgRGF0ZVRpbWVzIHdpdGguIERvZXMgbm90IGFmZmVjdCBleGlzdGluZyBpbnN0YW5jZXMuXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBzdGF0aWMgZ2V0IGRlZmF1bHRMb2NhbGUoKSB7XG4gICAgcmV0dXJuIGRlZmF1bHRMb2NhbGU7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBkZWZhdWx0IGxvY2FsZSB0byBjcmVhdGUgRGF0ZVRpbWVzIHdpdGguIERvZXMgbm90IGFmZmVjdCBleGlzdGluZyBpbnN0YW5jZXMuXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBzdGF0aWMgc2V0IGRlZmF1bHRMb2NhbGUobG9jYWxlKSB7XG4gICAgZGVmYXVsdExvY2FsZSA9IGxvY2FsZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRlZmF1bHQgbnVtYmVyaW5nIHN5c3RlbSB0byBjcmVhdGUgRGF0ZVRpbWVzIHdpdGguIERvZXMgbm90IGFmZmVjdCBleGlzdGluZyBpbnN0YW5jZXMuXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBzdGF0aWMgZ2V0IGRlZmF1bHROdW1iZXJpbmdTeXN0ZW0oKSB7XG4gICAgcmV0dXJuIGRlZmF1bHROdW1iZXJpbmdTeXN0ZW07XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRoZSBkZWZhdWx0IG51bWJlcmluZyBzeXN0ZW0gdG8gY3JlYXRlIERhdGVUaW1lcyB3aXRoLiBEb2VzIG5vdCBhZmZlY3QgZXhpc3RpbmcgaW5zdGFuY2VzLlxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKi9cbiAgc3RhdGljIHNldCBkZWZhdWx0TnVtYmVyaW5nU3lzdGVtKG51bWJlcmluZ1N5c3RlbSkge1xuICAgIGRlZmF1bHROdW1iZXJpbmdTeXN0ZW0gPSBudW1iZXJpbmdTeXN0ZW07XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBkZWZhdWx0IG91dHB1dCBjYWxlbmRhciB0byBjcmVhdGUgRGF0ZVRpbWVzIHdpdGguIERvZXMgbm90IGFmZmVjdCBleGlzdGluZyBpbnN0YW5jZXMuXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBzdGF0aWMgZ2V0IGRlZmF1bHRPdXRwdXRDYWxlbmRhcigpIHtcbiAgICByZXR1cm4gZGVmYXVsdE91dHB1dENhbGVuZGFyO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgZGVmYXVsdCBvdXRwdXQgY2FsZW5kYXIgdG8gY3JlYXRlIERhdGVUaW1lcyB3aXRoLiBEb2VzIG5vdCBhZmZlY3QgZXhpc3RpbmcgaW5zdGFuY2VzLlxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKi9cbiAgc3RhdGljIHNldCBkZWZhdWx0T3V0cHV0Q2FsZW5kYXIob3V0cHV0Q2FsZW5kYXIpIHtcbiAgICBkZWZhdWx0T3V0cHV0Q2FsZW5kYXIgPSBvdXRwdXRDYWxlbmRhcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGN1dG9mZiB5ZWFyIGFmdGVyIHdoaWNoIGEgc3RyaW5nIGVuY29kaW5nIGEgeWVhciBhcyB0d28gZGlnaXRzIGlzIGludGVycHJldGVkIHRvIG9jY3VyIGluIHRoZSBjdXJyZW50IGNlbnR1cnkuXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBzdGF0aWMgZ2V0IHR3b0RpZ2l0Q3V0b2ZmWWVhcigpIHtcbiAgICByZXR1cm4gdHdvRGlnaXRDdXRvZmZZZWFyO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgY3V0b2ZmIHllYXIgYWZ0ZXIgd2hpY2ggYSBzdHJpbmcgZW5jb2RpbmcgYSB5ZWFyIGFzIHR3byBkaWdpdHMgaXMgaW50ZXJwcmV0ZWQgdG8gb2NjdXIgaW4gdGhlIGN1cnJlbnQgY2VudHVyeS5cbiAgICogQHR5cGUge251bWJlcn1cbiAgICogQGV4YW1wbGUgU2V0dGluZ3MudHdvRGlnaXRDdXRvZmZZZWFyID0gMCAvLyBjdXQtb2ZmIHllYXIgaXMgMCwgc28gYWxsICd5eScgYXJlIGludGVycHJldHRlZCBhcyBjdXJyZW50IGNlbnR1cnlcbiAgICogQGV4YW1wbGUgU2V0dGluZ3MudHdvRGlnaXRDdXRvZmZZZWFyID0gNTAgLy8gJzQ5JyAtPiAxOTQ5OyAnNTAnIC0+IDIwNTBcbiAgICogQGV4YW1wbGUgU2V0dGluZ3MudHdvRGlnaXRDdXRvZmZZZWFyID0gMTk1MCAvLyBpbnRlcnByZXR0ZWQgYXMgNTBcbiAgICogQGV4YW1wbGUgU2V0dGluZ3MudHdvRGlnaXRDdXRvZmZZZWFyID0gMjA1MCAvLyBBTFNPIGludGVycHJldHRlZCBhcyA1MFxuICAgKi9cbiAgc3RhdGljIHNldCB0d29EaWdpdEN1dG9mZlllYXIoY3V0b2ZmWWVhcikge1xuICAgIHR3b0RpZ2l0Q3V0b2ZmWWVhciA9IGN1dG9mZlllYXIgJSAxMDA7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHdoZXRoZXIgTHV4b24gd2lsbCB0aHJvdyB3aGVuIGl0IGVuY291bnRlcnMgaW52YWxpZCBEYXRlVGltZXMsIER1cmF0aW9ucywgb3IgSW50ZXJ2YWxzXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKi9cbiAgc3RhdGljIGdldCB0aHJvd09uSW52YWxpZCgpIHtcbiAgICByZXR1cm4gdGhyb3dPbkludmFsaWQ7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHdoZXRoZXIgTHV4b24gd2lsbCB0aHJvdyB3aGVuIGl0IGVuY291bnRlcnMgaW52YWxpZCBEYXRlVGltZXMsIER1cmF0aW9ucywgb3IgSW50ZXJ2YWxzXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKi9cbiAgc3RhdGljIHNldCB0aHJvd09uSW52YWxpZCh0KSB7XG4gICAgdGhyb3dPbkludmFsaWQgPSB0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IEx1eG9uJ3MgZ2xvYmFsIGNhY2hlcy4gU2hvdWxkIG9ubHkgYmUgbmVjZXNzYXJ5IGluIHRlc3Rpbmcgc2NlbmFyaW9zLlxuICAgKiBAcmV0dXJuIHt2b2lkfVxuICAgKi9cbiAgc3RhdGljIHJlc2V0Q2FjaGVzKCkge1xuICAgIExvY2FsZS5yZXNldENhY2hlKCk7XG4gICAgSUFOQVpvbmUucmVzZXRDYWNoZSgpO1xuICB9XG59XG4iLCAiLypcbiAgVGhpcyBpcyBqdXN0IGEganVuayBkcmF3ZXIsIGNvbnRhaW5pbmcgYW55dGhpbmcgdXNlZCBhY3Jvc3MgbXVsdGlwbGUgY2xhc3Nlcy5cbiAgQmVjYXVzZSBMdXhvbiBpcyBzbWFsbChpc2gpLCB0aGlzIHNob3VsZCBzdGF5IHNtYWxsIGFuZCB3ZSB3b24ndCB3b3JyeSBhYm91dCBzcGxpdHRpbmdcbiAgaXQgdXAgaW50bywgc2F5LCBwYXJzaW5nVXRpbC5qcyBhbmQgYmFzaWNVdGlsLmpzIGFuZCBzbyBvbi4gQnV0IHRoZXkgYXJlIGRpdmlkZWQgdXAgYnkgZmVhdHVyZSBhcmVhLlxuKi9cblxuaW1wb3J0IHsgSW52YWxpZEFyZ3VtZW50RXJyb3IgfSBmcm9tIFwiLi4vZXJyb3JzLmpzXCI7XG5pbXBvcnQgU2V0dGluZ3MgZnJvbSBcIi4uL3NldHRpbmdzLmpzXCI7XG5cbi8qKlxuICogQHByaXZhdGVcbiAqL1xuXG4vLyBUWVBFU1xuXG5leHBvcnQgZnVuY3Rpb24gaXNVbmRlZmluZWQobykge1xuICByZXR1cm4gdHlwZW9mIG8gPT09IFwidW5kZWZpbmVkXCI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc051bWJlcihvKSB7XG4gIHJldHVybiB0eXBlb2YgbyA9PT0gXCJudW1iZXJcIjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzSW50ZWdlcihvKSB7XG4gIHJldHVybiB0eXBlb2YgbyA9PT0gXCJudW1iZXJcIiAmJiBvICUgMSA9PT0gMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGlzU3RyaW5nKG8pIHtcbiAgcmV0dXJuIHR5cGVvZiBvID09PSBcInN0cmluZ1wiO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaXNEYXRlKG8pIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvKSA9PT0gXCJbb2JqZWN0IERhdGVdXCI7XG59XG5cbi8vIENBUEFCSUxJVElFU1xuXG5leHBvcnQgZnVuY3Rpb24gaGFzUmVsYXRpdmUoKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHR5cGVvZiBJbnRsICE9PSBcInVuZGVmaW5lZFwiICYmICEhSW50bC5SZWxhdGl2ZVRpbWVGb3JtYXQ7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbn1cblxuLy8gT0JKRUNUUyBBTkQgQVJSQVlTXG5cbmV4cG9ydCBmdW5jdGlvbiBtYXliZUFycmF5KHRoaW5nKSB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHRoaW5nKSA/IHRoaW5nIDogW3RoaW5nXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGJlc3RCeShhcnIsIGJ5LCBjb21wYXJlKSB7XG4gIGlmIChhcnIubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuICByZXR1cm4gYXJyLnJlZHVjZSgoYmVzdCwgbmV4dCkgPT4ge1xuICAgIGNvbnN0IHBhaXIgPSBbYnkobmV4dCksIG5leHRdO1xuICAgIGlmICghYmVzdCkge1xuICAgICAgcmV0dXJuIHBhaXI7XG4gICAgfSBlbHNlIGlmIChjb21wYXJlKGJlc3RbMF0sIHBhaXJbMF0pID09PSBiZXN0WzBdKSB7XG4gICAgICByZXR1cm4gYmVzdDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHBhaXI7XG4gICAgfVxuICB9LCBudWxsKVsxXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBpY2sob2JqLCBrZXlzKSB7XG4gIHJldHVybiBrZXlzLnJlZHVjZSgoYSwgaykgPT4ge1xuICAgIGFba10gPSBvYmpba107XG4gICAgcmV0dXJuIGE7XG4gIH0sIHt9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhc093blByb3BlcnR5KG9iaiwgcHJvcCkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iaiwgcHJvcCk7XG59XG5cbi8vIE5VTUJFUlMgQU5EIFNUUklOR1NcblxuZXhwb3J0IGZ1bmN0aW9uIGludGVnZXJCZXR3ZWVuKHRoaW5nLCBib3R0b20sIHRvcCkge1xuICByZXR1cm4gaXNJbnRlZ2VyKHRoaW5nKSAmJiB0aGluZyA+PSBib3R0b20gJiYgdGhpbmcgPD0gdG9wO1xufVxuXG4vLyB4ICUgbiBidXQgdGFrZXMgdGhlIHNpZ24gb2YgbiBpbnN0ZWFkIG9mIHhcbmV4cG9ydCBmdW5jdGlvbiBmbG9vck1vZCh4LCBuKSB7XG4gIHJldHVybiB4IC0gbiAqIE1hdGguZmxvb3IoeCAvIG4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFkU3RhcnQoaW5wdXQsIG4gPSAyKSB7XG4gIGNvbnN0IGlzTmVnID0gaW5wdXQgPCAwO1xuICBsZXQgcGFkZGVkO1xuICBpZiAoaXNOZWcpIHtcbiAgICBwYWRkZWQgPSBcIi1cIiArIChcIlwiICsgLWlucHV0KS5wYWRTdGFydChuLCBcIjBcIik7XG4gIH0gZWxzZSB7XG4gICAgcGFkZGVkID0gKFwiXCIgKyBpbnB1dCkucGFkU3RhcnQobiwgXCIwXCIpO1xuICB9XG4gIHJldHVybiBwYWRkZWQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUludGVnZXIoc3RyaW5nKSB7XG4gIGlmIChpc1VuZGVmaW5lZChzdHJpbmcpIHx8IHN0cmluZyA9PT0gbnVsbCB8fCBzdHJpbmcgPT09IFwiXCIpIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBwYXJzZUludChzdHJpbmcsIDEwKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VGbG9hdGluZyhzdHJpbmcpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKHN0cmluZykgfHwgc3RyaW5nID09PSBudWxsIHx8IHN0cmluZyA9PT0gXCJcIikge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHBhcnNlRmxvYXQoc3RyaW5nKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VNaWxsaXMoZnJhY3Rpb24pIHtcbiAgLy8gUmV0dXJuIHVuZGVmaW5lZCAoaW5zdGVhZCBvZiAwKSBpbiB0aGVzZSBjYXNlcywgd2hlcmUgZnJhY3Rpb24gaXMgbm90IHNldFxuICBpZiAoaXNVbmRlZmluZWQoZnJhY3Rpb24pIHx8IGZyYWN0aW9uID09PSBudWxsIHx8IGZyYWN0aW9uID09PSBcIlwiKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBmID0gcGFyc2VGbG9hdChcIjAuXCIgKyBmcmFjdGlvbikgKiAxMDAwO1xuICAgIHJldHVybiBNYXRoLmZsb29yKGYpO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByb3VuZFRvKG51bWJlciwgZGlnaXRzLCB0b3dhcmRaZXJvID0gZmFsc2UpIHtcbiAgY29uc3QgZmFjdG9yID0gMTAgKiogZGlnaXRzLFxuICAgIHJvdW5kZXIgPSB0b3dhcmRaZXJvID8gTWF0aC50cnVuYyA6IE1hdGgucm91bmQ7XG4gIHJldHVybiByb3VuZGVyKG51bWJlciAqIGZhY3RvcikgLyBmYWN0b3I7XG59XG5cbi8vIERBVEUgQkFTSUNTXG5cbmV4cG9ydCBmdW5jdGlvbiBpc0xlYXBZZWFyKHllYXIpIHtcbiAgcmV0dXJuIHllYXIgJSA0ID09PSAwICYmICh5ZWFyICUgMTAwICE9PSAwIHx8IHllYXIgJSA0MDAgPT09IDApO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGF5c0luWWVhcih5ZWFyKSB7XG4gIHJldHVybiBpc0xlYXBZZWFyKHllYXIpID8gMzY2IDogMzY1O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGF5c0luTW9udGgoeWVhciwgbW9udGgpIHtcbiAgY29uc3QgbW9kTW9udGggPSBmbG9vck1vZChtb250aCAtIDEsIDEyKSArIDEsXG4gICAgbW9kWWVhciA9IHllYXIgKyAobW9udGggLSBtb2RNb250aCkgLyAxMjtcblxuICBpZiAobW9kTW9udGggPT09IDIpIHtcbiAgICByZXR1cm4gaXNMZWFwWWVhcihtb2RZZWFyKSA/IDI5IDogMjg7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIFszMSwgbnVsbCwgMzEsIDMwLCAzMSwgMzAsIDMxLCAzMSwgMzAsIDMxLCAzMCwgMzFdW21vZE1vbnRoIC0gMV07XG4gIH1cbn1cblxuLy8gY292ZXJ0IGEgY2FsZW5kYXIgb2JqZWN0IHRvIGEgbG9jYWwgdGltZXN0YW1wIChlcG9jaCwgYnV0IHdpdGggdGhlIG9mZnNldCBiYWtlZCBpbilcbmV4cG9ydCBmdW5jdGlvbiBvYmpUb0xvY2FsVFMob2JqKSB7XG4gIGxldCBkID0gRGF0ZS5VVEMoXG4gICAgb2JqLnllYXIsXG4gICAgb2JqLm1vbnRoIC0gMSxcbiAgICBvYmouZGF5LFxuICAgIG9iai5ob3VyLFxuICAgIG9iai5taW51dGUsXG4gICAgb2JqLnNlY29uZCxcbiAgICBvYmoubWlsbGlzZWNvbmRcbiAgKTtcblxuICAvLyBmb3IgbGVnYWN5IHJlYXNvbnMsIHllYXJzIGJldHdlZW4gMCBhbmQgOTkgYXJlIGludGVycHJldGVkIGFzIDE5WFg7IHJldmVydCB0aGF0XG4gIGlmIChvYmoueWVhciA8IDEwMCAmJiBvYmoueWVhciA+PSAwKSB7XG4gICAgZCA9IG5ldyBEYXRlKGQpO1xuICAgIC8vIHNldCB0aGUgbW9udGggYW5kIGRheSBhZ2FpbiwgdGhpcyBpcyBuZWNlc3NhcnkgYmVjYXVzZSB5ZWFyIDIwMDAgaXMgYSBsZWFwIHllYXIsIGJ1dCB5ZWFyIDEwMCBpcyBub3RcbiAgICAvLyBzbyBpZiBvYmoueWVhciBpcyBpbiA5OSwgYnV0IG9iai5kYXkgbWFrZXMgaXQgcm9sbCBvdmVyIGludG8geWVhciAxMDAsXG4gICAgLy8gdGhlIGNhbGN1bGF0aW9ucyBkb25lIGJ5IERhdGUuVVRDIGFyZSB1c2luZyB5ZWFyIDIwMDAgLSB3aGljaCBpcyBpbmNvcnJlY3RcbiAgICBkLnNldFVUQ0Z1bGxZZWFyKG9iai55ZWFyLCBvYmoubW9udGggLSAxLCBvYmouZGF5KTtcbiAgfVxuICByZXR1cm4gK2Q7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3ZWVrc0luV2Vla1llYXIod2Vla1llYXIpIHtcbiAgY29uc3QgcDEgPVxuICAgICAgKHdlZWtZZWFyICtcbiAgICAgICAgTWF0aC5mbG9vcih3ZWVrWWVhciAvIDQpIC1cbiAgICAgICAgTWF0aC5mbG9vcih3ZWVrWWVhciAvIDEwMCkgK1xuICAgICAgICBNYXRoLmZsb29yKHdlZWtZZWFyIC8gNDAwKSkgJVxuICAgICAgNyxcbiAgICBsYXN0ID0gd2Vla1llYXIgLSAxLFxuICAgIHAyID0gKGxhc3QgKyBNYXRoLmZsb29yKGxhc3QgLyA0KSAtIE1hdGguZmxvb3IobGFzdCAvIDEwMCkgKyBNYXRoLmZsb29yKGxhc3QgLyA0MDApKSAlIDc7XG4gIHJldHVybiBwMSA9PT0gNCB8fCBwMiA9PT0gMyA/IDUzIDogNTI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1bnRydW5jYXRlWWVhcih5ZWFyKSB7XG4gIGlmICh5ZWFyID4gOTkpIHtcbiAgICByZXR1cm4geWVhcjtcbiAgfSBlbHNlIHJldHVybiB5ZWFyID4gU2V0dGluZ3MudHdvRGlnaXRDdXRvZmZZZWFyID8gMTkwMCArIHllYXIgOiAyMDAwICsgeWVhcjtcbn1cblxuLy8gUEFSU0lOR1xuXG5leHBvcnQgZnVuY3Rpb24gcGFyc2Vab25lSW5mbyh0cywgb2Zmc2V0Rm9ybWF0LCBsb2NhbGUsIHRpbWVab25lID0gbnVsbCkge1xuICBjb25zdCBkYXRlID0gbmV3IERhdGUodHMpLFxuICAgIGludGxPcHRzID0ge1xuICAgICAgaG91ckN5Y2xlOiBcImgyM1wiLFxuICAgICAgeWVhcjogXCJudW1lcmljXCIsXG4gICAgICBtb250aDogXCIyLWRpZ2l0XCIsXG4gICAgICBkYXk6IFwiMi1kaWdpdFwiLFxuICAgICAgaG91cjogXCIyLWRpZ2l0XCIsXG4gICAgICBtaW51dGU6IFwiMi1kaWdpdFwiLFxuICAgIH07XG5cbiAgaWYgKHRpbWVab25lKSB7XG4gICAgaW50bE9wdHMudGltZVpvbmUgPSB0aW1lWm9uZTtcbiAgfVxuXG4gIGNvbnN0IG1vZGlmaWVkID0geyB0aW1lWm9uZU5hbWU6IG9mZnNldEZvcm1hdCwgLi4uaW50bE9wdHMgfTtcblxuICBjb25zdCBwYXJzZWQgPSBuZXcgSW50bC5EYXRlVGltZUZvcm1hdChsb2NhbGUsIG1vZGlmaWVkKVxuICAgIC5mb3JtYXRUb1BhcnRzKGRhdGUpXG4gICAgLmZpbmQoKG0pID0+IG0udHlwZS50b0xvd2VyQ2FzZSgpID09PSBcInRpbWV6b25lbmFtZVwiKTtcbiAgcmV0dXJuIHBhcnNlZCA/IHBhcnNlZC52YWx1ZSA6IG51bGw7XG59XG5cbi8vIHNpZ25lZE9mZnNldCgnLTUnLCAnMzAnKSAtPiAtMzMwXG5leHBvcnQgZnVuY3Rpb24gc2lnbmVkT2Zmc2V0KG9mZkhvdXJTdHIsIG9mZk1pbnV0ZVN0cikge1xuICBsZXQgb2ZmSG91ciA9IHBhcnNlSW50KG9mZkhvdXJTdHIsIDEwKTtcblxuICAvLyBkb24ndCB8fCB0aGlzIGJlY2F1c2Ugd2Ugd2FudCB0byBwcmVzZXJ2ZSAtMFxuICBpZiAoTnVtYmVyLmlzTmFOKG9mZkhvdXIpKSB7XG4gICAgb2ZmSG91ciA9IDA7XG4gIH1cblxuICBjb25zdCBvZmZNaW4gPSBwYXJzZUludChvZmZNaW51dGVTdHIsIDEwKSB8fCAwLFxuICAgIG9mZk1pblNpZ25lZCA9IG9mZkhvdXIgPCAwIHx8IE9iamVjdC5pcyhvZmZIb3VyLCAtMCkgPyAtb2ZmTWluIDogb2ZmTWluO1xuICByZXR1cm4gb2ZmSG91ciAqIDYwICsgb2ZmTWluU2lnbmVkO1xufVxuXG4vLyBDT0VSQ0lPTlxuXG5leHBvcnQgZnVuY3Rpb24gYXNOdW1iZXIodmFsdWUpIHtcbiAgY29uc3QgbnVtZXJpY1ZhbHVlID0gTnVtYmVyKHZhbHVlKTtcbiAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJib29sZWFuXCIgfHwgdmFsdWUgPT09IFwiXCIgfHwgTnVtYmVyLmlzTmFOKG51bWVyaWNWYWx1ZSkpXG4gICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEVycm9yKGBJbnZhbGlkIHVuaXQgdmFsdWUgJHt2YWx1ZX1gKTtcbiAgcmV0dXJuIG51bWVyaWNWYWx1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5vcm1hbGl6ZU9iamVjdChvYmosIG5vcm1hbGl6ZXIpIHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IHt9O1xuICBmb3IgKGNvbnN0IHUgaW4gb2JqKSB7XG4gICAgaWYgKGhhc093blByb3BlcnR5KG9iaiwgdSkpIHtcbiAgICAgIGNvbnN0IHYgPSBvYmpbdV07XG4gICAgICBpZiAodiA9PT0gdW5kZWZpbmVkIHx8IHYgPT09IG51bGwpIGNvbnRpbnVlO1xuICAgICAgbm9ybWFsaXplZFtub3JtYWxpemVyKHUpXSA9IGFzTnVtYmVyKHYpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbm9ybWFsaXplZDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdE9mZnNldChvZmZzZXQsIGZvcm1hdCkge1xuICBjb25zdCBob3VycyA9IE1hdGgudHJ1bmMoTWF0aC5hYnMob2Zmc2V0IC8gNjApKSxcbiAgICBtaW51dGVzID0gTWF0aC50cnVuYyhNYXRoLmFicyhvZmZzZXQgJSA2MCkpLFxuICAgIHNpZ24gPSBvZmZzZXQgPj0gMCA/IFwiK1wiIDogXCItXCI7XG5cbiAgc3dpdGNoIChmb3JtYXQpIHtcbiAgICBjYXNlIFwic2hvcnRcIjpcbiAgICAgIHJldHVybiBgJHtzaWdufSR7cGFkU3RhcnQoaG91cnMsIDIpfToke3BhZFN0YXJ0KG1pbnV0ZXMsIDIpfWA7XG4gICAgY2FzZSBcIm5hcnJvd1wiOlxuICAgICAgcmV0dXJuIGAke3NpZ259JHtob3Vyc30ke21pbnV0ZXMgPiAwID8gYDoke21pbnV0ZXN9YCA6IFwiXCJ9YDtcbiAgICBjYXNlIFwidGVjaGllXCI6XG4gICAgICByZXR1cm4gYCR7c2lnbn0ke3BhZFN0YXJ0KGhvdXJzLCAyKX0ke3BhZFN0YXJ0KG1pbnV0ZXMsIDIpfWA7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKGBWYWx1ZSBmb3JtYXQgJHtmb3JtYXR9IGlzIG91dCBvZiByYW5nZSBmb3IgcHJvcGVydHkgZm9ybWF0YCk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRpbWVPYmplY3Qob2JqKSB7XG4gIHJldHVybiBwaWNrKG9iaiwgW1wiaG91clwiLCBcIm1pbnV0ZVwiLCBcInNlY29uZFwiLCBcIm1pbGxpc2Vjb25kXCJdKTtcbn1cbiIsICJpbXBvcnQgKiBhcyBGb3JtYXRzIGZyb20gXCIuL2Zvcm1hdHMuanNcIjtcbmltcG9ydCB7IHBpY2sgfSBmcm9tIFwiLi91dGlsLmpzXCI7XG5cbmZ1bmN0aW9uIHN0cmluZ2lmeShvYmopIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KG9iaiwgT2JqZWN0LmtleXMob2JqKS5zb3J0KCkpO1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cblxuZXhwb3J0IGNvbnN0IG1vbnRoc0xvbmcgPSBbXG4gIFwiSmFudWFyeVwiLFxuICBcIkZlYnJ1YXJ5XCIsXG4gIFwiTWFyY2hcIixcbiAgXCJBcHJpbFwiLFxuICBcIk1heVwiLFxuICBcIkp1bmVcIixcbiAgXCJKdWx5XCIsXG4gIFwiQXVndXN0XCIsXG4gIFwiU2VwdGVtYmVyXCIsXG4gIFwiT2N0b2JlclwiLFxuICBcIk5vdmVtYmVyXCIsXG4gIFwiRGVjZW1iZXJcIixcbl07XG5cbmV4cG9ydCBjb25zdCBtb250aHNTaG9ydCA9IFtcbiAgXCJKYW5cIixcbiAgXCJGZWJcIixcbiAgXCJNYXJcIixcbiAgXCJBcHJcIixcbiAgXCJNYXlcIixcbiAgXCJKdW5cIixcbiAgXCJKdWxcIixcbiAgXCJBdWdcIixcbiAgXCJTZXBcIixcbiAgXCJPY3RcIixcbiAgXCJOb3ZcIixcbiAgXCJEZWNcIixcbl07XG5cbmV4cG9ydCBjb25zdCBtb250aHNOYXJyb3cgPSBbXCJKXCIsIFwiRlwiLCBcIk1cIiwgXCJBXCIsIFwiTVwiLCBcIkpcIiwgXCJKXCIsIFwiQVwiLCBcIlNcIiwgXCJPXCIsIFwiTlwiLCBcIkRcIl07XG5cbmV4cG9ydCBmdW5jdGlvbiBtb250aHMobGVuZ3RoKSB7XG4gIHN3aXRjaCAobGVuZ3RoKSB7XG4gICAgY2FzZSBcIm5hcnJvd1wiOlxuICAgICAgcmV0dXJuIFsuLi5tb250aHNOYXJyb3ddO1xuICAgIGNhc2UgXCJzaG9ydFwiOlxuICAgICAgcmV0dXJuIFsuLi5tb250aHNTaG9ydF07XG4gICAgY2FzZSBcImxvbmdcIjpcbiAgICAgIHJldHVybiBbLi4ubW9udGhzTG9uZ107XG4gICAgY2FzZSBcIm51bWVyaWNcIjpcbiAgICAgIHJldHVybiBbXCIxXCIsIFwiMlwiLCBcIjNcIiwgXCI0XCIsIFwiNVwiLCBcIjZcIiwgXCI3XCIsIFwiOFwiLCBcIjlcIiwgXCIxMFwiLCBcIjExXCIsIFwiMTJcIl07XG4gICAgY2FzZSBcIjItZGlnaXRcIjpcbiAgICAgIHJldHVybiBbXCIwMVwiLCBcIjAyXCIsIFwiMDNcIiwgXCIwNFwiLCBcIjA1XCIsIFwiMDZcIiwgXCIwN1wiLCBcIjA4XCIsIFwiMDlcIiwgXCIxMFwiLCBcIjExXCIsIFwiMTJcIl07XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCB3ZWVrZGF5c0xvbmcgPSBbXG4gIFwiTW9uZGF5XCIsXG4gIFwiVHVlc2RheVwiLFxuICBcIldlZG5lc2RheVwiLFxuICBcIlRodXJzZGF5XCIsXG4gIFwiRnJpZGF5XCIsXG4gIFwiU2F0dXJkYXlcIixcbiAgXCJTdW5kYXlcIixcbl07XG5cbmV4cG9ydCBjb25zdCB3ZWVrZGF5c1Nob3J0ID0gW1wiTW9uXCIsIFwiVHVlXCIsIFwiV2VkXCIsIFwiVGh1XCIsIFwiRnJpXCIsIFwiU2F0XCIsIFwiU3VuXCJdO1xuXG5leHBvcnQgY29uc3Qgd2Vla2RheXNOYXJyb3cgPSBbXCJNXCIsIFwiVFwiLCBcIldcIiwgXCJUXCIsIFwiRlwiLCBcIlNcIiwgXCJTXCJdO1xuXG5leHBvcnQgZnVuY3Rpb24gd2Vla2RheXMobGVuZ3RoKSB7XG4gIHN3aXRjaCAobGVuZ3RoKSB7XG4gICAgY2FzZSBcIm5hcnJvd1wiOlxuICAgICAgcmV0dXJuIFsuLi53ZWVrZGF5c05hcnJvd107XG4gICAgY2FzZSBcInNob3J0XCI6XG4gICAgICByZXR1cm4gWy4uLndlZWtkYXlzU2hvcnRdO1xuICAgIGNhc2UgXCJsb25nXCI6XG4gICAgICByZXR1cm4gWy4uLndlZWtkYXlzTG9uZ107XG4gICAgY2FzZSBcIm51bWVyaWNcIjpcbiAgICAgIHJldHVybiBbXCIxXCIsIFwiMlwiLCBcIjNcIiwgXCI0XCIsIFwiNVwiLCBcIjZcIiwgXCI3XCJdO1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gbnVsbDtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgbWVyaWRpZW1zID0gW1wiQU1cIiwgXCJQTVwiXTtcblxuZXhwb3J0IGNvbnN0IGVyYXNMb25nID0gW1wiQmVmb3JlIENocmlzdFwiLCBcIkFubm8gRG9taW5pXCJdO1xuXG5leHBvcnQgY29uc3QgZXJhc1Nob3J0ID0gW1wiQkNcIiwgXCJBRFwiXTtcblxuZXhwb3J0IGNvbnN0IGVyYXNOYXJyb3cgPSBbXCJCXCIsIFwiQVwiXTtcblxuZXhwb3J0IGZ1bmN0aW9uIGVyYXMobGVuZ3RoKSB7XG4gIHN3aXRjaCAobGVuZ3RoKSB7XG4gICAgY2FzZSBcIm5hcnJvd1wiOlxuICAgICAgcmV0dXJuIFsuLi5lcmFzTmFycm93XTtcbiAgICBjYXNlIFwic2hvcnRcIjpcbiAgICAgIHJldHVybiBbLi4uZXJhc1Nob3J0XTtcbiAgICBjYXNlIFwibG9uZ1wiOlxuICAgICAgcmV0dXJuIFsuLi5lcmFzTG9uZ107XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBtZXJpZGllbUZvckRhdGVUaW1lKGR0KSB7XG4gIHJldHVybiBtZXJpZGllbXNbZHQuaG91ciA8IDEyID8gMCA6IDFdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2Vla2RheUZvckRhdGVUaW1lKGR0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIHdlZWtkYXlzKGxlbmd0aClbZHQud2Vla2RheSAtIDFdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gbW9udGhGb3JEYXRlVGltZShkdCwgbGVuZ3RoKSB7XG4gIHJldHVybiBtb250aHMobGVuZ3RoKVtkdC5tb250aCAtIDFdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZXJhRm9yRGF0ZVRpbWUoZHQsIGxlbmd0aCkge1xuICByZXR1cm4gZXJhcyhsZW5ndGgpW2R0LnllYXIgPCAwID8gMCA6IDFdO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9ybWF0UmVsYXRpdmVUaW1lKHVuaXQsIGNvdW50LCBudW1lcmljID0gXCJhbHdheXNcIiwgbmFycm93ID0gZmFsc2UpIHtcbiAgY29uc3QgdW5pdHMgPSB7XG4gICAgeWVhcnM6IFtcInllYXJcIiwgXCJ5ci5cIl0sXG4gICAgcXVhcnRlcnM6IFtcInF1YXJ0ZXJcIiwgXCJxdHIuXCJdLFxuICAgIG1vbnRoczogW1wibW9udGhcIiwgXCJtby5cIl0sXG4gICAgd2Vla3M6IFtcIndlZWtcIiwgXCJ3ay5cIl0sXG4gICAgZGF5czogW1wiZGF5XCIsIFwiZGF5XCIsIFwiZGF5c1wiXSxcbiAgICBob3VyczogW1wiaG91clwiLCBcImhyLlwiXSxcbiAgICBtaW51dGVzOiBbXCJtaW51dGVcIiwgXCJtaW4uXCJdLFxuICAgIHNlY29uZHM6IFtcInNlY29uZFwiLCBcInNlYy5cIl0sXG4gIH07XG5cbiAgY29uc3QgbGFzdGFibGUgPSBbXCJob3Vyc1wiLCBcIm1pbnV0ZXNcIiwgXCJzZWNvbmRzXCJdLmluZGV4T2YodW5pdCkgPT09IC0xO1xuXG4gIGlmIChudW1lcmljID09PSBcImF1dG9cIiAmJiBsYXN0YWJsZSkge1xuICAgIGNvbnN0IGlzRGF5ID0gdW5pdCA9PT0gXCJkYXlzXCI7XG4gICAgc3dpdGNoIChjb3VudCkge1xuICAgICAgY2FzZSAxOlxuICAgICAgICByZXR1cm4gaXNEYXkgPyBcInRvbW9ycm93XCIgOiBgbmV4dCAke3VuaXRzW3VuaXRdWzBdfWA7XG4gICAgICBjYXNlIC0xOlxuICAgICAgICByZXR1cm4gaXNEYXkgPyBcInllc3RlcmRheVwiIDogYGxhc3QgJHt1bml0c1t1bml0XVswXX1gO1xuICAgICAgY2FzZSAwOlxuICAgICAgICByZXR1cm4gaXNEYXkgPyBcInRvZGF5XCIgOiBgdGhpcyAke3VuaXRzW3VuaXRdWzBdfWA7XG4gICAgICBkZWZhdWx0OiAvLyBmYWxsIHRocm91Z2hcbiAgICB9XG4gIH1cblxuICBjb25zdCBpc0luUGFzdCA9IE9iamVjdC5pcyhjb3VudCwgLTApIHx8IGNvdW50IDwgMCxcbiAgICBmbXRWYWx1ZSA9IE1hdGguYWJzKGNvdW50KSxcbiAgICBzaW5ndWxhciA9IGZtdFZhbHVlID09PSAxLFxuICAgIGxpbFVuaXRzID0gdW5pdHNbdW5pdF0sXG4gICAgZm10VW5pdCA9IG5hcnJvd1xuICAgICAgPyBzaW5ndWxhclxuICAgICAgICA/IGxpbFVuaXRzWzFdXG4gICAgICAgIDogbGlsVW5pdHNbMl0gfHwgbGlsVW5pdHNbMV1cbiAgICAgIDogc2luZ3VsYXJcbiAgICAgID8gdW5pdHNbdW5pdF1bMF1cbiAgICAgIDogdW5pdDtcbiAgcmV0dXJuIGlzSW5QYXN0ID8gYCR7Zm10VmFsdWV9ICR7Zm10VW5pdH0gYWdvYCA6IGBpbiAke2ZtdFZhbHVlfSAke2ZtdFVuaXR9YDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdFN0cmluZyhrbm93bkZvcm1hdCkge1xuICAvLyB0aGVzZSBhbGwgaGF2ZSB0aGUgb2Zmc2V0cyByZW1vdmVkIGJlY2F1c2Ugd2UgZG9uJ3QgaGF2ZSBhY2Nlc3MgdG8gdGhlbVxuICAvLyB3aXRob3V0IGFsbCB0aGUgaW50bCBzdHVmZiB0aGlzIGlzIGJhY2tmaWxsaW5nXG4gIGNvbnN0IGZpbHRlcmVkID0gcGljayhrbm93bkZvcm1hdCwgW1xuICAgICAgXCJ3ZWVrZGF5XCIsXG4gICAgICBcImVyYVwiLFxuICAgICAgXCJ5ZWFyXCIsXG4gICAgICBcIm1vbnRoXCIsXG4gICAgICBcImRheVwiLFxuICAgICAgXCJob3VyXCIsXG4gICAgICBcIm1pbnV0ZVwiLFxuICAgICAgXCJzZWNvbmRcIixcbiAgICAgIFwidGltZVpvbmVOYW1lXCIsXG4gICAgICBcImhvdXJDeWNsZVwiLFxuICAgIF0pLFxuICAgIGtleSA9IHN0cmluZ2lmeShmaWx0ZXJlZCksXG4gICAgZGF0ZVRpbWVIdWdlID0gXCJFRUVFLCBMTExMIGQsIHl5eXksIGg6bW0gYVwiO1xuICBzd2l0Y2ggKGtleSkge1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuREFURV9TSE9SVCk6XG4gICAgICByZXR1cm4gXCJNL2QveXl5eVwiO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuREFURV9NRUQpOlxuICAgICAgcmV0dXJuIFwiTExMIGQsIHl5eXlcIjtcbiAgICBjYXNlIHN0cmluZ2lmeShGb3JtYXRzLkRBVEVfTUVEX1dJVEhfV0VFS0RBWSk6XG4gICAgICByZXR1cm4gXCJFRUUsIExMTCBkLCB5eXl5XCI7XG4gICAgY2FzZSBzdHJpbmdpZnkoRm9ybWF0cy5EQVRFX0ZVTEwpOlxuICAgICAgcmV0dXJuIFwiTExMTCBkLCB5eXl5XCI7XG4gICAgY2FzZSBzdHJpbmdpZnkoRm9ybWF0cy5EQVRFX0hVR0UpOlxuICAgICAgcmV0dXJuIFwiRUVFRSwgTExMTCBkLCB5eXl5XCI7XG4gICAgY2FzZSBzdHJpbmdpZnkoRm9ybWF0cy5USU1FX1NJTVBMRSk6XG4gICAgICByZXR1cm4gXCJoOm1tIGFcIjtcbiAgICBjYXNlIHN0cmluZ2lmeShGb3JtYXRzLlRJTUVfV0lUSF9TRUNPTkRTKTpcbiAgICAgIHJldHVybiBcImg6bW06c3MgYVwiO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuVElNRV9XSVRIX1NIT1JUX09GRlNFVCk6XG4gICAgICByZXR1cm4gXCJoOm1tIGFcIjtcbiAgICBjYXNlIHN0cmluZ2lmeShGb3JtYXRzLlRJTUVfV0lUSF9MT05HX09GRlNFVCk6XG4gICAgICByZXR1cm4gXCJoOm1tIGFcIjtcbiAgICBjYXNlIHN0cmluZ2lmeShGb3JtYXRzLlRJTUVfMjRfU0lNUExFKTpcbiAgICAgIHJldHVybiBcIkhIOm1tXCI7XG4gICAgY2FzZSBzdHJpbmdpZnkoRm9ybWF0cy5USU1FXzI0X1dJVEhfU0VDT05EUyk6XG4gICAgICByZXR1cm4gXCJISDptbTpzc1wiO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuVElNRV8yNF9XSVRIX1NIT1JUX09GRlNFVCk6XG4gICAgICByZXR1cm4gXCJISDptbVwiO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuVElNRV8yNF9XSVRIX0xPTkdfT0ZGU0VUKTpcbiAgICAgIHJldHVybiBcIkhIOm1tXCI7XG4gICAgY2FzZSBzdHJpbmdpZnkoRm9ybWF0cy5EQVRFVElNRV9TSE9SVCk6XG4gICAgICByZXR1cm4gXCJNL2QveXl5eSwgaDptbSBhXCI7XG4gICAgY2FzZSBzdHJpbmdpZnkoRm9ybWF0cy5EQVRFVElNRV9NRUQpOlxuICAgICAgcmV0dXJuIFwiTExMIGQsIHl5eXksIGg6bW0gYVwiO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuREFURVRJTUVfRlVMTCk6XG4gICAgICByZXR1cm4gXCJMTExMIGQsIHl5eXksIGg6bW0gYVwiO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuREFURVRJTUVfSFVHRSk6XG4gICAgICByZXR1cm4gZGF0ZVRpbWVIdWdlO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuREFURVRJTUVfU0hPUlRfV0lUSF9TRUNPTkRTKTpcbiAgICAgIHJldHVybiBcIk0vZC95eXl5LCBoOm1tOnNzIGFcIjtcbiAgICBjYXNlIHN0cmluZ2lmeShGb3JtYXRzLkRBVEVUSU1FX01FRF9XSVRIX1NFQ09ORFMpOlxuICAgICAgcmV0dXJuIFwiTExMIGQsIHl5eXksIGg6bW06c3MgYVwiO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuREFURVRJTUVfTUVEX1dJVEhfV0VFS0RBWSk6XG4gICAgICByZXR1cm4gXCJFRUUsIGQgTExMIHl5eXksIGg6bW0gYVwiO1xuICAgIGNhc2Ugc3RyaW5naWZ5KEZvcm1hdHMuREFURVRJTUVfRlVMTF9XSVRIX1NFQ09ORFMpOlxuICAgICAgcmV0dXJuIFwiTExMTCBkLCB5eXl5LCBoOm1tOnNzIGFcIjtcbiAgICBjYXNlIHN0cmluZ2lmeShGb3JtYXRzLkRBVEVUSU1FX0hVR0VfV0lUSF9TRUNPTkRTKTpcbiAgICAgIHJldHVybiBcIkVFRUUsIExMTEwgZCwgeXl5eSwgaDptbTpzcyBhXCI7XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiBkYXRlVGltZUh1Z2U7XG4gIH1cbn1cbiIsICJpbXBvcnQgKiBhcyBFbmdsaXNoIGZyb20gXCIuL2VuZ2xpc2guanNcIjtcbmltcG9ydCAqIGFzIEZvcm1hdHMgZnJvbSBcIi4vZm9ybWF0cy5qc1wiO1xuaW1wb3J0IHsgcGFkU3RhcnQgfSBmcm9tIFwiLi91dGlsLmpzXCI7XG5cbmZ1bmN0aW9uIHN0cmluZ2lmeVRva2VucyhzcGxpdHMsIHRva2VuVG9TdHJpbmcpIHtcbiAgbGV0IHMgPSBcIlwiO1xuICBmb3IgKGNvbnN0IHRva2VuIG9mIHNwbGl0cykge1xuICAgIGlmICh0b2tlbi5saXRlcmFsKSB7XG4gICAgICBzICs9IHRva2VuLnZhbDtcbiAgICB9IGVsc2Uge1xuICAgICAgcyArPSB0b2tlblRvU3RyaW5nKHRva2VuLnZhbCk7XG4gICAgfVxuICB9XG4gIHJldHVybiBzO1xufVxuXG5jb25zdCBtYWNyb1Rva2VuVG9Gb3JtYXRPcHRzID0ge1xuICBEOiBGb3JtYXRzLkRBVEVfU0hPUlQsXG4gIEREOiBGb3JtYXRzLkRBVEVfTUVELFxuICBEREQ6IEZvcm1hdHMuREFURV9GVUxMLFxuICBEREREOiBGb3JtYXRzLkRBVEVfSFVHRSxcbiAgdDogRm9ybWF0cy5USU1FX1NJTVBMRSxcbiAgdHQ6IEZvcm1hdHMuVElNRV9XSVRIX1NFQ09ORFMsXG4gIHR0dDogRm9ybWF0cy5USU1FX1dJVEhfU0hPUlRfT0ZGU0VULFxuICB0dHR0OiBGb3JtYXRzLlRJTUVfV0lUSF9MT05HX09GRlNFVCxcbiAgVDogRm9ybWF0cy5USU1FXzI0X1NJTVBMRSxcbiAgVFQ6IEZvcm1hdHMuVElNRV8yNF9XSVRIX1NFQ09ORFMsXG4gIFRUVDogRm9ybWF0cy5USU1FXzI0X1dJVEhfU0hPUlRfT0ZGU0VULFxuICBUVFRUOiBGb3JtYXRzLlRJTUVfMjRfV0lUSF9MT05HX09GRlNFVCxcbiAgZjogRm9ybWF0cy5EQVRFVElNRV9TSE9SVCxcbiAgZmY6IEZvcm1hdHMuREFURVRJTUVfTUVELFxuICBmZmY6IEZvcm1hdHMuREFURVRJTUVfRlVMTCxcbiAgZmZmZjogRm9ybWF0cy5EQVRFVElNRV9IVUdFLFxuICBGOiBGb3JtYXRzLkRBVEVUSU1FX1NIT1JUX1dJVEhfU0VDT05EUyxcbiAgRkY6IEZvcm1hdHMuREFURVRJTUVfTUVEX1dJVEhfU0VDT05EUyxcbiAgRkZGOiBGb3JtYXRzLkRBVEVUSU1FX0ZVTExfV0lUSF9TRUNPTkRTLFxuICBGRkZGOiBGb3JtYXRzLkRBVEVUSU1FX0hVR0VfV0lUSF9TRUNPTkRTLFxufTtcblxuLyoqXG4gKiBAcHJpdmF0ZVxuICovXG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEZvcm1hdHRlciB7XG4gIHN0YXRpYyBjcmVhdGUobG9jYWxlLCBvcHRzID0ge30pIHtcbiAgICByZXR1cm4gbmV3IEZvcm1hdHRlcihsb2NhbGUsIG9wdHMpO1xuICB9XG5cbiAgc3RhdGljIHBhcnNlRm9ybWF0KGZtdCkge1xuICAgIC8vIHdoaXRlLXNwYWNlIGlzIGFsd2F5cyBjb25zaWRlcmVkIGEgbGl0ZXJhbCBpbiB1c2VyLXByb3ZpZGVkIGZvcm1hdHNcbiAgICAvLyB0aGUgXCIgXCIgdG9rZW4gaGFzIGEgc3BlY2lhbCBtZWFuaW5nIChzZWUgdW5pdEZvclRva2VuKVxuXG4gICAgbGV0IGN1cnJlbnQgPSBudWxsLFxuICAgICAgY3VycmVudEZ1bGwgPSBcIlwiLFxuICAgICAgYnJhY2tldGVkID0gZmFsc2U7XG4gICAgY29uc3Qgc3BsaXRzID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBmbXQubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGMgPSBmbXQuY2hhckF0KGkpO1xuICAgICAgaWYgKGMgPT09IFwiJ1wiKSB7XG4gICAgICAgIGlmIChjdXJyZW50RnVsbC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgc3BsaXRzLnB1c2goeyBsaXRlcmFsOiBicmFja2V0ZWQgfHwgL15cXHMrJC8udGVzdChjdXJyZW50RnVsbCksIHZhbDogY3VycmVudEZ1bGwgfSk7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudCA9IG51bGw7XG4gICAgICAgIGN1cnJlbnRGdWxsID0gXCJcIjtcbiAgICAgICAgYnJhY2tldGVkID0gIWJyYWNrZXRlZDtcbiAgICAgIH0gZWxzZSBpZiAoYnJhY2tldGVkKSB7XG4gICAgICAgIGN1cnJlbnRGdWxsICs9IGM7XG4gICAgICB9IGVsc2UgaWYgKGMgPT09IGN1cnJlbnQpIHtcbiAgICAgICAgY3VycmVudEZ1bGwgKz0gYztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmIChjdXJyZW50RnVsbC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgc3BsaXRzLnB1c2goeyBsaXRlcmFsOiAvXlxccyskLy50ZXN0KGN1cnJlbnRGdWxsKSwgdmFsOiBjdXJyZW50RnVsbCB9KTtcbiAgICAgICAgfVxuICAgICAgICBjdXJyZW50RnVsbCA9IGM7XG4gICAgICAgIGN1cnJlbnQgPSBjO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjdXJyZW50RnVsbC5sZW5ndGggPiAwKSB7XG4gICAgICBzcGxpdHMucHVzaCh7IGxpdGVyYWw6IGJyYWNrZXRlZCB8fCAvXlxccyskLy50ZXN0KGN1cnJlbnRGdWxsKSwgdmFsOiBjdXJyZW50RnVsbCB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3BsaXRzO1xuICB9XG5cbiAgc3RhdGljIG1hY3JvVG9rZW5Ub0Zvcm1hdE9wdHModG9rZW4pIHtcbiAgICByZXR1cm4gbWFjcm9Ub2tlblRvRm9ybWF0T3B0c1t0b2tlbl07XG4gIH1cblxuICBjb25zdHJ1Y3Rvcihsb2NhbGUsIGZvcm1hdE9wdHMpIHtcbiAgICB0aGlzLm9wdHMgPSBmb3JtYXRPcHRzO1xuICAgIHRoaXMubG9jID0gbG9jYWxlO1xuICAgIHRoaXMuc3lzdGVtTG9jID0gbnVsbDtcbiAgfVxuXG4gIGZvcm1hdFdpdGhTeXN0ZW1EZWZhdWx0KGR0LCBvcHRzKSB7XG4gICAgaWYgKHRoaXMuc3lzdGVtTG9jID09PSBudWxsKSB7XG4gICAgICB0aGlzLnN5c3RlbUxvYyA9IHRoaXMubG9jLnJlZGVmYXVsdFRvU3lzdGVtKCk7XG4gICAgfVxuICAgIGNvbnN0IGRmID0gdGhpcy5zeXN0ZW1Mb2MuZHRGb3JtYXR0ZXIoZHQsIHsgLi4udGhpcy5vcHRzLCAuLi5vcHRzIH0pO1xuICAgIHJldHVybiBkZi5mb3JtYXQoKTtcbiAgfVxuXG4gIGZvcm1hdERhdGVUaW1lKGR0LCBvcHRzID0ge30pIHtcbiAgICBjb25zdCBkZiA9IHRoaXMubG9jLmR0Rm9ybWF0dGVyKGR0LCB7IC4uLnRoaXMub3B0cywgLi4ub3B0cyB9KTtcbiAgICByZXR1cm4gZGYuZm9ybWF0KCk7XG4gIH1cblxuICBmb3JtYXREYXRlVGltZVBhcnRzKGR0LCBvcHRzID0ge30pIHtcbiAgICBjb25zdCBkZiA9IHRoaXMubG9jLmR0Rm9ybWF0dGVyKGR0LCB7IC4uLnRoaXMub3B0cywgLi4ub3B0cyB9KTtcbiAgICByZXR1cm4gZGYuZm9ybWF0VG9QYXJ0cygpO1xuICB9XG5cbiAgZm9ybWF0SW50ZXJ2YWwoaW50ZXJ2YWwsIG9wdHMgPSB7fSkge1xuICAgIGNvbnN0IGRmID0gdGhpcy5sb2MuZHRGb3JtYXR0ZXIoaW50ZXJ2YWwuc3RhcnQsIHsgLi4udGhpcy5vcHRzLCAuLi5vcHRzIH0pO1xuICAgIHJldHVybiBkZi5kdGYuZm9ybWF0UmFuZ2UoaW50ZXJ2YWwuc3RhcnQudG9KU0RhdGUoKSwgaW50ZXJ2YWwuZW5kLnRvSlNEYXRlKCkpO1xuICB9XG5cbiAgcmVzb2x2ZWRPcHRpb25zKGR0LCBvcHRzID0ge30pIHtcbiAgICBjb25zdCBkZiA9IHRoaXMubG9jLmR0Rm9ybWF0dGVyKGR0LCB7IC4uLnRoaXMub3B0cywgLi4ub3B0cyB9KTtcbiAgICByZXR1cm4gZGYucmVzb2x2ZWRPcHRpb25zKCk7XG4gIH1cblxuICBudW0obiwgcCA9IDApIHtcbiAgICAvLyB3ZSBnZXQgc29tZSBwZXJmIG91dCBvZiBkb2luZyB0aGlzIGhlcmUsIGFubm95aW5nbHlcbiAgICBpZiAodGhpcy5vcHRzLmZvcmNlU2ltcGxlKSB7XG4gICAgICByZXR1cm4gcGFkU3RhcnQobiwgcCk7XG4gICAgfVxuXG4gICAgY29uc3Qgb3B0cyA9IHsgLi4udGhpcy5vcHRzIH07XG5cbiAgICBpZiAocCA+IDApIHtcbiAgICAgIG9wdHMucGFkVG8gPSBwO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmxvYy5udW1iZXJGb3JtYXR0ZXIob3B0cykuZm9ybWF0KG4pO1xuICB9XG5cbiAgZm9ybWF0RGF0ZVRpbWVGcm9tU3RyaW5nKGR0LCBmbXQpIHtcbiAgICBjb25zdCBrbm93bkVuZ2xpc2ggPSB0aGlzLmxvYy5saXN0aW5nTW9kZSgpID09PSBcImVuXCIsXG4gICAgICB1c2VEYXRlVGltZUZvcm1hdHRlciA9IHRoaXMubG9jLm91dHB1dENhbGVuZGFyICYmIHRoaXMubG9jLm91dHB1dENhbGVuZGFyICE9PSBcImdyZWdvcnlcIixcbiAgICAgIHN0cmluZyA9IChvcHRzLCBleHRyYWN0KSA9PiB0aGlzLmxvYy5leHRyYWN0KGR0LCBvcHRzLCBleHRyYWN0KSxcbiAgICAgIGZvcm1hdE9mZnNldCA9IChvcHRzKSA9PiB7XG4gICAgICAgIGlmIChkdC5pc09mZnNldEZpeGVkICYmIGR0Lm9mZnNldCA9PT0gMCAmJiBvcHRzLmFsbG93Wikge1xuICAgICAgICAgIHJldHVybiBcIlpcIjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBkdC5pc1ZhbGlkID8gZHQuem9uZS5mb3JtYXRPZmZzZXQoZHQudHMsIG9wdHMuZm9ybWF0KSA6IFwiXCI7XG4gICAgICB9LFxuICAgICAgbWVyaWRpZW0gPSAoKSA9PlxuICAgICAgICBrbm93bkVuZ2xpc2hcbiAgICAgICAgICA/IEVuZ2xpc2gubWVyaWRpZW1Gb3JEYXRlVGltZShkdClcbiAgICAgICAgICA6IHN0cmluZyh7IGhvdXI6IFwibnVtZXJpY1wiLCBob3VyQ3ljbGU6IFwiaDEyXCIgfSwgXCJkYXlwZXJpb2RcIiksXG4gICAgICBtb250aCA9IChsZW5ndGgsIHN0YW5kYWxvbmUpID0+XG4gICAgICAgIGtub3duRW5nbGlzaFxuICAgICAgICAgID8gRW5nbGlzaC5tb250aEZvckRhdGVUaW1lKGR0LCBsZW5ndGgpXG4gICAgICAgICAgOiBzdHJpbmcoc3RhbmRhbG9uZSA/IHsgbW9udGg6IGxlbmd0aCB9IDogeyBtb250aDogbGVuZ3RoLCBkYXk6IFwibnVtZXJpY1wiIH0sIFwibW9udGhcIiksXG4gICAgICB3ZWVrZGF5ID0gKGxlbmd0aCwgc3RhbmRhbG9uZSkgPT5cbiAgICAgICAga25vd25FbmdsaXNoXG4gICAgICAgICAgPyBFbmdsaXNoLndlZWtkYXlGb3JEYXRlVGltZShkdCwgbGVuZ3RoKVxuICAgICAgICAgIDogc3RyaW5nKFxuICAgICAgICAgICAgICBzdGFuZGFsb25lID8geyB3ZWVrZGF5OiBsZW5ndGggfSA6IHsgd2Vla2RheTogbGVuZ3RoLCBtb250aDogXCJsb25nXCIsIGRheTogXCJudW1lcmljXCIgfSxcbiAgICAgICAgICAgICAgXCJ3ZWVrZGF5XCJcbiAgICAgICAgICAgICksXG4gICAgICBtYXliZU1hY3JvID0gKHRva2VuKSA9PiB7XG4gICAgICAgIGNvbnN0IGZvcm1hdE9wdHMgPSBGb3JtYXR0ZXIubWFjcm9Ub2tlblRvRm9ybWF0T3B0cyh0b2tlbik7XG4gICAgICAgIGlmIChmb3JtYXRPcHRzKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMuZm9ybWF0V2l0aFN5c3RlbURlZmF1bHQoZHQsIGZvcm1hdE9wdHMpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB0b2tlbjtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGVyYSA9IChsZW5ndGgpID0+XG4gICAgICAgIGtub3duRW5nbGlzaCA/IEVuZ2xpc2guZXJhRm9yRGF0ZVRpbWUoZHQsIGxlbmd0aCkgOiBzdHJpbmcoeyBlcmE6IGxlbmd0aCB9LCBcImVyYVwiKSxcbiAgICAgIHRva2VuVG9TdHJpbmcgPSAodG9rZW4pID0+IHtcbiAgICAgICAgLy8gV2hlcmUgcG9zc2libGU6IGh0dHA6Ly9jbGRyLnVuaWNvZGUub3JnL3RyYW5zbGF0aW9uL2RhdGUtdGltZS0xL2RhdGUtdGltZSNUT0MtU3RhbmRhbG9uZS12cy4tRm9ybWF0LVN0eWxlc1xuICAgICAgICBzd2l0Y2ggKHRva2VuKSB7XG4gICAgICAgICAgLy8gbXNcbiAgICAgICAgICBjYXNlIFwiU1wiOlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtKGR0Lm1pbGxpc2Vjb25kKTtcbiAgICAgICAgICBjYXNlIFwidVwiOlxuICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICBjYXNlIFwiU1NTXCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW0oZHQubWlsbGlzZWNvbmQsIDMpO1xuICAgICAgICAgIC8vIHNlY29uZHNcbiAgICAgICAgICBjYXNlIFwic1wiOlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtKGR0LnNlY29uZCk7XG4gICAgICAgICAgY2FzZSBcInNzXCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW0oZHQuc2Vjb25kLCAyKTtcbiAgICAgICAgICAvLyBmcmFjdGlvbmFsIHNlY29uZHNcbiAgICAgICAgICBjYXNlIFwidXVcIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShNYXRoLmZsb29yKGR0Lm1pbGxpc2Vjb25kIC8gMTApLCAyKTtcbiAgICAgICAgICBjYXNlIFwidXV1XCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW0oTWF0aC5mbG9vcihkdC5taWxsaXNlY29uZCAvIDEwMCkpO1xuICAgICAgICAgIC8vIG1pbnV0ZXNcbiAgICAgICAgICBjYXNlIFwibVwiOlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtKGR0Lm1pbnV0ZSk7XG4gICAgICAgICAgY2FzZSBcIm1tXCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW0oZHQubWludXRlLCAyKTtcbiAgICAgICAgICAvLyBob3Vyc1xuICAgICAgICAgIGNhc2UgXCJoXCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW0oZHQuaG91ciAlIDEyID09PSAwID8gMTIgOiBkdC5ob3VyICUgMTIpO1xuICAgICAgICAgIGNhc2UgXCJoaFwiOlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtKGR0LmhvdXIgJSAxMiA9PT0gMCA/IDEyIDogZHQuaG91ciAlIDEyLCAyKTtcbiAgICAgICAgICBjYXNlIFwiSFwiOlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtKGR0LmhvdXIpO1xuICAgICAgICAgIGNhc2UgXCJISFwiOlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtKGR0LmhvdXIsIDIpO1xuICAgICAgICAgIC8vIG9mZnNldFxuICAgICAgICAgIGNhc2UgXCJaXCI6XG4gICAgICAgICAgICAvLyBsaWtlICs2XG4gICAgICAgICAgICByZXR1cm4gZm9ybWF0T2Zmc2V0KHsgZm9ybWF0OiBcIm5hcnJvd1wiLCBhbGxvd1o6IHRoaXMub3B0cy5hbGxvd1ogfSk7XG4gICAgICAgICAgY2FzZSBcIlpaXCI6XG4gICAgICAgICAgICAvLyBsaWtlICswNjowMFxuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdE9mZnNldCh7IGZvcm1hdDogXCJzaG9ydFwiLCBhbGxvd1o6IHRoaXMub3B0cy5hbGxvd1ogfSk7XG4gICAgICAgICAgY2FzZSBcIlpaWlwiOlxuICAgICAgICAgICAgLy8gbGlrZSArMDYwMFxuICAgICAgICAgICAgcmV0dXJuIGZvcm1hdE9mZnNldCh7IGZvcm1hdDogXCJ0ZWNoaWVcIiwgYWxsb3daOiB0aGlzLm9wdHMuYWxsb3daIH0pO1xuICAgICAgICAgIGNhc2UgXCJaWlpaXCI6XG4gICAgICAgICAgICAvLyBsaWtlIEVTVFxuICAgICAgICAgICAgcmV0dXJuIGR0LnpvbmUub2Zmc2V0TmFtZShkdC50cywgeyBmb3JtYXQ6IFwic2hvcnRcIiwgbG9jYWxlOiB0aGlzLmxvYy5sb2NhbGUgfSk7XG4gICAgICAgICAgY2FzZSBcIlpaWlpaXCI6XG4gICAgICAgICAgICAvLyBsaWtlIEVhc3Rlcm4gU3RhbmRhcmQgVGltZVxuICAgICAgICAgICAgcmV0dXJuIGR0LnpvbmUub2Zmc2V0TmFtZShkdC50cywgeyBmb3JtYXQ6IFwibG9uZ1wiLCBsb2NhbGU6IHRoaXMubG9jLmxvY2FsZSB9KTtcbiAgICAgICAgICAvLyB6b25lXG4gICAgICAgICAgY2FzZSBcInpcIjpcbiAgICAgICAgICAgIC8vIGxpa2UgQW1lcmljYS9OZXdfWW9ya1xuICAgICAgICAgICAgcmV0dXJuIGR0LnpvbmVOYW1lO1xuICAgICAgICAgIC8vIG1lcmlkaWVtc1xuICAgICAgICAgIGNhc2UgXCJhXCI6XG4gICAgICAgICAgICByZXR1cm4gbWVyaWRpZW0oKTtcbiAgICAgICAgICAvLyBkYXRlc1xuICAgICAgICAgIGNhc2UgXCJkXCI6XG4gICAgICAgICAgICByZXR1cm4gdXNlRGF0ZVRpbWVGb3JtYXR0ZXIgPyBzdHJpbmcoeyBkYXk6IFwibnVtZXJpY1wiIH0sIFwiZGF5XCIpIDogdGhpcy5udW0oZHQuZGF5KTtcbiAgICAgICAgICBjYXNlIFwiZGRcIjpcbiAgICAgICAgICAgIHJldHVybiB1c2VEYXRlVGltZUZvcm1hdHRlciA/IHN0cmluZyh7IGRheTogXCIyLWRpZ2l0XCIgfSwgXCJkYXlcIikgOiB0aGlzLm51bShkdC5kYXksIDIpO1xuICAgICAgICAgIC8vIHdlZWtkYXlzIC0gc3RhbmRhbG9uZVxuICAgICAgICAgIGNhc2UgXCJjXCI6XG4gICAgICAgICAgICAvLyBsaWtlIDFcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShkdC53ZWVrZGF5KTtcbiAgICAgICAgICBjYXNlIFwiY2NjXCI6XG4gICAgICAgICAgICAvLyBsaWtlICdUdWVzJ1xuICAgICAgICAgICAgcmV0dXJuIHdlZWtkYXkoXCJzaG9ydFwiLCB0cnVlKTtcbiAgICAgICAgICBjYXNlIFwiY2NjY1wiOlxuICAgICAgICAgICAgLy8gbGlrZSAnVHVlc2RheSdcbiAgICAgICAgICAgIHJldHVybiB3ZWVrZGF5KFwibG9uZ1wiLCB0cnVlKTtcbiAgICAgICAgICBjYXNlIFwiY2NjY2NcIjpcbiAgICAgICAgICAgIC8vIGxpa2UgJ1QnXG4gICAgICAgICAgICByZXR1cm4gd2Vla2RheShcIm5hcnJvd1wiLCB0cnVlKTtcbiAgICAgICAgICAvLyB3ZWVrZGF5cyAtIGZvcm1hdFxuICAgICAgICAgIGNhc2UgXCJFXCI6XG4gICAgICAgICAgICAvLyBsaWtlIDFcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShkdC53ZWVrZGF5KTtcbiAgICAgICAgICBjYXNlIFwiRUVFXCI6XG4gICAgICAgICAgICAvLyBsaWtlICdUdWVzJ1xuICAgICAgICAgICAgcmV0dXJuIHdlZWtkYXkoXCJzaG9ydFwiLCBmYWxzZSk7XG4gICAgICAgICAgY2FzZSBcIkVFRUVcIjpcbiAgICAgICAgICAgIC8vIGxpa2UgJ1R1ZXNkYXknXG4gICAgICAgICAgICByZXR1cm4gd2Vla2RheShcImxvbmdcIiwgZmFsc2UpO1xuICAgICAgICAgIGNhc2UgXCJFRUVFRVwiOlxuICAgICAgICAgICAgLy8gbGlrZSAnVCdcbiAgICAgICAgICAgIHJldHVybiB3ZWVrZGF5KFwibmFycm93XCIsIGZhbHNlKTtcbiAgICAgICAgICAvLyBtb250aHMgLSBzdGFuZGFsb25lXG4gICAgICAgICAgY2FzZSBcIkxcIjpcbiAgICAgICAgICAgIC8vIGxpa2UgMVxuICAgICAgICAgICAgcmV0dXJuIHVzZURhdGVUaW1lRm9ybWF0dGVyXG4gICAgICAgICAgICAgID8gc3RyaW5nKHsgbW9udGg6IFwibnVtZXJpY1wiLCBkYXk6IFwibnVtZXJpY1wiIH0sIFwibW9udGhcIilcbiAgICAgICAgICAgICAgOiB0aGlzLm51bShkdC5tb250aCk7XG4gICAgICAgICAgY2FzZSBcIkxMXCI6XG4gICAgICAgICAgICAvLyBsaWtlIDAxLCBkb2Vzbid0IHNlZW0gdG8gd29ya1xuICAgICAgICAgICAgcmV0dXJuIHVzZURhdGVUaW1lRm9ybWF0dGVyXG4gICAgICAgICAgICAgID8gc3RyaW5nKHsgbW9udGg6IFwiMi1kaWdpdFwiLCBkYXk6IFwibnVtZXJpY1wiIH0sIFwibW9udGhcIilcbiAgICAgICAgICAgICAgOiB0aGlzLm51bShkdC5tb250aCwgMik7XG4gICAgICAgICAgY2FzZSBcIkxMTFwiOlxuICAgICAgICAgICAgLy8gbGlrZSBKYW5cbiAgICAgICAgICAgIHJldHVybiBtb250aChcInNob3J0XCIsIHRydWUpO1xuICAgICAgICAgIGNhc2UgXCJMTExMXCI6XG4gICAgICAgICAgICAvLyBsaWtlIEphbnVhcnlcbiAgICAgICAgICAgIHJldHVybiBtb250aChcImxvbmdcIiwgdHJ1ZSk7XG4gICAgICAgICAgY2FzZSBcIkxMTExMXCI6XG4gICAgICAgICAgICAvLyBsaWtlIEpcbiAgICAgICAgICAgIHJldHVybiBtb250aChcIm5hcnJvd1wiLCB0cnVlKTtcbiAgICAgICAgICAvLyBtb250aHMgLSBmb3JtYXRcbiAgICAgICAgICBjYXNlIFwiTVwiOlxuICAgICAgICAgICAgLy8gbGlrZSAxXG4gICAgICAgICAgICByZXR1cm4gdXNlRGF0ZVRpbWVGb3JtYXR0ZXJcbiAgICAgICAgICAgICAgPyBzdHJpbmcoeyBtb250aDogXCJudW1lcmljXCIgfSwgXCJtb250aFwiKVxuICAgICAgICAgICAgICA6IHRoaXMubnVtKGR0Lm1vbnRoKTtcbiAgICAgICAgICBjYXNlIFwiTU1cIjpcbiAgICAgICAgICAgIC8vIGxpa2UgMDFcbiAgICAgICAgICAgIHJldHVybiB1c2VEYXRlVGltZUZvcm1hdHRlclxuICAgICAgICAgICAgICA/IHN0cmluZyh7IG1vbnRoOiBcIjItZGlnaXRcIiB9LCBcIm1vbnRoXCIpXG4gICAgICAgICAgICAgIDogdGhpcy5udW0oZHQubW9udGgsIDIpO1xuICAgICAgICAgIGNhc2UgXCJNTU1cIjpcbiAgICAgICAgICAgIC8vIGxpa2UgSmFuXG4gICAgICAgICAgICByZXR1cm4gbW9udGgoXCJzaG9ydFwiLCBmYWxzZSk7XG4gICAgICAgICAgY2FzZSBcIk1NTU1cIjpcbiAgICAgICAgICAgIC8vIGxpa2UgSmFudWFyeVxuICAgICAgICAgICAgcmV0dXJuIG1vbnRoKFwibG9uZ1wiLCBmYWxzZSk7XG4gICAgICAgICAgY2FzZSBcIk1NTU1NXCI6XG4gICAgICAgICAgICAvLyBsaWtlIEpcbiAgICAgICAgICAgIHJldHVybiBtb250aChcIm5hcnJvd1wiLCBmYWxzZSk7XG4gICAgICAgICAgLy8geWVhcnNcbiAgICAgICAgICBjYXNlIFwieVwiOlxuICAgICAgICAgICAgLy8gbGlrZSAyMDE0XG4gICAgICAgICAgICByZXR1cm4gdXNlRGF0ZVRpbWVGb3JtYXR0ZXIgPyBzdHJpbmcoeyB5ZWFyOiBcIm51bWVyaWNcIiB9LCBcInllYXJcIikgOiB0aGlzLm51bShkdC55ZWFyKTtcbiAgICAgICAgICBjYXNlIFwieXlcIjpcbiAgICAgICAgICAgIC8vIGxpa2UgMTRcbiAgICAgICAgICAgIHJldHVybiB1c2VEYXRlVGltZUZvcm1hdHRlclxuICAgICAgICAgICAgICA/IHN0cmluZyh7IHllYXI6IFwiMi1kaWdpdFwiIH0sIFwieWVhclwiKVxuICAgICAgICAgICAgICA6IHRoaXMubnVtKGR0LnllYXIudG9TdHJpbmcoKS5zbGljZSgtMiksIDIpO1xuICAgICAgICAgIGNhc2UgXCJ5eXl5XCI6XG4gICAgICAgICAgICAvLyBsaWtlIDAwMTJcbiAgICAgICAgICAgIHJldHVybiB1c2VEYXRlVGltZUZvcm1hdHRlclxuICAgICAgICAgICAgICA/IHN0cmluZyh7IHllYXI6IFwibnVtZXJpY1wiIH0sIFwieWVhclwiKVxuICAgICAgICAgICAgICA6IHRoaXMubnVtKGR0LnllYXIsIDQpO1xuICAgICAgICAgIGNhc2UgXCJ5eXl5eXlcIjpcbiAgICAgICAgICAgIC8vIGxpa2UgMDAwMDEyXG4gICAgICAgICAgICByZXR1cm4gdXNlRGF0ZVRpbWVGb3JtYXR0ZXJcbiAgICAgICAgICAgICAgPyBzdHJpbmcoeyB5ZWFyOiBcIm51bWVyaWNcIiB9LCBcInllYXJcIilcbiAgICAgICAgICAgICAgOiB0aGlzLm51bShkdC55ZWFyLCA2KTtcbiAgICAgICAgICAvLyBlcmFzXG4gICAgICAgICAgY2FzZSBcIkdcIjpcbiAgICAgICAgICAgIC8vIGxpa2UgQURcbiAgICAgICAgICAgIHJldHVybiBlcmEoXCJzaG9ydFwiKTtcbiAgICAgICAgICBjYXNlIFwiR0dcIjpcbiAgICAgICAgICAgIC8vIGxpa2UgQW5ubyBEb21pbmlcbiAgICAgICAgICAgIHJldHVybiBlcmEoXCJsb25nXCIpO1xuICAgICAgICAgIGNhc2UgXCJHR0dHR1wiOlxuICAgICAgICAgICAgcmV0dXJuIGVyYShcIm5hcnJvd1wiKTtcbiAgICAgICAgICBjYXNlIFwia2tcIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShkdC53ZWVrWWVhci50b1N0cmluZygpLnNsaWNlKC0yKSwgMik7XG4gICAgICAgICAgY2FzZSBcImtra2tcIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShkdC53ZWVrWWVhciwgNCk7XG4gICAgICAgICAgY2FzZSBcIldcIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShkdC53ZWVrTnVtYmVyKTtcbiAgICAgICAgICBjYXNlIFwiV1dcIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShkdC53ZWVrTnVtYmVyLCAyKTtcbiAgICAgICAgICBjYXNlIFwib1wiOlxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubnVtKGR0Lm9yZGluYWwpO1xuICAgICAgICAgIGNhc2UgXCJvb29cIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShkdC5vcmRpbmFsLCAzKTtcbiAgICAgICAgICBjYXNlIFwicVwiOlxuICAgICAgICAgICAgLy8gbGlrZSAxXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW0oZHQucXVhcnRlcik7XG4gICAgICAgICAgY2FzZSBcInFxXCI6XG4gICAgICAgICAgICAvLyBsaWtlIDAxXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW0oZHQucXVhcnRlciwgMik7XG4gICAgICAgICAgY2FzZSBcIlhcIjpcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm51bShNYXRoLmZsb29yKGR0LnRzIC8gMTAwMCkpO1xuICAgICAgICAgIGNhc2UgXCJ4XCI6XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5udW0oZHQudHMpO1xuICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICByZXR1cm4gbWF5YmVNYWNybyh0b2tlbik7XG4gICAgICAgIH1cbiAgICAgIH07XG5cbiAgICByZXR1cm4gc3RyaW5naWZ5VG9rZW5zKEZvcm1hdHRlci5wYXJzZUZvcm1hdChmbXQpLCB0b2tlblRvU3RyaW5nKTtcbiAgfVxuXG4gIGZvcm1hdER1cmF0aW9uRnJvbVN0cmluZyhkdXIsIGZtdCkge1xuICAgIGNvbnN0IHRva2VuVG9GaWVsZCA9ICh0b2tlbikgPT4ge1xuICAgICAgICBzd2l0Y2ggKHRva2VuWzBdKSB7XG4gICAgICAgICAgY2FzZSBcIlNcIjpcbiAgICAgICAgICAgIHJldHVybiBcIm1pbGxpc2Vjb25kXCI7XG4gICAgICAgICAgY2FzZSBcInNcIjpcbiAgICAgICAgICAgIHJldHVybiBcInNlY29uZFwiO1xuICAgICAgICAgIGNhc2UgXCJtXCI6XG4gICAgICAgICAgICByZXR1cm4gXCJtaW51dGVcIjtcbiAgICAgICAgICBjYXNlIFwiaFwiOlxuICAgICAgICAgICAgcmV0dXJuIFwiaG91clwiO1xuICAgICAgICAgIGNhc2UgXCJkXCI6XG4gICAgICAgICAgICByZXR1cm4gXCJkYXlcIjtcbiAgICAgICAgICBjYXNlIFwid1wiOlxuICAgICAgICAgICAgcmV0dXJuIFwid2Vla1wiO1xuICAgICAgICAgIGNhc2UgXCJNXCI6XG4gICAgICAgICAgICByZXR1cm4gXCJtb250aFwiO1xuICAgICAgICAgIGNhc2UgXCJ5XCI6XG4gICAgICAgICAgICByZXR1cm4gXCJ5ZWFyXCI7XG4gICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgdG9rZW5Ub1N0cmluZyA9IChsaWxkdXIpID0+ICh0b2tlbikgPT4ge1xuICAgICAgICBjb25zdCBtYXBwZWQgPSB0b2tlblRvRmllbGQodG9rZW4pO1xuICAgICAgICBpZiAobWFwcGVkKSB7XG4gICAgICAgICAgcmV0dXJuIHRoaXMubnVtKGxpbGR1ci5nZXQobWFwcGVkKSwgdG9rZW4ubGVuZ3RoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gdG9rZW47XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICB0b2tlbnMgPSBGb3JtYXR0ZXIucGFyc2VGb3JtYXQoZm10KSxcbiAgICAgIHJlYWxUb2tlbnMgPSB0b2tlbnMucmVkdWNlKFxuICAgICAgICAoZm91bmQsIHsgbGl0ZXJhbCwgdmFsIH0pID0+IChsaXRlcmFsID8gZm91bmQgOiBmb3VuZC5jb25jYXQodmFsKSksXG4gICAgICAgIFtdXG4gICAgICApLFxuICAgICAgY29sbGFwc2VkID0gZHVyLnNoaWZ0VG8oLi4ucmVhbFRva2Vucy5tYXAodG9rZW5Ub0ZpZWxkKS5maWx0ZXIoKHQpID0+IHQpKTtcbiAgICByZXR1cm4gc3RyaW5naWZ5VG9rZW5zKHRva2VucywgdG9rZW5Ub1N0cmluZyhjb2xsYXBzZWQpKTtcbiAgfVxufVxuIiwgImV4cG9ydCBkZWZhdWx0IGNsYXNzIEludmFsaWQge1xuICBjb25zdHJ1Y3RvcihyZWFzb24sIGV4cGxhbmF0aW9uKSB7XG4gICAgdGhpcy5yZWFzb24gPSByZWFzb247XG4gICAgdGhpcy5leHBsYW5hdGlvbiA9IGV4cGxhbmF0aW9uO1xuICB9XG5cbiAgdG9NZXNzYWdlKCkge1xuICAgIGlmICh0aGlzLmV4cGxhbmF0aW9uKSB7XG4gICAgICByZXR1cm4gYCR7dGhpcy5yZWFzb259OiAke3RoaXMuZXhwbGFuYXRpb259YDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMucmVhc29uO1xuICAgIH1cbiAgfVxufVxuIiwgImltcG9ydCB7XG4gIHVudHJ1bmNhdGVZZWFyLFxuICBzaWduZWRPZmZzZXQsXG4gIHBhcnNlSW50ZWdlcixcbiAgcGFyc2VNaWxsaXMsXG4gIGlzVW5kZWZpbmVkLFxuICBwYXJzZUZsb2F0aW5nLFxufSBmcm9tIFwiLi91dGlsLmpzXCI7XG5pbXBvcnQgKiBhcyBFbmdsaXNoIGZyb20gXCIuL2VuZ2xpc2guanNcIjtcbmltcG9ydCBGaXhlZE9mZnNldFpvbmUgZnJvbSBcIi4uL3pvbmVzL2ZpeGVkT2Zmc2V0Wm9uZS5qc1wiO1xuaW1wb3J0IElBTkFab25lIGZyb20gXCIuLi96b25lcy9JQU5BWm9uZS5qc1wiO1xuXG4vKlxuICogVGhpcyBmaWxlIGhhbmRsZXMgcGFyc2luZyBmb3Igd2VsbC1zcGVjaWZpZWQgZm9ybWF0cy4gSGVyZSdzIGhvdyBpdCB3b3JrczpcbiAqIFR3byB0aGluZ3MgZ28gaW50byBwYXJzaW5nOiBhIHJlZ2V4IHRvIG1hdGNoIHdpdGggYW5kIGFuIGV4dHJhY3RvciB0byB0YWtlIGFwYXJ0IHRoZSBncm91cHMgaW4gdGhlIG1hdGNoLlxuICogQW4gZXh0cmFjdG9yIGlzIGp1c3QgYSBmdW5jdGlvbiB0aGF0IHRha2VzIGEgcmVnZXggbWF0Y2ggYXJyYXkgYW5kIHJldHVybnMgYSB7IHllYXI6IC4uLiwgbW9udGg6IC4uLiB9IG9iamVjdFxuICogcGFyc2UoKSBkb2VzIHRoZSB3b3JrIG9mIGV4ZWN1dGluZyB0aGUgcmVnZXggYW5kIGFwcGx5aW5nIHRoZSBleHRyYWN0b3IuIEl0IHRha2VzIG11bHRpcGxlIHJlZ2V4L2V4dHJhY3RvciBwYWlycyB0byB0cnkgaW4gc2VxdWVuY2UuXG4gKiBFeHRyYWN0b3JzIGNhbiB0YWtlIGEgXCJjdXJzb3JcIiByZXByZXNlbnRpbmcgdGhlIG9mZnNldCBpbiB0aGUgbWF0Y2ggdG8gbG9vayBhdC4gVGhpcyBtYWtlcyBpdCBlYXN5IHRvIGNvbWJpbmUgZXh0cmFjdG9ycy5cbiAqIGNvbWJpbmVFeHRyYWN0b3JzKCkgZG9lcyB0aGUgd29yayBvZiBjb21iaW5pbmcgdGhlbSwga2VlcGluZyB0cmFjayBvZiB0aGUgY3Vyc29yIHRocm91Z2ggbXVsdGlwbGUgZXh0cmFjdGlvbnMuXG4gKiBTb21lIGV4dHJhY3Rpb25zIGFyZSBzdXBlciBkdW1iIGFuZCBzaW1wbGVQYXJzZSBhbmQgZnJvbVN0cmluZ3MgaGVscCBEUlkgdGhlbS5cbiAqL1xuXG5jb25zdCBpYW5hUmVnZXggPSAvW0EtWmEtel8rLV17MSwyNTZ9KD86Oj9cXC9bQS1aYS16MC05XystXXsxLDI1Nn0oPzpcXC9bQS1aYS16MC05XystXXsxLDI1Nn0pPyk/LztcblxuZnVuY3Rpb24gY29tYmluZVJlZ2V4ZXMoLi4ucmVnZXhlcykge1xuICBjb25zdCBmdWxsID0gcmVnZXhlcy5yZWR1Y2UoKGYsIHIpID0+IGYgKyByLnNvdXJjZSwgXCJcIik7XG4gIHJldHVybiBSZWdFeHAoYF4ke2Z1bGx9JGApO1xufVxuXG5mdW5jdGlvbiBjb21iaW5lRXh0cmFjdG9ycyguLi5leHRyYWN0b3JzKSB7XG4gIHJldHVybiAobSkgPT5cbiAgICBleHRyYWN0b3JzXG4gICAgICAucmVkdWNlKFxuICAgICAgICAoW21lcmdlZFZhbHMsIG1lcmdlZFpvbmUsIGN1cnNvcl0sIGV4KSA9PiB7XG4gICAgICAgICAgY29uc3QgW3ZhbCwgem9uZSwgbmV4dF0gPSBleChtLCBjdXJzb3IpO1xuICAgICAgICAgIHJldHVybiBbeyAuLi5tZXJnZWRWYWxzLCAuLi52YWwgfSwgem9uZSB8fCBtZXJnZWRab25lLCBuZXh0XTtcbiAgICAgICAgfSxcbiAgICAgICAgW3t9LCBudWxsLCAxXVxuICAgICAgKVxuICAgICAgLnNsaWNlKDAsIDIpO1xufVxuXG5mdW5jdGlvbiBwYXJzZShzLCAuLi5wYXR0ZXJucykge1xuICBpZiAocyA9PSBudWxsKSB7XG4gICAgcmV0dXJuIFtudWxsLCBudWxsXTtcbiAgfVxuXG4gIGZvciAoY29uc3QgW3JlZ2V4LCBleHRyYWN0b3JdIG9mIHBhdHRlcm5zKSB7XG4gICAgY29uc3QgbSA9IHJlZ2V4LmV4ZWMocyk7XG4gICAgaWYgKG0pIHtcbiAgICAgIHJldHVybiBleHRyYWN0b3IobSk7XG4gICAgfVxuICB9XG4gIHJldHVybiBbbnVsbCwgbnVsbF07XG59XG5cbmZ1bmN0aW9uIHNpbXBsZVBhcnNlKC4uLmtleXMpIHtcbiAgcmV0dXJuIChtYXRjaCwgY3Vyc29yKSA9PiB7XG4gICAgY29uc3QgcmV0ID0ge307XG4gICAgbGV0IGk7XG5cbiAgICBmb3IgKGkgPSAwOyBpIDwga2V5cy5sZW5ndGg7IGkrKykge1xuICAgICAgcmV0W2tleXNbaV1dID0gcGFyc2VJbnRlZ2VyKG1hdGNoW2N1cnNvciArIGldKTtcbiAgICB9XG4gICAgcmV0dXJuIFtyZXQsIG51bGwsIGN1cnNvciArIGldO1xuICB9O1xufVxuXG4vLyBJU08gYW5kIFNRTCBwYXJzaW5nXG5jb25zdCBvZmZzZXRSZWdleCA9IC8oPzooWil8KFsrLV1cXGRcXGQpKD86Oj8oXFxkXFxkKSk/KS87XG5jb25zdCBpc29FeHRlbmRlZFpvbmUgPSBgKD86JHtvZmZzZXRSZWdleC5zb3VyY2V9Pyg/OlxcXFxbKCR7aWFuYVJlZ2V4LnNvdXJjZX0pXFxcXF0pPyk/YDtcbmNvbnN0IGlzb1RpbWVCYXNlUmVnZXggPSAvKFxcZFxcZCkoPzo6PyhcXGRcXGQpKD86Oj8oXFxkXFxkKSg/OlsuLF0oXFxkezEsMzB9KSk/KT8pPy87XG5jb25zdCBpc29UaW1lUmVnZXggPSBSZWdFeHAoYCR7aXNvVGltZUJhc2VSZWdleC5zb3VyY2V9JHtpc29FeHRlbmRlZFpvbmV9YCk7XG5jb25zdCBpc29UaW1lRXh0ZW5zaW9uUmVnZXggPSBSZWdFeHAoYCg/OlQke2lzb1RpbWVSZWdleC5zb3VyY2V9KT9gKTtcbmNvbnN0IGlzb1ltZFJlZ2V4ID0gLyhbKy1dXFxkezZ9fFxcZHs0fSkoPzotPyhcXGRcXGQpKD86LT8oXFxkXFxkKSk/KT8vO1xuY29uc3QgaXNvV2Vla1JlZ2V4ID0gLyhcXGR7NH0pLT9XKFxcZFxcZCkoPzotPyhcXGQpKT8vO1xuY29uc3QgaXNvT3JkaW5hbFJlZ2V4ID0gLyhcXGR7NH0pLT8oXFxkezN9KS87XG5jb25zdCBleHRyYWN0SVNPV2Vla0RhdGEgPSBzaW1wbGVQYXJzZShcIndlZWtZZWFyXCIsIFwid2Vla051bWJlclwiLCBcIndlZWtEYXlcIik7XG5jb25zdCBleHRyYWN0SVNPT3JkaW5hbERhdGEgPSBzaW1wbGVQYXJzZShcInllYXJcIiwgXCJvcmRpbmFsXCIpO1xuY29uc3Qgc3FsWW1kUmVnZXggPSAvKFxcZHs0fSktKFxcZFxcZCktKFxcZFxcZCkvOyAvLyBkdW1iZWQtZG93biB2ZXJzaW9uIG9mIHRoZSBJU08gb25lXG5jb25zdCBzcWxUaW1lUmVnZXggPSBSZWdFeHAoXG4gIGAke2lzb1RpbWVCYXNlUmVnZXguc291cmNlfSA/KD86JHtvZmZzZXRSZWdleC5zb3VyY2V9fCgke2lhbmFSZWdleC5zb3VyY2V9KSk/YFxuKTtcbmNvbnN0IHNxbFRpbWVFeHRlbnNpb25SZWdleCA9IFJlZ0V4cChgKD86ICR7c3FsVGltZVJlZ2V4LnNvdXJjZX0pP2ApO1xuXG5mdW5jdGlvbiBpbnQobWF0Y2gsIHBvcywgZmFsbGJhY2spIHtcbiAgY29uc3QgbSA9IG1hdGNoW3Bvc107XG4gIHJldHVybiBpc1VuZGVmaW5lZChtKSA/IGZhbGxiYWNrIDogcGFyc2VJbnRlZ2VyKG0pO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0SVNPWW1kKG1hdGNoLCBjdXJzb3IpIHtcbiAgY29uc3QgaXRlbSA9IHtcbiAgICB5ZWFyOiBpbnQobWF0Y2gsIGN1cnNvciksXG4gICAgbW9udGg6IGludChtYXRjaCwgY3Vyc29yICsgMSwgMSksXG4gICAgZGF5OiBpbnQobWF0Y2gsIGN1cnNvciArIDIsIDEpLFxuICB9O1xuXG4gIHJldHVybiBbaXRlbSwgbnVsbCwgY3Vyc29yICsgM107XG59XG5cbmZ1bmN0aW9uIGV4dHJhY3RJU09UaW1lKG1hdGNoLCBjdXJzb3IpIHtcbiAgY29uc3QgaXRlbSA9IHtcbiAgICBob3VyczogaW50KG1hdGNoLCBjdXJzb3IsIDApLFxuICAgIG1pbnV0ZXM6IGludChtYXRjaCwgY3Vyc29yICsgMSwgMCksXG4gICAgc2Vjb25kczogaW50KG1hdGNoLCBjdXJzb3IgKyAyLCAwKSxcbiAgICBtaWxsaXNlY29uZHM6IHBhcnNlTWlsbGlzKG1hdGNoW2N1cnNvciArIDNdKSxcbiAgfTtcblxuICByZXR1cm4gW2l0ZW0sIG51bGwsIGN1cnNvciArIDRdO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0SVNPT2Zmc2V0KG1hdGNoLCBjdXJzb3IpIHtcbiAgY29uc3QgbG9jYWwgPSAhbWF0Y2hbY3Vyc29yXSAmJiAhbWF0Y2hbY3Vyc29yICsgMV0sXG4gICAgZnVsbE9mZnNldCA9IHNpZ25lZE9mZnNldChtYXRjaFtjdXJzb3IgKyAxXSwgbWF0Y2hbY3Vyc29yICsgMl0pLFxuICAgIHpvbmUgPSBsb2NhbCA/IG51bGwgOiBGaXhlZE9mZnNldFpvbmUuaW5zdGFuY2UoZnVsbE9mZnNldCk7XG4gIHJldHVybiBbe30sIHpvbmUsIGN1cnNvciArIDNdO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0SUFOQVpvbmUobWF0Y2gsIGN1cnNvcikge1xuICBjb25zdCB6b25lID0gbWF0Y2hbY3Vyc29yXSA/IElBTkFab25lLmNyZWF0ZShtYXRjaFtjdXJzb3JdKSA6IG51bGw7XG4gIHJldHVybiBbe30sIHpvbmUsIGN1cnNvciArIDFdO1xufVxuXG4vLyBJU08gdGltZSBwYXJzaW5nXG5cbmNvbnN0IGlzb1RpbWVPbmx5ID0gUmVnRXhwKGBeVD8ke2lzb1RpbWVCYXNlUmVnZXguc291cmNlfSRgKTtcblxuLy8gSVNPIGR1cmF0aW9uIHBhcnNpbmdcblxuY29uc3QgaXNvRHVyYXRpb24gPVxuICAvXi0/UCg/Oig/OigtP1xcZHsxLDIwfSg/OlxcLlxcZHsxLDIwfSk/KVkpPyg/OigtP1xcZHsxLDIwfSg/OlxcLlxcZHsxLDIwfSk/KU0pPyg/OigtP1xcZHsxLDIwfSg/OlxcLlxcZHsxLDIwfSk/KVcpPyg/OigtP1xcZHsxLDIwfSg/OlxcLlxcZHsxLDIwfSk/KUQpPyg/OlQoPzooLT9cXGR7MSwyMH0oPzpcXC5cXGR7MSwyMH0pPylIKT8oPzooLT9cXGR7MSwyMH0oPzpcXC5cXGR7MSwyMH0pPylNKT8oPzooLT9cXGR7MSwyMH0pKD86Wy4sXSgtP1xcZHsxLDIwfSkpP1MpPyk/KSQvO1xuXG5mdW5jdGlvbiBleHRyYWN0SVNPRHVyYXRpb24obWF0Y2gpIHtcbiAgY29uc3QgW3MsIHllYXJTdHIsIG1vbnRoU3RyLCB3ZWVrU3RyLCBkYXlTdHIsIGhvdXJTdHIsIG1pbnV0ZVN0ciwgc2Vjb25kU3RyLCBtaWxsaXNlY29uZHNTdHJdID1cbiAgICBtYXRjaDtcblxuICBjb25zdCBoYXNOZWdhdGl2ZVByZWZpeCA9IHNbMF0gPT09IFwiLVwiO1xuICBjb25zdCBuZWdhdGl2ZVNlY29uZHMgPSBzZWNvbmRTdHIgJiYgc2Vjb25kU3RyWzBdID09PSBcIi1cIjtcblxuICBjb25zdCBtYXliZU5lZ2F0ZSA9IChudW0sIGZvcmNlID0gZmFsc2UpID0+XG4gICAgbnVtICE9PSB1bmRlZmluZWQgJiYgKGZvcmNlIHx8IChudW0gJiYgaGFzTmVnYXRpdmVQcmVmaXgpKSA/IC1udW0gOiBudW07XG5cbiAgcmV0dXJuIFtcbiAgICB7XG4gICAgICB5ZWFyczogbWF5YmVOZWdhdGUocGFyc2VGbG9hdGluZyh5ZWFyU3RyKSksXG4gICAgICBtb250aHM6IG1heWJlTmVnYXRlKHBhcnNlRmxvYXRpbmcobW9udGhTdHIpKSxcbiAgICAgIHdlZWtzOiBtYXliZU5lZ2F0ZShwYXJzZUZsb2F0aW5nKHdlZWtTdHIpKSxcbiAgICAgIGRheXM6IG1heWJlTmVnYXRlKHBhcnNlRmxvYXRpbmcoZGF5U3RyKSksXG4gICAgICBob3VyczogbWF5YmVOZWdhdGUocGFyc2VGbG9hdGluZyhob3VyU3RyKSksXG4gICAgICBtaW51dGVzOiBtYXliZU5lZ2F0ZShwYXJzZUZsb2F0aW5nKG1pbnV0ZVN0cikpLFxuICAgICAgc2Vjb25kczogbWF5YmVOZWdhdGUocGFyc2VGbG9hdGluZyhzZWNvbmRTdHIpLCBzZWNvbmRTdHIgPT09IFwiLTBcIiksXG4gICAgICBtaWxsaXNlY29uZHM6IG1heWJlTmVnYXRlKHBhcnNlTWlsbGlzKG1pbGxpc2Vjb25kc1N0ciksIG5lZ2F0aXZlU2Vjb25kcyksXG4gICAgfSxcbiAgXTtcbn1cblxuLy8gVGhlc2UgYXJlIGEgbGl0dGxlIGJyYWluZGVhZC4gRURUICpzaG91bGQqIHRlbGwgdXMgdGhhdCB3ZSdyZSBpbiwgc2F5LCBBbWVyaWNhL05ld19Zb3JrXG4vLyBhbmQgbm90IGp1c3QgdGhhdCB3ZSdyZSBpbiAtMjQwICpyaWdodCBub3cqLiBCdXQgc2luY2UgSSBkb24ndCB0aGluayB0aGVzZSBhcmUgdXNlZCB0aGF0IG9mdGVuXG4vLyBJJ20ganVzdCBnb2luZyB0byBpZ25vcmUgdGhhdFxuY29uc3Qgb2JzT2Zmc2V0cyA9IHtcbiAgR01UOiAwLFxuICBFRFQ6IC00ICogNjAsXG4gIEVTVDogLTUgKiA2MCxcbiAgQ0RUOiAtNSAqIDYwLFxuICBDU1Q6IC02ICogNjAsXG4gIE1EVDogLTYgKiA2MCxcbiAgTVNUOiAtNyAqIDYwLFxuICBQRFQ6IC03ICogNjAsXG4gIFBTVDogLTggKiA2MCxcbn07XG5cbmZ1bmN0aW9uIGZyb21TdHJpbmdzKHdlZWtkYXlTdHIsIHllYXJTdHIsIG1vbnRoU3RyLCBkYXlTdHIsIGhvdXJTdHIsIG1pbnV0ZVN0ciwgc2Vjb25kU3RyKSB7XG4gIGNvbnN0IHJlc3VsdCA9IHtcbiAgICB5ZWFyOiB5ZWFyU3RyLmxlbmd0aCA9PT0gMiA/IHVudHJ1bmNhdGVZZWFyKHBhcnNlSW50ZWdlcih5ZWFyU3RyKSkgOiBwYXJzZUludGVnZXIoeWVhclN0ciksXG4gICAgbW9udGg6IEVuZ2xpc2gubW9udGhzU2hvcnQuaW5kZXhPZihtb250aFN0cikgKyAxLFxuICAgIGRheTogcGFyc2VJbnRlZ2VyKGRheVN0ciksXG4gICAgaG91cjogcGFyc2VJbnRlZ2VyKGhvdXJTdHIpLFxuICAgIG1pbnV0ZTogcGFyc2VJbnRlZ2VyKG1pbnV0ZVN0ciksXG4gIH07XG5cbiAgaWYgKHNlY29uZFN0cikgcmVzdWx0LnNlY29uZCA9IHBhcnNlSW50ZWdlcihzZWNvbmRTdHIpO1xuICBpZiAod2Vla2RheVN0cikge1xuICAgIHJlc3VsdC53ZWVrZGF5ID1cbiAgICAgIHdlZWtkYXlTdHIubGVuZ3RoID4gM1xuICAgICAgICA/IEVuZ2xpc2gud2Vla2RheXNMb25nLmluZGV4T2Yod2Vla2RheVN0cikgKyAxXG4gICAgICAgIDogRW5nbGlzaC53ZWVrZGF5c1Nob3J0LmluZGV4T2Yod2Vla2RheVN0cikgKyAxO1xuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLy8gUkZDIDI4MjIvNTMyMlxuY29uc3QgcmZjMjgyMiA9XG4gIC9eKD86KE1vbnxUdWV8V2VkfFRodXxGcml8U2F0fFN1biksXFxzKT8oXFxkezEsMn0pXFxzKEphbnxGZWJ8TWFyfEFwcnxNYXl8SnVufEp1bHxBdWd8U2VwfE9jdHxOb3Z8RGVjKVxccyhcXGR7Miw0fSlcXHMoXFxkXFxkKTooXFxkXFxkKSg/OjooXFxkXFxkKSk/XFxzKD86KFVUfEdNVHxbRUNNUF1bU0RdVCl8KFtael0pfCg/OihbKy1dXFxkXFxkKShcXGRcXGQpKSkkLztcblxuZnVuY3Rpb24gZXh0cmFjdFJGQzI4MjIobWF0Y2gpIHtcbiAgY29uc3QgW1xuICAgICAgLFxuICAgICAgd2Vla2RheVN0cixcbiAgICAgIGRheVN0cixcbiAgICAgIG1vbnRoU3RyLFxuICAgICAgeWVhclN0cixcbiAgICAgIGhvdXJTdHIsXG4gICAgICBtaW51dGVTdHIsXG4gICAgICBzZWNvbmRTdHIsXG4gICAgICBvYnNPZmZzZXQsXG4gICAgICBtaWxPZmZzZXQsXG4gICAgICBvZmZIb3VyU3RyLFxuICAgICAgb2ZmTWludXRlU3RyLFxuICAgIF0gPSBtYXRjaCxcbiAgICByZXN1bHQgPSBmcm9tU3RyaW5ncyh3ZWVrZGF5U3RyLCB5ZWFyU3RyLCBtb250aFN0ciwgZGF5U3RyLCBob3VyU3RyLCBtaW51dGVTdHIsIHNlY29uZFN0cik7XG5cbiAgbGV0IG9mZnNldDtcbiAgaWYgKG9ic09mZnNldCkge1xuICAgIG9mZnNldCA9IG9ic09mZnNldHNbb2JzT2Zmc2V0XTtcbiAgfSBlbHNlIGlmIChtaWxPZmZzZXQpIHtcbiAgICBvZmZzZXQgPSAwO1xuICB9IGVsc2Uge1xuICAgIG9mZnNldCA9IHNpZ25lZE9mZnNldChvZmZIb3VyU3RyLCBvZmZNaW51dGVTdHIpO1xuICB9XG5cbiAgcmV0dXJuIFtyZXN1bHQsIG5ldyBGaXhlZE9mZnNldFpvbmUob2Zmc2V0KV07XG59XG5cbmZ1bmN0aW9uIHByZXByb2Nlc3NSRkMyODIyKHMpIHtcbiAgLy8gUmVtb3ZlIGNvbW1lbnRzIGFuZCBmb2xkaW5nIHdoaXRlc3BhY2UgYW5kIHJlcGxhY2UgbXVsdGlwbGUtc3BhY2VzIHdpdGggYSBzaW5nbGUgc3BhY2VcbiAgcmV0dXJuIHNcbiAgICAucmVwbGFjZSgvXFwoW14oKV0qXFwpfFtcXG5cXHRdL2csIFwiIFwiKVxuICAgIC5yZXBsYWNlKC8oXFxzXFxzKykvZywgXCIgXCIpXG4gICAgLnRyaW0oKTtcbn1cblxuLy8gaHR0cCBkYXRlXG5cbmNvbnN0IHJmYzExMjMgPVxuICAgIC9eKE1vbnxUdWV8V2VkfFRodXxGcml8U2F0fFN1biksIChcXGRcXGQpIChKYW58RmVifE1hcnxBcHJ8TWF5fEp1bnxKdWx8QXVnfFNlcHxPY3R8Tm92fERlYykgKFxcZHs0fSkgKFxcZFxcZCk6KFxcZFxcZCk6KFxcZFxcZCkgR01UJC8sXG4gIHJmYzg1MCA9XG4gICAgL14oTW9uZGF5fFR1ZXNkYXl8V2VkbmVzZGF5fFRodXJzZGF5fEZyaWRheXxTYXR1cmRheXxTdW5kYXkpLCAoXFxkXFxkKS0oSmFufEZlYnxNYXJ8QXByfE1heXxKdW58SnVsfEF1Z3xTZXB8T2N0fE5vdnxEZWMpLShcXGRcXGQpIChcXGRcXGQpOihcXGRcXGQpOihcXGRcXGQpIEdNVCQvLFxuICBhc2NpaSA9XG4gICAgL14oTW9ufFR1ZXxXZWR8VGh1fEZyaXxTYXR8U3VuKSAoSmFufEZlYnxNYXJ8QXByfE1heXxKdW58SnVsfEF1Z3xTZXB8T2N0fE5vdnxEZWMpICggXFxkfFxcZFxcZCkgKFxcZFxcZCk6KFxcZFxcZCk6KFxcZFxcZCkgKFxcZHs0fSkkLztcblxuZnVuY3Rpb24gZXh0cmFjdFJGQzExMjNPcjg1MChtYXRjaCkge1xuICBjb25zdCBbLCB3ZWVrZGF5U3RyLCBkYXlTdHIsIG1vbnRoU3RyLCB5ZWFyU3RyLCBob3VyU3RyLCBtaW51dGVTdHIsIHNlY29uZFN0cl0gPSBtYXRjaCxcbiAgICByZXN1bHQgPSBmcm9tU3RyaW5ncyh3ZWVrZGF5U3RyLCB5ZWFyU3RyLCBtb250aFN0ciwgZGF5U3RyLCBob3VyU3RyLCBtaW51dGVTdHIsIHNlY29uZFN0cik7XG4gIHJldHVybiBbcmVzdWx0LCBGaXhlZE9mZnNldFpvbmUudXRjSW5zdGFuY2VdO1xufVxuXG5mdW5jdGlvbiBleHRyYWN0QVNDSUkobWF0Y2gpIHtcbiAgY29uc3QgWywgd2Vla2RheVN0ciwgbW9udGhTdHIsIGRheVN0ciwgaG91clN0ciwgbWludXRlU3RyLCBzZWNvbmRTdHIsIHllYXJTdHJdID0gbWF0Y2gsXG4gICAgcmVzdWx0ID0gZnJvbVN0cmluZ3Mod2Vla2RheVN0ciwgeWVhclN0ciwgbW9udGhTdHIsIGRheVN0ciwgaG91clN0ciwgbWludXRlU3RyLCBzZWNvbmRTdHIpO1xuICByZXR1cm4gW3Jlc3VsdCwgRml4ZWRPZmZzZXRab25lLnV0Y0luc3RhbmNlXTtcbn1cblxuY29uc3QgaXNvWW1kV2l0aFRpbWVFeHRlbnNpb25SZWdleCA9IGNvbWJpbmVSZWdleGVzKGlzb1ltZFJlZ2V4LCBpc29UaW1lRXh0ZW5zaW9uUmVnZXgpO1xuY29uc3QgaXNvV2Vla1dpdGhUaW1lRXh0ZW5zaW9uUmVnZXggPSBjb21iaW5lUmVnZXhlcyhpc29XZWVrUmVnZXgsIGlzb1RpbWVFeHRlbnNpb25SZWdleCk7XG5jb25zdCBpc29PcmRpbmFsV2l0aFRpbWVFeHRlbnNpb25SZWdleCA9IGNvbWJpbmVSZWdleGVzKGlzb09yZGluYWxSZWdleCwgaXNvVGltZUV4dGVuc2lvblJlZ2V4KTtcbmNvbnN0IGlzb1RpbWVDb21iaW5lZFJlZ2V4ID0gY29tYmluZVJlZ2V4ZXMoaXNvVGltZVJlZ2V4KTtcblxuY29uc3QgZXh0cmFjdElTT1ltZFRpbWVBbmRPZmZzZXQgPSBjb21iaW5lRXh0cmFjdG9ycyhcbiAgZXh0cmFjdElTT1ltZCxcbiAgZXh0cmFjdElTT1RpbWUsXG4gIGV4dHJhY3RJU09PZmZzZXQsXG4gIGV4dHJhY3RJQU5BWm9uZVxuKTtcbmNvbnN0IGV4dHJhY3RJU09XZWVrVGltZUFuZE9mZnNldCA9IGNvbWJpbmVFeHRyYWN0b3JzKFxuICBleHRyYWN0SVNPV2Vla0RhdGEsXG4gIGV4dHJhY3RJU09UaW1lLFxuICBleHRyYWN0SVNPT2Zmc2V0LFxuICBleHRyYWN0SUFOQVpvbmVcbik7XG5jb25zdCBleHRyYWN0SVNPT3JkaW5hbERhdGVBbmRUaW1lID0gY29tYmluZUV4dHJhY3RvcnMoXG4gIGV4dHJhY3RJU09PcmRpbmFsRGF0YSxcbiAgZXh0cmFjdElTT1RpbWUsXG4gIGV4dHJhY3RJU09PZmZzZXQsXG4gIGV4dHJhY3RJQU5BWm9uZVxuKTtcbmNvbnN0IGV4dHJhY3RJU09UaW1lQW5kT2Zmc2V0ID0gY29tYmluZUV4dHJhY3RvcnMoXG4gIGV4dHJhY3RJU09UaW1lLFxuICBleHRyYWN0SVNPT2Zmc2V0LFxuICBleHRyYWN0SUFOQVpvbmVcbik7XG5cbi8qXG4gKiBAcHJpdmF0ZVxuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUlTT0RhdGUocykge1xuICByZXR1cm4gcGFyc2UoXG4gICAgcyxcbiAgICBbaXNvWW1kV2l0aFRpbWVFeHRlbnNpb25SZWdleCwgZXh0cmFjdElTT1ltZFRpbWVBbmRPZmZzZXRdLFxuICAgIFtpc29XZWVrV2l0aFRpbWVFeHRlbnNpb25SZWdleCwgZXh0cmFjdElTT1dlZWtUaW1lQW5kT2Zmc2V0XSxcbiAgICBbaXNvT3JkaW5hbFdpdGhUaW1lRXh0ZW5zaW9uUmVnZXgsIGV4dHJhY3RJU09PcmRpbmFsRGF0ZUFuZFRpbWVdLFxuICAgIFtpc29UaW1lQ29tYmluZWRSZWdleCwgZXh0cmFjdElTT1RpbWVBbmRPZmZzZXRdXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVJGQzI4MjJEYXRlKHMpIHtcbiAgcmV0dXJuIHBhcnNlKHByZXByb2Nlc3NSRkMyODIyKHMpLCBbcmZjMjgyMiwgZXh0cmFjdFJGQzI4MjJdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlSFRUUERhdGUocykge1xuICByZXR1cm4gcGFyc2UoXG4gICAgcyxcbiAgICBbcmZjMTEyMywgZXh0cmFjdFJGQzExMjNPcjg1MF0sXG4gICAgW3JmYzg1MCwgZXh0cmFjdFJGQzExMjNPcjg1MF0sXG4gICAgW2FzY2lpLCBleHRyYWN0QVNDSUldXG4gICk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUlTT0R1cmF0aW9uKHMpIHtcbiAgcmV0dXJuIHBhcnNlKHMsIFtpc29EdXJhdGlvbiwgZXh0cmFjdElTT0R1cmF0aW9uXSk7XG59XG5cbmNvbnN0IGV4dHJhY3RJU09UaW1lT25seSA9IGNvbWJpbmVFeHRyYWN0b3JzKGV4dHJhY3RJU09UaW1lKTtcblxuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlSVNPVGltZU9ubHkocykge1xuICByZXR1cm4gcGFyc2UocywgW2lzb1RpbWVPbmx5LCBleHRyYWN0SVNPVGltZU9ubHldKTtcbn1cblxuY29uc3Qgc3FsWW1kV2l0aFRpbWVFeHRlbnNpb25SZWdleCA9IGNvbWJpbmVSZWdleGVzKHNxbFltZFJlZ2V4LCBzcWxUaW1lRXh0ZW5zaW9uUmVnZXgpO1xuY29uc3Qgc3FsVGltZUNvbWJpbmVkUmVnZXggPSBjb21iaW5lUmVnZXhlcyhzcWxUaW1lUmVnZXgpO1xuXG5jb25zdCBleHRyYWN0SVNPVGltZU9mZnNldEFuZElBTkFab25lID0gY29tYmluZUV4dHJhY3RvcnMoXG4gIGV4dHJhY3RJU09UaW1lLFxuICBleHRyYWN0SVNPT2Zmc2V0LFxuICBleHRyYWN0SUFOQVpvbmVcbik7XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZVNRTChzKSB7XG4gIHJldHVybiBwYXJzZShcbiAgICBzLFxuICAgIFtzcWxZbWRXaXRoVGltZUV4dGVuc2lvblJlZ2V4LCBleHRyYWN0SVNPWW1kVGltZUFuZE9mZnNldF0sXG4gICAgW3NxbFRpbWVDb21iaW5lZFJlZ2V4LCBleHRyYWN0SVNPVGltZU9mZnNldEFuZElBTkFab25lXVxuICApO1xufVxuIiwgImltcG9ydCB7IEludmFsaWRBcmd1bWVudEVycm9yLCBJbnZhbGlkRHVyYXRpb25FcnJvciwgSW52YWxpZFVuaXRFcnJvciB9IGZyb20gXCIuL2Vycm9ycy5qc1wiO1xuaW1wb3J0IEZvcm1hdHRlciBmcm9tIFwiLi9pbXBsL2Zvcm1hdHRlci5qc1wiO1xuaW1wb3J0IEludmFsaWQgZnJvbSBcIi4vaW1wbC9pbnZhbGlkLmpzXCI7XG5pbXBvcnQgTG9jYWxlIGZyb20gXCIuL2ltcGwvbG9jYWxlLmpzXCI7XG5pbXBvcnQgeyBwYXJzZUlTT0R1cmF0aW9uLCBwYXJzZUlTT1RpbWVPbmx5IH0gZnJvbSBcIi4vaW1wbC9yZWdleFBhcnNlci5qc1wiO1xuaW1wb3J0IHtcbiAgYXNOdW1iZXIsXG4gIGhhc093blByb3BlcnR5LFxuICBpc051bWJlcixcbiAgaXNVbmRlZmluZWQsXG4gIG5vcm1hbGl6ZU9iamVjdCxcbiAgcm91bmRUbyxcbn0gZnJvbSBcIi4vaW1wbC91dGlsLmpzXCI7XG5pbXBvcnQgU2V0dGluZ3MgZnJvbSBcIi4vc2V0dGluZ3MuanNcIjtcblxuY29uc3QgSU5WQUxJRCA9IFwiSW52YWxpZCBEdXJhdGlvblwiO1xuXG4vLyB1bml0IGNvbnZlcnNpb24gY29uc3RhbnRzXG5leHBvcnQgY29uc3QgbG93T3JkZXJNYXRyaXggPSB7XG4gICAgd2Vla3M6IHtcbiAgICAgIGRheXM6IDcsXG4gICAgICBob3VyczogNyAqIDI0LFxuICAgICAgbWludXRlczogNyAqIDI0ICogNjAsXG4gICAgICBzZWNvbmRzOiA3ICogMjQgKiA2MCAqIDYwLFxuICAgICAgbWlsbGlzZWNvbmRzOiA3ICogMjQgKiA2MCAqIDYwICogMTAwMCxcbiAgICB9LFxuICAgIGRheXM6IHtcbiAgICAgIGhvdXJzOiAyNCxcbiAgICAgIG1pbnV0ZXM6IDI0ICogNjAsXG4gICAgICBzZWNvbmRzOiAyNCAqIDYwICogNjAsXG4gICAgICBtaWxsaXNlY29uZHM6IDI0ICogNjAgKiA2MCAqIDEwMDAsXG4gICAgfSxcbiAgICBob3VyczogeyBtaW51dGVzOiA2MCwgc2Vjb25kczogNjAgKiA2MCwgbWlsbGlzZWNvbmRzOiA2MCAqIDYwICogMTAwMCB9LFxuICAgIG1pbnV0ZXM6IHsgc2Vjb25kczogNjAsIG1pbGxpc2Vjb25kczogNjAgKiAxMDAwIH0sXG4gICAgc2Vjb25kczogeyBtaWxsaXNlY29uZHM6IDEwMDAgfSxcbiAgfSxcbiAgY2FzdWFsTWF0cml4ID0ge1xuICAgIHllYXJzOiB7XG4gICAgICBxdWFydGVyczogNCxcbiAgICAgIG1vbnRoczogMTIsXG4gICAgICB3ZWVrczogNTIsXG4gICAgICBkYXlzOiAzNjUsXG4gICAgICBob3VyczogMzY1ICogMjQsXG4gICAgICBtaW51dGVzOiAzNjUgKiAyNCAqIDYwLFxuICAgICAgc2Vjb25kczogMzY1ICogMjQgKiA2MCAqIDYwLFxuICAgICAgbWlsbGlzZWNvbmRzOiAzNjUgKiAyNCAqIDYwICogNjAgKiAxMDAwLFxuICAgIH0sXG4gICAgcXVhcnRlcnM6IHtcbiAgICAgIG1vbnRoczogMyxcbiAgICAgIHdlZWtzOiAxMyxcbiAgICAgIGRheXM6IDkxLFxuICAgICAgaG91cnM6IDkxICogMjQsXG4gICAgICBtaW51dGVzOiA5MSAqIDI0ICogNjAsXG4gICAgICBzZWNvbmRzOiA5MSAqIDI0ICogNjAgKiA2MCxcbiAgICAgIG1pbGxpc2Vjb25kczogOTEgKiAyNCAqIDYwICogNjAgKiAxMDAwLFxuICAgIH0sXG4gICAgbW9udGhzOiB7XG4gICAgICB3ZWVrczogNCxcbiAgICAgIGRheXM6IDMwLFxuICAgICAgaG91cnM6IDMwICogMjQsXG4gICAgICBtaW51dGVzOiAzMCAqIDI0ICogNjAsXG4gICAgICBzZWNvbmRzOiAzMCAqIDI0ICogNjAgKiA2MCxcbiAgICAgIG1pbGxpc2Vjb25kczogMzAgKiAyNCAqIDYwICogNjAgKiAxMDAwLFxuICAgIH0sXG5cbiAgICAuLi5sb3dPcmRlck1hdHJpeCxcbiAgfSxcbiAgZGF5c0luWWVhckFjY3VyYXRlID0gMTQ2MDk3LjAgLyA0MDAsXG4gIGRheXNJbk1vbnRoQWNjdXJhdGUgPSAxNDYwOTcuMCAvIDQ4MDAsXG4gIGFjY3VyYXRlTWF0cml4ID0ge1xuICAgIHllYXJzOiB7XG4gICAgICBxdWFydGVyczogNCxcbiAgICAgIG1vbnRoczogMTIsXG4gICAgICB3ZWVrczogZGF5c0luWWVhckFjY3VyYXRlIC8gNyxcbiAgICAgIGRheXM6IGRheXNJblllYXJBY2N1cmF0ZSxcbiAgICAgIGhvdXJzOiBkYXlzSW5ZZWFyQWNjdXJhdGUgKiAyNCxcbiAgICAgIG1pbnV0ZXM6IGRheXNJblllYXJBY2N1cmF0ZSAqIDI0ICogNjAsXG4gICAgICBzZWNvbmRzOiBkYXlzSW5ZZWFyQWNjdXJhdGUgKiAyNCAqIDYwICogNjAsXG4gICAgICBtaWxsaXNlY29uZHM6IGRheXNJblllYXJBY2N1cmF0ZSAqIDI0ICogNjAgKiA2MCAqIDEwMDAsXG4gICAgfSxcbiAgICBxdWFydGVyczoge1xuICAgICAgbW9udGhzOiAzLFxuICAgICAgd2Vla3M6IGRheXNJblllYXJBY2N1cmF0ZSAvIDI4LFxuICAgICAgZGF5czogZGF5c0luWWVhckFjY3VyYXRlIC8gNCxcbiAgICAgIGhvdXJzOiAoZGF5c0luWWVhckFjY3VyYXRlICogMjQpIC8gNCxcbiAgICAgIG1pbnV0ZXM6IChkYXlzSW5ZZWFyQWNjdXJhdGUgKiAyNCAqIDYwKSAvIDQsXG4gICAgICBzZWNvbmRzOiAoZGF5c0luWWVhckFjY3VyYXRlICogMjQgKiA2MCAqIDYwKSAvIDQsXG4gICAgICBtaWxsaXNlY29uZHM6IChkYXlzSW5ZZWFyQWNjdXJhdGUgKiAyNCAqIDYwICogNjAgKiAxMDAwKSAvIDQsXG4gICAgfSxcbiAgICBtb250aHM6IHtcbiAgICAgIHdlZWtzOiBkYXlzSW5Nb250aEFjY3VyYXRlIC8gNyxcbiAgICAgIGRheXM6IGRheXNJbk1vbnRoQWNjdXJhdGUsXG4gICAgICBob3VyczogZGF5c0luTW9udGhBY2N1cmF0ZSAqIDI0LFxuICAgICAgbWludXRlczogZGF5c0luTW9udGhBY2N1cmF0ZSAqIDI0ICogNjAsXG4gICAgICBzZWNvbmRzOiBkYXlzSW5Nb250aEFjY3VyYXRlICogMjQgKiA2MCAqIDYwLFxuICAgICAgbWlsbGlzZWNvbmRzOiBkYXlzSW5Nb250aEFjY3VyYXRlICogMjQgKiA2MCAqIDYwICogMTAwMCxcbiAgICB9LFxuICAgIC4uLmxvd09yZGVyTWF0cml4LFxuICB9O1xuXG4vLyB1bml0cyBvcmRlcmVkIGJ5IHNpemVcbmNvbnN0IG9yZGVyZWRVbml0cyA9IFtcbiAgXCJ5ZWFyc1wiLFxuICBcInF1YXJ0ZXJzXCIsXG4gIFwibW9udGhzXCIsXG4gIFwid2Vla3NcIixcbiAgXCJkYXlzXCIsXG4gIFwiaG91cnNcIixcbiAgXCJtaW51dGVzXCIsXG4gIFwic2Vjb25kc1wiLFxuICBcIm1pbGxpc2Vjb25kc1wiLFxuXTtcblxuY29uc3QgcmV2ZXJzZVVuaXRzID0gb3JkZXJlZFVuaXRzLnNsaWNlKDApLnJldmVyc2UoKTtcblxuLy8gY2xvbmUgcmVhbGx5IG1lYW5zIFwiY3JlYXRlIGFub3RoZXIgaW5zdGFuY2UganVzdCBsaWtlIHRoaXMgb25lLCBidXQgd2l0aCB0aGVzZSBjaGFuZ2VzXCJcbmZ1bmN0aW9uIGNsb25lKGR1ciwgYWx0cywgY2xlYXIgPSBmYWxzZSkge1xuICAvLyBkZWVwIG1lcmdlIGZvciB2YWxzXG4gIGNvbnN0IGNvbmYgPSB7XG4gICAgdmFsdWVzOiBjbGVhciA/IGFsdHMudmFsdWVzIDogeyAuLi5kdXIudmFsdWVzLCAuLi4oYWx0cy52YWx1ZXMgfHwge30pIH0sXG4gICAgbG9jOiBkdXIubG9jLmNsb25lKGFsdHMubG9jKSxcbiAgICBjb252ZXJzaW9uQWNjdXJhY3k6IGFsdHMuY29udmVyc2lvbkFjY3VyYWN5IHx8IGR1ci5jb252ZXJzaW9uQWNjdXJhY3ksXG4gICAgbWF0cml4OiBhbHRzLm1hdHJpeCB8fCBkdXIubWF0cml4LFxuICB9O1xuICByZXR1cm4gbmV3IER1cmF0aW9uKGNvbmYpO1xufVxuXG5mdW5jdGlvbiBhbnRpVHJ1bmMobikge1xuICByZXR1cm4gbiA8IDAgPyBNYXRoLmZsb29yKG4pIDogTWF0aC5jZWlsKG4pO1xufVxuXG4vLyBOQjogbXV0YXRlcyBwYXJhbWV0ZXJzXG5mdW5jdGlvbiBjb252ZXJ0KG1hdHJpeCwgZnJvbU1hcCwgZnJvbVVuaXQsIHRvTWFwLCB0b1VuaXQpIHtcbiAgY29uc3QgY29udiA9IG1hdHJpeFt0b1VuaXRdW2Zyb21Vbml0XSxcbiAgICByYXcgPSBmcm9tTWFwW2Zyb21Vbml0XSAvIGNvbnYsXG4gICAgc2FtZVNpZ24gPSBNYXRoLnNpZ24ocmF3KSA9PT0gTWF0aC5zaWduKHRvTWFwW3RvVW5pdF0pLFxuICAgIC8vIG9rLCBzbyB0aGlzIGlzIHdpbGQsIGJ1dCBzZWUgdGhlIG1hdHJpeCBpbiB0aGUgdGVzdHNcbiAgICBhZGRlZCA9XG4gICAgICAhc2FtZVNpZ24gJiYgdG9NYXBbdG9Vbml0XSAhPT0gMCAmJiBNYXRoLmFicyhyYXcpIDw9IDEgPyBhbnRpVHJ1bmMocmF3KSA6IE1hdGgudHJ1bmMocmF3KTtcbiAgdG9NYXBbdG9Vbml0XSArPSBhZGRlZDtcbiAgZnJvbU1hcFtmcm9tVW5pdF0gLT0gYWRkZWQgKiBjb252O1xufVxuXG4vLyBOQjogbXV0YXRlcyBwYXJhbWV0ZXJzXG5mdW5jdGlvbiBub3JtYWxpemVWYWx1ZXMobWF0cml4LCB2YWxzKSB7XG4gIHJldmVyc2VVbml0cy5yZWR1Y2UoKHByZXZpb3VzLCBjdXJyZW50KSA9PiB7XG4gICAgaWYgKCFpc1VuZGVmaW5lZCh2YWxzW2N1cnJlbnRdKSkge1xuICAgICAgaWYgKHByZXZpb3VzKSB7XG4gICAgICAgIGNvbnZlcnQobWF0cml4LCB2YWxzLCBwcmV2aW91cywgdmFscywgY3VycmVudCk7XG4gICAgICB9XG4gICAgICByZXR1cm4gY3VycmVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHByZXZpb3VzO1xuICAgIH1cbiAgfSwgbnVsbCk7XG59XG5cbi8vIFJlbW92ZSBhbGwgcHJvcGVydGllcyB3aXRoIGEgdmFsdWUgb2YgMCBmcm9tIGFuIG9iamVjdFxuZnVuY3Rpb24gcmVtb3ZlWmVyb2VzKHZhbHMpIHtcbiAgY29uc3QgbmV3VmFscyA9IHt9O1xuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyh2YWxzKSkge1xuICAgIGlmICh2YWx1ZSAhPT0gMCkge1xuICAgICAgbmV3VmFsc1trZXldID0gdmFsdWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBuZXdWYWxzO1xufVxuXG4vKipcbiAqIEEgRHVyYXRpb24gb2JqZWN0IHJlcHJlc2VudHMgYSBwZXJpb2Qgb2YgdGltZSwgbGlrZSBcIjIgbW9udGhzXCIgb3IgXCIxIGRheSwgMSBob3VyXCIuIENvbmNlcHR1YWxseSwgaXQncyBqdXN0IGEgbWFwIG9mIHVuaXRzIHRvIHRoZWlyIHF1YW50aXRpZXMsIGFjY29tcGFuaWVkIGJ5IHNvbWUgYWRkaXRpb25hbCBjb25maWd1cmF0aW9uIGFuZCBtZXRob2RzIGZvciBjcmVhdGluZywgcGFyc2luZywgaW50ZXJyb2dhdGluZywgdHJhbnNmb3JtaW5nLCBhbmQgZm9ybWF0dGluZyB0aGVtLiBUaGV5IGNhbiBiZSB1c2VkIG9uIHRoZWlyIG93biBvciBpbiBjb25qdW5jdGlvbiB3aXRoIG90aGVyIEx1eG9uIHR5cGVzOyBmb3IgZXhhbXBsZSwgeW91IGNhbiB1c2Uge0BsaW5rIERhdGVUaW1lI3BsdXN9IHRvIGFkZCBhIER1cmF0aW9uIG9iamVjdCB0byBhIERhdGVUaW1lLCBwcm9kdWNpbmcgYW5vdGhlciBEYXRlVGltZS5cbiAqXG4gKiBIZXJlIGlzIGEgYnJpZWYgb3ZlcnZpZXcgb2YgY29tbW9ubHkgdXNlZCBtZXRob2RzIGFuZCBnZXR0ZXJzIGluIER1cmF0aW9uOlxuICpcbiAqICogKipDcmVhdGlvbioqIFRvIGNyZWF0ZSBhIER1cmF0aW9uLCB1c2Uge0BsaW5rIER1cmF0aW9uLmZyb21NaWxsaXN9LCB7QGxpbmsgRHVyYXRpb24uZnJvbU9iamVjdH0sIG9yIHtAbGluayBEdXJhdGlvbi5mcm9tSVNPfS5cbiAqICogKipVbml0IHZhbHVlcyoqIFNlZSB0aGUge0BsaW5rIER1cmF0aW9uI3llYXJzfSwge0BsaW5rIER1cmF0aW9uI21vbnRoc30sIHtAbGluayBEdXJhdGlvbiN3ZWVrc30sIHtAbGluayBEdXJhdGlvbiNkYXlzfSwge0BsaW5rIER1cmF0aW9uI2hvdXJzfSwge0BsaW5rIER1cmF0aW9uI21pbnV0ZXN9LCB7QGxpbmsgRHVyYXRpb24jc2Vjb25kc30sIHtAbGluayBEdXJhdGlvbiNtaWxsaXNlY29uZHN9IGFjY2Vzc29ycy5cbiAqICogKipDb25maWd1cmF0aW9uKiogU2VlICB7QGxpbmsgRHVyYXRpb24jbG9jYWxlfSBhbmQge0BsaW5rIER1cmF0aW9uI251bWJlcmluZ1N5c3RlbX0gYWNjZXNzb3JzLlxuICogKiAqKlRyYW5zZm9ybWF0aW9uKiogVG8gY3JlYXRlIG5ldyBEdXJhdGlvbnMgb3V0IG9mIG9sZCBvbmVzIHVzZSB7QGxpbmsgRHVyYXRpb24jcGx1c30sIHtAbGluayBEdXJhdGlvbiNtaW51c30sIHtAbGluayBEdXJhdGlvbiNub3JtYWxpemV9LCB7QGxpbmsgRHVyYXRpb24jc2V0fSwge0BsaW5rIER1cmF0aW9uI3JlY29uZmlndXJlfSwge0BsaW5rIER1cmF0aW9uI3NoaWZ0VG99LCBhbmQge0BsaW5rIER1cmF0aW9uI25lZ2F0ZX0uXG4gKiAqICoqT3V0cHV0KiogVG8gY29udmVydCB0aGUgRHVyYXRpb24gaW50byBvdGhlciByZXByZXNlbnRhdGlvbnMsIHNlZSB7QGxpbmsgRHVyYXRpb24jYXN9LCB7QGxpbmsgRHVyYXRpb24jdG9JU099LCB7QGxpbmsgRHVyYXRpb24jdG9Gb3JtYXR9LCBhbmQge0BsaW5rIER1cmF0aW9uI3RvSlNPTn1cbiAqXG4gKiBUaGVyZSdzIGFyZSBtb3JlIG1ldGhvZHMgZG9jdW1lbnRlZCBiZWxvdy4gSW4gYWRkaXRpb24sIGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIHN1YnRsZXIgdG9waWNzIGxpa2UgaW50ZXJuYXRpb25hbGl6YXRpb24gYW5kIHZhbGlkaXR5LCBzZWUgdGhlIGV4dGVybmFsIGRvY3VtZW50YXRpb24uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIER1cmF0aW9uIHtcbiAgLyoqXG4gICAqIEBwcml2YXRlXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihjb25maWcpIHtcbiAgICBjb25zdCBhY2N1cmF0ZSA9IGNvbmZpZy5jb252ZXJzaW9uQWNjdXJhY3kgPT09IFwibG9uZ3Rlcm1cIiB8fCBmYWxzZTtcbiAgICBsZXQgbWF0cml4ID0gYWNjdXJhdGUgPyBhY2N1cmF0ZU1hdHJpeCA6IGNhc3VhbE1hdHJpeDtcblxuICAgIGlmIChjb25maWcubWF0cml4KSB7XG4gICAgICBtYXRyaXggPSBjb25maWcubWF0cml4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMudmFsdWVzID0gY29uZmlnLnZhbHVlcztcbiAgICAvKipcbiAgICAgKiBAYWNjZXNzIHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLmxvYyA9IGNvbmZpZy5sb2MgfHwgTG9jYWxlLmNyZWF0ZSgpO1xuICAgIC8qKlxuICAgICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuY29udmVyc2lvbkFjY3VyYWN5ID0gYWNjdXJhdGUgPyBcImxvbmd0ZXJtXCIgOiBcImNhc3VhbFwiO1xuICAgIC8qKlxuICAgICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuaW52YWxpZCA9IGNvbmZpZy5pbnZhbGlkIHx8IG51bGw7XG4gICAgLyoqXG4gICAgICogQGFjY2VzcyBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5tYXRyaXggPSBtYXRyaXg7XG4gICAgLyoqXG4gICAgICogQGFjY2VzcyBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5pc0x1eG9uRHVyYXRpb24gPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBEdXJhdGlvbiBmcm9tIGEgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcy5cbiAgICogQHBhcmFtIHtudW1iZXJ9IGNvdW50IG9mIG1pbGxpc2Vjb25kc1xuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnMgZm9yIHBhcnNpbmdcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmxvY2FsZT0nZW4tVVMnXSAtIHRoZSBsb2NhbGUgdG8gdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm51bWJlcmluZ1N5c3RlbSAtIHRoZSBudW1iZXJpbmcgc3lzdGVtIHRvIHVzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMuY29udmVyc2lvbkFjY3VyYWN5PSdjYXN1YWwnXSAtIHRoZSBjb252ZXJzaW9uIHN5c3RlbSB0byB1c2VcbiAgICogQHJldHVybiB7RHVyYXRpb259XG4gICAqL1xuICBzdGF0aWMgZnJvbU1pbGxpcyhjb3VudCwgb3B0cykge1xuICAgIHJldHVybiBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgbWlsbGlzZWNvbmRzOiBjb3VudCB9LCBvcHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBEdXJhdGlvbiBmcm9tIGEgSmF2YVNjcmlwdCBvYmplY3Qgd2l0aCBrZXlzIGxpa2UgJ3llYXJzJyBhbmQgJ2hvdXJzJy5cbiAgICogSWYgdGhpcyBvYmplY3QgaXMgZW1wdHkgdGhlbiBhIHplcm8gbWlsbGlzZWNvbmRzIGR1cmF0aW9uIGlzIHJldHVybmVkLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb2JqIC0gdGhlIG9iamVjdCB0byBjcmVhdGUgdGhlIERhdGVUaW1lIGZyb21cbiAgICogQHBhcmFtIHtudW1iZXJ9IG9iai55ZWFyc1xuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLnF1YXJ0ZXJzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvYmoubW9udGhzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvYmoud2Vla3NcbiAgICogQHBhcmFtIHtudW1iZXJ9IG9iai5kYXlzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvYmouaG91cnNcbiAgICogQHBhcmFtIHtudW1iZXJ9IG9iai5taW51dGVzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvYmouc2Vjb25kc1xuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLm1pbGxpc2Vjb25kc1xuICAgKiBAcGFyYW0ge09iamVjdH0gW29wdHM9W11dIC0gb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGhpcyBEdXJhdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubG9jYWxlPSdlbi1VUyddIC0gdGhlIGxvY2FsZSB0byB1c2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubnVtYmVyaW5nU3lzdGVtIC0gdGhlIG51bWJlcmluZyBzeXN0ZW0gdG8gdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5jb252ZXJzaW9uQWNjdXJhY3k9J2Nhc3VhbCddIC0gdGhlIHByZXNldCBjb252ZXJzaW9uIHN5c3RlbSB0byB1c2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLm1hdHJpeD1PYmplY3RdIC0gdGhlIGN1c3RvbSBjb252ZXJzaW9uIHN5c3RlbSB0byB1c2VcbiAgICogQHJldHVybiB7RHVyYXRpb259XG4gICAqL1xuICBzdGF0aWMgZnJvbU9iamVjdChvYmosIG9wdHMgPSB7fSkge1xuICAgIGlmIChvYmogPT0gbnVsbCB8fCB0eXBlb2Ygb2JqICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEFyZ3VtZW50RXJyb3IoXG4gICAgICAgIGBEdXJhdGlvbi5mcm9tT2JqZWN0OiBhcmd1bWVudCBleHBlY3RlZCB0byBiZSBhbiBvYmplY3QsIGdvdCAke1xuICAgICAgICAgIG9iaiA9PT0gbnVsbCA/IFwibnVsbFwiIDogdHlwZW9mIG9ialxuICAgICAgICB9YFxuICAgICAgKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IER1cmF0aW9uKHtcbiAgICAgIHZhbHVlczogbm9ybWFsaXplT2JqZWN0KG9iaiwgRHVyYXRpb24ubm9ybWFsaXplVW5pdCksXG4gICAgICBsb2M6IExvY2FsZS5mcm9tT2JqZWN0KG9wdHMpLFxuICAgICAgY29udmVyc2lvbkFjY3VyYWN5OiBvcHRzLmNvbnZlcnNpb25BY2N1cmFjeSxcbiAgICAgIG1hdHJpeDogb3B0cy5tYXRyaXgsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgRHVyYXRpb24gZnJvbSBEdXJhdGlvbkxpa2UuXG4gICAqXG4gICAqIEBwYXJhbSB7T2JqZWN0IHwgbnVtYmVyIHwgRHVyYXRpb259IGR1cmF0aW9uTGlrZVxuICAgKiBPbmUgb2Y6XG4gICAqIC0gb2JqZWN0IHdpdGgga2V5cyBsaWtlICd5ZWFycycgYW5kICdob3VycycuXG4gICAqIC0gbnVtYmVyIHJlcHJlc2VudGluZyBtaWxsaXNlY29uZHNcbiAgICogLSBEdXJhdGlvbiBpbnN0YW5jZVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIHN0YXRpYyBmcm9tRHVyYXRpb25MaWtlKGR1cmF0aW9uTGlrZSkge1xuICAgIGlmIChpc051bWJlcihkdXJhdGlvbkxpa2UpKSB7XG4gICAgICByZXR1cm4gRHVyYXRpb24uZnJvbU1pbGxpcyhkdXJhdGlvbkxpa2UpO1xuICAgIH0gZWxzZSBpZiAoRHVyYXRpb24uaXNEdXJhdGlvbihkdXJhdGlvbkxpa2UpKSB7XG4gICAgICByZXR1cm4gZHVyYXRpb25MaWtlO1xuICAgIH0gZWxzZSBpZiAodHlwZW9mIGR1cmF0aW9uTGlrZSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgcmV0dXJuIER1cmF0aW9uLmZyb21PYmplY3QoZHVyYXRpb25MaWtlKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEVycm9yKFxuICAgICAgICBgVW5rbm93biBkdXJhdGlvbiBhcmd1bWVudCAke2R1cmF0aW9uTGlrZX0gb2YgdHlwZSAke3R5cGVvZiBkdXJhdGlvbkxpa2V9YFxuICAgICAgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgRHVyYXRpb24gZnJvbSBhbiBJU08gODYwMSBkdXJhdGlvbiBzdHJpbmcuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gdGV4dCB0byBwYXJzZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnMgZm9yIHBhcnNpbmdcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmxvY2FsZT0nZW4tVVMnXSAtIHRoZSBsb2NhbGUgdG8gdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm51bWJlcmluZ1N5c3RlbSAtIHRoZSBudW1iZXJpbmcgc3lzdGVtIHRvIHVzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMuY29udmVyc2lvbkFjY3VyYWN5PSdjYXN1YWwnXSAtIHRoZSBwcmVzZXQgY29udmVyc2lvbiBzeXN0ZW0gdG8gdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5tYXRyaXg9T2JqZWN0XSAtIHRoZSBwcmVzZXQgY29udmVyc2lvbiBzeXN0ZW0gdG8gdXNlXG4gICAqIEBzZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzg2MDEjRHVyYXRpb25zXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21JU08oJ1AzWTZNMVc0RFQxMkgzME01UycpLnRvT2JqZWN0KCkgLy89PiB7IHllYXJzOiAzLCBtb250aHM6IDYsIHdlZWtzOiAxLCBkYXlzOiA0LCBob3VyczogMTIsIG1pbnV0ZXM6IDMwLCBzZWNvbmRzOiA1IH1cbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbUlTTygnUFQyM0gnKS50b09iamVjdCgpIC8vPT4geyBob3VyczogMjMgfVxuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tSVNPKCdQNVkzTScpLnRvT2JqZWN0KCkgLy89PiB7IHllYXJzOiA1LCBtb250aHM6IDMgfVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIHN0YXRpYyBmcm9tSVNPKHRleHQsIG9wdHMpIHtcbiAgICBjb25zdCBbcGFyc2VkXSA9IHBhcnNlSVNPRHVyYXRpb24odGV4dCk7XG4gICAgaWYgKHBhcnNlZCkge1xuICAgICAgcmV0dXJuIER1cmF0aW9uLmZyb21PYmplY3QocGFyc2VkLCBvcHRzKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIER1cmF0aW9uLmludmFsaWQoXCJ1bnBhcnNhYmxlXCIsIGB0aGUgaW5wdXQgXCIke3RleHR9XCIgY2FuJ3QgYmUgcGFyc2VkIGFzIElTTyA4NjAxYCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIER1cmF0aW9uIGZyb20gYW4gSVNPIDg2MDEgdGltZSBzdHJpbmcuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gdGV4dCB0byBwYXJzZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnMgZm9yIHBhcnNpbmdcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmxvY2FsZT0nZW4tVVMnXSAtIHRoZSBsb2NhbGUgdG8gdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm51bWJlcmluZ1N5c3RlbSAtIHRoZSBudW1iZXJpbmcgc3lzdGVtIHRvIHVzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMuY29udmVyc2lvbkFjY3VyYWN5PSdjYXN1YWwnXSAtIHRoZSBwcmVzZXQgY29udmVyc2lvbiBzeXN0ZW0gdG8gdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5tYXRyaXg9T2JqZWN0XSAtIHRoZSBjb252ZXJzaW9uIHN5c3RlbSB0byB1c2VcbiAgICogQHNlZSBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JU09fODYwMSNUaW1lc1xuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tSVNPVGltZSgnMTE6MjI6MzMuNDQ0JykudG9PYmplY3QoKSAvLz0+IHsgaG91cnM6IDExLCBtaW51dGVzOiAyMiwgc2Vjb25kczogMzMsIG1pbGxpc2Vjb25kczogNDQ0IH1cbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbUlTT1RpbWUoJzExOjAwJykudG9PYmplY3QoKSAvLz0+IHsgaG91cnM6IDExLCBtaW51dGVzOiAwLCBzZWNvbmRzOiAwIH1cbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbUlTT1RpbWUoJ1QxMTowMCcpLnRvT2JqZWN0KCkgLy89PiB7IGhvdXJzOiAxMSwgbWludXRlczogMCwgc2Vjb25kczogMCB9XG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21JU09UaW1lKCcxMTAwJykudG9PYmplY3QoKSAvLz0+IHsgaG91cnM6IDExLCBtaW51dGVzOiAwLCBzZWNvbmRzOiAwIH1cbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbUlTT1RpbWUoJ1QxMTAwJykudG9PYmplY3QoKSAvLz0+IHsgaG91cnM6IDExLCBtaW51dGVzOiAwLCBzZWNvbmRzOiAwIH1cbiAgICogQHJldHVybiB7RHVyYXRpb259XG4gICAqL1xuICBzdGF0aWMgZnJvbUlTT1RpbWUodGV4dCwgb3B0cykge1xuICAgIGNvbnN0IFtwYXJzZWRdID0gcGFyc2VJU09UaW1lT25seSh0ZXh0KTtcbiAgICBpZiAocGFyc2VkKSB7XG4gICAgICByZXR1cm4gRHVyYXRpb24uZnJvbU9iamVjdChwYXJzZWQsIG9wdHMpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gRHVyYXRpb24uaW52YWxpZChcInVucGFyc2FibGVcIiwgYHRoZSBpbnB1dCBcIiR7dGV4dH1cIiBjYW4ndCBiZSBwYXJzZWQgYXMgSVNPIDg2MDFgKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGFuIGludmFsaWQgRHVyYXRpb24uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZWFzb24gLSBzaW1wbGUgc3RyaW5nIG9mIHdoeSB0aGlzIGRhdGV0aW1lIGlzIGludmFsaWQuIFNob3VsZCBub3QgY29udGFpbiBwYXJhbWV0ZXJzIG9yIGFueXRoaW5nIGVsc2UgZGF0YS1kZXBlbmRlbnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtleHBsYW5hdGlvbj1udWxsXSAtIGxvbmdlciBleHBsYW5hdGlvbiwgbWF5IGluY2x1ZGUgcGFyYW1ldGVycyBhbmQgb3RoZXIgdXNlZnVsIGRlYnVnZ2luZyBpbmZvcm1hdGlvblxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIHN0YXRpYyBpbnZhbGlkKHJlYXNvbiwgZXhwbGFuYXRpb24gPSBudWxsKSB7XG4gICAgaWYgKCFyZWFzb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihcIm5lZWQgdG8gc3BlY2lmeSBhIHJlYXNvbiB0aGUgRHVyYXRpb24gaXMgaW52YWxpZFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnZhbGlkID0gcmVhc29uIGluc3RhbmNlb2YgSW52YWxpZCA/IHJlYXNvbiA6IG5ldyBJbnZhbGlkKHJlYXNvbiwgZXhwbGFuYXRpb24pO1xuXG4gICAgaWYgKFNldHRpbmdzLnRocm93T25JbnZhbGlkKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZER1cmF0aW9uRXJyb3IoaW52YWxpZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgRHVyYXRpb24oeyBpbnZhbGlkIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgc3RhdGljIG5vcm1hbGl6ZVVuaXQodW5pdCkge1xuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSB7XG4gICAgICB5ZWFyOiBcInllYXJzXCIsXG4gICAgICB5ZWFyczogXCJ5ZWFyc1wiLFxuICAgICAgcXVhcnRlcjogXCJxdWFydGVyc1wiLFxuICAgICAgcXVhcnRlcnM6IFwicXVhcnRlcnNcIixcbiAgICAgIG1vbnRoOiBcIm1vbnRoc1wiLFxuICAgICAgbW9udGhzOiBcIm1vbnRoc1wiLFxuICAgICAgd2VlazogXCJ3ZWVrc1wiLFxuICAgICAgd2Vla3M6IFwid2Vla3NcIixcbiAgICAgIGRheTogXCJkYXlzXCIsXG4gICAgICBkYXlzOiBcImRheXNcIixcbiAgICAgIGhvdXI6IFwiaG91cnNcIixcbiAgICAgIGhvdXJzOiBcImhvdXJzXCIsXG4gICAgICBtaW51dGU6IFwibWludXRlc1wiLFxuICAgICAgbWludXRlczogXCJtaW51dGVzXCIsXG4gICAgICBzZWNvbmQ6IFwic2Vjb25kc1wiLFxuICAgICAgc2Vjb25kczogXCJzZWNvbmRzXCIsXG4gICAgICBtaWxsaXNlY29uZDogXCJtaWxsaXNlY29uZHNcIixcbiAgICAgIG1pbGxpc2Vjb25kczogXCJtaWxsaXNlY29uZHNcIixcbiAgICB9W3VuaXQgPyB1bml0LnRvTG93ZXJDYXNlKCkgOiB1bml0XTtcblxuICAgIGlmICghbm9ybWFsaXplZCkgdGhyb3cgbmV3IEludmFsaWRVbml0RXJyb3IodW5pdCk7XG5cbiAgICByZXR1cm4gbm9ybWFsaXplZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBhbiBvYmplY3QgaXMgYSBEdXJhdGlvbi4gV29ya3MgYWNyb3NzIGNvbnRleHQgYm91bmRhcmllc1xuICAgKiBAcGFyYW0ge29iamVjdH0gb1xuICAgKiBAcmV0dXJuIHtib29sZWFufVxuICAgKi9cbiAgc3RhdGljIGlzRHVyYXRpb24obykge1xuICAgIHJldHVybiAobyAmJiBvLmlzTHV4b25EdXJhdGlvbikgfHwgZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogR2V0ICB0aGUgbG9jYWxlIG9mIGEgRHVyYXRpb24sIHN1Y2ggJ2VuLUdCJ1xuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKi9cbiAgZ2V0IGxvY2FsZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gdGhpcy5sb2MubG9jYWxlIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG51bWJlcmluZyBzeXN0ZW0gb2YgYSBEdXJhdGlvbiwgc3VjaCAnYmVuZycuIFRoZSBudW1iZXJpbmcgc3lzdGVtIGlzIHVzZWQgd2hlbiBmb3JtYXR0aW5nIHRoZSBEdXJhdGlvblxuICAgKlxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKi9cbiAgZ2V0IG51bWJlcmluZ1N5c3RlbSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gdGhpcy5sb2MubnVtYmVyaW5nU3lzdGVtIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRHVyYXRpb24gZm9ybWF0dGVkIGFjY29yZGluZyB0byB0aGUgc3BlY2lmaWVkIGZvcm1hdCBzdHJpbmcuIFlvdSBtYXkgdXNlIHRoZXNlIHRva2VuczpcbiAgICogKiBgU2AgZm9yIG1pbGxpc2Vjb25kc1xuICAgKiAqIGBzYCBmb3Igc2Vjb25kc1xuICAgKiAqIGBtYCBmb3IgbWludXRlc1xuICAgKiAqIGBoYCBmb3IgaG91cnNcbiAgICogKiBgZGAgZm9yIGRheXNcbiAgICogKiBgd2AgZm9yIHdlZWtzXG4gICAqICogYE1gIGZvciBtb250aHNcbiAgICogKiBgeWAgZm9yIHllYXJzXG4gICAqIE5vdGVzOlxuICAgKiAqIEFkZCBwYWRkaW5nIGJ5IHJlcGVhdGluZyB0aGUgdG9rZW4sIGUuZy4gXCJ5eVwiIHBhZHMgdGhlIHllYXJzIHRvIHR3byBkaWdpdHMsIFwiaGhoaFwiIHBhZHMgdGhlIGhvdXJzIG91dCB0byBmb3VyIGRpZ2l0c1xuICAgKiAqIFRva2VucyBjYW4gYmUgZXNjYXBlZCBieSB3cmFwcGluZyB3aXRoIHNpbmdsZSBxdW90ZXMuXG4gICAqICogVGhlIGR1cmF0aW9uIHdpbGwgYmUgY29udmVydGVkIHRvIHRoZSBzZXQgb2YgdW5pdHMgaW4gdGhlIGZvcm1hdCBzdHJpbmcgdXNpbmcge0BsaW5rIER1cmF0aW9uI3NoaWZ0VG99IGFuZCB0aGUgRHVyYXRpb25zJ3MgY29udmVyc2lvbiBhY2N1cmFjeSBzZXR0aW5nLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gZm10IC0gdGhlIGZvcm1hdCBzdHJpbmdcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBvcHRpb25zXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuZmxvb3I9dHJ1ZV0gLSBmbG9vciBudW1lcmljYWwgdmFsdWVzXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyB5ZWFyczogMSwgZGF5czogNiwgc2Vjb25kczogMiB9KS50b0Zvcm1hdChcInkgZCBzXCIpIC8vPT4gXCIxIDYgMlwiXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyB5ZWFyczogMSwgZGF5czogNiwgc2Vjb25kczogMiB9KS50b0Zvcm1hdChcInl5IGRkIHNzc1wiKSAvLz0+IFwiMDEgMDYgMDAyXCJcbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbU9iamVjdCh7IHllYXJzOiAxLCBkYXlzOiA2LCBzZWNvbmRzOiAyIH0pLnRvRm9ybWF0KFwiTSBTXCIpIC8vPT4gXCIxMiA1MTg0MDIwMDBcIlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b0Zvcm1hdChmbXQsIG9wdHMgPSB7fSkge1xuICAgIC8vIHJldmVyc2UtY29tcGF0IHNpbmNlIDEuMjsgd2UgYWx3YXlzIHJvdW5kIGRvd24gbm93LCBuZXZlciB1cCwgYW5kIHdlIGRvIGl0IGJ5IGRlZmF1bHRcbiAgICBjb25zdCBmbXRPcHRzID0ge1xuICAgICAgLi4ub3B0cyxcbiAgICAgIGZsb29yOiBvcHRzLnJvdW5kICE9PSBmYWxzZSAmJiBvcHRzLmZsb29yICE9PSBmYWxzZSxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWRcbiAgICAgID8gRm9ybWF0dGVyLmNyZWF0ZSh0aGlzLmxvYywgZm10T3B0cykuZm9ybWF0RHVyYXRpb25Gcm9tU3RyaW5nKHRoaXMsIGZtdClcbiAgICAgIDogSU5WQUxJRDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgRHVyYXRpb24gd2l0aCBhbGwgdW5pdHMgaW5jbHVkZWQuXG4gICAqIFRvIG1vZGlmeSBpdHMgYmVoYXZpb3IgdXNlIHRoZSBgbGlzdFN0eWxlYCBhbmQgYW55IEludGwuTnVtYmVyRm9ybWF0IG9wdGlvbiwgdGhvdWdoIGB1bml0RGlzcGxheWAgaXMgZXNwZWNpYWxseSByZWxldmFudC5cbiAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9JbnRsL051bWJlckZvcm1hdFxuICAgKiBAcGFyYW0gb3B0cyAtIE9uIG9wdGlvbiBvYmplY3QgdG8gb3ZlcnJpZGUgdGhlIGZvcm1hdHRpbmcuIEFjY2VwdHMgdGhlIHNhbWUga2V5cyBhcyB0aGUgb3B0aW9ucyBwYXJhbWV0ZXIgb2YgdGhlIG5hdGl2ZSBgSW50Lk51bWJlckZvcm1hdGAgY29uc3RydWN0b3IsIGFzIHdlbGwgYXMgYGxpc3RTdHlsZWAuXG4gICAqIEBleGFtcGxlXG4gICAqIGBgYGpzXG4gICAqIHZhciBkdXIgPSBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgZGF5czogMSwgaG91cnM6IDUsIG1pbnV0ZXM6IDYgfSlcbiAgICogZHVyLnRvSHVtYW4oKSAvLz0+ICcxIGRheSwgNSBob3VycywgNiBtaW51dGVzJ1xuICAgKiBkdXIudG9IdW1hbih7IGxpc3RTdHlsZTogXCJsb25nXCIgfSkgLy89PiAnMSBkYXksIDUgaG91cnMsIGFuZCA2IG1pbnV0ZXMnXG4gICAqIGR1ci50b0h1bWFuKHsgdW5pdERpc3BsYXk6IFwic2hvcnRcIiB9KSAvLz0+ICcxIGRheSwgNSBociwgNiBtaW4nXG4gICAqIGBgYFxuICAgKi9cbiAgdG9IdW1hbihvcHRzID0ge30pIHtcbiAgICBjb25zdCBsID0gb3JkZXJlZFVuaXRzXG4gICAgICAubWFwKCh1bml0KSA9PiB7XG4gICAgICAgIGNvbnN0IHZhbCA9IHRoaXMudmFsdWVzW3VuaXRdO1xuICAgICAgICBpZiAoaXNVbmRlZmluZWQodmFsKSkge1xuICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmxvY1xuICAgICAgICAgIC5udW1iZXJGb3JtYXR0ZXIoeyBzdHlsZTogXCJ1bml0XCIsIHVuaXREaXNwbGF5OiBcImxvbmdcIiwgLi4ub3B0cywgdW5pdDogdW5pdC5zbGljZSgwLCAtMSkgfSlcbiAgICAgICAgICAuZm9ybWF0KHZhbCk7XG4gICAgICB9KVxuICAgICAgLmZpbHRlcigobikgPT4gbik7XG5cbiAgICByZXR1cm4gdGhpcy5sb2NcbiAgICAgIC5saXN0Rm9ybWF0dGVyKHsgdHlwZTogXCJjb25qdW5jdGlvblwiLCBzdHlsZTogb3B0cy5saXN0U3R5bGUgfHwgXCJuYXJyb3dcIiwgLi4ub3B0cyB9KVxuICAgICAgLmZvcm1hdChsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgSmF2YVNjcmlwdCBvYmplY3Qgd2l0aCB0aGlzIER1cmF0aW9uJ3MgdmFsdWVzLlxuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgeWVhcnM6IDEsIGRheXM6IDYsIHNlY29uZHM6IDIgfSkudG9PYmplY3QoKSAvLz0+IHsgeWVhcnM6IDEsIGRheXM6IDYsIHNlY29uZHM6IDIgfVxuICAgKiBAcmV0dXJuIHtPYmplY3R9XG4gICAqL1xuICB0b09iamVjdCgpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIHt9O1xuICAgIHJldHVybiB7IC4uLnRoaXMudmFsdWVzIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBJU08gODYwMS1jb21wbGlhbnQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRHVyYXRpb24uXG4gICAqIEBzZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzg2MDEjRHVyYXRpb25zXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyB5ZWFyczogMywgc2Vjb25kczogNDUgfSkudG9JU08oKSAvLz0+ICdQM1lUNDVTJ1xuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgbW9udGhzOiA0LCBzZWNvbmRzOiA0NSB9KS50b0lTTygpIC8vPT4gJ1A0TVQ0NVMnXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyBtb250aHM6IDUgfSkudG9JU08oKSAvLz0+ICdQNU0nXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyBtaW51dGVzOiA1IH0pLnRvSVNPKCkgLy89PiAnUFQ1TSdcbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbU9iamVjdCh7IG1pbGxpc2Vjb25kczogNiB9KS50b0lTTygpIC8vPT4gJ1BUMC4wMDZTJ1xuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b0lTTygpIHtcbiAgICAvLyB3ZSBjb3VsZCB1c2UgdGhlIGZvcm1hdHRlciwgYnV0IHRoaXMgaXMgYW4gZWFzaWVyIHdheSB0byBnZXQgdGhlIG1pbmltdW0gc3RyaW5nXG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiBudWxsO1xuXG4gICAgbGV0IHMgPSBcIlBcIjtcbiAgICBpZiAodGhpcy55ZWFycyAhPT0gMCkgcyArPSB0aGlzLnllYXJzICsgXCJZXCI7XG4gICAgaWYgKHRoaXMubW9udGhzICE9PSAwIHx8IHRoaXMucXVhcnRlcnMgIT09IDApIHMgKz0gdGhpcy5tb250aHMgKyB0aGlzLnF1YXJ0ZXJzICogMyArIFwiTVwiO1xuICAgIGlmICh0aGlzLndlZWtzICE9PSAwKSBzICs9IHRoaXMud2Vla3MgKyBcIldcIjtcbiAgICBpZiAodGhpcy5kYXlzICE9PSAwKSBzICs9IHRoaXMuZGF5cyArIFwiRFwiO1xuICAgIGlmICh0aGlzLmhvdXJzICE9PSAwIHx8IHRoaXMubWludXRlcyAhPT0gMCB8fCB0aGlzLnNlY29uZHMgIT09IDAgfHwgdGhpcy5taWxsaXNlY29uZHMgIT09IDApXG4gICAgICBzICs9IFwiVFwiO1xuICAgIGlmICh0aGlzLmhvdXJzICE9PSAwKSBzICs9IHRoaXMuaG91cnMgKyBcIkhcIjtcbiAgICBpZiAodGhpcy5taW51dGVzICE9PSAwKSBzICs9IHRoaXMubWludXRlcyArIFwiTVwiO1xuICAgIGlmICh0aGlzLnNlY29uZHMgIT09IDAgfHwgdGhpcy5taWxsaXNlY29uZHMgIT09IDApXG4gICAgICAvLyB0aGlzIHdpbGwgaGFuZGxlIFwiZmxvYXRpbmcgcG9pbnQgbWFkbmVzc1wiIGJ5IHJlbW92aW5nIGV4dHJhIGRlY2ltYWwgcGxhY2VzXG4gICAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy81ODgwMDQvaXMtZmxvYXRpbmctcG9pbnQtbWF0aC1icm9rZW5cbiAgICAgIHMgKz0gcm91bmRUbyh0aGlzLnNlY29uZHMgKyB0aGlzLm1pbGxpc2Vjb25kcyAvIDEwMDAsIDMpICsgXCJTXCI7XG4gICAgaWYgKHMgPT09IFwiUFwiKSBzICs9IFwiVDBTXCI7XG4gICAgcmV0dXJuIHM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBJU08gODYwMS1jb21wbGlhbnQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRHVyYXRpb24sIGZvcm1hdHRlZCBhcyBhIHRpbWUgb2YgZGF5LlxuICAgKiBOb3RlIHRoYXQgdGhpcyB3aWxsIHJldHVybiBudWxsIGlmIHRoZSBkdXJhdGlvbiBpcyBpbnZhbGlkLCBuZWdhdGl2ZSwgb3IgZXF1YWwgdG8gb3IgZ3JlYXRlciB0aGFuIDI0IGhvdXJzLlxuICAgKiBAc2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lTT184NjAxI1RpbWVzXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRzLnN1cHByZXNzTWlsbGlzZWNvbmRzPWZhbHNlXSAtIGV4Y2x1ZGUgbWlsbGlzZWNvbmRzIGZyb20gdGhlIGZvcm1hdCBpZiB0aGV5J3JlIDBcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5zdXBwcmVzc1NlY29uZHM9ZmFsc2VdIC0gZXhjbHVkZSBzZWNvbmRzIGZyb20gdGhlIGZvcm1hdCBpZiB0aGV5J3JlIDBcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5pbmNsdWRlUHJlZml4PWZhbHNlXSAtIGluY2x1ZGUgdGhlIGBUYCBwcmVmaXhcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmZvcm1hdD0nZXh0ZW5kZWQnXSAtIGNob29zZSBiZXR3ZWVuIHRoZSBiYXNpYyBhbmQgZXh0ZW5kZWQgZm9ybWF0XG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyBob3VyczogMTEgfSkudG9JU09UaW1lKCkgLy89PiAnMTE6MDA6MDAuMDAwJ1xuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgaG91cnM6IDExIH0pLnRvSVNPVGltZSh7IHN1cHByZXNzTWlsbGlzZWNvbmRzOiB0cnVlIH0pIC8vPT4gJzExOjAwOjAwJ1xuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgaG91cnM6IDExIH0pLnRvSVNPVGltZSh7IHN1cHByZXNzU2Vjb25kczogdHJ1ZSB9KSAvLz0+ICcxMTowMCdcbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbU9iamVjdCh7IGhvdXJzOiAxMSB9KS50b0lTT1RpbWUoeyBpbmNsdWRlUHJlZml4OiB0cnVlIH0pIC8vPT4gJ1QxMTowMDowMC4wMDAnXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyBob3VyczogMTEgfSkudG9JU09UaW1lKHsgZm9ybWF0OiAnYmFzaWMnIH0pIC8vPT4gJzExMDAwMC4wMDAnXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIHRvSVNPVGltZShvcHRzID0ge30pIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIG51bGw7XG5cbiAgICBjb25zdCBtaWxsaXMgPSB0aGlzLnRvTWlsbGlzKCk7XG4gICAgaWYgKG1pbGxpcyA8IDAgfHwgbWlsbGlzID49IDg2NDAwMDAwKSByZXR1cm4gbnVsbDtcblxuICAgIG9wdHMgPSB7XG4gICAgICBzdXBwcmVzc01pbGxpc2Vjb25kczogZmFsc2UsXG4gICAgICBzdXBwcmVzc1NlY29uZHM6IGZhbHNlLFxuICAgICAgaW5jbHVkZVByZWZpeDogZmFsc2UsXG4gICAgICBmb3JtYXQ6IFwiZXh0ZW5kZWRcIixcbiAgICAgIC4uLm9wdHMsXG4gICAgfTtcblxuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5zaGlmdFRvKFwiaG91cnNcIiwgXCJtaW51dGVzXCIsIFwic2Vjb25kc1wiLCBcIm1pbGxpc2Vjb25kc1wiKTtcblxuICAgIGxldCBmbXQgPSBvcHRzLmZvcm1hdCA9PT0gXCJiYXNpY1wiID8gXCJoaG1tXCIgOiBcImhoOm1tXCI7XG5cbiAgICBpZiAoIW9wdHMuc3VwcHJlc3NTZWNvbmRzIHx8IHZhbHVlLnNlY29uZHMgIT09IDAgfHwgdmFsdWUubWlsbGlzZWNvbmRzICE9PSAwKSB7XG4gICAgICBmbXQgKz0gb3B0cy5mb3JtYXQgPT09IFwiYmFzaWNcIiA/IFwic3NcIiA6IFwiOnNzXCI7XG4gICAgICBpZiAoIW9wdHMuc3VwcHJlc3NNaWxsaXNlY29uZHMgfHwgdmFsdWUubWlsbGlzZWNvbmRzICE9PSAwKSB7XG4gICAgICAgIGZtdCArPSBcIi5TU1NcIjtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgc3RyID0gdmFsdWUudG9Gb3JtYXQoZm10KTtcblxuICAgIGlmIChvcHRzLmluY2x1ZGVQcmVmaXgpIHtcbiAgICAgIHN0ciA9IFwiVFwiICsgc3RyO1xuICAgIH1cblxuICAgIHJldHVybiBzdHI7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBJU08gODYwMSByZXByZXNlbnRhdGlvbiBvZiB0aGlzIER1cmF0aW9uIGFwcHJvcHJpYXRlIGZvciB1c2UgaW4gSlNPTi5cbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgdG9KU09OKCkge1xuICAgIHJldHVybiB0aGlzLnRvSVNPKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBJU08gODYwMSByZXByZXNlbnRhdGlvbiBvZiB0aGlzIER1cmF0aW9uIGFwcHJvcHJpYXRlIGZvciB1c2UgaW4gZGVidWdnaW5nLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gdGhpcy50b0lTTygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gbWlsbGlzZWNvbmRzIHZhbHVlIG9mIHRoaXMgRHVyYXRpb24uXG4gICAqIEByZXR1cm4ge251bWJlcn1cbiAgICovXG4gIHRvTWlsbGlzKCkge1xuICAgIHJldHVybiB0aGlzLmFzKFwibWlsbGlzZWNvbmRzXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gbWlsbGlzZWNvbmRzIHZhbHVlIG9mIHRoaXMgRHVyYXRpb24uIEFsaWFzIG9mIHtAbGluayB0b01pbGxpc31cbiAgICogQHJldHVybiB7bnVtYmVyfVxuICAgKi9cbiAgdmFsdWVPZigpIHtcbiAgICByZXR1cm4gdGhpcy50b01pbGxpcygpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ha2UgdGhpcyBEdXJhdGlvbiBsb25nZXIgYnkgdGhlIHNwZWNpZmllZCBhbW91bnQuIFJldHVybiBhIG5ld2x5LWNvbnN0cnVjdGVkIER1cmF0aW9uLlxuICAgKiBAcGFyYW0ge0R1cmF0aW9ufE9iamVjdHxudW1iZXJ9IGR1cmF0aW9uIC0gVGhlIGFtb3VudCB0byBhZGQuIEVpdGhlciBhIEx1eG9uIER1cmF0aW9uLCBhIG51bWJlciBvZiBtaWxsaXNlY29uZHMsIHRoZSBvYmplY3QgYXJndW1lbnQgdG8gRHVyYXRpb24uZnJvbU9iamVjdCgpXG4gICAqIEByZXR1cm4ge0R1cmF0aW9ufVxuICAgKi9cbiAgcGx1cyhkdXJhdGlvbikge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gdGhpcztcblxuICAgIGNvbnN0IGR1ciA9IER1cmF0aW9uLmZyb21EdXJhdGlvbkxpa2UoZHVyYXRpb24pLFxuICAgICAgcmVzdWx0ID0ge307XG5cbiAgICBmb3IgKGNvbnN0IGsgb2Ygb3JkZXJlZFVuaXRzKSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkoZHVyLnZhbHVlcywgaykgfHwgaGFzT3duUHJvcGVydHkodGhpcy52YWx1ZXMsIGspKSB7XG4gICAgICAgIHJlc3VsdFtrXSA9IGR1ci5nZXQoaykgKyB0aGlzLmdldChrKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY2xvbmUodGhpcywgeyB2YWx1ZXM6IHJlc3VsdCB9LCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNYWtlIHRoaXMgRHVyYXRpb24gc2hvcnRlciBieSB0aGUgc3BlY2lmaWVkIGFtb3VudC4gUmV0dXJuIGEgbmV3bHktY29uc3RydWN0ZWQgRHVyYXRpb24uXG4gICAqIEBwYXJhbSB7RHVyYXRpb258T2JqZWN0fG51bWJlcn0gZHVyYXRpb24gLSBUaGUgYW1vdW50IHRvIHN1YnRyYWN0LiBFaXRoZXIgYSBMdXhvbiBEdXJhdGlvbiwgYSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzLCB0aGUgb2JqZWN0IGFyZ3VtZW50IHRvIER1cmF0aW9uLmZyb21PYmplY3QoKVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIG1pbnVzKGR1cmF0aW9uKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiB0aGlzO1xuXG4gICAgY29uc3QgZHVyID0gRHVyYXRpb24uZnJvbUR1cmF0aW9uTGlrZShkdXJhdGlvbik7XG4gICAgcmV0dXJuIHRoaXMucGx1cyhkdXIubmVnYXRlKCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNjYWxlIHRoaXMgRHVyYXRpb24gYnkgdGhlIHNwZWNpZmllZCBhbW91bnQuIFJldHVybiBhIG5ld2x5LWNvbnN0cnVjdGVkIER1cmF0aW9uLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmbiAtIFRoZSBmdW5jdGlvbiB0byBhcHBseSB0byBlYWNoIHVuaXQuIEFyaXR5IGlzIDEgb3IgMjogdGhlIHZhbHVlIG9mIHRoZSB1bml0IGFuZCwgb3B0aW9uYWxseSwgdGhlIHVuaXQgbmFtZS4gTXVzdCByZXR1cm4gYSBudW1iZXIuXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyBob3VyczogMSwgbWludXRlczogMzAgfSkubWFwVW5pdHMoeCA9PiB4ICogMikgLy89PiB7IGhvdXJzOiAyLCBtaW51dGVzOiA2MCB9XG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyBob3VyczogMSwgbWludXRlczogMzAgfSkubWFwVW5pdHMoKHgsIHUpID0+IHUgPT09IFwiaG91cnNcIiA/IHggKiAyIDogeCkgLy89PiB7IGhvdXJzOiAyLCBtaW51dGVzOiAzMCB9XG4gICAqIEByZXR1cm4ge0R1cmF0aW9ufVxuICAgKi9cbiAgbWFwVW5pdHMoZm4pIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIHRoaXM7XG4gICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgZm9yIChjb25zdCBrIG9mIE9iamVjdC5rZXlzKHRoaXMudmFsdWVzKSkge1xuICAgICAgcmVzdWx0W2tdID0gYXNOdW1iZXIoZm4odGhpcy52YWx1ZXNba10sIGspKTtcbiAgICB9XG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIHsgdmFsdWVzOiByZXN1bHQgfSwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSB2YWx1ZSBvZiB1bml0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdW5pdCAtIGEgdW5pdCBzdWNoIGFzICdtaW51dGUnIG9yICdkYXknXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3Qoe3llYXJzOiAyLCBkYXlzOiAzfSkuZ2V0KCd5ZWFycycpIC8vPT4gMlxuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHt5ZWFyczogMiwgZGF5czogM30pLmdldCgnbW9udGhzJykgLy89PiAwXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3Qoe3llYXJzOiAyLCBkYXlzOiAzfSkuZ2V0KCdkYXlzJykgLy89PiAzXG4gICAqIEByZXR1cm4ge251bWJlcn1cbiAgICovXG4gIGdldCh1bml0KSB7XG4gICAgcmV0dXJuIHRoaXNbRHVyYXRpb24ubm9ybWFsaXplVW5pdCh1bml0KV07XG4gIH1cblxuICAvKipcbiAgICogXCJTZXRcIiB0aGUgdmFsdWVzIG9mIHNwZWNpZmllZCB1bml0cy4gUmV0dXJuIGEgbmV3bHktY29uc3RydWN0ZWQgRHVyYXRpb24uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZXMgLSBhIG1hcHBpbmcgb2YgdW5pdHMgdG8gbnVtYmVyc1xuICAgKiBAZXhhbXBsZSBkdXIuc2V0KHsgeWVhcnM6IDIwMTcgfSlcbiAgICogQGV4YW1wbGUgZHVyLnNldCh7IGhvdXJzOiA4LCBtaW51dGVzOiAzMCB9KVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIHNldCh2YWx1ZXMpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIHRoaXM7XG5cbiAgICBjb25zdCBtaXhlZCA9IHsgLi4udGhpcy52YWx1ZXMsIC4uLm5vcm1hbGl6ZU9iamVjdCh2YWx1ZXMsIER1cmF0aW9uLm5vcm1hbGl6ZVVuaXQpIH07XG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIHsgdmFsdWVzOiBtaXhlZCB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBcIlNldFwiIHRoZSBsb2NhbGUgYW5kL29yIG51bWJlcmluZ1N5c3RlbS4gIFJldHVybnMgYSBuZXdseS1jb25zdHJ1Y3RlZCBEdXJhdGlvbi5cbiAgICogQGV4YW1wbGUgZHVyLnJlY29uZmlndXJlKHsgbG9jYWxlOiAnZW4tR0InIH0pXG4gICAqIEByZXR1cm4ge0R1cmF0aW9ufVxuICAgKi9cbiAgcmVjb25maWd1cmUoeyBsb2NhbGUsIG51bWJlcmluZ1N5c3RlbSwgY29udmVyc2lvbkFjY3VyYWN5LCBtYXRyaXggfSA9IHt9KSB7XG4gICAgY29uc3QgbG9jID0gdGhpcy5sb2MuY2xvbmUoeyBsb2NhbGUsIG51bWJlcmluZ1N5c3RlbSB9KTtcbiAgICBjb25zdCBvcHRzID0geyBsb2MsIG1hdHJpeCwgY29udmVyc2lvbkFjY3VyYWN5IH07XG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIG9wdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgbGVuZ3RoIG9mIHRoZSBkdXJhdGlvbiBpbiB0aGUgc3BlY2lmaWVkIHVuaXQuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1bml0IC0gYSB1bml0IHN1Y2ggYXMgJ21pbnV0ZXMnIG9yICdkYXlzJ1xuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHt5ZWFyczogMX0pLmFzKCdkYXlzJykgLy89PiAzNjVcbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbU9iamVjdCh7eWVhcnM6IDF9KS5hcygnbW9udGhzJykgLy89PiAxMlxuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHtob3VyczogNjB9KS5hcygnZGF5cycpIC8vPT4gMi41XG4gICAqIEByZXR1cm4ge251bWJlcn1cbiAgICovXG4gIGFzKHVuaXQpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gdGhpcy5zaGlmdFRvKHVuaXQpLmdldCh1bml0KSA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWR1Y2UgdGhpcyBEdXJhdGlvbiB0byBpdHMgY2Fub25pY2FsIHJlcHJlc2VudGF0aW9uIGluIGl0cyBjdXJyZW50IHVuaXRzLlxuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgeWVhcnM6IDIsIGRheXM6IDUwMDAgfSkubm9ybWFsaXplKCkudG9PYmplY3QoKSAvLz0+IHsgeWVhcnM6IDE1LCBkYXlzOiAyNTUgfVxuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgaG91cnM6IDEyLCBtaW51dGVzOiAtNDUgfSkubm9ybWFsaXplKCkudG9PYmplY3QoKSAvLz0+IHsgaG91cnM6IDExLCBtaW51dGVzOiAxNSB9XG4gICAqIEByZXR1cm4ge0R1cmF0aW9ufVxuICAgKi9cbiAgbm9ybWFsaXplKCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gdGhpcztcbiAgICBjb25zdCB2YWxzID0gdGhpcy50b09iamVjdCgpO1xuICAgIG5vcm1hbGl6ZVZhbHVlcyh0aGlzLm1hdHJpeCwgdmFscyk7XG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIHsgdmFsdWVzOiB2YWxzIH0sIHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2NhbGUgdW5pdHMgdG8gaXRzIGxhcmdlc3QgcmVwcmVzZW50YXRpb25cbiAgICogQGV4YW1wbGUgRHVyYXRpb24uZnJvbU9iamVjdCh7IG1pbGxpc2Vjb25kczogOTAwMDAgfSkucmVzY2FsZSgpLnRvT2JqZWN0KCkgLy89PiB7IG1pbnV0ZXM6IDEsIHNlY29uZHM6IDMwIH1cbiAgICogQHJldHVybiB7RHVyYXRpb259XG4gICAqL1xuICByZXNjYWxlKCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gdGhpcztcbiAgICBjb25zdCB2YWxzID0gcmVtb3ZlWmVyb2VzKHRoaXMubm9ybWFsaXplKCkuc2hpZnRUb0FsbCgpLnRvT2JqZWN0KCkpO1xuICAgIHJldHVybiBjbG9uZSh0aGlzLCB7IHZhbHVlczogdmFscyB9LCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0IHRoaXMgRHVyYXRpb24gaW50byBpdHMgcmVwcmVzZW50YXRpb24gaW4gYSBkaWZmZXJlbnQgc2V0IG9mIHVuaXRzLlxuICAgKiBAZXhhbXBsZSBEdXJhdGlvbi5mcm9tT2JqZWN0KHsgaG91cnM6IDEsIHNlY29uZHM6IDMwIH0pLnNoaWZ0VG8oJ21pbnV0ZXMnLCAnbWlsbGlzZWNvbmRzJykudG9PYmplY3QoKSAvLz0+IHsgbWludXRlczogNjAsIG1pbGxpc2Vjb25kczogMzAwMDAgfVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIHNoaWZ0VG8oLi4udW5pdHMpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAodW5pdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICB1bml0cyA9IHVuaXRzLm1hcCgodSkgPT4gRHVyYXRpb24ubm9ybWFsaXplVW5pdCh1KSk7XG5cbiAgICBjb25zdCBidWlsdCA9IHt9LFxuICAgICAgYWNjdW11bGF0ZWQgPSB7fSxcbiAgICAgIHZhbHMgPSB0aGlzLnRvT2JqZWN0KCk7XG4gICAgbGV0IGxhc3RVbml0O1xuXG4gICAgZm9yIChjb25zdCBrIG9mIG9yZGVyZWRVbml0cykge1xuICAgICAgaWYgKHVuaXRzLmluZGV4T2YoaykgPj0gMCkge1xuICAgICAgICBsYXN0VW5pdCA9IGs7XG5cbiAgICAgICAgbGV0IG93biA9IDA7XG5cbiAgICAgICAgLy8gYW55dGhpbmcgd2UgaGF2ZW4ndCBib2lsZWQgZG93biB5ZXQgc2hvdWxkIGdldCBib2lsZWQgdG8gdGhpcyB1bml0XG4gICAgICAgIGZvciAoY29uc3QgYWsgaW4gYWNjdW11bGF0ZWQpIHtcbiAgICAgICAgICBvd24gKz0gdGhpcy5tYXRyaXhbYWtdW2tdICogYWNjdW11bGF0ZWRbYWtdO1xuICAgICAgICAgIGFjY3VtdWxhdGVkW2FrXSA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwbHVzIGFueXRoaW5nIHRoYXQncyBhbHJlYWR5IGluIHRoaXMgdW5pdFxuICAgICAgICBpZiAoaXNOdW1iZXIodmFsc1trXSkpIHtcbiAgICAgICAgICBvd24gKz0gdmFsc1trXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGkgPSBNYXRoLnRydW5jKG93bik7XG4gICAgICAgIGJ1aWx0W2tdID0gaTtcbiAgICAgICAgYWNjdW11bGF0ZWRba10gPSAob3duICogMTAwMCAtIGkgKiAxMDAwKSAvIDEwMDA7XG5cbiAgICAgICAgLy8gcGx1cyBhbnl0aGluZyBmdXJ0aGVyIGRvd24gdGhlIGNoYWluIHRoYXQgc2hvdWxkIGJlIHJvbGxlZCB1cCBpbiB0byB0aGlzXG4gICAgICAgIGZvciAoY29uc3QgZG93biBpbiB2YWxzKSB7XG4gICAgICAgICAgaWYgKG9yZGVyZWRVbml0cy5pbmRleE9mKGRvd24pID4gb3JkZXJlZFVuaXRzLmluZGV4T2YoaykpIHtcbiAgICAgICAgICAgIGNvbnZlcnQodGhpcy5tYXRyaXgsIHZhbHMsIGRvd24sIGJ1aWx0LCBrKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gb3RoZXJ3aXNlLCBrZWVwIGl0IGluIHRoZSB3aW5ncyB0byBib2lsIGl0IGxhdGVyXG4gICAgICB9IGVsc2UgaWYgKGlzTnVtYmVyKHZhbHNba10pKSB7XG4gICAgICAgIGFjY3VtdWxhdGVkW2tdID0gdmFsc1trXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBhbnl0aGluZyBsZWZ0b3ZlciBiZWNvbWVzIHRoZSBkZWNpbWFsIGZvciB0aGUgbGFzdCB1bml0XG4gICAgLy8gbGFzdFVuaXQgbXVzdCBiZSBkZWZpbmVkIHNpbmNlIHVuaXRzIGlzIG5vdCBlbXB0eVxuICAgIGZvciAoY29uc3Qga2V5IGluIGFjY3VtdWxhdGVkKSB7XG4gICAgICBpZiAoYWNjdW11bGF0ZWRba2V5XSAhPT0gMCkge1xuICAgICAgICBidWlsdFtsYXN0VW5pdF0gKz1cbiAgICAgICAgICBrZXkgPT09IGxhc3RVbml0ID8gYWNjdW11bGF0ZWRba2V5XSA6IGFjY3VtdWxhdGVkW2tleV0gLyB0aGlzLm1hdHJpeFtsYXN0VW5pdF1ba2V5XTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gY2xvbmUodGhpcywgeyB2YWx1ZXM6IGJ1aWx0IH0sIHRydWUpLm5vcm1hbGl6ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNoaWZ0IHRoaXMgRHVyYXRpb24gdG8gYWxsIGF2YWlsYWJsZSB1bml0cy5cbiAgICogU2FtZSBhcyBzaGlmdFRvKFwieWVhcnNcIiwgXCJtb250aHNcIiwgXCJ3ZWVrc1wiLCBcImRheXNcIiwgXCJob3Vyc1wiLCBcIm1pbnV0ZXNcIiwgXCJzZWNvbmRzXCIsIFwibWlsbGlzZWNvbmRzXCIpXG4gICAqIEByZXR1cm4ge0R1cmF0aW9ufVxuICAgKi9cbiAgc2hpZnRUb0FsbCgpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIHRoaXM7XG4gICAgcmV0dXJuIHRoaXMuc2hpZnRUbyhcbiAgICAgIFwieWVhcnNcIixcbiAgICAgIFwibW9udGhzXCIsXG4gICAgICBcIndlZWtzXCIsXG4gICAgICBcImRheXNcIixcbiAgICAgIFwiaG91cnNcIixcbiAgICAgIFwibWludXRlc1wiLFxuICAgICAgXCJzZWNvbmRzXCIsXG4gICAgICBcIm1pbGxpc2Vjb25kc1wiXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIG5lZ2F0aXZlIG9mIHRoaXMgRHVyYXRpb24uXG4gICAqIEBleGFtcGxlIER1cmF0aW9uLmZyb21PYmplY3QoeyBob3VyczogMSwgc2Vjb25kczogMzAgfSkubmVnYXRlKCkudG9PYmplY3QoKSAvLz0+IHsgaG91cnM6IC0xLCBzZWNvbmRzOiAtMzAgfVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIG5lZ2F0ZSgpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIHRoaXM7XG4gICAgY29uc3QgbmVnYXRlZCA9IHt9O1xuICAgIGZvciAoY29uc3QgayBvZiBPYmplY3Qua2V5cyh0aGlzLnZhbHVlcykpIHtcbiAgICAgIG5lZ2F0ZWRba10gPSB0aGlzLnZhbHVlc1trXSA9PT0gMCA/IDAgOiAtdGhpcy52YWx1ZXNba107XG4gICAgfVxuICAgIHJldHVybiBjbG9uZSh0aGlzLCB7IHZhbHVlczogbmVnYXRlZCB9LCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHllYXJzLlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKi9cbiAgZ2V0IHllYXJzKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLnZhbHVlcy55ZWFycyB8fCAwIDogTmFOO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgcXVhcnRlcnMuXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgcXVhcnRlcnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMudmFsdWVzLnF1YXJ0ZXJzIHx8IDAgOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBtb250aHMuXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgbW9udGhzKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLnZhbHVlcy5tb250aHMgfHwgMCA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHdlZWtzXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgd2Vla3MoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMudmFsdWVzLndlZWtzIHx8IDAgOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBkYXlzLlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKi9cbiAgZ2V0IGRheXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMudmFsdWVzLmRheXMgfHwgMCA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGhvdXJzLlxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKi9cbiAgZ2V0IGhvdXJzKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLnZhbHVlcy5ob3VycyB8fCAwIDogTmFOO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbWludXRlcy5cbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCBtaW51dGVzKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLnZhbHVlcy5taW51dGVzIHx8IDAgOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBzZWNvbmRzLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgc2Vjb25kcygpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gdGhpcy52YWx1ZXMuc2Vjb25kcyB8fCAwIDogTmFOO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbWlsbGlzZWNvbmRzLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgbWlsbGlzZWNvbmRzKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLnZhbHVlcy5taWxsaXNlY29uZHMgfHwgMCA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIER1cmF0aW9uIGlzIGludmFsaWQuIEludmFsaWQgZHVyYXRpb25zIGFyZSByZXR1cm5lZCBieSBkaWZmIG9wZXJhdGlvbnNcbiAgICogb24gaW52YWxpZCBEYXRlVGltZXMgb3IgSW50ZXJ2YWxzLlxuICAgKiBAcmV0dXJuIHtib29sZWFufVxuICAgKi9cbiAgZ2V0IGlzVmFsaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW52YWxpZCA9PT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIGVycm9yIGNvZGUgaWYgdGhpcyBEdXJhdGlvbiBiZWNhbWUgaW52YWxpZCwgb3IgbnVsbCBpZiB0aGUgRHVyYXRpb24gaXMgdmFsaWRcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgZ2V0IGludmFsaWRSZWFzb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuaW52YWxpZCA/IHRoaXMuaW52YWxpZC5yZWFzb24gOiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gZXhwbGFuYXRpb24gb2Ygd2h5IHRoaXMgRHVyYXRpb24gYmVjYW1lIGludmFsaWQsIG9yIG51bGwgaWYgdGhlIER1cmF0aW9uIGlzIHZhbGlkXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBnZXQgaW52YWxpZEV4cGxhbmF0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmludmFsaWQgPyB0aGlzLmludmFsaWQuZXhwbGFuYXRpb24gOiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEVxdWFsaXR5IGNoZWNrXG4gICAqIFR3byBEdXJhdGlvbnMgYXJlIGVxdWFsIGlmZiB0aGV5IGhhdmUgdGhlIHNhbWUgdW5pdHMgYW5kIHRoZSBzYW1lIHZhbHVlcyBmb3IgZWFjaCB1bml0LlxuICAgKiBAcGFyYW0ge0R1cmF0aW9ufSBvdGhlclxuICAgKiBAcmV0dXJuIHtib29sZWFufVxuICAgKi9cbiAgZXF1YWxzKG90aGVyKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQgfHwgIW90aGVyLmlzVmFsaWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMubG9jLmVxdWFscyhvdGhlci5sb2MpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXEodjEsIHYyKSB7XG4gICAgICAvLyBDb25zaWRlciAwIGFuZCB1bmRlZmluZWQgYXMgZXF1YWxcbiAgICAgIGlmICh2MSA9PT0gdW5kZWZpbmVkIHx8IHYxID09PSAwKSByZXR1cm4gdjIgPT09IHVuZGVmaW5lZCB8fCB2MiA9PT0gMDtcbiAgICAgIHJldHVybiB2MSA9PT0gdjI7XG4gICAgfVxuXG4gICAgZm9yIChjb25zdCB1IG9mIG9yZGVyZWRVbml0cykge1xuICAgICAgaWYgKCFlcSh0aGlzLnZhbHVlc1t1XSwgb3RoZXIudmFsdWVzW3VdKSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG4iLCAiaW1wb3J0IERhdGVUaW1lLCB7IGZyaWVuZGx5RGF0ZVRpbWUgfSBmcm9tIFwiLi9kYXRldGltZS5qc1wiO1xuaW1wb3J0IER1cmF0aW9uIGZyb20gXCIuL2R1cmF0aW9uLmpzXCI7XG5pbXBvcnQgU2V0dGluZ3MgZnJvbSBcIi4vc2V0dGluZ3MuanNcIjtcbmltcG9ydCB7IEludmFsaWRBcmd1bWVudEVycm9yLCBJbnZhbGlkSW50ZXJ2YWxFcnJvciB9IGZyb20gXCIuL2Vycm9ycy5qc1wiO1xuaW1wb3J0IEludmFsaWQgZnJvbSBcIi4vaW1wbC9pbnZhbGlkLmpzXCI7XG5pbXBvcnQgRm9ybWF0dGVyIGZyb20gXCIuL2ltcGwvZm9ybWF0dGVyLmpzXCI7XG5pbXBvcnQgKiBhcyBGb3JtYXRzIGZyb20gXCIuL2ltcGwvZm9ybWF0cy5qc1wiO1xuXG5jb25zdCBJTlZBTElEID0gXCJJbnZhbGlkIEludGVydmFsXCI7XG5cbi8vIGNoZWNrcyBpZiB0aGUgc3RhcnQgaXMgZXF1YWwgdG8gb3IgYmVmb3JlIHRoZSBlbmRcbmZ1bmN0aW9uIHZhbGlkYXRlU3RhcnRFbmQoc3RhcnQsIGVuZCkge1xuICBpZiAoIXN0YXJ0IHx8ICFzdGFydC5pc1ZhbGlkKSB7XG4gICAgcmV0dXJuIEludGVydmFsLmludmFsaWQoXCJtaXNzaW5nIG9yIGludmFsaWQgc3RhcnRcIik7XG4gIH0gZWxzZSBpZiAoIWVuZCB8fCAhZW5kLmlzVmFsaWQpIHtcbiAgICByZXR1cm4gSW50ZXJ2YWwuaW52YWxpZChcIm1pc3Npbmcgb3IgaW52YWxpZCBlbmRcIik7XG4gIH0gZWxzZSBpZiAoZW5kIDwgc3RhcnQpIHtcbiAgICByZXR1cm4gSW50ZXJ2YWwuaW52YWxpZChcbiAgICAgIFwiZW5kIGJlZm9yZSBzdGFydFwiLFxuICAgICAgYFRoZSBlbmQgb2YgYW4gaW50ZXJ2YWwgbXVzdCBiZSBhZnRlciBpdHMgc3RhcnQsIGJ1dCB5b3UgaGFkIHN0YXJ0PSR7c3RhcnQudG9JU08oKX0gYW5kIGVuZD0ke2VuZC50b0lTTygpfWBcbiAgICApO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBudWxsO1xuICB9XG59XG5cbi8qKlxuICogQW4gSW50ZXJ2YWwgb2JqZWN0IHJlcHJlc2VudHMgYSBoYWxmLW9wZW4gaW50ZXJ2YWwgb2YgdGltZSwgd2hlcmUgZWFjaCBlbmRwb2ludCBpcyBhIHtAbGluayBEYXRlVGltZX0uIENvbmNlcHR1YWxseSwgaXQncyBhIGNvbnRhaW5lciBmb3IgdGhvc2UgdHdvIGVuZHBvaW50cywgYWNjb21wYW5pZWQgYnkgbWV0aG9kcyBmb3IgY3JlYXRpbmcsIHBhcnNpbmcsIGludGVycm9nYXRpbmcsIGNvbXBhcmluZywgdHJhbnNmb3JtaW5nLCBhbmQgZm9ybWF0dGluZyB0aGVtLlxuICpcbiAqIEhlcmUgaXMgYSBicmllZiBvdmVydmlldyBvZiB0aGUgbW9zdCBjb21tb25seSB1c2VkIG1ldGhvZHMgYW5kIGdldHRlcnMgaW4gSW50ZXJ2YWw6XG4gKlxuICogKiAqKkNyZWF0aW9uKiogVG8gY3JlYXRlIGFuIEludGVydmFsLCB1c2Uge0BsaW5rIEludGVydmFsLmZyb21EYXRlVGltZXN9LCB7QGxpbmsgSW50ZXJ2YWwuYWZ0ZXJ9LCB7QGxpbmsgSW50ZXJ2YWwuYmVmb3JlfSwgb3Ige0BsaW5rIEludGVydmFsLmZyb21JU099LlxuICogKiAqKkFjY2Vzc29ycyoqIFVzZSB7QGxpbmsgSW50ZXJ2YWwjc3RhcnR9IGFuZCB7QGxpbmsgSW50ZXJ2YWwjZW5kfSB0byBnZXQgdGhlIHN0YXJ0IGFuZCBlbmQuXG4gKiAqICoqSW50ZXJyb2dhdGlvbioqIFRvIGFuYWx5emUgdGhlIEludGVydmFsLCB1c2Uge0BsaW5rIEludGVydmFsI2NvdW50fSwge0BsaW5rIEludGVydmFsI2xlbmd0aH0sIHtAbGluayBJbnRlcnZhbCNoYXNTYW1lfSwge0BsaW5rIEludGVydmFsI2NvbnRhaW5zfSwge0BsaW5rIEludGVydmFsI2lzQWZ0ZXJ9LCBvciB7QGxpbmsgSW50ZXJ2YWwjaXNCZWZvcmV9LlxuICogKiAqKlRyYW5zZm9ybWF0aW9uKiogVG8gY3JlYXRlIG90aGVyIEludGVydmFscyBvdXQgb2YgdGhpcyBvbmUsIHVzZSB7QGxpbmsgSW50ZXJ2YWwjc2V0fSwge0BsaW5rIEludGVydmFsI3NwbGl0QXR9LCB7QGxpbmsgSW50ZXJ2YWwjc3BsaXRCeX0sIHtAbGluayBJbnRlcnZhbCNkaXZpZGVFcXVhbGx5fSwge0BsaW5rIEludGVydmFsLm1lcmdlfSwge0BsaW5rIEludGVydmFsLnhvcn0sIHtAbGluayBJbnRlcnZhbCN1bmlvbn0sIHtAbGluayBJbnRlcnZhbCNpbnRlcnNlY3Rpb259LCBvciB7QGxpbmsgSW50ZXJ2YWwjZGlmZmVyZW5jZX0uXG4gKiAqICoqQ29tcGFyaXNvbioqIFRvIGNvbXBhcmUgdGhpcyBJbnRlcnZhbCB0byBhbm90aGVyIG9uZSwgdXNlIHtAbGluayBJbnRlcnZhbCNlcXVhbHN9LCB7QGxpbmsgSW50ZXJ2YWwjb3ZlcmxhcHN9LCB7QGxpbmsgSW50ZXJ2YWwjYWJ1dHNTdGFydH0sIHtAbGluayBJbnRlcnZhbCNhYnV0c0VuZH0sIHtAbGluayBJbnRlcnZhbCNlbmd1bGZzfVxuICogKiAqKk91dHB1dCoqIFRvIGNvbnZlcnQgdGhlIEludGVydmFsIGludG8gb3RoZXIgcmVwcmVzZW50YXRpb25zLCBzZWUge0BsaW5rIEludGVydmFsI3RvU3RyaW5nfSwge0BsaW5rIEludGVydmFsI3RvTG9jYWxlU3RyaW5nfSwge0BsaW5rIEludGVydmFsI3RvSVNPfSwge0BsaW5rIEludGVydmFsI3RvSVNPRGF0ZX0sIHtAbGluayBJbnRlcnZhbCN0b0lTT1RpbWV9LCB7QGxpbmsgSW50ZXJ2YWwjdG9Gb3JtYXR9LCBhbmQge0BsaW5rIEludGVydmFsI3RvRHVyYXRpb259LlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbnRlcnZhbCB7XG4gIC8qKlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgY29uc3RydWN0b3IoY29uZmlnKSB7XG4gICAgLyoqXG4gICAgICogQGFjY2VzcyBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5zID0gY29uZmlnLnN0YXJ0O1xuICAgIC8qKlxuICAgICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuZSA9IGNvbmZpZy5lbmQ7XG4gICAgLyoqXG4gICAgICogQGFjY2VzcyBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5pbnZhbGlkID0gY29uZmlnLmludmFsaWQgfHwgbnVsbDtcbiAgICAvKipcbiAgICAgKiBAYWNjZXNzIHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLmlzTHV4b25JbnRlcnZhbCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGFuIGludmFsaWQgSW50ZXJ2YWwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSByZWFzb24gLSBzaW1wbGUgc3RyaW5nIG9mIHdoeSB0aGlzIEludGVydmFsIGlzIGludmFsaWQuIFNob3VsZCBub3QgY29udGFpbiBwYXJhbWV0ZXJzIG9yIGFueXRoaW5nIGVsc2UgZGF0YS1kZXBlbmRlbnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtleHBsYW5hdGlvbj1udWxsXSAtIGxvbmdlciBleHBsYW5hdGlvbiwgbWF5IGluY2x1ZGUgcGFyYW1ldGVycyBhbmQgb3RoZXIgdXNlZnVsIGRlYnVnZ2luZyBpbmZvcm1hdGlvblxuICAgKiBAcmV0dXJuIHtJbnRlcnZhbH1cbiAgICovXG4gIHN0YXRpYyBpbnZhbGlkKHJlYXNvbiwgZXhwbGFuYXRpb24gPSBudWxsKSB7XG4gICAgaWYgKCFyZWFzb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihcIm5lZWQgdG8gc3BlY2lmeSBhIHJlYXNvbiB0aGUgSW50ZXJ2YWwgaXMgaW52YWxpZFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnZhbGlkID0gcmVhc29uIGluc3RhbmNlb2YgSW52YWxpZCA/IHJlYXNvbiA6IG5ldyBJbnZhbGlkKHJlYXNvbiwgZXhwbGFuYXRpb24pO1xuXG4gICAgaWYgKFNldHRpbmdzLnRocm93T25JbnZhbGlkKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZEludGVydmFsRXJyb3IoaW52YWxpZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgSW50ZXJ2YWwoeyBpbnZhbGlkIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW4gSW50ZXJ2YWwgZnJvbSBhIHN0YXJ0IERhdGVUaW1lIGFuZCBhbiBlbmQgRGF0ZVRpbWUuIEluY2x1c2l2ZSBvZiB0aGUgc3RhcnQgYnV0IG5vdCB0aGUgZW5kLlxuICAgKiBAcGFyYW0ge0RhdGVUaW1lfERhdGV8T2JqZWN0fSBzdGFydFxuICAgKiBAcGFyYW0ge0RhdGVUaW1lfERhdGV8T2JqZWN0fSBlbmRcbiAgICogQHJldHVybiB7SW50ZXJ2YWx9XG4gICAqL1xuICBzdGF0aWMgZnJvbURhdGVUaW1lcyhzdGFydCwgZW5kKSB7XG4gICAgY29uc3QgYnVpbHRTdGFydCA9IGZyaWVuZGx5RGF0ZVRpbWUoc3RhcnQpLFxuICAgICAgYnVpbHRFbmQgPSBmcmllbmRseURhdGVUaW1lKGVuZCk7XG5cbiAgICBjb25zdCB2YWxpZGF0ZUVycm9yID0gdmFsaWRhdGVTdGFydEVuZChidWlsdFN0YXJ0LCBidWlsdEVuZCk7XG5cbiAgICBpZiAodmFsaWRhdGVFcnJvciA9PSBudWxsKSB7XG4gICAgICByZXR1cm4gbmV3IEludGVydmFsKHtcbiAgICAgICAgc3RhcnQ6IGJ1aWx0U3RhcnQsXG4gICAgICAgIGVuZDogYnVpbHRFbmQsXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHZhbGlkYXRlRXJyb3I7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhbiBJbnRlcnZhbCBmcm9tIGEgc3RhcnQgRGF0ZVRpbWUgYW5kIGEgRHVyYXRpb24gdG8gZXh0ZW5kIHRvLlxuICAgKiBAcGFyYW0ge0RhdGVUaW1lfERhdGV8T2JqZWN0fSBzdGFydFxuICAgKiBAcGFyYW0ge0R1cmF0aW9ufE9iamVjdHxudW1iZXJ9IGR1cmF0aW9uIC0gdGhlIGxlbmd0aCBvZiB0aGUgSW50ZXJ2YWwuXG4gICAqIEByZXR1cm4ge0ludGVydmFsfVxuICAgKi9cbiAgc3RhdGljIGFmdGVyKHN0YXJ0LCBkdXJhdGlvbikge1xuICAgIGNvbnN0IGR1ciA9IER1cmF0aW9uLmZyb21EdXJhdGlvbkxpa2UoZHVyYXRpb24pLFxuICAgICAgZHQgPSBmcmllbmRseURhdGVUaW1lKHN0YXJ0KTtcbiAgICByZXR1cm4gSW50ZXJ2YWwuZnJvbURhdGVUaW1lcyhkdCwgZHQucGx1cyhkdXIpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW4gSW50ZXJ2YWwgZnJvbSBhbiBlbmQgRGF0ZVRpbWUgYW5kIGEgRHVyYXRpb24gdG8gZXh0ZW5kIGJhY2t3YXJkcyB0by5cbiAgICogQHBhcmFtIHtEYXRlVGltZXxEYXRlfE9iamVjdH0gZW5kXG4gICAqIEBwYXJhbSB7RHVyYXRpb258T2JqZWN0fG51bWJlcn0gZHVyYXRpb24gLSB0aGUgbGVuZ3RoIG9mIHRoZSBJbnRlcnZhbC5cbiAgICogQHJldHVybiB7SW50ZXJ2YWx9XG4gICAqL1xuICBzdGF0aWMgYmVmb3JlKGVuZCwgZHVyYXRpb24pIHtcbiAgICBjb25zdCBkdXIgPSBEdXJhdGlvbi5mcm9tRHVyYXRpb25MaWtlKGR1cmF0aW9uKSxcbiAgICAgIGR0ID0gZnJpZW5kbHlEYXRlVGltZShlbmQpO1xuICAgIHJldHVybiBJbnRlcnZhbC5mcm9tRGF0ZVRpbWVzKGR0Lm1pbnVzKGR1ciksIGR0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYW4gSW50ZXJ2YWwgZnJvbSBhbiBJU08gODYwMSBzdHJpbmcuXG4gICAqIEFjY2VwdHMgYDxzdGFydD4vPGVuZD5gLCBgPHN0YXJ0Pi88ZHVyYXRpb24+YCwgYW5kIGA8ZHVyYXRpb24+LzxlbmQ+YCBmb3JtYXRzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCAtIHRoZSBJU08gc3RyaW5nIHRvIHBhcnNlXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBbb3B0c10gLSBvcHRpb25zIHRvIHBhc3Mge0BsaW5rIERhdGVUaW1lI2Zyb21JU099IGFuZCBvcHRpb25hbGx5IHtAbGluayBEdXJhdGlvbiNmcm9tSVNPfVxuICAgKiBAc2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lTT184NjAxI1RpbWVfaW50ZXJ2YWxzXG4gICAqIEByZXR1cm4ge0ludGVydmFsfVxuICAgKi9cbiAgc3RhdGljIGZyb21JU08odGV4dCwgb3B0cykge1xuICAgIGNvbnN0IFtzLCBlXSA9ICh0ZXh0IHx8IFwiXCIpLnNwbGl0KFwiL1wiLCAyKTtcbiAgICBpZiAocyAmJiBlKSB7XG4gICAgICBsZXQgc3RhcnQsIHN0YXJ0SXNWYWxpZDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHN0YXJ0ID0gRGF0ZVRpbWUuZnJvbUlTTyhzLCBvcHRzKTtcbiAgICAgICAgc3RhcnRJc1ZhbGlkID0gc3RhcnQuaXNWYWxpZDtcbiAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgc3RhcnRJc1ZhbGlkID0gZmFsc2U7XG4gICAgICB9XG5cbiAgICAgIGxldCBlbmQsIGVuZElzVmFsaWQ7XG4gICAgICB0cnkge1xuICAgICAgICBlbmQgPSBEYXRlVGltZS5mcm9tSVNPKGUsIG9wdHMpO1xuICAgICAgICBlbmRJc1ZhbGlkID0gZW5kLmlzVmFsaWQ7XG4gICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGVuZElzVmFsaWQgPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgaWYgKHN0YXJ0SXNWYWxpZCAmJiBlbmRJc1ZhbGlkKSB7XG4gICAgICAgIHJldHVybiBJbnRlcnZhbC5mcm9tRGF0ZVRpbWVzKHN0YXJ0LCBlbmQpO1xuICAgICAgfVxuXG4gICAgICBpZiAoc3RhcnRJc1ZhbGlkKSB7XG4gICAgICAgIGNvbnN0IGR1ciA9IER1cmF0aW9uLmZyb21JU08oZSwgb3B0cyk7XG4gICAgICAgIGlmIChkdXIuaXNWYWxpZCkge1xuICAgICAgICAgIHJldHVybiBJbnRlcnZhbC5hZnRlcihzdGFydCwgZHVyKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChlbmRJc1ZhbGlkKSB7XG4gICAgICAgIGNvbnN0IGR1ciA9IER1cmF0aW9uLmZyb21JU08ocywgb3B0cyk7XG4gICAgICAgIGlmIChkdXIuaXNWYWxpZCkge1xuICAgICAgICAgIHJldHVybiBJbnRlcnZhbC5iZWZvcmUoZW5kLCBkdXIpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBJbnRlcnZhbC5pbnZhbGlkKFwidW5wYXJzYWJsZVwiLCBgdGhlIGlucHV0IFwiJHt0ZXh0fVwiIGNhbid0IGJlIHBhcnNlZCBhcyBJU08gODYwMWApO1xuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIGFuIG9iamVjdCBpcyBhbiBJbnRlcnZhbC4gV29ya3MgYWNyb3NzIGNvbnRleHQgYm91bmRhcmllc1xuICAgKiBAcGFyYW0ge29iamVjdH0gb1xuICAgKiBAcmV0dXJuIHtib29sZWFufVxuICAgKi9cbiAgc3RhdGljIGlzSW50ZXJ2YWwobykge1xuICAgIHJldHVybiAobyAmJiBvLmlzTHV4b25JbnRlcnZhbCkgfHwgZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgc3RhcnQgb2YgdGhlIEludGVydmFsXG4gICAqIEB0eXBlIHtEYXRlVGltZX1cbiAgICovXG4gIGdldCBzdGFydCgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gdGhpcy5zIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBlbmQgb2YgdGhlIEludGVydmFsXG4gICAqIEB0eXBlIHtEYXRlVGltZX1cbiAgICovXG4gIGdldCBlbmQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMuZSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB3aGV0aGVyIHRoaXMgSW50ZXJ2YWwncyBlbmQgaXMgYXQgbGVhc3QgaXRzIHN0YXJ0LCBtZWFuaW5nIHRoYXQgdGhlIEludGVydmFsIGlzbid0ICdiYWNrd2FyZHMnLlxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICovXG4gIGdldCBpc1ZhbGlkKCkge1xuICAgIHJldHVybiB0aGlzLmludmFsaWRSZWFzb24gPT09IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBlcnJvciBjb2RlIGlmIHRoaXMgSW50ZXJ2YWwgaXMgaW52YWxpZCwgb3IgbnVsbCBpZiB0aGUgSW50ZXJ2YWwgaXMgdmFsaWRcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICovXG4gIGdldCBpbnZhbGlkUmVhc29uKCkge1xuICAgIHJldHVybiB0aGlzLmludmFsaWQgPyB0aGlzLmludmFsaWQucmVhc29uIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIGV4cGxhbmF0aW9uIG9mIHdoeSB0aGlzIEludGVydmFsIGJlY2FtZSBpbnZhbGlkLCBvciBudWxsIGlmIHRoZSBJbnRlcnZhbCBpcyB2YWxpZFxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKi9cbiAgZ2V0IGludmFsaWRFeHBsYW5hdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy5pbnZhbGlkID8gdGhpcy5pbnZhbGlkLmV4cGxhbmF0aW9uIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBsZW5ndGggb2YgdGhlIEludGVydmFsIGluIHRoZSBzcGVjaWZpZWQgdW5pdC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHVuaXQgLSB0aGUgdW5pdCAoc3VjaCBhcyAnaG91cnMnIG9yICdkYXlzJykgdG8gcmV0dXJuIHRoZSBsZW5ndGggaW4uXG4gICAqIEByZXR1cm4ge251bWJlcn1cbiAgICovXG4gIGxlbmd0aCh1bml0ID0gXCJtaWxsaXNlY29uZHNcIikge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLnRvRHVyYXRpb24oLi4uW3VuaXRdKS5nZXQodW5pdCkgOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgY291bnQgb2YgbWludXRlcywgaG91cnMsIGRheXMsIG1vbnRocywgb3IgeWVhcnMgaW5jbHVkZWQgaW4gdGhlIEludGVydmFsLCBldmVuIGluIHBhcnQuXG4gICAqIFVubGlrZSB7QGxpbmsgSW50ZXJ2YWwjbGVuZ3RofSB0aGlzIGNvdW50cyBzZWN0aW9ucyBvZiB0aGUgY2FsZW5kYXIsIG5vdCBwZXJpb2RzIG9mIHRpbWUsIGUuZy4gc3BlY2lmeWluZyAnZGF5J1xuICAgKiBhc2tzICd3aGF0IGRhdGVzIGFyZSBpbmNsdWRlZCBpbiB0aGlzIGludGVydmFsPycsIG5vdCAnaG93IG1hbnkgZGF5cyBsb25nIGlzIHRoaXMgaW50ZXJ2YWw/J1xuICAgKiBAcGFyYW0ge3N0cmluZ30gW3VuaXQ9J21pbGxpc2Vjb25kcyddIC0gdGhlIHVuaXQgb2YgdGltZSB0byBjb3VudC5cbiAgICogQHJldHVybiB7bnVtYmVyfVxuICAgKi9cbiAgY291bnQodW5pdCA9IFwibWlsbGlzZWNvbmRzXCIpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIE5hTjtcbiAgICBjb25zdCBzdGFydCA9IHRoaXMuc3RhcnQuc3RhcnRPZih1bml0KSxcbiAgICAgIGVuZCA9IHRoaXMuZW5kLnN0YXJ0T2YodW5pdCk7XG4gICAgcmV0dXJuIE1hdGguZmxvb3IoZW5kLmRpZmYoc3RhcnQsIHVuaXQpLmdldCh1bml0KSkgKyAoZW5kLnZhbHVlT2YoKSAhPT0gdGhpcy5lbmQudmFsdWVPZigpKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhpcyBJbnRlcnZhbCdzIHN0YXJ0IGFuZCBlbmQgYXJlIGJvdGggaW4gdGhlIHNhbWUgdW5pdCBvZiB0aW1lXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1bml0IC0gdGhlIHVuaXQgb2YgdGltZSB0byBjaGVjayBzYW1lbmVzcyBvblxuICAgKiBAcmV0dXJuIHtib29sZWFufVxuICAgKi9cbiAgaGFzU2FtZSh1bml0KSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMuaXNFbXB0eSgpIHx8IHRoaXMuZS5taW51cygxKS5oYXNTYW1lKHRoaXMucywgdW5pdCkgOiBmYWxzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gd2hldGhlciB0aGlzIEludGVydmFsIGhhcyB0aGUgc2FtZSBzdGFydCBhbmQgZW5kIERhdGVUaW1lcy5cbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIGlzRW1wdHkoKSB7XG4gICAgcmV0dXJuIHRoaXMucy52YWx1ZU9mKCkgPT09IHRoaXMuZS52YWx1ZU9mKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHdoZXRoZXIgdGhpcyBJbnRlcnZhbCdzIHN0YXJ0IGlzIGFmdGVyIHRoZSBzcGVjaWZpZWQgRGF0ZVRpbWUuXG4gICAqIEBwYXJhbSB7RGF0ZVRpbWV9IGRhdGVUaW1lXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59XG4gICAqL1xuICBpc0FmdGVyKGRhdGVUaW1lKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5zID4gZGF0ZVRpbWU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHdoZXRoZXIgdGhpcyBJbnRlcnZhbCdzIGVuZCBpcyBiZWZvcmUgdGhlIHNwZWNpZmllZCBEYXRlVGltZS5cbiAgICogQHBhcmFtIHtEYXRlVGltZX0gZGF0ZVRpbWVcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIGlzQmVmb3JlKGRhdGVUaW1lKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5lIDw9IGRhdGVUaW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB3aGV0aGVyIHRoaXMgSW50ZXJ2YWwgY29udGFpbnMgdGhlIHNwZWNpZmllZCBEYXRlVGltZS5cbiAgICogQHBhcmFtIHtEYXRlVGltZX0gZGF0ZVRpbWVcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIGNvbnRhaW5zKGRhdGVUaW1lKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5zIDw9IGRhdGVUaW1lICYmIHRoaXMuZSA+IGRhdGVUaW1lO1xuICB9XG5cbiAgLyoqXG4gICAqIFwiU2V0c1wiIHRoZSBzdGFydCBhbmQvb3IgZW5kIGRhdGVzLiBSZXR1cm5zIGEgbmV3bHktY29uc3RydWN0ZWQgSW50ZXJ2YWwuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSB2YWx1ZXMgLSB0aGUgdmFsdWVzIHRvIHNldFxuICAgKiBAcGFyYW0ge0RhdGVUaW1lfSB2YWx1ZXMuc3RhcnQgLSB0aGUgc3RhcnRpbmcgRGF0ZVRpbWVcbiAgICogQHBhcmFtIHtEYXRlVGltZX0gdmFsdWVzLmVuZCAtIHRoZSBlbmRpbmcgRGF0ZVRpbWVcbiAgICogQHJldHVybiB7SW50ZXJ2YWx9XG4gICAqL1xuICBzZXQoeyBzdGFydCwgZW5kIH0gPSB7fSkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gdGhpcztcbiAgICByZXR1cm4gSW50ZXJ2YWwuZnJvbURhdGVUaW1lcyhzdGFydCB8fCB0aGlzLnMsIGVuZCB8fCB0aGlzLmUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNwbGl0IHRoaXMgSW50ZXJ2YWwgYXQgZWFjaCBvZiB0aGUgc3BlY2lmaWVkIERhdGVUaW1lc1xuICAgKiBAcGFyYW0gey4uLkRhdGVUaW1lfSBkYXRlVGltZXMgLSB0aGUgdW5pdCBvZiB0aW1lIHRvIGNvdW50LlxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIHNwbGl0QXQoLi4uZGF0ZVRpbWVzKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiBbXTtcbiAgICBjb25zdCBzb3J0ZWQgPSBkYXRlVGltZXNcbiAgICAgICAgLm1hcChmcmllbmRseURhdGVUaW1lKVxuICAgICAgICAuZmlsdGVyKChkKSA9PiB0aGlzLmNvbnRhaW5zKGQpKVxuICAgICAgICAuc29ydCgpLFxuICAgICAgcmVzdWx0cyA9IFtdO1xuICAgIGxldCB7IHMgfSA9IHRoaXMsXG4gICAgICBpID0gMDtcblxuICAgIHdoaWxlIChzIDwgdGhpcy5lKSB7XG4gICAgICBjb25zdCBhZGRlZCA9IHNvcnRlZFtpXSB8fCB0aGlzLmUsXG4gICAgICAgIG5leHQgPSArYWRkZWQgPiArdGhpcy5lID8gdGhpcy5lIDogYWRkZWQ7XG4gICAgICByZXN1bHRzLnB1c2goSW50ZXJ2YWwuZnJvbURhdGVUaW1lcyhzLCBuZXh0KSk7XG4gICAgICBzID0gbmV4dDtcbiAgICAgIGkgKz0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdCB0aGlzIEludGVydmFsIGludG8gc21hbGxlciBJbnRlcnZhbHMsIGVhY2ggb2YgdGhlIHNwZWNpZmllZCBsZW5ndGguXG4gICAqIExlZnQgb3ZlciB0aW1lIGlzIGdyb3VwZWQgaW50byBhIHNtYWxsZXIgaW50ZXJ2YWxcbiAgICogQHBhcmFtIHtEdXJhdGlvbnxPYmplY3R8bnVtYmVyfSBkdXJhdGlvbiAtIFRoZSBsZW5ndGggb2YgZWFjaCByZXN1bHRpbmcgaW50ZXJ2YWwuXG4gICAqIEByZXR1cm4ge0FycmF5fVxuICAgKi9cbiAgc3BsaXRCeShkdXJhdGlvbikge1xuICAgIGNvbnN0IGR1ciA9IER1cmF0aW9uLmZyb21EdXJhdGlvbkxpa2UoZHVyYXRpb24pO1xuXG4gICAgaWYgKCF0aGlzLmlzVmFsaWQgfHwgIWR1ci5pc1ZhbGlkIHx8IGR1ci5hcyhcIm1pbGxpc2Vjb25kc1wiKSA9PT0gMCkge1xuICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIGxldCB7IHMgfSA9IHRoaXMsXG4gICAgICBpZHggPSAxLFxuICAgICAgbmV4dDtcblxuICAgIGNvbnN0IHJlc3VsdHMgPSBbXTtcbiAgICB3aGlsZSAocyA8IHRoaXMuZSkge1xuICAgICAgY29uc3QgYWRkZWQgPSB0aGlzLnN0YXJ0LnBsdXMoZHVyLm1hcFVuaXRzKCh4KSA9PiB4ICogaWR4KSk7XG4gICAgICBuZXh0ID0gK2FkZGVkID4gK3RoaXMuZSA/IHRoaXMuZSA6IGFkZGVkO1xuICAgICAgcmVzdWx0cy5wdXNoKEludGVydmFsLmZyb21EYXRlVGltZXMocywgbmV4dCkpO1xuICAgICAgcyA9IG5leHQ7XG4gICAgICBpZHggKz0gMTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0cztcbiAgfVxuXG4gIC8qKlxuICAgKiBTcGxpdCB0aGlzIEludGVydmFsIGludG8gdGhlIHNwZWNpZmllZCBudW1iZXIgb2Ygc21hbGxlciBpbnRlcnZhbHMuXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBudW1iZXJPZlBhcnRzIC0gVGhlIG51bWJlciBvZiBJbnRlcnZhbHMgdG8gZGl2aWRlIHRoZSBJbnRlcnZhbCBpbnRvLlxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIGRpdmlkZUVxdWFsbHkobnVtYmVyT2ZQYXJ0cykge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gW107XG4gICAgcmV0dXJuIHRoaXMuc3BsaXRCeSh0aGlzLmxlbmd0aCgpIC8gbnVtYmVyT2ZQYXJ0cykuc2xpY2UoMCwgbnVtYmVyT2ZQYXJ0cyk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHdoZXRoZXIgdGhpcyBJbnRlcnZhbCBvdmVybGFwcyB3aXRoIHRoZSBzcGVjaWZpZWQgSW50ZXJ2YWxcbiAgICogQHBhcmFtIHtJbnRlcnZhbH0gb3RoZXJcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIG92ZXJsYXBzKG90aGVyKSB7XG4gICAgcmV0dXJuIHRoaXMuZSA+IG90aGVyLnMgJiYgdGhpcy5zIDwgb3RoZXIuZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gd2hldGhlciB0aGlzIEludGVydmFsJ3MgZW5kIGlzIGFkamFjZW50IHRvIHRoZSBzcGVjaWZpZWQgSW50ZXJ2YWwncyBzdGFydC5cbiAgICogQHBhcmFtIHtJbnRlcnZhbH0gb3RoZXJcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIGFidXRzU3RhcnQob3RoZXIpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIGZhbHNlO1xuICAgIHJldHVybiArdGhpcy5lID09PSArb3RoZXIucztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gd2hldGhlciB0aGlzIEludGVydmFsJ3Mgc3RhcnQgaXMgYWRqYWNlbnQgdG8gdGhlIHNwZWNpZmllZCBJbnRlcnZhbCdzIGVuZC5cbiAgICogQHBhcmFtIHtJbnRlcnZhbH0gb3RoZXJcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIGFidXRzRW5kKG90aGVyKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gK290aGVyLmUgPT09ICt0aGlzLnM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHdoZXRoZXIgdGhpcyBJbnRlcnZhbCBlbmd1bGZzIHRoZSBzdGFydCBhbmQgZW5kIG9mIHRoZSBzcGVjaWZpZWQgSW50ZXJ2YWwuXG4gICAqIEBwYXJhbSB7SW50ZXJ2YWx9IG90aGVyXG4gICAqIEByZXR1cm4ge2Jvb2xlYW59XG4gICAqL1xuICBlbmd1bGZzKG90aGVyKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdGhpcy5zIDw9IG90aGVyLnMgJiYgdGhpcy5lID49IG90aGVyLmU7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIHdoZXRoZXIgdGhpcyBJbnRlcnZhbCBoYXMgdGhlIHNhbWUgc3RhcnQgYW5kIGVuZCBhcyB0aGUgc3BlY2lmaWVkIEludGVydmFsLlxuICAgKiBAcGFyYW0ge0ludGVydmFsfSBvdGhlclxuICAgKiBAcmV0dXJuIHtib29sZWFufVxuICAgKi9cbiAgZXF1YWxzKG90aGVyKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQgfHwgIW90aGVyLmlzVmFsaWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zLmVxdWFscyhvdGhlci5zKSAmJiB0aGlzLmUuZXF1YWxzKG90aGVyLmUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbiBJbnRlcnZhbCByZXByZXNlbnRpbmcgdGhlIGludGVyc2VjdGlvbiBvZiB0aGlzIEludGVydmFsIGFuZCB0aGUgc3BlY2lmaWVkIEludGVydmFsLlxuICAgKiBTcGVjaWZpY2FsbHksIHRoZSByZXN1bHRpbmcgSW50ZXJ2YWwgaGFzIHRoZSBtYXhpbXVtIHN0YXJ0IHRpbWUgYW5kIHRoZSBtaW5pbXVtIGVuZCB0aW1lIG9mIHRoZSB0d28gSW50ZXJ2YWxzLlxuICAgKiBSZXR1cm5zIG51bGwgaWYgdGhlIGludGVyc2VjdGlvbiBpcyBlbXB0eSwgbWVhbmluZywgdGhlIGludGVydmFscyBkb24ndCBpbnRlcnNlY3QuXG4gICAqIEBwYXJhbSB7SW50ZXJ2YWx9IG90aGVyXG4gICAqIEByZXR1cm4ge0ludGVydmFsfVxuICAgKi9cbiAgaW50ZXJzZWN0aW9uKG90aGVyKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiB0aGlzO1xuICAgIGNvbnN0IHMgPSB0aGlzLnMgPiBvdGhlci5zID8gdGhpcy5zIDogb3RoZXIucyxcbiAgICAgIGUgPSB0aGlzLmUgPCBvdGhlci5lID8gdGhpcy5lIDogb3RoZXIuZTtcblxuICAgIGlmIChzID49IGUpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gSW50ZXJ2YWwuZnJvbURhdGVUaW1lcyhzLCBlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGFuIEludGVydmFsIHJlcHJlc2VudGluZyB0aGUgdW5pb24gb2YgdGhpcyBJbnRlcnZhbCBhbmQgdGhlIHNwZWNpZmllZCBJbnRlcnZhbC5cbiAgICogU3BlY2lmaWNhbGx5LCB0aGUgcmVzdWx0aW5nIEludGVydmFsIGhhcyB0aGUgbWluaW11bSBzdGFydCB0aW1lIGFuZCB0aGUgbWF4aW11bSBlbmQgdGltZSBvZiB0aGUgdHdvIEludGVydmFscy5cbiAgICogQHBhcmFtIHtJbnRlcnZhbH0gb3RoZXJcbiAgICogQHJldHVybiB7SW50ZXJ2YWx9XG4gICAqL1xuICB1bmlvbihvdGhlcikge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gdGhpcztcbiAgICBjb25zdCBzID0gdGhpcy5zIDwgb3RoZXIucyA/IHRoaXMucyA6IG90aGVyLnMsXG4gICAgICBlID0gdGhpcy5lID4gb3RoZXIuZSA/IHRoaXMuZSA6IG90aGVyLmU7XG4gICAgcmV0dXJuIEludGVydmFsLmZyb21EYXRlVGltZXMocywgZSk7XG4gIH1cblxuICAvKipcbiAgICogTWVyZ2UgYW4gYXJyYXkgb2YgSW50ZXJ2YWxzIGludG8gYSBlcXVpdmFsZW50IG1pbmltYWwgc2V0IG9mIEludGVydmFscy5cbiAgICogQ29tYmluZXMgb3ZlcmxhcHBpbmcgYW5kIGFkamFjZW50IEludGVydmFscy5cbiAgICogQHBhcmFtIHtBcnJheX0gaW50ZXJ2YWxzXG4gICAqIEByZXR1cm4ge0FycmF5fVxuICAgKi9cbiAgc3RhdGljIG1lcmdlKGludGVydmFscykge1xuICAgIGNvbnN0IFtmb3VuZCwgZmluYWxdID0gaW50ZXJ2YWxzXG4gICAgICAuc29ydCgoYSwgYikgPT4gYS5zIC0gYi5zKVxuICAgICAgLnJlZHVjZShcbiAgICAgICAgKFtzb2ZhciwgY3VycmVudF0sIGl0ZW0pID0+IHtcbiAgICAgICAgICBpZiAoIWN1cnJlbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBbc29mYXIsIGl0ZW1dO1xuICAgICAgICAgIH0gZWxzZSBpZiAoY3VycmVudC5vdmVybGFwcyhpdGVtKSB8fCBjdXJyZW50LmFidXRzU3RhcnQoaXRlbSkpIHtcbiAgICAgICAgICAgIHJldHVybiBbc29mYXIsIGN1cnJlbnQudW5pb24oaXRlbSldO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gW3NvZmFyLmNvbmNhdChbY3VycmVudF0pLCBpdGVtXTtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICAgIFtbXSwgbnVsbF1cbiAgICAgICk7XG4gICAgaWYgKGZpbmFsKSB7XG4gICAgICBmb3VuZC5wdXNoKGZpbmFsKTtcbiAgICB9XG4gICAgcmV0dXJuIGZvdW5kO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbiBhcnJheSBvZiBJbnRlcnZhbHMgcmVwcmVzZW50aW5nIHRoZSBzcGFucyBvZiB0aW1lIHRoYXQgb25seSBhcHBlYXIgaW4gb25lIG9mIHRoZSBzcGVjaWZpZWQgSW50ZXJ2YWxzLlxuICAgKiBAcGFyYW0ge0FycmF5fSBpbnRlcnZhbHNcbiAgICogQHJldHVybiB7QXJyYXl9XG4gICAqL1xuICBzdGF0aWMgeG9yKGludGVydmFscykge1xuICAgIGxldCBzdGFydCA9IG51bGwsXG4gICAgICBjdXJyZW50Q291bnQgPSAwO1xuICAgIGNvbnN0IHJlc3VsdHMgPSBbXSxcbiAgICAgIGVuZHMgPSBpbnRlcnZhbHMubWFwKChpKSA9PiBbXG4gICAgICAgIHsgdGltZTogaS5zLCB0eXBlOiBcInNcIiB9LFxuICAgICAgICB7IHRpbWU6IGkuZSwgdHlwZTogXCJlXCIgfSxcbiAgICAgIF0pLFxuICAgICAgZmxhdHRlbmVkID0gQXJyYXkucHJvdG90eXBlLmNvbmNhdCguLi5lbmRzKSxcbiAgICAgIGFyciA9IGZsYXR0ZW5lZC5zb3J0KChhLCBiKSA9PiBhLnRpbWUgLSBiLnRpbWUpO1xuXG4gICAgZm9yIChjb25zdCBpIG9mIGFycikge1xuICAgICAgY3VycmVudENvdW50ICs9IGkudHlwZSA9PT0gXCJzXCIgPyAxIDogLTE7XG5cbiAgICAgIGlmIChjdXJyZW50Q291bnQgPT09IDEpIHtcbiAgICAgICAgc3RhcnQgPSBpLnRpbWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAoc3RhcnQgJiYgK3N0YXJ0ICE9PSAraS50aW1lKSB7XG4gICAgICAgICAgcmVzdWx0cy5wdXNoKEludGVydmFsLmZyb21EYXRlVGltZXMoc3RhcnQsIGkudGltZSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgc3RhcnQgPSBudWxsO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBJbnRlcnZhbC5tZXJnZShyZXN1bHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYW4gSW50ZXJ2YWwgcmVwcmVzZW50aW5nIHRoZSBzcGFuIG9mIHRpbWUgaW4gdGhpcyBJbnRlcnZhbCB0aGF0IGRvZXNuJ3Qgb3ZlcmxhcCB3aXRoIGFueSBvZiB0aGUgc3BlY2lmaWVkIEludGVydmFscy5cbiAgICogQHBhcmFtIHsuLi5JbnRlcnZhbH0gaW50ZXJ2YWxzXG4gICAqIEByZXR1cm4ge0FycmF5fVxuICAgKi9cbiAgZGlmZmVyZW5jZSguLi5pbnRlcnZhbHMpIHtcbiAgICByZXR1cm4gSW50ZXJ2YWwueG9yKFt0aGlzXS5jb25jYXQoaW50ZXJ2YWxzKSlcbiAgICAgIC5tYXAoKGkpID0+IHRoaXMuaW50ZXJzZWN0aW9uKGkpKVxuICAgICAgLmZpbHRlcigoaSkgPT4gaSAmJiAhaS5pc0VtcHR5KCkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBJbnRlcnZhbCBhcHByb3ByaWF0ZSBmb3IgZGVidWdnaW5nLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b1N0cmluZygpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIElOVkFMSUQ7XG4gICAgcmV0dXJuIGBbJHt0aGlzLnMudG9JU08oKX0gXHUyMDEzICR7dGhpcy5lLnRvSVNPKCl9KWA7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxvY2FsaXplZCBzdHJpbmcgcmVwcmVzZW50aW5nIHRoaXMgSW50ZXJ2YWwuIEFjY2VwdHMgdGhlIHNhbWUgb3B0aW9ucyBhcyB0aGVcbiAgICogSW50bC5EYXRlVGltZUZvcm1hdCBjb25zdHJ1Y3RvciBhbmQgYW55IHByZXNldHMgZGVmaW5lZCBieSBMdXhvbiwgc3VjaCBhc1xuICAgKiB7QGxpbmsgRGF0ZVRpbWUuREFURV9GVUxMfSBvciB7QGxpbmsgRGF0ZVRpbWUuVElNRV9TSU1QTEV9LiBUaGUgZXhhY3QgYmVoYXZpb3Igb2YgdGhpcyBtZXRob2RcbiAgICogaXMgYnJvd3Nlci1zcGVjaWZpYywgYnV0IGluIGdlbmVyYWwgaXQgd2lsbCByZXR1cm4gYW4gYXBwcm9wcmlhdGUgcmVwcmVzZW50YXRpb24gb2YgdGhlXG4gICAqIEludGVydmFsIGluIHRoZSBhc3NpZ25lZCBsb2NhbGUuIERlZmF1bHRzIHRvIHRoZSBzeXN0ZW0ncyBsb2NhbGUgaWYgbm8gbG9jYWxlIGhhcyBiZWVuXG4gICAqIHNwZWNpZmllZC5cbiAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9EYXRlVGltZUZvcm1hdFxuICAgKiBAcGFyYW0ge09iamVjdH0gW2Zvcm1hdE9wdHM9RGF0ZVRpbWUuREFURV9TSE9SVF0gLSBFaXRoZXIgYSBEYXRlVGltZSBwcmVzZXQgb3JcbiAgICogSW50bC5EYXRlVGltZUZvcm1hdCBjb25zdHJ1Y3RvciBvcHRpb25zLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIE9wdGlvbnMgdG8gb3ZlcnJpZGUgdGhlIGNvbmZpZ3VyYXRpb24gb2YgdGhlIHN0YXJ0IERhdGVUaW1lLlxuICAgKiBAZXhhbXBsZSBJbnRlcnZhbC5mcm9tSVNPKCcyMDIyLTExLTA3VDA5OjAwWi8yMDIyLTExLTA4VDA5OjAwWicpLnRvTG9jYWxlU3RyaW5nKCk7IC8vPT4gMTEvNy8yMDIyIFx1MjAxMyAxMS84LzIwMjJcbiAgICogQGV4YW1wbGUgSW50ZXJ2YWwuZnJvbUlTTygnMjAyMi0xMS0wN1QwOTowMFovMjAyMi0xMS0wOFQwOTowMFonKS50b0xvY2FsZVN0cmluZyhEYXRlVGltZS5EQVRFX0ZVTEwpOyAvLz0+IE5vdmVtYmVyIDcgXHUyMDEzIDgsIDIwMjJcbiAgICogQGV4YW1wbGUgSW50ZXJ2YWwuZnJvbUlTTygnMjAyMi0xMS0wN1QwOTowMFovMjAyMi0xMS0wOFQwOTowMFonKS50b0xvY2FsZVN0cmluZyhEYXRlVGltZS5EQVRFX0ZVTEwsIHsgbG9jYWxlOiAnZnItRlInIH0pOyAvLz0+IDdcdTIwMTM4IG5vdmVtYnJlIDIwMjJcbiAgICogQGV4YW1wbGUgSW50ZXJ2YWwuZnJvbUlTTygnMjAyMi0xMS0wN1QxNzowMFovMjAyMi0xMS0wN1QxOTowMFonKS50b0xvY2FsZVN0cmluZyhEYXRlVGltZS5USU1FX1NJTVBMRSk7IC8vPT4gNjowMCBcdTIwMTMgODowMCBQTVxuICAgKiBAZXhhbXBsZSBJbnRlcnZhbC5mcm9tSVNPKCcyMDIyLTExLTA3VDE3OjAwWi8yMDIyLTExLTA3VDE5OjAwWicpLnRvTG9jYWxlU3RyaW5nKHsgd2Vla2RheTogJ3Nob3J0JywgbW9udGg6ICdzaG9ydCcsIGRheTogJzItZGlnaXQnLCBob3VyOiAnMi1kaWdpdCcsIG1pbnV0ZTogJzItZGlnaXQnIH0pOyAvLz0+IE1vbiwgTm92IDA3LCA2OjAwIFx1MjAxMyA4OjAwIHBcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgdG9Mb2NhbGVTdHJpbmcoZm9ybWF0T3B0cyA9IEZvcm1hdHMuREFURV9TSE9SVCwgb3B0cyA9IHt9KSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZFxuICAgICAgPyBGb3JtYXR0ZXIuY3JlYXRlKHRoaXMucy5sb2MuY2xvbmUob3B0cyksIGZvcm1hdE9wdHMpLmZvcm1hdEludGVydmFsKHRoaXMpXG4gICAgICA6IElOVkFMSUQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBJU08gODYwMS1jb21wbGlhbnQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgSW50ZXJ2YWwuXG4gICAqIEBzZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzg2MDEjVGltZV9pbnRlcnZhbHNcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBUaGUgc2FtZSBvcHRpb25zIGFzIHtAbGluayBEYXRlVGltZSN0b0lTT31cbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgdG9JU08ob3B0cykge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gSU5WQUxJRDtcbiAgICByZXR1cm4gYCR7dGhpcy5zLnRvSVNPKG9wdHMpfS8ke3RoaXMuZS50b0lTTyhvcHRzKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gSVNPIDg2MDEtY29tcGxpYW50IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiBkYXRlIG9mIHRoaXMgSW50ZXJ2YWwuXG4gICAqIFRoZSB0aW1lIGNvbXBvbmVudHMgYXJlIGlnbm9yZWQuXG4gICAqIEBzZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzg2MDEjVGltZV9pbnRlcnZhbHNcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgdG9JU09EYXRlKCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gSU5WQUxJRDtcbiAgICByZXR1cm4gYCR7dGhpcy5zLnRvSVNPRGF0ZSgpfS8ke3RoaXMuZS50b0lTT0RhdGUoKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gSVNPIDg2MDEtY29tcGxpYW50IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aW1lIG9mIHRoaXMgSW50ZXJ2YWwuXG4gICAqIFRoZSBkYXRlIGNvbXBvbmVudHMgYXJlIGlnbm9yZWQuXG4gICAqIEBzZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPXzg2MDEjVGltZV9pbnRlcnZhbHNcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBUaGUgc2FtZSBvcHRpb25zIGFzIHtAbGluayBEYXRlVGltZSN0b0lTT31cbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgdG9JU09UaW1lKG9wdHMpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIElOVkFMSUQ7XG4gICAgcmV0dXJuIGAke3RoaXMucy50b0lTT1RpbWUob3B0cyl9LyR7dGhpcy5lLnRvSVNPVGltZShvcHRzKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBJbnRlcnZhbCBmb3JtYXR0ZWQgYWNjb3JkaW5nIHRvIHRoZSBzcGVjaWZpZWQgZm9ybWF0XG4gICAqIHN0cmluZy4gKipZb3UgbWF5IG5vdCB3YW50IHRoaXMuKiogU2VlIHtAbGluayBJbnRlcnZhbCN0b0xvY2FsZVN0cmluZ30gZm9yIGEgbW9yZSBmbGV4aWJsZVxuICAgKiBmb3JtYXR0aW5nIHRvb2wuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBkYXRlRm9ybWF0IC0gVGhlIGZvcm1hdCBzdHJpbmcuIFRoaXMgc3RyaW5nIGZvcm1hdHMgdGhlIHN0YXJ0IGFuZCBlbmQgdGltZS5cbiAgICogU2VlIHtAbGluayBEYXRlVGltZSN0b0Zvcm1hdH0gZm9yIGRldGFpbHMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gT3B0aW9ucy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLnNlcGFyYXRvciA9ICAnIFx1MjAxMyAnXSAtIEEgc2VwYXJhdG9yIHRvIHBsYWNlIGJldHdlZW4gdGhlIHN0YXJ0IGFuZCBlbmRcbiAgICogcmVwcmVzZW50YXRpb25zLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b0Zvcm1hdChkYXRlRm9ybWF0LCB7IHNlcGFyYXRvciA9IFwiIFx1MjAxMyBcIiB9ID0ge30pIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIElOVkFMSUQ7XG4gICAgcmV0dXJuIGAke3RoaXMucy50b0Zvcm1hdChkYXRlRm9ybWF0KX0ke3NlcGFyYXRvcn0ke3RoaXMuZS50b0Zvcm1hdChkYXRlRm9ybWF0KX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhIER1cmF0aW9uIHJlcHJlc2VudGluZyB0aGUgdGltZSBzcGFubmVkIGJ5IHRoaXMgaW50ZXJ2YWwuXG4gICAqIEBwYXJhbSB7c3RyaW5nfHN0cmluZ1tdfSBbdW5pdD1bJ21pbGxpc2Vjb25kcyddXSAtIHRoZSB1bml0IG9yIHVuaXRzIChzdWNoIGFzICdob3Vycycgb3IgJ2RheXMnKSB0byBpbmNsdWRlIGluIHRoZSBkdXJhdGlvbi5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBvcHRpb25zIHRoYXQgYWZmZWN0IHRoZSBjcmVhdGlvbiBvZiB0aGUgRHVyYXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmNvbnZlcnNpb25BY2N1cmFjeT0nY2FzdWFsJ10gLSB0aGUgY29udmVyc2lvbiBzeXN0ZW0gdG8gdXNlXG4gICAqIEBleGFtcGxlIEludGVydmFsLmZyb21EYXRlVGltZXMoZHQxLCBkdDIpLnRvRHVyYXRpb24oKS50b09iamVjdCgpIC8vPT4geyBtaWxsaXNlY29uZHM6IDg4NDg5MjU3IH1cbiAgICogQGV4YW1wbGUgSW50ZXJ2YWwuZnJvbURhdGVUaW1lcyhkdDEsIGR0MikudG9EdXJhdGlvbignZGF5cycpLnRvT2JqZWN0KCkgLy89PiB7IGRheXM6IDEuMDI0MTgxMjE1Mjc3Nzc3OCB9XG4gICAqIEBleGFtcGxlIEludGVydmFsLmZyb21EYXRlVGltZXMoZHQxLCBkdDIpLnRvRHVyYXRpb24oWydob3VycycsICdtaW51dGVzJ10pLnRvT2JqZWN0KCkgLy89PiB7IGhvdXJzOiAyNCwgbWludXRlczogMzQuODIwOTUgfVxuICAgKiBAZXhhbXBsZSBJbnRlcnZhbC5mcm9tRGF0ZVRpbWVzKGR0MSwgZHQyKS50b0R1cmF0aW9uKFsnaG91cnMnLCAnbWludXRlcycsICdzZWNvbmRzJ10pLnRvT2JqZWN0KCkgLy89PiB7IGhvdXJzOiAyNCwgbWludXRlczogMzQsIHNlY29uZHM6IDQ5LjI1NyB9XG4gICAqIEBleGFtcGxlIEludGVydmFsLmZyb21EYXRlVGltZXMoZHQxLCBkdDIpLnRvRHVyYXRpb24oJ3NlY29uZHMnKS50b09iamVjdCgpIC8vPT4geyBzZWNvbmRzOiA4ODQ4OS4yNTcgfVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIHRvRHVyYXRpb24odW5pdCwgb3B0cykge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSB7XG4gICAgICByZXR1cm4gRHVyYXRpb24uaW52YWxpZCh0aGlzLmludmFsaWRSZWFzb24pO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5lLmRpZmYodGhpcy5zLCB1bml0LCBvcHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSdW4gbWFwRm4gb24gdGhlIGludGVydmFsIHN0YXJ0IGFuZCBlbmQsIHJldHVybmluZyBhIG5ldyBJbnRlcnZhbCBmcm9tIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWVzXG4gICAqIEBwYXJhbSB7ZnVuY3Rpb259IG1hcEZuXG4gICAqIEByZXR1cm4ge0ludGVydmFsfVxuICAgKiBAZXhhbXBsZSBJbnRlcnZhbC5mcm9tRGF0ZVRpbWVzKGR0MSwgZHQyKS5tYXBFbmRwb2ludHMoZW5kcG9pbnQgPT4gZW5kcG9pbnQudG9VVEMoKSlcbiAgICogQGV4YW1wbGUgSW50ZXJ2YWwuZnJvbURhdGVUaW1lcyhkdDEsIGR0MikubWFwRW5kcG9pbnRzKGVuZHBvaW50ID0+IGVuZHBvaW50LnBsdXMoeyBob3VyczogMiB9KSlcbiAgICovXG4gIG1hcEVuZHBvaW50cyhtYXBGbikge1xuICAgIHJldHVybiBJbnRlcnZhbC5mcm9tRGF0ZVRpbWVzKG1hcEZuKHRoaXMucyksIG1hcEZuKHRoaXMuZSkpO1xuICB9XG59XG4iLCAiaW1wb3J0IERhdGVUaW1lIGZyb20gXCIuL2RhdGV0aW1lLmpzXCI7XG5pbXBvcnQgU2V0dGluZ3MgZnJvbSBcIi4vc2V0dGluZ3MuanNcIjtcbmltcG9ydCBMb2NhbGUgZnJvbSBcIi4vaW1wbC9sb2NhbGUuanNcIjtcbmltcG9ydCBJQU5BWm9uZSBmcm9tIFwiLi96b25lcy9JQU5BWm9uZS5qc1wiO1xuaW1wb3J0IHsgbm9ybWFsaXplWm9uZSB9IGZyb20gXCIuL2ltcGwvem9uZVV0aWwuanNcIjtcblxuaW1wb3J0IHsgaGFzUmVsYXRpdmUgfSBmcm9tIFwiLi9pbXBsL3V0aWwuanNcIjtcblxuLyoqXG4gKiBUaGUgSW5mbyBjbGFzcyBjb250YWlucyBzdGF0aWMgbWV0aG9kcyBmb3IgcmV0cmlldmluZyBnZW5lcmFsIHRpbWUgYW5kIGRhdGUgcmVsYXRlZCBkYXRhLiBGb3IgZXhhbXBsZSwgaXQgaGFzIG1ldGhvZHMgZm9yIGZpbmRpbmcgb3V0IGlmIGEgdGltZSB6b25lIGhhcyBhIERTVCwgZm9yIGxpc3RpbmcgdGhlIG1vbnRocyBpbiBhbnkgc3VwcG9ydGVkIGxvY2FsZSwgYW5kIGZvciBkaXNjb3ZlcmluZyB3aGljaCBvZiBMdXhvbiBmZWF0dXJlcyBhcmUgYXZhaWxhYmxlIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50LlxuICovXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBJbmZvIHtcbiAgLyoqXG4gICAqIFJldHVybiB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgem9uZSBjb250YWlucyBhIERTVC5cbiAgICogQHBhcmFtIHtzdHJpbmd8Wm9uZX0gW3pvbmU9J2xvY2FsJ10gLSBab25lIHRvIGNoZWNrLiBEZWZhdWx0cyB0byB0aGUgZW52aXJvbm1lbnQncyBsb2NhbCB6b25lLlxuICAgKiBAcmV0dXJuIHtib29sZWFufVxuICAgKi9cbiAgc3RhdGljIGhhc0RTVCh6b25lID0gU2V0dGluZ3MuZGVmYXVsdFpvbmUpIHtcbiAgICBjb25zdCBwcm90byA9IERhdGVUaW1lLm5vdygpLnNldFpvbmUoem9uZSkuc2V0KHsgbW9udGg6IDEyIH0pO1xuXG4gICAgcmV0dXJuICF6b25lLmlzVW5pdmVyc2FsICYmIHByb3RvLm9mZnNldCAhPT0gcHJvdG8uc2V0KHsgbW9udGg6IDYgfSkub2Zmc2V0O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB3aGV0aGVyIHRoZSBzcGVjaWZpZWQgem9uZSBpcyBhIHZhbGlkIElBTkEgc3BlY2lmaWVyLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gem9uZSAtIFpvbmUgdG8gY2hlY2tcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBpc1ZhbGlkSUFOQVpvbmUoem9uZSkge1xuICAgIHJldHVybiBJQU5BWm9uZS5pc1ZhbGlkWm9uZSh6b25lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyB0aGUgaW5wdXQgaW50byBhIHtAbGluayBab25lfSBpbnN0YW5jZS5cbiAgICpcbiAgICogKiBJZiBgaW5wdXRgIGlzIGFscmVhZHkgYSBab25lIGluc3RhbmNlLCBpdCBpcyByZXR1cm5lZCB1bmNoYW5nZWQuXG4gICAqICogSWYgYGlucHV0YCBpcyBhIHN0cmluZyBjb250YWluaW5nIGEgdmFsaWQgdGltZSB6b25lIG5hbWUsIGEgWm9uZSBpbnN0YW5jZVxuICAgKiAgIHdpdGggdGhhdCBuYW1lIGlzIHJldHVybmVkLlxuICAgKiAqIElmIGBpbnB1dGAgaXMgYSBzdHJpbmcgdGhhdCBkb2Vzbid0IHJlZmVyIHRvIGEga25vd24gdGltZSB6b25lLCBhIFpvbmVcbiAgICogICBpbnN0YW5jZSB3aXRoIHtAbGluayBab25lI2lzVmFsaWR9ID09IGZhbHNlIGlzIHJldHVybmVkLlxuICAgKiAqIElmIGBpbnB1dCBpcyBhIG51bWJlciwgYSBab25lIGluc3RhbmNlIHdpdGggdGhlIHNwZWNpZmllZCBmaXhlZCBvZmZzZXRcbiAgICogICBpbiBtaW51dGVzIGlzIHJldHVybmVkLlxuICAgKiAqIElmIGBpbnB1dGAgaXMgYG51bGxgIG9yIGB1bmRlZmluZWRgLCB0aGUgZGVmYXVsdCB6b25lIGlzIHJldHVybmVkLlxuICAgKiBAcGFyYW0ge3N0cmluZ3xab25lfG51bWJlcn0gW2lucHV0XSAtIHRoZSB2YWx1ZSB0byBiZSBjb252ZXJ0ZWRcbiAgICogQHJldHVybiB7Wm9uZX1cbiAgICovXG4gIHN0YXRpYyBub3JtYWxpemVab25lKGlucHV0KSB7XG4gICAgcmV0dXJuIG5vcm1hbGl6ZVpvbmUoaW5wdXQsIFNldHRpbmdzLmRlZmF1bHRab25lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYW4gYXJyYXkgb2Ygc3RhbmRhbG9uZSBtb250aCBuYW1lcy5cbiAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9EYXRlVGltZUZvcm1hdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xlbmd0aD0nbG9uZyddIC0gdGhlIGxlbmd0aCBvZiB0aGUgbW9udGggcmVwcmVzZW50YXRpb24sIHN1Y2ggYXMgXCJudW1lcmljXCIsIFwiMi1kaWdpdFwiLCBcIm5hcnJvd1wiLCBcInNob3J0XCIsIFwibG9uZ1wiXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubG9jYWxlXSAtIHRoZSBsb2NhbGUgY29kZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubnVtYmVyaW5nU3lzdGVtPW51bGxdIC0gdGhlIG51bWJlcmluZyBzeXN0ZW1cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmxvY09iaj1udWxsXSAtIGFuIGV4aXN0aW5nIGxvY2FsZSBvYmplY3QgdG8gdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5vdXRwdXRDYWxlbmRhcj0nZ3JlZ29yeSddIC0gdGhlIGNhbGVuZGFyXG4gICAqIEBleGFtcGxlIEluZm8ubW9udGhzKClbMF0gLy89PiAnSmFudWFyeSdcbiAgICogQGV4YW1wbGUgSW5mby5tb250aHMoJ3Nob3J0JylbMF0gLy89PiAnSmFuJ1xuICAgKiBAZXhhbXBsZSBJbmZvLm1vbnRocygnbnVtZXJpYycpWzBdIC8vPT4gJzEnXG4gICAqIEBleGFtcGxlIEluZm8ubW9udGhzKCdzaG9ydCcsIHsgbG9jYWxlOiAnZnItQ0EnIH0gKVswXSAvLz0+ICdqYW52LidcbiAgICogQGV4YW1wbGUgSW5mby5tb250aHMoJ251bWVyaWMnLCB7IGxvY2FsZTogJ2FyJyB9KVswXSAvLz0+ICdcdTA2NjEnXG4gICAqIEBleGFtcGxlIEluZm8ubW9udGhzKCdsb25nJywgeyBvdXRwdXRDYWxlbmRhcjogJ2lzbGFtaWMnIH0pWzBdIC8vPT4gJ1JhYmlcdTAyQkIgSSdcbiAgICogQHJldHVybiB7QXJyYXl9XG4gICAqL1xuICBzdGF0aWMgbW9udGhzKFxuICAgIGxlbmd0aCA9IFwibG9uZ1wiLFxuICAgIHsgbG9jYWxlID0gbnVsbCwgbnVtYmVyaW5nU3lzdGVtID0gbnVsbCwgbG9jT2JqID0gbnVsbCwgb3V0cHV0Q2FsZW5kYXIgPSBcImdyZWdvcnlcIiB9ID0ge31cbiAgKSB7XG4gICAgcmV0dXJuIChsb2NPYmogfHwgTG9jYWxlLmNyZWF0ZShsb2NhbGUsIG51bWJlcmluZ1N5c3RlbSwgb3V0cHV0Q2FsZW5kYXIpKS5tb250aHMobGVuZ3RoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgZm9ybWF0IG1vbnRoIG5hbWVzLlxuICAgKiBGb3JtYXQgbW9udGhzIGRpZmZlciBmcm9tIHN0YW5kYWxvbmUgbW9udGhzIGluIHRoYXQgdGhleSdyZSBtZWFudCB0byBhcHBlYXIgbmV4dCB0byB0aGUgZGF5IG9mIHRoZSBtb250aC4gSW4gc29tZSBsYW5ndWFnZXMsIHRoYXRcbiAgICogY2hhbmdlcyB0aGUgc3RyaW5nLlxuICAgKiBTZWUge0BsaW5rIEluZm8jbW9udGhzfVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xlbmd0aD0nbG9uZyddIC0gdGhlIGxlbmd0aCBvZiB0aGUgbW9udGggcmVwcmVzZW50YXRpb24sIHN1Y2ggYXMgXCJudW1lcmljXCIsIFwiMi1kaWdpdFwiLCBcIm5hcnJvd1wiLCBcInNob3J0XCIsIFwibG9uZ1wiXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubG9jYWxlXSAtIHRoZSBsb2NhbGUgY29kZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubnVtYmVyaW5nU3lzdGVtPW51bGxdIC0gdGhlIG51bWJlcmluZyBzeXN0ZW1cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmxvY09iaj1udWxsXSAtIGFuIGV4aXN0aW5nIGxvY2FsZSBvYmplY3QgdG8gdXNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5vdXRwdXRDYWxlbmRhcj0nZ3JlZ29yeSddIC0gdGhlIGNhbGVuZGFyXG4gICAqIEByZXR1cm4ge0FycmF5fVxuICAgKi9cbiAgc3RhdGljIG1vbnRoc0Zvcm1hdChcbiAgICBsZW5ndGggPSBcImxvbmdcIixcbiAgICB7IGxvY2FsZSA9IG51bGwsIG51bWJlcmluZ1N5c3RlbSA9IG51bGwsIGxvY09iaiA9IG51bGwsIG91dHB1dENhbGVuZGFyID0gXCJncmVnb3J5XCIgfSA9IHt9XG4gICkge1xuICAgIHJldHVybiAobG9jT2JqIHx8IExvY2FsZS5jcmVhdGUobG9jYWxlLCBudW1iZXJpbmdTeXN0ZW0sIG91dHB1dENhbGVuZGFyKSkubW9udGhzKGxlbmd0aCwgdHJ1ZSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJuIGFuIGFycmF5IG9mIHN0YW5kYWxvbmUgd2VlayBuYW1lcy5cbiAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9EYXRlVGltZUZvcm1hdFxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xlbmd0aD0nbG9uZyddIC0gdGhlIGxlbmd0aCBvZiB0aGUgd2Vla2RheSByZXByZXNlbnRhdGlvbiwgc3VjaCBhcyBcIm5hcnJvd1wiLCBcInNob3J0XCIsIFwibG9uZ1wiLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnNcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmxvY2FsZV0gLSB0aGUgbG9jYWxlIGNvZGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLm51bWJlcmluZ1N5c3RlbT1udWxsXSAtIHRoZSBudW1iZXJpbmcgc3lzdGVtXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5sb2NPYmo9bnVsbF0gLSBhbiBleGlzdGluZyBsb2NhbGUgb2JqZWN0IHRvIHVzZVxuICAgKiBAZXhhbXBsZSBJbmZvLndlZWtkYXlzKClbMF0gLy89PiAnTW9uZGF5J1xuICAgKiBAZXhhbXBsZSBJbmZvLndlZWtkYXlzKCdzaG9ydCcpWzBdIC8vPT4gJ01vbidcbiAgICogQGV4YW1wbGUgSW5mby53ZWVrZGF5cygnc2hvcnQnLCB7IGxvY2FsZTogJ2ZyLUNBJyB9KVswXSAvLz0+ICdsdW4uJ1xuICAgKiBAZXhhbXBsZSBJbmZvLndlZWtkYXlzKCdzaG9ydCcsIHsgbG9jYWxlOiAnYXInIH0pWzBdIC8vPT4gJ1x1MDYyN1x1MDY0NFx1MDYyN1x1MDYyQlx1MDY0Nlx1MDY0QVx1MDY0NidcbiAgICogQHJldHVybiB7QXJyYXl9XG4gICAqL1xuICBzdGF0aWMgd2Vla2RheXMobGVuZ3RoID0gXCJsb25nXCIsIHsgbG9jYWxlID0gbnVsbCwgbnVtYmVyaW5nU3lzdGVtID0gbnVsbCwgbG9jT2JqID0gbnVsbCB9ID0ge30pIHtcbiAgICByZXR1cm4gKGxvY09iaiB8fCBMb2NhbGUuY3JlYXRlKGxvY2FsZSwgbnVtYmVyaW5nU3lzdGVtLCBudWxsKSkud2Vla2RheXMobGVuZ3RoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgZm9ybWF0IHdlZWsgbmFtZXMuXG4gICAqIEZvcm1hdCB3ZWVrZGF5cyBkaWZmZXIgZnJvbSBzdGFuZGFsb25lIHdlZWtkYXlzIGluIHRoYXQgdGhleSdyZSBtZWFudCB0byBhcHBlYXIgbmV4dCB0byBtb3JlIGRhdGUgaW5mb3JtYXRpb24uIEluIHNvbWUgbGFuZ3VhZ2VzLCB0aGF0XG4gICAqIGNoYW5nZXMgdGhlIHN0cmluZy5cbiAgICogU2VlIHtAbGluayBJbmZvI3dlZWtkYXlzfVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW2xlbmd0aD0nbG9uZyddIC0gdGhlIGxlbmd0aCBvZiB0aGUgbW9udGggcmVwcmVzZW50YXRpb24sIHN1Y2ggYXMgXCJuYXJyb3dcIiwgXCJzaG9ydFwiLCBcImxvbmdcIi5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBvcHRpb25zXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5sb2NhbGU9bnVsbF0gLSB0aGUgbG9jYWxlIGNvZGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLm51bWJlcmluZ1N5c3RlbT1udWxsXSAtIHRoZSBudW1iZXJpbmcgc3lzdGVtXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5sb2NPYmo9bnVsbF0gLSBhbiBleGlzdGluZyBsb2NhbGUgb2JqZWN0IHRvIHVzZVxuICAgKiBAcmV0dXJuIHtBcnJheX1cbiAgICovXG4gIHN0YXRpYyB3ZWVrZGF5c0Zvcm1hdChcbiAgICBsZW5ndGggPSBcImxvbmdcIixcbiAgICB7IGxvY2FsZSA9IG51bGwsIG51bWJlcmluZ1N5c3RlbSA9IG51bGwsIGxvY09iaiA9IG51bGwgfSA9IHt9XG4gICkge1xuICAgIHJldHVybiAobG9jT2JqIHx8IExvY2FsZS5jcmVhdGUobG9jYWxlLCBudW1iZXJpbmdTeXN0ZW0sIG51bGwpKS53ZWVrZGF5cyhsZW5ndGgsIHRydWUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbiBhcnJheSBvZiBtZXJpZGllbXMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubG9jYWxlXSAtIHRoZSBsb2NhbGUgY29kZVxuICAgKiBAZXhhbXBsZSBJbmZvLm1lcmlkaWVtcygpIC8vPT4gWyAnQU0nLCAnUE0nIF1cbiAgICogQGV4YW1wbGUgSW5mby5tZXJpZGllbXMoeyBsb2NhbGU6ICdteScgfSkgLy89PiBbICdcdTEwMTRcdTEwMzZcdTEwMTRcdTEwMDBcdTEwM0EnLCAnXHUxMDBBXHUxMDE0XHUxMDMxJyBdXG4gICAqIEByZXR1cm4ge0FycmF5fVxuICAgKi9cbiAgc3RhdGljIG1lcmlkaWVtcyh7IGxvY2FsZSA9IG51bGwgfSA9IHt9KSB7XG4gICAgcmV0dXJuIExvY2FsZS5jcmVhdGUobG9jYWxlKS5tZXJpZGllbXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgZXJhcywgc3VjaCBhcyBbJ0JDJywgJ0FEJ10uIFRoZSBsb2NhbGUgY2FuIGJlIHNwZWNpZmllZCwgYnV0IHRoZSBjYWxlbmRhciBzeXN0ZW0gaXMgYWx3YXlzIEdyZWdvcmlhbi5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtsZW5ndGg9J3Nob3J0J10gLSB0aGUgbGVuZ3RoIG9mIHRoZSBlcmEgcmVwcmVzZW50YXRpb24sIHN1Y2ggYXMgXCJzaG9ydFwiIG9yIFwibG9uZ1wiLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnNcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLmxvY2FsZV0gLSB0aGUgbG9jYWxlIGNvZGVcbiAgICogQGV4YW1wbGUgSW5mby5lcmFzKCkgLy89PiBbICdCQycsICdBRCcgXVxuICAgKiBAZXhhbXBsZSBJbmZvLmVyYXMoJ2xvbmcnKSAvLz0+IFsgJ0JlZm9yZSBDaHJpc3QnLCAnQW5ubyBEb21pbmknIF1cbiAgICogQGV4YW1wbGUgSW5mby5lcmFzKCdsb25nJywgeyBsb2NhbGU6ICdmcicgfSkgLy89PiBbICdhdmFudCBKXHUwMEU5c3VzLUNocmlzdCcsICdhcHJcdTAwRThzIEpcdTAwRTlzdXMtQ2hyaXN0JyBdXG4gICAqIEByZXR1cm4ge0FycmF5fVxuICAgKi9cbiAgc3RhdGljIGVyYXMobGVuZ3RoID0gXCJzaG9ydFwiLCB7IGxvY2FsZSA9IG51bGwgfSA9IHt9KSB7XG4gICAgcmV0dXJuIExvY2FsZS5jcmVhdGUobG9jYWxlLCBudWxsLCBcImdyZWdvcnlcIikuZXJhcyhsZW5ndGgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgc2V0IG9mIGF2YWlsYWJsZSBmZWF0dXJlcyBpbiB0aGlzIGVudmlyb25tZW50LlxuICAgKiBTb21lIGZlYXR1cmVzIG9mIEx1eG9uIGFyZSBub3QgYXZhaWxhYmxlIGluIGFsbCBlbnZpcm9ubWVudHMuIEZvciBleGFtcGxlLCBvbiBvbGRlciBicm93c2VycywgcmVsYXRpdmUgdGltZSBmb3JtYXR0aW5nIHN1cHBvcnQgaXMgbm90IGF2YWlsYWJsZS4gVXNlIHRoaXMgZnVuY3Rpb24gdG8gZmlndXJlIG91dCBpZiB0aGF0J3MgdGhlIGNhc2UuXG4gICAqIEtleXM6XG4gICAqICogYHJlbGF0aXZlYDogd2hldGhlciB0aGlzIGVudmlyb25tZW50IHN1cHBvcnRzIHJlbGF0aXZlIHRpbWUgZm9ybWF0dGluZ1xuICAgKiBAZXhhbXBsZSBJbmZvLmZlYXR1cmVzKCkgLy89PiB7IHJlbGF0aXZlOiBmYWxzZSB9XG4gICAqIEByZXR1cm4ge09iamVjdH1cbiAgICovXG4gIHN0YXRpYyBmZWF0dXJlcygpIHtcbiAgICByZXR1cm4geyByZWxhdGl2ZTogaGFzUmVsYXRpdmUoKSB9O1xuICB9XG59XG4iLCAiaW1wb3J0IER1cmF0aW9uIGZyb20gXCIuLi9kdXJhdGlvbi5qc1wiO1xuXG5mdW5jdGlvbiBkYXlEaWZmKGVhcmxpZXIsIGxhdGVyKSB7XG4gIGNvbnN0IHV0Y0RheVN0YXJ0ID0gKGR0KSA9PiBkdC50b1VUQygwLCB7IGtlZXBMb2NhbFRpbWU6IHRydWUgfSkuc3RhcnRPZihcImRheVwiKS52YWx1ZU9mKCksXG4gICAgbXMgPSB1dGNEYXlTdGFydChsYXRlcikgLSB1dGNEYXlTdGFydChlYXJsaWVyKTtcbiAgcmV0dXJuIE1hdGguZmxvb3IoRHVyYXRpb24uZnJvbU1pbGxpcyhtcykuYXMoXCJkYXlzXCIpKTtcbn1cblxuZnVuY3Rpb24gaGlnaE9yZGVyRGlmZnMoY3Vyc29yLCBsYXRlciwgdW5pdHMpIHtcbiAgY29uc3QgZGlmZmVycyA9IFtcbiAgICBbXCJ5ZWFyc1wiLCAoYSwgYikgPT4gYi55ZWFyIC0gYS55ZWFyXSxcbiAgICBbXCJxdWFydGVyc1wiLCAoYSwgYikgPT4gYi5xdWFydGVyIC0gYS5xdWFydGVyICsgKGIueWVhciAtIGEueWVhcikgKiA0XSxcbiAgICBbXCJtb250aHNcIiwgKGEsIGIpID0+IGIubW9udGggLSBhLm1vbnRoICsgKGIueWVhciAtIGEueWVhcikgKiAxMl0sXG4gICAgW1xuICAgICAgXCJ3ZWVrc1wiLFxuICAgICAgKGEsIGIpID0+IHtcbiAgICAgICAgY29uc3QgZGF5cyA9IGRheURpZmYoYSwgYik7XG4gICAgICAgIHJldHVybiAoZGF5cyAtIChkYXlzICUgNykpIC8gNztcbiAgICAgIH0sXG4gICAgXSxcbiAgICBbXCJkYXlzXCIsIGRheURpZmZdLFxuICBdO1xuXG4gIGNvbnN0IHJlc3VsdHMgPSB7fTtcbiAgY29uc3QgZWFybGllciA9IGN1cnNvcjtcbiAgbGV0IGxvd2VzdE9yZGVyLCBoaWdoV2F0ZXI7XG5cbiAgZm9yIChjb25zdCBbdW5pdCwgZGlmZmVyXSBvZiBkaWZmZXJzKSB7XG4gICAgaWYgKHVuaXRzLmluZGV4T2YodW5pdCkgPj0gMCkge1xuICAgICAgbG93ZXN0T3JkZXIgPSB1bml0O1xuXG4gICAgICByZXN1bHRzW3VuaXRdID0gZGlmZmVyKGN1cnNvciwgbGF0ZXIpO1xuICAgICAgaGlnaFdhdGVyID0gZWFybGllci5wbHVzKHJlc3VsdHMpO1xuXG4gICAgICBpZiAoaGlnaFdhdGVyID4gbGF0ZXIpIHtcbiAgICAgICAgcmVzdWx0c1t1bml0XS0tO1xuICAgICAgICBjdXJzb3IgPSBlYXJsaWVyLnBsdXMocmVzdWx0cyk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJzb3IgPSBoaWdoV2F0ZXI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIFtjdXJzb3IsIHJlc3VsdHMsIGhpZ2hXYXRlciwgbG93ZXN0T3JkZXJdO1xufVxuXG5leHBvcnQgZGVmYXVsdCBmdW5jdGlvbiAoZWFybGllciwgbGF0ZXIsIHVuaXRzLCBvcHRzKSB7XG4gIGxldCBbY3Vyc29yLCByZXN1bHRzLCBoaWdoV2F0ZXIsIGxvd2VzdE9yZGVyXSA9IGhpZ2hPcmRlckRpZmZzKGVhcmxpZXIsIGxhdGVyLCB1bml0cyk7XG5cbiAgY29uc3QgcmVtYWluaW5nTWlsbGlzID0gbGF0ZXIgLSBjdXJzb3I7XG5cbiAgY29uc3QgbG93ZXJPcmRlclVuaXRzID0gdW5pdHMuZmlsdGVyKFxuICAgICh1KSA9PiBbXCJob3Vyc1wiLCBcIm1pbnV0ZXNcIiwgXCJzZWNvbmRzXCIsIFwibWlsbGlzZWNvbmRzXCJdLmluZGV4T2YodSkgPj0gMFxuICApO1xuXG4gIGlmIChsb3dlck9yZGVyVW5pdHMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKGhpZ2hXYXRlciA8IGxhdGVyKSB7XG4gICAgICBoaWdoV2F0ZXIgPSBjdXJzb3IucGx1cyh7IFtsb3dlc3RPcmRlcl06IDEgfSk7XG4gICAgfVxuXG4gICAgaWYgKGhpZ2hXYXRlciAhPT0gY3Vyc29yKSB7XG4gICAgICByZXN1bHRzW2xvd2VzdE9yZGVyXSA9IChyZXN1bHRzW2xvd2VzdE9yZGVyXSB8fCAwKSArIHJlbWFpbmluZ01pbGxpcyAvIChoaWdoV2F0ZXIgLSBjdXJzb3IpO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IGR1cmF0aW9uID0gRHVyYXRpb24uZnJvbU9iamVjdChyZXN1bHRzLCBvcHRzKTtcblxuICBpZiAobG93ZXJPcmRlclVuaXRzLmxlbmd0aCA+IDApIHtcbiAgICByZXR1cm4gRHVyYXRpb24uZnJvbU1pbGxpcyhyZW1haW5pbmdNaWxsaXMsIG9wdHMpXG4gICAgICAuc2hpZnRUbyguLi5sb3dlck9yZGVyVW5pdHMpXG4gICAgICAucGx1cyhkdXJhdGlvbik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGR1cmF0aW9uO1xuICB9XG59XG4iLCAiY29uc3QgbnVtYmVyaW5nU3lzdGVtcyA9IHtcbiAgYXJhYjogXCJbXFx1MDY2MC1cXHUwNjY5XVwiLFxuICBhcmFiZXh0OiBcIltcXHUwNkYwLVxcdTA2RjldXCIsXG4gIGJhbGk6IFwiW1xcdTFCNTAtXFx1MUI1OV1cIixcbiAgYmVuZzogXCJbXFx1MDlFNi1cXHUwOUVGXVwiLFxuICBkZXZhOiBcIltcXHUwOTY2LVxcdTA5NkZdXCIsXG4gIGZ1bGx3aWRlOiBcIltcXHVGRjEwLVxcdUZGMTldXCIsXG4gIGd1anI6IFwiW1xcdTBBRTYtXFx1MEFFRl1cIixcbiAgaGFuaWRlYzogXCJbXHUzMDA3fFx1NEUwMHxcdTRFOEN8XHU0RTA5fFx1NTZEQnxcdTRFOTR8XHU1MTZEfFx1NEUwM3xcdTUxNkJ8XHU0RTVEXVwiLFxuICBraG1yOiBcIltcXHUxN0UwLVxcdTE3RTldXCIsXG4gIGtuZGE6IFwiW1xcdTBDRTYtXFx1MENFRl1cIixcbiAgbGFvbzogXCJbXFx1MEVEMC1cXHUwRUQ5XVwiLFxuICBsaW1iOiBcIltcXHUxOTQ2LVxcdTE5NEZdXCIsXG4gIG1seW06IFwiW1xcdTBENjYtXFx1MEQ2Rl1cIixcbiAgbW9uZzogXCJbXFx1MTgxMC1cXHUxODE5XVwiLFxuICBteW1yOiBcIltcXHUxMDQwLVxcdTEwNDldXCIsXG4gIG9yeWE6IFwiW1xcdTBCNjYtXFx1MEI2Rl1cIixcbiAgdGFtbGRlYzogXCJbXFx1MEJFNi1cXHUwQkVGXVwiLFxuICB0ZWx1OiBcIltcXHUwQzY2LVxcdTBDNkZdXCIsXG4gIHRoYWk6IFwiW1xcdTBFNTAtXFx1MEU1OV1cIixcbiAgdGlidDogXCJbXFx1MEYyMC1cXHUwRjI5XVwiLFxuICBsYXRuOiBcIlxcXFxkXCIsXG59O1xuXG5jb25zdCBudW1iZXJpbmdTeXN0ZW1zVVRGMTYgPSB7XG4gIGFyYWI6IFsxNjMyLCAxNjQxXSxcbiAgYXJhYmV4dDogWzE3NzYsIDE3ODVdLFxuICBiYWxpOiBbNjk5MiwgNzAwMV0sXG4gIGJlbmc6IFsyNTM0LCAyNTQzXSxcbiAgZGV2YTogWzI0MDYsIDI0MTVdLFxuICBmdWxsd2lkZTogWzY1Mjk2LCA2NTMwM10sXG4gIGd1anI6IFsyNzkwLCAyNzk5XSxcbiAga2htcjogWzYxMTIsIDYxMjFdLFxuICBrbmRhOiBbMzMwMiwgMzMxMV0sXG4gIGxhb286IFszNzkyLCAzODAxXSxcbiAgbGltYjogWzY0NzAsIDY0NzldLFxuICBtbHltOiBbMzQzMCwgMzQzOV0sXG4gIG1vbmc6IFs2MTYwLCA2MTY5XSxcbiAgbXltcjogWzQxNjAsIDQxNjldLFxuICBvcnlhOiBbMjkxOCwgMjkyN10sXG4gIHRhbWxkZWM6IFszMDQ2LCAzMDU1XSxcbiAgdGVsdTogWzMxNzQsIDMxODNdLFxuICB0aGFpOiBbMzY2NCwgMzY3M10sXG4gIHRpYnQ6IFszODcyLCAzODgxXSxcbn07XG5cbmNvbnN0IGhhbmlkZWNDaGFycyA9IG51bWJlcmluZ1N5c3RlbXMuaGFuaWRlYy5yZXBsYWNlKC9bXFxbfFxcXV0vZywgXCJcIikuc3BsaXQoXCJcIik7XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZURpZ2l0cyhzdHIpIHtcbiAgbGV0IHZhbHVlID0gcGFyc2VJbnQoc3RyLCAxMCk7XG4gIGlmIChpc05hTih2YWx1ZSkpIHtcbiAgICB2YWx1ZSA9IFwiXCI7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcblxuICAgICAgaWYgKHN0cltpXS5zZWFyY2gobnVtYmVyaW5nU3lzdGVtcy5oYW5pZGVjKSAhPT0gLTEpIHtcbiAgICAgICAgdmFsdWUgKz0gaGFuaWRlY0NoYXJzLmluZGV4T2Yoc3RyW2ldKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIG51bWJlcmluZ1N5c3RlbXNVVEYxNikge1xuICAgICAgICAgIGNvbnN0IFttaW4sIG1heF0gPSBudW1iZXJpbmdTeXN0ZW1zVVRGMTZba2V5XTtcbiAgICAgICAgICBpZiAoY29kZSA+PSBtaW4gJiYgY29kZSA8PSBtYXgpIHtcbiAgICAgICAgICAgIHZhbHVlICs9IGNvZGUgLSBtaW47XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBwYXJzZUludCh2YWx1ZSwgMTApO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGlnaXRSZWdleCh7IG51bWJlcmluZ1N5c3RlbSB9LCBhcHBlbmQgPSBcIlwiKSB7XG4gIHJldHVybiBuZXcgUmVnRXhwKGAke251bWJlcmluZ1N5c3RlbXNbbnVtYmVyaW5nU3lzdGVtIHx8IFwibGF0blwiXX0ke2FwcGVuZH1gKTtcbn1cbiIsICJpbXBvcnQgeyBwYXJzZU1pbGxpcywgaXNVbmRlZmluZWQsIHVudHJ1bmNhdGVZZWFyLCBzaWduZWRPZmZzZXQsIGhhc093blByb3BlcnR5IH0gZnJvbSBcIi4vdXRpbC5qc1wiO1xuaW1wb3J0IEZvcm1hdHRlciBmcm9tIFwiLi9mb3JtYXR0ZXIuanNcIjtcbmltcG9ydCBGaXhlZE9mZnNldFpvbmUgZnJvbSBcIi4uL3pvbmVzL2ZpeGVkT2Zmc2V0Wm9uZS5qc1wiO1xuaW1wb3J0IElBTkFab25lIGZyb20gXCIuLi96b25lcy9JQU5BWm9uZS5qc1wiO1xuaW1wb3J0IERhdGVUaW1lIGZyb20gXCIuLi9kYXRldGltZS5qc1wiO1xuaW1wb3J0IHsgZGlnaXRSZWdleCwgcGFyc2VEaWdpdHMgfSBmcm9tIFwiLi9kaWdpdHMuanNcIjtcbmltcG9ydCB7IENvbmZsaWN0aW5nU3BlY2lmaWNhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2Vycm9ycy5qc1wiO1xuXG5jb25zdCBNSVNTSU5HX0ZUUCA9IFwibWlzc2luZyBJbnRsLkRhdGVUaW1lRm9ybWF0LmZvcm1hdFRvUGFydHMgc3VwcG9ydFwiO1xuXG5mdW5jdGlvbiBpbnRVbml0KHJlZ2V4LCBwb3N0ID0gKGkpID0+IGkpIHtcbiAgcmV0dXJuIHsgcmVnZXgsIGRlc2VyOiAoW3NdKSA9PiBwb3N0KHBhcnNlRGlnaXRzKHMpKSB9O1xufVxuXG5jb25zdCBOQlNQID0gU3RyaW5nLmZyb21DaGFyQ29kZSgxNjApO1xuY29uc3Qgc3BhY2VPck5CU1AgPSBgWyAke05CU1B9XWA7XG5jb25zdCBzcGFjZU9yTkJTUFJlZ0V4cCA9IG5ldyBSZWdFeHAoc3BhY2VPck5CU1AsIFwiZ1wiKTtcblxuZnVuY3Rpb24gZml4TGlzdFJlZ2V4KHMpIHtcbiAgLy8gbWFrZSBkb3RzIG9wdGlvbmFsIGFuZCBhbHNvIG1ha2UgdGhlbSBsaXRlcmFsXG4gIC8vIG1ha2Ugc3BhY2UgYW5kIG5vbiBicmVha2FibGUgc3BhY2UgY2hhcmFjdGVycyBpbnRlcmNoYW5nZWFibGVcbiAgcmV0dXJuIHMucmVwbGFjZSgvXFwuL2csIFwiXFxcXC4/XCIpLnJlcGxhY2Uoc3BhY2VPck5CU1BSZWdFeHAsIHNwYWNlT3JOQlNQKTtcbn1cblxuZnVuY3Rpb24gc3RyaXBJbnNlbnNpdGl2aXRpZXMocykge1xuICByZXR1cm4gc1xuICAgIC5yZXBsYWNlKC9cXC4vZywgXCJcIikgLy8gaWdub3JlIGRvdHMgdGhhdCB3ZXJlIG1hZGUgb3B0aW9uYWxcbiAgICAucmVwbGFjZShzcGFjZU9yTkJTUFJlZ0V4cCwgXCIgXCIpIC8vIGludGVyY2hhbmdlIHNwYWNlIGFuZCBuYnNwXG4gICAgLnRvTG93ZXJDYXNlKCk7XG59XG5cbmZ1bmN0aW9uIG9uZU9mKHN0cmluZ3MsIHN0YXJ0SW5kZXgpIHtcbiAgaWYgKHN0cmluZ3MgPT09IG51bGwpIHtcbiAgICByZXR1cm4gbnVsbDtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVnZXg6IFJlZ0V4cChzdHJpbmdzLm1hcChmaXhMaXN0UmVnZXgpLmpvaW4oXCJ8XCIpKSxcbiAgICAgIGRlc2VyOiAoW3NdKSA9PlxuICAgICAgICBzdHJpbmdzLmZpbmRJbmRleCgoaSkgPT4gc3RyaXBJbnNlbnNpdGl2aXRpZXMocykgPT09IHN0cmlwSW5zZW5zaXRpdml0aWVzKGkpKSArIHN0YXJ0SW5kZXgsXG4gICAgfTtcbiAgfVxufVxuXG5mdW5jdGlvbiBvZmZzZXQocmVnZXgsIGdyb3Vwcykge1xuICByZXR1cm4geyByZWdleCwgZGVzZXI6IChbLCBoLCBtXSkgPT4gc2lnbmVkT2Zmc2V0KGgsIG0pLCBncm91cHMgfTtcbn1cblxuZnVuY3Rpb24gc2ltcGxlKHJlZ2V4KSB7XG4gIHJldHVybiB7IHJlZ2V4LCBkZXNlcjogKFtzXSkgPT4gcyB9O1xufVxuXG5mdW5jdGlvbiBlc2NhcGVUb2tlbih2YWx1ZSkge1xuICByZXR1cm4gdmFsdWUucmVwbGFjZSgvW1xcLVxcW1xcXXt9KCkqKz8uLFxcXFxcXF4kfCNcXHNdL2csIFwiXFxcXCQmXCIpO1xufVxuXG5mdW5jdGlvbiB1bml0Rm9yVG9rZW4odG9rZW4sIGxvYykge1xuICBjb25zdCBvbmUgPSBkaWdpdFJlZ2V4KGxvYyksXG4gICAgdHdvID0gZGlnaXRSZWdleChsb2MsIFwiezJ9XCIpLFxuICAgIHRocmVlID0gZGlnaXRSZWdleChsb2MsIFwiezN9XCIpLFxuICAgIGZvdXIgPSBkaWdpdFJlZ2V4KGxvYywgXCJ7NH1cIiksXG4gICAgc2l4ID0gZGlnaXRSZWdleChsb2MsIFwiezZ9XCIpLFxuICAgIG9uZU9yVHdvID0gZGlnaXRSZWdleChsb2MsIFwiezEsMn1cIiksXG4gICAgb25lVG9UaHJlZSA9IGRpZ2l0UmVnZXgobG9jLCBcInsxLDN9XCIpLFxuICAgIG9uZVRvU2l4ID0gZGlnaXRSZWdleChsb2MsIFwiezEsNn1cIiksXG4gICAgb25lVG9OaW5lID0gZGlnaXRSZWdleChsb2MsIFwiezEsOX1cIiksXG4gICAgdHdvVG9Gb3VyID0gZGlnaXRSZWdleChsb2MsIFwiezIsNH1cIiksXG4gICAgZm91clRvU2l4ID0gZGlnaXRSZWdleChsb2MsIFwiezQsNn1cIiksXG4gICAgbGl0ZXJhbCA9ICh0KSA9PiAoeyByZWdleDogUmVnRXhwKGVzY2FwZVRva2VuKHQudmFsKSksIGRlc2VyOiAoW3NdKSA9PiBzLCBsaXRlcmFsOiB0cnVlIH0pLFxuICAgIHVuaXRhdGUgPSAodCkgPT4ge1xuICAgICAgaWYgKHRva2VuLmxpdGVyYWwpIHtcbiAgICAgICAgcmV0dXJuIGxpdGVyYWwodCk7XG4gICAgICB9XG4gICAgICBzd2l0Y2ggKHQudmFsKSB7XG4gICAgICAgIC8vIGVyYVxuICAgICAgICBjYXNlIFwiR1wiOlxuICAgICAgICAgIHJldHVybiBvbmVPZihsb2MuZXJhcyhcInNob3J0XCIsIGZhbHNlKSwgMCk7XG4gICAgICAgIGNhc2UgXCJHR1wiOlxuICAgICAgICAgIHJldHVybiBvbmVPZihsb2MuZXJhcyhcImxvbmdcIiwgZmFsc2UpLCAwKTtcbiAgICAgICAgLy8geWVhcnNcbiAgICAgICAgY2FzZSBcInlcIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdChvbmVUb1NpeCk7XG4gICAgICAgIGNhc2UgXCJ5eVwiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KHR3b1RvRm91ciwgdW50cnVuY2F0ZVllYXIpO1xuICAgICAgICBjYXNlIFwieXl5eVwiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KGZvdXIpO1xuICAgICAgICBjYXNlIFwieXl5eXlcIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdChmb3VyVG9TaXgpO1xuICAgICAgICBjYXNlIFwieXl5eXl5XCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQoc2l4KTtcbiAgICAgICAgLy8gbW9udGhzXG4gICAgICAgIGNhc2UgXCJNXCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQob25lT3JUd28pO1xuICAgICAgICBjYXNlIFwiTU1cIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdCh0d28pO1xuICAgICAgICBjYXNlIFwiTU1NXCI6XG4gICAgICAgICAgcmV0dXJuIG9uZU9mKGxvYy5tb250aHMoXCJzaG9ydFwiLCB0cnVlLCBmYWxzZSksIDEpO1xuICAgICAgICBjYXNlIFwiTU1NTVwiOlxuICAgICAgICAgIHJldHVybiBvbmVPZihsb2MubW9udGhzKFwibG9uZ1wiLCB0cnVlLCBmYWxzZSksIDEpO1xuICAgICAgICBjYXNlIFwiTFwiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KG9uZU9yVHdvKTtcbiAgICAgICAgY2FzZSBcIkxMXCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQodHdvKTtcbiAgICAgICAgY2FzZSBcIkxMTFwiOlxuICAgICAgICAgIHJldHVybiBvbmVPZihsb2MubW9udGhzKFwic2hvcnRcIiwgZmFsc2UsIGZhbHNlKSwgMSk7XG4gICAgICAgIGNhc2UgXCJMTExMXCI6XG4gICAgICAgICAgcmV0dXJuIG9uZU9mKGxvYy5tb250aHMoXCJsb25nXCIsIGZhbHNlLCBmYWxzZSksIDEpO1xuICAgICAgICAvLyBkYXRlc1xuICAgICAgICBjYXNlIFwiZFwiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KG9uZU9yVHdvKTtcbiAgICAgICAgY2FzZSBcImRkXCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQodHdvKTtcbiAgICAgICAgLy8gb3JkaW5hbHNcbiAgICAgICAgY2FzZSBcIm9cIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdChvbmVUb1RocmVlKTtcbiAgICAgICAgY2FzZSBcIm9vb1wiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KHRocmVlKTtcbiAgICAgICAgLy8gdGltZVxuICAgICAgICBjYXNlIFwiSEhcIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdCh0d28pO1xuICAgICAgICBjYXNlIFwiSFwiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KG9uZU9yVHdvKTtcbiAgICAgICAgY2FzZSBcImhoXCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQodHdvKTtcbiAgICAgICAgY2FzZSBcImhcIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdChvbmVPclR3byk7XG4gICAgICAgIGNhc2UgXCJtbVwiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KHR3byk7XG4gICAgICAgIGNhc2UgXCJtXCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQob25lT3JUd28pO1xuICAgICAgICBjYXNlIFwicVwiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KG9uZU9yVHdvKTtcbiAgICAgICAgY2FzZSBcInFxXCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQodHdvKTtcbiAgICAgICAgY2FzZSBcInNcIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdChvbmVPclR3byk7XG4gICAgICAgIGNhc2UgXCJzc1wiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KHR3byk7XG4gICAgICAgIGNhc2UgXCJTXCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQob25lVG9UaHJlZSk7XG4gICAgICAgIGNhc2UgXCJTU1NcIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdCh0aHJlZSk7XG4gICAgICAgIGNhc2UgXCJ1XCI6XG4gICAgICAgICAgcmV0dXJuIHNpbXBsZShvbmVUb05pbmUpO1xuICAgICAgICBjYXNlIFwidXVcIjpcbiAgICAgICAgICByZXR1cm4gc2ltcGxlKG9uZU9yVHdvKTtcbiAgICAgICAgY2FzZSBcInV1dVwiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KG9uZSk7XG4gICAgICAgIC8vIG1lcmlkaWVtXG4gICAgICAgIGNhc2UgXCJhXCI6XG4gICAgICAgICAgcmV0dXJuIG9uZU9mKGxvYy5tZXJpZGllbXMoKSwgMCk7XG4gICAgICAgIC8vIHdlZWtZZWFyIChrKVxuICAgICAgICBjYXNlIFwia2tra1wiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KGZvdXIpO1xuICAgICAgICBjYXNlIFwia2tcIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdCh0d29Ub0ZvdXIsIHVudHJ1bmNhdGVZZWFyKTtcbiAgICAgICAgLy8gd2Vla051bWJlciAoVylcbiAgICAgICAgY2FzZSBcIldcIjpcbiAgICAgICAgICByZXR1cm4gaW50VW5pdChvbmVPclR3byk7XG4gICAgICAgIGNhc2UgXCJXV1wiOlxuICAgICAgICAgIHJldHVybiBpbnRVbml0KHR3byk7XG4gICAgICAgIC8vIHdlZWtkYXlzXG4gICAgICAgIGNhc2UgXCJFXCI6XG4gICAgICAgIGNhc2UgXCJjXCI6XG4gICAgICAgICAgcmV0dXJuIGludFVuaXQob25lKTtcbiAgICAgICAgY2FzZSBcIkVFRVwiOlxuICAgICAgICAgIHJldHVybiBvbmVPZihsb2Mud2Vla2RheXMoXCJzaG9ydFwiLCBmYWxzZSwgZmFsc2UpLCAxKTtcbiAgICAgICAgY2FzZSBcIkVFRUVcIjpcbiAgICAgICAgICByZXR1cm4gb25lT2YobG9jLndlZWtkYXlzKFwibG9uZ1wiLCBmYWxzZSwgZmFsc2UpLCAxKTtcbiAgICAgICAgY2FzZSBcImNjY1wiOlxuICAgICAgICAgIHJldHVybiBvbmVPZihsb2Mud2Vla2RheXMoXCJzaG9ydFwiLCB0cnVlLCBmYWxzZSksIDEpO1xuICAgICAgICBjYXNlIFwiY2NjY1wiOlxuICAgICAgICAgIHJldHVybiBvbmVPZihsb2Mud2Vla2RheXMoXCJsb25nXCIsIHRydWUsIGZhbHNlKSwgMSk7XG4gICAgICAgIC8vIG9mZnNldC96b25lXG4gICAgICAgIGNhc2UgXCJaXCI6XG4gICAgICAgIGNhc2UgXCJaWlwiOlxuICAgICAgICAgIHJldHVybiBvZmZzZXQobmV3IFJlZ0V4cChgKFsrLV0ke29uZU9yVHdvLnNvdXJjZX0pKD86Oigke3R3by5zb3VyY2V9KSk/YCksIDIpO1xuICAgICAgICBjYXNlIFwiWlpaXCI6XG4gICAgICAgICAgcmV0dXJuIG9mZnNldChuZXcgUmVnRXhwKGAoWystXSR7b25lT3JUd28uc291cmNlfSkoJHt0d28uc291cmNlfSk/YCksIDIpO1xuICAgICAgICAvLyB3ZSBkb24ndCBzdXBwb3J0IFpaWlogKFBTVCkgb3IgWlpaWlogKFBhY2lmaWMgU3RhbmRhcmQgVGltZSkgaW4gcGFyc2luZ1xuICAgICAgICAvLyBiZWNhdXNlIHdlIGRvbid0IGhhdmUgYW55IHdheSB0byBmaWd1cmUgb3V0IHdoYXQgdGhleSBhcmVcbiAgICAgICAgY2FzZSBcInpcIjpcbiAgICAgICAgICByZXR1cm4gc2ltcGxlKC9bYS16XystL117MSwyNTZ9Py9pKTtcbiAgICAgICAgLy8gdGhpcyBzcGVjaWFsLWNhc2UgXCJ0b2tlblwiIHJlcHJlc2VudHMgYSBwbGFjZSB3aGVyZSBhIG1hY3JvLXRva2VuIGV4cGFuZGVkIGludG8gYSB3aGl0ZS1zcGFjZSBsaXRlcmFsXG4gICAgICAgIC8vIGluIHRoaXMgY2FzZSB3ZSBhY2NlcHQgYW55IG5vbi1uZXdsaW5lIHdoaXRlLXNwYWNlXG4gICAgICAgIGNhc2UgXCIgXCI6XG4gICAgICAgICAgcmV0dXJuIHNpbXBsZSgvW15cXFNcXG5cXHJdLyk7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgcmV0dXJuIGxpdGVyYWwodCk7XG4gICAgICB9XG4gICAgfTtcblxuICBjb25zdCB1bml0ID0gdW5pdGF0ZSh0b2tlbikgfHwge1xuICAgIGludmFsaWRSZWFzb246IE1JU1NJTkdfRlRQLFxuICB9O1xuXG4gIHVuaXQudG9rZW4gPSB0b2tlbjtcblxuICByZXR1cm4gdW5pdDtcbn1cblxuY29uc3QgcGFydFR5cGVTdHlsZVRvVG9rZW5WYWwgPSB7XG4gIHllYXI6IHtcbiAgICBcIjItZGlnaXRcIjogXCJ5eVwiLFxuICAgIG51bWVyaWM6IFwieXl5eXlcIixcbiAgfSxcbiAgbW9udGg6IHtcbiAgICBudW1lcmljOiBcIk1cIixcbiAgICBcIjItZGlnaXRcIjogXCJNTVwiLFxuICAgIHNob3J0OiBcIk1NTVwiLFxuICAgIGxvbmc6IFwiTU1NTVwiLFxuICB9LFxuICBkYXk6IHtcbiAgICBudW1lcmljOiBcImRcIixcbiAgICBcIjItZGlnaXRcIjogXCJkZFwiLFxuICB9LFxuICB3ZWVrZGF5OiB7XG4gICAgc2hvcnQ6IFwiRUVFXCIsXG4gICAgbG9uZzogXCJFRUVFXCIsXG4gIH0sXG4gIGRheXBlcmlvZDogXCJhXCIsXG4gIGRheVBlcmlvZDogXCJhXCIsXG4gIGhvdXI6IHtcbiAgICBudW1lcmljOiBcImhcIixcbiAgICBcIjItZGlnaXRcIjogXCJoaFwiLFxuICB9LFxuICBtaW51dGU6IHtcbiAgICBudW1lcmljOiBcIm1cIixcbiAgICBcIjItZGlnaXRcIjogXCJtbVwiLFxuICB9LFxuICBzZWNvbmQ6IHtcbiAgICBudW1lcmljOiBcInNcIixcbiAgICBcIjItZGlnaXRcIjogXCJzc1wiLFxuICB9LFxuICB0aW1lWm9uZU5hbWU6IHtcbiAgICBsb25nOiBcIlpaWlpaXCIsXG4gICAgc2hvcnQ6IFwiWlpaXCIsXG4gIH0sXG59O1xuXG5mdW5jdGlvbiB0b2tlbkZvclBhcnQocGFydCwgZm9ybWF0T3B0cykge1xuICBjb25zdCB7IHR5cGUsIHZhbHVlIH0gPSBwYXJ0O1xuXG4gIGlmICh0eXBlID09PSBcImxpdGVyYWxcIikge1xuICAgIGNvbnN0IGlzU3BhY2UgPSAvXlxccyskLy50ZXN0KHZhbHVlKTtcbiAgICByZXR1cm4ge1xuICAgICAgbGl0ZXJhbDogIWlzU3BhY2UsXG4gICAgICB2YWw6IGlzU3BhY2UgPyBcIiBcIiA6IHZhbHVlLFxuICAgIH07XG4gIH1cblxuICBjb25zdCBzdHlsZSA9IGZvcm1hdE9wdHNbdHlwZV07XG5cbiAgbGV0IHZhbCA9IHBhcnRUeXBlU3R5bGVUb1Rva2VuVmFsW3R5cGVdO1xuICBpZiAodHlwZW9mIHZhbCA9PT0gXCJvYmplY3RcIikge1xuICAgIHZhbCA9IHZhbFtzdHlsZV07XG4gIH1cblxuICBpZiAodmFsKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxpdGVyYWw6IGZhbHNlLFxuICAgICAgdmFsLFxuICAgIH07XG4gIH1cblxuICByZXR1cm4gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBidWlsZFJlZ2V4KHVuaXRzKSB7XG4gIGNvbnN0IHJlID0gdW5pdHMubWFwKCh1KSA9PiB1LnJlZ2V4KS5yZWR1Y2UoKGYsIHIpID0+IGAke2Z9KCR7ci5zb3VyY2V9KWAsIFwiXCIpO1xuICByZXR1cm4gW2BeJHtyZX0kYCwgdW5pdHNdO1xufVxuXG5mdW5jdGlvbiBtYXRjaChpbnB1dCwgcmVnZXgsIGhhbmRsZXJzKSB7XG4gIGNvbnN0IG1hdGNoZXMgPSBpbnB1dC5tYXRjaChyZWdleCk7XG5cbiAgaWYgKG1hdGNoZXMpIHtcbiAgICBjb25zdCBhbGwgPSB7fTtcbiAgICBsZXQgbWF0Y2hJbmRleCA9IDE7XG4gICAgZm9yIChjb25zdCBpIGluIGhhbmRsZXJzKSB7XG4gICAgICBpZiAoaGFzT3duUHJvcGVydHkoaGFuZGxlcnMsIGkpKSB7XG4gICAgICAgIGNvbnN0IGggPSBoYW5kbGVyc1tpXSxcbiAgICAgICAgICBncm91cHMgPSBoLmdyb3VwcyA/IGguZ3JvdXBzICsgMSA6IDE7XG4gICAgICAgIGlmICghaC5saXRlcmFsICYmIGgudG9rZW4pIHtcbiAgICAgICAgICBhbGxbaC50b2tlbi52YWxbMF1dID0gaC5kZXNlcihtYXRjaGVzLnNsaWNlKG1hdGNoSW5kZXgsIG1hdGNoSW5kZXggKyBncm91cHMpKTtcbiAgICAgICAgfVxuICAgICAgICBtYXRjaEluZGV4ICs9IGdyb3VwcztcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIFttYXRjaGVzLCBhbGxdO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBbbWF0Y2hlcywge31dO1xuICB9XG59XG5cbmZ1bmN0aW9uIGRhdGVUaW1lRnJvbU1hdGNoZXMobWF0Y2hlcykge1xuICBjb25zdCB0b0ZpZWxkID0gKHRva2VuKSA9PiB7XG4gICAgc3dpdGNoICh0b2tlbikge1xuICAgICAgY2FzZSBcIlNcIjpcbiAgICAgICAgcmV0dXJuIFwibWlsbGlzZWNvbmRcIjtcbiAgICAgIGNhc2UgXCJzXCI6XG4gICAgICAgIHJldHVybiBcInNlY29uZFwiO1xuICAgICAgY2FzZSBcIm1cIjpcbiAgICAgICAgcmV0dXJuIFwibWludXRlXCI7XG4gICAgICBjYXNlIFwiaFwiOlxuICAgICAgY2FzZSBcIkhcIjpcbiAgICAgICAgcmV0dXJuIFwiaG91clwiO1xuICAgICAgY2FzZSBcImRcIjpcbiAgICAgICAgcmV0dXJuIFwiZGF5XCI7XG4gICAgICBjYXNlIFwib1wiOlxuICAgICAgICByZXR1cm4gXCJvcmRpbmFsXCI7XG4gICAgICBjYXNlIFwiTFwiOlxuICAgICAgY2FzZSBcIk1cIjpcbiAgICAgICAgcmV0dXJuIFwibW9udGhcIjtcbiAgICAgIGNhc2UgXCJ5XCI6XG4gICAgICAgIHJldHVybiBcInllYXJcIjtcbiAgICAgIGNhc2UgXCJFXCI6XG4gICAgICBjYXNlIFwiY1wiOlxuICAgICAgICByZXR1cm4gXCJ3ZWVrZGF5XCI7XG4gICAgICBjYXNlIFwiV1wiOlxuICAgICAgICByZXR1cm4gXCJ3ZWVrTnVtYmVyXCI7XG4gICAgICBjYXNlIFwia1wiOlxuICAgICAgICByZXR1cm4gXCJ3ZWVrWWVhclwiO1xuICAgICAgY2FzZSBcInFcIjpcbiAgICAgICAgcmV0dXJuIFwicXVhcnRlclwiO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICB9O1xuXG4gIGxldCB6b25lID0gbnVsbDtcbiAgbGV0IHNwZWNpZmljT2Zmc2V0O1xuICBpZiAoIWlzVW5kZWZpbmVkKG1hdGNoZXMueikpIHtcbiAgICB6b25lID0gSUFOQVpvbmUuY3JlYXRlKG1hdGNoZXMueik7XG4gIH1cblxuICBpZiAoIWlzVW5kZWZpbmVkKG1hdGNoZXMuWikpIHtcbiAgICBpZiAoIXpvbmUpIHtcbiAgICAgIHpvbmUgPSBuZXcgRml4ZWRPZmZzZXRab25lKG1hdGNoZXMuWik7XG4gICAgfVxuICAgIHNwZWNpZmljT2Zmc2V0ID0gbWF0Y2hlcy5aO1xuICB9XG5cbiAgaWYgKCFpc1VuZGVmaW5lZChtYXRjaGVzLnEpKSB7XG4gICAgbWF0Y2hlcy5NID0gKG1hdGNoZXMucSAtIDEpICogMyArIDE7XG4gIH1cblxuICBpZiAoIWlzVW5kZWZpbmVkKG1hdGNoZXMuaCkpIHtcbiAgICBpZiAobWF0Y2hlcy5oIDwgMTIgJiYgbWF0Y2hlcy5hID09PSAxKSB7XG4gICAgICBtYXRjaGVzLmggKz0gMTI7XG4gICAgfSBlbHNlIGlmIChtYXRjaGVzLmggPT09IDEyICYmIG1hdGNoZXMuYSA9PT0gMCkge1xuICAgICAgbWF0Y2hlcy5oID0gMDtcbiAgICB9XG4gIH1cblxuICBpZiAobWF0Y2hlcy5HID09PSAwICYmIG1hdGNoZXMueSkge1xuICAgIG1hdGNoZXMueSA9IC1tYXRjaGVzLnk7XG4gIH1cblxuICBpZiAoIWlzVW5kZWZpbmVkKG1hdGNoZXMudSkpIHtcbiAgICBtYXRjaGVzLlMgPSBwYXJzZU1pbGxpcyhtYXRjaGVzLnUpO1xuICB9XG5cbiAgY29uc3QgdmFscyA9IE9iamVjdC5rZXlzKG1hdGNoZXMpLnJlZHVjZSgociwgaykgPT4ge1xuICAgIGNvbnN0IGYgPSB0b0ZpZWxkKGspO1xuICAgIGlmIChmKSB7XG4gICAgICByW2ZdID0gbWF0Y2hlc1trXTtcbiAgICB9XG5cbiAgICByZXR1cm4gcjtcbiAgfSwge30pO1xuXG4gIHJldHVybiBbdmFscywgem9uZSwgc3BlY2lmaWNPZmZzZXRdO1xufVxuXG5sZXQgZHVtbXlEYXRlVGltZUNhY2hlID0gbnVsbDtcblxuZnVuY3Rpb24gZ2V0RHVtbXlEYXRlVGltZSgpIHtcbiAgaWYgKCFkdW1teURhdGVUaW1lQ2FjaGUpIHtcbiAgICBkdW1teURhdGVUaW1lQ2FjaGUgPSBEYXRlVGltZS5mcm9tTWlsbGlzKDE1NTU1NTU1NTU1NTUpO1xuICB9XG5cbiAgcmV0dXJuIGR1bW15RGF0ZVRpbWVDYWNoZTtcbn1cblxuZnVuY3Rpb24gbWF5YmVFeHBhbmRNYWNyb1Rva2VuKHRva2VuLCBsb2NhbGUpIHtcbiAgaWYgKHRva2VuLmxpdGVyYWwpIHtcbiAgICByZXR1cm4gdG9rZW47XG4gIH1cblxuICBjb25zdCBmb3JtYXRPcHRzID0gRm9ybWF0dGVyLm1hY3JvVG9rZW5Ub0Zvcm1hdE9wdHModG9rZW4udmFsKTtcbiAgY29uc3QgdG9rZW5zID0gZm9ybWF0T3B0c1RvVG9rZW5zKGZvcm1hdE9wdHMsIGxvY2FsZSk7XG5cbiAgaWYgKHRva2VucyA9PSBudWxsIHx8IHRva2Vucy5pbmNsdWRlcyh1bmRlZmluZWQpKSB7XG4gICAgcmV0dXJuIHRva2VuO1xuICB9XG5cbiAgcmV0dXJuIHRva2Vucztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGV4cGFuZE1hY3JvVG9rZW5zKHRva2VucywgbG9jYWxlKSB7XG4gIHJldHVybiBBcnJheS5wcm90b3R5cGUuY29uY2F0KC4uLnRva2Vucy5tYXAoKHQpID0+IG1heWJlRXhwYW5kTWFjcm9Ub2tlbih0LCBsb2NhbGUpKSk7XG59XG5cbi8qKlxuICogQHByaXZhdGVcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gZXhwbGFpbkZyb21Ub2tlbnMobG9jYWxlLCBpbnB1dCwgZm9ybWF0KSB7XG4gIGNvbnN0IHRva2VucyA9IGV4cGFuZE1hY3JvVG9rZW5zKEZvcm1hdHRlci5wYXJzZUZvcm1hdChmb3JtYXQpLCBsb2NhbGUpLFxuICAgIHVuaXRzID0gdG9rZW5zLm1hcCgodCkgPT4gdW5pdEZvclRva2VuKHQsIGxvY2FsZSkpLFxuICAgIGRpc3F1YWxpZnlpbmdVbml0ID0gdW5pdHMuZmluZCgodCkgPT4gdC5pbnZhbGlkUmVhc29uKTtcblxuICBpZiAoZGlzcXVhbGlmeWluZ1VuaXQpIHtcbiAgICByZXR1cm4geyBpbnB1dCwgdG9rZW5zLCBpbnZhbGlkUmVhc29uOiBkaXNxdWFsaWZ5aW5nVW5pdC5pbnZhbGlkUmVhc29uIH07XG4gIH0gZWxzZSB7XG4gICAgY29uc3QgW3JlZ2V4U3RyaW5nLCBoYW5kbGVyc10gPSBidWlsZFJlZ2V4KHVuaXRzKSxcbiAgICAgIHJlZ2V4ID0gUmVnRXhwKHJlZ2V4U3RyaW5nLCBcImlcIiksXG4gICAgICBbcmF3TWF0Y2hlcywgbWF0Y2hlc10gPSBtYXRjaChpbnB1dCwgcmVnZXgsIGhhbmRsZXJzKSxcbiAgICAgIFtyZXN1bHQsIHpvbmUsIHNwZWNpZmljT2Zmc2V0XSA9IG1hdGNoZXNcbiAgICAgICAgPyBkYXRlVGltZUZyb21NYXRjaGVzKG1hdGNoZXMpXG4gICAgICAgIDogW251bGwsIG51bGwsIHVuZGVmaW5lZF07XG4gICAgaWYgKGhhc093blByb3BlcnR5KG1hdGNoZXMsIFwiYVwiKSAmJiBoYXNPd25Qcm9wZXJ0eShtYXRjaGVzLCBcIkhcIikpIHtcbiAgICAgIHRocm93IG5ldyBDb25mbGljdGluZ1NwZWNpZmljYXRpb25FcnJvcihcbiAgICAgICAgXCJDYW4ndCBpbmNsdWRlIG1lcmlkaWVtIHdoZW4gc3BlY2lmeWluZyAyNC1ob3VyIGZvcm1hdFwiXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4geyBpbnB1dCwgdG9rZW5zLCByZWdleCwgcmF3TWF0Y2hlcywgbWF0Y2hlcywgcmVzdWx0LCB6b25lLCBzcGVjaWZpY09mZnNldCB9O1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXJzZUZyb21Ub2tlbnMobG9jYWxlLCBpbnB1dCwgZm9ybWF0KSB7XG4gIGNvbnN0IHsgcmVzdWx0LCB6b25lLCBzcGVjaWZpY09mZnNldCwgaW52YWxpZFJlYXNvbiB9ID0gZXhwbGFpbkZyb21Ub2tlbnMobG9jYWxlLCBpbnB1dCwgZm9ybWF0KTtcbiAgcmV0dXJuIFtyZXN1bHQsIHpvbmUsIHNwZWNpZmljT2Zmc2V0LCBpbnZhbGlkUmVhc29uXTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdE9wdHNUb1Rva2Vucyhmb3JtYXRPcHRzLCBsb2NhbGUpIHtcbiAgaWYgKCFmb3JtYXRPcHRzKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCBmb3JtYXR0ZXIgPSBGb3JtYXR0ZXIuY3JlYXRlKGxvY2FsZSwgZm9ybWF0T3B0cyk7XG4gIGNvbnN0IHBhcnRzID0gZm9ybWF0dGVyLmZvcm1hdERhdGVUaW1lUGFydHMoZ2V0RHVtbXlEYXRlVGltZSgpKTtcbiAgcmV0dXJuIHBhcnRzLm1hcCgocCkgPT4gdG9rZW5Gb3JQYXJ0KHAsIGZvcm1hdE9wdHMpKTtcbn1cbiIsICJpbXBvcnQge1xuICBpbnRlZ2VyQmV0d2VlbixcbiAgaXNMZWFwWWVhcixcbiAgdGltZU9iamVjdCxcbiAgZGF5c0luWWVhcixcbiAgZGF5c0luTW9udGgsXG4gIHdlZWtzSW5XZWVrWWVhcixcbiAgaXNJbnRlZ2VyLFxufSBmcm9tIFwiLi91dGlsLmpzXCI7XG5pbXBvcnQgSW52YWxpZCBmcm9tIFwiLi9pbnZhbGlkLmpzXCI7XG5cbmNvbnN0IG5vbkxlYXBMYWRkZXIgPSBbMCwgMzEsIDU5LCA5MCwgMTIwLCAxNTEsIDE4MSwgMjEyLCAyNDMsIDI3MywgMzA0LCAzMzRdLFxuICBsZWFwTGFkZGVyID0gWzAsIDMxLCA2MCwgOTEsIDEyMSwgMTUyLCAxODIsIDIxMywgMjQ0LCAyNzQsIDMwNSwgMzM1XTtcblxuZnVuY3Rpb24gdW5pdE91dE9mUmFuZ2UodW5pdCwgdmFsdWUpIHtcbiAgcmV0dXJuIG5ldyBJbnZhbGlkKFxuICAgIFwidW5pdCBvdXQgb2YgcmFuZ2VcIixcbiAgICBgeW91IHNwZWNpZmllZCAke3ZhbHVlfSAob2YgdHlwZSAke3R5cGVvZiB2YWx1ZX0pIGFzIGEgJHt1bml0fSwgd2hpY2ggaXMgaW52YWxpZGBcbiAgKTtcbn1cblxuZnVuY3Rpb24gZGF5T2ZXZWVrKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgY29uc3QgZCA9IG5ldyBEYXRlKERhdGUuVVRDKHllYXIsIG1vbnRoIC0gMSwgZGF5KSk7XG5cbiAgaWYgKHllYXIgPCAxMDAgJiYgeWVhciA+PSAwKSB7XG4gICAgZC5zZXRVVENGdWxsWWVhcihkLmdldFVUQ0Z1bGxZZWFyKCkgLSAxOTAwKTtcbiAgfVxuXG4gIGNvbnN0IGpzID0gZC5nZXRVVENEYXkoKTtcblxuICByZXR1cm4ganMgPT09IDAgPyA3IDoganM7XG59XG5cbmZ1bmN0aW9uIGNvbXB1dGVPcmRpbmFsKHllYXIsIG1vbnRoLCBkYXkpIHtcbiAgcmV0dXJuIGRheSArIChpc0xlYXBZZWFyKHllYXIpID8gbGVhcExhZGRlciA6IG5vbkxlYXBMYWRkZXIpW21vbnRoIC0gMV07XG59XG5cbmZ1bmN0aW9uIHVuY29tcHV0ZU9yZGluYWwoeWVhciwgb3JkaW5hbCkge1xuICBjb25zdCB0YWJsZSA9IGlzTGVhcFllYXIoeWVhcikgPyBsZWFwTGFkZGVyIDogbm9uTGVhcExhZGRlcixcbiAgICBtb250aDAgPSB0YWJsZS5maW5kSW5kZXgoKGkpID0+IGkgPCBvcmRpbmFsKSxcbiAgICBkYXkgPSBvcmRpbmFsIC0gdGFibGVbbW9udGgwXTtcbiAgcmV0dXJuIHsgbW9udGg6IG1vbnRoMCArIDEsIGRheSB9O1xufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cblxuZXhwb3J0IGZ1bmN0aW9uIGdyZWdvcmlhblRvV2VlayhncmVnT2JqKSB7XG4gIGNvbnN0IHsgeWVhciwgbW9udGgsIGRheSB9ID0gZ3JlZ09iaixcbiAgICBvcmRpbmFsID0gY29tcHV0ZU9yZGluYWwoeWVhciwgbW9udGgsIGRheSksXG4gICAgd2Vla2RheSA9IGRheU9mV2Vlayh5ZWFyLCBtb250aCwgZGF5KTtcblxuICBsZXQgd2Vla051bWJlciA9IE1hdGguZmxvb3IoKG9yZGluYWwgLSB3ZWVrZGF5ICsgMTApIC8gNyksXG4gICAgd2Vla1llYXI7XG5cbiAgaWYgKHdlZWtOdW1iZXIgPCAxKSB7XG4gICAgd2Vla1llYXIgPSB5ZWFyIC0gMTtcbiAgICB3ZWVrTnVtYmVyID0gd2Vla3NJbldlZWtZZWFyKHdlZWtZZWFyKTtcbiAgfSBlbHNlIGlmICh3ZWVrTnVtYmVyID4gd2Vla3NJbldlZWtZZWFyKHllYXIpKSB7XG4gICAgd2Vla1llYXIgPSB5ZWFyICsgMTtcbiAgICB3ZWVrTnVtYmVyID0gMTtcbiAgfSBlbHNlIHtcbiAgICB3ZWVrWWVhciA9IHllYXI7XG4gIH1cblxuICByZXR1cm4geyB3ZWVrWWVhciwgd2Vla051bWJlciwgd2Vla2RheSwgLi4udGltZU9iamVjdChncmVnT2JqKSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd2Vla1RvR3JlZ29yaWFuKHdlZWtEYXRhKSB7XG4gIGNvbnN0IHsgd2Vla1llYXIsIHdlZWtOdW1iZXIsIHdlZWtkYXkgfSA9IHdlZWtEYXRhLFxuICAgIHdlZWtkYXlPZkphbjQgPSBkYXlPZldlZWsod2Vla1llYXIsIDEsIDQpLFxuICAgIHllYXJJbkRheXMgPSBkYXlzSW5ZZWFyKHdlZWtZZWFyKTtcblxuICBsZXQgb3JkaW5hbCA9IHdlZWtOdW1iZXIgKiA3ICsgd2Vla2RheSAtIHdlZWtkYXlPZkphbjQgLSAzLFxuICAgIHllYXI7XG5cbiAgaWYgKG9yZGluYWwgPCAxKSB7XG4gICAgeWVhciA9IHdlZWtZZWFyIC0gMTtcbiAgICBvcmRpbmFsICs9IGRheXNJblllYXIoeWVhcik7XG4gIH0gZWxzZSBpZiAob3JkaW5hbCA+IHllYXJJbkRheXMpIHtcbiAgICB5ZWFyID0gd2Vla1llYXIgKyAxO1xuICAgIG9yZGluYWwgLT0gZGF5c0luWWVhcih3ZWVrWWVhcik7XG4gIH0gZWxzZSB7XG4gICAgeWVhciA9IHdlZWtZZWFyO1xuICB9XG5cbiAgY29uc3QgeyBtb250aCwgZGF5IH0gPSB1bmNvbXB1dGVPcmRpbmFsKHllYXIsIG9yZGluYWwpO1xuICByZXR1cm4geyB5ZWFyLCBtb250aCwgZGF5LCAuLi50aW1lT2JqZWN0KHdlZWtEYXRhKSB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ3JlZ29yaWFuVG9PcmRpbmFsKGdyZWdEYXRhKSB7XG4gIGNvbnN0IHsgeWVhciwgbW9udGgsIGRheSB9ID0gZ3JlZ0RhdGE7XG4gIGNvbnN0IG9yZGluYWwgPSBjb21wdXRlT3JkaW5hbCh5ZWFyLCBtb250aCwgZGF5KTtcbiAgcmV0dXJuIHsgeWVhciwgb3JkaW5hbCwgLi4udGltZU9iamVjdChncmVnRGF0YSkgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9yZGluYWxUb0dyZWdvcmlhbihvcmRpbmFsRGF0YSkge1xuICBjb25zdCB7IHllYXIsIG9yZGluYWwgfSA9IG9yZGluYWxEYXRhO1xuICBjb25zdCB7IG1vbnRoLCBkYXkgfSA9IHVuY29tcHV0ZU9yZGluYWwoeWVhciwgb3JkaW5hbCk7XG4gIHJldHVybiB7IHllYXIsIG1vbnRoLCBkYXksIC4uLnRpbWVPYmplY3Qob3JkaW5hbERhdGEpIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNJbnZhbGlkV2Vla0RhdGEob2JqKSB7XG4gIGNvbnN0IHZhbGlkWWVhciA9IGlzSW50ZWdlcihvYmoud2Vla1llYXIpLFxuICAgIHZhbGlkV2VlayA9IGludGVnZXJCZXR3ZWVuKG9iai53ZWVrTnVtYmVyLCAxLCB3ZWVrc0luV2Vla1llYXIob2JqLndlZWtZZWFyKSksXG4gICAgdmFsaWRXZWVrZGF5ID0gaW50ZWdlckJldHdlZW4ob2JqLndlZWtkYXksIDEsIDcpO1xuXG4gIGlmICghdmFsaWRZZWFyKSB7XG4gICAgcmV0dXJuIHVuaXRPdXRPZlJhbmdlKFwid2Vla1llYXJcIiwgb2JqLndlZWtZZWFyKTtcbiAgfSBlbHNlIGlmICghdmFsaWRXZWVrKSB7XG4gICAgcmV0dXJuIHVuaXRPdXRPZlJhbmdlKFwid2Vla1wiLCBvYmoud2Vlayk7XG4gIH0gZWxzZSBpZiAoIXZhbGlkV2Vla2RheSkge1xuICAgIHJldHVybiB1bml0T3V0T2ZSYW5nZShcIndlZWtkYXlcIiwgb2JqLndlZWtkYXkpO1xuICB9IGVsc2UgcmV0dXJuIGZhbHNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzSW52YWxpZE9yZGluYWxEYXRhKG9iaikge1xuICBjb25zdCB2YWxpZFllYXIgPSBpc0ludGVnZXIob2JqLnllYXIpLFxuICAgIHZhbGlkT3JkaW5hbCA9IGludGVnZXJCZXR3ZWVuKG9iai5vcmRpbmFsLCAxLCBkYXlzSW5ZZWFyKG9iai55ZWFyKSk7XG5cbiAgaWYgKCF2YWxpZFllYXIpIHtcbiAgICByZXR1cm4gdW5pdE91dE9mUmFuZ2UoXCJ5ZWFyXCIsIG9iai55ZWFyKTtcbiAgfSBlbHNlIGlmICghdmFsaWRPcmRpbmFsKSB7XG4gICAgcmV0dXJuIHVuaXRPdXRPZlJhbmdlKFwib3JkaW5hbFwiLCBvYmoub3JkaW5hbCk7XG4gIH0gZWxzZSByZXR1cm4gZmFsc2U7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNJbnZhbGlkR3JlZ29yaWFuRGF0YShvYmopIHtcbiAgY29uc3QgdmFsaWRZZWFyID0gaXNJbnRlZ2VyKG9iai55ZWFyKSxcbiAgICB2YWxpZE1vbnRoID0gaW50ZWdlckJldHdlZW4ob2JqLm1vbnRoLCAxLCAxMiksXG4gICAgdmFsaWREYXkgPSBpbnRlZ2VyQmV0d2VlbihvYmouZGF5LCAxLCBkYXlzSW5Nb250aChvYmoueWVhciwgb2JqLm1vbnRoKSk7XG5cbiAgaWYgKCF2YWxpZFllYXIpIHtcbiAgICByZXR1cm4gdW5pdE91dE9mUmFuZ2UoXCJ5ZWFyXCIsIG9iai55ZWFyKTtcbiAgfSBlbHNlIGlmICghdmFsaWRNb250aCkge1xuICAgIHJldHVybiB1bml0T3V0T2ZSYW5nZShcIm1vbnRoXCIsIG9iai5tb250aCk7XG4gIH0gZWxzZSBpZiAoIXZhbGlkRGF5KSB7XG4gICAgcmV0dXJuIHVuaXRPdXRPZlJhbmdlKFwiZGF5XCIsIG9iai5kYXkpO1xuICB9IGVsc2UgcmV0dXJuIGZhbHNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzSW52YWxpZFRpbWVEYXRhKG9iaikge1xuICBjb25zdCB7IGhvdXIsIG1pbnV0ZSwgc2Vjb25kLCBtaWxsaXNlY29uZCB9ID0gb2JqO1xuICBjb25zdCB2YWxpZEhvdXIgPVxuICAgICAgaW50ZWdlckJldHdlZW4oaG91ciwgMCwgMjMpIHx8XG4gICAgICAoaG91ciA9PT0gMjQgJiYgbWludXRlID09PSAwICYmIHNlY29uZCA9PT0gMCAmJiBtaWxsaXNlY29uZCA9PT0gMCksXG4gICAgdmFsaWRNaW51dGUgPSBpbnRlZ2VyQmV0d2VlbihtaW51dGUsIDAsIDU5KSxcbiAgICB2YWxpZFNlY29uZCA9IGludGVnZXJCZXR3ZWVuKHNlY29uZCwgMCwgNTkpLFxuICAgIHZhbGlkTWlsbGlzZWNvbmQgPSBpbnRlZ2VyQmV0d2VlbihtaWxsaXNlY29uZCwgMCwgOTk5KTtcblxuICBpZiAoIXZhbGlkSG91cikge1xuICAgIHJldHVybiB1bml0T3V0T2ZSYW5nZShcImhvdXJcIiwgaG91cik7XG4gIH0gZWxzZSBpZiAoIXZhbGlkTWludXRlKSB7XG4gICAgcmV0dXJuIHVuaXRPdXRPZlJhbmdlKFwibWludXRlXCIsIG1pbnV0ZSk7XG4gIH0gZWxzZSBpZiAoIXZhbGlkU2Vjb25kKSB7XG4gICAgcmV0dXJuIHVuaXRPdXRPZlJhbmdlKFwic2Vjb25kXCIsIHNlY29uZCk7XG4gIH0gZWxzZSBpZiAoIXZhbGlkTWlsbGlzZWNvbmQpIHtcbiAgICByZXR1cm4gdW5pdE91dE9mUmFuZ2UoXCJtaWxsaXNlY29uZFwiLCBtaWxsaXNlY29uZCk7XG4gIH0gZWxzZSByZXR1cm4gZmFsc2U7XG59XG4iLCAiaW1wb3J0IER1cmF0aW9uIGZyb20gXCIuL2R1cmF0aW9uLmpzXCI7XG5pbXBvcnQgSW50ZXJ2YWwgZnJvbSBcIi4vaW50ZXJ2YWwuanNcIjtcbmltcG9ydCBTZXR0aW5ncyBmcm9tIFwiLi9zZXR0aW5ncy5qc1wiO1xuaW1wb3J0IEluZm8gZnJvbSBcIi4vaW5mby5qc1wiO1xuaW1wb3J0IEZvcm1hdHRlciBmcm9tIFwiLi9pbXBsL2Zvcm1hdHRlci5qc1wiO1xuaW1wb3J0IEZpeGVkT2Zmc2V0Wm9uZSBmcm9tIFwiLi96b25lcy9maXhlZE9mZnNldFpvbmUuanNcIjtcbmltcG9ydCBMb2NhbGUgZnJvbSBcIi4vaW1wbC9sb2NhbGUuanNcIjtcbmltcG9ydCB7XG4gIGlzVW5kZWZpbmVkLFxuICBtYXliZUFycmF5LFxuICBpc0RhdGUsXG4gIGlzTnVtYmVyLFxuICBiZXN0QnksXG4gIGRheXNJbk1vbnRoLFxuICBkYXlzSW5ZZWFyLFxuICBpc0xlYXBZZWFyLFxuICB3ZWVrc0luV2Vla1llYXIsXG4gIG5vcm1hbGl6ZU9iamVjdCxcbiAgcm91bmRUbyxcbiAgb2JqVG9Mb2NhbFRTLFxuICBwYWRTdGFydCxcbn0gZnJvbSBcIi4vaW1wbC91dGlsLmpzXCI7XG5pbXBvcnQgeyBub3JtYWxpemVab25lIH0gZnJvbSBcIi4vaW1wbC96b25lVXRpbC5qc1wiO1xuaW1wb3J0IGRpZmYgZnJvbSBcIi4vaW1wbC9kaWZmLmpzXCI7XG5pbXBvcnQgeyBwYXJzZVJGQzI4MjJEYXRlLCBwYXJzZUlTT0RhdGUsIHBhcnNlSFRUUERhdGUsIHBhcnNlU1FMIH0gZnJvbSBcIi4vaW1wbC9yZWdleFBhcnNlci5qc1wiO1xuaW1wb3J0IHtcbiAgcGFyc2VGcm9tVG9rZW5zLFxuICBleHBsYWluRnJvbVRva2VucyxcbiAgZm9ybWF0T3B0c1RvVG9rZW5zLFxuICBleHBhbmRNYWNyb1Rva2Vucyxcbn0gZnJvbSBcIi4vaW1wbC90b2tlblBhcnNlci5qc1wiO1xuaW1wb3J0IHtcbiAgZ3JlZ29yaWFuVG9XZWVrLFxuICB3ZWVrVG9HcmVnb3JpYW4sXG4gIGdyZWdvcmlhblRvT3JkaW5hbCxcbiAgb3JkaW5hbFRvR3JlZ29yaWFuLFxuICBoYXNJbnZhbGlkR3JlZ29yaWFuRGF0YSxcbiAgaGFzSW52YWxpZFdlZWtEYXRhLFxuICBoYXNJbnZhbGlkT3JkaW5hbERhdGEsXG4gIGhhc0ludmFsaWRUaW1lRGF0YSxcbn0gZnJvbSBcIi4vaW1wbC9jb252ZXJzaW9ucy5qc1wiO1xuaW1wb3J0ICogYXMgRm9ybWF0cyBmcm9tIFwiLi9pbXBsL2Zvcm1hdHMuanNcIjtcbmltcG9ydCB7XG4gIEludmFsaWRBcmd1bWVudEVycm9yLFxuICBDb25mbGljdGluZ1NwZWNpZmljYXRpb25FcnJvcixcbiAgSW52YWxpZFVuaXRFcnJvcixcbiAgSW52YWxpZERhdGVUaW1lRXJyb3IsXG59IGZyb20gXCIuL2Vycm9ycy5qc1wiO1xuaW1wb3J0IEludmFsaWQgZnJvbSBcIi4vaW1wbC9pbnZhbGlkLmpzXCI7XG5cbmNvbnN0IElOVkFMSUQgPSBcIkludmFsaWQgRGF0ZVRpbWVcIjtcbmNvbnN0IE1BWF9EQVRFID0gOC42NGUxNTtcblxuZnVuY3Rpb24gdW5zdXBwb3J0ZWRab25lKHpvbmUpIHtcbiAgcmV0dXJuIG5ldyBJbnZhbGlkKFwidW5zdXBwb3J0ZWQgem9uZVwiLCBgdGhlIHpvbmUgXCIke3pvbmUubmFtZX1cIiBpcyBub3Qgc3VwcG9ydGVkYCk7XG59XG5cbi8vIHdlIGNhY2hlIHdlZWsgZGF0YSBvbiB0aGUgRFQgb2JqZWN0IGFuZCB0aGlzIGludGVybWVkaWF0ZXMgdGhlIGNhY2hlXG5mdW5jdGlvbiBwb3NzaWJseUNhY2hlZFdlZWtEYXRhKGR0KSB7XG4gIGlmIChkdC53ZWVrRGF0YSA9PT0gbnVsbCkge1xuICAgIGR0LndlZWtEYXRhID0gZ3JlZ29yaWFuVG9XZWVrKGR0LmMpO1xuICB9XG4gIHJldHVybiBkdC53ZWVrRGF0YTtcbn1cblxuLy8gY2xvbmUgcmVhbGx5IG1lYW5zLCBcIm1ha2UgYSBuZXcgb2JqZWN0IHdpdGggdGhlc2UgbW9kaWZpY2F0aW9uc1wiLiBhbGwgXCJzZXR0ZXJzXCIgcmVhbGx5IHVzZSB0aGlzXG4vLyB0byBjcmVhdGUgYSBuZXcgb2JqZWN0IHdoaWxlIG9ubHkgY2hhbmdpbmcgc29tZSBvZiB0aGUgcHJvcGVydGllc1xuZnVuY3Rpb24gY2xvbmUoaW5zdCwgYWx0cykge1xuICBjb25zdCBjdXJyZW50ID0ge1xuICAgIHRzOiBpbnN0LnRzLFxuICAgIHpvbmU6IGluc3Quem9uZSxcbiAgICBjOiBpbnN0LmMsXG4gICAgbzogaW5zdC5vLFxuICAgIGxvYzogaW5zdC5sb2MsXG4gICAgaW52YWxpZDogaW5zdC5pbnZhbGlkLFxuICB9O1xuICByZXR1cm4gbmV3IERhdGVUaW1lKHsgLi4uY3VycmVudCwgLi4uYWx0cywgb2xkOiBjdXJyZW50IH0pO1xufVxuXG4vLyBmaW5kIHRoZSByaWdodCBvZmZzZXQgYSBnaXZlbiBsb2NhbCB0aW1lLiBUaGUgbyBpbnB1dCBpcyBvdXIgZ3Vlc3MsIHdoaWNoIGRldGVybWluZXMgd2hpY2hcbi8vIG9mZnNldCB3ZSdsbCBwaWNrIGluIGFtYmlndW91cyBjYXNlcyAoZS5nLiB0aGVyZSBhcmUgdHdvIDMgQU1zIGIvYyBGYWxsYmFjayBEU1QpXG5mdW5jdGlvbiBmaXhPZmZzZXQobG9jYWxUUywgbywgdHopIHtcbiAgLy8gT3VyIFVUQyB0aW1lIGlzIGp1c3QgYSBndWVzcyBiZWNhdXNlIG91ciBvZmZzZXQgaXMganVzdCBhIGd1ZXNzXG4gIGxldCB1dGNHdWVzcyA9IGxvY2FsVFMgLSBvICogNjAgKiAxMDAwO1xuXG4gIC8vIFRlc3Qgd2hldGhlciB0aGUgem9uZSBtYXRjaGVzIHRoZSBvZmZzZXQgZm9yIHRoaXMgdHNcbiAgY29uc3QgbzIgPSB0ei5vZmZzZXQodXRjR3Vlc3MpO1xuXG4gIC8vIElmIHNvLCBvZmZzZXQgZGlkbid0IGNoYW5nZSBhbmQgd2UncmUgZG9uZVxuICBpZiAobyA9PT0gbzIpIHtcbiAgICByZXR1cm4gW3V0Y0d1ZXNzLCBvXTtcbiAgfVxuXG4gIC8vIElmIG5vdCwgY2hhbmdlIHRoZSB0cyBieSB0aGUgZGlmZmVyZW5jZSBpbiB0aGUgb2Zmc2V0XG4gIHV0Y0d1ZXNzIC09IChvMiAtIG8pICogNjAgKiAxMDAwO1xuXG4gIC8vIElmIHRoYXQgZ2l2ZXMgdXMgdGhlIGxvY2FsIHRpbWUgd2Ugd2FudCwgd2UncmUgZG9uZVxuICBjb25zdCBvMyA9IHR6Lm9mZnNldCh1dGNHdWVzcyk7XG4gIGlmIChvMiA9PT0gbzMpIHtcbiAgICByZXR1cm4gW3V0Y0d1ZXNzLCBvMl07XG4gIH1cblxuICAvLyBJZiBpdCdzIGRpZmZlcmVudCwgd2UncmUgaW4gYSBob2xlIHRpbWUuIFRoZSBvZmZzZXQgaGFzIGNoYW5nZWQsIGJ1dCB0aGUgd2UgZG9uJ3QgYWRqdXN0IHRoZSB0aW1lXG4gIHJldHVybiBbbG9jYWxUUyAtIE1hdGgubWluKG8yLCBvMykgKiA2MCAqIDEwMDAsIE1hdGgubWF4KG8yLCBvMyldO1xufVxuXG4vLyBjb252ZXJ0IGFuIGVwb2NoIHRpbWVzdGFtcCBpbnRvIGEgY2FsZW5kYXIgb2JqZWN0IHdpdGggdGhlIGdpdmVuIG9mZnNldFxuZnVuY3Rpb24gdHNUb09iaih0cywgb2Zmc2V0KSB7XG4gIHRzICs9IG9mZnNldCAqIDYwICogMTAwMDtcblxuICBjb25zdCBkID0gbmV3IERhdGUodHMpO1xuXG4gIHJldHVybiB7XG4gICAgeWVhcjogZC5nZXRVVENGdWxsWWVhcigpLFxuICAgIG1vbnRoOiBkLmdldFVUQ01vbnRoKCkgKyAxLFxuICAgIGRheTogZC5nZXRVVENEYXRlKCksXG4gICAgaG91cjogZC5nZXRVVENIb3VycygpLFxuICAgIG1pbnV0ZTogZC5nZXRVVENNaW51dGVzKCksXG4gICAgc2Vjb25kOiBkLmdldFVUQ1NlY29uZHMoKSxcbiAgICBtaWxsaXNlY29uZDogZC5nZXRVVENNaWxsaXNlY29uZHMoKSxcbiAgfTtcbn1cblxuLy8gY29udmVydCBhIGNhbGVuZGFyIG9iamVjdCB0byBhIGVwb2NoIHRpbWVzdGFtcFxuZnVuY3Rpb24gb2JqVG9UUyhvYmosIG9mZnNldCwgem9uZSkge1xuICByZXR1cm4gZml4T2Zmc2V0KG9ialRvTG9jYWxUUyhvYmopLCBvZmZzZXQsIHpvbmUpO1xufVxuXG4vLyBjcmVhdGUgYSBuZXcgRFQgaW5zdGFuY2UgYnkgYWRkaW5nIGEgZHVyYXRpb24sIGFkanVzdGluZyBmb3IgRFNUc1xuZnVuY3Rpb24gYWRqdXN0VGltZShpbnN0LCBkdXIpIHtcbiAgY29uc3Qgb1ByZSA9IGluc3QubyxcbiAgICB5ZWFyID0gaW5zdC5jLnllYXIgKyBNYXRoLnRydW5jKGR1ci55ZWFycyksXG4gICAgbW9udGggPSBpbnN0LmMubW9udGggKyBNYXRoLnRydW5jKGR1ci5tb250aHMpICsgTWF0aC50cnVuYyhkdXIucXVhcnRlcnMpICogMyxcbiAgICBjID0ge1xuICAgICAgLi4uaW5zdC5jLFxuICAgICAgeWVhcixcbiAgICAgIG1vbnRoLFxuICAgICAgZGF5OlxuICAgICAgICBNYXRoLm1pbihpbnN0LmMuZGF5LCBkYXlzSW5Nb250aCh5ZWFyLCBtb250aCkpICtcbiAgICAgICAgTWF0aC50cnVuYyhkdXIuZGF5cykgK1xuICAgICAgICBNYXRoLnRydW5jKGR1ci53ZWVrcykgKiA3LFxuICAgIH0sXG4gICAgbWlsbGlzVG9BZGQgPSBEdXJhdGlvbi5mcm9tT2JqZWN0KHtcbiAgICAgIHllYXJzOiBkdXIueWVhcnMgLSBNYXRoLnRydW5jKGR1ci55ZWFycyksXG4gICAgICBxdWFydGVyczogZHVyLnF1YXJ0ZXJzIC0gTWF0aC50cnVuYyhkdXIucXVhcnRlcnMpLFxuICAgICAgbW9udGhzOiBkdXIubW9udGhzIC0gTWF0aC50cnVuYyhkdXIubW9udGhzKSxcbiAgICAgIHdlZWtzOiBkdXIud2Vla3MgLSBNYXRoLnRydW5jKGR1ci53ZWVrcyksXG4gICAgICBkYXlzOiBkdXIuZGF5cyAtIE1hdGgudHJ1bmMoZHVyLmRheXMpLFxuICAgICAgaG91cnM6IGR1ci5ob3VycyxcbiAgICAgIG1pbnV0ZXM6IGR1ci5taW51dGVzLFxuICAgICAgc2Vjb25kczogZHVyLnNlY29uZHMsXG4gICAgICBtaWxsaXNlY29uZHM6IGR1ci5taWxsaXNlY29uZHMsXG4gICAgfSkuYXMoXCJtaWxsaXNlY29uZHNcIiksXG4gICAgbG9jYWxUUyA9IG9ialRvTG9jYWxUUyhjKTtcblxuICBsZXQgW3RzLCBvXSA9IGZpeE9mZnNldChsb2NhbFRTLCBvUHJlLCBpbnN0LnpvbmUpO1xuXG4gIGlmIChtaWxsaXNUb0FkZCAhPT0gMCkge1xuICAgIHRzICs9IG1pbGxpc1RvQWRkO1xuICAgIC8vIHRoYXQgY291bGQgaGF2ZSBjaGFuZ2VkIHRoZSBvZmZzZXQgYnkgZ29pbmcgb3ZlciBhIERTVCwgYnV0IHdlIHdhbnQgdG8ga2VlcCB0aGUgdHMgdGhlIHNhbWVcbiAgICBvID0gaW5zdC56b25lLm9mZnNldCh0cyk7XG4gIH1cblxuICByZXR1cm4geyB0cywgbyB9O1xufVxuXG4vLyBoZWxwZXIgdXNlZnVsIGluIHR1cm5pbmcgdGhlIHJlc3VsdHMgb2YgcGFyc2luZyBpbnRvIHJlYWwgZGF0ZXNcbi8vIGJ5IGhhbmRsaW5nIHRoZSB6b25lIG9wdGlvbnNcbmZ1bmN0aW9uIHBhcnNlRGF0YVRvRGF0ZVRpbWUocGFyc2VkLCBwYXJzZWRab25lLCBvcHRzLCBmb3JtYXQsIHRleHQsIHNwZWNpZmljT2Zmc2V0KSB7XG4gIGNvbnN0IHsgc2V0Wm9uZSwgem9uZSB9ID0gb3B0cztcbiAgaWYgKChwYXJzZWQgJiYgT2JqZWN0LmtleXMocGFyc2VkKS5sZW5ndGggIT09IDApIHx8IHBhcnNlZFpvbmUpIHtcbiAgICBjb25zdCBpbnRlcnByZXRhdGlvblpvbmUgPSBwYXJzZWRab25lIHx8IHpvbmUsXG4gICAgICBpbnN0ID0gRGF0ZVRpbWUuZnJvbU9iamVjdChwYXJzZWQsIHtcbiAgICAgICAgLi4ub3B0cyxcbiAgICAgICAgem9uZTogaW50ZXJwcmV0YXRpb25ab25lLFxuICAgICAgICBzcGVjaWZpY09mZnNldCxcbiAgICAgIH0pO1xuICAgIHJldHVybiBzZXRab25lID8gaW5zdCA6IGluc3Quc2V0Wm9uZSh6b25lKTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gRGF0ZVRpbWUuaW52YWxpZChcbiAgICAgIG5ldyBJbnZhbGlkKFwidW5wYXJzYWJsZVwiLCBgdGhlIGlucHV0IFwiJHt0ZXh0fVwiIGNhbid0IGJlIHBhcnNlZCBhcyAke2Zvcm1hdH1gKVxuICAgICk7XG4gIH1cbn1cblxuLy8gaWYgeW91IHdhbnQgdG8gb3V0cHV0IGEgdGVjaG5pY2FsIGZvcm1hdCAoZS5nLiBSRkMgMjgyMiksIHRoaXMgaGVscGVyXG4vLyBoZWxwcyBoYW5kbGUgdGhlIGRldGFpbHNcbmZ1bmN0aW9uIHRvVGVjaEZvcm1hdChkdCwgZm9ybWF0LCBhbGxvd1ogPSB0cnVlKSB7XG4gIHJldHVybiBkdC5pc1ZhbGlkXG4gICAgPyBGb3JtYXR0ZXIuY3JlYXRlKExvY2FsZS5jcmVhdGUoXCJlbi1VU1wiKSwge1xuICAgICAgICBhbGxvd1osXG4gICAgICAgIGZvcmNlU2ltcGxlOiB0cnVlLFxuICAgICAgfSkuZm9ybWF0RGF0ZVRpbWVGcm9tU3RyaW5nKGR0LCBmb3JtYXQpXG4gICAgOiBudWxsO1xufVxuXG5mdW5jdGlvbiB0b0lTT0RhdGUobywgZXh0ZW5kZWQpIHtcbiAgY29uc3QgbG9uZ0Zvcm1hdCA9IG8uYy55ZWFyID4gOTk5OSB8fCBvLmMueWVhciA8IDA7XG4gIGxldCBjID0gXCJcIjtcbiAgaWYgKGxvbmdGb3JtYXQgJiYgby5jLnllYXIgPj0gMCkgYyArPSBcIitcIjtcbiAgYyArPSBwYWRTdGFydChvLmMueWVhciwgbG9uZ0Zvcm1hdCA/IDYgOiA0KTtcblxuICBpZiAoZXh0ZW5kZWQpIHtcbiAgICBjICs9IFwiLVwiO1xuICAgIGMgKz0gcGFkU3RhcnQoby5jLm1vbnRoKTtcbiAgICBjICs9IFwiLVwiO1xuICAgIGMgKz0gcGFkU3RhcnQoby5jLmRheSk7XG4gIH0gZWxzZSB7XG4gICAgYyArPSBwYWRTdGFydChvLmMubW9udGgpO1xuICAgIGMgKz0gcGFkU3RhcnQoby5jLmRheSk7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG5cbmZ1bmN0aW9uIHRvSVNPVGltZShcbiAgbyxcbiAgZXh0ZW5kZWQsXG4gIHN1cHByZXNzU2Vjb25kcyxcbiAgc3VwcHJlc3NNaWxsaXNlY29uZHMsXG4gIGluY2x1ZGVPZmZzZXQsXG4gIGV4dGVuZGVkWm9uZVxuKSB7XG4gIGxldCBjID0gcGFkU3RhcnQoby5jLmhvdXIpO1xuICBpZiAoZXh0ZW5kZWQpIHtcbiAgICBjICs9IFwiOlwiO1xuICAgIGMgKz0gcGFkU3RhcnQoby5jLm1pbnV0ZSk7XG4gICAgaWYgKG8uYy5zZWNvbmQgIT09IDAgfHwgIXN1cHByZXNzU2Vjb25kcykge1xuICAgICAgYyArPSBcIjpcIjtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgYyArPSBwYWRTdGFydChvLmMubWludXRlKTtcbiAgfVxuXG4gIGlmIChvLmMuc2Vjb25kICE9PSAwIHx8ICFzdXBwcmVzc1NlY29uZHMpIHtcbiAgICBjICs9IHBhZFN0YXJ0KG8uYy5zZWNvbmQpO1xuXG4gICAgaWYgKG8uYy5taWxsaXNlY29uZCAhPT0gMCB8fCAhc3VwcHJlc3NNaWxsaXNlY29uZHMpIHtcbiAgICAgIGMgKz0gXCIuXCI7XG4gICAgICBjICs9IHBhZFN0YXJ0KG8uYy5taWxsaXNlY29uZCwgMyk7XG4gICAgfVxuICB9XG5cbiAgaWYgKGluY2x1ZGVPZmZzZXQpIHtcbiAgICBpZiAoby5pc09mZnNldEZpeGVkICYmIG8ub2Zmc2V0ID09PSAwICYmICFleHRlbmRlZFpvbmUpIHtcbiAgICAgIGMgKz0gXCJaXCI7XG4gICAgfSBlbHNlIGlmIChvLm8gPCAwKSB7XG4gICAgICBjICs9IFwiLVwiO1xuICAgICAgYyArPSBwYWRTdGFydChNYXRoLnRydW5jKC1vLm8gLyA2MCkpO1xuICAgICAgYyArPSBcIjpcIjtcbiAgICAgIGMgKz0gcGFkU3RhcnQoTWF0aC50cnVuYygtby5vICUgNjApKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYyArPSBcIitcIjtcbiAgICAgIGMgKz0gcGFkU3RhcnQoTWF0aC50cnVuYyhvLm8gLyA2MCkpO1xuICAgICAgYyArPSBcIjpcIjtcbiAgICAgIGMgKz0gcGFkU3RhcnQoTWF0aC50cnVuYyhvLm8gJSA2MCkpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChleHRlbmRlZFpvbmUpIHtcbiAgICBjICs9IFwiW1wiICsgby56b25lLmlhbmFOYW1lICsgXCJdXCI7XG4gIH1cbiAgcmV0dXJuIGM7XG59XG5cbi8vIGRlZmF1bHRzIGZvciB1bnNwZWNpZmllZCB1bml0cyBpbiB0aGUgc3VwcG9ydGVkIGNhbGVuZGFyc1xuY29uc3QgZGVmYXVsdFVuaXRWYWx1ZXMgPSB7XG4gICAgbW9udGg6IDEsXG4gICAgZGF5OiAxLFxuICAgIGhvdXI6IDAsXG4gICAgbWludXRlOiAwLFxuICAgIHNlY29uZDogMCxcbiAgICBtaWxsaXNlY29uZDogMCxcbiAgfSxcbiAgZGVmYXVsdFdlZWtVbml0VmFsdWVzID0ge1xuICAgIHdlZWtOdW1iZXI6IDEsXG4gICAgd2Vla2RheTogMSxcbiAgICBob3VyOiAwLFxuICAgIG1pbnV0ZTogMCxcbiAgICBzZWNvbmQ6IDAsXG4gICAgbWlsbGlzZWNvbmQ6IDAsXG4gIH0sXG4gIGRlZmF1bHRPcmRpbmFsVW5pdFZhbHVlcyA9IHtcbiAgICBvcmRpbmFsOiAxLFxuICAgIGhvdXI6IDAsXG4gICAgbWludXRlOiAwLFxuICAgIHNlY29uZDogMCxcbiAgICBtaWxsaXNlY29uZDogMCxcbiAgfTtcblxuLy8gVW5pdHMgaW4gdGhlIHN1cHBvcnRlZCBjYWxlbmRhcnMsIHNvcnRlZCBieSBiaWduZXNzXG5jb25zdCBvcmRlcmVkVW5pdHMgPSBbXCJ5ZWFyXCIsIFwibW9udGhcIiwgXCJkYXlcIiwgXCJob3VyXCIsIFwibWludXRlXCIsIFwic2Vjb25kXCIsIFwibWlsbGlzZWNvbmRcIl0sXG4gIG9yZGVyZWRXZWVrVW5pdHMgPSBbXG4gICAgXCJ3ZWVrWWVhclwiLFxuICAgIFwid2Vla051bWJlclwiLFxuICAgIFwid2Vla2RheVwiLFxuICAgIFwiaG91clwiLFxuICAgIFwibWludXRlXCIsXG4gICAgXCJzZWNvbmRcIixcbiAgICBcIm1pbGxpc2Vjb25kXCIsXG4gIF0sXG4gIG9yZGVyZWRPcmRpbmFsVW5pdHMgPSBbXCJ5ZWFyXCIsIFwib3JkaW5hbFwiLCBcImhvdXJcIiwgXCJtaW51dGVcIiwgXCJzZWNvbmRcIiwgXCJtaWxsaXNlY29uZFwiXTtcblxuLy8gc3RhbmRhcmRpemUgY2FzZSBhbmQgcGx1cmFsaXR5IGluIHVuaXRzXG5mdW5jdGlvbiBub3JtYWxpemVVbml0KHVuaXQpIHtcbiAgY29uc3Qgbm9ybWFsaXplZCA9IHtcbiAgICB5ZWFyOiBcInllYXJcIixcbiAgICB5ZWFyczogXCJ5ZWFyXCIsXG4gICAgbW9udGg6IFwibW9udGhcIixcbiAgICBtb250aHM6IFwibW9udGhcIixcbiAgICBkYXk6IFwiZGF5XCIsXG4gICAgZGF5czogXCJkYXlcIixcbiAgICBob3VyOiBcImhvdXJcIixcbiAgICBob3VyczogXCJob3VyXCIsXG4gICAgbWludXRlOiBcIm1pbnV0ZVwiLFxuICAgIG1pbnV0ZXM6IFwibWludXRlXCIsXG4gICAgcXVhcnRlcjogXCJxdWFydGVyXCIsXG4gICAgcXVhcnRlcnM6IFwicXVhcnRlclwiLFxuICAgIHNlY29uZDogXCJzZWNvbmRcIixcbiAgICBzZWNvbmRzOiBcInNlY29uZFwiLFxuICAgIG1pbGxpc2Vjb25kOiBcIm1pbGxpc2Vjb25kXCIsXG4gICAgbWlsbGlzZWNvbmRzOiBcIm1pbGxpc2Vjb25kXCIsXG4gICAgd2Vla2RheTogXCJ3ZWVrZGF5XCIsXG4gICAgd2Vla2RheXM6IFwid2Vla2RheVwiLFxuICAgIHdlZWtudW1iZXI6IFwid2Vla051bWJlclwiLFxuICAgIHdlZWtzbnVtYmVyOiBcIndlZWtOdW1iZXJcIixcbiAgICB3ZWVrbnVtYmVyczogXCJ3ZWVrTnVtYmVyXCIsXG4gICAgd2Vla3llYXI6IFwid2Vla1llYXJcIixcbiAgICB3ZWVreWVhcnM6IFwid2Vla1llYXJcIixcbiAgICBvcmRpbmFsOiBcIm9yZGluYWxcIixcbiAgfVt1bml0LnRvTG93ZXJDYXNlKCldO1xuXG4gIGlmICghbm9ybWFsaXplZCkgdGhyb3cgbmV3IEludmFsaWRVbml0RXJyb3IodW5pdCk7XG5cbiAgcmV0dXJuIG5vcm1hbGl6ZWQ7XG59XG5cbi8vIHRoaXMgaXMgYSBkdW1iZWQgZG93biB2ZXJzaW9uIG9mIGZyb21PYmplY3QoKSB0aGF0IHJ1bnMgYWJvdXQgNjAlIGZhc3RlclxuLy8gYnV0IGRvZXNuJ3QgZG8gYW55IHZhbGlkYXRpb24sIG1ha2VzIGEgYnVuY2ggb2YgYXNzdW1wdGlvbnMgYWJvdXQgd2hhdCB1bml0c1xuLy8gYXJlIHByZXNlbnQsIGFuZCBzbyBvbi5cbmZ1bmN0aW9uIHF1aWNrRFQob2JqLCBvcHRzKSB7XG4gIGNvbnN0IHpvbmUgPSBub3JtYWxpemVab25lKG9wdHMuem9uZSwgU2V0dGluZ3MuZGVmYXVsdFpvbmUpLFxuICAgIGxvYyA9IExvY2FsZS5mcm9tT2JqZWN0KG9wdHMpLFxuICAgIHRzTm93ID0gU2V0dGluZ3Mubm93KCk7XG5cbiAgbGV0IHRzLCBvO1xuXG4gIC8vIGFzc3VtZSB3ZSBoYXZlIHRoZSBoaWdoZXItb3JkZXIgdW5pdHNcbiAgaWYgKCFpc1VuZGVmaW5lZChvYmoueWVhcikpIHtcbiAgICBmb3IgKGNvbnN0IHUgb2Ygb3JkZXJlZFVuaXRzKSB7XG4gICAgICBpZiAoaXNVbmRlZmluZWQob2JqW3VdKSkge1xuICAgICAgICBvYmpbdV0gPSBkZWZhdWx0VW5pdFZhbHVlc1t1XTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBpbnZhbGlkID0gaGFzSW52YWxpZEdyZWdvcmlhbkRhdGEob2JqKSB8fCBoYXNJbnZhbGlkVGltZURhdGEob2JqKTtcbiAgICBpZiAoaW52YWxpZCkge1xuICAgICAgcmV0dXJuIERhdGVUaW1lLmludmFsaWQoaW52YWxpZCk7XG4gICAgfVxuXG4gICAgY29uc3Qgb2Zmc2V0UHJvdmlzID0gem9uZS5vZmZzZXQodHNOb3cpO1xuICAgIFt0cywgb10gPSBvYmpUb1RTKG9iaiwgb2Zmc2V0UHJvdmlzLCB6b25lKTtcbiAgfSBlbHNlIHtcbiAgICB0cyA9IHRzTm93O1xuICB9XG5cbiAgcmV0dXJuIG5ldyBEYXRlVGltZSh7IHRzLCB6b25lLCBsb2MsIG8gfSk7XG59XG5cbmZ1bmN0aW9uIGRpZmZSZWxhdGl2ZShzdGFydCwgZW5kLCBvcHRzKSB7XG4gIGNvbnN0IHJvdW5kID0gaXNVbmRlZmluZWQob3B0cy5yb3VuZCkgPyB0cnVlIDogb3B0cy5yb3VuZCxcbiAgICBmb3JtYXQgPSAoYywgdW5pdCkgPT4ge1xuICAgICAgYyA9IHJvdW5kVG8oYywgcm91bmQgfHwgb3B0cy5jYWxlbmRhcnkgPyAwIDogMiwgdHJ1ZSk7XG4gICAgICBjb25zdCBmb3JtYXR0ZXIgPSBlbmQubG9jLmNsb25lKG9wdHMpLnJlbEZvcm1hdHRlcihvcHRzKTtcbiAgICAgIHJldHVybiBmb3JtYXR0ZXIuZm9ybWF0KGMsIHVuaXQpO1xuICAgIH0sXG4gICAgZGlmZmVyID0gKHVuaXQpID0+IHtcbiAgICAgIGlmIChvcHRzLmNhbGVuZGFyeSkge1xuICAgICAgICBpZiAoIWVuZC5oYXNTYW1lKHN0YXJ0LCB1bml0KSkge1xuICAgICAgICAgIHJldHVybiBlbmQuc3RhcnRPZih1bml0KS5kaWZmKHN0YXJ0LnN0YXJ0T2YodW5pdCksIHVuaXQpLmdldCh1bml0KTtcbiAgICAgICAgfSBlbHNlIHJldHVybiAwO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGVuZC5kaWZmKHN0YXJ0LCB1bml0KS5nZXQodW5pdCk7XG4gICAgICB9XG4gICAgfTtcblxuICBpZiAob3B0cy51bml0KSB7XG4gICAgcmV0dXJuIGZvcm1hdChkaWZmZXIob3B0cy51bml0KSwgb3B0cy51bml0KTtcbiAgfVxuXG4gIGZvciAoY29uc3QgdW5pdCBvZiBvcHRzLnVuaXRzKSB7XG4gICAgY29uc3QgY291bnQgPSBkaWZmZXIodW5pdCk7XG4gICAgaWYgKE1hdGguYWJzKGNvdW50KSA+PSAxKSB7XG4gICAgICByZXR1cm4gZm9ybWF0KGNvdW50LCB1bml0KTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZvcm1hdChzdGFydCA+IGVuZCA/IC0wIDogMCwgb3B0cy51bml0c1tvcHRzLnVuaXRzLmxlbmd0aCAtIDFdKTtcbn1cblxuZnVuY3Rpb24gbGFzdE9wdHMoYXJnTGlzdCkge1xuICBsZXQgb3B0cyA9IHt9LFxuICAgIGFyZ3M7XG4gIGlmIChhcmdMaXN0Lmxlbmd0aCA+IDAgJiYgdHlwZW9mIGFyZ0xpc3RbYXJnTGlzdC5sZW5ndGggLSAxXSA9PT0gXCJvYmplY3RcIikge1xuICAgIG9wdHMgPSBhcmdMaXN0W2FyZ0xpc3QubGVuZ3RoIC0gMV07XG4gICAgYXJncyA9IEFycmF5LmZyb20oYXJnTGlzdCkuc2xpY2UoMCwgYXJnTGlzdC5sZW5ndGggLSAxKTtcbiAgfSBlbHNlIHtcbiAgICBhcmdzID0gQXJyYXkuZnJvbShhcmdMaXN0KTtcbiAgfVxuICByZXR1cm4gW29wdHMsIGFyZ3NdO1xufVxuXG4vKipcbiAqIEEgRGF0ZVRpbWUgaXMgYW4gaW1tdXRhYmxlIGRhdGEgc3RydWN0dXJlIHJlcHJlc2VudGluZyBhIHNwZWNpZmljIGRhdGUgYW5kIHRpbWUgYW5kIGFjY29tcGFueWluZyBtZXRob2RzLiBJdCBjb250YWlucyBjbGFzcyBhbmQgaW5zdGFuY2UgbWV0aG9kcyBmb3IgY3JlYXRpbmcsIHBhcnNpbmcsIGludGVycm9nYXRpbmcsIHRyYW5zZm9ybWluZywgYW5kIGZvcm1hdHRpbmcgdGhlbS5cbiAqXG4gKiBBIERhdGVUaW1lIGNvbXByaXNlcyBvZjpcbiAqICogQSB0aW1lc3RhbXAuIEVhY2ggRGF0ZVRpbWUgaW5zdGFuY2UgcmVmZXJzIHRvIGEgc3BlY2lmaWMgbWlsbGlzZWNvbmQgb2YgdGhlIFVuaXggZXBvY2guXG4gKiAqIEEgdGltZSB6b25lLiBFYWNoIGluc3RhbmNlIGlzIGNvbnNpZGVyZWQgaW4gdGhlIGNvbnRleHQgb2YgYSBzcGVjaWZpYyB6b25lIChieSBkZWZhdWx0IHRoZSBsb2NhbCBzeXN0ZW0ncyB6b25lKS5cbiAqICogQ29uZmlndXJhdGlvbiBwcm9wZXJ0aWVzIHRoYXQgZWZmZWN0IGhvdyBvdXRwdXQgc3RyaW5ncyBhcmUgZm9ybWF0dGVkLCBzdWNoIGFzIGBsb2NhbGVgLCBgbnVtYmVyaW5nU3lzdGVtYCwgYW5kIGBvdXRwdXRDYWxlbmRhcmAuXG4gKlxuICogSGVyZSBpcyBhIGJyaWVmIG92ZXJ2aWV3IG9mIHRoZSBtb3N0IGNvbW1vbmx5IHVzZWQgZnVuY3Rpb25hbGl0eSBpdCBwcm92aWRlczpcbiAqXG4gKiAqICoqQ3JlYXRpb24qKjogVG8gY3JlYXRlIGEgRGF0ZVRpbWUgZnJvbSBpdHMgY29tcG9uZW50cywgdXNlIG9uZSBvZiBpdHMgZmFjdG9yeSBjbGFzcyBtZXRob2RzOiB7QGxpbmsgRGF0ZVRpbWUubG9jYWx9LCB7QGxpbmsgRGF0ZVRpbWUudXRjfSwgYW5kIChtb3N0IGZsZXhpYmx5KSB7QGxpbmsgRGF0ZVRpbWUuZnJvbU9iamVjdH0uIFRvIGNyZWF0ZSBvbmUgZnJvbSBhIHN0YW5kYXJkIHN0cmluZyBmb3JtYXQsIHVzZSB7QGxpbmsgRGF0ZVRpbWUuZnJvbUlTT30sIHtAbGluayBEYXRlVGltZS5mcm9tSFRUUH0sIGFuZCB7QGxpbmsgRGF0ZVRpbWUuZnJvbVJGQzI4MjJ9LiBUbyBjcmVhdGUgb25lIGZyb20gYSBjdXN0b20gc3RyaW5nIGZvcm1hdCwgdXNlIHtAbGluayBEYXRlVGltZS5mcm9tRm9ybWF0fS4gVG8gY3JlYXRlIG9uZSBmcm9tIGEgbmF0aXZlIEpTIGRhdGUsIHVzZSB7QGxpbmsgRGF0ZVRpbWUuZnJvbUpTRGF0ZX0uXG4gKiAqICoqR3JlZ29yaWFuIGNhbGVuZGFyIGFuZCB0aW1lKio6IFRvIGV4YW1pbmUgdGhlIEdyZWdvcmlhbiBwcm9wZXJ0aWVzIG9mIGEgRGF0ZVRpbWUgaW5kaXZpZHVhbGx5IChpLmUgYXMgb3Bwb3NlZCB0byBjb2xsZWN0aXZlbHkgdGhyb3VnaCB7QGxpbmsgRGF0ZVRpbWUjdG9PYmplY3R9KSwgdXNlIHRoZSB7QGxpbmsgRGF0ZVRpbWUjeWVhcn0sIHtAbGluayBEYXRlVGltZSNtb250aH0sXG4gKiB7QGxpbmsgRGF0ZVRpbWUjZGF5fSwge0BsaW5rIERhdGVUaW1lI2hvdXJ9LCB7QGxpbmsgRGF0ZVRpbWUjbWludXRlfSwge0BsaW5rIERhdGVUaW1lI3NlY29uZH0sIHtAbGluayBEYXRlVGltZSNtaWxsaXNlY29uZH0gYWNjZXNzb3JzLlxuICogKiAqKldlZWsgY2FsZW5kYXIqKjogRm9yIElTTyB3ZWVrIGNhbGVuZGFyIGF0dHJpYnV0ZXMsIHNlZSB0aGUge0BsaW5rIERhdGVUaW1lI3dlZWtZZWFyfSwge0BsaW5rIERhdGVUaW1lI3dlZWtOdW1iZXJ9LCBhbmQge0BsaW5rIERhdGVUaW1lI3dlZWtkYXl9IGFjY2Vzc29ycy5cbiAqICogKipDb25maWd1cmF0aW9uKiogU2VlIHRoZSB7QGxpbmsgRGF0ZVRpbWUjbG9jYWxlfSBhbmQge0BsaW5rIERhdGVUaW1lI251bWJlcmluZ1N5c3RlbX0gYWNjZXNzb3JzLlxuICogKiAqKlRyYW5zZm9ybWF0aW9uKio6IFRvIHRyYW5zZm9ybSB0aGUgRGF0ZVRpbWUgaW50byBvdGhlciBEYXRlVGltZXMsIHVzZSB7QGxpbmsgRGF0ZVRpbWUjc2V0fSwge0BsaW5rIERhdGVUaW1lI3JlY29uZmlndXJlfSwge0BsaW5rIERhdGVUaW1lI3NldFpvbmV9LCB7QGxpbmsgRGF0ZVRpbWUjc2V0TG9jYWxlfSwge0BsaW5rIERhdGVUaW1lLnBsdXN9LCB7QGxpbmsgRGF0ZVRpbWUjbWludXN9LCB7QGxpbmsgRGF0ZVRpbWUjZW5kT2Z9LCB7QGxpbmsgRGF0ZVRpbWUjc3RhcnRPZn0sIHtAbGluayBEYXRlVGltZSN0b1VUQ30sIGFuZCB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbH0uXG4gKiAqICoqT3V0cHV0Kio6IFRvIGNvbnZlcnQgdGhlIERhdGVUaW1lIHRvIG90aGVyIHJlcHJlc2VudGF0aW9ucywgdXNlIHRoZSB7QGxpbmsgRGF0ZVRpbWUjdG9SZWxhdGl2ZX0sIHtAbGluayBEYXRlVGltZSN0b1JlbGF0aXZlQ2FsZW5kYXJ9LCB7QGxpbmsgRGF0ZVRpbWUjdG9KU09OfSwge0BsaW5rIERhdGVUaW1lI3RvSVNPfSwge0BsaW5rIERhdGVUaW1lI3RvSFRUUH0sIHtAbGluayBEYXRlVGltZSN0b09iamVjdH0sIHtAbGluayBEYXRlVGltZSN0b1JGQzI4MjJ9LCB7QGxpbmsgRGF0ZVRpbWUjdG9TdHJpbmd9LCB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbGVTdHJpbmd9LCB7QGxpbmsgRGF0ZVRpbWUjdG9Gb3JtYXR9LCB7QGxpbmsgRGF0ZVRpbWUjdG9NaWxsaXN9IGFuZCB7QGxpbmsgRGF0ZVRpbWUjdG9KU0RhdGV9LlxuICpcbiAqIFRoZXJlJ3MgcGxlbnR5IG90aGVycyBkb2N1bWVudGVkIGJlbG93LiBJbiBhZGRpdGlvbiwgZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gc3VidGxlciB0b3BpY3MgbGlrZSBpbnRlcm5hdGlvbmFsaXphdGlvbiwgdGltZSB6b25lcywgYWx0ZXJuYXRpdmUgY2FsZW5kYXJzLCB2YWxpZGl0eSwgYW5kIHNvIG9uLCBzZWUgdGhlIGV4dGVybmFsIGRvY3VtZW50YXRpb24uXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERhdGVUaW1lIHtcbiAgLyoqXG4gICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgKi9cbiAgY29uc3RydWN0b3IoY29uZmlnKSB7XG4gICAgY29uc3Qgem9uZSA9IGNvbmZpZy56b25lIHx8IFNldHRpbmdzLmRlZmF1bHRab25lO1xuXG4gICAgbGV0IGludmFsaWQgPVxuICAgICAgY29uZmlnLmludmFsaWQgfHxcbiAgICAgIChOdW1iZXIuaXNOYU4oY29uZmlnLnRzKSA/IG5ldyBJbnZhbGlkKFwiaW52YWxpZCBpbnB1dFwiKSA6IG51bGwpIHx8XG4gICAgICAoIXpvbmUuaXNWYWxpZCA/IHVuc3VwcG9ydGVkWm9uZSh6b25lKSA6IG51bGwpO1xuICAgIC8qKlxuICAgICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMudHMgPSBpc1VuZGVmaW5lZChjb25maWcudHMpID8gU2V0dGluZ3Mubm93KCkgOiBjb25maWcudHM7XG5cbiAgICBsZXQgYyA9IG51bGwsXG4gICAgICBvID0gbnVsbDtcbiAgICBpZiAoIWludmFsaWQpIHtcbiAgICAgIGNvbnN0IHVuY2hhbmdlZCA9IGNvbmZpZy5vbGQgJiYgY29uZmlnLm9sZC50cyA9PT0gdGhpcy50cyAmJiBjb25maWcub2xkLnpvbmUuZXF1YWxzKHpvbmUpO1xuXG4gICAgICBpZiAodW5jaGFuZ2VkKSB7XG4gICAgICAgIFtjLCBvXSA9IFtjb25maWcub2xkLmMsIGNvbmZpZy5vbGQub107XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBvdCA9IHpvbmUub2Zmc2V0KHRoaXMudHMpO1xuICAgICAgICBjID0gdHNUb09iaih0aGlzLnRzLCBvdCk7XG4gICAgICAgIGludmFsaWQgPSBOdW1iZXIuaXNOYU4oYy55ZWFyKSA/IG5ldyBJbnZhbGlkKFwiaW52YWxpZCBpbnB1dFwiKSA6IG51bGw7XG4gICAgICAgIGMgPSBpbnZhbGlkID8gbnVsbCA6IGM7XG4gICAgICAgIG8gPSBpbnZhbGlkID8gbnVsbCA6IG90O1xuICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMuX3pvbmUgPSB6b25lO1xuICAgIC8qKlxuICAgICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMubG9jID0gY29uZmlnLmxvYyB8fCBMb2NhbGUuY3JlYXRlKCk7XG4gICAgLyoqXG4gICAgICogQGFjY2VzcyBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5pbnZhbGlkID0gaW52YWxpZDtcbiAgICAvKipcbiAgICAgKiBAYWNjZXNzIHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLndlZWtEYXRhID0gbnVsbDtcbiAgICAvKipcbiAgICAgKiBAYWNjZXNzIHByaXZhdGVcbiAgICAgKi9cbiAgICB0aGlzLmMgPSBjO1xuICAgIC8qKlxuICAgICAqIEBhY2Nlc3MgcHJpdmF0ZVxuICAgICAqL1xuICAgIHRoaXMubyA9IG87XG4gICAgLyoqXG4gICAgICogQGFjY2VzcyBwcml2YXRlXG4gICAgICovXG4gICAgdGhpcy5pc0x1eG9uRGF0ZVRpbWUgPSB0cnVlO1xuICB9XG5cbiAgLy8gQ09OU1RSVUNUXG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIERhdGVUaW1lIGZvciB0aGUgY3VycmVudCBpbnN0YW50LCBpbiB0aGUgc3lzdGVtJ3MgdGltZSB6b25lLlxuICAgKlxuICAgKiBVc2UgU2V0dGluZ3MgdG8gb3ZlcnJpZGUgdGhlc2UgZGVmYXVsdCB2YWx1ZXMgaWYgbmVlZGVkLlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS50b0lTTygpIC8vfj4gbm93IGluIHRoZSBJU08gZm9ybWF0XG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc3RhdGljIG5vdygpIHtcbiAgICByZXR1cm4gbmV3IERhdGVUaW1lKHt9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBsb2NhbCBEYXRlVGltZVxuICAgKiBAcGFyYW0ge251bWJlcn0gW3llYXJdIC0gVGhlIGNhbGVuZGFyIHllYXIuIElmIG9taXR0ZWQgKGFzIGluLCBjYWxsIGBsb2NhbCgpYCB3aXRoIG5vIGFyZ3VtZW50cyksIHRoZSBjdXJyZW50IHRpbWUgd2lsbCBiZSB1c2VkXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbbW9udGg9MV0gLSBUaGUgbW9udGgsIDEtaW5kZXhlZFxuICAgKiBAcGFyYW0ge251bWJlcn0gW2RheT0xXSAtIFRoZSBkYXkgb2YgdGhlIG1vbnRoLCAxLWluZGV4ZWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtob3VyPTBdIC0gVGhlIGhvdXIgb2YgdGhlIGRheSwgaW4gMjQtaG91ciB0aW1lXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbbWludXRlPTBdIC0gVGhlIG1pbnV0ZSBvZiB0aGUgaG91ciwgbWVhbmluZyBhIG51bWJlciBiZXR3ZWVuIDAgYW5kIDU5XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbc2Vjb25kPTBdIC0gVGhlIHNlY29uZCBvZiB0aGUgbWludXRlLCBtZWFuaW5nIGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgNTlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFttaWxsaXNlY29uZD0wXSAtIFRoZSBtaWxsaXNlY29uZCBvZiB0aGUgc2Vjb25kLCBtZWFuaW5nIGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgOTk5XG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9+PiBub3dcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoeyB6b25lOiBcIkFtZXJpY2EvTmV3X1lvcmtcIiB9KSAgICAgIC8vfj4gbm93LCBpbiBVUyBlYXN0IGNvYXN0IHRpbWVcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL34+IDIwMTctMDEtMDFUMDA6MDA6MDBcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgMykgICAgICAgICAgICAgICAgICAgICAgICAgICAvL34+IDIwMTctMDMtMDFUMDA6MDA6MDBcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgMywgMTIsIHsgbG9jYWxlOiBcImZyXCIgfSkgICAgIC8vfj4gMjAxNy0wMy0xMlQwMDowMDowMCwgd2l0aCBhIEZyZW5jaCBsb2NhbGVcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgMywgMTIsIDUpICAgICAgICAgICAgICAgICAgICAvL34+IDIwMTctMDMtMTJUMDU6MDA6MDBcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgMywgMTIsIDUsIHsgem9uZTogXCJ1dGNcIiB9KSAgIC8vfj4gMjAxNy0wMy0xMlQwNTowMDowMCwgaW4gVVRDXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTcsIDMsIDEyLCA1LCA0NSkgICAgICAgICAgICAgICAgLy9+PiAyMDE3LTAzLTEyVDA1OjQ1OjAwXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTcsIDMsIDEyLCA1LCA0NSwgMTApICAgICAgICAgICAgLy9+PiAyMDE3LTAzLTEyVDA1OjQ1OjEwXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTcsIDMsIDEyLCA1LCA0NSwgMTAsIDc2NSkgICAgICAgLy9+PiAyMDE3LTAzLTEyVDA1OjQ1OjEwLjc2NVxuICAgKiBAcmV0dXJuIHtEYXRlVGltZX1cbiAgICovXG4gIHN0YXRpYyBsb2NhbCgpIHtcbiAgICBjb25zdCBbb3B0cywgYXJnc10gPSBsYXN0T3B0cyhhcmd1bWVudHMpLFxuICAgICAgW3llYXIsIG1vbnRoLCBkYXksIGhvdXIsIG1pbnV0ZSwgc2Vjb25kLCBtaWxsaXNlY29uZF0gPSBhcmdzO1xuICAgIHJldHVybiBxdWlja0RUKHsgeWVhciwgbW9udGgsIGRheSwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1pbGxpc2Vjb25kIH0sIG9wdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIERhdGVUaW1lIGluIFVUQ1xuICAgKiBAcGFyYW0ge251bWJlcn0gW3llYXJdIC0gVGhlIGNhbGVuZGFyIHllYXIuIElmIG9taXR0ZWQgKGFzIGluLCBjYWxsIGB1dGMoKWAgd2l0aCBubyBhcmd1bWVudHMpLCB0aGUgY3VycmVudCB0aW1lIHdpbGwgYmUgdXNlZFxuICAgKiBAcGFyYW0ge251bWJlcn0gW21vbnRoPTFdIC0gVGhlIG1vbnRoLCAxLWluZGV4ZWRcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtkYXk9MV0gLSBUaGUgZGF5IG9mIHRoZSBtb250aFxuICAgKiBAcGFyYW0ge251bWJlcn0gW2hvdXI9MF0gLSBUaGUgaG91ciBvZiB0aGUgZGF5LCBpbiAyNC1ob3VyIHRpbWVcbiAgICogQHBhcmFtIHtudW1iZXJ9IFttaW51dGU9MF0gLSBUaGUgbWludXRlIG9mIHRoZSBob3VyLCBtZWFuaW5nIGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgNTlcbiAgICogQHBhcmFtIHtudW1iZXJ9IFtzZWNvbmQ9MF0gLSBUaGUgc2Vjb25kIG9mIHRoZSBtaW51dGUsIG1lYW5pbmcgYSBudW1iZXIgYmV0d2VlbiAwIGFuZCA1OVxuICAgKiBAcGFyYW0ge251bWJlcn0gW21pbGxpc2Vjb25kPTBdIC0gVGhlIG1pbGxpc2Vjb25kIG9mIHRoZSBzZWNvbmQsIG1lYW5pbmcgYSBudW1iZXIgYmV0d2VlbiAwIGFuZCA5OTlcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBjb25maWd1cmF0aW9uIG9wdGlvbnMgZm9yIHRoZSBEYXRlVGltZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdGlvbnMubG9jYWxlXSAtIGEgbG9jYWxlIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy5vdXRwdXRDYWxlbmRhcl0gLSB0aGUgb3V0cHV0IGNhbGVuZGFyIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy5udW1iZXJpbmdTeXN0ZW1dIC0gdGhlIG51bWJlcmluZyBzeXN0ZW0gdG8gc2V0IG9uIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWUgaW5zdGFuY2VcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUudXRjKCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9+PiBub3dcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUudXRjKDIwMTcpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9+PiAyMDE3LTAxLTAxVDAwOjAwOjAwWlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoMjAxNywgMykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL34+IDIwMTctMDMtMDFUMDA6MDA6MDBaXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLnV0YygyMDE3LCAzLCAxMikgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vfj4gMjAxNy0wMy0xMlQwMDowMDowMFpcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUudXRjKDIwMTcsIDMsIDEyLCA1KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9+PiAyMDE3LTAzLTEyVDA1OjAwOjAwWlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoMjAxNywgMywgMTIsIDUsIDQ1KSAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL34+IDIwMTctMDMtMTJUMDU6NDU6MDBaXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLnV0YygyMDE3LCAzLCAxMiwgNSwgNDUsIHsgbG9jYWxlOiBcImZyXCIgfSkgICAgICAgICAgLy9+PiAyMDE3LTAzLTEyVDA1OjQ1OjAwWiB3aXRoIGEgRnJlbmNoIGxvY2FsZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoMjAxNywgMywgMTIsIDUsIDQ1LCAxMCkgICAgICAgICAgICAgICAgICAgICAgICAvL34+IDIwMTctMDMtMTJUMDU6NDU6MTBaXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLnV0YygyMDE3LCAzLCAxMiwgNSwgNDUsIDEwLCA3NjUsIHsgbG9jYWxlOiBcImZyXCIgfSkgLy9+PiAyMDE3LTAzLTEyVDA1OjQ1OjEwLjc2NVogd2l0aCBhIEZyZW5jaCBsb2NhbGVcbiAgICogQHJldHVybiB7RGF0ZVRpbWV9XG4gICAqL1xuICBzdGF0aWMgdXRjKCkge1xuICAgIGNvbnN0IFtvcHRzLCBhcmdzXSA9IGxhc3RPcHRzKGFyZ3VtZW50cyksXG4gICAgICBbeWVhciwgbW9udGgsIGRheSwgaG91ciwgbWludXRlLCBzZWNvbmQsIG1pbGxpc2Vjb25kXSA9IGFyZ3M7XG5cbiAgICBvcHRzLnpvbmUgPSBGaXhlZE9mZnNldFpvbmUudXRjSW5zdGFuY2U7XG4gICAgcmV0dXJuIHF1aWNrRFQoeyB5ZWFyLCBtb250aCwgZGF5LCBob3VyLCBtaW51dGUsIHNlY29uZCwgbWlsbGlzZWNvbmQgfSwgb3B0cyk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgRGF0ZVRpbWUgZnJvbSBhIEphdmFTY3JpcHQgRGF0ZSBvYmplY3QuIFVzZXMgdGhlIGRlZmF1bHQgem9uZS5cbiAgICogQHBhcmFtIHtEYXRlfSBkYXRlIC0gYSBKYXZhU2NyaXB0IERhdGUgb2JqZWN0XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gY29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB0aGUgRGF0ZVRpbWVcbiAgICogQHBhcmFtIHtzdHJpbmd8Wm9uZX0gW29wdGlvbnMuem9uZT0nbG9jYWwnXSAtIHRoZSB6b25lIHRvIHBsYWNlIHRoZSBEYXRlVGltZSBpbnRvXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc3RhdGljIGZyb21KU0RhdGUoZGF0ZSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgdHMgPSBpc0RhdGUoZGF0ZSkgPyBkYXRlLnZhbHVlT2YoKSA6IE5hTjtcbiAgICBpZiAoTnVtYmVyLmlzTmFOKHRzKSkge1xuICAgICAgcmV0dXJuIERhdGVUaW1lLmludmFsaWQoXCJpbnZhbGlkIGlucHV0XCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHpvbmVUb1VzZSA9IG5vcm1hbGl6ZVpvbmUob3B0aW9ucy56b25lLCBTZXR0aW5ncy5kZWZhdWx0Wm9uZSk7XG4gICAgaWYgKCF6b25lVG9Vc2UuaXNWYWxpZCkge1xuICAgICAgcmV0dXJuIERhdGVUaW1lLmludmFsaWQodW5zdXBwb3J0ZWRab25lKHpvbmVUb1VzZSkpO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgRGF0ZVRpbWUoe1xuICAgICAgdHM6IHRzLFxuICAgICAgem9uZTogem9uZVRvVXNlLFxuICAgICAgbG9jOiBMb2NhbGUuZnJvbU9iamVjdChvcHRpb25zKSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBEYXRlVGltZSBmcm9tIGEgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcyBzaW5jZSB0aGUgZXBvY2ggKG1lYW5pbmcgc2luY2UgMSBKYW51YXJ5IDE5NzAgMDA6MDA6MDAgVVRDKS4gVXNlcyB0aGUgZGVmYXVsdCB6b25lLlxuICAgKiBAcGFyYW0ge251bWJlcn0gbWlsbGlzZWNvbmRzIC0gYSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHNpbmNlIDE5NzAgVVRDXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gY29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB0aGUgRGF0ZVRpbWVcbiAgICogQHBhcmFtIHtzdHJpbmd8Wm9uZX0gW29wdGlvbnMuem9uZT0nbG9jYWwnXSAtIHRoZSB6b25lIHRvIHBsYWNlIHRoZSBEYXRlVGltZSBpbnRvXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy5sb2NhbGVdIC0gYSBsb2NhbGUgdG8gc2V0IG9uIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWUgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMub3V0cHV0Q2FsZW5kYXIgLSB0aGUgb3V0cHV0IGNhbGVuZGFyIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLm51bWJlcmluZ1N5c3RlbSAtIHRoZSBudW1iZXJpbmcgc3lzdGVtIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc3RhdGljIGZyb21NaWxsaXMobWlsbGlzZWNvbmRzLCBvcHRpb25zID0ge30pIHtcbiAgICBpZiAoIWlzTnVtYmVyKG1pbGxpc2Vjb25kcykpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgICAgYGZyb21NaWxsaXMgcmVxdWlyZXMgYSBudW1lcmljYWwgaW5wdXQsIGJ1dCByZWNlaXZlZCBhICR7dHlwZW9mIG1pbGxpc2Vjb25kc30gd2l0aCB2YWx1ZSAke21pbGxpc2Vjb25kc31gXG4gICAgICApO1xuICAgIH0gZWxzZSBpZiAobWlsbGlzZWNvbmRzIDwgLU1BWF9EQVRFIHx8IG1pbGxpc2Vjb25kcyA+IE1BWF9EQVRFKSB7XG4gICAgICAvLyB0aGlzIGlzbid0IHBlcmZlY3QgYmVjYXVzZSBiZWNhdXNlIHdlIGNhbiBzdGlsbCBlbmQgdXAgb3V0IG9mIHJhbmdlIGJlY2F1c2Ugb2YgYWRkaXRpb25hbCBzaGlmdGluZywgYnV0IGl0J3MgYSBzdGFydFxuICAgICAgcmV0dXJuIERhdGVUaW1lLmludmFsaWQoXCJUaW1lc3RhbXAgb3V0IG9mIHJhbmdlXCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbmV3IERhdGVUaW1lKHtcbiAgICAgICAgdHM6IG1pbGxpc2Vjb25kcyxcbiAgICAgICAgem9uZTogbm9ybWFsaXplWm9uZShvcHRpb25zLnpvbmUsIFNldHRpbmdzLmRlZmF1bHRab25lKSxcbiAgICAgICAgbG9jOiBMb2NhbGUuZnJvbU9iamVjdChvcHRpb25zKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBEYXRlVGltZSBmcm9tIGEgbnVtYmVyIG9mIHNlY29uZHMgc2luY2UgdGhlIGVwb2NoIChtZWFuaW5nIHNpbmNlIDEgSmFudWFyeSAxOTcwIDAwOjAwOjAwIFVUQykuIFVzZXMgdGhlIGRlZmF1bHQgem9uZS5cbiAgICogQHBhcmFtIHtudW1iZXJ9IHNlY29uZHMgLSBhIG51bWJlciBvZiBzZWNvbmRzIHNpbmNlIDE5NzAgVVRDXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gY29uZmlndXJhdGlvbiBvcHRpb25zIGZvciB0aGUgRGF0ZVRpbWVcbiAgICogQHBhcmFtIHtzdHJpbmd8Wm9uZX0gW29wdGlvbnMuem9uZT0nbG9jYWwnXSAtIHRoZSB6b25lIHRvIHBsYWNlIHRoZSBEYXRlVGltZSBpbnRvXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0aW9ucy5sb2NhbGVdIC0gYSBsb2NhbGUgdG8gc2V0IG9uIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWUgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMub3V0cHV0Q2FsZW5kYXIgLSB0aGUgb3V0cHV0IGNhbGVuZGFyIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLm51bWJlcmluZ1N5c3RlbSAtIHRoZSBudW1iZXJpbmcgc3lzdGVtIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc3RhdGljIGZyb21TZWNvbmRzKHNlY29uZHMsIG9wdGlvbnMgPSB7fSkge1xuICAgIGlmICghaXNOdW1iZXIoc2Vjb25kcykpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihcImZyb21TZWNvbmRzIHJlcXVpcmVzIGEgbnVtZXJpY2FsIGlucHV0XCIpO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbmV3IERhdGVUaW1lKHtcbiAgICAgICAgdHM6IHNlY29uZHMgKiAxMDAwLFxuICAgICAgICB6b25lOiBub3JtYWxpemVab25lKG9wdGlvbnMuem9uZSwgU2V0dGluZ3MuZGVmYXVsdFpvbmUpLFxuICAgICAgICBsb2M6IExvY2FsZS5mcm9tT2JqZWN0KG9wdGlvbnMpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIERhdGVUaW1lIGZyb20gYSBKYXZhU2NyaXB0IG9iamVjdCB3aXRoIGtleXMgbGlrZSAneWVhcicgYW5kICdob3VyJyB3aXRoIHJlYXNvbmFibGUgZGVmYXVsdHMuXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvYmogLSB0aGUgb2JqZWN0IHRvIGNyZWF0ZSB0aGUgRGF0ZVRpbWUgZnJvbVxuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLnllYXIgLSBhIHllYXIsIHN1Y2ggYXMgMTk4N1xuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLm1vbnRoIC0gYSBtb250aCwgMS0xMlxuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLmRheSAtIGEgZGF5IG9mIHRoZSBtb250aCwgMS0zMSwgZGVwZW5kaW5nIG9uIHRoZSBtb250aFxuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLm9yZGluYWwgLSBkYXkgb2YgdGhlIHllYXIsIDEtMzY1IG9yIDM2NlxuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLndlZWtZZWFyIC0gYW4gSVNPIHdlZWsgeWVhclxuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLndlZWtOdW1iZXIgLSBhbiBJU08gd2VlayBudW1iZXIsIGJldHdlZW4gMSBhbmQgNTIgb3IgNTMsIGRlcGVuZGluZyBvbiB0aGUgeWVhclxuICAgKiBAcGFyYW0ge251bWJlcn0gb2JqLndlZWtkYXkgLSBhbiBJU08gd2Vla2RheSwgMS03LCB3aGVyZSAxIGlzIE1vbmRheSBhbmQgNyBpcyBTdW5kYXlcbiAgICogQHBhcmFtIHtudW1iZXJ9IG9iai5ob3VyIC0gaG91ciBvZiB0aGUgZGF5LCAwLTIzXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvYmoubWludXRlIC0gbWludXRlIG9mIHRoZSBob3VyLCAwLTU5XG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvYmouc2Vjb25kIC0gc2Vjb25kIG9mIHRoZSBtaW51dGUsIDAtNTlcbiAgICogQHBhcmFtIHtudW1iZXJ9IG9iai5taWxsaXNlY29uZCAtIG1pbGxpc2Vjb25kIG9mIHRoZSBzZWNvbmQsIDAtOTk5XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9ucyBmb3IgY3JlYXRpbmcgdGhpcyBEYXRlVGltZVxuICAgKiBAcGFyYW0ge3N0cmluZ3xab25lfSBbb3B0cy56b25lPSdsb2NhbCddIC0gaW50ZXJwcmV0IHRoZSBudW1iZXJzIGluIHRoZSBjb250ZXh0IG9mIGEgcGFydGljdWxhciB6b25lLiBDYW4gdGFrZSBhbnkgdmFsdWUgdGFrZW4gYXMgdGhlIGZpcnN0IGFyZ3VtZW50IHRvIHNldFpvbmUoKVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubG9jYWxlPSdzeXN0ZW0ncyBsb2NhbGUnXSAtIGEgbG9jYWxlIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm91dHB1dENhbGVuZGFyIC0gdGhlIG91dHB1dCBjYWxlbmRhciB0byBzZXQgb24gdGhlIHJlc3VsdGluZyBEYXRlVGltZSBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5udW1iZXJpbmdTeXN0ZW0gLSB0aGUgbnVtYmVyaW5nIHN5c3RlbSB0byBzZXQgb24gdGhlIHJlc3VsdGluZyBEYXRlVGltZSBpbnN0YW5jZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tT2JqZWN0KHsgeWVhcjogMTk4MiwgbW9udGg6IDUsIGRheTogMjV9KS50b0lTT0RhdGUoKSAvLz0+ICcxOTgyLTA1LTI1J1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tT2JqZWN0KHsgeWVhcjogMTk4MiB9KS50b0lTT0RhdGUoKSAvLz0+ICcxOTgyLTAxLTAxJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tT2JqZWN0KHsgaG91cjogMTAsIG1pbnV0ZTogMjYsIHNlY29uZDogNiB9KSAvL34+IHRvZGF5IGF0IDEwOjI2OjA2XG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmZyb21PYmplY3QoeyBob3VyOiAxMCwgbWludXRlOiAyNiwgc2Vjb25kOiA2IH0sIHsgem9uZTogJ3V0YycgfSksXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmZyb21PYmplY3QoeyBob3VyOiAxMCwgbWludXRlOiAyNiwgc2Vjb25kOiA2IH0sIHsgem9uZTogJ2xvY2FsJyB9KVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tT2JqZWN0KHsgaG91cjogMTAsIG1pbnV0ZTogMjYsIHNlY29uZDogNiB9LCB7IHpvbmU6ICdBbWVyaWNhL05ld19Zb3JrJyB9KVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tT2JqZWN0KHsgd2Vla1llYXI6IDIwMTYsIHdlZWtOdW1iZXI6IDIsIHdlZWtkYXk6IDMgfSkudG9JU09EYXRlKCkgLy89PiAnMjAxNi0wMS0xMydcbiAgICogQHJldHVybiB7RGF0ZVRpbWV9XG4gICAqL1xuICBzdGF0aWMgZnJvbU9iamVjdChvYmosIG9wdHMgPSB7fSkge1xuICAgIG9iaiA9IG9iaiB8fCB7fTtcbiAgICBjb25zdCB6b25lVG9Vc2UgPSBub3JtYWxpemVab25lKG9wdHMuem9uZSwgU2V0dGluZ3MuZGVmYXVsdFpvbmUpO1xuICAgIGlmICghem9uZVRvVXNlLmlzVmFsaWQpIHtcbiAgICAgIHJldHVybiBEYXRlVGltZS5pbnZhbGlkKHVuc3VwcG9ydGVkWm9uZSh6b25lVG9Vc2UpKTtcbiAgICB9XG5cbiAgICBjb25zdCB0c05vdyA9IFNldHRpbmdzLm5vdygpLFxuICAgICAgb2Zmc2V0UHJvdmlzID0gIWlzVW5kZWZpbmVkKG9wdHMuc3BlY2lmaWNPZmZzZXQpXG4gICAgICAgID8gb3B0cy5zcGVjaWZpY09mZnNldFxuICAgICAgICA6IHpvbmVUb1VzZS5vZmZzZXQodHNOb3cpLFxuICAgICAgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZU9iamVjdChvYmosIG5vcm1hbGl6ZVVuaXQpLFxuICAgICAgY29udGFpbnNPcmRpbmFsID0gIWlzVW5kZWZpbmVkKG5vcm1hbGl6ZWQub3JkaW5hbCksXG4gICAgICBjb250YWluc0dyZWdvclllYXIgPSAhaXNVbmRlZmluZWQobm9ybWFsaXplZC55ZWFyKSxcbiAgICAgIGNvbnRhaW5zR3JlZ29yTUQgPSAhaXNVbmRlZmluZWQobm9ybWFsaXplZC5tb250aCkgfHwgIWlzVW5kZWZpbmVkKG5vcm1hbGl6ZWQuZGF5KSxcbiAgICAgIGNvbnRhaW5zR3JlZ29yID0gY29udGFpbnNHcmVnb3JZZWFyIHx8IGNvbnRhaW5zR3JlZ29yTUQsXG4gICAgICBkZWZpbml0ZVdlZWtEZWYgPSBub3JtYWxpemVkLndlZWtZZWFyIHx8IG5vcm1hbGl6ZWQud2Vla051bWJlcixcbiAgICAgIGxvYyA9IExvY2FsZS5mcm9tT2JqZWN0KG9wdHMpO1xuXG4gICAgLy8gY2FzZXM6XG4gICAgLy8ganVzdCBhIHdlZWtkYXkgLT4gdGhpcyB3ZWVrJ3MgaW5zdGFuY2Ugb2YgdGhhdCB3ZWVrZGF5LCBubyB3b3JyaWVzXG4gICAgLy8gKGdyZWdvcmlhbiBkYXRhIG9yIG9yZGluYWwpICsgKHdlZWtZZWFyIG9yIHdlZWtOdW1iZXIpIC0+IGVycm9yXG4gICAgLy8gKGdyZWdvcmlhbiBtb250aCBvciBkYXkpICsgb3JkaW5hbCAtPiBlcnJvclxuICAgIC8vIG90aGVyd2lzZSBqdXN0IHVzZSB3ZWVrcyBvciBvcmRpbmFscyBvciBncmVnb3JpYW4sIGRlcGVuZGluZyBvbiB3aGF0J3Mgc3BlY2lmaWVkXG5cbiAgICBpZiAoKGNvbnRhaW5zR3JlZ29yIHx8IGNvbnRhaW5zT3JkaW5hbCkgJiYgZGVmaW5pdGVXZWVrRGVmKSB7XG4gICAgICB0aHJvdyBuZXcgQ29uZmxpY3RpbmdTcGVjaWZpY2F0aW9uRXJyb3IoXG4gICAgICAgIFwiQ2FuJ3QgbWl4IHdlZWtZZWFyL3dlZWtOdW1iZXIgdW5pdHMgd2l0aCB5ZWFyL21vbnRoL2RheSBvciBvcmRpbmFsc1wiXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChjb250YWluc0dyZWdvck1EICYmIGNvbnRhaW5zT3JkaW5hbCkge1xuICAgICAgdGhyb3cgbmV3IENvbmZsaWN0aW5nU3BlY2lmaWNhdGlvbkVycm9yKFwiQ2FuJ3QgbWl4IG9yZGluYWwgZGF0ZXMgd2l0aCBtb250aC9kYXlcIik7XG4gICAgfVxuXG4gICAgY29uc3QgdXNlV2Vla0RhdGEgPSBkZWZpbml0ZVdlZWtEZWYgfHwgKG5vcm1hbGl6ZWQud2Vla2RheSAmJiAhY29udGFpbnNHcmVnb3IpO1xuXG4gICAgLy8gY29uZmlndXJlIG91cnNlbHZlcyB0byBkZWFsIHdpdGggZ3JlZ29yaWFuIGRhdGVzIG9yIHdlZWsgc3R1ZmZcbiAgICBsZXQgdW5pdHMsXG4gICAgICBkZWZhdWx0VmFsdWVzLFxuICAgICAgb2JqTm93ID0gdHNUb09iaih0c05vdywgb2Zmc2V0UHJvdmlzKTtcbiAgICBpZiAodXNlV2Vla0RhdGEpIHtcbiAgICAgIHVuaXRzID0gb3JkZXJlZFdlZWtVbml0cztcbiAgICAgIGRlZmF1bHRWYWx1ZXMgPSBkZWZhdWx0V2Vla1VuaXRWYWx1ZXM7XG4gICAgICBvYmpOb3cgPSBncmVnb3JpYW5Ub1dlZWsob2JqTm93KTtcbiAgICB9IGVsc2UgaWYgKGNvbnRhaW5zT3JkaW5hbCkge1xuICAgICAgdW5pdHMgPSBvcmRlcmVkT3JkaW5hbFVuaXRzO1xuICAgICAgZGVmYXVsdFZhbHVlcyA9IGRlZmF1bHRPcmRpbmFsVW5pdFZhbHVlcztcbiAgICAgIG9iak5vdyA9IGdyZWdvcmlhblRvT3JkaW5hbChvYmpOb3cpO1xuICAgIH0gZWxzZSB7XG4gICAgICB1bml0cyA9IG9yZGVyZWRVbml0cztcbiAgICAgIGRlZmF1bHRWYWx1ZXMgPSBkZWZhdWx0VW5pdFZhbHVlcztcbiAgICB9XG5cbiAgICAvLyBzZXQgZGVmYXVsdCB2YWx1ZXMgZm9yIG1pc3Npbmcgc3R1ZmZcbiAgICBsZXQgZm91bmRGaXJzdCA9IGZhbHNlO1xuICAgIGZvciAoY29uc3QgdSBvZiB1bml0cykge1xuICAgICAgY29uc3QgdiA9IG5vcm1hbGl6ZWRbdV07XG4gICAgICBpZiAoIWlzVW5kZWZpbmVkKHYpKSB7XG4gICAgICAgIGZvdW5kRmlyc3QgPSB0cnVlO1xuICAgICAgfSBlbHNlIGlmIChmb3VuZEZpcnN0KSB7XG4gICAgICAgIG5vcm1hbGl6ZWRbdV0gPSBkZWZhdWx0VmFsdWVzW3VdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbm9ybWFsaXplZFt1XSA9IG9iak5vd1t1XTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBtYWtlIHN1cmUgdGhlIHZhbHVlcyB3ZSBoYXZlIGFyZSBpbiByYW5nZVxuICAgIGNvbnN0IGhpZ2hlck9yZGVySW52YWxpZCA9IHVzZVdlZWtEYXRhXG4gICAgICAgID8gaGFzSW52YWxpZFdlZWtEYXRhKG5vcm1hbGl6ZWQpXG4gICAgICAgIDogY29udGFpbnNPcmRpbmFsXG4gICAgICAgID8gaGFzSW52YWxpZE9yZGluYWxEYXRhKG5vcm1hbGl6ZWQpXG4gICAgICAgIDogaGFzSW52YWxpZEdyZWdvcmlhbkRhdGEobm9ybWFsaXplZCksXG4gICAgICBpbnZhbGlkID0gaGlnaGVyT3JkZXJJbnZhbGlkIHx8IGhhc0ludmFsaWRUaW1lRGF0YShub3JtYWxpemVkKTtcblxuICAgIGlmIChpbnZhbGlkKSB7XG4gICAgICByZXR1cm4gRGF0ZVRpbWUuaW52YWxpZChpbnZhbGlkKTtcbiAgICB9XG5cbiAgICAvLyBjb21wdXRlIHRoZSBhY3R1YWwgdGltZVxuICAgIGNvbnN0IGdyZWdvcmlhbiA9IHVzZVdlZWtEYXRhXG4gICAgICAgID8gd2Vla1RvR3JlZ29yaWFuKG5vcm1hbGl6ZWQpXG4gICAgICAgIDogY29udGFpbnNPcmRpbmFsXG4gICAgICAgID8gb3JkaW5hbFRvR3JlZ29yaWFuKG5vcm1hbGl6ZWQpXG4gICAgICAgIDogbm9ybWFsaXplZCxcbiAgICAgIFt0c0ZpbmFsLCBvZmZzZXRGaW5hbF0gPSBvYmpUb1RTKGdyZWdvcmlhbiwgb2Zmc2V0UHJvdmlzLCB6b25lVG9Vc2UpLFxuICAgICAgaW5zdCA9IG5ldyBEYXRlVGltZSh7XG4gICAgICAgIHRzOiB0c0ZpbmFsLFxuICAgICAgICB6b25lOiB6b25lVG9Vc2UsXG4gICAgICAgIG86IG9mZnNldEZpbmFsLFxuICAgICAgICBsb2MsXG4gICAgICB9KTtcblxuICAgIC8vIGdyZWdvcmlhbiBkYXRhICsgd2Vla2RheSBzZXJ2ZXMgb25seSB0byB2YWxpZGF0ZVxuICAgIGlmIChub3JtYWxpemVkLndlZWtkYXkgJiYgY29udGFpbnNHcmVnb3IgJiYgb2JqLndlZWtkYXkgIT09IGluc3Qud2Vla2RheSkge1xuICAgICAgcmV0dXJuIERhdGVUaW1lLmludmFsaWQoXG4gICAgICAgIFwibWlzbWF0Y2hlZCB3ZWVrZGF5XCIsXG4gICAgICAgIGB5b3UgY2FuJ3Qgc3BlY2lmeSBib3RoIGEgd2Vla2RheSBvZiAke25vcm1hbGl6ZWQud2Vla2RheX0gYW5kIGEgZGF0ZSBvZiAke2luc3QudG9JU08oKX1gXG4gICAgICApO1xuICAgIH1cblxuICAgIHJldHVybiBpbnN0O1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIERhdGVUaW1lIGZyb20gYW4gSVNPIDg2MDEgc3RyaW5nXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gdGhlIElTTyBzdHJpbmdcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBvcHRpb25zIHRvIGFmZmVjdCB0aGUgY3JlYXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd8Wm9uZX0gW29wdHMuem9uZT0nbG9jYWwnXSAtIHVzZSB0aGlzIHpvbmUgaWYgbm8gb2Zmc2V0IGlzIHNwZWNpZmllZCBpbiB0aGUgaW5wdXQgc3RyaW5nIGl0c2VsZi4gV2lsbCBhbHNvIGNvbnZlcnQgdGhlIHRpbWUgdG8gdGhpcyB6b25lXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuc2V0Wm9uZT1mYWxzZV0gLSBvdmVycmlkZSB0aGUgem9uZSB3aXRoIGEgZml4ZWQtb2Zmc2V0IHpvbmUgc3BlY2lmaWVkIGluIHRoZSBzdHJpbmcgaXRzZWxmLCBpZiBpdCBzcGVjaWZpZXMgb25lXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5sb2NhbGU9J3N5c3RlbSdzIGxvY2FsZSddIC0gYSBsb2NhbGUgdG8gc2V0IG9uIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWUgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLm91dHB1dENhbGVuZGFyXSAtIHRoZSBvdXRwdXQgY2FsZW5kYXIgdG8gc2V0IG9uIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWUgaW5zdGFuY2VcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRzLm51bWJlcmluZ1N5c3RlbV0gLSB0aGUgbnVtYmVyaW5nIHN5c3RlbSB0byBzZXQgb24gdGhlIHJlc3VsdGluZyBEYXRlVGltZSBpbnN0YW5jZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tSVNPKCcyMDE2LTA1LTI1VDA5OjA4OjM0LjEyMycpXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmZyb21JU08oJzIwMTYtMDUtMjVUMDk6MDg6MzQuMTIzKzA2OjAwJylcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUuZnJvbUlTTygnMjAxNi0wNS0yNVQwOTowODozNC4xMjMrMDY6MDAnLCB7c2V0Wm9uZTogdHJ1ZX0pXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmZyb21JU08oJzIwMTYtMDUtMjVUMDk6MDg6MzQuMTIzJywge3pvbmU6ICd1dGMnfSlcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUuZnJvbUlTTygnMjAxNi1XMDUtNCcpXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc3RhdGljIGZyb21JU08odGV4dCwgb3B0cyA9IHt9KSB7XG4gICAgY29uc3QgW3ZhbHMsIHBhcnNlZFpvbmVdID0gcGFyc2VJU09EYXRlKHRleHQpO1xuICAgIHJldHVybiBwYXJzZURhdGFUb0RhdGVUaW1lKHZhbHMsIHBhcnNlZFpvbmUsIG9wdHMsIFwiSVNPIDg2MDFcIiwgdGV4dCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgRGF0ZVRpbWUgZnJvbSBhbiBSRkMgMjgyMiBzdHJpbmdcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSB0aGUgUkZDIDI4MjIgc3RyaW5nXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9ucyB0byBhZmZlY3QgdGhlIGNyZWF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfFpvbmV9IFtvcHRzLnpvbmU9J2xvY2FsJ10gLSBjb252ZXJ0IHRoZSB0aW1lIHRvIHRoaXMgem9uZS4gU2luY2UgdGhlIG9mZnNldCBpcyBhbHdheXMgc3BlY2lmaWVkIGluIHRoZSBzdHJpbmcgaXRzZWxmLCB0aGlzIGhhcyBubyBlZmZlY3Qgb24gdGhlIGludGVycHJldGF0aW9uIG9mIHN0cmluZywgbWVyZWx5IHRoZSB6b25lIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWUgaXMgZXhwcmVzc2VkIGluLlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRzLnNldFpvbmU9ZmFsc2VdIC0gb3ZlcnJpZGUgdGhlIHpvbmUgd2l0aCBhIGZpeGVkLW9mZnNldCB6b25lIHNwZWNpZmllZCBpbiB0aGUgc3RyaW5nIGl0c2VsZiwgaWYgaXQgc3BlY2lmaWVzIG9uZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubG9jYWxlPSdzeXN0ZW0ncyBsb2NhbGUnXSAtIGEgbG9jYWxlIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm91dHB1dENhbGVuZGFyIC0gdGhlIG91dHB1dCBjYWxlbmRhciB0byBzZXQgb24gdGhlIHJlc3VsdGluZyBEYXRlVGltZSBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5udW1iZXJpbmdTeXN0ZW0gLSB0aGUgbnVtYmVyaW5nIHN5c3RlbSB0byBzZXQgb24gdGhlIHJlc3VsdGluZyBEYXRlVGltZSBpbnN0YW5jZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tUkZDMjgyMignMjUgTm92IDIwMTYgMTM6MjM6MTIgR01UJylcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUuZnJvbVJGQzI4MjIoJ0ZyaSwgMjUgTm92IDIwMTYgMTM6MjM6MTIgKzA2MDAnKVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tUkZDMjgyMignMjUgTm92IDIwMTYgMTM6MjMgWicpXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc3RhdGljIGZyb21SRkMyODIyKHRleHQsIG9wdHMgPSB7fSkge1xuICAgIGNvbnN0IFt2YWxzLCBwYXJzZWRab25lXSA9IHBhcnNlUkZDMjgyMkRhdGUodGV4dCk7XG4gICAgcmV0dXJuIHBhcnNlRGF0YVRvRGF0ZVRpbWUodmFscywgcGFyc2VkWm9uZSwgb3B0cywgXCJSRkMgMjgyMlwiLCB0ZXh0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBEYXRlVGltZSBmcm9tIGFuIEhUVFAgaGVhZGVyIGRhdGVcbiAgICogQHNlZSBodHRwczovL3d3dy53My5vcmcvUHJvdG9jb2xzL3JmYzI2MTYvcmZjMjYxNi1zZWMzLmh0bWwjc2VjMy4zLjFcbiAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSB0aGUgSFRUUCBoZWFkZXIgZGF0ZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnMgdG8gYWZmZWN0IHRoZSBjcmVhdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZ3xab25lfSBbb3B0cy56b25lPSdsb2NhbCddIC0gY29udmVydCB0aGUgdGltZSB0byB0aGlzIHpvbmUuIFNpbmNlIEhUVFAgZGF0ZXMgYXJlIGFsd2F5cyBpbiBVVEMsIHRoaXMgaGFzIG5vIGVmZmVjdCBvbiB0aGUgaW50ZXJwcmV0YXRpb24gb2Ygc3RyaW5nLCBtZXJlbHkgdGhlIHpvbmUgdGhlIHJlc3VsdGluZyBEYXRlVGltZSBpcyBleHByZXNzZWQgaW4uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuc2V0Wm9uZT1mYWxzZV0gLSBvdmVycmlkZSB0aGUgem9uZSB3aXRoIHRoZSBmaXhlZC1vZmZzZXQgem9uZSBzcGVjaWZpZWQgaW4gdGhlIHN0cmluZy4gRm9yIEhUVFAgZGF0ZXMsIHRoaXMgaXMgYWx3YXlzIFVUQywgc28gdGhpcyBvcHRpb24gaXMgZXF1aXZhbGVudCB0byBzZXR0aW5nIHRoZSBgem9uZWAgb3B0aW9uIHRvICd1dGMnLCBidXQgdGhpcyBvcHRpb24gaXMgaW5jbHVkZWQgZm9yIGNvbnNpc3RlbmN5IHdpdGggc2ltaWxhciBtZXRob2RzLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubG9jYWxlPSdzeXN0ZW0ncyBsb2NhbGUnXSAtIGEgbG9jYWxlIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm91dHB1dENhbGVuZGFyIC0gdGhlIG91dHB1dCBjYWxlbmRhciB0byBzZXQgb24gdGhlIHJlc3VsdGluZyBEYXRlVGltZSBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5udW1iZXJpbmdTeXN0ZW0gLSB0aGUgbnVtYmVyaW5nIHN5c3RlbSB0byBzZXQgb24gdGhlIHJlc3VsdGluZyBEYXRlVGltZSBpbnN0YW5jZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tSFRUUCgnU3VuLCAwNiBOb3YgMTk5NCAwODo0OTozNyBHTVQnKVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tSFRUUCgnU3VuZGF5LCAwNi1Ob3YtOTQgMDg6NDk6MzcgR01UJylcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUuZnJvbUhUVFAoJ1N1biBOb3YgIDYgMDg6NDk6MzcgMTk5NCcpXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc3RhdGljIGZyb21IVFRQKHRleHQsIG9wdHMgPSB7fSkge1xuICAgIGNvbnN0IFt2YWxzLCBwYXJzZWRab25lXSA9IHBhcnNlSFRUUERhdGUodGV4dCk7XG4gICAgcmV0dXJuIHBhcnNlRGF0YVRvRGF0ZVRpbWUodmFscywgcGFyc2VkWm9uZSwgb3B0cywgXCJIVFRQXCIsIG9wdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhIERhdGVUaW1lIGZyb20gYW4gaW5wdXQgc3RyaW5nIGFuZCBmb3JtYXQgc3RyaW5nLlxuICAgKiBEZWZhdWx0cyB0byBlbi1VUyBpZiBubyBsb2NhbGUgaGFzIGJlZW4gc3BlY2lmaWVkLCByZWdhcmRsZXNzIG9mIHRoZSBzeXN0ZW0ncyBsb2NhbGUuIEZvciBhIHRhYmxlIG9mIHRva2VucyBhbmQgdGhlaXIgaW50ZXJwcmV0YXRpb25zLCBzZWUgW2hlcmVdKGh0dHBzOi8vbW9tZW50LmdpdGh1Yi5pby9sdXhvbi8jL3BhcnNpbmc/aWQ9dGFibGUtb2YtdG9rZW5zKS5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHRleHQgLSB0aGUgc3RyaW5nIHRvIHBhcnNlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbXQgLSB0aGUgZm9ybWF0IHRoZSBzdHJpbmcgaXMgZXhwZWN0ZWQgdG8gYmUgaW4gKHNlZSB0aGUgbGluayBiZWxvdyBmb3IgdGhlIGZvcm1hdHMpXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9ucyB0byBhZmZlY3QgdGhlIGNyZWF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfFpvbmV9IFtvcHRzLnpvbmU9J2xvY2FsJ10gLSB1c2UgdGhpcyB6b25lIGlmIG5vIG9mZnNldCBpcyBzcGVjaWZpZWQgaW4gdGhlIGlucHV0IHN0cmluZyBpdHNlbGYuIFdpbGwgYWxzbyBjb252ZXJ0IHRoZSBEYXRlVGltZSB0byB0aGlzIHpvbmVcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5zZXRab25lPWZhbHNlXSAtIG92ZXJyaWRlIHRoZSB6b25lIHdpdGggYSB6b25lIHNwZWNpZmllZCBpbiB0aGUgc3RyaW5nIGl0c2VsZiwgaWYgaXQgc3BlY2lmaWVzIG9uZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMubG9jYWxlPSdlbi1VUyddIC0gYSBsb2NhbGUgc3RyaW5nIHRvIHVzZSB3aGVuIHBhcnNpbmcuIFdpbGwgYWxzbyBzZXQgdGhlIERhdGVUaW1lIHRvIHRoaXMgbG9jYWxlXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRzLm51bWJlcmluZ1N5c3RlbSAtIHRoZSBudW1iZXJpbmcgc3lzdGVtIHRvIHVzZSB3aGVuIHBhcnNpbmcuIFdpbGwgYWxzbyBzZXQgdGhlIHJlc3VsdGluZyBEYXRlVGltZSB0byB0aGlzIG51bWJlcmluZyBzeXN0ZW1cbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMub3V0cHV0Q2FsZW5kYXIgLSB0aGUgb3V0cHV0IGNhbGVuZGFyIHRvIHNldCBvbiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIGluc3RhbmNlXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc3RhdGljIGZyb21Gb3JtYXQodGV4dCwgZm10LCBvcHRzID0ge30pIHtcbiAgICBpZiAoaXNVbmRlZmluZWQodGV4dCkgfHwgaXNVbmRlZmluZWQoZm10KSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRBcmd1bWVudEVycm9yKFwiZnJvbUZvcm1hdCByZXF1aXJlcyBhbiBpbnB1dCBzdHJpbmcgYW5kIGEgZm9ybWF0XCIpO1xuICAgIH1cblxuICAgIGNvbnN0IHsgbG9jYWxlID0gbnVsbCwgbnVtYmVyaW5nU3lzdGVtID0gbnVsbCB9ID0gb3B0cyxcbiAgICAgIGxvY2FsZVRvVXNlID0gTG9jYWxlLmZyb21PcHRzKHtcbiAgICAgICAgbG9jYWxlLFxuICAgICAgICBudW1iZXJpbmdTeXN0ZW0sXG4gICAgICAgIGRlZmF1bHRUb0VOOiB0cnVlLFxuICAgICAgfSksXG4gICAgICBbdmFscywgcGFyc2VkWm9uZSwgc3BlY2lmaWNPZmZzZXQsIGludmFsaWRdID0gcGFyc2VGcm9tVG9rZW5zKGxvY2FsZVRvVXNlLCB0ZXh0LCBmbXQpO1xuICAgIGlmIChpbnZhbGlkKSB7XG4gICAgICByZXR1cm4gRGF0ZVRpbWUuaW52YWxpZChpbnZhbGlkKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHBhcnNlRGF0YVRvRGF0ZVRpbWUodmFscywgcGFyc2VkWm9uZSwgb3B0cywgYGZvcm1hdCAke2ZtdH1gLCB0ZXh0LCBzcGVjaWZpY09mZnNldCk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIHVzZSBmcm9tRm9ybWF0IGluc3RlYWRcbiAgICovXG4gIHN0YXRpYyBmcm9tU3RyaW5nKHRleHQsIGZtdCwgb3B0cyA9IHt9KSB7XG4gICAgcmV0dXJuIERhdGVUaW1lLmZyb21Gb3JtYXQodGV4dCwgZm10LCBvcHRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBEYXRlVGltZSBmcm9tIGEgU1FMIGRhdGUsIHRpbWUsIG9yIGRhdGV0aW1lXG4gICAqIERlZmF1bHRzIHRvIGVuLVVTIGlmIG5vIGxvY2FsZSBoYXMgYmVlbiBzcGVjaWZpZWQsIHJlZ2FyZGxlc3Mgb2YgdGhlIHN5c3RlbSdzIGxvY2FsZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dCAtIHRoZSBzdHJpbmcgdG8gcGFyc2VcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBvcHRpb25zIHRvIGFmZmVjdCB0aGUgY3JlYXRpb25cbiAgICogQHBhcmFtIHtzdHJpbmd8Wm9uZX0gW29wdHMuem9uZT0nbG9jYWwnXSAtIHVzZSB0aGlzIHpvbmUgaWYgbm8gb2Zmc2V0IGlzIHNwZWNpZmllZCBpbiB0aGUgaW5wdXQgc3RyaW5nIGl0c2VsZi4gV2lsbCBhbHNvIGNvbnZlcnQgdGhlIERhdGVUaW1lIHRvIHRoaXMgem9uZVxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRzLnNldFpvbmU9ZmFsc2VdIC0gb3ZlcnJpZGUgdGhlIHpvbmUgd2l0aCBhIHpvbmUgc3BlY2lmaWVkIGluIHRoZSBzdHJpbmcgaXRzZWxmLCBpZiBpdCBzcGVjaWZpZXMgb25lXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5sb2NhbGU9J2VuLVVTJ10gLSBhIGxvY2FsZSBzdHJpbmcgdG8gdXNlIHdoZW4gcGFyc2luZy4gV2lsbCBhbHNvIHNldCB0aGUgRGF0ZVRpbWUgdG8gdGhpcyBsb2NhbGVcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wdHMubnVtYmVyaW5nU3lzdGVtIC0gdGhlIG51bWJlcmluZyBzeXN0ZW0gdG8gdXNlIHdoZW4gcGFyc2luZy4gV2lsbCBhbHNvIHNldCB0aGUgcmVzdWx0aW5nIERhdGVUaW1lIHRvIHRoaXMgbnVtYmVyaW5nIHN5c3RlbVxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0cy5vdXRwdXRDYWxlbmRhciAtIHRoZSBvdXRwdXQgY2FsZW5kYXIgdG8gc2V0IG9uIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWUgaW5zdGFuY2VcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUuZnJvbVNRTCgnMjAxNy0wNS0xNScpXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmZyb21TUUwoJzIwMTctMDUtMTUgMDk6MTI6MzQnKVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tU1FMKCcyMDE3LTA1LTE1IDA5OjEyOjM0LjM0MicpXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmZyb21TUUwoJzIwMTctMDUtMTUgMDk6MTI6MzQuMzQyKzA2OjAwJylcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUuZnJvbVNRTCgnMjAxNy0wNS0xNSAwOToxMjozNC4zNDIgQW1lcmljYS9Mb3NfQW5nZWxlcycpXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmZyb21TUUwoJzIwMTctMDUtMTUgMDk6MTI6MzQuMzQyIEFtZXJpY2EvTG9zX0FuZ2VsZXMnLCB7IHNldFpvbmU6IHRydWUgfSlcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUuZnJvbVNRTCgnMjAxNy0wNS0xNSAwOToxMjozNC4zNDInLCB7IHpvbmU6ICdBbWVyaWNhL0xvc19BbmdlbGVzJyB9KVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5mcm9tU1FMKCcwOToxMjozNC4zNDInKVxuICAgKiBAcmV0dXJuIHtEYXRlVGltZX1cbiAgICovXG4gIHN0YXRpYyBmcm9tU1FMKHRleHQsIG9wdHMgPSB7fSkge1xuICAgIGNvbnN0IFt2YWxzLCBwYXJzZWRab25lXSA9IHBhcnNlU1FMKHRleHQpO1xuICAgIHJldHVybiBwYXJzZURhdGFUb0RhdGVUaW1lKHZhbHMsIHBhcnNlZFpvbmUsIG9wdHMsIFwiU1FMXCIsIHRleHQpO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZSBhbiBpbnZhbGlkIERhdGVUaW1lLlxuICAgKiBAcGFyYW0ge0RhdGVUaW1lfSByZWFzb24gLSBzaW1wbGUgc3RyaW5nIG9mIHdoeSB0aGlzIERhdGVUaW1lIGlzIGludmFsaWQuIFNob3VsZCBub3QgY29udGFpbiBwYXJhbWV0ZXJzIG9yIGFueXRoaW5nIGVsc2UgZGF0YS1kZXBlbmRlbnRcbiAgICogQHBhcmFtIHtzdHJpbmd9IFtleHBsYW5hdGlvbj1udWxsXSAtIGxvbmdlciBleHBsYW5hdGlvbiwgbWF5IGluY2x1ZGUgcGFyYW1ldGVycyBhbmQgb3RoZXIgdXNlZnVsIGRlYnVnZ2luZyBpbmZvcm1hdGlvblxuICAgKiBAcmV0dXJuIHtEYXRlVGltZX1cbiAgICovXG4gIHN0YXRpYyBpbnZhbGlkKHJlYXNvbiwgZXhwbGFuYXRpb24gPSBudWxsKSB7XG4gICAgaWYgKCFyZWFzb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihcIm5lZWQgdG8gc3BlY2lmeSBhIHJlYXNvbiB0aGUgRGF0ZVRpbWUgaXMgaW52YWxpZFwiKTtcbiAgICB9XG5cbiAgICBjb25zdCBpbnZhbGlkID0gcmVhc29uIGluc3RhbmNlb2YgSW52YWxpZCA/IHJlYXNvbiA6IG5ldyBJbnZhbGlkKHJlYXNvbiwgZXhwbGFuYXRpb24pO1xuXG4gICAgaWYgKFNldHRpbmdzLnRocm93T25JbnZhbGlkKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZERhdGVUaW1lRXJyb3IoaW52YWxpZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBuZXcgRGF0ZVRpbWUoeyBpbnZhbGlkIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiBhbiBvYmplY3QgaXMgYW4gaW5zdGFuY2Ugb2YgRGF0ZVRpbWUuIFdvcmtzIGFjcm9zcyBjb250ZXh0IGJvdW5kYXJpZXNcbiAgICogQHBhcmFtIHtvYmplY3R9IG9cbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIHN0YXRpYyBpc0RhdGVUaW1lKG8pIHtcbiAgICByZXR1cm4gKG8gJiYgby5pc0x1eG9uRGF0ZVRpbWUpIHx8IGZhbHNlO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb2R1Y2UgdGhlIGZvcm1hdCBzdHJpbmcgZm9yIGEgc2V0IG9mIG9wdGlvbnNcbiAgICogQHBhcmFtIGZvcm1hdE9wdHNcbiAgICogQHBhcmFtIGxvY2FsZU9wdHNcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBwYXJzZUZvcm1hdEZvck9wdHMoZm9ybWF0T3B0cywgbG9jYWxlT3B0cyA9IHt9KSB7XG4gICAgY29uc3QgdG9rZW5MaXN0ID0gZm9ybWF0T3B0c1RvVG9rZW5zKGZvcm1hdE9wdHMsIExvY2FsZS5mcm9tT2JqZWN0KGxvY2FsZU9wdHMpKTtcbiAgICByZXR1cm4gIXRva2VuTGlzdCA/IG51bGwgOiB0b2tlbkxpc3QubWFwKCh0KSA9PiAodCA/IHQudmFsIDogbnVsbCkpLmpvaW4oXCJcIik7XG4gIH1cblxuICAvKipcbiAgICogUHJvZHVjZSB0aGUgdGhlIGZ1bGx5IGV4cGFuZGVkIGZvcm1hdCB0b2tlbiBmb3IgdGhlIGxvY2FsZVxuICAgKiBEb2VzIE5PVCBxdW90ZSBjaGFyYWN0ZXJzLCBzbyBxdW90ZWQgdG9rZW5zIHdpbGwgbm90IHJvdW5kIHRyaXAgY29ycmVjdGx5XG4gICAqIEBwYXJhbSBmbXRcbiAgICogQHBhcmFtIGxvY2FsZU9wdHNcbiAgICogQHJldHVybnMge3N0cmluZ31cbiAgICovXG4gIHN0YXRpYyBleHBhbmRGb3JtYXQoZm10LCBsb2NhbGVPcHRzID0ge30pIHtcbiAgICBjb25zdCBleHBhbmRlZCA9IGV4cGFuZE1hY3JvVG9rZW5zKEZvcm1hdHRlci5wYXJzZUZvcm1hdChmbXQpLCBMb2NhbGUuZnJvbU9iamVjdChsb2NhbGVPcHRzKSk7XG4gICAgcmV0dXJuIGV4cGFuZGVkLm1hcCgodCkgPT4gdC52YWwpLmpvaW4oXCJcIik7XG4gIH1cblxuICAvLyBJTkZPXG5cbiAgLyoqXG4gICAqIEdldCB0aGUgdmFsdWUgb2YgdW5pdC5cbiAgICogQHBhcmFtIHtzdHJpbmd9IHVuaXQgLSBhIHVuaXQgc3VjaCBhcyAnbWludXRlJyBvciAnZGF5J1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCA3LCA0KS5nZXQoJ21vbnRoJyk7IC8vPT4gN1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCA3LCA0KS5nZXQoJ2RheScpOyAvLz0+IDRcbiAgICogQHJldHVybiB7bnVtYmVyfVxuICAgKi9cbiAgZ2V0KHVuaXQpIHtcbiAgICByZXR1cm4gdGhpc1t1bml0XTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHdoZXRoZXIgdGhlIERhdGVUaW1lIGlzIHZhbGlkLiBJbnZhbGlkIERhdGVUaW1lcyBvY2N1ciB3aGVuOlxuICAgKiAqIFRoZSBEYXRlVGltZSB3YXMgY3JlYXRlZCBmcm9tIGludmFsaWQgY2FsZW5kYXIgaW5mb3JtYXRpb24sIHN1Y2ggYXMgdGhlIDEzdGggbW9udGggb3IgRmVicnVhcnkgMzBcbiAgICogKiBUaGUgRGF0ZVRpbWUgd2FzIGNyZWF0ZWQgYnkgYW4gb3BlcmF0aW9uIG9uIGFub3RoZXIgaW52YWxpZCBkYXRlXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKi9cbiAgZ2V0IGlzVmFsaWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaW52YWxpZCA9PT0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIGVycm9yIGNvZGUgaWYgdGhpcyBEYXRlVGltZSBpcyBpbnZhbGlkLCBvciBudWxsIGlmIHRoZSBEYXRlVGltZSBpcyB2YWxpZFxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKi9cbiAgZ2V0IGludmFsaWRSZWFzb24oKSB7XG4gICAgcmV0dXJuIHRoaXMuaW52YWxpZCA/IHRoaXMuaW52YWxpZC5yZWFzb24gOiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gZXhwbGFuYXRpb24gb2Ygd2h5IHRoaXMgRGF0ZVRpbWUgYmVjYW1lIGludmFsaWQsIG9yIG51bGwgaWYgdGhlIERhdGVUaW1lIGlzIHZhbGlkXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBnZXQgaW52YWxpZEV4cGxhbmF0aW9uKCkge1xuICAgIHJldHVybiB0aGlzLmludmFsaWQgPyB0aGlzLmludmFsaWQuZXhwbGFuYXRpb24gOiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbG9jYWxlIG9mIGEgRGF0ZVRpbWUsIHN1Y2ggJ2VuLUdCJy4gVGhlIGxvY2FsZSBpcyB1c2VkIHdoZW4gZm9ybWF0dGluZyB0aGUgRGF0ZVRpbWVcbiAgICpcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICovXG4gIGdldCBsb2NhbGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMubG9jLmxvY2FsZSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBudW1iZXJpbmcgc3lzdGVtIG9mIGEgRGF0ZVRpbWUsIHN1Y2ggJ2JlbmcnLiBUaGUgbnVtYmVyaW5nIHN5c3RlbSBpcyB1c2VkIHdoZW4gZm9ybWF0dGluZyB0aGUgRGF0ZVRpbWVcbiAgICpcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICovXG4gIGdldCBudW1iZXJpbmdTeXN0ZW0oKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMubG9jLm51bWJlcmluZ1N5c3RlbSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBvdXRwdXQgY2FsZW5kYXIgb2YgYSBEYXRlVGltZSwgc3VjaCAnaXNsYW1pYycuIFRoZSBvdXRwdXQgY2FsZW5kYXIgaXMgdXNlZCB3aGVuIGZvcm1hdHRpbmcgdGhlIERhdGVUaW1lXG4gICAqXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBnZXQgb3V0cHV0Q2FsZW5kYXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMubG9jLm91dHB1dENhbGVuZGFyIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHRpbWUgem9uZSBhc3NvY2lhdGVkIHdpdGggdGhpcyBEYXRlVGltZS5cbiAgICogQHR5cGUge1pvbmV9XG4gICAqL1xuICBnZXQgem9uZSgpIHtcbiAgICByZXR1cm4gdGhpcy5fem9uZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG5hbWUgb2YgdGhlIHRpbWUgem9uZS5cbiAgICogQHR5cGUge3N0cmluZ31cbiAgICovXG4gIGdldCB6b25lTmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gdGhpcy56b25lLm5hbWUgOiBudWxsO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgeWVhclxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCA1LCAyNSkueWVhciAvLz0+IDIwMTdcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCB5ZWFyKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLmMueWVhciA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHF1YXJ0ZXJcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgNSwgMjUpLnF1YXJ0ZXIgLy89PiAyXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgcXVhcnRlcigpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gTWF0aC5jZWlsKHRoaXMuYy5tb250aCAvIDMpIDogTmFOO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbW9udGggKDEtMTIpLlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCA1LCAyNSkubW9udGggLy89PiA1XG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgbW9udGgoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMuYy5tb250aCA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRheSBvZiB0aGUgbW9udGggKDEtMzBpc2gpLlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCA1LCAyNSkuZGF5IC8vPT4gMjVcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCBkYXkoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMuYy5kYXkgOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBob3VyIG9mIHRoZSBkYXkgKDAtMjMpLlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCA1LCAyNSwgOSkuaG91ciAvLz0+IDlcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCBob3VyKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLmMuaG91ciA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIG1pbnV0ZSBvZiB0aGUgaG91ciAoMC01OSkuXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTcsIDUsIDI1LCA5LCAzMCkubWludXRlIC8vPT4gMzBcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCBtaW51dGUoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMuYy5taW51dGUgOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBzZWNvbmQgb2YgdGhlIG1pbnV0ZSAoMC01OSkuXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTcsIDUsIDI1LCA5LCAzMCwgNTIpLnNlY29uZCAvLz0+IDUyXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgc2Vjb25kKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLmMuc2Vjb25kIDogTmFOO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbWlsbGlzZWNvbmQgb2YgdGhlIHNlY29uZCAoMC05OTkpLlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCA1LCAyNSwgOSwgMzAsIDUyLCA2NTQpLm1pbGxpc2Vjb25kIC8vPT4gNjU0XG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgbWlsbGlzZWNvbmQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMuYy5taWxsaXNlY29uZCA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHdlZWsgeWVhclxuICAgKiBAc2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lTT193ZWVrX2RhdGVcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNCwgMTIsIDMxKS53ZWVrWWVhciAvLz0+IDIwMTVcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCB3ZWVrWWVhcigpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gcG9zc2libHlDYWNoZWRXZWVrRGF0YSh0aGlzKS53ZWVrWWVhciA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHdlZWsgbnVtYmVyIG9mIHRoZSB3ZWVrIHllYXIgKDEtNTJpc2gpLlxuICAgKiBAc2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lTT193ZWVrX2RhdGVcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgNSwgMjUpLndlZWtOdW1iZXIgLy89PiAyMVxuICAgKiBAdHlwZSB7bnVtYmVyfVxuICAgKi9cbiAgZ2V0IHdlZWtOdW1iZXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHBvc3NpYmx5Q2FjaGVkV2Vla0RhdGEodGhpcykud2Vla051bWJlciA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGRheSBvZiB0aGUgd2Vlay5cbiAgICogMSBpcyBNb25kYXkgYW5kIDcgaXMgU3VuZGF5XG4gICAqIEBzZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSVNPX3dlZWtfZGF0ZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE0LCAxMSwgMzEpLndlZWtkYXkgLy89PiA0XG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgd2Vla2RheSgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gcG9zc2libHlDYWNoZWRXZWVrRGF0YSh0aGlzKS53ZWVrZGF5IDogTmFOO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgb3JkaW5hbCAobWVhbmluZyB0aGUgZGF5IG9mIHRoZSB5ZWFyKVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCA1LCAyNSkub3JkaW5hbCAvLz0+IDE0NVxuICAgKiBAdHlwZSB7bnVtYmVyfERhdGVUaW1lfVxuICAgKi9cbiAgZ2V0IG9yZGluYWwoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IGdyZWdvcmlhblRvT3JkaW5hbCh0aGlzLmMpLm9yZGluYWwgOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBodW1hbiByZWFkYWJsZSBzaG9ydCBtb250aCBuYW1lLCBzdWNoIGFzICdPY3QnLlxuICAgKiBEZWZhdWx0cyB0byB0aGUgc3lzdGVtJ3MgbG9jYWxlIGlmIG5vIGxvY2FsZSBoYXMgYmVlbiBzcGVjaWZpZWRcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgMTAsIDMwKS5tb250aFNob3J0IC8vPT4gT2N0XG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBnZXQgbW9udGhTaG9ydCgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gSW5mby5tb250aHMoXCJzaG9ydFwiLCB7IGxvY09iajogdGhpcy5sb2MgfSlbdGhpcy5tb250aCAtIDFdIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGh1bWFuIHJlYWRhYmxlIGxvbmcgbW9udGggbmFtZSwgc3VjaCBhcyAnT2N0b2JlcicuXG4gICAqIERlZmF1bHRzIHRvIHRoZSBzeXN0ZW0ncyBsb2NhbGUgaWYgbm8gbG9jYWxlIGhhcyBiZWVuIHNwZWNpZmllZFxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCAxMCwgMzApLm1vbnRoTG9uZyAvLz0+IE9jdG9iZXJcbiAgICogQHR5cGUge3N0cmluZ31cbiAgICovXG4gIGdldCBtb250aExvbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IEluZm8ubW9udGhzKFwibG9uZ1wiLCB7IGxvY09iajogdGhpcy5sb2MgfSlbdGhpcy5tb250aCAtIDFdIDogbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGh1bWFuIHJlYWRhYmxlIHNob3J0IHdlZWtkYXksIHN1Y2ggYXMgJ01vbicuXG4gICAqIERlZmF1bHRzIHRvIHRoZSBzeXN0ZW0ncyBsb2NhbGUgaWYgbm8gbG9jYWxlIGhhcyBiZWVuIHNwZWNpZmllZFxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCAxMCwgMzApLndlZWtkYXlTaG9ydCAvLz0+IE1vblxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKi9cbiAgZ2V0IHdlZWtkYXlTaG9ydCgpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gSW5mby53ZWVrZGF5cyhcInNob3J0XCIsIHsgbG9jT2JqOiB0aGlzLmxvYyB9KVt0aGlzLndlZWtkYXkgLSAxXSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBodW1hbiByZWFkYWJsZSBsb25nIHdlZWtkYXksIHN1Y2ggYXMgJ01vbmRheScuXG4gICAqIERlZmF1bHRzIHRvIHRoZSBzeXN0ZW0ncyBsb2NhbGUgaWYgbm8gbG9jYWxlIGhhcyBiZWVuIHNwZWNpZmllZFxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE3LCAxMCwgMzApLndlZWtkYXlMb25nIC8vPT4gTW9uZGF5XG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBnZXQgd2Vla2RheUxvbmcoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IEluZm8ud2Vla2RheXMoXCJsb25nXCIsIHsgbG9jT2JqOiB0aGlzLmxvYyB9KVt0aGlzLndlZWtkYXkgLSAxXSA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBVVEMgb2Zmc2V0IG9mIHRoaXMgRGF0ZVRpbWUgaW4gbWludXRlc1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS5vZmZzZXQgLy89PiAtMjQwXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLnV0YygpLm9mZnNldCAvLz0+IDBcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCBvZmZzZXQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/ICt0aGlzLm8gOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBzaG9ydCBodW1hbiBuYW1lIGZvciB0aGUgem9uZSdzIGN1cnJlbnQgb2Zmc2V0LCBmb3IgZXhhbXBsZSBcIkVTVFwiIG9yIFwiRURUXCIuXG4gICAqIERlZmF1bHRzIHRvIHRoZSBzeXN0ZW0ncyBsb2NhbGUgaWYgbm8gbG9jYWxlIGhhcyBiZWVuIHNwZWNpZmllZFxuICAgKiBAdHlwZSB7c3RyaW5nfVxuICAgKi9cbiAgZ2V0IG9mZnNldE5hbWVTaG9ydCgpIHtcbiAgICBpZiAodGhpcy5pc1ZhbGlkKSB7XG4gICAgICByZXR1cm4gdGhpcy56b25lLm9mZnNldE5hbWUodGhpcy50cywge1xuICAgICAgICBmb3JtYXQ6IFwic2hvcnRcIixcbiAgICAgICAgbG9jYWxlOiB0aGlzLmxvY2FsZSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBsb25nIGh1bWFuIG5hbWUgZm9yIHRoZSB6b25lJ3MgY3VycmVudCBvZmZzZXQsIGZvciBleGFtcGxlIFwiRWFzdGVybiBTdGFuZGFyZCBUaW1lXCIgb3IgXCJFYXN0ZXJuIERheWxpZ2h0IFRpbWVcIi5cbiAgICogRGVmYXVsdHMgdG8gdGhlIHN5c3RlbSdzIGxvY2FsZSBpZiBubyBsb2NhbGUgaGFzIGJlZW4gc3BlY2lmaWVkXG4gICAqIEB0eXBlIHtzdHJpbmd9XG4gICAqL1xuICBnZXQgb2Zmc2V0TmFtZUxvbmcoKSB7XG4gICAgaWYgKHRoaXMuaXNWYWxpZCkge1xuICAgICAgcmV0dXJuIHRoaXMuem9uZS5vZmZzZXROYW1lKHRoaXMudHMsIHtcbiAgICAgICAgZm9ybWF0OiBcImxvbmdcIixcbiAgICAgICAgbG9jYWxlOiB0aGlzLmxvY2FsZSxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogR2V0IHdoZXRoZXIgdGhpcyB6b25lJ3Mgb2Zmc2V0IGV2ZXIgY2hhbmdlcywgYXMgaW4gYSBEU1QuXG4gICAqIEB0eXBlIHtib29sZWFufVxuICAgKi9cbiAgZ2V0IGlzT2Zmc2V0Rml4ZWQoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMuem9uZS5pc1VuaXZlcnNhbCA6IG51bGw7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHdoZXRoZXIgdGhlIERhdGVUaW1lIGlzIGluIGEgRFNULlxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICovXG4gIGdldCBpc0luRFNUKCkge1xuICAgIGlmICh0aGlzLmlzT2Zmc2V0Rml4ZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIChcbiAgICAgICAgdGhpcy5vZmZzZXQgPiB0aGlzLnNldCh7IG1vbnRoOiAxLCBkYXk6IDEgfSkub2Zmc2V0IHx8XG4gICAgICAgIHRoaXMub2Zmc2V0ID4gdGhpcy5zZXQoeyBtb250aDogNSB9KS5vZmZzZXRcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIERhdGVUaW1lIGlzIGluIGEgbGVhcCB5ZWFyLCBmYWxzZSBvdGhlcndpc2VcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNikuaXNJbkxlYXBZZWFyIC8vPT4gdHJ1ZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDEzKS5pc0luTGVhcFllYXIgLy89PiBmYWxzZVxuICAgKiBAdHlwZSB7Ym9vbGVhbn1cbiAgICovXG4gIGdldCBpc0luTGVhcFllYXIoKSB7XG4gICAgcmV0dXJuIGlzTGVhcFllYXIodGhpcy55ZWFyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGlzIERhdGVUaW1lJ3MgbW9udGhcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNiwgMikuZGF5c0luTW9udGggLy89PiAyOVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE2LCAzKS5kYXlzSW5Nb250aCAvLz0+IDMxXG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgZGF5c0luTW9udGgoKSB7XG4gICAgcmV0dXJuIGRheXNJbk1vbnRoKHRoaXMueWVhciwgdGhpcy5tb250aCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgbnVtYmVyIG9mIGRheXMgaW4gdGhpcyBEYXRlVGltZSdzIHllYXJcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNikuZGF5c0luWWVhciAvLz0+IDM2NlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDEzKS5kYXlzSW5ZZWFyIC8vPT4gMzY1XG4gICAqIEB0eXBlIHtudW1iZXJ9XG4gICAqL1xuICBnZXQgZGF5c0luWWVhcigpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkID8gZGF5c0luWWVhcih0aGlzLnllYXIpIDogTmFOO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG51bWJlciBvZiB3ZWVrcyBpbiB0aGlzIERhdGVUaW1lJ3MgeWVhclxuICAgKiBAc2VlIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0lTT193ZWVrX2RhdGVcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAwNCkud2Vla3NJbldlZWtZZWFyIC8vPT4gNTNcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxMykud2Vla3NJbldlZWtZZWFyIC8vPT4gNTJcbiAgICogQHR5cGUge251bWJlcn1cbiAgICovXG4gIGdldCB3ZWVrc0luV2Vla1llYXIoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHdlZWtzSW5XZWVrWWVhcih0aGlzLndlZWtZZWFyKSA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSByZXNvbHZlZCBJbnRsIG9wdGlvbnMgZm9yIHRoaXMgRGF0ZVRpbWUuXG4gICAqIFRoaXMgaXMgdXNlZnVsIGluIHVuZGVyc3RhbmRpbmcgdGhlIGJlaGF2aW9yIG9mIGZvcm1hdHRpbmcgbWV0aG9kc1xuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIHRoZSBzYW1lIG9wdGlvbnMgYXMgdG9Mb2NhbGVTdHJpbmdcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cbiAgcmVzb2x2ZWRMb2NhbGVPcHRpb25zKG9wdHMgPSB7fSkge1xuICAgIGNvbnN0IHsgbG9jYWxlLCBudW1iZXJpbmdTeXN0ZW0sIGNhbGVuZGFyIH0gPSBGb3JtYXR0ZXIuY3JlYXRlKFxuICAgICAgdGhpcy5sb2MuY2xvbmUob3B0cyksXG4gICAgICBvcHRzXG4gICAgKS5yZXNvbHZlZE9wdGlvbnModGhpcyk7XG4gICAgcmV0dXJuIHsgbG9jYWxlLCBudW1iZXJpbmdTeXN0ZW0sIG91dHB1dENhbGVuZGFyOiBjYWxlbmRhciB9O1xuICB9XG5cbiAgLy8gVFJBTlNGT1JNXG5cbiAgLyoqXG4gICAqIFwiU2V0XCIgdGhlIERhdGVUaW1lJ3Mgem9uZSB0byBVVEMuIFJldHVybnMgYSBuZXdseS1jb25zdHJ1Y3RlZCBEYXRlVGltZS5cbiAgICpcbiAgICogRXF1aXZhbGVudCB0byB7QGxpbmsgRGF0ZVRpbWUjc2V0Wm9uZX0oJ3V0YycpXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBbb2Zmc2V0PTBdIC0gb3B0aW9uYWxseSwgYW4gb2Zmc2V0IGZyb20gVVRDIGluIG1pbnV0ZXNcbiAgICogQHBhcmFtIHtPYmplY3R9IFtvcHRzPXt9XSAtIG9wdGlvbnMgdG8gcGFzcyB0byBgc2V0Wm9uZSgpYFxuICAgKiBAcmV0dXJuIHtEYXRlVGltZX1cbiAgICovXG4gIHRvVVRDKG9mZnNldCA9IDAsIG9wdHMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLnNldFpvbmUoRml4ZWRPZmZzZXRab25lLmluc3RhbmNlKG9mZnNldCksIG9wdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFwiU2V0XCIgdGhlIERhdGVUaW1lJ3Mgem9uZSB0byB0aGUgaG9zdCdzIGxvY2FsIHpvbmUuIFJldHVybnMgYSBuZXdseS1jb25zdHJ1Y3RlZCBEYXRlVGltZS5cbiAgICpcbiAgICogRXF1aXZhbGVudCB0byBgc2V0Wm9uZSgnbG9jYWwnKWBcbiAgICogQHJldHVybiB7RGF0ZVRpbWV9XG4gICAqL1xuICB0b0xvY2FsKCkge1xuICAgIHJldHVybiB0aGlzLnNldFpvbmUoU2V0dGluZ3MuZGVmYXVsdFpvbmUpO1xuICB9XG5cbiAgLyoqXG4gICAqIFwiU2V0XCIgdGhlIERhdGVUaW1lJ3Mgem9uZSB0byBzcGVjaWZpZWQgem9uZS4gUmV0dXJucyBhIG5ld2x5LWNvbnN0cnVjdGVkIERhdGVUaW1lLlxuICAgKlxuICAgKiBCeSBkZWZhdWx0LCB0aGUgc2V0dGVyIGtlZXBzIHRoZSB1bmRlcmx5aW5nIHRpbWUgdGhlIHNhbWUgKGFzIGluLCB0aGUgc2FtZSB0aW1lc3RhbXApLCBidXQgdGhlIG5ldyBpbnN0YW5jZSB3aWxsIHJlcG9ydCBkaWZmZXJlbnQgbG9jYWwgdGltZXMgYW5kIGNvbnNpZGVyIERTVHMgd2hlbiBtYWtpbmcgY29tcHV0YXRpb25zLCBhcyB3aXRoIHtAbGluayBEYXRlVGltZSNwbHVzfS4gWW91IG1heSB3aXNoIHRvIHVzZSB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbH0gYW5kIHtAbGluayBEYXRlVGltZSN0b1VUQ30gd2hpY2ggcHJvdmlkZSBzaW1wbGUgY29udmVuaWVuY2Ugd3JhcHBlcnMgZm9yIGNvbW1vbmx5IHVzZWQgem9uZXMuXG4gICAqIEBwYXJhbSB7c3RyaW5nfFpvbmV9IFt6b25lPSdsb2NhbCddIC0gYSB6b25lIGlkZW50aWZpZXIuIEFzIGEgc3RyaW5nLCB0aGF0IGNhbiBiZSBhbnkgSUFOQSB6b25lIHN1cHBvcnRlZCBieSB0aGUgaG9zdCBlbnZpcm9ubWVudCwgb3IgYSBmaXhlZC1vZmZzZXQgbmFtZSBvZiB0aGUgZm9ybSAnVVRDKzMnLCBvciB0aGUgc3RyaW5ncyAnbG9jYWwnIG9yICd1dGMnLiBZb3UgbWF5IGFsc28gc3VwcGx5IGFuIGluc3RhbmNlIG9mIGEge0BsaW5rIERhdGVUaW1lI1pvbmV9IGNsYXNzLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnNcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5rZWVwTG9jYWxUaW1lPWZhbHNlXSAtIElmIHRydWUsIGFkanVzdCB0aGUgdW5kZXJseWluZyB0aW1lIHNvIHRoYXQgdGhlIGxvY2FsIHRpbWUgc3RheXMgdGhlIHNhbWUsIGJ1dCBpbiB0aGUgdGFyZ2V0IHpvbmUuIFlvdSBzaG91bGQgcmFyZWx5IG5lZWQgdGhpcy5cbiAgICogQHJldHVybiB7RGF0ZVRpbWV9XG4gICAqL1xuICBzZXRab25lKHpvbmUsIHsga2VlcExvY2FsVGltZSA9IGZhbHNlLCBrZWVwQ2FsZW5kYXJUaW1lID0gZmFsc2UgfSA9IHt9KSB7XG4gICAgem9uZSA9IG5vcm1hbGl6ZVpvbmUoem9uZSwgU2V0dGluZ3MuZGVmYXVsdFpvbmUpO1xuICAgIGlmICh6b25lLmVxdWFscyh0aGlzLnpvbmUpKSB7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9IGVsc2UgaWYgKCF6b25lLmlzVmFsaWQpIHtcbiAgICAgIHJldHVybiBEYXRlVGltZS5pbnZhbGlkKHVuc3VwcG9ydGVkWm9uZSh6b25lKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBuZXdUUyA9IHRoaXMudHM7XG4gICAgICBpZiAoa2VlcExvY2FsVGltZSB8fCBrZWVwQ2FsZW5kYXJUaW1lKSB7XG4gICAgICAgIGNvbnN0IG9mZnNldEd1ZXNzID0gem9uZS5vZmZzZXQodGhpcy50cyk7XG4gICAgICAgIGNvbnN0IGFzT2JqID0gdGhpcy50b09iamVjdCgpO1xuICAgICAgICBbbmV3VFNdID0gb2JqVG9UUyhhc09iaiwgb2Zmc2V0R3Vlc3MsIHpvbmUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNsb25lKHRoaXMsIHsgdHM6IG5ld1RTLCB6b25lIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBcIlNldFwiIHRoZSBsb2NhbGUsIG51bWJlcmluZ1N5c3RlbSwgb3Igb3V0cHV0Q2FsZW5kYXIuIFJldHVybnMgYSBuZXdseS1jb25zdHJ1Y3RlZCBEYXRlVGltZS5cbiAgICogQHBhcmFtIHtPYmplY3R9IHByb3BlcnRpZXMgLSB0aGUgcHJvcGVydGllcyB0byBzZXRcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgNSwgMjUpLnJlY29uZmlndXJlKHsgbG9jYWxlOiAnZW4tR0InIH0pXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgcmVjb25maWd1cmUoeyBsb2NhbGUsIG51bWJlcmluZ1N5c3RlbSwgb3V0cHV0Q2FsZW5kYXIgfSA9IHt9KSB7XG4gICAgY29uc3QgbG9jID0gdGhpcy5sb2MuY2xvbmUoeyBsb2NhbGUsIG51bWJlcmluZ1N5c3RlbSwgb3V0cHV0Q2FsZW5kYXIgfSk7XG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIHsgbG9jIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFwiU2V0XCIgdGhlIGxvY2FsZS4gUmV0dXJucyBhIG5ld2x5LWNvbnN0cnVjdGVkIERhdGVUaW1lLlxuICAgKiBKdXN0IGEgY29udmVuaWVudCBhbGlhcyBmb3IgcmVjb25maWd1cmUoeyBsb2NhbGUgfSlcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNywgNSwgMjUpLnNldExvY2FsZSgnZW4tR0InKVxuICAgKiBAcmV0dXJuIHtEYXRlVGltZX1cbiAgICovXG4gIHNldExvY2FsZShsb2NhbGUpIHtcbiAgICByZXR1cm4gdGhpcy5yZWNvbmZpZ3VyZSh7IGxvY2FsZSB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBcIlNldFwiIHRoZSB2YWx1ZXMgb2Ygc3BlY2lmaWVkIHVuaXRzLiBSZXR1cm5zIGEgbmV3bHktY29uc3RydWN0ZWQgRGF0ZVRpbWUuXG4gICAqIFlvdSBjYW4gb25seSBzZXQgdW5pdHMgd2l0aCB0aGlzIG1ldGhvZDsgZm9yIFwic2V0dGluZ1wiIG1ldGFkYXRhLCBzZWUge0BsaW5rIERhdGVUaW1lI3JlY29uZmlndXJlfSBhbmQge0BsaW5rIERhdGVUaW1lI3NldFpvbmV9LlxuICAgKiBAcGFyYW0ge09iamVjdH0gdmFsdWVzIC0gYSBtYXBwaW5nIG9mIHVuaXRzIHRvIG51bWJlcnNcbiAgICogQGV4YW1wbGUgZHQuc2V0KHsgeWVhcjogMjAxNyB9KVxuICAgKiBAZXhhbXBsZSBkdC5zZXQoeyBob3VyOiA4LCBtaW51dGU6IDMwIH0pXG4gICAqIEBleGFtcGxlIGR0LnNldCh7IHdlZWtkYXk6IDUgfSlcbiAgICogQGV4YW1wbGUgZHQuc2V0KHsgeWVhcjogMjAwNSwgb3JkaW5hbDogMjM0IH0pXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgc2V0KHZhbHVlcykge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gdGhpcztcblxuICAgIGNvbnN0IG5vcm1hbGl6ZWQgPSBub3JtYWxpemVPYmplY3QodmFsdWVzLCBub3JtYWxpemVVbml0KSxcbiAgICAgIHNldHRpbmdXZWVrU3R1ZmYgPVxuICAgICAgICAhaXNVbmRlZmluZWQobm9ybWFsaXplZC53ZWVrWWVhcikgfHxcbiAgICAgICAgIWlzVW5kZWZpbmVkKG5vcm1hbGl6ZWQud2Vla051bWJlcikgfHxcbiAgICAgICAgIWlzVW5kZWZpbmVkKG5vcm1hbGl6ZWQud2Vla2RheSksXG4gICAgICBjb250YWluc09yZGluYWwgPSAhaXNVbmRlZmluZWQobm9ybWFsaXplZC5vcmRpbmFsKSxcbiAgICAgIGNvbnRhaW5zR3JlZ29yWWVhciA9ICFpc1VuZGVmaW5lZChub3JtYWxpemVkLnllYXIpLFxuICAgICAgY29udGFpbnNHcmVnb3JNRCA9ICFpc1VuZGVmaW5lZChub3JtYWxpemVkLm1vbnRoKSB8fCAhaXNVbmRlZmluZWQobm9ybWFsaXplZC5kYXkpLFxuICAgICAgY29udGFpbnNHcmVnb3IgPSBjb250YWluc0dyZWdvclllYXIgfHwgY29udGFpbnNHcmVnb3JNRCxcbiAgICAgIGRlZmluaXRlV2Vla0RlZiA9IG5vcm1hbGl6ZWQud2Vla1llYXIgfHwgbm9ybWFsaXplZC53ZWVrTnVtYmVyO1xuXG4gICAgaWYgKChjb250YWluc0dyZWdvciB8fCBjb250YWluc09yZGluYWwpICYmIGRlZmluaXRlV2Vla0RlZikge1xuICAgICAgdGhyb3cgbmV3IENvbmZsaWN0aW5nU3BlY2lmaWNhdGlvbkVycm9yKFxuICAgICAgICBcIkNhbid0IG1peCB3ZWVrWWVhci93ZWVrTnVtYmVyIHVuaXRzIHdpdGggeWVhci9tb250aC9kYXkgb3Igb3JkaW5hbHNcIlxuICAgICAgKTtcbiAgICB9XG5cbiAgICBpZiAoY29udGFpbnNHcmVnb3JNRCAmJiBjb250YWluc09yZGluYWwpIHtcbiAgICAgIHRocm93IG5ldyBDb25mbGljdGluZ1NwZWNpZmljYXRpb25FcnJvcihcIkNhbid0IG1peCBvcmRpbmFsIGRhdGVzIHdpdGggbW9udGgvZGF5XCIpO1xuICAgIH1cblxuICAgIGxldCBtaXhlZDtcbiAgICBpZiAoc2V0dGluZ1dlZWtTdHVmZikge1xuICAgICAgbWl4ZWQgPSB3ZWVrVG9HcmVnb3JpYW4oeyAuLi5ncmVnb3JpYW5Ub1dlZWsodGhpcy5jKSwgLi4ubm9ybWFsaXplZCB9KTtcbiAgICB9IGVsc2UgaWYgKCFpc1VuZGVmaW5lZChub3JtYWxpemVkLm9yZGluYWwpKSB7XG4gICAgICBtaXhlZCA9IG9yZGluYWxUb0dyZWdvcmlhbih7IC4uLmdyZWdvcmlhblRvT3JkaW5hbCh0aGlzLmMpLCAuLi5ub3JtYWxpemVkIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBtaXhlZCA9IHsgLi4udGhpcy50b09iamVjdCgpLCAuLi5ub3JtYWxpemVkIH07XG5cbiAgICAgIC8vIGlmIHdlIGRpZG4ndCBzZXQgdGhlIGRheSBidXQgd2UgZW5kZWQgdXAgb24gYW4gb3ZlcmZsb3cgZGF0ZSxcbiAgICAgIC8vIHVzZSB0aGUgbGFzdCBkYXkgb2YgdGhlIHJpZ2h0IG1vbnRoXG4gICAgICBpZiAoaXNVbmRlZmluZWQobm9ybWFsaXplZC5kYXkpKSB7XG4gICAgICAgIG1peGVkLmRheSA9IE1hdGgubWluKGRheXNJbk1vbnRoKG1peGVkLnllYXIsIG1peGVkLm1vbnRoKSwgbWl4ZWQuZGF5KTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBbdHMsIG9dID0gb2JqVG9UUyhtaXhlZCwgdGhpcy5vLCB0aGlzLnpvbmUpO1xuICAgIHJldHVybiBjbG9uZSh0aGlzLCB7IHRzLCBvIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBhIHBlcmlvZCBvZiB0aW1lIHRvIHRoaXMgRGF0ZVRpbWUgYW5kIHJldHVybiB0aGUgcmVzdWx0aW5nIERhdGVUaW1lXG4gICAqXG4gICAqIEFkZGluZyBob3VycywgbWludXRlcywgc2Vjb25kcywgb3IgbWlsbGlzZWNvbmRzIGluY3JlYXNlcyB0aGUgdGltZXN0YW1wIGJ5IHRoZSByaWdodCBudW1iZXIgb2YgbWlsbGlzZWNvbmRzLiBBZGRpbmcgZGF5cywgbW9udGhzLCBvciB5ZWFycyBzaGlmdHMgdGhlIGNhbGVuZGFyLCBhY2NvdW50aW5nIGZvciBEU1RzIGFuZCBsZWFwIHllYXJzIGFsb25nIHRoZSB3YXkuIFRodXMsIGBkdC5wbHVzKHsgaG91cnM6IDI0IH0pYCBtYXkgcmVzdWx0IGluIGEgZGlmZmVyZW50IHRpbWUgdGhhbiBgZHQucGx1cyh7IGRheXM6IDEgfSlgIGlmIHRoZXJlJ3MgYSBEU1Qgc2hpZnQgaW4gYmV0d2Vlbi5cbiAgICogQHBhcmFtIHtEdXJhdGlvbnxPYmplY3R8bnVtYmVyfSBkdXJhdGlvbiAtIFRoZSBhbW91bnQgdG8gYWRkLiBFaXRoZXIgYSBMdXhvbiBEdXJhdGlvbiwgYSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzLCB0aGUgb2JqZWN0IGFyZ3VtZW50IHRvIER1cmF0aW9uLmZyb21PYmplY3QoKVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS5wbHVzKDEyMykgLy9+PiBpbiAxMjMgbWlsbGlzZWNvbmRzXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnBsdXMoeyBtaW51dGVzOiAxNSB9KSAvL34+IGluIDE1IG1pbnV0ZXNcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkucGx1cyh7IGRheXM6IDEgfSkgLy9+PiB0aGlzIHRpbWUgdG9tb3Jyb3dcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkucGx1cyh7IGRheXM6IC0xIH0pIC8vfj4gdGhpcyB0aW1lIHllc3RlcmRheVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS5wbHVzKHsgaG91cnM6IDMsIG1pbnV0ZXM6IDEzIH0pIC8vfj4gaW4gMyBociwgMTMgbWluXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnBsdXMoRHVyYXRpb24uZnJvbU9iamVjdCh7IGhvdXJzOiAzLCBtaW51dGVzOiAxMyB9KSkgLy9+PiBpbiAzIGhyLCAxMyBtaW5cbiAgICogQHJldHVybiB7RGF0ZVRpbWV9XG4gICAqL1xuICBwbHVzKGR1cmF0aW9uKSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiB0aGlzO1xuICAgIGNvbnN0IGR1ciA9IER1cmF0aW9uLmZyb21EdXJhdGlvbkxpa2UoZHVyYXRpb24pO1xuICAgIHJldHVybiBjbG9uZSh0aGlzLCBhZGp1c3RUaW1lKHRoaXMsIGR1cikpO1xuICB9XG5cbiAgLyoqXG4gICAqIFN1YnRyYWN0IGEgcGVyaW9kIG9mIHRpbWUgdG8gdGhpcyBEYXRlVGltZSBhbmQgcmV0dXJuIHRoZSByZXN1bHRpbmcgRGF0ZVRpbWVcbiAgICogU2VlIHtAbGluayBEYXRlVGltZSNwbHVzfVxuICAgKiBAcGFyYW0ge0R1cmF0aW9ufE9iamVjdHxudW1iZXJ9IGR1cmF0aW9uIC0gVGhlIGFtb3VudCB0byBzdWJ0cmFjdC4gRWl0aGVyIGEgTHV4b24gRHVyYXRpb24sIGEgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcywgdGhlIG9iamVjdCBhcmd1bWVudCB0byBEdXJhdGlvbi5mcm9tT2JqZWN0KClcbiAgIEByZXR1cm4ge0RhdGVUaW1lfVxuICAgKi9cbiAgbWludXMoZHVyYXRpb24pIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIHRoaXM7XG4gICAgY29uc3QgZHVyID0gRHVyYXRpb24uZnJvbUR1cmF0aW9uTGlrZShkdXJhdGlvbikubmVnYXRlKCk7XG4gICAgcmV0dXJuIGNsb25lKHRoaXMsIGFkanVzdFRpbWUodGhpcywgZHVyKSk7XG4gIH1cblxuICAvKipcbiAgICogXCJTZXRcIiB0aGlzIERhdGVUaW1lIHRvIHRoZSBiZWdpbm5pbmcgb2YgYSB1bml0IG9mIHRpbWUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1bml0IC0gVGhlIHVuaXQgdG8gZ28gdG8gdGhlIGJlZ2lubmluZyBvZi4gQ2FuIGJlICd5ZWFyJywgJ3F1YXJ0ZXInLCAnbW9udGgnLCAnd2VlaycsICdkYXknLCAnaG91cicsICdtaW51dGUnLCAnc2Vjb25kJywgb3IgJ21pbGxpc2Vjb25kJy5cbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNCwgMywgMykuc3RhcnRPZignbW9udGgnKS50b0lTT0RhdGUoKTsgLy89PiAnMjAxNC0wMy0wMSdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNCwgMywgMykuc3RhcnRPZigneWVhcicpLnRvSVNPRGF0ZSgpOyAvLz0+ICcyMDE0LTAxLTAxJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE0LCAzLCAzKS5zdGFydE9mKCd3ZWVrJykudG9JU09EYXRlKCk7IC8vPT4gJzIwMTQtMDMtMDMnLCB3ZWVrcyBhbHdheXMgc3RhcnQgb24gTW9uZGF5c1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE0LCAzLCAzLCA1LCAzMCkuc3RhcnRPZignZGF5JykudG9JU09UaW1lKCk7IC8vPT4gJzAwOjAwLjAwMC0wNTowMCdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNCwgMywgMywgNSwgMzApLnN0YXJ0T2YoJ2hvdXInKS50b0lTT1RpbWUoKTsgLy89PiAnMDU6MDA6MDAuMDAwLTA1OjAwJ1xuICAgKiBAcmV0dXJuIHtEYXRlVGltZX1cbiAgICovXG4gIHN0YXJ0T2YodW5pdCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gdGhpcztcbiAgICBjb25zdCBvID0ge30sXG4gICAgICBub3JtYWxpemVkVW5pdCA9IER1cmF0aW9uLm5vcm1hbGl6ZVVuaXQodW5pdCk7XG4gICAgc3dpdGNoIChub3JtYWxpemVkVW5pdCkge1xuICAgICAgY2FzZSBcInllYXJzXCI6XG4gICAgICAgIG8ubW9udGggPSAxO1xuICAgICAgLy8gZmFsbHMgdGhyb3VnaFxuICAgICAgY2FzZSBcInF1YXJ0ZXJzXCI6XG4gICAgICBjYXNlIFwibW9udGhzXCI6XG4gICAgICAgIG8uZGF5ID0gMTtcbiAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgIGNhc2UgXCJ3ZWVrc1wiOlxuICAgICAgY2FzZSBcImRheXNcIjpcbiAgICAgICAgby5ob3VyID0gMDtcbiAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgIGNhc2UgXCJob3Vyc1wiOlxuICAgICAgICBvLm1pbnV0ZSA9IDA7XG4gICAgICAvLyBmYWxscyB0aHJvdWdoXG4gICAgICBjYXNlIFwibWludXRlc1wiOlxuICAgICAgICBvLnNlY29uZCA9IDA7XG4gICAgICAvLyBmYWxscyB0aHJvdWdoXG4gICAgICBjYXNlIFwic2Vjb25kc1wiOlxuICAgICAgICBvLm1pbGxpc2Vjb25kID0gMDtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFwibWlsbGlzZWNvbmRzXCI6XG4gICAgICAgIGJyZWFrO1xuICAgICAgLy8gbm8gZGVmYXVsdCwgaW52YWxpZCB1bml0cyB0aHJvdyBpbiBub3JtYWxpemVVbml0KClcbiAgICB9XG5cbiAgICBpZiAobm9ybWFsaXplZFVuaXQgPT09IFwid2Vla3NcIikge1xuICAgICAgby53ZWVrZGF5ID0gMTtcbiAgICB9XG5cbiAgICBpZiAobm9ybWFsaXplZFVuaXQgPT09IFwicXVhcnRlcnNcIikge1xuICAgICAgY29uc3QgcSA9IE1hdGguY2VpbCh0aGlzLm1vbnRoIC8gMyk7XG4gICAgICBvLm1vbnRoID0gKHEgLSAxKSAqIDMgKyAxO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLnNldChvKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBcIlNldFwiIHRoaXMgRGF0ZVRpbWUgdG8gdGhlIGVuZCAobWVhbmluZyB0aGUgbGFzdCBtaWxsaXNlY29uZCkgb2YgYSB1bml0IG9mIHRpbWVcbiAgICogQHBhcmFtIHtzdHJpbmd9IHVuaXQgLSBUaGUgdW5pdCB0byBnbyB0byB0aGUgZW5kIG9mLiBDYW4gYmUgJ3llYXInLCAncXVhcnRlcicsICdtb250aCcsICd3ZWVrJywgJ2RheScsICdob3VyJywgJ21pbnV0ZScsICdzZWNvbmQnLCBvciAnbWlsbGlzZWNvbmQnLlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5sb2NhbCgyMDE0LCAzLCAzKS5lbmRPZignbW9udGgnKS50b0lTTygpOyAvLz0+ICcyMDE0LTAzLTMxVDIzOjU5OjU5Ljk5OS0wNTowMCdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNCwgMywgMykuZW5kT2YoJ3llYXInKS50b0lTTygpOyAvLz0+ICcyMDE0LTEyLTMxVDIzOjU5OjU5Ljk5OS0wNTowMCdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNCwgMywgMykuZW5kT2YoJ3dlZWsnKS50b0lTTygpOyAvLyA9PiAnMjAxNC0wMy0wOVQyMzo1OTo1OS45OTktMDU6MDAnLCB3ZWVrcyBzdGFydCBvbiBNb25kYXlzXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTQsIDMsIDMsIDUsIDMwKS5lbmRPZignZGF5JykudG9JU08oKTsgLy89PiAnMjAxNC0wMy0wM1QyMzo1OTo1OS45OTktMDU6MDAnXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTQsIDMsIDMsIDUsIDMwKS5lbmRPZignaG91cicpLnRvSVNPKCk7IC8vPT4gJzIwMTQtMDMtMDNUMDU6NTk6NTkuOTk5LTA1OjAwJ1xuICAgKiBAcmV0dXJuIHtEYXRlVGltZX1cbiAgICovXG4gIGVuZE9mKHVuaXQpIHtcbiAgICByZXR1cm4gdGhpcy5pc1ZhbGlkXG4gICAgICA/IHRoaXMucGx1cyh7IFt1bml0XTogMSB9KVxuICAgICAgICAgIC5zdGFydE9mKHVuaXQpXG4gICAgICAgICAgLm1pbnVzKDEpXG4gICAgICA6IHRoaXM7XG4gIH1cblxuICAvLyBPVVRQVVRcblxuICAvKipcbiAgICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIERhdGVUaW1lIGZvcm1hdHRlZCBhY2NvcmRpbmcgdG8gdGhlIHNwZWNpZmllZCBmb3JtYXQgc3RyaW5nLlxuICAgKiAqKllvdSBtYXkgbm90IHdhbnQgdGhpcy4qKiBTZWUge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3IgYSBtb3JlIGZsZXhpYmxlIGZvcm1hdHRpbmcgdG9vbC4gRm9yIGEgdGFibGUgb2YgdG9rZW5zIGFuZCB0aGVpciBpbnRlcnByZXRhdGlvbnMsIHNlZSBbaGVyZV0oaHR0cHM6Ly9tb21lbnQuZ2l0aHViLmlvL2x1eG9uLyMvZm9ybWF0dGluZz9pZD10YWJsZS1vZi10b2tlbnMpLlxuICAgKiBEZWZhdWx0cyB0byBlbi1VUyBpZiBubyBsb2NhbGUgaGFzIGJlZW4gc3BlY2lmaWVkLCByZWdhcmRsZXNzIG9mIHRoZSBzeXN0ZW0ncyBsb2NhbGUuXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBmbXQgLSB0aGUgZm9ybWF0IHN0cmluZ1xuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdHMgdG8gb3ZlcnJpZGUgdGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBvbiB0aGlzIERhdGVUaW1lXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnRvRm9ybWF0KCd5eXl5IExMTCBkZCcpIC8vPT4gJzIwMTcgQXByIDIyJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS5zZXRMb2NhbGUoJ2ZyJykudG9Gb3JtYXQoJ3l5eXkgTExMIGRkJykgLy89PiAnMjAxNyBhdnIuIDIyJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS50b0Zvcm1hdCgneXl5eSBMTEwgZGQnLCB7IGxvY2FsZTogXCJmclwiIH0pIC8vPT4gJzIwMTcgYXZyLiAyMidcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkudG9Gb3JtYXQoXCJISCAnaG91cnMgYW5kJyBtbSAnbWludXRlcydcIikgLy89PiAnMjAgaG91cnMgYW5kIDU1IG1pbnV0ZXMnXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIHRvRm9ybWF0KGZtdCwgb3B0cyA9IHt9KSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZFxuICAgICAgPyBGb3JtYXR0ZXIuY3JlYXRlKHRoaXMubG9jLnJlZGVmYXVsdFRvRU4ob3B0cykpLmZvcm1hdERhdGVUaW1lRnJvbVN0cmluZyh0aGlzLCBmbXQpXG4gICAgICA6IElOVkFMSUQ7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGxvY2FsaXplZCBzdHJpbmcgcmVwcmVzZW50aW5nIHRoaXMgZGF0ZS4gQWNjZXB0cyB0aGUgc2FtZSBvcHRpb25zIGFzIHRoZSBJbnRsLkRhdGVUaW1lRm9ybWF0IGNvbnN0cnVjdG9yIGFuZCBhbnkgcHJlc2V0cyBkZWZpbmVkIGJ5IEx1eG9uLCBzdWNoIGFzIGBEYXRlVGltZS5EQVRFX0ZVTExgIG9yIGBEYXRlVGltZS5USU1FX1NJTVBMRWAuXG4gICAqIFRoZSBleGFjdCBiZWhhdmlvciBvZiB0aGlzIG1ldGhvZCBpcyBicm93c2VyLXNwZWNpZmljLCBidXQgaW4gZ2VuZXJhbCBpdCB3aWxsIHJldHVybiBhbiBhcHByb3ByaWF0ZSByZXByZXNlbnRhdGlvblxuICAgKiBvZiB0aGUgRGF0ZVRpbWUgaW4gdGhlIGFzc2lnbmVkIGxvY2FsZS5cbiAgICogRGVmYXVsdHMgdG8gdGhlIHN5c3RlbSdzIGxvY2FsZSBpZiBubyBsb2NhbGUgaGFzIGJlZW4gc3BlY2lmaWVkXG4gICAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRGF0ZVRpbWVGb3JtYXRcbiAgICogQHBhcmFtIGZvcm1hdE9wdHMge09iamVjdH0gLSBJbnRsLkRhdGVUaW1lRm9ybWF0IGNvbnN0cnVjdG9yIG9wdGlvbnMgYW5kIGNvbmZpZ3VyYXRpb24gb3B0aW9uc1xuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdHMgdG8gb3ZlcnJpZGUgdGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyBvbiB0aGlzIERhdGVUaW1lXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnRvTG9jYWxlU3RyaW5nKCk7IC8vPT4gNC8yMC8yMDE3XG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnNldExvY2FsZSgnZW4tZ2InKS50b0xvY2FsZVN0cmluZygpOyAvLz0+ICcyMC8wNC8yMDE3J1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS50b0xvY2FsZVN0cmluZyhEYXRlVGltZS5EQVRFX0ZVTEwpOyAvLz0+ICdBcHJpbCAyMCwgMjAxNydcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkudG9Mb2NhbGVTdHJpbmcoRGF0ZVRpbWUuREFURV9GVUxMLCB7IGxvY2FsZTogJ2ZyJyB9KTsgLy89PiAnMjggYW9cdTAwRkJ0IDIwMjInXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnRvTG9jYWxlU3RyaW5nKERhdGVUaW1lLlRJTUVfU0lNUExFKTsgLy89PiAnMTE6MzIgQU0nXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnRvTG9jYWxlU3RyaW5nKERhdGVUaW1lLkRBVEVUSU1FX1NIT1JUKTsgLy89PiAnNC8yMC8yMDE3LCAxMTozMiBBTSdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkudG9Mb2NhbGVTdHJpbmcoeyB3ZWVrZGF5OiAnbG9uZycsIG1vbnRoOiAnbG9uZycsIGRheTogJzItZGlnaXQnIH0pOyAvLz0+ICdUaHVyc2RheSwgQXByaWwgMjAnXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnRvTG9jYWxlU3RyaW5nKHsgd2Vla2RheTogJ3Nob3J0JywgbW9udGg6ICdzaG9ydCcsIGRheTogJzItZGlnaXQnLCBob3VyOiAnMi1kaWdpdCcsIG1pbnV0ZTogJzItZGlnaXQnIH0pOyAvLz0+ICdUaHUsIEFwciAyMCwgMTE6MjcgQU0nXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnRvTG9jYWxlU3RyaW5nKHsgaG91cjogJzItZGlnaXQnLCBtaW51dGU6ICcyLWRpZ2l0JywgaG91ckN5Y2xlOiAnaDIzJyB9KTsgLy89PiAnMTE6MzInXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIHRvTG9jYWxlU3RyaW5nKGZvcm1hdE9wdHMgPSBGb3JtYXRzLkRBVEVfU0hPUlQsIG9wdHMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWRcbiAgICAgID8gRm9ybWF0dGVyLmNyZWF0ZSh0aGlzLmxvYy5jbG9uZShvcHRzKSwgZm9ybWF0T3B0cykuZm9ybWF0RGF0ZVRpbWUodGhpcylcbiAgICAgIDogSU5WQUxJRDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIGFycmF5IG9mIGZvcm1hdCBcInBhcnRzXCIsIG1lYW5pbmcgaW5kaXZpZHVhbCB0b2tlbnMgYWxvbmcgd2l0aCBtZXRhZGF0YS4gVGhpcyBpcyBhbGxvd3MgY2FsbGVycyB0byBwb3N0LXByb2Nlc3MgaW5kaXZpZHVhbCBzZWN0aW9ucyBvZiB0aGUgZm9ybWF0dGVkIG91dHB1dC5cbiAgICogRGVmYXVsdHMgdG8gdGhlIHN5c3RlbSdzIGxvY2FsZSBpZiBubyBsb2NhbGUgaGFzIGJlZW4gc3BlY2lmaWVkXG4gICAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvRGF0ZVRpbWVGb3JtYXQvZm9ybWF0VG9QYXJ0c1xuICAgKiBAcGFyYW0gb3B0cyB7T2JqZWN0fSAtIEludGwuRGF0ZVRpbWVGb3JtYXQgY29uc3RydWN0b3Igb3B0aW9ucywgc2FtZSBhcyBgdG9Mb2NhbGVTdHJpbmdgLlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS50b0xvY2FsZVBhcnRzKCk7IC8vPT4gW1xuICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy89PiAgIHsgdHlwZTogJ2RheScsIHZhbHVlOiAnMjUnIH0sXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLz0+ICAgeyB0eXBlOiAnbGl0ZXJhbCcsIHZhbHVlOiAnLycgfSxcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vPT4gICB7IHR5cGU6ICdtb250aCcsIHZhbHVlOiAnMDUnIH0sXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLz0+ICAgeyB0eXBlOiAnbGl0ZXJhbCcsIHZhbHVlOiAnLycgfSxcbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vPT4gICB7IHR5cGU6ICd5ZWFyJywgdmFsdWU6ICcxOTgyJyB9XG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLz0+IF1cbiAgICovXG4gIHRvTG9jYWxlUGFydHMob3B0cyA9IHt9KSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZFxuICAgICAgPyBGb3JtYXR0ZXIuY3JlYXRlKHRoaXMubG9jLmNsb25lKG9wdHMpLCBvcHRzKS5mb3JtYXREYXRlVGltZVBhcnRzKHRoaXMpXG4gICAgICA6IFtdO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gSVNPIDg2MDEtY29tcGxpYW50IHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIERhdGVUaW1lXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRzLnN1cHByZXNzTWlsbGlzZWNvbmRzPWZhbHNlXSAtIGV4Y2x1ZGUgbWlsbGlzZWNvbmRzIGZyb20gdGhlIGZvcm1hdCBpZiB0aGV5J3JlIDBcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5zdXBwcmVzc1NlY29uZHM9ZmFsc2VdIC0gZXhjbHVkZSBzZWNvbmRzIGZyb20gdGhlIGZvcm1hdCBpZiB0aGV5J3JlIDBcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5pbmNsdWRlT2Zmc2V0PXRydWVdIC0gaW5jbHVkZSB0aGUgb2Zmc2V0LCBzdWNoIGFzICdaJyBvciAnLTA0OjAwJ1xuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRzLmV4dGVuZGVkWm9uZT1mYWxzZV0gLSBhZGQgdGhlIHRpbWUgem9uZSBmb3JtYXQgZXh0ZW5zaW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5mb3JtYXQ9J2V4dGVuZGVkJ10gLSBjaG9vc2UgYmV0d2VlbiB0aGUgYmFzaWMgYW5kIGV4dGVuZGVkIGZvcm1hdFxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoMTk4MywgNSwgMjUpLnRvSVNPKCkgLy89PiAnMTk4Mi0wNS0yNVQwMDowMDowMC4wMDBaJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS50b0lTTygpIC8vPT4gJzIwMTctMDQtMjJUMjA6NDc6MDUuMzM1LTA0OjAwJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS50b0lTTyh7IGluY2x1ZGVPZmZzZXQ6IGZhbHNlIH0pIC8vPT4gJzIwMTctMDQtMjJUMjA6NDc6MDUuMzM1J1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS50b0lTTyh7IGZvcm1hdDogJ2Jhc2ljJyB9KSAvLz0+ICcyMDE3MDQyMlQyMDQ3MDUuMzM1LTA0MDAnXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIHRvSVNPKHtcbiAgICBmb3JtYXQgPSBcImV4dGVuZGVkXCIsXG4gICAgc3VwcHJlc3NTZWNvbmRzID0gZmFsc2UsXG4gICAgc3VwcHJlc3NNaWxsaXNlY29uZHMgPSBmYWxzZSxcbiAgICBpbmNsdWRlT2Zmc2V0ID0gdHJ1ZSxcbiAgICBleHRlbmRlZFpvbmUgPSBmYWxzZSxcbiAgfSA9IHt9KSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGV4dCA9IGZvcm1hdCA9PT0gXCJleHRlbmRlZFwiO1xuXG4gICAgbGV0IGMgPSB0b0lTT0RhdGUodGhpcywgZXh0KTtcbiAgICBjICs9IFwiVFwiO1xuICAgIGMgKz0gdG9JU09UaW1lKHRoaXMsIGV4dCwgc3VwcHJlc3NTZWNvbmRzLCBzdXBwcmVzc01pbGxpc2Vjb25kcywgaW5jbHVkZU9mZnNldCwgZXh0ZW5kZWRab25lKTtcbiAgICByZXR1cm4gYztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIElTTyA4NjAxLWNvbXBsaWFudCBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBEYXRlVGltZSdzIGRhdGUgY29tcG9uZW50XG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9uc1xuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMuZm9ybWF0PSdleHRlbmRlZCddIC0gY2hvb3NlIGJldHdlZW4gdGhlIGJhc2ljIGFuZCBleHRlbmRlZCBmb3JtYXRcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUudXRjKDE5ODIsIDUsIDI1KS50b0lTT0RhdGUoKSAvLz0+ICcxOTgyLTA1LTI1J1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoMTk4MiwgNSwgMjUpLnRvSVNPRGF0ZSh7IGZvcm1hdDogJ2Jhc2ljJyB9KSAvLz0+ICcxOTgyMDUyNSdcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgdG9JU09EYXRlKHsgZm9ybWF0ID0gXCJleHRlbmRlZFwiIH0gPSB7fSkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gdG9JU09EYXRlKHRoaXMsIGZvcm1hdCA9PT0gXCJleHRlbmRlZFwiKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIElTTyA4NjAxLWNvbXBsaWFudCBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBEYXRlVGltZSdzIHdlZWsgZGF0ZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoMTk4MiwgNSwgMjUpLnRvSVNPV2Vla0RhdGUoKSAvLz0+ICcxOTgyLVcyMS0yJ1xuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b0lTT1dlZWtEYXRlKCkge1xuICAgIHJldHVybiB0b1RlY2hGb3JtYXQodGhpcywgXCJra2trLSdXJ1dXLWNcIik7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhbiBJU08gODYwMS1jb21wbGlhbnQgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRGF0ZVRpbWUncyB0aW1lIGNvbXBvbmVudFxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnNcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5zdXBwcmVzc01pbGxpc2Vjb25kcz1mYWxzZV0gLSBleGNsdWRlIG1pbGxpc2Vjb25kcyBmcm9tIHRoZSBmb3JtYXQgaWYgdGhleSdyZSAwXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuc3VwcHJlc3NTZWNvbmRzPWZhbHNlXSAtIGV4Y2x1ZGUgc2Vjb25kcyBmcm9tIHRoZSBmb3JtYXQgaWYgdGhleSdyZSAwXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuaW5jbHVkZU9mZnNldD10cnVlXSAtIGluY2x1ZGUgdGhlIG9mZnNldCwgc3VjaCBhcyAnWicgb3IgJy0wNDowMCdcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5leHRlbmRlZFpvbmU9dHJ1ZV0gLSBhZGQgdGhlIHRpbWUgem9uZSBmb3JtYXQgZXh0ZW5zaW9uXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuaW5jbHVkZVByZWZpeD1mYWxzZV0gLSBpbmNsdWRlIHRoZSBgVGAgcHJlZml4XG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5mb3JtYXQ9J2V4dGVuZGVkJ10gLSBjaG9vc2UgYmV0d2VlbiB0aGUgYmFzaWMgYW5kIGV4dGVuZGVkIGZvcm1hdFxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoKS5zZXQoeyBob3VyOiA3LCBtaW51dGU6IDM0IH0pLnRvSVNPVGltZSgpIC8vPT4gJzA3OjM0OjE5LjM2MVonXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLnV0YygpLnNldCh7IGhvdXI6IDcsIG1pbnV0ZTogMzQsIHNlY29uZHM6IDAsIG1pbGxpc2Vjb25kczogMCB9KS50b0lTT1RpbWUoeyBzdXBwcmVzc1NlY29uZHM6IHRydWUgfSkgLy89PiAnMDc6MzRaJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoKS5zZXQoeyBob3VyOiA3LCBtaW51dGU6IDM0IH0pLnRvSVNPVGltZSh7IGZvcm1hdDogJ2Jhc2ljJyB9KSAvLz0+ICcwNzM0MTkuMzYxWidcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUudXRjKCkuc2V0KHsgaG91cjogNywgbWludXRlOiAzNCB9KS50b0lTT1RpbWUoeyBpbmNsdWRlUHJlZml4OiB0cnVlIH0pIC8vPT4gJ1QwNzozNDoxOS4zNjFaJ1xuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b0lTT1RpbWUoe1xuICAgIHN1cHByZXNzTWlsbGlzZWNvbmRzID0gZmFsc2UsXG4gICAgc3VwcHJlc3NTZWNvbmRzID0gZmFsc2UsXG4gICAgaW5jbHVkZU9mZnNldCA9IHRydWUsXG4gICAgaW5jbHVkZVByZWZpeCA9IGZhbHNlLFxuICAgIGV4dGVuZGVkWm9uZSA9IGZhbHNlLFxuICAgIGZvcm1hdCA9IFwiZXh0ZW5kZWRcIixcbiAgfSA9IHt9KSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGxldCBjID0gaW5jbHVkZVByZWZpeCA/IFwiVFwiIDogXCJcIjtcbiAgICByZXR1cm4gKFxuICAgICAgYyArXG4gICAgICB0b0lTT1RpbWUoXG4gICAgICAgIHRoaXMsXG4gICAgICAgIGZvcm1hdCA9PT0gXCJleHRlbmRlZFwiLFxuICAgICAgICBzdXBwcmVzc1NlY29uZHMsXG4gICAgICAgIHN1cHByZXNzTWlsbGlzZWNvbmRzLFxuICAgICAgICBpbmNsdWRlT2Zmc2V0LFxuICAgICAgICBleHRlbmRlZFpvbmVcbiAgICAgIClcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gUkZDIDI4MjItY29tcGF0aWJsZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBEYXRlVGltZVxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoMjAxNCwgNywgMTMpLnRvUkZDMjgyMigpIC8vPT4gJ1N1biwgMTMgSnVsIDIwMTQgMDA6MDA6MDAgKzAwMDAnXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTQsIDcsIDEzKS50b1JGQzI4MjIoKSAvLz0+ICdTdW4sIDEzIEp1bCAyMDE0IDAwOjAwOjAwIC0wNDAwJ1xuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b1JGQzI4MjIoKSB7XG4gICAgcmV0dXJuIHRvVGVjaEZvcm1hdCh0aGlzLCBcIkVFRSwgZGQgTExMIHl5eXkgSEg6bW06c3MgWlpaXCIsIGZhbHNlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRGF0ZVRpbWUgYXBwcm9wcmlhdGUgZm9yIHVzZSBpbiBIVFRQIGhlYWRlcnMuIFRoZSBvdXRwdXQgaXMgYWx3YXlzIGV4cHJlc3NlZCBpbiBHTVQuXG4gICAqIFNwZWNpZmljYWxseSwgdGhlIHN0cmluZyBjb25mb3JtcyB0byBSRkMgMTEyMy5cbiAgICogQHNlZSBodHRwczovL3d3dy53My5vcmcvUHJvdG9jb2xzL3JmYzI2MTYvcmZjMjYxNi1zZWMzLmh0bWwjc2VjMy4zLjFcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUudXRjKDIwMTQsIDcsIDEzKS50b0hUVFAoKSAvLz0+ICdTdW4sIDEzIEp1bCAyMDE0IDAwOjAwOjAwIEdNVCdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUudXRjKDIwMTQsIDcsIDEzLCAxOSkudG9IVFRQKCkgLy89PiAnU3VuLCAxMyBKdWwgMjAxNCAxOTowMDowMCBHTVQnXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIHRvSFRUUCgpIHtcbiAgICByZXR1cm4gdG9UZWNoRm9ybWF0KHRoaXMudG9VVEMoKSwgXCJFRUUsIGRkIExMTCB5eXl5IEhIOm1tOnNzICdHTVQnXCIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBEYXRlVGltZSBhcHByb3ByaWF0ZSBmb3IgdXNlIGluIFNRTCBEYXRlXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLnV0YygyMDE0LCA3LCAxMykudG9TUUxEYXRlKCkgLy89PiAnMjAxNC0wNy0xMydcbiAgICogQHJldHVybiB7c3RyaW5nfVxuICAgKi9cbiAgdG9TUUxEYXRlKCkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIHRvSVNPRGF0ZSh0aGlzLCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRGF0ZVRpbWUgYXBwcm9wcmlhdGUgZm9yIHVzZSBpbiBTUUwgVGltZVxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnNcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5pbmNsdWRlWm9uZT1mYWxzZV0gLSBpbmNsdWRlIHRoZSB6b25lLCBzdWNoIGFzICdBbWVyaWNhL05ld19Zb3JrJy4gT3ZlcnJpZGVzIGluY2x1ZGVPZmZzZXQuXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuaW5jbHVkZU9mZnNldD10cnVlXSAtIGluY2x1ZGUgdGhlIG9mZnNldCwgc3VjaCBhcyAnWicgb3IgJy0wNDowMCdcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5pbmNsdWRlT2Zmc2V0U3BhY2U9dHJ1ZV0gLSBpbmNsdWRlIHRoZSBzcGFjZSBiZXR3ZWVuIHRoZSB0aW1lIGFuZCB0aGUgb2Zmc2V0LCBzdWNoIGFzICcwNToxNToxNi4zNDUgLTA0OjAwJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS51dGMoKS50b1NRTCgpIC8vPT4gJzA1OjE1OjE2LjM0NSdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkudG9TUUwoKSAvLz0+ICcwNToxNToxNi4zNDUgLTA0OjAwJ1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS50b1NRTCh7IGluY2x1ZGVPZmZzZXQ6IGZhbHNlIH0pIC8vPT4gJzA1OjE1OjE2LjM0NSdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkudG9TUUwoeyBpbmNsdWRlWm9uZTogZmFsc2UgfSkgLy89PiAnMDU6MTU6MTYuMzQ1IEFtZXJpY2EvTmV3X1lvcmsnXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIHRvU1FMVGltZSh7IGluY2x1ZGVPZmZzZXQgPSB0cnVlLCBpbmNsdWRlWm9uZSA9IGZhbHNlLCBpbmNsdWRlT2Zmc2V0U3BhY2UgPSB0cnVlIH0gPSB7fSkge1xuICAgIGxldCBmbXQgPSBcIkhIOm1tOnNzLlNTU1wiO1xuXG4gICAgaWYgKGluY2x1ZGVab25lIHx8IGluY2x1ZGVPZmZzZXQpIHtcbiAgICAgIGlmIChpbmNsdWRlT2Zmc2V0U3BhY2UpIHtcbiAgICAgICAgZm10ICs9IFwiIFwiO1xuICAgICAgfVxuICAgICAgaWYgKGluY2x1ZGVab25lKSB7XG4gICAgICAgIGZtdCArPSBcInpcIjtcbiAgICAgIH0gZWxzZSBpZiAoaW5jbHVkZU9mZnNldCkge1xuICAgICAgICBmbXQgKz0gXCJaWlwiO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0b1RlY2hGb3JtYXQodGhpcywgZm10LCB0cnVlKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRGF0ZVRpbWUgYXBwcm9wcmlhdGUgZm9yIHVzZSBpbiBTUUwgRGF0ZVRpbWVcbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdHMgLSBvcHRpb25zXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuaW5jbHVkZVpvbmU9ZmFsc2VdIC0gaW5jbHVkZSB0aGUgem9uZSwgc3VjaCBhcyAnQW1lcmljYS9OZXdfWW9yaycuIE92ZXJyaWRlcyBpbmNsdWRlT2Zmc2V0LlxuICAgKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRzLmluY2x1ZGVPZmZzZXQ9dHJ1ZV0gLSBpbmNsdWRlIHRoZSBvZmZzZXQsIHN1Y2ggYXMgJ1onIG9yICctMDQ6MDAnXG4gICAqIEBwYXJhbSB7Ym9vbGVhbn0gW29wdHMuaW5jbHVkZU9mZnNldFNwYWNlPXRydWVdIC0gaW5jbHVkZSB0aGUgc3BhY2UgYmV0d2VlbiB0aGUgdGltZSBhbmQgdGhlIG9mZnNldCwgc3VjaCBhcyAnMDU6MTU6MTYuMzQ1IC0wNDowMCdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUudXRjKDIwMTQsIDcsIDEzKS50b1NRTCgpIC8vPT4gJzIwMTQtMDctMTMgMDA6MDA6MDAuMDAwIFonXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTQsIDcsIDEzKS50b1NRTCgpIC8vPT4gJzIwMTQtMDctMTMgMDA6MDA6MDAuMDAwIC0wNDowMCdcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubG9jYWwoMjAxNCwgNywgMTMpLnRvU1FMKHsgaW5jbHVkZU9mZnNldDogZmFsc2UgfSkgLy89PiAnMjAxNC0wNy0xMyAwMDowMDowMC4wMDAnXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLmxvY2FsKDIwMTQsIDcsIDEzKS50b1NRTCh7IGluY2x1ZGVab25lOiB0cnVlIH0pIC8vPT4gJzIwMTQtMDctMTMgMDA6MDA6MDAuMDAwIEFtZXJpY2EvTmV3X1lvcmsnXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIHRvU1FMKG9wdHMgPSB7fSkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSB7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICByZXR1cm4gYCR7dGhpcy50b1NRTERhdGUoKX0gJHt0aGlzLnRvU1FMVGltZShvcHRzKX1gO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBzdHJpbmcgcmVwcmVzZW50YXRpb24gb2YgdGhpcyBEYXRlVGltZSBhcHByb3ByaWF0ZSBmb3IgZGVidWdnaW5nXG4gICAqIEByZXR1cm4ge3N0cmluZ31cbiAgICovXG4gIHRvU3RyaW5nKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyB0aGlzLnRvSVNPKCkgOiBJTlZBTElEO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGVwb2NoIG1pbGxpc2Vjb25kcyBvZiB0aGlzIERhdGVUaW1lLiBBbGlhcyBvZiB7QGxpbmsgRGF0ZVRpbWUjdG9NaWxsaXN9XG4gICAqIEByZXR1cm4ge251bWJlcn1cbiAgICovXG4gIHZhbHVlT2YoKSB7XG4gICAgcmV0dXJuIHRoaXMudG9NaWxsaXMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBlcG9jaCBtaWxsaXNlY29uZHMgb2YgdGhpcyBEYXRlVGltZS5cbiAgICogQHJldHVybiB7bnVtYmVyfVxuICAgKi9cbiAgdG9NaWxsaXMoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMudHMgOiBOYU47XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgZXBvY2ggc2Vjb25kcyBvZiB0aGlzIERhdGVUaW1lLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9XG4gICAqL1xuICB0b1NlY29uZHMoKSB7XG4gICAgcmV0dXJuIHRoaXMuaXNWYWxpZCA/IHRoaXMudHMgLyAxMDAwIDogTmFOO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGVwb2NoIHNlY29uZHMgKGFzIGEgd2hvbGUgbnVtYmVyKSBvZiB0aGlzIERhdGVUaW1lLlxuICAgKiBAcmV0dXJuIHtudW1iZXJ9XG4gICAqL1xuICB0b1VuaXhJbnRlZ2VyKCkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyBNYXRoLmZsb29yKHRoaXMudHMgLyAxMDAwKSA6IE5hTjtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGFuIElTTyA4NjAxIHJlcHJlc2VudGF0aW9uIG9mIHRoaXMgRGF0ZVRpbWUgYXBwcm9wcmlhdGUgZm9yIHVzZSBpbiBKU09OLlxuICAgKiBAcmV0dXJuIHtzdHJpbmd9XG4gICAqL1xuICB0b0pTT04oKSB7XG4gICAgcmV0dXJuIHRoaXMudG9JU08oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgQlNPTiBzZXJpYWxpemFibGUgZXF1aXZhbGVudCB0byB0aGlzIERhdGVUaW1lLlxuICAgKiBAcmV0dXJuIHtEYXRlfVxuICAgKi9cbiAgdG9CU09OKCkge1xuICAgIHJldHVybiB0aGlzLnRvSlNEYXRlKCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIEphdmFTY3JpcHQgb2JqZWN0IHdpdGggdGhpcyBEYXRlVGltZSdzIHllYXIsIG1vbnRoLCBkYXksIGFuZCBzbyBvbi5cbiAgICogQHBhcmFtIG9wdHMgLSBvcHRpb25zIGZvciBnZW5lcmF0aW5nIHRoZSBvYmplY3RcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0cy5pbmNsdWRlQ29uZmlnPWZhbHNlXSAtIGluY2x1ZGUgY29uZmlndXJhdGlvbiBhdHRyaWJ1dGVzIGluIHRoZSBvdXRwdXRcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkudG9PYmplY3QoKSAvLz0+IHsgeWVhcjogMjAxNywgbW9udGg6IDQsIGRheTogMjIsIGhvdXI6IDIwLCBtaW51dGU6IDQ5LCBzZWNvbmQ6IDQyLCBtaWxsaXNlY29uZDogMjY4IH1cbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cbiAgdG9PYmplY3Qob3B0cyA9IHt9KSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiB7fTtcblxuICAgIGNvbnN0IGJhc2UgPSB7IC4uLnRoaXMuYyB9O1xuXG4gICAgaWYgKG9wdHMuaW5jbHVkZUNvbmZpZykge1xuICAgICAgYmFzZS5vdXRwdXRDYWxlbmRhciA9IHRoaXMub3V0cHV0Q2FsZW5kYXI7XG4gICAgICBiYXNlLm51bWJlcmluZ1N5c3RlbSA9IHRoaXMubG9jLm51bWJlcmluZ1N5c3RlbTtcbiAgICAgIGJhc2UubG9jYWxlID0gdGhpcy5sb2MubG9jYWxlO1xuICAgIH1cbiAgICByZXR1cm4gYmFzZTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgSmF2YVNjcmlwdCBEYXRlIGVxdWl2YWxlbnQgdG8gdGhpcyBEYXRlVGltZS5cbiAgICogQHJldHVybiB7RGF0ZX1cbiAgICovXG4gIHRvSlNEYXRlKCkge1xuICAgIHJldHVybiBuZXcgRGF0ZSh0aGlzLmlzVmFsaWQgPyB0aGlzLnRzIDogTmFOKTtcbiAgfVxuXG4gIC8vIENPTVBBUkVcblxuICAvKipcbiAgICogUmV0dXJuIHRoZSBkaWZmZXJlbmNlIGJldHdlZW4gdHdvIERhdGVUaW1lcyBhcyBhIER1cmF0aW9uLlxuICAgKiBAcGFyYW0ge0RhdGVUaW1lfSBvdGhlckRhdGVUaW1lIC0gdGhlIERhdGVUaW1lIHRvIGNvbXBhcmUgdGhpcyBvbmUgdG9cbiAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IFt1bml0PVsnbWlsbGlzZWNvbmRzJ11dIC0gdGhlIHVuaXQgb3IgYXJyYXkgb2YgdW5pdHMgKHN1Y2ggYXMgJ2hvdXJzJyBvciAnZGF5cycpIHRvIGluY2x1ZGUgaW4gdGhlIGR1cmF0aW9uLlxuICAgKiBAcGFyYW0ge09iamVjdH0gb3B0cyAtIG9wdGlvbnMgdGhhdCBhZmZlY3QgdGhlIGNyZWF0aW9uIG9mIHRoZSBEdXJhdGlvblxuICAgKiBAcGFyYW0ge3N0cmluZ30gW29wdHMuY29udmVyc2lvbkFjY3VyYWN5PSdjYXN1YWwnXSAtIHRoZSBjb252ZXJzaW9uIHN5c3RlbSB0byB1c2VcbiAgICogQGV4YW1wbGVcbiAgICogdmFyIGkxID0gRGF0ZVRpbWUuZnJvbUlTTygnMTk4Mi0wNS0yNVQwOTo0NScpLFxuICAgKiAgICAgaTIgPSBEYXRlVGltZS5mcm9tSVNPKCcxOTgzLTEwLTE0VDEwOjMwJyk7XG4gICAqIGkyLmRpZmYoaTEpLnRvT2JqZWN0KCkgLy89PiB7IG1pbGxpc2Vjb25kczogNDM4MDc1MDAwMDAgfVxuICAgKiBpMi5kaWZmKGkxLCAnaG91cnMnKS50b09iamVjdCgpIC8vPT4geyBob3VyczogMTIxNjguNzUgfVxuICAgKiBpMi5kaWZmKGkxLCBbJ21vbnRocycsICdkYXlzJ10pLnRvT2JqZWN0KCkgLy89PiB7IG1vbnRoczogMTYsIGRheXM6IDE5LjAzMTI1IH1cbiAgICogaTIuZGlmZihpMSwgWydtb250aHMnLCAnZGF5cycsICdob3VycyddKS50b09iamVjdCgpIC8vPT4geyBtb250aHM6IDE2LCBkYXlzOiAxOSwgaG91cnM6IDAuNzUgfVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIGRpZmYob3RoZXJEYXRlVGltZSwgdW5pdCA9IFwibWlsbGlzZWNvbmRzXCIsIG9wdHMgPSB7fSkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkIHx8ICFvdGhlckRhdGVUaW1lLmlzVmFsaWQpIHtcbiAgICAgIHJldHVybiBEdXJhdGlvbi5pbnZhbGlkKFwiY3JlYXRlZCBieSBkaWZmaW5nIGFuIGludmFsaWQgRGF0ZVRpbWVcIik7XG4gICAgfVxuXG4gICAgY29uc3QgZHVyT3B0cyA9IHsgbG9jYWxlOiB0aGlzLmxvY2FsZSwgbnVtYmVyaW5nU3lzdGVtOiB0aGlzLm51bWJlcmluZ1N5c3RlbSwgLi4ub3B0cyB9O1xuXG4gICAgY29uc3QgdW5pdHMgPSBtYXliZUFycmF5KHVuaXQpLm1hcChEdXJhdGlvbi5ub3JtYWxpemVVbml0KSxcbiAgICAgIG90aGVySXNMYXRlciA9IG90aGVyRGF0ZVRpbWUudmFsdWVPZigpID4gdGhpcy52YWx1ZU9mKCksXG4gICAgICBlYXJsaWVyID0gb3RoZXJJc0xhdGVyID8gdGhpcyA6IG90aGVyRGF0ZVRpbWUsXG4gICAgICBsYXRlciA9IG90aGVySXNMYXRlciA/IG90aGVyRGF0ZVRpbWUgOiB0aGlzLFxuICAgICAgZGlmZmVkID0gZGlmZihlYXJsaWVyLCBsYXRlciwgdW5pdHMsIGR1ck9wdHMpO1xuXG4gICAgcmV0dXJuIG90aGVySXNMYXRlciA/IGRpZmZlZC5uZWdhdGUoKSA6IGRpZmZlZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGlzIERhdGVUaW1lIGFuZCByaWdodCBub3cuXG4gICAqIFNlZSB7QGxpbmsgRGF0ZVRpbWUjZGlmZn1cbiAgICogQHBhcmFtIHtzdHJpbmd8c3RyaW5nW119IFt1bml0PVsnbWlsbGlzZWNvbmRzJ11dIC0gdGhlIHVuaXQgb3IgdW5pdHMgdW5pdHMgKHN1Y2ggYXMgJ2hvdXJzJyBvciAnZGF5cycpIHRvIGluY2x1ZGUgaW4gdGhlIGR1cmF0aW9uXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRzIC0gb3B0aW9ucyB0aGF0IGFmZmVjdCB0aGUgY3JlYXRpb24gb2YgdGhlIER1cmF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBbb3B0cy5jb252ZXJzaW9uQWNjdXJhY3k9J2Nhc3VhbCddIC0gdGhlIGNvbnZlcnNpb24gc3lzdGVtIHRvIHVzZVxuICAgKiBAcmV0dXJuIHtEdXJhdGlvbn1cbiAgICovXG4gIGRpZmZOb3codW5pdCA9IFwibWlsbGlzZWNvbmRzXCIsIG9wdHMgPSB7fSkge1xuICAgIHJldHVybiB0aGlzLmRpZmYoRGF0ZVRpbWUubm93KCksIHVuaXQsIG9wdHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiBhbiBJbnRlcnZhbCBzcGFubmluZyBiZXR3ZWVuIHRoaXMgRGF0ZVRpbWUgYW5kIGFub3RoZXIgRGF0ZVRpbWVcbiAgICogQHBhcmFtIHtEYXRlVGltZX0gb3RoZXJEYXRlVGltZSAtIHRoZSBvdGhlciBlbmQgcG9pbnQgb2YgdGhlIEludGVydmFsXG4gICAqIEByZXR1cm4ge0ludGVydmFsfVxuICAgKi9cbiAgdW50aWwob3RoZXJEYXRlVGltZSkge1xuICAgIHJldHVybiB0aGlzLmlzVmFsaWQgPyBJbnRlcnZhbC5mcm9tRGF0ZVRpbWVzKHRoaXMsIG90aGVyRGF0ZVRpbWUpIDogdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gd2hldGhlciB0aGlzIERhdGVUaW1lIGlzIGluIHRoZSBzYW1lIHVuaXQgb2YgdGltZSBhcyBhbm90aGVyIERhdGVUaW1lLlxuICAgKiBIaWdoZXItb3JkZXIgdW5pdHMgbXVzdCBhbHNvIGJlIGlkZW50aWNhbCBmb3IgdGhpcyBmdW5jdGlvbiB0byByZXR1cm4gYHRydWVgLlxuICAgKiBOb3RlIHRoYXQgdGltZSB6b25lcyBhcmUgKippZ25vcmVkKiogaW4gdGhpcyBjb21wYXJpc29uLCB3aGljaCBjb21wYXJlcyB0aGUgKipsb2NhbCoqIGNhbGVuZGFyIHRpbWUuIFVzZSB7QGxpbmsgRGF0ZVRpbWUjc2V0Wm9uZX0gdG8gY29udmVydCBvbmUgb2YgdGhlIGRhdGVzIGlmIG5lZWRlZC5cbiAgICogQHBhcmFtIHtEYXRlVGltZX0gb3RoZXJEYXRlVGltZSAtIHRoZSBvdGhlciBEYXRlVGltZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gdW5pdCAtIHRoZSB1bml0IG9mIHRpbWUgdG8gY2hlY2sgc2FtZW5lc3Mgb25cbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkuaGFzU2FtZShvdGhlckRULCAnZGF5Jyk7IC8vfj4gdHJ1ZSBpZiBvdGhlckRUIGlzIGluIHRoZSBzYW1lIGN1cnJlbnQgY2FsZW5kYXIgZGF5XG4gICAqIEByZXR1cm4ge2Jvb2xlYW59XG4gICAqL1xuICBoYXNTYW1lKG90aGVyRGF0ZVRpbWUsIHVuaXQpIHtcbiAgICBpZiAoIXRoaXMuaXNWYWxpZCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgY29uc3QgaW5wdXRNcyA9IG90aGVyRGF0ZVRpbWUudmFsdWVPZigpO1xuICAgIGNvbnN0IGFkanVzdGVkVG9ab25lID0gdGhpcy5zZXRab25lKG90aGVyRGF0ZVRpbWUuem9uZSwgeyBrZWVwTG9jYWxUaW1lOiB0cnVlIH0pO1xuICAgIHJldHVybiBhZGp1c3RlZFRvWm9uZS5zdGFydE9mKHVuaXQpIDw9IGlucHV0TXMgJiYgaW5wdXRNcyA8PSBhZGp1c3RlZFRvWm9uZS5lbmRPZih1bml0KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFcXVhbGl0eSBjaGVja1xuICAgKiBUd28gRGF0ZVRpbWVzIGFyZSBlcXVhbCBpZiBhbmQgb25seSBpZiB0aGV5IHJlcHJlc2VudCB0aGUgc2FtZSBtaWxsaXNlY29uZCwgaGF2ZSB0aGUgc2FtZSB6b25lIGFuZCBsb2NhdGlvbiwgYW5kIGFyZSBib3RoIHZhbGlkLlxuICAgKiBUbyBjb21wYXJlIGp1c3QgdGhlIG1pbGxpc2Vjb25kIHZhbHVlcywgdXNlIGArZHQxID09PSArZHQyYC5cbiAgICogQHBhcmFtIHtEYXRlVGltZX0gb3RoZXIgLSB0aGUgb3RoZXIgRGF0ZVRpbWVcbiAgICogQHJldHVybiB7Ym9vbGVhbn1cbiAgICovXG4gIGVxdWFscyhvdGhlcikge1xuICAgIHJldHVybiAoXG4gICAgICB0aGlzLmlzVmFsaWQgJiZcbiAgICAgIG90aGVyLmlzVmFsaWQgJiZcbiAgICAgIHRoaXMudmFsdWVPZigpID09PSBvdGhlci52YWx1ZU9mKCkgJiZcbiAgICAgIHRoaXMuem9uZS5lcXVhbHMob3RoZXIuem9uZSkgJiZcbiAgICAgIHRoaXMubG9jLmVxdWFscyhvdGhlci5sb2MpXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIGEgdGhpcyB0aW1lIHJlbGF0aXZlIHRvIG5vdywgc3VjaCBhcyBcImluIHR3byBkYXlzXCIuIENhbiBvbmx5IGludGVybmF0aW9uYWxpemUgaWYgeW91clxuICAgKiBwbGF0Zm9ybSBzdXBwb3J0cyBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdC4gUm91bmRzIGRvd24gYnkgZGVmYXVsdC5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBvcHRpb25zIHRoYXQgYWZmZWN0IHRoZSBvdXRwdXRcbiAgICogQHBhcmFtIHtEYXRlVGltZX0gW29wdGlvbnMuYmFzZT1EYXRlVGltZS5ub3coKV0gLSB0aGUgRGF0ZVRpbWUgdG8gdXNlIGFzIHRoZSBiYXNpcyB0byB3aGljaCB0aGlzIHRpbWUgaXMgY29tcGFyZWQuIERlZmF1bHRzIHRvIG5vdy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IFtvcHRpb25zLnN0eWxlPVwibG9uZ1wiXSAtIHRoZSBzdHlsZSBvZiB1bml0cywgbXVzdCBiZSBcImxvbmdcIiwgXCJzaG9ydFwiLCBvciBcIm5hcnJvd1wiXG4gICAqIEBwYXJhbSB7c3RyaW5nfHN0cmluZ1tdfSBvcHRpb25zLnVuaXQgLSB1c2UgYSBzcGVjaWZpYyB1bml0IG9yIGFycmF5IG9mIHVuaXRzOyBpZiBvbWl0dGVkLCBvciBhbiBhcnJheSwgdGhlIG1ldGhvZCB3aWxsIHBpY2sgdGhlIGJlc3QgdW5pdC4gVXNlIGFuIGFycmF5IG9yIG9uZSBvZiBcInllYXJzXCIsIFwicXVhcnRlcnNcIiwgXCJtb250aHNcIiwgXCJ3ZWVrc1wiLCBcImRheXNcIiwgXCJob3Vyc1wiLCBcIm1pbnV0ZXNcIiwgb3IgXCJzZWNvbmRzXCJcbiAgICogQHBhcmFtIHtib29sZWFufSBbb3B0aW9ucy5yb3VuZD10cnVlXSAtIHdoZXRoZXIgdG8gcm91bmQgdGhlIG51bWJlcnMgaW4gdGhlIG91dHB1dC5cbiAgICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLnBhZGRpbmc9MF0gLSBwYWRkaW5nIGluIG1pbGxpc2Vjb25kcy4gVGhpcyBhbGxvd3MgeW91IHRvIHJvdW5kIHVwIHRoZSByZXN1bHQgaWYgaXQgZml0cyBpbnNpZGUgdGhlIHRocmVzaG9sZC4gRG9uJ3QgdXNlIGluIGNvbWJpbmF0aW9uIHdpdGgge3JvdW5kOiBmYWxzZX0gYmVjYXVzZSB0aGUgZGVjaW1hbCBvdXRwdXQgd2lsbCBpbmNsdWRlIHRoZSBwYWRkaW5nLlxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5sb2NhbGUgLSBvdmVycmlkZSB0aGUgbG9jYWxlIG9mIHRoaXMgRGF0ZVRpbWVcbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMubnVtYmVyaW5nU3lzdGVtIC0gb3ZlcnJpZGUgdGhlIG51bWJlcmluZ1N5c3RlbSBvZiB0aGlzIERhdGVUaW1lLiBUaGUgSW50bCBzeXN0ZW0gbWF5IGNob29zZSBub3QgdG8gaG9ub3IgdGhpc1xuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS5wbHVzKHsgZGF5czogMSB9KS50b1JlbGF0aXZlKCkgLy89PiBcImluIDEgZGF5XCJcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkuc2V0TG9jYWxlKFwiZXNcIikudG9SZWxhdGl2ZSh7IGRheXM6IDEgfSkgLy89PiBcImRlbnRybyBkZSAxIGRcdTAwRURhXCJcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkucGx1cyh7IGRheXM6IDEgfSkudG9SZWxhdGl2ZSh7IGxvY2FsZTogXCJmclwiIH0pIC8vPT4gXCJkYW5zIDIzIGhldXJlc1wiXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLm1pbnVzKHsgZGF5czogMiB9KS50b1JlbGF0aXZlKCkgLy89PiBcIjIgZGF5cyBhZ29cIlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS5taW51cyh7IGRheXM6IDIgfSkudG9SZWxhdGl2ZSh7IHVuaXQ6IFwiaG91cnNcIiB9KSAvLz0+IFwiNDggaG91cnMgYWdvXCJcbiAgICogQGV4YW1wbGUgRGF0ZVRpbWUubm93KCkubWludXMoeyBob3VyczogMzYgfSkudG9SZWxhdGl2ZSh7IHJvdW5kOiBmYWxzZSB9KSAvLz0+IFwiMS41IGRheXMgYWdvXCJcbiAgICovXG4gIHRvUmVsYXRpdmUob3B0aW9ucyA9IHt9KSB7XG4gICAgaWYgKCF0aGlzLmlzVmFsaWQpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IGJhc2UgPSBvcHRpb25zLmJhc2UgfHwgRGF0ZVRpbWUuZnJvbU9iamVjdCh7fSwgeyB6b25lOiB0aGlzLnpvbmUgfSksXG4gICAgICBwYWRkaW5nID0gb3B0aW9ucy5wYWRkaW5nID8gKHRoaXMgPCBiYXNlID8gLW9wdGlvbnMucGFkZGluZyA6IG9wdGlvbnMucGFkZGluZykgOiAwO1xuICAgIGxldCB1bml0cyA9IFtcInllYXJzXCIsIFwibW9udGhzXCIsIFwiZGF5c1wiLCBcImhvdXJzXCIsIFwibWludXRlc1wiLCBcInNlY29uZHNcIl07XG4gICAgbGV0IHVuaXQgPSBvcHRpb25zLnVuaXQ7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucy51bml0KSkge1xuICAgICAgdW5pdHMgPSBvcHRpb25zLnVuaXQ7XG4gICAgICB1bml0ID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gZGlmZlJlbGF0aXZlKGJhc2UsIHRoaXMucGx1cyhwYWRkaW5nKSwge1xuICAgICAgLi4ub3B0aW9ucyxcbiAgICAgIG51bWVyaWM6IFwiYWx3YXlzXCIsXG4gICAgICB1bml0cyxcbiAgICAgIHVuaXQsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIHN0cmluZyByZXByZXNlbnRhdGlvbiBvZiB0aGlzIGRhdGUgcmVsYXRpdmUgdG8gdG9kYXksIHN1Y2ggYXMgXCJ5ZXN0ZXJkYXlcIiBvciBcIm5leHQgbW9udGhcIi5cbiAgICogT25seSBpbnRlcm5hdGlvbmFsaXplcyBvbiBwbGF0Zm9ybXMgdGhhdCBzdXBwb3J0cyBJbnRsLlJlbGF0aXZlVGltZUZvcm1hdC5cbiAgICogQHBhcmFtIHtPYmplY3R9IG9wdGlvbnMgLSBvcHRpb25zIHRoYXQgYWZmZWN0IHRoZSBvdXRwdXRcbiAgICogQHBhcmFtIHtEYXRlVGltZX0gW29wdGlvbnMuYmFzZT1EYXRlVGltZS5ub3coKV0gLSB0aGUgRGF0ZVRpbWUgdG8gdXNlIGFzIHRoZSBiYXNpcyB0byB3aGljaCB0aGlzIHRpbWUgaXMgY29tcGFyZWQuIERlZmF1bHRzIHRvIG5vdy5cbiAgICogQHBhcmFtIHtzdHJpbmd9IG9wdGlvbnMubG9jYWxlIC0gb3ZlcnJpZGUgdGhlIGxvY2FsZSBvZiB0aGlzIERhdGVUaW1lXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBvcHRpb25zLnVuaXQgLSB1c2UgYSBzcGVjaWZpYyB1bml0OyBpZiBvbWl0dGVkLCB0aGUgbWV0aG9kIHdpbGwgcGljayB0aGUgdW5pdC4gVXNlIG9uZSBvZiBcInllYXJzXCIsIFwicXVhcnRlcnNcIiwgXCJtb250aHNcIiwgXCJ3ZWVrc1wiLCBvciBcImRheXNcIlxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3B0aW9ucy5udW1iZXJpbmdTeXN0ZW0gLSBvdmVycmlkZSB0aGUgbnVtYmVyaW5nU3lzdGVtIG9mIHRoaXMgRGF0ZVRpbWUuIFRoZSBJbnRsIHN5c3RlbSBtYXkgY2hvb3NlIG5vdCB0byBob25vciB0aGlzXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnBsdXMoeyBkYXlzOiAxIH0pLnRvUmVsYXRpdmVDYWxlbmRhcigpIC8vPT4gXCJ0b21vcnJvd1wiXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnNldExvY2FsZShcImVzXCIpLnBsdXMoeyBkYXlzOiAxIH0pLnRvUmVsYXRpdmUoKSAvLz0+IFwiXCJtYVx1MDBGMWFuYVwiXG4gICAqIEBleGFtcGxlIERhdGVUaW1lLm5vdygpLnBsdXMoeyBkYXlzOiAxIH0pLnRvUmVsYXRpdmVDYWxlbmRhcih7IGxvY2FsZTogXCJmclwiIH0pIC8vPT4gXCJkZW1haW5cIlxuICAgKiBAZXhhbXBsZSBEYXRlVGltZS5ub3coKS5taW51cyh7IGRheXM6IDIgfSkudG9SZWxhdGl2ZUNhbGVuZGFyKCkgLy89PiBcIjIgZGF5cyBhZ29cIlxuICAgKi9cbiAgdG9SZWxhdGl2ZUNhbGVuZGFyKG9wdGlvbnMgPSB7fSkge1xuICAgIGlmICghdGhpcy5pc1ZhbGlkKSByZXR1cm4gbnVsbDtcblxuICAgIHJldHVybiBkaWZmUmVsYXRpdmUob3B0aW9ucy5iYXNlIHx8IERhdGVUaW1lLmZyb21PYmplY3Qoe30sIHsgem9uZTogdGhpcy56b25lIH0pLCB0aGlzLCB7XG4gICAgICAuLi5vcHRpb25zLFxuICAgICAgbnVtZXJpYzogXCJhdXRvXCIsXG4gICAgICB1bml0czogW1wieWVhcnNcIiwgXCJtb250aHNcIiwgXCJkYXlzXCJdLFxuICAgICAgY2FsZW5kYXJ5OiB0cnVlLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgbWluIG9mIHNldmVyYWwgZGF0ZSB0aW1lc1xuICAgKiBAcGFyYW0gey4uLkRhdGVUaW1lfSBkYXRlVGltZXMgLSB0aGUgRGF0ZVRpbWVzIGZyb20gd2hpY2ggdG8gY2hvb3NlIHRoZSBtaW5pbXVtXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfSB0aGUgbWluIERhdGVUaW1lLCBvciB1bmRlZmluZWQgaWYgY2FsbGVkIHdpdGggbm8gYXJndW1lbnRcbiAgICovXG4gIHN0YXRpYyBtaW4oLi4uZGF0ZVRpbWVzKSB7XG4gICAgaWYgKCFkYXRlVGltZXMuZXZlcnkoRGF0ZVRpbWUuaXNEYXRlVGltZSkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihcIm1pbiByZXF1aXJlcyBhbGwgYXJndW1lbnRzIGJlIERhdGVUaW1lc1wiKTtcbiAgICB9XG4gICAgcmV0dXJuIGJlc3RCeShkYXRlVGltZXMsIChpKSA9PiBpLnZhbHVlT2YoKSwgTWF0aC5taW4pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybiB0aGUgbWF4IG9mIHNldmVyYWwgZGF0ZSB0aW1lc1xuICAgKiBAcGFyYW0gey4uLkRhdGVUaW1lfSBkYXRlVGltZXMgLSB0aGUgRGF0ZVRpbWVzIGZyb20gd2hpY2ggdG8gY2hvb3NlIHRoZSBtYXhpbXVtXG4gICAqIEByZXR1cm4ge0RhdGVUaW1lfSB0aGUgbWF4IERhdGVUaW1lLCBvciB1bmRlZmluZWQgaWYgY2FsbGVkIHdpdGggbm8gYXJndW1lbnRcbiAgICovXG4gIHN0YXRpYyBtYXgoLi4uZGF0ZVRpbWVzKSB7XG4gICAgaWYgKCFkYXRlVGltZXMuZXZlcnkoRGF0ZVRpbWUuaXNEYXRlVGltZSkpIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihcIm1heCByZXF1aXJlcyBhbGwgYXJndW1lbnRzIGJlIERhdGVUaW1lc1wiKTtcbiAgICB9XG4gICAgcmV0dXJuIGJlc3RCeShkYXRlVGltZXMsIChpKSA9PiBpLnZhbHVlT2YoKSwgTWF0aC5tYXgpO1xuICB9XG5cbiAgLy8gTUlTQ1xuXG4gIC8qKlxuICAgKiBFeHBsYWluIGhvdyBhIHN0cmluZyB3b3VsZCBiZSBwYXJzZWQgYnkgZnJvbUZvcm1hdCgpXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0IC0gdGhlIHN0cmluZyB0byBwYXJzZVxuICAgKiBAcGFyYW0ge3N0cmluZ30gZm10IC0gdGhlIGZvcm1hdCB0aGUgc3RyaW5nIGlzIGV4cGVjdGVkIHRvIGJlIGluIChzZWUgZGVzY3JpcHRpb24pXG4gICAqIEBwYXJhbSB7T2JqZWN0fSBvcHRpb25zIC0gb3B0aW9ucyB0YWtlbiBieSBmcm9tRm9ybWF0KClcbiAgICogQHJldHVybiB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGZyb21Gb3JtYXRFeHBsYWluKHRleHQsIGZtdCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgeyBsb2NhbGUgPSBudWxsLCBudW1iZXJpbmdTeXN0ZW0gPSBudWxsIH0gPSBvcHRpb25zLFxuICAgICAgbG9jYWxlVG9Vc2UgPSBMb2NhbGUuZnJvbU9wdHMoe1xuICAgICAgICBsb2NhbGUsXG4gICAgICAgIG51bWJlcmluZ1N5c3RlbSxcbiAgICAgICAgZGVmYXVsdFRvRU46IHRydWUsXG4gICAgICB9KTtcbiAgICByZXR1cm4gZXhwbGFpbkZyb21Ub2tlbnMobG9jYWxlVG9Vc2UsIHRleHQsIGZtdCk7XG4gIH1cblxuICAvKipcbiAgICogQGRlcHJlY2F0ZWQgdXNlIGZyb21Gb3JtYXRFeHBsYWluIGluc3RlYWRcbiAgICovXG4gIHN0YXRpYyBmcm9tU3RyaW5nRXhwbGFpbih0ZXh0LCBmbXQsIG9wdGlvbnMgPSB7fSkge1xuICAgIHJldHVybiBEYXRlVGltZS5mcm9tRm9ybWF0RXhwbGFpbih0ZXh0LCBmbXQsIG9wdGlvbnMpO1xuICB9XG5cbiAgLy8gRk9STUFUIFBSRVNFVFNcblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAxMC8xNC8xOTgzXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IERBVEVfU0hPUlQoKSB7XG4gICAgcmV0dXJuIEZvcm1hdHMuREFURV9TSE9SVDtcbiAgfVxuXG4gIC8qKlxuICAgKiB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbGVTdHJpbmd9IGZvcm1hdCBsaWtlICdPY3QgMTQsIDE5ODMnXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IERBVEVfTUVEKCkge1xuICAgIHJldHVybiBGb3JtYXRzLkRBVEVfTUVEO1xuICB9XG5cbiAgLyoqXG4gICAqIHtAbGluayBEYXRlVGltZSN0b0xvY2FsZVN0cmluZ30gZm9ybWF0IGxpa2UgJ0ZyaSwgT2N0IDE0LCAxOTgzJ1xuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBEQVRFX01FRF9XSVRIX1dFRUtEQVkoKSB7XG4gICAgcmV0dXJuIEZvcm1hdHMuREFURV9NRURfV0lUSF9XRUVLREFZO1xuICB9XG5cbiAgLyoqXG4gICAqIHtAbGluayBEYXRlVGltZSN0b0xvY2FsZVN0cmluZ30gZm9ybWF0IGxpa2UgJ09jdG9iZXIgMTQsIDE5ODMnXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IERBVEVfRlVMTCgpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5EQVRFX0ZVTEw7XG4gIH1cblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAnVHVlc2RheSwgT2N0b2JlciAxNCwgMTk4MydcbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIHN0YXRpYyBnZXQgREFURV9IVUdFKCkge1xuICAgIHJldHVybiBGb3JtYXRzLkRBVEVfSFVHRTtcbiAgfVxuXG4gIC8qKlxuICAgKiB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbGVTdHJpbmd9IGZvcm1hdCBsaWtlICcwOTozMCBBTScuIE9ubHkgMTItaG91ciBpZiB0aGUgbG9jYWxlIGlzLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBUSU1FX1NJTVBMRSgpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5USU1FX1NJTVBMRTtcbiAgfVxuXG4gIC8qKlxuICAgKiB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbGVTdHJpbmd9IGZvcm1hdCBsaWtlICcwOTozMDoyMyBBTScuIE9ubHkgMTItaG91ciBpZiB0aGUgbG9jYWxlIGlzLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBUSU1FX1dJVEhfU0VDT05EUygpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5USU1FX1dJVEhfU0VDT05EUztcbiAgfVxuXG4gIC8qKlxuICAgKiB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbGVTdHJpbmd9IGZvcm1hdCBsaWtlICcwOTozMDoyMyBBTSBFRFQnLiBPbmx5IDEyLWhvdXIgaWYgdGhlIGxvY2FsZSBpcy5cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIHN0YXRpYyBnZXQgVElNRV9XSVRIX1NIT1JUX09GRlNFVCgpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5USU1FX1dJVEhfU0hPUlRfT0ZGU0VUO1xuICB9XG5cbiAgLyoqXG4gICAqIHtAbGluayBEYXRlVGltZSN0b0xvY2FsZVN0cmluZ30gZm9ybWF0IGxpa2UgJzA5OjMwOjIzIEFNIEVhc3Rlcm4gRGF5bGlnaHQgVGltZScuIE9ubHkgMTItaG91ciBpZiB0aGUgbG9jYWxlIGlzLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBUSU1FX1dJVEhfTE9OR19PRkZTRVQoKSB7XG4gICAgcmV0dXJuIEZvcm1hdHMuVElNRV9XSVRIX0xPTkdfT0ZGU0VUO1xuICB9XG5cbiAgLyoqXG4gICAqIHtAbGluayBEYXRlVGltZSN0b0xvY2FsZVN0cmluZ30gZm9ybWF0IGxpa2UgJzA5OjMwJywgYWx3YXlzIDI0LWhvdXIuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IFRJTUVfMjRfU0lNUExFKCkge1xuICAgIHJldHVybiBGb3JtYXRzLlRJTUVfMjRfU0lNUExFO1xuICB9XG5cbiAgLyoqXG4gICAqIHtAbGluayBEYXRlVGltZSN0b0xvY2FsZVN0cmluZ30gZm9ybWF0IGxpa2UgJzA5OjMwOjIzJywgYWx3YXlzIDI0LWhvdXIuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IFRJTUVfMjRfV0lUSF9TRUNPTkRTKCkge1xuICAgIHJldHVybiBGb3JtYXRzLlRJTUVfMjRfV0lUSF9TRUNPTkRTO1xuICB9XG5cbiAgLyoqXG4gICAqIHtAbGluayBEYXRlVGltZSN0b0xvY2FsZVN0cmluZ30gZm9ybWF0IGxpa2UgJzA5OjMwOjIzIEVEVCcsIGFsd2F5cyAyNC1ob3VyLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBUSU1FXzI0X1dJVEhfU0hPUlRfT0ZGU0VUKCkge1xuICAgIHJldHVybiBGb3JtYXRzLlRJTUVfMjRfV0lUSF9TSE9SVF9PRkZTRVQ7XG4gIH1cblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAnMDk6MzA6MjMgRWFzdGVybiBEYXlsaWdodCBUaW1lJywgYWx3YXlzIDI0LWhvdXIuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IFRJTUVfMjRfV0lUSF9MT05HX09GRlNFVCgpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5USU1FXzI0X1dJVEhfTE9OR19PRkZTRVQ7XG4gIH1cblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAnMTAvMTQvMTk4MywgOTozMCBBTScuIE9ubHkgMTItaG91ciBpZiB0aGUgbG9jYWxlIGlzLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBEQVRFVElNRV9TSE9SVCgpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5EQVRFVElNRV9TSE9SVDtcbiAgfVxuXG4gIC8qKlxuICAgKiB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbGVTdHJpbmd9IGZvcm1hdCBsaWtlICcxMC8xNC8xOTgzLCA5OjMwOjMzIEFNJy4gT25seSAxMi1ob3VyIGlmIHRoZSBsb2NhbGUgaXMuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IERBVEVUSU1FX1NIT1JUX1dJVEhfU0VDT05EUygpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5EQVRFVElNRV9TSE9SVF9XSVRIX1NFQ09ORFM7XG4gIH1cblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAnT2N0IDE0LCAxOTgzLCA5OjMwIEFNJy4gT25seSAxMi1ob3VyIGlmIHRoZSBsb2NhbGUgaXMuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IERBVEVUSU1FX01FRCgpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5EQVRFVElNRV9NRUQ7XG4gIH1cblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAnT2N0IDE0LCAxOTgzLCA5OjMwOjMzIEFNJy4gT25seSAxMi1ob3VyIGlmIHRoZSBsb2NhbGUgaXMuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IERBVEVUSU1FX01FRF9XSVRIX1NFQ09ORFMoKSB7XG4gICAgcmV0dXJuIEZvcm1hdHMuREFURVRJTUVfTUVEX1dJVEhfU0VDT05EUztcbiAgfVxuXG4gIC8qKlxuICAgKiB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbGVTdHJpbmd9IGZvcm1hdCBsaWtlICdGcmksIDE0IE9jdCAxOTgzLCA5OjMwIEFNJy4gT25seSAxMi1ob3VyIGlmIHRoZSBsb2NhbGUgaXMuXG4gICAqIEB0eXBlIHtPYmplY3R9XG4gICAqL1xuICBzdGF0aWMgZ2V0IERBVEVUSU1FX01FRF9XSVRIX1dFRUtEQVkoKSB7XG4gICAgcmV0dXJuIEZvcm1hdHMuREFURVRJTUVfTUVEX1dJVEhfV0VFS0RBWTtcbiAgfVxuXG4gIC8qKlxuICAgKiB7QGxpbmsgRGF0ZVRpbWUjdG9Mb2NhbGVTdHJpbmd9IGZvcm1hdCBsaWtlICdPY3RvYmVyIDE0LCAxOTgzLCA5OjMwIEFNIEVEVCcuIE9ubHkgMTItaG91ciBpZiB0aGUgbG9jYWxlIGlzLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBEQVRFVElNRV9GVUxMKCkge1xuICAgIHJldHVybiBGb3JtYXRzLkRBVEVUSU1FX0ZVTEw7XG4gIH1cblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAnT2N0b2JlciAxNCwgMTk4MywgOTozMDozMyBBTSBFRFQnLiBPbmx5IDEyLWhvdXIgaWYgdGhlIGxvY2FsZSBpcy5cbiAgICogQHR5cGUge09iamVjdH1cbiAgICovXG4gIHN0YXRpYyBnZXQgREFURVRJTUVfRlVMTF9XSVRIX1NFQ09ORFMoKSB7XG4gICAgcmV0dXJuIEZvcm1hdHMuREFURVRJTUVfRlVMTF9XSVRIX1NFQ09ORFM7XG4gIH1cblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAnRnJpZGF5LCBPY3RvYmVyIDE0LCAxOTgzLCA5OjMwIEFNIEVhc3Rlcm4gRGF5bGlnaHQgVGltZScuIE9ubHkgMTItaG91ciBpZiB0aGUgbG9jYWxlIGlzLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBEQVRFVElNRV9IVUdFKCkge1xuICAgIHJldHVybiBGb3JtYXRzLkRBVEVUSU1FX0hVR0U7XG4gIH1cblxuICAvKipcbiAgICoge0BsaW5rIERhdGVUaW1lI3RvTG9jYWxlU3RyaW5nfSBmb3JtYXQgbGlrZSAnRnJpZGF5LCBPY3RvYmVyIDE0LCAxOTgzLCA5OjMwOjMzIEFNIEVhc3Rlcm4gRGF5bGlnaHQgVGltZScuIE9ubHkgMTItaG91ciBpZiB0aGUgbG9jYWxlIGlzLlxuICAgKiBAdHlwZSB7T2JqZWN0fVxuICAgKi9cbiAgc3RhdGljIGdldCBEQVRFVElNRV9IVUdFX1dJVEhfU0VDT05EUygpIHtcbiAgICByZXR1cm4gRm9ybWF0cy5EQVRFVElNRV9IVUdFX1dJVEhfU0VDT05EUztcbiAgfVxufVxuXG4vKipcbiAqIEBwcml2YXRlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmcmllbmRseURhdGVUaW1lKGRhdGVUaW1laXNoKSB7XG4gIGlmIChEYXRlVGltZS5pc0RhdGVUaW1lKGRhdGVUaW1laXNoKSkge1xuICAgIHJldHVybiBkYXRlVGltZWlzaDtcbiAgfSBlbHNlIGlmIChkYXRlVGltZWlzaCAmJiBkYXRlVGltZWlzaC52YWx1ZU9mICYmIGlzTnVtYmVyKGRhdGVUaW1laXNoLnZhbHVlT2YoKSkpIHtcbiAgICByZXR1cm4gRGF0ZVRpbWUuZnJvbUpTRGF0ZShkYXRlVGltZWlzaCk7XG4gIH0gZWxzZSBpZiAoZGF0ZVRpbWVpc2ggJiYgdHlwZW9mIGRhdGVUaW1laXNoID09PSBcIm9iamVjdFwiKSB7XG4gICAgcmV0dXJuIERhdGVUaW1lLmZyb21PYmplY3QoZGF0ZVRpbWVpc2gpO1xuICB9IGVsc2Uge1xuICAgIHRocm93IG5ldyBJbnZhbGlkQXJndW1lbnRFcnJvcihcbiAgICAgIGBVbmtub3duIGRhdGV0aW1lIGFyZ3VtZW50OiAke2RhdGVUaW1laXNofSwgb2YgdHlwZSAke3R5cGVvZiBkYXRlVGltZWlzaH1gXG4gICAgKTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDS0EsSUFBTSxhQUFOLGNBQXlCLE1BQU07QUFBQztBQUt6QixJQUFNLHVCQUFOLGNBQW1DLFdBQVc7QUFBQSxFQUNuRCxZQUFZLFFBQVE7QUFDbEIsVUFBTSxxQkFBcUIsT0FBTyxVQUFVLEdBQUc7QUFBQSxFQUNqRDtBQUNGO0FBS08sSUFBTSx1QkFBTixjQUFtQyxXQUFXO0FBQUEsRUFDbkQsWUFBWSxRQUFRO0FBQ2xCLFVBQU0scUJBQXFCLE9BQU8sVUFBVSxHQUFHO0FBQUEsRUFDakQ7QUFDRjtBQUtPLElBQU0sdUJBQU4sY0FBbUMsV0FBVztBQUFBLEVBQ25ELFlBQVksUUFBUTtBQUNsQixVQUFNLHFCQUFxQixPQUFPLFVBQVUsR0FBRztBQUFBLEVBQ2pEO0FBQ0Y7QUFLTyxJQUFN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QVMsaUJBQ3BCLG9CQUFvQixRQUFRO0FBQzdCLGdCQUFNLEtBQUssT0FBTyxTQUFTLEtBQUssT0FBTyxRQUFRO0FBQy9DLGdCQUFNLFlBQVksS0FBSyxJQUFJLFVBQ3pCLGdCQUFnQixZQUFZLEVBQzVCLEtBQUssQ0FBQyxTQUFTLEtBQUssZ0JBQWdCLFNBQVM7QUFDL0MsY0FBSSxXQUFXO0FBQ2QsWUFBQyxVQUFVLEtBQW1CLFlBQVk7QUFBQSxVQUMzQztBQUNBLDhCQUFvQixRQUFRLEtBQUs7QUFBQSxRQUNsQztBQUFBLE1BQ0Q7QUFBQSxJQUNELENBQUMsRUFDQTtBQUFBLE1BQWUsQ0FBQyxXQUNoQixPQUNFLFFBQVEsT0FBTyxFQUNmLFdBQVcsdUJBQXVCLEVBQ2xDLFFBQVEsWUFBWTtBQUNwQixhQUFLLE9BQU8sU0FBUyxpQkFDcEIsaUJBQWlCO0FBQ2xCLGNBQU0sS0FBSyxPQUFPLFNBQVMsS0FBSyxPQUFPLFFBQVE7QUFDL0MsYUFBSyxPQUFPLEtBQUssWUFBWTtBQUc3Qiw0QkFBb0I7QUFBQSxVQUNuQixLQUFLLE9BQU8sU0FBUztBQUFBLFFBQ3RCO0FBQUEsTUFDRCxDQUFDO0FBQUEsSUFDSDtBQUdELHNCQUFrQixVQUFVLE1BQU0sWUFBWTtBQUM5QyxvQkFBZ0IsVUFBVSxNQUFNLFlBQVk7QUFDNUMsMEJBQXNCLFVBQVUsTUFBTSxZQUFZO0FBRWxELFFBQUksQ0FBQyxLQUFLLE9BQU8sU0FBUyxjQUFjO0FBQ3ZDLHNCQUFnQixVQUFVLE1BQU0sVUFBVTtBQUMxQyw0QkFBc0IsVUFBVSxNQUFNLFVBQVU7QUFBQSxJQUNqRDtBQUFBLEVBQ0Q7QUFDRDsiLAogICJuYW1lcyI6IFsicyIsICJzaW5nbGV0b24iLCAib2Zmc2V0IiwgInMiLCAiZGVmYXVsdFpvbmUiLCAib2Zmc2V0IiwgIm4iLCAibiIsICJvZmZzZXQiLCAicyIsICJuIiwgImZvcm1hdE9mZnNldCIsICJzIiwgIm1hdGNoIiwgIm9mZnNldCIsICJuIiwgImwiLCAicyIsICJJTlZBTElEIiwgInMiLCAiZSIsICJzIiwgIklOVkFMSUQiLCAiY2xvbmUiLCAib2Zmc2V0IiwgIm9yZGVyZWRVbml0cyIsICJvZmZzZXQiLCAidGV4dEZpZWxkIl0KfQo=
import { DateTime, Info } from "luxon";
import {
addIcon,
App,
ItemView,
Menu,
Plugin,
PluginSettingTab,
Setting,
TAbstractFile,
TFile,
WorkspaceLeaf,
Notice,
ExtraButtonComponent,
TextComponent,
} from "obsidian";
const ClockViewType = "my-clock-view";
class ClockView extends ItemView {
private readonly plugin: ClockPlugin;
private timeContainer: HTMLElement;
private dateContainer: HTMLElement;
private timezoneContainer: HTMLElement;
constructor(leaf: WorkspaceLeaf, plugin: ClockPlugin) {
super(leaf);
this.plugin = plugin;
// Create containers for time, date, and timezone
this.timeContainer = this.containerEl.createDiv();
this.dateContainer = this.containerEl.createDiv();
this.timezoneContainer = this.containerEl.createDiv();
}
public async onOpen(): Promise<void> {
this.displayTime();
}
public getViewType(): string {
return ClockViewType;
}
public getDisplayText(): string {
return "Clock";
}
public getIcon(): string {
return "clock";
}
// Omitted onHeaderMenu function as it is commented out
private sortTimeZones(): TimezonePair[] {
const currentOffset = DateTime.local().offset;
// Sort the timezone pairs based on the difference from the current offset in descending order
return this.plugin.settings.timeZonePairs.slice().sort((a, b) => {
const offsetA = parseFloat(a.offset);
const offsetB = parseFloat(b.offset);
const diffA = Math.abs(currentOffset - offsetA);
const diffB = Math.abs(currentOffset - offsetB);
return diffB - diffA;
});
}
public displayTime(): void {
this.timeContainer.empty();
this.dateContainer.empty();
this.timezoneContainer.empty();
// Displaying time based on user's format or default
const currentTime = DateTime.local().toFormat(
this.plugin.settings.timeFormat
);
this.timeContainer.createEl("h2", {
cls: "time-display",
text: currentTime,
});
if (this.plugin.settings.showDate) {
const currentDate = DateTime.local().toFormat(
this.plugin.settings.dateFormat
);
this.dateContainer.createEl("h2", {
cls: "date-display",
text: currentDate,
});
}
// Sort the timezone pairs
const sortedTimeZones = this.sortTimeZones();
// Update the timezone pairs
if (this.plugin.settings.showTimeZone) {
const timezoneContainer = this.timezoneContainer.createEl("div", {
cls: "timezone-container",
});
sortedTimeZones.forEach((entry) => {
if (entry.offset) {
const offset = parseFloat(entry.offset);
const timezoneTime = DateTime.utc()
.plus({ hours: offset })
.toFormat(this.plugin.settings.timezoneFormat);
// Creating timezone pair div and appending name and time divs to it
const timezonePair = timezoneContainer.createEl("div", {
cls: "timezone-pair",
});
timezonePair.createEl("div", {
cls: "timezone-name",
text: entry.name,
});
timezonePair.createEl("div", {
cls: "timezone-time",
text: timezoneTime,
});
}
});
}
}
}
interface TimezonePair {
name: string;
offset: string;
}
interface ClockSettings {
timeFormat: string;
showDate: boolean;
dateFormat: string;
showTimeZone: boolean;
timeZonePairs: TimezonePair[];
timezoneFormat: string;
}
const DEFAULT_SETTINGS: ClockSettings = {
timeFormat: "HH:mm",
showDate: true,
dateFormat: "EEE - dd",
showTimeZone: true,
timeZonePairs: [{ name: "", offset: "" }],
timezoneFormat: "HH:mm - EEEEE",
};
export default class ClockPlugin extends Plugin {
public view: ClockView;
public settings: ClockSettings;
public async onload(): Promise<void> {
// console.log("Clock: Loading plugin v" + this.manifest.version);
// Load plugin settings, using default values if no saved settings are found
this.settings = Object.assign(
{},
DEFAULT_SETTINGS,
await this.loadData()
);
// Register the ClockView with the plugin
this.registerView(
ClockViewType,
(leaf) => (this.view = new ClockView(leaf, this))
);
// Add the 'Open Clock' command to open the Clock plugin
this.addCommand({
id: "clock-open",
name: "Open Clock",
callback: async () => {
let [leaf] = this.app.workspace.getLeavesOfType(ClockViewType);
if (!leaf) {
leaf = this.app.workspace.getRightLeaf(false);
if (leaf) {
await leaf.setViewState({ type: ClockViewType });
} else {
// Handle case where leaf is null or undefined
}
}
if (leaf) {
this.app.workspace.revealLeaf(leaf);
}
},
});
// Initialize the Clock plugin view
if (this.app.workspace.layoutReady) {
await this.initView();
} else {
const checkLayoutInterval = setInterval(async () => {
if (this.app.workspace.layoutReady) {
await this.initView();
clearInterval(checkLayoutInterval);
}
}, 1000);
}
// Add the ClockSettingTab to the plugin's settings
this.addSettingTab(new ClockSettingTab(this.app, this));
}
public onunload(): void {
// console.log("Clock: Unloading plugin");
this.app.workspace.detachLeavesOfType(ClockViewType);
}
private async initView(): Promise<void> {
let [leaf] = this.app.workspace.getLeavesOfType(ClockViewType);
if (!leaf) {
leaf = this.app.workspace.getLeaf();
if (leaf) {
await leaf.setViewState({ type: ClockViewType });
} else {
// Handle case where leaf is null or undefined
}
}
if (leaf) {
this.app.workspace.revealLeaf(leaf);
}
this.view.displayTime();
setInterval(() => {
this.view.displayTime();
}, 1000);
}
async saveSettings(): Promise<void> {
await this.saveData(this.settings);
}
}
class ClockSettingTab extends PluginSettingTab {
private readonly plugin: ClockPlugin;
constructor(app: App, plugin: ClockPlugin) {
super(app, plugin);
this.plugin = plugin;
}
public display(): void {
const { containerEl } = this;
containerEl.empty();
containerEl.createEl("h1", { text: "Clock Settings" });
// Add a link to the Luxon reference
let h2El = containerEl.createEl("p", {
text: "Use the Luxon format for all time and date settings: ",
});
h2El.createEl("a", {
text: " Luxon Reference",
href: "https://moment.github.io/luxon/docs/manual/formatting.html",
attr: {
target: "_blank",
},
});
let textField: TextComponent;
// Time Format Settings
new Setting(containerEl)
.setName("Time format")
.setDesc(
createFragment((fragment) => {
fragment.append(
"Default Luxon format is ",
fragment.createEl("code", {
text: "HH:mm",
})
);
})
)
.addText((text) => {
textField = text
.setPlaceholder("Enter the time format")
.setValue(this.plugin.settings.timeFormat);
// Only save the setting when 'Enter' is pressed
textField.inputEl.onkeypress = async (e) => {
if (e.key === "Enter") {
e.preventDefault();
this.plugin.settings.timeFormat =
textField.inputEl.value;
await this.plugin.saveData(this.plugin.settings);
this.plugin.view.displayTime();
textField.inputEl.blur(); // Lose focus
}
};
})
.addExtraButton((button) =>
button
.setIcon("reset")
.setTooltip("Reset time format")
.onClick(async () => {
this.plugin.settings.timeFormat =
DEFAULT_SETTINGS.timeFormat;
await this.plugin.saveData(this.plugin.settings);
this.plugin.view.displayTime();
// Update the value in the text field to reflect the reset value
textField.setValue(this.plugin.settings.timeFormat);
})
);
// Date Format Settings
new Setting(containerEl)
.setName("Show date")
.setDesc("Enable to show the date.")
.addToggle((toggle) => {
toggle
.setValue(this.plugin.settings.showDate)
.onChange(async (value) => {
this.plugin.settings.showDate = value;
await this.plugin.saveData(this.plugin.settings);
const clockView = this.app.workspace
.getLeavesOfType("my-clock-view")
.find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
(clockView.view as ClockView).displayTime(); // Update the clock immediately
}
// Show or hide the Date Format setting based on the toggle value
if (value) {
dateFormatSetting.settingEl.style.display = "";
} else {
dateFormatSetting.settingEl.style.display = "none";
}
});
});
let dateFormatSetting = new Setting(containerEl)
.setName("Date format")
.setDesc(
createFragment((fragment) => {
fragment.append(
"Default Luxon format is ",
fragment.createEl("code", {
text: "DDD",
})
);
})
)
.addText((text) => {
let textField = text
.setPlaceholder("Enter the date format")
.setValue(this.plugin.settings.dateFormat);
textField.inputEl.onkeypress = async (e) => {
if (e.key === "Enter") {
e.preventDefault();
this.plugin.settings.dateFormat =
textField.inputEl.value;
await this.plugin.saveData(this.plugin.settings);
const clockView = this.app.workspace
.getLeavesOfType("my-clock-view")
.find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
(clockView.view as ClockView).displayTime();
}
textField.inputEl.blur();
}
};
// Show or hide the setting based on the 'Show Date' toggle value
if (!this.plugin.settings.showDate) {
textField.inputEl.style.display = "none";
}
})
.addExtraButton((button) => {
button
.setIcon("reset")
.setTooltip("Reset date format")
.onClick(async () => {
this.plugin.settings.dateFormat =
DEFAULT_SETTINGS.dateFormat;
await this.plugin.saveData(this.plugin.settings);
this.display();
new Notice("Date Format Reset");
const clockView = this.app.workspace
.getLeavesOfType("my-clock-view")
.find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
(clockView.view as ClockView).displayTime();
}
});
});
// Show Timezone Toggle
new Setting(containerEl)
.setName("Show Timezone")
.setDesc("Enable to show the timezone.")
.addToggle((toggle) => {
toggle
.setValue(this.plugin.settings.showTimeZone)
.onChange(async (value) => {
this.plugin.settings.showTimeZone = value;
await this.plugin.saveData(this.plugin.settings);
const clockView = this.app.workspace
.getLeavesOfType("clock-view")
.find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
(clockView.view as ClockView).displayTime(); // Update the clock immediately
}
// Show or hide the Timezone settings based on the toggle value
timezoneSetting.settingEl.style.display = value
? ""
: "none";
timezoneFormatSetting.settingEl.style.display = value
? ""
: "none";
});
});
// Timezone Settings
let timezoneSetting = new Setting(containerEl)
.setName("Timezone settings")
.setDesc(
createFragment((fragment) => {
fragment.append(
"Enter your timezone pairs.",
fragment.createEl("a", {
text: " Reference",
href: "https://www.timeanddate.com/time/map/",
}),
fragment.createEl("br"),
fragment.createEl("br"),
"Names and Offset pairs are not validated."
);
})
);
let timezoneSettingDiv = timezoneSetting.settingEl.createEl("div"); // Here is where we will attach the table
if (this.plugin.settings.showTimeZone) {
const table = timezoneSettingDiv.createEl("table");
const headerRow = table.createEl("tr");
headerRow.createEl("th", { text: "Timezone Name" });
headerRow.createEl("th", { text: "Timezone Offset" });
headerRow.createEl("th", { text: "" });
this.plugin.settings.timeZonePairs.forEach((entry, index) => {
const row = table.createEl("tr");
// Timezone Name input field
const nameCell = row.createEl("td");
const nameInput = nameCell.createEl("input", {
type: "text",
value: entry.name,
});
// Save the settings when Enter is pressed in the Name input field
const saveSettings = async () => {
if (
nameInput.value.trim() !== "" &&
offsetInput.value.trim() !== ""
) {
this.plugin.settings.timeZonePairs[index].name =
nameInput.value;
this.plugin.settings.timeZonePairs[index].offset =
offsetInput.value;
await this.plugin.saveSettings();
}
};
nameInput.addEventListener("keydown", async (e) => {
if (e.key === "Enter") {
e.preventDefault();
await saveSettings();
nameInput.blur();
}
});
// Timezone Offset input field
const offsetCell = row.createEl("td");
const offsetInput = offsetCell.createEl("input", {
type: "text",
value: entry.offset,
});
offsetInput.addEventListener("keydown", async (e) => {
if (e.key === "Enter") {
e.preventDefault();
await saveSettings();
offsetInput.blur();
}
});
// Buttons for deleting and adding timezone entries
const buttonsCell = row.createEl("td");
if (index !== 0) {
const deleteButton = buttonsCell.createEl("button", {
text: "-",
});
deleteButton.classList.add("deleteButtonClass");
deleteButton.addEventListener("click", async () => {
this.plugin.settings.timeZonePairs.splice(index, 1);
await this.plugin.saveSettings();
this.display();
});
}
if (index === this.plugin.settings.timeZonePairs.length - 1) {
const addButton = buttonsCell.createEl("button", {
text: "+",
});
addButton.classList.add("addButtonClass");
addButton.addEventListener("click", async () => {
// Limit timezone entries to 5
if (this.plugin.settings.timeZonePairs.length < 5) {
this.plugin.settings.timeZonePairs.push({
name: "",
offset: "",
});
this.display();
} else {
// Max entries reached
new Notice("Maximum timezone entries added.");
}
});
}
if (
index !== 0 &&
index === this.plugin.settings.timeZonePairs.length - 1
) {
buttonsCell.classList.add("twoButtonsClass");
}
});
}
let timezoneFormatField: TextComponent;
let timezoneFormatSetting = new Setting(containerEl)
.setName("Timezone Format")
.setDesc(
createFragment((fragment) => {
fragment.append(
"Default Luxon format is ",
fragment.createEl("code", {
text: "HH:mm - EEEEE",
})
);
})
)
.addText((text) => {
timezoneFormatField = text
.setPlaceholder("Enter the timezone format")
.setValue(this.plugin.settings.timezoneFormat);
timezoneFormatField.inputEl.onkeypress = async (e) => {
if (e.key === "Enter") {
e.preventDefault();
this.plugin.settings.timezoneFormat =
timezoneFormatField.inputEl.value;
await this.plugin.saveData(this.plugin.settings);
const clockView = this.app.workspace
.getLeavesOfType("clock-view")
.find((leaf) => leaf.view instanceof ClockView);
if (clockView) {
(clockView.view as ClockView).displayTime();
}
timezoneFormatField.inputEl.blur();
}
};
})
.addExtraButton((button) =>
button
.setIcon("reset")
.setTooltip("Reset timezone format")
.onClick(async () => {
this.plugin.settings.timezoneFormat =
DEFAULT_SETTINGS.timezoneFormat;
await this.plugin.saveData(this.plugin.settings);
this.plugin.view.displayTime();
// Update the value in the text field to reflect the reset value
timezoneFormatField.setValue(
this.plugin.settings.timezoneFormat
);
})
);
// Add these lines to remove the borders
dateFormatSetting.settingEl.style.borderTop = "none";
timezoneSetting.settingEl.style.borderTop = "none";
timezoneFormatSetting.settingEl.style.borderTop = "none";
if (!this.plugin.settings.showTimeZone) {
timezoneSetting.settingEl.style.display = "none";
timezoneFormatSetting.settingEl.style.display = "none";
}
}
}
{
"id": "clock-for-obsidian",
"name": "Clock for Obsidian",
"version": "1.3.6",
"minAppVersion": "0.16.3",
"description": "A simple clock plugin for Obsidian",
"author": "HiroMike",
"authorUrl": "none",
"isDesktopOnly": false,
"donation": "none"
}
@import url("https://fonts.googleapis.com/css2?family=Roboto&display=swap");
.clock-container {
font-family: "Roboto", sans-serif;
font-feature-settings: "zero";
}
.time-display {
margin-top: -2em;
display: flex;
font-size: 4em;
justify-content: center;
align-items: center;
color: rgb(176, 190, 197);
}
.date-display {
display: flex;
justify-content: center;
align-items: center;
font-size: 1.3em;
margin-top: -3em;
color: rgb(93, 119, 133);
}
.timezone-container {
display: flex;
flex-direction: row;
justify-content: space-between;
gap: 20px;
margin-left: 10px;
margin-right: 10px;
}
.timezone-pair {
display: flex;
flex-direction: column;
align-items: center;
background-color: rgb(38, 50, 56); /* Deep Blue-Gray */
border-radius: 10%;
border: 2px solid rgb(55, 71, 79); /* Slightly lighter Blue-Gray for border */
width: 100px;
margin-bottom: 10px;
color: rgb(176, 190, 197); /* Light Gray for text */
}
.timezone-name {
font-weight: bold;
color: ;
}
.timezone-time {
color: whitesmoke;
font-size: 0.8em;
}
.addButtonClass, .deleteButtonClass {
width: 2em;
height: 2em;
background-color: #2d2d2d;
color: #ffffff;
border: 1px solid rgb(49, 0, 49);
border-radius: 4px;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
}
.addButtonClass:hover, .deleteButtonClass:hover {
background-color: rgb(94, 0, 94);
}
.twoButtonsClass {
display: flex;
justify-content: flex-end;
gap: 2px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment