"use strict";
(self["webpackChunkramsey_plus_forms"] = self["webpackChunkramsey_plus_forms"] || []).push([[428],{
/***/ 7930:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ A: () => (/* binding */ Component)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6540);
/* harmony import */ var classnames__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6942);
/* harmony import */ var classnames__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(classnames__WEBPACK_IMPORTED_MODULE_1__);
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol, Iterator */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
var getConditionalProps = function (disabled, isLink, href) { return ({
href: !disabled ? href : undefined,
"aria-disabled": (isLink && disabled) || undefined,
disabled: !isLink && disabled,
}); };
var getLinkIconProps = function (iconPosition) {
var _a;
var iconClasses = classnames__WEBPACK_IMPORTED_MODULE_1___default()("rds-Link-icon", "rds-Link-icon--".concat(iconPosition));
return _a = {
fill: "currentColor",
className: iconClasses
},
_a["aria-hidden"] = true,
_a.focusable = false,
_a;
};
function Link(_a, ref) {
var _b;
var children = _a.children, className = _a.className, disabled = _a.disabled, element = _a.element, href = _a.href, LinkIcon = _a.icon, _c = _a.iconPosition, iconPosition = _c === void 0 ? "left" : _c, _d = _a.inheritColor, inheritColor = _d === void 0 ? false : _d, _e = _a.isOnDarkCanvas, isOnDarkCanvas = _e === void 0 ? false : _e, _f = _a.size, size = _f === void 0 ? "medium" : _f, text = _a.text, rest = __rest(_a, ["children", "className", "disabled", "element", "href", "icon", "iconPosition", "inheritColor", "isOnDarkCanvas", "size", "text"]);
var isLink = element !== "button";
var Element = element || "a";
var linkClasses = classnames__WEBPACK_IMPORTED_MODULE_1___default()("rds-Link", (_b = {},
_b["rds-Link--".concat(size)] = size !== "medium",
_b["rds-Link--inheritColor"] = inheritColor,
_b["is-disabled"] = isLink && disabled,
_b["on-darkCanvas"] = isOnDarkCanvas,
_b), className);
return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(Element, __assign({ className: linkClasses }, getConditionalProps(disabled, isLink, href), rest, { ref: ref }),
LinkIcon && iconPosition === "left" && (react__WEBPACK_IMPORTED_MODULE_0__.createElement(LinkIcon, __assign({}, getLinkIconProps(iconPosition)))),
children || text,
LinkIcon && iconPosition === "right" && (react__WEBPACK_IMPORTED_MODULE_0__.createElement(LinkIcon, __assign({}, getLinkIconProps(iconPosition))))));
}
var Component = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(Link);
Component.displayName = "Link";
//# sourceMappingURL=Link.esm.js.map
/***/ }),
/***/ 9785:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ mN: () => (/* binding */ useForm)
/* harmony export */ });
/* unused harmony exports Controller, Form, FormProvider, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useFormContext, useFormState, useWatch */
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6540);
var isCheckBoxInput = (element) => element.type === 'checkbox';
var isDateObject = (value) => value instanceof Date;
var isNullOrUndefined = (value) => value == null;
const isObjectType = (value) => typeof value === 'object';
var isObject = (value) => !isNullOrUndefined(value) &&
!Array.isArray(value) &&
isObjectType(value) &&
!isDateObject(value);
var getEventValue = (event) => isObject(event) && event.target
? isCheckBoxInput(event.target)
? event.target.checked
: event.target.value
: event;
var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name));
var isPlainObject = (tempObject) => {
const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
return (isObject(prototypeCopy) && prototypeCopy.hasOwnProperty('isPrototypeOf'));
};
var isWeb = typeof window !== 'undefined' &&
typeof window.HTMLElement !== 'undefined' &&
typeof document !== 'undefined';
function cloneObject(data) {
let copy;
const isArray = Array.isArray(data);
const isFileListInstance = typeof FileList !== 'undefined' ? data instanceof FileList : false;
if (data instanceof Date) {
copy = new Date(data);
}
else if (!(isWeb && (data instanceof Blob || isFileListInstance)) &&
(isArray || isObject(data))) {
copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
if (!isArray && !isPlainObject(data)) {
copy = data;
}
else {
for (const key in data) {
if (data.hasOwnProperty(key)) {
copy[key] = cloneObject(data[key]);
}
}
}
}
else {
return data;
}
return copy;
}
var isKey = (value) => /^\w*$/.test(value);
var isUndefined = (val) => val === undefined;
var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
var get = (object, path, defaultValue) => {
if (!path || !isObject(object)) {
return defaultValue;
}
const result = (isKey(path) ? [path] : stringToPath(path)).reduce((result, key) => isNullOrUndefined(result) ? result : result[key], object);
return isUndefined(result) || result === object
? isUndefined(object[path])
? defaultValue
: object[path]
: result;
};
var isBoolean = (value) => typeof value === 'boolean';
var set = (object, path, value) => {
let index = -1;
const tempPath = isKey(path) ? [path] : stringToPath(path);
const length = tempPath.length;
const lastIndex = length - 1;
while (++index < length) {
const key = tempPath[index];
let newValue = value;
if (index !== lastIndex) {
const objValue = object[key];
newValue =
isObject(objValue) || Array.isArray(objValue)
? objValue
: !isNaN(+tempPath[index + 1])
? []
: {};
}
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
return;
}
object[key] = newValue;
object = object[key];
}
};
const EVENTS = {
BLUR: 'blur',
FOCUS_OUT: 'focusout',
CHANGE: 'change',
};
const VALIDATION_MODE = {
onBlur: 'onBlur',
onChange: 'onChange',
onSubmit: 'onSubmit',
onTouched: 'onTouched',
all: 'all',
};
const INPUT_VALIDATION_RULES = {
max: 'max',
min: 'min',
maxLength: 'maxLength',
minLength: 'minLength',
pattern: 'pattern',
required: 'required',
validate: 'validate',
};
const HookFormContext = react__WEBPACK_IMPORTED_MODULE_0__.createContext(null);
HookFormContext.displayName = 'HookFormContext';
/**
* This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
*
* @remarks
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
*
* @returns return all useForm methods
*
* @example
* ```tsx
* function App() {
* const methods = useForm();
* const onSubmit = data => console.log(data);
*
* return (
*
*
*
* );
* }
*
* function NestedInput() {
* const { register } = useFormContext(); // retrieve all hook methods
* return ;
* }
* ```
*/
const useFormContext = () => React.useContext(HookFormContext);
/**
* A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
*
* @remarks
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
*
* @param props - all useForm methods
*
* @example
* ```tsx
* function App() {
* const methods = useForm();
* const onSubmit = data => console.log(data);
*
* return (
*
*
*
* );
* }
*
* function NestedInput() {
* const { register } = useFormContext(); // retrieve all hook methods
* return ;
* }
* ```
*/
const FormProvider = (props) => {
const { children, ...data } = props;
return (React.createElement(HookFormContext.Provider, { value: data }, children));
};
var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
const result = {
defaultValues: control._defaultValues,
};
for (const key in formState) {
Object.defineProperty(result, key, {
get: () => {
const _key = key;
if (control._proxyFormState[_key] !== VALIDATION_MODE.all) {
control._proxyFormState[_key] = !isRoot || VALIDATION_MODE.all;
}
localProxyFormState && (localProxyFormState[_key] = true);
return formState[_key];
},
});
}
return result;
};
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect : react__WEBPACK_IMPORTED_MODULE_0__.useEffect;
/**
* This custom hook allows you to subscribe to each form state, and isolate the re-render at the custom hook level. It has its scope in terms of form state subscription, so it would not affect other useFormState and useForm. Using this hook can reduce the re-render impact on large and complex form application.
*
* @remarks
* [API](https://react-hook-form.com/docs/useformstate) • [Demo](https://codesandbox.io/s/useformstate-75xly)
*
* @param props - include options on specify fields to subscribe. {@link UseFormStateReturn}
*
* @example
* ```tsx
* function App() {
* const { register, handleSubmit, control } = useForm({
* defaultValues: {
* firstName: "firstName"
* }});
* const { dirtyFields } = useFormState({
* control
* });
* const onSubmit = (data) => console.log(data);
*
* return (
*
* );
* }
* ```
*/
function useFormState(props) {
const methods = useFormContext();
const { control = methods.control, disabled, name, exact } = props || {};
const [formState, updateFormState] = React.useState(control._formState);
const _localProxyFormState = React.useRef({
isDirty: false,
isLoading: false,
dirtyFields: false,
touchedFields: false,
validatingFields: false,
isValidating: false,
isValid: false,
errors: false,
});
useIsomorphicLayoutEffect(() => control._subscribe({
name,
formState: _localProxyFormState.current,
exact,
callback: (formState) => {
!disabled &&
updateFormState({
...control._formState,
...formState,
});
},
}), [name, disabled, exact]);
React.useEffect(() => {
_localProxyFormState.current.isValid && control._setValid(true);
}, [control]);
return React.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]);
}
var isString = (value) => typeof value === 'string';
var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) => {
if (isString(names)) {
isGlobal && _names.watch.add(names);
return get(formValues, names, defaultValue);
}
if (Array.isArray(names)) {
return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName),
get(formValues, fieldName)));
}
isGlobal && (_names.watchAll = true);
return formValues;
};
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
if (isPrimitive(object1) || isPrimitive(object2)) {
return Object.is(object1, object2);
}
if (isDateObject(object1) && isDateObject(object2)) {
return object1.getTime() === object2.getTime();
}
const keys1 = Object.keys(object1);
const keys2 = Object.keys(object2);
if (keys1.length !== keys2.length) {
return false;
}
if (_internal_visited.has(object1) || _internal_visited.has(object2)) {
return true;
}
_internal_visited.add(object1);
_internal_visited.add(object2);
for (const key of keys1) {
const val1 = object1[key];
if (!keys2.includes(key)) {
return false;
}
if (key !== 'ref') {
const val2 = object2[key];
if ((isDateObject(val1) && isDateObject(val2)) ||
(isObject(val1) && isObject(val2)) ||
(Array.isArray(val1) && Array.isArray(val2))
? !deepEqual(val1, val2, _internal_visited)
: !Object.is(val1, val2)) {
return false;
}
}
}
return true;
}
/**
* Custom hook to subscribe to field change and isolate re-rendering at the component level.
*
* @remarks
*
* [API](https://react-hook-form.com/docs/usewatch) • [Demo](https://codesandbox.io/s/react-hook-form-v7-ts-usewatch-h9i5e)
*
* @example
* ```tsx
* const { control } = useForm();
* const values = useWatch({
* name: "fieldName"
* control,
* })
* ```
*/
function useWatch(props) {
const methods = useFormContext();
const { control = methods.control, name, defaultValue, disabled, exact, compute, } = props || {};
const _defaultValue = React.useRef(defaultValue);
const _compute = React.useRef(compute);
const _computeFormValues = React.useRef(undefined);
const _prevControl = React.useRef(control);
const _prevName = React.useRef(name);
_compute.current = compute;
const [value, updateValue] = React.useState(() => {
const defaultValue = control._getWatch(name, _defaultValue.current);
return _compute.current ? _compute.current(defaultValue) : defaultValue;
});
const getCurrentOutput = React.useCallback((values) => {
const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
return _compute.current ? _compute.current(formValues) : formValues;
}, [control._formValues, control._names, name]);
const refreshValue = React.useCallback((values) => {
if (!disabled) {
const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
if (_compute.current) {
const computedFormValues = _compute.current(formValues);
if (!deepEqual(computedFormValues, _computeFormValues.current)) {
updateValue(computedFormValues);
_computeFormValues.current = computedFormValues;
}
}
else {
updateValue(formValues);
}
}
}, [control._formValues, control._names, disabled, name]);
useIsomorphicLayoutEffect(() => {
if (_prevControl.current !== control ||
!deepEqual(_prevName.current, name)) {
_prevControl.current = control;
_prevName.current = name;
refreshValue();
}
return control._subscribe({
name,
formState: {
values: true,
},
exact,
callback: (formState) => {
refreshValue(formState.values);
},
});
}, [control, exact, name, refreshValue]);
React.useEffect(() => control._removeUnmounted());
// If name or control changed for this render, synchronously reflect the
// latest value so callers (like useController) see the correct value
// immediately on the same render.
// Optimize: Check control reference first before expensive deepEqual
const controlChanged = _prevControl.current !== control;
const prevName = _prevName.current;
// Cache the computed output to avoid duplicate calls within the same render
// We include shouldReturnImmediate in deps to ensure proper recomputation
const computedOutput = React.useMemo(() => {
if (disabled) {
return null;
}
const nameChanged = !controlChanged && !deepEqual(prevName, name);
const shouldReturnImmediate = controlChanged || nameChanged;
return shouldReturnImmediate ? getCurrentOutput() : null;
}, [disabled, controlChanged, name, prevName, getCurrentOutput]);
return computedOutput !== null ? computedOutput : value;
}
/**
* Custom hook to work with controlled component, this function provide you with both form and field level state. Re-render is isolated at the hook level.
*
* @remarks
* [API](https://react-hook-form.com/docs/usecontroller) • [Demo](https://codesandbox.io/s/usecontroller-0o8px)
*
* @param props - the path name to the form field value, and validation rules.
*
* @returns field properties, field and form state. {@link UseControllerReturn}
*
* @example
* ```tsx
* function Input(props) {
* const { field, fieldState, formState } = useController(props);
* return (
*
*
*
{fieldState.isTouched && "Touched"}
*
{formState.isSubmitted ? "submitted" : ""}
*
* );
* }
* ```
*/
function useController(props) {
const methods = useFormContext();
const { name, disabled, control = methods.control, shouldUnregister, defaultValue, } = props;
const isArrayField = isNameInFieldArray(control._names.array, name);
const defaultValueMemo = React.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
const value = useWatch({
control,
name,
defaultValue: defaultValueMemo,
exact: true,
});
const formState = useFormState({
control,
name,
exact: true,
});
const _props = React.useRef(props);
const _previousNameRef = React.useRef(undefined);
const _registerProps = React.useRef(control.register(name, {
...props.rules,
value,
...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}),
}));
_props.current = props;
const fieldState = React.useMemo(() => Object.defineProperties({}, {
invalid: {
enumerable: true,
get: () => !!get(formState.errors, name),
},
isDirty: {
enumerable: true,
get: () => !!get(formState.dirtyFields, name),
},
isTouched: {
enumerable: true,
get: () => !!get(formState.touchedFields, name),
},
isValidating: {
enumerable: true,
get: () => !!get(formState.validatingFields, name),
},
error: {
enumerable: true,
get: () => get(formState.errors, name),
},
}), [formState, name]);
const onChange = React.useCallback((event) => _registerProps.current.onChange({
target: {
value: getEventValue(event),
name: name,
},
type: EVENTS.CHANGE,
}), [name]);
const onBlur = React.useCallback(() => _registerProps.current.onBlur({
target: {
value: get(control._formValues, name),
name: name,
},
type: EVENTS.BLUR,
}), [name, control._formValues]);
const ref = React.useCallback((elm) => {
const field = get(control._fields, name);
if (field && elm) {
field._f.ref = {
focus: () => elm.focus && elm.focus(),
select: () => elm.select && elm.select(),
setCustomValidity: (message) => elm.setCustomValidity(message),
reportValidity: () => elm.reportValidity(),
};
}
}, [control._fields, name]);
const field = React.useMemo(() => ({
name,
value,
...(isBoolean(disabled) || formState.disabled
? { disabled: formState.disabled || disabled }
: {}),
onChange,
onBlur,
ref,
}), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
React.useEffect(() => {
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
const previousName = _previousNameRef.current;
if (previousName && previousName !== name && !isArrayField) {
control.unregister(previousName);
}
control.register(name, {
..._props.current.rules,
...(isBoolean(_props.current.disabled)
? { disabled: _props.current.disabled }
: {}),
});
const updateMounted = (name, value) => {
const field = get(control._fields, name);
if (field && field._f) {
field._f.mount = value;
}
};
updateMounted(name, true);
if (_shouldUnregisterField) {
const value = cloneObject(get(control._options.defaultValues, name, _props.current.defaultValue));
set(control._defaultValues, name, value);
if (isUndefined(get(control._formValues, name))) {
set(control._formValues, name, value);
}
}
!isArrayField && control.register(name);
_previousNameRef.current = name;
return () => {
(isArrayField
? _shouldUnregisterField && !control._state.action
: _shouldUnregisterField)
? control.unregister(name)
: updateMounted(name, false);
};
}, [name, control, isArrayField, shouldUnregister]);
React.useEffect(() => {
control._setDisabledField({
disabled,
name,
});
}, [disabled, name, control]);
return React.useMemo(() => ({
field,
formState,
fieldState,
}), [field, formState, fieldState]);
}
/**
* Component based on `useController` hook to work with controlled component.
*
* @remarks
* [API](https://react-hook-form.com/docs/usecontroller/controller) • [Demo](https://codesandbox.io/s/react-hook-form-v6-controller-ts-jwyzw) • [Video](https://www.youtube.com/watch?v=N2UNk_UCVyA)
*
* @param props - the path name to the form field value, and validation rules.
*
* @returns provide field handler functions, field and form state.
*
* @example
* ```tsx
* function App() {
* const { control } = useForm({
* defaultValues: {
* test: ""
* }
* });
*
* return (
*
* );
* }
* ```
*/
const Controller = (props) => props.render(useController(props));
const flatten = (obj) => {
const output = {};
for (const key of Object.keys(obj)) {
if (isObjectType(obj[key]) && obj[key] !== null) {
const nested = flatten(obj[key]);
for (const nestedKey of Object.keys(nested)) {
output[`${key}.${nestedKey}`] = nested[nestedKey];
}
}
else {
output[key] = obj[key];
}
}
return output;
};
const POST_REQUEST = 'post';
/**
* Form component to manage submission.
*
* @param props - to setup submission detail. {@link FormProps}
*
* @returns form component or headless render prop.
*
* @example
* ```tsx
* function App() {
* const { control, formState: { errors } } = useForm();
*
* return (
*
* );
* }
* ```
*/
function Form(props) {
const methods = useFormContext();
const [mounted, setMounted] = React.useState(false);
const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
const submit = async (event) => {
let hasError = false;
let type = '';
await control.handleSubmit(async (data) => {
const formData = new FormData();
let formDataJson = '';
try {
formDataJson = JSON.stringify(data);
}
catch (_a) { }
const flattenFormValues = flatten(control._formValues);
for (const key in flattenFormValues) {
formData.append(key, flattenFormValues[key]);
}
if (onSubmit) {
await onSubmit({
data,
event,
method,
formData,
formDataJson,
});
}
if (action) {
try {
const shouldStringifySubmissionData = [
headers && headers['Content-Type'],
encType,
].some((value) => value && value.includes('json'));
const response = await fetch(String(action), {
method,
headers: {
...headers,
...(encType && encType !== 'multipart/form-data'
? { 'Content-Type': encType }
: {}),
},
body: shouldStringifySubmissionData ? formDataJson : formData,
});
if (response &&
(validateStatus
? !validateStatus(response.status)
: response.status < 200 || response.status >= 300)) {
hasError = true;
onError && onError({ response });
type = String(response.status);
}
else {
onSuccess && onSuccess({ response });
}
}
catch (error) {
hasError = true;
onError && onError({ error });
}
}
})(event);
if (hasError && props.control) {
props.control._subjects.state.next({
isSubmitSuccessful: false,
});
props.control.setError('root.server', {
type,
});
}
};
React.useEffect(() => {
setMounted(true);
}, []);
return render ? (React.createElement(React.Fragment, null, render({
submit,
}))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
}
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
? {
...errors[name],
types: {
...(errors[name] && errors[name].types ? errors[name].types : {}),
[type]: message || true,
},
}
: {};
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
var createSubject = () => {
let _observers = [];
const next = (value) => {
for (const observer of _observers) {
observer.next && observer.next(value);
}
};
const subscribe = (observer) => {
_observers.push(observer);
return {
unsubscribe: () => {
_observers = _observers.filter((o) => o !== observer);
},
};
};
const unsubscribe = () => {
_observers = [];
};
return {
get observers() {
return _observers;
},
next,
subscribe,
unsubscribe,
};
};
function extractFormValues(fieldsState, formValues) {
const values = {};
for (const key in fieldsState) {
if (fieldsState.hasOwnProperty(key)) {
const fieldState = fieldsState[key];
const fieldValue = formValues[key];
if (fieldState && isObject(fieldState) && fieldValue) {
const nestedFieldsState = extractFormValues(fieldState, fieldValue);
if (isObject(nestedFieldsState)) {
values[key] = nestedFieldsState;
}
}
else if (fieldsState[key]) {
values[key] = fieldValue;
}
}
}
return values;
}
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
var isFileInput = (element) => element.type === 'file';
var isFunction = (value) => typeof value === 'function';
var isHTMLElement = (value) => {
if (!isWeb) {
return false;
}
const owner = value ? value.ownerDocument : 0;
return (value instanceof
(owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
};
var isMultipleSelect = (element) => element.type === `select-multiple`;
var isRadioInput = (element) => element.type === 'radio';
var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
function baseGet(object, updatePath) {
const length = updatePath.slice(0, -1).length;
let index = 0;
while (index < length) {
object = isUndefined(object) ? index++ : object[updatePath[index++]];
}
return object;
}
function isEmptyArray(obj) {
for (const key in obj) {
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
return false;
}
}
return true;
}
function unset(object, path) {
const paths = Array.isArray(path)
? path
: isKey(path)
? [path]
: stringToPath(path);
const childObject = paths.length === 1 ? object : baseGet(object, paths);
const index = paths.length - 1;
const key = paths[index];
if (childObject) {
delete childObject[key];
}
if (index !== 0 &&
((isObject(childObject) && isEmptyObject(childObject)) ||
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
unset(object, paths.slice(0, -1));
}
return object;
}
var objectHasFunction = (data) => {
for (const key in data) {
if (isFunction(data[key])) {
return true;
}
}
return false;
};
function isTraversable(value) {
return Array.isArray(value) || (isObject(value) && !objectHasFunction(value));
}
function markFieldsDirty(data, fields = {}) {
for (const key in data) {
const value = data[key];
if (isTraversable(value)) {
fields[key] = Array.isArray(value) ? [] : {};
markFieldsDirty(value, fields[key]);
}
else if (!isUndefined(value)) {
fields[key] = true;
}
}
return fields;
}
function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
if (!dirtyFieldsFromValues) {
dirtyFieldsFromValues = markFieldsDirty(formValues);
}
for (const key in data) {
const value = data[key];
if (isTraversable(value)) {
if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {});
}
else {
getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
}
}
else {
const formValue = formValues[key];
dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
}
}
return dirtyFieldsFromValues;
}
const defaultResult = {
value: false,
isValid: false,
};
const validResult = { value: true, isValid: true };
var getCheckboxValue = (options) => {
if (Array.isArray(options)) {
if (options.length > 1) {
const values = options
.filter((option) => option && option.checked && !option.disabled)
.map((option) => option.value);
return { value: values, isValid: !!values.length };
}
return options[0].checked && !options[0].disabled
? // @ts-expect-error expected to work in the browser
options[0].attributes && !isUndefined(options[0].attributes.value)
? isUndefined(options[0].value) || options[0].value === ''
? validResult
: { value: options[0].value, isValid: true }
: validResult
: defaultResult;
}
return defaultResult;
};
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
? value
: valueAsNumber
? value === ''
? NaN
: value
? +value
: value
: valueAsDate && isString(value)
? new Date(value)
: setValueAs
? setValueAs(value)
: value;
const defaultReturn = {
isValid: false,
value: null,
};
var getRadioValue = (options) => Array.isArray(options)
? options.reduce((previous, option) => option && option.checked && !option.disabled
? {
isValid: true,
value: option.value,
}
: previous, defaultReturn)
: defaultReturn;
function getFieldValue(_f) {
const ref = _f.ref;
if (isFileInput(ref)) {
return ref.files;
}
if (isRadioInput(ref)) {
return getRadioValue(_f.refs).value;
}
if (isMultipleSelect(ref)) {
return [...ref.selectedOptions].map(({ value }) => value);
}
if (isCheckBoxInput(ref)) {
return getCheckboxValue(_f.refs).value;
}
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
}
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
const fields = {};
for (const name of fieldsNames) {
const field = get(_fields, name);
field && set(fields, name, field._f);
}
return {
criteriaMode,
names: [...fieldsNames],
fields,
shouldUseNativeValidation,
};
};
var isRegex = (value) => value instanceof RegExp;
var getRuleValue = (rule) => isUndefined(rule)
? rule
: isRegex(rule)
? rule.source
: isObject(rule)
? isRegex(rule.value)
? rule.value.source
: rule.value
: rule;
var getValidationModes = (mode) => ({
isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
isOnBlur: mode === VALIDATION_MODE.onBlur,
isOnChange: mode === VALIDATION_MODE.onChange,
isOnAll: mode === VALIDATION_MODE.all,
isOnTouch: mode === VALIDATION_MODE.onTouched,
});
const ASYNC_FUNCTION = 'AsyncFunction';
var hasPromiseValidation = (fieldReference) => !!fieldReference &&
!!fieldReference.validate &&
!!((isFunction(fieldReference.validate) &&
fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
(isObject(fieldReference.validate) &&
Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
var hasValidation = (options) => options.mount &&
(options.required ||
options.min ||
options.max ||
options.maxLength ||
options.minLength ||
options.pattern ||
options.validate);
var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
(_names.watchAll ||
_names.watch.has(name) ||
[..._names.watch].some((watchName) => name.startsWith(watchName) &&
/^\.\w+/.test(name.slice(watchName.length))));
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
for (const key of fieldsNames || Object.keys(fields)) {
const field = get(fields, key);
if (field) {
const { _f, ...currentField } = field;
if (_f) {
if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
return true;
}
else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
return true;
}
else {
if (iterateFieldsByAction(currentField, action)) {
break;
}
}
}
else if (isObject(currentField)) {
if (iterateFieldsByAction(currentField, action)) {
break;
}
}
}
}
return;
};
function schemaErrorLookup(errors, _fields, name) {
const error = get(errors, name);
if (error || isKey(name)) {
return {
error,
name,
};
}
const names = name.split('.');
while (names.length) {
const fieldName = names.join('.');
const field = get(_fields, fieldName);
const foundError = get(errors, fieldName);
if (field && !Array.isArray(field) && name !== fieldName) {
return { name };
}
if (foundError && foundError.type) {
return {
name: fieldName,
error: foundError,
};
}
if (foundError && foundError.root && foundError.root.type) {
return {
name: `${fieldName}.root`,
error: foundError.root,
};
}
names.pop();
}
return {
name,
};
}
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
updateFormState(formStateData);
const { name, ...formState } = formStateData;
return (isEmptyObject(formState) ||
Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
Object.keys(formState).find((key) => _proxyFormState[key] ===
(!isRoot || VALIDATION_MODE.all)));
};
var shouldSubscribeByName = (name, signalName, exact) => !name ||
!signalName ||
name === signalName ||
convertToArrayPayload(name).some((currentName) => currentName &&
(exact
? currentName === signalName
: currentName.startsWith(signalName) ||
signalName.startsWith(currentName)));
var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
if (mode.isOnAll) {
return false;
}
else if (!isSubmitted && mode.isOnTouch) {
return !(isTouched || isBlurEvent);
}
else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
return !isBlurEvent;
}
else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
return isBlurEvent;
}
return true;
};
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
var updateFieldArrayRootError = (errors, error, name) => {
const fieldArrayErrors = convertToArrayPayload(get(errors, name));
set(fieldArrayErrors, 'root', error[name]);
set(errors, name, fieldArrayErrors);
return errors;
};
function getValidateError(result, ref, type = 'validate') {
if (isString(result) ||
(Array.isArray(result) && result.every(isString)) ||
(isBoolean(result) && !result)) {
return {
type,
message: isString(result) ? result : '',
ref,
};
}
}
var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
? validationData
: {
value: validationData,
message: '',
};
var validateField = async (field, disabledFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, } = field._f;
const inputValue = get(formValues, name);
if (!mount || disabledFieldNames.has(name)) {
return {};
}
const inputRef = refs ? refs[0] : ref;
const setCustomValidity = (message) => {
if (shouldUseNativeValidation && inputRef.reportValidity) {
inputRef.setCustomValidity(isBoolean(message) ? '' : message || '');
inputRef.reportValidity();
}
};
const error = {};
const isRadio = isRadioInput(ref);
const isCheckBox = isCheckBoxInput(ref);
const isRadioOrCheckbox = isRadio || isCheckBox;
const isEmpty = ((valueAsNumber || isFileInput(ref)) &&
isUndefined(ref.value) &&
isUndefined(inputValue)) ||
(isHTMLElement(ref) && ref.value === '') ||
inputValue === '' ||
(Array.isArray(inputValue) && !inputValue.length);
const appendErrorsCurry = appendErrors.bind(null, name, validateAllFieldCriteria, error);
const getMinMaxMessage = (exceedMax, maxLengthMessage, minLengthMessage, maxType = INPUT_VALIDATION_RULES.maxLength, minType = INPUT_VALIDATION_RULES.minLength) => {
const message = exceedMax ? maxLengthMessage : minLengthMessage;
error[name] = {
type: exceedMax ? maxType : minType,
message,
ref,
...appendErrorsCurry(exceedMax ? maxType : minType, message),
};
};
if (isFieldArray
? !Array.isArray(inputValue) || !inputValue.length
: required &&
((!isRadioOrCheckbox && (isEmpty || isNullOrUndefined(inputValue))) ||
(isBoolean(inputValue) && !inputValue) ||
(isCheckBox && !getCheckboxValue(refs).isValid) ||
(isRadio && !getRadioValue(refs).isValid))) {
const { value, message } = isString(required)
? { value: !!required, message: required }
: getValueAndMessage(required);
if (value) {
error[name] = {
type: INPUT_VALIDATION_RULES.required,
message,
ref: inputRef,
...appendErrorsCurry(INPUT_VALIDATION_RULES.required, message),
};
if (!validateAllFieldCriteria) {
setCustomValidity(message);
return error;
}
}
}
if (!isEmpty && (!isNullOrUndefined(min) || !isNullOrUndefined(max))) {
let exceedMax;
let exceedMin;
const maxOutput = getValueAndMessage(max);
const minOutput = getValueAndMessage(min);
if (!isNullOrUndefined(inputValue) && !isNaN(inputValue)) {
const valueNumber = ref.valueAsNumber ||
(inputValue ? +inputValue : inputValue);
if (!isNullOrUndefined(maxOutput.value)) {
exceedMax = valueNumber > maxOutput.value;
}
if (!isNullOrUndefined(minOutput.value)) {
exceedMin = valueNumber < minOutput.value;
}
}
else {
const valueDate = ref.valueAsDate || new Date(inputValue);
const convertTimeToDate = (time) => new Date(new Date().toDateString() + ' ' + time);
const isTime = ref.type == 'time';
const isWeek = ref.type == 'week';
if (isString(maxOutput.value) && inputValue) {
exceedMax = isTime
? convertTimeToDate(inputValue) > convertTimeToDate(maxOutput.value)
: isWeek
? inputValue > maxOutput.value
: valueDate > new Date(maxOutput.value);
}
if (isString(minOutput.value) && inputValue) {
exceedMin = isTime
? convertTimeToDate(inputValue) < convertTimeToDate(minOutput.value)
: isWeek
? inputValue < minOutput.value
: valueDate < new Date(minOutput.value);
}
}
if (exceedMax || exceedMin) {
getMinMaxMessage(!!exceedMax, maxOutput.message, minOutput.message, INPUT_VALIDATION_RULES.max, INPUT_VALIDATION_RULES.min);
if (!validateAllFieldCriteria) {
setCustomValidity(error[name].message);
return error;
}
}
}
if ((maxLength || minLength) &&
!isEmpty &&
(isString(inputValue) || (isFieldArray && Array.isArray(inputValue)))) {
const maxLengthOutput = getValueAndMessage(maxLength);
const minLengthOutput = getValueAndMessage(minLength);
const exceedMax = !isNullOrUndefined(maxLengthOutput.value) &&
inputValue.length > +maxLengthOutput.value;
const exceedMin = !isNullOrUndefined(minLengthOutput.value) &&
inputValue.length < +minLengthOutput.value;
if (exceedMax || exceedMin) {
getMinMaxMessage(exceedMax, maxLengthOutput.message, minLengthOutput.message);
if (!validateAllFieldCriteria) {
setCustomValidity(error[name].message);
return error;
}
}
}
if (pattern && !isEmpty && isString(inputValue)) {
const { value: patternValue, message } = getValueAndMessage(pattern);
if (isRegex(patternValue) && !inputValue.match(patternValue)) {
error[name] = {
type: INPUT_VALIDATION_RULES.pattern,
message,
ref,
...appendErrorsCurry(INPUT_VALIDATION_RULES.pattern, message),
};
if (!validateAllFieldCriteria) {
setCustomValidity(message);
return error;
}
}
}
if (validate) {
if (isFunction(validate)) {
const result = await validate(inputValue, formValues);
const validateError = getValidateError(result, inputRef);
if (validateError) {
error[name] = {
...validateError,
...appendErrorsCurry(INPUT_VALIDATION_RULES.validate, validateError.message),
};
if (!validateAllFieldCriteria) {
setCustomValidity(validateError.message);
return error;
}
}
}
else if (isObject(validate)) {
let validationResult = {};
for (const key in validate) {
if (!isEmptyObject(validationResult) && !validateAllFieldCriteria) {
break;
}
const validateError = getValidateError(await validate[key](inputValue, formValues), inputRef, key);
if (validateError) {
validationResult = {
...validateError,
...appendErrorsCurry(key, validateError.message),
};
setCustomValidity(validateError.message);
if (validateAllFieldCriteria) {
error[name] = validationResult;
}
}
}
if (!isEmptyObject(validationResult)) {
error[name] = {
ref: inputRef,
...validationResult,
};
if (!validateAllFieldCriteria) {
return error;
}
}
}
}
setCustomValidity(true);
return error;
};
const defaultOptions = {
mode: VALIDATION_MODE.onSubmit,
reValidateMode: VALIDATION_MODE.onChange,
shouldFocusError: true,
};
function createFormControl(props = {}) {
let _options = {
...defaultOptions,
...props,
};
let _formState = {
submitCount: 0,
isDirty: false,
isReady: false,
isLoading: isFunction(_options.defaultValues),
isValidating: false,
isSubmitted: false,
isSubmitting: false,
isSubmitSuccessful: false,
isValid: false,
touchedFields: {},
dirtyFields: {},
validatingFields: {},
errors: _options.errors || {},
disabled: _options.disabled || false,
};
let _fields = {};
let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
? cloneObject(_options.defaultValues || _options.values) || {}
: {};
let _formValues = _options.shouldUnregister
? {}
: cloneObject(_defaultValues);
let _state = {
action: false,
mount: false,
watch: false,
};
let _names = {
mount: new Set(),
disabled: new Set(),
unMount: new Set(),
array: new Set(),
watch: new Set(),
};
let delayErrorCallback;
let timer = 0;
const _proxyFormState = {
isDirty: false,
dirtyFields: false,
validatingFields: false,
touchedFields: false,
isValidating: false,
isValid: false,
errors: false,
};
let _proxySubscribeFormState = {
..._proxyFormState,
};
const _subjects = {
array: createSubject(),
state: createSubject(),
};
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
const debounce = (callback) => (wait) => {
clearTimeout(timer);
timer = setTimeout(callback, wait);
};
const _setValid = async (shouldUpdateValid) => {
if (!_options.disabled &&
(_proxyFormState.isValid ||
_proxySubscribeFormState.isValid ||
shouldUpdateValid)) {
const isValid = _options.resolver
? isEmptyObject((await _runSchema()).errors)
: await executeBuiltInValidation(_fields, true);
if (isValid !== _formState.isValid) {
_subjects.state.next({
isValid,
});
}
}
};
const _updateIsValidating = (names, isValidating) => {
if (!_options.disabled &&
(_proxyFormState.isValidating ||
_proxyFormState.validatingFields ||
_proxySubscribeFormState.isValidating ||
_proxySubscribeFormState.validatingFields)) {
(names || Array.from(_names.mount)).forEach((name) => {
if (name) {
isValidating
? set(_formState.validatingFields, name, isValidating)
: unset(_formState.validatingFields, name);
}
});
_subjects.state.next({
validatingFields: _formState.validatingFields,
isValidating: !isEmptyObject(_formState.validatingFields),
});
}
};
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
if (args && method && !_options.disabled) {
_state.action = true;
if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
const fieldValues = method(get(_fields, name), args.argA, args.argB);
shouldSetValues && set(_fields, name, fieldValues);
}
if (shouldUpdateFieldsAndState &&
Array.isArray(get(_formState.errors, name))) {
const errors = method(get(_formState.errors, name), args.argA, args.argB);
shouldSetValues && set(_formState.errors, name, errors);
unsetEmptyArray(_formState.errors, name);
}
if ((_proxyFormState.touchedFields ||
_proxySubscribeFormState.touchedFields) &&
shouldUpdateFieldsAndState &&
Array.isArray(get(_formState.touchedFields, name))) {
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
}
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
}
_subjects.state.next({
name,
isDirty: _getDirty(name, values),
dirtyFields: _formState.dirtyFields,
errors: _formState.errors,
isValid: _formState.isValid,
});
}
else {
set(_formValues, name, values);
}
};
const updateErrors = (name, error) => {
set(_formState.errors, name, error);
_subjects.state.next({
errors: _formState.errors,
});
};
const _setErrors = (errors) => {
_formState.errors = errors;
_subjects.state.next({
errors: _formState.errors,
isValid: false,
});
};
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
const field = get(_fields, name);
if (field) {
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
isUndefined(defaultValue) ||
(ref && ref.defaultChecked) ||
shouldSkipSetValueAs
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
: setFieldValue(name, defaultValue);
_state.mount && !_state.action && _setValid();
}
};
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
let shouldUpdateField = false;
let isPreviousDirty = false;
const output = {
name,
};
if (!_options.disabled) {
if (!isBlurEvent || shouldDirty) {
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
isPreviousDirty = _formState.isDirty;
_formState.isDirty = output.isDirty = _getDirty();
shouldUpdateField = isPreviousDirty !== output.isDirty;
}
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
isPreviousDirty = !!get(_formState.dirtyFields, name);
isCurrentFieldPristine
? unset(_formState.dirtyFields, name)
: set(_formState.dirtyFields, name, true);
output.dirtyFields = _formState.dirtyFields;
shouldUpdateField =
shouldUpdateField ||
((_proxyFormState.dirtyFields ||
_proxySubscribeFormState.dirtyFields) &&
isPreviousDirty !== !isCurrentFieldPristine);
}
if (isBlurEvent) {
const isPreviousFieldTouched = get(_formState.touchedFields, name);
if (!isPreviousFieldTouched) {
set(_formState.touchedFields, name, isBlurEvent);
output.touchedFields = _formState.touchedFields;
shouldUpdateField =
shouldUpdateField ||
((_proxyFormState.touchedFields ||
_proxySubscribeFormState.touchedFields) &&
isPreviousFieldTouched !== isBlurEvent);
}
}
shouldUpdateField && shouldRender && _subjects.state.next(output);
}
return shouldUpdateField ? output : {};
};
const shouldRenderByError = (name, isValid, error, fieldState) => {
const previousFieldError = get(_formState.errors, name);
const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
isBoolean(isValid) &&
_formState.isValid !== isValid;
if (_options.delayError && error) {
delayErrorCallback = debounce(() => updateErrors(name, error));
delayErrorCallback(_options.delayError);
}
else {
clearTimeout(timer);
delayErrorCallback = null;
error
? set(_formState.errors, name, error)
: unset(_formState.errors, name);
}
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
!isEmptyObject(fieldState) ||
shouldUpdateValid) {
const updatedFormState = {
...fieldState,
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
errors: _formState.errors,
name,
};
_formState = {
..._formState,
...updatedFormState,
};
_subjects.state.next(updatedFormState);
}
};
const _runSchema = async (name) => {
_updateIsValidating(name, true);
const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
_updateIsValidating(name);
return result;
};
const executeSchemaAndUpdateState = async (names) => {
const { errors } = await _runSchema(names);
if (names) {
for (const name of names) {
const error = get(errors, name);
error
? set(_formState.errors, name, error)
: unset(_formState.errors, name);
}
}
else {
_formState.errors = errors;
}
return errors;
};
const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
valid: true,
}) => {
for (const name in fields) {
const field = fields[name];
if (field) {
const { _f, ...fieldValue } = field;
if (_f) {
const isFieldArrayRoot = _names.array.has(_f.name);
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
if (isPromiseFunction && _proxyFormState.validatingFields) {
_updateIsValidating([_f.name], true);
}
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
if (isPromiseFunction && _proxyFormState.validatingFields) {
_updateIsValidating([_f.name]);
}
if (fieldError[_f.name]) {
context.valid = false;
if (shouldOnlyCheckValid) {
break;
}
}
!shouldOnlyCheckValid &&
(get(fieldError, _f.name)
? isFieldArrayRoot
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
: set(_formState.errors, _f.name, fieldError[_f.name])
: unset(_formState.errors, _f.name));
}
!isEmptyObject(fieldValue) &&
(await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
}
}
return context.valid;
};
const _removeUnmounted = () => {
for (const name of _names.unMount) {
const field = get(_fields, name);
field &&
(field._f.refs
? field._f.refs.every((ref) => !live(ref))
: !live(field._f.ref)) &&
unregister(name);
}
_names.unMount = new Set();
};
const _getDirty = (name, data) => !_options.disabled &&
(name && data && set(_formValues, name, data),
!deepEqual(getValues(), _defaultValues));
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
...(_state.mount
? _formValues
: isUndefined(defaultValue)
? _defaultValues
: isString(names)
? { [names]: defaultValue }
: defaultValue),
}, isGlobal, defaultValue);
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
const setFieldValue = (name, value, options = {}) => {
const field = get(_fields, name);
let fieldValue = value;
if (field) {
const fieldReference = field._f;
if (fieldReference) {
!fieldReference.disabled &&
set(_formValues, name, getFieldValueAs(value, fieldReference));
fieldValue =
isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
? ''
: value;
if (isMultipleSelect(fieldReference.ref)) {
[...fieldReference.ref.options].forEach((optionRef) => (optionRef.selected = fieldValue.includes(optionRef.value)));
}
else if (fieldReference.refs) {
if (isCheckBoxInput(fieldReference.ref)) {
fieldReference.refs.forEach((checkboxRef) => {
if (!checkboxRef.defaultChecked || !checkboxRef.disabled) {
if (Array.isArray(fieldValue)) {
checkboxRef.checked = !!fieldValue.find((data) => data === checkboxRef.value);
}
else {
checkboxRef.checked =
fieldValue === checkboxRef.value || !!fieldValue;
}
}
});
}
else {
fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
}
}
else if (isFileInput(fieldReference.ref)) {
fieldReference.ref.value = '';
}
else {
fieldReference.ref.value = fieldValue;
if (!fieldReference.ref.type) {
_subjects.state.next({
name,
values: cloneObject(_formValues),
});
}
}
}
}
(options.shouldDirty || options.shouldTouch) &&
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
options.shouldValidate && trigger(name);
};
const setValues = (name, value, options) => {
for (const fieldKey in value) {
if (!value.hasOwnProperty(fieldKey)) {
return;
}
const fieldValue = value[fieldKey];
const fieldName = name + '.' + fieldKey;
const field = get(_fields, fieldName);
(_names.array.has(name) ||
isObject(fieldValue) ||
(field && !field._f)) &&
!isDateObject(fieldValue)
? setValues(fieldName, fieldValue, options)
: setFieldValue(fieldName, fieldValue, options);
}
};
const setValue = (name, value, options = {}) => {
const field = get(_fields, name);
const isFieldArray = _names.array.has(name);
const cloneValue = cloneObject(value);
set(_formValues, name, cloneValue);
if (isFieldArray) {
_subjects.array.next({
name,
values: cloneObject(_formValues),
});
if ((_proxyFormState.isDirty ||
_proxyFormState.dirtyFields ||
_proxySubscribeFormState.isDirty ||
_proxySubscribeFormState.dirtyFields) &&
options.shouldDirty) {
_subjects.state.next({
name,
dirtyFields: getDirtyFields(_defaultValues, _formValues),
isDirty: _getDirty(name, cloneValue),
});
}
}
else {
field && !field._f && !isNullOrUndefined(cloneValue)
? setValues(name, cloneValue, options)
: setFieldValue(name, cloneValue, options);
}
isWatched(name, _names) && _subjects.state.next({ ..._formState, name });
_subjects.state.next({
name: _state.mount ? name : undefined,
values: cloneObject(_formValues),
});
};
const onChange = async (event) => {
_state.mount = true;
const target = event.target;
let name = target.name;
let isFieldValueUpdated = true;
const field = get(_fields, name);
const _updateIsFieldValueUpdated = (fieldValue) => {
isFieldValueUpdated =
Number.isNaN(fieldValue) ||
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
deepEqual(fieldValue, get(_formValues, name, fieldValue));
};
const validationModeBeforeSubmit = getValidationModes(_options.mode);
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
if (field) {
let error;
let isValid;
const fieldValue = target.type
? getFieldValue(field._f)
: getEventValue(event);
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
const shouldSkipValidation = (!hasValidation(field._f) &&
!_options.resolver &&
!get(_formState.errors, name) &&
!field._f.deps) ||
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
const watched = isWatched(name, _names, isBlurEvent);
set(_formValues, name, fieldValue);
if (isBlurEvent) {
if (!target || !target.readOnly) {
field._f.onBlur && field._f.onBlur(event);
delayErrorCallback && delayErrorCallback(0);
}
}
else if (field._f.onChange) {
field._f.onChange(event);
}
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
const shouldRender = !isEmptyObject(fieldState) || watched;
!isBlurEvent &&
_subjects.state.next({
name,
type: event.type,
values: cloneObject(_formValues),
});
if (shouldSkipValidation) {
if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
if (_options.mode === 'onBlur') {
if (isBlurEvent) {
_setValid();
}
}
else if (!isBlurEvent) {
_setValid();
}
}
return (shouldRender &&
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
}
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
if (_options.resolver) {
const { errors } = await _runSchema([name]);
_updateIsFieldValueUpdated(fieldValue);
if (isFieldValueUpdated) {
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
error = errorLookupResult.error;
name = errorLookupResult.name;
isValid = isEmptyObject(errors);
}
}
else {
_updateIsValidating([name], true);
error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
_updateIsValidating([name]);
_updateIsFieldValueUpdated(fieldValue);
if (isFieldValueUpdated) {
if (error) {
isValid = false;
}
else if (_proxyFormState.isValid ||
_proxySubscribeFormState.isValid) {
isValid = await executeBuiltInValidation(_fields, true);
}
}
}
if (isFieldValueUpdated) {
field._f.deps &&
(!Array.isArray(field._f.deps) || field._f.deps.length > 0) &&
trigger(field._f.deps);
shouldRenderByError(name, isValid, error, fieldState);
}
}
};
const _focusInput = (ref, key) => {
if (get(_formState.errors, key) && ref.focus) {
ref.focus();
return 1;
}
return;
};
const trigger = async (name, options = {}) => {
let isValid;
let validationResult;
const fieldNames = convertToArrayPayload(name);
if (_options.resolver) {
const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
isValid = isEmptyObject(errors);
validationResult = name
? !fieldNames.some((name) => get(errors, name))
: isValid;
}
else if (name) {
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
const field = get(_fields, fieldName);
return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
}))).every(Boolean);
!(!validationResult && !_formState.isValid) && _setValid();
}
else {
validationResult = isValid = await executeBuiltInValidation(_fields);
}
_subjects.state.next({
...(!isString(name) ||
((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
isValid !== _formState.isValid)
? {}
: { name }),
...(_options.resolver || !name ? { isValid } : {}),
errors: _formState.errors,
});
options.shouldFocus &&
!validationResult &&
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
return validationResult;
};
const getValues = (fieldNames, config) => {
let values = {
...(_state.mount ? _formValues : _defaultValues),
};
if (config) {
values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
}
return isUndefined(fieldNames)
? values
: isString(fieldNames)
? get(values, fieldNames)
: fieldNames.map((name) => get(values, name));
};
const getFieldState = (name, formState) => ({
invalid: !!get((formState || _formState).errors, name),
isDirty: !!get((formState || _formState).dirtyFields, name),
error: get((formState || _formState).errors, name),
isValidating: !!get(_formState.validatingFields, name),
isTouched: !!get((formState || _formState).touchedFields, name),
});
const clearErrors = (name) => {
name &&
convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
_subjects.state.next({
errors: name ? _formState.errors : {},
});
};
const setError = (name, error, options) => {
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
const currentError = get(_formState.errors, name) || {};
// Don't override existing error messages elsewhere in the object tree.
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
set(_formState.errors, name, {
...restOfErrorTree,
...error,
ref,
});
_subjects.state.next({
name,
errors: _formState.errors,
isValid: false,
});
options && options.shouldFocus && ref && ref.focus && ref.focus();
};
const watch = (name, defaultValue) => isFunction(name)
? _subjects.state.subscribe({
next: (payload) => 'values' in payload &&
name(_getWatch(undefined, defaultValue), payload),
})
: _getWatch(name, defaultValue, true);
const _subscribe = (props) => _subjects.state.subscribe({
next: (formState) => {
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
props.callback({
values: { ..._formValues },
..._formState,
...formState,
defaultValues: _defaultValues,
});
}
},
}).unsubscribe;
const subscribe = (props) => {
_state.mount = true;
_proxySubscribeFormState = {
..._proxySubscribeFormState,
...props.formState,
};
return _subscribe({
...props,
formState: _proxySubscribeFormState,
});
};
const unregister = (name, options = {}) => {
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
_names.mount.delete(fieldName);
_names.array.delete(fieldName);
if (!options.keepValue) {
unset(_fields, fieldName);
unset(_formValues, fieldName);
}
!options.keepError && unset(_formState.errors, fieldName);
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
!options.keepTouched && unset(_formState.touchedFields, fieldName);
!options.keepIsValidating &&
unset(_formState.validatingFields, fieldName);
!_options.shouldUnregister &&
!options.keepDefaultValue &&
unset(_defaultValues, fieldName);
}
_subjects.state.next({
values: cloneObject(_formValues),
});
_subjects.state.next({
..._formState,
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
});
!options.keepIsValid && _setValid();
};
const _setDisabledField = ({ disabled, name, }) => {
if ((isBoolean(disabled) && _state.mount) ||
!!disabled ||
_names.disabled.has(name)) {
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
}
};
const register = (name, options = {}) => {
let field = get(_fields, name);
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
set(_fields, name, {
...(field || {}),
_f: {
...(field && field._f ? field._f : { ref: { name } }),
name,
mount: true,
...options,
},
});
_names.mount.add(name);
if (field) {
_setDisabledField({
disabled: isBoolean(options.disabled)
? options.disabled
: _options.disabled,
name,
});
}
else {
updateValidAndValue(name, true, options.value);
}
return {
...(disabledIsDefined
? { disabled: options.disabled || _options.disabled }
: {}),
...(_options.progressive
? {
required: !!options.required,
min: getRuleValue(options.min),
max: getRuleValue(options.max),
minLength: getRuleValue(options.minLength),
maxLength: getRuleValue(options.maxLength),
pattern: getRuleValue(options.pattern),
}
: {}),
name,
onChange,
onBlur: onChange,
ref: (ref) => {
if (ref) {
register(name, options);
field = get(_fields, name);
const fieldRef = isUndefined(ref.value)
? ref.querySelectorAll
? ref.querySelectorAll('input,select,textarea')[0] || ref
: ref
: ref;
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
const refs = field._f.refs || [];
if (radioOrCheckbox
? refs.find((option) => option === fieldRef)
: fieldRef === field._f.ref) {
return;
}
set(_fields, name, {
_f: {
...field._f,
...(radioOrCheckbox
? {
refs: [
...refs.filter(live),
fieldRef,
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
],
ref: { type: fieldRef.type, name },
}
: { ref: fieldRef }),
},
});
updateValidAndValue(name, false, undefined, fieldRef);
}
else {
field = get(_fields, name, {});
if (field._f) {
field._f.mount = false;
}
(_options.shouldUnregister || options.shouldUnregister) &&
!(isNameInFieldArray(_names.array, name) && _state.action) &&
_names.unMount.add(name);
}
},
};
};
const _focusError = () => _options.shouldFocusError &&
iterateFieldsByAction(_fields, _focusInput, _names.mount);
const _disableForm = (disabled) => {
if (isBoolean(disabled)) {
_subjects.state.next({ disabled });
iterateFieldsByAction(_fields, (ref, name) => {
const currentField = get(_fields, name);
if (currentField) {
ref.disabled = currentField._f.disabled || disabled;
if (Array.isArray(currentField._f.refs)) {
currentField._f.refs.forEach((inputRef) => {
inputRef.disabled = currentField._f.disabled || disabled;
});
}
}
}, 0, false);
}
};
const handleSubmit = (onValid, onInvalid) => async (e) => {
let onValidError = undefined;
if (e) {
e.preventDefault && e.preventDefault();
e.persist &&
e.persist();
}
let fieldValues = cloneObject(_formValues);
_subjects.state.next({
isSubmitting: true,
});
if (_options.resolver) {
const { errors, values } = await _runSchema();
_formState.errors = errors;
fieldValues = cloneObject(values);
}
else {
await executeBuiltInValidation(_fields);
}
if (_names.disabled.size) {
for (const name of _names.disabled) {
unset(fieldValues, name);
}
}
unset(_formState.errors, 'root');
if (isEmptyObject(_formState.errors)) {
_subjects.state.next({
errors: {},
});
try {
await onValid(fieldValues, e);
}
catch (error) {
onValidError = error;
}
}
else {
if (onInvalid) {
await onInvalid({ ..._formState.errors }, e);
}
_focusError();
setTimeout(_focusError);
}
_subjects.state.next({
isSubmitted: true,
isSubmitting: false,
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
submitCount: _formState.submitCount + 1,
errors: _formState.errors,
});
if (onValidError) {
throw onValidError;
}
};
const resetField = (name, options = {}) => {
if (get(_fields, name)) {
if (isUndefined(options.defaultValue)) {
setValue(name, cloneObject(get(_defaultValues, name)));
}
else {
setValue(name, options.defaultValue);
set(_defaultValues, name, cloneObject(options.defaultValue));
}
if (!options.keepTouched) {
unset(_formState.touchedFields, name);
}
if (!options.keepDirty) {
unset(_formState.dirtyFields, name);
_formState.isDirty = options.defaultValue
? _getDirty(name, cloneObject(get(_defaultValues, name)))
: _getDirty();
}
if (!options.keepError) {
unset(_formState.errors, name);
_proxyFormState.isValid && _setValid();
}
_subjects.state.next({ ..._formState });
}
};
const _reset = (formValues, keepStateOptions = {}) => {
const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
const cloneUpdatedValues = cloneObject(updatedValues);
const isEmptyResetValues = isEmptyObject(formValues);
const values = isEmptyResetValues ? _defaultValues : cloneUpdatedValues;
if (!keepStateOptions.keepDefaultValues) {
_defaultValues = updatedValues;
}
if (!keepStateOptions.keepValues) {
if (keepStateOptions.keepDirtyValues) {
const fieldsToCheck = new Set([
..._names.mount,
...Object.keys(getDirtyFields(_defaultValues, _formValues)),
]);
for (const fieldName of Array.from(fieldsToCheck)) {
get(_formState.dirtyFields, fieldName)
? set(values, fieldName, get(_formValues, fieldName))
: setValue(fieldName, get(values, fieldName));
}
}
else {
if (isWeb && isUndefined(formValues)) {
for (const name of _names.mount) {
const field = get(_fields, name);
if (field && field._f) {
const fieldReference = Array.isArray(field._f.refs)
? field._f.refs[0]
: field._f.ref;
if (isHTMLElement(fieldReference)) {
const form = fieldReference.closest('form');
if (form) {
form.reset();
break;
}
}
}
}
}
if (keepStateOptions.keepFieldsRef) {
for (const fieldName of _names.mount) {
setValue(fieldName, get(values, fieldName));
}
}
else {
_fields = {};
}
}
_formValues = _options.shouldUnregister
? keepStateOptions.keepDefaultValues
? cloneObject(_defaultValues)
: {}
: cloneObject(values);
_subjects.array.next({
values: { ...values },
});
_subjects.state.next({
values: { ...values },
});
}
_names = {
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
unMount: new Set(),
array: new Set(),
disabled: new Set(),
watch: new Set(),
watchAll: false,
focus: '',
};
_state.mount =
!_proxyFormState.isValid ||
!!keepStateOptions.keepIsValid ||
!!keepStateOptions.keepDirtyValues ||
(!_options.shouldUnregister && !isEmptyObject(values));
_state.watch = !!_options.shouldUnregister;
_subjects.state.next({
submitCount: keepStateOptions.keepSubmitCount
? _formState.submitCount
: 0,
isDirty: isEmptyResetValues
? false
: keepStateOptions.keepDirty
? _formState.isDirty
: !!(keepStateOptions.keepDefaultValues &&
!deepEqual(formValues, _defaultValues)),
isSubmitted: keepStateOptions.keepIsSubmitted
? _formState.isSubmitted
: false,
dirtyFields: isEmptyResetValues
? {}
: keepStateOptions.keepDirtyValues
? keepStateOptions.keepDefaultValues && _formValues
? getDirtyFields(_defaultValues, _formValues)
: _formState.dirtyFields
: keepStateOptions.keepDefaultValues && formValues
? getDirtyFields(_defaultValues, formValues)
: keepStateOptions.keepDirty
? _formState.dirtyFields
: {},
touchedFields: keepStateOptions.keepTouched
? _formState.touchedFields
: {},
errors: keepStateOptions.keepErrors ? _formState.errors : {},
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
? _formState.isSubmitSuccessful
: false,
isSubmitting: false,
defaultValues: _defaultValues,
});
};
const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
? formValues(_formValues)
: formValues, keepStateOptions);
const setFocus = (name, options = {}) => {
const field = get(_fields, name);
const fieldReference = field && field._f;
if (fieldReference) {
const fieldRef = fieldReference.refs
? fieldReference.refs[0]
: fieldReference.ref;
if (fieldRef.focus) {
fieldRef.focus();
options.shouldSelect &&
isFunction(fieldRef.select) &&
fieldRef.select();
}
}
};
const _setFormState = (updatedFormState) => {
_formState = {
..._formState,
...updatedFormState,
};
};
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
_options.defaultValues().then((values) => {
reset(values, _options.resetOptions);
_subjects.state.next({
isLoading: false,
});
});
const methods = {
control: {
register,
unregister,
getFieldState,
handleSubmit,
setError,
_subscribe,
_runSchema,
_focusError,
_getWatch,
_getDirty,
_setValid,
_setFieldArray,
_setDisabledField,
_setErrors,
_getFieldArray,
_reset,
_resetDefaultValues,
_removeUnmounted,
_disableForm,
_subjects,
_proxyFormState,
get _fields() {
return _fields;
},
get _formValues() {
return _formValues;
},
get _state() {
return _state;
},
set _state(value) {
_state = value;
},
get _defaultValues() {
return _defaultValues;
},
get _names() {
return _names;
},
set _names(value) {
_names = value;
},
get _formState() {
return _formState;
},
get _options() {
return _options;
},
set _options(value) {
_options = {
..._options,
...value,
};
},
},
subscribe,
trigger,
register,
handleSubmit,
watch,
setValue,
getValues,
reset,
resetField,
clearErrors,
unregister,
setError,
setFocus,
getFieldState,
};
return {
...methods,
formControl: methods,
};
}
var generateId = () => {
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
return crypto.randomUUID();
}
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16 + d) % 16 | 0;
return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
});
};
var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
? options.focusName ||
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
: '';
var appendAt = (data, value) => [
...data,
...convertToArrayPayload(value),
];
var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
function insert(data, index, value) {
return [
...data.slice(0, index),
...convertToArrayPayload(value),
...data.slice(index),
];
}
var moveArrayAt = (data, from, to) => {
if (!Array.isArray(data)) {
return [];
}
if (isUndefined(data[to])) {
data[to] = undefined;
}
data.splice(to, 0, data.splice(from, 1)[0]);
return data;
};
var prependAt = (data, value) => [
...convertToArrayPayload(value),
...convertToArrayPayload(data),
];
function removeAtIndexes(data, indexes) {
let i = 0;
const temp = [...data];
for (const index of indexes) {
temp.splice(index - i, 1);
i++;
}
return compact(temp).length ? temp : [];
}
var removeArrayAt = (data, index) => isUndefined(index)
? []
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
var swapArrayAt = (data, indexA, indexB) => {
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
};
var updateAt = (fieldValues, index, value) => {
fieldValues[index] = value;
return fieldValues;
};
/**
* A custom hook that exposes convenient methods to perform operations with a list of dynamic inputs that need to be appended, updated, removed etc. • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) • [Video](https://youtu.be/4MrbfGSFY2A)
*
* @remarks
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
*
* @param props - useFieldArray props
*
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
*
* @example
* ```tsx
* function App() {
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
* defaultValues: {
* test: []
* }
* });
* const { fields, append } = useFieldArray({
* control,
* name: "test"
* });
*
* return (
*
* );
* }
* ```
*/
function useFieldArray(props) {
const methods = useFormContext();
const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props;
const [fields, setFields] = React.useState(control._getFieldArray(name));
const ids = React.useRef(control._getFieldArray(name).map(generateId));
const _actioned = React.useRef(false);
control._names.array.add(name);
React.useMemo(() => rules &&
fields.length >= 0 &&
control.register(name, rules), [control, name, fields.length, rules]);
useIsomorphicLayoutEffect(() => control._subjects.array.subscribe({
next: ({ values, name: fieldArrayName, }) => {
if (fieldArrayName === name || !fieldArrayName) {
const fieldValues = get(values, name);
if (Array.isArray(fieldValues)) {
setFields(fieldValues);
ids.current = fieldValues.map(generateId);
}
}
},
}).unsubscribe, [control, name]);
const updateValues = React.useCallback((updatedFieldArrayValues) => {
_actioned.current = true;
control._setFieldArray(name, updatedFieldArrayValues);
}, [control, name]);
const append = (value, options) => {
const appendValue = convertToArrayPayload(cloneObject(value));
const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
ids.current = appendAt(ids.current, appendValue.map(generateId));
updateValues(updatedFieldArrayValues);
setFields(updatedFieldArrayValues);
control._setFieldArray(name, updatedFieldArrayValues, appendAt, {
argA: fillEmptyArray(value),
});
};
const prepend = (value, options) => {
const prependValue = convertToArrayPayload(cloneObject(value));
const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
control._names.focus = getFocusFieldName(name, 0, options);
ids.current = prependAt(ids.current, prependValue.map(generateId));
updateValues(updatedFieldArrayValues);
setFields(updatedFieldArrayValues);
control._setFieldArray(name, updatedFieldArrayValues, prependAt, {
argA: fillEmptyArray(value),
});
};
const remove = (index) => {
const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
ids.current = removeArrayAt(ids.current, index);
updateValues(updatedFieldArrayValues);
setFields(updatedFieldArrayValues);
!Array.isArray(get(control._fields, name)) &&
set(control._fields, name, undefined);
control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
argA: index,
});
};
const insert$1 = (index, value, options) => {
const insertValue = convertToArrayPayload(cloneObject(value));
const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
control._names.focus = getFocusFieldName(name, index, options);
ids.current = insert(ids.current, index, insertValue.map(generateId));
updateValues(updatedFieldArrayValues);
setFields(updatedFieldArrayValues);
control._setFieldArray(name, updatedFieldArrayValues, insert, {
argA: index,
argB: fillEmptyArray(value),
});
};
const swap = (indexA, indexB) => {
const updatedFieldArrayValues = control._getFieldArray(name);
swapArrayAt(updatedFieldArrayValues, indexA, indexB);
swapArrayAt(ids.current, indexA, indexB);
updateValues(updatedFieldArrayValues);
setFields(updatedFieldArrayValues);
control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, {
argA: indexA,
argB: indexB,
}, false);
};
const move = (from, to) => {
const updatedFieldArrayValues = control._getFieldArray(name);
moveArrayAt(updatedFieldArrayValues, from, to);
moveArrayAt(ids.current, from, to);
updateValues(updatedFieldArrayValues);
setFields(updatedFieldArrayValues);
control._setFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
argA: from,
argB: to,
}, false);
};
const update = (index, value) => {
const updateValue = cloneObject(value);
const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
updateValues(updatedFieldArrayValues);
setFields([...updatedFieldArrayValues]);
control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
argA: index,
argB: updateValue,
}, true, false);
};
const replace = (value) => {
const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
ids.current = updatedFieldArrayValues.map(generateId);
updateValues([...updatedFieldArrayValues]);
setFields([...updatedFieldArrayValues]);
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
};
React.useEffect(() => {
control._state.action = false;
isWatched(name, control._names) &&
control._subjects.state.next({
...control._formState,
});
if (_actioned.current &&
(!getValidationModes(control._options.mode).isOnSubmit ||
control._formState.isSubmitted) &&
!getValidationModes(control._options.reValidateMode).isOnSubmit) {
if (control._options.resolver) {
control._runSchema([name]).then((result) => {
const error = get(result.errors, name);
const existingError = get(control._formState.errors, name);
if (existingError
? (!error && existingError.type) ||
(error &&
(existingError.type !== error.type ||
existingError.message !== error.message))
: error && error.type) {
error
? set(control._formState.errors, name, error)
: unset(control._formState.errors, name);
control._subjects.state.next({
errors: control._formState.errors,
});
}
});
}
else {
const field = get(control._fields, name);
if (field &&
field._f &&
!(getValidationModes(control._options.reValidateMode).isOnSubmit &&
getValidationModes(control._options.mode).isOnSubmit)) {
validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
control._subjects.state.next({
errors: updateFieldArrayRootError(control._formState.errors, error, name),
}));
}
}
}
control._subjects.state.next({
name,
values: cloneObject(control._formValues),
});
control._names.focus &&
iterateFieldsByAction(control._fields, (ref, key) => {
if (control._names.focus &&
key.startsWith(control._names.focus) &&
ref.focus) {
ref.focus();
return 1;
}
return;
});
control._names.focus = '';
control._setValid();
_actioned.current = false;
}, [fields, name, control]);
React.useEffect(() => {
!get(control._formValues, name) && control._setFieldArray(name);
return () => {
const updateMounted = (name, value) => {
const field = get(control._fields, name);
if (field && field._f) {
field._f.mount = value;
}
};
control._options.shouldUnregister || shouldUnregister
? control.unregister(name)
: updateMounted(name, false);
};
}, [name, control, keyName, shouldUnregister]);
return {
swap: React.useCallback(swap, [updateValues, name, control]),
move: React.useCallback(move, [updateValues, name, control]),
prepend: React.useCallback(prepend, [updateValues, name, control]),
append: React.useCallback(append, [updateValues, name, control]),
remove: React.useCallback(remove, [updateValues, name, control]),
insert: React.useCallback(insert$1, [updateValues, name, control]),
update: React.useCallback(update, [updateValues, name, control]),
replace: React.useCallback(replace, [updateValues, name, control]),
fields: React.useMemo(() => fields.map((field, index) => ({
...field,
[keyName]: ids.current[index] || generateId(),
})), [fields, keyName]),
};
}
/**
* Custom hook to manage the entire form.
*
* @remarks
* [API](https://react-hook-form.com/docs/useform) • [Demo](https://codesandbox.io/s/react-hook-form-get-started-ts-5ksmm) • [Video](https://www.youtube.com/watch?v=RkXv4AXXC_4)
*
* @param props - form configuration and validation parameters.
*
* @returns methods - individual functions to manage the form state. {@link UseFormReturn}
*
* @example
* ```tsx
* function App() {
* const { register, handleSubmit, watch, formState: { errors } } = useForm();
* const onSubmit = data => console.log(data);
*
* console.log(watch("example"));
*
* return (
*
* );
* }
* ```
*/
function useForm(props = {}) {
const _formControl = react__WEBPACK_IMPORTED_MODULE_0__.useRef(undefined);
const _values = react__WEBPACK_IMPORTED_MODULE_0__.useRef(undefined);
const [formState, updateFormState] = react__WEBPACK_IMPORTED_MODULE_0__.useState({
isDirty: false,
isValidating: false,
isLoading: isFunction(props.defaultValues),
isSubmitted: false,
isSubmitting: false,
isSubmitSuccessful: false,
isValid: false,
submitCount: 0,
dirtyFields: {},
touchedFields: {},
validatingFields: {},
errors: props.errors || {},
disabled: props.disabled || false,
isReady: false,
defaultValues: isFunction(props.defaultValues)
? undefined
: props.defaultValues,
});
if (!_formControl.current) {
if (props.formControl) {
_formControl.current = {
...props.formControl,
formState,
};
if (props.defaultValues && !isFunction(props.defaultValues)) {
props.formControl.reset(props.defaultValues, props.resetOptions);
}
}
else {
const { formControl, ...rest } = createFormControl(props);
_formControl.current = {
...rest,
formState,
};
}
}
const control = _formControl.current.control;
control._options = props;
useIsomorphicLayoutEffect(() => {
const sub = control._subscribe({
formState: control._proxyFormState,
callback: () => updateFormState({ ...control._formState }),
reRenderRoot: true,
});
updateFormState((data) => ({
...data,
isReady: true,
}));
control._formState.isReady = true;
return sub;
}, [control]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (props.mode) {
control._options.mode = props.mode;
}
if (props.reValidateMode) {
control._options.reValidateMode = props.reValidateMode;
}
}, [control, props.mode, props.reValidateMode]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (props.errors) {
control._setErrors(props.errors);
control._focusError();
}
}, [control, props.errors]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
props.shouldUnregister &&
control._subjects.state.next({
values: control._getWatch(),
});
}, [control, props.shouldUnregister]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (control._proxyFormState.isDirty) {
const isDirty = control._getDirty();
if (isDirty !== formState.isDirty) {
control._subjects.state.next({
isDirty,
});
}
}
}, [control, formState.isDirty]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
var _a;
if (props.values && !deepEqual(props.values, _values.current)) {
control._reset(props.values, {
keepFieldsRef: true,
...control._options.resetOptions,
});
if (!((_a = control._options.resetOptions) === null || _a === void 0 ? void 0 : _a.keepIsValid)) {
control._setValid();
}
_values.current = props.values;
updateFormState((state) => ({ ...state }));
}
else {
control._resetDefaultValues();
}
}, [control, props.values]);
react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => {
if (!control._state.mount) {
control._setValid();
control._state.mount = true;
}
if (control._state.watch) {
control._state.watch = false;
control._subjects.state.next({ ...control._formState });
}
control._removeUnmounted();
});
_formControl.current.formState = getProxyFormState(formState, control);
return _formControl.current;
}
/**
* Watch component that subscribes to form field changes and re-renders when watched fields update.
*
* @param control - The form control object from useForm
* @param names - Array of field names to watch for changes
* @param render - The function that receives watched values and returns ReactNode
* @returns The result of calling render function with watched values
*
* @example
* The `Watch` component only re-render when the values of `foo`, `bar`, and `baz.qux` change.
* The types of `foo`, `bar`, and `baz.qux` are precisely inferred.
*
* ```tsx
* const { control } = useForm();
*
* {foo}{bar}{baz_qux}
}
* />
* ```
*/
const Watch = ({ control, names, render, }) => render(useWatch({ control, name: names }));
//# sourceMappingURL=index.esm.mjs.map
/***/ })
}]);
//# sourceMappingURL=data:application/json;charset=utf-8;base64,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QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLCtDQUErQyxPQUFPO0FBQ3REO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsQ0FBQzs7QUFFRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0Isc0JBQXNCO0FBQzFDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUI7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCLFVBQVU7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxZQUFZLHFCQUFxQjtBQUNqQztBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLFlBQVksc0dBQXNHO0FBQ2xIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsaUJBQWlCO0FBQ2pDLGdCQUFnQjtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsK0JBQStCO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekIsdUJBQXVCO0FBQ3ZCLDRCQUE0QjtBQUM1QixxQ0FBcUM7QUFDckM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdFQUFnRSxVQUFVLElBQUk7QUFDOUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdCQUFnQixTQUFTO0FBQ3pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSx3QkFBd0Isb0JBQW9CO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNB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QTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUZBQXFGO0FBQ3JGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUF5QjtBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esc0VBQXNFO0FBQ3RFO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYSw0Q0FBNEMsV0FBVztBQUNwRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCLHVCQUF1QjtBQUM5QyxxQ0FBcUMsd0JBQXdCO0FBQzdELGlCQUFpQixpQ0FBaUMsZ0JBQWdCLEdBQUc7QUFDckUsVUFBVTtBQUNWO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJCQUEyQjtBQUMzQix5QkFBeUIseUNBQVk7QUFDckMsb0JBQW9CLHlDQUFZO0FBQ2hDLHlDQUF5QywyQ0FBYztBQUN2RDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsdUJBQXVCO0FBQ3ZCLHlCQUF5QjtBQUN6Qiw0QkFBNEI7QUFDNUIsa0NBQWtDO0FBQ2xDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9CQUFvQix1QkFBdUI7QUFDM0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhDQUE4Qyx1QkFBdUI7QUFDckU7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSSw0Q0FBZTtBQUNuQixJQUFJLDRDQUFlO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJLDRDQUFlO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUksNENBQWU7QUFDbkI7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLEtBQUs7QUFDTCxJQUFJLDRDQUFlO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJLDRDQUFlO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQSwwQ0FBMEMsVUFBVTtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJLDRDQUFlO0FBQ25CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDJDQUEyQyx1QkFBdUI7QUFDbEU7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFVBQVU7QUFDckI7QUFDQTtBQUNBLGNBQWM7QUFDZCxZQUFZO0FBQ1osYUFBYSwrQkFBK0IsS0FBSyxLQUFLLFFBQVE7QUFDOUQ7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLHlCQUF5Qix1QkFBdUIsc0JBQXNCOztBQUVvRjtBQUMzSyIsInNvdXJjZXMiOlsid2VicGFjazovL3JhbXNleS1wbHVzLWZvcm1zLy4vbm9kZV9tb2R1bGVzL0ByYW1zZXktZGVzaWduLXN5c3RlbS9saW5rL2Rpc3QvTGluay5lc20uanMiLCJ3ZWJwYWNrOi8vcmFtc2V5LXBsdXMtZm9ybXMvLi9ub2RlX21vZHVsZXMvcmVhY3QtaG9vay1mb3JtL2Rpc3QvaW5kZXguZXNtLm1qcyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QsIHsgZm9yd2FyZFJlZiB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCBjbGFzc05hbWVzIGZyb20gJ2NsYXNzbmFtZXMnO1xuXG4vKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXHJcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxyXG5cclxuUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55XHJcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cclxuXHJcblRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEhcclxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXHJcbkFORCBGSVRORVNTLiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SIEJFIExJQUJMRSBGT1IgQU5ZIFNQRUNJQUwsIERJUkVDVCxcclxuSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NXHJcbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXHJcbk9USEVSIFRPUlRJT1VTIEFDVElPTiwgQVJJU0lORyBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBVU0UgT1JcclxuUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS5cclxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cclxuLyogZ2xvYmFsIFJlZmxlY3QsIFByb21pc2UsIFN1cHByZXNzZWRFcnJvciwgU3ltYm9sLCBJdGVyYXRvciAqL1xyXG5cclxuXHJcbnZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xyXG4gICAgX19hc3NpZ24gPSBPYmplY3QuYXNzaWduIHx8IGZ1bmN0aW9uIF9fYXNzaWduKHQpIHtcclxuICAgICAgICBmb3IgKHZhciBzLCBpID0gMSwgbiA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBuOyBpKyspIHtcclxuICAgICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcclxuICAgICAgICAgICAgZm9yICh2YXIgcCBpbiBzKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKHMsIHApKSB0W3BdID0gc1twXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHQ7XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XHJcbn07XHJcblxyXG5mdW5jdGlvbiBfX3Jlc3QocywgZSkge1xyXG4gICAgdmFyIHQgPSB7fTtcclxuICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSAmJiBlLmluZGV4T2YocCkgPCAwKVxyXG4gICAgICAgIHRbcF0gPSBzW3BdO1xyXG4gICAgaWYgKHMgIT0gbnVsbCAmJiB0eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyA9PT0gXCJmdW5jdGlvblwiKVxyXG4gICAgICAgIGZvciAodmFyIGkgPSAwLCBwID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzKTsgaSA8IHAubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDAgJiYgT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHMsIHBbaV0pKVxyXG4gICAgICAgICAgICAgICAgdFtwW2ldXSA9IHNbcFtpXV07XHJcbiAgICAgICAgfVxyXG4gICAgcmV0dXJuIHQ7XHJcbn1cclxuXHJcbnR5cGVvZiBTdXBwcmVzc2VkRXJyb3IgPT09IFwiZnVuY3Rpb25cIiA/IFN1cHByZXNzZWRFcnJvciA6IGZ1bmN0aW9uIChlcnJvciwgc3VwcHJlc3NlZCwgbWVzc2FnZSkge1xyXG4gICAgdmFyIGUgPSBuZXcgRXJyb3IobWVzc2FnZSk7XHJcbiAgICByZXR1cm4gZS5uYW1lID0gXCJTdXBwcmVzc2VkRXJyb3JcIiwgZS5lcnJvciA9IGVycm9yLCBlLnN1cHByZXNzZWQgPSBzdXBwcmVzc2VkLCBlO1xyXG59O1xuXG52YXIgZ2V0Q29uZGl0aW9uYWxQcm9wcyA9IGZ1bmN0aW9uIChkaXNhYmxlZCwgaXNMaW5rLCBocmVmKSB7IHJldHVybiAoe1xuICAgIGhyZWY6ICFkaXNhYmxlZCA/IGhyZWYgOiB1bmRlZmluZWQsXG4gICAgXCJhcmlhLWRpc2FibGVkXCI6IChpc0xpbmsgJiYgZGlzYWJsZWQpIHx8IHVuZGVmaW5lZCxcbiAgICBkaXNhYmxlZDogIWlzTGluayAmJiBkaXNhYmxlZCxcbn0pOyB9O1xudmFyIGdldExpbmtJY29uUHJvcHMgPSBmdW5jdGlvbiAoaWNvblBvc2l0aW9uKSB7XG4gICAgdmFyIF9hO1xuICAgIHZhciBpY29uQ2xhc3NlcyA9IGNsYXNzTmFtZXMoXCJyZHMtTGluay1pY29uXCIsIFwicmRzLUxpbmstaWNvbi0tXCIuY29uY2F0KGljb25Qb3NpdGlvbikpO1xuICAgIHJldHVybiBfYSA9IHtcbiAgICAgICAgICAgIGZpbGw6IFwiY3VycmVudENvbG9yXCIsXG4gICAgICAgICAgICBjbGFzc05hbWU6IGljb25DbGFzc2VzXG4gICAgICAgIH0sXG4gICAgICAgIF9hW1wiYXJpYS1oaWRkZW5cIl0gPSB0cnVlLFxuICAgICAgICBfYS5mb2N1c2FibGUgPSBmYWxzZSxcbiAgICAgICAgX2E7XG59O1xuZnVuY3Rpb24gTGluayhfYSwgcmVmKSB7XG4gICAgdmFyIF9iO1xuICAgIHZhciBjaGlsZHJlbiA9IF9hLmNoaWxkcmVuLCBjbGFzc05hbWUgPSBfYS5jbGFzc05hbWUsIGRpc2FibGVkID0gX2EuZGlzYWJsZWQsIGVsZW1lbnQgPSBfYS5lbGVtZW50LCBocmVmID0gX2EuaHJlZiwgTGlua0ljb24gPSBfYS5pY29uLCBfYyA9IF9hLmljb25Qb3NpdGlvbiwgaWNvblBvc2l0aW9uID0gX2MgPT09IHZvaWQgMCA/IFwibGVmdFwiIDogX2MsIF9kID0gX2EuaW5oZXJpdENvbG9yLCBpbmhlcml0Q29sb3IgPSBfZCA9PT0gdm9pZCAwID8gZmFsc2UgOiBfZCwgX2UgPSBfYS5pc09uRGFya0NhbnZhcywgaXNPbkRhcmtDYW52YXMgPSBfZSA9PT0gdm9pZCAwID8gZmFsc2UgOiBfZSwgX2YgPSBfYS5zaXplLCBzaXplID0gX2YgPT09IHZvaWQgMCA/IFwibWVkaXVtXCIgOiBfZiwgdGV4dCA9IF9hLnRleHQsIHJlc3QgPSBfX3Jlc3QoX2EsIFtcImNoaWxkcmVuXCIsIFwiY2xhc3NOYW1lXCIsIFwiZGlzYWJsZWRcIiwgXCJlbGVtZW50XCIsIFwiaHJlZlwiLCBcImljb25cIiwgXCJpY29uUG9zaXRpb25cIiwgXCJpbmhlcml0Q29sb3JcIiwgXCJpc09uRGFya0NhbnZhc1wiLCBcInNpemVcIiwgXCJ0ZXh0XCJdKTtcbiAgICB2YXIgaXNMaW5rID0gZWxlbWVudCAhPT0gXCJidXR0b25cIjtcbiAgICB2YXIgRWxlbWVudCA9IGVsZW1lbnQgfHwgXCJhXCI7XG4gICAgdmFyIGxpbmtDbGFzc2VzID0gY2xhc3NOYW1lcyhcInJkcy1MaW5rXCIsIChfYiA9IHt9LFxuICAgICAgICBfYltcInJkcy1MaW5rLS1cIi5jb25jYXQoc2l6ZSldID0gc2l6ZSAhPT0gXCJtZWRpdW1cIixcbiAgICAgICAgX2JbXCJyZHMtTGluay0taW5oZXJpdENvbG9yXCJdID0gaW5oZXJpdENvbG9yLFxuICAgICAgICBfYltcImlzLWRpc2FibGVkXCJdID0gaXNMaW5rICYmIGRpc2FibGVkLFxuICAgICAgICBfYltcIm9uLWRhcmtDYW52YXNcIl0gPSBpc09uRGFya0NhbnZhcyxcbiAgICAgICAgX2IpLCBjbGFzc05hbWUpO1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChFbGVtZW50LCBfX2Fzc2lnbih7IGNsYXNzTmFtZTogbGlua0NsYXNzZXMgfSwgZ2V0Q29uZGl0aW9uYWxQcm9wcyhkaXNhYmxlZCwgaXNMaW5rLCBocmVmKSwgcmVzdCwgeyByZWY6IHJlZiB9KSxcbiAgICAgICAgTGlua0ljb24gJiYgaWNvblBvc2l0aW9uID09PSBcImxlZnRcIiAmJiAoUmVhY3QuY3JlYXRlRWxlbWVudChMaW5rSWNvbiwgX19hc3NpZ24oe30sIGdldExpbmtJY29uUHJvcHMoaWNvblBvc2l0aW9uKSkpKSxcbiAgICAgICAgY2hpbGRyZW4gfHwgdGV4dCxcbiAgICAgICAgTGlua0ljb24gJiYgaWNvblBvc2l0aW9uID09PSBcInJpZ2h0XCIgJiYgKFJlYWN0LmNyZWF0ZUVsZW1lbnQoTGlua0ljb24sIF9fYXNzaWduKHt9LCBnZXRMaW5rSWNvblByb3BzKGljb25Qb3NpdGlvbikpKSkpKTtcbn1cbnZhciBDb21wb25lbnQgPSBmb3J3YXJkUmVmKExpbmspO1xuQ29tcG9uZW50LmRpc3BsYXlOYW1lID0gXCJMaW5rXCI7XG5cbmV4cG9ydCB7IENvbXBvbmVudCBhcyBkZWZhdWx0IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1MaW5rLmVzbS5qcy5tYXBcbiIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5cbnZhciBpc0NoZWNrQm94SW5wdXQgPSAoZWxlbWVudCkgPT4gZWxlbWVudC50eXBlID09PSAnY2hlY2tib3gnO1xuXG52YXIgaXNEYXRlT2JqZWN0ID0gKHZhbHVlKSA9PiB2YWx1ZSBpbnN0YW5jZW9mIERhdGU7XG5cbnZhciBpc051bGxPclVuZGVmaW5lZCA9ICh2YWx1ZSkgPT4gdmFsdWUgPT0gbnVsbDtcblxuY29uc3QgaXNPYmplY3RUeXBlID0gKHZhbHVlKSA9PiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xudmFyIGlzT2JqZWN0ID0gKHZhbHVlKSA9PiAhaXNOdWxsT3JVbmRlZmluZWQodmFsdWUpICYmXG4gICAgIUFycmF5LmlzQXJyYXkodmFsdWUpICYmXG4gICAgaXNPYmplY3RUeXBlKHZhbHVlKSAmJlxuICAgICFpc0RhdGVPYmplY3QodmFsdWUpO1xuXG52YXIgZ2V0RXZlbnRWYWx1ZSA9IChldmVudCkgPT4gaXNPYmplY3QoZXZlbnQpICYmIGV2ZW50LnRhcmdldFxuICAgID8gaXNDaGVja0JveElucHV0KGV2ZW50LnRhcmdldClcbiAgICAgICAgPyBldmVudC50YXJnZXQuY2hlY2tlZFxuICAgICAgICA6IGV2ZW50LnRhcmdldC52YWx1ZVxuICAgIDogZXZlbnQ7XG5cbnZhciBnZXROb2RlUGFyZW50TmFtZSA9IChuYW1lKSA9PiBuYW1lLnN1YnN0cmluZygwLCBuYW1lLnNlYXJjaCgvXFwuXFxkKyhcXC58JCkvKSkgfHwgbmFtZTtcblxudmFyIGlzTmFtZUluRmllbGRBcnJheSA9IChuYW1lcywgbmFtZSkgPT4gbmFtZXMuaGFzKGdldE5vZGVQYXJlbnROYW1lKG5hbWUpKTtcblxudmFyIGlzUGxhaW5PYmplY3QgPSAodGVtcE9iamVjdCkgPT4ge1xuICAgIGNvbnN0IHByb3RvdHlwZUNvcHkgPSB0ZW1wT2JqZWN0LmNvbnN0cnVjdG9yICYmIHRlbXBPYmplY3QuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgIHJldHVybiAoaXNPYmplY3QocHJvdG90eXBlQ29weSkgJiYgcHJvdG90eXBlQ29weS5oYXNPd25Qcm9wZXJ0eSgnaXNQcm90b3R5cGVPZicpKTtcbn07XG5cbnZhciBpc1dlYiA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmXG4gICAgdHlwZW9mIHdpbmRvdy5IVE1MRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xuXG5mdW5jdGlvbiBjbG9uZU9iamVjdChkYXRhKSB7XG4gICAgbGV0IGNvcHk7XG4gICAgY29uc3QgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkoZGF0YSk7XG4gICAgY29uc3QgaXNGaWxlTGlzdEluc3RhbmNlID0gdHlwZW9mIEZpbGVMaXN0ICE9PSAndW5kZWZpbmVkJyA/IGRhdGEgaW5zdGFuY2VvZiBGaWxlTGlzdCA6IGZhbHNlO1xuICAgIGlmIChkYXRhIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICBjb3B5ID0gbmV3IERhdGUoZGF0YSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEoaXNXZWIgJiYgKGRhdGEgaW5zdGFuY2VvZiBCbG9iIHx8IGlzRmlsZUxpc3RJbnN0YW5jZSkpICYmXG4gICAgICAgIChpc0FycmF5IHx8IGlzT2JqZWN0KGRhdGEpKSkge1xuICAgICAgICBjb3B5ID0gaXNBcnJheSA/IFtdIDogT2JqZWN0LmNyZWF0ZShPYmplY3QuZ2V0UHJvdG90eXBlT2YoZGF0YSkpO1xuICAgICAgICBpZiAoIWlzQXJyYXkgJiYgIWlzUGxhaW5PYmplY3QoZGF0YSkpIHtcbiAgICAgICAgICAgIGNvcHkgPSBkYXRhO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29weVtrZXldID0gY2xvbmVPYmplY3QoZGF0YVtrZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgICByZXR1cm4gY29weTtcbn1cblxudmFyIGlzS2V5ID0gKHZhbHVlKSA9PiAvXlxcdyokLy50ZXN0KHZhbHVlKTtcblxudmFyIGlzVW5kZWZpbmVkID0gKHZhbCkgPT4gdmFsID09PSB1bmRlZmluZWQ7XG5cbnZhciBjb21wYWN0ID0gKHZhbHVlKSA9PiBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlLmZpbHRlcihCb29sZWFuKSA6IFtdO1xuXG52YXIgc3RyaW5nVG9QYXRoID0gKGlucHV0KSA9PiBjb21wYWN0KGlucHV0LnJlcGxhY2UoL1tcInwnXXxcXF0vZywgJycpLnNwbGl0KC9cXC58XFxbLykpO1xuXG52YXIgZ2V0ID0gKG9iamVjdCwgcGF0aCwgZGVmYXVsdFZhbHVlKSA9PiB7XG4gICAgaWYgKCFwYXRoIHx8ICFpc09iamVjdChvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdCA9IChpc0tleShwYXRoKSA/IFtwYXRoXSA6IHN0cmluZ1RvUGF0aChwYXRoKSkucmVkdWNlKChyZXN1bHQsIGtleSkgPT4gaXNOdWxsT3JVbmRlZmluZWQocmVzdWx0KSA/IHJlc3VsdCA6IHJlc3VsdFtrZXldLCBvYmplY3QpO1xuICAgIHJldHVybiBpc1VuZGVmaW5lZChyZXN1bHQpIHx8IHJlc3VsdCA9PT0gb2JqZWN0XG4gICAgICAgID8gaXNVbmRlZmluZWQob2JqZWN0W3BhdGhdKVxuICAgICAgICAgICAgPyBkZWZhdWx0VmFsdWVcbiAgICAgICAgICAgIDogb2JqZWN0W3BhdGhdXG4gICAgICAgIDogcmVzdWx0O1xufTtcblxudmFyIGlzQm9vbGVhbiA9ICh2YWx1ZSkgPT4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG5cbnZhciBzZXQgPSAob2JqZWN0LCBwYXRoLCB2YWx1ZSkgPT4ge1xuICAgIGxldCBpbmRleCA9IC0xO1xuICAgIGNvbnN0IHRlbXBQYXRoID0gaXNLZXkocGF0aCkgPyBbcGF0aF0gOiBzdHJpbmdUb1BhdGgocGF0aCk7XG4gICAgY29uc3QgbGVuZ3RoID0gdGVtcFBhdGgubGVuZ3RoO1xuICAgIGNvbnN0IGxhc3RJbmRleCA9IGxlbmd0aCAtIDE7XG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgY29uc3Qga2V5ID0gdGVtcFBhdGhbaW5kZXhdO1xuICAgICAgICBsZXQgbmV3VmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgaWYgKGluZGV4ICE9PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICAgIGNvbnN0IG9ialZhbHVlID0gb2JqZWN0W2tleV07XG4gICAgICAgICAgICBuZXdWYWx1ZSA9XG4gICAgICAgICAgICAgICAgaXNPYmplY3Qob2JqVmFsdWUpIHx8IEFycmF5LmlzQXJyYXkob2JqVmFsdWUpXG4gICAgICAgICAgICAgICAgICAgID8gb2JqVmFsdWVcbiAgICAgICAgICAgICAgICAgICAgOiAhaXNOYU4oK3RlbXBQYXRoW2luZGV4ICsgMV0pXG4gICAgICAgICAgICAgICAgICAgICAgICA/IFtdXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHt9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXkgPT09ICdfX3Byb3RvX18nIHx8IGtleSA9PT0gJ2NvbnN0cnVjdG9yJyB8fCBrZXkgPT09ICdwcm90b3R5cGUnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgb2JqZWN0W2tleV0gPSBuZXdWYWx1ZTtcbiAgICAgICAgb2JqZWN0ID0gb2JqZWN0W2tleV07XG4gICAgfVxufTtcblxuY29uc3QgRVZFTlRTID0ge1xuICAgIEJMVVI6ICdibHVyJyxcbiAgICBGT0NVU19PVVQ6ICdmb2N1c291dCcsXG4gICAgQ0hBTkdFOiAnY2hhbmdlJyxcbn07XG5jb25zdCBWQUxJREFUSU9OX01PREUgPSB7XG4gICAgb25CbHVyOiAnb25CbHVyJyxcbiAgICBvbkNoYW5nZTogJ29uQ2hhbmdlJyxcbiAgICBvblN1Ym1pdDogJ29uU3VibWl0JyxcbiAgICBvblRvdWNoZWQ6ICdvblRvdWNoZWQnLFxuICAgIGFsbDogJ2FsbCcsXG59O1xuY29uc3QgSU5QVVRfVkFMSURBVElPTl9SVUxFUyA9IHtcbiAgICBtYXg6ICdtYXgnLFxuICAgIG1pbjogJ21pbicsXG4gICAgbWF4TGVuZ3RoOiAnbWF4TGVuZ3RoJyxcbiAgICBtaW5MZW5ndGg6ICdtaW5MZW5ndGgnLFxuICAgIHBhdHRlcm46ICdwYXR0ZXJuJyxcbiAgICByZXF1aXJlZDogJ3JlcXVpcmVkJyxcbiAgICB2YWxpZGF0ZTogJ3ZhbGlkYXRlJyxcbn07XG5cbmNvbnN0IEhvb2tGb3JtQ29udGV4dCA9IFJlYWN0LmNyZWF0ZUNvbnRleHQobnVsbCk7XG5Ib29rRm9ybUNvbnRleHQuZGlzcGxheU5hbWUgPSAnSG9va0Zvcm1Db250ZXh0Jztcbi8qKlxuICogVGhpcyBjdXN0b20gaG9vayBhbGxvd3MgeW91IHRvIGFjY2VzcyB0aGUgZm9ybSBjb250ZXh0LiB1c2VGb3JtQ29udGV4dCBpcyBpbnRlbmRlZCB0byBiZSB1c2VkIGluIGRlZXBseSBuZXN0ZWQgc3RydWN0dXJlcywgd2hlcmUgaXQgd291bGQgYmVjb21lIGluY29udmVuaWVudCB0byBwYXNzIHRoZSBjb250ZXh0IGFzIGEgcHJvcC4gVG8gYmUgdXNlZCB3aXRoIHtAbGluayBGb3JtUHJvdmlkZXJ9LlxuICpcbiAqIEByZW1hcmtzXG4gKiBbQVBJXShodHRwczovL3JlYWN0LWhvb2stZm9ybS5jb20vZG9jcy91c2Vmb3JtY29udGV4dCkg4oCiIFtEZW1vXShodHRwczovL2NvZGVzYW5kYm94LmlvL3MvcmVhY3QtaG9vay1mb3JtLXY3LWZvcm0tY29udGV4dC15dHVkaSlcbiAqXG4gKiBAcmV0dXJucyByZXR1cm4gYWxsIHVzZUZvcm0gbWV0aG9kc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c3hcbiAqIGZ1bmN0aW9uIEFwcCgpIHtcbiAqICAgY29uc3QgbWV0aG9kcyA9IHVzZUZvcm0oKTtcbiAqICAgY29uc3Qgb25TdWJtaXQgPSBkYXRhID0+IGNvbnNvbGUubG9nKGRhdGEpO1xuICpcbiAqICAgcmV0dXJuIChcbiAqICAgICA8Rm9ybVByb3ZpZGVyIHsuLi5tZXRob2RzfSA+XG4gKiAgICAgICA8Zm9ybSBvblN1Ym1pdD17bWV0aG9kcy5oYW5kbGVTdWJtaXQob25TdWJtaXQpfT5cbiAqICAgICAgICAgPE5lc3RlZElucHV0IC8+XG4gKiAgICAgICAgIDxpbnB1dCB0eXBlPVwic3VibWl0XCIgLz5cbiAqICAgICAgIDwvZm9ybT5cbiAqICAgICA8L0Zvcm1Qcm92aWRlcj5cbiAqICAgKTtcbiAqIH1cbiAqXG4gKiAgZnVuY3Rpb24gTmVzdGVkSW5wdXQoKSB7XG4gKiAgIGNvbnN0IHsgcmVnaXN0ZXIgfSA9IHVzZUZvcm1Db250ZXh0KCk7IC8vIHJldHJpZXZlIGFsbCBob29rIG1ldGhvZHNcbiAqICAgcmV0dXJuIDxpbnB1dCB7Li4ucmVnaXN0ZXIoXCJ0ZXN0XCIpfSAvPjtcbiAqIH1cbiAqIGBgYFxuICovXG5jb25zdCB1c2VGb3JtQ29udGV4dCA9ICgpID0+IFJlYWN0LnVzZUNvbnRleHQoSG9va0Zvcm1Db250ZXh0KTtcbi8qKlxuICogQSBwcm92aWRlciBjb21wb25lbnQgdGhhdCBwcm9wYWdhdGVzIHRoZSBgdXNlRm9ybWAgbWV0aG9kcyB0byBhbGwgY2hpbGRyZW4gY29tcG9uZW50cyB2aWEgW1JlYWN0IENvbnRleHRdKGh0dHBzOi8vcmVhY3QuZGV2L3JlZmVyZW5jZS9yZWFjdC91c2VDb250ZXh0KSBBUEkuIFRvIGJlIHVzZWQgd2l0aCB7QGxpbmsgdXNlRm9ybUNvbnRleHR9LlxuICpcbiAqIEByZW1hcmtzXG4gKiBbQVBJXShodHRwczovL3JlYWN0LWhvb2stZm9ybS5jb20vZG9jcy91c2Vmb3JtY29udGV4dCkg4oCiIFtEZW1vXShodHRwczovL2NvZGVzYW5kYm94LmlvL3MvcmVhY3QtaG9vay1mb3JtLXY3LWZvcm0tY29udGV4dC15dHVkaSlcbiAqXG4gKiBAcGFyYW0gcHJvcHMgLSBhbGwgdXNlRm9ybSBtZXRob2RzXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCBtZXRob2RzID0gdXNlRm9ybSgpO1xuICogICBjb25zdCBvblN1Ym1pdCA9IGRhdGEgPT4gY29uc29sZS5sb2coZGF0YSk7XG4gKlxuICogICByZXR1cm4gKFxuICogICAgIDxGb3JtUHJvdmlkZXIgey4uLm1ldGhvZHN9ID5cbiAqICAgICAgIDxmb3JtIG9uU3VibWl0PXttZXRob2RzLmhhbmRsZVN1Ym1pdChvblN1Ym1pdCl9PlxuICogICAgICAgICA8TmVzdGVkSW5wdXQgLz5cbiAqICAgICAgICAgPGlucHV0IHR5cGU9XCJzdWJtaXRcIiAvPlxuICogICAgICAgPC9mb3JtPlxuICogICAgIDwvRm9ybVByb3ZpZGVyPlxuICogICApO1xuICogfVxuICpcbiAqICBmdW5jdGlvbiBOZXN0ZWRJbnB1dCgpIHtcbiAqICAgY29uc3QgeyByZWdpc3RlciB9ID0gdXNlRm9ybUNvbnRleHQoKTsgLy8gcmV0cmlldmUgYWxsIGhvb2sgbWV0aG9kc1xuICogICByZXR1cm4gPGlucHV0IHsuLi5yZWdpc3RlcihcInRlc3RcIil9IC8+O1xuICogfVxuICogYGBgXG4gKi9cbmNvbnN0IEZvcm1Qcm92aWRlciA9IChwcm9wcykgPT4ge1xuICAgIGNvbnN0IHsgY2hpbGRyZW4sIC4uLmRhdGEgfSA9IHByb3BzO1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChIb29rRm9ybUNvbnRleHQuUHJvdmlkZXIsIHsgdmFsdWU6IGRhdGEgfSwgY2hpbGRyZW4pKTtcbn07XG5cbnZhciBnZXRQcm94eUZvcm1TdGF0ZSA9IChmb3JtU3RhdGUsIGNvbnRyb2wsIGxvY2FsUHJveHlGb3JtU3RhdGUsIGlzUm9vdCA9IHRydWUpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSB7XG4gICAgICAgIGRlZmF1bHRWYWx1ZXM6IGNvbnRyb2wuX2RlZmF1bHRWYWx1ZXMsXG4gICAgfTtcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBmb3JtU3RhdGUpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHJlc3VsdCwga2V5LCB7XG4gICAgICAgICAgICBnZXQ6ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBfa2V5ID0ga2V5O1xuICAgICAgICAgICAgICAgIGlmIChjb250cm9sLl9wcm94eUZvcm1TdGF0ZVtfa2V5XSAhPT0gVkFMSURBVElPTl9NT0RFLmFsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250cm9sLl9wcm94eUZvcm1TdGF0ZVtfa2V5XSA9ICFpc1Jvb3QgfHwgVkFMSURBVElPTl9NT0RFLmFsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbG9jYWxQcm94eUZvcm1TdGF0ZSAmJiAobG9jYWxQcm94eUZvcm1TdGF0ZVtfa2V5XSA9IHRydWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmb3JtU3RhdGVbX2tleV07XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbmNvbnN0IHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IFJlYWN0LnVzZUxheW91dEVmZmVjdCA6IFJlYWN0LnVzZUVmZmVjdDtcblxuLyoqXG4gKiBUaGlzIGN1c3RvbSBob29rIGFsbG93cyB5b3UgdG8gc3Vic2NyaWJlIHRvIGVhY2ggZm9ybSBzdGF0ZSwgYW5kIGlzb2xhdGUgdGhlIHJlLXJlbmRlciBhdCB0aGUgY3VzdG9tIGhvb2sgbGV2ZWwuIEl0IGhhcyBpdHMgc2NvcGUgaW4gdGVybXMgb2YgZm9ybSBzdGF0ZSBzdWJzY3JpcHRpb24sIHNvIGl0IHdvdWxkIG5vdCBhZmZlY3Qgb3RoZXIgdXNlRm9ybVN0YXRlIGFuZCB1c2VGb3JtLiBVc2luZyB0aGlzIGhvb2sgY2FuIHJlZHVjZSB0aGUgcmUtcmVuZGVyIGltcGFjdCBvbiBsYXJnZSBhbmQgY29tcGxleCBmb3JtIGFwcGxpY2F0aW9uLlxuICpcbiAqIEByZW1hcmtzXG4gKiBbQVBJXShodHRwczovL3JlYWN0LWhvb2stZm9ybS5jb20vZG9jcy91c2Vmb3Jtc3RhdGUpIOKAoiBbRGVtb10oaHR0cHM6Ly9jb2Rlc2FuZGJveC5pby9zL3VzZWZvcm1zdGF0ZS03NXhseSlcbiAqXG4gKiBAcGFyYW0gcHJvcHMgLSBpbmNsdWRlIG9wdGlvbnMgb24gc3BlY2lmeSBmaWVsZHMgdG8gc3Vic2NyaWJlLiB7QGxpbmsgVXNlRm9ybVN0YXRlUmV0dXJufVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c3hcbiAqIGZ1bmN0aW9uIEFwcCgpIHtcbiAqICAgY29uc3QgeyByZWdpc3RlciwgaGFuZGxlU3VibWl0LCBjb250cm9sIH0gPSB1c2VGb3JtKHtcbiAqICAgICBkZWZhdWx0VmFsdWVzOiB7XG4gKiAgICAgZmlyc3ROYW1lOiBcImZpcnN0TmFtZVwiXG4gKiAgIH19KTtcbiAqICAgY29uc3QgeyBkaXJ0eUZpZWxkcyB9ID0gdXNlRm9ybVN0YXRlKHtcbiAqICAgICBjb250cm9sXG4gKiAgIH0pO1xuICogICBjb25zdCBvblN1Ym1pdCA9IChkYXRhKSA9PiBjb25zb2xlLmxvZyhkYXRhKTtcbiAqXG4gKiAgIHJldHVybiAoXG4gKiAgICAgPGZvcm0gb25TdWJtaXQ9e2hhbmRsZVN1Ym1pdChvblN1Ym1pdCl9PlxuICogICAgICAgPGlucHV0IHsuLi5yZWdpc3RlcihcImZpcnN0TmFtZVwiKX0gcGxhY2Vob2xkZXI9XCJGaXJzdCBOYW1lXCIgLz5cbiAqICAgICAgIHtkaXJ0eUZpZWxkcy5maXJzdE5hbWUgJiYgPHA+RmllbGQgaXMgZGlydHkuPC9wPn1cbiAqICAgICAgIDxpbnB1dCB0eXBlPVwic3VibWl0XCIgLz5cbiAqICAgICA8L2Zvcm0+XG4gKiAgICk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZnVuY3Rpb24gdXNlRm9ybVN0YXRlKHByb3BzKSB7XG4gICAgY29uc3QgbWV0aG9kcyA9IHVzZUZvcm1Db250ZXh0KCk7XG4gICAgY29uc3QgeyBjb250cm9sID0gbWV0aG9kcy5jb250cm9sLCBkaXNhYmxlZCwgbmFtZSwgZXhhY3QgfSA9IHByb3BzIHx8IHt9O1xuICAgIGNvbnN0IFtmb3JtU3RhdGUsIHVwZGF0ZUZvcm1TdGF0ZV0gPSBSZWFjdC51c2VTdGF0ZShjb250cm9sLl9mb3JtU3RhdGUpO1xuICAgIGNvbnN0IF9sb2NhbFByb3h5Rm9ybVN0YXRlID0gUmVhY3QudXNlUmVmKHtcbiAgICAgICAgaXNEaXJ0eTogZmFsc2UsXG4gICAgICAgIGlzTG9hZGluZzogZmFsc2UsXG4gICAgICAgIGRpcnR5RmllbGRzOiBmYWxzZSxcbiAgICAgICAgdG91Y2hlZEZpZWxkczogZmFsc2UsXG4gICAgICAgIHZhbGlkYXRpbmdGaWVsZHM6IGZhbHNlLFxuICAgICAgICBpc1ZhbGlkYXRpbmc6IGZhbHNlLFxuICAgICAgICBpc1ZhbGlkOiBmYWxzZSxcbiAgICAgICAgZXJyb3JzOiBmYWxzZSxcbiAgICB9KTtcbiAgICB1c2VJc29tb3JwaGljTGF5b3V0RWZmZWN0KCgpID0+IGNvbnRyb2wuX3N1YnNjcmliZSh7XG4gICAgICAgIG5hbWUsXG4gICAgICAgIGZvcm1TdGF0ZTogX2xvY2FsUHJveHlGb3JtU3RhdGUuY3VycmVudCxcbiAgICAgICAgZXhhY3QsXG4gICAgICAgIGNhbGxiYWNrOiAoZm9ybVN0YXRlKSA9PiB7XG4gICAgICAgICAgICAhZGlzYWJsZWQgJiZcbiAgICAgICAgICAgICAgICB1cGRhdGVGb3JtU3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICAuLi5jb250cm9sLl9mb3JtU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgIC4uLmZvcm1TdGF0ZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICB9KSwgW25hbWUsIGRpc2FibGVkLCBleGFjdF0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIF9sb2NhbFByb3h5Rm9ybVN0YXRlLmN1cnJlbnQuaXNWYWxpZCAmJiBjb250cm9sLl9zZXRWYWxpZCh0cnVlKTtcbiAgICB9LCBbY29udHJvbF0pO1xuICAgIHJldHVybiBSZWFjdC51c2VNZW1vKCgpID0+IGdldFByb3h5Rm9ybVN0YXRlKGZvcm1TdGF0ZSwgY29udHJvbCwgX2xvY2FsUHJveHlGb3JtU3RhdGUuY3VycmVudCwgZmFsc2UpLCBbZm9ybVN0YXRlLCBjb250cm9sXSk7XG59XG5cbnZhciBpc1N0cmluZyA9ICh2YWx1ZSkgPT4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcblxudmFyIGdlbmVyYXRlV2F0Y2hPdXRwdXQgPSAobmFtZXMsIF9uYW1lcywgZm9ybVZhbHVlcywgaXNHbG9iYWwsIGRlZmF1bHRWYWx1ZSkgPT4ge1xuICAgIGlmIChpc1N0cmluZyhuYW1lcykpIHtcbiAgICAgICAgaXNHbG9iYWwgJiYgX25hbWVzLndhdGNoLmFkZChuYW1lcyk7XG4gICAgICAgIHJldHVybiBnZXQoZm9ybVZhbHVlcywgbmFtZXMsIGRlZmF1bHRWYWx1ZSk7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KG5hbWVzKSkge1xuICAgICAgICByZXR1cm4gbmFtZXMubWFwKChmaWVsZE5hbWUpID0+IChpc0dsb2JhbCAmJiBfbmFtZXMud2F0Y2guYWRkKGZpZWxkTmFtZSksXG4gICAgICAgICAgICBnZXQoZm9ybVZhbHVlcywgZmllbGROYW1lKSkpO1xuICAgIH1cbiAgICBpc0dsb2JhbCAmJiAoX25hbWVzLndhdGNoQWxsID0gdHJ1ZSk7XG4gICAgcmV0dXJuIGZvcm1WYWx1ZXM7XG59O1xuXG52YXIgaXNQcmltaXRpdmUgPSAodmFsdWUpID0+IGlzTnVsbE9yVW5kZWZpbmVkKHZhbHVlKSB8fCAhaXNPYmplY3RUeXBlKHZhbHVlKTtcblxuZnVuY3Rpb24gZGVlcEVxdWFsKG9iamVjdDEsIG9iamVjdDIsIF9pbnRlcm5hbF92aXNpdGVkID0gbmV3IFdlYWtTZXQoKSkge1xuICAgIGlmIChpc1ByaW1pdGl2ZShvYmplY3QxKSB8fCBpc1ByaW1pdGl2ZShvYmplY3QyKSkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmlzKG9iamVjdDEsIG9iamVjdDIpO1xuICAgIH1cbiAgICBpZiAoaXNEYXRlT2JqZWN0KG9iamVjdDEpICYmIGlzRGF0ZU9iamVjdChvYmplY3QyKSkge1xuICAgICAgICByZXR1cm4gb2JqZWN0MS5nZXRUaW1lKCkgPT09IG9iamVjdDIuZ2V0VGltZSgpO1xuICAgIH1cbiAgICBjb25zdCBrZXlzMSA9IE9iamVjdC5rZXlzKG9iamVjdDEpO1xuICAgIGNvbnN0IGtleXMyID0gT2JqZWN0LmtleXMob2JqZWN0Mik7XG4gICAgaWYgKGtleXMxLmxlbmd0aCAhPT0ga2V5czIubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKF9pbnRlcm5hbF92aXNpdGVkLmhhcyhvYmplY3QxKSB8fCBfaW50ZXJuYWxfdmlzaXRlZC5oYXMob2JqZWN0MikpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIF9pbnRlcm5hbF92aXNpdGVkLmFkZChvYmplY3QxKTtcbiAgICBfaW50ZXJuYWxfdmlzaXRlZC5hZGQob2JqZWN0Mik7XG4gICAgZm9yIChjb25zdCBrZXkgb2Yga2V5czEpIHtcbiAgICAgICAgY29uc3QgdmFsMSA9IG9iamVjdDFba2V5XTtcbiAgICAgICAgaWYgKCFrZXlzMi5pbmNsdWRlcyhrZXkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGtleSAhPT0gJ3JlZicpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbDIgPSBvYmplY3QyW2tleV07XG4gICAgICAgICAgICBpZiAoKGlzRGF0ZU9iamVjdCh2YWwxKSAmJiBpc0RhdGVPYmplY3QodmFsMikpIHx8XG4gICAgICAgICAgICAgICAgKGlzT2JqZWN0KHZhbDEpICYmIGlzT2JqZWN0KHZhbDIpKSB8fFxuICAgICAgICAgICAgICAgIChBcnJheS5pc0FycmF5KHZhbDEpICYmIEFycmF5LmlzQXJyYXkodmFsMikpXG4gICAgICAgICAgICAgICAgPyAhZGVlcEVxdWFsKHZhbDEsIHZhbDIsIF9pbnRlcm5hbF92aXNpdGVkKVxuICAgICAgICAgICAgICAgIDogIU9iamVjdC5pcyh2YWwxLCB2YWwyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBDdXN0b20gaG9vayB0byBzdWJzY3JpYmUgdG8gZmllbGQgY2hhbmdlIGFuZCBpc29sYXRlIHJlLXJlbmRlcmluZyBhdCB0aGUgY29tcG9uZW50IGxldmVsLlxuICpcbiAqIEByZW1hcmtzXG4gKlxuICogW0FQSV0oaHR0cHM6Ly9yZWFjdC1ob29rLWZvcm0uY29tL2RvY3MvdXNld2F0Y2gpIOKAoiBbRGVtb10oaHR0cHM6Ly9jb2Rlc2FuZGJveC5pby9zL3JlYWN0LWhvb2stZm9ybS12Ny10cy11c2V3YXRjaC1oOWk1ZSlcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHN4XG4gKiBjb25zdCB7IGNvbnRyb2wgfSA9IHVzZUZvcm0oKTtcbiAqIGNvbnN0IHZhbHVlcyA9IHVzZVdhdGNoKHtcbiAqICAgbmFtZTogXCJmaWVsZE5hbWVcIlxuICogICBjb250cm9sLFxuICogfSlcbiAqIGBgYFxuICovXG5mdW5jdGlvbiB1c2VXYXRjaChwcm9wcykge1xuICAgIGNvbnN0IG1ldGhvZHMgPSB1c2VGb3JtQ29udGV4dCgpO1xuICAgIGNvbnN0IHsgY29udHJvbCA9IG1ldGhvZHMuY29udHJvbCwgbmFtZSwgZGVmYXVsdFZhbHVlLCBkaXNhYmxlZCwgZXhhY3QsIGNvbXB1dGUsIH0gPSBwcm9wcyB8fCB7fTtcbiAgICBjb25zdCBfZGVmYXVsdFZhbHVlID0gUmVhY3QudXNlUmVmKGRlZmF1bHRWYWx1ZSk7XG4gICAgY29uc3QgX2NvbXB1dGUgPSBSZWFjdC51c2VSZWYoY29tcHV0ZSk7XG4gICAgY29uc3QgX2NvbXB1dGVGb3JtVmFsdWVzID0gUmVhY3QudXNlUmVmKHVuZGVmaW5lZCk7XG4gICAgY29uc3QgX3ByZXZDb250cm9sID0gUmVhY3QudXNlUmVmKGNvbnRyb2wpO1xuICAgIGNvbnN0IF9wcmV2TmFtZSA9IFJlYWN0LnVzZVJlZihuYW1lKTtcbiAgICBfY29tcHV0ZS5jdXJyZW50ID0gY29tcHV0ZTtcbiAgICBjb25zdCBbdmFsdWUsIHVwZGF0ZVZhbHVlXSA9IFJlYWN0LnVzZVN0YXRlKCgpID0+IHtcbiAgICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gY29udHJvbC5fZ2V0V2F0Y2gobmFtZSwgX2RlZmF1bHRWYWx1ZS5jdXJyZW50KTtcbiAgICAgICAgcmV0dXJuIF9jb21wdXRlLmN1cnJlbnQgPyBfY29tcHV0ZS5jdXJyZW50KGRlZmF1bHRWYWx1ZSkgOiBkZWZhdWx0VmFsdWU7XG4gICAgfSk7XG4gICAgY29uc3QgZ2V0Q3VycmVudE91dHB1dCA9IFJlYWN0LnVzZUNhbGxiYWNrKCh2YWx1ZXMpID0+IHtcbiAgICAgICAgY29uc3QgZm9ybVZhbHVlcyA9IGdlbmVyYXRlV2F0Y2hPdXRwdXQobmFtZSwgY29udHJvbC5fbmFtZXMsIHZhbHVlcyB8fCBjb250cm9sLl9mb3JtVmFsdWVzLCBmYWxzZSwgX2RlZmF1bHRWYWx1ZS5jdXJyZW50KTtcbiAgICAgICAgcmV0dXJuIF9jb21wdXRlLmN1cnJlbnQgPyBfY29tcHV0ZS5jdXJyZW50KGZvcm1WYWx1ZXMpIDogZm9ybVZhbHVlcztcbiAgICB9LCBbY29udHJvbC5fZm9ybVZhbHVlcywgY29udHJvbC5fbmFtZXMsIG5hbWVdKTtcbiAgICBjb25zdCByZWZyZXNoVmFsdWUgPSBSZWFjdC51c2VDYWxsYmFjaygodmFsdWVzKSA9PiB7XG4gICAgICAgIGlmICghZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1WYWx1ZXMgPSBnZW5lcmF0ZVdhdGNoT3V0cHV0KG5hbWUsIGNvbnRyb2wuX25hbWVzLCB2YWx1ZXMgfHwgY29udHJvbC5fZm9ybVZhbHVlcywgZmFsc2UsIF9kZWZhdWx0VmFsdWUuY3VycmVudCk7XG4gICAgICAgICAgICBpZiAoX2NvbXB1dGUuY3VycmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbXB1dGVkRm9ybVZhbHVlcyA9IF9jb21wdXRlLmN1cnJlbnQoZm9ybVZhbHVlcyk7XG4gICAgICAgICAgICAgICAgaWYgKCFkZWVwRXF1YWwoY29tcHV0ZWRGb3JtVmFsdWVzLCBfY29tcHV0ZUZvcm1WYWx1ZXMuY3VycmVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlVmFsdWUoY29tcHV0ZWRGb3JtVmFsdWVzKTtcbiAgICAgICAgICAgICAgICAgICAgX2NvbXB1dGVGb3JtVmFsdWVzLmN1cnJlbnQgPSBjb21wdXRlZEZvcm1WYWx1ZXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlVmFsdWUoZm9ybVZhbHVlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCBbY29udHJvbC5fZm9ybVZhbHVlcywgY29udHJvbC5fbmFtZXMsIGRpc2FibGVkLCBuYW1lXSk7XG4gICAgdXNlSXNvbW9ycGhpY0xheW91dEVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChfcHJldkNvbnRyb2wuY3VycmVudCAhPT0gY29udHJvbCB8fFxuICAgICAgICAgICAgIWRlZXBFcXVhbChfcHJldk5hbWUuY3VycmVudCwgbmFtZSkpIHtcbiAgICAgICAgICAgIF9wcmV2Q29udHJvbC5jdXJyZW50ID0gY29udHJvbDtcbiAgICAgICAgICAgIF9wcmV2TmFtZS5jdXJyZW50ID0gbmFtZTtcbiAgICAgICAgICAgIHJlZnJlc2hWYWx1ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb250cm9sLl9zdWJzY3JpYmUoe1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIGZvcm1TdGF0ZToge1xuICAgICAgICAgICAgICAgIHZhbHVlczogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBleGFjdCxcbiAgICAgICAgICAgIGNhbGxiYWNrOiAoZm9ybVN0YXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVmcmVzaFZhbHVlKGZvcm1TdGF0ZS52YWx1ZXMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgfSwgW2NvbnRyb2wsIGV4YWN0LCBuYW1lLCByZWZyZXNoVmFsdWVdKTtcbiAgICBSZWFjdC51c2VFZmZlY3QoKCkgPT4gY29udHJvbC5fcmVtb3ZlVW5tb3VudGVkKCkpO1xuICAgIC8vIElmIG5hbWUgb3IgY29udHJvbCBjaGFuZ2VkIGZvciB0aGlzIHJlbmRlciwgc3luY2hyb25vdXNseSByZWZsZWN0IHRoZVxuICAgIC8vIGxhdGVzdCB2YWx1ZSBzbyBjYWxsZXJzIChsaWtlIHVzZUNvbnRyb2xsZXIpIHNlZSB0aGUgY29ycmVjdCB2YWx1ZVxuICAgIC8vIGltbWVkaWF0ZWx5IG9uIHRoZSBzYW1lIHJlbmRlci5cbiAgICAvLyBPcHRpbWl6ZTogQ2hlY2sgY29udHJvbCByZWZlcmVuY2UgZmlyc3QgYmVmb3JlIGV4cGVuc2l2ZSBkZWVwRXF1YWxcbiAgICBjb25zdCBjb250cm9sQ2hhbmdlZCA9IF9wcmV2Q29udHJvbC5jdXJyZW50ICE9PSBjb250cm9sO1xuICAgIGNvbnN0IHByZXZOYW1lID0gX3ByZXZOYW1lLmN1cnJlbnQ7XG4gICAgLy8gQ2FjaGUgdGhlIGNvbXB1dGVkIG91dHB1dCB0byBhdm9pZCBkdXBsaWNhdGUgY2FsbHMgd2l0aGluIHRoZSBzYW1lIHJlbmRlclxuICAgIC8vIFdlIGluY2x1ZGUgc2hvdWxkUmV0dXJuSW1tZWRpYXRlIGluIGRlcHMgdG8gZW5zdXJlIHByb3BlciByZWNvbXB1dGF0aW9uXG4gICAgY29uc3QgY29tcHV0ZWRPdXRwdXQgPSBSZWFjdC51c2VNZW1vKCgpID0+IHtcbiAgICAgICAgaWYgKGRpc2FibGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuYW1lQ2hhbmdlZCA9ICFjb250cm9sQ2hhbmdlZCAmJiAhZGVlcEVxdWFsKHByZXZOYW1lLCBuYW1lKTtcbiAgICAgICAgY29uc3Qgc2hvdWxkUmV0dXJuSW1tZWRpYXRlID0gY29udHJvbENoYW5nZWQgfHwgbmFtZUNoYW5nZWQ7XG4gICAgICAgIHJldHVybiBzaG91bGRSZXR1cm5JbW1lZGlhdGUgPyBnZXRDdXJyZW50T3V0cHV0KCkgOiBudWxsO1xuICAgIH0sIFtkaXNhYmxlZCwgY29udHJvbENoYW5nZWQsIG5hbWUsIHByZXZOYW1lLCBnZXRDdXJyZW50T3V0cHV0XSk7XG4gICAgcmV0dXJuIGNvbXB1dGVkT3V0cHV0ICE9PSBudWxsID8gY29tcHV0ZWRPdXRwdXQgOiB2YWx1ZTtcbn1cblxuLyoqXG4gKiBDdXN0b20gaG9vayB0byB3b3JrIHdpdGggY29udHJvbGxlZCBjb21wb25lbnQsIHRoaXMgZnVuY3Rpb24gcHJvdmlkZSB5b3Ugd2l0aCBib3RoIGZvcm0gYW5kIGZpZWxkIGxldmVsIHN0YXRlLiBSZS1yZW5kZXIgaXMgaXNvbGF0ZWQgYXQgdGhlIGhvb2sgbGV2ZWwuXG4gKlxuICogQHJlbWFya3NcbiAqIFtBUEldKGh0dHBzOi8vcmVhY3QtaG9vay1mb3JtLmNvbS9kb2NzL3VzZWNvbnRyb2xsZXIpIOKAoiBbRGVtb10oaHR0cHM6Ly9jb2Rlc2FuZGJveC5pby9zL3VzZWNvbnRyb2xsZXItMG84cHgpXG4gKlxuICogQHBhcmFtIHByb3BzIC0gdGhlIHBhdGggbmFtZSB0byB0aGUgZm9ybSBmaWVsZCB2YWx1ZSwgYW5kIHZhbGlkYXRpb24gcnVsZXMuXG4gKlxuICogQHJldHVybnMgZmllbGQgcHJvcGVydGllcywgZmllbGQgYW5kIGZvcm0gc3RhdGUuIHtAbGluayBVc2VDb250cm9sbGVyUmV0dXJufVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c3hcbiAqIGZ1bmN0aW9uIElucHV0KHByb3BzKSB7XG4gKiAgIGNvbnN0IHsgZmllbGQsIGZpZWxkU3RhdGUsIGZvcm1TdGF0ZSB9ID0gdXNlQ29udHJvbGxlcihwcm9wcyk7XG4gKiAgIHJldHVybiAoXG4gKiAgICAgPGRpdj5cbiAqICAgICAgIDxpbnB1dCB7Li4uZmllbGR9IHBsYWNlaG9sZGVyPXtwcm9wcy5uYW1lfSAvPlxuICogICAgICAgPHA+e2ZpZWxkU3RhdGUuaXNUb3VjaGVkICYmIFwiVG91Y2hlZFwifTwvcD5cbiAqICAgICAgIDxwPntmb3JtU3RhdGUuaXNTdWJtaXR0ZWQgPyBcInN1Ym1pdHRlZFwiIDogXCJcIn08L3A+XG4gKiAgICAgPC9kaXY+XG4gKiAgICk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZnVuY3Rpb24gdXNlQ29udHJvbGxlcihwcm9wcykge1xuICAgIGNvbnN0IG1ldGhvZHMgPSB1c2VGb3JtQ29udGV4dCgpO1xuICAgIGNvbnN0IHsgbmFtZSwgZGlzYWJsZWQsIGNvbnRyb2wgPSBtZXRob2RzLmNvbnRyb2wsIHNob3VsZFVucmVnaXN0ZXIsIGRlZmF1bHRWYWx1ZSwgfSA9IHByb3BzO1xuICAgIGNvbnN0IGlzQXJyYXlGaWVsZCA9IGlzTmFtZUluRmllbGRBcnJheShjb250cm9sLl9uYW1lcy5hcnJheSwgbmFtZSk7XG4gICAgY29uc3QgZGVmYXVsdFZhbHVlTWVtbyA9IFJlYWN0LnVzZU1lbW8oKCkgPT4gZ2V0KGNvbnRyb2wuX2Zvcm1WYWx1ZXMsIG5hbWUsIGdldChjb250cm9sLl9kZWZhdWx0VmFsdWVzLCBuYW1lLCBkZWZhdWx0VmFsdWUpKSwgW2NvbnRyb2wsIG5hbWUsIGRlZmF1bHRWYWx1ZV0pO1xuICAgIGNvbnN0IHZhbHVlID0gdXNlV2F0Y2goe1xuICAgICAgICBjb250cm9sLFxuICAgICAgICBuYW1lLFxuICAgICAgICBkZWZhdWx0VmFsdWU6IGRlZmF1bHRWYWx1ZU1lbW8sXG4gICAgICAgIGV4YWN0OiB0cnVlLFxuICAgIH0pO1xuICAgIGNvbnN0IGZvcm1TdGF0ZSA9IHVzZUZvcm1TdGF0ZSh7XG4gICAgICAgIGNvbnRyb2wsXG4gICAgICAgIG5hbWUsXG4gICAgICAgIGV4YWN0OiB0cnVlLFxuICAgIH0pO1xuICAgIGNvbnN0IF9wcm9wcyA9IFJlYWN0LnVzZVJlZihwcm9wcyk7XG4gICAgY29uc3QgX3ByZXZpb3VzTmFtZVJlZiA9IFJlYWN0LnVzZVJlZih1bmRlZmluZWQpO1xuICAgIGNvbnN0IF9yZWdpc3RlclByb3BzID0gUmVhY3QudXNlUmVmKGNvbnRyb2wucmVnaXN0ZXIobmFtZSwge1xuICAgICAgICAuLi5wcm9wcy5ydWxlcyxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIC4uLihpc0Jvb2xlYW4ocHJvcHMuZGlzYWJsZWQpID8geyBkaXNhYmxlZDogcHJvcHMuZGlzYWJsZWQgfSA6IHt9KSxcbiAgICB9KSk7XG4gICAgX3Byb3BzLmN1cnJlbnQgPSBwcm9wcztcbiAgICBjb25zdCBmaWVsZFN0YXRlID0gUmVhY3QudXNlTWVtbygoKSA9PiBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh7fSwge1xuICAgICAgICBpbnZhbGlkOiB7XG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZ2V0OiAoKSA9PiAhIWdldChmb3JtU3RhdGUuZXJyb3JzLCBuYW1lKSxcbiAgICAgICAgfSxcbiAgICAgICAgaXNEaXJ0eToge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gISFnZXQoZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBuYW1lKSxcbiAgICAgICAgfSxcbiAgICAgICAgaXNUb3VjaGVkOiB7XG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZ2V0OiAoKSA9PiAhIWdldChmb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgbmFtZSksXG4gICAgICAgIH0sXG4gICAgICAgIGlzVmFsaWRhdGluZzoge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gISFnZXQoZm9ybVN0YXRlLnZhbGlkYXRpbmdGaWVsZHMsIG5hbWUpLFxuICAgICAgICB9LFxuICAgICAgICBlcnJvcjoge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gZ2V0KGZvcm1TdGF0ZS5lcnJvcnMsIG5hbWUpLFxuICAgICAgICB9LFxuICAgIH0pLCBbZm9ybVN0YXRlLCBuYW1lXSk7XG4gICAgY29uc3Qgb25DaGFuZ2UgPSBSZWFjdC51c2VDYWxsYmFjaygoZXZlbnQpID0+IF9yZWdpc3RlclByb3BzLmN1cnJlbnQub25DaGFuZ2Uoe1xuICAgICAgICB0YXJnZXQ6IHtcbiAgICAgICAgICAgIHZhbHVlOiBnZXRFdmVudFZhbHVlKGV2ZW50KSxcbiAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIHR5cGU6IEVWRU5UUy5DSEFOR0UsXG4gICAgfSksIFtuYW1lXSk7XG4gICAgY29uc3Qgb25CbHVyID0gUmVhY3QudXNlQ2FsbGJhY2soKCkgPT4gX3JlZ2lzdGVyUHJvcHMuY3VycmVudC5vbkJsdXIoe1xuICAgICAgICB0YXJnZXQ6IHtcbiAgICAgICAgICAgIHZhbHVlOiBnZXQoY29udHJvbC5fZm9ybVZhbHVlcywgbmFtZSksXG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICB9LFxuICAgICAgICB0eXBlOiBFVkVOVFMuQkxVUixcbiAgICB9KSwgW25hbWUsIGNvbnRyb2wuX2Zvcm1WYWx1ZXNdKTtcbiAgICBjb25zdCByZWYgPSBSZWFjdC51c2VDYWxsYmFjaygoZWxtKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KGNvbnRyb2wuX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgIGlmIChmaWVsZCAmJiBlbG0pIHtcbiAgICAgICAgICAgIGZpZWxkLl9mLnJlZiA9IHtcbiAgICAgICAgICAgICAgICBmb2N1czogKCkgPT4gZWxtLmZvY3VzICYmIGVsbS5mb2N1cygpLFxuICAgICAgICAgICAgICAgIHNlbGVjdDogKCkgPT4gZWxtLnNlbGVjdCAmJiBlbG0uc2VsZWN0KCksXG4gICAgICAgICAgICAgICAgc2V0Q3VzdG9tVmFsaWRpdHk6IChtZXNzYWdlKSA9PiBlbG0uc2V0Q3VzdG9tVmFsaWRpdHkobWVzc2FnZSksXG4gICAgICAgICAgICAgICAgcmVwb3J0VmFsaWRpdHk6ICgpID0+IGVsbS5yZXBvcnRWYWxpZGl0eSgpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH0sIFtjb250cm9sLl9maWVsZHMsIG5hbWVdKTtcbiAgICBjb25zdCBmaWVsZCA9IFJlYWN0LnVzZU1lbW8oKCkgPT4gKHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIC4uLihpc0Jvb2xlYW4oZGlzYWJsZWQpIHx8IGZvcm1TdGF0ZS5kaXNhYmxlZFxuICAgICAgICAgICAgPyB7IGRpc2FibGVkOiBmb3JtU3RhdGUuZGlzYWJsZWQgfHwgZGlzYWJsZWQgfVxuICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIG9uQ2hhbmdlLFxuICAgICAgICBvbkJsdXIsXG4gICAgICAgIHJlZixcbiAgICB9KSwgW25hbWUsIGRpc2FibGVkLCBmb3JtU3RhdGUuZGlzYWJsZWQsIG9uQ2hhbmdlLCBvbkJsdXIsIHJlZiwgdmFsdWVdKTtcbiAgICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBjb25zdCBfc2hvdWxkVW5yZWdpc3RlckZpZWxkID0gY29udHJvbC5fb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyIHx8IHNob3VsZFVucmVnaXN0ZXI7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzTmFtZSA9IF9wcmV2aW91c05hbWVSZWYuY3VycmVudDtcbiAgICAgICAgaWYgKHByZXZpb3VzTmFtZSAmJiBwcmV2aW91c05hbWUgIT09IG5hbWUgJiYgIWlzQXJyYXlGaWVsZCkge1xuICAgICAgICAgICAgY29udHJvbC51bnJlZ2lzdGVyKHByZXZpb3VzTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29udHJvbC5yZWdpc3RlcihuYW1lLCB7XG4gICAgICAgICAgICAuLi5fcHJvcHMuY3VycmVudC5ydWxlcyxcbiAgICAgICAgICAgIC4uLihpc0Jvb2xlYW4oX3Byb3BzLmN1cnJlbnQuZGlzYWJsZWQpXG4gICAgICAgICAgICAgICAgPyB7IGRpc2FibGVkOiBfcHJvcHMuY3VycmVudC5kaXNhYmxlZCB9XG4gICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB1cGRhdGVNb3VudGVkID0gKG5hbWUsIHZhbHVlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IGdldChjb250cm9sLl9maWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgaWYgKGZpZWxkICYmIGZpZWxkLl9mKSB7XG4gICAgICAgICAgICAgICAgZmllbGQuX2YubW91bnQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdXBkYXRlTW91bnRlZChuYW1lLCB0cnVlKTtcbiAgICAgICAgaWYgKF9zaG91bGRVbnJlZ2lzdGVyRmllbGQpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gY2xvbmVPYmplY3QoZ2V0KGNvbnRyb2wuX29wdGlvbnMuZGVmYXVsdFZhbHVlcywgbmFtZSwgX3Byb3BzLmN1cnJlbnQuZGVmYXVsdFZhbHVlKSk7XG4gICAgICAgICAgICBzZXQoY29udHJvbC5fZGVmYXVsdFZhbHVlcywgbmFtZSwgdmFsdWUpO1xuICAgICAgICAgICAgaWYgKGlzVW5kZWZpbmVkKGdldChjb250cm9sLl9mb3JtVmFsdWVzLCBuYW1lKSkpIHtcbiAgICAgICAgICAgICAgICBzZXQoY29udHJvbC5fZm9ybVZhbHVlcywgbmFtZSwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgICFpc0FycmF5RmllbGQgJiYgY29udHJvbC5yZWdpc3RlcihuYW1lKTtcbiAgICAgICAgX3ByZXZpb3VzTmFtZVJlZi5jdXJyZW50ID0gbmFtZTtcbiAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgIChpc0FycmF5RmllbGRcbiAgICAgICAgICAgICAgICA/IF9zaG91bGRVbnJlZ2lzdGVyRmllbGQgJiYgIWNvbnRyb2wuX3N0YXRlLmFjdGlvblxuICAgICAgICAgICAgICAgIDogX3Nob3VsZFVucmVnaXN0ZXJGaWVsZClcbiAgICAgICAgICAgICAgICA/IGNvbnRyb2wudW5yZWdpc3RlcihuYW1lKVxuICAgICAgICAgICAgICAgIDogdXBkYXRlTW91bnRlZChuYW1lLCBmYWxzZSk7XG4gICAgICAgIH07XG4gICAgfSwgW25hbWUsIGNvbnRyb2wsIGlzQXJyYXlGaWVsZCwgc2hvdWxkVW5yZWdpc3Rlcl0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGNvbnRyb2wuX3NldERpc2FibGVkRmllbGQoe1xuICAgICAgICAgICAgZGlzYWJsZWQsXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICB9KTtcbiAgICB9LCBbZGlzYWJsZWQsIG5hbWUsIGNvbnRyb2xdKTtcbiAgICByZXR1cm4gUmVhY3QudXNlTWVtbygoKSA9PiAoe1xuICAgICAgICBmaWVsZCxcbiAgICAgICAgZm9ybVN0YXRlLFxuICAgICAgICBmaWVsZFN0YXRlLFxuICAgIH0pLCBbZmllbGQsIGZvcm1TdGF0ZSwgZmllbGRTdGF0ZV0pO1xufVxuXG4vKipcbiAqIENvbXBvbmVudCBiYXNlZCBvbiBgdXNlQ29udHJvbGxlcmAgaG9vayB0byB3b3JrIHdpdGggY29udHJvbGxlZCBjb21wb25lbnQuXG4gKlxuICogQHJlbWFya3NcbiAqIFtBUEldKGh0dHBzOi8vcmVhY3QtaG9vay1mb3JtLmNvbS9kb2NzL3VzZWNvbnRyb2xsZXIvY29udHJvbGxlcikg4oCiIFtEZW1vXShodHRwczovL2NvZGVzYW5kYm94LmlvL3MvcmVhY3QtaG9vay1mb3JtLXY2LWNvbnRyb2xsZXItdHMtand5encpIOKAoiBbVmlkZW9dKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9TjJVTmtfVUNWeUEpXG4gKlxuICogQHBhcmFtIHByb3BzIC0gdGhlIHBhdGggbmFtZSB0byB0aGUgZm9ybSBmaWVsZCB2YWx1ZSwgYW5kIHZhbGlkYXRpb24gcnVsZXMuXG4gKlxuICogQHJldHVybnMgcHJvdmlkZSBmaWVsZCBoYW5kbGVyIGZ1bmN0aW9ucywgZmllbGQgYW5kIGZvcm0gc3RhdGUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCB7IGNvbnRyb2wgfSA9IHVzZUZvcm08Rm9ybVZhbHVlcz4oe1xuICogICAgIGRlZmF1bHRWYWx1ZXM6IHtcbiAqICAgICAgIHRlc3Q6IFwiXCJcbiAqICAgICB9XG4gKiAgIH0pO1xuICpcbiAqICAgcmV0dXJuIChcbiAqICAgICA8Zm9ybT5cbiAqICAgICAgIDxDb250cm9sbGVyXG4gKiAgICAgICAgIGNvbnRyb2w9e2NvbnRyb2x9XG4gKiAgICAgICAgIG5hbWU9XCJ0ZXN0XCJcbiAqICAgICAgICAgcmVuZGVyPXsoeyBmaWVsZDogeyBvbkNoYW5nZSwgb25CbHVyLCB2YWx1ZSwgcmVmIH0sIGZvcm1TdGF0ZSwgZmllbGRTdGF0ZSB9KSA9PiAoXG4gKiAgICAgICAgICAgPD5cbiAqICAgICAgICAgICAgIDxpbnB1dFxuICogICAgICAgICAgICAgICBvbkNoYW5nZT17b25DaGFuZ2V9IC8vIHNlbmQgdmFsdWUgdG8gaG9vayBmb3JtXG4gKiAgICAgICAgICAgICAgIG9uQmx1cj17b25CbHVyfSAvLyBub3RpZnkgd2hlbiBpbnB1dCBpcyB0b3VjaGVkXG4gKiAgICAgICAgICAgICAgIHZhbHVlPXt2YWx1ZX0gLy8gcmV0dXJuIHVwZGF0ZWQgdmFsdWVcbiAqICAgICAgICAgICAgICAgcmVmPXtyZWZ9IC8vIHNldCByZWYgZm9yIGZvY3VzIG1hbmFnZW1lbnRcbiAqICAgICAgICAgICAgIC8+XG4gKiAgICAgICAgICAgICA8cD57Zm9ybVN0YXRlLmlzU3VibWl0dGVkID8gXCJzdWJtaXR0ZWRcIiA6IFwiXCJ9PC9wPlxuICogICAgICAgICAgICAgPHA+e2ZpZWxkU3RhdGUuaXNUb3VjaGVkID8gXCJ0b3VjaGVkXCIgOiBcIlwifTwvcD5cbiAqICAgICAgICAgICA8Lz5cbiAqICAgICAgICAgKX1cbiAqICAgICAgIC8+XG4gKiAgICAgPC9mb3JtPlxuICogICApO1xuICogfVxuICogYGBgXG4gKi9cbmNvbnN0IENvbnRyb2xsZXIgPSAocHJvcHMpID0+IHByb3BzLnJlbmRlcih1c2VDb250cm9sbGVyKHByb3BzKSk7XG5cbmNvbnN0IGZsYXR0ZW4gPSAob2JqKSA9PiB7XG4gICAgY29uc3Qgb3V0cHV0ID0ge307XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMob2JqKSkge1xuICAgICAgICBpZiAoaXNPYmplY3RUeXBlKG9ialtrZXldKSAmJiBvYmpba2V5XSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc3QgbmVzdGVkID0gZmxhdHRlbihvYmpba2V5XSk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5lc3RlZEtleSBvZiBPYmplY3Qua2V5cyhuZXN0ZWQpKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0W2Ake2tleX0uJHtuZXN0ZWRLZXl9YF0gPSBuZXN0ZWRbbmVzdGVkS2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG91dHB1dFtrZXldID0gb2JqW2tleV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG91dHB1dDtcbn07XG5cbmNvbnN0IFBPU1RfUkVRVUVTVCA9ICdwb3N0Jztcbi8qKlxuICogRm9ybSBjb21wb25lbnQgdG8gbWFuYWdlIHN1Ym1pc3Npb24uXG4gKlxuICogQHBhcmFtIHByb3BzIC0gdG8gc2V0dXAgc3VibWlzc2lvbiBkZXRhaWwuIHtAbGluayBGb3JtUHJvcHN9XG4gKlxuICogQHJldHVybnMgZm9ybSBjb21wb25lbnQgb3IgaGVhZGxlc3MgcmVuZGVyIHByb3AuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCB7IGNvbnRyb2wsIGZvcm1TdGF0ZTogeyBlcnJvcnMgfSB9ID0gdXNlRm9ybSgpO1xuICpcbiAqICAgcmV0dXJuIChcbiAqICAgICA8Rm9ybSBhY3Rpb249XCIvYXBpXCIgY29udHJvbD17Y29udHJvbH0+XG4gKiAgICAgICA8aW5wdXQgey4uLnJlZ2lzdGVyKFwibmFtZVwiKX0gLz5cbiAqICAgICAgIDxwPntlcnJvcnM/LnJvb3Q/LnNlcnZlciAmJiAnU2VydmVyIGVycm9yJ308L3A+XG4gKiAgICAgICA8YnV0dG9uPlN1Ym1pdDwvYnV0dG9uPlxuICogICAgIDwvRm9ybT5cbiAqICAgKTtcbiAqIH1cbiAqIGBgYFxuICovXG5mdW5jdGlvbiBGb3JtKHByb3BzKSB7XG4gICAgY29uc3QgbWV0aG9kcyA9IHVzZUZvcm1Db250ZXh0KCk7XG4gICAgY29uc3QgW21vdW50ZWQsIHNldE1vdW50ZWRdID0gUmVhY3QudXNlU3RhdGUoZmFsc2UpO1xuICAgIGNvbnN0IHsgY29udHJvbCA9IG1ldGhvZHMuY29udHJvbCwgb25TdWJtaXQsIGNoaWxkcmVuLCBhY3Rpb24sIG1ldGhvZCA9IFBPU1RfUkVRVUVTVCwgaGVhZGVycywgZW5jVHlwZSwgb25FcnJvciwgcmVuZGVyLCBvblN1Y2Nlc3MsIHZhbGlkYXRlU3RhdHVzLCAuLi5yZXN0IH0gPSBwcm9wcztcbiAgICBjb25zdCBzdWJtaXQgPSBhc3luYyAoZXZlbnQpID0+IHtcbiAgICAgICAgbGV0IGhhc0Vycm9yID0gZmFsc2U7XG4gICAgICAgIGxldCB0eXBlID0gJyc7XG4gICAgICAgIGF3YWl0IGNvbnRyb2wuaGFuZGxlU3VibWl0KGFzeW5jIChkYXRhKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgbGV0IGZvcm1EYXRhSnNvbiA9ICcnO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBmb3JtRGF0YUpzb24gPSBKU09OLnN0cmluZ2lmeShkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChfYSkgeyB9XG4gICAgICAgICAgICBjb25zdCBmbGF0dGVuRm9ybVZhbHVlcyA9IGZsYXR0ZW4oY29udHJvbC5fZm9ybVZhbHVlcyk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBmbGF0dGVuRm9ybVZhbHVlcykge1xuICAgICAgICAgICAgICAgIGZvcm1EYXRhLmFwcGVuZChrZXksIGZsYXR0ZW5Gb3JtVmFsdWVzW2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9uU3VibWl0KSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgb25TdWJtaXQoe1xuICAgICAgICAgICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgICAgICAgICAgICBmb3JtRGF0YSxcbiAgICAgICAgICAgICAgICAgICAgZm9ybURhdGFKc29uLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFjdGlvbikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNob3VsZFN0cmluZ2lmeVN1Ym1pc3Npb25EYXRhID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVycyAmJiBoZWFkZXJzWydDb250ZW50LVR5cGUnXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuY1R5cGUsXG4gICAgICAgICAgICAgICAgICAgIF0uc29tZSgodmFsdWUpID0+IHZhbHVlICYmIHZhbHVlLmluY2x1ZGVzKCdqc29uJykpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKFN0cmluZyhhY3Rpb24pLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uaGVhZGVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4oZW5jVHlwZSAmJiBlbmNUeXBlICE9PSAnbXVsdGlwYXJ0L2Zvcm0tZGF0YSdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB7ICdDb250ZW50LVR5cGUnOiBlbmNUeXBlIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9keTogc2hvdWxkU3RyaW5naWZ5U3VibWlzc2lvbkRhdGEgPyBmb3JtRGF0YUpzb24gOiBmb3JtRGF0YSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKHZhbGlkYXRlU3RhdHVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyAhdmFsaWRhdGVTdGF0dXMocmVzcG9uc2Uuc3RhdHVzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2Uuc3RhdHVzIDwgMjAwIHx8IHJlc3BvbnNlLnN0YXR1cyA+PSAzMDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNFcnJvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkVycm9yICYmIG9uRXJyb3IoeyByZXNwb25zZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSBTdHJpbmcocmVzcG9uc2Uuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uU3VjY2VzcyAmJiBvblN1Y2Nlc3MoeyByZXNwb25zZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzRXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBvbkVycm9yICYmIG9uRXJyb3IoeyBlcnJvciB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pKGV2ZW50KTtcbiAgICAgICAgaWYgKGhhc0Vycm9yICYmIHByb3BzLmNvbnRyb2wpIHtcbiAgICAgICAgICAgIHByb3BzLmNvbnRyb2wuX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgIGlzU3VibWl0U3VjY2Vzc2Z1bDogZmFsc2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHByb3BzLmNvbnRyb2wuc2V0RXJyb3IoJ3Jvb3Quc2VydmVyJywge1xuICAgICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgc2V0TW91bnRlZCh0cnVlKTtcbiAgICB9LCBbXSk7XG4gICAgcmV0dXJuIHJlbmRlciA/IChSZWFjdC5jcmVhdGVFbGVtZW50KFJlYWN0LkZyYWdtZW50LCBudWxsLCByZW5kZXIoe1xuICAgICAgICBzdWJtaXQsXG4gICAgfSkpKSA6IChSZWFjdC5jcmVhdGVFbGVtZW50KFwiZm9ybVwiLCB7IG5vVmFsaWRhdGU6IG1vdW50ZWQsIGFjdGlvbjogYWN0aW9uLCBtZXRob2Q6IG1ldGhvZCwgZW5jVHlwZTogZW5jVHlwZSwgb25TdWJtaXQ6IHN1Ym1pdCwgLi4ucmVzdCB9LCBjaGlsZHJlbikpO1xufVxuXG52YXIgYXBwZW5kRXJyb3JzID0gKG5hbWUsIHZhbGlkYXRlQWxsRmllbGRDcml0ZXJpYSwgZXJyb3JzLCB0eXBlLCBtZXNzYWdlKSA9PiB2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWFcbiAgICA/IHtcbiAgICAgICAgLi4uZXJyb3JzW25hbWVdLFxuICAgICAgICB0eXBlczoge1xuICAgICAgICAgICAgLi4uKGVycm9yc1tuYW1lXSAmJiBlcnJvcnNbbmFtZV0udHlwZXMgPyBlcnJvcnNbbmFtZV0udHlwZXMgOiB7fSksXG4gICAgICAgICAgICBbdHlwZV06IG1lc3NhZ2UgfHwgdHJ1ZSxcbiAgICAgICAgfSxcbiAgICB9XG4gICAgOiB7fTtcblxudmFyIGNvbnZlcnRUb0FycmF5UGF5bG9hZCA9ICh2YWx1ZSkgPT4gKEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbdmFsdWVdKTtcblxudmFyIGNyZWF0ZVN1YmplY3QgPSAoKSA9PiB7XG4gICAgbGV0IF9vYnNlcnZlcnMgPSBbXTtcbiAgICBjb25zdCBuZXh0ID0gKHZhbHVlKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3Qgb2JzZXJ2ZXIgb2YgX29ic2VydmVycykge1xuICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCAmJiBvYnNlcnZlci5uZXh0KHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3Qgc3Vic2NyaWJlID0gKG9ic2VydmVyKSA9PiB7XG4gICAgICAgIF9vYnNlcnZlcnMucHVzaChvYnNlcnZlcik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB1bnN1YnNjcmliZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgIF9vYnNlcnZlcnMgPSBfb2JzZXJ2ZXJzLmZpbHRlcigobykgPT4gbyAhPT0gb2JzZXJ2ZXIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIGNvbnN0IHVuc3Vic2NyaWJlID0gKCkgPT4ge1xuICAgICAgICBfb2JzZXJ2ZXJzID0gW107XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgICBnZXQgb2JzZXJ2ZXJzKCkge1xuICAgICAgICAgICAgcmV0dXJuIF9vYnNlcnZlcnM7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHQsXG4gICAgICAgIHN1YnNjcmliZSxcbiAgICAgICAgdW5zdWJzY3JpYmUsXG4gICAgfTtcbn07XG5cbmZ1bmN0aW9uIGV4dHJhY3RGb3JtVmFsdWVzKGZpZWxkc1N0YXRlLCBmb3JtVmFsdWVzKSB7XG4gICAgY29uc3QgdmFsdWVzID0ge307XG4gICAgZm9yIChjb25zdCBrZXkgaW4gZmllbGRzU3RhdGUpIHtcbiAgICAgICAgaWYgKGZpZWxkc1N0YXRlLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkU3RhdGUgPSBmaWVsZHNTdGF0ZVtrZXldO1xuICAgICAgICAgICAgY29uc3QgZmllbGRWYWx1ZSA9IGZvcm1WYWx1ZXNba2V5XTtcbiAgICAgICAgICAgIGlmIChmaWVsZFN0YXRlICYmIGlzT2JqZWN0KGZpZWxkU3RhdGUpICYmIGZpZWxkVmFsdWUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXN0ZWRGaWVsZHNTdGF0ZSA9IGV4dHJhY3RGb3JtVmFsdWVzKGZpZWxkU3RhdGUsIGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChuZXN0ZWRGaWVsZHNTdGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVzW2tleV0gPSBuZXN0ZWRGaWVsZHNTdGF0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChmaWVsZHNTdGF0ZVtrZXldKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzW2tleV0gPSBmaWVsZFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZXM7XG59XG5cbnZhciBpc0VtcHR5T2JqZWN0ID0gKHZhbHVlKSA9PiBpc09iamVjdCh2YWx1ZSkgJiYgIU9iamVjdC5rZXlzKHZhbHVlKS5sZW5ndGg7XG5cbnZhciBpc0ZpbGVJbnB1dCA9IChlbGVtZW50KSA9PiBlbGVtZW50LnR5cGUgPT09ICdmaWxlJztcblxudmFyIGlzRnVuY3Rpb24gPSAodmFsdWUpID0+IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJztcblxudmFyIGlzSFRNTEVsZW1lbnQgPSAodmFsdWUpID0+IHtcbiAgICBpZiAoIWlzV2ViKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3Qgb3duZXIgPSB2YWx1ZSA/IHZhbHVlLm93bmVyRG9jdW1lbnQgOiAwO1xuICAgIHJldHVybiAodmFsdWUgaW5zdGFuY2VvZlxuICAgICAgICAob3duZXIgJiYgb3duZXIuZGVmYXVsdFZpZXcgPyBvd25lci5kZWZhdWx0Vmlldy5IVE1MRWxlbWVudCA6IEhUTUxFbGVtZW50KSk7XG59O1xuXG52YXIgaXNNdWx0aXBsZVNlbGVjdCA9IChlbGVtZW50KSA9PiBlbGVtZW50LnR5cGUgPT09IGBzZWxlY3QtbXVsdGlwbGVgO1xuXG52YXIgaXNSYWRpb0lucHV0ID0gKGVsZW1lbnQpID0+IGVsZW1lbnQudHlwZSA9PT0gJ3JhZGlvJztcblxudmFyIGlzUmFkaW9PckNoZWNrYm94ID0gKHJlZikgPT4gaXNSYWRpb0lucHV0KHJlZikgfHwgaXNDaGVja0JveElucHV0KHJlZik7XG5cbnZhciBsaXZlID0gKHJlZikgPT4gaXNIVE1MRWxlbWVudChyZWYpICYmIHJlZi5pc0Nvbm5lY3RlZDtcblxuZnVuY3Rpb24gYmFzZUdldChvYmplY3QsIHVwZGF0ZVBhdGgpIHtcbiAgICBjb25zdCBsZW5ndGggPSB1cGRhdGVQYXRoLnNsaWNlKDAsIC0xKS5sZW5ndGg7XG4gICAgbGV0IGluZGV4ID0gMDtcbiAgICB3aGlsZSAoaW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgb2JqZWN0ID0gaXNVbmRlZmluZWQob2JqZWN0KSA/IGluZGV4KysgOiBvYmplY3RbdXBkYXRlUGF0aFtpbmRleCsrXV07XG4gICAgfVxuICAgIHJldHVybiBvYmplY3Q7XG59XG5mdW5jdGlvbiBpc0VtcHR5QXJyYXkob2JqKSB7XG4gICAgZm9yIChjb25zdCBrZXkgaW4gb2JqKSB7XG4gICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoa2V5KSAmJiAhaXNVbmRlZmluZWQob2JqW2tleV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiB1bnNldChvYmplY3QsIHBhdGgpIHtcbiAgICBjb25zdCBwYXRocyA9IEFycmF5LmlzQXJyYXkocGF0aClcbiAgICAgICAgPyBwYXRoXG4gICAgICAgIDogaXNLZXkocGF0aClcbiAgICAgICAgICAgID8gW3BhdGhdXG4gICAgICAgICAgICA6IHN0cmluZ1RvUGF0aChwYXRoKTtcbiAgICBjb25zdCBjaGlsZE9iamVjdCA9IHBhdGhzLmxlbmd0aCA9PT0gMSA/IG9iamVjdCA6IGJhc2VHZXQob2JqZWN0LCBwYXRocyk7XG4gICAgY29uc3QgaW5kZXggPSBwYXRocy5sZW5ndGggLSAxO1xuICAgIGNvbnN0IGtleSA9IHBhdGhzW2luZGV4XTtcbiAgICBpZiAoY2hpbGRPYmplY3QpIHtcbiAgICAgICAgZGVsZXRlIGNoaWxkT2JqZWN0W2tleV07XG4gICAgfVxuICAgIGlmIChpbmRleCAhPT0gMCAmJlxuICAgICAgICAoKGlzT2JqZWN0KGNoaWxkT2JqZWN0KSAmJiBpc0VtcHR5T2JqZWN0KGNoaWxkT2JqZWN0KSkgfHxcbiAgICAgICAgICAgIChBcnJheS5pc0FycmF5KGNoaWxkT2JqZWN0KSAmJiBpc0VtcHR5QXJyYXkoY2hpbGRPYmplY3QpKSkpIHtcbiAgICAgICAgdW5zZXQob2JqZWN0LCBwYXRocy5zbGljZSgwLCAtMSkpO1xuICAgIH1cbiAgICByZXR1cm4gb2JqZWN0O1xufVxuXG52YXIgb2JqZWN0SGFzRnVuY3Rpb24gPSAoZGF0YSkgPT4ge1xuICAgIGZvciAoY29uc3Qga2V5IGluIGRhdGEpIHtcbiAgICAgICAgaWYgKGlzRnVuY3Rpb24oZGF0YVtrZXldKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxuZnVuY3Rpb24gaXNUcmF2ZXJzYWJsZSh2YWx1ZSkge1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKSB8fCAoaXNPYmplY3QodmFsdWUpICYmICFvYmplY3RIYXNGdW5jdGlvbih2YWx1ZSkpO1xufVxuZnVuY3Rpb24gbWFya0ZpZWxkc0RpcnR5KGRhdGEsIGZpZWxkcyA9IHt9KSB7XG4gICAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGRhdGFba2V5XTtcbiAgICAgICAgaWYgKGlzVHJhdmVyc2FibGUodmFsdWUpKSB7XG4gICAgICAgICAgICBmaWVsZHNba2V5XSA9IEFycmF5LmlzQXJyYXkodmFsdWUpID8gW10gOiB7fTtcbiAgICAgICAgICAgIG1hcmtGaWVsZHNEaXJ0eSh2YWx1ZSwgZmllbGRzW2tleV0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCFpc1VuZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGZpZWxkc1trZXldID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmllbGRzO1xufVxuZnVuY3Rpb24gZ2V0RGlydHlGaWVsZHMoZGF0YSwgZm9ybVZhbHVlcywgZGlydHlGaWVsZHNGcm9tVmFsdWVzKSB7XG4gICAgaWYgKCFkaXJ0eUZpZWxkc0Zyb21WYWx1ZXMpIHtcbiAgICAgICAgZGlydHlGaWVsZHNGcm9tVmFsdWVzID0gbWFya0ZpZWxkc0RpcnR5KGZvcm1WYWx1ZXMpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGtleSBpbiBkYXRhKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gZGF0YVtrZXldO1xuICAgICAgICBpZiAoaXNUcmF2ZXJzYWJsZSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGlmIChpc1VuZGVmaW5lZChmb3JtVmFsdWVzKSB8fCBpc1ByaW1pdGl2ZShkaXJ0eUZpZWxkc0Zyb21WYWx1ZXNba2V5XSkpIHtcbiAgICAgICAgICAgICAgICBkaXJ0eUZpZWxkc0Zyb21WYWx1ZXNba2V5XSA9IG1hcmtGaWVsZHNEaXJ0eSh2YWx1ZSwgQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyBbXSA6IHt9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGdldERpcnR5RmllbGRzKHZhbHVlLCBpc051bGxPclVuZGVmaW5lZChmb3JtVmFsdWVzKSA/IHt9IDogZm9ybVZhbHVlc1trZXldLCBkaXJ0eUZpZWxkc0Zyb21WYWx1ZXNba2V5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBmb3JtVmFsdWUgPSBmb3JtVmFsdWVzW2tleV07XG4gICAgICAgICAgICBkaXJ0eUZpZWxkc0Zyb21WYWx1ZXNba2V5XSA9ICFkZWVwRXF1YWwodmFsdWUsIGZvcm1WYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRpcnR5RmllbGRzRnJvbVZhbHVlcztcbn1cblxuY29uc3QgZGVmYXVsdFJlc3VsdCA9IHtcbiAgICB2YWx1ZTogZmFsc2UsXG4gICAgaXNWYWxpZDogZmFsc2UsXG59O1xuY29uc3QgdmFsaWRSZXN1bHQgPSB7IHZhbHVlOiB0cnVlLCBpc1ZhbGlkOiB0cnVlIH07XG52YXIgZ2V0Q2hlY2tib3hWYWx1ZSA9IChvcHRpb25zKSA9PiB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gb3B0aW9uc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIoKG9wdGlvbikgPT4gb3B0aW9uICYmIG9wdGlvbi5jaGVja2VkICYmICFvcHRpb24uZGlzYWJsZWQpXG4gICAgICAgICAgICAgICAgLm1hcCgob3B0aW9uKSA9PiBvcHRpb24udmFsdWUpO1xuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlcywgaXNWYWxpZDogISF2YWx1ZXMubGVuZ3RoIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9wdGlvbnNbMF0uY2hlY2tlZCAmJiAhb3B0aW9uc1swXS5kaXNhYmxlZFxuICAgICAgICAgICAgPyAvLyBAdHMtZXhwZWN0LWVycm9yIGV4cGVjdGVkIHRvIHdvcmsgaW4gdGhlIGJyb3dzZXJcbiAgICAgICAgICAgICAgICBvcHRpb25zWzBdLmF0dHJpYnV0ZXMgJiYgIWlzVW5kZWZpbmVkKG9wdGlvbnNbMF0uYXR0cmlidXRlcy52YWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgPyBpc1VuZGVmaW5lZChvcHRpb25zWzBdLnZhbHVlKSB8fCBvcHRpb25zWzBdLnZhbHVlID09PSAnJ1xuICAgICAgICAgICAgICAgICAgICAgICAgPyB2YWxpZFJlc3VsdFxuICAgICAgICAgICAgICAgICAgICAgICAgOiB7IHZhbHVlOiBvcHRpb25zWzBdLnZhbHVlLCBpc1ZhbGlkOiB0cnVlIH1cbiAgICAgICAgICAgICAgICAgICAgOiB2YWxpZFJlc3VsdFxuICAgICAgICAgICAgOiBkZWZhdWx0UmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4gZGVmYXVsdFJlc3VsdDtcbn07XG5cbnZhciBnZXRGaWVsZFZhbHVlQXMgPSAodmFsdWUsIHsgdmFsdWVBc051bWJlciwgdmFsdWVBc0RhdGUsIHNldFZhbHVlQXMgfSkgPT4gaXNVbmRlZmluZWQodmFsdWUpXG4gICAgPyB2YWx1ZVxuICAgIDogdmFsdWVBc051bWJlclxuICAgICAgICA/IHZhbHVlID09PSAnJ1xuICAgICAgICAgICAgPyBOYU5cbiAgICAgICAgICAgIDogdmFsdWVcbiAgICAgICAgICAgICAgICA/ICt2YWx1ZVxuICAgICAgICAgICAgICAgIDogdmFsdWVcbiAgICAgICAgOiB2YWx1ZUFzRGF0ZSAmJiBpc1N0cmluZyh2YWx1ZSlcbiAgICAgICAgICAgID8gbmV3IERhdGUodmFsdWUpXG4gICAgICAgICAgICA6IHNldFZhbHVlQXNcbiAgICAgICAgICAgICAgICA/IHNldFZhbHVlQXModmFsdWUpXG4gICAgICAgICAgICAgICAgOiB2YWx1ZTtcblxuY29uc3QgZGVmYXVsdFJldHVybiA9IHtcbiAgICBpc1ZhbGlkOiBmYWxzZSxcbiAgICB2YWx1ZTogbnVsbCxcbn07XG52YXIgZ2V0UmFkaW9WYWx1ZSA9IChvcHRpb25zKSA9PiBBcnJheS5pc0FycmF5KG9wdGlvbnMpXG4gICAgPyBvcHRpb25zLnJlZHVjZSgocHJldmlvdXMsIG9wdGlvbikgPT4gb3B0aW9uICYmIG9wdGlvbi5jaGVja2VkICYmICFvcHRpb24uZGlzYWJsZWRcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBpc1ZhbGlkOiB0cnVlLFxuICAgICAgICAgICAgdmFsdWU6IG9wdGlvbi52YWx1ZSxcbiAgICAgICAgfVxuICAgICAgICA6IHByZXZpb3VzLCBkZWZhdWx0UmV0dXJuKVxuICAgIDogZGVmYXVsdFJldHVybjtcblxuZnVuY3Rpb24gZ2V0RmllbGRWYWx1ZShfZikge1xuICAgIGNvbnN0IHJlZiA9IF9mLnJlZjtcbiAgICBpZiAoaXNGaWxlSW5wdXQocmVmKSkge1xuICAgICAgICByZXR1cm4gcmVmLmZpbGVzO1xuICAgIH1cbiAgICBpZiAoaXNSYWRpb0lucHV0KHJlZikpIHtcbiAgICAgICAgcmV0dXJuIGdldFJhZGlvVmFsdWUoX2YucmVmcykudmFsdWU7XG4gICAgfVxuICAgIGlmIChpc011bHRpcGxlU2VsZWN0KHJlZikpIHtcbiAgICAgICAgcmV0dXJuIFsuLi5yZWYuc2VsZWN0ZWRPcHRpb25zXS5tYXAoKHsgdmFsdWUgfSkgPT4gdmFsdWUpO1xuICAgIH1cbiAgICBpZiAoaXNDaGVja0JveElucHV0KHJlZikpIHtcbiAgICAgICAgcmV0dXJuIGdldENoZWNrYm94VmFsdWUoX2YucmVmcykudmFsdWU7XG4gICAgfVxuICAgIHJldHVybiBnZXRGaWVsZFZhbHVlQXMoaXNVbmRlZmluZWQocmVmLnZhbHVlKSA/IF9mLnJlZi52YWx1ZSA6IHJlZi52YWx1ZSwgX2YpO1xufVxuXG52YXIgZ2V0UmVzb2x2ZXJPcHRpb25zID0gKGZpZWxkc05hbWVzLCBfZmllbGRzLCBjcml0ZXJpYU1vZGUsIHNob3VsZFVzZU5hdGl2ZVZhbGlkYXRpb24pID0+IHtcbiAgICBjb25zdCBmaWVsZHMgPSB7fTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgZmllbGRzTmFtZXMpIHtcbiAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgIGZpZWxkICYmIHNldChmaWVsZHMsIG5hbWUsIGZpZWxkLl9mKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY3JpdGVyaWFNb2RlLFxuICAgICAgICBuYW1lczogWy4uLmZpZWxkc05hbWVzXSxcbiAgICAgICAgZmllbGRzLFxuICAgICAgICBzaG91bGRVc2VOYXRpdmVWYWxpZGF0aW9uLFxuICAgIH07XG59O1xuXG52YXIgaXNSZWdleCA9ICh2YWx1ZSkgPT4gdmFsdWUgaW5zdGFuY2VvZiBSZWdFeHA7XG5cbnZhciBnZXRSdWxlVmFsdWUgPSAocnVsZSkgPT4gaXNVbmRlZmluZWQocnVsZSlcbiAgICA/IHJ1bGVcbiAgICA6IGlzUmVnZXgocnVsZSlcbiAgICAgICAgPyBydWxlLnNvdXJjZVxuICAgICAgICA6IGlzT2JqZWN0KHJ1bGUpXG4gICAgICAgICAgICA/IGlzUmVnZXgocnVsZS52YWx1ZSlcbiAgICAgICAgICAgICAgICA/IHJ1bGUudmFsdWUuc291cmNlXG4gICAgICAgICAgICAgICAgOiBydWxlLnZhbHVlXG4gICAgICAgICAgICA6IHJ1bGU7XG5cbnZhciBnZXRWYWxpZGF0aW9uTW9kZXMgPSAobW9kZSkgPT4gKHtcbiAgICBpc09uU3VibWl0OiAhbW9kZSB8fCBtb2RlID09PSBWQUxJREFUSU9OX01PREUub25TdWJtaXQsXG4gICAgaXNPbkJsdXI6IG1vZGUgPT09IFZBTElEQVRJT05fTU9ERS5vbkJsdXIsXG4gICAgaXNPbkNoYW5nZTogbW9kZSA9PT0gVkFMSURBVElPTl9NT0RFLm9uQ2hhbmdlLFxuICAgIGlzT25BbGw6IG1vZGUgPT09IFZBTElEQVRJT05fTU9ERS5hbGwsXG4gICAgaXNPblRvdWNoOiBtb2RlID09PSBWQUxJREFUSU9OX01PREUub25Ub3VjaGVkLFxufSk7XG5cbmNvbnN0IEFTWU5DX0ZVTkNUSU9OID0gJ0FzeW5jRnVuY3Rpb24nO1xudmFyIGhhc1Byb21pc2VWYWxpZGF0aW9uID0gKGZpZWxkUmVmZXJlbmNlKSA9PiAhIWZpZWxkUmVmZXJlbmNlICYmXG4gICAgISFmaWVsZFJlZmVyZW5jZS52YWxpZGF0ZSAmJlxuICAgICEhKChpc0Z1bmN0aW9uKGZpZWxkUmVmZXJlbmNlLnZhbGlkYXRlKSAmJlxuICAgICAgICBmaWVsZFJlZmVyZW5jZS52YWxpZGF0ZS5jb25zdHJ1Y3Rvci5uYW1lID09PSBBU1lOQ19GVU5DVElPTikgfHxcbiAgICAgICAgKGlzT2JqZWN0KGZpZWxkUmVmZXJlbmNlLnZhbGlkYXRlKSAmJlxuICAgICAgICAgICAgT2JqZWN0LnZhbHVlcyhmaWVsZFJlZmVyZW5jZS52YWxpZGF0ZSkuZmluZCgodmFsaWRhdGVGdW5jdGlvbikgPT4gdmFsaWRhdGVGdW5jdGlvbi5jb25zdHJ1Y3Rvci5uYW1lID09PSBBU1lOQ19GVU5DVElPTikpKTtcblxudmFyIGhhc1ZhbGlkYXRpb24gPSAob3B0aW9ucykgPT4gb3B0aW9ucy5tb3VudCAmJlxuICAgIChvcHRpb25zLnJlcXVpcmVkIHx8XG4gICAgICAgIG9wdGlvbnMubWluIHx8XG4gICAgICAgIG9wdGlvbnMubWF4IHx8XG4gICAgICAgIG9wdGlvbnMubWF4TGVuZ3RoIHx8XG4gICAgICAgIG9wdGlvbnMubWluTGVuZ3RoIHx8XG4gICAgICAgIG9wdGlvbnMucGF0dGVybiB8fFxuICAgICAgICBvcHRpb25zLnZhbGlkYXRlKTtcblxudmFyIGlzV2F0Y2hlZCA9IChuYW1lLCBfbmFtZXMsIGlzQmx1ckV2ZW50KSA9PiAhaXNCbHVyRXZlbnQgJiZcbiAgICAoX25hbWVzLndhdGNoQWxsIHx8XG4gICAgICAgIF9uYW1lcy53YXRjaC5oYXMobmFtZSkgfHxcbiAgICAgICAgWy4uLl9uYW1lcy53YXRjaF0uc29tZSgod2F0Y2hOYW1lKSA9PiBuYW1lLnN0YXJ0c1dpdGgod2F0Y2hOYW1lKSAmJlxuICAgICAgICAgICAgL15cXC5cXHcrLy50ZXN0KG5hbWUuc2xpY2Uod2F0Y2hOYW1lLmxlbmd0aCkpKSk7XG5cbmNvbnN0IGl0ZXJhdGVGaWVsZHNCeUFjdGlvbiA9IChmaWVsZHMsIGFjdGlvbiwgZmllbGRzTmFtZXMsIGFib3J0RWFybHkpID0+IHtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBmaWVsZHNOYW1lcyB8fCBPYmplY3Qua2V5cyhmaWVsZHMpKSB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KGZpZWxkcywga2V5KTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCB7IF9mLCAuLi5jdXJyZW50RmllbGQgfSA9IGZpZWxkO1xuICAgICAgICAgICAgaWYgKF9mKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9mLnJlZnMgJiYgX2YucmVmc1swXSAmJiBhY3Rpb24oX2YucmVmc1swXSwga2V5KSAmJiAhYWJvcnRFYXJseSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoX2YucmVmICYmIGFjdGlvbihfZi5yZWYsIF9mLm5hbWUpICYmICFhYm9ydEVhcmx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZXJhdGVGaWVsZHNCeUFjdGlvbihjdXJyZW50RmllbGQsIGFjdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaXNPYmplY3QoY3VycmVudEZpZWxkKSkge1xuICAgICAgICAgICAgICAgIGlmIChpdGVyYXRlRmllbGRzQnlBY3Rpb24oY3VycmVudEZpZWxkLCBhY3Rpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm47XG59O1xuXG5mdW5jdGlvbiBzY2hlbWFFcnJvckxvb2t1cChlcnJvcnMsIF9maWVsZHMsIG5hbWUpIHtcbiAgICBjb25zdCBlcnJvciA9IGdldChlcnJvcnMsIG5hbWUpO1xuICAgIGlmIChlcnJvciB8fCBpc0tleShuYW1lKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBjb25zdCBuYW1lcyA9IG5hbWUuc3BsaXQoJy4nKTtcbiAgICB3aGlsZSAobmFtZXMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IG5hbWVzLmpvaW4oJy4nKTtcbiAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoX2ZpZWxkcywgZmllbGROYW1lKTtcbiAgICAgICAgY29uc3QgZm91bmRFcnJvciA9IGdldChlcnJvcnMsIGZpZWxkTmFtZSk7XG4gICAgICAgIGlmIChmaWVsZCAmJiAhQXJyYXkuaXNBcnJheShmaWVsZCkgJiYgbmFtZSAhPT0gZmllbGROYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4geyBuYW1lIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvdW5kRXJyb3IgJiYgZm91bmRFcnJvci50eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG5hbWU6IGZpZWxkTmFtZSxcbiAgICAgICAgICAgICAgICBlcnJvcjogZm91bmRFcnJvcixcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvdW5kRXJyb3IgJiYgZm91bmRFcnJvci5yb290ICYmIGZvdW5kRXJyb3Iucm9vdC50eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG5hbWU6IGAke2ZpZWxkTmFtZX0ucm9vdGAsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZvdW5kRXJyb3Iucm9vdCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgbmFtZXMucG9wKCk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIG5hbWUsXG4gICAgfTtcbn1cblxudmFyIHNob3VsZFJlbmRlckZvcm1TdGF0ZSA9IChmb3JtU3RhdGVEYXRhLCBfcHJveHlGb3JtU3RhdGUsIHVwZGF0ZUZvcm1TdGF0ZSwgaXNSb290KSA9PiB7XG4gICAgdXBkYXRlRm9ybVN0YXRlKGZvcm1TdGF0ZURhdGEpO1xuICAgIGNvbnN0IHsgbmFtZSwgLi4uZm9ybVN0YXRlIH0gPSBmb3JtU3RhdGVEYXRhO1xuICAgIHJldHVybiAoaXNFbXB0eU9iamVjdChmb3JtU3RhdGUpIHx8XG4gICAgICAgIE9iamVjdC5rZXlzKGZvcm1TdGF0ZSkubGVuZ3RoID49IE9iamVjdC5rZXlzKF9wcm94eUZvcm1TdGF0ZSkubGVuZ3RoIHx8XG4gICAgICAgIE9iamVjdC5rZXlzKGZvcm1TdGF0ZSkuZmluZCgoa2V5KSA9PiBfcHJveHlGb3JtU3RhdGVba2V5XSA9PT1cbiAgICAgICAgICAgICghaXNSb290IHx8IFZBTElEQVRJT05fTU9ERS5hbGwpKSk7XG59O1xuXG52YXIgc2hvdWxkU3Vic2NyaWJlQnlOYW1lID0gKG5hbWUsIHNpZ25hbE5hbWUsIGV4YWN0KSA9PiAhbmFtZSB8fFxuICAgICFzaWduYWxOYW1lIHx8XG4gICAgbmFtZSA9PT0gc2lnbmFsTmFtZSB8fFxuICAgIGNvbnZlcnRUb0FycmF5UGF5bG9hZChuYW1lKS5zb21lKChjdXJyZW50TmFtZSkgPT4gY3VycmVudE5hbWUgJiZcbiAgICAgICAgKGV4YWN0XG4gICAgICAgICAgICA/IGN1cnJlbnROYW1lID09PSBzaWduYWxOYW1lXG4gICAgICAgICAgICA6IGN1cnJlbnROYW1lLnN0YXJ0c1dpdGgoc2lnbmFsTmFtZSkgfHxcbiAgICAgICAgICAgICAgICBzaWduYWxOYW1lLnN0YXJ0c1dpdGgoY3VycmVudE5hbWUpKSk7XG5cbnZhciBza2lwVmFsaWRhdGlvbiA9IChpc0JsdXJFdmVudCwgaXNUb3VjaGVkLCBpc1N1Ym1pdHRlZCwgcmVWYWxpZGF0ZU1vZGUsIG1vZGUpID0+IHtcbiAgICBpZiAobW9kZS5pc09uQWxsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZWxzZSBpZiAoIWlzU3VibWl0dGVkICYmIG1vZGUuaXNPblRvdWNoKSB7XG4gICAgICAgIHJldHVybiAhKGlzVG91Y2hlZCB8fCBpc0JsdXJFdmVudCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGlzU3VibWl0dGVkID8gcmVWYWxpZGF0ZU1vZGUuaXNPbkJsdXIgOiBtb2RlLmlzT25CbHVyKSB7XG4gICAgICAgIHJldHVybiAhaXNCbHVyRXZlbnQ7XG4gICAgfVxuICAgIGVsc2UgaWYgKGlzU3VibWl0dGVkID8gcmVWYWxpZGF0ZU1vZGUuaXNPbkNoYW5nZSA6IG1vZGUuaXNPbkNoYW5nZSkge1xuICAgICAgICByZXR1cm4gaXNCbHVyRXZlbnQ7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcblxudmFyIHVuc2V0RW1wdHlBcnJheSA9IChyZWYsIG5hbWUpID0+ICFjb21wYWN0KGdldChyZWYsIG5hbWUpKS5sZW5ndGggJiYgdW5zZXQocmVmLCBuYW1lKTtcblxudmFyIHVwZGF0ZUZpZWxkQXJyYXlSb290RXJyb3IgPSAoZXJyb3JzLCBlcnJvciwgbmFtZSkgPT4ge1xuICAgIGNvbnN0IGZpZWxkQXJyYXlFcnJvcnMgPSBjb252ZXJ0VG9BcnJheVBheWxvYWQoZ2V0KGVycm9ycywgbmFtZSkpO1xuICAgIHNldChmaWVsZEFycmF5RXJyb3JzLCAncm9vdCcsIGVycm9yW25hbWVdKTtcbiAgICBzZXQoZXJyb3JzLCBuYW1lLCBmaWVsZEFycmF5RXJyb3JzKTtcbiAgICByZXR1cm4gZXJyb3JzO1xufTtcblxuZnVuY3Rpb24gZ2V0VmFsaWRhdGVFcnJvcihyZXN1bHQsIHJlZiwgdHlwZSA9ICd2YWxpZGF0ZScpIHtcbiAgICBpZiAoaXNTdHJpbmcocmVzdWx0KSB8fFxuICAgICAgICAoQXJyYXkuaXNBcnJheShyZXN1bHQpICYmIHJlc3VsdC5ldmVyeShpc1N0cmluZykpIHx8XG4gICAgICAgIChpc0Jvb2xlYW4ocmVzdWx0KSAmJiAhcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGlzU3RyaW5nKHJlc3VsdCkgPyByZXN1bHQgOiAnJyxcbiAgICAgICAgICAgIHJlZixcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbnZhciBnZXRWYWx1ZUFuZE1lc3NhZ2UgPSAodmFsaWRhdGlvbkRhdGEpID0+IGlzT2JqZWN0KHZhbGlkYXRpb25EYXRhKSAmJiAhaXNSZWdleCh2YWxpZGF0aW9uRGF0YSlcbiAgICA/IHZhbGlkYXRpb25EYXRhXG4gICAgOiB7XG4gICAgICAgIHZhbHVlOiB2YWxpZGF0aW9uRGF0YSxcbiAgICAgICAgbWVzc2FnZTogJycsXG4gICAgfTtcblxudmFyIHZhbGlkYXRlRmllbGQgPSBhc3luYyAoZmllbGQsIGRpc2FibGVkRmllbGROYW1lcywgZm9ybVZhbHVlcywgdmFsaWRhdGVBbGxGaWVsZENyaXRlcmlhLCBzaG91bGRVc2VOYXRpdmVWYWxpZGF0aW9uLCBpc0ZpZWxkQXJyYXkpID0+IHtcbiAgICBjb25zdCB7IHJlZiwgcmVmcywgcmVxdWlyZWQsIG1heExlbmd0aCwgbWluTGVuZ3RoLCBtaW4sIG1heCwgcGF0dGVybiwgdmFsaWRhdGUsIG5hbWUsIHZhbHVlQXNOdW1iZXIsIG1vdW50LCB9ID0gZmllbGQuX2Y7XG4gICAgY29uc3QgaW5wdXRWYWx1ZSA9IGdldChmb3JtVmFsdWVzLCBuYW1lKTtcbiAgICBpZiAoIW1vdW50IHx8IGRpc2FibGVkRmllbGROYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBjb25zdCBpbnB1dFJlZiA9IHJlZnMgPyByZWZzWzBdIDogcmVmO1xuICAgIGNvbnN0IHNldEN1c3RvbVZhbGlkaXR5ID0gKG1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKHNob3VsZFVzZU5hdGl2ZVZhbGlkYXRpb24gJiYgaW5wdXRSZWYucmVwb3J0VmFsaWRpdHkpIHtcbiAgICAgICAgICAgIGlucHV0UmVmLnNldEN1c3RvbVZhbGlkaXR5KGlzQm9vbGVhbihtZXNzYWdlKSA/ICcnIDogbWVzc2FnZSB8fCAnJyk7XG4gICAgICAgICAgICBpbnB1dFJlZi5yZXBvcnRWYWxpZGl0eSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBjb25zdCBlcnJvciA9IHt9O1xuICAgIGNvbnN0IGlzUmFkaW8gPSBpc1JhZGlvSW5wdXQocmVmKTtcbiAgICBjb25zdCBpc0NoZWNrQm94ID0gaXNDaGVja0JveElucHV0KHJlZik7XG4gICAgY29uc3QgaXNSYWRpb09yQ2hlY2tib3ggPSBpc1JhZGlvIHx8IGlzQ2hlY2tCb3g7XG4gICAgY29uc3QgaXNFbXB0eSA9ICgodmFsdWVBc051bWJlciB8fCBpc0ZpbGVJbnB1dChyZWYpKSAmJlxuICAgICAgICBpc1VuZGVmaW5lZChyZWYudmFsdWUpICYmXG4gICAgICAgIGlzVW5kZWZpbmVkKGlucHV0VmFsdWUpKSB8fFxuICAgICAgICAoaXNIVE1MRWxlbWVudChyZWYpICYmIHJlZi52YWx1ZSA9PT0gJycpIHx8XG4gICAgICAgIGlucHV0VmFsdWUgPT09ICcnIHx8XG4gICAgICAgIChBcnJheS5pc0FycmF5KGlucHV0VmFsdWUpICYmICFpbnB1dFZhbHVlLmxlbmd0aCk7XG4gICAgY29uc3QgYXBwZW5kRXJyb3JzQ3VycnkgPSBhcHBlbmRFcnJvcnMuYmluZChudWxsLCBuYW1lLCB2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWEsIGVycm9yKTtcbiAgICBjb25zdCBnZXRNaW5NYXhNZXNzYWdlID0gKGV4Y2VlZE1heCwgbWF4TGVuZ3RoTWVzc2FnZSwgbWluTGVuZ3RoTWVzc2FnZSwgbWF4VHlwZSA9IElOUFVUX1ZBTElEQVRJT05fUlVMRVMubWF4TGVuZ3RoLCBtaW5UeXBlID0gSU5QVVRfVkFMSURBVElPTl9SVUxFUy5taW5MZW5ndGgpID0+IHtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IGV4Y2VlZE1heCA/IG1heExlbmd0aE1lc3NhZ2UgOiBtaW5MZW5ndGhNZXNzYWdlO1xuICAgICAgICBlcnJvcltuYW1lXSA9IHtcbiAgICAgICAgICAgIHR5cGU6IGV4Y2VlZE1heCA/IG1heFR5cGUgOiBtaW5UeXBlLFxuICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgIHJlZixcbiAgICAgICAgICAgIC4uLmFwcGVuZEVycm9yc0N1cnJ5KGV4Y2VlZE1heCA/IG1heFR5cGUgOiBtaW5UeXBlLCBtZXNzYWdlKSxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIGlmIChpc0ZpZWxkQXJyYXlcbiAgICAgICAgPyAhQXJyYXkuaXNBcnJheShpbnB1dFZhbHVlKSB8fCAhaW5wdXRWYWx1ZS5sZW5ndGhcbiAgICAgICAgOiByZXF1aXJlZCAmJlxuICAgICAgICAgICAgKCghaXNSYWRpb09yQ2hlY2tib3ggJiYgKGlzRW1wdHkgfHwgaXNOdWxsT3JVbmRlZmluZWQoaW5wdXRWYWx1ZSkpKSB8fFxuICAgICAgICAgICAgICAgIChpc0Jvb2xlYW4oaW5wdXRWYWx1ZSkgJiYgIWlucHV0VmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgKGlzQ2hlY2tCb3ggJiYgIWdldENoZWNrYm94VmFsdWUocmVmcykuaXNWYWxpZCkgfHxcbiAgICAgICAgICAgICAgICAoaXNSYWRpbyAmJiAhZ2V0UmFkaW9WYWx1ZShyZWZzKS5pc1ZhbGlkKSkpIHtcbiAgICAgICAgY29uc3QgeyB2YWx1ZSwgbWVzc2FnZSB9ID0gaXNTdHJpbmcocmVxdWlyZWQpXG4gICAgICAgICAgICA/IHsgdmFsdWU6ICEhcmVxdWlyZWQsIG1lc3NhZ2U6IHJlcXVpcmVkIH1cbiAgICAgICAgICAgIDogZ2V0VmFsdWVBbmRNZXNzYWdlKHJlcXVpcmVkKTtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICBlcnJvcltuYW1lXSA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBJTlBVVF9WQUxJREFUSU9OX1JVTEVTLnJlcXVpcmVkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgcmVmOiBpbnB1dFJlZixcbiAgICAgICAgICAgICAgICAuLi5hcHBlbmRFcnJvcnNDdXJyeShJTlBVVF9WQUxJREFUSU9OX1JVTEVTLnJlcXVpcmVkLCBtZXNzYWdlKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoIXZhbGlkYXRlQWxsRmllbGRDcml0ZXJpYSkge1xuICAgICAgICAgICAgICAgIHNldEN1c3RvbVZhbGlkaXR5KG1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWlzRW1wdHkgJiYgKCFpc051bGxPclVuZGVmaW5lZChtaW4pIHx8ICFpc051bGxPclVuZGVmaW5lZChtYXgpKSkge1xuICAgICAgICBsZXQgZXhjZWVkTWF4O1xuICAgICAgICBsZXQgZXhjZWVkTWluO1xuICAgICAgICBjb25zdCBtYXhPdXRwdXQgPSBnZXRWYWx1ZUFuZE1lc3NhZ2UobWF4KTtcbiAgICAgICAgY29uc3QgbWluT3V0cHV0ID0gZ2V0VmFsdWVBbmRNZXNzYWdlKG1pbik7XG4gICAgICAgIGlmICghaXNOdWxsT3JVbmRlZmluZWQoaW5wdXRWYWx1ZSkgJiYgIWlzTmFOKGlucHV0VmFsdWUpKSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZU51bWJlciA9IHJlZi52YWx1ZUFzTnVtYmVyIHx8XG4gICAgICAgICAgICAgICAgKGlucHV0VmFsdWUgPyAraW5wdXRWYWx1ZSA6IGlucHV0VmFsdWUpO1xuICAgICAgICAgICAgaWYgKCFpc051bGxPclVuZGVmaW5lZChtYXhPdXRwdXQudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgZXhjZWVkTWF4ID0gdmFsdWVOdW1iZXIgPiBtYXhPdXRwdXQudmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKG1pbk91dHB1dC52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBleGNlZWRNaW4gPSB2YWx1ZU51bWJlciA8IG1pbk91dHB1dC52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlRGF0ZSA9IHJlZi52YWx1ZUFzRGF0ZSB8fCBuZXcgRGF0ZShpbnB1dFZhbHVlKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbnZlcnRUaW1lVG9EYXRlID0gKHRpbWUpID0+IG5ldyBEYXRlKG5ldyBEYXRlKCkudG9EYXRlU3RyaW5nKCkgKyAnICcgKyB0aW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGlzVGltZSA9IHJlZi50eXBlID09ICd0aW1lJztcbiAgICAgICAgICAgIGNvbnN0IGlzV2VlayA9IHJlZi50eXBlID09ICd3ZWVrJztcbiAgICAgICAgICAgIGlmIChpc1N0cmluZyhtYXhPdXRwdXQudmFsdWUpICYmIGlucHV0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICBleGNlZWRNYXggPSBpc1RpbWVcbiAgICAgICAgICAgICAgICAgICAgPyBjb252ZXJ0VGltZVRvRGF0ZShpbnB1dFZhbHVlKSA+IGNvbnZlcnRUaW1lVG9EYXRlKG1heE91dHB1dC52YWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgOiBpc1dlZWtcbiAgICAgICAgICAgICAgICAgICAgICAgID8gaW5wdXRWYWx1ZSA+IG1heE91dHB1dC52YWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgOiB2YWx1ZURhdGUgPiBuZXcgRGF0ZShtYXhPdXRwdXQudmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaW5nKG1pbk91dHB1dC52YWx1ZSkgJiYgaW5wdXRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIGV4Y2VlZE1pbiA9IGlzVGltZVxuICAgICAgICAgICAgICAgICAgICA/IGNvbnZlcnRUaW1lVG9EYXRlKGlucHV0VmFsdWUpIDwgY29udmVydFRpbWVUb0RhdGUobWluT3V0cHV0LnZhbHVlKVxuICAgICAgICAgICAgICAgICAgICA6IGlzV2Vla1xuICAgICAgICAgICAgICAgICAgICAgICAgPyBpbnB1dFZhbHVlIDwgbWluT3V0cHV0LnZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHZhbHVlRGF0ZSA8IG5ldyBEYXRlKG1pbk91dHB1dC52YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4Y2VlZE1heCB8fCBleGNlZWRNaW4pIHtcbiAgICAgICAgICAgIGdldE1pbk1heE1lc3NhZ2UoISFleGNlZWRNYXgsIG1heE91dHB1dC5tZXNzYWdlLCBtaW5PdXRwdXQubWVzc2FnZSwgSU5QVVRfVkFMSURBVElPTl9SVUxFUy5tYXgsIElOUFVUX1ZBTElEQVRJT05fUlVMRVMubWluKTtcbiAgICAgICAgICAgIGlmICghdmFsaWRhdGVBbGxGaWVsZENyaXRlcmlhKSB7XG4gICAgICAgICAgICAgICAgc2V0Q3VzdG9tVmFsaWRpdHkoZXJyb3JbbmFtZV0ubWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGlmICgobWF4TGVuZ3RoIHx8IG1pbkxlbmd0aCkgJiZcbiAgICAgICAgIWlzRW1wdHkgJiZcbiAgICAgICAgKGlzU3RyaW5nKGlucHV0VmFsdWUpIHx8IChpc0ZpZWxkQXJyYXkgJiYgQXJyYXkuaXNBcnJheShpbnB1dFZhbHVlKSkpKSB7XG4gICAgICAgIGNvbnN0IG1heExlbmd0aE91dHB1dCA9IGdldFZhbHVlQW5kTWVzc2FnZShtYXhMZW5ndGgpO1xuICAgICAgICBjb25zdCBtaW5MZW5ndGhPdXRwdXQgPSBnZXRWYWx1ZUFuZE1lc3NhZ2UobWluTGVuZ3RoKTtcbiAgICAgICAgY29uc3QgZXhjZWVkTWF4ID0gIWlzTnVsbE9yVW5kZWZpbmVkKG1heExlbmd0aE91dHB1dC52YWx1ZSkgJiZcbiAgICAgICAgICAgIGlucHV0VmFsdWUubGVuZ3RoID4gK21heExlbmd0aE91dHB1dC52YWx1ZTtcbiAgICAgICAgY29uc3QgZXhjZWVkTWluID0gIWlzTnVsbE9yVW5kZWZpbmVkKG1pbkxlbmd0aE91dHB1dC52YWx1ZSkgJiZcbiAgICAgICAgICAgIGlucHV0VmFsdWUubGVuZ3RoIDwgK21pbkxlbmd0aE91dHB1dC52YWx1ZTtcbiAgICAgICAgaWYgKGV4Y2VlZE1heCB8fCBleGNlZWRNaW4pIHtcbiAgICAgICAgICAgIGdldE1pbk1heE1lc3NhZ2UoZXhjZWVkTWF4LCBtYXhMZW5ndGhPdXRwdXQubWVzc2FnZSwgbWluTGVuZ3RoT3V0cHV0Lm1lc3NhZ2UpO1xuICAgICAgICAgICAgaWYgKCF2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWEpIHtcbiAgICAgICAgICAgICAgICBzZXRDdXN0b21WYWxpZGl0eShlcnJvcltuYW1lXS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHBhdHRlcm4gJiYgIWlzRW1wdHkgJiYgaXNTdHJpbmcoaW5wdXRWYWx1ZSkpIHtcbiAgICAgICAgY29uc3QgeyB2YWx1ZTogcGF0dGVyblZhbHVlLCBtZXNzYWdlIH0gPSBnZXRWYWx1ZUFuZE1lc3NhZ2UocGF0dGVybik7XG4gICAgICAgIGlmIChpc1JlZ2V4KHBhdHRlcm5WYWx1ZSkgJiYgIWlucHV0VmFsdWUubWF0Y2gocGF0dGVyblZhbHVlKSkge1xuICAgICAgICAgICAgZXJyb3JbbmFtZV0gPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogSU5QVVRfVkFMSURBVElPTl9SVUxFUy5wYXR0ZXJuLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgcmVmLFxuICAgICAgICAgICAgICAgIC4uLmFwcGVuZEVycm9yc0N1cnJ5KElOUFVUX1ZBTElEQVRJT05fUlVMRVMucGF0dGVybiwgbWVzc2FnZSksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKCF2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWEpIHtcbiAgICAgICAgICAgICAgICBzZXRDdXN0b21WYWxpZGl0eShtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHZhbGlkYXRlKSB7XG4gICAgICAgIGlmIChpc0Z1bmN0aW9uKHZhbGlkYXRlKSkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdmFsaWRhdGUoaW5wdXRWYWx1ZSwgZm9ybVZhbHVlcyk7XG4gICAgICAgICAgICBjb25zdCB2YWxpZGF0ZUVycm9yID0gZ2V0VmFsaWRhdGVFcnJvcihyZXN1bHQsIGlucHV0UmVmKTtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0ZUVycm9yKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JbbmFtZV0gPSB7XG4gICAgICAgICAgICAgICAgICAgIC4uLnZhbGlkYXRlRXJyb3IsXG4gICAgICAgICAgICAgICAgICAgIC4uLmFwcGVuZEVycm9yc0N1cnJ5KElOUFVUX1ZBTElEQVRJT05fUlVMRVMudmFsaWRhdGUsIHZhbGlkYXRlRXJyb3IubWVzc2FnZSksXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAoIXZhbGlkYXRlQWxsRmllbGRDcml0ZXJpYSkge1xuICAgICAgICAgICAgICAgICAgICBzZXRDdXN0b21WYWxpZGl0eSh2YWxpZGF0ZUVycm9yLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzT2JqZWN0KHZhbGlkYXRlKSkge1xuICAgICAgICAgICAgbGV0IHZhbGlkYXRpb25SZXN1bHQgPSB7fTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIHZhbGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc0VtcHR5T2JqZWN0KHZhbGlkYXRpb25SZXN1bHQpICYmICF2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWEpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IHZhbGlkYXRlRXJyb3IgPSBnZXRWYWxpZGF0ZUVycm9yKGF3YWl0IHZhbGlkYXRlW2tleV0oaW5wdXRWYWx1ZSwgZm9ybVZhbHVlcyksIGlucHV0UmVmLCBrZXkpO1xuICAgICAgICAgICAgICAgIGlmICh2YWxpZGF0ZUVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb25SZXN1bHQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAuLi52YWxpZGF0ZUVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYXBwZW5kRXJyb3JzQ3Vycnkoa2V5LCB2YWxpZGF0ZUVycm9yLm1lc3NhZ2UpLFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBzZXRDdXN0b21WYWxpZGl0eSh2YWxpZGF0ZUVycm9yLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsaWRhdGVBbGxGaWVsZENyaXRlcmlhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcltuYW1lXSA9IHZhbGlkYXRpb25SZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzRW1wdHlPYmplY3QodmFsaWRhdGlvblJlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICBlcnJvcltuYW1lXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgcmVmOiBpbnB1dFJlZixcbiAgICAgICAgICAgICAgICAgICAgLi4udmFsaWRhdGlvblJlc3VsdCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGlmICghdmFsaWRhdGVBbGxGaWVsZENyaXRlcmlhKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2V0Q3VzdG9tVmFsaWRpdHkodHJ1ZSk7XG4gICAgcmV0dXJuIGVycm9yO1xufTtcblxuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgbW9kZTogVkFMSURBVElPTl9NT0RFLm9uU3VibWl0LFxuICAgIHJlVmFsaWRhdGVNb2RlOiBWQUxJREFUSU9OX01PREUub25DaGFuZ2UsXG4gICAgc2hvdWxkRm9jdXNFcnJvcjogdHJ1ZSxcbn07XG5mdW5jdGlvbiBjcmVhdGVGb3JtQ29udHJvbChwcm9wcyA9IHt9KSB7XG4gICAgbGV0IF9vcHRpb25zID0ge1xuICAgICAgICAuLi5kZWZhdWx0T3B0aW9ucyxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgfTtcbiAgICBsZXQgX2Zvcm1TdGF0ZSA9IHtcbiAgICAgICAgc3VibWl0Q291bnQ6IDAsXG4gICAgICAgIGlzRGlydHk6IGZhbHNlLFxuICAgICAgICBpc1JlYWR5OiBmYWxzZSxcbiAgICAgICAgaXNMb2FkaW5nOiBpc0Z1bmN0aW9uKF9vcHRpb25zLmRlZmF1bHRWYWx1ZXMpLFxuICAgICAgICBpc1ZhbGlkYXRpbmc6IGZhbHNlLFxuICAgICAgICBpc1N1Ym1pdHRlZDogZmFsc2UsXG4gICAgICAgIGlzU3VibWl0dGluZzogZmFsc2UsXG4gICAgICAgIGlzU3VibWl0U3VjY2Vzc2Z1bDogZmFsc2UsXG4gICAgICAgIGlzVmFsaWQ6IGZhbHNlLFxuICAgICAgICB0b3VjaGVkRmllbGRzOiB7fSxcbiAgICAgICAgZGlydHlGaWVsZHM6IHt9LFxuICAgICAgICB2YWxpZGF0aW5nRmllbGRzOiB7fSxcbiAgICAgICAgZXJyb3JzOiBfb3B0aW9ucy5lcnJvcnMgfHwge30sXG4gICAgICAgIGRpc2FibGVkOiBfb3B0aW9ucy5kaXNhYmxlZCB8fCBmYWxzZSxcbiAgICB9O1xuICAgIGxldCBfZmllbGRzID0ge307XG4gICAgbGV0IF9kZWZhdWx0VmFsdWVzID0gaXNPYmplY3QoX29wdGlvbnMuZGVmYXVsdFZhbHVlcykgfHwgaXNPYmplY3QoX29wdGlvbnMudmFsdWVzKVxuICAgICAgICA/IGNsb25lT2JqZWN0KF9vcHRpb25zLmRlZmF1bHRWYWx1ZXMgfHwgX29wdGlvbnMudmFsdWVzKSB8fCB7fVxuICAgICAgICA6IHt9O1xuICAgIGxldCBfZm9ybVZhbHVlcyA9IF9vcHRpb25zLnNob3VsZFVucmVnaXN0ZXJcbiAgICAgICAgPyB7fVxuICAgICAgICA6IGNsb25lT2JqZWN0KF9kZWZhdWx0VmFsdWVzKTtcbiAgICBsZXQgX3N0YXRlID0ge1xuICAgICAgICBhY3Rpb246IGZhbHNlLFxuICAgICAgICBtb3VudDogZmFsc2UsXG4gICAgICAgIHdhdGNoOiBmYWxzZSxcbiAgICB9O1xuICAgIGxldCBfbmFtZXMgPSB7XG4gICAgICAgIG1vdW50OiBuZXcgU2V0KCksXG4gICAgICAgIGRpc2FibGVkOiBuZXcgU2V0KCksXG4gICAgICAgIHVuTW91bnQ6IG5ldyBTZXQoKSxcbiAgICAgICAgYXJyYXk6IG5ldyBTZXQoKSxcbiAgICAgICAgd2F0Y2g6IG5ldyBTZXQoKSxcbiAgICB9O1xuICAgIGxldCBkZWxheUVycm9yQ2FsbGJhY2s7XG4gICAgbGV0IHRpbWVyID0gMDtcbiAgICBjb25zdCBfcHJveHlGb3JtU3RhdGUgPSB7XG4gICAgICAgIGlzRGlydHk6IGZhbHNlLFxuICAgICAgICBkaXJ0eUZpZWxkczogZmFsc2UsXG4gICAgICAgIHZhbGlkYXRpbmdGaWVsZHM6IGZhbHNlLFxuICAgICAgICB0b3VjaGVkRmllbGRzOiBmYWxzZSxcbiAgICAgICAgaXNWYWxpZGF0aW5nOiBmYWxzZSxcbiAgICAgICAgaXNWYWxpZDogZmFsc2UsXG4gICAgICAgIGVycm9yczogZmFsc2UsXG4gICAgfTtcbiAgICBsZXQgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlID0ge1xuICAgICAgICAuLi5fcHJveHlGb3JtU3RhdGUsXG4gICAgfTtcbiAgICBjb25zdCBfc3ViamVjdHMgPSB7XG4gICAgICAgIGFycmF5OiBjcmVhdGVTdWJqZWN0KCksXG4gICAgICAgIHN0YXRlOiBjcmVhdGVTdWJqZWN0KCksXG4gICAgfTtcbiAgICBjb25zdCBzaG91bGREaXNwbGF5QWxsQXNzb2NpYXRlZEVycm9ycyA9IF9vcHRpb25zLmNyaXRlcmlhTW9kZSA9PT0gVkFMSURBVElPTl9NT0RFLmFsbDtcbiAgICBjb25zdCBkZWJvdW5jZSA9IChjYWxsYmFjaykgPT4gKHdhaXQpID0+IHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KGNhbGxiYWNrLCB3YWl0KTtcbiAgICB9O1xuICAgIGNvbnN0IF9zZXRWYWxpZCA9IGFzeW5jIChzaG91bGRVcGRhdGVWYWxpZCkgPT4ge1xuICAgICAgICBpZiAoIV9vcHRpb25zLmRpc2FibGVkICYmXG4gICAgICAgICAgICAoX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWQgfHxcbiAgICAgICAgICAgICAgICBfcHJveHlTdWJzY3JpYmVGb3JtU3RhdGUuaXNWYWxpZCB8fFxuICAgICAgICAgICAgICAgIHNob3VsZFVwZGF0ZVZhbGlkKSkge1xuICAgICAgICAgICAgY29uc3QgaXNWYWxpZCA9IF9vcHRpb25zLnJlc29sdmVyXG4gICAgICAgICAgICAgICAgPyBpc0VtcHR5T2JqZWN0KChhd2FpdCBfcnVuU2NoZW1hKCkpLmVycm9ycylcbiAgICAgICAgICAgICAgICA6IGF3YWl0IGV4ZWN1dGVCdWlsdEluVmFsaWRhdGlvbihfZmllbGRzLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChpc1ZhbGlkICE9PSBfZm9ybVN0YXRlLmlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgICAgIGlzVmFsaWQsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IF91cGRhdGVJc1ZhbGlkYXRpbmcgPSAobmFtZXMsIGlzVmFsaWRhdGluZykgPT4ge1xuICAgICAgICBpZiAoIV9vcHRpb25zLmRpc2FibGVkICYmXG4gICAgICAgICAgICAoX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWRhdGluZyB8fFxuICAgICAgICAgICAgICAgIF9wcm94eUZvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzIHx8XG4gICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLmlzVmFsaWRhdGluZyB8fFxuICAgICAgICAgICAgICAgIF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzKSkge1xuICAgICAgICAgICAgKG5hbWVzIHx8IEFycmF5LmZyb20oX25hbWVzLm1vdW50KSkuZm9yRWFjaCgobmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzVmFsaWRhdGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgPyBzZXQoX2Zvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzLCBuYW1lLCBpc1ZhbGlkYXRpbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHVuc2V0KF9mb3JtU3RhdGUudmFsaWRhdGluZ0ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgdmFsaWRhdGluZ0ZpZWxkczogX2Zvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzLFxuICAgICAgICAgICAgICAgIGlzVmFsaWRhdGluZzogIWlzRW1wdHlPYmplY3QoX2Zvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBjb25zdCBfc2V0RmllbGRBcnJheSA9IChuYW1lLCB2YWx1ZXMgPSBbXSwgbWV0aG9kLCBhcmdzLCBzaG91bGRTZXRWYWx1ZXMgPSB0cnVlLCBzaG91bGRVcGRhdGVGaWVsZHNBbmRTdGF0ZSA9IHRydWUpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MgJiYgbWV0aG9kICYmICFfb3B0aW9ucy5kaXNhYmxlZCkge1xuICAgICAgICAgICAgX3N0YXRlLmFjdGlvbiA9IHRydWU7XG4gICAgICAgICAgICBpZiAoc2hvdWxkVXBkYXRlRmllbGRzQW5kU3RhdGUgJiYgQXJyYXkuaXNBcnJheShnZXQoX2ZpZWxkcywgbmFtZSkpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmllbGRWYWx1ZXMgPSBtZXRob2QoZ2V0KF9maWVsZHMsIG5hbWUpLCBhcmdzLmFyZ0EsIGFyZ3MuYXJnQik7XG4gICAgICAgICAgICAgICAgc2hvdWxkU2V0VmFsdWVzICYmIHNldChfZmllbGRzLCBuYW1lLCBmaWVsZFZhbHVlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2hvdWxkVXBkYXRlRmllbGRzQW5kU3RhdGUgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KGdldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSkpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3JzID0gbWV0aG9kKGdldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSksIGFyZ3MuYXJnQSwgYXJncy5hcmdCKTtcbiAgICAgICAgICAgICAgICBzaG91bGRTZXRWYWx1ZXMgJiYgc2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBuYW1lLCBlcnJvcnMpO1xuICAgICAgICAgICAgICAgIHVuc2V0RW1wdHlBcnJheShfZm9ybVN0YXRlLmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoKF9wcm94eUZvcm1TdGF0ZS50b3VjaGVkRmllbGRzIHx8XG4gICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMpICYmXG4gICAgICAgICAgICAgICAgc2hvdWxkVXBkYXRlRmllbGRzQW5kU3RhdGUgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KGdldChfZm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMsIG5hbWUpKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRvdWNoZWRGaWVsZHMgPSBtZXRob2QoZ2V0KF9mb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgbmFtZSksIGFyZ3MuYXJnQSwgYXJncy5hcmdCKTtcbiAgICAgICAgICAgICAgICBzaG91bGRTZXRWYWx1ZXMgJiYgc2V0KF9mb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgbmFtZSwgdG91Y2hlZEZpZWxkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3Byb3h5Rm9ybVN0YXRlLmRpcnR5RmllbGRzIHx8IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5kaXJ0eUZpZWxkcykge1xuICAgICAgICAgICAgICAgIF9mb3JtU3RhdGUuZGlydHlGaWVsZHMgPSBnZXREaXJ0eUZpZWxkcyhfZGVmYXVsdFZhbHVlcywgX2Zvcm1WYWx1ZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgaXNEaXJ0eTogX2dldERpcnR5KG5hbWUsIHZhbHVlcyksXG4gICAgICAgICAgICAgICAgZGlydHlGaWVsZHM6IF9mb3JtU3RhdGUuZGlydHlGaWVsZHMsXG4gICAgICAgICAgICAgICAgZXJyb3JzOiBfZm9ybVN0YXRlLmVycm9ycyxcbiAgICAgICAgICAgICAgICBpc1ZhbGlkOiBfZm9ybVN0YXRlLmlzVmFsaWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNldChfZm9ybVZhbHVlcywgbmFtZSwgdmFsdWVzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgdXBkYXRlRXJyb3JzID0gKG5hbWUsIGVycm9yKSA9PiB7XG4gICAgICAgIHNldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSwgZXJyb3IpO1xuICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICBlcnJvcnM6IF9mb3JtU3RhdGUuZXJyb3JzLFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IF9zZXRFcnJvcnMgPSAoZXJyb3JzKSA9PiB7XG4gICAgICAgIF9mb3JtU3RhdGUuZXJyb3JzID0gZXJyb3JzO1xuICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICBlcnJvcnM6IF9mb3JtU3RhdGUuZXJyb3JzLFxuICAgICAgICAgICAgaXNWYWxpZDogZmFsc2UsXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgY29uc3QgdXBkYXRlVmFsaWRBbmRWYWx1ZSA9IChuYW1lLCBzaG91bGRTa2lwU2V0VmFsdWVBcywgdmFsdWUsIHJlZikgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGdldChfZmllbGRzLCBuYW1lKTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSBnZXQoX2Zvcm1WYWx1ZXMsIG5hbWUsIGlzVW5kZWZpbmVkKHZhbHVlKSA/IGdldChfZGVmYXVsdFZhbHVlcywgbmFtZSkgOiB2YWx1ZSk7XG4gICAgICAgICAgICBpc1VuZGVmaW5lZChkZWZhdWx0VmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgKHJlZiAmJiByZWYuZGVmYXVsdENoZWNrZWQpIHx8XG4gICAgICAgICAgICAgICAgc2hvdWxkU2tpcFNldFZhbHVlQXNcbiAgICAgICAgICAgICAgICA/IHNldChfZm9ybVZhbHVlcywgbmFtZSwgc2hvdWxkU2tpcFNldFZhbHVlQXMgPyBkZWZhdWx0VmFsdWUgOiBnZXRGaWVsZFZhbHVlKGZpZWxkLl9mKSlcbiAgICAgICAgICAgICAgICA6IHNldEZpZWxkVmFsdWUobmFtZSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIF9zdGF0ZS5tb3VudCAmJiAhX3N0YXRlLmFjdGlvbiAmJiBfc2V0VmFsaWQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgdXBkYXRlVG91Y2hBbmREaXJ0eSA9IChuYW1lLCBmaWVsZFZhbHVlLCBpc0JsdXJFdmVudCwgc2hvdWxkRGlydHksIHNob3VsZFJlbmRlcikgPT4ge1xuICAgICAgICBsZXQgc2hvdWxkVXBkYXRlRmllbGQgPSBmYWxzZTtcbiAgICAgICAgbGV0IGlzUHJldmlvdXNEaXJ0eSA9IGZhbHNlO1xuICAgICAgICBjb25zdCBvdXRwdXQgPSB7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICB9O1xuICAgICAgICBpZiAoIV9vcHRpb25zLmRpc2FibGVkKSB7XG4gICAgICAgICAgICBpZiAoIWlzQmx1ckV2ZW50IHx8IHNob3VsZERpcnR5KSB7XG4gICAgICAgICAgICAgICAgaWYgKF9wcm94eUZvcm1TdGF0ZS5pc0RpcnR5IHx8IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5pc0RpcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlzUHJldmlvdXNEaXJ0eSA9IF9mb3JtU3RhdGUuaXNEaXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgX2Zvcm1TdGF0ZS5pc0RpcnR5ID0gb3V0cHV0LmlzRGlydHkgPSBfZ2V0RGlydHkoKTtcbiAgICAgICAgICAgICAgICAgICAgc2hvdWxkVXBkYXRlRmllbGQgPSBpc1ByZXZpb3VzRGlydHkgIT09IG91dHB1dC5pc0RpcnR5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBpc0N1cnJlbnRGaWVsZFByaXN0aW5lID0gZGVlcEVxdWFsKGdldChfZGVmYXVsdFZhbHVlcywgbmFtZSksIGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgICAgIGlzUHJldmlvdXNEaXJ0eSA9ICEhZ2V0KF9mb3JtU3RhdGUuZGlydHlGaWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgICAgIGlzQ3VycmVudEZpZWxkUHJpc3RpbmVcbiAgICAgICAgICAgICAgICAgICAgPyB1bnNldChfZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBuYW1lKVxuICAgICAgICAgICAgICAgICAgICA6IHNldChfZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBuYW1lLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBvdXRwdXQuZGlydHlGaWVsZHMgPSBfZm9ybVN0YXRlLmRpcnR5RmllbGRzO1xuICAgICAgICAgICAgICAgIHNob3VsZFVwZGF0ZUZpZWxkID1cbiAgICAgICAgICAgICAgICAgICAgc2hvdWxkVXBkYXRlRmllbGQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICgoX3Byb3h5Rm9ybVN0YXRlLmRpcnR5RmllbGRzIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLmRpcnR5RmllbGRzKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJldmlvdXNEaXJ0eSAhPT0gIWlzQ3VycmVudEZpZWxkUHJpc3RpbmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzQmx1ckV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNQcmV2aW91c0ZpZWxkVG91Y2hlZCA9IGdldChfZm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgICAgIGlmICghaXNQcmV2aW91c0ZpZWxkVG91Y2hlZCkge1xuICAgICAgICAgICAgICAgICAgICBzZXQoX2Zvcm1TdGF0ZS50b3VjaGVkRmllbGRzLCBuYW1lLCBpc0JsdXJFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dC50b3VjaGVkRmllbGRzID0gX2Zvcm1TdGF0ZS50b3VjaGVkRmllbGRzO1xuICAgICAgICAgICAgICAgICAgICBzaG91bGRVcGRhdGVGaWVsZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBzaG91bGRVcGRhdGVGaWVsZCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICgoX3Byb3h5Rm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJldmlvdXNGaWVsZFRvdWNoZWQgIT09IGlzQmx1ckV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaG91bGRVcGRhdGVGaWVsZCAmJiBzaG91bGRSZW5kZXIgJiYgX3N1YmplY3RzLnN0YXRlLm5leHQob3V0cHV0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2hvdWxkVXBkYXRlRmllbGQgPyBvdXRwdXQgOiB7fTtcbiAgICB9O1xuICAgIGNvbnN0IHNob3VsZFJlbmRlckJ5RXJyb3IgPSAobmFtZSwgaXNWYWxpZCwgZXJyb3IsIGZpZWxkU3RhdGUpID0+IHtcbiAgICAgICAgY29uc3QgcHJldmlvdXNGaWVsZEVycm9yID0gZ2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBuYW1lKTtcbiAgICAgICAgY29uc3Qgc2hvdWxkVXBkYXRlVmFsaWQgPSAoX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWQgfHwgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLmlzVmFsaWQpICYmXG4gICAgICAgICAgICBpc0Jvb2xlYW4oaXNWYWxpZCkgJiZcbiAgICAgICAgICAgIF9mb3JtU3RhdGUuaXNWYWxpZCAhPT0gaXNWYWxpZDtcbiAgICAgICAgaWYgKF9vcHRpb25zLmRlbGF5RXJyb3IgJiYgZXJyb3IpIHtcbiAgICAgICAgICAgIGRlbGF5RXJyb3JDYWxsYmFjayA9IGRlYm91bmNlKCgpID0+IHVwZGF0ZUVycm9ycyhuYW1lLCBlcnJvcikpO1xuICAgICAgICAgICAgZGVsYXlFcnJvckNhbGxiYWNrKF9vcHRpb25zLmRlbGF5RXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgIGRlbGF5RXJyb3JDYWxsYmFjayA9IG51bGw7XG4gICAgICAgICAgICBlcnJvclxuICAgICAgICAgICAgICAgID8gc2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBuYW1lLCBlcnJvcilcbiAgICAgICAgICAgICAgICA6IHVuc2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBuYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKGVycm9yID8gIWRlZXBFcXVhbChwcmV2aW91c0ZpZWxkRXJyb3IsIGVycm9yKSA6IHByZXZpb3VzRmllbGRFcnJvcikgfHxcbiAgICAgICAgICAgICFpc0VtcHR5T2JqZWN0KGZpZWxkU3RhdGUpIHx8XG4gICAgICAgICAgICBzaG91bGRVcGRhdGVWYWxpZCkge1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlZEZvcm1TdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICAuLi5maWVsZFN0YXRlLFxuICAgICAgICAgICAgICAgIC4uLihzaG91bGRVcGRhdGVWYWxpZCAmJiBpc0Jvb2xlYW4oaXNWYWxpZCkgPyB7IGlzVmFsaWQgfSA6IHt9KSxcbiAgICAgICAgICAgICAgICBlcnJvcnM6IF9mb3JtU3RhdGUuZXJyb3JzLFxuICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgX2Zvcm1TdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICAuLi5fZm9ybVN0YXRlLFxuICAgICAgICAgICAgICAgIC4uLnVwZGF0ZWRGb3JtU3RhdGUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQodXBkYXRlZEZvcm1TdGF0ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IF9ydW5TY2hlbWEgPSBhc3luYyAobmFtZSkgPT4ge1xuICAgICAgICBfdXBkYXRlSXNWYWxpZGF0aW5nKG5hbWUsIHRydWUpO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBfb3B0aW9ucy5yZXNvbHZlcihfZm9ybVZhbHVlcywgX29wdGlvbnMuY29udGV4dCwgZ2V0UmVzb2x2ZXJPcHRpb25zKG5hbWUgfHwgX25hbWVzLm1vdW50LCBfZmllbGRzLCBfb3B0aW9ucy5jcml0ZXJpYU1vZGUsIF9vcHRpb25zLnNob3VsZFVzZU5hdGl2ZVZhbGlkYXRpb24pKTtcbiAgICAgICAgX3VwZGF0ZUlzVmFsaWRhdGluZyhuYW1lKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIGNvbnN0IGV4ZWN1dGVTY2hlbWFBbmRVcGRhdGVTdGF0ZSA9IGFzeW5jIChuYW1lcykgPT4ge1xuICAgICAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgX3J1blNjaGVtYShuYW1lcyk7XG4gICAgICAgIGlmIChuYW1lcykge1xuICAgICAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBnZXQoZXJyb3JzLCBuYW1lKTtcbiAgICAgICAgICAgICAgICBlcnJvclxuICAgICAgICAgICAgICAgICAgICA/IHNldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSwgZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgIDogdW5zZXQoX2Zvcm1TdGF0ZS5lcnJvcnMsIG5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgX2Zvcm1TdGF0ZS5lcnJvcnMgPSBlcnJvcnM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVycm9ycztcbiAgICB9O1xuICAgIGNvbnN0IGV4ZWN1dGVCdWlsdEluVmFsaWRhdGlvbiA9IGFzeW5jIChmaWVsZHMsIHNob3VsZE9ubHlDaGVja1ZhbGlkLCBjb250ZXh0ID0ge1xuICAgICAgICB2YWxpZDogdHJ1ZSxcbiAgICB9KSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBmaWVsZHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZmllbGRzW25hbWVdO1xuICAgICAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBfZiwgLi4uZmllbGRWYWx1ZSB9ID0gZmllbGQ7XG4gICAgICAgICAgICAgICAgaWYgKF9mKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzRmllbGRBcnJheVJvb3QgPSBfbmFtZXMuYXJyYXkuaGFzKF9mLm5hbWUpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpc1Byb21pc2VGdW5jdGlvbiA9IGZpZWxkLl9mICYmIGhhc1Byb21pc2VWYWxpZGF0aW9uKGZpZWxkLl9mKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzUHJvbWlzZUZ1bmN0aW9uICYmIF9wcm94eUZvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdXBkYXRlSXNWYWxpZGF0aW5nKFtfZi5uYW1lXSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmllbGRFcnJvciA9IGF3YWl0IHZhbGlkYXRlRmllbGQoZmllbGQsIF9uYW1lcy5kaXNhYmxlZCwgX2Zvcm1WYWx1ZXMsIHNob3VsZERpc3BsYXlBbGxBc3NvY2lhdGVkRXJyb3JzLCBfb3B0aW9ucy5zaG91bGRVc2VOYXRpdmVWYWxpZGF0aW9uICYmICFzaG91bGRPbmx5Q2hlY2tWYWxpZCwgaXNGaWVsZEFycmF5Um9vdCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1Byb21pc2VGdW5jdGlvbiAmJiBfcHJveHlGb3JtU3RhdGUudmFsaWRhdGluZ0ZpZWxkcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3VwZGF0ZUlzVmFsaWRhdGluZyhbX2YubmFtZV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWVsZEVycm9yW19mLm5hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkT25seUNoZWNrVmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAhc2hvdWxkT25seUNoZWNrVmFsaWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChnZXQoZmllbGRFcnJvciwgX2YubmFtZSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGlzRmllbGRBcnJheVJvb3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB1cGRhdGVGaWVsZEFycmF5Um9vdEVycm9yKF9mb3JtU3RhdGUuZXJyb3JzLCBmaWVsZEVycm9yLCBfZi5uYW1lKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHNldChfZm9ybVN0YXRlLmVycm9ycywgX2YubmFtZSwgZmllbGRFcnJvcltfZi5uYW1lXSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHVuc2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBfZi5uYW1lKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICFpc0VtcHR5T2JqZWN0KGZpZWxkVmFsdWUpICYmXG4gICAgICAgICAgICAgICAgICAgIChhd2FpdCBleGVjdXRlQnVpbHRJblZhbGlkYXRpb24oZmllbGRWYWx1ZSwgc2hvdWxkT25seUNoZWNrVmFsaWQsIGNvbnRleHQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29udGV4dC52YWxpZDtcbiAgICB9O1xuICAgIGNvbnN0IF9yZW1vdmVVbm1vdW50ZWQgPSAoKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBfbmFtZXMudW5Nb3VudCkge1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICBmaWVsZCAmJlxuICAgICAgICAgICAgICAgIChmaWVsZC5fZi5yZWZzXG4gICAgICAgICAgICAgICAgICAgID8gZmllbGQuX2YucmVmcy5ldmVyeSgocmVmKSA9PiAhbGl2ZShyZWYpKVxuICAgICAgICAgICAgICAgICAgICA6ICFsaXZlKGZpZWxkLl9mLnJlZikpICYmXG4gICAgICAgICAgICAgICAgdW5yZWdpc3RlcihuYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBfbmFtZXMudW5Nb3VudCA9IG5ldyBTZXQoKTtcbiAgICB9O1xuICAgIGNvbnN0IF9nZXREaXJ0eSA9IChuYW1lLCBkYXRhKSA9PiAhX29wdGlvbnMuZGlzYWJsZWQgJiZcbiAgICAgICAgKG5hbWUgJiYgZGF0YSAmJiBzZXQoX2Zvcm1WYWx1ZXMsIG5hbWUsIGRhdGEpLFxuICAgICAgICAgICAgIWRlZXBFcXVhbChnZXRWYWx1ZXMoKSwgX2RlZmF1bHRWYWx1ZXMpKTtcbiAgICBjb25zdCBfZ2V0V2F0Y2ggPSAobmFtZXMsIGRlZmF1bHRWYWx1ZSwgaXNHbG9iYWwpID0+IGdlbmVyYXRlV2F0Y2hPdXRwdXQobmFtZXMsIF9uYW1lcywge1xuICAgICAgICAuLi4oX3N0YXRlLm1vdW50XG4gICAgICAgICAgICA/IF9mb3JtVmFsdWVzXG4gICAgICAgICAgICA6IGlzVW5kZWZpbmVkKGRlZmF1bHRWYWx1ZSlcbiAgICAgICAgICAgICAgICA/IF9kZWZhdWx0VmFsdWVzXG4gICAgICAgICAgICAgICAgOiBpc1N0cmluZyhuYW1lcylcbiAgICAgICAgICAgICAgICAgICAgPyB7IFtuYW1lc106IGRlZmF1bHRWYWx1ZSB9XG4gICAgICAgICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlKSxcbiAgICB9LCBpc0dsb2JhbCwgZGVmYXVsdFZhbHVlKTtcbiAgICBjb25zdCBfZ2V0RmllbGRBcnJheSA9IChuYW1lKSA9PiBjb21wYWN0KGdldChfc3RhdGUubW91bnQgPyBfZm9ybVZhbHVlcyA6IF9kZWZhdWx0VmFsdWVzLCBuYW1lLCBfb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyID8gZ2V0KF9kZWZhdWx0VmFsdWVzLCBuYW1lLCBbXSkgOiBbXSkpO1xuICAgIGNvbnN0IHNldEZpZWxkVmFsdWUgPSAobmFtZSwgdmFsdWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGdldChfZmllbGRzLCBuYW1lKTtcbiAgICAgICAgbGV0IGZpZWxkVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCBmaWVsZFJlZmVyZW5jZSA9IGZpZWxkLl9mO1xuICAgICAgICAgICAgaWYgKGZpZWxkUmVmZXJlbmNlKSB7XG4gICAgICAgICAgICAgICAgIWZpZWxkUmVmZXJlbmNlLmRpc2FibGVkICYmXG4gICAgICAgICAgICAgICAgICAgIHNldChfZm9ybVZhbHVlcywgbmFtZSwgZ2V0RmllbGRWYWx1ZUFzKHZhbHVlLCBmaWVsZFJlZmVyZW5jZSkpO1xuICAgICAgICAgICAgICAgIGZpZWxkVmFsdWUgPVxuICAgICAgICAgICAgICAgICAgICBpc0hUTUxFbGVtZW50KGZpZWxkUmVmZXJlbmNlLnJlZikgJiYgaXNOdWxsT3JVbmRlZmluZWQodmFsdWUpXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICcnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChpc011bHRpcGxlU2VsZWN0KGZpZWxkUmVmZXJlbmNlLnJlZikpIHtcbiAgICAgICAgICAgICAgICAgICAgWy4uLmZpZWxkUmVmZXJlbmNlLnJlZi5vcHRpb25zXS5mb3JFYWNoKChvcHRpb25SZWYpID0+IChvcHRpb25SZWYuc2VsZWN0ZWQgPSBmaWVsZFZhbHVlLmluY2x1ZGVzKG9wdGlvblJlZi52YWx1ZSkpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZmllbGRSZWZlcmVuY2UucmVmcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNDaGVja0JveElucHV0KGZpZWxkUmVmZXJlbmNlLnJlZikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkUmVmZXJlbmNlLnJlZnMuZm9yRWFjaCgoY2hlY2tib3hSZWYpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNoZWNrYm94UmVmLmRlZmF1bHRDaGVja2VkIHx8ICFjaGVja2JveFJlZi5kaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShmaWVsZFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tib3hSZWYuY2hlY2tlZCA9ICEhZmllbGRWYWx1ZS5maW5kKChkYXRhKSA9PiBkYXRhID09PSBjaGVja2JveFJlZi52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja2JveFJlZi5jaGVja2VkID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZFZhbHVlID09PSBjaGVja2JveFJlZi52YWx1ZSB8fCAhIWZpZWxkVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkUmVmZXJlbmNlLnJlZnMuZm9yRWFjaCgocmFkaW9SZWYpID0+IChyYWRpb1JlZi5jaGVja2VkID0gcmFkaW9SZWYudmFsdWUgPT09IGZpZWxkVmFsdWUpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChpc0ZpbGVJbnB1dChmaWVsZFJlZmVyZW5jZS5yZWYpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkUmVmZXJlbmNlLnJlZi52YWx1ZSA9ICcnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZmllbGRSZWZlcmVuY2UucmVmLnZhbHVlID0gZmllbGRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmaWVsZFJlZmVyZW5jZS5yZWYudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzOiBjbG9uZU9iamVjdChfZm9ybVZhbHVlcyksXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAob3B0aW9ucy5zaG91bGREaXJ0eSB8fCBvcHRpb25zLnNob3VsZFRvdWNoKSAmJlxuICAgICAgICAgICAgdXBkYXRlVG91Y2hBbmREaXJ0eShuYW1lLCBmaWVsZFZhbHVlLCBvcHRpb25zLnNob3VsZFRvdWNoLCBvcHRpb25zLnNob3VsZERpcnR5LCB0cnVlKTtcbiAgICAgICAgb3B0aW9ucy5zaG91bGRWYWxpZGF0ZSAmJiB0cmlnZ2VyKG5hbWUpO1xuICAgIH07XG4gICAgY29uc3Qgc2V0VmFsdWVzID0gKG5hbWUsIHZhbHVlLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgZmllbGRLZXkgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgIGlmICghdmFsdWUuaGFzT3duUHJvcGVydHkoZmllbGRLZXkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZmllbGRWYWx1ZSA9IHZhbHVlW2ZpZWxkS2V5XTtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IG5hbWUgKyAnLicgKyBmaWVsZEtleTtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KF9maWVsZHMsIGZpZWxkTmFtZSk7XG4gICAgICAgICAgICAoX25hbWVzLmFycmF5LmhhcyhuYW1lKSB8fFxuICAgICAgICAgICAgICAgIGlzT2JqZWN0KGZpZWxkVmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgKGZpZWxkICYmICFmaWVsZC5fZikpICYmXG4gICAgICAgICAgICAgICAgIWlzRGF0ZU9iamVjdChmaWVsZFZhbHVlKVxuICAgICAgICAgICAgICAgID8gc2V0VmFsdWVzKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICA6IHNldEZpZWxkVmFsdWUoZmllbGROYW1lLCBmaWVsZFZhbHVlLCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3Qgc2V0VmFsdWUgPSAobmFtZSwgdmFsdWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGdldChfZmllbGRzLCBuYW1lKTtcbiAgICAgICAgY29uc3QgaXNGaWVsZEFycmF5ID0gX25hbWVzLmFycmF5LmhhcyhuYW1lKTtcbiAgICAgICAgY29uc3QgY2xvbmVWYWx1ZSA9IGNsb25lT2JqZWN0KHZhbHVlKTtcbiAgICAgICAgc2V0KF9mb3JtVmFsdWVzLCBuYW1lLCBjbG9uZVZhbHVlKTtcbiAgICAgICAgaWYgKGlzRmllbGRBcnJheSkge1xuICAgICAgICAgICAgX3N1YmplY3RzLmFycmF5Lm5leHQoe1xuICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgdmFsdWVzOiBjbG9uZU9iamVjdChfZm9ybVZhbHVlcyksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICgoX3Byb3h5Rm9ybVN0YXRlLmlzRGlydHkgfHxcbiAgICAgICAgICAgICAgICBfcHJveHlGb3JtU3RhdGUuZGlydHlGaWVsZHMgfHxcbiAgICAgICAgICAgICAgICBfcHJveHlTdWJzY3JpYmVGb3JtU3RhdGUuaXNEaXJ0eSB8fFxuICAgICAgICAgICAgICAgIF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5kaXJ0eUZpZWxkcykgJiZcbiAgICAgICAgICAgICAgICBvcHRpb25zLnNob3VsZERpcnR5KSB7XG4gICAgICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgICAgICBkaXJ0eUZpZWxkczogZ2V0RGlydHlGaWVsZHMoX2RlZmF1bHRWYWx1ZXMsIF9mb3JtVmFsdWVzKSxcbiAgICAgICAgICAgICAgICAgICAgaXNEaXJ0eTogX2dldERpcnR5KG5hbWUsIGNsb25lVmFsdWUpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZmllbGQgJiYgIWZpZWxkLl9mICYmICFpc051bGxPclVuZGVmaW5lZChjbG9uZVZhbHVlKVxuICAgICAgICAgICAgICAgID8gc2V0VmFsdWVzKG5hbWUsIGNsb25lVmFsdWUsIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgOiBzZXRGaWVsZFZhbHVlKG5hbWUsIGNsb25lVmFsdWUsIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGlzV2F0Y2hlZChuYW1lLCBfbmFtZXMpICYmIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHsgLi4uX2Zvcm1TdGF0ZSwgbmFtZSB9KTtcbiAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgbmFtZTogX3N0YXRlLm1vdW50ID8gbmFtZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHZhbHVlczogY2xvbmVPYmplY3QoX2Zvcm1WYWx1ZXMpLFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IG9uQ2hhbmdlID0gYXN5bmMgKGV2ZW50KSA9PiB7XG4gICAgICAgIF9zdGF0ZS5tb3VudCA9IHRydWU7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcbiAgICAgICAgbGV0IG5hbWUgPSB0YXJnZXQubmFtZTtcbiAgICAgICAgbGV0IGlzRmllbGRWYWx1ZVVwZGF0ZWQgPSB0cnVlO1xuICAgICAgICBjb25zdCBmaWVsZCA9IGdldChfZmllbGRzLCBuYW1lKTtcbiAgICAgICAgY29uc3QgX3VwZGF0ZUlzRmllbGRWYWx1ZVVwZGF0ZWQgPSAoZmllbGRWYWx1ZSkgPT4ge1xuICAgICAgICAgICAgaXNGaWVsZFZhbHVlVXBkYXRlZCA9XG4gICAgICAgICAgICAgICAgTnVtYmVyLmlzTmFOKGZpZWxkVmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgICAgIChpc0RhdGVPYmplY3QoZmllbGRWYWx1ZSkgJiYgaXNOYU4oZmllbGRWYWx1ZS5nZXRUaW1lKCkpKSB8fFxuICAgICAgICAgICAgICAgICAgICBkZWVwRXF1YWwoZmllbGRWYWx1ZSwgZ2V0KF9mb3JtVmFsdWVzLCBuYW1lLCBmaWVsZFZhbHVlKSk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb25Nb2RlQmVmb3JlU3VibWl0ID0gZ2V0VmFsaWRhdGlvbk1vZGVzKF9vcHRpb25zLm1vZGUpO1xuICAgICAgICBjb25zdCB2YWxpZGF0aW9uTW9kZUFmdGVyU3VibWl0ID0gZ2V0VmFsaWRhdGlvbk1vZGVzKF9vcHRpb25zLnJlVmFsaWRhdGVNb2RlKTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBsZXQgZXJyb3I7XG4gICAgICAgICAgICBsZXQgaXNWYWxpZDtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkVmFsdWUgPSB0YXJnZXQudHlwZVxuICAgICAgICAgICAgICAgID8gZ2V0RmllbGRWYWx1ZShmaWVsZC5fZilcbiAgICAgICAgICAgICAgICA6IGdldEV2ZW50VmFsdWUoZXZlbnQpO1xuICAgICAgICAgICAgY29uc3QgaXNCbHVyRXZlbnQgPSBldmVudC50eXBlID09PSBFVkVOVFMuQkxVUiB8fCBldmVudC50eXBlID09PSBFVkVOVFMuRk9DVVNfT1VUO1xuICAgICAgICAgICAgY29uc3Qgc2hvdWxkU2tpcFZhbGlkYXRpb24gPSAoIWhhc1ZhbGlkYXRpb24oZmllbGQuX2YpICYmXG4gICAgICAgICAgICAgICAgIV9vcHRpb25zLnJlc29sdmVyICYmXG4gICAgICAgICAgICAgICAgIWdldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSkgJiZcbiAgICAgICAgICAgICAgICAhZmllbGQuX2YuZGVwcykgfHxcbiAgICAgICAgICAgICAgICBza2lwVmFsaWRhdGlvbihpc0JsdXJFdmVudCwgZ2V0KF9mb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgbmFtZSksIF9mb3JtU3RhdGUuaXNTdWJtaXR0ZWQsIHZhbGlkYXRpb25Nb2RlQWZ0ZXJTdWJtaXQsIHZhbGlkYXRpb25Nb2RlQmVmb3JlU3VibWl0KTtcbiAgICAgICAgICAgIGNvbnN0IHdhdGNoZWQgPSBpc1dhdGNoZWQobmFtZSwgX25hbWVzLCBpc0JsdXJFdmVudCk7XG4gICAgICAgICAgICBzZXQoX2Zvcm1WYWx1ZXMsIG5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgaWYgKGlzQmx1ckV2ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YXJnZXQgfHwgIXRhcmdldC5yZWFkT25seSkge1xuICAgICAgICAgICAgICAgICAgICBmaWVsZC5fZi5vbkJsdXIgJiYgZmllbGQuX2Yub25CbHVyKGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgZGVsYXlFcnJvckNhbGxiYWNrICYmIGRlbGF5RXJyb3JDYWxsYmFjaygwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChmaWVsZC5fZi5vbkNoYW5nZSkge1xuICAgICAgICAgICAgICAgIGZpZWxkLl9mLm9uQ2hhbmdlKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGZpZWxkU3RhdGUgPSB1cGRhdGVUb3VjaEFuZERpcnR5KG5hbWUsIGZpZWxkVmFsdWUsIGlzQmx1ckV2ZW50KTtcbiAgICAgICAgICAgIGNvbnN0IHNob3VsZFJlbmRlciA9ICFpc0VtcHR5T2JqZWN0KGZpZWxkU3RhdGUpIHx8IHdhdGNoZWQ7XG4gICAgICAgICAgICAhaXNCbHVyRXZlbnQgJiZcbiAgICAgICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IGV2ZW50LnR5cGUsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlczogY2xvbmVPYmplY3QoX2Zvcm1WYWx1ZXMpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHNob3VsZFNraXBWYWxpZGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9wcm94eUZvcm1TdGF0ZS5pc1ZhbGlkIHx8IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5pc1ZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfb3B0aW9ucy5tb2RlID09PSAnb25CbHVyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzQmx1ckV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3NldFZhbGlkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWlzQmx1ckV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfc2V0VmFsaWQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gKHNob3VsZFJlbmRlciAmJlxuICAgICAgICAgICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7IG5hbWUsIC4uLih3YXRjaGVkID8ge30gOiBmaWVsZFN0YXRlKSB9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAhaXNCbHVyRXZlbnQgJiYgd2F0Y2hlZCAmJiBfc3ViamVjdHMuc3RhdGUubmV4dCh7IC4uLl9mb3JtU3RhdGUgfSk7XG4gICAgICAgICAgICBpZiAoX29wdGlvbnMucmVzb2x2ZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgX3J1blNjaGVtYShbbmFtZV0pO1xuICAgICAgICAgICAgICAgIF91cGRhdGVJc0ZpZWxkVmFsdWVVcGRhdGVkKGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgICAgIGlmIChpc0ZpZWxkVmFsdWVVcGRhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzRXJyb3JMb29rdXBSZXN1bHQgPSBzY2hlbWFFcnJvckxvb2t1cChfZm9ybVN0YXRlLmVycm9ycywgX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTG9va3VwUmVzdWx0ID0gc2NoZW1hRXJyb3JMb29rdXAoZXJyb3JzLCBfZmllbGRzLCBwcmV2aW91c0Vycm9yTG9va3VwUmVzdWx0Lm5hbWUgfHwgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gZXJyb3JMb29rdXBSZXN1bHQuZXJyb3I7XG4gICAgICAgICAgICAgICAgICAgIG5hbWUgPSBlcnJvckxvb2t1cFJlc3VsdC5uYW1lO1xuICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkID0gaXNFbXB0eU9iamVjdChlcnJvcnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIF91cGRhdGVJc1ZhbGlkYXRpbmcoW25hbWVdLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBlcnJvciA9IChhd2FpdCB2YWxpZGF0ZUZpZWxkKGZpZWxkLCBfbmFtZXMuZGlzYWJsZWQsIF9mb3JtVmFsdWVzLCBzaG91bGREaXNwbGF5QWxsQXNzb2NpYXRlZEVycm9ycywgX29wdGlvbnMuc2hvdWxkVXNlTmF0aXZlVmFsaWRhdGlvbikpW25hbWVdO1xuICAgICAgICAgICAgICAgIF91cGRhdGVJc1ZhbGlkYXRpbmcoW25hbWVdKTtcbiAgICAgICAgICAgICAgICBfdXBkYXRlSXNGaWVsZFZhbHVlVXBkYXRlZChmaWVsZFZhbHVlKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNGaWVsZFZhbHVlVXBkYXRlZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChfcHJveHlGb3JtU3RhdGUuaXNWYWxpZCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLmlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSBhd2FpdCBleGVjdXRlQnVpbHRJblZhbGlkYXRpb24oX2ZpZWxkcywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNGaWVsZFZhbHVlVXBkYXRlZCkge1xuICAgICAgICAgICAgICAgIGZpZWxkLl9mLmRlcHMgJiZcbiAgICAgICAgICAgICAgICAgICAgKCFBcnJheS5pc0FycmF5KGZpZWxkLl9mLmRlcHMpIHx8IGZpZWxkLl9mLmRlcHMubGVuZ3RoID4gMCkgJiZcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlcihmaWVsZC5fZi5kZXBzKTtcbiAgICAgICAgICAgICAgICBzaG91bGRSZW5kZXJCeUVycm9yKG5hbWUsIGlzVmFsaWQsIGVycm9yLCBmaWVsZFN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgX2ZvY3VzSW5wdXQgPSAocmVmLCBrZXkpID0+IHtcbiAgICAgICAgaWYgKGdldChfZm9ybVN0YXRlLmVycm9ycywga2V5KSAmJiByZWYuZm9jdXMpIHtcbiAgICAgICAgICAgIHJlZi5mb2N1cygpO1xuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH07XG4gICAgY29uc3QgdHJpZ2dlciA9IGFzeW5jIChuYW1lLCBvcHRpb25zID0ge30pID0+IHtcbiAgICAgICAgbGV0IGlzVmFsaWQ7XG4gICAgICAgIGxldCB2YWxpZGF0aW9uUmVzdWx0O1xuICAgICAgICBjb25zdCBmaWVsZE5hbWVzID0gY29udmVydFRvQXJyYXlQYXlsb2FkKG5hbWUpO1xuICAgICAgICBpZiAoX29wdGlvbnMucmVzb2x2ZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IGV4ZWN1dGVTY2hlbWFBbmRVcGRhdGVTdGF0ZShpc1VuZGVmaW5lZChuYW1lKSA/IG5hbWUgOiBmaWVsZE5hbWVzKTtcbiAgICAgICAgICAgIGlzVmFsaWQgPSBpc0VtcHR5T2JqZWN0KGVycm9ycyk7XG4gICAgICAgICAgICB2YWxpZGF0aW9uUmVzdWx0ID0gbmFtZVxuICAgICAgICAgICAgICAgID8gIWZpZWxkTmFtZXMuc29tZSgobmFtZSkgPT4gZ2V0KGVycm9ycywgbmFtZSkpXG4gICAgICAgICAgICAgICAgOiBpc1ZhbGlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG5hbWUpIHtcbiAgICAgICAgICAgIHZhbGlkYXRpb25SZXN1bHQgPSAoYXdhaXQgUHJvbWlzZS5hbGwoZmllbGROYW1lcy5tYXAoYXN5bmMgKGZpZWxkTmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KF9maWVsZHMsIGZpZWxkTmFtZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGV4ZWN1dGVCdWlsdEluVmFsaWRhdGlvbihmaWVsZCAmJiBmaWVsZC5fZiA/IHsgW2ZpZWxkTmFtZV06IGZpZWxkIH0gOiBmaWVsZCk7XG4gICAgICAgICAgICB9KSkpLmV2ZXJ5KEJvb2xlYW4pO1xuICAgICAgICAgICAgISghdmFsaWRhdGlvblJlc3VsdCAmJiAhX2Zvcm1TdGF0ZS5pc1ZhbGlkKSAmJiBfc2V0VmFsaWQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhbGlkYXRpb25SZXN1bHQgPSBpc1ZhbGlkID0gYXdhaXQgZXhlY3V0ZUJ1aWx0SW5WYWxpZGF0aW9uKF9maWVsZHMpO1xuICAgICAgICB9XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIC4uLighaXNTdHJpbmcobmFtZSkgfHxcbiAgICAgICAgICAgICAgICAoKF9wcm94eUZvcm1TdGF0ZS5pc1ZhbGlkIHx8IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5pc1ZhbGlkKSAmJlxuICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkICE9PSBfZm9ybVN0YXRlLmlzVmFsaWQpXG4gICAgICAgICAgICAgICAgPyB7fVxuICAgICAgICAgICAgICAgIDogeyBuYW1lIH0pLFxuICAgICAgICAgICAgLi4uKF9vcHRpb25zLnJlc29sdmVyIHx8ICFuYW1lID8geyBpc1ZhbGlkIH0gOiB7fSksXG4gICAgICAgICAgICBlcnJvcnM6IF9mb3JtU3RhdGUuZXJyb3JzLFxuICAgICAgICB9KTtcbiAgICAgICAgb3B0aW9ucy5zaG91bGRGb2N1cyAmJlxuICAgICAgICAgICAgIXZhbGlkYXRpb25SZXN1bHQgJiZcbiAgICAgICAgICAgIGl0ZXJhdGVGaWVsZHNCeUFjdGlvbihfZmllbGRzLCBfZm9jdXNJbnB1dCwgbmFtZSA/IGZpZWxkTmFtZXMgOiBfbmFtZXMubW91bnQpO1xuICAgICAgICByZXR1cm4gdmFsaWRhdGlvblJlc3VsdDtcbiAgICB9O1xuICAgIGNvbnN0IGdldFZhbHVlcyA9IChmaWVsZE5hbWVzLCBjb25maWcpID0+IHtcbiAgICAgICAgbGV0IHZhbHVlcyA9IHtcbiAgICAgICAgICAgIC4uLihfc3RhdGUubW91bnQgPyBfZm9ybVZhbHVlcyA6IF9kZWZhdWx0VmFsdWVzKSxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGNvbmZpZykge1xuICAgICAgICAgICAgdmFsdWVzID0gZXh0cmFjdEZvcm1WYWx1ZXMoY29uZmlnLmRpcnR5RmllbGRzID8gX2Zvcm1TdGF0ZS5kaXJ0eUZpZWxkcyA6IF9mb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgdmFsdWVzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNVbmRlZmluZWQoZmllbGROYW1lcylcbiAgICAgICAgICAgID8gdmFsdWVzXG4gICAgICAgICAgICA6IGlzU3RyaW5nKGZpZWxkTmFtZXMpXG4gICAgICAgICAgICAgICAgPyBnZXQodmFsdWVzLCBmaWVsZE5hbWVzKVxuICAgICAgICAgICAgICAgIDogZmllbGROYW1lcy5tYXAoKG5hbWUpID0+IGdldCh2YWx1ZXMsIG5hbWUpKTtcbiAgICB9O1xuICAgIGNvbnN0IGdldEZpZWxkU3RhdGUgPSAobmFtZSwgZm9ybVN0YXRlKSA9PiAoe1xuICAgICAgICBpbnZhbGlkOiAhIWdldCgoZm9ybVN0YXRlIHx8IF9mb3JtU3RhdGUpLmVycm9ycywgbmFtZSksXG4gICAgICAgIGlzRGlydHk6ICEhZ2V0KChmb3JtU3RhdGUgfHwgX2Zvcm1TdGF0ZSkuZGlydHlGaWVsZHMsIG5hbWUpLFxuICAgICAgICBlcnJvcjogZ2V0KChmb3JtU3RhdGUgfHwgX2Zvcm1TdGF0ZSkuZXJyb3JzLCBuYW1lKSxcbiAgICAgICAgaXNWYWxpZGF0aW5nOiAhIWdldChfZm9ybVN0YXRlLnZhbGlkYXRpbmdGaWVsZHMsIG5hbWUpLFxuICAgICAgICBpc1RvdWNoZWQ6ICEhZ2V0KChmb3JtU3RhdGUgfHwgX2Zvcm1TdGF0ZSkudG91Y2hlZEZpZWxkcywgbmFtZSksXG4gICAgfSk7XG4gICAgY29uc3QgY2xlYXJFcnJvcnMgPSAobmFtZSkgPT4ge1xuICAgICAgICBuYW1lICYmXG4gICAgICAgICAgICBjb252ZXJ0VG9BcnJheVBheWxvYWQobmFtZSkuZm9yRWFjaCgoaW5wdXROYW1lKSA9PiB1bnNldChfZm9ybVN0YXRlLmVycm9ycywgaW5wdXROYW1lKSk7XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIGVycm9yczogbmFtZSA/IF9mb3JtU3RhdGUuZXJyb3JzIDoge30sXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgY29uc3Qgc2V0RXJyb3IgPSAobmFtZSwgZXJyb3IsIG9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgcmVmID0gKGdldChfZmllbGRzLCBuYW1lLCB7IF9mOiB7fSB9KS5fZiB8fCB7fSkucmVmO1xuICAgICAgICBjb25zdCBjdXJyZW50RXJyb3IgPSBnZXQoX2Zvcm1TdGF0ZS5lcnJvcnMsIG5hbWUpIHx8IHt9O1xuICAgICAgICAvLyBEb24ndCBvdmVycmlkZSBleGlzdGluZyBlcnJvciBtZXNzYWdlcyBlbHNld2hlcmUgaW4gdGhlIG9iamVjdCB0cmVlLlxuICAgICAgICBjb25zdCB7IHJlZjogY3VycmVudFJlZiwgbWVzc2FnZSwgdHlwZSwgLi4ucmVzdE9mRXJyb3JUcmVlIH0gPSBjdXJyZW50RXJyb3I7XG4gICAgICAgIHNldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSwge1xuICAgICAgICAgICAgLi4ucmVzdE9mRXJyb3JUcmVlLFxuICAgICAgICAgICAgLi4uZXJyb3IsXG4gICAgICAgICAgICByZWYsXG4gICAgICAgIH0pO1xuICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgZXJyb3JzOiBfZm9ybVN0YXRlLmVycm9ycyxcbiAgICAgICAgICAgIGlzVmFsaWQ6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgICAgb3B0aW9ucyAmJiBvcHRpb25zLnNob3VsZEZvY3VzICYmIHJlZiAmJiByZWYuZm9jdXMgJiYgcmVmLmZvY3VzKCk7XG4gICAgfTtcbiAgICBjb25zdCB3YXRjaCA9IChuYW1lLCBkZWZhdWx0VmFsdWUpID0+IGlzRnVuY3Rpb24obmFtZSlcbiAgICAgICAgPyBfc3ViamVjdHMuc3RhdGUuc3Vic2NyaWJlKHtcbiAgICAgICAgICAgIG5leHQ6IChwYXlsb2FkKSA9PiAndmFsdWVzJyBpbiBwYXlsb2FkICYmXG4gICAgICAgICAgICAgICAgbmFtZShfZ2V0V2F0Y2godW5kZWZpbmVkLCBkZWZhdWx0VmFsdWUpLCBwYXlsb2FkKSxcbiAgICAgICAgfSlcbiAgICAgICAgOiBfZ2V0V2F0Y2gobmFtZSwgZGVmYXVsdFZhbHVlLCB0cnVlKTtcbiAgICBjb25zdCBfc3Vic2NyaWJlID0gKHByb3BzKSA9PiBfc3ViamVjdHMuc3RhdGUuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKGZvcm1TdGF0ZSkgPT4ge1xuICAgICAgICAgICAgaWYgKHNob3VsZFN1YnNjcmliZUJ5TmFtZShwcm9wcy5uYW1lLCBmb3JtU3RhdGUubmFtZSwgcHJvcHMuZXhhY3QpICYmXG4gICAgICAgICAgICAgICAgc2hvdWxkUmVuZGVyRm9ybVN0YXRlKGZvcm1TdGF0ZSwgcHJvcHMuZm9ybVN0YXRlIHx8IF9wcm94eUZvcm1TdGF0ZSwgX3NldEZvcm1TdGF0ZSwgcHJvcHMucmVSZW5kZXJSb290KSkge1xuICAgICAgICAgICAgICAgIHByb3BzLmNhbGxiYWNrKHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVzOiB7IC4uLl9mb3JtVmFsdWVzIH0sXG4gICAgICAgICAgICAgICAgICAgIC4uLl9mb3JtU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgIC4uLmZvcm1TdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlczogX2RlZmF1bHRWYWx1ZXMsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgfSkudW5zdWJzY3JpYmU7XG4gICAgY29uc3Qgc3Vic2NyaWJlID0gKHByb3BzKSA9PiB7XG4gICAgICAgIF9zdGF0ZS5tb3VudCA9IHRydWU7XG4gICAgICAgIF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZSA9IHtcbiAgICAgICAgICAgIC4uLl9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZSxcbiAgICAgICAgICAgIC4uLnByb3BzLmZvcm1TdGF0ZSxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF9zdWJzY3JpYmUoe1xuICAgICAgICAgICAgLi4ucHJvcHMsXG4gICAgICAgICAgICBmb3JtU3RhdGU6IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZSxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCB1bnJlZ2lzdGVyID0gKG5hbWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBvZiBuYW1lID8gY29udmVydFRvQXJyYXlQYXlsb2FkKG5hbWUpIDogX25hbWVzLm1vdW50KSB7XG4gICAgICAgICAgICBfbmFtZXMubW91bnQuZGVsZXRlKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICBfbmFtZXMuYXJyYXkuZGVsZXRlKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMua2VlcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdW5zZXQoX2ZpZWxkcywgZmllbGROYW1lKTtcbiAgICAgICAgICAgICAgICB1bnNldChfZm9ybVZhbHVlcywgZmllbGROYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICFvcHRpb25zLmtlZXBFcnJvciAmJiB1bnNldChfZm9ybVN0YXRlLmVycm9ycywgZmllbGROYW1lKTtcbiAgICAgICAgICAgICFvcHRpb25zLmtlZXBEaXJ0eSAmJiB1bnNldChfZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBmaWVsZE5hbWUpO1xuICAgICAgICAgICAgIW9wdGlvbnMua2VlcFRvdWNoZWQgJiYgdW5zZXQoX2Zvcm1TdGF0ZS50b3VjaGVkRmllbGRzLCBmaWVsZE5hbWUpO1xuICAgICAgICAgICAgIW9wdGlvbnMua2VlcElzVmFsaWRhdGluZyAmJlxuICAgICAgICAgICAgICAgIHVuc2V0KF9mb3JtU3RhdGUudmFsaWRhdGluZ0ZpZWxkcywgZmllbGROYW1lKTtcbiAgICAgICAgICAgICFfb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyICYmXG4gICAgICAgICAgICAgICAgIW9wdGlvbnMua2VlcERlZmF1bHRWYWx1ZSAmJlxuICAgICAgICAgICAgICAgIHVuc2V0KF9kZWZhdWx0VmFsdWVzLCBmaWVsZE5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIHZhbHVlczogY2xvbmVPYmplY3QoX2Zvcm1WYWx1ZXMpLFxuICAgICAgICB9KTtcbiAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgLi4uX2Zvcm1TdGF0ZSxcbiAgICAgICAgICAgIC4uLighb3B0aW9ucy5rZWVwRGlydHkgPyB7fSA6IHsgaXNEaXJ0eTogX2dldERpcnR5KCkgfSksXG4gICAgICAgIH0pO1xuICAgICAgICAhb3B0aW9ucy5rZWVwSXNWYWxpZCAmJiBfc2V0VmFsaWQoKTtcbiAgICB9O1xuICAgIGNvbnN0IF9zZXREaXNhYmxlZEZpZWxkID0gKHsgZGlzYWJsZWQsIG5hbWUsIH0pID0+IHtcbiAgICAgICAgaWYgKChpc0Jvb2xlYW4oZGlzYWJsZWQpICYmIF9zdGF0ZS5tb3VudCkgfHxcbiAgICAgICAgICAgICEhZGlzYWJsZWQgfHxcbiAgICAgICAgICAgIF9uYW1lcy5kaXNhYmxlZC5oYXMobmFtZSkpIHtcbiAgICAgICAgICAgIGRpc2FibGVkID8gX25hbWVzLmRpc2FibGVkLmFkZChuYW1lKSA6IF9uYW1lcy5kaXNhYmxlZC5kZWxldGUobmFtZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IHJlZ2lzdGVyID0gKG5hbWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBsZXQgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgIGNvbnN0IGRpc2FibGVkSXNEZWZpbmVkID0gaXNCb29sZWFuKG9wdGlvbnMuZGlzYWJsZWQpIHx8IGlzQm9vbGVhbihfb3B0aW9ucy5kaXNhYmxlZCk7XG4gICAgICAgIHNldChfZmllbGRzLCBuYW1lLCB7XG4gICAgICAgICAgICAuLi4oZmllbGQgfHwge30pLFxuICAgICAgICAgICAgX2Y6IHtcbiAgICAgICAgICAgICAgICAuLi4oZmllbGQgJiYgZmllbGQuX2YgPyBmaWVsZC5fZiA6IHsgcmVmOiB7IG5hbWUgfSB9KSxcbiAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgIG1vdW50OiB0cnVlLFxuICAgICAgICAgICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgX25hbWVzLm1vdW50LmFkZChuYW1lKTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBfc2V0RGlzYWJsZWRGaWVsZCh7XG4gICAgICAgICAgICAgICAgZGlzYWJsZWQ6IGlzQm9vbGVhbihvcHRpb25zLmRpc2FibGVkKVxuICAgICAgICAgICAgICAgICAgICA/IG9wdGlvbnMuZGlzYWJsZWRcbiAgICAgICAgICAgICAgICAgICAgOiBfb3B0aW9ucy5kaXNhYmxlZCxcbiAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB1cGRhdGVWYWxpZEFuZFZhbHVlKG5hbWUsIHRydWUsIG9wdGlvbnMudmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi4oZGlzYWJsZWRJc0RlZmluZWRcbiAgICAgICAgICAgICAgICA/IHsgZGlzYWJsZWQ6IG9wdGlvbnMuZGlzYWJsZWQgfHwgX29wdGlvbnMuZGlzYWJsZWQgfVxuICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgLi4uKF9vcHRpb25zLnByb2dyZXNzaXZlXG4gICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiAhIW9wdGlvbnMucmVxdWlyZWQsXG4gICAgICAgICAgICAgICAgICAgIG1pbjogZ2V0UnVsZVZhbHVlKG9wdGlvbnMubWluKSxcbiAgICAgICAgICAgICAgICAgICAgbWF4OiBnZXRSdWxlVmFsdWUob3B0aW9ucy5tYXgpLFxuICAgICAgICAgICAgICAgICAgICBtaW5MZW5ndGg6IGdldFJ1bGVWYWx1ZShvcHRpb25zLm1pbkxlbmd0aCksXG4gICAgICAgICAgICAgICAgICAgIG1heExlbmd0aDogZ2V0UnVsZVZhbHVlKG9wdGlvbnMubWF4TGVuZ3RoKSxcbiAgICAgICAgICAgICAgICAgICAgcGF0dGVybjogZ2V0UnVsZVZhbHVlKG9wdGlvbnMucGF0dGVybiksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIG9uQ2hhbmdlLFxuICAgICAgICAgICAgb25CbHVyOiBvbkNoYW5nZSxcbiAgICAgICAgICAgIHJlZjogKHJlZikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVnaXN0ZXIobmFtZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkID0gZ2V0KF9maWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWVsZFJlZiA9IGlzVW5kZWZpbmVkKHJlZi52YWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgID8gcmVmLnF1ZXJ5U2VsZWN0b3JBbGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IHJlZi5xdWVyeVNlbGVjdG9yQWxsKCdpbnB1dCxzZWxlY3QsdGV4dGFyZWEnKVswXSB8fCByZWZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHJlZlxuICAgICAgICAgICAgICAgICAgICAgICAgOiByZWY7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhZGlvT3JDaGVja2JveCA9IGlzUmFkaW9PckNoZWNrYm94KGZpZWxkUmVmKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVmcyA9IGZpZWxkLl9mLnJlZnMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgIGlmIChyYWRpb09yQ2hlY2tib3hcbiAgICAgICAgICAgICAgICAgICAgICAgID8gcmVmcy5maW5kKChvcHRpb24pID0+IG9wdGlvbiA9PT0gZmllbGRSZWYpXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGZpZWxkUmVmID09PSBmaWVsZC5fZi5yZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZXQoX2ZpZWxkcywgbmFtZSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2Y6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5maWVsZC5fZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4ocmFkaW9PckNoZWNrYm94XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnJlZnMuZmlsdGVyKGxpdmUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkUmVmLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLihBcnJheS5pc0FycmF5KGdldChfZGVmYXVsdFZhbHVlcywgbmFtZSkpID8gW3t9XSA6IFtdKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWY6IHsgdHlwZTogZmllbGRSZWYudHlwZSwgbmFtZSB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogeyByZWY6IGZpZWxkUmVmIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZVZhbGlkQW5kVmFsdWUobmFtZSwgZmFsc2UsIHVuZGVmaW5lZCwgZmllbGRSZWYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSwge30pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmllbGQuX2YpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkLl9mLm1vdW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKF9vcHRpb25zLnNob3VsZFVucmVnaXN0ZXIgfHwgb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgIShpc05hbWVJbkZpZWxkQXJyYXkoX25hbWVzLmFycmF5LCBuYW1lKSAmJiBfc3RhdGUuYWN0aW9uKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgX25hbWVzLnVuTW91bnQuYWRkKG5hbWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBjb25zdCBfZm9jdXNFcnJvciA9ICgpID0+IF9vcHRpb25zLnNob3VsZEZvY3VzRXJyb3IgJiZcbiAgICAgICAgaXRlcmF0ZUZpZWxkc0J5QWN0aW9uKF9maWVsZHMsIF9mb2N1c0lucHV0LCBfbmFtZXMubW91bnQpO1xuICAgIGNvbnN0IF9kaXNhYmxlRm9ybSA9IChkaXNhYmxlZCkgPT4ge1xuICAgICAgICBpZiAoaXNCb29sZWFuKGRpc2FibGVkKSkge1xuICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoeyBkaXNhYmxlZCB9KTtcbiAgICAgICAgICAgIGl0ZXJhdGVGaWVsZHNCeUFjdGlvbihfZmllbGRzLCAocmVmLCBuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY3VycmVudEZpZWxkID0gZ2V0KF9maWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50RmllbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmLmRpc2FibGVkID0gY3VycmVudEZpZWxkLl9mLmRpc2FibGVkIHx8IGRpc2FibGVkO1xuICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjdXJyZW50RmllbGQuX2YucmVmcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRGaWVsZC5fZi5yZWZzLmZvckVhY2goKGlucHV0UmVmKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRSZWYuZGlzYWJsZWQgPSBjdXJyZW50RmllbGQuX2YuZGlzYWJsZWQgfHwgZGlzYWJsZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIDAsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgaGFuZGxlU3VibWl0ID0gKG9uVmFsaWQsIG9uSW52YWxpZCkgPT4gYXN5bmMgKGUpID0+IHtcbiAgICAgICAgbGV0IG9uVmFsaWRFcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQgJiYgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZS5wZXJzaXN0ICYmXG4gICAgICAgICAgICAgICAgZS5wZXJzaXN0KCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGZpZWxkVmFsdWVzID0gY2xvbmVPYmplY3QoX2Zvcm1WYWx1ZXMpO1xuICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICBpc1N1Ym1pdHRpbmc6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoX29wdGlvbnMucmVzb2x2ZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgZXJyb3JzLCB2YWx1ZXMgfSA9IGF3YWl0IF9ydW5TY2hlbWEoKTtcbiAgICAgICAgICAgIF9mb3JtU3RhdGUuZXJyb3JzID0gZXJyb3JzO1xuICAgICAgICAgICAgZmllbGRWYWx1ZXMgPSBjbG9uZU9iamVjdCh2YWx1ZXMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYXdhaXQgZXhlY3V0ZUJ1aWx0SW5WYWxpZGF0aW9uKF9maWVsZHMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChfbmFtZXMuZGlzYWJsZWQuc2l6ZSkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIF9uYW1lcy5kaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgIHVuc2V0KGZpZWxkVmFsdWVzLCBuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB1bnNldChfZm9ybVN0YXRlLmVycm9ycywgJ3Jvb3QnKTtcbiAgICAgICAgaWYgKGlzRW1wdHlPYmplY3QoX2Zvcm1TdGF0ZS5lcnJvcnMpKSB7XG4gICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiB7fSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBvblZhbGlkKGZpZWxkVmFsdWVzLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIG9uVmFsaWRFcnJvciA9IGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKG9uSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IG9uSW52YWxpZCh7IC4uLl9mb3JtU3RhdGUuZXJyb3JzIH0sIGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX2ZvY3VzRXJyb3IoKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoX2ZvY3VzRXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIGlzU3VibWl0dGVkOiB0cnVlLFxuICAgICAgICAgICAgaXNTdWJtaXR0aW5nOiBmYWxzZSxcbiAgICAgICAgICAgIGlzU3VibWl0U3VjY2Vzc2Z1bDogaXNFbXB0eU9iamVjdChfZm9ybVN0YXRlLmVycm9ycykgJiYgIW9uVmFsaWRFcnJvcixcbiAgICAgICAgICAgIHN1Ym1pdENvdW50OiBfZm9ybVN0YXRlLnN1Ym1pdENvdW50ICsgMSxcbiAgICAgICAgICAgIGVycm9yczogX2Zvcm1TdGF0ZS5lcnJvcnMsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAob25WYWxpZEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBvblZhbGlkRXJyb3I7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IHJlc2V0RmllbGQgPSAobmFtZSwgb3B0aW9ucyA9IHt9KSA9PiB7XG4gICAgICAgIGlmIChnZXQoX2ZpZWxkcywgbmFtZSkpIHtcbiAgICAgICAgICAgIGlmIChpc1VuZGVmaW5lZChvcHRpb25zLmRlZmF1bHRWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBzZXRWYWx1ZShuYW1lLCBjbG9uZU9iamVjdChnZXQoX2RlZmF1bHRWYWx1ZXMsIG5hbWUpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZXRWYWx1ZShuYW1lLCBvcHRpb25zLmRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgc2V0KF9kZWZhdWx0VmFsdWVzLCBuYW1lLCBjbG9uZU9iamVjdChvcHRpb25zLmRlZmF1bHRWYWx1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFvcHRpb25zLmtlZXBUb3VjaGVkKSB7XG4gICAgICAgICAgICAgICAgdW5zZXQoX2Zvcm1TdGF0ZS50b3VjaGVkRmllbGRzLCBuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghb3B0aW9ucy5rZWVwRGlydHkpIHtcbiAgICAgICAgICAgICAgICB1bnNldChfZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBuYW1lKTtcbiAgICAgICAgICAgICAgICBfZm9ybVN0YXRlLmlzRGlydHkgPSBvcHRpb25zLmRlZmF1bHRWYWx1ZVxuICAgICAgICAgICAgICAgICAgICA/IF9nZXREaXJ0eShuYW1lLCBjbG9uZU9iamVjdChnZXQoX2RlZmF1bHRWYWx1ZXMsIG5hbWUpKSlcbiAgICAgICAgICAgICAgICAgICAgOiBfZ2V0RGlydHkoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghb3B0aW9ucy5rZWVwRXJyb3IpIHtcbiAgICAgICAgICAgICAgICB1bnNldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICAgICAgX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWQgJiYgX3NldFZhbGlkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7IC4uLl9mb3JtU3RhdGUgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IF9yZXNldCA9IChmb3JtVmFsdWVzLCBrZWVwU3RhdGVPcHRpb25zID0ge30pID0+IHtcbiAgICAgICAgY29uc3QgdXBkYXRlZFZhbHVlcyA9IGZvcm1WYWx1ZXMgPyBjbG9uZU9iamVjdChmb3JtVmFsdWVzKSA6IF9kZWZhdWx0VmFsdWVzO1xuICAgICAgICBjb25zdCBjbG9uZVVwZGF0ZWRWYWx1ZXMgPSBjbG9uZU9iamVjdCh1cGRhdGVkVmFsdWVzKTtcbiAgICAgICAgY29uc3QgaXNFbXB0eVJlc2V0VmFsdWVzID0gaXNFbXB0eU9iamVjdChmb3JtVmFsdWVzKTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gaXNFbXB0eVJlc2V0VmFsdWVzID8gX2RlZmF1bHRWYWx1ZXMgOiBjbG9uZVVwZGF0ZWRWYWx1ZXM7XG4gICAgICAgIGlmICgha2VlcFN0YXRlT3B0aW9ucy5rZWVwRGVmYXVsdFZhbHVlcykge1xuICAgICAgICAgICAgX2RlZmF1bHRWYWx1ZXMgPSB1cGRhdGVkVmFsdWVzO1xuICAgICAgICB9XG4gICAgICAgIGlmICgha2VlcFN0YXRlT3B0aW9ucy5rZWVwVmFsdWVzKSB7XG4gICAgICAgICAgICBpZiAoa2VlcFN0YXRlT3B0aW9ucy5rZWVwRGlydHlWYWx1ZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWVsZHNUb0NoZWNrID0gbmV3IFNldChbXG4gICAgICAgICAgICAgICAgICAgIC4uLl9uYW1lcy5tb3VudCxcbiAgICAgICAgICAgICAgICAgICAgLi4uT2JqZWN0LmtleXMoZ2V0RGlydHlGaWVsZHMoX2RlZmF1bHRWYWx1ZXMsIF9mb3JtVmFsdWVzKSksXG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWVsZE5hbWUgb2YgQXJyYXkuZnJvbShmaWVsZHNUb0NoZWNrKSkge1xuICAgICAgICAgICAgICAgICAgICBnZXQoX2Zvcm1TdGF0ZS5kaXJ0eUZpZWxkcywgZmllbGROYW1lKVxuICAgICAgICAgICAgICAgICAgICAgICAgPyBzZXQodmFsdWVzLCBmaWVsZE5hbWUsIGdldChfZm9ybVZhbHVlcywgZmllbGROYW1lKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIDogc2V0VmFsdWUoZmllbGROYW1lLCBnZXQodmFsdWVzLCBmaWVsZE5hbWUpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXZWIgJiYgaXNVbmRlZmluZWQoZm9ybVZhbHVlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIF9uYW1lcy5tb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmllbGQgJiYgZmllbGQuX2YpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWVsZFJlZmVyZW5jZSA9IEFycmF5LmlzQXJyYXkoZmllbGQuX2YucmVmcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBmaWVsZC5fZi5yZWZzWzBdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogZmllbGQuX2YucmVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hUTUxFbGVtZW50KGZpZWxkUmVmZXJlbmNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb3JtID0gZmllbGRSZWZlcmVuY2UuY2xvc2VzdCgnZm9ybScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9ybSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybS5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGtlZXBTdGF0ZU9wdGlvbnMua2VlcEZpZWxkc1JlZikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBvZiBfbmFtZXMubW91bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlKGZpZWxkTmFtZSwgZ2V0KHZhbHVlcywgZmllbGROYW1lKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF9maWVsZHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfZm9ybVZhbHVlcyA9IF9vcHRpb25zLnNob3VsZFVucmVnaXN0ZXJcbiAgICAgICAgICAgICAgICA/IGtlZXBTdGF0ZU9wdGlvbnMua2VlcERlZmF1bHRWYWx1ZXNcbiAgICAgICAgICAgICAgICAgICAgPyBjbG9uZU9iamVjdChfZGVmYXVsdFZhbHVlcylcbiAgICAgICAgICAgICAgICAgICAgOiB7fVxuICAgICAgICAgICAgICAgIDogY2xvbmVPYmplY3QodmFsdWVzKTtcbiAgICAgICAgICAgIF9zdWJqZWN0cy5hcnJheS5uZXh0KHtcbiAgICAgICAgICAgICAgICB2YWx1ZXM6IHsgLi4udmFsdWVzIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgICAgICB2YWx1ZXM6IHsgLi4udmFsdWVzIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBfbmFtZXMgPSB7XG4gICAgICAgICAgICBtb3VudDoga2VlcFN0YXRlT3B0aW9ucy5rZWVwRGlydHlWYWx1ZXMgPyBfbmFtZXMubW91bnQgOiBuZXcgU2V0KCksXG4gICAgICAgICAgICB1bk1vdW50OiBuZXcgU2V0KCksXG4gICAgICAgICAgICBhcnJheTogbmV3IFNldCgpLFxuICAgICAgICAgICAgZGlzYWJsZWQ6IG5ldyBTZXQoKSxcbiAgICAgICAgICAgIHdhdGNoOiBuZXcgU2V0KCksXG4gICAgICAgICAgICB3YXRjaEFsbDogZmFsc2UsXG4gICAgICAgICAgICBmb2N1czogJycsXG4gICAgICAgIH07XG4gICAgICAgIF9zdGF0ZS5tb3VudCA9XG4gICAgICAgICAgICAhX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWQgfHxcbiAgICAgICAgICAgICAgICAhIWtlZXBTdGF0ZU9wdGlvbnMua2VlcElzVmFsaWQgfHxcbiAgICAgICAgICAgICAgICAhIWtlZXBTdGF0ZU9wdGlvbnMua2VlcERpcnR5VmFsdWVzIHx8XG4gICAgICAgICAgICAgICAgKCFfb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyICYmICFpc0VtcHR5T2JqZWN0KHZhbHVlcykpO1xuICAgICAgICBfc3RhdGUud2F0Y2ggPSAhIV9vcHRpb25zLnNob3VsZFVucmVnaXN0ZXI7XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIHN1Ym1pdENvdW50OiBrZWVwU3RhdGVPcHRpb25zLmtlZXBTdWJtaXRDb3VudFxuICAgICAgICAgICAgICAgID8gX2Zvcm1TdGF0ZS5zdWJtaXRDb3VudFxuICAgICAgICAgICAgICAgIDogMCxcbiAgICAgICAgICAgIGlzRGlydHk6IGlzRW1wdHlSZXNldFZhbHVlc1xuICAgICAgICAgICAgICAgID8gZmFsc2VcbiAgICAgICAgICAgICAgICA6IGtlZXBTdGF0ZU9wdGlvbnMua2VlcERpcnR5XG4gICAgICAgICAgICAgICAgICAgID8gX2Zvcm1TdGF0ZS5pc0RpcnR5XG4gICAgICAgICAgICAgICAgICAgIDogISEoa2VlcFN0YXRlT3B0aW9ucy5rZWVwRGVmYXVsdFZhbHVlcyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgIWRlZXBFcXVhbChmb3JtVmFsdWVzLCBfZGVmYXVsdFZhbHVlcykpLFxuICAgICAgICAgICAgaXNTdWJtaXR0ZWQ6IGtlZXBTdGF0ZU9wdGlvbnMua2VlcElzU3VibWl0dGVkXG4gICAgICAgICAgICAgICAgPyBfZm9ybVN0YXRlLmlzU3VibWl0dGVkXG4gICAgICAgICAgICAgICAgOiBmYWxzZSxcbiAgICAgICAgICAgIGRpcnR5RmllbGRzOiBpc0VtcHR5UmVzZXRWYWx1ZXNcbiAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBEaXJ0eVZhbHVlc1xuICAgICAgICAgICAgICAgICAgICA/IGtlZXBTdGF0ZU9wdGlvbnMua2VlcERlZmF1bHRWYWx1ZXMgJiYgX2Zvcm1WYWx1ZXNcbiAgICAgICAgICAgICAgICAgICAgICAgID8gZ2V0RGlydHlGaWVsZHMoX2RlZmF1bHRWYWx1ZXMsIF9mb3JtVmFsdWVzKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBfZm9ybVN0YXRlLmRpcnR5RmllbGRzXG4gICAgICAgICAgICAgICAgICAgIDoga2VlcFN0YXRlT3B0aW9ucy5rZWVwRGVmYXVsdFZhbHVlcyAmJiBmb3JtVmFsdWVzXG4gICAgICAgICAgICAgICAgICAgICAgICA/IGdldERpcnR5RmllbGRzKF9kZWZhdWx0VmFsdWVzLCBmb3JtVmFsdWVzKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBEaXJ0eVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gX2Zvcm1TdGF0ZS5kaXJ0eUZpZWxkc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDoge30sXG4gICAgICAgICAgICB0b3VjaGVkRmllbGRzOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBUb3VjaGVkXG4gICAgICAgICAgICAgICAgPyBfZm9ybVN0YXRlLnRvdWNoZWRGaWVsZHNcbiAgICAgICAgICAgICAgICA6IHt9LFxuICAgICAgICAgICAgZXJyb3JzOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBFcnJvcnMgPyBfZm9ybVN0YXRlLmVycm9ycyA6IHt9LFxuICAgICAgICAgICAgaXNTdWJtaXRTdWNjZXNzZnVsOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBJc1N1Ym1pdFN1Y2Nlc3NmdWxcbiAgICAgICAgICAgICAgICA/IF9mb3JtU3RhdGUuaXNTdWJtaXRTdWNjZXNzZnVsXG4gICAgICAgICAgICAgICAgOiBmYWxzZSxcbiAgICAgICAgICAgIGlzU3VibWl0dGluZzogZmFsc2UsXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWVzOiBfZGVmYXVsdFZhbHVlcyxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCByZXNldCA9IChmb3JtVmFsdWVzLCBrZWVwU3RhdGVPcHRpb25zKSA9PiBfcmVzZXQoaXNGdW5jdGlvbihmb3JtVmFsdWVzKVxuICAgICAgICA/IGZvcm1WYWx1ZXMoX2Zvcm1WYWx1ZXMpXG4gICAgICAgIDogZm9ybVZhbHVlcywga2VlcFN0YXRlT3B0aW9ucyk7XG4gICAgY29uc3Qgc2V0Rm9jdXMgPSAobmFtZSwgb3B0aW9ucyA9IHt9KSA9PiB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KF9maWVsZHMsIG5hbWUpO1xuICAgICAgICBjb25zdCBmaWVsZFJlZmVyZW5jZSA9IGZpZWxkICYmIGZpZWxkLl9mO1xuICAgICAgICBpZiAoZmllbGRSZWZlcmVuY2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkUmVmID0gZmllbGRSZWZlcmVuY2UucmVmc1xuICAgICAgICAgICAgICAgID8gZmllbGRSZWZlcmVuY2UucmVmc1swXVxuICAgICAgICAgICAgICAgIDogZmllbGRSZWZlcmVuY2UucmVmO1xuICAgICAgICAgICAgaWYgKGZpZWxkUmVmLmZvY3VzKSB7XG4gICAgICAgICAgICAgICAgZmllbGRSZWYuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICBvcHRpb25zLnNob3VsZFNlbGVjdCAmJlxuICAgICAgICAgICAgICAgICAgICBpc0Z1bmN0aW9uKGZpZWxkUmVmLnNlbGVjdCkgJiZcbiAgICAgICAgICAgICAgICAgICAgZmllbGRSZWYuc2VsZWN0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IF9zZXRGb3JtU3RhdGUgPSAodXBkYXRlZEZvcm1TdGF0ZSkgPT4ge1xuICAgICAgICBfZm9ybVN0YXRlID0ge1xuICAgICAgICAgICAgLi4uX2Zvcm1TdGF0ZSxcbiAgICAgICAgICAgIC4uLnVwZGF0ZWRGb3JtU3RhdGUsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBjb25zdCBfcmVzZXREZWZhdWx0VmFsdWVzID0gKCkgPT4gaXNGdW5jdGlvbihfb3B0aW9ucy5kZWZhdWx0VmFsdWVzKSAmJlxuICAgICAgICBfb3B0aW9ucy5kZWZhdWx0VmFsdWVzKCkudGhlbigodmFsdWVzKSA9PiB7XG4gICAgICAgICAgICByZXNldCh2YWx1ZXMsIF9vcHRpb25zLnJlc2V0T3B0aW9ucyk7XG4gICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgaXNMb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICBjb25zdCBtZXRob2RzID0ge1xuICAgICAgICBjb250cm9sOiB7XG4gICAgICAgICAgICByZWdpc3RlcixcbiAgICAgICAgICAgIHVucmVnaXN0ZXIsXG4gICAgICAgICAgICBnZXRGaWVsZFN0YXRlLFxuICAgICAgICAgICAgaGFuZGxlU3VibWl0LFxuICAgICAgICAgICAgc2V0RXJyb3IsXG4gICAgICAgICAgICBfc3Vic2NyaWJlLFxuICAgICAgICAgICAgX3J1blNjaGVtYSxcbiAgICAgICAgICAgIF9mb2N1c0Vycm9yLFxuICAgICAgICAgICAgX2dldFdhdGNoLFxuICAgICAgICAgICAgX2dldERpcnR5LFxuICAgICAgICAgICAgX3NldFZhbGlkLFxuICAgICAgICAgICAgX3NldEZpZWxkQXJyYXksXG4gICAgICAgICAgICBfc2V0RGlzYWJsZWRGaWVsZCxcbiAgICAgICAgICAgIF9zZXRFcnJvcnMsXG4gICAgICAgICAgICBfZ2V0RmllbGRBcnJheSxcbiAgICAgICAgICAgIF9yZXNldCxcbiAgICAgICAgICAgIF9yZXNldERlZmF1bHRWYWx1ZXMsXG4gICAgICAgICAgICBfcmVtb3ZlVW5tb3VudGVkLFxuICAgICAgICAgICAgX2Rpc2FibGVGb3JtLFxuICAgICAgICAgICAgX3N1YmplY3RzLFxuICAgICAgICAgICAgX3Byb3h5Rm9ybVN0YXRlLFxuICAgICAgICAgICAgZ2V0IF9maWVsZHMoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9maWVsZHM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0IF9mb3JtVmFsdWVzKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfZm9ybVZhbHVlcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQgX3N0YXRlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfc3RhdGU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0IF9zdGF0ZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIF9zdGF0ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldCBfZGVmYXVsdFZhbHVlcygpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX2RlZmF1bHRWYWx1ZXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0IF9uYW1lcygpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX25hbWVzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldCBfbmFtZXModmFsdWUpIHtcbiAgICAgICAgICAgICAgICBfbmFtZXMgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQgX2Zvcm1TdGF0ZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX2Zvcm1TdGF0ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQgX29wdGlvbnMoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9vcHRpb25zO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldCBfb3B0aW9ucyh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIF9vcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAuLi5fb3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgLi4udmFsdWUsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHN1YnNjcmliZSxcbiAgICAgICAgdHJpZ2dlcixcbiAgICAgICAgcmVnaXN0ZXIsXG4gICAgICAgIGhhbmRsZVN1Ym1pdCxcbiAgICAgICAgd2F0Y2gsXG4gICAgICAgIHNldFZhbHVlLFxuICAgICAgICBnZXRWYWx1ZXMsXG4gICAgICAgIHJlc2V0LFxuICAgICAgICByZXNldEZpZWxkLFxuICAgICAgICBjbGVhckVycm9ycyxcbiAgICAgICAgdW5yZWdpc3RlcixcbiAgICAgICAgc2V0RXJyb3IsXG4gICAgICAgIHNldEZvY3VzLFxuICAgICAgICBnZXRGaWVsZFN0YXRlLFxuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0aG9kcyxcbiAgICAgICAgZm9ybUNvbnRyb2w6IG1ldGhvZHMsXG4gICAgfTtcbn1cblxudmFyIGdlbmVyYXRlSWQgPSAoKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBjcnlwdG8gIT09ICd1bmRlZmluZWQnICYmIGNyeXB0by5yYW5kb21VVUlEKSB7XG4gICAgICAgIHJldHVybiBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIH1cbiAgICBjb25zdCBkID0gdHlwZW9mIHBlcmZvcm1hbmNlID09PSAndW5kZWZpbmVkJyA/IERhdGUubm93KCkgOiBwZXJmb3JtYW5jZS5ub3coKSAqIDEwMDA7XG4gICAgcmV0dXJuICd4eHh4eHh4eC14eHh4LTR4eHgteXh4eC14eHh4eHh4eHh4eHgnLnJlcGxhY2UoL1t4eV0vZywgKGMpID0+IHtcbiAgICAgICAgY29uc3QgciA9IChNYXRoLnJhbmRvbSgpICogMTYgKyBkKSAlIDE2IHwgMDtcbiAgICAgICAgcmV0dXJuIChjID09ICd4JyA/IHIgOiAociAmIDB4MykgfCAweDgpLnRvU3RyaW5nKDE2KTtcbiAgICB9KTtcbn07XG5cbnZhciBnZXRGb2N1c0ZpZWxkTmFtZSA9IChuYW1lLCBpbmRleCwgb3B0aW9ucyA9IHt9KSA9PiBvcHRpb25zLnNob3VsZEZvY3VzIHx8IGlzVW5kZWZpbmVkKG9wdGlvbnMuc2hvdWxkRm9jdXMpXG4gICAgPyBvcHRpb25zLmZvY3VzTmFtZSB8fFxuICAgICAgICBgJHtuYW1lfS4ke2lzVW5kZWZpbmVkKG9wdGlvbnMuZm9jdXNJbmRleCkgPyBpbmRleCA6IG9wdGlvbnMuZm9jdXNJbmRleH0uYFxuICAgIDogJyc7XG5cbnZhciBhcHBlbmRBdCA9IChkYXRhLCB2YWx1ZSkgPT4gW1xuICAgIC4uLmRhdGEsXG4gICAgLi4uY29udmVydFRvQXJyYXlQYXlsb2FkKHZhbHVlKSxcbl07XG5cbnZhciBmaWxsRW1wdHlBcnJheSA9ICh2YWx1ZSkgPT4gQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZS5tYXAoKCkgPT4gdW5kZWZpbmVkKSA6IHVuZGVmaW5lZDtcblxuZnVuY3Rpb24gaW5zZXJ0KGRhdGEsIGluZGV4LCB2YWx1ZSkge1xuICAgIHJldHVybiBbXG4gICAgICAgIC4uLmRhdGEuc2xpY2UoMCwgaW5kZXgpLFxuICAgICAgICAuLi5jb252ZXJ0VG9BcnJheVBheWxvYWQodmFsdWUpLFxuICAgICAgICAuLi5kYXRhLnNsaWNlKGluZGV4KSxcbiAgICBdO1xufVxuXG52YXIgbW92ZUFycmF5QXQgPSAoZGF0YSwgZnJvbSwgdG8pID0+IHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBpZiAoaXNVbmRlZmluZWQoZGF0YVt0b10pKSB7XG4gICAgICAgIGRhdGFbdG9dID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBkYXRhLnNwbGljZSh0bywgMCwgZGF0YS5zcGxpY2UoZnJvbSwgMSlbMF0pO1xuICAgIHJldHVybiBkYXRhO1xufTtcblxudmFyIHByZXBlbmRBdCA9IChkYXRhLCB2YWx1ZSkgPT4gW1xuICAgIC4uLmNvbnZlcnRUb0FycmF5UGF5bG9hZCh2YWx1ZSksXG4gICAgLi4uY29udmVydFRvQXJyYXlQYXlsb2FkKGRhdGEpLFxuXTtcblxuZnVuY3Rpb24gcmVtb3ZlQXRJbmRleGVzKGRhdGEsIGluZGV4ZXMpIHtcbiAgICBsZXQgaSA9IDA7XG4gICAgY29uc3QgdGVtcCA9IFsuLi5kYXRhXTtcbiAgICBmb3IgKGNvbnN0IGluZGV4IG9mIGluZGV4ZXMpIHtcbiAgICAgICAgdGVtcC5zcGxpY2UoaW5kZXggLSBpLCAxKTtcbiAgICAgICAgaSsrO1xuICAgIH1cbiAgICByZXR1cm4gY29tcGFjdCh0ZW1wKS5sZW5ndGggPyB0ZW1wIDogW107XG59XG52YXIgcmVtb3ZlQXJyYXlBdCA9IChkYXRhLCBpbmRleCkgPT4gaXNVbmRlZmluZWQoaW5kZXgpXG4gICAgPyBbXVxuICAgIDogcmVtb3ZlQXRJbmRleGVzKGRhdGEsIGNvbnZlcnRUb0FycmF5UGF5bG9hZChpbmRleCkuc29ydCgoYSwgYikgPT4gYSAtIGIpKTtcblxudmFyIHN3YXBBcnJheUF0ID0gKGRhdGEsIGluZGV4QSwgaW5kZXhCKSA9PiB7XG4gICAgW2RhdGFbaW5kZXhBXSwgZGF0YVtpbmRleEJdXSA9IFtkYXRhW2luZGV4Ql0sIGRhdGFbaW5kZXhBXV07XG59O1xuXG52YXIgdXBkYXRlQXQgPSAoZmllbGRWYWx1ZXMsIGluZGV4LCB2YWx1ZSkgPT4ge1xuICAgIGZpZWxkVmFsdWVzW2luZGV4XSA9IHZhbHVlO1xuICAgIHJldHVybiBmaWVsZFZhbHVlcztcbn07XG5cbi8qKlxuICogQSBjdXN0b20gaG9vayB0aGF0IGV4cG9zZXMgY29udmVuaWVudCBtZXRob2RzIHRvIHBlcmZvcm0gb3BlcmF0aW9ucyB3aXRoIGEgbGlzdCBvZiBkeW5hbWljIGlucHV0cyB0aGF0IG5lZWQgdG8gYmUgYXBwZW5kZWQsIHVwZGF0ZWQsIHJlbW92ZWQgZXRjLiDigKIgW0RlbW9dKGh0dHBzOi8vY29kZXNhbmRib3guaW8vcy9yZWFjdC1ob29rLWZvcm0tdXNlZmllbGRhcnJheS1zc3Vnbikg4oCiIFtWaWRlb10oaHR0cHM6Ly95b3V0dS5iZS80TXJiZkdTRlkyQSlcbiAqXG4gKiBAcmVtYXJrc1xuICogW0FQSV0oaHR0cHM6Ly9yZWFjdC1ob29rLWZvcm0uY29tL2RvY3MvdXNlZmllbGRhcnJheSkg4oCiIFtEZW1vXShodHRwczovL2NvZGVzYW5kYm94LmlvL3MvcmVhY3QtaG9vay1mb3JtLXVzZWZpZWxkYXJyYXktc3N1Z24pXG4gKlxuICogQHBhcmFtIHByb3BzIC0gdXNlRmllbGRBcnJheSBwcm9wc1xuICpcbiAqIEByZXR1cm5zIG1ldGhvZHMgLSBmdW5jdGlvbnMgdG8gbWFuaXB1bGF0ZSB3aXRoIHRoZSBGaWVsZCBBcnJheXMgKGR5bmFtaWMgaW5wdXRzKSB7QGxpbmsgVXNlRmllbGRBcnJheVJldHVybn1cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHN4XG4gKiBmdW5jdGlvbiBBcHAoKSB7XG4gKiAgIGNvbnN0IHsgcmVnaXN0ZXIsIGNvbnRyb2wsIGhhbmRsZVN1Ym1pdCwgcmVzZXQsIHRyaWdnZXIsIHNldEVycm9yIH0gPSB1c2VGb3JtKHtcbiAqICAgICBkZWZhdWx0VmFsdWVzOiB7XG4gKiAgICAgICB0ZXN0OiBbXVxuICogICAgIH1cbiAqICAgfSk7XG4gKiAgIGNvbnN0IHsgZmllbGRzLCBhcHBlbmQgfSA9IHVzZUZpZWxkQXJyYXkoe1xuICogICAgIGNvbnRyb2wsXG4gKiAgICAgbmFtZTogXCJ0ZXN0XCJcbiAqICAgfSk7XG4gKlxuICogICByZXR1cm4gKFxuICogICAgIDxmb3JtIG9uU3VibWl0PXtoYW5kbGVTdWJtaXQoZGF0YSA9PiBjb25zb2xlLmxvZyhkYXRhKSl9PlxuICogICAgICAge2ZpZWxkcy5tYXAoKGl0ZW0sIGluZGV4KSA9PiAoXG4gKiAgICAgICAgICA8aW5wdXQga2V5PXtpdGVtLmlkfSB7Li4ucmVnaXN0ZXIoYHRlc3QuJHtpbmRleH0uZmlyc3ROYW1lYCl9ICAvPlxuICogICAgICAgKSl9XG4gKiAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBvbkNsaWNrPXsoKSA9PiBhcHBlbmQoeyBmaXJzdE5hbWU6IFwiYmlsbFwiIH0pfT5cbiAqICAgICAgICAgYXBwZW5kXG4gKiAgICAgICA8L2J1dHRvbj5cbiAqICAgICAgIDxpbnB1dCB0eXBlPVwic3VibWl0XCIgLz5cbiAqICAgICA8L2Zvcm0+XG4gKiAgICk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZnVuY3Rpb24gdXNlRmllbGRBcnJheShwcm9wcykge1xuICAgIGNvbnN0IG1ldGhvZHMgPSB1c2VGb3JtQ29udGV4dCgpO1xuICAgIGNvbnN0IHsgY29udHJvbCA9IG1ldGhvZHMuY29udHJvbCwgbmFtZSwga2V5TmFtZSA9ICdpZCcsIHNob3VsZFVucmVnaXN0ZXIsIHJ1bGVzLCB9ID0gcHJvcHM7XG4gICAgY29uc3QgW2ZpZWxkcywgc2V0RmllbGRzXSA9IFJlYWN0LnVzZVN0YXRlKGNvbnRyb2wuX2dldEZpZWxkQXJyYXkobmFtZSkpO1xuICAgIGNvbnN0IGlkcyA9IFJlYWN0LnVzZVJlZihjb250cm9sLl9nZXRGaWVsZEFycmF5KG5hbWUpLm1hcChnZW5lcmF0ZUlkKSk7XG4gICAgY29uc3QgX2FjdGlvbmVkID0gUmVhY3QudXNlUmVmKGZhbHNlKTtcbiAgICBjb250cm9sLl9uYW1lcy5hcnJheS5hZGQobmFtZSk7XG4gICAgUmVhY3QudXNlTWVtbygoKSA9PiBydWxlcyAmJlxuICAgICAgICBmaWVsZHMubGVuZ3RoID49IDAgJiZcbiAgICAgICAgY29udHJvbC5yZWdpc3RlcihuYW1lLCBydWxlcyksIFtjb250cm9sLCBuYW1lLCBmaWVsZHMubGVuZ3RoLCBydWxlc10pO1xuICAgIHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QoKCkgPT4gY29udHJvbC5fc3ViamVjdHMuYXJyYXkuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKHsgdmFsdWVzLCBuYW1lOiBmaWVsZEFycmF5TmFtZSwgfSkgPT4ge1xuICAgICAgICAgICAgaWYgKGZpZWxkQXJyYXlOYW1lID09PSBuYW1lIHx8ICFmaWVsZEFycmF5TmFtZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkVmFsdWVzID0gZ2V0KHZhbHVlcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldEZpZWxkcyhmaWVsZFZhbHVlcyk7XG4gICAgICAgICAgICAgICAgICAgIGlkcy5jdXJyZW50ID0gZmllbGRWYWx1ZXMubWFwKGdlbmVyYXRlSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICB9KS51bnN1YnNjcmliZSwgW2NvbnRyb2wsIG5hbWVdKTtcbiAgICBjb25zdCB1cGRhdGVWYWx1ZXMgPSBSZWFjdC51c2VDYWxsYmFjaygodXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMpID0+IHtcbiAgICAgICAgX2FjdGlvbmVkLmN1cnJlbnQgPSB0cnVlO1xuICAgICAgICBjb250cm9sLl9zZXRGaWVsZEFycmF5KG5hbWUsIHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICB9LCBbY29udHJvbCwgbmFtZV0pO1xuICAgIGNvbnN0IGFwcGVuZCA9ICh2YWx1ZSwgb3B0aW9ucykgPT4ge1xuICAgICAgICBjb25zdCBhcHBlbmRWYWx1ZSA9IGNvbnZlcnRUb0FycmF5UGF5bG9hZChjbG9uZU9iamVjdCh2YWx1ZSkpO1xuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcyA9IGFwcGVuZEF0KGNvbnRyb2wuX2dldEZpZWxkQXJyYXkobmFtZSksIGFwcGVuZFZhbHVlKTtcbiAgICAgICAgY29udHJvbC5fbmFtZXMuZm9jdXMgPSBnZXRGb2N1c0ZpZWxkTmFtZShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcy5sZW5ndGggLSAxLCBvcHRpb25zKTtcbiAgICAgICAgaWRzLmN1cnJlbnQgPSBhcHBlbmRBdChpZHMuY3VycmVudCwgYXBwZW5kVmFsdWUubWFwKGdlbmVyYXRlSWQpKTtcbiAgICAgICAgdXBkYXRlVmFsdWVzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgc2V0RmllbGRzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgY29udHJvbC5fc2V0RmllbGRBcnJheShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcywgYXBwZW5kQXQsIHtcbiAgICAgICAgICAgIGFyZ0E6IGZpbGxFbXB0eUFycmF5KHZhbHVlKSxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCBwcmVwZW5kID0gKHZhbHVlLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGNvbnN0IHByZXBlbmRWYWx1ZSA9IGNvbnZlcnRUb0FycmF5UGF5bG9hZChjbG9uZU9iamVjdCh2YWx1ZSkpO1xuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcyA9IHByZXBlbmRBdChjb250cm9sLl9nZXRGaWVsZEFycmF5KG5hbWUpLCBwcmVwZW5kVmFsdWUpO1xuICAgICAgICBjb250cm9sLl9uYW1lcy5mb2N1cyA9IGdldEZvY3VzRmllbGROYW1lKG5hbWUsIDAsIG9wdGlvbnMpO1xuICAgICAgICBpZHMuY3VycmVudCA9IHByZXBlbmRBdChpZHMuY3VycmVudCwgcHJlcGVuZFZhbHVlLm1hcChnZW5lcmF0ZUlkKSk7XG4gICAgICAgIHVwZGF0ZVZhbHVlcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIHNldEZpZWxkcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIGNvbnRyb2wuX3NldEZpZWxkQXJyYXkobmFtZSwgdXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMsIHByZXBlbmRBdCwge1xuICAgICAgICAgICAgYXJnQTogZmlsbEVtcHR5QXJyYXkodmFsdWUpLFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IHJlbW92ZSA9IChpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcyA9IHJlbW92ZUFycmF5QXQoY29udHJvbC5fZ2V0RmllbGRBcnJheShuYW1lKSwgaW5kZXgpO1xuICAgICAgICBpZHMuY3VycmVudCA9IHJlbW92ZUFycmF5QXQoaWRzLmN1cnJlbnQsIGluZGV4KTtcbiAgICAgICAgdXBkYXRlVmFsdWVzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgc2V0RmllbGRzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoZ2V0KGNvbnRyb2wuX2ZpZWxkcywgbmFtZSkpICYmXG4gICAgICAgICAgICBzZXQoY29udHJvbC5fZmllbGRzLCBuYW1lLCB1bmRlZmluZWQpO1xuICAgICAgICBjb250cm9sLl9zZXRGaWVsZEFycmF5KG5hbWUsIHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzLCByZW1vdmVBcnJheUF0LCB7XG4gICAgICAgICAgICBhcmdBOiBpbmRleCxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCBpbnNlcnQkMSA9IChpbmRleCwgdmFsdWUsIG9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgaW5zZXJ0VmFsdWUgPSBjb252ZXJ0VG9BcnJheVBheWxvYWQoY2xvbmVPYmplY3QodmFsdWUpKTtcbiAgICAgICAgY29uc3QgdXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMgPSBpbnNlcnQoY29udHJvbC5fZ2V0RmllbGRBcnJheShuYW1lKSwgaW5kZXgsIGluc2VydFZhbHVlKTtcbiAgICAgICAgY29udHJvbC5fbmFtZXMuZm9jdXMgPSBnZXRGb2N1c0ZpZWxkTmFtZShuYW1lLCBpbmRleCwgb3B0aW9ucyk7XG4gICAgICAgIGlkcy5jdXJyZW50ID0gaW5zZXJ0KGlkcy5jdXJyZW50LCBpbmRleCwgaW5zZXJ0VmFsdWUubWFwKGdlbmVyYXRlSWQpKTtcbiAgICAgICAgdXBkYXRlVmFsdWVzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgc2V0RmllbGRzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgY29udHJvbC5fc2V0RmllbGRBcnJheShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcywgaW5zZXJ0LCB7XG4gICAgICAgICAgICBhcmdBOiBpbmRleCxcbiAgICAgICAgICAgIGFyZ0I6IGZpbGxFbXB0eUFycmF5KHZhbHVlKSxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCBzd2FwID0gKGluZGV4QSwgaW5kZXhCKSA9PiB7XG4gICAgICAgIGNvbnN0IHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzID0gY29udHJvbC5fZ2V0RmllbGRBcnJheShuYW1lKTtcbiAgICAgICAgc3dhcEFycmF5QXQodXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMsIGluZGV4QSwgaW5kZXhCKTtcbiAgICAgICAgc3dhcEFycmF5QXQoaWRzLmN1cnJlbnQsIGluZGV4QSwgaW5kZXhCKTtcbiAgICAgICAgdXBkYXRlVmFsdWVzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgc2V0RmllbGRzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgY29udHJvbC5fc2V0RmllbGRBcnJheShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcywgc3dhcEFycmF5QXQsIHtcbiAgICAgICAgICAgIGFyZ0E6IGluZGV4QSxcbiAgICAgICAgICAgIGFyZ0I6IGluZGV4QixcbiAgICAgICAgfSwgZmFsc2UpO1xuICAgIH07XG4gICAgY29uc3QgbW92ZSA9IChmcm9tLCB0bykgPT4ge1xuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcyA9IGNvbnRyb2wuX2dldEZpZWxkQXJyYXkobmFtZSk7XG4gICAgICAgIG1vdmVBcnJheUF0KHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzLCBmcm9tLCB0byk7XG4gICAgICAgIG1vdmVBcnJheUF0KGlkcy5jdXJyZW50LCBmcm9tLCB0byk7XG4gICAgICAgIHVwZGF0ZVZhbHVlcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIHNldEZpZWxkcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIGNvbnRyb2wuX3NldEZpZWxkQXJyYXkobmFtZSwgdXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMsIG1vdmVBcnJheUF0LCB7XG4gICAgICAgICAgICBhcmdBOiBmcm9tLFxuICAgICAgICAgICAgYXJnQjogdG8sXG4gICAgICAgIH0sIGZhbHNlKTtcbiAgICB9O1xuICAgIGNvbnN0IHVwZGF0ZSA9IChpbmRleCwgdmFsdWUpID0+IHtcbiAgICAgICAgY29uc3QgdXBkYXRlVmFsdWUgPSBjbG9uZU9iamVjdCh2YWx1ZSk7XG4gICAgICAgIGNvbnN0IHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzID0gdXBkYXRlQXQoY29udHJvbC5fZ2V0RmllbGRBcnJheShuYW1lKSwgaW5kZXgsIHVwZGF0ZVZhbHVlKTtcbiAgICAgICAgaWRzLmN1cnJlbnQgPSBbLi4udXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXNdLm1hcCgoaXRlbSwgaSkgPT4gIWl0ZW0gfHwgaSA9PT0gaW5kZXggPyBnZW5lcmF0ZUlkKCkgOiBpZHMuY3VycmVudFtpXSk7XG4gICAgICAgIHVwZGF0ZVZhbHVlcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIHNldEZpZWxkcyhbLi4udXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXNdKTtcbiAgICAgICAgY29udHJvbC5fc2V0RmllbGRBcnJheShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcywgdXBkYXRlQXQsIHtcbiAgICAgICAgICAgIGFyZ0E6IGluZGV4LFxuICAgICAgICAgICAgYXJnQjogdXBkYXRlVmFsdWUsXG4gICAgICAgIH0sIHRydWUsIGZhbHNlKTtcbiAgICB9O1xuICAgIGNvbnN0IHJlcGxhY2UgPSAodmFsdWUpID0+IHtcbiAgICAgICAgY29uc3QgdXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMgPSBjb252ZXJ0VG9BcnJheVBheWxvYWQoY2xvbmVPYmplY3QodmFsdWUpKTtcbiAgICAgICAgaWRzLmN1cnJlbnQgPSB1cGRhdGVkRmllbGRBcnJheVZhbHVlcy5tYXAoZ2VuZXJhdGVJZCk7XG4gICAgICAgIHVwZGF0ZVZhbHVlcyhbLi4udXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXNdKTtcbiAgICAgICAgc2V0RmllbGRzKFsuLi51cGRhdGVkRmllbGRBcnJheVZhbHVlc10pO1xuICAgICAgICBjb250cm9sLl9zZXRGaWVsZEFycmF5KG5hbWUsIFsuLi51cGRhdGVkRmllbGRBcnJheVZhbHVlc10sIChkYXRhKSA9PiBkYXRhLCB7fSwgdHJ1ZSwgZmFsc2UpO1xuICAgIH07XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgY29udHJvbC5fc3RhdGUuYWN0aW9uID0gZmFsc2U7XG4gICAgICAgIGlzV2F0Y2hlZChuYW1lLCBjb250cm9sLl9uYW1lcykgJiZcbiAgICAgICAgICAgIGNvbnRyb2wuX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgIC4uLmNvbnRyb2wuX2Zvcm1TdGF0ZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBpZiAoX2FjdGlvbmVkLmN1cnJlbnQgJiZcbiAgICAgICAgICAgICghZ2V0VmFsaWRhdGlvbk1vZGVzKGNvbnRyb2wuX29wdGlvbnMubW9kZSkuaXNPblN1Ym1pdCB8fFxuICAgICAgICAgICAgICAgIGNvbnRyb2wuX2Zvcm1TdGF0ZS5pc1N1Ym1pdHRlZCkgJiZcbiAgICAgICAgICAgICFnZXRWYWxpZGF0aW9uTW9kZXMoY29udHJvbC5fb3B0aW9ucy5yZVZhbGlkYXRlTW9kZSkuaXNPblN1Ym1pdCkge1xuICAgICAgICAgICAgaWYgKGNvbnRyb2wuX29wdGlvbnMucmVzb2x2ZXIpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sLl9ydW5TY2hlbWEoW25hbWVdKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBnZXQocmVzdWx0LmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nRXJyb3IgPSBnZXQoY29udHJvbC5fZm9ybVN0YXRlLmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGlzdGluZ0Vycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICghZXJyb3IgJiYgZXhpc3RpbmdFcnJvci50eXBlKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlcnJvciAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXhpc3RpbmdFcnJvci50eXBlICE9PSBlcnJvci50eXBlIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ0Vycm9yLm1lc3NhZ2UgIT09IGVycm9yLm1lc3NhZ2UpKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBlcnJvciAmJiBlcnJvci50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gc2V0KGNvbnRyb2wuX2Zvcm1TdGF0ZS5lcnJvcnMsIG5hbWUsIGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdW5zZXQoY29udHJvbC5fZm9ybVN0YXRlLmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sLl9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnM6IGNvbnRyb2wuX2Zvcm1TdGF0ZS5lcnJvcnMsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoY29udHJvbC5fZmllbGRzLCBuYW1lKTtcbiAgICAgICAgICAgICAgICBpZiAoZmllbGQgJiZcbiAgICAgICAgICAgICAgICAgICAgZmllbGQuX2YgJiZcbiAgICAgICAgICAgICAgICAgICAgIShnZXRWYWxpZGF0aW9uTW9kZXMoY29udHJvbC5fb3B0aW9ucy5yZVZhbGlkYXRlTW9kZSkuaXNPblN1Ym1pdCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0VmFsaWRhdGlvbk1vZGVzKGNvbnRyb2wuX29wdGlvbnMubW9kZSkuaXNPblN1Ym1pdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGVGaWVsZChmaWVsZCwgY29udHJvbC5fbmFtZXMuZGlzYWJsZWQsIGNvbnRyb2wuX2Zvcm1WYWx1ZXMsIGNvbnRyb2wuX29wdGlvbnMuY3JpdGVyaWFNb2RlID09PSBWQUxJREFUSU9OX01PREUuYWxsLCBjb250cm9sLl9vcHRpb25zLnNob3VsZFVzZU5hdGl2ZVZhbGlkYXRpb24sIHRydWUpLnRoZW4oKGVycm9yKSA9PiAhaXNFbXB0eU9iamVjdChlcnJvcikgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wuX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yczogdXBkYXRlRmllbGRBcnJheVJvb3RFcnJvcihjb250cm9sLl9mb3JtU3RhdGUuZXJyb3JzLCBlcnJvciwgbmFtZSksXG4gICAgICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnRyb2wuX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIHZhbHVlczogY2xvbmVPYmplY3QoY29udHJvbC5fZm9ybVZhbHVlcyksXG4gICAgICAgIH0pO1xuICAgICAgICBjb250cm9sLl9uYW1lcy5mb2N1cyAmJlxuICAgICAgICAgICAgaXRlcmF0ZUZpZWxkc0J5QWN0aW9uKGNvbnRyb2wuX2ZpZWxkcywgKHJlZiwga2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRyb2wuX25hbWVzLmZvY3VzICYmXG4gICAgICAgICAgICAgICAgICAgIGtleS5zdGFydHNXaXRoKGNvbnRyb2wuX25hbWVzLmZvY3VzKSAmJlxuICAgICAgICAgICAgICAgICAgICByZWYuZm9jdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgY29udHJvbC5fbmFtZXMuZm9jdXMgPSAnJztcbiAgICAgICAgY29udHJvbC5fc2V0VmFsaWQoKTtcbiAgICAgICAgX2FjdGlvbmVkLmN1cnJlbnQgPSBmYWxzZTtcbiAgICB9LCBbZmllbGRzLCBuYW1lLCBjb250cm9sXSk7XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgIWdldChjb250cm9sLl9mb3JtVmFsdWVzLCBuYW1lKSAmJiBjb250cm9sLl9zZXRGaWVsZEFycmF5KG5hbWUpO1xuICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlTW91bnRlZCA9IChuYW1lLCB2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KGNvbnRyb2wuX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKGZpZWxkICYmIGZpZWxkLl9mKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkLl9mLm1vdW50ID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnRyb2wuX29wdGlvbnMuc2hvdWxkVW5yZWdpc3RlciB8fCBzaG91bGRVbnJlZ2lzdGVyXG4gICAgICAgICAgICAgICAgPyBjb250cm9sLnVucmVnaXN0ZXIobmFtZSlcbiAgICAgICAgICAgICAgICA6IHVwZGF0ZU1vdW50ZWQobmFtZSwgZmFsc2UpO1xuICAgICAgICB9O1xuICAgIH0sIFtuYW1lLCBjb250cm9sLCBrZXlOYW1lLCBzaG91bGRVbnJlZ2lzdGVyXSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3dhcDogUmVhY3QudXNlQ2FsbGJhY2soc3dhcCwgW3VwZGF0ZVZhbHVlcywgbmFtZSwgY29udHJvbF0pLFxuICAgICAgICBtb3ZlOiBSZWFjdC51c2VDYWxsYmFjayhtb3ZlLCBbdXBkYXRlVmFsdWVzLCBuYW1lLCBjb250cm9sXSksXG4gICAgICAgIHByZXBlbmQ6IFJlYWN0LnVzZUNhbGxiYWNrKHByZXBlbmQsIFt1cGRhdGVWYWx1ZXMsIG5hbWUsIGNvbnRyb2xdKSxcbiAgICAgICAgYXBwZW5kOiBSZWFjdC51c2VDYWxsYmFjayhhcHBlbmQsIFt1cGRhdGVWYWx1ZXMsIG5hbWUsIGNvbnRyb2xdKSxcbiAgICAgICAgcmVtb3ZlOiBSZWFjdC51c2VDYWxsYmFjayhyZW1vdmUsIFt1cGRhdGVWYWx1ZXMsIG5hbWUsIGNvbnRyb2xdKSxcbiAgICAgICAgaW5zZXJ0OiBSZWFjdC51c2VDYWxsYmFjayhpbnNlcnQkMSwgW3VwZGF0ZVZhbHVlcywgbmFtZSwgY29udHJvbF0pLFxuICAgICAgICB1cGRhdGU6IFJlYWN0LnVzZUNhbGxiYWNrKHVwZGF0ZSwgW3VwZGF0ZVZhbHVlcywgbmFtZSwgY29udHJvbF0pLFxuICAgICAgICByZXBsYWNlOiBSZWFjdC51c2VDYWxsYmFjayhyZXBsYWNlLCBbdXBkYXRlVmFsdWVzLCBuYW1lLCBjb250cm9sXSksXG4gICAgICAgIGZpZWxkczogUmVhY3QudXNlTWVtbygoKSA9PiBmaWVsZHMubWFwKChmaWVsZCwgaW5kZXgpID0+ICh7XG4gICAgICAgICAgICAuLi5maWVsZCxcbiAgICAgICAgICAgIFtrZXlOYW1lXTogaWRzLmN1cnJlbnRbaW5kZXhdIHx8IGdlbmVyYXRlSWQoKSxcbiAgICAgICAgfSkpLCBbZmllbGRzLCBrZXlOYW1lXSksXG4gICAgfTtcbn1cblxuLyoqXG4gKiBDdXN0b20gaG9vayB0byBtYW5hZ2UgdGhlIGVudGlyZSBmb3JtLlxuICpcbiAqIEByZW1hcmtzXG4gKiBbQVBJXShodHRwczovL3JlYWN0LWhvb2stZm9ybS5jb20vZG9jcy91c2Vmb3JtKSDigKIgW0RlbW9dKGh0dHBzOi8vY29kZXNhbmRib3guaW8vcy9yZWFjdC1ob29rLWZvcm0tZ2V0LXN0YXJ0ZWQtdHMtNWtzbW0pIOKAoiBbVmlkZW9dKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9UmtYdjRBWFhDXzQpXG4gKlxuICogQHBhcmFtIHByb3BzIC0gZm9ybSBjb25maWd1cmF0aW9uIGFuZCB2YWxpZGF0aW9uIHBhcmFtZXRlcnMuXG4gKlxuICogQHJldHVybnMgbWV0aG9kcyAtIGluZGl2aWR1YWwgZnVuY3Rpb25zIHRvIG1hbmFnZSB0aGUgZm9ybSBzdGF0ZS4ge0BsaW5rIFVzZUZvcm1SZXR1cm59XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCB7IHJlZ2lzdGVyLCBoYW5kbGVTdWJtaXQsIHdhdGNoLCBmb3JtU3RhdGU6IHsgZXJyb3JzIH0gfSA9IHVzZUZvcm0oKTtcbiAqICAgY29uc3Qgb25TdWJtaXQgPSBkYXRhID0+IGNvbnNvbGUubG9nKGRhdGEpO1xuICpcbiAqICAgY29uc29sZS5sb2cod2F0Y2goXCJleGFtcGxlXCIpKTtcbiAqXG4gKiAgIHJldHVybiAoXG4gKiAgICAgPGZvcm0gb25TdWJtaXQ9e2hhbmRsZVN1Ym1pdChvblN1Ym1pdCl9PlxuICogICAgICAgPGlucHV0IGRlZmF1bHRWYWx1ZT1cInRlc3RcIiB7Li4ucmVnaXN0ZXIoXCJleGFtcGxlXCIpfSAvPlxuICogICAgICAgPGlucHV0IHsuLi5yZWdpc3RlcihcImV4YW1wbGVSZXF1aXJlZFwiLCB7IHJlcXVpcmVkOiB0cnVlIH0pfSAvPlxuICogICAgICAge2Vycm9ycy5leGFtcGxlUmVxdWlyZWQgJiYgPHNwYW4+VGhpcyBmaWVsZCBpcyByZXF1aXJlZDwvc3Bhbj59XG4gKiAgICAgICA8YnV0dG9uPlN1Ym1pdDwvYnV0dG9uPlxuICogICAgIDwvZm9ybT5cbiAqICAgKTtcbiAqIH1cbiAqIGBgYFxuICovXG5mdW5jdGlvbiB1c2VGb3JtKHByb3BzID0ge30pIHtcbiAgICBjb25zdCBfZm9ybUNvbnRyb2wgPSBSZWFjdC51c2VSZWYodW5kZWZpbmVkKTtcbiAgICBjb25zdCBfdmFsdWVzID0gUmVhY3QudXNlUmVmKHVuZGVmaW5lZCk7XG4gICAgY29uc3QgW2Zvcm1TdGF0ZSwgdXBkYXRlRm9ybVN0YXRlXSA9IFJlYWN0LnVzZVN0YXRlKHtcbiAgICAgICAgaXNEaXJ0eTogZmFsc2UsXG4gICAgICAgIGlzVmFsaWRhdGluZzogZmFsc2UsXG4gICAgICAgIGlzTG9hZGluZzogaXNGdW5jdGlvbihwcm9wcy5kZWZhdWx0VmFsdWVzKSxcbiAgICAgICAgaXNTdWJtaXR0ZWQ6IGZhbHNlLFxuICAgICAgICBpc1N1Ym1pdHRpbmc6IGZhbHNlLFxuICAgICAgICBpc1N1Ym1pdFN1Y2Nlc3NmdWw6IGZhbHNlLFxuICAgICAgICBpc1ZhbGlkOiBmYWxzZSxcbiAgICAgICAgc3VibWl0Q291bnQ6IDAsXG4gICAgICAgIGRpcnR5RmllbGRzOiB7fSxcbiAgICAgICAgdG91Y2hlZEZpZWxkczoge30sXG4gICAgICAgIHZhbGlkYXRpbmdGaWVsZHM6IHt9LFxuICAgICAgICBlcnJvcnM6IHByb3BzLmVycm9ycyB8fCB7fSxcbiAgICAgICAgZGlzYWJsZWQ6IHByb3BzLmRpc2FibGVkIHx8IGZhbHNlLFxuICAgICAgICBpc1JlYWR5OiBmYWxzZSxcbiAgICAgICAgZGVmYXVsdFZhbHVlczogaXNGdW5jdGlvbihwcm9wcy5kZWZhdWx0VmFsdWVzKVxuICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgIDogcHJvcHMuZGVmYXVsdFZhbHVlcyxcbiAgICB9KTtcbiAgICBpZiAoIV9mb3JtQ29udHJvbC5jdXJyZW50KSB7XG4gICAgICAgIGlmIChwcm9wcy5mb3JtQ29udHJvbCkge1xuICAgICAgICAgICAgX2Zvcm1Db250cm9sLmN1cnJlbnQgPSB7XG4gICAgICAgICAgICAgICAgLi4ucHJvcHMuZm9ybUNvbnRyb2wsXG4gICAgICAgICAgICAgICAgZm9ybVN0YXRlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChwcm9wcy5kZWZhdWx0VmFsdWVzICYmICFpc0Z1bmN0aW9uKHByb3BzLmRlZmF1bHRWYWx1ZXMpKSB7XG4gICAgICAgICAgICAgICAgcHJvcHMuZm9ybUNvbnRyb2wucmVzZXQocHJvcHMuZGVmYXVsdFZhbHVlcywgcHJvcHMucmVzZXRPcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHsgZm9ybUNvbnRyb2wsIC4uLnJlc3QgfSA9IGNyZWF0ZUZvcm1Db250cm9sKHByb3BzKTtcbiAgICAgICAgICAgIF9mb3JtQ29udHJvbC5jdXJyZW50ID0ge1xuICAgICAgICAgICAgICAgIC4uLnJlc3QsXG4gICAgICAgICAgICAgICAgZm9ybVN0YXRlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBjb250cm9sID0gX2Zvcm1Db250cm9sLmN1cnJlbnQuY29udHJvbDtcbiAgICBjb250cm9sLl9vcHRpb25zID0gcHJvcHM7XG4gICAgdXNlSXNvbW9ycGhpY0xheW91dEVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHN1YiA9IGNvbnRyb2wuX3N1YnNjcmliZSh7XG4gICAgICAgICAgICBmb3JtU3RhdGU6IGNvbnRyb2wuX3Byb3h5Rm9ybVN0YXRlLFxuICAgICAgICAgICAgY2FsbGJhY2s6ICgpID0+IHVwZGF0ZUZvcm1TdGF0ZSh7IC4uLmNvbnRyb2wuX2Zvcm1TdGF0ZSB9KSxcbiAgICAgICAgICAgIHJlUmVuZGVyUm9vdDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICAgIHVwZGF0ZUZvcm1TdGF0ZSgoZGF0YSkgPT4gKHtcbiAgICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgICAgICBpc1JlYWR5OiB0cnVlLFxuICAgICAgICB9KSk7XG4gICAgICAgIGNvbnRyb2wuX2Zvcm1TdGF0ZS5pc1JlYWR5ID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHN1YjtcbiAgICB9LCBbY29udHJvbF0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiBjb250cm9sLl9kaXNhYmxlRm9ybShwcm9wcy5kaXNhYmxlZCksIFtjb250cm9sLCBwcm9wcy5kaXNhYmxlZF0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChwcm9wcy5tb2RlKSB7XG4gICAgICAgICAgICBjb250cm9sLl9vcHRpb25zLm1vZGUgPSBwcm9wcy5tb2RlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwcm9wcy5yZVZhbGlkYXRlTW9kZSkge1xuICAgICAgICAgICAgY29udHJvbC5fb3B0aW9ucy5yZVZhbGlkYXRlTW9kZSA9IHByb3BzLnJlVmFsaWRhdGVNb2RlO1xuICAgICAgICB9XG4gICAgfSwgW2NvbnRyb2wsIHByb3BzLm1vZGUsIHByb3BzLnJlVmFsaWRhdGVNb2RlXSk7XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgaWYgKHByb3BzLmVycm9ycykge1xuICAgICAgICAgICAgY29udHJvbC5fc2V0RXJyb3JzKHByb3BzLmVycm9ycyk7XG4gICAgICAgICAgICBjb250cm9sLl9mb2N1c0Vycm9yKCk7XG4gICAgICAgIH1cbiAgICB9LCBbY29udHJvbCwgcHJvcHMuZXJyb3JzXSk7XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgcHJvcHMuc2hvdWxkVW5yZWdpc3RlciAmJlxuICAgICAgICAgICAgY29udHJvbC5fc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgdmFsdWVzOiBjb250cm9sLl9nZXRXYXRjaCgpLFxuICAgICAgICAgICAgfSk7XG4gICAgfSwgW2NvbnRyb2wsIHByb3BzLnNob3VsZFVucmVnaXN0ZXJdKTtcbiAgICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBpZiAoY29udHJvbC5fcHJveHlGb3JtU3RhdGUuaXNEaXJ0eSkge1xuICAgICAgICAgICAgY29uc3QgaXNEaXJ0eSA9IGNvbnRyb2wuX2dldERpcnR5KCk7XG4gICAgICAgICAgICBpZiAoaXNEaXJ0eSAhPT0gZm9ybVN0YXRlLmlzRGlydHkpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sLl9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgaXNEaXJ0eSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sIFtjb250cm9sLCBmb3JtU3RhdGUuaXNEaXJ0eV0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgaWYgKHByb3BzLnZhbHVlcyAmJiAhZGVlcEVxdWFsKHByb3BzLnZhbHVlcywgX3ZhbHVlcy5jdXJyZW50KSkge1xuICAgICAgICAgICAgY29udHJvbC5fcmVzZXQocHJvcHMudmFsdWVzLCB7XG4gICAgICAgICAgICAgICAga2VlcEZpZWxkc1JlZjogdHJ1ZSxcbiAgICAgICAgICAgICAgICAuLi5jb250cm9sLl9vcHRpb25zLnJlc2V0T3B0aW9ucyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEoKF9hID0gY29udHJvbC5fb3B0aW9ucy5yZXNldE9wdGlvbnMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5rZWVwSXNWYWxpZCkpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sLl9zZXRWYWxpZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3ZhbHVlcy5jdXJyZW50ID0gcHJvcHMudmFsdWVzO1xuICAgICAgICAgICAgdXBkYXRlRm9ybVN0YXRlKChzdGF0ZSkgPT4gKHsgLi4uc3RhdGUgfSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29udHJvbC5fcmVzZXREZWZhdWx0VmFsdWVzKCk7XG4gICAgICAgIH1cbiAgICB9LCBbY29udHJvbCwgcHJvcHMudmFsdWVzXSk7XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgaWYgKCFjb250cm9sLl9zdGF0ZS5tb3VudCkge1xuICAgICAgICAgICAgY29udHJvbC5fc2V0VmFsaWQoKTtcbiAgICAgICAgICAgIGNvbnRyb2wuX3N0YXRlLm1vdW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29udHJvbC5fc3RhdGUud2F0Y2gpIHtcbiAgICAgICAgICAgIGNvbnRyb2wuX3N0YXRlLndhdGNoID0gZmFsc2U7XG4gICAgICAgICAgICBjb250cm9sLl9zdWJqZWN0cy5zdGF0ZS5uZXh0KHsgLi4uY29udHJvbC5fZm9ybVN0YXRlIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRyb2wuX3JlbW92ZVVubW91bnRlZCgpO1xuICAgIH0pO1xuICAgIF9mb3JtQ29udHJvbC5jdXJyZW50LmZvcm1TdGF0ZSA9IGdldFByb3h5Rm9ybVN0YXRlKGZvcm1TdGF0ZSwgY29udHJvbCk7XG4gICAgcmV0dXJuIF9mb3JtQ29udHJvbC5jdXJyZW50O1xufVxuXG4vKipcbiAqIFdhdGNoIGNvbXBvbmVudCB0aGF0IHN1YnNjcmliZXMgdG8gZm9ybSBmaWVsZCBjaGFuZ2VzIGFuZCByZS1yZW5kZXJzIHdoZW4gd2F0Y2hlZCBmaWVsZHMgdXBkYXRlLlxuICpcbiAqIEBwYXJhbSBjb250cm9sIC0gVGhlIGZvcm0gY29udHJvbCBvYmplY3QgZnJvbSB1c2VGb3JtXG4gKiBAcGFyYW0gbmFtZXMgLSBBcnJheSBvZiBmaWVsZCBuYW1lcyB0byB3YXRjaCBmb3IgY2hhbmdlc1xuICogQHBhcmFtIHJlbmRlciAtIFRoZSBmdW5jdGlvbiB0aGF0IHJlY2VpdmVzIHdhdGNoZWQgdmFsdWVzIGFuZCByZXR1cm5zIFJlYWN0Tm9kZVxuICogQHJldHVybnMgVGhlIHJlc3VsdCBvZiBjYWxsaW5nIHJlbmRlciBmdW5jdGlvbiB3aXRoIHdhdGNoZWQgdmFsdWVzXG4gKlxuICogQGV4YW1wbGVcbiAqIFRoZSBgV2F0Y2hgIGNvbXBvbmVudCBvbmx5IHJlLXJlbmRlciB3aGVuIHRoZSB2YWx1ZXMgb2YgYGZvb2AsIGBiYXJgLCBhbmQgYGJhei5xdXhgIGNoYW5nZS5cbiAqIFRoZSB0eXBlcyBvZiBgZm9vYCwgYGJhcmAsIGFuZCBgYmF6LnF1eGAgYXJlIHByZWNpc2VseSBpbmZlcnJlZC5cbiAqXG4gKiBgYGB0c3hcbiAqIGNvbnN0IHsgY29udHJvbCB9ID0gdXNlRm9ybSgpO1xuICpcbiAqIDxXYXRjaFxuICogICBjb250cm9sPXtjb250cm9sfVxuICogICBuYW1lcz17Wydmb28nLCAnYmFyJywgJ2Jhei5xdXgnXX1cbiAqICAgcmVuZGVyPXsoW2ZvbywgYmFyLCBiYXpfcXV4XSkgPT4gPGRpdj57Zm9vfXtiYXJ9e2Jhel9xdXh9PC9kaXY+fVxuICogLz5cbiAqIGBgYFxuICovXG5jb25zdCBXYXRjaCA9ICh7IGNvbnRyb2wsIG5hbWVzLCByZW5kZXIsIH0pID0+IHJlbmRlcih1c2VXYXRjaCh7IGNvbnRyb2wsIG5hbWU6IG5hbWVzIH0pKTtcblxuZXhwb3J0IHsgQ29udHJvbGxlciwgRm9ybSwgRm9ybVByb3ZpZGVyLCBXYXRjaCwgYXBwZW5kRXJyb3JzLCBjcmVhdGVGb3JtQ29udHJvbCwgZ2V0LCBzZXQsIHVzZUNvbnRyb2xsZXIsIHVzZUZpZWxkQXJyYXksIHVzZUZvcm0sIHVzZUZvcm1Db250ZXh0LCB1c2VGb3JtU3RhdGUsIHVzZVdhdGNoIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5lc20ubWpzLm1hcFxuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==