material-dynamic-forms
Version:
¡Crea formularios dinámicos, potentes y configurables en Angular usando Material Design! 🚀
398 lines • 62.4 kB
JavaScript
import { Injectable } from '@angular/core';
import { Validators, } from '@angular/forms';
import { HttpParams } from '@angular/common/http';
import { eDataType, eTypeMOdel, } from './interfaces';
import { getValueFromProperty, transformToObject } from './functions/functions';
import * as i0 from "@angular/core";
import * as i1 from "@angular/forms";
import * as i2 from "@angular/common/http";
export class DynamicFormService {
constructor(fb, http) {
this.fb = fb;
this.http = http;
this.baseUrl = '';
// Agregamos esta variable para almacenar los valores externos
this.externalDependenciesValues = {};
// Declarar formGroupControls como propiedad
this.formGroupControls = {};
// Variable para manejar el modo de edición
this.isEditMode = false;
this.isReadonly = false; // Add readonly flag
this.rangeValidator = (group) => {
const desde = Number(group.get('desde')?.value);
const hasta = Number(group.get('hasta')?.value);
return desde <= hasta ? null : { rangeError: true };
};
}
setBaseUrl(url) {
this.baseUrl = url;
}
// Método para establecer el modo de edición
setEditMode(isEdit) {
this.isEditMode = isEdit;
}
// Add method to set readonly
setReadonly(isReadonly) {
this.isReadonly = isReadonly;
}
// Permite setear/actualizar los valores externos desde el componente
setExternalDependenciesValues(values) {
this.externalDependenciesValues = {
...this.externalDependenciesValues,
...values,
};
}
removeExternalDependency(key) {
if (this.externalDependenciesValues.hasOwnProperty(key)) {
delete this.externalDependenciesValues[key];
}
}
functionInitComponent(fieldGroupsDynamicForm, form) {
this.formGroupControls = {};
let isRangeValidator = false;
const initializeControl = (field) => {
const initialValue = field.value !== undefined
? field.value
: field.type === eDataType.select_chips
? []
: '';
const validators = this.isReadonly ? [] : field.validation || [];
const isDisabled = this.isReadonly || !!field.dependency || field.disabled;
return this.fb.control({ value: initialValue, disabled: isDisabled }, validators);
};
const handleDependenciesValue = (field, control) => {
if (!field.valueDependency && !field.valueExcludeDependency) {
return;
}
const updateField = () => {
const depValue = field.valueDependency
? this.formGroupControls[field.valueDependency.dependency] &&
this.formGroupControls[field.valueDependency.dependency].value
: field.valueExcludeDependency
? this.formGroupControls[field.valueExcludeDependency.dependency] &&
this.formGroupControls[field.valueExcludeDependency.dependency]
.value
: undefined;
const valueComparar = field.valueDependency
? field.valueDependency.valueDep
: field.valueExcludeDependency
? field.valueExcludeDependency.valueDep
: undefined;
if (field.valueDependency && depValue === valueComparar) {
control.enable();
control.clearValidators();
control.setValidators(field.valueDependency.validation ?? []);
control.updateValueAndValidity();
}
else if (field.valueExcludeDependency && depValue !== valueComparar) {
control.enable();
control.clearValidators();
control.setValidators(field.valueExcludeDependency.validation ?? []);
control.updateValueAndValidity();
}
else {
control.disable();
control.reset();
control.clearValidators();
control.updateValueAndValidity();
}
};
if (field.valueDependency) {
this.formGroupControls[field.valueDependency.dependency].valueChanges.subscribe(updateField);
}
else if (field.valueExcludeDependency) {
this.formGroupControls[field.valueExcludeDependency.dependency].valueChanges.subscribe(updateField);
}
updateField();
};
const handleDependencies = (field, control) => {
if (!field.dependency) {
return;
}
const dependencyFields = field.dependency.split(',');
dependencyFields.forEach((depField) => {
if (!this.formGroupControls[depField]) {
this.formGroupControls[depField] = this.fb.control('', Validators.required);
}
});
const updateField = () => {
if ((field.valueDependency || field.valueExcludeDependency) &&
control.disabled) {
return;
}
const allDependenciesFilled = dependencyFields.every((depField) => this.formGroupControls[depField] &&
this.formGroupControls[depField]?.value);
if (allDependenciesFilled) {
const dependencyValue = this.formGroupControls[dependencyFields[0]].value;
if (!field.valueDependency &&
!field.valueExcludeDependency &&
field.disabled) {
control.disable();
}
else {
control.enable();
}
if (!this.isEditMode)
control.reset();
// Verificar si hay dependencias externas
const hasExternalDeps = field.externalDependencies && field.externalDependencies.length > 0;
// Aquí se unifica la lógica de obtención de datos
if (field.apiUrl && dependencyValue) {
this.fetchOptions(field, dependencyValue, hasExternalDeps);
}
}
else {
control.reset();
field.options = [];
if (!field.valueDependency && !field.valueExcludeDependency) {
control.disable();
}
}
};
dependencyFields.forEach((depField) => {
this.formGroupControls[depField].valueChanges.subscribe(updateField);
});
updateField();
};
const handleDynamicDateConstraints = (field, control) => {
if (!field.dateDependency || (!field.minDateFn && !field.maxDateFn)) {
return;
}
const dependencyField = this.formGroupControls[field.dateDependency];
if (!dependencyField) {
console.error(`El campo de dependencia ${field.dateDependency} no existe.`);
return;
}
const updateConstraints = () => {
const dependencyValue = dependencyField.value
? new Date(dependencyField.value)
: null;
if (dependencyValue) {
// Asegurarse de que la hora sea 00:00:00
dependencyValue.setHours(0, 0, 0, 0);
}
if (field.minDateFn && dependencyValue) {
const calculatedMinDate = field.minDateFn(dependencyValue);
field.minDate = calculatedMinDate;
control.setValidators([
...(control.validator ? [control.validator] : []),
Validators.min(calculatedMinDate.getTime()),
]);
}
if (field.maxDateFn && dependencyValue) {
const calculatedMaxDate = field.maxDateFn(dependencyValue);
field.maxDate = calculatedMaxDate;
control.setValidators([
...(control.validator ? [control.validator] : []),
Validators.max(calculatedMaxDate.getTime()),
]);
}
control.updateValueAndValidity();
};
dependencyField.valueChanges.subscribe(updateConstraints);
updateConstraints(); // Aplicar al inicializar
// Forzar una actualización manual del valor del campo dependiente
setTimeout(() => {
dependencyField.updateValueAndValidity();
}, 0);
};
fieldGroupsDynamicForm.forEach((group) => {
group.fields.forEach((field) => {
if (field.visible) {
// Inicializar control
const control = initializeControl(field);
// Agregar control al objeto de controles
if (field.name)
this.formGroupControls[field.name] = control;
// Agregar opciones al campo select sin dependencias
if (field.apiUrl &&
!field.urlParamDependency &&
!field.urlQueryParam &&
!field.urlEndParam) {
this.fetchOptions(field, null, false);
}
if (!this.isReadonly) {
// Manejar dependencias de values de campos internas
if (field.valueDependency || field.valueExcludeDependency)
handleDependenciesValue(field, control);
// Manejar dependencias de campos
if (field.dependency)
handleDependencies(field, control);
// Manejar dependencias de fechas
if (field.type === eDataType.date)
handleDynamicDateConstraints(field, control);
}
}
});
isRangeValidator = group.isRangeValidator ?? false;
});
form = this.fb.group(this.formGroupControls);
if (isRangeValidator)
form.setValidators(this.rangeValidator);
if (this.isEditMode) {
this.markControlsAsTouched(form);
}
if (this.isReadonly) {
form.disable(); // Disable the entire form if readonly
}
return form;
}
markControlsAsTouched(form) {
Object.keys(form.controls).forEach((key) => {
const control = form.get(key);
if (control) {
control.markAsTouched();
control.updateValueAndValidity(); // Actualiza los errores y validaciones
}
});
}
handleExternalDependenciesService(field, control) {
if (!control) {
console.warn(`Control no encontrado para el campo ${field.name}`);
return () => { };
}
const checkDependencies = () => {
// 1) Verificar dependencias externas
const depsExtOk = field.externalDependencies?.every((dep) => this.externalDependenciesValues?.[dep] !== undefined);
// 2) Verificar dependencias de formulario (field.dependency)
let depsFormOk = true;
if (field.dependency) {
const dependencyFields = field.dependency.split(',');
// Chequea que todos esos campos tengan algún valor
depsFormOk = dependencyFields.every((depField) => !!this.formGroupControls[depField]?.value);
}
// Si todo está OK, habilitar campo y llamar a la API
if (depsExtOk && depsFormOk) {
control.enable();
if (field.apiUrl) {
// Verificar si hay dependencias externas
const hasExternalDeps = field.externalDependencies && field.externalDependencies.length > 0;
// fetchOptions con "useExternalDeps = true" si hay dependencias externas
this.fetchOptions(field, undefined, hasExternalDeps);
}
}
else if (!this.isEditMode || !control.value) {
// Si no está en modo edición o el control no tiene valor, deshabilita
control.disable();
control.reset();
field.options = [];
}
// En modo edición y tiene valor, no hacer nada para mantener el valor
};
// Ejecuta inicialmente
checkDependencies();
// Retorna la función para que el componente la invoque cuando cambien las dependencias
return checkDependencies;
}
functionGetFormValue(form, fieldGroupsDynamicForm) {
let dataFilterSend = {};
fieldGroupsDynamicForm.forEach((group) => {
group.fields.forEach((fieldDynamicForm) => {
const control = form.get(fieldDynamicForm.name);
if (control) {
if (control.value !== '' && control.value !== null) {
fieldDynamicForm.active = true;
switch (fieldDynamicForm.type) {
case eDataType.select:
fieldDynamicForm.value = control.value;
if (control.value === -1) {
fieldDynamicForm.options = [
{ key: -1, value: 'TODOS' },
...fieldDynamicForm.options,
];
}
fieldDynamicForm.selectedOption =
fieldDynamicForm.options?.find((option) => option.key === control.value);
fieldDynamicForm.filterParam
? (dataFilterSend[fieldDynamicForm.filterParam] =
fieldDynamicForm.selectedOption
? fieldDynamicForm.selectedOption['key']
: null)
: (dataFilterSend[fieldDynamicForm.name] =
fieldDynamicForm.selectedOption
? transformToObject(fieldDynamicForm.selectedOption)
: null);
break;
case eDataType.date:
fieldDynamicForm.value = control.value || null;
dataFilterSend[fieldDynamicForm.name] = fieldDynamicForm.value;
break;
default:
fieldDynamicForm.value =
fieldDynamicForm.typeModel === eTypeMOdel.number
? Number(control.value)
: control.value;
//fieldDynamicForm.value = control.value;
dataFilterSend[fieldDynamicForm.name] = fieldDynamicForm.value;
break;
}
}
else {
fieldDynamicForm.active = false;
fieldDynamicForm.value = null;
dataFilterSend[fieldDynamicForm.name] = null;
}
}
});
});
return dataFilterSend;
}
buildUrlAndParams(field, dependencyValue, useExternalDeps = false) {
let url = `${this.baseUrl}${field.apiUrl}`;
let params = new HttpParams();
// 1. urlParamDependency (ej: /api/{id})
if (field.urlParamDependency && dependencyValue) {
url = url.replace(/\{.*?\}/g, dependencyValue);
}
// 2. urlQueryParam (ej: ?depField=value)
else if (field.urlQueryParam && field.dependency) {
const dependencyFields = field.dependency.split(',');
dependencyFields.forEach((depField) => {
params = params.set(depField, this.formGroupControls[depField].value);
});
}
// 3. urlEndParam (ej: /api/id)
else if (field.urlEndParam && dependencyValue) {
url = `${url}/${dependencyValue}`;
}
// 4. Agregar dependencias externas si se indica
if (useExternalDeps && field.externalDependencies) {
field.externalDependencies.forEach((dep) => {
if (this.externalDependenciesValues[dep] !== undefined) {
params = params.append(dep, this.externalDependenciesValues[dep]);
}
});
}
return { url, params };
}
fetchOptions(field, dependencyValue, useExternalDeps = false) {
if (!field.apiUrl) {
return;
}
const { url, params } = this.buildUrlAndParams(field, dependencyValue, useExternalDeps);
this.http.get(url, { params }).subscribe((res) => {
field.options = field.subscribeMap
? field.subscribeMap(res).map((item) => ({
key: item.id,
value: field.valueTOShow
? getValueFromProperty(item, field.valueTOShow)
: item.nombre || item.name,
data: item.data,
}))
: res.data.map((item) => ({
key: item.id,
value: field.valueTOShow
? item[field.valueTOShow]
: item.nombre || item.name,
data: item,
}));
field.options?.sort((a, b) => (a.value || '').localeCompare(b.value || ''));
});
}
}
DynamicFormService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DynamicFormService, deps: [{ token: i1.FormBuilder }, { token: i2.HttpClient }], target: i0.ɵɵFactoryTarget.Injectable });
DynamicFormService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DynamicFormService });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: DynamicFormService, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: i1.FormBuilder }, { type: i2.HttpClient }]; } });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZHluYW1pYy1mb3JtLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9keW5hbWljLWZvcm0vc3JjL2xpYi9keW5hbWljLWZvcm0uc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzNDLE9BQU8sRUFHTCxVQUFVLEdBR1gsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQWMsVUFBVSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDOUQsT0FBTyxFQUdMLFNBQVMsRUFHVCxVQUFVLEdBQ1gsTUFBTSxjQUFjLENBQUM7QUFDdEIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7Ozs7QUFHaEYsTUFBTSxPQUFPLGtCQUFrQjtJQWM3QixZQUFvQixFQUFlLEVBQVUsSUFBZ0I7UUFBekMsT0FBRSxHQUFGLEVBQUUsQ0FBYTtRQUFVLFNBQUksR0FBSixJQUFJLENBQVk7UUFickQsWUFBTyxHQUFXLEVBQUUsQ0FBQztRQUU3Qiw4REFBOEQ7UUFDdEQsK0JBQTBCLEdBQTJCLEVBQUUsQ0FBQztRQUVoRSw0Q0FBNEM7UUFDcEMsc0JBQWlCLEdBQXVDLEVBQUUsQ0FBQztRQUVuRSwyQ0FBMkM7UUFDbkMsZUFBVSxHQUFZLEtBQUssQ0FBQztRQUU1QixlQUFVLEdBQVksS0FBSyxDQUFDLENBQUMsb0JBQW9CO1FBc1Z6RCxtQkFBYyxHQUFnQixDQUM1QixLQUFzQixFQUNTLEVBQUU7WUFDakMsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDaEQsTUFBTSxLQUFLLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUM7WUFDaEQsT0FBTyxLQUFLLElBQUksS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO1FBQ3RELENBQUMsQ0FBQztJQTFWK0QsQ0FBQztJQUUzRCxVQUFVLENBQUMsR0FBVztRQUMzQixJQUFJLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQztJQUNyQixDQUFDO0lBRUQsNENBQTRDO0lBQ3JDLFdBQVcsQ0FBQyxNQUFlO1FBQ2hDLElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDO0lBQzNCLENBQUM7SUFFRCw2QkFBNkI7SUFDdEIsV0FBVyxDQUFDLFVBQW1CO1FBQ3BDLElBQUksQ0FBQyxVQUFVLEdBQUcsVUFBVSxDQUFDO0lBQy9CLENBQUM7SUFFRCxxRUFBcUU7SUFDOUQsNkJBQTZCLENBQUMsTUFBOEI7UUFDakUsSUFBSSxDQUFDLDBCQUEwQixHQUFHO1lBQ2hDLEdBQUcsSUFBSSxDQUFDLDBCQUEwQjtZQUNsQyxHQUFHLE1BQU07U0FDVixDQUFDO0lBQ0osQ0FBQztJQUVNLHdCQUF3QixDQUFDLEdBQVc7UUFDekMsSUFBSSxJQUFJLENBQUMsMEJBQTBCLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1lBQ3ZELE9BQU8sSUFBSSxDQUFDLDBCQUEwQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1NBQzdDO0lBQ0gsQ0FBQztJQUVELHFCQUFxQixDQUNuQixzQkFBcUMsRUFDckMsSUFBZTtRQUVmLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxFQUFFLENBQUM7UUFDNUIsSUFBSSxnQkFBZ0IsR0FBWSxLQUFLLENBQUM7UUFFdEMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLEtBQXdCLEVBQUUsRUFBRTtZQUNyRCxNQUFNLFlBQVksR0FDaEIsS0FBSyxDQUFDLEtBQUssS0FBSyxTQUFTO2dCQUN2QixDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUs7Z0JBQ2IsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLEtBQUssU0FBUyxDQUFDLFlBQVk7b0JBQ3JDLENBQUMsQ0FBQyxFQUFFO29CQUNKLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDWCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDO1lBQ2pFLE1BQU0sVUFBVSxHQUNkLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDLEtBQUssQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQztZQUMxRCxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUNwQixFQUFFLEtBQUssRUFBRSxZQUFZLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxFQUM3QyxVQUFVLENBQ1gsQ0FBQztRQUNKLENBQUMsQ0FBQztRQUVGLE1BQU0sdUJBQXVCLEdBQUcsQ0FDOUIsS0FBd0IsRUFDeEIsT0FBWSxFQUNaLEVBQUU7WUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsSUFBSSxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsRUFBRTtnQkFDM0QsT0FBTzthQUNSO1lBRUQsTUFBTSxXQUFXLEdBQUcsR0FBRyxFQUFFO2dCQUN2QixNQUFNLFFBQVEsR0FBRyxLQUFLLENBQUMsZUFBZTtvQkFDcEMsQ0FBQyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLFVBQVUsQ0FBQzt3QkFDMUQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUMsS0FBSztvQkFDOUQsQ0FBQyxDQUFDLEtBQUssQ0FBQyxzQkFBc0I7d0JBQzVCLENBQUMsQ0FBQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUFDLFVBQVUsQ0FBQzs0QkFDakUsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLENBQUM7aUNBQzVELEtBQUs7d0JBQ1IsQ0FBQyxDQUFDLFNBQVMsQ0FBQztnQkFDaEIsTUFBTSxhQUFhLEdBQUcsS0FBSyxDQUFDLGVBQWU7b0JBQ3pDLENBQUMsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLFFBQVE7b0JBQ2hDLENBQUMsQ0FBQyxLQUFLLENBQUMsc0JBQXNCO3dCQUM1QixDQUFDLENBQUMsS0FBSyxDQUFDLHNCQUFzQixDQUFDLFFBQVE7d0JBQ3ZDLENBQUMsQ0FBQyxTQUFTLENBQUM7Z0JBRWhCLElBQUksS0FBSyxDQUFDLGVBQWUsSUFBSSxRQUFRLEtBQUssYUFBYSxFQUFFO29CQUN2RCxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7b0JBQ2pCLE9BQU8sQ0FBQyxlQUFlLEVBQUUsQ0FBQztvQkFDMUIsT0FBTyxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsZUFBZSxDQUFDLFVBQVUsSUFBSSxFQUFFLENBQUMsQ0FBQztvQkFDOUQsT0FBTyxDQUFDLHNCQUFzQixFQUFFLENBQUM7aUJBQ2xDO3FCQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixJQUFJLFFBQVEsS0FBSyxhQUFhLEVBQUU7b0JBQ3JFLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztvQkFDakIsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFDO29CQUMxQixPQUFPLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLENBQUM7b0JBQ3JFLE9BQU8sQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO2lCQUNsQztxQkFBTTtvQkFDTCxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7b0JBQ2xCLE9BQU8sQ0FBQyxLQUFLLEVBQUUsQ0FBQztvQkFDaEIsT0FBTyxDQUFDLGVBQWUsRUFBRSxDQUFDO29CQUMxQixPQUFPLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztpQkFDbEM7WUFDSCxDQUFDLENBQUM7WUFFRixJQUFJLEtBQUssQ0FBQyxlQUFlLEVBQUU7Z0JBQ3pCLElBQUksQ0FBQyxpQkFBaUIsQ0FDcEIsS0FBSyxDQUFDLGVBQWUsQ0FBQyxVQUFVLENBQ2pDLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQzthQUN2QztpQkFBTSxJQUFJLEtBQUssQ0FBQyxzQkFBc0IsRUFBRTtnQkFDdkMsSUFBSSxDQUFDLGlCQUFpQixDQUNwQixLQUFLLENBQUMsc0JBQXNCLENBQUMsVUFBVSxDQUN4QyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLENBQUM7YUFDdkM7WUFFRCxXQUFXLEVBQUUsQ0FBQztRQUNoQixDQUFDLENBQUM7UUFFRixNQUFNLGtCQUFrQixHQUFHLENBQUMsS0FBd0IsRUFBRSxPQUFZLEVBQUUsRUFBRTtZQUNwRSxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRTtnQkFDckIsT0FBTzthQUNSO1lBRUQsTUFBTSxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNyRCxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRTtnQkFDcEMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxRQUFRLENBQUMsRUFBRTtvQkFDckMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsT0FBTyxDQUNoRCxFQUFFLEVBQ0YsVUFBVSxDQUFDLFFBQVEsQ0FDcEIsQ0FBQztpQkFDSDtZQUNILENBQUMsQ0FBQyxDQUFDO1lBRUgsTUFBTSxXQUFXLEdBQUcsR0FBRyxFQUFFO2dCQUN2QixJQUNFLENBQUMsS0FBSyxDQUFDLGVBQWUsSUFBSSxLQUFLLENBQUMsc0JBQXNCLENBQUM7b0JBQ3ZELE9BQU8sQ0FBQyxRQUFRLEVBQ2hCO29CQUNBLE9BQU87aUJBQ1I7Z0JBRUQsTUFBTSxxQkFBcUIsR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQ2xELENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FDWCxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDO29CQUNoQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLEVBQUUsS0FBSyxDQUMxQyxDQUFDO2dCQUVGLElBQUkscUJBQXFCLEVBQUU7b0JBQ3pCLE1BQU0sZUFBZSxHQUNuQixJQUFJLENBQUMsaUJBQWlCLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7b0JBRXBELElBQ0UsQ0FBQyxLQUFLLENBQUMsZUFBZTt3QkFDdEIsQ0FBQyxLQUFLLENBQUMsc0JBQXNCO3dCQUM3QixLQUFLLENBQUMsUUFBUSxFQUNkO3dCQUNBLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztxQkFDbkI7eUJBQU07d0JBQ0wsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO3FCQUNsQjtvQkFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVU7d0JBQUUsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO29CQUV0Qyx5Q0FBeUM7b0JBQ3pDLE1BQU0sZUFBZSxHQUNuQixLQUFLLENBQUMsb0JBQW9CLElBQUksS0FBSyxDQUFDLG9CQUFvQixDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7b0JBRXRFLGtEQUFrRDtvQkFDbEQsSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLGVBQWUsRUFBRTt3QkFDbkMsSUFBSSxDQUFDLFlBQVksQ0FBQyxLQUFLLEVBQUUsZUFBZSxFQUFFLGVBQWUsQ0FBQyxDQUFDO3FCQUM1RDtpQkFDRjtxQkFBTTtvQkFDTCxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7b0JBQ2hCLEtBQUssQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO29CQUNuQixJQUFJLENBQUMsS0FBSyxDQUFDLGVBQWUsSUFBSSxDQUFDLEtBQUssQ0FBQyxzQkFBc0IsRUFBRTt3QkFDM0QsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO3FCQUNuQjtpQkFDRjtZQUNILENBQUMsQ0FBQztZQUVGLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFO2dCQUNwQyxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxXQUFXLENBQUMsQ0FBQztZQUN2RSxDQUFDLENBQUMsQ0FBQztZQUVILFdBQVcsRUFBRSxDQUFDO1FBQ2hCLENBQUMsQ0FBQztRQUVGLE1BQU0sNEJBQTRCLEdBQUcsQ0FDbkMsS0FBd0IsRUFDeEIsT0FBWSxFQUNaLEVBQUU7WUFDRixJQUFJLENBQUMsS0FBSyxDQUFDLGNBQWMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLFNBQVMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRTtnQkFDbkUsT0FBTzthQUNSO1lBRUQsTUFBTSxlQUFlLEdBQUcsSUFBSSxDQUFDLGlCQUFpQixDQUFDLEtBQUssQ0FBQyxjQUFjLENBQUMsQ0FBQztZQUNyRSxJQUFJLENBQUMsZUFBZSxFQUFFO2dCQUNwQixPQUFPLENBQUMsS0FBSyxDQUNYLDJCQUEyQixLQUFLLENBQUMsY0FBYyxhQUFhLENBQzdELENBQUM7Z0JBQ0YsT0FBTzthQUNSO1lBRUQsTUFBTSxpQkFBaUIsR0FBRyxHQUFHLEVBQUU7Z0JBQzdCLE1BQU0sZUFBZSxHQUFnQixlQUFlLENBQUMsS0FBSztvQkFDeEQsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLENBQUM7b0JBQ2pDLENBQUMsQ0FBQyxJQUFJLENBQUM7Z0JBRVQsSUFBSSxlQUFlLEVBQUU7b0JBQ25CLHlDQUF5QztvQkFDekMsZUFBZSxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztpQkFDdEM7Z0JBRUQsSUFBSSxLQUFLLENBQUMsU0FBUyxJQUFJLGVBQWUsRUFBRTtvQkFDdEMsTUFBTSxpQkFBaUIsR0FBRyxLQUFLLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxDQUFDO29CQUMzRCxLQUFLLENBQUMsT0FBTyxHQUFHLGlCQUFpQixDQUFDO29CQUNsQyxPQUFPLENBQUMsYUFBYSxDQUFDO3dCQUNwQixHQUFHLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQzt3QkFDakQsVUFBVSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsQ0FBQztxQkFDNUMsQ0FBQyxDQUFDO2lCQUNKO2dCQUVELElBQUksS0FBSyxDQUFDLFNBQVMsSUFBSSxlQUFlLEVBQUU7b0JBQ3RDLE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDLFNBQVMsQ0FBQyxlQUFlLENBQUMsQ0FBQztvQkFDM0QsS0FBSyxDQUFDLE9BQU8sR0FBRyxpQkFBaUIsQ0FBQztvQkFDbEMsT0FBTyxDQUFDLGFBQWEsQ0FBQzt3QkFDcEIsR0FBRyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7d0JBQ2pELFVBQVUsQ0FBQyxHQUFHLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLENBQUM7cUJBQzVDLENBQUMsQ0FBQztpQkFDSjtnQkFFRCxPQUFPLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztZQUNuQyxDQUFDLENBQUM7WUFFRixlQUFlLENBQUMsWUFBWSxDQUFDLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1lBQzFELGlCQUFpQixFQUFFLENBQUMsQ0FBQyx5QkFBeUI7WUFFOUMsa0VBQWtFO1lBQ2xFLFVBQVUsQ0FBQyxHQUFHLEVBQUU7Z0JBQ2QsZUFBZSxDQUFDLHNCQUFzQixFQUFFLENBQUM7WUFDM0MsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ1IsQ0FBQyxDQUFDO1FBRUYsc0JBQXNCLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBa0IsRUFBRSxFQUFFO1lBQ3BELEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBd0IsRUFBRSxFQUFFO2dCQUNoRCxJQUFJLEtBQUssQ0FBQyxPQUFPLEVBQUU7b0JBQ2pCLHNCQUFzQjtvQkFDdEIsTUFBTSxPQUFPLEdBQUcsaUJBQWlCLENBQUMsS0FBSyxDQUFDLENBQUM7b0JBRXpDLHlDQUF5QztvQkFDekMsSUFBSSxLQUFLLENBQUMsSUFBSTt3QkFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQztvQkFFN0Qsb0RBQW9EO29CQUNwRCxJQUNFLEtBQUssQ0FBQyxNQUFNO3dCQUNaLENBQUMsS0FBSyxDQUFDLGtCQUFrQjt3QkFDekIsQ0FBQyxLQUFLLENBQUMsYUFBYTt3QkFDcEIsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUNsQjt3QkFDQSxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUM7cUJBQ3ZDO29CQUNELElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFO3dCQUNwQixvREFBb0Q7d0JBQ3BELElBQUksS0FBSyxDQUFDLGVBQWUsSUFBSSxLQUFLLENBQUMsc0JBQXNCOzRCQUN2RCx1QkFBdUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7d0JBRTFDLGlDQUFpQzt3QkFDakMsSUFBSSxLQUFLLENBQUMsVUFBVTs0QkFBRSxrQkFBa0IsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7d0JBRXpELGlDQUFpQzt3QkFDakMsSUFBSSxLQUFLLENBQUMsSUFBSSxLQUFLLFNBQVMsQ0FBQyxJQUFJOzRCQUMvQiw0QkFBNEIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7cUJBQ2hEO2lCQUNGO1lBQ0gsQ0FBQyxDQUFDLENBQUM7WUFDSCxnQkFBZ0IsR0FBRyxLQUFLLENBQUMsZ0JBQWdCLElBQUksS0FBSyxDQUFDO1FBQ3JELENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO1FBQzdDLElBQUksZ0JBQWdCO1lBQUUsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDOUQsSUFBSSxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ25CLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztTQUNsQztRQUVELElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRTtZQUNuQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxzQ0FBc0M7U0FDdkQ7UUFFRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxxQkFBcUIsQ0FBQyxJQUFlO1FBQ25DLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1lBQ3pDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDOUIsSUFBSSxPQUFPLEVBQUU7Z0JBQ1gsT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFDO2dCQUN4QixPQUFPLENBQUMsc0JBQXNCLEVBQUUsQ0FBQyxDQUFDLHVDQUF1QzthQUMxRTtRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVNLGlDQUFpQyxDQUN0QyxLQUF3QixFQUN4QixPQUF3QjtRQUV4QixJQUFJLENBQUMsT0FBTyxFQUFFO1lBQ1osT0FBTyxDQUFDLElBQUksQ0FBQyx1Q0FBdUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7WUFDbEUsT0FBTyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7U0FDbEI7UUFFRCxNQUFNLGlCQUFpQixHQUFHLEdBQUcsRUFBRTtZQUM3QixxQ0FBcUM7WUFDckMsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLG9CQUFvQixFQUFFLEtBQUssQ0FDakQsQ0FBQyxHQUFHLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQywwQkFBMEIsRUFBRSxDQUFDLEdBQUcsQ0FBQyxLQUFLLFNBQVMsQ0FDOUQsQ0FBQztZQUVGLDZEQUE2RDtZQUM3RCxJQUFJLFVBQVUsR0FBRyxJQUFJLENBQUM7WUFDdEIsSUFBSSxLQUFLLENBQUMsVUFBVSxFQUFFO2dCQUNwQixNQUFNLGdCQUFnQixHQUFHLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUNyRCxtREFBbUQ7Z0JBQ25ELFVBQVUsR0FBRyxnQkFBZ0IsQ0FBQyxLQUFLLENBQ2pDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxFQUFFLEtBQUssQ0FDeEQsQ0FBQzthQUNIO1lBRUQscURBQXFEO1lBQ3JELElBQUksU0FBUyxJQUFJLFVBQVUsRUFBRTtnQkFDM0IsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUNqQixJQUFJLEtBQUssQ0FBQyxNQUFNLEVBQUU7b0JBQ2hCLHlDQUF5QztvQkFDekMsTUFBTSxlQUFlLEdBQ25CLEtBQUssQ0FBQyxvQkFBb0IsSUFBSSxLQUFLLENBQUMsb0JBQW9CLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztvQkFDdEUseUVBQXlFO29CQUN6RSxJQUFJLENBQUMsWUFBWSxDQUFDLEtBQUssRUFBRSxTQUFTLEVBQUUsZUFBZSxDQUFDLENBQUM7aUJBQ3REO2FBQ0Y7aUJBQU0sSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFO2dCQUM3QyxzRUFBc0U7Z0JBQ3RFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDbEIsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNoQixLQUFLLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQzthQUNwQjtZQUNELHNFQUFzRTtRQUN4RSxDQUFDLENBQUM7UUFFRix1QkFBdUI7UUFDdkIsaUJBQWlCLEVBQUUsQ0FBQztRQUVwQix1RkFBdUY7UUFDdkYsT0FBTyxpQkFBaUIsQ0FBQztJQUMzQixDQUFDO0lBVUQsb0JBQW9CLENBQ2xCLElBQWUsRUFDZixzQkFBcUM7UUFFckMsSUFBSSxjQUFjLEdBQWEsRUFBYyxDQUFDO1FBRTlDLHNCQUFzQixDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ3ZDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsZ0JBQWdCLEVBQUUsRUFBRTtnQkFDeEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFLLENBQUMsQ0FBQztnQkFFakQsSUFBSSxPQUFPLEVBQUU7b0JBQ1gsSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLEVBQUUsSUFBSSxPQUFPLENBQUMsS0FBSyxLQUFLLElBQUksRUFBRTt3QkFDbEQsZ0JBQWdCLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQzt3QkFFL0IsUUFBUSxnQkFBZ0IsQ0FBQyxJQUFJLEVBQUU7NEJBQzdCLEtBQUssU0FBUyxDQUFDLE1BQU07Z0NBQ25CLGdCQUFnQixDQUFDLEtBQUssR0FBRyxPQUFPLENBQUMsS0FBSyxDQUFDO2dDQUN2QyxJQUFJLE9BQU8sQ0FBQyxLQUFLLEtBQUssQ0FBQyxDQUFDLEVBQUU7b0NBQ3hCLGdCQUFnQixDQUFDLE9BQU8sR0FBRzt3Q0FDekIsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLE9BQU8sRUFBRTt3Q0FDM0IsR0FBRyxnQkFBZ0IsQ0FBQyxPQUFRO3FDQUM3QixDQUFDO2lDQUNIO2dDQUNELGdCQUFnQixDQUFDLGNBQWM7b0NBQzdCLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxJQUFJLENBQzVCLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsR0FBRyxLQUFLLE9BQU8sQ0FBQyxLQUFLLENBQ3pDLENBQUM7Z0NBQ0osZ0JBQWdCLENBQUMsV0FBWTtvQ0FDM0IsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLGdCQUFnQixDQUFDLFdBQVksQ0FBQzt3Q0FDOUMsZ0JBQWdCLENBQUMsY0FBYzs0Q0FDN0IsQ0FBQyxDQUFFLGdCQUFnQixDQUFDLGNBQWMsQ0FDaEMsS0FBSyxDQUNhOzRDQUNwQixDQUFDLENBQUMsSUFBSSxDQUFDO29DQUNYLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFLLENBQUM7d0NBQ3ZDLGdCQUFnQixDQUFDLGNBQWM7NENBQzdCLENBQUMsQ0FBQyxpQkFBaUIsQ0FDakIsZ0JBQWdCLENBQUMsY0FBZ0MsQ0FDbEQ7NENBQ0QsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO2dDQUNkLE1BQU07NEJBQ1IsS0FBSyxTQUFTLENBQUMsSUFBSTtnQ0FDakIsZ0JBQWdCLENBQUMsS0FBSyxHQUFHLE9BQU8sQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDO2dDQUMvQyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsSUFBSyxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDO2dDQUNoRSxNQUFNOzRCQUNSO2dDQUNFLGdCQUFnQixDQUFDLEtBQUs7b0NBQ3BCLGdCQUFnQixDQUFDLFNBQVMsS0FBSyxVQUFVLENBQUMsTUFBTTt3Q0FDOUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDO3dDQUN2QixDQUFDLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztnQ0FDcEIseUNBQXlDO2dDQUN6QyxjQUFjLENBQUMsZ0JBQWdCLENBQUMsSUFBSyxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsS0FBSyxDQUFDO2dDQUNoRSxNQUFNO3lCQUNUO3FCQUNGO3lCQUFNO3dCQUNMLGdCQUFnQixDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7d0JBQ2hDLGdCQUFnQixDQUFDLEtBQUssR0FBRyxJQUFJLENBQUM7d0JBQzlCLGNBQWMsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFLLENBQUMsR0FBRyxJQUFJLENBQUM7cUJBQy9DO2lCQUNGO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDLENBQUMsQ0FBQztRQUVILE9BQU8sY0FBYyxDQUFDO0lBQ3hCLENBQUM7SUFFTyxpQkFBaUIsQ0FDdkIsS0FBd0IsRUFDeEIsZUFBcUIsRUFDckIsa0JBQTJCLEtBQUs7UUFFaEMsSUFBSSxHQUFHLEdBQUcsR0FBRyxJQUFJLENBQUMsT0FBTyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUMzQyxJQUFJLE1BQU0sR0FBRyxJQUFJLFVBQVUsRUFBRSxDQUFDO1FBRTlCLHdDQUF3QztRQUN4QyxJQUFJLEtBQUssQ0FBQyxrQkFBa0IsSUFBSSxlQUFlLEVBQUU7WUFDL0MsR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLGVBQWUsQ0FBQyxDQUFDO1NBQ2hEO1FBQ0QseUNBQXlDO2FBQ3BDLElBQUksS0FBSyxDQUFDLGFBQWEsSUFBSSxLQUFLLENBQUMsVUFBVSxFQUFFO1lBQ2hELE1BQU0sZ0JBQWdCLEdBQUcsS0FBSyxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDckQsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7Z0JBQ3BDLE1BQU0sR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsaUJBQWlCLENBQUMsUUFBUSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDeEUsQ0FBQyxDQUFDLENBQUM7U0FDSjtRQUNELCtCQUErQjthQUMxQixJQUFJLEtBQUssQ0FBQyxXQUFXLElBQUksZUFBZSxFQUFFO1lBQzdDLEdBQUcsR0FBRyxHQUFHLEdBQUcsSUFBSSxlQUFlLEVBQUUsQ0FBQztTQUNuQztRQUVELGdEQUFnRDtRQUNoRCxJQUFJLGVBQWUsSUFBSSxLQUFLLENBQUMsb0JBQW9CLEVBQUU7WUFDakQsS0FBSyxDQUFDLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO2dCQUN6QyxJQUFJLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxHQUFHLENBQUMsS0FBSyxTQUFTLEVBQUU7b0JBQ3RELE1BQU0sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLEdBQUcsRUFBRSxJQUFJLENBQUMsMEJBQTBCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztpQkFDbkU7WUFDSCxDQUFDLENBQUMsQ0FBQztTQUNKO1FBRUQsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRU8sWUFBWSxDQUNsQixLQUF3QixFQUN4QixlQUFxQixFQUNyQixrQkFBMkIsS0FBSztRQUVoQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRTtZQUNqQixPQUFPO1NBQ1I7UUFFRCxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FDNUMsS0FBSyxFQUNMLGVBQWUsRUFDZixlQUFlLENBQ2hCLENBQUM7UUFFRixJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEdBQVEsRUFBRSxFQUFFO1lBQ3BELEtBQUssQ0FBQyxPQUFPLEdBQUcsS0FBSyxDQUFDLFlBQVk7Z0JBQ2hDLENBQUMsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQVMsRUFBRSxFQUFFLENBQUMsQ0FBQztvQkFDNUMsR0FBRyxFQUFFLElBQUksQ0FBQyxFQUFFO29CQUNaLEtBQUssRUFBRSxLQUFLLENBQUMsV0FBVzt3QkFDdEIsQ0FBQyxDQUFDLG9CQUFvQixDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsV0FBVyxDQUFDO3dCQUMvQyxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsSUFBSTtvQkFDNUIsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJO2lCQUNoQixDQUFDLENBQUM7Z0JBQ0gsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBUyxFQUFFLEVBQUUsQ0FBQyxDQUFDO29CQUM3QixHQUFHLEVBQUUsSUFBSSxDQUFDLEVBQUU7b0JBQ1osS0FBSyxFQUFFLEtBQUssQ0FBQyxXQUFXO3dCQUN0QixDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUM7d0JBQ3pCLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxJQUFJO29CQUM1QixJQUFJLEVBQUUsSUFBSTtpQkFDWCxDQUFDLENBQUMsQ0FBQztZQUNOLEtBQUssQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQzNCLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FDN0MsQ0FBQztRQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQzs7K0dBbmZVLGtCQUFrQjttSEFBbEIsa0JBQWtCOzJGQUFsQixrQkFBa0I7a0JBRDlCLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgRm9ybUJ1aWxkZXIsXHJcbiAgRm9ybUdyb3VwLFxyXG4gIFZhbGlkYXRvcnMsXHJcbiAgQWJzdHJhY3RDb250cm9sLFxyXG4gIFZhbGlkYXRvckZuLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgSHR0cENsaWVudCwgSHR0cFBhcmFtcyB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbi9odHRwJztcclxuaW1wb3J0IHtcclxuICBJRmllbGRHcm91cCxcclxuICBJRmllbGREeW5hbWljRm9ybSxcclxuICBlRGF0YVR5cGUsXHJcbiAgS2V5VmFsdWUsXHJcbiAgT2JqZWN0S2V5VmFsdWUsXHJcbiAgZVR5cGVNT2RlbCxcclxufSBmcm9tICcuL2ludGVyZmFjZXMnO1xyXG5pbXBvcnQgeyBnZXRWYWx1ZUZyb21Qcm9wZXJ0eSwgdHJhbnNmb3JtVG9PYmplY3QgfSBmcm9tICcuL2Z1bmN0aW9ucy9mdW5jdGlvbnMnO1xyXG5cclxuQEluamVjdGFibGUoKVxyXG5leHBvcnQgY2xhc3MgRHluYW1pY0Zvcm1TZXJ2aWNlIHtcclxuICBwcml2YXRlIGJhc2VVcmw6IHN0cmluZyA9ICcnO1xyXG5cclxuICAvLyBBZ3JlZ2Ftb3MgZXN0YSB2YXJpYWJsZSBwYXJhIGFsbWFjZW5hciBsb3MgdmFsb3JlcyBleHRlcm5vc1xyXG4gIHByaXZhdGUgZXh0ZXJuYWxEZXBlbmRlbmNpZXNWYWx1ZXM6IHsgW2tleTogc3RyaW5nXTogYW55IH0gPSB7fTtcclxuXHJcbiAgLy8gRGVjbGFyYXIgZm9ybUdyb3VwQ29udHJvbHMgY29tbyBwcm9waWVkYWRcclxuICBwcml2YXRlIGZvcm1Hcm91cENvbnRyb2xzOiB7IFtrZXk6IHN0cmluZ106IEFic3RyYWN0Q29udHJvbCB9ID0ge307XHJcblxyXG4gIC8vIFZhcmlhYmxlIHBhcmEgbWFuZWphciBlbCBtb2RvIGRlIGVkaWNpw7NuXHJcbiAgcHJpdmF0ZSBpc0VkaXRNb2RlOiBib29sZWFuID0gZmFsc2U7XHJcblxyXG4gIHByaXZhdGUgaXNSZWFkb25seTogYm9vbGVhbiA9IGZhbHNlOyAvLyBBZGQgcmVhZG9ubHkgZmxhZ1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZiOiBGb3JtQnVpbGRlciwgcHJpdmF0ZSBodHRwOiBIdHRwQ2xpZW50KSB7IH1cclxuXHJcbiAgcHVibGljIHNldEJhc2VVcmwodXJsOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIHRoaXMuYmFzZVVybCA9IHVybDtcclxuICB9XHJcblxyXG4gIC8vIE3DqXRvZG8gcGFyYSBlc3RhYmxlY2VyIGVsIG1vZG8gZGUgZWRpY2nDs25cclxuICBwdWJsaWMgc2V0RWRpdE1vZGUoaXNFZGl0OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzRWRpdE1vZGUgPSBpc0VkaXQ7XHJcbiAgfVxyXG5cclxuICAvLyBBZGQgbWV0aG9kIHRvIHNldCByZWFkb25seVxyXG4gIHB1YmxpYyBzZXRSZWFkb25seShpc1JlYWRvbmx5OiBib29sZWFuKTogdm9pZCB7XHJcbiAgICB0aGlzLmlzUmVhZG9ubHkgPSBpc1JlYWRvbmx5O1xyXG4gIH1cclxuXHJcbiAgLy8gUGVybWl0ZSBzZXRlYXIvYWN0dWFsaXphciBsb3MgdmFsb3JlcyBleHRlcm5vcyBkZXNkZSBlbCBjb21wb25lbnRlXHJcbiAgcHVibGljIHNldEV4dGVybmFsRGVwZW5kZW5jaWVzVmFsdWVzKHZhbHVlczogeyBba2V5OiBzdHJpbmddOiBhbnkgfSk6IHZvaWQge1xyXG4gICAgdGhpcy5leHRlcm5hbERlcGVuZGVuY2llc1ZhbHVlcyA9IHtcclxuICAgICAgLi4udGhpcy5leHRlcm5hbERlcGVuZGVuY2llc1ZhbHVlcyxcclxuICAgICAgLi4udmFsdWVzLFxyXG4gICAgfTtcclxuICB9XHJcblxyXG4gIHB1YmxpYyByZW1vdmVFeHRlcm5hbERlcGVuZGVuY3koa2V5OiBzdHJpbmcpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLmV4dGVybmFsRGVwZW5kZW5jaWVzVmFsdWVzLmhhc093blByb3BlcnR5KGtleSkpIHtcclxuICAgICAgZGVsZXRlIHRoaXMuZXh0ZXJuYWxEZXBlbmRlbmNpZXNWYWx1ZXNba2V5XTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGZ1bmN0aW9uSW5pdENvbXBvbmVudChcclxuICAgIGZpZWxkR3JvdXBzRHluYW1pY0Zvcm06IElGaWVsZEdyb3VwW10sXHJcbiAgICBmb3JtOiBGb3JtR3JvdXBcclxuICApOiBGb3JtR3JvdXAge1xyXG4gICAgdGhpcy5mb3JtR3JvdXBDb250cm9scyA9IHt9O1xyXG4gICAgbGV0IGlzUmFuZ2VWYWxpZGF0b3I6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgICBjb25zdCBpbml0aWFsaXplQ29udHJvbCA9IChmaWVsZDogSUZpZWxkRHluYW1pY0Zvcm0pID0+IHtcclxuICAgICAgY29uc3QgaW5pdGlhbFZhbHVlID1cclxuICAgICAgICBmaWVsZC52YWx1ZSAhPT0gdW5kZWZpbmVkXHJcbiAgICAgICAgICA/IGZpZWxkLnZhbHVlXHJcbiAgICAgICAgICA6IGZpZWxkLnR5cGUgPT09IGVEYXRhVHlwZS5zZWxlY3RfY2hpcHNcclxuICAgICAgICAgICAgPyBbXVxyXG4gICAgICAgICAgICA6ICcnO1xyXG4gICAgICBjb25zdCB2YWxpZGF0b3JzID0gdGhpcy5pc1JlYWRvbmx5ID8gW10gOiBmaWVsZC52YWxpZGF0aW9uIHx8IFtdO1xyXG4gICAgICBjb25zdCBpc0Rpc2FibGVkID1cclxuICAgICAgICB0aGlzLmlzUmVhZG9ubHkgfHwgISFmaWVsZC5kZXBlbmRlbmN5IHx8IGZpZWxkLmRpc2FibGVkO1xyXG4gICAgICByZXR1cm4gdGhpcy5mYi5jb250cm9sKFxyXG4gICAgICAgIHsgdmFsdWU6IGluaXRpYWxWYWx1ZSwgZGlzYWJsZWQ6IGlzRGlzYWJsZWQgfSxcclxuICAgICAgICB2YWxpZGF0b3JzXHJcbiAgICAgICk7XHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGhhbmRsZURlcGVuZGVuY2llc1ZhbHVlID0gKFxyXG4gICAgICBmaWVsZDogSUZpZWxkRHluYW1pY0Zvcm0sXHJcbiAgICAgIGNvbnRyb2w6IGFueVxyXG4gICAgKSA9PiB7XHJcbiAgICAgIGlmICghZmllbGQudmFsdWVEZXBlbmRlbmN5ICYmICFmaWVsZC52YWx1ZUV4Y2x1ZGVEZXBlbmRlbmN5KSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVGaWVsZCA9ICgpID0+IHtcclxuICAgICAgICBjb25zdCBkZXBWYWx1ZSA9IGZpZWxkLnZhbHVlRGVwZW5kZW5jeVxyXG4gICAgICAgICAgPyB0aGlzLmZvcm1Hcm91cENvbnRyb2xzW2ZpZWxkLnZhbHVlRGVwZW5kZW5jeS5kZXBlbmRlbmN5XSAmJlxyXG4gICAgICAgICAgdGhpcy5mb3JtR3JvdXBDb250cm9sc1tmaWVsZC52YWx1ZURlcGVuZGVuY3kuZGVwZW5kZW5jeV0udmFsdWVcclxuICAgICAgICAgIDogZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeVxyXG4gICAgICAgICAgICA/IHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeS5kZXBlbmRlbmN5XSAmJlxyXG4gICAgICAgICAgICB0aGlzLmZvcm1Hcm91cENvbnRyb2xzW2ZpZWxkLnZhbHVlRXhjbHVkZURlcGVuZGVuY3kuZGVwZW5kZW5jeV1cclxuICAgICAgICAgICAgICAudmFsdWVcclxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XHJcbiAgICAgICAgY29uc3QgdmFsdWVDb21wYXJhciA9IGZpZWxkLnZhbHVlRGVwZW5kZW5jeVxyXG4gICAgICAgICAgPyBmaWVsZC52YWx1ZURlcGVuZGVuY3kudmFsdWVEZXBcclxuICAgICAgICAgIDogZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeVxyXG4gICAgICAgICAgICA/IGZpZWxkLnZhbHVlRXhjbHVkZURlcGVuZGVuY3kudmFsdWVEZXBcclxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XHJcblxyXG4gICAgICAgIGlmIChmaWVsZC52YWx1ZURlcGVuZGVuY3kgJiYgZGVwVmFsdWUgPT09IHZhbHVlQ29tcGFyYXIpIHtcclxuICAgICAgICAgIGNvbnRyb2wuZW5hYmxlKCk7XHJcbiAgICAgICAgICBjb250cm9sLmNsZWFyVmFsaWRhdG9ycygpO1xyXG4gICAgICAgICAgY29udHJvbC5zZXRWYWxpZGF0b3JzKGZpZWxkLnZhbHVlRGVwZW5kZW5jeS52YWxpZGF0aW9uID8/IFtdKTtcclxuICAgICAgICAgIGNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeSAmJiBkZXBWYWx1ZSAhPT0gdmFsdWVDb21wYXJhcikge1xyXG4gICAgICAgICAgY29udHJvbC5lbmFibGUoKTtcclxuICAgICAgICAgIGNvbnRyb2wuY2xlYXJWYWxpZGF0b3JzKCk7XHJcbiAgICAgICAgICBjb250cm9sLnNldFZhbGlkYXRvcnMoZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeS52YWxpZGF0aW9uID8/IFtdKTtcclxuICAgICAgICAgIGNvbnRyb2wudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb250cm9sLmRpc2FibGUoKTtcclxuICAgICAgICAgIGNvbnRyb2wucmVzZXQoKTtcclxuICAgICAgICAgIGNvbnRyb2wuY2xlYXJWYWxpZGF0b3JzKCk7XHJcbiAgICAgICAgICBjb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICAgICAgICB9XHJcbiAgICAgIH07XHJcblxyXG4gICAgICBpZiAoZmllbGQudmFsdWVEZXBlbmRlbmN5KSB7XHJcbiAgICAgICAgdGhpcy5mb3JtR3JvdXBDb250cm9sc1tcclxuICAgICAgICAgIGZpZWxkLnZhbHVlRGVwZW5kZW5jeS5kZXBlbmRlbmN5XHJcbiAgICAgICAgXS52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHVwZGF0ZUZpZWxkKTtcclxuICAgICAgfSBlbHNlIGlmIChmaWVsZC52YWx1ZUV4Y2x1ZGVEZXBlbmRlbmN5KSB7XHJcbiAgICAgICAgdGhpcy5mb3JtR3JvdXBDb250cm9sc1tcclxuICAgICAgICAgIGZpZWxkLnZhbHVlRXhjbHVkZURlcGVuZGVuY3kuZGVwZW5kZW5jeVxyXG4gICAgICAgIF0udmFsdWVDaGFuZ2VzLnN1YnNjcmliZSh1cGRhdGVGaWVsZCk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHVwZGF0ZUZpZWxkKCk7XHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGhhbmRsZURlcGVuZGVuY2llcyA9IChmaWVsZDogSUZpZWxkRHluYW1pY0Zvcm0sIGNvbnRyb2w6IGFueSkgPT4ge1xyXG4gICAgICBpZiAoIWZpZWxkLmRlcGVuZGVuY3kpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGRlcGVuZGVuY3lGaWVsZHMgPSBmaWVsZC5kZXBlbmRlbmN5LnNwbGl0KCcsJyk7XHJcbiAgICAgIGRlcGVuZGVuY3lGaWVsZHMuZm9yRWFjaCgoZGVwRmllbGQpID0+IHtcclxuICAgICAgICBpZiAoIXRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwRmllbGRdKSB7XHJcbiAgICAgICAgICB0aGlzLmZvcm1Hcm91cENvbnRyb2xzW2RlcEZpZWxkXSA9IHRoaXMuZmIuY29udHJvbChcclxuICAgICAgICAgICAgJycsXHJcbiAgICAgICAgICAgIFZhbGlkYXRvcnMucmVxdWlyZWRcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIGNvbnN0IHVwZGF0ZUZpZWxkID0gKCkgPT4ge1xyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgIChmaWVsZC52YWx1ZURlcGVuZGVuY3kgfHwgZmllbGQudmFsdWVFeGNsdWRlRGVwZW5kZW5jeSkgJiZcclxuICAgICAgICAgIGNvbnRyb2wuZGlzYWJsZWRcclxuICAgICAgICApIHtcclxuICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGFsbERlcGVuZGVuY2llc0ZpbGxlZCA9IGRlcGVuZGVuY3lGaWVsZHMuZXZlcnkoXHJcbiAgICAgICAgICAoZGVwRmllbGQpID0+XHJcbiAgICAgICAgICAgIHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwRmllbGRdICYmXHJcbiAgICAgICAgICAgIHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwRmllbGRdPy52YWx1ZVxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIGlmIChhbGxEZXBlbmRlbmNpZXNGaWxsZWQpIHtcclxuICAgICAgICAgIGNvbnN0IGRlcGVuZGVuY3lWYWx1ZSA9XHJcbiAgICAgICAgICAgIHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwZW5kZW5jeUZpZWxkc1swXV0udmFsdWU7XHJcblxyXG4gICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAhZmllbGQudmFsdWVEZXBlbmRlbmN5ICYmXHJcbiAgICAgICAgICAgICFmaWVsZC52YWx1ZUV4Y2x1ZGVEZXBlbmRlbmN5ICYmXHJcbiAgICAgICAgICAgIGZpZWxkLmRpc2FibGVkXHJcbiAgICAgICAgICApIHtcclxuICAgICAgICAgICAgY29udHJvbC5kaXNhYmxlKCk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb250cm9sLmVuYWJsZSgpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgaWYgKCF0aGlzLmlzRWRpdE1vZGUpIGNvbnRyb2wucmVzZXQoKTtcclxuXHJcbiAgICAgICAgICAvLyBWZXJpZmljYXIgc2kgaGF5IGRlcGVuZGVuY2lhcyBleHRlcm5hc1xyXG4gICAgICAgICAgY29uc3QgaGFzRXh0ZXJuYWxEZXBzID1cclxuICAgICAgICAgICAgZmllbGQuZXh0ZXJuYWxEZXBlbmRlbmNpZXMgJiYgZmllbGQuZXh0ZXJuYWxEZXBlbmRlbmNpZXMubGVuZ3RoID4gMDtcclxuXHJcbiAgICAgICAgICAvLyBBcXXDrSBzZSB1bmlmaWNhIGxhIGzDs2dpY2EgZGUgb2J0ZW5jacOzbiBkZSBkYXRvc1xyXG4gICAgICAgICAgaWYgKGZpZWxkLmFwaVVybCAmJiBkZXBlbmRlbmN5VmFsdWUpIHtcclxuICAgICAgICAgICAgdGhpcy5mZXRjaE9wdGlvbnMoZmllbGQsIGRlcGVuZGVuY3lWYWx1ZSwgaGFzRXh0ZXJuYWxEZXBzKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY29udHJvbC5yZXNldCgpO1xyXG4gICAgICAgICAgZmllbGQub3B0aW9ucyA9IFtdO1xyXG4gICAgICAgICAgaWYgKCFmaWVsZC52YWx1ZURlcGVuZGVuY3kgJiYgIWZpZWxkLnZhbHVlRXhjbHVkZURlcGVuZGVuY3kpIHtcclxuICAgICAgICAgICAgY29udHJvbC5kaXNhYmxlKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9O1xyXG5cclxuICAgICAgZGVwZW5kZW5jeUZpZWxkcy5mb3JFYWNoKChkZXBGaWVsZCkgPT4ge1xyXG4gICAgICAgIHRoaXMuZm9ybUdyb3VwQ29udHJvbHNbZGVwRmllbGRdLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUodXBkYXRlRmllbGQpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIHVwZGF0ZUZpZWxkKCk7XHJcbiAgICB9O1xyXG5cclxuICAgIGNvbnN0IGhhbmRsZUR5bmFtaWNEYXRlQ29uc3RyYWludHMgPSAoXHJcbiAgICAgIGZpZWxkOiBJRmllbGREeW5hbWljRm9ybSxcclxuICAgICAgY29udHJvbDogYW55XHJcbiAgICApID0+IHtcclxuICAgICAgaWYgKCFmaWVsZC5kYXRlRGVwZW5kZW5jeSB8fCAoIWZpZWxkLm1pbkRhdGVGbiAmJiAhZmllbGQubWF4RGF0ZUZuKSkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgZGVwZW5kZW5jeUZpZWxkID0gdGhpcy5mb3JtR3JvdXBDb250cm9sc1tmaWVsZC5kYXRlRGVwZW5kZW5jeV07XHJcbiAgICAgIGlmICghZGVwZW5kZW5jeUZpZWxkKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcihcclxuICAgICAgICAgIGBFbCBjYW1wbyBkZSBkZXBlbmRlbmNpYSAke2ZpZWxkLmRhdGVEZXBlbmRlbmN5fSBubyBleGlzdGUuYFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCB1cGRhdGVDb25zdHJhaW50cyA9ICgpID0+IHtcclxuICAgICAgICBjb25zdCBkZXBlbmRlbmN5VmFsdWU6IERhdGUgfCBudWxsID0gZGVwZW5kZW5jeUZpZWxkLnZhbHVlXHJcbiAgICAgICAgICA/IG5ldyBEYXRlKGRlcGVuZGVuY3lGaWVsZC52YWx1ZSlcclxuICAgICAgICAgIDogbnVsbDtcclxuXHJcbiAgICAgICAgaWYgKGRlcGVuZGVuY3lWYWx1ZSkge1xyXG4gICAgICAgICAgLy8gQXNlZ3VyYXJzZSBkZSBxdWUgbGEgaG9yYSBzZWEgMDA6MDA6MDBcclxuICAgICAgICAgIGRlcGVuZGVuY3lWYWx1ZS5zZXRIb3VycygwLCAwLCAwLCAwKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChmaWVsZC5taW5EYXRlRm4gJiYgZGVwZW5kZW5jeVZhbHVlKSB7XHJcbiAgICAgICAgICBjb25zdCBjYWxjdWxhdGVkTWluRGF0ZSA9IGZpZWxkLm1pbkRhdGVGbihkZXBlbmRlbmN5VmFsdWUpO1xyXG4gICAgICAgICAgZmllbGQubWluRGF0ZSA9IGNhbGN1bGF0ZWRNaW5EYXRlO1xyXG4gICAgICAgICAgY29udHJvbC5zZXRWYWxpZGF0b3JzKFtcclxuICAgICAgICAgICAgLi4uKGNvbnRyb2wudmFsaWRhdG9yID8gW2NvbnRyb2wudmFsaWRhdG9yXSA6IFtdKSxcclxuICAgICAgICAgICAgVmFsaWRhdG9ycy5taW4oY2FsY3VsYXRlZE1pbkRhdGUuZ2V0VGltZSgpKSxcclxuICAgICAgICAgIF0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGZpZWxkLm1heERhdGVGbiAmJiBkZXBlbmRlbmN5VmFsdWUpIHtcclxuICAgICAgICAgIGNvbnN0IGNhbGN1bGF0ZWRNYXhEYXRlID0gZmllbGQubWF4RGF0ZUZuKGRlcGVuZGVuY3lWYWx1ZSk7XHJcbiAgICAgICAgICBmaWVsZC5tYXhEYXRlID0gY2FsY3VsYXRlZE1heERhdGU7XHJcbiAgICAgICAgICBjb250cm9sLnNldFZhbGlkYXRvcnMoW1xyXG4gICAgICAgICAgICAuLi4oY29udHJvbC52YWxpZGF0b3IgPyBbY29udHJvbC52YWxpZGF0b3JdIDogW10pLFxyXG4gICAgICAgICAgICBWYWxpZGF0b3JzLm1heChjYWxjdWxhdGVkTWF4RGF0ZS5nZXRUaW1lKCkpLFxyXG4gICAgICAgICAgXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb250cm9sLnVwZGF0ZVZhbHVlQW5kVmFsaWRpdHkoKTtcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGRlcGVuZGVuY3lGaWVsZC52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKHVwZGF0ZUNvbnN0cmFpbnRzKTtcclxuICAgICAgdXBkYXRlQ29uc3RyYWludHMoKTsgLy8gQXBsaWNhciBhbCBpbmljaWFsaXphclxyXG5cclxuICAgICAgLy8gRm9yemFyIHVuYSBhY3R1YWxpemFjacOzbiBtYW51YWwgZGVsIHZhbG9yIGRlbCBjYW1wbyBkZXBlbmRpZW50ZVxyXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICBkZXBlbmRlbmN5RmllbGQudXBkYXRlVmFsdWVBbmRWYWxpZGl0eSgpO1xyXG4gICAgICB9LCAwKTtcclxuICAgIH07XHJcblxyXG4gICAgZmllbGRHcm91cHNEeW5hbWljRm9ybS5mb3JFYWNoKChncm91cDogSUZpZWxkR3JvdXApID0+IHtcclxuICAgICAgZ3JvdXAuZmllbGRzLmZvckVhY