import { difference, flatten, isEqual, uniq } from "/_nuxt/node_modules/.cache/vite/client/deps/lodash-es.js?v=e4f18c29"; import { useThrottleFn, watchTriggerable, useMagicKeys, useEventListener } from "/_nuxt/node_modules/@vueuse/core/index.mjs?v=e4f18c29"; import { ViewerEvent, VisualDiffMode, CameraController, DiffExtension, UpdateFlags, SectionOutlines, SectionToolEvent, SectionTool, SpeckleLoader, LargeModelStreamingLoader, ExplodeEvent, ExplodeExtension, LoaderEvent, SelectionExtension } from "/_nuxt/@fs/D:/speckle-server/packages/viewer/dist/index.js"; import { Vector3 } from "/_nuxt/node_modules/.cache/vite/client/deps/three.js?v=e4f18c29"; import { useAuthManager } from "/_nuxt/lib/auth/composables/auth.ts"; import { ProjectCommentsUpdatedMessageType } from "/_nuxt/lib/common/generated/gql/graphql.ts"; import { useInjectedViewerState, useInjectedViewerInterfaceState } from "/_nuxt/lib/viewer/composables/setup.ts"; import { useViewerSelectionEventHandler } from "/_nuxt/lib/viewer/composables/setup/selection.ts"; import { useGetObjectUrl, useOnViewerLoadComplete, useViewerCameraControlStartTracker, useViewerCameraTracker, useViewerEventListener } from "/_nuxt/lib/viewer/composables/viewer.ts"; import { useCommentContext, useViewerCommentUpdateTracking } from "/_nuxt/lib/viewer/composables/commentManagement.ts"; import { getCacheId } from "/_nuxt/lib/common/helpers/graphql.ts"; import { useViewerOpenedThreadUpdateEmitter, useViewerThreadTracking } from "/_nuxt/lib/viewer/composables/commentBubbles.ts"; import { useGeneralProjectPageUpdateTracking } from "/_nuxt/lib/projects/composables/projectPages.ts"; import { arraysEqual, isNonNullable } from "/_nuxt/lib/common/helpers/utils.ts"; import { getTargetObjectIds } from "/_nuxt/lib/object-sidebar/helpers.ts"; import { areVectorsLooselyEqual } from "/_nuxt/lib/viewer/helpers/three.ts"; import { SafeLocalStorage } from "/_nuxt/@fs/D:/speckle-server/packages/shared/dist/esm/index.js"; import { useCameraUtilities, useSectionBoxUtilities } from "/_nuxt/lib/viewer/composables/ui.ts"; import { ToastNotificationType, useGlobalToast } from "/_nuxt/lib/common/composables/toast.ts"; import { setupDebugMode } from "/_nuxt/lib/viewer/composables/setup/dev.ts"; import { useEmbed } from "/_nuxt/lib/viewer/composables/setup/embed.ts"; import { useMixpanel } from "/_nuxt/lib/core/composables/mp.ts"; import { graphql } from "/_nuxt/lib/common/generated/gql/index.ts"; import { useTreeManagement } from "/_nuxt/lib/viewer/composables/tree.ts"; import { useViewerSavedViewIntegration } from "/_nuxt/lib/viewer/composables/savedViews/state.ts"; import { useViewModesPostSetup } from "/_nuxt/lib/viewer/composables/setup/viewMode.ts"; import { useMeasurementsPostSetup } from "/_nuxt/lib/viewer/composables/setup/measurements.ts"; import { useFilterColoringPostSetup } from "/_nuxt/lib/viewer/composables/setup/coloring.ts"; import { usePropertyFilteringPostSetup, useManualFilteringPostSetup } from "/_nuxt/lib/viewer/composables/setup/filters.ts"; import { useFilterUtilities } from "/_nuxt/lib/viewer/composables/filtering/filtering.ts"; import { useFilteringSetup } from "/_nuxt/lib/viewer/composables/filtering/setup.ts"; import { useHighlightingPostSetup, HighlightExtension } from "/_nuxt/lib/viewer/composables/setup/highlighting.ts"; import { useProjectSavedViewsUpdateTracking } from "/_nuxt/lib/viewer/composables/savedViews/subscriptions.ts"; import { onMounted, onBeforeUnmount, watch, computed, ref } from "/_nuxt/node_modules/vue/dist/vue.runtime.esm-bundler.js?v=e4f18c29"; import { useApiOrigin } from "/_nuxt/composables/env.ts"; import { useActiveUser } from "/_nuxt/composables/globals.ts"; import { modifyObjectField } from "/_nuxt/utils/globals.ts"; function useViewerLoadCompleteEventHandler() { const state = useInjectedViewerState(); const callback = () => { state.ui.loading.value = false; }; onMounted(() => { state.viewer.instance.on(ViewerEvent.LoadComplete, callback); }); onBeforeUnmount(() => { state.viewer.instance.removeListener(ViewerEvent.LoadComplete, callback); }); } function useViewerObjectAutoLoading() { if (false) return; const disableViewerCache = SafeLocalStorage.get("FE2_FORCE_DISABLE_VIEWER_CACHE") === "true"; const { effectiveAuthToken } = useAuthManager(); const { triggerNotification } = useGlobalToast(); const getObjectUrl = useGetObjectUrl(); const apiOrigin = useApiOrigin({ forcePublic: true }); const { projectId, viewer: { instance: viewer, init: { ref: isInitialized }, hasDoneInitialLoad }, resources: { request: { savedView: { id: savedViewId } }, response: { resourceItems, savedView } }, ui: { loadProgress, loading, spotlightUserSessionId, hasLoadedQueuedUpModels }, urlHashState: { focusedThreadId } } = useInjectedViewerState(); const loadingProgressMap = {}; const derivativeNotificationKeys = /* @__PURE__ */ new Set(); viewer.on(ViewerEvent.LoadComplete, (id) => { delete loadingProgressMap[id]; consolidateProgressInternal({ id, progress: 1 }); }); const consolidateProgressInternal = (args) => { loadingProgressMap[args.id] = args.progress; const values = Object.values(loadingProgressMap); const min = values.length ? Math.min(...values) : 1; loadProgress.value = min; loading.value = min < 1; }; const consolidateProgressThorttled = useThrottleFn(consolidateProgressInternal, 250); const getViewerDerivativeManifest = async (versionId) => { const res = await fetch( new URL( `/api/viewer-derivatives/${projectId.value}/${versionId}/manifest`, apiOrigin ), { headers: effectiveAuthToken.value ? { Authorization: `Bearer ${effectiveAuthToken.value}` } : void 0, cache: "no-store" } ); if (res.status === 404) return void 0; if (!res.ok) return void 0; return await res.json(); }; const maybeLoadViewerDerivative = async (objectId, options) => { const resourceItem = resourceItems.value.find( (item) => item.objectId === objectId && item.versionId ); if (!resourceItem?.versionId) return false; const derivative = await getViewerDerivativeManifest(resourceItem.versionId); if (!derivative || derivative.status === "missing") return false; const notificationKey = `${resourceItem.versionId}:${derivative.status}`; if (!derivativeNotificationKeys.has(notificationKey)) { derivativeNotificationKeys.add(notificationKey); triggerNotification({ type: derivative.status === "failed" ? ToastNotificationType.Danger : ToastNotificationType.Info, title: "Large model streaming", description: derivative.status === "ready" ? "Loading viewer derivative." : derivative.status === "failed" ? derivative.errorMessage || "Viewer derivative generation failed." : "Viewer derivative generation is still processing." }); } if (derivative.status === "ready" && derivative.manifest) { const objectUrl = getObjectUrl(projectId.value, objectId); const artifactBaseUrl = new URL( `/api/viewer-derivatives/${projectId.value}/${resourceItem.versionId}/artifacts`, apiOrigin ).toString(); const loader = new LargeModelStreamingLoader( viewer.getWorldTree(), objectUrl, derivative.manifest, artifactBaseUrl, effectiveAuthToken.value || void 0 ); loader.on(LoaderEvent.LoadProgress, (args) => { consolidateProgressThorttled(args); }); loader.on(LoaderEvent.LoadCancelled, (id) => { delete loadingProgressMap[id]; consolidateProgressInternal({ id, progress: 1 }); }); await viewer.loadObject(loader, options?.zoomToObject); consolidateProgressInternal({ id: objectUrl, progress: 1 }); return true; } consolidateProgressInternal({ id: objectId, progress: 1 }); return true; }; const loadObject = async (objectId, unload, options) => { const objectUrl = getObjectUrl(projectId.value, objectId); if (unload) { return viewer.unloadObject(objectUrl); } else { if (await maybeLoadViewerDerivative(objectId, options)) return; const loader = new SpeckleLoader( viewer.getWorldTree(), objectUrl, effectiveAuthToken.value || void 0, disableViewerCache ? false : void 0, void 0 ); loader.on(LoaderEvent.LoadProgress, (args) => { consolidateProgressThorttled(args); }); loader.on(LoaderEvent.LoadCancelled, (id) => { delete loadingProgressMap[id]; consolidateProgressInternal({ id, progress: 1 }); }); loader.on(LoaderEvent.LoadWarning, ({ message }) => { if (!message.startsWith("Viewer full-load guard:")) return; triggerNotification({ type: ToastNotificationType.Danger, title: "Large model needs streaming", description: message }); }); return viewer.loadObject(loader, options?.zoomToObject); } }; const getUniqueObjectIds = (resourceItems2) => uniq(resourceItems2.map((i) => i.objectId)); const activeLoads = /* @__PURE__ */ new Set(); watch( () => [resourceItems.value, isInitialized.value, hasDoneInitialLoad.value], async ([newResources, newIsInitialized, newHasDoneInitialLoad], oldData) => { if (!newIsInitialized) return; const [oldResources] = oldData || [[], false]; const preventZooming = focusedThreadId.value || savedViewId.value || savedView.value || spotlightUserSessionId.value; const zoomToObject = !preventZooming; if (!newHasDoneInitialLoad) { const allObjectIds = getUniqueObjectIds(newResources); if (allObjectIds.length) { hasLoadedQueuedUpModels.value = false; } const res = []; const loadAll = async () => { for (const i of allObjectIds) { res.push(await loadObject(i, false, { zoomToObject })); } }; const promise2 = loadAll().then(() => { activeLoads.delete(promise2); }); activeLoads.add(promise2); await promise2; if (res.length) { hasDoneInitialLoad.value = true; if (!activeLoads.size) hasLoadedQueuedUpModels.value = true; } return; } const loadAndUnloadChanged = async () => { const newObjectIds = getUniqueObjectIds(newResources); const oldObjectIds = getUniqueObjectIds(oldResources); const removableObjectIds = difference(oldObjectIds, newObjectIds); const addableObjectIds = difference(newObjectIds, oldObjectIds); if (addableObjectIds.length) { hasLoadedQueuedUpModels.value = false; } await Promise.all(removableObjectIds.map((i) => loadObject(i, true))); await Promise.all( addableObjectIds.map((i) => loadObject(i, false, { zoomToObject: false })) ); }; const promise = loadAndUnloadChanged().then(() => { activeLoads.delete(promise); }); activeLoads.add(promise); await promise; if (!activeLoads.size) hasLoadedQueuedUpModels.value = true; }, { deep: true, immediate: true } ); onBeforeUnmount(async () => { await viewer.unloadAll(); }); } function useViewerReceiveTracking() { const { resources: { response: { modelsAndVersionIds } } } = useInjectedViewerState(); const mixpanel = useMixpanel(); const { userId } = useActiveUser(); const receivedVersions = /* @__PURE__ */ new Set(); watch(modelsAndVersionIds, (newVal) => { for (const { model, versionId } of newVal) { if (receivedVersions.has(versionId)) { continue; } receivedVersions.add(versionId); mixpanel.track("Receive", { hostApp: "viewer", sourceHostApp: model.loadedVersion.items[0].sourceApplication, isMultiplayer: model.loadedVersion.items[0].authorUser?.id !== userId.value }); } }); } function useViewerSubscriptionEventTracker() { if (false) return; const { projectId, resources: { request: { resourceIdString, threadFilters } } } = useInjectedViewerState(); useGeneralProjectPageUpdateTracking({ projectId }); useProjectSavedViewsUpdateTracking({ projectId }); useViewerCommentUpdateTracking( { projectId, resourceIdString, loadedVersionsOnly: computed(() => threadFilters.value.loadedVersionsOnly) }, (event, cache) => { const isArchived = event.type === ProjectCommentsUpdatedMessageType.Archived; const isNew = event.type === ProjectCommentsUpdatedMessageType.Created; const comment = event.comment; if (isArchived) { cache.modify({ id: getCacheId("Comment", event.id), fields: { archived: () => true } }); modifyObjectField( cache, getCacheId("Project", projectId.value), "commentThreads", ({ variables, helpers: { createUpdatedValue, readField } }) => { if (variables.filter?.includeArchived) return; return createUpdatedValue(({ update }) => { update("totalCount", (totalCount) => totalCount - 1); update( "items", (items) => items.filter((i) => readField(i, "id") !== event.id) ); }); } ); } else if (isNew && comment) { const parentId = comment.parent?.id; if (parentId) { modifyObjectField( cache, getCacheId("Comment", parentId), "replies", ({ helpers: { createUpdatedValue, ref: ref2 } }) => createUpdatedValue(({ update }) => { update("totalCount", (totalCount) => totalCount + 1); update("items", (items) => [ref2("Comment", comment.id), ...items]); }) ); } else { modifyObjectField( cache, getCacheId("Project", projectId.value), "commentThreads", ({ helpers: { ref: ref2, createUpdatedValue, readField }, value }) => { const includesItem = value.items?.find( (i) => readField(i, "id") === comment.id ); if (includesItem) return; return createUpdatedValue(({ update }) => { update("totalCount", (totalCount) => totalCount + 1); update("items", (items) => [ref2("Comment", comment.id), ...items]); }); } ); } } } ); } function useViewerSectionBoxIntegration() { const { ui: { sectionBox, sectionBoxContext: { visible, edited } }, viewer: { instance } } = useInjectedViewerState(); const { sectionBoxDataToBox3, sectionBoxDataEquals } = useSectionBoxUtilities(); const sectionTool = instance.getExtension(SectionTool); const onDragStart = () => { edited.value = true; }; sectionTool.on(SectionToolEvent.DragStart, onDragStart); watch( sectionBox, (newVal, oldVal) => { if (newVal && oldVal && sectionBoxDataEquals(newVal, oldVal)) return; if (!newVal && !oldVal) return; if (oldVal && !newVal) { visible.value = false; edited.value = false; sectionTool.enabled = false; instance.requestRender(UpdateFlags.RENDER_RESET); return; } if (newVal && (!oldVal || !sectionBoxDataEquals(newVal, oldVal))) { visible.value = true; edited.value = false; const box3 = sectionBoxDataToBox3(newVal); sectionTool.setBox(box3); sectionTool.enabled = true; const outlines = instance.getExtension(SectionOutlines); if (outlines) outlines.requestUpdate(); instance.requestRender(UpdateFlags.RENDER_RESET); } }, { immediate: true, deep: true, flush: "sync" } ); watch( visible, (newVal, oldVal) => { if (newVal && oldVal) return; if (!newVal && !oldVal) return; if (newVal) { sectionTool.visible = true; } else { sectionTool.visible = false; } instance.requestRender(); }, { immediate: true, deep: true, flush: "sync" } ); onBeforeUnmount(() => { sectionTool.enabled = false; sectionTool.removeListener(SectionToolEvent.DragStart, onDragStart); }); } function useViewerCameraIntegration() { const { viewer: { instance }, ui: { camera: { isOrthoProjection, position, target }, spotlightUserSessionId } } = useInjectedViewerState(); const { forceViewToViewerSync, setView, cameraController } = useCameraUtilities(); const hasInitialLoadFired = ref(false); const loadCameraDataFromViewer = () => { const extension = instance.getExtension(CameraController); const viewerPos = new Vector3().copy(extension.getPosition()); const viewerTarget = new Vector3().copy(extension.getTarget()); if (hasInitialLoadFired.value) { if (!areVectorsLooselyEqual(position.value, viewerPos)) { position.value = viewerPos.clone(); } if (!areVectorsLooselyEqual(target.value, viewerTarget)) { target.value = viewerTarget.clone(); } } }; useViewerCameraTracker( () => { loadCameraDataFromViewer(); }, { throttleWait: 100 } ); useOnViewerLoadComplete(({ isInitial }) => { if (isInitial) { hasInitialLoadFired.value = true; const hasInitCoords = position.value.equals(new Vector3()) && target.value.equals(new Vector3()); if (hasInitCoords) { loadCameraDataFromViewer(); } else { forceViewToViewerSync(); } orthoProjectionUpdate(isOrthoProjection.value); } else { loadCameraDataFromViewer(); } }); useViewerCameraControlStartTracker(() => { if (spotlightUserSessionId.value) { spotlightUserSessionId.value = null; } }); const orthoProjectionUpdate = (newVal) => { if (!hasInitialLoadFired.value) { throw new Error("Attempting to set projection too early"); } if (newVal) { cameraController.setOrthoCameraOn(); } else { cameraController.setPerspectiveCameraOn(); } forceViewToViewerSync(); }; watch( isOrthoProjection, (newVal, oldVal) => { if (newVal === oldVal || !hasInitialLoadFired.value) return; orthoProjectionUpdate(newVal); }, { immediate: true } ); watch( position, (newVal, oldVal) => { if (!newVal && !oldVal || oldVal && areVectorsLooselyEqual(newVal, oldVal)) { return; } setView({ position: newVal, target: target.value }); } // { immediate: true } ); watch( target, (newVal, oldVal) => { if (!newVal && !oldVal || oldVal && areVectorsLooselyEqual(newVal, oldVal)) { return; } setView({ position: position.value, target: newVal }); } // { immediate: true } ); } function useViewerFiltersIntegration() { const state = useInjectedViewerState(); const { viewer: { instance }, ui: { filters } } = state; useFilteringSetup(); useFilterUtilities({ state }); watch( filters.selectedObjects, (newVal, oldVal) => { const newIds = flatten( newVal.map((v) => getTargetObjectIds(v)) ).filter(isNonNullable); const oldIds = flatten( (oldVal || []).map((v) => getTargetObjectIds(v)) ).filter(isNonNullable); if (arraysEqual(newIds, oldIds)) return; const selectionExtension = instance.getExtension(SelectionExtension); const currentViewerSelection = selectionExtension.getSelectedObjects().map((obj) => obj.id); if (currentViewerSelection.length === newIds.length && difference(currentViewerSelection, newIds).length === 0) { return; } state.ui.highlightedObjectIds.value = []; const highlightExtension = instance.getExtension(HighlightExtension); if (highlightExtension) { highlightExtension.clearSelection(); } selectionExtension.clearSelection(); if (newVal.length > 0) { selectionExtension.selectObjects(newIds); } }, { immediate: true, flush: "sync" } ); } function useLightConfigIntegration() { const { ui: { lightConfig }, viewer: { instance } } = useInjectedViewerState(); useViewerEventListener( ViewerEvent.LightConfigUpdated, (config) => { if (isEqual(lightConfig.value, config)) return; lightConfig.value = config; } ); watch( lightConfig, (newVal, oldVal) => { if (newVal && oldVal && isEqual(newVal, oldVal)) return; instance.setLightConfiguration(newVal); }, { immediate: true, deep: true, flush: "sync" } ); useOnViewerLoadComplete( () => { instance.setLightConfiguration(lightConfig.value); }, { initialOnly: true } ); } function useExplodeFactorIntegration() { const { ui: { explodeFactor }, viewer: { instance } } = useInjectedViewerState(); const explodeExtension = instance.getExtension(ExplodeExtension); const updateOutlines = () => { const sectionOutlines = instance.getExtension(SectionOutlines); if (sectionOutlines && sectionOutlines.enabled) sectionOutlines.requestUpdate(true); }; onMounted(() => { explodeExtension.on(ExplodeEvent.Finshed, updateOutlines); }); onBeforeUnmount(() => { explodeExtension.removeListener(ExplodeEvent.Finshed, updateOutlines); }); watch( explodeFactor, (newVal) => { explodeExtension.setExplode(newVal); }, { immediate: true } ); useOnViewerLoadComplete( () => { explodeExtension.setExplode(explodeFactor.value); }, { initialOnly: true } ); } function useDiffingIntegration() { const state = useInjectedViewerState(); const { effectiveAuthToken } = useAuthManager(); const getObjectUrl = useGetObjectUrl(); const hasInitialLoadFired = ref(false); const diffExtension = state.viewer.instance.getExtension(DiffExtension); const { trigger: triggerDiffCommandWatch } = watchTriggerable( () => [state.ui.diff.oldVersion.value, state.ui.diff.newVersion.value], async (newVal, oldVal) => { if (!hasInitialLoadFired.value) return; const [oldVersion, newVersion] = newVal; const [oldOldVersion, oldNewVersion] = oldVal || [null, null]; const versionId = (version) => version?.id || null; const commandId = (oldVersion2, newVersion2) => { const oldId = versionId(oldVersion2); const newId = versionId(newVersion2); return oldId && newId ? `${oldId}->${newId}` : null; }; const newCommand = commandId(oldVersion, newVersion); const oldCommand = commandId(oldOldVersion, oldNewVersion); if (newCommand && oldCommand === newCommand || !!newCommand === !!oldCommand) return; if (!newCommand || oldVal) { await diffExtension.undiff(); if (!newCommand) return; } const oldObjUrl = getObjectUrl( state.projectId.value, oldVersion?.referencedObject ); const newObjUrl = getObjectUrl( state.projectId.value, newVersion?.referencedObject ); state.ui.diff.result.value = await diffExtension.diff( oldObjUrl, newObjUrl, state.ui.diff.mode.value, effectiveAuthToken.value ); }, { immediate: true } ); watch(state.ui.diff.result, (val) => { if (!val) return; ignoreDiffModeUpdates(() => { ignoreDiffTimeUpdates(() => { state.ui.diff.time.value = 0.5; state.ui.diff.mode.value = VisualDiffMode.COLORED; triggerDiffModeWatch(); }); }); }); const { ignoreUpdates: ignoreDiffTimeUpdates } = watchTriggerable( state.ui.diff.time, (val) => { if (!hasInitialLoadFired.value) return; if (!state.ui.diff.result.value) return; diffExtension.updateVisualDiff(val, state.ui.diff.mode.value); } ); const { trigger: triggerDiffModeWatch, ignoreUpdates: ignoreDiffModeUpdates } = watchTriggerable(state.ui.diff.mode, (val) => { if (!hasInitialLoadFired.value) return; if (!state.ui.diff.result.value) return; diffExtension.updateVisualDiff(state.ui.diff.time.value, val); }); useOnViewerLoadComplete(({ isInitial }) => { if (!isInitial) return; hasInitialLoadFired.value = true; triggerDiffCommandWatch(); }); } function useDisableZoomOnEmbed() { const { viewer } = useInjectedViewerState(); const embedOptions = useEmbed(); watch( () => embedOptions.noScroll.value, (newNoScrollValue) => { const cameraController = viewer.instance.getExtension(CameraController); if (newNoScrollValue) { cameraController.options = { enableZoom: false }; } else { cameraController.options = { enableZoom: true }; } }, { immediate: true } ); } function useViewerTreeIntegration() { const { viewer } = useInjectedViewerState(); const { treeStateManager } = useTreeManagement(); onMounted(() => treeStateManager.initialize(viewer.instance)); } graphql(` fragment UseViewerSavedViewSetup_SavedView on SavedView { id viewerState ...ViewerPageSetup_SavedView } `); function useViewerCursorIntegration() { const { viewer: { container } } = useInjectedViewerState(); const { filters: { selectedObjects } } = useInjectedViewerInterfaceState(); const { shift } = useMagicKeys(); const isDragging = ref(false); const handlePointerDown = (_event) => { if (shift.value && selectedObjects.value.length === 0) { isDragging.value = true; } }; const handlePointerUp = () => { isDragging.value = false; }; watch( [shift, selectedObjects, isDragging], () => { if (!container) return; const hasSelection = selectedObjects.value.length > 0; const shouldShowDrag = shift.value && !hasSelection; if (shouldShowDrag) { container.style.cursor = isDragging.value ? "grabbing" : "grab"; } else { container.style.cursor = ""; } }, { immediate: true } ); useEventListener(container, "pointerdown", handlePointerDown, { passive: true }); useEventListener(document, "pointerup", handlePointerUp, { passive: true }); onBeforeUnmount(() => { if (container) { container.style.cursor = ""; } }); } const useCommentContextIntegration = () => { const { cleanupThreadContext } = useCommentContext(); onBeforeUnmount(() => { cleanupThreadContext(); }); }; export function useViewerPostSetup() { if (false) return; useViewerObjectAutoLoading(); useViewerSavedViewIntegration(); useViewerReceiveTracking(); useViewerSelectionEventHandler(); useViewerLoadCompleteEventHandler(); useViewerSubscriptionEventTracker(); useViewerThreadTracking(); useViewerOpenedThreadUpdateEmitter(); useViewerSectionBoxIntegration(); useViewerCameraIntegration(); useViewerFiltersIntegration(); useLightConfigIntegration(); useExplodeFactorIntegration(); useDiffingIntegration(); useMeasurementsPostSetup(); useFilterColoringPostSetup(); usePropertyFilteringPostSetup(); useManualFilteringPostSetup(); useDisableZoomOnEmbed(); useViewerCursorIntegration(); useViewerTreeIntegration(); useViewModesPostSetup(); useHighlightingPostSetup(); useCommentContextIntegration(); setupDebugMode(); } //# sourceMappingURL=data:application/json;base64,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LDJCQUF5QjtBQUN6QixpQ0FBK0I7QUFDL0Isb0NBQWtDO0FBQ2xDLG9DQUFrQztBQUNsQywwQkFBd0I7QUFDeEIscUNBQW1DO0FBQ25DLGlDQUErQjtBQUMvQiw2QkFBMkI7QUFDM0IsOEJBQTRCO0FBQzVCLDRCQUEwQjtBQUMxQiw4QkFBNEI7QUFDNUIsd0JBQXNCO0FBQ3RCLDJCQUF5QjtBQUN6Qiw2QkFBMkI7QUFDM0IsZ0NBQThCO0FBQzlCLDhCQUE0QjtBQUM1Qix3QkFBc0I7QUFDdEIsNkJBQTJCO0FBQzNCLDJCQUF5QjtBQUN6Qix3QkFBc0I7QUFDdEIsMkJBQXlCO0FBQ3pCLCtCQUE2QjtBQUM3QixpQkFBZTtBQUNqQiIsIm5hbWVzIjpbInJlc291cmNlSXRlbXMiLCJwcm9taXNlIiwicmVmIiwib2xkVmVyc2lvbiIsIm5ld1ZlcnNpb24iXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZXMiOlsicG9zdFNldHVwLnRzIl0sInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGRpZmZlcmVuY2UsIGZsYXR0ZW4sIGlzRXF1YWwsIHVuaXEgfSBmcm9tICdsb2Rhc2gtZXMnXHJcbmltcG9ydCB7XHJcbiAgdXNlVGhyb3R0bGVGbixcclxuICB3YXRjaFRyaWdnZXJhYmxlLFxyXG4gIHVzZU1hZ2ljS2V5cyxcclxuICB1c2VFdmVudExpc3RlbmVyXHJcbn0gZnJvbSAnQHZ1ZXVzZS9jb3JlJ1xyXG5pbXBvcnQge1xyXG4gIFZpZXdlckV2ZW50LFxyXG4gIFZpc3VhbERpZmZNb2RlLFxyXG4gIENhbWVyYUNvbnRyb2xsZXIsXHJcbiAgRGlmZkV4dGVuc2lvbixcclxuICBVcGRhdGVGbGFncyxcclxuICBTZWN0aW9uT3V0bGluZXMsXHJcbiAgU2VjdGlvblRvb2xFdmVudCxcclxuICBTZWN0aW9uVG9vbCxcclxuICBTcGVja2xlTG9hZGVyLFxyXG4gIExhcmdlTW9kZWxTdHJlYW1pbmdMb2FkZXIsXHJcbiAgRXhwbG9kZUV2ZW50LFxyXG4gIEV4cGxvZGVFeHRlbnNpb24sXHJcbiAgTG9hZGVyRXZlbnQsXHJcbiAgU2VsZWN0aW9uRXh0ZW5zaW9uLFxyXG4gIHR5cGUgU3VuTGlnaHRDb25maWd1cmF0aW9uXHJcbn0gZnJvbSAnQHNwZWNrbGUvdmlld2VyJ1xyXG5pbXBvcnQgeyBWZWN0b3IzIH0gZnJvbSAndGhyZWUnXHJcbmltcG9ydCB7IHVzZUF1dGhNYW5hZ2VyIH0gZnJvbSAnfn4vbGliL2F1dGgvY29tcG9zYWJsZXMvYXV0aCdcclxuaW1wb3J0IHR5cGUgeyBWaWV3ZXJSZXNvdXJjZUl0ZW0gfSBmcm9tICd+fi9saWIvY29tbW9uL2dlbmVyYXRlZC9ncWwvZ3JhcGhxbCdcclxuaW1wb3J0IHsgUHJvamVjdENvbW1lbnRzVXBkYXRlZE1lc3NhZ2VUeXBlIH0gZnJvbSAnfn4vbGliL2NvbW1vbi9nZW5lcmF0ZWQvZ3FsL2dyYXBocWwnXHJcbmltcG9ydCB7XHJcbiAgdXNlSW5qZWN0ZWRWaWV3ZXJTdGF0ZSxcclxuICB1c2VJbmplY3RlZFZpZXdlckludGVyZmFjZVN0YXRlXHJcbn0gZnJvbSAnfn4vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9zZXR1cCdcclxuaW1wb3J0IHsgdXNlVmlld2VyU2VsZWN0aW9uRXZlbnRIYW5kbGVyIH0gZnJvbSAnfn4vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9zZXR1cC9zZWxlY3Rpb24nXHJcbmltcG9ydCB7XHJcbiAgdXNlR2V0T2JqZWN0VXJsLFxyXG4gIHVzZU9uVmlld2VyTG9hZENvbXBsZXRlLFxyXG4gIHVzZVZpZXdlckNhbWVyYUNvbnRyb2xTdGFydFRyYWNrZXIsXHJcbiAgdXNlVmlld2VyQ2FtZXJhVHJhY2tlcixcclxuICB1c2VWaWV3ZXJFdmVudExpc3RlbmVyXHJcbn0gZnJvbSAnfn4vbGliL3ZpZXdlci9jb21wb3NhYmxlcy92aWV3ZXInXHJcbmltcG9ydCB7XHJcbiAgdXNlQ29tbWVudENvbnRleHQsXHJcbiAgdXNlVmlld2VyQ29tbWVudFVwZGF0ZVRyYWNraW5nXHJcbn0gZnJvbSAnfn4vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9jb21tZW50TWFuYWdlbWVudCdcclxuaW1wb3J0IHsgZ2V0Q2FjaGVJZCB9IGZyb20gJ35+L2xpYi9jb21tb24vaGVscGVycy9ncmFwaHFsJ1xyXG5pbXBvcnQge1xyXG4gIHVzZVZpZXdlck9wZW5lZFRocmVhZFVwZGF0ZUVtaXR0ZXIsXHJcbiAgdXNlVmlld2VyVGhyZWFkVHJhY2tpbmdcclxufSBmcm9tICd+fi9saWIvdmlld2VyL2NvbXBvc2FibGVzL2NvbW1lbnRCdWJibGVzJ1xyXG5pbXBvcnQgeyB1c2VHZW5lcmFsUHJvamVjdFBhZ2VVcGRhdGVUcmFja2luZyB9IGZyb20gJ35+L2xpYi9wcm9qZWN0cy9jb21wb3NhYmxlcy9wcm9qZWN0UGFnZXMnXHJcbmltcG9ydCB7IGFycmF5c0VxdWFsLCBpc05vbk51bGxhYmxlIH0gZnJvbSAnfn4vbGliL2NvbW1vbi9oZWxwZXJzL3V0aWxzJ1xyXG5pbXBvcnQgeyBnZXRUYXJnZXRPYmplY3RJZHMgfSBmcm9tICd+fi9saWIvb2JqZWN0LXNpZGViYXIvaGVscGVycydcclxuaW1wb3J0IHsgYXJlVmVjdG9yc0xvb3NlbHlFcXVhbCB9IGZyb20gJ35+L2xpYi92aWV3ZXIvaGVscGVycy90aHJlZSdcclxuaW1wb3J0IHsgU2FmZUxvY2FsU3RvcmFnZSB9IGZyb20gJ0BzcGVja2xlL3NoYXJlZCdcclxuaW1wb3J0IHtcclxuICB1c2VDYW1lcmFVdGlsaXRpZXMsXHJcbiAgdXNlU2VjdGlvbkJveFV0aWxpdGllc1xyXG59IGZyb20gJ35+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvdWknXHJcbmltcG9ydCB7IFRvYXN0Tm90aWZpY2F0aW9uVHlwZSwgdXNlR2xvYmFsVG9hc3QgfSBmcm9tICd+fi9saWIvY29tbW9uL2NvbXBvc2FibGVzL3RvYXN0J1xyXG5pbXBvcnQgeyBzZXR1cERlYnVnTW9kZSB9IGZyb20gJ35+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvc2V0dXAvZGV2J1xyXG5pbXBvcnQgeyB1c2VFbWJlZCB9IGZyb20gJ34vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9zZXR1cC9lbWJlZCdcclxuaW1wb3J0IHsgdXNlTWl4cGFuZWwgfSBmcm9tICd+fi9saWIvY29yZS9jb21wb3NhYmxlcy9tcCdcclxuaW1wb3J0IHsgZ3JhcGhxbCB9IGZyb20gJ34vbGliL2NvbW1vbi9nZW5lcmF0ZWQvZ3FsJ1xyXG5pbXBvcnQgeyB1c2VUcmVlTWFuYWdlbWVudCB9IGZyb20gJ35+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvdHJlZSdcclxuaW1wb3J0IHsgdXNlVmlld2VyU2F2ZWRWaWV3SW50ZWdyYXRpb24gfSBmcm9tICd+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvc2F2ZWRWaWV3cy9zdGF0ZSdcclxuaW1wb3J0IHsgdXNlVmlld01vZGVzUG9zdFNldHVwIH0gZnJvbSAnfi9saWIvdmlld2VyL2NvbXBvc2FibGVzL3NldHVwL3ZpZXdNb2RlJ1xyXG5pbXBvcnQgeyB1c2VNZWFzdXJlbWVudHNQb3N0U2V0dXAgfSBmcm9tICd+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvc2V0dXAvbWVhc3VyZW1lbnRzJ1xyXG5pbXBvcnQgeyB1c2VGaWx0ZXJDb2xvcmluZ1Bvc3RTZXR1cCB9IGZyb20gJ34vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9zZXR1cC9jb2xvcmluZydcclxuaW1wb3J0IHtcclxuICB1c2VQcm9wZXJ0eUZpbHRlcmluZ1Bvc3RTZXR1cCxcclxuICB1c2VNYW51YWxGaWx0ZXJpbmdQb3N0U2V0dXBcclxufSBmcm9tICd+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvc2V0dXAvZmlsdGVycydcclxuaW1wb3J0IHsgdXNlRmlsdGVyVXRpbGl0aWVzIH0gZnJvbSAnfi9saWIvdmlld2VyL2NvbXBvc2FibGVzL2ZpbHRlcmluZy9maWx0ZXJpbmcnXHJcbmltcG9ydCB7IHVzZUZpbHRlcmluZ1NldHVwIH0gZnJvbSAnfi9saWIvdmlld2VyL2NvbXBvc2FibGVzL2ZpbHRlcmluZy9zZXR1cCdcclxuaW1wb3J0IHtcclxuICB1c2VIaWdobGlnaHRpbmdQb3N0U2V0dXAsXHJcbiAgSGlnaGxpZ2h0RXh0ZW5zaW9uXHJcbn0gZnJvbSAnfi9saWIvdmlld2VyL2NvbXBvc2FibGVzL3NldHVwL2hpZ2hsaWdodGluZydcclxuaW1wb3J0IHsgdXNlUHJvamVjdFNhdmVkVmlld3NVcGRhdGVUcmFja2luZyB9IGZyb20gJ34vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9zYXZlZFZpZXdzL3N1YnNjcmlwdGlvbnMnXHJcblxyXG5mdW5jdGlvbiB1c2VWaWV3ZXJMb2FkQ29tcGxldGVFdmVudEhhbmRsZXIoKSB7XHJcbiAgY29uc3Qgc3RhdGUgPSB1c2VJbmplY3RlZFZpZXdlclN0YXRlKClcclxuXHJcbiAgY29uc3QgY2FsbGJhY2sgPSAoKSA9PiB7XHJcbiAgICBzdGF0ZS51aS5sb2FkaW5nLnZhbHVlID0gZmFsc2VcclxuICB9XHJcbiAgb25Nb3VudGVkKCgpID0+IHtcclxuICAgIHN0YXRlLnZpZXdlci5pbnN0YW5jZS5vbihWaWV3ZXJFdmVudC5Mb2FkQ29tcGxldGUsIGNhbGxiYWNrKVxyXG4gIH0pXHJcblxyXG4gIG9uQmVmb3JlVW5tb3VudCgoKSA9PiB7XHJcbiAgICBzdGF0ZS52aWV3ZXIuaW5zdGFuY2UucmVtb3ZlTGlzdGVuZXIoVmlld2VyRXZlbnQuTG9hZENvbXBsZXRlLCBjYWxsYmFjaylcclxuICB9KVxyXG59XHJcblxyXG4vKipcclxuICogQXV0b21hdGljYWxseSBsb2FkcyAmIHVubG9hZHMgb2JqZWN0cyBpbnRvIHRoZSB2aWV3ZXIgZGVwZW5kaW5nIG9uIHRoZSBnbG9iYWwgVVJMIHJlc291cmNlIGlkZW50aWZpZXIgc3RhdGVcclxuICovXHJcbmZ1bmN0aW9uIHVzZVZpZXdlck9iamVjdEF1dG9Mb2FkaW5nKCkge1xyXG4gIGlmIChpbXBvcnQubWV0YS5zZXJ2ZXIpIHJldHVyblxyXG5cclxuICB0eXBlIFZpZXdlckRlcml2YXRpdmVNYW5pZmVzdFJlc3BvbnNlID0ge1xyXG4gICAgc3RhdHVzOiAnbWlzc2luZycgfCAncXVldWVkJyB8ICdwcm9jZXNzaW5nJyB8ICdyZWFkeScgfCAnZmFpbGVkJ1xyXG4gICAgc3RhZ2U/OiBzdHJpbmcgfCBudWxsXHJcbiAgICBwcm9ncmVzcz86IG51bWJlciB8IG51bGxcclxuICAgIGVycm9yTWVzc2FnZT86IHN0cmluZyB8IG51bGxcbiAgICBtYW5pZmVzdD86IHtcbiAgICAgIGJvdW5kcz86IG51bWJlcltdXG4gICAgICB0aWxlczogQXJyYXk8e1xuICAgICAgICBpZD86IHN0cmluZ1xuICAgICAgICBiYm94PzogbnVtYmVyW11cbiAgICAgICAgbG9kczogQXJyYXk8e1xuICAgICAgICAgIGxldmVsPzogbnVtYmVyXG4gICAgICAgICAgdXJsOiBzdHJpbmdcbiAgICAgICAgICBieXRlcz86IG51bWJlclxuICAgICAgICAgIG1lc2hlcz86IG51bWJlclxuICAgICAgICAgIHZlcnRleENvdW50PzogbnVtYmVyXG4gICAgICAgICAgaW5kZXhDb3VudD86IG51bWJlclxuICAgICAgICAgIHRyaWFuZ2xlQ291bnQ/OiBudW1iZXJcbiAgICAgICAgfT5cbiAgICAgIH0+XG4gICAgfVxuICB9XHJcblxyXG4gIGNvbnN0IGRpc2FibGVWaWV3ZXJDYWNoZSA9XHJcbiAgICBTYWZlTG9jYWxTdG9yYWdlLmdldCgnRkUyX0ZPUkNFX0RJU0FCTEVfVklFV0VSX0NBQ0hFJykgPT09ICd0cnVlJ1xyXG4gIGNvbnN0IHsgZWZmZWN0aXZlQXV0aFRva2VuIH0gPSB1c2VBdXRoTWFuYWdlcigpXG4gIGNvbnN0IHsgdHJpZ2dlck5vdGlmaWNhdGlvbiB9ID0gdXNlR2xvYmFsVG9hc3QoKVxuICBjb25zdCBnZXRPYmplY3RVcmwgPSB1c2VHZXRPYmplY3RVcmwoKVxuICBjb25zdCBhcGlPcmlnaW4gPSB1c2VBcGlPcmlnaW4oeyBmb3JjZVB1YmxpYzogdHJ1ZSB9KVxuICBjb25zdCB7XHJcbiAgICBwcm9qZWN0SWQsXHJcbiAgICB2aWV3ZXI6IHtcclxuICAgICAgaW5zdGFuY2U6IHZpZXdlcixcclxuICAgICAgaW5pdDogeyByZWY6IGlzSW5pdGlhbGl6ZWQgfSxcclxuICAgICAgaGFzRG9uZUluaXRpYWxMb2FkXHJcbiAgICB9LFxyXG4gICAgcmVzb3VyY2VzOiB7XHJcbiAgICAgIHJlcXVlc3Q6IHtcclxuICAgICAgICBzYXZlZFZpZXc6IHsgaWQ6IHNhdmVkVmlld0lkIH1cclxuICAgICAgfSxcclxuICAgICAgcmVzcG9uc2U6IHsgcmVzb3VyY2VJdGVtcywgc2F2ZWRWaWV3IH1cclxuICAgIH0sXHJcbiAgICB1aTogeyBsb2FkUHJvZ3Jlc3MsIGxvYWRpbmcsIHNwb3RsaWdodFVzZXJTZXNzaW9uSWQsIGhhc0xvYWRlZFF1ZXVlZFVwTW9kZWxzIH0sXHJcbiAgICB1cmxIYXNoU3RhdGU6IHsgZm9jdXNlZFRocmVhZElkIH1cclxuICB9ID0gdXNlSW5qZWN0ZWRWaWV3ZXJTdGF0ZSgpXHJcblxyXG4gIGNvbnN0IGxvYWRpbmdQcm9ncmVzc01hcDogeyBbaWQ6IHN0cmluZ106IG51bWJlciB9ID0ge31cclxuICBjb25zdCBkZXJpdmF0aXZlTm90aWZpY2F0aW9uS2V5cyA9IG5ldyBTZXQ8c3RyaW5nPigpXHJcblxyXG4gIHZpZXdlci5vbihWaWV3ZXJFdmVudC5Mb2FkQ29tcGxldGUsIChpZCkgPT4ge1xyXG4gICAgZGVsZXRlIGxvYWRpbmdQcm9ncmVzc01hcFtpZF1cclxuICAgIGNvbnNvbGlkYXRlUHJvZ3Jlc3NJbnRlcm5hbCh7IGlkLCBwcm9ncmVzczogMSB9KVxyXG4gIH0pXHJcblxyXG4gIGNvbnN0IGNvbnNvbGlkYXRlUHJvZ3Jlc3NJbnRlcm5hbCA9IChhcmdzOiB7IHByb2dyZXNzOiBudW1iZXI7IGlkOiBzdHJpbmcgfSkgPT4ge1xyXG4gICAgbG9hZGluZ1Byb2dyZXNzTWFwW2FyZ3MuaWRdID0gYXJncy5wcm9ncmVzc1xyXG4gICAgY29uc3QgdmFsdWVzID0gT2JqZWN0LnZhbHVlcyhsb2FkaW5nUHJvZ3Jlc3NNYXApXHJcbiAgICBjb25zdCBtaW4gPSB2YWx1ZXMubGVuZ3RoID8gTWF0aC5taW4oLi4udmFsdWVzKSA6IDFcclxuXHJcbiAgICBsb2FkUHJvZ3Jlc3MudmFsdWUgPSBtaW5cclxuICAgIGxvYWRpbmcudmFsdWUgPSBtaW4gPCAxXHJcbiAgfVxyXG5cclxuICBjb25zdCBjb25zb2xpZGF0ZVByb2dyZXNzVGhvcnR0bGVkID0gdXNlVGhyb3R0bGVGbihjb25zb2xpZGF0ZVByb2dyZXNzSW50ZXJuYWwsIDI1MClcclxuXHJcbiAgY29uc3QgZ2V0Vmlld2VyRGVyaXZhdGl2ZU1hbmlmZXN0ID0gYXN5bmMgKFxuICAgIHZlcnNpb25JZDogc3RyaW5nXG4gICk6IFByb21pc2U8Vmlld2VyRGVyaXZhdGl2ZU1hbmlmZXN0UmVzcG9uc2UgfCB1bmRlZmluZWQ+ID0+IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaChcbiAgICAgIG5ldyBVUkwoXG4gICAgICAgIGAvYXBpL3ZpZXdlci1kZXJpdmF0aXZlcy8ke3Byb2plY3RJZC52YWx1ZX0vJHt2ZXJzaW9uSWR9L21hbmlmZXN0YCxcbiAgICAgICAgYXBpT3JpZ2luXG4gICAgICApLFxuICAgICAge1xuICAgICAgICBoZWFkZXJzOiBlZmZlY3RpdmVBdXRoVG9rZW4udmFsdWVcbiAgICAgICAgICA/IHsgQXV0aG9yaXphdGlvbjogYEJlYXJlciAke2VmZmVjdGl2ZUF1dGhUb2tlbi52YWx1ZX1gIH1cbiAgICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgICAgY2FjaGU6ICduby1zdG9yZSdcbiAgICAgIH1cbiAgICApXG5cclxuICAgIGlmIChyZXMuc3RhdHVzID09PSA0MDQpIHJldHVybiB1bmRlZmluZWRcclxuICAgIGlmICghcmVzLm9rKSByZXR1cm4gdW5kZWZpbmVkXHJcblxyXG4gICAgcmV0dXJuIChhd2FpdCByZXMuanNvbigpKSBhcyBWaWV3ZXJEZXJpdmF0aXZlTWFuaWZlc3RSZXNwb25zZVxyXG4gIH1cclxuXHJcbiAgY29uc3QgbWF5YmVMb2FkVmlld2VyRGVyaXZhdGl2ZSA9IGFzeW5jIChcclxuICAgIG9iamVjdElkOiBzdHJpbmcsXHJcbiAgICBvcHRpb25zPzogUGFydGlhbDx7IHpvb21Ub09iamVjdDogYm9vbGVhbiB9PlxyXG4gICkgPT4ge1xyXG4gICAgY29uc3QgcmVzb3VyY2VJdGVtID0gcmVzb3VyY2VJdGVtcy52YWx1ZS5maW5kKFxyXG4gICAgICAoaXRlbSkgPT4gaXRlbS5vYmplY3RJZCA9PT0gb2JqZWN0SWQgJiYgaXRlbS52ZXJzaW9uSWRcclxuICAgIClcclxuICAgIGlmICghcmVzb3VyY2VJdGVtPy52ZXJzaW9uSWQpIHJldHVybiBmYWxzZVxyXG5cclxuICAgIGNvbnN0IGRlcml2YXRpdmUgPSBhd2FpdCBnZXRWaWV3ZXJEZXJpdmF0aXZlTWFuaWZlc3QocmVzb3VyY2VJdGVtLnZlcnNpb25JZClcclxuICAgIGlmICghZGVyaXZhdGl2ZSB8fCBkZXJpdmF0aXZlLnN0YXR1cyA9PT0gJ21pc3NpbmcnKSByZXR1cm4gZmFsc2VcclxuXHJcbiAgICBjb25zdCBub3RpZmljYXRpb25LZXkgPSBgJHtyZXNvdXJjZUl0ZW0udmVyc2lvbklkfToke2Rlcml2YXRpdmUuc3RhdHVzfWBcclxuICAgIGlmICghZGVyaXZhdGl2ZU5vdGlmaWNhdGlvbktleXMuaGFzKG5vdGlmaWNhdGlvbktleSkpIHtcclxuICAgICAgZGVyaXZhdGl2ZU5vdGlmaWNhdGlvbktleXMuYWRkKG5vdGlmaWNhdGlvbktleSlcclxuICAgICAgdHJpZ2dlck5vdGlmaWNhdGlvbih7XHJcbiAgICAgICAgdHlwZTpcclxuICAgICAgICAgIGRlcml2YXRpdmUuc3RhdHVzID09PSAnZmFpbGVkJ1xyXG4gICAgICAgICAgICA/IFRvYXN0Tm90aWZpY2F0aW9uVHlwZS5EYW5nZXJcclxuICAgICAgICAgICAgOiBUb2FzdE5vdGlmaWNhdGlvblR5cGUuSW5mbyxcclxuICAgICAgICB0aXRsZTogJ0xhcmdlIG1vZGVsIHN0cmVhbWluZycsXHJcbiAgICAgICAgZGVzY3JpcHRpb246XHJcbiAgICAgICAgICBkZXJpdmF0aXZlLnN0YXR1cyA9PT0gJ3JlYWR5J1xyXG4gICAgICAgICAgICA/ICdMb2FkaW5nIHZpZXdlciBkZXJpdmF0aXZlLidcclxuICAgICAgICAgICAgOiBkZXJpdmF0aXZlLnN0YXR1cyA9PT0gJ2ZhaWxlZCdcclxuICAgICAgICAgICAgPyBkZXJpdmF0aXZlLmVycm9yTWVzc2FnZSB8fCAnVmlld2VyIGRlcml2YXRpdmUgZ2VuZXJhdGlvbiBmYWlsZWQuJ1xyXG4gICAgICAgICAgICA6ICdWaWV3ZXIgZGVyaXZhdGl2ZSBnZW5lcmF0aW9uIGlzIHN0aWxsIHByb2Nlc3NpbmcuJ1xyXG4gICAgICB9KVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChkZXJpdmF0aXZlLnN0YXR1cyA9PT0gJ3JlYWR5JyAmJiBkZXJpdmF0aXZlLm1hbmlmZXN0KSB7XHJcbiAgICAgIGNvbnN0IG9iamVjdFVybCA9IGdldE9iamVjdFVybChwcm9qZWN0SWQudmFsdWUsIG9iamVjdElkKVxuICAgICAgY29uc3QgYXJ0aWZhY3RCYXNlVXJsID0gbmV3IFVSTChcbiAgICAgICAgYC9hcGkvdmlld2VyLWRlcml2YXRpdmVzLyR7cHJvamVjdElkLnZhbHVlfS8ke3Jlc291cmNlSXRlbS52ZXJzaW9uSWR9L2FydGlmYWN0c2AsXG4gICAgICAgIGFwaU9yaWdpblxuICAgICAgKS50b1N0cmluZygpXG4gICAgICBjb25zdCBsb2FkZXIgPSBuZXcgTGFyZ2VNb2RlbFN0cmVhbWluZ0xvYWRlcihcbiAgICAgICAgdmlld2VyLmdldFdvcmxkVHJlZSgpLFxuICAgICAgICBvYmplY3RVcmwsXG4gICAgICAgIGRlcml2YXRpdmUubWFuaWZlc3QsXG4gICAgICAgIGFydGlmYWN0QmFzZVVybCxcbiAgICAgICAgZWZmZWN0aXZlQXV0aFRva2VuLnZhbHVlIHx8IHVuZGVmaW5lZFxuICAgICAgKVxuICAgICAgbG9hZGVyLm9uKExvYWRlckV2ZW50LkxvYWRQcm9ncmVzcywgKGFyZ3MpID0+IHtcclxuICAgICAgICBjb25zb2xpZGF0ZVByb2dyZXNzVGhvcnR0bGVkKGFyZ3MpXHJcbiAgICAgIH0pXHJcbiAgICAgIGxvYWRlci5vbihMb2FkZXJFdmVudC5Mb2FkQ2FuY2VsbGVkLCAoaWQpID0+IHtcclxuICAgICAgICBkZWxldGUgbG9hZGluZ1Byb2dyZXNzTWFwW2lkXVxyXG4gICAgICAgIGNvbnNvbGlkYXRlUHJvZ3Jlc3NJbnRlcm5hbCh7IGlkLCBwcm9ncmVzczogMSB9KVxyXG4gICAgICB9KVxyXG4gICAgICBhd2FpdCB2aWV3ZXIubG9hZE9iamVjdChsb2FkZXIsIG9wdGlvbnM/Lnpvb21Ub09iamVjdClcbiAgICAgIGNvbnNvbGlkYXRlUHJvZ3Jlc3NJbnRlcm5hbCh7IGlkOiBvYmplY3RVcmwsIHByb2dyZXNzOiAxIH0pXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH1cblxyXG4gICAgY29uc29saWRhdGVQcm9ncmVzc0ludGVybmFsKHsgaWQ6IG9iamVjdElkLCBwcm9ncmVzczogMSB9KVxyXG4gICAgcmV0dXJuIHRydWVcclxuICB9XHJcblxyXG4gIGNvbnN0IGxvYWRPYmplY3QgPSBhc3luYyAoXHJcbiAgICBvYmplY3RJZDogc3RyaW5nLFxyXG4gICAgdW5sb2FkPzogYm9vbGVhbixcclxuICAgIG9wdGlvbnM/OiBQYXJ0aWFsPHsgem9vbVRvT2JqZWN0OiBib29sZWFuIH0+XHJcbiAgKSA9PiB7XHJcbiAgICBjb25zdCBvYmplY3RVcmwgPSBnZXRPYmplY3RVcmwocHJvamVjdElkLnZhbHVlLCBvYmplY3RJZClcclxuXHJcbiAgICBpZiAodW5sb2FkKSB7XHJcbiAgICAgIHJldHVybiB2aWV3ZXIudW5sb2FkT2JqZWN0KG9iamVjdFVybClcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGlmIChhd2FpdCBtYXliZUxvYWRWaWV3ZXJEZXJpdmF0aXZlKG9iamVjdElkLCBvcHRpb25zKSkgcmV0dXJuXHJcblxyXG4gICAgICBjb25zdCBsb2FkZXIgPSBuZXcgU3BlY2tsZUxvYWRlcihcclxuICAgICAgICB2aWV3ZXIuZ2V0V29ybGRUcmVlKCksXHJcbiAgICAgICAgb2JqZWN0VXJsLFxyXG4gICAgICAgIGVmZmVjdGl2ZUF1dGhUb2tlbi52YWx1ZSB8fCB1bmRlZmluZWQsXHJcbiAgICAgICAgZGlzYWJsZVZpZXdlckNhY2hlID8gZmFsc2UgOiB1bmRlZmluZWQsXHJcbiAgICAgICAgdW5kZWZpbmVkXHJcbiAgICAgIClcclxuXHJcbiAgICAgIGxvYWRlci5vbihMb2FkZXJFdmVudC5Mb2FkUHJvZ3Jlc3MsIChhcmdzKSA9PiB7XHJcbiAgICAgICAgY29uc29saWRhdGVQcm9ncmVzc1Rob3J0dGxlZChhcmdzKVxyXG4gICAgICB9KVxyXG4gICAgICBsb2FkZXIub24oTG9hZGVyRXZlbnQuTG9hZENhbmNlbGxlZCwgKGlkKSA9PiB7XHJcbiAgICAgICAgZGVsZXRlIGxvYWRpbmdQcm9ncmVzc01hcFtpZF1cclxuICAgICAgICBjb25zb2xpZGF0ZVByb2dyZXNzSW50ZXJuYWwoeyBpZCwgcHJvZ3Jlc3M6IDEgfSlcclxuICAgICAgfSlcclxuICAgICAgbG9hZGVyLm9uKExvYWRlckV2ZW50LkxvYWRXYXJuaW5nLCAoeyBtZXNzYWdlIH0pID0+IHtcclxuICAgICAgICBpZiAoIW1lc3NhZ2Uuc3RhcnRzV2l0aCgnVmlld2VyIGZ1bGwtbG9hZCBndWFyZDonKSkgcmV0dXJuXHJcblxyXG4gICAgICAgIHRyaWdnZXJOb3RpZmljYXRpb24oe1xyXG4gICAgICAgICAgdHlwZTogVG9hc3ROb3RpZmljYXRpb25UeXBlLkRhbmdlcixcclxuICAgICAgICAgIHRpdGxlOiAnTGFyZ2UgbW9kZWwgbmVlZHMgc3RyZWFtaW5nJyxcclxuICAgICAgICAgIGRlc2NyaXB0aW9uOiBtZXNzYWdlXHJcbiAgICAgICAgfSlcclxuICAgICAgfSlcclxuXHJcbiAgICAgIHJldHVybiB2aWV3ZXIubG9hZE9iamVjdChsb2FkZXIsIG9wdGlvbnM/Lnpvb21Ub09iamVjdClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IGdldFVuaXF1ZU9iamVjdElkcyA9IChyZXNvdXJjZUl0ZW1zOiBWaWV3ZXJSZXNvdXJjZUl0ZW1bXSkgPT5cclxuICAgIHVuaXEocmVzb3VyY2VJdGVtcy5tYXAoKGkpID0+IGkub2JqZWN0SWQpKVxyXG5cclxuICBjb25zdCBhY3RpdmVMb2FkcyA9IG5ldyBTZXQ8UHJvbWlzZTx2b2lkPj4oKVxyXG4gIHdhdGNoKFxyXG4gICAgKCkgPT4gPGNvbnN0PltyZXNvdXJjZUl0ZW1zLnZhbHVlLCBpc0luaXRpYWxpemVkLnZhbHVlLCBoYXNEb25lSW5pdGlhbExvYWQudmFsdWVdLFxyXG4gICAgYXN5bmMgKFtuZXdSZXNvdXJjZXMsIG5ld0lzSW5pdGlhbGl6ZWQsIG5ld0hhc0RvbmVJbml0aWFsTG9hZF0sIG9sZERhdGEpID0+IHtcclxuICAgICAgLy8gV2FpdCB0aWxsIHZpZXdlciBsb2FkZWQgaW5cclxuICAgICAgaWYgKCFuZXdJc0luaXRpYWxpemVkKSByZXR1cm5cclxuXHJcbiAgICAgIGNvbnN0IFtvbGRSZXNvdXJjZXNdID0gb2xkRGF0YSB8fCBbW10sIGZhbHNlXVxyXG5cclxuICAgICAgLy8gd2UgZG9udCB3YW50IHRvIHpvb20gdG8gb2JqZWN0LCBpZiB3ZSdyZSBsb2FkaW5nIHNwZWNpZmljIGNvb3JkcyBiZWNhdXNlIG9mIGEgdGhyZWFkLFxyXG4gICAgICAvLyBvciBzcG90bGlnaHQgbW9kZSBvciBhIHNhdmVkIHZpZXcgZXRjLlxyXG4gICAgICBjb25zdCBwcmV2ZW50Wm9vbWluZyA9XHJcbiAgICAgICAgZm9jdXNlZFRocmVhZElkLnZhbHVlIHx8XHJcbiAgICAgICAgc2F2ZWRWaWV3SWQudmFsdWUgfHxcclxuICAgICAgICBzYXZlZFZpZXcudmFsdWUgfHxcclxuICAgICAgICBzcG90bGlnaHRVc2VyU2Vzc2lvbklkLnZhbHVlXHJcbiAgICAgIGNvbnN0IHpvb21Ub09iamVjdCA9ICFwcmV2ZW50Wm9vbWluZ1xyXG5cclxuICAgICAgLy8gVmlld2VyIGluaXRpYWxpemVkIC0gbG9hZCBpbiBhbGwgcmVzb3VyY2VzXHJcbiAgICAgIGlmICghbmV3SGFzRG9uZUluaXRpYWxMb2FkKSB7XHJcbiAgICAgICAgY29uc3QgYWxsT2JqZWN0SWRzID0gZ2V0VW5pcXVlT2JqZWN0SWRzKG5ld1Jlc291cmNlcylcclxuICAgICAgICBpZiAoYWxsT2JqZWN0SWRzLmxlbmd0aCkge1xyXG4gICAgICAgICAgLy8gb25seSBtYXJrLCBpZiBhbnl0aGluZyB0byBsb2FkXHJcbiAgICAgICAgICBoYXNMb2FkZWRRdWV1ZWRVcE1vZGVscy52YWx1ZSA9IGZhbHNlXHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvKiogTG9hZCBzZXF1ZW50aWFsbHkgKi9cclxuICAgICAgICBjb25zdCByZXMgPSBbXVxyXG4gICAgICAgIGNvbnN0IGxvYWRBbGwgPSBhc3luYyAoKSA9PiB7XHJcbiAgICAgICAgICBmb3IgKGNvbnN0IGkgb2YgYWxsT2JqZWN0SWRzKSB7XHJcbiAgICAgICAgICAgIHJlcy5wdXNoKGF3YWl0IGxvYWRPYmplY3QoaSwgZmFsc2UsIHsgem9vbVRvT2JqZWN0IH0pKVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gUmVnaXN0ZXIgZm9yIGFjY3VyYXRlICdpcyBhbnl0aGluZyBsb2FkaW5nJyByZXBvcnRpbmdcclxuICAgICAgICBjb25zdCBwcm9taXNlID0gbG9hZEFsbCgpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgYWN0aXZlTG9hZHMuZGVsZXRlKHByb21pc2UpXHJcbiAgICAgICAgfSlcclxuICAgICAgICBhY3RpdmVMb2Fkcy5hZGQocHJvbWlzZSlcclxuICAgICAgICBhd2FpdCBwcm9taXNlXHJcblxyXG4gICAgICAgIGlmIChyZXMubGVuZ3RoKSB7XHJcbiAgICAgICAgICBoYXNEb25lSW5pdGlhbExvYWQudmFsdWUgPSB0cnVlXHJcbiAgICAgICAgICBpZiAoIWFjdGl2ZUxvYWRzLnNpemUpIGhhc0xvYWRlZFF1ZXVlZFVwTW9kZWxzLnZhbHVlID0gdHJ1ZVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFJlc291cmNlcyBjaGFuZ2VkP1xyXG4gICAgICBjb25zdCBsb2FkQW5kVW5sb2FkQ2hhbmdlZCA9IGFzeW5jICgpID0+IHtcclxuICAgICAgICBjb25zdCBuZXdPYmplY3RJZHMgPSBnZXRVbmlxdWVPYmplY3RJZHMobmV3UmVzb3VyY2VzKVxyXG4gICAgICAgIGNvbnN0IG9sZE9iamVjdElkcyA9IGdldFVuaXF1ZU9iamVjdElkcyhvbGRSZXNvdXJjZXMpXHJcbiAgICAgICAgY29uc3QgcmVtb3ZhYmxlT2JqZWN0SWRzID0gZGlmZmVyZW5jZShvbGRPYmplY3RJZHMsIG5ld09iamVjdElkcylcclxuICAgICAgICBjb25zdCBhZGRhYmxlT2JqZWN0SWRzID0gZGlmZmVyZW5jZShuZXdPYmplY3RJZHMsIG9sZE9iamVjdElkcylcclxuXHJcbiAgICAgICAgaWYgKGFkZGFibGVPYmplY3RJZHMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAvLyBvbmx5IG1hcmssIGlmIGFueXRoaW5nIHRvIGxvYWRcclxuICAgICAgICAgIGhhc0xvYWRlZFF1ZXVlZFVwTW9kZWxzLnZhbHVlID0gZmFsc2VcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHJlbW92YWJsZU9iamVjdElkcy5tYXAoKGkpID0+IGxvYWRPYmplY3QoaSwgdHJ1ZSkpKVxyXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICAgICAgYWRkYWJsZU9iamVjdElkcy5tYXAoKGkpID0+IGxvYWRPYmplY3QoaSwgZmFsc2UsIHsgem9vbVRvT2JqZWN0OiBmYWxzZSB9KSlcclxuICAgICAgICApXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIC8vIFJlZ2lzdGVyIGZvciBhY2N1cmF0ZSAnaXMgYW55dGhpbmcgbG9hZGluZycgcmVwb3J0aW5nXHJcbiAgICAgIGNvbnN0IHByb21pc2UgPSBsb2FkQW5kVW5sb2FkQ2hhbmdlZCgpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgIGFjdGl2ZUxvYWRzLmRlbGV0ZShwcm9taXNlKVxyXG4gICAgICB9KVxyXG4gICAgICBhY3RpdmVMb2Fkcy5hZGQocHJvbWlzZSlcclxuICAgICAgYXdhaXQgcHJvbWlzZVxyXG5cclxuICAgICAgaWYgKCFhY3RpdmVMb2Fkcy5zaXplKSBoYXNMb2FkZWRRdWV1ZWRVcE1vZGVscy52YWx1ZSA9IHRydWVcclxuICAgIH0sXHJcbiAgICB7IGRlZXA6IHRydWUsIGltbWVkaWF0ZTogdHJ1ZSB9XHJcbiAgKVxyXG5cclxuICBvbkJlZm9yZVVubW91bnQoYXN5bmMgKCkgPT4ge1xyXG4gICAgYXdhaXQgdmlld2VyLnVubG9hZEFsbCgpXHJcbiAgfSlcclxufVxyXG5cclxuLyoqXHJcbiAqIEhlcmUgd2UgbWFrZSB0aGUgdmlld2VyIHByZXRlbmQgaXQncyBhIGNvbm5lY3RvciBhbmQgc2VuZCBvdXQgcmVjZWl2ZSBldmVudHMuIE5vdGUsIHRoaXMgaXMgaW1wb3J0YW50IGZvciB1cyB0byB0cmFjayB0byBiZSBhYmxlIHRvIGdldCBhIHBpY3R1cmUgb2YgaG93IG11Y2ggZGF0YSBpcyBjb25zdW1lZFxyXG4gKiBpbiBvdXIgdmlld2VyLlxyXG4gKi9cclxuZnVuY3Rpb24gdXNlVmlld2VyUmVjZWl2ZVRyYWNraW5nKCkge1xyXG4gIC8vXHJcbiAgY29uc3Qge1xyXG4gICAgcmVzb3VyY2VzOiB7XHJcbiAgICAgIHJlc3BvbnNlOiB7IG1vZGVsc0FuZFZlcnNpb25JZHMgfVxyXG4gICAgfVxyXG4gIH0gPSB1c2VJbmplY3RlZFZpZXdlclN0YXRlKClcclxuICBjb25zdCBtaXhwYW5lbCA9IHVzZU1peHBhbmVsKClcclxuICBjb25zdCB7IHVzZXJJZCB9ID0gdXNlQWN0aXZlVXNlcigpXHJcbiAgY29uc3QgcmVjZWl2ZWRWZXJzaW9ucyA9IG5ldyBTZXQ8c3RyaW5nPigpXHJcbiAgd2F0Y2gobW9kZWxzQW5kVmVyc2lvbklkcywgKG5ld1ZhbCkgPT4ge1xyXG4gICAgZm9yIChjb25zdCB7IG1vZGVsLCB2ZXJzaW9uSWQgfSBvZiBuZXdWYWwpIHtcclxuICAgICAgaWYgKHJlY2VpdmVkVmVyc2lvbnMuaGFzKHZlcnNpb25JZCkpIHtcclxuICAgICAgICBjb250aW51ZVxyXG4gICAgICB9XHJcbiAgICAgIHJlY2VpdmVkVmVyc2lvbnMuYWRkKHZlcnNpb25JZClcclxuICAgICAgbWl4cGFuZWwudHJhY2soJ1JlY2VpdmUnLCB7XHJcbiAgICAgICAgaG9zdEFwcDogJ3ZpZXdlcicsXHJcbiAgICAgICAgc291cmNlSG9zdEFwcDogbW9kZWwubG9hZGVkVmVyc2lvbi5pdGVtc1swXS5zb3VyY2VBcHBsaWNhdGlvbixcclxuICAgICAgICBpc011bHRpcGxheWVyOiBtb2RlbC5sb2FkZWRWZXJzaW9uLml0ZW1zWzBdLmF1dGhvclVzZXI/LmlkICE9PSB1c2VySWQudmFsdWVcclxuICAgICAgfSlcclxuICAgIH1cclxuICB9KVxyXG59XHJcblxyXG4vKipcclxuICogTGlzdGVuaW5nIHRvIG1vZGVsL3ZlcnNpb24gdXBkYXRlcyB0aHJvdWdoIHN1YnNjcmlwdGlvbnMgYW5kIG1ha2luZyB2YXJpb3VzXHJcbiAqIGNhY2hlIHVwZGF0ZXMgc28gdGhhdCB3ZSBkb24ndCBuZWVkIHRvIGFsd2F5cyByZWZldGNoIHF1ZXJpZXNcclxuICovXHJcbmZ1bmN0aW9uIHVzZVZpZXdlclN1YnNjcmlwdGlvbkV2ZW50VHJhY2tlcigpIHtcclxuICBpZiAoaW1wb3J0Lm1ldGEuc2VydmVyKSByZXR1cm5cclxuXHJcbiAgY29uc3Qge1xyXG4gICAgcHJvamVjdElkLFxyXG4gICAgcmVzb3VyY2VzOiB7XHJcbiAgICAgIHJlcXVlc3Q6IHsgcmVzb3VyY2VJZFN0cmluZywgdGhyZWFkRmlsdGVycyB9XHJcbiAgICB9XHJcbiAgfSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG5cclxuICAvLyBUcmFjayBhbGwgcHJvamVjdC9tb2RlbC92ZXJzaW9uIHVwZGF0ZXNcclxuICB1c2VHZW5lcmFsUHJvamVjdFBhZ2VVcGRhdGVUcmFja2luZyh7XHJcbiAgICBwcm9qZWN0SWRcclxuICB9KVxyXG5cclxuICAvLyBUcmFjayBzYXZlZCB2aWV3c1xyXG4gIHVzZVByb2plY3RTYXZlZFZpZXdzVXBkYXRlVHJhY2tpbmcoeyBwcm9qZWN0SWQgfSlcclxuXHJcbiAgLy8gQWxzbyB0cmFjayB1cGRhdGVzIHRvIGNvbW1lbnRzXHJcbiAgdXNlVmlld2VyQ29tbWVudFVwZGF0ZVRyYWNraW5nKFxyXG4gICAge1xyXG4gICAgICBwcm9qZWN0SWQsXHJcbiAgICAgIHJlc291cmNlSWRTdHJpbmcsXHJcbiAgICAgIGxvYWRlZFZlcnNpb25zT25seTogY29tcHV0ZWQoKCkgPT4gdGhyZWFkRmlsdGVycy52YWx1ZS5sb2FkZWRWZXJzaW9uc09ubHkpXHJcbiAgICB9LFxyXG4gICAgKGV2ZW50LCBjYWNoZSkgPT4ge1xyXG4gICAgICBjb25zdCBpc0FyY2hpdmVkID0gZXZlbnQudHlwZSA9PT0gUHJvamVjdENvbW1lbnRzVXBkYXRlZE1lc3NhZ2VUeXBlLkFyY2hpdmVkXHJcbiAgICAgIGNvbnN0IGlzTmV3ID0gZXZlbnQudHlwZSA9PT0gUHJvamVjdENvbW1lbnRzVXBkYXRlZE1lc3NhZ2VUeXBlLkNyZWF0ZWRcclxuICAgICAgY29uc3QgY29tbWVudCA9IGV2ZW50LmNvbW1lbnRcclxuXHJcbiAgICAgIGlmIChpc0FyY2hpdmVkKSB7XHJcbiAgICAgICAgLy8gTWFyayBhcyBhcmNoaXZlZFxyXG4gICAgICAgIGNhY2hlLm1vZGlmeSh7XHJcbiAgICAgICAgICBpZDogZ2V0Q2FjaGVJZCgnQ29tbWVudCcsIGV2ZW50LmlkKSxcclxuICAgICAgICAgIGZpZWxkczoge1xyXG4gICAgICAgICAgICBhcmNoaXZlZDogKCkgPT4gdHJ1ZVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0pXHJcblxyXG4gICAgICAgIC8vIFJlbW92ZSBmcm9tIHByb2plY3QuY29tbWVudFRocmVhZHNcclxuICAgICAgICBtb2RpZnlPYmplY3RGaWVsZChcclxuICAgICAgICAgIGNhY2hlLFxyXG4gICAgICAgICAgZ2V0Q2FjaGVJZCgnUHJvamVjdCcsIHByb2plY3RJZC52YWx1ZSksXHJcbiAgICAgICAgICAnY29tbWVudFRocmVhZHMnLFxyXG4gICAgICAgICAgKHsgdmFyaWFibGVzLCBoZWxwZXJzOiB7IGNyZWF0ZVVwZGF0ZWRWYWx1ZSwgcmVhZEZpZWxkIH0gfSkgPT4ge1xyXG4gICAgICAgICAgICBpZiAodmFyaWFibGVzLmZpbHRlcj8uaW5jbHVkZUFyY2hpdmVkKSByZXR1cm4gLy8gd2Ugd2FudCBpdCBpbiB0aGF0IGxpc3RcclxuXHJcbiAgICAgICAgICAgIHJldHVybiBjcmVhdGVVcGRhdGVkVmFsdWUoKHsgdXBkYXRlIH0pID0+IHtcclxuICAgICAgICAgICAgICB1cGRhdGUoJ3RvdGFsQ291bnQnLCAodG90YWxDb3VudCkgPT4gdG90YWxDb3VudCAtIDEpXHJcbiAgICAgICAgICAgICAgdXBkYXRlKCdpdGVtcycsIChpdGVtcykgPT5cclxuICAgICAgICAgICAgICAgIGl0ZW1zLmZpbHRlcigoaSkgPT4gcmVhZEZpZWxkKGksICdpZCcpICE9PSBldmVudC5pZClcclxuICAgICAgICAgICAgICApXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgKVxyXG4gICAgICB9IGVsc2UgaWYgKGlzTmV3ICYmIGNvbW1lbnQpIHtcclxuICAgICAgICBjb25zdCBwYXJlbnRJZCA9IGNvbW1lbnQucGFyZW50Py5pZFxyXG5cclxuICAgICAgICAvLyBBZGQgcmVwbHkgdG8gcGFyZW50XHJcbiAgICAgICAgaWYgKHBhcmVudElkKSB7XHJcbiAgICAgICAgICBtb2RpZnlPYmplY3RGaWVsZChcclxuICAgICAgICAgICAgY2FjaGUsXHJcbiAgICAgICAgICAgIGdldENhY2hlSWQoJ0NvbW1lbnQnLCBwYXJlbnRJZCksXHJcbiAgICAgICAgICAgICdyZXBsaWVzJyxcclxuICAgICAgICAgICAgKHsgaGVscGVyczogeyBjcmVhdGVVcGRhdGVkVmFsdWUsIHJlZiB9IH0pID0+XHJcbiAgICAgICAgICAgICAgY3JlYXRlVXBkYXRlZFZhbHVlKCh7IHVwZGF0ZSB9KSA9PiB7XHJcbiAgICAgICAgICAgICAgICB1cGRhdGUoJ3RvdGFsQ291bnQnLCAodG90YWxDb3VudCkgPT4gdG90YWxDb3VudCArIDEpXHJcbiAgICAgICAgICAgICAgICB1cGRhdGUoJ2l0ZW1zJywgKGl0ZW1zKSA9PiBbcmVmKCdDb21tZW50JywgY29tbWVudC5pZCksIC4uLml0ZW1zXSlcclxuICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgKVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAvLyBBZGQgY29tbWVudCB0aHJlYWRcclxuICAgICAgICAgIG1vZGlmeU9iamVjdEZpZWxkKFxyXG4gICAgICAgICAgICBjYWNoZSxcclxuICAgICAgICAgICAgZ2V0Q2FjaGVJZCgnUHJvamVjdCcsIHByb2plY3RJZC52YWx1ZSksXHJcbiAgICAgICAgICAgICdjb21tZW50VGhyZWFkcycsXHJcbiAgICAgICAgICAgICh7IGhlbHBlcnM6IHsgcmVmLCBjcmVhdGVVcGRhdGVkVmFsdWUsIHJlYWRGaWVsZCB9LCB2YWx1ZSB9KSA9PiB7XHJcbiAgICAgICAgICAgICAgLy8gSW4gY2FzZSB0aGlzIGlzIGFjdHVhbGx5IGFuIHVuYXJjaGl2ZWQgY29tbWVudCwgd2Ugb25seSB3YW50IHRvIGFkZCBpdCBpZiBpdCBkb2VzbnRcclxuICAgICAgICAgICAgICAvLyBleGlzdCBpbiB0aGUgaW5jbHVkZXNBcmNoaXZlZCBsaXN0IGFscmVhZHlcclxuICAgICAgICAgICAgICBjb25zdCBpbmNsdWRlc0l0ZW0gPSB2YWx1ZS5pdGVtcz8uZmluZChcclxuICAgICAgICAgICAgICAgIChpKSA9PiByZWFkRmllbGQoaSwgJ2lkJykgPT09IGNvbW1lbnQuaWRcclxuICAgICAgICAgICAgICApXHJcbiAgICAgICAgICAgICAgaWYgKGluY2x1ZGVzSXRlbSkgcmV0dXJuXHJcblxyXG4gICAgICAgICAgICAgIHJldHVybiBjcmVhdGVVcGRhdGVkVmFsdWUoKHsgdXBkYXRlIH0pID0+IHtcclxuICAgICAgICAgICAgICAgIHVwZGF0ZSgndG90YWxDb3VudCcsICh0b3RhbENvdW50KSA9PiB0b3RhbENvdW50ICsgMSlcclxuICAgICAgICAgICAgICAgIHVwZGF0ZSgnaXRlbXMnLCAoaXRlbXMpID0+IFtyZWYoJ0NvbW1lbnQnLCBjb21tZW50LmlkKSwgLi4uaXRlbXNdKVxyXG4gICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIClcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuICApXHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVzZVZpZXdlclNlY3Rpb25Cb3hJbnRlZ3JhdGlvbigpIHtcclxuICBjb25zdCB7XHJcbiAgICB1aToge1xyXG4gICAgICBzZWN0aW9uQm94LFxyXG4gICAgICBzZWN0aW9uQm94Q29udGV4dDogeyB2aXNpYmxlLCBlZGl0ZWQgfVxyXG4gICAgfSxcclxuICAgIHZpZXdlcjogeyBpbnN0YW5jZSB9XHJcbiAgfSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG5cclxuICBjb25zdCB7IHNlY3Rpb25Cb3hEYXRhVG9Cb3gzLCBzZWN0aW9uQm94RGF0YUVxdWFscyB9ID0gdXNlU2VjdGlvbkJveFV0aWxpdGllcygpXHJcblxyXG4gIC8vIENoYW5nZSBlZGl0ZWQ9dHJ1ZSB3aGVuIHVzZXIgc3RhcnRzIGNoYW5naW5nIHRoZSBzZWN0aW9uIGJveCBieSBkcmFnZ2luZyBpdFxyXG4gIGNvbnN0IHNlY3Rpb25Ub29sID0gaW5zdGFuY2UuZ2V0RXh0ZW5zaW9uKFNlY3Rpb25Ub29sKVxyXG4gIGNvbnN0IG9uRHJhZ1N0YXJ0ID0gKCkgPT4ge1xyXG4gICAgZWRpdGVkLnZhbHVlID0gdHJ1ZVxyXG4gIH1cclxuICBzZWN0aW9uVG9vbC5vbihTZWN0aW9uVG9vbEV2ZW50LkRyYWdTdGFydCwgb25EcmFnU3RhcnQpXHJcblxyXG4gIC8vIE5vIHR3by13YXkgc3luYyBmb3Igc2VjdGlvbiBib3hlcywgYmVjYXVzZSBvbmNlIHlvdSBzZXQgYSBCb3gzIGludG8gdGhlIHZpZXdlclxyXG4gIC8vIHRoZSB2aWV3ZXIgdHJhbnNmb3JtcyBpdCBpbnRvIHNvbWV0aGluZyBlbHNlIGNhdXNpbmcgdGhlIHVwZGF0ZXMgZ29pbmcgaW50byBhbiBpbmZpbml0ZSBsb29wXHJcblxyXG4gIC8vIHN0YXRlIC0+IHZpZXdlclxyXG4gIHdhdGNoKFxyXG4gICAgc2VjdGlvbkJveCxcclxuICAgIChuZXdWYWwsIG9sZFZhbCkgPT4ge1xyXG4gICAgICBpZiAobmV3VmFsICYmIG9sZFZhbCAmJiBzZWN0aW9uQm94RGF0YUVxdWFscyhuZXdWYWwsIG9sZFZhbCkpIHJldHVyblxyXG4gICAgICBpZiAoIW5ld1ZhbCAmJiAhb2xkVmFsKSByZXR1cm5cclxuXHJcbiAgICAgIGlmIChvbGRWYWwgJiYgIW5ld1ZhbCkge1xyXG4gICAgICAgIHZpc2libGUudmFsdWUgPSBmYWxzZVxyXG4gICAgICAgIGVkaXRlZC52YWx1ZSA9IGZhbHNlXHJcblxyXG4gICAgICAgIHNlY3Rpb25Ub29sLmVuYWJsZWQgPSBmYWxzZVxyXG4gICAgICAgIGluc3RhbmNlLnJlcXVlc3RSZW5kZXIoVXBkYXRlRmxhZ3MuUkVOREVSX1JFU0VUKVxyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAobmV3VmFsICYmICghb2xkVmFsIHx8ICFzZWN0aW9uQm94RGF0YUVxdWFscyhuZXdWYWwsIG9sZFZhbCkpKSB7XHJcbiAgICAgICAgdmlzaWJsZS52YWx1ZSA9IHRydWVcclxuICAgICAgICBlZGl0ZWQudmFsdWUgPSBmYWxzZVxyXG5cclxuICAgICAgICBjb25zdCBib3gzID0gc2VjdGlvbkJveERhdGFUb0JveDMobmV3VmFsKVxyXG4gICAgICAgIHNlY3Rpb25Ub29sLnNldEJveChib3gzKVxyXG4gICAgICAgIHNlY3Rpb25Ub29sLmVuYWJsZWQgPSB0cnVlXHJcbiAgICAgICAgY29uc3Qgb3V0bGluZXMgPSBpbnN0YW5jZS5nZXRFeHRlbnNpb24oU2VjdGlvbk91dGxpbmVzKVxyXG4gICAgICAgIGlmIChvdXRsaW5lcykgb3V0bGluZXMucmVxdWVzdFVwZGF0ZSgpXHJcbiAgICAgICAgaW5zdGFuY2UucmVxdWVzdFJlbmRlcihVcGRhdGVGbGFncy5SRU5ERVJfUkVTRVQpXHJcbiAgICAgIH1cclxuICAgIH0sXHJcbiAgICB7IGltbWVkaWF0ZTogdHJ1ZSwgZGVlcDogdHJ1ZSwgZmx1c2g6ICdzeW5jJyB9XHJcbiAgKVxyXG5cclxuICB3YXRjaChcclxuICAgIHZpc2libGUsXHJcbiAgICAobmV3VmFsLCBvbGRWYWwpID0+IHtcclxuICAgICAgaWYgKG5ld1ZhbCAmJiBvbGRWYWwpIHJldHVyblxyXG4gICAgICBpZiAoIW5ld1ZhbCAmJiAhb2xkVmFsKSByZXR1cm5cclxuXHJcbiAgICAgIGlmIChuZXdWYWwpIHtcclxuICAgICAgICBzZWN0aW9uVG9vbC52aXNpYmxlID0gdHJ1ZVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHNlY3Rpb25Ub29sLnZpc2libGUgPSBmYWxzZVxyXG4gICAgICB9XHJcbiAgICAgIGluc3RhbmNlLnJlcXVlc3RSZW5kZXIoKVxyXG4gICAgfSxcclxuICAgIHsgaW1tZWRpYXRlOiB0cnVlLCBkZWVwOiB0cnVlLCBmbHVzaDogJ3N5bmMnIH1cclxuICApXHJcblxyXG4gIG9uQmVmb3JlVW5tb3VudCgoKSA9PiB7XHJcbiAgICBzZWN0aW9uVG9vbC5lbmFibGVkID0gZmFsc2VcclxuICAgIHNlY3Rpb25Ub29sLnJlbW92ZUxpc3RlbmVyKFNlY3Rpb25Ub29sRXZlbnQuRHJhZ1N0YXJ0LCBvbkRyYWdTdGFydClcclxuICB9KVxyXG59XHJcblxyXG5mdW5jdGlvbiB1c2VWaWV3ZXJDYW1lcmFJbnRlZ3JhdGlvbigpIHtcclxuICBjb25zdCB7XHJcbiAgICB2aWV3ZXI6IHsgaW5zdGFuY2UgfSxcclxuICAgIHVpOiB7XHJcbiAgICAgIGNhbWVyYTogeyBpc09ydGhvUHJvamVjdGlvbiwgcG9zaXRpb24sIHRhcmdldCB9LFxyXG4gICAgICBzcG90bGlnaHRVc2VyU2Vzc2lvbklkXHJcbiAgICB9XHJcbiAgfSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG4gIGNvbnN0IHsgZm9yY2VWaWV3VG9WaWV3ZXJTeW5jLCBzZXRWaWV3LCBjYW1lcmFDb250cm9sbGVyIH0gPSB1c2VDYW1lcmFVdGlsaXRpZXMoKVxyXG5cclxuICBjb25zdCBoYXNJbml0aWFsTG9hZEZpcmVkID0gcmVmKGZhbHNlKVxyXG5cclxuICBjb25zdCBsb2FkQ2FtZXJhRGF0YUZyb21WaWV3ZXIgPSAoKSA9PiB7XHJcbiAgICBjb25zdCBleHRlbnNpb246IENhbWVyYUNvbnRyb2xsZXIgPSBpbnN0YW5jZS5nZXRFeHRlbnNpb24oQ2FtZXJhQ29udHJvbGxlcilcclxuXHJcbiAgICBjb25zdCB2aWV3ZXJQb3MgPSBuZXcgVmVjdG9yMygpLmNvcHkoZXh0ZW5zaW9uLmdldFBvc2l0aW9uKCkpXHJcbiAgICBjb25zdCB2aWV3ZXJUYXJnZXQgPSBuZXcgVmVjdG9yMygpLmNvcHkoZXh0ZW5zaW9uLmdldFRhcmdldCgpKVxyXG5cclxuICAgIGlmIChoYXNJbml0aWFsTG9hZEZpcmVkLnZhbHVlKSB7XHJcbiAgICAgIGlmICghYXJlVmVjdG9yc0xvb3NlbHlFcXVhbChwb3NpdGlvbi52YWx1ZSwgdmlld2VyUG9zKSkge1xyXG4gICAgICAgIHBvc2l0aW9uLnZhbHVlID0gdmlld2VyUG9zLmNsb25lKClcclxuICAgICAgfVxyXG4gICAgICBpZiAoIWFyZVZlY3RvcnNMb29zZWx5RXF1YWwodGFyZ2V0LnZhbHVlLCB2aWV3ZXJUYXJnZXQpKSB7XHJcbiAgICAgICAgdGFyZ2V0LnZhbHVlID0gdmlld2VyVGFyZ2V0LmNsb25lKClcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLy8gdmlld2VyIC0+IHN0YXRlXHJcbiAgLy8gZGVib3VuY2luZyBwb3MvdGFyZ2V0IHVwZGF0ZXMgdG8gYXZvaWQgaml0dGVyaW5lc3MgKyBzcG90bGlnaHQgbW9kZSB1bm5lY2Vzc2FyaWx5IGRpc2FibGluZ1xyXG4gIHVzZVZpZXdlckNhbWVyYVRyYWNrZXIoXHJcbiAgICAoKSA9PiB7XHJcbiAgICAgIGxvYWRDYW1lcmFEYXRhRnJvbVZpZXdlcigpXHJcbiAgICB9LFxyXG4gICAgeyB0aHJvdHRsZVdhaXQ6IDEwMCB9XHJcbiAgKVxyXG5cclxuICB1c2VPblZpZXdlckxvYWRDb21wbGV0ZSgoeyBpc0luaXRpYWwgfSkgPT4ge1xyXG4gICAgaWYgKGlzSW5pdGlhbCkge1xyXG4gICAgICBoYXNJbml0aWFsTG9hZEZpcmVkLnZhbHVlID0gdHJ1ZVxyXG5cclxuICAgICAgLy8gTG9hZCBjYW1lcmEgcG9zaXRpb24gc28gd2UgY2FuIHJldHVybiB0byBpdCBjb3JyZWN0bHlcclxuICAgICAgLy8gT05MWSBpZiB3ZSBkb24ndCBhbHJlYWR5IGhhdmUgc3BlY2lmaWMgY29vcmRpbmF0ZXMgKGUuZy4gZnJvbSBvcGVuZWQgdGhyZWFkKVxyXG4gICAgICAvLyBvdGhlcndpc2UgLSBsb2FkIGN1cnJlbnQgcG9zL3RhcmdldCBpbnRvIHZpZXdlclxyXG4gICAgICBjb25zdCBoYXNJbml0Q29vcmRzID1cclxuICAgICAgICBwb3NpdGlvbi52YWx1ZS5lcXVhbHMobmV3IFZlY3RvcjMoKSkgJiYgdGFyZ2V0LnZhbHVlLmVxdWFscyhuZXcgVmVjdG9yMygpKVxyXG4gICAgICBpZiAoaGFzSW5pdENvb3Jkcykge1xyXG4gICAgICAgIGxvYWRDYW1lcmFEYXRhRnJvbVZpZXdlcigpXHJcbiAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZm9yY2VWaWV3VG9WaWV3ZXJTeW5jKClcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gT25seSBub3cgc2V0IHByb2plY3Rpb24sIHdlIGNhbid0IGRvIGl0IHRvbyBlYXJseVxyXG4gICAgICBvcnRob1Byb2plY3Rpb25VcGRhdGUoaXNPcnRob1Byb2plY3Rpb24udmFsdWUpXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBsb2FkQ2FtZXJhRGF0YUZyb21WaWV3ZXIoKVxyXG4gICAgfVxyXG4gIH0pXHJcblxyXG4gIHVzZVZpZXdlckNhbWVyYUNvbnRyb2xTdGFydFRyYWNrZXIoKCkgPT4ge1xyXG4gICAgaWYgKHNwb3RsaWdodFVzZXJTZXNzaW9uSWQudmFsdWUpIHtcclxuICAgICAgc3BvdGxpZ2h0VXNlclNlc3Npb25JZC52YWx1ZSA9IG51bGwgLy8gY2FuY2VsXHJcbiAgICB9XHJcbiAgfSlcclxuXHJcbiAgY29uc3Qgb3J0aG9Qcm9qZWN0aW9uVXBkYXRlID0gKG5ld1ZhbDogYm9vbGVhbikgPT4ge1xyXG4gICAgaWYgKCFoYXNJbml0aWFsTG9hZEZpcmVkLnZhbHVlKSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcignQXR0ZW1wdGluZyB0byBzZXQgcHJvamVjdGlvbiB0b28gZWFybHknKVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChuZXdWYWwpIHtcclxuICAgICAgY2FtZXJhQ29udHJvbGxlci5zZXRPcnRob0NhbWVyYU9uKClcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNhbWVyYUNvbnRyb2xsZXIuc2V0UGVyc3BlY3RpdmVDYW1lcmFPbigpXHJcbiAgICB9XHJcblxyXG4gICAgLy8gcmVzZXQgY2FtZXJhIHBvcywgY2F1c2Ugd2UndmUgc3dpdGNoZWQgY2FtZXJhcyBub3cgYW5kIGl0IG1pZ2h0IG5vdCBoYXZlIHRoZSBuZXcgb25lc1xyXG4gICAgZm9yY2VWaWV3VG9WaWV3ZXJTeW5jKClcclxuICB9XHJcblxyXG4gIC8vIHN0YXRlIC0+IHZpZXdlclxyXG4gIHdhdGNoKFxyXG4gICAgaXNPcnRob1Byb2plY3Rpb24sXHJcbiAgICAobmV3VmFsLCBvbGRWYWwpID0+IHtcclxuICAgICAgaWYgKG5ld1ZhbCA9PT0gb2xkVmFsIHx8ICFoYXNJbml0aWFsTG9hZEZpcmVkLnZhbHVlKSByZXR1cm5cclxuICAgICAgb3J0aG9Qcm9qZWN0aW9uVXBkYXRlKG5ld1ZhbClcclxuICAgIH0sXHJcbiAgICB7IGltbWVkaWF0ZTogdHJ1ZSB9XHJcbiAgKVxyXG5cclxuICB3YXRjaChcclxuICAgIHBvc2l0aW9uLFxyXG4gICAgKG5ld1ZhbCwgb2xkVmFsKSA9PiB7XHJcbiAgICAgIGlmICgoIW5ld1ZhbCAmJiAhb2xkVmFsKSB8fCAob2xkVmFsICYmIGFyZVZlY3RvcnNMb29zZWx5RXF1YWwobmV3VmFsLCBvbGRWYWwpKSkge1xyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcbiAgICAgIHNldFZpZXcoe1xyXG4gICAgICAgIHBvc2l0aW9uOiBuZXdWYWwsXHJcbiAgICAgICAgdGFyZ2V0OiB0YXJnZXQudmFsdWVcclxuICAgICAgfSlcclxuICAgIH1cclxuICAgIC8vIHsgaW1tZWRpYXRlOiB0cnVlIH1cclxuICApXHJcblxyXG4gIHdhdGNoKFxyXG4gICAgdGFyZ2V0LFxyXG4gICAgKG5ld1ZhbCwgb2xkVmFsKSA9PiB7XHJcbiAgICAgIGlmICgoIW5ld1ZhbCAmJiAhb2xkVmFsKSB8fCAob2xkVmFsICYmIGFyZVZlY3RvcnNMb29zZWx5RXF1YWwobmV3VmFsLCBvbGRWYWwpKSkge1xyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICBzZXRWaWV3KHtcclxuICAgICAgICBwb3NpdGlvbjogcG9zaXRpb24udmFsdWUsXHJcbiAgICAgICAgdGFyZ2V0OiBuZXdWYWxcclxuICAgICAgfSlcclxuICAgIH1cclxuICAgIC8vIHsgaW1tZWRpYXRlOiB0cnVlIH1cclxuICApXHJcbn1cclxuXHJcbmZ1bmN0aW9uIHVzZVZpZXdlckZpbHRlcnNJbnRlZ3JhdGlvbigpIHtcclxuICBjb25zdCBzdGF0ZSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG4gIGNvbnN0IHtcclxuICAgIHZpZXdlcjogeyBpbnN0YW5jZSB9LFxyXG4gICAgdWk6IHsgZmlsdGVycyB9XHJcbiAgfSA9IHN0YXRlXHJcblxyXG4gIHVzZUZpbHRlcmluZ1NldHVwKClcclxuICB1c2VGaWx0ZXJVdGlsaXRpZXMoeyBzdGF0ZSB9KVxyXG5cclxuICB3YXRjaChcclxuICAgIGZpbHRlcnMuc2VsZWN0ZWRPYmplY3RzLFxyXG4gICAgKG5ld1ZhbCwgb2xkVmFsKSA9PiB7XHJcbiAgICAgIGNvbnN0IG5ld0lkcyA9IGZsYXR0ZW4oXG4gICAgICAgIG5ld1ZhbC5tYXAoKHYpID0+IGdldFRhcmdldE9iamVjdElkcyh2IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSlcbiAgICAgICkuZmlsdGVyKGlzTm9uTnVsbGFibGUpXG4gICAgICBjb25zdCBvbGRJZHMgPSBmbGF0dGVuKFxuICAgICAgICAob2xkVmFsIHx8IFtdKS5tYXAoKHYpID0+IGdldFRhcmdldE9iamVjdElkcyh2IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSlcbiAgICAgICkuZmlsdGVyKGlzTm9uTnVsbGFibGUpXG4gICAgICBpZiAoYXJyYXlzRXF1YWwobmV3SWRzLCBvbGRJZHMpKSByZXR1cm5cclxuXHJcbiAgICAgIGNvbnN0IHNlbGVjdGlvbkV4dGVuc2lvbiA9IGluc3RhbmNlLmdldEV4dGVuc2lvbihTZWxlY3Rpb25FeHRlbnNpb24pXHJcbiAgICAgIGNvbnN0IGN1cnJlbnRWaWV3ZXJTZWxlY3Rpb24gPSBzZWxlY3Rpb25FeHRlbnNpb25cclxuICAgICAgICAuZ2V0U2VsZWN0ZWRPYmplY3RzKClcclxuICAgICAgICAubWFwKChvYmopID0+IG9iai5pZCBhcyBzdHJpbmcpXHJcblxyXG4gICAgICBpZiAoXHJcbiAgICAgICAgY3VycmVudFZpZXdlclNlbGVjdGlvbi5sZW5ndGggPT09IG5ld0lkcy5sZW5ndGggJiZcclxuICAgICAgICBkaWZmZXJlbmNlKGN1cnJlbnRWaWV3ZXJTZWxlY3Rpb24sIG5ld0lkcykubGVuZ3RoID09PSAwXHJcbiAgICAgICkge1xyXG4gICAgICAgIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICBzdGF0ZS51aS5oaWdobGlnaHRlZE9iamVjdElkcy52YWx1ZSA9IFtdXHJcbiAgICAgIGNvbnN0IGhpZ2hsaWdodEV4dGVuc2lvbiA9IGluc3RhbmNlLmdldEV4dGVuc2lvbihIaWdobGlnaHRFeHRlbnNpb24pXHJcbiAgICAgIGlmIChoaWdobGlnaHRFeHRlbnNpb24pIHtcclxuICAgICAgICBoaWdobGlnaHRFeHRlbnNpb24uY2xlYXJTZWxlY3Rpb24oKVxyXG4gICAgICB9XHJcblxyXG4gICAgICBzZWxlY3Rpb25FeHRlbnNpb24uY2xlYXJTZWxlY3Rpb24oKVxyXG4gICAgICBpZiAobmV3VmFsLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBzZWxlY3Rpb25FeHRlbnNpb24uc2VsZWN0T2JqZWN0cyhuZXdJZHMpXHJcbiAgICAgIH1cclxuICAgIH0sXHJcbiAgICB7XHJcbiAgICAgIGltbWVkaWF0ZTogdHJ1ZSxcclxuICAgICAgZmx1c2g6ICdzeW5jJ1xyXG4gICAgfVxyXG4gIClcclxufVxyXG5cclxuZnVuY3Rpb24gdXNlTGlnaHRDb25maWdJbnRlZ3JhdGlvbigpIHtcclxuICBjb25zdCB7XHJcbiAgICB1aTogeyBsaWdodENvbmZpZyB9LFxyXG4gICAgdmlld2VyOiB7IGluc3RhbmNlIH1cclxuICB9ID0gdXNlSW5qZWN0ZWRWaWV3ZXJTdGF0ZSgpXHJcblxyXG4gIC8vIHZpZXdlciAtPiBzdGF0ZVxyXG4gIHVzZVZpZXdlckV2ZW50TGlzdGVuZXIoXHJcbiAgICBWaWV3ZXJFdmVudC5MaWdodENvbmZpZ1VwZGF0ZWQsXHJcbiAgICAoY29uZmlnOiBTdW5MaWdodENvbmZpZ3VyYXRpb24pID0+IHtcclxuICAgICAgaWYgKGlzRXF1YWwobGlnaHRDb25maWcudmFsdWUsIGNvbmZpZykpIHJldHVyblxyXG4gICAgICBsaWdodENvbmZpZy52YWx1ZSA9IGNvbmZpZ1xyXG4gICAgfVxyXG4gIClcclxuXHJcbiAgLy8gc3RhdGUgLT4gdmlld2VyXHJcbiAgd2F0Y2goXHJcbiAgICBsaWdodENvbmZpZyxcclxuICAgIChuZXdWYWwsIG9sZFZhbCkgPT4ge1xyXG4gICAgICBpZiAobmV3VmFsICYmIG9sZFZhbCAmJiBpc0VxdWFsKG5ld1ZhbCwgb2xkVmFsKSkgcmV0dXJuXHJcbiAgICAgIGluc3RhbmNlLnNldExpZ2h0Q29uZmlndXJhdGlvbihuZXdWYWwpXHJcbiAgICB9LFxyXG4gICAge1xyXG4gICAgICBpbW1lZGlhdGU6IHRydWUsXHJcbiAgICAgIGRlZXA6IHRydWUsXHJcbiAgICAgIGZsdXNoOiAnc3luYydcclxuICAgIH1cclxuICApXHJcblxyXG4gIHVzZU9uVmlld2VyTG9hZENvbXBsZXRlKFxyXG4gICAgKCkgPT4ge1xyXG4gICAgICBpbnN0YW5jZS5zZXRMaWdodENvbmZpZ3VyYXRpb24obGlnaHRDb25maWcudmFsdWUpXHJcbiAgICB9LFxyXG4gICAgeyBpbml0aWFsT25seTogdHJ1ZSB9XHJcbiAgKVxyXG59XHJcblxyXG5mdW5jdGlvbiB1c2VFeHBsb2RlRmFjdG9ySW50ZWdyYXRpb24oKSB7XHJcbiAgY29uc3Qge1xyXG4gICAgdWk6IHsgZXhwbG9kZUZhY3RvciB9LFxyXG4gICAgdmlld2VyOiB7IGluc3RhbmNlIH1cclxuICB9ID0gdXNlSW5qZWN0ZWRWaWV3ZXJTdGF0ZSgpXHJcblxyXG4gIGNvbnN0IGV4cGxvZGVFeHRlbnNpb24gPSBpbnN0YW5jZS5nZXRFeHRlbnNpb24oRXhwbG9kZUV4dGVuc2lvbilcclxuXHJcbiAgY29uc3QgdXBkYXRlT3V0bGluZXMgPSAoKSA9PiB7XHJcbiAgICBjb25zdCBzZWN0aW9uT3V0bGluZXMgPSBpbnN0YW5jZS5nZXRFeHRlbnNpb24oU2VjdGlvbk91dGxpbmVzKVxyXG4gICAgaWYgKHNlY3Rpb25PdXRsaW5lcyAmJiBzZWN0aW9uT3V0bGluZXMuZW5hYmxlZCkgc2VjdGlvbk91dGxpbmVzLnJlcXVlc3RVcGRhdGUodHJ1ZSlcclxuICB9XHJcbiAgb25Nb3VudGVkKCgpID0+IHtcclxuICAgIGV4cGxvZGVFeHRlbnNpb24ub24oRXhwbG9kZUV2ZW50LkZpbnNoZWQsIHVwZGF0ZU91dGxpbmVzKVxyXG4gIH0pXHJcblxyXG4gIG9uQmVmb3JlVW5tb3VudCgoKSA9PiB7XHJcbiAgICBleHBsb2RlRXh0ZW5zaW9uLnJlbW92ZUxpc3RlbmVyKEV4cGxvZGVFdmVudC5GaW5zaGVkLCB1cGRhdGVPdXRsaW5lcylcclxuICB9KVxyXG5cclxuICAvLyBzdGF0ZSAtPiB2aWV3ZXIgb25seS4gd2UgZG9uJ3QgbmVlZCB0aGUgcmV2ZXJzZS5cclxuICB3YXRjaChcclxuICAgIGV4cGxvZGVGYWN0b3IsXHJcbiAgICAobmV3VmFsKSA9PiB7XHJcbiAgICAgIGV4cGxvZGVFeHRlbnNpb24uc2V0RXhwbG9kZShuZXdWYWwpXHJcbiAgICB9LFxyXG4gICAgeyBpbW1lZGlhdGU6IHRydWUgfVxyXG4gIClcclxuXHJcbiAgdXNlT25WaWV3ZXJMb2FkQ29tcGxldGUoXHJcbiAgICAoKSA9PiB7XHJcbiAgICAgIGV4cGxvZGVFeHRlbnNpb24uc2V0RXhwbG9kZShleHBsb2RlRmFjdG9yLnZhbHVlKVxyXG4gICAgfSxcclxuICAgIHsgaW5pdGlhbE9ubHk6IHRydWUgfVxyXG4gIClcclxufVxyXG5cclxuZnVuY3Rpb24gdXNlRGlmZmluZ0ludGVncmF0aW9uKCkge1xyXG4gIGNvbnN0IHN0YXRlID0gdXNlSW5qZWN0ZWRWaWV3ZXJTdGF0ZSgpXHJcbiAgY29uc3QgeyBlZmZlY3RpdmVBdXRoVG9rZW4gfSA9IHVzZUF1dGhNYW5hZ2VyKClcclxuICBjb25zdCBnZXRPYmplY3RVcmwgPSB1c2VHZXRPYmplY3RVcmwoKVxyXG5cclxuICBjb25zdCBoYXNJbml0aWFsTG9hZEZpcmVkID0gcmVmKGZhbHNlKVxyXG4gIGNvbnN0IGRpZmZFeHRlbnNpb24gPSBzdGF0ZS52aWV3ZXIuaW5zdGFuY2UuZ2V0RXh0ZW5zaW9uKERpZmZFeHRlbnNpb24pXHJcblxyXG4gIGNvbnN0IHsgdHJpZ2dlcjogdHJpZ2dlckRpZmZDb21tYW5kV2F0Y2ggfSA9IHdhdGNoVHJpZ2dlcmFibGUoXHJcbiAgICAoKSA9PiA8Y29uc3Q+W3N0YXRlLnVpLmRpZmYub2xkVmVyc2lvbi52YWx1ZSwgc3RhdGUudWkuZGlmZi5uZXdWZXJzaW9uLnZhbHVlXSxcclxuICAgIGFzeW5jIChuZXdWYWwsIG9sZFZhbCkgPT4ge1xyXG4gICAgICBpZiAoIWhhc0luaXRpYWxMb2FkRmlyZWQudmFsdWUpIHJldHVyblxyXG4gICAgICBjb25zdCBbb2xkVmVyc2lvbiwgbmV3VmVyc2lvbl0gPSBuZXdWYWxcclxuICAgICAgY29uc3QgW29sZE9sZFZlcnNpb24sIG9sZE5ld1ZlcnNpb25dID0gb2xkVmFsIHx8IFtudWxsLCBudWxsXVxyXG5cclxuICAgICAgY29uc3QgdmVyc2lvbklkID0gKHZlcnNpb246IHR5cGVvZiBvbGRPbGRWZXJzaW9uKSA9PiB2ZXJzaW9uPy5pZCB8fCBudWxsXHJcbiAgICAgIGNvbnN0IGNvbW1hbmRJZCA9IChcclxuICAgICAgICBvbGRWZXJzaW9uOiB0eXBlb2Ygb2xkT2xkVmVyc2lvbixcclxuICAgICAgICBuZXdWZXJzaW9uOiB0eXBlb2Ygb2xkT2xkVmVyc2lvblxyXG4gICAgICApID0+IHtcclxuICAgICAgICBjb25zdCBvbGRJZCA9IHZlcnNpb25JZChvbGRWZXJzaW9uKVxyXG4gICAgICAgIGNvbnN0IG5ld0lkID0gdmVyc2lvbklkKG5ld1ZlcnNpb24pXHJcbiAgICAgICAgcmV0dXJuIG9sZElkICYmIG5ld0lkID8gYCR7b2xkSWR9LT4ke25ld0lkfWAgOiBudWxsXHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IG5ld0NvbW1hbmQgPSBjb21tYW5kSWQob2xkVmVyc2lvbiwgbmV3VmVyc2lvbilcclxuICAgICAgY29uc3Qgb2xkQ29tbWFuZCA9IGNvbW1hbmRJZChvbGRPbGRWZXJzaW9uLCBvbGROZXdWZXJzaW9uKVxyXG5cclxuICAgICAgaWYgKChuZXdDb21tYW5kICYmIG9sZENvbW1hbmQgPT09IG5ld0NvbW1hbmQpIHx8ICEhbmV3Q29tbWFuZCA9PT0gISFvbGRDb21tYW5kKVxyXG4gICAgICAgIHJldHVyblxyXG5cclxuICAgICAgaWYgKCFuZXdDb21tYW5kIHx8IG9sZFZhbCkge1xyXG4gICAgICAgIGF3YWl0IGRpZmZFeHRlbnNpb24udW5kaWZmKClcclxuICAgICAgICBpZiAoIW5ld0NvbW1hbmQpIHJldHVyblxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyB2YWx1ZXMgc2hvdWxkbid0IGJlIHVuZGVmaW5lZCBjYXVzZSBjb21tYW5kSWQoKSBnZW5lcmF0aW9uIHN1Y2NlZWRlZFxyXG4gICAgICBjb25zdCBvbGRPYmpVcmwgPSBnZXRPYmplY3RVcmwoXHJcbiAgICAgICAgc3RhdGUucHJvamVjdElkLnZhbHVlLFxyXG4gICAgICAgIG9sZFZlcnNpb24/LnJlZmVyZW5jZWRPYmplY3QgYXMgc3RyaW5nXHJcbiAgICAgIClcclxuICAgICAgY29uc3QgbmV3T2JqVXJsID0gZ2V0T2JqZWN0VXJsKFxyXG4gICAgICAgIHN0YXRlLnByb2plY3RJZC52YWx1ZSxcclxuICAgICAgICBuZXdWZXJzaW9uPy5yZWZlcmVuY2VkT2JqZWN0IGFzIHN0cmluZ1xyXG4gICAgICApXHJcblxyXG4gICAgICBzdGF0ZS51aS5kaWZmLnJlc3VsdC52YWx1ZSA9IGF3YWl0IGRpZmZFeHRlbnNpb24uZGlmZihcclxuICAgICAgICBvbGRPYmpVcmwsXHJcbiAgICAgICAgbmV3T2JqVXJsLFxyXG4gICAgICAgIHN0YXRlLnVpLmRpZmYubW9kZS52YWx1ZSxcclxuICAgICAgICBlZmZlY3RpdmVBdXRoVG9rZW4udmFsdWVcclxuICAgICAgKVxyXG4gICAgfSxcclxuICAgIHsgaW1tZWRpYXRlOiB0cnVlIH1cclxuICApXHJcblxyXG4gIC8vIGNvbnN0IHByZXZlbnRXYXRjaGVycyA9IDBcclxuICB3YXRjaChzdGF0ZS51aS5kaWZmLnJlc3VsdCwgKHZhbCkgPT4ge1xyXG4gICAgaWYgKCF2YWwpIHJldHVyblxyXG4gICAgLy8gcmVzZXQgdmlzdWFsIGRpZmYgdGltZSBhbmQgbW9kZSBvbiBuZXcgZGlmZiByZXN1bHRcclxuICAgIC8vIHNvbWV0aW1lcyB0aGUgd2F0Y2hlciB3b24ndCBmaXJlIGV2ZW4gd2hlbiB0aGUgdmFsdWVzIGFyZSB1cGRhdGVkLCBiZWNhdXNlIHRoZXkncmUgdXBkYXRlZCB0b1xyXG4gICAgLy8gdGhlIHNhbWUgdmFsdWVzIHRoYXQgdGhleSB3ZXJlIGFscmVhZHkuIGJlY2F1c2Ugb2YgdGhhdCB3ZSdyZSBtYW51YWxseSAmIGZvcmNlZnVsbHkgcnVubmluZ1xyXG4gICAgLy8gdGhlIHJlbGV2YW50IHdhdGNoZXJzIHdoZW4gZGlmZlJlc3VsdCBjaGFuZ2VzXHJcbiAgICBpZ25vcmVEaWZmTW9kZVVwZGF0ZXMoKCkgPT4ge1xyXG4gICAgICBpZ25vcmVEaWZmVGltZVVwZGF0ZXMoKCkgPT4ge1xyXG4gICAgICAgIHN0YXRlLnVpLmRpZmYudGltZS52YWx1ZSA9IDAuNVxyXG4gICAgICAgIHN0YXRlLnVpLmRpZmYubW9kZS52YWx1ZSA9IFZpc3VhbERpZmZNb2RlLkNPTE9SRURcclxuXHJcbiAgICAgICAgLy8gdGhpcyB3YXRjaGVyIGFsc28gdXBkYXRlcyBkaWZmVGltZSwgc28gbm8gbmVlZCB0byBpbnZva2UgdGhhdCBzZXBhcmF0ZWx5XHJcbiAgICAgICAgdHJpZ2dlckRpZmZNb2RlV2F0Y2goKVxyXG4gICAgICB9KVxyXG4gICAgfSlcclxuICB9KVxyXG5cclxuICBjb25zdCB7IGlnbm9yZVVwZGF0ZXM6IGlnbm9yZURpZmZUaW1lVXBkYXRlcyB9ID0gd2F0Y2hUcmlnZ2VyYWJsZShcclxuICAgIHN0YXRlLnVpLmRpZmYudGltZSxcclxuICAgICh2YWwpID0+IHtcclxuICAgICAgaWYgKCFoYXNJbml0aWFsTG9hZEZpcmVkLnZhbHVlKSByZXR1cm5cclxuICAgICAgaWYgKCFzdGF0ZS51aS5kaWZmLnJlc3VsdC52YWx1ZSkgcmV0dXJuXHJcblxyXG4gICAgICBkaWZmRXh0ZW5zaW9uLnVwZGF0ZVZpc3VhbERpZmYodmFsLCBzdGF0ZS51aS5kaWZmLm1vZGUudmFsdWUpXHJcbiAgICB9XHJcbiAgKVxyXG5cclxuICBjb25zdCB7IHRyaWdnZXI6IHRyaWdnZXJEaWZmTW9kZVdhdGNoLCBpZ25vcmVVcGRhdGVzOiBpZ25vcmVEaWZmTW9kZVVwZGF0ZXMgfSA9XHJcbiAgICB3YXRjaFRyaWdnZXJhYmxlKHN0YXRlLnVpLmRpZmYubW9kZSwgKHZhbCkgPT4ge1xyXG4gICAgICBpZiAoIWhhc0luaXRpYWxMb2FkRmlyZWQudmFsdWUpIHJldHVyblxyXG4gICAgICBpZiAoIXN0YXRlLnVpLmRpZmYucmVzdWx0LnZhbHVlKSByZXR1cm5cclxuXHJcbiAgICAgIGRpZmZFeHRlbnNpb24udXBkYXRlVmlzdWFsRGlmZihzdGF0ZS51aS5kaWZmLnRpbWUudmFsdWUsIHZhbClcclxuICAgIH0pXHJcblxyXG4gIHVzZU9uVmlld2VyTG9hZENvbXBsZXRlKCh7IGlzSW5pdGlhbCB9KSA9PiB7XHJcbiAgICBpZiAoIWlzSW5pdGlhbCkgcmV0dXJuXHJcbiAgICBoYXNJbml0aWFsTG9hZEZpcmVkLnZhbHVlID0gdHJ1ZVxyXG5cclxuICAgIHRyaWdnZXJEaWZmQ29tbWFuZFdhdGNoKClcclxuICB9KVxyXG59XHJcblxyXG5mdW5jdGlvbiB1c2VEaXNhYmxlWm9vbU9uRW1iZWQoKSB7XHJcbiAgY29uc3QgeyB2aWV3ZXIgfSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG4gIGNvbnN0IGVtYmVkT3B0aW9ucyA9IHVzZUVtYmVkKClcclxuXHJcbiAgd2F0Y2goXHJcbiAgICAoKSA9PiBlbWJlZE9wdGlvbnMubm9TY3JvbGwudmFsdWUsXHJcbiAgICAobmV3Tm9TY3JvbGxWYWx1ZSkgPT4ge1xyXG4gICAgICBjb25zdCBjYW1lcmFDb250cm9sbGVyOiBDYW1lcmFDb250cm9sbGVyID1cclxuICAgICAgICB2aWV3ZXIuaW5zdGFuY2UuZ2V0RXh0ZW5zaW9uKENhbWVyYUNvbnRyb2xsZXIpXHJcblxyXG4gICAgICBpZiAobmV3Tm9TY3JvbGxWYWx1ZSkge1xyXG4gICAgICAgIGNhbWVyYUNvbnRyb2xsZXIub3B0aW9ucyA9IHsgZW5hYmxlWm9vbTogZmFsc2UgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNhbWVyYUNvbnRyb2xsZXIub3B0aW9ucyA9IHsgZW5hYmxlWm9vbTogdHJ1ZSB9XHJcbiAgICAgIH1cclxuICAgIH0sXHJcbiAgICB7IGltbWVkaWF0ZTogdHJ1ZSB9XHJcbiAgKVxyXG59XHJcblxyXG5mdW5jdGlvbiB1c2VWaWV3ZXJUcmVlSW50ZWdyYXRpb24oKSB7XHJcbiAgY29uc3QgeyB2aWV3ZXIgfSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG4gIGNvbnN0IHsgdHJlZVN0YXRlTWFuYWdlciB9ID0gdXNlVHJlZU1hbmFnZW1lbnQoKVxyXG5cclxuICAvLyBJbml0aWFsaXplIHRoZSB0cmVlIHN0YXRlIG1hbmFnZXIgd2l0aCB2aWV3ZXIgaW5zdGFuY2VcclxuICBvbk1vdW50ZWQoKCkgPT4gdHJlZVN0YXRlTWFuYWdlci5pbml0aWFsaXplKHZpZXdlci5pbnN0YW5jZSkpXHJcbn1cclxuXHJcbmdyYXBocWwoYFxyXG4gIGZyYWdtZW50IFVzZVZpZXdlclNhdmVkVmlld1NldHVwX1NhdmVkVmlldyBvbiBTYXZlZFZpZXcge1xyXG4gICAgaWRcclxuICAgIHZpZXdlclN0YXRlXHJcbiAgICAuLi5WaWV3ZXJQYWdlU2V0dXBfU2F2ZWRWaWV3XHJcbiAgfVxyXG5gKVxyXG5cclxuZnVuY3Rpb24gdXNlVmlld2VyQ3Vyc29ySW50ZWdyYXRpb24oKSB7XHJcbiAgY29uc3Qge1xyXG4gICAgdmlld2VyOiB7IGNvbnRhaW5lciB9XHJcbiAgfSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG5cclxuICBjb25zdCB7XHJcbiAgICBmaWx0ZXJzOiB7IHNlbGVjdGVkT2JqZWN0cyB9XHJcbiAgfSA9IHVzZUluamVjdGVkVmlld2VySW50ZXJmYWNlU3RhdGUoKVxyXG5cclxuICBjb25zdCB7IHNoaWZ0IH0gPSB1c2VNYWdpY0tleXMoKVxyXG4gIGNvbnN0IGlzRHJhZ2dpbmcgPSByZWYoZmFsc2UpXHJcblxyXG4gIC8vIEhhbmRsZSBtb3VzZSBkb3duL3VwIHRvIHRyYWNrIGRyYWdnaW5nIHN0YXRlXHJcbiAgY29uc3QgaGFuZGxlUG9pbnRlckRvd24gPSAoX2V2ZW50OiBQb2ludGVyRXZlbnQpID0+IHtcclxuICAgIGlmIChzaGlmdC52YWx1ZSAmJiBzZWxlY3RlZE9iamVjdHMudmFsdWUubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgIGlzRHJhZ2dpbmcudmFsdWUgPSB0cnVlXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBjb25zdCBoYW5kbGVQb2ludGVyVXAgPSAoKSA9PiB7XHJcbiAgICBpc0RyYWdnaW5nLnZhbHVlID0gZmFsc2VcclxuICB9XHJcblxyXG4gIC8vIFNob3cgZGlmZmVyZW50IGN1cnNvcnM6IGdyYWIgKHJlYWR5IHRvIGRyYWcpIHZzIGdyYWJiaW5nIChhY3RpdmVseSBkcmFnZ2luZylcclxuICB3YXRjaChcclxuICAgIFtzaGlmdCwgc2VsZWN0ZWRPYmplY3RzLCBpc0RyYWdnaW5nXSxcclxuICAgICgpID0+IHtcclxuICAgICAgaWYgKCFjb250YWluZXIpIHJldHVyblxyXG5cclxuICAgICAgY29uc3QgaGFzU2VsZWN0aW9uID0gc2VsZWN0ZWRPYmplY3RzLnZhbHVlLmxlbmd0aCA+IDBcclxuICAgICAgY29uc3Qgc2hvdWxkU2hvd0RyYWcgPSBzaGlmdC52YWx1ZSAmJiAhaGFzU2VsZWN0aW9uXHJcblxyXG4gICAgICBpZiAoc2hvdWxkU2hvd0RyYWcpIHtcclxuICAgICAgICBjb250YWluZXIuc3R5bGUuY3Vyc29yID0gaXNEcmFnZ2luZy52YWx1ZSA/ICdncmFiYmluZycgOiAnZ3JhYidcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICBjb250YWluZXIuc3R5bGUuY3Vyc29yID0gJydcclxuICAgICAgfVxyXG4gICAgfSxcclxuICAgIHsgaW1tZWRpYXRlOiB0cnVlIH1cclxuICApXHJcblxyXG4gIHVzZUV2ZW50TGlzdGVuZXIoY29udGFpbmVyLCAncG9pbnRlcmRvd24nLCBoYW5kbGVQb2ludGVyRG93biwgeyBwYXNzaXZlOiB0cnVlIH0pXHJcbiAgdXNlRXZlbnRMaXN0ZW5lcihkb2N1bWVudCwgJ3BvaW50ZXJ1cCcsIGhhbmRsZVBvaW50ZXJVcCwgeyBwYXNzaXZlOiB0cnVlIH0pXHJcblxyXG4gIG9uQmVmb3JlVW5tb3VudCgoKSA9PiB7XHJcbiAgICBpZiAoY29udGFpbmVyKSB7XHJcbiAgICAgIGNvbnRhaW5lci5zdHlsZS5jdXJzb3IgPSAnJ1xyXG4gICAgfVxyXG4gIH0pXHJcbn1cclxuXHJcbmNvbnN0IHVzZUNvbW1lbnRDb250ZXh0SW50ZWdyYXRpb24gPSAoKSA9PiB7XHJcbiAgY29uc3QgeyBjbGVhbnVwVGhyZWFkQ29udGV4dCB9ID0gdXNlQ29tbWVudENvbnRleHQoKVxyXG5cclxuICBvbkJlZm9yZVVubW91bnQoKCkgPT4ge1xyXG4gICAgY2xlYW51cFRocmVhZENvbnRleHQoKVxyXG4gIH0pXHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiB1c2VWaWV3ZXJQb3N0U2V0dXAoKSB7XHJcbiAgaWYgKGltcG9ydC5tZXRhLnNlcnZlcikgcmV0dXJuXHJcbiAgdXNlVmlld2VyT2JqZWN0QXV0b0xvYWRpbmcoKVxyXG4gIHVzZVZpZXdlclNhdmVkVmlld0ludGVncmF0aW9uKClcclxuICB1c2VWaWV3ZXJSZWNlaXZlVHJhY2tpbmcoKVxyXG4gIHVzZVZpZXdlclNlbGVjdGlvbkV2ZW50SGFuZGxlcigpXHJcbiAgdXNlVmlld2VyTG9hZENvbXBsZXRlRXZlbnRIYW5kbGVyKClcclxuICB1c2VWaWV3ZXJTdWJzY3JpcHRpb25FdmVudFRyYWNrZXIoKVxyXG4gIHVzZVZpZXdlclRocmVhZFRyYWNraW5nKClcclxuICB1c2VWaWV3ZXJPcGVuZWRUaHJlYWRVcGRhdGVFbWl0dGVyKClcclxuICB1c2VWaWV3ZXJTZWN0aW9uQm94SW50ZWdyYXRpb24oKVxyXG4gIHVzZVZpZXdlckNhbWVyYUludGVncmF0aW9uKClcclxuICB1c2VWaWV3ZXJGaWx0ZXJzSW50ZWdyYXRpb24oKVxyXG4gIHVzZUxpZ2h0Q29uZmlnSW50ZWdyYXRpb24oKVxyXG4gIHVzZUV4cGxvZGVGYWN0b3JJbnRlZ3JhdGlvbigpXHJcbiAgdXNlRGlmZmluZ0ludGVncmF0aW9uKClcclxuICB1c2VNZWFzdXJlbWVudHNQb3N0U2V0dXAoKVxyXG4gIHVzZUZpbHRlckNvbG9yaW5nUG9zdFNldHVwKClcclxuICB1c2VQcm9wZXJ0eUZpbHRlcmluZ1Bvc3RTZXR1cCgpXHJcbiAgdXNlTWFudWFsRmlsdGVyaW5nUG9zdFNldHVwKClcclxuICB1c2VEaXNhYmxlWm9vbU9uRW1iZWQoKVxyXG4gIHVzZVZpZXdlckN1cnNvckludGVncmF0aW9uKClcclxuICB1c2VWaWV3ZXJUcmVlSW50ZWdyYXRpb24oKVxyXG4gIHVzZVZpZXdNb2Rlc1Bvc3RTZXR1cCgpXHJcbiAgdXNlSGlnaGxpZ2h0aW5nUG9zdFNldHVwKClcclxuICB1c2VDb21tZW50Q29udGV4dEludGVncmF0aW9uKClcclxuICBzZXR1cERlYnVnTW9kZSgpXHJcbn1cclxuIl0sImZpbGUiOiJEOi9zcGVja2xlLXNlcnZlci9wYWNrYWdlcy9mcm9udGVuZC0yL2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvc2V0dXAvcG9zdFNldHVwLnRzIn0=