340 lines
43 KiB
Plaintext
340 lines
43 KiB
Plaintext
import { uniq, flatten, compact, isString } from "/_nuxt/node_modules/.cache/vite/client/deps/lodash-es.js?v=e4f18c29";
|
|
import {
|
|
FilterLogic,
|
|
FilterType,
|
|
NumericFilterCondition,
|
|
StringFilterCondition,
|
|
ExistenceFilterCondition,
|
|
BooleanFilterCondition
|
|
} from "/_nuxt/lib/viewer/helpers/filters/types.ts";
|
|
import { useInjectedViewerState } from "/_nuxt/lib/viewer/composables/setup.ts";
|
|
import {
|
|
shouldExcludeFromFiltering,
|
|
extractNestedProperties,
|
|
isParameter,
|
|
isValueNumeric,
|
|
isValueBooleanTrue,
|
|
isValueBooleanFalse
|
|
} from "/_nuxt/lib/viewer/helpers/filters/utils.ts";
|
|
import { DEEP_EXTRACTION_CONFIG } from "/_nuxt/lib/viewer/helpers/filters/constants.ts";
|
|
|
|
import { ref, computed, markRaw } from "/_nuxt/node_modules/vue/dist/vue.runtime.esm-bundler.js?v=e4f18c29";
|
|
function processBatchedPropertyUpdates(updates, propertyMap) {
|
|
for (const update of updates) {
|
|
const existingProperty = propertyMap[update.path];
|
|
if (!existingProperty) {
|
|
let filterType;
|
|
if (update.type === "number") {
|
|
filterType = FilterType.Numeric;
|
|
} else if (update.type === "boolean") {
|
|
filterType = FilterType.Boolean;
|
|
} else {
|
|
filterType = FilterType.String;
|
|
}
|
|
propertyMap[update.path] = {
|
|
concatenatedPath: update.path,
|
|
value: update.value,
|
|
type: filterType
|
|
};
|
|
} else {
|
|
if (existingProperty.type === FilterType.Numeric && isString(update.value) && !isValueNumeric(update.value)) {
|
|
existingProperty.type = FilterType.String;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
export function useCreateViewerFilteringDataStore() {
|
|
const dataSourcesMap = ref({});
|
|
const dataSources = computed(() => Object.values(dataSourcesMap.value));
|
|
const currentFilterLogic = ref(FilterLogic.All);
|
|
const dataSlices = ref([]);
|
|
const populateDataStore = async (viewer, resources) => {
|
|
const tree = viewer.getWorldTree();
|
|
if (!tree) return;
|
|
for (const res of resources) {
|
|
const foundNodes = tree.findId(res.resourceUrl);
|
|
const subnode = foundNodes?.[0];
|
|
if (!subnode) {
|
|
continue;
|
|
}
|
|
const objectMap = {};
|
|
const propertyMap = {};
|
|
const objectProperties = {};
|
|
const defProxyByAppId = /* @__PURE__ */ new Map();
|
|
await tree.walkAsync((node) => {
|
|
const raw = node.model?.raw;
|
|
if (!raw) return true;
|
|
const speckleType = String(raw.speckle_type ?? "");
|
|
const isDefProxy = speckleType.includes("InstanceDefinitionProxy") || speckleType.includes("BlockDefinition");
|
|
if (isDefProxy) {
|
|
const appId = String(raw.applicationId ?? "");
|
|
const name = typeof raw.name === "string" ? raw.name : void 0;
|
|
if (appId) {
|
|
defProxyByAppId.set(appId, { name });
|
|
}
|
|
return true;
|
|
}
|
|
if (node.model.atomic && node.model.id && node.model.id.length === 32 && !node.model.raw.speckle_type?.includes("InstanceDefinitionProxy") && node.model.raw.properties?.builtInCategory !== "OST_Levels") {
|
|
const objectId = node.model.id;
|
|
objectMap[objectId] = node.model.raw;
|
|
const objProps = {};
|
|
const extractedProperties = extractNestedProperties(
|
|
node.model.raw
|
|
);
|
|
const pendingPropertyUpdates = [];
|
|
for (const prop of extractedProperties) {
|
|
const fullPath = prop.concatenatedPath;
|
|
if (shouldExcludeFromFiltering(fullPath)) {
|
|
continue;
|
|
}
|
|
let finalValue;
|
|
let finalType;
|
|
if (isParameter(prop) && "value" in prop) {
|
|
finalValue = prop.value;
|
|
finalType = prop.type;
|
|
} else if ("value" in prop) {
|
|
finalValue = prop.value;
|
|
finalType = prop.type;
|
|
} else {
|
|
const value = prop.path.reduce(
|
|
(current, key) => current?.[key],
|
|
node.model.raw
|
|
);
|
|
if (value && isParameter(value)) {
|
|
finalValue = value.value;
|
|
finalType = typeof finalValue;
|
|
} else {
|
|
finalValue = value;
|
|
finalType = prop.type;
|
|
}
|
|
}
|
|
if (finalValue !== null && finalValue !== void 0) {
|
|
objProps[fullPath] = finalValue;
|
|
pendingPropertyUpdates.push({
|
|
path: fullPath,
|
|
value: finalValue,
|
|
type: finalType
|
|
});
|
|
const pathParts = fullPath.split(".");
|
|
const lastPart = pathParts[pathParts.length - 1];
|
|
if (lastPart === "definitionId" && typeof finalValue === "string" && finalValue) {
|
|
const defInfo = defProxyByAppId.get(finalValue);
|
|
if (defInfo?.name) {
|
|
const basePath = pathParts.slice(0, -1).join(".");
|
|
const namePath = basePath ? `${basePath}.definitionName` : "definitionName";
|
|
objProps[namePath] = defInfo.name;
|
|
pendingPropertyUpdates.push({
|
|
path: namePath,
|
|
value: defInfo.name,
|
|
type: "string"
|
|
});
|
|
}
|
|
}
|
|
if (pendingPropertyUpdates.length >= DEEP_EXTRACTION_CONFIG.BATCH_SIZE) {
|
|
processBatchedPropertyUpdates(pendingPropertyUpdates, propertyMap);
|
|
pendingPropertyUpdates.length = 0;
|
|
}
|
|
}
|
|
}
|
|
if (pendingPropertyUpdates.length > 0) {
|
|
processBatchedPropertyUpdates(pendingPropertyUpdates, propertyMap);
|
|
pendingPropertyUpdates.length = 0;
|
|
}
|
|
objectProperties[objectId] = objProps;
|
|
}
|
|
return true;
|
|
}, subnode);
|
|
const rootObject = subnode.model.raw.children?.[0];
|
|
dataSourcesMap.value[res.resourceUrl] = {
|
|
...res,
|
|
viewerInstance: markRaw(viewer),
|
|
rootObject: rootObject ? markRaw(rootObject) : null,
|
|
objectMap: markRaw(objectMap),
|
|
propertyMap,
|
|
objectProperties
|
|
};
|
|
}
|
|
};
|
|
const queryObjects = (criteria) => {
|
|
const matchingIds = [];
|
|
const PRECISION = 4;
|
|
for (const dataSource of dataSources.value) {
|
|
const propertyInfo = dataSource.propertyMap[criteria.propertyKey];
|
|
if (!propertyInfo) {
|
|
continue;
|
|
}
|
|
if (criteria.condition === ExistenceFilterCondition.IsSet) {
|
|
for (const [objectId, objProps] of Object.entries(
|
|
dataSource.objectProperties
|
|
)) {
|
|
const hasProperty = criteria.propertyKey in objProps;
|
|
if (hasProperty) {
|
|
matchingIds.push(objectId);
|
|
}
|
|
}
|
|
} else if (criteria.condition === ExistenceFilterCondition.IsNotSet) {
|
|
for (const [objectId, objProps] of Object.entries(
|
|
dataSource.objectProperties
|
|
)) {
|
|
const hasProperty = criteria.propertyKey in objProps;
|
|
if (!hasProperty) {
|
|
matchingIds.push(objectId);
|
|
}
|
|
}
|
|
} else if (criteria.condition === BooleanFilterCondition.IsTrue) {
|
|
for (const [objectId, objProps] of Object.entries(
|
|
dataSource.objectProperties
|
|
)) {
|
|
const value = objProps[criteria.propertyKey];
|
|
if (isValueBooleanTrue(value)) {
|
|
matchingIds.push(objectId);
|
|
}
|
|
}
|
|
} else if (criteria.condition === BooleanFilterCondition.IsFalse) {
|
|
for (const [objectId, objProps] of Object.entries(
|
|
dataSource.objectProperties
|
|
)) {
|
|
const value = objProps[criteria.propertyKey];
|
|
if (isValueBooleanFalse(value)) {
|
|
matchingIds.push(objectId);
|
|
}
|
|
}
|
|
} else {
|
|
for (const [objectId, objProps] of Object.entries(
|
|
dataSource.objectProperties
|
|
)) {
|
|
const value = objProps[criteria.propertyKey];
|
|
if (value === void 0) continue;
|
|
let shouldInclude = false;
|
|
if (criteria.minValue !== void 0 || criteria.maxValue !== void 0) {
|
|
const numericValue = Number(value);
|
|
if (isNaN(numericValue)) continue;
|
|
const minValue = criteria.minValue ?? -Infinity;
|
|
const maxValue = criteria.maxValue ?? Infinity;
|
|
switch (criteria.condition) {
|
|
case NumericFilterCondition.IsBetween:
|
|
shouldInclude = numericValue >= minValue && numericValue <= maxValue;
|
|
break;
|
|
case NumericFilterCondition.IsGreaterThan:
|
|
shouldInclude = numericValue > minValue;
|
|
break;
|
|
case NumericFilterCondition.IsLessThan:
|
|
shouldInclude = numericValue < maxValue;
|
|
break;
|
|
case NumericFilterCondition.IsEqualTo: {
|
|
const tolerance = Math.pow(10, -PRECISION);
|
|
shouldInclude = Math.abs(numericValue - minValue) <= tolerance;
|
|
break;
|
|
}
|
|
case NumericFilterCondition.IsNotEqualTo: {
|
|
const tolerance = Math.pow(10, -PRECISION);
|
|
shouldInclude = Math.abs(numericValue - minValue) > tolerance;
|
|
break;
|
|
}
|
|
default:
|
|
shouldInclude = numericValue >= minValue && numericValue <= maxValue;
|
|
}
|
|
} else if (criteria.condition === StringFilterCondition.Is) {
|
|
shouldInclude = criteria.values.includes(String(value));
|
|
} else if (criteria.condition === StringFilterCondition.IsNot) {
|
|
shouldInclude = !criteria.values.includes(String(value));
|
|
}
|
|
if (shouldInclude) {
|
|
matchingIds.push(objectId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return matchingIds;
|
|
};
|
|
const computeSliceIntersections = () => {
|
|
if (dataSlices.value.length < 1) return;
|
|
if (currentFilterLogic.value === FilterLogic.All) {
|
|
dataSlices.value[0].intersectedObjectIds = [...dataSlices.value[0].objectIds];
|
|
for (let i = 1; i < dataSlices.value.length; i++) {
|
|
const prevSlice = dataSlices.value[i - 1];
|
|
const currentSlice = dataSlices.value[i];
|
|
currentSlice.intersectedObjectIds = currentSlice.objectIds.filter(
|
|
(id) => prevSlice.intersectedObjectIds.includes(id)
|
|
);
|
|
}
|
|
} else {
|
|
for (const slice of dataSlices.value) {
|
|
slice.intersectedObjectIds = [];
|
|
}
|
|
}
|
|
};
|
|
const pushOrReplaceSlice = (dataSlice) => {
|
|
const sliceByWidgetIdIndex = dataSlices.value.findIndex(
|
|
(slice) => slice.widgetId === dataSlice.widgetId
|
|
);
|
|
if (sliceByWidgetIdIndex === -1) {
|
|
dataSlices.value.push(dataSlice);
|
|
} else {
|
|
if (dataSlices.value[sliceByWidgetIdIndex].name === dataSlice.name) {
|
|
popSlice(dataSlice);
|
|
return;
|
|
} else {
|
|
dataSlices.value[sliceByWidgetIdIndex] = dataSlice;
|
|
}
|
|
}
|
|
computeSliceIntersections();
|
|
};
|
|
const popSlice = (dataSlice) => {
|
|
const sliceByWidgetIdIndex = dataSlices.value.findIndex(
|
|
(slice) => slice.widgetId === dataSlice.widgetId
|
|
);
|
|
if (sliceByWidgetIdIndex !== -1) {
|
|
dataSlices.value.splice(sliceByWidgetIdIndex, 1);
|
|
computeSliceIntersections();
|
|
}
|
|
};
|
|
const getFinalObjectIds = () => {
|
|
if (dataSlices.value.length === 0) return [];
|
|
if (currentFilterLogic.value === FilterLogic.Any) {
|
|
const validObjectIds = compact(
|
|
flatten(
|
|
dataSlices.value.filter((slice) => slice.objectIds && Array.isArray(slice.objectIds)).map((slice) => slice.objectIds)
|
|
)
|
|
);
|
|
const result = uniq(validObjectIds);
|
|
return result;
|
|
} else {
|
|
const lastSlice = dataSlices.value[dataSlices.value.length - 1];
|
|
const result = lastSlice?.intersectedObjectIds || [];
|
|
return result;
|
|
}
|
|
};
|
|
const clearDataOnRouteLeave = () => {
|
|
dataSourcesMap.value = {};
|
|
dataSlices.value = [];
|
|
};
|
|
const setFilterLogic = (logic) => {
|
|
currentFilterLogic.value = logic;
|
|
computeSliceIntersections();
|
|
};
|
|
return {
|
|
populateDataStore,
|
|
queryObjects,
|
|
pushOrReplaceSlice,
|
|
popSlice,
|
|
computeSliceIntersections,
|
|
getFinalObjectIds,
|
|
clearDataOnRouteLeave,
|
|
setFilterLogic,
|
|
currentFilterLogic,
|
|
dataSlices,
|
|
dataSources
|
|
};
|
|
}
|
|
export function useFilteringDataStore() {
|
|
const { viewer } = useInjectedViewerState();
|
|
if (!viewer.metadata.filteringDataStore) {
|
|
throw new Error(
|
|
"Filtering data store not initialized. Ensure viewer is properly set up."
|
|
);
|
|
}
|
|
return viewer.metadata.filteringDataStore;
|
|
}
|
|
|
|
//# sourceMappingURL=data:application/json;base64,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IjpbXSwic291cmNlcyI6WyJkYXRhU3RvcmUudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBTcGVja2xlT2JqZWN0LCBUcmVlTm9kZSwgVmlld2VyIH0gZnJvbSAnQHNwZWNrbGUvdmlld2VyJ1xyXG5pbXBvcnQgeyB1bmlxLCBmbGF0dGVuLCBjb21wYWN0LCBpc1N0cmluZyB9IGZyb20gJ2xvZGFzaC1lcydcclxuaW1wb3J0IHtcclxuICBGaWx0ZXJMb2dpYyxcclxuICBGaWx0ZXJUeXBlLFxyXG4gIE51bWVyaWNGaWx0ZXJDb25kaXRpb24sXHJcbiAgU3RyaW5nRmlsdGVyQ29uZGl0aW9uLFxyXG4gIEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbixcclxuICBCb29sZWFuRmlsdGVyQ29uZGl0aW9uXHJcbn0gZnJvbSAnfi9saWIvdmlld2VyL2hlbHBlcnMvZmlsdGVycy90eXBlcydcclxuaW1wb3J0IHR5cGUge1xyXG4gIERhdGFTbGljZSxcclxuICBRdWVyeUNyaXRlcmlhLFxyXG4gIERhdGFTb3VyY2UsXHJcbiAgUmVzb3VyY2VJbmZvLFxyXG4gIEZpbHRlcmluZ1Byb3BlcnR5SW5mbyxcclxuICBQcm9wZXJ0eUluZm9CYXNlXHJcbn0gZnJvbSAnfi9saWIvdmlld2VyL2hlbHBlcnMvZmlsdGVycy90eXBlcydcclxuaW1wb3J0IHsgdXNlSW5qZWN0ZWRWaWV3ZXJTdGF0ZSB9IGZyb20gJ35+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvc2V0dXAnXHJcbmltcG9ydCB7XHJcbiAgc2hvdWxkRXhjbHVkZUZyb21GaWx0ZXJpbmcsXHJcbiAgZXh0cmFjdE5lc3RlZFByb3BlcnRpZXMsXHJcbiAgaXNQYXJhbWV0ZXIsXHJcbiAgaXNWYWx1ZU51bWVyaWMsXHJcbiAgaXNWYWx1ZUJvb2xlYW5UcnVlLFxyXG4gIGlzVmFsdWVCb29sZWFuRmFsc2VcclxufSBmcm9tICd+L2xpYi92aWV3ZXIvaGVscGVycy9maWx0ZXJzL3V0aWxzJ1xyXG5pbXBvcnQgeyBERUVQX0VYVFJBQ1RJT05fQ09ORklHIH0gZnJvbSAnfi9saWIvdmlld2VyL2hlbHBlcnMvZmlsdGVycy9jb25zdGFudHMnXHJcblxyXG4vKipcclxuICogSGVscGVyIGZ1bmN0aW9uIHRvIGJhdGNoIHByb3BlcnR5IG1hcCB1cGRhdGVzIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcclxuICovXHJcbmZ1bmN0aW9uIHByb2Nlc3NCYXRjaGVkUHJvcGVydHlVcGRhdGVzKFxyXG4gIHVwZGF0ZXM6IEFycmF5PHsgcGF0aDogc3RyaW5nOyB2YWx1ZTogdW5rbm93bjsgdHlwZTogc3RyaW5nIH0+LFxyXG4gIHByb3BlcnR5TWFwOiBSZWNvcmQ8c3RyaW5nLCBGaWx0ZXJpbmdQcm9wZXJ0eUluZm8+XHJcbikge1xyXG4gIGZvciAoY29uc3QgdXBkYXRlIG9mIHVwZGF0ZXMpIHtcclxuICAgIGNvbnN0IGV4aXN0aW5nUHJvcGVydHkgPSBwcm9wZXJ0eU1hcFt1cGRhdGUucGF0aF1cclxuXHJcbiAgICBpZiAoIWV4aXN0aW5nUHJvcGVydHkpIHtcclxuICAgICAgLy8gQ29udmVydCBzdHJpbmcgdHlwZSB0byBGaWx0ZXJUeXBlXHJcbiAgICAgIGxldCBmaWx0ZXJUeXBlOiBGaWx0ZXJUeXBlXHJcbiAgICAgIGlmICh1cGRhdGUudHlwZSA9PT0gJ251bWJlcicpIHtcclxuICAgICAgICBmaWx0ZXJUeXBlID0gRmlsdGVyVHlwZS5OdW1lcmljXHJcbiAgICAgIH0gZWxzZSBpZiAodXBkYXRlLnR5cGUgPT09ICdib29sZWFuJykge1xyXG4gICAgICAgIGZpbHRlclR5cGUgPSBGaWx0ZXJUeXBlLkJvb2xlYW5cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBmaWx0ZXJUeXBlID0gRmlsdGVyVHlwZS5TdHJpbmdcclxuICAgICAgfVxyXG5cclxuICAgICAgcHJvcGVydHlNYXBbdXBkYXRlLnBhdGhdID0ge1xyXG4gICAgICAgIGNvbmNhdGVuYXRlZFBhdGg6IHVwZGF0ZS5wYXRoLFxyXG4gICAgICAgIHZhbHVlOiB1cGRhdGUudmFsdWUgYXMgc3RyaW5nIHwgbnVtYmVyLFxyXG4gICAgICAgIHR5cGU6IGZpbHRlclR5cGVcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgLy8gUHJvcGVydHkgZXhpc3RzIC0gY2hlY2sgaWYgd2UgbmVlZCB0byB1cGRhdGUgdHlwZSBkdWUgdG8gY29uZmxpY3RpbmcgZXZpZGVuY2VcclxuICAgICAgaWYgKFxyXG4gICAgICAgIGV4aXN0aW5nUHJvcGVydHkudHlwZSA9PT0gRmlsdGVyVHlwZS5OdW1lcmljICYmXHJcbiAgICAgICAgaXNTdHJpbmcodXBkYXRlLnZhbHVlKSAmJlxyXG4gICAgICAgICFpc1ZhbHVlTnVtZXJpYyh1cGRhdGUudmFsdWUpXHJcbiAgICAgICkge1xyXG4gICAgICAgIGV4aXN0aW5nUHJvcGVydHkudHlwZSA9IEZpbHRlclR5cGUuU3RyaW5nXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiB1c2VDcmVhdGVWaWV3ZXJGaWx0ZXJpbmdEYXRhU3RvcmUoKSB7XHJcbiAgY29uc3QgZGF0YVNvdXJjZXNNYXA6IFJlZjxSZWNvcmQ8c3RyaW5nLCBEYXRhU291cmNlPj4gPSByZWYoe30pXHJcbiAgY29uc3QgZGF0YVNvdXJjZXMgPSBjb21wdXRlZCgoKSA9PiBPYmplY3QudmFsdWVzKGRhdGFTb3VyY2VzTWFwLnZhbHVlKSlcclxuICBjb25zdCBjdXJyZW50RmlsdGVyTG9naWMgPSByZWY8RmlsdGVyTG9naWM+KEZpbHRlckxvZ2ljLkFsbClcclxuICBjb25zdCBkYXRhU2xpY2VzOiBSZWY8RGF0YVNsaWNlW10+ID0gcmVmKFtdKVxyXG5cclxuICBjb25zdCBwb3B1bGF0ZURhdGFTdG9yZSA9IGFzeW5jICh2aWV3ZXI6IFZpZXdlciwgcmVzb3VyY2VzOiBSZXNvdXJjZUluZm9bXSkgPT4ge1xyXG4gICAgY29uc3QgdHJlZSA9IHZpZXdlci5nZXRXb3JsZFRyZWUoKVxyXG4gICAgaWYgKCF0cmVlKSByZXR1cm5cclxuXHJcbiAgICBmb3IgKGNvbnN0IHJlcyBvZiByZXNvdXJjZXMpIHtcclxuICAgICAgY29uc3QgZm91bmROb2RlcyA9IHRyZWUuZmluZElkKHJlcy5yZXNvdXJjZVVybClcclxuICAgICAgY29uc3Qgc3Vibm9kZSA9IGZvdW5kTm9kZXM/LlswXVxyXG4gICAgICBpZiAoIXN1Ym5vZGUpIHtcclxuICAgICAgICBjb250aW51ZVxyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCBvYmplY3RNYXA6IFJlY29yZDxzdHJpbmcsIFNwZWNrbGVPYmplY3Q+ID0ge31cclxuICAgICAgY29uc3QgcHJvcGVydHlNYXA6IFJlY29yZDxzdHJpbmcsIEZpbHRlcmluZ1Byb3BlcnR5SW5mbz4gPSB7fVxyXG4gICAgICAvLyBNYXAgZnJvbSBvYmplY3RJZCB0byBpdHMgcHJvcGVydHkgdmFsdWVzIGZvciBlZmZpY2llbnQgZmlsdGVyaW5nXHJcbiAgICAgIGNvbnN0IG9iamVjdFByb3BlcnRpZXM6IFJlY29yZDxzdHJpbmcsIFJlY29yZDxzdHJpbmcsIHVua25vd24+PiA9IHt9XHJcblxyXG4gICAgICAvLyBTaW5nbGUtcGFzczogY29sbGVjdCBkZWZpbml0aW9uIHByb3hpZXMgQU5EIGF0b21pYyBvYmplY3RzIGluIG9uZSB3YWxrXHJcbiAgICAgIGNvbnN0IGRlZlByb3h5QnlBcHBJZCA9IG5ldyBNYXA8c3RyaW5nLCB7IG5hbWU/OiBzdHJpbmcgfT4oKVxyXG5cclxuICAgICAgYXdhaXQgdHJlZS53YWxrQXN5bmMoKG5vZGU6IFRyZWVOb2RlKSA9PiB7XHJcbiAgICAgICAgY29uc3QgcmF3ID0gbm9kZS5tb2RlbD8ucmF3IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkXHJcbiAgICAgICAgaWYgKCFyYXcpIHJldHVybiB0cnVlXHJcblxyXG4gICAgICAgIC8vIEZpcnN0LCBjaGVjayBpZiB0aGlzIGlzIGEgZGVmaW5pdGlvbiBwcm94eSAobm9uLWF0b21pYylcclxuICAgICAgICBjb25zdCBzcGVja2xlVHlwZSA9IFN0cmluZyhyYXcuc3BlY2tsZV90eXBlID8/ICcnKVxyXG4gICAgICAgIGNvbnN0IGlzRGVmUHJveHkgPVxyXG4gICAgICAgICAgc3BlY2tsZVR5cGUuaW5jbHVkZXMoJ0luc3RhbmNlRGVmaW5pdGlvblByb3h5JykgfHxcclxuICAgICAgICAgIHNwZWNrbGVUeXBlLmluY2x1ZGVzKCdCbG9ja0RlZmluaXRpb24nKVxyXG5cclxuICAgICAgICBpZiAoaXNEZWZQcm94eSkge1xyXG4gICAgICAgICAgY29uc3QgYXBwSWQgPSBTdHJpbmcocmF3LmFwcGxpY2F0aW9uSWQgPz8gJycpXHJcbiAgICAgICAgICBjb25zdCBuYW1lID0gdHlwZW9mIHJhdy5uYW1lID09PSAnc3RyaW5nJyA/IHJhdy5uYW1lIDogdW5kZWZpbmVkXHJcbiAgICAgICAgICBpZiAoYXBwSWQpIHtcclxuICAgICAgICAgICAgZGVmUHJveHlCeUFwcElkLnNldChhcHBJZCwgeyBuYW1lIH0pXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICByZXR1cm4gdHJ1ZSAvLyBDb250aW51ZSB0cmF2ZXJzYWwsIGRvbid0IHByb2Nlc3MgYXMgYXRvbWljXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoXHJcbiAgICAgICAgICBub2RlLm1vZGVsLmF0b21pYyAmJlxyXG4gICAgICAgICAgbm9kZS5tb2RlbC5pZCAmJlxyXG4gICAgICAgICAgbm9kZS5tb2RlbC5pZC5sZW5ndGggPT09IDMyICYmXHJcbiAgICAgICAgICAhbm9kZS5tb2RlbC5yYXcuc3BlY2tsZV90eXBlPy5pbmNsdWRlcygnSW5zdGFuY2VEZWZpbml0aW9uUHJveHknKSAmJlxyXG4gICAgICAgICAgbm9kZS5tb2RlbC5yYXcucHJvcGVydGllcz8uYnVpbHRJbkNhdGVnb3J5ICE9PSAnT1NUX0xldmVscydcclxuICAgICAgICApIHtcclxuICAgICAgICAgIGNvbnN0IG9iamVjdElkID0gbm9kZS5tb2RlbC5pZFxyXG4gICAgICAgICAgb2JqZWN0TWFwW29iamVjdElkXSA9IG5vZGUubW9kZWwucmF3IGFzIFNwZWNrbGVPYmplY3RcclxuXHJcbiAgICAgICAgICAvLyBFeHRyYWN0IGFsbCBwcm9wZXJ0aWVzIHVzaW5nIHRoZSBuZXcgcHJvcGVydHkgZXh0cmFjdG9yXHJcbiAgICAgICAgICBjb25zdCBvYmpQcm9wczogUmVjb3JkPHN0cmluZywgdW5rbm93bj4gPSB7fVxyXG4gICAgICAgICAgY29uc3QgZXh0cmFjdGVkUHJvcGVydGllczogUHJvcGVydHlJbmZvQmFzZVtdID0gZXh0cmFjdE5lc3RlZFByb3BlcnRpZXMoXHJcbiAgICAgICAgICAgIG5vZGUubW9kZWwucmF3IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+XHJcbiAgICAgICAgICApXHJcblxyXG4gICAgICAgICAgY29uc3QgcGVuZGluZ1Byb3BlcnR5VXBkYXRlczogQXJyYXk8e1xyXG4gICAgICAgICAgICBwYXRoOiBzdHJpbmdcclxuICAgICAgICAgICAgdmFsdWU6IHVua25vd25cclxuICAgICAgICAgICAgdHlwZTogc3RyaW5nXHJcbiAgICAgICAgICB9PiA9IFtdXHJcblxyXG4gICAgICAgICAgZm9yIChjb25zdCBwcm9wIG9mIGV4dHJhY3RlZFByb3BlcnRpZXMpIHtcclxuICAgICAgICAgICAgY29uc3QgZnVsbFBhdGggPSBwcm9wLmNvbmNhdGVuYXRlZFBhdGhcclxuXHJcbiAgICAgICAgICAgIGlmIChzaG91bGRFeGNsdWRlRnJvbUZpbHRlcmluZyhmdWxsUGF0aCkpIHtcclxuICAgICAgICAgICAgICBjb250aW51ZVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBIYW5kbGUgbmFtZS12YWx1ZSBwYWlycyBieSBjb2xsYXBzaW5nIHRoZW0gdG8ganVzdCB0aGUgdmFsdWVcclxuICAgICAgICAgICAgbGV0IGZpbmFsVmFsdWU6IHVua25vd25cclxuICAgICAgICAgICAgbGV0IGZpbmFsVHlwZTogc3RyaW5nXHJcblxyXG4gICAgICAgICAgICBpZiAoaXNQYXJhbWV0ZXIocHJvcCkgJiYgJ3ZhbHVlJyBpbiBwcm9wKSB7XHJcbiAgICAgICAgICAgICAgLy8gVGhpcyBpcyBhIG5hbWUtdmFsdWUgcGFpciwgZXh0cmFjdCBqdXN0IHRoZSB2YWx1ZVxyXG4gICAgICAgICAgICAgIGZpbmFsVmFsdWUgPSBwcm9wLnZhbHVlXHJcbiAgICAgICAgICAgICAgZmluYWxUeXBlID0gcHJvcC50eXBlXHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoJ3ZhbHVlJyBpbiBwcm9wKSB7XHJcbiAgICAgICAgICAgICAgLy8gVGhpcyBhbHJlYWR5IGhhcyBhIHZhbHVlXHJcbiAgICAgICAgICAgICAgZmluYWxWYWx1ZSA9IHByb3AudmFsdWVcclxuICAgICAgICAgICAgICBmaW5hbFR5cGUgPSBwcm9wLnR5cGVcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAvLyBUaGlzIGlzIGEgcmVndWxhciBwcm9wZXJ0eSwgd2UgbmVlZCB0byBnZXQgdGhlIHZhbHVlIGZyb20gdGhlIG9iamVjdFxyXG4gICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcHJvcC5wYXRoLnJlZHVjZShcclxuICAgICAgICAgICAgICAgIChjdXJyZW50LCBrZXkpID0+IChjdXJyZW50IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KT8uW2tleV0sXHJcbiAgICAgICAgICAgICAgICBub2RlLm1vZGVsLnJhd1xyXG4gICAgICAgICAgICAgIClcclxuXHJcbiAgICAgICAgICAgICAgaWYgKHZhbHVlICYmIGlzUGFyYW1ldGVyKHZhbHVlKSkge1xyXG4gICAgICAgICAgICAgICAgZmluYWxWYWx1ZSA9ICh2YWx1ZSBhcyB7IHZhbHVlOiB1bmtub3duIH0pLnZhbHVlXHJcbiAgICAgICAgICAgICAgICBmaW5hbFR5cGUgPSB0eXBlb2YgZmluYWxWYWx1ZVxyXG4gICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBmaW5hbFZhbHVlID0gdmFsdWVcclxuICAgICAgICAgICAgICAgIGZpbmFsVHlwZSA9IHByb3AudHlwZVxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGZpbmFsVmFsdWUgIT09IG51bGwgJiYgZmluYWxWYWx1ZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgb2JqUHJvcHNbZnVsbFBhdGhdID0gZmluYWxWYWx1ZVxyXG5cclxuICAgICAgICAgICAgICBwZW5kaW5nUHJvcGVydHlVcGRhdGVzLnB1c2goe1xyXG4gICAgICAgICAgICAgICAgcGF0aDogZnVsbFBhdGgsXHJcbiAgICAgICAgICAgICAgICB2YWx1ZTogZmluYWxWYWx1ZSxcclxuICAgICAgICAgICAgICAgIHR5cGU6IGZpbmFsVHlwZVxyXG4gICAgICAgICAgICAgIH0pXHJcblxyXG4gICAgICAgICAgICAgIGNvbnN0IHBhdGhQYXJ0cyA9IGZ1bGxQYXRoLnNwbGl0KCcuJylcclxuICAgICAgICAgICAgICBjb25zdCBsYXN0UGFydCA9IHBhdGhQYXJ0c1twYXRoUGFydHMubGVuZ3RoIC0gMV1cclxuICAgICAgICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgICAgICBsYXN0UGFydCA9PT0gJ2RlZmluaXRpb25JZCcgJiZcclxuICAgICAgICAgICAgICAgIHR5cGVvZiBmaW5hbFZhbHVlID09PSAnc3RyaW5nJyAmJlxyXG4gICAgICAgICAgICAgICAgZmluYWxWYWx1ZVxyXG4gICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGVmSW5mbyA9IGRlZlByb3h5QnlBcHBJZC5nZXQoZmluYWxWYWx1ZSlcclxuICAgICAgICAgICAgICAgIGlmIChkZWZJbmZvPy5uYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgIGNvbnN0IGJhc2VQYXRoID0gcGF0aFBhcnRzLnNsaWNlKDAsIC0xKS5qb2luKCcuJylcclxuICAgICAgICAgICAgICAgICAgY29uc3QgbmFtZVBhdGggPSBiYXNlUGF0aFxyXG4gICAgICAgICAgICAgICAgICAgID8gYCR7YmFzZVBhdGh9LmRlZmluaXRpb25OYW1lYFxyXG4gICAgICAgICAgICAgICAgICAgIDogJ2RlZmluaXRpb25OYW1lJ1xyXG4gICAgICAgICAgICAgICAgICBvYmpQcm9wc1tuYW1lUGF0aF0gPSBkZWZJbmZvLm5hbWVcclxuICAgICAgICAgICAgICAgICAgcGVuZGluZ1Byb3BlcnR5VXBkYXRlcy5wdXNoKHtcclxuICAgICAgICAgICAgICAgICAgICBwYXRoOiBuYW1lUGF0aCxcclxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogZGVmSW5mby5uYW1lLFxyXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6ICdzdHJpbmcnXHJcbiAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICBpZiAocGVuZGluZ1Byb3BlcnR5VXBkYXRlcy5sZW5ndGggPj0gREVFUF9FWFRSQUNUSU9OX0NPTkZJRy5CQVRDSF9TSVpFKSB7XHJcbiAgICAgICAgICAgICAgICBwcm9jZXNzQmF0Y2hlZFByb3BlcnR5VXBkYXRlcyhwZW5kaW5nUHJvcGVydHlVcGRhdGVzLCBwcm9wZXJ0eU1hcClcclxuICAgICAgICAgICAgICAgIHBlbmRpbmdQcm9wZXJ0eVVwZGF0ZXMubGVuZ3RoID0gMFxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIGlmIChwZW5kaW5nUHJvcGVydHlVcGRhdGVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgcHJvY2Vzc0JhdGNoZWRQcm9wZXJ0eVVwZGF0ZXMocGVuZGluZ1Byb3BlcnR5VXBkYXRlcywgcHJvcGVydHlNYXApXHJcbiAgICAgICAgICAgIHBlbmRpbmdQcm9wZXJ0eVVwZGF0ZXMubGVuZ3RoID0gMFxyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIG9iamVjdFByb3BlcnRpZXNbb2JqZWN0SWRdID0gb2JqUHJvcHNcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRydWVcclxuICAgICAgfSwgc3Vibm9kZSlcclxuXHJcbiAgICAgIGNvbnN0IHJvb3RPYmplY3QgPSBzdWJub2RlLm1vZGVsLnJhdy5jaGlsZHJlbj8uWzBdIGFzIFNwZWNrbGVPYmplY3RcclxuXHJcbiAgICAgIGRhdGFTb3VyY2VzTWFwLnZhbHVlW3Jlcy5yZXNvdXJjZVVybF0gPSB7XHJcbiAgICAgICAgLi4ucmVzLFxyXG4gICAgICAgIHZpZXdlckluc3RhbmNlOiBtYXJrUmF3KHZpZXdlciksXHJcbiAgICAgICAgcm9vdE9iamVjdDogcm9vdE9iamVjdCA/IG1hcmtSYXcocm9vdE9iamVjdCkgOiBudWxsLFxyXG4gICAgICAgIG9iamVjdE1hcDogbWFya1JhdyhvYmplY3RNYXApLFxyXG4gICAgICAgIHByb3BlcnR5TWFwLFxyXG4gICAgICAgIG9iamVjdFByb3BlcnRpZXNcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgY29uc3QgcXVlcnlPYmplY3RzID0gKGNyaXRlcmlhOiBRdWVyeUNyaXRlcmlhKTogc3RyaW5nW10gPT4ge1xyXG4gICAgY29uc3QgbWF0Y2hpbmdJZHM6IHN0cmluZ1tdID0gW11cclxuICAgIGNvbnN0IFBSRUNJU0lPTiA9IDQgLy8gbWF0Y2hlcyAwLjAwMDEgc3RlcFxyXG5cclxuICAgIGZvciAoY29uc3QgZGF0YVNvdXJjZSBvZiBkYXRhU291cmNlcy52YWx1ZSkge1xyXG4gICAgICAvLyBDaGVjayBpZiBwcm9wZXJ0eSBleGlzdHMgaW4gcHJvcGVydHlNYXBcclxuICAgICAgY29uc3QgcHJvcGVydHlJbmZvID0gZGF0YVNvdXJjZS5wcm9wZXJ0eU1hcFtjcml0ZXJpYS5wcm9wZXJ0eUtleV1cclxuICAgICAgaWYgKCFwcm9wZXJ0eUluZm8pIHtcclxuICAgICAgICBjb250aW51ZVxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoY3JpdGVyaWEuY29uZGl0aW9uID09PSBFeGlzdGVuY2VGaWx0ZXJDb25kaXRpb24uSXNTZXQpIHtcclxuICAgICAgICAvLyBGaW5kIGFsbCBvYmplY3RzIHRoYXQgaGF2ZSB0aGlzIHByb3BlcnR5IC0gdXNlIHByZS1jb21wdXRlZCBvYmplY3RQcm9wZXJ0aWVzXHJcbiAgICAgICAgZm9yIChjb25zdCBbb2JqZWN0SWQsIG9ialByb3BzXSBvZiBPYmplY3QuZW50cmllcyhcclxuICAgICAgICAgIGRhdGFTb3VyY2Uub2JqZWN0UHJvcGVydGllc1xyXG4gICAgICAgICkpIHtcclxuICAgICAgICAgIGNvbnN0IGhhc1Byb3BlcnR5ID0gY3JpdGVyaWEucHJvcGVydHlLZXkgaW4gb2JqUHJvcHNcclxuICAgICAgICAgIGlmIChoYXNQcm9wZXJ0eSkge1xyXG4gICAgICAgICAgICBtYXRjaGluZ0lkcy5wdXNoKG9iamVjdElkKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIGlmIChjcml0ZXJpYS5jb25kaXRpb24gPT09IEV4aXN0ZW5jZUZpbHRlckNvbmRpdGlvbi5Jc05vdFNldCkge1xyXG4gICAgICAgIC8vIEZpbmQgYWxsIG9iamVjdHMgdGhhdCBkb24ndCBoYXZlIHRoaXMgcHJvcGVydHlcclxuICAgICAgICBmb3IgKGNvbnN0IFtvYmplY3RJZCwgb2JqUHJvcHNdIG9mIE9iamVjdC5lbnRyaWVzKFxyXG4gICAgICAgICAgZGF0YVNvdXJjZS5vYmplY3RQcm9wZXJ0aWVzXHJcbiAgICAgICAgKSkge1xyXG4gICAgICAgICAgY29uc3QgaGFzUHJvcGVydHkgPSBjcml0ZXJpYS5wcm9wZXJ0eUtleSBpbiBvYmpQcm9wc1xyXG4gICAgICAgICAgaWYgKCFoYXNQcm9wZXJ0eSkge1xyXG4gICAgICAgICAgICBtYXRjaGluZ0lkcy5wdXNoKG9iamVjdElkKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIGlmIChjcml0ZXJpYS5jb25kaXRpb24gPT09IEJvb2xlYW5GaWx0ZXJDb25kaXRpb24uSXNUcnVlKSB7XHJcbiAgICAgICAgLy8gRmluZCBhbGwgIHdoZXJlIHRoaXMgcHJvcGVydHkgaXMgdHJ1ZVxyXG4gICAgICAgIGZvciAoY29uc3QgW29iamVjdElkLCBvYmpQcm9wc10gb2YgT2JqZWN0LmVudHJpZXMoXHJcbiAgICAgICAgICBkYXRhU291cmNlLm9iamVjdFByb3BlcnRpZXNcclxuICAgICAgICApKSB7XHJcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IG9ialByb3BzW2NyaXRlcmlhLnByb3BlcnR5S2V5XVxyXG4gICAgICAgICAgaWYgKGlzVmFsdWVCb29sZWFuVHJ1ZSh2YWx1ZSkpIHtcclxuICAgICAgICAgICAgbWF0Y2hpbmdJZHMucHVzaChvYmplY3RJZClcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0gZWxzZSBpZiAoY3JpdGVyaWEuY29uZGl0aW9uID09PSBCb29sZWFuRmlsdGVyQ29uZGl0aW9uLklzRmFsc2UpIHtcclxuICAgICAgICAvLyBGaW5kIGFsbCBvYmplY3RzIHdoZXJlIHRoaXMgcHJvcGVydHkgaXMgZmFsc2VcclxuICAgICAgICBmb3IgKGNvbnN0IFtvYmplY3RJZCwgb2JqUHJvcHNdIG9mIE9iamVjdC5lbnRyaWVzKFxyXG4gICAgICAgICAgZGF0YVNvdXJjZS5vYmplY3RQcm9wZXJ0aWVzXHJcbiAgICAgICAgKSkge1xyXG4gICAgICAgICAgY29uc3QgdmFsdWUgPSBvYmpQcm9wc1tjcml0ZXJpYS5wcm9wZXJ0eUtleV1cclxuICAgICAgICAgIGlmIChpc1ZhbHVlQm9vbGVhbkZhbHNlKHZhbHVlKSkge1xyXG4gICAgICAgICAgICBtYXRjaGluZ0lkcy5wdXNoKG9iamVjdElkKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBGb3IgdmFsdWUtYmFzZWQgZmlsdGVyaW5nLCBjaGVjayBlYWNoIG9iamVjdFxyXG4gICAgICAgIGZvciAoY29uc3QgW29iamVjdElkLCBvYmpQcm9wc10gb2YgT2JqZWN0LmVudHJpZXMoXHJcbiAgICAgICAgICBkYXRhU291cmNlLm9iamVjdFByb3BlcnRpZXNcclxuICAgICAgICApKSB7XHJcbiAgICAgICAgICBjb25zdCB2YWx1ZSA9IG9ialByb3BzW2NyaXRlcmlhLnByb3BlcnR5S2V5XVxyXG4gICAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIGNvbnRpbnVlXHJcbiAgICAgICAgICBsZXQgc2hvdWxkSW5jbHVkZSA9IGZhbHNlXHJcblxyXG4gICAgICAgICAgaWYgKGNyaXRlcmlhLm1pblZhbHVlICE9PSB1bmRlZmluZWQgfHwgY3JpdGVyaWEubWF4VmFsdWUgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAvLyBOdW1lcmljIGZpbHRlcmluZ1xyXG4gICAgICAgICAgICBjb25zdCBudW1lcmljVmFsdWUgPSBOdW1iZXIodmFsdWUpXHJcbiAgICAgICAgICAgIGlmIChpc05hTihudW1lcmljVmFsdWUpKSBjb250aW51ZVxyXG5cclxuICAgICAgICAgICAgY29uc3QgbWluVmFsdWUgPSBjcml0ZXJpYS5taW5WYWx1ZSA/PyAtSW5maW5pdHlcclxuICAgICAgICAgICAgY29uc3QgbWF4VmFsdWUgPSBjcml0ZXJpYS5tYXhWYWx1ZSA/PyBJbmZpbml0eVxyXG5cclxuICAgICAgICAgICAgc3dpdGNoIChjcml0ZXJpYS5jb25kaXRpb24pIHtcclxuICAgICAgICAgICAgICBjYXNlIE51bWVyaWNGaWx0ZXJDb25kaXRpb24uSXNCZXR3ZWVuOlxyXG4gICAgICAgICAgICAgICAgc2hvdWxkSW5jbHVkZSA9IG51bWVyaWNWYWx1ZSA+PSBtaW5WYWx1ZSAmJiBudW1lcmljVmFsdWUgPD0gbWF4VmFsdWVcclxuICAgICAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICAgICAgY2FzZSBOdW1lcmljRmlsdGVyQ29uZGl0aW9uLklzR3JlYXRlclRoYW46XHJcbiAgICAgICAgICAgICAgICBzaG91bGRJbmNsdWRlID0gbnVtZXJpY1ZhbHVlID4gbWluVmFsdWVcclxuICAgICAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICAgICAgY2FzZSBOdW1lcmljRmlsdGVyQ29uZGl0aW9uLklzTGVzc1RoYW46XHJcbiAgICAgICAgICAgICAgICBzaG91bGRJbmNsdWRlID0gbnVtZXJpY1ZhbHVlIDwgbWF4VmFsdWVcclxuICAgICAgICAgICAgICAgIGJyZWFrXHJcbiAgICAgICAgICAgICAgY2FzZSBOdW1lcmljRmlsdGVyQ29uZGl0aW9uLklzRXF1YWxUbzoge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdG9sZXJhbmNlID0gTWF0aC5wb3coMTAsIC1QUkVDSVNJT04pXHJcbiAgICAgICAgICAgICAgICBzaG91bGRJbmNsdWRlID0gTWF0aC5hYnMobnVtZXJpY1ZhbHVlIC0gbWluVmFsdWUpIDw9IHRvbGVyYW5jZVxyXG4gICAgICAgICAgICAgICAgYnJlYWtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgY2FzZSBOdW1lcmljRmlsdGVyQ29uZGl0aW9uLklzTm90RXF1YWxUbzoge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdG9sZXJhbmNlID0gTWF0aC5wb3coMTAsIC1QUkVDSVNJT04pXHJcbiAgICAgICAgICAgICAgICBzaG91bGRJbmNsdWRlID0gTWF0aC5hYnMobnVtZXJpY1ZhbHVlIC0gbWluVmFsdWUpID4gdG9sZXJhbmNlXHJcbiAgICAgICAgICAgICAgICBicmVha1xyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgc2hvdWxkSW5jbHVkZSA9IG51bWVyaWNWYWx1ZSA+PSBtaW5WYWx1ZSAmJiBudW1lcmljVmFsdWUgPD0gbWF4VmFsdWVcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfSBlbHNlIGlmIChjcml0ZXJpYS5jb25kaXRpb24gPT09IFN0cmluZ0ZpbHRlckNvbmRpdGlvbi5Jcykge1xyXG4gICAgICAgICAgICAvLyBTdHJpbmcgZmlsdGVyaW5nIC0gZXhhY3QgbWF0Y2hcclxuICAgICAgICAgICAgc2hvdWxkSW5jbHVkZSA9IGNyaXRlcmlhLnZhbHVlcy5pbmNsdWRlcyhTdHJpbmcodmFsdWUpKVxyXG4gICAgICAgICAgfSBlbHNlIGlmIChjcml0ZXJpYS5jb25kaXRpb24gPT09IFN0cmluZ0ZpbHRlckNvbmRpdGlvbi5Jc05vdCkge1xyXG4gICAgICAgICAgICAvLyBTdHJpbmcgZmlsdGVyaW5nIC0gZXhjbHVkZSB2YWx1ZXNcclxuICAgICAgICAgICAgc2hvdWxkSW5jbHVkZSA9ICFjcml0ZXJpYS52YWx1ZXMuaW5jbHVkZXMoU3RyaW5nKHZhbHVlKSlcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBpZiAoc2hvdWxkSW5jbHVkZSkge1xyXG4gICAgICAgICAgICBtYXRjaGluZ0lkcy5wdXNoKG9iamVjdElkKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBtYXRjaGluZ0lkc1xyXG4gIH1cclxuXHJcbiAgY29uc3QgY29tcHV0ZVNsaWNlSW50ZXJzZWN0aW9ucyA9ICgpID0+IHtcclxuICAgIGlmIChkYXRhU2xpY2VzLnZhbHVlLmxlbmd0aCA8IDEpIHJldHVyblxyXG5cclxuICAgIGlmIChjdXJyZW50RmlsdGVyTG9naWMudmFsdWUgPT09IEZpbHRlckxvZ2ljLkFsbCkge1xyXG4gICAgICBkYXRhU2xpY2VzLnZhbHVlWzBdIS5pbnRlcnNlY3RlZE9iamVjdElkcyA9IFsuLi5kYXRhU2xpY2VzLnZhbHVlWzBdIS5vYmplY3RJZHNdXHJcblxyXG4gICAgICBmb3IgKGxldCBpID0gMTsgaSA8IGRhdGFTbGljZXMudmFsdWUubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBjb25zdCBwcmV2U2xpY2UgPSBkYXRhU2xpY2VzLnZhbHVlW2kgLSAxXSFcclxuICAgICAgICBjb25zdCBjdXJyZW50U2xpY2UgPSBkYXRhU2xpY2VzLnZhbHVlW2ldIVxyXG4gICAgICAgIGN1cnJlbnRTbGljZS5pbnRlcnNlY3RlZE9iamVjdElkcyA9IGN1cnJlbnRTbGljZS5vYmplY3RJZHMuZmlsdGVyKChpZCkgPT5cclxuICAgICAgICAgIHByZXZTbGljZS5pbnRlcnNlY3RlZE9iamVjdElkcyEuaW5jbHVkZXMoaWQpXHJcbiAgICAgICAgKVxyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBmb3IgKGNvbnN0IHNsaWNlIG9mIGRhdGFTbGljZXMudmFsdWUpIHtcclxuICAgICAgICBzbGljZS5pbnRlcnNlY3RlZE9iamVjdElkcyA9IFtdXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IHB1c2hPclJlcGxhY2VTbGljZSA9IChkYXRhU2xpY2U6IERhdGFTbGljZSkgPT4ge1xyXG4gICAgY29uc3Qgc2xpY2VCeVdpZGdldElkSW5kZXggPSBkYXRhU2xpY2VzLnZhbHVlLmZpbmRJbmRleChcclxuICAgICAgKHNsaWNlKSA9PiBzbGljZS53aWRnZXRJZCA9PT0gZGF0YVNsaWNlLndpZGdldElkXHJcbiAgICApXHJcbiAgICBpZiAoc2xpY2VCeVdpZGdldElkSW5kZXggPT09IC0xKSB7XHJcbiAgICAgIGRhdGFTbGljZXMudmFsdWUucHVzaChkYXRhU2xpY2UpXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBpZiAoZGF0YVNsaWNlcy52YWx1ZVtzbGljZUJ5V2lkZ2V0SWRJbmRleF0hLm5hbWUgPT09IGRhdGFTbGljZS5uYW1lKSB7XHJcbiAgICAgICAgcG9wU2xpY2UoZGF0YVNsaWNlKVxyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGRhdGFTbGljZXMudmFsdWVbc2xpY2VCeVdpZGdldElkSW5kZXhdID0gZGF0YVNsaWNlXHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb21wdXRlU2xpY2VJbnRlcnNlY3Rpb25zKClcclxuICB9XHJcblxyXG4gIGNvbnN0IHBvcFNsaWNlID0gKGRhdGFTbGljZTogRGF0YVNsaWNlKSA9PiB7XHJcbiAgICBjb25zdCBzbGljZUJ5V2lkZ2V0SWRJbmRleCA9IGRhdGFTbGljZXMudmFsdWUuZmluZEluZGV4KFxyXG4gICAgICAoc2xpY2UpID0+IHNsaWNlLndpZGdldElkID09PSBkYXRhU2xpY2Uud2lkZ2V0SWRcclxuICAgIClcclxuICAgIGlmIChzbGljZUJ5V2lkZ2V0SWRJbmRleCAhPT0gLTEpIHtcclxuICAgICAgZGF0YVNsaWNlcy52YWx1ZS5zcGxpY2Uoc2xpY2VCeVdpZGdldElkSW5kZXgsIDEpXHJcbiAgICAgIGNvbXB1dGVTbGljZUludGVyc2VjdGlvbnMoKVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgY29uc3QgZ2V0RmluYWxPYmplY3RJZHMgPSAoKTogc3RyaW5nW10gPT4ge1xyXG4gICAgaWYgKGRhdGFTbGljZXMudmFsdWUubGVuZ3RoID09PSAwKSByZXR1cm4gW11cclxuXHJcbiAgICBpZiAoY3VycmVudEZpbHRlckxvZ2ljLnZhbHVlID09PSBGaWx0ZXJMb2dpYy5BbnkpIHtcclxuICAgICAgY29uc3QgdmFsaWRPYmplY3RJZHMgPSBjb21wYWN0KFxyXG4gICAgICAgIGZsYXR0ZW4oXHJcbiAgICAgICAgICBkYXRhU2xpY2VzLnZhbHVlXHJcbiAgICAgICAgICAgIC5maWx0ZXIoKHNsaWNlKSA9PiBzbGljZS5vYmplY3RJZHMgJiYgQXJyYXkuaXNBcnJheShzbGljZS5vYmplY3RJZHMpKVxyXG4gICAgICAgICAgICAubWFwKChzbGljZSkgPT4gc2xpY2Uub2JqZWN0SWRzKVxyXG4gICAgICAgIClcclxuICAgICAgKVxyXG4gICAgICBjb25zdCByZXN1bHQgPSB1bmlxKHZhbGlkT2JqZWN0SWRzKVxyXG4gICAgICByZXR1cm4gcmVzdWx0XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zdCBsYXN0U2xpY2UgPSBkYXRhU2xpY2VzLnZhbHVlW2RhdGFTbGljZXMudmFsdWUubGVuZ3RoIC0gMV1cclxuICAgICAgY29uc3QgcmVzdWx0ID0gbGFzdFNsaWNlPy5pbnRlcnNlY3RlZE9iamVjdElkcyB8fCBbXVxyXG4gICAgICByZXR1cm4gcmVzdWx0XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb25zdCBjbGVhckRhdGFPblJvdXRlTGVhdmUgPSAoKSA9PiB7XHJcbiAgICBkYXRhU291cmNlc01hcC52YWx1ZSA9IHt9XHJcbiAgICBkYXRhU2xpY2VzLnZhbHVlID0gW11cclxuICB9XHJcblxyXG4gIGNvbnN0IHNldEZpbHRlckxvZ2ljID0gKGxvZ2ljOiBGaWx0ZXJMb2dpYykgPT4ge1xyXG4gICAgY3VycmVudEZpbHRlckxvZ2ljLnZhbHVlID0gbG9naWNcclxuICAgIGNvbXB1dGVTbGljZUludGVyc2VjdGlvbnMoKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIHBvcHVsYXRlRGF0YVN0b3JlLFxyXG4gICAgcXVlcnlPYmplY3RzLFxyXG4gICAgcHVzaE9yUmVwbGFjZVNsaWNlLFxyXG4gICAgcG9wU2xpY2UsXHJcbiAgICBjb21wdXRlU2xpY2VJbnRlcnNlY3Rpb25zLFxyXG4gICAgZ2V0RmluYWxPYmplY3RJZHMsXHJcbiAgICBjbGVhckRhdGFPblJvdXRlTGVhdmUsXHJcbiAgICBzZXRGaWx0ZXJMb2dpYyxcclxuICAgIGN1cnJlbnRGaWx0ZXJMb2dpYyxcclxuICAgIGRhdGFTbGljZXMsXHJcbiAgICBkYXRhU291cmNlc1xyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIEdldCB0aGUgZmlsdGVyaW5nIGRhdGEgc3RvcmUgZnJvbSB0aGUgY3VycmVudCB2aWV3ZXIgc3RhdGVcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiB1c2VGaWx0ZXJpbmdEYXRhU3RvcmUoKSB7XHJcbiAgY29uc3QgeyB2aWV3ZXIgfSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG5cclxuICBpZiAoIXZpZXdlci5tZXRhZGF0YS5maWx0ZXJpbmdEYXRhU3RvcmUpIHtcclxuICAgIHRocm93IG5ldyBFcnJvcihcclxuICAgICAgJ0ZpbHRlcmluZyBkYXRhIHN0b3JlIG5vdCBpbml0aWFsaXplZC4gRW5zdXJlIHZpZXdlciBpcyBwcm9wZXJseSBzZXQgdXAuJ1xyXG4gICAgKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHZpZXdlci5tZXRhZGF0YS5maWx0ZXJpbmdEYXRhU3RvcmVcclxufVxyXG4iXSwiZmlsZSI6IkQ6L3NwZWNrbGUtc2VydmVyL3BhY2thZ2VzL2Zyb250ZW5kLTIvbGliL3ZpZXdlci9jb21wb3NhYmxlcy9maWx0ZXJpbmcvZGF0YVN0b3JlLnRzIn0= |