@snabcentr/client-ui 3.52.1 → 3.52.2

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,31 @@ 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.filter((item) => item.type !== 'range' || item.min !== item.max)), tap((filters) => {
68
+ this.updateFormControls(filters);
69
+ }), share()));
70
+ inject(DestroyRef).onDestroy(() => {
71
+ this.formSyncs.unsubscribe();
72
+ });
73
+ this.form.valueChanges.pipe(debounceTime(0), takeUntilDestroyed()).subscribe((filters) => {
58
74
  this.catalogProductsFilters$.next(this.buildPropertyFilters(filters));
59
75
  });
60
76
  }
@@ -64,17 +80,28 @@ export class ScCatalogFiltersComponent {
64
80
  * @param filters Массив фильтров для создания контролов.
65
81
  */
66
82
  updateFormControls(filters) {
83
+ this.formSyncs.unsubscribe();
84
+ this.formSyncs = new Subscription();
67
85
  Object.keys(this.form.controls).forEach((key) => {
68
86
  this.form.removeControl(key, { emitEvent: false });
69
87
  });
70
88
  filters.forEach((item) => {
71
89
  switch (item.type) {
72
- case 'checkbox':
73
- this.form.addControl(item.id, this.createCheckboxFormControl(item), { emitEvent: false });
90
+ case 'checkbox': {
91
+ const checkboxControl = this.createCheckboxFormControl(item);
92
+ this.form.addControl(item.id, checkboxControl, { emitEvent: false });
93
+ // Single-select для !isMultiple: при выборе одного остальные снимаются.
94
+ if (!item.isMultiple && item.values.length > 1) {
95
+ this.formSyncs.add(this.syncSingleSelectCheckbox(checkboxControl));
96
+ }
74
97
  break;
75
- case 'range':
76
- this.form.addControl(item.id, this.createRangeFormControl(item), { emitEvent: false });
98
+ }
99
+ case 'range': {
100
+ const rangeControl = this.createRangeFormControl(item);
101
+ this.form.addControl(item.id, rangeControl, { emitEvent: false });
102
+ this.formSyncs.add(this.syncRangeFromToAndSlider(rangeControl));
77
103
  break;
104
+ }
78
105
  case 'toggle':
79
106
  this.form.addControl(item.id, this.createToggleFormControl(item), { emitEvent: false });
80
107
  break;
@@ -98,7 +125,7 @@ export class ScCatalogFiltersComponent {
98
125
  }
99
126
  switch (filterItem.type) {
100
127
  case 'checkbox':
101
- this.processCheckboxFilter(result, filterItem.id, controlValue);
128
+ this.processCheckboxFilter(result, filterItem, controlValue);
102
129
  break;
103
130
  case 'range':
104
131
  this.processRangeFilter(result, filterItem.id, controlValue);
@@ -110,34 +137,111 @@ export class ScCatalogFiltersComponent {
110
137
  break;
111
138
  }
112
139
  });
140
+ console.log(result);
113
141
  return result;
114
142
  }
115
143
  /**
116
- * Создает контрол формы для фильтра типа checkbox.
144
+ * Создаёт FormGroup для checkbox: на каждый {@code value.id} — булевый контрол.
117
145
  *
118
- * Если `isMultiple === false` возвращает {@link FormControl} строкового идентификатора (логика radio),
119
- * иначе {@link FormGroup} независимых булевых контролов по идентификаторам значений.
146
+ * Единый формат и для одного, и для множества значений: шаблон рендерит их одинаково.
147
+ * Различие в API-выводе для одиночного значения (boolean вместо массива) обрабатывается в {@link processCheckboxFilter}.
120
148
  *
121
149
  * @param checkboxFilter Фильтр типа checkbox.
122
150
  */
123
151
  createCheckboxFormControl(checkboxFilter) {
124
- if (!checkboxFilter.isMultiple) {
125
- return new FormControl(null);
126
- }
152
+ const isSelected = (id) => checkboxFilter.selectedValues?.includes(id) ?? false;
127
153
  const controls = {};
128
154
  checkboxFilter.values.forEach((value) => {
129
- controls[value.id] = new FormControl(false, { nonNullable: true });
155
+ controls[value.id] = new FormControl(isSelected(value.id), { nonNullable: true });
130
156
  });
131
157
  return new FormGroup(controls);
132
158
  }
133
159
  /**
134
- * Создает FormControl для range.
160
+ * Создаёт {@link FormGroup} для range: {@code from}, {@code to}, {@code slider} (кортеж для {@link TuiRange}).
135
161
  *
136
162
  * @param rangeFilter Фильтр типа range.
137
163
  */
138
164
  createRangeFormControl(rangeFilter) {
139
- // TODO: Добавить updateOn: 'blur' после исправления бага в taiga-ui.
140
- return new FormControl([Number(rangeFilter.selectedMin ?? rangeFilter.min), Number(rangeFilter.selectedMax ?? rangeFilter.max)], { nonNullable: true });
165
+ const fromValue = Number(rangeFilter.selectedMin ?? rangeFilter.min);
166
+ const toValue = Number(rangeFilter.selectedMax ?? rangeFilter.max);
167
+ return new FormGroup({
168
+ from: new FormControl(fromValue, { nonNullable: true }),
169
+ to: new FormControl(toValue, { nonNullable: true }),
170
+ slider: new FormControl([fromValue, toValue], { nonNullable: true }),
171
+ });
172
+ }
173
+ /**
174
+ * Реализует single-select поведение для FormGroup с булевыми контролами:
175
+ * при появлении нового true остальные контролы группы сбрасываются в false.
176
+ *
177
+ * Сохраняет последнее «стабильное» состояние и сравнивает следующее значение с ним —
178
+ * новый true (отсутствовал в prev) считается выбранным, остальные сбрасываются через setValue.
179
+ *
180
+ * @param group FormGroup checkbox-фильтра (id → boolean).
181
+ */
182
+ syncSingleSelectCheckbox(group) {
183
+ let previousState = group.getRawValue();
184
+ return group.valueChanges.subscribe((value) => {
185
+ const current = value;
186
+ const newlyChecked = Object.entries(current).find(([id, isChecked]) => {
187
+ // eslint-disable-next-line security/detect-object-injection
188
+ return isChecked && !previousState[id];
189
+ })?.[0];
190
+ if (!newlyChecked) {
191
+ previousState = { ...current };
192
+ return;
193
+ }
194
+ const next = {};
195
+ Object.keys(group.controls).forEach((id) => {
196
+ // eslint-disable-next-line security/detect-object-injection
197
+ next[id] = id === newlyChecked;
198
+ });
199
+ previousState = next;
200
+ group.setValue(next);
201
+ });
202
+ }
203
+ /**
204
+ * Связывает поля «от»/«до» с контролом слайдера.
205
+ *
206
+ * @param group FormGroup range-фильтра.
207
+ */
208
+ syncRangeFromToAndSlider(group) {
209
+ const from = group.get('from');
210
+ const to = group.get('to');
211
+ const slider = group.get('slider');
212
+ if (!from || !to || !slider) {
213
+ return new Subscription();
214
+ }
215
+ const sub = new Subscription();
216
+ // Инпуты → слайдер; если «от» > «до», поднимаем «до» до «от».
217
+ const applySliderFromInputs = () => {
218
+ const low = Number(from.value);
219
+ let high = Number(to.value);
220
+ if (low > high) {
221
+ high = low;
222
+ to.setValue(high, { emitEvent: false });
223
+ }
224
+ const currentPair = slider.value;
225
+ if (currentPair[0] !== low || currentPair[1] !== high) {
226
+ slider.setValue([low, high], { emitEvent: false });
227
+ slider.markAsDirty();
228
+ }
229
+ };
230
+ sub.add(merge(from.valueChanges, to.valueChanges).subscribe(applySliderFromInputs));
231
+ sub.add(slider.valueChanges.subscribe((value) => {
232
+ const [low, high] = value;
233
+ if (from.value !== low) {
234
+ from.setValue(low, { emitEvent: false });
235
+ from.markAsDirty();
236
+ }
237
+ if (to.value !== high) {
238
+ to.setValue(high, { emitEvent: false });
239
+ to.markAsDirty();
240
+ }
241
+ }));
242
+ // Совпасть с полями при первом показе (уже совпадает при создании, но на всякий случай).
243
+ applySliderFromInputs();
244
+ return sub;
141
245
  }
142
246
  /**
143
247
  * Создает FormControl для toggle.
@@ -148,45 +252,36 @@ export class ScCatalogFiltersComponent {
148
252
  return new FormControl(toggleFilter.selectedValue ?? false, { nonNullable: true });
149
253
  }
150
254
  /**
151
- * Обрабатывает checkbox фильтр.
255
+ * Обрабатывает checkbox: FormGroup → string[] выбранных id; для единственного значения — boolean (как toggle).
152
256
  *
153
257
  * @param result Объект результата для заполнения.
154
- * @param filterId Идентификатор фильтра.
155
- * @param controlValue Значение контрола формы.
258
+ * @param checkboxFilter Метафильтр checkbox.
259
+ * @param controlValue Значение контрола формы (запись id → boolean).
156
260
  */
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 выбранных значений).
261
+ processCheckboxFilter(result, checkboxFilter, controlValue) {
167
262
  const selectedIds = Object.entries(controlValue)
168
263
  .filter(([, isSelected]) => isSelected)
169
264
  .map(([id]) => id);
170
- if (selectedIds.length > 0) {
171
- // eslint-disable-next-line security/detect-object-injection, no-param-reassign
172
- result[filterId] = selectedIds;
265
+ if (selectedIds.length === 0) {
266
+ return;
173
267
  }
268
+ // eslint-disable-next-line security/detect-object-injection, no-param-reassign
269
+ result[checkboxFilter.id] = selectedIds;
174
270
  }
175
271
  /**
176
272
  * Обрабатывает range фильтр.
177
273
  *
178
274
  * @param result Объект результата для заполнения.
179
275
  * @param filterId Идентификатор фильтра.
180
- * @param controlValue Значение контрола формы.
181
- * @param controlValue.0 Начальное значение диапазона.
182
- * @param controlValue.1 Конечное значение диапазона.
276
+ * @param range Значение контрола формы (объект с границами).
277
+ * @param range.from Начальное значение диапазона.
278
+ * @param range.to Конечное значение диапазона.
183
279
  */
184
- processRangeFilter(result, filterId, [from, to]) {
185
- // Для range: FormControl<[number, number]> -> { from?: string; to?: string; }
280
+ processRangeFilter(result, filterId, range) {
186
281
  // eslint-disable-next-line security/detect-object-injection, no-param-reassign
187
282
  result[filterId] = {
188
- from: String(from),
189
- to: String(to),
283
+ from: String(range.from),
284
+ to: String(range.to),
190
285
  };
191
286
  }
192
287
  /**
@@ -197,17 +292,110 @@ export class ScCatalogFiltersComponent {
197
292
  * @param controlValue Значение контрола формы.
198
293
  */
199
294
  processToggleFilter(result, filterId, controlValue) {
200
- // Для toggle: FormControl<boolean> -> boolean
201
295
  if (controlValue) {
202
296
  // eslint-disable-next-line security/detect-object-injection, no-param-reassign
203
297
  result[filterId] = controlValue;
204
298
  }
205
299
  }
300
+ /**
301
+ * Сбрасывает поле «от» диапазона к минимальному значению фильтра.
302
+ *
303
+ * @param filterId Идентификатор фильтра.
304
+ * @param min Минимальное значение диапазона.
305
+ */
306
+ resetRangeFrom(filterId, min) {
307
+ this.form.get(filterId)?.get('from')?.reset(+min);
308
+ }
309
+ /**
310
+ * Сбрасывает поле «до» диапазона к максимальному значению фильтра.
311
+ *
312
+ * @param filterId Идентификатор фильтра.
313
+ * @param max Максимальное значение диапазона.
314
+ */
315
+ resetRangeTo(filterId, max) {
316
+ this.form.get(filterId)?.get('to')?.reset(+max);
317
+ }
318
+ /**
319
+ * Сбрасывает все чекбоксы группы в `false`.
320
+ *
321
+ * @param filterId Идентификатор фильтра (ключ FormGroup в форме).
322
+ */
323
+ resetCheckboxGroup(filterId) {
324
+ const group = this.form.get(filterId);
325
+ if (!group) {
326
+ return;
327
+ }
328
+ const resetValue = {};
329
+ Object.keys(group.controls).forEach((id) => {
330
+ // eslint-disable-next-line security/detect-object-injection
331
+ resetValue[id] = false;
332
+ });
333
+ group.reset(resetValue);
334
+ }
335
+ /**
336
+ * Сбрасывает все фильтры и оповещает родителя о нажатии кнопки сброса.
337
+ */
338
+ onResetFiltersClick() {
339
+ this.resetAllFilters();
340
+ this.resetFilters.emit();
341
+ }
342
+ /**
343
+ * Оповещает родителя о нажатии кнопки показа результатов.
344
+ */
345
+ onShowResultsClick() {
346
+ this.showResults.emit();
347
+ }
348
+ /**
349
+ * Сбрасывает все фильтры к исходным значениям.
350
+ */
351
+ resetAllFilters() {
352
+ this.filters()?.forEach((filterItem) => {
353
+ const control = this.form.get(filterItem.id);
354
+ if (!control) {
355
+ return;
356
+ }
357
+ switch (filterItem.type) {
358
+ case 'checkbox': {
359
+ const group = control;
360
+ const resetValue = {};
361
+ Object.keys(group.controls).forEach((id) => {
362
+ // eslint-disable-next-line security/detect-object-injection
363
+ resetValue[id] = false;
364
+ });
365
+ group.reset(resetValue);
366
+ break;
367
+ }
368
+ case 'toggle':
369
+ control.reset(false);
370
+ break;
371
+ case 'range': {
372
+ const group = control;
373
+ const min = +filterItem.min;
374
+ const max = +filterItem.max;
375
+ group.reset({ from: min, to: max, slider: [min, max] });
376
+ break;
377
+ }
378
+ default:
379
+ break;
380
+ }
381
+ });
382
+ }
206
383
  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 }); }
384
+ 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
385
  }
209
386
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScCatalogFiltersComponent, decorators: [{
210
387
  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"] }]
388
+ args: [{ standalone: true, selector: 'sc-catalog-filters', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
389
+ ReactiveFormsModule,
390
+ TuiTextfield,
391
+ ScSelectOnFocusinDirective,
392
+ ScCatalogFilterCollapsibleComponent,
393
+ TuiLabel,
394
+ TuiNumberFormat,
395
+ TuiCheckbox,
396
+ TuiInputNumber,
397
+ TuiRange,
398
+ TuiButton,
399
+ ], 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
400
  }], 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
401
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2MtY2F0YWxvZy1maWx0ZXJzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NsaWVudC11aS9jYXRhbG9nL2NhdGFsb2ctZmlsdGVycy9zYy1jYXRhbG9nLWZpbHRlcnMuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NhdGFsb2cvY2F0YWxvZy1maWx0ZXJzL3NjLWNhdGFsb2ctZmlsdGVycy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFFM0MsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdEcsT0FBTyxFQUFFLGtCQUFrQixFQUFFLFFBQVEsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQzFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsU0FBUyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0UsT0FBTyxFQUNILGdCQUFnQixFQUVoQixzQkFBc0IsRUFFdEIsY0FBYyxHQUlqQixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDN0MsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsZUFBZSxFQUFFLFlBQVksRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BGLE9BQU8sRUFBRSxXQUFXLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0RSxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ2xDLE9BQU8sRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsWUFBWSxFQUFFLFNB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SSxZQUNOLG9CQUFvQixtQkFHYix1QkFBdUIsQ0FBQyxNQUFNLFdBQ3RDO3dCQUNMLG1CQUFtQjt3QkFDbkIsWUFBWTt3QkFDWiwwQkFBMEI7d0JBQzFCLG1DQUFtQzt3QkFDbkMsUUFBUTt3QkFDUixlQUFlO3dCQUNmLFdBQVc7d0JBQ1gsY0FBYzt3QkFDZCxRQUFRO3dCQUNSLFNBQVM7cUJBQ1oiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzICovXG5cbmltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIERlc3Ryb3lSZWYsIGluamVjdCwgaW5wdXQsIG91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkLCB0b1NpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IEZvcm1Db250cm9sLCBGb3JtR3JvdXAsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge1xuICAgIFNDX0NBVEVHT1JZX0lORk8sXG4gICAgU2NDYXRhbG9nRmlsdGVyLFxuICAgIFNjQ2F0YWxvZ0ZpbHRlclNlcnZpY2UsXG4gICAgU2NJQ2hlY2tib3hGaWx0ZXIsXG4gICAgU2NJZE9yU2x1Z1BpcGUsXG4gICAgU2NQcm9wZXJ0eUZpbHRlcnMsXG4gICAgU2NSYW5nZUZpbHRlcixcbiAgICBTY1RvZ2dsZUZpbHRlcixcbn0gZnJvbSAnQHNuYWJjZW50ci9jbGllbnQtY29yZSc7XG5pbXBvcnQgeyB0dWlJc1ByZXNlbnQgfSBmcm9tICdAdGFpZ2EtdWkvY2RrJztcbmltcG9ydCB7IFR1aUJ1dHRvbiwgVHVpTGFiZWwsIFR1aU51bWJlckZvcm1hdCwgVHVpVGV4dGZpZWxkIH0gZnJvbSAnQHRhaWdhLXVpL2NvcmUnO1xuaW1wb3J0IHsgVHVpQ2hlY2tib3gsIFR1aUlucHV0TnVtYmVyLCBUdWlSYW5nZSB9IGZyb20gJ0B0YWlnYS11aS9raXQnO1xuaW1wb3J0IHsgaXNOaWwgfSBmcm9tICdsb2Rhc2gtZXMnO1xuaW1wb3J0IHsgY2F0Y2hFcnJvciwgZGVib3VuY2VUaW1lLCBFTVBUWSwgZmlsdGVyLCBtYXAsIG1lcmdlLCBzaGFyZSwgU3Vic2NyaXB0aW9uLCBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBTY1NlbGVjdE9uRm9jdXNpbkRpcmVjdGl2ZSB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvc2VsZWN0LW9uLWZvY3VzaW4vc2Mtc2VsZWN0LW9uLWZvY3VzaW4uZGlyZWN0aXZlJztcbmltcG9ydCB7IFNjQ2F0YWxvZ0ZpbHRlckNvbGxhcHNpYmxlQ29tcG9uZW50IH0gZnJvbSAnLi9jb2xsYXBzaWJsZS9zYy1jYXRhbG9nLWZpbHRlci1jb2xsYXBzaWJsZS5jb21wb25lbnQnO1xuaW1wb3J0IHsgU0NfQ0FUQUxPR19QUk9EVUNUU19GSUxURVJTIH0gZnJvbSAnLi90b2tlbnMvc2MtY2F0YWxvZy1wcm9kdWN0cy1maWx0ZXJzJztcbmltcG9ydCB7IFNDX0NBVEFMT0dfU0hPV19QUk9EVUNUU19SRUNVUlNJVkVMWSB9IGZyb20gJy4vdG9rZW5zL3NjLWNhdGFsb2ctc2hvdy1wcm9kdWN0cy1yZWN1cnNpdmVseSc7XG5cbi8qKlxuICog0JrQvtC80L/QvtC90LXQvdGCINCy0YvQstC+0LTQsCDRhNC40LvRjNGC0YDQvtCyINC60LDRgtCw0LvQvtCz0LAuXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc2VsZWN0b3I6ICdzYy1jYXRhbG9nLWZpbHRlcnMnLFxuICAgIHN0eWxlVXJsOiAnLi9zYy1jYXRhbG9nLWZpbHRlcnMuY29tcG9uZW50LnNjc3MnLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9zYy1jYXRhbG9nLWZpbHRlcnMuY29tcG9uZW50Lmh0bWwnLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICAgIGltcG9ydHM6IFtcbiAgICAgICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgICAgICAgVHVpVGV4dGZpZWxkLFxuICAgICAgICBTY1NlbGVjdE9uRm9jdXNpbkRpcmVjdGl2ZSxcbiAgICAgICAgU2NDYXRhbG9nRmlsdGVyQ29sbGFwc2libGVDb21wb25lbnQsXG4gICAgICAgIFR1aUxhYmVsLFxuICAgICAgICBUdWlOdW1iZXJGb3JtYXQsXG4gICAgICAgIFR1aUNoZWNrYm94LFxuICAgICAgICBUdWlJbnB1dE51bWJlcixcbiAgICAgICAgVHVpUmFuZ2UsXG4gICAgICAgIFR1aUJ1dHRvbixcbiAgICBdLFxufSlcbmV4cG9ydCBjbGFzcyBTY0NhdGFsb2dGaWx0ZXJzQ29tcG9uZW50IHtcbiAgICAvKipcbiAgICAgKiDQn9C+0LTQv9C40YHQutC4INGB0LjQvdGF0YDQvtC90LjQt9Cw0YbQuNC4INC60L7QvdGC0YDQvtC70L7QsiDRhNC+0YDQvNGLIChyYW5nZSBzbGlkZXIsIHNpbmdsZS1zZWxlY3QgY2hlY2tib3gpLlxuICAgICAqL1xuICAgIHByaXZhdGUgZm9ybVN5bmNzID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuXG4gICAgLyoqXG4gICAgICog0KHQtdGA0LLQuNGBINC00LvRjyDRgNCw0LHQvtGC0Ysg0YEg0YTQuNC70YzRgtGA0LDQvNC4INC60LDRgtCw0LvQvtCz0LAuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBjYXRhbG9nRmlsdGVyU2VydmljZTogU2NDYXRhbG9nRmlsdGVyU2VydmljZSA9IGluamVjdChTY0NhdGFsb2dGaWx0ZXJTZXJ2aWNlKTtcblxuICAgIC8qKlxuICAgICAqINCf0LDQudC/LCDQstC+0LfQstGA0LDRidCw0Y7RidC40Lkg0LjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0LjQu9C4INGB0LjQvNCy0L7Qu9GM0L3QvtC1INC+0LHQvtC30L3QsNGH0LXQvdC40LUgKHNsdWcpINC40YHRhdC+0LTRjyDQuNC3INC90LDRgdGC0YDQvtC10Log0L7QutGA0YPQttC10L3QuNGPLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaWRPclNsdWdQaXBlOiBTY0lkT3JTbHVnUGlwZSA9IGluamVjdChTY0lkT3JTbHVnUGlwZSk7XG5cbiAgICAvKipcbiAgICAgKiBTdWJqZWN0INC00LvRjyDRhdGA0LDQvdC10L3QuNGPINGE0LjQu9GM0YLRgNC+0LIg0L/RgNC+0LTRg9C60YLQvtCyLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY2F0YWxvZ1Byb2R1Y3RzRmlsdGVycyQgPSBpbmplY3QoU0NfQ0FUQUxPR19QUk9EVUNUU19GSUxURVJTKTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC30L3QsNC6INC90LXQvtCx0YXQvtC00LjQvNC+0YHRgtC4INC+0YLQvtCx0YDQsNC20LDRgtGMINGE0LjQu9GM0YLRgNGLINC00LvRjyDQstC70L7QttC10L3QvdGL0YUg0LrQsNGC0LXQs9C+0YDQuNC5LlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgaXNSZWN1cnNpdmVseSA9IGluamVjdChTQ19DQVRBTE9HX1NIT1dfUFJPRFVDVFNfUkVDVVJTSVZFTFkpO1xuXG4gICAgLyoqXG4gICAgICog0J/QvtC60LDQt9GL0LLQsNGC0Ywg0LvQuCDQutC90L7Qv9C60YMgwqvQn9C+0LrQsNC30LDRgtGMINGA0LXQt9GD0LvRjNGC0LDRgtGLwrsuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IHNob3dSZXN1bHRzQnV0dG9uID0gaW5wdXQoZmFsc2UpO1xuXG4gICAgLyoqXG4gICAgICog0KHQvtCx0YvRgtC40LUg0L3QsNC20LDRgtC40Y8g0L3QsCDQutC90L7Qv9C60YMg0YHQsdGA0L7RgdCwINCy0YHQtdGFINGE0LjQu9GM0YLRgNC+0LIuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IHJlc2V0RmlsdGVycyA9IG91dHB1dCgpO1xuXG4gICAgLyoqXG4gICAgICog0KHQvtCx0YvRgtC40LUg0L3QsNC20LDRgtC40Y8g0L3QsCDQutC90L7Qv9C60YMg0L/QvtC60LDQt9CwINGA0LXQt9GD0LvRjNGC0LDRgtC+0LIuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IHNob3dSZXN1bHRzID0gb3V0cHV0KCk7XG5cbiAgICAvKipcbiAgICAgKiBGb3JtR3JvdXAg0LTQu9GPINGE0LjQu9GM0YLRgNC+0LIuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGZvcm0gPSBuZXcgRm9ybUdyb3VwPFxuICAgICAgICBSZWNvcmQ8c3RyaW5nLCBSZXR1cm5UeXBlPHR5cGVvZiB0aGlzLmNyZWF0ZUNoZWNrYm94Rm9ybUNvbnRyb2w+IHwgUmV0dXJuVHlwZTx0eXBlb2YgdGhpcy5jcmVhdGVSYW5nZUZvcm1Db250cm9sPiB8IFJldHVyblR5cGU8dHlwZW9mIHRoaXMuY3JlYXRlVG9nZ2xlRm9ybUNvbnRyb2w+PlxuICAgID4oe30pO1xuXG4gICAgLyoqXG4gICAgICoge0BsaW5rIE9ic2VydmFibGV9INGE0LjQu9GM0YLRgNC+0LIg0LrQsNGC0LXQs9C+0YDQuNC4LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBmaWx0ZXJzID0gdG9TaWduYWwoXG4gICAgICAgIGluamVjdChTQ19DQVRFR09SWV9JTkZPKS5waXBlKFxuICAgICAgICAgICAgY2F0Y2hFcnJvcigoKSA9PiBFTVBUWSksXG4gICAgICAgICAgICBmaWx0ZXIodHVpSXNQcmVzZW50KSxcbiAgICAgICAgICAgIHN3aXRjaE1hcCgoY2F0ZWdvcnkpID0+IHRoaXMuY2F0YWxvZ0ZpbHRlclNlcnZpY2UuZ2V0RmlsdGVycyQodGhpcy5pZE9yU2x1Z1BpcGUudHJhbnNmb3JtKGNhdGVnb3J5KSwgdGhpcy5pc1JlY3Vyc2l2ZWx5KSksXG4gICAgICAgICAgICBmaWx0ZXIodHVpSXNQcmVzZW50KSxcbiAgICAgICAgICAgIG1hcCgoZmlsdGVycykgPT4gZmlsdGVycy5maWx0ZXIoKGl0ZW0pID0+IGl0ZW0udHlwZSAhPT0gJ3JhbmdlJyB8fCBpdGVtLm1pbiAhPT0gaXRlbS5tYXgpKSxcbiAgICAgICAgICAgIHRhcCgoZmlsdGVycykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlRm9ybUNvbnRyb2xzKGZpbHRlcnMpO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICBzaGFyZSgpXG4gICAgICAgIClcbiAgICApO1xuXG4gICAgLyoqXG4gICAgICog0JjQvdC40YbQuNCw0LvQuNC30LjRgNGD0LXRgiDRjdC60LfQtdC80L/Qu9GP0YAg0LrQu9Cw0YHRgdCwIHtAbGluayBTY0NhdGFsb2dGaWx0ZXJzQ29tcG9uZW50fS5cbiAgICAgKi9cbiAgICBwdWJsaWMgY29uc3RydWN0b3IoKSB7XG4gICAgICAgIGluamVjdChEZXN0cm95UmVmKS5vbkRlc3Ryb3koKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5mb3JtU3luY3MudW5zdWJzY3JpYmUoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5mb3JtLnZhbHVlQ2hhbmdlcy5waXBlKGRlYm91bmNlVGltZSgwKSwgdGFrZVVudGlsRGVzdHJveWVkKCkpLnN1YnNjcmliZSgoZmlsdGVycykgPT4ge1xuICAgICAgICAgICAgdGhpcy5jYXRhbG9nUHJvZHVjdHNGaWx0ZXJzJC5uZXh0KHRoaXMuYnVpbGRQcm9wZXJ0eUZpbHRlcnMoZmlsdGVycykpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0L3QvtCy0LvRj9C10YIg0YHQvtGB0YLQsNCyINC60L7QvdGC0YDQvtC70L7QsiDRhNC+0YDQvNGLINC90LAg0L7RgdC90L7QstC1INC/0LXRgNC10LTQsNC90L3Ri9GFINGE0LjQu9GM0YLRgNC+0LIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmlsdGVycyDQnNCw0YHRgdC40LIg0YTQuNC70YzRgtGA0L7QsiDQtNC70Y8g0YHQvtC30LTQsNC90LjRjyDQutC+0L3RgtGA0L7Qu9C+0LIuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHVwZGF0ZUZvcm1Db250cm9scyhmaWx0ZXJzOiBTY0NhdGFsb2dGaWx0ZXJbXSk6IHZvaWQge1xuICAgICAgICB0aGlzLmZvcm1TeW5jcy51bnN1YnNjcmliZSgpO1xuICAgICAgICB0aGlzLmZvcm1TeW5jcyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICAgICAgICBPYmplY3Qua2V5cyh0aGlzLmZvcm0uY29udHJvbHMpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgICAgdGhpcy5mb3JtLnJlbW92ZUNvbnRyb2woa2V5IGFzIG5ldmVyLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGZpbHRlcnMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgc3dpdGNoIChpdGVtLnR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjaGVja2JveCc6IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hlY2tib3hDb250cm9sID0gdGhpcy5jcmVhdGVDaGVja2JveEZvcm1Db250cm9sKGl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uYWRkQ29udHJvbChpdGVtLmlkLCBjaGVja2JveENvbnRyb2wsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBTaW5nbGUtc2VsZWN0INC00LvRjyAhaXNNdWx0aXBsZTog0L/RgNC4INCy0YvQsdC+0YDQtSDQvtC00L3QvtCz0L4g0L7RgdGC0LDQu9GM0L3Ri9C1INGB0L3QuNC80LDRjtGC0YHRjy5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFpdGVtLmlzTXVsdGlwbGUgJiYgaXRlbS52YWx1ZXMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtU3luY3MuYWRkKHRoaXMuc3luY1NpbmdsZVNlbGVjdENoZWNrYm94KGNoZWNrYm94Q29udHJvbCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXNlICdyYW5nZSc6IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2VDb250cm9sID0gdGhpcy5jcmVhdGVSYW5nZUZvcm1Db250cm9sKGl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uYWRkQ29udHJvbChpdGVtLmlkLCByYW5nZUNvbnRyb2wsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtU3luY3MuYWRkKHRoaXMuc3luY1JhbmdlRnJvbVRvQW5kU2xpZGVyKHJhbmdlQ29udHJvbCkpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAndG9nZ2xlJzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmFkZENvbnRyb2woaXRlbS5pZCwgdGhpcy5jcmVhdGVUb2dnbGVGb3JtQ29udHJvbChpdGVtKSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J/RgNC10L7QsdGA0LDQt9GD0LXRgiDQt9C90LDRh9C10L3QuNGPINGE0L7RgNC80Ysg0LIg0L7QsdGK0LXQutGCINGE0LjQu9GM0YLRgNC+0LIg0YHQstC+0LnRgdGC0LIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdmFsdWUg0JfQvdCw0YfQtdC90LjRjyDRhNC+0YDQvNGLLlxuICAgICAqIEByZXR1cm5zINCe0LHRitC10LrRgiDRhNC40LvRjNGC0YDQvtCyINGB0LLQvtC50YHRgtCyLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBidWlsZFByb3BlcnR5RmlsdGVycyh2YWx1ZTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBTY1Byb3BlcnR5RmlsdGVycyB7XG4gICAgICAgIGNvbnN0IHJlc3VsdDogU2NQcm9wZXJ0eUZpbHRlcnMgPSB7fTtcblxuICAgICAgICB0aGlzLmZpbHRlcnMoKT8uZm9yRWFjaCgoZmlsdGVySXRlbSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29udHJvbFZhbHVlID0gdmFsdWVbZmlsdGVySXRlbS5pZF07XG5cbiAgICAgICAgICAgIGlmIChpc05pbChjb250cm9sVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzd2l0Y2ggKGZpbHRlckl0ZW0udHlwZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgJ2NoZWNrYm94JzpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcm9jZXNzQ2hlY2tib3hGaWx0ZXIocmVzdWx0LCBmaWx0ZXJJdGVtLCBjb250cm9sVmFsdWUgYXMgUmVjb3JkPHN0cmluZywgYm9vbGVhbj4pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdyYW5nZSc6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucHJvY2Vzc1JhbmdlRmlsdGVyKHJlc3VsdCwgZmlsdGVySXRlbS5pZCwgY29udHJvbFZhbHVlIGFzIHsgZnJvbTogbnVtYmVyOyB0bzogbnVtYmVyIH0pO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICd0b2dnbGUnOlxuICAgICAgICAgICAgICAgICAgICB0aGlzLnByb2Nlc3NUb2dnbGVGaWx0ZXIocmVzdWx0LCBmaWx0ZXJJdGVtLmlkLCBjb250cm9sVmFsdWUgYXMgYm9vbGVhbik7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgY29uc29sZS5sb2cocmVzdWx0KTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodC+0LfQtNCw0ZHRgiBGb3JtR3JvdXAg0LTQu9GPIGNoZWNrYm94OiDQvdCwINC60LDQttC00YvQuSB7QGNvZGUgdmFsdWUuaWR9IOKAlCDQsdGD0LvQtdCy0YvQuSDQutC+0L3RgtGA0L7Quy5cbiAgICAgKlxuICAgICAqINCV0LTQuNC90YvQuSDRhNC+0YDQvNCw0YIg0Lgg0LTQu9GPINC+0LTQvdC+0LPQviwg0Lgg0LTQu9GPINC80L3QvtC20LXRgdGC0LLQsCDQt9C90LDRh9C10L3QuNC5OiDRiNCw0LHQu9C+0L0g0YDQtdC90LTQtdGA0LjRgiDQuNGFINC+0LTQuNC90LDQutC+0LLQvi5cbiAgICAgKiDQoNCw0LfQu9C40YfQuNC1INCyIEFQSS3QstGL0LLQvtC00LUg0LTQu9GPINC+0LTQuNC90L7Rh9C90L7Qs9C+INC30L3QsNGH0LXQvdC40Y8gKGJvb2xlYW4g0LLQvNC10YHRgtC+INC80LDRgdGB0LjQstCwKSDQvtCx0YDQsNCx0LDRgtGL0LLQsNC10YLRgdGPINCyIHtAbGluayBwcm9jZXNzQ2hlY2tib3hGaWx0ZXJ9LlxuICAgICAqXG4gICAgICogQHBhcmFtIGNoZWNrYm94RmlsdGVyINCk0LjQu9GM0YLRgCDRgtC40L/QsCBjaGVja2JveC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY3JlYXRlQ2hlY2tib3hGb3JtQ29udHJvbChjaGVja2JveEZpbHRlcjogU2NJQ2hlY2tib3hGaWx0ZXIpOiBGb3JtR3JvdXA8UmVjb3JkPHN0cmluZywgRm9ybUNvbnRyb2w8Ym9vbGVhbj4+PiB7XG4gICAgICAgIGNvbnN0IGlzU2VsZWN0ZWQgPSAoaWQ6IHN0cmluZyk6IGJvb2xlYW4gPT4gY2hlY2tib3hGaWx0ZXIuc2VsZWN0ZWRWYWx1ZXM/LmluY2x1ZGVzKGlkKSA/PyBmYWxzZTtcbiAgICAgICAgY29uc3QgY29udHJvbHM6IFJlY29yZDxzdHJpbmcsIEZvcm1Db250cm9sPGJvb2xlYW4+PiA9IHt9O1xuXG4gICAgICAgIGNoZWNrYm94RmlsdGVyLnZhbHVlcy5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgY29udHJvbHNbdmFsdWUuaWRdID0gbmV3IEZvcm1Db250cm9sKGlzU2VsZWN0ZWQodmFsdWUuaWQpLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gbmV3IEZvcm1Hcm91cChjb250cm9scyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQvtC30LTQsNGR0YIge0BsaW5rIEZvcm1Hcm91cH0g0LTQu9GPIHJhbmdlOiB7QGNvZGUgZnJvbX0sIHtAY29kZSB0b30sIHtAY29kZSBzbGlkZXJ9ICjQutC+0YDRgtC10LYg0LTQu9GPIHtAbGluayBUdWlSYW5nZX0pLlxuICAgICAqXG4gICAgICogQHBhcmFtIHJhbmdlRmlsdGVyINCk0LjQu9GM0YLRgCDRgtC40L/QsCByYW5nZS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY3JlYXRlUmFuZ2VGb3JtQ29udHJvbChyYW5nZUZpbHRlcjogU2NSYW5nZUZpbHRlcik6IEZvcm1Hcm91cDx7XG4gICAgICAgIGZyb206IEZvcm1Db250cm9sPG51bWJlcj47XG4gICAgICAgIHRvOiBGb3JtQ29udHJvbDxudW1iZXI+O1xuICAgICAgICBzbGlkZXI6IEZvcm1Db250cm9sPFtudW1iZXIsIG51bWJlcl0+O1xuICAgIH0+IHtcbiAgICAgICAgY29uc3QgZnJvbVZhbHVlID0gTnVtYmVyKHJhbmdlRmlsdGVyLnNlbGVjdGVkTWluID8/IHJhbmdlRmlsdGVyLm1pbik7XG4gICAgICAgIGNvbnN0IHRvVmFsdWUgPSBOdW1iZXIocmFuZ2VGaWx0ZXIuc2VsZWN0ZWRNYXggPz8gcmFuZ2VGaWx0ZXIubWF4KTtcblxuICAgICAgICByZXR1cm4gbmV3IEZvcm1Hcm91cCh7XG4gICAgICAgICAgICBmcm9tOiBuZXcgRm9ybUNvbnRyb2woZnJvbVZhbHVlLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pLFxuICAgICAgICAgICAgdG86IG5ldyBGb3JtQ29udHJvbCh0b1ZhbHVlLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pLFxuICAgICAgICAgICAgc2xpZGVyOiBuZXcgRm9ybUNvbnRyb2w8W251bWJlciwgbnVtYmVyXT4oW2Zyb21WYWx1ZSwgdG9WYWx1ZV0sIHsgbm9uTnVsbGFibGU6IHRydWUgfSksXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCg0LXQsNC70LjQt9GD0LXRgiBzaW5nbGUtc2VsZWN0INC/0L7QstC10LTQtdC90LjQtSDQtNC70Y8gRm9ybUdyb3VwINGBINCx0YPQu9C10LLRi9C80Lgg0LrQvtC90YLRgNC+0LvQsNC80Lg6XG4gICAgICog0L/RgNC4INC/0L7Rj9Cy0LvQtdC90LjQuCDQvdC+0LLQvtCz0L4gdHJ1ZSDQvtGB0YLQsNC70YzQvdGL0LUg0LrQvtC90YLRgNC+0LvRiyDQs9GA0YPQv9C/0Ysg0YHQsdGA0LDRgdGL0LLQsNGO0YLRgdGPINCyIGZhbHNlLlxuICAgICAqXG4gICAgICog0KHQvtGF0YDQsNC90Y/QtdGCINC/0L7RgdC70LXQtNC90LXQtSDCq9GB0YLQsNCx0LjQu9GM0L3QvtC1wrsg0YHQvtGB0YLQvtGP0L3QuNC1INC4INGB0YDQsNCy0L3QuNCy0LDQtdGCINGB0LvQtdC00YPRjtGJ0LXQtSDQt9C90LDRh9C10L3QuNC1INGBINC90LjQvCDigJRcbiAgICAgKiDQvdC+0LLRi9C5IHRydWUgKNC+0YLRgdGD0YLRgdGC0LLQvtCy0LDQuyDQsiBwcmV2KSDRgdGH0LjRgtCw0LXRgtGB0Y8g0LLRi9Cx0YDQsNC90L3Ri9C8LCDQvtGB0YLQsNC70YzQvdGL0LUg0YHQsdGA0LDRgdGL0LLQsNGO0YLRgdGPINGH0LXRgNC10Lcgc2V0VmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZ3JvdXAgRm9ybUdyb3VwIGNoZWNrYm94LdGE0LjQu9GM0YLRgNCwIChpZCDihpIgYm9vbGVhbikuXG4gICAgICovXG4gICAgcHJpdmF0ZSBzeW5jU2luZ2xlU2VsZWN0Q2hlY2tib3goZ3JvdXA6IEZvcm1Hcm91cDxSZWNvcmQ8c3RyaW5nLCBGb3JtQ29udHJvbDxib29sZWFuPj4+KTogU3Vic2NyaXB0aW9uIHtcbiAgICAgICAgbGV0IHByZXZpb3VzU3RhdGUgPSBncm91cC5nZXRSYXdWYWx1ZSgpIGFzIFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+O1xuXG4gICAgICAgIHJldHVybiBncm91cC52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudCA9IHZhbHVlIGFzIFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+O1xuICAgICAgICAgICAgY29uc3QgbmV3bHlDaGVja2VkID0gT2JqZWN0LmVudHJpZXMoY3VycmVudCkuZmluZCgoW2lkLCBpc0NoZWNrZWRdKSA9PiB7XG4gICAgICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHNlY3VyaXR5L2RldGVjdC1vYmplY3QtaW5qZWN0aW9uXG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzQ2hlY2tlZCAmJiAhcHJldmlvdXNTdGF0ZVtpZF07XG4gICAgICAgICAgICB9KT8uWzBdO1xuXG4gICAgICAgICAgICBpZiAoIW5ld2x5Q2hlY2tlZCkge1xuICAgICAgICAgICAgICAgIHByZXZpb3VzU3RhdGUgPSB7IC4uLmN1cnJlbnQgfTtcblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbmV4dDogUmVjb3JkPHN0cmluZywgYm9vbGVhbj4gPSB7fTtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKGdyb3VwLmNvbnRyb2xzKS5mb3JFYWNoKChpZCkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzZWN1cml0eS9kZXRlY3Qtb2JqZWN0LWluamVjdGlvblxuICAgICAgICAgICAgICAgIG5leHRbaWRdID0gaWQgPT09IG5ld2x5Q2hlY2tlZDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgcHJldmlvdXNTdGF0ZSA9IG5leHQ7XG4gICAgICAgICAgICBncm91cC5zZXRWYWx1ZShuZXh0KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQstGP0LfRi9Cy0LDQtdGCINC/0L7Qu9GPIMKr0L7RgsK7L8Kr0LTQvsK7INGBINC60L7QvdGC0YDQvtC70L7QvCDRgdC70LDQudC00LXRgNCwLlxuICAgICAqXG4gICAgICogQHBhcmFtIGdyb3VwIEZvcm1Hcm91cCByYW5nZS3RhNC40LvRjNGC0YDQsC5cbiAgICAgKi9cbiAgICBwcml2YXRlIHN5bmNSYW5nZUZyb21Ub0FuZFNsaWRlcihncm91cDogRm9ybUdyb3VwKTogU3Vic2NyaXB0aW9uIHtcbiAgICAgICAgY29uc3QgZnJvbSA9IGdyb3VwLmdldCgnZnJvbScpO1xuICAgICAgICBjb25zdCB0byA9IGdyb3VwLmdldCgndG8nKTtcbiAgICAgICAgY29uc3Qgc2xpZGVyID0gZ3JvdXAuZ2V0KCdzbGlkZXInKTtcblxuICAgICAgICBpZiAoIWZyb20gfHwgIXRvIHx8ICFzbGlkZXIpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgU3Vic2NyaXB0aW9uKCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzdWIgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XG5cbiAgICAgICAgLy8g0JjQvdC/0YPRgtGLIOKGkiDRgdC70LDQudC00LXRgDsg0LXRgdC70LggwqvQvtGCwrsgPiDCq9C00L7Cuywg0L/QvtC00L3QuNC80LDQtdC8IMKr0LTQvsK7INC00L4gwqvQvtGCwrsuXG4gICAgICAgIGNvbnN0IGFwcGx5U2xpZGVyRnJvbUlucHV0cyA9ICgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGxvdyA9IE51bWJlcihmcm9tLnZhbHVlKTtcbiAgICAgICAgICAgIGxldCBoaWdoID0gTnVtYmVyKHRvLnZhbHVlKTtcblxuICAgICAgICAgICAgaWYgKGxvdyA+IGhpZ2gpIHtcbiAgICAgICAgICAgICAgICBoaWdoID0gbG93O1xuICAgICAgICAgICAgICAgIHRvLnNldFZhbHVlKGhpZ2gsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY3VycmVudFBhaXIgPSBzbGlkZXIudmFsdWUgYXMgW251bWJlciwgbnVtYmVyXTtcblxuICAgICAgICAgICAgaWYgKGN1cnJlbnRQYWlyWzBdICE9PSBsb3cgfHwgY3VycmVudFBhaXJbMV0gIT09IGhpZ2gpIHtcbiAgICAgICAgICAgICAgICBzbGlkZXIuc2V0VmFsdWUoW2xvdywgaGlnaF0sIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICBzbGlkZXIubWFya0FzRGlydHkoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcblxuICAgICAgICBzdWIuYWRkKG1lcmdlKGZyb20udmFsdWVDaGFuZ2VzLCB0by52YWx1ZUNoYW5nZXMpLnN1YnNjcmliZShhcHBseVNsaWRlckZyb21JbnB1dHMpKTtcblxuICAgICAgICBzdWIuYWRkKFxuICAgICAgICAgICAgc2xpZGVyLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgW2xvdywgaGlnaF0gPSB2YWx1ZSBhcyBbbnVtYmVyLCBudW1iZXJdO1xuXG4gICAgICAgICAgICAgICAgaWYgKGZyb20udmFsdWUgIT09IGxvdykge1xuICAgICAgICAgICAgICAgICAgICBmcm9tLnNldFZhbHVlKGxvdywgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgICAgICBmcm9tLm1hcmtBc0RpcnR5KCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRvLnZhbHVlICE9PSBoaWdoKSB7XG4gICAgICAgICAgICAgICAgICAgIHRvLnNldFZhbHVlKGhpZ2gsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgdG8ubWFya0FzRGlydHkoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIC8vINCh0L7QstC/0LDRgdGC0Ywg0YEg0L/QvtC70Y/QvNC4INC/0YDQuCDQv9C10YDQstC+0Lwg0L/QvtC60LDQt9C1ICjRg9C20LUg0YHQvtCy0L/QsNC00LDQtdGCINC/0YDQuCDRgdC+0LfQtNCw0L3QuNC4LCDQvdC+INC90LAg0LLRgdGP0LrQuNC5INGB0LvRg9GH0LDQuSkuXG4gICAgICAgIGFwcGx5U2xpZGVyRnJvbUlucHV0cygpO1xuXG4gICAgICAgIHJldHVybiBzdWI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQvtC30LTQsNC10YIgRm9ybUNvbnRyb2wg0LTQu9GPIHRvZ2dsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0b2dnbGVGaWx0ZXIg0KTQuNC70YzRgtGAINGC0LjQv9CwIHRvZ2dsZS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgY3JlYXRlVG9nZ2xlRm9ybUNvbnRyb2wodG9nZ2xlRmlsdGVyOiBTY1RvZ2dsZUZpbHRlcik6IEZvcm1Db250cm9sPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBGb3JtQ29udHJvbCh0b2dnbGVGaWx0ZXIuc2VsZWN0ZWRWYWx1ZSA/PyBmYWxzZSwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0YDQsNCx0LDRgtGL0LLQsNC10YIgY2hlY2tib3g6IEZvcm1Hcm91cCDihpIgc3RyaW5nW10g0LLRi9Cx0YDQsNC90L3Ri9GFIGlkOyDQtNC70Y8g0LXQtNC40L3RgdGC0LLQtdC90L3QvtCz0L4g0LfQvdCw0YfQtdC90LjRjyDigJQgYm9vbGVhbiAo0LrQsNC6IHRvZ2dsZSkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVzdWx0INCe0LHRitC10LrRgiDRgNC10LfRg9C70YzRgtCw0YLQsCDQtNC70Y8g0LfQsNC/0L7Qu9C90LXQvdC40Y8uXG4gICAgICogQHBhcmFtIGNoZWNrYm94RmlsdGVyINCc0LXRgtCw0YTQuNC70YzRgtGAIGNoZWNrYm94LlxuICAgICAqIEBwYXJhbSBjb250cm9sVmFsdWUg0JfQvdCw0YfQtdC90LjQtSDQutC+0L3RgtGA0L7Qu9CwINGE0L7RgNC80YsgKNC30LDQv9C40YHRjCBpZCDihpIgYm9vbGVhbikuXG4gICAgICovXG4gICAgcHJpdmF0ZSBwcm9jZXNzQ2hlY2tib3hGaWx0ZXIocmVzdWx0OiBTY1Byb3BlcnR5RmlsdGVycywgY2hlY2tib3hGaWx0ZXI6IFNjSUNoZWNrYm94RmlsdGVyLCBjb250cm9sVmFsdWU6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+KTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkSWRzID0gT2JqZWN0LmVudHJpZXMoY29udHJvbFZhbHVlKVxuICAgICAgICAgICAgLmZpbHRlcigoWywgaXNTZWxlY3RlZF0pID0+IGlzU2VsZWN0ZWQpXG4gICAgICAgICAgICAubWFwKChbaWRdKSA9PiBpZCk7XG5cbiAgICAgICAgaWYgKHNlbGVjdGVkSWRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHNlY3VyaXR5L2RldGVjdC1vYmplY3QtaW5qZWN0aW9uLCBuby1wYXJhbS1yZWFzc2lnblxuICAgICAgICByZXN1bHRbY2hlY2tib3hGaWx0ZXIuaWRdID0gc2VsZWN0ZWRJZHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J7QsdGA0LDQsdCw0YLRi9Cy0LDQtdGCIHJhbmdlINGE0LjQu9GM0YLRgC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSByZXN1bHQg0J7QsdGK0LXQutGCINGA0LXQt9GD0LvRjNGC0LDRgtCwINC00LvRjyDQt9Cw0L/QvtC70L3QtdC90LjRjy5cbiAgICAgKiBAcGFyYW0gZmlsdGVySWQg0JjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0YTQuNC70YzRgtGA0LAuXG4gICAgICogQHBhcmFtIHJhbmdlINCX0L3QsNGH0LXQvdC40LUg0LrQvtC90YLRgNC+0LvQsCDRhNC+0YDQvNGLICjQvtCx0YrQtdC60YIg0YEg0LPRgNCw0L3QuNGG0LDQvNC4KS5cbiAgICAgKiBAcGFyYW0gcmFuZ2UuZnJvbSDQndCw0YfQsNC70YzQvdC+0LUg0LfQvdCw0YfQtdC90LjQtSDQtNC40LDQv9Cw0LfQvtC90LAuXG4gICAgICogQHBhcmFtIHJhbmdlLnRvINCa0L7QvdC10YfQvdC+0LUg0LfQvdCw0YfQtdC90LjQtSDQtNC40LDQv9Cw0LfQvtC90LAuXG4gICAgICovXG4gICAgcHJpdmF0ZSBwcm9jZXNzUmFuZ2VGaWx0ZXIocmVzdWx0OiBTY1Byb3BlcnR5RmlsdGVycywgZmlsdGVySWQ6IHN0cmluZywgcmFuZ2U6IHsgZnJvbTogbnVtYmVyOyB0bzogbnVtYmVyIH0pOiB2b2lkIHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHNlY3VyaXR5L2RldGVjdC1vYmplY3QtaW5qZWN0aW9uLCBuby1wYXJhbS1yZWFzc2lnblxuICAgICAgICByZXN1bHRbZmlsdGVySWRdID0ge1xuICAgICAgICAgICAgZnJvbTogU3RyaW5nKHJhbmdlLmZyb20pLFxuICAgICAgICAgICAgdG86IFN0cmluZyhyYW5nZS50byksXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J7QsdGA0LDQsdCw0YLRi9Cy0LDQtdGCIHRvZ2dsZSDRhNC40LvRjNGC0YAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVzdWx0INCe0LHRitC10LrRgiDRgNC10LfRg9C70YzRgtCw0YLQsCDQtNC70Y8g0LfQsNC/0L7Qu9C90LXQvdC40Y8uXG4gICAgICogQHBhcmFtIGZpbHRlcklkINCY0LTQtdC90YLQuNGE0LjQutCw0YLQvtGAINGE0LjQu9GM0YLRgNCwLlxuICAgICAqIEBwYXJhbSBjb250cm9sVmFsdWUg0JfQvdCw0YfQtdC90LjQtSDQutC+0L3RgtGA0L7Qu9CwINGE0L7RgNC80YsuXG4gICAgICovXG4gICAgcHJpdmF0ZSBwcm9jZXNzVG9nZ2xlRmlsdGVyKHJlc3VsdDogU2NQcm9wZXJ0eUZpbHRlcnMsIGZpbHRlcklkOiBzdHJpbmcsIGNvbnRyb2xWYWx1ZTogYm9vbGVhbik6IHZvaWQge1xuICAgICAgICBpZiAoY29udHJvbFZhbHVlKSB7XG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc2VjdXJpdHkvZGV0ZWN0LW9iamVjdC1pbmplY3Rpb24sIG5vLXBhcmFtLXJlYXNzaWduXG4gICAgICAgICAgICByZXN1bHRbZmlsdGVySWRdID0gY29udHJvbFZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQsdGA0LDRgdGL0LLQsNC10YIg0L/QvtC70LUgwqvQvtGCwrsg0LTQuNCw0L/QsNC30L7QvdCwINC6INC80LjQvdC40LzQsNC70YzQvdC+0LzRgyDQt9C90LDRh9C10L3QuNGOINGE0LjQu9GM0YLRgNCwLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZpbHRlcklkINCY0LTQtdC90YLQuNGE0LjQutCw0YLQvtGAINGE0LjQu9GM0YLRgNCwLlxuICAgICAqIEBwYXJhbSBtaW4g0JzQuNC90LjQvNCw0LvRjNC90L7QtSDQt9C90LDRh9C10L3QuNC1INC00LjQsNC/0LDQt9C+0L3QsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVzZXRSYW5nZUZyb20oZmlsdGVySWQ6IHN0cmluZywgbWluOiBzdHJpbmcgfCBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5mb3JtLmdldChmaWx0ZXJJZCk/LmdldCgnZnJvbScpPy5yZXNldCgrbWluKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodCx0YDQsNGB0YvQstCw0LXRgiDQv9C+0LvQtSDCq9C00L7CuyDQtNC40LDQv9Cw0LfQvtC90LAg0Log0LzQsNC60YHQuNC80LDQu9GM0L3QvtC80YMg0LfQvdCw0YfQtdC90LjRjiDRhNC40LvRjNGC0YDQsC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBmaWx0ZXJJZCDQmNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgCDRhNC40LvRjNGC0YDQsC5cbiAgICAgKiBAcGFyYW0gbWF4INCc0LDQutGB0LjQvNCw0LvRjNC90L7QtSDQt9C90LDRh9C10L3QuNC1INC00LjQsNC/0LDQt9C+0L3QsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVzZXRSYW5nZVRvKGZpbHRlcklkOiBzdHJpbmcsIG1heDogc3RyaW5nIHwgbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZm9ybS5nZXQoZmlsdGVySWQpPy5nZXQoJ3RvJyk/LnJlc2V0KCttYXgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCh0LHRgNCw0YHRi9Cy0LDQtdGCINCy0YHQtSDRh9C10LrQsdC+0LrRgdGLINCz0YDRg9C/0L/RiyDQsiBgZmFsc2VgLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZpbHRlcklkINCY0LTQtdC90YLQuNGE0LjQutCw0YLQvtGAINGE0LjQu9GM0YLRgNCwICjQutC70Y7RhyBGb3JtR3JvdXAg0LIg0YTQvtGA0LzQtSkuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlc2V0Q2hlY2tib3hHcm91cChmaWx0ZXJJZDogc3RyaW5nKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGdyb3VwID0gdGhpcy5mb3JtLmdldChmaWx0ZXJJZCkgYXMgRm9ybUdyb3VwPFJlY29yZDxzdHJpbmcsIEZvcm1Db250cm9sPGJvb2xlYW4+Pj4gfCBudWxsO1xuXG4gICAgICAgIGlmICghZ3JvdXApIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHJlc2V0VmFsdWU6IFJlY29yZDxzdHJpbmcsIGJvb2xlYW4+ID0ge307XG4gICAgICAgIE9iamVjdC5rZXlzKGdyb3VwLmNvbnRyb2xzKS5mb3JFYWNoKChpZCkgPT4ge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIHNlY3VyaXR5L2RldGVjdC1vYmplY3QtaW5qZWN0aW9uXG4gICAgICAgICAgICByZXNldFZhbHVlW2lkXSA9IGZhbHNlO1xuICAgICAgICB9KTtcbiAgICAgICAgZ3JvdXAucmVzZXQocmVzZXRWYWx1ZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQsdGA0LDRgdGL0LLQsNC10YIg0LLRgdC1INGE0LjQu9GM0YLRgNGLINC4INC+0L/QvtCy0LXRidCw0LXRgiDRgNC+0LTQuNGC0LXQu9GPINC+INC90LDQttCw0YLQuNC4INC60L3QvtC/0LrQuCDRgdCx0YDQvtGB0LAuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIG9uUmVzZXRGaWx0ZXJzQ2xpY2soKTogdm9pZCB7XG4gICAgICAgIHRoaXMucmVzZXRBbGxGaWx0ZXJzKCk7XG4gICAgICAgIHRoaXMucmVzZXRGaWx0ZXJzLmVtaXQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntC/0L7QstC10YnQsNC10YIg0YDQvtC00LjRgtC10LvRjyDQviDQvdCw0LbQsNGC0LjQuCDQutC90L7Qv9C60Lgg0L/QvtC60LDQt9CwINGA0LXQt9GD0LvRjNGC0LDRgtC+0LIuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIG9uU2hvd1Jlc3VsdHNDbGljaygpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5zaG93UmVzdWx0cy5lbWl0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQsdGA0LDRgdGL0LLQsNC10YIg0LLRgdC1INGE0LjQu9GM0YLRgNGLINC6INC40YHRhdC+0LTQvdGL0Lwg0LfQvdCw0YfQtdC90LjRj9C8LlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVzZXRBbGxGaWx0ZXJzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmZpbHRlcnMoKT8uZm9yRWFjaCgoZmlsdGVySXRlbSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgY29udHJvbCA9IHRoaXMuZm9ybS5nZXQoZmlsdGVySXRlbS5pZCk7XG5cbiAgICAgICAgICAgIGlmICghY29udHJvbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3dpdGNoIChmaWx0ZXJJdGVtLnR5cGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlICdjaGVja2JveCc6IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZ3JvdXAgPSBjb250cm9sIGFzIEZvcm1Hcm91cDxSZWNvcmQ8c3RyaW5nLCBGb3JtQ29udHJvbDxib29sZWFuPj4+O1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNldFZhbHVlOiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiA9IHt9O1xuICAgICAgICAgICAgICAgICAgICBPYmplY3Qua2V5cyhncm91cC5jb250cm9scykuZm9yRWFjaCgoaWQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBzZWN1cml0eS9kZXRlY3Qtb2JqZWN0LWluamVjdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzZXRWYWx1ZVtpZF0gPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGdyb3VwLnJlc2V0KHJlc2V0VmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FzZSAndG9nZ2xlJzpcbiAgICAgICAgICAgICAgICAgICAgY29udHJvbC5yZXNldChmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ3JhbmdlJzoge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBncm91cCA9IGNvbnRyb2wgYXMgRm9ybUdyb3VwO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBtaW4gPSArZmlsdGVySXRlbS5taW47XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG1heCA9ICtmaWx0ZXJJdGVtLm1heDtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXAucmVzZXQoeyBmcm9tOiBtaW4sIHRvOiBtYXgsIHNsaWRlcjogW21pbiwgbWF4XSB9KTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG59XG4iLCJAaWYgKGZpbHRlcnMoKT8ubGVuZ3RoKSB7XG4gICAgPGZvcm1cbiAgICAgICAgW2Zvcm1Hcm91cF09XCJmb3JtXCJcbiAgICAgICAgY2xhc3M9XCJmbGV4IGZsZXgtY29sIHBiLTFcIlxuICAgID5cbiAgICAgICAgQGZvciAoZmlsdGVyIG9mIGZpbHRlcnMoKTsgdHJhY2sgZmlsdGVyLmlkOyBsZXQgaXNGaXJzdCA9ICRmaXJzdCkge1xuICAgICAgICAgICAgQGlmICghaXNGaXJzdCkge1xuICAgICAgICAgICAgICAgIDxociBjbGFzcz1cIm15LTMgdy1mdWxsIGgtcHhcIiAvPlxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtMlwiPlxuICAgICAgICAgICAgICAgIDwhLS0g0JfQsNCz0L7Qu9C+0LLQvtC6INCz0YDRg9C/0L/Riy4g0JTQu9GPIHRvZ2dsZSDQv9C+0LTQv9C40YHQuCDQvdC10YI6INC80LXRgtC60LAg0LjQtNGR0YIg0L/RgNGP0LzQviDRgNGP0LTQvtC8INGBINGB0LDQvNC40LwgY2hlY2tib3guIC0tPlxuICAgICAgICAgICAgICAgIEBpZiAoZmlsdGVyLnR5cGUgIT09ICd0b2dnbGUnKSB7XG4gICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cInRleHQtYm9keS1zLWJvbGRcIj57eyBmaWx0ZXIubGFiZWwgfX08L2xhYmVsPlxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIDwhLS0gQ2hlY2tib3g6IEZvcm1Hcm91cCh2YWx1ZS5pZCDihpIgYm9vbGVhbikg0LTQu9GPINC70Y7QsdC+0LPQviDRh9C40YHQu9CwINC30L3QsNGH0LXQvdC40LkuXG4gICAgICAgICAgICAgICAgICAgICDQoNCw0LfQstC40LvQutCwINC+0LTQvdC+L9C80L3QvtCz0L4g0LfQvdCw0YfQtdC90LjQuSDQstGL0L3QtdGB0LXQvdCwINCyIFRTICjRgdC8LiBwcm9jZXNzQ2hlY2tib3hGaWx0ZXIpLlxuICAgICAgICAgICAgICAgICAgICAgbmctdGVtcGxhdGUg0LLQvdGD0YLRgNC4IGZvcm1Hcm91cE5hbWU6INC40L3QsNGH0LUgcmVhY3RpdmUgZm9ybXMg0L3QtSDQvdCw0LnQtNGR0YIgQ29udHJvbENvbnRhaW5lciDQv9GA0Lgg0L/RgNC+0LXQutGG0LjQuCDQsiDQtNC+0YfQtdGA0L3QuNC5INC60L7QvNC/0L7QvdC10L3Rgi4gLS0+XG4gICAgICAgICAgICAgICAgQGlmIChmaWx0ZXIudHlwZSA9PT0gJ2NoZWNrYm94Jykge1xuICAgICAgICAgICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Hcm91cE5hbWVdPVwiZmlsdGVyLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHNjLWNhdGFsb2ctZmlsdGVyLWNvbGxhcHNpYmxlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2l0ZW1zQ291bnRdPVwiZmlsdGVyLnZhbHVlcy5sZW5ndGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzaG93UmVzZXRdPVwiZm9ybS5nZXQoZmlsdGVyLmlkKT8uZGlydHkgPz8gZmFsc2VcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZXNldEdyb3VwKT1cInJlc2V0Q2hlY2tib3hHcm91cChmaWx0ZXIuaWQpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0yXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAZm9yICh2YWx1ZSBvZiBmaWx0ZXIudmFsdWVzOyB0cmFjayB2YWx1ZS5pZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sTmFtZV09XCJ2YWx1ZS5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlDaGVja2JveFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cImNoZWNrYm94XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ0ZXh0LWJvZHktc1wiPnt7IHZhbHVlLmxhYmVsIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L3NjLWNhdGFsb2ctZmlsdGVyLWNvbGxhcHNpYmxlPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICA8IS0tIFRvZ2dsZTog0L7QtNC40L0gYm9vbGVhbiDQvdCwINC60L7RgNC90LUg0YTQvtGA0LzRiywg0L/QvtC00L/QuNGB0YwgPSBmaWx0ZXIubGFiZWwgLS0+XG4gICAgICAgICAgICAgICAgfSBAZWxzZSBpZiAoZmlsdGVyLnR5cGUgPT09ICd0b2dnbGUnKSB7XG4gICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZsZXggaXRlbXMtY2VudGVyIGdhcC0yXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xOYW1lXT1cImZpbHRlci5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpQ2hlY2tib3hcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidGV4dC1ib2R5LXMtYm9sZFwiPnt7IGZpbHRlci5sYWJlbCB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cblxuICAgICAgICAgICAgICAgICAgICA8IS0tIFJhbmdlOiBGb3JtR3JvdXAoZnJvbSwgdG8sIHNsaWRlcikg0YEg0LTQstGD0YHRgtC+0YDQvtC90L3QtdC5INGB0LjQvdGF0YDQvtC90LjQt9Cw0YbQuNC10LkgLS0+XG4gICAgICAgICAgICAgICAgfSBAZWxzZSBpZiAoZmlsdGVyLnR5cGUgPT09ICdyYW5nZScpIHtcbiAgICAgICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Hcm91cE5hbWVdPVwiZmlsdGVyLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtM1wiXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGdhcC0zIHB4LTFcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpTGFiZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtaW4tdy0wIGZsZXgtMVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDQntGCXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktdGV4dGZpZWxkIFt0dWlUZXh0ZmllbGRDbGVhbmVyXT1cImZhbHNlXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY1NlbGVjdE9uRm9jdXNpblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aUlucHV0TnVtYmVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiZnJvbVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3R1aU51bWJlckZvcm1hdF09XCJ7IHByZWNpc2lvbjogMCB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWluXT1cIitmaWx0ZXIubWluXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWF4XT1cIitmaWx0ZXIubWF4XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoZm9ybS5nZXQoZmlsdGVyLmlkKT8uZ2V0KCdmcm9tJyk/LmRpcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlJY29uQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaXplPVwieHNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcHBlYXJhbmNlPVwiaWNvblwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGljb25TdGFydD1cIkB0dWkueFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJyZXNldFJhbmdlRnJvbShmaWx0ZXIuaWQsIGZpbHRlci5taW4pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+PC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdHVpLXRleHRmaWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlMYWJlbFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm1pbi13LTAgZmxleC0xXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgINCU0L5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS10ZXh0ZmllbGQgW3R1aVRleHRmaWVsZENsZWFuZXJdPVwiZmFsc2VcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjU2VsZWN0T25Gb2N1c2luXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpSW5wdXROdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ0b1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3R1aU51bWJlckZvcm1hdF09XCJ7IHByZWNpc2lvbjogMCB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWluXT1cIitmaWx0ZXIubWluXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWF4XT1cIitmaWx0ZXIubWF4XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoZm9ybS5nZXQoZmlsdGVyLmlkKT8uZ2V0KCd0bycpPy5kaXJ0eSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpSWNvbkJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT1cInhzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwZWFyYW5jZT1cImljb25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpY29uU3RhcnQ9XCJAdHVpLnhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwicmVzZXRSYW5nZVRvKGZpbHRlci5pZCwgZmlsdGVyLm1heClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID48L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90dWktdGV4dGZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS1yYW5nZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9XCJtXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJzbGlkZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttaW5dPVwiK2ZpbHRlci5taW5cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttYXhdPVwiK2ZpbHRlci5tYXhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzdHlsZS4tLXR1aS10aGlja25lc3MucmVtXT1cIjAuMjVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgdHVpQnV0dG9uXG4gICAgICAgICAgICBhcHBlYXJhbmNlPVwic2Vjb25kYXJ5XCJcbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgY2xhc3M9XCJtdC0yXCJcbiAgICAgICAgICAgIChjbGljayk9XCJvblJlc2V0RmlsdGVyc0NsaWNrKClcIlxuICAgICAgICA+XG4gICAgICAgICAgICDQodCx0YDQvtGB0LjRgtGMINGE0LjQu9GM0YLRgNGLXG4gICAgICAgIDwvYnV0dG9uPlxuICAgICAgICBAaWYgKHNob3dSZXN1bHRzQnV0dG9uKCkpIHtcbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICB0dWlCdXR0b25cbiAgICAgICAgICAgICAgICBhcHBlYXJhbmNlPVwicHJpbWFyeVwiXG4gICAgICAgICAgICAgICAgdHlwZT1cImJ1dHRvblwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJtdC0yXCJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwib25TaG93UmVzdWx0c0NsaWNrKClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgINCf0L7QutCw0LfQsNGC0Ywg0YDQtdC30YPQu9GM0YLQsNGC0YtcbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICB9XG4gICAgPC9mb3JtPlxufVxuIl19