@snabcentr/client-ui 3.52.1 → 3.52.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,21 +1,22 @@
1
1
  /* eslint-disable class-methods-use-this */
2
- import { ChangeDetectionStrategy, Component, inject, input } from '@angular/core';
2
+ import { ChangeDetectionStrategy, Component, DestroyRef, inject, input, output } from '@angular/core';
3
3
  import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
4
- import { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';
4
+ import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
5
5
  import { SC_CATEGORY_INFO, ScCatalogFilterService, ScIdOrSlugPipe, } from '@snabcentr/client-core';
6
6
  import { tuiIsPresent } from '@taiga-ui/cdk';
7
- import { TuiTextfield } from '@taiga-ui/core';
8
- import { TuiAccordion } from '@taiga-ui/experimental';
9
- import { TuiCheckbox, TuiInputRange, TuiRadio } from '@taiga-ui/kit';
7
+ import { TuiButton, TuiLabel, TuiNumberFormat, TuiTextfield } from '@taiga-ui/core';
8
+ import { TuiCheckbox, TuiInputNumber, TuiRange } from '@taiga-ui/kit';
10
9
  import { isNil } from 'lodash-es';
11
- import { catchError, EMPTY, filter, map, share, switchMap, tap } from 'rxjs';
10
+ import { catchError, debounceTime, EMPTY, filter, map, merge, share, Subscription, switchMap, tap } from 'rxjs';
11
+ import { ScSelectOnFocusinDirective } from '../../directives/select-on-focusin/sc-select-on-focusin.directive';
12
+ import { ScCatalogFilterCollapsibleComponent } from './collapsible/sc-catalog-filter-collapsible.component';
12
13
  import { SC_CATALOG_PRODUCTS_FILTERS } from './tokens/sc-catalog-products-filters';
13
14
  import { SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY } from './tokens/sc-catalog-show-products-recursively';
14
15
  import * as i0 from "@angular/core";
15
16
  import * as i1 from "@angular/forms";
16
- import * as i2 from "@taiga-ui/kit";
17
- import * as i3 from "@taiga-ui/experimental";
18
- import * as i4 from "@taiga-ui/experimental/components/expand";
17
+ import * as i2 from "@taiga-ui/core/components/label";
18
+ import * as i3 from "@taiga-ui/core";
19
+ import * as i4 from "@taiga-ui/kit";
19
20
  /**
20
21
  * Компонент вывода фильтров каталога.
21
22
  */
@@ -25,9 +26,9 @@ export class ScCatalogFiltersComponent {
25
26
  */
26
27
  constructor() {
27
28
  /**
28
- * Состояние открытия accordion.
29
+ * Подписки синхронизации контролов формы (range slider, single-select checkbox).
29
30
  */
30
- this.isOpenAccordion = input(false);
31
+ this.formSyncs = new Subscription();
31
32
  /**
32
33
  * Сервис для работы с фильтрами каталога.
33
34
  */
@@ -45,16 +46,33 @@ export class ScCatalogFiltersComponent {
45
46
  */
46
47
  this.isRecursively = inject(SC_CATALOG_SHOW_PRODUCTS_RECURSIVELY);
47
48
  /**
48
- * {@link Observable} фильтров категории.
49
+ * Показывать ли кнопку «Показать результаты».
49
50
  */
50
- this.filters = toSignal(inject(SC_CATEGORY_INFO).pipe(catchError(() => EMPTY), filter(tuiIsPresent), switchMap((category) => this.catalogFilterService.getFilters$(this.idOrSlugPipe.transform(category), this.isRecursively)), map((filters) => filters.filter((item) => item.type !== 'range' || item.min !== item.max)), tap((filters) => {
51
- this.updateFormControls(filters);
52
- }), share()));
51
+ this.showResultsButton = input(false);
52
+ /**
53
+ * Событие нажатия на кнопку сброса всех фильтров.
54
+ */
55
+ this.resetFilters = output();
56
+ /**
57
+ * Событие нажатия на кнопку показа результатов.
58
+ */
59
+ this.showResults = output();
53
60
  /**
54
61
  * FormGroup для фильтров.
55
62
  */
56
63
  this.form = new FormGroup({});
57
- this.form.valueChanges.pipe(takeUntilDestroyed()).subscribe((filters) => {
64
+ /**
65
+ * {@link Observable} фильтров категории.
66
+ */
67
+ this.filters = toSignal(inject(SC_CATEGORY_INFO).pipe(catchError(() => EMPTY), filter(tuiIsPresent), switchMap((category) => this.catalogFilterService.getFilters$(this.idOrSlugPipe.transform(category), this.isRecursively)), filter(tuiIsPresent), map((filters) => filters
68
+ .filter((item) => item.type !== 'range' || item.min !== item.max)
69
+ .map((item) => (item.type === 'checkbox' ? { ...item, values: [...item.values].sort((a, b) => a.label.localeCompare(b.label)) } : item))), tap((filters) => {
70
+ this.updateFormControls(filters);
71
+ }), share()));
72
+ inject(DestroyRef).onDestroy(() => {
73
+ this.formSyncs.unsubscribe();
74
+ });
75
+ this.form.valueChanges.pipe(debounceTime(0), takeUntilDestroyed()).subscribe((filters) => {
58
76
  this.catalogProductsFilters$.next(this.buildPropertyFilters(filters));
59
77
  });
60
78
  }
@@ -64,17 +82,28 @@ export class ScCatalogFiltersComponent {
64
82
  * @param filters Массив фильтров для создания контролов.
65
83
  */
66
84
  updateFormControls(filters) {
85
+ this.formSyncs.unsubscribe();
86
+ this.formSyncs = new Subscription();
67
87
  Object.keys(this.form.controls).forEach((key) => {
68
88
  this.form.removeControl(key, { emitEvent: false });
69
89
  });
70
90
  filters.forEach((item) => {
71
91
  switch (item.type) {
72
- case 'checkbox':
73
- this.form.addControl(item.id, this.createCheckboxFormControl(item), { emitEvent: false });
92
+ case 'checkbox': {
93
+ const checkboxControl = this.createCheckboxFormControl(item);
94
+ this.form.addControl(item.id, checkboxControl, { emitEvent: false });
95
+ // Single-select для !isMultiple: при выборе одного остальные снимаются.
96
+ if (!item.isMultiple && item.values.length > 1) {
97
+ this.formSyncs.add(this.syncSingleSelectCheckbox(checkboxControl));
98
+ }
74
99
  break;
75
- case 'range':
76
- this.form.addControl(item.id, this.createRangeFormControl(item), { emitEvent: false });
100
+ }
101
+ case 'range': {
102
+ const rangeControl = this.createRangeFormControl(item);
103
+ this.form.addControl(item.id, rangeControl, { emitEvent: false });
104
+ this.formSyncs.add(this.syncRangeFromToAndSlider(rangeControl));
77
105
  break;
106
+ }
78
107
  case 'toggle':
79
108
  this.form.addControl(item.id, this.createToggleFormControl(item), { emitEvent: false });
80
109
  break;
@@ -98,7 +127,7 @@ export class ScCatalogFiltersComponent {
98
127
  }
99
128
  switch (filterItem.type) {
100
129
  case 'checkbox':
101
- this.processCheckboxFilter(result, filterItem.id, controlValue);
130
+ this.processCheckboxFilter(result, filterItem, controlValue);
102
131
  break;
103
132
  case 'range':
104
133
  this.processRangeFilter(result, filterItem.id, controlValue);
@@ -113,31 +142,107 @@ export class ScCatalogFiltersComponent {
113
142
  return result;
114
143
  }
115
144
  /**
116
- * Создает контрол формы для фильтра типа checkbox.
145
+ * Создаёт FormGroup для checkbox: на каждый {@code value.id} — булевый контрол.
117
146
  *
118
- * Если `isMultiple === false` возвращает {@link FormControl} строкового идентификатора (логика radio),
119
- * иначе {@link FormGroup} независимых булевых контролов по идентификаторам значений.
147
+ * Единый формат и для одного, и для множества значений: шаблон рендерит их одинаково.
148
+ * Различие в API-выводе для одиночного значения (boolean вместо массива) обрабатывается в {@link processCheckboxFilter}.
120
149
  *
121
150
  * @param checkboxFilter Фильтр типа checkbox.
122
151
  */
123
152
  createCheckboxFormControl(checkboxFilter) {
124
- if (!checkboxFilter.isMultiple) {
125
- return new FormControl(null);
126
- }
153
+ const isSelected = (id) => checkboxFilter.selectedValues?.includes(id) ?? false;
127
154
  const controls = {};
128
155
  checkboxFilter.values.forEach((value) => {
129
- controls[value.id] = new FormControl(false, { nonNullable: true });
156
+ controls[value.id] = new FormControl(isSelected(value.id), { nonNullable: true });
130
157
  });
131
158
  return new FormGroup(controls);
132
159
  }
133
160
  /**
134
- * Создает FormControl для range.
161
+ * Создаёт {@link FormGroup} для range: {@code from}, {@code to}, {@code slider} (кортеж для {@link TuiRange}).
135
162
  *
136
163
  * @param rangeFilter Фильтр типа range.
137
164
  */
138
165
  createRangeFormControl(rangeFilter) {
139
- // TODO: Добавить updateOn: 'blur' после исправления бага в taiga-ui.
140
- return new FormControl([Number(rangeFilter.selectedMin ?? rangeFilter.min), Number(rangeFilter.selectedMax ?? rangeFilter.max)], { nonNullable: true });
166
+ const fromValue = Number(rangeFilter.selectedMin ?? rangeFilter.min);
167
+ const toValue = Number(rangeFilter.selectedMax ?? rangeFilter.max);
168
+ return new FormGroup({
169
+ from: new FormControl(fromValue, { nonNullable: true }),
170
+ to: new FormControl(toValue, { nonNullable: true }),
171
+ slider: new FormControl([fromValue, toValue], { nonNullable: true }),
172
+ });
173
+ }
174
+ /**
175
+ * Реализует single-select поведение для FormGroup с булевыми контролами:
176
+ * при появлении нового true остальные контролы группы сбрасываются в false.
177
+ *
178
+ * Сохраняет последнее «стабильное» состояние и сравнивает следующее значение с ним —
179
+ * новый true (отсутствовал в prev) считается выбранным, остальные сбрасываются через setValue.
180
+ *
181
+ * @param group FormGroup checkbox-фильтра (id → boolean).
182
+ */
183
+ syncSingleSelectCheckbox(group) {
184
+ let previousState = group.getRawValue();
185
+ return group.valueChanges.subscribe((value) => {
186
+ const current = value;
187
+ const newlyChecked = Object.entries(current).find(([id, isChecked]) => {
188
+ // eslint-disable-next-line security/detect-object-injection
189
+ return isChecked && !previousState[id];
190
+ })?.[0];
191
+ if (!newlyChecked) {
192
+ previousState = { ...current };
193
+ return;
194
+ }
195
+ const next = {};
196
+ Object.keys(group.controls).forEach((id) => {
197
+ // eslint-disable-next-line security/detect-object-injection
198
+ next[id] = id === newlyChecked;
199
+ });
200
+ previousState = next;
201
+ group.setValue(next);
202
+ });
203
+ }
204
+ /**
205
+ * Связывает поля «от»/«до» с контролом слайдера.
206
+ *
207
+ * @param group FormGroup range-фильтра.
208
+ */
209
+ syncRangeFromToAndSlider(group) {
210
+ const from = group.get('from');
211
+ const to = group.get('to');
212
+ const slider = group.get('slider');
213
+ if (!from || !to || !slider) {
214
+ return new Subscription();
215
+ }
216
+ const sub = new Subscription();
217
+ // Инпуты → слайдер; если «от» > «до», поднимаем «до» до «от».
218
+ const applySliderFromInputs = () => {
219
+ const low = Number(from.value);
220
+ let high = Number(to.value);
221
+ if (low > high) {
222
+ high = low;
223
+ to.setValue(high, { emitEvent: false });
224
+ }
225
+ const currentPair = slider.value;
226
+ if (currentPair[0] !== low || currentPair[1] !== high) {
227
+ slider.setValue([low, high], { emitEvent: false });
228
+ slider.markAsDirty();
229
+ }
230
+ };
231
+ sub.add(merge(from.valueChanges, to.valueChanges).subscribe(applySliderFromInputs));
232
+ sub.add(slider.valueChanges.subscribe((value) => {
233
+ const [low, high] = value;
234
+ if (from.value !== low) {
235
+ from.setValue(low, { emitEvent: false });
236
+ from.markAsDirty();
237
+ }
238
+ if (to.value !== high) {
239
+ to.setValue(high, { emitEvent: false });
240
+ to.markAsDirty();
241
+ }
242
+ }));
243
+ // Совпасть с полями при первом показе (уже совпадает при создании, но на всякий случай).
244
+ applySliderFromInputs();
245
+ return sub;
141
246
  }
142
247
  /**
143
248
  * Создает FormControl для toggle.
@@ -148,45 +253,36 @@ export class ScCatalogFiltersComponent {
148
253
  return new FormControl(toggleFilter.selectedValue ?? false, { nonNullable: true });
149
254
  }
150
255
  /**
151
- * Обрабатывает checkbox фильтр.
256
+ * Обрабатывает checkbox: FormGroup → string[] выбранных id; для единственного значения — boolean (как toggle).
152
257
  *
153
258
  * @param result Объект результата для заполнения.
154
- * @param filterId Идентификатор фильтра.
155
- * @param controlValue Значение контрола формы.
259
+ * @param checkboxFilter Метафильтр checkbox.
260
+ * @param controlValue Значение контрола формы (запись id → boolean).
156
261
  */
157
- processCheckboxFilter(result, filterId, controlValue) {
158
- // Для isMultiple === false: FormControl<string | null> -> string[] из одного выбранного ID.
159
- if (typeof controlValue === 'string') {
160
- if (controlValue) {
161
- // eslint-disable-next-line security/detect-object-injection, no-param-reassign
162
- result[filterId] = [controlValue];
163
- }
164
- return;
165
- }
166
- // Для checkbox: FormGroup с FormControl<boolean> -> string[] (массив ID выбранных значений).
262
+ processCheckboxFilter(result, checkboxFilter, controlValue) {
167
263
  const selectedIds = Object.entries(controlValue)
168
264
  .filter(([, isSelected]) => isSelected)
169
265
  .map(([id]) => id);
170
- if (selectedIds.length > 0) {
171
- // eslint-disable-next-line security/detect-object-injection, no-param-reassign
172
- result[filterId] = selectedIds;
266
+ if (selectedIds.length === 0) {
267
+ return;
173
268
  }
269
+ // eslint-disable-next-line security/detect-object-injection, no-param-reassign
270
+ result[checkboxFilter.id] = selectedIds;
174
271
  }
175
272
  /**
176
273
  * Обрабатывает range фильтр.
177
274
  *
178
275
  * @param result Объект результата для заполнения.
179
276
  * @param filterId Идентификатор фильтра.
180
- * @param controlValue Значение контрола формы.
181
- * @param controlValue.0 Начальное значение диапазона.
182
- * @param controlValue.1 Конечное значение диапазона.
277
+ * @param range Значение контрола формы (объект с границами).
278
+ * @param range.from Начальное значение диапазона.
279
+ * @param range.to Конечное значение диапазона.
183
280
  */
184
- processRangeFilter(result, filterId, [from, to]) {
185
- // Для range: FormControl<[number, number]> -> { from?: string; to?: string; }
281
+ processRangeFilter(result, filterId, range) {
186
282
  // eslint-disable-next-line security/detect-object-injection, no-param-reassign
187
283
  result[filterId] = {
188
- from: String(from),
189
- to: String(to),
284
+ from: String(range.from),
285
+ to: String(range.to),
190
286
  };
191
287
  }
192
288
  /**
@@ -197,17 +293,110 @@ export class ScCatalogFiltersComponent {
197
293
  * @param controlValue Значение контрола формы.
198
294
  */
199
295
  processToggleFilter(result, filterId, controlValue) {
200
- // Для toggle: FormControl<boolean> -> boolean
201
296
  if (controlValue) {
202
297
  // eslint-disable-next-line security/detect-object-injection, no-param-reassign
203
298
  result[filterId] = controlValue;
204
299
  }
205
300
  }
301
+ /**
302
+ * Сбрасывает поле «от» диапазона к минимальному значению фильтра.
303
+ *
304
+ * @param filterId Идентификатор фильтра.
305
+ * @param min Минимальное значение диапазона.
306
+ */
307
+ resetRangeFrom(filterId, min) {
308
+ this.form.get(filterId)?.get('from')?.reset(+min);
309
+ }
310
+ /**
311
+ * Сбрасывает поле «до» диапазона к максимальному значению фильтра.
312
+ *
313
+ * @param filterId Идентификатор фильтра.
314
+ * @param max Максимальное значение диапазона.
315
+ */
316
+ resetRangeTo(filterId, max) {
317
+ this.form.get(filterId)?.get('to')?.reset(+max);
318
+ }
319
+ /**
320
+ * Сбрасывает все чекбоксы группы в `false`.
321
+ *
322
+ * @param filterId Идентификатор фильтра (ключ FormGroup в форме).
323
+ */
324
+ resetCheckboxGroup(filterId) {
325
+ const group = this.form.get(filterId);
326
+ if (!group) {
327
+ return;
328
+ }
329
+ const resetValue = {};
330
+ Object.keys(group.controls).forEach((id) => {
331
+ // eslint-disable-next-line security/detect-object-injection
332
+ resetValue[id] = false;
333
+ });
334
+ group.reset(resetValue);
335
+ }
336
+ /**
337
+ * Сбрасывает все фильтры и оповещает родителя о нажатии кнопки сброса.
338
+ */
339
+ onResetFiltersClick() {
340
+ this.resetAllFilters();
341
+ this.resetFilters.emit();
342
+ }
343
+ /**
344
+ * Оповещает родителя о нажатии кнопки показа результатов.
345
+ */
346
+ onShowResultsClick() {
347
+ this.showResults.emit();
348
+ }
349
+ /**
350
+ * Сбрасывает все фильтры к исходным значениям.
351
+ */
352
+ resetAllFilters() {
353
+ this.filters()?.forEach((filterItem) => {
354
+ const control = this.form.get(filterItem.id);
355
+ if (!control) {
356
+ return;
357
+ }
358
+ switch (filterItem.type) {
359
+ case 'checkbox': {
360
+ const group = control;
361
+ const resetValue = {};
362
+ Object.keys(group.controls).forEach((id) => {
363
+ // eslint-disable-next-line security/detect-object-injection
364
+ resetValue[id] = false;
365
+ });
366
+ group.reset(resetValue);
367
+ break;
368
+ }
369
+ case 'toggle':
370
+ control.reset(false);
371
+ break;
372
+ case 'range': {
373
+ const group = control;
374
+ const min = +filterItem.min;
375
+ const max = +filterItem.max;
376
+ group.reset({ from: min, to: max, slider: [min, max] });
377
+ break;
378
+ }
379
+ default:
380
+ break;
381
+ }
382
+ });
383
+ }
206
384
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFiltersComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
207
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScCatalogFiltersComponent, isStandalone: true, selector: "sc-catalog-filters", inputs: { isOpenAccordion: { classPropertyName: "isOpenAccordion", publicName: "isOpenAccordion", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "@if (filters()?.length) {\n <div class=\"bg-tui-base-01 shadow-sc flex flex-col items-center gap-3 rounded-xl\">\n <tui-accordion class=\"accordion\">\n <button\n [tuiAccordion]=\"isOpenAccordion()\"\n appearance=\"primary\"\n >\n \u0424\u0438\u043B\u044C\u0442\u0440\u044B\n </button>\n <tui-expand>\n <form\n [formGroup]=\"form\"\n class=\"flex flex-col gap-4 pb-1\"\n >\n @for (filter of filters(); track filter.id) {\n <div class=\"flex flex-col gap-2\">\n <label class=\"text-body-s font-medium\">{{ filter.label }}</label>\n\n @if (filter.type === 'checkbox') {\n @if (filter.isMultiple === false) {\n <div class=\"flex flex-col gap-2\">\n @for (value of filter.values; track value.id) {\n @let formControl = form.get(filter.id);\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n [value]=\"value.id\"\n tuiRadio\n (click)=\"formControl?.setValue(formControl?.value === value.id ? null : value.id)\"\n type=\"radio\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n } @else {\n <div\n [formGroupName]=\"filter.id\"\n class=\"flex flex-col gap-2\"\n >\n @for (value of filter.values; track value.id) {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"value.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n }\n }\n\n @if (filter.type === 'range') {\n <tui-input-range\n [formControlName]=\"filter.id\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n />\n }\n\n @if (filter.type === 'toggle') {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">\u0414\u0430</span>\n </label>\n }\n </div>\n }\n </form>\n </tui-expand>\n </tui-accordion>\n </div>\n}\n", styles: [".accordion [tuiAccordion]{border:none;mask:none}.accordion tui-expand{box-shadow:none}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: TuiCheckbox, selector: "input[type=\"checkbox\"][tuiCheckbox]", inputs: ["size"] }, { kind: "component", type: i2.TuiRadioComponent, selector: "input[type=\"radio\"][tuiRadio]", inputs: ["size"] }, { kind: "component", type: i2.TuiInputRangeComponent, selector: "tui-input-range", inputs: ["min", "max", "step", "segments", "keySteps", "prefix", "postfix", "quantum", "content"] }, { kind: "component", type: i3.TuiAccordionComponent, selector: "tui-accordion", inputs: ["closeOthers", "size"] }, { kind: "directive", type: i3.TuiAccordionDirective, selector: "button[tuiAccordion]", inputs: ["tuiAccordion"], outputs: ["tuiAccordionChange"] }, { kind: "component", type: i4.TuiExpand, selector: "tui-expand", inputs: ["expanded"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
385
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScCatalogFiltersComponent, isStandalone: true, selector: "sc-catalog-filters", inputs: { showResultsButton: { classPropertyName: "showResultsButton", publicName: "showResultsButton", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resetFilters: "resetFilters", showResults: "showResults" }, ngImport: i0, template: "@if (filters()?.length) {\n <form\n [formGroup]=\"form\"\n class=\"flex flex-col pb-1\"\n >\n @for (filter of filters(); track filter.id; let isFirst = $first) {\n @if (!isFirst) {\n <hr class=\"my-3 w-full h-px\" />\n }\n\n <div class=\"flex flex-col gap-2\">\n <!-- \u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0433\u0440\u0443\u043F\u043F\u044B. \u0414\u043B\u044F toggle \u043F\u043E\u0434\u043F\u0438\u0441\u0438 \u043D\u0435\u0442: \u043C\u0435\u0442\u043A\u0430 \u0438\u0434\u0451\u0442 \u043F\u0440\u044F\u043C\u043E \u0440\u044F\u0434\u043E\u043C \u0441 \u0441\u0430\u043C\u0438\u043C checkbox. -->\n @if (filter.type !== 'toggle') {\n <label class=\"text-body-s-bold\">{{ filter.label }}</label>\n }\n\n <!-- Checkbox: FormGroup(value.id \u2192 boolean) \u0434\u043B\u044F \u043B\u044E\u0431\u043E\u0433\u043E \u0447\u0438\u0441\u043B\u0430 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439.\n \u0420\u0430\u0437\u0432\u0438\u043B\u043A\u0430 \u043E\u0434\u043D\u043E/\u043C\u043D\u043E\u0433\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0432\u044B\u043D\u0435\u0441\u0435\u043D\u0430 \u0432 TS (\u0441\u043C. processCheckboxFilter).\n ng-template \u0432\u043D\u0443\u0442\u0440\u0438 formGroupName: \u0438\u043D\u0430\u0447\u0435 reactive forms \u043D\u0435 \u043D\u0430\u0439\u0434\u0451\u0442 ControlContainer \u043F\u0440\u0438 \u043F\u0440\u043E\u0435\u043A\u0446\u0438\u0438 \u0432 \u0434\u043E\u0447\u0435\u0440\u043D\u0438\u0439 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442. -->\n @if (filter.type === 'checkbox') {\n <div\n class=\"flex flex-col gap-2\"\n [formGroupName]=\"filter.id\"\n >\n <sc-catalog-filter-collapsible\n [itemsCount]=\"filter.values.length\"\n [showReset]=\"form.get(filter.id)?.dirty ?? false\"\n (resetGroup)=\"resetCheckboxGroup(filter.id)\"\n >\n <ng-template>\n <div class=\"flex flex-col gap-2\">\n @for (value of filter.values; track value.id) {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"value.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n </ng-template>\n </sc-catalog-filter-collapsible>\n </div>\n\n <!-- Toggle: \u043E\u0434\u0438\u043D boolean \u043D\u0430 \u043A\u043E\u0440\u043D\u0435 \u0444\u043E\u0440\u043C\u044B, \u043F\u043E\u0434\u043F\u0438\u0441\u044C = filter.label -->\n } @else if (filter.type === 'toggle') {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s-bold\">{{ filter.label }}</span>\n </label>\n\n <!-- Range: FormGroup(from, to, slider) \u0441 \u0434\u0432\u0443\u0441\u0442\u043E\u0440\u043E\u043D\u043D\u0435\u0439 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u0435\u0439 -->\n } @else if (filter.type === 'range') {\n <div\n [formGroupName]=\"filter.id\"\n class=\"flex flex-col gap-3\"\n >\n <div class=\"flex gap-3 px-1\">\n <label\n tuiLabel\n class=\"min-w-0 flex-1\"\n >\n \u041E\u0442\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n scSelectOnFocusin\n tuiInputNumber\n formControlName=\"from\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n autocomplete=\"off\"\n />\n @if (form.get(filter.id)?.get('from')?.dirty) {\n <button\n tuiIconButton\n type=\"button\"\n size=\"xs\"\n appearance=\"icon\"\n iconStart=\"@tui.x\"\n (click)=\"resetRangeFrom(filter.id, filter.min)\"\n ></button>\n }\n </tui-textfield>\n </label>\n <label\n tuiLabel\n class=\"min-w-0 flex-1\"\n >\n \u0414\u043E\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n scSelectOnFocusin\n tuiInputNumber\n formControlName=\"to\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n autocomplete=\"off\"\n />\n @if (form.get(filter.id)?.get('to')?.dirty) {\n <button\n tuiIconButton\n type=\"button\"\n size=\"xs\"\n appearance=\"icon\"\n iconStart=\"@tui.x\"\n (click)=\"resetRangeTo(filter.id, filter.max)\"\n ></button>\n }\n </tui-textfield>\n </label>\n </div>\n\n <tui-range\n size=\"m\"\n formControlName=\"slider\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n [style.--tui-thickness.rem]=\"0.25\"\n />\n </div>\n }\n </div>\n }\n <button\n tuiButton\n appearance=\"secondary\"\n type=\"button\"\n class=\"mt-2\"\n (click)=\"onResetFiltersClick()\"\n >\n \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0444\u0438\u043B\u044C\u0442\u0440\u044B\n </button>\n @if (showResultsButton()) {\n <button\n tuiButton\n appearance=\"primary\"\n type=\"button\"\n class=\"mt-2\"\n (click)=\"onShowResultsClick()\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B\n </button>\n }\n </form>\n}\n", styles: [".accordion [tuiAccordion]{border:none;mask:none}.accordion tui-expand{box-shadow:none}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "directive", type: i2.TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: i3.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i3.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: ScSelectOnFocusinDirective, selector: "tui-input-number, tui-input, tui-input-phone, tui-input-date, tui-input-password, input[tuiInputNumber], input[tuiTextfield], input[tuiInputSlider]" }, { kind: "component", type: ScCatalogFilterCollapsibleComponent, selector: "sc-catalog-filter-collapsible", inputs: ["itemsCount", "showReset"], outputs: ["resetGroup"] }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "component", type: TuiCheckbox, selector: "input[type=\"checkbox\"][tuiCheckbox]", inputs: ["size"] }, { kind: "directive", type: i4.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "component", type: TuiRange, selector: "tui-range", inputs: ["min", "max", "step", "size", "segments", "keySteps", "focusable", "margin", "limit"] }, { kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
208
386
  }
209
387
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFiltersComponent, decorators: [{
210
388
  type: Component,
211
- args: [{ standalone: true, selector: 'sc-catalog-filters', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, TuiTextfield, TuiCheckbox, TuiRadio, TuiInputRange, TuiAccordion, ReactiveFormsModule], template: "@if (filters()?.length) {\n <div class=\"bg-tui-base-01 shadow-sc flex flex-col items-center gap-3 rounded-xl\">\n <tui-accordion class=\"accordion\">\n <button\n [tuiAccordion]=\"isOpenAccordion()\"\n appearance=\"primary\"\n >\n \u0424\u0438\u043B\u044C\u0442\u0440\u044B\n </button>\n <tui-expand>\n <form\n [formGroup]=\"form\"\n class=\"flex flex-col gap-4 pb-1\"\n >\n @for (filter of filters(); track filter.id) {\n <div class=\"flex flex-col gap-2\">\n <label class=\"text-body-s font-medium\">{{ filter.label }}</label>\n\n @if (filter.type === 'checkbox') {\n @if (filter.isMultiple === false) {\n <div class=\"flex flex-col gap-2\">\n @for (value of filter.values; track value.id) {\n @let formControl = form.get(filter.id);\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n [value]=\"value.id\"\n tuiRadio\n (click)=\"formControl?.setValue(formControl?.value === value.id ? null : value.id)\"\n type=\"radio\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n } @else {\n <div\n [formGroupName]=\"filter.id\"\n class=\"flex flex-col gap-2\"\n >\n @for (value of filter.values; track value.id) {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"value.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n }\n }\n\n @if (filter.type === 'range') {\n <tui-input-range\n [formControlName]=\"filter.id\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n />\n }\n\n @if (filter.type === 'toggle') {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">\u0414\u0430</span>\n </label>\n }\n </div>\n }\n </form>\n </tui-expand>\n </tui-accordion>\n </div>\n}\n", styles: [".accordion [tuiAccordion]{border:none;mask:none}.accordion tui-expand{box-shadow:none}\n"] }]
389
+ args: [{ standalone: true, selector: 'sc-catalog-filters', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
390
+ ReactiveFormsModule,
391
+ TuiTextfield,
392
+ ScSelectOnFocusinDirective,
393
+ ScCatalogFilterCollapsibleComponent,
394
+ TuiLabel,
395
+ TuiNumberFormat,
396
+ TuiCheckbox,
397
+ TuiInputNumber,
398
+ TuiRange,
399
+ TuiButton,
400
+ ], template: "@if (filters()?.length) {\n <form\n [formGroup]=\"form\"\n class=\"flex flex-col pb-1\"\n >\n @for (filter of filters(); track filter.id; let isFirst = $first) {\n @if (!isFirst) {\n <hr class=\"my-3 w-full h-px\" />\n }\n\n <div class=\"flex flex-col gap-2\">\n <!-- \u0417\u0430\u0433\u043E\u043B\u043E\u0432\u043E\u043A \u0433\u0440\u0443\u043F\u043F\u044B. \u0414\u043B\u044F toggle \u043F\u043E\u0434\u043F\u0438\u0441\u0438 \u043D\u0435\u0442: \u043C\u0435\u0442\u043A\u0430 \u0438\u0434\u0451\u0442 \u043F\u0440\u044F\u043C\u043E \u0440\u044F\u0434\u043E\u043C \u0441 \u0441\u0430\u043C\u0438\u043C checkbox. -->\n @if (filter.type !== 'toggle') {\n <label class=\"text-body-s-bold\">{{ filter.label }}</label>\n }\n\n <!-- Checkbox: FormGroup(value.id \u2192 boolean) \u0434\u043B\u044F \u043B\u044E\u0431\u043E\u0433\u043E \u0447\u0438\u0441\u043B\u0430 \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439.\n \u0420\u0430\u0437\u0432\u0438\u043B\u043A\u0430 \u043E\u0434\u043D\u043E/\u043C\u043D\u043E\u0433\u043E \u0437\u043D\u0430\u0447\u0435\u043D\u0438\u0439 \u0432\u044B\u043D\u0435\u0441\u0435\u043D\u0430 \u0432 TS (\u0441\u043C. processCheckboxFilter).\n ng-template \u0432\u043D\u0443\u0442\u0440\u0438 formGroupName: \u0438\u043D\u0430\u0447\u0435 reactive forms \u043D\u0435 \u043D\u0430\u0439\u0434\u0451\u0442 ControlContainer \u043F\u0440\u0438 \u043F\u0440\u043E\u0435\u043A\u0446\u0438\u0438 \u0432 \u0434\u043E\u0447\u0435\u0440\u043D\u0438\u0439 \u043A\u043E\u043C\u043F\u043E\u043D\u0435\u043D\u0442. -->\n @if (filter.type === 'checkbox') {\n <div\n class=\"flex flex-col gap-2\"\n [formGroupName]=\"filter.id\"\n >\n <sc-catalog-filter-collapsible\n [itemsCount]=\"filter.values.length\"\n [showReset]=\"form.get(filter.id)?.dirty ?? false\"\n (resetGroup)=\"resetCheckboxGroup(filter.id)\"\n >\n <ng-template>\n <div class=\"flex flex-col gap-2\">\n @for (value of filter.values; track value.id) {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"value.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s\">{{ value.label }}</span>\n </label>\n }\n </div>\n </ng-template>\n </sc-catalog-filter-collapsible>\n </div>\n\n <!-- Toggle: \u043E\u0434\u0438\u043D boolean \u043D\u0430 \u043A\u043E\u0440\u043D\u0435 \u0444\u043E\u0440\u043C\u044B, \u043F\u043E\u0434\u043F\u0438\u0441\u044C = filter.label -->\n } @else if (filter.type === 'toggle') {\n <label class=\"flex items-center gap-2\">\n <input\n [formControlName]=\"filter.id\"\n tuiCheckbox\n type=\"checkbox\"\n />\n <span class=\"text-body-s-bold\">{{ filter.label }}</span>\n </label>\n\n <!-- Range: FormGroup(from, to, slider) \u0441 \u0434\u0432\u0443\u0441\u0442\u043E\u0440\u043E\u043D\u043D\u0435\u0439 \u0441\u0438\u043D\u0445\u0440\u043E\u043D\u0438\u0437\u0430\u0446\u0438\u0435\u0439 -->\n } @else if (filter.type === 'range') {\n <div\n [formGroupName]=\"filter.id\"\n class=\"flex flex-col gap-3\"\n >\n <div class=\"flex gap-3 px-1\">\n <label\n tuiLabel\n class=\"min-w-0 flex-1\"\n >\n \u041E\u0442\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n scSelectOnFocusin\n tuiInputNumber\n formControlName=\"from\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n autocomplete=\"off\"\n />\n @if (form.get(filter.id)?.get('from')?.dirty) {\n <button\n tuiIconButton\n type=\"button\"\n size=\"xs\"\n appearance=\"icon\"\n iconStart=\"@tui.x\"\n (click)=\"resetRangeFrom(filter.id, filter.min)\"\n ></button>\n }\n </tui-textfield>\n </label>\n <label\n tuiLabel\n class=\"min-w-0 flex-1\"\n >\n \u0414\u043E\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n scSelectOnFocusin\n tuiInputNumber\n formControlName=\"to\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n autocomplete=\"off\"\n />\n @if (form.get(filter.id)?.get('to')?.dirty) {\n <button\n tuiIconButton\n type=\"button\"\n size=\"xs\"\n appearance=\"icon\"\n iconStart=\"@tui.x\"\n (click)=\"resetRangeTo(filter.id, filter.max)\"\n ></button>\n }\n </tui-textfield>\n </label>\n </div>\n\n <tui-range\n size=\"m\"\n formControlName=\"slider\"\n [min]=\"+filter.min\"\n [max]=\"+filter.max\"\n [style.--tui-thickness.rem]=\"0.25\"\n />\n </div>\n }\n </div>\n }\n <button\n tuiButton\n appearance=\"secondary\"\n type=\"button\"\n class=\"mt-2\"\n (click)=\"onResetFiltersClick()\"\n >\n \u0421\u0431\u0440\u043E\u0441\u0438\u0442\u044C \u0444\u0438\u043B\u044C\u0442\u0440\u044B\n </button>\n @if (showResultsButton()) {\n <button\n tuiButton\n appearance=\"primary\"\n type=\"button\"\n class=\"mt-2\"\n (click)=\"onShowResultsClick()\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0440\u0435\u0437\u0443\u043B\u044C\u0442\u0430\u0442\u044B\n </button>\n }\n </form>\n}\n", styles: [".accordion [tuiAccordion]{border:none;mask:none}.accordion tui-expand{box-shadow:none}\n"] }]
212
401
  }], ctorParameters: () => [] });
213
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2MtY2F0YWxvZy1maWx0ZXJzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NsaWVudC11aS9jYXRhbG9nL2NhdGFsb2ctZmlsdGVycy9zYy1jYXRhbG9nLWZpbHRlcnMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NhdGFsb2cvY2F0YWxvZy1maWx0ZXJzL3NjLWNhdGFsb2ctZmlsdGVycy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFFM0MsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2xGLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxRQUFRLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUMxRSxPQUFPLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxXQUFXLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUMxRixPQUFPLEVBQ0gsZ0JBQWdCLEVBRWhCLHNCQUFzQixFQUV0QixjQUFjLEdBSWpCLE1BQU0sd0JBQXdCLENBQUM7QUFDaEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDOUMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3RELE9BQU8sRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNyRSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLEVBQUUsTUFBTSxNQUFN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eUJBQXlCO21HQUF6Qix5QkFBeUIsZ1BDcEN0Qywra0lBK0VBLGlKRDdDYyxXQUFXLGdpQ0FBZ0IsV0FBVyw2dUJBQXlDLG1CQUFtQjs7NEZBRW5HLHlCQUF5QjtrQkFSckMsU0FBUztpQ0FDTSxJQUFJLFlBQ04sb0JBQW9CLG1CQUdiLHVCQUF1QixDQUFDLE1BQU0sV0FDdEMsQ0FBQyxXQUFXLEVBQUUsWUFBWSxFQUFFLFdBQVcsRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLFlBQVksRUFBRSxtQkFBbUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXMgKi9cblxuaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgaW5qZWN0LCBpbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkLCB0b1NpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIEZvcm1zTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtcbiAgICBTQ19DQVRFR09SWV9JTkZPLFxuICAgIFNjQ2F0YWxvZ0ZpbHRlcixcbiAgICBTY0NhdGFsb2dGaWx0ZXJTZXJ2aWNlLFxuICAgIFNjSUNoZWNrYm94RmlsdGVyLFxuICAgIFNjSWRPclNsdWdQaXBlLFxuICAgIFNjUHJvcGVydHlGaWx0ZXJzLFxuICAgIFNjUmFuZ2VGaWx0ZXIsXG4gICAgU2NUb2dnbGVGaWx0ZXIsXG59IGZyb20gJ0BzbmFiY2VudHIvY2xpZW50LWNvcmUnO1xuaW1wb3J0IHsgdHVpSXNQcmVzZW50IH0gZnJvbSAnQHRhaWdhLXVpL2Nkayc7XG5pbXBvcnQgeyBUdWlUZXh0ZmllbGQgfSBmcm9tICdAdGFpZ2EtdWkvY29yZSc7XG5pbXBvcnQgeyBUdWlBY2NvcmRpb24gfSBmcm9tICdAdGFpZ2EtdWkvZXhwZXJpbWVudGFsJztcbmltcG9ydCB7IFR1aUNoZWNrYm94LCBUdWlJbnB1dFJhbmdlLCBUdWlSYWRpbyB9IGZyb20gJ0B0YWlnYS11aS9raXQnO1xuaW1wb3J0IHsgaXNOaWwgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgRU1QVFksIGZpbHRlciwgbWFwLCBzaGFyZSwgc3dpdGNoTWFwLCB0YXAgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgU0NfQ0FUQUxPR19QUk9EVUNUU19GSUxURVJTIH0gZnJvbSAnLi90b2tlbnMvc2MtY2F0YWxvZy1wcm9kdWN0cy1maWx0ZXJzJztcbmltcG9ydCB7IFNDX0NBVEFMT0dfU0hPV19QUk9EVUNUU19SRUNVUlNJVkVMWSB9IGZyb20gJy4vdG9rZW5zL3NjLWNhdGFsb2ctc2hvdy1wcm9kdWN0cy1yZWN1cnNpdmVseSc7XG5cbi8qKlxuICog0JrQvtC80L/QvtC90LXQvdGCINCy0YvQstC+0LTQsCDRhNC40LvRjNGC0YDQvtCyINC60LDRgtCw0LvQvtCz0LAuXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc2VsZWN0b3I6ICdzYy1jYXRhbG9nLWZpbHRlcnMnLFxuICAgIHN0eWxlVXJsOiAnLi9zYy1jYXRhbG9nLWZpbHRlcnMuY29tcG9uZW50LnNjc3MnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9zYy1jYXRhbG9nLWZpbHRlcnMuY29tcG9uZW50Lmh0bWwnLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgIGltcG9ydHM6IFtGb3Jtc01vZHVsZSwgVHVpVGV4dGZpZWxkLCBUdWlDaGVja2JveCwgVHVpUmFkaW8sIFR1aUlucHV0UmFuZ2UsIFR1aUFjY29yZGlvbiwgUmVhY3RpdmVGb3Jtc01vZHVsZV0sXG59KVxuZXhwb3J0IGNsYXNzIFNjQ2F0YWxvZ0ZpbHRlcnNDb21wb25lbnQge1xuICAgIC8qKlxuICAgICAqINCh0L7RgdGC0L7Rj9C90LjQtSDQvtGC0LrRgNGL0YLQuNGPIGFjY29yZGlvbi5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgaXNPcGVuQWNjb3JkaW9uID0gaW5wdXQ8Ym9vbGVhbj4oZmFsc2UpO1xuXG4gICAgLyoqXG4gICAgICog0KHQtdGA0LLQuNGBINC00LvRjyDRgNCw0LHQvtGC0Ysg0YEg0YTQuNC70YzRgtGA0LDQvNC4INC60LDRgtCw0LvQvtCz0LAuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBjYXRhbG9nRmlsdGVyU2VydmljZTogU2NDYXRhbG9nRmlsdGVyU2VydmljZSA9IGluamVjdChTY0NhdGFsb2dGaWx0ZXJTZXJ2aWNlKTtcblxuICAgIC8qKlxuICAgICAqINCf0LDQudC/LCDQstC+0LfQstGA0LDRidCw0Y7RidC40Lkg0LjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0LjQu9C4INGB0LjQvNCy0L7Qu9GM0L3QvtC1INC+0LHQvtC30L3QsNGH0LXQvdC40LUgKHNsdWcpINC40YHRhdC+0LTRjyDQuNC3INC90LDRgdGC0YDQvtC10Log0L7QutGA0YPQttC10L3QuNGPLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaWRPclNsdWdQaXBlOiBTY0lkT3JTbHVnUGlwZSA9IGluamVjdChTY0lkT3JTbHVnUGlwZSk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJqZWN0INC00LvRjyDRhdGA0LDQvdC10L3QuNGPINGE0LjQu9GM0YLRgNC+0LIg0L/RgNC+0LTRg9C60YLQvtCyLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY2F0YWxvZ1Byb2R1Y3RzRmlsdGVycyQgPSBpbmplY3QoU0NfQ0FUQUxPR19QUk9EVUNUU19GSUxURVJTKTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC30L3QsNC6INC90LXQvtCx0YXQvtC00LjQvNC+0YHRgtC4INC+0YLQvtCx0YDQsNC20LDRgtGMINGE0LjQu9GM0YLRgNGLINC00LvRjyDQstC70L7QttC10L3QvdGL0YUg0LrQsNGC0LXQs9C+0YDQuNC5LlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaXNSZWN1cnNpdmVseSA9IGluamVjdChTQ19DQVRBTE9HX1NIT1dfUFJPRFVDVFNfUkVDVVJTSVZFTFkpO1xuXG4gICAgLyoqXG4gICAgICoge0BsaW5rIE9ic2VydmFibGV9INGE0LjQu9GM0YLRgNC+0LIg0LrQsNGC0LXQs9C+0YDQuNC4LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBmaWx0ZXJzID0gdG9TaWduYWwoXG4gICAgICAgIGluamVjdChTQ19DQVRFR09SWV9JTkZPKS5waXBlKFxuICAgICAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiBFTVBUWSksXG4gICAgICAgICAgICBmaWx0ZXIodHVpSXNQcmVzZW50KSxcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoY2F0ZWdvcnkpID0+IHRoaXMuY2F0YWxvZ0ZpbHRlclNlcnZpY2UuZ2V0RmlsdGVycyQodGhpcy5pZE9yU2x1Z1BpcGUudHJhbnNmb3JtKGNhdGVnb3J5KSwgdGhpcy5pc1JlY3Vyc2l2ZWx5KSksXG4gICAgICAgICAgICBtYXAoKGZpbHRlcnMpID0+IGZpbHRlcnMuZmlsdGVyKChpdGVtKSA9PiBpdGVtLnR5cGUgIT09ICdyYW5nZScgfHwgaXRlbS5taW4gIT09IGl0ZW0ubWF4KSksXG4gICAgICAgICAgICB0YXAoKGZpbHRlcnMpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZUZvcm1Db250cm9scyhmaWx0ZXJzKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgc2hhcmUoKVxuICAgICAgICApXG4gICAgKTtcblxuICAgIC8qKlxuICAgICAqIEZvcm1Hcm91cCDQtNC70Y8g0YTQuNC70YzRgtGA0L7Qsi5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZm9ybSA9IG5ldyBGb3JtR3JvdXA8XG4gICAgICAgIFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIHRoaXMuY3JlYXRlQ2hlY2tib3hGb3JtQ29udHJvbD4gfCBSZXR1cm5UeXBlPHR5cGVvZiB0aGlzLmNyZWF0ZVJhbmdlRm9ybUNvbnRyb2w+IHwgUmV0dXJuVHlwZTx0eXBlb2YgdGhpcy5jcmVhdGVUb2dnbGVGb3JtQ29udHJvbD4+XG4gICAgPih7fSk7XG5cbiAgICAvKipcbiAgICAgKiDQmNC90LjRhtC40LDQu9C40LfQuNGA0YPQtdGCINGN0LrQt9C10LzQv9C70Y/RgCDQutC70LDRgdGB0LAge0BsaW5rIFNjQ2F0YWxvZ0ZpbHRlcnNDb21wb25lbnR9LlxuICAgICAqL1xuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpcy5mb3JtLnZhbHVlQ2hhbmdlcy5waXBlKHRha2VVbnRpbERlc3Ryb3llZCgpKS5zdWJzY3JpYmUoKGZpbHRlcnMpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2F0YWxvZ1Byb2R1Y3RzRmlsdGVycyQubmV4dCh0aGlzLmJ1aWxkUHJvcGVydHlGaWx0ZXJzKGZpbHRlcnMpKTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J7QsdC90L7QstC70Y/QtdGCINGB0L7RgdGC0LDQsiDQutC+0L3RgtGA0L7Qu9C+0LIg0YTQvtGA0LzRiyDQvdCwINC+0YHQvdC+0LLQtSDQv9C10YDQtdC00LDQvdC90YvRhSDRhNC40LvRjNGC0YDQvtCyLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZpbHRlcnMg0JzQsNGB0YHQuNCyINGE0LjQu9GM0YLRgNC+0LIg0LTQu9GPINGB0L7Qt9C00LDQvdC40Y8g0LrQvtC90YLRgNC+0LvQvtCyLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCB1cGRhdGVGb3JtQ29udHJvbHMoZmlsdGVyczogU2NDYXRhbG9nRmlsdGVyW10pOiB2b2lkIHtcbiAgICAgICAgT2JqZWN0LmtleXModGhpcy5mb3JtLmNvbnRyb2xzKS5mb3JFYWNoKChrZXk6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgdGhpcy5mb3JtLnJlbW92ZUNvbnRyb2woa2V5IGFzIG5ldmVyLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGZpbHRlcnMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgc3dpdGNoIChpdGVtLnR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjaGVja2JveCc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5hZGRDb250cm9sKGl0ZW0uaWQsIHRoaXMuY3JlYXRlQ2hlY2tib3hGb3JtQ29udHJvbChpdGVtKSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdyYW5nZSc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5hZGRDb250cm9sKGl0ZW0uaWQsIHRoaXMuY3JlYXRlUmFuZ2VGb3JtQ29udHJvbChpdGVtKSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGUnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uYWRkQ29udHJvbChpdGVtLmlkLCB0aGlzLmNyZWF0ZVRvZ2dsZUZvcm1Db250cm9sKGl0ZW0pLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQn9GA0LXQvtCx0YDQsNC30YPQtdGCINC30L3QsNGH0LXQvdC40Y8g0YTQvtGA0LzRiyDQsiDQvtCx0YrQtdC60YIg0YTQuNC70YzRgtGA0L7QsiDRgdCy0L7QudGB0YLQsi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB2YWx1ZSDQl9C90LDRh9C10L3QuNGPINGE0L7RgNC80YsuXG4gICAgICogQHJldHVybnMg0J7QsdGK0LXQutGCINGE0LjQu9GM0YLRgNC+0LIg0YHQstC+0LnRgdGC0LIuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGJ1aWxkUHJvcGVydHlGaWx0ZXJzKHZhbHVlOiBQYXJ0aWFsPFJlY29yZDxzdHJpbmcsIGJvb2xlYW4gfCBzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiB8IFtudW1iZXIsIG51bWJlcl0+PiB8IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogU2NQcm9wZXJ0eUZpbHRlcnMge1xuICAgICAgICBjb25zdCByZXN1bHQ6IFNjUHJvcGVydHlGaWx0ZXJzID0ge307XG5cbiAgICAgICAgdGhpcy5maWx0ZXJzKCk/LmZvckVhY2goKGZpbHRlckl0ZW0pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNvbnRyb2xWYWx1ZSA9IHZhbHVlW2ZpbHRlckl0ZW0uaWRdIGFzIGJvb2xlYW4gfCBzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiB8IFtudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgIGlmIChpc05pbChjb250cm9sVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzd2l0Y2ggKGZpbHRlckl0ZW0udHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNrYm94JzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzQ2hlY2tib3hGaWx0ZXIocmVzdWx0LCBmaWx0ZXJJdGVtLmlkLCBjb250cm9sVmFsdWUgYXMgc3RyaW5nIHwgUmVjb3JkPHN0cmluZywgYm9vbGVhbj4pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdyYW5nZSc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1JhbmdlRmlsdGVyKHJlc3VsdCwgZmlsdGVySXRlbS5pZCwgY29udHJvbFZhbHVlIGFzIFtudW1iZXIsIG51bWJlcl0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGUnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NUb2dnbGVGaWx0ZXIocmVzdWx0LCBmaWx0ZXJJdGVtLmlkLCBjb250cm9sVmFsdWUgYXMgYm9vbGVhbik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCh0L7Qt9C00LDQtdGCINC60L7QvdGC0YDQvtC7INGE0L7RgNC80Ysg0LTQu9GPINGE0LjQu9GM0YLRgNCwINGC0LjQv9CwIGNoZWNrYm94LlxuICAgICAqXG4gICAgICog0JXRgdC70LggYGlzTXVsdGlwbGUgPT09IGZhbHNlYCDigJQg0LLQvtC30LLRgNCw0YnQsNC10YIge0BsaW5rIEZvcm1Db250cm9sfSDRgdGC0YDQvtC60L7QstC+0LPQviDQuNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgNCwICjQu9C+0LPQuNC60LAgcmFkaW8pLFxuICAgICAqINC40L3QsNGH0LUg4oCUIHtAbGluayBGb3JtR3JvdXB9INC90LXQt9Cw0LLQuNGB0LjQvNGL0YUg0LHRg9C70LXQstGL0YUg0LrQvtC90YLRgNC+0LvQvtCyINC/0L4g0LjQtNC10L3RgtC40YTQuNC60LDRgtC+0YDQsNC8INC30L3QsNGH0LXQvdC40LkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY2hlY2tib3hGaWx0ZXIg0KTQuNC70YzRgtGAINGC0LjQv9CwIGNoZWNrYm94LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVDaGVja2JveEZvcm1Db250cm9sKGNoZWNrYm94RmlsdGVyOiBTY0lDaGVja2JveEZpbHRlcik6IEZvcm1Hcm91cDxSZWNvcmQ8c3RyaW5nLCBGb3JtQ29udHJvbDxib29sZWFuPj4+IHwgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4ge1xuICAgICAgICBpZiAoIWNoZWNrYm94RmlsdGVyLmlzTXVsdGlwbGUpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjb250cm9sczogUmVjb3JkPHN0cmluZywgRm9ybUNvbnRyb2w8Ym9vbGVhbj4+ID0ge307XG4gICAgICAgIGNoZWNrYm94RmlsdGVyLnZhbHVlcy5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgY29udHJvbHNbdmFsdWUuaWRdID0gbmV3IEZvcm1Db250cm9sKGZhbHNlLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gbmV3IEZvcm1Hcm91cChjb250cm9scyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQvtC30LTQsNC10YIgRm9ybUNvbnRyb2wg0LTQu9GPIHJhbmdlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHJhbmdlRmlsdGVyINCk0LjQu9GM0YLRgCDRgtC40L/QsCByYW5nZS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY3JlYXRlUmFuZ2VGb3JtQ29udHJvbChyYW5nZUZpbHRlcjogU2NSYW5nZUZpbHRlcik6IEZvcm1Db250cm9sPFtudW1iZXIsIG51bWJlcl0+IHtcbiAgICAgICAgLy8gVE9ETzog0JTQvtCx0LDQstC40YLRjCB1cGRhdGVPbjogJ2JsdXInINC/0L7RgdC70LUg0LjRgdC/0YDQsNCy0LvQtdC90LjRjyDQsdCw0LPQsCDQsiB0YWlnYS11aS5cbiAgICAgICAgcmV0dXJuIG5ldyBGb3JtQ29udHJvbChbTnVtYmVyKHJhbmdlRmlsdGVyLnNlbGVjdGVkTWluID8/IHJhbmdlRmlsdGVyLm1pbiksIE51bWJlcihyYW5nZUZpbHRlci5zZWxlY3RlZE1heCA/PyByYW5nZUZpbHRlci5tYXgpXSwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodC+0LfQtNCw0LXRgiBGb3JtQ29udHJvbCDQtNC70Y8gdG9nZ2xlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHRvZ2dsZUZpbHRlciDQpNC40LvRjNGC0YAg0YLQuNC/0LAgdG9nZ2xlLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVUb2dnbGVGb3JtQ29udHJvbCh0b2dnbGVGaWx0ZXI6IFNjVG9nZ2xlRmlsdGVyKTogRm9ybUNvbnRyb2w8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gbmV3IEZvcm1Db250cm9sKHRvZ2dsZUZpbHRlci5zZWxlY3RlZFZhbHVlID8/IGZhbHNlLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCe0LHRgNCw0LHQsNGC0YvQstCw0LXRgiBjaGVja2JveCDRhNC40LvRjNGC0YAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVzdWx0INCe0LHRitC10LrRgiDRgNC10LfRg9C70YzRgtCw0YLQsCDQtNC70Y8g0LfQsNC/0L7Qu9C90LXQvdC40Y8uXG4gICAgICogQHBhcmFtIGZpbHRlcklkINCY0LTQtdC90YLQuNGE0LjQutCw0YLQvtGAINGE0LjQu9GM0YLRgNCwLlxuICAgICAqIEBwYXJhbSBjb250cm9sVmFsdWUg0JfQvdCw0YfQtdC90LjQtSDQutC+0L3RgtGA0L7Qu9CwINGE0L7RgNC80YsuXG4gICAgICovXG4gICAgcHJpdmF0ZSBwcm9jZXNzQ2hlY2tib3hGaWx0ZXIocmVzdWx0OiBTY1Byb3BlcnR5RmlsdGVycywgZmlsdGVySWQ6IHN0cmluZywgY29udHJvbFZhbHVlOiBzdHJpbmcgfCBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPik6IHZvaWQge1xuICAgICAgICAvLyDQlNC70Y8gaXNNdWx0aXBsZSA9PT0gZmFsc2U6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+IC0+IHN0cmluZ1tdINC40Lcg0L7QtNC90L7Qs9C+INCy0YvQsdGA0LDQvdC90L7Qs9C+IElELlxuICAgICAgICBpZiAodHlwZW9mIGNvbnRyb2xWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGlmIChjb250cm9sVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc2VjdXJpdHkvZGV0ZWN0LW9iamVjdC1pbmplY3Rpb24sIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgICAgICAgICAgcmVzdWx0W2ZpbHRlcklkXSA9IFtjb250cm9sVmFsdWVdO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyDQlNC70Y8gY2hlY2tib3g6IEZvcm1Hcm91cCDRgSBGb3JtQ29udHJvbDxib29sZWFuPiAtPiBzdHJpbmdbXSAo0LzQsNGB0YHQuNCyIElEINCy0YvQsdGA0LDQvdC90YvRhSDQt9C90LDRh9C10L3QuNC5KS5cbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRJZHMgPSBPYmplY3QuZW50cmllcyhjb250cm9sVmFsdWUpXG4gICAgICAgICAgICAuZmlsdGVyKChbLCBpc1NlbGVjdGVkXSkgPT4gaXNTZWxlY3RlZClcbiAgICAgICAgICAgIC5tYXAoKFtpZF0pID0+IGlkKTtcblxuICAgICAgICBpZiAoc2VsZWN0ZWRJZHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHNlY3VyaXR5L2RldGVjdC1vYmplY3QtaW5qZWN0aW9uLCBuby1wYXJhbS1yZWFzc2lnblxuICAgICAgICAgICAgcmVzdWx0W2ZpbHRlcklkXSA9IHNlbGVjdGVkSWRzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J7QsdGA0LDQsdCw0YLRi9Cy0LDQtdGCIHJhbmdlINGE0LjQu9GM0YLRgC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXN1bHQg0J7QsdGK0LXQutGCINGA0LXQt9GD0LvRjNGC0LDRgtCwINC00LvRjyDQt9Cw0L/QvtC70L3QtdC90LjRjy5cbiAgICAgKiBAcGFyYW0gZmlsdGVySWQg0JjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0YTQuNC70YzRgtGA0LAuXG4gICAgICogQHBhcmFtIGNvbnRyb2xWYWx1ZSDQl9C90LDRh9C10L3QuNC1INC60L7QvdGC0YDQvtC70LAg0YTQvtGA0LzRiy5cbiAgICAgKiBAcGFyYW0gY29udHJvbFZhbHVlLjAg0J3QsNGH0LDQu9GM0L3QvtC1INC30L3QsNGH0LXQvdC40LUg0LTQuNCw0L/QsNC30L7QvdCwLlxuICAgICAqIEBwYXJhbSBjb250cm9sVmFsdWUuMSDQmtC+0L3QtdGH0L3QvtC1INC30L3QsNGH0LXQvdC40LUg0LTQuNCw0L/QsNC30L7QvdCwLlxuICAgICAqL1xuICAgIHByaXZhdGUgcHJvY2Vzc1JhbmdlRmlsdGVyKHJlc3VsdDogU2NQcm9wZXJ0eUZpbHRlcnMsIGZpbHRlcklkOiBzdHJpbmcsIFtmcm9tLCB0b106IFtudW1iZXIsIG51bWJlcl0pOiB2b2lkIHtcbiAgICAgICAgLy8g0JTQu9GPIHJhbmdlOiBGb3JtQ29udHJvbDxbbnVtYmVyLCBudW1iZXJdPiAtPiB7IGZyb20/OiBzdHJpbmc7IHRvPzogc3RyaW5nOyB9XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzZWN1cml0eS9kZXRlY3Qtb2JqZWN0LWluamVjdGlvbiwgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICAgICAgcmVzdWx0W2ZpbHRlcklkXSA9IHtcbiAgICAgICAgICAgIGZyb206IFN0cmluZyhmcm9tKSxcbiAgICAgICAgICAgIHRvOiBTdHJpbmcodG8pLFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCe0LHRgNCw0LHQsNGC0YvQstCw0LXRgiB0b2dnbGUg0YTQuNC70YzRgtGALlxuICAgICAqXG4gICAgICogQHBhcmFtIHJlc3VsdCDQntCx0YrQtdC60YIg0YDQtdC30YPQu9GM0YLQsNGC0LAg0LTQu9GPINC30LDQv9C+0LvQvdC10L3QuNGPLlxuICAgICAqIEBwYXJhbSBmaWx0ZXJJZCDQmNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgCDRhNC40LvRjNGC0YDQsC5cbiAgICAgKiBAcGFyYW0gY29udHJvbFZhbHVlINCX0L3QsNGH0LXQvdC40LUg0LrQvtC90YLRgNC+0LvQsCDRhNC+0YDQvNGLLlxuICAgICAqL1xuICAgIHByaXZhdGUgcHJvY2Vzc1RvZ2dsZUZpbHRlcihyZXN1bHQ6IFNjUHJvcGVydHlGaWx0ZXJzLCBmaWx0ZXJJZDogc3RyaW5nLCBjb250cm9sVmFsdWU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgLy8g0JTQu9GPIHRvZ2dsZTogRm9ybUNvbnRyb2w8Ym9vbGVhbj4gLT4gYm9vbGVhblxuICAgICAgICBpZiAoY29udHJvbFZhbHVlKSB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc2VjdXJpdHkvZGV0ZWN0LW9iamVjdC1pbmplY3Rpb24sIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgICAgICByZXN1bHRbZmlsdGVySWRdID0gY29udHJvbFZhbHVlO1xuICAgICAgICB9XG4gICAgfVxufVxuIiwiQGlmIChmaWx0ZXJzKCk/Lmxlbmd0aCkge1xuICAgIDxkaXYgY2xhc3M9XCJiZy10dWktYmFzZS0wMSBzaGFkb3ctc2MgZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIgZ2FwLTMgcm91bmRlZC14bFwiPlxuICAgICAgICA8dHVpLWFjY29yZGlvbiBjbGFzcz1cImFjY29yZGlvblwiPlxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIFt0dWlBY2NvcmRpb25dPVwiaXNPcGVuQWNjb3JkaW9uKClcIlxuICAgICAgICAgICAgICAgIGFwcGVhcmFuY2U9XCJwcmltYXJ5XCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICDQpNC40LvRjNGC0YDRi1xuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICA8dHVpLWV4cGFuZD5cbiAgICAgICAgICAgICAgICA8Zm9ybVxuICAgICAgICAgICAgICAgICAgICBbZm9ybUdyb3VwXT1cImZvcm1cIlxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTQgcGItMVwiXG4gICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICBAZm9yIChmaWx0ZXIgb2YgZmlsdGVycygpOyB0cmFjayBmaWx0ZXIuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0yXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwidGV4dC1ib2R5LXMgZm9udC1tZWRpdW1cIj57eyBmaWx0ZXIubGFiZWwgfX08L2xhYmVsPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChmaWx0ZXIudHlwZSA9PT0gJ2NoZWNrYm94Jykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGZpbHRlci5pc011bHRpcGxlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAZm9yICh2YWx1ZSBvZiBmaWx0ZXIudmFsdWVzOyB0cmFjayB2YWx1ZS5pZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAbGV0IGZvcm1Db250cm9sID0gZm9ybS5nZXQoZmlsdGVyLmlkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbE5hbWVdPVwiZmlsdGVyLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwidmFsdWUuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aVJhZGlvXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImZvcm1Db250cm9sPy5zZXRWYWx1ZShmb3JtQ29udHJvbD8udmFsdWUgPT09IHZhbHVlLmlkID8gbnVsbCA6IHZhbHVlLmlkKVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInJhZGlvXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtYm9keS1zXCI+e3sgdmFsdWUubGFiZWwgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmb3JtR3JvdXBOYW1lXT1cImZpbHRlci5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAZm9yICh2YWx1ZSBvZiBmaWx0ZXIudmFsdWVzOyB0cmFjayB2YWx1ZS5pZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJ2YWx1ZS5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpQ2hlY2tib3hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1ib2R5LXNcIj57eyB2YWx1ZS5sYWJlbCB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoZmlsdGVyLnR5cGUgPT09ICdyYW5nZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS1pbnB1dC1yYW5nZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJmaWx0ZXIuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21pbl09XCIrZmlsdGVyLm1pblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWF4XT1cIitmaWx0ZXIubWF4XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGZpbHRlci50eXBlID09PSAndG9nZ2xlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmbGV4IGl0ZW1zLWNlbnRlciBnYXAtMlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJmaWx0ZXIuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aUNoZWNrYm94XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtYm9keS1zXCI+0JTQsDwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvZm9ybT5cbiAgICAgICAgICAgIDwvdHVpLWV4cGFuZD5cbiAgICAgICAgPC90dWktYWNjb3JkaW9uPlxuICAgIDwvZGl2PlxufVxuIl19
402
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2MtY2F0YWxvZy1maWx0ZXJzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NsaWVudC11aS9jYXRhbG9nL2NhdGFsb2ctZmlsdGVycy9zYy1jYXRhbG9nLWZpbHRlcnMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NhdGFsb2cvY2F0YWxvZy1maWx0ZXJzL3NjLWNhdGFsb2ctZmlsdGVycy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFFM0MsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdEcsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFFBQVEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0UsT0FBTyxFQUNILGdCQUFnQixFQUVoQixzQkFBc0IsRUFFdEIsY0FBYyxHQUlqQixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BGLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0RSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFNB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Q3hELE1BQU07Z0JBQ1YsQ0FBQztnQkFDRDtvQkFDSSxNQUFNO1lBQ2QsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO0lBQ1AsQ0FBQzsrR0F2YlEseUJBQXlCO21HQUF6Qix5QkFBeUIsNlRDaER0QyxxNlFBeUpBLGlKRHJIUSxtQkFBbUIsdW1EQUVuQiwwQkFBMEIsZ01BQzFCLG1DQUFtQyx3SUFFbkMsZUFBZSwyRkFDZixXQUFXLDZPQUVYLFFBQVEsc0pBQ1IsU0FBUzs7NEZBR0oseUJBQXlCO2tCQW5CckMsU0FBUztpQ0FDTSxJQUFJLFlBQ04sb0JBQW9CLG1CQUdiLHVCQUF1QixDQUFDLE1BQU0sV0FDdEM7d0JBQ0wsbUJBQW1CO3dCQUNuQixZQUFZO3dCQUNaLDBCQUEwQjt3QkFDMUIsbUNBQW1DO3dCQUNuQyxRQUFRO3dCQUNSLGVBQWU7d0JBQ2YsV0FBVzt3QkFDWCxjQUFjO3dCQUNkLFFBQVE7d0JBQ1IsU0FBUztxQkFDWiIsInNvdXJjZXNDb250ZW50IjpbIi8qIGVzbGludC1kaXNhYmxlIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXMgKi9cblxuaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRGVzdHJveVJlZiwgaW5qZWN0LCBpbnB1dCwgb3V0cHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQsIHRvU2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgUmVhY3RpdmVGb3Jtc01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7XG4gICAgU0NfQ0FURUdPUllfSU5GTyxcbiAgICBTY0NhdGFsb2dGaWx0ZXIsXG4gICAgU2NDYXRhbG9nRmlsdGVyU2VydmljZSxcbiAgICBTY0lDaGVja2JveEZpbHRlcixcbiAgICBTY0lkT3JTbHVnUGlwZSxcbiAgICBTY1Byb3BlcnR5RmlsdGVycyxcbiAgICBTY1JhbmdlRmlsdGVyLFxuICAgIFNjVG9nZ2xlRmlsdGVyLFxufSBmcm9tICdAc25hYmNlbnRyL2NsaWVudC1jb3JlJztcbmltcG9ydCB7IHR1aUlzUHJlc2VudCB9IGZyb20gJ0B0YWlnYS11aS9jZGsnO1xuaW1wb3J0IHsgVHVpQnV0dG9uLCBUdWlMYWJlbCwgVHVpTnVtYmVyRm9ybWF0LCBUdWlUZXh0ZmllbGQgfSBmcm9tICdAdGFpZ2EtdWkvY29yZSc7XG5pbXBvcnQgeyBUdWlDaGVja2JveCwgVHVpSW5wdXROdW1iZXIsIFR1aVJhbmdlIH0gZnJvbSAnQHRhaWdhLXVpL2tpdCc7XG5pbXBvcnQgeyBpc05pbCB9IGZyb20gJ2xvZGFzaC1lcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBkZWJvdW5jZVRpbWUsIEVNUFRZLCBmaWx0ZXIsIG1hcCwgbWVyZ2UsIHNoYXJlLCBTdWJzY3JpcHRpb24sIHN3aXRjaE1hcCwgdGFwIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFNjU2VsZWN0T25Gb2N1c2luRGlyZWN0aXZlIH0gZnJvbSAnLi4vLi4vZGlyZWN0aXZlcy9zZWxlY3Qtb24tZm9jdXNpbi9zYy1zZWxlY3Qtb24tZm9jdXNpbi5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgU2NDYXRhbG9nRmlsdGVyQ29sbGFwc2libGVDb21wb25lbnQgfSBmcm9tICcuL2NvbGxhcHNpYmxlL3NjLWNhdGFsb2ctZmlsdGVyLWNvbGxhcHNpYmxlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBTQ19DQVRBTE9HX1BST0RVQ1RTX0ZJTFRFUlMgfSBmcm9tICcuL3Rva2Vucy9zYy1jYXRhbG9nLXByb2R1Y3RzLWZpbHRlcnMnO1xuaW1wb3J0IHsgU0NfQ0FUQUxPR19TSE9XX1BST0RVQ1RTX1JFQ1VSU0lWRUxZIH0gZnJvbSAnLi90b2tlbnMvc2MtY2F0YWxvZy1zaG93LXByb2R1Y3RzLXJlY3Vyc2l2ZWx5JztcblxuLyoqXG4gKiDQmtC+0LzQv9C+0L3QtdC90YIg0LLRi9Cy0L7QtNCwINGE0LjQu9GM0YLRgNC+0LIg0LrQsNGC0LDQu9C+0LPQsC5cbiAqL1xuQENvbXBvbmVudCh7XG4gICAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgICBzZWxlY3RvcjogJ3NjLWNhdGFsb2ctZmlsdGVycycsXG4gICAgc3R5bGVVcmw6ICcuL3NjLWNhdGFsb2ctZmlsdGVycy5jb21wb25lbnQuc2NzcycsXG4gICAgdGVtcGxhdGVVcmw6ICcuL3NjLWNhdGFsb2ctZmlsdGVycy5jb21wb25lbnQuaHRtbCcsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgaW1wb3J0czogW1xuICAgICAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgICAgICBUdWlUZXh0ZmllbGQsXG4gICAgICAgIFNjU2VsZWN0T25Gb2N1c2luRGlyZWN0aXZlLFxuICAgICAgICBTY0NhdGFsb2dGaWx0ZXJDb2xsYXBzaWJsZUNvbXBvbmVudCxcbiAgICAgICAgVHVpTGFiZWwsXG4gICAgICAgIFR1aU51bWJlckZvcm1hdCxcbiAgICAgICAgVHVpQ2hlY2tib3gsXG4gICAgICAgIFR1aUlucHV0TnVtYmVyLFxuICAgICAgICBUdWlSYW5nZSxcbiAgICAgICAgVHVpQnV0dG9uLFxuICAgIF0sXG59KVxuZXhwb3J0IGNsYXNzIFNjQ2F0YWxvZ0ZpbHRlcnNDb21wb25lbnQge1xuICAgIC8qKlxuICAgICAqINCf0L7QtNC/0LjRgdC60Lgg0YHQuNC90YXRgNC+0L3QuNC30LDRhtC40Lgg0LrQvtC90YLRgNC+0LvQvtCyINGE0L7RgNC80YsgKHJhbmdlIHNsaWRlciwgc2luZ2xlLXNlbGVjdCBjaGVja2JveCkuXG4gICAgICovXG4gICAgcHJpdmF0ZSBmb3JtU3luY3MgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG5cbiAgICAvKipcbiAgICAgKiDQodC10YDQstC40YEg0LTQu9GPINGA0LDQsdC+0YLRiyDRgSDRhNC40LvRjNGC0YDQsNC80Lgg0LrQsNGC0LDQu9C+0LPQsC5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGNhdGFsb2dGaWx0ZXJTZXJ2aWNlOiBTY0NhdGFsb2dGaWx0ZXJTZXJ2aWNlID0gaW5qZWN0KFNjQ2F0YWxvZ0ZpbHRlclNlcnZpY2UpO1xuXG4gICAgLyoqXG4gICAgICog0J/QsNC50L8sINCy0L7Qt9Cy0YDQsNGJ0LDRjtGJ0LjQuSDQuNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgCDQuNC70Lgg0YHQuNC80LLQvtC70YzQvdC+0LUg0L7QsdC+0LfQvdCw0YfQtdC90LjQtSAoc2x1Zykg0LjRgdGF0L7QtNGPINC40Lcg0L3QsNGB0YLRgNC+0LXQuiDQvtC60YDRg9C20LXQvdC40Y8uXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBpZE9yU2x1Z1BpcGU6IFNjSWRPclNsdWdQaXBlID0gaW5qZWN0KFNjSWRPclNsdWdQaXBlKTtcblxuICAgIC8qKlxuICAgICAqIFN1YmplY3Qg0LTQu9GPINGF0YDQsNC90LXQvdC40Y8g0YTQuNC70YzRgtGA0L7QsiDQv9GA0L7QtNGD0LrRgtC+0LIuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBjYXRhbG9nUHJvZHVjdHNGaWx0ZXJzJCA9IGluamVjdChTQ19DQVRBTE9HX1BST0RVQ1RTX0ZJTFRFUlMpO1xuXG4gICAgLyoqXG4gICAgICog0J/RgNC40LfQvdCw0Log0L3QtdC+0LHRhdC+0LTQuNC80L7RgdGC0Lgg0L7RgtC+0LHRgNCw0LbQsNGC0Ywg0YTQuNC70YzRgtGA0Ysg0LTQu9GPINCy0LvQvtC20LXQvdC90YvRhSDQutCw0YLQtdCz0L7RgNC40LkuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBpc1JlY3Vyc2l2ZWx5ID0gaW5qZWN0KFNDX0NBVEFMT0dfU0hPV19QUk9EVUNUU19SRUNVUlNJVkVMWSk7XG5cbiAgICAvKipcbiAgICAgKiDQn9C+0LrQsNC30YvQstCw0YLRjCDQu9C4INC60L3QvtC/0LrRgyDCq9Cf0L7QutCw0LfQsNGC0Ywg0YDQtdC30YPQu9GM0YLQsNGC0YvCuy5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgc2hvd1Jlc3VsdHNCdXR0b24gPSBpbnB1dChmYWxzZSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC+0LHRi9GC0LjQtSDQvdCw0LbQsNGC0LjRjyDQvdCwINC60L3QvtC/0LrRgyDRgdCx0YDQvtGB0LAg0LLRgdC10YUg0YTQuNC70YzRgtGA0L7Qsi5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgcmVzZXRGaWx0ZXJzID0gb3V0cHV0KCk7XG5cbiAgICAvKipcbiAgICAgKiDQodC+0LHRi9GC0LjQtSDQvdCw0LbQsNGC0LjRjyDQvdCwINC60L3QvtC/0LrRgyDQv9C+0LrQsNC30LAg0YDQtdC30YPQu9GM0YLQsNGC0L7Qsi5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgc2hvd1Jlc3VsdHMgPSBvdXRwdXQoKTtcblxuICAgIC8qKlxuICAgICAqIEZvcm1Hcm91cCDQtNC70Y8g0YTQuNC70YzRgtGA0L7Qsi5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZm9ybSA9IG5ldyBGb3JtR3JvdXA8XG4gICAgICAgIFJlY29yZDxzdHJpbmcsIFJldHVyblR5cGU8dHlwZW9mIHRoaXMuY3JlYXRlQ2hlY2tib3hGb3JtQ29udHJvbD4gfCBSZXR1cm5UeXBlPHR5cGVvZiB0aGlzLmNyZWF0ZVJhbmdlRm9ybUNvbnRyb2w+IHwgUmV0dXJuVHlwZTx0eXBlb2YgdGhpcy5jcmVhdGVUb2dnbGVGb3JtQ29udHJvbD4+XG4gICAgPih7fSk7XG5cbiAgICAvKipcbiAgICAgKiB7QGxpbmsgT2JzZXJ2YWJsZX0g0YTQuNC70YzRgtGA0L7QsiDQutCw0YLQtdCz0L7RgNC40LguXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGZpbHRlcnMgPSB0b1NpZ25hbChcbiAgICAgICAgaW5qZWN0KFNDX0NBVEVHT1JZX0lORk8pLnBpcGUoXG4gICAgICAgICAgICBjYXRjaEVycm9yKCgpID0+IEVNUFRZKSxcbiAgICAgICAgICAgIGZpbHRlcih0dWlJc1ByZXNlbnQpLFxuICAgICAgICAgICAgc3dpdGNoTWFwKChjYXRlZ29yeSkgPT4gdGhpcy5jYXRhbG9nRmlsdGVyU2VydmljZS5nZXRGaWx0ZXJzJCh0aGlzLmlkT3JTbHVnUGlwZS50cmFuc2Zvcm0oY2F0ZWdvcnkpLCB0aGlzLmlzUmVjdXJzaXZlbHkpKSxcbiAgICAgICAgICAgIGZpbHRlcih0dWlJc1ByZXNlbnQpLFxuICAgICAgICAgICAgbWFwKChmaWx0ZXJzKSA9PlxuICAgICAgICAgICAgICAgIGZpbHRlcnNcbiAgICAgICAgICAgICAgICAgICAgLmZpbHRlcigoaXRlbSkgPT4gaXRlbS50eXBlICE9PSAncmFuZ2UnIHx8IGl0ZW0ubWluICE9PSBpdGVtLm1heClcbiAgICAgICAgICAgICAgICAgICAgLm1hcCgoaXRlbSkgPT4gKGl0ZW0udHlwZSA9PT0gJ2NoZWNrYm94JyA/IHsgLi4uaXRlbSwgdmFsdWVzOiBbLi4uaXRlbS52YWx1ZXNdLnNvcnQoKGEsIGIpID0+IGEubGFiZWwubG9jYWxlQ29tcGFyZShiLmxhYmVsKSkgfSA6IGl0ZW0pKVxuICAgICAgICAgICAgKSxcbiAgICAgICAgICAgIHRhcCgoZmlsdGVycykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRm9ybUNvbnRyb2xzKGZpbHRlcnMpO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBzaGFyZSgpXG4gICAgICAgIClcbiAgICApO1xuXG4gICAgLyoqXG4gICAgICog0JjQvdC40YbQuNCw0LvQuNC30LjRgNGD0LXRgiDRjdC60LfQtdC80L/Qu9GP0YAg0LrQu9Cw0YHRgdCwIHtAbGluayBTY0NhdGFsb2dGaWx0ZXJzQ29tcG9uZW50fS5cbiAgICAgKi9cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIGluamVjdChEZXN0cm95UmVmKS5vbkRlc3Ryb3koKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5mb3JtU3luY3MudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5mb3JtLnZhbHVlQ2hhbmdlcy5waXBlKGRlYm91bmNlVGltZSgwKSwgdGFrZVVudGlsRGVzdHJveWVkKCkpLnN1YnNjcmliZSgoZmlsdGVycykgPT4ge1xuICAgICAgICAgICAgdGhpcy5jYXRhbG9nUHJvZHVjdHNGaWx0ZXJzJC5uZXh0KHRoaXMuYnVpbGRQcm9wZXJ0eUZpbHRlcnMoZmlsdGVycykpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0L3QvtCy0LvRj9C10YIg0YHQvtGB0YLQsNCyINC60L7QvdGC0YDQvtC70L7QsiDRhNC+0YDQvNGLINC90LAg0L7RgdC90L7QstC1INC/0LXRgNC10LTQsNC90L3Ri9GFINGE0LjQu9GM0YLRgNC+0LIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmlsdGVycyDQnNCw0YHRgdC40LIg0YTQuNC70YzRgtGA0L7QsiDQtNC70Y8g0YHQvtC30LTQsNC90LjRjyDQutC+0L3RgtGA0L7Qu9C+0LIuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHVwZGF0ZUZvcm1Db250cm9scyhmaWx0ZXJzOiBTY0NhdGFsb2dGaWx0ZXJbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmZvcm1TeW5jcy51bnN1YnNjcmliZSgpO1xuICAgICAgICB0aGlzLmZvcm1TeW5jcyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICAgICAgICBPYmplY3Qua2V5cyh0aGlzLmZvcm0uY29udHJvbHMpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5mb3JtLnJlbW92ZUNvbnRyb2woa2V5IGFzIG5ldmVyLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGZpbHRlcnMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgc3dpdGNoIChpdGVtLnR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjaGVja2JveCc6IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hlY2tib3hDb250cm9sID0gdGhpcy5jcmVhdGVDaGVja2JveEZvcm1Db250cm9sKGl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uYWRkQ29udHJvbChpdGVtLmlkLCBjaGVja2JveENvbnRyb2wsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBTaW5nbGUtc2VsZWN0INC00LvRjyAhaXNNdWx0aXBsZTog0L/RgNC4INCy0YvQsdC+0YDQtSDQvtC00L3QvtCz0L4g0L7RgdGC0LDQu9GM0L3Ri9C1INGB0L3QuNC80LDRjtGC0YHRjy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpdGVtLmlzTXVsdGlwbGUgJiYgaXRlbS52YWx1ZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtU3luY3MuYWRkKHRoaXMuc3luY1NpbmdsZVNlbGVjdENoZWNrYm94KGNoZWNrYm94Q29udHJvbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdyYW5nZSc6IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2VDb250cm9sID0gdGhpcy5jcmVhdGVSYW5nZUZvcm1Db250cm9sKGl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uYWRkQ29udHJvbChpdGVtLmlkLCByYW5nZUNvbnRyb2wsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtU3luY3MuYWRkKHRoaXMuc3luY1JhbmdlRnJvbVRvQW5kU2xpZGVyKHJhbmdlQ29udHJvbCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAndG9nZ2xlJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmFkZENvbnRyb2woaXRlbS5pZCwgdGhpcy5jcmVhdGVUb2dnbGVGb3JtQ29udHJvbChpdGVtKSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J/RgNC10L7QsdGA0LDQt9GD0LXRgiDQt9C90LDRh9C10L3QuNGPINGE0L7RgNC80Ysg0LIg0L7QsdGK0LXQutGCINGE0LjQu9GM0YLRgNC+0LIg0YHQstC+0LnRgdGC0LIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUg0JfQvdCw0YfQtdC90LjRjyDRhNC+0YDQvNGLLlxuICAgICAqIEByZXR1cm5zINCe0LHRitC10LrRgiDRhNC40LvRjNGC0YDQvtCyINGB0LLQvtC50YHRgtCyLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBidWlsZFByb3BlcnR5RmlsdGVycyh2YWx1ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBTY1Byb3BlcnR5RmlsdGVycyB7XG4gICAgICAgIGNvbnN0IHJlc3VsdDogU2NQcm9wZXJ0eUZpbHRlcnMgPSB7fTtcblxuICAgICAgICB0aGlzLmZpbHRlcnMoKT8uZm9yRWFjaCgoZmlsdGVySXRlbSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29udHJvbFZhbHVlID0gdmFsdWVbZmlsdGVySXRlbS5pZF07XG5cbiAgICAgICAgICAgIGlmIChpc05pbChjb250cm9sVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzd2l0Y2ggKGZpbHRlckl0ZW0udHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNrYm94JzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzQ2hlY2tib3hGaWx0ZXIocmVzdWx0LCBmaWx0ZXJJdGVtLCBjb250cm9sVmFsdWUgYXMgUmVjb3JkPHN0cmluZywgYm9vbGVhbj4pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdyYW5nZSc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1JhbmdlRmlsdGVyKHJlc3VsdCwgZmlsdGVySXRlbS5pZCwgY29udHJvbFZhbHVlIGFzIHsgZnJvbTogbnVtYmVyOyB0bzogbnVtYmVyIH0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGUnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NUb2dnbGVGaWx0ZXIocmVzdWx0LCBmaWx0ZXJJdGVtLmlkLCBjb250cm9sVmFsdWUgYXMgYm9vbGVhbik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCh0L7Qt9C00LDRkdGCIEZvcm1Hcm91cCDQtNC70Y8gY2hlY2tib3g6INC90LAg0LrQsNC20LTRi9C5IHtAY29kZSB2YWx1ZS5pZH0g4oCUINCx0YPQu9C10LLRi9C5INC60L7QvdGC0YDQvtC7LlxuICAgICAqXG4gICAgICog0JXQtNC40L3Ri9C5INGE0L7RgNC80LDRgiDQuCDQtNC70Y8g0L7QtNC90L7Qs9C+LCDQuCDQtNC70Y8g0LzQvdC+0LbQtdGB0YLQstCwINC30L3QsNGH0LXQvdC40Lk6INGI0LDQsdC70L7QvSDRgNC10L3QtNC10YDQuNGCINC40YUg0L7QtNC40L3QsNC60L7QstC+LlxuICAgICAqINCg0LDQt9C70LjRh9C40LUg0LIgQVBJLdCy0YvQstC+0LTQtSDQtNC70Y8g0L7QtNC40L3QvtGH0L3QvtCz0L4g0LfQvdCw0YfQtdC90LjRjyAoYm9vbGVhbiDQstC80LXRgdGC0L4g0LzQsNGB0YHQuNCy0LApINC+0LHRgNCw0LHQsNGC0YvQstCw0LXRgtGB0Y8g0LIge0BsaW5rIHByb2Nlc3NDaGVja2JveEZpbHRlcn0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gY2hlY2tib3hGaWx0ZXIg0KTQuNC70YzRgtGAINGC0LjQv9CwIGNoZWNrYm94LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVDaGVja2JveEZvcm1Db250cm9sKGNoZWNrYm94RmlsdGVyOiBTY0lDaGVja2JveEZpbHRlcik6IEZvcm1Hcm91cDxSZWNvcmQ8c3RyaW5nLCBGb3JtQ29udHJvbDxib29sZWFuPj4+IHtcbiAgICAgICAgY29uc3QgaXNTZWxlY3RlZCA9IChpZDogc3RyaW5nKTogYm9vbGVhbiA9PiBjaGVja2JveEZpbHRlci5zZWxlY3RlZFZhbHVlcz8uaW5jbHVkZXMoaWQpID8/IGZhbHNlO1xuICAgICAgICBjb25zdCBjb250cm9sczogUmVjb3JkPHN0cmluZywgRm9ybUNvbnRyb2w8Ym9vbGVhbj4+ID0ge307XG5cbiAgICAgICAgY2hlY2tib3hGaWx0ZXIudmFsdWVzLmZvckVhY2goKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICBjb250cm9sc1t2YWx1ZS5pZF0gPSBuZXcgRm9ybUNvbnRyb2woaXNTZWxlY3RlZCh2YWx1ZS5pZCksIHsgbm9uTnVsbGFibGU6IHRydWUgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBuZXcgRm9ybUdyb3VwKGNvbnRyb2xzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodC+0LfQtNCw0ZHRgiB7QGxpbmsgRm9ybUdyb3VwfSDQtNC70Y8gcmFuZ2U6IHtAY29kZSBmcm9tfSwge0Bjb2RlIHRvfSwge0Bjb2RlIHNsaWRlcn0gKNC60L7RgNGC0LXQtiDQtNC70Y8ge0BsaW5rIFR1aVJhbmdlfSkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmFuZ2VGaWx0ZXIg0KTQuNC70YzRgtGAINGC0LjQv9CwIHJhbmdlLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVSYW5nZUZvcm1Db250cm9sKHJhbmdlRmlsdGVyOiBTY1JhbmdlRmlsdGVyKTogRm9ybUdyb3VwPHtcbiAgICAgICAgZnJvbTogRm9ybUNvbnRyb2w8bnVtYmVyPjtcbiAgICAgICAgdG86IEZvcm1Db250cm9sPG51bWJlcj47XG4gICAgICAgIHNsaWRlcjogRm9ybUNvbnRyb2w8W251bWJlciwgbnVtYmVyXT47XG4gICAgfT4ge1xuICAgICAgICBjb25zdCBmcm9tVmFsdWUgPSBOdW1iZXIocmFuZ2VGaWx0ZXIuc2VsZWN0ZWRNaW4gPz8gcmFuZ2VGaWx0ZXIubWluKTtcbiAgICAgICAgY29uc3QgdG9WYWx1ZSA9IE51bWJlcihyYW5nZUZpbHRlci5zZWxlY3RlZE1heCA/PyByYW5nZUZpbHRlci5tYXgpO1xuXG4gICAgICAgIHJldHVybiBuZXcgRm9ybUdyb3VwKHtcbiAgICAgICAgICAgIGZyb206IG5ldyBGb3JtQ29udHJvbChmcm9tVmFsdWUsIHsgbm9uTnVsbGFibGU6IHRydWUgfSksXG4gICAgICAgICAgICB0bzogbmV3IEZvcm1Db250cm9sKHRvVmFsdWUsIHsgbm9uTnVsbGFibGU6IHRydWUgfSksXG4gICAgICAgICAgICBzbGlkZXI6IG5ldyBGb3JtQ29udHJvbDxbbnVtYmVyLCBudW1iZXJdPihbZnJvbVZhbHVlLCB0b1ZhbHVlXSwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KSxcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KDQtdCw0LvQuNC30YPQtdGCIHNpbmdsZS1zZWxlY3Qg0L/QvtCy0LXQtNC10L3QuNC1INC00LvRjyBGb3JtR3JvdXAg0YEg0LHRg9C70LXQstGL0LzQuCDQutC+0L3RgtGA0L7Qu9Cw0LzQuDpcbiAgICAgKiDQv9GA0Lgg0L/QvtGP0LLQu9C10L3QuNC4INC90L7QstC+0LPQviB0cnVlINC+0YHRgtCw0LvRjNC90YvQtSDQutC+0L3RgtGA0L7Qu9GLINCz0YDRg9C/0L/RiyDRgdCx0YDQsNGB0YvQstCw0Y7RgtGB0Y8g0LIgZmFsc2UuXG4gICAgICpcbiAgICAgKiDQodC+0YXRgNCw0L3Rj9C10YIg0L/QvtGB0LvQtdC00L3QtdC1IMKr0YHRgtCw0LHQuNC70YzQvdC+0LXCuyDRgdC+0YHRgtC+0Y/QvdC40LUg0Lgg0YHRgNCw0LLQvdC40LLQsNC10YIg0YHQu9C10LTRg9GO0YnQtdC1INC30L3QsNGH0LXQvdC40LUg0YEg0L3QuNC8IOKAlFxuICAgICAqINC90L7QstGL0LkgdHJ1ZSAo0L7RgtGB0YPRgtGB0YLQstC+0LLQsNC7INCyIHByZXYpINGB0YfQuNGC0LDQtdGC0YHRjyDQstGL0LHRgNCw0L3QvdGL0LwsINC+0YHRgtCw0LvRjNC90YvQtSDRgdCx0YDQsNGB0YvQstCw0Y7RgtGB0Y8g0YfQtdGA0LXQtyBzZXRWYWx1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBncm91cCBGb3JtR3JvdXAgY2hlY2tib3gt0YTQuNC70YzRgtGA0LAgKGlkIOKGkiBib29sZWFuKS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHN5bmNTaW5nbGVTZWxlY3RDaGVja2JveChncm91cDogRm9ybUdyb3VwPFJlY29yZDxzdHJpbmcsIEZvcm1Db250cm9sPGJvb2xlYW4+Pj4pOiBTdWJzY3JpcHRpb24ge1xuICAgICAgICBsZXQgcHJldmlvdXNTdGF0ZSA9IGdyb3VwLmdldFJhd1ZhbHVlKCkgYXMgUmVjb3JkPHN0cmluZywgYm9vbGVhbj47XG5cbiAgICAgICAgcmV0dXJuIGdyb3VwLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50ID0gdmFsdWUgYXMgUmVjb3JkPHN0cmluZywgYm9vbGVhbj47XG4gICAgICAgICAgICBjb25zdCBuZXdseUNoZWNrZWQgPSBPYmplY3QuZW50cmllcyhjdXJyZW50KS5maW5kKChbaWQsIGlzQ2hlY2tlZF0pID0+IHtcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc2VjdXJpdHkvZGV0ZWN0LW9iamVjdC1pbmplY3Rpb25cbiAgICAgICAgICAgICAgICByZXR1cm4gaXNDaGVja2VkICYmICFwcmV2aW91c1N0YXRlW2lkXTtcbiAgICAgICAgICAgIH0pPy5bMF07XG5cbiAgICAgICAgICAgIGlmICghbmV3bHlDaGVja2VkKSB7XG4gICAgICAgICAgICAgICAgcHJldmlvdXNTdGF0ZSA9IHsgLi4uY3VycmVudCB9O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBuZXh0OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiA9IHt9O1xuICAgICAgICAgICAgT2JqZWN0LmtleXMoZ3JvdXAuY29udHJvbHMpLmZvckVhY2goKGlkKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHNlY3VyaXR5L2RldGVjdC1vYmplY3QtaW5qZWN0aW9uXG4gICAgICAgICAgICAgICAgbmV4dFtpZF0gPSBpZCA9PT0gbmV3bHlDaGVja2VkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBwcmV2aW91c1N0YXRlID0gbmV4dDtcbiAgICAgICAgICAgIGdyb3VwLnNldFZhbHVlKG5leHQpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodCy0Y/Qt9GL0LLQsNC10YIg0L/QvtC70Y8gwqvQvtGCwrsvwqvQtNC+wrsg0YEg0LrQvtC90YLRgNC+0LvQvtC8INGB0LvQsNC50LTQtdGA0LAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZ3JvdXAgRm9ybUdyb3VwIHJhbmdlLdGE0LjQu9GM0YLRgNCwLlxuICAgICAqL1xuICAgIHByaXZhdGUgc3luY1JhbmdlRnJvbVRvQW5kU2xpZGVyKGdyb3VwOiBGb3JtR3JvdXApOiBTdWJzY3JpcHRpb24ge1xuICAgICAgICBjb25zdCBmcm9tID0gZ3JvdXAuZ2V0KCdmcm9tJyk7XG4gICAgICAgIGNvbnN0IHRvID0gZ3JvdXAuZ2V0KCd0bycpO1xuICAgICAgICBjb25zdCBzbGlkZXIgPSBncm91cC5nZXQoJ3NsaWRlcicpO1xuXG4gICAgICAgIGlmICghZnJvbSB8fCAhdG8gfHwgIXNsaWRlcikge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBTdWJzY3JpcHRpb24oKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN1YiA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICAgICAgICAvLyDQmNC90L/Rg9GC0Ysg4oaSINGB0LvQsNC50LTQtdGAOyDQtdGB0LvQuCDCq9C+0YLCuyA+IMKr0LTQvsK7LCDQv9C+0LTQvdC40LzQsNC10LwgwqvQtNC+wrsg0LTQviDCq9C+0YLCuy5cbiAgICAgICAgY29uc3QgYXBwbHlTbGlkZXJGcm9tSW5wdXRzID0gKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgY29uc3QgbG93ID0gTnVtYmVyKGZyb20udmFsdWUpO1xuICAgICAgICAgICAgbGV0IGhpZ2ggPSBOdW1iZXIodG8udmFsdWUpO1xuXG4gICAgICAgICAgICBpZiAobG93ID4gaGlnaCkge1xuICAgICAgICAgICAgICAgIGhpZ2ggPSBsb3c7XG4gICAgICAgICAgICAgICAgdG8uc2V0VmFsdWUoaGlnaCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBjdXJyZW50UGFpciA9IHNsaWRlci52YWx1ZSBhcyBbbnVtYmVyLCBudW1iZXJdO1xuXG4gICAgICAgICAgICBpZiAoY3VycmVudFBhaXJbMF0gIT09IGxvdyB8fCBjdXJyZW50UGFpclsxXSAhPT0gaGlnaCkge1xuICAgICAgICAgICAgICAgIHNsaWRlci5zZXRWYWx1ZShbbG93LCBoaWdoXSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgIHNsaWRlci5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuXG4gICAgICAgIHN1Yi5hZGQobWVyZ2UoZnJvbS52YWx1ZUNoYW5nZXMsIHRvLnZhbHVlQ2hhbmdlcykuc3Vic2NyaWJlKGFwcGx5U2xpZGVyRnJvbUlucHV0cykpO1xuXG4gICAgICAgIHN1Yi5hZGQoXG4gICAgICAgICAgICBzbGlkZXIudmFsdWVDaGFuZ2VzLnN1YnNjcmliZSgodmFsdWUpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBbbG93LCBoaWdoXSA9IHZhbHVlIGFzIFtudW1iZXIsIG51bWJlcl07XG5cbiAgICAgICAgICAgICAgICBpZiAoZnJvbS52YWx1ZSAhPT0gbG93KSB7XG4gICAgICAgICAgICAgICAgICAgIGZyb20uc2V0VmFsdWUobG93LCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICAgICAgICAgIGZyb20ubWFya0FzRGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodG8udmFsdWUgIT09IGhpZ2gpIHtcbiAgICAgICAgICAgICAgICAgICAgdG8uc2V0VmFsdWUoaGlnaCwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgICAgICB0by5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG5cbiAgICAgICAgLy8g0KHQvtCy0L/QsNGB0YLRjCDRgSDQv9C+0LvRj9C80Lgg0L/RgNC4INC/0LXRgNCy0L7QvCDQv9C+0LrQsNC30LUgKNGD0LbQtSDRgdC+0LLQv9Cw0LTQsNC10YIg0L/RgNC4INGB0L7Qt9C00LDQvdC40LgsINC90L4g0L3QsCDQstGB0Y/QutC40Lkg0YHQu9GD0YfQsNC5KS5cbiAgICAgICAgYXBwbHlTbGlkZXJGcm9tSW5wdXRzKCk7XG5cbiAgICAgICAgcmV0dXJuIHN1YjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodC+0LfQtNCw0LXRgiBGb3JtQ29udHJvbCDQtNC70Y8gdG9nZ2xlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHRvZ2dsZUZpbHRlciDQpNC40LvRjNGC0YAg0YLQuNC/0LAgdG9nZ2xlLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBjcmVhdGVUb2dnbGVGb3JtQ29udHJvbCh0b2dnbGVGaWx0ZXI6IFNjVG9nZ2xlRmlsdGVyKTogRm9ybUNvbnRyb2w8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gbmV3IEZvcm1Db250cm9sKHRvZ2dsZUZpbHRlci5zZWxlY3RlZFZhbHVlID8/IGZhbHNlLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCe0LHRgNCw0LHQsNGC0YvQstCw0LXRgiBjaGVja2JveDogRm9ybUdyb3VwIOKGkiBzdHJpbmdbXSDQstGL0LHRgNCw0L3QvdGL0YUgaWQ7INC00LvRjyDQtdC00LjQvdGB0YLQstC10L3QvdC+0LPQviDQt9C90LDRh9C10L3QuNGPIOKAlCBib29sZWFuICjQutCw0LogdG9nZ2xlKS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXN1bHQg0J7QsdGK0LXQutGCINGA0LXQt9GD0LvRjNGC0LDRgtCwINC00LvRjyDQt9Cw0L/QvtC70L3QtdC90LjRjy5cbiAgICAgKiBAcGFyYW0gY2hlY2tib3hGaWx0ZXIg0JzQtdGC0LDRhNC40LvRjNGC0YAgY2hlY2tib3guXG4gICAgICogQHBhcmFtIGNvbnRyb2xWYWx1ZSDQl9C90LDRh9C10L3QuNC1INC60L7QvdGC0YDQvtC70LAg0YTQvtGA0LzRiyAo0LfQsNC/0LjRgdGMIGlkIOKGkiBib29sZWFuKS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHByb2Nlc3NDaGVja2JveEZpbHRlcihyZXN1bHQ6IFNjUHJvcGVydHlGaWx0ZXJzLCBjaGVja2JveEZpbHRlcjogU2NJQ2hlY2tib3hGaWx0ZXIsIGNvbnRyb2xWYWx1ZTogUmVjb3JkPHN0cmluZywgYm9vbGVhbj4pOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRJZHMgPSBPYmplY3QuZW50cmllcyhjb250cm9sVmFsdWUpXG4gICAgICAgICAgICAuZmlsdGVyKChbLCBpc1NlbGVjdGVkXSkgPT4gaXNTZWxlY3RlZClcbiAgICAgICAgICAgIC5tYXAoKFtpZF0pID0+IGlkKTtcblxuICAgICAgICBpZiAoc2VsZWN0ZWRJZHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc2VjdXJpdHkvZGV0ZWN0LW9iamVjdC1pbmplY3Rpb24sIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgIHJlc3VsdFtjaGVja2JveEZpbHRlci5pZF0gPSBzZWxlY3RlZElkcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0YDQsNCx0LDRgtGL0LLQsNC10YIgcmFuZ2Ug0YTQuNC70YzRgtGALlxuICAgICAqXG4gICAgICogQHBhcmFtIHJlc3VsdCDQntCx0YrQtdC60YIg0YDQtdC30YPQu9GM0YLQsNGC0LAg0LTQu9GPINC30LDQv9C+0LvQvdC10L3QuNGPLlxuICAgICAqIEBwYXJhbSBmaWx0ZXJJZCDQmNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgCDRhNC40LvRjNGC0YDQsC5cbiAgICAgKiBAcGFyYW0gcmFuZ2Ug0JfQvdCw0YfQtdC90LjQtSDQutC+0L3RgtGA0L7Qu9CwINGE0L7RgNC80YsgKNC+0LHRitC10LrRgiDRgSDQs9GA0LDQvdC40YbQsNC80LgpLlxuICAgICAqIEBwYXJhbSByYW5nZS5mcm9tINCd0LDRh9Cw0LvRjNC90L7QtSDQt9C90LDRh9C10L3QuNC1INC00LjQsNC/0LDQt9C+0L3QsC5cbiAgICAgKiBAcGFyYW0gcmFuZ2UudG8g0JrQvtC90LXRh9C90L7QtSDQt9C90LDRh9C10L3QuNC1INC00LjQsNC/0LDQt9C+0L3QsC5cbiAgICAgKi9cbiAgICBwcml2YXRlIHByb2Nlc3NSYW5nZUZpbHRlcihyZXN1bHQ6IFNjUHJvcGVydHlGaWx0ZXJzLCBmaWx0ZXJJZDogc3RyaW5nLCByYW5nZTogeyBmcm9tOiBudW1iZXI7IHRvOiBudW1iZXIgfSk6IHZvaWQge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc2VjdXJpdHkvZGV0ZWN0LW9iamVjdC1pbmplY3Rpb24sIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgIHJlc3VsdFtmaWx0ZXJJZF0gPSB7XG4gICAgICAgICAgICBmcm9tOiBTdHJpbmcocmFuZ2UuZnJvbSksXG4gICAgICAgICAgICB0bzogU3RyaW5nKHJhbmdlLnRvKSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0YDQsNCx0LDRgtGL0LLQsNC10YIgdG9nZ2xlINGE0LjQu9GM0YLRgC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXN1bHQg0J7QsdGK0LXQutGCINGA0LXQt9GD0LvRjNGC0LDRgtCwINC00LvRjyDQt9Cw0L/QvtC70L3QtdC90LjRjy5cbiAgICAgKiBAcGFyYW0gZmlsdGVySWQg0JjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0YTQuNC70YzRgtGA0LAuXG4gICAgICogQHBhcmFtIGNvbnRyb2xWYWx1ZSDQl9C90LDRh9C10L3QuNC1INC60L7QvdGC0YDQvtC70LAg0YTQvtGA0LzRiy5cbiAgICAgKi9cbiAgICBwcml2YXRlIHByb2Nlc3NUb2dnbGVGaWx0ZXIocmVzdWx0OiBTY1Byb3BlcnR5RmlsdGVycywgZmlsdGVySWQ6IHN0cmluZywgY29udHJvbFZhbHVlOiBib29sZWFuKTogdm9pZCB7XG4gICAgICAgIGlmIChjb250cm9sVmFsdWUpIHtcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzZWN1cml0eS9kZXRlY3Qtb2JqZWN0LWluamVjdGlvbiwgbm8tcGFyYW0tcmVhc3NpZ25cbiAgICAgICAgICAgIHJlc3VsdFtmaWx0ZXJJZF0gPSBjb250cm9sVmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodCx0YDQsNGB0YvQstCw0LXRgiDQv9C+0LvQtSDCq9C+0YLCuyDQtNC40LDQv9Cw0LfQvtC90LAg0Log0LzQuNC90LjQvNCw0LvRjNC90L7QvNGDINC30L3QsNGH0LXQvdC40Y4g0YTQuNC70YzRgtGA0LAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmlsdGVySWQg0JjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0YTQuNC70YzRgtGA0LAuXG4gICAgICogQHBhcmFtIG1pbiDQnNC40L3QuNC80LDQu9GM0L3QvtC1INC30L3QsNGH0LXQvdC40LUg0LTQuNCw0L/QsNC30L7QvdCwLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZXNldFJhbmdlRnJvbShmaWx0ZXJJZDogc3RyaW5nLCBtaW46IHN0cmluZyB8IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLmZvcm0uZ2V0KGZpbHRlcklkKT8uZ2V0KCdmcm9tJyk/LnJlc2V0KCttaW4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCh0LHRgNCw0YHRi9Cy0LDQtdGCINC/0L7Qu9C1IMKr0LTQvsK7INC00LjQsNC/0LDQt9C+0L3QsCDQuiDQvNCw0LrRgdC40LzQsNC70YzQvdC+0LzRgyDQt9C90LDRh9C10L3QuNGOINGE0LjQu9GM0YLRgNCwLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZpbHRlcklkINCY0LTQtdC90YLQuNGE0LjQutCw0YLQvtGAINGE0LjQu9GM0YLRgNCwLlxuICAgICAqIEBwYXJhbSBtYXgg0JzQsNC60YHQuNC80LDQu9GM0L3QvtC1INC30L3QsNGH0LXQvdC40LUg0LTQuNCw0L/QsNC30L7QvdCwLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZXNldFJhbmdlVG8oZmlsdGVySWQ6IHN0cmluZywgbWF4OiBzdHJpbmcgfCBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mb3JtLmdldChmaWx0ZXJJZCk/LmdldCgndG8nKT8ucmVzZXQoK21heCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQsdGA0LDRgdGL0LLQsNC10YIg0LLRgdC1INGH0LXQutCx0L7QutGB0Ysg0LPRgNGD0L/Qv9GLINCyIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmlsdGVySWQg0JjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0YTQuNC70YzRgtGA0LAgKNC60LvRjtGHIEZvcm1Hcm91cCDQsiDRhNC+0YDQvNC1KS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVzZXRDaGVja2JveEdyb3VwKGZpbHRlcklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAgICAgY29uc3QgZ3JvdXAgPSB0aGlzLmZvcm0uZ2V0KGZpbHRlcklkKSBhcyBGb3JtR3JvdXA8UmVjb3JkPHN0cmluZywgRm9ybUNvbnRyb2w8Ym9vbGVhbj4+PiB8IG51bGw7XG5cbiAgICAgICAgaWYgKCFncm91cCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzZXRWYWx1ZTogUmVjb3JkPHN0cmluZywgYm9vbGVhbj4gPSB7fTtcbiAgICAgICAgT2JqZWN0LmtleXMoZ3JvdXAuY29udHJvbHMpLmZvckVhY2goKGlkKSA9PiB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc2VjdXJpdHkvZGV0ZWN0LW9iamVjdC1pbmplY3Rpb25cbiAgICAgICAgICAgIHJlc2V0VmFsdWVbaWRdID0gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgICAgICBncm91cC5yZXNldChyZXNldFZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodCx0YDQsNGB0YvQstCw0LXRgiDQstGB0LUg0YTQuNC70YzRgtGA0Ysg0Lgg0L7Qv9C+0LLQtdGJ0LDQtdGCINGA0L7QtNC40YLQtdC70Y8g0L4g0L3QsNC20LDRgtC40Lgg0LrQvdC+0L/QutC4INGB0LHRgNC+0YHQsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgb25SZXNldEZpbHRlcnNDbGljaygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5yZXNldEFsbEZpbHRlcnMoKTtcbiAgICAgICAgdGhpcy5yZXNldEZpbHRlcnMuZW1pdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCe0L/QvtCy0LXRidCw0LXRgiDRgNC+0LTQuNGC0LXQu9GPINC+INC90LDQttCw0YLQuNC4INC60L3QvtC/0LrQuCDQv9C+0LrQsNC30LAg0YDQtdC30YPQu9GM0YLQsNGC0L7Qsi5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgb25TaG93UmVzdWx0c0NsaWNrKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNob3dSZXN1bHRzLmVtaXQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodCx0YDQsNGB0YvQstCw0LXRgiDQstGB0LUg0YTQuNC70YzRgtGA0Ysg0Log0LjRgdGF0L7QtNC90YvQvCDQt9C90LDRh9C10L3QuNGP0LwuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZXNldEFsbEZpbHRlcnMoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZmlsdGVycygpPy5mb3JFYWNoKChmaWx0ZXJJdGVtKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBjb250cm9sID0gdGhpcy5mb3JtLmdldChmaWx0ZXJJdGVtLmlkKTtcblxuICAgICAgICAgICAgaWYgKCFjb250cm9sKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzd2l0Y2ggKGZpbHRlckl0ZW0udHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNrYm94Jzoge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBncm91cCA9IGNvbnRyb2wgYXMgRm9ybUdyb3VwPFJlY29yZDxzdHJpbmcsIEZvcm1Db250cm9sPGJvb2xlYW4+Pj47XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc2V0VmFsdWU6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+ID0ge307XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5rZXlzKGdyb3VwLmNvbnRyb2xzKS5mb3JFYWNoKChpZCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHNlY3VyaXR5L2RldGVjdC1vYmplY3QtaW5qZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICByZXNldFZhbHVlW2lkXSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXAucmVzZXQocmVzZXRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGUnOlxuICAgICAgICAgICAgICAgICAgICBjb250cm9sLnJlc2V0KGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAncmFuZ2UnOiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGdyb3VwID0gY29udHJvbCBhcyBGb3JtR3JvdXA7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1pbiA9ICtmaWx0ZXJJdGVtLm1pbjtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF4ID0gK2ZpbHRlckl0ZW0ubWF4O1xuICAgICAgICAgICAgICAgICAgICBncm91cC5yZXNldCh7IGZyb206IG1pbiwgdG86IG1heCwgc2xpZGVyOiBbbWluLCBtYXhdIH0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbn1cbiIsIkBpZiAoZmlsdGVycygpPy5sZW5ndGgpIHtcbiAgICA8Zm9ybVxuICAgICAgICBbZm9ybUdyb3VwXT1cImZvcm1cIlxuICAgICAgICBjbGFzcz1cImZsZXggZmxleC1jb2wgcGItMVwiXG4gICAgPlxuICAgICAgICBAZm9yIChmaWx0ZXIgb2YgZmlsdGVycygpOyB0cmFjayBmaWx0ZXIuaWQ7IGxldCBpc0ZpcnN0ID0gJGZpcnN0KSB7XG4gICAgICAgICAgICBAaWYgKCFpc0ZpcnN0KSB7XG4gICAgICAgICAgICAgICAgPGhyIGNsYXNzPVwibXktMyB3LWZ1bGwgaC1weFwiIC8+XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0yXCI+XG4gICAgICAgICAgICAgICAgPCEtLSDQl9Cw0LPQvtC70L7QstC+0Log0LPRgNGD0L/Qv9GLLiDQlNC70Y8gdG9nZ2xlINC/0L7QtNC/0LjRgdC4INC90LXRgjog0LzQtdGC0LrQsCDQuNC00ZHRgiDQv9GA0Y/QvNC+INGA0Y/QtNC+0Lwg0YEg0YHQsNC80LjQvCBjaGVja2JveC4gLS0+XG4gICAgICAgICAgICAgICAgQGlmIChmaWx0ZXIudHlwZSAhPT0gJ3RvZ2dsZScpIHtcbiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwidGV4dC1ib2R5LXMtYm9sZFwiPnt7IGZpbHRlci5sYWJlbCB9fTwvbGFiZWw+XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgPCEtLSBDaGVja2JveDogRm9ybUdyb3VwKHZhbHVlLmlkIOKGkiBib29sZWFuKSDQtNC70Y8g0LvRjtCx0L7Qs9C+INGH0LjRgdC70LAg0LfQvdCw0YfQtdC90LjQuS5cbiAgICAgICAgICAgICAgICAgICAgINCg0LDQt9Cy0LjQu9C60LAg0L7QtNC90L4v0LzQvdC+0LPQviDQt9C90LDRh9C10L3QuNC5INCy0YvQvdC10YHQtdC90LAg0LIgVFMgKNGB0LwuIHByb2Nlc3NDaGVja2JveEZpbHRlcikuXG4gICAgICAgICAgICAgICAgICAgICBuZy10ZW1wbGF0ZSDQstC90YPRgtGA0LggZm9ybUdyb3VwTmFtZTog0LjQvdCw0YfQtSByZWFjdGl2ZSBmb3JtcyDQvdC1INC90LDQudC00ZHRgiBDb250cm9sQ29udGFpbmVyINC/0YDQuCDQv9GA0L7QtdC60YbQuNC4INCyINC00L7Rh9C10YDQvdC40Lkg0LrQvtC80L/QvtC90LXQvdGCLiAtLT5cbiAgICAgICAgICAgICAgICBAaWYgKGZpbHRlci50eXBlID09PSAnY2hlY2tib3gnKSB7XG4gICAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtMlwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbZm9ybUdyb3VwTmFtZV09XCJmaWx0ZXIuaWRcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c2MtY2F0YWxvZy1maWx0ZXItY29sbGFwc2libGVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbaXRlbXNDb3VudF09XCJmaWx0ZXIudmFsdWVzLmxlbmd0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3Nob3dSZXNldF09XCJmb3JtLmdldChmaWx0ZXIuaWQpPy5kaXJ0eSA/PyBmYWxzZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHJlc2V0R3JvdXApPVwicmVzZXRDaGVja2JveEdyb3VwKGZpbHRlci5pZClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxuZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBmb3IgKHZhbHVlIG9mIGZpbHRlci52YWx1ZXM7IHRyYWNrIHZhbHVlLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xOYW1lXT1cInZhbHVlLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aUNoZWNrYm94XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInRleHQtYm9keS1zXCI+e3sgdmFsdWUubGFiZWwgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc2MtY2F0YWxvZy1maWx0ZXItY29sbGFwc2libGU+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgIDwhLS0gVG9nZ2xlOiDQvtC00LjQvSBib29sZWFuINC90LAg0LrQvtGA0L3QtSDRhNC+0YDQvNGLLCDQv9C+0LTQv9C40YHRjCA9IGZpbHRlci5sYWJlbCAtLT5cbiAgICAgICAgICAgICAgICB9IEBlbHNlIGlmIChmaWx0ZXIudHlwZSA9PT0gJ3RvZ2dsZScpIHtcbiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwiZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbE5hbWVdPVwiZmlsdGVyLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlDaGVja2JveFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LWJvZHktcy1ib2xkXCI+e3sgZmlsdGVyLmxhYmVsIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPlxuXG4gICAgICAgICAgICAgICAgICAgIDwhLS0gUmFuZ2U6IEZvcm1Hcm91cChmcm9tLCB0bywgc2xpZGVyKSDRgSDQtNCy0YPRgdGC0L7RgNC+0L3QvdC10Lkg0YHQuNC90YXRgNC+0L3QuNC30LDRhtC40LXQuSAtLT5cbiAgICAgICAgICAgICAgICB9IEBlbHNlIGlmIChmaWx0ZXIudHlwZSA9PT0gJ3JhbmdlJykge1xuICAgICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgICBbZm9ybUdyb3VwTmFtZV09XCJmaWx0ZXIuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0zXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZ2FwLTMgcHgtMVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlMYWJlbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1pbi13LTAgZmxleC0xXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgINCe0YJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS10ZXh0ZmllbGQgW3R1aVRleHRmaWVsZENsZWFuZXJdPVwiZmFsc2VcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjU2VsZWN0T25Gb2N1c2luXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpSW5wdXROdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJmcm9tXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdHVpTnVtYmVyRm9ybWF0XT1cInsgcHJlY2lzaW9uOiAwIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttaW5dPVwiK2ZpbHRlci5taW5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttYXhdPVwiK2ZpbHRlci5tYXhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9jb21wbGV0ZT1cIm9mZlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChmb3JtLmdldChmaWx0ZXIuaWQpPy5nZXQoJ2Zyb20nKT8uZGlydHkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aUljb25CdXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9XCJ4c1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGVhcmFuY2U9XCJpY29uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWNvblN0YXJ0PVwiQHR1aS54XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlc2V0UmFuZ2VGcm9tKGZpbHRlci5pZCwgZmlsdGVyLm1pbilcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID48L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90dWktdGV4dGZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aUxhYmVsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibWluLXctMCBmbGV4LTFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg0JTQvlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHVpLXRleHRmaWVsZCBbdHVpVGV4dGZpZWxkQ2xlYW5lcl09XCJmYWxzZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NTZWxlY3RPbkZvY3VzaW5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlJbnB1dE51bWJlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInRvXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdHVpTnVtYmVyRm9ybWF0XT1cInsgcHJlY2lzaW9uOiAwIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttaW5dPVwiK2ZpbHRlci5taW5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttYXhdPVwiK2ZpbHRlci5tYXhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9jb21wbGV0ZT1cIm9mZlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChmb3JtLmdldChmaWx0ZXIuaWQpPy5nZXQoJ3RvJyk/LmRpcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlJY29uQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPVwieHNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBlYXJhbmNlPVwiaWNvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGljb25TdGFydD1cIkB0dWkueFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJyZXNldFJhbmdlVG8oZmlsdGVyLmlkLCBmaWx0ZXIubWF4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPjwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3R1aS10ZXh0ZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICA8dHVpLXJhbmdlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT1cIm1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInNsaWRlclwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW21pbl09XCIrZmlsdGVyLm1pblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW21heF09XCIrZmlsdGVyLm1heFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLi0tdHVpLXRoaWNrbmVzcy5yZW1dPVwiMC4yNVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICB0dWlCdXR0b25cbiAgICAgICAgICAgIGFwcGVhcmFuY2U9XCJzZWNvbmRhcnlcIlxuICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICBjbGFzcz1cIm10LTJcIlxuICAgICAgICAgICAgKGNsaWNrKT1cIm9uUmVzZXRGaWx0ZXJzQ2xpY2soKVwiXG4gICAgICAgID5cbiAgICAgICAgICAgINCh0LHRgNC+0YHQuNGC0Ywg0YTQuNC70YzRgtGA0YtcbiAgICAgICAgPC9idXR0b24+XG4gICAgICAgIEBpZiAoc2hvd1Jlc3VsdHNCdXR0b24oKSkge1xuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIHR1aUJ1dHRvblxuICAgICAgICAgICAgICAgIGFwcGVhcmFuY2U9XCJwcmltYXJ5XCJcbiAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cIm10LTJcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJvblNob3dSZXN1bHRzQ2xpY2soKVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAg0J/QvtC60LDQt9Cw0YLRjCDRgNC10LfRg9C70YzRgtCw0YLRi1xuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIH1cbiAgICA8L2Zvcm0+XG59XG4iXX0=