UNPKG

angular-bootstrap-datetimepicker

Version:

Native Angular (8+) datetime picker component styled by Twitter Bootstrap 4.

268 lines 34.6 kB
/** * @license * Copyright 2013-present Dale Lotts All Rights Reserved. * http://www.dalelotts.com * * Use of this source code is governed by an MIT-style license that can be * found in the LICENSE file at https://github.com/dalelotts/angular-bootstrap-datetimepicker/blob/master/LICENSE */ import * as _moment from 'moment'; /** * Work around for moment namespace conflict when used with webpack and rollup. * See https://github.com/dherges/ng-packagr/issues/163 * * Depending on whether rollup is used, moment needs to be imported differently. * Since Moment.js doesn't have a default export, we normally need to import using * the `* as`syntax. * * rollup creates a synthetic default module and we thus need to import it using * the `default as` syntax. * * @internal **/ const moment = _moment; /** * Default implementation for the `minute` view. */ export class DlMinuteModelProvider { constructor() { this.step = 5; } /** * Receives `minuteStep` configuration changes detected by Angular. * * Changes where the value has not changed are ignored. * * Setting `minuteStep` to `null` or `undefined` will result in a * minuteStep of `5`. * * @param changes * the input changes detected by Angular. */ onChanges(changes) { const minuteStepChange = changes['minuteStep']; if (minuteStepChange && (minuteStepChange.previousValue !== minuteStepChange.currentValue)) { this.step = minuteStepChange.currentValue; if (this.step === null || this.step === undefined) { this.step = 5; } } } /** * Returns the `minute` model for the specified moment in `local` time with the * `active` minute set to the beginning of the hour. * * The `minute` model represents an hour (60 minutes) as three rows with four columns * and each cell representing 5-minute increments. * * The hour always starts at midnight. * * Each cell represents a 5-minute increment starting at midnight. * * The `active` minute will be the 5-minute increments less than or equal to the specified milliseconds. * * @param milliseconds * the moment in time from which the minute model will be created. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * the model representing the specified moment in time. */ getModel(milliseconds, selectedMilliseconds) { const startDate = moment(milliseconds).startOf('hour'); const currentMilliseconds = moment().valueOf(); const minuteSteps = new Array(Math.ceil(60 / this.step)).fill(0).map((zero, index) => zero + index * this.step); const minuteValues = minuteSteps.map((minutesToAdd) => moment(startDate).add(minutesToAdd, 'minutes').valueOf()); const activeValue = moment(minuteValues.filter((value) => value <= milliseconds).pop()).valueOf(); const nowValue = currentMilliseconds >= startDate.valueOf() && currentMilliseconds <= moment(startDate).endOf('hour').valueOf() ? moment(minuteValues.filter((value) => value <= currentMilliseconds).pop()).valueOf() : null; const previousHour = moment(startDate).subtract(1, 'hour'); const nextHour = moment(startDate).add(1, 'hour'); const selectedValue = selectedMilliseconds === null || selectedMilliseconds === undefined ? selectedMilliseconds : moment(minuteValues.filter((value) => value <= selectedMilliseconds).pop()).valueOf(); const rows = new Array(Math.ceil(minuteSteps.length / 4)) .fill(0) .map((zero, index) => zero + index) .map((value) => { return { cells: minuteSteps.slice((value * 4), (value * 4) + 4).map(rowOfMinutes) }; }); return { viewName: 'minute', viewLabel: startDate.format('lll'), activeDate: activeValue, leftButton: { value: previousHour.valueOf(), ariaLabel: `Go to ${previousHour.format('lll')}`, classes: {}, }, upButton: { value: startDate.valueOf(), ariaLabel: `Go to ${startDate.format('ll')}`, classes: {}, }, rightButton: { value: nextHour.valueOf(), ariaLabel: `Go to ${nextHour.format('lll')}`, classes: {}, }, rows }; function rowOfMinutes(stepMinutes) { const minuteMoment = moment(startDate).add(stepMinutes, 'minutes'); return { display: minuteMoment.format('LT'), ariaLabel: minuteMoment.format('LLL'), value: minuteMoment.valueOf(), classes: { 'dl-abdtp-active': activeValue === minuteMoment.valueOf(), 'dl-abdtp-selected': selectedValue === minuteMoment.valueOf(), 'dl-abdtp-now': nowValue === minuteMoment.valueOf(), } }; } } /** * Move the active `minute` one row `down` from the specified moment in time. * * Moving `down` can result in the `active` minute being part of a different hour than * the specified `fromMilliseconds`, in this case the hour represented by the model * will change to show the correct hour. * * @param fromMilliseconds * the moment in time from which the next `minute` model `down` will be constructed. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * model containing an `active` `minute` one row `down` from the specified moment in time. */ goDown(fromMilliseconds, selectedMilliseconds) { return this.getModel(moment(fromMilliseconds).add(this.step * 4, 'minutes').valueOf(), selectedMilliseconds); } /** * Move the active `minute` one row `down` from the specified moment in time. * * Moving `down` can result in the `active` minute being part of a different hour than * the specified `fromMilliseconds`, in this case the hour represented by the model * will change to show the correct hour. * * @param fromMilliseconds * the moment in time from which the next `minute` model `down` will be constructed. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * model containing an `active` `minute` one row `down` from the specified moment in time. */ goUp(fromMilliseconds, selectedMilliseconds) { return this.getModel(moment(fromMilliseconds).subtract(this.step * 4, 'minutes').valueOf(), selectedMilliseconds); } /** * Move the `active` date one cell to `left` in the current `minute` view. * * Moving `left` can result in the `active` hour being part of a different hour than * the specified `fromMilliseconds`, in this case the hour represented by the model * will change to show the correct hour. * * @param fromMilliseconds * the moment in time from which the `minute` model to the `left` will be constructed. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * model containing an `active` `minute` one cell to the `left` of the specified moment in time. */ goLeft(fromMilliseconds, selectedMilliseconds) { return this.getModel(moment(fromMilliseconds).subtract(this.step, 'minutes').valueOf(), selectedMilliseconds); } /** * Move `active` minute one cell to `right` in the current `minute` view. * * Moving `right` can result in the `active` hour being part of a different hour than * the specified `fromMilliseconds`, in this case the hour represented by the model * will change to show the correct hour. * * @param fromMilliseconds * the moment in time from which the `minute` model to the `right` will be constructed. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * model containing an `active` `minute` one cell to the `right` of the specified moment in time. */ goRight(fromMilliseconds, selectedMilliseconds) { return this.getModel(moment(fromMilliseconds).add(this.step, 'minutes').valueOf(), selectedMilliseconds); } /** * Move the active `minute` one hour `down` from the specified moment in time. * * The `active` minute will be `one (1) hour after` the specified milliseconds. * This moves the `active` date one `page` `down` from the current `minute` view. * * The next cell `page-down` will be in a different hour than the currently * displayed view and the model time range will include the new active cell. * * @param fromMilliseconds * the moment in time from which the next `month` model page `down` will be constructed. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * model containing an `active` `month` one year `down` from the specified moment in time. */ pageDown(fromMilliseconds, selectedMilliseconds) { return this.getModel(moment(fromMilliseconds).add(1, 'hour').valueOf(), selectedMilliseconds); } /** * Move the active `minute` one hour `up` from the specified moment in time. * * The `active` minute will be `one (1) hour before` the specified milliseconds. * This moves the `active` date one `page` `down` from the current `minute` view. * * The next cell `page-up` will be in a different hour than the currently * displayed view and the model time range will include the new active cell. * * @param fromMilliseconds * the moment in time from which the next `month` model page `down` will be constructed. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * model containing an `active` `month` one year `down` from the specified moment in time. */ pageUp(fromMilliseconds, selectedMilliseconds) { return this.getModel(moment(fromMilliseconds).subtract(1, 'hour').valueOf(), selectedMilliseconds); } /** * Move the `active` `minute` to the last cell of the current hour. * * The view or time range will not change unless the `fromMilliseconds` value * is in a different hour than the displayed decade. * * @param fromMilliseconds * the moment in time from which the last cell will be calculated. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * a model with the last cell in the view as the active `minute`. */ goEnd(fromMilliseconds, selectedMilliseconds) { return this.getModel(moment(fromMilliseconds) .endOf('hour') .valueOf(), selectedMilliseconds); } /** * Move the `active` `minute` to the first cell of the current hour. * * The view or time range will not change unless the `fromMilliseconds` value * is in a different hour than the displayed decade. * * @param fromMilliseconds * the moment in time from which the first cell will be calculated. * @param selectedMilliseconds * the current value of the date/time picker. * @returns * a model with the first cell in the view as the active `minute`. */ goHome(fromMilliseconds, selectedMilliseconds) { return this.getModel(moment(fromMilliseconds).startOf('hour').valueOf(), selectedMilliseconds); } } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGwtbW9kZWwtcHJvdmlkZXItbWludXRlLmpzIiwic291cmNlUm9vdCI6Im5nOi8vYW5ndWxhci1ib290c3RyYXAtZGF0ZXRpbWVwaWNrZXIvIiwic291cmNlcyI6WyJkbC1kYXRlLXRpbWUtcGlja2VyL2RsLW1vZGVsLXByb3ZpZGVyLW1pbnV0ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7OztHQU9HO0FBR0gsT0FBTyxLQUFLLE9BQU8sTUFBTSxRQUFRLENBQUM7QUFJbEM7Ozs7Ozs7Ozs7OztJQVlJO0FBQ0osTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDO0FBRXZCOztHQUVHO0FBQ0gsTUFBTSxPQUFPLHFCQUFxQjtJQUFsQztRQUVVLFNBQUksR0FBRyxDQUFDLENBQUM7SUF3UW5CLENBQUM7SUF0UUM7Ozs7Ozs7Ozs7T0FVRztJQUVILFNBQVMsQ0FBQyxPQUFzQjtRQUU5QixNQUFNLGdCQUFnQixHQUFHLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUUvQyxJQUFJLGdCQUFnQjtlQUNmLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxLQUFLLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxFQUNyRTtZQUNBLElBQUksQ0FBQyxJQUFJLEdBQUcsZ0JBQWdCLENBQUMsWUFBWSxDQUFDO1lBQzFDLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxJQUFJLElBQUksSUFBSSxDQUFDLElBQUksS0FBSyxTQUFTLEVBQUU7Z0JBQ2pELElBQUksQ0FBQyxJQUFJLEdBQUcsQ0FBQyxDQUFDO2FBQ2Y7U0FDRjtJQUNILENBQUM7SUFHRDs7Ozs7Ozs7Ozs7Ozs7Ozs7OztPQW1CRztJQUNILFFBQVEsQ0FBQyxZQUFvQixFQUFFLG9CQUE0QjtRQUN6RCxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3ZELE1BQU0sbUJBQW1CLEdBQUcsTUFBTSxFQUFFLENBQUMsT0FBTyxFQUFFLENBQUM7UUFF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QUFPLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO0lBQ3JHLENBQUM7SUFFRDs7Ozs7Ozs7Ozs7O09BWUc7SUFDSCxLQUFLLENBQUMsZ0JBQXdCLEVBQUUsb0JBQTRCO1FBQzFELE9BQU8sSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsZ0JBQWdCLENBQUM7YUFDMUMsS0FBSyxDQUFDLE1BQU0sQ0FBQzthQUNiLE9BQU8sRUFBRSxFQUFFLG9CQUFvQixDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7Ozs7Ozs7Ozs7T0FZRztJQUNILE1BQU0sQ0FBQyxnQkFBd0IsRUFBRSxvQkFBNEI7UUFDM0QsT0FBTyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxPQUFPLEVBQUUsRUFBRSxvQkFBb0IsQ0FBQyxDQUFDO0lBQ2pHLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCAyMDEzLXByZXNlbnQgRGFsZSBMb3R0cyBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICogaHR0cDovL3d3dy5kYWxlbG90dHMuY29tXG4gKlxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcbiAqIGZvdW5kIGluIHRoZSBMSUNFTlNFIGZpbGUgYXQgaHR0cHM6Ly9naXRodWIuY29tL2RhbGVsb3R0cy9hbmd1bGFyLWJvb3RzdHJhcC1kYXRldGltZXBpY2tlci9ibG9iL21hc3Rlci9MSUNFTlNFXG4gKi9cblxuaW1wb3J0IHtTaW1wbGVDaGFuZ2VzfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCAqIGFzIF9tb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7RGxEYXRlVGltZVBpY2tlck1vZGVsfSBmcm9tICcuL2RsLWRhdGUtdGltZS1waWNrZXItbW9kZWwnO1xuaW1wb3J0IHtEbE1vZGVsUHJvdmlkZXJ9IGZyb20gJy4vZGwtbW9kZWwtcHJvdmlkZXInO1xuXG4vKipcbiAqIFdvcmsgYXJvdW5kIGZvciBtb21lbnQgbmFtZXNwYWNlIGNvbmZsaWN0IHdoZW4gdXNlZCB3aXRoIHdlYnBhY2sgYW5kIHJvbGx1cC5cbiAqIFNlZSBodHRwczovL2dpdGh1Yi5jb20vZGhlcmdlcy9uZy1wYWNrYWdyL2lzc3Vlcy8xNjNcbiAqXG4gKiBEZXBlbmRpbmcgb24gd2hldGhlciByb2xsdXAgaXMgdXNlZCwgbW9tZW50IG5lZWRzIHRvIGJlIGltcG9ydGVkIGRpZmZlcmVudGx5LlxuICogU2luY2UgTW9tZW50LmpzIGRvZXNuJ3QgaGF2ZSBhIGRlZmF1bHQgZXhwb3J0LCB3ZSBub3JtYWxseSBuZWVkIHRvIGltcG9ydCB1c2luZ1xuICogdGhlIGAqIGFzYHN5bnRheC5cbiAqXG4gKiByb2xsdXAgY3JlYXRlcyBhIHN5bnRoZXRpYyBkZWZhdWx0IG1vZHVsZSBhbmQgd2UgdGh1cyBuZWVkIHRvIGltcG9ydCBpdCB1c2luZ1xuICogdGhlIGBkZWZhdWx0IGFzYCBzeW50YXguXG4gKlxuICogQGludGVybmFsXG4gKiovXG5jb25zdCBtb21lbnQgPSBfbW9tZW50O1xuXG4vKipcbiAqIERlZmF1bHQgaW1wbGVtZW50YXRpb24gZm9yIHRoZSBgbWludXRlYCB2aWV3LlxuICovXG5leHBvcnQgY2xhc3MgRGxNaW51dGVNb2RlbFByb3ZpZGVyIGltcGxlbWVudHMgRGxNb2RlbFByb3ZpZGVyIHtcblxuICBwcml2YXRlIHN0ZXAgPSA1O1xuXG4gIC8qKlxuICAgKiBSZWNlaXZlcyBgbWludXRlU3RlcGAgY29uZmlndXJhdGlvbiBjaGFuZ2VzIGRldGVjdGVkIGJ5IEFuZ3VsYXIuXG4gICAqXG4gICAqIENoYW5nZXMgd2hlcmUgdGhlIHZhbHVlIGhhcyBub3QgY2hhbmdlZCBhcmUgaWdub3JlZC5cbiAgICpcbiAgICogU2V0dGluZyBgbWludXRlU3RlcGAgdG8gYG51bGxgIG9yIGB1bmRlZmluZWRgIHdpbGwgcmVzdWx0IGluIGFcbiAgICogbWludXRlU3RlcCBvZiBgNWAuXG4gICAqXG4gICAqIEBwYXJhbSBjaGFuZ2VzXG4gICAqICB0aGUgaW5wdXQgY2hhbmdlcyBkZXRlY3RlZCBieSBBbmd1bGFyLlxuICAgKi9cblxuICBvbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuXG4gICAgY29uc3QgbWludXRlU3RlcENoYW5nZSA9IGNoYW5nZXNbJ21pbnV0ZVN0ZXAnXTtcblxuICAgIGlmIChtaW51dGVTdGVwQ2hhbmdlXG4gICAgICAmJiAobWludXRlU3RlcENoYW5nZS5wcmV2aW91c1ZhbHVlICE9PSBtaW51dGVTdGVwQ2hhbmdlLmN1cnJlbnRWYWx1ZSlcbiAgICApIHtcbiAgICAgIHRoaXMuc3RlcCA9IG1pbnV0ZVN0ZXBDaGFuZ2UuY3VycmVudFZhbHVlO1xuICAgICAgaWYgKHRoaXMuc3RlcCA9PT0gbnVsbCB8fCB0aGlzLnN0ZXAgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICB0aGlzLnN0ZXAgPSA1O1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGBtaW51dGVgIG1vZGVsIGZvciB0aGUgc3BlY2lmaWVkIG1vbWVudCBpbiBgbG9jYWxgIHRpbWUgd2l0aCB0aGVcbiAgICogYGFjdGl2ZWAgbWludXRlIHNldCB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBob3VyLlxuICAgKlxuICAgKiBUaGUgYG1pbnV0ZWAgbW9kZWwgcmVwcmVzZW50cyBhbiBob3VyICg2MCBtaW51dGVzKSBhcyB0aHJlZSByb3dzIHdpdGggZm91ciBjb2x1bW5zXG4gICAqIGFuZCBlYWNoIGNlbGwgcmVwcmVzZW50aW5nIDUtbWludXRlIGluY3JlbWVudHMuXG4gICAqXG4gICAqIFRoZSBob3VyIGFsd2F5cyBzdGFydHMgYXQgbWlkbmlnaHQuXG4gICAqXG4gICAqIEVhY2ggY2VsbCByZXByZXNlbnRzIGEgNS1taW51dGUgaW5jcmVtZW50IHN0YXJ0aW5nIGF0IG1pZG5pZ2h0LlxuICAgKlxuICAgKiBUaGUgYGFjdGl2ZWAgbWludXRlIHdpbGwgYmUgdGhlIDUtbWludXRlIGluY3JlbWVudHMgbGVzcyB0aGFuIG9yIGVxdWFsIHRvIHRoZSBzcGVjaWZpZWQgbWlsbGlzZWNvbmRzLlxuICAgKlxuICAgKiBAcGFyYW0gbWlsbGlzZWNvbmRzXG4gICAqICB0aGUgbW9tZW50IGluIHRpbWUgZnJvbSB3aGljaCB0aGUgbWludXRlIG1vZGVsIHdpbGwgYmUgY3JlYXRlZC5cbiAgICogQHBhcmFtIHNlbGVjdGVkTWlsbGlzZWNvbmRzXG4gICAqICB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlci5cbiAgICogQHJldHVybnNcbiAgICogIHRoZSBtb2RlbCByZXByZXNlbnRpbmcgdGhlIHNwZWNpZmllZCBtb21lbnQgaW4gdGltZS5cbiAgICovXG4gIGdldE1vZGVsKG1pbGxpc2Vjb25kczogbnVtYmVyLCBzZWxlY3RlZE1pbGxpc2Vjb25kczogbnVtYmVyKTogRGxEYXRlVGltZVBpY2tlck1vZGVsIHtcbiAgICBjb25zdCBzdGFydERhdGUgPSBtb21lbnQobWlsbGlzZWNvbmRzKS5zdGFydE9mKCdob3VyJyk7XG4gICAgY29uc3QgY3VycmVudE1pbGxpc2Vjb25kcyA9IG1vbWVudCgpLnZhbHVlT2YoKTtcblxuICAgIGNvbnN0IG1pbnV0ZVN0ZXBzID0gbmV3IEFycmF5KE1hdGguY2VpbCg2MCAvIHRoaXMuc3RlcCkpLmZpbGwoMCkubWFwKCh6ZXJvLCBpbmRleCkgPT4gemVybyArIGluZGV4ICogdGhpcy5zdGVwKTtcbiAgICBjb25zdCBtaW51dGVWYWx1ZXMgPSBtaW51dGVTdGVwcy5tYXAoKG1pbnV0ZXNUb0FkZCkgPT4gbW9tZW50KHN0YXJ0RGF0ZSkuYWRkKG1pbnV0ZXNUb0FkZCwgJ21pbnV0ZXMnKS52YWx1ZU9mKCkpO1xuICAgIGNvbnN0IGFjdGl2ZVZhbHVlID0gbW9tZW50KG1pbnV0ZVZhbHVlcy5maWx0ZXIoKHZhbHVlKSA9PiB2YWx1ZSA8PSBtaWxsaXNlY29uZHMpLnBvcCgpKS52YWx1ZU9mKCk7XG5cbiAgICBjb25zdCBub3dWYWx1ZSA9IGN1cnJlbnRNaWxsaXNlY29uZHMgPj0gc3RhcnREYXRlLnZhbHVlT2YoKSAmJiBjdXJyZW50TWlsbGlzZWNvbmRzIDw9IG1vbWVudChzdGFydERhdGUpLmVuZE9mKCdob3VyJykudmFsdWVPZigpXG4gICAgICA/IG1vbWVudChtaW51dGVWYWx1ZXMuZmlsdGVyKCh2YWx1ZSkgPT4gdmFsdWUgPD0gY3VycmVudE1pbGxpc2Vjb25kcykucG9wKCkpLnZhbHVlT2YoKVxuICAgICAgOiBudWxsO1xuXG5cbiAgICBjb25zdCBwcmV2aW91c0hvdXIgPSBtb21lbnQoc3RhcnREYXRlKS5zdWJ0cmFjdCgxLCAnaG91cicpO1xuICAgIGNvbnN0IG5leHRIb3VyID0gbW9tZW50KHN0YXJ0RGF0ZSkuYWRkKDEsICdob3VyJyk7XG4gICAgY29uc3Qgc2VsZWN0ZWRWYWx1ZSA9IHNlbGVjdGVkTWlsbGlzZWNvbmRzID09PSBudWxsIHx8IHNlbGVjdGVkTWlsbGlzZWNvbmRzID09PSB1bmRlZmluZWRcbiAgICAgID8gc2VsZWN0ZWRNaWxsaXNlY29uZHNcbiAgICAgIDogbW9tZW50KG1pbnV0ZVZhbHVlcy5maWx0ZXIoKHZhbHVlKSA9PiB2YWx1ZSA8PSBzZWxlY3RlZE1pbGxpc2Vjb25kcykucG9wKCkpLnZhbHVlT2YoKTtcblxuICAgIGNvbnN0IHJvd3MgPSBuZXcgQXJyYXkoTWF0aC5jZWlsKG1pbnV0ZVN0ZXBzLmxlbmd0aCAvIDQpKVxuICAgICAgLmZpbGwoMClcbiAgICAgIC5tYXAoKHplcm8sIGluZGV4KSA9PiB6ZXJvICsgaW5kZXgpXG4gICAgICAubWFwKCh2YWx1ZSkgPT4ge1xuICAgICAgICByZXR1cm4ge2NlbGxzOiBtaW51dGVTdGVwcy5zbGljZSgodmFsdWUgKiA0KSwgKHZhbHVlICogNCkgKyA0KS5tYXAocm93T2ZNaW51dGVzKX07XG4gICAgICB9KTtcblxuICAgIHJldHVybiB7XG4gICAgICB2aWV3TmFtZTogJ21pbnV0ZScsXG4gICAgICB2aWV3TGFiZWw6IHN0YXJ0RGF0ZS5mb3JtYXQoJ2xsbCcpLFxuICAgICAgYWN0aXZlRGF0ZTogYWN0aXZlVmFsdWUsXG4gICAgICBsZWZ0QnV0dG9uOiB7XG4gICAgICAgIHZhbHVlOiBwcmV2aW91c0hvdXIudmFsdWVPZigpLFxuICAgICAgICBhcmlhTGFiZWw6IGBHbyB0byAke3ByZXZpb3VzSG91ci5mb3JtYXQoJ2xsbCcpfWAsXG4gICAgICAgIGNsYXNzZXM6IHt9LFxuICAgICAgfSxcbiAgICAgIHVwQnV0dG9uOiB7XG4gICAgICAgIHZhbHVlOiBzdGFydERhdGUudmFsdWVPZigpLFxuICAgICAgICBhcmlhTGFiZWw6IGBHbyB0byAke3N0YXJ0RGF0ZS5mb3JtYXQoJ2xsJyl9YCxcbiAgICAgICAgY2xhc3Nlczoge30sXG4gICAgICB9LFxuICAgICAgcmlnaHRCdXR0b246IHtcbiAgICAgICAgdmFsdWU6IG5leHRIb3VyLnZhbHVlT2YoKSxcbiAgICAgICAgYXJpYUxhYmVsOiBgR28gdG8gJHtuZXh0SG91ci5mb3JtYXQoJ2xsbCcpfWAsXG4gICAgICAgIGNsYXNzZXM6IHt9LFxuICAgICAgfSxcbiAgICAgIHJvd3NcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gcm93T2ZNaW51dGVzKHN0ZXBNaW51dGVzKToge1xuICAgICAgZGlzcGxheTogc3RyaW5nO1xuICAgICAgYXJpYUxhYmVsOiBzdHJpbmc7XG4gICAgICB2YWx1ZTogbnVtYmVyO1xuICAgICAgY2xhc3Nlczoge307XG4gICAgfSB7XG4gICAgICBjb25zdCBtaW51dGVNb21lbnQgPSBtb21lbnQoc3RhcnREYXRlKS5hZGQoc3RlcE1pbnV0ZXMsICdtaW51dGVzJyk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBkaXNwbGF5OiBtaW51dGVNb21lbnQuZm9ybWF0KCdMVCcpLFxuICAgICAgICBhcmlhTGFiZWw6IG1pbnV0ZU1vbWVudC5mb3JtYXQoJ0xMTCcpLFxuICAgICAgICB2YWx1ZTogbWludXRlTW9tZW50LnZhbHVlT2YoKSxcbiAgICAgICAgY2xhc3Nlczoge1xuICAgICAgICAgICdkbC1hYmR0cC1hY3RpdmUnOiBhY3RpdmVWYWx1ZSA9PT0gbWludXRlTW9tZW50LnZhbHVlT2YoKSxcbiAgICAgICAgICAnZGwtYWJkdHAtc2VsZWN0ZWQnOiBzZWxlY3RlZFZhbHVlID09PSBtaW51dGVNb21lbnQudmFsdWVPZigpLFxuICAgICAgICAgICdkbC1hYmR0cC1ub3cnOiBub3dWYWx1ZSA9PT0gbWludXRlTW9tZW50LnZhbHVlT2YoKSxcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTW92ZSB0aGUgYWN0aXZlIGBtaW51dGVgIG9uZSByb3cgYGRvd25gIGZyb20gdGhlIHNwZWNpZmllZCBtb21lbnQgaW4gdGltZS5cbiAgICpcbiAgICogTW92aW5nIGBkb3duYCBjYW4gcmVzdWx0IGluIHRoZSBgYWN0aXZlYCBtaW51dGUgYmVpbmcgcGFydCBvZiBhIGRpZmZlcmVudCBob3VyIHRoYW5cbiAgICogdGhlIHNwZWNpZmllZCBgZnJvbU1pbGxpc2Vjb25kc2AsIGluIHRoaXMgY2FzZSB0aGUgaG91ciByZXByZXNlbnRlZCBieSB0aGUgbW9kZWxcbiAgICogd2lsbCBjaGFuZ2UgdG8gc2hvdyB0aGUgY29ycmVjdCBob3VyLlxuICAgKlxuICAgKiBAcGFyYW0gZnJvbU1pbGxpc2Vjb25kc1xuICAgKiAgdGhlIG1vbWVudCBpbiB0aW1lIGZyb20gd2hpY2ggdGhlIG5leHQgYG1pbnV0ZWAgbW9kZWwgYGRvd25gIHdpbGwgYmUgY29uc3RydWN0ZWQuXG4gICAqIEBwYXJhbSBzZWxlY3RlZE1pbGxpc2Vjb25kc1xuICAgKiAgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGRhdGUvdGltZSBwaWNrZXIuXG4gICAqIEByZXR1cm5zXG4gICAqICBtb2RlbCBjb250YWluaW5nIGFuIGBhY3RpdmVgIGBtaW51dGVgIG9uZSByb3cgYGRvd25gIGZyb20gdGhlIHNwZWNpZmllZCBtb21lbnQgaW4gdGltZS5cbiAgICovXG4gIGdvRG93bihmcm9tTWlsbGlzZWNvbmRzOiBudW1iZXIsIHNlbGVjdGVkTWlsbGlzZWNvbmRzOiBudW1iZXIpOiBEbERhdGVUaW1lUGlja2VyTW9kZWwge1xuICAgIHJldHVybiB0aGlzLmdldE1vZGVsKG1vbWVudChmcm9tTWlsbGlzZWNvbmRzKS5hZGQodGhpcy5zdGVwICogNCwgJ21pbnV0ZXMnKS52YWx1ZU9mKCksIHNlbGVjdGVkTWlsbGlzZWNvbmRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3ZlIHRoZSBhY3RpdmUgYG1pbnV0ZWAgb25lIHJvdyBgZG93bmAgZnJvbSB0aGUgc3BlY2lmaWVkIG1vbWVudCBpbiB0aW1lLlxuICAgKlxuICAgKiBNb3ZpbmcgYGRvd25gIGNhbiByZXN1bHQgaW4gdGhlIGBhY3RpdmVgIG1pbnV0ZSBiZWluZyBwYXJ0IG9mIGEgZGlmZmVyZW50IGhvdXIgdGhhblxuICAgKiB0aGUgc3BlY2lmaWVkIGBmcm9tTWlsbGlzZWNvbmRzYCwgaW4gdGhpcyBjYXNlIHRoZSBob3VyIHJlcHJlc2VudGVkIGJ5IHRoZSBtb2RlbFxuICAgKiB3aWxsIGNoYW5nZSB0byBzaG93IHRoZSBjb3JyZWN0IGhvdXIuXG4gICAqXG4gICAqIEBwYXJhbSBmcm9tTWlsbGlzZWNvbmRzXG4gICAqICB0aGUgbW9tZW50IGluIHRpbWUgZnJvbSB3aGljaCB0aGUgbmV4dCBgbWludXRlYCBtb2RlbCBgZG93bmAgd2lsbCBiZSBjb25zdHJ1Y3RlZC5cbiAgICogQHBhcmFtIHNlbGVjdGVkTWlsbGlzZWNvbmRzXG4gICAqICB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlci5cbiAgICogQHJldHVybnNcbiAgICogIG1vZGVsIGNvbnRhaW5pbmcgYW4gYGFjdGl2ZWAgYG1pbnV0ZWAgb25lIHJvdyBgZG93bmAgZnJvbSB0aGUgc3BlY2lmaWVkIG1vbWVudCBpbiB0aW1lLlxuICAgKi9cbiAgZ29VcChmcm9tTWlsbGlzZWNvbmRzOiBudW1iZXIsIHNlbGVjdGVkTWlsbGlzZWNvbmRzOiBudW1iZXIpOiBEbERhdGVUaW1lUGlja2VyTW9kZWwge1xuICAgIHJldHVybiB0aGlzLmdldE1vZGVsKG1vbWVudChmcm9tTWlsbGlzZWNvbmRzKS5zdWJ0cmFjdCh0aGlzLnN0ZXAgKiA0LCAnbWludXRlcycpLnZhbHVlT2YoKSwgc2VsZWN0ZWRNaWxsaXNlY29uZHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vdmUgdGhlIGBhY3RpdmVgIGRhdGUgb25lIGNlbGwgdG8gYGxlZnRgIGluIHRoZSBjdXJyZW50IGBtaW51dGVgIHZpZXcuXG4gICAqXG4gICAqIE1vdmluZyBgbGVmdGAgY2FuIHJlc3VsdCBpbiB0aGUgYGFjdGl2ZWAgaG91ciBiZWluZyBwYXJ0IG9mIGEgZGlmZmVyZW50IGhvdXIgdGhhblxuICAgKiB0aGUgc3BlY2lmaWVkIGBmcm9tTWlsbGlzZWNvbmRzYCwgaW4gdGhpcyBjYXNlIHRoZSBob3VyIHJlcHJlc2VudGVkIGJ5IHRoZSBtb2RlbFxuICAgKiB3aWxsIGNoYW5nZSB0byBzaG93IHRoZSBjb3JyZWN0IGhvdXIuXG4gICAqXG4gICAqIEBwYXJhbSBmcm9tTWlsbGlzZWNvbmRzXG4gICAqICB0aGUgbW9tZW50IGluIHRpbWUgZnJvbSB3aGljaCB0aGUgYG1pbnV0ZWAgbW9kZWwgdG8gdGhlIGBsZWZ0YCB3aWxsIGJlIGNvbnN0cnVjdGVkLlxuICAgKiBAcGFyYW0gc2VsZWN0ZWRNaWxsaXNlY29uZHNcbiAgICogIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBkYXRlL3RpbWUgcGlja2VyLlxuICAgKiBAcmV0dXJuc1xuICAgKiAgbW9kZWwgY29udGFpbmluZyBhbiBgYWN0aXZlYCBgbWludXRlYCBvbmUgY2VsbCB0byB0aGUgYGxlZnRgIG9mIHRoZSBzcGVjaWZpZWQgbW9tZW50IGluIHRpbWUuXG4gICAqL1xuICBnb0xlZnQoZnJvbU1pbGxpc2Vjb25kczogbnVtYmVyLCBzZWxlY3RlZE1pbGxpc2Vjb25kczogbnVtYmVyKTogRGxEYXRlVGltZVBpY2tlck1vZGVsIHtcbiAgICByZXR1cm4gdGhpcy5nZXRNb2RlbChtb21lbnQoZnJvbU1pbGxpc2Vjb25kcykuc3VidHJhY3QodGhpcy5zdGVwLCAnbWludXRlcycpLnZhbHVlT2YoKSwgc2VsZWN0ZWRNaWxsaXNlY29uZHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vdmUgYGFjdGl2ZWAgbWludXRlIG9uZSBjZWxsIHRvIGByaWdodGAgaW4gdGhlIGN1cnJlbnQgYG1pbnV0ZWAgdmlldy5cbiAgICpcbiAgICogTW92aW5nIGByaWdodGAgY2FuIHJlc3VsdCBpbiB0aGUgYGFjdGl2ZWAgaG91ciBiZWluZyBwYXJ0IG9mIGEgZGlmZmVyZW50IGhvdXIgdGhhblxuICAgKiB0aGUgc3BlY2lmaWVkIGBmcm9tTWlsbGlzZWNvbmRzYCwgaW4gdGhpcyBjYXNlIHRoZSBob3VyIHJlcHJlc2VudGVkIGJ5IHRoZSBtb2RlbFxuICAgKiB3aWxsIGNoYW5nZSB0byBzaG93IHRoZSBjb3JyZWN0IGhvdXIuXG4gICAqXG4gICAqIEBwYXJhbSBmcm9tTWlsbGlzZWNvbmRzXG4gICAqICB0aGUgbW9tZW50IGluIHRpbWUgZnJvbSB3aGljaCB0aGUgYG1pbnV0ZWAgbW9kZWwgdG8gdGhlIGByaWdodGAgd2lsbCBiZSBjb25zdHJ1Y3RlZC5cbiAgICogQHBhcmFtIHNlbGVjdGVkTWlsbGlzZWNvbmRzXG4gICAqICB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlci5cbiAgICogQHJldHVybnNcbiAgICogIG1vZGVsIGNvbnRhaW5pbmcgYW4gYGFjdGl2ZWAgYG1pbnV0ZWAgb25lIGNlbGwgdG8gdGhlIGByaWdodGAgb2YgdGhlIHNwZWNpZmllZCBtb21lbnQgaW4gdGltZS5cbiAgICovXG4gIGdvUmlnaHQoZnJvbU1pbGxpc2Vjb25kczogbnVtYmVyLCBzZWxlY3RlZE1pbGxpc2Vjb25kczogbnVtYmVyKTogRGxEYXRlVGltZVBpY2tlck1vZGVsIHtcbiAgICByZXR1cm4gdGhpcy5nZXRNb2RlbChtb21lbnQoZnJvbU1pbGxpc2Vjb25kcykuYWRkKHRoaXMuc3RlcCwgJ21pbnV0ZXMnKS52YWx1ZU9mKCksIHNlbGVjdGVkTWlsbGlzZWNvbmRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNb3ZlIHRoZSBhY3RpdmUgYG1pbnV0ZWAgb25lIGhvdXIgYGRvd25gIGZyb20gdGhlIHNwZWNpZmllZCBtb21lbnQgaW4gdGltZS5cbiAgICpcbiAgICogVGhlIGBhY3RpdmVgIG1pbnV0ZSB3aWxsIGJlIGBvbmUgKDEpIGhvdXIgYWZ0ZXJgIHRoZSBzcGVjaWZpZWQgbWlsbGlzZWNvbmRzLlxuICAgKiBUaGlzIG1vdmVzIHRoZSBgYWN0aXZlYCBkYXRlIG9uZSBgcGFnZWAgYGRvd25gIGZyb20gdGhlIGN1cnJlbnQgYG1pbnV0ZWAgdmlldy5cbiAgICpcbiAgICogVGhlIG5leHQgY2VsbCBgcGFnZS1kb3duYCB3aWxsIGJlIGluIGEgZGlmZmVyZW50IGhvdXIgdGhhbiB0aGUgY3VycmVudGx5XG4gICAqIGRpc3BsYXllZCB2aWV3IGFuZCB0aGUgbW9kZWwgdGltZSByYW5nZSB3aWxsIGluY2x1ZGUgdGhlIG5ldyBhY3RpdmUgY2VsbC5cbiAgICpcbiAgICogQHBhcmFtIGZyb21NaWxsaXNlY29uZHNcbiAgICogIHRoZSBtb21lbnQgaW4gdGltZSBmcm9tIHdoaWNoIHRoZSBuZXh0IGBtb250aGAgbW9kZWwgcGFnZSBgZG93bmAgd2lsbCBiZSBjb25zdHJ1Y3RlZC5cbiAgICogQHBhcmFtIHNlbGVjdGVkTWlsbGlzZWNvbmRzXG4gICAqICB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgZGF0ZS90aW1lIHBpY2tlci5cbiAgICogQHJldHVybnNcbiAgICogIG1vZGVsIGNvbnRhaW5pbmcgYW4gYGFjdGl2ZWAgYG1vbnRoYCBvbmUgeWVhciBgZG93bmAgZnJvbSB0aGUgc3BlY2lmaWVkIG1vbWVudCBpbiB0aW1lLlxuICAgKi9cbiAgcGFnZURvd24oZnJvbU1pbGxpc2Vjb25kczogbnVtYmVyLCBzZWxlY3RlZE1pbGxpc2Vjb25kczogbnVtYmVyKTogRGxEYXRlVGltZVBpY2tlck1vZGVsIHtcbiAgICByZXR1cm4gdGhpcy5nZXRNb2RlbChtb21lbnQoZnJvbU1pbGxpc2Vjb25kcykuYWRkKDEsICdob3VyJykudmFsdWVPZigpLCBzZWxlY3RlZE1pbGxpc2Vjb25kcyk7XG4gIH1cblxuICAvKipcbiAgICogTW92ZSB0aGUgYWN0aXZlIGBtaW51dGVgIG9uZSBob3VyIGB1cGAgZnJvbSB0aGUgc3BlY2lmaWVkIG1vbWVudCBpbiB0aW1lLlxuICAgKlxuICAgKiBUaGUgYGFjdGl2ZWAgbWludXRlIHdpbGwgYmUgYG9uZSAoMSkgaG91ciBiZWZvcmVgIHRoZSBzcGVjaWZpZWQgbWlsbGlzZWNvbmRzLlxuICAgKiBUaGlzIG1vdmVzIHRoZSBgYWN0aXZlYCBkYXRlIG9uZSBgcGFnZWAgYGRvd25gIGZyb20gdGhlIGN1cnJlbnQgYG1pbnV0ZWAgdmlldy5cbiAgICpcbiAgICogVGhlIG5leHQgY2VsbCBgcGFnZS11cGAgd2lsbCBiZSBpbiBhIGRpZmZlcmVudCBob3VyIHRoYW4gdGhlIGN1cnJlbnRseVxuICAgKiBkaXNwbGF5ZWQgdmlldyBhbmQgdGhlIG1vZGVsIHRpbWUgcmFuZ2Ugd2lsbCBpbmNsdWRlIHRoZSBuZXcgYWN0aXZlIGNlbGwuXG4gICAqXG4gICAqIEBwYXJhbSBmcm9tTWlsbGlzZWNvbmRzXG4gICAqICB0aGUgbW9tZW50IGluIHRpbWUgZnJvbSB3aGljaCB0aGUgbmV4dCBgbW9udGhgIG1vZGVsIHBhZ2UgYGRvd25gIHdpbGwgYmUgY29uc3RydWN0ZWQuXG4gICAqIEBwYXJhbSBzZWxlY3RlZE1pbGxpc2Vjb25kc1xuICAgKiAgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGRhdGUvdGltZSBwaWNrZXIuXG4gICAqIEByZXR1cm5zXG4gICAqICBtb2RlbCBjb250YWluaW5nIGFuIGBhY3RpdmVgIGBtb250aGAgb25lIHllYXIgYGRvd25gIGZyb20gdGhlIHNwZWNpZmllZCBtb21lbnQgaW4gdGltZS5cbiAgICovXG4gIHBhZ2VVcChmcm9tTWlsbGlzZWNvbmRzOiBudW1iZXIsIHNlbGVjdGVkTWlsbGlzZWNvbmRzOiBudW1iZXIpOiBEbERhdGVUaW1lUGlja2VyTW9kZWwge1xuICAgIHJldHVybiB0aGlzLmdldE1vZGVsKG1vbWVudChmcm9tTWlsbGlzZWNvbmRzKS5zdWJ0cmFjdCgxLCAnaG91cicpLnZhbHVlT2YoKSwgc2VsZWN0ZWRNaWxsaXNlY29uZHMpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1vdmUgdGhlIGBhY3RpdmVgIGBtaW51dGVgIHRvIHRoZSBsYXN0IGNlbGwgb2YgdGhlIGN1cnJlbnQgaG91ci5cbiAgICpcbiAgICogVGhlIHZpZXcgb3IgdGltZSByYW5nZSB3aWxsIG5vdCBjaGFuZ2UgdW5sZXNzIHRoZSBgZnJvbU1pbGxpc2Vjb25kc2AgdmFsdWVcbiAgICogaXMgaW4gYSBkaWZmZXJlbnQgaG91ciB0aGFuIHRoZSBkaXNwbGF5ZWQgZGVjYWRlLlxuICAgKlxuICAgKiBAcGFyYW0gZnJvbU1pbGxpc2Vjb25kc1xuICAgKiAgdGhlIG1vbWVudCBpbiB0aW1lIGZyb20gd2hpY2ggdGhlIGxhc3QgY2VsbCB3aWxsIGJlIGNhbGN1bGF0ZWQuXG4gICAqIEBwYXJhbSBzZWxlY3RlZE1pbGxpc2Vjb25kc1xuICAgKiAgdGhlIGN1cnJlbnQgdmFsdWUgb2YgdGhlIGRhdGUvdGltZSBwaWNrZXIuXG4gICAqIEByZXR1cm5zXG4gICAqICBhIG1vZGVsIHdpdGggdGhlIGxhc3QgY2VsbCBpbiB0aGUgdmlldyBhcyB0aGUgYWN0aXZlIGBtaW51dGVgLlxuICAgKi9cbiAgZ29FbmQoZnJvbU1pbGxpc2Vjb25kczogbnVtYmVyLCBzZWxlY3RlZE1pbGxpc2Vjb25kczogbnVtYmVyKTogRGxEYXRlVGltZVBpY2tlck1vZGVsIHtcbiAgICByZXR1cm4gdGhpcy5nZXRNb2RlbChtb21lbnQoZnJvbU1pbGxpc2Vjb25kcylcbiAgICAgIC5lbmRPZignaG91cicpXG4gICAgICAudmFsdWVPZigpLCBzZWxlY3RlZE1pbGxpc2Vjb25kcyk7XG4gIH1cblxuICAvKipcbiAgICogTW92ZSB0aGUgYGFjdGl2ZWAgYG1pbnV0ZWAgdG8gdGhlIGZpcnN0IGNlbGwgb2YgdGhlIGN1cnJlbnQgaG91ci5cbiAgICpcbiAgICogVGhlIHZpZXcgb3IgdGltZSByYW5nZSB3aWxsIG5vdCBjaGFuZ2UgdW5sZXNzIHRoZSBgZnJvbU1pbGxpc2Vjb25kc2AgdmFsdWVcbiAgICogaXMgaW4gYSBkaWZmZXJlbnQgaG91ciB0aGFuIHRoZSBkaXNwbGF5ZWQgZGVjYWRlLlxuICAgKlxuICAgKiBAcGFyYW0gZnJvbU1pbGxpc2Vjb25kc1xuICAgKiAgdGhlIG1vbWVudCBpbiB0aW1lIGZyb20gd2hpY2ggdGhlIGZpcnN0IGNlbGwgd2lsbCBiZSBjYWxjdWxhdGVkLlxuICAgKiBAcGFyYW0gc2VsZWN0ZWRNaWxsaXNlY29uZHNcbiAgICogIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBkYXRlL3RpbWUgcGlja2VyLlxuICAgKiBAcmV0dXJuc1xuICAgKiAgYSBtb2RlbCB3aXRoIHRoZSBmaXJzdCBjZWxsIGluIHRoZSB2aWV3IGFzIHRoZSBhY3RpdmUgYG1pbnV0ZWAuXG4gICAqL1xuICBnb0hvbWUoZnJvbU1pbGxpc2Vjb25kczogbnVtYmVyLCBzZWxlY3RlZE1pbGxpc2Vjb25kczogbnVtYmVyKTogRGxEYXRlVGltZVBpY2tlck1vZGVsIHtcbiAgICByZXR1cm4gdGhpcy5nZXRNb2RlbChtb21lbnQoZnJvbU1pbGxpc2Vjb25kcykuc3RhcnRPZignaG91cicpLnZhbHVlT2YoKSwgc2VsZWN0ZWRNaWxsaXNlY29uZHMpO1xuICB9XG59XG4iXX0=