UNPKG

@c8y/ngx-components

Version:

Angular modules for Cumulocity IoT applications

258 lines 39.9 kB
import { Pipe } from '@angular/core'; import { TranslateService } from '@ngx-translate/core'; import { gettext } from '../i18n/gettext'; import * as i0 from "@angular/core"; import * as i1 from "@ngx-translate/core"; export const NULL_VALUE_PLACEHOLDER = '--'; export class RelativeTimePipe { constructor(translateService) { this.translateService = translateService; } /** * Transforms the given input into a formatted time difference string. * * This method calculates the time difference between the current date and the input. * If the input is a `Date` object, the difference in milliseconds is calculated from the current date. * If the input is a number, it is treated as the difference in milliseconds. * * The method returns a string representing the time difference, optionally prefixed with * "in " for future dates or suffixed with " ago" for past dates, based on the `noPrefixOrSuffix` flag. * * @param input - The date or the time difference in milliseconds to be transformed. * A positive number indicates a future time relative to now, and a negative number indicates a past time. * @param noPrefixOrSuffix - If `true`, the output will not include "in" or "ago" prefixes/suffixes. * If `false`, the output will include these based on whether the time is in the future or past. * @returns The formatted and translated time difference string. */ transform(input, noPrefixOrSuffix = false) { if (input == null) { return NULL_VALUE_PLACEHOLDER; } let differenceMs; if (input instanceof Date) { const now = new Date(); differenceMs = input.getTime() - now.getTime(); } else { differenceMs = input; } return this.getHumanReadableTimeDiffString(differenceMs, noPrefixOrSuffix); } /** * Calculates a human-readable representation of a time difference. * * Time ranges are same as moment.js timeFromNow function counterpart: * https://momentjscom.readthedocs.io/en/latest/moment/04-displaying/02-fromnow/ * * @param differenceMs - The time difference in milliseconds. * A positive number indicates a future time relative to now, and a negative number indicates a past time. * @param noPrefixOrSuffix - If `true`, the output will not include "in" or "ago" prefixes/suffixes. * If `false`, the output will include these based on whether the time is in the future or past. * @returns A string representing the time difference in a human-readable format. * The format depends on the duration of the difference: * - Less than 45 seconds: returns 'a few seconds' * - 45 to 89 seconds: returns 'a minute' * - 90 seconds to 44 minutes: returns the number of minutes * - 45 to 89 minutes: returns 'an hour' * - 90 minutes to 21 hours: returns the number of hours * - 22 to 35 hours: returns 'a day' * - 36 hours to 25 days: returns the number of days * - 26 to 45 days: returns 'a month' * - 45 to 319 days: returns the number of months * - 320 days to 1.5 years: returns 'a year' * - More than 1.5 years: returns the number of years */ getHumanReadableTimeDiffString(differenceMs, noPrefixOrSuffix) { if (differenceMs == null) { return NULL_VALUE_PLACEHOLDER; } const isInFuture = differenceMs > 0; differenceMs = Math.abs(differenceMs); const conditions = [ this.withinFewSeconds.bind(this), this.withinMinute.bind(this), this.withinMinutes.bind(this), this.withinHour.bind(this), this.withinHours.bind(this), this.withinDay.bind(this), this.withinDays.bind(this), this.withinMonth.bind(this), this.withinMonths.bind(this), this.withinYear.bind(this), this.withinYears.bind(this) ]; for (const condition of conditions) { const result = condition(differenceMs, noPrefixOrSuffix, isInFuture); if (result !== null) { return result; } } } withinFewSeconds(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; if (differenceInSeconds < 45) { if (noPrefixOrSuffix) { return this.translateService.instant(gettext('a few seconds')); } return isInFuture ? this.translateService.instant(gettext('in a few seconds')) : this.translateService.instant(gettext('a few seconds ago')); } return null; } withinMinute(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; if (differenceInSeconds < 90) { if (noPrefixOrSuffix) { return this.translateService.instant(gettext('a minute')); } return isInFuture ? this.translateService.instant(gettext('in a minute')) : this.translateService.instant(gettext('a minute ago')); } return null; } withinMinutes(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; if (differenceInMinutes < 45) { const params = { count: Math.round(differenceInMinutes) }; if (noPrefixOrSuffix) { return this.translateService.instant(gettext('{{ count }} minutes'), params); } return isInFuture ? this.translateService.instant(gettext('in {{ count }} minutes'), params) : this.translateService.instant(gettext('{{ count }} minutes ago'), params); } return null; } withinHour(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; if (differenceInMinutes < 90) { if (noPrefixOrSuffix) { return this.translateService.instant(gettext('an hour')); } return isInFuture ? this.translateService.instant(gettext('in an hour')) : this.translateService.instant(gettext('an hour ago')); } return null; } withinHours(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; const differenceInHours = differenceInMinutes / 60; if (differenceInHours < 22) { const params = { count: Math.round(differenceInHours) }; if (noPrefixOrSuffix) { return this.translateService.instant(gettext('{{ count }} hours'), params); } return isInFuture ? this.translateService.instant(gettext('in {{ count }} hours'), params) : this.translateService.instant(gettext('{{ count }} hours ago'), params); } return null; } withinDay(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; const differenceInHours = differenceInMinutes / 60; if (differenceInHours < 36) { if (noPrefixOrSuffix) { return this.translateService.instant(gettext('a day')); } return isInFuture ? this.translateService.instant(gettext('in a day')) : this.translateService.instant(gettext('a day ago')); } return null; } withinDays(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; const differenceInHours = differenceInMinutes / 60; const differenceInDays = differenceInHours / 24; if (differenceInDays < 26) { const params = { count: Math.round(differenceInDays) }; if (noPrefixOrSuffix) { return this.translateService.instant(gettext('{{ count }} days'), params); } return isInFuture ? this.translateService.instant(gettext('in {{ count }} days'), params) : this.translateService.instant(gettext('{{ count }} days ago'), params); } return null; } withinMonth(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; const differenceInHours = differenceInMinutes / 60; const differenceInDays = differenceInHours / 24; if (differenceInDays < 45) { if (noPrefixOrSuffix) { return this.translateService.instant(gettext('a month')); } return isInFuture ? this.translateService.instant(gettext('in a month')) : this.translateService.instant(gettext('a month ago')); } return null; } withinMonths(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; const differenceInHours = differenceInMinutes / 60; const differenceInDays = differenceInHours / 24; if (differenceInDays < 320) { const params = { count: Math.round(differenceInDays / 30) }; if (noPrefixOrSuffix) { return this.translateService.instant(gettext('{{ count }} months'), params); } return isInFuture ? this.translateService.instant(gettext('in {{ count }} months'), params) : this.translateService.instant(gettext('{{ count }} months ago'), params); } return null; } withinYear(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; const differenceInHours = differenceInMinutes / 60; const differenceInDays = differenceInHours / 24; const differenceInYears = differenceInDays / 365; if (differenceInYears < 1.5) { if (noPrefixOrSuffix) { return this.translateService.instant(gettext('a year')); } return isInFuture ? this.translateService.instant(gettext('in a year')) : this.translateService.instant(gettext('a year ago')); } return null; } withinYears(differenceMs, noPrefixOrSuffix, isInFuture) { const differenceInSeconds = differenceMs / 1000; const differenceInMinutes = differenceInSeconds / 60; const differenceInHours = differenceInMinutes / 60; const differenceInDays = differenceInHours / 24; const differenceInYears = differenceInDays / 365; const params = { count: Math.round(differenceInYears) }; if (noPrefixOrSuffix) { return this.translateService.instant(gettext('{{ count }} years'), params); } return isInFuture ? this.translateService.instant(gettext('in {{ count }} years'), params) : this.translateService.instant(gettext('{{ count }} years ago'), params); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RelativeTimePipe, deps: [{ token: i1.TranslateService }], target: i0.ɵɵFactoryTarget.Pipe }); } static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: RelativeTimePipe, isStandalone: true, name: "relativeTime" }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: RelativeTimePipe, decorators: [{ type: Pipe, args: [{ name: 'relativeTime', standalone: true }] }], ctorParameters: () => [{ type: i1.TranslateService }] }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVsYXRpdmUtdGltZS5waXBlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vY29yZS9jb21tb24vcmVsYXRpdmUtdGltZS5waXBlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQWlCLE1BQU0sZUFBZSxDQUFDO0FBQ3BELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7O0FBRTFDLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLElBQUksQ0FBQztBQU0zQyxNQUFNLE9BQU8sZ0JBQWdCO0lBQzNCLFlBQW9CLGdCQUFrQztRQUFsQyxxQkFBZ0IsR0FBaEIsZ0JBQWdCLENBQWtCO0lBQUcsQ0FBQztJQUUxRDs7Ozs7Ozs7Ozs7Ozs7O09BZUc7SUFDSCxTQUFTLENBQUMsS0FBb0IsRUFBRSxnQkFBZ0IsR0FBRyxLQUFLO1FBQ3RELElBQUksS0FBSyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ2xCLE9BQU8sc0JBQXNCLENBQUM7UUFDaEMsQ0FBQztRQUVELElBQUksWUFBb0IsQ0FBQztRQUV6QixJQUFJLEtBQUssWUFBWSxJQUFJLEVBQUUsQ0FBQztZQUMxQixNQUFNLEdBQUcsR0FBRyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3ZCLFlBQVksR0FBRyxLQUFLLENBQUMsT0FBTyxFQUFFLEdBQUcsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pELENBQUM7YUFBTSxDQUFDO1lBQ04sWUFBWSxHQUFHLEtBQUssQ0FBQztRQUN2QixDQUFDO1FBRUQsT0FBTyxJQUFJLENBQUMsOEJBQThCLENBQUMsWUFBWSxFQUFFLGdCQUFnQixDQUFDLENBQUM7SUFDN0UsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQXVCRztJQUNILDhCQUE4QixDQUFDLFlBQW9CLEVBQUUsZ0JBQXlCO1FBQzVFLElBQUksWUFBWSxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3pCLE9BQU8sc0JBQXNCLENBQUM7UUFDaEMsQ0FBQztRQUVELE1BQU0sVUFBVSxHQUFHLFlBQVksR0FBRyxDQUFDLENBQUM7UUFFcEMsWUFBWSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDLENBQUM7UUFFdEMsTUFBTSxVQUFVLEdBQUc7WUFDakIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDaEMsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQzVCLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUM3QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDMUIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQzNCLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUN6QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDMUIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1lBQzNCLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQztZQUM1QixJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUM7WUFDMUIsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1NBQzVCLENBQUM7UUFFRixLQUFLLE1BQU0sU0FBUyxJQUFJLFVBQVUsRUFBRSxDQUFDO1lBQ25DLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxZQUFZLEVBQUUsZ0JBQWdCLEVBQUUsVUFBVSxDQUFDLENBQUM7WUFDckUsSUFBSSxNQUFNLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQ3BCLE9BQU8sTUFBTSxDQUFDO1lBQ2hCLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVPLGdCQUFnQixDQUN0QixZQUFvQixFQUNwQixnQkFBeUIsRUFDekIsVUFBbUI7UUFFbkIsTUFBTSxtQkFBbUIsR0FBRyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ2hELElBQUksbUJBQW1CLEdBQUcsRUFBRSxFQUFFLENBQUM7WUFDN0IsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNyQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUM7WUFDakUsQ0FBQztZQUNELE9BQU8sVUFBVTtnQkFDZixDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FBQztnQkFDNUQsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBQUMsQ0FBQztRQUNsRSxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sWUFBWSxDQUNsQixZQUFvQixFQUNwQixnQkFBeUIsRUFDekIsVUFBbUI7UUFFbkIsTUFBTSxtQkFBbUIsR0FBRyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ2hELElBQUksbUJBQW1CLEdBQUcsRUFBRSxFQUFFLENBQUM7WUFDN0IsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNyQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFDNUQsQ0FBQztZQUNELE9BQU8sVUFBVTtnQkFDZixDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7Z0JBQ3ZELENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDO1FBQzdELENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTyxhQUFhLENBQ25CLFlBQW9CLEVBQ3BCLGdCQUF5QixFQUN6QixVQUFtQjtRQUVuQixNQUFNLG1CQUFtQixHQUFHLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDaEQsTUFBTSxtQkFBbUIsR0FBRyxtQkFBbUIsR0FBRyxFQUFFLENBQUM7UUFFckQsSUFBSSxtQkFBbUIsR0FBRyxFQUFFLEVBQUUsQ0FBQztZQUM3QixNQUFNLE1BQU0sR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSyxDQUFDLG1CQUFtQixDQUFDLEVBQUUsQ0FBQztZQUUxRCxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3JCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUMvRSxDQUFDO1lBQ0QsT0FBTyxVQUFVO2dCQUNmLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQztnQkFDMUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLHlCQUF5QixDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDaEYsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVPLFVBQVUsQ0FDaEIsWUFBb0IsRUFDcEIsZ0JBQXlCLEVBQ3pCLFVBQW1CO1FBRW5CLE1BQU0sbUJBQW1CLEdBQUcsWUFBWSxHQUFHLElBQUksQ0FBQztRQUNoRCxNQUFNLG1CQUFtQixHQUFHLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUVyRCxJQUFJLG1CQUFtQixHQUFHLEVBQUUsRUFBRSxDQUFDO1lBQzdCLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztnQkFDckIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDO1lBQzNELENBQUM7WUFDRCxPQUFPLFVBQVU7Z0JBQ2YsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUN0RCxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQztRQUM1RCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sV0FBVyxDQUNqQixZQUFvQixFQUNwQixnQkFBeUIsRUFDekIsVUFBbUI7UUFFbkIsTUFBTSxtQkFBbUIsR0FBRyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ2hELE1BQU0sbUJBQW1CLEdBQUcsbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBQ3JELE1BQU0saUJBQWlCLEdBQUcsbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBRW5ELElBQUksaUJBQWlCLEdBQUcsRUFBRSxFQUFFLENBQUM7WUFDM0IsTUFBTSxNQUFNLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLENBQUM7WUFFeEQsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNyQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDN0UsQ0FBQztZQUNELE9BQU8sVUFBVTtnQkFDZixDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsc0JBQXNCLENBQUMsRUFBRSxNQUFNLENBQUM7Z0JBQ3hFLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzlFLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTyxTQUFTLENBQ2YsWUFBb0IsRUFDcEIsZ0JBQXlCLEVBQ3pCLFVBQW1CO1FBRW5CLE1BQU0sbUJBQW1CLEdBQUcsWUFBWSxHQUFHLElBQUksQ0FBQztRQUNoRCxNQUFNLG1CQUFtQixHQUFHLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUNyRCxNQUFNLGlCQUFpQixHQUFHLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUVuRCxJQUFJLGlCQUFpQixHQUFHLEVBQUUsRUFBRSxDQUFDO1lBQzNCLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztnQkFDckIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1lBQ3pELENBQUM7WUFDRCxPQUFPLFVBQVU7Z0JBQ2YsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFDO2dCQUNwRCxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sVUFBVSxDQUNoQixZQUFvQixFQUNwQixnQkFBeUIsRUFDekIsVUFBbUI7UUFFbkIsTUFBTSxtQkFBbUIsR0FBRyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ2hELE1BQU0sbUJBQW1CLEdBQUcsbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBQ3JELE1BQU0saUJBQWlCLEdBQUcsbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBQ25ELE1BQU0sZ0JBQWdCLEdBQUcsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBRWhELElBQUksZ0JBQWdCLEdBQUcsRUFBRSxFQUFFLENBQUM7WUFDMUIsTUFBTSxNQUFNLEdBQUcsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7WUFDdkQsSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO2dCQUNyQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7WUFDNUUsQ0FBQztZQUNELE9BQU8sVUFBVTtnQkFDZixDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMscUJBQXFCLENBQUMsRUFBRSxNQUFNLENBQUM7Z0JBQ3ZFLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQzdFLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFTyxXQUFXLENBQ2pCLFlBQW9CLEVBQ3BCLGdCQUF5QixFQUN6QixVQUFtQjtRQUVuQixNQUFNLG1CQUFtQixHQUFHLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDaEQsTUFBTSxtQkFBbUIsR0FBRyxtQkFBbUIsR0FBRyxFQUFFLENBQUM7UUFDckQsTUFBTSxpQkFBaUIsR0FBRyxtQkFBbUIsR0FBRyxFQUFFLENBQUM7UUFDbkQsTUFBTSxnQkFBZ0IsR0FBRyxpQkFBaUIsR0FBRyxFQUFFLENBQUM7UUFFaEQsSUFBSSxnQkFBZ0IsR0FBRyxFQUFFLEVBQUUsQ0FBQztZQUMxQixJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3JCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQztZQUMzRCxDQUFDO1lBQ0QsT0FBTyxVQUFVO2dCQUNmLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDdEQsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUM7UUFDNUQsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVPLFlBQVksQ0FDbEIsWUFBb0IsRUFDcEIsZ0JBQXlCLEVBQ3pCLFVBQW1CO1FBRW5CLE1BQU0sbUJBQW1CLEdBQUcsWUFBWSxHQUFHLElBQUksQ0FBQztRQUNoRCxNQUFNLG1CQUFtQixHQUFHLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUNyRCxNQUFNLGlCQUFpQixHQUFHLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUNuRCxNQUFNLGdCQUFnQixHQUFHLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztRQUVoRCxJQUFJLGdCQUFnQixHQUFHLEdBQUcsRUFBRSxDQUFDO1lBQzNCLE1BQU0sTUFBTSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUU1RCxJQUFJLGdCQUFnQixFQUFFLENBQUM7Z0JBQ3JCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsb0JBQW9CLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztZQUM5RSxDQUFDO1lBQ0QsT0FBTyxVQUFVO2dCQUNmLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFLE1BQU0sQ0FBQztnQkFDekUsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLHdCQUF3QixDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDL0UsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVPLFVBQVUsQ0FDaEIsWUFBb0IsRUFDcEIsZ0JBQXlCLEVBQ3pCLFVBQW1CO1FBRW5CLE1BQU0sbUJBQW1CLEdBQUcsWUFBWSxHQUFHLElBQUksQ0FBQztRQUNoRCxNQUFNLG1CQUFtQixHQUFHLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUNyRCxNQUFNLGlCQUFpQixHQUFHLG1CQUFtQixHQUFHLEVBQUUsQ0FBQztRQUNuRCxNQUFNLGdCQUFnQixHQUFHLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztRQUNoRCxNQUFNLGlCQUFpQixHQUFHLGdCQUFnQixHQUFHLEdBQUcsQ0FBQztRQUVqRCxJQUFJLGlCQUFpQixHQUFHLEdBQUcsRUFBRSxDQUFDO1lBQzVCLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztnQkFDckIsT0FBTyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO1lBQzFELENBQUM7WUFDRCxPQUFPLFVBQVU7Z0JBQ2YsQ0FBQyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDO2dCQUNyRCxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztRQUMzRCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRU8sV0FBVyxDQUNqQixZQUFvQixFQUNwQixnQkFBeUIsRUFDekIsVUFBbUI7UUFFbkIsTUFBTSxtQkFBbUIsR0FBRyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ2hELE1BQU0sbUJBQW1CLEdBQUcsbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBQ3JELE1BQU0saUJBQWlCLEdBQUcsbUJBQW1CLEdBQUcsRUFBRSxDQUFDO1FBQ25ELE1BQU0sZ0JBQWdCLEdBQUcsaUJBQWlCLEdBQUcsRUFBRSxDQUFDO1FBQ2hELE1BQU0saUJBQWlCLEdBQUcsZ0JBQWdCLEdBQUcsR0FBRyxDQUFDO1FBRWpELE1BQU0sTUFBTSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsaUJBQWlCLENBQUMsRUFBRSxDQUFDO1FBRXhELElBQUksZ0JBQWdCLEVBQUUsQ0FBQztZQUNyQixPQUFPLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLG1CQUFtQixDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDN0UsQ0FBQztRQUNELE9BQU8sVUFBVTtZQUNmLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLE1BQU0sQ0FBQztZQUN4RSxDQUFDLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsdUJBQXVCLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQztJQUM5RSxDQUFDOytHQTFUVSxnQkFBZ0I7NkdBQWhCLGdCQUFnQjs7NEZBQWhCLGdCQUFnQjtrQkFKNUIsSUFBSTttQkFBQztvQkFDSixJQUFJLEVBQUUsY0FBYztvQkFDcEIsVUFBVSxFQUFFLElBQUk7aUJBQ2pCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUGlwZSwgUGlwZVRyYW5zZm9ybSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgVHJhbnNsYXRlU2VydmljZSB9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuaW1wb3J0IHsgZ2V0dGV4dCB9IGZyb20gJy4uL2kxOG4vZ2V0dGV4dCc7XG5cbmV4cG9ydCBjb25zdCBOVUxMX1ZBTFVFX1BMQUNFSE9MREVSID0gJy0tJztcblxuQFBpcGUoe1xuICBuYW1lOiAncmVsYXRpdmVUaW1lJyxcbiAgc3RhbmRhbG9uZTogdHJ1ZVxufSlcbmV4cG9ydCBjbGFzcyBSZWxhdGl2ZVRpbWVQaXBlIGltcGxlbWVudHMgUGlwZVRyYW5zZm9ybSB7XG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgdHJhbnNsYXRlU2VydmljZTogVHJhbnNsYXRlU2VydmljZSkge31cblxuICAvKipcbiAgICogVHJhbnNmb3JtcyB0aGUgZ2l2ZW4gaW5wdXQgaW50byBhIGZvcm1hdHRlZCB0aW1lIGRpZmZlcmVuY2Ugc3RyaW5nLlxuICAgKlxuICAgKiBUaGlzIG1ldGhvZCBjYWxjdWxhdGVzIHRoZSB0aW1lIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgY3VycmVudCBkYXRlIGFuZCB0aGUgaW5wdXQuXG4gICAqIElmIHRoZSBpbnB1dCBpcyBhIGBEYXRlYCBvYmplY3QsIHRoZSBkaWZmZXJlbmNlIGluIG1pbGxpc2Vjb25kcyBpcyBjYWxjdWxhdGVkIGZyb20gdGhlIGN1cnJlbnQgZGF0ZS5cbiAgICogSWYgdGhlIGlucHV0IGlzIGEgbnVtYmVyLCBpdCBpcyB0cmVhdGVkIGFzIHRoZSBkaWZmZXJlbmNlIGluIG1pbGxpc2Vjb25kcy5cbiAgICpcbiAgICogVGhlIG1ldGhvZCByZXR1cm5zIGEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgdGltZSBkaWZmZXJlbmNlLCBvcHRpb25hbGx5IHByZWZpeGVkIHdpdGhcbiAgICogXCJpbiBcIiBmb3IgZnV0dXJlIGRhdGVzIG9yIHN1ZmZpeGVkIHdpdGggXCIgYWdvXCIgZm9yIHBhc3QgZGF0ZXMsIGJhc2VkIG9uIHRoZSBgbm9QcmVmaXhPclN1ZmZpeGAgZmxhZy5cbiAgICpcbiAgICogQHBhcmFtIGlucHV0IC0gVGhlIGRhdGUgb3IgdGhlIHRpbWUgZGlmZmVyZW5jZSBpbiBtaWxsaXNlY29uZHMgdG8gYmUgdHJhbnNmb3JtZWQuXG4gICAqICAgICAgICAgICAgICAgIEEgcG9zaXRpdmUgbnVtYmVyIGluZGljYXRlcyBhIGZ1dHVyZSB0aW1lIHJlbGF0aXZlIHRvIG5vdywgYW5kIGEgbmVnYXRpdmUgbnVtYmVyIGluZGljYXRlcyBhIHBhc3QgdGltZS5cbiAgICogQHBhcmFtIG5vUHJlZml4T3JTdWZmaXggLSBJZiBgdHJ1ZWAsIHRoZSBvdXRwdXQgd2lsbCBub3QgaW5jbHVkZSBcImluXCIgb3IgXCJhZ29cIiBwcmVmaXhlcy9zdWZmaXhlcy5cbiAgICogICAgICAgICAgICAgICAgICAgICAgICAgSWYgYGZhbHNlYCwgdGhlIG91dHB1dCB3aWxsIGluY2x1ZGUgdGhlc2UgYmFzZWQgb24gd2hldGhlciB0aGUgdGltZSBpcyBpbiB0aGUgZnV0dXJlIG9yIHBhc3QuXG4gICAqIEByZXR1cm5zIFRoZSBmb3JtYXR0ZWQgYW5kIHRyYW5zbGF0ZWQgdGltZSBkaWZmZXJlbmNlIHN0cmluZy5cbiAgICovXG4gIHRyYW5zZm9ybShpbnB1dDogRGF0ZSB8IG51bWJlciwgbm9QcmVmaXhPclN1ZmZpeCA9IGZhbHNlKTogc3RyaW5nIHtcbiAgICBpZiAoaW5wdXQgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIE5VTExfVkFMVUVfUExBQ0VIT0xERVI7XG4gICAgfVxuXG4gICAgbGV0IGRpZmZlcmVuY2VNczogbnVtYmVyO1xuXG4gICAgaWYgKGlucHV0IGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKTtcbiAgICAgIGRpZmZlcmVuY2VNcyA9IGlucHV0LmdldFRpbWUoKSAtIG5vdy5nZXRUaW1lKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRpZmZlcmVuY2VNcyA9IGlucHV0O1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmdldEh1bWFuUmVhZGFibGVUaW1lRGlmZlN0cmluZyhkaWZmZXJlbmNlTXMsIG5vUHJlZml4T3JTdWZmaXgpO1xuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgYSBodW1hbi1yZWFkYWJsZSByZXByZXNlbnRhdGlvbiBvZiBhIHRpbWUgZGlmZmVyZW5jZS5cbiAgICpcbiAgICogVGltZSByYW5nZXMgYXJlIHNhbWUgYXMgbW9tZW50LmpzIHRpbWVGcm9tTm93IGZ1bmN0aW9uIGNvdW50ZXJwYXJ0OlxuICAgKiBodHRwczovL21vbWVudGpzY29tLnJlYWR0aGVkb2NzLmlvL2VuL2xhdGVzdC9tb21lbnQvMDQtZGlzcGxheWluZy8wMi1mcm9tbm93L1xuICAgKlxuICAgKiBAcGFyYW0gZGlmZmVyZW5jZU1zIC0gVGhlIHRpbWUgZGlmZmVyZW5jZSBpbiBtaWxsaXNlY29uZHMuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICBBIHBvc2l0aXZlIG51bWJlciBpbmRpY2F0ZXMgYSBmdXR1cmUgdGltZSByZWxhdGl2ZSB0byBub3csIGFuZCBhIG5lZ2F0aXZlIG51bWJlciBpbmRpY2F0ZXMgYSBwYXN0IHRpbWUuXG4gICAqIEBwYXJhbSBub1ByZWZpeE9yU3VmZml4IC0gSWYgYHRydWVgLCB0aGUgb3V0cHV0IHdpbGwgbm90IGluY2x1ZGUgXCJpblwiIG9yIFwiYWdvXCIgcHJlZml4ZXMvc3VmZml4ZXMuXG4gICAqICAgICAgICAgICAgICAgICAgICAgICAgIElmIGBmYWxzZWAsIHRoZSBvdXRwdXQgd2lsbCBpbmNsdWRlIHRoZXNlIGJhc2VkIG9uIHdoZXRoZXIgdGhlIHRpbWUgaXMgaW4gdGhlIGZ1dHVyZSBvciBwYXN0LlxuICAgKiBAcmV0dXJucyBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIHRpbWUgZGlmZmVyZW5jZSBpbiBhIGh1bWFuLXJlYWRhYmxlIGZvcm1hdC5cbiAgICogICAgICAgICAgICAgICAgICAgIFRoZSBmb3JtYXQgZGVwZW5kcyBvbiB0aGUgZHVyYXRpb24gb2YgdGhlIGRpZmZlcmVuY2U6XG4gICAqICAgICAgICAgICAgICAgICAgICAtIExlc3MgdGhhbiA0NSBzZWNvbmRzOiByZXR1cm5zICdhIGZldyBzZWNvbmRzJ1xuICAgKiAgICAgICAgICAgICAgICAgICAgLSA0NSB0byA4OSBzZWNvbmRzOiByZXR1cm5zICdhIG1pbnV0ZSdcbiAgICogICAgICAgICAgICAgICAgICAgIC0gOTAgc2Vjb25kcyB0byA0NCBtaW51dGVzOiByZXR1cm5zIHRoZSBudW1iZXIgb2YgbWludXRlc1xuICAgKiAgICAgICAgICAgICAgICAgICAgLSA0NSB0byA4OSBtaW51dGVzOiByZXR1cm5zICdhbiBob3VyJ1xuICAgKiAgICAgICAgICAgICAgICAgICAgLSA5MCBtaW51dGVzIHRvIDIxIGhvdXJzOiByZXR1cm5zIHRoZSBudW1iZXIgb2YgaG91cnNcbiAgICogICAgICAgICAgICAgICAgICAgIC0gMjIgdG8gMzUgaG91cnM6IHJldHVybnMgJ2EgZGF5J1xuICAgKiAgICAgICAgICAgICAgICAgICAgLSAzNiBob3VycyB0byAyNSBkYXlzOiByZXR1cm5zIHRoZSBudW1iZXIgb2YgZGF5c1xuICAgKiAgICAgICAgICAgICAgICAgICAgLSAyNiB0byA0NSBkYXlzOiByZXR1cm5zICdhIG1vbnRoJ1xuICAgKiAgICAgICAgICAgICAgICAgICAgLSA0NSB0byAzMTkgZGF5czogcmV0dXJucyB0aGUgbnVtYmVyIG9mIG1vbnRoc1xuICAgKiAgICAgICAgICAgICAgICAgICAgLSAzMjAgZGF5cyB0byAxLjUgeWVhcnM6IHJldHVybnMgJ2EgeWVhcidcbiAgICogICAgICAgICAgICAgICAgICAgIC0gTW9yZSB0aGFuIDEuNSB5ZWFyczogcmV0dXJucyB0aGUgbnVtYmVyIG9mIHllYXJzXG4gICAqL1xuICBnZXRIdW1hblJlYWRhYmxlVGltZURpZmZTdHJpbmcoZGlmZmVyZW5jZU1zOiBudW1iZXIsIG5vUHJlZml4T3JTdWZmaXg6IGJvb2xlYW4pOiBzdHJpbmcge1xuICAgIGlmIChkaWZmZXJlbmNlTXMgPT0gbnVsbCkge1xuICAgICAgcmV0dXJuIE5VTExfVkFMVUVfUExBQ0VIT0xERVI7XG4gICAgfVxuXG4gICAgY29uc3QgaXNJbkZ1dHVyZSA9IGRpZmZlcmVuY2VNcyA+IDA7XG5cbiAgICBkaWZmZXJlbmNlTXMgPSBNYXRoLmFicyhkaWZmZXJlbmNlTXMpO1xuXG4gICAgY29uc3QgY29uZGl0aW9ucyA9IFtcbiAgICAgIHRoaXMud2l0aGluRmV3U2Vjb25kcy5iaW5kKHRoaXMpLFxuICAgICAgdGhpcy53aXRoaW5NaW51dGUuYmluZCh0aGlzKSxcbiAgICAgIHRoaXMud2l0aGluTWludXRlcy5iaW5kKHRoaXMpLFxuICAgICAgdGhpcy53aXRoaW5Ib3VyLmJpbmQodGhpcyksXG4gICAgICB0aGlzLndpdGhpbkhvdXJzLmJpbmQodGhpcyksXG4gICAgICB0aGlzLndpdGhpbkRheS5iaW5kKHRoaXMpLFxuICAgICAgdGhpcy53aXRoaW5EYXlzLmJpbmQodGhpcyksXG4gICAgICB0aGlzLndpdGhpbk1vbnRoLmJpbmQodGhpcyksXG4gICAgICB0aGlzLndpdGhpbk1vbnRocy5iaW5kKHRoaXMpLFxuICAgICAgdGhpcy53aXRoaW5ZZWFyLmJpbmQodGhpcyksXG4gICAgICB0aGlzLndpdGhpblllYXJzLmJpbmQodGhpcylcbiAgICBdO1xuXG4gICAgZm9yIChjb25zdCBjb25kaXRpb24gb2YgY29uZGl0aW9ucykge1xuICAgICAgY29uc3QgcmVzdWx0ID0gY29uZGl0aW9uKGRpZmZlcmVuY2VNcywgbm9QcmVmaXhPclN1ZmZpeCwgaXNJbkZ1dHVyZSk7XG4gICAgICBpZiAocmVzdWx0ICE9PSBudWxsKSB7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB3aXRoaW5GZXdTZWNvbmRzKFxuICAgIGRpZmZlcmVuY2VNczogbnVtYmVyLFxuICAgIG5vUHJlZml4T3JTdWZmaXg6IGJvb2xlYW4sXG4gICAgaXNJbkZ1dHVyZTogYm9vbGVhblxuICApOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5TZWNvbmRzID0gZGlmZmVyZW5jZU1zIC8gMTAwMDtcbiAgICBpZiAoZGlmZmVyZW5jZUluU2Vjb25kcyA8IDQ1KSB7XG4gICAgICBpZiAobm9QcmVmaXhPclN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnYSBmZXcgc2Vjb25kcycpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0luRnV0dXJlXG4gICAgICAgID8gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnaW4gYSBmZXcgc2Vjb25kcycpKVxuICAgICAgICA6IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ2EgZmV3IHNlY29uZHMgYWdvJykpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgd2l0aGluTWludXRlKFxuICAgIGRpZmZlcmVuY2VNczogbnVtYmVyLFxuICAgIG5vUHJlZml4T3JTdWZmaXg6IGJvb2xlYW4sXG4gICAgaXNJbkZ1dHVyZTogYm9vbGVhblxuICApOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5TZWNvbmRzID0gZGlmZmVyZW5jZU1zIC8gMTAwMDtcbiAgICBpZiAoZGlmZmVyZW5jZUluU2Vjb25kcyA8IDkwKSB7XG4gICAgICBpZiAobm9QcmVmaXhPclN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnYSBtaW51dGUnKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNJbkZ1dHVyZVxuICAgICAgICA/IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ2luIGEgbWludXRlJykpXG4gICAgICAgIDogdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnYSBtaW51dGUgYWdvJykpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgd2l0aGluTWludXRlcyhcbiAgICBkaWZmZXJlbmNlTXM6IG51bWJlcixcbiAgICBub1ByZWZpeE9yU3VmZml4OiBib29sZWFuLFxuICAgIGlzSW5GdXR1cmU6IGJvb2xlYW5cbiAgKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluU2Vjb25kcyA9IGRpZmZlcmVuY2VNcyAvIDEwMDA7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluTWludXRlcyA9IGRpZmZlcmVuY2VJblNlY29uZHMgLyA2MDtcblxuICAgIGlmIChkaWZmZXJlbmNlSW5NaW51dGVzIDwgNDUpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHsgY291bnQ6IE1hdGgucm91bmQoZGlmZmVyZW5jZUluTWludXRlcykgfTtcblxuICAgICAgaWYgKG5vUHJlZml4T3JTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ3t7IGNvdW50IH19IG1pbnV0ZXMnKSwgcGFyYW1zKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0luRnV0dXJlXG4gICAgICAgID8gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnaW4ge3sgY291bnQgfX0gbWludXRlcycpLCBwYXJhbXMpXG4gICAgICAgIDogdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgne3sgY291bnQgfX0gbWludXRlcyBhZ28nKSwgcGFyYW1zKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwcml2YXRlIHdpdGhpbkhvdXIoXG4gICAgZGlmZmVyZW5jZU1zOiBudW1iZXIsXG4gICAgbm9QcmVmaXhPclN1ZmZpeDogYm9vbGVhbixcbiAgICBpc0luRnV0dXJlOiBib29sZWFuXG4gICk6IHN0cmluZyB8IG51bGwge1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJblNlY29uZHMgPSBkaWZmZXJlbmNlTXMgLyAxMDAwO1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJbk1pbnV0ZXMgPSBkaWZmZXJlbmNlSW5TZWNvbmRzIC8gNjA7XG5cbiAgICBpZiAoZGlmZmVyZW5jZUluTWludXRlcyA8IDkwKSB7XG4gICAgICBpZiAobm9QcmVmaXhPclN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnYW4gaG91cicpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0luRnV0dXJlXG4gICAgICAgID8gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnaW4gYW4gaG91cicpKVxuICAgICAgICA6IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ2FuIGhvdXIgYWdvJykpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgd2l0aGluSG91cnMoXG4gICAgZGlmZmVyZW5jZU1zOiBudW1iZXIsXG4gICAgbm9QcmVmaXhPclN1ZmZpeDogYm9vbGVhbixcbiAgICBpc0luRnV0dXJlOiBib29sZWFuXG4gICk6IHN0cmluZyB8IG51bGwge1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJblNlY29uZHMgPSBkaWZmZXJlbmNlTXMgLyAxMDAwO1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJbk1pbnV0ZXMgPSBkaWZmZXJlbmNlSW5TZWNvbmRzIC8gNjA7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluSG91cnMgPSBkaWZmZXJlbmNlSW5NaW51dGVzIC8gNjA7XG5cbiAgICBpZiAoZGlmZmVyZW5jZUluSG91cnMgPCAyMikge1xuICAgICAgY29uc3QgcGFyYW1zID0geyBjb3VudDogTWF0aC5yb3VuZChkaWZmZXJlbmNlSW5Ib3VycykgfTtcblxuICAgICAgaWYgKG5vUHJlZml4T3JTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ3t7IGNvdW50IH19IGhvdXJzJyksIHBhcmFtcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNJbkZ1dHVyZVxuICAgICAgICA/IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ2luIHt7IGNvdW50IH19IGhvdXJzJyksIHBhcmFtcylcbiAgICAgICAgOiB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCd7eyBjb3VudCB9fSBob3VycyBhZ28nKSwgcGFyYW1zKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwcml2YXRlIHdpdGhpbkRheShcbiAgICBkaWZmZXJlbmNlTXM6IG51bWJlcixcbiAgICBub1ByZWZpeE9yU3VmZml4OiBib29sZWFuLFxuICAgIGlzSW5GdXR1cmU6IGJvb2xlYW5cbiAgKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluU2Vjb25kcyA9IGRpZmZlcmVuY2VNcyAvIDEwMDA7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluTWludXRlcyA9IGRpZmZlcmVuY2VJblNlY29uZHMgLyA2MDtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5Ib3VycyA9IGRpZmZlcmVuY2VJbk1pbnV0ZXMgLyA2MDtcblxuICAgIGlmIChkaWZmZXJlbmNlSW5Ib3VycyA8IDM2KSB7XG4gICAgICBpZiAobm9QcmVmaXhPclN1ZmZpeCkge1xuICAgICAgICByZXR1cm4gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnYSBkYXknKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNJbkZ1dHVyZVxuICAgICAgICA/IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ2luIGEgZGF5JykpXG4gICAgICAgIDogdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnYSBkYXkgYWdvJykpO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgd2l0aGluRGF5cyhcbiAgICBkaWZmZXJlbmNlTXM6IG51bWJlcixcbiAgICBub1ByZWZpeE9yU3VmZml4OiBib29sZWFuLFxuICAgIGlzSW5GdXR1cmU6IGJvb2xlYW5cbiAgKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluU2Vjb25kcyA9IGRpZmZlcmVuY2VNcyAvIDEwMDA7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluTWludXRlcyA9IGRpZmZlcmVuY2VJblNlY29uZHMgLyA2MDtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5Ib3VycyA9IGRpZmZlcmVuY2VJbk1pbnV0ZXMgLyA2MDtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5EYXlzID0gZGlmZmVyZW5jZUluSG91cnMgLyAyNDtcblxuICAgIGlmIChkaWZmZXJlbmNlSW5EYXlzIDwgMjYpIHtcbiAgICAgIGNvbnN0IHBhcmFtcyA9IHsgY291bnQ6IE1hdGgucm91bmQoZGlmZmVyZW5jZUluRGF5cykgfTtcbiAgICAgIGlmIChub1ByZWZpeE9yU3VmZml4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCd7eyBjb3VudCB9fSBkYXlzJyksIHBhcmFtcyk7XG4gICAgICB9XG4gICAgICByZXR1cm4gaXNJbkZ1dHVyZVxuICAgICAgICA/IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ2luIHt7IGNvdW50IH19IGRheXMnKSwgcGFyYW1zKVxuICAgICAgICA6IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ3t7IGNvdW50IH19IGRheXMgYWdvJyksIHBhcmFtcyk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSB3aXRoaW5Nb250aChcbiAgICBkaWZmZXJlbmNlTXM6IG51bWJlcixcbiAgICBub1ByZWZpeE9yU3VmZml4OiBib29sZWFuLFxuICAgIGlzSW5GdXR1cmU6IGJvb2xlYW5cbiAgKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluU2Vjb25kcyA9IGRpZmZlcmVuY2VNcyAvIDEwMDA7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluTWludXRlcyA9IGRpZmZlcmVuY2VJblNlY29uZHMgLyA2MDtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5Ib3VycyA9IGRpZmZlcmVuY2VJbk1pbnV0ZXMgLyA2MDtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5EYXlzID0gZGlmZmVyZW5jZUluSG91cnMgLyAyNDtcblxuICAgIGlmIChkaWZmZXJlbmNlSW5EYXlzIDwgNDUpIHtcbiAgICAgIGlmIChub1ByZWZpeE9yU3VmZml4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCdhIG1vbnRoJykpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGlzSW5GdXR1cmVcbiAgICAgICAgPyB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCdpbiBhIG1vbnRoJykpXG4gICAgICAgIDogdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnYSBtb250aCBhZ28nKSk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSB3aXRoaW5Nb250aHMoXG4gICAgZGlmZmVyZW5jZU1zOiBudW1iZXIsXG4gICAgbm9QcmVmaXhPclN1ZmZpeDogYm9vbGVhbixcbiAgICBpc0luRnV0dXJlOiBib29sZWFuXG4gICk6IHN0cmluZyB8IG51bGwge1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJblNlY29uZHMgPSBkaWZmZXJlbmNlTXMgLyAxMDAwO1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJbk1pbnV0ZXMgPSBkaWZmZXJlbmNlSW5TZWNvbmRzIC8gNjA7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluSG91cnMgPSBkaWZmZXJlbmNlSW5NaW51dGVzIC8gNjA7XG4gICAgY29uc3QgZGlmZmVyZW5jZUluRGF5cyA9IGRpZmZlcmVuY2VJbkhvdXJzIC8gMjQ7XG5cbiAgICBpZiAoZGlmZmVyZW5jZUluRGF5cyA8IDMyMCkge1xuICAgICAgY29uc3QgcGFyYW1zID0geyBjb3VudDogTWF0aC5yb3VuZChkaWZmZXJlbmNlSW5EYXlzIC8gMzApIH07XG5cbiAgICAgIGlmIChub1ByZWZpeE9yU3VmZml4KSB7XG4gICAgICAgIHJldHVybiB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCd7eyBjb3VudCB9fSBtb250aHMnKSwgcGFyYW1zKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0luRnV0dXJlXG4gICAgICAgID8gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnaW4ge3sgY291bnQgfX0gbW9udGhzJyksIHBhcmFtcylcbiAgICAgICAgOiB0aGlzLnRyYW5zbGF0ZVNlcnZpY2UuaW5zdGFudChnZXR0ZXh0KCd7eyBjb3VudCB9fSBtb250aHMgYWdvJyksIHBhcmFtcyk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgcHJpdmF0ZSB3aXRoaW5ZZWFyKFxuICAgIGRpZmZlcmVuY2VNczogbnVtYmVyLFxuICAgIG5vUHJlZml4T3JTdWZmaXg6IGJvb2xlYW4sXG4gICAgaXNJbkZ1dHVyZTogYm9vbGVhblxuICApOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5TZWNvbmRzID0gZGlmZmVyZW5jZU1zIC8gMTAwMDtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5NaW51dGVzID0gZGlmZmVyZW5jZUluU2Vjb25kcyAvIDYwO1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJbkhvdXJzID0gZGlmZmVyZW5jZUluTWludXRlcyAvIDYwO1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJbkRheXMgPSBkaWZmZXJlbmNlSW5Ib3VycyAvIDI0O1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJblllYXJzID0gZGlmZmVyZW5jZUluRGF5cyAvIDM2NTtcblxuICAgIGlmIChkaWZmZXJlbmNlSW5ZZWFycyA8IDEuNSkge1xuICAgICAgaWYgKG5vUHJlZml4T3JTdWZmaXgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ2EgeWVhcicpKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBpc0luRnV0dXJlXG4gICAgICAgID8gdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnaW4gYSB5ZWFyJykpXG4gICAgICAgIDogdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgnYSB5ZWFyIGFnbycpKTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwcml2YXRlIHdpdGhpblllYXJzKFxuICAgIGRpZmZlcmVuY2VNczogbnVtYmVyLFxuICAgIG5vUHJlZml4T3JTdWZmaXg6IGJvb2xlYW4sXG4gICAgaXNJbkZ1dHVyZTogYm9vbGVhblxuICApOiBzdHJpbmcgfCBudWxsIHtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5TZWNvbmRzID0gZGlmZmVyZW5jZU1zIC8gMTAwMDtcbiAgICBjb25zdCBkaWZmZXJlbmNlSW5NaW51dGVzID0gZGlmZmVyZW5jZUluU2Vjb25kcyAvIDYwO1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJbkhvdXJzID0gZGlmZmVyZW5jZUluTWludXRlcyAvIDYwO1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJbkRheXMgPSBkaWZmZXJlbmNlSW5Ib3VycyAvIDI0O1xuICAgIGNvbnN0IGRpZmZlcmVuY2VJblllYXJzID0gZGlmZmVyZW5jZUluRGF5cyAvIDM2NTtcblxuICAgIGNvbnN0IHBhcmFtcyA9IHsgY291bnQ6IE1hdGgucm91bmQoZGlmZmVyZW5jZUluWWVhcnMpIH07XG5cbiAgICBpZiAobm9QcmVmaXhPclN1ZmZpeCkge1xuICAgICAgcmV0dXJuIHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ3t7IGNvdW50IH19IHllYXJzJyksIHBhcmFtcyk7XG4gICAgfVxuICAgIHJldHVybiBpc0luRnV0dXJlXG4gICAgICA/IHRoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KGdldHRleHQoJ2luIHt7IGNvdW50IH19IHllYXJzJyksIHBhcmFtcylcbiAgICAgIDogdGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoZ2V0dGV4dCgne3sgY291bnQgfX0geWVhcnMgYWdvJyksIHBhcmFtcyk7XG4gIH1cbn1cbiJdfQ==