UNPKG

@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
/** * 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==