UNPKG

@taiga-ui/kit

Version:

Taiga UI Angular main components kit

200 lines 30.7 kB
import { computed, Directive, effect, inject, Input, signal, untracked, } from '@angular/core'; import { toSignal } from '@angular/core/rxjs-interop'; import { MaskitoDirective } from '@maskito/angular'; import { maskitoTransform } from '@maskito/core'; import { maskitoCaretGuard, maskitoNumberOptionsGenerator, maskitoParseNumber, } from '@maskito/kit'; import { tuiAsControl, TuiControl, tuiValueTransformerFrom } from '@taiga-ui/cdk/classes'; import { CHAR_HYPHEN, CHAR_MINUS, TUI_ALLOW_SIGNAL_WRITES } from '@taiga-ui/cdk/constants'; import { TUI_IS_IOS } from '@taiga-ui/cdk/tokens'; import { tuiInjectElement } from '@taiga-ui/cdk/utils/dom'; import { tuiIsSafeToRound } from '@taiga-ui/cdk/utils/math'; import { TuiTextfieldDirective, TuiWithTextfield, } from '@taiga-ui/core/components/textfield'; import { TUI_DEFAULT_NUMBER_FORMAT, TUI_NUMBER_FORMAT } from '@taiga-ui/core/tokens'; import { tuiFormatNumber } from '@taiga-ui/core/utils/format'; import { tuiMaskito } from '@taiga-ui/kit/utils'; import { TUI_INPUT_NUMBER_OPTIONS } from './input-number.options'; import * as i0 from "@angular/core"; import * as i1 from "@taiga-ui/core/components/textfield"; import * as i2 from "@maskito/angular"; const DEFAULT_MAX_LENGTH = 18; class TuiInputNumberDirective extends TuiControl { constructor() { super(...arguments); this.options = inject(TUI_INPUT_NUMBER_OPTIONS); this.textfield = inject(TuiTextfieldDirective); this.isIOS = inject(TUI_IS_IOS); this.minRaw = signal(this.options.min); this.maxRaw = signal(this.options.max); this.numberFormat = toSignal(inject(TUI_NUMBER_FORMAT), { initialValue: TUI_DEFAULT_NUMBER_FORMAT, }); this.formatted = computed(() => maskitoParseNumber(this.textfield.value(), this.numberFormat())); this.precision = computed((precision = this.numberFormat().precision) => Number.isNaN(precision) ? 2 : precision); this.unfinished = computed((value = this.formatted()) => value < 0 ? value > this.max() : value < this.min()); this.element = tuiInjectElement(); this.mask = tuiMaskito(computed(() => this.computeMask(this.maskParams))); this.inputMode = computed(() => { if (this.isIOS) { return this.min() < 0 ? 'text' // iPhone does not have minus sign if inputMode equals to 'numeric' / 'decimal' : 'decimal'; } /** * Samsung Keyboard does not minus sign for `inputmode=decimal` * @see https://github.com/taiga-family/taiga-ui/issues/11061#issuecomment-2939103792 */ return 'numeric'; }); this.defaultMaxLength = computed(() => { const { decimalSeparator, thousandSeparator } = this.numberFormat(); const decimalPart = !!this.precision() && this.textfield.value().includes(decimalSeparator); const precision = decimalPart ? Math.min(this.precision() + 1, 20) : 0; const takeThousand = thousandSeparator.repeat(5).length; const affixes = this.prefix().length + this.postfix().length; return DEFAULT_MAX_LENGTH + precision + takeThousand + affixes; }); this.onChangeEffect = effect(() => { const value = this.formatted(); if (Number.isNaN(value)) { this.onChange(null); return; } if (this.unfinished() || value < this.min() || value > this.max() || this.value() === value) { return; } this.onChange(value); }, TUI_ALLOW_SIGNAL_WRITES); this.maskInitialCalibrationEffect = effect(() => { const options = maskitoNumberOptionsGenerator({ ...this.maskParams, min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER, }); this.textfield.value.update((x) => maskitoTransform(x, options)); }, TUI_ALLOW_SIGNAL_WRITES); this.min = computed(() => Math.min(this.minRaw(), this.maxRaw())); this.max = computed(() => Math.max(this.minRaw(), this.maxRaw())); this.prefix = signal(this.options.prefix); this.postfix = signal(this.options.postfix); } set minSetter(x) { this.minRaw.set(this.transformer.fromControlValue(x ?? this.options.min)); } set maxSetter(x) { this.maxRaw.set(this.transformer.fromControlValue(x ?? this.options.max)); } // TODO(v5): replace with signal input set prefixSetter(x) { this.prefix.set(x); } // TODO(v5): replace with signal input set postfixSetter(x) { this.postfix.set(x); } writeValue(value) { const reset = this.control.pristine && this.control.untouched && !value; const changed = untracked(() => value !== this.value()); if (changed || reset) { super.writeValue(value); untracked(() => this.setValue(this.value())); } } setValue(value) { this.textfield.value.set(this.formatNumber(value)); } onFocus() { if (Number.isNaN(this.formatted()) && !this.readOnly()) { this.textfield.value.set(this.prefix() + this.postfix()); } } onBlur() { setTimeout(() => this.setValue(this.transformer.fromControlValue(this.control.value))); } get maskParams() { const { decimalMode, ...numberFormat } = this.numberFormat(); const maximumFractionDigits = this.precision(); return { ...numberFormat, maximumFractionDigits, min: this.min(), max: this.max(), prefix: this.prefix(), postfix: this.postfix(), minimumFractionDigits: decimalMode === 'always' ? maximumFractionDigits : 0, }; } formatNumber(value) { if (value === null || Number.isNaN(value)) { return ''; } return ((this.prefix() !== CHAR_MINUS ? this.prefix() : '') + tuiFormatNumber(value, { ...this.numberFormat(), /** * Number can satisfy interval [Number.MIN_SAFE_INTEGER; Number.MAX_SAFE_INTEGER] * but its rounding can violate it. * Before BigInt support there is no perfect solution – only trade off. * No rounding is better than lose precision and incorrect mutation of already valid value. */ precision: tuiIsSafeToRound(value, this.precision()) ? this.precision() : Infinity, }).replace(CHAR_HYPHEN, CHAR_MINUS) + this.postfix()); } computeMask(params) { const { prefix = '', postfix = '' } = params; const { plugins, ...options } = maskitoNumberOptionsGenerator(params); return { ...options, plugins: [ ...plugins, maskitoCaretGuard((value) => [ prefix.length, value.length - postfix.length, ]), ], }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiInputNumberDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.12", type: TuiInputNumberDirective, isStandalone: true, selector: "input[tuiInputNumber]", inputs: { minSetter: ["min", "minSetter"], maxSetter: ["max", "maxSetter"], prefixSetter: ["prefix", "prefixSetter"], postfixSetter: ["postfix", "postfixSetter"] }, host: { listeners: { "focus": "onFocus()", "blur": "onBlur()" }, properties: { "disabled": "disabled()", "attr.inputMode": "inputMode()", "attr.maxLength": "element.maxLength > 0 ? element.maxLength : defaultMaxLength()" } }, providers: [ tuiAsControl(TuiInputNumberDirective), tuiValueTransformerFrom(TUI_INPUT_NUMBER_OPTIONS), ], usesInheritance: true, hostDirectives: [{ directive: i1.TuiWithTextfield }, { directive: i2.MaskitoDirective }], ngImport: i0 }); } } export { TuiInputNumberDirective }; i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: TuiInputNumberDirective, decorators: [{ type: Directive, args: [{ standalone: true, selector: 'input[tuiInputNumber]', providers: [ tuiAsControl(TuiInputNumberDirective), tuiValueTransformerFrom(TUI_INPUT_NUMBER_OPTIONS), ], hostDirectives: [TuiWithTextfield, MaskitoDirective], host: { '[disabled]': 'disabled()', '[attr.inputMode]': 'inputMode()', '[attr.maxLength]': 'element.maxLength > 0 ? element.maxLength : defaultMaxLength()', '(focus)': 'onFocus()', '(blur)': 'onBlur()', }, }] }], propDecorators: { minSetter: [{ type: Input, args: ['min'] }], maxSetter: [{ type: Input, args: ['max'] }], prefixSetter: [{ type: Input, args: ['prefix'] }], postfixSetter: [{ type: Input, args: ['postfix'] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtbnVtYmVyLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2tpdC9jb21wb25lbnRzL2lucHV0LW51bWJlci9pbnB1dC1udW1iZXIuZGlyZWN0aXZlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDSCxRQUFRLEVBQ1IsU0FBUyxFQUNULE1BQU0sRUFDTixNQUFNLEVBQ04sS0FBSyxFQUNMLE1BQU0sRUFDTixTQUFTLEdBQ1osTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFDLFFBQVEsRUFBQyxNQUFNLDRCQUE0QixDQUFDO0FBQ3BELE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLGtCQUFrQixDQUFDO0FBQ2xELE9BQU8sRUFBc0IsZ0JBQWdCLEVBQUMsTUFBTSxlQUFlLENBQUM7QUFDcEUsT0FBTyxFQUNILGlCQUFpQixFQUNqQiw2QkFBNkIsRUFFN0Isa0JBQWtCLEdBQ3JCLE1BQU0sY0FBYyxDQUFDO0FBQ3RCLE9BQU8sRUFBQyxZQUFZLEVBQUUsVUFBVSxFQUFFLHVCQUF1QixFQUFDLE1BQU0sdUJBQXVCLENBQUM7QUFDeEYsT0FBTyxFQUFDLFdBQVcsRUFBRSxVQUFVLEVBQUUsdUJBQXVCLEVBQUMsTUFBTSx5QkFBeUIsQ0FBQztBQUN6RixPQUFPLEVBQUMsVUFBVSxFQUFDLE1BQU0sc0JBQXNCLENBQUM7QUFDaEQsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0seUJBQXlCLENBQUM7QUFDekQsT0FBTyxFQUFDLGdCQUFnQixFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDMUQsT0FBTyxFQUNILHFCQUFxQixFQUNyQixnQkFBZ0IsR0FDbkIsTUFBTSxxQ0FBcUMsQ0FBQztBQUM3QyxPQUFPLEVBQUMseUJBQXlCLEVBQUUsaUJBQWlCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUNuRixPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0sNkJBQTZCLENBQUM7QUFDNUQsT0FBTyxFQUFDLFVBQVUsRUFBQyxNQUFNLHFCQUFxQixDQUFDO0FBRS9DLE9BQU8sRUFBQyx3QkFBd0IsRUFBQyxNQUFNLHdCQUF3QixDQUFDOzs7O0FBRWhFLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxDQUFDO0FBRTlCLE1BaUJhLHVCQUF3QixTQUFRLFVBQXlCO0lBakJ0RTs7UUFrQnFCLFlBQU8sR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsQ0FBQztRQUMzQyxjQUFTLEdBQUcsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUM7UUFDMUMsVUFBSyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUMzQixXQUFNLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbEMsV0FBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQ2xDLGlCQUFZLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFO1lBQ2hFLFlBQVksRUFBRSx5QkFBeUI7U0FDMUMsQ0FBQyxDQUFDO1FBRWMsY0FBUyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FDdkMsa0JBQWtCLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUMsQ0FDbEUsQ0FBQztRQUVlLGNBQVMsR0FBRyxRQUFRLENBQUMsQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQ2hGLE1BQU0sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUMxQyxDQUFDO1FBRWUsZUFBVSxHQUFHLFFBQVEsQ0FBQyxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLEVBQUUsRUFBRSxDQUNoRSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUN0RCxDQUFDO1FBRWlCLFlBQU8sR0FBRyxnQkFBZ0IsRUFBb0IsQ0FBQztRQUMvQyxTQUFJLEdBQUcsVUFBVSxDQUNoQyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FDcEQsQ0FBQztRQUVpQixjQUFTLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtZQUN6QyxJQUFJLElBQUksQ0FBQyxLQUFLLEVBQUU7Z0JBQ1osT0FBTyxJQUFJLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQztvQkFDakIsQ0FBQyxDQUFDLE1BQU0sQ0FBQywrRUFBK0U7b0JBQ3hGLENBQUMsQ0FBQyxTQUFTLENBQUM7YUFDbkI7WUFFRDs7O2VBR0c7WUFDSCxPQUFPLFNBQVMsQ0FBQztRQUNyQixDQUFDLENBQUMsQ0FBQztRQUVnQixxQkFBZ0IsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFO1lBQ2hELE1BQU0sRUFBQyxnQkFBZ0IsRUFBRSxpQkFBaUIsRUFBQyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUNsRSxNQUFNLFdBQVcsR0FDYixDQUFDLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLENBQUM7WUFDNUUsTUFBTSxTQUFTLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN2RSxNQUFNLFlBQVksR0FBRyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1lBQ3hELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLE1BQU0sQ0FBQztZQUU3RCxPQUFPLGtCQUFrQixHQUFHLFNBQVMsR0FBRyxZQUFZLEdBQUcsT0FBTyxDQUFDO1FBQ25FLENBQUMsQ0FBQyxDQUFDO1FBRWdCLG1CQUFjLEdBQUcsTUFBTSxDQUFDLEdBQUcsRUFBRTtZQUM1QyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFFL0IsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFO2dCQUNyQixJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO2dCQUVwQixPQUFPO2FBQ1Y7WUFFRCxJQUNJLElBQUksQ0FBQyxVQUFVLEVBQUU7Z0JBQ2pCLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFO2dCQUNsQixLQUFLLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRTtnQkFDbEIsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLEtBQUssRUFDeEI7Z0JBQ0UsT0FBTzthQUNWO1lBRUQsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixDQUFDLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztRQUVsQixpQ0FBNEIsR0FBRyxNQUFNLENBQUMsR0FBRyxFQUFFO1lBQ2pELE1BQU0sT0FBTyxHQUFHLDZCQUE2QixDQUFDO2dCQUMxQyxHQUFHLElBQUksQ0FBQyxVQUFVO2dCQUNsQixHQUFHLEVBQUUsTUFBTSxDQUFDLGdCQUFnQjtnQkFDNUIsR0FBRyxFQUFFLE1BQU0sQ0FBQyxnQkFBZ0I7YUFDL0IsQ0FBQyxDQUFDO1lBRUgsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQztRQUNyRSxDQUFDLEVBQUUsdUJBQXVCLENBQUMsQ0FBQztRQUVaLFFBQUcsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztRQUM3RCxRQUFHLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDN0QsV0FBTSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3JDLFlBQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztLQXVHMUQ7SUFyR0csSUFDVyxTQUFTLENBQUMsQ0FBZ0I7UUFDakMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzlFLENBQUM7SUFFRCxJQUNXLFNBQVMsQ0FBQyxDQUFnQjtRQUNqQyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGdCQUFnQixDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDOUUsQ0FBQztJQUVELHNDQUFzQztJQUN0QyxJQUNXLFlBQVksQ0FBQyxDQUFTO1FBQzdCLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3ZCLENBQUM7SUFFRCxzQ0FBc0M7SUFDdEMsSUFDVyxhQUFhLENBQUMsQ0FBUztRQUM5QixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBRWUsVUFBVSxDQUFDLEtBQW9CO1FBQzNDLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUMsUUFBUSxJQUFJLElBQUksQ0FBQyxPQUFPLENBQUMsU0FBUyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQ3hFLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLEtBQUssSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFFeEQsSUFBSSxPQUFPLElBQUksS0FBSyxFQUFFO1lBQ2xCLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDeEIsU0FBUyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztTQUNoRDtJQUNMLENBQUM7SUFFTSxRQUFRLENBQUMsS0FBb0I7UUFDaEMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRVMsT0FBTztRQUNiLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRTtZQUNwRCxJQUFJLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO1NBQzVEO0lBQ0wsQ0FBQztJQUVTLE1BQU07UUFDWixVQUFVLENBQUMsR0FBRyxFQUFFLENBQ1osSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FDdkUsQ0FBQztJQUNOLENBQUM7SUFFRCxJQUFZLFVBQVU7UUFDbEIsTUFBTSxFQUFDLFdBQVcsRUFBRSxHQUFHLFlBQVksRUFBQyxHQUFHLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUMzRCxNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQyxTQUFTLEVBQUUsQ0FBQztRQUUvQyxPQUFPO1lBQ0gsR0FBRyxZQUFZO1lBQ2YscUJBQXFCO1lBQ3JCLEdBQUcsRUFBRSxJQUFJLENBQUMsR0FBRyxFQUFFO1lBQ2YsR0FBRyxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUU7WUFDZixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRTtZQUNyQixPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUN2QixxQkFBcUIsRUFBRSxXQUFXLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDLENBQUMsQ0FBQztTQUM5RSxDQUFDO0lBQ04sQ0FBQztJQUVPLFlBQVksQ0FBQyxLQUFvQjtRQUNyQyxJQUFJLEtBQUssS0FBSyxJQUFJLElBQUksTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUN2QyxPQUFPLEVBQUUsQ0FBQztTQUNiO1FBRUQsT0FBTyxDQUNILENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxLQUFLLFVBQVUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDbkQsZUFBZSxDQUFDLEtBQUssRUFBRTtnQkFDbkIsR0FBRyxJQUFJLENBQUMsWUFBWSxFQUFFO2dCQUN0Qjs7Ozs7bUJBS0c7Z0JBQ0gsU0FBUyxFQUFFLGdCQUFnQixDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7b0JBQ2hELENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFO29CQUNsQixDQUFDLENBQUMsUUFBUTthQUNqQixDQUFDLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQUM7WUFDbkMsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUNqQixDQUFDO0lBQ04sQ0FBQztJQUVPLFdBQVcsQ0FBQyxNQUEyQjtRQUMzQyxNQUFNLEVBQUMsTUFBTSxHQUFHLEVBQUUsRUFBRSxPQUFPLEdBQUcsRUFBRSxFQUFDLEdBQUcsTUFBTSxDQUFDO1FBQzNDLE1BQU0sRUFBQyxPQUFPLEVBQUUsR0FBRyxPQUFPLEVBQUMsR0FBRyw2QkFBNkIsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUVwRSxPQUFPO1lBQ0gsR0FBRyxPQUFPO1lBQ1YsT0FBTyxFQUFFO2dCQUNMLEdBQUcsT0FBTztnQkFDVixpQkFBaUIsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUM7b0JBQ3pCLE1BQU0sQ0FBQyxNQUFNO29CQUNiLEtBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU07aUJBQ2hDLENBQUM7YUFDTDtTQUNKLENBQUM7SUFDTixDQUFDOytHQTVMUSx1QkFBdUI7bUdBQXZCLHVCQUF1QiwyY0FkckI7WUFDUCxZQUFZLENBQUMsdUJBQXVCLENBQUM7WUFDckMsdUJBQXVCLENBQUMsd0JBQXdCLENBQUM7U0FDcEQ7O1NBV1EsdUJBQXVCOzRGQUF2Qix1QkFBdUI7a0JBakJuQyxTQUFTO21CQUFDO29CQUNQLFVBQVUsRUFBRSxJQUFJO29CQUNoQixRQUFRLEVBQUUsdUJBQXVCO29CQUNqQyxTQUFTLEVBQUU7d0JBQ1AsWUFBWSx5QkFBeUI7d0JBQ3JDLHVCQUF1QixDQUFDLHdCQUF3QixDQUFDO3FCQUNwRDtvQkFDRCxjQUFjLEVBQUUsQ0FBQyxnQkFBZ0IsRUFBRSxnQkFBZ0IsQ0FBQztvQkFDcEQsSUFBSSxFQUFFO3dCQUNGLFlBQVksRUFBRSxZQUFZO3dCQUMxQixrQkFBa0IsRUFBRSxhQUFhO3dCQUNqQyxrQkFBa0IsRUFDZCxnRUFBZ0U7d0JBQ3BFLFNBQVMsRUFBRSxXQUFXO3dCQUN0QixRQUFRLEVBQUUsVUFBVTtxQkFDdkI7aUJBQ0o7OEJBMEZjLFNBQVM7c0JBRG5CLEtBQUs7dUJBQUMsS0FBSztnQkFNRCxTQUFTO3NCQURuQixLQUFLO3VCQUFDLEtBQUs7Z0JBT0QsWUFBWTtzQkFEdEIsS0FBSzt1QkFBQyxRQUFRO2dCQU9KLGFBQWE7c0JBRHZCLEtBQUs7dUJBQUMsU0FBUyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gICAgY29tcHV0ZWQsXG4gICAgRGlyZWN0aXZlLFxuICAgIGVmZmVjdCxcbiAgICBpbmplY3QsXG4gICAgSW5wdXQsXG4gICAgc2lnbmFsLFxuICAgIHVudHJhY2tlZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge3RvU2lnbmFsfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQge01hc2tpdG9EaXJlY3RpdmV9IGZyb20gJ0BtYXNraXRvL2FuZ3VsYXInO1xuaW1wb3J0IHt0eXBlIE1hc2tpdG9PcHRpb25zLCBtYXNraXRvVHJhbnNmb3JtfSBmcm9tICdAbWFza2l0by9jb3JlJztcbmltcG9ydCB7XG4gICAgbWFza2l0b0NhcmV0R3VhcmQsXG4gICAgbWFza2l0b051bWJlck9wdGlvbnNHZW5lcmF0b3IsXG4gICAgdHlwZSBNYXNraXRvTnVtYmVyUGFyYW1zLFxuICAgIG1hc2tpdG9QYXJzZU51bWJlcixcbn0gZnJvbSAnQG1hc2tpdG8va2l0JztcbmltcG9ydCB7dHVpQXNDb250cm9sLCBUdWlDb250cm9sLCB0dWlWYWx1ZVRyYW5zZm9ybWVyRnJvbX0gZnJvbSAnQHRhaWdhLXVpL2Nkay9jbGFzc2VzJztcbmltcG9ydCB7Q0hBUl9IWVBIRU4sIENIQVJfTUlOVVMsIFRVSV9BTExPV19TSUdOQUxfV1JJVEVTfSBmcm9tICdAdGFpZ2EtdWkvY2RrL2NvbnN0YW50cyc7XG5pbXBvcnQge1RVSV9JU19JT1N9IGZyb20gJ0B0YWlnYS11aS9jZGsvdG9rZW5zJztcbmltcG9ydCB7dHVpSW5qZWN0RWxlbWVudH0gZnJvbSAnQHRhaWdhLXVpL2Nkay91dGlscy9kb20nO1xuaW1wb3J0IHt0dWlJc1NhZmVUb1JvdW5kfSBmcm9tICdAdGFpZ2EtdWkvY2RrL3V0aWxzL21hdGgnO1xuaW1wb3J0IHtcbiAgICBUdWlUZXh0ZmllbGREaXJlY3RpdmUsXG4gICAgVHVpV2l0aFRleHRmaWVsZCxcbn0gZnJvbSAnQHRhaWdhLXVpL2NvcmUvY29tcG9uZW50cy90ZXh0ZmllbGQnO1xuaW1wb3J0IHtUVUlfREVGQVVMVF9OVU1CRVJfRk9STUFULCBUVUlfTlVNQkVSX0ZPUk1BVH0gZnJvbSAnQHRhaWdhLXVpL2NvcmUvdG9rZW5zJztcbmltcG9ydCB7dHVpRm9ybWF0TnVtYmVyfSBmcm9tICdAdGFpZ2EtdWkvY29yZS91dGlscy9mb3JtYXQnO1xuaW1wb3J0IHt0dWlNYXNraXRvfSBmcm9tICdAdGFpZ2EtdWkva2l0L3V0aWxzJztcblxuaW1wb3J0IHtUVUlfSU5QVVRfTlVNQkVSX09QVElPTlN9IGZyb20gJy4vaW5wdXQtbnVtYmVyLm9wdGlvbnMnO1xuXG5jb25zdCBERUZBVUxUX01BWF9MRU5HVEggPSAxODtcblxuQERpcmVjdGl2ZSh7XG4gICAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgICBzZWxlY3RvcjogJ2lucHV0W3R1aUlucHV0TnVtYmVyXScsXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHR1aUFzQ29udHJvbChUdWlJbnB1dE51bWJlckRpcmVjdGl2ZSksXG4gICAgICAgIHR1aVZhbHVlVHJhbnNmb3JtZXJGcm9tKFRVSV9JTlBVVF9OVU1CRVJfT1BUSU9OUyksXG4gICAgXSxcbiAgICBob3N0RGlyZWN0aXZlczogW1R1aVdpdGhUZXh0ZmllbGQsIE1hc2tpdG9EaXJlY3RpdmVdLFxuICAgIGhvc3Q6IHtcbiAgICAgICAgJ1tkaXNhYmxlZF0nOiAnZGlzYWJsZWQoKScsXG4gICAgICAgICdbYXR0ci5pbnB1dE1vZGVdJzogJ2lucHV0TW9kZSgpJyxcbiAgICAgICAgJ1thdHRyLm1heExlbmd0aF0nOlxuICAgICAgICAgICAgJ2VsZW1lbnQubWF4TGVuZ3RoID4gMCA/IGVsZW1lbnQubWF4TGVuZ3RoIDogZGVmYXVsdE1heExlbmd0aCgpJyxcbiAgICAgICAgJyhmb2N1cyknOiAnb25Gb2N1cygpJyxcbiAgICAgICAgJyhibHVyKSc6ICdvbkJsdXIoKScsXG4gICAgfSxcbn0pXG5leHBvcnQgY2xhc3MgVHVpSW5wdXROdW1iZXJEaXJlY3RpdmUgZXh0ZW5kcyBUdWlDb250cm9sPG51bWJlciB8IG51bGw+IHtcbiAgICBwcml2YXRlIHJlYWRvbmx5IG9wdGlvbnMgPSBpbmplY3QoVFVJX0lOUFVUX05VTUJFUl9PUFRJT05TKTtcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRleHRmaWVsZCA9IGluamVjdChUdWlUZXh0ZmllbGREaXJlY3RpdmUpO1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaXNJT1MgPSBpbmplY3QoVFVJX0lTX0lPUyk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBtaW5SYXcgPSBzaWduYWwodGhpcy5vcHRpb25zLm1pbik7XG4gICAgcHJpdmF0ZSByZWFkb25seSBtYXhSYXcgPSBzaWduYWwodGhpcy5vcHRpb25zLm1heCk7XG4gICAgcHJpdmF0ZSByZWFkb25seSBudW1iZXJGb3JtYXQgPSB0b1NpZ25hbChpbmplY3QoVFVJX05VTUJFUl9GT1JNQVQpLCB7XG4gICAgICAgIGluaXRpYWxWYWx1ZTogVFVJX0RFRkFVTFRfTlVNQkVSX0ZPUk1BVCxcbiAgICB9KTtcblxuICAgIHByaXZhdGUgcmVhZG9ubHkgZm9ybWF0dGVkID0gY29tcHV0ZWQoKCkgPT5cbiAgICAgICAgbWFza2l0b1BhcnNlTnVtYmVyKHRoaXMudGV4dGZpZWxkLnZhbHVlKCksIHRoaXMubnVtYmVyRm9ybWF0KCkpLFxuICAgICk7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IHByZWNpc2lvbiA9IGNvbXB1dGVkKChwcmVjaXNpb24gPSB0aGlzLm51bWJlckZvcm1hdCgpLnByZWNpc2lvbikgPT5cbiAgICAgICAgTnVtYmVyLmlzTmFOKHByZWNpc2lvbikgPyAyIDogcHJlY2lzaW9uLFxuICAgICk7XG5cbiAgICBwcml2YXRlIHJlYWRvbmx5IHVuZmluaXNoZWQgPSBjb21wdXRlZCgodmFsdWUgPSB0aGlzLmZvcm1hdHRlZCgpKSA9PlxuICAgICAgICB2YWx1ZSA8IDAgPyB2YWx1ZSA+IHRoaXMubWF4KCkgOiB2YWx1ZSA8IHRoaXMubWluKCksXG4gICAgKTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBlbGVtZW50ID0gdHVpSW5qZWN0RWxlbWVudDxIVE1MSW5wdXRFbGVtZW50PigpO1xuICAgIHByb3RlY3RlZCByZWFkb25seSBtYXNrID0gdHVpTWFza2l0byhcbiAgICAgICAgY29tcHV0ZWQoKCkgPT4gdGhpcy5jb21wdXRlTWFzayh0aGlzLm1hc2tQYXJhbXMpKSxcbiAgICApO1xuXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGlucHV0TW9kZSA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuaXNJT1MpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLm1pbigpIDwgMFxuICAgICAgICAgICAgICAgID8gJ3RleHQnIC8vIGlQaG9uZSBkb2VzIG5vdCBoYXZlIG1pbnVzIHNpZ24gaWYgaW5wdXRNb2RlIGVxdWFscyB0byAnbnVtZXJpYycgLyAnZGVjaW1hbCdcbiAgICAgICAgICAgICAgICA6ICdkZWNpbWFsJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiBTYW1zdW5nIEtleWJvYXJkIGRvZXMgbm90IG1pbnVzIHNpZ24gZm9yIGBpbnB1dG1vZGU9ZGVjaW1hbGBcbiAgICAgICAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vdGFpZ2EtZmFtaWx5L3RhaWdhLXVpL2lzc3Vlcy8xMTA2MSNpc3N1ZWNvbW1lbnQtMjkzOTEwMzc5MlxuICAgICAgICAgKi9cbiAgICAgICAgcmV0dXJuICdudW1lcmljJztcbiAgICB9KTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBkZWZhdWx0TWF4TGVuZ3RoID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgICAgICBjb25zdCB7ZGVjaW1hbFNlcGFyYXRvciwgdGhvdXNhbmRTZXBhcmF0b3J9ID0gdGhpcy5udW1iZXJGb3JtYXQoKTtcbiAgICAgICAgY29uc3QgZGVjaW1hbFBhcnQgPVxuICAgICAgICAgICAgISF0aGlzLnByZWNpc2lvbigpICYmIHRoaXMudGV4dGZpZWxkLnZhbHVlKCkuaW5jbHVkZXMoZGVjaW1hbFNlcGFyYXRvcik7XG4gICAgICAgIGNvbnN0IHByZWNpc2lvbiA9IGRlY2ltYWxQYXJ0ID8gTWF0aC5taW4odGhpcy5wcmVjaXNpb24oKSArIDEsIDIwKSA6IDA7XG4gICAgICAgIGNvbnN0IHRha2VUaG91c2FuZCA9IHRob3VzYW5kU2VwYXJhdG9yLnJlcGVhdCg1KS5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGFmZml4ZXMgPSB0aGlzLnByZWZpeCgpLmxlbmd0aCArIHRoaXMucG9zdGZpeCgpLmxlbmd0aDtcblxuICAgICAgICByZXR1cm4gREVGQVVMVF9NQVhfTEVOR1RIICsgcHJlY2lzaW9uICsgdGFrZVRob3VzYW5kICsgYWZmaXhlcztcbiAgICB9KTtcblxuICAgIHByb3RlY3RlZCByZWFkb25seSBvbkNoYW5nZUVmZmVjdCA9IGVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5mb3JtYXR0ZWQoKTtcblxuICAgICAgICBpZiAoTnVtYmVyLmlzTmFOKHZhbHVlKSkge1xuICAgICAgICAgICAgdGhpcy5vbkNoYW5nZShudWxsKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFxuICAgICAgICAgICAgdGhpcy51bmZpbmlzaGVkKCkgfHxcbiAgICAgICAgICAgIHZhbHVlIDwgdGhpcy5taW4oKSB8fFxuICAgICAgICAgICAgdmFsdWUgPiB0aGlzLm1heCgpIHx8XG4gICAgICAgICAgICB0aGlzLnZhbHVlKCkgPT09IHZhbHVlXG4gICAgICAgICkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5vbkNoYW5nZSh2YWx1ZSk7XG4gICAgfSwgVFVJX0FMTE9XX1NJR05BTF9XUklURVMpO1xuXG4gICAgcHJvdGVjdGVkIG1hc2tJbml0aWFsQ2FsaWJyYXRpb25FZmZlY3QgPSBlZmZlY3QoKCkgPT4ge1xuICAgICAgICBjb25zdCBvcHRpb25zID0gbWFza2l0b051bWJlck9wdGlvbnNHZW5lcmF0b3Ioe1xuICAgICAgICAgICAgLi4udGhpcy5tYXNrUGFyYW1zLFxuICAgICAgICAgICAgbWluOiBOdW1iZXIuTUlOX1NBRkVfSU5URUdFUixcbiAgICAgICAgICAgIG1heDogTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMudGV4dGZpZWxkLnZhbHVlLnVwZGF0ZSgoeCkgPT4gbWFza2l0b1RyYW5zZm9ybSh4LCBvcHRpb25zKSk7XG4gICAgfSwgVFVJX0FMTE9XX1NJR05BTF9XUklURVMpO1xuXG4gICAgcHVibGljIHJlYWRvbmx5IG1pbiA9IGNvbXB1dGVkKCgpID0+IE1hdGgubWluKHRoaXMubWluUmF3KCksIHRoaXMubWF4UmF3KCkpKTtcbiAgICBwdWJsaWMgcmVhZG9ubHkgbWF4ID0gY29tcHV0ZWQoKCkgPT4gTWF0aC5tYXgodGhpcy5taW5SYXcoKSwgdGhpcy5tYXhSYXcoKSkpO1xuICAgIHB1YmxpYyByZWFkb25seSBwcmVmaXggPSBzaWduYWwodGhpcy5vcHRpb25zLnByZWZpeCk7XG4gICAgcHVibGljIHJlYWRvbmx5IHBvc3RmaXggPSBzaWduYWwodGhpcy5vcHRpb25zLnBvc3RmaXgpO1xuXG4gICAgQElucHV0KCdtaW4nKVxuICAgIHB1YmxpYyBzZXQgbWluU2V0dGVyKHg6IG51bWJlciB8IG51bGwpIHtcbiAgICAgICAgdGhpcy5taW5SYXcuc2V0KHRoaXMudHJhbnNmb3JtZXIuZnJvbUNvbnRyb2xWYWx1ZSh4ID8/IHRoaXMub3B0aW9ucy5taW4pKTtcbiAgICB9XG5cbiAgICBASW5wdXQoJ21heCcpXG4gICAgcHVibGljIHNldCBtYXhTZXR0ZXIoeDogbnVtYmVyIHwgbnVsbCkge1xuICAgICAgICB0aGlzLm1heFJhdy5zZXQodGhpcy50cmFuc2Zvcm1lci5mcm9tQ29udHJvbFZhbHVlKHggPz8gdGhpcy5vcHRpb25zLm1heCkpO1xuICAgIH1cblxuICAgIC8vIFRPRE8odjUpOiByZXBsYWNlIHdpdGggc2lnbmFsIGlucHV0XG4gICAgQElucHV0KCdwcmVmaXgnKVxuICAgIHB1YmxpYyBzZXQgcHJlZml4U2V0dGVyKHg6IHN0cmluZykge1xuICAgICAgICB0aGlzLnByZWZpeC5zZXQoeCk7XG4gICAgfVxuXG4gICAgLy8gVE9ETyh2NSk6IHJlcGxhY2Ugd2l0aCBzaWduYWwgaW5wdXRcbiAgICBASW5wdXQoJ3Bvc3RmaXgnKVxuICAgIHB1YmxpYyBzZXQgcG9zdGZpeFNldHRlcih4OiBzdHJpbmcpIHtcbiAgICAgICAgdGhpcy5wb3N0Zml4LnNldCh4KTtcbiAgICB9XG5cbiAgICBwdWJsaWMgb3ZlcnJpZGUgd3JpdGVWYWx1ZSh2YWx1ZTogbnVtYmVyIHwgbnVsbCk6IHZvaWQge1xuICAgICAgICBjb25zdCByZXNldCA9IHRoaXMuY29udHJvbC5wcmlzdGluZSAmJiB0aGlzLmNvbnRyb2wudW50b3VjaGVkICYmICF2YWx1ZTtcbiAgICAgICAgY29uc3QgY2hhbmdlZCA9IHVudHJhY2tlZCgoKSA9PiB2YWx1ZSAhPT0gdGhpcy52YWx1ZSgpKTtcblxuICAgICAgICBpZiAoY2hhbmdlZCB8fCByZXNldCkge1xuICAgICAgICAgICAgc3VwZXIud3JpdGVWYWx1ZSh2YWx1ZSk7XG4gICAgICAgICAgICB1bnRyYWNrZWQoKCkgPT4gdGhpcy5zZXRWYWx1ZSh0aGlzLnZhbHVlKCkpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHB1YmxpYyBzZXRWYWx1ZSh2YWx1ZTogbnVtYmVyIHwgbnVsbCk6IHZvaWQge1xuICAgICAgICB0aGlzLnRleHRmaWVsZC52YWx1ZS5zZXQodGhpcy5mb3JtYXROdW1iZXIodmFsdWUpKTtcbiAgICB9XG5cbiAgICBwcm90ZWN0ZWQgb25Gb2N1cygpOiB2b2lkIHtcbiAgICAgICAgaWYgKE51bWJlci5pc05hTih0aGlzLmZvcm1hdHRlZCgpKSAmJiAhdGhpcy5yZWFkT25seSgpKSB7XG4gICAgICAgICAgICB0aGlzLnRleHRmaWVsZC52YWx1ZS5zZXQodGhpcy5wcmVmaXgoKSArIHRoaXMucG9zdGZpeCgpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByb3RlY3RlZCBvbkJsdXIoKTogdm9pZCB7XG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT5cbiAgICAgICAgICAgIHRoaXMuc2V0VmFsdWUodGhpcy50cmFuc2Zvcm1lci5mcm9tQ29udHJvbFZhbHVlKHRoaXMuY29udHJvbC52YWx1ZSkpLFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHByaXZhdGUgZ2V0IG1hc2tQYXJhbXMoKTogTWFza2l0b051bWJlclBhcmFtcyB7XG4gICAgICAgIGNvbnN0IHtkZWNpbWFsTW9kZSwgLi4ubnVtYmVyRm9ybWF0fSA9IHRoaXMubnVtYmVyRm9ybWF0KCk7XG4gICAgICAgIGNvbnN0IG1heGltdW1GcmFjdGlvbkRpZ2l0cyA9IHRoaXMucHJlY2lzaW9uKCk7XG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLm51bWJlckZvcm1hdCxcbiAgICAgICAgICAgIG1heGltdW1GcmFjdGlvbkRpZ2l0cyxcbiAgICAgICAgICAgIG1pbjogdGhpcy5taW4oKSxcbiAgICAgICAgICAgIG1heDogdGhpcy5tYXgoKSxcbiAgICAgICAgICAgIHByZWZpeDogdGhpcy5wcmVmaXgoKSxcbiAgICAgICAgICAgIHBvc3RmaXg6IHRoaXMucG9zdGZpeCgpLFxuICAgICAgICAgICAgbWluaW11bUZyYWN0aW9uRGlnaXRzOiBkZWNpbWFsTW9kZSA9PT0gJ2Fsd2F5cycgPyBtYXhpbXVtRnJhY3Rpb25EaWdpdHMgOiAwLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIHByaXZhdGUgZm9ybWF0TnVtYmVyKHZhbHVlOiBudW1iZXIgfCBudWxsKTogc3RyaW5nIHtcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IE51bWJlci5pc05hTih2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAoXG4gICAgICAgICAgICAodGhpcy5wcmVmaXgoKSAhPT0gQ0hBUl9NSU5VUyA/IHRoaXMucHJlZml4KCkgOiAnJykgK1xuICAgICAgICAgICAgdHVpRm9ybWF0TnVtYmVyKHZhbHVlLCB7XG4gICAgICAgICAgICAgICAgLi4udGhpcy5udW1iZXJGb3JtYXQoKSxcbiAgICAgICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAgICAgKiBOdW1iZXIgY2FuIHNhdGlzZnkgaW50ZXJ2YWwgW051bWJlci5NSU5fU0FGRV9JTlRFR0VSOyBOdW1iZXIuTUFYX1NBRkVfSU5URUdFUl1cbiAgICAgICAgICAgICAgICAgKiBidXQgaXRzIHJvdW5kaW5nIGNhbiB2aW9sYXRlIGl0LlxuICAgICAgICAgICAgICAgICAqIEJlZm9yZSBCaWdJbnQgc3VwcG9ydCB0aGVyZSBpcyBubyBwZXJmZWN0IHNvbHV0aW9uIOKAkyBvbmx5IHRyYWRlIG9mZi5cbiAgICAgICAgICAgICAgICAgKiBObyByb3VuZGluZyBpcyBiZXR0ZXIgdGhhbiBsb3NlIHByZWNpc2lvbiBhbmQgaW5jb3JyZWN0IG11dGF0aW9uIG9mIGFscmVhZHkgdmFsaWQgdmFsdWUuXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgcHJlY2lzaW9uOiB0dWlJc1NhZmVUb1JvdW5kKHZhbHVlLCB0aGlzLnByZWNpc2lvbigpKVxuICAgICAgICAgICAgICAgICAgICA/IHRoaXMucHJlY2lzaW9uKClcbiAgICAgICAgICAgICAgICAgICAgOiBJbmZpbml0eSxcbiAgICAgICAgICAgIH0pLnJlcGxhY2UoQ0hBUl9IWVBIRU4sIENIQVJfTUlOVVMpICtcbiAgICAgICAgICAgIHRoaXMucG9zdGZpeCgpXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBjb21wdXRlTWFzayhwYXJhbXM6IE1hc2tpdG9OdW1iZXJQYXJhbXMpOiBNYXNraXRvT3B0aW9ucyB7XG4gICAgICAgIGNvbnN0IHtwcmVmaXggPSAnJywgcG9zdGZpeCA9ICcnfSA9IHBhcmFtcztcbiAgICAgICAgY29uc3Qge3BsdWdpbnMsIC4uLm9wdGlvbnN9ID0gbWFza2l0b051bWJlck9wdGlvbnNHZW5lcmF0b3IocGFyYW1zKTtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgLi4ub3B0aW9ucyxcbiAgICAgICAgICAgIHBsdWdpbnM6IFtcbiAgICAgICAgICAgICAgICAuLi5wbHVnaW5zLFxuICAgICAgICAgICAgICAgIG1hc2tpdG9DYXJldEd1YXJkKCh2YWx1ZSkgPT4gW1xuICAgICAgICAgICAgICAgICAgICBwcmVmaXgubGVuZ3RoLFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5sZW5ndGggLSBwb3N0Zml4Lmxlbmd0aCxcbiAgICAgICAgICAgICAgICBdKSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgIH07XG4gICAgfVxufVxuIl19