@snabcentr/client-ui 3.51.15 → 3.52.1
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/directives/next-input-focus/sc-next-input-focus.directive.d.ts +14 -5
- 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 +561 -0
- package/esm2022/directives/next-input-focus/sc-next-input-focus.directive.mjs +39 -12
- package/fesm2022/snabcentr-client-ui.mjs +651 -16
- package/fesm2022/snabcentr-client-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/release_notes.tmp +3 -3
- package/styles/tailwind/tailwind.scss +72 -0
|
@@ -0,0 +1,561 @@
|
|
|
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 { TuiAutoFocus, 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 mb-3 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 [tuiAutoFocus]=\"!$first\"\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=\"min-w-0 gap-1 pt-2 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 }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <div class=\"flex flex-wrap items-center gap-3\">\n @if (productValue && !isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\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 <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"ml-auto\"\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 </div>\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"] }, { kind: "directive", type: TuiAutoFocus, selector: "[tuiAutoFocus]", inputs: ["tuiAutoFocus"] }], 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
|
+
TuiAutoFocus,
|
|
548
|
+
], providers: [
|
|
549
|
+
tuiNumberFormatProvider({ precision: 0 }),
|
|
550
|
+
tuiInputNumberOptionsProvider({
|
|
551
|
+
min: 0,
|
|
552
|
+
}),
|
|
553
|
+
tuiItemsHandlersProvider({
|
|
554
|
+
stringify: signal((x) => x.name),
|
|
555
|
+
identityMatcher: signal((a, b) => a.id === b.id),
|
|
556
|
+
}),
|
|
557
|
+
], 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 mb-3 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 [tuiAutoFocus]=\"!$first\"\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=\"min-w-0 gap-1 pt-2 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 }\n </div>\n\n <tui-error [error]=\"[] | tuiFieldError | async\" />\n\n <div class=\"flex flex-wrap items-center gap-3\">\n @if (productValue && !isEditingExistingItem()) {\n <button\n tuiButton\n appearance=\"secondary\"\n [disabled]=\"!product.value || items.invalid\"\n (click)=\"addItem()\"\n type=\"button\"\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 <button\n type=\"submit\"\n [disabled]=\"form.invalid || isSubmitLoading() || hasNoPendingItems()\"\n [loading]=\"isSubmitLoading()\"\n tuiButton\n class=\"ml-auto\"\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 </div>\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"] }]
|
|
558
|
+
}], propDecorators: { orderId: [{
|
|
559
|
+
type: Input
|
|
560
|
+
}] } });
|
|
561
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Mtc2FuZHdpY2gtbTIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NvbmZpZ3VyYXRvcnMvc2FuZHdpY2hfbTIvc2Mtc2FuZHdpY2gtbTIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL2NvbmZpZ3VyYXRvcnMvc2FuZHdpY2hfbTIvc2Mtc2FuZHdpY2gtbTIuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdUZBQXVGO0FBRXZGLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDekQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDekQsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkksT0FBTyxFQUFFLGtCQUFrQixFQUFFLFlBQVksRUFBRSxRQUFRLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN4RixPQUFPLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLG1CQUFtQixFQUFlLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQzlILE9BQU8sRUFDSCxlQUFlLEVBRWYsZ0JBQWdCLEVBQ2hCLG1CQUFtQixHQU90QixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBRSxZQUFZLEVBQUUsZUFBZSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzlELE9BQU8sRUFDSCxTQUFTLEVBRVQsUUFBUSxFQUNSLE9BQU8sRUFDUCx3QkFBd0IsRUFDeEIsUUFBUSxFQUNSLFNBQVMsRUFDVCxlQUFlLEVBQ2YsdUJBQXVCLEVBQ3ZCLFlB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LDBDQUNYLGlCQUFpQiw4UUFFakIsMEJBQTBCLGdNQUMxQixTQUFTLGlJQUNULGdCQUFnQix1SEFDaEIsT0FBTyxxRkFDUCxZQUFZOzs0RkFjUCxxQkFBcUI7a0JBeENqQyxTQUFTO2lDQUNNLElBQUksWUFDTixnQkFBZ0IsV0FHakI7d0JBQ0wsU0FBUzt3QkFDVCxXQUFXO3dCQUNYLG1CQUFtQjt3QkFDbkIsc0JBQXNCO3dCQUN0QixRQUFRO3dCQUNSLDJCQUEyQjt3QkFDM0IsUUFBUTt3QkFDUixZQUFZO3dCQUNaLFVBQVU7d0JBQ1YsU0FBUzt3QkFDVCxjQUFjO3dCQUNkLGVBQWU7d0JBQ2YsU0FBUzt3QkFDVCxXQUFXO3dCQUNYLGlCQUFpQjt3QkFDakIsY0FBYzt3QkFDZCwwQkFBMEI7d0JBQzFCLFNBQVM7d0JBQ1QsZ0JBQWdCO3dCQUNoQixPQUFPO3dCQUNQLFlBQVk7cUJBQ2YsYUFDVTt3QkFDUCx1QkFBdUIsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLEVBQUUsQ0FBQzt3QkFDekMsNkJBQTZCLENBQUM7NEJBQzFCLEdBQUcsRUFBRSxDQUFDO3lCQUNULENBQUM7d0JBQ0Ysd0JBQXdCLENBQUM7NEJBQ3JCLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFZLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7NEJBQzNDLGVBQWUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFZLEVBQUUsQ0FBWSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUM7eUJBQ3pFLENBQUM7cUJBQ0wsbUJBQ2dCLHVCQUF1QixDQUFDLE1BQU07OEJBMkJ4QyxPQUFPO3NCQURiLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBzZWN1cml0eS9kZXRlY3Qtb2JqZWN0LWluamVjdGlvbixAdHlwZXNjcmlwdC1lc2xpbnQvdW5ib3VuZC1tZXRob2QgKi9cblxuaW1wb3J0IHsgQXN5bmNQaXBlLCBEZWNpbWFsUGlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBIdHRwRXJyb3JSZXNwb25zZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGNvbXB1dGVkLCBEZXN0cm95UmVmLCBpbmplY3QsIElucHV0LCBpbnB1dCwgT25Jbml0LCBvdXRwdXQsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkLCB0b09ic2VydmFibGUsIHRvU2lnbmFsIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgRm9ybUFycmF5LCBGb3JtQ29udHJvbCwgRm9ybUdyb3VwLCBGb3Jtc01vZHVsZSwgUmVhY3RpdmVGb3Jtc01vZHVsZSwgVmFsaWRhdG9yRm4sIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQge1xuICAgIFNDX09SREVSX0xPQURFUixcbiAgICBTY0NhcnQsXG4gICAgU2NDYXRhbG9nU2VydmljZSxcbiAgICBTY0NvbnZlcnRlcnNTZXJ2aWNlLFxuICAgIFNjSUFwaUVycm9yUmVzcG9uc2UsXG4gICAgU2NJTmV3T3JkZXJJdGVtQmFzZSxcbiAgICBTY0lPcmRlckVkaXRvckxvYWRlcixcbiAgICBTY09yZGVyRHJhZnQsXG4gICAgU2NPcmRlckl0ZW0sXG4gICAgU2NQcm9kdWN0LFxufSBmcm9tICdAc25hYmNlbnRyL2NsaWVudC1jb3JlJztcbmltcG9ydCB7IFR1aUF1dG9Gb2N1cywgdHVpQ29udHJvbFZhbHVlIH0gZnJvbSAnQHRhaWdhLXVpL2Nkayc7XG5pbXBvcnQge1xuICAgIFR1aUJ1dHRvbixcbiAgICBUdWlEaWFsb2dDb250ZXh0LFxuICAgIFR1aUVycm9yLFxuICAgIFR1aUljb24sXG4gICAgdHVpSXRlbXNIYW5kbGVyc1Byb3ZpZGVyLFxuICAgIFR1aUxhYmVsLFxuICAgIFR1aUxvYWRlcixcbiAgICBUdWlOdW1iZXJGb3JtYXQsXG4gICAgdHVpTnVtYmVyRm9ybWF0UHJvdmlkZXIsXG4gICAgVHVpVGV4dGZpZWxkLFxufSBmcm9tICdAdGFpZ2EtdWkvY29yZSc7XG5pbXBvcnQge1xuICAgIFR1aUJ1dHRvbkxvYWRpbmcsXG4gICAgVHVpQ2hldnJvbixcbiAgICBUdWlEYXRhTGlzdFdyYXBwZXJDb21wb25lbnQsXG4gICAgVHVpRmllbGRFcnJvclBpcGUsXG4gICAgVHVpSW5wdXROdW1iZXIsXG4gICAgdHVpSW5wdXROdW1iZXJPcHRpb25zUHJvdmlkZXIsXG4gICAgVHVpSW5wdXRTbGlkZXIsXG4gICAgVHVpU2VsZWN0LFxufSBmcm9tICdAdGFpZ2EtdWkva2l0JztcbmltcG9ydCB7IFBPTFlNT1JQSEVVU19DT05URVhUIH0gZnJvbSAnQHRhaWdhLXVpL3BvbHltb3JwaGV1cyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBjb25jYXRNYXAsIGZyb20sIG1hcCwgT2JzZXJ2YWJsZSwgb2YsIHN3aXRjaE1hcCwgdGFwLCB0aHJvd0Vycm9yIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFNjTmV4dElucHV0Rm9jdXNNb2R1bGUgfSBmcm9tICcuLi8uLi9kaXJlY3RpdmVzL25leHQtaW5wdXQtZm9jdXMvc2MtbmV4dC1pbnB1dC1mb2N1cy5tb2R1bGUnO1xuaW1wb3J0IHsgU2NTZWxlY3RPbkZvY3VzaW5EaXJlY3RpdmUgfSBmcm9tICcuLi8uLi9kaXJlY3RpdmVzL3NlbGVjdC1vbi1mb2N1c2luL3NjLXNlbGVjdC1vbi1mb2N1c2luLmRpcmVjdGl2ZSc7XG5pbXBvcnQgeyBzdGVwVmFsaWRhdG9yIH0gZnJvbSAnLi4vLi4vdmFsaWRhdG9ycy9zdGVwLXZhbGlkYXRvcic7XG5pbXBvcnQgeyBTY0lTYW5kd2ljaE0yU2V0dGluZ3MgfSBmcm9tICcuLi9tb2RlbHMvc2FuZHdpY2hfbTIvc2MtaS1zYW5kd2ljaC1tMi1zZXR0aW5ncyc7XG5pbXBvcnQgeyBTY0lOZXdDYXJ0SXRlbVNhbmR3aWNoTTIgfSBmcm9tICcuL3NjLWktbmV3LWNhcnQtaXRlbS1zYW5kd2ljaC1tMic7XG5pbXBvcnQgeyBJRExFX0lURU1fU1RBVEUsIFNjU2FuZHdpY2hNMkl0ZW1TdWJtaXRTdGF0ZSB9IGZyb20gJy4vc2Mtc2FuZHdpY2gtbTItaXRlbS1zdWJtaXQtc3RhdGUnO1xuXG4vKipcbiAqINCa0L7QvdGE0LjQs9GD0YDQsNGC0L7RgCDRgNCw0YHQv9C40LvQsCDRgdGN0L3QtNCy0LjRhy3Qv9Cw0L3QtdC70LXQuSDQv9C+INC/0LvQvtGJ0LDQtNC4LlxuICovXG5AQ29tcG9uZW50KHtcbiAgICBzdGFuZGFsb25lOiB0cnVlLFxuICAgIHNlbGVjdG9yOiAnc2Mtc2FuZHdpY2gtbTInLFxuICAgIHRlbXBsYXRlVXJsOiAnLi9zYy1zYW5kd2ljaC1tMi5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmw6ICcuL3NjLXNhbmR3aWNoLW0yLmNvbXBvbmVudC5zY3NzJyxcbiAgICBpbXBvcnRzOiBbXG4gICAgICAgIFR1aUJ1dHRvbixcbiAgICAgICAgRm9ybXNNb2R1bGUsXG4gICAgICAgIFJlYWN0aXZlRm9ybXNNb2R1bGUsXG4gICAgICAgIFNjTmV4dElucHV0Rm9jdXNNb2R1bGUsXG4gICAgICAgIFR1aUxhYmVsLFxuICAgICAgICBUdWlEYXRhTGlzdFdyYXBwZXJDb21wb25lbnQsXG4gICAgICAgIFR1aUVycm9yLFxuICAgICAgICBUdWlUZXh0ZmllbGQsXG4gICAgICAgIFR1aUNoZXZyb24sXG4gICAgICAgIFR1aVNlbGVjdCxcbiAgICAgICAgVHVpSW5wdXROdW1iZXIsXG4gICAgICAgIFR1aU51bWJlckZvcm1hdCxcbiAgICAgICAgQXN5bmNQaXBlLFxuICAgICAgICBEZWNpbWFsUGlwZSxcbiAgICAgICAgVHVpRmllbGRFcnJvclBpcGUsXG4gICAgICAgIFR1aUlucHV0U2xpZGVyLFxuICAgICAgICBTY1NlbGVjdE9uRm9jdXNpbkRpcmVjdGl2ZSxcbiAgICAgICAgVHVpTG9hZGVyLFxuICAgICAgICBUdWlCdXR0b25Mb2FkaW5nLFxuICAgICAgICBUdWlJY29uLFxuICAgICAgICBUdWlBdXRvRm9jdXMsXG4gICAgXSxcbiAgICBwcm92aWRlcnM6IFtcbiAgICAgICAgdHVpTnVtYmVyRm9ybWF0UHJvdmlkZXIoeyBwcmVjaXNpb246IDAgfSksXG4gICAgICAgIHR1aUlucHV0TnVtYmVyT3B0aW9uc1Byb3ZpZGVyKHtcbiAgICAgICAgICAgIG1pbjogMCxcbiAgICAgICAgfSksXG4gICAgICAgIHR1aUl0ZW1zSGFuZGxlcnNQcm92aWRlcih7XG4gICAgICAgICAgICBzdHJpbmdpZnk6IHNpZ25hbCgoeDogU2NQcm9kdWN0KSA9PiB4Lm5hbWUpLFxuICAgICAgICAgICAgaWRlbnRpdHlNYXRjaGVyOiBzaWduYWwoKGE6IFNjUHJvZHVjdCwgYjogU2NQcm9kdWN0KSA9PiBhLmlkID09PSBiLmlkKSxcbiAgICAgICAgfSksXG4gICAgXSxcbiAgICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgU2NTYW5kd2ljaE0yQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgICAvKipcbiAgICAgKiDQndCw0YHRgtGA0L7QudC60Lgg0LTQu9GPINC60L7QvdGE0LjQs9GD0YDQsNGC0L7RgNCwINGA0LDRgdC/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+XG4gICAgICAgICAgICAgICAg4oCUXG4gICAgICAgICAgICAgICAge3sgcHJvZHVjdFZhbHVlLmNvc3RSdWIudG9Mb2NhbGVTdHJpbmcoKSB9fSB7eyBwcm9kdWN0VmFsdWUuY3VycmVuY3kuc3ltYm9sIH19L9C8wrJcbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChwcm9kdWN0VmFsdWUpIHtcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtdC00IG1iLTMgZmxleCBmbGV4LWNvbCBnYXAtMS41XCI+XG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInctZnVsbCBmb250LWJvbGRcIj7QoNCw0LfQvNC10YDRiyDQuNC30LTQtdC70LjQuTwvZGl2PlxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0xIHRleHQtc20gdGV4dC10dWktdGV4dC1zZWNvbmRhcnlcIj5cbiAgICAgICAgICAgICAgICAgICAgQGxldCB3dCA9IHdpZHRoUmFuZ2VUZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIEBsZXQgbHQgPSBsZW5ndGhSYW5nZVRleHQoKTtcbiAgICAgICAgICAgICAgICAgICAgQGlmICh3dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj7QqNC40YDQuNC90LAge3sgd3QgfX0uPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGlmIChsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj7QlNC70LjQvdCwIHt7IGx0IH19LjwvZGl2PlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgfVxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0zXCI+XG4gICAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAgICAgZm9ybUFycmF5TmFtZT1cIml0ZW1zXCJcbiAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTNcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgIEBmb3IgKGl0ZW0gb2YgaXRlbXMuY29udHJvbHM7IHRyYWNrIGl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgICAgQGlmICgkaW5kZXggPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8aHIgY2xhc3M9XCJib3JkZXItc2MtZ3JleSBoLXB4XCIgLz5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBAbGV0IGl0ZW1JbmRleCA9ICRpbmRleDtcbiAgICAgICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJyZWxhdGl2ZSBmbGV4IGZsZXgtY29sIGdhcC0xXCJcbiAgICAgICAgICAgICAgICAgICAgICAgIFtmb3JtR3JvdXBOYW1lXT1cIml0ZW1JbmRleFwiXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAoaXNJdGVtTG9ja2VkKGl0ZW1JbmRleCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicG9pbnRlci1ldmVudHMtbm9uZSBhYnNvbHV0ZSByaWdodC0zIGJvdHRvbS0wIHotMTAgZmxleCBzaXplLTggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktaWNvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWNvbj1cIkB0dWkuY2hlY2tcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJ0ZXh0LXR1aS1zdGF0dXMtcG9zaXRpdmVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS1sb2FkZXIgW3Nob3dMb2FkZXJdPVwiaXNJdGVtTG9hZGluZyhpdGVtSW5kZXgpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3Mub3BhY2l0eS03MF09XCJpc0l0ZW1Mb2NrZWQoaXRlbUluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmxleCBtaW4tdy0wIGl0ZW1zLXN0YXJ0IGdhcC0yXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IG1pbi13LTAgZmxleC0xIGZsZXgtY29sIGdhcC0zXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtMyBsZzohZmxleC1yb3cgbGc6IWl0ZW1zLXN0YXJ0IGxnOiFnYXAtNlwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0g0JPRgNGD0L/Qv9CwIDE6INGI0LjRgNC40L3QsCArINC00LvQuNC90LAgLS0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImdyaWQgZ3JpZC1jb2xzLTEgZ2FwLTIgc206Z3JpZC1jb2xzLTIgbGc6IWZsZXgtWzJdXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCB0dWlMYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgINCo0LjRgNC40L3QsCwg0LzQvFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS10ZXh0ZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aUlucHV0U2xpZGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cIndpZHRoXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21pbl09XCJzZXR0aW5ncygpPy5taW5XaWR0aCA/PyAwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21heF09XCJwcm9kdWN0LnZhbHVlPy5wcm9wZXJ0aWVzPy53aWR0aCA/PyAwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3R1aU51bWJlckZvcm1hdF09XCJ7IHByZWNpc2lvbjogMCB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3JlYWRPbmx5XT1cIiFwcm9kdWN0LnZhbHVlIHx8IGlzSXRlbUxvY2tlZChpdGVtSW5kZXgpIHx8IGlzSXRlbUxvYWRpbmcoaXRlbUluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0dWlBdXRvRm9jdXNdPVwiISRmaXJzdFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwi0KjQuNGA0LjQvdCwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAocHJvZHVjdC52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aVNsaWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1cInJhbmdlXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3R1aS10ZXh0ZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHVpLWVycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwid2lkdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtlcnJvcl09XCJbXSB8IHR1aUZpZWxkRXJyb3IgfCBhc3luY1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCB0dWlMYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgINCU0LvQuNC90LAsINC80LxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktdGV4dGZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlJbnB1dFNsaWRlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJsZW5ndGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWluXT1cInNldHRpbmdzKCk/Lm1pbkxlbmd0aCA/PyAwXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21heF09XCJwcm9kdWN0LnZhbHVlPy5wcm9wZXJ0aWVzPy5sZW5ndGggPz8gMFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0dWlOdW1iZXJGb3JtYXRdPVwieyBwcmVjaXNpb246IDAgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtyZWFkT25seV09XCIhcHJvZHVjdC52YWx1ZSB8fCBpc0l0ZW1Mb2NrZWQoaXRlbUluZGV4KSB8fCBpc0l0ZW1Mb2FkaW5nKGl0ZW1JbmRleClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cItCU0LvQuNC90LBcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJvZmZcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChwcm9kdWN0LnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpU2xpZGVyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwicmFuZ2VcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdHVpLXRleHRmaWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJsZW5ndGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtlcnJvcl09XCJbXSB8IHR1aUZpZWxkRXJyb3IgfCBhc3luY1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSDQk9GA0YPQv9C/0LAgMjog0LrQvtC70LjRh9C10YHRgtCy0L4gKyDQvNCw0YDQutC40YDQvtCy0LrQsCAo0L3QsCBsZyAxZnIgfCAyZnIpIC0tPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJncmlkIGdyaWQtY29scy0xIGdhcC0yIHNtOmdyaWQtY29scy0yIGxnOiFncmlkLWNvbHMtWzFmcl8yZnJdIGxnOiFmbGV4LVszXVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgdHVpTGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIndoaXRlc3BhY2Utbm93cmFwXCI+0JrQvtC70LjRh9C10YHRgtCy0L4sINGI0YI8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dHVpLXRleHRmaWVsZCBbdHVpVGV4dGZpZWxkQ2xlYW5lcl09XCJmYWxzZVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlJbnB1dE51bWJlclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJjb3VudFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFttaW5dPVwiMVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFt0dWlOdW1iZXJGb3JtYXRdPVwieyBwcmVjaXNpb246IDAgfVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtyZWFkT25seV09XCIhcHJvZHVjdC52YWx1ZSB8fCBpc0l0ZW1Mb2NrZWQoaXRlbUluZGV4KSB8fCBpc0l0ZW1Mb2FkaW5nKGl0ZW1JbmRleClcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cItCa0L7Qu9C40YfQtdGB0YLQstC+XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXV0b2NvbXBsZXRlPVwib2ZmXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC90dWktdGV4dGZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS1lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImNvdW50XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgdHVpTGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDQnNCw0YDQutC40YDQvtCy0LrQsFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHR1aS10ZXh0ZmllbGQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aVRleHRmaWVsZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJtYXJrZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbcmVhZE9ubHldPVwiIXByb2R1Y3QudmFsdWUgfHwgaXNJdGVtTG9ja2VkKGl0ZW1JbmRleCkgfHwgaXNJdGVtTG9hZGluZyhpdGVtSW5kZXgpXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCLQnNCw0YDQutC40YDQvtCy0LrQsFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF1dG9jb21wbGV0ZT1cIm9mZlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdHVpLXRleHRmaWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0dWktZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJtYXJrZXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtlcnJvcl09XCJbXSB8IHR1aUZpZWxkRXJyb3IgfCBhc3luY1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBsZXQgcm93VmFsID0gaXRlbS5nZXRSYXdWYWx1ZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKHJvd1ZhbC53aWR0aCA+IDAgJiYgcm93VmFsLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibXQtMSBmbGV4IGZsZXgtY29sIGdhcC15LTEgdGV4dC1zbSBsZzohZmxleC1yb3cgbGc6IWdhcC02XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEBpZiAocGllY2VBcmVhTTIocm93VmFsKSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJsZzohZmxleC1bMl1cIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDQn9C70L7RidCw0LTRjCAoUykgPVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZm9udC1ib2xkXCI+e3sgcGllY2VBcmVhTTIocm93VmFsKSB8IG51bWJlcjogJzEuMC00JyB9fSDQvMKyPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmIChwcm9kdWN0VmFsdWUgJiYgcm93Q29zdChyb3dWYWwpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImxnOiFmbGV4LVszXVwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgINCY0YLQvtCz0L46XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJmb250LWJvbGRcIj57eyByb3dDb3N0KHJvd1ZhbCkudG9Mb2NhbGVTdHJpbmcoKSB9fSB7eyBwcm9kdWN0VmFsdWUuY3VycmVuY3kuc3ltYm9sIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQGlmICghaXNFZGl0aW5nRXhpc3RpbmdJdGVtKCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlJY29uQnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGl0bGU9XCLQo9C00LDQu9C40YLRjCDQuNC30LTQtdC70LjQtVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInJlbW92ZUl0ZW0oaXRlbUluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Rpc2FibGVkXT1cIml0ZW1zLmxlbmd0aCA8PSAxIHx8ICFwcm9kdWN0LnZhbHVlIHx8IGlzSXRlbUxvYWRpbmcoaXRlbUluZGV4KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZT1cIm1cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGljb25TdGFydD1cIkB0dWkudHJhc2gtMlwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXBwZWFyYW5jZT1cInNlY29uZGFyeVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtdC02IHNocmluay0wIGxnOiFtbC00XCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc3R5bGUuZmxleF09XCInMCAwIGF1dG8nXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID48L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICAgICAgPC90dWktbG9hZGVyPlxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgQGlmIChwcm9kdWN0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICA8aHIgY2xhc3M9XCJib3JkZXItc2MtZ3JleSBoLXB4XCIgLz5cbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWluLXctMCBnYXAtMSBwdC0yIHRleHQtcmlnaHRcIj5cbiAgICAgICAgICAgICAgICAgICAgQGlmICh0b3RhbEFyZWFNMigpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICDQntCx0YnQsNGPINC/0LvQvtGJ0LDQtNGMOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZm9udC1ib2xkXCI+e3sgdG90YWxBcmVhTTIoKSB8IG51bWJlcjogJzEuMC00JyB9fSDQvMKyPC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQGlmIChwcm9kdWN0VmFsdWUuY29zdFJ1YiAmJiB0b3RhbENvc3QoKSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXY+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAg0JjRgtC+0LPQvjpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cIndoaXRlc3BhY2Utbm93cmFwIHRleHQteGwgZm9udC1ib2xkXCI+IHt7IHRvdGFsQ29zdCgpLnRvTG9jYWxlU3RyaW5nKCkgfX0ge3sgcHJvZHVjdFZhbHVlLmN1cnJlbmN5LnN5bWJvbCB9fSA8L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8dHVpLWVycm9yIFtlcnJvcl09XCJbXSB8IHR1aUZpZWxkRXJyb3IgfCBhc3luY1wiIC8+XG5cbiAgICAgICAgPGRpdiBjbGFzcz1cImZsZXggZmxleC13cmFwIGl0ZW1zLWNlbnRlciBnYXAtM1wiPlxuICAgICAgICAgICAgQGlmIChwcm9kdWN0VmFsdWUgJiYgIWlzRWRpdGluZ0V4aXN0aW5nSXRlbSgpKSB7XG4gICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICB0dWlCdXR0b25cbiAgICAgICAgICAgICAgICAgICAgYXBwZWFyYW5jZT1cInNlY29uZGFyeVwiXG4gICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCIhcHJvZHVjdC52YWx1ZSB8fCBpdGVtcy5pbnZhbGlkXCJcbiAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cImFkZEl0ZW0oKVwiXG4gICAgICAgICAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgICAgICAgICBpY29uU3RhcnQ9XCJAdHVpLnBsdXNcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAg0JTQvtCx0LDQstC40YLRjCDQuNC30LTQtdC70LjQtVxuICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgIHR5cGU9XCJzdWJtaXRcIlxuICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJmb3JtLmludmFsaWQgfHwgaXNTdWJtaXRMb2FkaW5nKCkgfHwgaGFzTm9QZW5kaW5nSXRlbXMoKVwiXG4gICAgICAgICAgICAgICAgW2xvYWRpbmddPVwiaXNTdWJtaXRMb2FkaW5nKClcIlxuICAgICAgICAgICAgICAgIHR1aUJ1dHRvblxuICAgICAgICAgICAgICAgIGNsYXNzPVwibWwtYXV0b1wiXG4gICAgICAgICAgICAgICAgaWNvblN0YXJ0PVwiQHR1aS5jaGVja1wiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAge3sgIW9yZGVySXRlbSgpID8gJ9CSINC60L7RgNC30LjQvdGDJyA6ICfQmNC30LzQtdC90LjRgtGMJyB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgIDwvZGl2PlxuICAgIDwvZm9ybT5cbjwvZGl2PlxuIl19
|