@snabcentr/client-ui 3.51.15 → 3.52.0
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.
- package/configurators/index.d.ts +1 -0
- package/configurators/models/index.d.ts +1 -0
- package/configurators/models/sandwich_m2/sc-i-sandwich-m2-settings.d.ts +18 -0
- package/configurators/sandwich/sc-sandwich.component.d.ts +24 -0
- package/configurators/sandwich_m2/index.d.ts +4 -0
- package/configurators/sandwich_m2/sandwich-m2-skeleton/sc-sandwich-m2-skeleton.component.d.ts +8 -0
- package/configurators/sandwich_m2/sc-i-new-cart-item-sandwich-m2.d.ts +23 -0
- package/configurators/sandwich_m2/sc-sandwich-m2-item-submit-state.d.ts +13 -0
- package/configurators/sandwich_m2/sc-sandwich-m2.component.d.ts +267 -0
- package/esm2022/configurators/index.mjs +2 -1
- package/esm2022/configurators/models/index.mjs +2 -1
- package/esm2022/configurators/models/sandwich_m2/sc-i-sandwich-m2-settings.mjs +2 -0
- package/esm2022/configurators/sandwich/sc-sandwich.component.mjs +57 -6
- package/esm2022/configurators/sandwich_m2/index.mjs +5 -0
- package/esm2022/configurators/sandwich_m2/sandwich-m2-skeleton/sc-sandwich-m2-skeleton.component.mjs +14 -0
- package/esm2022/configurators/sandwich_m2/sc-i-new-cart-item-sandwich-m2.mjs +2 -0
- package/esm2022/configurators/sandwich_m2/sc-sandwich-m2-item-submit-state.mjs +5 -0
- package/esm2022/configurators/sandwich_m2/sc-sandwich-m2.component.mjs +560 -0
- package/fesm2022/snabcentr-client-ui.mjs +613 -6
- package/fesm2022/snabcentr-client-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/release_notes.tmp +6 -2
- package/styles/tailwind/tailwind.scss +72 -0
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
/* eslint-disable security/detect-object-injection,@typescript-eslint/unbound-method */
|
|
2
|
+
import { AsyncPipe, DecimalPipe } from '@angular/common';
|
|
3
|
+
import { HttpErrorResponse } from '@angular/common/http';
|
|
4
|
+
import { ChangeDetectionStrategy, Component, computed, DestroyRef, inject, Input, input, output, signal } from '@angular/core';
|
|
5
|
+
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
|
|
6
|
+
import { FormArray, FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
7
|
+
import { SC_ORDER_LOADER, ScCatalogService, ScConvertersService, } from '@snabcentr/client-core';
|
|
8
|
+
import { tuiControlValue } from '@taiga-ui/cdk';
|
|
9
|
+
import { TuiButton, TuiError, TuiIcon, tuiItemsHandlersProvider, TuiLabel, TuiLoader, TuiNumberFormat, tuiNumberFormatProvider, TuiTextfield, } from '@taiga-ui/core';
|
|
10
|
+
import { TuiButtonLoading, TuiChevron, TuiDataListWrapperComponent, TuiFieldErrorPipe, TuiInputNumber, tuiInputNumberOptionsProvider, TuiInputSlider, TuiSelect, } from '@taiga-ui/kit';
|
|
11
|
+
import { POLYMORPHEUS_CONTEXT } from '@taiga-ui/polymorpheus';
|
|
12
|
+
import { catchError, concatMap, from, map, of, switchMap, tap, throwError } from 'rxjs';
|
|
13
|
+
import { ScNextInputFocusModule } from '../../directives/next-input-focus/sc-next-input-focus.module';
|
|
14
|
+
import { ScSelectOnFocusinDirective } from '../../directives/select-on-focusin/sc-select-on-focusin.directive';
|
|
15
|
+
import { stepValidator } from '../../validators/step-validator';
|
|
16
|
+
import { IDLE_ITEM_STATE } from './sc-sandwich-m2-item-submit-state';
|
|
17
|
+
import * as i0 from "@angular/core";
|
|
18
|
+
import * as i1 from "@angular/forms";
|
|
19
|
+
import * as i2 from "../../directives/next-input-focus/sc-next-input-focus.directive";
|
|
20
|
+
import * as i3 from "@taiga-ui/core";
|
|
21
|
+
import * as i4 from "@taiga-ui/kit";
|
|
22
|
+
import * as i5 from "@taiga-ui/kit/components/slider";
|
|
23
|
+
/**
|
|
24
|
+
* Конфигуратор распила сэндвич-панелей по площади.
|
|
25
|
+
*/
|
|
26
|
+
export class ScSandwichM2Component {
|
|
27
|
+
constructor() {
|
|
28
|
+
/**
|
|
29
|
+
* Настройки для конфигуратора распила сэндвич-панелей по площади.
|
|
30
|
+
*/
|
|
31
|
+
this.settings = input();
|
|
32
|
+
/**
|
|
33
|
+
* Идентификатор категории.
|
|
34
|
+
*/
|
|
35
|
+
this.categoryId = input.required();
|
|
36
|
+
/**
|
|
37
|
+
* Название конфигуратора.
|
|
38
|
+
*/
|
|
39
|
+
this.editor = input.required();
|
|
40
|
+
/**
|
|
41
|
+
* Позиция товара/услуги в корзине.
|
|
42
|
+
*/
|
|
43
|
+
this.orderItem = input.required();
|
|
44
|
+
/**
|
|
45
|
+
* Событие переключения отображения товаров.
|
|
46
|
+
*/
|
|
47
|
+
this.toggleShowEvent = output();
|
|
48
|
+
/**
|
|
49
|
+
* Форма добавления/редактирования продукта в корзине.
|
|
50
|
+
*/
|
|
51
|
+
this.form = new FormGroup({
|
|
52
|
+
productCategoryId: new FormControl(null, { validators: Validators.required }),
|
|
53
|
+
configurator: new FormControl(null, { validators: Validators.required }),
|
|
54
|
+
items: new FormArray([]),
|
|
55
|
+
});
|
|
56
|
+
/**
|
|
57
|
+
* Сервис получения и редактирования списка товаров заказа (корзина / заказ / черновик = заказ).
|
|
58
|
+
*/
|
|
59
|
+
this.orderService = inject(SC_ORDER_LOADER);
|
|
60
|
+
/**
|
|
61
|
+
* Сервис конвертации данных.
|
|
62
|
+
*/
|
|
63
|
+
this.convertersService = inject(ScConvertersService);
|
|
64
|
+
/**
|
|
65
|
+
* Контекст диалогового окна, в котором открыт компонент.
|
|
66
|
+
*/
|
|
67
|
+
this.context = inject(POLYMORPHEUS_CONTEXT, { optional: true });
|
|
68
|
+
/**
|
|
69
|
+
* Сервис для работы с каталогом.
|
|
70
|
+
*/
|
|
71
|
+
this.catalogService = inject(ScCatalogService);
|
|
72
|
+
/**
|
|
73
|
+
* {@link Observable} списка товаров категории.
|
|
74
|
+
*/
|
|
75
|
+
this.products$ = toObservable(this.categoryId).pipe(switchMap((categoryId) => {
|
|
76
|
+
if (!categoryId) {
|
|
77
|
+
return of([]);
|
|
78
|
+
}
|
|
79
|
+
return this.catalogService.getProductsCategoryCached$({ categoryId: Number(categoryId) }).pipe(map((products) => products ?? []));
|
|
80
|
+
}));
|
|
81
|
+
/**
|
|
82
|
+
* Выбранный продукт.
|
|
83
|
+
*/
|
|
84
|
+
this.product = new FormControl(null, { validators: Validators.required });
|
|
85
|
+
/**
|
|
86
|
+
* Сигнал текущего выбранного продукта — обновляется при `valueChanges` контрола `product`.
|
|
87
|
+
*/
|
|
88
|
+
this.productSignal = toSignal(tuiControlValue(this.product), { initialValue: null });
|
|
89
|
+
/**
|
|
90
|
+
* Сигнал содержимого FormArray позиций — пересчитывается при любом изменении значений.
|
|
91
|
+
*/
|
|
92
|
+
this.itemsValue = toSignal(tuiControlValue(this.items).pipe(map(() => this.items.controls.map((c) => c.getRawValue()))), {
|
|
93
|
+
initialValue: [],
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* Признак того, что выполняется запрос на отправку данных.
|
|
97
|
+
*/
|
|
98
|
+
this.isSubmitLoading = computed(() => this.itemStates().includes('loading'));
|
|
99
|
+
/**
|
|
100
|
+
* Состояние отправки каждой позиции — параллельный массив к контролу `items` формы.
|
|
101
|
+
*/
|
|
102
|
+
this.itemStates = signal([]);
|
|
103
|
+
/**
|
|
104
|
+
* Признак режима редактирования существующей позиции — `orderItem` задан.
|
|
105
|
+
*/
|
|
106
|
+
this.isEditingExistingItem = computed(() => this.orderItem() != null);
|
|
107
|
+
/**
|
|
108
|
+
* Признак того, что отправлять больше нечего — все позиции либо успешно
|
|
109
|
+
* отправлены, либо находятся в процессе отправки.
|
|
110
|
+
*/
|
|
111
|
+
this.hasNoPendingItems = computed(() => {
|
|
112
|
+
const states = this.itemStates();
|
|
113
|
+
if (this.items.length === 0) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
return this.items.controls.every((_, index) => {
|
|
117
|
+
const state = states[index] ?? IDLE_ITEM_STATE;
|
|
118
|
+
return state === 'success' || state === 'loading';
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
/**
|
|
122
|
+
* Суммарная площадь всех позиций (м²), рассчитанная локально.
|
|
123
|
+
*/
|
|
124
|
+
this.totalAreaM2 = computed(() => {
|
|
125
|
+
let total = 0;
|
|
126
|
+
this.itemsValue().forEach((value) => {
|
|
127
|
+
total += this.rowTotalPartsAreaM2(value);
|
|
128
|
+
});
|
|
129
|
+
return total;
|
|
130
|
+
});
|
|
131
|
+
/**
|
|
132
|
+
* Итоговая стоимость по всем позициям (локальный расчёт).
|
|
133
|
+
*/
|
|
134
|
+
this.totalCost = computed(() => {
|
|
135
|
+
const cost = this.productSignal()?.costRub ?? 0;
|
|
136
|
+
const area = this.totalAreaM2();
|
|
137
|
+
return Math.round(area * cost * 100) / 100;
|
|
138
|
+
});
|
|
139
|
+
/**
|
|
140
|
+
* Текст ограничения по ширине («от … до …»), пока есть выбранный товар.
|
|
141
|
+
*/
|
|
142
|
+
this.widthRangeText = computed(() => this.formatRange(this.settings()?.minWidth ?? null, this.productSignal()?.properties?.width ?? null, 'мм'));
|
|
143
|
+
/**
|
|
144
|
+
* Текст ограничения по длине («от … до …»), пока есть выбранный товар.
|
|
145
|
+
*/
|
|
146
|
+
this.lengthRangeText = computed(() => this.formatRange(this.settings()?.minLength ?? null, this.productSignal()?.properties?.length ?? null, 'мм'));
|
|
147
|
+
/**
|
|
148
|
+
* Ссылка для автоматического управления уничтожением зависимостей.
|
|
149
|
+
*/
|
|
150
|
+
this.destroyRef = inject(DestroyRef);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Валидаторы ширины/длины: пока товар не выбран — не накладываем min/max каталога (поля read-only без товара).
|
|
154
|
+
*
|
|
155
|
+
* @param min Нижняя граница размера из настроек конфигуратора.
|
|
156
|
+
* @param maxUpper Верхняя граница из свойств выбранного товара.
|
|
157
|
+
*/
|
|
158
|
+
dimensionValidators(min, maxUpper) {
|
|
159
|
+
const chosenProduct = this.product.value;
|
|
160
|
+
if (!chosenProduct) {
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
return [Validators.required, Validators.min(min), ...(maxUpper != null && maxUpper > 0 ? [Validators.max(maxUpper)] : []), stepValidator(1)];
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Обновляет валидаторы размерных полей после смены товара или настроек.
|
|
167
|
+
*/
|
|
168
|
+
updateItemsValidators() {
|
|
169
|
+
const settings = this.settings();
|
|
170
|
+
const minWidth = settings?.minWidth ?? 0.01;
|
|
171
|
+
const minLength = settings?.minLength ?? 0.01;
|
|
172
|
+
const chosenProduct = this.product.value;
|
|
173
|
+
this.items.controls.forEach((group) => {
|
|
174
|
+
group.get('width')?.setValidators(this.dimensionValidators(minWidth, chosenProduct?.properties?.width));
|
|
175
|
+
group.get('length')?.setValidators(this.dimensionValidators(minLength, chosenProduct?.properties?.length));
|
|
176
|
+
group.get('width')?.updateValueAndValidity({ emitEvent: false });
|
|
177
|
+
group.get('length')?.updateValueAndValidity({ emitEvent: false });
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Форматирование диапазона «от … до …» с учётом отсутствующих границ.
|
|
182
|
+
*
|
|
183
|
+
* @param min Нижняя граница диапазона.
|
|
184
|
+
* @param max Верхняя граница диапазона.
|
|
185
|
+
* @param unit Единица измерения для подписи.
|
|
186
|
+
*/
|
|
187
|
+
// eslint-disable-next-line class-methods-use-this
|
|
188
|
+
formatRange(min, max, unit) {
|
|
189
|
+
const hasMin = min != null && min > 0;
|
|
190
|
+
const hasMax = max != null && max > 0;
|
|
191
|
+
if (!hasMin && !hasMax) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
if (hasMin && hasMax) {
|
|
195
|
+
return `от ${min} ${unit} до ${max} ${unit}`;
|
|
196
|
+
}
|
|
197
|
+
if (hasMin) {
|
|
198
|
+
return `от ${min} ${unit}`;
|
|
199
|
+
}
|
|
200
|
+
return `до ${max} ${unit}`;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Массив изделий.
|
|
204
|
+
*/
|
|
205
|
+
get items() {
|
|
206
|
+
return this.form.controls.items;
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* {@inheritDoc}
|
|
210
|
+
*/
|
|
211
|
+
ngOnInit() {
|
|
212
|
+
this.setDefaultFormValue();
|
|
213
|
+
this.products$.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((products) => {
|
|
214
|
+
if (this.product.value != null || products.length === 0) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
/* При загрузке списка автоматически выбираем первый материал. */
|
|
218
|
+
this.product.setValue(products[0], { emitEvent: true });
|
|
219
|
+
});
|
|
220
|
+
this.product.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((chosenProduct) => {
|
|
221
|
+
this.updateItemsValidators();
|
|
222
|
+
if (chosenProduct) {
|
|
223
|
+
this.items.controls.forEach((item) => {
|
|
224
|
+
const value = item.getRawValue();
|
|
225
|
+
const maxW = chosenProduct.properties?.width;
|
|
226
|
+
const maxL = chosenProduct.properties?.length;
|
|
227
|
+
item.patchValue({
|
|
228
|
+
width: maxW ? Math.min(value.width, maxW) : value.width,
|
|
229
|
+
length: maxL ? Math.min(value.length, maxL) : value.length,
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
/*
|
|
233
|
+
* Смена продукта — сбрасываем состояние позиций: границы каталога изменились,
|
|
234
|
+
* успешная отправка больше не отражает текущее состояние.
|
|
235
|
+
*/
|
|
236
|
+
this.resetAllItemStates();
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Создает группу для изделия.
|
|
242
|
+
*
|
|
243
|
+
* @param item Параметры изделия.
|
|
244
|
+
* @param item.width Ширина изделия.
|
|
245
|
+
* @param item.length Длина изделия.
|
|
246
|
+
* @param item.count Количество изделий.
|
|
247
|
+
* @param item.marker Маркер позиции.
|
|
248
|
+
*/
|
|
249
|
+
createItemGroup(item) {
|
|
250
|
+
const group = new FormGroup({
|
|
251
|
+
width: new FormControl(item?.width ?? 0, { nonNullable: true }),
|
|
252
|
+
length: new FormControl(item?.length ?? 0, { nonNullable: true }),
|
|
253
|
+
count: new FormControl(item?.count ?? 1, {
|
|
254
|
+
validators: [Validators.required, Validators.min(1), stepValidator(1)],
|
|
255
|
+
nonNullable: true,
|
|
256
|
+
}),
|
|
257
|
+
marker: new FormControl(item?.marker ?? null),
|
|
258
|
+
});
|
|
259
|
+
// Любое изменение значений позиции сбрасывает её состояние отправки —
|
|
260
|
+
// ранее успешный submit становится неактуальным при правке полей,
|
|
261
|
+
// ошибку валидации сервера тоже сбрасываем.
|
|
262
|
+
group.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(() => {
|
|
263
|
+
const index = this.items.controls.indexOf(group);
|
|
264
|
+
if (index !== -1) {
|
|
265
|
+
this.resetItemState(index);
|
|
266
|
+
['width', 'length', 'count', 'marker'].forEach((field) => {
|
|
267
|
+
const control = group.get(field);
|
|
268
|
+
if (control?.hasError('serverResponse')) {
|
|
269
|
+
const errors = { ...control.errors };
|
|
270
|
+
delete errors['serverResponse'];
|
|
271
|
+
control.setErrors(Object.keys(errors).length > 0 ? errors : null);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
return group;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Сбрасывает состояние одной позиции на `idle`, если оно было `success`/`error`.
|
|
280
|
+
*
|
|
281
|
+
* @param index Индекс позиции.
|
|
282
|
+
*/
|
|
283
|
+
resetItemState(index) {
|
|
284
|
+
const states = this.itemStates();
|
|
285
|
+
const current = states[index];
|
|
286
|
+
if (current === 'success' || current === 'error') {
|
|
287
|
+
const updated = [...states];
|
|
288
|
+
updated[index] = 'idle';
|
|
289
|
+
this.itemStates.set(updated);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Сбрасывает состояния всех позиций на `idle`.
|
|
294
|
+
*/
|
|
295
|
+
resetAllItemStates() {
|
|
296
|
+
this.itemStates.set(this.items.controls.map(() => IDLE_ITEM_STATE));
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Возвращает состояние позиции по индексу (по умолчанию `idle`).
|
|
300
|
+
*
|
|
301
|
+
* @param index Индекс позиции.
|
|
302
|
+
*/
|
|
303
|
+
getItemState(index) {
|
|
304
|
+
return this.itemStates()[index] ?? IDLE_ITEM_STATE;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Признак того, что позиция отправляется (поля должны быть заблокированы).
|
|
308
|
+
*
|
|
309
|
+
* @param index Индекс позиции.
|
|
310
|
+
*/
|
|
311
|
+
isItemLoading(index) {
|
|
312
|
+
return this.getItemState(index) === 'loading';
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Признак того, что позиция успешно отправлена и её поля нужно заблокировать.
|
|
316
|
+
*
|
|
317
|
+
* @param index Индекс позиции.
|
|
318
|
+
*/
|
|
319
|
+
isItemLocked(index) {
|
|
320
|
+
return this.getItemState(index) === 'success';
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Добавляет новое изделие в форму.
|
|
324
|
+
*/
|
|
325
|
+
addItem() {
|
|
326
|
+
this.items.push(this.createItemGroup());
|
|
327
|
+
this.itemStates.update((states) => [...states, 'idle']);
|
|
328
|
+
this.updateItemsValidators();
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Удаляет изделие из формы.
|
|
332
|
+
*
|
|
333
|
+
* @param index Индекс изделия.
|
|
334
|
+
*/
|
|
335
|
+
removeItem(index) {
|
|
336
|
+
this.items.removeAt(index);
|
|
337
|
+
this.itemStates.update((states) => {
|
|
338
|
+
const updated = [...states];
|
|
339
|
+
updated.splice(index, 1);
|
|
340
|
+
return updated;
|
|
341
|
+
});
|
|
342
|
+
this.updateItemsValidators();
|
|
343
|
+
}
|
|
344
|
+
/**
|
|
345
|
+
* Площадь одной единицы изделия без учёта количества, м².
|
|
346
|
+
*
|
|
347
|
+
* @param value Значения размеров изделия.
|
|
348
|
+
* @param value.width Ширина изделия.
|
|
349
|
+
* @param value.length Длина изделия.
|
|
350
|
+
*/
|
|
351
|
+
// eslint-disable-next-line class-methods-use-this
|
|
352
|
+
pieceAreaM2(value) {
|
|
353
|
+
const { width, length } = value;
|
|
354
|
+
if (!width || !length) {
|
|
355
|
+
return 0;
|
|
356
|
+
}
|
|
357
|
+
return (width * length) / 1_000_000;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Суммарная площадь по строке позиции: площадь единицы × количество, м².
|
|
361
|
+
*
|
|
362
|
+
* @param value Значения позиции.
|
|
363
|
+
* @param value.width Ширина изделия.
|
|
364
|
+
* @param value.length Длина изделия.
|
|
365
|
+
* @param value.count Количество изделий.
|
|
366
|
+
*/
|
|
367
|
+
rowTotalPartsAreaM2(value) {
|
|
368
|
+
const qty = value.count;
|
|
369
|
+
if (!qty || !value.width || value.length === 0) {
|
|
370
|
+
return 0;
|
|
371
|
+
}
|
|
372
|
+
return this.pieceAreaM2(value) * qty;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Возвращает приблизительную стоимость строки (локальный расчёт — на всю строку позиции).
|
|
376
|
+
*
|
|
377
|
+
* @param value Значения изделия.
|
|
378
|
+
* @param value.width Ширина изделия.
|
|
379
|
+
* @param value.length Длина изделия.
|
|
380
|
+
* @param value.count Количество изделий.
|
|
381
|
+
*/
|
|
382
|
+
rowCost(value) {
|
|
383
|
+
const area = this.rowTotalPartsAreaM2(value);
|
|
384
|
+
const cost = this.product.value?.costRub ?? 0;
|
|
385
|
+
return Math.round(area * cost * 100) / 100;
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Обновляет состояние позиции на указанное значение.
|
|
389
|
+
*
|
|
390
|
+
* @param index Индекс позиции.
|
|
391
|
+
* @param state Новое состояние.
|
|
392
|
+
*/
|
|
393
|
+
setItemState(index, state) {
|
|
394
|
+
this.itemStates.update((states) => {
|
|
395
|
+
const updated = [...states];
|
|
396
|
+
updated[index] = state;
|
|
397
|
+
return updated;
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Применяет ошибки серверной валидации к контролам формы.
|
|
402
|
+
* Сервер возвращает ключи вида `items.0.<field>` — переводим в фактический индекс позиции.
|
|
403
|
+
*
|
|
404
|
+
* @param error Ответ сервера.
|
|
405
|
+
* @param index Индекс позиции в форме.
|
|
406
|
+
*/
|
|
407
|
+
applyServerValidationErrors(error, index) {
|
|
408
|
+
if (!(error instanceof HttpErrorResponse)) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
const { errors, message } = error.error;
|
|
412
|
+
if (errors) {
|
|
413
|
+
Object.keys(errors).forEach((key) => {
|
|
414
|
+
this.form.get(['items', index, key])?.setErrors({ serverResponse: errors[key] });
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
else if (message) {
|
|
418
|
+
this.form.setErrors({ serverResponse: [message] });
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Обработчик добавления/редактирования продукта в корзине.
|
|
423
|
+
*/
|
|
424
|
+
onSubmit() {
|
|
425
|
+
if (this.form.invalid || !this.product.value) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
const productId = this.product.value.id;
|
|
429
|
+
const productCategoryId = Number(this.categoryId());
|
|
430
|
+
const configurator = this.editor();
|
|
431
|
+
const orderData = this.orderItem();
|
|
432
|
+
const indexesToSubmit = this.items.controls
|
|
433
|
+
.map((_, index) => index)
|
|
434
|
+
.filter((index) => {
|
|
435
|
+
const state = this.getItemState(index);
|
|
436
|
+
return state !== 'success' && state !== 'loading';
|
|
437
|
+
});
|
|
438
|
+
if (indexesToSubmit.length === 0) {
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
// Позиции отправляются последовательно: каждая следующая — только после ответа предыдущей.
|
|
442
|
+
// При ошибке цепочка прерывается; диалог не закрывается.
|
|
443
|
+
from(indexesToSubmit)
|
|
444
|
+
.pipe(concatMap((index, position) => {
|
|
445
|
+
// Editing-режим: первая позиция (index 0) обновляется, остальные добавляются.
|
|
446
|
+
const isEdit = orderData != null && index === 0 && position === 0;
|
|
447
|
+
this.setItemState(index, 'loading');
|
|
448
|
+
return this.buildItemRequest$(index, productId, productCategoryId, configurator, isEdit, orderData).pipe(tap(() => {
|
|
449
|
+
this.setItemState(index, 'success');
|
|
450
|
+
}), catchError((error) => {
|
|
451
|
+
this.applyServerValidationErrors(error, index);
|
|
452
|
+
this.setItemState(index, 'error');
|
|
453
|
+
return throwError(() => error);
|
|
454
|
+
}));
|
|
455
|
+
}), takeUntilDestroyed(this.destroyRef))
|
|
456
|
+
.subscribe({
|
|
457
|
+
complete: () => {
|
|
458
|
+
if (this.context) {
|
|
459
|
+
this.context.$implicit.complete();
|
|
460
|
+
}
|
|
461
|
+
else {
|
|
462
|
+
this.setDefaultFormValue();
|
|
463
|
+
}
|
|
464
|
+
},
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Формирует HTTP-запрос для одной позиции формы.
|
|
469
|
+
*
|
|
470
|
+
* @param index Индекс позиции в форме.
|
|
471
|
+
* @param productId Идентификатор выбранного продукта.
|
|
472
|
+
* @param productCategoryId Идентификатор категории.
|
|
473
|
+
* @param configurator Название конфигуратора.
|
|
474
|
+
* @param isEdit Режим обновления существующей позиции.
|
|
475
|
+
* @param orderData Текущая позиция заказа (только в режиме редактирования).
|
|
476
|
+
*/
|
|
477
|
+
buildItemRequest$(index, productId, productCategoryId, configurator, isEdit, orderData) {
|
|
478
|
+
const itemValue = this.items.at(index).getRawValue();
|
|
479
|
+
const payload = this.convertersService.removeNull({
|
|
480
|
+
productCategoryId,
|
|
481
|
+
configurator,
|
|
482
|
+
productId,
|
|
483
|
+
width: itemValue.width,
|
|
484
|
+
length: itemValue.length,
|
|
485
|
+
quantity: itemValue.count,
|
|
486
|
+
marker: itemValue.marker,
|
|
487
|
+
});
|
|
488
|
+
return isEdit && orderData != null
|
|
489
|
+
? this.orderService.updateProduct$(orderData.id, payload, this.orderId)
|
|
490
|
+
: this.orderService.addProduct$(payload, this.orderId);
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* Устанавливает начальные значения для полей формы.
|
|
494
|
+
*/
|
|
495
|
+
setDefaultFormValue() {
|
|
496
|
+
this.form.reset({
|
|
497
|
+
productCategoryId: Number(this.categoryId()),
|
|
498
|
+
configurator: this.editor(),
|
|
499
|
+
});
|
|
500
|
+
this.items.clear();
|
|
501
|
+
const orderItem = this.orderItem();
|
|
502
|
+
this.items.push(this.createItemGroup({
|
|
503
|
+
width: (orderItem?.width ?? 0) * 1000,
|
|
504
|
+
length: (orderItem?.length ?? 0) * 1000,
|
|
505
|
+
count: orderItem?.quantity ?? 1,
|
|
506
|
+
marker: orderItem?.marker ?? null,
|
|
507
|
+
}));
|
|
508
|
+
this.itemStates.set(this.items.controls.map(() => IDLE_ITEM_STATE));
|
|
509
|
+
this.updateItemsValidators();
|
|
510
|
+
this.form.markAsUntouched();
|
|
511
|
+
}
|
|
512
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichM2Component, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
513
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScSandwichM2Component, isStandalone: true, selector: "sc-sandwich-m2", inputs: { settings: { classPropertyName: "settings", publicName: "settings", isSignal: true, isRequired: false, transformFunction: null }, categoryId: { classPropertyName: "categoryId", publicName: "categoryId", isSignal: true, isRequired: true, transformFunction: null }, editor: { classPropertyName: "editor", publicName: "editor", isSignal: true, isRequired: true, transformFunction: null }, orderItem: { classPropertyName: "orderItem", publicName: "orderItem", isSignal: true, isRequired: true, transformFunction: null }, orderId: { classPropertyName: "orderId", publicName: "orderId", isSignal: false, isRequired: false, transformFunction: null } }, outputs: { toggleShowEvent: "toggleShowEvent" }, providers: [
|
|
514
|
+
tuiNumberFormatProvider({ precision: 0 }),
|
|
515
|
+
tuiInputNumberOptionsProvider({
|
|
516
|
+
min: 0,
|
|
517
|
+
}),
|
|
518
|
+
tuiItemsHandlersProvider({
|
|
519
|
+
stringify: signal((x) => x.name),
|
|
520
|
+
identityMatcher: signal((a, b) => a.id === b.id),
|
|
521
|
+
}),
|
|
522
|
+
], ngImport: i0, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let products = products$ | async;\n @let productValue = product.value;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub !== undefined) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014\n {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u043C\u00B2\n </div>\n }\n\n @if (productValue) {\n <div class=\"mt-4 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @let wt = widthRangeText();\n @let lt = lengthRangeText();\n @if (wt) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ wt }}.</div>\n }\n @if (lt) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lt }}.</div>\n }\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n @if ($index > 0) {\n <hr class=\"border-sc-grey h-px\" />\n }\n @let itemIndex = $index;\n <div\n class=\"relative flex flex-col gap-1\"\n [formGroupName]=\"itemIndex\"\n >\n @if (isItemLocked(itemIndex)) {\n <div class=\"pointer-events-none absolute right-3 bottom-0 z-10 flex size-8 items-center justify-center\">\n <tui-icon\n icon=\"@tui.check\"\n class=\"text-tui-status-positive\"\n />\n </div>\n }\n <tui-loader [showLoader]=\"isItemLoading(itemIndex)\">\n <div\n [class.opacity-70]=\"isItemLocked(itemIndex)\"\n class=\"flex min-w-0 items-start gap-2\"\n >\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-3 lg:!flex-row lg:!items-start lg:!gap-6\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 1: \u0448\u0438\u0440\u0438\u043D\u0430 + \u0434\u043B\u0438\u043D\u0430 -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!flex-[2]\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 2: \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E + \u043C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 (\u043D\u0430 lg 1fr | 2fr) -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!grid-cols-[1fr_2fr] lg:!flex-[3]\">\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n </div>\n\n @let rowVal = item.getRawValue();\n\n @if (rowVal.width > 0 && rowVal.length > 0) {\n <div class=\"mt-1 flex flex-col gap-y-1 text-sm lg:!flex-row lg:!gap-6\">\n @if (pieceAreaM2(rowVal) > 0) {\n <div class=\"lg:!flex-[2]\">\n \u041F\u043B\u043E\u0449\u0430\u0434\u044C (S) =\n <span class=\"font-bold\">{{ pieceAreaM2(rowVal) | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue && rowCost(rowVal) > 0) {\n <div class=\"lg:!flex-[3]\">\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"font-bold\">{{ rowCost(rowVal).toLocaleString() }} {{ productValue.currency.symbol }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (!isEditingExistingItem()) {\n <button\n tuiIconButton\n title=\"\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\"\n (click)=\"removeItem(itemIndex)\"\n [disabled]=\"items.length <= 1 || !product.value || isItemLoading(itemIndex)\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6 shrink-0 lg:!ml-4\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n }\n </div>\n </tui-loader>\n </div>\n }\n </div>\n\n @if (productValue) {\n <hr class=\"border-sc-grey h-px\" />\n <div class=\"flex flex-wrap items-end gap-4 pt-2\">\n @if (!isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n class=\"self-start\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n\n <div class=\"ml-auto min-w-0 gap-1 text-right\">\n @if (totalAreaM2() > 0) {\n <div>\n \u041E\u0431\u0449\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C:\n <span class=\"font-bold\">{{ totalAreaM2() | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue.costRub && totalCost() > 0) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"> {{ totalCost().toLocaleString() }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"self-start\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:36rem}.row-summary{color:var(--tui-text-secondary);font-size:.75rem}\n"], dependencies: [{ kind: "directive", type: TuiButton, selector: "a[tuiButton],button[tuiButton],a[tuiIconButton],button[tuiIconButton]", inputs: ["size"] }, { 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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["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: i1.FormArrayName, selector: "[formArrayName]", inputs: ["formArrayName"] }, { kind: "ngmodule", type: ScNextInputFocusModule }, { kind: "directive", type: i2.ScNextInputFocusDirective, selector: "form[ScNextInputFocus]" }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "component", type: TuiDataListWrapperComponent, selector: "tui-data-list-wrapper:not([labels]), tui-data-list-wrapper:not([labels])[new]", inputs: ["items", "disabledItemHandler", "emptyContent", "size", "itemContent"], outputs: ["itemClick"] }, { kind: "component", type: TuiError, selector: "tui-error", inputs: ["error"] }, { kind: "component", type: i3.TuiTextfieldComponent, selector: "tui-textfield:not([multi])" }, { kind: "directive", type: i3.TuiTextfieldDirective, selector: "input[tuiTextfield]:not([tuiInputCard]):not([tuiInputExpire]):not([tuiInputCVC])" }, { kind: "directive", type: i3.TuiTextfieldOptionsDirective, selector: "[tuiTextfieldAppearance],[tuiTextfieldSize],[tuiTextfieldCleaner]", inputs: ["tuiTextfieldAppearance", "tuiTextfieldSize", "tuiTextfieldCleaner"] }, { kind: "directive", type: i3.TuiTextfieldDropdownDirective, selector: "ng-template[tuiTextfieldDropdown]" }, { kind: "directive", type: TuiChevron, selector: "[tuiChevron]", inputs: ["tuiChevron"] }, { kind: "directive", type: i4.TuiSelectDirective, selector: "input[tuiSelect]" }, { kind: "directive", type: i4.TuiInputNumberDirective, selector: "input[tuiInputNumber]", inputs: ["min", "max", "prefix", "postfix"] }, { kind: "directive", type: TuiNumberFormat, selector: "[tuiNumberFormat]", inputs: ["tuiNumberFormat"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: DecimalPipe, name: "number" }, { kind: "pipe", type: TuiFieldErrorPipe, name: "tuiFieldError" }, { kind: "component", type: i5.TuiSliderComponent, selector: "input[type=range][tuiSlider]", inputs: ["size", "segments"] }, { kind: "directive", type: i4.TuiInputSliderDirective, selector: "input[tuiInputSlider]" }, { 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: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "component", type: TuiButtonLoading, selector: "[tuiButton][loading],[tuiIconButton][loading]", inputs: ["size", "loading"] }, { kind: "component", type: TuiIcon, selector: "tui-icon", inputs: ["icon", "background"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
523
|
+
}
|
|
524
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScSandwichM2Component, decorators: [{
|
|
525
|
+
type: Component,
|
|
526
|
+
args: [{ standalone: true, selector: 'sc-sandwich-m2', imports: [
|
|
527
|
+
TuiButton,
|
|
528
|
+
FormsModule,
|
|
529
|
+
ReactiveFormsModule,
|
|
530
|
+
ScNextInputFocusModule,
|
|
531
|
+
TuiLabel,
|
|
532
|
+
TuiDataListWrapperComponent,
|
|
533
|
+
TuiError,
|
|
534
|
+
TuiTextfield,
|
|
535
|
+
TuiChevron,
|
|
536
|
+
TuiSelect,
|
|
537
|
+
TuiInputNumber,
|
|
538
|
+
TuiNumberFormat,
|
|
539
|
+
AsyncPipe,
|
|
540
|
+
DecimalPipe,
|
|
541
|
+
TuiFieldErrorPipe,
|
|
542
|
+
TuiInputSlider,
|
|
543
|
+
ScSelectOnFocusinDirective,
|
|
544
|
+
TuiLoader,
|
|
545
|
+
TuiButtonLoading,
|
|
546
|
+
TuiIcon,
|
|
547
|
+
], providers: [
|
|
548
|
+
tuiNumberFormatProvider({ precision: 0 }),
|
|
549
|
+
tuiInputNumberOptionsProvider({
|
|
550
|
+
min: 0,
|
|
551
|
+
}),
|
|
552
|
+
tuiItemsHandlersProvider({
|
|
553
|
+
stringify: signal((x) => x.name),
|
|
554
|
+
identityMatcher: signal((a, b) => a.id === b.id),
|
|
555
|
+
}),
|
|
556
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (!orderItem() && settings()?.allowShowTable) {\n <div class=\"mb-5 flex justify-center\">\n <button\n tuiButton\n appearance=\"secondary\"\n (click)=\"toggleShowEvent.emit()\"\n type=\"button\"\n iconStart=\"@tui.layout-list\"\n >\n \u041F\u043E\u043A\u0430\u0437\u0430\u0442\u044C \u0432 \u0432\u0438\u0434\u0435 \u0441\u043F\u0438\u0441\u043A\u0430\n </button>\n </div>\n}\n<div class=\"\">\n @let products = products$ | async;\n @let productValue = product.value;\n\n <form\n [formGroup]=\"form\"\n (ngSubmit)=\"onSubmit()\"\n ScNextInputFocus\n class=\"flex flex-col gap-2\"\n >\n <label\n tuiLabel\n class=\"grow\"\n >\n \u0422\u043E\u0432\u0430\u0440\n <tui-textfield\n tuiChevron\n [tuiTextfieldCleaner]=\"false\"\n >\n <input\n tuiChevron\n tuiSelect\n [formControl]=\"product\"\n placeholder=\"\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043C\u0430\u0442\u0435\u0440\u0438\u0430\u043B\"\n />\n\n <tui-data-list-wrapper\n *tuiTextfieldDropdown\n new\n [items]=\"products\"\n />\n </tui-textfield>\n <tui-error\n [formControl]=\"product\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n @if (productValue && productValue.costRub !== undefined) {\n <div class=\"-mt-1 text-sm text-tui-text-secondary\">\n <span class=\"font-bold\">{{ productValue.code }}</span>\n \u2014\n {{ productValue.costRub.toLocaleString() }} {{ productValue.currency.symbol }}/\u043C\u00B2\n </div>\n }\n\n @if (productValue) {\n <div class=\"mt-4 flex flex-col gap-1.5\">\n <div class=\"w-full font-bold\">\u0420\u0430\u0437\u043C\u0435\u0440\u044B \u0438\u0437\u0434\u0435\u043B\u0438\u0439</div>\n <div class=\"flex flex-col gap-1 text-sm text-tui-text-secondary\">\n @let wt = widthRangeText();\n @let lt = lengthRangeText();\n @if (wt) {\n <div>\u0428\u0438\u0440\u0438\u043D\u0430 {{ wt }}.</div>\n }\n @if (lt) {\n <div>\u0414\u043B\u0438\u043D\u0430 {{ lt }}.</div>\n }\n </div>\n </div>\n }\n\n <div class=\"flex flex-col gap-3\">\n <div\n formArrayName=\"items\"\n class=\"flex flex-col gap-3\"\n >\n @for (item of items.controls; track item) {\n @if ($index > 0) {\n <hr class=\"border-sc-grey h-px\" />\n }\n @let itemIndex = $index;\n <div\n class=\"relative flex flex-col gap-1\"\n [formGroupName]=\"itemIndex\"\n >\n @if (isItemLocked(itemIndex)) {\n <div class=\"pointer-events-none absolute right-3 bottom-0 z-10 flex size-8 items-center justify-center\">\n <tui-icon\n icon=\"@tui.check\"\n class=\"text-tui-status-positive\"\n />\n </div>\n }\n <tui-loader [showLoader]=\"isItemLoading(itemIndex)\">\n <div\n [class.opacity-70]=\"isItemLocked(itemIndex)\"\n class=\"flex min-w-0 items-start gap-2\"\n >\n <div class=\"flex min-w-0 flex-1 flex-col gap-3\">\n <div class=\"flex flex-col gap-3 lg:!flex-row lg:!items-start lg:!gap-6\">\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 1: \u0448\u0438\u0440\u0438\u043D\u0430 + \u0434\u043B\u0438\u043D\u0430 -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!flex-[2]\">\n <label tuiLabel>\n \u0428\u0438\u0440\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"width\"\n [min]=\"settings()?.minWidth ?? 0\"\n [max]=\"product.value?.properties?.width ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0428\u0438\u0440\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"width\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u0414\u043B\u0438\u043D\u0430, \u043C\u043C\n <tui-textfield>\n <input\n tuiInputSlider\n formControlName=\"length\"\n [min]=\"settings()?.minLength ?? 0\"\n [max]=\"product.value?.properties?.length ?? 0\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u0414\u043B\u0438\u043D\u0430\"\n autocomplete=\"off\"\n />\n @if (product.value) {\n <input\n tuiSlider\n type=\"range\"\n />\n }\n </tui-textfield>\n <tui-error\n formControlName=\"length\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n\n <!-- \u0413\u0440\u0443\u043F\u043F\u0430 2: \u043A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E + \u043C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430 (\u043D\u0430 lg 1fr | 2fr) -->\n <div class=\"grid grid-cols-1 gap-2 sm:grid-cols-2 lg:!grid-cols-[1fr_2fr] lg:!flex-[3]\">\n <label tuiLabel>\n <span class=\"whitespace-nowrap\">\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E, \u0448\u0442</span>\n <tui-textfield [tuiTextfieldCleaner]=\"false\">\n <input\n tuiInputNumber\n formControlName=\"count\"\n [min]=\"1\"\n [tuiNumberFormat]=\"{ precision: 0 }\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041A\u043E\u043B\u0438\u0447\u0435\u0441\u0442\u0432\u043E\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"count\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <label tuiLabel>\n \u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\n <tui-textfield>\n <input\n tuiTextfield\n formControlName=\"marker\"\n [readOnly]=\"!product.value || isItemLocked(itemIndex) || isItemLoading(itemIndex)\"\n placeholder=\"\u041C\u0430\u0440\u043A\u0438\u0440\u043E\u0432\u043A\u0430\"\n autocomplete=\"off\"\n />\n </tui-textfield>\n <tui-error\n formControlName=\"marker\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n </div>\n </div>\n\n @let rowVal = item.getRawValue();\n\n @if (rowVal.width > 0 && rowVal.length > 0) {\n <div class=\"mt-1 flex flex-col gap-y-1 text-sm lg:!flex-row lg:!gap-6\">\n @if (pieceAreaM2(rowVal) > 0) {\n <div class=\"lg:!flex-[2]\">\n \u041F\u043B\u043E\u0449\u0430\u0434\u044C (S) =\n <span class=\"font-bold\">{{ pieceAreaM2(rowVal) | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue && rowCost(rowVal) > 0) {\n <div class=\"lg:!flex-[3]\">\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"font-bold\">{{ rowCost(rowVal).toLocaleString() }} {{ productValue.currency.symbol }}</span>\n </div>\n }\n </div>\n }\n </div>\n\n @if (!isEditingExistingItem()) {\n <button\n tuiIconButton\n title=\"\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\"\n (click)=\"removeItem(itemIndex)\"\n [disabled]=\"items.length <= 1 || !product.value || isItemLoading(itemIndex)\"\n size=\"m\"\n type=\"button\"\n iconStart=\"@tui.trash-2\"\n appearance=\"secondary\"\n class=\"mt-6 shrink-0 lg:!ml-4\"\n [style.flex]=\"'0 0 auto'\"\n ></button>\n }\n </div>\n </tui-loader>\n </div>\n }\n </div>\n\n @if (productValue) {\n <hr class=\"border-sc-grey h-px\" />\n <div class=\"flex flex-wrap items-end gap-4 pt-2\">\n @if (!isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\n class=\"self-start\"\n iconStart=\"@tui.plus\"\n >\n \u0414\u043E\u0431\u0430\u0432\u0438\u0442\u044C \u0438\u0437\u0434\u0435\u043B\u0438\u0435\n </button>\n }\n\n <div class=\"ml-auto min-w-0 gap-1 text-right\">\n @if (totalAreaM2() > 0) {\n <div>\n \u041E\u0431\u0449\u0430\u044F \u043F\u043B\u043E\u0449\u0430\u0434\u044C:\n <span class=\"font-bold\">{{ totalAreaM2() | number: '1.0-4' }} \u043C\u00B2</span>\n </div>\n }\n @if (productValue.costRub && totalCost() > 0) {\n <div>\n \u0418\u0442\u043E\u0433\u043E:\n <span class=\"whitespace-nowrap text-xl font-bold\"> {{ totalCost().toLocaleString() }} {{ productValue.currency.symbol }} </span>\n </div>\n }\n </div>\n </div>\n }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"self-start\"\n iconStart=\"@tui.check\"\n >\n {{ !orderItem() ? '\u0412 \u043A\u043E\u0440\u0437\u0438\u043D\u0443' : '\u0418\u0437\u043C\u0435\u043D\u0438\u0442\u044C' }}\n </button>\n </form>\n</div>\n", styles: [":host{display:block;width:100%;max-width:36rem}.row-summary{color:var(--tui-text-secondary);font-size:.75rem}\n"] }]
|
|
557
|
+
}], propDecorators: { orderId: [{
|
|
558
|
+
type: Input
|
|
559
|
+
}] } });
|
|
560
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Mtc2FuZHdpY2gtbTIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NvbmZpZ3VyYXRvcnMvc2FuZHdpY2hfbTIvc2Mtc2FuZHdpY2gtbTIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NvbmZpZ3VyYXRvcnMvc2FuZHdpY2hfbTIvc2Mtc2FuZHdpY2gtbTIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdUZBQXVGO0FBRXZGLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkksT0FBTyxFQUFFLGtCQUFrQixFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN4RixPQUFPLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixFQUFlLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlILE9BQU8sRUFDSCxlQUFlLEVBRWYsZ0JBQWdCLEVBQ2hCLG1CQUFtQixHQU90QixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDaEQsT0FBTyxFQUNILFNBQVMsRUFFVCxRQUFRLEVBQ1IsT0FBTyxFQUNQLHdCQUF3QixFQUN4QixRQUFRLEVBQ1IsU0FBUyxFQUNULGVBQWUsRUFDZix1QkFBdUIsRUFDdkIsWUFBWSxHQUNmLE1B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QWlCLDhRQUVqQiwwQkFBMEIsZ01BQzFCLFNBQVMsaUlBQ1QsZ0JBQWdCLHVIQUNoQixPQUFPOzs0RkFjRixxQkFBcUI7a0JBdkNqQyxTQUFTO2lDQUNNLElBQUksWUFDTixnQkFBZ0IsV0FHakI7d0JBQ0wsU0FBUzt3QkFDVCxXQUFXO3dCQUNYLG1CQUFtQjt3QkFDbkIsc0JBQXNCO3dCQUN0QixRQUFRO3dCQUNSLDJCQUEyQjt3QkFDM0IsUUFBUTt3QkFDUixZQUFZO3dCQUNaLFVBQVU7d0JBQ1YsU0FBUzt3QkFDVCxjQUFjO3dCQUNkLGVBQWU7d0JBQ2YsU0FBUzt3QkFDVCxXQUFXO3dCQUNYLGlCQUFpQjt3QkFDakIsY0FBYzt3QkFDZCwwQkFBMEI7d0JBQzFCLFNBQVM7d0JBQ1QsZ0JBQWdCO3dCQUNoQixPQUFPO3FCQUNWLGFBQ1U7d0JBQ1AsdUJBQXVCLENBQUMsRUFBRSxTQUFTLEVBQUUsQ0FBQyxFQUFFLENBQUM7d0JBQ3pDLDZCQUE2QixDQUFDOzRCQUMxQixHQUFHLEVBQUUsQ0FBQzt5QkFDVCxDQUFDO3dCQUNGLHdCQUF3QixDQUFDOzRCQUNyQixTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDOzRCQUMzQyxlQUFlLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBWSxFQUFFLENBQVksRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO3lCQUN6RSxDQUFDO3FCQUNMLG1CQUNnQix1QkFBdUIsQ0FBQyxNQUFNOzhCQTJCeEMsT0FBTztzQkFEYixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgc2VjdXJpdHkvZGV0ZWN0LW9iamVjdC1pbmplY3Rpb24sQHR5cGVzY3JpcHQtZXNsaW50L3VuYm91bmQtbWV0aG9kICovXG5cbmltcG9ydCB7IEFzeW5jUGlwZSwgRGVjaW1hbFBpcGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgSHR0cEVycm9yUmVzcG9uc2UgfSBmcm9tICdAYW5ndWxhci9jb21tb24vaHR0cCc7XG5pbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBjb21wdXRlZCwgRGVzdHJveVJlZiwgaW5qZWN0LCBJbnB1dCwgaW5wdXQsIE9uSW5pdCwgb3V0cHV0LCBzaWduYWwgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCwgdG9PYnNlcnZhYmxlLCB0b1NpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IEZvcm1BcnJheSwgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgRm9ybXNNb2R1bGUsIFJlYWN0aXZlRm9ybXNNb2R1bGUsIFZhbGlkYXRvckZuLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHtcbiAgICBTQ19PUkRFUl9MT0FERVIsXG4gICAgU2NDYXJ0LFxuICAgIFNjQ2F0YWxvZ1NlcnZpY2UsXG4gICAgU2NDb252ZXJ0ZXJzU2VydmljZSxcbiAgICBTY0lBcGlFcnJvclJlc3BvbnNlLFxuICAgIFNjSU5ld09yZGVySXRlbUJhc2UsXG4gICAgU2NJT3JkZXJFZGl0b3JMb2FkZXIsXG4gICAgU2NPcmRlckRyYWZ0LFxuICAgIFNjT3JkZXJJdGVtLFxuICAgIFNjUHJvZHVjdCxcbn0gZnJvbSAnQHNuYWJjZW50ci9jbGllbnQtY29yZSc7XG5pbXBvcnQgeyB0dWlDb250cm9sVmFsdWUgfSBmcm9tICdAdGFpZ2EtdWkvY2RrJztcbmltcG9ydCB7XG4gICAgVHVpQnV0dG9uLFxuICAgIFR1aURpYWxvZ0NvbnRleHQsXG4gICAgVHVpRXJyb3IsXG4gICAgVHVpSWNvbixcbiAgICB0dWlJdGVtc0hhbmRsZXJzUHJvdmlkZXIsXG4gICAgVHVpTGFiZWwsXG4gICAgVHVpTG9hZGVyLFxuICAgIFR1aU51bWJlckZvcm1hdCxcbiAgICB0dWlOdW1iZXJGb3JtYXRQcm92aWRlcixcbiAgICBUdWlUZXh0ZmllbGQsXG59IGZyb20gJ0B0YWlnYS11aS9jb3JlJztcbmltcG9ydCB7XG4gICAgVHVpQnV0dG9uTG9hZGluZyxcbiAgICBUdWlDaGV2cm9uLFxuICAgIFR1aURhdGFMaXN0V3JhcHBlckNvbXBvbmVudCxcbiAgICBUdWlGaWVsZEVycm9yUGlwZSxcbiAgICBUdWlJbnB1dE51bWJlcixcbiAgICB0dWlJbnB1dE51bWJlck9wdGlvbnNQcm92aWRlcixcbiAgICBUdWlJbnB1dFNsaWRlcixcbiAgICBUdWlTZWxlY3QsXG59IGZyb20gJ0B0YWlnYS11aS9raXQnO1xuaW1wb3J0IHsgUE9MWU1PUlBIRVVTX0NPTlRFWFQgfSBmcm9tICdAdGFpZ2EtdWkvcG9seW1vcnBoZXVzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIGNvbmNhdE1hcCwgZnJvbSwgbWFwLCBPYnNlcnZhYmxlLCBvZiwgc3dpdGNoTWFwLCB0YXAsIHRocm93RXJyb3IgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgU2NOZXh0SW5wdXRGb2N1c01vZHVsZSB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvbmV4dC1pbnB1dC1mb2N1cy9zYy1uZXh0LWlucHV0LWZvY3VzLm1vZHVsZSc7XG5pbXBvcnQgeyBTY1NlbGVjdE9uRm9jdXNpbkRpcmVjdGl2ZSB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvc2VsZWN0LW9uLWZvY3VzaW4vc2Mtc2VsZWN0LW9uLWZvY3VzaW4uZGlyZWN0aXZlJztcbmltcG9ydCB7IHN0ZXBWYWxpZGF0b3IgfSBmcm9tICcuLi8uLi92YWxpZGF0b3JzL3N0ZXAtdmFsaWRhdG9yJztcbmltcG9ydCB7IFNjSVNhbmR3aWNoTTJTZXR0aW5ncyB9IGZyb20gJy4uL21vZGVscy9zYW5kd2ljaF9tMi9zYy1pLXNhbmR3aWNoLW0yLXNldHRpbmdzJztcbmltcG9ydCB7IFNjSU5ld0NhcnRJdGVtU2FuZHdpY2hNMiB9IGZyb20gJy4vc2MtaS1uZXctY2FydC1pdGVtLXNhbmR3aWNoLW0yJztcbmltcG9ydCB7IElETEVfSVRFTV9TVEFURSwgU2NTYW5kd2ljaE0ySXRlbVN1Ym1pdFN0YXRlIH0gZnJvbSAnLi9zYy1zYW5kd2ljaC1tMi1pdGVtLXN1Ym1pdC1zdGF0ZSc7XG5cbi8qKlxuICog0JrQvtC90YTQuNCz0YPRgNCw0YLQvtGAINGA0LDRgdC/0LjQu9CwINGB0Y3QvdC00LLQuNGHLdC/0LDQvdC10LvQtdC5INC/0L4g0L/Qu9C+0YnQsNC00LguXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc2VsZWN0b3I6ICdzYy1zYW5kd2ljaC1tMicsXG4gICAgdGVtcGxhdGVVcmw6ICcuL3NjLXNhbmR3aWNoLW0yLmNvbXBvbmVudC5odG1sJyxcbiAgICBzdHlsZVVybDogJy4vc2Mtc2FuZHdpY2gtbTIuY29tcG9uZW50LnNjc3MnLFxuICAgIGltcG9ydHM6IFtcbiAgICAgICAgVHVpQnV0dG9uLFxuICAgICAgICBGb3Jtc01vZHVsZSxcbiAgICAgICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgICAgICAgU2NOZXh0SW5wdXRGb2N1c01vZHVsZSxcbiAgICAgICAgVHVpTGFiZWwsXG4gICAgICAgIFR1aURhdGFMaXN0V3JhcHBlckNvbXBvbmVudCxcbiAgICAgICAgVHVpRXJyb3IsXG4gICAgICAgIFR1aVRleHRmaWVsZCxcbiAgICAgICAgVHVpQ2hldnJvbixcbiAgICAgICAgVHVpU2VsZWN0LFxuICAgICAgICBUdWlJbnB1dE51bWJlcixcbiAgICAgICAgVHVpTnVtYmVyRm9ybWF0LFxuICAgICAgICBBc3luY1BpcGUsXG4gICAgICAgIERlY2ltYWxQaXBlLFxuICAgICAgICBUdWlGaWVsZEVycm9yUGlwZSxcbiAgICAgICAgVHVpSW5wdXRTbGlkZXIsXG4gICAgICAgIFNjU2VsZWN0T25Gb2N1c2luRGlyZWN0aXZlLFxuICAgICAgICBUdWlMb2FkZXIsXG4gICAgICAgIFR1aUJ1dHRvbkxvYWRpbmcsXG4gICAgICAgIFR1aUljb24sXG4gICAgXSxcbiAgICBwcm92aWRlcnM6IFtcbiAgICAgICAgdHVpTnVtYmVyRm9ybWF0UHJvdmlkZXIoeyBwcmVjaXNpb246IDAgfSksXG4gICAgICAgIHR1aUlucHV0TnVtYmVyT3B0aW9uc1Byb3ZpZGVyKHtcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgfSksXG4gICAgICAgIHR1aUl0ZW1zSGFuZGxlcnNQcm92aWRlcih7XG4gICAgICAgICAgICBzdHJpbmdpZnk6IHNpZ25hbCgoeDogU2NQcm9kdWN0KSA9PiB4Lm5hbWUpLFxuICAgICAgICAgICAgaWRlbnRpdHlNYXRjaGVyOiBzaWduYWwoKGE6IFNjUHJvZHVjdCwgYjogU2NQcm9kdWN0KSA9PiBhLmlkID09PSBiLmlkKSxcbiAgICAgICAgfSksXG4gICAgXSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgU2NTYW5kd2ljaE0yQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgICAvKipcbiAgICAgKiDQndCw0YHRgtGA0L7QudC60Lgg0LTQu9GPINC60L7QvdGE0LjQs9GD0YDQsNGC0L7RgNCwINGA0LDRgdC/0LjQu9CwINGB0Y3QvdC00LLQuNGHLdC/0LDQvdC10LvQtdC5INC/0L4g0L/Qu9C+0YnQsNC00LguXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IHNldHRpbmdzID0gaW5wdXQ8U2NJU2FuZHdpY2hNMlNldHRpbmdzPigpO1xuXG4gICAgLyoqXG4gICAgICog0JjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0LrQsNGC0LXQs9C+0YDQuNC4LlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSBjYXRlZ29yeUlkID0gaW5wdXQucmVxdWlyZWQ8bnVtYmVyIHwgc3RyaW5nPigpO1xuXG4gICAgLyoqXG4gICAgICog0J3QsNC30LLQsNC90LjQtSDQutC+0L3RhNC40LPRg9GA0LDRgtC+0YDQsC5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZWRpdG9yID0gaW5wdXQucmVxdWlyZWQ8c3RyaW5nPigpO1xuXG4gICAgLyoqXG4gICAgICog0J/QvtC30LjRhtC40Y8g0YLQvtCy0LDRgNCwL9GD0YHQu9GD0LPQuCDQsiDQutC+0YDQt9C40L3QtS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgb3JkZXJJdGVtID0gaW5wdXQucmVxdWlyZWQ8U2NPcmRlckl0ZW0gfCB1bmRlZmluZWQ+KCk7XG5cbiAgICAvKipcbiAgICAgKiDQmNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgCDQt9Cw0LrQsNC30LAuXG4gICAgICovXG4gICAgQElucHV0KClcbiAgICBwdWJsaWMgb3JkZXJJZD86IG51bWJlcjtcblxuICAgIC8qKlxuICAgICAqINCh0L7QsdGL0YLQuNC1INC/0LXRgNC10LrQu9GO0YfQtdC90LjRjyDQvtGC0L7QsdGA0LDQttC10L3QuNGPINGC0L7QstCw0YDQvtCyLlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSB0b2dnbGVTaG93RXZlbnQgPSBvdXRwdXQoKTtcblxuICAgIC8qKlxuICAgICAqINCk0L7RgNC80LAg0LTQvtCx0LDQstC70LXQvdC40Y8v0YDQtdC00LDQutGC0LjRgNC+0LLQsNC90LjRjyDQv9GA0L7QtNGD0LrRgtCwINCyINC60L7RgNC30LjQvdC1LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBmb3JtID0gbmV3IEZvcm1Hcm91cCh7XG4gICAgICAgIHByb2R1Y3RDYXRlZ29yeUlkOiBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyIHwgbnVsbD4obnVsbCwgeyB2YWxpZGF0b3JzOiBWYWxpZGF0b3JzLnJlcXVpcmVkIH0pLFxuICAgICAgICBjb25maWd1cmF0b3I6IG5ldyBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsLCB7IHZhbGlkYXRvcnM6IFZhbGlkYXRvcnMucmVxdWlyZWQgfSksXG4gICAgICAgIGl0ZW1zOiBuZXcgRm9ybUFycmF5PFJldHVyblR5cGU8U2NTYW5kd2ljaE0yQ29tcG9uZW50WydjcmVhdGVJdGVtR3JvdXAnXT4+KFtdKSxcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqINCh0LXRgNCy0LjRgSDQv9C+0LvRg9GH0LXQvdC40Y8g0Lgg0YDQtdC00LDQutGC0LjRgNC+0LLQsNC90LjRjyDRgdC/0LjRgdC60LAg0YLQvtCy0LDRgNC+0LIg0LfQsNC60LDQt9CwICjQutC+0YDQt9C40L3QsCAvINC30LDQutCw0LcgLyDRh9C10YDQvdC+0LLQuNC6ID0g0LfQsNC60LDQtykuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IG9yZGVyU2VydmljZSA9IGluamVjdDxTY0lPcmRlckVkaXRvckxvYWRlcjxTY09yZGVySXRlbSwgU2NDYXJ0IHwgU2NPcmRlckRyYWZ0Pj4oU0NfT1JERVJfTE9BREVSKTtcblxuICAgIC8qKlxuICAgICAqINCh0LXRgNCy0LjRgSDQutC+0L3QstC10YDRgtCw0YbQuNC4INC00LDQvdC90YvRhS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbnZlcnRlcnNTZXJ2aWNlOiBTY0NvbnZlcnRlcnNTZXJ2aWNlID0gaW5qZWN0KFNjQ29udmVydGVyc1NlcnZpY2UpO1xuXG4gICAgLyoqXG4gICAgICog0JrQvtC90YLQtdC60YHRgiDQtNC40LDQu9C+0LPQvtCy0L7Qs9C+INC+0LrQvdCwLCDQsiDQutC+0YLQvtGA0L7QvCDQvtGC0LrRgNGL0YIg0LrQvtC80L/QvtC90LXQvdGCLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY29udGV4dDogVHVpRGlhbG9nQ29udGV4dCB8IHVuZGVmaW5lZCA9IGluamVjdChQT0xZTU9SUEhFVVNfQ09OVEVYVCwgeyBvcHRpb25hbDogdHJ1ZSB9KSBhcyBUdWlEaWFsb2dDb250ZXh0IHwgdW5kZWZpbmVkO1xuXG4gICAgLyoqXG4gICAgICog0KHQtdGA0LLQuNGBINC00LvRjyDRgNCw0LHQvtGC0Ysg0YEg0LrQsNGC0LDQu9C+0LPQvtC8LlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY2F0YWxvZ1NlcnZpY2U6IFNjQ2F0YWxvZ1NlcnZpY2UgPSBpbmplY3QoU2NDYXRhbG9nU2VydmljZSk7XG5cbiAgICAvKipcbiAgICAgKiB7QGxpbmsgT2JzZXJ2YWJsZX0g0YHQv9C40YHQutCwINGC0L7QstCw0YDQvtCyINC60LDRgtC10LPQvtGA0LjQuC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgcHJvZHVjdHMkOiBPYnNlcnZhYmxlPFNjUHJvZHVjdFtdPiA9IHRvT2JzZXJ2YWJsZSh0aGlzLmNhdGVnb3J5SWQpLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgoY2F0ZWdvcnlJZCkgPT4ge1xuICAgICAgICAgICAgaWYgKCFjYXRlZ29yeUlkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG9mKFtdKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuY2F0YWxvZ1NlcnZpY2UuZ2V0UHJvZHVjdHNDYXRlZ29yeUNhY2hlZCQoeyBjYXRlZ29yeUlkOiBOdW1iZXIoY2F0ZWdvcnlJZCkgfSkucGlwZShtYXAoKHByb2R1Y3RzKSA9PiBwcm9kdWN0cyA/PyBbXSkpO1xuICAgICAgICB9KVxuICAgICk7XG5cbiAgICAvKipcbiAgICAgKiDQktGL0LHRgNCw0L3QvdGL0Lkg0L/RgNC+0LTRg9C60YIuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHByb2R1Y3QgPSBuZXcgRm9ybUNvbnRyb2w8U2NQcm9kdWN0IHwgbnVsbD4obnVsbCwgeyB2YWxpZGF0b3JzOiBWYWxpZGF0b3JzLnJlcXVpcmVkIH0pO1xuXG4gICAgLyoqXG4gICAgICog0KHQuNCz0L3QsNC7INGC0LXQutGD0YnQtdCz0L4g0LLRi9Cx0YDQsNC90L3QvtCz0L4g0L/RgNC+0LTRg9C60YLQsCDigJQg0L7QsdC90L7QstC70Y/QtdGC0YHRjyDQv9GA0LggYHZhbHVlQ2hhbmdlc2Ag0LrQvtC90YLRgNC+0LvQsCBgcHJvZHVjdGAuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHByb2R1Y3RTaWduYWwgPSB0b1NpZ25hbCh0dWlDb250cm9sVmFsdWU8U2NQcm9kdWN0IHwgbnVsbD4odGhpcy5wcm9kdWN0KSwgeyBpbml0aWFsVmFsdWU6IG51bGwgfSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC40LPQvdCw0Lsg0YHQvtC00LXRgNC20LjQvNC+0LPQviBGb3JtQXJyYXkg0L/QvtC30LjRhtC40Lkg4oCUINC/0LXRgNC10YHRh9C40YLRi9Cy0LDQtdGC0YHRjyDQv9GA0Lgg0LvRjtCx0L7QvCDQuNC30LzQtdC90LXQvdC40Lgg0LfQvdCw0YfQtdC90LjQuS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXRlbXNWYWx1ZSA9IHRvU2lnbmFsKHR1aUNvbnRyb2xWYWx1ZTx1bmtub3duW10+KHRoaXMuaXRlbXMpLnBpcGUobWFwKCgpID0+IHRoaXMuaXRlbXMuY29udHJvbHMubWFwKChjKSA9PiBjLmdldFJhd1ZhbHVlKCkpKSksIHtcbiAgICAgICAgaW5pdGlhbFZhbHVlOiBbXSBhcyBBcnJheTxSZXR1cm5UeXBlPFJldHVyblR5cGU8U2NTYW5kd2ljaE0yQ29tcG9uZW50WydjcmVhdGVJdGVtR3JvdXAnXT5bJ2dldFJhd1ZhbHVlJ10+PixcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC30L3QsNC6INGC0L7Qs9C+LCDRh9GC0L4g0LLRi9C/0L7Qu9C90Y/QtdGC0YHRjyDQt9Cw0L/RgNC+0YEg0L3QsCDQvtGC0L/RgNCw0LLQutGDINC00LDQvdC90YvRhS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNTdWJtaXRMb2FkaW5nID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5pdGVtU3RhdGVzKCkuaW5jbHVkZXMoJ2xvYWRpbmcnKSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC+0YHRgtC+0Y/QvdC40LUg0L7RgtC/0YDQsNCy0LrQuCDQutCw0LbQtNC+0Lkg0L/QvtC30LjRhtC40Lgg4oCUINC/0LDRgNCw0LvQu9C10LvRjNC90YvQuSDQvNCw0YHRgdC40LIg0Log0LrQvtC90YLRgNC+0LvRgyBgaXRlbXNgINGE0L7RgNC80YsuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGl0ZW1TdGF0ZXMgPSBzaWduYWw8U2NTYW5kd2ljaE0ySXRlbVN1Ym1pdFN0YXRlW10+KFtdKTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC30L3QsNC6INGA0LXQttC40LzQsCDRgNC10LTQsNC60YLQuNGA0L7QstCw0L3QuNGPINGB0YPRidC10YHRgtCy0YPRjtGJ0LXQuSDQv9C+0LfQuNGG0LjQuCDigJQgYG9yZGVySXRlbWAg0LfQsNC00LDQvS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNFZGl0aW5nRXhpc3RpbmdJdGVtID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5vcmRlckl0ZW0oKSAhPSBudWxsKTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC30L3QsNC6INGC0L7Qs9C+LCDRh9GC0L4g0L7RgtC/0YDQsNCy0LvRj9GC0Ywg0LHQvtC70YzRiNC1INC90LXRh9C10LPQviDigJQg0LLRgdC1INC/0L7Qt9C40YbQuNC4INC70LjQsdC+INGD0YHQv9C10YjQvdC+XG4gICAgICog0L7RgtC/0YDQsNCy0LvQtdC90YssINC70LjQsdC+INC90LDRhdC+0LTRj9GC0YHRjyDQsiDQv9GA0L7RhtC10YHRgdC1INC+0YLQv9GA0LDQstC60LguXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGhhc05vUGVuZGluZ0l0ZW1zID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgICAgICBjb25zdCBzdGF0ZXMgPSB0aGlzLml0ZW1TdGF0ZXMoKTtcblxuICAgICAgICBpZiAodGhpcy5pdGVtcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuaXRlbXMuY29udHJvbHMuZXZlcnkoKF8sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzdGF0ZSA9IHN0YXRlc1tpbmRleF0gPz8gSURMRV9JVEVNX1NUQVRFO1xuXG4gICAgICAgICAgICByZXR1cm4gc3RhdGUgPT09ICdzdWNjZXNzJyB8fCBzdGF0ZSA9PT0gJ2xvYWRpbmcnO1xuICAgICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8qKlxuICAgICAqINCh0YPQvNC80LDRgNC90LDRjyDQv9C70L7RidCw0LTRjCDQstGB0LXRhSDQv9C+0LfQuNGG0LjQuSAo0LzCsiksINGA0LDRgdGB0YfQuNGC0LDQvdC90LDRjyDQu9C+0LrQsNC70YzQvdC+LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSB0b3RhbEFyZWFNMiA9IGNvbXB1dGVkKCgpID0+IHtcbiAgICAgICAgbGV0IHRvdGFsID0gMDtcblxuICAgICAgICB0aGlzLml0ZW1zVmFsdWUoKS5mb3JFYWNoKCh2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgdG90YWwgKz0gdGhpcy5yb3dUb3RhbFBhcnRzQXJlYU0yKHZhbHVlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRvdGFsO1xuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICog0JjRgtC+0LPQvtCy0LDRjyDRgdGC0L7QuNC80L7RgdGC0Ywg0L/QviDQstGB0LXQvCDQv9C+0LfQuNGG0LjRj9C8ICjQu9C+0LrQsNC70YzQvdGL0Lkg0YDQsNGB0YfRkdGCKS5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgdG90YWxDb3N0ID0gY29tcHV0ZWQoKCkgPT4ge1xuICAgICAgICBjb25zdCBjb3N0ID0gdGhpcy5wcm9kdWN0U2lnbmFsKCk/LmNvc3RSdWIgPz8gMDtcbiAgICAgICAgY29uc3QgYXJlYSA9IHRoaXMudG90YWxBcmVhTTIoKTtcblxuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZChhcmVhICogY29zdCAqIDEwMCkgLyAxMDA7XG4gICAgfSk7XG5cbiAgICAvKipcbiAgICAgKiDQotC10LrRgdGCINC+0LPRgNCw0L3QuNGH0LXQvdC40Y8g0L/QviDRiNC40YDQuNC90LUgKMKr0L7RgiDigKYg0LTQviDigKbCuyksINC/0L7QutCwINC10YHRgtGMINCy0YvQsdGA0LDQvdC90YvQuSDRgtC+0LLQsNGALlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSB3aWR0aFJhbmdlVGV4dCA9IGNvbXB1dGVkKCgpID0+IHRoaXMuZm9ybWF0UmFuZ2UodGhpcy5zZXR0aW5ncygpPy5taW5XaWR0aCA/PyBudWxsLCB0aGlzLnByb2R1Y3RTaWduYWwoKT8ucHJvcGVydGllcz8ud2lkdGggPz8gbnVsbCwgJ9C80LwnKSk7XG5cbiAgICAvKipcbiAgICAgKiDQotC10LrRgdGCINC+0LPRgNCw0L3QuNGH0LXQvdC40Y8g0L/QviDQtNC70LjQvdC1ICjCq9C+0YIg4oCmINC00L4g4oCmwrspLCDQv9C+0LrQsCDQtdGB0YLRjCDQstGL0LHRgNCw0L3QvdGL0Lkg0YLQvtCy0LDRgC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgbGVuZ3RoUmFuZ2VUZXh0ID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5mb3JtYXRSYW5nZSh0aGlzLnNldHRpbmdzKCk/Lm1pbkxlbmd0aCA/PyBudWxsLCB0aGlzLnByb2R1Y3RTaWduYWwoKT8ucHJvcGVydGllcz8ubGVuZ3RoID8/IG51bGwsICfQvNC8JykpO1xuXG4gICAgLyoqXG4gICAgICog0KHRgdGL0LvQutCwINC00LvRjyDQsNCy0YLQvtC80LDRgtC40YfQtdGB0LrQvtCz0L4g0YPQv9GA0LDQstC70LXQvdC40Y8g0YPQvdC40YfRgtC+0LbQtdC90LjQtdC8INC30LDQstC40YHQuNC80L7RgdGC0LXQuS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3lSZWY6IERlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgICAvKipcbiAgICAgKiDQktCw0LvQuNC00LDRgtC+0YDRiyDRiNC40YDQuNC90Ysv0LTQu9C40L3Rizog0L/QvtC60LAg0YLQvtCy0LDRgCDQvdC1INCy0YvQsdGA0LDQvSDigJQg0L3QtSDQvdCw0LrQu9Cw0LTRi9Cy0LDQtdC8IG1pbi9tYXgg0LrQsNGC0LDQu9C+0LPQsCAo0L/QvtC70Y8gcmVhZC1vbmx5INCx0LXQtyDRgtC+0LLQsNGA0LApLlxuICAgICAqXG4gICAgICogQHBhcmFtIG1pbiDQndC40LbQvdGP0Y8g0LPRgNCw0L3QuNGG0LAg0YDQsNC30LzQtdGA0LAg0LjQtyDQvdCw0YHRgtGA0L7QtdC6INC60L7QvdGE0LjQs9GD0YDQsNGC0L7RgNCwLlxuICAgICAqIEBwYXJhbSBtYXhVcHBlciDQktC10YDRhdC90Y/RjyDQs9GA0LDQvdC40YbQsCDQuNC3INGB0LLQvtC50YHRgtCyINCy0YvQsdGA0LDQvdC90L7Qs9C+INGC0L7QstCw0YDQsC5cbiAgICAgKi9cbiAgICBwcml2YXRlIGRpbWVuc2lvblZhbGlkYXRvcnMobWluOiBudW1iZXIsIG1heFVwcGVyOiBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkKTogVmFsaWRhdG9yRm5bXSB7XG4gICAgICAgIGNvbnN0IGNob3NlblByb2R1Y3QgPSB0aGlzLnByb2R1Y3QudmFsdWU7XG5cbiAgICAgICAgaWYgKCFjaG9zZW5Qcm9kdWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMubWluKG1pbiksIC4uLihtYXhVcHBlciAhPSBudWxsICYmIG1heFVwcGVyID4gMCA/IFtWYWxpZGF0b3JzLm1heChtYXhVcHBlcildIDogW10pLCBzdGVwVmFsaWRhdG9yKDEpXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0L3QvtCy0LvRj9C10YIg0LLQsNC70LjQtNCw0YLQvtGA0Ysg0YDQsNC30LzQtdGA0L3Ri9GFINC/0L7Qu9C10Lkg0L/QvtGB0LvQtSDRgdC80LXQvdGLINGC0L7QstCw0YDQsCDQuNC70Lgg0L3QsNGB0YLRgNC+0LXQui5cbiAgICAgKi9cbiAgICBwcml2YXRlIHVwZGF0ZUl0ZW1zVmFsaWRhdG9ycygpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSB0aGlzLnNldHRpbmdzKCk7XG4gICAgICAgIGNvbnN0IG1pbldpZHRoID0gc2V0dGluZ3M/Lm1pbldpZHRoID8/IDAuMDE7XG4gICAgICAgIGNvbnN0IG1pbkxlbmd0aCA9IHNldHRpbmdzPy5taW5MZW5ndGggPz8gMC4wMTtcbiAgICAgICAgY29uc3QgY2hvc2VuUHJvZHVjdCA9IHRoaXMucHJvZHVjdC52YWx1ZTtcblxuICAgICAgICB0aGlzLml0ZW1zLmNvbnRyb2xzLmZvckVhY2goKGdyb3VwKSA9PiB7XG4gICAgICAgICAgICBncm91cC5nZXQoJ3dpZHRoJyk/LnNldFZhbGlkYXRvcnModGhpcy5kaW1lbnNpb25WYWxpZGF0b3JzKG1pbldpZHRoLCBjaG9zZW5Qcm9kdWN0Py5wcm9wZXJ0aWVzPy53aWR0aCkpO1xuICAgICAgICAgICAgZ3JvdXAuZ2V0KCdsZW5ndGgnKT8uc2V0VmFsaWRhdG9ycyh0aGlzLmRpbWVuc2lvblZhbGlkYXRvcnMobWluTGVuZ3RoLCBjaG9zZW5Qcm9kdWN0Py5wcm9wZXJ0aWVzPy5sZW5ndGgpKTtcbiAgICAgICAgICAgIGdyb3VwLmdldCgnd2lkdGgnKT8udXBkYXRlVmFsdWVBbmRWYWxpZGl0eSh7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgICAgICAgICBncm91cC5nZXQoJ2xlbmd0aCcpPy51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KTQvtGA0LzQsNGC0LjRgNC+0LLQsNC90LjQtSDQtNC40LDQv9Cw0LfQvtC90LAgwqvQvtGCIOKApiDQtNC+IOKApsK7INGBINGD0YfRkdGC0L7QvCDQvtGC0YHRg9GC0YHRgtCy0YPRjtGJ0LjRhSDQs9GA0LDQvdC40YYuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbWluINCd0LjQttC90Y/RjyDQs9GA0LDQvdC40YbQsCDQtNC40LDQv9Cw0LfQvtC90LAuXG4gICAgICogQHBhcmFtIG1heCDQktC10YDRhdC90Y/RjyDQs9GA0LDQvdC40YbQsCDQtNC40LDQv9Cw0LfQvtC90LAuXG4gICAgICogQHBhcmFtIHVuaXQg0JXQtNC40L3QuNGG0LAg0LjQt9C80LXRgNC10L3QuNGPINC00LvRjyDQv9C+0LTQv9C40YHQuC5cbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuICAgIHByaXZhdGUgZm9ybWF0UmFuZ2UobWluOiBudW1iZXIgfCBudWxsIHwgdW5kZWZpbmVkLCBtYXg6IG51bWJlciB8IG51bGwgfCB1bmRlZmluZWQsIHVuaXQ6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xuICAgICAgICBjb25zdCBoYXNNaW4gPSBtaW4gIT0gbnVsbCAmJiBtaW4gPiAwO1xuICAgICAgICBjb25zdCBoYXNNYXggPSBtYXggIT0gbnVsbCAmJiBtYXggPiAwO1xuXG4gICAgICAgIGlmICghaGFzTWluICYmICFoYXNNYXgpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGhhc01pbiAmJiBoYXNNYXgpIHtcbiAgICAgICAgICAgIHJldHVybiBg0L7RgiAke21pbn0gJHt1bml0fSDQtNC+ICR7bWF4fSAke3VuaXR9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChoYXNNaW4pIHtcbiAgICAgICAgICAgIHJldHVybiBg0L7RgiAke21pbn0gJHt1bml0fWA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYNC00L4gJHttYXh9ICR7dW5pdH1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCc0LDRgdGB0LjQsiDQuNC30LTQtdC70LjQuS5cbiAgICAgKi9cbiAgICBnZXQgaXRlbXMoKTogRm9ybUFycmF5PFJldHVyblR5cGU8U2NTYW5kd2ljaE0yQ29tcG9uZW50WydjcmVhdGVJdGVtR3JvdXAnXT4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZm9ybS5jb250cm9scy5pdGVtcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiB7QGluaGVyaXREb2N9XG4gICAgICovXG4gICAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLnNldERlZmF1bHRGb3JtVmFsdWUoKTtcblxuICAgICAgICB0aGlzLnByb2R1Y3RzJC5waXBlKHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpKS5zdWJzY3JpYmUoKHByb2R1Y3RzKSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5wcm9kdWN0LnZhbHVlICE9IG51bGwgfHwgcHJvZHVjdHMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKiDQn9GA0Lgg0LfQsNCz0YDRg9C30LrQtSDRgdC/0LjRgdC60LAg0LDQstGC0L7QvNCw0YLQuNGH0LXRgdC60Lgg0LLRi9Cx0LjRgNCw0LXQvCDQv9C10YDQstGL0Lkg0LzQsNGC0LXRgNC40LDQuy4gKi9cbiAgICAgICAgICAgIHRoaXMucHJvZHVjdC5zZXRWYWx1ZShwcm9kdWN0c1swXSwgeyBlbWl0RXZlbnQ6IHRydWUgfSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMucHJvZHVjdC52YWx1ZUNoYW5nZXMucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSkuc3Vic2NyaWJlKChjaG9zZW5Qcm9kdWN0KSA9PiB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUl0ZW1zVmFsaWRhdG9ycygpO1xuXG4gICAgICAgICAgICBpZiAoY2hvc2VuUHJvZHVjdCkge1xuICAgICAgICAgICAgICAgIHRoaXMuaXRlbXMuY29udHJvbHMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IGl0ZW0uZ2V0UmF3VmFsdWUoKTtcblxuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXhXID0gY2hvc2VuUHJvZHVjdC5wcm9wZXJ0aWVzPy53aWR0aDtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbWF4TCA9IGNob3NlblByb2R1Y3QucHJvcGVydGllcz8ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgICAgIGl0ZW0ucGF0Y2hWYWx1ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICB3aWR0aDogbWF4VyA/IE1hdGgubWluKHZhbHVlLndpZHRoLCBtYXhXKSA6IHZhbHVlLndpZHRoLFxuICAgICAgICAgICAgICAgICAgICAgICAgbGVuZ3RoOiBtYXhMID8gTWF0aC5taW4odmFsdWUubGVuZ3RoLCBtYXhMKSA6IHZhbHVlLmxlbmd0aCxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgICAqINCh0LzQtdC90LAg0L/RgNC+0LTRg9C60YLQsCDigJQg0YHQsdGA0LDRgdGL0LLQsNC10Lwg0YHQvtGB0YLQvtGP0L3QuNC1INC/0L7Qt9C40YbQuNC5OiDQs9GA0LDQvdC40YbRiyDQutCw0YLQsNC70L7Qs9CwINC40LfQvNC10L3QuNC70LjRgdGMLFxuICAgICAgICAgICAgICAgICAqINGD0YHQv9C10YjQvdCw0Y8g0L7RgtC/0YDQsNCy0LrQsCDQsdC+0LvRjNGI0LUg0L3QtSDQvtGC0YDQsNC20LDQtdGCINGC0LXQutGD0YnQtdC1INGB0L7RgdGC0L7Rj9C90LjQtS5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICB0aGlzLnJlc2V0QWxsSXRlbVN0YXRlcygpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodC+0LfQtNCw0LXRgiDQs9GA0YPQv9C/0YMg0LTQu9GPINC40LfQtNC10LvQuNGPLlxuICAgICAqXG4gICAgICogQHBhcmFtIGl0ZW0g0J/QsNGA0LDQvNC10YLRgNGLINC40LfQtNC10LvQuNGPLlxuICAgICAqIEBwYXJhbSBpdGVtLndpZHRoINCo0LjRgNC40L3QsCDQuNC30LTQtdC70LjRjy5cbiAgICAgKiBAcGFyYW0gaXRlbS5sZW5ndGgg0JTQu9C40L3QsCDQuNC30LTQtdC70LjRjy5cbiAgICAgKiBAcGFyYW0gaXRlbS5jb3VudCDQmtC+0LvQuNGH0LXRgdGC0LLQviDQuNC30LTQtdC70LjQuS5cbiAgICAgKiBAcGFyYW0gaXRlbS5tYXJrZXIg0JzQsNGA0LrQtdGAINC/0L7Qt9C40YbQuNC4LlxuICAgICAqL1xuICAgIHByaXZhdGUgY3JlYXRlSXRlbUdyb3VwKGl0ZW0/OiB7IHdpZHRoOiBudW1iZXI7IGxlbmd0aDogbnVtYmVyOyBjb3VudDogbnVtYmVyOyBtYXJrZXI6IHN0cmluZyB8IG51bGwgfSk6IEZvcm1Hcm91cDx7XG4gICAgICAgIHdpZHRoOiBGb3JtQ29udHJvbDxudW1iZXI+O1xuICAgICAgICBsZW5ndGg6IEZvcm1Db250cm9sPG51bWJlcj47XG4gICAgICAgIGNvdW50OiBGb3JtQ29udHJvbDxudW1iZXI+O1xuICAgICAgICBtYXJrZXI6IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+O1xuICAgIH0+IHtcbiAgICAgICAgY29uc3QgZ3JvdXAgPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgICAgICAgIHdpZHRoOiBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPihpdGVtPy53aWR0aCA/PyAwLCB7IG5vbk51bGxhYmxlOiB0cnVlIH0pLFxuICAgICAgICAgICAgbGVuZ3RoOiBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPihpdGVtPy5sZW5ndGggPz8gMCwgeyBub25OdWxsYWJsZTogdHJ1ZSB9KSxcbiAgICAgICAgICAgIGNvdW50OiBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyPihpdGVtPy5jb3VudCA/PyAxLCB7XG4gICAgICAgICAgICAgICAgdmFsaWRhdG9yczogW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMubWluKDEpLCBzdGVwVmFsaWRhdG9yKDEpXSxcbiAgICAgICAgICAgICAgICBub25OdWxsYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgbWFya2VyOiBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4oaXRlbT8ubWFya2VyID8/IG51bGwpLFxuICAgICAgICB9KTtcblxuICAgICAgICAvLyDQm9GO0LHQvtC1INC40LfQvNC10L3QtdC90LjQtSDQt9C90LDRh9C10L3QuNC5INC/0L7Qt9C40YbQuNC4INGB0LHRgNCw0YHRi9Cy0LDQtdGCINC10ZEg0YHQvtGB0YLQvtGP0L3QuNC1INC+0YLQv9GA0LDQstC60Lgg4oCUXG4gICAgICAgIC8vINGA0LDQvdC10LUg0YPRgdC/0LXRiNC90YvQuSBzdWJtaXQg0YHRgtCw0L3QvtCy0LjRgtGB0Y8g0L3QtdCw0LrRgtGD0LDQu9GM0L3Ri9C8INC/0YDQuCDQv9GA0LDQstC60LUg0L/QvtC70LXQuSxcbiAgICAgICAgLy8g0L7RiNC40LHQutGDINCy0LDQu9C40LTQsNGG0LjQuCDRgdC10YDQstC10YDQsCDRgtC+0LbQtSDRgdCx0YDQsNGB0YvQstCw0LXQvC5cbiAgICAgICAgZ3JvdXAudmFsdWVDaGFuZ2VzLnBpcGUodGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZikpLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBpbmRleCA9IHRoaXMuaXRlbXMuY29udHJvbHMuaW5kZXhPZihncm91cCk7XG5cbiAgICAgICAgICAgIGlmIChpbmRleCAhPT0gLTEpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2V0SXRlbVN0YXRlKGluZGV4KTtcbiAgICAgICAgICAgICAgICAoWyd3aWR0aCcsICdsZW5ndGgnLCAnY291bnQnLCAnbWFya2VyJ10gYXMgY29uc3QpLmZvckVhY2goKGZpZWxkKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRyb2wgPSBncm91cC5nZXQoZmllbGQpO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChjb250cm9sPy5oYXNFcnJvcignc2VydmVyUmVzcG9uc2UnKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3JzID0geyAuLi5jb250cm9sLmVycm9ycyB9IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xuICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIGVycm9yc1snc2VydmVyUmVzcG9uc2UnXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wuc2V0RXJyb3JzKE9iamVjdC5rZXlzKGVycm9ycykubGVuZ3RoID4gMCA/IGVycm9ycyA6IG51bGwpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBncm91cDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQodCx0YDQsNGB0YvQstCw0LXRgiDRgdC+0YHRgtC+0Y/QvdC40LUg0L7QtNC90L7QuSDQv9C+0LfQuNGG0LjQuCDQvdCwIGBpZGxlYCwg0LXRgdC70Lgg0L7QvdC+INCx0YvQu9C+IGBzdWNjZXNzYC9gZXJyb3JgLlxuICAgICAqXG4gICAgICogQHBhcmFtIGluZGV4INCY0L3QtNC10LrRgSDQv9C+0LfQuNGG0LjQuC5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlc2V0SXRlbVN0YXRlKGluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgY29uc3Qgc3RhdGVzID0gdGhpcy5pdGVtU3RhdGVzKCk7XG4gICAgICAgIGNvbnN0IGN1cnJlbnQgPSBzdGF0ZXNbaW5kZXhdO1xuXG4gICAgICAgIGlmIChjdXJyZW50ID09PSAnc3VjY2VzcycgfHwgY3VycmVudCA9PT0gJ2Vycm9yJykge1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlZCA9IFsuLi5zdGF0ZXNdO1xuICAgICAgICAgICAgdXBkYXRlZFtpbmRleF0gPSAnaWRsZSc7XG4gICAgICAgICAgICB0aGlzLml0ZW1TdGF0ZXMuc2V0KHVwZGF0ZWQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHQsdGA0LDRgdGL0LLQsNC10YIg0YHQvtGB0YLQvtGP0L3QuNGPINCy0YHQtdGFINC/0L7Qt9C40YbQuNC5INC90LAgYGlkbGVgLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVzZXRBbGxJdGVtU3RhdGVzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLml0ZW1TdGF0ZXMuc2V0KHRoaXMuaXRlbXMuY29udHJvbHMubWFwKCgpID0+IElETEVfSVRFTV9TVEFURSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCS0L7Qt9Cy0YDQsNGJ0LDQtdGCINGB0L7RgdGC0L7Rj9C90LjQtSDQv9C+0LfQuNGG0LjQuCDQv9C+INC40L3QtNC10LrRgdGDICjQv9C+INGD0LzQvtC70YfQsNC90LjRjiBgaWRsZWApLlxuICAgICAqXG4gICAgICogQHBhcmFtIGluZGV4INCY0L3QtNC10LrRgSDQv9C+0LfQuNGG0LjQuC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgZ2V0SXRlbVN0YXRlKGluZGV4OiBudW1iZXIpOiBTY1NhbmR3aWNoTTJJdGVtU3VibWl0U3RhdGUge1xuICAgICAgICByZXR1cm4gdGhpcy5pdGVtU3RhdGVzKClbaW5kZXhdID8/IElETEVfSVRFTV9TVEFURTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQn9GA0LjQt9C90LDQuiDRgtC+0LPQviwg0YfRgtC+INC/0L7Qt9C40YbQuNGPINC+0YLQv9GA0LDQstC70Y/QtdGC0YHRjyAo0L/QvtC70Y8g0LTQvtC70LbQvdGLINCx0YvRgtGMINC30LDQsdC70L7QutC40YDQvtCy0LDQvdGLKS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBpbmRleCDQmNC90LTQtdC60YEg0L/QvtC30LjRhtC40LguXG4gICAgICovXG4gICAgcHJvdGVjdGVkIGlzSXRlbUxvYWRpbmcoaW5kZXg6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRJdGVtU3RhdGUoaW5kZXgpID09PSAnbG9hZGluZyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J/RgNC40LfQvdCw0Log0YLQvtCz0L4sINGH0YLQviDQv9C+0LfQuNGG0LjRjyDRg9GB0L/QtdGI0L3QviDQvtGC0L/RgNCw0LLQu9C10L3QsCDQuCDQtdGRINC/0L7Qu9GPINC90YPQttC90L4g0LfQsNCx0LvQvtC60LjRgNC+0LLQsNGC0YwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gaW5kZXgg0JjQvdC00LXQutGBINC/0L7Qt9C40YbQuNC4LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBpc0l0ZW1Mb2NrZWQoaW5kZXg6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRJdGVtU3RhdGUoaW5kZXgpID09PSAnc3VjY2Vzcyc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0JTQvtCx0LDQstC70Y/QtdGCINC90L7QstC+0LUg0LjQt9C00LXQu9C40LUg0LIg0YTQvtGA0LzRgy5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYWRkSXRlbSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5pdGVtcy5wdXNoKHRoaXMuY3JlYXRlSXRlbUdyb3VwKCkpO1xuICAgICAgICB0aGlzLml0ZW1TdGF0ZXMudXBkYXRlKChzdGF0ZXMpID0+IFsuLi5zdGF0ZXMsICdpZGxlJ10pO1xuICAgICAgICB0aGlzLnVwZGF0ZUl0ZW1zVmFsaWRhdG9ycygpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCj0LTQsNC70Y/QtdGCINC40LfQtNC10LvQuNC1INC40Lcg0YTQvtGA0LzRiy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBpbmRleCDQmNC90LTQtdC60YEg0LjQt9C00LXQu9C40Y8uXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlbW92ZUl0ZW0oaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgICAgICB0aGlzLml0ZW1zLnJlbW92ZUF0KGluZGV4KTtcbiAgICAgICAgdGhpcy5pdGVtU3RhdGVzLnVwZGF0ZSgoc3RhdGVzKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB1cGRhdGVkID0gWy4uLnN0YXRlc107XG4gICAgICAgICAgICB1cGRhdGVkLnNwbGljZShpbmRleCwgMSk7XG5cbiAgICAgICAgICAgIHJldHVybiB1cGRhdGVkO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy51cGRhdGVJdGVtc1ZhbGlkYXRvcnMoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQn9C70L7RidCw0LTRjCDQvtC00L3QvtC5INC10LTQuNC90LjRhtGLINC40LfQtNC10LvQuNGPINCx0LXQtyDRg9GH0ZHRgtCwINC60L7Qu9C40YfQtdGB0YLQstCwLCDQvMKyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlINCX0L3QsNGH0LXQvdC40Y8g0YDQsNC30LzQtdGA0L7QsiDQuNC30LTQtdC70LjRjy5cbiAgICAgKiBAcGFyYW0gdmFsdWUud2lkdGgg0KjQuNGA0LjQvdCwINC40LfQtNC10LvQuNGPLlxuICAgICAqIEBwYXJhbSB2YWx1ZS5sZW5ndGgg0JTQu9C40L3QsCDQuNC30LTQtdC70LjRjy5cbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuICAgIHByb3RlY3RlZCBwaWVjZUFyZWFNMih2YWx1ZTogeyB3aWR0aDogbnVtYmVyOyBsZW5ndGg6IG51bWJlciB9KTogbnVtYmVyIHtcbiAgICAgICAgY29uc3QgeyB3aWR0aCwgbGVuZ3RoIH0gPSB2YWx1ZTtcblxuICAgICAgICBpZiAoIXdpZHRoIHx8ICFsZW5ndGgpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuICh3aWR0aCAqIGxlbmd0aCkgLyAxXzAwMF8wMDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KHRg9C80LzQsNGA0L3QsNGPINC/0LvQvtGJ0LDQtNGMINC/0L4g0YHRgtGA0L7QutC1INC/0L7Qt9C40YbQuNC4OiDQv9C70L7RidCw0LTRjCDQtdC00LjQvdC40YbRiyDDlyDQutC+0LvQuNGH0LXRgdGC0LLQviwg0LzCsi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB2YWx1ZSDQl9C90LDRh9C10L3QuNGPINC/0L7Qt9C40YbQuNC4LlxuICAgICAqIEBwYXJhbSB2YWx1ZS53aWR0aCDQqNC40YDQuNC90LAg0LjQt9C00LXQu9C40Y8uXG4gICAgICogQHBhcmFtIHZhbHVlLmxlbmd0aCDQlNC70LjQvdCwINC40LfQtNC10LvQuNGPLlxuICAgICAqIEBwYXJhbSB2YWx1ZS5jb3VudCDQmtC+0LvQuNGH0LXRgdGC0LLQviDQuNC30LTQtdC70LjQuS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJvd1RvdGFsUGFydHNBcmVhTTIodmFsdWU6IHsgd2lkdGg6IG51bWJlcjsgbGVuZ3RoOiBudW1iZXI7IGNvdW50OiBudW1iZXIgfSk6IG51bWJlciB7XG4gICAgICAgIGNvbnN0IHF0eSA9IHZhbHVlLmNvdW50O1xuXG4gICAgICAgIGlmICghcXR5IHx8ICF2YWx1ZS53aWR0aCB8fCB2YWx1ZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucGllY2VBcmVhTTIodmFsdWUpICogcXR5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCS0L7Qt9Cy0YDQsNGJ0LDQtdGCINC/0YDQuNCx0LvQuNC30LjRgtC10LvRjNC90YPRjiDRgdGC0L7QuNC80L7RgdGC0Ywg0YHRgtGA0L7QutC4ICjQu9C+0LrQsNC70YzQvdGL0Lkg0YDQsNGB0YfRkdGCIOKAlCDQvdCwINCy0YHRjiDRgdGC0YDQvtC60YMg0L/QvtC30LjRhtC40LgpLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlINCX0L3QsNGH0LXQvdC40Y8g0LjQt9C00LXQu9C40Y8uXG4gICAgICogQHBhcmFtIHZhbHVlLndpZHRoINCo0LjRgNC40L3QsCDQuNC30LTQtdC70LjRjy5cbiAgICAgKiBAcGFyYW0gdmFsdWUubGVuZ3RoINCU0LvQuNC90LAg0LjQt9C00LXQu9C40Y8uXG4gICAgICogQHBhcmFtIHZhbHVlLmNvdW50INCa0L7Qu9C40YfQtdGB0YLQstC+INC40LfQtNC10LvQuNC5LlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByb3dDb3N0KHZhbHVlOiB7IHdpZHRoOiBudW1iZXI7IGxlbmd0aDogbnVtYmVyOyBjb3VudDogbnVtYmVyIH0pOiBudW1iZXIge1xuICAgICAgICBjb25zdCBhcmVhID0gdGhpcy5yb3dUb3RhbFBhcnRzQXJlYU0yKHZhbHVlKTtcbiAgICAgICAgY29uc3QgY29zdCA9IHRoaXMucHJvZHVjdC52YWx1ZT8uY29zdFJ1YiA/PyAwO1xuXG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kKGFyZWEgKiBjb3N0ICogMTAwKSAvIDEwMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0L3QvtCy0LvRj9C10YIg0YHQvtGB0YLQvtGP0L3QuNC1INC/0L7Qt9C40YbQuNC4INC90LAg0YPQutCw0LfQsNC90L3QvtC1INC30L3QsNGH0LXQvdC40LUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gaW5kZXgg0JjQvdC00LXQutGBINC/0L7Qt9C40YbQuNC4LlxuICAgICAqIEBwYXJhbSBzdGF0ZSDQndC+0LLQvtC1INGB0L7RgdGC0L7Rj9C90LjQtS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHNldEl0ZW1TdGF0ZShpbmRleDogbnVtYmVyLCBzdGF0ZTogU2NTYW5kd2ljaE0ySXRlbVN1Ym1pdFN0YXRlKTogdm9pZCB7XG4gICAgICAgIHRoaXMuaXRlbVN0YXRlcy51cGRhdGUoKHN0YXRlcykgPT4ge1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlZCA9IFsuLi5zdGF0ZXNdO1xuICAgICAgICAgICAgdXBkYXRlZFtpbmRleF0gPSBzdGF0ZTtcblxuICAgICAgICAgICAgcmV0dXJuIHVwZGF0ZWQ7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC80LXQvdGP0LXRgiDQvtGI0LjQsdC60Lgg0YHQtdGA0LLQtdGA0L3QvtC5INCy0LDQu9C40LTQsNGG0LjQuCDQuiDQutC+0L3RgtGA0L7Qu9Cw0Lwg0YTQvtGA0LzRiy5cbiAgICAgKiDQodC10YDQstC10YAg0LLQvtC30LLRgNCw0YnQsNC10YIg0LrQu9GO0YfQuCDQstC40LTQsCBgaXRlbXMuMC48ZmllbGQ+YCDigJQg0L/QtdGA0LXQstC+0LTQuNC8INCyINGE0LDQutGC0LjRh9C10YHQutC40Lkg0LjQvdC00LXQutGBINC/0L7Qt9C40YbQuNC4LlxuICAgICAqXG4gICAgICogQHBhcmFtIGVycm9yINCe0YLQstC10YIg0YHQtdGA0LLQtdGA0LAuXG4gICAgICogQHBhcmFtIGluZGV4INCY0L3QtNC10LrRgSDQv9C+0LfQuNGG0LjQuCDQsiDRhNC+0YDQvNC1LlxuICAgICAqL1xuICAgIHByaXZhdGUgYXBwbHlTZXJ2ZXJWYWxpZGF0aW9uRXJyb3JzKGVycm9yOiB1bmtub3duLCBpbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgICAgIGlmICghKGVycm9yIGluc3RhbmNlb2YgSHR0cEVycm9yUmVzcG9uc2UpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB7IGVycm9ycywgbWVzc2FnZSB9ID0gZXJyb3IuZXJyb3IgYXMgU2NJQXBpRXJyb3JSZXNwb25zZTtcblxuICAgICAgICBpZiAoZXJyb3JzKSB7XG4gICAgICAgICAgICBPYmplY3Qua2V5cyhlcnJvcnMpLmZvckVhY2goKGtleSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5nZXQoWydpdGVtcycsIGluZGV4LCBrZXldKT8uc2V0RXJyb3JzKHsgc2VydmVyUmVzcG9uc2U6IGVycm9yc1trZXldIH0pO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAobWVzc2FnZSkge1xuICAgICAgICAgICAgdGhpcy5mb3JtLnNldEVycm9ycyh7IHNlcnZlclJlc3BvbnNlOiBbbWVzc2FnZV0gfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0YDQsNCx0L7RgtGH0LjQuiDQtNC+0LHQsNCy0LvQtdC90LjRjy/RgNC10LTQsNC60YLQuNGA0L7QstCw0L3QuNGPINC/0YDQvtC00YPQutGC0LAg0LIg0LrQvtGA0LfQuNC90LUuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIG9uU3VibWl0KCk6IHZvaWQge1xuICAgICAgICBpZiAodGhpcy5mb3JtLmludmFsaWQgfHwgIXRoaXMucHJvZHVjdC52YWx1ZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcHJvZHVjdElkID0gdGhpcy5wcm9kdWN0LnZhbHVlLmlkO1xuICAgICAgICBjb25zdCBwcm9kdWN0Q2F0ZWdvcnlJZCA9IE51bWJlcih0aGlzLmNhdGVnb3J5SWQoKSk7XG4gICAgICAgIGNvbnN0IGNvbmZpZ3VyYXRvciA9IHRoaXMuZWRpdG9yKCk7XG4gICAgICAgIGNvbnN0IG9yZGVyRGF0YSA9IHRoaXMub3JkZXJJdGVtKCk7XG5cbiAgICAgICAgY29uc3QgaW5kZXhlc1RvU3VibWl0ID0gdGhpcy5pdGVtcy5jb250cm9sc1xuICAgICAgICAgICAgLm1hcCgoXywgaW5kZXgpID0+IGluZGV4KVxuICAgICAgICAgICAgLmZpbHRlcigoaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBzdGF0ZSA9IHRoaXMuZ2V0SXRlbVN0YXRlKGluZGV4KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiBzdGF0ZSAhPT0gJ3N1Y2Nlc3MnICYmIHN0YXRlICE9PSAnbG9hZGluZyc7XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICBpZiAoaW5kZXhlc1RvU3VibWl0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8g0J/QvtC30LjRhtC40Lgg0L7RgtC/0YDQsNCy0LvRj9GO0YLRgdGPINC/0L7RgdC70LXQtNC+0LLQsNGC0LXQu9GM0L3Qvjog0LrQsNC20LTQsNGPINGB0LvQtdC00YPRjtGJ0LDRjyDigJQg0YLQvtC70YzQutC+INC/0L7RgdC70LUg0L7RgtCy0LXRgtCwINC/0YDQtdC00YvQtNGD0YnQtdC5LlxuICAgICAgICAvLyDQn9GA0Lgg0L7RiNC40LHQutC1INGG0LXQv9C+0YfQutCwINC/0YDQtdGA0YvQstCw0LXRgtGB0Y87INC00LjQsNC70L7QsyDQvdC1INC30LDQutGA0YvQstCw0LXRgtGB0Y8uXG4gICAgICAgIGZyb20oaW5kZXhlc1RvU3VibWl0KVxuICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgY29uY2F0TWFwKChpbmRleCwgcG9zaXRpb24pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRWRpdGluZy3RgNC10LbQuNC8OiDQv9C10YDQstCw0Y8g0L/QvtC30LjRhtC40Y8gKGluZGV4IDApINC+0LHQvdC+0LLQu9GP0LXRgtGB0Y8sINC+0YHRgtCw0LvRjNC90YvQtSDQtNC+0LHQsNCy0LvRj9GO0YLRgdGPLlxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpc0VkaXQgPSBvcmRlckRhdGEgIT0gbnVsbCAmJiBpbmRleCA9PT0gMCAmJiBwb3NpdGlvbiA9PT0gMDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRJdGVtU3RhdGUoaW5kZXgsICdsb2FkaW5nJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuYnVpbGRJdGVtUmVxdWVzdCQoaW5kZXgsIHByb2R1Y3RJZCwgcHJvZHVjdENhdGVnb3J5SWQsIGNvbmZpZ3VyYXRvciwgaXNFZGl0LCBvcmRlckRhdGEpLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0SXRlbVN0YXRlKGluZGV4LCAnc3VjY2VzcycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXRjaEVycm9yKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYXBwbHlTZXJ2ZXJWYWxpZGF0aW9uRXJyb3JzKGVycm9yLCBpbmRleCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRJdGVtU3RhdGUoaW5kZXgsICdlcnJvcicpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgICAgICAgICAgY29tcGxldGU6ICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuY29udGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jb250ZXh0LiRpbXBsaWNpdC5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXREZWZhdWx0Rm9ybVZhbHVlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KTQvtGA0LzQuNGA0YPQtdGCIEhUVFAt0LfQsNC/0YDQvtGBINC00LvRjyDQvtC00L3QvtC5INC/0L7Qt9C40YbQuNC4INGE0L7RgNC80YsuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gaW5kZXgg0JjQvdC00LXQutGBINC/0L7Qt9C40YbQuNC4INCyINGE0L7RgNC80LUuXG4gICAgICogQHBhcmFtIHByb2R1Y3RJZCDQmNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgCDQstGL0LHRgNCw0L3QvdC+0LPQviDQv9GA0L7QtNGD0LrRgtCwLlxuICAgICAqIEBwYXJhbSBwcm9kdWN0Q2F0ZWdvcnlJZCDQmNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgCDQutCw0YLQtdCz0L7RgNC40LguXG4gICAgICogQHBhcmFtIGNvbmZpZ3VyYXRvciDQndCw0LfQstCw0L3QuNC1INC60L7QvdGE0LjQs9GD0YDQsNGC0L7RgNCwLlxuICAgICAqIEBwYXJhbSBpc0VkaXQg0KDQtdC20LjQvCDQvtCx0L3QvtCy0LvQtdC90LjRjyDRgdGD0YnQtdGB0YLQstGD0Y7RidC10Lkg0L/QvtC30LjRhtC40LguXG4gICAgICogQHBhcmFtIG9yZGVyRGF0YSDQotC10LrRg9GJ0LDRjyDQv9C+0LfQuNGG0LjRjyDQt9Cw0LrQsNC30LAgKNGC0L7Qu9GM0LrQviDQsiDRgNC10LbQuNC80LUg0YDQtdC00LDQutGC0LjRgNC+0LLQsNC90LjRjykuXG4gICAgICovXG4gICAgcHJpdmF0ZSBidWlsZEl0ZW1SZXF1ZXN0JChcbiAgICAgICAgaW5kZXg6IG51bWJlcixcbiAgICAgICAgcHJvZHVjdElkOiBudW1iZXIsXG4gICAgICAgIHByb2R1Y3RDYXRlZ29yeUlkOiBudW1iZXIsXG4gICAgICAgIGNvbmZpZ3VyYXRvcjogc3RyaW5nLFxuICAgICAgICBpc0VkaXQ6IGJvb2xlYW4sXG4gICAgICAgIG9yZGVyRGF0YTogU2NPcmRlckl0ZW0gfCB1bmRlZmluZWRcbiAgICApOiBPYnNlcnZhYmxlPHVua25vd24+IHtcbiAgICAgICAgY29uc3QgaXRlbVZhbHVlID0gdGhpcy5pdGVtcy5hdChpbmRleCkuZ2V0UmF3VmFsdWUoKTtcbiAgICAgICAgY29uc3QgcGF5bG9hZCA9IHRoaXMuY29udmVydGVyc1NlcnZpY2UucmVtb3ZlTnVsbCh7XG4gICAgICAgICAgICBwcm9kdWN0Q2F0ZWdvcnlJZCxcbiAgICAgICAgICAgIGNvbmZpZ3VyYXRvcixcbiAgICAgICAgICAgIHByb2R1Y3RJZCxcbiAgICAgICAgICAgIHdpZHRoOiBpdGVtVmFsdWUud2lkdGgsXG4gICAgICAgICAgICBsZW5ndGg6IGl0ZW1WYWx1ZS5sZW5ndGgsXG4gICAgICAgICAgICBxdWFudGl0eTogaXRlbVZhbHVlLmNvdW50LFxuICAgICAgICAgICAgbWFya2VyOiBpdGVtVmFsdWUubWFya2VyLFxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gaXNFZGl0ICYmIG9yZGVyRGF0YSAhPSBudWxsXG4gICAgICAgICAgICA/IHRoaXMub3JkZXJTZXJ2aWNlLnVwZGF0ZVByb2R1Y3QkKG9yZGVyRGF0YS5pZCwgcGF5bG9hZCBhcyBPbWl0PFNjSU5ld09yZGVySXRlbUJhc2UsICdwcm9kdWN0SWQnPiAmIHsgcHJvZHVjdElkPzogbnVtYmVyIH0sIHRoaXMub3JkZXJJZClcbiAgICAgICAgICAgIDogdGhpcy5vcmRlclNlcnZpY2UuYWRkUHJvZHVjdCQocGF5bG9hZCBhcyBTY0lOZXdDYXJ0SXRlbVNhbmR3aWNoTTIsIHRoaXMub3JkZXJJZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KPRgdGC0LDQvdCw0LLQu9C40LLQsNC10YIg0L3QsNGH0LDQu9GM0L3Ri9C1INC30L3QsNGH0LXQvdC40Y8g0LTQu9GPINC/0L7Qu9C10Lkg0YTQvtGA0LzRiy5cbiAgICAgKi9cbiAgICBwcml2YXRlIHNldERlZmF1bHRGb3JtVmFsdWUoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZm9ybS5yZXNldCh7XG4gICAgICAgICAgICBwcm9kdWN0Q2F0ZWdvcnlJZDogTnVtYmVyKHRoaXMuY2F0ZWdvcnlJZCgpKSxcbiAgICAgICAgICAgIGNvbmZpZ3VyYXRvcjogdGhpcy5lZGl0b3IoKSxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5pdGVtcy5jbGVhcigpO1xuXG4gICAgICAgIGNvbnN0IG9yZGVySXRlbSA9IHRoaXMub3JkZXJJdGVtKCk7XG5cbiAgICAgICAgdGhpcy5pdGVtcy5wdXNoKFxuICAgICAgICAgICAgdGhpcy5jcmVhdGVJdGVtR3JvdXAoe1xuICAgICAgICAgICAgICAgIHdpZHRoOiAob3JkZXJJdGVtPy53aWR0aCA/PyAwKSAqIDEwMDAsXG4gICAgICAgICAgICAgICAgbGVuZ3RoOiAob3JkZXJJdGVtPy5sZW5ndGggPz8gMCkgKiAxMDAwLFxuICAgICAgICAgICAgICAgIGNvdW50OiBvcmRlckl0ZW0/LnF1YW50aXR5ID8/IDEsXG4gICAgICAgICAgICAgICAgbWFya2VyOiBvcmRlckl0ZW0/Lm1hcmtlciA/PyBudWxsLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgKTtcblxuICAgICAgICB0aGlzLml0ZW1TdGF0ZXMuc2V0KHRoaXMuaXRlbXMuY29udHJvbHMubWFwKCgpID0+IElETEVfSVRFTV9TVEFURSkpO1xuICAgICAgICB0aGlzLnVwZGF0ZUl0ZW1zVmFsaWRhdG9ycygpO1xuICAgICAgICB0aGlzLmZvcm0ubWFya0FzVW50b3VjaGVkKCk7XG4gICAgfVxufVxuIiwiQGlmICghb3JkZXJJdGVtKCkgJiYgc2V0dGluZ3MoKT8uYWxsb3dTaG93VGFibGUpIHtcbiAgICA8ZGl2IGNsYXNzPVwibWItNSBmbGV4IGp1c3RpZnktY2VudGVyXCI+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR1aUJ1dHRvblxuICAgICAgICAgICAgYXBwZWFyYW5jZT1cInNlY29uZGFyeVwiXG4gICAgICAgICAgICAoY2xpY2spPVwidG9nZ2xlU2hvd0V2ZW50LmVtaXQoKVwiXG4gICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgIGljb25TdGFydD1cIkB0dWkubGF5b3V0LWxpc3RcIlxuICAgICAgICA+XG4gICAgICAgICAgICDQn9C+0LrQsNC30LDRgtGMINCyINCy0LjQtNC1INGB0L/QuNGB0LrQsFxuICAgICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbn1cbjxkaXYgY2xhc3M9XCJcIj5cbiAgICBAbGV0IHByb2R1Y3RzID0gcHJvZHVjdHMkIHwgYXN5bmM7XG4gICAgQGxldCBwcm9kdWN0VmFsdWUgPSBwcm9kdWN0LnZhbHVlO1xuXG4gICAgPGZvcm1cbiAgICAgICAgW2Zvcm1Hcm91cF09XCJmb3JtXCJcbiAgICAgICAgKG5nU3VibWl0KT1cIm9uU3VibWl0KClcIlxuICAgICAgICBTY05leHRJbnB1dEZvY3VzXG4gICAgICAgIGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtMlwiXG4gICAgPlxuICAgICAgICA8bGFiZWxcbiAgICAgICAgICAgIHR1aUxhYmVsXG4gICAgICAgICAgICBjbGFzcz1cImdyb3dcIlxuICAgICAgICA+XG4gICAgICAgICAgICDQotC+0LLQsNGAXG4gICAgICAgICAgICA8dHVpLXRleHRmaWVsZFxuICAgICAgICAgICAgICAgIHR1aUNoZXZyb25cbiAgICAgICAgICAgICAgICBbdHVpVGV4dGZpZWxkQ2xlYW5lcl09XCJmYWxzZVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgIHR1aUNoZXZyb25cbiAgICAgICAgICAgICAgICAgICAgdHVpU2VsZWN0XG4gICAgICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJwcm9kdWN0XCJcbiAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCLQktGL0LHQtdGA0LjRgtC1INC80LDRgtC10YDQuNCw0LtcIlxuICAgICAgICAgICAgICAgIC8+XG5cbiAgICAgICAgICAgICAgICA8dHVpLWRhdGEtbGlzdC13cmFwcGVyXG4gICAgICAgICAgICAgICAgICAgICp0dWlUZXh0ZmllbGREcm9wZG93blxuICAgICAgICAgICAgICAgICAgICBuZXdcbiAgICAgICAgICAgICAgICAgICAgW2l0ZW1zXT1cInByb2R1Y3RzXCJcbiAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgPC90dWktdGV4dGZpZWxkPlxuICAgICAgICAgICAgPHR1aS1lcnJvclxuICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJwcm9kdWN0XCJcbiAgICAgICAgICAgICAgICBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgPC9sYWJlbD5cblxuICAgICAgICBAaWYgKHByb2R1Y3RWYWx1ZSAmJiBwcm9kdWN0VmFsdWUuY29zdFJ1YiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICA8ZGl2IGNsYXNzPVwiLW10LTEgdGV4dC1zbSB0ZXh0LXR1aS10ZXh0LXNlY29uZGFyeVwiPlxuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZm9udC1ib2xkXCI+e3sgcHJvZHVjdFZhbHVlLmNvZGUgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAg4oCUXG4gICAgICAgICAgICAgICAge3sgcHJvZHVjdFZhbHVlLmNvc3RSdWIudG9Mb2NhbGVTdHJpbmcoKSB9fSB7eyBwcm9kdWN0VmFsdWUuY3VycmVuY3kuc3ltYm9sIH19L9C8wrJcbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChwcm9kdWN0VmFsdWUpIHtcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtdC00IGZsZXggZmxleC1jb2wgZ2FwLTEuNVwiPlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3LWZ1bGwgZm9udC1ib2xkXCI+0KDQsNC30LzQtdGA0Ysg0LjQt9C00LXQu9C40Lk8L2Rpdj5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtMSB0ZXh0LXNtIHRleHQtdHVpLXRleHQtc2Vjb25kYXJ5XCI+XG4gICAgICAgICAgICAgICAgICAgIEBsZXQgd3QgPSB3aWR0aFJhbmdlVGV4dCgpO1xuICAgICAgICAgICAgICAgICAgICBAbGV0IGx0ID0gbGVuZ3RoUmFuZ2VUZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIEBpZiAod3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXY+0KjQuNGA0LjQvdCwIHt7IHd0IH19LjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIEBpZiAobHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXY+0JTQu9C40L3QsCB7eyBsdCB9fS48L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgIH1cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtM1wiPlxuICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgIGZvcm1BcnJheU5hbWU9XCJpdGVtc1wiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0zXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICBAZm9yIChpdGVtIG9mIGl0ZW1zLmNvbnRyb2xzOyB0cmFjayBpdGVtKSB7XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoJGluZGV4ID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGhyIGNsYXNzPVwiYm9yZGVyLXNjLWdyZXkgaC1weFwiIC8+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGxldCBpdGVtSW5kZXggPSAkaW5kZXg7XG4gICAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwicmVsYXRpdmUgZmxleCBmbGV4LWNvbCBnYXAtMVwiXG4gICAgICAgICAgICAgICAgICAgICAgICBbZm9ybUdyb3VwTmFtZV09XCJpdGVtSW5kZXhcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICBAaWYgKGlzSXRlbUxvY2tlZChpdGVtSW5kZXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInBvaW50ZXItZXZlbnRzLW5vbmUgYWJzb2x1dGUgcmlnaHQtMyBib3R0b20tMCB6LTEwIGZsZXggc2l6ZS04IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlclwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHVpLWljb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGljb249XCJAdHVpLmNoZWNrXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC10dWktc3RhdHVzLXBvc2l0aXZlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktbG9hZGVyIFtzaG93TG9hZGVyXT1cImlzSXRlbUxvYWRpbmcoaXRlbUluZGV4KVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NsYXNzLm9wYWNpdHktNzBdPVwiaXNJdGVtTG9ja2VkKGl0ZW1JbmRleClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggbWluLXctMCBpdGVtcy1zdGFydCBnYXAtMlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBtaW4tdy0wIGZsZXgtMSBmbGV4LWNvbCBnYXAtM1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTMgbGc6IWZsZXgtcm93IGxnOiFpdGVtcy1zdGFydCBsZzohZ2FwLTZcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tINCT0YDRg9C/0L/QsCAxOiDRiNC40YDQuNC90LAgKyDQtNC70LjQvdCwIC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJncmlkIGdyaWQtY29scy0xIGdhcC0yIHNtOmdyaWQtY29scy0yIGxnOiFmbGV4LVsyXVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgdHVpTGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDQqNC40YDQuNC90LAsINC80LxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktdGV4dGZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlJbnB1dFNsaWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ3aWR0aFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttaW5dPVwic2V0dGluZ3MoKT8ubWluV2lkdGggPz8gMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttYXhdPVwicHJvZHVjdC52YWx1ZT8ucHJvcGVydGllcz8ud2lkdGggPz8gMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0dWlOdW1iZXJGb3JtYXRdPVwieyBwcmVjaXNpb246IDAgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtyZWFkT25seV09XCIhcHJvZHVjdC52YWx1ZSB8fCBpc0l0ZW1Mb2NrZWQoaXRlbUluZGV4KSB8fCBpc0l0ZW1Mb2FkaW5nKGl0ZW1JbmRleClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cItCo0LjRgNC40L3QsFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9jb21wbGV0ZT1cIm9mZlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKHByb2R1Y3QudmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlTbGlkZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJyYW5nZVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90dWktdGV4dGZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS1lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cIndpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgdHVpTGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDQlNC70LjQvdCwLCDQvNC8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHVpLXRleHRmaWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpSW5wdXRTbGlkZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibGVuZ3RoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21pbl09XCJzZXR0aW5ncygpPy5taW5MZW5ndGggPz8gMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttYXhdPVwicHJvZHVjdC52YWx1ZT8ucHJvcGVydGllcz8ubGVuZ3RoID8/IDBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdHVpTnVtYmVyRm9ybWF0XT1cInsgcHJlY2lzaW9uOiAwIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcmVhZE9ubHldPVwiIXByb2R1Y3QudmFsdWUgfHwgaXNJdGVtTG9ja2VkKGl0ZW1JbmRleCkgfHwgaXNJdGVtTG9hZGluZyhpdGVtSW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCLQlNC70LjQvdCwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAocHJvZHVjdC52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aVNsaWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInJhbmdlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3R1aS10ZXh0ZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHVpLWVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibGVuZ3RoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0g0JPRgNGD0L/Qv9CwIDI6INC60L7Qu9C40YfQtdGB0YLQstC+ICsg0LzQsNGA0LrQuNGA0L7QstC60LAgKNC90LAgbGcgMWZyIHwgMmZyKSAtLT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZ3JpZCBncmlkLWNvbHMtMSBnYXAtMiBzbTpncmlkLWNvbHMtMiBsZzohZ3JpZC1jb2xzLVsxZnJfMmZyXSBsZzohZmxleC1bM11cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIHR1aUxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJ3aGl0ZXNwYWNlLW5vd3JhcFwiPtCa0L7Qu9C40YfQtdGB0YLQstC+LCDRiNGCPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS10ZXh0ZmllbGQgW3R1aVRleHRmaWVsZENsZWFuZXJdPVwiZmFsc2VcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpSW5wdXROdW1iZXJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY291bnRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWluXT1cIjFcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdHVpTnVtYmVyRm9ybWF0XT1cInsgcHJlY2lzaW9uOiAwIH1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcmVhZE9ubHldPVwiIXByb2R1Y3QudmFsdWUgfHwgaXNJdGVtTG9ja2VkKGl0ZW1JbmRleCkgfHwgaXNJdGVtTG9hZGluZyhpdGVtSW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCLQmtC+0LvQuNGH0LXRgdGC0LLQvlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9jb21wbGV0ZT1cIm9mZlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdHVpLXRleHRmaWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJjb3VudFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Vycm9yXT1cIltdIHwgdHVpRmllbGRFcnJvciB8IGFzeW5jXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGFiZWw+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxhYmVsIHR1aUxhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg0JzQsNGA0LrQuNGA0L7QstC60LBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktdGV4dGZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlUZXh0ZmllbGRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibWFya2VyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3JlYWRPbmx5XT1cIiFwcm9kdWN0LnZhbHVlIHx8IGlzSXRlbUxvY2tlZChpdGVtSW5kZXgpIHx8IGlzSXRlbUxvYWRpbmcoaXRlbUluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwi0JzQsNGA0LrQuNGA0L7QstC60LBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3R1aS10ZXh0ZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHVpLWVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwibWFya2VyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAbGV0IHJvd1ZhbCA9IGl0ZW0uZ2V0UmF3VmFsdWUoKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChyb3dWYWwud2lkdGggPiAwICYmIHJvd1ZhbC5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm10LTEgZmxleCBmbGV4LWNvbCBnYXAteS0xIHRleHQtc20gbGc6IWZsZXgtcm93IGxnOiFnYXAtNlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKHBpZWNlQXJlYU0yKHJvd1ZhbCkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGc6IWZsZXgtWzJdXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg0J/Qu9C+0YnQsNC00YwgKFMpID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cImZvbnQtYm9sZFwiPnt7IHBpZWNlQXJlYU0yKHJvd1ZhbCkgfCBudW1iZXI6ICcxLjAtNCcgfX0g0LzCsjwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAocHJvZHVjdFZhbHVlICYmIHJvd0Nvc3Qocm93VmFsKSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsZzohZmxleC1bM11cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDQmNGC0L7Qs9C+OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZm9udC1ib2xkXCI+e3sgcm93Q29zdChyb3dWYWwpLnRvTG9jYWxlU3RyaW5nKCkgfX0ge3sgcHJvZHVjdFZhbHVlLmN1cnJlbmN5LnN5bWJvbCB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoIWlzRWRpdGluZ0V4aXN0aW5nSXRlbSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpSWNvbkJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlPVwi0KPQtNCw0LvQuNGC0Ywg0LjQt9C00LXQu9C40LVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJyZW1vdmVJdGVtKGl0ZW1JbmRleClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJpdGVtcy5sZW5ndGggPD0gMSB8fCAhcHJvZHVjdC52YWx1ZSB8fCBpc0l0ZW1Mb2FkaW5nKGl0ZW1JbmRleClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpemU9XCJtXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpY29uU3RhcnQ9XCJAdHVpLnRyYXNoLTJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFwcGVhcmFuY2U9XCJzZWNvbmRhcnlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwibXQtNiBzaHJpbmstMCBsZzohbWwtNFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLmZsZXhdPVwiJzAgMCBhdXRvJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA+PC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvdHVpLWxvYWRlcj5cbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgIEBpZiAocHJvZHVjdFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgPGhyIGNsYXNzPVwiYm9yZGVyLXNjLWdyZXkgaC1weFwiIC8+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC13cmFwIGl0ZW1zLWVuZCBnYXAtNCBwdC0yXCI+XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoIWlzRWRpdGluZ0V4aXN0aW5nSXRlbSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwZWFyYW5jZT1cInNlY29uZGFyeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIiFwcm9kdWN0LnZhbHVlIHx8IGl0ZW1zLmludmFsaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJhZGRJdGVtKClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwic2VsZi1zdGFydFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWNvblN0YXJ0PVwiQHR1aS5wbHVzXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICDQlNC+0LHQsNCy0LjRgtGMINC40LfQtNC10LvQuNC1XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtbC1hdXRvIG1pbi13LTAgZ2FwLTEgdGV4dC1yaWdodFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgQGlmICh0b3RhbEFyZWFNMigpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgINCe0LHRidCw0Y8g0L/Qu9C+0YnQsNC00Yw6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZm9udC1ib2xkXCI+e3sgdG90YWxBcmVhTTIoKSB8IG51bWJlcjogJzEuMC00JyB9fSDQvMKyPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChwcm9kdWN0VmFsdWUuY29zdFJ1YiAmJiB0b3RhbENvc3QoKSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDQmNGC0L7Qs9C+OlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIndoaXRlc3BhY2Utbm93cmFwIHRleHQteGwgZm9udC1ib2xkXCI+IHt7IHRvdGFsQ29zdCgpLnRvTG9jYWxlU3RyaW5nKCkgfX0ge3sgcHJvZHVjdFZhbHVlLmN1cnJlbmN5LnN5bWJvbCB9fSA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8dHVpLWVycm9yIFtlcnJvcl09XCJbXSB8IHR1aUZpZWxkRXJyb3IgfCBhc3luY1wiIC8+XG5cbiAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgdHlwZT1cInN1Ym1pdFwiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZm9ybS5pbnZhbGlkIHx8IGlzU3VibWl0TG9hZGluZygpIHx8IGhhc05vUGVuZGluZ0l0ZW1zKClcIlxuICAgICAgICAgICAgW2xvYWRpbmddPVwiaXNTdWJtaXRMb2FkaW5nKClcIlxuICAgICAgICAgICAgdHVpQnV0dG9uXG4gICAgICAgICAgICBjbGFzcz1cInNlbGYtc3RhcnRcIlxuICAgICAgICAgICAgaWNvblN0YXJ0PVwiQHR1aS5jaGVja1wiXG4gICAgICAgID5cbiAgICAgICAgICAgIHt7ICFvcmRlckl0ZW0oKSA/ICfQkiDQutC+0YDQt9C40L3RgycgOiAn0JjQt9C80LXQvdC40YLRjCcgfX1cbiAgICAgICAgPC9idXR0b24+XG4gICAgPC9mb3JtPlxuPC9kaXY+XG4iXX0=
|