import { isStringPropertyInfo } from "/_nuxt/lib/viewer/helpers/sceneExplorer.ts"; import { isNumber, isString, isBoolean, toNumber } from "/_nuxt/node_modules/.cache/vite/client/deps/lodash-es.js?v=e4f18c29"; import { ExistenceFilterCondition, FilterType } from "/_nuxt/lib/viewer/helpers/filters/types.ts"; export const revitPropertyRegex = /^parameters\./; export const revitPropertyRegexDui3000InstanceProps = /^properties\.Instance/; export const revitPropertyRegexDui3000TypeProps = /^properties\.Type/; export const isRevitProperty = (key) => { return revitPropertyRegex.test(key) || revitPropertyRegexDui3000InstanceProps.test(key) || revitPropertyRegexDui3000TypeProps.test(key); }; export const shouldExcludeFromFiltering = (key) => { const pathParts = key.split("."); const lastPart = pathParts[pathParts.length - 1]; if (["definitionId", "transform", "name", "definitionName"].includes(lastPart)) { return false; } if (key.endsWith(".units") || key.endsWith(".speckle_type") || key.includes(".parameters.") || key.includes("renderMaterial") || key.includes(".domain") || key.includes("plane.") || key.includes("baseLine") || key.includes("referenceLine") || key.includes("end.") || key.includes("start.") || key.includes("endPoint.") || key.includes("midPoint.") || key.includes("startPoint.") || key.includes(".materialName") || key.includes(".materialClass") || key.includes(".materialCategory") || key.includes("displayStyle") || key.includes("displayValue") || key.includes("displayMesh") || key.startsWith("__")) { return true; } if (isRevitProperty(key)) { if (key.endsWith(".value")) return false; else return true; } return false; }; export const getPropertyName = (key, availableFilters) => { if (!key) return "Loading"; if (key === "level.name") return "Level Name"; if (key === "speckle_type") return "Object Type"; if (isRevitProperty(key) && key.endsWith(".value")) { const correspondingProperty = (availableFilters || []).find( (f) => f.key === key.replace(".value", ".name") ); if (correspondingProperty && isStringPropertyInfo(correspondingProperty)) { return correspondingProperty.valueGroups[0]?.value || key.split(".").pop() || key; } } return key.split(".").pop() || key; }; export const findFilterByDisplayName = (displayKey, availableFilters) => { if (!availableFilters) return void 0; const exactDisplayMatch = availableFilters.find((f) => { const propertyDisplayName = getPropertyName(f.key, availableFilters); return propertyDisplayName === displayKey; }); if (exactDisplayMatch) return exactDisplayMatch; const endMatches = availableFilters.filter((f) => f.key.split(".").pop() === displayKey).sort((a, b) => a.key.length - b.key.length); return endMatches[0]; }; export const isKvpFilterable = (kvp, availableFilters) => { const propertyKey = kvp.backendPath || kvp.key; const directMatch = availableFilters?.some((f) => f.key === propertyKey); if (directMatch) { return !shouldExcludeFromFiltering(propertyKey); } const displayKey = kvp.key; const matchByDisplayName = findFilterByDisplayName(displayKey, availableFilters); if (matchByDisplayName) { return !shouldExcludeFromFiltering(matchByDisplayName.key); } return false; }; export const getFilterDisabledReason = (kvp, availableFilters) => { const availableKeys = availableFilters?.map((f) => f.key) || []; if (kvp.backendPath) { if (!availableKeys.includes(kvp.backendPath)) { const propertyName = kvp.key; const similarPaths = availableKeys.filter( (key) => key.split(".").pop() === propertyName ); if (similarPaths.length > 0) { return `Property path '${kvp.backendPath}' not found. Similar properties: ${similarPaths.slice(0, 3).join(", ")}`; } return `Property path '${kvp.backendPath}' is not available in the current scene`; } if (shouldExcludeFromFiltering(kvp.backendPath)) { return `Property '${kvp.backendPath}' is excluded from filtering (technical property)`; } } else { const propertyKey = kvp.key; if (!availableKeys.includes(propertyKey)) { const similarKeys = availableKeys.filter( (key) => key.toLowerCase().includes("type") || key.toLowerCase().includes("category") || key.toLowerCase().includes("class") ); const debugInfo = similarKeys.length > 0 ? ` (Similar available: ${similarKeys.slice(0, 3).join(", ")})` : ""; return `Property '${propertyKey}' is not available in the current scene${debugInfo}`; } if (shouldExcludeFromFiltering(propertyKey)) { return `Property '${propertyKey}' is excluded from filtering (technical property)`; } } return "This property is not available for filtering"; }; export const findFilterByKvp = (kvp, availableFilters) => { if (!availableFilters) return void 0; if (kvp.backendPath) { const exactMatch = availableFilters.find( (f) => f.key === kvp.backendPath ); if (exactMatch) { return exactMatch; } } const directMatch = availableFilters.find( (f) => f.key === kvp.key ); if (directMatch) { return directMatch; } if (kvp.backendPath) { const pathParts = kvp.backendPath.split("."); const partialMatches = availableFilters.filter((f) => { const filterParts = f.key.split("."); if (pathParts.length === 1) { return filterParts[filterParts.length - 1] === pathParts[0]; } if (pathParts.length >= 2 && filterParts.length >= 2) { const kvpEnd = pathParts.slice(-2).join("."); const filterEnd = filterParts.slice(-2).join("."); return kvpEnd === filterEnd; } return false; }); if (partialMatches.length === 1) { return partialMatches[0]; } if (partialMatches.length > 1) { const sortedMatches = partialMatches.sort((a, b) => a.key.length - b.key.length); return sortedMatches[0]; } return void 0; } const displayKey = kvp.key; return findFilterByDisplayName(displayKey, availableFilters); }; export const isBooleanProperty = (filter) => { return "type" in filter && filter.type === "boolean"; }; export const isValueNumeric = (value) => { if (isNumber(value)) return Number.isFinite(value); if (isString(value)) { const trimmed = value.trim(); if (trimmed === "") return false; if (/-.*-/.test(trimmed)) return false; if (trimmed.includes("-") && !trimmed.startsWith("-")) return false; const converted = toNumber(trimmed); return Number.isFinite(converted); } return false; }; export const isValueBoolean = (value) => { if (isBoolean(value)) return true; if (isString(value)) { const str = value.toLowerCase(); return str === "true" || str === "false"; } return false; }; export const isValueBooleanTrue = (value) => { return value === true || isString(value) && value.toLowerCase() === "true"; }; export const isValueBooleanFalse = (value) => { return value === false || isString(value) && value.toLowerCase() === "false"; }; export function getFilterValueCount(filter, value) { if (!("valueGroups" in filter) || !Array.isArray(filter.valueGroups)) { return 0; } const valueGroups = filter.valueGroups; for (const vg of valueGroups) { if (String(vg.value) === value) { return vg.ids?.length ?? 0; } } return 0; } export function getExistenceFilterCount(filter, condition, totalObjectCount) { if (!("valueGroups" in filter) || !Array.isArray(filter.valueGroups)) { return filter.objectCount ?? 0; } const hasIndividualIds = filter.valueGroups.length > 0 && "id" in filter.valueGroups[0] && !("ids" in filter.valueGroups[0]); const objectsWithProperty = hasIndividualIds ? filter.valueGroups.length : filter.valueGroups.reduce((total, vg) => { if ("ids" in vg && Array.isArray(vg.ids)) { return total + vg.ids.length; } return total; }, 0); if (condition === ExistenceFilterCondition.IsSet) { return objectsWithProperty; } else { const relevantObjectCount = filter.objectCount ?? totalObjectCount ?? 0; return Math.max(0, relevantObjectCount - objectsWithProperty); } } export function injectGradientDataIntoDataStore(filteringDataStore, propertyKey, gradientValues) { if (!filteringDataStore || Object.keys(gradientValues).length === 0) { return; } const store = filteringDataStore; if (!store.dataSources?.value) { return; } for (const dataSource of store.dataSources.value) { for (const [objectId, { gradientValue }] of Object.entries(gradientValues)) { if (dataSource.objectProperties[objectId]) { dataSource.objectProperties[objectId][propertyKey] = gradientValue; } } if (!dataSource.propertyMap[propertyKey]) { dataSource.propertyMap[propertyKey] = { concatenatedPath: propertyKey, value: Object.values(gradientValues)[0]?.gradientValue || 0, type: FilterType.Numeric }; } } } export const extractNestedProperties = (obj, currentPath = [], knownObjectType, rootObj) => { const properties = []; rootObj = rootObj ?? obj; knownObjectType = knownObjectType ?? (obj.speckle_type === "Objects.Data.DataObject:Objects.Data.RevitObject" ? "revit" : void 0); for (const key in obj) { if (!Object.prototype.hasOwnProperty.call(obj, key) || key === "__closure" || key === "displayValue" || knownObjectType === "revit" && (key === "location" || key === "elements")) continue; if (knownObjectType === "revit" && key === "Material Quantities") { extractMaterialProperties( obj[key], [...currentPath, key], properties ); continue; } if (knownObjectType === "revit" && key === "Structure" && currentPath[currentPath.length - 1] === "Type Parameters") { continue; } const value = obj[key]; const newPath = [...currentPath, key]; const isParam = value && isParameter(value); const isActualObject = typeof value === "object" && value !== null && !Array.isArray(value) && !isParam; if (isActualObject) { properties.push( ...extractNestedProperties( value, newPath, knownObjectType, rootObj ) ); } else if (isParam) { const param = value; properties.push({ name: key, path: newPath, concatenatedPath: newPath.join("."), type: getValueType(param.value), units: param.units }); } else { const valueType = getValueType(value); properties.push({ name: key, path: newPath, concatenatedPath: newPath.join("."), type: valueType }); } } return properties; }; function getValueType(value) { if (value === null) return "null"; if (Array.isArray(value)) return "array"; if (isValueBoolean(value)) return "boolean"; if (isValueNumeric(value)) return "number"; return "string"; } function extractMaterialProperties(matQuants, path, properties) { for (const matName in matQuants) { const matInfo = matQuants[matName]; const areaProp = matInfo.area ? { path, concatenatedPath: path.join("."), type: "number", name: `${matName} - area`, value: matInfo.area.value, units: matInfo.area.units, materialCategory: matInfo.materialCategory, materialClass: matInfo.materialClass } : void 0; const volumeProp = matInfo.volume ? { path, concatenatedPath: path.join("."), type: "number", name: `${matName} - volume`, value: matInfo.volume.value, units: matInfo.volume.units, materialCategory: matInfo.materialCategory, materialClass: matInfo.materialClass } : void 0; if (areaProp) properties.push(areaProp); if (volumeProp) properties.push(volumeProp); } } export function isParameter(value) { return typeof value === "object" && Object.hasOwn(value, "name") && Object.hasOwn(value, "value"); } export function isRevitMaterialQuantity(value) { return typeof value === "object" && isParameter(value) && Object.hasOwn(value, "materialCategory") && Object.hasOwn(value, "materialClass"); } export function getNestedProperties(obj, properties) { const values = []; for (const prop of properties) { const value = prop.path.reduce( (current, key) => current?.[key], obj ); if (value && isParameter(value)) { values.push(value.value); } else { values.push(value ?? void 0); } } return values; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInV0aWxzLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzU3RyaW5nUHJvcGVydHlJbmZvIH0gZnJvbSAnfi9saWIvdmlld2VyL2hlbHBlcnMvc2NlbmVFeHBsb3JlcidcclxuaW1wb3J0IHsgaXNOdW1iZXIsIGlzU3RyaW5nLCBpc0Jvb2xlYW4sIHRvTnVtYmVyIH0gZnJvbSAnbG9kYXNoLWVzJ1xyXG5pbXBvcnQge1xyXG4gIEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbixcclxuICBGaWx0ZXJUeXBlLFxyXG4gIHR5cGUgQm9vbGVhblByb3BlcnR5SW5mbyxcclxuICB0eXBlIERhdGFTb3VyY2UsXHJcbiAgdHlwZSBFeHRlbmRlZFByb3BlcnR5SW5mbyxcclxuICB0eXBlIFByb3BlcnR5SW5mb0Jhc2UsXHJcbiAgdHlwZSBQcm9wZXJ0eUluZm9WYWx1ZSxcclxuICB0eXBlIFBhcmFtZXRlcixcclxuICB0eXBlIFJldml0TWF0ZXJpYWxQcm9wZXJ0eUluZm8sXHJcbiAgdHlwZSBSZXZpdE1hdGVyaWFsSW5mb1xyXG59IGZyb20gJ34vbGliL3ZpZXdlci9oZWxwZXJzL2ZpbHRlcnMvdHlwZXMnXHJcblxyXG5leHBvcnQgY29uc3QgcmV2aXRQcm9wZXJ0eVJlZ2V4ID0gL15wYXJhbWV0ZXJzXFwuL1xyXG5leHBvcnQgY29uc3QgcmV2aXRQcm9wZXJ0eVJlZ2V4RHVpMzAwMEluc3RhbmNlUHJvcHMgPSAvXnByb3BlcnRpZXNcXC5JbnN0YW5jZS9cclxuZXhwb3J0IGNvbnN0IHJldml0UHJvcGVydHlSZWdleER1aTMwMDBUeXBlUHJvcHMgPSAvXnByb3BlcnRpZXNcXC5UeXBlL1xyXG5cclxuLyoqXHJcbiAqIERldGVybWluZXMgaWYgYSBwcm9wZXJ0eSBrZXkgcmVwcmVzZW50cyBhIFJldml0IHByb3BlcnR5XHJcbiAqL1xyXG5leHBvcnQgY29uc3QgaXNSZXZpdFByb3BlcnR5ID0gKGtleTogc3RyaW5nKTogYm9vbGVhbiA9PiB7XHJcbiAgcmV0dXJuIChcclxuICAgIHJldml0UHJvcGVydHlSZWdleC50ZXN0KGtleSkgfHxcclxuICAgIHJldml0UHJvcGVydHlSZWdleER1aTMwMDBJbnN0YW5jZVByb3BzLnRlc3Qoa2V5KSB8fFxyXG4gICAgcmV2aXRQcm9wZXJ0eVJlZ2V4RHVpMzAwMFR5cGVQcm9wcy50ZXN0KGtleSlcclxuICApXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEZXRlcm1pbmVzIGlmIGEgcHJvcGVydHkgc2hvdWxkIGJlIGV4Y2x1ZGVkIGZyb20gZmlsdGVyaW5nIGJhc2VkIG9uIGl0cyBrZXlcclxuICovXHJcbmV4cG9ydCBjb25zdCBzaG91bGRFeGNsdWRlRnJvbUZpbHRlcmluZyA9IChrZXk6IHN0cmluZyk6IGJvb2xlYW4gPT4ge1xyXG4gIC8vIFdoaXRlbGlzdCBlc3NlbnRpYWwgaW5zdGFuY2UgcHJvcGVydGllc1xyXG4gIGNvbnN0IHBhdGhQYXJ0cyA9IGtleS5zcGxpdCgnLicpXHJcbiAgY29uc3QgbGFzdFBhcnQgPSBwYXRoUGFydHNbcGF0aFBhcnRzLmxlbmd0aCAtIDFdXHJcblxyXG4gIC8vIEFsd2F5cyBpbmNsdWRlIHRoZXNlIGluc3RhbmNlLXJlbGF0ZWQgcHJvcGVydGllc1xyXG4gIGlmIChbJ2RlZmluaXRpb25JZCcsICd0cmFuc2Zvcm0nLCAnbmFtZScsICdkZWZpbml0aW9uTmFtZSddLmluY2x1ZGVzKGxhc3RQYXJ0KSkge1xyXG4gICAgcmV0dXJuIGZhbHNlXHJcbiAgfVxyXG5cclxuICBpZiAoXHJcbiAgICBrZXkuZW5kc1dpdGgoJy51bml0cycpIHx8XHJcbiAgICBrZXkuZW5kc1dpdGgoJy5zcGVja2xlX3R5cGUnKSB8fFxyXG4gICAga2V5LmluY2x1ZGVzKCcucGFyYW1ldGVycy4nKSB8fFxyXG4gICAga2V5LmluY2x1ZGVzKCdyZW5kZXJNYXRlcmlhbCcpIHx8XHJcbiAgICBrZXkuaW5jbHVkZXMoJy5kb21haW4nKSB8fFxyXG4gICAga2V5LmluY2x1ZGVzKCdwbGFuZS4nKSB8fFxyXG4gICAga2V5LmluY2x1ZGVzKCdiYXNlTGluZScpIHx8XHJcbiAgICBrZXkuaW5jbHVkZXMoJ3JlZmVyZW5jZUxpbmUnKSB8fFxyXG4gICAga2V5LmluY2x1ZGVzKCdlbmQuJykgfHxcclxuICAgIGtleS5pbmNsdWRlcygnc3RhcnQuJykgfHxcclxuICAgIGtleS5pbmNsdWRlcygnZW5kUG9pbnQuJykgfHxcclxuICAgIGtleS5pbmNsdWRlcygnbWlkUG9pbnQuJykgfHxcclxuICAgIGtleS5pbmNsdWRlcygnc3RhcnRQb2ludC4nKSB8fFxyXG4gICAga2V5LmluY2x1ZGVzKCcubWF0ZXJpYWxOYW1lJykgfHxcclxuICAgIGtleS5pbmNsdWRlcygnLm1hdGVyaWFsQ2xhc3MnKSB8fFxyXG4gICAga2V5LmluY2x1ZGVzKCcubWF0ZXJpYWxDYXRlZ29yeScpIHx8XHJcbiAgICBrZXkuaW5jbHVkZXMoJ2Rpc3BsYXlTdHlsZScpIHx8XHJcbiAgICBrZXkuaW5jbHVkZXMoJ2Rpc3BsYXlWYWx1ZScpIHx8XHJcbiAgICBrZXkuaW5jbHVkZXMoJ2Rpc3BsYXlNZXNoJykgfHxcclxuICAgIGtleS5zdGFydHNXaXRoKCdfXycpXHJcbiAgKSB7XHJcbiAgICByZXR1cm4gdHJ1ZVxyXG4gIH1cclxuXHJcbiAgaWYgKGlzUmV2aXRQcm9wZXJ0eShrZXkpKSB7XHJcbiAgICBpZiAoa2V5LmVuZHNXaXRoKCcudmFsdWUnKSkgcmV0dXJuIGZhbHNlXHJcbiAgICBlbHNlIHJldHVybiB0cnVlXHJcbiAgfVxyXG5cclxuICByZXR1cm4gZmFsc2VcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgYSB1c2VyLWZyaWVuZGx5IGRpc3BsYXkgbmFtZSBmb3IgYSBwcm9wZXJ0eSBrZXlcclxuICovXHJcbmV4cG9ydCBjb25zdCBnZXRQcm9wZXJ0eU5hbWUgPSAoXHJcbiAga2V5OiBzdHJpbmcsXHJcbiAgYXZhaWxhYmxlRmlsdGVycz86IEV4dGVuZGVkUHJvcGVydHlJbmZvW10gfCBudWxsXHJcbik6IHN0cmluZyA9PiB7XHJcbiAgaWYgKCFrZXkpIHJldHVybiAnTG9hZGluZydcclxuXHJcbiAgaWYgKGtleSA9PT0gJ2xldmVsLm5hbWUnKSByZXR1cm4gJ0xldmVsIE5hbWUnXHJcbiAgaWYgKGtleSA9PT0gJ3NwZWNrbGVfdHlwZScpIHJldHVybiAnT2JqZWN0IFR5cGUnXHJcblxyXG4gIGlmIChpc1Jldml0UHJvcGVydHkoa2V5KSAmJiBrZXkuZW5kc1dpdGgoJy52YWx1ZScpKSB7XHJcbiAgICBjb25zdCBjb3JyZXNwb25kaW5nUHJvcGVydHkgPSAoYXZhaWxhYmxlRmlsdGVycyB8fCBbXSkuZmluZChcclxuICAgICAgKGY6IEV4dGVuZGVkUHJvcGVydHlJbmZvKSA9PiBmLmtleSA9PT0ga2V5LnJlcGxhY2UoJy52YWx1ZScsICcubmFtZScpXHJcbiAgICApXHJcbiAgICBpZiAoY29ycmVzcG9uZGluZ1Byb3BlcnR5ICYmIGlzU3RyaW5nUHJvcGVydHlJbmZvKGNvcnJlc3BvbmRpbmdQcm9wZXJ0eSkpIHtcclxuICAgICAgcmV0dXJuIGNvcnJlc3BvbmRpbmdQcm9wZXJ0eS52YWx1ZUdyb3Vwc1swXT8udmFsdWUgfHwga2V5LnNwbGl0KCcuJykucG9wKCkgfHwga2V5XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4ga2V5LnNwbGl0KCcuJykucG9wKCkgfHwga2V5XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBGaW5kcyBhIGZpbHRlciBieSBtYXRjaGluZyBkaXNwbGF5IG5hbWVzXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgZmluZEZpbHRlckJ5RGlzcGxheU5hbWUgPSAoXHJcbiAgZGlzcGxheUtleTogc3RyaW5nLFxyXG4gIGF2YWlsYWJsZUZpbHRlcnM6IEV4dGVuZGVkUHJvcGVydHlJbmZvW10gfCBudWxsIHwgdW5kZWZpbmVkXHJcbik6IEV4dGVuZGVkUHJvcGVydHlJbmZvIHwgdW5kZWZpbmVkID0+IHtcclxuICBpZiAoIWF2YWlsYWJsZUZpbHRlcnMpIHJldHVybiB1bmRlZmluZWRcclxuXHJcbiAgLy8gRmlyc3QsIHRyeSB0byBmaW5kIGFuIGV4YWN0IGRpc3BsYXkgbmFtZSBtYXRjaFxyXG4gIGNvbnN0IGV4YWN0RGlzcGxheU1hdGNoID0gYXZhaWxhYmxlRmlsdGVycy5maW5kKChmKSA9PiB7XHJcbiAgICBjb25zdCBwcm9wZXJ0eURpc3BsYXlOYW1lID0gZ2V0UHJvcGVydHlOYW1lKGYua2V5LCBhdmFpbGFibGVGaWx0ZXJzKVxyXG4gICAgcmV0dXJuIHByb3BlcnR5RGlzcGxheU5hbWUgPT09IGRpc3BsYXlLZXlcclxuICB9KVxyXG4gIGlmIChleGFjdERpc3BsYXlNYXRjaCkgcmV0dXJuIGV4YWN0RGlzcGxheU1hdGNoXHJcblxyXG4gIC8vIFRoZW4gdHJ5IHRvIGZpbmQgYSBtYXRjaCB3aGVyZSB0aGUga2V5IGVuZHMgd2l0aCB0aGUgZGlzcGxheSBrZXlcclxuICBjb25zdCBlbmRNYXRjaGVzID0gYXZhaWxhYmxlRmlsdGVyc1xyXG4gICAgLmZpbHRlcigoZikgPT4gZi5rZXkuc3BsaXQoJy4nKS5wb3AoKSA9PT0gZGlzcGxheUtleSlcclxuICAgIC5zb3J0KChhLCBiKSA9PiBhLmtleS5sZW5ndGggLSBiLmtleS5sZW5ndGgpIC8vIFNob3J0ZXIgcGF0aHMgZmlyc3RcclxuXHJcbiAgcmV0dXJuIGVuZE1hdGNoZXNbMF0gLy8gUmV0dXJuIHRoZSBzaG9ydGVzdCBtYXRjaGluZyBwYXRoXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBEZXRlcm1pbmVzIGlmIGEga2V5LXZhbHVlIHBhaXIgaXMgZmlsdGVyYWJsZSAod2l0aCBzbWFydCBtYXRjaGluZyBmb3IgbmVzdGVkIHByb3BlcnRpZXMpXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgaXNLdnBGaWx0ZXJhYmxlID0gKFxyXG4gIGt2cDogeyBrZXk6IHN0cmluZzsgYmFja2VuZFBhdGg/OiBzdHJpbmcgfSxcclxuICBhdmFpbGFibGVGaWx0ZXJzOiBFeHRlbmRlZFByb3BlcnR5SW5mb1tdIHwgbnVsbCB8IHVuZGVmaW5lZFxyXG4pOiBib29sZWFuID0+IHtcclxuICAvLyBVc2UgYmFja2VuZFBhdGggZm9yIGxlZ2FjeSBjb21wYXRpYmlsaXR5LCBidXQgcHJlZmVyIHRoZSBkaXJlY3Qga2V5XHJcbiAgY29uc3QgcHJvcGVydHlLZXkgPSBrdnAuYmFja2VuZFBhdGggfHwga3ZwLmtleVxyXG5cclxuICBjb25zdCBkaXJlY3RNYXRjaCA9IGF2YWlsYWJsZUZpbHRlcnM/LnNvbWUoKGYpID0+IGYua2V5ID09PSBwcm9wZXJ0eUtleSlcclxuICBpZiAoZGlyZWN0TWF0Y2gpIHtcclxuICAgIHJldHVybiAhc2hvdWxkRXhjbHVkZUZyb21GaWx0ZXJpbmcocHJvcGVydHlLZXkpXHJcbiAgfVxyXG5cclxuICBjb25zdCBkaXNwbGF5S2V5ID0ga3ZwLmtleSBhcyBzdHJpbmdcclxuICBjb25zdCBtYXRjaEJ5RGlzcGxheU5hbWUgPSBmaW5kRmlsdGVyQnlEaXNwbGF5TmFtZShkaXNwbGF5S2V5LCBhdmFpbGFibGVGaWx0ZXJzKVxyXG5cclxuICBpZiAobWF0Y2hCeURpc3BsYXlOYW1lKSB7XHJcbiAgICByZXR1cm4gIXNob3VsZEV4Y2x1ZGVGcm9tRmlsdGVyaW5nKG1hdGNoQnlEaXNwbGF5TmFtZS5rZXkpXHJcbiAgfVxyXG5cclxuICByZXR1cm4gZmFsc2VcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldHMgYSBkZXRhaWxlZCByZWFzb24gd2h5IGEgcHJvcGVydHkgaXMgZGlzYWJsZWQgZm9yIGZpbHRlcmluZ1xyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGdldEZpbHRlckRpc2FibGVkUmVhc29uID0gKFxyXG4gIGt2cDogeyBrZXk6IHN0cmluZzsgYmFja2VuZFBhdGg/OiBzdHJpbmcgfSxcclxuICBhdmFpbGFibGVGaWx0ZXJzOiBFeHRlbmRlZFByb3BlcnR5SW5mb1tdIHwgbnVsbCB8IHVuZGVmaW5lZFxyXG4pOiBzdHJpbmcgPT4ge1xyXG4gIGNvbnN0IGF2YWlsYWJsZUtleXMgPSBhdmFpbGFibGVGaWx0ZXJzPy5tYXAoKGYpID0+IGYua2V5KSB8fCBbXVxyXG5cclxuICBpZiAoa3ZwLmJhY2tlbmRQYXRoKSB7XHJcbiAgICBpZiAoIWF2YWlsYWJsZUtleXMuaW5jbHVkZXMoa3ZwLmJhY2tlbmRQYXRoKSkge1xyXG4gICAgICBjb25zdCBwcm9wZXJ0eU5hbWUgPSBrdnAua2V5XHJcbiAgICAgIGNvbnN0IHNpbWlsYXJQYXRocyA9IGF2YWlsYWJsZUtleXMuZmlsdGVyKFxyXG4gICAgICAgIChrZXkpID0+IGtleS5zcGxpdCgnLicpLnBvcCgpID09PSBwcm9wZXJ0eU5hbWVcclxuICAgICAgKVxyXG5cclxuICAgICAgaWYgKHNpbWlsYXJQYXRocy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgcmV0dXJuIGBQcm9wZXJ0eSBwYXRoICcke1xyXG4gICAgICAgICAga3ZwLmJhY2tlbmRQYXRoXHJcbiAgICAgICAgfScgbm90IGZvdW5kLiBTaW1pbGFyIHByb3BlcnRpZXM6ICR7c2ltaWxhclBhdGhzLnNsaWNlKDAsIDMpLmpvaW4oJywgJyl9YFxyXG4gICAgICB9XHJcblxyXG4gICAgICByZXR1cm4gYFByb3BlcnR5IHBhdGggJyR7a3ZwLmJhY2tlbmRQYXRofScgaXMgbm90IGF2YWlsYWJsZSBpbiB0aGUgY3VycmVudCBzY2VuZWBcclxuICAgIH1cclxuXHJcbiAgICBpZiAoc2hvdWxkRXhjbHVkZUZyb21GaWx0ZXJpbmcoa3ZwLmJhY2tlbmRQYXRoKSkge1xyXG4gICAgICByZXR1cm4gYFByb3BlcnR5ICcke2t2cC5iYWNrZW5kUGF0aH0nIGlzIGV4Y2x1ZGVkIGZyb20gZmlsdGVyaW5nICh0ZWNobmljYWwgcHJvcGVydHkpYFxyXG4gICAgfVxyXG4gIH0gZWxzZSB7XHJcbiAgICAvLyBGYWxsYmFjayB0byBrZXktYmFzZWQgY2hlY2tpbmdcclxuICAgIGNvbnN0IHByb3BlcnR5S2V5ID0ga3ZwLmtleVxyXG4gICAgaWYgKCFhdmFpbGFibGVLZXlzLmluY2x1ZGVzKHByb3BlcnR5S2V5KSkge1xyXG4gICAgICBjb25zdCBzaW1pbGFyS2V5cyA9IGF2YWlsYWJsZUtleXMuZmlsdGVyKFxyXG4gICAgICAgIChrZXkpID0+XHJcbiAgICAgICAgICBrZXkudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygndHlwZScpIHx8XHJcbiAgICAgICAgICBrZXkudG9Mb3dlckNhc2UoKS5pbmNsdWRlcygnY2F0ZWdvcnknKSB8fFxyXG4gICAgICAgICAga2V5LnRvTG93ZXJDYXNlKCkuaW5jbHVkZXMoJ2NsYXNzJylcclxuICAgICAgKVxyXG5cclxuICAgICAgY29uc3QgZGVidWdJbmZvID1cclxuICAgICAgICBzaW1pbGFyS2V5cy5sZW5ndGggPiAwXHJcbiAgICAgICAgICA/IGAgKFNpbWlsYXIgYXZhaWxhYmxlOiAke3NpbWlsYXJLZXlzLnNsaWNlKDAsIDMpLmpvaW4oJywgJyl9KWBcclxuICAgICAgICAgIDogJydcclxuXHJcbiAgICAgIHJldHVybiBgUHJvcGVydHkgJyR7cHJvcGVydHlLZXl9JyBpcyBub3QgYXZhaWxhYmxlIGluIHRoZSBjdXJyZW50IHNjZW5lJHtkZWJ1Z0luZm99YFxyXG4gICAgfVxyXG5cclxuICAgIGlmIChzaG91bGRFeGNsdWRlRnJvbUZpbHRlcmluZyhwcm9wZXJ0eUtleSkpIHtcclxuICAgICAgcmV0dXJuIGBQcm9wZXJ0eSAnJHtwcm9wZXJ0eUtleX0nIGlzIGV4Y2x1ZGVkIGZyb20gZmlsdGVyaW5nICh0ZWNobmljYWwgcHJvcGVydHkpYFxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuICdUaGlzIHByb3BlcnR5IGlzIG5vdCBhdmFpbGFibGUgZm9yIGZpbHRlcmluZydcclxufVxyXG5cclxuLyoqXHJcbiAqIEZpbmRzIGEgZmlsdGVyIGZvciBhIGtleS12YWx1ZSBwYWlyIHVzaW5nIHNtYXJ0IG1hdGNoaW5nIGxvZ2ljXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgZmluZEZpbHRlckJ5S3ZwID0gKFxyXG4gIGt2cDogeyBrZXk6IHN0cmluZzsgYmFja2VuZFBhdGg/OiBzdHJpbmcgfSxcclxuICBhdmFpbGFibGVGaWx0ZXJzOiBFeHRlbmRlZFByb3BlcnR5SW5mb1tdIHwgbnVsbCB8IHVuZGVmaW5lZFxyXG4pOiBFeHRlbmRlZFByb3BlcnR5SW5mbyB8IHVuZGVmaW5lZCA9PiB7XHJcbiAgaWYgKCFhdmFpbGFibGVGaWx0ZXJzKSByZXR1cm4gdW5kZWZpbmVkXHJcblxyXG4gIGlmIChrdnAuYmFja2VuZFBhdGgpIHtcclxuICAgIGNvbnN0IGV4YWN0TWF0Y2ggPSBhdmFpbGFibGVGaWx0ZXJzLmZpbmQoXHJcbiAgICAgIChmOiBFeHRlbmRlZFByb3BlcnR5SW5mbykgPT4gZi5rZXkgPT09IGt2cC5iYWNrZW5kUGF0aFxyXG4gICAgKVxyXG4gICAgaWYgKGV4YWN0TWF0Y2gpIHtcclxuICAgICAgcmV0dXJuIGV4YWN0TWF0Y2hcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IGRpcmVjdE1hdGNoID0gYXZhaWxhYmxlRmlsdGVycy5maW5kKFxyXG4gICAgKGY6IEV4dGVuZGVkUHJvcGVydHlJbmZvKSA9PiBmLmtleSA9PT0ga3ZwLmtleVxyXG4gIClcclxuICBpZiAoZGlyZWN0TWF0Y2gpIHtcclxuICAgIHJldHVybiBkaXJlY3RNYXRjaFxyXG4gIH1cclxuXHJcbiAgLy8gSWYgd2UgaGF2ZSBhIGJhY2tlbmRQYXRoIGJ1dCBubyBleGFjdCBtYXRjaCwgdHJ5IHBhcnRpYWwgbWF0Y2hpbmdcclxuICBpZiAoa3ZwLmJhY2tlbmRQYXRoKSB7XHJcbiAgICBjb25zdCBwYXRoUGFydHMgPSBrdnAuYmFja2VuZFBhdGguc3BsaXQoJy4nKVxyXG4gICAgY29uc3QgcGFydGlhbE1hdGNoZXMgPSBhdmFpbGFibGVGaWx0ZXJzLmZpbHRlcigoZjogRXh0ZW5kZWRQcm9wZXJ0eUluZm8pID0+IHtcclxuICAgICAgY29uc3QgZmlsdGVyUGFydHMgPSBmLmtleS5zcGxpdCgnLicpXHJcblxyXG4gICAgICBpZiAocGF0aFBhcnRzLmxlbmd0aCA9PT0gMSkge1xyXG4gICAgICAgIHJldHVybiBmaWx0ZXJQYXJ0c1tmaWx0ZXJQYXJ0cy5sZW5ndGggLSAxXSA9PT0gcGF0aFBhcnRzWzBdXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmIChwYXRoUGFydHMubGVuZ3RoID49IDIgJiYgZmlsdGVyUGFydHMubGVuZ3RoID49IDIpIHtcclxuICAgICAgICBjb25zdCBrdnBFbmQgPSBwYXRoUGFydHMuc2xpY2UoLTIpLmpvaW4oJy4nKVxyXG4gICAgICAgIGNvbnN0IGZpbHRlckVuZCA9IGZpbHRlclBhcnRzLnNsaWNlKC0yKS5qb2luKCcuJylcclxuICAgICAgICByZXR1cm4ga3ZwRW5kID09PSBmaWx0ZXJFbmRcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIGZhbHNlXHJcbiAgICB9KVxyXG5cclxuICAgIGlmIChwYXJ0aWFsTWF0Y2hlcy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgcmV0dXJuIHBhcnRpYWxNYXRjaGVzWzBdXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHBhcnRpYWxNYXRjaGVzLmxlbmd0aCA+IDEpIHtcclxuICAgICAgY29uc3Qgc29ydGVkTWF0Y2hlcyA9IHBhcnRpYWxNYXRjaGVzLnNvcnQoKGEsIGIpID0+IGEua2V5Lmxlbmd0aCAtIGIua2V5Lmxlbmd0aClcclxuICAgICAgcmV0dXJuIHNvcnRlZE1hdGNoZXNbMF1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdW5kZWZpbmVkXHJcbiAgfVxyXG5cclxuICAvLyBPbmx5IGZhbGwgYmFjayB0byBmdXp6eSBtYXRjaGluZyBpZiBubyBiYWNrZW5kUGF0aCBpcyBwcm92aWRlZCAobGVnYWN5IHN1cHBvcnQpXHJcbiAgY29uc3QgZGlzcGxheUtleSA9IGt2cC5rZXkgYXMgc3RyaW5nXHJcbiAgcmV0dXJuIGZpbmRGaWx0ZXJCeURpc3BsYXlOYW1lKGRpc3BsYXlLZXksIGF2YWlsYWJsZUZpbHRlcnMpXHJcbn1cclxuXHJcbmV4cG9ydCBjb25zdCBpc0Jvb2xlYW5Qcm9wZXJ0eSA9IChmaWx0ZXI6IEV4dGVuZGVkUHJvcGVydHlJbmZvKTogYm9vbGVhbiA9PiB7XHJcbiAgcmV0dXJuICd0eXBlJyBpbiBmaWx0ZXIgJiYgKGZpbHRlciBhcyB7IHR5cGU6IHN0cmluZyB9KS50eXBlID09PSAnYm9vbGVhbidcclxufVxyXG5cclxuLyoqXHJcbiAqIERldGVybWluZXMgaWYgYSB2YWx1ZSBzaG91bGQgYmUgdHJlYXRlZCBhcyBudW1lcmljIGZvciBmaWx0ZXJpbmdcclxuICovXHJcbmV4cG9ydCBjb25zdCBpc1ZhbHVlTnVtZXJpYyA9ICh2YWx1ZTogdW5rbm93bik6IGJvb2xlYW4gPT4ge1xyXG4gIGlmIChpc051bWJlcih2YWx1ZSkpIHJldHVybiBOdW1iZXIuaXNGaW5pdGUodmFsdWUpXHJcblxyXG4gIGlmIChpc1N0cmluZyh2YWx1ZSkpIHtcclxuICAgIGNvbnN0IHRyaW1tZWQgPSB2YWx1ZS50cmltKClcclxuICAgIGlmICh0cmltbWVkID09PSAnJykgcmV0dXJuIGZhbHNlXHJcblxyXG4gICAgLy8gQWxsb3c6IGRpZ2l0cywgZGVjaW1hbCBwb2ludHMsIG1pbnVzIHNpZ24gYXQgc3RhcnRcclxuICAgIGlmICgvLS4qLS8udGVzdCh0cmltbWVkKSkgcmV0dXJuIGZhbHNlIC8vIE11bHRpcGxlIGRhc2hlcyAoVVVJRCBwYXR0ZXJuKVxyXG4gICAgaWYgKHRyaW1tZWQuaW5jbHVkZXMoJy0nKSAmJiAhdHJpbW1lZC5zdGFydHNXaXRoKCctJykpIHJldHVybiBmYWxzZSAvLyBEYXNoIG5vdCBhdCB0aGUgc3RhcnRcclxuXHJcbiAgICBjb25zdCBjb252ZXJ0ZWQgPSB0b051bWJlcih0cmltbWVkKVxyXG4gICAgcmV0dXJuIE51bWJlci5pc0Zpbml0ZShjb252ZXJ0ZWQpXHJcbiAgfVxyXG5cclxuICByZXR1cm4gZmFsc2VcclxufVxyXG5cclxuLyoqXHJcbiAqIERldGVybWluZXMgaWYgYSB2YWx1ZSBzaG91bGQgYmUgdHJlYXRlZCBhcyBib29sZWFuIGZvciBmaWx0ZXJpbmcgKGNhc2UtaW5zZW5zaXRpdmUpXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgaXNWYWx1ZUJvb2xlYW4gPSAodmFsdWU6IHVua25vd24pOiBib29sZWFuID0+IHtcclxuICBpZiAoaXNCb29sZWFuKHZhbHVlKSkgcmV0dXJuIHRydWVcclxuICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7XHJcbiAgICBjb25zdCBzdHIgPSB2YWx1ZS50b0xvd2VyQ2FzZSgpXHJcbiAgICByZXR1cm4gc3RyID09PSAndHJ1ZScgfHwgc3RyID09PSAnZmFsc2UnXHJcbiAgfVxyXG4gIHJldHVybiBmYWxzZVxyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIGEgdmFsdWUgcmVwcmVzZW50cyBib29sZWFuIHRydWUgKGNhc2UtaW5zZW5zaXRpdmUpXHJcbiAqL1xyXG5leHBvcnQgY29uc3QgaXNWYWx1ZUJvb2xlYW5UcnVlID0gKHZhbHVlOiB1bmtub3duKTogYm9vbGVhbiA9PiB7XHJcbiAgcmV0dXJuIHZhbHVlID09PSB0cnVlIHx8IChpc1N0cmluZyh2YWx1ZSkgJiYgdmFsdWUudG9Mb3dlckNhc2UoKSA9PT0gJ3RydWUnKVxyXG59XHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIGEgdmFsdWUgcmVwcmVzZW50cyBib29sZWFuIGZhbHNlIChjYXNlLWluc2Vuc2l0aXZlKVxyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGlzVmFsdWVCb29sZWFuRmFsc2UgPSAodmFsdWU6IHVua25vd24pOiBib29sZWFuID0+IHtcclxuICByZXR1cm4gdmFsdWUgPT09IGZhbHNlIHx8IChpc1N0cmluZyh2YWx1ZSkgJiYgdmFsdWUudG9Mb3dlckNhc2UoKSA9PT0gJ2ZhbHNlJylcclxufVxyXG5cclxuLyoqXHJcbiAqIEdldCBjb3VudCBmb3IgYSBzcGVjaWZpYyBmaWx0ZXIgdmFsdWVcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRGaWx0ZXJWYWx1ZUNvdW50KFxyXG4gIGZpbHRlcjogRXh0ZW5kZWRQcm9wZXJ0eUluZm8sXHJcbiAgdmFsdWU6IHN0cmluZ1xyXG4pOiBudW1iZXIge1xyXG4gIGlmICghKCd2YWx1ZUdyb3VwcycgaW4gZmlsdGVyKSB8fCAhQXJyYXkuaXNBcnJheShmaWx0ZXIudmFsdWVHcm91cHMpKSB7XHJcbiAgICByZXR1cm4gMFxyXG4gIH1cclxuXHJcbiAgY29uc3QgdmFsdWVHcm91cHMgPSBmaWx0ZXIudmFsdWVHcm91cHMgYXMgQXJyYXk8eyB2YWx1ZTogdW5rbm93bjsgaWRzPzogc3RyaW5nW10gfT5cclxuXHJcbiAgZm9yIChjb25zdCB2ZyBvZiB2YWx1ZUdyb3Vwcykge1xyXG4gICAgaWYgKFN0cmluZyh2Zy52YWx1ZSkgPT09IHZhbHVlKSB7XHJcbiAgICAgIHJldHVybiB2Zy5pZHM/Lmxlbmd0aCA/PyAwXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZXR1cm4gMFxyXG59XHJcblxyXG4vKipcclxuICogR2V0IGNvdW50IGZvciBleGlzdGVuY2UgZmlsdGVycyAob2JqZWN0cyB0aGF0IGhhdmUvZG9uJ3QgaGF2ZSBhIHByb3BlcnR5IHNldClcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRFeGlzdGVuY2VGaWx0ZXJDb3VudChcclxuICBmaWx0ZXI6IEV4dGVuZGVkUHJvcGVydHlJbmZvIHwgQm9vbGVhblByb3BlcnR5SW5mbyxcclxuICBjb25kaXRpb246IEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbixcclxuICB0b3RhbE9iamVjdENvdW50PzogbnVtYmVyXHJcbik6IG51bWJlciB7XHJcbiAgaWYgKCEoJ3ZhbHVlR3JvdXBzJyBpbiBmaWx0ZXIpIHx8ICFBcnJheS5pc0FycmF5KGZpbHRlci52YWx1ZUdyb3VwcykpIHtcclxuICAgIHJldHVybiBmaWx0ZXIub2JqZWN0Q291bnQgPz8gMFxyXG4gIH1cclxuXHJcbiAgY29uc3QgaGFzSW5kaXZpZHVhbElkcyA9XHJcbiAgICBmaWx0ZXIudmFsdWVHcm91cHMubGVuZ3RoID4gMCAmJlxyXG4gICAgJ2lkJyBpbiBmaWx0ZXIudmFsdWVHcm91cHNbMF0gJiZcclxuICAgICEoJ2lkcycgaW4gZmlsdGVyLnZhbHVlR3JvdXBzWzBdKVxyXG5cclxuICBjb25zdCBvYmplY3RzV2l0aFByb3BlcnR5ID0gaGFzSW5kaXZpZHVhbElkc1xyXG4gICAgPyBmaWx0ZXIudmFsdWVHcm91cHMubGVuZ3RoIC8vIEVhY2ggdmFsdWVHcm91cCA9IG9uZSBvYmplY3RcclxuICAgIDogZmlsdGVyLnZhbHVlR3JvdXBzLnJlZHVjZSgodG90YWwsIHZnKSA9PiB7XHJcbiAgICAgICAgaWYgKCdpZHMnIGluIHZnICYmIEFycmF5LmlzQXJyYXkodmcuaWRzKSkge1xyXG4gICAgICAgICAgcmV0dXJuIHRvdGFsICsgdmcuaWRzLmxlbmd0aFxyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gdG90YWxcclxuICAgICAgfSwgMClcclxuXHJcbiAgaWYgKGNvbmRpdGlvbiA9PT0gRXhpc3RlbmNlRmlsdGVyQ29uZGl0aW9uLklzU2V0KSB7XHJcbiAgICByZXR1cm4gb2JqZWN0c1dpdGhQcm9wZXJ0eVxyXG4gIH0gZWxzZSB7XHJcbiAgICBjb25zdCByZWxldmFudE9iamVjdENvdW50ID0gZmlsdGVyLm9iamVjdENvdW50ID8/IHRvdGFsT2JqZWN0Q291bnQgPz8gMFxyXG4gICAgcmV0dXJuIE1hdGgubWF4KDAsIHJlbGV2YW50T2JqZWN0Q291bnQgLSBvYmplY3RzV2l0aFByb3BlcnR5KVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEluamVjdHMgZ3JhZGllbnQgZGF0YSBpbnRvIHRoZSBmaWx0ZXJpbmcgZGF0YSBzdG9yZSBzbyBpdCBjYW4gYmUgdXNlZCBmb3IgZmlsdGVyaW5nXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gaW5qZWN0R3JhZGllbnREYXRhSW50b0RhdGFTdG9yZShcclxuICBmaWx0ZXJpbmdEYXRhU3RvcmU6IHVua25vd24sXHJcbiAgcHJvcGVydHlLZXk6IHN0cmluZyxcclxuICBncmFkaWVudFZhbHVlczogUmVjb3JkPHN0cmluZywgeyBncmFkaWVudFZhbHVlOiBudW1iZXIgfT5cclxuKTogdm9pZCB7XHJcbiAgaWYgKCFmaWx0ZXJpbmdEYXRhU3RvcmUgfHwgT2JqZWN0LmtleXMoZ3JhZGllbnRWYWx1ZXMpLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgcmV0dXJuXHJcbiAgfVxyXG5cclxuICBjb25zdCBzdG9yZSA9IGZpbHRlcmluZ0RhdGFTdG9yZSBhcyB7XHJcbiAgICBkYXRhU291cmNlczoge1xyXG4gICAgICB2YWx1ZTogRGF0YVNvdXJjZVtdXHJcbiAgICB9XHJcbiAgfVxyXG4gIGlmICghc3RvcmUuZGF0YVNvdXJjZXM/LnZhbHVlKSB7XHJcbiAgICByZXR1cm5cclxuICB9XHJcblxyXG4gIGZvciAoY29uc3QgZGF0YVNvdXJjZSBvZiBzdG9yZS5kYXRhU291cmNlcy52YWx1ZSkge1xyXG4gICAgZm9yIChjb25zdCBbb2JqZWN0SWQsIHsgZ3JhZGllbnRWYWx1ZSB9XSBvZiBPYmplY3QuZW50cmllcyhncmFkaWVudFZhbHVlcykpIHtcclxuICAgICAgLy8gQWRkIHRoZSBncmFkaWVudCBwcm9wZXJ0eSB0byB0aGUgb2JqZWN0IGlmIGl0IGV4aXN0cyBpbiB0aGlzIGRhdGEgc291cmNlXHJcbiAgICAgIGlmIChkYXRhU291cmNlLm9iamVjdFByb3BlcnRpZXNbb2JqZWN0SWRdKSB7XHJcbiAgICAgICAgZGF0YVNvdXJjZS5vYmplY3RQcm9wZXJ0aWVzW29iamVjdElkXVtwcm9wZXJ0eUtleV0gPSBncmFkaWVudFZhbHVlXHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBBZGQgcHJvcGVydHkgaW5mbyB0byB0aGUgcHJvcGVydHlNYXAgaWYgbm90IGFscmVhZHkgcHJlc2VudFxyXG4gICAgaWYgKCFkYXRhU291cmNlLnByb3BlcnR5TWFwW3Byb3BlcnR5S2V5XSkge1xyXG4gICAgICBkYXRhU291cmNlLnByb3BlcnR5TWFwW3Byb3BlcnR5S2V5XSA9IHtcclxuICAgICAgICBjb25jYXRlbmF0ZWRQYXRoOiBwcm9wZXJ0eUtleSxcclxuICAgICAgICB2YWx1ZTogT2JqZWN0LnZhbHVlcyhncmFkaWVudFZhbHVlcylbMF0/LmdyYWRpZW50VmFsdWUgfHwgMCxcclxuICAgICAgICB0eXBlOiBGaWx0ZXJUeXBlLk51bWVyaWNcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE5hc3R5IHNtYXJ0c3kgb2JqZWN0IGZsYXR0ZW5lciB0aGF0IGN1cnJlbnRseSBpbmNsdWRlcyBzcGVjaWFsIGhhbmRsaW5nIGxvZ2ljIGZvciBSZXZpdCBvYmplY3RzXHJcbiAqIEBwYXJhbSBvYmogb2JqZWN0IHlvdSB3YW50IHRvIGV4dHJhY3QgdGhlIHByb3BlcnRpZXMgZnJvbVxyXG4gKiBAcGFyYW0gY3VycmVudFBhdGggZG8gbm90IHBhc3MgaW4gb24gZmlyc3QgY2FsbCwgdXNlZCBpbiByZWN1cnNpb25cclxuICogQHBhcmFtIGtub3duT2JqZWN0VHlwZSBkbyBub3QgcGFzcyBpbiBvbiBmaXJzdCBjYWxsLCB1c2VkIGluIHJlY3Vyc2lvblxyXG4gKiBAcGFyYW0gcm9vdE9iaiBkbyBub3QgcGFzcyBpbiBvbiBmaXJzdCBjYWxsLCB1c2VkIGluIHJlY3Vyc2lvblxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGNvbnN0IGV4dHJhY3ROZXN0ZWRQcm9wZXJ0aWVzID0gKFxyXG4gIG9iajogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXHJcbiAgY3VycmVudFBhdGg6IHN0cmluZ1tdID0gW10sXHJcbiAga25vd25PYmplY3RUeXBlPzogc3RyaW5nLFxyXG4gIHJvb3RPYmo/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPlxyXG4pID0+IHtcclxuICBjb25zdCBwcm9wZXJ0aWVzOiAoXHJcbiAgICB8IFByb3BlcnR5SW5mb0Jhc2VcclxuICAgIHwgUHJvcGVydHlJbmZvVmFsdWVcclxuICAgIHwgUGFyYW1ldGVyXHJcbiAgICB8IFJldml0TWF0ZXJpYWxQcm9wZXJ0eUluZm9cclxuICApW10gPSBbXVxyXG4gIHJvb3RPYmogPSByb290T2JqID8/IG9ialxyXG5cclxuICBrbm93bk9iamVjdFR5cGUgPVxyXG4gICAga25vd25PYmplY3RUeXBlID8/XHJcbiAgICAob2JqLnNwZWNrbGVfdHlwZSA9PT0gJ09iamVjdHMuRGF0YS5EYXRhT2JqZWN0Ok9iamVjdHMuRGF0YS5SZXZpdE9iamVjdCdcclxuICAgICAgPyAncmV2aXQnXHJcbiAgICAgIDogdW5kZWZpbmVkKVxyXG5cclxuICBmb3IgKGNvbnN0IGtleSBpbiBvYmopIHtcclxuICAgIGlmIChcclxuICAgICAgIU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmosIGtleSkgfHxcclxuICAgICAga2V5ID09PSAnX19jbG9zdXJlJyB8fFxyXG4gICAgICBrZXkgPT09ICdkaXNwbGF5VmFsdWUnIHx8XHJcbiAgICAgIChrbm93bk9iamVjdFR5cGUgPT09ICdyZXZpdCcgJiYgKGtleSA9PT0gJ2xvY2F0aW9uJyB8fCBrZXkgPT09ICdlbGVtZW50cycpKVxyXG4gICAgKVxyXG4gICAgICBjb250aW51ZVxyXG5cclxuICAgIC8vIGlmIChrZXkuaW5jbHVkZXMoJy4nKSkge1xyXG4gICAgLy8gICAvLyBMaWZlIGlzIGZ1biwgaXNuJ3QgaXRcclxuICAgIC8vICAgY29uc29sZS53YXJuKFxyXG4gICAgLy8gICAgICdPYmplY3QgY29udGFpbnMgYSBwcm9wZXJ0eSB0aGF0IGhhcyBhIC4gaW4gaXRzIG5hbWUuIFNraXBwaW5nIScsXHJcbiAgICAvLyAgICAga2V5LFxyXG4gICAgLy8gICAgIGN1cnJlbnRQYXRoLFxyXG4gICAgLy8gICAgIHJvb3RPYmpcclxuICAgIC8vICAgKVxyXG4gICAgLy8gICBjb250aW51ZVxyXG4gICAgLy8gfVxyXG5cclxuICAgIGlmIChrbm93bk9iamVjdFR5cGUgPT09ICdyZXZpdCcgJiYga2V5ID09PSAnTWF0ZXJpYWwgUXVhbnRpdGllcycpIHtcclxuICAgICAgZXh0cmFjdE1hdGVyaWFsUHJvcGVydGllcyhcclxuICAgICAgICBvYmpba2V5XSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcclxuICAgICAgICBbLi4uY3VycmVudFBhdGgsIGtleV0sXHJcbiAgICAgICAgcHJvcGVydGllc1xyXG4gICAgICApXHJcbiAgICAgIGNvbnRpbnVlXHJcbiAgICB9XHJcblxyXG4gICAgaWYgKFxyXG4gICAgICBrbm93bk9iamVjdFR5cGUgPT09ICdyZXZpdCcgJiZcclxuICAgICAga2V5ID09PSAnU3RydWN0dXJlJyAmJlxyXG4gICAgICBjdXJyZW50UGF0aFtjdXJyZW50UGF0aC5sZW5ndGggLSAxXSA9PT0gJ1R5cGUgUGFyYW1ldGVycydcclxuICAgICkge1xyXG4gICAgICAvLyBUT0RPOiBoYW5kbGUgbGF0ZXI7IGZvciBub3cgdGhpcyBpbnRyb2R1Y2VzIGdhcmJhZ2VcclxuICAgICAgY29udGludWVcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB2YWx1ZSA9IG9ialtrZXldXHJcbiAgICBjb25zdCBuZXdQYXRoID0gWy4uLmN1cnJlbnRQYXRoLCBrZXldXHJcbiAgICBjb25zdCBpc1BhcmFtID0gdmFsdWUgJiYgaXNQYXJhbWV0ZXIodmFsdWUpXHJcblxyXG4gICAgY29uc3QgaXNBY3R1YWxPYmplY3QgPVxyXG4gICAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICE9PSBudWxsICYmICFBcnJheS5pc0FycmF5KHZhbHVlKSAmJiAhaXNQYXJhbVxyXG5cclxuICAgIGlmIChpc0FjdHVhbE9iamVjdCkge1xyXG4gICAgICBwcm9wZXJ0aWVzLnB1c2goXHJcbiAgICAgICAgLi4uZXh0cmFjdE5lc3RlZFByb3BlcnRpZXMoXHJcbiAgICAgICAgICB2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcclxuICAgICAgICAgIG5ld1BhdGgsXHJcbiAgICAgICAgICBrbm93bk9iamVjdFR5cGUsXHJcbiAgICAgICAgICByb290T2JqXHJcbiAgICAgICAgKVxyXG4gICAgICApXHJcbiAgICB9IGVsc2UgaWYgKGlzUGFyYW0pIHtcclxuICAgICAgY29uc3QgcGFyYW0gPSB2YWx1ZSBhcyBQYXJhbWV0ZXJcclxuXHJcbiAgICAgIHByb3BlcnRpZXMucHVzaCh7XHJcbiAgICAgICAgbmFtZToga2V5LFxyXG4gICAgICAgIHBhdGg6IG5ld1BhdGgsXHJcbiAgICAgICAgY29uY2F0ZW5hdGVkUGF0aDogbmV3UGF0aC5qb2luKCcuJyksXHJcbiAgICAgICAgdHlwZTogZ2V0VmFsdWVUeXBlKHBhcmFtLnZhbHVlKSxcclxuICAgICAgICB1bml0czogcGFyYW0udW5pdHNcclxuICAgICAgfSlcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnN0IHZhbHVlVHlwZSA9IGdldFZhbHVlVHlwZSh2YWx1ZSlcclxuICAgICAgcHJvcGVydGllcy5wdXNoKHtcclxuICAgICAgICBuYW1lOiBrZXksXHJcbiAgICAgICAgcGF0aDogbmV3UGF0aCxcclxuICAgICAgICBjb25jYXRlbmF0ZWRQYXRoOiBuZXdQYXRoLmpvaW4oJy4nKSxcclxuICAgICAgICB0eXBlOiB2YWx1ZVR5cGVcclxuICAgICAgfSlcclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIHByb3BlcnRpZXMgYXMgUHJvcGVydHlJbmZvQmFzZVtdXHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldFZhbHVlVHlwZSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XHJcbiAgaWYgKHZhbHVlID09PSBudWxsKSByZXR1cm4gJ251bGwnXHJcbiAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSByZXR1cm4gJ2FycmF5J1xyXG5cclxuICBpZiAoaXNWYWx1ZUJvb2xlYW4odmFsdWUpKSByZXR1cm4gJ2Jvb2xlYW4nXHJcbiAgaWYgKGlzVmFsdWVOdW1lcmljKHZhbHVlKSkgcmV0dXJuICdudW1iZXInXHJcblxyXG4gIHJldHVybiAnc3RyaW5nJ1xyXG59XHJcblxyXG5mdW5jdGlvbiBleHRyYWN0TWF0ZXJpYWxQcm9wZXJ0aWVzKFxyXG4gIG1hdFF1YW50czogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXHJcbiAgcGF0aDogc3RyaW5nW10sXHJcbiAgcHJvcGVydGllczogKFxyXG4gICAgfCBQcm9wZXJ0eUluZm9CYXNlXHJcbiAgICB8IFByb3BlcnR5SW5mb1ZhbHVlXHJcbiAgICB8IFBhcmFtZXRlclxyXG4gICAgfCBSZXZpdE1hdGVyaWFsUHJvcGVydHlJbmZvXHJcbiAgKVtdXHJcbikge1xyXG4gIGZvciAoY29uc3QgbWF0TmFtZSBpbiBtYXRRdWFudHMpIHtcclxuICAgIGNvbnN0IG1hdEluZm8gPSBtYXRRdWFudHNbbWF0TmFtZV0gYXMgUmV2aXRNYXRlcmlhbEluZm9cclxuXHJcbiAgICBjb25zdCBhcmVhUHJvcDogUmV2aXRNYXRlcmlhbFByb3BlcnR5SW5mbyB8IHVuZGVmaW5lZCA9IG1hdEluZm8uYXJlYVxyXG4gICAgICA/IHtcclxuICAgICAgICAgIHBhdGgsXHJcbiAgICAgICAgICBjb25jYXRlbmF0ZWRQYXRoOiBwYXRoLmpvaW4oJy4nKSxcclxuICAgICAgICAgIHR5cGU6ICdudW1iZXInLFxyXG4gICAgICAgICAgbmFtZTogYCR7bWF0TmFtZX0gLSBhcmVhYCxcclxuICAgICAgICAgIHZhbHVlOiBtYXRJbmZvLmFyZWEudmFsdWUsXHJcbiAgICAgICAgICB1bml0czogbWF0SW5mby5hcmVhLnVuaXRzLFxyXG4gICAgICAgICAgbWF0ZXJpYWxDYXRlZ29yeTogbWF0SW5mby5tYXRlcmlhbENhdGVnb3J5LFxyXG4gICAgICAgICAgbWF0ZXJpYWxDbGFzczogbWF0SW5mby5tYXRlcmlhbENsYXNzXHJcbiAgICAgICAgfVxyXG4gICAgICA6IHVuZGVmaW5lZFxyXG5cclxuICAgIGNvbnN0IHZvbHVtZVByb3A6IFJldml0TWF0ZXJpYWxQcm9wZXJ0eUluZm8gfCB1bmRlZmluZWQgPSBtYXRJbmZvLnZvbHVtZVxyXG4gICAgICA/IHtcclxuICAgICAgICAgIHBhdGgsXHJcbiAgICAgICAgICBjb25jYXRlbmF0ZWRQYXRoOiBwYXRoLmpvaW4oJy4nKSxcclxuICAgICAgICAgIHR5cGU6ICdudW1iZXInLFxyXG4gICAgICAgICAgbmFtZTogYCR7bWF0TmFtZX0gLSB2b2x1bWVgLFxyXG4gICAgICAgICAgdmFsdWU6IG1hdEluZm8udm9sdW1lLnZhbHVlLFxyXG4gICAgICAgICAgdW5pdHM6IG1hdEluZm8udm9sdW1lLnVuaXRzLFxyXG4gICAgICAgICAgbWF0ZXJpYWxDYXRlZ29yeTogbWF0SW5mby5tYXRlcmlhbENhdGVnb3J5LFxyXG4gICAgICAgICAgbWF0ZXJpYWxDbGFzczogbWF0SW5mby5tYXRlcmlhbENsYXNzXHJcbiAgICAgICAgfVxyXG4gICAgICA6IHVuZGVmaW5lZFxyXG4gICAgaWYgKGFyZWFQcm9wKSBwcm9wZXJ0aWVzLnB1c2goYXJlYVByb3ApXHJcbiAgICBpZiAodm9sdW1lUHJvcCkgcHJvcGVydGllcy5wdXNoKHZvbHVtZVByb3ApXHJcbiAgfVxyXG59XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gaXNQYXJhbWV0ZXIodmFsdWU6IHVua25vd24pIHtcclxuICByZXR1cm4gKFxyXG4gICAgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJlxyXG4gICAgT2JqZWN0Lmhhc093bih2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgJ25hbWUnKSAmJlxyXG4gICAgT2JqZWN0Lmhhc093bih2YWx1ZSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgJ3ZhbHVlJylcclxuICApXHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBpc1Jldml0TWF0ZXJpYWxRdWFudGl0eSh2YWx1ZTogdW5rbm93bikge1xyXG4gIHJldHVybiAoXHJcbiAgICB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmXHJcbiAgICBpc1BhcmFtZXRlcih2YWx1ZSkgJiZcclxuICAgIE9iamVjdC5oYXNPd24odmFsdWUgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sICdtYXRlcmlhbENhdGVnb3J5JykgJiZcclxuICAgIE9iamVjdC5oYXNPd24odmFsdWUgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sICdtYXRlcmlhbENsYXNzJylcclxuICApXHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXROZXN0ZWRQcm9wZXJ0aWVzKG9iajogdW5rbm93biwgcHJvcGVydGllczogUHJvcGVydHlJbmZvQmFzZVtdKSB7XHJcbiAgY29uc3QgdmFsdWVzID0gW11cclxuICBmb3IgKGNvbnN0IHByb3Agb2YgcHJvcGVydGllcykge1xyXG4gICAgY29uc3QgdmFsdWUgPSBwcm9wLnBhdGgucmVkdWNlKFxyXG4gICAgICAoY3VycmVudDogdW5rbm93biwga2V5OiBzdHJpbmcpID0+IChjdXJyZW50IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KT8uW2tleV0sXHJcbiAgICAgIG9ialxyXG4gICAgKVxyXG4gICAgaWYgKHZhbHVlICYmIGlzUGFyYW1ldGVyKHZhbHVlKSkge1xyXG4gICAgICB2YWx1ZXMucHVzaCgodmFsdWUgYXMgUGFyYW1ldGVyKS52YWx1ZSlcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHZhbHVlcy5wdXNoKHZhbHVlID8/IHVuZGVmaW5lZClcclxuICAgIH1cclxuICB9XHJcbiAgcmV0dXJuIHZhbHVlc1xyXG59XHJcbiJdLCJtYXBwaW5ncyI6IkFBQUEsU0FBUyw0QkFBNEI7QUFDckMsU0FBUyxVQUFVLFVBQVUsV0FBVyxnQkFBZ0I7QUFDeEQ7QUFBQSxFQUNFO0FBQUEsRUFDQTtBQUFBLE9BU0s7QUFFQSxhQUFNLHFCQUFxQjtBQUMzQixhQUFNLHlDQUF5QztBQUMvQyxhQUFNLHFDQUFxQztBQUszQyxhQUFNLGtCQUFrQixDQUFDLFFBQXlCO0FBQ3ZELFNBQ0UsbUJBQW1CLEtBQUssR0FBRyxLQUMzQix1Q0FBdUMsS0FBSyxHQUFHLEtBQy9DLG1DQUFtQyxLQUFLLEdBQUc7QUFFL0M7QUFLTyxhQUFNLDZCQUE2QixDQUFDLFFBQXlCO0FBRWxFLFFBQU0sWUFBWSxJQUFJLE1BQU0sR0FBRztBQUMvQixRQUFNLFdBQVcsVUFBVSxVQUFVLFNBQVMsQ0FBQztBQUcvQyxNQUFJLENBQUMsZ0JBQWdCLGFBQWEsUUFBUSxnQkFBZ0IsRUFBRSxTQUFTLFFBQVEsR0FBRztBQUM5RSxXQUFPO0FBQUEsRUFDVDtBQUVBLE1BQ0UsSUFBSSxTQUFTLFFBQVEsS0FDckIsSUFBSSxTQUFTLGVBQWUsS0FDNUIsSUFBSSxTQUFTLGNBQWMsS0FDM0IsSUFBSSxTQUFTLGdCQUFnQixLQUM3QixJQUFJLFNBQVMsU0FBUyxLQUN0QixJQUFJLFNBQVMsUUFBUSxLQUNyQixJQUFJLFNBQVMsVUFBVSxLQUN2QixJQUFJLFNBQVMsZUFBZSxLQUM1QixJQUFJLFNBQVMsTUFBTSxLQUNuQixJQUFJLFNBQVMsUUFBUSxLQUNyQixJQUFJLFNBQVMsV0FBVyxLQUN4QixJQUFJLFNBQVMsV0FBVyxLQUN4QixJQUFJLFNBQVMsYUFBYSxLQUMxQixJQUFJLFNBQVMsZUFBZSxLQUM1QixJQUFJLFNBQVMsZ0JBQWdCLEtBQzdCLElBQUksU0FBUyxtQkFBbUIsS0FDaEMsSUFBSSxTQUFTLGNBQWMsS0FDM0IsSUFBSSxTQUFTLGNBQWMsS0FDM0IsSUFBSSxTQUFTLGFBQWEsS0FDMUIsSUFBSSxXQUFXLElBQUksR0FDbkI7QUFDQSxXQUFPO0FBQUEsRUFDVDtBQUVBLE1BQUksZ0JBQWdCLEdBQUcsR0FBRztBQUN4QixRQUFJLElBQUksU0FBUyxRQUFRLEVBQUcsUUFBTztBQUFBLFFBQzlCLFFBQU87QUFBQSxFQUNkO0FBRUEsU0FBTztBQUNUO0FBS08sYUFBTSxrQkFBa0IsQ0FDN0IsS0FDQSxxQkFDVztBQUNYLE1BQUksQ0FBQyxJQUFLLFFBQU87QUFFakIsTUFBSSxRQUFRLGFBQWMsUUFBTztBQUNqQyxNQUFJLFFBQVEsZUFBZ0IsUUFBTztBQUVuQyxNQUFJLGdCQUFnQixHQUFHLEtBQUssSUFBSSxTQUFTLFFBQVEsR0FBRztBQUNsRCxVQUFNLHlCQUF5QixvQkFBb0IsQ0FBQyxHQUFHO0FBQUEsTUFDckQsQ0FBQyxNQUE0QixFQUFFLFFBQVEsSUFBSSxRQUFRLFVBQVUsT0FBTztBQUFBLElBQ3RFO0FBQ0EsUUFBSSx5QkFBeUIscUJBQXFCLHFCQUFxQixHQUFHO0FBQ3hFLGFBQU8sc0JBQXNCLFlBQVksQ0FBQyxHQUFHLFNBQVMsSUFBSSxNQUFNLEdBQUcsRUFBRSxJQUFJLEtBQUs7QUFBQSxJQUNoRjtBQUFBLEVBQ0Y7QUFFQSxTQUFPLElBQUksTUFBTSxHQUFHLEVBQUUsSUFBSSxLQUFLO0FBQ2pDO0FBS08sYUFBTSwwQkFBMEIsQ0FDckMsWUFDQSxxQkFDcUM7QUFDckMsTUFBSSxDQUFDLGlCQUFrQixRQUFPO0FBRzlCLFFBQU0sb0JBQW9CLGlCQUFpQixLQUFLLENBQUMsTUFBTTtBQUNyRCxVQUFNLHNCQUFzQixnQkFBZ0IsRUFBRSxLQUFLLGdCQUFnQjtBQUNuRSxXQUFPLHdCQUF3QjtBQUFBLEVBQ2pDLENBQUM7QUFDRCxNQUFJLGtCQUFtQixRQUFPO0FBRzlCLFFBQU0sYUFBYSxpQkFDaEIsT0FBTyxDQUFDLE1BQU0sRUFBRSxJQUFJLE1BQU0sR0FBRyxFQUFFLElBQUksTUFBTSxVQUFVLEVBQ25ELEtBQUssQ0FBQyxHQUFHLE1BQU0sRUFBRSxJQUFJLFNBQVMsRUFBRSxJQUFJLE1BQU07QUFFN0MsU0FBTyxXQUFXLENBQUM7QUFDckI7QUFLTyxhQUFNLGtCQUFrQixDQUM3QixLQUNBLHFCQUNZO0FBRVosUUFBTSxjQUFjLElBQUksZUFBZSxJQUFJO0FBRTNDLFFBQU0sY0FBYyxrQkFBa0IsS0FBSyxDQUFDLE1BQU0sRUFBRSxRQUFRLFdBQVc7QUFDdkUsTUFBSSxhQUFhO0FBQ2YsV0FBTyxDQUFDLDJCQUEyQixXQUFXO0FBQUEsRUFDaEQ7QUFFQSxRQUFNLGFBQWEsSUFBSTtBQUN2QixRQUFNLHFCQUFxQix3QkFBd0IsWUFBWSxnQkFBZ0I7QUFFL0UsTUFBSSxvQkFBb0I7QUFDdEIsV0FBTyxDQUFDLDJCQUEyQixtQkFBbUIsR0FBRztBQUFBLEVBQzNEO0FBRUEsU0FBTztBQUNUO0FBS08sYUFBTSwwQkFBMEIsQ0FDckMsS0FDQSxxQkFDVztBQUNYLFFBQU0sZ0JBQWdCLGtCQUFrQixJQUFJLENBQUMsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDO0FBRTlELE1BQUksSUFBSSxhQUFhO0FBQ25CLFFBQUksQ0FBQyxjQUFjLFNBQVMsSUFBSSxXQUFXLEdBQUc7QUFDNUMsWUFBTSxlQUFlLElBQUk7QUFDekIsWUFBTSxlQUFlLGNBQWM7QUFBQSxRQUNqQyxDQUFDLFFBQVEsSUFBSSxNQUFNLEdBQUcsRUFBRSxJQUFJLE1BQU07QUFBQSxNQUNwQztBQUVBLFVBQUksYUFBYSxTQUFTLEdBQUc7QUFDM0IsZUFBTyxrQkFDTCxJQUFJLFdBQ04sb0NBQW9DLGFBQWEsTUFBTSxHQUFHLENBQUMsRUFBRSxLQUFLLElBQUksQ0FBQztBQUFBLE1BQ3pFO0FBRUEsYUFBTyxrQkFBa0IsSUFBSSxXQUFXO0FBQUEsSUFDMUM7QUFFQSxRQUFJLDJCQUEyQixJQUFJLFdBQVcsR0FBRztBQUMvQyxhQUFPLGFBQWEsSUFBSSxXQUFXO0FBQUEsSUFDckM7QUFBQSxFQUNGLE9BQU87QUFFTCxVQUFNLGNBQWMsSUFBSTtBQUN4QixRQUFJLENBQUMsY0FBYyxTQUFTLFdBQVcsR0FBRztBQUN4QyxZQUFNLGNBQWMsY0FBYztBQUFBLFFBQ2hDLENBQUMsUUFDQyxJQUFJLFlBQVksRUFBRSxTQUFTLE1BQU0sS0FDakMsSUFBSSxZQUFZLEVBQUUsU0FBUyxVQUFVLEtBQ3JDLElBQUksWUFBWSxFQUFFLFNBQVMsT0FBTztBQUFBLE1BQ3RDO0FBRUEsWUFBTSxZQUNKLFlBQVksU0FBUyxJQUNqQix3QkFBd0IsWUFBWSxNQUFNLEdBQUcsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLE1BQzFEO0FBRU4sYUFBTyxhQUFhLFdBQVcsMENBQTBDLFNBQVM7QUFBQSxJQUNwRjtBQUVBLFFBQUksMkJBQTJCLFdBQVcsR0FBRztBQUMzQyxhQUFPLGFBQWEsV0FBVztBQUFBLElBQ2pDO0FBQUEsRUFDRjtBQUVBLFNBQU87QUFDVDtBQUtPLGFBQU0sa0JBQWtCLENBQzdCLEtBQ0EscUJBQ3FDO0FBQ3JDLE1BQUksQ0FBQyxpQkFBa0IsUUFBTztBQUU5QixNQUFJLElBQUksYUFBYTtBQUNuQixVQUFNLGFBQWEsaUJBQWlCO0FBQUEsTUFDbEMsQ0FBQyxNQUE0QixFQUFFLFFBQVEsSUFBSTtBQUFBLElBQzdDO0FBQ0EsUUFBSSxZQUFZO0FBQ2QsYUFBTztBQUFBLElBQ1Q7QUFBQSxFQUNGO0FBRUEsUUFBTSxjQUFjLGlCQUFpQjtBQUFBLElBQ25DLENBQUMsTUFBNEIsRUFBRSxRQUFRLElBQUk7QUFBQSxFQUM3QztBQUNBLE1BQUksYUFBYTtBQUNmLFdBQU87QUFBQSxFQUNUO0FBR0EsTUFBSSxJQUFJLGFBQWE7QUFDbkIsVUFBTSxZQUFZLElBQUksWUFBWSxNQUFNLEdBQUc7QUFDM0MsVUFBTSxpQkFBaUIsaUJBQWlCLE9BQU8sQ0FBQyxNQUE0QjtBQUMxRSxZQUFNLGNBQWMsRUFBRSxJQUFJLE1BQU0sR0FBRztBQUVuQyxVQUFJLFVBQVUsV0FBVyxHQUFHO0FBQzFCLGVBQU8sWUFBWSxZQUFZLFNBQVMsQ0FBQyxNQUFNLFVBQVUsQ0FBQztBQUFBLE1BQzVEO0FBRUEsVUFBSSxVQUFVLFVBQVUsS0FBSyxZQUFZLFVBQVUsR0FBRztBQUNwRCxjQUFNLFNBQVMsVUFBVSxNQUFNLEVBQUUsRUFBRSxLQUFLLEdBQUc7QUFDM0MsY0FBTSxZQUFZLFlBQVksTUFBTSxFQUFFLEVBQUUsS0FBSyxHQUFHO0FBQ2hELGVBQU8sV0FBVztBQUFBLE1BQ3BCO0FBRUEsYUFBTztBQUFBLElBQ1QsQ0FBQztBQUVELFFBQUksZUFBZSxXQUFXLEdBQUc7QUFDL0IsYUFBTyxlQUFlLENBQUM7QUFBQSxJQUN6QjtBQUVBLFFBQUksZUFBZSxTQUFTLEdBQUc7QUFDN0IsWUFBTSxnQkFBZ0IsZUFBZSxLQUFLLENBQUMsR0FBRyxNQUFNLEVBQUUsSUFBSSxTQUFTLEVBQUUsSUFBSSxNQUFNO0FBQy9FLGFBQU8sY0FBYyxDQUFDO0FBQUEsSUFDeEI7QUFFQSxXQUFPO0FBQUEsRUFDVDtBQUdBLFFBQU0sYUFBYSxJQUFJO0FBQ3ZCLFNBQU8sd0JBQXdCLFlBQVksZ0JBQWdCO0FBQzdEO0FBRU8sYUFBTSxvQkFBb0IsQ0FBQyxXQUEwQztBQUMxRSxTQUFPLFVBQVUsVUFBVyxPQUE0QixTQUFTO0FBQ25FO0FBS08sYUFBTSxpQkFBaUIsQ0FBQyxVQUE0QjtBQUN6RCxNQUFJLFNBQVMsS0FBSyxFQUFHLFFBQU8sT0FBTyxTQUFTLEtBQUs7QUFFakQsTUFBSSxTQUFTLEtBQUssR0FBRztBQUNuQixVQUFNLFVBQVUsTUFBTSxLQUFLO0FBQzNCLFFBQUksWUFBWSxHQUFJLFFBQU87QUFHM0IsUUFBSSxPQUFPLEtBQUssT0FBTyxFQUFHLFFBQU87QUFDakMsUUFBSSxRQUFRLFNBQVMsR0FBRyxLQUFLLENBQUMsUUFBUSxXQUFXLEdBQUcsRUFBRyxRQUFPO0FBRTlELFVBQU0sWUFBWSxTQUFTLE9BQU87QUFDbEMsV0FBTyxPQUFPLFNBQVMsU0FBUztBQUFBLEVBQ2xDO0FBRUEsU0FBTztBQUNUO0FBS08sYUFBTSxpQkFBaUIsQ0FBQyxVQUE0QjtBQUN6RCxNQUFJLFVBQVUsS0FBSyxFQUFHLFFBQU87QUFDN0IsTUFBSSxTQUFTLEtBQUssR0FBRztBQUNuQixVQUFNLE1BQU0sTUFBTSxZQUFZO0FBQzlCLFdBQU8sUUFBUSxVQUFVLFFBQVE7QUFBQSxFQUNuQztBQUNBLFNBQU87QUFDVDtBQUtPLGFBQU0scUJBQXFCLENBQUMsVUFBNEI7QUFDN0QsU0FBTyxVQUFVLFFBQVMsU0FBUyxLQUFLLEtBQUssTUFBTSxZQUFZLE1BQU07QUFDdkU7QUFLTyxhQUFNLHNCQUFzQixDQUFDLFVBQTRCO0FBQzlELFNBQU8sVUFBVSxTQUFVLFNBQVMsS0FBSyxLQUFLLE1BQU0sWUFBWSxNQUFNO0FBQ3hFO0FBS08sZ0JBQVMsb0JBQ2QsUUFDQSxPQUNRO0FBQ1IsTUFBSSxFQUFFLGlCQUFpQixXQUFXLENBQUMsTUFBTSxRQUFRLE9BQU8sV0FBVyxHQUFHO0FBQ3BFLFdBQU87QUFBQSxFQUNUO0FBRUEsUUFBTSxjQUFjLE9BQU87QUFFM0IsYUFBVyxNQUFNLGFBQWE7QUFDNUIsUUFBSSxPQUFPLEdBQUcsS0FBSyxNQUFNLE9BQU87QUFDOUIsYUFBTyxHQUFHLEtBQUssVUFBVTtBQUFBLElBQzNCO0FBQUEsRUFDRjtBQUVBLFNBQU87QUFDVDtBQUtPLGdCQUFTLHdCQUNkLFFBQ0EsV0FDQSxrQkFDUTtBQUNSLE1BQUksRUFBRSxpQkFBaUIsV0FBVyxDQUFDLE1BQU0sUUFBUSxPQUFPLFdBQVcsR0FBRztBQUNwRSxXQUFPLE9BQU8sZUFBZTtBQUFBLEVBQy9CO0FBRUEsUUFBTSxtQkFDSixPQUFPLFlBQVksU0FBUyxLQUM1QixRQUFRLE9BQU8sWUFBWSxDQUFDLEtBQzVCLEVBQUUsU0FBUyxPQUFPLFlBQVksQ0FBQztBQUVqQyxRQUFNLHNCQUFzQixtQkFDeEIsT0FBTyxZQUFZLFNBQ25CLE9BQU8sWUFBWSxPQUFPLENBQUMsT0FBTyxPQUFPO0FBQ3ZDLFFBQUksU0FBUyxNQUFNLE1BQU0sUUFBUSxHQUFHLEdBQUcsR0FBRztBQUN4QyxhQUFPLFFBQVEsR0FBRyxJQUFJO0FBQUEsSUFDeEI7QUFDQSxXQUFPO0FBQUEsRUFDVCxHQUFHLENBQUM7QUFFUixNQUFJLGNBQWMseUJBQXlCLE9BQU87QUFDaEQsV0FBTztBQUFBLEVBQ1QsT0FBTztBQUNMLFVBQU0sc0JBQXNCLE9BQU8sZUFBZSxvQkFBb0I7QUFDdEUsV0FBTyxLQUFLLElBQUksR0FBRyxzQkFBc0IsbUJBQW1CO0FBQUEsRUFDOUQ7QUFDRjtBQUtPLGdCQUFTLGdDQUNkLG9CQUNBLGFBQ0EsZ0JBQ007QUFDTixNQUFJLENBQUMsc0JBQXNCLE9BQU8sS0FBSyxjQUFjLEVBQUUsV0FBVyxHQUFHO0FBQ25FO0FBQUEsRUFDRjtBQUVBLFFBQU0sUUFBUTtBQUtkLE1BQUksQ0FBQyxNQUFNLGFBQWEsT0FBTztBQUM3QjtBQUFBLEVBQ0Y7QUFFQSxhQUFXLGNBQWMsTUFBTSxZQUFZLE9BQU87QUFDaEQsZUFBVyxDQUFDLFVBQVUsRUFBRSxjQUFjLENBQUMsS0FBSyxPQUFPLFFBQVEsY0FBYyxHQUFHO0FBRTFFLFVBQUksV0FBVyxpQkFBaUIsUUFBUSxHQUFHO0FBQ3pDLG1CQUFXLGlCQUFpQixRQUFRLEVBQUUsV0FBVyxJQUFJO0FBQUEsTUFDdkQ7QUFBQSxJQUNGO0FBR0EsUUFBSSxDQUFDLFdBQVcsWUFBWSxXQUFXLEdBQUc7QUFDeEMsaUJBQVcsWUFBWSxXQUFXLElBQUk7QUFBQSxRQUNwQyxrQkFBa0I7QUFBQSxRQUNsQixPQUFPLE9BQU8sT0FBTyxjQUFjLEVBQUUsQ0FBQyxHQUFHLGlCQUFpQjtBQUFBLFFBQzFELE1BQU0sV0FBVztBQUFBLE1BQ25CO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRjtBQVVPLGFBQU0sMEJBQTBCLENBQ3JDLEtBQ0EsY0FBd0IsQ0FBQyxHQUN6QixpQkFDQSxZQUNHO0FBQ0gsUUFBTSxhQUtBLENBQUM7QUFDUCxZQUFVLFdBQVc7QUFFckIsb0JBQ0Usb0JBQ0MsSUFBSSxpQkFBaUIscURBQ2xCLFVBQ0E7QUFFTixhQUFXLE9BQU8sS0FBSztBQUNyQixRQUNFLENBQUMsT0FBTyxVQUFVLGVBQWUsS0FBSyxLQUFLLEdBQUcsS0FDOUMsUUFBUSxlQUNSLFFBQVEsa0JBQ1Asb0JBQW9CLFlBQVksUUFBUSxjQUFjLFFBQVE7QUFFL0Q7QUFhRixRQUFJLG9CQUFvQixXQUFXLFFBQVEsdUJBQXVCO0FBQ2hFO0FBQUEsUUFDRSxJQUFJLEdBQUc7QUFBQSxRQUNQLENBQUMsR0FBRyxhQUFhLEdBQUc7QUFBQSxRQUNwQjtBQUFBLE1BQ0Y7QUFDQTtBQUFBLElBQ0Y7QUFFQSxRQUNFLG9CQUFvQixXQUNwQixRQUFRLGVBQ1IsWUFBWSxZQUFZLFNBQVMsQ0FBQyxNQUFNLG1CQUN4QztBQUVBO0FBQUEsSUFDRjtBQUVBLFVBQU0sUUFBUSxJQUFJLEdBQUc7QUFDckIsVUFBTSxVQUFVLENBQUMsR0FBRyxhQUFhLEdBQUc7QUFDcEMsVUFBTSxVQUFVLFNBQVMsWUFBWSxLQUFLO0FBRTFDLFVBQU0saUJBQ0osT0FBTyxVQUFVLFlBQVksVUFBVSxRQUFRLENBQUMsTUFBTSxRQUFRLEtBQUssS0FBSyxDQUFDO0FBRTNFLFFBQUksZ0JBQWdCO0FBQ2xCLGlCQUFXO0FBQUEsUUFDVCxHQUFHO0FBQUEsVUFDRDtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFFBQ0Y7QUFBQSxNQUNGO0FBQUEsSUFDRixXQUFXLFNBQVM7QUFDbEIsWUFBTSxRQUFRO0FBRWQsaUJBQVcsS0FBSztBQUFBLFFBQ2QsTUFBTTtBQUFBLFFBQ04sTUFBTTtBQUFBLFFBQ04sa0JBQWtCLFFBQVEsS0FBSyxHQUFHO0FBQUEsUUFDbEMsTUFBTSxhQUFhLE1BQU0sS0FBSztBQUFBLFFBQzlCLE9BQU8sTUFBTTtBQUFBLE1BQ2YsQ0FBQztBQUFBLElBQ0gsT0FBTztBQUNMLFlBQU0sWUFBWSxhQUFhLEtBQUs7QUFDcEMsaUJBQVcsS0FBSztBQUFBLFFBQ2QsTUFBTTtBQUFBLFFBQ04sTUFBTTtBQUFBLFFBQ04sa0JBQWtCLFFBQVEsS0FBSyxHQUFHO0FBQUEsUUFDbEMsTUFBTTtBQUFBLE1BQ1IsQ0FBQztBQUFBLElBQ0g7QUFBQSxFQUNGO0FBQ0EsU0FBTztBQUNUO0FBRUEsU0FBUyxhQUFhLE9BQXdCO0FBQzVDLE1BQUksVUFBVSxLQUFNLFFBQU87QUFDM0IsTUFBSSxNQUFNLFFBQVEsS0FBSyxFQUFHLFFBQU87QUFFakMsTUFBSSxlQUFlLEtBQUssRUFBRyxRQUFPO0FBQ2xDLE1BQUksZUFBZSxLQUFLLEVBQUcsUUFBTztBQUVsQyxTQUFPO0FBQ1Q7QUFFQSxTQUFTLDBCQUNQLFdBQ0EsTUFDQSxZQU1BO0FBQ0EsYUFBVyxXQUFXLFdBQVc7QUFDL0IsVUFBTSxVQUFVLFVBQVUsT0FBTztBQUVqQyxVQUFNLFdBQWtELFFBQVEsT0FDNUQ7QUFBQSxNQUNFO0FBQUEsTUFDQSxrQkFBa0IsS0FBSyxLQUFLLEdBQUc7QUFBQSxNQUMvQixNQUFNO0FBQUEsTUFDTixNQUFNLEdBQUcsT0FBTztBQUFBLE1BQ2hCLE9BQU8sUUFBUSxLQUFLO0FBQUEsTUFDcEIsT0FBTyxRQUFRLEtBQUs7QUFBQSxNQUNwQixrQkFBa0IsUUFBUTtBQUFBLE1BQzFCLGVBQWUsUUFBUTtBQUFBLElBQ3pCLElBQ0E7QUFFSixVQUFNLGFBQW9ELFFBQVEsU0FDOUQ7QUFBQSxNQUNFO0FBQUEsTUFDQSxrQkFBa0IsS0FBSyxLQUFLLEdBQUc7QUFBQSxNQUMvQixNQUFNO0FBQUEsTUFDTixNQUFNLEdBQUcsT0FBTztBQUFBLE1BQ2hCLE9BQU8sUUFBUSxPQUFPO0FBQUEsTUFDdEIsT0FBTyxRQUFRLE9BQU87QUFBQSxNQUN0QixrQkFBa0IsUUFBUTtBQUFBLE1BQzFCLGVBQWUsUUFBUTtBQUFBLElBQ3pCLElBQ0E7QUFDSixRQUFJLFNBQVUsWUFBVyxLQUFLLFFBQVE7QUFDdEMsUUFBSSxXQUFZLFlBQVcsS0FBSyxVQUFVO0FBQUEsRUFDNUM7QUFDRjtBQUVPLGdCQUFTLFlBQVksT0FBZ0I7QUFDMUMsU0FDRSxPQUFPLFVBQVUsWUFDakIsT0FBTyxPQUFPLE9BQWtDLE1BQU0sS0FDdEQsT0FBTyxPQUFPLE9BQWtDLE9BQU87QUFFM0Q7QUFFTyxnQkFBUyx3QkFBd0IsT0FBZ0I7QUFDdEQsU0FDRSxPQUFPLFVBQVUsWUFDakIsWUFBWSxLQUFLLEtBQ2pCLE9BQU8sT0FBTyxPQUFrQyxrQkFBa0IsS0FDbEUsT0FBTyxPQUFPLE9BQWtDLGVBQWU7QUFFbkU7QUFFTyxnQkFBUyxvQkFBb0IsS0FBYyxZQUFnQztBQUNoRixRQUFNLFNBQVMsQ0FBQztBQUNoQixhQUFXLFFBQVEsWUFBWTtBQUM3QixVQUFNLFFBQVEsS0FBSyxLQUFLO0FBQUEsTUFDdEIsQ0FBQyxTQUFrQixRQUFpQixVQUFzQyxHQUFHO0FBQUEsTUFDN0U7QUFBQSxJQUNGO0FBQ0EsUUFBSSxTQUFTLFlBQVksS0FBSyxHQUFHO0FBQy9CLGFBQU8sS0FBTSxNQUFvQixLQUFLO0FBQUEsSUFDeEMsT0FBTztBQUNMLGFBQU8sS0FBSyxTQUFTLE1BQVM7QUFBQSxJQUNoQztBQUFBLEVBQ0Y7QUFDQSxTQUFPO0FBQ1Q7IiwibmFtZXMiOltdfQ==