@cute-dw/core
Version:
This TypeScript library is the main part of a more powerfull package designed for the fast WEB software development. The cornerstone of the library is the **DataStore** class, which might be useful when you need a full control of the data, but do not need
400 lines (399 loc) • 49.5 kB
JavaScript
/**
* This class consists exclusively of the static methods that operate on or return date/time values
*/
export class Dates {
/**
* Gets the current date and time
* @returns Current date/time value
*/
static getDate() {
return new Date();
}
/**
* Calculates the number of days in the month
* @param date Base date
* @returns Count of days
*/
static daysInMonth(date) {
if (date == null)
return NaN;
const yy = date.getFullYear();
const mm = date.getMonth();
return Dates.toDays(Date.UTC(yy, mm + 1, 1) - Date.UTC(yy, mm, 1));
}
/**
* Calculates the number of days in the `quarter`
* @param year The number of the year.
* @param quarter The number of the quarter.
* @returns Count of days
*/
static daysInQuarter(year, quarter) {
const today = Dates.getDate();
year = year ?? today.getFullYear();
quarter = quarter ?? Dates.getQuarter(today);
return Dates.toDays(Date.UTC(year, (quarter + 1) * 3, 1) - Date.UTC(year, (quarter * 3), 1));
}
/**
* Calculates the number of days in the `year`
* @param year The number of the year. Default is the current year.
* @returns Count of days
*/
static daysInYear(year) {
year = year ?? new Date(Date.now()).getFullYear();
return (Dates.toDays(Date.UTC(year + 1, 0, 1) - Date.UTC(year, 0, 1)));
}
/**
* Calculates the date of the first week's day in the month
* @param day Day of the week in range 0 Sunday to 6 Saturday
* @param month Month
* @param year Year
* @returns Date
*/
static firstDayInMonth(day, month, year) {
// day is in range 0 Sunday to 6 Saturday
const today = Dates.getDate();
year = year ?? today.getFullYear();
month = month ?? today.getMonth();
return new Date(year, month, 1 +
(day - new Date(year, month, 1).getDay() + 7) % 7);
}
/**
* Calculates the date of n-th week's day in the month
* @param n Ordered number
* @param day Day of week in range 0 Sunday to 6 Saturday
* @param month Month
* @param year Year
* @returns Date
*/
static nthDayInMonth(n, day, month, year) {
// day is in range 0 Sunday to 6 Saturday
const today = Dates.getDate();
year = year ?? today.getFullYear();
month = month ?? today.getMonth();
const d = Dates.firstDayInMonth(day, month, year);
return new Date(d.getFullYear(), d.getMonth(), d.getDate() + (n - 1) * 7);
}
/**
* Calculates the number of days to fixed `day` number
* @param day The day number in the current month
* @returns Number of days
*/
static daysFromFixedDay(day) {
const today = Dates.getDate();
const y = today.getFullYear();
const m = today.getMonth();
const d2 = today.getDate();
const dInPrevMonth = Dates.daysInMonth(new Date(y, m - 1, 1));
return (Dates.toDays(Date.UTC(y, m, d2) - Date.UTC(y, m, day)) + dInPrevMonth) % dInPrevMonth;
}
/**
* Determines the number of days one date occurs after another.
* @param date1 A date value that is the start date of the interval being measured
* @param date2 A date value that is the end date of the interval
* @returns {number} Returns a number of days date2 occurs after date1. If date2 occurs before date1, DaysAfter returns a negative number. If any argument's value is null, DaysAfter returns null.
*/
static daysAfter(date1, date2) {
if (date1 == null || date2 == null)
return null;
//var diff = new Date(+date2).setHours(12) - new Date(+date1).setHours(12);
//return Math.round(diff / Dates.msPerDay);
return Dates.toDays(Dates.toUTC(date2) - Dates.toUTC(date1));
}
/**
* Determines the number of seconds one date occurs after another.
* @param date1 A date value that is the start date of the interval being measured
* @param date2 A date value that is the end date of the interval
* @returns {number} Returns a number of seconds date2 occurs after date1. If date2 occurs before date1, DaysAfter returns a negative number. If any argument's value is null, DaysAfter returns null.
*/
static secondsAfter(date1, date2) {
if (date1 == null || date2 == null)
return null;
// var diff = new Date(+date2).getTime() - new Date(+date1).getTime();
const diff = Dates.toUTC(date2) - Dates.toUTC(date1);
return Math.round(diff / 1000);
}
/**
* Obtains the date that occurs a specified number of days after or before another date
* @param date A value of type date
* @param days An integer indicating a number of days
* @returns The date that occurs `days` after date if `days` is greater than 0. Returns the date that occurs `days` before date if `days` is less than 0. If any argument's value is null, {@link relativeDate} returns null.
* @see {@link relativeTime}
*/
static relativeDate(date, days) {
if (date == null || days == null)
return null;
let dt = new Date(date);
dt.setDate(dt.getDate() + days);
return dt;
}
/**
* Obtains a time that occurs a specified number of seconds after or before another time within a 24-hour period
* @param date A value of type time
* @param secs A long number of seconds
* @returns The time that occurs `secs` seconds after time if `secs` is greater than 0. Returns the time that occurs `secs` seconds before time if `secs` is less than 0. The maximum return value is 23:59:59. If any argument's value is null, {@link relativeTime} returns null
* @see {@link relativeDate}
*/
static relativeTime(date, secs) {
if (date == null || secs == null)
return null;
let dt = new Date(date);
dt.setSeconds(dt.getSeconds() + secs);
return dt;
}
/**
* Converts milliseconds to number of days
* @param ms Number of milliseconds
* @returns Number/interval of days
*/
static toDays(ms) {
return ms / Dates.msPerDay;
}
/**
* Converts date to UTC
* @param date The base date
* @returns The number of milliseconds, or `NaN` if the `date` is _null_.
*/
static toUTC(date) {
if (date == null)
return NaN;
return Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
}
/**
* Converts Date to localized ISO-string
*/
static toString(date, showTime = true) {
if (date == null)
return null;
return [date.getFullYear(), ('0' + (date.getMonth() + 1)).slice(-2), ('0' + date.getDate()).slice(-2)].join('-') +
((showTime) ?
"T" + [('0' + date.getHours()).slice(-2), ('0' + date.getMinutes()).slice(-2), ("0" + date.getSeconds()).slice(-2)].join(":") +
"." + date.getMilliseconds()
: "");
/*
let isoDate = date.toISOString();
if (!showTime) {
const pT = isoDate.indexOf("T");
if (pT >= 0)
isoDate = isoDate.substring(0, pT);
}
return isoDate;
*/
}
/**
* Gets the first date of the month
* @param date The base date. Default is the current date.
* @returns The calculated date, or _null_ if the `date` is _null_
* @see {@link dateEOM}
*/
static dateBOM(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
return new Date(date.getFullYear(), date.getMonth(), 1);
}
/**
* Gets the last date of the month
* @param date The base date. Default is the current date.
* @returns The calculated date, or _null_ if the `date` is _null_.
* @see {@link dateBOM}
*/
static dateEOM(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
return new Date(date.getFullYear(), date.getMonth() + 1, 0);
}
/**
* Gets the first date of the year
* @param date The base date. Default is the current date.
* @returns The calculated date, or _null_ if the `date` is _null_.
* @see {@link dateEOY}
*/
static dateBOY(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
return new Date(date.getFullYear(), 0, 1);
}
/**
* Gets the last date of the year
* @param date The base date. Default is the current date.
* @returns The calculated date, or _null_ if the `date` is _null_.
* @see {@link dateBOY}
*/
static dateEOY(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
return new Date(date.getFullYear(), 11, 31);
}
/**
* Gets the first date of quarter
* @param date The base date. Default is the current date.
* @returns The calculated date, or _null_ if the `date` is _null_.
* @see {@link dateEOQ}
*/
static dateBOQ(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
let quart = Dates.getQuarter(date);
let month = quart * 3;
return new Date(date.getFullYear(), month, 1);
}
/**
* Gets the last date of the quarter
* @param date The base date. Default is the current date.
* @returns The calculated date, or _null_ if the `date` is _null_.
* @see {@link dateBOQ}
*/
static dateEOQ(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
let quart = Dates.getQuarter(date);
let month = quart * 3;
return new Date(date.getFullYear(), month + 3, 0);
}
/**
* Gets the quarter number to which the `date` belongs
* @param date The base date. Default is the current date.
* @returns The quarter number starting from 0, or _null_ if the `date` is _null_.
*/
static getQuarter(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
let quart;
switch (date.getMonth()) {
case 0:
case 1:
case 2:
quart = 0;
break;
case 3:
case 4:
case 5:
quart = 1;
break;
case 6:
case 7:
case 8:
quart = 2;
break;
case 9:
case 10:
case 11:
quart = 3;
break;
default:
quart = NaN;
break;
}
return quart;
}
/**
* Return whether the provided year is a leap year
* @param year Year number to check
* @returns _true_ if `year` is a leap year, else _false_.
*/
static isLeapYear(year) {
return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
}
/**
* Returns the result of checking whether the number of hours in the specified date is less than 12
* @param date Date to check. Default is the current date
* @returns _true_ if hours of `date` is less than 12, else _false_.
*/
static isAM(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
return date.getHours() < 12;
}
/**
* Returns the result of checking whether the number of hours in the specified date is greater than or equal to 12
* @param date Date to check. Default is the current date
* @returns _true_ if hours of `date` is greater than or equal to 12, else _false_.
*/
static isPM(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
return date.getHours() >= 12;
}
/**
* Get ISO-8601 numeric representation of the day of the week
* 1 (for Monday) through 7 (for Sunday)
* @param date Source date. Default is current date.
* @returns The day of the week starting from 1, or _null_ if the `date` is _null_.
* @since 0.5.0
*/
static getDayOfWeek(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
let dow = date.getDay();
if (dow === 0) {
dow = 7;
}
return dow;
}
;
/**
* Gets a day number in year
* @param date Source date. Default is the current date
* @returns Day number in year, or _null_ if the `date` is _null_.
* @since 0.5.0
*/
static getDayOfYear(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
return Math.floor(Dates.daysAfter(Dates.dateBOY(date), date) + 1);
}
/**
* Gets a week number of month
* @param date Source date. Default is the current date
* @returns Week number of month, or _null_ if the `date` is _null_.
* @since 0.5.0
*/
static getWeekOfMonth(date) {
if (date === null)
return null;
const d = date ?? Dates.getDate();
const firstDay = new Date(d.getFullYear(), d.getMonth(), 1).getDay();
return Math.ceil((d.getDate() + (firstDay - 1)) / 7);
}
/**
* Get the ISO 8601 week number of year
* Based on comments from
* http://techblog.procurios.nl/k/n618/news/view/33796/14863/Calculate-ISO-8601-week-and-year-in-javascript.html
*
* @param date Source date. Default is the current date
* @returns ISO 8601 week number of year, or _null_ if the `date` is _null_.
* @since 0.5.0
*/
static getWeek(date) {
if (date === null)
return null;
date = date ?? Dates.getDate();
// Remove time components of date
const targetThursday = new Date(date.getFullYear(), date.getMonth(), date.getDate());
// Change date to Thursday same week
targetThursday.setDate(targetThursday.getDate() - ((targetThursday.getDay() + 6) % 7) + 3);
// Take January 4th as it is always in week 1 (see ISO 8601)
const firstThursday = new Date(targetThursday.getFullYear(), 0, 4);
// Change date to Thursday same week
firstThursday.setDate(firstThursday.getDate() - ((firstThursday.getDay() + 6) % 7) + 3);
// Check if daylight-saving-time-switch occurred and correct for it
const ds = targetThursday.getTimezoneOffset() - firstThursday.getTimezoneOffset();
targetThursday.setHours(targetThursday.getHours() - ds);
// Number of weeks between target Thursday and first Thursday
const weekDiff = (targetThursday - firstThursday) / (86400000 * 7);
return 1 + Math.floor(weekDiff);
}
;
}
Dates.msPerDay = 8.64e7;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGF0ZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jdXRlLWNvcmUvc3JjL2xpYi91dGlsL0RhdGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBOztHQUVHO0FBQ0gsTUFBTSxPQUFPLEtBQUs7SUFFaEI7OztPQUdHO0lBQ0gsTUFBTSxDQUFDLE9BQU87UUFDWixPQUFPLElBQUksSUFBSSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUNEOzs7O09BSUc7SUFDSCxNQUFNLENBQUMsV0FBVyxDQUFDLElBQVU7UUFDM0IsSUFBSSxJQUFJLElBQUksSUFBSTtZQUNkLE9BQU8sR0FBRyxDQUFDO1FBQ2IsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzlCLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUMzQixPQUFPLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBQ0Q7Ozs7O09BS0c7SUFDSCxNQUFNLENBQUMsYUFBYSxDQUFDLElBQWEsRUFBRSxPQUFnQjtRQUNsRCxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDOUIsSUFBSSxHQUFHLElBQUksSUFBSSxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbkMsT0FBTyxHQUFHLE9BQU8sSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBRSxDQUFDO1FBQzlDLE9BQU8sS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFDLE9BQU8sR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFD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QUFDO1FBRUYsb0NBQW9DO1FBQ3BDLGNBQWMsQ0FBQyxPQUFPLENBQ3BCLGNBQWMsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FDbkUsQ0FBQztRQUVGLDREQUE0RDtRQUM1RCxNQUFNLGFBQWEsR0FBRyxJQUFJLElBQUksQ0FBQyxjQUFjLENBQUMsV0FBVyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRW5FLG9DQUFvQztRQUNwQyxhQUFhLENBQUMsT0FBTyxDQUNuQixhQUFhLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxNQUFNLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQ2pFLENBQUM7UUFFRixtRUFBbUU7UUFDbkUsTUFBTSxFQUFFLEdBQUcsY0FBYyxDQUFDLGlCQUFpQixFQUFFLEdBQUcsYUFBYSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDbEYsY0FBYyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsUUFBUSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUM7UUFFeEQsNkRBQTZEO1FBQzdELE1BQU0sUUFBUSxHQUFHLENBQU0sY0FBYyxHQUFRLGFBQWEsQ0FBQyxHQUFHLENBQUMsUUFBUSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzdFLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUFBLENBQUM7O0FBbllhLGNBQVEsR0FBVyxNQUFNLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJcclxuLyoqXHJcbiAqIFRoaXMgY2xhc3MgY29uc2lzdHMgZXhjbHVzaXZlbHkgb2YgdGhlIHN0YXRpYyBtZXRob2RzIHRoYXQgb3BlcmF0ZSBvbiBvciByZXR1cm4gZGF0ZS90aW1lIHZhbHVlc1xyXG4gKi9cclxuZXhwb3J0IGNsYXNzIERhdGVzIHtcclxuICBwcml2YXRlIHN0YXRpYyBtc1BlckRheTogbnVtYmVyID0gOC42NGU3O1xyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIGN1cnJlbnQgZGF0ZSBhbmQgdGltZVxyXG4gICAqIEByZXR1cm5zIEN1cnJlbnQgZGF0ZS90aW1lIHZhbHVlXHJcbiAgICovXHJcbiAgc3RhdGljIGdldERhdGUoKTogRGF0ZSB7XHJcbiAgICByZXR1cm4gbmV3IERhdGUoKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQ2FsY3VsYXRlcyB0aGUgbnVtYmVyIG9mIGRheXMgaW4gdGhlIG1vbnRoXHJcbiAgICogQHBhcmFtIGRhdGUgQmFzZSBkYXRlXHJcbiAgICogQHJldHVybnMgQ291bnQgb2YgZGF5c1xyXG4gICAqL1xyXG4gIHN0YXRpYyBkYXlzSW5Nb250aChkYXRlOiBEYXRlKTogbnVtYmVyIHtcclxuICAgIGlmIChkYXRlID09IG51bGwpXHJcbiAgICAgIHJldHVybiBOYU47XHJcbiAgICBjb25zdCB5eSA9IGRhdGUuZ2V0RnVsbFllYXIoKTtcclxuICAgIGNvbnN0IG1tID0gZGF0ZS5nZXRNb250aCgpO1xyXG4gICAgcmV0dXJuIERhdGVzLnRvRGF5cyhEYXRlLlVUQyh5eSwgbW0gKyAxLCAxKSAtIERhdGUuVVRDKHl5LCBtbSwgMSkpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDYWxjdWxhdGVzIHRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGUgYHF1YXJ0ZXJgXHJcbiAgICogQHBhcmFtIHllYXIgVGhlIG51bWJlciBvZiB0aGUgeWVhci5cclxuICAgKiBAcGFyYW0gcXVhcnRlciBUaGUgbnVtYmVyIG9mIHRoZSBxdWFydGVyLlxyXG4gICAqIEByZXR1cm5zIENvdW50IG9mIGRheXNcclxuICAgKi9cclxuICBzdGF0aWMgZGF5c0luUXVhcnRlcih5ZWFyPzogbnVtYmVyLCBxdWFydGVyPzogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIGNvbnN0IHRvZGF5ID0gRGF0ZXMuZ2V0RGF0ZSgpO1xyXG4gICAgeWVhciA9IHllYXIgPz8gdG9kYXkuZ2V0RnVsbFllYXIoKTtcclxuICAgIHF1YXJ0ZXIgPSBxdWFydGVyID8/IERhdGVzLmdldFF1YXJ0ZXIodG9kYXkpITtcclxuICAgIHJldHVybiBEYXRlcy50b0RheXMoRGF0ZS5VVEMoeWVhciwgKHF1YXJ0ZXIgKyAxKSAqIDMsIDEpIC0gRGF0ZS5VVEMoeWVhciwgKHF1YXJ0ZXIgKiAzKSwgMSkpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDYWxjdWxhdGVzIHRoZSBudW1iZXIgb2YgZGF5cyBpbiB0aGUgYHllYXJgXHJcbiAgICogQHBhcmFtIHllYXIgVGhlIG51bWJlciBvZiB0aGUgeWVhci4gRGVmYXVsdCBpcyB0aGUgY3VycmVudCB5ZWFyLlxyXG4gICAqIEByZXR1cm5zIENvdW50IG9mIGRheXNcclxuICAgKi9cclxuICBzdGF0aWMgZGF5c0luWWVhcih5ZWFyPzogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIHllYXIgPSB5ZWFyID8/IG5ldyBEYXRlKERhdGUubm93KCkpLmdldEZ1bGxZZWFyKCk7XHJcbiAgICByZXR1cm4gKERhdGVzLnRvRGF5cyhEYXRlLlVUQyh5ZWFyICsgMSwgMCwgMSkgLSBEYXRlLlVUQyh5ZWFyLCAwLCAxKSkpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDYWxjdWxhdGVzIHRoZSBkYXRlIG9mIHRoZSBmaXJzdCB3ZWVrJ3MgZGF5IGluIHRoZSBtb250aFxyXG4gICAqIEBwYXJhbSBkYXkgRGF5IG9mIHRoZSB3ZWVrIGluIHJhbmdlIDAgU3VuZGF5IHRvIDYgU2F0dXJkYXlcclxuICAgKiBAcGFyYW0gbW9udGggTW9udGhcclxuICAgKiBAcGFyYW0geWVhciBZZWFyXHJcbiAgICogQHJldHVybnMgRGF0ZVxyXG4gICAqL1xyXG4gIHN0YXRpYyBmaXJzdERheUluTW9udGgoZGF5OiAwIHwgMSB8IDIgfCAzIHwgNCB8IDUgfCA2LCBtb250aDogbnVtYmVyLCB5ZWFyOiBudW1iZXIpOiBEYXRlIHtcclxuICAgIC8vIGRheSBpcyBpbiByYW5nZSAwIFN1bmRheSB0byA2IFNhdHVyZGF5XHJcbiAgICBjb25zdCB0b2RheSA9IERhdGVzLmdldERhdGUoKTtcclxuICAgIHllYXIgPSB5ZWFyID8/IHRvZGF5LmdldEZ1bGxZZWFyKCk7XHJcbiAgICBtb250aCA9IG1vbnRoID8/IHRvZGF5LmdldE1vbnRoKCk7XHJcbiAgICByZXR1cm4gbmV3IERhdGUoeWVhciwgbW9udGgsIDEgK1xyXG4gICAgICAoZGF5IC0gbmV3IERhdGUoeWVhciwgbW9udGgsIDEpLmdldERheSgpICsgNykgJSA3KTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQ2FsY3VsYXRlcyB0aGUgZGF0ZSBvZiBuLXRoIHdlZWsncyBkYXkgaW4gdGhlIG1vbnRoXHJcbiAgICogQHBhcmFtIG4gT3JkZXJlZCBudW1iZXJcclxuICAgKiBAcGFyYW0gZGF5IERheSBvZiB3ZWVrIGluIHJhbmdlIDAgU3VuZGF5IHRvIDYgU2F0dXJkYXlcclxuICAgKiBAcGFyYW0gbW9udGggTW9udGhcclxuICAgKiBAcGFyYW0geWVhciBZZWFyXHJcbiAgICogQHJldHVybnMgRGF0ZVxyXG4gICAqL1xyXG4gIHN0YXRpYyBudGhEYXlJbk1vbnRoKG46IG51bWJlciwgZGF5OiAwIHwgMSB8IDIgfCAzIHwgNCB8IDUgfCA2LCBtb250aDogbnVtYmVyLCB5ZWFyOiBudW1iZXIpOiBEYXRlIHtcclxuICAgIC8vIGRheSBpcyBpbiByYW5nZSAwIFN1bmRheSB0byA2IFNhdHVyZGF5XHJcbiAgICBjb25zdCB0b2RheSA9IERhdGVzLmdldERhdGUoKTtcclxuICAgIHllYXIgPSB5ZWFyID8/IHRvZGF5LmdldEZ1bGxZZWFyKCk7XHJcbiAgICBtb250aCA9IG1vbnRoID8/IHRvZGF5LmdldE1vbnRoKCk7XHJcbiAgICBjb25zdCBkID0gRGF0ZXMuZmlyc3REYXlJbk1vbnRoKGRheSwgbW9udGgsIHllYXIpO1xyXG4gICAgcmV0dXJuIG5ldyBEYXRlKGQuZ2V0RnVsbFllYXIoKSwgZC5nZXRNb250aCgpLCBkLmdldERhdGUoKSArIChuIC0gMSkgKiA3KTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogQ2FsY3VsYXRlcyB0aGUgbnVtYmVyIG9mIGRheXMgdG8gZml4ZWQgYGRheWAgbnVtYmVyXHJcbiAgICogQHBhcmFtIGRheSBUaGUgZGF5IG51bWJlciBpbiB0aGUgY3VycmVudCBtb250aFxyXG4gICAqIEByZXR1cm5zIE51bWJlciBvZiBkYXlzXHJcbiAgICovXHJcbiAgc3RhdGljIGRheXNGcm9tRml4ZWREYXkoZGF5OiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgY29uc3QgdG9kYXkgPSBEYXRlcy5nZXREYXRlKCk7XHJcbiAgICBjb25zdCB5ID0gdG9kYXkuZ2V0RnVsbFllYXIoKTtcclxuICAgIGNvbnN0IG0gPSB0b2RheS5nZXRNb250aCgpO1xyXG4gICAgY29uc3QgZDIgPSB0b2RheS5nZXREYXRlKCk7XHJcbiAgICBjb25zdCBkSW5QcmV2TW9udGggPSBEYXRlcy5kYXlzSW5Nb250aChuZXcgRGF0ZSh5LCBtIC0gMSwgMSkpO1xyXG4gICAgcmV0dXJuIChEYXRlcy50b0RheXMoRGF0ZS5VVEMoeSwgbSwgZDIpIC0gRGF0ZS5VVEMoeSwgbSwgZGF5KSkgKyBkSW5QcmV2TW9udGgpICUgZEluUHJldk1vbnRoO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBEZXRlcm1pbmVzIHRoZSBudW1iZXIgb2YgZGF5cyBvbmUgZGF0ZSBvY2N1cnMgYWZ0ZXIgYW5vdGhlci5cclxuICAgKiBAcGFyYW0gZGF0ZTEgQSBkYXRlIHZhbHVlIHRoYXQgaXMgdGhlIHN0YXJ0IGRhdGUgb2YgdGhlIGludGVydmFsIGJlaW5nIG1lYXN1cmVkXHJcbiAgICogQHBhcmFtIGRhdGUyIEEgZGF0ZSB2YWx1ZSB0aGF0IGlzIHRoZSBlbmQgZGF0ZSBvZiB0aGUgaW50ZXJ2YWxcclxuICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZXR1cm5zIGEgbnVtYmVyIG9mIGRheXMgZGF0ZTIgb2NjdXJzIGFmdGVyIGRhdGUxLiBJZiBkYXRlMiBvY2N1cnMgYmVmb3JlIGRhdGUxLCBEYXlzQWZ0ZXIgcmV0dXJucyBhIG5lZ2F0aXZlIG51bWJlci4gSWYgYW55IGFyZ3VtZW50J3MgdmFsdWUgaXMgbnVsbCwgRGF5c0FmdGVyIHJldHVybnMgbnVsbC5cclxuICAgKi9cclxuICBzdGF0aWMgZGF5c0FmdGVyKGRhdGUxOiBEYXRlLCBkYXRlMjogRGF0ZSk6IG51bWJlciB8IG51bGwge1xyXG4gICAgaWYgKGRhdGUxID09IG51bGwgfHwgZGF0ZTIgPT0gbnVsbClcclxuICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAvL3ZhciBkaWZmID0gbmV3IERhdGUoK2RhdGUyKS5zZXRIb3VycygxMikgLSBuZXcgRGF0ZSgrZGF0ZTEpLnNldEhvdXJzKDEyKTtcclxuICAgIC8vcmV0dXJuIE1hdGgucm91bmQoZGlmZiAvIERhdGVzLm1zUGVyRGF5KTtcclxuICAgIHJldHVybiBEYXRlcy50b0RheXMoRGF0ZXMudG9VVEMoZGF0ZTIpIC0gRGF0ZXMudG9VVEMoZGF0ZTEpKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogRGV0ZXJtaW5lcyB0aGUgbnVtYmVyIG9mIHNlY29uZHMgb25lIGRhdGUgb2NjdXJzIGFmdGVyIGFub3RoZXIuXHJcbiAgICogQHBhcmFtIGRhdGUxIEEgZGF0ZSB2YWx1ZSB0aGF0IGlzIHRoZSBzdGFydCBkYXRlIG9mIHRoZSBpbnRlcnZhbCBiZWluZyBtZWFzdXJlZFxyXG4gICAqIEBwYXJhbSBkYXRlMiBBIGRhdGUgdmFsdWUgdGhhdCBpcyB0aGUgZW5kIGRhdGUgb2YgdGhlIGludGVydmFsXHJcbiAgICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyBhIG51bWJlciBvZiBzZWNvbmRzIGRhdGUyIG9jY3VycyBhZnRlciBkYXRlMS4gSWYgZGF0ZTIgb2NjdXJzIGJlZm9yZSBkYXRlMSwgRGF5c0FmdGVyIHJldHVybnMgYSBuZWdhdGl2ZSBudW1iZXIuIElmIGFueSBhcmd1bWVudCdzIHZhbHVlIGlzIG51bGwsIERheXNBZnRlciByZXR1cm5zIG51bGwuXHJcbiAgICovXHJcbiAgc3RhdGljIHNlY29uZHNBZnRlcihkYXRlMTogRGF0ZSwgZGF0ZTI6IERhdGUpOiBudW1iZXIgfCBudWxsIHtcclxuICAgIGlmIChkYXRlMSA9PSBudWxsIHx8IGRhdGUyID09IG51bGwpXHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgLy8gdmFyIGRpZmYgPSBuZXcgRGF0ZSgrZGF0ZTIpLmdldFRpbWUoKSAtIG5ldyBEYXRlKCtkYXRlMSkuZ2V0VGltZSgpO1xyXG4gICAgY29uc3QgZGlmZiA9IERhdGVzLnRvVVRDKGRhdGUyKSAtIERhdGVzLnRvVVRDKGRhdGUxKTtcclxuICAgIHJldHVybiBNYXRoLnJvdW5kKGRpZmYgLyAxMDAwKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogT2J0YWlucyB0aGUgZGF0ZSB0aGF0IG9jY3VycyBhIHNwZWNpZmllZCBudW1iZXIgb2YgZGF5cyBhZnRlciBvciBiZWZvcmUgYW5vdGhlciBkYXRlXHJcbiAgICogQHBhcmFtIGRhdGUgQSB2YWx1ZSBvZiB0eXBlIGRhdGVcclxuICAgKiBAcGFyYW0gZGF5cyBBbiBpbnRlZ2VyIGluZGljYXRpbmcgYSBudW1iZXIgb2YgZGF5c1xyXG4gICAqIEByZXR1cm5zIFRoZSBkYXRlIHRoYXQgb2NjdXJzIGBkYXlzYCBhZnRlciBkYXRlIGlmIGBkYXlzYCBpcyBncmVhdGVyIHRoYW4gMC4gUmV0dXJucyB0aGUgZGF0ZSB0aGF0IG9jY3VycyBgZGF5c2AgYmVmb3JlIGRhdGUgaWYgYGRheXNgIGlzIGxlc3MgdGhhbiAwLiBJZiBhbnkgYXJndW1lbnQncyB2YWx1ZSBpcyBudWxsLCB7QGxpbmsgcmVsYXRpdmVEYXRlfSByZXR1cm5zIG51bGwuXHJcbiAgICogQHNlZSB7QGxpbmsgcmVsYXRpdmVUaW1lfVxyXG4gICAqL1xyXG4gIHN0YXRpYyByZWxhdGl2ZURhdGUoZGF0ZTogRGF0ZSwgZGF5czogbnVtYmVyKTogRGF0ZSB8IG51bGwge1xyXG4gICAgaWYgKGRhdGUgPT0gbnVsbCB8fCBkYXlzID09IG51bGwpXHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgbGV0IGR0ID0gbmV3IERhdGUoZGF0ZSk7XHJcbiAgICBkdC5zZXREYXRlKGR0LmdldERhdGUoKSArIGRheXMpO1xyXG4gICAgcmV0dXJuIGR0O1xyXG4gIH1cclxuICAvKipcclxuICAgKiBPYnRhaW5zIGEgdGltZSB0aGF0IG9jY3VycyBhIHNwZWNpZmllZCBudW1iZXIgb2Ygc2Vjb25kcyBhZnRlciBvciBiZWZvcmUgYW5vdGhlciB0aW1lIHdpdGhpbiBhIDI0LWhvdXIgcGVyaW9kXHJcbiAgICogQHBhcmFtIGRhdGUgQSB2YWx1ZSBvZiB0eXBlIHRpbWVcclxuICAgKiBAcGFyYW0gc2VjcyBBIGxvbmcgbnVtYmVyIG9mIHNlY29uZHNcclxuICAgKiBAcmV0dXJucyBUaGUgdGltZSB0aGF0IG9jY3VycyBgc2Vjc2Agc2Vjb25kcyBhZnRlciB0aW1lIGlmIGBzZWNzYCBpcyBncmVhdGVyIHRoYW4gMC4gUmV0dXJucyB0aGUgdGltZSB0aGF0IG9jY3VycyBgc2Vjc2Agc2Vjb25kcyBiZWZvcmUgdGltZSBpZiBgc2Vjc2AgaXMgbGVzcyB0aGFuIDAuIFRoZSBtYXhpbXVtIHJldHVybiB2YWx1ZSBpcyAyMzo1OTo1OS4gSWYgYW55IGFyZ3VtZW50J3MgdmFsdWUgaXMgbnVsbCwge0BsaW5rIHJlbGF0aXZlVGltZX0gcmV0dXJucyBudWxsXHJcbiAgICogQHNlZSB7QGxpbmsgcmVsYXRpdmVEYXRlfVxyXG4gICAqL1xyXG4gIHN0YXRpYyByZWxhdGl2ZVRpbWUoZGF0ZTogRGF0ZSwgc2VjczogbnVtYmVyKTogRGF0ZSB8IG51bGwge1xyXG4gICAgaWYgKGRhdGUgPT0gbnVsbCB8fCBzZWNzID09IG51bGwpXHJcbiAgICAgIHJldHVybiBudWxsO1xyXG4gICAgbGV0IGR0ID0gbmV3IERhdGUoZGF0ZSk7XHJcbiAgICBkdC5zZXRTZWNvbmRzKGR0LmdldFNlY29uZHMoKSArIHNlY3MpO1xyXG4gICAgcmV0dXJuIGR0O1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDb252ZXJ0cyBtaWxsaXNlY29uZHMgdG8gbnVtYmVyIG9mIGRheXNcclxuICAgKiBAcGFyYW0gbXMgTnVtYmVyIG9mIG1pbGxpc2Vjb25kc1xyXG4gICAqIEByZXR1cm5zIE51bWJlci9pbnRlcnZhbCBvZiBkYXlzXHJcbiAgICovXHJcbiAgc3RhdGljIHRvRGF5cyhtczogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBtcyAvIERhdGVzLm1zUGVyRGF5O1xyXG4gIH1cclxuICAvKipcclxuICAgKiBDb252ZXJ0cyBkYXRlIHRvIFVUQ1xyXG4gICAqIEBwYXJhbSBkYXRlIFRoZSBiYXNlIGRhdGVcclxuICAgKiBAcmV0dXJucyBUaGUgbnVtYmVyIG9mIG1pbGxpc2Vjb25kcywgb3IgYE5hTmAgaWYgdGhlIGBkYXRlYCBpcyBfbnVsbF8uXHJcbiAgICovXHJcbiAgc3RhdGljIHRvVVRDKGRhdGU6IERhdGUgfCBudWxsKTogbnVtYmVyIHtcclxuICAgIGlmIChkYXRlID09IG51bGwpXHJcbiAgICAgIHJldHVybiBOYU47XHJcbiAgICByZXR1cm4gRGF0ZS5VVEMoZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCksIGRhdGUuZ2V0RGF0ZSgpLCBkYXRlLmdldEhvdXJzKCksIGRhdGUuZ2V0TWludXRlcygpLCBkYXRlLmdldFNlY29uZHMoKSwgZGF0ZS5nZXRNaWxsaXNlY29uZHMoKSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIENvbnZlcnRzIERhdGUgdG8gbG9jYWxpemVkIElTTy1zdHJpbmdcclxuICAgKi9cclxuICBzdGF0aWMgdG9TdHJpbmcoZGF0ZTogRGF0ZSB8IG51bGwsIHNob3dUaW1lOiBib29sZWFuID0gdHJ1ZSk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgaWYgKGRhdGUgPT0gbnVsbClcclxuICAgICAgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgcmV0dXJuIFtkYXRlLmdldEZ1bGxZZWFyKCksICgnMCcgKyAoZGF0ZS5nZXRNb250aCgpICsgMSkpLnNsaWNlKC0yKSwgKCcwJyArIGRhdGUuZ2V0RGF0ZSgpKS5zbGljZSgtMildLmpvaW4oJy0nKSArXHJcbiAgICAgICgoc2hvd1RpbWUpID9cclxuICAgICAgICBcIlRcIiArIFsoJzAnICsgZGF0ZS5nZXRIb3VycygpKS5zbGljZSgtMiksICgnMCcgKyBkYXRlLmdldE1pbnV0ZXMoKSkuc2xpY2UoLTIpLCAoXCIwXCIgKyBkYXRlLmdldFNlY29uZHMoKSkuc2xpY2UoLTIpXS5qb2luKFwiOlwiKSArXHJcbiAgICAgICAgXCIuXCIgKyBkYXRlLmdldE1pbGxpc2Vjb25kcygpXHJcbiAgICAgICAgOiBcIlwiKTtcclxuICAgIC8qXHJcbiAgICBsZXQgaXNvRGF0ZSA9IGRhdGUudG9JU09TdHJpbmcoKTtcclxuICAgIGlmICghc2hvd1RpbWUpIHtcclxuICAgICAgY29uc3QgcFQgPSBpc29EYXRlLmluZGV4T2YoXCJUXCIpO1xyXG4gICAgICBpZiAocFQgPj0gMClcclxuICAgICAgICBpc29EYXRlID0gaXNvRGF0ZS5zdWJzdHJpbmcoMCwgcFQpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBpc29EYXRlO1xyXG4gICAgKi9cclxuICB9XHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgZmlyc3QgZGF0ZSBvZiB0aGUgbW9udGhcclxuICAgKiBAcGFyYW0gZGF0ZSBUaGUgYmFzZSBkYXRlLiBEZWZhdWx0IGlzIHRoZSBjdXJyZW50IGRhdGUuXHJcbiAgICogQHJldHVybnMgVGhlIGNhbGN1bGF0ZWQgZGF0ZSwgb3IgX251bGxfIGlmIHRoZSBgZGF0ZWAgaXMgX251bGxfXHJcbiAgICogQHNlZSB7QGxpbmsgZGF0ZUVPTX1cclxuICAgKi9cclxuICBzdGF0aWMgZGF0ZUJPTShkYXRlPzogRGF0ZSB8IG51bGwpOiBEYXRlIHwgbnVsbCB7XHJcbiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XHJcbiAgICBkYXRlID0gZGF0ZSA/PyBEYXRlcy5nZXREYXRlKCk7XHJcbiAgICByZXR1cm4gbmV3IERhdGUoZGF0ZS5nZXRGdWxsWWVhcigpLCBkYXRlLmdldE1vbnRoKCksIDEpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBsYXN0IGRhdGUgb2YgdGhlIG1vbnRoXHJcbiAgICogQHBhcmFtIGRhdGUgVGhlIGJhc2UgZGF0ZS4gRGVmYXVsdCBpcyB0aGUgY3VycmVudCBkYXRlLlxyXG4gICAqIEByZXR1cm5zIFRoZSBjYWxjdWxhdGVkIGRhdGUsIG9yIF9udWxsXyBpZiB0aGUgYGRhdGVgIGlzIF9udWxsXy5cclxuICAgKiBAc2VlIHtAbGluayBkYXRlQk9NfVxyXG4gICAqL1xyXG4gIHN0YXRpYyBkYXRlRU9NKGRhdGU/OiBEYXRlIHwgbnVsbCk6IERhdGUgfCBudWxsIHtcclxuICAgIGlmIChkYXRlID09PSBudWxsKSByZXR1cm4gbnVsbDtcclxuICAgIGRhdGUgPSBkYXRlID8/IERhdGVzLmdldERhdGUoKTtcclxuICAgIHJldHVybiBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIGRhdGUuZ2V0TW9udGgoKSArIDEsIDApO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBmaXJzdCBkYXRlIG9mIHRoZSB5ZWFyXHJcbiAgICogQHBhcmFtIGRhdGUgVGhlIGJhc2UgZGF0ZS4gRGVmYXVsdCBpcyB0aGUgY3VycmVudCBkYXRlLlxyXG4gICAqIEByZXR1cm5zIFRoZSBjYWxjdWxhdGVkIGRhdGUsIG9yIF9udWxsXyBpZiB0aGUgYGRhdGVgIGlzIF9udWxsXy5cclxuICAgKiBAc2VlIHtAbGluayBkYXRlRU9ZfVxyXG4gICAqL1xyXG4gIHN0YXRpYyBkYXRlQk9ZKGRhdGU/OiBEYXRlIHwgbnVsbCk6IERhdGUgfCBudWxsIHtcclxuICAgIGlmIChkYXRlID09PSBudWxsKSByZXR1cm4gbnVsbDtcclxuICAgIGRhdGUgPSBkYXRlID8/IERhdGVzLmdldERhdGUoKTtcclxuICAgIHJldHVybiBuZXcgRGF0ZShkYXRlLmdldEZ1bGxZZWFyKCksIDAsIDEpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBsYXN0IGRhdGUgb2YgdGhlIHllYXJcclxuICAgKiBAcGFyYW0gZGF0ZSBUaGUgYmFzZSBkYXRlLiBEZWZhdWx0IGlzIHRoZSBjdXJyZW50IGRhdGUuXHJcbiAgICogQHJldHVybnMgVGhlIGNhbGN1bGF0ZWQgZGF0ZSwgb3IgX251bGxfIGlmIHRoZSBgZGF0ZWAgaXMgX251bGxfLlxyXG4gICAqIEBzZWUge0BsaW5rIGRhdGVCT1l9XHJcbiAgICovXHJcbiAgc3RhdGljIGRhdGVFT1koZGF0ZT86IERhdGUgfCBudWxsKTogRGF0ZSB8IG51bGwge1xyXG4gICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybiBudWxsO1xyXG4gICAgZGF0ZSA9IGRhdGUgPz8gRGF0ZXMuZ2V0RGF0ZSgpO1xyXG4gICAgcmV0dXJuIG5ldyBEYXRlKGRhdGUuZ2V0RnVsbFllYXIoKSwgMTEsIDMxKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogR2V0cyB0aGUgZmlyc3QgZGF0ZSBvZiBxdWFydGVyXHJcbiAgICogQHBhcmFtIGRhdGUgVGhlIGJhc2UgZGF0ZS4gRGVmYXVsdCBpcyB0aGUgY3VycmVudCBkYXRlLlxyXG4gICAqIEByZXR1cm5zIFRoZSBjYWxjdWxhdGVkIGRhdGUsIG9yIF9udWxsXyBpZiB0aGUgYGRhdGVgIGlzIF9udWxsXy5cclxuICAgKiBAc2VlIHtAbGluayBkYXRlRU9RfVxyXG4gICAqL1xyXG4gIHN0YXRpYyBkYXRlQk9RKGRhdGU/OiBEYXRlIHwgbnVsbCk6IERhdGUgfCBudWxsICB7XHJcbiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XHJcbiAgICBkYXRlID0gZGF0ZSA/PyBEYXRlcy5nZXREYXRlKCk7XHJcbiAgICBsZXQgcXVhcnQ6IG51bWJlciA9IERhdGVzLmdldFF1YXJ0ZXIoZGF0ZSkhO1xyXG4gICAgbGV0IG1vbnRoOiBudW1iZXIgPSBxdWFydCAqIDM7XHJcbiAgICByZXR1cm4gbmV3IERhdGUoZGF0ZS5nZXRGdWxsWWVhcigpLCBtb250aCwgMSk7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEdldHMgdGhlIGxhc3QgZGF0ZSBvZiB0aGUgcXVhcnRlclxyXG4gICAqIEBwYXJhbSBkYXRlIFRoZSBiYXNlIGRhdGUuIERlZmF1bHQgaXMgdGhlIGN1cnJlbnQgZGF0ZS5cclxuICAgKiBAcmV0dXJucyBUaGUgY2FsY3VsYXRlZCBkYXRlLCBvciBfbnVsbF8gaWYgdGhlIGBkYXRlYCBpcyBfbnVsbF8uXHJcbiAgICogQHNlZSB7QGxpbmsgZGF0ZUJPUX1cclxuICAgKi9cclxuICBzdGF0aWMgZGF0ZUVPUShkYXRlPzogRGF0ZSB8IG51bGwpOiBEYXRlIHwgbnVsbCB7XHJcbiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XHJcbiAgICBkYXRlID0gZGF0ZSA/PyBEYXRlcy5nZXREYXRlKCk7XHJcbiAgICBsZXQgcXVhcnQ6IG51bWJlciA9IERhdGVzLmdldFF1YXJ0ZXIoZGF0ZSkhO1xyXG4gICAgbGV0IG1vbnRoOiBudW1iZXIgPSBxdWFydCAqIDM7XHJcbiAgICByZXR1cm4gbmV3IERhdGUoZGF0ZS5nZXRGdWxsWWVhcigpLCBtb250aCArIDMsIDApO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBHZXRzIHRoZSBxdWFydGVyIG51bWJlciB0byB3aGljaCB0aGUgYGRhdGVgIGJlbG9uZ3NcclxuICAgKiBAcGFyYW0gZGF0ZSBUaGUgYmFzZSBkYXRlLiBEZWZhdWx0IGlzIHRoZSBjdXJyZW50IGRhdGUuXHJcbiAgICogQHJldHVybnMgVGhlIHF1YXJ0ZXIgbnVtYmVyIHN0YXJ0aW5nIGZyb20gMCwgb3IgX251bGxfIGlmIHRoZSBgZGF0ZWAgaXMgX251bGxfLlxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXRRdWFydGVyKGRhdGU/OiBEYXRlIHwgbnVsbCk6IG51bWJlciB8IG51bGwge1xyXG4gICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybiBudWxsO1xyXG4gICAgZGF0ZSA9IGRhdGUgPz8gRGF0ZXMuZ2V0RGF0ZSgpO1xyXG4gICAgbGV0IHF1YXJ0OiBudW1iZXI7XHJcbiAgICBzd2l0Y2ggKGRhdGUuZ2V0TW9udGgoKSkge1xyXG4gICAgICBjYXNlIDA6XHJcbiAgICAgIGNhc2UgMTpcclxuICAgICAgY2FzZSAyOlxyXG4gICAgICAgIHF1YXJ0ID0gMDsgYnJlYWs7XHJcbiAgICAgIGNhc2UgMzpcclxuICAgICAgY2FzZSA0OlxyXG4gICAgICBjYXNlIDU6XHJcbiAgICAgICAgcXVhcnQgPSAxOyBicmVhaztcclxuICAgICAgY2FzZSA2OlxyXG4gICAgICBjYXNlIDc6XHJcbiAgICAgIGNhc2UgODpcclxuICAgICAgICBxdWFydCA9IDI7IGJyZWFrO1xyXG4gICAgICBjYXNlIDk6XHJcbiAgICAgIGNhc2UgMTA6XHJcbiAgICAgIGNhc2UgMTE6XHJcbiAgICAgICAgcXVhcnQgPSAzOyBicmVhaztcclxuICAgICAgZGVmYXVsdDpcclxuICAgICAgICBxdWFydCA9IE5hTjsgYnJlYWs7XHJcbiAgICB9XHJcbiAgICByZXR1cm4gcXVhcnQ7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFJldHVybiB3aGV0aGVyIHRoZSBwcm92aWRlZCB5ZWFyIGlzIGEgbGVhcCB5ZWFyXHJcbiAgICogQHBhcmFtIHllYXIgWWVhciBudW1iZXIgdG8gY2hlY2tcclxuICAgKiBAcmV0dXJucyBfdHJ1ZV8gaWYgYHllYXJgIGlzIGEgbGVhcCB5ZWFyLCBlbHNlIF9mYWxzZV8uXHJcbiAgICovXHJcbiAgc3RhdGljIGlzTGVhcFllYXIoeWVhcjogbnVtYmVyKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gKHllYXIgJSA0ID09PSAwICYmIHllYXIgJSAxMDAgIT09IDApIHx8IHllYXIgJSA0MDAgPT09IDA7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIFJldHVybnMgdGhlIHJlc3VsdCBvZiBjaGVja2luZyB3aGV0aGVyIHRoZSBudW1iZXIgb2YgaG91cnMgaW4gdGhlIHNwZWNpZmllZCBkYXRlIGlzIGxlc3MgdGhhbiAxMlxyXG4gICAqIEBwYXJhbSBkYXRlIERhdGUgdG8gY2hlY2suIERlZmF1bHQgaXMgdGhlIGN1cnJlbnQgZGF0ZVxyXG4gICAqIEByZXR1cm5zIF90cnVlXyBpZiBob3VycyBvZiBgZGF0ZWAgaXMgbGVzcyB0aGFuIDEyLCBlbHNlIF9mYWxzZV8uXHJcbiAgICovXHJcbiAgc3RhdGljIGlzQU0oZGF0ZT86IERhdGUgfCBudWxsKTogYm9vbGVhbiB8IG51bGwge1xyXG4gICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybiBudWxsO1xyXG4gICAgZGF0ZSA9IGRhdGUgPz8gRGF0ZXMuZ2V0RGF0ZSgpO1xyXG4gICAgcmV0dXJuIGRhdGUuZ2V0SG91cnMoKSA8IDEyO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBSZXR1cm5zIHRoZSByZXN1bHQgb2YgY2hlY2tpbmcgd2hldGhlciB0aGUgbnVtYmVyIG9mIGhvdXJzIGluIHRoZSBzcGVjaWZpZWQgZGF0ZSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gMTJcclxuICAgKiBAcGFyYW0gZGF0ZSBEYXRlIHRvIGNoZWNrLiBEZWZhdWx0IGlzIHRoZSBjdXJyZW50IGRhdGVcclxuICAgKiBAcmV0dXJucyBfdHJ1ZV8gaWYgaG91cnMgb2YgYGRhdGVgIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0byAxMiwgZWxzZSBfZmFsc2VfLlxyXG4gICAqL1xyXG4gIHN0YXRpYyBpc1BNKGRhdGU/OiBEYXRlIHwgbnVsbCk6IGJvb2xlYW4gfCBudWxsIHtcclxuICAgIGlmIChkYXRlID09PSBudWxsKSByZXR1cm4gbnVsbDtcclxuICAgIGRhdGUgPSBkYXRlID8/IERhdGVzLmdldERhdGUoKTtcclxuICAgIHJldHVybiBkYXRlLmdldEhvdXJzKCkgPj0gMTI7XHJcbiAgfVxyXG4gIC8qKlxyXG4gICAqIEdldCBJU08tODYwMSBudW1lcmljIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBkYXkgb2YgdGhlIHdlZWtcclxuICAgKiAxIChmb3IgTW9uZGF5KSB0aHJvdWdoIDcgKGZvciBTdW5kYXkpXHJcbiAgICogQHBhcmFtICBkYXRlIFNvdXJjZSBkYXRlLiBEZWZhdWx0IGlzIGN1cnJlbnQgZGF0ZS5cclxuICAgKiBAcmV0dXJucyBUaGUgZGF5IG9mIHRoZSB3ZWVrIHN0YXJ0aW5nIGZyb20gMSwgb3IgX251bGxfIGlmIHRoZSBgZGF0ZWAgaXMgX251bGxfLlxyXG4gICAqIEBzaW5jZSAwLjUuMFxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXREYXlPZldlZWsoZGF0ZT86IERhdGUgfCBudWxsKTogbnVtYmVyIHwgbnVsbCB7XHJcbiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XHJcbiAgICBkYXRlID0gZGF0ZSA/PyBEYXRlcy5nZXREYXRlKCk7XHJcbiAgICBsZXQgZG93ID0gZGF0ZS5nZXREYXkoKTtcclxuICAgIGlmIChkb3cgPT09IDApIHtcclxuICAgICAgZG93ID0gNztcclxuICAgIH1cclxuICAgIHJldHVybiBkb3c7XHJcbiAgfTtcclxuICAvKipcclxuICAgKiBHZXRzIGEgZGF5IG51bWJlciBpbiB5ZWFyXHJcbiAgICogQHBhcmFtIGRhdGUgU291cmNlIGRhdGUuIERlZmF1bHQgaXMgdGhlIGN1cnJlbnQgZGF0ZVxyXG4gICAqIEByZXR1cm5zIERheSBudW1iZXIgaW4geWVhciwgb3IgX251bGxfIGlmIHRoZSBgZGF0ZWAgaXMgX251bGxfLlxyXG4gICAqIEBzaW5jZSAwLjUuMFxyXG4gICAqL1xyXG4gIHN0YXRpYyBnZXREYXlPZlllYXIoZGF0ZT86IERhdGUpOiBudW1iZXIgfCBudWxsIHtcclxuICAgIGlmIChkYXRlID09PSBudWxsKSByZXR1cm4gbnVsbDtcclxuICAgIGRhdGUgPSBkYXRlID8/IERhdGVzLmdldERhdGUoKTtcclxuICAgIHJldHVybiBNYXRoLmZsb29yKCBEYXRlcy5kYXlzQWZ0ZXIoRGF0ZXMuZGF0ZUJPWShkYXRlKSEsIGRhdGUpISArIDEgKTtcclxuICB9XHJcbiAgLyoqXHJcbiAgICogR2V0cyBhIHdlZWsgbnVtYmVyIG9mIG1vbnRoXHJcbiAgICogQHBhcmFtIGRhdGUgU291cmNlIGRhdGUuIERlZmF1bHQgaXMgdGhlIGN1cnJlbnQgZGF0ZVxyXG4gICAqIEByZXR1cm5zIFdlZWsgbnVtYmVyIG9mIG1vbnRoLCBvciBfbnVsbF8gaWYgdGhlIGBkYXRlYCBpcyBfbnVsbF8uXHJcbiAgICogQHNpbmNlIDAuNS4wXHJcbiAgICovXHJcbiAgc3RhdGljIGdldFdlZWtPZk1vbnRoKGRhdGU/OiBEYXRlIHwgbnVsbCk6IG51bWJlciB8IG51bGwge1xyXG4gICAgaWYgKGRhdGUgPT09IG51bGwpIHJldHVybiBudWxsO1xyXG4gICAgY29uc3QgZCA9IGRhdGUgPz8gRGF0ZXMuZ2V0RGF0ZSgpO1xyXG4gICAgY29uc3QgZmlyc3REYXkgPSBuZXcgRGF0ZShkLmdldEZ1bGxZZWFyKCksIGQuZ2V0TW9udGgoKSwgMSkuZ2V0RGF5KCk7XHJcbiAgICByZXR1cm4gTWF0aC5jZWlsKChkLmdldERhdGUoKSArIChmaXJzdERheSAtIDEpKSAvIDcpO1xyXG4gIH1cclxuICAvKipcclxuICAgKiBHZXQgdGhlIElTTyA4NjAxIHdlZWsgbnVtYmVyIG9mIHllYXJcclxuICAgKiBCYXNlZCBvbiBjb21tZW50cyBmcm9tXHJcbiAgICogaHR0cDovL3RlY2hibG9nLnByb2N1cmlvcy5ubC9rL242MTgvbmV3cy92aWV3LzMzNzk2LzE0ODYzL0NhbGN1bGF0ZS1JU08tODYwMS13ZWVrLWFuZC15ZWFyLWluLWphdmFzY3JpcHQuaHRtbFxyXG4gICAqXHJcbiAgICogQHBhcmFtICBkYXRlIFNvdXJjZSBkYXRlLiBEZWZhdWx0IGlzIHRoZSBjdXJyZW50IGRhdGVcclxuICAgKiBAcmV0dXJucyBJU08gODYwMSB3ZWVrIG51bWJlciBvZiB5ZWFyLCBvciBfbnVsbF8gaWYgdGhlIGBkYXRlYCBpcyBfbnVsbF8uXHJcbiAgICogQHNpbmNlIDAuNS4wXHJcbiAgICovXHJcbiAgc3RhdGljIGdldFdlZWsoZGF0ZT86IERhdGUgfCBudWxsKTogbnVtYmVyIHwgbnVsbCB7XHJcbiAgICBpZiAoZGF0ZSA9PT0gbnVsbCkgcmV0dXJuIG51bGw7XHJcbiAgICBkYXRlID0gZGF0ZSA/PyBEYXRlcy5nZXREYXRlKCk7XHJcbiAgICAvLyBSZW1vdmUgdGltZSBjb21wb25lbnRzIG9mIGRhdGVcclxuICAgIGNvbnN0IHRhcmdldFRodXJzZGF5ID0gbmV3IERhdGUoXHJcbiAgICAgIGRhdGUuZ2V0RnVsbFllYXIoKSxcclxuICAgICAgZGF0ZS5nZXRNb250aCgpLFxyXG4gICAgICBkYXRlLmdldERhdGUoKVxyXG4gICAgKTtcclxuXHJcbiAgICAvLyBDaGFuZ2UgZGF0ZSB0byBUaHVyc2RheSBzYW1lIHdlZWtcclxuICAgIHRhcmdldFRodXJzZGF5LnNldERhdGUoXHJcbiAgICAgIHRhcmdldFRodXJzZGF5LmdldERhdGUoKSAtICgodGFyZ2V0VGh1cnNkYXkuZ2V0RGF5KCkgKyA2KSAlIDcpICsgM1xyXG4gICAgKTtcclxuXHJcbiAgICAvLyBUYWtlIEphbnVhcnkgNHRoIGFzIGl0IGlzIGFsd2F5cyBpbiB3ZWVrIDEgKHNlZSBJU08gODYwMSlcclxuICAgIGNvbnN0IGZpcnN0VGh1cnNkYXkgPSBuZXcgRGF0ZSh0YXJnZXRUaHVyc2RheS5nZXRGdWxsWWVhcigpLCAwLCA0KTtcclxuXHJcbiAgICAvLyBDaGFuZ2UgZGF0ZSB0byBUaHVyc2RheSBzYW1lIHdlZWtcclxuICAgIGZpcnN0VGh1cnNkYXkuc2V0RGF0ZShcclxuICAgICAgZmlyc3RUaHVyc2RheS5nZXREYXRlKCkgLSAoKGZpcnN0VGh1cnNkYXkuZ2V0RGF5KCkgKyA2KSAlIDcpICsgM1xyXG4gICAgKTtcclxuXHJcbiAgICAvLyBDaGVjayBpZiBkYXlsaWdodC1zYXZpbmctdGltZS1zd2l0Y2ggb2NjdXJyZWQgYW5kIGNvcnJlY3QgZm9yIGl0XHJcbiAgICBjb25zdCBkcyA9IHRhcmdldFRodXJzZGF5LmdldFRpbWV6b25lT2Zmc2V0KCkgLSBmaXJzdFRodXJzZGF5LmdldFRpbWV6b25lT2Zmc2V0KCk7XHJcbiAgICB0YXJnZXRUaHVyc2RheS5zZXRIb3Vycyh0YXJnZXRUaHVyc2RheS5nZXRIb3VycygpIC0gZHMpO1xyXG5cclxuICAgIC8vIE51bWJlciBvZiB3ZWVrcyBiZXR3ZWVuIHRhcmdldCBUaHVyc2RheSBhbmQgZmlyc3QgVGh1cnNkYXlcclxuICAgIGNvbnN0IHdlZWtEaWZmID0gKDxhbnk+dGFyZ2V0VGh1cnNkYXkgLSA8YW55PmZpcnN0VGh1cnNkYXkpIC8gKDg2NDAwMDAwICogNyk7XHJcbiAgICByZXR1cm4gMSArIE1hdGguZmxvb3Iod2Vla0RpZmYpO1xyXG4gIH07XHJcblxyXG59XHJcbiJdfQ==