@snabcentr/client-ui 4.6.6 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2022/order/index.mjs +5 -1
- package/esm2022/order/models/i-new-order-form.mjs +2 -0
- package/esm2022/order/order-direction-items/sc-order-direction-items.component.mjs +39 -0
- package/esm2022/order/order-form/sc-order-form.component.mjs +545 -0
- package/esm2022/order/order-form/sc-order-form.config.mjs +7 -0
- package/fesm2022/snabcentr-client-ui.mjs +571 -8
- package/fesm2022/snabcentr-client-ui.mjs.map +1 -1
- package/order/index.d.ts +4 -0
- package/order/models/i-new-order-form.d.ts +39 -0
- package/order/order-direction-items/sc-order-direction-items.component.d.ts +29 -0
- package/order/order-form/sc-order-form.component.d.ts +264 -0
- package/order/order-form/sc-order-form.config.d.ts +20 -0
- package/package.json +2 -1
- package/release_notes.tmp +2 -14
- package/styles/tailwind/tailwind.scss +9 -0
|
@@ -0,0 +1,545 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion,rxjs/no-sharereplay,@typescript-eslint/no-unsafe-enum-comparison,@typescript-eslint/unbound-method,@typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-unsafe-call,@typescript-eslint/no-unsafe-argument,security/detect-object-injection */
|
|
2
|
+
import { AsyncPipe } from '@angular/common';
|
|
3
|
+
import { HttpErrorResponse } from '@angular/common/http';
|
|
4
|
+
import { ChangeDetectionStrategy, Component, computed, DestroyRef, inject, input, output, signal, viewChild } from '@angular/core';
|
|
5
|
+
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
|
|
6
|
+
import { FormControl, FormGroup, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
|
|
7
|
+
import { RouterLink } from '@angular/router';
|
|
8
|
+
import { IS_RUNNING_ON_TERMINAL, IS_SERVER, SC_USER_INFO, ScContragentService, ScConvertersService, ScDeliveryAddressService, ScDeliveryType, ScOpfList, ScOrdersService, ScPaymentType, ScReferencesService, ScUIService, ScUploadedFile, ScWarehouseService, TERMINAL_PROVIDERS, } from '@snabcentr/client-core';
|
|
9
|
+
import { tuiControlValue, tuiIsPresent, TuiValidationError } from '@taiga-ui/cdk';
|
|
10
|
+
import { TuiDataListComponent, TuiDialogService, TuiError, TuiLabel, TuiLink, TuiLoader, TuiOption } from '@taiga-ui/core';
|
|
11
|
+
import { TuiDataListDirective } from '@taiga-ui/core/components/data-list';
|
|
12
|
+
import { TuiFieldErrorPipe, TuiFile, TuiFileRejectedPipe, tuiFilesAccepted, TuiFilesComponent, TuiInputFiles, TuiInputFilesDirective } from '@taiga-ui/kit';
|
|
13
|
+
import { TuiInputDateModule, TuiSelectModule, TuiTextareaModule } from '@taiga-ui/legacy';
|
|
14
|
+
import { PolymorpheusComponent } from '@taiga-ui/polymorpheus';
|
|
15
|
+
import { format, isValid, parse } from 'date-fns';
|
|
16
|
+
import { isArray, isString } from 'lodash-es';
|
|
17
|
+
import { catchError, combineLatest, debounceTime, filter, first, map, merge, of, retry, shareReplay, switchMap, tap, throwError } from 'rxjs';
|
|
18
|
+
import { ScAddContragentDialogComponent } from '../../contragents/add-contragent-dialog/sc-add-contragent-dialog.component';
|
|
19
|
+
import { ScAddDeliveryAddressDialogComponent } from '../../delivery-address/add-delivery-address-dialog/sc-add-delivery-address-dialog.component';
|
|
20
|
+
import { ScFocusFirstInvalidFieldDirective } from '../../directives/sc-focus-first-invalid-field.directive';
|
|
21
|
+
import { SC_ORDER_FORM_CONFIG } from './sc-order-form.config';
|
|
22
|
+
import * as i0 from "@angular/core";
|
|
23
|
+
import * as i1 from "@angular/forms";
|
|
24
|
+
import * as i2 from "@taiga-ui/legacy";
|
|
25
|
+
import * as i3 from "@taiga-ui/core/components/data-list";
|
|
26
|
+
/**
|
|
27
|
+
* Форма оформления заказа.
|
|
28
|
+
*/
|
|
29
|
+
export class ScOrderFormComponent {
|
|
30
|
+
/**
|
|
31
|
+
* Инициализирует экземпляр класса {@link ScOrderFormComponent}.
|
|
32
|
+
*/
|
|
33
|
+
constructor() {
|
|
34
|
+
/**
|
|
35
|
+
* Идентификатор направления продаж заказа.
|
|
36
|
+
*/
|
|
37
|
+
this.directionId = input.required();
|
|
38
|
+
/**
|
|
39
|
+
* Требовать подтверждённые контактные данные для оформления. Для черновика — `false`.
|
|
40
|
+
*/
|
|
41
|
+
this.enforceApprovedContacts = input(true);
|
|
42
|
+
/**
|
|
43
|
+
* Сохранять и восстанавливать черновые данные формы по направлению (метаданные). Для черновика — `false`.
|
|
44
|
+
* Работает только если предоставлен токен {@link SC_ORDER_FORM_CONFIG}.
|
|
45
|
+
*/
|
|
46
|
+
this.persistMetadata = input(true);
|
|
47
|
+
/**
|
|
48
|
+
* Событие отправки валидной формы оформления. Полезная нагрузка — сырые значения формы.
|
|
49
|
+
*/
|
|
50
|
+
this.orderSubmit = output();
|
|
51
|
+
/**
|
|
52
|
+
* Сервис справочников.
|
|
53
|
+
*/
|
|
54
|
+
this.referencesService = inject(ScReferencesService);
|
|
55
|
+
/**
|
|
56
|
+
* Сервис работы с контрагентами.
|
|
57
|
+
*/
|
|
58
|
+
this.contragentService = inject(ScContragentService);
|
|
59
|
+
/**
|
|
60
|
+
* Сервис работы с адресами доставки.
|
|
61
|
+
*/
|
|
62
|
+
this.deliveryAddressService = inject(ScDeliveryAddressService);
|
|
63
|
+
/**
|
|
64
|
+
* Сервис для работы со складами.
|
|
65
|
+
*/
|
|
66
|
+
this.warehouseService = inject(ScWarehouseService);
|
|
67
|
+
/**
|
|
68
|
+
* Сервис для работы с заказами (загрузка дат доставки/самовывоза).
|
|
69
|
+
*/
|
|
70
|
+
this.ordersService = inject(ScOrdersService);
|
|
71
|
+
/**
|
|
72
|
+
* Сервис для работы с UI.
|
|
73
|
+
*/
|
|
74
|
+
this.uiService = inject(ScUIService);
|
|
75
|
+
/**
|
|
76
|
+
* Сервис конвертации данных.
|
|
77
|
+
*/
|
|
78
|
+
this.convertersService = inject(ScConvertersService);
|
|
79
|
+
/**
|
|
80
|
+
* Сервис работы с диалоговым окном.
|
|
81
|
+
*/
|
|
82
|
+
this.dialog = inject(TuiDialogService);
|
|
83
|
+
/**
|
|
84
|
+
* Провайдер данных о терминале.
|
|
85
|
+
*/
|
|
86
|
+
this.terminal = inject(IS_RUNNING_ON_TERMINAL);
|
|
87
|
+
/**
|
|
88
|
+
* Поток данных о текущем пользователе.
|
|
89
|
+
*/
|
|
90
|
+
this.user$ = inject(SC_USER_INFO);
|
|
91
|
+
/**
|
|
92
|
+
* Настройки формы оформления заказа. Если не предоставлены, метаданные формы не сохраняются.
|
|
93
|
+
*/
|
|
94
|
+
this.config = inject(SC_ORDER_FORM_CONFIG, { optional: true });
|
|
95
|
+
/**
|
|
96
|
+
* Признак выполнения скрипта на сервере.
|
|
97
|
+
*/
|
|
98
|
+
this.isServer = inject(IS_SERVER);
|
|
99
|
+
/**
|
|
100
|
+
* Ссылка для автоматического управления уничтожением зависимостей.
|
|
101
|
+
*/
|
|
102
|
+
this.destroyRef = inject(DestroyRef);
|
|
103
|
+
/**
|
|
104
|
+
* Задержка считывания сигналов формы, для избежания лишних обработок при смене значений.
|
|
105
|
+
*/
|
|
106
|
+
this.debounceTimeFormChange = 50;
|
|
107
|
+
/**
|
|
108
|
+
* Форма создания заказа.
|
|
109
|
+
*/
|
|
110
|
+
this.form = new FormGroup({
|
|
111
|
+
contragentId: new FormControl(null, Validators.required),
|
|
112
|
+
paymentType: new FormControl({ value: null, disabled: true }, Validators.required),
|
|
113
|
+
deliveryType: new FormControl({ value: null, disabled: true }, Validators.required),
|
|
114
|
+
deliveryDate: new FormControl({ value: null, disabled: true }, [
|
|
115
|
+
Validators.required,
|
|
116
|
+
({ value }) => {
|
|
117
|
+
if (!value || this.deliveryDates().length === 0) {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
if (value && !this.deliveryDates().includes(value)) {
|
|
121
|
+
return { serverResponse: 'Укажите корректную дату, или выберите из активных дат календаря' };
|
|
122
|
+
}
|
|
123
|
+
return null;
|
|
124
|
+
},
|
|
125
|
+
]),
|
|
126
|
+
warehouseId: new FormControl({ value: null, disabled: true }, Validators.required),
|
|
127
|
+
addressId: new FormControl({ value: null, disabled: true }, Validators.required),
|
|
128
|
+
comment: new FormControl(null),
|
|
129
|
+
image: new FormControl(null),
|
|
130
|
+
});
|
|
131
|
+
/**
|
|
132
|
+
* Поле файла.
|
|
133
|
+
*/
|
|
134
|
+
this.controlFile = new FormControl(null);
|
|
135
|
+
/**
|
|
136
|
+
* {@link Observable} списка подтверждённых файлов.
|
|
137
|
+
*/
|
|
138
|
+
this.accepted$ = this.controlFile.valueChanges.pipe(map(() => tuiFilesAccepted(this.controlFile)));
|
|
139
|
+
/**
|
|
140
|
+
* Признак, что включён режим анимации предупреждения о неподтверждённых данных.
|
|
141
|
+
*/
|
|
142
|
+
this.warningShake = signal(false);
|
|
143
|
+
/**
|
|
144
|
+
* Признак, что контрагент является физическим лицом.
|
|
145
|
+
*/
|
|
146
|
+
this.isIndividual = signal(true);
|
|
147
|
+
/**
|
|
148
|
+
* Список возможных дат самовывоза со склада.
|
|
149
|
+
*/
|
|
150
|
+
this.warehouseDeliveryDates = signal([]);
|
|
151
|
+
/**
|
|
152
|
+
* Список возможных дат доставки.
|
|
153
|
+
*/
|
|
154
|
+
this.addressDeliveryDates = signal([]);
|
|
155
|
+
/**
|
|
156
|
+
* {@link Observable} списка контрагентов пользователя.
|
|
157
|
+
*/
|
|
158
|
+
this.contragents$ = this.contragentService.contragents$;
|
|
159
|
+
/**
|
|
160
|
+
* {@link Observable} списка адресов контрагента.
|
|
161
|
+
*/
|
|
162
|
+
this.addresses$ = this.deliveryAddressService.deliveryAddresses$.pipe(tap((deliveryAddresses) => {
|
|
163
|
+
if (deliveryAddresses && this.form.controls.addressId.value && !deliveryAddresses.some((delivery) => delivery.id === this.form.controls.addressId.value)) {
|
|
164
|
+
this.form.controls.addressId.reset();
|
|
165
|
+
}
|
|
166
|
+
}));
|
|
167
|
+
/**
|
|
168
|
+
* {@link Observable} списка складов.
|
|
169
|
+
*/
|
|
170
|
+
this.warehouses$ = this.warehouseService.getWarehouses$();
|
|
171
|
+
/**
|
|
172
|
+
* {@link Observable} ОПФ выбранного контрагента.
|
|
173
|
+
*/
|
|
174
|
+
this.opf$ = tuiControlValue(this.form.controls.contragentId).pipe(filter(tuiIsPresent), tap(() => {
|
|
175
|
+
this.form.controls.paymentType.enable();
|
|
176
|
+
this.form.controls.deliveryType.enable();
|
|
177
|
+
}), switchMap((selectContragentId) => this.contragents$.pipe(filter(tuiIsPresent), map((contragents) => contragents.find((contragent) => contragent.id === selectContragentId)), map((contragent) => contragent?.opf), tap((opf) => {
|
|
178
|
+
this.isIndividual.set(opf?.id === ScOpfList.individual.valueOf());
|
|
179
|
+
}))), shareReplay(1), takeUntilDestroyed(this.destroyRef));
|
|
180
|
+
/**
|
|
181
|
+
* {@link Observable} типов оплаты заказа.
|
|
182
|
+
*/
|
|
183
|
+
this.paymentTypes$ = this.opf$.pipe(map((opf) => opf && (opf.id === ScOpfList.individual ? ScPaymentType.beznal2 : ScPaymentType.online)), switchMap((paymentTypeFilter) => this.referencesService.paymentTypes$.pipe(map((paymentTypes) => (paymentTypeFilter ? paymentTypes : [])), map((paymentTypes) => paymentTypes.filter((type) => type.id !== paymentTypeFilter)), tap((paymentTypes) => {
|
|
184
|
+
if (this.form.controls.paymentType.value && !paymentTypes.some((payment) => payment.id === this.form.controls.paymentType.value)) {
|
|
185
|
+
this.form.controls.paymentType.reset();
|
|
186
|
+
}
|
|
187
|
+
if (!this.form.controls.paymentType.value && paymentTypes.length === 1) {
|
|
188
|
+
this.form.controls.paymentType.patchValue(paymentTypes[0].id);
|
|
189
|
+
}
|
|
190
|
+
}))));
|
|
191
|
+
/**
|
|
192
|
+
* {@link Observable} типов доставки заказа.
|
|
193
|
+
*/
|
|
194
|
+
this.deliveryTypes$ = this.opf$.pipe(switchMap((opf) => this.referencesService.deliveryTypes$.pipe(map((deliveryTypes) => (opf ? deliveryTypes : [])), switchMap((deliveryTypes) => this.deliveryAddressService.deliveryAddresses$.pipe(map((deliveryAddresses) => opf?.id === ScOpfList.individual && !(deliveryAddresses && deliveryAddresses.length > 0)
|
|
195
|
+
? deliveryTypes.filter((type) => type.id !== ScDeliveryType.delivery)
|
|
196
|
+
: deliveryTypes))), tap((deliveryTypes) => {
|
|
197
|
+
if (this.form.controls.deliveryType.value && !deliveryTypes.some((delivery) => delivery.id === this.form.controls.deliveryType.value)) {
|
|
198
|
+
this.form.controls.deliveryType.reset();
|
|
199
|
+
}
|
|
200
|
+
if (!this.form.controls.deliveryType.value && deliveryTypes.length === 1) {
|
|
201
|
+
this.form.controls.deliveryType.patchValue(deliveryTypes[0].id);
|
|
202
|
+
}
|
|
203
|
+
}))));
|
|
204
|
+
/**
|
|
205
|
+
* Признак, что выбран тип оплаты наличными.
|
|
206
|
+
*/
|
|
207
|
+
this.isCashPaymentSelected = toSignal(tuiControlValue(this.form.controls.paymentType).pipe(map((paymentType) => paymentType === ScPaymentType.nal)), { initialValue: false });
|
|
208
|
+
/**
|
|
209
|
+
* Признак, что номер телефона подтверждён.
|
|
210
|
+
*/
|
|
211
|
+
this.isPhoneApproved = toSignal(this.user$.pipe(filter((user) => !user.isGuest), map((user) => user.contacts.phone.isApproved)), { initialValue: true });
|
|
212
|
+
/**
|
|
213
|
+
* Признак, что адрес электронной почты подтверждён пользователем.
|
|
214
|
+
*/
|
|
215
|
+
this.isEmailApprovedUser = toSignal(this.user$.pipe(filter((user) => !user.isGuest), map((user) => user.contacts.email.isApproved)), { initialValue: true });
|
|
216
|
+
/**
|
|
217
|
+
* Признак, что адрес электронной почты подтверждён или контрагент является физическим лицом.
|
|
218
|
+
*/
|
|
219
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
220
|
+
this.isEmailApproved = computed(() => this.isEmailApprovedUser() || this.isIndividual());
|
|
221
|
+
/**
|
|
222
|
+
* Значение выбранного типа доставки.
|
|
223
|
+
*/
|
|
224
|
+
this.deliveryTypeValue = toSignal(tuiControlValue(this.form.controls.deliveryType), { initialValue: null });
|
|
225
|
+
/**
|
|
226
|
+
* Признак, что выбран тип доставки "Доставка".
|
|
227
|
+
*/
|
|
228
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
229
|
+
this.isDelivery = computed(() => this.deliveryTypeValue() === ScDeliveryType.delivery);
|
|
230
|
+
/**
|
|
231
|
+
* Набор доступных дат в зависимости от типа доставки.
|
|
232
|
+
*/
|
|
233
|
+
// eslint-disable-next-line unicorn/consistent-function-scoping
|
|
234
|
+
this.deliveryDates = computed(() => this.deliveryTypeValue() === ScDeliveryType.self_delivery ? this.warehouseDeliveryDates() : this.addressDeliveryDates());
|
|
235
|
+
/**
|
|
236
|
+
* Ссылка на элемент с предупреждением о неподтверждённых данных.
|
|
237
|
+
*/
|
|
238
|
+
this.unconfirmedDataWarning = viewChild('unconfirmedDataWarning');
|
|
239
|
+
/**
|
|
240
|
+
* Возвращает признак, что указанная дата недоступна для выбора.
|
|
241
|
+
*
|
|
242
|
+
* @param date Дата.
|
|
243
|
+
*/
|
|
244
|
+
this.deliveryDateFilter = (date) => !this.deliveryDates().includes(`${date.toString('YMD', '-')} 00:00:00`);
|
|
245
|
+
// Автоматически выбираем единственного контрагента-физлицо.
|
|
246
|
+
this.contragents$
|
|
247
|
+
.pipe(filter((contragents) => !!contragents && contragents.length === 1), first(), filter(([contragent]) => contragent.opf.id === ScOpfList.individual.valueOf()), takeUntilDestroyed(this.destroyRef))
|
|
248
|
+
.subscribe(([contragent]) => {
|
|
249
|
+
this.form.controls.contragentId?.patchValue(contragent.id);
|
|
250
|
+
});
|
|
251
|
+
this.initFormChanges();
|
|
252
|
+
}
|
|
253
|
+
/** @inheritdoc */
|
|
254
|
+
ngOnInit() {
|
|
255
|
+
// Восстанавливаем и сохраняем черновые данные формы по направлению.
|
|
256
|
+
if (this.persistMetadata()) {
|
|
257
|
+
this.initMetadata();
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Преобразует объекты в значения, отображаемое в поле ввода.
|
|
262
|
+
*
|
|
263
|
+
* @param items Выбранные объекты выпадающего списка.
|
|
264
|
+
*/
|
|
265
|
+
// eslint-disable-next-line class-methods-use-this
|
|
266
|
+
stringify(items) {
|
|
267
|
+
const itemsMap = new Map(items.map((item) => {
|
|
268
|
+
// eslint-disable-next-line unicorn/no-nested-ternary,sonarjs/no-nested-conditional
|
|
269
|
+
const name = 'name' in item ? item.name : 'address' in item ? item.address : '';
|
|
270
|
+
return [item.id, name];
|
|
271
|
+
}));
|
|
272
|
+
return ({ $implicit }) => itemsMap.get($implicit) ?? '';
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Обрабатывает отправку формы: валидирует и эмитит данные заказа родителю.
|
|
276
|
+
*/
|
|
277
|
+
submit() {
|
|
278
|
+
this.form.markAllAsTouched();
|
|
279
|
+
if (!this.form.valid) {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
const contactsApproved = !this.enforceApprovedContacts() || (this.isPhoneApproved() && this.isEmailApproved());
|
|
283
|
+
if (!contactsApproved) {
|
|
284
|
+
this.triggerUnconfirmedWarning();
|
|
285
|
+
return;
|
|
286
|
+
}
|
|
287
|
+
this.orderSubmit.emit(this.form.getRawValue());
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Применяет к полям формы ошибки, пришедшие от сервера.
|
|
291
|
+
*
|
|
292
|
+
* @param error Ответ сервера с ошибками.
|
|
293
|
+
*/
|
|
294
|
+
applyServerErrors(error) {
|
|
295
|
+
const { errors, message } = error.error;
|
|
296
|
+
if (errors) {
|
|
297
|
+
Object.keys(errors).forEach((key) => {
|
|
298
|
+
if (key === 'deliveryDate' && isArray(errors[key])) {
|
|
299
|
+
this.form.get(key)?.setErrors({ serverResponse: new TuiValidationError(errors[key].at(1) ?? errors[key].at(0)) });
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
this.form.get(key)?.setErrors({ serverResponse: new TuiValidationError(errors[key]) });
|
|
303
|
+
}
|
|
304
|
+
this.form.get(key)?.markAsTouched();
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
else if (message) {
|
|
308
|
+
this.form.setErrors({ serverResponse: new TuiValidationError(message) });
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Удаляет файл из формы заказа.
|
|
313
|
+
*/
|
|
314
|
+
removeFile() {
|
|
315
|
+
this.controlFile.reset();
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Открывает диалоговое окно добавления адреса доставки.
|
|
319
|
+
*/
|
|
320
|
+
addDeliveryAddress() {
|
|
321
|
+
this.dialog
|
|
322
|
+
.open(new PolymorpheusComponent(ScAddDeliveryAddressDialogComponent), {
|
|
323
|
+
size: 'l',
|
|
324
|
+
label: 'Добавление адреса доставки',
|
|
325
|
+
})
|
|
326
|
+
.subscribe();
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Открывает диалоговое окно добавления контрагента.
|
|
330
|
+
*/
|
|
331
|
+
addContragent() {
|
|
332
|
+
this.dialog
|
|
333
|
+
.open(new PolymorpheusComponent(ScAddContragentDialogComponent), {
|
|
334
|
+
size: 'm',
|
|
335
|
+
label: 'Добавление контрагента',
|
|
336
|
+
})
|
|
337
|
+
.subscribe();
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Запускает анимацию предупреждения о неподтверждённых данных и прокручивает к нему.
|
|
341
|
+
*/
|
|
342
|
+
triggerUnconfirmedWarning() {
|
|
343
|
+
const element = this.unconfirmedDataWarning()?.nativeElement;
|
|
344
|
+
if (!this.isServer && element) {
|
|
345
|
+
element.scrollIntoView({ behavior: 'smooth', block: 'center' });
|
|
346
|
+
}
|
|
347
|
+
this.warningShake.set(false);
|
|
348
|
+
setTimeout(() => {
|
|
349
|
+
this.warningShake.set(true);
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Восстанавливает черновые данные формы из метаданных и инициализирует их сохранение.
|
|
354
|
+
*/
|
|
355
|
+
initMetadata() {
|
|
356
|
+
const { config } = this;
|
|
357
|
+
if (!config) {
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
combineLatest({
|
|
361
|
+
orderMetadata: this.uiService.getNewOrderMetadata$(this.directionId()),
|
|
362
|
+
user: this.user$.pipe(filter((user) => !user.isGuest)),
|
|
363
|
+
})
|
|
364
|
+
.pipe(first(), takeUntilDestroyed(this.destroyRef))
|
|
365
|
+
// eslint-disable-next-line sonarjs/cognitive-complexity
|
|
366
|
+
.subscribe(({ orderMetadata }) => {
|
|
367
|
+
let deliveryDate = orderMetadata?.deliveryDate && isValid(parse(orderMetadata.deliveryDate, config.dateFormats.api, new Date())) ? orderMetadata.deliveryDate : null;
|
|
368
|
+
// Если дата старого формата, то преобразуем её в новый формат.
|
|
369
|
+
// TODO: Убрать этот блок когда все даты у клиентов встанут в нормальном формате.
|
|
370
|
+
if (orderMetadata?.deliveryDate && !deliveryDate && isValid(parse(orderMetadata.deliveryDate, config.dateFormats.uiDate, new Date()))) {
|
|
371
|
+
deliveryDate = format(parse(orderMetadata.deliveryDate, config.dateFormats.uiDate, new Date()), config.dateFormats.api);
|
|
372
|
+
}
|
|
373
|
+
if (tuiIsPresent(orderMetadata)) {
|
|
374
|
+
this.form.patchValue({
|
|
375
|
+
contragentId: orderMetadata.contragentId,
|
|
376
|
+
paymentType: orderMetadata.contragentId ? orderMetadata.paymentType : null,
|
|
377
|
+
deliveryType: orderMetadata.contragentId ? orderMetadata.deliveryType : null,
|
|
378
|
+
deliveryDate: orderMetadata.contragentId && Boolean(orderMetadata.deliveryType) && deliveryDate ? deliveryDate : null,
|
|
379
|
+
addressId: orderMetadata.deliveryType === ScDeliveryType.delivery && orderMetadata.addressId ? orderMetadata.addressId : null,
|
|
380
|
+
warehouseId: orderMetadata.contragentId && Boolean(orderMetadata.deliveryType) ? orderMetadata.warehouseId : null,
|
|
381
|
+
comment: orderMetadata.comment,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
this.form.valueChanges.pipe(debounceTime(config.debounceTime), takeUntilDestroyed(this.destroyRef)).subscribe((newOrder) => {
|
|
386
|
+
this.uiService.setNewOrderMetadata(this.directionId(), this.convertersService.removeNull(newOrder));
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Инициализирует подписки на изменения полей формы.
|
|
391
|
+
*/
|
|
392
|
+
initFormChanges() {
|
|
393
|
+
this.initFileChange();
|
|
394
|
+
this.initWarehouseChange();
|
|
395
|
+
this.initDeliveryDatesChange();
|
|
396
|
+
this.initDateFieldActivationChange();
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Инициализирует подписку на изменение поля прикрепления файла.
|
|
400
|
+
*/
|
|
401
|
+
initFileChange() {
|
|
402
|
+
this.controlFile.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe((file) => {
|
|
403
|
+
if (file && this.form.controls.image) {
|
|
404
|
+
this.onUploadFile(file, this.form.controls.image);
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
this.form.controls.image?.reset();
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Инициализирует подписку на изменение выбранного склада.
|
|
413
|
+
*/
|
|
414
|
+
initWarehouseChange() {
|
|
415
|
+
this.form.controls.warehouseId.valueChanges
|
|
416
|
+
.pipe(filter((warehouseId) => tuiIsPresent(warehouseId) && this.warehouseService.getCurrentWarehouseIdSelect() !== warehouseId), debounceTime(0), takeUntilDestroyed(this.destroyRef))
|
|
417
|
+
.subscribe((id) => {
|
|
418
|
+
this.warehouseService.setWarehouseIdSelectChange(id);
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Инициализирует подписку на изменение адреса доставки и выбранного склада для получения списка доступных дат доставки.
|
|
423
|
+
*/
|
|
424
|
+
initDeliveryDatesChange() {
|
|
425
|
+
merge(tuiControlValue(this.form.controls.addressId).pipe(filter(tuiIsPresent), debounceTime(this.debounceTimeFormChange), switchMap((addressId) => this.deliveriesByAddress(addressId))), tuiControlValue(this.form.controls.warehouseId).pipe(filter(tuiIsPresent), debounceTime(this.debounceTimeFormChange), filter(() => this.form.controls.deliveryType.value === ScDeliveryType.self_delivery), switchMap((warehouseId) => this.deliveriesByWarehouse(warehouseId))))
|
|
426
|
+
.pipe(catchError((error) => {
|
|
427
|
+
this.form.controls.deliveryDate.disable();
|
|
428
|
+
return throwError(() => error);
|
|
429
|
+
}), retry(), takeUntilDestroyed(this.destroyRef))
|
|
430
|
+
.subscribe((deliveryDates) => {
|
|
431
|
+
const deliveryDateValue = this.form.controls.deliveryDate.value;
|
|
432
|
+
if (deliveryDateValue && !deliveryDates.includes(deliveryDateValue)) {
|
|
433
|
+
this.form.controls.deliveryDate.reset();
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Инициализирует подписку на изменение полей формы для блокирования/активации поля выбора даты.
|
|
439
|
+
*/
|
|
440
|
+
initDateFieldActivationChange() {
|
|
441
|
+
merge(tuiControlValue(this.form.controls.deliveryType), this.form.controls.contragentId?.valueChanges.pipe(filter(() => this.form.controls.deliveryType.value === ScDeliveryType.delivery)) ?? of())
|
|
442
|
+
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
443
|
+
.subscribe(() => {
|
|
444
|
+
this.form.controls.deliveryDate.disable();
|
|
445
|
+
this.form.controls.warehouseId.disable();
|
|
446
|
+
this.addressDeliveryDates.set([]);
|
|
447
|
+
if (this.form.controls.deliveryType.value === ScDeliveryType.delivery) {
|
|
448
|
+
this.form.controls.addressId.enable();
|
|
449
|
+
this.warehouseService
|
|
450
|
+
.getDeliveryWarehouse$()
|
|
451
|
+
.pipe(first(), takeUntilDestroyed(this.destroyRef))
|
|
452
|
+
// eslint-disable-next-line rxjs/no-nested-subscribe
|
|
453
|
+
.subscribe((warehouse) => {
|
|
454
|
+
this.form.controls.warehouseId.patchValue(warehouse.id);
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
if (this.form.controls.deliveryType.value === ScDeliveryType.self_delivery) {
|
|
458
|
+
this.form.controls.addressId.disable();
|
|
459
|
+
this.form.controls.warehouseId.enable();
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Запрашивает даты доставки по адресу.
|
|
465
|
+
*
|
|
466
|
+
* @param addressId Идентификатор адреса доставки.
|
|
467
|
+
*/
|
|
468
|
+
deliveriesByAddress(addressId) {
|
|
469
|
+
return this.ordersService.getDeliveriesData$(addressId).pipe(catchError((error) => {
|
|
470
|
+
const message = error instanceof HttpErrorResponse ? error.error.message : undefined;
|
|
471
|
+
this.form.controls.addressId.setErrors({
|
|
472
|
+
serverResponse: message ?? `Ошибка сервера: пожалуйста, перезагрузите страницу и/или выполните запрос позже.`,
|
|
473
|
+
});
|
|
474
|
+
this.addressDeliveryDates.set([]);
|
|
475
|
+
return throwError(() => error);
|
|
476
|
+
}), tap((deliveryDates) => {
|
|
477
|
+
this.addressDeliveryDates.set(deliveryDates);
|
|
478
|
+
this.form.controls.deliveryDate.enable();
|
|
479
|
+
}));
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Запрашивает даты самовывоза по складу.
|
|
483
|
+
*
|
|
484
|
+
* @param warehouseId Идентификатор склада.
|
|
485
|
+
*/
|
|
486
|
+
deliveriesByWarehouse(warehouseId) {
|
|
487
|
+
return this.ordersService.getSelfDeliveriesData$(warehouseId).pipe(catchError((error) => {
|
|
488
|
+
const message = error instanceof HttpErrorResponse ? error.error.message : undefined;
|
|
489
|
+
this.form.controls.warehouseId.setErrors({
|
|
490
|
+
serverResponse: message ?? `Ошибка сервера: пожалуйста, перезагрузите страницу и/или выполните запрос позже.`,
|
|
491
|
+
});
|
|
492
|
+
this.warehouseDeliveryDates.set([]);
|
|
493
|
+
return throwError(() => error);
|
|
494
|
+
}), tap((deliveryDates) => {
|
|
495
|
+
this.warehouseDeliveryDates.set(deliveryDates);
|
|
496
|
+
this.form.controls.deliveryDate.enable();
|
|
497
|
+
}));
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Загружает файл в форму.
|
|
501
|
+
*
|
|
502
|
+
* @param file Файл.
|
|
503
|
+
* @param filesControl Поле файла заказа.
|
|
504
|
+
*/
|
|
505
|
+
// eslint-disable-next-line class-methods-use-this
|
|
506
|
+
onUploadFile(file, filesControl) {
|
|
507
|
+
const reader = new FileReader();
|
|
508
|
+
reader.addEventListener('load', () => {
|
|
509
|
+
const { result } = reader;
|
|
510
|
+
if (isString(result)) {
|
|
511
|
+
filesControl.setValue(new ScUploadedFile(file.name, result));
|
|
512
|
+
}
|
|
513
|
+
});
|
|
514
|
+
reader.readAsDataURL(file);
|
|
515
|
+
}
|
|
516
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScOrderFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
517
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScOrderFormComponent, isStandalone: true, selector: "sc-order-form", inputs: { directionId: { classPropertyName: "directionId", publicName: "directionId", isSignal: true, isRequired: true, transformFunction: null }, enforceApprovedContacts: { classPropertyName: "enforceApprovedContacts", publicName: "enforceApprovedContacts", isSignal: true, isRequired: false, transformFunction: null }, persistMetadata: { classPropertyName: "persistMetadata", publicName: "persistMetadata", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { orderSubmit: "orderSubmit" }, providers: [TERMINAL_PROVIDERS], viewQueries: [{ propertyName: "unconfirmedDataWarning", first: true, predicate: ["unconfirmedDataWarning"], descendants: true, isSignal: true }], ngImport: i0, template: "@let user = user$ | async;\n\n<form\n [formGroup]=\"form\"\n scFocusFirstInvalidField\n [fieldOrder]=\"['contragentId', 'paymentType', 'deliveryType', 'warehouseId', 'addressId', 'deliveryDate', 'comment']\"\n (ngSubmit)=\"submit()\"\n class=\"flex flex-col gap-4\"\n>\n <ng-template #selectLoading> <tui-loader /> </ng-template>\n\n <!-- \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442. -->\n @if (contragents$ | async; as contragents) {\n @if (contragents.length > 1 || user?.isOrg) {\n <label tuiLabel>\n \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\n <tui-select\n formControlName=\"contragentId\"\n [valueContent]=\"contragents ? stringify(contragents) : selectLoading\"\n >\n \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\n <tui-data-list *tuiDataList>\n @for (contragent of contragents; track contragent.id) {\n <button\n tuiOption\n [value]=\"contragent.id\"\n >\n {{ contragent.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"contragentId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n <a\n tuiLink\n iconStart=\"@tui.plus\"\n (click)=\"addContragent()\"\n class=\"mt-2 block\"\n >\n \u041D\u043E\u0432\u044B\u0439\n </a>\n </label>\n }\n }\n\n <!-- \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B. -->\n <label tuiLabel>\n \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\n @let paymentTypes = paymentTypes$ | async;\n <tui-select\n formControlName=\"paymentType\"\n [valueContent]=\"paymentTypes ? stringify(paymentTypes) : selectLoading\"\n >\n \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\n <tui-data-list *tuiDataList>\n @for (type of paymentTypes; track type.id) {\n <button\n tuiOption\n [value]=\"type.id\"\n >\n {{ type.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"paymentType\"\n [error]=\"[] | tuiFieldError | async\"\n />\n @if (isCashPaymentSelected()) {\n <p class=\"text-xs text-tui-status-positive\">\u0417\u0430\u043A\u0430\u0437\u044B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u044F\u0442\u0441\u044F \u043F\u043E \u043F\u0440\u0435\u0434\u043E\u043F\u043B\u0430\u0442\u0435</p>\n }\n </label>\n\n <!-- \u041F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435 \u043E \u043D\u0435\u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D\u043D\u044B\u0445 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u043D\u044B\u0445 \u0434\u0430\u043D\u043D\u044B\u0445. -->\n @if (!isPhoneApproved() || !isEmailApproved()) {\n <div\n #unconfirmedDataWarning\n class=\"text-tui-text-negative\"\n [class.warning-shake]=\"warningShake()\"\n >\n \u0412\u043D\u0438\u043C\u0430\u043D\u0438\u0435! \u0414\u043B\u044F \u043E\u0444\u043E\u0440\u043C\u043B\u0435\u043D\u0438\u044F \u0437\u0430\u043A\u0430\u0437\u0430 \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C\n @if (!isPhoneApproved()) {\n <span class=\"font-bold\"> \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430 </span>\n }\n @if (!isPhoneApproved() && !isEmailApproved()) {\n <span> \u0438 </span>\n }\n @if (!isEmailApproved()) {\n <span class=\"font-bold\"> \u0430\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B </span>\n }\n <a\n tuiLink\n routerLink=\"/profile\"\n >\n \u0432 \u0432\u0430\u0448\u0435\u043C \u043F\u0440\u043E\u0444\u0438\u043B\u0435\n </a>\n </div>\n }\n\n <!-- \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438. -->\n <label tuiLabel>\n \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n @let deliveryTypes = deliveryTypes$ | async;\n <tui-select\n formControlName=\"deliveryType\"\n [valueContent]=\"deliveryTypes ? stringify(deliveryTypes) : selectLoading\"\n >\n \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-data-list *tuiDataList>\n @for (delivery of deliveryTypes; track delivery.id) {\n <button\n tuiOption\n [value]=\"delivery.id\"\n >\n {{ delivery.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"deliveryType\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u0421\u043A\u043B\u0430\u0434. -->\n <label tuiLabel>\n \u0421\u043A\u043B\u0430\u0434\n @let warehouses = warehouses$ | async;\n <tui-select\n formControlName=\"warehouseId\"\n [valueContent]=\"warehouses ? stringify(warehouses) : selectLoading\"\n >\n \u0421\u043A\u043B\u0430\u0434\n <tui-data-list *tuiDataList>\n @if (!terminal.isRunningOnTerminal) {\n @for (warehouse of warehouses; track warehouse.id) {\n <button\n tuiOption\n [value]=\"warehouse.id\"\n >\n {{ warehouse.name }}\n </button>\n }\n } @else {\n @if (warehouseService.getCatalogWarehouseChange$() | async; as terminalWarehouse) {\n <button\n tuiOption\n [value]=\"terminalWarehouse.id\"\n >\n {{ terminalWarehouse.name }}\n </button>\n }\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"warehouseId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438. -->\n @if (isDelivery()) {\n @let addresses = addresses$ | async;\n <div>\n <label tuiLabel>\n \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-select\n formControlName=\"addressId\"\n [valueContent]=\"addresses ? stringify(addresses) : selectLoading\"\n >\n \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-data-list *tuiDataList>\n @for (address of addresses; track address.id) {\n <button\n tuiOption\n [value]=\"address.id\"\n >\n {{ address.address }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n @if (addresses && addresses.length === 0) {\n <tui-error error=\"\u0423 \u043A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\u0430 \u043D\u0435\u0442 \u0430\u0434\u0440\u0435\u0441\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\" />\n }\n <tui-error\n formControlName=\"addressId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <a\n tuiLink\n iconStart=\"@tui.plus\"\n (click)=\"addDeliveryAddress()\"\n class=\"mt-2 block\"\n >\n \u041D\u043E\u0432\u044B\u0439\n </a>\n </div>\n }\n\n <!-- \u0414\u0430\u0442\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438/\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430. -->\n <label tuiLabel>\n \u0416\u0435\u043B\u0430\u0435\u043C\u0430\u044F \u0434\u0430\u0442\u0430 {{ isDelivery() ? '\u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438' : '\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430' }}\n <tui-input-date\n formControlName=\"deliveryDate\"\n [disabledItemHandler]=\"deliveryDateFilter\"\n >\n \u0416\u0435\u043B\u0430\u0435\u043C\u0430\u044F \u0434\u0430\u0442\u0430 {{ isDelivery() ? '\u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438' : '\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430' }}\n </tui-input-date>\n <tui-error\n formControlName=\"deliveryDate\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043A\u043B\u0438\u0435\u043D\u0442\u0430. -->\n <label tuiLabel>\n \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043A\u043B\u0438\u0435\u043D\u0442\u0430 \u043A \u0437\u0430\u043A\u0430\u0437\u0443\n <tui-textarea\n formControlName=\"comment\"\n [expandable]=\"true\"\n [rows]=\"15\"\n >\n \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442\n </tui-textarea>\n <tui-error\n formControlName=\"comment\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u043B\u0435\u043D\u0438\u0435 \u0444\u0430\u0439\u043B\u0430 \u043A \u0437\u0430\u043A\u0430\u0437\u0443. -->\n <div>\n @if (!controlFile.value) {\n <label tuiInputFiles>\n <input\n accept=\"image/*\"\n tuiInputFiles\n [formControl]=\"controlFile\"\n />\n </label>\n }\n\n <tui-files class=\"tui-space_top-1\">\n @if (controlFile.value | tuiFileRejected: { accept: 'image/*' } | async; as file) {\n <tui-file\n state=\"error\"\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n }\n\n @for (file of accepted$ | async; track file.name) {\n <tui-file\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n }\n </tui-files>\n\n <tui-error\n [error]=\"['maxLength'] | tuiFieldError | async\"\n [formControl]=\"controlFile\"\n />\n <p class=\"tui-form__field-note\">\u041D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, \u0444\u043E\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u044E \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0439 \u0438 \u0434\u0435\u0444\u0444\u0435\u043A\u0442\u043E\u0432, \u0447\u0442\u043E \u043F\u043E\u0441\u043B\u0443\u0436\u0438\u0442 \u0434\u043E\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044C\u0441\u0442\u0432\u043E\u043C \u043D\u0435\u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044F \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u043E\u0433\u043E \u043A\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430.</p>\n </div>\n</form>\n", dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.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: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: TuiLoader, selector: "tui-loader", inputs: ["size", "inheritColor", "overlay", "textContent", "showLoader"] }, { kind: "directive", type: TuiLabel, selector: "label[tuiLabel]" }, { kind: "ngmodule", type: TuiSelectModule }, { kind: "component", type: i2.TuiSelectComponent, selector: "tui-select", inputs: ["stringify", "identityMatcher", "valueContent"] }, { kind: "directive", type: i2.TuiSelectDirective, selector: "tui-select" }, { kind: "component", type: i3.TuiDataListComponent, selector: "tui-data-list", inputs: ["emptyContent", "size"] }, { kind: "directive", type: i3.TuiDataListDirective, selector: "ng-template[tuiDataList]" }, { kind: "component", type: i3.TuiOption, selector: "button[tuiOption]:not([new]), a[tuiOption]:not([new]), label[tuiOption]:not([new])", inputs: ["disabled", "value"] }, { kind: "component", type: TuiError, selector: "tui-error", inputs: ["error"] }, { kind: "directive", type: TuiLink, selector: "a[tuiLink], button[tuiLink]", inputs: ["pseudo"] }, { kind: "ngmodule", type: TuiInputDateModule }, { kind: "component", type: i2.TuiInputDateComponent, selector: "tui-input-date:not([multiple])", inputs: ["min", "max", "disabledItemHandler", "markerHandler", "items", "defaultActiveYearMonth"] }, { kind: "directive", type: i2.TuiInputDateDirective, selector: "tui-input-date:not([multiple])" }, { kind: "ngmodule", type: TuiTextareaModule }, { kind: "component", type: i2.TuiTextareaComponent, selector: "tui-textarea", inputs: ["rows", "maxLength", "expandable"] }, { kind: "directive", type: i2.TuiTextareaDirective, selector: "tui-textarea" }, { kind: "component", type: TuiInputFiles, selector: "label[tuiInputFiles]" }, { kind: "directive", type: TuiInputFilesDirective, selector: "input[tuiInputFiles]", outputs: ["reject"] }, { kind: "component", type: TuiFilesComponent, selector: "tui-files", inputs: ["max", "expanded"], outputs: ["expandedChange"] }, { kind: "component", type: TuiFile, selector: "tui-file,a[tuiFile],button[tuiFile]", inputs: ["file", "state", "size", "showDelete", "showSize", "leftContent"], outputs: ["remove"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "pipe", type: TuiFieldErrorPipe, name: "tuiFieldError" }, { kind: "pipe", type: TuiFileRejectedPipe, name: "tuiFileRejected" }, { kind: "directive", type: ScFocusFirstInvalidFieldDirective, selector: "form[formGroup][scFocusFirstInvalidField]", inputs: ["fieldOrder"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
518
|
+
}
|
|
519
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScOrderFormComponent, decorators: [{
|
|
520
|
+
type: Component,
|
|
521
|
+
args: [{ standalone: true, selector: 'sc-order-form', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
|
|
522
|
+
FormsModule,
|
|
523
|
+
ReactiveFormsModule,
|
|
524
|
+
RouterLink,
|
|
525
|
+
TuiLoader,
|
|
526
|
+
TuiLabel,
|
|
527
|
+
TuiSelectModule,
|
|
528
|
+
TuiDataListDirective,
|
|
529
|
+
TuiDataListComponent,
|
|
530
|
+
TuiOption,
|
|
531
|
+
TuiError,
|
|
532
|
+
TuiLink,
|
|
533
|
+
TuiInputDateModule,
|
|
534
|
+
TuiTextareaModule,
|
|
535
|
+
TuiInputFiles,
|
|
536
|
+
TuiInputFilesDirective,
|
|
537
|
+
TuiFilesComponent,
|
|
538
|
+
TuiFile,
|
|
539
|
+
AsyncPipe,
|
|
540
|
+
TuiFieldErrorPipe,
|
|
541
|
+
TuiFileRejectedPipe,
|
|
542
|
+
ScFocusFirstInvalidFieldDirective,
|
|
543
|
+
], providers: [TERMINAL_PROVIDERS], template: "@let user = user$ | async;\n\n<form\n [formGroup]=\"form\"\n scFocusFirstInvalidField\n [fieldOrder]=\"['contragentId', 'paymentType', 'deliveryType', 'warehouseId', 'addressId', 'deliveryDate', 'comment']\"\n (ngSubmit)=\"submit()\"\n class=\"flex flex-col gap-4\"\n>\n <ng-template #selectLoading> <tui-loader /> </ng-template>\n\n <!-- \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442. -->\n @if (contragents$ | async; as contragents) {\n @if (contragents.length > 1 || user?.isOrg) {\n <label tuiLabel>\n \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\n <tui-select\n formControlName=\"contragentId\"\n [valueContent]=\"contragents ? stringify(contragents) : selectLoading\"\n >\n \u041A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\n <tui-data-list *tuiDataList>\n @for (contragent of contragents; track contragent.id) {\n <button\n tuiOption\n [value]=\"contragent.id\"\n >\n {{ contragent.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"contragentId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n <a\n tuiLink\n iconStart=\"@tui.plus\"\n (click)=\"addContragent()\"\n class=\"mt-2 block\"\n >\n \u041D\u043E\u0432\u044B\u0439\n </a>\n </label>\n }\n }\n\n <!-- \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B. -->\n <label tuiLabel>\n \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\n @let paymentTypes = paymentTypes$ | async;\n <tui-select\n formControlName=\"paymentType\"\n [valueContent]=\"paymentTypes ? stringify(paymentTypes) : selectLoading\"\n >\n \u0422\u0438\u043F \u043E\u043F\u043B\u0430\u0442\u044B\n <tui-data-list *tuiDataList>\n @for (type of paymentTypes; track type.id) {\n <button\n tuiOption\n [value]=\"type.id\"\n >\n {{ type.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"paymentType\"\n [error]=\"[] | tuiFieldError | async\"\n />\n @if (isCashPaymentSelected()) {\n <p class=\"text-xs text-tui-status-positive\">\u0417\u0430\u043A\u0430\u0437\u044B \u043F\u0440\u043E\u0438\u0437\u0432\u043E\u0434\u044F\u0442\u0441\u044F \u043F\u043E \u043F\u0440\u0435\u0434\u043E\u043F\u043B\u0430\u0442\u0435</p>\n }\n </label>\n\n <!-- \u041F\u0440\u0435\u0434\u0443\u043F\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0435 \u043E \u043D\u0435\u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0451\u043D\u043D\u044B\u0445 \u043A\u043E\u043D\u0442\u0430\u043A\u0442\u043D\u044B\u0445 \u0434\u0430\u043D\u043D\u044B\u0445. -->\n @if (!isPhoneApproved() || !isEmailApproved()) {\n <div\n #unconfirmedDataWarning\n class=\"text-tui-text-negative\"\n [class.warning-shake]=\"warningShake()\"\n >\n \u0412\u043D\u0438\u043C\u0430\u043D\u0438\u0435! \u0414\u043B\u044F \u043E\u0444\u043E\u0440\u043C\u043B\u0435\u043D\u0438\u044F \u0437\u0430\u043A\u0430\u0437\u0430 \u043D\u0435\u043E\u0431\u0445\u043E\u0434\u0438\u043C\u043E \u043F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C\n @if (!isPhoneApproved()) {\n <span class=\"font-bold\"> \u043D\u043E\u043C\u0435\u0440 \u0442\u0435\u043B\u0435\u0444\u043E\u043D\u0430 </span>\n }\n @if (!isPhoneApproved() && !isEmailApproved()) {\n <span> \u0438 </span>\n }\n @if (!isEmailApproved()) {\n <span class=\"font-bold\"> \u0430\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B </span>\n }\n <a\n tuiLink\n routerLink=\"/profile\"\n >\n \u0432 \u0432\u0430\u0448\u0435\u043C \u043F\u0440\u043E\u0444\u0438\u043B\u0435\n </a>\n </div>\n }\n\n <!-- \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438. -->\n <label tuiLabel>\n \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n @let deliveryTypes = deliveryTypes$ | async;\n <tui-select\n formControlName=\"deliveryType\"\n [valueContent]=\"deliveryTypes ? stringify(deliveryTypes) : selectLoading\"\n >\n \u0421\u043F\u043E\u0441\u043E\u0431 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-data-list *tuiDataList>\n @for (delivery of deliveryTypes; track delivery.id) {\n <button\n tuiOption\n [value]=\"delivery.id\"\n >\n {{ delivery.name }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"deliveryType\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u0421\u043A\u043B\u0430\u0434. -->\n <label tuiLabel>\n \u0421\u043A\u043B\u0430\u0434\n @let warehouses = warehouses$ | async;\n <tui-select\n formControlName=\"warehouseId\"\n [valueContent]=\"warehouses ? stringify(warehouses) : selectLoading\"\n >\n \u0421\u043A\u043B\u0430\u0434\n <tui-data-list *tuiDataList>\n @if (!terminal.isRunningOnTerminal) {\n @for (warehouse of warehouses; track warehouse.id) {\n <button\n tuiOption\n [value]=\"warehouse.id\"\n >\n {{ warehouse.name }}\n </button>\n }\n } @else {\n @if (warehouseService.getCatalogWarehouseChange$() | async; as terminalWarehouse) {\n <button\n tuiOption\n [value]=\"terminalWarehouse.id\"\n >\n {{ terminalWarehouse.name }}\n </button>\n }\n }\n </tui-data-list>\n </tui-select>\n <tui-error\n formControlName=\"warehouseId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438. -->\n @if (isDelivery()) {\n @let addresses = addresses$ | async;\n <div>\n <label tuiLabel>\n \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-select\n formControlName=\"addressId\"\n [valueContent]=\"addresses ? stringify(addresses) : selectLoading\"\n >\n \u0410\u0434\u0440\u0435\u0441 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\n <tui-data-list *tuiDataList>\n @for (address of addresses; track address.id) {\n <button\n tuiOption\n [value]=\"address.id\"\n >\n {{ address.address }}\n </button>\n }\n </tui-data-list>\n </tui-select>\n @if (addresses && addresses.length === 0) {\n <tui-error error=\"\u0423 \u043A\u043E\u043D\u0442\u0440\u0430\u0433\u0435\u043D\u0442\u0430 \u043D\u0435\u0442 \u0430\u0434\u0440\u0435\u0441\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438\" />\n }\n <tui-error\n formControlName=\"addressId\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n <a\n tuiLink\n iconStart=\"@tui.plus\"\n (click)=\"addDeliveryAddress()\"\n class=\"mt-2 block\"\n >\n \u041D\u043E\u0432\u044B\u0439\n </a>\n </div>\n }\n\n <!-- \u0414\u0430\u0442\u0430 \u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438/\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430. -->\n <label tuiLabel>\n \u0416\u0435\u043B\u0430\u0435\u043C\u0430\u044F \u0434\u0430\u0442\u0430 {{ isDelivery() ? '\u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438' : '\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430' }}\n <tui-input-date\n formControlName=\"deliveryDate\"\n [disabledItemHandler]=\"deliveryDateFilter\"\n >\n \u0416\u0435\u043B\u0430\u0435\u043C\u0430\u044F \u0434\u0430\u0442\u0430 {{ isDelivery() ? '\u0434\u043E\u0441\u0442\u0430\u0432\u043A\u0438' : '\u0441\u0430\u043C\u043E\u0432\u044B\u0432\u043E\u0437\u0430' }}\n </tui-input-date>\n <tui-error\n formControlName=\"deliveryDate\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043A\u043B\u0438\u0435\u043D\u0442\u0430. -->\n <label tuiLabel>\n \u041A\u043E\u043C\u043C\u0435\u043D\u0442\u0430\u0440\u0438\u0439 \u043A\u043B\u0438\u0435\u043D\u0442\u0430 \u043A \u0437\u0430\u043A\u0430\u0437\u0443\n <tui-textarea\n formControlName=\"comment\"\n [expandable]=\"true\"\n [rows]=\"15\"\n >\n \u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0442\u0435\u043A\u0441\u0442\n </tui-textarea>\n <tui-error\n formControlName=\"comment\"\n [error]=\"[] | tuiFieldError | async\"\n />\n </label>\n\n <!-- \u041F\u0440\u0438\u043A\u0440\u0435\u043F\u043B\u0435\u043D\u0438\u0435 \u0444\u0430\u0439\u043B\u0430 \u043A \u0437\u0430\u043A\u0430\u0437\u0443. -->\n <div>\n @if (!controlFile.value) {\n <label tuiInputFiles>\n <input\n accept=\"image/*\"\n tuiInputFiles\n [formControl]=\"controlFile\"\n />\n </label>\n }\n\n <tui-files class=\"tui-space_top-1\">\n @if (controlFile.value | tuiFileRejected: { accept: 'image/*' } | async; as file) {\n <tui-file\n state=\"error\"\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n }\n\n @for (file of accepted$ | async; track file.name) {\n <tui-file\n [file]=\"file\"\n (remove)=\"removeFile()\"\n />\n }\n </tui-files>\n\n <tui-error\n [error]=\"['maxLength'] | tuiFieldError | async\"\n [formControl]=\"controlFile\"\n />\n <p class=\"tui-form__field-note\">\u041D\u0430\u043F\u0440\u0438\u043C\u0435\u0440, \u0444\u043E\u0442\u043E\u0433\u0440\u0430\u0444\u0438\u044E \u043F\u043E\u0432\u0440\u0435\u0436\u0434\u0435\u043D\u0438\u0439 \u0438 \u0434\u0435\u0444\u0444\u0435\u043A\u0442\u043E\u0432, \u0447\u0442\u043E \u043F\u043E\u0441\u043B\u0443\u0436\u0438\u0442 \u0434\u043E\u043A\u0430\u0437\u0430\u0442\u0435\u043B\u044C\u0441\u0442\u0432\u043E\u043C \u043D\u0435\u0441\u043E\u043E\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044F \u0437\u0430\u044F\u0432\u043B\u0435\u043D\u043D\u043E\u0433\u043E \u043A\u0430\u0447\u0435\u0441\u0442\u0432\u0430 \u0442\u043E\u0432\u0430\u0440\u0430.</p>\n </div>\n</form>\n" }]
|
|
544
|
+
}], ctorParameters: () => [] });
|
|
545
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Mtb3JkZXItZm9ybS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jbGllbnQtdWkvb3JkZXIvb3JkZXItZm9ybS9zYy1vcmRlci1mb3JtLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NsaWVudC11aS9vcmRlci9vcmRlci1mb3JtL3NjLW9yZGVyLWZvcm0uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsNFZBQTRWO0FBRTVWLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM1QyxPQUFPLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxVQUFVLEVBQWMsTUFBTSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQVUsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUMvSixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsUUFBUSxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDMUUsT0FBTyxFQUFtQixXQUFXLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxtQkFBbUIsRUFBb0IsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDekksT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQzdDLE9BQU8sRUFDSCxzQkFBc0IsRUFDdEIsU0FBUyxFQUNULFlBQVksRUFFWixtQkFBbUIsRUFDbkIsbUJBQW1CLEVBQ25CLHdCQUF3QixFQUN4QixjQUFjLEVBT2QsU0FBUyxFQUNULGVBQWUsRUFDZixhQUFhLEVBQ2IsbUJBQW1CLEVBQ25CLFdBQVcsRUFDWCxjQUFjLEVBRWQsa0JBQWtCLEVBQ2xCLGtCQUFrQixHQUNyQixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFBYyxlQUFlLEVBQVUs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V0FBVzt3QkFDWCxtQkFBbUI7d0JBQ25CLFVBQVU7d0JBQ1YsU0FBUzt3QkFDVCxRQUFRO3dCQUNSLGVBQWU7d0JBQ2Ysb0JBQW9CO3dCQUNwQixvQkFBb0I7d0JBQ3BCLFNBQVM7d0JBQ1QsUUFBUTt3QkFDUixPQUFPO3dCQUNQLGtCQUFrQjt3QkFDbEIsaUJBQWlCO3dCQUNqQixhQUFhO3dCQUNiLHNCQUFzQjt3QkFDdEIsaUJBQWlCO3dCQUNqQixPQUFPO3dCQUNQLFNBQVM7d0JBQ1QsaUJBQWlCO3dCQUNqQixtQkFBbUI7d0JBQ25CLGlDQUFpQztxQkFDcEMsYUFDVSxDQUFDLGtCQUFrQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLW5vbi1udWxsLWFzc2VydGlvbixyeGpzL25vLXNoYXJlcmVwbGF5LEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtZW51bS1jb21wYXJpc29uLEB0eXBlc2NyaXB0LWVzbGludC91bmJvdW5kLW1ldGhvZCxAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFzc2lnbm1lbnQsQHR5cGVzY3JpcHQtZXNsaW50L25vLXVuc2FmZS1tZW1iZXItYWNjZXNzLEB0eXBlc2NyaXB0LWVzbGludC9uby11bnNhZmUtY2FsbCxAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW5zYWZlLWFyZ3VtZW50LHNlY3VyaXR5L2RldGVjdC1vYmplY3QtaW5qZWN0aW9uICovXG5cbmltcG9ydCB7IEFzeW5jUGlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBIdHRwRXJyb3JSZXNwb25zZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcbmltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGNvbXB1dGVkLCBEZXN0cm95UmVmLCBFbGVtZW50UmVmLCBpbmplY3QsIGlucHV0LCBPbkluaXQsIG91dHB1dCwgU2lnbmFsLCBzaWduYWwsIHZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkLCB0b1NpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcbmltcG9ydCB7IEFic3RyYWN0Q29udHJvbCwgRm9ybUNvbnRyb2wsIEZvcm1Hcm91cCwgRm9ybXNNb2R1bGUsIFJlYWN0aXZlRm9ybXNNb2R1bGUsIFZhbGlkYXRpb25FcnJvcnMsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBSb3V0ZXJMaW5rIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7XG4gICAgSVNfUlVOTklOR19PTl9URVJNSU5BTCxcbiAgICBJU19TRVJWRVIsXG4gICAgU0NfVVNFUl9JTkZPLFxuICAgIFNjQ29udHJhZ2VudCxcbiAgICBTY0NvbnRyYWdlbnRTZXJ2aWNlLFxuICAgIFNjQ29udmVydGVyc1NlcnZpY2UsXG4gICAgU2NEZWxpdmVyeUFkZHJlc3NTZXJ2aWNlLFxuICAgIFNjRGVsaXZlcnlUeXBlLFxuICAgIFNjSUFwaUVycm9yUmVzcG9uc2UsXG4gICAgU2NJRGVsaXZlcnlBZGRyZXNzLFxuICAgIFNjSU5ld09yZGVyLFxuICAgIFNjSVJlZmVyZW5jZXNUeXBlcyxcbiAgICBTY0lUZXJtaW5hbFByb3ZpZGVyLFxuICAgIFNjSVdhcmVob3VzZSxcbiAgICBTY09wZkxpc3QsXG4gICAgU2NPcmRlcnNTZXJ2aWNlLFxuICAgIFNjUGF5bWVudFR5cGUsXG4gICAgU2NSZWZlcmVuY2VzU2VydmljZSxcbiAgICBTY1VJU2VydmljZSxcbiAgICBTY1VwbG9hZGVkRmlsZSxcbiAgICBTY1VzZXIsXG4gICAgU2NXYXJlaG91c2VTZXJ2aWNlLFxuICAgIFRFUk1JTkFMX1BST1ZJREVSUyxcbn0gZnJvbSAnQHNuYWJjZW50ci9jbGllbnQtY29yZSc7XG5pbXBvcnQgeyBUdWlDb250ZXh0LCB0dWlDb250cm9sVmFsdWUsIFR1aURheSwgdHVpSXNQcmVzZW50LCBUdWlTdHJpbmdIYW5kbGVyLCBUdWlWYWxpZGF0aW9uRXJyb3IgfSBmcm9tICdAdGFpZ2EtdWkvY2RrJztcbmltcG9ydCB7IFR1aURhdGFMaXN0Q29tcG9uZW50LCBUdWlEaWFsb2dTZXJ2aWNlLCBUdWlFcnJvciwgVHVpTGFiZWwsIFR1aUxpbmssIFR1aUxvYWRlciwgVHVpT3B0aW9uIH0gZnJvbSAnQHRhaWdhLXVpL2NvcmUnO1xuaW1wb3J0IHsgVHVpRGF0YUxpc3REaXJlY3RpdmUgfSBmcm9tICdAdGFpZ2EtdWkvY29yZS9jb21wb25lbnRzL2RhdGEtbGlzdCc7XG5pbXBvcnQgeyBUdWlGaWVsZEVycm9yUGlwZSwgVHVpRmlsZSwgVHVpRmlsZUxpa2UsIFR1aUZpbGVSZWplY3RlZFBpcGUsIHR1aUZpbGVzQWNjZXB0ZWQsIFR1aUZpbGVzQ29tcG9uZW50LCBUdWlJbnB1dEZpbGVzLCBUdWlJbnB1dEZpbGVzRGlyZWN0aXZlIH0gZnJvbSAnQHRhaWdhLXVpL2tpdCc7XG5pbXBvcnQgeyBUdWlJbnB1dERhdGVNb2R1bGUsIFR1aVNlbGVjdE1vZHVsZSwgVHVpVGV4dGFyZWFNb2R1bGUgfSBmcm9tICdAdGFpZ2EtdWkvbGVnYWN5JztcbmltcG9ydCB7IFBvbHltb3JwaGV1c0NvbXBvbmVudCB9IGZyb20gJ0B0YWlnYS11aS9wb2x5bW9ycGhldXMnO1xuaW1wb3J0IHsgZm9ybWF0LCBpc1ZhbGlkLCBwYXJzZSB9IGZyb20gJ2RhdGUtZm5zJztcbmltcG9ydCB7IGlzQXJyYXksIGlzU3RyaW5nIH0gZnJvbSAnbG9kYXNoLWVzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IsIGNvbWJpbmVMYXRlc3QsIGRlYm91bmNlVGltZSwgZmlsdGVyLCBmaXJzdCwgbWFwLCBtZXJnZSwgT2JzZXJ2YWJsZSwgb2YsIHJldHJ5LCBzaGFyZVJlcGxheSwgc3dpdGNoTWFwLCB0YXAsIHRocm93RXJyb3IgfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgU2NBZGRDb250cmFnZW50RGlhbG9nQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vY29udHJhZ2VudHMvYWRkLWNvbnRyYWdlbnQtZGlhbG9nL3NjLWFkZC1jb250cmFnZW50LWRpYWxvZy5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2NBZGREZWxpdmVyeUFkZHJlc3NEaWFsb2dDb21wb25lbnQgfSBmcm9tICcuLi8uLi9kZWxpdmVyeS1hZGRyZXNzL2FkZC1kZWxpdmVyeS1hZGRyZXNzLWRpYWxvZy9zYy1hZGQtZGVsaXZlcnktYWRkcmVzcy1kaWFsb2cuY29tcG9uZW50JztcbmltcG9ydCB7IFNjRm9jdXNGaXJzdEludmFsaWRGaWVsZERpcmVjdGl2ZSB9IGZyb20gJy4uLy4uL2RpcmVjdGl2ZXMvc2MtZm9jdXMtZmlyc3QtaW52YWxpZC1maWVsZC5kaXJlY3RpdmUnO1xuaW1wb3J0IHsgSU5ld09yZGVyRm9ybSB9IGZyb20gJy4uL21vZGVscy9pLW5ldy1vcmRlci1mb3JtJztcbmltcG9ydCB7IFNDX09SREVSX0ZPUk1fQ09ORklHIH0gZnJvbSAnLi9zYy1vcmRlci1mb3JtLmNvbmZpZyc7XG5cbi8qKlxuICog0KLQuNC/0YssINC60L7RgtC+0YDRi9C1INCy0L7Qt9C80L7QttC90L4g0L/RgNC10L7QsdGA0LDQt9C+0LLQsNGC0Ywg0LIg0LfQvdCw0YfQtdC90LjQtSwg0L7RgtC+0LHRgNCw0LbQsNC10LzQvtC1INCyINC/0L7Qu9C1INCy0LLQvtC00LAuXG4gKi9cbnR5cGUgU2VsZWN0VHlwZSA9XG4gICAgfCBTY0lSZWZlcmVuY2VzVHlwZXM8U2NQYXltZW50VHlwZSwgdHlwZW9mIFNjUGF5bWVudFR5cGU+XG4gICAgfCBTY0NvbnRyYWdlbnRcbiAgICB8IFNjSVJlZmVyZW5jZXNUeXBlczxTY0RlbGl2ZXJ5VHlwZSwgdHlwZW9mIFNjRGVsaXZlcnlUeXBlPlxuICAgIHwgU2NJV2FyZWhvdXNlXG4gICAgfCBTY0lEZWxpdmVyeUFkZHJlc3M7XG5cbi8qKlxuICog0KTQvtGA0LzQsCDQvtGE0L7RgNC80LvQtdC90LjRjyDQt9Cw0LrQsNC30LAuXG4gKi9cbkBDb21wb25lbnQoe1xuICAgIHN0YW5kYWxvbmU6IHRydWUsXG4gICAgc2VsZWN0b3I6ICdzYy1vcmRlci1mb3JtJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vc2Mtb3JkZXItZm9ybS5jb21wb25lbnQuaHRtbCcsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgaW1wb3J0czogW1xuICAgICAgICBGb3Jtc01vZHVsZSxcbiAgICAgICAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgICAgICAgUm91dGVyTGluayxcbiAgICAgICAgVHVpTG9hZGVyLFxuICAgICAgICBUdWlMYWJlbCxcbiAgICAgICAgVHVpU2VsZWN0TW9kdWxlLFxuICAgICAgICBUdWlEYXRhTGlzdERpcmVjdGl2ZSxcbiAgICAgICAgVHVpRGF0YUxpc3RDb21wb25lbnQsXG4gICAgICAgIFR1aU9wdGlvbixcbiAgICAgICAgVHVpRXJyb3IsXG4gICAgICAgIFR1aUxpbmssXG4gICAgICAgIFR1aUlucHV0RGF0ZU1vZHVsZSxcbiAgICAgICAgVHVpVGV4dGFyZWFNb2R1bGUsXG4gICAgICAgIFR1aUlucHV0RmlsZXMsXG4gICAgICAgIFR1aUlucHV0RmlsZXNEaXJlY3RpdmUsXG4gICAgICAgIFR1aUZpbGVzQ29tcG9uZW50LFxuICAgICAgICBUdWlGaWxlLFxuICAgICAgICBBc3luY1BpcGUsXG4gICAgICAgIFR1aUZpZWxkRXJyb3JQaXBlLFxuICAgICAgICBUdWlGaWxlUmVqZWN0ZWRQaXBlLFxuICAgICAgICBTY0ZvY3VzRmlyc3RJbnZhbGlkRmllbGREaXJlY3RpdmUsXG4gICAgXSxcbiAgICBwcm92aWRlcnM6IFtURVJNSU5BTF9QUk9WSURFUlNdLFxufSlcbmV4cG9ydCBjbGFzcyBTY09yZGVyRm9ybUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gICAgLyoqXG4gICAgICog0JjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0L3QsNC/0YDQsNCy0LvQtdC90LjRjyDQv9GA0L7QtNCw0LYg0LfQsNC60LDQt9CwLlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSBkaXJlY3Rpb25JZCA9IGlucHV0LnJlcXVpcmVkPG51bWJlcj4oKTtcblxuICAgIC8qKlxuICAgICAqINCi0YDQtdCx0L7QstCw0YLRjCDQv9C+0LTRgtCy0LXRgNC20LTRkdC90L3Ri9C1INC60L7QvdGC0LDQutGC0L3Ri9C1INC00LDQvdC90YvQtSDQtNC70Y8g0L7RhNC+0YDQvNC70LXQvdC40Y8uINCU0LvRjyDRh9C10YDQvdC+0LLQuNC60LAg4oCUIGBmYWxzZWAuXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGVuZm9yY2VBcHByb3ZlZENvbnRhY3RzID0gaW5wdXQ8Ym9vbGVhbj4odHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC+0YXRgNCw0L3Rj9GC0Ywg0Lgg0LLQvtGB0YHRgtCw0L3QsNCy0LvQuNCy0LDRgtGMINGH0LXRgNC90L7QstGL0LUg0LTQsNC90L3Ri9C1INGE0L7RgNC80Ysg0L/QviDQvdCw0L/RgNCw0LLQu9C10L3QuNGOICjQvNC10YLQsNC00LDQvdC90YvQtSkuINCU0LvRjyDRh9C10YDQvdC+0LLQuNC60LAg4oCUIGBmYWxzZWAuXG4gICAgICog0KDQsNCx0L7RgtCw0LXRgiDRgtC+0LvRjNC60L4g0LXRgdC70Lgg0L/RgNC10LTQvtGB0YLQsNCy0LvQtdC9INGC0L7QutC10L0ge0BsaW5rIFNDX09SREVSX0ZPUk1fQ09ORklHfS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgcGVyc2lzdE1ldGFkYXRhID0gaW5wdXQ8Ym9vbGVhbj4odHJ1ZSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC+0LHRi9GC0LjQtSDQvtGC0L/RgNCw0LLQutC4INCy0LDQu9C40LTQvdC+0Lkg0YTQvtGA0LzRiyDQvtGE0L7RgNC80LvQtdC90LjRjy4g0J/QvtC70LXQt9C90LDRjyDQvdCw0LPRgNGD0LfQutCwIOKAlCDRgdGL0YDRi9C1INC30L3QsNGH0LXQvdC40Y8g0YTQvtGA0LzRiy5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgb3JkZXJTdWJtaXQgPSBvdXRwdXQ8U2NJTmV3T3JkZXI+KCk7XG5cbiAgICAvKipcbiAgICAgKiDQodC10YDQstC40YEg0YHQv9GA0LDQstC+0YfQvdC40LrQvtCyLlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgcmVmZXJlbmNlc1NlcnZpY2UgPSBpbmplY3QoU2NSZWZlcmVuY2VzU2VydmljZSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC10YDQstC40YEg0YDQsNCx0L7RgtGLINGBINC60L7QvdGC0YDQsNCz0LXQvdGC0LDQvNC4LlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgY29udHJhZ2VudFNlcnZpY2UgPSBpbmplY3QoU2NDb250cmFnZW50U2VydmljZSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC10YDQstC40YEg0YDQsNCx0L7RgtGLINGBINCw0LTRgNC10YHQsNC80Lgg0LTQvtGB0YLQsNCy0LrQuC5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlbGl2ZXJ5QWRkcmVzc1NlcnZpY2UgPSBpbmplY3QoU2NEZWxpdmVyeUFkZHJlc3NTZXJ2aWNlKTtcblxuICAgIC8qKlxuICAgICAqINCh0LXRgNCy0LjRgSDQtNC70Y8g0YDQsNCx0L7RgtGLINGB0L4g0YHQutC70LDQtNCw0LzQuC5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgd2FyZWhvdXNlU2VydmljZSA9IGluamVjdChTY1dhcmVob3VzZVNlcnZpY2UpO1xuXG4gICAgLyoqXG4gICAgICog0KHQtdGA0LLQuNGBINC00LvRjyDRgNCw0LHQvtGC0Ysg0YEg0LfQsNC60LDQt9Cw0LzQuCAo0LfQsNCz0YDRg9C30LrQsCDQtNCw0YIg0LTQvtGB0YLQsNCy0LrQuC/RgdCw0LzQvtCy0YvQstC+0LfQsCkuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBvcmRlcnNTZXJ2aWNlID0gaW5qZWN0KFNjT3JkZXJzU2VydmljZSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC10YDQstC40YEg0LTQu9GPINGA0LDQsdC+0YLRiyDRgSBVSS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IHVpU2VydmljZSA9IGluamVjdChTY1VJU2VydmljZSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC10YDQstC40YEg0LrQvtC90LLQtdGA0YLQsNGG0LjQuCDQtNCw0L3QvdGL0YUuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBjb252ZXJ0ZXJzU2VydmljZSA9IGluamVjdChTY0NvbnZlcnRlcnNTZXJ2aWNlKTtcblxuICAgIC8qKlxuICAgICAqINCh0LXRgNCy0LjRgSDRgNCw0LHQvtGC0Ysg0YEg0LTQuNCw0LvQvtCz0L7QstGL0Lwg0L7QutC90L7QvC5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRpYWxvZyA9IGluamVjdChUdWlEaWFsb2dTZXJ2aWNlKTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQvtCy0LDQudC00LXRgCDQtNCw0L3QvdGL0YUg0L4g0YLQtdGA0LzQuNC90LDQu9C1LlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSB0ZXJtaW5hbCA9IGluamVjdDxTY0lUZXJtaW5hbFByb3ZpZGVyPihJU19SVU5OSU5HX09OX1RFUk1JTkFMKTtcblxuICAgIC8qKlxuICAgICAqINCf0L7RgtC+0Log0LTQsNC90L3Ri9GFINC+INGC0LXQutGD0YnQtdC8INC/0L7Qu9GM0LfQvtCy0LDRgtC10LvQtS5cbiAgICAgKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgdXNlciQgPSBpbmplY3Q8T2JzZXJ2YWJsZTxTY1VzZXI+PihTQ19VU0VSX0lORk8pO1xuXG4gICAgLyoqXG4gICAgICog0J3QsNGB0YLRgNC+0LnQutC4INGE0L7RgNC80Ysg0L7RhNC+0YDQvNC70LXQvdC40Y8g0LfQsNC60LDQt9CwLiDQldGB0LvQuCDQvdC1INC/0YDQtdC00L7RgdGC0LDQstC70LXQvdGLLCDQvNC10YLQsNC00LDQvdC90YvQtSDRhNC+0YDQvNGLINC90LUg0YHQvtGF0YDQsNC90Y/RjtGC0YHRjy5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGNvbmZpZyA9IGluamVjdChTQ19PUkRFUl9GT1JNX0NPTkZJRywgeyBvcHRpb25hbDogdHJ1ZSB9KTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC30L3QsNC6INCy0YvQv9C+0LvQvdC10L3QuNGPINGB0LrRgNC40L/RgtCwINC90LAg0YHQtdGA0LLQtdGA0LUuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBpc1NlcnZlciA9IGluamVjdChJU19TRVJWRVIpO1xuXG4gICAgLyoqXG4gICAgICog0KHRgdGL0LvQutCwINC00LvRjyDQsNCy0YLQvtC80LDRgtC40YfQtdGB0LrQvtCz0L4g0YPQv9GA0LDQstC70LXQvdC40Y8g0YPQvdC40YfRgtC+0LbQtdC90LjQtdC8INC30LDQstC40YHQuNC80L7RgdGC0LXQuS5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IGRlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgICAvKipcbiAgICAgKiDQl9Cw0LTQtdGA0LbQutCwINGB0YfQuNGC0YvQstCw0L3QuNGPINGB0LjQs9C90LDQu9C+0LIg0YTQvtGA0LzRiywg0LTQu9GPINC40LfQsdC10LbQsNC90LjRjyDQu9C40YjQvdC40YUg0L7QsdGA0LDQsdC+0YLQvtC6INC/0YDQuCDRgdC80LXQvdC1INC30L3QsNGH0LXQvdC40LkuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBkZWJvdW5jZVRpbWVGb3JtQ2hhbmdlID0gNTA7XG5cbiAgICAvKipcbiAgICAgKiDQpNC+0YDQvNCwINGB0L7Qt9C00LDQvdC40Y8g0LfQsNC60LDQt9CwLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBmb3JtID0gbmV3IEZvcm1Hcm91cDxJTmV3T3JkZXJGb3JtPih7XG4gICAgICAgIGNvbnRyYWdlbnRJZDogbmV3IEZvcm1Db250cm9sPG51bWJlciB8IG51bGw+KG51bGwsIFZhbGlkYXRvcnMucmVxdWlyZWQpLFxuICAgICAgICBwYXltZW50VHlwZTogbmV3IEZvcm1Db250cm9sPFNjUGF5bWVudFR5cGUgfCBudWxsPih7IHZhbHVlOiBudWxsLCBkaXNhYmxlZDogdHJ1ZSB9LCBWYWxpZGF0b3JzLnJlcXVpcmVkKSxcbiAgICAgICAgZGVsaXZlcnlUeXBlOiBuZXcgRm9ybUNvbnRyb2w8U2NEZWxpdmVyeVR5cGUgfCBudWxsPih7IHZhbHVlOiBudWxsLCBkaXNhYmxlZDogdHJ1ZSB9LCBWYWxpZGF0b3JzLnJlcXVpcmVkKSxcbiAgICAgICAgZGVsaXZlcnlEYXRlOiBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4oeyB2YWx1ZTogbnVsbCwgZGlzYWJsZWQ6IHRydWUgfSwgW1xuICAgICAgICAgICAgVmFsaWRhdG9ycy5yZXF1aXJlZCxcbiAgICAgICAgICAgICh7IHZhbHVlIH06IEFic3RyYWN0Q29udHJvbDxzdHJpbmcgfCBudWxsPik6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoIXZhbHVlIHx8IHRoaXMuZGVsaXZlcnlEYXRlcygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlICYmICF0aGlzLmRlbGl2ZXJ5RGF0ZXMoKS5pbmNsdWRlcyh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgc2VydmVyUmVzcG9uc2U6ICfQo9C60LDQttC40YLQtSDQutC+0YDRgNC10LrRgtC90YPRjiDQtNCw0YLRgywg0LjQu9C4INCy0YvQsdC10YDQuNGC0LUg0LjQtyDQsNC60YLQuNCy0L3Ri9GFINC00LDRgiDQutCw0LvQtdC90LTQsNGA0Y8nIH07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9LFxuICAgICAgICBdKSxcbiAgICAgICAgd2FyZWhvdXNlSWQ6IG5ldyBGb3JtQ29udHJvbDxudW1iZXIgfCBudWxsPih7IHZhbHVlOiBudWxsLCBkaXNhYmxlZDogdHJ1ZSB9LCBWYWxpZGF0b3JzLnJlcXVpcmVkKSxcbiAgICAgICAgYWRkcmVzc0lkOiBuZXcgRm9ybUNvbnRyb2w8bnVtYmVyIHwgbnVsbD4oeyB2YWx1ZTogbnVsbCwgZGlzYWJsZWQ6IHRydWUgfSwgVmFsaWRhdG9ycy5yZXF1aXJlZCksXG4gICAgICAgIGNvbW1lbnQ6IG5ldyBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsKSxcbiAgICAgICAgaW1hZ2U6IG5ldyBGb3JtQ29udHJvbDxTY1VwbG9hZGVkRmlsZSB8IG51bGw+KG51bGwpLFxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICog0J/QvtC70LUg0YTQsNC50LvQsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY29udHJvbEZpbGUgPSBuZXcgRm9ybUNvbnRyb2w8RmlsZSB8IG51bGw+KG51bGwpO1xuXG4gICAgLyoqXG4gICAgICoge0BsaW5rIE9ic2VydmFibGV9INGB0L/QuNGB0LrQsCDQv9C+0LTRgtCy0LXRgNC20LTRkdC90L3Ri9GFINGE0LDQudC70L7Qsi5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgYWNjZXB0ZWQkID0gdGhpcy5jb250cm9sRmlsZS52YWx1ZUNoYW5nZXMucGlwZShtYXAoKCkgPT4gdHVpRmlsZXNBY2NlcHRlZCh0aGlzLmNvbnRyb2xGaWxlKSkpO1xuXG4gICAgLyoqXG4gICAgICog0J/RgNC40LfQvdCw0LosINGH0YLQviDQstC60LvRjtGH0ZHQvSDRgNC10LbQuNC8INCw0L3QuNC80LDRhtC40Lgg0L/RgNC10LTRg9C/0YDQtdC20LTQtdC90LjRjyDQviDQvdC10L/QvtC00YLQstC10YDQttC00ZHQvdC90YvRhSDQtNCw0L3QvdGL0YUuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHdhcm5pbmdTaGFrZSA9IHNpZ25hbChmYWxzZSk7XG5cbiAgICAvKipcbiAgICAgKiDQn9GA0LjQt9C90LDQuiwg0YfRgtC+INC60L7QvdGC0YDQsNCz0LXQvdGCINGP0LLQu9GP0LXRgtGB0Y8g0YTQuNC30LjRh9C10YHQutC40Lwg0LvQuNGG0L7QvC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNJbmRpdmlkdWFsID0gc2lnbmFsPGJvb2xlYW4+KHRydWUpO1xuXG4gICAgLyoqXG4gICAgICog0KHQv9C40YHQvtC6INCy0L7Qt9C80L7QttC90YvRhSDQtNCw0YIg0YHQsNC80L7QstGL0LLQvtC30LAg0YHQviDRgdC60LvQsNC00LAuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSB3YXJlaG91c2VEZWxpdmVyeURhdGVzID0gc2lnbmFsPHN0cmluZ1tdPihbXSk7XG5cbiAgICAvKipcbiAgICAgKiDQodC/0LjRgdC+0Log0LLQvtC30LzQvtC20L3Ri9GFINC00LDRgiDQtNC+0YHRgtCw0LLQutC4LlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgYWRkcmVzc0RlbGl2ZXJ5RGF0ZXMgPSBzaWduYWw8c3RyaW5nW10+KFtdKTtcblxuICAgIC8qKlxuICAgICAqIHtAbGluayBPYnNlcnZhYmxlfSDRgdC/0LjRgdC60LAg0LrQvtC90YLRgNCw0LPQtdC90YLQvtCyINC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjy5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgY29udHJhZ2VudHMkOiBPYnNlcnZhYmxlPFNjQ29udHJhZ2VudFtdIHwgbnVsbD4gPSB0aGlzLmNvbnRyYWdlbnRTZXJ2aWNlLmNvbnRyYWdlbnRzJDtcblxuICAgIC8qKlxuICAgICAqIHtAbGluayBPYnNlcnZhYmxlfSDRgdC/0LjRgdC60LAg0LDQtNGA0LXRgdC+0LIg0LrQvtC90YLRgNCw0LPQtdC90YLQsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgYWRkcmVzc2VzJDogT2JzZXJ2YWJsZTxTY0lEZWxpdmVyeUFkZHJlc3NbXSB8IG51bGw+ID0gdGhpcy5kZWxpdmVyeUFkZHJlc3NTZXJ2aWNlLmRlbGl2ZXJ5QWRkcmVzc2VzJC5waXBlKFxuICAgICAgICB0YXAoKGRlbGl2ZXJ5QWRkcmVzc2VzKSA9PiB7XG4gICAgICAgICAgICBpZiAoZGVsaXZlcnlBZGRyZXNzZXMgJiYgdGhpcy5mb3JtLmNvbnRyb2xzLmFkZHJlc3NJZC52YWx1ZSAmJiAhZGVsaXZlcnlBZGRyZXNzZXMuc29tZSgoZGVsaXZlcnkpID0+IGRlbGl2ZXJ5LmlkID09PSB0aGlzLmZvcm0uY29udHJvbHMuYWRkcmVzc0lkLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5jb250cm9scy5hZGRyZXNzSWQucmVzZXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICApO1xuXG4gICAgLyoqXG4gICAgICoge0BsaW5rIE9ic2VydmFibGV9INGB0L/QuNGB0LrQsCDRgdC60LvQsNC00L7Qsi5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgd2FyZWhvdXNlcyQ6IE9ic2VydmFibGU8U2NJV2FyZWhvdXNlW10+ID0gdGhpcy53YXJlaG91c2VTZXJ2aWNlLmdldFdhcmVob3VzZXMkKCk7XG5cbiAgICAvKipcbiAgICAgKiB7QGxpbmsgT2JzZXJ2YWJsZX0g0J7Qn9CkINCy0YvQsdGA0LDQvdC90L7Qs9C+INC60L7QvdGC0YDQsNCz0LXQvdGC0LAuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBvcGYkID0gdHVpQ29udHJvbFZhbHVlPG51bWJlciB8IG51bGwgfCB1bmRlZmluZWQ+KHRoaXMuZm9ybS5jb250cm9scy5jb250cmFnZW50SWQpLnBpcGUoXG4gICAgICAgIGZpbHRlcih0dWlJc1ByZXNlbnQpLFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2xzLnBheW1lbnRUeXBlLmVuYWJsZSgpO1xuICAgICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2xzLmRlbGl2ZXJ5VHlwZS5lbmFibGUoKTtcbiAgICAgICAgfSksXG4gICAgICAgIHN3aXRjaE1hcCgoc2VsZWN0Q29udHJhZ2VudElkKSA9PlxuICAgICAgICAgICAgdGhpcy5jb250cmFnZW50cyQucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIodHVpSXNQcmVzZW50KSxcbiAgICAgICAgICAgICAgICBtYXAoKGNvbnRyYWdlbnRzOiBTY0NvbnRyYWdlbnRbXSkgPT4gY29udHJhZ2VudHMuZmluZCgoY29udHJhZ2VudCkgPT4gY29udHJhZ2VudC5pZCA9PT0gc2VsZWN0Q29udHJhZ2VudElkKSksXG4gICAgICAgICAgICAgICAgbWFwKChjb250cmFnZW50KSA9PiBjb250cmFnZW50Py5vcGYpLFxuICAgICAgICAgICAgICAgIHRhcCgob3BmKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaXNJbmRpdmlkdWFsLnNldChvcGY/LmlkID09PSBTY09wZkxpc3QuaW5kaXZpZHVhbC52YWx1ZU9mKCkpO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICApXG4gICAgICAgICksXG4gICAgICAgIHNoYXJlUmVwbGF5KDEpLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKVxuICAgICk7XG5cbiAgICAvKipcbiAgICAgKiB7QGxpbmsgT2JzZXJ2YWJsZX0g0YLQuNC/0L7QsiDQvtC/0LvQsNGC0Ysg0LfQsNC60LDQt9CwLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCByZWFkb25seSBwYXltZW50VHlwZXMkOiBPYnNlcnZhYmxlPEFycmF5PFNjSVJlZmVyZW5jZXNUeXBlczxTY1BheW1lbnRUeXBlLCB0eXBlb2YgU2NQYXltZW50VHlwZT4+PiA9IHRoaXMub3BmJC5waXBlKFxuICAgICAgICBtYXAoKG9wZikgPT4gb3BmICYmIChvcGYuaWQgPT09IFNjT3BmTGlzdC5pbmRpdmlkdWFsID8gU2NQYXltZW50VHlwZS5iZXpuYWwyIDogU2NQYXltZW50VHlwZS5vbmxpbmUpKSxcbiAgICAgICAgc3dpdGNoTWFwKChwYXltZW50VHlwZUZpbHRlcikgPT5cbiAgICAgICAgICAgIHRoaXMucmVmZXJlbmNlc1NlcnZpY2UucGF5bWVudFR5cGVzJC5waXBlKFxuICAgICAgICAgICAgICAgIG1hcCgocGF5bWVudFR5cGVzKSA9PiAocGF5bWVudFR5cGVGaWx0ZXIgPyBwYXltZW50VHlwZXMgOiBbXSkpLFxuICAgICAgICAgICAgICAgIG1hcCgocGF5bWVudFR5cGVzKSA9PiBwYXltZW50VHlwZXMuZmlsdGVyKCh0eXBlKSA9PiB0eXBlLmlkICE9PSBwYXltZW50VHlwZUZpbHRlcikpLFxuICAgICAgICAgICAgICAgIHRhcCgocGF5bWVudFR5cGVzKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmZvcm0uY29udHJvbHMucGF5bWVudFR5cGUudmFsdWUgJiYgIXBheW1lbnRUeXBlcy5zb21lKChwYXltZW50KSA9PiBwYXltZW50LmlkID09PSB0aGlzLmZvcm0uY29udHJvbHMucGF5bWVudFR5cGUudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uY29udHJvbHMucGF5bWVudFR5cGUucmVzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuZm9ybS5jb250cm9scy5wYXltZW50VHlwZS52YWx1ZSAmJiBwYXltZW50VHlwZXMubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uY29udHJvbHMucGF5bWVudFR5cGUucGF0Y2hWYWx1ZShwYXltZW50VHlwZXNbMF0uaWQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICAvKipcbiAgICAgKiB7QGxpbmsgT2JzZXJ2YWJsZX0g0YLQuNC/0L7QsiDQtNC+0YHRgtCw0LLQutC4INC30LDQutCw0LfQsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgZGVsaXZlcnlUeXBlcyQ6IE9ic2VydmFibGU8QXJyYXk8U2NJUmVmZXJlbmNlc1R5cGVzPFNjRGVsaXZlcnlUeXBlLCB0eXBlb2YgU2NEZWxpdmVyeVR5cGU+Pj4gPSB0aGlzLm9wZiQucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKChvcGYpID0+XG4gICAgICAgICAgICB0aGlzLnJlZmVyZW5jZXNTZXJ2aWNlLmRlbGl2ZXJ5VHlwZXMkLnBpcGUoXG4gICAgICAgICAgICAgICAgbWFwKChkZWxpdmVyeVR5cGVzKSA9PiAob3BmID8gZGVsaXZlcnlUeXBlcyA6IFtdKSksXG4gICAgICAgICAgICAgICAgc3dpdGNoTWFwKChkZWxpdmVyeVR5cGVzKSA9PlxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRlbGl2ZXJ5QWRkcmVzc1NlcnZpY2UuZGVsaXZlcnlBZGRyZXNzZXMkLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXAoKGRlbGl2ZXJ5QWRkcmVzc2VzKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wZj8uaWQgPT09IFNjT3BmTGlzdC5pbmRpdmlkdWFsICYmICEoZGVsaXZlcnlBZGRyZXNzZXMgJiYgZGVsaXZlcnlBZGRyZXNzZXMubGVuZ3RoID4gMClcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBkZWxpdmVyeVR5cGVzLmZpbHRlcigodHlwZSkgPT4gdHlwZS5pZCAhPT0gU2NEZWxpdmVyeVR5cGUuZGVsaXZlcnkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogZGVsaXZlcnlUeXBlc1xuICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICB0YXAoKGRlbGl2ZXJ5VHlwZXMpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZm9ybS5jb250cm9scy5kZWxpdmVyeVR5cGUudmFsdWUgJiYgIWRlbGl2ZXJ5VHlwZXMuc29tZSgoZGVsaXZlcnkpID0+IGRlbGl2ZXJ5LmlkID09PSB0aGlzLmZvcm0uY29udHJvbHMuZGVsaXZlcnlUeXBlLnZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2xzLmRlbGl2ZXJ5VHlwZS5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5mb3JtLmNvbnRyb2xzLmRlbGl2ZXJ5VHlwZS52YWx1ZSAmJiBkZWxpdmVyeVR5cGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2xzLmRlbGl2ZXJ5VHlwZS5wYXRjaFZhbHVlKGRlbGl2ZXJ5VHlwZXNbMF0uaWQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIClcbiAgICAgICAgKVxuICAgICk7XG5cbiAgICAvKipcbiAgICAgKiDQn9GA0LjQt9C90LDQuiwg0YfRgtC+INCy0YvQsdGA0LDQvSDRgtC40L8g0L7Qv9C70LDRgtGLINC90LDQu9C40YfQvdGL0LzQuC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNDYXNoUGF5bWVudFNlbGVjdGVkOiBTaWduYWw8Ym9vbGVhbj4gPSB0b1NpZ25hbChcbiAgICAgICAgdHVpQ29udHJvbFZhbHVlPFNjUGF5bWVudFR5cGUgfCBudWxsPih0aGlzLmZvcm0uY29udHJvbHMucGF5bWVudFR5cGUpLnBpcGUobWFwKChwYXltZW50VHlwZSkgPT4gcGF5bWVudFR5cGUgPT09IFNjUGF5bWVudFR5cGUubmFsKSksXG4gICAgICAgIHsgaW5pdGlhbFZhbHVlOiBmYWxzZSB9XG4gICAgKTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC30L3QsNC6LCDRh9GC0L4g0L3QvtC80LXRgCDRgtC10LvQtdGE0L7QvdCwINC/0L7QtNGC0LLQtdGA0LbQtNGR0L0uXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGlzUGhvbmVBcHByb3ZlZDogU2lnbmFsPGJvb2xlYW4+ID0gdG9TaWduYWwoXG4gICAgICAgIHRoaXMudXNlciQucGlwZShcbiAgICAgICAgICAgIGZpbHRlcigodXNlcikgPT4gIXVzZXIuaXNHdWVzdCksXG4gICAgICAgICAgICBtYXAoKHVzZXIpID0+IHVzZXIuY29udGFjdHMucGhvbmUuaXNBcHByb3ZlZClcbiAgICAgICAgKSxcbiAgICAgICAgeyBpbml0aWFsVmFsdWU6IHRydWUgfVxuICAgICk7XG5cbiAgICAvKipcbiAgICAgKiDQn9GA0LjQt9C90LDQuiwg0YfRgtC+INCw0LTRgNC10YEg0Y3Qu9C10LrRgtGA0L7QvdC90L7QuSDQv9C+0YfRgtGLINC/0L7QtNGC0LLQtdGA0LbQtNGR0L0g0L/QvtC70YzQt9C+0LLQsNGC0LXQu9C10LwuXG4gICAgICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBpc0VtYWlsQXBwcm92ZWRVc2VyOiBTaWduYWw8Ym9vbGVhbj4gPSB0b1NpZ25hbChcbiAgICAgICAgdGhpcy51c2VyJC5waXBlKFxuICAgICAgICAgICAgZmlsdGVyKCh1c2VyKSA9PiAhdXNlci5pc0d1ZXN0KSxcbiAgICAgICAgICAgIG1hcCgodXNlcikgPT4gdXNlci5jb250YWN0cy5lbWFpbC5pc0FwcHJvdmVkKVxuICAgICAgICApLFxuICAgICAgICB7IGluaXRpYWxWYWx1ZTogdHJ1ZSB9XG4gICAgKTtcblxuICAgIC8qKlxuICAgICAqINCf0YDQuNC30L3QsNC6LCDRh9GC0L4g0LDQtNGA0LXRgSDRjdC70LXQutGC0YDQvtC90L3QvtC5INC/0L7Rh9GC0Ysg0L/QvtC00YLQstC10YDQttC00ZHQvSDQuNC70Lgg0LrQvtC90YLRgNCw0LPQtdC90YIg0Y/QstC70Y/QtdGC0YHRjyDRhNC40LfQuNGH0LXRgdC60LjQvCDQu9C40YbQvtC8LlxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSB1bmljb3JuL2NvbnNpc3RlbnQtZnVuY3Rpb24tc2NvcGluZ1xuICAgIHByb3RlY3RlZCByZWFkb25seSBpc0VtYWlsQXBwcm92ZWQ6IFNpZ25hbDxib29sZWFuPiA9IGNvbXB1dGVkKCgpID0+IHRoaXMuaXNFbWFpbEFwcHJvdmVkVXNlcigpIHx8IHRoaXMuaXNJbmRpdmlkdWFsKCkpO1xuXG4gICAgLyoqXG4gICAgICog0JfQvdCw0YfQtdC90LjQtSDQstGL0LHRgNCw0L3QvdC+0LPQviDRgtC40L/QsCDQtNC+0YHRgtCw0LLQutC4LlxuICAgICAqL1xuICAgIHByaXZhdGUgcmVhZG9ubHkgZGVsaXZlcnlUeXBlVmFsdWUgPSB0b1NpZ25hbCh0dWlDb250cm9sVmFsdWU8U2NEZWxpdmVyeVR5cGUgfCBudWxsPih0aGlzLmZvcm0uY29udHJvbHMuZGVsaXZlcnlUeXBlKSwgeyBpbml0aWFsVmFsdWU6IG51bGwgfSk7XG5cbiAgICAvKipcbiAgICAgKiDQn9GA0LjQt9C90LDQuiwg0YfRgtC+INCy0YvQsdGA0LDQvSDRgtC40L8g0LTQvtGB0YLQsNCy0LrQuCBcItCU0L7RgdGC0LDQstC60LBcIi5cbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgdW5pY29ybi9jb25zaXN0ZW50LWZ1bmN0aW9uLXNjb3BpbmdcbiAgICBwcm90ZWN0ZWQgcmVhZG9ubHkgaXNEZWxpdmVyeSA9IGNvbXB1dGVkPGJvb2xlYW4+KCgpID0+IHRoaXMuZGVsaXZlcnlUeXBlVmFsdWUoKSA9PT0gU2NEZWxpdmVyeVR5cGUuZGVsaXZlcnkpO1xuXG4gICAgLyoqXG4gICAgICog0J3QsNCx0L7RgCDQtNC+0YHRgtGD0L/QvdGL0YUg0LTQsNGCINCyINC30LDQstC40YHQuNC80L7RgdGC0Lgg0L7RgiDRgtC40L/QsCDQtNC+0YHRgtCw0LLQutC4LlxuICAgICAqL1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSB1bmljb3JuL2NvbnNpc3RlbnQtZnVuY3Rpb24tc2NvcGluZ1xuICAgIHByb3RlY3RlZCByZWFkb25seSBkZWxpdmVyeURhdGVzID0gY29tcHV0ZWQ8c3RyaW5nW10+KCgpID0+XG4gICAgICAgIHRoaXMuZGVsaXZlcnlUeXBlVmFsdWUoKSA9PT0gU2NEZWxpdmVyeVR5cGUuc2VsZl9kZWxpdmVyeSA/IHRoaXMud2FyZWhvdXNlRGVsaXZlcnlEYXRlcygpIDogdGhpcy5hZGRyZXNzRGVsaXZlcnlEYXRlcygpXG4gICAgKTtcblxuICAgIC8qKlxuICAgICAqINCh0YHRi9C70LrQsCDQvdCwINGN0LvQtdC80LXQvdGCINGBINC/0YDQtdC00YPQv9GA0LXQttC00LXQvdC40LXQvCDQviDQvdC10L/QvtC00YLQstC10YDQttC00ZHQvdC90YvRhSDQtNCw0L3QvdGL0YUuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHVuY29uZmlybWVkRGF0YVdhcm5pbmcgPSB2aWV3Q2hpbGQ8RWxlbWVudFJlZjxIVE1MRWxlbWVudD4+KCd1bmNvbmZpcm1lZERhdGFXYXJuaW5nJyk7XG5cbiAgICAvKipcbiAgICAgKiDQktC+0LfQstGA0LDRidCw0LXRgiDQv9GA0LjQt9C90LDQuiwg0YfRgtC+INGD0LrQsNC30LDQvdC90LDRjyDQtNCw0YLQsCDQvdC10LTQvtGB0YLRg9C/0L3QsCDQtNC70Y8g0LLRi9Cx0L7RgNCwLlxuICAgICAqXG4gICAgICogQHBhcmFtIGRhdGUg0JTQsNGC0LAuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGRlbGl2ZXJ5RGF0ZUZpbHRlciA9IChkYXRlOiBUdWlEYXkpOiBib29sZWFuID0+ICF0aGlzLmRlbGl2ZXJ5RGF0ZXMoKS5pbmNsdWRlcyhgJHtkYXRlLnRvU3RyaW5nKCdZTUQnLCAnLScpfSAwMDowMDowMGApO1xuXG4gICAgLyoqXG4gICAgICog0JjQvdC40YbQuNCw0LvQuNC30LjRgNGD0LXRgiDRjdC60LfQtdC80L/Qu9GP0YAg0LrQu9Cw0YHRgdCwIHtAbGluayBTY09yZGVyRm9ybUNvbXBvbmVudH0uXG4gICAgICovXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKCkge1xuICAgICAgICAvLyDQkNCy0YLQvtC80LDRgtC40YfQtdGB0LrQuCDQstGL0LHQuNGA0LDQtdC8INC10LTQuNC90YHRgtCy0LXQvdC90L7Qs9C+INC60L7QvdGC0YDQsNCz0LXQvdGC0LAt0YTQuNC30LvQuNGG0L4uXG4gICAgICAgIHRoaXMuY29udHJhZ2VudHMkXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIoKGNvbnRyYWdlbnRzKTogY29udHJhZ2VudHMgaXMgW1NjQ29udHJhZ2VudF0gPT4gISFjb250cmFnZW50cyAmJiBjb250cmFnZW50cy5sZW5ndGggPT09IDEpLFxuICAgICAgICAgICAgICAgIGZpcnN0KCksXG4gICAgICAgICAgICAgICAgZmlsdGVyKChbY29udHJhZ2VudF0pID0+IGNvbnRyYWdlbnQub3BmLmlkID09PSBTY09wZkxpc3QuaW5kaXZpZHVhbC52YWx1ZU9mKCkpLFxuICAgICAgICAgICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKChbY29udHJhZ2VudF0pID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm0uY29udHJvbHMuY29udHJhZ2VudElkPy5wYXRjaFZhbHVlKGNvbnRyYWdlbnQuaWQpO1xuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5pbml0Rm9ybUNoYW5nZXMoKTtcbiAgICB9XG5cbiAgICAvKiogQGluaGVyaXRkb2MgKi9cbiAgICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgICAgIC8vINCS0L7RgdGB0YLQsNC90LDQstC70LjQstCw0LXQvCDQuCDRgdC+0YXRgNCw0L3Rj9C10Lwg0YfQtdGA0L3QvtCy0YvQtSDQtNCw0L3QvdGL0LUg0YTQvtGA0LzRiyDQv9C+INC90LDQv9GA0LDQstC70LXQvdC40Y4uXG4gICAgICAgIGlmICh0aGlzLnBlcnNpc3RNZXRhZGF0YSgpKSB7XG4gICAgICAgICAgICB0aGlzLmluaXRNZXRhZGF0YSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J/RgNC10L7QsdGA0LDQt9GD0LXRgiDQvtCx0YrQtdC60YLRiyDQsiDQt9C90LDRh9C10L3QuNGPLCDQvtGC0L7QsdGA0LDQttCw0LXQvNC+0LUg0LIg0L/QvtC70LUg0LLQstC+0LTQsC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBpdGVtcyDQktGL0LHRgNCw0L3QvdGL0LUg0L7QsdGK0LXQutGC0Ysg0LLRi9C/0LDQtNCw0Y7RidC10LPQviDRgdC/0LjRgdC60LAuXG4gICAgICovXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXNcbiAgICBwdWJsaWMgc3RyaW5naWZ5KGl0ZW1zOiByZWFkb25seSBTZWxlY3RUeXBlW10pOiBUdWlTdHJpbmdIYW5kbGVyPFR1aUNvbnRleHQ8bnVtYmVyPj4ge1xuICAgICAgICBjb25zdCBpdGVtc01hcCA9IG5ldyBNYXAoXG4gICAgICAgICAgICBpdGVtcy5tYXAoKGl0ZW0pID0+IHtcbiAgICAgICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgdW5pY29ybi9uby1uZXN0ZWQtdGVybmFyeSxzb25hcmpzL25vLW5lc3RlZC1jb25kaXRpb25hbFxuICAgICAgICAgICAgICAgIGNvbnN0IG5hbWUgPSAnbmFtZScgaW4gaXRlbSA/IGl0ZW0ubmFtZSA6ICdhZGRyZXNzJyBpbiBpdGVtID8gaXRlbS5hZGRyZXNzIDogJyc7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gW2l0ZW0uaWQsIG5hbWVdIGFzIFtudW1iZXIsIHN0cmluZ107XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiAoeyAkaW1wbGljaXQgfTogVHVpQ29udGV4dDxudW1iZXI+KSA9PiBpdGVtc01hcC5nZXQoJGltcGxpY2l0KSA/PyAnJztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQntCx0YDQsNCx0LDRgtGL0LLQsNC10YIg0L7RgtC/0YDQsNCy0LrRgyDRhNC+0YDQvNGLOiDQstCw0LvQuNC00LjRgNGD0LXRgiDQuCDRjdC80LjRgtC40YIg0LTQsNC90L3Ri9C1INC30LDQutCw0LfQsCDRgNC+0LTQuNGC0LXQu9GOLlxuICAgICAqL1xuICAgIHB1YmxpYyBzdWJtaXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXMuZm9ybS5tYXJrQWxsQXNUb3VjaGVkKCk7XG5cbiAgICAgICAgaWYgKCF0aGlzLmZvcm0udmFsaWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGNvbnRhY3RzQXBwcm92ZWQgPSAhdGhpcy5lbmZvcmNlQXBwcm92ZWRDb250YWN0cygpIHx8ICh0aGlzLmlzUGhvbmVBcHByb3ZlZCgpICYmIHRoaXMuaXNFbWFpbEFwcHJvdmVkKCkpO1xuXG4gICAgICAgIGlmICghY29udGFjdHNBcHByb3ZlZCkge1xuICAgICAgICAgICAgdGhpcy50cmlnZ2VyVW5jb25maXJtZWRXYXJuaW5nKCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMub3JkZXJTdWJtaXQuZW1pdCh0aGlzLmZvcm0uZ2V0UmF3VmFsdWUoKSBhcyBTY0lOZXdPcmRlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0J/RgNC40LzQtdC90Y/QtdGCINC6INC/0L7Qu9GP0Lwg0YTQvtGA0LzRiyDQvtGI0LjQsdC60LgsINC/0YDQuNGI0LXQtNGI0LjQtSDQvtGCINGB0LXRgNCy0LXRgNCwLlxuICAgICAqXG4gICAgICogQHBhcmFtIGVycm9yINCe0YLQstC10YIg0YHQtdGA0LLQtdGA0LAg0YEg0L7RiNC40LHQutCw0LzQuC5cbiAgICAgKi9cbiAgICBwdWJsaWMgYXBwbHlTZXJ2ZXJFcnJvcnMoZXJyb3I6IEh0dHBFcnJvclJlc3BvbnNlKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IHsgZXJyb3JzLCBtZXNzYWdlIH0gPSBlcnJvci5lcnJvciBhcyBTY0lBcGlFcnJvclJlc3BvbnNlO1xuXG4gICAgICAgIGlmIChlcnJvcnMpIHtcbiAgICAgICAgICAgIE9iamVjdC5rZXlzKGVycm9ycykuZm9yRWFjaCgoa2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGtleSA9PT0gJ2RlbGl2ZXJ5RGF0ZScgJiYgaXNBcnJheShlcnJvcnNba2V5XSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmdldChrZXkpPy5zZXRFcnJvcnMoeyBzZXJ2ZXJSZXNwb25zZTogbmV3IFR1aVZhbGlkYXRpb25FcnJvcihlcnJvcnNba2V5XS5hdCgxKSA/PyBlcnJvcnNba2V5XS5hdCgwKSkgfSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmdldChrZXkpPy5zZXRFcnJvcnMoeyBzZXJ2ZXJSZXNwb25zZTogbmV3IFR1aVZhbGlkYXRpb25FcnJvcihlcnJvcnNba2V5XSkgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5nZXQoa2V5KT8ubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSBpZiAobWVzc2FnZSkge1xuICAgICAgICAgICAgdGhpcy5mb3JtLnNldEVycm9ycyh7IHNlcnZlclJlc3BvbnNlOiBuZXcgVHVpVmFsaWRhdGlvbkVycm9yKG1lc3NhZ2UpIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0KPQtNCw0LvRj9C10YIg0YTQsNC50Lsg0LjQtyDRhNC+0YDQvNGLINC30LDQutCw0LfQsC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgcmVtb3ZlRmlsZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jb250cm9sRmlsZS5yZXNldCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCe0YLQutGA0YvQstCw0LXRgiDQtNC40LDQu9C+0LPQvtCy0L7QtSDQvtC60L3QviDQtNC+0LHQsNCy0LvQtdC90LjRjyDQsNC00YDQtdGB0LAg0LTQvtGB0YLQsNCy0LrQuC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgYWRkRGVsaXZlcnlBZGRyZXNzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRpYWxvZ1xuICAgICAgICAgICAgLm9wZW4obmV3IFBvbHltb3JwaGV1c0NvbXBvbmVudChTY0FkZERlbGl2ZXJ5QWRkcmVzc0RpYWxvZ0NvbXBvbmVudCksIHtcbiAgICAgICAgICAgICAgICBzaXplOiAnbCcsXG4gICAgICAgICAgICAgICAgbGFiZWw6ICfQlNC+0LHQsNCy0LvQtdC90LjQtSDQsNC00YDQtdGB0LAg0LTQvtGB0YLQsNCy0LrQuCcsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnN1YnNjcmliZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCe0YLQutGA0YvQstCw0LXRgiDQtNC40LDQu9C+0LPQvtCy0L7QtSDQvtC60L3QviDQtNC+0LHQsNCy0LvQtdC90LjRjyDQutC+0L3RgtGA0LDQs9C10L3RgtCwLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBhZGRDb250cmFnZW50KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmRpYWxvZ1xuICAgICAgICAgICAgLm9wZW4obmV3IFBvbHltb3JwaGV1c0NvbXBvbmVudChTY0FkZENvbnRyYWdlbnREaWFsb2dDb21wb25lbnQpLCB7XG4gICAgICAgICAgICAgICAgc2l6ZTogJ20nLFxuICAgICAgICAgICAgICAgIGxhYmVsOiAn0JTQvtCx0LDQstC70LXQvdC40LUg0LrQvtC90YLRgNCw0LPQtdC90YLQsCcsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLnN1YnNjcmliZSgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCX0LDQv9GD0YHQutCw0LXRgiDQsNC90LjQvNCw0YbQuNGOINC/0YDQtdC00YPQv9GA0LXQttC00LXQvdC40Y8g0L4g0L3QtdC/0L7QtNGC0LLQtdGA0LbQtNGR0L3QvdGL0YUg0LTQsNC90L3Ri9GFINC4INC/0YDQvtC60YDRg9GH0LjQstCw0LXRgiDQuiDQvdC10LzRgy5cbiAgICAgKi9cbiAgICBwcml2YXRlIHRyaWdnZXJVbmNvbmZpcm1lZFdhcm5pbmcoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLnVuY29uZmlybWVkRGF0YVdhcm5pbmcoKT8ubmF0aXZlRWxlbWVudDtcblxuICAgICAgICBpZiAoIXRoaXMuaXNTZXJ2ZXIgJiYgZWxlbWVudCkge1xuICAgICAgICAgICAgZWxlbWVudC5zY3JvbGxJbnRvVmlldyh7IGJlaGF2aW9yOiAnc21vb3RoJywgYmxvY2s6ICdjZW50ZXInIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy53YXJuaW5nU2hha2Uuc2V0KGZhbHNlKTtcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgICB0aGlzLndhcm5pbmdTaGFrZS5zZXQodHJ1ZSk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCS0L7RgdGB0YLQsNC90LDQstC70LjQstCw0LXRgiDRh9C10YDQvdC+0LLRi9C1INC00LDQvdC90YvQtSDRhNC+0YDQvNGLINC40Lcg0LzQtdGC0LDQtNCw0L3QvdGL0YUg0Lgg0LjQvdC40YbQuNCw0LvQuNC30LjRgNGD0LXRgiDQuNGFINGB0L7RhdGA0LDQvdC10L3QuNC1LlxuICAgICAqL1xuICAgIHByaXZhdGUgaW5pdE1ldGFkYXRhKCk6IHZvaWQge1xuICAgICAgICBjb25zdCB7IGNvbmZpZyB9ID0gdGhpcztcblxuICAgICAgICBpZiAoIWNvbmZpZykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29tYmluZUxhdGVzdCh7XG4gICAgICAgICAgICBvcmRlck1ldGFkYXRhOiB0aGlzLnVpU2VydmljZS5nZXROZXdPcmRlck1ldGFkYXRhJCh0aGlzLmRpcmVjdGlvbklkKCkpLFxuICAgICAgICAgICAgdXNlcjogdGhpcy51c2VyJC5waXBlKGZpbHRlcigodXNlcikgPT4gIXVzZXIuaXNHdWVzdCkpLFxuICAgICAgICB9KVxuICAgICAgICAgICAgLnBpcGUoZmlyc3QoKSwgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuZGVzdHJveVJlZikpXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgc29uYXJqcy9jb2duaXRpdmUtY29tcGxleGl0eVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoeyBvcmRlck1ldGFkYXRhIH0pID0+IHtcbiAgICAgICAgICAgICAgICBsZXQgZGVsaXZlcnlEYXRlOiBzdHJpbmcgfCBudWxsID1cbiAgICAgICAgICAgICAgICAgICAgb3JkZXJNZXRhZGF0YT8uZGVsaXZlcnlEYXRlICYmIGlzVmFsaWQocGFyc2Uob3JkZXJNZXRhZGF0YS5kZWxpdmVyeURhdGUsIGNvbmZpZy5kYXRlRm9ybWF0cy5hcGksIG5ldyBEYXRlKCkpKSA/IG9yZGVyTWV0YWRhdGEuZGVsaXZlcnlEYXRlIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIC8vINCV0YHQu9C4INC00LDRgtCwINGB0YLQsNGA0L7Qs9C+INGE0L7RgNC80LDRgtCwLCDRgtC+INC/0YDQtdC+0LHRgNCw0LfRg9C10Lwg0LXRkSDQsiDQvdC+0LLRi9C5INGE0L7RgNC80LDRgi5cbiAgICAgICAgICAgICAgICAvLyBUT0RPOiDQo9Cx0YDQsNGC0Ywg0Y3RgtC+0YIg0LHQu9C+0Log0LrQvtCz0LTQsCDQstGB0LUg0LTQsNGC0Ysg0YMg0LrQu9C40LXQvdGC0L7QsiDQstGB0YLQsNC90YPRgiDQsiDQvdC+0YDQvNCw0LvRjNC90L7QvCDRhNC+0YDQvNCw0YLQtS5cbiAgICAgICAgICAgICAgICBpZiAob3JkZXJNZXRhZGF0YT8uZGVsaXZlcnlEYXRlICYmICFkZWxpdmVyeURhdGUgJiYgaXNWYWxpZChwYXJzZShvcmRlck1ldGFkYXRhLmRlbGl2ZXJ5RGF0ZSwgY29uZmlnLmRhdGVGb3JtYXRzLnVpRGF0ZSwgbmV3IERhdGUoKSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGRlbGl2ZXJ5RGF0ZSA9IGZvcm1hdChwYXJzZShvcmRlck1ldGFkYXRhLmRlbGl2ZXJ5RGF0ZSwgY29uZmlnLmRhdGVGb3JtYXRzLnVpRGF0ZSwgbmV3IERhdGUoKSksIGNvbmZpZy5kYXRlRm9ybWF0cy5hcGkpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0dWlJc1ByZXNlbnQob3JkZXJNZXRhZGF0YSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLnBhdGNoVmFsdWUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udHJhZ2VudElkOiBvcmRlck1ldGFkYXRhLmNvbnRyYWdlbnRJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHBheW1lbnRUeXBlOiBvcmRlck1ldGFkYXRhLmNvbnRyYWdlbnRJZCA/IG9yZGVyTWV0YWRhdGEucGF5bWVudFR5cGUgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgZGVsaXZlcnlUeXBlOiBvcmRlck1ldGFkYXRhLmNvbnRyYWdlbnRJZCA/IG9yZGVyTWV0YWRhdGEuZGVsaXZlcnlUeXBlIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbGl2ZXJ5RGF0ZTogb3JkZXJNZXRhZGF0YS5jb250cmFnZW50SWQgJiYgQm9vbGVhbihvcmRlck1ldGFkYXRhLmRlbGl2ZXJ5VHlwZSkgJiYgZGVsaXZlcnlEYXRlID8gZGVsaXZlcnlEYXRlIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZHJlc3NJZDogb3JkZXJNZXRhZGF0YS5kZWxpdmVyeVR5cGUgPT09IFNjRGVsaXZlcnlUeXBlLmRlbGl2ZXJ5ICYmIG9yZGVyTWV0YWRhdGEuYWRkcmVzc0lkID8gb3JkZXJNZXRhZGF0YS5hZGRyZXNzSWQgOiBudWxsLFxuICAgICAgICAgICAgICAgICAgICAgICAgd2FyZWhvdXNlSWQ6IG9yZGVyTWV0YWRhdGEuY29udHJhZ2VudElkICYmIEJvb2xlYW4ob3JkZXJNZXRhZGF0YS5kZWxpdmVyeVR5cGUpID8gb3JkZXJNZXRhZGF0YS53YXJlaG91c2VJZCA6IG51bGwsXG4gICAgICAgICAgICAgICAgICAgICAgICBjb21tZW50OiBvcmRlck1ldGFkYXRhLmNvbW1lbnQsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgIHRoaXMuZm9ybS52YWx1ZUNoYW5nZXMucGlwZShkZWJvdW5jZVRpbWUoY29uZmlnLmRlYm91bmNlVGltZSksIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpKS5zdWJzY3JpYmUoKG5ld09yZGVyKSA9PiB7XG4gICAgICAgICAgICB0aGlzLnVpU2VydmljZS5zZXROZXdPcmRlck1ldGFkYXRhKHRoaXMuZGlyZWN0aW9uSWQoKSwgdGhpcy5jb252ZXJ0ZXJzU2VydmljZS5yZW1vdmVOdWxsPFNjSU5ld09yZGVyPihuZXdPcmRlciBhcyBTY0lOZXdPcmRlcikpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQmNC90LjRhtC40LDQu9C40LfQuNGA0YPQtdGCINC/0L7QtNC/0LjRgdC60Lgg0L3QsCDQuNC30LzQtdC90LXQvdC40Y8g0L/QvtC70LXQuSDRhNC+0YDQvNGLLlxuICAgICAqL1xuICAgIHByaXZhdGUgaW5pdEZvcm1DaGFuZ2VzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmluaXRGaWxlQ2hhbmdlKCk7XG4gICAgICAgIHRoaXMuaW5pdFdhcmVob3VzZUNoYW5nZSgpO1xuICAgICAgICB0aGlzLmluaXREZWxpdmVyeURhdGVzQ2hhbmdlKCk7XG4gICAgICAgIHRoaXMuaW5pdERhdGVGaWVsZEFjdGl2YXRpb25DaGFuZ2UoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiDQmNC90LjRhtC40LDQu9C40LfQuNGA0YPQtdGCINC/0L7QtNC/0LjRgdC60YMg0L3QsCDQuNC30LzQtdC90LXQvdC40LUg0L/QvtC70Y8g0L/RgNC40LrRgNC10L/Qu9C10L3QuNGPINGE0LDQudC70LAuXG4gICAgICovXG4gICAgcHJpdmF0ZSBpbml0RmlsZUNoYW5nZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jb250cm9sRmlsZS52YWx1ZUNoYW5nZXMucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSkuc3Vic2NyaWJlKChmaWxlKSA9PiB7XG4gICAgICAgICAgICBpZiAoZmlsZSAmJiB0aGlzLmZvcm0uY29udHJvbHMuaW1hZ2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLm9uVXBsb2FkRmlsZShmaWxlLCB0aGlzLmZvcm0uY29udHJvbHMuaW1hZ2UpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm0uY29udHJvbHMuaW1hZ2U/LnJlc2V0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCY0L3QuNGG0LjQsNC70LjQt9C40YDRg9C10YIg0L/QvtC00L/QuNGB0LrRgyDQvdCwINC40LfQvNC10L3QtdC90LjQtSDQstGL0LHRgNCw0L3QvdC+0LPQviDRgdC60LvQsNC00LAuXG4gICAgICovXG4gICAgcHJpdmF0ZSBpbml0V2FyZWhvdXNlQ2hhbmdlKCk6IHZvaWQge1xuICAgICAgICB0aGlzLmZvcm0uY29udHJvbHMud2FyZWhvdXNlSWQudmFsdWVDaGFuZ2VzXG4gICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIoKHdhcmVob3VzZUlkKSA9PiB0dWlJc1ByZXNlbnQod2FyZWhvdXNlSWQpICYmIHRoaXMud2FyZWhvdXNlU2VydmljZS5nZXRDdXJyZW50V2FyZWhvdXNlSWRTZWxlY3QoKSAhPT0gd2FyZWhvdXNlSWQpLFxuICAgICAgICAgICAgICAgIGRlYm91bmNlVGltZSgwKSxcbiAgICAgICAgICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKVxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgLnN1YnNjcmliZSgoaWQpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLndhcmVob3VzZVNlcnZpY2Uuc2V0V2FyZWhvdXNlSWRTZWxlY3RDaGFuZ2UoaWQhKTtcbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCY0L3QuNGG0LjQsNC70LjQt9C40YDRg9C10YIg0L/QvtC00L/QuNGB0LrRgyDQvdCwINC40LfQvNC10L3QtdC90LjQtSDQsNC00YDQtdGB0LAg0LTQvtGB0YLQsNCy0LrQuCDQuCDQstGL0LHRgNCw0L3QvdC+0LPQviDRgdC60LvQsNC00LAg0LTQu9GPINC/0L7Qu9GD0YfQtdC90LjRjyDRgdC/0LjRgdC60LAg0LTQvtGB0YLRg9C/0L3Ri9GFINC00LDRgiDQtNC+0YHRgtCw0LLQutC4LlxuICAgICAqL1xuICAgIHByaXZhdGUgaW5pdERlbGl2ZXJ5RGF0ZXNDaGFuZ2UoKTogdm9pZCB7XG4gICAgICAgIG1lcmdlKFxuICAgICAgICAgICAgdHVpQ29udHJvbFZhbHVlPG51bWJlciB8IG51bGw+KHRoaXMuZm9ybS5jb250cm9scy5hZGRyZXNzSWQpLnBpcGUoXG4gICAgICAgICAgICAgICAgZmlsdGVyKHR1aUlzUHJlc2VudCksXG4gICAgICAgICAgICAgICAgZGVib3VuY2VUaW1lKHRoaXMuZGVib3VuY2VUaW1lRm9ybUNoYW5nZSksXG4gICAgICAgICAgICAgICAgc3dpdGNoTWFwKChhZGRyZXNzSWQ6IG51bWJlcikgPT4gdGhpcy5kZWxpdmVyaWVzQnlBZGRyZXNzKGFkZHJlc3NJZCkpXG4gICAgICAgICAgICApLFxuICAgICAgICAgICAgdHVpQ29udHJvbFZhbHVlPG51bWJlciB8IG51bGw+KHRoaXMuZm9ybS5jb250cm9scy53YXJlaG91c2VJZCkucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIodHVpSXNQcmVzZW50KSxcbiAgICAgICAgICAgICAgICBkZWJvdW5jZVRpbWUodGhpcy5kZWJvdW5jZVRpbWVGb3JtQ2hhbmdlKSxcbiAgICAgICAgICAgICAgICBmaWx0ZXIoKCkgPT4gdGhpcy5mb3JtLmNvbnRyb2xzLmRlbGl2ZXJ5VHlwZS52YWx1ZSA9PT0gU2NEZWxpdmVyeVR5cGUuc2VsZl9kZWxpdmVyeSksXG4gICAgICAgICAgICAgICAgc3dpdGNoTWFwKCh3YXJlaG91c2VJZDogbnVtYmVyKSA9PiB0aGlzLmRlbGl2ZXJpZXNCeVdhcmVob3VzZSh3YXJlaG91c2VJZCkpXG4gICAgICAgICAgICApXG4gICAgICAgIClcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgIGNhdGNoRXJyb3IoKGVycm9yOiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5jb250cm9scy5kZWxpdmVyeURhdGUuZGlzYWJsZSgpO1xuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgICByZXRyeSgpLFxuICAgICAgICAgICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLmRlc3Ryb3lSZWYpXG4gICAgICAgICAgICApXG4gICAgICAgICAgICAuc3Vic2NyaWJlKChkZWxpdmVyeURhdGVzKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGVsaXZlcnlEYXRlVmFsdWUgPSB0aGlzLmZvcm0uY29udHJvbHMuZGVsaXZlcnlEYXRlLnZhbHVlO1xuXG4gICAgICAgICAgICAgICAgaWYgKGRlbGl2ZXJ5RGF0ZVZhbHVlICYmICFkZWxpdmVyeURhdGVzLmluY2x1ZGVzKGRlbGl2ZXJ5RGF0ZVZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uY29udHJvbHMuZGVsaXZlcnlEYXRlLnJlc2V0KCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0JjQvdC40YbQuNCw0LvQuNC30LjRgNGD0LXRgiDQv9C+0LTQv9C40YHQutGDINC90LAg0LjQt9C80LXQvdC10L3QuNC1INC/0L7Qu9C10Lkg0YTQvtGA0LzRiyDQtNC70Y8g0LHQu9C+0LrQuNGA0L7QstCw0L3QuNGPL9Cw0LrRgtC40LLQsNGG0LjQuCDQv9C+0LvRjyDQstGL0LHQvtGA0LAg0LTQsNGC0YsuXG4gICAgICovXG4gICAgcHJpdmF0ZSBpbml0RGF0ZUZpZWxkQWN0aXZhdGlvbkNoYW5nZSgpOiB2b2lkIHtcbiAgICAgICAgbWVyZ2UoXG4gICAgICAgICAgICB0dWlDb250cm9sVmFsdWU8U2NEZWxpdmVyeVR5cGU+KHRoaXMuZm9ybS5jb250cm9scy5kZWxpdmVyeVR5cGUpLFxuICAgICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2xzLmNvbnRyYWdlbnRJZD8udmFsdWVDaGFuZ2VzLnBpcGUoZmlsdGVyKCgpID0+IHRoaXMuZm9ybS5jb250cm9scy5kZWxpdmVyeVR5cGUudmFsdWUgPT09IFNjRGVsaXZlcnlUeXBlLmRlbGl2ZXJ5KSkgPz8gb2YoKVxuICAgICAgICApXG4gICAgICAgICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5jb250cm9scy5kZWxpdmVyeURhdGUuZGlzYWJsZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5jb250cm9scy53YXJlaG91c2VJZC5kaXNhYmxlKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRyZXNzRGVsaXZlcnlEYXRlcy5zZXQoW10pO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZm9ybS5jb250cm9scy5kZWxpdmVyeVR5cGUudmFsdWUgPT09IFNjRGVsaXZlcnlUeXBlLmRlbGl2ZXJ5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5jb250cm9scy5hZGRyZXNzSWQuZW5hYmxlKCk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2FyZWhvdXNlU2VydmljZVxuICAgICAgICAgICAgICAgICAgICAgICAgLmdldERlbGl2ZXJ5V2FyZWhvdXNlJCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAucGlwZShmaXJzdCgpLCB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5kZXN0cm95UmVmKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByeGpzL25vLW5lc3RlZC1zdWJzY3JpYmVcbiAgICAgICAgICAgICAgICAgICAgICAgIC5zdWJzY3JpYmUoKHdhcmVob3VzZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5jb250cm9scy53YXJlaG91c2VJZC5wYXRjaFZhbHVlKHdhcmVob3VzZS5pZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5mb3JtLmNvbnRyb2xzLmRlbGl2ZXJ5VHlwZS52YWx1ZSA9PT0gU2NEZWxpdmVyeVR5cGUuc2VsZl9kZWxpdmVyeSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uY29udHJvbHMuYWRkcmVzc0lkLmRpc2FibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2xzLndhcmVob3VzZUlkLmVuYWJsZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCX0LDQv9GA0LDRiNC40LLQsNC10YIg0LTQsNGC0Ysg0LTQvtGB0YLQsNCy0LrQuCDQv9C+INCw0LTRgNC10YHRgy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhZGRyZXNzSWQg0JjQtNC10L3RgtC40YTQuNC60LDRgtC+0YAg0LDQtNGA0LXRgdCwINC00L7RgdGC0LDQstC60LguXG4gICAgICovXG4gICAgcHJpdmF0ZSBkZWxpdmVyaWVzQnlBZGRyZXNzKGFkZHJlc3NJZDogbnVtYmVyKTogT2JzZXJ2YWJsZTxzdHJpbmdbXT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5vcmRlcnNTZXJ2aWNlLmdldERlbGl2ZXJpZXNEYXRhJChhZGRyZXNzSWQpLnBpcGUoXG4gICAgICAgICAgICBjYXRjaEVycm9yKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvciBpbnN0YW5jZW9mIEh0dHBFcnJvclJlc3BvbnNlID8gZXJyb3IuZXJyb3IubWVzc2FnZSA6IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5jb250cm9scy5hZGRyZXNzSWQuc2V0RXJyb3JzKHtcbiAgICAgICAgICAgICAgICAgICAgc2VydmVyUmVzcG9uc2U6IG1lc3NhZ2UgPz8gYNCe0YjQuNCx0LrQsCDRgdC10YDQstC10YDQsDog0L/QvtC20LDQu9GD0LnRgdGC0LAsINC/0LXRgNC10LfQsNCz0YDRg9C30LjRgtC1INGB0YLRgNCw0L3QuNGG0YMg0Lgv0LjQu9C4INCy0YvQv9C+0LvQvdC40YLQtSDQt9Cw0L/RgNC+0YEg0L/QvtC30LbQtS5gLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuYWRkcmVzc0RlbGl2ZXJ5RGF0ZXMuc2V0KFtdKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aHJvd0Vycm9yKCgpID0+IGVycm9yKTtcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgdGFwKChkZWxpdmVyeURhdGVzKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hZGRyZXNzRGVsaXZlcnlEYXRlcy5zZXQoZGVsaXZlcnlEYXRlcyk7XG4gICAgICAgICAgICAgICAgdGhpcy5mb3JtLmNvbnRyb2xzLmRlbGl2ZXJ5RGF0ZS5lbmFibGUoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICog0JfQsNC/0YDQsNGI0LjQstCw0LXRgiDQtNCw0YLRiyDRgdCw0LzQvtCy0YvQstC+0LfQsCDQv9C+INGB0LrQu9Cw0LTRgy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB3YXJlaG91c2VJZCDQmNC00LXQvdGC0LjRhNC40LrQsNGC0L7RgCDRgdC60LvQsNC00LAuXG4gICAgICovXG4gICAgcHJpdmF0ZSBkZWxpdmVyaWVzQnlXYXJlaG91c2Uod2FyZWhvdXNlSWQ6IG51bWJlcik6IE9ic2VydmFibGU8c3RyaW5nW10+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMub3JkZXJzU2VydmljZS5nZXRTZWxmRGVsaXZlcmllc0RhdGEkKHdhcmVob3VzZUlkKS5waXBlKFxuICAgICAgICAgICAgY2F0Y2hFcnJvcigoZXJyb3I6IHVua25vd24pID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBtZXNzYWdlID0gZXJyb3IgaW5zdGFuY2VvZiBIdHRwRXJyb3JSZXNwb25zZSA/IGVycm9yLmVycm9yLm1lc3NhZ2UgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICB0aGlzLmZvcm0uY29udHJvbHMud2FyZWhvdXNlSWQuc2V0RXJyb3JzKHtcbiAgICAgICAgICAgICAgICAgICAgc2VydmVyUmVzcG9uc2U6IG1lc3NhZ2UgPz8gYNCe0YjQuNCx0LrQsCDRgdC10YDQstC10YDQsDog0L/QvtC20LDQu9GD0LnRgdGC0LAsINC/0LXRgNC10LfQsNCz0YDRg9C30LjRgtC1INGB0YLRgNCw0L3QuNGG0YMg0Lgv0LjQu9C4INCy0YvQv9C+0LvQvdC40YLQtSDQt9Cw0L/RgNC+0YEg0L/QvtC30LbQtS5gLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMud2FyZWhvdXNlRGVsaXZlcnlEYXRlcy5zZXQoW10pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRocm93RXJyb3IoKCkgPT4gZXJyb3IpO1xuICAgICAgICAgICAgfSksXG4gICAgICAgICAgICB0YXAoKGRlbGl2ZXJ5RGF0ZXMpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLndhcmVob3VzZURlbGl2ZXJ5RGF0ZXMuc2V0KGRlbGl2ZXJ5RGF0ZXMpO1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5jb250cm9scy5kZWxpdmVyeURhdGUuZW5hYmxlKCk7XG4gICAgICAgICAgICB9KVxuICAgICAgICApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqINCX0LDQs9GA0YPQttCw0LXRgiDRhNCw0LnQuyDQsiDRhNC+0YDQvNGDLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZpbGUg0KTQsNC50LsuXG4gICAgICogQHBhcmFtIGZpbGVzQ29udHJvbCDQn9C+0LvQtSDRhNCw0LnQu9CwINC30LDQutCw0LfQsC5cbiAgICAgKi9cbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xuICAgIHByaXZhdGUgb25VcGxvYWRGaWxlKGZpbGU6IFR1aUZpbGVMaWtlLCBmaWxlc0NvbnRyb2w6IEZvcm1Db250cm9sPFNjVXBsb2FkZWRGaWxlIHwgbnVsbD4pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTtcblxuICAgICAgICByZWFkZXIuYWRkRXZlbnRMaXN0ZW5lcignbG9hZCcsICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgcmVzdWx0IH0gPSByZWFkZXI7XG5cbiAgICAgICAgICAgIGlmIChpc1N0cmluZyhyZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgZmlsZXNDb250cm9sLnNldFZhbHVlKG5ldyBTY1VwbG9hZGVkRmlsZShmaWxlLm5hbWUsIHJlc3VsdCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZWFkZXIucmVhZEFzRGF0YVVSTChmaWxlIGFzIHVua25vd24gYXMgQmxvYik7XG4gICAgfVxufVxuIiwiQGxldCB1c2VyID0gdXNlciQgfCBhc3luYztcblxuPGZvcm1cbiAgICBbZm9ybUdyb3VwXT1cImZvcm1cIlxuICAgIHNjRm9jdXNGaXJzdEludmFsaWRGaWVsZFxuICAgIFtmaWVsZE9yZGVyXT1cIlsnY29udHJhZ2VudElkJywgJ3BheW1lbnRUeXBlJywgJ2RlbGl2ZXJ5VHlwZScsICd3YXJlaG91c2VJZCcsICdhZGRyZXNzSWQnLCAnZGVsaXZlcnlEYXRlJywgJ2NvbW1lbnQnXVwiXG4gICAgKG5nU3VibWl0KT1cInN1Ym1pdCgpXCJcbiAgICBjbGFzcz1cImZsZXggZmxleC1jb2wgZ2FwLTRcIlxuPlxuICAgIDxuZy10ZW1wbGF0ZSAjc2VsZWN0TG9hZGluZz4gPHR1aS1sb2FkZXIgLz4gPC9uZy10ZW1wbGF0ZT5cblxuICAgIDwhLS0g0JrQvtC90YLRgNCw0LPQtdC90YIuIC0tPlxuICAgIEBpZiAoY29udHJhZ2VudHMkIHwgYXN5bmM7IGFzIGNvbnRyYWdlbnRzKSB7XG4gICAgICAgIEBpZiAoY29udHJhZ2VudHMubGVuZ3RoID4gMSB8fCB1c2VyPy5pc09yZykge1xuICAgICAgICAgICAgPGxhYmVsIHR1aUxhYmVsPlxuICAgICAgICAgICAgICAgINCa0L7QvdGC0YDQsNCz0LXQvdGCXG4gICAgICAgICAgICAgICAgPHR1aS1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY29udHJhZ2VudElkXCJcbiAgICAgICAgICAgICAgICAgICAgW3ZhbHVlQ29udGVudF09XCJjb250cmFnZW50cyA/IHN0cmluZ2lmeShjb250cmFnZW50cykgOiBzZWxlY3RMb2FkaW5nXCJcbiAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgINCa0L7QvdGC0YDQsNCz0LXQvdGCXG4gICAgICAgICAgICAgICAgICAgIDx0dWktZGF0YS1saXN0ICp0dWlEYXRhTGlzdD5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBmb3IgKGNvbnRyYWdlbnQgb2YgY29udHJhZ2VudHM7IHRyYWNrIGNvbnRyYWdlbnQuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR1aU9wdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiY29udHJhZ2VudC5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBjb250cmFnZW50Lm5hbWUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgPC90dWktZGF0YS1saXN0PlxuICAgICAgICAgICAgICAgIDwvdHVpLXNlbGVjdD5cbiAgICAgICAgICAgICAgICA8dHVpLWVycm9yXG4gICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImNvbnRyYWdlbnRJZFwiXG4gICAgICAgICAgICAgICAgICAgIFtlcnJvcl09XCJbXSB8IHR1aUZpZWxkRXJyb3IgfCBhc3luY1wiXG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICA8YVxuICAgICAgICAgICAgICAgICAgICB0dWlMaW5rXG4gICAgICAgICAgICAgICAgICAgIGljb25TdGFydD1cIkB0dWkucGx1c1wiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJhZGRDb250cmFnZW50KClcIlxuICAgICAgICAgICAgICAgICAgICBjbGFzcz1cIm10LTIgYmxvY2tcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAg0J3QvtCy0YvQuVxuICAgICAgICAgICAgICAgIDwvYT5cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICA8IS0tINCi0LjQvyDQvtC/0LvQsNGC0YsuIC0tPlxuICAgIDxsYWJlbCB0dWlMYWJlbD5cbiAgICAgICAg0KLQuNC/INC+0L/Qu9Cw0YLRi1xuICAgICAgICBAbGV0IHBheW1lbnRUeXBlcyA9IHBheW1lbnRUeXBlcyQgfCBhc3luYztcbiAgICAgICAgPHR1aS1zZWxlY3RcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInBheW1lbnRUeXBlXCJcbiAgICAgICAgICAgIFt2YWx1ZUNvbnRlbnRdPVwicGF5bWVudFR5cGVzID8gc3RyaW5naWZ5KHBheW1lbnRUeXBlcykgOiBzZWxlY3RMb2FkaW5nXCJcbiAgICAgICAgPlxuICAgICAgICAgICAg0KLQuNC/INC+0L/Qu9Cw0YLRi1xuICAgICAgICAgICAgPHR1aS1kYXRhLWxpc3QgKnR1aURhdGFMaXN0PlxuICAgICAgICAgICAgICAgIEBmb3IgKHR5cGUgb2YgcGF5bWVudFR5cGVzOyB0cmFjayB0eXBlLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgICAgICAgICAgIHR1aU9wdGlvblxuICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cInR5cGUuaWRcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyB0eXBlLm5hbWUgfX1cbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC90dWktZGF0YS1saXN0PlxuICAgICAgICA8L3R1aS1zZWxlY3Q+XG4gICAgICAgIDx0dWktZXJyb3JcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInBheW1lbnRUeXBlXCJcbiAgICAgICAgICAgIFtlcnJvcl09XCJbXSB8IHR1aUZpZWxkRXJyb3IgfCBhc3luY1wiXG4gICAgICAgIC8+XG4gICAgICAgIEBpZiAoaXNDYXNoUGF5bWVudFNlbGVjdGVkKCkpIHtcbiAgICAgICAgICAgIDxwIGNsYXNzPVwidGV4dC14cyB0ZXh0LXR1aS1zdGF0dXMtcG9zaXRpdmVcIj7Ql9Cw0LrQsNC30Ysg0L/RgNC+0LjQt9Cy0L7QtNGP0YLRgdGPINC/0L4g0L/RgNC10LTQvtC/0LvQsNGC0LU8L3A+XG4gICAgICAgIH1cbiAgICA8L2xhYmVsPlxuXG4gICAgPCEtLSDQn9GA0LXQtNGD0L/RgNC10LbQtNC10L3QuNC1INC+INC90LXQv9C+0LTRgtCy0LXRgNC20LTRkdC90L3Ri9GFINC60L7QvdGC0LDQutGC0L3Ri9GFINC00LDQvdC90YvRhS4gLS0+XG4gICAgQGlmICghaXNQaG9uZUFwcHJvdmVkKCkgfHwgIWlzRW1haWxBcHByb3ZlZCgpKSB7XG4gICAgICAgIDxkaXZcbiAgICAgICAgICAgICN1bmNvbmZpcm1lZERhdGFXYXJuaW5nXG4gICAgICAgICAgICBjbGFzcz1cInRleHQtdHVpLXRleHQtbmVnYXRpdmVcIlxuICAgICAgICAgICAgW2NsYXNzLndhcm5pbmctc2hha2VdPVwid2FybmluZ1NoYWtlKClcIlxuICAgICAgICA+XG4gICAgICAgICAgICDQktC90LjQvNCw0L3QuNC1ISDQlNC70Y8g0L7RhNC+0YDQvNC70LXQvdC40Y8g0LfQsNC60LDQt9CwINC90LXQvtCx0YXQvtC00LjQvNC+INC/0L7QtNGC0LLQtdGA0LTQuNGC0YxcbiAgICAgICAgICAgIEBpZiAoIWlzUGhvbmVBcHByb3ZlZCgpKSB7XG4gICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJmb250LWJvbGRcIj4g0L3QvtC80LXRgCDRgtC10LvQtdGE0L7QvdCwIDwvc3Bhbj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIEBpZiAoIWlzUGhvbmVBcHByb3ZlZCgpICYmICFpc0VtYWlsQXBwcm92ZWQoKSkge1xuICAgICAgICAgICAgICAgIDxzcGFuPiDQuCA8L3NwYW4+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBAaWYgKCFpc0VtYWlsQXBwcm92ZWQoKSkge1xuICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwiZm9udC1ib2xkXCI+INCw0LTRgNC10YEg0Y3Qu9C10LrRgtGA0L7QvdC90L7QuSDQv9C+0YfRgtGLIDwvc3Bhbj5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDxhXG4gICAgICAgICAgICAgICAgdHVpTGlua1xuICAgICAgICAgICAgICAgIHJvdXRlckxpbms9XCIvcHJvZmlsZVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAg0LIg0LLQsNGI0LXQvCDQv9GA0L7RhNC40LvQtVxuICAgICAgICAgICAgPC9hPlxuICAgICAgICA8L2Rpdj5cbiAgICB9XG5cbiAgICA8IS0tINCh0L/QvtGB0L7QsSDQtNC+0YHRgtCw0LLQutC4LiAtLT5cbiAgICA8bGFiZWwgdHVpTGFiZWw+XG4gICAgICAgINCh0L/QvtGB0L7QsSDQtNC+0YHRgtCw0LLQutC4XG4gICAgICAgIEBsZXQgZGVsaXZlcnlUeXBlcyA9IGRlbGl2ZXJ5VHlwZXMkIHwgYXN5bmM7XG4gICAgICAgIDx0dWktc2VsZWN0XG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJkZWxpdmVyeVR5cGVcIlxuICAgICAgICAgICAgW3ZhbHVlQ29udGVudF09XCJkZWxpdmVyeVR5cGVzID8gc3RyaW5naWZ5KGRlbGl2ZXJ5VHlwZXMpIDogc2VsZWN0TG9hZGluZ1wiXG4gICAgICAgID5cbiAgICAgICAgICAgINCh0L/QvtGB0L7QsSDQtNC+0YHRgtCw0LLQutC4XG4gICAgICAgICAgICA8dHVpLWRhdGEtbGlzdCAqdHVpRGF0YUxpc3Q+XG4gICAgICAgICAgICAgICAgQGZvciAoZGVsaXZlcnkgb2YgZGVsaXZlcnlUeXBlczsgdHJhY2sgZGVsaXZlcnkuaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgdHVpT3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBbdmFsdWVdPVwiZGVsaXZlcnkuaWRcIlxuICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBkZWxpdmVyeS5uYW1lIH19XG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvdHVpLWRhdGEtbGlzdD5cbiAgICAgICAgPC90dWktc2VsZWN0PlxuICAgICAgICA8dHVpLWVycm9yXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJkZWxpdmVyeVR5cGVcIlxuICAgICAgICAgICAgW2Vycm9yXT1cIltdIHwgdHVpRmllbGRFcnJvciB8IGFzeW5jXCJcbiAgICAgICAgLz5cbiAgICA8L2xhYmVsPlxuXG4gICAgPCEtLSDQodC60LvQsNC0LiAtLT5cbiAgICA8bGFiZWwgdHVpTGFiZWw+XG4gICAgICAgINCh0LrQu9Cw0LRcbiAgICAgICAgQGxldCB3YXJlaG91c2VzID0gd2FyZWhvdXNlcyQgfCBhc3luYztcbiAgICAgICAgPHR1aS1zZWxlY3RcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cIndhcmVob3VzZUlkXCJcbiAgICAgICAgICAgIFt2YWx1ZUNvbnRlbnRdPVwid2FyZWhvdXNlcyA/IHN0cmluZ2lmeSh3YXJlaG91c2VzKSA6IHNlbGVjdExvYWRpbmdcIlxuICAgICAgICA+XG4gICAgICAgICAgICDQodC60LvQsNC0XG4gICAgICAgICAgICA8dHVpLWRhdGEtbGlzdCAqdHVpRGF0YUxpc3Q+XG4gICAgICAgICAgICAgICAgQGlmICghdGVybWluYWwuaXNSdW5uaW5nT25UZXJtaW5hbCkge1xuICAgICAgICAgICAgICAgICAgICBAZm9yICh3YXJlaG91c2Ugb2Ygd2FyZWhvdXNlczsgdHJhY2sgd2FyZWhvdXNlLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpT3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cIndhcmVob3VzZS5pZFwiXG4gICAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgd2FyZWhvdXNlLm5hbWUgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIEBpZiAod2FyZWhvdXNlU2VydmljZS5nZXRDYXRhbG9nV2FyZWhvdXNlQ2hhbmdlJCgpIHwgYXN5bmM7IGFzIHRlcm1pbmFsV2FyZWhvdXNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHVpT3B0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cInRlcm1pbmFsV2FyZWhvdXNlLmlkXCJcbiAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyB0ZXJtaW5hbFdhcmVob3VzZS5uYW1lIH19XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvdHVpLWRhdGEtbGlzdD5cbiAgICAgICAgPC90dWktc2VsZWN0PlxuICAgICAgICA8dHVpLWVycm9yXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ3YXJlaG91c2VJZFwiXG4gICAgICAgICAgICBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAvPlxuICAgIDwvbGFiZWw+XG5cbiAgICA8IS0tINCQ0LTRgNC10YEg0LTQvtGB0YLQsNCy0LrQuC4gLS0+XG4gICAgQGlmIChpc0RlbGl2ZXJ5KCkpIHtcbiAgICAgICAgQGxldCBhZGRyZXNzZXMgPSBhZGRyZXNzZXMkIHwgYXN5bmM7XG4gICAgICAgIDxkaXY+XG4gICAgICAgICAgICA8bGFiZWwgdHVpTGFiZWw+XG4gICAgICAgICAgICAgICAg0JDQtNGA0LXRgSDQtNC+0YHRgtCw0LLQutC4XG4gICAgICAgICAgICAgICAgPHR1aS1zZWxlY3RcbiAgICAgICAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiYWRkcmVzc0lkXCJcbiAgICAgICAgICAgICAgICAgICAgW3ZhbHVlQ29udGVudF09XCJhZGRyZXNzZXMgPyBzdHJpbmdpZnkoYWRkcmVzc2VzKSA6IHNlbGVjdExvYWRpbmdcIlxuICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAg0JDQtNGA0LXRgSDQtNC+0YHRgtCw0LLQutC4XG4gICAgICAgICAgICAgICAgICAgIDx0dWktZGF0YS1saXN0ICp0dWlEYXRhTGlzdD5cbiAgICAgICAgICAgICAgICAgICAgICAgIEBmb3IgKGFkZHJlc3Mgb2YgYWRkcmVzc2VzOyB0cmFjayBhZGRyZXNzLmlkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0dWlPcHRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3ZhbHVlXT1cImFkZHJlc3MuaWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgYWRkcmVzcy5hZGRyZXNzIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIDwvdHVpLWRhdGEtbGlzdD5cbiAgICAgICAgICAgICAgICA8L3R1aS1zZWxlY3Q+XG4gICAgICAgICAgICAgICAgQGlmIChhZGRyZXNzZXMgJiYgYWRkcmVzc2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICA8dHVpLWVycm9yIGVycm9yPVwi0KMg0LrQvtC90YLRgNCw0LPQtdC90YLQsCDQvdC10YIg0LDQtNGA0LXRgdCwINC00L7RgdGC0LDQstC60LhcIiAvPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICA8dHVpLWVycm9yXG4gICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImFkZHJlc3NJZFwiXG4gICAgICAgICAgICAgICAgICAgIFtlcnJvcl09XCJbXSB8IHR1aUZpZWxkRXJyb3IgfCBhc3luY1wiXG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDwvbGFiZWw+XG4gICAgICAgICAgICA8YVxuICAgICAgICAgICAgICAgIHR1aUxpbmtcbiAgICAgICAgICAgICAgICBpY29uU3RhcnQ9XCJAdHVpLnBsdXNcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJhZGREZWxpdmVyeUFkZHJlc3MoKVwiXG4gICAgICAgICAgICAgICAgY2xhc3M9XCJtdC0yIGJsb2NrXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICDQndC+0LLRi9C5XG4gICAgICAgICAgICA8L2E+XG4gICAgICAgIDwvZGl2PlxuICAgIH1cblxuICAgIDwhLS0g0JTQsNGC0LAg0LTQvtGB0YLQsNCy0LrQuC/RgdCw0LzQvtCy0YvQstC+0LfQsC4gLS0+XG4gICAgPGxhYmVsIHR1aUxhYmVsPlxuICAgICAgICDQltC10LvQsNC10LzQsNGPINC00LDRgtCwIHt7IGlzRGVsaXZlcnkoKSA/ICfQtNC+0YHRgtCw0LLQutC4JyA6ICfRgdCw0LzQvtCy0YvQstC+0LfQsCcgfX1cbiAgICAgICAgPHR1aS1pbnB1dC1kYXRlXG4gICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJkZWxpdmVyeURhdGVcIlxuICAgICAgICAgICAgW2Rpc2FibGVkSXRlbUhhbmRsZXJdPVwiZGVsaXZlcnlEYXRlRmlsdGVyXCJcbiAgICAgICAgPlxuICAgICAgICAgICAg0JbQtdC70LDQtdC80LDRjyDQtNCw0YLQsCB7eyBpc0RlbGl2ZXJ5KCkgPyAn0LTQvtGB0YLQsNCy0LrQuCcgOiAn0YHQsNC80L7QstGL0LLQvtC30LAnIH19XG4gICAgICAgIDwvdHVpLWlucHV0LWRhdGU+XG4gICAgICAgIDx0dWktZXJyb3JcbiAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImRlbGl2ZXJ5RGF0ZVwiXG4gICAgICAgICAgICBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAvPlxuICAgIDwvbGFiZWw+XG5cbiAgICA8IS0tINCa0L7QvNC80LXQvdGC0LDRgNC40Lkg0LrQu9C40LXQvdGC0LAuIC0tPlxuICAgIDxsYWJlbCB0dWlMYWJlbD5cbiAgICAgICAg0JrQvtC80LzQtdC90YLQsNGA0LjQuSDQutC70LjQtdC90YLQsCDQuiDQt9Cw0LrQsNC30YNcbiAgICAgICAgPHR1aS10ZXh0YXJlYVxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY29tbWVudFwiXG4gICAgICAgICAgICBbZXhwYW5kYWJsZV09XCJ0cnVlXCJcbiAgICAgICAgICAgIFtyb3dzXT1cIjE1XCJcbiAgICAgICAgPlxuICAgICAgICAgICAg0JLQstC10LTQuNGC0LUg0YLQtdC60YHRglxuICAgICAgICA8L3R1aS10ZXh0YXJlYT5cbiAgICAgICAgPHR1aS1lcnJvclxuICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiY29tbWVudFwiXG4gICAgICAgICAgICBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAvPlxuICAgIDwvbGFiZWw+XG5cbiAgICA8IS0tINCf0YDQuNC60YDQtdC/0LvQtdC90LjQtSDRhNCw0LnQu9CwINC6INC30LDQutCw0LfRgy4gLS0+XG4gICAgPGRpdj5cbiAgICAgICAgQGlmICghY29udHJvbEZpbGUudmFsdWUpIHtcbiAgICAgICAgICAgIDxsYWJlbCB0dWlJbnB1dEZpbGVzPlxuICAgICAgICAgICAgICAgIDxpbnB1dFxuICAgICAgICAgICAgICAgICAgICBhY2NlcHQ9XCJpbWFnZS8qXCJcbiAgICAgICAgICAgICAgICAgICAgdHVpSW5wdXRGaWxlc1xuICAgICAgICAgICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwiY29udHJvbEZpbGVcIlxuICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8L2xhYmVsPlxuICAgICAgICB9XG5cbiAgICAgICAgPHR1aS1maWxlcyBjbGFzcz1cInR1aS1zcGFjZV90b3AtMVwiPlxuICAgICAgICAgICAgQGlmIChjb250cm9sRmlsZS52YWx1ZSB8IHR1aUZpbGVSZWplY3RlZDogeyBhY2NlcHQ6ICdpbWFnZS8qJyB9IHwgYXN5bmM7IGFzIGZpbGUpIHtcbiAgICAgICAgICAgICAgICA8dHVpLWZpbGVcbiAgICAgICAgICAgICAgICAgICAgc3RhdGU9XCJlcnJvclwiXG4gICAgICAgICAgICAgICAgICAgIFtmaWxlXT1cImZpbGVcIlxuICAgICAgICAgICAgICAgICAgICAocmVtb3ZlKT1cInJlbW92ZUZpbGUoKVwiXG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgQGZvciAoZmlsZSBvZiBhY2NlcHRlZCQgfCBhc3luYzsgdHJhY2sgZmlsZS5uYW1lKSB7XG4gICAgICAgICAgICAgICAgPHR1aS1maWxlXG4gICAgICAgICAgICAgICAgICAgIFtmaWxlXT1cImZpbGVcIlxuICAgICAgICAgICAgICAgICAgICAocmVtb3ZlKT1cInJlbW92ZUZpbGUoKVwiXG4gICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIH1cbiAgICAgICAgPC90dWktZmlsZXM+XG5cbiAgICAgICAgPHR1aS1lcnJvclxuICAgICAgICAgICAgW2Vycm9yXT1cIlsnbWF4TGVuZ3RoJ10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIlxuICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cImNvbnRyb2xGaWxlXCJcbiAgICAgICAgLz5cbiAgICAgICAgPHAgY2xhc3M9XCJ0dWktZm9ybV9fZmllbGQtbm90ZVwiPtCd0LDQv9GA0LjQvNC10YAsINGE0L7RgtC+0LPRgNCw0YTQuNGOINC/0L7QstGA0LXQttC00LXQvdC40Lkg0Lgg0LTQtdGE0YTQtdC60YLQvtCyLCDRh9GC0L4g0L/QvtGB0LvRg9C20LjRgiDQtNC+0LrQsNC30LDRgtC10LvRjNGB0YLQstC+0Lwg0L3QtdGB0L7QvtGC0LLQtdGC0YHRgtCy0LjRjyDQt9Cw0Y/QstC70LXQvdC90L7Qs9C+INC60LDRh9C10YHRgtCy0LAg0YLQvtCy0LDRgNCwLjwvcD5cbiAgICA8L2Rpdj5cbjwvZm9ybT5cbiJdfQ==
|