@hxui/angular
Version:
An Angular library based on the [HXUI design system](https://hxui.io).
652 lines • 55.4 kB
JavaScript
import { ChangeDetectorRef, Component, forwardRef, Input, ViewEncapsulation, } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { isInteger, isNumber, padNumber, toInteger } from '../utils/util';
import { HxaTime } from './hxa-time';
import { HxaTimeAdapter } from './hxa-time-adapter';
import { TimepickerConfig } from './timepicker-config';
import { TimepickerI18n } from './timepicker-i18n';
import * as i0 from "@angular/core";
import * as i1 from "./timepicker-config";
import * as i2 from "./hxa-time-adapter";
import * as i3 from "./timepicker-i18n";
import * as i4 from "@angular/common";
const FILTER_REGEX = /[^0-9]/g;
/**
* A directive that helps with wth picking hours, minutes and seconds.
*/
// TODO: rename to TimePickerComponent
// eslint-disable-next-line @angular-eslint/component-class-suffix
export class Timepicker {
constructor(_config, _ngbTimeAdapter, _cd, i18n) {
this._config = _config;
this._ngbTimeAdapter = _ngbTimeAdapter;
this._cd = _cd;
this.i18n = i18n;
/* eslint-disable @typescript-eslint/no-empty-function */
this.onChange = (_) => { };
this.onTouched = () => { };
this.meridian = _config.meridian;
this.spinners = _config.spinners;
this.seconds = _config.seconds;
this.hourStep = _config.hourStep;
this.minuteStep = _config.minuteStep;
this.secondStep = _config.secondStep;
this.disabled = _config.disabled;
this.readonlyInputs = _config.readonlyInputs;
this.size = _config.size;
}
/**
* The number of hours to add/subtract when clicking hour spinners.
*/
set hourStep(step) {
this._hourStep = isInteger(step) ? step : this._config.hourStep;
}
get hourStep() {
return this._hourStep;
}
/**
* The number of minutes to add/subtract when clicking minute spinners.
*/
set minuteStep(step) {
this._minuteStep = isInteger(step) ? step : this._config.minuteStep;
}
get minuteStep() {
return this._minuteStep;
}
/**
* The number of seconds to add/subtract when clicking second spinners.
*/
set secondStep(step) {
this._secondStep = isInteger(step) ? step : this._config.secondStep;
}
get secondStep() {
return this._secondStep;
}
/* eslint-disable @typescript-eslint/no-empty-function */
writeValue(value) {
const structValue = this._ngbTimeAdapter.fromModel(value);
this.model = structValue
? new HxaTime(structValue.hour, structValue.minute, structValue.second)
: new HxaTime();
if (!this.seconds && (!structValue || !isNumber(structValue.second))) {
this.model.second = 0;
}
this._cd.markForCheck();
}
registerOnChange(fn) {
this.onChange = fn;
}
registerOnTouched(fn) {
this.onTouched = fn;
}
setDisabledState(isDisabled) {
this.disabled = isDisabled;
}
changeHour(step) {
this.model.changeHour(step);
this.propagateModelChange();
}
changeMinute(step) {
this.model.changeMinute(step);
this.propagateModelChange();
}
changeSecond(step) {
this.model.changeSecond(step);
this.propagateModelChange();
}
updateHour(newVal) {
const isPM = this.model.hour >= 12;
const enteredHour = toInteger(newVal);
if (this.meridian &&
((isPM && enteredHour < 12) || (!isPM && enteredHour === 12))) {
this.model.updateHour(enteredHour + 12);
}
else {
this.model.updateHour(enteredHour);
}
this.propagateModelChange();
}
updateMinute(newVal) {
this.model.updateMinute(toInteger(newVal));
this.propagateModelChange();
}
updateSecond(newVal) {
this.model.updateSecond(toInteger(newVal));
this.propagateModelChange();
}
toggleMeridian() {
if (this.meridian) {
this.changeHour(12);
}
}
formatInput(input) {
input.value = input.value.replace(FILTER_REGEX, '');
}
formatHour(value) {
if (isNumber(value)) {
if (this.meridian) {
return padNumber(value % 12 === 0 ? 12 : value % 12);
}
else {
return padNumber(value % 24);
}
}
else {
return padNumber(NaN);
}
}
formatMinSec(value) {
return padNumber(isNumber(value) ? value : NaN);
}
get isSmallSize() {
return this.size === 'small';
}
get isLargeSize() {
return this.size === 'large';
}
ngOnChanges(changes) {
if (changes['seconds'] &&
!this.seconds &&
this.model &&
!isNumber(this.model.second)) {
this.model.second = 0;
this.propagateModelChange(false);
}
}
propagateModelChange(touched = true) {
if (touched) {
this.onTouched();
}
if (this.model.isValid(this.seconds)) {
this.onChange(this._ngbTimeAdapter.toModel({
hour: this.model.hour,
minute: this.model.minute,
second: this.model.second,
}));
}
else {
this.onChange(this._ngbTimeAdapter.toModel(null));
}
}
}
Timepicker.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: Timepicker, deps: [{ token: i1.TimepickerConfig }, { token: i2.HxaTimeAdapter }, { token: i0.ChangeDetectorRef }, { token: i3.TimepickerI18n }], target: i0.ɵɵFactoryTarget.Component });
Timepicker.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: Timepicker, selector: "hxa-timepicker", inputs: { meridian: "meridian", spinners: "spinners", seconds: "seconds", hourStep: "hourStep", minuteStep: "minuteStep", secondStep: "secondStep", readonlyInputs: "readonlyInputs", disabled: "disabled", size: "size" }, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Timepicker),
multi: true,
},
], usesOnChanges: true, ngImport: i0, template: `
<fieldset [disabled]="disabled" [class.disabled]="disabled">
<div class="ngb-tp">
<div class="ngb-tp-input-container ngb-tp-hour">
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeHour(hourStep)"
class="hx-button is-flat"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-up is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.increment-hours"
>Increment hours</span
>
</button>
<div class="hx-input-control">
<input
type="text"
class="hx-input is-text-center"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
maxlength="2"
inputmode="numeric"
placeholder="HH"
i18n-placeholder="@@ngb.timepicker.HH"
[value]="formatHour(model?.hour)"
(change)="updateHour($any($event).target.value)"
[readOnly]="readonlyInputs"
[disabled]="disabled"
aria-label="Hours"
i18n-aria-label="@@ngb.timepicker.hours"
(input)="formatInput($any($event).target)"
(keydown.ArrowUp)="changeHour(hourStep); $event.preventDefault()"
(keydown.ArrowDown)="
changeHour(-hourStep); $event.preventDefault()
"
hxaTextInput
/>
<label class="hx-label"></label>
<div class="hx-help"></div>
</div>
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeHour(-hourStep)"
class="hx-button is-flat mt-2"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-down is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.decrement-hours"
>Decrement hours</span
>
</button>
</div>
<div class="ngb-tp-spacer">:</div>
<div class="ngb-tp-input-container ngb-tp-minute">
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeMinute(minuteStep)"
class="hx-button is-flat"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-up is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.increment-minutes"
>Increment minutes</span
>
</button>
<div class="hx-input-control">
<input
type="text"
class="hx-input is-text-center"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
maxlength="2"
inputmode="numeric"
placeholder="MM"
i18n-placeholder="@@ngb.timepicker.MM"
[value]="formatMinSec(model?.minute)"
(change)="updateMinute($any($event).target.value)"
[readOnly]="readonlyInputs"
[disabled]="disabled"
aria-label="Minutes"
i18n-aria-label="@@ngb.timepicker.minutes"
(input)="formatInput($any($event).target)"
(keydown.ArrowUp)="
changeMinute(minuteStep); $event.preventDefault()
"
(keydown.ArrowDown)="
changeMinute(-minuteStep); $event.preventDefault()
"
/>
<label class="hx-label"></label>
<div class="hx-help"></div>
</div>
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeMinute(-minuteStep)"
class="hx-button is-flat mt-2"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-down is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.decrement-minutes"
>Decrement minutes</span
>
</button>
</div>
<div *ngIf="seconds" class="ngb-tp-spacer">:</div>
<div *ngIf="seconds" class="ngb-tp-input-container ngb-tp-second">
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeSecond(secondStep)"
class="hx-button is-flat"
[class.btn-sm]="isSmallSize"
[class.btn-lg]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-up is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.increment-seconds"
>Increment seconds</span
>
</button>
<div class="hx-input-control">
<input
type="text"
class="hx-input is-text-center"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
maxlength="2"
inputmode="numeric"
placeholder="SS"
i18n-placeholder="@@ngb.timepicker.SS"
[value]="formatMinSec(model?.second)"
(change)="updateSecond($any($event).target.value)"
[readOnly]="readonlyInputs"
[disabled]="disabled"
aria-label="Seconds"
i18n-aria-label="@@ngb.timepicker.seconds"
(input)="formatInput($any($event).target)"
(keydown.ArrowUp)="
changeSecond(secondStep); $event.preventDefault()
"
(keydown.ArrowDown)="
changeSecond(-secondStep); $event.preventDefault()
"
/>
<label class="hx-label"></label>
<div class="hx-help"></div>
</div>
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeSecond(-secondStep)"
class="hx-button mt-2"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-down is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.decrement-seconds"
>Decrement seconds</span
>
</button>
</div>
<div *ngIf="meridian" class="ngb-tp-spacer"></div>
<div *ngIf="meridian" class="ngb-tp-meridian">
<button
type="button"
class="hx-button mb-1"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[disabled]="disabled"
[class.disabled]="disabled"
(click)="toggleMeridian()"
>
<ng-container
*ngIf="model && model.hour >= 12; else am"
i18n="@@ngb.timepicker.PM"
>{{ i18n.getAfternoonPeriod() }}</ng-container
>
<ng-template #am i18n="@@ngb.timepicker.AM">{{
i18n.getMorningPeriod()
}}</ng-template>
</button>
</div>
</div>
</fieldset>
`, isInline: true, styles: ["ngb-timepicker{font-size:1rem}fieldset{border:none}.ngb-tp{display:flex;align-items:center}.ngb-tp-input-container{width:4em}.ngb-tp-chevron:before{border-style:solid;border-width:.29em .29em 0 0;content:\"\";display:inline-block;height:.69em;left:.05em;position:relative;top:.15em;transform:rotate(-45deg);vertical-align:middle;width:.69em}.ngb-tp-chevron.bottom:before{top:-.3em;transform:rotate(135deg)}.ngb-tp-input{text-align:center}.ngb-tp-hour,.ngb-tp-minute,.ngb-tp-second,.ngb-tp-meridian{display:flex;flex-direction:column;align-items:center;justify-content:space-around}.ngb-tp-spacer{width:1em;text-align:center}\n"], directives: [{ type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], encapsulation: i0.ViewEncapsulation.None });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: Timepicker, decorators: [{
type: Component,
args: [{ selector: 'hxa-timepicker', encapsulation: ViewEncapsulation.None, template: `
<fieldset [disabled]="disabled" [class.disabled]="disabled">
<div class="ngb-tp">
<div class="ngb-tp-input-container ngb-tp-hour">
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeHour(hourStep)"
class="hx-button is-flat"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-up is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.increment-hours"
>Increment hours</span
>
</button>
<div class="hx-input-control">
<input
type="text"
class="hx-input is-text-center"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
maxlength="2"
inputmode="numeric"
placeholder="HH"
i18n-placeholder="@@ngb.timepicker.HH"
[value]="formatHour(model?.hour)"
(change)="updateHour($any($event).target.value)"
[readOnly]="readonlyInputs"
[disabled]="disabled"
aria-label="Hours"
i18n-aria-label="@@ngb.timepicker.hours"
(input)="formatInput($any($event).target)"
(keydown.ArrowUp)="changeHour(hourStep); $event.preventDefault()"
(keydown.ArrowDown)="
changeHour(-hourStep); $event.preventDefault()
"
hxaTextInput
/>
<label class="hx-label"></label>
<div class="hx-help"></div>
</div>
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeHour(-hourStep)"
class="hx-button is-flat mt-2"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-down is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.decrement-hours"
>Decrement hours</span
>
</button>
</div>
<div class="ngb-tp-spacer">:</div>
<div class="ngb-tp-input-container ngb-tp-minute">
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeMinute(minuteStep)"
class="hx-button is-flat"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-up is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.increment-minutes"
>Increment minutes</span
>
</button>
<div class="hx-input-control">
<input
type="text"
class="hx-input is-text-center"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
maxlength="2"
inputmode="numeric"
placeholder="MM"
i18n-placeholder="@@ngb.timepicker.MM"
[value]="formatMinSec(model?.minute)"
(change)="updateMinute($any($event).target.value)"
[readOnly]="readonlyInputs"
[disabled]="disabled"
aria-label="Minutes"
i18n-aria-label="@@ngb.timepicker.minutes"
(input)="formatInput($any($event).target)"
(keydown.ArrowUp)="
changeMinute(minuteStep); $event.preventDefault()
"
(keydown.ArrowDown)="
changeMinute(-minuteStep); $event.preventDefault()
"
/>
<label class="hx-label"></label>
<div class="hx-help"></div>
</div>
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeMinute(-minuteStep)"
class="hx-button is-flat mt-2"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-down is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.decrement-minutes"
>Decrement minutes</span
>
</button>
</div>
<div *ngIf="seconds" class="ngb-tp-spacer">:</div>
<div *ngIf="seconds" class="ngb-tp-input-container ngb-tp-second">
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeSecond(secondStep)"
class="hx-button is-flat"
[class.btn-sm]="isSmallSize"
[class.btn-lg]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-up is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.increment-seconds"
>Increment seconds</span
>
</button>
<div class="hx-input-control">
<input
type="text"
class="hx-input is-text-center"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
maxlength="2"
inputmode="numeric"
placeholder="SS"
i18n-placeholder="@@ngb.timepicker.SS"
[value]="formatMinSec(model?.second)"
(change)="updateSecond($any($event).target.value)"
[readOnly]="readonlyInputs"
[disabled]="disabled"
aria-label="Seconds"
i18n-aria-label="@@ngb.timepicker.seconds"
(input)="formatInput($any($event).target)"
(keydown.ArrowUp)="
changeSecond(secondStep); $event.preventDefault()
"
(keydown.ArrowDown)="
changeSecond(-secondStep); $event.preventDefault()
"
/>
<label class="hx-label"></label>
<div class="hx-help"></div>
</div>
<button
*ngIf="spinners"
tabindex="-1"
type="button"
(click)="changeSecond(-secondStep)"
class="hx-button mt-2"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[class.disabled]="disabled"
[disabled]="disabled"
>
<span class="hx-icon icon-angle-down is-medium is-info"></span>
<span
class="sr-only is-hidden"
i18n="@@ngb.timepicker.decrement-seconds"
>Decrement seconds</span
>
</button>
</div>
<div *ngIf="meridian" class="ngb-tp-spacer"></div>
<div *ngIf="meridian" class="ngb-tp-meridian">
<button
type="button"
class="hx-button mb-1"
[class.is-small]="isSmallSize"
[class.is-large]="isLargeSize"
[disabled]="disabled"
[class.disabled]="disabled"
(click)="toggleMeridian()"
>
<ng-container
*ngIf="model && model.hour >= 12; else am"
i18n="@@ngb.timepicker.PM"
>{{ i18n.getAfternoonPeriod() }}</ng-container
>
<ng-template #am i18n="@@ngb.timepicker.AM">{{
i18n.getMorningPeriod()
}}</ng-template>
</button>
</div>
</div>
</fieldset>
`, providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => Timepicker),
multi: true,
},
], styles: ["ngb-timepicker{font-size:1rem}fieldset{border:none}.ngb-tp{display:flex;align-items:center}.ngb-tp-input-container{width:4em}.ngb-tp-chevron:before{border-style:solid;border-width:.29em .29em 0 0;content:\"\";display:inline-block;height:.69em;left:.05em;position:relative;top:.15em;transform:rotate(-45deg);vertical-align:middle;width:.69em}.ngb-tp-chevron.bottom:before{top:-.3em;transform:rotate(135deg)}.ngb-tp-input{text-align:center}.ngb-tp-hour,.ngb-tp-minute,.ngb-tp-second,.ngb-tp-meridian{display:flex;flex-direction:column;align-items:center;justify-content:space-around}.ngb-tp-spacer{width:1em;text-align:center}\n"] }]
}], ctorParameters: function () { return [{ type: i1.TimepickerConfig }, { type: i2.HxaTimeAdapter }, { type: i0.ChangeDetectorRef }, { type: i3.TimepickerI18n }]; }, propDecorators: { meridian: [{
type: Input
}], spinners: [{
type: Input
}], seconds: [{
type: Input
}], hourStep: [{
type: Input
}], minuteStep: [{
type: Input
}], secondStep: [{
type: Input
}], readonlyInputs: [{
type: Input
}], disabled: [{
type: Input
}], size: [{
type: Input
}] } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXBpY2tlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2h4LXVpL3NyYy9saWIvdGltZS1waWNrZXIvdGltZXBpY2tlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsS0FBSyxFQUdMLGlCQUFpQixHQUNsQixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQXdCLGlCQUFpQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFekUsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMxRSxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN2RCxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7Ozs7OztBQUVuRCxNQUFNLFlBQVksR0FBRyxTQUFTLENBQUM7QUFFL0I7O0dBRUc7QUE0T0gsc0NBQXNDO0FBQ3RDLGtFQUFrRTtBQUNsRSxNQUFNLE9BQU8sVUFBVTtJQTJFckIsWUFDbUIsT0FBeUIsRUFDbEMsZUFBb0MsRUFDcEMsR0FBc0IsRUFDdkIsSUFBb0I7UUFIVixZQUFPLEdBQVAsT0FBTyxDQUFrQjtRQUNsQyxvQkFBZSxHQUFmLGVBQWUsQ0FBcUI7UUFDcEMsUUFBRyxHQUFILEdBQUcsQ0FBbUI7UUFDdkIsU0FBSSxHQUFKLElBQUksQ0FBZ0I7UUFhN0IseURBQXlEO1FBQ3pELGFBQVEsR0FBRyxDQUFDLENBQU0sRUFBRSxFQUFFLEdBQUUsQ0FBQyxDQUFDO1FBQzFCLGNBQVMsR0FBRyxHQUFHLEVBQUUsR0FBRSxDQUFDLENBQUM7UUFibkIsSUFB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Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBOE5UOzRGQVdVLFVBQVU7a0JBN090QixTQUFTOytCQUNFLGdCQUFnQixpQkFDWCxpQkFBaUIsQ0FBQyxJQUFJLFlBRTNCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E4TlQsYUFDVTt3QkFDVDs0QkFDRSxPQUFPLEVBQUUsaUJBQWlCOzRCQUMxQixXQUFXLEVBQUUsVUFBVSxDQUFDLEdBQUcsRUFBRSxXQUFXLENBQUM7NEJBQ3pDLEtBQUssRUFBRSxJQUFJO3lCQUNaO3FCQUNGO2lNQWdCUSxRQUFRO3NCQUFoQixLQUFLO2dCQUtHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBS0csT0FBTztzQkFBZixLQUFLO2dCQU1GLFFBQVE7c0JBRFgsS0FBSztnQkFhRixVQUFVO3NCQURiLEtBQUs7Z0JBYUYsVUFBVTtzQkFEYixLQUFLO2dCQVlHLGNBQWM7c0JBQXRCLEtBQUs7Z0JBS0csUUFBUTtzQkFBaEIsS0FBSztnQkFLRyxJQUFJO3NCQUFaLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xyXG4gIENoYW5nZURldGVjdG9yUmVmLFxyXG4gIENvbXBvbmVudCxcclxuICBmb3J3YXJkUmVmLFxyXG4gIElucHV0LFxyXG4gIE9uQ2hhbmdlcyxcclxuICBTaW1wbGVDaGFuZ2VzLFxyXG4gIFZpZXdFbmNhcHN1bGF0aW9uLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcblxyXG5pbXBvcnQgeyBpc0ludGVnZXIsIGlzTnVtYmVyLCBwYWROdW1iZXIsIHRvSW50ZWdlciB9IGZyb20gJy4uL3V0aWxzL3V0aWwnO1xyXG5pbXBvcnQgeyBIeGFUaW1lIH0gZnJvbSAnLi9oeGEtdGltZSc7XHJcbmltcG9ydCB7IEh4YVRpbWVBZGFwdGVyIH0gZnJvbSAnLi9oeGEtdGltZS1hZGFwdGVyJztcclxuaW1wb3J0IHsgVGltZXBpY2tlckNvbmZpZyB9IGZyb20gJy4vdGltZXBpY2tlci1jb25maWcnO1xyXG5pbXBvcnQgeyBUaW1lcGlja2VySTE4biB9IGZyb20gJy4vdGltZXBpY2tlci1pMThuJztcclxuXHJcbmNvbnN0IEZJTFRFUl9SRUdFWCA9IC9bXjAtOV0vZztcclxuXHJcbi8qKlxyXG4gKiBBIGRpcmVjdGl2ZSB0aGF0IGhlbHBzIHdpdGggd3RoIHBpY2tpbmcgaG91cnMsIG1pbnV0ZXMgYW5kIHNlY29uZHMuXHJcbiAqL1xyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2h4YS10aW1lcGlja2VyJyxcclxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxyXG4gIHN0eWxlVXJsczogWycuL3RpbWVwaWNrZXIuc2NzcyddLFxyXG4gIHRlbXBsYXRlOiBgXHJcbiAgICA8ZmllbGRzZXQgW2Rpc2FibGVkXT1cImRpc2FibGVkXCIgW2NsYXNzLmRpc2FibGVkXT1cImRpc2FibGVkXCI+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJuZ2ItdHBcIj5cclxuICAgICAgICA8ZGl2IGNsYXNzPVwibmdiLXRwLWlucHV0LWNvbnRhaW5lciBuZ2ItdHAtaG91clwiPlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAqbmdJZj1cInNwaW5uZXJzXCJcclxuICAgICAgICAgICAgdGFiaW5kZXg9XCItMVwiXHJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwiY2hhbmdlSG91cihob3VyU3RlcClcIlxyXG4gICAgICAgICAgICBjbGFzcz1cImh4LWJ1dHRvbiBpcy1mbGF0XCJcclxuICAgICAgICAgICAgW2NsYXNzLmlzLXNtYWxsXT1cImlzU21hbGxTaXplXCJcclxuICAgICAgICAgICAgW2NsYXNzLmlzLWxhcmdlXT1cImlzTGFyZ2VTaXplXCJcclxuICAgICAgICAgICAgW2NsYXNzLmRpc2FibGVkXT1cImRpc2FibGVkXCJcclxuICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcclxuICAgICAgICAgID5cclxuICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJoeC1pY29uIGljb24tYW5nbGUtdXAgaXMtbWVkaXVtIGlzLWluZm9cIj48L3NwYW4+XHJcbiAgICAgICAgICAgIDxzcGFuXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJzci1vbmx5IGlzLWhpZGRlblwiXHJcbiAgICAgICAgICAgICAgaTE4bj1cIkBAbmdiLnRpbWVwaWNrZXIuaW5jcmVtZW50LWhvdXJzXCJcclxuICAgICAgICAgICAgICA+SW5jcmVtZW50IGhvdXJzPC9zcGFuXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImh4LWlucHV0LWNvbnRyb2xcIj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiaHgtaW5wdXQgaXMtdGV4dC1jZW50ZXJcIlxyXG4gICAgICAgICAgICAgIFtjbGFzcy5pcy1zbWFsbF09XCJpc1NtYWxsU2l6ZVwiXHJcbiAgICAgICAgICAgICAgW2NsYXNzLmlzLWxhcmdlXT1cImlzTGFyZ2VTaXplXCJcclxuICAgICAgICAgICAgICBtYXhsZW5ndGg9XCIyXCJcclxuICAgICAgICAgICAgICBpbnB1dG1vZGU9XCJudW1lcmljXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIkhIXCJcclxuICAgICAgICAgICAgICBpMThuLXBsYWNlaG9sZGVyPVwiQEBuZ2IudGltZXBpY2tlci5ISFwiXHJcbiAgICAgICAgICAgICAgW3ZhbHVlXT1cImZvcm1hdEhvdXIobW9kZWw/LmhvdXIpXCJcclxuICAgICAgICAgICAgICAoY2hhbmdlKT1cInVwZGF0ZUhvdXIoJGFueSgkZXZlbnQpLnRhcmdldC52YWx1ZSlcIlxyXG4gICAgICAgICAgICAgIFtyZWFkT25seV09XCJyZWFkb25seUlucHV0c1wiXHJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcclxuICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiSG91cnNcIlxyXG4gICAgICAgICAgICAgIGkxOG4tYXJpYS1sYWJlbD1cIkBAbmdiLnRpbWVwaWNrZXIuaG91cnNcIlxyXG4gICAgICAgICAgICAgIChpbnB1dCk9XCJmb3JtYXRJbnB1dCgkYW55KCRldmVudCkudGFyZ2V0KVwiXHJcbiAgICAgICAgICAgICAgKGtleWRvd24uQXJyb3dVcCk9XCJjaGFuZ2VIb3VyKGhvdXJTdGVwKTsgJGV2ZW50LnByZXZlbnREZWZhdWx0KClcIlxyXG4gICAgICAgICAgICAgIChrZXlkb3duLkFycm93RG93bik9XCJcclxuICAgICAgICAgICAgICAgIGNoYW5nZUhvdXIoLWhvdXJTdGVwKTsgJGV2ZW50LnByZXZlbnREZWZhdWx0KClcclxuICAgICAgICAgICAgICBcIlxyXG4gICAgICAgICAgICAgIGh4YVRleHRJbnB1dFxyXG4gICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJoeC1sYWJlbFwiPjwvbGFiZWw+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJoeC1oZWxwXCI+PC9kaXY+XHJcbiAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgKm5nSWY9XCJzcGlubmVyc1wiXHJcbiAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxyXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cImNoYW5nZUhvdXIoLWhvdXJTdGVwKVwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiaHgtYnV0dG9uIGlzLWZsYXQgbXQtMlwiXHJcbiAgICAgICAgICAgIFtjbGFzcy5pcy1zbWFsbF09XCJpc1NtYWxsU2l6ZVwiXHJcbiAgICAgICAgICAgIFtjbGFzcy5pcy1sYXJnZV09XCJpc0xhcmdlU2l6ZVwiXHJcbiAgICAgICAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCJkaXNhYmxlZFwiXHJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaHgtaWNvbiBpY29uLWFuZ2xlLWRvd24gaXMtbWVkaXVtIGlzLWluZm9cIj48L3NwYW4+XHJcbiAgICAgICAgICAgIDxzcGFuXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJzci1vbmx5IGlzLWhpZGRlblwiXHJcbiAgICAgICAgICAgICAgaTE4bj1cIkBAbmdiLnRpbWVwaWNrZXIuZGVjcmVtZW50LWhvdXJzXCJcclxuICAgICAgICAgICAgICA+RGVjcmVtZW50IGhvdXJzPC9zcGFuXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJuZ2ItdHAtc3BhY2VyXCI+OjwvZGl2PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJuZ2ItdHAtaW5wdXQtY29udGFpbmVyIG5nYi10cC1taW51dGVcIj5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgKm5nSWY9XCJzcGlubmVyc1wiXHJcbiAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxyXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgKGNsaWNrKT1cImNoYW5nZU1pbnV0ZShtaW51dGVTdGVwKVwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiaHgtYnV0dG9uIGlzLWZsYXRcIlxyXG4gICAgICAgICAgICBbY2xhc3MuaXMtc21hbGxdPVwiaXNTbWFsbFNpemVcIlxyXG4gICAgICAgICAgICBbY2xhc3MuaXMtbGFyZ2VdPVwiaXNMYXJnZVNpemVcIlxyXG4gICAgICAgICAgICBbY2xhc3MuZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImh4LWljb24gaWNvbi1hbmdsZS11cCBpcy1tZWRpdW0gaXMtaW5mb1wiPjwvc3Bhbj5cclxuICAgICAgICAgICAgPHNwYW5cclxuICAgICAgICAgICAgICBjbGFzcz1cInNyLW9ubHkgaXMtaGlkZGVuXCJcclxuICAgICAgICAgICAgICBpMThuPVwiQEBuZ2IudGltZXBpY2tlci5pbmNyZW1lbnQtbWludXRlc1wiXHJcbiAgICAgICAgICAgICAgPkluY3JlbWVudCBtaW51dGVzPC9zcGFuXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImh4LWlucHV0LWNvbnRyb2xcIj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiaHgtaW5wdXQgaXMtdGV4dC1jZW50ZXJcIlxyXG4gICAgICAgICAgICAgIFtjbGFzcy5pcy1zbWFsbF09XCJpc1NtYWxsU2l6ZVwiXHJcbiAgICAgICAgICAgICAgW2NsYXNzLmlzLWxhcmdlXT1cImlzTGFyZ2VTaXplXCJcclxuICAgICAgICAgICAgICBtYXhsZW5ndGg9XCIyXCJcclxuICAgICAgICAgICAgICBpbnB1dG1vZGU9XCJudW1lcmljXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIk1NXCJcclxuICAgICAgICAgICAgICBpMThuLXBsYWNlaG9sZGVyPVwiQEBuZ2IudGltZXBpY2tlci5NTVwiXHJcbiAgICAgICAgICAgICAgW3ZhbHVlXT1cImZvcm1hdE1pblNlYyhtb2RlbD8ubWludXRlKVwiXHJcbiAgICAgICAgICAgICAgKGNoYW5nZSk9XCJ1cGRhdGVNaW51dGUoJGFueSgkZXZlbnQpLnRhcmdldC52YWx1ZSlcIlxyXG4gICAgICAgICAgICAgIFtyZWFkT25seV09XCJyZWFkb25seUlucHV0c1wiXHJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcclxuICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiTWludXRlc1wiXHJcbiAgICAgICAgICAgICAgaTE4bi1hcmlhLWxhYmVsPVwiQEBuZ2IudGltZXBpY2tlci5taW51dGVzXCJcclxuICAgICAgICAgICAgICAoaW5wdXQpPVwiZm9ybWF0SW5wdXQoJGFueSgkZXZlbnQpLnRhcmdldClcIlxyXG4gICAgICAgICAgICAgIChrZXlkb3duLkFycm93VXApPVwiXHJcbiAgICAgICAgICAgICAgICBjaGFuZ2VNaW51dGUobWludXRlU3RlcCk7ICRldmVudC5wcmV2ZW50RGVmYXVsdCgpXHJcbiAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAoa2V5ZG93bi5BcnJvd0Rvd24pPVwiXHJcbiAgICAgICAgICAgICAgICBjaGFuZ2VNaW51dGUoLW1pbnV0ZVN0ZXApOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVxyXG4gICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImh4LWxhYmVsXCI+PC9sYWJlbD5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImh4LWhlbHBcIj48L2Rpdj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAqbmdJZj1cInNwaW5uZXJzXCJcclxuICAgICAgICAgICAgdGFiaW5kZXg9XCItMVwiXHJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwiY2hhbmdlTWludXRlKC1taW51dGVTdGVwKVwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiaHgtYnV0dG9uIGlzLWZsYXQgbXQtMlwiXHJcbiAgICAgICAgICAgIFtjbGFzcy5pcy1zbWFsbF09XCJpc1NtYWxsU2l6ZVwiXHJcbiAgICAgICAgICAgIFtjbGFzcy5pcy1sYXJnZV09XCJpc0xhcmdlU2l6ZVwiXHJcbiAgICAgICAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCJkaXNhYmxlZFwiXHJcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiaHgtaWNvbiBpY29uLWFuZ2xlLWRvd24gaXMtbWVkaXVtIGlzLWluZm9cIj48L3NwYW4+XHJcbiAgICAgICAgICAgIDxzcGFuXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJzci1vbmx5IGlzLWhpZGRlblwiXHJcbiAgICAgICAgICAgICAgaTE4bj1cIkBAbmdiLnRpbWVwaWNrZXIuZGVjcmVtZW50LW1pbnV0ZXNcIlxyXG4gICAgICAgICAgICAgID5EZWNyZW1lbnQgbWludXRlczwvc3BhblxyXG4gICAgICAgICAgICA+XHJcbiAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwic2Vjb25kc1wiIGNsYXNzPVwibmdiLXRwLXNwYWNlclwiPjo8L2Rpdj5cclxuICAgICAgICA8ZGl2ICpuZ0lmPVwic2Vjb25kc1wiIGNsYXNzPVwibmdiLXRwLWlucHV0LWNvbnRhaW5lciBuZ2ItdHAtc2Vjb25kXCI+XHJcbiAgICAgICAgICA8YnV0dG9uXHJcbiAgICAgICAgICAgICpuZ0lmPVwic3Bpbm5lcnNcIlxyXG4gICAgICAgICAgICB0YWJpbmRleD1cIi0xXCJcclxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgIChjbGljayk9XCJjaGFuZ2VTZWNvbmQoc2Vjb25kU3RlcClcIlxyXG4gICAgICAgICAgICBjbGFzcz1cImh4LWJ1dHRvbiBpcy1mbGF0XCJcclxuICAgICAgICAgICAgW2NsYXNzLmJ0bi1zbV09XCJpc1NtYWxsU2l6ZVwiXHJcbiAgICAgICAgICAgIFtjbGFzcy5idG4tbGddPVwiaXNMYXJnZVNpemVcIlxyXG4gICAgICAgICAgICBbY2xhc3MuZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImh4LWljb24gaWNvbi1hbmdsZS11cCBpcy1tZWRpdW0gaXMtaW5mb1wiPjwvc3Bhbj5cclxuICAgICAgICAgICAgPHNwYW5cclxuICAgICAgICAgICAgICBjbGFzcz1cInNyLW9ubHkgaXMtaGlkZGVuXCJcclxuICAgICAgICAgICAgICBpMThuPVwiQEBuZ2IudGltZXBpY2tlci5pbmNyZW1lbnQtc2Vjb25kc1wiXHJcbiAgICAgICAgICAgICAgPkluY3JlbWVudCBzZWNvbmRzPC9zcGFuXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgPGRpdiBjbGFzcz1cImh4LWlucHV0LWNvbnRyb2xcIj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cInRleHRcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiaHgtaW5wdXQgaXMtdGV4dC1jZW50ZXJcIlxyXG4gICAgICAgICAgICAgIFtjbGFzcy5pcy1zbWFsbF09XCJpc1NtYWxsU2l6ZVwiXHJcbiAgICAgICAgICAgICAgW2NsYXNzLmlzLWxhcmdlXT1cImlzTGFyZ2VTaXplXCJcclxuICAgICAgICAgICAgICBtYXhsZW5ndGg9XCIyXCJcclxuICAgICAgICAgICAgICBpbnB1dG1vZGU9XCJudW1lcmljXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlNTXCJcclxuICAgICAgICAgICAgICBpMThuLXBsYWNlaG9sZGVyPVwiQEBuZ2IudGltZXBpY2tlci5TU1wiXHJcbiAgICAgICAgICAgICAgW3ZhbHVlXT1cImZvcm1hdE1pblNlYyhtb2RlbD8uc2Vjb25kKVwiXHJcbiAgICAgICAgICAgICAgKGNoYW5nZSk9XCJ1cGRhdGVTZWNvbmQoJGFueSgkZXZlbnQpLnRhcmdldC52YWx1ZSlcIlxyXG4gICAgICAgICAgICAgIFtyZWFkT25seV09XCJyZWFkb25seUlucHV0c1wiXHJcbiAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cImRpc2FibGVkXCJcclxuICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiU2Vjb25kc1wiXHJcbiAgICAgICAgICAgICAgaTE4bi1hcmlhLWxhYmVsPVwiQEBuZ2IudGltZXBpY2tlci5zZWNvbmRzXCJcclxuICAgICAgICAgICAgICAoaW5wdXQpPVwiZm9ybWF0SW5wdXQoJGFueSgkZXZlbnQpLnRhcmdldClcIlxyXG4gICAgICAgICAgICAgIChrZXlkb3duLkFycm93VXApPVwiXHJcbiAgICAgICAgICAgICAgICBjaGFuZ2VTZWNvbmQoc2Vjb25kU3RlcCk7ICRldmVudC5wcmV2ZW50RGVmYXVsdCgpXHJcbiAgICAgICAgICAgICAgXCJcclxuICAgICAgICAgICAgICAoa2V5ZG93bi5BcnJvd0Rvd24pPVwiXHJcbiAgICAgICAgICAgICAgICBjaGFuZ2VTZWNvbmQoLXNlY29uZFN0ZXApOyAkZXZlbnQucHJldmVudERlZmF1bHQoKVxyXG4gICAgICAgICAgICAgIFwiXHJcbiAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImh4LWxhYmVsXCI+PC9sYWJlbD5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImh4LWhlbHBcIj48L2Rpdj5cclxuICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPGJ1dHRvblxyXG4gICAgICAgICAgICAqbmdJZj1cInNwaW5uZXJzXCJcclxuICAgICAgICAgICAgdGFiaW5kZXg9XCItMVwiXHJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwiY2hhbmdlU2Vjb25kKC1zZWNvbmRTdGVwKVwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiaHgtYnV0dG9uIG10LTJcIlxyXG4gICAgICAgICAgICBbY2xhc3MuaXMtc21hbGxdPVwiaXNTbWFsbFNpemVcIlxyXG4gICAgICAgICAgICBbY2xhc3MuaXMtbGFyZ2VdPVwiaXNMYXJnZVNpemVcIlxyXG4gICAgICAgICAgICBbY2xhc3MuZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG4gICAgICAgICAgPlxyXG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cImh4LWljb24gaWNvbi1hbmdsZS1kb3duIGlzLW1lZGl1bSBpcy1pbmZvXCI+PC9zcGFuPlxyXG4gICAgICAgICAgICA8c3BhblxyXG4gICAgICAgICAgICAgIGNsYXNzPVwic3Itb25seSBpcy1oaWRkZW5cIlxyXG4gICAgICAgICAgICAgIGkxOG49XCJAQG5nYi50aW1lcGlja2VyLmRlY3JlbWVudC1zZWNvbmRzXCJcclxuICAgICAgICAgICAgICA+RGVjcmVtZW50IHNlY29uZHM8L3NwYW5cclxuICAgICAgICAgICAgPlxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPGRpdiAqbmdJZj1cIm1lcmlkaWFuXCIgY2xhc3M9XCJuZ2ItdHAtc3BhY2VyXCI+PC9kaXY+XHJcbiAgICAgICAgPGRpdiAqbmdJZj1cIm1lcmlkaWFuXCIgY2xhc3M9XCJuZ2ItdHAtbWVyaWRpYW5cIj5cclxuICAgICAgICAgIDxidXR0b25cclxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXHJcbiAgICAgICAgICAgIGNsYXNzPVwiaHgtYnV0dG9uIG1iLTFcIlxyXG4gICAgICAgICAgICBbY2xhc3MuaXMtc21hbGxdPVwiaXNTbWFsbFNpemVcIlxyXG4gICAgICAgICAgICBbY2xhc3MuaXMtbGFyZ2VdPVwiaXNMYXJnZVNpemVcIlxyXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG4gICAgICAgICAgICBbY2xhc3MuZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlTWVyaWRpYW4oKVwiXHJcbiAgICAgICAgICA+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXJcclxuICAgICAgICAgICAgICAqbmdJZj1cIm1vZGVsICYmIG1vZGVsLmhvdXIgPj0gMTI7IGVsc2UgYW1cIlxyXG4gICAgICAgICAgICAgIGkxOG49XCJAQG5nYi50aW1lcGlja2VyLlBNXCJcclxuICAgICAgICAgICAgICA+e3sgaTE4bi5nZXRBZnRlcm5vb25QZXJpb2QoKSB9fTwvbmctY29udGFpbmVyXHJcbiAgICAgICAgICAgID5cclxuICAgICAgICAgICAgPG5nLXRlbXBsYXRlICNhbSBpMThuPVwiQEBuZ2IudGltZXBpY2tlci5BTVwiPnt7XHJcbiAgICAgICAgICAgICAgaTE4bi5nZXRNb3JuaW5nUGVyaW9kKClcclxuICAgICAgICAgICAgfX08L25nLXRlbXBsYXRlPlxyXG4gICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgPC9maWVsZHNldD5cclxuICBgLFxyXG4gIHByb3ZpZGVyczogW1xyXG4gICAge1xyXG4gICAgICBwcm92aWRlOiBOR19WQUxVRV9BQ0NFU1NPUixcclxuICAgICAgdXNlRXhpc3Rpbmc6IGZvcndhcmRSZWYoKCkgPT4gVGltZXBpY2tlciksXHJcbiAgICAgIG11bHRpOiB0cnVlLFxyXG4gICAgfSxcclxuICBdLFxyXG59KVxyXG4vLyBUT0RPOiByZW5hbWUgdG8gVGltZVBpY2tlckNvbXBvbmVudFxyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L2NvbXBvbmVudC1jbGFzcy1zdWZmaXhcclxuZXhwb3J0IGNsYXNzIFRpbWVwaWNrZXIgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgT25DaGFuZ2VzIHtcclxuICBzdGF0aWMgbmdBY2NlcHRJbnB1dFR5cGVfc2l6ZTogc3RyaW5nO1xyXG5cclxuICBwdWJsaWMgbW9kZWw6IEh4YVRpbWU7XHJcblxyXG4gIHByaXZhdGUgX2hvdXJTdGVwOiBudW1iZXI7XHJcbiAgcHJpdmF0ZSBfbWludXRlU3RlcDogbnVtYmVyO1xyXG4gIHByaXZhdGUgX3NlY29uZFN0ZXA6IG51bWJlcjtcclxuXHJcbiAgLyoqXHJcbiAgICogV2hldGhlciB0byBkaXNwbGF5IDEySCBvciAyNEggbW9kZS5cclxuICAgKi9cclxuICBASW5wdXQoKSBtZXJpZGlhbjogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogSWYgYHRydWVgLCB0aGUgc3Bpbm5lcnMgYWJvdmUgYW5kIGJlbG93IGlucHV0cyBhcmUgdmlzaWJsZS5cclxuICAgKi9cclxuICBASW5wdXQoKSBzcGlubmVyczogYm9vbGVhbjtcclxuXHJcbiAgLyoqXHJcbiAgICogSWYgYHRydWVgLCBpdCBpcyBwb3NzaWJsZSB0byBzZWxlY3Qgc2Vjb25kcy5cclxuICAgKi9cclxuICBASW5wdXQoKSBzZWNvbmRzOiBib29sZWFuO1xyXG5cclxuICAvKipcclxuICAgKiBUaGUgbnVtYmVyIG9mIGhvdXJzIHRvIGFkZC9zdWJ0cmFjdCB3aGVuIGNsaWNraW5nIGhvdXIgc3Bpbm5lcnMuXHJcbiAgICovXHJcbiAgQElucHV0KClcclxuICBzZXQgaG91clN0ZXAoc3RlcDogbnVtYmVyKSB7XHJcbiAgICB0aGlzLl9ob3VyU3RlcCA9IGlzSW50ZWdlcihzdGVwKSA/IHN0ZXAgOiB0aGlzLl9jb25maWcuaG91clN0ZXA7XHJcbiAgfVxyXG5cclxuICBnZXQgaG91clN0ZXAoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLl9ob3VyU3RlcDtcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoZSBudW1iZXIgb2YgbWludXRlcyB0byBhZGQvc3VidHJhY3Qgd2hlbiBjbGlja2luZyBtaW51dGUgc3Bpbm5lcnMuXHJcbiAgICovXHJcbiAgQElucHV0KClcclxuICBzZXQgbWludXRlU3RlcChzdGVwOiBudW1iZXIpIHtcclxuICAgIHRoaXMuX21pbnV0ZVN0ZXAgPSBpc0ludGVnZXIoc3RlcCkgPyBzdGVwIDogdGhpcy5fY29uZmlnLm1pbnV0ZVN0ZXA7XHJcbiAgfVxyXG5cclxuICBnZXQgbWludXRlU3RlcCgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuX21pbnV0ZVN0ZXA7XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUaGUgbnVtYmVyIG9mIHNlY29uZHMgdG8gYWRkL3N1YnRyYWN0IHdoZW4gY2xpY2tpbmcgc2Vjb25kIHNwaW5uZXJzLlxyXG4gICAqL1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IHNlY29uZFN0ZXAoc3RlcDogbnVtYmVyKSB7XHJcbiAgICB0aGlzLl9zZWNvbmRTdGVwID0gaXNJbnRlZ2VyKHN0ZXApID8gc3RlcCA6IHRoaXMuX2NvbmZpZy5zZWNvbmRTdGVwO1xyXG4gIH1cclxuXHJcbiAgZ2V0IHNlY29uZFN0ZXAoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLl9zZWNvbmRTdGVwO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogSWYgYHRydWVgLCB0aGUgdGltZS1waWNrZXIgaXMgcmVhZG9ubHkgYW5kIGNhbid0IGJlIGNoYW5nZWQuXHJcbiAgICovXHJcbiAgQElucHV0KCkgcmVhZG9ubHlJbnB1dHM6IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIElmIGB0cnVlYCwgdGhlIHRpbWVwaWNrZXIgaW5wdXQgaXMgZGlzYWJsZWQuXHJcbiAgICovXHJcbiAgQElucHV0KCkgZGlzYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gIC8qKlxyXG4gICAqIFRoZSBzaXplIG9mIGlucHV0cyBhbmQgYnV0dG9ucy5cclxuICAgKi