import { difference, uniq, partition } from "/_nuxt/node_modules/.cache/vite/client/deps/lodash-es.js?v=e4f18c29"; import { whenever } from "/_nuxt/node_modules/@vueuse/core/index.mjs?v=e4f18c29"; import { useInjectedViewerState } from "/_nuxt/lib/viewer/composables/setup.ts"; import { isNumericPropertyInfo } from "/_nuxt/lib/viewer/helpers/sceneExplorer.ts"; import { FilterLogic, FilterType, isNumericFilter, isBooleanFilter, NumericFilterCondition, StringFilterCondition, ExistenceFilterCondition, BooleanFilterCondition, SortMode } from "/_nuxt/lib/viewer/helpers/filters/types.ts"; import { getConditionLabel } from "/_nuxt/lib/viewer/helpers/filters/constants.ts"; import { useFilteringDataStore } from "/_nuxt/lib/viewer/composables/filtering/dataStore.ts"; import { shouldExcludeFromFiltering, getPropertyName, isKvpFilterable, getFilterDisabledReason, findFilterByKvp, isValueNumeric, isValueBoolean } from "/_nuxt/lib/viewer/helpers/filters/utils.ts"; import { useFilterColoringHelpers } from "/_nuxt/lib/viewer/composables/filtering/coloringHelpers.ts"; import { useHighlightedObjectsUtilities, useSelectionUtilities } from "/_nuxt/lib/viewer/composables/ui.ts"; import { computed, ref } from "/_nuxt/node_modules/vue/dist/vue.runtime.esm-bundler.js?v=e4f18c29"; export function useFilterUtilities(options) { const state = options?.state || useInjectedViewerState(); const { ui: { filters, explodeFactor } } = state; const dataStore = useFilteringDataStore(); const { removeColorFilter } = useFilterColoringHelpers({ state }); const { clearHighlightedObjects } = useHighlightedObjectsUtilities(); const { clearSelection } = useSelectionUtilities(); const isolateObjects = (objectIds, options2) => { clearHighlightedObjects(); filters.isolatedObjectIds.value = uniq([ ...options2?.replace ? [] : filters.isolatedObjectIds.value, ...objectIds ]); }; const unIsolateObjects = (objectIds) => { clearHighlightedObjects(); filters.isolatedObjectIds.value = difference( filters.isolatedObjectIds.value, objectIds ); }; const resetIsolations = () => { clearHighlightedObjects(); filters.isolatedObjectIds.value = []; }; const resetHiddenAndIsolations = () => { clearHighlightedObjects(); clearSelection(); filters.isolatedObjectIds.value = []; filters.hiddenObjectIds.value = []; }; const hasAnyIsolationsApplied = computed(() => { return filters.isolatedObjectIds.value.length > 0; }); const hideObjects = (objectIds, options2) => { clearHighlightedObjects(); clearSelection(); filters.hiddenObjectIds.value = uniq([ ...options2?.replace ? [] : filters.hiddenObjectIds.value, ...objectIds ]); }; const showObjects = (objectIds) => { clearHighlightedObjects(); clearSelection(); filters.hiddenObjectIds.value = difference(filters.hiddenObjectIds.value, objectIds); }; const resetHidden = () => { clearHighlightedObjects(); clearSelection(); filters.hiddenObjectIds.value = []; }; const hasAnyHiddenApplied = computed(() => { return filters.hiddenObjectIds.value.length > 0; }); const getAllPropertyValues = (propertyKey) => { const allValues = []; for (const dataSource of dataStore.dataSources.value) { const propertyInfo = dataSource.propertyMap[propertyKey]; if (!propertyInfo) { continue; } for (const [, objProps] of Object.entries(dataSource.objectProperties)) { const value = objProps[propertyKey]; if (value !== void 0) { allValues.push(String(value)); } } } return [...new Set(allValues)].filter( (v) => v !== null && v !== void 0 && v !== "null" && v !== "undefined" ); }; const getAvailableFilterValues = (filter, limit) => { const hasValueGroups = (f) => { return "valueGroups" in f && Array.isArray(f.valueGroups); }; if (hasValueGroups(filter)) { const values = filter.valueGroups.map((vg) => String(vg.value)).filter( (v) => v !== null && v !== void 0 && v !== "null" && v !== "undefined" ); return limit ? values.slice(0, limit) : values; } return []; }; const LARGE_PROPERTY_THRESHOLD = 2e4; const isLargeProperty = (propertyKey) => { const uniqueValues = /* @__PURE__ */ new Set(); for (const dataSource of dataStore.dataSources.value) { if (!dataSource.propertyMap[propertyKey]) { continue; } for (const [, objProps] of Object.entries(dataSource.objectProperties)) { const value = objProps[propertyKey]; if (value !== void 0) { uniqueValues.add(String(value)); } } } const count = uniqueValues.size; return { isLarge: count > LARGE_PROPERTY_THRESHOLD, count }; }; const computeFullPropertyData = (propertyKey) => { const valueToObjectIds = /* @__PURE__ */ new Map(); for (const dataSource of dataStore.dataSources.value) { if (!dataSource.propertyMap[propertyKey]) { continue; } for (const [objectId, objProps] of Object.entries(dataSource.objectProperties)) { const value = objProps[propertyKey]; if (value !== void 0) { const stringValue = String(value); if (!valueToObjectIds.has(stringValue)) { valueToObjectIds.set(stringValue, []); } valueToObjectIds.get(stringValue).push(objectId); } } } if (valueToObjectIds.size === 0) { return null; } const uniqueValues = Array.from(valueToObjectIds.keys()); const isBooleanProperty = uniqueValues.every((v) => isValueBoolean(v)) && uniqueValues.length <= 2; const isNumeric = uniqueValues.every((v) => isValueNumeric(v)); if (isBooleanProperty) { return { key: propertyKey, type: "boolean", objectCount: valueToObjectIds.size, valueGroups: uniqueValues.map((value) => ({ value: String(value).toLowerCase() === "true", ids: valueToObjectIds.get(value) || [] })) }; } else if (isNumeric) { const numericValues = uniqueValues.map((v) => Number(v)).filter((v) => !isNaN(v)); const min = parseFloat(Math.min(...numericValues).toFixed(4)); const max = parseFloat(Math.max(...numericValues).toFixed(4)); const numericValueGroups = []; for (const value of uniqueValues) { const objectIds = valueToObjectIds.get(value) || []; for (const objectId of objectIds) { numericValueGroups.push({ value: Number(value), id: objectId }); } } return { key: propertyKey, type: "number", objectCount: valueToObjectIds.size, min, max, valueGroups: numericValueGroups, passMin: null, passMax: null }; } else { return { key: propertyKey, type: "string", objectCount: valueToObjectIds.size, valueGroups: uniqueValues.map((value) => ({ value: String(value), ids: valueToObjectIds.get(value) || [] })) }; } }; const isBooleanPropertyInfo = (prop) => { return prop.type === "boolean"; }; const createFilterData = (params) => { const { filter, id } = params; const fullFilter = filter.objectCount === 0 ? computeFullPropertyData(filter.key) || filter : filter; if (isBooleanPropertyInfo(fullFilter)) { return { id, isApplied: true, selectedValues: [], condition: BooleanFilterCondition.IsTrue, type: FilterType.Boolean, filter: fullFilter }; } else if (isNumericPropertyInfo(fullFilter)) { const numericFilter = fullFilter; const { min, max } = numericFilter; const range = max - min; const MIN_MEANINGFUL_RANGE = 1e-10; const hasConstantValue = range === 0; const hasNearZeroRange = range > 0 && range < MIN_MEANINGFUL_RANGE; if (hasConstantValue || hasNearZeroRange) { const reason = hasConstantValue ? `All objects have the same value (${min})` : `Range too small for meaningful filtering (${range.toExponential()})`; return { id, isApplied: true, selectedValues: [], condition: ExistenceFilterCondition.IsSet, type: FilterType.Numeric, filter: numericFilter, numericRange: { min, max }, hasConstantValue, hasNearZeroRange, rangeDisabledReason: reason }; } return { id, isApplied: true, selectedValues: [], condition: NumericFilterCondition.IsBetween, type: FilterType.Numeric, filter: numericFilter, numericRange: { min, max } }; } else { return { id, isApplied: true, selectedValues: [], condition: StringFilterCondition.Is, type: FilterType.String, filter: fullFilter, isDefaultAllSelected: true }; } }; const addActiveFilter = (filter, id) => { const existingIndex = filters.propertyFilters.value.findIndex( (f) => f.filter?.key === filter.key ); if (existingIndex !== -1) { return filters.propertyFilters.value[existingIndex].id; } else { id ||= `filter-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; const filterData = createFilterData({ filter, id }); filters.propertyFilters.value.push(filterData); updateDataStoreSlices(); return id; } }; const updateFilterProperty = (filterId, newProperty) => { const filterIndex = filters.propertyFilters.value.findIndex( (f) => f.id === filterId ); if (filterIndex === -1) return false; const newFilterData = createFilterData({ filter: newProperty, id: filterId }); if (filters.activeColorFilterId.value === filterId) { removeColorFilter(); } filters.propertyFilters.value[filterIndex] = newFilterData; updateDataStoreSlices(); return true; }; const removeActiveFilter = (filterId) => { const index = filters.propertyFilters.value.findIndex((f) => f.id === filterId); if (index !== -1) { if (filters.activeColorFilterId.value === filterId) { removeColorFilter(); } filters.propertyFilters.value.splice(index, 1); updateDataStoreSlices(); } }; const toggleFilterApplied = (filterId) => { const filter = filters.propertyFilters.value.find((f) => f.id === filterId); if (filter) { filter.isApplied = !filter.isApplied; updateDataStoreSlices(); } }; const updateActiveFilterValues = (filterId, values) => { clearHighlightedObjects(); clearSelection(); const filter = filters.propertyFilters.value.find((f) => f.id === filterId); if (filter) { filter.selectedValues = [...values]; if (!isNumericFilter(filter) && !isBooleanFilter(filter) && filter.isDefaultAllSelected) { filter.isDefaultAllSelected = false; } updateDataStoreSlices(); } }; const selectAllFilterValues = (filterId) => { clearHighlightedObjects(); clearSelection(); const filter = filters.propertyFilters.value.find((f) => f.id === filterId); if (filter && !isNumericFilter(filter)) { const propertyFilter = filter.filter; if ("valueGroups" in propertyFilter && Array.isArray(propertyFilter.valueGroups)) { filter.selectedValues = propertyFilter.valueGroups.map((vg) => String(vg.value)).filter( (v) => v !== null && v !== void 0 && v !== "null" && v !== "undefined" ); } else { const allValues = getAllPropertyValues(propertyFilter.key); filter.selectedValues = [...allValues]; } if (!isBooleanFilter(filter)) { filter.isDefaultAllSelected = false; } updateDataStoreSlices(); } }; const updateFilterCondition = (filterId, condition) => { clearHighlightedObjects(); clearSelection(); const filter = filters.propertyFilters.value.find((f) => f.id === filterId); if (filter) { filter.condition = condition; if (condition === ExistenceFilterCondition.IsSet || condition === ExistenceFilterCondition.IsNotSet) { filter.isApplied = true; } updateDataStoreSlices(); } }; const setNumericRange = (filterId, min, max) => { clearHighlightedObjects(); clearSelection(); const filter = filters.propertyFilters.value.find((f) => f.id === filterId); if (filter && isNumericFilter(filter)) { const roundedMin = parseFloat(min.toFixed(4)); const roundedMax = parseFloat(max.toFixed(4)); filter.numericRange = { min: roundedMin, max: roundedMax }; if (!filter.isApplied) { filter.isApplied = true; } updateDataStoreSlices(); } }; const setFilterLogic = (logic) => { dataStore.setFilterLogic(logic); updateDataStoreSlices(); }; const updateDataStoreSlices = () => { const nonFilterSlices = dataStore.dataSlices.value.filter( (slice) => !slice.id.startsWith("filter-") ); dataStore.dataSlices.value = nonFilterSlices; const newFilterSlices = []; filters.propertyFilters.value.forEach((filter) => { if (isNumericFilter(filter) && filter.isApplied) { const queryCriteria = { propertyKey: filter.filter.key, condition: filter.condition, values: [], minValue: filter.numericRange.min, maxValue: filter.numericRange.max }; const matchingObjectIds = dataStore.queryObjects(queryCriteria); const slice = { id: `filter-${filter.id}`, widgetId: filter.id, name: filter.condition === ExistenceFilterCondition.IsSet ? `${getPropertyName(filter.filter.key)} is set` : filter.condition === ExistenceFilterCondition.IsNotSet ? `${getPropertyName(filter.filter.key)} is not set` : `${getPropertyName(filter.filter.key)} ${getConditionLabel( filter.condition )} (${filter.numericRange.min.toFixed( 2 )} - ${filter.numericRange.max.toFixed(2)})`, objectIds: matchingObjectIds }; newFilterSlices.push(slice); } else if (isBooleanFilter(filter) && filter.isApplied) { const { condition } = filter; const queryCriteria = { propertyKey: filter.filter.key, condition, values: [] }; const matchingObjectIds = dataStore.queryObjects(queryCriteria); const slice = { id: `filter-${filter.id}`, widgetId: filter.id, name: `${getPropertyName(filter.filter.key)} ${getConditionLabel(condition)}`, objectIds: matchingObjectIds }; newFilterSlices.push(slice); } else if (!isNumericFilter(filter) && !isBooleanFilter(filter) && filter.isApplied && (filter.selectedValues.length > 0 || filter.isDefaultAllSelected || filter.condition === ExistenceFilterCondition.IsSet || filter.condition === ExistenceFilterCondition.IsNotSet)) { const values = filter.isDefaultAllSelected && filter.selectedValues.length === 0 ? filter.filter.valueGroups?.map((vg) => String(vg.value)).filter((v) => v !== "null" && v !== "undefined") || [] : filter.selectedValues; const { condition } = filter; const queryCriteria = { propertyKey: filter.filter.key, condition, values }; const matchingObjectIds = dataStore.queryObjects(queryCriteria); const slice = { id: `filter-${filter.id}`, widgetId: filter.id, name: filter.condition === ExistenceFilterCondition.IsSet ? `${getPropertyName(filter.filter.key)} is set` : filter.condition === ExistenceFilterCondition.IsNotSet ? `${getPropertyName(filter.filter.key)} is not set` : `${getPropertyName(filter.filter.key)} ${filter.condition === StringFilterCondition.Is ? "is" : "is not"} ${filter.isDefaultAllSelected && filter.selectedValues.length === 0 ? "all values" : filter.selectedValues.join(", ")}`, objectIds: matchingObjectIds }; newFilterSlices.push(slice); } }); dataStore.dataSlices.value.push(...newFilterSlices); dataStore.computeSliceIntersections(); }; const toggleActiveFilterValue = (filterId, value) => { clearHighlightedObjects(); clearSelection(); const filter = filters.propertyFilters.value.find((f) => f.id === filterId); if (filter) { const index = filter.selectedValues.indexOf(value); const wasSelected = index > -1; if (!isNumericFilter(filter) && !isBooleanFilter(filter) && filter.isDefaultAllSelected) { filter.selectedValues = [value]; filter.isDefaultAllSelected = false; } else { if (wasSelected) { filter.selectedValues.splice(index, 1); } else { filter.selectedValues.push(value); } } updateDataStoreSlices(); } }; const isActiveFilterValueSelected = (filterId, value) => { const filter = filters.propertyFilters.value.find((f) => f.id === filterId); return filter ? filter.selectedValues.includes(value) : false; }; const resetFilters = () => { clearHighlightedObjects(); clearSelection(); filters.propertyFilters.value = []; filters.selectedObjects.value = []; filters.activeColorFilterId.value = null; dataStore.setFilterLogic(FilterLogic.All); const nonFilterSlices = dataStore.dataSlices.value.filter( (slice) => !slice.id.startsWith("filter-") ); dataStore.dataSlices.value = nonFilterSlices; if (nonFilterSlices.length > 0) { dataStore.computeSliceIntersections(); } }; const resetExplode = () => { explodeFactor.value = 0; }; const pendingFiltersToRestore = ref(null); const restoreFilters = async (serializedFilters, activeColorFilterId, filterLogic) => { if (!serializedFilters?.length) return; resetFilters(); const availableProperties = getPropertyOptionsFromDataStore(); if (availableProperties.length > 0) { applyFiltersFromSerialized(serializedFilters, availableProperties); filters.activeColorFilterId.value = activeColorFilterId; if (filterLogic) { const logicValue = typeof filterLogic === "string" ? filterLogic === "any" ? FilterLogic.Any : FilterLogic.All : filterLogic; dataStore.setFilterLogic(logicValue); } } else { pendingFiltersToRestore.value = { filters: serializedFilters, activeColorFilterId, filterLogic }; } }; const applyFiltersFromSerialized = (serializedFilters, availableProperties) => { for (const serializedFilter of serializedFilters) { if (serializedFilter.key) { const propertyInfo = availableProperties.find( (f) => f.key === serializedFilter.key ); if (propertyInfo) { const filterId = addActiveFilter(propertyInfo, serializedFilter.id); updateFilterCondition(filterId, serializedFilter.condition); if (serializedFilter.selectedValues?.length) { updateActiveFilterValues(filterId, serializedFilter.selectedValues); } if (serializedFilter.numericRange) { setNumericRange( filterId, serializedFilter.numericRange.min, serializedFilter.numericRange.max ); } if (!serializedFilter.isApplied) { toggleFilterApplied(filterId); } } } } }; const getRelevantFilters = (allFilters) => { return (allFilters || []).filter((f) => { if (shouldExcludeFromFiltering(f.key)) { return false; } return true; }); }; const getPropertyOptionsFromDataStore = () => { const allProperties = /* @__PURE__ */ new Map(); for (const dataSource of dataStore.dataSources.value) { const propertyKeys = Object.keys(dataSource.propertyMap); for (const propertyKey of propertyKeys) { if (allProperties.has(propertyKey)) { continue; } const propertyInfo = dataSource.propertyMap[propertyKey]; const filterType = propertyInfo.type; if (filterType === FilterType.Boolean) { allProperties.set(propertyKey, { key: propertyKey, type: "boolean", objectCount: 0, valueGroups: [] }); } else if (filterType === FilterType.Numeric) { allProperties.set(propertyKey, { key: propertyKey, type: "number", objectCount: 0, min: 0, max: 0, valueGroups: [], passMin: null, passMax: null }); } else { allProperties.set(propertyKey, { key: propertyKey, type: "string", objectCount: 0, valueGroups: [] }); } } } return Array.from(allProperties.values()); }; const getFilteredFilterValues = (filter, options2) => { const { searchQuery, sortMode = SortMode.Alphabetical, filterId } = options2 || {}; let values; values = getAvailableFilterValues(filter); if (searchQuery?.trim()) { const searchTerm = searchQuery.toLowerCase().trim(); values = values.filter( (value) => value.toLowerCase().includes(searchTerm) ); } if (sortMode === SortMode.SelectedFirst && filterId) { const [selectedValues, unselectedValues] = partition( values, (value) => isActiveFilterValueSelected(filterId, value) ); const sortedSelectedValues = selectedValues.sort((a, b) => a.localeCompare(b)); const sortedUnselectedValues = unselectedValues.sort((a, b) => a.localeCompare(b)); return [...sortedSelectedValues, ...sortedUnselectedValues]; } else { return values.sort((a, b) => a.localeCompare(b)); } }; const shouldRestoreFilters = computed(() => { return pendingFiltersToRestore.value && getPropertyOptionsFromDataStore().length > 0; }); whenever(shouldRestoreFilters, () => { if (pendingFiltersToRestore.value) { const availableProperties = getPropertyOptionsFromDataStore(); applyFiltersFromSerialized( pendingFiltersToRestore.value.filters, availableProperties ); if (pendingFiltersToRestore.value.activeColorFilterId) { filters.activeColorFilterId.value = pendingFiltersToRestore.value.activeColorFilterId; } if (pendingFiltersToRestore.value.filterLogic) { const filterLogic = pendingFiltersToRestore.value.filterLogic; const logicValue = typeof filterLogic === "string" ? filterLogic === "any" ? FilterLogic.Any : FilterLogic.All : filterLogic; dataStore.setFilterLogic(logicValue); } pendingFiltersToRestore.value = null; } }); return { isolateObjects, unIsolateObjects, resetIsolations, resetHiddenAndIsolations, hideObjects, showObjects, resetHidden, hasAnyIsolationsApplied, hasAnyHiddenApplied, filters, addActiveFilter, updateFilterProperty, removeActiveFilter, toggleFilterApplied, updateActiveFilterValues, selectAllFilterValues, updateFilterCondition, setFilterLogic, toggleActiveFilterValue, isActiveFilterValueSelected, resetFilters, restoreFilters, resetExplode, getRelevantFilters, getPropertyOptionsFromDataStore, getPropertyName, isKvpFilterable, getFilterDisabledReason, findFilterByKvp, getFilteredFilterValues, setNumericRange, isLargeProperty }; } //# sourceMappingURL=data:application/json;base64,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QUNGLENBQUM7QUFFRCxTQUFPO0FBQUEsSUFDTDtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxFQUNGO0FBQ0YiLCJuYW1lcyI6WyJvcHRpb25zIl0sImlnbm9yZUxpc3QiOltdLCJzb3VyY2VzIjpbImZpbHRlcmluZy50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IE51bWVyaWNQcm9wZXJ0eUluZm8sIFN0cmluZ1Byb3BlcnR5SW5mbyB9IGZyb20gJ0BzcGVja2xlL3ZpZXdlcidcclxuaW1wb3J0IHsgZGlmZmVyZW5jZSwgdW5pcSwgcGFydGl0aW9uIH0gZnJvbSAnbG9kYXNoLWVzJ1xyXG5pbXBvcnQgeyB3aGVuZXZlciB9IGZyb20gJ0B2dWV1c2UvY29yZSdcclxuaW1wb3J0IHtcclxuICB1c2VJbmplY3RlZFZpZXdlclN0YXRlLFxyXG4gIHR5cGUgSW5qZWN0YWJsZVZpZXdlclN0YXRlXHJcbn0gZnJvbSAnfn4vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9zZXR1cCdcclxuaW1wb3J0IHsgaXNOdW1lcmljUHJvcGVydHlJbmZvIH0gZnJvbSAnfi9saWIvdmlld2VyL2hlbHBlcnMvc2NlbmVFeHBsb3JlcidcclxuaW1wb3J0IHtcclxuICB0eXBlIEZpbHRlckNvbmRpdGlvbixcclxuICBGaWx0ZXJMb2dpYyxcclxuICBGaWx0ZXJUeXBlLFxyXG4gIHR5cGUgRmlsdGVyRGF0YSxcclxuICB0eXBlIE51bWVyaWNGaWx0ZXJEYXRhLFxyXG4gIHR5cGUgU3RyaW5nRmlsdGVyRGF0YSxcclxuICB0eXBlIEJvb2xlYW5GaWx0ZXJEYXRhLFxyXG4gIHR5cGUgQm9vbGVhblByb3BlcnR5SW5mbyxcclxuICB0eXBlIENyZWF0ZUZpbHRlclBhcmFtcyxcclxuICBpc051bWVyaWNGaWx0ZXIsXHJcbiAgaXNCb29sZWFuRmlsdGVyLFxyXG4gIE51bWVyaWNGaWx0ZXJDb25kaXRpb24sXHJcbiAgU3RyaW5nRmlsdGVyQ29uZGl0aW9uLFxyXG4gIEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbixcclxuICBCb29sZWFuRmlsdGVyQ29uZGl0aW9uLFxyXG4gIFNvcnRNb2RlLFxyXG4gIHR5cGUgRGF0YVNsaWNlLFxyXG4gIHR5cGUgUXVlcnlDcml0ZXJpYSxcclxuICB0eXBlIEV4dGVuZGVkUHJvcGVydHlJbmZvLFxyXG4gIHR5cGUgU2VyaWFsaXplZEZpbHRlckRhdGFcclxufSBmcm9tICd+L2xpYi92aWV3ZXIvaGVscGVycy9maWx0ZXJzL3R5cGVzJ1xyXG5pbXBvcnQgeyBnZXRDb25kaXRpb25MYWJlbCB9IGZyb20gJ34vbGliL3ZpZXdlci9oZWxwZXJzL2ZpbHRlcnMvY29uc3RhbnRzJ1xyXG5pbXBvcnQgeyB1c2VGaWx0ZXJpbmdEYXRhU3RvcmUgfSBmcm9tICd+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvZmlsdGVyaW5nL2RhdGFTdG9yZSdcclxuaW1wb3J0IHtcclxuICBzaG91bGRFeGNsdWRlRnJvbUZpbHRlcmluZyxcclxuICBnZXRQcm9wZXJ0eU5hbWUsXHJcbiAgaXNLdnBGaWx0ZXJhYmxlLFxyXG4gIGdldEZpbHRlckRpc2FibGVkUmVhc29uLFxyXG4gIGZpbmRGaWx0ZXJCeUt2cCxcclxuICBpc1ZhbHVlTnVtZXJpYyxcclxuICBpc1ZhbHVlQm9vbGVhblxyXG59IGZyb20gJ34vbGliL3ZpZXdlci9oZWxwZXJzL2ZpbHRlcnMvdXRpbHMnXHJcbmltcG9ydCB7IHVzZUZpbHRlckNvbG9yaW5nSGVscGVycyB9IGZyb20gJ34vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9maWx0ZXJpbmcvY29sb3JpbmdIZWxwZXJzJ1xyXG5pbXBvcnQge1xyXG4gIHVzZUhpZ2hsaWdodGVkT2JqZWN0c1V0aWxpdGllcyxcclxuICB1c2VTZWxlY3Rpb25VdGlsaXRpZXNcclxufSBmcm9tICd+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvdWknXHJcblxyXG5leHBvcnQgZnVuY3Rpb24gdXNlRmlsdGVyVXRpbGl0aWVzKFxyXG4gIG9wdGlvbnM/OiBQYXJ0aWFsPHsgc3RhdGU6IEluamVjdGFibGVWaWV3ZXJTdGF0ZSB9PlxyXG4pIHtcclxuICBjb25zdCBzdGF0ZSA9IG9wdGlvbnM/LnN0YXRlIHx8IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG4gIGNvbnN0IHtcclxuICAgIHVpOiB7IGZpbHRlcnMsIGV4cGxvZGVGYWN0b3IgfVxyXG4gIH0gPSBzdGF0ZVxyXG5cclxuICBjb25zdCBkYXRhU3RvcmUgPSB1c2VGaWx0ZXJpbmdEYXRhU3RvcmUoKVxyXG4gIGNvbnN0IHsgcmVtb3ZlQ29sb3JGaWx0ZXIgfSA9IHVzZUZpbHRlckNvbG9yaW5nSGVscGVycyh7IHN0YXRlIH0pXHJcbiAgY29uc3QgeyBjbGVhckhpZ2hsaWdodGVkT2JqZWN0cyB9ID0gdXNlSGlnaGxpZ2h0ZWRPYmplY3RzVXRpbGl0aWVzKClcclxuICBjb25zdCB7IGNsZWFyU2VsZWN0aW9uIH0gPSB1c2VTZWxlY3Rpb25VdGlsaXRpZXMoKVxyXG5cclxuICBjb25zdCBpc29sYXRlT2JqZWN0cyA9IChcclxuICAgIG9iamVjdElkczogc3RyaW5nW10sXHJcbiAgICBvcHRpb25zPzogUGFydGlhbDx7XHJcbiAgICAgIHJlcGxhY2U6IGJvb2xlYW5cclxuICAgIH0+XHJcbiAgKSA9PiB7XHJcbiAgICBjbGVhckhpZ2hsaWdodGVkT2JqZWN0cygpXHJcblxyXG4gICAgZmlsdGVycy5pc29sYXRlZE9iamVjdElkcy52YWx1ZSA9IHVuaXEoW1xyXG4gICAgICAuLi4ob3B0aW9ucz8ucmVwbGFjZSA/IFtdIDogZmlsdGVycy5pc29sYXRlZE9iamVjdElkcy52YWx1ZSksXHJcbiAgICAgIC4uLm9iamVjdElkc1xyXG4gICAgXSlcclxuICB9XHJcblxyXG4gIGNvbnN0IHVuSXNvbGF0ZU9iamVjdHMgPSAob2JqZWN0SWRzOiBzdHJpbmdbXSkgPT4ge1xyXG4gICAgY2xlYXJIaWdobGlnaHRlZE9iamVjdHMoKVxyXG5cclxuICAgIGZpbHRlcnMuaXNvbGF0ZWRPYmplY3RJZHMudmFsdWUgPSBkaWZmZXJlbmNlKFxyXG4gICAgICBmaWx0ZXJzLmlzb2xhdGVkT2JqZWN0SWRzLnZhbHVlLFxyXG4gICAgICBvYmplY3RJZHNcclxuICAgIClcclxuICB9XHJcblxyXG4gIGNvbnN0IHJlc2V0SXNvbGF0aW9ucyA9ICgpID0+IHtcclxuICAgIGNsZWFySGlnaGxpZ2h0ZWRPYmplY3RzKClcclxuICAgIGZpbHRlcnMuaXNvbGF0ZWRPYmplY3RJZHMudmFsdWUgPSBbXVxyXG4gIH1cclxuXHJcbiAgY29uc3QgcmVzZXRIaWRkZW5BbmRJc29sYXRpb25zID0gKCkgPT4ge1xyXG4gICAgY2xlYXJIaWdobGlnaHRlZE9iamVjdHMoKVxyXG4gICAgY2xlYXJTZWxlY3Rpb24oKVxyXG4gICAgZmlsdGVycy5pc29sYXRlZE9iamVjdElkcy52YWx1ZSA9IFtdXHJcbiAgICBmaWx0ZXJzLmhpZGRlbk9iamVjdElkcy52YWx1ZSA9IFtdXHJcbiAgfVxyXG5cclxuICBjb25zdCBoYXNBbnlJc29sYXRpb25zQXBwbGllZCA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgIHJldHVybiBmaWx0ZXJzLmlzb2xhdGVkT2JqZWN0SWRzLnZhbHVlLmxlbmd0aCA+IDBcclxuICB9KVxyXG5cclxuICBjb25zdCBoaWRlT2JqZWN0cyA9IChcclxuICAgIG9iamVjdElkczogc3RyaW5nW10sXHJcbiAgICBvcHRpb25zPzogUGFydGlhbDx7XHJcbiAgICAgIHJlcGxhY2U6IGJvb2xlYW5cclxuICAgIH0+XHJcbiAgKSA9PiB7XHJcbiAgICBjbGVhckhpZ2hsaWdodGVkT2JqZWN0cygpXHJcbiAgICBjbGVhclNlbGVjdGlvbigpXHJcblxyXG4gICAgZmlsdGVycy5oaWRkZW5PYmplY3RJZHMudmFsdWUgPSB1bmlxKFtcclxuICAgICAgLi4uKG9wdGlvbnM/LnJlcGxhY2UgPyBbXSA6IGZpbHRlcnMuaGlkZGVuT2JqZWN0SWRzLnZhbHVlKSxcclxuICAgICAgLi4ub2JqZWN0SWRzXHJcbiAgICBdKVxyXG4gIH1cclxuXHJcbiAgY29uc3Qgc2hvd09iamVjdHMgPSAob2JqZWN0SWRzOiBzdHJpbmdbXSkgPT4ge1xyXG4gICAgY2xlYXJIaWdobGlnaHRlZE9iamVjdHMoKVxyXG4gICAgY2xlYXJTZWxlY3Rpb24oKVxyXG4gICAgZmlsdGVycy5oaWRkZW5PYmplY3RJZHMudmFsdWUgPSBkaWZmZXJlbmNlKGZpbHRlcnMuaGlkZGVuT2JqZWN0SWRzLnZhbHVlLCBvYmplY3RJZHMpXHJcbiAgfVxyXG5cclxuICBjb25zdCByZXNldEhpZGRlbiA9ICgpID0+IHtcclxuICAgIGNsZWFySGlnaGxpZ2h0ZWRPYmplY3RzKClcclxuICAgIGNsZWFyU2VsZWN0aW9uKClcclxuICAgIGZpbHRlcnMuaGlkZGVuT2JqZWN0SWRzLnZhbHVlID0gW11cclxuICB9XHJcblxyXG4gIGNvbnN0IGhhc0FueUhpZGRlbkFwcGxpZWQgPSBjb21wdXRlZCgoKSA9PiB7XHJcbiAgICByZXR1cm4gZmlsdGVycy5oaWRkZW5PYmplY3RJZHMudmFsdWUubGVuZ3RoID4gMFxyXG4gIH0pXHJcblxyXG4gIC8qKlxyXG4gICAqIEdldHMgQUxMIHZhbHVlcyBmb3IgYSBwcm9wZXJ0eSB1c2luZyBwcmUtY29tcHV0ZWQgZGF0YSAodXNlZCBmb3IgZmlsdGVyaW5nIGxvZ2ljKVxyXG4gICAqL1xyXG4gIGNvbnN0IGdldEFsbFByb3BlcnR5VmFsdWVzID0gKHByb3BlcnR5S2V5OiBzdHJpbmcpOiBzdHJpbmdbXSA9PiB7XHJcbiAgICBjb25zdCBhbGxWYWx1ZXM6IHN0cmluZ1tdID0gW11cclxuXHJcbiAgICBmb3IgKGNvbnN0IGRhdGFTb3VyY2Ugb2YgZGF0YVN0b3JlLmRhdGFTb3VyY2VzLnZhbHVlKSB7XHJcbiAgICAgIC8vIENoZWNrIGlmIHByb3BlcnR5IGV4aXN0cyBpbiBwcm9wZXJ0eU1hcCBmaXJzdCAocXVpY2sgY2hlY2spXHJcbiAgICAgIGNvbnN0IHByb3BlcnR5SW5mbyA9IGRhdGFTb3VyY2UucHJvcGVydHlNYXBbcHJvcGVydHlLZXldXHJcbiAgICAgIGlmICghcHJvcGVydHlJbmZvKSB7XHJcbiAgICAgICAgY29udGludWVcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gQ29sbGVjdCB2YWx1ZXMgZnJvbSBwcmUtY29tcHV0ZWQgb2JqZWN0IHByb3BlcnRpZXNcclxuICAgICAgZm9yIChjb25zdCBbLCBvYmpQcm9wc10gb2YgT2JqZWN0LmVudHJpZXMoZGF0YVNvdXJjZS5vYmplY3RQcm9wZXJ0aWVzKSkge1xyXG4gICAgICAgIGNvbnN0IHZhbHVlID0gb2JqUHJvcHNbcHJvcGVydHlLZXldXHJcbiAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgIGFsbFZhbHVlcy5wdXNoKFN0cmluZyh2YWx1ZSkpXHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gUmVtb3ZlIGR1cGxpY2F0ZXMgYW5kIGZpbHRlciBvdXQgbnVsbC91bmRlZmluZWQgdmFsdWVzXHJcbiAgICByZXR1cm4gWy4uLm5ldyBTZXQoYWxsVmFsdWVzKV0uZmlsdGVyKFxyXG4gICAgICAodikgPT4gdiAhPT0gbnVsbCAmJiB2ICE9PSB1bmRlZmluZWQgJiYgdiAhPT0gJ251bGwnICYmIHYgIT09ICd1bmRlZmluZWQnXHJcbiAgICApXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIGF2YWlsYWJsZSB2YWx1ZXMgZm9yIHRoZSBjdXJyZW50IHByb3BlcnR5IGZpbHRlciAodXNlZCBmb3IgVUkgZGlzcGxheSlcclxuICAgKi9cclxuICBjb25zdCBnZXRBdmFpbGFibGVGaWx0ZXJWYWx1ZXMgPSAoXHJcbiAgICBmaWx0ZXI6IEV4dGVuZGVkUHJvcGVydHlJbmZvLFxyXG4gICAgbGltaXQ/OiBudW1iZXJcclxuICApOiBzdHJpbmdbXSA9PiB7XHJcbiAgICAvLyBUeXBlIGd1YXJkIHRvIGNoZWNrIGlmIGZpbHRlciBoYXMgdmFsdWVHcm91cHMgcHJvcGVydHlcclxuICAgIGNvbnN0IGhhc1ZhbHVlR3JvdXBzID0gKFxyXG4gICAgICBmOiBFeHRlbmRlZFByb3BlcnR5SW5mb1xyXG4gICAgKTogZiBpcyBFeHRlbmRlZFByb3BlcnR5SW5mbyAmIHtcclxuICAgICAgdmFsdWVHcm91cHM6IEFycmF5PHsgdmFsdWU6IHN0cmluZyB8IG51bWJlciB9PlxyXG4gICAgfSA9PiB7XHJcbiAgICAgIHJldHVybiAoXHJcbiAgICAgICAgJ3ZhbHVlR3JvdXBzJyBpbiBmICYmIEFycmF5LmlzQXJyYXkoKGYgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pLnZhbHVlR3JvdXBzKVxyXG4gICAgICApXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGhhc1ZhbHVlR3JvdXBzKGZpbHRlcikpIHtcclxuICAgICAgY29uc3QgdmFsdWVzID0gZmlsdGVyLnZhbHVlR3JvdXBzXHJcbiAgICAgICAgLm1hcCgodmcpID0+IFN0cmluZyh2Zy52YWx1ZSkpXHJcbiAgICAgICAgLmZpbHRlcihcclxuICAgICAgICAgICh2KSA9PiB2ICE9PSBudWxsICYmIHYgIT09IHVuZGVmaW5lZCAmJiB2ICE9PSAnbnVsbCcgJiYgdiAhPT0gJ3VuZGVmaW5lZCdcclxuICAgICAgICApXHJcblxyXG4gICAgICByZXR1cm4gbGltaXQgPyB2YWx1ZXMuc2xpY2UoMCwgbGltaXQpIDogdmFsdWVzXHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIFtdXHJcbiAgfVxyXG5cclxuICAvLyBUaHJlc2hvbGQgZm9yIHNob3dpbmcgbGFyZ2UgcHJvcGVydHkgd2FybmluZ1xyXG4gIGNvbnN0IExBUkdFX1BST1BFUlRZX1RIUkVTSE9MRCA9IDIwMDAwXHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrcyBpZiBhIHByb3BlcnR5IGhhcyB0b28gbWFueSB1bmlxdWUgdmFsdWVzIGFuZCByZXR1cm5zIGNvdW50IGluZm9cclxuICAgKi9cclxuICBjb25zdCBpc0xhcmdlUHJvcGVydHkgPSAoXHJcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nXHJcbiAgKTogeyBpc0xhcmdlOiBib29sZWFuOyBjb3VudDogbnVtYmVyIH0gPT4ge1xyXG4gICAgY29uc3QgdW5pcXVlVmFsdWVzID0gbmV3IFNldDxzdHJpbmc+KClcclxuXHJcbiAgICBmb3IgKGNvbnN0IGRhdGFTb3VyY2Ugb2YgZGF0YVN0b3JlLmRhdGFTb3VyY2VzLnZhbHVlKSB7XHJcbiAgICAgIGlmICghZGF0YVNvdXJjZS5wcm9wZXJ0eU1hcFtwcm9wZXJ0eUtleV0pIHtcclxuICAgICAgICBjb250aW51ZVxyXG4gICAgICB9XHJcblxyXG4gICAgICBmb3IgKGNvbnN0IFssIG9ialByb3BzXSBvZiBPYmplY3QuZW50cmllcyhkYXRhU291cmNlLm9iamVjdFByb3BlcnRpZXMpKSB7XHJcbiAgICAgICAgY29uc3QgdmFsdWUgPSBvYmpQcm9wc1twcm9wZXJ0eUtleV1cclxuICAgICAgICBpZiAodmFsdWUgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgdW5pcXVlVmFsdWVzLmFkZChTdHJpbmcodmFsdWUpKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGNvdW50ID0gdW5pcXVlVmFsdWVzLnNpemVcclxuICAgIHJldHVybiB7XHJcbiAgICAgIGlzTGFyZ2U6IGNvdW50ID4gTEFSR0VfUFJPUEVSVFlfVEhSRVNIT0xELFxyXG4gICAgICBjb3VudFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ29tcHV0ZXMgZnVsbCBwcm9wZXJ0eSBkYXRhIGZvciBhIGdpdmVuIHByb3BlcnR5IGtleSAobWluL21heCwgdmFsdWVHcm91cHMpXHJcbiAgICovXHJcbiAgY29uc3QgY29tcHV0ZUZ1bGxQcm9wZXJ0eURhdGEgPSAoXHJcbiAgICBwcm9wZXJ0eUtleTogc3RyaW5nXHJcbiAgKTogRXh0ZW5kZWRQcm9wZXJ0eUluZm8gfCBudWxsID0+IHtcclxuICAgIGNvbnN0IHZhbHVlVG9PYmplY3RJZHMgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nW10+KClcclxuXHJcbiAgICBmb3IgKGNvbnN0IGRhdGFTb3VyY2Ugb2YgZGF0YVN0b3JlLmRhdGFTb3VyY2VzLnZhbHVlKSB7XHJcbiAgICAgIGlmICghZGF0YVNvdXJjZS5wcm9wZXJ0eU1hcFtwcm9wZXJ0eUtleV0pIHtcclxuICAgICAgICBjb250aW51ZVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBDb2xsZWN0IHZhbHVlcyBhbmQgdGhlaXIgYXNzb2NpYXRlZCBvYmplY3QgSURzIHVzaW5nIHByZS1jb21wdXRlZCBkYXRhXHJcbiAgICAgIGZvciAoY29uc3QgW29iamVjdElkLCBvYmpQcm9wc10gb2YgT2JqZWN0LmVudHJpZXMoZGF0YVNvdXJjZS5vYmplY3RQcm9wZXJ0aWVzKSkge1xyXG4gICAgICAgIGNvbnN0IHZhbHVlID0gb2JqUHJvcHNbcHJvcGVydHlLZXldXHJcbiAgICAgICAgaWYgKHZhbHVlICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgIGNvbnN0IHN0cmluZ1ZhbHVlID0gU3RyaW5nKHZhbHVlKVxyXG4gICAgICAgICAgaWYgKCF2YWx1ZVRvT2JqZWN0SWRzLmhhcyhzdHJpbmdWYWx1ZSkpIHtcclxuICAgICAgICAgICAgdmFsdWVUb09iamVjdElkcy5zZXQoc3RyaW5nVmFsdWUsIFtdKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgdmFsdWVUb09iamVjdElkcy5nZXQoc3RyaW5nVmFsdWUpIS5wdXNoKG9iamVjdElkKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh2YWx1ZVRvT2JqZWN0SWRzLnNpemUgPT09IDApIHtcclxuICAgICAgcmV0dXJuIG51bGxcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB1bmlxdWVWYWx1ZXMgPSBBcnJheS5mcm9tKHZhbHVlVG9PYmplY3RJZHMua2V5cygpKVxyXG5cclxuICAgIGNvbnN0IGlzQm9vbGVhblByb3BlcnR5ID1cclxuICAgICAgdW5pcXVlVmFsdWVzLmV2ZXJ5KCh2KSA9PiBpc1ZhbHVlQm9vbGVhbih2KSkgJiYgdW5pcXVlVmFsdWVzLmxlbmd0aCA8PSAyXHJcblxyXG4gICAgY29uc3QgaXNOdW1lcmljID0gdW5pcXVlVmFsdWVzLmV2ZXJ5KCh2KSA9PiBpc1ZhbHVlTnVtZXJpYyh2KSlcclxuXHJcbiAgICBpZiAoaXNCb29sZWFuUHJvcGVydHkpIHtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBrZXk6IHByb3BlcnR5S2V5LFxyXG4gICAgICAgIHR5cGU6ICdib29sZWFuJyxcclxuICAgICAgICBvYmplY3RDb3VudDogdmFsdWVUb09iamVjdElkcy5zaXplLFxyXG4gICAgICAgIHZhbHVlR3JvdXBzOiB1bmlxdWVWYWx1ZXMubWFwKCh2YWx1ZSkgPT4gKHtcclxuICAgICAgICAgIHZhbHVlOiBTdHJpbmcodmFsdWUpLnRvTG93ZXJDYXNlKCkgPT09ICd0cnVlJyxcclxuICAgICAgICAgIGlkczogdmFsdWVUb09iamVjdElkcy5nZXQodmFsdWUpIHx8IFtdXHJcbiAgICAgICAgfSkpXHJcbiAgICAgIH0gYXMgQm9vbGVhblByb3BlcnR5SW5mb1xyXG4gICAgfSBlbHNlIGlmIChpc051bWVyaWMpIHtcclxuICAgICAgY29uc3QgbnVtZXJpY1ZhbHVlcyA9IHVuaXF1ZVZhbHVlcy5tYXAoKHYpID0+IE51bWJlcih2KSkuZmlsdGVyKCh2KSA9PiAhaXNOYU4odikpXHJcbiAgICAgIGNvbnN0IG1pbiA9IHBhcnNlRmxvYXQoTWF0aC5taW4oLi4ubnVtZXJpY1ZhbHVlcykudG9GaXhlZCg0KSlcclxuICAgICAgY29uc3QgbWF4ID0gcGFyc2VGbG9hdChNYXRoLm1heCguLi5udW1lcmljVmFsdWVzKS50b0ZpeGVkKDQpKVxyXG5cclxuICAgICAgY29uc3QgbnVtZXJpY1ZhbHVlR3JvdXBzOiB7IHZhbHVlOiBudW1iZXI7IGlkOiBzdHJpbmcgfVtdID0gW11cclxuICAgICAgZm9yIChjb25zdCB2YWx1ZSBvZiB1bmlxdWVWYWx1ZXMpIHtcclxuICAgICAgICBjb25zdCBvYmplY3RJZHMgPSB2YWx1ZVRvT2JqZWN0SWRzLmdldCh2YWx1ZSkgfHwgW11cclxuICAgICAgICBmb3IgKGNvbnN0IG9iamVjdElkIG9mIG9iamVjdElkcykge1xyXG4gICAgICAgICAgbnVtZXJpY1ZhbHVlR3JvdXBzLnB1c2goe1xyXG4gICAgICAgICAgICB2YWx1ZTogTnVtYmVyKHZhbHVlKSxcclxuICAgICAgICAgICAgaWQ6IG9iamVjdElkXHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBrZXk6IHByb3BlcnR5S2V5LFxyXG4gICAgICAgIHR5cGU6ICdudW1iZXInLFxyXG4gICAgICAgIG9iamVjdENvdW50OiB2YWx1ZVRvT2JqZWN0SWRzLnNpemUsXHJcbiAgICAgICAgbWluLFxyXG4gICAgICAgIG1heCxcclxuICAgICAgICB2YWx1ZUdyb3VwczogbnVtZXJpY1ZhbHVlR3JvdXBzLFxyXG4gICAgICAgIHBhc3NNaW46IG51bGwsXHJcbiAgICAgICAgcGFzc01heDogbnVsbFxyXG4gICAgICB9IGFzIE51bWVyaWNQcm9wZXJ0eUluZm9cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAga2V5OiBwcm9wZXJ0eUtleSxcclxuICAgICAgICB0eXBlOiAnc3RyaW5nJyxcclxuICAgICAgICBvYmplY3RDb3VudDogdmFsdWVUb09iamVjdElkcy5zaXplLFxyXG4gICAgICAgIHZhbHVlR3JvdXBzOiB1bmlxdWVWYWx1ZXMubWFwKCh2YWx1ZSkgPT4gKHtcclxuICAgICAgICAgIHZhbHVlOiBTdHJpbmcodmFsdWUpLFxyXG4gICAgICAgICAgaWRzOiB2YWx1ZVRvT2JqZWN0SWRzLmdldCh2YWx1ZSkgfHwgW11cclxuICAgICAgICB9KSlcclxuICAgICAgfSBhcyBTdHJpbmdQcm9wZXJ0eUluZm9cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IGlzQm9vbGVhblByb3BlcnR5SW5mbyA9IChcclxuICAgIHByb3A6IEV4dGVuZGVkUHJvcGVydHlJbmZvXHJcbiAgKTogcHJvcCBpcyBCb29sZWFuUHJvcGVydHlJbmZvID0+IHtcclxuICAgIHJldHVybiBwcm9wLnR5cGUgPT09ICdib29sZWFuJ1xyXG4gIH1cclxuXHJcbiAgY29uc3QgY3JlYXRlRmlsdGVyRGF0YSA9IChwYXJhbXM6IENyZWF0ZUZpbHRlclBhcmFtcyk6IEZpbHRlckRhdGEgPT4ge1xyXG4gICAgY29uc3QgeyBmaWx0ZXIsIGlkIH0gPSBwYXJhbXNcclxuXHJcbiAgICAvLyBJZiB0aGUgZmlsdGVyIGRvZXNuJ3QgaGF2ZSBmdWxsIGRhdGEsIGNvbXB1dGUgaXQgbm93XHJcbiAgICBjb25zdCBmdWxsRmlsdGVyID1cclxuICAgICAgZmlsdGVyLm9iamVjdENvdW50ID09PSAwID8gY29tcHV0ZUZ1bGxQcm9wZXJ0eURhdGEoZmlsdGVyLmtleSkgfHwgZmlsdGVyIDogZmlsdGVyXHJcblxyXG4gICAgaWYgKGlzQm9vbGVhblByb3BlcnR5SW5mbyhmdWxsRmlsdGVyKSkge1xyXG4gICAgICByZXR1cm4ge1xyXG4gICAgICAgIGlkLFxyXG4gICAgICAgIGlzQXBwbGllZDogdHJ1ZSxcclxuICAgICAgICBzZWxlY3RlZFZhbHVlczogW10sXHJcbiAgICAgICAgY29uZGl0aW9uOiBCb29sZWFuRmlsdGVyQ29uZGl0aW9uLklzVHJ1ZSxcclxuICAgICAgICB0eXBlOiBGaWx0ZXJUeXBlLkJvb2xlYW4sXHJcbiAgICAgICAgZmlsdGVyOiBmdWxsRmlsdGVyXHJcbiAgICAgIH0gYXMgQm9vbGVhbkZpbHRlckRhdGFcclxuICAgIH0gZWxzZSBpZiAoaXNOdW1lcmljUHJvcGVydHlJbmZvKGZ1bGxGaWx0ZXIpKSB7XHJcbiAgICAgIGNvbnN0IG51bWVyaWNGaWx0ZXIgPSBmdWxsRmlsdGVyIGFzIE51bWVyaWNQcm9wZXJ0eUluZm9cclxuICAgICAgY29uc3QgeyBtaW4sIG1heCB9ID0gbnVtZXJpY0ZpbHRlclxyXG4gICAgICBjb25zdCByYW5nZSA9IG1heCAtIG1pblxyXG5cclxuICAgICAgLy8gSGFuZGxlIGZpbHRlcnMgd2l0aCBtZWFuaW5nbGVzcyByYW5nZXMgYnkgZGVmYXVsdGluZyB0byBleGlzdGVuY2UtYmFzZWQgZmlsdGVyaW5nXHJcbiAgICAgIGNvbnN0IE1JTl9NRUFOSU5HRlVMX1JBTkdFID0gMWUtMTBcclxuICAgICAgY29uc3QgaGFzQ29uc3RhbnRWYWx1ZSA9IHJhbmdlID09PSAwXHJcbiAgICAgIGNvbnN0IGhhc05lYXJaZXJvUmFuZ2UgPSByYW5nZSA+IDAgJiYgcmFuZ2UgPCBNSU5fTUVBTklOR0ZVTF9SQU5HRVxyXG5cclxuICAgICAgaWYgKGhhc0NvbnN0YW50VmFsdWUgfHwgaGFzTmVhclplcm9SYW5nZSkge1xyXG4gICAgICAgIGNvbnN0IHJlYXNvbiA9IGhhc0NvbnN0YW50VmFsdWVcclxuICAgICAgICAgID8gYEFsbCBvYmplY3RzIGhhdmUgdGhlIHNhbWUgdmFsdWUgKCR7bWlufSlgXHJcbiAgICAgICAgICA6IGBSYW5nZSB0b28gc21hbGwgZm9yIG1lYW5pbmdmdWwgZmlsdGVyaW5nICgke3JhbmdlLnRvRXhwb25lbnRpYWwoKX0pYFxyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgaWQsXHJcbiAgICAgICAgICBpc0FwcGxpZWQ6IHRydWUsXHJcbiAgICAgICAgICBzZWxlY3RlZFZhbHVlczogW10sXHJcbiAgICAgICAgICBjb25kaXRpb246IEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbi5Jc1NldCxcclxuICAgICAgICAgIHR5cGU6IEZpbHRlclR5cGUuTnVtZXJpYyxcclxuICAgICAgICAgIGZpbHRlcjogbnVtZXJpY0ZpbHRlcixcclxuICAgICAgICAgIG51bWVyaWNSYW5nZTogeyBtaW4sIG1heCB9LFxyXG4gICAgICAgICAgaGFzQ29uc3RhbnRWYWx1ZSxcclxuICAgICAgICAgIGhhc05lYXJaZXJvUmFuZ2UsXHJcbiAgICAgICAgICByYW5nZURpc2FibGVkUmVhc29uOiByZWFzb25cclxuICAgICAgICB9IGFzIE51bWVyaWNGaWx0ZXJEYXRhXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHJldHVybiB7XHJcbiAgICAgICAgaWQsXHJcbiAgICAgICAgaXNBcHBsaWVkOiB0cnVlLFxyXG4gICAgICAgIHNlbGVjdGVkVmFsdWVzOiBbXSxcclxuICAgICAgICBjb25kaXRpb246IE51bWVyaWNGaWx0ZXJDb25kaXRpb24uSXNCZXR3ZWVuLFxyXG4gICAgICAgIHR5cGU6IEZpbHRlclR5cGUuTnVtZXJpYyxcclxuICAgICAgICBmaWx0ZXI6IG51bWVyaWNGaWx0ZXIsXHJcbiAgICAgICAgbnVtZXJpY1JhbmdlOiB7IG1pbiwgbWF4IH1cclxuICAgICAgfSBhcyBOdW1lcmljRmlsdGVyRGF0YVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgcmV0dXJuIHtcclxuICAgICAgICBpZCxcclxuICAgICAgICBpc0FwcGxpZWQ6IHRydWUsXHJcbiAgICAgICAgc2VsZWN0ZWRWYWx1ZXM6IFtdLFxyXG4gICAgICAgIGNvbmRpdGlvbjogU3RyaW5nRmlsdGVyQ29uZGl0aW9uLklzLFxyXG4gICAgICAgIHR5cGU6IEZpbHRlclR5cGUuU3RyaW5nLFxyXG4gICAgICAgIGZpbHRlcjogZnVsbEZpbHRlciBhcyBTdHJpbmdQcm9wZXJ0eUluZm8sXHJcbiAgICAgICAgaXNEZWZhdWx0QWxsU2VsZWN0ZWQ6IHRydWVcclxuICAgICAgfSBhcyBTdHJpbmdGaWx0ZXJEYXRhXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb25zdCBhZGRBY3RpdmVGaWx0ZXIgPSAoZmlsdGVyOiBFeHRlbmRlZFByb3BlcnR5SW5mbywgaWQ/OiBzdHJpbmcpOiBzdHJpbmcgPT4ge1xyXG4gICAgY29uc3QgZXhpc3RpbmdJbmRleCA9IGZpbHRlcnMucHJvcGVydHlGaWx0ZXJzLnZhbHVlLmZpbmRJbmRleChcclxuICAgICAgKGYpID0+IGYuZmlsdGVyPy5rZXkgPT09IGZpbHRlci5rZXlcclxuICAgIClcclxuXHJcbiAgICBpZiAoZXhpc3RpbmdJbmRleCAhPT0gLTEpIHtcclxuICAgICAgcmV0dXJuIGZpbHRlcnMucHJvcGVydHlGaWx0ZXJzLnZhbHVlW2V4aXN0aW5nSW5kZXhdLmlkXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZCB8fD0gYGZpbHRlci0ke0RhdGUubm93KCl9LSR7TWF0aC5yYW5kb20oKS50b1N0cmluZygzNikuc3Vic3RyKDIsIDkpfWBcclxuXHJcbiAgICAgIGNvbnN0IGZpbHRlckRhdGEgPSBjcmVhdGVGaWx0ZXJEYXRhKHsgZmlsdGVyLCBpZCB9KVxyXG4gICAgICBmaWx0ZXJzLnByb3BlcnR5RmlsdGVycy52YWx1ZS5wdXNoKGZpbHRlckRhdGEpXHJcblxyXG4gICAgICB1cGRhdGVEYXRhU3RvcmVTbGljZXMoKVxyXG4gICAgICByZXR1cm4gaWRcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFVwZGF0ZXMgdGhlIHByb3BlcnR5IG9mIGFuIGV4aXN0aW5nIGZpbHRlciB3aGlsZSBwcmVzZXJ2aW5nIGl0cyBwb3NpdGlvbiBhbmQgc2V0dGluZ3NcclxuICAgKi9cclxuICBjb25zdCB1cGRhdGVGaWx0ZXJQcm9wZXJ0eSA9IChcclxuICAgIGZpbHRlcklkOiBzdHJpbmcsXHJcbiAgICBuZXdQcm9wZXJ0eTogRXh0ZW5kZWRQcm9wZXJ0eUluZm9cclxuICApOiBib29sZWFuID0+IHtcclxuICAgIGNvbnN0IGZpbHRlckluZGV4ID0gZmlsdGVycy5wcm9wZXJ0eUZpbHRlcnMudmFsdWUuZmluZEluZGV4KFxyXG4gICAgICAoZikgPT4gZi5pZCA9PT0gZmlsdGVySWRcclxuICAgIClcclxuICAgIGlmIChmaWx0ZXJJbmRleCA9PT0gLTEpIHJldHVybiBmYWxzZVxyXG5cclxuICAgIGNvbnN0IG5ld0ZpbHRlckRhdGEgPSBjcmVhdGVGaWx0ZXJEYXRhKHtcclxuICAgICAgZmlsdGVyOiBuZXdQcm9wZXJ0eSxcclxuICAgICAgaWQ6IGZpbHRlcklkXHJcbiAgICB9KVxyXG5cclxuICAgIGlmIChmaWx0ZXJzLmFjdGl2ZUNvbG9yRmlsdGVySWQudmFsdWUgPT09IGZpbHRlcklkKSB7XHJcbiAgICAgIHJlbW92ZUNvbG9yRmlsdGVyKClcclxuICAgIH1cclxuXHJcbiAgICBmaWx0ZXJzLnByb3BlcnR5RmlsdGVycy52YWx1ZVtmaWx0ZXJJbmRleF0gPSBuZXdGaWx0ZXJEYXRhXHJcblxyXG4gICAgdXBkYXRlRGF0YVN0b3JlU2xpY2VzKClcclxuICAgIHJldHVybiB0cnVlXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBSZW1vdmVzIGFuIGFjdGl2ZSBmaWx0ZXIgYnkgSURcclxuICAgKi9cclxuICBjb25zdCByZW1vdmVBY3RpdmVGaWx0ZXIgPSAoZmlsdGVySWQ6IHN0cmluZykgPT4ge1xyXG4gICAgY29uc3QgaW5kZXggPSBmaWx0ZXJzLnByb3BlcnR5RmlsdGVycy52YWx1ZS5maW5kSW5kZXgoKGYpID0+IGYuaWQgPT09IGZpbHRlcklkKVxyXG4gICAgaWYgKGluZGV4ICE9PSAtMSkge1xyXG4gICAgICBpZiAoZmlsdGVycy5hY3RpdmVDb2xvckZpbHRlcklkLnZhbHVlID09PSBmaWx0ZXJJZCkge1xyXG4gICAgICAgIHJlbW92ZUNvbG9yRmlsdGVyKClcclxuICAgICAgfVxyXG4gICAgICBmaWx0ZXJzLnByb3BlcnR5RmlsdGVycy52YWx1ZS5zcGxpY2UoaW5kZXgsIDEpXHJcbiAgICAgIHVwZGF0ZURhdGFTdG9yZVNsaWNlcygpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUb2dnbGVzIHRoZSBhcHBsaWVkIHN0YXRlIG9mIGEgc3BlY2lmaWMgZmlsdGVyXHJcbiAgICovXHJcbiAgY29uc3QgdG9nZ2xlRmlsdGVyQXBwbGllZCA9IChmaWx0ZXJJZDogc3RyaW5nKSA9PiB7XHJcbiAgICBjb25zdCBmaWx0ZXIgPSBmaWx0ZXJzLnByb3BlcnR5RmlsdGVycy52YWx1ZS5maW5kKChmKSA9PiBmLmlkID09PSBmaWx0ZXJJZClcclxuICAgIGlmIChmaWx0ZXIpIHtcclxuICAgICAgZmlsdGVyLmlzQXBwbGllZCA9ICFmaWx0ZXIuaXNBcHBsaWVkXHJcbiAgICAgIHVwZGF0ZURhdGFTdG9yZVNsaWNlcygpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGVzIHNlbGVjdGVkIHZhbHVlcyBmb3IgYSBzcGVjaWZpYyBhY3RpdmUgZmlsdGVyXHJcbiAgICovXHJcbiAgY29uc3QgdXBkYXRlQWN0aXZlRmlsdGVyVmFsdWVzID0gKGZpbHRlcklkOiBzdHJpbmcsIHZhbHVlczogc3RyaW5nW10pID0+IHtcclxuICAgIGNsZWFySGlnaGxpZ2h0ZWRPYmplY3RzKClcclxuICAgIGNsZWFyU2VsZWN0aW9uKClcclxuXHJcbiAgICBjb25zdCBmaWx0ZXIgPSBmaWx0ZXJzLnByb3BlcnR5RmlsdGVycy52YWx1ZS5maW5kKChmKSA9PiBmLmlkID09PSBmaWx0ZXJJZClcclxuICAgIGlmIChmaWx0ZXIpIHtcclxuICAgICAgZmlsdGVyLnNlbGVjdGVkVmFsdWVzID0gWy4uLnZhbHVlc11cclxuXHJcbiAgICAgIGlmIChcclxuICAgICAgICAhaXNOdW1lcmljRmlsdGVyKGZpbHRlcikgJiZcclxuICAgICAgICAhaXNCb29sZWFuRmlsdGVyKGZpbHRlcikgJiZcclxuICAgICAgICBmaWx0ZXIuaXNEZWZhdWx0QWxsU2VsZWN0ZWRcclxuICAgICAgKSB7XHJcbiAgICAgICAgZmlsdGVyLmlzRGVmYXVsdEFsbFNlbGVjdGVkID0gZmFsc2VcclxuICAgICAgfVxyXG5cclxuICAgICAgdXBkYXRlRGF0YVN0b3JlU2xpY2VzKClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEVmZmljaWVudGx5IHNlbGVjdHMgYWxsIHZhbHVlcyBieSB1c2luZyB2YWx1ZUdyb3VwcyBkaXJlY3RseSBpbnN0ZWFkIG9mIGV4cGVuc2l2ZSBnZXRBbGxQcm9wZXJ0eVZhbHVlc1xyXG4gICAqL1xyXG4gIGNvbnN0IHNlbGVjdEFsbEZpbHRlclZhbHVlcyA9IChmaWx0ZXJJZDogc3RyaW5nKSA9PiB7XHJcbiAgICBjbGVhckhpZ2hsaWdodGVkT2JqZWN0cygpXHJcbiAgICBjbGVhclNlbGVjdGlvbigpXHJcblxyXG4gICAgY29uc3QgZmlsdGVyID0gZmlsdGVycy5wcm9wZXJ0eUZpbHRlcnMudmFsdWUuZmluZCgoZikgPT4gZi5pZCA9PT0gZmlsdGVySWQpXHJcbiAgICBpZiAoZmlsdGVyICYmICFpc051bWVyaWNGaWx0ZXIoZmlsdGVyKSkge1xyXG4gICAgICBjb25zdCBwcm9wZXJ0eUZpbHRlciA9IGZpbHRlci5maWx0ZXJcclxuXHJcbiAgICAgIGlmIChcclxuICAgICAgICAndmFsdWVHcm91cHMnIGluIHByb3BlcnR5RmlsdGVyICYmXHJcbiAgICAgICAgQXJyYXkuaXNBcnJheShwcm9wZXJ0eUZpbHRlci52YWx1ZUdyb3VwcylcclxuICAgICAgKSB7XHJcbiAgICAgICAgZmlsdGVyLnNlbGVjdGVkVmFsdWVzID0gcHJvcGVydHlGaWx0ZXIudmFsdWVHcm91cHNcclxuICAgICAgICAgIC5tYXAoKHZnOiB7IHZhbHVlOiB1bmtub3duIH0pID0+IFN0cmluZyh2Zy52YWx1ZSkpXHJcbiAgICAgICAgICAuZmlsdGVyKFxyXG4gICAgICAgICAgICAodjogc3RyaW5nKSA9PlxyXG4gICAgICAgICAgICAgIHYgIT09IG51bGwgJiYgdiAhPT0gdW5kZWZpbmVkICYmIHYgIT09ICdudWxsJyAmJiB2ICE9PSAndW5kZWZpbmVkJ1xyXG4gICAgICAgICAgKVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIEZhbGxiYWNrIGZvciBlZGdlIGNhc2VzXHJcbiAgICAgICAgY29uc3QgYWxsVmFsdWVzID0gZ2V0QWxsUHJvcGVydHlWYWx1ZXMocHJvcGVydHlGaWx0ZXIua2V5KVxyXG4gICAgICAgIGZpbHRlci5zZWxlY3RlZFZhbHVlcyA9IFsuLi5hbGxWYWx1ZXNdXHJcbiAgICAgIH1cclxuICAgICAgaWYgKCFpc0Jvb2xlYW5GaWx0ZXIoZmlsdGVyKSkge1xyXG4gICAgICAgIGZpbHRlci5pc0RlZmF1bHRBbGxTZWxlY3RlZCA9IGZhbHNlXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHVwZGF0ZURhdGFTdG9yZVNsaWNlcygpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGVzIGNvbmRpdGlvbiBmb3IgYSBzcGVjaWZpYyBhY3RpdmUgZmlsdGVyXHJcbiAgICovXHJcbiAgY29uc3QgdXBkYXRlRmlsdGVyQ29uZGl0aW9uID0gKGZpbHRlcklkOiBzdHJpbmcsIGNvbmRpdGlvbjogRmlsdGVyQ29uZGl0aW9uKSA9PiB7XHJcbiAgICBjbGVhckhpZ2hsaWdodGVkT2JqZWN0cygpXHJcbiAgICBjbGVhclNlbGVjdGlvbigpXHJcblxyXG4gICAgY29uc3QgZmlsdGVyID0gZmlsdGVycy5wcm9wZXJ0eUZpbHRlcnMudmFsdWUuZmluZCgoZikgPT4gZi5pZCA9PT0gZmlsdGVySWQpXHJcbiAgICBpZiAoZmlsdGVyKSB7XHJcbiAgICAgIGZpbHRlci5jb25kaXRpb24gPSBjb25kaXRpb25cclxuXHJcbiAgICAgIGlmIChcclxuICAgICAgICBjb25kaXRpb24gPT09IEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbi5Jc1NldCB8fFxyXG4gICAgICAgIGNvbmRpdGlvbiA9PT0gRXhpc3RlbmNlRmlsdGVyQ29uZGl0aW9uLklzTm90U2V0XHJcbiAgICAgICkge1xyXG4gICAgICAgIGZpbHRlci5pc0FwcGxpZWQgPSB0cnVlXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHVwZGF0ZURhdGFTdG9yZVNsaWNlcygpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIG51bWVyaWMgcmFuZ2UgZm9yIGEgZmlsdGVyXHJcbiAgICovXHJcbiAgY29uc3Qgc2V0TnVtZXJpY1JhbmdlID0gKGZpbHRlcklkOiBzdHJpbmcsIG1pbjogbnVtYmVyLCBtYXg6IG51bWJlcikgPT4ge1xyXG4gICAgY2xlYXJIaWdobGlnaHRlZE9iamVjdHMoKVxyXG4gICAgY2xlYXJTZWxlY3Rpb24oKVxyXG5cclxuICAgIGNvbnN0IGZpbHRlciA9IGZpbHRlcnMucHJvcGVydHlGaWx0ZXJzLnZhbHVlLmZpbmQoKGYpID0+IGYuaWQgPT09IGZpbHRlcklkKVxyXG4gICAgaWYgKGZpbHRlciAmJiBpc051bWVyaWNGaWx0ZXIoZmlsdGVyKSkge1xyXG4gICAgICBjb25zdCByb3VuZGVkTWluID0gcGFyc2VGbG9hdChtaW4udG9GaXhlZCg0KSlcclxuICAgICAgY29uc3Qgcm91bmRlZE1heCA9IHBhcnNlRmxvYXQobWF4LnRvRml4ZWQoNCkpXHJcblxyXG4gICAgICBmaWx0ZXIubnVtZXJpY1JhbmdlID0geyBtaW46IHJvdW5kZWRNaW4sIG1heDogcm91bmRlZE1heCB9XHJcblxyXG4gICAgICBpZiAoIWZpbHRlci5pc0FwcGxpZWQpIHtcclxuICAgICAgICBmaWx0ZXIuaXNBcHBsaWVkID0gdHJ1ZVxyXG4gICAgICB9XHJcbiAgICAgIHVwZGF0ZURhdGFTdG9yZVNsaWNlcygpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBTZXRzIGZpbHRlciBsb2dpYyBhbmQgdXBkYXRlcyBzbGljZXNcclxuICAgKi9cclxuICBjb25zdCBzZXRGaWx0ZXJMb2dpYyA9IChsb2dpYzogRmlsdGVyTG9naWMpID0+IHtcclxuICAgIGRhdGFTdG9yZS5zZXRGaWx0ZXJMb2dpYyhsb2dpYylcclxuICAgIHVwZGF0ZURhdGFTdG9yZVNsaWNlcygpXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBVcGRhdGVzIGRhdGEgc3RvcmUgc2xpY2VzIGJhc2VkIG9uIGN1cnJlbnQgZmlsdGVyIHN0YXRlIChvcHRpbWl6ZWQpXHJcbiAgICovXHJcbiAgY29uc3QgdXBkYXRlRGF0YVN0b3JlU2xpY2VzID0gKCkgPT4ge1xyXG4gICAgY29uc3Qgbm9uRmlsdGVyU2xpY2VzID0gZGF0YVN0b3JlLmRhdGFTbGljZXMudmFsdWUuZmlsdGVyKFxyXG4gICAgICAoc2xpY2UpID0+ICFzbGljZS5pZC5zdGFydHNXaXRoKCdmaWx0ZXItJylcclxuICAgIClcclxuICAgIGRhdGFTdG9yZS5kYXRhU2xpY2VzLnZhbHVlID0gbm9uRmlsdGVyU2xpY2VzXHJcblxyXG4gICAgY29uc3QgbmV3RmlsdGVyU2xpY2VzOiBEYXRhU2xpY2VbXSA9IFtdXHJcblxyXG4gICAgZmlsdGVycy5wcm9wZXJ0eUZpbHRlcnMudmFsdWUuZm9yRWFjaCgoZmlsdGVyKSA9PiB7XHJcbiAgICAgIGlmIChpc051bWVyaWNGaWx0ZXIoZmlsdGVyKSAmJiBmaWx0ZXIuaXNBcHBsaWVkKSB7XHJcbiAgICAgICAgY29uc3QgcXVlcnlDcml0ZXJpYTogUXVlcnlDcml0ZXJpYSA9IHtcclxuICAgICAgICAgIHByb3BlcnR5S2V5OiBmaWx0ZXIuZmlsdGVyLmtleSxcclxuICAgICAgICAgIGNvbmRpdGlvbjogZmlsdGVyLmNvbmRpdGlvbixcclxuICAgICAgICAgIHZhbHVlczogW10sXHJcbiAgICAgICAgICBtaW5WYWx1ZTogZmlsdGVyLm51bWVyaWNSYW5nZS5taW4sXHJcbiAgICAgICAgICBtYXhWYWx1ZTogZmlsdGVyLm51bWVyaWNSYW5nZS5tYXhcclxuICAgICAgICB9XHJcbiAgICAgICAgY29uc3QgbWF0Y2hpbmdPYmplY3RJZHMgPSBkYXRhU3RvcmUucXVlcnlPYmplY3RzKHF1ZXJ5Q3JpdGVyaWEpXHJcblxyXG4gICAgICAgIGNvbnN0IHNsaWNlOiBEYXRhU2xpY2UgPSB7XHJcbiAgICAgICAgICBpZDogYGZpbHRlci0ke2ZpbHRlci5pZH1gLFxyXG4gICAgICAgICAgd2lkZ2V0SWQ6IGZpbHRlci5pZCxcclxuICAgICAgICAgIG5hbWU6XHJcbiAgICAgICAgICAgIGZpbHRlci5jb25kaXRpb24gPT09IEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbi5Jc1NldFxyXG4gICAgICAgICAgICAgID8gYCR7Z2V0UHJvcGVydHlOYW1lKGZpbHRlci5maWx0ZXIua2V5KX0gaXMgc2V0YFxyXG4gICAgICAgICAgICAgIDogZmlsdGVyLmNvbmRpdGlvbiA9PT0gRXhpc3RlbmNlRmlsdGVyQ29uZGl0aW9uLklzTm90U2V0XHJcbiAgICAgICAgICAgICAgPyBgJHtnZXRQcm9wZXJ0eU5hbWUoZmlsdGVyLmZpbHRlci5rZXkpfSBpcyBub3Qgc2V0YFxyXG4gICAgICAgICAgICAgIDogYCR7Z2V0UHJvcGVydHlOYW1lKGZpbHRlci5maWx0ZXIua2V5KX0gJHtnZXRDb25kaXRpb25MYWJlbChcclxuICAgICAgICAgICAgICAgICAgZmlsdGVyLmNvbmRpdGlvblxyXG4gICAgICAgICAgICAgICAgKX0gKCR7ZmlsdGVyLm51bWVyaWNSYW5nZS5taW4udG9GaXhlZChcclxuICAgICAgICAgICAgICAgICAgMlxyXG4gICAgICAgICAgICAgICAgKX0gLSAke2ZpbHRlci5udW1lcmljUmFuZ2UubWF4LnRvRml4ZWQoMil9KWAsXHJcbiAgICAgICAgICBvYmplY3RJZHM6IG1hdGNoaW5nT2JqZWN0SWRzXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBuZXdGaWx0ZXJTbGljZXMucHVzaChzbGljZSlcclxuICAgICAgfSBlbHNlIGlmIChpc0Jvb2xlYW5GaWx0ZXIoZmlsdGVyKSAmJiBmaWx0ZXIuaXNBcHBsaWVkKSB7XHJcbiAgICAgICAgY29uc3QgeyBjb25kaXRpb24gfSA9IGZpbHRlclxyXG4gICAgICAgIGNvbnN0IHF1ZXJ5Q3JpdGVyaWE6IFF1ZXJ5Q3JpdGVyaWEgPSB7XHJcbiAgICAgICAgICBwcm9wZXJ0eUtleTogZmlsdGVyLmZpbHRlci5rZXksXHJcbiAgICAgICAgICBjb25kaXRpb24sXHJcbiAgICAgICAgICB2YWx1ZXM6IFtdXHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IG1hdGNoaW5nT2JqZWN0SWRzID0gZGF0YVN0b3JlLnF1ZXJ5T2JqZWN0cyhxdWVyeUNyaXRlcmlhKVxyXG5cclxuICAgICAgICBjb25zdCBzbGljZTogRGF0YVNsaWNlID0ge1xyXG4gICAgICAgICAgaWQ6IGBmaWx0ZXItJHtmaWx0ZXIuaWR9YCxcclxuICAgICAgICAgIHdpZGdldElkOiBmaWx0ZXIuaWQsXHJcbiAgICAgICAgICBuYW1lOiBgJHtnZXRQcm9wZXJ0eU5hbWUoZmlsdGVyLmZpbHRlci5rZXkpfSAke2dldENvbmRpdGlvbkxhYmVsKGNvbmRpdGlvbil9YCxcclxuICAgICAgICAgIG9iamVjdElkczogbWF0Y2hpbmdPYmplY3RJZHNcclxuICAgICAgICB9XHJcbiAgICAgICAgbmV3RmlsdGVyU2xpY2VzLnB1c2goc2xpY2UpXHJcbiAgICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgICAgIWlzTnVtZXJpY0ZpbHRlcihmaWx0ZXIpICYmXHJcbiAgICAgICAgIWlzQm9vbGVhbkZpbHRlcihmaWx0ZXIpICYmXHJcbiAgICAgICAgZmlsdGVyLmlzQXBwbGllZCAmJlxyXG4gICAgICAgIChmaWx0ZXIuc2VsZWN0ZWRWYWx1ZXMubGVuZ3RoID4gMCB8fFxyXG4gICAgICAgICAgZmlsdGVyLmlzRGVmYXVsdEFsbFNlbGVjdGVkIHx8XHJcbiAgICAgICAgICBmaWx0ZXIuY29uZGl0aW9uID09PSBFeGlzdGVuY2VGaWx0ZXJDb25kaXRpb24uSXNTZXQgfHxcclxuICAgICAgICAgIGZpbHRlci5jb25kaXRpb24gPT09IEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbi5Jc05vdFNldClcclxuICAgICAgKSB7XHJcbiAgICAgICAgY29uc3QgdmFsdWVzID1cclxuICAgICAgICAgIGZpbHRlci5pc0RlZmF1bHRBbGxTZWxlY3RlZCAmJiBmaWx0ZXIuc2VsZWN0ZWRWYWx1ZXMubGVuZ3RoID09PSAwXHJcbiAgICAgICAgICAgID8gZmlsdGVyLmZpbHRlci52YWx1ZUdyb3Vwc1xyXG4gICAgICAgICAgICAgICAgPy5tYXAoKHZnKSA9PiBTdHJpbmcodmcudmFsdWUpKVxyXG4gICAgICAgICAgICAgICAgLmZpbHRlcigodikgPT4gdiAhPT0gJ251bGwnICYmIHYgIT09ICd1bmRlZmluZWQnKSB8fCBbXVxyXG4gICAgICAgICAgICA6IGZpbHRlci5zZWxlY3RlZFZhbHVlc1xyXG5cclxuICAgICAgICBjb25zdCB7IGNvbmRpdGlvbiB9ID0gZmlsdGVyXHJcbiAgICAgICAgY29uc3QgcXVlcnlDcml0ZXJpYTogUXVlcnlDcml0ZXJpYSA9IHtcclxuICAgICAgICAgIHByb3BlcnR5S2V5OiBmaWx0ZXIuZmlsdGVyLmtleSxcclxuICAgICAgICAgIGNvbmRpdGlvbixcclxuICAgICAgICAgIHZhbHVlc1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBtYXRjaGluZ09iamVjdElkcyA9IGRhdGFTdG9yZS5xdWVyeU9iamVjdHMocXVlcnlDcml0ZXJpYSlcclxuXHJcbiAgICAgICAgY29uc3Qgc2xpY2U6IERhdGFTbGljZSA9IHtcclxuICAgICAgICAgIGlkOiBgZmlsdGVyLSR7ZmlsdGVyLmlkfWAsXHJcbiAgICAgICAgICB3aWRnZXRJZDogZmlsdGVyLmlkLFxyXG4gICAgICAgICAgbmFtZTpcclxuICAgICAgICAgICAgZmlsdGVyLmNvbmRpdGlvbiA9PT0gRXhpc3RlbmNlRmlsdGVyQ29uZGl0aW9uLklzU2V0XHJcbiAgICAgICAgICAgICAgPyBgJHtnZXRQcm9wZXJ0eU5hbWUoZmlsdGVyLmZpbHRlci5rZXkpfSBpcyBzZXRgXHJcbiAgICAgICAgICAgICAgOiBmaWx0ZXIuY29uZGl0aW9uID09PSBFeGlzdGVuY2VGaWx0ZXJDb25kaXRpb24uSXNOb3RTZXRcclxuICAgICAgICAgICAgICA/IGAke2dldFByb3BlcnR5TmFtZShmaWx0ZXIuZmlsdGVyLmtleSl9IGlzIG5vdCBzZXRgXHJcbiAgICAgICAgICAgICAgOiBgJHtnZXRQcm9wZXJ0eU5hbWUoZmlsdGVyLmZpbHRlci5rZXkpfSAke1xyXG4gICAgICAgICAgICAgICAgICBmaWx0ZXIuY29uZGl0aW9uID09PSBTdHJpbmdGaWx0ZXJDb25kaXRpb24uSXMgPyAnaXMnIDogJ2lzIG5vdCdcclxuICAgICAgICAgICAgICAgIH0gJHtcclxuICAgICAgICAgICAgICAgICAgZmlsdGVyLmlzRGVmYXVsdEFsbFNlbGVjdGVkICYmIGZpbHRlci5zZWxlY3RlZFZhbHVlcy5sZW5ndGggPT09IDBcclxuICAgICAgICAgICAgICAgICAgICA/ICdhbGwgdmFsdWVzJ1xyXG4gICAgICAgICAgICAgICAgICAgIDogZmlsdGVyLnNlbGVjdGVkVmFsdWVzLmpvaW4oJywgJylcclxuICAgICAgICAgICAgICAgIH1gLFxyXG4gICAgICAgICAgb2JqZWN0SWRzOiBtYXRjaGluZ09iamVjdElkc1xyXG4gICAgICAgIH1cclxuICAgICAgICBuZXdGaWx0ZXJTbGljZXMucHVzaChzbGljZSlcclxuICAgICAgfVxyXG4gICAgfSlcclxuXHJcbiAgICBkYXRhU3RvcmUuZGF0YVNsaWNlcy52YWx1ZS5wdXNoKC4uLm5ld0ZpbHRlclNsaWNlcylcclxuICAgIGRhdGFTdG9yZS5jb21wdXRlU2xpY2VJbnRlcnNlY3Rpb25zKClcclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIFRvZ2dsZXMgYSB2YWx1ZSBmb3IgYSBzcGVjaWZpYyBhY3RpdmUgZmlsdGVyXHJcbiAgICovXHJcbiAgY29uc3QgdG9nZ2xlQWN0aXZlRmlsdGVyVmFsdWUgPSAoZmlsdGVySWQ6IHN0cmluZywgdmFsdWU6IHN0cmluZykgPT4ge1xyXG4gICAgY2xlYXJIaWdobGlnaHRlZE9iamVjdHMoKVxyXG4gICAgY2xlYXJTZWxlY3Rpb24oKVxyXG5cclxuICAgIGNvbnN0IGZpbHRlciA9IGZpbHRlcnMucHJvcGVydHlGaWx0ZXJzLnZhbHVlLmZpbmQoKGYpID0+IGYuaWQgPT09IGZpbHRlcklkKVxyXG4gICAgaWYgKGZpbHRlcikge1xyXG4gICAgICBjb25zdCBpbmRleCA9IGZpbHRlci5zZWxlY3RlZFZhbHVlcy5pbmRleE9mKHZhbHVlKVxyXG4gICAgICBjb25zdCB3YXNTZWxlY3RlZCA9IGluZGV4ID4gLTFcclxuXHJcbiAgICAgIGlmIChcclxuICAgICAgICAhaXNOdW1lcmljRmlsdGVyKGZpbHRlcikgJiZcclxuICAgICAgICAhaXNCb29sZWFuRmlsdGVyKGZpbHRlcikgJiZcclxuICAgICAgICBmaWx0ZXIuaXNEZWZhdWx0QWxsU2VsZWN0ZWRcclxuICAgICAgKSB7XHJcbiAgICAgICAgZmlsdGVyLnNlbGVjdGVkVmFsdWVzID0gW3ZhbHVlXVxyXG4gICAgICAgIGZpbHRlci5pc0RlZmF1bHRBbGxTZWxlY3RlZCA9IGZhbHNlXHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgaWYgKHdhc1NlbGVjdGVkKSB7XHJcbiAgICAgICAgICBmaWx0ZXIuc2VsZWN0ZWRWYWx1ZXMuc3BsaWNlKGluZGV4LCAxKVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBmaWx0ZXIuc2VsZWN0ZWRWYWx1ZXMucHVzaCh2YWx1ZSlcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgICAgdXBkYXRlRGF0YVN0b3JlU2xpY2VzKClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIENoZWNrcyBpZiBhIHZhbHVlIGlzIHNlbGVjdGVkIGZvciBhIHNwZWNpZmljIGFjdGl2ZSBmaWx0ZXJcclxuICAgKi9cclxuICBjb25zdCBpc0FjdGl2ZUZpbHRlclZhbHVlU2VsZWN0ZWQgPSAoZmlsdGVySWQ6IHN0cmluZywgdmFsdWU6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xyXG4gICAgY29uc3QgZmlsdGVyID0gZmlsdGVycy5wcm9wZXJ0eUZpbHRlcnMudmFsdWUuZmluZCgoZikgPT4gZi5pZCA9PT0gZmlsdGVySWQpXHJcbiAgICByZXR1cm4gZmlsdGVyID8gZmlsdGVyLnNlbGVjdGVkVmFsdWVzLmluY2x1ZGVzKHZhbHVlKSA6IGZhbHNlXHJcbiAgfVxyXG5cclxuICBjb25zdCByZXNldEZpbHRlcnMgPSAoKSA9PiB7XHJcbiAgICBjbGVhckhpZ2hsaWdodGVkT2JqZWN0cygpXHJcbiAgICBjbGVhclNlbGVjdGlvbigpXHJcblxyXG4gICAgZmlsdGVycy5wcm9wZXJ0eUZpbHRlcnMudmFsdWUgPSBbXVxyXG4gICAgZmlsdGVycy5zZWxlY3RlZE9iamVjdHMudmFsdWUgPSBbXVxyXG4gICAgZmlsdGVycy5hY3RpdmVDb2xvckZpbHRlcklkLnZhbHVlID0gbnVsbFxyXG5cclxuICAgIGRhdGFTdG9yZS5zZXRGaWx0ZXJMb2dpYyhGaWx0ZXJMb2dpYy5BbGwpXHJcblxyXG4gICAgY29uc3Qgbm9uRmlsdGVyU2xpY2VzID0gZGF0YVN0b3JlLmRhdGFTbGljZXMudmFsdWUuZmlsdGVyKFxyXG4gICAgICAoc2xpY2UpID0+ICFzbGljZS5pZC5zdGFydHNXaXRoKCdmaWx0ZXItJylcclxuICAgIClcclxuICAgIGRhdGFTdG9yZS5kYXRhU2xpY2VzLnZhbHVlID0gbm9uRmlsdGVyU2xpY2VzXHJcblxyXG4gICAgaWYgKG5vbkZpbHRlclNsaWNlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIGRhdGFTdG9yZS5jb21wdXRlU2xpY2VJbnRlcnNlY3Rpb25zKClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IHJlc2V0RXhwbG9kZSA9ICgpID0+IHtcclxuICAgIGV4cGxvZGVGYWN0b3IudmFsdWUgPSAwXHJcbiAgfVxyXG5cclxuICAvLyBTdG9yZSBmaWx0ZXJzIHRoYXQgbmVlZCB0byBiZSByZXN0b3JlZCBvbmNlIGRhdGEgc3RvcmUgaXMgcmVhZHlcclxuICBjb25zdCBwZW5kaW5nRmlsdGVyc1RvUmVzdG9yZSA9IHJlZjx7XHJcbiAgICBmaWx0ZXJzOiBTZXJpYWxpemVkRmlsdGVyRGF0YVtdXHJcbiAgICBhY3RpdmVDb2xvckZpbHRlcklkOiBzdHJpbmcgfCBudWxsXHJcbiAgICBmaWx0ZXJMb2dpYz86IEZpbHRlckxvZ2ljXHJcbiAgfSB8IG51bGw+KG51bGwpXHJcblxyXG4gIC8qKlxyXG4gICAqIFJlc3RvcmVzIGZpbHRlcnMgZnJvbSBzZXJpYWxpemVkIHN0YXRlXHJcbiAgICovXHJcbiAgY29uc3QgcmVzdG9yZUZpbHRlcnMgPSBhc3luYyAoXHJcbiAgICBzZXJpYWxpemVkRmlsdGVyczogU2VyaWFsaXplZEZpbHRlckRhdGFbXSxcclxuICAgIGFjdGl2ZUNvbG9yRmlsdGVySWQ6IHN0cmluZyB8IG51bGwsXHJcbiAgICBmaWx0ZXJMb2dpYz86IEZpbHRlckxvZ2ljXHJcbiAgKSA9PiB7XHJcbiAgICBpZiAoIXNlcmlhbGl6ZWRGaWx0ZXJzPy5sZW5ndGgpIHJldHVyblxyXG5cclxuICAgIHJlc2V0RmlsdGVycygpIC8vIENsZWFyIGV4aXN0aW5nIGZpbHRlcnMgZmlyc3RcclxuXHJcbiAgICBjb25zdCBhdmFpbGFibGVQcm9wZXJ0aWVzID0gZ2V0UHJvcGVydHlPcHRpb25zRnJvbURhdGFTdG9yZSgpXHJcblxyXG4gICAgLy8gSWYgZGF0YSBzdG9yZSBpcyByZWFkeSwgcmVzdG9yZSBpbW1lZGlhdGVseVxyXG4gICAgaWYgKGF2YWlsYWJsZVByb3BlcnRpZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICBhcHBseUZpbHRlcnNGcm9tU2VyaWFsaXplZChzZXJpYWxpemVkRmlsdGVycywgYXZhaWxhYmxlUHJvcGVydGllcylcclxuICAgICAgZmlsdGVycy5hY3RpdmVDb2xvckZpbHRlcklkLnZhbHVlID0gYWN0aXZlQ29sb3JGaWx0ZXJJZFxyXG5cclxuICAgICAgaWYgKGZpbHRlckxvZ2ljKSB7XHJcbiAgICAgICAgY29uc3QgbG9naWNWYWx1ZSA9XHJcbiAgICAgICAgICB0eXBlb2YgZmlsdGVyTG9naWMgPT09ICdzdHJpbmcnXHJcbiAgICAgICAgICAgID8gZmlsdGVyTG9naWMgPT09ICdhbnknXHJcbiAgICAgICAgICAgICAgPyBGaWx0ZXJMb2dpYy5BbnlcclxuICAgICAgICAgICAgICA6IEZpbHRlckxvZ2ljLkFsbFxyXG4gICAgICAgICAgICA6IGZpbHRlckxvZ2ljXHJcbiAgICAgICAgZGF0YVN0b3JlLnNldEZpbHRlckxvZ2ljKGxvZ2ljVmFsdWUpXHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIFN0b3JlIGZpbHRlcnMgdG8gcmVzdG9yZSBsYXRlciB3aGVuIGRhdGEgc3RvcmUgaXMgcmVhZHlcclxuICAgICAgcGVuZGluZ0ZpbHRlcnNUb1Jlc3RvcmUudmFsdWUgPSB7XHJcbiAgICAgICAgZmlsdGVyczogc2VyaWFsaXplZEZpbHRlcnMsXHJcbiAgICAgICAgYWN0aXZlQ29sb3JGaWx0ZXJJZCxcclxuICAgICAgICBmaWx0ZXJMb2dpY1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBBY3R1YWxseSBhcHBsaWVzIHRoZSBmaWx0ZXJzIG9uY2Ugd2UgaGF2ZSB0aGUgcHJvcGVydHkgZGF0YVxyXG4gICAqL1xyXG4gIGNvbnN0IGFwcGx5RmlsdGVyc0Zyb21TZXJpYWxpemVkID0gKFxyXG4gICAgc2VyaWFsaXplZEZpbHRlcnM6IFNlcmlhbGl6ZWRGaWx0ZXJEYXRhW10sXHJcbiAgICBhdmFpbGFibGVQcm9wZXJ0aWVzOiBFeHRlbmRlZFByb3BlcnR5SW5mb1tdXHJcbiAgKSA9PiB7XHJcbiAgICBmb3IgKGNvbnN0IHNlcmlhbGl6ZWRGaWx0ZXIgb2Ygc2VyaWFsaXplZEZpbHRlcnMpIHtcclxuICAgICAgaWYgKHNlcmlhbGl6ZWRGaWx0ZXIua2V5KSB7XHJcbiAgICAgICAgY29uc3QgcHJvcGVydHlJbmZvID0gYXZhaWxhYmxlUHJvcGVydGllcy5maW5kKFxyXG4gICAgICAgICAgKGYpID0+IGYua2V5ID09PSBzZXJpYWxpemVkRmlsdGVyLmtleVxyXG4gICAgICAgIClcclxuICAgICAgICBpZiAocHJvcGVydHlJbmZvKSB7XHJcbiAgICAgICAgICBjb25zdCBmaWx0ZXJJZCA9IGFkZEFjdGl2ZUZpbHRlcihwcm9wZXJ0eUluZm8sIHNlcmlhbGl6ZWRGaWx0ZXIuaWQpXHJcblxyXG4gICAgICAgICAgdXBkYXRlRmlsdGVyQ29uZGl0aW9uKGZpbHRlcklkLCBzZXJpYWxpemVkRmlsdGVyLmNvbmRpdGlvbilcclxuXHJcbiAgICAgICAgICBpZiAoc2VyaWFsaXplZEZpbHRlci5zZWxlY3RlZFZhbHVlcz8ubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHVwZGF0ZUFjdGl2ZUZpbHRlclZhbHVlcyhmaWx0ZXJJZCwgc2VyaWFsaXplZEZpbHRlci5zZWxlY3RlZFZhbHVlcylcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAoc2VyaWFsaXplZEZpbHRlci5udW1lcmljUmFuZ2UpIHtcclxuICAgICAgICAgICAgc2V0TnVtZXJpY1JhbmdlKFxyXG4gICAgICAgICAgICAgIGZpbHRlcklkLFxyXG4gICAgICAgICAgICAgIHNlcmlhbGl6ZWRGaWx0ZXIubnVtZXJpY1JhbmdlLm1pbixcclxuICAgICAgICAgICAgICBzZXJpYWxpemVkRmlsdGVyLm51bWVyaWNSYW5nZS5tYXhcclxuICAgICAgICAgICAgKVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIGlmICghc2VyaWFsaXplZEZpbHRlci5pc0FwcGxpZWQpIHtcclxuICAgICAgICAgICAgdG9nZ2xlRmlsdGVyQXBwbGllZChmaWx0ZXJJZClcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKlxyXG4gICAqIEZpbHRlcnMgdGhlIGF2YWlsYWJsZSBmaWx0ZXJzIHRvIG9ubHkgaW5jbHVkZSByZWxldmFudCBvbmVzIGZvciB0aGUgZmlsdGVyIFVJXHJcbiAgICovXHJcbiAgY29uc3QgZ2V0UmVsZXZhbnRGaWx0ZXJzID0gKFxyXG4gICAgYWxsRmlsdGVyczogRXh0ZW5kZWRQcm9wZXJ0eUluZm9bXSB8IG51bGwgfCB1bmRlZmluZWRcclxuICApOiBFeHRlbmRlZFByb3BlcnR5SW5mb1tdID0+IHtcclxuICAgIHJldHVybiAoYWxsRmlsdGVycyB8fCBbXSkuZmlsdGVyKChmOiBFeHRlbmRlZFByb3BlcnR5SW5mbykgPT4ge1xyXG4gICAgICBpZiAoc2hvdWxkRXhjbHVkZUZyb21GaWx0ZXJpbmcoZi5rZXkpKSB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlXHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHRydWVcclxuICAgIH0pXHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBHZXRzIHByb3BlcnR5IG9wdGlvbnMgZnJvbSB0aGUgZGF0YSBzdG9yZSAob3B0aW1pemVkIHRvIHVzZSBwcm9wZXJ0eU1hcClcclxuICAgKi9cclxuICBjb25zdCBnZXRQcm9wZXJ0eU9wdGlvbnNGcm9tRGF0YVN0b3JlID0gKCk6IChcclxuICAgIHwgRXh0ZW5kZWRQcm9wZXJ0eUluZm9cclxuICAgIHwgQm9vbGVhblByb3BlcnR5SW5mb1xyXG4gIClbXSA9PiB7XHJcbiAgICBjb25zdCBhbGxQcm9wZXJ0aWVzID0gbmV3IE1hcDxzdHJpbmcsIEV4dGVuZGVkUHJvcGVydHlJbmZvIHwgQm9vbGVhblByb3BlcnR5SW5mbz4oKVxyXG5cclxuICAgIGZvciAoY29uc3QgZGF0YVNvdXJjZSBvZiBkYXRhU3RvcmUuZGF0YVNvdXJjZXMudmFsdWUpIHtcclxuICAgICAgY29uc3QgcHJvcGVydHlLZXlzID0gT2JqZWN0LmtleXMoZGF0YVNvdXJjZS5wcm9wZXJ0eU1hcClcclxuXHJcbiAgICAgIGZvciAoY29uc3QgcHJvcGVydHlLZXkgb2YgcHJvcGVydHlLZXlzKSB7XHJcbiAgICAgICAgaWYgKGFsbFByb3BlcnRpZXMuaGFzKHByb3BlcnR5S2V5KSkge1xyXG4gICAgICAgICAgY29udGludWVcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb3BlcnR5SW5mbyA9IGRhdGFTb3VyY2UucHJvcGVydHlNYXBbcHJvcGVydHlLZXldXHJcblxyXG4gICAgICAgIGNvbnN0IGZpbHRlclR5cGUgPSBwcm9wZXJ0eUluZm8udHlwZVxyXG5cclxuICAgICAgICBpZiAoZmlsdGVyVHlwZSA9PT0gRmlsdGVyVHlwZS5Cb29sZWFuKSB7XHJcbiAgICAgICAgICBhbGxQcm9wZXJ0aWVzLnNldChwcm9wZXJ0eUtleSwge1xyXG4gICAgICAgICAgICBrZXk6IHByb3BlcnR5S2V5LFxyXG4gICAgICAgICAgICB0eXBlOiAnYm9vbGVhbicsXHJcbiAgICAgICAgICAgIG9iamVjdENvdW50OiAwLFxyXG4gICAgICAgICAgICB2YWx1ZUdyb3VwczogW11cclxuICAgICAgICAgIH0gYXMgQm9vbGVhblByb3BlcnR5SW5mbylcclxuICAgICAgICB9IGVsc2UgaWYgKGZpbHRlclR5cGUgPT09IEZpbHRlclR5cGUuTnVtZXJpYykge1xyXG4gICAgICAgICAgYWxsUHJvcGVydGllcy5zZXQocHJvcGVydHlLZXksIHtcclxuICAgICAgICAgICAga2V5OiBwcm9wZXJ0eUtleSxcclxuICAgICAgICAgICAgdHlwZTogJ251bWJlcicsXHJcbiAgICAgICAgICAgIG9iamVjdENvdW50OiAwLFxyXG4gICAgICAgICAgICBtaW46IDAsXHJcbiAgICAgICAgICAgIG1heDogMCxcclxuICAgICAgICAgICAgdmFsdWVHcm91cHM6IFtdLFxyXG4gICAgICAgICAgICBwYXNzTWluOiBudWxsLFxyXG4gICAgICAgICAgICBwYXNzTWF4OiBudWxsXHJcbiAgICAgICAgICB9IGFzIE51bWVyaWNQcm9wZXJ0eUluZm8pXHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGFsbFByb3BlcnRpZXMuc2V0KHByb3BlcnR5S2V5LCB7XHJcbiAgICAgICAgICAgIGtleTogcHJvcGVydHlLZXksXHJcbiAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnLFxyXG4gICAgICAgICAgICBvYmplY3RDb3VudDogMCxcclxuICAgICAgICAgICAgdmFsdWVHcm91cHM6IFtdXHJcbiAgICAgICAgICB9IGFzIFN0cmluZ1Byb3BlcnR5SW5mbylcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gQXJyYXkuZnJvbShhbGxQcm9wZXJ0aWVzLnZhbHVlcygpKVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogR2V0cyBmaWx0ZXJlZCBhbmQgc29ydGVkIHZhbHVlcyBmb3IgYSBzdHJpbmcgZmlsdGVyIHdpdGggc2VhcmNoIGFuZCBzb3J0aW5nIG9wdGlvbnNcclxuICAgKi9cclxuICBjb25zdCBnZXRGaWx0ZXJlZEZpbHRlclZhbHVlcyA9IChcclxuICAgIGZpbHRlcjogRXh0ZW5kZWRQcm9wZXJ0eUluZm8sXHJcbiAgICBvcHRpb25zPzoge1xyXG4gICAgICBzZWFyY2hRdWVyeT86IHN0cmluZ1xyXG4gICAgICBzb3J0TW9kZT86IFNvcnRNb2RlXHJcbiAgICAgIGZpbHRlcklkPzogc3RyaW5nXHJcbiAgICB9XHJcbiAgKTogc3RyaW5nW10gPT4ge1xyXG4gICAgY29uc3QgeyBzZWFyY2hRdWVyeSwgc29ydE1vZGUgPSBTb3J0TW9kZS5BbHBoYWJldGljYWwsIGZpbHRlcklkIH0gPSBvcHRpb25zIHx8IHt9XHJcblxyXG4gICAgbGV0IHZhbHVlczogc3RyaW5nW11cclxuXHJcbiAgICB2YWx1ZXMgPSBnZXRBdmFpbGFibGVGaWx0ZXJWYWx1ZXMoZmlsdGVyKVxyXG5cclxuICAgIGlmIChzZWFyY2hRdWVyeT8udHJpbSgpKSB7XHJcbiAgICAgIGNvbnN0IHNlYXJjaFRlcm0gPSBzZWFyY2hRdWVyeS50b0xvd2VyQ2FzZSgpLnRyaW0oKVxyXG4gICAgICB2YWx1ZXMgPSB2YWx1ZXMuZmlsdGVyKCh2YWx1ZTogc3RyaW5nKSA9PlxyXG4gICAgICAgIHZhbHVlLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoc2VhcmNoVGVybSlcclxuICAgICAgKVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChzb3J0TW9kZSA9PT0gU29ydE1vZGUuU2VsZWN0ZWRGaXJzdCAmJiBmaWx0ZXJJZCkge1xyXG4gICAgICBjb25zdCBbc2VsZWN0ZWRWYWx1ZXMsIHVuc2VsZWN0ZWRWYWx1ZXNdID0gcGFydGl0aW9uKHZhbHVlcywgKHZhbHVlOiBzdHJpbmcpID0+XHJcbiAgICAgICAgaXNBY3RpdmVGaWx0ZXJWYWx1ZVNlbGVjdGVkKGZpbHRlcklkLCB2YWx1ZSlcclxuICAgICAgKVxyXG5cclxuICAgICAgY29uc3Qgc29ydGVkU2VsZWN0ZWRWYWx1ZXMgPSBzZWxlY3RlZFZhbHVlcy5zb3J0KChhLCBiKSA9PiBhLmxvY2FsZUNvbXBhcmUoYikpXHJcbiAgICAgIGNvbnN0IHNvcnRlZFVuc2VsZWN0ZWRWYWx1ZXMgPSB1bnNlbGVjdGVkVmFsdWVzLnNvcnQoKGEsIGIpID0+IGEubG9jYWxlQ29tcGFyZShiKSlcclxuXHJcbiAgICAgIHJldHVybiBbLi4uc29ydGVkU2VsZWN0ZWRWYWx1ZXMsIC4uLnNvcnRlZFVuc2VsZWN0ZWRWYWx1ZXNdXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICByZXR1cm4gdmFsdWVzLnNvcnQoKGEsIGIpID0+IGEubG9jYWxlQ29tcGFyZShiKSlcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8vIFdhdGNoIGZvciBkYXRhIHN0b3JlIHRvIGJlY29tZSByZWFkeSBhbmQgcmVzdG9yZSBwZW5kaW5nIGZpbHRlcnNcclxuICBjb25zdCBzaG91bGRSZXN0b3JlRmlsdGVycyA9IGNvbXB1dGVkKCgpID0+IHtcclxuICAgIHJldHVybiBwZW5kaW5nRmlsdGVyc1RvUmVzdG9yZS52YWx1ZSAmJiBnZXRQcm9wZXJ0eU9wdGlvbnNGcm9tRGF0YVN0b3JlKCkubGVuZ3RoID4gMFxyXG4gIH0pXHJcblxyXG4gIHdoZW5ldmVyKHNob3VsZFJlc3RvcmVGaWx0ZXJzLCAoKSA9PiB7XHJcbiAgICBpZiAocGVuZGluZ0ZpbHRlcnNUb1Jlc3RvcmUudmFsdWUpIHtcclxuICAgICAgY29uc3QgYXZhaWxhYmxlUHJvcGVydGllcyA9XHJcbiAgICAgICAgZ2V0UHJvcGVydHlPcHRpb25zRnJvbURhdGFTdG9yZSgpIGFzIEV4dGVuZGVkUHJvcGVydHlJbmZvW11cclxuICAgICAgYXBwbHlGaWx0ZXJzRnJvbVNlcmlhbGl6ZWQoXHJcbiAgICAgICAgcGVuZGluZ0ZpbHRlcnNUb1Jlc3RvcmUudmFsdWUuZmlsdGVycyxcclxuICAgICAgICBhdmFpbGFibGVQcm9wZXJ0aWVzXHJcbiAgICAgIClcclxuICAgICAgaWYgKHBlbmRpbmdGaWx0ZXJzVG9SZXN0b3JlLnZhbHVlLmFjdGl2ZUNvbG9yRmlsdGVySWQpIHtcclxuICAgICAgICBmaWx0ZXJzLmFjdGl2ZUNvbG9yRmlsdGVySWQudmFsdWUgPVxyXG4gICAgICAgICAgcGVuZGluZ0ZpbHRlcnNUb1Jlc3RvcmUudmFsdWUuYWN0aXZlQ29sb3JGaWx0ZXJJZFxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAocGVuZGluZ0ZpbHRlcnNUb1Jlc3RvcmUudmFsdWUuZmlsdGVyTG9naWMpIHtcclxuICAgICAgICBjb25zdCBmaWx0ZXJMb2dpYyA9IHBlbmRpbmdGaWx0ZXJzVG9SZXN0b3JlLnZhbHVlLmZpbHRlckxvZ2ljXHJcbiAgICAgICAgY29uc3QgbG9naWNWYWx1ZSA9XHJcbiAgICAgICAgICB0eXBlb2YgZmlsdGVyTG9naWMgPT09ICdzdHJpbmcnXHJcbiAgICAgICAgICAgID8gZmlsdGVyTG9naWMgPT09ICdhbnknXHJcbiAgICAgICAgICAgICAgPyBGaWx0ZXJMb2dpYy5BbnlcclxuICAgICAgICAgICAgICA6IEZpbHRlckxvZ2ljLkFsbFxyXG4gICAgICAgICAgICA6IGZpbHRlckxvZ2ljXHJcbiAgICAgICAgZGF0YVN0b3JlLnNldEZpbHRlckxvZ2ljKGxvZ2ljVmFsdWUpXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIHBlbmRpbmdGaWx0ZXJzVG9SZXN0b3JlLnZhbHVlID0gbnVsbFxyXG4gICAgfVxyXG4gIH0pXHJcblxyXG4gIHJldHVybiB7XHJcbiAgICBpc29sYXRlT2JqZWN0cyxcclxuICAgIHVuSXNvbGF0ZU9iamVjdHMsXHJcbiAgICByZXNldElzb2xhdGlvbnMsXHJcbiAgICByZXNldEhpZGRlbkFuZElzb2xhdGlvbnMsXHJcbiAgICBoaWRlT2JqZWN0cyxcclxuICAgIHNob3dPYmplY3RzLFxyXG4gICAgcmVzZXRIaWRkZW4sXHJcbiAgICBoYXNBbnlJc29sYXRpb25zQXBwbGllZCxcclxuICAgIGhhc0FueUhpZGRlbkFwcGxpZWQsXHJcbiAgICBmaWx0ZXJzLFxyXG4gICAgYWRkQWN0aXZlRmlsdGVyLFxyXG4gICAgdXBkYXRlRmlsdGVyUHJvcGVydHksXHJcbiAgICByZW1vdmVBY3RpdmVGaWx0ZXIsXHJcbiAgICB0b2dnbGVGaWx0ZXJBcHBsaWVkLFxyXG4gICAgdXBkYXRlQWN0aXZlRmlsdGVyVmFsdWVzLFxyXG4gICAgc2VsZWN0QWxsRmlsdGVyVmFsdWVzLFxyXG4gICAgdXBkYXRlRmlsdGVyQ29uZGl0aW9uLFxyXG4gICAgc2V0RmlsdGVyTG9naWMsXHJcbiAgICB0b2dnbGVBY3RpdmVGaWx0ZXJWYWx1ZSxcclxuICAgIGlzQWN0aXZlRmlsdGVyVmFsdWVTZWxlY3RlZCxcclxuICAgIHJlc2V0RmlsdGVycyxcclxuICAgIHJlc3RvcmVGaWx0ZXJzLFxyXG4gICAgcmVzZXRFeHBsb2RlLFxyXG4gICAgZ2V0UmVsZXZhbnRGaWx0ZXJzLFxyXG4gICAgZ2V0UHJvcGVydHlPcHRpb25zRnJvbURhdGFTdG9yZSxcclxuICAgIGdldFByb3BlcnR5TmFtZSxcclxuICAgIGlzS3ZwRmlsdGVyYWJsZSxcclxuICAgIGdldEZpbHRlckRpc2FibGVkUmVhc29uLFxyXG4gICAgZmluZEZpbHRlckJ5S3ZwLFxyXG4gICAgZ2V0RmlsdGVyZWRGaWx0ZXJWYWx1ZXMsXHJcbiAgICBzZXROdW1lcmljUmFuZ2UsXHJcbiAgICBpc0xhcmdlUHJvcGVydHlcclxuICB9XHJcbn1cclxuIl0sImZpbGUiOiJEOi9zcGVja2xlLXNlcnZlci9wYWNrYWdlcy9mcm9udGVuZC0yL2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvZmlsdGVyaW5nL2ZpbHRlcmluZy50cyJ9