import { useApolloClient, useSubscription } from "/_nuxt/node_modules/@vue/apollo-composable/dist/index.mjs?v=e4f18c29"; import { ViewerUserActivityStatus } from "/_nuxt/lib/common/generated/gql/graphql.ts"; import { useInjectedViewerInterfaceState, useInjectedViewerState } from "/_nuxt/lib/viewer/composables/setup.ts"; import { useSelectionEvents, useViewerCameraControlEndTracker } from "/_nuxt/lib/viewer/composables/viewer.ts"; import { xor, TIME_MS } from "/_nuxt/@fs/D:/speckle-server/packages/shared/dist/esm/index.js"; import { Vector3 } from "/_nuxt/node_modules/.cache/vite/client/deps/three.js?v=e4f18c29"; import { useActiveUser } from "/_nuxt/lib/auth/composables/activeUser.ts"; import { broadcastViewerUserActivityMutation } from "/_nuxt/lib/viewer/graphql/mutations.ts"; import { convertThrowIntoFetchResult } from "/_nuxt/lib/common/helpers/graphql.ts"; import __vite__cjsImport9_dayjs from "/_nuxt/node_modules/.cache/vite/client/deps/dayjs.js?v=e4f18c29"; const dayjs = __vite__cjsImport9_dayjs.__esModule ? __vite__cjsImport9_dayjs.default : __vite__cjsImport9_dayjs; import { useIntervalFn, useWindowFocus } from "/_nuxt/node_modules/@vueuse/core/index.mjs?v=e4f18c29"; import { useViewerAnchoredPoints } from "/_nuxt/lib/viewer/composables/anchorPoints.ts"; import { useOnBeforeWindowUnload } from "/_nuxt/lib/common/composables/window.ts"; import { ToastNotificationType, useGlobalToast } from "/_nuxt/lib/common/composables/toast.ts"; import { onViewerUserActivityBroadcastedSubscription } from "/_nuxt/lib/viewer/graphql/subscriptions.ts"; import { useEmbed } from "/_nuxt/lib/viewer/composables/setup/embed.ts"; import { StateApplyMode, useApplySerializedState, useStateSerialization } from "/_nuxt/lib/viewer/composables/serialization.ts"; import { graphql } from "/_nuxt/lib/common/generated/gql/index.ts"; import { isSerializedViewerState } from "/_nuxt/@fs/D:/speckle-server/packages/shared/dist/esm/viewer/helpers/state.js"; import { omit, debounce } from "/_nuxt/node_modules/.cache/vite/client/deps/lodash-es.js?v=e4f18c29"; import { useState } from "/_nuxt/node_modules/nuxt/dist/app/composables/state.js?v=e4f18c29"; import { computed, onUnmounted, ref, watch, nextTick, onMounted, onBeforeUnmount, unref } from "/_nuxt/node_modules/vue/dist/vue.runtime.esm-bundler.js?v=e4f18c29"; import { useRuntimeConfig } from "/_nuxt/node_modules/nuxt/dist/app/nuxt.js?v=e4f18c29"; const OWN_ACTIVITY_UPDATE_INTERVAL = 5 * TIME_MS.second; const USER_STALE_CHECK_INTERVAL = 2e3; const USER_STALE_AFTER_PERIOD = 20 * OWN_ACTIVITY_UPDATE_INTERVAL; const USER_REMOVABLE_AFTER_PERIOD = USER_STALE_AFTER_PERIOD * 2; function useCollectMainMetadata() { const { sessionId } = useInjectedViewerState(); const { activeUser } = useActiveUser(); const { serialize } = useStateSerialization(); return () => ({ userId: activeUser.value?.id || null, userName: activeUser.value?.name || "Anonymous Viewer", state: serialize(), sessionId: sessionId.value }); } graphql(` fragment UseViewerUserActivityBroadcasting_Project on Project { id permissions { canBroadcastActivity { ...FullPermissionCheckResult } } } `); const useViewerRealtimeActivityState = () => useState("viewer_realtime_activity_state", () => ({ activity: void 0, status: ViewerUserActivityStatus.Viewing })); export const useViewerRealtimeActivityTracker = () => { const state = useViewerRealtimeActivityState(); const getMainMetadata = useCollectMainMetadata(); const serializer = (val) => JSON.stringify(val); const activity = computed({ get: () => state.value.activity || getMainMetadata(), set: (value) => { state.value.activity = value; } }); const status = computed({ get: () => state.value.status, set: (value) => { state.value.status = value; } }); const serializedState = computed(() => activity.value.state); const serializedStateId = computed(() => serializer(serializedState.value)); const activityId = computed(() => { const stateId = serializedStateId.value; const otherActivity = omit(activity.value, [ "state" ]); const otherActivityId = serializer(otherActivity); return `${stateId}-${otherActivityId}-${status.value}`; }); const update = (params) => { activity.value = params?.newActivity || getMainMetadata(); if (params?.status) { status.value = params.status; } }; onUnmounted(() => { state.value.activity = void 0; state.value.status = ViewerUserActivityStatus.Viewing; }); return { activity, serializedState, status, update, serializedStateId, activityId, serializer }; }; export function useViewerUserActivityBroadcasting(options) { const { projectId, resources: { request: { resourceIdString }, response: { project } } } = options?.state || useInjectedViewerState(); const { public: { disableViewerActivityBroadcasting } } = useRuntimeConfig(); const { activeUser } = useActiveUser(); const { update, activity, status, activityId } = useViewerRealtimeActivityTracker(); const apollo = useApolloClient().client; const { isEnabled: isEmbedEnabled } = useEmbed(); const canBroadcast = computed( () => project.value?.permissions.canBroadcastActivity.authorized ); const isSameActivity = (previousActivityId2, newActivityId) => { if (xor(previousActivityId2, newActivityId)) return false; if (!previousActivityId2 && !newActivityId) return false; return previousActivityId2 === newActivityId; }; const invokeMutation = async () => { if (!activeUser.value?.id || disableViewerActivityBroadcasting) return false; const result = await apollo.mutate({ mutation: broadcastViewerUserActivityMutation, variables: { resourceIdString: resourceIdString.value, message: { ...activity.value, status: status.value, userId: activeUser.value.id, userName: activeUser.value.name }, projectId: projectId.value } }).catch(convertThrowIntoFetchResult); return result.data?.broadcastViewerUserActivity || false; }; let previousActivityId = void 0; const invokeObservabilityEvent = async () => { const dd = window.DD_RUM; if (!dd || !("addAction" in dd)) return; const message = { ...activity.value, status: status.value }; if (isSameActivity(previousActivityId, activityId.value)) return; previousActivityId = activityId.value; dd.addAction("Viewer User Activity", { message }); }; const invoke = async () => { if (!canBroadcast.value || isEmbedEnabled.value) return false; return await Promise.all([invokeMutation(), invokeObservabilityEvent()]); }; return { emitDisconnected: async () => { update({ status: ViewerUserActivityStatus.Disconnected }); await invoke(); }, emitViewing: async () => { update({ status: ViewerUserActivityStatus.Viewing }); await invoke(); } }; } export function useViewerUserActivityTracking(params) { const { anchoredPointsParentEl: parentEl, trackInternallyOnly } = params || {}; const { projectId, sessionId, resources: { request: { resourceIdString, threadFilters } } } = useInjectedViewerState(); const { isLoggedIn } = useActiveUser(); const { triggerNotification } = useGlobalToast(); const { update } = useViewerRealtimeActivityTracker(); const sendUpdate = useViewerUserActivityBroadcasting(); const { isEnabled: isEmbedEnabled } = useEmbed(); const { activeUser } = useActiveUser(); const processViewerViewing = async () => { if (trackInternallyOnly) { update({ status: ViewerUserActivityStatus.Viewing }); } else { await sendUpdate.emitViewing(); } }; const processViewerDisconnected = async () => { if (trackInternallyOnly) { update({ status: ViewerUserActivityStatus.Disconnected }); } else { await sendUpdate.emitDisconnected(); } }; const { onResult: onUserActivity } = useSubscription( onViewerUserActivityBroadcastedSubscription, () => ({ target: { projectId: projectId.value, resourceIdString: resourceIdString.value, loadedVersionsOnly: threadFilters.value.loadedVersionsOnly }, sessionId: sessionId.value }), () => ({ enabled: isLoggedIn.value && !trackInternallyOnly, errorPolicy: "all" }) ); const users = ref({}); const { spotlightUserSessionId } = useInjectedViewerInterfaceState(); const spotlightTracker = useViewerSpotlightTracking(); onUserActivity((res) => { if (!res.data?.viewerUserActivityBroadcasted) return; const event = res.data.viewerUserActivityBroadcasted; const status = event.status; const incomingSessionId = event.sessionId; const incomingUserId = event.userId; const currentUserId = activeUser.value?.id; if (sessionId.value === incomingSessionId) return; if (currentUserId && incomingUserId && currentUserId === incomingUserId) return; if (!isEmbedEnabled.value && status === ViewerUserActivityStatus.Disconnected) { const disconnectingUser = users.value[incomingSessionId]; const hasOtherActiveSessions = incomingUserId ? Object.values(users.value).some( (user) => user.userId === incomingUserId && user.sessionId !== incomingSessionId ) : false; if (disconnectingUser && !hasOtherActiveSessions) { triggerNotification({ title: `${disconnectingUser.userName || "A user"} left.`, type: ToastNotificationType.Info }); } if (spotlightUserSessionId.value === incomingSessionId) spotlightUserSessionId.value = null; delete users.value[incomingSessionId]; return; } const state2 = isSerializedViewerState(event.state) ? event.state : null; if (!state2) return; const userData = { ...users.value[incomingSessionId] ? users.value[incomingSessionId] : { isClipped: false, projectedPosition: [0, 0], style: { target: {} }, isOccluded: false }, ...event, state: state2, isStale: false, lastUpdate: dayjs() }; const isNewSession = !Object.keys(users.value).includes(incomingSessionId); const hasExistingUserSessions = incomingUserId ? Object.values(users.value).some((user) => user.userId === incomingUserId) : false; if (!isEmbedEnabled.value && isNewSession && !hasExistingUserSessions) { triggerNotification({ title: `${userData.userName} joined.`, type: ToastNotificationType.Info }); } users.value[incomingSessionId] = userData; if (spotlightUserSessionId.value === userData.sessionId) { spotlightTracker(userData); } }); if (parentEl) { useViewerAnchoredPoints( { parentEl, points: computed(() => Object.values(users.value)), pointLocationGetter: (user) => { const selection = user.state.ui.selection; const selectionVector = selection ? new Vector3(selection[0], selection[1], selection[2]) : null; function getPointInBetweenByPerc(pointA, pointB, percentage) { let dir = pointB.clone().sub(pointA); const len = dir.length(); dir = dir.normalize().multiplyScalar(len * percentage); return pointA.clone().add(dir); } if (!selectionVector) { const camPos = user.state.ui.camera.position; const camPosVector = new Vector3(camPos[0], camPos[1], camPos[2]); const camTarget = user.state.ui.camera.target; const camTargetVector = new Vector3( camTarget[0], camTarget[1], camTarget[2] ); return getPointInBetweenByPerc(camTargetVector, camPosVector, 0.2); } return selectionVector.clone(); }, updatePositionCallback: (user, result, options) => { user.isOccluded = result.isOccluded; user.style = { ...user.style, target: { ...user.style.target, ...result.style, transition: options?.smoothTranslation === false ? "" : "all 0.1s ease" // opacity: user.isOccluded ? '0.5' : user.isStale ? '0.2' : '1.0' // note: handled in component via css } }; } } ); } const hideStaleUsers = () => { if (!Object.values(users.value).length) return; for (const [key, user] of Object.entries(users.value)) { user.isStale = user.lastUpdate.isBefore( dayjs().subtract(USER_STALE_AFTER_PERIOD, "milliseconds") ); if (user.lastUpdate.isBefore( dayjs().subtract(USER_REMOVABLE_AFTER_PERIOD, "millisecond") )) { delete users.value[key]; } } }; const focused = useWindowFocus(); const debouncedDisconnect = debounce( async () => { await processViewerDisconnected(); }, 30 * 1e3 // 30 seconds ); watch(focused, async (newVal) => { if (!newVal) { debouncedDisconnect(); } else { debouncedDisconnect.cancel(); await processViewerViewing(); } }); const sendUpdateAndHideStaleUsers = () => { if (!focused.value) return; hideStaleUsers(); processViewerViewing(); }; useIntervalFn(sendUpdateAndHideStaleUsers, OWN_ACTIVITY_UPDATE_INTERVAL); useIntervalFn(hideStaleUsers, USER_STALE_CHECK_INTERVAL); const selectionCallback = () => { nextTick(() => sendUpdateAndHideStaleUsers()); }; useSelectionEvents({ singleClickCallback: selectionCallback, doubleClickCallback: selectionCallback }); useViewerCameraControlEndTracker(() => processViewerViewing()); useOnBeforeWindowUnload(async () => { debouncedDisconnect.cancel(); await processViewerDisconnected(); }); onMounted(() => { processViewerViewing(); }); onBeforeUnmount(() => { debouncedDisconnect.cancel(); void processViewerDisconnected(); }); const state = useInjectedViewerState(); watch(spotlightUserSessionId, (newVal) => { if (!newVal) { state.ui.highlightedObjectIds.value = []; return; } const user = Object.values(users.value).find((u) => u.sessionId === newVal); if (!user) return; spotlightTracker(user); }); watch(resourceIdString, (newVal, oldVal) => { if (newVal !== oldVal) { void processViewerViewing(); } }); return { users }; } function useViewerSpotlightTracking() { const applyState = useApplySerializedState(); return async (user) => { await applyState(user.state, StateApplyMode.Spotlight); }; } export function useViewerThreadTypingTracking(threadId) { const usersTyping = ref([]); const { sessionId, projectId, resources: { request: { resourceIdString, threadFilters } } } = useInjectedViewerState(); const { isLoggedIn } = useActiveUser(); const { onResult: onUserActivity } = useSubscription( onViewerUserActivityBroadcastedSubscription, () => ({ target: { projectId: projectId.value, resourceIdString: resourceIdString.value, loadedVersionsOnly: threadFilters.value.loadedVersionsOnly }, sessionId: sessionId.value }), () => ({ enabled: isLoggedIn.value, errorPolicy: "all" }) ); onUserActivity((res) => { if (!res.data?.viewerUserActivityBroadcasted) return; const event = res.data.viewerUserActivityBroadcasted; const userId = event.userId || event.sessionId; const existingItemIdx = usersTyping.value.findIndex((i) => i.userId === userId); if (existingItemIdx !== -1) { usersTyping.value.splice(existingItemIdx, 1); } const state = isSerializedViewerState(event.state) ? event.state : null; if (!state) return; const typingPayload = state.ui.threads.openThread; if (typingPayload.threadId !== unref(threadId)) { return; } const typingInfo = { userId, userName: event.userName, thread: typingPayload, lastSeen: dayjs() }; if (typingInfo.thread.isTyping) usersTyping.value.push(typingInfo); }); return { usersTyping: computed(() => usersTyping.value) }; } //# sourceMappingURL=data:application/json;base64,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QVcsTUFBTTtBQUc5RSxRQUFJLG9CQUFvQixJQUFJO0FBQzFCLGtCQUFZLE1BQU0sT0FBTyxpQkFBaUIsQ0FBQztBQUFBLElBQzdDO0FBRUEsVUFBTSxRQUFRLHdCQUF3QixNQUFNLEtBQUssSUFBSSxNQUFNLFFBQVE7QUFDbkUsUUFBSSxDQUFDLE1BQU87QUFDWixVQUFNLGdCQUFnQixNQUFNLEdBQUcsUUFBUTtBQUN2QyxRQUFJLGNBQWMsYUFBYSxNQUFNLFFBQVEsR0FBRztBQUM5QztBQUFBLElBQ0Y7QUFFQSxVQUFNLGFBQTZCO0FBQUEsTUFDakM7QUFBQSxNQUNBLFVBQVUsTUFBTTtBQUFBLE1BQ2hCLFFBQVE7QUFBQSxNQUNSLFVBQVUsTUFBTTtBQUFBLElBQ2xCO0FBRUEsUUFBSSxXQUFXLE9BQU8sU0FBVSxhQUFZLE1BQU0sS0FBSyxVQUFVO0FBQUEsRUFDbkUsQ0FBQztBQUVELFNBQU87QUFBQSxJQUNMLGFBQWEsU0FBUyxNQUFNLFlBQVksS0FBSztBQUFBLEVBQy9DO0FBQ0YiLCJuYW1lcyI6WyJwcmV2aW91c0FjdGl2aXR5SWQiLCJzdGF0ZSJdLCJpZ25vcmVMaXN0IjpbXSwic291cmNlcyI6WyJhY3Rpdml0eS50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyB1c2VBcG9sbG9DbGllbnQsIHVzZVN1YnNjcmlwdGlvbiB9IGZyb20gJ0B2dWUvYXBvbGxvLWNvbXBvc2FibGUnXHJcbmltcG9ydCB7IFZpZXdlclVzZXJBY3Rpdml0eVN0YXR1cyB9IGZyb20gJ35+L2xpYi9jb21tb24vZ2VuZXJhdGVkL2dxbC9ncmFwaHFsJ1xyXG5pbXBvcnQgdHlwZSB7XHJcbiAgT25WaWV3ZXJVc2VyQWN0aXZpdHlCcm9hZGNhc3RlZFN1YnNjcmlwdGlvbixcclxuICBWaWV3ZXJVc2VyQWN0aXZpdHlNZXNzYWdlSW5wdXRcclxufSBmcm9tICd+fi9saWIvY29tbW9uL2dlbmVyYXRlZC9ncWwvZ3JhcGhxbCdcclxuaW1wb3J0IHtcclxuICB1c2VJbmplY3RlZFZpZXdlckludGVyZmFjZVN0YXRlLFxyXG4gIHVzZUluamVjdGVkVmlld2VyU3RhdGVcclxufSBmcm9tICd+fi9saWIvdmlld2VyL2NvbXBvc2FibGVzL3NldHVwJ1xyXG5pbXBvcnQgdHlwZSB7IEluamVjdGFibGVWaWV3ZXJTdGF0ZSB9IGZyb20gJ35+L2xpYi92aWV3ZXIvY29tcG9zYWJsZXMvc2V0dXAnXHJcbmltcG9ydCB7XHJcbiAgdXNlU2VsZWN0aW9uRXZlbnRzLFxyXG4gIHVzZVZpZXdlckNhbWVyYUNvbnRyb2xFbmRUcmFja2VyXHJcbn0gZnJvbSAnfn4vbGliL3ZpZXdlci9jb21wb3NhYmxlcy92aWV3ZXInXHJcbmltcG9ydCB7IHhvciwgVElNRV9NUyB9IGZyb20gJ0BzcGVja2xlL3NoYXJlZCdcclxuaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSwgT3B0aW9uYWwgfSBmcm9tICdAc3BlY2tsZS9zaGFyZWQnXHJcbmltcG9ydCB7IFZlY3RvcjMgfSBmcm9tICd0aHJlZSdcclxuaW1wb3J0IHsgdXNlQWN0aXZlVXNlciB9IGZyb20gJ35+L2xpYi9hdXRoL2NvbXBvc2FibGVzL2FjdGl2ZVVzZXInXHJcbmltcG9ydCB7IGJyb2FkY2FzdFZpZXdlclVzZXJBY3Rpdml0eU11dGF0aW9uIH0gZnJvbSAnfn4vbGliL3ZpZXdlci9ncmFwaHFsL211dGF0aW9ucydcclxuaW1wb3J0IHsgY29udmVydFRocm93SW50b0ZldGNoUmVzdWx0IH0gZnJvbSAnfn4vbGliL2NvbW1vbi9oZWxwZXJzL2dyYXBocWwnXHJcbmltcG9ydCB0eXBlIHsgRGF5anMgfSBmcm9tICdkYXlqcydcclxuaW1wb3J0IGRheWpzIGZyb20gJ2RheWpzJ1xyXG5pbXBvcnQgeyB1c2VJbnRlcnZhbEZuLCB1c2VXaW5kb3dGb2N1cyB9IGZyb20gJ0B2dWV1c2UvY29yZSdcclxuaW1wb3J0IHR5cGUgeyBNYXliZVJlZiB9IGZyb20gJ0B2dWV1c2UvY29yZSdcclxuaW1wb3J0IHR5cGUgeyBDU1NQcm9wZXJ0aWVzLCBSZWYgfSBmcm9tICd2dWUnXHJcbmltcG9ydCB7IHVzZVZpZXdlckFuY2hvcmVkUG9pbnRzIH0gZnJvbSAnfn4vbGliL3ZpZXdlci9jb21wb3NhYmxlcy9hbmNob3JQb2ludHMnXHJcbmltcG9ydCB7IHVzZU9uQmVmb3JlV2luZG93VW5sb2FkIH0gZnJvbSAnfn4vbGliL2NvbW1vbi9jb21wb3NhYmxlcy93aW5kb3cnXHJcbmltcG9ydCB7IFRvYXN0Tm90aWZpY2F0aW9uVHlwZSwgdXNlR2xvYmFsVG9hc3QgfSBmcm9tICd+fi9saWIvY29tbW9uL2NvbXBvc2FibGVzL3RvYXN0J1xyXG5pbXBvcnQgeyBvblZpZXdlclVzZXJBY3Rpdml0eUJyb2FkY2FzdGVkU3Vic2NyaXB0aW9uIH0gZnJvbSAnfn4vbGliL3ZpZXdlci9ncmFwaHFsL3N1YnNjcmlwdGlvbnMnXHJcbmltcG9ydCB7IHVzZUVtYmVkIH0gZnJvbSAnfi9saWIvdmlld2VyL2NvbXBvc2FibGVzL3NldHVwL2VtYmVkJ1xyXG5cclxuaW1wb3J0IHtcclxuICBTdGF0ZUFwcGx5TW9kZSxcclxuICB1c2VBcHBseVNlcmlhbGl6ZWRTdGF0ZSxcclxuICB1c2VTdGF0ZVNlcmlhbGl6YXRpb25cclxufSBmcm9tICd+fi9saWIvdmlld2VyL2NvbXBvc2FibGVzL3NlcmlhbGl6YXRpb24nXHJcbmltcG9ydCB0eXBlIHsgTWVyZ2UsIE92ZXJyaWRlUHJvcGVydGllcyB9IGZyb20gJ3R5cGUtZmVzdCdcclxuaW1wb3J0IHsgZ3JhcGhxbCB9IGZyb20gJ34vbGliL2NvbW1vbi9nZW5lcmF0ZWQvZ3FsJ1xyXG5pbXBvcnQge1xyXG4gIGlzU2VyaWFsaXplZFZpZXdlclN0YXRlLFxyXG4gIHR5cGUgU2VyaWFsaXplZFZpZXdlclN0YXRlXHJcbn0gZnJvbSAnQHNwZWNrbGUvc2hhcmVkL3ZpZXdlci9zdGF0ZSdcclxuaW1wb3J0IHsgb21pdCwgZGVib3VuY2UgfSBmcm9tICdsb2Rhc2gtZXMnXHJcblxyXG4vKipcclxuICogSG93IG9mdGVuIHdlIHNlbmQgb3V0IGFuIFwiYWN0aXZpdHlcIiBtZXNzYWdlIGV2ZW4gaWYgdXNlciBoYXNuJ3QgbWFkZSBhbnkgY2xpY2tzIChqdXN0IHRvIGtlZXAgaGltIGFjdGl2ZSlcclxuICovXHJcbmNvbnN0IE9XTl9BQ1RJVklUWV9VUERBVEVfSU5URVJWQUwgPSA1ICogVElNRV9NUy5zZWNvbmRcclxuLyoqXHJcbiAqIEhvdyBvZnRlbiB3ZSBjaGVjayBmb3IgdXNlciBzdGFsZW5lc3NcclxuICovXHJcbmNvbnN0IFVTRVJfU1RBTEVfQ0hFQ0tfSU5URVJWQUwgPSAyMDAwXHJcbi8qKlxyXG4gKiBIb3cgbXVjaCB0aW1lIG11c3QgcGFzcyBhZnRlciBhbiB1cGRhdGUgZnJvbSB1c2VyIGFmdGVyIHdoaWNoIHdlIGNvbnNpZGVyIHRoZW0gXCJzdGFsZVwiIG9yIFwiZGlzY29ubmVjdGVkXCJcclxuICovXHJcbmNvbnN0IFVTRVJfU1RBTEVfQUZURVJfUEVSSU9EID0gMjAgKiBPV05fQUNUSVZJVFlfVVBEQVRFX0lOVEVSVkFMXHJcbi8qKlxyXG4gKiBIb3cgbXVjaCB0aW1lIG11c3QgcGFzcyBmb3IgYSB1c2VyIHRvIGJlIGNvbXBsZXRlbHkgcmVtb3ZhYmxlIGlmIGEgbmV3IHVwZGF0ZSBoYXNuJ3QgYmVlbiByZWNlaXZlZCBmcm9tIHRoZW1cclxuICovXHJcbmNvbnN0IFVTRVJfUkVNT1ZBQkxFX0FGVEVSX1BFUklPRCA9IFVTRVJfU1RBTEVfQUZURVJfUEVSSU9EICogMlxyXG5cclxudHlwZSBWaWV3ZXJBY3Rpdml0eU1ldGFkYXRhID0gT3ZlcnJpZGVQcm9wZXJ0aWVzPFxyXG4gIFJlcXVpcmVkPE9taXQ8Vmlld2VyVXNlckFjdGl2aXR5TWVzc2FnZUlucHV0LCAnc3RhdHVzJz4+LFxyXG4gIHsgc3RhdGU6IFNlcmlhbGl6ZWRWaWV3ZXJTdGF0ZSB9XHJcbj5cclxuXHJcbmZ1bmN0aW9uIHVzZUNvbGxlY3RNYWluTWV0YWRhdGEoKSB7XHJcbiAgY29uc3QgeyBzZXNzaW9uSWQgfSA9IHVzZUluamVjdGVkVmlld2VyU3RhdGUoKVxyXG4gIGNvbnN0IHsgYWN0aXZlVXNlciB9ID0gdXNlQWN0aXZlVXNlcigpXHJcbiAgY29uc3QgeyBzZXJpYWxpemUgfSA9IHVzZVN0YXRlU2VyaWFsaXphdGlvbigpXHJcbiAgcmV0dXJuICgpOiBWaWV3ZXJBY3Rpdml0eU1ldGFkYXRhID0+ICh7XHJcbiAgICB1c2VySWQ6IGFjdGl2ZVVzZXIudmFsdWU/LmlkIHx8IG51bGwsXHJcbiAgICB1c2VyTmFtZTogYWN0aXZlVXNlci52YWx1ZT8ubmFtZSB8fCAnQW5vbnltb3VzIFZpZXdlcicsXHJcbiAgICBzdGF0ZTogc2VyaWFsaXplKCksXHJcbiAgICBzZXNzaW9uSWQ6IHNlc3Npb25JZC52YWx1ZVxyXG4gIH0pXHJcbn1cclxuXHJcbmdyYXBocWwoYFxyXG4gIGZyYWdtZW50IFVzZVZpZXdlclVzZXJBY3Rpdml0eUJyb2FkY2FzdGluZ19Qcm9qZWN0IG9uIFByb2plY3Qge1xyXG4gICAgaWRcclxuICAgIHBlcm1pc3Npb25zIHtcclxuICAgICAgY2FuQnJvYWRjYXN0QWN0aXZpdHkge1xyXG4gICAgICAgIC4uLkZ1bGxQZXJtaXNzaW9uQ2hlY2tSZXN1bHRcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuYClcclxuXHJcbmNvbnN0IHVzZVZpZXdlclJlYWx0aW1lQWN0aXZpdHlTdGF0ZSA9ICgpID0+XHJcbiAgdXNlU3RhdGUoJ3ZpZXdlcl9yZWFsdGltZV9hY3Rpdml0eV9zdGF0ZScsICgpID0+ICh7XHJcbiAgICBhY3Rpdml0eTogdW5kZWZpbmVkIGFzIE9wdGlvbmFsPFZpZXdlckFjdGl2aXR5TWV0YWRhdGE+LFxyXG4gICAgc3RhdHVzOiBWaWV3ZXJVc2VyQWN0aXZpdHlTdGF0dXMuVmlld2luZyBhcyBWaWV3ZXJVc2VyQWN0aXZpdHlTdGF0dXNcclxuICB9KSlcclxuXHJcbmV4cG9ydCBjb25zdCB1c2VWaWV3ZXJSZWFsdGltZUFjdGl2aXR5VHJhY2tlciA9ICgpID0+IHtcclxuICBjb25zdCBzdGF0ZSA9IHVzZVZpZXdlclJlYWx0aW1lQWN0aXZpdHlTdGF0ZSgpXHJcbiAgY29uc3QgZ2V0TWFpbk1ldGFkYXRhID0gdXNlQ29sbGVjdE1haW5NZXRhZGF0YSgpXHJcblxyXG4gIGNvbnN0IHNlcmlhbGl6ZXIgPSAodmFsOiB1bmtub3duKSA9PiBKU09OLnN0cmluZ2lmeSh2YWwpXHJcblxyXG4gIGNvbnN0IGFjdGl2aXR5ID0gY29tcHV0ZWQoe1xyXG4gICAgZ2V0OiAoKSA9PiBzdGF0ZS52YWx1ZS5hY3Rpdml0eSB8fCBnZXRNYWluTWV0YWRhdGEoKSxcclxuICAgIHNldDogKHZhbHVlKSA9PiB7XHJcbiAgICAgIHN0YXRlLnZhbHVlLmFjdGl2aXR5ID0gdmFsdWVcclxuICAgIH1cclxuICB9KVxyXG5cclxuICBjb25zdCBzdGF0dXMgPSBjb21wdXRlZCh7XHJcbiAgICBnZXQ6ICgpID0+IHN0YXRlLnZhbHVlLnN0YXR1cyxcclxuICAgIHNldDogKHZhbHVlKSA9PiB7XHJcbiAgICAgIHN0YXRlLnZhbHVlLnN0YXR1cyA9IHZhbHVlXHJcbiAgICB9XHJcbiAgfSlcclxuXHJcbiAgY29uc3Qgc2VyaWFsaXplZFN0YXRlID0gY29tcHV0ZWQoKCkgPT4gYWN0aXZpdHkudmFsdWUuc3RhdGUpXHJcblxyXG4gIC8vIElkcyBmb3IgZWFzeSBlcXVhbGl0eSBjb21wYXJpc29uc1xyXG4gIGNvbnN0IHNlcmlhbGl6ZWRTdGF0ZUlkID0gY29tcHV0ZWQoKCkgPT4gc2VyaWFsaXplcihzZXJpYWxpemVkU3RhdGUudmFsdWUpKVxyXG4gIGNvbnN0IGFjdGl2aXR5SWQgPSBjb21wdXRlZCgoKSA9PiB7XHJcbiAgICBjb25zdCBzdGF0ZUlkID0gc2VyaWFsaXplZFN0YXRlSWQudmFsdWVcclxuICAgIGNvbnN0IG90aGVyQWN0aXZpdHk6IE9taXQ8Vmlld2VyQWN0aXZpdHlNZXRhZGF0YSwgJ3N0YXRlJz4gPSBvbWl0KGFjdGl2aXR5LnZhbHVlLCBbXHJcbiAgICAgICdzdGF0ZSdcclxuICAgIF0pXHJcbiAgICBjb25zdCBvdGhlckFjdGl2aXR5SWQgPSBzZXJpYWxpemVyKG90aGVyQWN0aXZpdHkpXHJcbiAgICByZXR1cm4gYCR7c3RhdGVJZH0tJHtvdGhlckFjdGl2aXR5SWR9LSR7c3RhdHVzLnZhbHVlfWBcclxuICB9KVxyXG5cclxuICBjb25zdCB1cGRhdGUgPSAocGFyYW1zPzoge1xyXG4gICAgbmV3QWN0aXZpdHk/OiBWaWV3ZXJBY3Rpdml0eU1ldGFkYXRhXHJcbiAgICBzdGF0dXM/OiBWaWV3ZXJVc2VyQWN0aXZpdHlTdGF0dXNcclxuICB9KSA9PiB7XHJcbiAgICBhY3Rpdml0eS52YWx1ZSA9IHBhcmFtcz8ubmV3QWN0aXZpdHkgfHwgZ2V0TWFpbk1ldGFkYXRhKClcclxuXHJcbiAgICBpZiAocGFyYW1zPy5zdGF0dXMpIHtcclxuICAgICAgc3RhdHVzLnZhbHVlID0gcGFyYW1zLnN0YXR1c1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25Vbm1vdW50ZWQoKCkgPT4ge1xyXG4gICAgLy8gUmVzZXQgYWN0aXZpdHkgc3RhdGUgb24gdW5tb3VudFxyXG4gICAgc3RhdGUudmFsdWUuYWN0aXZpdHkgPSB1bmRlZmluZWRcclxuICAgIHN0YXRlLnZhbHVlLnN0YXR1cyA9IFZpZXdlclVzZXJBY3Rpdml0eVN0YXR1cy5WaWV3aW5nXHJcbiAgfSlcclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIGFjdGl2aXR5LFxyXG4gICAgc2VyaWFsaXplZFN0YXRlLFxyXG4gICAgc3RhdHVzLFxyXG4gICAgdXBkYXRlLFxyXG4gICAgc2VyaWFsaXplZFN0YXRlSWQsXHJcbiAgICBhY3Rpdml0eUlkLFxyXG4gICAgc2VyaWFsaXplclxyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIHVzZVZpZXdlclVzZXJBY3Rpdml0eUJyb2FkY2FzdGluZyhcclxuICBvcHRpb25zPzogUGFydGlhbDx7XHJcbiAgICBzdGF0ZTogSW5qZWN0YWJsZVZpZXdlclN0YXRlXHJcbiAgfT5cclxuKSB7XHJcbiAgY29uc3Qge1xyXG4gICAgcHJvamVjdElkLFxyXG4gICAgcmVzb3VyY2VzOiB7XHJcbiAgICAgIHJlcXVlc3Q6IHsgcmVzb3VyY2VJZFN0cmluZyB9LFxyXG4gICAgICByZXNwb25zZTogeyBwcm9qZWN0IH1cclxuICAgIH1cclxuICB9ID0gb3B0aW9ucz8uc3RhdGUgfHwgdXNlSW5qZWN0ZWRWaWV3ZXJTdGF0ZSgpXHJcbiAgY29uc3Qge1xyXG4gICAgcHVibGljOiB7IGRpc2FibGVWaWV3ZXJBY3Rpdml0eUJyb2FkY2FzdGluZyB9XHJcbiAgfSA9IHVzZVJ1bnRpbWVDb25maWcoKVxyXG4gIGNvbnN0IHsgYWN0aXZlVXNlciB9ID0gdXNlQWN0aXZlVXNlcigpXHJcbiAgY29uc3QgeyB1cGRhdGUsIGFjdGl2aXR5LCBzdGF0dXMsIGFjdGl2aXR5SWQgfSA9IHVzZVZpZXdlclJlYWx0aW1lQWN0aXZpdHlUcmFja2VyKClcclxuICBjb25zdCBhcG9sbG8gPSB1c2VBcG9sbG9DbGllbnQoKS5jbGllbnRcclxuICBjb25zdCB7IGlzRW5hYmxlZDogaXNFbWJlZEVuYWJsZWQgfSA9IHVzZUVtYmVkKClcclxuXHJcbiAgY29uc3QgY2FuQnJvYWRjYXN0ID0gY29tcHV0ZWQoXHJcbiAgICAoKSA9PiBwcm9qZWN0LnZhbHVlPy5wZXJtaXNzaW9ucy5jYW5Ccm9hZGNhc3RBY3Rpdml0eS5hdXRob3JpemVkXHJcbiAgKVxyXG5cclxuICBjb25zdCBpc1NhbWVBY3Rpdml0eSA9IChcclxuICAgIHByZXZpb3VzQWN0aXZpdHlJZDogT3B0aW9uYWw8c3RyaW5nPixcclxuICAgIG5ld0FjdGl2aXR5SWQ6IHN0cmluZ1xyXG4gICkgPT4ge1xyXG4gICAgaWYgKHhvcihwcmV2aW91c0FjdGl2aXR5SWQsIG5ld0FjdGl2aXR5SWQpKSByZXR1cm4gZmFsc2VcclxuICAgIGlmICghcHJldmlvdXNBY3Rpdml0eUlkICYmICFuZXdBY3Rpdml0eUlkKSByZXR1cm4gZmFsc2VcclxuICAgIHJldHVybiBwcmV2aW91c0FjdGl2aXR5SWQgPT09IG5ld0FjdGl2aXR5SWRcclxuICB9XHJcblxyXG4gIGNvbnN0IGludm9rZU11dGF0aW9uID0gYXN5bmMgKCkgPT4ge1xyXG4gICAgaWYgKCFhY3RpdmVVc2VyLnZhbHVlPy5pZCB8fCBkaXNhYmxlVmlld2VyQWN0aXZpdHlCcm9hZGNhc3RpbmcpIHJldHVybiBmYWxzZVxyXG5cclxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGFwb2xsb1xyXG4gICAgICAubXV0YXRlKHtcclxuICAgICAgICBtdXRhdGlvbjogYnJvYWRjYXN0Vmlld2VyVXNlckFjdGl2aXR5TXV0YXRpb24sXHJcbiAgICAgICAgdmFyaWFibGVzOiB7XHJcbiAgICAgICAgICByZXNvdXJjZUlkU3RyaW5nOiByZXNvdXJjZUlkU3RyaW5nLnZhbHVlLFxyXG4gICAgICAgICAgbWVzc2FnZToge1xyXG4gICAgICAgICAgICAuLi5hY3Rpdml0eS52YWx1ZSxcclxuICAgICAgICAgICAgc3RhdHVzOiBzdGF0dXMudmFsdWUsXHJcbiAgICAgICAgICAgIHVzZXJJZDogYWN0aXZlVXNlci52YWx1ZS5pZCxcclxuICAgICAgICAgICAgdXNlck5hbWU6IGFjdGl2ZVVzZXIudmFsdWUubmFtZVxyXG4gICAgICAgICAgfSxcclxuICAgICAgICAgIHByb2plY3RJZDogcHJvamVjdElkLnZhbHVlXHJcbiAgICAgICAgfVxyXG4gICAgICB9KVxyXG4gICAgICAuY2F0Y2goY29udmVydFRocm93SW50b0ZldGNoUmVzdWx0KVxyXG5cclxuICAgIHJldHVybiByZXN1bHQuZGF0YT8uYnJvYWRjYXN0Vmlld2VyVXNlckFjdGl2aXR5IHx8IGZhbHNlXHJcbiAgfVxyXG5cclxuICBsZXQgcHJldmlvdXNBY3Rpdml0eUlkOiBPcHRpb25hbDxzdHJpbmc+ID0gdW5kZWZpbmVkXHJcbiAgY29uc3QgaW52b2tlT2JzZXJ2YWJpbGl0eUV2ZW50ID0gYXN5bmMgKCkgPT4ge1xyXG4gICAgY29uc3QgZGQgPSB3aW5kb3cuRERfUlVNXHJcbiAgICBpZiAoIWRkIHx8ICEoJ2FkZEFjdGlvbicgaW4gZGQpKSByZXR1cm5cclxuXHJcbiAgICBjb25zdCBtZXNzYWdlID0ge1xyXG4gICAgICAuLi5hY3Rpdml0eS52YWx1ZSxcclxuICAgICAgc3RhdHVzOiBzdGF0dXMudmFsdWVcclxuICAgIH1cclxuXHJcbiAgICBpZiAoaXNTYW1lQWN0aXZpdHkocHJldmlvdXNBY3Rpdml0eUlkLCBhY3Rpdml0eUlkLnZhbHVlKSkgcmV0dXJuXHJcblxyXG4gICAgcHJldmlvdXNBY3Rpdml0eUlkID0gYWN0aXZpdHlJZC52YWx1ZVxyXG4gICAgZGQuYWRkQWN0aW9uKCdWaWV3ZXIgVXNlciBBY3Rpdml0eScsIHsgbWVzc2FnZSB9KVxyXG4gIH1cclxuXHJcbiAgY29uc3QgaW52b2tlID0gYXN5bmMgKCkgPT4ge1xyXG4gICAgaWYgKCFjYW5Ccm9hZGNhc3QudmFsdWUgfHwgaXNFbWJlZEVuYWJsZWQudmFsdWUpIHJldHVybiBmYWxzZVxyXG5cclxuICAgIHJldHVybiBhd2FpdCBQcm9taXNlLmFsbChbaW52b2tlTXV0YXRpb24oKSwgaW52b2tlT2JzZXJ2YWJpbGl0eUV2ZW50KCldKVxyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHtcclxuICAgIGVtaXREaXNjb25uZWN0ZWQ6IGFzeW5jICgpID0+IHtcclxuICAgICAgdXBkYXRlKHsgc3RhdHVzOiBWaWV3ZXJVc2VyQWN0aXZpdHlTdGF0dXMuRGlzY29ubmVjdGVkIH0pXHJcbiAgICAgIGF3YWl0IGludm9rZSgpXHJcbiAgICB9LFxyXG4gICAgZW1pdFZpZXdpbmc6IGFzeW5jICgpID0+IHtcclxuICAgICAgdXBkYXRlKHsgc3RhdHVzOiBWaWV3ZXJVc2VyQWN0aXZpdHlTdGF0dXMuVmlld2luZyB9KVxyXG4gICAgICBhd2FpdCBpbnZva2UoKVxyXG4gICAgfVxyXG4gIH1cclxufVxyXG5cclxuZXhwb3J0IHR5cGUgVXNlckFjdGl2aXR5TW9kZWwgPSBNZXJnZTxcclxuICBPblZpZXdlclVzZXJBY3Rpdml0eUJyb2FkY2FzdGVkU3Vic2NyaXB0aW9uWyd2aWV3ZXJVc2VyQWN0aXZpdHlCcm9hZGNhc3RlZCddLFxyXG4gIHsgc3RhdGU6IFNlcmlhbGl6ZWRWaWV3ZXJTdGF0ZSB9XHJcbj4gJiB7XHJcbiAgaXNTdGFsZTogYm9vbGVhblxyXG4gIGlzT2NjbHVkZWQ6IGJvb2xlYW5cclxuICBsYXN0VXBkYXRlOiBEYXlqc1xyXG4gIGlzQ2xpcHBlZDogYm9vbGVhblxyXG4gIHByb2plY3RlZFBvc2l0aW9uOiBbbnVtYmVyLCBudW1iZXJdXHJcbiAgc3R5bGU6IHtcclxuICAgIHRhcmdldDogUGFydGlhbDxDU1NQcm9wZXJ0aWVzPlxyXG4gIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFRyYWNrIG90aGVyIHVzZXIgYWN0aXZpdHkgYW5kIGVtaXQgdmlld2luZy9kaXNjb25uZWN0ZWQgdXBkYXRlc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHVzZVZpZXdlclVzZXJBY3Rpdml0eVRyYWNraW5nKFxyXG4gIHBhcmFtcz86IFBhcnRpYWw8e1xyXG4gICAgLyoqXHJcbiAgICAgKiBTZXQgaWYgeW91IG5lZWQgdXNlcnMgdG8gYmUgcG9zaXRpb25lZCBjb3JyZWN0bHkgaW4gdmlld2VyIHdvcmxkIHNwYWNlIGluIGFuIG92ZXJsYWlkIGFuY2hvcmVkIHBvaW50cyBlbGVtZW50XHJcbiAgICAgKi9cclxuICAgIGFuY2hvcmVkUG9pbnRzUGFyZW50RWw6IFJlZjxOdWxsYWJsZTxIVE1MRWxlbWVudD4+XHJcbiAgICAvKipcclxuICAgICAqIFdoZXRoZXIgdG8gb25seSB0cmFjayB2aWV3ZXIgc3RhdGUgY2hhbmdlcywgd2l0aG91dCBicm9hZGNhc3RpbmcgaXQgdG8gb3RoZXIgdXNlcnMgb3IgZ2V0dGluZyB1cGRhdGVzIGZyb20gdGhlbVxyXG4gICAgICovXHJcbiAgICB0cmFja0ludGVybmFsbHlPbmx5OiBib29sZWFuXHJcbiAgfT5cclxuKSB7XHJcbiAgY29uc3QgeyBhbmNob3JlZFBvaW50c1BhcmVudEVsOiBwYXJlbnRFbCwgdHJhY2tJbnRlcm5hbGx5T25seSB9ID0gcGFyYW1zIHx8IHt9XHJcblxyXG4gIGNvbnN0IHtcclxuICAgIHByb2plY3RJZCxcclxuICAgIHNlc3Npb25JZCxcclxuICAgIHJlc291cmNlczoge1xyXG4gICAgICByZXF1ZXN0OiB7IHJlc291cmNlSWRTdHJpbmcsIHRocmVhZEZpbHRlcnMgfVxyXG4gICAgfVxyXG4gIH0gPSB1c2VJbmplY3RlZFZpZXdlclN0YXRlKClcclxuICBjb25zdCB7IGlzTG9nZ2VkSW4gfSA9IHVzZUFjdGl2ZVVzZXIoKVxyXG4gIGNvbnN0IHsgdHJpZ2dlck5vdGlmaWNhdGlvbiB9ID0gdXNlR2xvYmFsVG9hc3QoKVxyXG4gIGNvbnN0IHsgdXBkYXRlIH0gPSB1c2VWaWV3ZXJSZWFsdGltZUFjdGl2aXR5VHJhY2tlcigpXHJcbiAgY29uc3Qgc2VuZFVwZGF0ZSA9IHVzZVZpZXdlclVzZXJBY3Rpdml0eUJyb2FkY2FzdGluZygpXHJcbiAgY29uc3QgeyBpc0VuYWJsZWQ6IGlzRW1iZWRFbmFibGVkIH0gPSB1c2VFbWJlZCgpXHJcbiAgY29uc3QgeyBhY3RpdmVVc2VyIH0gPSB1c2VBY3RpdmVVc2VyKClcclxuXHJcbiAgY29uc3QgcHJvY2Vzc1ZpZXdlclZpZXdpbmcgPSBhc3luYyAoKSA9PiB7XHJcbiAgICBpZiAodHJhY2tJbnRlcm5hbGx5T25seSkge1xyXG4gICAgICB1cGRhdGUoeyBzdGF0dXM6IFZpZXdlclVzZXJBY3Rpdml0eVN0YXR1cy5WaWV3aW5nIH0pXHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBhd2FpdCBzZW5kVXBkYXRlLmVtaXRWaWV3aW5nKClcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IHByb2Nlc3NWaWV3ZXJEaXNjb25uZWN0ZWQgPSBhc3luYyAoKSA9PiB7XHJcbiAgICBpZiAodHJhY2tJbnRlcm5hbGx5T25seSkge1xyXG4gICAgICB1cGRhdGUoeyBzdGF0dXM6IFZpZXdlclVzZXJBY3Rpdml0eVN0YXR1cy5EaXNjb25uZWN0ZWQgfSlcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGF3YWl0IHNlbmRVcGRhdGUuZW1pdERpc2Nvbm5lY3RlZCgpXHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBUT0RPOiBGb3Igc29tZSByZWFzb24gc3Vic2NyaXB0aW9uIGlzIHNldCB1cCB0d2ljZT8gVnVlIEFwb2xsbyBidWc/XHJcbiAgY29uc3QgeyBvblJlc3VsdDogb25Vc2VyQWN0aXZpdHkgfSA9IHVzZVN1YnNjcmlwdGlvbihcclxuICAgIG9uVmlld2VyVXNlckFjdGl2aXR5QnJvYWRjYXN0ZWRTdWJzY3JpcHRpb24sXHJcbiAgICAoKSA9PiAoe1xyXG4gICAgICB0YXJnZXQ6IHtcclxuICAgICAgICBwcm9qZWN0SWQ6IHByb2plY3RJZC52YWx1ZSxcclxuICAgICAgICByZXNvdXJjZUlkU3RyaW5nOiByZXNvdXJjZUlkU3RyaW5nLnZhbHVlLFxyXG4gICAgICAgIGxvYWRlZFZlcnNpb25zT25seTogdGhyZWFkRmlsdGVycy52YWx1ZS5sb2FkZWRWZXJzaW9uc09ubHlcclxuICAgICAgfSxcclxuICAgICAgc2Vzc2lvbklkOiBzZXNzaW9uSWQudmFsdWVcclxuICAgIH0pLFxyXG4gICAgKCkgPT4gKHtcclxuICAgICAgZW5hYmxlZDogaXNMb2dnZWRJbi52YWx1ZSAmJiAhdHJhY2tJbnRlcm5hbGx5T25seSxcclxuICAgICAgZXJyb3JQb2xpY3k6ICdhbGwnXHJcbiAgICB9KVxyXG4gIClcclxuXHJcbiAgY29uc3QgdXNlcnMgPSByZWYoe30gYXMgUmVjb3JkPHN0cmluZywgVXNlckFjdGl2aXR5TW9kZWw+KVxyXG4gIGNvbnN0IHsgc3BvdGxpZ2h0VXNlclNlc3Npb25JZCB9ID0gdXNlSW5qZWN0ZWRWaWV3ZXJJbnRlcmZhY2VTdGF0ZSgpXHJcbiAgY29uc3Qgc3BvdGxpZ2h0VHJhY2tlciA9IHVzZVZpZXdlclNwb3RsaWdodFRyYWNraW5nKClcclxuXHJcbiAgb25Vc2VyQWN0aXZpdHkoKHJlcykgPT4ge1xyXG4gICAgLy8gVE9USElOSy9UT0RPOiBpbnN0ZWFkIG9mIGZhc3QgT1dOX0FDVElWSVRZX1VQREFURV9JTlRFUlZBTCwgd2UgY291bGRcclxuICAgIC8vIHNlbmQgYW4gZXZlbnQgd2hlbiB3ZSBpZGVudGlmeSBoZXJlIHRoYXQgYSBuZXcgdXNlciBqb2luZWQgdGhlIHBhcnR5XHJcblxyXG4gICAgaWYgKCFyZXMuZGF0YT8udmlld2VyVXNlckFjdGl2aXR5QnJvYWRjYXN0ZWQpIHJldHVyblxyXG4gICAgY29uc3QgZXZlbnQgPSByZXMuZGF0YS52aWV3ZXJVc2VyQWN0aXZpdHlCcm9hZGNhc3RlZFxyXG4gICAgY29uc3Qgc3RhdHVzID0gZXZlbnQuc3RhdHVzXHJcbiAgICBjb25zdCBpbmNvbWluZ1Nlc3Npb25JZCA9IGV2ZW50LnNlc3Npb25JZFxyXG4gICAgY29uc3QgaW5jb21pbmdVc2VySWQgPSBldmVudC51c2VySWRcclxuXHJcbiAgICAvLyBQcmV2ZW50IHVzZXJzIGZyb20gc2VlaW5nIHRoZWlyIG93biBhY3Rpdml0eSBub3RpZmljYXRpb25zXHJcbiAgICBjb25zdCBjdXJyZW50VXNlcklkID0gYWN0aXZlVXNlci52YWx1ZT8uaWRcclxuXHJcbiAgICBpZiAoc2Vzc2lvbklkLnZhbHVlID09PSBpbmNvbWluZ1Nlc3Npb25JZCkgcmV0dXJuXHJcbiAgICBpZiAoY3VycmVudFVzZXJJZCAmJiBpbmNvbWluZ1VzZXJJZCAmJiBjdXJyZW50VXNlcklkID09PSBpbmNvbWluZ1VzZXJJZCkgcmV0dXJuXHJcblxyXG4gICAgaWYgKCFpc0VtYmVkRW5hYmxlZC52YWx1ZSAmJiBzdGF0dXMgPT09IFZpZXdlclVzZXJBY3Rpdml0eVN0YXR1cy5EaXNjb25uZWN0ZWQpIHtcclxuICAgICAgY29uc3QgZGlzY29ubmVjdGluZ1VzZXIgPSB1c2Vycy52YWx1ZVtpbmNvbWluZ1Nlc3Npb25JZF1cclxuXHJcbiAgICAgIC8vIENoZWNrIGlmIHRoaXMgdXNlciBoYXMgb3RoZXIgYWN0aXZlIHNlc3Npb25zIGJlZm9yZSBzaG93aW5nIFwibGVmdFwiIG5vdGlmaWNhdGlvblxyXG4gICAgICBjb25zdCBoYXNPdGhlckFjdGl2ZVNlc3Npb25zID0gaW5jb21pbmdVc2VySWRcclxuICAgICAgICA/IE9iamVjdC52YWx1ZXModXNlcnMudmFsdWUpLnNvbWUoXHJcbiAgICAgICAgICAgICh1c2VyKSA9PlxyXG4gICAgICAgICAgICAgIHVzZXIudXNlcklkID09PSBpbmNvbWluZ1VzZXJJZCAmJiB1c2VyLnNlc3Npb25JZCAhPT0gaW5jb21pbmdTZXNzaW9uSWRcclxuICAgICAgICAgIClcclxuICAgICAgICA6IGZhbHNlXHJcblxyXG4gICAgICAvLyBPbmx5IHNob3cgXCJsZWZ0XCIgbm90aWZpY2F0aW9uIGlmIHRoaXMgaXMgdGhlIHVzZXIncyBsYXN0IHNlc3Npb25cclxuICAgICAgaWYgKGRpc2Nvbm5lY3RpbmdVc2VyICYmICFoYXNPdGhlckFjdGl2ZVNlc3Npb25zKSB7XHJcbiAgICAgICAgdHJpZ2dlck5vdGlmaWNhdGlvbih7XHJcbiAgICAgICAgICB0aXRsZTogYCR7ZGlzY29ubmVjdGluZ1VzZXIudXNlck5hbWUgfHwgJ0EgdXNlcid9IGxlZnQuYCxcclxuICAgICAgICAgIHR5cGU6IFRvYXN0Tm90aWZpY2F0aW9uVHlwZS5JbmZvXHJcbiAgICAgICAgfSlcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHNwb3RsaWdodFVzZXJTZXNzaW9uSWQudmFsdWUgPT09IGluY29taW5nU2Vzc2lvbklkKVxyXG4gICAgICAgIHNwb3RsaWdodFVzZXJTZXNzaW9uSWQudmFsdWUgPSBudWxsIC8vIGVuc3VyZSB3ZSdyZSBub3Qgc3BvdGxpZ2h0aW5nIGRpc2Nvbm5lY3RlZCB1c2Vyc1xyXG4gICAgICBkZWxldGUgdXNlcnMudmFsdWVbaW5jb21pbmdTZXNzaW9uSWRdXHJcbiAgICAgIHJldHVyblxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHN0YXRlID0gaXNTZXJpYWxpemVkVmlld2VyU3RhdGUoZXZlbnQuc3RhdGUpID8gZXZlbnQuc3RhdGUgOiBudWxsXHJcbiAgICBpZiAoIXN0YXRlKSByZXR1cm5cclxuXHJcbiAgICBjb25zdCB1c2VyRGF0YTogVXNlckFjdGl2aXR5TW9kZWwgPSB7XHJcbiAgICAgIC4uLih1c2Vycy52YWx1ZVtpbmNvbWluZ1Nlc3Npb25JZF1cclxuICAgICAgICA/IHVzZXJzLnZhbHVlW2luY29taW5nU2Vzc2lvbklkXVxyXG4gICAgICAgIDoge1xyXG4gICAgICAgICAgICBpc0NsaXBwZWQ6IGZhbHNlLFxyXG4gICAgICAgICAgICBwcm9qZWN0ZWRQb3NpdGlvbjogWzAsIDBdLFxyXG4gICAgICAgICAgICBzdHlsZTogeyB0YXJnZXQ6IHt9IH0sXHJcbiAgICAgICAgICAgIGlzT2NjbHVkZWQ6IGZhbHNlXHJcbiAgICAgICAgICB9KSxcclxuICAgICAgLi4uZXZlbnQsXHJcbiAgICAgIHN0YXRlLFxyXG4gICAgICBpc1N0YWxlOiBmYWxzZSxcclxuICAgICAgbGFzdFVwZGF0ZTogZGF5anMoKVxyXG4gICAgfVxyXG5cclxuICAgIC8vIE9ubHkgc2hvdyBcImpvaW5lZFwiIG5vdGlmaWNhdGlvbiBpZiB0aGlzIGlzIGEgbmV3IHVzZXIgKG5vdCBqdXN0IGEgbmV3IHNlc3Npb24gZm9yIGV4aXN0aW5nIHVzZXIpXHJcbiAgICBjb25zdCBpc05ld1Nlc3Npb24gPSAhT2JqZWN0LmtleXModXNlcnMudmFsdWUpLmluY2x1ZGVzKGluY29taW5nU2Vzc2lvbklkKVxyXG4gICAgY29uc3QgaGFzRXhpc3RpbmdVc2VyU2Vzc2lvbnMgPSBpbmNvbWluZ1VzZXJJZFxyXG4gICAgICA/IE9iamVjdC52YWx1ZXModXNlcnMudmFsdWUpLnNvbWUoKHVzZXIpID0+IHVzZXIudXNlcklkID09PSBpbmNvbWluZ1VzZXJJZClcclxuICAgICAgOiBmYWxzZVxyXG5cclxuICAgIGlmICghaXNFbWJlZEVuYWJsZWQudmFsdWUgJiYgaXNOZXdTZXNzaW9uICYmICFoYXNFeGlzdGluZ1VzZXJTZXNzaW9ucykge1xyXG4gICAgICB0cmlnZ2VyTm90aWZpY2F0aW9uKHtcclxuICAgICAgICB0aXRsZTogYCR7dXNlckRhdGEudXNlck5hbWV9IGpvaW5lZC5gLFxyXG4gICAgICAgIHR5cGU6IFRvYXN0Tm90aWZpY2F0aW9uVHlwZS5JbmZvXHJcbiAgICAgIH0pXHJcbiAgICB9XHJcblxyXG4gICAgdXNlcnMudmFsdWVbaW5jb21pbmdTZXNzaW9uSWRdID0gdXNlckRhdGFcclxuXHJcbiAgICBpZiAoc3BvdGxpZ2h0VXNlclNlc3Npb25JZC52YWx1ZSA9PT0gdXNlckRhdGEuc2Vzc2lvbklkKSB7XHJcbiAgICAgIHNwb3RsaWdodFRyYWNrZXIodXNlckRhdGEpXHJcbiAgICB9XHJcbiAgfSlcclxuXHJcbiAgaWYgKHBhcmVudEVsKSB7XHJcbiAgICB1c2VWaWV3ZXJBbmNob3JlZFBvaW50czxVc2VyQWN0aXZpdHlNb2RlbCwgUGFydGlhbDx7IHNtb290aFRyYW5zbGF0aW9uOiBib29sZWFuIH0+PihcclxuICAgICAge1xyXG4gICAgICAgIHBhcmVudEVsLFxyXG4gICAgICAgIHBvaW50czogY29tcHV0ZWQoKCkgPT4gT2JqZWN0LnZhbHVlcyh1c2Vycy52YWx1ZSkpLFxyXG4gICAgICAgIHBvaW50TG9jYXRpb25HZXR0ZXI6ICh1c2VyKSA9PiB7XHJcbiAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB1c2VyLnN0YXRlLnVpLnNlbGVjdGlvblxyXG4gICAgICAgICAgY29uc3Qgc2VsZWN0aW9uVmVjdG9yID0gc2VsZWN0aW9uXHJcbiAgICAgICAgICAgID8gbmV3IFZlY3RvcjMoc2VsZWN0aW9uWzBdLCBzZWxlY3Rpb25bMV0sIHNlbGVjdGlvblsyXSlcclxuICAgICAgICAgICAgOiBudWxsXHJcblxyXG4gICAgICAgICAgZnVuY3Rpb24gZ2V0UG9pbnRJbkJldHdlZW5CeVBlcmMoXHJcbiAgICAgICAgICAgIHBvaW50QTogVmVjdG9yMyxcclxuICAgICAgICAgICAgcG9pbnRCOiBWZWN0b3IzLFxyXG4gICAgICAgICAgICBwZXJjZW50YWdlOiBudW1iZXJcclxuICAgICAgICAgICkge1xyXG4gICAgICAgICAgICBsZXQgZGlyID0gcG9pbnRCLmNsb25lKCkuc3ViKHBvaW50QSlcclxuICAgICAgICAgICAgY29uc3QgbGVuID0gZGlyLmxlbmd0aCgpXHJcbiAgICAgICAgICAgIGRpciA9IGRpci5ub3JtYWxpemUoKS5tdWx0aXBseVNjYWxhcihsZW4gKiBwZXJjZW50YWdlKVxyXG4gICAgICAgICAgICByZXR1cm4gcG9pbnRBLmNsb25lKCkuYWRkKGRpcilcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBubyBzZWxlY3Rpb24gbG9jYXRpb24sIHJldHVybiB0byBhIGJsZW5kZWQgbG9jYXRpb24gYmFzZWQgb24gdGhlIGNhbWVyYSdzIHRhcmdldCBhbmQgbG9jYXRpb24uXHJcbiAgICAgICAgICAvLyBUaGlzIGVuc3VyZXMgdGhhdCByb3RhdGlvbiBhbmQgem9vbSB3aWxsIGhhdmUgYW4gZWZmZWN0IG9uIHRoZSB1c2VycycgY3Vyc29ycyBhbmQgY3JlYXRlIGEgbGl2ZWx5IGVudmlyb25tZW50LlxyXG4gICAgICAgICAgaWYgKCFzZWxlY3Rpb25WZWN0b3IpIHtcclxuICAgICAgICAgICAgY29uc3QgY2FtUG9zID0gdXNlci5zdGF0ZS51aS5jYW1lcmEucG9zaXRpb25cclxuICAgICAgICAgICAgY29uc3QgY2FtUG9zVmVjdG9yID0gbmV3IFZlY3RvcjMoY2FtUG9zWzBdLCBjYW1Qb3NbMV0sIGNhbVBvc1syXSlcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGNhbVRhcmdldCA9IHVzZXIuc3RhdGUudWkuY2FtZXJhLnRhcmdldFxyXG4gICAgICAgICAgICBjb25zdCBjYW1UYXJnZXRWZWN0b3IgPSBuZXcgVmVjdG9yMyhcclxuICAgICAgICAgICAgICBjYW1UYXJnZXRbMF0sXHJcbiAgICAgICAgICAgICAgY2FtVGFyZ2V0WzFdLFxyXG4gICAgICAgICAgICAgIGNhbVRhcmdldFsyXVxyXG4gICAgICAgICAgICApXHJcblxyXG4gICAgICAgICAgICByZXR1cm4gZ2V0UG9pbnRJbkJldHdlZW5CeVBlcmMoY2FtVGFyZ2V0VmVjdG9yLCBjYW1Qb3NWZWN0b3IsIDAuMilcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICByZXR1cm4gc2VsZWN0aW9uVmVjdG9yLmNsb25lKClcclxuICAgICAgICB9LFxyXG4gICAgICAgIHVwZGF0ZVBvc2l0aW9uQ2FsbGJhY2s6ICh1c2VyLCByZXN1bHQsIG9wdGlvbnMpID0+IHtcclxuICAgICAgICAgIHVzZXIuaXNPY2NsdWRlZCA9IHJlc3VsdC5pc09jY2x1ZGVkXHJcbiAgICAgICAgICB1c2VyLnN0eWxlID0ge1xyXG4gICAgICAgICAgICAuLi51c2VyLnN0eWxlLFxyXG4gICAgICAgICAgICB0YXJnZXQ6IHtcclxuICAgICAgICAgICAgICAuLi51c2VyLnN0eWxlLnRhcmdldCxcclxuICAgICAgICAgICAgICAuLi5yZXN1bHQuc3R5bGUsXHJcbiAgICAgICAgICAgICAgdHJhbnNpdGlvbjogb3B0aW9ucz8uc21vb3RoVHJhbnNsYXRpb24gPT09IGZhbHNlID8gJycgOiAnYWxsIDAuMXMgZWFzZSdcclxuICAgICAgICAgICAgICAvLyBvcGFjaXR5OiB1c2VyLmlzT2NjbHVkZWQgPyAnMC41JyA6IHVzZXIuaXNTdGFsZSA/ICcwLjInIDogJzEuMCcgLy8gbm90ZTogaGFuZGxlZCBpbiBjb21wb25lbnQgdmlhIGNzc1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICApXHJcbiAgfVxyXG5cclxuICBjb25zdCBoaWRlU3RhbGVVc2VycyA9ICgpID0+IHtcclxuICAgIGlmICghT2JqZWN0LnZhbHVlcyh1c2Vycy52YWx1ZSkubGVuZ3RoKSByZXR1cm5cclxuXHJcbiAgICAvLyBNYXJrIHN0YWxlIHVzZXJzXHJcbiAgICBmb3IgKGNvbnN0IFtrZXksIHVzZXJdIG9mIE9iamVjdC5lbnRyaWVzKHVzZXJzLnZhbHVlKSkge1xyXG4gICAgICB1c2VyLmlzU3RhbGUgPSB1c2VyLmxhc3RVcGRhdGUuaXNCZWZvcmUoXHJcbiAgICAgICAgZGF5anMoKS5zdWJ0cmFjdChVU0VSX1NUQUxFX0FGVEVSX1BFUklPRCwgJ21pbGxpc2Vjb25kcycpXHJcbiAgICAgIClcclxuXHJcbiAgICAgIC8vIFJlbW92ZSBhbHRvZ2V0aGVyIGlmIHN0YWxlIGZvciBhIHdoaWxlXHJcbiAgICAgIGlmIChcclxuICAgICAgICB1c2VyLmxhc3RVcGRhdGUuaXNCZWZvcmUoXHJcbiAgICAgICAgICBkYXlqcygpLnN1YnRyYWN0KFVTRVJfUkVNT1ZBQkxFX0FGVEVSX1BFUklPRCwgJ21pbGxpc2Vjb25kJylcclxuICAgICAgICApXHJcbiAgICAgICkge1xyXG4gICAgICAgIGRlbGV0ZSB1c2Vycy52YWx1ZVtrZXldXHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbnN0IGZvY3VzZWQgPSB1c2VXaW5kb3dGb2N1cygpXHJcblxyXG4gIC8vIERlYm91bmNlZCBkaXNjb25uZWN0IGZ1bmN0aW9uIC0gMzAgc2Vjb25kIGRlbGF5XHJcbiAgY29uc3QgZGVib3VuY2VkRGlzY29ubmVjdCA9IGRlYm91bmNlKFxyXG4gICAgYXN5bmMgKCkgPT4ge1xyXG4gICAgICBhd2FpdCBwcm9jZXNzVmlld2VyRGlzY29ubmVjdGVkKClcclxuICAgIH0sXHJcbiAgICAzMCAqIDEwMDAgLy8gMzAgc2Vjb25kc1xyXG4gIClcclxuXHJcbiAgd2F0Y2goZm9jdXNlZCwgYXN5bmMgKG5ld1ZhbCkgPT4ge1xyXG4gICAgaWYgKCFuZXdWYWwpIHtcclxuICAgICAgLy8gV2luZG93IGxvc3QgZm9jdXMgLSBzdGFydCBkZWJvdW5jZWQgZGlzY29ubmVjdFxyXG4gICAgICBkZWJvdW5jZWREaXNjb25uZWN0KClcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIFdpbmRvdyByZWdhaW5lZCBmb2N1cyAtIGNhbmNlbCBhbnkgcGVuZGluZyBkaXNjb25uZWN0IGFuZCBlbWl0IHZpZXdpbmdcclxuICAgICAgZGVib3VuY2VkRGlzY29ubmVjdC5jYW5jZWwoKVxyXG4gICAgICBhd2FpdCBwcm9jZXNzVmlld2VyVmlld2luZygpXHJcbiAgICB9XHJcbiAgfSlcclxuICBjb25zdCBzZW5kVXBkYXRlQW5kSGlkZVN0YWxlVXNlcnMgPSAoKSA9PiB7XHJcbiAgICBpZiAoIWZvY3VzZWQudmFsdWUpIHJldHVyblxyXG4gICAgaGlkZVN0YWxlVXNlcnMoKVxyXG4gICAgcHJvY2Vzc1ZpZXdlclZpZXdpbmcoKVxyXG4gIH1cclxuXHJcbiAgdXNlSW50ZXJ2YWxGbihzZW5kVXBkYXRlQW5kSGlkZVN0YWxlVXNlcnMsIE9XTl9BQ1RJVklUWV9VUERBVEVfSU5URVJWQUwpXHJcbiAgdXNlSW50ZXJ2YWxGbihoaWRlU3RhbGVVc2VycywgVVNFUl9TVEFMRV9DSEVDS19JTlRFUlZBTClcclxuXHJcbiAgY29uc3Qgc2VsZWN0aW9uQ2FsbGJhY2sgPSAoKSA9PiB7XHJcbiAgICAvLyB0byBlbnN1cmUgdGhhdCB1c2VDb2xsZWN0U2VsZWN0aW9uKCkgd29ya3MgZmlyc3RcclxuICAgIG5leHRUaWNrKCgpID0+IHNlbmRVcGRhdGVBbmRIaWRlU3RhbGVVc2VycygpKVxyXG4gIH1cclxuICB1c2VTZWxlY3Rpb25FdmVudHMoe1xyXG4gICAgc2luZ2xlQ2xpY2tDYWxsYmFjazogc2VsZWN0aW9uQ2FsbGJhY2ssXHJcbiAgICBkb3VibGVDbGlja0NhbGxiYWNrOiBzZWxlY3Rpb25DYWxsYmFja1xyXG4gIH0pXHJcblxyXG4gIHVzZVZpZXdlckNhbWVyYUNvbnRyb2xFbmRUcmFja2VyKCgpID0+IHByb2Nlc3NWaWV3ZXJWaWV3aW5nKCkpXHJcblxyXG4gIHVzZU9uQmVmb3JlV2luZG93VW5sb2FkKGFzeW5jICgpID0+IHtcclxuICAgIC8vIENhbmNlbCBhbnkgcGVuZGluZyBkZWJvdW5jZWQgZGlzY29ubmVjdCBzaW5jZSB3ZSdyZSBhY3R1YWxseSBsZWF2aW5nXHJcbiAgICBkZWJvdW5jZWREaXNjb25uZWN0LmNhbmNlbCgpXHJcbiAgICBhd2FpdCBwcm9jZXNzVmlld2VyRGlzY29ubmVjdGVkKClcclxuICB9KVxyXG5cclxuICBvbk1vdW50ZWQoKCkgPT4ge1xyXG4gICAgcHJvY2Vzc1ZpZXdlclZpZXdpbmcoKVxyXG4gIH0pXHJcblxyXG4gIG9uQmVmb3JlVW5tb3VudCgoKSA9PiB7XHJcbiAgICAvLyBDYW5jZWwgYW55IHBlbmRpbmcgZGVib3VuY2VkIGRpc2Nvbm5lY3RcclxuICAgIGRlYm91bmNlZERpc2Nvbm5lY3QuY2FuY2VsKClcclxuICAgIHZvaWQgcHJvY2Vzc1ZpZXdlckRpc2Nvbm5lY3RlZCgpXHJcbiAgfSlcclxuXHJcbiAgY29uc3Qgc3RhdGUgPSB1c2VJbmplY3RlZFZpZXdlclN0YXRlKClcclxuXHJcbiAgLy8gUmVtb3ZlcyBvYmplY3QgaGlnaGxpZ2h0cyBmcm9tIHVzZXIgc2VsZWN0aW9uIG9uIHRyYWNraW5nIHN0b3A7XHJcbiAgLy8gU2V0cyBpbml0aWFsIHVzZXIgc3RhdGUgb24gdHJhY2tpbmcgc3RhcnRcclxuICB3YXRjaChzcG90bGlnaHRVc2VyU2Vzc2lvbklkLCAobmV3VmFsKSA9PiB7XHJcbiAgICBpZiAoIW5ld1ZhbCkge1xyXG4gICAgICBzdGF0ZS51aS5oaWdobGlnaHRlZE9iamVjdElkcy52YWx1ZSA9IFtdXHJcbiAgICAgIHJldHVyblxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHVzZXIgPSBPYmplY3QudmFsdWVzKHVzZXJzLnZhbHVlKS5maW5kKCh1KSA9PiB1LnNlc3Npb25JZCA9PT0gbmV3VmFsKVxyXG4gICAgaWYgKCF1c2VyKSByZXR1cm5cclxuICAgIHNwb3RsaWdodFRyYWNrZXIodXNlcilcclxuICB9KVxyXG5cclxuICB3YXRjaChyZXNvdXJjZUlkU3RyaW5nLCAobmV3VmFsLCBvbGRWYWwpID0+IHtcclxuICAgIGlmIChuZXdWYWwgIT09IG9sZFZhbCkge1xyXG4gICAgICB2b2lkIHByb2Nlc3NWaWV3ZXJWaWV3aW5nKClcclxuICAgIH1cclxuICB9KVxyXG5cclxuICByZXR1cm4ge1xyXG4gICAgdXNlcnNcclxuICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBUT0RPOlxyXG4gKiAtIE1vdmUgdXNlciBhY3Rpdml0eS90aHJlYWQgc3R1ZmYgdG8gc2V0dXAgc28gdGhhdCBpdCBpc24ndCBzdHJld24gYWJvdXRcclxuICovXHJcblxyXG5mdW5jdGlvbiB1c2VWaWV3ZXJTcG90bGlnaHRUcmFja2luZygpIHtcclxuICBjb25zdCBhcHBseVN0YXRlID0gdXNlQXBwbHlTZXJpYWxpemVkU3RhdGUoKVxyXG5cclxuICByZXR1cm4gYXN5bmMgKHVzZXI6IFVzZXJBY3Rpdml0eU1vZGVsKSA9PiB7XHJcbiAgICBhd2FpdCBhcHBseVN0YXRlKHVzZXIuc3RhdGUsIFN0YXRlQXBwbHlNb2RlLlNwb3RsaWdodClcclxuICB9XHJcbn1cclxuXHJcbnR5cGUgVXNlclR5cGluZ0luZm8gPSB7XHJcbiAgdXNlcklkOiBzdHJpbmdcclxuICB1c2VyTmFtZTogc3RyaW5nXHJcbiAgdGhyZWFkOiBTZXJpYWxpemVkVmlld2VyU3RhdGVbJ3VpJ11bJ3RocmVhZHMnXVsnb3BlblRocmVhZCddXHJcbiAgbGFzdFNlZW46IERheWpzXHJcbn1cclxuXHJcbmV4cG9ydCBmdW5jdGlvbiB1c2VWaWV3ZXJUaHJlYWRUeXBpbmdUcmFja2luZyh0aHJlYWRJZDogTWF5YmVSZWY8c3RyaW5nPikge1xyXG4gIGNvbnN0IHVzZXJzVHlwaW5nID0gcmVmKFtdIGFzIFVzZXJUeXBpbmdJbmZvW10pXHJcblxyXG4gIGNvbnN0IHtcclxuICAgIHNlc3Npb25JZCxcclxuICAgIHByb2plY3RJZCxcclxuICAgIHJlc291cmNlczoge1xyXG4gICAgICByZXF1ZXN0OiB7IHJlc291cmNlSWRTdHJpbmcsIHRocmVhZEZpbHRlcnMgfVxyXG4gICAgfVxyXG4gIH0gPSB1c2VJbmplY3RlZFZpZXdlclN0YXRlKClcclxuICBjb25zdCB7IGlzTG9nZ2VkSW4gfSA9IHVzZUFjdGl2ZVVzZXIoKVxyXG4gIGNvbnN0IHsgb25SZXN1bHQ6IG9uVXNlckFjdGl2aXR5IH0gPSB1c2VTdWJzY3JpcHRpb24oXHJcbiAgICBvblZpZXdlclVzZXJBY3Rpdml0eUJyb2FkY2FzdGVkU3Vic2NyaXB0aW9uLFxyXG4gICAgKCkgPT4gKHtcclxuICAgICAgdGFyZ2V0OiB7XHJcbiAgICAgICAgcHJvamVjdElkOiBwcm9qZWN0SWQudmFsdWUsXHJcbiAgICAgICAgcmVzb3VyY2VJZFN0cmluZzogcmVzb3VyY2VJZFN0cmluZy52YWx1ZSxcclxuICAgICAgICBsb2FkZWRWZXJzaW9uc09ubHk6IHRocmVhZEZpbHRlcnMudmFsdWUubG9hZGVkVmVyc2lvbnNPbmx5XHJcbiAgICAgIH0sXHJcbiAgICAgIHNlc3Npb25JZDogc2Vzc2lvbklkLnZhbHVlXHJcbiAgICB9KSxcclxuICAgICgpID0+ICh7XHJcbiAgICAgIGVuYWJsZWQ6IGlzTG9nZ2VkSW4udmFsdWUsXHJcbiAgICAgIGVycm9yUG9saWN5OiAnYWxsJ1xyXG4gICAgfSlcclxuICApXHJcblxyXG4gIG9uVXNlckFjdGl2aXR5KChyZXMpID0+IHtcclxuICAgIGlmICghcmVzLmRhdGE/LnZpZXdlclVzZXJBY3Rpdml0eUJyb2FkY2FzdGVkKSByZXR1cm5cclxuXHJcbiAgICBjb25zdCBldmVudCA9IHJlcy5kYXRhLnZpZXdlclVzZXJBY3Rpdml0eUJyb2FkY2FzdGVkXHJcbiAgICBjb25zdCB1c2VySWQgPSBldmVudC51c2VySWQgfHwgZXZlbnQuc2Vzc2lvbklkXHJcbiAgICBjb25zdCBleGlzdGluZ0l0ZW1JZHggPSB1c2Vyc1R5cGluZy52YWx1ZS5maW5kSW5kZXgoKGkpID0+IGkudXNlcklkID09PSB1c2VySWQpXHJcblxyXG4gICAgLy8gcmVtb3ZlIGV4aXN0aW5nIGRhdGEgYmVmb3JlIChwb3RlbnRpYWxseSkgYWRkaW5nIG5ld1xyXG4gICAgaWYgKGV4aXN0aW5nSXRlbUlkeCAhPT0gLTEpIHtcclxuICAgICAgdXNlcnNUeXBpbmcudmFsdWUuc3BsaWNlKGV4aXN0aW5nSXRlbUlkeCwgMSlcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBzdGF0ZSA9IGlzU2VyaWFsaXplZFZpZXdlclN0YXRlKGV2ZW50LnN0YXRlKSA/IGV2ZW50LnN0YXRlIDogbnVsbFxyXG4gICAgaWYgKCFzdGF0ZSkgcmV0dXJuXHJcbiAgICBjb25zdCB0eXBpbmdQYXlsb2FkID0gc3RhdGUudWkudGhyZWFkcy5vcGVuVGhyZWFkXHJcbiAgICBpZiAodHlwaW5nUGF5bG9hZC50aHJlYWRJZCAhPT0gdW5yZWYodGhyZWFkSWQpKSB7XHJcbiAgICAgIHJldHVyblxyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHR5cGluZ0luZm86IFVzZXJUeXBpbmdJbmZvID0ge1xyXG4gICAgICB1c2VySWQsXHJcbiAgICAgIHVzZXJOYW1lOiBldmVudC51c2VyTmFtZSxcclxuICAgICAgdGhyZWFkOiB0eXBpbmdQYXlsb2FkLFxyXG4gICAgICBsYXN0U2VlbjogZGF5anMoKVxyXG4gICAgfVxyXG5cclxuICAgIGlmICh0eXBpbmdJbmZvLnRocmVhZC5pc1R5cGluZykgdXNlcnNUeXBpbmcudmFsdWUucHVzaCh0eXBpbmdJbmZvKVxyXG4gIH0pXHJcblxyXG4gIHJldHVybiB7XHJcbiAgICB1c2Vyc1R5cGluZzogY29tcHV0ZWQoKCkgPT4gdXNlcnNUeXBpbmcudmFsdWUpXHJcbiAgfVxyXG59XHJcbiJdLCJmaWxlIjoiRDovc3BlY2tsZS1zZXJ2ZXIvcGFja2FnZXMvZnJvbnRlbmQtMi9saWIvdmlld2VyL2NvbXBvc2FibGVzL2FjdGl2aXR5LnRzIn0=