ghostos 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.esm.js CHANGED
@@ -22576,7 +22576,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
22576
22576
  \********************************************************/
22577
22577
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
22578
22578
 
22579
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LEAFAnchorEdge: () => (/* binding */ LEAFAnchorEdge),\n/* harmony export */ LEAFEdge: () => (/* binding */ LEAFEdge),\n/* harmony export */ LEAFLambdaEdge: () => (/* binding */ LEAFLambdaEdge)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var _lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/reactflow.11.10.4/core/dist/esm/index.mjs */ \"./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/core/dist/esm/index.mjs\");\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react/jsx-runtime */ \"./node_modules/react/jsx-runtime.js\");\n\n\n\nconst foreignObjectSize = 40;\nconst onEdgeClick = (event, id) => {\n event.stopPropagation();\n alert(`remove ${id}`);\n};\nfunction LEAFEdge({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n arrowHeadType,\n markerEndId\n}) {\n const [edgePath] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getBezierPath)({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition\n });\n const markerEnd = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getMarkerEnd)(arrowHeadType, markerEndId);\n const [edgeCenterX, edgeCenterY] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getEdgeCenter)({\n sourceX,\n sourceY,\n targetX,\n targetY\n });\n\n // <path id={id} stroke-width=\"10\" stroke-dasharray=\"5,5\" style={style} className=\"react-flow__edge-path\" d={edgePath} markerEnd={markerEnd} />\n // <foreignObject\n // width={foreignObjectSize}\n // height={foreignObjectSize}\n // x={edgeCenterX - foreignObjectSize / 2}\n // y={edgeCenterY - foreignObjectSize / 2}\n // className=\"edgebutton-foreignobject\"\n // requiredExtensions=\"http://www.w3.org/1999/xhtml\"\n // >\n // <body>\n // <button\n // className=\"edgebutton\"\n // onClick={(event) => onEdgeClick(event, id)}\n // >\n // ×\n // </button>\n // </body>\n // </foreignObject>\n // <text>\n // <textPath href={`#${id}`} style={{ fontSize: '12px' }} startOffset=\"50%\" textAnchor=\"middle\">\n // {data.text}\n // </textPath>\n // </text>\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.BaseEdge, {\n id: id,\n style: {\n ...style,\n strokeWidth: \"10\"\n },\n path: edgePath,\n markerEnd: markerEnd\n })\n });\n}\nfunction LEAFLambdaEdge({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n arrowHeadType,\n markerEndId\n}) {\n const [edgePath] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getBezierPath)({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition\n });\n const markerEnd = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getMarkerEnd)(arrowHeadType, markerEndId);\n const [edgeCenterX, edgeCenterY] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getEdgeCenter)({\n sourceX,\n sourceY,\n targetX,\n targetY\n });\n\n // <path id={id} stroke-width=\"10\" stroke-dasharray=\"5,5\" style={style} className=\"react-flow__edge-path\" d={edgePath} markerEnd={markerEnd} />\n // markerEnd from getMarkerEnd() = 'url(#react-flow__arrow)'\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.BaseEdge, {\n id: id,\n style: {\n ...style,\n strokeWidth: \"10\",\n strokeDasharray: \"10,5\"\n },\n path: edgePath,\n markerEnd: markerEnd\n }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)(\"g\", {\n id: \"UrTavla\",\n children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"circle\", {\n cx: edgeCenterX,\n cy: edgeCenterY,\n fill: \"#fff\",\n r: 6.5,\n stroke: \"#222\",\n strokeWidth: 0.5\n }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"text\", {\n x: edgeCenterX,\n y: edgeCenterY + 5.5,\n textAnchor: \"middle\",\n children: \"\\u03BB\"\n })]\n })]\n });\n}\nfunction LEAFAnchorEdge({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n arrowHeadType,\n markerEndId\n}) {\n const [edgePath] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getBezierPath)({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition\n });\n const markerEnd = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getMarkerEnd)(arrowHeadType, markerEndId);\n const [edgeCenterX, edgeCenterY] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.getEdgeCenter)({\n sourceX,\n sourceY,\n targetX,\n targetY\n });\n\n // <path id={id} stroke-width=\"10\" stroke-dasharray=\"5,5\" style={style} className=\"react-flow__edge-path\" d={edgePath} markerEnd={markerEnd} />\n // markerEnd from getMarkerEnd() = 'url(#react-flow__arrow)'\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(_lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_2__.BaseEdge, {\n id: id,\n style: {\n ...style,\n strokeWidth: \"10\",\n strokeDasharray: \"10,5\"\n },\n path: edgePath,\n markerEnd: markerEnd\n }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"div\", {\n position: \"relative\",\n style: {\n zIndex: 2\n },\n children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)(\"g\", {\n id: \"UrTavla\",\n children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"circle\", {\n cx: sourceX,\n cy: sourceY,\n fill: \"#fff\",\n r: 6.5,\n stroke: \"#222\",\n strokeWidth: 0.5\n }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"text\", {\n x: sourceX,\n y: sourceY + 6,\n textAnchor: \"middle\",\n children: \"\\u2646\"\n })]\n })\n })]\n });\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvYXBpL2xlYWZ1aS9lbGVtZW50cy9mbG93ZWRpdG9yL2xlYWZlZGdlLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUdBO0FBQUE7QUFDQTtBQUdBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFHQTtBQUFBO0FBQ0E7QUFDQTtBQUdBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vZ2hvc3Rvcy8uL3NyYy9hcGkvbGVhZnVpL2VsZW1lbnRzL2Zsb3dlZGl0b3IvbGVhZmVkZ2UuanM/YmQwZCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgQmFzZUVkZ2UsIGdldEJlemllclBhdGgsIGdldEVkZ2VDZW50ZXIsIGdldE1hcmtlckVuZCB9IGZyb20gJy4vbGliL3JlYWN0Zmxvdy4xMS4xMC40L2NvcmUvZGlzdC9lc20vaW5kZXgubWpzJztcblxuY29uc3QgZm9yZWlnbk9iamVjdFNpemUgPSA0MDtcbmNvbnN0IG9uRWRnZUNsaWNrID0gKGV2ZW50LCBpZCkgPT4ge1xuICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgYWxlcnQoYHJlbW92ZSAke2lkfWApO1xufTtcblxuZnVuY3Rpb24gTEVBRkVkZ2Uoe1xuICBpZCxcbiAgc291cmNlWCxcbiAgc291cmNlWSxcbiAgdGFyZ2V0WCxcbiAgdGFyZ2V0WSxcbiAgc291cmNlUG9zaXRpb24sXG4gIHRhcmdldFBvc2l0aW9uLFxuICBzdHlsZSA9IHt9LFxuICBkYXRhLFxuICBhcnJvd0hlYWRUeXBlLFxuICBtYXJrZXJFbmRJZCxcbn0pIHtcbiAgY29uc3QgW2VkZ2VQYXRoXSA9IGdldEJlemllclBhdGgoeyBzb3VyY2VYLCBzb3VyY2VZLCBzb3VyY2VQb3NpdGlvbiwgdGFyZ2V0WCwgdGFyZ2V0WSwgdGFyZ2V0UG9zaXRpb24gfSk7XG4gIGNvbnN0IG1hcmtlckVuZCA9IGdldE1hcmtlckVuZChhcnJvd0hlYWRUeXBlLCBtYXJrZXJFbmRJZCk7XG4gIGNvbnN0IFtlZGdlQ2VudGVyWCwgZWRnZUNlbnRlclldID0gZ2V0RWRnZUNlbnRlcih7XG4gICAgc291cmNlWCxcbiAgICBzb3VyY2VZLFxuICAgIHRhcmdldFgsXG4gICAgdGFyZ2V0WSxcbiAgfSk7XG5cbi8vICAgICAgPHBhdGggaWQ9e2lkfSBzdHJva2Utd2lkdGg9XCIxMFwiIHN0cm9rZS1kYXNoYXJyYXk9XCI1LDVcIiBzdHlsZT17c3R5bGV9IGNsYXNzTmFtZT1cInJlYWN0LWZsb3dfX2VkZ2UtcGF0aFwiIGQ9e2VkZ2VQYXRofSBtYXJrZXJFbmQ9e21hcmtlckVuZH0gLz5cbi8vICAgICAgPGZvcmVpZ25PYmplY3Rcbi8vICAgICAgICB3aWR0aD17Zm9yZWlnbk9iamVjdFNpemV9XG4vLyAgICAgICAgaGVpZ2h0PXtmb3JlaWduT2JqZWN0U2l6ZX1cbi8vICAgICAgICB4PXtlZGdlQ2VudGVyWCAtIGZvcmVpZ25PYmplY3RTaXplIC8gMn1cbi8vICAgICAgICB5PXtlZGdlQ2VudGVyWSAtIGZvcmVpZ25PYmplY3RTaXplIC8gMn1cbi8vICAgICAgICBjbGFzc05hbWU9XCJlZGdlYnV0dG9uLWZvcmVpZ25vYmplY3RcIlxuLy8gICAgICAgIHJlcXVpcmVkRXh0ZW5zaW9ucz1cImh0dHA6Ly93d3cudzMub3JnLzE5OTkveGh0bWxcIlxuLy8gICAgICA+XG4vLyAgICAgICAgPGJvZHk+XG4vLyAgICAgICAgICA8YnV0dG9uXG4vLyAgICAgICAgICAgIGNsYXNzTmFtZT1cImVkZ2VidXR0b25cIlxuLy8gICAgICAgICAgICBvbkNsaWNrPXsoZXZlbnQpID0+IG9uRWRnZUNsaWNrKGV2ZW50LCBpZCl9XG4vLyAgICAgICAgICA+XG4vLyAgICAgICAgICAgIMOXXG4vLyAgICAgICAgICA8L2J1dHRvbj5cbi8vICAgICAgICA8L2JvZHk+XG4vLyAgICAgIDwvZm9yZWlnbk9iamVjdD5cbi8vICAgICAgPHRleHQ+XG4vLyAgICAgICAgPHRleHRQYXRoIGhyZWY9e2AjJHtpZH1gfSBzdHlsZT17eyBmb250U2l6ZTogJzEycHgnIH19IHN0YXJ0T2Zmc2V0PVwiNTAlXCIgdGV4dEFuY2hvcj1cIm1pZGRsZVwiPlxuLy8gICAgICAgICAge2RhdGEudGV4dH1cbi8vICAgICAgICA8L3RleHRQYXRoPlxuLy8gICAgICA8L3RleHQ+XG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxCYXNlRWRnZSBpZD17aWR9IHN0eWxlPXt7Li4uc3R5bGUsIHN0cm9rZVdpZHRoOlwiMTBcIiB9fSBwYXRoPXtlZGdlUGF0aH0gbWFya2VyRW5kPXttYXJrZXJFbmR9IC8+XG4gICAgPC8+XG4gICk7XG59XG5cbmZ1bmN0aW9uIExFQUZMYW1iZGFFZGdlKHtcbiAgaWQsXG4gIHNvdXJjZVgsXG4gIHNvdXJjZVksXG4gIHRhcmdldFgsXG4gIHRhcmdldFksXG4gIHNvdXJjZVBvc2l0aW9uLFxuICB0YXJnZXRQb3NpdGlvbixcbiAgc3R5bGUgPSB7fSxcbiAgZGF0YSxcbiAgYXJyb3dIZWFkVHlwZSxcbiAgbWFya2VyRW5kSWQsXG59KSB7XG4gIGNvbnN0IFtlZGdlUGF0aF0gPSBnZXRCZXppZXJQYXRoKHsgc291cmNlWCwgc291cmNlWSwgc291cmNlUG9zaXRpb24sIHRhcmdldFgsIHRhcmdldFksIHRhcmdldFBvc2l0aW9uIH0pO1xuICBjb25zdCBtYXJrZXJFbmQgPSBnZXRNYXJrZXJFbmQoYXJyb3dIZWFkVHlwZSwgbWFya2VyRW5kSWQpO1xuICBjb25zdCBbZWRnZUNlbnRlclgsIGVkZ2VDZW50ZXJZXSA9IGdldEVkZ2VDZW50ZXIoe1xuICAgIHNvdXJjZVgsXG4gICAgc291cmNlWSxcbiAgICB0YXJnZXRYLFxuICAgIHRhcmdldFksXG4gIH0pO1xuXG4vLyAgICAgIDxwYXRoIGlkPXtpZH0gc3Ryb2tlLXdpZHRoPVwiMTBcIiBzdHJva2UtZGFzaGFycmF5PVwiNSw1XCIgc3R5bGU9e3N0eWxlfSBjbGFzc05hbWU9XCJyZWFjdC1mbG93X19lZGdlLXBhdGhcIiBkPXtlZGdlUGF0aH0gbWFya2VyRW5kPXttYXJrZXJFbmR9IC8+XG4vLyBtYXJrZXJFbmQgZnJvbSBnZXRNYXJrZXJFbmQoKSA9ICd1cmwoI3JlYWN0LWZsb3dfX2Fycm93KSdcbiAgcmV0dXJuIChcbiAgICA8PlxuICAgICAgPEJhc2VFZGdlIGlkPXtpZH0gc3R5bGU9e3suLi5zdHlsZSwgc3Ryb2tlV2lkdGg6XCIxMFwiLCBzdHJva2VEYXNoYXJyYXk6XCIxMCw1XCJ9fSBwYXRoPXtlZGdlUGF0aH0gbWFya2VyRW5kPXttYXJrZXJFbmR9IC8+XG4gICAgICA8ZyBpZD1cIlVyVGF2bGFcIj5cbiAgICAgIDxjaXJjbGUgY3g9e2VkZ2VDZW50ZXJYfSBjeT17ZWRnZUNlbnRlcll9IGZpbGw9XCIjZmZmXCIgcj17Ni41fSBzdHJva2U9XCIjMjIyXCIgc3Ryb2tlV2lkdGg9ezAuNX0gLz5cbiAgICAgIDx0ZXh0XG4gICAgICAgIHg9e2VkZ2VDZW50ZXJYfVxuICAgICAgICB5PXtlZGdlQ2VudGVyWSs1LjV9XG4gICAgICAgIHRleHRBbmNob3I9XCJtaWRkbGVcIlxuICAgICAgPlxuICAgICAgICAmbGFtYmRhO1xuICAgICAgPC90ZXh0PlxuICAgICAgPC9nPlxuICAgIDwvPlxuICApO1xufVxuXG5mdW5jdGlvbiBMRUFGQW5jaG9yRWRnZSh7XG4gIGlkLFxuICBzb3VyY2VYLFxuICBzb3VyY2VZLFxuICB0YXJnZXRYLFxuICB0YXJnZXRZLFxuICBzb3VyY2VQb3NpdGlvbixcbiAgdGFyZ2V0UG9zaXRpb24sXG4gIHN0eWxlID0ge30sXG4gIGRhdGEsXG4gIGFycm93SGVhZFR5cGUsXG4gIG1hcmtlckVuZElkLFxufSkge1xuICBjb25zdCBbZWRnZVBhdGhdID0gZ2V0QmV6aWVyUGF0aCh7IHNvdXJjZVgsIHNvdXJjZVksIHNvdXJjZVBvc2l0aW9uLCB0YXJnZXRYLCB0YXJnZXRZLCB0YXJnZXRQb3NpdGlvbiB9KTtcbiAgY29uc3QgbWFya2VyRW5kID0gZ2V0TWFya2VyRW5kKGFycm93SGVhZFR5cGUsIG1hcmtlckVuZElkKTtcbiAgY29uc3QgW2VkZ2VDZW50ZXJYLCBlZGdlQ2VudGVyWV0gPSBnZXRFZGdlQ2VudGVyKHtcbiAgICBzb3VyY2VYLFxuICAgIHNvdXJjZVksXG4gICAgdGFyZ2V0WCxcbiAgICB0YXJnZXRZLFxuICB9KTtcblxuLy8gICAgICA8cGF0aCBpZD17aWR9IHN0cm9rZS13aWR0aD1cIjEwXCIgc3Ryb2tlLWRhc2hhcnJheT1cIjUsNVwiIHN0eWxlPXtzdHlsZX0gY2xhc3NOYW1lPVwicmVhY3QtZmxvd19fZWRnZS1wYXRoXCIgZD17ZWRnZVBhdGh9IG1hcmtlckVuZD17bWFya2VyRW5kfSAvPlxuLy8gbWFya2VyRW5kIGZyb20gZ2V0TWFya2VyRW5kKCkgPSAndXJsKCNyZWFjdC1mbG93X19hcnJvdyknXG4gIHJldHVybiAoXG4gICAgPD5cbiAgICAgIDxCYXNlRWRnZSBpZD17aWR9IHN0eWxlPXt7Li4uc3R5bGUsIHN0cm9rZVdpZHRoOlwiMTBcIiwgc3Ryb2tlRGFzaGFycmF5OlwiMTAsNVwiIH19IHBhdGg9e2VkZ2VQYXRofSBtYXJrZXJFbmQ9e21hcmtlckVuZH0gLz5cbiAgICAgIDxkaXYgcG9zaXRpb249J3JlbGF0aXZlJyBzdHlsZT17e3pJbmRleDogMn19ID5cbiAgICAgICAgPGcgaWQ9XCJVclRhdmxhXCI+XG4gICAgICAgIDxjaXJjbGUgY3g9e3NvdXJjZVh9IGN5PXtzb3VyY2VZfSBmaWxsPVwiI2ZmZlwiIHI9ezYuNX0gc3Ryb2tlPVwiIzIyMlwiIHN0cm9rZVdpZHRoPXswLjV9IC8+XG4gICAgICAgIDx0ZXh0XG4gICAgICAgICAgeD17c291cmNlWH1cbiAgICAgICAgICB5PXtzb3VyY2VZKzZ9XG4gICAgICAgICAgdGV4dEFuY2hvcj1cIm1pZGRsZVwiXG4gICAgICAgID5cbiAgICAgICAgICAmI3gyNjQ2O1xuICAgICAgICA8L3RleHQ+XG4gICAgICAgIDwvZz5cbiAgICAgIDwvZGl2PlxuICAgIDwvPlxuICApO1xufVxuXG5leHBvcnQge0xFQUZFZGdlLCBMRUFGTGFtYmRhRWRnZSwgTEVBRkFuY2hvckVkZ2V9Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/api/leafui/elements/floweditor/leafedge.js\n\n}");
22579
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ LEAFAnchorEdge: () => (/* binding */ LEAFAnchorEdge),\n/* harmony export */ LEAFEdge: () => (/* binding */ LEAFEdge),\n/* harmony export */ LEAFLambdaEdge: () => (/* binding */ LEAFLambdaEdge)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var _lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./lib/reactflow.11.10.4/core/dist/esm/index.js */ \"./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/core/dist/esm/index.js\");\n/* harmony import */ var react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! react/jsx-runtime */ \"./node_modules/react/jsx-runtime.js\");\n\n\n\nconst foreignObjectSize = 40;\nconst onEdgeClick = (event, id) => {\n event.stopPropagation();\n alert(`remove ${id}`);\n};\nfunction LEAFEdge({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n arrowHeadType,\n markerEndId\n}) {\n const [edgePath] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getBezierPath)({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition\n });\n const markerEnd = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getMarkerEnd)(arrowHeadType, markerEndId);\n const [edgeCenterX, edgeCenterY] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getEdgeCenter)({\n sourceX,\n sourceY,\n targetX,\n targetY\n });\n\n // <path id={id} stroke-width=\"10\" stroke-dasharray=\"5,5\" style={style} className=\"react-flow__edge-path\" d={edgePath} markerEnd={markerEnd} />\n // <foreignObject\n // width={foreignObjectSize}\n // height={foreignObjectSize}\n // x={edgeCenterX - foreignObjectSize / 2}\n // y={edgeCenterY - foreignObjectSize / 2}\n // className=\"edgebutton-foreignobject\"\n // requiredExtensions=\"http://www.w3.org/1999/xhtml\"\n // >\n // <body>\n // <button\n // className=\"edgebutton\"\n // onClick={(event) => onEdgeClick(event, id)}\n // >\n // ×\n // </button>\n // </body>\n // </foreignObject>\n // <text>\n // <textPath href={`#${id}`} style={{ fontSize: '12px' }} startOffset=\"50%\" textAnchor=\"middle\">\n // {data.text}\n // </textPath>\n // </text>\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.BaseEdge, {\n id: id,\n style: {\n ...style,\n strokeWidth: \"10\"\n },\n path: edgePath,\n markerEnd: markerEnd\n })\n });\n}\nfunction LEAFLambdaEdge({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n arrowHeadType,\n markerEndId\n}) {\n const [edgePath] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getBezierPath)({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition\n });\n const markerEnd = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getMarkerEnd)(arrowHeadType, markerEndId);\n const [edgeCenterX, edgeCenterY] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getEdgeCenter)({\n sourceX,\n sourceY,\n targetX,\n targetY\n });\n\n // <path id={id} stroke-width=\"10\" stroke-dasharray=\"5,5\" style={style} className=\"react-flow__edge-path\" d={edgePath} markerEnd={markerEnd} />\n // markerEnd from getMarkerEnd() = 'url(#react-flow__arrow)'\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.BaseEdge, {\n id: id,\n style: {\n ...style,\n strokeWidth: \"10\",\n strokeDasharray: \"10,5\"\n },\n path: edgePath,\n markerEnd: markerEnd\n }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)(\"g\", {\n id: \"UrTavla\",\n children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"circle\", {\n cx: edgeCenterX,\n cy: edgeCenterY,\n fill: \"#fff\",\n r: 6.5,\n stroke: \"#222\",\n strokeWidth: 0.5\n }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"text\", {\n x: edgeCenterX,\n y: edgeCenterY + 5.5,\n textAnchor: \"middle\",\n children: \"\\u03BB\"\n })]\n })]\n });\n}\nfunction LEAFAnchorEdge({\n id,\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourcePosition,\n targetPosition,\n style = {},\n data,\n arrowHeadType,\n markerEndId\n}) {\n const [edgePath] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getBezierPath)({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition\n });\n const markerEnd = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getMarkerEnd)(arrowHeadType, markerEndId);\n const [edgeCenterX, edgeCenterY] = (0,_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.getEdgeCenter)({\n sourceX,\n sourceY,\n targetX,\n targetY\n });\n\n // <path id={id} stroke-width=\"10\" stroke-dasharray=\"5,5\" style={style} className=\"react-flow__edge-path\" d={edgePath} markerEnd={markerEnd} />\n // markerEnd from getMarkerEnd() = 'url(#react-flow__arrow)'\n return /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)(react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.Fragment, {\n children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(_lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_2__.BaseEdge, {\n id: id,\n style: {\n ...style,\n strokeWidth: \"10\",\n strokeDasharray: \"10,5\"\n },\n path: edgePath,\n markerEnd: markerEnd\n }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"div\", {\n position: \"relative\",\n style: {\n zIndex: 2\n },\n children: /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsxs)(\"g\", {\n id: \"UrTavla\",\n children: [/*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"circle\", {\n cx: sourceX,\n cy: sourceY,\n fill: \"#fff\",\n r: 6.5,\n stroke: \"#222\",\n strokeWidth: 0.5\n }), /*#__PURE__*/(0,react_jsx_runtime__WEBPACK_IMPORTED_MODULE_1__.jsx)(\"text\", {\n x: sourceX,\n y: sourceY + 6,\n textAnchor: \"middle\",\n children: \"\\u2646\"\n })]\n })\n })]\n });\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvYXBpL2xlYWZ1aS9lbGVtZW50cy9mbG93ZWRpdG9yL2xlYWZlZGdlLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7OztBQUFBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUdBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUdBO0FBQUE7QUFDQTtBQUdBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFHQTtBQUFBO0FBQ0E7QUFDQTtBQUdBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vZ2hvc3Rvcy8uL3NyYy9hcGkvbGVhZnVpL2VsZW1lbnRzL2Zsb3dlZGl0b3IvbGVhZmVkZ2UuanM/YmQwZCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QgZnJvbSAncmVhY3QnO1xuaW1wb3J0IHsgQmFzZUVkZ2UsIGdldEJlemllclBhdGgsIGdldEVkZ2VDZW50ZXIsIGdldE1hcmtlckVuZCB9IGZyb20gJy4vbGliL3JlYWN0Zmxvdy4xMS4xMC40L2NvcmUvZGlzdC9lc20vaW5kZXguanMnO1xuXG5jb25zdCBmb3JlaWduT2JqZWN0U2l6ZSA9IDQwO1xuY29uc3Qgb25FZGdlQ2xpY2sgPSAoZXZlbnQsIGlkKSA9PiB7XG4gIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICBhbGVydChgcmVtb3ZlICR7aWR9YCk7XG59O1xuXG5mdW5jdGlvbiBMRUFGRWRnZSh7XG4gIGlkLFxuICBzb3VyY2VYLFxuICBzb3VyY2VZLFxuICB0YXJnZXRYLFxuICB0YXJnZXRZLFxuICBzb3VyY2VQb3NpdGlvbixcbiAgdGFyZ2V0UG9zaXRpb24sXG4gIHN0eWxlID0ge30sXG4gIGRhdGEsXG4gIGFycm93SGVhZFR5cGUsXG4gIG1hcmtlckVuZElkLFxufSkge1xuICBjb25zdCBbZWRnZVBhdGhdID0gZ2V0QmV6aWVyUGF0aCh7IHNvdXJjZVgsIHNvdXJjZVksIHNvdXJjZVBvc2l0aW9uLCB0YXJnZXRYLCB0YXJnZXRZLCB0YXJnZXRQb3NpdGlvbiB9KTtcbiAgY29uc3QgbWFya2VyRW5kID0gZ2V0TWFya2VyRW5kKGFycm93SGVhZFR5cGUsIG1hcmtlckVuZElkKTtcbiAgY29uc3QgW2VkZ2VDZW50ZXJYLCBlZGdlQ2VudGVyWV0gPSBnZXRFZGdlQ2VudGVyKHtcbiAgICBzb3VyY2VYLFxuICAgIHNvdXJjZVksXG4gICAgdGFyZ2V0WCxcbiAgICB0YXJnZXRZLFxuICB9KTtcblxuLy8gICAgICA8cGF0aCBpZD17aWR9IHN0cm9rZS13aWR0aD1cIjEwXCIgc3Ryb2tlLWRhc2hhcnJheT1cIjUsNVwiIHN0eWxlPXtzdHlsZX0gY2xhc3NOYW1lPVwicmVhY3QtZmxvd19fZWRnZS1wYXRoXCIgZD17ZWRnZVBhdGh9IG1hcmtlckVuZD17bWFya2VyRW5kfSAvPlxuLy8gICAgICA8Zm9yZWlnbk9iamVjdFxuLy8gICAgICAgIHdpZHRoPXtmb3JlaWduT2JqZWN0U2l6ZX1cbi8vICAgICAgICBoZWlnaHQ9e2ZvcmVpZ25PYmplY3RTaXplfVxuLy8gICAgICAgIHg9e2VkZ2VDZW50ZXJYIC0gZm9yZWlnbk9iamVjdFNpemUgLyAyfVxuLy8gICAgICAgIHk9e2VkZ2VDZW50ZXJZIC0gZm9yZWlnbk9iamVjdFNpemUgLyAyfVxuLy8gICAgICAgIGNsYXNzTmFtZT1cImVkZ2VidXR0b24tZm9yZWlnbm9iamVjdFwiXG4vLyAgICAgICAgcmVxdWlyZWRFeHRlbnNpb25zPVwiaHR0cDovL3d3dy53My5vcmcvMTk5OS94aHRtbFwiXG4vLyAgICAgID5cbi8vICAgICAgICA8Ym9keT5cbi8vICAgICAgICAgIDxidXR0b25cbi8vICAgICAgICAgICAgY2xhc3NOYW1lPVwiZWRnZWJ1dHRvblwiXG4vLyAgICAgICAgICAgIG9uQ2xpY2s9eyhldmVudCkgPT4gb25FZGdlQ2xpY2soZXZlbnQsIGlkKX1cbi8vICAgICAgICAgID5cbi8vICAgICAgICAgICAgw5dcbi8vICAgICAgICAgIDwvYnV0dG9uPlxuLy8gICAgICAgIDwvYm9keT5cbi8vICAgICAgPC9mb3JlaWduT2JqZWN0PlxuLy8gICAgICA8dGV4dD5cbi8vICAgICAgICA8dGV4dFBhdGggaHJlZj17YCMke2lkfWB9IHN0eWxlPXt7IGZvbnRTaXplOiAnMTJweCcgfX0gc3RhcnRPZmZzZXQ9XCI1MCVcIiB0ZXh0QW5jaG9yPVwibWlkZGxlXCI+XG4vLyAgICAgICAgICB7ZGF0YS50ZXh0fVxuLy8gICAgICAgIDwvdGV4dFBhdGg+XG4vLyAgICAgIDwvdGV4dD5cbiAgcmV0dXJuIChcbiAgICA8PlxuICAgICAgPEJhc2VFZGdlIGlkPXtpZH0gc3R5bGU9e3suLi5zdHlsZSwgc3Ryb2tlV2lkdGg6XCIxMFwiIH19IHBhdGg9e2VkZ2VQYXRofSBtYXJrZXJFbmQ9e21hcmtlckVuZH0gLz5cbiAgICA8Lz5cbiAgKTtcbn1cblxuZnVuY3Rpb24gTEVBRkxhbWJkYUVkZ2Uoe1xuICBpZCxcbiAgc291cmNlWCxcbiAgc291cmNlWSxcbiAgdGFyZ2V0WCxcbiAgdGFyZ2V0WSxcbiAgc291cmNlUG9zaXRpb24sXG4gIHRhcmdldFBvc2l0aW9uLFxuICBzdHlsZSA9IHt9LFxuICBkYXRhLFxuICBhcnJvd0hlYWRUeXBlLFxuICBtYXJrZXJFbmRJZCxcbn0pIHtcbiAgY29uc3QgW2VkZ2VQYXRoXSA9IGdldEJlemllclBhdGgoeyBzb3VyY2VYLCBzb3VyY2VZLCBzb3VyY2VQb3NpdGlvbiwgdGFyZ2V0WCwgdGFyZ2V0WSwgdGFyZ2V0UG9zaXRpb24gfSk7XG4gIGNvbnN0IG1hcmtlckVuZCA9IGdldE1hcmtlckVuZChhcnJvd0hlYWRUeXBlLCBtYXJrZXJFbmRJZCk7XG4gIGNvbnN0IFtlZGdlQ2VudGVyWCwgZWRnZUNlbnRlclldID0gZ2V0RWRnZUNlbnRlcih7XG4gICAgc291cmNlWCxcbiAgICBzb3VyY2VZLFxuICAgIHRhcmdldFgsXG4gICAgdGFyZ2V0WSxcbiAgfSk7XG5cbi8vICAgICAgPHBhdGggaWQ9e2lkfSBzdHJva2Utd2lkdGg9XCIxMFwiIHN0cm9rZS1kYXNoYXJyYXk9XCI1LDVcIiBzdHlsZT17c3R5bGV9IGNsYXNzTmFtZT1cInJlYWN0LWZsb3dfX2VkZ2UtcGF0aFwiIGQ9e2VkZ2VQYXRofSBtYXJrZXJFbmQ9e21hcmtlckVuZH0gLz5cbi8vIG1hcmtlckVuZCBmcm9tIGdldE1hcmtlckVuZCgpID0gJ3VybCgjcmVhY3QtZmxvd19fYXJyb3cpJ1xuICByZXR1cm4gKFxuICAgIDw+XG4gICAgICA8QmFzZUVkZ2UgaWQ9e2lkfSBzdHlsZT17ey4uLnN0eWxlLCBzdHJva2VXaWR0aDpcIjEwXCIsIHN0cm9rZURhc2hhcnJheTpcIjEwLDVcIn19IHBhdGg9e2VkZ2VQYXRofSBtYXJrZXJFbmQ9e21hcmtlckVuZH0gLz5cbiAgICAgIDxnIGlkPVwiVXJUYXZsYVwiPlxuICAgICAgPGNpcmNsZSBjeD17ZWRnZUNlbnRlclh9IGN5PXtlZGdlQ2VudGVyWX0gZmlsbD1cIiNmZmZcIiByPXs2LjV9IHN0cm9rZT1cIiMyMjJcIiBzdHJva2VXaWR0aD17MC41fSAvPlxuICAgICAgPHRleHRcbiAgICAgICAgeD17ZWRnZUNlbnRlclh9XG4gICAgICAgIHk9e2VkZ2VDZW50ZXJZKzUuNX1cbiAgICAgICAgdGV4dEFuY2hvcj1cIm1pZGRsZVwiXG4gICAgICA+XG4gICAgICAgICZsYW1iZGE7XG4gICAgICA8L3RleHQ+XG4gICAgICA8L2c+XG4gICAgPC8+XG4gICk7XG59XG5cbmZ1bmN0aW9uIExFQUZBbmNob3JFZGdlKHtcbiAgaWQsXG4gIHNvdXJjZVgsXG4gIHNvdXJjZVksXG4gIHRhcmdldFgsXG4gIHRhcmdldFksXG4gIHNvdXJjZVBvc2l0aW9uLFxuICB0YXJnZXRQb3NpdGlvbixcbiAgc3R5bGUgPSB7fSxcbiAgZGF0YSxcbiAgYXJyb3dIZWFkVHlwZSxcbiAgbWFya2VyRW5kSWQsXG59KSB7XG4gIGNvbnN0IFtlZGdlUGF0aF0gPSBnZXRCZXppZXJQYXRoKHsgc291cmNlWCwgc291cmNlWSwgc291cmNlUG9zaXRpb24sIHRhcmdldFgsIHRhcmdldFksIHRhcmdldFBvc2l0aW9uIH0pO1xuICBjb25zdCBtYXJrZXJFbmQgPSBnZXRNYXJrZXJFbmQoYXJyb3dIZWFkVHlwZSwgbWFya2VyRW5kSWQpO1xuICBjb25zdCBbZWRnZUNlbnRlclgsIGVkZ2VDZW50ZXJZXSA9IGdldEVkZ2VDZW50ZXIoe1xuICAgIHNvdXJjZVgsXG4gICAgc291cmNlWSxcbiAgICB0YXJnZXRYLFxuICAgIHRhcmdldFksXG4gIH0pO1xuXG4vLyAgICAgIDxwYXRoIGlkPXtpZH0gc3Ryb2tlLXdpZHRoPVwiMTBcIiBzdHJva2UtZGFzaGFycmF5PVwiNSw1XCIgc3R5bGU9e3N0eWxlfSBjbGFzc05hbWU9XCJyZWFjdC1mbG93X19lZGdlLXBhdGhcIiBkPXtlZGdlUGF0aH0gbWFya2VyRW5kPXttYXJrZXJFbmR9IC8+XG4vLyBtYXJrZXJFbmQgZnJvbSBnZXRNYXJrZXJFbmQoKSA9ICd1cmwoI3JlYWN0LWZsb3dfX2Fycm93KSdcbiAgcmV0dXJuIChcbiAgICA8PlxuICAgICAgPEJhc2VFZGdlIGlkPXtpZH0gc3R5bGU9e3suLi5zdHlsZSwgc3Ryb2tlV2lkdGg6XCIxMFwiLCBzdHJva2VEYXNoYXJyYXk6XCIxMCw1XCIgfX0gcGF0aD17ZWRnZVBhdGh9IG1hcmtlckVuZD17bWFya2VyRW5kfSAvPlxuICAgICAgPGRpdiBwb3NpdGlvbj0ncmVsYXRpdmUnIHN0eWxlPXt7ekluZGV4OiAyfX0gPlxuICAgICAgICA8ZyBpZD1cIlVyVGF2bGFcIj5cbiAgICAgICAgPGNpcmNsZSBjeD17c291cmNlWH0gY3k9e3NvdXJjZVl9IGZpbGw9XCIjZmZmXCIgcj17Ni41fSBzdHJva2U9XCIjMjIyXCIgc3Ryb2tlV2lkdGg9ezAuNX0gLz5cbiAgICAgICAgPHRleHRcbiAgICAgICAgICB4PXtzb3VyY2VYfVxuICAgICAgICAgIHk9e3NvdXJjZVkrNn1cbiAgICAgICAgICB0ZXh0QW5jaG9yPVwibWlkZGxlXCJcbiAgICAgICAgPlxuICAgICAgICAgICYjeDI2NDY7XG4gICAgICAgIDwvdGV4dD5cbiAgICAgICAgPC9nPlxuICAgICAgPC9kaXY+XG4gICAgPC8+XG4gICk7XG59XG5cbmV4cG9ydCB7TEVBRkVkZ2UsIExFQUZMYW1iZGFFZGdlLCBMRUFGQW5jaG9yRWRnZX0iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/api/leafui/elements/floweditor/leafedge.js\n\n}");
22580
22580
 
22581
22581
  /***/ }),
22582
22582
 
@@ -22676,7 +22676,7 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
22676
22676
  \********************************************************************************/
22677
22677
  /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
22678
22678
 
22679
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ checkElementBelowIsValid: () => (/* binding */ checkElementBelowIsValid),\n/* harmony export */ onMouseDown: () => (/* binding */ onMouseDown)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var _lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../lib/reactflow.11.10.4/core/dist/esm/index.mjs */ \"./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/core/dist/esm/index.mjs\");\n\n\n\n//import { getHostForElement } from 'react-flow-renderer'; //.utils';\n\n//#reactflow #migration\n//import {\n// OnConnect,\n// OnConnectStart,\n// OnConnectStop,\n// OnConnectEnd,\n// ConnectionMode,\n// Connection,\n// HandleType,\n// ReactFlowState,\n//} from '../../lib/react-flow-renderer'; //.types';\n //.types';\n\n//import {getHostForElement} from 'react-flow-renderer';\n// in lieu of the unexported react-flow_renderer defined getHostForElement\n//const getHostForElement = (element): Document | ShadowRoot =>\n// (element.getRootNode?.()) || window?.document\nvar getHostForElement = function getHostForElement(element) {\n var _element$getRootNode, _window;\n return ((_element$getRootNode = element.getRootNode) === null || _element$getRootNode === void 0 ? void 0 : _element$getRootNode.call(element)) || ((_window = window) === null || _window === void 0 ? void 0 : _window.document);\n};\n\n//type ValidConnectionFunc = (connection) => boolean; //(connection: Connection)\n//export type SetSourceIdFunc = (params: SetConnectionId) => void;\n\n//export type SetPosition = (pos: XYPosition) => void;\n\n//type Result = {\n// elementBelow: Element | null;\n// isValid: boolean;\n// connection: Connection;\n// isHoveringHandle: boolean;\n//};\n\n// checks if element below mouse is a handle and returns connection in form of an object { source: 123, target: 312 }\nfunction checkElementBelowIsValid(event,\n//: MouseEvent,\nconnectionMode,\n//: ConnectionMode,\nisTarget,\n//: boolean,\nnodeId,\n//: ElementId,\nhandleId,\n//: ElementId | null,\nisValidConnection,\n//: ValidConnectionFunc,\ndoc //: Document | ShadowRoot\n) {\n const elementBelow = doc.elementFromPoint(event.clientX, event.clientY);\n const elementBelowIsTarget = elementBelow?.classList.contains('target') || false;\n const elementBelowIsSource = elementBelow?.classList.contains('source') || false;\n const result = {\n //result: Result \n elementBelow,\n isValid: false,\n connection: {\n source: null,\n target: null,\n sourceHandle: null,\n targetHandle: null\n },\n isHoveringHandle: false\n };\n if (elementBelow && (elementBelowIsTarget || elementBelowIsSource)) {\n result.isHoveringHandle = true;\n\n // in strict mode we don't allow target to target or source to source connections\n const isValid = connectionMode === _lib_reactflow_11_10_4_core_dist_esm_index_mjs__WEBPACK_IMPORTED_MODULE_1__.ConnectionMode.Strict ? isTarget && elementBelowIsSource || !isTarget && elementBelowIsTarget : true;\n if (isValid) {\n const elementBelowNodeId = elementBelow.getAttribute('data-nodeid');\n const elementBelowHandleId = elementBelow.getAttribute('data-handleid');\n const connection = isTarget //connection: Connection\n ? {\n source: elementBelowNodeId,\n sourceHandle: elementBelowHandleId,\n target: nodeId,\n targetHandle: handleId\n } : {\n source: nodeId,\n sourceHandle: handleId,\n target: elementBelowNodeId,\n targetHandle: elementBelowHandleId\n };\n result.connection = connection;\n result.isValid = isValidConnection(connection);\n }\n }\n return result;\n}\nfunction resetRecentHandle(hoveredHandle) {\n //(hoveredHandle: Element): void\n hoveredHandle?.classList.remove('react-flow__handle-valid');\n hoveredHandle?.classList.remove('react-flow__handle-connecting');\n}\nfunction onMouseDown(event,\n//: ReactMouseEvent,\nhandleId,\n//: ElementId | null,\nnodeId,\n//: ElementId,\nsetState,\n//setConnectionNodeId, //: SetSourceIdFunc,\n//setPosition, //: SetPosition,\nonConnect,\n//: OnConnectFunc,\nisTarget,\n//: boolean,\nisValidConnection,\n//: ValidConnectionFunc,\nconnectionMode,\n//: ConnectionMode,\nelementEdgeUpdaterType,\n//?: HandleType,\nonEdgeUpdateEnd,\n//?: (evt: MouseEvent) => void,\nonConnectStart,\n//?: OnConnectStartFunc,\nonConnectStop,\n//?: OnConnectStopFunc,\nonConnectEnd //?: OnConnectEndFunc\n) {\n //: void\n //console.debug(\"onMouseDown()\");\n const reactFlowNode = event.target.closest('.react-flow');\n // when react-flow is used inside a shadow root we can't use document\n const doc = getHostForElement(event.target);\n if (!doc) {\n return;\n }\n const elementBelow = doc.elementFromPoint(event.clientX, event.clientY);\n const elementBelowIsTarget = elementBelow?.classList.contains('target');\n const elementBelowIsSource = elementBelow?.classList.contains('source');\n if (!reactFlowNode || !elementBelowIsTarget && !elementBelowIsSource && !elementEdgeUpdaterType) {\n return;\n }\n const handleType = elementEdgeUpdaterType ? elementEdgeUpdaterType : elementBelowIsTarget ? 'target' : 'source';\n const containerBounds = reactFlowNode.getBoundingClientRect();\n let recentHoveredHandle; //: Element;\n\n //setPosition({\n // x: event.clientX - containerBounds.left,\n // y: event.clientY - containerBounds.top,\n //});\n\n //setConnectionNodeId({ connectionNodeId: nodeId, connectionHandleId: handleId, connectionHandleType: handleType });\n setState({\n connectionPosition: {\n x: event.clientX - containerBounds.left,\n y: event.clientY - containerBounds.top\n },\n connectionNodeId: nodeId,\n connectionHandleId: handleId,\n connectionHandleType: handleType\n });\n onConnectStart?.(event, {\n nodeId,\n handleId,\n handleType\n });\n function onMouseMove(event) {\n //(event: MouseEvent)\n //console.debug(\"onMouseMove() \"+doc);\n //setPosition({\n // x: event.clientX - containerBounds.left,\n // y: event.clientY - containerBounds.top,\n //});\n setState({\n connectionPosition: {\n x: event.clientX - containerBounds.left,\n y: event.clientY - containerBounds.top\n }\n });\n const {\n connection,\n elementBelow,\n isValid,\n isHoveringHandle\n } = checkElementBelowIsValid(event, connectionMode, isTarget, nodeId, handleId, isValidConnection, doc);\n if (!isHoveringHandle) {\n return resetRecentHandle(recentHoveredHandle);\n }\n const isOwnHandle = connection.source === connection.target;\n if (!isOwnHandle && elementBelow) {\n recentHoveredHandle = elementBelow;\n elementBelow.classList.add('react-flow__handle-connecting');\n elementBelow.classList.toggle('react-flow__handle-valid', isValid);\n }\n }\n function onMouseUp(event) {\n //(event: MouseEvent)\n //console.debug(\"onMouseUp()\");\n const {\n connection,\n isValid\n } = checkElementBelowIsValid(event, connectionMode, isTarget, nodeId, handleId, isValidConnection, doc);\n onConnectStop?.(event);\n if (isValid) {\n onConnect?.(connection);\n }\n onConnectEnd?.(event);\n if (elementEdgeUpdaterType && onEdgeUpdateEnd) {\n onEdgeUpdateEnd(event);\n }\n resetRecentHandle(recentHoveredHandle);\n //setConnectionNodeId({ connectionNodeId: null, connectionHandleId: null, connectionHandleType: null });\n setState({\n connectionNodeId: null,\n connectionHandleId: null,\n connectionHandleType: null\n });\n doc.removeEventListener('mousemove', onMouseMove); // as EventListenerOrEventListenerObject);\n doc.removeEventListener('mouseup', onMouseUp); // as EventListenerOrEventListenerObject);\n }\n doc.addEventListener('mousemove', onMouseMove); // as EventListenerOrEventListenerObject);\n doc.addEventListener('mouseup', onMouseUp); // as EventListenerOrEventListenerObject);\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvYXBpL2xlYWZ1aS9lbGVtZW50cy9mbG93ZWRpdG9yL2xlYWZub2RldHlwZXMvcG9ydGhhbmRsZS9oYW5kbGVyLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBVUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQVVBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2dob3N0b3MvLi9zcmMvYXBpL2xlYWZ1aS9lbGVtZW50cy9mbG93ZWRpdG9yL2xlYWZub2RldHlwZXMvcG9ydGhhbmRsZS9oYW5kbGVyLmpzPzBhOTMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTW91c2VFdmVudCBhcyBSZWFjdE1vdXNlRXZlbnQgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBTZXRTdGF0ZSB9IGZyb20gJ3p1c3RhbmQnO1xuXG4vL2ltcG9ydCB7IGdldEhvc3RGb3JFbGVtZW50IH0gZnJvbSAncmVhY3QtZmxvdy1yZW5kZXJlcic7IC8vLnV0aWxzJztcblxuLy8jcmVhY3RmbG93ICNtaWdyYXRpb25cbi8vaW1wb3J0IHtcbi8vICBPbkNvbm5lY3QsXG4vLyAgT25Db25uZWN0U3RhcnQsXG4vLyAgT25Db25uZWN0U3RvcCxcbi8vICBPbkNvbm5lY3RFbmQsXG4vLyAgQ29ubmVjdGlvbk1vZGUsXG4vLyAgQ29ubmVjdGlvbixcbi8vICBIYW5kbGVUeXBlLFxuLy8gIFJlYWN0Rmxvd1N0YXRlLFxuLy99IGZyb20gJy4uLy4uL2xpYi9yZWFjdC1mbG93LXJlbmRlcmVyJzsgLy8udHlwZXMnO1xuaW1wb3J0IHtcbiAgT25Db25uZWN0LFxuICBPbkNvbm5lY3RTdGFydCxcbiAgT25Db25uZWN0U3RvcCxcbiAgT25Db25uZWN0RW5kLFxuICBDb25uZWN0aW9uTW9kZSxcbiAgQ29ubmVjdGlvbixcbiAgSGFuZGxlVHlwZSxcbiAgUmVhY3RGbG93U3RhdGUsXG59IGZyb20gJy4uLy4uL2xpYi9yZWFjdGZsb3cuMTEuMTAuNC9jb3JlL2Rpc3QvZXNtL2luZGV4Lm1qcyc7IC8vLnR5cGVzJztcblxuLy9pbXBvcnQge2dldEhvc3RGb3JFbGVtZW50fSBmcm9tICdyZWFjdC1mbG93LXJlbmRlcmVyJztcbi8vIGluIGxpZXUgb2YgdGhlIHVuZXhwb3J0ZWQgcmVhY3QtZmxvd19yZW5kZXJlciBkZWZpbmVkIGdldEhvc3RGb3JFbGVtZW50XG4vL2NvbnN0IGdldEhvc3RGb3JFbGVtZW50ID0gKGVsZW1lbnQpOiBEb2N1bWVudCB8IFNoYWRvd1Jvb3QgPT5cbi8vICAoZWxlbWVudC5nZXRSb290Tm9kZT8uKCkpIHx8IHdpbmRvdz8uZG9jdW1lbnRcbnZhciBnZXRIb3N0Rm9yRWxlbWVudCA9IGZ1bmN0aW9uIGdldEhvc3RGb3JFbGVtZW50KGVsZW1lbnQpIHtcbiAgdmFyIF9lbGVtZW50JGdldFJvb3ROb2RlLCBfd2luZG93O1xuXG4gIHJldHVybiAoKF9lbGVtZW50JGdldFJvb3ROb2RlID0gZWxlbWVudC5nZXRSb290Tm9kZSkgPT09IG51bGwgfHwgX2VsZW1lbnQkZ2V0Um9vdE5vZGUgPT09IHZvaWQgMCA/IHZvaWQgMCA6IF9lbGVtZW50JGdldFJvb3ROb2RlLmNhbGwoZWxlbWVudCkpIHx8ICgoX3dpbmRvdyA9IHdpbmRvdykgPT09IG51bGwgfHwgX3dpbmRvdyA9PT0gdm9pZCAwID8gdm9pZCAwIDogX3dpbmRvdy5kb2N1bWVudCk7XG59O1xuXG4vL3R5cGUgVmFsaWRDb25uZWN0aW9uRnVuYyA9IChjb25uZWN0aW9uKSA9PiBib29sZWFuOyAvLyhjb25uZWN0aW9uOiBDb25uZWN0aW9uKVxuLy9leHBvcnQgdHlwZSBTZXRTb3VyY2VJZEZ1bmMgPSAocGFyYW1zOiBTZXRDb25uZWN0aW9uSWQpID0+IHZvaWQ7XG5cbi8vZXhwb3J0IHR5cGUgU2V0UG9zaXRpb24gPSAocG9zOiBYWVBvc2l0aW9uKSA9PiB2b2lkO1xuXG4vL3R5cGUgUmVzdWx0ID0ge1xuLy8gIGVsZW1lbnRCZWxvdzogRWxlbWVudCB8IG51bGw7XG4vLyAgaXNWYWxpZDogYm9vbGVhbjtcbi8vICBjb25uZWN0aW9uOiBDb25uZWN0aW9uO1xuLy8gIGlzSG92ZXJpbmdIYW5kbGU6IGJvb2xlYW47XG4vL307XG5cbi8vIGNoZWNrcyBpZiBlbGVtZW50IGJlbG93IG1vdXNlIGlzIGEgaGFuZGxlIGFuZCByZXR1cm5zIGNvbm5lY3Rpb24gaW4gZm9ybSBvZiBhbiBvYmplY3QgeyBzb3VyY2U6IDEyMywgdGFyZ2V0OiAzMTIgfVxuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrRWxlbWVudEJlbG93SXNWYWxpZChcbiAgZXZlbnQsIC8vOiBNb3VzZUV2ZW50LFxuICBjb25uZWN0aW9uTW9kZSwgLy86IENvbm5lY3Rpb25Nb2RlLFxuICBpc1RhcmdldCwgLy86IGJvb2xlYW4sXG4gIG5vZGVJZCwgLy86IEVsZW1lbnRJZCxcbiAgaGFuZGxlSWQsIC8vOiBFbGVtZW50SWQgfCBudWxsLFxuICBpc1ZhbGlkQ29ubmVjdGlvbiwgLy86IFZhbGlkQ29ubmVjdGlvbkZ1bmMsXG4gIGRvYywgLy86IERvY3VtZW50IHwgU2hhZG93Um9vdFxuKSB7XG4gIGNvbnN0IGVsZW1lbnRCZWxvdyA9IGRvYy5lbGVtZW50RnJvbVBvaW50KGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFkpO1xuICBjb25zdCBlbGVtZW50QmVsb3dJc1RhcmdldCA9IGVsZW1lbnRCZWxvdz8uY2xhc3NMaXN0LmNvbnRhaW5zKCd0YXJnZXQnKSB8fCBmYWxzZTtcbiAgY29uc3QgZWxlbWVudEJlbG93SXNTb3VyY2UgPSBlbGVtZW50QmVsb3c/LmNsYXNzTGlzdC5jb250YWlucygnc291cmNlJykgfHwgZmFsc2U7XG5cbiAgY29uc3QgcmVzdWx0ID0geyAvL3Jlc3VsdDogUmVzdWx0IFxuICAgIGVsZW1lbnRCZWxvdyxcbiAgICBpc1ZhbGlkOiBmYWxzZSxcbiAgICBjb25uZWN0aW9uOiB7IHNvdXJjZTogbnVsbCwgdGFyZ2V0OiBudWxsLCBzb3VyY2VIYW5kbGU6IG51bGwsIHRhcmdldEhhbmRsZTogbnVsbCB9LFxuICAgIGlzSG92ZXJpbmdIYW5kbGU6IGZhbHNlLFxuICB9O1xuXG4gIGlmIChlbGVtZW50QmVsb3cgJiYgKGVsZW1lbnRCZWxvd0lzVGFyZ2V0IHx8IGVsZW1lbnRCZWxvd0lzU291cmNlKSkge1xuICAgIHJlc3VsdC5pc0hvdmVyaW5nSGFuZGxlID0gdHJ1ZTtcblxuICAgIC8vIGluIHN0cmljdCBtb2RlIHdlIGRvbid0IGFsbG93IHRhcmdldCB0byB0YXJnZXQgb3Igc291cmNlIHRvIHNvdXJjZSBjb25uZWN0aW9uc1xuICAgIGNvbnN0IGlzVmFsaWQgPVxuICAgICAgY29ubmVjdGlvbk1vZGUgPT09IENvbm5lY3Rpb25Nb2RlLlN0cmljdFxuICAgICAgICA/IChpc1RhcmdldCAmJiBlbGVtZW50QmVsb3dJc1NvdXJjZSkgfHwgKCFpc1RhcmdldCAmJiBlbGVtZW50QmVsb3dJc1RhcmdldClcbiAgICAgICAgOiB0cnVlO1xuXG4gICAgaWYgKGlzVmFsaWQpIHtcbiAgICAgIGNvbnN0IGVsZW1lbnRCZWxvd05vZGVJZCA9IGVsZW1lbnRCZWxvdy5nZXRBdHRyaWJ1dGUoJ2RhdGEtbm9kZWlkJyk7XG4gICAgICBjb25zdCBlbGVtZW50QmVsb3dIYW5kbGVJZCA9IGVsZW1lbnRCZWxvdy5nZXRBdHRyaWJ1dGUoJ2RhdGEtaGFuZGxlaWQnKTtcbiAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSBpc1RhcmdldCAvL2Nvbm5lY3Rpb246IENvbm5lY3Rpb25cbiAgICAgICAgPyB7XG4gICAgICAgICAgICBzb3VyY2U6IGVsZW1lbnRCZWxvd05vZGVJZCxcbiAgICAgICAgICAgIHNvdXJjZUhhbmRsZTogZWxlbWVudEJlbG93SGFuZGxlSWQsXG4gICAgICAgICAgICB0YXJnZXQ6IG5vZGVJZCxcbiAgICAgICAgICAgIHRhcmdldEhhbmRsZTogaGFuZGxlSWQsXG4gICAgICAgICAgfVxuICAgICAgICA6IHtcbiAgICAgICAgICAgIHNvdXJjZTogbm9kZUlkLFxuICAgICAgICAgICAgc291cmNlSGFuZGxlOiBoYW5kbGVJZCxcbiAgICAgICAgICAgIHRhcmdldDogZWxlbWVudEJlbG93Tm9kZUlkLFxuICAgICAgICAgICAgdGFyZ2V0SGFuZGxlOiBlbGVtZW50QmVsb3dIYW5kbGVJZCxcbiAgICAgICAgICB9O1xuXG4gICAgICByZXN1bHQuY29ubmVjdGlvbiA9IGNvbm5lY3Rpb247XG4gICAgICByZXN1bHQuaXNWYWxpZCA9IGlzVmFsaWRDb25uZWN0aW9uKGNvbm5lY3Rpb24pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiByZXN1bHQ7XG59XG5cbmZ1bmN0aW9uIHJlc2V0UmVjZW50SGFuZGxlKGhvdmVyZWRIYW5kbGUpIHsgLy8oaG92ZXJlZEhhbmRsZTogRWxlbWVudCk6IHZvaWRcbiAgaG92ZXJlZEhhbmRsZT8uY2xhc3NMaXN0LnJlbW92ZSgncmVhY3QtZmxvd19faGFuZGxlLXZhbGlkJyk7XG4gIGhvdmVyZWRIYW5kbGU/LmNsYXNzTGlzdC5yZW1vdmUoJ3JlYWN0LWZsb3dfX2hhbmRsZS1jb25uZWN0aW5nJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBvbk1vdXNlRG93bihcbiAgZXZlbnQsIC8vOiBSZWFjdE1vdXNlRXZlbnQsXG4gIGhhbmRsZUlkLCAvLzogRWxlbWVudElkIHwgbnVsbCxcbiAgbm9kZUlkLCAvLzogRWxlbWVudElkLFxuICBzZXRTdGF0ZSxcbiAgLy9zZXRDb25uZWN0aW9uTm9kZUlkLCAvLzogU2V0U291cmNlSWRGdW5jLFxuICAvL3NldFBvc2l0aW9uLCAvLzogU2V0UG9zaXRpb24sXG4gIG9uQ29ubmVjdCwgLy86IE9uQ29ubmVjdEZ1bmMsXG4gIGlzVGFyZ2V0LCAvLzogYm9vbGVhbixcbiAgaXNWYWxpZENvbm5lY3Rpb24sIC8vOiBWYWxpZENvbm5lY3Rpb25GdW5jLFxuICBjb25uZWN0aW9uTW9kZSwgLy86IENvbm5lY3Rpb25Nb2RlLFxuICBlbGVtZW50RWRnZVVwZGF0ZXJUeXBlLCAvLz86IEhhbmRsZVR5cGUsXG4gIG9uRWRnZVVwZGF0ZUVuZCwgLy8/OiAoZXZ0OiBNb3VzZUV2ZW50KSA9PiB2b2lkLFxuICBvbkNvbm5lY3RTdGFydCwgLy8/OiBPbkNvbm5lY3RTdGFydEZ1bmMsXG4gIG9uQ29ubmVjdFN0b3AsIC8vPzogT25Db25uZWN0U3RvcEZ1bmMsXG4gIG9uQ29ubmVjdEVuZCwgLy8/OiBPbkNvbm5lY3RFbmRGdW5jXG4pIHsgLy86IHZvaWRcbiAgLy9jb25zb2xlLmRlYnVnKFwib25Nb3VzZURvd24oKVwiKTtcbiAgY29uc3QgcmVhY3RGbG93Tm9kZSA9IChldmVudC50YXJnZXQpLmNsb3Nlc3QoJy5yZWFjdC1mbG93Jyk7XG4gIC8vIHdoZW4gcmVhY3QtZmxvdyBpcyB1c2VkIGluc2lkZSBhIHNoYWRvdyByb290IHdlIGNhbid0IHVzZSBkb2N1bWVudFxuICBjb25zdCBkb2MgPSBnZXRIb3N0Rm9yRWxlbWVudChldmVudC50YXJnZXQpO1xuXG4gIGlmICghZG9jKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgZWxlbWVudEJlbG93ID0gZG9jLmVsZW1lbnRGcm9tUG9pbnQoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSk7XG4gIGNvbnN0IGVsZW1lbnRCZWxvd0lzVGFyZ2V0ID0gZWxlbWVudEJlbG93Py5jbGFzc0xpc3QuY29udGFpbnMoJ3RhcmdldCcpO1xuICBjb25zdCBlbGVtZW50QmVsb3dJc1NvdXJjZSA9IGVsZW1lbnRCZWxvdz8uY2xhc3NMaXN0LmNvbnRhaW5zKCdzb3VyY2UnKTtcblxuICBpZiAoIXJlYWN0Rmxvd05vZGUgfHwgKCFlbGVtZW50QmVsb3dJc1RhcmdldCAmJiAhZWxlbWVudEJlbG93SXNTb3VyY2UgJiYgIWVsZW1lbnRFZGdlVXBkYXRlclR5cGUpKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgY29uc3QgaGFuZGxlVHlwZSA9IGVsZW1lbnRFZGdlVXBkYXRlclR5cGUgPyBlbGVtZW50RWRnZVVwZGF0ZXJUeXBlIDogZWxlbWVudEJlbG93SXNUYXJnZXQgPyAndGFyZ2V0JyA6ICdzb3VyY2UnO1xuICBjb25zdCBjb250YWluZXJCb3VuZHMgPSByZWFjdEZsb3dOb2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICBsZXQgcmVjZW50SG92ZXJlZEhhbmRsZTsgLy86IEVsZW1lbnQ7XG5cbiAgLy9zZXRQb3NpdGlvbih7XG4gIC8vICB4OiBldmVudC5jbGllbnRYIC0gY29udGFpbmVyQm91bmRzLmxlZnQsXG4gIC8vICB5OiBldmVudC5jbGllbnRZIC0gY29udGFpbmVyQm91bmRzLnRvcCxcbiAgLy99KTtcblxuICAvL3NldENvbm5lY3Rpb25Ob2RlSWQoeyBjb25uZWN0aW9uTm9kZUlkOiBub2RlSWQsIGNvbm5lY3Rpb25IYW5kbGVJZDogaGFuZGxlSWQsIGNvbm5lY3Rpb25IYW5kbGVUeXBlOiBoYW5kbGVUeXBlIH0pO1xuICBzZXRTdGF0ZSh7XG4gICAgICBjb25uZWN0aW9uUG9zaXRpb246IHtcbiAgICAgICAgICB4OiBldmVudC5jbGllbnRYIC0gY29udGFpbmVyQm91bmRzLmxlZnQsXG4gICAgICAgICAgeTogZXZlbnQuY2xpZW50WSAtIGNvbnRhaW5lckJvdW5kcy50b3AsXG4gICAgICB9LFxuICAgICAgY29ubmVjdGlvbk5vZGVJZDogbm9kZUlkLFxuICAgICAgY29ubmVjdGlvbkhhbmRsZUlkOiBoYW5kbGVJZCxcbiAgICAgIGNvbm5lY3Rpb25IYW5kbGVUeXBlOiBoYW5kbGVUeXBlLFxuICB9KTtcblxuICBvbkNvbm5lY3RTdGFydD8uKGV2ZW50LCB7IG5vZGVJZCwgaGFuZGxlSWQsIGhhbmRsZVR5cGUgfSk7XG5cbiAgZnVuY3Rpb24gb25Nb3VzZU1vdmUoZXZlbnQpIHsgLy8oZXZlbnQ6IE1vdXNlRXZlbnQpXG4gICAgLy9jb25zb2xlLmRlYnVnKFwib25Nb3VzZU1vdmUoKSBcIitkb2MpO1xuICAgIC8vc2V0UG9zaXRpb24oe1xuICAgIC8vICB4OiBldmVudC5jbGllbnRYIC0gY29udGFpbmVyQm91bmRzLmxlZnQsXG4gICAgLy8gIHk6IGV2ZW50LmNsaWVudFkgLSBjb250YWluZXJCb3VuZHMudG9wLFxuICAgIC8vfSk7XG4gICAgc2V0U3RhdGUoe1xuICAgICAgICBjb25uZWN0aW9uUG9zaXRpb246IHtcbiAgICAgICAgICAgIHg6IGV2ZW50LmNsaWVudFggLSBjb250YWluZXJCb3VuZHMubGVmdCxcbiAgICAgICAgICAgIHk6IGV2ZW50LmNsaWVudFkgLSBjb250YWluZXJCb3VuZHMudG9wLFxuICAgICAgICB9LFxuICAgIH0pO1xuXG4gICAgY29uc3QgeyBjb25uZWN0aW9uLCBlbGVtZW50QmVsb3csIGlzVmFsaWQsIGlzSG92ZXJpbmdIYW5kbGUgfSA9IGNoZWNrRWxlbWVudEJlbG93SXNWYWxpZChcbiAgICAgIGV2ZW50LFxuICAgICAgY29ubmVjdGlvbk1vZGUsXG4gICAgICBpc1RhcmdldCxcbiAgICAgIG5vZGVJZCxcbiAgICAgIGhhbmRsZUlkLFxuICAgICAgaXNWYWxpZENvbm5lY3Rpb24sXG4gICAgICBkb2NcbiAgICApO1xuXG4gICAgaWYgKCFpc0hvdmVyaW5nSGFuZGxlKSB7XG4gICAgICByZXR1cm4gcmVzZXRSZWNlbnRIYW5kbGUocmVjZW50SG92ZXJlZEhhbmRsZSk7XG4gICAgfVxuXG4gICAgY29uc3QgaXNPd25IYW5kbGUgPSBjb25uZWN0aW9uLnNvdXJjZSA9PT0gY29ubmVjdGlvbi50YXJnZXQ7XG5cbiAgICBpZiAoIWlzT3duSGFuZGxlICYmIGVsZW1lbnRCZWxvdykge1xuICAgICAgcmVjZW50SG92ZXJlZEhhbmRsZSA9IGVsZW1lbnRCZWxvdztcbiAgICAgIGVsZW1lbnRCZWxvdy5jbGFzc0xpc3QuYWRkKCdyZWFjdC1mbG93X19oYW5kbGUtY29ubmVjdGluZycpO1xuICAgICAgZWxlbWVudEJlbG93LmNsYXNzTGlzdC50b2dnbGUoJ3JlYWN0LWZsb3dfX2hhbmRsZS12YWxpZCcsIGlzVmFsaWQpO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIG9uTW91c2VVcChldmVudCkgeyAvLyhldmVudDogTW91c2VFdmVudClcbiAgICAvL2NvbnNvbGUuZGVidWcoXCJvbk1vdXNlVXAoKVwiKTtcbiAgICBjb25zdCB7IGNvbm5lY3Rpb24sIGlzVmFsaWQgfSA9IGNoZWNrRWxlbWVudEJlbG93SXNWYWxpZChcbiAgICAgIGV2ZW50LFxuICAgICAgY29ubmVjdGlvbk1vZGUsXG4gICAgICBpc1RhcmdldCxcbiAgICAgIG5vZGVJZCxcbiAgICAgIGhhbmRsZUlkLFxuICAgICAgaXNWYWxpZENvbm5lY3Rpb24sXG4gICAgICBkb2NcbiAgICApO1xuXG4gICAgb25Db25uZWN0U3RvcD8uKGV2ZW50KTtcblxuICAgIGlmIChpc1ZhbGlkKSB7XG4gICAgICBvbkNvbm5lY3Q/Lihjb25uZWN0aW9uKTtcbiAgICB9XG5cbiAgICBvbkNvbm5lY3RFbmQ/LihldmVudCk7XG5cbiAgICBpZiAoZWxlbWVudEVkZ2VVcGRhdGVyVHlwZSAmJiBvbkVkZ2VVcGRhdGVFbmQpIHtcbiAgICAgIG9uRWRnZVVwZGF0ZUVuZChldmVudCk7XG4gICAgfVxuXG4gICAgcmVzZXRSZWNlbnRIYW5kbGUocmVjZW50SG92ZXJlZEhhbmRsZSk7XG4gICAgLy9zZXRDb25uZWN0aW9uTm9kZUlkKHsgY29ubmVjdGlvbk5vZGVJZDogbnVsbCwgY29ubmVjdGlvbkhhbmRsZUlkOiBudWxsLCBjb25uZWN0aW9uSGFuZGxlVHlwZTogbnVsbCB9KTtcbiAgICBzZXRTdGF0ZSh7XG4gICAgICAgIGNvbm5lY3Rpb25Ob2RlSWQ6IG51bGwsXG4gICAgICAgIGNvbm5lY3Rpb25IYW5kbGVJZDogbnVsbCxcbiAgICAgICAgY29ubmVjdGlvbkhhbmRsZVR5cGU6IG51bGwsXG4gICAgfSk7XG5cbiAgICBkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgb25Nb3VzZU1vdmUpOyAvLyBhcyBFdmVudExpc3RlbmVyT3JFdmVudExpc3RlbmVyT2JqZWN0KTtcbiAgICBkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIG9uTW91c2VVcCk7IC8vIGFzIEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3QpO1xuICB9XG5cbiAgZG9jLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG9uTW91c2VNb3ZlKTsgLy8gYXMgRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdCk7XG4gIGRvYy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Nb3VzZVVwKTsgLy8gYXMgRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdCk7XG59XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/api/leafui/elements/floweditor/leafnodetypes/porthandle/handler.js\n\n}");
22679
+ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ checkElementBelowIsValid: () => (/* binding */ checkElementBelowIsValid),\n/* harmony export */ onMouseDown: () => (/* binding */ onMouseDown)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var _lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../lib/reactflow.11.10.4/core/dist/esm/index.js */ \"./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/core/dist/esm/index.js\");\n\n\n\n//import { getHostForElement } from 'react-flow-renderer'; //.utils';\n\n//#reactflow #migration\n//import {\n// OnConnect,\n// OnConnectStart,\n// OnConnectStop,\n// OnConnectEnd,\n// ConnectionMode,\n// Connection,\n// HandleType,\n// ReactFlowState,\n//} from '../../lib/react-flow-renderer'; //.types';\n //.types';\n\n//import {getHostForElement} from 'react-flow-renderer';\n// in lieu of the unexported react-flow_renderer defined getHostForElement\n//const getHostForElement = (element): Document | ShadowRoot =>\n// (element.getRootNode?.()) || window?.document\nvar getHostForElement = function getHostForElement(element) {\n var _element$getRootNode, _window;\n return ((_element$getRootNode = element.getRootNode) === null || _element$getRootNode === void 0 ? void 0 : _element$getRootNode.call(element)) || ((_window = window) === null || _window === void 0 ? void 0 : _window.document);\n};\n\n//type ValidConnectionFunc = (connection) => boolean; //(connection: Connection)\n//export type SetSourceIdFunc = (params: SetConnectionId) => void;\n\n//export type SetPosition = (pos: XYPosition) => void;\n\n//type Result = {\n// elementBelow: Element | null;\n// isValid: boolean;\n// connection: Connection;\n// isHoveringHandle: boolean;\n//};\n\n// checks if element below mouse is a handle and returns connection in form of an object { source: 123, target: 312 }\nfunction checkElementBelowIsValid(event,\n//: MouseEvent,\nconnectionMode,\n//: ConnectionMode,\nisTarget,\n//: boolean,\nnodeId,\n//: ElementId,\nhandleId,\n//: ElementId | null,\nisValidConnection,\n//: ValidConnectionFunc,\ndoc //: Document | ShadowRoot\n) {\n const elementBelow = doc.elementFromPoint(event.clientX, event.clientY);\n const elementBelowIsTarget = elementBelow?.classList.contains('target') || false;\n const elementBelowIsSource = elementBelow?.classList.contains('source') || false;\n const result = {\n //result: Result \n elementBelow,\n isValid: false,\n connection: {\n source: null,\n target: null,\n sourceHandle: null,\n targetHandle: null\n },\n isHoveringHandle: false\n };\n if (elementBelow && (elementBelowIsTarget || elementBelowIsSource)) {\n result.isHoveringHandle = true;\n\n // in strict mode we don't allow target to target or source to source connections\n const isValid = connectionMode === _lib_reactflow_11_10_4_core_dist_esm_index_js__WEBPACK_IMPORTED_MODULE_1__.ConnectionMode.Strict ? isTarget && elementBelowIsSource || !isTarget && elementBelowIsTarget : true;\n if (isValid) {\n const elementBelowNodeId = elementBelow.getAttribute('data-nodeid');\n const elementBelowHandleId = elementBelow.getAttribute('data-handleid');\n const connection = isTarget //connection: Connection\n ? {\n source: elementBelowNodeId,\n sourceHandle: elementBelowHandleId,\n target: nodeId,\n targetHandle: handleId\n } : {\n source: nodeId,\n sourceHandle: handleId,\n target: elementBelowNodeId,\n targetHandle: elementBelowHandleId\n };\n result.connection = connection;\n result.isValid = isValidConnection(connection);\n }\n }\n return result;\n}\nfunction resetRecentHandle(hoveredHandle) {\n //(hoveredHandle: Element): void\n hoveredHandle?.classList.remove('react-flow__handle-valid');\n hoveredHandle?.classList.remove('react-flow__handle-connecting');\n}\nfunction onMouseDown(event,\n//: ReactMouseEvent,\nhandleId,\n//: ElementId | null,\nnodeId,\n//: ElementId,\nsetState,\n//setConnectionNodeId, //: SetSourceIdFunc,\n//setPosition, //: SetPosition,\nonConnect,\n//: OnConnectFunc,\nisTarget,\n//: boolean,\nisValidConnection,\n//: ValidConnectionFunc,\nconnectionMode,\n//: ConnectionMode,\nelementEdgeUpdaterType,\n//?: HandleType,\nonEdgeUpdateEnd,\n//?: (evt: MouseEvent) => void,\nonConnectStart,\n//?: OnConnectStartFunc,\nonConnectStop,\n//?: OnConnectStopFunc,\nonConnectEnd //?: OnConnectEndFunc\n) {\n //: void\n //console.debug(\"onMouseDown()\");\n const reactFlowNode = event.target.closest('.react-flow');\n // when react-flow is used inside a shadow root we can't use document\n const doc = getHostForElement(event.target);\n if (!doc) {\n return;\n }\n const elementBelow = doc.elementFromPoint(event.clientX, event.clientY);\n const elementBelowIsTarget = elementBelow?.classList.contains('target');\n const elementBelowIsSource = elementBelow?.classList.contains('source');\n if (!reactFlowNode || !elementBelowIsTarget && !elementBelowIsSource && !elementEdgeUpdaterType) {\n return;\n }\n const handleType = elementEdgeUpdaterType ? elementEdgeUpdaterType : elementBelowIsTarget ? 'target' : 'source';\n const containerBounds = reactFlowNode.getBoundingClientRect();\n let recentHoveredHandle; //: Element;\n\n //setPosition({\n // x: event.clientX - containerBounds.left,\n // y: event.clientY - containerBounds.top,\n //});\n\n //setConnectionNodeId({ connectionNodeId: nodeId, connectionHandleId: handleId, connectionHandleType: handleType });\n setState({\n connectionPosition: {\n x: event.clientX - containerBounds.left,\n y: event.clientY - containerBounds.top\n },\n connectionNodeId: nodeId,\n connectionHandleId: handleId,\n connectionHandleType: handleType\n });\n onConnectStart?.(event, {\n nodeId,\n handleId,\n handleType\n });\n function onMouseMove(event) {\n //(event: MouseEvent)\n //console.debug(\"onMouseMove() \"+doc);\n //setPosition({\n // x: event.clientX - containerBounds.left,\n // y: event.clientY - containerBounds.top,\n //});\n setState({\n connectionPosition: {\n x: event.clientX - containerBounds.left,\n y: event.clientY - containerBounds.top\n }\n });\n const {\n connection,\n elementBelow,\n isValid,\n isHoveringHandle\n } = checkElementBelowIsValid(event, connectionMode, isTarget, nodeId, handleId, isValidConnection, doc);\n if (!isHoveringHandle) {\n return resetRecentHandle(recentHoveredHandle);\n }\n const isOwnHandle = connection.source === connection.target;\n if (!isOwnHandle && elementBelow) {\n recentHoveredHandle = elementBelow;\n elementBelow.classList.add('react-flow__handle-connecting');\n elementBelow.classList.toggle('react-flow__handle-valid', isValid);\n }\n }\n function onMouseUp(event) {\n //(event: MouseEvent)\n //console.debug(\"onMouseUp()\");\n const {\n connection,\n isValid\n } = checkElementBelowIsValid(event, connectionMode, isTarget, nodeId, handleId, isValidConnection, doc);\n onConnectStop?.(event);\n if (isValid) {\n onConnect?.(connection);\n }\n onConnectEnd?.(event);\n if (elementEdgeUpdaterType && onEdgeUpdateEnd) {\n onEdgeUpdateEnd(event);\n }\n resetRecentHandle(recentHoveredHandle);\n //setConnectionNodeId({ connectionNodeId: null, connectionHandleId: null, connectionHandleType: null });\n setState({\n connectionNodeId: null,\n connectionHandleId: null,\n connectionHandleType: null\n });\n doc.removeEventListener('mousemove', onMouseMove); // as EventListenerOrEventListenerObject);\n doc.removeEventListener('mouseup', onMouseUp); // as EventListenerOrEventListenerObject);\n }\n doc.addEventListener('mousemove', onMouseMove); // as EventListenerOrEventListenerObject);\n doc.addEventListener('mouseup', onMouseUp); // as EventListenerOrEventListenerObject);\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvYXBpL2xlYWZ1aS9lbGVtZW50cy9mbG93ZWRpdG9yL2xlYWZub2RldHlwZXMvcG9ydGhhbmRsZS9oYW5kbGVyLmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7QUFBQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBVUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFBQTtBQVVBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2dob3N0b3MvLi9zcmMvYXBpL2xlYWZ1aS9lbGVtZW50cy9mbG93ZWRpdG9yL2xlYWZub2RldHlwZXMvcG9ydGhhbmRsZS9oYW5kbGVyLmpzPzBhOTMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgTW91c2VFdmVudCBhcyBSZWFjdE1vdXNlRXZlbnQgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgeyBTZXRTdGF0ZSB9IGZyb20gJ3p1c3RhbmQnO1xuXG4vL2ltcG9ydCB7IGdldEhvc3RGb3JFbGVtZW50IH0gZnJvbSAncmVhY3QtZmxvdy1yZW5kZXJlcic7IC8vLnV0aWxzJztcblxuLy8jcmVhY3RmbG93ICNtaWdyYXRpb25cbi8vaW1wb3J0IHtcbi8vICBPbkNvbm5lY3QsXG4vLyAgT25Db25uZWN0U3RhcnQsXG4vLyAgT25Db25uZWN0U3RvcCxcbi8vICBPbkNvbm5lY3RFbmQsXG4vLyAgQ29ubmVjdGlvbk1vZGUsXG4vLyAgQ29ubmVjdGlvbixcbi8vICBIYW5kbGVUeXBlLFxuLy8gIFJlYWN0Rmxvd1N0YXRlLFxuLy99IGZyb20gJy4uLy4uL2xpYi9yZWFjdC1mbG93LXJlbmRlcmVyJzsgLy8udHlwZXMnO1xuaW1wb3J0IHtcbiAgT25Db25uZWN0LFxuICBPbkNvbm5lY3RTdGFydCxcbiAgT25Db25uZWN0U3RvcCxcbiAgT25Db25uZWN0RW5kLFxuICBDb25uZWN0aW9uTW9kZSxcbiAgQ29ubmVjdGlvbixcbiAgSGFuZGxlVHlwZSxcbiAgUmVhY3RGbG93U3RhdGUsXG59IGZyb20gJy4uLy4uL2xpYi9yZWFjdGZsb3cuMTEuMTAuNC9jb3JlL2Rpc3QvZXNtL2luZGV4LmpzJzsgLy8udHlwZXMnO1xuXG4vL2ltcG9ydCB7Z2V0SG9zdEZvckVsZW1lbnR9IGZyb20gJ3JlYWN0LWZsb3ctcmVuZGVyZXInO1xuLy8gaW4gbGlldSBvZiB0aGUgdW5leHBvcnRlZCByZWFjdC1mbG93X3JlbmRlcmVyIGRlZmluZWQgZ2V0SG9zdEZvckVsZW1lbnRcbi8vY29uc3QgZ2V0SG9zdEZvckVsZW1lbnQgPSAoZWxlbWVudCk6IERvY3VtZW50IHwgU2hhZG93Um9vdCA9PlxuLy8gIChlbGVtZW50LmdldFJvb3ROb2RlPy4oKSkgfHwgd2luZG93Py5kb2N1bWVudFxudmFyIGdldEhvc3RGb3JFbGVtZW50ID0gZnVuY3Rpb24gZ2V0SG9zdEZvckVsZW1lbnQoZWxlbWVudCkge1xuICB2YXIgX2VsZW1lbnQkZ2V0Um9vdE5vZGUsIF93aW5kb3c7XG5cbiAgcmV0dXJuICgoX2VsZW1lbnQkZ2V0Um9vdE5vZGUgPSBlbGVtZW50LmdldFJvb3ROb2RlKSA9PT0gbnVsbCB8fCBfZWxlbWVudCRnZXRSb290Tm9kZSA9PT0gdm9pZCAwID8gdm9pZCAwIDogX2VsZW1lbnQkZ2V0Um9vdE5vZGUuY2FsbChlbGVtZW50KSkgfHwgKChfd2luZG93ID0gd2luZG93KSA9PT0gbnVsbCB8fCBfd2luZG93ID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfd2luZG93LmRvY3VtZW50KTtcbn07XG5cbi8vdHlwZSBWYWxpZENvbm5lY3Rpb25GdW5jID0gKGNvbm5lY3Rpb24pID0+IGJvb2xlYW47IC8vKGNvbm5lY3Rpb246IENvbm5lY3Rpb24pXG4vL2V4cG9ydCB0eXBlIFNldFNvdXJjZUlkRnVuYyA9IChwYXJhbXM6IFNldENvbm5lY3Rpb25JZCkgPT4gdm9pZDtcblxuLy9leHBvcnQgdHlwZSBTZXRQb3NpdGlvbiA9IChwb3M6IFhZUG9zaXRpb24pID0+IHZvaWQ7XG5cbi8vdHlwZSBSZXN1bHQgPSB7XG4vLyAgZWxlbWVudEJlbG93OiBFbGVtZW50IHwgbnVsbDtcbi8vICBpc1ZhbGlkOiBib29sZWFuO1xuLy8gIGNvbm5lY3Rpb246IENvbm5lY3Rpb247XG4vLyAgaXNIb3ZlcmluZ0hhbmRsZTogYm9vbGVhbjtcbi8vfTtcblxuLy8gY2hlY2tzIGlmIGVsZW1lbnQgYmVsb3cgbW91c2UgaXMgYSBoYW5kbGUgYW5kIHJldHVybnMgY29ubmVjdGlvbiBpbiBmb3JtIG9mIGFuIG9iamVjdCB7IHNvdXJjZTogMTIzLCB0YXJnZXQ6IDMxMiB9XG5leHBvcnQgZnVuY3Rpb24gY2hlY2tFbGVtZW50QmVsb3dJc1ZhbGlkKFxuICBldmVudCwgLy86IE1vdXNlRXZlbnQsXG4gIGNvbm5lY3Rpb25Nb2RlLCAvLzogQ29ubmVjdGlvbk1vZGUsXG4gIGlzVGFyZ2V0LCAvLzogYm9vbGVhbixcbiAgbm9kZUlkLCAvLzogRWxlbWVudElkLFxuICBoYW5kbGVJZCwgLy86IEVsZW1lbnRJZCB8IG51bGwsXG4gIGlzVmFsaWRDb25uZWN0aW9uLCAvLzogVmFsaWRDb25uZWN0aW9uRnVuYyxcbiAgZG9jLCAvLzogRG9jdW1lbnQgfCBTaGFkb3dSb290XG4pIHtcbiAgY29uc3QgZWxlbWVudEJlbG93ID0gZG9jLmVsZW1lbnRGcm9tUG9pbnQoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSk7XG4gIGNvbnN0IGVsZW1lbnRCZWxvd0lzVGFyZ2V0ID0gZWxlbWVudEJlbG93Py5jbGFzc0xpc3QuY29udGFpbnMoJ3RhcmdldCcpIHx8IGZhbHNlO1xuICBjb25zdCBlbGVtZW50QmVsb3dJc1NvdXJjZSA9IGVsZW1lbnRCZWxvdz8uY2xhc3NMaXN0LmNvbnRhaW5zKCdzb3VyY2UnKSB8fCBmYWxzZTtcblxuICBjb25zdCByZXN1bHQgPSB7IC8vcmVzdWx0OiBSZXN1bHQgXG4gICAgZWxlbWVudEJlbG93LFxuICAgIGlzVmFsaWQ6IGZhbHNlLFxuICAgIGNvbm5lY3Rpb246IHsgc291cmNlOiBudWxsLCB0YXJnZXQ6IG51bGwsIHNvdXJjZUhhbmRsZTogbnVsbCwgdGFyZ2V0SGFuZGxlOiBudWxsIH0sXG4gICAgaXNIb3ZlcmluZ0hhbmRsZTogZmFsc2UsXG4gIH07XG5cbiAgaWYgKGVsZW1lbnRCZWxvdyAmJiAoZWxlbWVudEJlbG93SXNUYXJnZXQgfHwgZWxlbWVudEJlbG93SXNTb3VyY2UpKSB7XG4gICAgcmVzdWx0LmlzSG92ZXJpbmdIYW5kbGUgPSB0cnVlO1xuXG4gICAgLy8gaW4gc3RyaWN0IG1vZGUgd2UgZG9uJ3QgYWxsb3cgdGFyZ2V0IHRvIHRhcmdldCBvciBzb3VyY2UgdG8gc291cmNlIGNvbm5lY3Rpb25zXG4gICAgY29uc3QgaXNWYWxpZCA9XG4gICAgICBjb25uZWN0aW9uTW9kZSA9PT0gQ29ubmVjdGlvbk1vZGUuU3RyaWN0XG4gICAgICAgID8gKGlzVGFyZ2V0ICYmIGVsZW1lbnRCZWxvd0lzU291cmNlKSB8fCAoIWlzVGFyZ2V0ICYmIGVsZW1lbnRCZWxvd0lzVGFyZ2V0KVxuICAgICAgICA6IHRydWU7XG5cbiAgICBpZiAoaXNWYWxpZCkge1xuICAgICAgY29uc3QgZWxlbWVudEJlbG93Tm9kZUlkID0gZWxlbWVudEJlbG93LmdldEF0dHJpYnV0ZSgnZGF0YS1ub2RlaWQnKTtcbiAgICAgIGNvbnN0IGVsZW1lbnRCZWxvd0hhbmRsZUlkID0gZWxlbWVudEJlbG93LmdldEF0dHJpYnV0ZSgnZGF0YS1oYW5kbGVpZCcpO1xuICAgICAgY29uc3QgY29ubmVjdGlvbiA9IGlzVGFyZ2V0IC8vY29ubmVjdGlvbjogQ29ubmVjdGlvblxuICAgICAgICA/IHtcbiAgICAgICAgICAgIHNvdXJjZTogZWxlbWVudEJlbG93Tm9kZUlkLFxuICAgICAgICAgICAgc291cmNlSGFuZGxlOiBlbGVtZW50QmVsb3dIYW5kbGVJZCxcbiAgICAgICAgICAgIHRhcmdldDogbm9kZUlkLFxuICAgICAgICAgICAgdGFyZ2V0SGFuZGxlOiBoYW5kbGVJZCxcbiAgICAgICAgICB9XG4gICAgICAgIDoge1xuICAgICAgICAgICAgc291cmNlOiBub2RlSWQsXG4gICAgICAgICAgICBzb3VyY2VIYW5kbGU6IGhhbmRsZUlkLFxuICAgICAgICAgICAgdGFyZ2V0OiBlbGVtZW50QmVsb3dOb2RlSWQsXG4gICAgICAgICAgICB0YXJnZXRIYW5kbGU6IGVsZW1lbnRCZWxvd0hhbmRsZUlkLFxuICAgICAgICAgIH07XG5cbiAgICAgIHJlc3VsdC5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgIHJlc3VsdC5pc1ZhbGlkID0gaXNWYWxpZENvbm5lY3Rpb24oY29ubmVjdGlvbik7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZnVuY3Rpb24gcmVzZXRSZWNlbnRIYW5kbGUoaG92ZXJlZEhhbmRsZSkgeyAvLyhob3ZlcmVkSGFuZGxlOiBFbGVtZW50KTogdm9pZFxuICBob3ZlcmVkSGFuZGxlPy5jbGFzc0xpc3QucmVtb3ZlKCdyZWFjdC1mbG93X19oYW5kbGUtdmFsaWQnKTtcbiAgaG92ZXJlZEhhbmRsZT8uY2xhc3NMaXN0LnJlbW92ZSgncmVhY3QtZmxvd19faGFuZGxlLWNvbm5lY3RpbmcnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG9uTW91c2VEb3duKFxuICBldmVudCwgLy86IFJlYWN0TW91c2VFdmVudCxcbiAgaGFuZGxlSWQsIC8vOiBFbGVtZW50SWQgfCBudWxsLFxuICBub2RlSWQsIC8vOiBFbGVtZW50SWQsXG4gIHNldFN0YXRlLFxuICAvL3NldENvbm5lY3Rpb25Ob2RlSWQsIC8vOiBTZXRTb3VyY2VJZEZ1bmMsXG4gIC8vc2V0UG9zaXRpb24sIC8vOiBTZXRQb3NpdGlvbixcbiAgb25Db25uZWN0LCAvLzogT25Db25uZWN0RnVuYyxcbiAgaXNUYXJnZXQsIC8vOiBib29sZWFuLFxuICBpc1ZhbGlkQ29ubmVjdGlvbiwgLy86IFZhbGlkQ29ubmVjdGlvbkZ1bmMsXG4gIGNvbm5lY3Rpb25Nb2RlLCAvLzogQ29ubmVjdGlvbk1vZGUsXG4gIGVsZW1lbnRFZGdlVXBkYXRlclR5cGUsIC8vPzogSGFuZGxlVHlwZSxcbiAgb25FZGdlVXBkYXRlRW5kLCAvLz86IChldnQ6IE1vdXNlRXZlbnQpID0+IHZvaWQsXG4gIG9uQ29ubmVjdFN0YXJ0LCAvLz86IE9uQ29ubmVjdFN0YXJ0RnVuYyxcbiAgb25Db25uZWN0U3RvcCwgLy8/OiBPbkNvbm5lY3RTdG9wRnVuYyxcbiAgb25Db25uZWN0RW5kLCAvLz86IE9uQ29ubmVjdEVuZEZ1bmNcbikgeyAvLzogdm9pZFxuICAvL2NvbnNvbGUuZGVidWcoXCJvbk1vdXNlRG93bigpXCIpO1xuICBjb25zdCByZWFjdEZsb3dOb2RlID0gKGV2ZW50LnRhcmdldCkuY2xvc2VzdCgnLnJlYWN0LWZsb3cnKTtcbiAgLy8gd2hlbiByZWFjdC1mbG93IGlzIHVzZWQgaW5zaWRlIGEgc2hhZG93IHJvb3Qgd2UgY2FuJ3QgdXNlIGRvY3VtZW50XG4gIGNvbnN0IGRvYyA9IGdldEhvc3RGb3JFbGVtZW50KGV2ZW50LnRhcmdldCk7XG5cbiAgaWYgKCFkb2MpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBlbGVtZW50QmVsb3cgPSBkb2MuZWxlbWVudEZyb21Qb2ludChldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZKTtcbiAgY29uc3QgZWxlbWVudEJlbG93SXNUYXJnZXQgPSBlbGVtZW50QmVsb3c/LmNsYXNzTGlzdC5jb250YWlucygndGFyZ2V0Jyk7XG4gIGNvbnN0IGVsZW1lbnRCZWxvd0lzU291cmNlID0gZWxlbWVudEJlbG93Py5jbGFzc0xpc3QuY29udGFpbnMoJ3NvdXJjZScpO1xuXG4gIGlmICghcmVhY3RGbG93Tm9kZSB8fCAoIWVsZW1lbnRCZWxvd0lzVGFyZ2V0ICYmICFlbGVtZW50QmVsb3dJc1NvdXJjZSAmJiAhZWxlbWVudEVkZ2VVcGRhdGVyVHlwZSkpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBoYW5kbGVUeXBlID0gZWxlbWVudEVkZ2VVcGRhdGVyVHlwZSA/IGVsZW1lbnRFZGdlVXBkYXRlclR5cGUgOiBlbGVtZW50QmVsb3dJc1RhcmdldCA/ICd0YXJnZXQnIDogJ3NvdXJjZSc7XG4gIGNvbnN0IGNvbnRhaW5lckJvdW5kcyA9IHJlYWN0Rmxvd05vZGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gIGxldCByZWNlbnRIb3ZlcmVkSGFuZGxlOyAvLzogRWxlbWVudDtcblxuICAvL3NldFBvc2l0aW9uKHtcbiAgLy8gIHg6IGV2ZW50LmNsaWVudFggLSBjb250YWluZXJCb3VuZHMubGVmdCxcbiAgLy8gIHk6IGV2ZW50LmNsaWVudFkgLSBjb250YWluZXJCb3VuZHMudG9wLFxuICAvL30pO1xuXG4gIC8vc2V0Q29ubmVjdGlvbk5vZGVJZCh7IGNvbm5lY3Rpb25Ob2RlSWQ6IG5vZGVJZCwgY29ubmVjdGlvbkhhbmRsZUlkOiBoYW5kbGVJZCwgY29ubmVjdGlvbkhhbmRsZVR5cGU6IGhhbmRsZVR5cGUgfSk7XG4gIHNldFN0YXRlKHtcbiAgICAgIGNvbm5lY3Rpb25Qb3NpdGlvbjoge1xuICAgICAgICAgIHg6IGV2ZW50LmNsaWVudFggLSBjb250YWluZXJCb3VuZHMubGVmdCxcbiAgICAgICAgICB5OiBldmVudC5jbGllbnRZIC0gY29udGFpbmVyQm91bmRzLnRvcCxcbiAgICAgIH0sXG4gICAgICBjb25uZWN0aW9uTm9kZUlkOiBub2RlSWQsXG4gICAgICBjb25uZWN0aW9uSGFuZGxlSWQ6IGhhbmRsZUlkLFxuICAgICAgY29ubmVjdGlvbkhhbmRsZVR5cGU6IGhhbmRsZVR5cGUsXG4gIH0pO1xuXG4gIG9uQ29ubmVjdFN0YXJ0Py4oZXZlbnQsIHsgbm9kZUlkLCBoYW5kbGVJZCwgaGFuZGxlVHlwZSB9KTtcblxuICBmdW5jdGlvbiBvbk1vdXNlTW92ZShldmVudCkgeyAvLyhldmVudDogTW91c2VFdmVudClcbiAgICAvL2NvbnNvbGUuZGVidWcoXCJvbk1vdXNlTW92ZSgpIFwiK2RvYyk7XG4gICAgLy9zZXRQb3NpdGlvbih7XG4gICAgLy8gIHg6IGV2ZW50LmNsaWVudFggLSBjb250YWluZXJCb3VuZHMubGVmdCxcbiAgICAvLyAgeTogZXZlbnQuY2xpZW50WSAtIGNvbnRhaW5lckJvdW5kcy50b3AsXG4gICAgLy99KTtcbiAgICBzZXRTdGF0ZSh7XG4gICAgICAgIGNvbm5lY3Rpb25Qb3NpdGlvbjoge1xuICAgICAgICAgICAgeDogZXZlbnQuY2xpZW50WCAtIGNvbnRhaW5lckJvdW5kcy5sZWZ0LFxuICAgICAgICAgICAgeTogZXZlbnQuY2xpZW50WSAtIGNvbnRhaW5lckJvdW5kcy50b3AsXG4gICAgICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCB7IGNvbm5lY3Rpb24sIGVsZW1lbnRCZWxvdywgaXNWYWxpZCwgaXNIb3ZlcmluZ0hhbmRsZSB9ID0gY2hlY2tFbGVtZW50QmVsb3dJc1ZhbGlkKFxuICAgICAgZXZlbnQsXG4gICAgICBjb25uZWN0aW9uTW9kZSxcbiAgICAgIGlzVGFyZ2V0LFxuICAgICAgbm9kZUlkLFxuICAgICAgaGFuZGxlSWQsXG4gICAgICBpc1ZhbGlkQ29ubmVjdGlvbixcbiAgICAgIGRvY1xuICAgICk7XG5cbiAgICBpZiAoIWlzSG92ZXJpbmdIYW5kbGUpIHtcbiAgICAgIHJldHVybiByZXNldFJlY2VudEhhbmRsZShyZWNlbnRIb3ZlcmVkSGFuZGxlKTtcbiAgICB9XG5cbiAgICBjb25zdCBpc093bkhhbmRsZSA9IGNvbm5lY3Rpb24uc291cmNlID09PSBjb25uZWN0aW9uLnRhcmdldDtcblxuICAgIGlmICghaXNPd25IYW5kbGUgJiYgZWxlbWVudEJlbG93KSB7XG4gICAgICByZWNlbnRIb3ZlcmVkSGFuZGxlID0gZWxlbWVudEJlbG93O1xuICAgICAgZWxlbWVudEJlbG93LmNsYXNzTGlzdC5hZGQoJ3JlYWN0LWZsb3dfX2hhbmRsZS1jb25uZWN0aW5nJyk7XG4gICAgICBlbGVtZW50QmVsb3cuY2xhc3NMaXN0LnRvZ2dsZSgncmVhY3QtZmxvd19faGFuZGxlLXZhbGlkJywgaXNWYWxpZCk7XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gb25Nb3VzZVVwKGV2ZW50KSB7IC8vKGV2ZW50OiBNb3VzZUV2ZW50KVxuICAgIC8vY29uc29sZS5kZWJ1ZyhcIm9uTW91c2VVcCgpXCIpO1xuICAgIGNvbnN0IHsgY29ubmVjdGlvbiwgaXNWYWxpZCB9ID0gY2hlY2tFbGVtZW50QmVsb3dJc1ZhbGlkKFxuICAgICAgZXZlbnQsXG4gICAgICBjb25uZWN0aW9uTW9kZSxcbiAgICAgIGlzVGFyZ2V0LFxuICAgICAgbm9kZUlkLFxuICAgICAgaGFuZGxlSWQsXG4gICAgICBpc1ZhbGlkQ29ubmVjdGlvbixcbiAgICAgIGRvY1xuICAgICk7XG5cbiAgICBvbkNvbm5lY3RTdG9wPy4oZXZlbnQpO1xuXG4gICAgaWYgKGlzVmFsaWQpIHtcbiAgICAgIG9uQ29ubmVjdD8uKGNvbm5lY3Rpb24pO1xuICAgIH1cblxuICAgIG9uQ29ubmVjdEVuZD8uKGV2ZW50KTtcblxuICAgIGlmIChlbGVtZW50RWRnZVVwZGF0ZXJUeXBlICYmIG9uRWRnZVVwZGF0ZUVuZCkge1xuICAgICAgb25FZGdlVXBkYXRlRW5kKGV2ZW50KTtcbiAgICB9XG5cbiAgICByZXNldFJlY2VudEhhbmRsZShyZWNlbnRIb3ZlcmVkSGFuZGxlKTtcbiAgICAvL3NldENvbm5lY3Rpb25Ob2RlSWQoeyBjb25uZWN0aW9uTm9kZUlkOiBudWxsLCBjb25uZWN0aW9uSGFuZGxlSWQ6IG51bGwsIGNvbm5lY3Rpb25IYW5kbGVUeXBlOiBudWxsIH0pO1xuICAgIHNldFN0YXRlKHtcbiAgICAgICAgY29ubmVjdGlvbk5vZGVJZDogbnVsbCxcbiAgICAgICAgY29ubmVjdGlvbkhhbmRsZUlkOiBudWxsLFxuICAgICAgICBjb25uZWN0aW9uSGFuZGxlVHlwZTogbnVsbCxcbiAgICB9KTtcblxuICAgIGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvbk1vdXNlTW92ZSk7IC8vIGFzIEV2ZW50TGlzdGVuZXJPckV2ZW50TGlzdGVuZXJPYmplY3QpO1xuICAgIGRvYy5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgb25Nb3VzZVVwKTsgLy8gYXMgRXZlbnRMaXN0ZW5lck9yRXZlbnRMaXN0ZW5lck9iamVjdCk7XG4gIH1cblxuICBkb2MuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgb25Nb3VzZU1vdmUpOyAvLyBhcyBFdmVudExpc3RlbmVyT3JFdmVudExpc3RlbmVyT2JqZWN0KTtcbiAgZG9jLmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCBvbk1vdXNlVXApOyAvLyBhcyBFdmVudExpc3RlbmVyT3JFdmVudExpc3RlbmVyT2JqZWN0KTtcbn1cbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/api/leafui/elements/floweditor/leafnodetypes/porthandle/handler.js\n\n}");
22680
22680
 
22681
22681
  /***/ }),
22682
22682
 
@@ -22750,16 +22750,6 @@ eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpa
22750
22750
 
22751
22751
  /***/ }),
22752
22752
 
22753
- /***/ "./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/core/dist/esm/index.mjs":
22754
- /*!******************************************************************************************!*\
22755
- !*** ./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/core/dist/esm/index.mjs ***!
22756
- \******************************************************************************************/
22757
- /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
22758
-
22759
- eval("{__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ BaseEdge: () => (/* binding */ BaseEdge),\n/* harmony export */ BezierEdge: () => (/* binding */ BezierEdge),\n/* harmony export */ ConnectionLineType: () => (/* binding */ ConnectionLineType),\n/* harmony export */ ConnectionMode: () => (/* binding */ ConnectionMode),\n/* harmony export */ EdgeLabelRenderer: () => (/* binding */ EdgeLabelRenderer),\n/* harmony export */ EdgeText: () => (/* binding */ EdgeText$1),\n/* harmony export */ Handle: () => (/* binding */ Handle$1),\n/* harmony export */ MarkerType: () => (/* binding */ MarkerType),\n/* harmony export */ PanOnScrollMode: () => (/* binding */ PanOnScrollMode),\n/* harmony export */ Panel: () => (/* binding */ Panel),\n/* harmony export */ Position: () => (/* binding */ Position),\n/* harmony export */ ReactFlow: () => (/* binding */ ReactFlow),\n/* harmony export */ ReactFlowProvider: () => (/* binding */ ReactFlowProvider),\n/* harmony export */ SelectionMode: () => (/* binding */ SelectionMode),\n/* harmony export */ SimpleBezierEdge: () => (/* binding */ SimpleBezierEdge),\n/* harmony export */ SmoothStepEdge: () => (/* binding */ SmoothStepEdge),\n/* harmony export */ StepEdge: () => (/* binding */ StepEdge),\n/* harmony export */ StraightEdge: () => (/* binding */ StraightEdge),\n/* harmony export */ addEdge: () => (/* binding */ addEdge),\n/* harmony export */ applyEdgeChanges: () => (/* binding */ applyEdgeChanges),\n/* harmony export */ applyNodeChanges: () => (/* binding */ applyNodeChanges),\n/* harmony export */ boxToRect: () => (/* binding */ boxToRect),\n/* harmony export */ clamp: () => (/* binding */ clamp),\n/* harmony export */ getBezierPath: () => (/* binding */ getBezierPath),\n/* harmony export */ getBoundsOfRects: () => (/* binding */ getBoundsOfRects),\n/* harmony export */ getConnectedEdges: () => (/* binding */ getConnectedEdges),\n/* harmony export */ getEdgeCenter: () => (/* binding */ getEdgeCenter),\n/* harmony export */ getHostForElement: () => (/* binding */ getHostForElement),\n/* harmony export */ getIncomers: () => (/* binding */ getIncomers),\n/* harmony export */ getMarkerEnd: () => (/* binding */ getMarkerEnd),\n/* harmony export */ getNodePositionWithOrigin: () => (/* binding */ getNodePositionWithOrigin),\n/* harmony export */ getNodesBounds: () => (/* binding */ getNodesBounds),\n/* harmony export */ getOutgoers: () => (/* binding */ getOutgoers),\n/* harmony export */ getRectOfNodes: () => (/* binding */ getRectOfNodes),\n/* harmony export */ getSimpleBezierPath: () => (/* binding */ getSimpleBezierPath),\n/* harmony export */ getSmoothStepPath: () => (/* binding */ getSmoothStepPath),\n/* harmony export */ getStraightPath: () => (/* binding */ getStraightPath),\n/* harmony export */ getTransformForBounds: () => (/* binding */ getTransformForBounds),\n/* harmony export */ getViewportForBounds: () => (/* binding */ getViewportForBounds),\n/* harmony export */ handleParentExpand: () => (/* binding */ handleParentExpand),\n/* harmony export */ internalsSymbol: () => (/* binding */ internalsSymbol),\n/* harmony export */ isEdge: () => (/* binding */ isEdge),\n/* harmony export */ isNode: () => (/* binding */ isNode),\n/* harmony export */ rectToBox: () => (/* binding */ rectToBox),\n/* harmony export */ updateEdge: () => (/* binding */ updateEdge),\n/* harmony export */ useEdges: () => (/* binding */ useEdges),\n/* harmony export */ useEdgesState: () => (/* binding */ useEdgesState),\n/* harmony export */ useGetPointerPosition: () => (/* binding */ useGetPointerPosition),\n/* harmony export */ useKeyPress: () => (/* binding */ useKeyPress),\n/* harmony export */ useNodeId: () => (/* binding */ useNodeId),\n/* harmony export */ useNodes: () => (/* binding */ useNodes),\n/* harmony export */ useNodesInitialized: () => (/* binding */ useNodesInitialized),\n/* harmony export */ useNodesState: () => (/* binding */ useNodesState),\n/* harmony export */ useOnSelectionChange: () => (/* binding */ useOnSelectionChange),\n/* harmony export */ useOnViewportChange: () => (/* binding */ useOnViewportChange),\n/* harmony export */ useReactFlow: () => (/* binding */ useReactFlow),\n/* harmony export */ useStore: () => (/* binding */ useStore),\n/* harmony export */ useStoreApi: () => (/* binding */ useStoreApi),\n/* harmony export */ useUpdateNodeInternals: () => (/* binding */ useUpdateNodeInternals),\n/* harmony export */ useViewport: () => (/* binding */ useViewport)\n/* harmony export */ });\n/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ \"react\");\n/* harmony import */ var classcat__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! classcat */ \"./node_modules/classcat/index.js\");\n/* harmony import */ var zustand_traditional__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! zustand/traditional */ \"./node_modules/zustand/esm/traditional.mjs\");\n/* harmony import */ var zustand_shallow__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! zustand/shallow */ \"./node_modules/zustand/esm/vanilla/shallow.mjs\");\n/* harmony import */ var d3_zoom__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! d3-zoom */ \"./node_modules/d3-zoom/src/index.js\");\n/* harmony import */ var d3_selection__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! d3-selection */ \"./node_modules/d3-selection/src/select.js\");\n/* harmony import */ var d3_selection__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! d3-selection */ \"./node_modules/d3-selection/src/pointer.js\");\n/* harmony import */ var d3_drag__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! d3-drag */ \"./node_modules/d3-drag/src/drag.js\");\n/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! react-dom */ \"react-dom\");\n\n\n\n\n\n\n\n\n\nconst StoreContext = (0,react__WEBPACK_IMPORTED_MODULE_0__.createContext)(null);\nconst Provider$1 = StoreContext.Provider;\n\nconst errorMessages = {\n error001: () => '[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001',\n error002: () => \"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.\",\n error003: (nodeType) => `Node type \"${nodeType}\" not found. Using fallback type \"default\".`,\n error004: () => 'The React Flow parent container needs a width and a height to render the graph.',\n error005: () => 'Only child nodes can use a parent extent.',\n error006: () => \"Can't create edge. An edge needs a source and a target.\",\n error007: (id) => `The old edge with id=${id} does not exist.`,\n error009: (type) => `Marker type \"${type}\" doesn't exist.`,\n error008: (sourceHandle, edge) => `Couldn't create edge for ${!sourceHandle ? 'source' : 'target'} handle id: \"${!sourceHandle ? edge.sourceHandle : edge.targetHandle}\", edge id: ${edge.id}.`,\n error010: () => 'Handle: No node id found. Make sure to only use a Handle inside a custom Node.',\n error011: (edgeType) => `Edge type \"${edgeType}\" not found. Using fallback type \"default\".`,\n error012: (id) => `Node with id \"${id}\" does not exist, it may have been removed. This can happen when a node is deleted before the \"onNodeClick\" handler is called.`,\n};\n\nconst zustandErrorMessage = errorMessages['error001']();\nfunction useStore(selector, equalityFn) {\n const store = (0,react__WEBPACK_IMPORTED_MODULE_0__.useContext)(StoreContext);\n if (store === null) {\n throw new Error(zustandErrorMessage);\n }\n return (0,zustand_traditional__WEBPACK_IMPORTED_MODULE_4__.useStoreWithEqualityFn)(store, selector, equalityFn);\n}\nconst useStoreApi = () => {\n const store = (0,react__WEBPACK_IMPORTED_MODULE_0__.useContext)(StoreContext);\n if (store === null) {\n throw new Error(zustandErrorMessage);\n }\n return (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => ({\n getState: store.getState,\n setState: store.setState,\n subscribe: store.subscribe,\n destroy: store.destroy,\n }), [store]);\n};\n\nconst selector$g = (s) => (s.userSelectionActive ? 'none' : 'all');\nfunction Panel({ position, children, className, style, ...rest }) {\n const pointerEvents = useStore(selector$g);\n const positionClasses = `${position}`.split('-');\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(['react-flow__panel', className, ...positionClasses]), style: { ...style, pointerEvents }, ...rest }, children));\n}\n\nfunction Attribution({ proOptions, position = 'bottom-right' }) {\n if (proOptions?.hideAttribution) {\n return null;\n }\n return null;\n // spark_dev_note: no attribution for now.\n //(React.createElement(Panel, { position: position, className: \"react-flow__attribution\", \"data-message\": \"Please only hide this attribution when you are subscribed to React Flow Pro: https://reactflow.dev/pro\" },\n // React.createElement(\"a\", { href: \"https://reactflow.dev\", target: \"_blank\", rel: \"noopener noreferrer\", \"aria-label\": \"React Flow attribution\" }, \"React Flow\")));\n}\n\nconst EdgeText = ({ x, y, label, labelStyle = {}, labelShowBg = true, labelBgStyle = {}, labelBgPadding = [2, 4], labelBgBorderRadius = 2, children, className, ...rest }) => {\n const edgeRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n const [edgeTextBbox, setEdgeTextBbox] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)({ x: 0, y: 0, width: 0, height: 0 });\n const edgeTextClasses = (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(['react-flow__edge-textwrapper', className]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (edgeRef.current) {\n const textBbox = edgeRef.current.getBBox();\n setEdgeTextBbox({\n x: textBbox.x,\n y: textBbox.y,\n width: textBbox.width,\n height: textBbox.height,\n });\n }\n }, [label]);\n if (typeof label === 'undefined' || !label) {\n return null;\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"g\", { transform: `translate(${x - edgeTextBbox.width / 2} ${y - edgeTextBbox.height / 2})`, className: edgeTextClasses, visibility: edgeTextBbox.width ? 'visible' : 'hidden', ...rest },\n labelShowBg && (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"rect\", { width: edgeTextBbox.width + 2 * labelBgPadding[0], x: -labelBgPadding[0], y: -labelBgPadding[1], height: edgeTextBbox.height + 2 * labelBgPadding[1], className: \"react-flow__edge-textbg\", style: labelBgStyle, rx: labelBgBorderRadius, ry: labelBgBorderRadius })),\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"text\", { className: \"react-flow__edge-text\", y: edgeTextBbox.height / 2, dy: \"0.3em\", ref: edgeRef, style: labelStyle }, label),\n children));\n};\nvar EdgeText$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(EdgeText);\n\nconst getDimensions = (node) => ({\n width: node.offsetWidth,\n height: node.offsetHeight,\n});\nconst clamp = (val, min = 0, max = 1) => Math.min(Math.max(val, min), max);\nconst clampPosition = (position = { x: 0, y: 0 }, extent) => ({\n x: clamp(position.x, extent[0][0], extent[1][0]),\n y: clamp(position.y, extent[0][1], extent[1][1]),\n});\n// returns a number between 0 and 1 that represents the velocity of the movement\n// when the mouse is close to the edge of the canvas\nconst calcAutoPanVelocity = (value, min, max) => {\n if (value < min) {\n return clamp(Math.abs(value - min), 1, 50) / 50;\n }\n else if (value > max) {\n return -clamp(Math.abs(value - max), 1, 50) / 50;\n }\n return 0;\n};\nconst calcAutoPan = (pos, bounds) => {\n const xMovement = calcAutoPanVelocity(pos.x, 35, bounds.width - 35) * 20;\n const yMovement = calcAutoPanVelocity(pos.y, 35, bounds.height - 35) * 20;\n return [xMovement, yMovement];\n};\nconst getHostForElement = (element) => element.getRootNode?.() || window?.document;\nconst getBoundsOfBoxes = (box1, box2) => ({\n x: Math.min(box1.x, box2.x),\n y: Math.min(box1.y, box2.y),\n x2: Math.max(box1.x2, box2.x2),\n y2: Math.max(box1.y2, box2.y2),\n});\nconst rectToBox = ({ x, y, width, height }) => ({\n x,\n y,\n x2: x + width,\n y2: y + height,\n});\nconst boxToRect = ({ x, y, x2, y2 }) => ({\n x,\n y,\n width: x2 - x,\n height: y2 - y,\n});\nconst nodeToRect = (node) => ({\n ...(node.positionAbsolute || { x: 0, y: 0 }),\n width: node.width || 0,\n height: node.height || 0,\n});\nconst getBoundsOfRects = (rect1, rect2) => boxToRect(getBoundsOfBoxes(rectToBox(rect1), rectToBox(rect2)));\nconst getOverlappingArea = (rectA, rectB) => {\n const xOverlap = Math.max(0, Math.min(rectA.x + rectA.width, rectB.x + rectB.width) - Math.max(rectA.x, rectB.x));\n const yOverlap = Math.max(0, Math.min(rectA.y + rectA.height, rectB.y + rectB.height) - Math.max(rectA.y, rectB.y));\n return Math.ceil(xOverlap * yOverlap);\n};\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nconst isRectObject = (obj) => isNumeric(obj.width) && isNumeric(obj.height) && isNumeric(obj.x) && isNumeric(obj.y);\n/* eslint-disable-next-line @typescript-eslint/no-explicit-any */\nconst isNumeric = (n) => !isNaN(n) && isFinite(n);\nconst internalsSymbol = Symbol.for('internals');\n// used for a11y key board controls for nodes and edges\nconst elementSelectionKeys = ['Enter', ' ', 'Escape'];\nconst devWarn = (id, message) => {\n if (true) {\n console.warn(`[React Flow]: ${message} Help: https://reactflow.dev/error#${id}`);\n }\n};\nconst isReactKeyboardEvent = (event) => 'nativeEvent' in event;\nfunction isInputDOMNode(event) {\n const kbEvent = isReactKeyboardEvent(event) ? event.nativeEvent : event;\n // using composed path for handling shadow dom\n const target = (kbEvent.composedPath?.()?.[0] || event.target);\n const isInput = ['INPUT', 'SELECT', 'TEXTAREA'].includes(target?.nodeName) || target?.hasAttribute('contenteditable');\n // when an input field is focused we don't want to trigger deletion or movement of nodes\n return isInput || !!target?.closest('.nokey');\n}\nconst isMouseEvent = (event) => 'clientX' in event;\nconst getEventPosition = (event, bounds) => {\n const isMouseTriggered = isMouseEvent(event);\n const evtX = isMouseTriggered ? event.clientX : event.touches?.[0].clientX;\n const evtY = isMouseTriggered ? event.clientY : event.touches?.[0].clientY;\n return {\n x: evtX - (bounds?.left ?? 0),\n y: evtY - (bounds?.top ?? 0),\n };\n};\nconst isMacOs = () => typeof navigator !== 'undefined' && navigator?.userAgent?.indexOf('Mac') >= 0;\n\nconst BaseEdge = ({ id, path, labelX, labelY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, interactionWidth = 20, }) => {\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"path\", { id: id, style: style, d: path, fill: \"none\", className: \"react-flow__edge-path\", markerEnd: markerEnd, markerStart: markerStart }),\n interactionWidth && (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"path\", { d: path, fill: \"none\", strokeOpacity: 0, strokeWidth: interactionWidth, className: \"react-flow__edge-interaction\" })),\n label && isNumeric(labelX) && isNumeric(labelY) ? (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(EdgeText$1, { x: labelX, y: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius })) : null));\n};\nBaseEdge.displayName = 'BaseEdge';\n\nconst getMarkerEnd = (markerType, markerEndId) => {\n if (typeof markerEndId !== 'undefined' && markerEndId) {\n return `url(#${markerEndId})`;\n }\n return typeof markerType !== 'undefined' ? `url(#react-flow__${markerType})` : 'none';\n};\nfunction getMouseHandler$1(id, getState, handler) {\n return handler === undefined\n ? handler\n : (event) => {\n const edge = getState().edges.find((e) => e.id === id);\n if (edge) {\n handler(event, { ...edge });\n }\n };\n}\n// this is used for straight edges and simple smoothstep edges (LTR, RTL, BTT, TTB)\nfunction getEdgeCenter({ sourceX, sourceY, targetX, targetY, }) {\n const xOffset = Math.abs(targetX - sourceX) / 2;\n const centerX = targetX < sourceX ? targetX + xOffset : targetX - xOffset;\n const yOffset = Math.abs(targetY - sourceY) / 2;\n const centerY = targetY < sourceY ? targetY + yOffset : targetY - yOffset;\n return [centerX, centerY, xOffset, yOffset];\n}\nfunction getBezierEdgeCenter({ sourceX, sourceY, targetX, targetY, sourceControlX, sourceControlY, targetControlX, targetControlY, }) {\n // cubic bezier t=0.5 mid point, not the actual mid point, but easy to calculate\n // https://stackoverflow.com/questions/67516101/how-to-find-distance-mid-point-of-bezier-curve\n const centerX = sourceX * 0.125 + sourceControlX * 0.375 + targetControlX * 0.375 + targetX * 0.125;\n const centerY = sourceY * 0.125 + sourceControlY * 0.375 + targetControlY * 0.375 + targetY * 0.125;\n const offsetX = Math.abs(centerX - sourceX);\n const offsetY = Math.abs(centerY - sourceY);\n return [centerX, centerY, offsetX, offsetY];\n}\n\nvar ConnectionMode;\n(function (ConnectionMode) {\n ConnectionMode[\"Strict\"] = \"strict\";\n ConnectionMode[\"Loose\"] = \"loose\";\n})(ConnectionMode || (ConnectionMode = {}));\nvar PanOnScrollMode;\n(function (PanOnScrollMode) {\n PanOnScrollMode[\"Free\"] = \"free\";\n PanOnScrollMode[\"Vertical\"] = \"vertical\";\n PanOnScrollMode[\"Horizontal\"] = \"horizontal\";\n})(PanOnScrollMode || (PanOnScrollMode = {}));\nvar SelectionMode;\n(function (SelectionMode) {\n SelectionMode[\"Partial\"] = \"partial\";\n SelectionMode[\"Full\"] = \"full\";\n})(SelectionMode || (SelectionMode = {}));\n\nvar ConnectionLineType;\n(function (ConnectionLineType) {\n ConnectionLineType[\"Bezier\"] = \"default\";\n ConnectionLineType[\"Straight\"] = \"straight\";\n ConnectionLineType[\"Step\"] = \"step\";\n ConnectionLineType[\"SmoothStep\"] = \"smoothstep\";\n ConnectionLineType[\"SimpleBezier\"] = \"simplebezier\";\n})(ConnectionLineType || (ConnectionLineType = {}));\nvar MarkerType;\n(function (MarkerType) {\n MarkerType[\"Arrow\"] = \"arrow\";\n MarkerType[\"ArrowClosed\"] = \"arrowclosed\";\n})(MarkerType || (MarkerType = {}));\n\nvar Position;\n(function (Position) {\n Position[\"Left\"] = \"left\";\n Position[\"Top\"] = \"top\";\n Position[\"Right\"] = \"right\";\n Position[\"Bottom\"] = \"bottom\";\n})(Position || (Position = {}));\n\nfunction getControl({ pos, x1, y1, x2, y2 }) {\n if (pos === Position.Left || pos === Position.Right) {\n return [0.5 * (x1 + x2), y1];\n }\n return [x1, 0.5 * (y1 + y2)];\n}\nfunction getSimpleBezierPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, }) {\n const [sourceControlX, sourceControlY] = getControl({\n pos: sourcePosition,\n x1: sourceX,\n y1: sourceY,\n x2: targetX,\n y2: targetY,\n });\n const [targetControlX, targetControlY] = getControl({\n pos: targetPosition,\n x1: targetX,\n y1: targetY,\n x2: sourceX,\n y2: sourceY,\n });\n const [labelX, labelY, offsetX, offsetY] = getBezierEdgeCenter({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourceControlX,\n sourceControlY,\n targetControlX,\n targetControlY,\n });\n return [\n `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`,\n labelX,\n labelY,\n offsetX,\n offsetY,\n ];\n}\nconst SimpleBezierEdge = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(({ sourceX, sourceY, targetX, targetY, sourcePosition = Position.Bottom, targetPosition = Position.Top, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, interactionWidth, }) => {\n const [path, labelX, labelY] = getSimpleBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n });\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart, interactionWidth: interactionWidth }));\n});\nSimpleBezierEdge.displayName = 'SimpleBezierEdge';\n\nconst handleDirections = {\n [Position.Left]: { x: -1, y: 0 },\n [Position.Right]: { x: 1, y: 0 },\n [Position.Top]: { x: 0, y: -1 },\n [Position.Bottom]: { x: 0, y: 1 },\n};\nconst getDirection = ({ source, sourcePosition = Position.Bottom, target, }) => {\n if (sourcePosition === Position.Left || sourcePosition === Position.Right) {\n return source.x < target.x ? { x: 1, y: 0 } : { x: -1, y: 0 };\n }\n return source.y < target.y ? { x: 0, y: 1 } : { x: 0, y: -1 };\n};\nconst distance = (a, b) => Math.sqrt(Math.pow(b.x - a.x, 2) + Math.pow(b.y - a.y, 2));\n// ith this function we try to mimic a orthogonal edge routing behaviour\n// It's not as good as a real orthogonal edge routing but it's faster and good enough as a default for step and smooth step edges\nfunction getPoints({ source, sourcePosition = Position.Bottom, target, targetPosition = Position.Top, center, offset, }) {\n const sourceDir = handleDirections[sourcePosition];\n const targetDir = handleDirections[targetPosition];\n const sourceGapped = { x: source.x + sourceDir.x * offset, y: source.y + sourceDir.y * offset };\n const targetGapped = { x: target.x + targetDir.x * offset, y: target.y + targetDir.y * offset };\n const dir = getDirection({\n source: sourceGapped,\n sourcePosition,\n target: targetGapped,\n });\n const dirAccessor = dir.x !== 0 ? 'x' : 'y';\n const currDir = dir[dirAccessor];\n let points = [];\n let centerX, centerY;\n const sourceGapOffset = { x: 0, y: 0 };\n const targetGapOffset = { x: 0, y: 0 };\n const [defaultCenterX, defaultCenterY, defaultOffsetX, defaultOffsetY] = getEdgeCenter({\n sourceX: source.x,\n sourceY: source.y,\n targetX: target.x,\n targetY: target.y,\n });\n // opposite handle positions, default case\n if (sourceDir[dirAccessor] * targetDir[dirAccessor] === -1) {\n centerX = center.x || defaultCenterX;\n centerY = center.y || defaultCenterY;\n // --->\n // |\n // >---\n const verticalSplit = [\n { x: centerX, y: sourceGapped.y },\n { x: centerX, y: targetGapped.y },\n ];\n // |\n // ---\n // |\n const horizontalSplit = [\n { x: sourceGapped.x, y: centerY },\n { x: targetGapped.x, y: centerY },\n ];\n if (sourceDir[dirAccessor] === currDir) {\n points = dirAccessor === 'x' ? verticalSplit : horizontalSplit;\n }\n else {\n points = dirAccessor === 'x' ? horizontalSplit : verticalSplit;\n }\n }\n else {\n // sourceTarget means we take x from source and y from target, targetSource is the opposite\n const sourceTarget = [{ x: sourceGapped.x, y: targetGapped.y }];\n const targetSource = [{ x: targetGapped.x, y: sourceGapped.y }];\n // this handles edges with same handle positions\n if (dirAccessor === 'x') {\n points = sourceDir.x === currDir ? targetSource : sourceTarget;\n }\n else {\n points = sourceDir.y === currDir ? sourceTarget : targetSource;\n }\n if (sourcePosition === targetPosition) {\n const diff = Math.abs(source[dirAccessor] - target[dirAccessor]);\n // if an edge goes from right to right for example (sourcePosition === targetPosition) and the distance between source.x and target.x is less than the offset, the added point and the gapped source/target will overlap. This leads to a weird edge path. To avoid this we add a gapOffset to the source/target\n if (diff <= offset) {\n const gapOffset = Math.min(offset - 1, offset - diff);\n if (sourceDir[dirAccessor] === currDir) {\n sourceGapOffset[dirAccessor] = (sourceGapped[dirAccessor] > source[dirAccessor] ? -1 : 1) * gapOffset;\n }\n else {\n targetGapOffset[dirAccessor] = (targetGapped[dirAccessor] > target[dirAccessor] ? -1 : 1) * gapOffset;\n }\n }\n }\n // these are conditions for handling mixed handle positions like Right -> Bottom for example\n if (sourcePosition !== targetPosition) {\n const dirAccessorOpposite = dirAccessor === 'x' ? 'y' : 'x';\n const isSameDir = sourceDir[dirAccessor] === targetDir[dirAccessorOpposite];\n const sourceGtTargetOppo = sourceGapped[dirAccessorOpposite] > targetGapped[dirAccessorOpposite];\n const sourceLtTargetOppo = sourceGapped[dirAccessorOpposite] < targetGapped[dirAccessorOpposite];\n const flipSourceTarget = (sourceDir[dirAccessor] === 1 && ((!isSameDir && sourceGtTargetOppo) || (isSameDir && sourceLtTargetOppo))) ||\n (sourceDir[dirAccessor] !== 1 && ((!isSameDir && sourceLtTargetOppo) || (isSameDir && sourceGtTargetOppo)));\n if (flipSourceTarget) {\n points = dirAccessor === 'x' ? sourceTarget : targetSource;\n }\n }\n const sourceGapPoint = { x: sourceGapped.x + sourceGapOffset.x, y: sourceGapped.y + sourceGapOffset.y };\n const targetGapPoint = { x: targetGapped.x + targetGapOffset.x, y: targetGapped.y + targetGapOffset.y };\n const maxXDistance = Math.max(Math.abs(sourceGapPoint.x - points[0].x), Math.abs(targetGapPoint.x - points[0].x));\n const maxYDistance = Math.max(Math.abs(sourceGapPoint.y - points[0].y), Math.abs(targetGapPoint.y - points[0].y));\n // we want to place the label on the longest segment of the edge\n if (maxXDistance >= maxYDistance) {\n centerX = (sourceGapPoint.x + targetGapPoint.x) / 2;\n centerY = points[0].y;\n }\n else {\n centerX = points[0].x;\n centerY = (sourceGapPoint.y + targetGapPoint.y) / 2;\n }\n }\n const pathPoints = [\n source,\n { x: sourceGapped.x + sourceGapOffset.x, y: sourceGapped.y + sourceGapOffset.y },\n ...points,\n { x: targetGapped.x + targetGapOffset.x, y: targetGapped.y + targetGapOffset.y },\n target,\n ];\n return [pathPoints, centerX, centerY, defaultOffsetX, defaultOffsetY];\n}\nfunction getBend(a, b, c, size) {\n const bendSize = Math.min(distance(a, b) / 2, distance(b, c) / 2, size);\n const { x, y } = b;\n // no bend\n if ((a.x === x && x === c.x) || (a.y === y && y === c.y)) {\n return `L${x} ${y}`;\n }\n // first segment is horizontal\n if (a.y === y) {\n const xDir = a.x < c.x ? -1 : 1;\n const yDir = a.y < c.y ? 1 : -1;\n return `L ${x + bendSize * xDir},${y}Q ${x},${y} ${x},${y + bendSize * yDir}`;\n }\n const xDir = a.x < c.x ? 1 : -1;\n const yDir = a.y < c.y ? -1 : 1;\n return `L ${x},${y + bendSize * yDir}Q ${x},${y} ${x + bendSize * xDir},${y}`;\n}\nfunction getSmoothStepPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, borderRadius = 5, centerX, centerY, offset = 20, }) {\n const [points, labelX, labelY, offsetX, offsetY] = getPoints({\n source: { x: sourceX, y: sourceY },\n sourcePosition,\n target: { x: targetX, y: targetY },\n targetPosition,\n center: { x: centerX, y: centerY },\n offset,\n });\n const path = points.reduce((res, p, i) => {\n let segment = '';\n if (i > 0 && i < points.length - 1) {\n segment = getBend(points[i - 1], p, points[i + 1], borderRadius);\n }\n else {\n segment = `${i === 0 ? 'M' : 'L'}${p.x} ${p.y}`;\n }\n res += segment;\n return res;\n }, '');\n return [path, labelX, labelY, offsetX, offsetY];\n}\nconst SmoothStepEdge = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, sourcePosition = Position.Bottom, targetPosition = Position.Top, markerEnd, markerStart, pathOptions, interactionWidth, }) => {\n const [path, labelX, labelY] = getSmoothStepPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n borderRadius: pathOptions?.borderRadius,\n offset: pathOptions?.offset,\n });\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart, interactionWidth: interactionWidth }));\n});\nSmoothStepEdge.displayName = 'SmoothStepEdge';\n\nconst StepEdge = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)((props) => (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(SmoothStepEdge, { ...props, pathOptions: (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => ({ borderRadius: 0, offset: props.pathOptions?.offset }), [props.pathOptions?.offset]) })));\nStepEdge.displayName = 'StepEdge';\n\nfunction getStraightPath({ sourceX, sourceY, targetX, targetY, }) {\n const [labelX, labelY, offsetX, offsetY] = getEdgeCenter({\n sourceX,\n sourceY,\n targetX,\n targetY,\n });\n return [`M ${sourceX},${sourceY}L ${targetX},${targetY}`, labelX, labelY, offsetX, offsetY];\n}\nconst StraightEdge = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(({ sourceX, sourceY, targetX, targetY, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, interactionWidth, }) => {\n const [path, labelX, labelY] = getStraightPath({ sourceX, sourceY, targetX, targetY });\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart, interactionWidth: interactionWidth }));\n});\nStraightEdge.displayName = 'StraightEdge';\n\nfunction calculateControlOffset(distance, curvature) {\n if (distance >= 0) {\n return 0.5 * distance;\n }\n return curvature * 25 * Math.sqrt(-distance);\n}\nfunction getControlWithCurvature({ pos, x1, y1, x2, y2, c }) {\n switch (pos) {\n case Position.Left:\n return [x1 - calculateControlOffset(x1 - x2, c), y1];\n case Position.Right:\n return [x1 + calculateControlOffset(x2 - x1, c), y1];\n case Position.Top:\n return [x1, y1 - calculateControlOffset(y1 - y2, c)];\n case Position.Bottom:\n return [x1, y1 + calculateControlOffset(y2 - y1, c)];\n }\n}\nfunction getBezierPath({ sourceX, sourceY, sourcePosition = Position.Bottom, targetX, targetY, targetPosition = Position.Top, curvature = 0.25, }) {\n const [sourceControlX, sourceControlY] = getControlWithCurvature({\n pos: sourcePosition,\n x1: sourceX,\n y1: sourceY,\n x2: targetX,\n y2: targetY,\n c: curvature,\n });\n const [targetControlX, targetControlY] = getControlWithCurvature({\n pos: targetPosition,\n x1: targetX,\n y1: targetY,\n x2: sourceX,\n y2: sourceY,\n c: curvature,\n });\n const [labelX, labelY, offsetX, offsetY] = getBezierEdgeCenter({\n sourceX,\n sourceY,\n targetX,\n targetY,\n sourceControlX,\n sourceControlY,\n targetControlX,\n targetControlY,\n });\n return [\n `M${sourceX},${sourceY} C${sourceControlX},${sourceControlY} ${targetControlX},${targetControlY} ${targetX},${targetY}`,\n labelX,\n labelY,\n offsetX,\n offsetY,\n ];\n}\nconst BezierEdge = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(({ sourceX, sourceY, targetX, targetY, sourcePosition = Position.Bottom, targetPosition = Position.Top, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, markerEnd, markerStart, pathOptions, interactionWidth, }) => {\n const [path, labelX, labelY] = getBezierPath({\n sourceX,\n sourceY,\n sourcePosition,\n targetX,\n targetY,\n targetPosition,\n curvature: pathOptions?.curvature,\n });\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(BaseEdge, { path: path, labelX: labelX, labelY: labelY, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, style: style, markerEnd: markerEnd, markerStart: markerStart, interactionWidth: interactionWidth }));\n});\nBezierEdge.displayName = 'BezierEdge';\n\nconst NodeIdContext = (0,react__WEBPACK_IMPORTED_MODULE_0__.createContext)(null);\nconst Provider = NodeIdContext.Provider;\nNodeIdContext.Consumer;\nconst useNodeId = () => {\n const nodeId = (0,react__WEBPACK_IMPORTED_MODULE_0__.useContext)(NodeIdContext);\n return nodeId;\n};\n\nconst isEdge = (element) => 'id' in element && 'source' in element && 'target' in element;\nconst isNode = (element) => 'id' in element && !('source' in element) && !('target' in element);\nconst getOutgoers = (node, nodes, edges) => {\n if (!isNode(node)) {\n return [];\n }\n const outgoerIds = edges.filter((e) => e.source === node.id).map((e) => e.target);\n return nodes.filter((n) => outgoerIds.includes(n.id));\n};\nconst getIncomers = (node, nodes, edges) => {\n if (!isNode(node)) {\n return [];\n }\n const incomersIds = edges.filter((e) => e.target === node.id).map((e) => e.source);\n return nodes.filter((n) => incomersIds.includes(n.id));\n};\nconst getEdgeId = ({ source, sourceHandle, target, targetHandle }) => `reactflow__edge-${source}${sourceHandle || ''}-${target}${targetHandle || ''}`;\nconst getMarkerId = (marker, rfId) => {\n if (typeof marker === 'undefined') {\n return '';\n }\n if (typeof marker === 'string') {\n return marker;\n }\n const idPrefix = rfId ? `${rfId}__` : '';\n return `${idPrefix}${Object.keys(marker)\n .sort()\n .map((key) => `${key}=${marker[key]}`)\n .join('&')}`;\n};\nconst connectionExists = (edge, edges) => {\n return edges.some((el) => el.source === edge.source &&\n el.target === edge.target &&\n (el.sourceHandle === edge.sourceHandle || (!el.sourceHandle && !edge.sourceHandle)) &&\n (el.targetHandle === edge.targetHandle || (!el.targetHandle && !edge.targetHandle)));\n};\nconst addEdge = (edgeParams, edges) => {\n if (!edgeParams.source || !edgeParams.target) {\n devWarn('006', errorMessages['error006']());\n return edges;\n }\n let edge;\n if (isEdge(edgeParams)) {\n edge = { ...edgeParams };\n }\n else {\n edge = {\n ...edgeParams,\n id: getEdgeId(edgeParams),\n };\n }\n if (connectionExists(edge, edges)) {\n return edges;\n }\n return edges.concat(edge);\n};\nconst updateEdge = (oldEdge, newConnection, edges, options = { shouldReplaceId: true }) => {\n const { id: oldEdgeId, ...rest } = oldEdge;\n if (!newConnection.source || !newConnection.target) {\n devWarn('006', errorMessages['error006']());\n return edges;\n }\n const foundEdge = edges.find((e) => e.id === oldEdgeId);\n if (!foundEdge) {\n devWarn('007', errorMessages['error007'](oldEdgeId));\n return edges;\n }\n // Remove old edge and create the new edge with parameters of old edge.\n const edge = {\n ...rest,\n id: options.shouldReplaceId ? getEdgeId(newConnection) : oldEdgeId,\n source: newConnection.source,\n target: newConnection.target,\n sourceHandle: newConnection.sourceHandle,\n targetHandle: newConnection.targetHandle,\n };\n return edges.filter((e) => e.id !== oldEdgeId).concat(edge);\n};\nconst pointToRendererPoint = ({ x, y }, [tx, ty, tScale], snapToGrid, [snapX, snapY]) => {\n const position = {\n x: (x - tx) / tScale,\n y: (y - ty) / tScale,\n };\n if (snapToGrid) {\n return {\n x: snapX * Math.round(position.x / snapX),\n y: snapY * Math.round(position.y / snapY),\n };\n }\n return position;\n};\nconst rendererPointToPoint = ({ x, y }, [tx, ty, tScale]) => {\n return {\n x: x * tScale + tx,\n y: y * tScale + ty,\n };\n};\nconst getNodePositionWithOrigin = (node, nodeOrigin = [0, 0]) => {\n if (!node) {\n return {\n x: 0,\n y: 0,\n positionAbsolute: {\n x: 0,\n y: 0,\n },\n };\n }\n const offsetX = (node.width ?? 0) * nodeOrigin[0];\n const offsetY = (node.height ?? 0) * nodeOrigin[1];\n const position = {\n x: node.position.x - offsetX,\n y: node.position.y - offsetY,\n };\n return {\n ...position,\n positionAbsolute: node.positionAbsolute\n ? {\n x: node.positionAbsolute.x - offsetX,\n y: node.positionAbsolute.y - offsetY,\n }\n : position,\n };\n};\nconst getNodesBounds = (nodes, nodeOrigin = [0, 0]) => {\n if (nodes.length === 0) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n const box = nodes.reduce((currBox, node) => {\n const { x, y } = getNodePositionWithOrigin(node, nodeOrigin).positionAbsolute;\n return getBoundsOfBoxes(currBox, rectToBox({\n x,\n y,\n width: node.width || 0,\n height: node.height || 0,\n }));\n }, { x: Infinity, y: Infinity, x2: -Infinity, y2: -Infinity });\n return boxToRect(box);\n};\n// @deprecated Use `getNodesBounds`.\nconst getRectOfNodes = (nodes, nodeOrigin = [0, 0]) => {\n console.warn('[DEPRECATED] `getRectOfNodes` is deprecated. Instead use `getNodesBounds` https://reactflow.dev/api-reference/utils/get-nodes-bounds.');\n return getNodesBounds(nodes, nodeOrigin);\n};\nconst getNodesInside = (nodeInternals, rect, [tx, ty, tScale] = [0, 0, 1], partially = false, \n// set excludeNonSelectableNodes if you want to pay attention to the nodes \"selectable\" attribute\nexcludeNonSelectableNodes = false, nodeOrigin = [0, 0]) => {\n const paneRect = {\n x: (rect.x - tx) / tScale,\n y: (rect.y - ty) / tScale,\n width: rect.width / tScale,\n height: rect.height / tScale,\n };\n const visibleNodes = [];\n nodeInternals.forEach((node) => {\n const { width, height, selectable = true, hidden = false } = node;\n if ((excludeNonSelectableNodes && !selectable) || hidden) {\n return false;\n }\n const { positionAbsolute } = getNodePositionWithOrigin(node, nodeOrigin);\n const nodeRect = {\n x: positionAbsolute.x,\n y: positionAbsolute.y,\n width: width || 0,\n height: height || 0,\n };\n const overlappingArea = getOverlappingArea(paneRect, nodeRect);\n const notInitialized = typeof width === 'undefined' || typeof height === 'undefined' || width === null || height === null;\n const partiallyVisible = partially && overlappingArea > 0;\n const area = (width || 0) * (height || 0);\n const isVisible = notInitialized || partiallyVisible || overlappingArea >= area;\n if (isVisible || node.dragging) {\n visibleNodes.push(node);\n }\n });\n return visibleNodes;\n};\nconst getConnectedEdges = (nodes, edges) => {\n const nodeIds = nodes.map((node) => node.id);\n return edges.filter((edge) => nodeIds.includes(edge.source) || nodeIds.includes(edge.target));\n};\n// @deprecated Use `getViewportForBounds`.\nconst getTransformForBounds = (bounds, width, height, minZoom, maxZoom, padding = 0.1) => {\n const { x, y, zoom } = getViewportForBounds(bounds, width, height, minZoom, maxZoom, padding);\n console.warn('[DEPRECATED] `getTransformForBounds` is deprecated. Instead use `getViewportForBounds`. Beware that the return value is type Viewport (`{ x: number, y: number, zoom: number }`) instead of Transform (`[number, number, number]`). https://reactflow.dev/api-reference/utils/get-viewport-for-bounds');\n return [x, y, zoom];\n};\nconst getViewportForBounds = (bounds, width, height, minZoom, maxZoom, padding = 0.1) => {\n const xZoom = width / (bounds.width * (1 + padding));\n const yZoom = height / (bounds.height * (1 + padding));\n const zoom = Math.min(xZoom, yZoom);\n const clampedZoom = clamp(zoom, minZoom, maxZoom);\n const boundsCenterX = bounds.x + bounds.width / 2;\n const boundsCenterY = bounds.y + bounds.height / 2;\n const x = width / 2 - boundsCenterX * clampedZoom;\n const y = height / 2 - boundsCenterY * clampedZoom;\n return { x, y, zoom: clampedZoom };\n};\nconst getD3Transition = (selection, duration = 0) => {\n return selection.transition().duration(duration);\n};\n\n// this functions collects all handles and adds an absolute position\n// so that we can later find the closest handle to the mouse position\nfunction getHandles(node, handleBounds, type, currentHandle) {\n return (handleBounds[type] || []).reduce((res, h) => {\n if (`${node.id}-${h.id}-${type}` !== currentHandle) {\n res.push({\n id: h.id || null,\n type,\n nodeId: node.id,\n x: (node.positionAbsolute?.x ?? 0) + h.x + h.width / 2,\n y: (node.positionAbsolute?.y ?? 0) + h.y + h.height / 2,\n });\n }\n return res;\n }, []);\n}\nfunction getClosestHandle(event, doc, pos, connectionRadius, handles, validator) {\n // we always want to prioritize the handle below the mouse cursor over the closest distance handle,\n // because it could be that the center of another handle is closer to the mouse pointer than the handle below the cursor\n const { x, y } = getEventPosition(event);\n const domNodes = doc.elementsFromPoint(x, y);\n const handleBelow = domNodes.find((el) => el.classList.contains('react-flow__handle'));\n if (handleBelow) {\n const handleNodeId = handleBelow.getAttribute('data-nodeid');\n if (handleNodeId) {\n const handleType = getHandleType(undefined, handleBelow);\n const handleId = handleBelow.getAttribute('data-handleid');\n const validHandleResult = validator({ nodeId: handleNodeId, id: handleId, type: handleType });\n if (validHandleResult) {\n const handle = handles.find((h) => h.nodeId === handleNodeId && h.type === handleType && h.id === handleId);\n return {\n handle: {\n id: handleId,\n type: handleType,\n nodeId: handleNodeId,\n x: handle?.x || pos.x,\n y: handle?.y || pos.y,\n },\n validHandleResult,\n };\n }\n }\n }\n // if we couldn't find a handle below the mouse cursor we look for the closest distance based on the connectionRadius\n let closestHandles = [];\n let minDistance = Infinity;\n handles.forEach((handle) => {\n const distance = Math.sqrt((handle.x - pos.x) ** 2 + (handle.y - pos.y) ** 2);\n if (distance <= connectionRadius) {\n const validHandleResult = validator(handle);\n if (distance <= minDistance) {\n if (distance < minDistance) {\n closestHandles = [{ handle, validHandleResult }];\n }\n else if (distance === minDistance) {\n // when multiple handles are on the same distance we collect all of them\n closestHandles.push({\n handle,\n validHandleResult,\n });\n }\n minDistance = distance;\n }\n }\n });\n if (!closestHandles.length) {\n return { handle: null, validHandleResult: defaultResult() };\n }\n if (closestHandles.length === 1) {\n return closestHandles[0];\n }\n const hasValidHandle = closestHandles.some(({ validHandleResult }) => validHandleResult.isValid);\n const hasTargetHandle = closestHandles.some(({ handle }) => handle.type === 'target');\n // if multiple handles are layouted on top of each other we prefer the one with type = target and the one that is valid\n return (closestHandles.find(({ handle, validHandleResult }) => hasTargetHandle ? handle.type === 'target' : (hasValidHandle ? validHandleResult.isValid : true)) || closestHandles[0]);\n}\nconst nullConnection = { source: null, target: null, sourceHandle: null, targetHandle: null };\nconst defaultResult = () => ({\n handleDomNode: null,\n isValid: false,\n connection: nullConnection,\n endHandle: null,\n});\n// checks if and returns connection in fom of an object { source: 123, target: 312 }\nfunction isValidHandle(handle, connectionMode, fromNodeId, fromHandleId, fromType, isValidConnection, doc) {\n const isTarget = fromType === 'target';\n const handleToCheck = doc.querySelector(`.react-flow__handle[data-id=\"${handle?.nodeId}-${handle?.id}-${handle?.type}\"]`);\n const result = {\n ...defaultResult(),\n handleDomNode: handleToCheck,\n };\n if (handleToCheck) {\n const handleType = getHandleType(undefined, handleToCheck);\n const handleNodeId = handleToCheck.getAttribute('data-nodeid');\n const handleId = handleToCheck.getAttribute('data-handleid');\n const connectable = handleToCheck.classList.contains('connectable');\n const connectableEnd = handleToCheck.classList.contains('connectableend');\n const connection = {\n source: isTarget ? handleNodeId : fromNodeId,\n sourceHandle: isTarget ? handleId : fromHandleId,\n target: isTarget ? fromNodeId : handleNodeId,\n targetHandle: isTarget ? fromHandleId : handleId,\n };\n result.connection = connection;\n const isConnectable = connectable && connectableEnd;\n // in strict mode we don't allow target to target or source to source connections\n const isValid = isConnectable &&\n (connectionMode === ConnectionMode.Strict\n ? (isTarget && handleType === 'source') || (!isTarget && handleType === 'target')\n : handleNodeId !== fromNodeId || handleId !== fromHandleId);\n if (isValid) {\n result.endHandle = {\n nodeId: handleNodeId,\n handleId,\n type: handleType,\n };\n result.isValid = isValidConnection(connection);\n }\n }\n return result;\n}\nfunction getHandleLookup({ nodes, nodeId, handleId, handleType }) {\n return nodes.reduce((res, node) => {\n if (node[internalsSymbol]) {\n const { handleBounds } = node[internalsSymbol];\n let sourceHandles = [];\n let targetHandles = [];\n if (handleBounds) {\n sourceHandles = getHandles(node, handleBounds, 'source', `${nodeId}-${handleId}-${handleType}`);\n targetHandles = getHandles(node, handleBounds, 'target', `${nodeId}-${handleId}-${handleType}`);\n }\n res.push(...sourceHandles, ...targetHandles);\n }\n return res;\n }, []);\n}\nfunction getHandleType(edgeUpdaterType, handleDomNode) {\n if (edgeUpdaterType) {\n return edgeUpdaterType;\n }\n else if (handleDomNode?.classList.contains('target')) {\n return 'target';\n }\n else if (handleDomNode?.classList.contains('source')) {\n return 'source';\n }\n return null;\n}\nfunction resetRecentHandle(handleDomNode) {\n handleDomNode?.classList.remove('valid', 'connecting', 'react-flow__handle-valid', 'react-flow__handle-connecting');\n}\nfunction getConnectionStatus(isInsideConnectionRadius, isHandleValid) {\n let connectionStatus = null;\n if (isHandleValid) {\n connectionStatus = 'valid';\n }\n else if (isInsideConnectionRadius && !isHandleValid) {\n connectionStatus = 'invalid';\n }\n return connectionStatus;\n}\n\nfunction handlePointerDown({ event, handleId, nodeId, onConnect, isTarget, getState, setState, isValidConnection, edgeUpdaterType, onEdgeUpdateEnd, }) {\n // when react-flow is used inside a shadow root we can't use document\n const doc = getHostForElement(event.target);\n const { connectionMode, domNode, autoPanOnConnect, connectionRadius, onConnectStart, panBy, getNodes, cancelConnection, } = getState();\n let autoPanId = 0;\n let closestHandle;\n const { x, y } = getEventPosition(event);\n const clickedHandle = doc?.elementFromPoint(x, y);\n const handleType = getHandleType(edgeUpdaterType, clickedHandle);\n const containerBounds = domNode?.getBoundingClientRect();\n if (!containerBounds || !handleType) {\n return;\n }\n let prevActiveHandle;\n let connectionPosition = getEventPosition(event, containerBounds);\n let autoPanStarted = false;\n let connection = null;\n let isValid = false;\n let handleDomNode = null;\n const handleLookup = getHandleLookup({\n nodes: getNodes(),\n nodeId,\n handleId,\n handleType,\n });\n // when the user is moving the mouse close to the edge of the canvas while connecting we move the canvas\n const autoPan = () => {\n if (!autoPanOnConnect) {\n return;\n }\n const [xMovement, yMovement] = calcAutoPan(connectionPosition, containerBounds);\n panBy({ x: xMovement, y: yMovement });\n autoPanId = requestAnimationFrame(autoPan);\n };\n setState({\n connectionPosition,\n connectionStatus: null,\n // connectionNodeId etc will be removed in the next major in favor of connectionStartHandle\n connectionNodeId: nodeId,\n connectionHandleId: handleId,\n connectionHandleType: handleType,\n connectionStartHandle: {\n nodeId,\n handleId,\n type: handleType,\n },\n connectionEndHandle: null,\n });\n onConnectStart?.(event, { nodeId, handleId, handleType });\n function onPointerMove(event) {\n const { transform } = getState();\n connectionPosition = getEventPosition(event, containerBounds);\n const { handle, validHandleResult } = getClosestHandle(event, doc, pointToRendererPoint(connectionPosition, transform, false, [1, 1]), connectionRadius, handleLookup, (handle) => isValidHandle(handle, connectionMode, nodeId, handleId, isTarget ? 'target' : 'source', isValidConnection, doc));\n closestHandle = handle;\n if (!autoPanStarted) {\n autoPan();\n autoPanStarted = true;\n }\n handleDomNode = validHandleResult.handleDomNode;\n connection = validHandleResult.connection;\n isValid = validHandleResult.isValid;\n setState({\n connectionPosition: closestHandle && isValid\n ? rendererPointToPoint({\n x: closestHandle.x,\n y: closestHandle.y,\n }, transform)\n : connectionPosition,\n connectionStatus: getConnectionStatus(!!closestHandle, isValid),\n connectionEndHandle: validHandleResult.endHandle,\n });\n if (!closestHandle && !isValid && !handleDomNode) {\n return resetRecentHandle(prevActiveHandle);\n }\n if (connection.source !== connection.target && handleDomNode) {\n resetRecentHandle(prevActiveHandle);\n prevActiveHandle = handleDomNode;\n // @todo: remove the old class names \"react-flow__handle-\" in the next major version\n handleDomNode.classList.add('connecting', 'react-flow__handle-connecting');\n handleDomNode.classList.toggle('valid', isValid);\n handleDomNode.classList.toggle('react-flow__handle-valid', isValid);\n }\n }\n function onPointerUp(event) {\n if ((closestHandle || handleDomNode) && connection && isValid) {\n onConnect?.(connection);\n }\n // it's important to get a fresh reference from the store here\n // in order to get the latest state of onConnectEnd\n getState().onConnectEnd?.(event);\n if (edgeUpdaterType) {\n onEdgeUpdateEnd?.(event);\n }\n resetRecentHandle(prevActiveHandle);\n cancelConnection();\n cancelAnimationFrame(autoPanId);\n autoPanStarted = false;\n isValid = false;\n connection = null;\n handleDomNode = null;\n doc.removeEventListener('mousemove', onPointerMove);\n doc.removeEventListener('mouseup', onPointerUp);\n doc.removeEventListener('touchmove', onPointerMove);\n doc.removeEventListener('touchend', onPointerUp);\n }\n doc.addEventListener('mousemove', onPointerMove);\n doc.addEventListener('mouseup', onPointerUp);\n doc.addEventListener('touchmove', onPointerMove);\n doc.addEventListener('touchend', onPointerUp);\n}\n\nconst alwaysValid = () => true;\nconst selector$f = (s) => ({\n connectionStartHandle: s.connectionStartHandle,\n connectOnClick: s.connectOnClick,\n noPanClassName: s.noPanClassName,\n});\nconst connectingSelector = (nodeId, handleId, type) => (state) => {\n const { connectionStartHandle: startHandle, connectionEndHandle: endHandle, connectionClickStartHandle: clickHandle, } = state;\n return {\n connecting: (startHandle?.nodeId === nodeId && startHandle?.handleId === handleId && startHandle?.type === type) ||\n (endHandle?.nodeId === nodeId && endHandle?.handleId === handleId && endHandle?.type === type),\n clickConnecting: clickHandle?.nodeId === nodeId && clickHandle?.handleId === handleId && clickHandle?.type === type,\n };\n};\nconst Handle = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ type = 'source', position = Position.Top, isValidConnection, isConnectable = true, isConnectableStart = true, isConnectableEnd = true, id, onConnect, children, className, onMouseDown, onTouchStart, ...rest }, ref) => {\n const handleId = id || null;\n const isTarget = type === 'target';\n const store = useStoreApi();\n const nodeId = useNodeId();\n const { connectOnClick, noPanClassName } = useStore(selector$f, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const { connecting, clickConnecting } = useStore(connectingSelector(nodeId, handleId, type), zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n if (!nodeId) {\n store.getState().onError?.('010', errorMessages['error010']());\n }\n const onConnectExtended = (params) => {\n const { defaultEdgeOptions, onConnect: onConnectAction, hasDefaultEdges } = store.getState();\n const edgeParams = {\n ...defaultEdgeOptions,\n ...params,\n };\n if (hasDefaultEdges) {\n const { edges, setEdges } = store.getState();\n setEdges(addEdge(edgeParams, edges));\n }\n onConnectAction?.(edgeParams);\n onConnect?.(edgeParams);\n };\n const onPointerDown = (event) => {\n if (!nodeId) {\n return;\n }\n const isMouseTriggered = isMouseEvent(event);\n if (isConnectableStart && ((isMouseTriggered && event.button === 0) || !isMouseTriggered)) {\n handlePointerDown({\n event,\n handleId,\n nodeId,\n onConnect: onConnectExtended,\n isTarget,\n getState: store.getState,\n setState: store.setState,\n isValidConnection: isValidConnection || store.getState().isValidConnection || alwaysValid,\n });\n }\n if (isMouseTriggered) {\n onMouseDown?.(event);\n }\n else {\n onTouchStart?.(event);\n }\n };\n const onClick = (event) => {\n const { onClickConnectStart, onClickConnectEnd, connectionClickStartHandle, connectionMode, isValidConnection: isValidConnectionStore, } = store.getState();\n if (!nodeId || (!connectionClickStartHandle && !isConnectableStart)) {\n return;\n }\n if (!connectionClickStartHandle) {\n onClickConnectStart?.(event, { nodeId, handleId, handleType: type });\n store.setState({ connectionClickStartHandle: { nodeId, type, handleId } });\n return;\n }\n const doc = getHostForElement(event.target);\n const isValidConnectionHandler = isValidConnection || isValidConnectionStore || alwaysValid;\n const { connection, isValid } = isValidHandle({\n nodeId,\n id: handleId,\n type,\n }, connectionMode, connectionClickStartHandle.nodeId, connectionClickStartHandle.handleId || null, connectionClickStartHandle.type, isValidConnectionHandler, doc);\n if (isValid) {\n onConnectExtended(connection);\n }\n onClickConnectEnd?.(event);\n store.setState({ connectionClickStartHandle: null });\n };\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { \"data-handleid\": handleId, \"data-nodeid\": nodeId, \"data-handlepos\": position, \"data-id\": `${nodeId}-${handleId}-${type}`, className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])([\n 'react-flow__handle',\n `react-flow__handle-${position}`,\n 'nodrag',\n noPanClassName,\n className,\n {\n source: !isTarget,\n target: isTarget,\n connectable: isConnectable,\n connectablestart: isConnectableStart,\n connectableend: isConnectableEnd,\n connecting: clickConnecting,\n // this class is used to style the handle when the user is connecting\n connectionindicator: isConnectable && ((isConnectableStart && !connecting) || (isConnectableEnd && connecting)),\n },\n ]), onMouseDown: onPointerDown, onTouchStart: onPointerDown, onClick: connectOnClick ? onClick : undefined, ref: ref, ...rest }, children));\n});\nHandle.displayName = 'Handle';\nvar Handle$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(Handle);\n\nconst DefaultNode = ({ data, isConnectable, targetPosition = Position.Top, sourcePosition = Position.Bottom, }) => {\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Handle$1, { type: \"target\", position: targetPosition, isConnectable: isConnectable }),\n data?.label,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Handle$1, { type: \"source\", position: sourcePosition, isConnectable: isConnectable })));\n};\nDefaultNode.displayName = 'DefaultNode';\nvar DefaultNode$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(DefaultNode);\n\nconst InputNode = ({ data, isConnectable, sourcePosition = Position.Bottom }) => (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Fragment, null,\n data?.label,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Handle$1, { type: \"source\", position: sourcePosition, isConnectable: isConnectable })));\nInputNode.displayName = 'InputNode';\nvar InputNode$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(InputNode);\n\nconst OutputNode = ({ data, isConnectable, targetPosition = Position.Top }) => (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Handle$1, { type: \"target\", position: targetPosition, isConnectable: isConnectable }),\n data?.label));\nOutputNode.displayName = 'OutputNode';\nvar OutputNode$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(OutputNode);\n\nconst GroupNode = () => null;\nGroupNode.displayName = 'GroupNode';\n\nconst selector$e = (s) => ({\n selectedNodes: s.getNodes().filter((n) => n.selected),\n selectedEdges: s.edges.filter((e) => e.selected),\n});\nconst selectId = (obj) => obj.id;\nfunction areEqual(a, b) {\n return ((0,zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow)(a.selectedNodes.map(selectId), b.selectedNodes.map(selectId)) &&\n (0,zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow)(a.selectedEdges.map(selectId), b.selectedEdges.map(selectId)));\n}\n// This is just a helper component for calling the onSelectionChange listener.\n// @TODO: Now that we have the onNodesChange and on EdgesChange listeners, do we still need this component?\nconst SelectionListener = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(({ onSelectionChange }) => {\n const store = useStoreApi();\n const { selectedNodes, selectedEdges } = useStore(selector$e, areEqual);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n const params = { nodes: selectedNodes, edges: selectedEdges };\n onSelectionChange?.(params);\n store.getState().onSelectionChange.forEach((fn) => fn(params));\n }, [selectedNodes, selectedEdges, onSelectionChange]);\n return null;\n});\nSelectionListener.displayName = 'SelectionListener';\nconst changeSelector = (s) => !!s.onSelectionChange;\nfunction Wrapper$1({ onSelectionChange }) {\n const storeHasSelectionChange = useStore(changeSelector);\n if (onSelectionChange || storeHasSelectionChange) {\n return react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(SelectionListener, { onSelectionChange: onSelectionChange });\n }\n return null;\n}\n\nconst selector$d = (s) => ({\n setNodes: s.setNodes,\n setEdges: s.setEdges,\n setDefaultNodesAndEdges: s.setDefaultNodesAndEdges,\n setMinZoom: s.setMinZoom,\n setMaxZoom: s.setMaxZoom,\n setTranslateExtent: s.setTranslateExtent,\n setNodeExtent: s.setNodeExtent,\n reset: s.reset,\n});\nfunction useStoreUpdater(value, setStoreState) {\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (typeof value !== 'undefined') {\n setStoreState(value);\n }\n }, [value]);\n}\n// updates with values in store that don't have a dedicated setter function\nfunction useDirectStoreUpdater(key, value, setState) {\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (typeof value !== 'undefined') {\n setState({ [key]: value });\n }\n }, [value]);\n}\nconst StoreUpdater = ({ nodes, edges, defaultNodes, defaultEdges, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, nodesDraggable, nodesConnectable, nodesFocusable, edgesFocusable, edgesUpdatable, elevateNodesOnSelect, minZoom, maxZoom, nodeExtent, onNodesChange, onEdgesChange, elementsSelectable, connectionMode, snapGrid, snapToGrid, translateExtent, connectOnClick, defaultEdgeOptions, fitView, fitViewOptions, onNodesDelete, onEdgesDelete, onNodeDrag, onNodeDragStart, onNodeDragStop, onSelectionDrag, onSelectionDragStart, onSelectionDragStop, noPanClassName, nodeOrigin, rfId, autoPanOnConnect, autoPanOnNodeDrag, onError, connectionRadius, isValidConnection, nodeDragThreshold, }) => {\n const { setNodes, setEdges, setDefaultNodesAndEdges, setMinZoom, setMaxZoom, setTranslateExtent, setNodeExtent, reset, } = useStore(selector$d, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const store = useStoreApi();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n const edgesWithDefaults = defaultEdges?.map((e) => ({ ...e, ...defaultEdgeOptions }));\n setDefaultNodesAndEdges(defaultNodes, edgesWithDefaults);\n return () => {\n reset();\n };\n }, []);\n useDirectStoreUpdater('defaultEdgeOptions', defaultEdgeOptions, store.setState);\n useDirectStoreUpdater('connectionMode', connectionMode, store.setState);\n useDirectStoreUpdater('onConnect', onConnect, store.setState);\n useDirectStoreUpdater('onConnectStart', onConnectStart, store.setState);\n useDirectStoreUpdater('onConnectEnd', onConnectEnd, store.setState);\n useDirectStoreUpdater('onClickConnectStart', onClickConnectStart, store.setState);\n useDirectStoreUpdater('onClickConnectEnd', onClickConnectEnd, store.setState);\n useDirectStoreUpdater('nodesDraggable', nodesDraggable, store.setState);\n useDirectStoreUpdater('nodesConnectable', nodesConnectable, store.setState);\n useDirectStoreUpdater('nodesFocusable', nodesFocusable, store.setState);\n useDirectStoreUpdater('edgesFocusable', edgesFocusable, store.setState);\n useDirectStoreUpdater('edgesUpdatable', edgesUpdatable, store.setState);\n useDirectStoreUpdater('elementsSelectable', elementsSelectable, store.setState);\n useDirectStoreUpdater('elevateNodesOnSelect', elevateNodesOnSelect, store.setState);\n useDirectStoreUpdater('snapToGrid', snapToGrid, store.setState);\n useDirectStoreUpdater('snapGrid', snapGrid, store.setState);\n useDirectStoreUpdater('onNodesChange', onNodesChange, store.setState);\n useDirectStoreUpdater('onEdgesChange', onEdgesChange, store.setState);\n useDirectStoreUpdater('connectOnClick', connectOnClick, store.setState);\n useDirectStoreUpdater('fitViewOnInit', fitView, store.setState);\n useDirectStoreUpdater('fitViewOnInitOptions', fitViewOptions, store.setState);\n useDirectStoreUpdater('onNodesDelete', onNodesDelete, store.setState);\n useDirectStoreUpdater('onEdgesDelete', onEdgesDelete, store.setState);\n useDirectStoreUpdater('onNodeDrag', onNodeDrag, store.setState);\n useDirectStoreUpdater('onNodeDragStart', onNodeDragStart, store.setState);\n useDirectStoreUpdater('onNodeDragStop', onNodeDragStop, store.setState);\n useDirectStoreUpdater('onSelectionDrag', onSelectionDrag, store.setState);\n useDirectStoreUpdater('onSelectionDragStart', onSelectionDragStart, store.setState);\n useDirectStoreUpdater('onSelectionDragStop', onSelectionDragStop, store.setState);\n useDirectStoreUpdater('noPanClassName', noPanClassName, store.setState);\n useDirectStoreUpdater('nodeOrigin', nodeOrigin, store.setState);\n useDirectStoreUpdater('rfId', rfId, store.setState);\n useDirectStoreUpdater('autoPanOnConnect', autoPanOnConnect, store.setState);\n useDirectStoreUpdater('autoPanOnNodeDrag', autoPanOnNodeDrag, store.setState);\n useDirectStoreUpdater('onError', onError, store.setState);\n useDirectStoreUpdater('connectionRadius', connectionRadius, store.setState);\n useDirectStoreUpdater('isValidConnection', isValidConnection, store.setState);\n useDirectStoreUpdater('nodeDragThreshold', nodeDragThreshold, store.setState);\n useStoreUpdater(nodes, setNodes);\n useStoreUpdater(edges, setEdges);\n useStoreUpdater(minZoom, setMinZoom);\n useStoreUpdater(maxZoom, setMaxZoom);\n useStoreUpdater(translateExtent, setTranslateExtent);\n useStoreUpdater(nodeExtent, setNodeExtent);\n return null;\n};\n\nconst style = { display: 'none' };\nconst ariaLiveStyle = {\n position: 'absolute',\n width: 1,\n height: 1,\n margin: -1,\n border: 0,\n padding: 0,\n overflow: 'hidden',\n clip: 'rect(0px, 0px, 0px, 0px)',\n clipPath: 'inset(100%)',\n};\nconst ARIA_NODE_DESC_KEY = 'react-flow__node-desc';\nconst ARIA_EDGE_DESC_KEY = 'react-flow__edge-desc';\nconst ARIA_LIVE_MESSAGE = 'react-flow__aria-live';\nconst selector$c = (s) => s.ariaLiveMessage;\nfunction AriaLiveMessage({ rfId }) {\n const ariaLiveMessage = useStore(selector$c);\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { id: `${ARIA_LIVE_MESSAGE}-${rfId}`, \"aria-live\": \"assertive\", \"aria-atomic\": \"true\", style: ariaLiveStyle }, ariaLiveMessage));\n}\nfunction A11yDescriptions({ rfId, disableKeyboardA11y }) {\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Fragment, null,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { id: `${ARIA_NODE_DESC_KEY}-${rfId}`, style: style },\n \"Press enter or space to select a node.\",\n !disableKeyboardA11y && 'You can then use the arrow keys to move the node around.',\n \" Press delete to remove it and escape to cancel.\",\n ' '),\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { id: `${ARIA_EDGE_DESC_KEY}-${rfId}`, style: style }, \"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.\"),\n !disableKeyboardA11y && react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(AriaLiveMessage, { rfId: rfId })));\n}\n\n// the keycode can be a string 'a' or an array of strings ['a', 'a+d']\n// a string means a single key 'a' or a combination when '+' is used 'a+d'\n// an array means different possibilities. Explainer: ['a', 'd+s'] here the\n// user can use the single key 'a' or the combination 'd' + 's'\nvar useKeyPress = (keyCode = null, options = { actInsideInputWithModifier: true }) => {\n const [keyPressed, setKeyPressed] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);\n // we need to remember if a modifier key is pressed in order to track it\n const modifierPressed = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false);\n // we need to remember the pressed keys in order to support combinations\n const pressedKeys = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(new Set([]));\n // keyCodes = array with single keys [['a']] or key combinations [['a', 's']]\n // keysToWatch = array with all keys flattened ['a', 'd', 'ShiftLeft']\n // used to check if we store event.code or event.key. When the code is in the list of keysToWatch\n // we use the code otherwise the key. Explainer: When you press the left \"command\" key, the code is \"MetaLeft\"\n // and the key is \"Meta\". We want users to be able to pass keys and codes so we assume that the key is meant when\n // we can't find it in the list of keysToWatch.\n const [keyCodes, keysToWatch] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {\n if (keyCode !== null) {\n const keyCodeArr = Array.isArray(keyCode) ? keyCode : [keyCode];\n const keys = keyCodeArr.filter((kc) => typeof kc === 'string').map((kc) => kc.split('+'));\n const keysFlat = keys.reduce((res, item) => res.concat(...item), []);\n return [keys, keysFlat];\n }\n return [[], []];\n }, [keyCode]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n const doc = typeof document !== 'undefined' ? document : null;\n const target = options?.target || doc;\n if (keyCode !== null) {\n const downHandler = (event) => {\n modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey;\n const preventAction = (!modifierPressed.current || (modifierPressed.current && !options.actInsideInputWithModifier)) &&\n isInputDOMNode(event);\n if (preventAction) {\n return false;\n }\n const keyOrCode = useKeyOrCode(event.code, keysToWatch);\n pressedKeys.current.add(event[keyOrCode]);\n if (isMatchingKey(keyCodes, pressedKeys.current, false)) {\n event.preventDefault();\n setKeyPressed(true);\n }\n };\n const upHandler = (event) => {\n const preventAction = (!modifierPressed.current || (modifierPressed.current && !options.actInsideInputWithModifier)) &&\n isInputDOMNode(event);\n if (preventAction) {\n return false;\n }\n const keyOrCode = useKeyOrCode(event.code, keysToWatch);\n if (isMatchingKey(keyCodes, pressedKeys.current, true)) {\n setKeyPressed(false);\n pressedKeys.current.clear();\n }\n else {\n pressedKeys.current.delete(event[keyOrCode]);\n }\n // fix for Mac: when cmd key is pressed, keyup is not triggered for any other key, see: https://stackoverflow.com/questions/27380018/when-cmd-key-is-kept-pressed-keyup-is-not-triggered-for-any-other-key\n if (event.key === 'Meta') {\n pressedKeys.current.clear();\n }\n modifierPressed.current = false;\n };\n const resetHandler = () => {\n pressedKeys.current.clear();\n setKeyPressed(false);\n };\n target?.addEventListener('keydown', downHandler);\n target?.addEventListener('keyup', upHandler);\n window.addEventListener('blur', resetHandler);\n return () => {\n target?.removeEventListener('keydown', downHandler);\n target?.removeEventListener('keyup', upHandler);\n window.removeEventListener('blur', resetHandler);\n };\n }\n }, [keyCode, setKeyPressed]);\n return keyPressed;\n};\n// utils\nfunction isMatchingKey(keyCodes, pressedKeys, isUp) {\n return (keyCodes\n // we only want to compare same sizes of keyCode definitions\n // and pressed keys. When the user specified 'Meta' as a key somewhere\n // this would also be truthy without this filter when user presses 'Meta' + 'r'\n .filter((keys) => isUp || keys.length === pressedKeys.size)\n // since we want to support multiple possibilities only one of the\n // combinations need to be part of the pressed keys\n .some((keys) => keys.every((k) => pressedKeys.has(k))));\n}\nfunction useKeyOrCode(eventCode, keysToWatch) {\n return keysToWatch.includes(eventCode) ? 'code' : 'key';\n}\n\nfunction calculateXYZPosition(node, nodeInternals, result, nodeOrigin) {\n if (!node.parentNode) {\n return result;\n }\n const parentNode = nodeInternals.get(node.parentNode);\n const parentNodePosition = getNodePositionWithOrigin(parentNode, nodeOrigin);\n return calculateXYZPosition(parentNode, nodeInternals, {\n x: (result.x ?? 0) + parentNodePosition.x,\n y: (result.y ?? 0) + parentNodePosition.y,\n z: (parentNode[internalsSymbol]?.z ?? 0) > (result.z ?? 0) ? parentNode[internalsSymbol]?.z ?? 0 : result.z ?? 0,\n }, nodeOrigin);\n}\nfunction updateAbsoluteNodePositions(nodeInternals, nodeOrigin, parentNodes) {\n nodeInternals.forEach((node) => {\n if (node.parentNode && !nodeInternals.has(node.parentNode)) {\n throw new Error(`Parent node ${node.parentNode} not found`);\n }\n if (node.parentNode || parentNodes?.[node.id]) {\n const { x, y, z } = calculateXYZPosition(node, nodeInternals, {\n ...node.position,\n z: node[internalsSymbol]?.z ?? 0,\n }, nodeOrigin);\n node.positionAbsolute = {\n x,\n y,\n };\n node[internalsSymbol].z = z;\n if (parentNodes?.[node.id]) {\n node[internalsSymbol].isParent = true;\n }\n }\n });\n}\nfunction createNodeInternals(nodes, nodeInternals, nodeOrigin, elevateNodesOnSelect) {\n const nextNodeInternals = new Map();\n const parentNodes = {};\n const selectedNodeZ = elevateNodesOnSelect ? 1000 : 0;\n nodes.forEach((node) => {\n const z = (isNumeric(node.zIndex) ? node.zIndex : 0) + (node.selected ? selectedNodeZ : 0);\n const currInternals = nodeInternals.get(node.id);\n const internals = {\n ...node,\n positionAbsolute: {\n x: node.position.x,\n y: node.position.y,\n },\n };\n if (node.parentNode) {\n parentNodes[node.parentNode] = true;\n }\n const resetHandleBounds = currInternals?.type && currInternals?.type !== node.type;\n Object.defineProperty(internals, internalsSymbol, {\n enumerable: false,\n value: {\n handleBounds: resetHandleBounds ? undefined : currInternals?.[internalsSymbol]?.handleBounds,\n z,\n },\n });\n nextNodeInternals.set(node.id, internals);\n });\n updateAbsoluteNodePositions(nextNodeInternals, nodeOrigin, parentNodes);\n return nextNodeInternals;\n}\nfunction fitView(get, options = {}) {\n const { getNodes, width, height, minZoom, maxZoom, d3Zoom, d3Selection, fitViewOnInitDone, fitViewOnInit, nodeOrigin, } = get();\n const isInitialFitView = options.initial && !fitViewOnInitDone && fitViewOnInit;\n const d3initialized = d3Zoom && d3Selection;\n if (d3initialized && (isInitialFitView || !options.initial)) {\n const nodes = getNodes().filter((n) => {\n const isVisible = options.includeHiddenNodes ? n.width && n.height : !n.hidden;\n if (options.nodes?.length) {\n return isVisible && options.nodes.some((optionNode) => optionNode.id === n.id);\n }\n return isVisible;\n });\n const nodesInitialized = nodes.every((n) => n.width && n.height);\n if (nodes.length > 0 && nodesInitialized) {\n const bounds = getNodesBounds(nodes, nodeOrigin);\n const { x, y, zoom } = getViewportForBounds(bounds, width, height, options.minZoom ?? minZoom, options.maxZoom ?? maxZoom, options.padding ?? 0.1);\n const nextTransform = d3_zoom__WEBPACK_IMPORTED_MODULE_2__.zoomIdentity.translate(x, y).scale(zoom);\n if (typeof options.duration === 'number' && options.duration > 0) {\n d3Zoom.transform(getD3Transition(d3Selection, options.duration), nextTransform);\n }\n else {\n d3Zoom.transform(d3Selection, nextTransform);\n }\n return true;\n }\n }\n return false;\n}\nfunction handleControlledNodeSelectionChange(nodeChanges, nodeInternals) {\n nodeChanges.forEach((change) => {\n const node = nodeInternals.get(change.id);\n if (node) {\n nodeInternals.set(node.id, {\n ...node,\n [internalsSymbol]: node[internalsSymbol],\n selected: change.selected,\n });\n }\n });\n return new Map(nodeInternals);\n}\nfunction handleControlledEdgeSelectionChange(edgeChanges, edges) {\n return edges.map((e) => {\n const change = edgeChanges.find((change) => change.id === e.id);\n if (change) {\n e.selected = change.selected;\n }\n return e;\n });\n}\nfunction updateNodesAndEdgesSelections({ changedNodes, changedEdges, get, set }) {\n const { nodeInternals, edges, onNodesChange, onEdgesChange, hasDefaultNodes, hasDefaultEdges } = get();\n if (changedNodes?.length) {\n if (hasDefaultNodes) {\n set({ nodeInternals: handleControlledNodeSelectionChange(changedNodes, nodeInternals) });\n }\n onNodesChange?.(changedNodes);\n }\n if (changedEdges?.length) {\n if (hasDefaultEdges) {\n set({ edges: handleControlledEdgeSelectionChange(changedEdges, edges) });\n }\n onEdgesChange?.(changedEdges);\n }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-empty-function\nconst noop = () => { };\nconst initialViewportHelper = {\n zoomIn: noop,\n zoomOut: noop,\n zoomTo: noop,\n getZoom: () => 1,\n setViewport: noop,\n getViewport: () => ({ x: 0, y: 0, zoom: 1 }),\n fitView: () => false,\n setCenter: noop,\n fitBounds: noop,\n project: (position) => position,\n screenToFlowPosition: (position) => position,\n flowToScreenPosition: (position) => position,\n viewportInitialized: false,\n};\nconst selector$b = (s) => ({\n d3Zoom: s.d3Zoom,\n d3Selection: s.d3Selection,\n});\nconst useViewportHelper = () => {\n const store = useStoreApi();\n const { d3Zoom, d3Selection } = useStore(selector$b, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const viewportHelperFunctions = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {\n if (d3Selection && d3Zoom) {\n return {\n zoomIn: (options) => d3Zoom.scaleBy(getD3Transition(d3Selection, options?.duration), 1.2),\n zoomOut: (options) => d3Zoom.scaleBy(getD3Transition(d3Selection, options?.duration), 1 / 1.2),\n zoomTo: (zoomLevel, options) => d3Zoom.scaleTo(getD3Transition(d3Selection, options?.duration), zoomLevel),\n getZoom: () => store.getState().transform[2],\n setViewport: (transform, options) => {\n const [x, y, zoom] = store.getState().transform;\n const nextTransform = d3_zoom__WEBPACK_IMPORTED_MODULE_2__.zoomIdentity\n .translate(transform.x ?? x, transform.y ?? y)\n .scale(transform.zoom ?? zoom);\n d3Zoom.transform(getD3Transition(d3Selection, options?.duration), nextTransform);\n },\n getViewport: () => {\n const [x, y, zoom] = store.getState().transform;\n return { x, y, zoom };\n },\n fitView: (options) => fitView(store.getState, options),\n setCenter: (x, y, options) => {\n const { width, height, maxZoom } = store.getState();\n const nextZoom = typeof options?.zoom !== 'undefined' ? options.zoom : maxZoom;\n const centerX = width / 2 - x * nextZoom;\n const centerY = height / 2 - y * nextZoom;\n const transform = d3_zoom__WEBPACK_IMPORTED_MODULE_2__.zoomIdentity.translate(centerX, centerY).scale(nextZoom);\n d3Zoom.transform(getD3Transition(d3Selection, options?.duration), transform);\n },\n fitBounds: (bounds, options) => {\n const { width, height, minZoom, maxZoom } = store.getState();\n const { x, y, zoom } = getViewportForBounds(bounds, width, height, minZoom, maxZoom, options?.padding ?? 0.1);\n const transform = d3_zoom__WEBPACK_IMPORTED_MODULE_2__.zoomIdentity.translate(x, y).scale(zoom);\n d3Zoom.transform(getD3Transition(d3Selection, options?.duration), transform);\n },\n // @deprecated Use `screenToFlowPosition`.\n project: (position) => {\n const { transform, snapToGrid, snapGrid } = store.getState();\n console.warn('[DEPRECATED] `project` is deprecated. Instead use `screenToFlowPosition`. There is no need to subtract the react flow bounds anymore! https://reactflow.dev/api-reference/types/react-flow-instance#screen-to-flow-position');\n return pointToRendererPoint(position, transform, snapToGrid, snapGrid);\n },\n screenToFlowPosition: (position) => {\n const { transform, snapToGrid, snapGrid, domNode } = store.getState();\n if (!domNode) {\n return position;\n }\n const { x: domX, y: domY } = domNode.getBoundingClientRect();\n const relativePosition = {\n x: position.x - domX,\n y: position.y - domY,\n };\n return pointToRendererPoint(relativePosition, transform, snapToGrid, snapGrid);\n },\n flowToScreenPosition: (position) => {\n const { transform, domNode } = store.getState();\n if (!domNode) {\n return position;\n }\n const { x: domX, y: domY } = domNode.getBoundingClientRect();\n const rendererPosition = rendererPointToPoint(position, transform);\n return {\n x: rendererPosition.x + domX,\n y: rendererPosition.y + domY,\n };\n },\n viewportInitialized: true,\n };\n }\n return initialViewportHelper;\n }, [d3Zoom, d3Selection]);\n return viewportHelperFunctions;\n};\n\n/* eslint-disable-next-line @typescript-eslint/no-explicit-any */\nfunction useReactFlow() {\n const viewportHelper = useViewportHelper();\n const store = useStoreApi();\n const getNodes = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {\n return store\n .getState()\n .getNodes()\n .map((n) => ({ ...n }));\n }, []);\n const getNode = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((id) => {\n return store.getState().nodeInternals.get(id);\n }, []);\n const getEdges = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {\n const { edges = [] } = store.getState();\n return edges.map((e) => ({ ...e }));\n }, []);\n const getEdge = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((id) => {\n const { edges = [] } = store.getState();\n return edges.find((e) => e.id === id);\n }, []);\n const setNodes = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((payload) => {\n const { getNodes, setNodes, hasDefaultNodes, onNodesChange } = store.getState();\n const nodes = getNodes();\n const nextNodes = typeof payload === 'function' ? payload(nodes) : payload;\n if (hasDefaultNodes) {\n setNodes(nextNodes);\n }\n else if (onNodesChange) {\n const changes = nextNodes.length === 0\n ? nodes.map((node) => ({ type: 'remove', id: node.id }))\n : nextNodes.map((node) => ({ item: node, type: 'reset' }));\n onNodesChange(changes);\n }\n }, []);\n const setEdges = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((payload) => {\n const { edges = [], setEdges, hasDefaultEdges, onEdgesChange } = store.getState();\n const nextEdges = typeof payload === 'function' ? payload(edges) : payload;\n if (hasDefaultEdges) {\n setEdges(nextEdges);\n }\n else if (onEdgesChange) {\n const changes = nextEdges.length === 0\n ? edges.map((edge) => ({ type: 'remove', id: edge.id }))\n : nextEdges.map((edge) => ({ item: edge, type: 'reset' }));\n onEdgesChange(changes);\n }\n }, []);\n const addNodes = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((payload) => {\n const nodes = Array.isArray(payload) ? payload : [payload];\n const { getNodes, setNodes, hasDefaultNodes, onNodesChange } = store.getState();\n if (hasDefaultNodes) {\n const currentNodes = getNodes();\n const nextNodes = [...currentNodes, ...nodes];\n setNodes(nextNodes);\n }\n else if (onNodesChange) {\n const changes = nodes.map((node) => ({ item: node, type: 'add' }));\n onNodesChange(changes);\n }\n }, []);\n const addEdges = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((payload) => {\n const nextEdges = Array.isArray(payload) ? payload : [payload];\n const { edges = [], setEdges, hasDefaultEdges, onEdgesChange } = store.getState();\n if (hasDefaultEdges) {\n setEdges([...edges, ...nextEdges]);\n }\n else if (onEdgesChange) {\n const changes = nextEdges.map((edge) => ({ item: edge, type: 'add' }));\n onEdgesChange(changes);\n }\n }, []);\n const toObject = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(() => {\n const { getNodes, edges = [], transform } = store.getState();\n const [x, y, zoom] = transform;\n return {\n nodes: getNodes().map((n) => ({ ...n })),\n edges: edges.map((e) => ({ ...e })),\n viewport: {\n x,\n y,\n zoom,\n },\n };\n }, []);\n const deleteElements = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(({ nodes: nodesDeleted, edges: edgesDeleted }) => {\n const { nodeInternals, getNodes, edges, hasDefaultNodes, hasDefaultEdges, onNodesDelete, onEdgesDelete, onNodesChange, onEdgesChange, } = store.getState();\n const nodeIds = (nodesDeleted || []).map((node) => node.id);\n const edgeIds = (edgesDeleted || []).map((edge) => edge.id);\n const nodesToRemove = getNodes().reduce((res, node) => {\n const parentHit = !nodeIds.includes(node.id) && node.parentNode && res.find((n) => n.id === node.parentNode);\n const deletable = typeof node.deletable === 'boolean' ? node.deletable : true;\n if (deletable && (nodeIds.includes(node.id) || parentHit)) {\n res.push(node);\n }\n return res;\n }, []);\n const deletableEdges = edges.filter((e) => (typeof e.deletable === 'boolean' ? e.deletable : true));\n const initialHitEdges = deletableEdges.filter((e) => edgeIds.includes(e.id));\n if (nodesToRemove || initialHitEdges) {\n const connectedEdges = getConnectedEdges(nodesToRemove, deletableEdges);\n const edgesToRemove = [...initialHitEdges, ...connectedEdges];\n const edgeIdsToRemove = edgesToRemove.reduce((res, edge) => {\n if (!res.includes(edge.id)) {\n res.push(edge.id);\n }\n return res;\n }, []);\n if (hasDefaultEdges || hasDefaultNodes) {\n if (hasDefaultEdges) {\n store.setState({\n edges: edges.filter((e) => !edgeIdsToRemove.includes(e.id)),\n });\n }\n if (hasDefaultNodes) {\n nodesToRemove.forEach((node) => {\n nodeInternals.delete(node.id);\n });\n store.setState({\n nodeInternals: new Map(nodeInternals),\n });\n }\n }\n if (edgeIdsToRemove.length > 0) {\n onEdgesDelete?.(edgesToRemove);\n if (onEdgesChange) {\n onEdgesChange(edgeIdsToRemove.map((id) => ({\n id,\n type: 'remove',\n })));\n }\n }\n if (nodesToRemove.length > 0) {\n onNodesDelete?.(nodesToRemove);\n if (onNodesChange) {\n const nodeChanges = nodesToRemove.map((n) => ({ id: n.id, type: 'remove' }));\n onNodesChange(nodeChanges);\n }\n }\n }\n }, []);\n const getNodeRect = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((nodeOrRect) => {\n const isRect = isRectObject(nodeOrRect);\n const node = isRect ? null : store.getState().nodeInternals.get(nodeOrRect.id);\n if (!isRect && !node) {\n return [null, null, isRect];\n }\n const nodeRect = isRect ? nodeOrRect : nodeToRect(node);\n return [nodeRect, node, isRect];\n }, []);\n const getIntersectingNodes = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((nodeOrRect, partially = true, nodes) => {\n const [nodeRect, node, isRect] = getNodeRect(nodeOrRect);\n if (!nodeRect) {\n return [];\n }\n return (nodes || store.getState().getNodes()).filter((n) => {\n if (!isRect && (n.id === node.id || !n.positionAbsolute)) {\n return false;\n }\n const currNodeRect = nodeToRect(n);\n const overlappingArea = getOverlappingArea(currNodeRect, nodeRect);\n const partiallyVisible = partially && overlappingArea > 0;\n return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;\n });\n }, []);\n const isNodeIntersecting = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((nodeOrRect, area, partially = true) => {\n const [nodeRect] = getNodeRect(nodeOrRect);\n if (!nodeRect) {\n return false;\n }\n const overlappingArea = getOverlappingArea(nodeRect, area);\n const partiallyVisible = partially && overlappingArea > 0;\n return partiallyVisible || overlappingArea >= nodeRect.width * nodeRect.height;\n }, []);\n return (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {\n return {\n ...viewportHelper,\n getNodes,\n getNode,\n getEdges,\n getEdge,\n setNodes,\n setEdges,\n addNodes,\n addEdges,\n toObject,\n deleteElements,\n getIntersectingNodes,\n isNodeIntersecting,\n };\n }, [\n viewportHelper,\n getNodes,\n getNode,\n getEdges,\n getEdge,\n setNodes,\n setEdges,\n addNodes,\n addEdges,\n toObject,\n deleteElements,\n getIntersectingNodes,\n isNodeIntersecting,\n ]);\n}\n\nconst deleteKeyOptions = { actInsideInputWithModifier: false };\nvar useGlobalKeyHandler = ({ deleteKeyCode, multiSelectionKeyCode }) => {\n const store = useStoreApi();\n const { deleteElements } = useReactFlow();\n const deleteKeyPressed = useKeyPress(deleteKeyCode, deleteKeyOptions);\n const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (deleteKeyPressed) {\n const { edges, getNodes } = store.getState();\n const selectedNodes = getNodes().filter((node) => node.selected);\n const selectedEdges = edges.filter((edge) => edge.selected);\n deleteElements({ nodes: selectedNodes, edges: selectedEdges });\n store.setState({ nodesSelectionActive: false });\n }\n }, [deleteKeyPressed]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n store.setState({ multiSelectionActive: multiSelectionKeyPressed });\n }, [multiSelectionKeyPressed]);\n};\n\nfunction useResizeHandler(rendererNode) {\n const store = useStoreApi();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n let resizeObserver;\n const updateDimensions = () => {\n if (!rendererNode.current) {\n return;\n }\n const size = getDimensions(rendererNode.current);\n if (size.height === 0 || size.width === 0) {\n store.getState().onError?.('004', errorMessages['error004']());\n }\n store.setState({ width: size.width || 500, height: size.height || 500 });\n };\n updateDimensions();\n window.addEventListener('resize', updateDimensions);\n if (rendererNode.current) {\n resizeObserver = new ResizeObserver(() => updateDimensions());\n resizeObserver.observe(rendererNode.current);\n }\n return () => {\n window.removeEventListener('resize', updateDimensions);\n if (resizeObserver && rendererNode.current) {\n resizeObserver.unobserve(rendererNode.current);\n }\n };\n }, []);\n}\n\nconst containerStyle = {\n position: 'absolute',\n width: '100%',\n height: '100%',\n top: 0,\n left: 0,\n};\n\n/* eslint-disable @typescript-eslint/ban-ts-comment */\nconst viewChanged = (prevViewport, eventTransform) => prevViewport.x !== eventTransform.x || prevViewport.y !== eventTransform.y || prevViewport.zoom !== eventTransform.k;\nconst eventToFlowTransform = (eventTransform) => ({\n x: eventTransform.x,\n y: eventTransform.y,\n zoom: eventTransform.k,\n});\nconst isWrappedWithClass = (event, className) => event.target.closest(`.${className}`);\nconst isRightClickPan = (panOnDrag, usedButton) => usedButton === 2 && Array.isArray(panOnDrag) && panOnDrag.includes(2);\nconst wheelDelta = (event) => {\n const factor = event.ctrlKey && isMacOs() ? 10 : 1;\n return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 0.002) * factor;\n};\nconst selector$a = (s) => ({\n d3Zoom: s.d3Zoom,\n d3Selection: s.d3Selection,\n d3ZoomHandler: s.d3ZoomHandler,\n userSelectionActive: s.userSelectionActive,\n});\nconst ZoomPane = ({ onMove, onMoveStart, onMoveEnd, onPaneContextMenu, zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, elementsSelectable, panOnDrag = true, defaultViewport, translateExtent, minZoom, maxZoom, zoomActivationKeyCode, preventScrolling = true, children, noWheelClassName, noPanClassName, }) => {\n const timerId = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)();\n const store = useStoreApi();\n const isZoomingOrPanning = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false);\n const zoomedWithRightMouseButton = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false);\n const zoomPane = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n const prevTransform = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)({ x: 0, y: 0, zoom: 0 });\n const { d3Zoom, d3Selection, d3ZoomHandler, userSelectionActive } = useStore(selector$a, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const zoomActivationKeyPressed = useKeyPress(zoomActivationKeyCode);\n const mouseButton = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(0);\n const isPanScrolling = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false);\n const panScrollTimeout = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)();\n useResizeHandler(zoomPane);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (zoomPane.current) {\n const bbox = zoomPane.current.getBoundingClientRect();\n const d3ZoomInstance = (0,d3_zoom__WEBPACK_IMPORTED_MODULE_2__.zoom)().scaleExtent([minZoom, maxZoom]).translateExtent(translateExtent);\n const selection = (0,d3_selection__WEBPACK_IMPORTED_MODULE_6__[\"default\"])(zoomPane.current).call(d3ZoomInstance);\n const updatedTransform = d3_zoom__WEBPACK_IMPORTED_MODULE_2__.zoomIdentity\n .translate(defaultViewport.x, defaultViewport.y)\n .scale(clamp(defaultViewport.zoom, minZoom, maxZoom));\n const extent = [\n [0, 0],\n [bbox.width, bbox.height],\n ];\n const constrainedTransform = d3ZoomInstance.constrain()(updatedTransform, extent, translateExtent);\n d3ZoomInstance.transform(selection, constrainedTransform);\n d3ZoomInstance.wheelDelta(wheelDelta);\n store.setState({\n d3Zoom: d3ZoomInstance,\n d3Selection: selection,\n d3ZoomHandler: selection.on('wheel.zoom'),\n // we need to pass transform because zoom handler is not registered when we set the initial transform\n transform: [constrainedTransform.x, constrainedTransform.y, constrainedTransform.k],\n domNode: zoomPane.current.closest('.react-flow'),\n });\n }\n }, []);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (d3Selection && d3Zoom) {\n if (panOnScroll && !zoomActivationKeyPressed && !userSelectionActive) {\n d3Selection.on('wheel.zoom', (event) => {\n if (isWrappedWithClass(event, noWheelClassName)) {\n return false;\n }\n event.preventDefault();\n event.stopImmediatePropagation();\n const currentZoom = d3Selection.property('__zoom').k || 1;\n const _isMacOs = isMacOs();\n // macos sets ctrlKey=true for pinch gesture on a trackpad\n if (event.ctrlKey && zoomOnPinch && _isMacOs) {\n const point = (0,d3_selection__WEBPACK_IMPORTED_MODULE_7__[\"default\"])(event);\n const pinchDelta = wheelDelta(event);\n const zoom = currentZoom * Math.pow(2, pinchDelta);\n // @ts-ignore\n d3Zoom.scaleTo(d3Selection, zoom, point, event);\n return;\n }\n // increase scroll speed in firefox\n // firefox: deltaMode === 1; chrome: deltaMode === 0\n const deltaNormalize = event.deltaMode === 1 ? 20 : 1;\n let deltaX = panOnScrollMode === PanOnScrollMode.Vertical ? 0 : event.deltaX * deltaNormalize;\n let deltaY = panOnScrollMode === PanOnScrollMode.Horizontal ? 0 : event.deltaY * deltaNormalize;\n // this enables vertical scrolling with shift + scroll on windows\n if (!_isMacOs && event.shiftKey && panOnScrollMode !== PanOnScrollMode.Vertical) {\n deltaX = event.deltaY * deltaNormalize;\n deltaY = 0;\n }\n d3Zoom.translateBy(d3Selection, -(deltaX / currentZoom) * panOnScrollSpeed, -(deltaY / currentZoom) * panOnScrollSpeed, \n // @ts-ignore\n { internal: true });\n const nextViewport = eventToFlowTransform(d3Selection.property('__zoom'));\n const { onViewportChangeStart, onViewportChange, onViewportChangeEnd } = store.getState();\n clearTimeout(panScrollTimeout.current);\n // for pan on scroll we need to handle the event calls on our own\n // we can't use the start, zoom and end events from d3-zoom\n // because start and move gets called on every scroll event and not once at the beginning\n if (!isPanScrolling.current) {\n isPanScrolling.current = true;\n onMoveStart?.(event, nextViewport);\n onViewportChangeStart?.(nextViewport);\n }\n if (isPanScrolling.current) {\n onMove?.(event, nextViewport);\n onViewportChange?.(nextViewport);\n panScrollTimeout.current = setTimeout(() => {\n onMoveEnd?.(event, nextViewport);\n onViewportChangeEnd?.(nextViewport);\n isPanScrolling.current = false;\n }, 150);\n }\n }, { passive: false });\n }\n else if (typeof d3ZoomHandler !== 'undefined') {\n d3Selection.on('wheel.zoom', function (event, d) {\n if (!preventScrolling || isWrappedWithClass(event, noWheelClassName)) {\n return null;\n }\n event.preventDefault();\n d3ZoomHandler.call(this, event, d);\n }, { passive: false });\n }\n }\n }, [\n userSelectionActive,\n panOnScroll,\n panOnScrollMode,\n d3Selection,\n d3Zoom,\n d3ZoomHandler,\n zoomActivationKeyPressed,\n zoomOnPinch,\n preventScrolling,\n noWheelClassName,\n onMoveStart,\n onMove,\n onMoveEnd,\n ]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (d3Zoom) {\n d3Zoom.on('start', (event) => {\n if (!event.sourceEvent || event.sourceEvent.internal) {\n return null;\n }\n // we need to remember it here, because it's always 0 in the \"zoom\" event\n mouseButton.current = event.sourceEvent?.button;\n const { onViewportChangeStart } = store.getState();\n const flowTransform = eventToFlowTransform(event.transform);\n isZoomingOrPanning.current = true;\n prevTransform.current = flowTransform;\n if (event.sourceEvent?.type === 'mousedown') {\n store.setState({ paneDragging: true });\n }\n onViewportChangeStart?.(flowTransform);\n onMoveStart?.(event.sourceEvent, flowTransform);\n });\n }\n }, [d3Zoom, onMoveStart]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (d3Zoom) {\n if (userSelectionActive && !isZoomingOrPanning.current) {\n d3Zoom.on('zoom', null);\n }\n else if (!userSelectionActive) {\n d3Zoom.on('zoom', (event) => {\n const { onViewportChange } = store.getState();\n store.setState({ transform: [event.transform.x, event.transform.y, event.transform.k] });\n zoomedWithRightMouseButton.current = !!(onPaneContextMenu && isRightClickPan(panOnDrag, mouseButton.current ?? 0));\n if ((onMove || onViewportChange) && !event.sourceEvent?.internal) {\n const flowTransform = eventToFlowTransform(event.transform);\n onViewportChange?.(flowTransform);\n onMove?.(event.sourceEvent, flowTransform);\n }\n });\n }\n }\n }, [userSelectionActive, d3Zoom, onMove, panOnDrag, onPaneContextMenu]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (d3Zoom) {\n d3Zoom.on('end', (event) => {\n if (!event.sourceEvent || event.sourceEvent.internal) {\n return null;\n }\n const { onViewportChangeEnd } = store.getState();\n isZoomingOrPanning.current = false;\n store.setState({ paneDragging: false });\n if (onPaneContextMenu &&\n isRightClickPan(panOnDrag, mouseButton.current ?? 0) &&\n !zoomedWithRightMouseButton.current) {\n onPaneContextMenu(event.sourceEvent);\n }\n zoomedWithRightMouseButton.current = false;\n if ((onMoveEnd || onViewportChangeEnd) && viewChanged(prevTransform.current, event.transform)) {\n const flowTransform = eventToFlowTransform(event.transform);\n prevTransform.current = flowTransform;\n clearTimeout(timerId.current);\n timerId.current = setTimeout(() => {\n onViewportChangeEnd?.(flowTransform);\n onMoveEnd?.(event.sourceEvent, flowTransform);\n }, panOnScroll ? 150 : 0);\n }\n });\n }\n }, [d3Zoom, panOnScroll, panOnDrag, onMoveEnd, onPaneContextMenu]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (d3Zoom) {\n d3Zoom.filter((event) => {\n const zoomScroll = zoomActivationKeyPressed || zoomOnScroll;\n const pinchZoom = zoomOnPinch && event.ctrlKey;\n if ((panOnDrag === true || (Array.isArray(panOnDrag) && panOnDrag.includes(1))) &&\n event.button === 1 &&\n event.type === 'mousedown' &&\n (isWrappedWithClass(event, 'react-flow__node') || isWrappedWithClass(event, 'react-flow__edge'))) {\n return true;\n }\n // if all interactions are disabled, we prevent all zoom events\n if (!panOnDrag && !zoomScroll && !panOnScroll && !zoomOnDoubleClick && !zoomOnPinch) {\n return false;\n }\n // during a selection we prevent all other interactions\n if (userSelectionActive) {\n return false;\n }\n // if zoom on double click is disabled, we prevent the double click event\n if (!zoomOnDoubleClick && event.type === 'dblclick') {\n return false;\n }\n // if the target element is inside an element with the nowheel class, we prevent zooming\n if (isWrappedWithClass(event, noWheelClassName) && event.type === 'wheel') {\n return false;\n }\n // if the target element is inside an element with the nopan class, we prevent panning\n if (isWrappedWithClass(event, noPanClassName) &&\n (event.type !== 'wheel' || (panOnScroll && event.type === 'wheel' && !zoomActivationKeyPressed))) {\n return false;\n }\n if (!zoomOnPinch && event.ctrlKey && event.type === 'wheel') {\n return false;\n }\n // when there is no scroll handling enabled, we prevent all wheel events\n if (!zoomScroll && !panOnScroll && !pinchZoom && event.type === 'wheel') {\n return false;\n }\n // if the pane is not movable, we prevent dragging it with mousestart or touchstart\n if (!panOnDrag && (event.type === 'mousedown' || event.type === 'touchstart')) {\n return false;\n }\n // if the pane is only movable using allowed clicks\n if (Array.isArray(panOnDrag) &&\n !panOnDrag.includes(event.button) &&\n (event.type === 'mousedown' || event.type === 'touchstart')) {\n return false;\n }\n // We only allow right clicks if pan on drag is set to right click\n const buttonAllowed = (Array.isArray(panOnDrag) && panOnDrag.includes(event.button)) || !event.button || event.button <= 1;\n // default filter for d3-zoom\n return (!event.ctrlKey || event.type === 'wheel') && buttonAllowed;\n });\n }\n }, [\n userSelectionActive,\n d3Zoom,\n zoomOnScroll,\n zoomOnPinch,\n panOnScroll,\n zoomOnDoubleClick,\n panOnDrag,\n elementsSelectable,\n zoomActivationKeyPressed,\n ]);\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: \"react-flow__renderer\", ref: zoomPane, style: containerStyle }, children));\n};\n\nconst selector$9 = (s) => ({\n userSelectionActive: s.userSelectionActive,\n userSelectionRect: s.userSelectionRect,\n});\nfunction UserSelection() {\n const { userSelectionActive, userSelectionRect } = useStore(selector$9, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const isActive = userSelectionActive && userSelectionRect;\n if (!isActive) {\n return null;\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: \"react-flow__selection react-flow__container\", style: {\n width: userSelectionRect.width,\n height: userSelectionRect.height,\n transform: `translate(${userSelectionRect.x}px, ${userSelectionRect.y}px)`,\n } }));\n}\n\nfunction handleParentExpand(res, updateItem) {\n const parent = res.find((e) => e.id === updateItem.parentNode);\n if (parent) {\n const extendWidth = updateItem.position.x + updateItem.width - parent.width;\n const extendHeight = updateItem.position.y + updateItem.height - parent.height;\n if (extendWidth > 0 || extendHeight > 0 || updateItem.position.x < 0 || updateItem.position.y < 0) {\n parent.style = { ...parent.style } || {};\n parent.style.width = parent.style.width ?? parent.width;\n parent.style.height = parent.style.height ?? parent.height;\n if (extendWidth > 0) {\n parent.style.width += extendWidth;\n }\n if (extendHeight > 0) {\n parent.style.height += extendHeight;\n }\n if (updateItem.position.x < 0) {\n const xDiff = Math.abs(updateItem.position.x);\n parent.position.x = parent.position.x - xDiff;\n parent.style.width += xDiff;\n updateItem.position.x = 0;\n }\n if (updateItem.position.y < 0) {\n const yDiff = Math.abs(updateItem.position.y);\n parent.position.y = parent.position.y - yDiff;\n parent.style.height += yDiff;\n updateItem.position.y = 0;\n }\n parent.width = parent.style.width;\n parent.height = parent.style.height;\n }\n }\n}\nfunction applyChanges(changes, elements) {\n // we need this hack to handle the setNodes and setEdges function of the useReactFlow hook for controlled flows\n if (changes.some((c) => c.type === 'reset')) {\n return changes.filter((c) => c.type === 'reset').map((c) => c.item);\n }\n const initElements = changes.filter((c) => c.type === 'add').map((c) => c.item);\n return elements.reduce((res, item) => {\n const currentChanges = changes.filter((c) => c.id === item.id);\n if (currentChanges.length === 0) {\n res.push(item);\n return res;\n }\n const updateItem = { ...item };\n for (const currentChange of currentChanges) {\n if (currentChange) {\n switch (currentChange.type) {\n case 'select': {\n updateItem.selected = currentChange.selected;\n break;\n }\n case 'position': {\n if (typeof currentChange.position !== 'undefined') {\n updateItem.position = currentChange.position;\n }\n if (typeof currentChange.positionAbsolute !== 'undefined') {\n updateItem.positionAbsolute = currentChange.positionAbsolute;\n }\n if (typeof currentChange.dragging !== 'undefined') {\n updateItem.dragging = currentChange.dragging;\n }\n if (updateItem.expandParent) {\n handleParentExpand(res, updateItem);\n }\n break;\n }\n case 'dimensions': {\n if (typeof currentChange.dimensions !== 'undefined') {\n updateItem.width = currentChange.dimensions.width;\n updateItem.height = currentChange.dimensions.height;\n }\n if (typeof currentChange.updateStyle !== 'undefined') {\n updateItem.style = { ...(updateItem.style || {}), ...currentChange.dimensions };\n }\n if (typeof currentChange.resizing === 'boolean') {\n updateItem.resizing = currentChange.resizing;\n }\n if (updateItem.expandParent) {\n handleParentExpand(res, updateItem);\n }\n break;\n }\n case 'remove': {\n return res;\n }\n }\n }\n }\n res.push(updateItem);\n return res;\n }, initElements);\n}\nfunction applyNodeChanges(changes, nodes) {\n return applyChanges(changes, nodes);\n}\nfunction applyEdgeChanges(changes, edges) {\n return applyChanges(changes, edges);\n}\nconst createSelectionChange = (id, selected) => ({\n id,\n type: 'select',\n selected,\n});\nfunction getSelectionChanges(items, selectedIds) {\n return items.reduce((res, item) => {\n const willBeSelected = selectedIds.includes(item.id);\n if (!item.selected && willBeSelected) {\n item.selected = true;\n res.push(createSelectionChange(item.id, true));\n }\n else if (item.selected && !willBeSelected) {\n item.selected = false;\n res.push(createSelectionChange(item.id, false));\n }\n return res;\n }, []);\n}\n\n/**\n * The user selection rectangle gets displayed when a user drags the mouse while pressing shift\n */\nconst wrapHandler = (handler, containerRef) => {\n return (event) => {\n if (event.target !== containerRef.current) {\n return;\n }\n handler?.(event);\n };\n};\nconst selector$8 = (s) => ({\n userSelectionActive: s.userSelectionActive,\n elementsSelectable: s.elementsSelectable,\n dragging: s.paneDragging,\n});\nconst Pane = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(({ isSelecting, selectionMode = SelectionMode.Full, panOnDrag, onSelectionStart, onSelectionEnd, onPaneClick, onPaneContextMenu, onPaneScroll, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, children, }) => {\n const container = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n const store = useStoreApi();\n const prevSelectedNodesCount = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(0);\n const prevSelectedEdgesCount = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(0);\n const containerBounds = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)();\n const { userSelectionActive, elementsSelectable, dragging } = useStore(selector$8, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const resetUserSelection = () => {\n store.setState({ userSelectionActive: false, userSelectionRect: null });\n prevSelectedNodesCount.current = 0;\n prevSelectedEdgesCount.current = 0;\n };\n const onClick = (event) => {\n onPaneClick?.(event);\n store.getState().resetSelectedElements();\n store.setState({ nodesSelectionActive: false });\n };\n const onContextMenu = (event) => {\n if (Array.isArray(panOnDrag) && panOnDrag?.includes(2)) {\n event.preventDefault();\n return;\n }\n onPaneContextMenu?.(event);\n };\n const onWheel = onPaneScroll ? (event) => onPaneScroll(event) : undefined;\n const onMouseDown = (event) => {\n const { resetSelectedElements, domNode } = store.getState();\n containerBounds.current = domNode?.getBoundingClientRect();\n if (!elementsSelectable ||\n !isSelecting ||\n event.button !== 0 ||\n event.target !== container.current ||\n !containerBounds.current) {\n return;\n }\n const { x, y } = getEventPosition(event, containerBounds.current);\n resetSelectedElements();\n store.setState({\n userSelectionRect: {\n width: 0,\n height: 0,\n startX: x,\n startY: y,\n x,\n y,\n },\n });\n onSelectionStart?.(event);\n };\n const onMouseMove = (event) => {\n const { userSelectionRect, nodeInternals, edges, transform, onNodesChange, onEdgesChange, nodeOrigin, getNodes } = store.getState();\n if (!isSelecting || !containerBounds.current || !userSelectionRect) {\n return;\n }\n store.setState({ userSelectionActive: true, nodesSelectionActive: false });\n const mousePos = getEventPosition(event, containerBounds.current);\n const startX = userSelectionRect.startX ?? 0;\n const startY = userSelectionRect.startY ?? 0;\n const nextUserSelectRect = {\n ...userSelectionRect,\n x: mousePos.x < startX ? mousePos.x : startX,\n y: mousePos.y < startY ? mousePos.y : startY,\n width: Math.abs(mousePos.x - startX),\n height: Math.abs(mousePos.y - startY),\n };\n const nodes = getNodes();\n const selectedNodes = getNodesInside(nodeInternals, nextUserSelectRect, transform, selectionMode === SelectionMode.Partial, true, nodeOrigin);\n const selectedEdgeIds = getConnectedEdges(selectedNodes, edges).map((e) => e.id);\n const selectedNodeIds = selectedNodes.map((n) => n.id);\n if (prevSelectedNodesCount.current !== selectedNodeIds.length) {\n prevSelectedNodesCount.current = selectedNodeIds.length;\n const changes = getSelectionChanges(nodes, selectedNodeIds);\n if (changes.length) {\n onNodesChange?.(changes);\n }\n }\n if (prevSelectedEdgesCount.current !== selectedEdgeIds.length) {\n prevSelectedEdgesCount.current = selectedEdgeIds.length;\n const changes = getSelectionChanges(edges, selectedEdgeIds);\n if (changes.length) {\n onEdgesChange?.(changes);\n }\n }\n store.setState({\n userSelectionRect: nextUserSelectRect,\n });\n };\n const onMouseUp = (event) => {\n if (event.button !== 0) {\n return;\n }\n const { userSelectionRect } = store.getState();\n // We only want to trigger click functions when in selection mode if\n // the user did not move the mouse.\n if (!userSelectionActive && userSelectionRect && event.target === container.current) {\n onClick?.(event);\n }\n store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 });\n resetUserSelection();\n onSelectionEnd?.(event);\n };\n const onMouseLeave = (event) => {\n if (userSelectionActive) {\n store.setState({ nodesSelectionActive: prevSelectedNodesCount.current > 0 });\n onSelectionEnd?.(event);\n }\n resetUserSelection();\n };\n const hasActiveSelection = elementsSelectable && (isSelecting || userSelectionActive);\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(['react-flow__pane', { dragging, selection: isSelecting }]), onClick: hasActiveSelection ? undefined : wrapHandler(onClick, container), onContextMenu: wrapHandler(onContextMenu, container), onWheel: wrapHandler(onWheel, container), onMouseEnter: hasActiveSelection ? undefined : onPaneMouseEnter, onMouseDown: hasActiveSelection ? onMouseDown : undefined, onMouseMove: hasActiveSelection ? onMouseMove : onPaneMouseMove, onMouseUp: hasActiveSelection ? onMouseUp : undefined, onMouseLeave: hasActiveSelection ? onMouseLeave : onPaneMouseLeave, ref: container, style: containerStyle },\n children,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(UserSelection, null)));\n});\nPane.displayName = 'Pane';\n\nfunction isParentSelected(node, nodeInternals) {\n if (!node.parentNode) {\n return false;\n }\n const parentNode = nodeInternals.get(node.parentNode);\n if (!parentNode) {\n return false;\n }\n if (parentNode.selected) {\n return true;\n }\n return isParentSelected(parentNode, nodeInternals);\n}\nfunction hasSelector(target, selector, nodeRef) {\n let current = target;\n do {\n if (current?.matches(selector))\n return true;\n if (current === nodeRef.current)\n return false;\n current = current.parentElement;\n } while (current);\n return false;\n}\n// looks for all selected nodes and created a NodeDragItem for each of them\nfunction getDragItems(nodeInternals, nodesDraggable, mousePos, nodeId) {\n return Array.from(nodeInternals.values())\n .filter((n) => (n.selected || n.id === nodeId) &&\n (!n.parentNode || !isParentSelected(n, nodeInternals)) &&\n (n.draggable || (nodesDraggable && typeof n.draggable === 'undefined')))\n .map((n) => ({\n id: n.id,\n position: n.position || { x: 0, y: 0 },\n positionAbsolute: n.positionAbsolute || { x: 0, y: 0 },\n distance: {\n x: mousePos.x - (n.positionAbsolute?.x ?? 0),\n y: mousePos.y - (n.positionAbsolute?.y ?? 0),\n },\n delta: {\n x: 0,\n y: 0,\n },\n extent: n.extent,\n parentNode: n.parentNode,\n width: n.width,\n height: n.height,\n expandParent: n.expandParent,\n }));\n}\nfunction clampNodeExtent(node, extent) {\n if (!extent || extent === 'parent') {\n return extent;\n }\n return [extent[0], [extent[1][0] - (node.width || 0), extent[1][1] - (node.height || 0)]];\n}\nfunction calcNextPosition(node, nextPosition, nodeInternals, nodeExtent, nodeOrigin = [0, 0], onError) {\n const clampedNodeExtent = clampNodeExtent(node, node.extent || nodeExtent);\n let currentExtent = clampedNodeExtent;\n if (node.extent === 'parent' && !node.expandParent) {\n if (node.parentNode && node.width && node.height) {\n const parent = nodeInternals.get(node.parentNode);\n const { x: parentX, y: parentY } = getNodePositionWithOrigin(parent, nodeOrigin).positionAbsolute;\n currentExtent =\n parent && isNumeric(parentX) && isNumeric(parentY) && isNumeric(parent.width) && isNumeric(parent.height)\n ? [\n [parentX + node.width * nodeOrigin[0], parentY + node.height * nodeOrigin[1]],\n [\n parentX + parent.width - node.width + node.width * nodeOrigin[0],\n parentY + parent.height - node.height + node.height * nodeOrigin[1],\n ],\n ]\n : currentExtent;\n }\n else {\n onError?.('005', errorMessages['error005']());\n currentExtent = clampedNodeExtent;\n }\n }\n else if (node.extent && node.parentNode && node.extent !== 'parent') {\n const parent = nodeInternals.get(node.parentNode);\n const { x: parentX, y: parentY } = getNodePositionWithOrigin(parent, nodeOrigin).positionAbsolute;\n currentExtent = [\n [node.extent[0][0] + parentX, node.extent[0][1] + parentY],\n [node.extent[1][0] + parentX, node.extent[1][1] + parentY],\n ];\n }\n let parentPosition = { x: 0, y: 0 };\n if (node.parentNode) {\n const parentNode = nodeInternals.get(node.parentNode);\n parentPosition = getNodePositionWithOrigin(parentNode, nodeOrigin).positionAbsolute;\n }\n const positionAbsolute = currentExtent && currentExtent !== 'parent'\n ? clampPosition(nextPosition, currentExtent)\n : nextPosition;\n return {\n position: {\n x: positionAbsolute.x - parentPosition.x,\n y: positionAbsolute.y - parentPosition.y,\n },\n positionAbsolute,\n };\n}\n// returns two params:\n// 1. the dragged node (or the first of the list, if we are dragging a node selection)\n// 2. array of selected nodes (for multi selections)\nfunction getEventHandlerParams({ nodeId, dragItems, nodeInternals, }) {\n const extentedDragItems = dragItems.map((n) => {\n const node = nodeInternals.get(n.id);\n return {\n ...node,\n position: n.position,\n positionAbsolute: n.positionAbsolute,\n };\n });\n return [nodeId ? extentedDragItems.find((n) => n.id === nodeId) : extentedDragItems[0], extentedDragItems];\n}\n\nconst getHandleBounds = (selector, nodeElement, zoom, nodeOrigin) => {\n const handles = nodeElement.querySelectorAll(selector);\n if (!handles || !handles.length) {\n return null;\n }\n const handlesArray = Array.from(handles);\n const nodeBounds = nodeElement.getBoundingClientRect();\n const nodeOffset = {\n x: nodeBounds.width * nodeOrigin[0],\n y: nodeBounds.height * nodeOrigin[1],\n };\n return handlesArray.map((handle) => {\n const handleBounds = handle.getBoundingClientRect();\n return {\n id: handle.getAttribute('data-handleid'),\n position: handle.getAttribute('data-handlepos'),\n x: (handleBounds.left - nodeBounds.left - nodeOffset.x) / zoom,\n y: (handleBounds.top - nodeBounds.top - nodeOffset.y) / zoom,\n ...getDimensions(handle),\n };\n });\n};\nfunction getMouseHandler(id, getState, handler) {\n return handler === undefined\n ? handler\n : (event) => {\n const node = getState().nodeInternals.get(id);\n if (node) {\n handler(event, { ...node });\n }\n };\n}\n// this handler is called by\n// 1. the click handler when node is not draggable or selectNodesOnDrag = false\n// or\n// 2. the on drag start handler when node is draggable and selectNodesOnDrag = true\nfunction handleNodeClick({ id, store, unselect = false, nodeRef, }) {\n const { addSelectedNodes, unselectNodesAndEdges, multiSelectionActive, nodeInternals, onError } = store.getState();\n const node = nodeInternals.get(id);\n if (!node) {\n onError?.('012', errorMessages['error012'](id));\n return;\n }\n store.setState({ nodesSelectionActive: false });\n if (!node.selected) {\n addSelectedNodes([id]);\n }\n else if (unselect || (node.selected && multiSelectionActive)) {\n unselectNodesAndEdges({ nodes: [node], edges: [] });\n requestAnimationFrame(() => nodeRef?.current?.blur());\n }\n}\n\nfunction useGetPointerPosition() {\n const store = useStoreApi();\n // returns the pointer position projected to the RF coordinate system\n const getPointerPosition = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(({ sourceEvent }) => {\n const { transform, snapGrid, snapToGrid } = store.getState();\n const x = sourceEvent.touches ? sourceEvent.touches[0].clientX : sourceEvent.clientX;\n const y = sourceEvent.touches ? sourceEvent.touches[0].clientY : sourceEvent.clientY;\n const pointerPos = {\n x: (x - transform[0]) / transform[2],\n y: (y - transform[1]) / transform[2],\n };\n // we need the snapped position in order to be able to skip unnecessary drag events\n return {\n xSnapped: snapToGrid ? snapGrid[0] * Math.round(pointerPos.x / snapGrid[0]) : pointerPos.x,\n ySnapped: snapToGrid ? snapGrid[1] * Math.round(pointerPos.y / snapGrid[1]) : pointerPos.y,\n ...pointerPos,\n };\n }, []);\n return getPointerPosition;\n}\n\nfunction wrapSelectionDragFunc(selectionFunc) {\n return (event, _, nodes) => selectionFunc?.(event, nodes);\n}\nfunction useDrag({ nodeRef, disabled = false, noDragClassName, handleSelector, nodeId, isSelectable, selectNodesOnDrag, }) {\n const store = useStoreApi();\n const [dragging, setDragging] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);\n const dragItems = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)([]);\n const lastPos = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)({ x: null, y: null });\n const autoPanId = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(0);\n const containerBounds = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n const mousePosition = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)({ x: 0, y: 0 });\n const dragEvent = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n const autoPanStarted = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false);\n const dragStarted = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false);\n const getPointerPosition = useGetPointerPosition();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (nodeRef?.current) {\n const selection = (0,d3_selection__WEBPACK_IMPORTED_MODULE_6__[\"default\"])(nodeRef.current);\n const updateNodes = ({ x, y }) => {\n const { nodeInternals, onNodeDrag, onSelectionDrag, updateNodePositions, nodeExtent, snapGrid, snapToGrid, nodeOrigin, onError, } = store.getState();\n lastPos.current = { x, y };\n let hasChange = false;\n let nodesBox = { x: 0, y: 0, x2: 0, y2: 0 };\n if (dragItems.current.length > 1 && nodeExtent) {\n const rect = getNodesBounds(dragItems.current, nodeOrigin);\n nodesBox = rectToBox(rect);\n }\n dragItems.current = dragItems.current.map((n) => {\n const nextPosition = { x: x - n.distance.x, y: y - n.distance.y };\n if (snapToGrid) {\n nextPosition.x = snapGrid[0] * Math.round(nextPosition.x / snapGrid[0]);\n nextPosition.y = snapGrid[1] * Math.round(nextPosition.y / snapGrid[1]);\n }\n // if there is selection with multiple nodes and a node extent is set, we need to adjust the node extent for each node\n // based on its position so that the node stays at it's position relative to the selection.\n const adjustedNodeExtent = [\n [nodeExtent[0][0], nodeExtent[0][1]],\n [nodeExtent[1][0], nodeExtent[1][1]],\n ];\n if (dragItems.current.length > 1 && nodeExtent && !n.extent) {\n adjustedNodeExtent[0][0] = n.positionAbsolute.x - nodesBox.x + nodeExtent[0][0];\n adjustedNodeExtent[1][0] = n.positionAbsolute.x + (n.width ?? 0) - nodesBox.x2 + nodeExtent[1][0];\n adjustedNodeExtent[0][1] = n.positionAbsolute.y - nodesBox.y + nodeExtent[0][1];\n adjustedNodeExtent[1][1] = n.positionAbsolute.y + (n.height ?? 0) - nodesBox.y2 + nodeExtent[1][1];\n }\n const updatedPos = calcNextPosition(n, nextPosition, nodeInternals, adjustedNodeExtent, nodeOrigin, onError);\n // we want to make sure that we only fire a change event when there is a change\n hasChange = hasChange || n.position.x !== updatedPos.position.x || n.position.y !== updatedPos.position.y;\n n.position = updatedPos.position;\n n.positionAbsolute = updatedPos.positionAbsolute;\n return n;\n });\n if (!hasChange) {\n return;\n }\n updateNodePositions(dragItems.current, true, true);\n setDragging(true);\n const onDrag = nodeId ? onNodeDrag : wrapSelectionDragFunc(onSelectionDrag);\n if (onDrag && dragEvent.current) {\n const [currentNode, nodes] = getEventHandlerParams({\n nodeId,\n dragItems: dragItems.current,\n nodeInternals,\n });\n onDrag(dragEvent.current, currentNode, nodes);\n }\n };\n const autoPan = () => {\n if (!containerBounds.current) {\n return;\n }\n const [xMovement, yMovement] = calcAutoPan(mousePosition.current, containerBounds.current);\n if (xMovement !== 0 || yMovement !== 0) {\n const { transform, panBy } = store.getState();\n lastPos.current.x = (lastPos.current.x ?? 0) - xMovement / transform[2];\n lastPos.current.y = (lastPos.current.y ?? 0) - yMovement / transform[2];\n if (panBy({ x: xMovement, y: yMovement })) {\n updateNodes(lastPos.current);\n }\n }\n autoPanId.current = requestAnimationFrame(autoPan);\n };\n const startDrag = (event) => {\n const { nodeInternals, multiSelectionActive, nodesDraggable, unselectNodesAndEdges, onNodeDragStart, onSelectionDragStart, } = store.getState();\n dragStarted.current = true;\n const onStart = nodeId ? onNodeDragStart : wrapSelectionDragFunc(onSelectionDragStart);\n if ((!selectNodesOnDrag || !isSelectable) && !multiSelectionActive && nodeId) {\n if (!nodeInternals.get(nodeId)?.selected) {\n // we need to reset selected nodes when selectNodesOnDrag=false\n unselectNodesAndEdges();\n }\n }\n if (nodeId && isSelectable && selectNodesOnDrag) {\n handleNodeClick({\n id: nodeId,\n store,\n nodeRef: nodeRef,\n });\n }\n const pointerPos = getPointerPosition(event);\n lastPos.current = pointerPos;\n dragItems.current = getDragItems(nodeInternals, nodesDraggable, pointerPos, nodeId);\n if (onStart && dragItems.current) {\n const [currentNode, nodes] = getEventHandlerParams({\n nodeId,\n dragItems: dragItems.current,\n nodeInternals,\n });\n onStart(event.sourceEvent, currentNode, nodes);\n }\n };\n if (disabled) {\n selection.on('.drag', null);\n }\n else {\n const dragHandler = (0,d3_drag__WEBPACK_IMPORTED_MODULE_8__[\"default\"])()\n .on('start', (event) => {\n const { domNode, nodeDragThreshold } = store.getState();\n if (nodeDragThreshold === 0) {\n startDrag(event);\n }\n const pointerPos = getPointerPosition(event);\n lastPos.current = pointerPos;\n containerBounds.current = domNode?.getBoundingClientRect() || null;\n mousePosition.current = getEventPosition(event.sourceEvent, containerBounds.current);\n })\n .on('drag', (event) => {\n const pointerPos = getPointerPosition(event);\n const { autoPanOnNodeDrag, nodeDragThreshold } = store.getState();\n if (!autoPanStarted.current && dragStarted.current && autoPanOnNodeDrag) {\n autoPanStarted.current = true;\n autoPan();\n }\n if (!dragStarted.current) {\n const x = pointerPos.xSnapped - (lastPos?.current?.x ?? 0);\n const y = pointerPos.ySnapped - (lastPos?.current?.y ?? 0);\n const distance = Math.sqrt(x * x + y * y);\n if (distance > nodeDragThreshold) {\n startDrag(event);\n }\n }\n // skip events without movement\n if ((lastPos.current.x !== pointerPos.xSnapped || lastPos.current.y !== pointerPos.ySnapped) &&\n dragItems.current &&\n dragStarted.current) {\n dragEvent.current = event.sourceEvent;\n mousePosition.current = getEventPosition(event.sourceEvent, containerBounds.current);\n updateNodes(pointerPos);\n }\n })\n .on('end', (event) => {\n if (!dragStarted.current) {\n return;\n }\n setDragging(false);\n autoPanStarted.current = false;\n dragStarted.current = false;\n cancelAnimationFrame(autoPanId.current);\n if (dragItems.current) {\n const { updateNodePositions, nodeInternals, onNodeDragStop, onSelectionDragStop } = store.getState();\n const onStop = nodeId ? onNodeDragStop : wrapSelectionDragFunc(onSelectionDragStop);\n updateNodePositions(dragItems.current, false, false);\n if (onStop) {\n const [currentNode, nodes] = getEventHandlerParams({\n nodeId,\n dragItems: dragItems.current,\n nodeInternals,\n });\n onStop(event.sourceEvent, currentNode, nodes);\n }\n }\n })\n .filter((event) => {\n const target = event.target;\n const isDraggable = !event.button &&\n (!noDragClassName || !hasSelector(target, `.${noDragClassName}`, nodeRef)) &&\n (!handleSelector || hasSelector(target, handleSelector, nodeRef));\n return isDraggable;\n });\n selection.call(dragHandler);\n return () => {\n selection.on('.drag', null);\n };\n }\n }\n }, [\n nodeRef,\n disabled,\n noDragClassName,\n handleSelector,\n isSelectable,\n store,\n nodeId,\n selectNodesOnDrag,\n getPointerPosition,\n ]);\n return dragging;\n}\n\nfunction useUpdateNodePositions() {\n const store = useStoreApi();\n const updatePositions = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((params) => {\n const { nodeInternals, nodeExtent, updateNodePositions, getNodes, snapToGrid, snapGrid, onError, nodesDraggable } = store.getState();\n const selectedNodes = getNodes().filter((n) => n.selected && (n.draggable || (nodesDraggable && typeof n.draggable === 'undefined')));\n // by default a node moves 5px on each key press, or 20px if shift is pressed\n // if snap grid is enabled, we use that for the velocity.\n const xVelo = snapToGrid ? snapGrid[0] : 5;\n const yVelo = snapToGrid ? snapGrid[1] : 5;\n const factor = params.isShiftPressed ? 4 : 1;\n const positionDiffX = params.x * xVelo * factor;\n const positionDiffY = params.y * yVelo * factor;\n const nodeUpdates = selectedNodes.map((n) => {\n if (n.positionAbsolute) {\n const nextPosition = { x: n.positionAbsolute.x + positionDiffX, y: n.positionAbsolute.y + positionDiffY };\n if (snapToGrid) {\n nextPosition.x = snapGrid[0] * Math.round(nextPosition.x / snapGrid[0]);\n nextPosition.y = snapGrid[1] * Math.round(nextPosition.y / snapGrid[1]);\n }\n const { positionAbsolute, position } = calcNextPosition(n, nextPosition, nodeInternals, nodeExtent, undefined, onError);\n n.position = position;\n n.positionAbsolute = positionAbsolute;\n }\n return n;\n });\n updateNodePositions(nodeUpdates, true, false);\n }, []);\n return updatePositions;\n}\n\nconst arrowKeyDiffs = {\n ArrowUp: { x: 0, y: -1 },\n ArrowDown: { x: 0, y: 1 },\n ArrowLeft: { x: -1, y: 0 },\n ArrowRight: { x: 1, y: 0 },\n};\nvar wrapNode = (NodeComponent) => {\n const NodeWrapper = ({ id, type, data, xPos, yPos, xPosOrigin, yPosOrigin, selected, onClick, onMouseEnter, onMouseMove, onMouseLeave, onContextMenu, onDoubleClick, style, className, isDraggable, isSelectable, isConnectable, isFocusable, selectNodesOnDrag, sourcePosition, targetPosition, hidden, resizeObserver, dragHandle, zIndex, isParent, noDragClassName, noPanClassName, initialized, disableKeyboardA11y, ariaLabel, rfId, hasHandleBounds, }) => {\n const store = useStoreApi();\n const nodeRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n const prevSourcePosition = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(sourcePosition);\n const prevTargetPosition = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(targetPosition);\n const prevType = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(type);\n const hasPointerEvents = isSelectable || isDraggable || onClick || onMouseEnter || onMouseMove || onMouseLeave;\n const updatePositions = useUpdateNodePositions();\n const onMouseEnterHandler = getMouseHandler(id, store.getState, onMouseEnter);\n const onMouseMoveHandler = getMouseHandler(id, store.getState, onMouseMove);\n const onMouseLeaveHandler = getMouseHandler(id, store.getState, onMouseLeave);\n const onContextMenuHandler = getMouseHandler(id, store.getState, onContextMenu);\n const onDoubleClickHandler = getMouseHandler(id, store.getState, onDoubleClick);\n const onSelectNodeHandler = (event) => {\n const { nodeDragThreshold } = store.getState();\n if (isSelectable && (!selectNodesOnDrag || !isDraggable || nodeDragThreshold > 0)) {\n // this handler gets called within the drag start event when selectNodesOnDrag=true\n handleNodeClick({\n id,\n store,\n nodeRef,\n });\n }\n if (onClick) {\n const node = store.getState().nodeInternals.get(id);\n if (node) {\n onClick(event, { ...node });\n }\n }\n };\n const onKeyDown = (event) => {\n if (isInputDOMNode(event)) {\n return;\n }\n if (elementSelectionKeys.includes(event.key) && isSelectable) {\n const unselect = event.key === 'Escape';\n handleNodeClick({\n id,\n store,\n unselect,\n nodeRef,\n });\n }\n else if (!disableKeyboardA11y &&\n isDraggable &&\n selected &&\n Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) {\n store.setState({\n ariaLiveMessage: `Moved selected node ${event.key\n .replace('Arrow', '')\n .toLowerCase()}. New position, x: ${~~xPos}, y: ${~~yPos}`,\n });\n updatePositions({\n x: arrowKeyDiffs[event.key].x,\n y: arrowKeyDiffs[event.key].y,\n isShiftPressed: event.shiftKey,\n });\n }\n };\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n return () => {\n if (nodeRef.current) {\n resizeObserver?.unobserve(nodeRef.current);\n }\n };\n }, []);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (nodeRef.current && !hidden) {\n const currNode = nodeRef.current;\n if (!initialized || !hasHandleBounds) {\n // At this point we always want to make sure that the node gets re-measured / re-initialized.\n // We need to unobserve it first in case it is still observed\n resizeObserver?.unobserve(currNode);\n resizeObserver?.observe(currNode);\n }\n }\n }, [hidden, initialized, hasHandleBounds]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n // when the user programmatically changes the source or handle position, we re-initialize the node\n const typeChanged = prevType.current !== type;\n const sourcePosChanged = prevSourcePosition.current !== sourcePosition;\n const targetPosChanged = prevTargetPosition.current !== targetPosition;\n if (nodeRef.current && (typeChanged || sourcePosChanged || targetPosChanged)) {\n if (typeChanged) {\n prevType.current = type;\n }\n if (sourcePosChanged) {\n prevSourcePosition.current = sourcePosition;\n }\n if (targetPosChanged) {\n prevTargetPosition.current = targetPosition;\n }\n store.getState().updateNodeDimensions([{ id, nodeElement: nodeRef.current, forceUpdate: true }]);\n }\n }, [id, type, sourcePosition, targetPosition]);\n const dragging = useDrag({\n nodeRef,\n disabled: hidden || !isDraggable,\n noDragClassName,\n handleSelector: dragHandle,\n nodeId: id,\n isSelectable,\n selectNodesOnDrag,\n });\n if (hidden) {\n return null;\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])([\n 'react-flow__node',\n `react-flow__node-${type}`,\n {\n // this is overwritable by passing `nopan` as a class name\n [noPanClassName]: isDraggable,\n },\n className,\n {\n selected,\n selectable: isSelectable,\n parent: isParent,\n dragging,\n },\n ]), ref: nodeRef, style: {\n zIndex,\n transform: `translate(${xPosOrigin}px,${yPosOrigin}px)`,\n pointerEvents: hasPointerEvents ? 'all' : 'none',\n visibility: initialized ? 'visible' : 'hidden',\n ...style,\n }, \"data-id\": id, \"data-testid\": `rf__node-${id}`, onMouseEnter: onMouseEnterHandler, onMouseMove: onMouseMoveHandler, onMouseLeave: onMouseLeaveHandler, onContextMenu: onContextMenuHandler, onClick: onSelectNodeHandler, onDoubleClick: onDoubleClickHandler, onKeyDown: isFocusable ? onKeyDown : undefined, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : undefined, \"aria-describedby\": disableKeyboardA11y ? undefined : `${ARIA_NODE_DESC_KEY}-${rfId}`, \"aria-label\": ariaLabel },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Provider, { value: id },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(NodeComponent, { id: id, data: data, type: type, xPos: xPos, yPos: yPos, selected: selected, isConnectable: isConnectable, sourcePosition: sourcePosition, targetPosition: targetPosition, dragging: dragging, dragHandle: dragHandle, zIndex: zIndex }))));\n };\n NodeWrapper.displayName = 'NodeWrapper';\n return (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(NodeWrapper);\n};\n\n/**\n * The nodes selection rectangle gets displayed when a user\n * made a selection with on or several nodes\n */\nconst selector$7 = (s) => {\n const selectedNodes = s.getNodes().filter((n) => n.selected);\n return {\n ...getNodesBounds(selectedNodes, s.nodeOrigin),\n transformString: `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`,\n userSelectionActive: s.userSelectionActive,\n };\n};\nfunction NodesSelection({ onSelectionContextMenu, noPanClassName, disableKeyboardA11y }) {\n const store = useStoreApi();\n const { width, height, x: left, y: top, transformString, userSelectionActive } = useStore(selector$7, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const updatePositions = useUpdateNodePositions();\n const nodeRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (!disableKeyboardA11y) {\n nodeRef.current?.focus({\n preventScroll: true,\n });\n }\n }, [disableKeyboardA11y]);\n useDrag({\n nodeRef,\n });\n if (userSelectionActive || !width || !height) {\n return null;\n }\n const onContextMenu = onSelectionContextMenu\n ? (event) => {\n const selectedNodes = store\n .getState()\n .getNodes()\n .filter((n) => n.selected);\n onSelectionContextMenu(event, selectedNodes);\n }\n : undefined;\n const onKeyDown = (event) => {\n if (Object.prototype.hasOwnProperty.call(arrowKeyDiffs, event.key)) {\n updatePositions({\n x: arrowKeyDiffs[event.key].x,\n y: arrowKeyDiffs[event.key].y,\n isShiftPressed: event.shiftKey,\n });\n }\n };\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(['react-flow__nodesselection', 'react-flow__container', noPanClassName]), style: {\n transform: transformString,\n } },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { ref: nodeRef, className: \"react-flow__nodesselection-rect\", onContextMenu: onContextMenu, tabIndex: disableKeyboardA11y ? undefined : -1, onKeyDown: disableKeyboardA11y ? undefined : onKeyDown, style: {\n width,\n height,\n top,\n left,\n } })));\n}\nvar NodesSelection$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(NodesSelection);\n\nconst selector$6 = (s) => s.nodesSelectionActive;\nconst FlowRenderer = ({ children, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneContextMenu, onPaneScroll, deleteKeyCode, onMove, onMoveStart, onMoveEnd, selectionKeyCode, selectionOnDrag, selectionMode, onSelectionStart, onSelectionEnd, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, elementsSelectable, zoomOnScroll, zoomOnPinch, panOnScroll: _panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag: _panOnDrag, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, onSelectionContextMenu, noWheelClassName, noPanClassName, disableKeyboardA11y, }) => {\n const nodesSelectionActive = useStore(selector$6);\n const selectionKeyPressed = useKeyPress(selectionKeyCode);\n const panActivationKeyPressed = useKeyPress(panActivationKeyCode);\n const panOnDrag = panActivationKeyPressed || _panOnDrag;\n const panOnScroll = panActivationKeyPressed || _panOnScroll;\n const isSelecting = selectionKeyPressed || (selectionOnDrag && panOnDrag !== true);\n useGlobalKeyHandler({ deleteKeyCode, multiSelectionKeyCode });\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(ZoomPane, { onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, onPaneContextMenu: onPaneContextMenu, elementsSelectable: elementsSelectable, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, zoomOnDoubleClick: zoomOnDoubleClick, panOnDrag: !selectionKeyPressed && panOnDrag, defaultViewport: defaultViewport, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, zoomActivationKeyCode: zoomActivationKeyCode, preventScrolling: preventScrolling, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Pane, { onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneContextMenu: onPaneContextMenu, onPaneScroll: onPaneScroll, panOnDrag: panOnDrag, isSelecting: !!isSelecting, selectionMode: selectionMode },\n children,\n nodesSelectionActive && (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(NodesSelection$1, { onSelectionContextMenu: onSelectionContextMenu, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y })))));\n};\nFlowRenderer.displayName = 'FlowRenderer';\nvar FlowRenderer$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(FlowRenderer);\n\nfunction useVisibleNodes(onlyRenderVisible) {\n const nodes = useStore((0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((s) => onlyRenderVisible\n ? getNodesInside(s.nodeInternals, { x: 0, y: 0, width: s.width, height: s.height }, s.transform, true)\n : s.getNodes(), [onlyRenderVisible]));\n return nodes;\n}\n\nfunction createNodeTypes(nodeTypes) {\n const standardTypes = {\n input: wrapNode((nodeTypes.input || InputNode$1)),\n default: wrapNode((nodeTypes.default || DefaultNode$1)),\n output: wrapNode((nodeTypes.output || OutputNode$1)),\n group: wrapNode((nodeTypes.group || GroupNode)),\n };\n const wrappedTypes = {};\n const specialTypes = Object.keys(nodeTypes)\n .filter((k) => !['input', 'default', 'output', 'group'].includes(k))\n .reduce((res, key) => {\n res[key] = wrapNode((nodeTypes[key] || DefaultNode$1));\n return res;\n }, wrappedTypes);\n return {\n ...standardTypes,\n ...specialTypes,\n };\n}\nconst getPositionWithOrigin = ({ x, y, width, height, origin, }) => {\n if (!width || !height) {\n return { x, y };\n }\n if (origin[0] < 0 || origin[1] < 0 || origin[0] > 1 || origin[1] > 1) {\n return { x, y };\n }\n return {\n x: x - width * origin[0],\n y: y - height * origin[1],\n };\n};\n\nconst selector$5 = (s) => ({\n nodesDraggable: s.nodesDraggable,\n nodesConnectable: s.nodesConnectable,\n nodesFocusable: s.nodesFocusable,\n elementsSelectable: s.elementsSelectable,\n updateNodeDimensions: s.updateNodeDimensions,\n onError: s.onError,\n});\nconst NodeRenderer = (props) => {\n const { nodesDraggable, nodesConnectable, nodesFocusable, elementsSelectable, updateNodeDimensions, onError } = useStore(selector$5, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const nodes = useVisibleNodes(props.onlyRenderVisibleElements);\n const resizeObserverRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)();\n const resizeObserver = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {\n if (typeof ResizeObserver === 'undefined') {\n return null;\n }\n const observer = new ResizeObserver((entries) => {\n const updates = entries.map((entry) => ({\n id: entry.target.getAttribute('data-id'),\n nodeElement: entry.target,\n forceUpdate: true,\n }));\n updateNodeDimensions(updates);\n });\n resizeObserverRef.current = observer;\n return observer;\n }, []);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n return () => {\n resizeObserverRef?.current?.disconnect();\n };\n }, []);\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: \"react-flow__nodes\", style: containerStyle }, nodes.map((node) => {\n let nodeType = node.type || 'default';\n if (!props.nodeTypes[nodeType]) {\n onError?.('003', errorMessages['error003'](nodeType));\n nodeType = 'default';\n }\n const NodeComponent = (props.nodeTypes[nodeType] || props.nodeTypes.default);\n const isDraggable = !!(node.draggable || (nodesDraggable && typeof node.draggable === 'undefined'));\n const isSelectable = !!(node.selectable || (elementsSelectable && typeof node.selectable === 'undefined'));\n const isConnectable = !!(node.connectable || (nodesConnectable && typeof node.connectable === 'undefined'));\n const isFocusable = !!(node.focusable || (nodesFocusable && typeof node.focusable === 'undefined'));\n const clampedPosition = props.nodeExtent\n ? clampPosition(node.positionAbsolute, props.nodeExtent)\n : node.positionAbsolute;\n const posX = clampedPosition?.x ?? 0;\n const posY = clampedPosition?.y ?? 0;\n const posOrigin = getPositionWithOrigin({\n x: posX,\n y: posY,\n width: node.width ?? 0,\n height: node.height ?? 0,\n origin: props.nodeOrigin,\n });\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(NodeComponent, { key: node.id, id: node.id, className: node.className, style: node.style, type: nodeType, data: node.data, sourcePosition: node.sourcePosition || Position.Bottom, targetPosition: node.targetPosition || Position.Top, hidden: node.hidden, xPos: posX, yPos: posY, xPosOrigin: posOrigin.x, yPosOrigin: posOrigin.y, selectNodesOnDrag: props.selectNodesOnDrag, onClick: props.onNodeClick, onMouseEnter: props.onNodeMouseEnter, onMouseMove: props.onNodeMouseMove, onMouseLeave: props.onNodeMouseLeave, onContextMenu: props.onNodeContextMenu, onDoubleClick: props.onNodeDoubleClick, selected: !!node.selected, isDraggable: isDraggable, isSelectable: isSelectable, isConnectable: isConnectable, isFocusable: isFocusable, resizeObserver: resizeObserver, dragHandle: node.dragHandle, zIndex: node[internalsSymbol]?.z ?? 0, isParent: !!node[internalsSymbol]?.isParent, noDragClassName: props.noDragClassName, noPanClassName: props.noPanClassName, initialized: !!node.width && !!node.height, rfId: props.rfId, disableKeyboardA11y: props.disableKeyboardA11y, ariaLabel: node.ariaLabel, hasHandleBounds: !!node[internalsSymbol]?.handleBounds }));\n })));\n};\nNodeRenderer.displayName = 'NodeRenderer';\nvar NodeRenderer$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(NodeRenderer);\n\nconst shiftX = (x, shift, position) => {\n if (position === Position.Left)\n return x - shift;\n if (position === Position.Right)\n return x + shift;\n return x;\n};\nconst shiftY = (y, shift, position) => {\n if (position === Position.Top)\n return y - shift;\n if (position === Position.Bottom)\n return y + shift;\n return y;\n};\nconst EdgeUpdaterClassName = 'react-flow__edgeupdater';\nconst EdgeAnchor = ({ position, centerX, centerY, radius = 10, onMouseDown, onMouseEnter, onMouseOut, type, }) => (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"circle\", { onMouseDown: onMouseDown, onMouseEnter: onMouseEnter, onMouseOut: onMouseOut, className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])([EdgeUpdaterClassName, `${EdgeUpdaterClassName}-${type}`]), cx: shiftX(centerX, radius, position), cy: shiftY(centerY, radius, position), r: radius, stroke: \"transparent\", fill: \"transparent\" }));\n\nconst alwaysValidConnection = () => true;\nvar wrapEdge = (EdgeComponent) => {\n const EdgeWrapper = ({ id, className, type, data, onClick, onEdgeDoubleClick, selected, animated, label, labelStyle, labelShowBg, labelBgStyle, labelBgPadding, labelBgBorderRadius, style, source, target, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, elementsSelectable, hidden, sourceHandleId, targetHandleId, onContextMenu, onMouseEnter, onMouseMove, onMouseLeave, edgeUpdaterRadius, onEdgeUpdate, onEdgeUpdateStart, onEdgeUpdateEnd, markerEnd, markerStart, rfId, ariaLabel, isFocusable, isUpdatable, pathOptions, interactionWidth, }) => {\n const edgeRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n const [updateHover, setUpdateHover] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);\n const [updating, setUpdating] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false);\n const store = useStoreApi();\n const markerStartUrl = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => `url('#${getMarkerId(markerStart, rfId)}')`, [markerStart, rfId]);\n const markerEndUrl = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => `url('#${getMarkerId(markerEnd, rfId)}')`, [markerEnd, rfId]);\n if (hidden) {\n return null;\n }\n const onEdgeClick = (event) => {\n const { edges, addSelectedEdges, unselectNodesAndEdges, multiSelectionActive } = store.getState();\n const edge = edges.find((e) => e.id === id);\n if (!edge) {\n return;\n }\n if (elementsSelectable) {\n store.setState({ nodesSelectionActive: false });\n if (edge.selected && multiSelectionActive) {\n unselectNodesAndEdges({ nodes: [], edges: [edge] });\n edgeRef.current?.blur();\n }\n else {\n addSelectedEdges([id]);\n }\n }\n if (onClick) {\n onClick(event, edge);\n }\n };\n const onEdgeDoubleClickHandler = getMouseHandler$1(id, store.getState, onEdgeDoubleClick);\n const onEdgeContextMenu = getMouseHandler$1(id, store.getState, onContextMenu);\n const onEdgeMouseEnter = getMouseHandler$1(id, store.getState, onMouseEnter);\n const onEdgeMouseMove = getMouseHandler$1(id, store.getState, onMouseMove);\n const onEdgeMouseLeave = getMouseHandler$1(id, store.getState, onMouseLeave);\n const handleEdgeUpdater = (event, isSourceHandle) => {\n // avoid triggering edge updater if mouse btn is not left\n if (event.button !== 0) {\n return;\n }\n const { edges, isValidConnection: isValidConnectionStore } = store.getState();\n const nodeId = isSourceHandle ? target : source;\n const handleId = (isSourceHandle ? targetHandleId : sourceHandleId) || null;\n const handleType = isSourceHandle ? 'target' : 'source';\n const isValidConnection = isValidConnectionStore || alwaysValidConnection;\n const isTarget = isSourceHandle;\n const edge = edges.find((e) => e.id === id);\n setUpdating(true);\n onEdgeUpdateStart?.(event, edge, handleType);\n const _onEdgeUpdateEnd = (evt) => {\n setUpdating(false);\n onEdgeUpdateEnd?.(evt, edge, handleType);\n };\n const onConnectEdge = (connection) => onEdgeUpdate?.(edge, connection);\n handlePointerDown({\n event,\n handleId,\n nodeId,\n onConnect: onConnectEdge,\n isTarget,\n getState: store.getState,\n setState: store.setState,\n isValidConnection,\n edgeUpdaterType: handleType,\n onEdgeUpdateEnd: _onEdgeUpdateEnd,\n });\n };\n const onEdgeUpdaterSourceMouseDown = (event) => handleEdgeUpdater(event, true);\n const onEdgeUpdaterTargetMouseDown = (event) => handleEdgeUpdater(event, false);\n const onEdgeUpdaterMouseEnter = () => setUpdateHover(true);\n const onEdgeUpdaterMouseOut = () => setUpdateHover(false);\n const inactive = !elementsSelectable && !onClick;\n const onKeyDown = (event) => {\n if (elementSelectionKeys.includes(event.key) && elementsSelectable) {\n const { unselectNodesAndEdges, addSelectedEdges, edges } = store.getState();\n const unselect = event.key === 'Escape';\n if (unselect) {\n edgeRef.current?.blur();\n unselectNodesAndEdges({ edges: [edges.find((e) => e.id === id)] });\n }\n else {\n addSelectedEdges([id]);\n }\n }\n };\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"g\", { className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])([\n 'react-flow__edge',\n `react-flow__edge-${type}`,\n className,\n { selected, animated, inactive, updating: updateHover },\n ]), onClick: onEdgeClick, onDoubleClick: onEdgeDoubleClickHandler, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onKeyDown: isFocusable ? onKeyDown : undefined, tabIndex: isFocusable ? 0 : undefined, role: isFocusable ? 'button' : 'img', \"data-testid\": `rf__edge-${id}`, \"aria-label\": ariaLabel === null ? undefined : ariaLabel ? ariaLabel : `Edge from ${source} to ${target}`, \"aria-describedby\": isFocusable ? `${ARIA_EDGE_DESC_KEY}-${rfId}` : undefined, ref: edgeRef },\n !updating && (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(EdgeComponent, { id: id, source: source, target: target, selected: selected, animated: animated, label: label, labelStyle: labelStyle, labelShowBg: labelShowBg, labelBgStyle: labelBgStyle, labelBgPadding: labelBgPadding, labelBgBorderRadius: labelBgBorderRadius, data: data, style: style, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, sourceHandleId: sourceHandleId, targetHandleId: targetHandleId, markerStart: markerStartUrl, markerEnd: markerEndUrl, pathOptions: pathOptions, interactionWidth: interactionWidth })),\n isUpdatable && (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Fragment, null,\n (isUpdatable === 'source' || isUpdatable === true) && (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(EdgeAnchor, { position: sourcePosition, centerX: sourceX, centerY: sourceY, radius: edgeUpdaterRadius, onMouseDown: onEdgeUpdaterSourceMouseDown, onMouseEnter: onEdgeUpdaterMouseEnter, onMouseOut: onEdgeUpdaterMouseOut, type: \"source\" })),\n (isUpdatable === 'target' || isUpdatable === true) && (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(EdgeAnchor, { position: targetPosition, centerX: targetX, centerY: targetY, radius: edgeUpdaterRadius, onMouseDown: onEdgeUpdaterTargetMouseDown, onMouseEnter: onEdgeUpdaterMouseEnter, onMouseOut: onEdgeUpdaterMouseOut, type: \"target\" }))))));\n };\n EdgeWrapper.displayName = 'EdgeWrapper';\n return (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(EdgeWrapper);\n};\n\nfunction createEdgeTypes(edgeTypes) {\n const standardTypes = {\n default: wrapEdge((edgeTypes.default || BezierEdge)),\n straight: wrapEdge((edgeTypes.bezier || StraightEdge)),\n step: wrapEdge((edgeTypes.step || StepEdge)),\n smoothstep: wrapEdge((edgeTypes.step || SmoothStepEdge)),\n simplebezier: wrapEdge((edgeTypes.simplebezier || SimpleBezierEdge)),\n };\n const wrappedTypes = {};\n const specialTypes = Object.keys(edgeTypes)\n .filter((k) => !['default', 'bezier'].includes(k))\n .reduce((res, key) => {\n res[key] = wrapEdge((edgeTypes[key] || BezierEdge));\n return res;\n }, wrappedTypes);\n return {\n ...standardTypes,\n ...specialTypes,\n };\n}\nfunction getHandlePosition(position, nodeRect, handle = null) {\n const x = (handle?.x || 0) + nodeRect.x;\n const y = (handle?.y || 0) + nodeRect.y;\n const width = handle?.width || nodeRect.width;\n const height = handle?.height || nodeRect.height;\n switch (position) {\n case Position.Top:\n return {\n x: x + width / 2,\n y,\n };\n case Position.Right:\n return {\n x: x + width,\n y: y + height / 2,\n };\n case Position.Bottom:\n return {\n x: x + width / 2,\n y: y + height,\n };\n case Position.Left:\n return {\n x,\n y: y + height / 2,\n };\n }\n}\nfunction getHandle(bounds, handleId) {\n if (!bounds) {\n return null;\n }\n if (bounds.length === 1 || !handleId) {\n return bounds[0];\n }\n else if (handleId) {\n return bounds.find((d) => d.id === handleId) || null;\n }\n return null;\n}\nconst getEdgePositions = (sourceNodeRect, sourceHandle, sourcePosition, targetNodeRect, targetHandle, targetPosition) => {\n const sourceHandlePos = getHandlePosition(sourcePosition, sourceNodeRect, sourceHandle);\n const targetHandlePos = getHandlePosition(targetPosition, targetNodeRect, targetHandle);\n return {\n sourceX: sourceHandlePos.x,\n sourceY: sourceHandlePos.y,\n targetX: targetHandlePos.x,\n targetY: targetHandlePos.y,\n };\n};\nfunction isEdgeVisible({ sourcePos, targetPos, sourceWidth, sourceHeight, targetWidth, targetHeight, width, height, transform, }) {\n const edgeBox = {\n x: Math.min(sourcePos.x, targetPos.x),\n y: Math.min(sourcePos.y, targetPos.y),\n x2: Math.max(sourcePos.x + sourceWidth, targetPos.x + targetWidth),\n y2: Math.max(sourcePos.y + sourceHeight, targetPos.y + targetHeight),\n };\n if (edgeBox.x === edgeBox.x2) {\n edgeBox.x2 += 1;\n }\n if (edgeBox.y === edgeBox.y2) {\n edgeBox.y2 += 1;\n }\n const viewBox = rectToBox({\n x: (0 - transform[0]) / transform[2],\n y: (0 - transform[1]) / transform[2],\n width: width / transform[2],\n height: height / transform[2],\n });\n const xOverlap = Math.max(0, Math.min(viewBox.x2, edgeBox.x2) - Math.max(viewBox.x, edgeBox.x));\n const yOverlap = Math.max(0, Math.min(viewBox.y2, edgeBox.y2) - Math.max(viewBox.y, edgeBox.y));\n const overlappingArea = Math.ceil(xOverlap * yOverlap);\n return overlappingArea > 0;\n}\nfunction getNodeData(node) {\n const handleBounds = node?.[internalsSymbol]?.handleBounds || null;\n const isValid = handleBounds &&\n node?.width &&\n node?.height &&\n typeof node?.positionAbsolute?.x !== 'undefined' &&\n typeof node?.positionAbsolute?.y !== 'undefined';\n return [\n {\n x: node?.positionAbsolute?.x || 0,\n y: node?.positionAbsolute?.y || 0,\n width: node?.width || 0,\n height: node?.height || 0,\n },\n handleBounds,\n !!isValid,\n ];\n}\n\nconst defaultEdgeTree = [{ level: 0, isMaxLevel: true, edges: [] }];\nfunction groupEdgesByZLevel(edges, nodeInternals, elevateEdgesOnSelect = false) {\n let maxLevel = -1;\n const levelLookup = edges.reduce((tree, edge) => {\n const hasZIndex = isNumeric(edge.zIndex);\n let z = hasZIndex ? edge.zIndex : 0;\n if (elevateEdgesOnSelect) {\n const targetNode = nodeInternals.get(edge.target);\n const sourceNode = nodeInternals.get(edge.source);\n const edgeOrConnectedNodeSelected = edge.selected || targetNode?.selected || sourceNode?.selected;\n const selectedZIndex = Math.max(sourceNode?.[internalsSymbol]?.z || 0, targetNode?.[internalsSymbol]?.z || 0, 1000);\n z = (hasZIndex ? edge.zIndex : 0) + (edgeOrConnectedNodeSelected ? selectedZIndex : 0);\n }\n if (tree[z]) {\n tree[z].push(edge);\n }\n else {\n tree[z] = [edge];\n }\n maxLevel = z > maxLevel ? z : maxLevel;\n return tree;\n }, {});\n const edgeTree = Object.entries(levelLookup).map(([key, edges]) => {\n const level = +key;\n return {\n edges,\n level,\n isMaxLevel: level === maxLevel,\n };\n });\n if (edgeTree.length === 0) {\n return defaultEdgeTree;\n }\n return edgeTree;\n}\nfunction useVisibleEdges(onlyRenderVisible, nodeInternals, elevateEdgesOnSelect) {\n const edges = useStore((0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((s) => {\n if (!onlyRenderVisible) {\n return s.edges;\n }\n return s.edges.filter((e) => {\n const sourceNode = nodeInternals.get(e.source);\n const targetNode = nodeInternals.get(e.target);\n return (sourceNode?.width &&\n sourceNode?.height &&\n targetNode?.width &&\n targetNode?.height &&\n isEdgeVisible({\n sourcePos: sourceNode.positionAbsolute || { x: 0, y: 0 },\n targetPos: targetNode.positionAbsolute || { x: 0, y: 0 },\n sourceWidth: sourceNode.width,\n sourceHeight: sourceNode.height,\n targetWidth: targetNode.width,\n targetHeight: targetNode.height,\n width: s.width,\n height: s.height,\n transform: s.transform,\n }));\n });\n }, [onlyRenderVisible, nodeInternals]));\n return groupEdgesByZLevel(edges, nodeInternals, elevateEdgesOnSelect);\n}\n\nconst ArrowSymbol = ({ color = 'none', strokeWidth = 1 }) => {\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"polyline\", { style: {\n stroke: color,\n strokeWidth,\n }, strokeLinecap: \"round\", strokeLinejoin: \"round\", fill: \"none\", points: \"-5,-4 0,0 -5,4\" }));\n};\nconst ArrowClosedSymbol = ({ color = 'none', strokeWidth = 1 }) => {\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"polyline\", { style: {\n stroke: color,\n fill: color,\n strokeWidth,\n }, strokeLinecap: \"round\", strokeLinejoin: \"round\", points: \"-5,-4 0,0 -5,4 -5,-4\" }));\n};\nconst MarkerSymbols = {\n [MarkerType.Arrow]: ArrowSymbol,\n [MarkerType.ArrowClosed]: ArrowClosedSymbol,\n};\nfunction useMarkerSymbol(type) {\n const store = useStoreApi();\n const symbol = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {\n const symbolExists = Object.prototype.hasOwnProperty.call(MarkerSymbols, type);\n if (!symbolExists) {\n store.getState().onError?.('009', errorMessages['error009'](type));\n return null;\n }\n return MarkerSymbols[type];\n }, [type]);\n return symbol;\n}\n\nconst Marker = ({ id, type, color, width = 12.5, height = 12.5, markerUnits = 'strokeWidth', strokeWidth, orient = 'auto-start-reverse', }) => {\n const Symbol = useMarkerSymbol(type);\n if (!Symbol) {\n return null;\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"marker\", { className: \"react-flow__arrowhead\", id: id, markerWidth: `${width}`, markerHeight: `${height}`, viewBox: \"-10 -10 20 20\", markerUnits: markerUnits, orient: orient, refX: \"0\", refY: \"0\" },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Symbol, { color: color, strokeWidth: strokeWidth })));\n};\nconst markerSelector = ({ defaultColor, rfId }) => (s) => {\n const ids = [];\n return s.edges\n .reduce((markers, edge) => {\n [edge.markerStart, edge.markerEnd].forEach((marker) => {\n if (marker && typeof marker === 'object') {\n const markerId = getMarkerId(marker, rfId);\n if (!ids.includes(markerId)) {\n markers.push({ id: markerId, color: marker.color || defaultColor, ...marker });\n ids.push(markerId);\n }\n }\n });\n return markers;\n }, [])\n .sort((a, b) => a.id.localeCompare(b.id));\n};\n// when you have multiple flows on a page and you hide the first one, the other ones have no markers anymore\n// when they do have markers with the same ids. To prevent this the user can pass a unique id to the react flow wrapper\n// that we can then use for creating our unique marker ids\nconst MarkerDefinitions = ({ defaultColor, rfId }) => {\n const markers = useStore((0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)(markerSelector({ defaultColor, rfId }), [defaultColor, rfId]), \n // the id includes all marker options, so we just need to look at that part of the marker\n (a, b) => !(a.length !== b.length || a.some((m, i) => m.id !== b[i].id)));\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"defs\", null, markers.map((marker) => (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Marker, { id: marker.id, key: marker.id, type: marker.type, color: marker.color, width: marker.width, height: marker.height, markerUnits: marker.markerUnits, strokeWidth: marker.strokeWidth, orient: marker.orient })))));\n};\nMarkerDefinitions.displayName = 'MarkerDefinitions';\nvar MarkerDefinitions$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(MarkerDefinitions);\n\nconst selector$4 = (s) => ({\n nodesConnectable: s.nodesConnectable,\n edgesFocusable: s.edgesFocusable,\n edgesUpdatable: s.edgesUpdatable,\n elementsSelectable: s.elementsSelectable,\n width: s.width,\n height: s.height,\n connectionMode: s.connectionMode,\n nodeInternals: s.nodeInternals,\n onError: s.onError,\n});\nconst EdgeRenderer = ({ defaultMarkerColor, onlyRenderVisibleElements, elevateEdgesOnSelect, rfId, edgeTypes, noPanClassName, onEdgeUpdate, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeClick, edgeUpdaterRadius, onEdgeDoubleClick, onEdgeUpdateStart, onEdgeUpdateEnd, children, }) => {\n const { edgesFocusable, edgesUpdatable, elementsSelectable, width, height, connectionMode, nodeInternals, onError } = useStore(selector$4, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const edgeTree = useVisibleEdges(onlyRenderVisibleElements, nodeInternals, elevateEdgesOnSelect);\n if (!width) {\n return null;\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Fragment, null,\n edgeTree.map(({ level, edges, isMaxLevel }) => (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"svg\", { key: level, style: { zIndex: level }, width: width, height: height, className: \"react-flow__edges react-flow__container\" },\n isMaxLevel && react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(MarkerDefinitions$1, { defaultColor: defaultMarkerColor, rfId: rfId }),\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"g\", null, edges.map((edge) => {\n const [sourceNodeRect, sourceHandleBounds, sourceIsValid] = getNodeData(nodeInternals.get(edge.source));\n const [targetNodeRect, targetHandleBounds, targetIsValid] = getNodeData(nodeInternals.get(edge.target));\n if (!sourceIsValid || !targetIsValid) {\n return null;\n }\n let edgeType = edge.type || 'default';\n if (!edgeTypes[edgeType]) {\n onError?.('011', errorMessages['error011'](edgeType));\n edgeType = 'default';\n }\n const EdgeComponent = edgeTypes[edgeType] || edgeTypes.default;\n // when connection type is loose we can define all handles as sources and connect source -> source\n const targetNodeHandles = connectionMode === ConnectionMode.Strict\n ? targetHandleBounds.target\n : (targetHandleBounds.target ?? []).concat(targetHandleBounds.source ?? []);\n const sourceHandle = getHandle(sourceHandleBounds.source, edge.sourceHandle);\n const targetHandle = getHandle(targetNodeHandles, edge.targetHandle);\n const sourcePosition = sourceHandle?.position || Position.Bottom;\n const targetPosition = targetHandle?.position || Position.Top;\n const isFocusable = !!(edge.focusable || (edgesFocusable && typeof edge.focusable === 'undefined'));\n const isUpdatable = typeof onEdgeUpdate !== 'undefined' &&\n (edge.updatable || (edgesUpdatable && typeof edge.updatable === 'undefined'));\n if (!sourceHandle || !targetHandle) {\n onError?.('008', errorMessages['error008'](sourceHandle, edge));\n return null;\n }\n const { sourceX, sourceY, targetX, targetY } = getEdgePositions(sourceNodeRect, sourceHandle, sourcePosition, targetNodeRect, targetHandle, targetPosition);\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(EdgeComponent, { key: edge.id, id: edge.id, className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])([edge.className, noPanClassName]), type: edgeType, data: edge.data, selected: !!edge.selected, animated: !!edge.animated, hidden: !!edge.hidden, label: edge.label, labelStyle: edge.labelStyle, labelShowBg: edge.labelShowBg, labelBgStyle: edge.labelBgStyle, labelBgPadding: edge.labelBgPadding, labelBgBorderRadius: edge.labelBgBorderRadius, style: edge.style, source: edge.source, target: edge.target, sourceHandleId: edge.sourceHandle, targetHandleId: edge.targetHandle, markerEnd: edge.markerEnd, markerStart: edge.markerStart, sourceX: sourceX, sourceY: sourceY, targetX: targetX, targetY: targetY, sourcePosition: sourcePosition, targetPosition: targetPosition, elementsSelectable: elementsSelectable, onEdgeUpdate: onEdgeUpdate, onContextMenu: onEdgeContextMenu, onMouseEnter: onEdgeMouseEnter, onMouseMove: onEdgeMouseMove, onMouseLeave: onEdgeMouseLeave, onClick: onEdgeClick, edgeUpdaterRadius: edgeUpdaterRadius, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, rfId: rfId, ariaLabel: edge.ariaLabel, isFocusable: isFocusable, isUpdatable: isUpdatable, pathOptions: 'pathOptions' in edge ? edge.pathOptions : undefined, interactionWidth: edge.interactionWidth }));\n }))))),\n children));\n};\nEdgeRenderer.displayName = 'EdgeRenderer';\nvar EdgeRenderer$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(EdgeRenderer);\n\nconst selector$3 = (s) => `translate(${s.transform[0]}px,${s.transform[1]}px) scale(${s.transform[2]})`;\nfunction Viewport({ children }) {\n const transform = useStore(selector$3);\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: \"react-flow__viewport react-flow__container\", style: { transform } }, children));\n}\n\nfunction useOnInitHandler(onInit) {\n const rfInstance = useReactFlow();\n const isInitialized = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(false);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n if (!isInitialized.current && rfInstance.viewportInitialized && onInit) {\n setTimeout(() => onInit(rfInstance), 1);\n isInitialized.current = true;\n }\n }, [onInit, rfInstance.viewportInitialized]);\n}\n\nconst oppositePosition = {\n [Position.Left]: Position.Right,\n [Position.Right]: Position.Left,\n [Position.Top]: Position.Bottom,\n [Position.Bottom]: Position.Top,\n};\nconst ConnectionLine = ({ nodeId, handleType, style, type = ConnectionLineType.Bezier, CustomComponent, connectionStatus, }) => {\n const { fromNode, handleId, toX, toY, connectionMode } = useStore((0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((s) => ({\n fromNode: s.nodeInternals.get(nodeId),\n handleId: s.connectionHandleId,\n toX: (s.connectionPosition.x - s.transform[0]) / s.transform[2],\n toY: (s.connectionPosition.y - s.transform[1]) / s.transform[2],\n connectionMode: s.connectionMode,\n }), [nodeId]), zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const fromHandleBounds = fromNode?.[internalsSymbol]?.handleBounds;\n let handleBounds = fromHandleBounds?.[handleType];\n if (connectionMode === ConnectionMode.Loose) {\n handleBounds = handleBounds ? handleBounds : fromHandleBounds?.[handleType === 'source' ? 'target' : 'source'];\n }\n if (!fromNode || !handleBounds) {\n return null;\n }\n const fromHandle = handleId ? handleBounds.find((d) => d.id === handleId) : handleBounds[0];\n const fromHandleX = fromHandle ? fromHandle.x + fromHandle.width / 2 : (fromNode.width ?? 0) / 2;\n const fromHandleY = fromHandle ? fromHandle.y + fromHandle.height / 2 : fromNode.height ?? 0;\n const fromX = (fromNode.positionAbsolute?.x ?? 0) + fromHandleX;\n const fromY = (fromNode.positionAbsolute?.y ?? 0) + fromHandleY;\n const fromPosition = fromHandle?.position;\n const toPosition = fromPosition ? oppositePosition[fromPosition] : null;\n if (!fromPosition || !toPosition) {\n return null;\n }\n if (CustomComponent) {\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(CustomComponent, { connectionLineType: type, connectionLineStyle: style, fromNode: fromNode, fromHandle: fromHandle, fromX: fromX, fromY: fromY, toX: toX, toY: toY, fromPosition: fromPosition, toPosition: toPosition, connectionStatus: connectionStatus }));\n }\n let dAttr = '';\n const pathParams = {\n sourceX: fromX,\n sourceY: fromY,\n sourcePosition: fromPosition,\n targetX: toX,\n targetY: toY,\n targetPosition: toPosition,\n };\n if (type === ConnectionLineType.Bezier) {\n // we assume the destination position is opposite to the source position\n [dAttr] = getBezierPath(pathParams);\n }\n else if (type === ConnectionLineType.Step) {\n [dAttr] = getSmoothStepPath({\n ...pathParams,\n borderRadius: 0,\n });\n }\n else if (type === ConnectionLineType.SmoothStep) {\n [dAttr] = getSmoothStepPath(pathParams);\n }\n else if (type === ConnectionLineType.SimpleBezier) {\n [dAttr] = getSimpleBezierPath(pathParams);\n }\n else {\n dAttr = `M${fromX},${fromY} ${toX},${toY}`;\n }\n return react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"path\", { d: dAttr, fill: \"none\", className: \"react-flow__connection-path\", style: style });\n};\nConnectionLine.displayName = 'ConnectionLine';\nconst selector$2 = (s) => ({\n nodeId: s.connectionNodeId,\n handleType: s.connectionHandleType,\n nodesConnectable: s.nodesConnectable,\n connectionStatus: s.connectionStatus,\n width: s.width,\n height: s.height,\n});\nfunction ConnectionLineWrapper({ containerStyle, style, type, component }) {\n const { nodeId, handleType, nodesConnectable, width, height, connectionStatus } = useStore(selector$2, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n const isValid = !!(nodeId && handleType && width && nodesConnectable);\n if (!isValid) {\n return null;\n }\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"svg\", { style: containerStyle, width: width, height: height, className: \"react-flow__edges react-flow__connectionline react-flow__container\" },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"g\", { className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(['react-flow__connection', connectionStatus]) },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(ConnectionLine, { nodeId: nodeId, handleType: handleType, style: style, type: type, CustomComponent: component, connectionStatus: connectionStatus }))));\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction useNodeOrEdgeTypes(nodeOrEdgeTypes, createTypes) {\n const typesKeysRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n const store = useStoreApi();\n const typesParsed = (0,react__WEBPACK_IMPORTED_MODULE_0__.useMemo)(() => {\n if (true) {\n const typeKeys = Object.keys(nodeOrEdgeTypes);\n if ((0,zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow)(typesKeysRef.current, typeKeys)) {\n store.getState().onError?.('002', errorMessages['error002']());\n }\n typesKeysRef.current = typeKeys;\n }\n return createTypes(nodeOrEdgeTypes);\n }, [nodeOrEdgeTypes]);\n return typesParsed;\n}\n\nconst GraphView = ({ nodeTypes, edgeTypes, onMove, onMoveStart, onMoveEnd, onInit, onNodeClick, onEdgeClick, onNodeDoubleClick, onEdgeDoubleClick, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onSelectionContextMenu, onSelectionStart, onSelectionEnd, connectionLineType, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, selectionKeyCode, selectionOnDrag, selectionMode, multiSelectionKeyCode, panActivationKeyCode, zoomActivationKeyCode, deleteKeyCode, onlyRenderVisibleElements, elementsSelectable, selectNodesOnDrag, defaultViewport, translateExtent, minZoom, maxZoom, preventScrolling, defaultMarkerColor, zoomOnScroll, zoomOnPinch, panOnScroll, panOnScrollSpeed, panOnScrollMode, zoomOnDoubleClick, panOnDrag, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, onEdgeUpdate, onEdgeContextMenu, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, edgeUpdaterRadius, onEdgeUpdateStart, onEdgeUpdateEnd, noDragClassName, noWheelClassName, noPanClassName, elevateEdgesOnSelect, disableKeyboardA11y, nodeOrigin, nodeExtent, rfId, }) => {\n const nodeTypesWrapped = useNodeOrEdgeTypes(nodeTypes, createNodeTypes);\n const edgeTypesWrapped = useNodeOrEdgeTypes(edgeTypes, createEdgeTypes);\n useOnInitHandler(onInit);\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(FlowRenderer$1, { onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneContextMenu: onPaneContextMenu, onPaneScroll: onPaneScroll, deleteKeyCode: deleteKeyCode, selectionKeyCode: selectionKeyCode, selectionOnDrag: selectionOnDrag, selectionMode: selectionMode, onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, multiSelectionKeyCode: multiSelectionKeyCode, panActivationKeyCode: panActivationKeyCode, zoomActivationKeyCode: zoomActivationKeyCode, elementsSelectable: elementsSelectable, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, zoomOnDoubleClick: zoomOnDoubleClick, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, panOnDrag: panOnDrag, defaultViewport: defaultViewport, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, onSelectionContextMenu: onSelectionContextMenu, preventScrolling: preventScrolling, noDragClassName: noDragClassName, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, disableKeyboardA11y: disableKeyboardA11y },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Viewport, null,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(EdgeRenderer$1, { edgeTypes: edgeTypesWrapped, onEdgeClick: onEdgeClick, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeUpdate: onEdgeUpdate, onlyRenderVisibleElements: onlyRenderVisibleElements, onEdgeContextMenu: onEdgeContextMenu, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, edgeUpdaterRadius: edgeUpdaterRadius, defaultMarkerColor: defaultMarkerColor, noPanClassName: noPanClassName, elevateEdgesOnSelect: !!elevateEdgesOnSelect, disableKeyboardA11y: disableKeyboardA11y, rfId: rfId },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(ConnectionLineWrapper, { style: connectionLineStyle, type: connectionLineType, component: connectionLineComponent, containerStyle: connectionLineContainerStyle })),\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { className: \"react-flow__edgelabel-renderer\" }),\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(NodeRenderer$1, { nodeTypes: nodeTypesWrapped, onNodeClick: onNodeClick, onNodeDoubleClick: onNodeDoubleClick, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onNodeContextMenu: onNodeContextMenu, selectNodesOnDrag: selectNodesOnDrag, onlyRenderVisibleElements: onlyRenderVisibleElements, noPanClassName: noPanClassName, noDragClassName: noDragClassName, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent, rfId: rfId }))));\n};\nGraphView.displayName = 'GraphView';\nvar GraphView$1 = (0,react__WEBPACK_IMPORTED_MODULE_0__.memo)(GraphView);\n\nconst infiniteExtent = [\n [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY],\n [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY],\n];\nconst initialState = {\n rfId: '1',\n width: 0,\n height: 0,\n transform: [0, 0, 1],\n nodeInternals: new Map(),\n edges: [],\n onNodesChange: null,\n onEdgesChange: null,\n hasDefaultNodes: false,\n hasDefaultEdges: false,\n d3Zoom: null,\n d3Selection: null,\n d3ZoomHandler: undefined,\n minZoom: 0.5,\n maxZoom: 2,\n translateExtent: infiniteExtent,\n nodeExtent: infiniteExtent,\n nodesSelectionActive: false,\n userSelectionActive: false,\n userSelectionRect: null,\n connectionNodeId: null,\n connectionHandleId: null,\n connectionHandleType: 'source',\n connectionPosition: { x: 0, y: 0 },\n connectionStatus: null,\n connectionMode: ConnectionMode.Strict,\n domNode: null,\n paneDragging: false,\n noPanClassName: 'nopan',\n nodeOrigin: [0, 0],\n nodeDragThreshold: 0,\n snapGrid: [15, 15],\n snapToGrid: false,\n nodesDraggable: true,\n nodesConnectable: true,\n nodesFocusable: true,\n edgesFocusable: true,\n edgesUpdatable: true,\n elementsSelectable: true,\n elevateNodesOnSelect: true,\n fitViewOnInit: false,\n fitViewOnInitDone: false,\n fitViewOnInitOptions: undefined,\n onSelectionChange: [],\n multiSelectionActive: false,\n connectionStartHandle: null,\n connectionEndHandle: null,\n connectionClickStartHandle: null,\n connectOnClick: true,\n ariaLiveMessage: '',\n autoPanOnConnect: true,\n autoPanOnNodeDrag: true,\n connectionRadius: 20,\n onError: devWarn,\n isValidConnection: undefined,\n};\n\nconst createRFStore = () => (0,zustand_traditional__WEBPACK_IMPORTED_MODULE_4__.createWithEqualityFn)((set, get) => ({\n ...initialState,\n setNodes: (nodes) => {\n const { nodeInternals, nodeOrigin, elevateNodesOnSelect } = get();\n set({ nodeInternals: createNodeInternals(nodes, nodeInternals, nodeOrigin, elevateNodesOnSelect) });\n },\n getNodes: () => {\n return Array.from(get().nodeInternals.values());\n },\n setEdges: (edges) => {\n const { defaultEdgeOptions = {} } = get();\n set({ edges: edges.map((e) => ({ ...defaultEdgeOptions, ...e })) });\n },\n setDefaultNodesAndEdges: (nodes, edges) => {\n const hasDefaultNodes = typeof nodes !== 'undefined';\n const hasDefaultEdges = typeof edges !== 'undefined';\n const nodeInternals = hasDefaultNodes\n ? createNodeInternals(nodes, new Map(), get().nodeOrigin, get().elevateNodesOnSelect)\n : new Map();\n const nextEdges = hasDefaultEdges ? edges : [];\n set({ nodeInternals, edges: nextEdges, hasDefaultNodes, hasDefaultEdges });\n },\n updateNodeDimensions: (updates) => {\n const { onNodesChange, nodeInternals, fitViewOnInit, fitViewOnInitDone, fitViewOnInitOptions, domNode, nodeOrigin, } = get();\n const viewportNode = domNode?.querySelector('.react-flow__viewport');\n if (!viewportNode) {\n return;\n }\n const style = window.getComputedStyle(viewportNode);\n const { m22: zoom } = new window.DOMMatrixReadOnly(style.transform);\n const changes = updates.reduce((res, update) => {\n const node = nodeInternals.get(update.id);\n if (node) {\n const dimensions = getDimensions(update.nodeElement);\n const doUpdate = !!(dimensions.width &&\n dimensions.height &&\n (node.width !== dimensions.width || node.height !== dimensions.height || update.forceUpdate));\n if (doUpdate) {\n nodeInternals.set(node.id, {\n ...node,\n [internalsSymbol]: {\n ...node[internalsSymbol],\n handleBounds: {\n source: getHandleBounds('.source', update.nodeElement, zoom, nodeOrigin),\n target: getHandleBounds('.target', update.nodeElement, zoom, nodeOrigin),\n },\n },\n ...dimensions,\n });\n res.push({\n id: node.id,\n type: 'dimensions',\n dimensions,\n });\n }\n }\n return res;\n }, []);\n updateAbsoluteNodePositions(nodeInternals, nodeOrigin);\n const nextFitViewOnInitDone = fitViewOnInitDone ||\n (fitViewOnInit && !fitViewOnInitDone && fitView(get, { initial: true, ...fitViewOnInitOptions }));\n set({ nodeInternals: new Map(nodeInternals), fitViewOnInitDone: nextFitViewOnInitDone });\n if (changes?.length > 0) {\n onNodesChange?.(changes);\n }\n },\n updateNodePositions: (nodeDragItems, positionChanged = true, dragging = false) => {\n const { triggerNodeChanges } = get();\n const changes = nodeDragItems.map((node) => {\n const change = {\n id: node.id,\n type: 'position',\n dragging,\n };\n if (positionChanged) {\n change.positionAbsolute = node.positionAbsolute;\n change.position = node.position;\n }\n return change;\n });\n triggerNodeChanges(changes);\n },\n triggerNodeChanges: (changes) => {\n const { onNodesChange, nodeInternals, hasDefaultNodes, nodeOrigin, getNodes, elevateNodesOnSelect } = get();\n if (changes?.length) {\n if (hasDefaultNodes) {\n const nodes = applyNodeChanges(changes, getNodes());\n const nextNodeInternals = createNodeInternals(nodes, nodeInternals, nodeOrigin, elevateNodesOnSelect);\n set({ nodeInternals: nextNodeInternals });\n }\n onNodesChange?.(changes);\n }\n },\n addSelectedNodes: (selectedNodeIds) => {\n const { multiSelectionActive, edges, getNodes } = get();\n let changedNodes;\n let changedEdges = null;\n if (multiSelectionActive) {\n changedNodes = selectedNodeIds.map((nodeId) => createSelectionChange(nodeId, true));\n }\n else {\n changedNodes = getSelectionChanges(getNodes(), selectedNodeIds);\n changedEdges = getSelectionChanges(edges, []);\n }\n updateNodesAndEdgesSelections({\n changedNodes,\n changedEdges,\n get,\n set,\n });\n },\n addSelectedEdges: (selectedEdgeIds) => {\n const { multiSelectionActive, edges, getNodes } = get();\n let changedEdges;\n let changedNodes = null;\n if (multiSelectionActive) {\n changedEdges = selectedEdgeIds.map((edgeId) => createSelectionChange(edgeId, true));\n }\n else {\n changedEdges = getSelectionChanges(edges, selectedEdgeIds);\n changedNodes = getSelectionChanges(getNodes(), []);\n }\n updateNodesAndEdgesSelections({\n changedNodes,\n changedEdges,\n get,\n set,\n });\n },\n unselectNodesAndEdges: ({ nodes, edges } = {}) => {\n const { edges: storeEdges, getNodes } = get();\n const nodesToUnselect = nodes ? nodes : getNodes();\n const edgesToUnselect = edges ? edges : storeEdges;\n const changedNodes = nodesToUnselect.map((n) => {\n n.selected = false;\n return createSelectionChange(n.id, false);\n });\n const changedEdges = edgesToUnselect.map((edge) => createSelectionChange(edge.id, false));\n updateNodesAndEdgesSelections({\n changedNodes,\n changedEdges,\n get,\n set,\n });\n },\n setMinZoom: (minZoom) => {\n const { d3Zoom, maxZoom } = get();\n d3Zoom?.scaleExtent([minZoom, maxZoom]);\n set({ minZoom });\n },\n setMaxZoom: (maxZoom) => {\n const { d3Zoom, minZoom } = get();\n d3Zoom?.scaleExtent([minZoom, maxZoom]);\n set({ maxZoom });\n },\n setTranslateExtent: (translateExtent) => {\n get().d3Zoom?.translateExtent(translateExtent);\n set({ translateExtent });\n },\n resetSelectedElements: () => {\n const { edges, getNodes } = get();\n const nodes = getNodes();\n const nodesToUnselect = nodes\n .filter((e) => e.selected)\n .map((n) => createSelectionChange(n.id, false));\n const edgesToUnselect = edges\n .filter((e) => e.selected)\n .map((e) => createSelectionChange(e.id, false));\n updateNodesAndEdgesSelections({\n changedNodes: nodesToUnselect,\n changedEdges: edgesToUnselect,\n get,\n set,\n });\n },\n setNodeExtent: (nodeExtent) => {\n const { nodeInternals } = get();\n nodeInternals.forEach((node) => {\n node.positionAbsolute = clampPosition(node.position, nodeExtent);\n });\n set({\n nodeExtent,\n nodeInternals: new Map(nodeInternals),\n });\n },\n panBy: (delta) => {\n const { transform, width, height, d3Zoom, d3Selection, translateExtent } = get();\n if (!d3Zoom || !d3Selection || (!delta.x && !delta.y)) {\n return false;\n }\n const nextTransform = d3_zoom__WEBPACK_IMPORTED_MODULE_2__.zoomIdentity\n .translate(transform[0] + delta.x, transform[1] + delta.y)\n .scale(transform[2]);\n const extent = [\n [0, 0],\n [width, height],\n ];\n const constrainedTransform = d3Zoom?.constrain()(nextTransform, extent, translateExtent);\n d3Zoom.transform(d3Selection, constrainedTransform);\n const transformChanged = transform[0] !== constrainedTransform.x ||\n transform[1] !== constrainedTransform.y ||\n transform[2] !== constrainedTransform.k;\n return transformChanged;\n },\n cancelConnection: () => set({\n connectionNodeId: initialState.connectionNodeId,\n connectionHandleId: initialState.connectionHandleId,\n connectionHandleType: initialState.connectionHandleType,\n connectionStatus: initialState.connectionStatus,\n connectionStartHandle: initialState.connectionStartHandle,\n connectionEndHandle: initialState.connectionEndHandle,\n }),\n reset: () => set({ ...initialState }),\n}), Object.is);\n\nconst ReactFlowProvider = ({ children }) => {\n const storeRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null);\n if (!storeRef.current) {\n storeRef.current = createRFStore();\n }\n return react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Provider$1, { value: storeRef.current }, children);\n};\nReactFlowProvider.displayName = 'ReactFlowProvider';\n\nconst Wrapper = ({ children }) => {\n const isWrapped = (0,react__WEBPACK_IMPORTED_MODULE_0__.useContext)(StoreContext);\n if (isWrapped) {\n // we need to wrap it with a fragment because it's not allowed for children to be a ReactNode\n // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18051\n return react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].Fragment, null, children);\n }\n return react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(ReactFlowProvider, null, children);\n};\nWrapper.displayName = 'ReactFlowWrapper';\n\nconst defaultNodeTypes = {\n input: InputNode$1,\n default: DefaultNode$1,\n output: OutputNode$1,\n group: GroupNode,\n};\nconst defaultEdgeTypes = {\n default: BezierEdge,\n straight: StraightEdge,\n step: StepEdge,\n smoothstep: SmoothStepEdge,\n simplebezier: SimpleBezierEdge,\n};\nconst initNodeOrigin = [0, 0];\nconst initSnapGrid = [15, 15];\nconst initDefaultViewport = { x: 0, y: 0, zoom: 1 };\nconst wrapperStyle = {\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n position: 'relative',\n zIndex: 0,\n};\nconst ReactFlow = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(({ nodes, edges, defaultNodes, defaultEdges, className, nodeTypes = defaultNodeTypes, edgeTypes = defaultEdgeTypes, onNodeClick, onEdgeClick, onInit, onMove, onMoveStart, onMoveEnd, onConnect, onConnectStart, onConnectEnd, onClickConnectStart, onClickConnectEnd, onNodeMouseEnter, onNodeMouseMove, onNodeMouseLeave, onNodeContextMenu, onNodeDoubleClick, onNodeDragStart, onNodeDrag, onNodeDragStop, onNodesDelete, onEdgesDelete, onSelectionChange, onSelectionDragStart, onSelectionDrag, onSelectionDragStop, onSelectionContextMenu, onSelectionStart, onSelectionEnd, connectionMode = ConnectionMode.Strict, connectionLineType = ConnectionLineType.Bezier, connectionLineStyle, connectionLineComponent, connectionLineContainerStyle, deleteKeyCode = 'Backspace', selectionKeyCode = 'Shift', selectionOnDrag = false, selectionMode = SelectionMode.Full, panActivationKeyCode = 'Space', multiSelectionKeyCode = isMacOs() ? 'Meta' : 'Control', zoomActivationKeyCode = isMacOs() ? 'Meta' : 'Control', snapToGrid = false, snapGrid = initSnapGrid, onlyRenderVisibleElements = false, selectNodesOnDrag = true, nodesDraggable, nodesConnectable, nodesFocusable, nodeOrigin = initNodeOrigin, edgesFocusable, edgesUpdatable, elementsSelectable, defaultViewport = initDefaultViewport, minZoom = 0.5, maxZoom = 2, translateExtent = infiniteExtent, preventScrolling = true, nodeExtent, defaultMarkerColor = '#b1b1b7', zoomOnScroll = true, zoomOnPinch = true, panOnScroll = false, panOnScrollSpeed = 0.5, panOnScrollMode = PanOnScrollMode.Free, zoomOnDoubleClick = true, panOnDrag = true, onPaneClick, onPaneMouseEnter, onPaneMouseMove, onPaneMouseLeave, onPaneScroll, onPaneContextMenu, children, onEdgeUpdate, onEdgeContextMenu, onEdgeDoubleClick, onEdgeMouseEnter, onEdgeMouseMove, onEdgeMouseLeave, onEdgeUpdateStart, onEdgeUpdateEnd, edgeUpdaterRadius = 10, onNodesChange, onEdgesChange, noDragClassName = 'nodrag', noWheelClassName = 'nowheel', noPanClassName = 'nopan', fitView = false, fitViewOptions, connectOnClick = true, attributionPosition, proOptions, defaultEdgeOptions, elevateNodesOnSelect = true, elevateEdgesOnSelect = false, disableKeyboardA11y = false, autoPanOnConnect = true, autoPanOnNodeDrag = true, connectionRadius = 20, isValidConnection, onError, style, id, nodeDragThreshold, ...rest }, ref) => {\n const rfId = id || '1';\n return (react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(\"div\", { ...rest, style: { ...style, ...wrapperStyle }, ref: ref, className: (0,classcat__WEBPACK_IMPORTED_MODULE_1__[\"default\"])(['react-flow', className]), \"data-testid\": \"rf__wrapper\", id: id },\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Wrapper, null,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(GraphView$1, { onInit: onInit, onMove: onMove, onMoveStart: onMoveStart, onMoveEnd: onMoveEnd, onNodeClick: onNodeClick, onEdgeClick: onEdgeClick, onNodeMouseEnter: onNodeMouseEnter, onNodeMouseMove: onNodeMouseMove, onNodeMouseLeave: onNodeMouseLeave, onNodeContextMenu: onNodeContextMenu, onNodeDoubleClick: onNodeDoubleClick, nodeTypes: nodeTypes, edgeTypes: edgeTypes, connectionLineType: connectionLineType, connectionLineStyle: connectionLineStyle, connectionLineComponent: connectionLineComponent, connectionLineContainerStyle: connectionLineContainerStyle, selectionKeyCode: selectionKeyCode, selectionOnDrag: selectionOnDrag, selectionMode: selectionMode, deleteKeyCode: deleteKeyCode, multiSelectionKeyCode: multiSelectionKeyCode, panActivationKeyCode: panActivationKeyCode, zoomActivationKeyCode: zoomActivationKeyCode, onlyRenderVisibleElements: onlyRenderVisibleElements, selectNodesOnDrag: selectNodesOnDrag, defaultViewport: defaultViewport, translateExtent: translateExtent, minZoom: minZoom, maxZoom: maxZoom, preventScrolling: preventScrolling, zoomOnScroll: zoomOnScroll, zoomOnPinch: zoomOnPinch, zoomOnDoubleClick: zoomOnDoubleClick, panOnScroll: panOnScroll, panOnScrollSpeed: panOnScrollSpeed, panOnScrollMode: panOnScrollMode, panOnDrag: panOnDrag, onPaneClick: onPaneClick, onPaneMouseEnter: onPaneMouseEnter, onPaneMouseMove: onPaneMouseMove, onPaneMouseLeave: onPaneMouseLeave, onPaneScroll: onPaneScroll, onPaneContextMenu: onPaneContextMenu, onSelectionContextMenu: onSelectionContextMenu, onSelectionStart: onSelectionStart, onSelectionEnd: onSelectionEnd, onEdgeUpdate: onEdgeUpdate, onEdgeContextMenu: onEdgeContextMenu, onEdgeDoubleClick: onEdgeDoubleClick, onEdgeMouseEnter: onEdgeMouseEnter, onEdgeMouseMove: onEdgeMouseMove, onEdgeMouseLeave: onEdgeMouseLeave, onEdgeUpdateStart: onEdgeUpdateStart, onEdgeUpdateEnd: onEdgeUpdateEnd, edgeUpdaterRadius: edgeUpdaterRadius, defaultMarkerColor: defaultMarkerColor, noDragClassName: noDragClassName, noWheelClassName: noWheelClassName, noPanClassName: noPanClassName, elevateEdgesOnSelect: elevateEdgesOnSelect, rfId: rfId, disableKeyboardA11y: disableKeyboardA11y, nodeOrigin: nodeOrigin, nodeExtent: nodeExtent }),\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(StoreUpdater, { nodes: nodes, edges: edges, defaultNodes: defaultNodes, defaultEdges: defaultEdges, onConnect: onConnect, onConnectStart: onConnectStart, onConnectEnd: onConnectEnd, onClickConnectStart: onClickConnectStart, onClickConnectEnd: onClickConnectEnd, nodesDraggable: nodesDraggable, nodesConnectable: nodesConnectable, nodesFocusable: nodesFocusable, edgesFocusable: edgesFocusable, edgesUpdatable: edgesUpdatable, elementsSelectable: elementsSelectable, elevateNodesOnSelect: elevateNodesOnSelect, minZoom: minZoom, maxZoom: maxZoom, nodeExtent: nodeExtent, onNodesChange: onNodesChange, onEdgesChange: onEdgesChange, snapToGrid: snapToGrid, snapGrid: snapGrid, connectionMode: connectionMode, translateExtent: translateExtent, connectOnClick: connectOnClick, defaultEdgeOptions: defaultEdgeOptions, fitView: fitView, fitViewOptions: fitViewOptions, onNodesDelete: onNodesDelete, onEdgesDelete: onEdgesDelete, onNodeDragStart: onNodeDragStart, onNodeDrag: onNodeDrag, onNodeDragStop: onNodeDragStop, onSelectionDrag: onSelectionDrag, onSelectionDragStart: onSelectionDragStart, onSelectionDragStop: onSelectionDragStop, noPanClassName: noPanClassName, nodeOrigin: nodeOrigin, rfId: rfId, autoPanOnConnect: autoPanOnConnect, autoPanOnNodeDrag: autoPanOnNodeDrag, onError: onError, connectionRadius: connectionRadius, isValidConnection: isValidConnection, nodeDragThreshold: nodeDragThreshold }),\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Wrapper$1, { onSelectionChange: onSelectionChange }),\n children,\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(Attribution, { proOptions: proOptions, position: attributionPosition }),\n react__WEBPACK_IMPORTED_MODULE_0__[\"default\"].createElement(A11yDescriptions, { rfId: rfId, disableKeyboardA11y: disableKeyboardA11y }))));\n});\nReactFlow.displayName = 'ReactFlow';\n\nconst selector$1 = (s) => s.domNode?.querySelector('.react-flow__edgelabel-renderer');\nfunction EdgeLabelRenderer({ children }) {\n const edgeLabelRenderer = useStore(selector$1);\n if (!edgeLabelRenderer) {\n return null;\n }\n return (0,react_dom__WEBPACK_IMPORTED_MODULE_3__.createPortal)(children, edgeLabelRenderer);\n}\n\nfunction useUpdateNodeInternals() {\n const store = useStoreApi();\n return (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((id) => {\n const { domNode, updateNodeDimensions } = store.getState();\n const updateIds = Array.isArray(id) ? id : [id];\n const updates = updateIds.reduce((res, updateId) => {\n const nodeElement = domNode?.querySelector(`.react-flow__node[data-id=\"${updateId}\"]`);\n if (nodeElement) {\n res.push({ id: updateId, nodeElement, forceUpdate: true });\n }\n return res;\n }, []);\n requestAnimationFrame(() => updateNodeDimensions(updates));\n }, []);\n}\n\nconst nodesSelector = (state) => state.getNodes();\nfunction useNodes() {\n const nodes = useStore(nodesSelector, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n return nodes;\n}\n\nconst edgesSelector = (state) => state.edges;\nfunction useEdges() {\n const edges = useStore(edgesSelector, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n return edges;\n}\n\nconst viewportSelector = (state) => ({\n x: state.transform[0],\n y: state.transform[1],\n zoom: state.transform[2],\n});\nfunction useViewport() {\n const viewport = useStore(viewportSelector, zustand_shallow__WEBPACK_IMPORTED_MODULE_5__.shallow);\n return viewport;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nfunction createUseItemsState(applyChanges) {\n return (initialItems) => {\n const [items, setItems] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(initialItems);\n const onItemsChange = (0,react__WEBPACK_IMPORTED_MODULE_0__.useCallback)((changes) => setItems((items) => applyChanges(changes, items)), []);\n return [items, setItems, onItemsChange];\n };\n}\nconst useNodesState = createUseItemsState(applyNodeChanges);\nconst useEdgesState = createUseItemsState(applyEdgeChanges);\n\nfunction useOnViewportChange({ onStart, onChange, onEnd }) {\n const store = useStoreApi();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n store.setState({ onViewportChangeStart: onStart });\n }, [onStart]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n store.setState({ onViewportChange: onChange });\n }, [onChange]);\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n store.setState({ onViewportChangeEnd: onEnd });\n }, [onEnd]);\n}\n\nfunction useOnSelectionChange({ onChange }) {\n const store = useStoreApi();\n (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {\n const nextSelectionChangeHandlers = [...store.getState().onSelectionChange, onChange];\n store.setState({ onSelectionChange: nextSelectionChangeHandlers });\n return () => {\n const nextHandlers = store.getState().onSelectionChange.filter((fn) => fn !== onChange);\n store.setState({ onSelectionChange: nextHandlers });\n };\n }, [onChange]);\n}\n\nconst selector = (options) => (s) => {\n if (s.nodeInternals.size === 0) {\n return false;\n }\n return s\n .getNodes()\n .filter((n) => (options.includeHiddenNodes ? true : !n.hidden))\n .every((n) => n[internalsSymbol]?.handleBounds !== undefined);\n};\nconst defaultOptions = {\n includeHiddenNodes: false,\n};\nfunction useNodesInitialized(options = defaultOptions) {\n const initialized = useStore(selector(options));\n return initialized;\n}\n\n// spark_dev_note: getHostForElement and getEdgeCenter added to export list\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvYXBpL2xlYWZ1aS9lbGVtZW50cy9mbG93ZWRpdG9yL2xpYi9yZWFjdGZsb3cuMTEuMTAuNC9jb3JlL2Rpc3QvZXNtL2luZGV4Lm1qcyIsIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vZ2hvc3Rvcy8uL3NyYy9hcGkvbGVhZnVpL2VsZW1lbnRzL2Zsb3dlZGl0b3IvbGliL3JlYWN0Zmxvdy4xMS4xMC40L2NvcmUvZGlzdC9lc20vaW5kZXgubWpzP2MxMTgiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0LCB7IGNyZWF0ZUNvbnRleHQsIHVzZUNvbnRleHQsIHVzZU1lbW8sIG1lbW8sIHVzZVJlZiwgdXNlU3RhdGUsIHVzZUVmZmVjdCwgZm9yd2FyZFJlZiwgdXNlQ2FsbGJhY2sgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgY2MgZnJvbSAnY2xhc3NjYXQnO1xuaW1wb3J0IHsgdXNlU3RvcmVXaXRoRXF1YWxpdHlGbiwgY3JlYXRlV2l0aEVxdWFsaXR5Rm4gfSBmcm9tICd6dXN0YW5kL3RyYWRpdGlvbmFsJztcbmltcG9ydCB7IHNoYWxsb3cgfSBmcm9tICd6dXN0YW5kL3NoYWxsb3cnO1xuaW1wb3J0IHsgem9vbUlkZW50aXR5LCB6b29tIH0gZnJvbSAnZDMtem9vbSc7XG5pbXBvcnQgeyBzZWxlY3QsIHBvaW50ZXIgfSBmcm9tICdkMy1zZWxlY3Rpb24nO1xuaW1wb3J0IHsgZHJhZyB9IGZyb20gJ2QzLWRyYWcnO1xuaW1wb3J0IHsgY3JlYXRlUG9ydGFsIH0gZnJvbSAncmVhY3QtZG9tJztcblxuY29uc3QgU3RvcmVDb250ZXh0ID0gY3JlYXRlQ29udGV4dChudWxsKTtcbmNvbnN0IFByb3ZpZGVyJDEgPSBTdG9yZUNvbnRleHQuUHJvdmlkZXI7XG5cbmNvbnN0IGVycm9yTWVzc2FnZXMgPSB7XG4gICAgZXJyb3IwMDE6ICgpID0+ICdbUmVhY3QgRmxvd106IFNlZW1zIGxpa2UgeW91IGhhdmUgbm90IHVzZWQgenVzdGFuZCBwcm92aWRlciBhcyBhbiBhbmNlc3Rvci4gSGVscDogaHR0cHM6Ly9yZWFjdGZsb3cuZGV2L2Vycm9yIzAwMScsXG4gICAgZXJyb3IwMDI6ICgpID0+IFwiSXQgbG9va3MgbGlrZSB5b3UndmUgY3JlYXRlZCBhIG5ldyBub2RlVHlwZXMgb3IgZWRnZVR5cGVzIG9iamVjdC4gSWYgdGhpcyB3YXNuJ3Qgb24gcHVycG9zZSBwbGVhc2UgZGVmaW5lIHRoZSBub2RlVHlwZXMvZWRnZVR5cGVzIG91dHNpZGUgb2YgdGhlIGNvbXBvbmVudCBvciBtZW1vaXplIHRoZW0uXCIsXG4gICAgZXJyb3IwMDM6IChub2RlVHlwZSkgPT4gYE5vZGUgdHlwZSBcIiR7bm9kZVR5cGV9XCIgbm90IGZvdW5kLiBVc2luZyBmYWxsYmFjayB0eXBlIFwiZGVmYXVsdFwiLmAsXG4gICAgZXJyb3IwMDQ6ICgpID0+ICdUaGUgUmVhY3QgRmxvdyBwYXJlbnQgY29udGFpbmVyIG5lZWRzIGEgd2lkdGggYW5kIGEgaGVpZ2h0IHRvIHJlbmRlciB0aGUgZ3JhcGguJyxcbiAgICBlcnJvcjAwNTogKCkgPT4gJ09ubHkgY2hpbGQgbm9kZXMgY2FuIHVzZSBhIHBhcmVudCBleHRlbnQuJyxcbiAgICBlcnJvcjAwNjogKCkgPT4gXCJDYW4ndCBjcmVhdGUgZWRnZS4gQW4gZWRnZSBuZWVkcyBhIHNvdXJjZSBhbmQgYSB0YXJnZXQuXCIsXG4gICAgZXJyb3IwMDc6IChpZCkgPT4gYFRoZSBvbGQgZWRnZSB3aXRoIGlkPSR7aWR9IGRvZXMgbm90IGV4aXN0LmAsXG4gICAgZXJyb3IwMDk6ICh0eXBlKSA9PiBgTWFya2VyIHR5cGUgXCIke3R5cGV9XCIgZG9lc24ndCBleGlzdC5gLFxuICAgIGVycm9yMDA4OiAoc291cmNlSGFuZGxlLCBlZGdlKSA9PiBgQ291bGRuJ3QgY3JlYXRlIGVkZ2UgZm9yICR7IXNvdXJjZUhhbmRsZSA/ICdzb3VyY2UnIDogJ3RhcmdldCd9IGhhbmRsZSBpZDogXCIkeyFzb3VyY2VIYW5kbGUgPyBlZGdlLnNvdXJjZUhhbmRsZSA6IGVkZ2UudGFyZ2V0SGFuZGxlfVwiLCBlZGdlIGlkOiAke2VkZ2UuaWR9LmAsXG4gICAgZXJyb3IwMTA6ICgpID0+ICdIYW5kbGU6IE5vIG5vZGUgaWQgZm91bmQuIE1ha2Ugc3VyZSB0byBvbmx5IHVzZSBhIEhhbmRsZSBpbnNpZGUgYSBjdXN0b20gTm9kZS4nLFxuICAgIGVycm9yMDExOiAoZWRnZVR5cGUpID0+IGBFZGdlIHR5cGUgXCIke2VkZ2VUeXBlfVwiIG5vdCBmb3VuZC4gVXNpbmcgZmFsbGJhY2sgdHlwZSBcImRlZmF1bHRcIi5gLFxuICAgIGVycm9yMDEyOiAoaWQpID0+IGBOb2RlIHdpdGggaWQgXCIke2lkfVwiIGRvZXMgbm90IGV4aXN0LCBpdCBtYXkgaGF2ZSBiZWVuIHJlbW92ZWQuIFRoaXMgY2FuIGhhcHBlbiB3aGVuIGEgbm9kZSBpcyBkZWxldGVkIGJlZm9yZSB0aGUgXCJvbk5vZGVDbGlja1wiIGhhbmRsZXIgaXMgY2FsbGVkLmAsXG59O1xuXG5jb25zdCB6dXN0YW5kRXJyb3JNZXNzYWdlID0gZXJyb3JNZXNzYWdlc1snZXJyb3IwMDEnXSgpO1xuZnVuY3Rpb24gdXNlU3RvcmUoc2VsZWN0b3IsIGVxdWFsaXR5Rm4pIHtcbiAgICBjb25zdCBzdG9yZSA9IHVzZUNvbnRleHQoU3RvcmVDb250ZXh0KTtcbiAgICBpZiAoc3RvcmUgPT09IG51bGwpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKHp1c3RhbmRFcnJvck1lc3NhZ2UpO1xuICAgIH1cbiAgICByZXR1cm4gdXNlU3RvcmVXaXRoRXF1YWxpdHlGbihzdG9yZSwgc2VsZWN0b3IsIGVxdWFsaXR5Rm4pO1xufVxuY29uc3QgdXNlU3RvcmVBcGkgPSAoKSA9PiB7XG4gICAgY29uc3Qgc3RvcmUgPSB1c2VDb250ZXh0KFN0b3JlQ29udGV4dCk7XG4gICAgaWYgKHN0b3JlID09PSBudWxsKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcih6dXN0YW5kRXJyb3JNZXNzYWdlKTtcbiAgICB9XG4gICAgcmV0dXJuIHVzZU1lbW8oKCkgPT4gKHtcbiAgICAgICAgZ2V0U3RhdGU6IHN0b3JlLmdldFN0YXRlLFxuICAgICAgICBzZXRTdGF0ZTogc3RvcmUuc2V0U3RhdGUsXG4gICAgICAgIHN1YnNjcmliZTogc3RvcmUuc3Vic2NyaWJlLFxuICAgICAgICBkZXN0cm95OiBzdG9yZS5kZXN0cm95LFxuICAgIH0pLCBbc3RvcmVdKTtcbn07XG5cbmNvbnN0IHNlbGVjdG9yJGcgPSAocykgPT4gKHMudXNlclNlbGVjdGlvbkFjdGl2ZSA/ICdub25lJyA6ICdhbGwnKTtcbmZ1bmN0aW9uIFBhbmVsKHsgcG9zaXRpb24sIGNoaWxkcmVuLCBjbGFzc05hbWUsIHN0eWxlLCAuLi5yZXN0IH0pIHtcbiAgICBjb25zdCBwb2ludGVyRXZlbnRzID0gdXNlU3RvcmUoc2VsZWN0b3IkZyk7XG4gICAgY29uc3QgcG9zaXRpb25DbGFzc2VzID0gYCR7cG9zaXRpb259YC5zcGxpdCgnLScpO1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogY2MoWydyZWFjdC1mbG93X19wYW5lbCcsIGNsYXNzTmFtZSwgLi4ucG9zaXRpb25DbGFzc2VzXSksIHN0eWxlOiB7IC4uLnN0eWxlLCBwb2ludGVyRXZlbnRzIH0sIC4uLnJlc3QgfSwgY2hpbGRyZW4pKTtcbn1cblxuZnVuY3Rpb24gQXR0cmlidXRpb24oeyBwcm9PcHRpb25zLCBwb3NpdGlvbiA9ICdib3R0b20tcmlnaHQnIH0pIHtcbiAgICBpZiAocHJvT3B0aW9ucz8uaGlkZUF0dHJpYnV0aW9uKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbiAgICAvLyBzcGFya19kZXZfbm90ZTogbm8gYXR0cmlidXRpb24gZm9yIG5vdy5cbiAgICAvLyhSZWFjdC5jcmVhdGVFbGVtZW50KFBhbmVsLCB7IHBvc2l0aW9uOiBwb3NpdGlvbiwgY2xhc3NOYW1lOiBcInJlYWN0LWZsb3dfX2F0dHJpYnV0aW9uXCIsIFwiZGF0YS1tZXNzYWdlXCI6IFwiUGxlYXNlIG9ubHkgaGlkZSB0aGlzIGF0dHJpYnV0aW9uIHdoZW4geW91IGFyZSBzdWJzY3JpYmVkIHRvIFJlYWN0IEZsb3cgUHJvOiBodHRwczovL3JlYWN0Zmxvdy5kZXYvcHJvXCIgfSxcbiAgICAvLyAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiYVwiLCB7IGhyZWY6IFwiaHR0cHM6Ly9yZWFjdGZsb3cuZGV2XCIsIHRhcmdldDogXCJfYmxhbmtcIiwgcmVsOiBcIm5vb3BlbmVyIG5vcmVmZXJyZXJcIiwgXCJhcmlhLWxhYmVsXCI6IFwiUmVhY3QgRmxvdyBhdHRyaWJ1dGlvblwiIH0sIFwiUmVhY3QgRmxvd1wiKSkpO1xufVxuXG5jb25zdCBFZGdlVGV4dCA9ICh7IHgsIHksIGxhYmVsLCBsYWJlbFN0eWxlID0ge30sIGxhYmVsU2hvd0JnID0gdHJ1ZSwgbGFiZWxCZ1N0eWxlID0ge30sIGxhYmVsQmdQYWRkaW5nID0gWzIsIDRdLCBsYWJlbEJnQm9yZGVyUmFkaXVzID0gMiwgY2hpbGRyZW4sIGNsYXNzTmFtZSwgLi4ucmVzdCB9KSA9PiB7XG4gICAgY29uc3QgZWRnZVJlZiA9IHVzZVJlZihudWxsKTtcbiAgICBjb25zdCBbZWRnZVRleHRCYm94LCBzZXRFZGdlVGV4dEJib3hdID0gdXNlU3RhdGUoeyB4OiAwLCB5OiAwLCB3aWR0aDogMCwgaGVpZ2h0OiAwIH0pO1xuICAgIGNvbnN0IGVkZ2VUZXh0Q2xhc3NlcyA9IGNjKFsncmVhY3QtZmxvd19fZWRnZS10ZXh0d3JhcHBlcicsIGNsYXNzTmFtZV0pO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChlZGdlUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IHRleHRCYm94ID0gZWRnZVJlZi5jdXJyZW50LmdldEJCb3goKTtcbiAgICAgICAgICAgIHNldEVkZ2VUZXh0QmJveCh7XG4gICAgICAgICAgICAgICAgeDogdGV4dEJib3gueCxcbiAgICAgICAgICAgICAgICB5OiB0ZXh0QmJveC55LFxuICAgICAgICAgICAgICAgIHdpZHRoOiB0ZXh0QmJveC53aWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQ6IHRleHRCYm94LmhlaWdodCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSwgW2xhYmVsXSk7XG4gICAgaWYgKHR5cGVvZiBsYWJlbCA9PT0gJ3VuZGVmaW5lZCcgfHwgIWxhYmVsKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJnXCIsIHsgdHJhbnNmb3JtOiBgdHJhbnNsYXRlKCR7eCAtIGVkZ2VUZXh0QmJveC53aWR0aCAvIDJ9ICR7eSAtIGVkZ2VUZXh0QmJveC5oZWlnaHQgLyAyfSlgLCBjbGFzc05hbWU6IGVkZ2VUZXh0Q2xhc3NlcywgdmlzaWJpbGl0eTogZWRnZVRleHRCYm94LndpZHRoID8gJ3Zpc2libGUnIDogJ2hpZGRlbicsIC4uLnJlc3QgfSxcbiAgICAgICAgbGFiZWxTaG93QmcgJiYgKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJyZWN0XCIsIHsgd2lkdGg6IGVkZ2VUZXh0QmJveC53aWR0aCArIDIgKiBsYWJlbEJnUGFkZGluZ1swXSwgeDogLWxhYmVsQmdQYWRkaW5nWzBdLCB5OiAtbGFiZWxCZ1BhZGRpbmdbMV0sIGhlaWdodDogZWRnZVRleHRCYm94LmhlaWdodCArIDIgKiBsYWJlbEJnUGFkZGluZ1sxXSwgY2xhc3NOYW1lOiBcInJlYWN0LWZsb3dfX2VkZ2UtdGV4dGJnXCIsIHN0eWxlOiBsYWJlbEJnU3R5bGUsIHJ4OiBsYWJlbEJnQm9yZGVyUmFkaXVzLCByeTogbGFiZWxCZ0JvcmRlclJhZGl1cyB9KSksXG4gICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJ0ZXh0XCIsIHsgY2xhc3NOYW1lOiBcInJlYWN0LWZsb3dfX2VkZ2UtdGV4dFwiLCB5OiBlZGdlVGV4dEJib3guaGVpZ2h0IC8gMiwgZHk6IFwiMC4zZW1cIiwgcmVmOiBlZGdlUmVmLCBzdHlsZTogbGFiZWxTdHlsZSB9LCBsYWJlbCksXG4gICAgICAgIGNoaWxkcmVuKSk7XG59O1xudmFyIEVkZ2VUZXh0JDEgPSBtZW1vKEVkZ2VUZXh0KTtcblxuY29uc3QgZ2V0RGltZW5zaW9ucyA9IChub2RlKSA9PiAoe1xuICAgIHdpZHRoOiBub2RlLm9mZnNldFdpZHRoLFxuICAgIGhlaWdodDogbm9kZS5vZmZzZXRIZWlnaHQsXG59KTtcbmNvbnN0IGNsYW1wID0gKHZhbCwgbWluID0gMCwgbWF4ID0gMSkgPT4gTWF0aC5taW4oTWF0aC5tYXgodmFsLCBtaW4pLCBtYXgpO1xuY29uc3QgY2xhbXBQb3NpdGlvbiA9IChwb3NpdGlvbiA9IHsgeDogMCwgeTogMCB9LCBleHRlbnQpID0+ICh7XG4gICAgeDogY2xhbXAocG9zaXRpb24ueCwgZXh0ZW50WzBdWzBdLCBleHRlbnRbMV1bMF0pLFxuICAgIHk6IGNsYW1wKHBvc2l0aW9uLnksIGV4dGVudFswXVsxXSwgZXh0ZW50WzFdWzFdKSxcbn0pO1xuLy8gcmV0dXJucyBhIG51bWJlciBiZXR3ZWVuIDAgYW5kIDEgdGhhdCByZXByZXNlbnRzIHRoZSB2ZWxvY2l0eSBvZiB0aGUgbW92ZW1lbnRcbi8vIHdoZW4gdGhlIG1vdXNlIGlzIGNsb3NlIHRvIHRoZSBlZGdlIG9mIHRoZSBjYW52YXNcbmNvbnN0IGNhbGNBdXRvUGFuVmVsb2NpdHkgPSAodmFsdWUsIG1pbiwgbWF4KSA9PiB7XG4gICAgaWYgKHZhbHVlIDwgbWluKSB7XG4gICAgICAgIHJldHVybiBjbGFtcChNYXRoLmFicyh2YWx1ZSAtIG1pbiksIDEsIDUwKSAvIDUwO1xuICAgIH1cbiAgICBlbHNlIGlmICh2YWx1ZSA+IG1heCkge1xuICAgICAgICByZXR1cm4gLWNsYW1wKE1hdGguYWJzKHZhbHVlIC0gbWF4KSwgMSwgNTApIC8gNTA7XG4gICAgfVxuICAgIHJldHVybiAwO1xufTtcbmNvbnN0IGNhbGNBdXRvUGFuID0gKHBvcywgYm91bmRzKSA9PiB7XG4gICAgY29uc3QgeE1vdmVtZW50ID0gY2FsY0F1dG9QYW5WZWxvY2l0eShwb3MueCwgMzUsIGJvdW5kcy53aWR0aCAtIDM1KSAqIDIwO1xuICAgIGNvbnN0IHlNb3ZlbWVudCA9IGNhbGNBdXRvUGFuVmVsb2NpdHkocG9zLnksIDM1LCBib3VuZHMuaGVpZ2h0IC0gMzUpICogMjA7XG4gICAgcmV0dXJuIFt4TW92ZW1lbnQsIHlNb3ZlbWVudF07XG59O1xuY29uc3QgZ2V0SG9zdEZvckVsZW1lbnQgPSAoZWxlbWVudCkgPT4gZWxlbWVudC5nZXRSb290Tm9kZT8uKCkgfHwgd2luZG93Py5kb2N1bWVudDtcbmNvbnN0IGdldEJvdW5kc09mQm94ZXMgPSAoYm94MSwgYm94MikgPT4gKHtcbiAgICB4OiBNYXRoLm1pbihib3gxLngsIGJveDIueCksXG4gICAgeTogTWF0aC5taW4oYm94MS55LCBib3gyLnkpLFxuICAgIHgyOiBNYXRoLm1heChib3gxLngyLCBib3gyLngyKSxcbiAgICB5MjogTWF0aC5tYXgoYm94MS55MiwgYm94Mi55MiksXG59KTtcbmNvbnN0IHJlY3RUb0JveCA9ICh7IHgsIHksIHdpZHRoLCBoZWlnaHQgfSkgPT4gKHtcbiAgICB4LFxuICAgIHksXG4gICAgeDI6IHggKyB3aWR0aCxcbiAgICB5MjogeSArIGhlaWdodCxcbn0pO1xuY29uc3QgYm94VG9SZWN0ID0gKHsgeCwgeSwgeDIsIHkyIH0pID0+ICh7XG4gICAgeCxcbiAgICB5LFxuICAgIHdpZHRoOiB4MiAtIHgsXG4gICAgaGVpZ2h0OiB5MiAtIHksXG59KTtcbmNvbnN0IG5vZGVUb1JlY3QgPSAobm9kZSkgPT4gKHtcbiAgICAuLi4obm9kZS5wb3NpdGlvbkFic29sdXRlIHx8IHsgeDogMCwgeTogMCB9KSxcbiAgICB3aWR0aDogbm9kZS53aWR0aCB8fCAwLFxuICAgIGhlaWdodDogbm9kZS5oZWlnaHQgfHwgMCxcbn0pO1xuY29uc3QgZ2V0Qm91bmRzT2ZSZWN0cyA9IChyZWN0MSwgcmVjdDIpID0+IGJveFRvUmVjdChnZXRCb3VuZHNPZkJveGVzKHJlY3RUb0JveChyZWN0MSksIHJlY3RUb0JveChyZWN0MikpKTtcbmNvbnN0IGdldE92ZXJsYXBwaW5nQXJlYSA9IChyZWN0QSwgcmVjdEIpID0+IHtcbiAgICBjb25zdCB4T3ZlcmxhcCA9IE1hdGgubWF4KDAsIE1hdGgubWluKHJlY3RBLnggKyByZWN0QS53aWR0aCwgcmVjdEIueCArIHJlY3RCLndpZHRoKSAtIE1hdGgubWF4KHJlY3RBLngsIHJlY3RCLngpKTtcbiAgICBjb25zdCB5T3ZlcmxhcCA9IE1hdGgubWF4KDAsIE1hdGgubWluKHJlY3RBLnkgKyByZWN0QS5oZWlnaHQsIHJlY3RCLnkgKyByZWN0Qi5oZWlnaHQpIC0gTWF0aC5tYXgocmVjdEEueSwgcmVjdEIueSkpO1xuICAgIHJldHVybiBNYXRoLmNlaWwoeE92ZXJsYXAgKiB5T3ZlcmxhcCk7XG59O1xuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uby1leHBsaWNpdC1hbnlcbmNvbnN0IGlzUmVjdE9iamVjdCA9IChvYmopID0+IGlzTnVtZXJpYyhvYmoud2lkdGgpICYmIGlzTnVtZXJpYyhvYmouaGVpZ2h0KSAmJiBpc051bWVyaWMob2JqLngpICYmIGlzTnVtZXJpYyhvYmoueSk7XG4vKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuY29uc3QgaXNOdW1lcmljID0gKG4pID0+ICFpc05hTihuKSAmJiBpc0Zpbml0ZShuKTtcbmNvbnN0IGludGVybmFsc1N5bWJvbCA9IFN5bWJvbC5mb3IoJ2ludGVybmFscycpO1xuLy8gdXNlZCBmb3IgYTExeSBrZXkgYm9hcmQgY29udHJvbHMgZm9yIG5vZGVzIGFuZCBlZGdlc1xuY29uc3QgZWxlbWVudFNlbGVjdGlvbktleXMgPSBbJ0VudGVyJywgJyAnLCAnRXNjYXBlJ107XG5jb25zdCBkZXZXYXJuID0gKGlkLCBtZXNzYWdlKSA9PiB7XG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAnZGV2ZWxvcG1lbnQnKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgW1JlYWN0IEZsb3ddOiAke21lc3NhZ2V9IEhlbHA6IGh0dHBzOi8vcmVhY3RmbG93LmRldi9lcnJvciMke2lkfWApO1xuICAgIH1cbn07XG5jb25zdCBpc1JlYWN0S2V5Ym9hcmRFdmVudCA9IChldmVudCkgPT4gJ25hdGl2ZUV2ZW50JyBpbiBldmVudDtcbmZ1bmN0aW9uIGlzSW5wdXRET01Ob2RlKGV2ZW50KSB7XG4gICAgY29uc3Qga2JFdmVudCA9IGlzUmVhY3RLZXlib2FyZEV2ZW50KGV2ZW50KSA/IGV2ZW50Lm5hdGl2ZUV2ZW50IDogZXZlbnQ7XG4gICAgLy8gdXNpbmcgY29tcG9zZWQgcGF0aCBmb3IgaGFuZGxpbmcgc2hhZG93IGRvbVxuICAgIGNvbnN0IHRhcmdldCA9IChrYkV2ZW50LmNvbXBvc2VkUGF0aD8uKCk/LlswXSB8fCBldmVudC50YXJnZXQpO1xuICAgIGNvbnN0IGlzSW5wdXQgPSBbJ0lOUFVUJywgJ1NFTEVDVCcsICdURVhUQVJFQSddLmluY2x1ZGVzKHRhcmdldD8ubm9kZU5hbWUpIHx8IHRhcmdldD8uaGFzQXR0cmlidXRlKCdjb250ZW50ZWRpdGFibGUnKTtcbiAgICAvLyB3aGVuIGFuIGlucHV0IGZpZWxkIGlzIGZvY3VzZWQgd2UgZG9uJ3Qgd2FudCB0byB0cmlnZ2VyIGRlbGV0aW9uIG9yIG1vdmVtZW50IG9mIG5vZGVzXG4gICAgcmV0dXJuIGlzSW5wdXQgfHwgISF0YXJnZXQ/LmNsb3Nlc3QoJy5ub2tleScpO1xufVxuY29uc3QgaXNNb3VzZUV2ZW50ID0gKGV2ZW50KSA9PiAnY2xpZW50WCcgaW4gZXZlbnQ7XG5jb25zdCBnZXRFdmVudFBvc2l0aW9uID0gKGV2ZW50LCBib3VuZHMpID0+IHtcbiAgICBjb25zdCBpc01vdXNlVHJpZ2dlcmVkID0gaXNNb3VzZUV2ZW50KGV2ZW50KTtcbiAgICBjb25zdCBldnRYID0gaXNNb3VzZVRyaWdnZXJlZCA/IGV2ZW50LmNsaWVudFggOiBldmVudC50b3VjaGVzPy5bMF0uY2xpZW50WDtcbiAgICBjb25zdCBldnRZID0gaXNNb3VzZVRyaWdnZXJlZCA/IGV2ZW50LmNsaWVudFkgOiBldmVudC50b3VjaGVzPy5bMF0uY2xpZW50WTtcbiAgICByZXR1cm4ge1xuICAgICAgICB4OiBldnRYIC0gKGJvdW5kcz8ubGVmdCA/PyAwKSxcbiAgICAgICAgeTogZXZ0WSAtIChib3VuZHM/LnRvcCA/PyAwKSxcbiAgICB9O1xufTtcbmNvbnN0IGlzTWFjT3MgPSAoKSA9PiB0eXBlb2YgbmF2aWdhdG9yICE9PSAndW5kZWZpbmVkJyAmJiBuYXZpZ2F0b3I/LnVzZXJBZ2VudD8uaW5kZXhPZignTWFjJykgPj0gMDtcblxuY29uc3QgQmFzZUVkZ2UgPSAoeyBpZCwgcGF0aCwgbGFiZWxYLCBsYWJlbFksIGxhYmVsLCBsYWJlbFN0eWxlLCBsYWJlbFNob3dCZywgbGFiZWxCZ1N0eWxlLCBsYWJlbEJnUGFkZGluZywgbGFiZWxCZ0JvcmRlclJhZGl1cywgc3R5bGUsIG1hcmtlckVuZCwgbWFya2VyU3RhcnQsIGludGVyYWN0aW9uV2lkdGggPSAyMCwgfSkgPT4ge1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChSZWFjdC5GcmFnbWVudCwgbnVsbCxcbiAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcInBhdGhcIiwgeyBpZDogaWQsIHN0eWxlOiBzdHlsZSwgZDogcGF0aCwgZmlsbDogXCJub25lXCIsIGNsYXNzTmFtZTogXCJyZWFjdC1mbG93X19lZGdlLXBhdGhcIiwgbWFya2VyRW5kOiBtYXJrZXJFbmQsIG1hcmtlclN0YXJ0OiBtYXJrZXJTdGFydCB9KSxcbiAgICAgICAgaW50ZXJhY3Rpb25XaWR0aCAmJiAoUmVhY3QuY3JlYXRlRWxlbWVudChcInBhdGhcIiwgeyBkOiBwYXRoLCBmaWxsOiBcIm5vbmVcIiwgc3Ryb2tlT3BhY2l0eTogMCwgc3Ryb2tlV2lkdGg6IGludGVyYWN0aW9uV2lkdGgsIGNsYXNzTmFtZTogXCJyZWFjdC1mbG93X19lZGdlLWludGVyYWN0aW9uXCIgfSkpLFxuICAgICAgICBsYWJlbCAmJiBpc051bWVyaWMobGFiZWxYKSAmJiBpc051bWVyaWMobGFiZWxZKSA/IChSZWFjdC5jcmVhdGVFbGVtZW50KEVkZ2VUZXh0JDEsIHsgeDogbGFiZWxYLCB5OiBsYWJlbFksIGxhYmVsOiBsYWJlbCwgbGFiZWxTdHlsZTogbGFiZWxTdHlsZSwgbGFiZWxTaG93Qmc6IGxhYmVsU2hvd0JnLCBsYWJlbEJnU3R5bGU6IGxhYmVsQmdTdHlsZSwgbGFiZWxCZ1BhZGRpbmc6IGxhYmVsQmdQYWRkaW5nLCBsYWJlbEJnQm9yZGVyUmFkaXVzOiBsYWJlbEJnQm9yZGVyUmFkaXVzIH0pKSA6IG51bGwpKTtcbn07XG5CYXNlRWRnZS5kaXNwbGF5TmFtZSA9ICdCYXNlRWRnZSc7XG5cbmNvbnN0IGdldE1hcmtlckVuZCA9IChtYXJrZXJUeXBlLCBtYXJrZXJFbmRJZCkgPT4ge1xuICAgIGlmICh0eXBlb2YgbWFya2VyRW5kSWQgIT09ICd1bmRlZmluZWQnICYmIG1hcmtlckVuZElkKSB7XG4gICAgICAgIHJldHVybiBgdXJsKCMke21hcmtlckVuZElkfSlgO1xuICAgIH1cbiAgICByZXR1cm4gdHlwZW9mIG1hcmtlclR5cGUgIT09ICd1bmRlZmluZWQnID8gYHVybCgjcmVhY3QtZmxvd19fJHttYXJrZXJUeXBlfSlgIDogJ25vbmUnO1xufTtcbmZ1bmN0aW9uIGdldE1vdXNlSGFuZGxlciQxKGlkLCBnZXRTdGF0ZSwgaGFuZGxlcikge1xuICAgIHJldHVybiBoYW5kbGVyID09PSB1bmRlZmluZWRcbiAgICAgICAgPyBoYW5kbGVyXG4gICAgICAgIDogKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBlZGdlID0gZ2V0U3RhdGUoKS5lZGdlcy5maW5kKChlKSA9PiBlLmlkID09PSBpZCk7XG4gICAgICAgICAgICBpZiAoZWRnZSkge1xuICAgICAgICAgICAgICAgIGhhbmRsZXIoZXZlbnQsIHsgLi4uZWRnZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbn1cbi8vIHRoaXMgaXMgdXNlZCBmb3Igc3RyYWlnaHQgZWRnZXMgYW5kIHNpbXBsZSBzbW9vdGhzdGVwIGVkZ2VzIChMVFIsIFJUTCwgQlRULCBUVEIpXG5mdW5jdGlvbiBnZXRFZGdlQ2VudGVyKHsgc291cmNlWCwgc291cmNlWSwgdGFyZ2V0WCwgdGFyZ2V0WSwgfSkge1xuICAgIGNvbnN0IHhPZmZzZXQgPSBNYXRoLmFicyh0YXJnZXRYIC0gc291cmNlWCkgLyAyO1xuICAgIGNvbnN0IGNlbnRlclggPSB0YXJnZXRYIDwgc291cmNlWCA/IHRhcmdldFggKyB4T2Zmc2V0IDogdGFyZ2V0WCAtIHhPZmZzZXQ7XG4gICAgY29uc3QgeU9mZnNldCA9IE1hdGguYWJzKHRhcmdldFkgLSBzb3VyY2VZKSAvIDI7XG4gICAgY29uc3QgY2VudGVyWSA9IHRhcmdldFkgPCBzb3VyY2VZID8gdGFyZ2V0WSArIHlPZmZzZXQgOiB0YXJnZXRZIC0geU9mZnNldDtcbiAgICByZXR1cm4gW2NlbnRlclgsIGNlbnRlclksIHhPZmZzZXQsIHlPZmZzZXRdO1xufVxuZnVuY3Rpb24gZ2V0QmV6aWVyRWRnZUNlbnRlcih7IHNvdXJjZVgsIHNvdXJjZVksIHRhcmdldFgsIHRhcmdldFksIHNvdXJjZUNvbnRyb2xYLCBzb3VyY2VDb250cm9sWSwgdGFyZ2V0Q29udHJvbFgsIHRhcmdldENvbnRyb2xZLCB9KSB7XG4gICAgLy8gY3ViaWMgYmV6aWVyIHQ9MC41IG1pZCBwb2ludCwgbm90IHRoZSBhY3R1YWwgbWlkIHBvaW50LCBidXQgZWFzeSB0byBjYWxjdWxhdGVcbiAgICAvLyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82NzUxNjEwMS9ob3ctdG8tZmluZC1kaXN0YW5jZS1taWQtcG9pbnQtb2YtYmV6aWVyLWN1cnZlXG4gICAgY29uc3QgY2VudGVyWCA9IHNvdXJjZVggKiAwLjEyNSArIHNvdXJjZUNvbnRyb2xYICogMC4zNzUgKyB0YXJnZXRDb250cm9sWCAqIDAuMzc1ICsgdGFyZ2V0WCAqIDAuMTI1O1xuICAgIGNvbnN0IGNlbnRlclkgPSBzb3VyY2VZICogMC4xMjUgKyBzb3VyY2VDb250cm9sWSAqIDAuMzc1ICsgdGFyZ2V0Q29udHJvbFkgKiAwLjM3NSArIHRhcmdldFkgKiAwLjEyNTtcbiAgICBjb25zdCBvZmZzZXRYID0gTWF0aC5hYnMoY2VudGVyWCAtIHNvdXJjZVgpO1xuICAgIGNvbnN0IG9mZnNldFkgPSBNYXRoLmFicyhjZW50ZXJZIC0gc291cmNlWSk7XG4gICAgcmV0dXJuIFtjZW50ZXJYLCBjZW50ZXJZLCBvZmZzZXRYLCBvZmZzZXRZXTtcbn1cblxudmFyIENvbm5lY3Rpb25Nb2RlO1xuKGZ1bmN0aW9uIChDb25uZWN0aW9uTW9kZSkge1xuICAgIENvbm5lY3Rpb25Nb2RlW1wiU3RyaWN0XCJdID0gXCJzdHJpY3RcIjtcbiAgICBDb25uZWN0aW9uTW9kZVtcIkxvb3NlXCJdID0gXCJsb29zZVwiO1xufSkoQ29ubmVjdGlvbk1vZGUgfHwgKENvbm5lY3Rpb25Nb2RlID0ge30pKTtcbnZhciBQYW5PblNjcm9sbE1vZGU7XG4oZnVuY3Rpb24gKFBhbk9uU2Nyb2xsTW9kZSkge1xuICAgIFBhbk9uU2Nyb2xsTW9kZVtcIkZyZWVcIl0gPSBcImZyZWVcIjtcbiAgICBQYW5PblNjcm9sbE1vZGVbXCJWZXJ0aWNhbFwiXSA9IFwidmVydGljYWxcIjtcbiAgICBQYW5PblNjcm9sbE1vZGVbXCJIb3Jpem9udGFsXCJdID0gXCJob3Jpem9udGFsXCI7XG59KShQYW5PblNjcm9sbE1vZGUgfHwgKFBhbk9uU2Nyb2xsTW9kZSA9IHt9KSk7XG52YXIgU2VsZWN0aW9uTW9kZTtcbihmdW5jdGlvbiAoU2VsZWN0aW9uTW9kZSkge1xuICAgIFNlbGVjdGlvbk1vZGVbXCJQYXJ0aWFsXCJdID0gXCJwYXJ0aWFsXCI7XG4gICAgU2VsZWN0aW9uTW9kZVtcIkZ1bGxcIl0gPSBcImZ1bGxcIjtcbn0pKFNlbGVjdGlvbk1vZGUgfHwgKFNlbGVjdGlvbk1vZGUgPSB7fSkpO1xuXG52YXIgQ29ubmVjdGlvbkxpbmVUeXBlO1xuKGZ1bmN0aW9uIChDb25uZWN0aW9uTGluZVR5cGUpIHtcbiAgICBDb25uZWN0aW9uTGluZVR5cGVbXCJCZXppZXJcIl0gPSBcImRlZmF1bHRcIjtcbiAgICBDb25uZWN0aW9uTGluZVR5cGVbXCJTdHJhaWdodFwiXSA9IFwic3RyYWlnaHRcIjtcbiAgICBDb25uZWN0aW9uTGluZVR5cGVbXCJTdGVwXCJdID0gXCJzdGVwXCI7XG4gICAgQ29ubmVjdGlvbkxpbmVUeXBlW1wiU21vb3RoU3RlcFwiXSA9IFwic21vb3Roc3RlcFwiO1xuICAgIENvbm5lY3Rpb25MaW5lVHlwZVtcIlNpbXBsZUJlemllclwiXSA9IFwic2ltcGxlYmV6aWVyXCI7XG59KShDb25uZWN0aW9uTGluZVR5cGUgfHwgKENvbm5lY3Rpb25MaW5lVHlwZSA9IHt9KSk7XG52YXIgTWFya2VyVHlwZTtcbihmdW5jdGlvbiAoTWFya2VyVHlwZSkge1xuICAgIE1hcmtlclR5cGVbXCJBcnJvd1wiXSA9IFwiYXJyb3dcIjtcbiAgICBNYXJrZXJUeXBlW1wiQXJyb3dDbG9zZWRcIl0gPSBcImFycm93Y2xvc2VkXCI7XG59KShNYXJrZXJUeXBlIHx8IChNYXJrZXJUeXBlID0ge30pKTtcblxudmFyIFBvc2l0aW9uO1xuKGZ1bmN0aW9uIChQb3NpdGlvbikge1xuICAgIFBvc2l0aW9uW1wiTGVmdFwiXSA9IFwibGVmdFwiO1xuICAgIFBvc2l0aW9uW1wiVG9wXCJdID0gXCJ0b3BcIjtcbiAgICBQb3NpdGlvbltcIlJpZ2h0XCJdID0gXCJyaWdodFwiO1xuICAgIFBvc2l0aW9uW1wiQm90dG9tXCJdID0gXCJib3R0b21cIjtcbn0pKFBvc2l0aW9uIHx8IChQb3NpdGlvbiA9IHt9KSk7XG5cbmZ1bmN0aW9uIGdldENvbnRyb2woeyBwb3MsIHgxLCB5MSwgeDIsIHkyIH0pIHtcbiAgICBpZiAocG9zID09PSBQb3NpdGlvbi5MZWZ0IHx8IHBvcyA9PT0gUG9zaXRpb24uUmlnaHQpIHtcbiAgICAgICAgcmV0dXJuIFswLjUgKiAoeDEgKyB4MiksIHkxXTtcbiAgICB9XG4gICAgcmV0dXJuIFt4MSwgMC41ICogKHkxICsgeTIpXTtcbn1cbmZ1bmN0aW9uIGdldFNpbXBsZUJlemllclBhdGgoeyBzb3VyY2VYLCBzb3VyY2VZLCBzb3VyY2VQb3NpdGlvbiA9IFBvc2l0aW9uLkJvdHRvbSwgdGFyZ2V0WCwgdGFyZ2V0WSwgdGFyZ2V0UG9zaXRpb24gPSBQb3NpdGlvbi5Ub3AsIH0pIHtcbiAgICBjb25zdCBbc291cmNlQ29udHJvbFgsIHNvdXJjZUNvbnRyb2xZXSA9IGdldENvbnRyb2woe1xuICAgICAgICBwb3M6IHNvdXJjZVBvc2l0aW9uLFxuICAgICAgICB4MTogc291cmNlWCxcbiAgICAgICAgeTE6IHNvdXJjZVksXG4gICAgICAgIHgyOiB0YXJnZXRYLFxuICAgICAgICB5MjogdGFyZ2V0WSxcbiAgICB9KTtcbiAgICBjb25zdCBbdGFyZ2V0Q29udHJvbFgsIHRhcmdldENvbnRyb2xZXSA9IGdldENvbnRyb2woe1xuICAgICAgICBwb3M6IHRhcmdldFBvc2l0aW9uLFxuICAgICAgICB4MTogdGFyZ2V0WCxcbiAgICAgICAgeTE6IHRhcmdldFksXG4gICAgICAgIHgyOiBzb3VyY2VYLFxuICAgICAgICB5Mjogc291cmNlWSxcbiAgICB9KTtcbiAgICBjb25zdCBbbGFiZWxYLCBsYWJlbFksIG9mZnNldFgsIG9mZnNldFldID0gZ2V0QmV6aWVyRWRnZUNlbnRlcih7XG4gICAgICAgIHNvdXJjZVgsXG4gICAgICAgIHNvdXJjZVksXG4gICAgICAgIHRhcmdldFgsXG4gICAgICAgIHRhcmdldFksXG4gICAgICAgIHNvdXJjZUNvbnRyb2xYLFxuICAgICAgICBzb3VyY2VDb250cm9sWSxcbiAgICAgICAgdGFyZ2V0Q29udHJvbFgsXG4gICAgICAgIHRhcmdldENvbnRyb2xZLFxuICAgIH0pO1xuICAgIHJldHVybiBbXG4gICAgICAgIGBNJHtzb3VyY2VYfSwke3NvdXJjZVl9IEMke3NvdXJjZUNvbnRyb2xYfSwke3NvdXJjZUNvbnRyb2xZfSAke3RhcmdldENvbnRyb2xYfSwke3RhcmdldENvbnRyb2xZfSAke3RhcmdldFh9LCR7dGFyZ2V0WX1gLFxuICAgICAgICBsYWJlbFgsXG4gICAgICAgIGxhYmVsWSxcbiAgICAgICAgb2Zmc2V0WCxcbiAgICAgICAgb2Zmc2V0WSxcbiAgICBdO1xufVxuY29uc3QgU2ltcGxlQmV6aWVyRWRnZSA9IG1lbW8oKHsgc291cmNlWCwgc291cmNlWSwgdGFyZ2V0WCwgdGFyZ2V0WSwgc291cmNlUG9zaXRpb24gPSBQb3NpdGlvbi5Cb3R0b20sIHRhcmdldFBvc2l0aW9uID0gUG9zaXRpb24uVG9wLCBsYWJlbCwgbGFiZWxTdHlsZSwgbGFiZWxTaG93QmcsIGxhYmVsQmdTdHlsZSwgbGFiZWxCZ1BhZGRpbmcsIGxhYmVsQmdCb3JkZXJSYWRpdXMsIHN0eWxlLCBtYXJrZXJFbmQsIG1hcmtlclN0YXJ0LCBpbnRlcmFjdGlvbldpZHRoLCB9KSA9PiB7XG4gICAgY29uc3QgW3BhdGgsIGxhYmVsWCwgbGFiZWxZXSA9IGdldFNpbXBsZUJlemllclBhdGgoe1xuICAgICAgICBzb3VyY2VYLFxuICAgICAgICBzb3VyY2VZLFxuICAgICAgICBzb3VyY2VQb3NpdGlvbixcbiAgICAgICAgdGFyZ2V0WCxcbiAgICAgICAgdGFyZ2V0WSxcbiAgICAgICAgdGFyZ2V0UG9zaXRpb24sXG4gICAgfSk7XG4gICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KEJhc2VFZGdlLCB7IHBhdGg6IHBhdGgsIGxhYmVsWDogbGFiZWxYLCBsYWJlbFk6IGxhYmVsWSwgbGFiZWw6IGxhYmVsLCBsYWJlbFN0eWxlOiBsYWJlbFN0eWxlLCBsYWJlbFNob3dCZzogbGFiZWxTaG93QmcsIGxhYmVsQmdTdHlsZTogbGFiZWxCZ1N0eWxlLCBsYWJlbEJnUGFkZGluZzogbGFiZWxCZ1BhZGRpbmcsIGxhYmVsQmdCb3JkZXJSYWRpdXM6IGxhYmVsQmdCb3JkZXJSYWRpdXMsIHN0eWxlOiBzdHlsZSwgbWFya2VyRW5kOiBtYXJrZXJFbmQsIG1hcmtlclN0YXJ0OiBtYXJrZXJTdGFydCwgaW50ZXJhY3Rpb25XaWR0aDogaW50ZXJhY3Rpb25XaWR0aCB9KSk7XG59KTtcblNpbXBsZUJlemllckVkZ2UuZGlzcGxheU5hbWUgPSAnU2ltcGxlQmV6aWVyRWRnZSc7XG5cbmNvbnN0IGhhbmRsZURpcmVjdGlvbnMgPSB7XG4gICAgW1Bvc2l0aW9uLkxlZnRdOiB7IHg6IC0xLCB5OiAwIH0sXG4gICAgW1Bvc2l0aW9uLlJpZ2h0XTogeyB4OiAxLCB5OiAwIH0sXG4gICAgW1Bvc2l0aW9uLlRvcF06IHsgeDogMCwgeTogLTEgfSxcbiAgICBbUG9zaXRpb24uQm90dG9tXTogeyB4OiAwLCB5OiAxIH0sXG59O1xuY29uc3QgZ2V0RGlyZWN0aW9uID0gKHsgc291cmNlLCBzb3VyY2VQb3NpdGlvbiA9IFBvc2l0aW9uLkJvdHRvbSwgdGFyZ2V0LCB9KSA9PiB7XG4gICAgaWYgKHNvdXJjZVBvc2l0aW9uID09PSBQb3NpdGlvbi5MZWZ0IHx8IHNvdXJjZVBvc2l0aW9uID09PSBQb3NpdGlvbi5SaWdodCkge1xuICAgICAgICByZXR1cm4gc291cmNlLnggPCB0YXJnZXQueCA/IHsgeDogMSwgeTogMCB9IDogeyB4OiAtMSwgeTogMCB9O1xuICAgIH1cbiAgICByZXR1cm4gc291cmNlLnkgPCB0YXJnZXQueSA/IHsgeDogMCwgeTogMSB9IDogeyB4OiAwLCB5OiAtMSB9O1xufTtcbmNvbnN0IGRpc3RhbmNlID0gKGEsIGIpID0+IE1hdGguc3FydChNYXRoLnBvdyhiLnggLSBhLngsIDIpICsgTWF0aC5wb3coYi55IC0gYS55LCAyKSk7XG4vLyBpdGggdGhpcyBmdW5jdGlvbiB3ZSB0cnkgdG8gbWltaWMgYSBvcnRob2dvbmFsIGVkZ2Ugcm91dGluZyBiZWhhdmlvdXJcbi8vIEl0J3Mgbm90IGFzIGdvb2QgYXMgYSByZWFsIG9ydGhvZ29uYWwgZWRnZSByb3V0aW5nIGJ1dCBpdCdzIGZhc3RlciBhbmQgZ29vZCBlbm91Z2ggYXMgYSBkZWZhdWx0IGZvciBzdGVwIGFuZCBzbW9vdGggc3RlcCBlZGdlc1xuZnVuY3Rpb24gZ2V0UG9pbnRzKHsgc291cmNlLCBzb3VyY2VQb3NpdGlvbiA9IFBvc2l0aW9uLkJvdHRvbSwgdGFyZ2V0LCB0YXJnZXRQb3NpdGlvbiA9IFBvc2l0aW9uLlRvcCwgY2VudGVyLCBvZmZzZXQsIH0pIHtcbiAgICBjb25zdCBzb3VyY2VEaXIgPSBoYW5kbGVEaXJlY3Rpb25zW3NvdXJjZVBvc2l0aW9uXTtcbiAgICBjb25zdCB0YXJnZXREaXIgPSBoYW5kbGVEaXJlY3Rpb25zW3RhcmdldFBvc2l0aW9uXTtcbiAgICBjb25zdCBzb3VyY2VHYXBwZWQgPSB7IHg6IHNvdXJjZS54ICsgc291cmNlRGlyLnggKiBvZmZzZXQsIHk6IHNvdXJjZS55ICsgc291cmNlRGlyLnkgKiBvZmZzZXQgfTtcbiAgICBjb25zdCB0YXJnZXRHYXBwZWQgPSB7IHg6IHRhcmdldC54ICsgdGFyZ2V0RGlyLnggKiBvZmZzZXQsIHk6IHRhcmdldC55ICsgdGFyZ2V0RGlyLnkgKiBvZmZzZXQgfTtcbiAgICBjb25zdCBkaXIgPSBnZXREaXJlY3Rpb24oe1xuICAgICAgICBzb3VyY2U6IHNvdXJjZUdhcHBlZCxcbiAgICAgICAgc291cmNlUG9zaXRpb24sXG4gICAgICAgIHRhcmdldDogdGFyZ2V0R2FwcGVkLFxuICAgIH0pO1xuICAgIGNvbnN0IGRpckFjY2Vzc29yID0gZGlyLnggIT09IDAgPyAneCcgOiAneSc7XG4gICAgY29uc3QgY3VyckRpciA9IGRpcltkaXJBY2Nlc3Nvcl07XG4gICAgbGV0IHBvaW50cyA9IFtdO1xuICAgIGxldCBjZW50ZXJYLCBjZW50ZXJZO1xuICAgIGNvbnN0IHNvdXJjZUdhcE9mZnNldCA9IHsgeDogMCwgeTogMCB9O1xuICAgIGNvbnN0IHRhcmdldEdhcE9mZnNldCA9IHsgeDogMCwgeTogMCB9O1xuICAgIGNvbnN0IFtkZWZhdWx0Q2VudGVyWCwgZGVmYXVsdENlbnRlclksIGRlZmF1bHRPZmZzZXRYLCBkZWZhdWx0T2Zmc2V0WV0gPSBnZXRFZGdlQ2VudGVyKHtcbiAgICAgICAgc291cmNlWDogc291cmNlLngsXG4gICAgICAgIHNvdXJjZVk6IHNvdXJjZS55LFxuICAgICAgICB0YXJnZXRYOiB0YXJnZXQueCxcbiAgICAgICAgdGFyZ2V0WTogdGFyZ2V0LnksXG4gICAgfSk7XG4gICAgLy8gb3Bwb3NpdGUgaGFuZGxlIHBvc2l0aW9ucywgZGVmYXVsdCBjYXNlXG4gICAgaWYgKHNvdXJjZURpcltkaXJBY2Nlc3Nvcl0gKiB0YXJnZXREaXJbZGlyQWNjZXNzb3JdID09PSAtMSkge1xuICAgICAgICBjZW50ZXJYID0gY2VudGVyLnggfHwgZGVmYXVsdENlbnRlclg7XG4gICAgICAgIGNlbnRlclkgPSBjZW50ZXIueSB8fCBkZWZhdWx0Q2VudGVyWTtcbiAgICAgICAgLy8gICAgLS0tPlxuICAgICAgICAvLyAgICB8XG4gICAgICAgIC8vID4tLS1cbiAgICAgICAgY29uc3QgdmVydGljYWxTcGxpdCA9IFtcbiAgICAgICAgICAgIHsgeDogY2VudGVyWCwgeTogc291cmNlR2FwcGVkLnkgfSxcbiAgICAgICAgICAgIHsgeDogY2VudGVyWCwgeTogdGFyZ2V0R2FwcGVkLnkgfSxcbiAgICAgICAgXTtcbiAgICAgICAgLy8gICAgfFxuICAgICAgICAvLyAgLS0tXG4gICAgICAgIC8vICB8XG4gICAgICAgIGNvbnN0IGhvcml6b250YWxTcGxpdCA9IFtcbiAgICAgICAgICAgIHsgeDogc291cmNlR2FwcGVkLngsIHk6IGNlbnRlclkgfSxcbiAgICAgICAgICAgIHsgeDogdGFyZ2V0R2FwcGVkLngsIHk6IGNlbnRlclkgfSxcbiAgICAgICAgXTtcbiAgICAgICAgaWYgKHNvdXJjZURpcltkaXJBY2Nlc3Nvcl0gPT09IGN1cnJEaXIpIHtcbiAgICAgICAgICAgIHBvaW50cyA9IGRpckFjY2Vzc29yID09PSAneCcgPyB2ZXJ0aWNhbFNwbGl0IDogaG9yaXpvbnRhbFNwbGl0O1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcG9pbnRzID0gZGlyQWNjZXNzb3IgPT09ICd4JyA/IGhvcml6b250YWxTcGxpdCA6IHZlcnRpY2FsU3BsaXQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIC8vIHNvdXJjZVRhcmdldCBtZWFucyB3ZSB0YWtlIHggZnJvbSBzb3VyY2UgYW5kIHkgZnJvbSB0YXJnZXQsIHRhcmdldFNvdXJjZSBpcyB0aGUgb3Bwb3NpdGVcbiAgICAgICAgY29uc3Qgc291cmNlVGFyZ2V0ID0gW3sgeDogc291cmNlR2FwcGVkLngsIHk6IHRhcmdldEdhcHBlZC55IH1dO1xuICAgICAgICBjb25zdCB0YXJnZXRTb3VyY2UgPSBbeyB4OiB0YXJnZXRHYXBwZWQueCwgeTogc291cmNlR2FwcGVkLnkgfV07XG4gICAgICAgIC8vIHRoaXMgaGFuZGxlcyBlZGdlcyB3aXRoIHNhbWUgaGFuZGxlIHBvc2l0aW9uc1xuICAgICAgICBpZiAoZGlyQWNjZXNzb3IgPT09ICd4Jykge1xuICAgICAgICAgICAgcG9pbnRzID0gc291cmNlRGlyLnggPT09IGN1cnJEaXIgPyB0YXJnZXRTb3VyY2UgOiBzb3VyY2VUYXJnZXQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBwb2ludHMgPSBzb3VyY2VEaXIueSA9PT0gY3VyckRpciA/IHNvdXJjZVRhcmdldCA6IHRhcmdldFNvdXJjZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc291cmNlUG9zaXRpb24gPT09IHRhcmdldFBvc2l0aW9uKSB7XG4gICAgICAgICAgICBjb25zdCBkaWZmID0gTWF0aC5hYnMoc291cmNlW2RpckFjY2Vzc29yXSAtIHRhcmdldFtkaXJBY2Nlc3Nvcl0pO1xuICAgICAgICAgICAgLy8gaWYgYW4gZWRnZSBnb2VzIGZyb20gcmlnaHQgdG8gcmlnaHQgZm9yIGV4YW1wbGUgKHNvdXJjZVBvc2l0aW9uID09PSB0YXJnZXRQb3NpdGlvbikgYW5kIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHNvdXJjZS54IGFuZCB0YXJnZXQueCBpcyBsZXNzIHRoYW4gdGhlIG9mZnNldCwgdGhlIGFkZGVkIHBvaW50IGFuZCB0aGUgZ2FwcGVkIHNvdXJjZS90YXJnZXQgd2lsbCBvdmVybGFwLiBUaGlzIGxlYWRzIHRvIGEgd2VpcmQgZWRnZSBwYXRoLiBUbyBhdm9pZCB0aGlzIHdlIGFkZCBhIGdhcE9mZnNldCB0byB0aGUgc291cmNlL3RhcmdldFxuICAgICAgICAgICAgaWYgKGRpZmYgPD0gb2Zmc2V0KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZ2FwT2Zmc2V0ID0gTWF0aC5taW4ob2Zmc2V0IC0gMSwgb2Zmc2V0IC0gZGlmZik7XG4gICAgICAgICAgICAgICAgaWYgKHNvdXJjZURpcltkaXJBY2Nlc3Nvcl0gPT09IGN1cnJEaXIpIHtcbiAgICAgICAgICAgICAgICAgICAgc291cmNlR2FwT2Zmc2V0W2RpckFjY2Vzc29yXSA9IChzb3VyY2VHYXBwZWRbZGlyQWNjZXNzb3JdID4gc291cmNlW2RpckFjY2Vzc29yXSA/IC0xIDogMSkgKiBnYXBPZmZzZXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0YXJnZXRHYXBPZmZzZXRbZGlyQWNjZXNzb3JdID0gKHRhcmdldEdhcHBlZFtkaXJBY2Nlc3Nvcl0gPiB0YXJnZXRbZGlyQWNjZXNzb3JdID8gLTEgOiAxKSAqIGdhcE9mZnNldDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gdGhlc2UgYXJlIGNvbmRpdGlvbnMgZm9yIGhhbmRsaW5nIG1peGVkIGhhbmRsZSBwb3NpdGlvbnMgbGlrZSBSaWdodCAtPiBCb3R0b20gZm9yIGV4YW1wbGVcbiAgICAgICAgaWYgKHNvdXJjZVBvc2l0aW9uICE9PSB0YXJnZXRQb3NpdGlvbikge1xuICAgICAgICAgICAgY29uc3QgZGlyQWNjZXNzb3JPcHBvc2l0ZSA9IGRpckFjY2Vzc29yID09PSAneCcgPyAneScgOiAneCc7XG4gICAgICAgICAgICBjb25zdCBpc1NhbWVEaXIgPSBzb3VyY2VEaXJbZGlyQWNjZXNzb3JdID09PSB0YXJnZXREaXJbZGlyQWNjZXNzb3JPcHBvc2l0ZV07XG4gICAgICAgICAgICBjb25zdCBzb3VyY2VHdFRhcmdldE9wcG8gPSBzb3VyY2VHYXBwZWRbZGlyQWNjZXNzb3JPcHBvc2l0ZV0gPiB0YXJnZXRHYXBwZWRbZGlyQWNjZXNzb3JPcHBvc2l0ZV07XG4gICAgICAgICAgICBjb25zdCBzb3VyY2VMdFRhcmdldE9wcG8gPSBzb3VyY2VHYXBwZWRbZGlyQWNjZXNzb3JPcHBvc2l0ZV0gPCB0YXJnZXRHYXBwZWRbZGlyQWNjZXNzb3JPcHBvc2l0ZV07XG4gICAgICAgICAgICBjb25zdCBmbGlwU291cmNlVGFyZ2V0ID0gKHNvdXJjZURpcltkaXJBY2Nlc3Nvcl0gPT09IDEgJiYgKCghaXNTYW1lRGlyICYmIHNvdXJjZUd0VGFyZ2V0T3BwbykgfHwgKGlzU2FtZURpciAmJiBzb3VyY2VMdFRhcmdldE9wcG8pKSkgfHxcbiAgICAgICAgICAgICAgICAoc291cmNlRGlyW2RpckFjY2Vzc29yXSAhPT0gMSAmJiAoKCFpc1NhbWVEaXIgJiYgc291cmNlTHRUYXJnZXRPcHBvKSB8fCAoaXNTYW1lRGlyICYmIHNvdXJjZUd0VGFyZ2V0T3BwbykpKTtcbiAgICAgICAgICAgIGlmIChmbGlwU291cmNlVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgcG9pbnRzID0gZGlyQWNjZXNzb3IgPT09ICd4JyA/IHNvdXJjZVRhcmdldCA6IHRhcmdldFNvdXJjZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBjb25zdCBzb3VyY2VHYXBQb2ludCA9IHsgeDogc291cmNlR2FwcGVkLnggKyBzb3VyY2VHYXBPZmZzZXQueCwgeTogc291cmNlR2FwcGVkLnkgKyBzb3VyY2VHYXBPZmZzZXQueSB9O1xuICAgICAgICBjb25zdCB0YXJnZXRHYXBQb2ludCA9IHsgeDogdGFyZ2V0R2FwcGVkLnggKyB0YXJnZXRHYXBPZmZzZXQueCwgeTogdGFyZ2V0R2FwcGVkLnkgKyB0YXJnZXRHYXBPZmZzZXQueSB9O1xuICAgICAgICBjb25zdCBtYXhYRGlzdGFuY2UgPSBNYXRoLm1heChNYXRoLmFicyhzb3VyY2VHYXBQb2ludC54IC0gcG9pbnRzWzBdLngpLCBNYXRoLmFicyh0YXJnZXRHYXBQb2ludC54IC0gcG9pbnRzWzBdLngpKTtcbiAgICAgICAgY29uc3QgbWF4WURpc3RhbmNlID0gTWF0aC5tYXgoTWF0aC5hYnMoc291cmNlR2FwUG9pbnQueSAtIHBvaW50c1swXS55KSwgTWF0aC5hYnModGFyZ2V0R2FwUG9pbnQueSAtIHBvaW50c1swXS55KSk7XG4gICAgICAgIC8vIHdlIHdhbnQgdG8gcGxhY2UgdGhlIGxhYmVsIG9uIHRoZSBsb25nZXN0IHNlZ21lbnQgb2YgdGhlIGVkZ2VcbiAgICAgICAgaWYgKG1heFhEaXN0YW5jZSA+PSBtYXhZRGlzdGFuY2UpIHtcbiAgICAgICAgICAgIGNlbnRlclggPSAoc291cmNlR2FwUG9pbnQueCArIHRhcmdldEdhcFBvaW50LngpIC8gMjtcbiAgICAgICAgICAgIGNlbnRlclkgPSBwb2ludHNbMF0ueTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNlbnRlclggPSBwb2ludHNbMF0ueDtcbiAgICAgICAgICAgIGNlbnRlclkgPSAoc291cmNlR2FwUG9pbnQueSArIHRhcmdldEdhcFBvaW50LnkpIC8gMjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBwYXRoUG9pbnRzID0gW1xuICAgICAgICBzb3VyY2UsXG4gICAgICAgIHsgeDogc291cmNlR2FwcGVkLnggKyBzb3VyY2VHYXBPZmZzZXQueCwgeTogc291cmNlR2FwcGVkLnkgKyBzb3VyY2VHYXBPZmZzZXQueSB9LFxuICAgICAgICAuLi5wb2ludHMsXG4gICAgICAgIHsgeDogdGFyZ2V0R2FwcGVkLnggKyB0YXJnZXRHYXBPZmZzZXQueCwgeTogdGFyZ2V0R2FwcGVkLnkgKyB0YXJnZXRHYXBPZmZzZXQueSB9LFxuICAgICAgICB0YXJnZXQsXG4gICAgXTtcbiAgICByZXR1cm4gW3BhdGhQb2ludHMsIGNlbnRlclgsIGNlbnRlclksIGRlZmF1bHRPZmZzZXRYLCBkZWZhdWx0T2Zmc2V0WV07XG59XG5mdW5jdGlvbiBnZXRCZW5kKGEsIGIsIGMsIHNpemUpIHtcbiAgICBjb25zdCBiZW5kU2l6ZSA9IE1hdGgubWluKGRpc3RhbmNlKGEsIGIpIC8gMiwgZGlzdGFuY2UoYiwgYykgLyAyLCBzaXplKTtcbiAgICBjb25zdCB7IHgsIHkgfSA9IGI7XG4gICAgLy8gbm8gYmVuZFxuICAgIGlmICgoYS54ID09PSB4ICYmIHggPT09IGMueCkgfHwgKGEueSA9PT0geSAmJiB5ID09PSBjLnkpKSB7XG4gICAgICAgIHJldHVybiBgTCR7eH0gJHt5fWA7XG4gICAgfVxuICAgIC8vIGZpcnN0IHNlZ21lbnQgaXMgaG9yaXpvbnRhbFxuICAgIGlmIChhLnkgPT09IHkpIHtcbiAgICAgICAgY29uc3QgeERpciA9IGEueCA8IGMueCA/IC0xIDogMTtcbiAgICAgICAgY29uc3QgeURpciA9IGEueSA8IGMueSA/IDEgOiAtMTtcbiAgICAgICAgcmV0dXJuIGBMICR7eCArIGJlbmRTaXplICogeERpcn0sJHt5fVEgJHt4fSwke3l9ICR7eH0sJHt5ICsgYmVuZFNpemUgKiB5RGlyfWA7XG4gICAgfVxuICAgIGNvbnN0IHhEaXIgPSBhLnggPCBjLnggPyAxIDogLTE7XG4gICAgY29uc3QgeURpciA9IGEueSA8IGMueSA/IC0xIDogMTtcbiAgICByZXR1cm4gYEwgJHt4fSwke3kgKyBiZW5kU2l6ZSAqIHlEaXJ9USAke3h9LCR7eX0gJHt4ICsgYmVuZFNpemUgKiB4RGlyfSwke3l9YDtcbn1cbmZ1bmN0aW9uIGdldFNtb290aFN0ZXBQYXRoKHsgc291cmNlWCwgc291cmNlWSwgc291cmNlUG9zaXRpb24gPSBQb3NpdGlvbi5Cb3R0b20sIHRhcmdldFgsIHRhcmdldFksIHRhcmdldFBvc2l0aW9uID0gUG9zaXRpb24uVG9wLCBib3JkZXJSYWRpdXMgPSA1LCBjZW50ZXJYLCBjZW50ZXJZLCBvZmZzZXQgPSAyMCwgfSkge1xuICAgIGNvbnN0IFtwb2ludHMsIGxhYmVsWCwgbGFiZWxZLCBvZmZzZXRYLCBvZmZzZXRZXSA9IGdldFBvaW50cyh7XG4gICAgICAgIHNvdXJjZTogeyB4OiBzb3VyY2VYLCB5OiBzb3VyY2VZIH0sXG4gICAgICAgIHNvdXJjZVBvc2l0aW9uLFxuICAgICAgICB0YXJnZXQ6IHsgeDogdGFyZ2V0WCwgeTogdGFyZ2V0WSB9LFxuICAgICAgICB0YXJnZXRQb3NpdGlvbixcbiAgICAgICAgY2VudGVyOiB7IHg6IGNlbnRlclgsIHk6IGNlbnRlclkgfSxcbiAgICAgICAgb2Zmc2V0LFxuICAgIH0pO1xuICAgIGNvbnN0IHBhdGggPSBwb2ludHMucmVkdWNlKChyZXMsIHAsIGkpID0+IHtcbiAgICAgICAgbGV0IHNlZ21lbnQgPSAnJztcbiAgICAgICAgaWYgKGkgPiAwICYmIGkgPCBwb2ludHMubGVuZ3RoIC0gMSkge1xuICAgICAgICAgICAgc2VnbWVudCA9IGdldEJlbmQocG9pbnRzW2kgLSAxXSwgcCwgcG9pbnRzW2kgKyAxXSwgYm9yZGVyUmFkaXVzKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNlZ21lbnQgPSBgJHtpID09PSAwID8gJ00nIDogJ0wnfSR7cC54fSAke3AueX1gO1xuICAgICAgICB9XG4gICAgICAgIHJlcyArPSBzZWdtZW50O1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH0sICcnKTtcbiAgICByZXR1cm4gW3BhdGgsIGxhYmVsWCwgbGFiZWxZLCBvZmZzZXRYLCBvZmZzZXRZXTtcbn1cbmNvbnN0IFNtb290aFN0ZXBFZGdlID0gbWVtbygoeyBzb3VyY2VYLCBzb3VyY2VZLCB0YXJnZXRYLCB0YXJnZXRZLCBsYWJlbCwgbGFiZWxTdHlsZSwgbGFiZWxTaG93QmcsIGxhYmVsQmdTdHlsZSwgbGFiZWxCZ1BhZGRpbmcsIGxhYmVsQmdCb3JkZXJSYWRpdXMsIHN0eWxlLCBzb3VyY2VQb3NpdGlvbiA9IFBvc2l0aW9uLkJvdHRvbSwgdGFyZ2V0UG9zaXRpb24gPSBQb3NpdGlvbi5Ub3AsIG1hcmtlckVuZCwgbWFya2VyU3RhcnQsIHBhdGhPcHRpb25zLCBpbnRlcmFjdGlvbldpZHRoLCB9KSA9PiB7XG4gICAgY29uc3QgW3BhdGgsIGxhYmVsWCwgbGFiZWxZXSA9IGdldFNtb290aFN0ZXBQYXRoKHtcbiAgICAgICAgc291cmNlWCxcbiAgICAgICAgc291cmNlWSxcbiAgICAgICAgc291cmNlUG9zaXRpb24sXG4gICAgICAgIHRhcmdldFgsXG4gICAgICAgIHRhcmdldFksXG4gICAgICAgIHRhcmdldFBvc2l0aW9uLFxuICAgICAgICBib3JkZXJSYWRpdXM6IHBhdGhPcHRpb25zPy5ib3JkZXJSYWRpdXMsXG4gICAgICAgIG9mZnNldDogcGF0aE9wdGlvbnM/Lm9mZnNldCxcbiAgICB9KTtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoQmFzZUVkZ2UsIHsgcGF0aDogcGF0aCwgbGFiZWxYOiBsYWJlbFgsIGxhYmVsWTogbGFiZWxZLCBsYWJlbDogbGFiZWwsIGxhYmVsU3R5bGU6IGxhYmVsU3R5bGUsIGxhYmVsU2hvd0JnOiBsYWJlbFNob3dCZywgbGFiZWxCZ1N0eWxlOiBsYWJlbEJnU3R5bGUsIGxhYmVsQmdQYWRkaW5nOiBsYWJlbEJnUGFkZGluZywgbGFiZWxCZ0JvcmRlclJhZGl1czogbGFiZWxCZ0JvcmRlclJhZGl1cywgc3R5bGU6IHN0eWxlLCBtYXJrZXJFbmQ6IG1hcmtlckVuZCwgbWFya2VyU3RhcnQ6IG1hcmtlclN0YXJ0LCBpbnRlcmFjdGlvbldpZHRoOiBpbnRlcmFjdGlvbldpZHRoIH0pKTtcbn0pO1xuU21vb3RoU3RlcEVkZ2UuZGlzcGxheU5hbWUgPSAnU21vb3RoU3RlcEVkZ2UnO1xuXG5jb25zdCBTdGVwRWRnZSA9IG1lbW8oKHByb3BzKSA9PiAoUmVhY3QuY3JlYXRlRWxlbWVudChTbW9vdGhTdGVwRWRnZSwgeyAuLi5wcm9wcywgcGF0aE9wdGlvbnM6IHVzZU1lbW8oKCkgPT4gKHsgYm9yZGVyUmFkaXVzOiAwLCBvZmZzZXQ6IHByb3BzLnBhdGhPcHRpb25zPy5vZmZzZXQgfSksIFtwcm9wcy5wYXRoT3B0aW9ucz8ub2Zmc2V0XSkgfSkpKTtcblN0ZXBFZGdlLmRpc3BsYXlOYW1lID0gJ1N0ZXBFZGdlJztcblxuZnVuY3Rpb24gZ2V0U3RyYWlnaHRQYXRoKHsgc291cmNlWCwgc291cmNlWSwgdGFyZ2V0WCwgdGFyZ2V0WSwgfSkge1xuICAgIGNvbnN0IFtsYWJlbFgsIGxhYmVsWSwgb2Zmc2V0WCwgb2Zmc2V0WV0gPSBnZXRFZGdlQ2VudGVyKHtcbiAgICAgICAgc291cmNlWCxcbiAgICAgICAgc291cmNlWSxcbiAgICAgICAgdGFyZ2V0WCxcbiAgICAgICAgdGFyZ2V0WSxcbiAgICB9KTtcbiAgICByZXR1cm4gW2BNICR7c291cmNlWH0sJHtzb3VyY2VZfUwgJHt0YXJnZXRYfSwke3RhcmdldFl9YCwgbGFiZWxYLCBsYWJlbFksIG9mZnNldFgsIG9mZnNldFldO1xufVxuY29uc3QgU3RyYWlnaHRFZGdlID0gbWVtbygoeyBzb3VyY2VYLCBzb3VyY2VZLCB0YXJnZXRYLCB0YXJnZXRZLCBsYWJlbCwgbGFiZWxTdHlsZSwgbGFiZWxTaG93QmcsIGxhYmVsQmdTdHlsZSwgbGFiZWxCZ1BhZGRpbmcsIGxhYmVsQmdCb3JkZXJSYWRpdXMsIHN0eWxlLCBtYXJrZXJFbmQsIG1hcmtlclN0YXJ0LCBpbnRlcmFjdGlvbldpZHRoLCB9KSA9PiB7XG4gICAgY29uc3QgW3BhdGgsIGxhYmVsWCwgbGFiZWxZXSA9IGdldFN0cmFpZ2h0UGF0aCh7IHNvdXJjZVgsIHNvdXJjZVksIHRhcmdldFgsIHRhcmdldFkgfSk7XG4gICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KEJhc2VFZGdlLCB7IHBhdGg6IHBhdGgsIGxhYmVsWDogbGFiZWxYLCBsYWJlbFk6IGxhYmVsWSwgbGFiZWw6IGxhYmVsLCBsYWJlbFN0eWxlOiBsYWJlbFN0eWxlLCBsYWJlbFNob3dCZzogbGFiZWxTaG93QmcsIGxhYmVsQmdTdHlsZTogbGFiZWxCZ1N0eWxlLCBsYWJlbEJnUGFkZGluZzogbGFiZWxCZ1BhZGRpbmcsIGxhYmVsQmdCb3JkZXJSYWRpdXM6IGxhYmVsQmdCb3JkZXJSYWRpdXMsIHN0eWxlOiBzdHlsZSwgbWFya2VyRW5kOiBtYXJrZXJFbmQsIG1hcmtlclN0YXJ0OiBtYXJrZXJTdGFydCwgaW50ZXJhY3Rpb25XaWR0aDogaW50ZXJhY3Rpb25XaWR0aCB9KSk7XG59KTtcblN0cmFpZ2h0RWRnZS5kaXNwbGF5TmFtZSA9ICdTdHJhaWdodEVkZ2UnO1xuXG5mdW5jdGlvbiBjYWxjdWxhdGVDb250cm9sT2Zmc2V0KGRpc3RhbmNlLCBjdXJ2YXR1cmUpIHtcbiAgICBpZiAoZGlzdGFuY2UgPj0gMCkge1xuICAgICAgICByZXR1cm4gMC41ICogZGlzdGFuY2U7XG4gICAgfVxuICAgIHJldHVybiBjdXJ2YXR1cmUgKiAyNSAqIE1hdGguc3FydCgtZGlzdGFuY2UpO1xufVxuZnVuY3Rpb24gZ2V0Q29udHJvbFdpdGhDdXJ2YXR1cmUoeyBwb3MsIHgxLCB5MSwgeDIsIHkyLCBjIH0pIHtcbiAgICBzd2l0Y2ggKHBvcykge1xuICAgICAgICBjYXNlIFBvc2l0aW9uLkxlZnQ6XG4gICAgICAgICAgICByZXR1cm4gW3gxIC0gY2FsY3VsYXRlQ29udHJvbE9mZnNldCh4MSAtIHgyLCBjKSwgeTFdO1xuICAgICAgICBjYXNlIFBvc2l0aW9uLlJpZ2h0OlxuICAgICAgICAgICAgcmV0dXJuIFt4MSArIGNhbGN1bGF0ZUNvbnRyb2xPZmZzZXQoeDIgLSB4MSwgYyksIHkxXTtcbiAgICAgICAgY2FzZSBQb3NpdGlvbi5Ub3A6XG4gICAgICAgICAgICByZXR1cm4gW3gxLCB5MSAtIGNhbGN1bGF0ZUNvbnRyb2xPZmZzZXQoeTEgLSB5MiwgYyldO1xuICAgICAgICBjYXNlIFBvc2l0aW9uLkJvdHRvbTpcbiAgICAgICAgICAgIHJldHVybiBbeDEsIHkxICsgY2FsY3VsYXRlQ29udHJvbE9mZnNldCh5MiAtIHkxLCBjKV07XG4gICAgfVxufVxuZnVuY3Rpb24gZ2V0QmV6aWVyUGF0aCh7IHNvdXJjZVgsIHNvdXJjZVksIHNvdXJjZVBvc2l0aW9uID0gUG9zaXRpb24uQm90dG9tLCB0YXJnZXRYLCB0YXJnZXRZLCB0YXJnZXRQb3NpdGlvbiA9IFBvc2l0aW9uLlRvcCwgY3VydmF0dXJlID0gMC4yNSwgfSkge1xuICAgIGNvbnN0IFtzb3VyY2VDb250cm9sWCwgc291cmNlQ29udHJvbFldID0gZ2V0Q29udHJvbFdpdGhDdXJ2YXR1cmUoe1xuICAgICAgICBwb3M6IHNvdXJjZVBvc2l0aW9uLFxuICAgICAgICB4MTogc291cmNlWCxcbiAgICAgICAgeTE6IHNvdXJjZVksXG4gICAgICAgIHgyOiB0YXJnZXRYLFxuICAgICAgICB5MjogdGFyZ2V0WSxcbiAgICAgICAgYzogY3VydmF0dXJlLFxuICAgIH0pO1xuICAgIGNvbnN0IFt0YXJnZXRDb250cm9sWCwgdGFyZ2V0Q29udHJvbFldID0gZ2V0Q29udHJvbFdpdGhDdXJ2YXR1cmUoe1xuICAgICAgICBwb3M6IHRhcmdldFBvc2l0aW9uLFxuICAgICAgICB4MTogdGFyZ2V0WCxcbiAgICAgICAgeTE6IHRhcmdldFksXG4gICAgICAgIHgyOiBzb3VyY2VYLFxuICAgICAgICB5Mjogc291cmNlWSxcbiAgICAgICAgYzogY3VydmF0dXJlLFxuICAgIH0pO1xuICAgIGNvbnN0IFtsYWJlbFgsIGxhYmVsWSwgb2Zmc2V0WCwgb2Zmc2V0WV0gPSBnZXRCZXppZXJFZGdlQ2VudGVyKHtcbiAgICAgICAgc291cmNlWCxcbiAgICAgICAgc291cmNlWSxcbiAgICAgICAgdGFyZ2V0WCxcbiAgICAgICAgdGFyZ2V0WSxcbiAgICAgICAgc291cmNlQ29udHJvbFgsXG4gICAgICAgIHNvdXJjZUNvbnRyb2xZLFxuICAgICAgICB0YXJnZXRDb250cm9sWCxcbiAgICAgICAgdGFyZ2V0Q29udHJvbFksXG4gICAgfSk7XG4gICAgcmV0dXJuIFtcbiAgICAgICAgYE0ke3NvdXJjZVh9LCR7c291cmNlWX0gQyR7c291cmNlQ29udHJvbFh9LCR7c291cmNlQ29udHJvbFl9ICR7dGFyZ2V0Q29udHJvbFh9LCR7dGFyZ2V0Q29udHJvbFl9ICR7dGFyZ2V0WH0sJHt0YXJnZXRZfWAsXG4gICAgICAgIGxhYmVsWCxcbiAgICAgICAgbGFiZWxZLFxuICAgICAgICBvZmZzZXRYLFxuICAgICAgICBvZmZzZXRZLFxuICAgIF07XG59XG5jb25zdCBCZXppZXJFZGdlID0gbWVtbygoeyBzb3VyY2VYLCBzb3VyY2VZLCB0YXJnZXRYLCB0YXJnZXRZLCBzb3VyY2VQb3NpdGlvbiA9IFBvc2l0aW9uLkJvdHRvbSwgdGFyZ2V0UG9zaXRpb24gPSBQb3NpdGlvbi5Ub3AsIGxhYmVsLCBsYWJlbFN0eWxlLCBsYWJlbFNob3dCZywgbGFiZWxCZ1N0eWxlLCBsYWJlbEJnUGFkZGluZywgbGFiZWxCZ0JvcmRlclJhZGl1cywgc3R5bGUsIG1hcmtlckVuZCwgbWFya2VyU3RhcnQsIHBhdGhPcHRpb25zLCBpbnRlcmFjdGlvbldpZHRoLCB9KSA9PiB7XG4gICAgY29uc3QgW3BhdGgsIGxhYmVsWCwgbGFiZWxZXSA9IGdldEJlemllclBhdGgoe1xuICAgICAgICBzb3VyY2VYLFxuICAgICAgICBzb3VyY2VZLFxuICAgICAgICBzb3VyY2VQb3NpdGlvbixcbiAgICAgICAgdGFyZ2V0WCxcbiAgICAgICAgdGFyZ2V0WSxcbiAgICAgICAgdGFyZ2V0UG9zaXRpb24sXG4gICAgICAgIGN1cnZhdHVyZTogcGF0aE9wdGlvbnM/LmN1cnZhdHVyZSxcbiAgICB9KTtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoQmFzZUVkZ2UsIHsgcGF0aDogcGF0aCwgbGFiZWxYOiBsYWJlbFgsIGxhYmVsWTogbGFiZWxZLCBsYWJlbDogbGFiZWwsIGxhYmVsU3R5bGU6IGxhYmVsU3R5bGUsIGxhYmVsU2hvd0JnOiBsYWJlbFNob3dCZywgbGFiZWxCZ1N0eWxlOiBsYWJlbEJnU3R5bGUsIGxhYmVsQmdQYWRkaW5nOiBsYWJlbEJnUGFkZGluZywgbGFiZWxCZ0JvcmRlclJhZGl1czogbGFiZWxCZ0JvcmRlclJhZGl1cywgc3R5bGU6IHN0eWxlLCBtYXJrZXJFbmQ6IG1hcmtlckVuZCwgbWFya2VyU3RhcnQ6IG1hcmtlclN0YXJ0LCBpbnRlcmFjdGlvbldpZHRoOiBpbnRlcmFjdGlvbldpZHRoIH0pKTtcbn0pO1xuQmV6aWVyRWRnZS5kaXNwbGF5TmFtZSA9ICdCZXppZXJFZGdlJztcblxuY29uc3QgTm9kZUlkQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQobnVsbCk7XG5jb25zdCBQcm92aWRlciA9IE5vZGVJZENvbnRleHQuUHJvdmlkZXI7XG5Ob2RlSWRDb250ZXh0LkNvbnN1bWVyO1xuY29uc3QgdXNlTm9kZUlkID0gKCkgPT4ge1xuICAgIGNvbnN0IG5vZGVJZCA9IHVzZUNvbnRleHQoTm9kZUlkQ29udGV4dCk7XG4gICAgcmV0dXJuIG5vZGVJZDtcbn07XG5cbmNvbnN0IGlzRWRnZSA9IChlbGVtZW50KSA9PiAnaWQnIGluIGVsZW1lbnQgJiYgJ3NvdXJjZScgaW4gZWxlbWVudCAmJiAndGFyZ2V0JyBpbiBlbGVtZW50O1xuY29uc3QgaXNOb2RlID0gKGVsZW1lbnQpID0+ICdpZCcgaW4gZWxlbWVudCAmJiAhKCdzb3VyY2UnIGluIGVsZW1lbnQpICYmICEoJ3RhcmdldCcgaW4gZWxlbWVudCk7XG5jb25zdCBnZXRPdXRnb2VycyA9IChub2RlLCBub2RlcywgZWRnZXMpID0+IHtcbiAgICBpZiAoIWlzTm9kZShub2RlKSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGNvbnN0IG91dGdvZXJJZHMgPSBlZGdlcy5maWx0ZXIoKGUpID0+IGUuc291cmNlID09PSBub2RlLmlkKS5tYXAoKGUpID0+IGUudGFyZ2V0KTtcbiAgICByZXR1cm4gbm9kZXMuZmlsdGVyKChuKSA9PiBvdXRnb2VySWRzLmluY2x1ZGVzKG4uaWQpKTtcbn07XG5jb25zdCBnZXRJbmNvbWVycyA9IChub2RlLCBub2RlcywgZWRnZXMpID0+IHtcbiAgICBpZiAoIWlzTm9kZShub2RlKSkge1xuICAgICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGNvbnN0IGluY29tZXJzSWRzID0gZWRnZXMuZmlsdGVyKChlKSA9PiBlLnRhcmdldCA9PT0gbm9kZS5pZCkubWFwKChlKSA9PiBlLnNvdXJjZSk7XG4gICAgcmV0dXJuIG5vZGVzLmZpbHRlcigobikgPT4gaW5jb21lcnNJZHMuaW5jbHVkZXMobi5pZCkpO1xufTtcbmNvbnN0IGdldEVkZ2VJZCA9ICh7IHNvdXJjZSwgc291cmNlSGFuZGxlLCB0YXJnZXQsIHRhcmdldEhhbmRsZSB9KSA9PiBgcmVhY3RmbG93X19lZGdlLSR7c291cmNlfSR7c291cmNlSGFuZGxlIHx8ICcnfS0ke3RhcmdldH0ke3RhcmdldEhhbmRsZSB8fCAnJ31gO1xuY29uc3QgZ2V0TWFya2VySWQgPSAobWFya2VyLCByZklkKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBtYXJrZXIgPT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgIHJldHVybiAnJztcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBtYXJrZXIgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHJldHVybiBtYXJrZXI7XG4gICAgfVxuICAgIGNvbnN0IGlkUHJlZml4ID0gcmZJZCA/IGAke3JmSWR9X19gIDogJyc7XG4gICAgcmV0dXJuIGAke2lkUHJlZml4fSR7T2JqZWN0LmtleXMobWFya2VyKVxuICAgICAgICAuc29ydCgpXG4gICAgICAgIC5tYXAoKGtleSkgPT4gYCR7a2V5fT0ke21hcmtlcltrZXldfWApXG4gICAgICAgIC5qb2luKCcmJyl9YDtcbn07XG5jb25zdCBjb25uZWN0aW9uRXhpc3RzID0gKGVkZ2UsIGVkZ2VzKSA9PiB7XG4gICAgcmV0dXJuIGVkZ2VzLnNvbWUoKGVsKSA9PiBlbC5zb3VyY2UgPT09IGVkZ2Uuc291cmNlICYmXG4gICAgICAgIGVsLnRhcmdldCA9PT0gZWRnZS50YXJnZXQgJiZcbiAgICAgICAgKGVsLnNvdXJjZUhhbmRsZSA9PT0gZWRnZS5zb3VyY2VIYW5kbGUgfHwgKCFlbC5zb3VyY2VIYW5kbGUgJiYgIWVkZ2Uuc291cmNlSGFuZGxlKSkgJiZcbiAgICAgICAgKGVsLnRhcmdldEhhbmRsZSA9PT0gZWRnZS50YXJnZXRIYW5kbGUgfHwgKCFlbC50YXJnZXRIYW5kbGUgJiYgIWVkZ2UudGFyZ2V0SGFuZGxlKSkpO1xufTtcbmNvbnN0IGFkZEVkZ2UgPSAoZWRnZVBhcmFtcywgZWRnZXMpID0+IHtcbiAgICBpZiAoIWVkZ2VQYXJhbXMuc291cmNlIHx8ICFlZGdlUGFyYW1zLnRhcmdldCkge1xuICAgICAgICBkZXZXYXJuKCcwMDYnLCBlcnJvck1lc3NhZ2VzWydlcnJvcjAwNiddKCkpO1xuICAgICAgICByZXR1cm4gZWRnZXM7XG4gICAgfVxuICAgIGxldCBlZGdlO1xuICAgIGlmIChpc0VkZ2UoZWRnZVBhcmFtcykpIHtcbiAgICAgICAgZWRnZSA9IHsgLi4uZWRnZVBhcmFtcyB9O1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZWRnZSA9IHtcbiAgICAgICAgICAgIC4uLmVkZ2VQYXJhbXMsXG4gICAgICAgICAgICBpZDogZ2V0RWRnZUlkKGVkZ2VQYXJhbXMpLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBpZiAoY29ubmVjdGlvbkV4aXN0cyhlZGdlLCBlZGdlcykpIHtcbiAgICAgICAgcmV0dXJuIGVkZ2VzO1xuICAgIH1cbiAgICByZXR1cm4gZWRnZXMuY29uY2F0KGVkZ2UpO1xufTtcbmNvbnN0IHVwZGF0ZUVkZ2UgPSAob2xkRWRnZSwgbmV3Q29ubmVjdGlvbiwgZWRnZXMsIG9wdGlvbnMgPSB7IHNob3VsZFJlcGxhY2VJZDogdHJ1ZSB9KSA9PiB7XG4gICAgY29uc3QgeyBpZDogb2xkRWRnZUlkLCAuLi5yZXN0IH0gPSBvbGRFZGdlO1xuICAgIGlmICghbmV3Q29ubmVjdGlvbi5zb3VyY2UgfHwgIW5ld0Nvbm5lY3Rpb24udGFyZ2V0KSB7XG4gICAgICAgIGRldldhcm4oJzAwNicsIGVycm9yTWVzc2FnZXNbJ2Vycm9yMDA2J10oKSk7XG4gICAgICAgIHJldHVybiBlZGdlcztcbiAgICB9XG4gICAgY29uc3QgZm91bmRFZGdlID0gZWRnZXMuZmluZCgoZSkgPT4gZS5pZCA9PT0gb2xkRWRnZUlkKTtcbiAgICBpZiAoIWZvdW5kRWRnZSkge1xuICAgICAgICBkZXZXYXJuKCcwMDcnLCBlcnJvck1lc3NhZ2VzWydlcnJvcjAwNyddKG9sZEVkZ2VJZCkpO1xuICAgICAgICByZXR1cm4gZWRnZXM7XG4gICAgfVxuICAgIC8vIFJlbW92ZSBvbGQgZWRnZSBhbmQgY3JlYXRlIHRoZSBuZXcgZWRnZSB3aXRoIHBhcmFtZXRlcnMgb2Ygb2xkIGVkZ2UuXG4gICAgY29uc3QgZWRnZSA9IHtcbiAgICAgICAgLi4ucmVzdCxcbiAgICAgICAgaWQ6IG9wdGlvbnMuc2hvdWxkUmVwbGFjZUlkID8gZ2V0RWRnZUlkKG5ld0Nvbm5lY3Rpb24pIDogb2xkRWRnZUlkLFxuICAgICAgICBzb3VyY2U6IG5ld0Nvbm5lY3Rpb24uc291cmNlLFxuICAgICAgICB0YXJnZXQ6IG5ld0Nvbm5lY3Rpb24udGFyZ2V0LFxuICAgICAgICBzb3VyY2VIYW5kbGU6IG5ld0Nvbm5lY3Rpb24uc291cmNlSGFuZGxlLFxuICAgICAgICB0YXJnZXRIYW5kbGU6IG5ld0Nvbm5lY3Rpb24udGFyZ2V0SGFuZGxlLFxuICAgIH07XG4gICAgcmV0dXJuIGVkZ2VzLmZpbHRlcigoZSkgPT4gZS5pZCAhPT0gb2xkRWRnZUlkKS5jb25jYXQoZWRnZSk7XG59O1xuY29uc3QgcG9pbnRUb1JlbmRlcmVyUG9pbnQgPSAoeyB4LCB5IH0sIFt0eCwgdHksIHRTY2FsZV0sIHNuYXBUb0dyaWQsIFtzbmFwWCwgc25hcFldKSA9PiB7XG4gICAgY29uc3QgcG9zaXRpb24gPSB7XG4gICAgICAgIHg6ICh4IC0gdHgpIC8gdFNjYWxlLFxuICAgICAgICB5OiAoeSAtIHR5KSAvIHRTY2FsZSxcbiAgICB9O1xuICAgIGlmIChzbmFwVG9HcmlkKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4OiBzbmFwWCAqIE1hdGgucm91bmQocG9zaXRpb24ueCAvIHNuYXBYKSxcbiAgICAgICAgICAgIHk6IHNuYXBZICogTWF0aC5yb3VuZChwb3NpdGlvbi55IC8gc25hcFkpLFxuICAgICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4gcG9zaXRpb247XG59O1xuY29uc3QgcmVuZGVyZXJQb2ludFRvUG9pbnQgPSAoeyB4LCB5IH0sIFt0eCwgdHksIHRTY2FsZV0pID0+IHtcbiAgICByZXR1cm4ge1xuICAgICAgICB4OiB4ICogdFNjYWxlICsgdHgsXG4gICAgICAgIHk6IHkgKiB0U2NhbGUgKyB0eSxcbiAgICB9O1xufTtcbmNvbnN0IGdldE5vZGVQb3NpdGlvbldpdGhPcmlnaW4gPSAobm9kZSwgbm9kZU9yaWdpbiA9IFswLCAwXSkgPT4ge1xuICAgIGlmICghbm9kZSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICBwb3NpdGlvbkFic29sdXRlOiB7XG4gICAgICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgICAgICB5OiAwLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9XG4gICAgY29uc3Qgb2Zmc2V0WCA9IChub2RlLndpZHRoID8/IDApICogbm9kZU9yaWdpblswXTtcbiAgICBjb25zdCBvZmZzZXRZID0gKG5vZGUuaGVpZ2h0ID8/IDApICogbm9kZU9yaWdpblsxXTtcbiAgICBjb25zdCBwb3NpdGlvbiA9IHtcbiAgICAgICAgeDogbm9kZS5wb3NpdGlvbi54IC0gb2Zmc2V0WCxcbiAgICAgICAgeTogbm9kZS5wb3NpdGlvbi55IC0gb2Zmc2V0WSxcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICAgIC4uLnBvc2l0aW9uLFxuICAgICAgICBwb3NpdGlvbkFic29sdXRlOiBub2RlLnBvc2l0aW9uQWJzb2x1dGVcbiAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgIHg6IG5vZGUucG9zaXRpb25BYnNvbHV0ZS54IC0gb2Zmc2V0WCxcbiAgICAgICAgICAgICAgICB5OiBub2RlLnBvc2l0aW9uQWJzb2x1dGUueSAtIG9mZnNldFksXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICA6IHBvc2l0aW9uLFxuICAgIH07XG59O1xuY29uc3QgZ2V0Tm9kZXNCb3VuZHMgPSAobm9kZXMsIG5vZGVPcmlnaW4gPSBbMCwgMF0pID0+IHtcbiAgICBpZiAobm9kZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJldHVybiB7IHg6IDAsIHk6IDAsIHdpZHRoOiAwLCBoZWlnaHQ6IDAgfTtcbiAgICB9XG4gICAgY29uc3QgYm94ID0gbm9kZXMucmVkdWNlKChjdXJyQm94LCBub2RlKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgeCwgeSB9ID0gZ2V0Tm9kZVBvc2l0aW9uV2l0aE9yaWdpbihub2RlLCBub2RlT3JpZ2luKS5wb3NpdGlvbkFic29sdXRlO1xuICAgICAgICByZXR1cm4gZ2V0Qm91bmRzT2ZCb3hlcyhjdXJyQm94LCByZWN0VG9Cb3goe1xuICAgICAgICAgICAgeCxcbiAgICAgICAgICAgIHksXG4gICAgICAgICAgICB3aWR0aDogbm9kZS53aWR0aCB8fCAwLFxuICAgICAgICAgICAgaGVpZ2h0OiBub2RlLmhlaWdodCB8fCAwLFxuICAgICAgICB9KSk7XG4gICAgfSwgeyB4OiBJbmZpbml0eSwgeTogSW5maW5pdHksIHgyOiAtSW5maW5pdHksIHkyOiAtSW5maW5pdHkgfSk7XG4gICAgcmV0dXJuIGJveFRvUmVjdChib3gpO1xufTtcbi8vIEBkZXByZWNhdGVkIFVzZSBgZ2V0Tm9kZXNCb3VuZHNgLlxuY29uc3QgZ2V0UmVjdE9mTm9kZXMgPSAobm9kZXMsIG5vZGVPcmlnaW4gPSBbMCwgMF0pID0+IHtcbiAgICBjb25zb2xlLndhcm4oJ1tERVBSRUNBVEVEXSBgZ2V0UmVjdE9mTm9kZXNgIGlzIGRlcHJlY2F0ZWQuIEluc3RlYWQgdXNlIGBnZXROb2Rlc0JvdW5kc2AgaHR0cHM6Ly9yZWFjdGZsb3cuZGV2L2FwaS1yZWZlcmVuY2UvdXRpbHMvZ2V0LW5vZGVzLWJvdW5kcy4nKTtcbiAgICByZXR1cm4gZ2V0Tm9kZXNCb3VuZHMobm9kZXMsIG5vZGVPcmlnaW4pO1xufTtcbmNvbnN0IGdldE5vZGVzSW5zaWRlID0gKG5vZGVJbnRlcm5hbHMsIHJlY3QsIFt0eCwgdHksIHRTY2FsZV0gPSBbMCwgMCwgMV0sIHBhcnRpYWxseSA9IGZhbHNlLCBcbi8vIHNldCBleGNsdWRlTm9uU2VsZWN0YWJsZU5vZGVzIGlmIHlvdSB3YW50IHRvIHBheSBhdHRlbnRpb24gdG8gdGhlIG5vZGVzIFwic2VsZWN0YWJsZVwiIGF0dHJpYnV0ZVxuZXhjbHVkZU5vblNlbGVjdGFibGVOb2RlcyA9IGZhbHNlLCBub2RlT3JpZ2luID0gWzAsIDBdKSA9PiB7XG4gICAgY29uc3QgcGFuZVJlY3QgPSB7XG4gICAgICAgIHg6IChyZWN0LnggLSB0eCkgLyB0U2NhbGUsXG4gICAgICAgIHk6IChyZWN0LnkgLSB0eSkgLyB0U2NhbGUsXG4gICAgICAgIHdpZHRoOiByZWN0LndpZHRoIC8gdFNjYWxlLFxuICAgICAgICBoZWlnaHQ6IHJlY3QuaGVpZ2h0IC8gdFNjYWxlLFxuICAgIH07XG4gICAgY29uc3QgdmlzaWJsZU5vZGVzID0gW107XG4gICAgbm9kZUludGVybmFscy5mb3JFYWNoKChub2RlKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCwgc2VsZWN0YWJsZSA9IHRydWUsIGhpZGRlbiA9IGZhbHNlIH0gPSBub2RlO1xuICAgICAgICBpZiAoKGV4Y2x1ZGVOb25TZWxlY3RhYmxlTm9kZXMgJiYgIXNlbGVjdGFibGUpIHx8IGhpZGRlbikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHsgcG9zaXRpb25BYnNvbHV0ZSB9ID0gZ2V0Tm9kZVBvc2l0aW9uV2l0aE9yaWdpbihub2RlLCBub2RlT3JpZ2luKTtcbiAgICAgICAgY29uc3Qgbm9kZVJlY3QgPSB7XG4gICAgICAgICAgICB4OiBwb3NpdGlvbkFic29sdXRlLngsXG4gICAgICAgICAgICB5OiBwb3NpdGlvbkFic29sdXRlLnksXG4gICAgICAgICAgICB3aWR0aDogd2lkdGggfHwgMCxcbiAgICAgICAgICAgIGhlaWdodDogaGVpZ2h0IHx8IDAsXG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IG92ZXJsYXBwaW5nQXJlYSA9IGdldE92ZXJsYXBwaW5nQXJlYShwYW5lUmVjdCwgbm9kZVJlY3QpO1xuICAgICAgICBjb25zdCBub3RJbml0aWFsaXplZCA9IHR5cGVvZiB3aWR0aCA9PT0gJ3VuZGVmaW5lZCcgfHwgdHlwZW9mIGhlaWdodCA9PT0gJ3VuZGVmaW5lZCcgfHwgd2lkdGggPT09IG51bGwgfHwgaGVpZ2h0ID09PSBudWxsO1xuICAgICAgICBjb25zdCBwYXJ0aWFsbHlWaXNpYmxlID0gcGFydGlhbGx5ICYmIG92ZXJsYXBwaW5nQXJlYSA+IDA7XG4gICAgICAgIGNvbnN0IGFyZWEgPSAod2lkdGggfHwgMCkgKiAoaGVpZ2h0IHx8IDApO1xuICAgICAgICBjb25zdCBpc1Zpc2libGUgPSBub3RJbml0aWFsaXplZCB8fCBwYXJ0aWFsbHlWaXNpYmxlIHx8IG92ZXJsYXBwaW5nQXJlYSA+PSBhcmVhO1xuICAgICAgICBpZiAoaXNWaXNpYmxlIHx8IG5vZGUuZHJhZ2dpbmcpIHtcbiAgICAgICAgICAgIHZpc2libGVOb2Rlcy5wdXNoKG5vZGUpO1xuICAgICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHZpc2libGVOb2Rlcztcbn07XG5jb25zdCBnZXRDb25uZWN0ZWRFZGdlcyA9IChub2RlcywgZWRnZXMpID0+IHtcbiAgICBjb25zdCBub2RlSWRzID0gbm9kZXMubWFwKChub2RlKSA9PiBub2RlLmlkKTtcbiAgICByZXR1cm4gZWRnZXMuZmlsdGVyKChlZGdlKSA9PiBub2RlSWRzLmluY2x1ZGVzKGVkZ2Uuc291cmNlKSB8fCBub2RlSWRzLmluY2x1ZGVzKGVkZ2UudGFyZ2V0KSk7XG59O1xuLy8gQGRlcHJlY2F0ZWQgVXNlIGBnZXRWaWV3cG9ydEZvckJvdW5kc2AuXG5jb25zdCBnZXRUcmFuc2Zvcm1Gb3JCb3VuZHMgPSAoYm91bmRzLCB3aWR0aCwgaGVpZ2h0LCBtaW5ab29tLCBtYXhab29tLCBwYWRkaW5nID0gMC4xKSA9PiB7XG4gICAgY29uc3QgeyB4LCB5LCB6b29tIH0gPSBnZXRWaWV3cG9ydEZvckJvdW5kcyhib3VuZHMsIHdpZHRoLCBoZWlnaHQsIG1pblpvb20sIG1heFpvb20sIHBhZGRpbmcpO1xuICAgIGNvbnNvbGUud2FybignW0RFUFJFQ0FURURdIGBnZXRUcmFuc2Zvcm1Gb3JCb3VuZHNgIGlzIGRlcHJlY2F0ZWQuIEluc3RlYWQgdXNlIGBnZXRWaWV3cG9ydEZvckJvdW5kc2AuIEJld2FyZSB0aGF0IHRoZSByZXR1cm4gdmFsdWUgaXMgdHlwZSBWaWV3cG9ydCAoYHsgeDogbnVtYmVyLCB5OiBudW1iZXIsIHpvb206IG51bWJlciB9YCkgaW5zdGVhZCBvZiBUcmFuc2Zvcm0gKGBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl1gKS4gaHR0cHM6Ly9yZWFjdGZsb3cuZGV2L2FwaS1yZWZlcmVuY2UvdXRpbHMvZ2V0LXZpZXdwb3J0LWZvci1ib3VuZHMnKTtcbiAgICByZXR1cm4gW3gsIHksIHpvb21dO1xufTtcbmNvbnN0IGdldFZpZXdwb3J0Rm9yQm91bmRzID0gKGJvdW5kcywgd2lkdGgsIGhlaWdodCwgbWluWm9vbSwgbWF4Wm9vbSwgcGFkZGluZyA9IDAuMSkgPT4ge1xuICAgIGNvbnN0IHhab29tID0gd2lkdGggLyAoYm91bmRzLndpZHRoICogKDEgKyBwYWRkaW5nKSk7XG4gICAgY29uc3QgeVpvb20gPSBoZWlnaHQgLyAoYm91bmRzLmhlaWdodCAqICgxICsgcGFkZGluZykpO1xuICAgIGNvbnN0IHpvb20gPSBNYXRoLm1pbih4Wm9vbSwgeVpvb20pO1xuICAgIGNvbnN0IGNsYW1wZWRab29tID0gY2xhbXAoem9vbSwgbWluWm9vbSwgbWF4Wm9vbSk7XG4gICAgY29uc3QgYm91bmRzQ2VudGVyWCA9IGJvdW5kcy54ICsgYm91bmRzLndpZHRoIC8gMjtcbiAgICBjb25zdCBib3VuZHNDZW50ZXJZID0gYm91bmRzLnkgKyBib3VuZHMuaGVpZ2h0IC8gMjtcbiAgICBjb25zdCB4ID0gd2lkdGggLyAyIC0gYm91bmRzQ2VudGVyWCAqIGNsYW1wZWRab29tO1xuICAgIGNvbnN0IHkgPSBoZWlnaHQgLyAyIC0gYm91bmRzQ2VudGVyWSAqIGNsYW1wZWRab29tO1xuICAgIHJldHVybiB7IHgsIHksIHpvb206IGNsYW1wZWRab29tIH07XG59O1xuY29uc3QgZ2V0RDNUcmFuc2l0aW9uID0gKHNlbGVjdGlvbiwgZHVyYXRpb24gPSAwKSA9PiB7XG4gICAgcmV0dXJuIHNlbGVjdGlvbi50cmFuc2l0aW9uKCkuZHVyYXRpb24oZHVyYXRpb24pO1xufTtcblxuLy8gdGhpcyBmdW5jdGlvbnMgY29sbGVjdHMgYWxsIGhhbmRsZXMgYW5kIGFkZHMgYW4gYWJzb2x1dGUgcG9zaXRpb25cbi8vIHNvIHRoYXQgd2UgY2FuIGxhdGVyIGZpbmQgdGhlIGNsb3Nlc3QgaGFuZGxlIHRvIHRoZSBtb3VzZSBwb3NpdGlvblxuZnVuY3Rpb24gZ2V0SGFuZGxlcyhub2RlLCBoYW5kbGVCb3VuZHMsIHR5cGUsIGN1cnJlbnRIYW5kbGUpIHtcbiAgICByZXR1cm4gKGhhbmRsZUJvdW5kc1t0eXBlXSB8fCBbXSkucmVkdWNlKChyZXMsIGgpID0+IHtcbiAgICAgICAgaWYgKGAke25vZGUuaWR9LSR7aC5pZH0tJHt0eXBlfWAgIT09IGN1cnJlbnRIYW5kbGUpIHtcbiAgICAgICAgICAgIHJlcy5wdXNoKHtcbiAgICAgICAgICAgICAgICBpZDogaC5pZCB8fCBudWxsLFxuICAgICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICAgICAgbm9kZUlkOiBub2RlLmlkLFxuICAgICAgICAgICAgICAgIHg6IChub2RlLnBvc2l0aW9uQWJzb2x1dGU/LnggPz8gMCkgKyBoLnggKyBoLndpZHRoIC8gMixcbiAgICAgICAgICAgICAgICB5OiAobm9kZS5wb3NpdGlvbkFic29sdXRlPy55ID8/IDApICsgaC55ICsgaC5oZWlnaHQgLyAyLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9LCBbXSk7XG59XG5mdW5jdGlvbiBnZXRDbG9zZXN0SGFuZGxlKGV2ZW50LCBkb2MsIHBvcywgY29ubmVjdGlvblJhZGl1cywgaGFuZGxlcywgdmFsaWRhdG9yKSB7XG4gICAgLy8gd2UgYWx3YXlzIHdhbnQgdG8gcHJpb3JpdGl6ZSB0aGUgaGFuZGxlIGJlbG93IHRoZSBtb3VzZSBjdXJzb3Igb3ZlciB0aGUgY2xvc2VzdCBkaXN0YW5jZSBoYW5kbGUsXG4gICAgLy8gYmVjYXVzZSBpdCBjb3VsZCBiZSB0aGF0IHRoZSBjZW50ZXIgb2YgYW5vdGhlciBoYW5kbGUgaXMgY2xvc2VyIHRvIHRoZSBtb3VzZSBwb2ludGVyIHRoYW4gdGhlIGhhbmRsZSBiZWxvdyB0aGUgY3Vyc29yXG4gICAgY29uc3QgeyB4LCB5IH0gPSBnZXRFdmVudFBvc2l0aW9uKGV2ZW50KTtcbiAgICBjb25zdCBkb21Ob2RlcyA9IGRvYy5lbGVtZW50c0Zyb21Qb2ludCh4LCB5KTtcbiAgICBjb25zdCBoYW5kbGVCZWxvdyA9IGRvbU5vZGVzLmZpbmQoKGVsKSA9PiBlbC5jbGFzc0xpc3QuY29udGFpbnMoJ3JlYWN0LWZsb3dfX2hhbmRsZScpKTtcbiAgICBpZiAoaGFuZGxlQmVsb3cpIHtcbiAgICAgICAgY29uc3QgaGFuZGxlTm9kZUlkID0gaGFuZGxlQmVsb3cuZ2V0QXR0cmlidXRlKCdkYXRhLW5vZGVpZCcpO1xuICAgICAgICBpZiAoaGFuZGxlTm9kZUlkKSB7XG4gICAgICAgICAgICBjb25zdCBoYW5kbGVUeXBlID0gZ2V0SGFuZGxlVHlwZSh1bmRlZmluZWQsIGhhbmRsZUJlbG93KTtcbiAgICAgICAgICAgIGNvbnN0IGhhbmRsZUlkID0gaGFuZGxlQmVsb3cuZ2V0QXR0cmlidXRlKCdkYXRhLWhhbmRsZWlkJyk7XG4gICAgICAgICAgICBjb25zdCB2YWxpZEhhbmRsZVJlc3VsdCA9IHZhbGlkYXRvcih7IG5vZGVJZDogaGFuZGxlTm9kZUlkLCBpZDogaGFuZGxlSWQsIHR5cGU6IGhhbmRsZVR5cGUgfSk7XG4gICAgICAgICAgICBpZiAodmFsaWRIYW5kbGVSZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBoYW5kbGUgPSBoYW5kbGVzLmZpbmQoKGgpID0+IGgubm9kZUlkID09PSBoYW5kbGVOb2RlSWQgJiYgaC50eXBlID09PSBoYW5kbGVUeXBlICYmIGguaWQgPT09IGhhbmRsZUlkKTtcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgICAgICBoYW5kbGU6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkOiBoYW5kbGVJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6IGhhbmRsZVR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlSWQ6IGhhbmRsZU5vZGVJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHg6IGhhbmRsZT8ueCB8fCBwb3MueCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHk6IGhhbmRsZT8ueSB8fCBwb3MueSxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRIYW5kbGVSZXN1bHQsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICAvLyBpZiB3ZSBjb3VsZG4ndCBmaW5kIGEgaGFuZGxlIGJlbG93IHRoZSBtb3VzZSBjdXJzb3Igd2UgbG9vayBmb3IgdGhlIGNsb3Nlc3QgZGlzdGFuY2UgYmFzZWQgb24gdGhlIGNvbm5lY3Rpb25SYWRpdXNcbiAgICBsZXQgY2xvc2VzdEhhbmRsZXMgPSBbXTtcbiAgICBsZXQgbWluRGlzdGFuY2UgPSBJbmZpbml0eTtcbiAgICBoYW5kbGVzLmZvckVhY2goKGhhbmRsZSkgPT4ge1xuICAgICAgICBjb25zdCBkaXN0YW5jZSA9IE1hdGguc3FydCgoaGFuZGxlLnggLSBwb3MueCkgKiogMiArIChoYW5kbGUueSAtIHBvcy55KSAqKiAyKTtcbiAgICAgICAgaWYgKGRpc3RhbmNlIDw9IGNvbm5lY3Rpb25SYWRpdXMpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbGlkSGFuZGxlUmVzdWx0ID0gdmFsaWRhdG9yKGhhbmRsZSk7XG4gICAgICAgICAgICBpZiAoZGlzdGFuY2UgPD0gbWluRGlzdGFuY2UpIHtcbiAgICAgICAgICAgICAgICBpZiAoZGlzdGFuY2UgPCBtaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgICAgICBjbG9zZXN0SGFuZGxlcyA9IFt7IGhhbmRsZSwgdmFsaWRIYW5kbGVSZXN1bHQgfV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKGRpc3RhbmNlID09PSBtaW5EaXN0YW5jZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyB3aGVuIG11bHRpcGxlIGhhbmRsZXMgYXJlIG9uIHRoZSBzYW1lIGRpc3RhbmNlIHdlIGNvbGxlY3QgYWxsIG9mIHRoZW1cbiAgICAgICAgICAgICAgICAgICAgY2xvc2VzdEhhbmRsZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGUsXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWxpZEhhbmRsZVJlc3VsdCxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1pbkRpc3RhbmNlID0gZGlzdGFuY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAoIWNsb3Nlc3RIYW5kbGVzLmxlbmd0aCkge1xuICAgICAgICByZXR1cm4geyBoYW5kbGU6IG51bGwsIHZhbGlkSGFuZGxlUmVzdWx0OiBkZWZhdWx0UmVzdWx0KCkgfTtcbiAgICB9XG4gICAgaWYgKGNsb3Nlc3RIYW5kbGVzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gY2xvc2VzdEhhbmRsZXNbMF07XG4gICAgfVxuICAgIGNvbnN0IGhhc1ZhbGlkSGFuZGxlID0gY2xvc2VzdEhhbmRsZXMuc29tZSgoeyB2YWxpZEhhbmRsZVJlc3VsdCB9KSA9PiB2YWxpZEhhbmRsZVJlc3VsdC5pc1ZhbGlkKTtcbiAgICBjb25zdCBoYXNUYXJnZXRIYW5kbGUgPSBjbG9zZXN0SGFuZGxlcy5zb21lKCh7IGhhbmRsZSB9KSA9PiBoYW5kbGUudHlwZSA9PT0gJ3RhcmdldCcpO1xuICAgIC8vIGlmIG11bHRpcGxlIGhhbmRsZXMgYXJlIGxheW91dGVkIG9uIHRvcCBvZiBlYWNoIG90aGVyIHdlIHByZWZlciB0aGUgb25lIHdpdGggdHlwZSA9IHRhcmdldCBhbmQgdGhlIG9uZSB0aGF0IGlzIHZhbGlkXG4gICAgcmV0dXJuIChjbG9zZXN0SGFuZGxlcy5maW5kKCh7IGhhbmRsZSwgdmFsaWRIYW5kbGVSZXN1bHQgfSkgPT4gaGFzVGFyZ2V0SGFuZGxlID8gaGFuZGxlLnR5cGUgPT09ICd0YXJnZXQnIDogKGhhc1ZhbGlkSGFuZGxlID8gdmFsaWRIYW5kbGVSZXN1bHQuaXNWYWxpZCA6IHRydWUpKSB8fCBjbG9zZXN0SGFuZGxlc1swXSk7XG59XG5jb25zdCBudWxsQ29ubmVjdGlvbiA9IHsgc291cmNlOiBudWxsLCB0YXJnZXQ6IG51bGwsIHNvdXJjZUhhbmRsZTogbnVsbCwgdGFyZ2V0SGFuZGxlOiBudWxsIH07XG5jb25zdCBkZWZhdWx0UmVzdWx0ID0gKCkgPT4gKHtcbiAgICBoYW5kbGVEb21Ob2RlOiBudWxsLFxuICAgIGlzVmFsaWQ6IGZhbHNlLFxuICAgIGNvbm5lY3Rpb246IG51bGxDb25uZWN0aW9uLFxuICAgIGVuZEhhbmRsZTogbnVsbCxcbn0pO1xuLy8gY2hlY2tzIGlmICBhbmQgcmV0dXJucyBjb25uZWN0aW9uIGluIGZvbSBvZiBhbiBvYmplY3QgeyBzb3VyY2U6IDEyMywgdGFyZ2V0OiAzMTIgfVxuZnVuY3Rpb24gaXNWYWxpZEhhbmRsZShoYW5kbGUsIGNvbm5lY3Rpb25Nb2RlLCBmcm9tTm9kZUlkLCBmcm9tSGFuZGxlSWQsIGZyb21UeXBlLCBpc1ZhbGlkQ29ubmVjdGlvbiwgZG9jKSB7XG4gICAgY29uc3QgaXNUYXJnZXQgPSBmcm9tVHlwZSA9PT0gJ3RhcmdldCc7XG4gICAgY29uc3QgaGFuZGxlVG9DaGVjayA9IGRvYy5xdWVyeVNlbGVjdG9yKGAucmVhY3QtZmxvd19faGFuZGxlW2RhdGEtaWQ9XCIke2hhbmRsZT8ubm9kZUlkfS0ke2hhbmRsZT8uaWR9LSR7aGFuZGxlPy50eXBlfVwiXWApO1xuICAgIGNvbnN0IHJlc3VsdCA9IHtcbiAgICAgICAgLi4uZGVmYXVsdFJlc3VsdCgpLFxuICAgICAgICBoYW5kbGVEb21Ob2RlOiBoYW5kbGVUb0NoZWNrLFxuICAgIH07XG4gICAgaWYgKGhhbmRsZVRvQ2hlY2spIHtcbiAgICAgICAgY29uc3QgaGFuZGxlVHlwZSA9IGdldEhhbmRsZVR5cGUodW5kZWZpbmVkLCBoYW5kbGVUb0NoZWNrKTtcbiAgICAgICAgY29uc3QgaGFuZGxlTm9kZUlkID0gaGFuZGxlVG9DaGVjay5nZXRBdHRyaWJ1dGUoJ2RhdGEtbm9kZWlkJyk7XG4gICAgICAgIGNvbnN0IGhhbmRsZUlkID0gaGFuZGxlVG9DaGVjay5nZXRBdHRyaWJ1dGUoJ2RhdGEtaGFuZGxlaWQnKTtcbiAgICAgICAgY29uc3QgY29ubmVjdGFibGUgPSBoYW5kbGVUb0NoZWNrLmNsYXNzTGlzdC5jb250YWlucygnY29ubmVjdGFibGUnKTtcbiAgICAgICAgY29uc3QgY29ubmVjdGFibGVFbmQgPSBoYW5kbGVUb0NoZWNrLmNsYXNzTGlzdC5jb250YWlucygnY29ubmVjdGFibGVlbmQnKTtcbiAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHtcbiAgICAgICAgICAgIHNvdXJjZTogaXNUYXJnZXQgPyBoYW5kbGVOb2RlSWQgOiBmcm9tTm9kZUlkLFxuICAgICAgICAgICAgc291cmNlSGFuZGxlOiBpc1RhcmdldCA/IGhhbmRsZUlkIDogZnJvbUhhbmRsZUlkLFxuICAgICAgICAgICAgdGFyZ2V0OiBpc1RhcmdldCA/IGZyb21Ob2RlSWQgOiBoYW5kbGVOb2RlSWQsXG4gICAgICAgICAgICB0YXJnZXRIYW5kbGU6IGlzVGFyZ2V0ID8gZnJvbUhhbmRsZUlkIDogaGFuZGxlSWQsXG4gICAgICAgIH07XG4gICAgICAgIHJlc3VsdC5jb25uZWN0aW9uID0gY29ubmVjdGlvbjtcbiAgICAgICAgY29uc3QgaXNDb25uZWN0YWJsZSA9IGNvbm5lY3RhYmxlICYmIGNvbm5lY3RhYmxlRW5kO1xuICAgICAgICAvLyBpbiBzdHJpY3QgbW9kZSB3ZSBkb24ndCBhbGxvdyB0YXJnZXQgdG8gdGFyZ2V0IG9yIHNvdXJjZSB0byBzb3VyY2UgY29ubmVjdGlvbnNcbiAgICAgICAgY29uc3QgaXNWYWxpZCA9IGlzQ29ubmVjdGFibGUgJiZcbiAgICAgICAgICAgIChjb25uZWN0aW9uTW9kZSA9PT0gQ29ubmVjdGlvbk1vZGUuU3RyaWN0XG4gICAgICAgICAgICAgICAgPyAoaXNUYXJnZXQgJiYgaGFuZGxlVHlwZSA9PT0gJ3NvdXJjZScpIHx8ICghaXNUYXJnZXQgJiYgaGFuZGxlVHlwZSA9PT0gJ3RhcmdldCcpXG4gICAgICAgICAgICAgICAgOiBoYW5kbGVOb2RlSWQgIT09IGZyb21Ob2RlSWQgfHwgaGFuZGxlSWQgIT09IGZyb21IYW5kbGVJZCk7XG4gICAgICAgIGlmIChpc1ZhbGlkKSB7XG4gICAgICAgICAgICByZXN1bHQuZW5kSGFuZGxlID0ge1xuICAgICAgICAgICAgICAgIG5vZGVJZDogaGFuZGxlTm9kZUlkLFxuICAgICAgICAgICAgICAgIGhhbmRsZUlkLFxuICAgICAgICAgICAgICAgIHR5cGU6IGhhbmRsZVR5cGUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgcmVzdWx0LmlzVmFsaWQgPSBpc1ZhbGlkQ29ubmVjdGlvbihjb25uZWN0aW9uKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gZ2V0SGFuZGxlTG9va3VwKHsgbm9kZXMsIG5vZGVJZCwgaGFuZGxlSWQsIGhhbmRsZVR5cGUgfSkge1xuICAgIHJldHVybiBub2Rlcy5yZWR1Y2UoKHJlcywgbm9kZSkgPT4ge1xuICAgICAgICBpZiAobm9kZVtpbnRlcm5hbHNTeW1ib2xdKSB7XG4gICAgICAgICAgICBjb25zdCB7IGhhbmRsZUJvdW5kcyB9ID0gbm9kZVtpbnRlcm5hbHNTeW1ib2xdO1xuICAgICAgICAgICAgbGV0IHNvdXJjZUhhbmRsZXMgPSBbXTtcbiAgICAgICAgICAgIGxldCB0YXJnZXRIYW5kbGVzID0gW107XG4gICAgICAgICAgICBpZiAoaGFuZGxlQm91bmRzKSB7XG4gICAgICAgICAgICAgICAgc291cmNlSGFuZGxlcyA9IGdldEhhbmRsZXMobm9kZSwgaGFuZGxlQm91bmRzLCAnc291cmNlJywgYCR7bm9kZUlkfS0ke2hhbmRsZUlkfS0ke2hhbmRsZVR5cGV9YCk7XG4gICAgICAgICAgICAgICAgdGFyZ2V0SGFuZGxlcyA9IGdldEhhbmRsZXMobm9kZSwgaGFuZGxlQm91bmRzLCAndGFyZ2V0JywgYCR7bm9kZUlkfS0ke2hhbmRsZUlkfS0ke2hhbmRsZVR5cGV9YCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXMucHVzaCguLi5zb3VyY2VIYW5kbGVzLCAuLi50YXJnZXRIYW5kbGVzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH0sIFtdKTtcbn1cbmZ1bmN0aW9uIGdldEhhbmRsZVR5cGUoZWRnZVVwZGF0ZXJUeXBlLCBoYW5kbGVEb21Ob2RlKSB7XG4gICAgaWYgKGVkZ2VVcGRhdGVyVHlwZSkge1xuICAgICAgICByZXR1cm4gZWRnZVVwZGF0ZXJUeXBlO1xuICAgIH1cbiAgICBlbHNlIGlmIChoYW5kbGVEb21Ob2RlPy5jbGFzc0xpc3QuY29udGFpbnMoJ3RhcmdldCcpKSB7XG4gICAgICAgIHJldHVybiAndGFyZ2V0JztcbiAgICB9XG4gICAgZWxzZSBpZiAoaGFuZGxlRG9tTm9kZT8uY2xhc3NMaXN0LmNvbnRhaW5zKCdzb3VyY2UnKSkge1xuICAgICAgICByZXR1cm4gJ3NvdXJjZSc7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xufVxuZnVuY3Rpb24gcmVzZXRSZWNlbnRIYW5kbGUoaGFuZGxlRG9tTm9kZSkge1xuICAgIGhhbmRsZURvbU5vZGU/LmNsYXNzTGlzdC5yZW1vdmUoJ3ZhbGlkJywgJ2Nvbm5lY3RpbmcnLCAncmVhY3QtZmxvd19faGFuZGxlLXZhbGlkJywgJ3JlYWN0LWZsb3dfX2hhbmRsZS1jb25uZWN0aW5nJyk7XG59XG5mdW5jdGlvbiBnZXRDb25uZWN0aW9uU3RhdHVzKGlzSW5zaWRlQ29ubmVjdGlvblJhZGl1cywgaXNIYW5kbGVWYWxpZCkge1xuICAgIGxldCBjb25uZWN0aW9uU3RhdHVzID0gbnVsbDtcbiAgICBpZiAoaXNIYW5kbGVWYWxpZCkge1xuICAgICAgICBjb25uZWN0aW9uU3RhdHVzID0gJ3ZhbGlkJztcbiAgICB9XG4gICAgZWxzZSBpZiAoaXNJbnNpZGVDb25uZWN0aW9uUmFkaXVzICYmICFpc0hhbmRsZVZhbGlkKSB7XG4gICAgICAgIGNvbm5lY3Rpb25TdGF0dXMgPSAnaW52YWxpZCc7XG4gICAgfVxuICAgIHJldHVybiBjb25uZWN0aW9uU3RhdHVzO1xufVxuXG5mdW5jdGlvbiBoYW5kbGVQb2ludGVyRG93bih7IGV2ZW50LCBoYW5kbGVJZCwgbm9kZUlkLCBvbkNvbm5lY3QsIGlzVGFyZ2V0LCBnZXRTdGF0ZSwgc2V0U3RhdGUsIGlzVmFsaWRDb25uZWN0aW9uLCBlZGdlVXBkYXRlclR5cGUsIG9uRWRnZVVwZGF0ZUVuZCwgfSkge1xuICAgIC8vIHdoZW4gcmVhY3QtZmxvdyBpcyB1c2VkIGluc2lkZSBhIHNoYWRvdyByb290IHdlIGNhbid0IHVzZSBkb2N1bWVudFxuICAgIGNvbnN0IGRvYyA9IGdldEhvc3RGb3JFbGVtZW50KGV2ZW50LnRhcmdldCk7XG4gICAgY29uc3QgeyBjb25uZWN0aW9uTW9kZSwgZG9tTm9kZSwgYXV0b1Bhbk9uQ29ubmVjdCwgY29ubmVjdGlvblJhZGl1cywgb25Db25uZWN0U3RhcnQsIHBhbkJ5LCBnZXROb2RlcywgY2FuY2VsQ29ubmVjdGlvbiwgfSA9IGdldFN0YXRlKCk7XG4gICAgbGV0IGF1dG9QYW5JZCA9IDA7XG4gICAgbGV0IGNsb3Nlc3RIYW5kbGU7XG4gICAgY29uc3QgeyB4LCB5IH0gPSBnZXRFdmVudFBvc2l0aW9uKGV2ZW50KTtcbiAgICBjb25zdCBjbGlja2VkSGFuZGxlID0gZG9jPy5lbGVtZW50RnJvbVBvaW50KHgsIHkpO1xuICAgIGNvbnN0IGhhbmRsZVR5cGUgPSBnZXRIYW5kbGVUeXBlKGVkZ2VVcGRhdGVyVHlwZSwgY2xpY2tlZEhhbmRsZSk7XG4gICAgY29uc3QgY29udGFpbmVyQm91bmRzID0gZG9tTm9kZT8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgaWYgKCFjb250YWluZXJCb3VuZHMgfHwgIWhhbmRsZVR5cGUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBsZXQgcHJldkFjdGl2ZUhhbmRsZTtcbiAgICBsZXQgY29ubmVjdGlvblBvc2l0aW9uID0gZ2V0RXZlbnRQb3NpdGlvbihldmVudCwgY29udGFpbmVyQm91bmRzKTtcbiAgICBsZXQgYXV0b1BhblN0YXJ0ZWQgPSBmYWxzZTtcbiAgICBsZXQgY29ubmVjdGlvbiA9IG51bGw7XG4gICAgbGV0IGlzVmFsaWQgPSBmYWxzZTtcbiAgICBsZXQgaGFuZGxlRG9tTm9kZSA9IG51bGw7XG4gICAgY29uc3QgaGFuZGxlTG9va3VwID0gZ2V0SGFuZGxlTG9va3VwKHtcbiAgICAgICAgbm9kZXM6IGdldE5vZGVzKCksXG4gICAgICAgIG5vZGVJZCxcbiAgICAgICAgaGFuZGxlSWQsXG4gICAgICAgIGhhbmRsZVR5cGUsXG4gICAgfSk7XG4gICAgLy8gd2hlbiB0aGUgdXNlciBpcyBtb3ZpbmcgdGhlIG1vdXNlIGNsb3NlIHRvIHRoZSBlZGdlIG9mIHRoZSBjYW52YXMgd2hpbGUgY29ubmVjdGluZyB3ZSBtb3ZlIHRoZSBjYW52YXNcbiAgICBjb25zdCBhdXRvUGFuID0gKCkgPT4ge1xuICAgICAgICBpZiAoIWF1dG9QYW5PbkNvbm5lY3QpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBbeE1vdmVtZW50LCB5TW92ZW1lbnRdID0gY2FsY0F1dG9QYW4oY29ubmVjdGlvblBvc2l0aW9uLCBjb250YWluZXJCb3VuZHMpO1xuICAgICAgICBwYW5CeSh7IHg6IHhNb3ZlbWVudCwgeTogeU1vdmVtZW50IH0pO1xuICAgICAgICBhdXRvUGFuSWQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoYXV0b1Bhbik7XG4gICAgfTtcbiAgICBzZXRTdGF0ZSh7XG4gICAgICAgIGNvbm5lY3Rpb25Qb3NpdGlvbixcbiAgICAgICAgY29ubmVjdGlvblN0YXR1czogbnVsbCxcbiAgICAgICAgLy8gY29ubmVjdGlvbk5vZGVJZCBldGMgd2lsbCBiZSByZW1vdmVkIGluIHRoZSBuZXh0IG1ham9yIGluIGZhdm9yIG9mIGNvbm5lY3Rpb25TdGFydEhhbmRsZVxuICAgICAgICBjb25uZWN0aW9uTm9kZUlkOiBub2RlSWQsXG4gICAgICAgIGNvbm5lY3Rpb25IYW5kbGVJZDogaGFuZGxlSWQsXG4gICAgICAgIGNvbm5lY3Rpb25IYW5kbGVUeXBlOiBoYW5kbGVUeXBlLFxuICAgICAgICBjb25uZWN0aW9uU3RhcnRIYW5kbGU6IHtcbiAgICAgICAgICAgIG5vZGVJZCxcbiAgICAgICAgICAgIGhhbmRsZUlkLFxuICAgICAgICAgICAgdHlwZTogaGFuZGxlVHlwZSxcbiAgICAgICAgfSxcbiAgICAgICAgY29ubmVjdGlvbkVuZEhhbmRsZTogbnVsbCxcbiAgICB9KTtcbiAgICBvbkNvbm5lY3RTdGFydD8uKGV2ZW50LCB7IG5vZGVJZCwgaGFuZGxlSWQsIGhhbmRsZVR5cGUgfSk7XG4gICAgZnVuY3Rpb24gb25Qb2ludGVyTW92ZShldmVudCkge1xuICAgICAgICBjb25zdCB7IHRyYW5zZm9ybSB9ID0gZ2V0U3RhdGUoKTtcbiAgICAgICAgY29ubmVjdGlvblBvc2l0aW9uID0gZ2V0RXZlbnRQb3NpdGlvbihldmVudCwgY29udGFpbmVyQm91bmRzKTtcbiAgICAgICAgY29uc3QgeyBoYW5kbGUsIHZhbGlkSGFuZGxlUmVzdWx0IH0gPSBnZXRDbG9zZXN0SGFuZGxlKGV2ZW50LCBkb2MsIHBvaW50VG9SZW5kZXJlclBvaW50KGNvbm5lY3Rpb25Qb3NpdGlvbiwgdHJhbnNmb3JtLCBmYWxzZSwgWzEsIDFdKSwgY29ubmVjdGlvblJhZGl1cywgaGFuZGxlTG9va3VwLCAoaGFuZGxlKSA9PiBpc1ZhbGlkSGFuZGxlKGhhbmRsZSwgY29ubmVjdGlvbk1vZGUsIG5vZGVJZCwgaGFuZGxlSWQsIGlzVGFyZ2V0ID8gJ3RhcmdldCcgOiAnc291cmNlJywgaXNWYWxpZENvbm5lY3Rpb24sIGRvYykpO1xuICAgICAgICBjbG9zZXN0SGFuZGxlID0gaGFuZGxlO1xuICAgICAgICBpZiAoIWF1dG9QYW5TdGFydGVkKSB7XG4gICAgICAgICAgICBhdXRvUGFuKCk7XG4gICAgICAgICAgICBhdXRvUGFuU3RhcnRlZCA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaGFuZGxlRG9tTm9kZSA9IHZhbGlkSGFuZGxlUmVzdWx0LmhhbmRsZURvbU5vZGU7XG4gICAgICAgIGNvbm5lY3Rpb24gPSB2YWxpZEhhbmRsZVJlc3VsdC5jb25uZWN0aW9uO1xuICAgICAgICBpc1ZhbGlkID0gdmFsaWRIYW5kbGVSZXN1bHQuaXNWYWxpZDtcbiAgICAgICAgc2V0U3RhdGUoe1xuICAgICAgICAgICAgY29ubmVjdGlvblBvc2l0aW9uOiBjbG9zZXN0SGFuZGxlICYmIGlzVmFsaWRcbiAgICAgICAgICAgICAgICA/IHJlbmRlcmVyUG9pbnRUb1BvaW50KHtcbiAgICAgICAgICAgICAgICAgICAgeDogY2xvc2VzdEhhbmRsZS54LFxuICAgICAgICAgICAgICAgICAgICB5OiBjbG9zZXN0SGFuZGxlLnksXG4gICAgICAgICAgICAgICAgfSwgdHJhbnNmb3JtKVxuICAgICAgICAgICAgICAgIDogY29ubmVjdGlvblBvc2l0aW9uLFxuICAgICAgICAgICAgY29ubmVjdGlvblN0YXR1czogZ2V0Q29ubmVjdGlvblN0YXR1cyghIWNsb3Nlc3RIYW5kbGUsIGlzVmFsaWQpLFxuICAgICAgICAgICAgY29ubmVjdGlvbkVuZEhhbmRsZTogdmFsaWRIYW5kbGVSZXN1bHQuZW5kSGFuZGxlLFxuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCFjbG9zZXN0SGFuZGxlICYmICFpc1ZhbGlkICYmICFoYW5kbGVEb21Ob2RlKSB7XG4gICAgICAgICAgICByZXR1cm4gcmVzZXRSZWNlbnRIYW5kbGUocHJldkFjdGl2ZUhhbmRsZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbm5lY3Rpb24uc291cmNlICE9PSBjb25uZWN0aW9uLnRhcmdldCAmJiBoYW5kbGVEb21Ob2RlKSB7XG4gICAgICAgICAgICByZXNldFJlY2VudEhhbmRsZShwcmV2QWN0aXZlSGFuZGxlKTtcbiAgICAgICAgICAgIHByZXZBY3RpdmVIYW5kbGUgPSBoYW5kbGVEb21Ob2RlO1xuICAgICAgICAgICAgLy8gQHRvZG86IHJlbW92ZSB0aGUgb2xkIGNsYXNzIG5hbWVzIFwicmVhY3QtZmxvd19faGFuZGxlLVwiIGluIHRoZSBuZXh0IG1ham9yIHZlcnNpb25cbiAgICAgICAgICAgIGhhbmRsZURvbU5vZGUuY2xhc3NMaXN0LmFkZCgnY29ubmVjdGluZycsICdyZWFjdC1mbG93X19oYW5kbGUtY29ubmVjdGluZycpO1xuICAgICAgICAgICAgaGFuZGxlRG9tTm9kZS5jbGFzc0xpc3QudG9nZ2xlKCd2YWxpZCcsIGlzVmFsaWQpO1xuICAgICAgICAgICAgaGFuZGxlRG9tTm9kZS5jbGFzc0xpc3QudG9nZ2xlKCdyZWFjdC1mbG93X19oYW5kbGUtdmFsaWQnLCBpc1ZhbGlkKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBmdW5jdGlvbiBvblBvaW50ZXJVcChldmVudCkge1xuICAgICAgICBpZiAoKGNsb3Nlc3RIYW5kbGUgfHwgaGFuZGxlRG9tTm9kZSkgJiYgY29ubmVjdGlvbiAmJiBpc1ZhbGlkKSB7XG4gICAgICAgICAgICBvbkNvbm5lY3Q/Lihjb25uZWN0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpdCdzIGltcG9ydGFudCB0byBnZXQgYSBmcmVzaCByZWZlcmVuY2UgZnJvbSB0aGUgc3RvcmUgaGVyZVxuICAgICAgICAvLyBpbiBvcmRlciB0byBnZXQgdGhlIGxhdGVzdCBzdGF0ZSBvZiBvbkNvbm5lY3RFbmRcbiAgICAgICAgZ2V0U3RhdGUoKS5vbkNvbm5lY3RFbmQ/LihldmVudCk7XG4gICAgICAgIGlmIChlZGdlVXBkYXRlclR5cGUpIHtcbiAgICAgICAgICAgIG9uRWRnZVVwZGF0ZUVuZD8uKGV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgICByZXNldFJlY2VudEhhbmRsZShwcmV2QWN0aXZlSGFuZGxlKTtcbiAgICAgICAgY2FuY2VsQ29ubmVjdGlvbigpO1xuICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZShhdXRvUGFuSWQpO1xuICAgICAgICBhdXRvUGFuU3RhcnRlZCA9IGZhbHNlO1xuICAgICAgICBpc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgIGNvbm5lY3Rpb24gPSBudWxsO1xuICAgICAgICBoYW5kbGVEb21Ob2RlID0gbnVsbDtcbiAgICAgICAgZG9jLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIG9uUG9pbnRlck1vdmUpO1xuICAgICAgICBkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIG9uUG9pbnRlclVwKTtcbiAgICAgICAgZG9jLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNobW92ZScsIG9uUG9pbnRlck1vdmUpO1xuICAgICAgICBkb2MucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBvblBvaW50ZXJVcCk7XG4gICAgfVxuICAgIGRvYy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBvblBvaW50ZXJNb3ZlKTtcbiAgICBkb2MuYWRkRXZlbnRMaXN0ZW5lcignbW91c2V1cCcsIG9uUG9pbnRlclVwKTtcbiAgICBkb2MuYWRkRXZlbnRMaXN0ZW5lcigndG91Y2htb3ZlJywgb25Qb2ludGVyTW92ZSk7XG4gICAgZG9jLmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoZW5kJywgb25Qb2ludGVyVXApO1xufVxuXG5jb25zdCBhbHdheXNWYWxpZCA9ICgpID0+IHRydWU7XG5jb25zdCBzZWxlY3RvciRmID0gKHMpID0+ICh7XG4gICAgY29ubmVjdGlvblN0YXJ0SGFuZGxlOiBzLmNvbm5lY3Rpb25TdGFydEhhbmRsZSxcbiAgICBjb25uZWN0T25DbGljazogcy5jb25uZWN0T25DbGljayxcbiAgICBub1BhbkNsYXNzTmFtZTogcy5ub1BhbkNsYXNzTmFtZSxcbn0pO1xuY29uc3QgY29ubmVjdGluZ1NlbGVjdG9yID0gKG5vZGVJZCwgaGFuZGxlSWQsIHR5cGUpID0+IChzdGF0ZSkgPT4ge1xuICAgIGNvbnN0IHsgY29ubmVjdGlvblN0YXJ0SGFuZGxlOiBzdGFydEhhbmRsZSwgY29ubmVjdGlvbkVuZEhhbmRsZTogZW5kSGFuZGxlLCBjb25uZWN0aW9uQ2xpY2tTdGFydEhhbmRsZTogY2xpY2tIYW5kbGUsIH0gPSBzdGF0ZTtcbiAgICByZXR1cm4ge1xuICAgICAgICBjb25uZWN0aW5nOiAoc3RhcnRIYW5kbGU/Lm5vZGVJZCA9PT0gbm9kZUlkICYmIHN0YXJ0SGFuZGxlPy5oYW5kbGVJZCA9PT0gaGFuZGxlSWQgJiYgc3RhcnRIYW5kbGU/LnR5cGUgPT09IHR5cGUpIHx8XG4gICAgICAgICAgICAoZW5kSGFuZGxlPy5ub2RlSWQgPT09IG5vZGVJZCAmJiBlbmRIYW5kbGU/LmhhbmRsZUlkID09PSBoYW5kbGVJZCAmJiBlbmRIYW5kbGU/LnR5cGUgPT09IHR5cGUpLFxuICAgICAgICBjbGlja0Nvbm5lY3Rpbmc6IGNsaWNrSGFuZGxlPy5ub2RlSWQgPT09IG5vZGVJZCAmJiBjbGlja0hhbmRsZT8uaGFuZGxlSWQgPT09IGhhbmRsZUlkICYmIGNsaWNrSGFuZGxlPy50eXBlID09PSB0eXBlLFxuICAgIH07XG59O1xuY29uc3QgSGFuZGxlID0gZm9yd2FyZFJlZigoeyB0eXBlID0gJ3NvdXJjZScsIHBvc2l0aW9uID0gUG9zaXRpb24uVG9wLCBpc1ZhbGlkQ29ubmVjdGlvbiwgaXNDb25uZWN0YWJsZSA9IHRydWUsIGlzQ29ubmVjdGFibGVTdGFydCA9IHRydWUsIGlzQ29ubmVjdGFibGVFbmQgPSB0cnVlLCBpZCwgb25Db25uZWN0LCBjaGlsZHJlbiwgY2xhc3NOYW1lLCBvbk1vdXNlRG93biwgb25Ub3VjaFN0YXJ0LCAuLi5yZXN0IH0sIHJlZikgPT4ge1xuICAgIGNvbnN0IGhhbmRsZUlkID0gaWQgfHwgbnVsbDtcbiAgICBjb25zdCBpc1RhcmdldCA9IHR5cGUgPT09ICd0YXJnZXQnO1xuICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICBjb25zdCBub2RlSWQgPSB1c2VOb2RlSWQoKTtcbiAgICBjb25zdCB7IGNvbm5lY3RPbkNsaWNrLCBub1BhbkNsYXNzTmFtZSB9ID0gdXNlU3RvcmUoc2VsZWN0b3IkZiwgc2hhbGxvdyk7XG4gICAgY29uc3QgeyBjb25uZWN0aW5nLCBjbGlja0Nvbm5lY3RpbmcgfSA9IHVzZVN0b3JlKGNvbm5lY3RpbmdTZWxlY3Rvcihub2RlSWQsIGhhbmRsZUlkLCB0eXBlKSwgc2hhbGxvdyk7XG4gICAgaWYgKCFub2RlSWQpIHtcbiAgICAgICAgc3RvcmUuZ2V0U3RhdGUoKS5vbkVycm9yPy4oJzAxMCcsIGVycm9yTWVzc2FnZXNbJ2Vycm9yMDEwJ10oKSk7XG4gICAgfVxuICAgIGNvbnN0IG9uQ29ubmVjdEV4dGVuZGVkID0gKHBhcmFtcykgPT4ge1xuICAgICAgICBjb25zdCB7IGRlZmF1bHRFZGdlT3B0aW9ucywgb25Db25uZWN0OiBvbkNvbm5lY3RBY3Rpb24sIGhhc0RlZmF1bHRFZGdlcyB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgY29uc3QgZWRnZVBhcmFtcyA9IHtcbiAgICAgICAgICAgIC4uLmRlZmF1bHRFZGdlT3B0aW9ucyxcbiAgICAgICAgICAgIC4uLnBhcmFtcyxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGhhc0RlZmF1bHRFZGdlcykge1xuICAgICAgICAgICAgY29uc3QgeyBlZGdlcywgc2V0RWRnZXMgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICBzZXRFZGdlcyhhZGRFZGdlKGVkZ2VQYXJhbXMsIGVkZ2VzKSk7XG4gICAgICAgIH1cbiAgICAgICAgb25Db25uZWN0QWN0aW9uPy4oZWRnZVBhcmFtcyk7XG4gICAgICAgIG9uQ29ubmVjdD8uKGVkZ2VQYXJhbXMpO1xuICAgIH07XG4gICAgY29uc3Qgb25Qb2ludGVyRG93biA9IChldmVudCkgPT4ge1xuICAgICAgICBpZiAoIW5vZGVJZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGlzTW91c2VUcmlnZ2VyZWQgPSBpc01vdXNlRXZlbnQoZXZlbnQpO1xuICAgICAgICBpZiAoaXNDb25uZWN0YWJsZVN0YXJ0ICYmICgoaXNNb3VzZVRyaWdnZXJlZCAmJiBldmVudC5idXR0b24gPT09IDApIHx8ICFpc01vdXNlVHJpZ2dlcmVkKSkge1xuICAgICAgICAgICAgaGFuZGxlUG9pbnRlckRvd24oe1xuICAgICAgICAgICAgICAgIGV2ZW50LFxuICAgICAgICAgICAgICAgIGhhbmRsZUlkLFxuICAgICAgICAgICAgICAgIG5vZGVJZCxcbiAgICAgICAgICAgICAgICBvbkNvbm5lY3Q6IG9uQ29ubmVjdEV4dGVuZGVkLFxuICAgICAgICAgICAgICAgIGlzVGFyZ2V0LFxuICAgICAgICAgICAgICAgIGdldFN0YXRlOiBzdG9yZS5nZXRTdGF0ZSxcbiAgICAgICAgICAgICAgICBzZXRTdGF0ZTogc3RvcmUuc2V0U3RhdGUsXG4gICAgICAgICAgICAgICAgaXNWYWxpZENvbm5lY3Rpb246IGlzVmFsaWRDb25uZWN0aW9uIHx8IHN0b3JlLmdldFN0YXRlKCkuaXNWYWxpZENvbm5lY3Rpb24gfHwgYWx3YXlzVmFsaWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNNb3VzZVRyaWdnZXJlZCkge1xuICAgICAgICAgICAgb25Nb3VzZURvd24/LihldmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBvblRvdWNoU3RhcnQ/LihldmVudCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IG9uQ2xpY2sgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgY29uc3QgeyBvbkNsaWNrQ29ubmVjdFN0YXJ0LCBvbkNsaWNrQ29ubmVjdEVuZCwgY29ubmVjdGlvbkNsaWNrU3RhcnRIYW5kbGUsIGNvbm5lY3Rpb25Nb2RlLCBpc1ZhbGlkQ29ubmVjdGlvbjogaXNWYWxpZENvbm5lY3Rpb25TdG9yZSwgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgIGlmICghbm9kZUlkIHx8ICghY29ubmVjdGlvbkNsaWNrU3RhcnRIYW5kbGUgJiYgIWlzQ29ubmVjdGFibGVTdGFydCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbm5lY3Rpb25DbGlja1N0YXJ0SGFuZGxlKSB7XG4gICAgICAgICAgICBvbkNsaWNrQ29ubmVjdFN0YXJ0Py4oZXZlbnQsIHsgbm9kZUlkLCBoYW5kbGVJZCwgaGFuZGxlVHlwZTogdHlwZSB9KTtcbiAgICAgICAgICAgIHN0b3JlLnNldFN0YXRlKHsgY29ubmVjdGlvbkNsaWNrU3RhcnRIYW5kbGU6IHsgbm9kZUlkLCB0eXBlLCBoYW5kbGVJZCB9IH0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGRvYyA9IGdldEhvc3RGb3JFbGVtZW50KGV2ZW50LnRhcmdldCk7XG4gICAgICAgIGNvbnN0IGlzVmFsaWRDb25uZWN0aW9uSGFuZGxlciA9IGlzVmFsaWRDb25uZWN0aW9uIHx8IGlzVmFsaWRDb25uZWN0aW9uU3RvcmUgfHwgYWx3YXlzVmFsaWQ7XG4gICAgICAgIGNvbnN0IHsgY29ubmVjdGlvbiwgaXNWYWxpZCB9ID0gaXNWYWxpZEhhbmRsZSh7XG4gICAgICAgICAgICBub2RlSWQsXG4gICAgICAgICAgICBpZDogaGFuZGxlSWQsXG4gICAgICAgICAgICB0eXBlLFxuICAgICAgICB9LCBjb25uZWN0aW9uTW9kZSwgY29ubmVjdGlvbkNsaWNrU3RhcnRIYW5kbGUubm9kZUlkLCBjb25uZWN0aW9uQ2xpY2tTdGFydEhhbmRsZS5oYW5kbGVJZCB8fCBudWxsLCBjb25uZWN0aW9uQ2xpY2tTdGFydEhhbmRsZS50eXBlLCBpc1ZhbGlkQ29ubmVjdGlvbkhhbmRsZXIsIGRvYyk7XG4gICAgICAgIGlmIChpc1ZhbGlkKSB7XG4gICAgICAgICAgICBvbkNvbm5lY3RFeHRlbmRlZChjb25uZWN0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICBvbkNsaWNrQ29ubmVjdEVuZD8uKGV2ZW50KTtcbiAgICAgICAgc3RvcmUuc2V0U3RhdGUoeyBjb25uZWN0aW9uQ2xpY2tTdGFydEhhbmRsZTogbnVsbCB9KTtcbiAgICB9O1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IFwiZGF0YS1oYW5kbGVpZFwiOiBoYW5kbGVJZCwgXCJkYXRhLW5vZGVpZFwiOiBub2RlSWQsIFwiZGF0YS1oYW5kbGVwb3NcIjogcG9zaXRpb24sIFwiZGF0YS1pZFwiOiBgJHtub2RlSWR9LSR7aGFuZGxlSWR9LSR7dHlwZX1gLCBjbGFzc05hbWU6IGNjKFtcbiAgICAgICAgICAgICdyZWFjdC1mbG93X19oYW5kbGUnLFxuICAgICAgICAgICAgYHJlYWN0LWZsb3dfX2hhbmRsZS0ke3Bvc2l0aW9ufWAsXG4gICAgICAgICAgICAnbm9kcmFnJyxcbiAgICAgICAgICAgIG5vUGFuQ2xhc3NOYW1lLFxuICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHNvdXJjZTogIWlzVGFyZ2V0LFxuICAgICAgICAgICAgICAgIHRhcmdldDogaXNUYXJnZXQsXG4gICAgICAgICAgICAgICAgY29ubmVjdGFibGU6IGlzQ29ubmVjdGFibGUsXG4gICAgICAgICAgICAgICAgY29ubmVjdGFibGVzdGFydDogaXNDb25uZWN0YWJsZVN0YXJ0LFxuICAgICAgICAgICAgICAgIGNvbm5lY3RhYmxlZW5kOiBpc0Nvbm5lY3RhYmxlRW5kLFxuICAgICAgICAgICAgICAgIGNvbm5lY3Rpbmc6IGNsaWNrQ29ubmVjdGluZyxcbiAgICAgICAgICAgICAgICAvLyB0aGlzIGNsYXNzIGlzIHVzZWQgdG8gc3R5bGUgdGhlIGhhbmRsZSB3aGVuIHRoZSB1c2VyIGlzIGNvbm5lY3RpbmdcbiAgICAgICAgICAgICAgICBjb25uZWN0aW9uaW5kaWNhdG9yOiBpc0Nvbm5lY3RhYmxlICYmICgoaXNDb25uZWN0YWJsZVN0YXJ0ICYmICFjb25uZWN0aW5nKSB8fCAoaXNDb25uZWN0YWJsZUVuZCAmJiBjb25uZWN0aW5nKSksXG4gICAgICAgICAgICB9LFxuICAgICAgICBdKSwgb25Nb3VzZURvd246IG9uUG9pbnRlckRvd24sIG9uVG91Y2hTdGFydDogb25Qb2ludGVyRG93biwgb25DbGljazogY29ubmVjdE9uQ2xpY2sgPyBvbkNsaWNrIDogdW5kZWZpbmVkLCByZWY6IHJlZiwgLi4ucmVzdCB9LCBjaGlsZHJlbikpO1xufSk7XG5IYW5kbGUuZGlzcGxheU5hbWUgPSAnSGFuZGxlJztcbnZhciBIYW5kbGUkMSA9IG1lbW8oSGFuZGxlKTtcblxuY29uc3QgRGVmYXVsdE5vZGUgPSAoeyBkYXRhLCBpc0Nvbm5lY3RhYmxlLCB0YXJnZXRQb3NpdGlvbiA9IFBvc2l0aW9uLlRvcCwgc291cmNlUG9zaXRpb24gPSBQb3NpdGlvbi5Cb3R0b20sIH0pID0+IHtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoUmVhY3QuRnJhZ21lbnQsIG51bGwsXG4gICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoSGFuZGxlJDEsIHsgdHlwZTogXCJ0YXJnZXRcIiwgcG9zaXRpb246IHRhcmdldFBvc2l0aW9uLCBpc0Nvbm5lY3RhYmxlOiBpc0Nvbm5lY3RhYmxlIH0pLFxuICAgICAgICBkYXRhPy5sYWJlbCxcbiAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChIYW5kbGUkMSwgeyB0eXBlOiBcInNvdXJjZVwiLCBwb3NpdGlvbjogc291cmNlUG9zaXRpb24sIGlzQ29ubmVjdGFibGU6IGlzQ29ubmVjdGFibGUgfSkpKTtcbn07XG5EZWZhdWx0Tm9kZS5kaXNwbGF5TmFtZSA9ICdEZWZhdWx0Tm9kZSc7XG52YXIgRGVmYXVsdE5vZGUkMSA9IG1lbW8oRGVmYXVsdE5vZGUpO1xuXG5jb25zdCBJbnB1dE5vZGUgPSAoeyBkYXRhLCBpc0Nvbm5lY3RhYmxlLCBzb3VyY2VQb3NpdGlvbiA9IFBvc2l0aW9uLkJvdHRvbSB9KSA9PiAoUmVhY3QuY3JlYXRlRWxlbWVudChSZWFjdC5GcmFnbWVudCwgbnVsbCxcbiAgICBkYXRhPy5sYWJlbCxcbiAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEhhbmRsZSQxLCB7IHR5cGU6IFwic291cmNlXCIsIHBvc2l0aW9uOiBzb3VyY2VQb3NpdGlvbiwgaXNDb25uZWN0YWJsZTogaXNDb25uZWN0YWJsZSB9KSkpO1xuSW5wdXROb2RlLmRpc3BsYXlOYW1lID0gJ0lucHV0Tm9kZSc7XG52YXIgSW5wdXROb2RlJDEgPSBtZW1vKElucHV0Tm9kZSk7XG5cbmNvbnN0IE91dHB1dE5vZGUgPSAoeyBkYXRhLCBpc0Nvbm5lY3RhYmxlLCB0YXJnZXRQb3NpdGlvbiA9IFBvc2l0aW9uLlRvcCB9KSA9PiAoUmVhY3QuY3JlYXRlRWxlbWVudChSZWFjdC5GcmFnbWVudCwgbnVsbCxcbiAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEhhbmRsZSQxLCB7IHR5cGU6IFwidGFyZ2V0XCIsIHBvc2l0aW9uOiB0YXJnZXRQb3NpdGlvbiwgaXNDb25uZWN0YWJsZTogaXNDb25uZWN0YWJsZSB9KSxcbiAgICBkYXRhPy5sYWJlbCkpO1xuT3V0cHV0Tm9kZS5kaXNwbGF5TmFtZSA9ICdPdXRwdXROb2RlJztcbnZhciBPdXRwdXROb2RlJDEgPSBtZW1vKE91dHB1dE5vZGUpO1xuXG5jb25zdCBHcm91cE5vZGUgPSAoKSA9PiBudWxsO1xuR3JvdXBOb2RlLmRpc3BsYXlOYW1lID0gJ0dyb3VwTm9kZSc7XG5cbmNvbnN0IHNlbGVjdG9yJGUgPSAocykgPT4gKHtcbiAgICBzZWxlY3RlZE5vZGVzOiBzLmdldE5vZGVzKCkuZmlsdGVyKChuKSA9PiBuLnNlbGVjdGVkKSxcbiAgICBzZWxlY3RlZEVkZ2VzOiBzLmVkZ2VzLmZpbHRlcigoZSkgPT4gZS5zZWxlY3RlZCksXG59KTtcbmNvbnN0IHNlbGVjdElkID0gKG9iaikgPT4gb2JqLmlkO1xuZnVuY3Rpb24gYXJlRXF1YWwoYSwgYikge1xuICAgIHJldHVybiAoc2hhbGxvdyhhLnNlbGVjdGVkTm9kZXMubWFwKHNlbGVjdElkKSwgYi5zZWxlY3RlZE5vZGVzLm1hcChzZWxlY3RJZCkpICYmXG4gICAgICAgIHNoYWxsb3coYS5zZWxlY3RlZEVkZ2VzLm1hcChzZWxlY3RJZCksIGIuc2VsZWN0ZWRFZGdlcy5tYXAoc2VsZWN0SWQpKSk7XG59XG4vLyBUaGlzIGlzIGp1c3QgYSBoZWxwZXIgY29tcG9uZW50IGZvciBjYWxsaW5nIHRoZSBvblNlbGVjdGlvbkNoYW5nZSBsaXN0ZW5lci5cbi8vIEBUT0RPOiBOb3cgdGhhdCB3ZSBoYXZlIHRoZSBvbk5vZGVzQ2hhbmdlIGFuZCBvbiBFZGdlc0NoYW5nZSBsaXN0ZW5lcnMsIGRvIHdlIHN0aWxsIG5lZWQgdGhpcyBjb21wb25lbnQ/XG5jb25zdCBTZWxlY3Rpb25MaXN0ZW5lciA9IG1lbW8oKHsgb25TZWxlY3Rpb25DaGFuZ2UgfSkgPT4ge1xuICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICBjb25zdCB7IHNlbGVjdGVkTm9kZXMsIHNlbGVjdGVkRWRnZXMgfSA9IHVzZVN0b3JlKHNlbGVjdG9yJGUsIGFyZUVxdWFsKTtcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBjb25zdCBwYXJhbXMgPSB7IG5vZGVzOiBzZWxlY3RlZE5vZGVzLCBlZGdlczogc2VsZWN0ZWRFZGdlcyB9O1xuICAgICAgICBvblNlbGVjdGlvbkNoYW5nZT8uKHBhcmFtcyk7XG4gICAgICAgIHN0b3JlLmdldFN0YXRlKCkub25TZWxlY3Rpb25DaGFuZ2UuZm9yRWFjaCgoZm4pID0+IGZuKHBhcmFtcykpO1xuICAgIH0sIFtzZWxlY3RlZE5vZGVzLCBzZWxlY3RlZEVkZ2VzLCBvblNlbGVjdGlvbkNoYW5nZV0pO1xuICAgIHJldHVybiBudWxsO1xufSk7XG5TZWxlY3Rpb25MaXN0ZW5lci5kaXNwbGF5TmFtZSA9ICdTZWxlY3Rpb25MaXN0ZW5lcic7XG5jb25zdCBjaGFuZ2VTZWxlY3RvciA9IChzKSA9PiAhIXMub25TZWxlY3Rpb25DaGFuZ2U7XG5mdW5jdGlvbiBXcmFwcGVyJDEoeyBvblNlbGVjdGlvbkNoYW5nZSB9KSB7XG4gICAgY29uc3Qgc3RvcmVIYXNTZWxlY3Rpb25DaGFuZ2UgPSB1c2VTdG9yZShjaGFuZ2VTZWxlY3Rvcik7XG4gICAgaWYgKG9uU2VsZWN0aW9uQ2hhbmdlIHx8IHN0b3JlSGFzU2VsZWN0aW9uQ2hhbmdlKSB7XG4gICAgICAgIHJldHVybiBSZWFjdC5jcmVhdGVFbGVtZW50KFNlbGVjdGlvbkxpc3RlbmVyLCB7IG9uU2VsZWN0aW9uQ2hhbmdlOiBvblNlbGVjdGlvbkNoYW5nZSB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG51bGw7XG59XG5cbmNvbnN0IHNlbGVjdG9yJGQgPSAocykgPT4gKHtcbiAgICBzZXROb2Rlczogcy5zZXROb2RlcyxcbiAgICBzZXRFZGdlczogcy5zZXRFZGdlcyxcbiAgICBzZXREZWZhdWx0Tm9kZXNBbmRFZGdlczogcy5zZXREZWZhdWx0Tm9kZXNBbmRFZGdlcyxcbiAgICBzZXRNaW5ab29tOiBzLnNldE1pblpvb20sXG4gICAgc2V0TWF4Wm9vbTogcy5zZXRNYXhab29tLFxuICAgIHNldFRyYW5zbGF0ZUV4dGVudDogcy5zZXRUcmFuc2xhdGVFeHRlbnQsXG4gICAgc2V0Tm9kZUV4dGVudDogcy5zZXROb2RlRXh0ZW50LFxuICAgIHJlc2V0OiBzLnJlc2V0LFxufSk7XG5mdW5jdGlvbiB1c2VTdG9yZVVwZGF0ZXIodmFsdWUsIHNldFN0b3JlU3RhdGUpIHtcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgc2V0U3RvcmVTdGF0ZSh2YWx1ZSk7XG4gICAgICAgIH1cbiAgICB9LCBbdmFsdWVdKTtcbn1cbi8vIHVwZGF0ZXMgd2l0aCB2YWx1ZXMgaW4gc3RvcmUgdGhhdCBkb24ndCBoYXZlIGEgZGVkaWNhdGVkIHNldHRlciBmdW5jdGlvblxuZnVuY3Rpb24gdXNlRGlyZWN0U3RvcmVVcGRhdGVyKGtleSwgdmFsdWUsIHNldFN0YXRlKSB7XG4gICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHNldFN0YXRlKHsgW2tleV06IHZhbHVlIH0pO1xuICAgICAgICB9XG4gICAgfSwgW3ZhbHVlXSk7XG59XG5jb25zdCBTdG9yZVVwZGF0ZXIgPSAoeyBub2RlcywgZWRnZXMsIGRlZmF1bHROb2RlcywgZGVmYXVsdEVkZ2VzLCBvbkNvbm5lY3QsIG9uQ29ubmVjdFN0YXJ0LCBvbkNvbm5lY3RFbmQsIG9uQ2xpY2tDb25uZWN0U3RhcnQsIG9uQ2xpY2tDb25uZWN0RW5kLCBub2Rlc0RyYWdnYWJsZSwgbm9kZXNDb25uZWN0YWJsZSwgbm9kZXNGb2N1c2FibGUsIGVkZ2VzRm9jdXNhYmxlLCBlZGdlc1VwZGF0YWJsZSwgZWxldmF0ZU5vZGVzT25TZWxlY3QsIG1pblpvb20sIG1heFpvb20sIG5vZGVFeHRlbnQsIG9uTm9kZXNDaGFuZ2UsIG9uRWRnZXNDaGFuZ2UsIGVsZW1lbnRzU2VsZWN0YWJsZSwgY29ubmVjdGlvbk1vZGUsIHNuYXBHcmlkLCBzbmFwVG9HcmlkLCB0cmFuc2xhdGVFeHRlbnQsIGNvbm5lY3RPbkNsaWNrLCBkZWZhdWx0RWRnZU9wdGlvbnMsIGZpdFZpZXcsIGZpdFZpZXdPcHRpb25zLCBvbk5vZGVzRGVsZXRlLCBvbkVkZ2VzRGVsZXRlLCBvbk5vZGVEcmFnLCBvbk5vZGVEcmFnU3RhcnQsIG9uTm9kZURyYWdTdG9wLCBvblNlbGVjdGlvbkRyYWcsIG9uU2VsZWN0aW9uRHJhZ1N0YXJ0LCBvblNlbGVjdGlvbkRyYWdTdG9wLCBub1BhbkNsYXNzTmFtZSwgbm9kZU9yaWdpbiwgcmZJZCwgYXV0b1Bhbk9uQ29ubmVjdCwgYXV0b1Bhbk9uTm9kZURyYWcsIG9uRXJyb3IsIGNvbm5lY3Rpb25SYWRpdXMsIGlzVmFsaWRDb25uZWN0aW9uLCBub2RlRHJhZ1RocmVzaG9sZCwgfSkgPT4ge1xuICAgIGNvbnN0IHsgc2V0Tm9kZXMsIHNldEVkZ2VzLCBzZXREZWZhdWx0Tm9kZXNBbmRFZGdlcywgc2V0TWluWm9vbSwgc2V0TWF4Wm9vbSwgc2V0VHJhbnNsYXRlRXh0ZW50LCBzZXROb2RlRXh0ZW50LCByZXNldCwgfSA9IHVzZVN0b3JlKHNlbGVjdG9yJGQsIHNoYWxsb3cpO1xuICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBjb25zdCBlZGdlc1dpdGhEZWZhdWx0cyA9IGRlZmF1bHRFZGdlcz8ubWFwKChlKSA9PiAoeyAuLi5lLCAuLi5kZWZhdWx0RWRnZU9wdGlvbnMgfSkpO1xuICAgICAgICBzZXREZWZhdWx0Tm9kZXNBbmRFZGdlcyhkZWZhdWx0Tm9kZXMsIGVkZ2VzV2l0aERlZmF1bHRzKTtcbiAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgIHJlc2V0KCk7XG4gICAgICAgIH07XG4gICAgfSwgW10pO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignZGVmYXVsdEVkZ2VPcHRpb25zJywgZGVmYXVsdEVkZ2VPcHRpb25zLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdjb25uZWN0aW9uTW9kZScsIGNvbm5lY3Rpb25Nb2RlLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdvbkNvbm5lY3QnLCBvbkNvbm5lY3QsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ29uQ29ubmVjdFN0YXJ0Jywgb25Db25uZWN0U3RhcnQsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ29uQ29ubmVjdEVuZCcsIG9uQ29ubmVjdEVuZCwgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignb25DbGlja0Nvbm5lY3RTdGFydCcsIG9uQ2xpY2tDb25uZWN0U3RhcnQsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ29uQ2xpY2tDb25uZWN0RW5kJywgb25DbGlja0Nvbm5lY3RFbmQsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ25vZGVzRHJhZ2dhYmxlJywgbm9kZXNEcmFnZ2FibGUsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ25vZGVzQ29ubmVjdGFibGUnLCBub2Rlc0Nvbm5lY3RhYmxlLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdub2Rlc0ZvY3VzYWJsZScsIG5vZGVzRm9jdXNhYmxlLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdlZGdlc0ZvY3VzYWJsZScsIGVkZ2VzRm9jdXNhYmxlLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdlZGdlc1VwZGF0YWJsZScsIGVkZ2VzVXBkYXRhYmxlLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdlbGVtZW50c1NlbGVjdGFibGUnLCBlbGVtZW50c1NlbGVjdGFibGUsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ2VsZXZhdGVOb2Rlc09uU2VsZWN0JywgZWxldmF0ZU5vZGVzT25TZWxlY3QsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ3NuYXBUb0dyaWQnLCBzbmFwVG9HcmlkLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdzbmFwR3JpZCcsIHNuYXBHcmlkLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdvbk5vZGVzQ2hhbmdlJywgb25Ob2Rlc0NoYW5nZSwgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignb25FZGdlc0NoYW5nZScsIG9uRWRnZXNDaGFuZ2UsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ2Nvbm5lY3RPbkNsaWNrJywgY29ubmVjdE9uQ2xpY2ssIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ2ZpdFZpZXdPbkluaXQnLCBmaXRWaWV3LCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdmaXRWaWV3T25Jbml0T3B0aW9ucycsIGZpdFZpZXdPcHRpb25zLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdvbk5vZGVzRGVsZXRlJywgb25Ob2Rlc0RlbGV0ZSwgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignb25FZGdlc0RlbGV0ZScsIG9uRWRnZXNEZWxldGUsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ29uTm9kZURyYWcnLCBvbk5vZGVEcmFnLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdvbk5vZGVEcmFnU3RhcnQnLCBvbk5vZGVEcmFnU3RhcnQsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ29uTm9kZURyYWdTdG9wJywgb25Ob2RlRHJhZ1N0b3AsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ29uU2VsZWN0aW9uRHJhZycsIG9uU2VsZWN0aW9uRHJhZywgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignb25TZWxlY3Rpb25EcmFnU3RhcnQnLCBvblNlbGVjdGlvbkRyYWdTdGFydCwgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignb25TZWxlY3Rpb25EcmFnU3RvcCcsIG9uU2VsZWN0aW9uRHJhZ1N0b3AsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ25vUGFuQ2xhc3NOYW1lJywgbm9QYW5DbGFzc05hbWUsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ25vZGVPcmlnaW4nLCBub2RlT3JpZ2luLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdyZklkJywgcmZJZCwgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignYXV0b1Bhbk9uQ29ubmVjdCcsIGF1dG9QYW5PbkNvbm5lY3QsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ2F1dG9QYW5Pbk5vZGVEcmFnJywgYXV0b1Bhbk9uTm9kZURyYWcsIHN0b3JlLnNldFN0YXRlKTtcbiAgICB1c2VEaXJlY3RTdG9yZVVwZGF0ZXIoJ29uRXJyb3InLCBvbkVycm9yLCBzdG9yZS5zZXRTdGF0ZSk7XG4gICAgdXNlRGlyZWN0U3RvcmVVcGRhdGVyKCdjb25uZWN0aW9uUmFkaXVzJywgY29ubmVjdGlvblJhZGl1cywgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignaXNWYWxpZENvbm5lY3Rpb24nLCBpc1ZhbGlkQ29ubmVjdGlvbiwgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZURpcmVjdFN0b3JlVXBkYXRlcignbm9kZURyYWdUaHJlc2hvbGQnLCBub2RlRHJhZ1RocmVzaG9sZCwgc3RvcmUuc2V0U3RhdGUpO1xuICAgIHVzZVN0b3JlVXBkYXRlcihub2Rlcywgc2V0Tm9kZXMpO1xuICAgIHVzZVN0b3JlVXBkYXRlcihlZGdlcywgc2V0RWRnZXMpO1xuICAgIHVzZVN0b3JlVXBkYXRlcihtaW5ab29tLCBzZXRNaW5ab29tKTtcbiAgICB1c2VTdG9yZVVwZGF0ZXIobWF4Wm9vbSwgc2V0TWF4Wm9vbSk7XG4gICAgdXNlU3RvcmVVcGRhdGVyKHRyYW5zbGF0ZUV4dGVudCwgc2V0VHJhbnNsYXRlRXh0ZW50KTtcbiAgICB1c2VTdG9yZVVwZGF0ZXIobm9kZUV4dGVudCwgc2V0Tm9kZUV4dGVudCk7XG4gICAgcmV0dXJuIG51bGw7XG59O1xuXG5jb25zdCBzdHlsZSA9IHsgZGlzcGxheTogJ25vbmUnIH07XG5jb25zdCBhcmlhTGl2ZVN0eWxlID0ge1xuICAgIHBvc2l0aW9uOiAnYWJzb2x1dGUnLFxuICAgIHdpZHRoOiAxLFxuICAgIGhlaWdodDogMSxcbiAgICBtYXJnaW46IC0xLFxuICAgIGJvcmRlcjogMCxcbiAgICBwYWRkaW5nOiAwLFxuICAgIG92ZXJmbG93OiAnaGlkZGVuJyxcbiAgICBjbGlwOiAncmVjdCgwcHgsIDBweCwgMHB4LCAwcHgpJyxcbiAgICBjbGlwUGF0aDogJ2luc2V0KDEwMCUpJyxcbn07XG5jb25zdCBBUklBX05PREVfREVTQ19LRVkgPSAncmVhY3QtZmxvd19fbm9kZS1kZXNjJztcbmNvbnN0IEFSSUFfRURHRV9ERVNDX0tFWSA9ICdyZWFjdC1mbG93X19lZGdlLWRlc2MnO1xuY29uc3QgQVJJQV9MSVZFX01FU1NBR0UgPSAncmVhY3QtZmxvd19fYXJpYS1saXZlJztcbmNvbnN0IHNlbGVjdG9yJGMgPSAocykgPT4gcy5hcmlhTGl2ZU1lc3NhZ2U7XG5mdW5jdGlvbiBBcmlhTGl2ZU1lc3NhZ2UoeyByZklkIH0pIHtcbiAgICBjb25zdCBhcmlhTGl2ZU1lc3NhZ2UgPSB1c2VTdG9yZShzZWxlY3RvciRjKTtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBpZDogYCR7QVJJQV9MSVZFX01FU1NBR0V9LSR7cmZJZH1gLCBcImFyaWEtbGl2ZVwiOiBcImFzc2VydGl2ZVwiLCBcImFyaWEtYXRvbWljXCI6IFwidHJ1ZVwiLCBzdHlsZTogYXJpYUxpdmVTdHlsZSB9LCBhcmlhTGl2ZU1lc3NhZ2UpKTtcbn1cbmZ1bmN0aW9uIEExMXlEZXNjcmlwdGlvbnMoeyByZklkLCBkaXNhYmxlS2V5Ym9hcmRBMTF5IH0pIHtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoUmVhY3QuRnJhZ21lbnQsIG51bGwsXG4gICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBpZDogYCR7QVJJQV9OT0RFX0RFU0NfS0VZfS0ke3JmSWR9YCwgc3R5bGU6IHN0eWxlIH0sXG4gICAgICAgICAgICBcIlByZXNzIGVudGVyIG9yIHNwYWNlIHRvIHNlbGVjdCBhIG5vZGUuXCIsXG4gICAgICAgICAgICAhZGlzYWJsZUtleWJvYXJkQTExeSAmJiAnWW91IGNhbiB0aGVuIHVzZSB0aGUgYXJyb3cga2V5cyB0byBtb3ZlIHRoZSBub2RlIGFyb3VuZC4nLFxuICAgICAgICAgICAgXCIgUHJlc3MgZGVsZXRlIHRvIHJlbW92ZSBpdCBhbmQgZXNjYXBlIHRvIGNhbmNlbC5cIixcbiAgICAgICAgICAgICcgJyksXG4gICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBpZDogYCR7QVJJQV9FREdFX0RFU0NfS0VZfS0ke3JmSWR9YCwgc3R5bGU6IHN0eWxlIH0sIFwiUHJlc3MgZW50ZXIgb3Igc3BhY2UgdG8gc2VsZWN0IGFuIGVkZ2UuIFlvdSBjYW4gdGhlbiBwcmVzcyBkZWxldGUgdG8gcmVtb3ZlIGl0IG9yIGVzY2FwZSB0byBjYW5jZWwuXCIpLFxuICAgICAgICAhZGlzYWJsZUtleWJvYXJkQTExeSAmJiBSZWFjdC5jcmVhdGVFbGVtZW50KEFyaWFMaXZlTWVzc2FnZSwgeyByZklkOiByZklkIH0pKSk7XG59XG5cbi8vIHRoZSBrZXljb2RlIGNhbiBiZSBhIHN0cmluZyAnYScgb3IgYW4gYXJyYXkgb2Ygc3RyaW5ncyBbJ2EnLCAnYStkJ11cbi8vIGEgc3RyaW5nIG1lYW5zIGEgc2luZ2xlIGtleSAnYScgb3IgYSBjb21iaW5hdGlvbiB3aGVuICcrJyBpcyB1c2VkICdhK2QnXG4vLyBhbiBhcnJheSBtZWFucyBkaWZmZXJlbnQgcG9zc2liaWxpdGllcy4gRXhwbGFpbmVyOiBbJ2EnLCAnZCtzJ10gaGVyZSB0aGVcbi8vIHVzZXIgY2FuIHVzZSB0aGUgc2luZ2xlIGtleSAnYScgb3IgdGhlIGNvbWJpbmF0aW9uICdkJyArICdzJ1xudmFyIHVzZUtleVByZXNzID0gKGtleUNvZGUgPSBudWxsLCBvcHRpb25zID0geyBhY3RJbnNpZGVJbnB1dFdpdGhNb2RpZmllcjogdHJ1ZSB9KSA9PiB7XG4gICAgY29uc3QgW2tleVByZXNzZWQsIHNldEtleVByZXNzZWRdID0gdXNlU3RhdGUoZmFsc2UpO1xuICAgIC8vIHdlIG5lZWQgdG8gcmVtZW1iZXIgaWYgYSBtb2RpZmllciBrZXkgaXMgcHJlc3NlZCBpbiBvcmRlciB0byB0cmFjayBpdFxuICAgIGNvbnN0IG1vZGlmaWVyUHJlc3NlZCA9IHVzZVJlZihmYWxzZSk7XG4gICAgLy8gd2UgbmVlZCB0byByZW1lbWJlciB0aGUgcHJlc3NlZCBrZXlzIGluIG9yZGVyIHRvIHN1cHBvcnQgY29tYmluYXRpb25zXG4gICAgY29uc3QgcHJlc3NlZEtleXMgPSB1c2VSZWYobmV3IFNldChbXSkpO1xuICAgIC8vIGtleUNvZGVzID0gYXJyYXkgd2l0aCBzaW5nbGUga2V5cyBbWydhJ11dIG9yIGtleSBjb21iaW5hdGlvbnMgW1snYScsICdzJ11dXG4gICAgLy8ga2V5c1RvV2F0Y2ggPSBhcnJheSB3aXRoIGFsbCBrZXlzIGZsYXR0ZW5lZCBbJ2EnLCAnZCcsICdTaGlmdExlZnQnXVxuICAgIC8vIHVzZWQgdG8gY2hlY2sgaWYgd2Ugc3RvcmUgZXZlbnQuY29kZSBvciBldmVudC5rZXkuIFdoZW4gdGhlIGNvZGUgaXMgaW4gdGhlIGxpc3Qgb2Yga2V5c1RvV2F0Y2hcbiAgICAvLyB3ZSB1c2UgdGhlIGNvZGUgb3RoZXJ3aXNlIHRoZSBrZXkuIEV4cGxhaW5lcjogV2hlbiB5b3UgcHJlc3MgdGhlIGxlZnQgXCJjb21tYW5kXCIga2V5LCB0aGUgY29kZSBpcyBcIk1ldGFMZWZ0XCJcbiAgICAvLyBhbmQgdGhlIGtleSBpcyBcIk1ldGFcIi4gV2Ugd2FudCB1c2VycyB0byBiZSBhYmxlIHRvIHBhc3Mga2V5cyBhbmQgY29kZXMgc28gd2UgYXNzdW1lIHRoYXQgdGhlIGtleSBpcyBtZWFudCB3aGVuXG4gICAgLy8gd2UgY2FuJ3QgZmluZCBpdCBpbiB0aGUgbGlzdCBvZiBrZXlzVG9XYXRjaC5cbiAgICBjb25zdCBba2V5Q29kZXMsIGtleXNUb1dhdGNoXSA9IHVzZU1lbW8oKCkgPT4ge1xuICAgICAgICBpZiAoa2V5Q29kZSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc3Qga2V5Q29kZUFyciA9IEFycmF5LmlzQXJyYXkoa2V5Q29kZSkgPyBrZXlDb2RlIDogW2tleUNvZGVdO1xuICAgICAgICAgICAgY29uc3Qga2V5cyA9IGtleUNvZGVBcnIuZmlsdGVyKChrYykgPT4gdHlwZW9mIGtjID09PSAnc3RyaW5nJykubWFwKChrYykgPT4ga2Muc3BsaXQoJysnKSk7XG4gICAgICAgICAgICBjb25zdCBrZXlzRmxhdCA9IGtleXMucmVkdWNlKChyZXMsIGl0ZW0pID0+IHJlcy5jb25jYXQoLi4uaXRlbSksIFtdKTtcbiAgICAgICAgICAgIHJldHVybiBba2V5cywga2V5c0ZsYXRdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBbW10sIFtdXTtcbiAgICB9LCBba2V5Q29kZV0pO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IGRvYyA9IHR5cGVvZiBkb2N1bWVudCAhPT0gJ3VuZGVmaW5lZCcgPyBkb2N1bWVudCA6IG51bGw7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IG9wdGlvbnM/LnRhcmdldCB8fCBkb2M7XG4gICAgICAgIGlmIChrZXlDb2RlICE9PSBudWxsKSB7XG4gICAgICAgICAgICBjb25zdCBkb3duSGFuZGxlciA9IChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIG1vZGlmaWVyUHJlc3NlZC5jdXJyZW50ID0gZXZlbnQuY3RybEtleSB8fCBldmVudC5tZXRhS2V5IHx8IGV2ZW50LnNoaWZ0S2V5O1xuICAgICAgICAgICAgICAgIGNvbnN0IHByZXZlbnRBY3Rpb24gPSAoIW1vZGlmaWVyUHJlc3NlZC5jdXJyZW50IHx8IChtb2RpZmllclByZXNzZWQuY3VycmVudCAmJiAhb3B0aW9ucy5hY3RJbnNpZGVJbnB1dFdpdGhNb2RpZmllcikpICYmXG4gICAgICAgICAgICAgICAgICAgIGlzSW5wdXRET01Ob2RlKGV2ZW50KTtcbiAgICAgICAgICAgICAgICBpZiAocHJldmVudEFjdGlvbikge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IGtleU9yQ29kZSA9IHVzZUtleU9yQ29kZShldmVudC5jb2RlLCBrZXlzVG9XYXRjaCk7XG4gICAgICAgICAgICAgICAgcHJlc3NlZEtleXMuY3VycmVudC5hZGQoZXZlbnRba2V5T3JDb2RlXSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzTWF0Y2hpbmdLZXkoa2V5Q29kZXMsIHByZXNzZWRLZXlzLmN1cnJlbnQsIGZhbHNlKSkge1xuICAgICAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBzZXRLZXlQcmVzc2VkKHRydWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBjb25zdCB1cEhhbmRsZXIgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBwcmV2ZW50QWN0aW9uID0gKCFtb2RpZmllclByZXNzZWQuY3VycmVudCB8fCAobW9kaWZpZXJQcmVzc2VkLmN1cnJlbnQgJiYgIW9wdGlvbnMuYWN0SW5zaWRlSW5wdXRXaXRoTW9kaWZpZXIpKSAmJlxuICAgICAgICAgICAgICAgICAgICBpc0lucHV0RE9NTm9kZShldmVudCk7XG4gICAgICAgICAgICAgICAgaWYgKHByZXZlbnRBY3Rpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBrZXlPckNvZGUgPSB1c2VLZXlPckNvZGUoZXZlbnQuY29kZSwga2V5c1RvV2F0Y2gpO1xuICAgICAgICAgICAgICAgIGlmIChpc01hdGNoaW5nS2V5KGtleUNvZGVzLCBwcmVzc2VkS2V5cy5jdXJyZW50LCB0cnVlKSkge1xuICAgICAgICAgICAgICAgICAgICBzZXRLZXlQcmVzc2VkKGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgcHJlc3NlZEtleXMuY3VycmVudC5jbGVhcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcHJlc3NlZEtleXMuY3VycmVudC5kZWxldGUoZXZlbnRba2V5T3JDb2RlXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGZpeCBmb3IgTWFjOiB3aGVuIGNtZCBrZXkgaXMgcHJlc3NlZCwga2V5dXAgaXMgbm90IHRyaWdnZXJlZCBmb3IgYW55IG90aGVyIGtleSwgc2VlOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8yNzM4MDAxOC93aGVuLWNtZC1rZXktaXMta2VwdC1wcmVzc2VkLWtleXVwLWlzLW5vdC10cmlnZ2VyZWQtZm9yLWFueS1vdGhlci1rZXlcbiAgICAgICAgICAgICAgICBpZiAoZXZlbnQua2V5ID09PSAnTWV0YScpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJlc3NlZEtleXMuY3VycmVudC5jbGVhcigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBtb2RpZmllclByZXNzZWQuY3VycmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IHJlc2V0SGFuZGxlciA9ICgpID0+IHtcbiAgICAgICAgICAgICAgICBwcmVzc2VkS2V5cy5jdXJyZW50LmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgc2V0S2V5UHJlc3NlZChmYWxzZSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdGFyZ2V0Py5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgZG93bkhhbmRsZXIpO1xuICAgICAgICAgICAgdGFyZ2V0Py5hZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsIHVwSGFuZGxlcik7XG4gICAgICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignYmx1cicsIHJlc2V0SGFuZGxlcik7XG4gICAgICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRhcmdldD8ucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGRvd25IYW5kbGVyKTtcbiAgICAgICAgICAgICAgICB0YXJnZXQ/LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleXVwJywgdXBIYW5kbGVyKTtcbiAgICAgICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignYmx1cicsIHJlc2V0SGFuZGxlcik7XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgfSwgW2tleUNvZGUsIHNldEtleVByZXNzZWRdKTtcbiAgICByZXR1cm4ga2V5UHJlc3NlZDtcbn07XG4vLyB1dGlsc1xuZnVuY3Rpb24gaXNNYXRjaGluZ0tleShrZXlDb2RlcywgcHJlc3NlZEtleXMsIGlzVXApIHtcbiAgICByZXR1cm4gKGtleUNvZGVzXG4gICAgICAgIC8vIHdlIG9ubHkgd2FudCB0byBjb21wYXJlIHNhbWUgc2l6ZXMgb2Yga2V5Q29kZSBkZWZpbml0aW9uc1xuICAgICAgICAvLyBhbmQgcHJlc3NlZCBrZXlzLiBXaGVuIHRoZSB1c2VyIHNwZWNpZmllZCAnTWV0YScgYXMgYSBrZXkgc29tZXdoZXJlXG4gICAgICAgIC8vIHRoaXMgd291bGQgYWxzbyBiZSB0cnV0aHkgd2l0aG91dCB0aGlzIGZpbHRlciB3aGVuIHVzZXIgcHJlc3NlcyAnTWV0YScgKyAncidcbiAgICAgICAgLmZpbHRlcigoa2V5cykgPT4gaXNVcCB8fCBrZXlzLmxlbmd0aCA9PT0gcHJlc3NlZEtleXMuc2l6ZSlcbiAgICAgICAgLy8gc2luY2Ugd2Ugd2FudCB0byBzdXBwb3J0IG11bHRpcGxlIHBvc3NpYmlsaXRpZXMgb25seSBvbmUgb2YgdGhlXG4gICAgICAgIC8vIGNvbWJpbmF0aW9ucyBuZWVkIHRvIGJlIHBhcnQgb2YgdGhlIHByZXNzZWQga2V5c1xuICAgICAgICAuc29tZSgoa2V5cykgPT4ga2V5cy5ldmVyeSgoaykgPT4gcHJlc3NlZEtleXMuaGFzKGspKSkpO1xufVxuZnVuY3Rpb24gdXNlS2V5T3JDb2RlKGV2ZW50Q29kZSwga2V5c1RvV2F0Y2gpIHtcbiAgICByZXR1cm4ga2V5c1RvV2F0Y2guaW5jbHVkZXMoZXZlbnRDb2RlKSA/ICdjb2RlJyA6ICdrZXknO1xufVxuXG5mdW5jdGlvbiBjYWxjdWxhdGVYWVpQb3NpdGlvbihub2RlLCBub2RlSW50ZXJuYWxzLCByZXN1bHQsIG5vZGVPcmlnaW4pIHtcbiAgICBpZiAoIW5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbiAgICBjb25zdCBwYXJlbnROb2RlID0gbm9kZUludGVybmFscy5nZXQobm9kZS5wYXJlbnROb2RlKTtcbiAgICBjb25zdCBwYXJlbnROb2RlUG9zaXRpb24gPSBnZXROb2RlUG9zaXRpb25XaXRoT3JpZ2luKHBhcmVudE5vZGUsIG5vZGVPcmlnaW4pO1xuICAgIHJldHVybiBjYWxjdWxhdGVYWVpQb3NpdGlvbihwYXJlbnROb2RlLCBub2RlSW50ZXJuYWxzLCB7XG4gICAgICAgIHg6IChyZXN1bHQueCA/PyAwKSArIHBhcmVudE5vZGVQb3NpdGlvbi54LFxuICAgICAgICB5OiAocmVzdWx0LnkgPz8gMCkgKyBwYXJlbnROb2RlUG9zaXRpb24ueSxcbiAgICAgICAgejogKHBhcmVudE5vZGVbaW50ZXJuYWxzU3ltYm9sXT8ueiA/PyAwKSA+IChyZXN1bHQueiA/PyAwKSA/IHBhcmVudE5vZGVbaW50ZXJuYWxzU3ltYm9sXT8ueiA/PyAwIDogcmVzdWx0LnogPz8gMCxcbiAgICB9LCBub2RlT3JpZ2luKTtcbn1cbmZ1bmN0aW9uIHVwZGF0ZUFic29sdXRlTm9kZVBvc2l0aW9ucyhub2RlSW50ZXJuYWxzLCBub2RlT3JpZ2luLCBwYXJlbnROb2Rlcykge1xuICAgIG5vZGVJbnRlcm5hbHMuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgICAgICBpZiAobm9kZS5wYXJlbnROb2RlICYmICFub2RlSW50ZXJuYWxzLmhhcyhub2RlLnBhcmVudE5vZGUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFBhcmVudCBub2RlICR7bm9kZS5wYXJlbnROb2RlfSBub3QgZm91bmRgKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobm9kZS5wYXJlbnROb2RlIHx8IHBhcmVudE5vZGVzPy5bbm9kZS5pZF0pIHtcbiAgICAgICAgICAgIGNvbnN0IHsgeCwgeSwgeiB9ID0gY2FsY3VsYXRlWFlaUG9zaXRpb24obm9kZSwgbm9kZUludGVybmFscywge1xuICAgICAgICAgICAgICAgIC4uLm5vZGUucG9zaXRpb24sXG4gICAgICAgICAgICAgICAgejogbm9kZVtpbnRlcm5hbHNTeW1ib2xdPy56ID8/IDAsXG4gICAgICAgICAgICB9LCBub2RlT3JpZ2luKTtcbiAgICAgICAgICAgIG5vZGUucG9zaXRpb25BYnNvbHV0ZSA9IHtcbiAgICAgICAgICAgICAgICB4LFxuICAgICAgICAgICAgICAgIHksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgbm9kZVtpbnRlcm5hbHNTeW1ib2xdLnogPSB6O1xuICAgICAgICAgICAgaWYgKHBhcmVudE5vZGVzPy5bbm9kZS5pZF0pIHtcbiAgICAgICAgICAgICAgICBub2RlW2ludGVybmFsc1N5bWJvbF0uaXNQYXJlbnQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSk7XG59XG5mdW5jdGlvbiBjcmVhdGVOb2RlSW50ZXJuYWxzKG5vZGVzLCBub2RlSW50ZXJuYWxzLCBub2RlT3JpZ2luLCBlbGV2YXRlTm9kZXNPblNlbGVjdCkge1xuICAgIGNvbnN0IG5leHROb2RlSW50ZXJuYWxzID0gbmV3IE1hcCgpO1xuICAgIGNvbnN0IHBhcmVudE5vZGVzID0ge307XG4gICAgY29uc3Qgc2VsZWN0ZWROb2RlWiA9IGVsZXZhdGVOb2Rlc09uU2VsZWN0ID8gMTAwMCA6IDA7XG4gICAgbm9kZXMuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgICAgICBjb25zdCB6ID0gKGlzTnVtZXJpYyhub2RlLnpJbmRleCkgPyBub2RlLnpJbmRleCA6IDApICsgKG5vZGUuc2VsZWN0ZWQgPyBzZWxlY3RlZE5vZGVaIDogMCk7XG4gICAgICAgIGNvbnN0IGN1cnJJbnRlcm5hbHMgPSBub2RlSW50ZXJuYWxzLmdldChub2RlLmlkKTtcbiAgICAgICAgY29uc3QgaW50ZXJuYWxzID0ge1xuICAgICAgICAgICAgLi4ubm9kZSxcbiAgICAgICAgICAgIHBvc2l0aW9uQWJzb2x1dGU6IHtcbiAgICAgICAgICAgICAgICB4OiBub2RlLnBvc2l0aW9uLngsXG4gICAgICAgICAgICAgICAgeTogbm9kZS5wb3NpdGlvbi55LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKG5vZGUucGFyZW50Tm9kZSkge1xuICAgICAgICAgICAgcGFyZW50Tm9kZXNbbm9kZS5wYXJlbnROb2RlXSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcmVzZXRIYW5kbGVCb3VuZHMgPSBjdXJySW50ZXJuYWxzPy50eXBlICYmIGN1cnJJbnRlcm5hbHM/LnR5cGUgIT09IG5vZGUudHlwZTtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KGludGVybmFscywgaW50ZXJuYWxzU3ltYm9sLCB7XG4gICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIHZhbHVlOiB7XG4gICAgICAgICAgICAgICAgaGFuZGxlQm91bmRzOiByZXNldEhhbmRsZUJvdW5kcyA/IHVuZGVmaW5lZCA6IGN1cnJJbnRlcm5hbHM/LltpbnRlcm5hbHNTeW1ib2xdPy5oYW5kbGVCb3VuZHMsXG4gICAgICAgICAgICAgICAgeixcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBuZXh0Tm9kZUludGVybmFscy5zZXQobm9kZS5pZCwgaW50ZXJuYWxzKTtcbiAgICB9KTtcbiAgICB1cGRhdGVBYnNvbHV0ZU5vZGVQb3NpdGlvbnMobmV4dE5vZGVJbnRlcm5hbHMsIG5vZGVPcmlnaW4sIHBhcmVudE5vZGVzKTtcbiAgICByZXR1cm4gbmV4dE5vZGVJbnRlcm5hbHM7XG59XG5mdW5jdGlvbiBmaXRWaWV3KGdldCwgb3B0aW9ucyA9IHt9KSB7XG4gICAgY29uc3QgeyBnZXROb2Rlcywgd2lkdGgsIGhlaWdodCwgbWluWm9vbSwgbWF4Wm9vbSwgZDNab29tLCBkM1NlbGVjdGlvbiwgZml0Vmlld09uSW5pdERvbmUsIGZpdFZpZXdPbkluaXQsIG5vZGVPcmlnaW4sIH0gPSBnZXQoKTtcbiAgICBjb25zdCBpc0luaXRpYWxGaXRWaWV3ID0gb3B0aW9ucy5pbml0aWFsICYmICFmaXRWaWV3T25Jbml0RG9uZSAmJiBmaXRWaWV3T25Jbml0O1xuICAgIGNvbnN0IGQzaW5pdGlhbGl6ZWQgPSBkM1pvb20gJiYgZDNTZWxlY3Rpb247XG4gICAgaWYgKGQzaW5pdGlhbGl6ZWQgJiYgKGlzSW5pdGlhbEZpdFZpZXcgfHwgIW9wdGlvbnMuaW5pdGlhbCkpIHtcbiAgICAgICAgY29uc3Qgbm9kZXMgPSBnZXROb2RlcygpLmZpbHRlcigobikgPT4ge1xuICAgICAgICAgICAgY29uc3QgaXNWaXNpYmxlID0gb3B0aW9ucy5pbmNsdWRlSGlkZGVuTm9kZXMgPyBuLndpZHRoICYmIG4uaGVpZ2h0IDogIW4uaGlkZGVuO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMubm9kZXM/Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBpc1Zpc2libGUgJiYgb3B0aW9ucy5ub2Rlcy5zb21lKChvcHRpb25Ob2RlKSA9PiBvcHRpb25Ob2RlLmlkID09PSBuLmlkKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBpc1Zpc2libGU7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBub2Rlc0luaXRpYWxpemVkID0gbm9kZXMuZXZlcnkoKG4pID0+IG4ud2lkdGggJiYgbi5oZWlnaHQpO1xuICAgICAgICBpZiAobm9kZXMubGVuZ3RoID4gMCAmJiBub2Rlc0luaXRpYWxpemVkKSB7XG4gICAgICAgICAgICBjb25zdCBib3VuZHMgPSBnZXROb2Rlc0JvdW5kcyhub2Rlcywgbm9kZU9yaWdpbik7XG4gICAgICAgICAgICBjb25zdCB7IHgsIHksIHpvb20gfSA9IGdldFZpZXdwb3J0Rm9yQm91bmRzKGJvdW5kcywgd2lkdGgsIGhlaWdodCwgb3B0aW9ucy5taW5ab29tID8/IG1pblpvb20sIG9wdGlvbnMubWF4Wm9vbSA/PyBtYXhab29tLCBvcHRpb25zLnBhZGRpbmcgPz8gMC4xKTtcbiAgICAgICAgICAgIGNvbnN0IG5leHRUcmFuc2Zvcm0gPSB6b29tSWRlbnRpdHkudHJhbnNsYXRlKHgsIHkpLnNjYWxlKHpvb20pO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvcHRpb25zLmR1cmF0aW9uID09PSAnbnVtYmVyJyAmJiBvcHRpb25zLmR1cmF0aW9uID4gMCkge1xuICAgICAgICAgICAgICAgIGQzWm9vbS50cmFuc2Zvcm0oZ2V0RDNUcmFuc2l0aW9uKGQzU2VsZWN0aW9uLCBvcHRpb25zLmR1cmF0aW9uKSwgbmV4dFRyYW5zZm9ybSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBkM1pvb20udHJhbnNmb3JtKGQzU2VsZWN0aW9uLCBuZXh0VHJhbnNmb3JtKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cbmZ1bmN0aW9uIGhhbmRsZUNvbnRyb2xsZWROb2RlU2VsZWN0aW9uQ2hhbmdlKG5vZGVDaGFuZ2VzLCBub2RlSW50ZXJuYWxzKSB7XG4gICAgbm9kZUNoYW5nZXMuZm9yRWFjaCgoY2hhbmdlKSA9PiB7XG4gICAgICAgIGNvbnN0IG5vZGUgPSBub2RlSW50ZXJuYWxzLmdldChjaGFuZ2UuaWQpO1xuICAgICAgICBpZiAobm9kZSkge1xuICAgICAgICAgICAgbm9kZUludGVybmFscy5zZXQobm9kZS5pZCwge1xuICAgICAgICAgICAgICAgIC4uLm5vZGUsXG4gICAgICAgICAgICAgICAgW2ludGVybmFsc1N5bWJvbF06IG5vZGVbaW50ZXJuYWxzU3ltYm9sXSxcbiAgICAgICAgICAgICAgICBzZWxlY3RlZDogY2hhbmdlLnNlbGVjdGVkLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9KTtcbiAgICByZXR1cm4gbmV3IE1hcChub2RlSW50ZXJuYWxzKTtcbn1cbmZ1bmN0aW9uIGhhbmRsZUNvbnRyb2xsZWRFZGdlU2VsZWN0aW9uQ2hhbmdlKGVkZ2VDaGFuZ2VzLCBlZGdlcykge1xuICAgIHJldHVybiBlZGdlcy5tYXAoKGUpID0+IHtcbiAgICAgICAgY29uc3QgY2hhbmdlID0gZWRnZUNoYW5nZXMuZmluZCgoY2hhbmdlKSA9PiBjaGFuZ2UuaWQgPT09IGUuaWQpO1xuICAgICAgICBpZiAoY2hhbmdlKSB7XG4gICAgICAgICAgICBlLnNlbGVjdGVkID0gY2hhbmdlLnNlbGVjdGVkO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBlO1xuICAgIH0pO1xufVxuZnVuY3Rpb24gdXBkYXRlTm9kZXNBbmRFZGdlc1NlbGVjdGlvbnMoeyBjaGFuZ2VkTm9kZXMsIGNoYW5nZWRFZGdlcywgZ2V0LCBzZXQgfSkge1xuICAgIGNvbnN0IHsgbm9kZUludGVybmFscywgZWRnZXMsIG9uTm9kZXNDaGFuZ2UsIG9uRWRnZXNDaGFuZ2UsIGhhc0RlZmF1bHROb2RlcywgaGFzRGVmYXVsdEVkZ2VzIH0gPSBnZXQoKTtcbiAgICBpZiAoY2hhbmdlZE5vZGVzPy5sZW5ndGgpIHtcbiAgICAgICAgaWYgKGhhc0RlZmF1bHROb2Rlcykge1xuICAgICAgICAgICAgc2V0KHsgbm9kZUludGVybmFsczogaGFuZGxlQ29udHJvbGxlZE5vZGVTZWxlY3Rpb25DaGFuZ2UoY2hhbmdlZE5vZGVzLCBub2RlSW50ZXJuYWxzKSB9KTtcbiAgICAgICAgfVxuICAgICAgICBvbk5vZGVzQ2hhbmdlPy4oY2hhbmdlZE5vZGVzKTtcbiAgICB9XG4gICAgaWYgKGNoYW5nZWRFZGdlcz8ubGVuZ3RoKSB7XG4gICAgICAgIGlmIChoYXNEZWZhdWx0RWRnZXMpIHtcbiAgICAgICAgICAgIHNldCh7IGVkZ2VzOiBoYW5kbGVDb250cm9sbGVkRWRnZVNlbGVjdGlvbkNoYW5nZShjaGFuZ2VkRWRnZXMsIGVkZ2VzKSB9KTtcbiAgICAgICAgfVxuICAgICAgICBvbkVkZ2VzQ2hhbmdlPy4oY2hhbmdlZEVkZ2VzKTtcbiAgICB9XG59XG5cbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tZW1wdHktZnVuY3Rpb25cbmNvbnN0IG5vb3AgPSAoKSA9PiB7IH07XG5jb25zdCBpbml0aWFsVmlld3BvcnRIZWxwZXIgPSB7XG4gICAgem9vbUluOiBub29wLFxuICAgIHpvb21PdXQ6IG5vb3AsXG4gICAgem9vbVRvOiBub29wLFxuICAgIGdldFpvb206ICgpID0+IDEsXG4gICAgc2V0Vmlld3BvcnQ6IG5vb3AsXG4gICAgZ2V0Vmlld3BvcnQ6ICgpID0+ICh7IHg6IDAsIHk6IDAsIHpvb206IDEgfSksXG4gICAgZml0VmlldzogKCkgPT4gZmFsc2UsXG4gICAgc2V0Q2VudGVyOiBub29wLFxuICAgIGZpdEJvdW5kczogbm9vcCxcbiAgICBwcm9qZWN0OiAocG9zaXRpb24pID0+IHBvc2l0aW9uLFxuICAgIHNjcmVlblRvRmxvd1Bvc2l0aW9uOiAocG9zaXRpb24pID0+IHBvc2l0aW9uLFxuICAgIGZsb3dUb1NjcmVlblBvc2l0aW9uOiAocG9zaXRpb24pID0+IHBvc2l0aW9uLFxuICAgIHZpZXdwb3J0SW5pdGlhbGl6ZWQ6IGZhbHNlLFxufTtcbmNvbnN0IHNlbGVjdG9yJGIgPSAocykgPT4gKHtcbiAgICBkM1pvb206IHMuZDNab29tLFxuICAgIGQzU2VsZWN0aW9uOiBzLmQzU2VsZWN0aW9uLFxufSk7XG5jb25zdCB1c2VWaWV3cG9ydEhlbHBlciA9ICgpID0+IHtcbiAgICBjb25zdCBzdG9yZSA9IHVzZVN0b3JlQXBpKCk7XG4gICAgY29uc3QgeyBkM1pvb20sIGQzU2VsZWN0aW9uIH0gPSB1c2VTdG9yZShzZWxlY3RvciRiLCBzaGFsbG93KTtcbiAgICBjb25zdCB2aWV3cG9ydEhlbHBlckZ1bmN0aW9ucyA9IHVzZU1lbW8oKCkgPT4ge1xuICAgICAgICBpZiAoZDNTZWxlY3Rpb24gJiYgZDNab29tKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHpvb21JbjogKG9wdGlvbnMpID0+IGQzWm9vbS5zY2FsZUJ5KGdldEQzVHJhbnNpdGlvbihkM1NlbGVjdGlvbiwgb3B0aW9ucz8uZHVyYXRpb24pLCAxLjIpLFxuICAgICAgICAgICAgICAgIHpvb21PdXQ6IChvcHRpb25zKSA9PiBkM1pvb20uc2NhbGVCeShnZXREM1RyYW5zaXRpb24oZDNTZWxlY3Rpb24sIG9wdGlvbnM/LmR1cmF0aW9uKSwgMSAvIDEuMiksXG4gICAgICAgICAgICAgICAgem9vbVRvOiAoem9vbUxldmVsLCBvcHRpb25zKSA9PiBkM1pvb20uc2NhbGVUbyhnZXREM1RyYW5zaXRpb24oZDNTZWxlY3Rpb24sIG9wdGlvbnM/LmR1cmF0aW9uKSwgem9vbUxldmVsKSxcbiAgICAgICAgICAgICAgICBnZXRab29tOiAoKSA9PiBzdG9yZS5nZXRTdGF0ZSgpLnRyYW5zZm9ybVsyXSxcbiAgICAgICAgICAgICAgICBzZXRWaWV3cG9ydDogKHRyYW5zZm9ybSwgb3B0aW9ucykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBbeCwgeSwgem9vbV0gPSBzdG9yZS5nZXRTdGF0ZSgpLnRyYW5zZm9ybTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV4dFRyYW5zZm9ybSA9IHpvb21JZGVudGl0eVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRyYW5zbGF0ZSh0cmFuc2Zvcm0ueCA/PyB4LCB0cmFuc2Zvcm0ueSA/PyB5KVxuICAgICAgICAgICAgICAgICAgICAgICAgLnNjYWxlKHRyYW5zZm9ybS56b29tID8/IHpvb20pO1xuICAgICAgICAgICAgICAgICAgICBkM1pvb20udHJhbnNmb3JtKGdldEQzVHJhbnNpdGlvbihkM1NlbGVjdGlvbiwgb3B0aW9ucz8uZHVyYXRpb24pLCBuZXh0VHJhbnNmb3JtKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIGdldFZpZXdwb3J0OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IFt4LCB5LCB6b29tXSA9IHN0b3JlLmdldFN0YXRlKCkudHJhbnNmb3JtO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4geyB4LCB5LCB6b29tIH07XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBmaXRWaWV3OiAob3B0aW9ucykgPT4gZml0VmlldyhzdG9yZS5nZXRTdGF0ZSwgb3B0aW9ucyksXG4gICAgICAgICAgICAgICAgc2V0Q2VudGVyOiAoeCwgeSwgb3B0aW9ucykgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQsIG1heFpvb20gfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG5leHRab29tID0gdHlwZW9mIG9wdGlvbnM/Lnpvb20gIT09ICd1bmRlZmluZWQnID8gb3B0aW9ucy56b29tIDogbWF4Wm9vbTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2VudGVyWCA9IHdpZHRoIC8gMiAtIHggKiBuZXh0Wm9vbTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2VudGVyWSA9IGhlaWdodCAvIDIgLSB5ICogbmV4dFpvb207XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybSA9IHpvb21JZGVudGl0eS50cmFuc2xhdGUoY2VudGVyWCwgY2VudGVyWSkuc2NhbGUobmV4dFpvb20pO1xuICAgICAgICAgICAgICAgICAgICBkM1pvb20udHJhbnNmb3JtKGdldEQzVHJhbnNpdGlvbihkM1NlbGVjdGlvbiwgb3B0aW9ucz8uZHVyYXRpb24pLCB0cmFuc2Zvcm0pO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZml0Qm91bmRzOiAoYm91bmRzLCBvcHRpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgd2lkdGgsIGhlaWdodCwgbWluWm9vbSwgbWF4Wm9vbSB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeyB4LCB5LCB6b29tIH0gPSBnZXRWaWV3cG9ydEZvckJvdW5kcyhib3VuZHMsIHdpZHRoLCBoZWlnaHQsIG1pblpvb20sIG1heFpvb20sIG9wdGlvbnM/LnBhZGRpbmcgPz8gMC4xKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdHJhbnNmb3JtID0gem9vbUlkZW50aXR5LnRyYW5zbGF0ZSh4LCB5KS5zY2FsZSh6b29tKTtcbiAgICAgICAgICAgICAgICAgICAgZDNab29tLnRyYW5zZm9ybShnZXREM1RyYW5zaXRpb24oZDNTZWxlY3Rpb24sIG9wdGlvbnM/LmR1cmF0aW9uKSwgdHJhbnNmb3JtKTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIC8vIEBkZXByZWNhdGVkIFVzZSBgc2NyZWVuVG9GbG93UG9zaXRpb25gLlxuICAgICAgICAgICAgICAgIHByb2plY3Q6IChwb3NpdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHRyYW5zZm9ybSwgc25hcFRvR3JpZCwgc25hcEdyaWQgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUud2FybignW0RFUFJFQ0FURURdIGBwcm9qZWN0YCBpcyBkZXByZWNhdGVkLiBJbnN0ZWFkIHVzZSBgc2NyZWVuVG9GbG93UG9zaXRpb25gLiBUaGVyZSBpcyBubyBuZWVkIHRvIHN1YnRyYWN0IHRoZSByZWFjdCBmbG93IGJvdW5kcyBhbnltb3JlISBodHRwczovL3JlYWN0Zmxvdy5kZXYvYXBpLXJlZmVyZW5jZS90eXBlcy9yZWFjdC1mbG93LWluc3RhbmNlI3NjcmVlbi10by1mbG93LXBvc2l0aW9uJyk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBwb2ludFRvUmVuZGVyZXJQb2ludChwb3NpdGlvbiwgdHJhbnNmb3JtLCBzbmFwVG9HcmlkLCBzbmFwR3JpZCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBzY3JlZW5Ub0Zsb3dQb3NpdGlvbjogKHBvc2l0aW9uKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgdHJhbnNmb3JtLCBzbmFwVG9HcmlkLCBzbmFwR3JpZCwgZG9tTm9kZSB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeyB4OiBkb21YLCB5OiBkb21ZIH0gPSBkb21Ob2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWxhdGl2ZVBvc2l0aW9uID0ge1xuICAgICAgICAgICAgICAgICAgICAgICAgeDogcG9zaXRpb24ueCAtIGRvbVgsXG4gICAgICAgICAgICAgICAgICAgICAgICB5OiBwb3NpdGlvbi55IC0gZG9tWSxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBvaW50VG9SZW5kZXJlclBvaW50KHJlbGF0aXZlUG9zaXRpb24sIHRyYW5zZm9ybSwgc25hcFRvR3JpZCwgc25hcEdyaWQpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZmxvd1RvU2NyZWVuUG9zaXRpb246IChwb3NpdGlvbikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHRyYW5zZm9ybSwgZG9tTm9kZSB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkb21Ob2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeyB4OiBkb21YLCB5OiBkb21ZIH0gPSBkb21Ob2RlLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZW5kZXJlclBvc2l0aW9uID0gcmVuZGVyZXJQb2ludFRvUG9pbnQocG9zaXRpb24sIHRyYW5zZm9ybSk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgICAgICAgICB4OiByZW5kZXJlclBvc2l0aW9uLnggKyBkb21YLFxuICAgICAgICAgICAgICAgICAgICAgICAgeTogcmVuZGVyZXJQb3NpdGlvbi55ICsgZG9tWSxcbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHZpZXdwb3J0SW5pdGlhbGl6ZWQ6IHRydWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpbml0aWFsVmlld3BvcnRIZWxwZXI7XG4gICAgfSwgW2QzWm9vbSwgZDNTZWxlY3Rpb25dKTtcbiAgICByZXR1cm4gdmlld3BvcnRIZWxwZXJGdW5jdGlvbnM7XG59O1xuXG4vKiBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuZnVuY3Rpb24gdXNlUmVhY3RGbG93KCkge1xuICAgIGNvbnN0IHZpZXdwb3J0SGVscGVyID0gdXNlVmlld3BvcnRIZWxwZXIoKTtcbiAgICBjb25zdCBzdG9yZSA9IHVzZVN0b3JlQXBpKCk7XG4gICAgY29uc3QgZ2V0Tm9kZXMgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgICAgIHJldHVybiBzdG9yZVxuICAgICAgICAgICAgLmdldFN0YXRlKClcbiAgICAgICAgICAgIC5nZXROb2RlcygpXG4gICAgICAgICAgICAubWFwKChuKSA9PiAoeyAuLi5uIH0pKTtcbiAgICB9LCBbXSk7XG4gICAgY29uc3QgZ2V0Tm9kZSA9IHVzZUNhbGxiYWNrKChpZCkgPT4ge1xuICAgICAgICByZXR1cm4gc3RvcmUuZ2V0U3RhdGUoKS5ub2RlSW50ZXJuYWxzLmdldChpZCk7XG4gICAgfSwgW10pO1xuICAgIGNvbnN0IGdldEVkZ2VzID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgICAgICBjb25zdCB7IGVkZ2VzID0gW10gfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgIHJldHVybiBlZGdlcy5tYXAoKGUpID0+ICh7IC4uLmUgfSkpO1xuICAgIH0sIFtdKTtcbiAgICBjb25zdCBnZXRFZGdlID0gdXNlQ2FsbGJhY2soKGlkKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZWRnZXMgPSBbXSB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgcmV0dXJuIGVkZ2VzLmZpbmQoKGUpID0+IGUuaWQgPT09IGlkKTtcbiAgICB9LCBbXSk7XG4gICAgY29uc3Qgc2V0Tm9kZXMgPSB1c2VDYWxsYmFjaygocGF5bG9hZCkgPT4ge1xuICAgICAgICBjb25zdCB7IGdldE5vZGVzLCBzZXROb2RlcywgaGFzRGVmYXVsdE5vZGVzLCBvbk5vZGVzQ2hhbmdlIH0gPSBzdG9yZS5nZXRTdGF0ZSgpO1xuICAgICAgICBjb25zdCBub2RlcyA9IGdldE5vZGVzKCk7XG4gICAgICAgIGNvbnN0IG5leHROb2RlcyA9IHR5cGVvZiBwYXlsb2FkID09PSAnZnVuY3Rpb24nID8gcGF5bG9hZChub2RlcykgOiBwYXlsb2FkO1xuICAgICAgICBpZiAoaGFzRGVmYXVsdE5vZGVzKSB7XG4gICAgICAgICAgICBzZXROb2RlcyhuZXh0Tm9kZXMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG9uTm9kZXNDaGFuZ2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZXMgPSBuZXh0Tm9kZXMubGVuZ3RoID09PSAwXG4gICAgICAgICAgICAgICAgPyBub2Rlcy5tYXAoKG5vZGUpID0+ICh7IHR5cGU6ICdyZW1vdmUnLCBpZDogbm9kZS5pZCB9KSlcbiAgICAgICAgICAgICAgICA6IG5leHROb2Rlcy5tYXAoKG5vZGUpID0+ICh7IGl0ZW06IG5vZGUsIHR5cGU6ICdyZXNldCcgfSkpO1xuICAgICAgICAgICAgb25Ob2Rlc0NoYW5nZShjaGFuZ2VzKTtcbiAgICAgICAgfVxuICAgIH0sIFtdKTtcbiAgICBjb25zdCBzZXRFZGdlcyA9IHVzZUNhbGxiYWNrKChwYXlsb2FkKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZWRnZXMgPSBbXSwgc2V0RWRnZXMsIGhhc0RlZmF1bHRFZGdlcywgb25FZGdlc0NoYW5nZSB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgY29uc3QgbmV4dEVkZ2VzID0gdHlwZW9mIHBheWxvYWQgPT09ICdmdW5jdGlvbicgPyBwYXlsb2FkKGVkZ2VzKSA6IHBheWxvYWQ7XG4gICAgICAgIGlmIChoYXNEZWZhdWx0RWRnZXMpIHtcbiAgICAgICAgICAgIHNldEVkZ2VzKG5leHRFZGdlcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob25FZGdlc0NoYW5nZSkge1xuICAgICAgICAgICAgY29uc3QgY2hhbmdlcyA9IG5leHRFZGdlcy5sZW5ndGggPT09IDBcbiAgICAgICAgICAgICAgICA/IGVkZ2VzLm1hcCgoZWRnZSkgPT4gKHsgdHlwZTogJ3JlbW92ZScsIGlkOiBlZGdlLmlkIH0pKVxuICAgICAgICAgICAgICAgIDogbmV4dEVkZ2VzLm1hcCgoZWRnZSkgPT4gKHsgaXRlbTogZWRnZSwgdHlwZTogJ3Jlc2V0JyB9KSk7XG4gICAgICAgICAgICBvbkVkZ2VzQ2hhbmdlKGNoYW5nZXMpO1xuICAgICAgICB9XG4gICAgfSwgW10pO1xuICAgIGNvbnN0IGFkZE5vZGVzID0gdXNlQ2FsbGJhY2soKHBheWxvYWQpID0+IHtcbiAgICAgICAgY29uc3Qgbm9kZXMgPSBBcnJheS5pc0FycmF5KHBheWxvYWQpID8gcGF5bG9hZCA6IFtwYXlsb2FkXTtcbiAgICAgICAgY29uc3QgeyBnZXROb2Rlcywgc2V0Tm9kZXMsIGhhc0RlZmF1bHROb2Rlcywgb25Ob2Rlc0NoYW5nZSB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgaWYgKGhhc0RlZmF1bHROb2Rlcykge1xuICAgICAgICAgICAgY29uc3QgY3VycmVudE5vZGVzID0gZ2V0Tm9kZXMoKTtcbiAgICAgICAgICAgIGNvbnN0IG5leHROb2RlcyA9IFsuLi5jdXJyZW50Tm9kZXMsIC4uLm5vZGVzXTtcbiAgICAgICAgICAgIHNldE5vZGVzKG5leHROb2Rlcyk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob25Ob2Rlc0NoYW5nZSkge1xuICAgICAgICAgICAgY29uc3QgY2hhbmdlcyA9IG5vZGVzLm1hcCgobm9kZSkgPT4gKHsgaXRlbTogbm9kZSwgdHlwZTogJ2FkZCcgfSkpO1xuICAgICAgICAgICAgb25Ob2Rlc0NoYW5nZShjaGFuZ2VzKTtcbiAgICAgICAgfVxuICAgIH0sIFtdKTtcbiAgICBjb25zdCBhZGRFZGdlcyA9IHVzZUNhbGxiYWNrKChwYXlsb2FkKSA9PiB7XG4gICAgICAgIGNvbnN0IG5leHRFZGdlcyA9IEFycmF5LmlzQXJyYXkocGF5bG9hZCkgPyBwYXlsb2FkIDogW3BheWxvYWRdO1xuICAgICAgICBjb25zdCB7IGVkZ2VzID0gW10sIHNldEVkZ2VzLCBoYXNEZWZhdWx0RWRnZXMsIG9uRWRnZXNDaGFuZ2UgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgIGlmIChoYXNEZWZhdWx0RWRnZXMpIHtcbiAgICAgICAgICAgIHNldEVkZ2VzKFsuLi5lZGdlcywgLi4ubmV4dEVkZ2VzXSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAob25FZGdlc0NoYW5nZSkge1xuICAgICAgICAgICAgY29uc3QgY2hhbmdlcyA9IG5leHRFZGdlcy5tYXAoKGVkZ2UpID0+ICh7IGl0ZW06IGVkZ2UsIHR5cGU6ICdhZGQnIH0pKTtcbiAgICAgICAgICAgIG9uRWRnZXNDaGFuZ2UoY2hhbmdlcyk7XG4gICAgICAgIH1cbiAgICB9LCBbXSk7XG4gICAgY29uc3QgdG9PYmplY3QgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZ2V0Tm9kZXMsIGVkZ2VzID0gW10sIHRyYW5zZm9ybSB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgY29uc3QgW3gsIHksIHpvb21dID0gdHJhbnNmb3JtO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbm9kZXM6IGdldE5vZGVzKCkubWFwKChuKSA9PiAoeyAuLi5uIH0pKSxcbiAgICAgICAgICAgIGVkZ2VzOiBlZGdlcy5tYXAoKGUpID0+ICh7IC4uLmUgfSkpLFxuICAgICAgICAgICAgdmlld3BvcnQ6IHtcbiAgICAgICAgICAgICAgICB4LFxuICAgICAgICAgICAgICAgIHksXG4gICAgICAgICAgICAgICAgem9vbSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgfSwgW10pO1xuICAgIGNvbnN0IGRlbGV0ZUVsZW1lbnRzID0gdXNlQ2FsbGJhY2soKHsgbm9kZXM6IG5vZGVzRGVsZXRlZCwgZWRnZXM6IGVkZ2VzRGVsZXRlZCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgbm9kZUludGVybmFscywgZ2V0Tm9kZXMsIGVkZ2VzLCBoYXNEZWZhdWx0Tm9kZXMsIGhhc0RlZmF1bHRFZGdlcywgb25Ob2Rlc0RlbGV0ZSwgb25FZGdlc0RlbGV0ZSwgb25Ob2Rlc0NoYW5nZSwgb25FZGdlc0NoYW5nZSwgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgIGNvbnN0IG5vZGVJZHMgPSAobm9kZXNEZWxldGVkIHx8IFtdKS5tYXAoKG5vZGUpID0+IG5vZGUuaWQpO1xuICAgICAgICBjb25zdCBlZGdlSWRzID0gKGVkZ2VzRGVsZXRlZCB8fCBbXSkubWFwKChlZGdlKSA9PiBlZGdlLmlkKTtcbiAgICAgICAgY29uc3Qgbm9kZXNUb1JlbW92ZSA9IGdldE5vZGVzKCkucmVkdWNlKChyZXMsIG5vZGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmVudEhpdCA9ICFub2RlSWRzLmluY2x1ZGVzKG5vZGUuaWQpICYmIG5vZGUucGFyZW50Tm9kZSAmJiByZXMuZmluZCgobikgPT4gbi5pZCA9PT0gbm9kZS5wYXJlbnROb2RlKTtcbiAgICAgICAgICAgIGNvbnN0IGRlbGV0YWJsZSA9IHR5cGVvZiBub2RlLmRlbGV0YWJsZSA9PT0gJ2Jvb2xlYW4nID8gbm9kZS5kZWxldGFibGUgOiB0cnVlO1xuICAgICAgICAgICAgaWYgKGRlbGV0YWJsZSAmJiAobm9kZUlkcy5pbmNsdWRlcyhub2RlLmlkKSB8fCBwYXJlbnRIaXQpKSB7XG4gICAgICAgICAgICAgICAgcmVzLnB1c2gobm9kZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9LCBbXSk7XG4gICAgICAgIGNvbnN0IGRlbGV0YWJsZUVkZ2VzID0gZWRnZXMuZmlsdGVyKChlKSA9PiAodHlwZW9mIGUuZGVsZXRhYmxlID09PSAnYm9vbGVhbicgPyBlLmRlbGV0YWJsZSA6IHRydWUpKTtcbiAgICAgICAgY29uc3QgaW5pdGlhbEhpdEVkZ2VzID0gZGVsZXRhYmxlRWRnZXMuZmlsdGVyKChlKSA9PiBlZGdlSWRzLmluY2x1ZGVzKGUuaWQpKTtcbiAgICAgICAgaWYgKG5vZGVzVG9SZW1vdmUgfHwgaW5pdGlhbEhpdEVkZ2VzKSB7XG4gICAgICAgICAgICBjb25zdCBjb25uZWN0ZWRFZGdlcyA9IGdldENvbm5lY3RlZEVkZ2VzKG5vZGVzVG9SZW1vdmUsIGRlbGV0YWJsZUVkZ2VzKTtcbiAgICAgICAgICAgIGNvbnN0IGVkZ2VzVG9SZW1vdmUgPSBbLi4uaW5pdGlhbEhpdEVkZ2VzLCAuLi5jb25uZWN0ZWRFZGdlc107XG4gICAgICAgICAgICBjb25zdCBlZGdlSWRzVG9SZW1vdmUgPSBlZGdlc1RvUmVtb3ZlLnJlZHVjZSgocmVzLCBlZGdlKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFyZXMuaW5jbHVkZXMoZWRnZS5pZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzLnB1c2goZWRnZS5pZCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgICAgICB9LCBbXSk7XG4gICAgICAgICAgICBpZiAoaGFzRGVmYXVsdEVkZ2VzIHx8IGhhc0RlZmF1bHROb2Rlcykge1xuICAgICAgICAgICAgICAgIGlmIChoYXNEZWZhdWx0RWRnZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgc3RvcmUuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICAgICAgZWRnZXM6IGVkZ2VzLmZpbHRlcigoZSkgPT4gIWVkZ2VJZHNUb1JlbW92ZS5pbmNsdWRlcyhlLmlkKSksXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoaGFzRGVmYXVsdE5vZGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVzVG9SZW1vdmUuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZUludGVybmFscy5kZWxldGUobm9kZS5pZCk7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBzdG9yZS5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlSW50ZXJuYWxzOiBuZXcgTWFwKG5vZGVJbnRlcm5hbHMpLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZWRnZUlkc1RvUmVtb3ZlLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBvbkVkZ2VzRGVsZXRlPy4oZWRnZXNUb1JlbW92ZSk7XG4gICAgICAgICAgICAgICAgaWYgKG9uRWRnZXNDaGFuZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgb25FZGdlc0NoYW5nZShlZGdlSWRzVG9SZW1vdmUubWFwKChpZCkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZTogJ3JlbW92ZScsXG4gICAgICAgICAgICAgICAgICAgIH0pKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG5vZGVzVG9SZW1vdmUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIG9uTm9kZXNEZWxldGU/Lihub2Rlc1RvUmVtb3ZlKTtcbiAgICAgICAgICAgICAgICBpZiAob25Ob2Rlc0NoYW5nZSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBub2RlQ2hhbmdlcyA9IG5vZGVzVG9SZW1vdmUubWFwKChuKSA9PiAoeyBpZDogbi5pZCwgdHlwZTogJ3JlbW92ZScgfSkpO1xuICAgICAgICAgICAgICAgICAgICBvbk5vZGVzQ2hhbmdlKG5vZGVDaGFuZ2VzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCBbXSk7XG4gICAgY29uc3QgZ2V0Tm9kZVJlY3QgPSB1c2VDYWxsYmFjaygobm9kZU9yUmVjdCkgPT4ge1xuICAgICAgICBjb25zdCBpc1JlY3QgPSBpc1JlY3RPYmplY3Qobm9kZU9yUmVjdCk7XG4gICAgICAgIGNvbnN0IG5vZGUgPSBpc1JlY3QgPyBudWxsIDogc3RvcmUuZ2V0U3RhdGUoKS5ub2RlSW50ZXJuYWxzLmdldChub2RlT3JSZWN0LmlkKTtcbiAgICAgICAgaWYgKCFpc1JlY3QgJiYgIW5vZGUpIHtcbiAgICAgICAgICAgIHJldHVybiBbbnVsbCwgbnVsbCwgaXNSZWN0XTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBub2RlUmVjdCA9IGlzUmVjdCA/IG5vZGVPclJlY3QgOiBub2RlVG9SZWN0KG5vZGUpO1xuICAgICAgICByZXR1cm4gW25vZGVSZWN0LCBub2RlLCBpc1JlY3RdO1xuICAgIH0sIFtdKTtcbiAgICBjb25zdCBnZXRJbnRlcnNlY3RpbmdOb2RlcyA9IHVzZUNhbGxiYWNrKChub2RlT3JSZWN0LCBwYXJ0aWFsbHkgPSB0cnVlLCBub2RlcykgPT4ge1xuICAgICAgICBjb25zdCBbbm9kZVJlY3QsIG5vZGUsIGlzUmVjdF0gPSBnZXROb2RlUmVjdChub2RlT3JSZWN0KTtcbiAgICAgICAgaWYgKCFub2RlUmVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAobm9kZXMgfHwgc3RvcmUuZ2V0U3RhdGUoKS5nZXROb2RlcygpKS5maWx0ZXIoKG4pID0+IHtcbiAgICAgICAgICAgIGlmICghaXNSZWN0ICYmIChuLmlkID09PSBub2RlLmlkIHx8ICFuLnBvc2l0aW9uQWJzb2x1dGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgY3Vyck5vZGVSZWN0ID0gbm9kZVRvUmVjdChuKTtcbiAgICAgICAgICAgIGNvbnN0IG92ZXJsYXBwaW5nQXJlYSA9IGdldE92ZXJsYXBwaW5nQXJlYShjdXJyTm9kZVJlY3QsIG5vZGVSZWN0KTtcbiAgICAgICAgICAgIGNvbnN0IHBhcnRpYWxseVZpc2libGUgPSBwYXJ0aWFsbHkgJiYgb3ZlcmxhcHBpbmdBcmVhID4gMDtcbiAgICAgICAgICAgIHJldHVybiBwYXJ0aWFsbHlWaXNpYmxlIHx8IG92ZXJsYXBwaW5nQXJlYSA+PSBub2RlUmVjdC53aWR0aCAqIG5vZGVSZWN0LmhlaWdodDtcbiAgICAgICAgfSk7XG4gICAgfSwgW10pO1xuICAgIGNvbnN0IGlzTm9kZUludGVyc2VjdGluZyA9IHVzZUNhbGxiYWNrKChub2RlT3JSZWN0LCBhcmVhLCBwYXJ0aWFsbHkgPSB0cnVlKSA9PiB7XG4gICAgICAgIGNvbnN0IFtub2RlUmVjdF0gPSBnZXROb2RlUmVjdChub2RlT3JSZWN0KTtcbiAgICAgICAgaWYgKCFub2RlUmVjdCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG92ZXJsYXBwaW5nQXJlYSA9IGdldE92ZXJsYXBwaW5nQXJlYShub2RlUmVjdCwgYXJlYSk7XG4gICAgICAgIGNvbnN0IHBhcnRpYWxseVZpc2libGUgPSBwYXJ0aWFsbHkgJiYgb3ZlcmxhcHBpbmdBcmVhID4gMDtcbiAgICAgICAgcmV0dXJuIHBhcnRpYWxseVZpc2libGUgfHwgb3ZlcmxhcHBpbmdBcmVhID49IG5vZGVSZWN0LndpZHRoICogbm9kZVJlY3QuaGVpZ2h0O1xuICAgIH0sIFtdKTtcbiAgICByZXR1cm4gdXNlTWVtbygoKSA9PiB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi52aWV3cG9ydEhlbHBlcixcbiAgICAgICAgICAgIGdldE5vZGVzLFxuICAgICAgICAgICAgZ2V0Tm9kZSxcbiAgICAgICAgICAgIGdldEVkZ2VzLFxuICAgICAgICAgICAgZ2V0RWRnZSxcbiAgICAgICAgICAgIHNldE5vZGVzLFxuICAgICAgICAgICAgc2V0RWRnZXMsXG4gICAgICAgICAgICBhZGROb2RlcyxcbiAgICAgICAgICAgIGFkZEVkZ2VzLFxuICAgICAgICAgICAgdG9PYmplY3QsXG4gICAgICAgICAgICBkZWxldGVFbGVtZW50cyxcbiAgICAgICAgICAgIGdldEludGVyc2VjdGluZ05vZGVzLFxuICAgICAgICAgICAgaXNOb2RlSW50ZXJzZWN0aW5nLFxuICAgICAgICB9O1xuICAgIH0sIFtcbiAgICAgICAgdmlld3BvcnRIZWxwZXIsXG4gICAgICAgIGdldE5vZGVzLFxuICAgICAgICBnZXROb2RlLFxuICAgICAgICBnZXRFZGdlcyxcbiAgICAgICAgZ2V0RWRnZSxcbiAgICAgICAgc2V0Tm9kZXMsXG4gICAgICAgIHNldEVkZ2VzLFxuICAgICAgICBhZGROb2RlcyxcbiAgICAgICAgYWRkRWRnZXMsXG4gICAgICAgIHRvT2JqZWN0LFxuICAgICAgICBkZWxldGVFbGVtZW50cyxcbiAgICAgICAgZ2V0SW50ZXJzZWN0aW5nTm9kZXMsXG4gICAgICAgIGlzTm9kZUludGVyc2VjdGluZyxcbiAgICBdKTtcbn1cblxuY29uc3QgZGVsZXRlS2V5T3B0aW9ucyA9IHsgYWN0SW5zaWRlSW5wdXRXaXRoTW9kaWZpZXI6IGZhbHNlIH07XG52YXIgdXNlR2xvYmFsS2V5SGFuZGxlciA9ICh7IGRlbGV0ZUtleUNvZGUsIG11bHRpU2VsZWN0aW9uS2V5Q29kZSB9KSA9PiB7XG4gICAgY29uc3Qgc3RvcmUgPSB1c2VTdG9yZUFwaSgpO1xuICAgIGNvbnN0IHsgZGVsZXRlRWxlbWVudHMgfSA9IHVzZVJlYWN0RmxvdygpO1xuICAgIGNvbnN0IGRlbGV0ZUtleVByZXNzZWQgPSB1c2VLZXlQcmVzcyhkZWxldGVLZXlDb2RlLCBkZWxldGVLZXlPcHRpb25zKTtcbiAgICBjb25zdCBtdWx0aVNlbGVjdGlvbktleVByZXNzZWQgPSB1c2VLZXlQcmVzcyhtdWx0aVNlbGVjdGlvbktleUNvZGUpO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChkZWxldGVLZXlQcmVzc2VkKSB7XG4gICAgICAgICAgICBjb25zdCB7IGVkZ2VzLCBnZXROb2RlcyB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkTm9kZXMgPSBnZXROb2RlcygpLmZpbHRlcigobm9kZSkgPT4gbm9kZS5zZWxlY3RlZCk7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3RlZEVkZ2VzID0gZWRnZXMuZmlsdGVyKChlZGdlKSA9PiBlZGdlLnNlbGVjdGVkKTtcbiAgICAgICAgICAgIGRlbGV0ZUVsZW1lbnRzKHsgbm9kZXM6IHNlbGVjdGVkTm9kZXMsIGVkZ2VzOiBzZWxlY3RlZEVkZ2VzIH0pO1xuICAgICAgICAgICAgc3RvcmUuc2V0U3RhdGUoeyBub2Rlc1NlbGVjdGlvbkFjdGl2ZTogZmFsc2UgfSk7XG4gICAgICAgIH1cbiAgICB9LCBbZGVsZXRlS2V5UHJlc3NlZF0pO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIHN0b3JlLnNldFN0YXRlKHsgbXVsdGlTZWxlY3Rpb25BY3RpdmU6IG11bHRpU2VsZWN0aW9uS2V5UHJlc3NlZCB9KTtcbiAgICB9LCBbbXVsdGlTZWxlY3Rpb25LZXlQcmVzc2VkXSk7XG59O1xuXG5mdW5jdGlvbiB1c2VSZXNpemVIYW5kbGVyKHJlbmRlcmVyTm9kZSkge1xuICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBsZXQgcmVzaXplT2JzZXJ2ZXI7XG4gICAgICAgIGNvbnN0IHVwZGF0ZURpbWVuc2lvbnMgPSAoKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXJlbmRlcmVyTm9kZS5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgc2l6ZSA9IGdldERpbWVuc2lvbnMocmVuZGVyZXJOb2RlLmN1cnJlbnQpO1xuICAgICAgICAgICAgaWYgKHNpemUuaGVpZ2h0ID09PSAwIHx8IHNpemUud2lkdGggPT09IDApIHtcbiAgICAgICAgICAgICAgICBzdG9yZS5nZXRTdGF0ZSgpLm9uRXJyb3I/LignMDA0JywgZXJyb3JNZXNzYWdlc1snZXJyb3IwMDQnXSgpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHN0b3JlLnNldFN0YXRlKHsgd2lkdGg6IHNpemUud2lkdGggfHwgNTAwLCBoZWlnaHQ6IHNpemUuaGVpZ2h0IHx8IDUwMCB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgdXBkYXRlRGltZW5zaW9ucygpO1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdXBkYXRlRGltZW5zaW9ucyk7XG4gICAgICAgIGlmIChyZW5kZXJlck5vZGUuY3VycmVudCkge1xuICAgICAgICAgICAgcmVzaXplT2JzZXJ2ZXIgPSBuZXcgUmVzaXplT2JzZXJ2ZXIoKCkgPT4gdXBkYXRlRGltZW5zaW9ucygpKTtcbiAgICAgICAgICAgIHJlc2l6ZU9ic2VydmVyLm9ic2VydmUocmVuZGVyZXJOb2RlLmN1cnJlbnQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdXBkYXRlRGltZW5zaW9ucyk7XG4gICAgICAgICAgICBpZiAocmVzaXplT2JzZXJ2ZXIgJiYgcmVuZGVyZXJOb2RlLmN1cnJlbnQpIHtcbiAgICAgICAgICAgICAgICByZXNpemVPYnNlcnZlci51bm9ic2VydmUocmVuZGVyZXJOb2RlLmN1cnJlbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgIH0sIFtdKTtcbn1cblxuY29uc3QgY29udGFpbmVyU3R5bGUgPSB7XG4gICAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG4gICAgd2lkdGg6ICcxMDAlJyxcbiAgICBoZWlnaHQ6ICcxMDAlJyxcbiAgICB0b3A6IDAsXG4gICAgbGVmdDogMCxcbn07XG5cbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9iYW4tdHMtY29tbWVudCAqL1xuY29uc3Qgdmlld0NoYW5nZWQgPSAocHJldlZpZXdwb3J0LCBldmVudFRyYW5zZm9ybSkgPT4gcHJldlZpZXdwb3J0LnggIT09IGV2ZW50VHJhbnNmb3JtLnggfHwgcHJldlZpZXdwb3J0LnkgIT09IGV2ZW50VHJhbnNmb3JtLnkgfHwgcHJldlZpZXdwb3J0Lnpvb20gIT09IGV2ZW50VHJhbnNmb3JtLms7XG5jb25zdCBldmVudFRvRmxvd1RyYW5zZm9ybSA9IChldmVudFRyYW5zZm9ybSkgPT4gKHtcbiAgICB4OiBldmVudFRyYW5zZm9ybS54LFxuICAgIHk6IGV2ZW50VHJhbnNmb3JtLnksXG4gICAgem9vbTogZXZlbnRUcmFuc2Zvcm0uayxcbn0pO1xuY29uc3QgaXNXcmFwcGVkV2l0aENsYXNzID0gKGV2ZW50LCBjbGFzc05hbWUpID0+IGV2ZW50LnRhcmdldC5jbG9zZXN0KGAuJHtjbGFzc05hbWV9YCk7XG5jb25zdCBpc1JpZ2h0Q2xpY2tQYW4gPSAocGFuT25EcmFnLCB1c2VkQnV0dG9uKSA9PiB1c2VkQnV0dG9uID09PSAyICYmIEFycmF5LmlzQXJyYXkocGFuT25EcmFnKSAmJiBwYW5PbkRyYWcuaW5jbHVkZXMoMik7XG5jb25zdCB3aGVlbERlbHRhID0gKGV2ZW50KSA9PiB7XG4gICAgY29uc3QgZmFjdG9yID0gZXZlbnQuY3RybEtleSAmJiBpc01hY09zKCkgPyAxMCA6IDE7XG4gICAgcmV0dXJuIC1ldmVudC5kZWx0YVkgKiAoZXZlbnQuZGVsdGFNb2RlID09PSAxID8gMC4wNSA6IGV2ZW50LmRlbHRhTW9kZSA/IDEgOiAwLjAwMikgKiBmYWN0b3I7XG59O1xuY29uc3Qgc2VsZWN0b3IkYSA9IChzKSA9PiAoe1xuICAgIGQzWm9vbTogcy5kM1pvb20sXG4gICAgZDNTZWxlY3Rpb246IHMuZDNTZWxlY3Rpb24sXG4gICAgZDNab29tSGFuZGxlcjogcy5kM1pvb21IYW5kbGVyLFxuICAgIHVzZXJTZWxlY3Rpb25BY3RpdmU6IHMudXNlclNlbGVjdGlvbkFjdGl2ZSxcbn0pO1xuY29uc3QgWm9vbVBhbmUgPSAoeyBvbk1vdmUsIG9uTW92ZVN0YXJ0LCBvbk1vdmVFbmQsIG9uUGFuZUNvbnRleHRNZW51LCB6b29tT25TY3JvbGwgPSB0cnVlLCB6b29tT25QaW5jaCA9IHRydWUsIHBhbk9uU2Nyb2xsID0gZmFsc2UsIHBhbk9uU2Nyb2xsU3BlZWQgPSAwLjUsIHBhbk9uU2Nyb2xsTW9kZSA9IFBhbk9uU2Nyb2xsTW9kZS5GcmVlLCB6b29tT25Eb3VibGVDbGljayA9IHRydWUsIGVsZW1lbnRzU2VsZWN0YWJsZSwgcGFuT25EcmFnID0gdHJ1ZSwgZGVmYXVsdFZpZXdwb3J0LCB0cmFuc2xhdGVFeHRlbnQsIG1pblpvb20sIG1heFpvb20sIHpvb21BY3RpdmF0aW9uS2V5Q29kZSwgcHJldmVudFNjcm9sbGluZyA9IHRydWUsIGNoaWxkcmVuLCBub1doZWVsQ2xhc3NOYW1lLCBub1BhbkNsYXNzTmFtZSwgfSkgPT4ge1xuICAgIGNvbnN0IHRpbWVySWQgPSB1c2VSZWYoKTtcbiAgICBjb25zdCBzdG9yZSA9IHVzZVN0b3JlQXBpKCk7XG4gICAgY29uc3QgaXNab29taW5nT3JQYW5uaW5nID0gdXNlUmVmKGZhbHNlKTtcbiAgICBjb25zdCB6b29tZWRXaXRoUmlnaHRNb3VzZUJ1dHRvbiA9IHVzZVJlZihmYWxzZSk7XG4gICAgY29uc3Qgem9vbVBhbmUgPSB1c2VSZWYobnVsbCk7XG4gICAgY29uc3QgcHJldlRyYW5zZm9ybSA9IHVzZVJlZih7IHg6IDAsIHk6IDAsIHpvb206IDAgfSk7XG4gICAgY29uc3QgeyBkM1pvb20sIGQzU2VsZWN0aW9uLCBkM1pvb21IYW5kbGVyLCB1c2VyU2VsZWN0aW9uQWN0aXZlIH0gPSB1c2VTdG9yZShzZWxlY3RvciRhLCBzaGFsbG93KTtcbiAgICBjb25zdCB6b29tQWN0aXZhdGlvbktleVByZXNzZWQgPSB1c2VLZXlQcmVzcyh6b29tQWN0aXZhdGlvbktleUNvZGUpO1xuICAgIGNvbnN0IG1vdXNlQnV0dG9uID0gdXNlUmVmKDApO1xuICAgIGNvbnN0IGlzUGFuU2Nyb2xsaW5nID0gdXNlUmVmKGZhbHNlKTtcbiAgICBjb25zdCBwYW5TY3JvbGxUaW1lb3V0ID0gdXNlUmVmKCk7XG4gICAgdXNlUmVzaXplSGFuZGxlcih6b29tUGFuZSk7XG4gICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgaWYgKHpvb21QYW5lLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNvbnN0IGJib3ggPSB6b29tUGFuZS5jdXJyZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICAgICAgY29uc3QgZDNab29tSW5zdGFuY2UgPSB6b29tKCkuc2NhbGVFeHRlbnQoW21pblpvb20sIG1heFpvb21dKS50cmFuc2xhdGVFeHRlbnQodHJhbnNsYXRlRXh0ZW50KTtcbiAgICAgICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IHNlbGVjdCh6b29tUGFuZS5jdXJyZW50KS5jYWxsKGQzWm9vbUluc3RhbmNlKTtcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZWRUcmFuc2Zvcm0gPSB6b29tSWRlbnRpdHlcbiAgICAgICAgICAgICAgICAudHJhbnNsYXRlKGRlZmF1bHRWaWV3cG9ydC54LCBkZWZhdWx0Vmlld3BvcnQueSlcbiAgICAgICAgICAgICAgICAuc2NhbGUoY2xhbXAoZGVmYXVsdFZpZXdwb3J0Lnpvb20sIG1pblpvb20sIG1heFpvb20pKTtcbiAgICAgICAgICAgIGNvbnN0IGV4dGVudCA9IFtcbiAgICAgICAgICAgICAgICBbMCwgMF0sXG4gICAgICAgICAgICAgICAgW2Jib3gud2lkdGgsIGJib3guaGVpZ2h0XSxcbiAgICAgICAgICAgIF07XG4gICAgICAgICAgICBjb25zdCBjb25zdHJhaW5lZFRyYW5zZm9ybSA9IGQzWm9vbUluc3RhbmNlLmNvbnN0cmFpbigpKHVwZGF0ZWRUcmFuc2Zvcm0sIGV4dGVudCwgdHJhbnNsYXRlRXh0ZW50KTtcbiAgICAgICAgICAgIGQzWm9vbUluc3RhbmNlLnRyYW5zZm9ybShzZWxlY3Rpb24sIGNvbnN0cmFpbmVkVHJhbnNmb3JtKTtcbiAgICAgICAgICAgIGQzWm9vbUluc3RhbmNlLndoZWVsRGVsdGEod2hlZWxEZWx0YSk7XG4gICAgICAgICAgICBzdG9yZS5zZXRTdGF0ZSh7XG4gICAgICAgICAgICAgICAgZDNab29tOiBkM1pvb21JbnN0YW5jZSxcbiAgICAgICAgICAgICAgICBkM1NlbGVjdGlvbjogc2VsZWN0aW9uLFxuICAgICAgICAgICAgICAgIGQzWm9vbUhhbmRsZXI6IHNlbGVjdGlvbi5vbignd2hlZWwuem9vbScpLFxuICAgICAgICAgICAgICAgIC8vIHdlIG5lZWQgdG8gcGFzcyB0cmFuc2Zvcm0gYmVjYXVzZSB6b29tIGhhbmRsZXIgaXMgbm90IHJlZ2lzdGVyZWQgd2hlbiB3ZSBzZXQgdGhlIGluaXRpYWwgdHJhbnNmb3JtXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtOiBbY29uc3RyYWluZWRUcmFuc2Zvcm0ueCwgY29uc3RyYWluZWRUcmFuc2Zvcm0ueSwgY29uc3RyYWluZWRUcmFuc2Zvcm0ua10sXG4gICAgICAgICAgICAgICAgZG9tTm9kZTogem9vbVBhbmUuY3VycmVudC5jbG9zZXN0KCcucmVhY3QtZmxvdycpLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LCBbXSk7XG4gICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgaWYgKGQzU2VsZWN0aW9uICYmIGQzWm9vbSkge1xuICAgICAgICAgICAgaWYgKHBhbk9uU2Nyb2xsICYmICF6b29tQWN0aXZhdGlvbktleVByZXNzZWQgJiYgIXVzZXJTZWxlY3Rpb25BY3RpdmUpIHtcbiAgICAgICAgICAgICAgICBkM1NlbGVjdGlvbi5vbignd2hlZWwuem9vbScsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNXcmFwcGVkV2l0aENsYXNzKGV2ZW50LCBub1doZWVsQ2xhc3NOYW1lKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50Wm9vbSA9IGQzU2VsZWN0aW9uLnByb3BlcnR5KCdfX3pvb20nKS5rIHx8IDE7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IF9pc01hY09zID0gaXNNYWNPcygpO1xuICAgICAgICAgICAgICAgICAgICAvLyBtYWNvcyBzZXRzIGN0cmxLZXk9dHJ1ZSBmb3IgcGluY2ggZ2VzdHVyZSBvbiBhIHRyYWNrcGFkXG4gICAgICAgICAgICAgICAgICAgIGlmIChldmVudC5jdHJsS2V5ICYmIHpvb21PblBpbmNoICYmIF9pc01hY09zKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb2ludCA9IHBvaW50ZXIoZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcGluY2hEZWx0YSA9IHdoZWVsRGVsdGEoZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgem9vbSA9IGN1cnJlbnRab29tICogTWF0aC5wb3coMiwgcGluY2hEZWx0YSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBAdHMtaWdub3JlXG4gICAgICAgICAgICAgICAgICAgICAgICBkM1pvb20uc2NhbGVUbyhkM1NlbGVjdGlvbiwgem9vbSwgcG9pbnQsIGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvLyBpbmNyZWFzZSBzY3JvbGwgc3BlZWQgaW4gZmlyZWZveFxuICAgICAgICAgICAgICAgICAgICAvLyBmaXJlZm94OiBkZWx0YU1vZGUgPT09IDE7IGNocm9tZTogZGVsdGFNb2RlID09PSAwXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlbHRhTm9ybWFsaXplID0gZXZlbnQuZGVsdGFNb2RlID09PSAxID8gMjAgOiAxO1xuICAgICAgICAgICAgICAgICAgICBsZXQgZGVsdGFYID0gcGFuT25TY3JvbGxNb2RlID09PSBQYW5PblNjcm9sbE1vZGUuVmVydGljYWwgPyAwIDogZXZlbnQuZGVsdGFYICogZGVsdGFOb3JtYWxpemU7XG4gICAgICAgICAgICAgICAgICAgIGxldCBkZWx0YVkgPSBwYW5PblNjcm9sbE1vZGUgPT09IFBhbk9uU2Nyb2xsTW9kZS5Ib3Jpem9udGFsID8gMCA6IGV2ZW50LmRlbHRhWSAqIGRlbHRhTm9ybWFsaXplO1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGVuYWJsZXMgdmVydGljYWwgc2Nyb2xsaW5nIHdpdGggc2hpZnQgKyBzY3JvbGwgb24gd2luZG93c1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV9pc01hY09zICYmIGV2ZW50LnNoaWZ0S2V5ICYmIHBhbk9uU2Nyb2xsTW9kZSAhPT0gUGFuT25TY3JvbGxNb2RlLlZlcnRpY2FsKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkZWx0YVggPSBldmVudC5kZWx0YVkgKiBkZWx0YU5vcm1hbGl6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGRlbHRhWSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZDNab29tLnRyYW5zbGF0ZUJ5KGQzU2VsZWN0aW9uLCAtKGRlbHRhWCAvIGN1cnJlbnRab29tKSAqIHBhbk9uU2Nyb2xsU3BlZWQsIC0oZGVsdGFZIC8gY3VycmVudFpvb20pICogcGFuT25TY3JvbGxTcGVlZCwgXG4gICAgICAgICAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgICAgICAgICAgeyBpbnRlcm5hbDogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV4dFZpZXdwb3J0ID0gZXZlbnRUb0Zsb3dUcmFuc2Zvcm0oZDNTZWxlY3Rpb24ucHJvcGVydHkoJ19fem9vbScpKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeyBvblZpZXdwb3J0Q2hhbmdlU3RhcnQsIG9uVmlld3BvcnRDaGFuZ2UsIG9uVmlld3BvcnRDaGFuZ2VFbmQgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIGNsZWFyVGltZW91dChwYW5TY3JvbGxUaW1lb3V0LmN1cnJlbnQpO1xuICAgICAgICAgICAgICAgICAgICAvLyBmb3IgcGFuIG9uIHNjcm9sbCB3ZSBuZWVkIHRvIGhhbmRsZSB0aGUgZXZlbnQgY2FsbHMgb24gb3VyIG93blxuICAgICAgICAgICAgICAgICAgICAvLyB3ZSBjYW4ndCB1c2UgdGhlIHN0YXJ0LCB6b29tIGFuZCBlbmQgZXZlbnRzIGZyb20gZDMtem9vbVxuICAgICAgICAgICAgICAgICAgICAvLyBiZWNhdXNlIHN0YXJ0IGFuZCBtb3ZlIGdldHMgY2FsbGVkIG9uIGV2ZXJ5IHNjcm9sbCBldmVudCBhbmQgbm90IG9uY2UgYXQgdGhlIGJlZ2lubmluZ1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWlzUGFuU2Nyb2xsaW5nLmN1cnJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzUGFuU2Nyb2xsaW5nLmN1cnJlbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgb25Nb3ZlU3RhcnQ/LihldmVudCwgbmV4dFZpZXdwb3J0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uVmlld3BvcnRDaGFuZ2VTdGFydD8uKG5leHRWaWV3cG9ydCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzUGFuU2Nyb2xsaW5nLmN1cnJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uTW92ZT8uKGV2ZW50LCBuZXh0Vmlld3BvcnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgb25WaWV3cG9ydENoYW5nZT8uKG5leHRWaWV3cG9ydCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwYW5TY3JvbGxUaW1lb3V0LmN1cnJlbnQgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvbk1vdmVFbmQ/LihldmVudCwgbmV4dFZpZXdwb3J0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvblZpZXdwb3J0Q2hhbmdlRW5kPy4obmV4dFZpZXdwb3J0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpc1BhblNjcm9sbGluZy5jdXJyZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICB9LCAxNTApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSwgeyBwYXNzaXZlOiBmYWxzZSB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBkM1pvb21IYW5kbGVyICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgICAgICAgICAgIGQzU2VsZWN0aW9uLm9uKCd3aGVlbC56b29tJywgZnVuY3Rpb24gKGV2ZW50LCBkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghcHJldmVudFNjcm9sbGluZyB8fCBpc1dyYXBwZWRXaXRoQ2xhc3MoZXZlbnQsIG5vV2hlZWxDbGFzc05hbWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICBkM1pvb21IYW5kbGVyLmNhbGwodGhpcywgZXZlbnQsIGQpO1xuICAgICAgICAgICAgICAgIH0sIHsgcGFzc2l2ZTogZmFsc2UgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCBbXG4gICAgICAgIHVzZXJTZWxlY3Rpb25BY3RpdmUsXG4gICAgICAgIHBhbk9uU2Nyb2xsLFxuICAgICAgICBwYW5PblNjcm9sbE1vZGUsXG4gICAgICAgIGQzU2VsZWN0aW9uLFxuICAgICAgICBkM1pvb20sXG4gICAgICAgIGQzWm9vbUhhbmRsZXIsXG4gICAgICAgIHpvb21BY3RpdmF0aW9uS2V5UHJlc3NlZCxcbiAgICAgICAgem9vbU9uUGluY2gsXG4gICAgICAgIHByZXZlbnRTY3JvbGxpbmcsXG4gICAgICAgIG5vV2hlZWxDbGFzc05hbWUsXG4gICAgICAgIG9uTW92ZVN0YXJ0LFxuICAgICAgICBvbk1vdmUsXG4gICAgICAgIG9uTW92ZUVuZCxcbiAgICBdKTtcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBpZiAoZDNab29tKSB7XG4gICAgICAgICAgICBkM1pvb20ub24oJ3N0YXJ0JywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFldmVudC5zb3VyY2VFdmVudCB8fCBldmVudC5zb3VyY2VFdmVudC5pbnRlcm5hbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gd2UgbmVlZCB0byByZW1lbWJlciBpdCBoZXJlLCBiZWNhdXNlIGl0J3MgYWx3YXlzIDAgaW4gdGhlIFwiem9vbVwiIGV2ZW50XG4gICAgICAgICAgICAgICAgbW91c2VCdXR0b24uY3VycmVudCA9IGV2ZW50LnNvdXJjZUV2ZW50Py5idXR0b247XG4gICAgICAgICAgICAgICAgY29uc3QgeyBvblZpZXdwb3J0Q2hhbmdlU3RhcnQgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZmxvd1RyYW5zZm9ybSA9IGV2ZW50VG9GbG93VHJhbnNmb3JtKGV2ZW50LnRyYW5zZm9ybSk7XG4gICAgICAgICAgICAgICAgaXNab29taW5nT3JQYW5uaW5nLmN1cnJlbnQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHByZXZUcmFuc2Zvcm0uY3VycmVudCA9IGZsb3dUcmFuc2Zvcm07XG4gICAgICAgICAgICAgICAgaWYgKGV2ZW50LnNvdXJjZUV2ZW50Py50eXBlID09PSAnbW91c2Vkb3duJykge1xuICAgICAgICAgICAgICAgICAgICBzdG9yZS5zZXRTdGF0ZSh7IHBhbmVEcmFnZ2luZzogdHJ1ZSB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgb25WaWV3cG9ydENoYW5nZVN0YXJ0Py4oZmxvd1RyYW5zZm9ybSk7XG4gICAgICAgICAgICAgICAgb25Nb3ZlU3RhcnQ/LihldmVudC5zb3VyY2VFdmVudCwgZmxvd1RyYW5zZm9ybSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sIFtkM1pvb20sIG9uTW92ZVN0YXJ0XSk7XG4gICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgaWYgKGQzWm9vbSkge1xuICAgICAgICAgICAgaWYgKHVzZXJTZWxlY3Rpb25BY3RpdmUgJiYgIWlzWm9vbWluZ09yUGFubmluZy5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgZDNab29tLm9uKCd6b29tJywgbnVsbCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmICghdXNlclNlbGVjdGlvbkFjdGl2ZSkge1xuICAgICAgICAgICAgICAgIGQzWm9vbS5vbignem9vbScsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IG9uVmlld3BvcnRDaGFuZ2UgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIHN0b3JlLnNldFN0YXRlKHsgdHJhbnNmb3JtOiBbZXZlbnQudHJhbnNmb3JtLngsIGV2ZW50LnRyYW5zZm9ybS55LCBldmVudC50cmFuc2Zvcm0ua10gfSk7XG4gICAgICAgICAgICAgICAgICAgIHpvb21lZFdpdGhSaWdodE1vdXNlQnV0dG9uLmN1cnJlbnQgPSAhIShvblBhbmVDb250ZXh0TWVudSAmJiBpc1JpZ2h0Q2xpY2tQYW4ocGFuT25EcmFnLCBtb3VzZUJ1dHRvbi5jdXJyZW50ID8/IDApKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKChvbk1vdmUgfHwgb25WaWV3cG9ydENoYW5nZSkgJiYgIWV2ZW50LnNvdXJjZUV2ZW50Py5pbnRlcm5hbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmxvd1RyYW5zZm9ybSA9IGV2ZW50VG9GbG93VHJhbnNmb3JtKGV2ZW50LnRyYW5zZm9ybSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvblZpZXdwb3J0Q2hhbmdlPy4oZmxvd1RyYW5zZm9ybSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBvbk1vdmU/LihldmVudC5zb3VyY2VFdmVudCwgZmxvd1RyYW5zZm9ybSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sIFt1c2VyU2VsZWN0aW9uQWN0aXZlLCBkM1pvb20sIG9uTW92ZSwgcGFuT25EcmFnLCBvblBhbmVDb250ZXh0TWVudV0pO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChkM1pvb20pIHtcbiAgICAgICAgICAgIGQzWm9vbS5vbignZW5kJywgKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFldmVudC5zb3VyY2VFdmVudCB8fCBldmVudC5zb3VyY2VFdmVudC5pbnRlcm5hbCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgeyBvblZpZXdwb3J0Q2hhbmdlRW5kIH0gPSBzdG9yZS5nZXRTdGF0ZSgpO1xuICAgICAgICAgICAgICAgIGlzWm9vbWluZ09yUGFubmluZy5jdXJyZW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgc3RvcmUuc2V0U3RhdGUoeyBwYW5lRHJhZ2dpbmc6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgIGlmIChvblBhbmVDb250ZXh0TWVudSAmJlxuICAgICAgICAgICAgICAgICAgICBpc1JpZ2h0Q2xpY2tQYW4ocGFuT25EcmFnLCBtb3VzZUJ1dHRvbi5jdXJyZW50ID8/IDApICYmXG4gICAgICAgICAgICAgICAgICAgICF6b29tZWRXaXRoUmlnaHRNb3VzZUJ1dHRvbi5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIG9uUGFuZUNvbnRleHRNZW51KGV2ZW50LnNvdXJjZUV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgem9vbWVkV2l0aFJpZ2h0TW91c2VCdXR0b24uY3VycmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGlmICgob25Nb3ZlRW5kIHx8IG9uVmlld3BvcnRDaGFuZ2VFbmQpICYmIHZpZXdDaGFuZ2VkKHByZXZUcmFuc2Zvcm0uY3VycmVudCwgZXZlbnQudHJhbnNmb3JtKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmbG93VHJhbnNmb3JtID0gZXZlbnRUb0Zsb3dUcmFuc2Zvcm0oZXZlbnQudHJhbnNmb3JtKTtcbiAgICAgICAgICAgICAgICAgICAgcHJldlRyYW5zZm9ybS5jdXJyZW50ID0gZmxvd1RyYW5zZm9ybTtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVySWQuY3VycmVudCk7XG4gICAgICAgICAgICAgICAgICAgIHRpbWVySWQuY3VycmVudCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgb25WaWV3cG9ydENoYW5nZUVuZD8uKGZsb3dUcmFuc2Zvcm0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgb25Nb3ZlRW5kPy4oZXZlbnQuc291cmNlRXZlbnQsIGZsb3dUcmFuc2Zvcm0pO1xuICAgICAgICAgICAgICAgICAgICB9LCBwYW5PblNjcm9sbCA/IDE1MCA6IDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfSwgW2QzWm9vbSwgcGFuT25TY3JvbGwsIHBhbk9uRHJhZywgb25Nb3ZlRW5kLCBvblBhbmVDb250ZXh0TWVudV0pO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChkM1pvb20pIHtcbiAgICAgICAgICAgIGQzWm9vbS5maWx0ZXIoKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3Qgem9vbVNjcm9sbCA9IHpvb21BY3RpdmF0aW9uS2V5UHJlc3NlZCB8fCB6b29tT25TY3JvbGw7XG4gICAgICAgICAgICAgICAgY29uc3QgcGluY2hab29tID0gem9vbU9uUGluY2ggJiYgZXZlbnQuY3RybEtleTtcbiAgICAgICAgICAgICAgICBpZiAoKHBhbk9uRHJhZyA9PT0gdHJ1ZSB8fCAoQXJyYXkuaXNBcnJheShwYW5PbkRyYWcpICYmIHBhbk9uRHJhZy5pbmNsdWRlcygxKSkpICYmXG4gICAgICAgICAgICAgICAgICAgIGV2ZW50LmJ1dHRvbiA9PT0gMSAmJlxuICAgICAgICAgICAgICAgICAgICBldmVudC50eXBlID09PSAnbW91c2Vkb3duJyAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNXcmFwcGVkV2l0aENsYXNzKGV2ZW50LCAncmVhY3QtZmxvd19fbm9kZScpIHx8IGlzV3JhcHBlZFdpdGhDbGFzcyhldmVudCwgJ3JlYWN0LWZsb3dfX2VkZ2UnKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGlmIGFsbCBpbnRlcmFjdGlvbnMgYXJlIGRpc2FibGVkLCB3ZSBwcmV2ZW50IGFsbCB6b29tIGV2ZW50c1xuICAgICAgICAgICAgICAgIGlmICghcGFuT25EcmFnICYmICF6b29tU2Nyb2xsICYmICFwYW5PblNjcm9sbCAmJiAhem9vbU9uRG91YmxlQ2xpY2sgJiYgIXpvb21PblBpbmNoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gZHVyaW5nIGEgc2VsZWN0aW9uIHdlIHByZXZlbnQgYWxsIG90aGVyIGludGVyYWN0aW9uc1xuICAgICAgICAgICAgICAgIGlmICh1c2VyU2VsZWN0aW9uQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gaWYgem9vbSBvbiBkb3VibGUgY2xpY2sgaXMgZGlzYWJsZWQsIHdlIHByZXZlbnQgdGhlIGRvdWJsZSBjbGljayBldmVudFxuICAgICAgICAgICAgICAgIGlmICghem9vbU9uRG91YmxlQ2xpY2sgJiYgZXZlbnQudHlwZSA9PT0gJ2RibGNsaWNrJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSB0YXJnZXQgZWxlbWVudCBpcyBpbnNpZGUgYW4gZWxlbWVudCB3aXRoIHRoZSBub3doZWVsIGNsYXNzLCB3ZSBwcmV2ZW50IHpvb21pbmdcbiAgICAgICAgICAgICAgICBpZiAoaXNXcmFwcGVkV2l0aENsYXNzKGV2ZW50LCBub1doZWVsQ2xhc3NOYW1lKSAmJiBldmVudC50eXBlID09PSAnd2hlZWwnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIHRhcmdldCBlbGVtZW50IGlzIGluc2lkZSBhbiBlbGVtZW50IHdpdGggdGhlIG5vcGFuIGNsYXNzLCB3ZSBwcmV2ZW50IHBhbm5pbmdcbiAgICAgICAgICAgICAgICBpZiAoaXNXcmFwcGVkV2l0aENsYXNzKGV2ZW50LCBub1BhbkNsYXNzTmFtZSkgJiZcbiAgICAgICAgICAgICAgICAgICAgKGV2ZW50LnR5cGUgIT09ICd3aGVlbCcgfHwgKHBhbk9uU2Nyb2xsICYmIGV2ZW50LnR5cGUgPT09ICd3aGVlbCcgJiYgIXpvb21BY3RpdmF0aW9uS2V5UHJlc3NlZCkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCF6b29tT25QaW5jaCAmJiBldmVudC5jdHJsS2V5ICYmIGV2ZW50LnR5cGUgPT09ICd3aGVlbCcpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyB3aGVuIHRoZXJlIGlzIG5vIHNjcm9sbCBoYW5kbGluZyBlbmFibGVkLCB3ZSBwcmV2ZW50IGFsbCB3aGVlbCBldmVudHNcbiAgICAgICAgICAgICAgICBpZiAoIXpvb21TY3JvbGwgJiYgIXBhbk9uU2Nyb2xsICYmICFwaW5jaFpvb20gJiYgZXZlbnQudHlwZSA9PT0gJ3doZWVsJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIGlmIHRoZSBwYW5lIGlzIG5vdCBtb3ZhYmxlLCB3ZSBwcmV2ZW50IGRyYWdnaW5nIGl0IHdpdGggbW91c2VzdGFydCBvciB0b3VjaHN0YXJ0XG4gICAgICAgICAgICAgICAgaWYgKCFwYW5PbkRyYWcgJiYgKGV2ZW50LnR5cGUgPT09ICdtb3VzZWRvd24nIHx8IGV2ZW50LnR5cGUgPT09ICd0b3VjaHN0YXJ0JykpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyBpZiB0aGUgcGFuZSBpcyBvbmx5IG1vdmFibGUgdXNpbmcgYWxsb3dlZCBjbGlja3NcbiAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShwYW5PbkRyYWcpICYmXG4gICAgICAgICAgICAgICAgICAgICFwYW5PbkRyYWcuaW5jbHVkZXMoZXZlbnQuYnV0dG9uKSAmJlxuICAgICAgICAgICAgICAgICAgICAoZXZlbnQudHlwZSA9PT0gJ21vdXNlZG93bicgfHwgZXZlbnQudHlwZSA9PT0gJ3RvdWNoc3RhcnQnKSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFdlIG9ubHkgYWxsb3cgcmlnaHQgY2xpY2tzIGlmIHBhbiBvbiBkcmFnIGlzIHNldCB0byByaWdodCBjbGlja1xuICAgICAgICAgICAgICAgIGNvbnN0IGJ1dHRvbkFsbG93ZWQgPSAoQXJyYXkuaXNBcnJheShwYW5PbkRyYWcpICYmIHBhbk9uRHJhZy5pbmNsdWRlcyhldmVudC5idXR0b24pKSB8fCAhZXZlbnQuYnV0dG9uIHx8IGV2ZW50LmJ1dHRvbiA8PSAxO1xuICAgICAgICAgICAgICAgIC8vIGRlZmF1bHQgZmlsdGVyIGZvciBkMy16b29tXG4gICAgICAgICAgICAgICAgcmV0dXJuICghZXZlbnQuY3RybEtleSB8fCBldmVudC50eXBlID09PSAnd2hlZWwnKSAmJiBidXR0b25BbGxvd2VkO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LCBbXG4gICAgICAgIHVzZXJTZWxlY3Rpb25BY3RpdmUsXG4gICAgICAgIGQzWm9vbSxcbiAgICAgICAgem9vbU9uU2Nyb2xsLFxuICAgICAgICB6b29tT25QaW5jaCxcbiAgICAgICAgcGFuT25TY3JvbGwsXG4gICAgICAgIHpvb21PbkRvdWJsZUNsaWNrLFxuICAgICAgICBwYW5PbkRyYWcsXG4gICAgICAgIGVsZW1lbnRzU2VsZWN0YWJsZSxcbiAgICAgICAgem9vbUFjdGl2YXRpb25LZXlQcmVzc2VkLFxuICAgIF0pO1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJyZWFjdC1mbG93X19yZW5kZXJlclwiLCByZWY6IHpvb21QYW5lLCBzdHlsZTogY29udGFpbmVyU3R5bGUgfSwgY2hpbGRyZW4pKTtcbn07XG5cbmNvbnN0IHNlbGVjdG9yJDkgPSAocykgPT4gKHtcbiAgICB1c2VyU2VsZWN0aW9uQWN0aXZlOiBzLnVzZXJTZWxlY3Rpb25BY3RpdmUsXG4gICAgdXNlclNlbGVjdGlvblJlY3Q6IHMudXNlclNlbGVjdGlvblJlY3QsXG59KTtcbmZ1bmN0aW9uIFVzZXJTZWxlY3Rpb24oKSB7XG4gICAgY29uc3QgeyB1c2VyU2VsZWN0aW9uQWN0aXZlLCB1c2VyU2VsZWN0aW9uUmVjdCB9ID0gdXNlU3RvcmUoc2VsZWN0b3IkOSwgc2hhbGxvdyk7XG4gICAgY29uc3QgaXNBY3RpdmUgPSB1c2VyU2VsZWN0aW9uQWN0aXZlICYmIHVzZXJTZWxlY3Rpb25SZWN0O1xuICAgIGlmICghaXNBY3RpdmUpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogXCJyZWFjdC1mbG93X19zZWxlY3Rpb24gcmVhY3QtZmxvd19fY29udGFpbmVyXCIsIHN0eWxlOiB7XG4gICAgICAgICAgICB3aWR0aDogdXNlclNlbGVjdGlvblJlY3Qud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHVzZXJTZWxlY3Rpb25SZWN0LmhlaWdodCxcbiAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgke3VzZXJTZWxlY3Rpb25SZWN0Lnh9cHgsICR7dXNlclNlbGVjdGlvblJlY3QueX1weClgLFxuICAgICAgICB9IH0pKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlUGFyZW50RXhwYW5kKHJlcywgdXBkYXRlSXRlbSkge1xuICAgIGNvbnN0IHBhcmVudCA9IHJlcy5maW5kKChlKSA9PiBlLmlkID09PSB1cGRhdGVJdGVtLnBhcmVudE5vZGUpO1xuICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgY29uc3QgZXh0ZW5kV2lkdGggPSB1cGRhdGVJdGVtLnBvc2l0aW9uLnggKyB1cGRhdGVJdGVtLndpZHRoIC0gcGFyZW50LndpZHRoO1xuICAgICAgICBjb25zdCBleHRlbmRIZWlnaHQgPSB1cGRhdGVJdGVtLnBvc2l0aW9uLnkgKyB1cGRhdGVJdGVtLmhlaWdodCAtIHBhcmVudC5oZWlnaHQ7XG4gICAgICAgIGlmIChleHRlbmRXaWR0aCA+IDAgfHwgZXh0ZW5kSGVpZ2h0ID4gMCB8fCB1cGRhdGVJdGVtLnBvc2l0aW9uLnggPCAwIHx8IHVwZGF0ZUl0ZW0ucG9zaXRpb24ueSA8IDApIHtcbiAgICAgICAgICAgIHBhcmVudC5zdHlsZSA9IHsgLi4ucGFyZW50LnN0eWxlIH0gfHwge307XG4gICAgICAgICAgICBwYXJlbnQuc3R5bGUud2lkdGggPSBwYXJlbnQuc3R5bGUud2lkdGggPz8gcGFyZW50LndpZHRoO1xuICAgICAgICAgICAgcGFyZW50LnN0eWxlLmhlaWdodCA9IHBhcmVudC5zdHlsZS5oZWlnaHQgPz8gcGFyZW50LmhlaWdodDtcbiAgICAgICAgICAgIGlmIChleHRlbmRXaWR0aCA+IDApIHtcbiAgICAgICAgICAgICAgICBwYXJlbnQuc3R5bGUud2lkdGggKz0gZXh0ZW5kV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZXh0ZW5kSGVpZ2h0ID4gMCkge1xuICAgICAgICAgICAgICAgIHBhcmVudC5zdHlsZS5oZWlnaHQgKz0gZXh0ZW5kSGVpZ2h0O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVwZGF0ZUl0ZW0ucG9zaXRpb24ueCA8IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCB4RGlmZiA9IE1hdGguYWJzKHVwZGF0ZUl0ZW0ucG9zaXRpb24ueCk7XG4gICAgICAgICAgICAgICAgcGFyZW50LnBvc2l0aW9uLnggPSBwYXJlbnQucG9zaXRpb24ueCAtIHhEaWZmO1xuICAgICAgICAgICAgICAgIHBhcmVudC5zdHlsZS53aWR0aCArPSB4RGlmZjtcbiAgICAgICAgICAgICAgICB1cGRhdGVJdGVtLnBvc2l0aW9uLnggPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHVwZGF0ZUl0ZW0ucG9zaXRpb24ueSA8IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCB5RGlmZiA9IE1hdGguYWJzKHVwZGF0ZUl0ZW0ucG9zaXRpb24ueSk7XG4gICAgICAgICAgICAgICAgcGFyZW50LnBvc2l0aW9uLnkgPSBwYXJlbnQucG9zaXRpb24ueSAtIHlEaWZmO1xuICAgICAgICAgICAgICAgIHBhcmVudC5zdHlsZS5oZWlnaHQgKz0geURpZmY7XG4gICAgICAgICAgICAgICAgdXBkYXRlSXRlbS5wb3NpdGlvbi55ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHBhcmVudC53aWR0aCA9IHBhcmVudC5zdHlsZS53aWR0aDtcbiAgICAgICAgICAgIHBhcmVudC5oZWlnaHQgPSBwYXJlbnQuc3R5bGUuaGVpZ2h0O1xuICAgICAgICB9XG4gICAgfVxufVxuZnVuY3Rpb24gYXBwbHlDaGFuZ2VzKGNoYW5nZXMsIGVsZW1lbnRzKSB7XG4gICAgLy8gd2UgbmVlZCB0aGlzIGhhY2sgdG8gaGFuZGxlIHRoZSBzZXROb2RlcyBhbmQgc2V0RWRnZXMgZnVuY3Rpb24gb2YgdGhlIHVzZVJlYWN0RmxvdyBob29rIGZvciBjb250cm9sbGVkIGZsb3dzXG4gICAgaWYgKGNoYW5nZXMuc29tZSgoYykgPT4gYy50eXBlID09PSAncmVzZXQnKSkge1xuICAgICAgICByZXR1cm4gY2hhbmdlcy5maWx0ZXIoKGMpID0+IGMudHlwZSA9PT0gJ3Jlc2V0JykubWFwKChjKSA9PiBjLml0ZW0pO1xuICAgIH1cbiAgICBjb25zdCBpbml0RWxlbWVudHMgPSBjaGFuZ2VzLmZpbHRlcigoYykgPT4gYy50eXBlID09PSAnYWRkJykubWFwKChjKSA9PiBjLml0ZW0pO1xuICAgIHJldHVybiBlbGVtZW50cy5yZWR1Y2UoKHJlcywgaXRlbSkgPT4ge1xuICAgICAgICBjb25zdCBjdXJyZW50Q2hhbmdlcyA9IGNoYW5nZXMuZmlsdGVyKChjKSA9PiBjLmlkID09PSBpdGVtLmlkKTtcbiAgICAgICAgaWYgKGN1cnJlbnRDaGFuZ2VzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmVzLnB1c2goaXRlbSk7XG4gICAgICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHVwZGF0ZUl0ZW0gPSB7IC4uLml0ZW0gfTtcbiAgICAgICAgZm9yIChjb25zdCBjdXJyZW50Q2hhbmdlIG9mIGN1cnJlbnRDaGFuZ2VzKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudENoYW5nZSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoY3VycmVudENoYW5nZS50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ3NlbGVjdCc6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZUl0ZW0uc2VsZWN0ZWQgPSBjdXJyZW50Q2hhbmdlLnNlbGVjdGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncG9zaXRpb24nOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRDaGFuZ2UucG9zaXRpb24gIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlSXRlbS5wb3NpdGlvbiA9IGN1cnJlbnRDaGFuZ2UucG9zaXRpb247XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRDaGFuZ2UucG9zaXRpb25BYnNvbHV0ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVJdGVtLnBvc2l0aW9uQWJzb2x1dGUgPSBjdXJyZW50Q2hhbmdlLnBvc2l0aW9uQWJzb2x1dGU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRDaGFuZ2UuZHJhZ2dpbmcgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlSXRlbS5kcmFnZ2luZyA9IGN1cnJlbnRDaGFuZ2UuZHJhZ2dpbmc7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodXBkYXRlSXRlbS5leHBhbmRQYXJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBoYW5kbGVQYXJlbnRFeHBhbmQocmVzLCB1cGRhdGVJdGVtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgJ2RpbWVuc2lvbnMnOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGN1cnJlbnRDaGFuZ2UuZGltZW5zaW9ucyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVJdGVtLndpZHRoID0gY3VycmVudENoYW5nZS5kaW1lbnNpb25zLndpZHRoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZUl0ZW0uaGVpZ2h0ID0gY3VycmVudENoYW5nZS5kaW1lbnNpb25zLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgY3VycmVudENoYW5nZS51cGRhdGVTdHlsZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVJdGVtLnN0eWxlID0geyAuLi4odXBkYXRlSXRlbS5zdHlsZSB8fCB7fSksIC4uLmN1cnJlbnRDaGFuZ2UuZGltZW5zaW9ucyB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBjdXJyZW50Q2hhbmdlLnJlc2l6aW5nID09PSAnYm9vbGVhbicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVJdGVtLnJlc2l6aW5nID0gY3VycmVudENoYW5nZS5yZXNpemluZztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1cGRhdGVJdGVtLmV4cGFuZFBhcmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZVBhcmVudEV4cGFuZChyZXMsIHVwZGF0ZUl0ZW0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY2FzZSAncmVtb3ZlJzoge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXMucHVzaCh1cGRhdGVJdGVtKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9LCBpbml0RWxlbWVudHMpO1xufVxuZnVuY3Rpb24gYXBwbHlOb2RlQ2hhbmdlcyhjaGFuZ2VzLCBub2Rlcykge1xuICAgIHJldHVybiBhcHBseUNoYW5nZXMoY2hhbmdlcywgbm9kZXMpO1xufVxuZnVuY3Rpb24gYXBwbHlFZGdlQ2hhbmdlcyhjaGFuZ2VzLCBlZGdlcykge1xuICAgIHJldHVybiBhcHBseUNoYW5nZXMoY2hhbmdlcywgZWRnZXMpO1xufVxuY29uc3QgY3JlYXRlU2VsZWN0aW9uQ2hhbmdlID0gKGlkLCBzZWxlY3RlZCkgPT4gKHtcbiAgICBpZCxcbiAgICB0eXBlOiAnc2VsZWN0JyxcbiAgICBzZWxlY3RlZCxcbn0pO1xuZnVuY3Rpb24gZ2V0U2VsZWN0aW9uQ2hhbmdlcyhpdGVtcywgc2VsZWN0ZWRJZHMpIHtcbiAgICByZXR1cm4gaXRlbXMucmVkdWNlKChyZXMsIGl0ZW0pID0+IHtcbiAgICAgICAgY29uc3Qgd2lsbEJlU2VsZWN0ZWQgPSBzZWxlY3RlZElkcy5pbmNsdWRlcyhpdGVtLmlkKTtcbiAgICAgICAgaWYgKCFpdGVtLnNlbGVjdGVkICYmIHdpbGxCZVNlbGVjdGVkKSB7XG4gICAgICAgICAgICBpdGVtLnNlbGVjdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHJlcy5wdXNoKGNyZWF0ZVNlbGVjdGlvbkNoYW5nZShpdGVtLmlkLCB0cnVlKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoaXRlbS5zZWxlY3RlZCAmJiAhd2lsbEJlU2VsZWN0ZWQpIHtcbiAgICAgICAgICAgIGl0ZW0uc2VsZWN0ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIHJlcy5wdXNoKGNyZWF0ZVNlbGVjdGlvbkNoYW5nZShpdGVtLmlkLCBmYWxzZSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfSwgW10pO1xufVxuXG4vKipcbiAqIFRoZSB1c2VyIHNlbGVjdGlvbiByZWN0YW5nbGUgZ2V0cyBkaXNwbGF5ZWQgd2hlbiBhIHVzZXIgZHJhZ3MgdGhlIG1vdXNlIHdoaWxlIHByZXNzaW5nIHNoaWZ0XG4gKi9cbmNvbnN0IHdyYXBIYW5kbGVyID0gKGhhbmRsZXIsIGNvbnRhaW5lclJlZikgPT4ge1xuICAgIHJldHVybiAoZXZlbnQpID0+IHtcbiAgICAgICAgaWYgKGV2ZW50LnRhcmdldCAhPT0gY29udGFpbmVyUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBoYW5kbGVyPy4oZXZlbnQpO1xuICAgIH07XG59O1xuY29uc3Qgc2VsZWN0b3IkOCA9IChzKSA9PiAoe1xuICAgIHVzZXJTZWxlY3Rpb25BY3RpdmU6IHMudXNlclNlbGVjdGlvbkFjdGl2ZSxcbiAgICBlbGVtZW50c1NlbGVjdGFibGU6IHMuZWxlbWVudHNTZWxlY3RhYmxlLFxuICAgIGRyYWdnaW5nOiBzLnBhbmVEcmFnZ2luZyxcbn0pO1xuY29uc3QgUGFuZSA9IG1lbW8oKHsgaXNTZWxlY3RpbmcsIHNlbGVjdGlvbk1vZGUgPSBTZWxlY3Rpb25Nb2RlLkZ1bGwsIHBhbk9uRHJhZywgb25TZWxlY3Rpb25TdGFydCwgb25TZWxlY3Rpb25FbmQsIG9uUGFuZUNsaWNrLCBvblBhbmVDb250ZXh0TWVudSwgb25QYW5lU2Nyb2xsLCBvblBhbmVNb3VzZUVudGVyLCBvblBhbmVNb3VzZU1vdmUsIG9uUGFuZU1vdXNlTGVhdmUsIGNoaWxkcmVuLCB9KSA9PiB7XG4gICAgY29uc3QgY29udGFpbmVyID0gdXNlUmVmKG51bGwpO1xuICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICBjb25zdCBwcmV2U2VsZWN0ZWROb2Rlc0NvdW50ID0gdXNlUmVmKDApO1xuICAgIGNvbnN0IHByZXZTZWxlY3RlZEVkZ2VzQ291bnQgPSB1c2VSZWYoMCk7XG4gICAgY29uc3QgY29udGFpbmVyQm91bmRzID0gdXNlUmVmKCk7XG4gICAgY29uc3QgeyB1c2VyU2VsZWN0aW9uQWN0aXZlLCBlbGVtZW50c1NlbGVjdGFibGUsIGRyYWdnaW5nIH0gPSB1c2VTdG9yZShzZWxlY3RvciQ4LCBzaGFsbG93KTtcbiAgICBjb25zdCByZXNldFVzZXJTZWxlY3Rpb24gPSAoKSA9PiB7XG4gICAgICAgIHN0b3JlLnNldFN0YXRlKHsgdXNlclNlbGVjdGlvbkFjdGl2ZTogZmFsc2UsIHVzZXJTZWxlY3Rpb25SZWN0OiBudWxsIH0pO1xuICAgICAgICBwcmV2U2VsZWN0ZWROb2Rlc0NvdW50LmN1cnJlbnQgPSAwO1xuICAgICAgICBwcmV2U2VsZWN0ZWRFZGdlc0NvdW50LmN1cnJlbnQgPSAwO1xuICAgIH07XG4gICAgY29uc3Qgb25DbGljayA9IChldmVudCkgPT4ge1xuICAgICAgICBvblBhbmVDbGljaz8uKGV2ZW50KTtcbiAgICAgICAgc3RvcmUuZ2V0U3RhdGUoKS5yZXNldFNlbGVjdGVkRWxlbWVudHMoKTtcbiAgICAgICAgc3RvcmUuc2V0U3RhdGUoeyBub2Rlc1NlbGVjdGlvbkFjdGl2ZTogZmFsc2UgfSk7XG4gICAgfTtcbiAgICBjb25zdCBvbkNvbnRleHRNZW51ID0gKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHBhbk9uRHJhZykgJiYgcGFuT25EcmFnPy5pbmNsdWRlcygyKSkge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBvblBhbmVDb250ZXh0TWVudT8uKGV2ZW50KTtcbiAgICB9O1xuICAgIGNvbnN0IG9uV2hlZWwgPSBvblBhbmVTY3JvbGwgPyAoZXZlbnQpID0+IG9uUGFuZVNjcm9sbChldmVudCkgOiB1bmRlZmluZWQ7XG4gICAgY29uc3Qgb25Nb3VzZURvd24gPSAoZXZlbnQpID0+IHtcbiAgICAgICAgY29uc3QgeyByZXNldFNlbGVjdGVkRWxlbWVudHMsIGRvbU5vZGUgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgIGNvbnRhaW5lckJvdW5kcy5jdXJyZW50ID0gZG9tTm9kZT8uZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIGlmICghZWxlbWVudHNTZWxlY3RhYmxlIHx8XG4gICAgICAgICAgICAhaXNTZWxlY3RpbmcgfHxcbiAgICAgICAgICAgIGV2ZW50LmJ1dHRvbiAhPT0gMCB8fFxuICAgICAgICAgICAgZXZlbnQudGFyZ2V0ICE9PSBjb250YWluZXIuY3VycmVudCB8fFxuICAgICAgICAgICAgIWNvbnRhaW5lckJvdW5kcy5jdXJyZW50KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyB4LCB5IH0gPSBnZXRFdmVudFBvc2l0aW9uKGV2ZW50LCBjb250YWluZXJCb3VuZHMuY3VycmVudCk7XG4gICAgICAgIHJlc2V0U2VsZWN0ZWRFbGVtZW50cygpO1xuICAgICAgICBzdG9yZS5zZXRTdGF0ZSh7XG4gICAgICAgICAgICB1c2VyU2VsZWN0aW9uUmVjdDoge1xuICAgICAgICAgICAgICAgIHdpZHRoOiAwLFxuICAgICAgICAgICAgICAgIGhlaWdodDogMCxcbiAgICAgICAgICAgICAgICBzdGFydFg6IHgsXG4gICAgICAgICAgICAgICAgc3RhcnRZOiB5LFxuICAgICAgICAgICAgICAgIHgsXG4gICAgICAgICAgICAgICAgeSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0pO1xuICAgICAgICBvblNlbGVjdGlvblN0YXJ0Py4oZXZlbnQpO1xuICAgIH07XG4gICAgY29uc3Qgb25Nb3VzZU1vdmUgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgY29uc3QgeyB1c2VyU2VsZWN0aW9uUmVjdCwgbm9kZUludGVybmFscywgZWRnZXMsIHRyYW5zZm9ybSwgb25Ob2Rlc0NoYW5nZSwgb25FZGdlc0NoYW5nZSwgbm9kZU9yaWdpbiwgZ2V0Tm9kZXMgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgIGlmICghaXNTZWxlY3RpbmcgfHwgIWNvbnRhaW5lckJvdW5kcy5jdXJyZW50IHx8ICF1c2VyU2VsZWN0aW9uUmVjdCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHN0b3JlLnNldFN0YXRlKHsgdXNlclNlbGVjdGlvbkFjdGl2ZTogdHJ1ZSwgbm9kZXNTZWxlY3Rpb25BY3RpdmU6IGZhbHNlIH0pO1xuICAgICAgICBjb25zdCBtb3VzZVBvcyA9IGdldEV2ZW50UG9zaXRpb24oZXZlbnQsIGNvbnRhaW5lckJvdW5kcy5jdXJyZW50KTtcbiAgICAgICAgY29uc3Qgc3RhcnRYID0gdXNlclNlbGVjdGlvblJlY3Quc3RhcnRYID8/IDA7XG4gICAgICAgIGNvbnN0IHN0YXJ0WSA9IHVzZXJTZWxlY3Rpb25SZWN0LnN0YXJ0WSA/PyAwO1xuICAgICAgICBjb25zdCBuZXh0VXNlclNlbGVjdFJlY3QgPSB7XG4gICAgICAgICAgICAuLi51c2VyU2VsZWN0aW9uUmVjdCxcbiAgICAgICAgICAgIHg6IG1vdXNlUG9zLnggPCBzdGFydFggPyBtb3VzZVBvcy54IDogc3RhcnRYLFxuICAgICAgICAgICAgeTogbW91c2VQb3MueSA8IHN0YXJ0WSA/IG1vdXNlUG9zLnkgOiBzdGFydFksXG4gICAgICAgICAgICB3aWR0aDogTWF0aC5hYnMobW91c2VQb3MueCAtIHN0YXJ0WCksXG4gICAgICAgICAgICBoZWlnaHQ6IE1hdGguYWJzKG1vdXNlUG9zLnkgLSBzdGFydFkpLFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBub2RlcyA9IGdldE5vZGVzKCk7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkTm9kZXMgPSBnZXROb2Rlc0luc2lkZShub2RlSW50ZXJuYWxzLCBuZXh0VXNlclNlbGVjdFJlY3QsIHRyYW5zZm9ybSwgc2VsZWN0aW9uTW9kZSA9PT0gU2VsZWN0aW9uTW9kZS5QYXJ0aWFsLCB0cnVlLCBub2RlT3JpZ2luKTtcbiAgICAgICAgY29uc3Qgc2VsZWN0ZWRFZGdlSWRzID0gZ2V0Q29ubmVjdGVkRWRnZXMoc2VsZWN0ZWROb2RlcywgZWRnZXMpLm1hcCgoZSkgPT4gZS5pZCk7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkTm9kZUlkcyA9IHNlbGVjdGVkTm9kZXMubWFwKChuKSA9PiBuLmlkKTtcbiAgICAgICAgaWYgKHByZXZTZWxlY3RlZE5vZGVzQ291bnQuY3VycmVudCAhPT0gc2VsZWN0ZWROb2RlSWRzLmxlbmd0aCkge1xuICAgICAgICAgICAgcHJldlNlbGVjdGVkTm9kZXNDb3VudC5jdXJyZW50ID0gc2VsZWN0ZWROb2RlSWRzLmxlbmd0aDtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZXMgPSBnZXRTZWxlY3Rpb25DaGFuZ2VzKG5vZGVzLCBzZWxlY3RlZE5vZGVJZHMpO1xuICAgICAgICAgICAgaWYgKGNoYW5nZXMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgb25Ob2Rlc0NoYW5nZT8uKGNoYW5nZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChwcmV2U2VsZWN0ZWRFZGdlc0NvdW50LmN1cnJlbnQgIT09IHNlbGVjdGVkRWRnZUlkcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHByZXZTZWxlY3RlZEVkZ2VzQ291bnQuY3VycmVudCA9IHNlbGVjdGVkRWRnZUlkcy5sZW5ndGg7XG4gICAgICAgICAgICBjb25zdCBjaGFuZ2VzID0gZ2V0U2VsZWN0aW9uQ2hhbmdlcyhlZGdlcywgc2VsZWN0ZWRFZGdlSWRzKTtcbiAgICAgICAgICAgIGlmIChjaGFuZ2VzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIG9uRWRnZXNDaGFuZ2U/LihjaGFuZ2VzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBzdG9yZS5zZXRTdGF0ZSh7XG4gICAgICAgICAgICB1c2VyU2VsZWN0aW9uUmVjdDogbmV4dFVzZXJTZWxlY3RSZWN0LFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IG9uTW91c2VVcCA9IChldmVudCkgPT4ge1xuICAgICAgICBpZiAoZXZlbnQuYnV0dG9uICE9PSAwKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgeyB1c2VyU2VsZWN0aW9uUmVjdCB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgLy8gV2Ugb25seSB3YW50IHRvIHRyaWdnZXIgY2xpY2sgZnVuY3Rpb25zIHdoZW4gaW4gc2VsZWN0aW9uIG1vZGUgaWZcbiAgICAgICAgLy8gdGhlIHVzZXIgZGlkIG5vdCBtb3ZlIHRoZSBtb3VzZS5cbiAgICAgICAgaWYgKCF1c2VyU2VsZWN0aW9uQWN0aXZlICYmIHVzZXJTZWxlY3Rpb25SZWN0ICYmIGV2ZW50LnRhcmdldCA9PT0gY29udGFpbmVyLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIG9uQ2xpY2s/LihldmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgc3RvcmUuc2V0U3RhdGUoeyBub2Rlc1NlbGVjdGlvbkFjdGl2ZTogcHJldlNlbGVjdGVkTm9kZXNDb3VudC5jdXJyZW50ID4gMCB9KTtcbiAgICAgICAgcmVzZXRVc2VyU2VsZWN0aW9uKCk7XG4gICAgICAgIG9uU2VsZWN0aW9uRW5kPy4oZXZlbnQpO1xuICAgIH07XG4gICAgY29uc3Qgb25Nb3VzZUxlYXZlID0gKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICh1c2VyU2VsZWN0aW9uQWN0aXZlKSB7XG4gICAgICAgICAgICBzdG9yZS5zZXRTdGF0ZSh7IG5vZGVzU2VsZWN0aW9uQWN0aXZlOiBwcmV2U2VsZWN0ZWROb2Rlc0NvdW50LmN1cnJlbnQgPiAwIH0pO1xuICAgICAgICAgICAgb25TZWxlY3Rpb25FbmQ/LihldmVudCk7XG4gICAgICAgIH1cbiAgICAgICAgcmVzZXRVc2VyU2VsZWN0aW9uKCk7XG4gICAgfTtcbiAgICBjb25zdCBoYXNBY3RpdmVTZWxlY3Rpb24gPSBlbGVtZW50c1NlbGVjdGFibGUgJiYgKGlzU2VsZWN0aW5nIHx8IHVzZXJTZWxlY3Rpb25BY3RpdmUpO1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IGNsYXNzTmFtZTogY2MoWydyZWFjdC1mbG93X19wYW5lJywgeyBkcmFnZ2luZywgc2VsZWN0aW9uOiBpc1NlbGVjdGluZyB9XSksIG9uQ2xpY2s6IGhhc0FjdGl2ZVNlbGVjdGlvbiA/IHVuZGVmaW5lZCA6IHdyYXBIYW5kbGVyKG9uQ2xpY2ssIGNvbnRhaW5lciksIG9uQ29udGV4dE1lbnU6IHdyYXBIYW5kbGVyKG9uQ29udGV4dE1lbnUsIGNvbnRhaW5lciksIG9uV2hlZWw6IHdyYXBIYW5kbGVyKG9uV2hlZWwsIGNvbnRhaW5lciksIG9uTW91c2VFbnRlcjogaGFzQWN0aXZlU2VsZWN0aW9uID8gdW5kZWZpbmVkIDogb25QYW5lTW91c2VFbnRlciwgb25Nb3VzZURvd246IGhhc0FjdGl2ZVNlbGVjdGlvbiA/IG9uTW91c2VEb3duIDogdW5kZWZpbmVkLCBvbk1vdXNlTW92ZTogaGFzQWN0aXZlU2VsZWN0aW9uID8gb25Nb3VzZU1vdmUgOiBvblBhbmVNb3VzZU1vdmUsIG9uTW91c2VVcDogaGFzQWN0aXZlU2VsZWN0aW9uID8gb25Nb3VzZVVwIDogdW5kZWZpbmVkLCBvbk1vdXNlTGVhdmU6IGhhc0FjdGl2ZVNlbGVjdGlvbiA/IG9uTW91c2VMZWF2ZSA6IG9uUGFuZU1vdXNlTGVhdmUsIHJlZjogY29udGFpbmVyLCBzdHlsZTogY29udGFpbmVyU3R5bGUgfSxcbiAgICAgICAgY2hpbGRyZW4sXG4gICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoVXNlclNlbGVjdGlvbiwgbnVsbCkpKTtcbn0pO1xuUGFuZS5kaXNwbGF5TmFtZSA9ICdQYW5lJztcblxuZnVuY3Rpb24gaXNQYXJlbnRTZWxlY3RlZChub2RlLCBub2RlSW50ZXJuYWxzKSB7XG4gICAgaWYgKCFub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBjb25zdCBwYXJlbnROb2RlID0gbm9kZUludGVybmFscy5nZXQobm9kZS5wYXJlbnROb2RlKTtcbiAgICBpZiAoIXBhcmVudE5vZGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICBpZiAocGFyZW50Tm9kZS5zZWxlY3RlZCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGlzUGFyZW50U2VsZWN0ZWQocGFyZW50Tm9kZSwgbm9kZUludGVybmFscyk7XG59XG5mdW5jdGlvbiBoYXNTZWxlY3Rvcih0YXJnZXQsIHNlbGVjdG9yLCBub2RlUmVmKSB7XG4gICAgbGV0IGN1cnJlbnQgPSB0YXJnZXQ7XG4gICAgZG8ge1xuICAgICAgICBpZiAoY3VycmVudD8ubWF0Y2hlcyhzZWxlY3RvcikpXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgaWYgKGN1cnJlbnQgPT09IG5vZGVSZWYuY3VycmVudClcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgY3VycmVudCA9IGN1cnJlbnQucGFyZW50RWxlbWVudDtcbiAgICB9IHdoaWxlIChjdXJyZW50KTtcbiAgICByZXR1cm4gZmFsc2U7XG59XG4vLyBsb29rcyBmb3IgYWxsIHNlbGVjdGVkIG5vZGVzIGFuZCBjcmVhdGVkIGEgTm9kZURyYWdJdGVtIGZvciBlYWNoIG9mIHRoZW1cbmZ1bmN0aW9uIGdldERyYWdJdGVtcyhub2RlSW50ZXJuYWxzLCBub2Rlc0RyYWdnYWJsZSwgbW91c2VQb3MsIG5vZGVJZCkge1xuICAgIHJldHVybiBBcnJheS5mcm9tKG5vZGVJbnRlcm5hbHMudmFsdWVzKCkpXG4gICAgICAgIC5maWx0ZXIoKG4pID0+IChuLnNlbGVjdGVkIHx8IG4uaWQgPT09IG5vZGVJZCkgJiZcbiAgICAgICAgKCFuLnBhcmVudE5vZGUgfHwgIWlzUGFyZW50U2VsZWN0ZWQobiwgbm9kZUludGVybmFscykpICYmXG4gICAgICAgIChuLmRyYWdnYWJsZSB8fCAobm9kZXNEcmFnZ2FibGUgJiYgdHlwZW9mIG4uZHJhZ2dhYmxlID09PSAndW5kZWZpbmVkJykpKVxuICAgICAgICAubWFwKChuKSA9PiAoe1xuICAgICAgICBpZDogbi5pZCxcbiAgICAgICAgcG9zaXRpb246IG4ucG9zaXRpb24gfHwgeyB4OiAwLCB5OiAwIH0sXG4gICAgICAgIHBvc2l0aW9uQWJzb2x1dGU6IG4ucG9zaXRpb25BYnNvbHV0ZSB8fCB7IHg6IDAsIHk6IDAgfSxcbiAgICAgICAgZGlzdGFuY2U6IHtcbiAgICAgICAgICAgIHg6IG1vdXNlUG9zLnggLSAobi5wb3NpdGlvbkFic29sdXRlPy54ID8/IDApLFxuICAgICAgICAgICAgeTogbW91c2VQb3MueSAtIChuLnBvc2l0aW9uQWJzb2x1dGU/LnkgPz8gMCksXG4gICAgICAgIH0sXG4gICAgICAgIGRlbHRhOiB7XG4gICAgICAgICAgICB4OiAwLFxuICAgICAgICAgICAgeTogMCxcbiAgICAgICAgfSxcbiAgICAgICAgZXh0ZW50OiBuLmV4dGVudCxcbiAgICAgICAgcGFyZW50Tm9kZTogbi5wYXJlbnROb2RlLFxuICAgICAgICB3aWR0aDogbi53aWR0aCxcbiAgICAgICAgaGVpZ2h0OiBuLmhlaWdodCxcbiAgICAgICAgZXhwYW5kUGFyZW50OiBuLmV4cGFuZFBhcmVudCxcbiAgICB9KSk7XG59XG5mdW5jdGlvbiBjbGFtcE5vZGVFeHRlbnQobm9kZSwgZXh0ZW50KSB7XG4gICAgaWYgKCFleHRlbnQgfHwgZXh0ZW50ID09PSAncGFyZW50Jykge1xuICAgICAgICByZXR1cm4gZXh0ZW50O1xuICAgIH1cbiAgICByZXR1cm4gW2V4dGVudFswXSwgW2V4dGVudFsxXVswXSAtIChub2RlLndpZHRoIHx8IDApLCBleHRlbnRbMV1bMV0gLSAobm9kZS5oZWlnaHQgfHwgMCldXTtcbn1cbmZ1bmN0aW9uIGNhbGNOZXh0UG9zaXRpb24obm9kZSwgbmV4dFBvc2l0aW9uLCBub2RlSW50ZXJuYWxzLCBub2RlRXh0ZW50LCBub2RlT3JpZ2luID0gWzAsIDBdLCBvbkVycm9yKSB7XG4gICAgY29uc3QgY2xhbXBlZE5vZGVFeHRlbnQgPSBjbGFtcE5vZGVFeHRlbnQobm9kZSwgbm9kZS5leHRlbnQgfHwgbm9kZUV4dGVudCk7XG4gICAgbGV0IGN1cnJlbnRFeHRlbnQgPSBjbGFtcGVkTm9kZUV4dGVudDtcbiAgICBpZiAobm9kZS5leHRlbnQgPT09ICdwYXJlbnQnICYmICFub2RlLmV4cGFuZFBhcmVudCkge1xuICAgICAgICBpZiAobm9kZS5wYXJlbnROb2RlICYmIG5vZGUud2lkdGggJiYgbm9kZS5oZWlnaHQpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcmVudCA9IG5vZGVJbnRlcm5hbHMuZ2V0KG5vZGUucGFyZW50Tm9kZSk7XG4gICAgICAgICAgICBjb25zdCB7IHg6IHBhcmVudFgsIHk6IHBhcmVudFkgfSA9IGdldE5vZGVQb3NpdGlvbldpdGhPcmlnaW4ocGFyZW50LCBub2RlT3JpZ2luKS5wb3NpdGlvbkFic29sdXRlO1xuICAgICAgICAgICAgY3VycmVudEV4dGVudCA9XG4gICAgICAgICAgICAgICAgcGFyZW50ICYmIGlzTnVtZXJpYyhwYXJlbnRYKSAmJiBpc051bWVyaWMocGFyZW50WSkgJiYgaXNOdW1lcmljKHBhcmVudC53aWR0aCkgJiYgaXNOdW1lcmljKHBhcmVudC5oZWlnaHQpXG4gICAgICAgICAgICAgICAgICAgID8gW1xuICAgICAgICAgICAgICAgICAgICAgICAgW3BhcmVudFggKyBub2RlLndpZHRoICogbm9kZU9yaWdpblswXSwgcGFyZW50WSArIG5vZGUuaGVpZ2h0ICogbm9kZU9yaWdpblsxXV0sXG4gICAgICAgICAgICAgICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGFyZW50WCArIHBhcmVudC53aWR0aCAtIG5vZGUud2lkdGggKyBub2RlLndpZHRoICogbm9kZU9yaWdpblswXSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXJlbnRZICsgcGFyZW50LmhlaWdodCAtIG5vZGUuaGVpZ2h0ICsgbm9kZS5oZWlnaHQgKiBub2RlT3JpZ2luWzFdLFxuICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAgICAgXVxuICAgICAgICAgICAgICAgICAgICA6IGN1cnJlbnRFeHRlbnQ7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBvbkVycm9yPy4oJzAwNScsIGVycm9yTWVzc2FnZXNbJ2Vycm9yMDA1J10oKSk7XG4gICAgICAgICAgICBjdXJyZW50RXh0ZW50ID0gY2xhbXBlZE5vZGVFeHRlbnQ7XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSBpZiAobm9kZS5leHRlbnQgJiYgbm9kZS5wYXJlbnROb2RlICYmIG5vZGUuZXh0ZW50ICE9PSAncGFyZW50Jykge1xuICAgICAgICBjb25zdCBwYXJlbnQgPSBub2RlSW50ZXJuYWxzLmdldChub2RlLnBhcmVudE5vZGUpO1xuICAgICAgICBjb25zdCB7IHg6IHBhcmVudFgsIHk6IHBhcmVudFkgfSA9IGdldE5vZGVQb3NpdGlvbldpdGhPcmlnaW4ocGFyZW50LCBub2RlT3JpZ2luKS5wb3NpdGlvbkFic29sdXRlO1xuICAgICAgICBjdXJyZW50RXh0ZW50ID0gW1xuICAgICAgICAgICAgW25vZGUuZXh0ZW50WzBdWzBdICsgcGFyZW50WCwgbm9kZS5leHRlbnRbMF1bMV0gKyBwYXJlbnRZXSxcbiAgICAgICAgICAgIFtub2RlLmV4dGVudFsxXVswXSArIHBhcmVudFgsIG5vZGUuZXh0ZW50WzFdWzFdICsgcGFyZW50WV0sXG4gICAgICAgIF07XG4gICAgfVxuICAgIGxldCBwYXJlbnRQb3NpdGlvbiA9IHsgeDogMCwgeTogMCB9O1xuICAgIGlmIChub2RlLnBhcmVudE5vZGUpIHtcbiAgICAgICAgY29uc3QgcGFyZW50Tm9kZSA9IG5vZGVJbnRlcm5hbHMuZ2V0KG5vZGUucGFyZW50Tm9kZSk7XG4gICAgICAgIHBhcmVudFBvc2l0aW9uID0gZ2V0Tm9kZVBvc2l0aW9uV2l0aE9yaWdpbihwYXJlbnROb2RlLCBub2RlT3JpZ2luKS5wb3NpdGlvbkFic29sdXRlO1xuICAgIH1cbiAgICBjb25zdCBwb3NpdGlvbkFic29sdXRlID0gY3VycmVudEV4dGVudCAmJiBjdXJyZW50RXh0ZW50ICE9PSAncGFyZW50J1xuICAgICAgICA/IGNsYW1wUG9zaXRpb24obmV4dFBvc2l0aW9uLCBjdXJyZW50RXh0ZW50KVxuICAgICAgICA6IG5leHRQb3NpdGlvbjtcbiAgICByZXR1cm4ge1xuICAgICAgICBwb3NpdGlvbjoge1xuICAgICAgICAgICAgeDogcG9zaXRpb25BYnNvbHV0ZS54IC0gcGFyZW50UG9zaXRpb24ueCxcbiAgICAgICAgICAgIHk6IHBvc2l0aW9uQWJzb2x1dGUueSAtIHBhcmVudFBvc2l0aW9uLnksXG4gICAgICAgIH0sXG4gICAgICAgIHBvc2l0aW9uQWJzb2x1dGUsXG4gICAgfTtcbn1cbi8vIHJldHVybnMgdHdvIHBhcmFtczpcbi8vIDEuIHRoZSBkcmFnZ2VkIG5vZGUgKG9yIHRoZSBmaXJzdCBvZiB0aGUgbGlzdCwgaWYgd2UgYXJlIGRyYWdnaW5nIGEgbm9kZSBzZWxlY3Rpb24pXG4vLyAyLiBhcnJheSBvZiBzZWxlY3RlZCBub2RlcyAoZm9yIG11bHRpIHNlbGVjdGlvbnMpXG5mdW5jdGlvbiBnZXRFdmVudEhhbmRsZXJQYXJhbXMoeyBub2RlSWQsIGRyYWdJdGVtcywgbm9kZUludGVybmFscywgfSkge1xuICAgIGNvbnN0IGV4dGVudGVkRHJhZ0l0ZW1zID0gZHJhZ0l0ZW1zLm1hcCgobikgPT4ge1xuICAgICAgICBjb25zdCBub2RlID0gbm9kZUludGVybmFscy5nZXQobi5pZCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi5ub2RlLFxuICAgICAgICAgICAgcG9zaXRpb246IG4ucG9zaXRpb24sXG4gICAgICAgICAgICBwb3NpdGlvbkFic29sdXRlOiBuLnBvc2l0aW9uQWJzb2x1dGUsXG4gICAgICAgIH07XG4gICAgfSk7XG4gICAgcmV0dXJuIFtub2RlSWQgPyBleHRlbnRlZERyYWdJdGVtcy5maW5kKChuKSA9PiBuLmlkID09PSBub2RlSWQpIDogZXh0ZW50ZWREcmFnSXRlbXNbMF0sIGV4dGVudGVkRHJhZ0l0ZW1zXTtcbn1cblxuY29uc3QgZ2V0SGFuZGxlQm91bmRzID0gKHNlbGVjdG9yLCBub2RlRWxlbWVudCwgem9vbSwgbm9kZU9yaWdpbikgPT4ge1xuICAgIGNvbnN0IGhhbmRsZXMgPSBub2RlRWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKHNlbGVjdG9yKTtcbiAgICBpZiAoIWhhbmRsZXMgfHwgIWhhbmRsZXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICBjb25zdCBoYW5kbGVzQXJyYXkgPSBBcnJheS5mcm9tKGhhbmRsZXMpO1xuICAgIGNvbnN0IG5vZGVCb3VuZHMgPSBub2RlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBub2RlT2Zmc2V0ID0ge1xuICAgICAgICB4OiBub2RlQm91bmRzLndpZHRoICogbm9kZU9yaWdpblswXSxcbiAgICAgICAgeTogbm9kZUJvdW5kcy5oZWlnaHQgKiBub2RlT3JpZ2luWzFdLFxuICAgIH07XG4gICAgcmV0dXJuIGhhbmRsZXNBcnJheS5tYXAoKGhhbmRsZSkgPT4ge1xuICAgICAgICBjb25zdCBoYW5kbGVCb3VuZHMgPSBoYW5kbGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpZDogaGFuZGxlLmdldEF0dHJpYnV0ZSgnZGF0YS1oYW5kbGVpZCcpLFxuICAgICAgICAgICAgcG9zaXRpb246IGhhbmRsZS5nZXRBdHRyaWJ1dGUoJ2RhdGEtaGFuZGxlcG9zJyksXG4gICAgICAgICAgICB4OiAoaGFuZGxlQm91bmRzLmxlZnQgLSBub2RlQm91bmRzLmxlZnQgLSBub2RlT2Zmc2V0LngpIC8gem9vbSxcbiAgICAgICAgICAgIHk6IChoYW5kbGVCb3VuZHMudG9wIC0gbm9kZUJvdW5kcy50b3AgLSBub2RlT2Zmc2V0LnkpIC8gem9vbSxcbiAgICAgICAgICAgIC4uLmdldERpbWVuc2lvbnMoaGFuZGxlKSxcbiAgICAgICAgfTtcbiAgICB9KTtcbn07XG5mdW5jdGlvbiBnZXRNb3VzZUhhbmRsZXIoaWQsIGdldFN0YXRlLCBoYW5kbGVyKSB7XG4gICAgcmV0dXJuIGhhbmRsZXIgPT09IHVuZGVmaW5lZFxuICAgICAgICA/IGhhbmRsZXJcbiAgICAgICAgOiAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG5vZGUgPSBnZXRTdGF0ZSgpLm5vZGVJbnRlcm5hbHMuZ2V0KGlkKTtcbiAgICAgICAgICAgIGlmIChub2RlKSB7XG4gICAgICAgICAgICAgICAgaGFuZGxlcihldmVudCwgeyAuLi5ub2RlIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xufVxuLy8gdGhpcyBoYW5kbGVyIGlzIGNhbGxlZCBieVxuLy8gMS4gdGhlIGNsaWNrIGhhbmRsZXIgd2hlbiBub2RlIGlzIG5vdCBkcmFnZ2FibGUgb3Igc2VsZWN0Tm9kZXNPbkRyYWcgPSBmYWxzZVxuLy8gb3Jcbi8vIDIuIHRoZSBvbiBkcmFnIHN0YXJ0IGhhbmRsZXIgd2hlbiBub2RlIGlzIGRyYWdnYWJsZSBhbmQgc2VsZWN0Tm9kZXNPbkRyYWcgPSB0cnVlXG5mdW5jdGlvbiBoYW5kbGVOb2RlQ2xpY2soeyBpZCwgc3RvcmUsIHVuc2VsZWN0ID0gZmFsc2UsIG5vZGVSZWYsIH0pIHtcbiAgICBjb25zdCB7IGFkZFNlbGVjdGVkTm9kZXMsIHVuc2VsZWN0Tm9kZXNBbmRFZGdlcywgbXVsdGlTZWxlY3Rpb25BY3RpdmUsIG5vZGVJbnRlcm5hbHMsIG9uRXJyb3IgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgY29uc3Qgbm9kZSA9IG5vZGVJbnRlcm5hbHMuZ2V0KGlkKTtcbiAgICBpZiAoIW5vZGUpIHtcbiAgICAgICAgb25FcnJvcj8uKCcwMTInLCBlcnJvck1lc3NhZ2VzWydlcnJvcjAxMiddKGlkKSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgc3RvcmUuc2V0U3RhdGUoeyBub2Rlc1NlbGVjdGlvbkFjdGl2ZTogZmFsc2UgfSk7XG4gICAgaWYgKCFub2RlLnNlbGVjdGVkKSB7XG4gICAgICAgIGFkZFNlbGVjdGVkTm9kZXMoW2lkXSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHVuc2VsZWN0IHx8IChub2RlLnNlbGVjdGVkICYmIG11bHRpU2VsZWN0aW9uQWN0aXZlKSkge1xuICAgICAgICB1bnNlbGVjdE5vZGVzQW5kRWRnZXMoeyBub2RlczogW25vZGVdLCBlZGdlczogW10gfSk7XG4gICAgICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiBub2RlUmVmPy5jdXJyZW50Py5ibHVyKCkpO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gdXNlR2V0UG9pbnRlclBvc2l0aW9uKCkge1xuICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICAvLyByZXR1cm5zIHRoZSBwb2ludGVyIHBvc2l0aW9uIHByb2plY3RlZCB0byB0aGUgUkYgY29vcmRpbmF0ZSBzeXN0ZW1cbiAgICBjb25zdCBnZXRQb2ludGVyUG9zaXRpb24gPSB1c2VDYWxsYmFjaygoeyBzb3VyY2VFdmVudCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgdHJhbnNmb3JtLCBzbmFwR3JpZCwgc25hcFRvR3JpZCB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgY29uc3QgeCA9IHNvdXJjZUV2ZW50LnRvdWNoZXMgPyBzb3VyY2VFdmVudC50b3VjaGVzWzBdLmNsaWVudFggOiBzb3VyY2VFdmVudC5jbGllbnRYO1xuICAgICAgICBjb25zdCB5ID0gc291cmNlRXZlbnQudG91Y2hlcyA/IHNvdXJjZUV2ZW50LnRvdWNoZXNbMF0uY2xpZW50WSA6IHNvdXJjZUV2ZW50LmNsaWVudFk7XG4gICAgICAgIGNvbnN0IHBvaW50ZXJQb3MgPSB7XG4gICAgICAgICAgICB4OiAoeCAtIHRyYW5zZm9ybVswXSkgLyB0cmFuc2Zvcm1bMl0sXG4gICAgICAgICAgICB5OiAoeSAtIHRyYW5zZm9ybVsxXSkgLyB0cmFuc2Zvcm1bMl0sXG4gICAgICAgIH07XG4gICAgICAgIC8vIHdlIG5lZWQgdGhlIHNuYXBwZWQgcG9zaXRpb24gaW4gb3JkZXIgdG8gYmUgYWJsZSB0byBza2lwIHVubmVjZXNzYXJ5IGRyYWcgZXZlbnRzXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB4U25hcHBlZDogc25hcFRvR3JpZCA/IHNuYXBHcmlkWzBdICogTWF0aC5yb3VuZChwb2ludGVyUG9zLnggLyBzbmFwR3JpZFswXSkgOiBwb2ludGVyUG9zLngsXG4gICAgICAgICAgICB5U25hcHBlZDogc25hcFRvR3JpZCA/IHNuYXBHcmlkWzFdICogTWF0aC5yb3VuZChwb2ludGVyUG9zLnkgLyBzbmFwR3JpZFsxXSkgOiBwb2ludGVyUG9zLnksXG4gICAgICAgICAgICAuLi5wb2ludGVyUG9zLFxuICAgICAgICB9O1xuICAgIH0sIFtdKTtcbiAgICByZXR1cm4gZ2V0UG9pbnRlclBvc2l0aW9uO1xufVxuXG5mdW5jdGlvbiB3cmFwU2VsZWN0aW9uRHJhZ0Z1bmMoc2VsZWN0aW9uRnVuYykge1xuICAgIHJldHVybiAoZXZlbnQsIF8sIG5vZGVzKSA9PiBzZWxlY3Rpb25GdW5jPy4oZXZlbnQsIG5vZGVzKTtcbn1cbmZ1bmN0aW9uIHVzZURyYWcoeyBub2RlUmVmLCBkaXNhYmxlZCA9IGZhbHNlLCBub0RyYWdDbGFzc05hbWUsIGhhbmRsZVNlbGVjdG9yLCBub2RlSWQsIGlzU2VsZWN0YWJsZSwgc2VsZWN0Tm9kZXNPbkRyYWcsIH0pIHtcbiAgICBjb25zdCBzdG9yZSA9IHVzZVN0b3JlQXBpKCk7XG4gICAgY29uc3QgW2RyYWdnaW5nLCBzZXREcmFnZ2luZ10gPSB1c2VTdGF0ZShmYWxzZSk7XG4gICAgY29uc3QgZHJhZ0l0ZW1zID0gdXNlUmVmKFtdKTtcbiAgICBjb25zdCBsYXN0UG9zID0gdXNlUmVmKHsgeDogbnVsbCwgeTogbnVsbCB9KTtcbiAgICBjb25zdCBhdXRvUGFuSWQgPSB1c2VSZWYoMCk7XG4gICAgY29uc3QgY29udGFpbmVyQm91bmRzID0gdXNlUmVmKG51bGwpO1xuICAgIGNvbnN0IG1vdXNlUG9zaXRpb24gPSB1c2VSZWYoeyB4OiAwLCB5OiAwIH0pO1xuICAgIGNvbnN0IGRyYWdFdmVudCA9IHVzZVJlZihudWxsKTtcbiAgICBjb25zdCBhdXRvUGFuU3RhcnRlZCA9IHVzZVJlZihmYWxzZSk7XG4gICAgY29uc3QgZHJhZ1N0YXJ0ZWQgPSB1c2VSZWYoZmFsc2UpO1xuICAgIGNvbnN0IGdldFBvaW50ZXJQb3NpdGlvbiA9IHVzZUdldFBvaW50ZXJQb3NpdGlvbigpO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChub2RlUmVmPy5jdXJyZW50KSB7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSBzZWxlY3Qobm9kZVJlZi5jdXJyZW50KTtcbiAgICAgICAgICAgIGNvbnN0IHVwZGF0ZU5vZGVzID0gKHsgeCwgeSB9KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBub2RlSW50ZXJuYWxzLCBvbk5vZGVEcmFnLCBvblNlbGVjdGlvbkRyYWcsIHVwZGF0ZU5vZGVQb3NpdGlvbnMsIG5vZGVFeHRlbnQsIHNuYXBHcmlkLCBzbmFwVG9HcmlkLCBub2RlT3JpZ2luLCBvbkVycm9yLCB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgICAgICAgICBsYXN0UG9zLmN1cnJlbnQgPSB7IHgsIHkgfTtcbiAgICAgICAgICAgICAgICBsZXQgaGFzQ2hhbmdlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgbGV0IG5vZGVzQm94ID0geyB4OiAwLCB5OiAwLCB4MjogMCwgeTI6IDAgfTtcbiAgICAgICAgICAgICAgICBpZiAoZHJhZ0l0ZW1zLmN1cnJlbnQubGVuZ3RoID4gMSAmJiBub2RlRXh0ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY3QgPSBnZXROb2Rlc0JvdW5kcyhkcmFnSXRlbXMuY3VycmVudCwgbm9kZU9yaWdpbik7XG4gICAgICAgICAgICAgICAgICAgIG5vZGVzQm94ID0gcmVjdFRvQm94KHJlY3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBkcmFnSXRlbXMuY3VycmVudCA9IGRyYWdJdGVtcy5jdXJyZW50Lm1hcCgobikgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXh0UG9zaXRpb24gPSB7IHg6IHggLSBuLmRpc3RhbmNlLngsIHk6IHkgLSBuLmRpc3RhbmNlLnkgfTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNuYXBUb0dyaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5leHRQb3NpdGlvbi54ID0gc25hcEdyaWRbMF0gKiBNYXRoLnJvdW5kKG5leHRQb3NpdGlvbi54IC8gc25hcEdyaWRbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV4dFBvc2l0aW9uLnkgPSBzbmFwR3JpZFsxXSAqIE1hdGgucm91bmQobmV4dFBvc2l0aW9uLnkgLyBzbmFwR3JpZFsxXSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgLy8gaWYgdGhlcmUgaXMgc2VsZWN0aW9uIHdpdGggbXVsdGlwbGUgbm9kZXMgYW5kIGEgbm9kZSBleHRlbnQgaXMgc2V0LCB3ZSBuZWVkIHRvIGFkanVzdCB0aGUgbm9kZSBleHRlbnQgZm9yIGVhY2ggbm9kZVxuICAgICAgICAgICAgICAgICAgICAvLyBiYXNlZCBvbiBpdHMgcG9zaXRpb24gc28gdGhhdCB0aGUgbm9kZSBzdGF5cyBhdCBpdCdzIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBzZWxlY3Rpb24uXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGFkanVzdGVkTm9kZUV4dGVudCA9IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIFtub2RlRXh0ZW50WzBdWzBdLCBub2RlRXh0ZW50WzBdWzFdXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtub2RlRXh0ZW50WzFdWzBdLCBub2RlRXh0ZW50WzFdWzFdXSxcbiAgICAgICAgICAgICAgICAgICAgXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGRyYWdJdGVtcy5jdXJyZW50Lmxlbmd0aCA+IDEgJiYgbm9kZUV4dGVudCAmJiAhbi5leHRlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkanVzdGVkTm9kZUV4dGVudFswXVswXSA9IG4ucG9zaXRpb25BYnNvbHV0ZS54IC0gbm9kZXNCb3gueCArIG5vZGVFeHRlbnRbMF1bMF07XG4gICAgICAgICAgICAgICAgICAgICAgICBhZGp1c3RlZE5vZGVFeHRlbnRbMV1bMF0gPSBuLnBvc2l0aW9uQWJzb2x1dGUueCArIChuLndpZHRoID8/IDApIC0gbm9kZXNCb3gueDIgKyBub2RlRXh0ZW50WzFdWzBdO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWRqdXN0ZWROb2RlRXh0ZW50WzBdWzFdID0gbi5wb3NpdGlvbkFic29sdXRlLnkgLSBub2Rlc0JveC55ICsgbm9kZUV4dGVudFswXVsxXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkanVzdGVkTm9kZUV4dGVudFsxXVsxXSA9IG4ucG9zaXRpb25BYnNvbHV0ZS55ICsgKG4uaGVpZ2h0ID8/IDApIC0gbm9kZXNCb3gueTIgKyBub2RlRXh0ZW50WzFdWzFdO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHVwZGF0ZWRQb3MgPSBjYWxjTmV4dFBvc2l0aW9uKG4sIG5leHRQb3NpdGlvbiwgbm9kZUludGVybmFscywgYWRqdXN0ZWROb2RlRXh0ZW50LCBub2RlT3JpZ2luLCBvbkVycm9yKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gd2Ugd2FudCB0byBtYWtlIHN1cmUgdGhhdCB3ZSBvbmx5IGZpcmUgYSBjaGFuZ2UgZXZlbnQgd2hlbiB0aGVyZSBpcyBhIGNoYW5nZVxuICAgICAgICAgICAgICAgICAgICBoYXNDaGFuZ2UgPSBoYXNDaGFuZ2UgfHwgbi5wb3NpdGlvbi54ICE9PSB1cGRhdGVkUG9zLnBvc2l0aW9uLnggfHwgbi5wb3NpdGlvbi55ICE9PSB1cGRhdGVkUG9zLnBvc2l0aW9uLnk7XG4gICAgICAgICAgICAgICAgICAgIG4ucG9zaXRpb24gPSB1cGRhdGVkUG9zLnBvc2l0aW9uO1xuICAgICAgICAgICAgICAgICAgICBuLnBvc2l0aW9uQWJzb2x1dGUgPSB1cGRhdGVkUG9zLnBvc2l0aW9uQWJzb2x1dGU7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBuO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIGlmICghaGFzQ2hhbmdlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdXBkYXRlTm9kZVBvc2l0aW9ucyhkcmFnSXRlbXMuY3VycmVudCwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgc2V0RHJhZ2dpbmcodHJ1ZSk7XG4gICAgICAgICAgICAgICAgY29uc3Qgb25EcmFnID0gbm9kZUlkID8gb25Ob2RlRHJhZyA6IHdyYXBTZWxlY3Rpb25EcmFnRnVuYyhvblNlbGVjdGlvbkRyYWcpO1xuICAgICAgICAgICAgICAgIGlmIChvbkRyYWcgJiYgZHJhZ0V2ZW50LmN1cnJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgW2N1cnJlbnROb2RlLCBub2Rlc10gPSBnZXRFdmVudEhhbmRsZXJQYXJhbXMoe1xuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ0l0ZW1zOiBkcmFnSXRlbXMuY3VycmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVJbnRlcm5hbHMsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICBvbkRyYWcoZHJhZ0V2ZW50LmN1cnJlbnQsIGN1cnJlbnROb2RlLCBub2Rlcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnN0IGF1dG9QYW4gPSAoKSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKCFjb250YWluZXJCb3VuZHMuY3VycmVudCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IFt4TW92ZW1lbnQsIHlNb3ZlbWVudF0gPSBjYWxjQXV0b1Bhbihtb3VzZVBvc2l0aW9uLmN1cnJlbnQsIGNvbnRhaW5lckJvdW5kcy5jdXJyZW50KTtcbiAgICAgICAgICAgICAgICBpZiAoeE1vdmVtZW50ICE9PSAwIHx8IHlNb3ZlbWVudCAhPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB7IHRyYW5zZm9ybSwgcGFuQnkgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIGxhc3RQb3MuY3VycmVudC54ID0gKGxhc3RQb3MuY3VycmVudC54ID8/IDApIC0geE1vdmVtZW50IC8gdHJhbnNmb3JtWzJdO1xuICAgICAgICAgICAgICAgICAgICBsYXN0UG9zLmN1cnJlbnQueSA9IChsYXN0UG9zLmN1cnJlbnQueSA/PyAwKSAtIHlNb3ZlbWVudCAvIHRyYW5zZm9ybVsyXTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhbkJ5KHsgeDogeE1vdmVtZW50LCB5OiB5TW92ZW1lbnQgfSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHVwZGF0ZU5vZGVzKGxhc3RQb3MuY3VycmVudCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYXV0b1BhbklkLmN1cnJlbnQgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoYXV0b1Bhbik7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgc3RhcnREcmFnID0gKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBub2RlSW50ZXJuYWxzLCBtdWx0aVNlbGVjdGlvbkFjdGl2ZSwgbm9kZXNEcmFnZ2FibGUsIHVuc2VsZWN0Tm9kZXNBbmRFZGdlcywgb25Ob2RlRHJhZ1N0YXJ0LCBvblNlbGVjdGlvbkRyYWdTdGFydCwgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICAgICAgZHJhZ1N0YXJ0ZWQuY3VycmVudCA9IHRydWU7XG4gICAgICAgICAgICAgICAgY29uc3Qgb25TdGFydCA9IG5vZGVJZCA/IG9uTm9kZURyYWdTdGFydCA6IHdyYXBTZWxlY3Rpb25EcmFnRnVuYyhvblNlbGVjdGlvbkRyYWdTdGFydCk7XG4gICAgICAgICAgICAgICAgaWYgKCghc2VsZWN0Tm9kZXNPbkRyYWcgfHwgIWlzU2VsZWN0YWJsZSkgJiYgIW11bHRpU2VsZWN0aW9uQWN0aXZlICYmIG5vZGVJZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIW5vZGVJbnRlcm5hbHMuZ2V0KG5vZGVJZCk/LnNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyB3ZSBuZWVkIHRvIHJlc2V0IHNlbGVjdGVkIG5vZGVzIHdoZW4gc2VsZWN0Tm9kZXNPbkRyYWc9ZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHVuc2VsZWN0Tm9kZXNBbmRFZGdlcygpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChub2RlSWQgJiYgaXNTZWxlY3RhYmxlICYmIHNlbGVjdE5vZGVzT25EcmFnKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhbmRsZU5vZGVDbGljayh7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZDogbm9kZUlkLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3RvcmUsXG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlUmVmOiBub2RlUmVmLFxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgcG9pbnRlclBvcyA9IGdldFBvaW50ZXJQb3NpdGlvbihldmVudCk7XG4gICAgICAgICAgICAgICAgbGFzdFBvcy5jdXJyZW50ID0gcG9pbnRlclBvcztcbiAgICAgICAgICAgICAgICBkcmFnSXRlbXMuY3VycmVudCA9IGdldERyYWdJdGVtcyhub2RlSW50ZXJuYWxzLCBub2Rlc0RyYWdnYWJsZSwgcG9pbnRlclBvcywgbm9kZUlkKTtcbiAgICAgICAgICAgICAgICBpZiAob25TdGFydCAmJiBkcmFnSXRlbXMuY3VycmVudCkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBbY3VycmVudE5vZGUsIG5vZGVzXSA9IGdldEV2ZW50SGFuZGxlclBhcmFtcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlSWQsXG4gICAgICAgICAgICAgICAgICAgICAgICBkcmFnSXRlbXM6IGRyYWdJdGVtcy5jdXJyZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZUludGVybmFscyxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIG9uU3RhcnQoZXZlbnQuc291cmNlRXZlbnQsIGN1cnJlbnROb2RlLCBub2Rlcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChkaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5vbignLmRyYWcnLCBudWxsKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRyYWdIYW5kbGVyID0gZHJhZygpXG4gICAgICAgICAgICAgICAgICAgIC5vbignc3RhcnQnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgeyBkb21Ob2RlLCBub2RlRHJhZ1RocmVzaG9sZCB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vZGVEcmFnVGhyZXNob2xkID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydERyYWcoZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50ZXJQb3MgPSBnZXRQb2ludGVyUG9zaXRpb24oZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICBsYXN0UG9zLmN1cnJlbnQgPSBwb2ludGVyUG9zO1xuICAgICAgICAgICAgICAgICAgICBjb250YWluZXJCb3VuZHMuY3VycmVudCA9IGRvbU5vZGU/LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpIHx8IG51bGw7XG4gICAgICAgICAgICAgICAgICAgIG1vdXNlUG9zaXRpb24uY3VycmVudCA9IGdldEV2ZW50UG9zaXRpb24oZXZlbnQuc291cmNlRXZlbnQsIGNvbnRhaW5lckJvdW5kcy5jdXJyZW50KTtcbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAub24oJ2RyYWcnLCAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9pbnRlclBvcyA9IGdldFBvaW50ZXJQb3NpdGlvbihldmVudCk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHsgYXV0b1Bhbk9uTm9kZURyYWcsIG5vZGVEcmFnVGhyZXNob2xkIH0gPSBzdG9yZS5nZXRTdGF0ZSgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWF1dG9QYW5TdGFydGVkLmN1cnJlbnQgJiYgZHJhZ1N0YXJ0ZWQuY3VycmVudCAmJiBhdXRvUGFuT25Ob2RlRHJhZykge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXV0b1BhblN0YXJ0ZWQuY3VycmVudCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBhdXRvUGFuKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFkcmFnU3RhcnRlZC5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB4ID0gcG9pbnRlclBvcy54U25hcHBlZCAtIChsYXN0UG9zPy5jdXJyZW50Py54ID8/IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeSA9IHBvaW50ZXJQb3MueVNuYXBwZWQgLSAobGFzdFBvcz8uY3VycmVudD8ueSA/PyAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpc3RhbmNlID0gTWF0aC5zcXJ0KHggKiB4ICsgeSAqIHkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRpc3RhbmNlID4gbm9kZURyYWdUaHJlc2hvbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydERyYWcoZXZlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIC8vIHNraXAgZXZlbnRzIHdpdGhvdXQgbW92ZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgaWYgKChsYXN0UG9zLmN1cnJlbnQueCAhPT0gcG9pbnRlclBvcy54U25hcHBlZCB8fCBsYXN0UG9zLmN1cnJlbnQueSAhPT0gcG9pbnRlclBvcy55U25hcHBlZCkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGRyYWdJdGVtcy5jdXJyZW50ICYmXG4gICAgICAgICAgICAgICAgICAgICAgICBkcmFnU3RhcnRlZC5jdXJyZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBkcmFnRXZlbnQuY3VycmVudCA9IGV2ZW50LnNvdXJjZUV2ZW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgbW91c2VQb3NpdGlvbi5jdXJyZW50ID0gZ2V0RXZlbnRQb3NpdGlvbihldmVudC5zb3VyY2VFdmVudCwgY29udGFpbmVyQm91bmRzLmN1cnJlbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlTm9kZXMocG9pbnRlclBvcyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAub24oJ2VuZCcsIChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWRyYWdTdGFydGVkLmN1cnJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZXREcmFnZ2luZyhmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgIGF1dG9QYW5TdGFydGVkLmN1cnJlbnQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgZHJhZ1N0YXJ0ZWQuY3VycmVudCA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZShhdXRvUGFuSWQuY3VycmVudCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChkcmFnSXRlbXMuY3VycmVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgeyB1cGRhdGVOb2RlUG9zaXRpb25zLCBub2RlSW50ZXJuYWxzLCBvbk5vZGVEcmFnU3RvcCwgb25TZWxlY3Rpb25EcmFnU3RvcCB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG9uU3RvcCA9IG5vZGVJZCA/IG9uTm9kZURyYWdTdG9wIDogd3JhcFNlbGVjdGlvbkRyYWdGdW5jKG9uU2VsZWN0aW9uRHJhZ1N0b3ApO1xuICAgICAgICAgICAgICAgICAgICAgICAgdXBkYXRlTm9kZVBvc2l0aW9ucyhkcmFnSXRlbXMuY3VycmVudCwgZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvblN0b3ApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBbY3VycmVudE5vZGUsIG5vZGVzXSA9IGdldEV2ZW50SGFuZGxlclBhcmFtcyh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHJhZ0l0ZW1zOiBkcmFnSXRlbXMuY3VycmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9kZUludGVybmFscyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvblN0b3AoZXZlbnQuc291cmNlRXZlbnQsIGN1cnJlbnROb2RlLCBub2Rlcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgICAgICAuZmlsdGVyKChldmVudCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXQgPSBldmVudC50YXJnZXQ7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzRHJhZ2dhYmxlID0gIWV2ZW50LmJ1dHRvbiAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKCFub0RyYWdDbGFzc05hbWUgfHwgIWhhc1NlbGVjdG9yKHRhcmdldCwgYC4ke25vRHJhZ0NsYXNzTmFtZX1gLCBub2RlUmVmKSkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICghaGFuZGxlU2VsZWN0b3IgfHwgaGFzU2VsZWN0b3IodGFyZ2V0LCBoYW5kbGVTZWxlY3Rvciwgbm9kZVJlZikpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXNEcmFnZ2FibGU7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgc2VsZWN0aW9uLmNhbGwoZHJhZ0hhbmRsZXIpO1xuICAgICAgICAgICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbi5vbignLmRyYWcnLCBudWxsKTtcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSwgW1xuICAgICAgICBub2RlUmVmLFxuICAgICAgICBkaXNhYmxlZCxcbiAgICAgICAgbm9EcmFnQ2xhc3NOYW1lLFxuICAgICAgICBoYW5kbGVTZWxlY3RvcixcbiAgICAgICAgaXNTZWxlY3RhYmxlLFxuICAgICAgICBzdG9yZSxcbiAgICAgICAgbm9kZUlkLFxuICAgICAgICBzZWxlY3ROb2Rlc09uRHJhZyxcbiAgICAgICAgZ2V0UG9pbnRlclBvc2l0aW9uLFxuICAgIF0pO1xuICAgIHJldHVybiBkcmFnZ2luZztcbn1cblxuZnVuY3Rpb24gdXNlVXBkYXRlTm9kZVBvc2l0aW9ucygpIHtcbiAgICBjb25zdCBzdG9yZSA9IHVzZVN0b3JlQXBpKCk7XG4gICAgY29uc3QgdXBkYXRlUG9zaXRpb25zID0gdXNlQ2FsbGJhY2soKHBhcmFtcykgPT4ge1xuICAgICAgICBjb25zdCB7IG5vZGVJbnRlcm5hbHMsIG5vZGVFeHRlbnQsIHVwZGF0ZU5vZGVQb3NpdGlvbnMsIGdldE5vZGVzLCBzbmFwVG9HcmlkLCBzbmFwR3JpZCwgb25FcnJvciwgbm9kZXNEcmFnZ2FibGUgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgIGNvbnN0IHNlbGVjdGVkTm9kZXMgPSBnZXROb2RlcygpLmZpbHRlcigobikgPT4gbi5zZWxlY3RlZCAmJiAobi5kcmFnZ2FibGUgfHwgKG5vZGVzRHJhZ2dhYmxlICYmIHR5cGVvZiBuLmRyYWdnYWJsZSA9PT0gJ3VuZGVmaW5lZCcpKSk7XG4gICAgICAgIC8vIGJ5IGRlZmF1bHQgYSBub2RlIG1vdmVzIDVweCBvbiBlYWNoIGtleSBwcmVzcywgb3IgMjBweCBpZiBzaGlmdCBpcyBwcmVzc2VkXG4gICAgICAgIC8vIGlmIHNuYXAgZ3JpZCBpcyBlbmFibGVkLCB3ZSB1c2UgdGhhdCBmb3IgdGhlIHZlbG9jaXR5LlxuICAgICAgICBjb25zdCB4VmVsbyA9IHNuYXBUb0dyaWQgPyBzbmFwR3JpZFswXSA6IDU7XG4gICAgICAgIGNvbnN0IHlWZWxvID0gc25hcFRvR3JpZCA/IHNuYXBHcmlkWzFdIDogNTtcbiAgICAgICAgY29uc3QgZmFjdG9yID0gcGFyYW1zLmlzU2hpZnRQcmVzc2VkID8gNCA6IDE7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uRGlmZlggPSBwYXJhbXMueCAqIHhWZWxvICogZmFjdG9yO1xuICAgICAgICBjb25zdCBwb3NpdGlvbkRpZmZZID0gcGFyYW1zLnkgKiB5VmVsbyAqIGZhY3RvcjtcbiAgICAgICAgY29uc3Qgbm9kZVVwZGF0ZXMgPSBzZWxlY3RlZE5vZGVzLm1hcCgobikgPT4ge1xuICAgICAgICAgICAgaWYgKG4ucG9zaXRpb25BYnNvbHV0ZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5leHRQb3NpdGlvbiA9IHsgeDogbi5wb3NpdGlvbkFic29sdXRlLnggKyBwb3NpdGlvbkRpZmZYLCB5OiBuLnBvc2l0aW9uQWJzb2x1dGUueSArIHBvc2l0aW9uRGlmZlkgfTtcbiAgICAgICAgICAgICAgICBpZiAoc25hcFRvR3JpZCkge1xuICAgICAgICAgICAgICAgICAgICBuZXh0UG9zaXRpb24ueCA9IHNuYXBHcmlkWzBdICogTWF0aC5yb3VuZChuZXh0UG9zaXRpb24ueCAvIHNuYXBHcmlkWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgbmV4dFBvc2l0aW9uLnkgPSBzbmFwR3JpZFsxXSAqIE1hdGgucm91bmQobmV4dFBvc2l0aW9uLnkgLyBzbmFwR3JpZFsxXSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IHsgcG9zaXRpb25BYnNvbHV0ZSwgcG9zaXRpb24gfSA9IGNhbGNOZXh0UG9zaXRpb24obiwgbmV4dFBvc2l0aW9uLCBub2RlSW50ZXJuYWxzLCBub2RlRXh0ZW50LCB1bmRlZmluZWQsIG9uRXJyb3IpO1xuICAgICAgICAgICAgICAgIG4ucG9zaXRpb24gPSBwb3NpdGlvbjtcbiAgICAgICAgICAgICAgICBuLnBvc2l0aW9uQWJzb2x1dGUgPSBwb3NpdGlvbkFic29sdXRlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgIH0pO1xuICAgICAgICB1cGRhdGVOb2RlUG9zaXRpb25zKG5vZGVVcGRhdGVzLCB0cnVlLCBmYWxzZSk7XG4gICAgfSwgW10pO1xuICAgIHJldHVybiB1cGRhdGVQb3NpdGlvbnM7XG59XG5cbmNvbnN0IGFycm93S2V5RGlmZnMgPSB7XG4gICAgQXJyb3dVcDogeyB4OiAwLCB5OiAtMSB9LFxuICAgIEFycm93RG93bjogeyB4OiAwLCB5OiAxIH0sXG4gICAgQXJyb3dMZWZ0OiB7IHg6IC0xLCB5OiAwIH0sXG4gICAgQXJyb3dSaWdodDogeyB4OiAxLCB5OiAwIH0sXG59O1xudmFyIHdyYXBOb2RlID0gKE5vZGVDb21wb25lbnQpID0+IHtcbiAgICBjb25zdCBOb2RlV3JhcHBlciA9ICh7IGlkLCB0eXBlLCBkYXRhLCB4UG9zLCB5UG9zLCB4UG9zT3JpZ2luLCB5UG9zT3JpZ2luLCBzZWxlY3RlZCwgb25DbGljaywgb25Nb3VzZUVudGVyLCBvbk1vdXNlTW92ZSwgb25Nb3VzZUxlYXZlLCBvbkNvbnRleHRNZW51LCBvbkRvdWJsZUNsaWNrLCBzdHlsZSwgY2xhc3NOYW1lLCBpc0RyYWdnYWJsZSwgaXNTZWxlY3RhYmxlLCBpc0Nvbm5lY3RhYmxlLCBpc0ZvY3VzYWJsZSwgc2VsZWN0Tm9kZXNPbkRyYWcsIHNvdXJjZVBvc2l0aW9uLCB0YXJnZXRQb3NpdGlvbiwgaGlkZGVuLCByZXNpemVPYnNlcnZlciwgZHJhZ0hhbmRsZSwgekluZGV4LCBpc1BhcmVudCwgbm9EcmFnQ2xhc3NOYW1lLCBub1BhbkNsYXNzTmFtZSwgaW5pdGlhbGl6ZWQsIGRpc2FibGVLZXlib2FyZEExMXksIGFyaWFMYWJlbCwgcmZJZCwgaGFzSGFuZGxlQm91bmRzLCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICAgICAgY29uc3Qgbm9kZVJlZiA9IHVzZVJlZihudWxsKTtcbiAgICAgICAgY29uc3QgcHJldlNvdXJjZVBvc2l0aW9uID0gdXNlUmVmKHNvdXJjZVBvc2l0aW9uKTtcbiAgICAgICAgY29uc3QgcHJldlRhcmdldFBvc2l0aW9uID0gdXNlUmVmKHRhcmdldFBvc2l0aW9uKTtcbiAgICAgICAgY29uc3QgcHJldlR5cGUgPSB1c2VSZWYodHlwZSk7XG4gICAgICAgIGNvbnN0IGhhc1BvaW50ZXJFdmVudHMgPSBpc1NlbGVjdGFibGUgfHwgaXNEcmFnZ2FibGUgfHwgb25DbGljayB8fCBvbk1vdXNlRW50ZXIgfHwgb25Nb3VzZU1vdmUgfHwgb25Nb3VzZUxlYXZlO1xuICAgICAgICBjb25zdCB1cGRhdGVQb3NpdGlvbnMgPSB1c2VVcGRhdGVOb2RlUG9zaXRpb25zKCk7XG4gICAgICAgIGNvbnN0IG9uTW91c2VFbnRlckhhbmRsZXIgPSBnZXRNb3VzZUhhbmRsZXIoaWQsIHN0b3JlLmdldFN0YXRlLCBvbk1vdXNlRW50ZXIpO1xuICAgICAgICBjb25zdCBvbk1vdXNlTW92ZUhhbmRsZXIgPSBnZXRNb3VzZUhhbmRsZXIoaWQsIHN0b3JlLmdldFN0YXRlLCBvbk1vdXNlTW92ZSk7XG4gICAgICAgIGNvbnN0IG9uTW91c2VMZWF2ZUhhbmRsZXIgPSBnZXRNb3VzZUhhbmRsZXIoaWQsIHN0b3JlLmdldFN0YXRlLCBvbk1vdXNlTGVhdmUpO1xuICAgICAgICBjb25zdCBvbkNvbnRleHRNZW51SGFuZGxlciA9IGdldE1vdXNlSGFuZGxlcihpZCwgc3RvcmUuZ2V0U3RhdGUsIG9uQ29udGV4dE1lbnUpO1xuICAgICAgICBjb25zdCBvbkRvdWJsZUNsaWNrSGFuZGxlciA9IGdldE1vdXNlSGFuZGxlcihpZCwgc3RvcmUuZ2V0U3RhdGUsIG9uRG91YmxlQ2xpY2spO1xuICAgICAgICBjb25zdCBvblNlbGVjdE5vZGVIYW5kbGVyID0gKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCB7IG5vZGVEcmFnVGhyZXNob2xkIH0gPSBzdG9yZS5nZXRTdGF0ZSgpO1xuICAgICAgICAgICAgaWYgKGlzU2VsZWN0YWJsZSAmJiAoIXNlbGVjdE5vZGVzT25EcmFnIHx8ICFpc0RyYWdnYWJsZSB8fCBub2RlRHJhZ1RocmVzaG9sZCA+IDApKSB7XG4gICAgICAgICAgICAgICAgLy8gdGhpcyBoYW5kbGVyIGdldHMgY2FsbGVkIHdpdGhpbiB0aGUgZHJhZyBzdGFydCBldmVudCB3aGVuIHNlbGVjdE5vZGVzT25EcmFnPXRydWVcbiAgICAgICAgICAgICAgICBoYW5kbGVOb2RlQ2xpY2soe1xuICAgICAgICAgICAgICAgICAgICBpZCxcbiAgICAgICAgICAgICAgICAgICAgc3RvcmUsXG4gICAgICAgICAgICAgICAgICAgIG5vZGVSZWYsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAob25DbGljaykge1xuICAgICAgICAgICAgICAgIGNvbnN0IG5vZGUgPSBzdG9yZS5nZXRTdGF0ZSgpLm5vZGVJbnRlcm5hbHMuZ2V0KGlkKTtcbiAgICAgICAgICAgICAgICBpZiAobm9kZSkge1xuICAgICAgICAgICAgICAgICAgICBvbkNsaWNrKGV2ZW50LCB7IC4uLm5vZGUgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBvbktleURvd24gPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGlmIChpc0lucHV0RE9NTm9kZShldmVudCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZWxlbWVudFNlbGVjdGlvbktleXMuaW5jbHVkZXMoZXZlbnQua2V5KSAmJiBpc1NlbGVjdGFibGUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB1bnNlbGVjdCA9IGV2ZW50LmtleSA9PT0gJ0VzY2FwZSc7XG4gICAgICAgICAgICAgICAgaGFuZGxlTm9kZUNsaWNrKHtcbiAgICAgICAgICAgICAgICAgICAgaWQsXG4gICAgICAgICAgICAgICAgICAgIHN0b3JlLFxuICAgICAgICAgICAgICAgICAgICB1bnNlbGVjdCxcbiAgICAgICAgICAgICAgICAgICAgbm9kZVJlZixcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2UgaWYgKCFkaXNhYmxlS2V5Ym9hcmRBMTF5ICYmXG4gICAgICAgICAgICAgICAgaXNEcmFnZ2FibGUgJiZcbiAgICAgICAgICAgICAgICBzZWxlY3RlZCAmJlxuICAgICAgICAgICAgICAgIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhcnJvd0tleURpZmZzLCBldmVudC5rZXkpKSB7XG4gICAgICAgICAgICAgICAgc3RvcmUuc2V0U3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICBhcmlhTGl2ZU1lc3NhZ2U6IGBNb3ZlZCBzZWxlY3RlZCBub2RlICR7ZXZlbnQua2V5XG4gICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgnQXJyb3cnLCAnJylcbiAgICAgICAgICAgICAgICAgICAgICAgIC50b0xvd2VyQ2FzZSgpfS4gTmV3IHBvc2l0aW9uLCB4OiAke35+eFBvc30sIHk6ICR7fn55UG9zfWAsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdXBkYXRlUG9zaXRpb25zKHtcbiAgICAgICAgICAgICAgICAgICAgeDogYXJyb3dLZXlEaWZmc1tldmVudC5rZXldLngsXG4gICAgICAgICAgICAgICAgICAgIHk6IGFycm93S2V5RGlmZnNbZXZlbnQua2V5XS55LFxuICAgICAgICAgICAgICAgICAgICBpc1NoaWZ0UHJlc3NlZDogZXZlbnQuc2hpZnRLZXksXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChub2RlUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzaXplT2JzZXJ2ZXI/LnVub2JzZXJ2ZShub2RlUmVmLmN1cnJlbnQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIH0sIFtdKTtcbiAgICAgICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgICAgIGlmIChub2RlUmVmLmN1cnJlbnQgJiYgIWhpZGRlbikge1xuICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJOb2RlID0gbm9kZVJlZi5jdXJyZW50O1xuICAgICAgICAgICAgICAgIGlmICghaW5pdGlhbGl6ZWQgfHwgIWhhc0hhbmRsZUJvdW5kcykge1xuICAgICAgICAgICAgICAgICAgICAvLyBBdCB0aGlzIHBvaW50IHdlIGFsd2F5cyB3YW50IHRvIG1ha2Ugc3VyZSB0aGF0IHRoZSBub2RlIGdldHMgcmUtbWVhc3VyZWQgLyByZS1pbml0aWFsaXplZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgbmVlZCB0byB1bm9ic2VydmUgaXQgZmlyc3QgaW4gY2FzZSBpdCBpcyBzdGlsbCBvYnNlcnZlZFxuICAgICAgICAgICAgICAgICAgICByZXNpemVPYnNlcnZlcj8udW5vYnNlcnZlKGN1cnJOb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzaXplT2JzZXJ2ZXI/Lm9ic2VydmUoY3Vyck5vZGUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgW2hpZGRlbiwgaW5pdGlhbGl6ZWQsIGhhc0hhbmRsZUJvdW5kc10pO1xuICAgICAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICAgICAgLy8gd2hlbiB0aGUgdXNlciBwcm9ncmFtbWF0aWNhbGx5IGNoYW5nZXMgdGhlIHNvdXJjZSBvciBoYW5kbGUgcG9zaXRpb24sIHdlIHJlLWluaXRpYWxpemUgdGhlIG5vZGVcbiAgICAgICAgICAgIGNvbnN0IHR5cGVDaGFuZ2VkID0gcHJldlR5cGUuY3VycmVudCAhPT0gdHlwZTtcbiAgICAgICAgICAgIGNvbnN0IHNvdXJjZVBvc0NoYW5nZWQgPSBwcmV2U291cmNlUG9zaXRpb24uY3VycmVudCAhPT0gc291cmNlUG9zaXRpb247XG4gICAgICAgICAgICBjb25zdCB0YXJnZXRQb3NDaGFuZ2VkID0gcHJldlRhcmdldFBvc2l0aW9uLmN1cnJlbnQgIT09IHRhcmdldFBvc2l0aW9uO1xuICAgICAgICAgICAgaWYgKG5vZGVSZWYuY3VycmVudCAmJiAodHlwZUNoYW5nZWQgfHwgc291cmNlUG9zQ2hhbmdlZCB8fCB0YXJnZXRQb3NDaGFuZ2VkKSkge1xuICAgICAgICAgICAgICAgIGlmICh0eXBlQ2hhbmdlZCkge1xuICAgICAgICAgICAgICAgICAgICBwcmV2VHlwZS5jdXJyZW50ID0gdHlwZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHNvdXJjZVBvc0NoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJldlNvdXJjZVBvc2l0aW9uLmN1cnJlbnQgPSBzb3VyY2VQb3NpdGlvbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldFBvc0NoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJldlRhcmdldFBvc2l0aW9uLmN1cnJlbnQgPSB0YXJnZXRQb3NpdGlvbjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3RvcmUuZ2V0U3RhdGUoKS51cGRhdGVOb2RlRGltZW5zaW9ucyhbeyBpZCwgbm9kZUVsZW1lbnQ6IG5vZGVSZWYuY3VycmVudCwgZm9yY2VVcGRhdGU6IHRydWUgfV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LCBbaWQsIHR5cGUsIHNvdXJjZVBvc2l0aW9uLCB0YXJnZXRQb3NpdGlvbl0pO1xuICAgICAgICBjb25zdCBkcmFnZ2luZyA9IHVzZURyYWcoe1xuICAgICAgICAgICAgbm9kZVJlZixcbiAgICAgICAgICAgIGRpc2FibGVkOiBoaWRkZW4gfHwgIWlzRHJhZ2dhYmxlLFxuICAgICAgICAgICAgbm9EcmFnQ2xhc3NOYW1lLFxuICAgICAgICAgICAgaGFuZGxlU2VsZWN0b3I6IGRyYWdIYW5kbGUsXG4gICAgICAgICAgICBub2RlSWQ6IGlkLFxuICAgICAgICAgICAgaXNTZWxlY3RhYmxlLFxuICAgICAgICAgICAgc2VsZWN0Tm9kZXNPbkRyYWcsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoaGlkZGVuKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IGNjKFtcbiAgICAgICAgICAgICAgICAncmVhY3QtZmxvd19fbm9kZScsXG4gICAgICAgICAgICAgICAgYHJlYWN0LWZsb3dfX25vZGUtJHt0eXBlfWAsXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAvLyB0aGlzIGlzIG92ZXJ3cml0YWJsZSBieSBwYXNzaW5nIGBub3BhbmAgYXMgYSBjbGFzcyBuYW1lXG4gICAgICAgICAgICAgICAgICAgIFtub1BhbkNsYXNzTmFtZV06IGlzRHJhZ2dhYmxlLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgY2xhc3NOYW1lLFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgc2VsZWN0ZWQsXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGFibGU6IGlzU2VsZWN0YWJsZSxcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50OiBpc1BhcmVudCxcbiAgICAgICAgICAgICAgICAgICAgZHJhZ2dpbmcsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0pLCByZWY6IG5vZGVSZWYsIHN0eWxlOiB7XG4gICAgICAgICAgICAgICAgekluZGV4LFxuICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogYHRyYW5zbGF0ZSgke3hQb3NPcmlnaW59cHgsJHt5UG9zT3JpZ2lufXB4KWAsXG4gICAgICAgICAgICAgICAgcG9pbnRlckV2ZW50czogaGFzUG9pbnRlckV2ZW50cyA/ICdhbGwnIDogJ25vbmUnLFxuICAgICAgICAgICAgICAgIHZpc2liaWxpdHk6IGluaXRpYWxpemVkID8gJ3Zpc2libGUnIDogJ2hpZGRlbicsXG4gICAgICAgICAgICAgICAgLi4uc3R5bGUsXG4gICAgICAgICAgICB9LCBcImRhdGEtaWRcIjogaWQsIFwiZGF0YS10ZXN0aWRcIjogYHJmX19ub2RlLSR7aWR9YCwgb25Nb3VzZUVudGVyOiBvbk1vdXNlRW50ZXJIYW5kbGVyLCBvbk1vdXNlTW92ZTogb25Nb3VzZU1vdmVIYW5kbGVyLCBvbk1vdXNlTGVhdmU6IG9uTW91c2VMZWF2ZUhhbmRsZXIsIG9uQ29udGV4dE1lbnU6IG9uQ29udGV4dE1lbnVIYW5kbGVyLCBvbkNsaWNrOiBvblNlbGVjdE5vZGVIYW5kbGVyLCBvbkRvdWJsZUNsaWNrOiBvbkRvdWJsZUNsaWNrSGFuZGxlciwgb25LZXlEb3duOiBpc0ZvY3VzYWJsZSA/IG9uS2V5RG93biA6IHVuZGVmaW5lZCwgdGFiSW5kZXg6IGlzRm9jdXNhYmxlID8gMCA6IHVuZGVmaW5lZCwgcm9sZTogaXNGb2N1c2FibGUgPyAnYnV0dG9uJyA6IHVuZGVmaW5lZCwgXCJhcmlhLWRlc2NyaWJlZGJ5XCI6IGRpc2FibGVLZXlib2FyZEExMXkgPyB1bmRlZmluZWQgOiBgJHtBUklBX05PREVfREVTQ19LRVl9LSR7cmZJZH1gLCBcImFyaWEtbGFiZWxcIjogYXJpYUxhYmVsIH0sXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFByb3ZpZGVyLCB7IHZhbHVlOiBpZCB9LFxuICAgICAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoTm9kZUNvbXBvbmVudCwgeyBpZDogaWQsIGRhdGE6IGRhdGEsIHR5cGU6IHR5cGUsIHhQb3M6IHhQb3MsIHlQb3M6IHlQb3MsIHNlbGVjdGVkOiBzZWxlY3RlZCwgaXNDb25uZWN0YWJsZTogaXNDb25uZWN0YWJsZSwgc291cmNlUG9zaXRpb246IHNvdXJjZVBvc2l0aW9uLCB0YXJnZXRQb3NpdGlvbjogdGFyZ2V0UG9zaXRpb24sIGRyYWdnaW5nOiBkcmFnZ2luZywgZHJhZ0hhbmRsZTogZHJhZ0hhbmRsZSwgekluZGV4OiB6SW5kZXggfSkpKSk7XG4gICAgfTtcbiAgICBOb2RlV3JhcHBlci5kaXNwbGF5TmFtZSA9ICdOb2RlV3JhcHBlcic7XG4gICAgcmV0dXJuIG1lbW8oTm9kZVdyYXBwZXIpO1xufTtcblxuLyoqXG4gKiBUaGUgbm9kZXMgc2VsZWN0aW9uIHJlY3RhbmdsZSBnZXRzIGRpc3BsYXllZCB3aGVuIGEgdXNlclxuICogbWFkZSBhIHNlbGVjdGlvbiB3aXRoIG9uIG9yIHNldmVyYWwgbm9kZXNcbiAqL1xuY29uc3Qgc2VsZWN0b3IkNyA9IChzKSA9PiB7XG4gICAgY29uc3Qgc2VsZWN0ZWROb2RlcyA9IHMuZ2V0Tm9kZXMoKS5maWx0ZXIoKG4pID0+IG4uc2VsZWN0ZWQpO1xuICAgIHJldHVybiB7XG4gICAgICAgIC4uLmdldE5vZGVzQm91bmRzKHNlbGVjdGVkTm9kZXMsIHMubm9kZU9yaWdpbiksXG4gICAgICAgIHRyYW5zZm9ybVN0cmluZzogYHRyYW5zbGF0ZSgke3MudHJhbnNmb3JtWzBdfXB4LCR7cy50cmFuc2Zvcm1bMV19cHgpIHNjYWxlKCR7cy50cmFuc2Zvcm1bMl19KWAsXG4gICAgICAgIHVzZXJTZWxlY3Rpb25BY3RpdmU6IHMudXNlclNlbGVjdGlvbkFjdGl2ZSxcbiAgICB9O1xufTtcbmZ1bmN0aW9uIE5vZGVzU2VsZWN0aW9uKHsgb25TZWxlY3Rpb25Db250ZXh0TWVudSwgbm9QYW5DbGFzc05hbWUsIGRpc2FibGVLZXlib2FyZEExMXkgfSkge1xuICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICBjb25zdCB7IHdpZHRoLCBoZWlnaHQsIHg6IGxlZnQsIHk6IHRvcCwgdHJhbnNmb3JtU3RyaW5nLCB1c2VyU2VsZWN0aW9uQWN0aXZlIH0gPSB1c2VTdG9yZShzZWxlY3RvciQ3LCBzaGFsbG93KTtcbiAgICBjb25zdCB1cGRhdGVQb3NpdGlvbnMgPSB1c2VVcGRhdGVOb2RlUG9zaXRpb25zKCk7XG4gICAgY29uc3Qgbm9kZVJlZiA9IHVzZVJlZihudWxsKTtcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBpZiAoIWRpc2FibGVLZXlib2FyZEExMXkpIHtcbiAgICAgICAgICAgIG5vZGVSZWYuY3VycmVudD8uZm9jdXMoe1xuICAgICAgICAgICAgICAgIHByZXZlbnRTY3JvbGw6IHRydWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sIFtkaXNhYmxlS2V5Ym9hcmRBMTF5XSk7XG4gICAgdXNlRHJhZyh7XG4gICAgICAgIG5vZGVSZWYsXG4gICAgfSk7XG4gICAgaWYgKHVzZXJTZWxlY3Rpb25BY3RpdmUgfHwgIXdpZHRoIHx8ICFoZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IG9uQ29udGV4dE1lbnUgPSBvblNlbGVjdGlvbkNvbnRleHRNZW51XG4gICAgICAgID8gKGV2ZW50KSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3RlZE5vZGVzID0gc3RvcmVcbiAgICAgICAgICAgICAgICAuZ2V0U3RhdGUoKVxuICAgICAgICAgICAgICAgIC5nZXROb2RlcygpXG4gICAgICAgICAgICAgICAgLmZpbHRlcigobikgPT4gbi5zZWxlY3RlZCk7XG4gICAgICAgICAgICBvblNlbGVjdGlvbkNvbnRleHRNZW51KGV2ZW50LCBzZWxlY3RlZE5vZGVzKTtcbiAgICAgICAgfVxuICAgICAgICA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBvbktleURvd24gPSAoZXZlbnQpID0+IHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChhcnJvd0tleURpZmZzLCBldmVudC5rZXkpKSB7XG4gICAgICAgICAgICB1cGRhdGVQb3NpdGlvbnMoe1xuICAgICAgICAgICAgICAgIHg6IGFycm93S2V5RGlmZnNbZXZlbnQua2V5XS54LFxuICAgICAgICAgICAgICAgIHk6IGFycm93S2V5RGlmZnNbZXZlbnQua2V5XS55LFxuICAgICAgICAgICAgICAgIGlzU2hpZnRQcmVzc2VkOiBldmVudC5zaGlmdEtleSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IGNjKFsncmVhY3QtZmxvd19fbm9kZXNzZWxlY3Rpb24nLCAncmVhY3QtZmxvd19fY29udGFpbmVyJywgbm9QYW5DbGFzc05hbWVdKSwgc3R5bGU6IHtcbiAgICAgICAgICAgIHRyYW5zZm9ybTogdHJhbnNmb3JtU3RyaW5nLFxuICAgICAgICB9IH0sXG4gICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyByZWY6IG5vZGVSZWYsIGNsYXNzTmFtZTogXCJyZWFjdC1mbG93X19ub2Rlc3NlbGVjdGlvbi1yZWN0XCIsIG9uQ29udGV4dE1lbnU6IG9uQ29udGV4dE1lbnUsIHRhYkluZGV4OiBkaXNhYmxlS2V5Ym9hcmRBMTF5ID8gdW5kZWZpbmVkIDogLTEsIG9uS2V5RG93bjogZGlzYWJsZUtleWJvYXJkQTExeSA/IHVuZGVmaW5lZCA6IG9uS2V5RG93biwgc3R5bGU6IHtcbiAgICAgICAgICAgICAgICB3aWR0aCxcbiAgICAgICAgICAgICAgICBoZWlnaHQsXG4gICAgICAgICAgICAgICAgdG9wLFxuICAgICAgICAgICAgICAgIGxlZnQsXG4gICAgICAgICAgICB9IH0pKSk7XG59XG52YXIgTm9kZXNTZWxlY3Rpb24kMSA9IG1lbW8oTm9kZXNTZWxlY3Rpb24pO1xuXG5jb25zdCBzZWxlY3RvciQ2ID0gKHMpID0+IHMubm9kZXNTZWxlY3Rpb25BY3RpdmU7XG5jb25zdCBGbG93UmVuZGVyZXIgPSAoeyBjaGlsZHJlbiwgb25QYW5lQ2xpY2ssIG9uUGFuZU1vdXNlRW50ZXIsIG9uUGFuZU1vdXNlTW92ZSwgb25QYW5lTW91c2VMZWF2ZSwgb25QYW5lQ29udGV4dE1lbnUsIG9uUGFuZVNjcm9sbCwgZGVsZXRlS2V5Q29kZSwgb25Nb3ZlLCBvbk1vdmVTdGFydCwgb25Nb3ZlRW5kLCBzZWxlY3Rpb25LZXlDb2RlLCBzZWxlY3Rpb25PbkRyYWcsIHNlbGVjdGlvbk1vZGUsIG9uU2VsZWN0aW9uU3RhcnQsIG9uU2VsZWN0aW9uRW5kLCBtdWx0aVNlbGVjdGlvbktleUNvZGUsIHBhbkFjdGl2YXRpb25LZXlDb2RlLCB6b29tQWN0aXZhdGlvbktleUNvZGUsIGVsZW1lbnRzU2VsZWN0YWJsZSwgem9vbU9uU2Nyb2xsLCB6b29tT25QaW5jaCwgcGFuT25TY3JvbGw6IF9wYW5PblNjcm9sbCwgcGFuT25TY3JvbGxTcGVlZCwgcGFuT25TY3JvbGxNb2RlLCB6b29tT25Eb3VibGVDbGljaywgcGFuT25EcmFnOiBfcGFuT25EcmFnLCBkZWZhdWx0Vmlld3BvcnQsIHRyYW5zbGF0ZUV4dGVudCwgbWluWm9vbSwgbWF4Wm9vbSwgcHJldmVudFNjcm9sbGluZywgb25TZWxlY3Rpb25Db250ZXh0TWVudSwgbm9XaGVlbENsYXNzTmFtZSwgbm9QYW5DbGFzc05hbWUsIGRpc2FibGVLZXlib2FyZEExMXksIH0pID0+IHtcbiAgICBjb25zdCBub2Rlc1NlbGVjdGlvbkFjdGl2ZSA9IHVzZVN0b3JlKHNlbGVjdG9yJDYpO1xuICAgIGNvbnN0IHNlbGVjdGlvbktleVByZXNzZWQgPSB1c2VLZXlQcmVzcyhzZWxlY3Rpb25LZXlDb2RlKTtcbiAgICBjb25zdCBwYW5BY3RpdmF0aW9uS2V5UHJlc3NlZCA9IHVzZUtleVByZXNzKHBhbkFjdGl2YXRpb25LZXlDb2RlKTtcbiAgICBjb25zdCBwYW5PbkRyYWcgPSBwYW5BY3RpdmF0aW9uS2V5UHJlc3NlZCB8fCBfcGFuT25EcmFnO1xuICAgIGNvbnN0IHBhbk9uU2Nyb2xsID0gcGFuQWN0aXZhdGlvbktleVByZXNzZWQgfHwgX3Bhbk9uU2Nyb2xsO1xuICAgIGNvbnN0IGlzU2VsZWN0aW5nID0gc2VsZWN0aW9uS2V5UHJlc3NlZCB8fCAoc2VsZWN0aW9uT25EcmFnICYmIHBhbk9uRHJhZyAhPT0gdHJ1ZSk7XG4gICAgdXNlR2xvYmFsS2V5SGFuZGxlcih7IGRlbGV0ZUtleUNvZGUsIG11bHRpU2VsZWN0aW9uS2V5Q29kZSB9KTtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoWm9vbVBhbmUsIHsgb25Nb3ZlOiBvbk1vdmUsIG9uTW92ZVN0YXJ0OiBvbk1vdmVTdGFydCwgb25Nb3ZlRW5kOiBvbk1vdmVFbmQsIG9uUGFuZUNvbnRleHRNZW51OiBvblBhbmVDb250ZXh0TWVudSwgZWxlbWVudHNTZWxlY3RhYmxlOiBlbGVtZW50c1NlbGVjdGFibGUsIHpvb21PblNjcm9sbDogem9vbU9uU2Nyb2xsLCB6b29tT25QaW5jaDogem9vbU9uUGluY2gsIHBhbk9uU2Nyb2xsOiBwYW5PblNjcm9sbCwgcGFuT25TY3JvbGxTcGVlZDogcGFuT25TY3JvbGxTcGVlZCwgcGFuT25TY3JvbGxNb2RlOiBwYW5PblNjcm9sbE1vZGUsIHpvb21PbkRvdWJsZUNsaWNrOiB6b29tT25Eb3VibGVDbGljaywgcGFuT25EcmFnOiAhc2VsZWN0aW9uS2V5UHJlc3NlZCAmJiBwYW5PbkRyYWcsIGRlZmF1bHRWaWV3cG9ydDogZGVmYXVsdFZpZXdwb3J0LCB0cmFuc2xhdGVFeHRlbnQ6IHRyYW5zbGF0ZUV4dGVudCwgbWluWm9vbTogbWluWm9vbSwgbWF4Wm9vbTogbWF4Wm9vbSwgem9vbUFjdGl2YXRpb25LZXlDb2RlOiB6b29tQWN0aXZhdGlvbktleUNvZGUsIHByZXZlbnRTY3JvbGxpbmc6IHByZXZlbnRTY3JvbGxpbmcsIG5vV2hlZWxDbGFzc05hbWU6IG5vV2hlZWxDbGFzc05hbWUsIG5vUGFuQ2xhc3NOYW1lOiBub1BhbkNsYXNzTmFtZSB9LFxuICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFBhbmUsIHsgb25TZWxlY3Rpb25TdGFydDogb25TZWxlY3Rpb25TdGFydCwgb25TZWxlY3Rpb25FbmQ6IG9uU2VsZWN0aW9uRW5kLCBvblBhbmVDbGljazogb25QYW5lQ2xpY2ssIG9uUGFuZU1vdXNlRW50ZXI6IG9uUGFuZU1vdXNlRW50ZXIsIG9uUGFuZU1vdXNlTW92ZTogb25QYW5lTW91c2VNb3ZlLCBvblBhbmVNb3VzZUxlYXZlOiBvblBhbmVNb3VzZUxlYXZlLCBvblBhbmVDb250ZXh0TWVudTogb25QYW5lQ29udGV4dE1lbnUsIG9uUGFuZVNjcm9sbDogb25QYW5lU2Nyb2xsLCBwYW5PbkRyYWc6IHBhbk9uRHJhZywgaXNTZWxlY3Rpbmc6ICEhaXNTZWxlY3RpbmcsIHNlbGVjdGlvbk1vZGU6IHNlbGVjdGlvbk1vZGUgfSxcbiAgICAgICAgICAgIGNoaWxkcmVuLFxuICAgICAgICAgICAgbm9kZXNTZWxlY3Rpb25BY3RpdmUgJiYgKFJlYWN0LmNyZWF0ZUVsZW1lbnQoTm9kZXNTZWxlY3Rpb24kMSwgeyBvblNlbGVjdGlvbkNvbnRleHRNZW51OiBvblNlbGVjdGlvbkNvbnRleHRNZW51LCBub1BhbkNsYXNzTmFtZTogbm9QYW5DbGFzc05hbWUsIGRpc2FibGVLZXlib2FyZEExMXk6IGRpc2FibGVLZXlib2FyZEExMXkgfSkpKSkpO1xufTtcbkZsb3dSZW5kZXJlci5kaXNwbGF5TmFtZSA9ICdGbG93UmVuZGVyZXInO1xudmFyIEZsb3dSZW5kZXJlciQxID0gbWVtbyhGbG93UmVuZGVyZXIpO1xuXG5mdW5jdGlvbiB1c2VWaXNpYmxlTm9kZXMob25seVJlbmRlclZpc2libGUpIHtcbiAgICBjb25zdCBub2RlcyA9IHVzZVN0b3JlKHVzZUNhbGxiYWNrKChzKSA9PiBvbmx5UmVuZGVyVmlzaWJsZVxuICAgICAgICA/IGdldE5vZGVzSW5zaWRlKHMubm9kZUludGVybmFscywgeyB4OiAwLCB5OiAwLCB3aWR0aDogcy53aWR0aCwgaGVpZ2h0OiBzLmhlaWdodCB9LCBzLnRyYW5zZm9ybSwgdHJ1ZSlcbiAgICAgICAgOiBzLmdldE5vZGVzKCksIFtvbmx5UmVuZGVyVmlzaWJsZV0pKTtcbiAgICByZXR1cm4gbm9kZXM7XG59XG5cbmZ1bmN0aW9uIGNyZWF0ZU5vZGVUeXBlcyhub2RlVHlwZXMpIHtcbiAgICBjb25zdCBzdGFuZGFyZFR5cGVzID0ge1xuICAgICAgICBpbnB1dDogd3JhcE5vZGUoKG5vZGVUeXBlcy5pbnB1dCB8fCBJbnB1dE5vZGUkMSkpLFxuICAgICAgICBkZWZhdWx0OiB3cmFwTm9kZSgobm9kZVR5cGVzLmRlZmF1bHQgfHwgRGVmYXVsdE5vZGUkMSkpLFxuICAgICAgICBvdXRwdXQ6IHdyYXBOb2RlKChub2RlVHlwZXMub3V0cHV0IHx8IE91dHB1dE5vZGUkMSkpLFxuICAgICAgICBncm91cDogd3JhcE5vZGUoKG5vZGVUeXBlcy5ncm91cCB8fCBHcm91cE5vZGUpKSxcbiAgICB9O1xuICAgIGNvbnN0IHdyYXBwZWRUeXBlcyA9IHt9O1xuICAgIGNvbnN0IHNwZWNpYWxUeXBlcyA9IE9iamVjdC5rZXlzKG5vZGVUeXBlcylcbiAgICAgICAgLmZpbHRlcigoaykgPT4gIVsnaW5wdXQnLCAnZGVmYXVsdCcsICdvdXRwdXQnLCAnZ3JvdXAnXS5pbmNsdWRlcyhrKSlcbiAgICAgICAgLnJlZHVjZSgocmVzLCBrZXkpID0+IHtcbiAgICAgICAgcmVzW2tleV0gPSB3cmFwTm9kZSgobm9kZVR5cGVzW2tleV0gfHwgRGVmYXVsdE5vZGUkMSkpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH0sIHdyYXBwZWRUeXBlcyk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLi4uc3RhbmRhcmRUeXBlcyxcbiAgICAgICAgLi4uc3BlY2lhbFR5cGVzLFxuICAgIH07XG59XG5jb25zdCBnZXRQb3NpdGlvbldpdGhPcmlnaW4gPSAoeyB4LCB5LCB3aWR0aCwgaGVpZ2h0LCBvcmlnaW4sIH0pID0+IHtcbiAgICBpZiAoIXdpZHRoIHx8ICFoZWlnaHQpIHtcbiAgICAgICAgcmV0dXJuIHsgeCwgeSB9O1xuICAgIH1cbiAgICBpZiAob3JpZ2luWzBdIDwgMCB8fCBvcmlnaW5bMV0gPCAwIHx8IG9yaWdpblswXSA+IDEgfHwgb3JpZ2luWzFdID4gMSkge1xuICAgICAgICByZXR1cm4geyB4LCB5IH07XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIHg6IHggLSB3aWR0aCAqIG9yaWdpblswXSxcbiAgICAgICAgeTogeSAtIGhlaWdodCAqIG9yaWdpblsxXSxcbiAgICB9O1xufTtcblxuY29uc3Qgc2VsZWN0b3IkNSA9IChzKSA9PiAoe1xuICAgIG5vZGVzRHJhZ2dhYmxlOiBzLm5vZGVzRHJhZ2dhYmxlLFxuICAgIG5vZGVzQ29ubmVjdGFibGU6IHMubm9kZXNDb25uZWN0YWJsZSxcbiAgICBub2Rlc0ZvY3VzYWJsZTogcy5ub2Rlc0ZvY3VzYWJsZSxcbiAgICBlbGVtZW50c1NlbGVjdGFibGU6IHMuZWxlbWVudHNTZWxlY3RhYmxlLFxuICAgIHVwZGF0ZU5vZGVEaW1lbnNpb25zOiBzLnVwZGF0ZU5vZGVEaW1lbnNpb25zLFxuICAgIG9uRXJyb3I6IHMub25FcnJvcixcbn0pO1xuY29uc3QgTm9kZVJlbmRlcmVyID0gKHByb3BzKSA9PiB7XG4gICAgY29uc3QgeyBub2Rlc0RyYWdnYWJsZSwgbm9kZXNDb25uZWN0YWJsZSwgbm9kZXNGb2N1c2FibGUsIGVsZW1lbnRzU2VsZWN0YWJsZSwgdXBkYXRlTm9kZURpbWVuc2lvbnMsIG9uRXJyb3IgfSA9IHVzZVN0b3JlKHNlbGVjdG9yJDUsIHNoYWxsb3cpO1xuICAgIGNvbnN0IG5vZGVzID0gdXNlVmlzaWJsZU5vZGVzKHByb3BzLm9ubHlSZW5kZXJWaXNpYmxlRWxlbWVudHMpO1xuICAgIGNvbnN0IHJlc2l6ZU9ic2VydmVyUmVmID0gdXNlUmVmKCk7XG4gICAgY29uc3QgcmVzaXplT2JzZXJ2ZXIgPSB1c2VNZW1vKCgpID0+IHtcbiAgICAgICAgaWYgKHR5cGVvZiBSZXNpemVPYnNlcnZlciA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKChlbnRyaWVzKSA9PiB7XG4gICAgICAgICAgICBjb25zdCB1cGRhdGVzID0gZW50cmllcy5tYXAoKGVudHJ5KSA9PiAoe1xuICAgICAgICAgICAgICAgIGlkOiBlbnRyeS50YXJnZXQuZ2V0QXR0cmlidXRlKCdkYXRhLWlkJyksXG4gICAgICAgICAgICAgICAgbm9kZUVsZW1lbnQ6IGVudHJ5LnRhcmdldCxcbiAgICAgICAgICAgICAgICBmb3JjZVVwZGF0ZTogdHJ1ZSxcbiAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIHVwZGF0ZU5vZGVEaW1lbnNpb25zKHVwZGF0ZXMpO1xuICAgICAgICB9KTtcbiAgICAgICAgcmVzaXplT2JzZXJ2ZXJSZWYuY3VycmVudCA9IG9ic2VydmVyO1xuICAgICAgICByZXR1cm4gb2JzZXJ2ZXI7XG4gICAgfSwgW10pO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIHJldHVybiAoKSA9PiB7XG4gICAgICAgICAgICByZXNpemVPYnNlcnZlclJlZj8uY3VycmVudD8uZGlzY29ubmVjdCgpO1xuICAgICAgICB9O1xuICAgIH0sIFtdKTtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwicmVhY3QtZmxvd19fbm9kZXNcIiwgc3R5bGU6IGNvbnRhaW5lclN0eWxlIH0sIG5vZGVzLm1hcCgobm9kZSkgPT4ge1xuICAgICAgICBsZXQgbm9kZVR5cGUgPSBub2RlLnR5cGUgfHwgJ2RlZmF1bHQnO1xuICAgICAgICBpZiAoIXByb3BzLm5vZGVUeXBlc1tub2RlVHlwZV0pIHtcbiAgICAgICAgICAgIG9uRXJyb3I/LignMDAzJywgZXJyb3JNZXNzYWdlc1snZXJyb3IwMDMnXShub2RlVHlwZSkpO1xuICAgICAgICAgICAgbm9kZVR5cGUgPSAnZGVmYXVsdCc7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgTm9kZUNvbXBvbmVudCA9IChwcm9wcy5ub2RlVHlwZXNbbm9kZVR5cGVdIHx8IHByb3BzLm5vZGVUeXBlcy5kZWZhdWx0KTtcbiAgICAgICAgY29uc3QgaXNEcmFnZ2FibGUgPSAhIShub2RlLmRyYWdnYWJsZSB8fCAobm9kZXNEcmFnZ2FibGUgJiYgdHlwZW9mIG5vZGUuZHJhZ2dhYmxlID09PSAndW5kZWZpbmVkJykpO1xuICAgICAgICBjb25zdCBpc1NlbGVjdGFibGUgPSAhIShub2RlLnNlbGVjdGFibGUgfHwgKGVsZW1lbnRzU2VsZWN0YWJsZSAmJiB0eXBlb2Ygbm9kZS5zZWxlY3RhYmxlID09PSAndW5kZWZpbmVkJykpO1xuICAgICAgICBjb25zdCBpc0Nvbm5lY3RhYmxlID0gISEobm9kZS5jb25uZWN0YWJsZSB8fCAobm9kZXNDb25uZWN0YWJsZSAmJiB0eXBlb2Ygbm9kZS5jb25uZWN0YWJsZSA9PT0gJ3VuZGVmaW5lZCcpKTtcbiAgICAgICAgY29uc3QgaXNGb2N1c2FibGUgPSAhIShub2RlLmZvY3VzYWJsZSB8fCAobm9kZXNGb2N1c2FibGUgJiYgdHlwZW9mIG5vZGUuZm9jdXNhYmxlID09PSAndW5kZWZpbmVkJykpO1xuICAgICAgICBjb25zdCBjbGFtcGVkUG9zaXRpb24gPSBwcm9wcy5ub2RlRXh0ZW50XG4gICAgICAgICAgICA/IGNsYW1wUG9zaXRpb24obm9kZS5wb3NpdGlvbkFic29sdXRlLCBwcm9wcy5ub2RlRXh0ZW50KVxuICAgICAgICAgICAgOiBub2RlLnBvc2l0aW9uQWJzb2x1dGU7XG4gICAgICAgIGNvbnN0IHBvc1ggPSBjbGFtcGVkUG9zaXRpb24/LnggPz8gMDtcbiAgICAgICAgY29uc3QgcG9zWSA9IGNsYW1wZWRQb3NpdGlvbj8ueSA/PyAwO1xuICAgICAgICBjb25zdCBwb3NPcmlnaW4gPSBnZXRQb3NpdGlvbldpdGhPcmlnaW4oe1xuICAgICAgICAgICAgeDogcG9zWCxcbiAgICAgICAgICAgIHk6IHBvc1ksXG4gICAgICAgICAgICB3aWR0aDogbm9kZS53aWR0aCA/PyAwLFxuICAgICAgICAgICAgaGVpZ2h0OiBub2RlLmhlaWdodCA/PyAwLFxuICAgICAgICAgICAgb3JpZ2luOiBwcm9wcy5ub2RlT3JpZ2luLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KE5vZGVDb21wb25lbnQsIHsga2V5OiBub2RlLmlkLCBpZDogbm9kZS5pZCwgY2xhc3NOYW1lOiBub2RlLmNsYXNzTmFtZSwgc3R5bGU6IG5vZGUuc3R5bGUsIHR5cGU6IG5vZGVUeXBlLCBkYXRhOiBub2RlLmRhdGEsIHNvdXJjZVBvc2l0aW9uOiBub2RlLnNvdXJjZVBvc2l0aW9uIHx8IFBvc2l0aW9uLkJvdHRvbSwgdGFyZ2V0UG9zaXRpb246IG5vZGUudGFyZ2V0UG9zaXRpb24gfHwgUG9zaXRpb24uVG9wLCBoaWRkZW46IG5vZGUuaGlkZGVuLCB4UG9zOiBwb3NYLCB5UG9zOiBwb3NZLCB4UG9zT3JpZ2luOiBwb3NPcmlnaW4ueCwgeVBvc09yaWdpbjogcG9zT3JpZ2luLnksIHNlbGVjdE5vZGVzT25EcmFnOiBwcm9wcy5zZWxlY3ROb2Rlc09uRHJhZywgb25DbGljazogcHJvcHMub25Ob2RlQ2xpY2ssIG9uTW91c2VFbnRlcjogcHJvcHMub25Ob2RlTW91c2VFbnRlciwgb25Nb3VzZU1vdmU6IHByb3BzLm9uTm9kZU1vdXNlTW92ZSwgb25Nb3VzZUxlYXZlOiBwcm9wcy5vbk5vZGVNb3VzZUxlYXZlLCBvbkNvbnRleHRNZW51OiBwcm9wcy5vbk5vZGVDb250ZXh0TWVudSwgb25Eb3VibGVDbGljazogcHJvcHMub25Ob2RlRG91YmxlQ2xpY2ssIHNlbGVjdGVkOiAhIW5vZGUuc2VsZWN0ZWQsIGlzRHJhZ2dhYmxlOiBpc0RyYWdnYWJsZSwgaXNTZWxlY3RhYmxlOiBpc1NlbGVjdGFibGUsIGlzQ29ubmVjdGFibGU6IGlzQ29ubmVjdGFibGUsIGlzRm9jdXNhYmxlOiBpc0ZvY3VzYWJsZSwgcmVzaXplT2JzZXJ2ZXI6IHJlc2l6ZU9ic2VydmVyLCBkcmFnSGFuZGxlOiBub2RlLmRyYWdIYW5kbGUsIHpJbmRleDogbm9kZVtpbnRlcm5hbHNTeW1ib2xdPy56ID8/IDAsIGlzUGFyZW50OiAhIW5vZGVbaW50ZXJuYWxzU3ltYm9sXT8uaXNQYXJlbnQsIG5vRHJhZ0NsYXNzTmFtZTogcHJvcHMubm9EcmFnQ2xhc3NOYW1lLCBub1BhbkNsYXNzTmFtZTogcHJvcHMubm9QYW5DbGFzc05hbWUsIGluaXRpYWxpemVkOiAhIW5vZGUud2lkdGggJiYgISFub2RlLmhlaWdodCwgcmZJZDogcHJvcHMucmZJZCwgZGlzYWJsZUtleWJvYXJkQTExeTogcHJvcHMuZGlzYWJsZUtleWJvYXJkQTExeSwgYXJpYUxhYmVsOiBub2RlLmFyaWFMYWJlbCwgaGFzSGFuZGxlQm91bmRzOiAhIW5vZGVbaW50ZXJuYWxzU3ltYm9sXT8uaGFuZGxlQm91bmRzIH0pKTtcbiAgICB9KSkpO1xufTtcbk5vZGVSZW5kZXJlci5kaXNwbGF5TmFtZSA9ICdOb2RlUmVuZGVyZXInO1xudmFyIE5vZGVSZW5kZXJlciQxID0gbWVtbyhOb2RlUmVuZGVyZXIpO1xuXG5jb25zdCBzaGlmdFggPSAoeCwgc2hpZnQsIHBvc2l0aW9uKSA9PiB7XG4gICAgaWYgKHBvc2l0aW9uID09PSBQb3NpdGlvbi5MZWZ0KVxuICAgICAgICByZXR1cm4geCAtIHNoaWZ0O1xuICAgIGlmIChwb3NpdGlvbiA9PT0gUG9zaXRpb24uUmlnaHQpXG4gICAgICAgIHJldHVybiB4ICsgc2hpZnQ7XG4gICAgcmV0dXJuIHg7XG59O1xuY29uc3Qgc2hpZnRZID0gKHksIHNoaWZ0LCBwb3NpdGlvbikgPT4ge1xuICAgIGlmIChwb3NpdGlvbiA9PT0gUG9zaXRpb24uVG9wKVxuICAgICAgICByZXR1cm4geSAtIHNoaWZ0O1xuICAgIGlmIChwb3NpdGlvbiA9PT0gUG9zaXRpb24uQm90dG9tKVxuICAgICAgICByZXR1cm4geSArIHNoaWZ0O1xuICAgIHJldHVybiB5O1xufTtcbmNvbnN0IEVkZ2VVcGRhdGVyQ2xhc3NOYW1lID0gJ3JlYWN0LWZsb3dfX2VkZ2V1cGRhdGVyJztcbmNvbnN0IEVkZ2VBbmNob3IgPSAoeyBwb3NpdGlvbiwgY2VudGVyWCwgY2VudGVyWSwgcmFkaXVzID0gMTAsIG9uTW91c2VEb3duLCBvbk1vdXNlRW50ZXIsIG9uTW91c2VPdXQsIHR5cGUsIH0pID0+IChSZWFjdC5jcmVhdGVFbGVtZW50KFwiY2lyY2xlXCIsIHsgb25Nb3VzZURvd246IG9uTW91c2VEb3duLCBvbk1vdXNlRW50ZXI6IG9uTW91c2VFbnRlciwgb25Nb3VzZU91dDogb25Nb3VzZU91dCwgY2xhc3NOYW1lOiBjYyhbRWRnZVVwZGF0ZXJDbGFzc05hbWUsIGAke0VkZ2VVcGRhdGVyQ2xhc3NOYW1lfS0ke3R5cGV9YF0pLCBjeDogc2hpZnRYKGNlbnRlclgsIHJhZGl1cywgcG9zaXRpb24pLCBjeTogc2hpZnRZKGNlbnRlclksIHJhZGl1cywgcG9zaXRpb24pLCByOiByYWRpdXMsIHN0cm9rZTogXCJ0cmFuc3BhcmVudFwiLCBmaWxsOiBcInRyYW5zcGFyZW50XCIgfSkpO1xuXG5jb25zdCBhbHdheXNWYWxpZENvbm5lY3Rpb24gPSAoKSA9PiB0cnVlO1xudmFyIHdyYXBFZGdlID0gKEVkZ2VDb21wb25lbnQpID0+IHtcbiAgICBjb25zdCBFZGdlV3JhcHBlciA9ICh7IGlkLCBjbGFzc05hbWUsIHR5cGUsIGRhdGEsIG9uQ2xpY2ssIG9uRWRnZURvdWJsZUNsaWNrLCBzZWxlY3RlZCwgYW5pbWF0ZWQsIGxhYmVsLCBsYWJlbFN0eWxlLCBsYWJlbFNob3dCZywgbGFiZWxCZ1N0eWxlLCBsYWJlbEJnUGFkZGluZywgbGFiZWxCZ0JvcmRlclJhZGl1cywgc3R5bGUsIHNvdXJjZSwgdGFyZ2V0LCBzb3VyY2VYLCBzb3VyY2VZLCB0YXJnZXRYLCB0YXJnZXRZLCBzb3VyY2VQb3NpdGlvbiwgdGFyZ2V0UG9zaXRpb24sIGVsZW1lbnRzU2VsZWN0YWJsZSwgaGlkZGVuLCBzb3VyY2VIYW5kbGVJZCwgdGFyZ2V0SGFuZGxlSWQsIG9uQ29udGV4dE1lbnUsIG9uTW91c2VFbnRlciwgb25Nb3VzZU1vdmUsIG9uTW91c2VMZWF2ZSwgZWRnZVVwZGF0ZXJSYWRpdXMsIG9uRWRnZVVwZGF0ZSwgb25FZGdlVXBkYXRlU3RhcnQsIG9uRWRnZVVwZGF0ZUVuZCwgbWFya2VyRW5kLCBtYXJrZXJTdGFydCwgcmZJZCwgYXJpYUxhYmVsLCBpc0ZvY3VzYWJsZSwgaXNVcGRhdGFibGUsIHBhdGhPcHRpb25zLCBpbnRlcmFjdGlvbldpZHRoLCB9KSA9PiB7XG4gICAgICAgIGNvbnN0IGVkZ2VSZWYgPSB1c2VSZWYobnVsbCk7XG4gICAgICAgIGNvbnN0IFt1cGRhdGVIb3Zlciwgc2V0VXBkYXRlSG92ZXJdID0gdXNlU3RhdGUoZmFsc2UpO1xuICAgICAgICBjb25zdCBbdXBkYXRpbmcsIHNldFVwZGF0aW5nXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgICAgICAgY29uc3Qgc3RvcmUgPSB1c2VTdG9yZUFwaSgpO1xuICAgICAgICBjb25zdCBtYXJrZXJTdGFydFVybCA9IHVzZU1lbW8oKCkgPT4gYHVybCgnIyR7Z2V0TWFya2VySWQobWFya2VyU3RhcnQsIHJmSWQpfScpYCwgW21hcmtlclN0YXJ0LCByZklkXSk7XG4gICAgICAgIGNvbnN0IG1hcmtlckVuZFVybCA9IHVzZU1lbW8oKCkgPT4gYHVybCgnIyR7Z2V0TWFya2VySWQobWFya2VyRW5kLCByZklkKX0nKWAsIFttYXJrZXJFbmQsIHJmSWRdKTtcbiAgICAgICAgaWYgKGhpZGRlbikge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgb25FZGdlQ2xpY2sgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHsgZWRnZXMsIGFkZFNlbGVjdGVkRWRnZXMsIHVuc2VsZWN0Tm9kZXNBbmRFZGdlcywgbXVsdGlTZWxlY3Rpb25BY3RpdmUgfSA9IHN0b3JlLmdldFN0YXRlKCk7XG4gICAgICAgICAgICBjb25zdCBlZGdlID0gZWRnZXMuZmluZCgoZSkgPT4gZS5pZCA9PT0gaWQpO1xuICAgICAgICAgICAgaWYgKCFlZGdlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGVsZW1lbnRzU2VsZWN0YWJsZSkge1xuICAgICAgICAgICAgICAgIHN0b3JlLnNldFN0YXRlKHsgbm9kZXNTZWxlY3Rpb25BY3RpdmU6IGZhbHNlIH0pO1xuICAgICAgICAgICAgICAgIGlmIChlZGdlLnNlbGVjdGVkICYmIG11bHRpU2VsZWN0aW9uQWN0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHVuc2VsZWN0Tm9kZXNBbmRFZGdlcyh7IG5vZGVzOiBbXSwgZWRnZXM6IFtlZGdlXSB9KTtcbiAgICAgICAgICAgICAgICAgICAgZWRnZVJlZi5jdXJyZW50Py5ibHVyKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhZGRTZWxlY3RlZEVkZ2VzKFtpZF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChvbkNsaWNrKSB7XG4gICAgICAgICAgICAgICAgb25DbGljayhldmVudCwgZWRnZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IG9uRWRnZURvdWJsZUNsaWNrSGFuZGxlciA9IGdldE1vdXNlSGFuZGxlciQxKGlkLCBzdG9yZS5nZXRTdGF0ZSwgb25FZGdlRG91YmxlQ2xpY2spO1xuICAgICAgICBjb25zdCBvbkVkZ2VDb250ZXh0TWVudSA9IGdldE1vdXNlSGFuZGxlciQxKGlkLCBzdG9yZS5nZXRTdGF0ZSwgb25Db250ZXh0TWVudSk7XG4gICAgICAgIGNvbnN0IG9uRWRnZU1vdXNlRW50ZXIgPSBnZXRNb3VzZUhhbmRsZXIkMShpZCwgc3RvcmUuZ2V0U3RhdGUsIG9uTW91c2VFbnRlcik7XG4gICAgICAgIGNvbnN0IG9uRWRnZU1vdXNlTW92ZSA9IGdldE1vdXNlSGFuZGxlciQxKGlkLCBzdG9yZS5nZXRTdGF0ZSwgb25Nb3VzZU1vdmUpO1xuICAgICAgICBjb25zdCBvbkVkZ2VNb3VzZUxlYXZlID0gZ2V0TW91c2VIYW5kbGVyJDEoaWQsIHN0b3JlLmdldFN0YXRlLCBvbk1vdXNlTGVhdmUpO1xuICAgICAgICBjb25zdCBoYW5kbGVFZGdlVXBkYXRlciA9IChldmVudCwgaXNTb3VyY2VIYW5kbGUpID0+IHtcbiAgICAgICAgICAgIC8vIGF2b2lkIHRyaWdnZXJpbmcgZWRnZSB1cGRhdGVyIGlmIG1vdXNlIGJ0biBpcyBub3QgbGVmdFxuICAgICAgICAgICAgaWYgKGV2ZW50LmJ1dHRvbiAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IHsgZWRnZXMsIGlzVmFsaWRDb25uZWN0aW9uOiBpc1ZhbGlkQ29ubmVjdGlvblN0b3JlIH0gPSBzdG9yZS5nZXRTdGF0ZSgpO1xuICAgICAgICAgICAgY29uc3Qgbm9kZUlkID0gaXNTb3VyY2VIYW5kbGUgPyB0YXJnZXQgOiBzb3VyY2U7XG4gICAgICAgICAgICBjb25zdCBoYW5kbGVJZCA9IChpc1NvdXJjZUhhbmRsZSA/IHRhcmdldEhhbmRsZUlkIDogc291cmNlSGFuZGxlSWQpIHx8IG51bGw7XG4gICAgICAgICAgICBjb25zdCBoYW5kbGVUeXBlID0gaXNTb3VyY2VIYW5kbGUgPyAndGFyZ2V0JyA6ICdzb3VyY2UnO1xuICAgICAgICAgICAgY29uc3QgaXNWYWxpZENvbm5lY3Rpb24gPSBpc1ZhbGlkQ29ubmVjdGlvblN0b3JlIHx8IGFsd2F5c1ZhbGlkQ29ubmVjdGlvbjtcbiAgICAgICAgICAgIGNvbnN0IGlzVGFyZ2V0ID0gaXNTb3VyY2VIYW5kbGU7XG4gICAgICAgICAgICBjb25zdCBlZGdlID0gZWRnZXMuZmluZCgoZSkgPT4gZS5pZCA9PT0gaWQpO1xuICAgICAgICAgICAgc2V0VXBkYXRpbmcodHJ1ZSk7XG4gICAgICAgICAgICBvbkVkZ2VVcGRhdGVTdGFydD8uKGV2ZW50LCBlZGdlLCBoYW5kbGVUeXBlKTtcbiAgICAgICAgICAgIGNvbnN0IF9vbkVkZ2VVcGRhdGVFbmQgPSAoZXZ0KSA9PiB7XG4gICAgICAgICAgICAgICAgc2V0VXBkYXRpbmcoZmFsc2UpO1xuICAgICAgICAgICAgICAgIG9uRWRnZVVwZGF0ZUVuZD8uKGV2dCwgZWRnZSwgaGFuZGxlVHlwZSk7XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgY29uc3Qgb25Db25uZWN0RWRnZSA9IChjb25uZWN0aW9uKSA9PiBvbkVkZ2VVcGRhdGU/LihlZGdlLCBjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIGhhbmRsZVBvaW50ZXJEb3duKHtcbiAgICAgICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgICAgICBoYW5kbGVJZCxcbiAgICAgICAgICAgICAgICBub2RlSWQsXG4gICAgICAgICAgICAgICAgb25Db25uZWN0OiBvbkNvbm5lY3RFZGdlLFxuICAgICAgICAgICAgICAgIGlzVGFyZ2V0LFxuICAgICAgICAgICAgICAgIGdldFN0YXRlOiBzdG9yZS5nZXRTdGF0ZSxcbiAgICAgICAgICAgICAgICBzZXRTdGF0ZTogc3RvcmUuc2V0U3RhdGUsXG4gICAgICAgICAgICAgICAgaXNWYWxpZENvbm5lY3Rpb24sXG4gICAgICAgICAgICAgICAgZWRnZVVwZGF0ZXJUeXBlOiBoYW5kbGVUeXBlLFxuICAgICAgICAgICAgICAgIG9uRWRnZVVwZGF0ZUVuZDogX29uRWRnZVVwZGF0ZUVuZCxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9O1xuICAgICAgICBjb25zdCBvbkVkZ2VVcGRhdGVyU291cmNlTW91c2VEb3duID0gKGV2ZW50KSA9PiBoYW5kbGVFZGdlVXBkYXRlcihldmVudCwgdHJ1ZSk7XG4gICAgICAgIGNvbnN0IG9uRWRnZVVwZGF0ZXJUYXJnZXRNb3VzZURvd24gPSAoZXZlbnQpID0+IGhhbmRsZUVkZ2VVcGRhdGVyKGV2ZW50LCBmYWxzZSk7XG4gICAgICAgIGNvbnN0IG9uRWRnZVVwZGF0ZXJNb3VzZUVudGVyID0gKCkgPT4gc2V0VXBkYXRlSG92ZXIodHJ1ZSk7XG4gICAgICAgIGNvbnN0IG9uRWRnZVVwZGF0ZXJNb3VzZU91dCA9ICgpID0+IHNldFVwZGF0ZUhvdmVyKGZhbHNlKTtcbiAgICAgICAgY29uc3QgaW5hY3RpdmUgPSAhZWxlbWVudHNTZWxlY3RhYmxlICYmICFvbkNsaWNrO1xuICAgICAgICBjb25zdCBvbktleURvd24gPSAoZXZlbnQpID0+IHtcbiAgICAgICAgICAgIGlmIChlbGVtZW50U2VsZWN0aW9uS2V5cy5pbmNsdWRlcyhldmVudC5rZXkpICYmIGVsZW1lbnRzU2VsZWN0YWJsZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHsgdW5zZWxlY3ROb2Rlc0FuZEVkZ2VzLCBhZGRTZWxlY3RlZEVkZ2VzLCBlZGdlcyB9ID0gc3RvcmUuZ2V0U3RhdGUoKTtcbiAgICAgICAgICAgICAgICBjb25zdCB1bnNlbGVjdCA9IGV2ZW50LmtleSA9PT0gJ0VzY2FwZSc7XG4gICAgICAgICAgICAgICAgaWYgKHVuc2VsZWN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGVkZ2VSZWYuY3VycmVudD8uYmx1cigpO1xuICAgICAgICAgICAgICAgICAgICB1bnNlbGVjdE5vZGVzQW5kRWRnZXMoeyBlZGdlczogW2VkZ2VzLmZpbmQoKGUpID0+IGUuaWQgPT09IGlkKV0gfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBhZGRTZWxlY3RlZEVkZ2VzKFtpZF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KFwiZ1wiLCB7IGNsYXNzTmFtZTogY2MoW1xuICAgICAgICAgICAgICAgICdyZWFjdC1mbG93X19lZGdlJyxcbiAgICAgICAgICAgICAgICBgcmVhY3QtZmxvd19fZWRnZS0ke3R5cGV9YCxcbiAgICAgICAgICAgICAgICBjbGFzc05hbWUsXG4gICAgICAgICAgICAgICAgeyBzZWxlY3RlZCwgYW5pbWF0ZWQsIGluYWN0aXZlLCB1cGRhdGluZzogdXBkYXRlSG92ZXIgfSxcbiAgICAgICAgICAgIF0pLCBvbkNsaWNrOiBvbkVkZ2VDbGljaywgb25Eb3VibGVDbGljazogb25FZGdlRG91YmxlQ2xpY2tIYW5kbGVyLCBvbkNvbnRleHRNZW51OiBvbkVkZ2VDb250ZXh0TWVudSwgb25Nb3VzZUVudGVyOiBvbkVkZ2VNb3VzZUVudGVyLCBvbk1vdXNlTW92ZTogb25FZGdlTW91c2VNb3ZlLCBvbk1vdXNlTGVhdmU6IG9uRWRnZU1vdXNlTGVhdmUsIG9uS2V5RG93bjogaXNGb2N1c2FibGUgPyBvbktleURvd24gOiB1bmRlZmluZWQsIHRhYkluZGV4OiBpc0ZvY3VzYWJsZSA/IDAgOiB1bmRlZmluZWQsIHJvbGU6IGlzRm9jdXNhYmxlID8gJ2J1dHRvbicgOiAnaW1nJywgXCJkYXRhLXRlc3RpZFwiOiBgcmZfX2VkZ2UtJHtpZH1gLCBcImFyaWEtbGFiZWxcIjogYXJpYUxhYmVsID09PSBudWxsID8gdW5kZWZpbmVkIDogYXJpYUxhYmVsID8gYXJpYUxhYmVsIDogYEVkZ2UgZnJvbSAke3NvdXJjZX0gdG8gJHt0YXJnZXR9YCwgXCJhcmlhLWRlc2NyaWJlZGJ5XCI6IGlzRm9jdXNhYmxlID8gYCR7QVJJQV9FREdFX0RFU0NfS0VZfS0ke3JmSWR9YCA6IHVuZGVmaW5lZCwgcmVmOiBlZGdlUmVmIH0sXG4gICAgICAgICAgICAhdXBkYXRpbmcgJiYgKFJlYWN0LmNyZWF0ZUVsZW1lbnQoRWRnZUNvbXBvbmVudCwgeyBpZDogaWQsIHNvdXJjZTogc291cmNlLCB0YXJnZXQ6IHRhcmdldCwgc2VsZWN0ZWQ6IHNlbGVjdGVkLCBhbmltYXRlZDogYW5pbWF0ZWQsIGxhYmVsOiBsYWJlbCwgbGFiZWxTdHlsZTogbGFiZWxTdHlsZSwgbGFiZWxTaG93Qmc6IGxhYmVsU2hvd0JnLCBsYWJlbEJnU3R5bGU6IGxhYmVsQmdTdHlsZSwgbGFiZWxCZ1BhZGRpbmc6IGxhYmVsQmdQYWRkaW5nLCBsYWJlbEJnQm9yZGVyUmFkaXVzOiBsYWJlbEJnQm9yZGVyUmFkaXVzLCBkYXRhOiBkYXRhLCBzdHlsZTogc3R5bGUsIHNvdXJjZVg6IHNvdXJjZVgsIHNvdXJjZVk6IHNvdXJjZVksIHRhcmdldFg6IHRhcmdldFgsIHRhcmdldFk6IHRhcmdldFksIHNvdXJjZVBvc2l0aW9uOiBzb3VyY2VQb3NpdGlvbiwgdGFyZ2V0UG9zaXRpb246IHRhcmdldFBvc2l0aW9uLCBzb3VyY2VIYW5kbGVJZDogc291cmNlSGFuZGxlSWQsIHRhcmdldEhhbmRsZUlkOiB0YXJnZXRIYW5kbGVJZCwgbWFya2VyU3RhcnQ6IG1hcmtlclN0YXJ0VXJsLCBtYXJrZXJFbmQ6IG1hcmtlckVuZFVybCwgcGF0aE9wdGlvbnM6IHBhdGhPcHRpb25zLCBpbnRlcmFjdGlvbldpZHRoOiBpbnRlcmFjdGlvbldpZHRoIH0pKSxcbiAgICAgICAgICAgIGlzVXBkYXRhYmxlICYmIChSZWFjdC5jcmVhdGVFbGVtZW50KFJlYWN0LkZyYWdtZW50LCBudWxsLFxuICAgICAgICAgICAgICAgIChpc1VwZGF0YWJsZSA9PT0gJ3NvdXJjZScgfHwgaXNVcGRhdGFibGUgPT09IHRydWUpICYmIChSZWFjdC5jcmVhdGVFbGVtZW50KEVkZ2VBbmNob3IsIHsgcG9zaXRpb246IHNvdXJjZVBvc2l0aW9uLCBjZW50ZXJYOiBzb3VyY2VYLCBjZW50ZXJZOiBzb3VyY2VZLCByYWRpdXM6IGVkZ2VVcGRhdGVyUmFkaXVzLCBvbk1vdXNlRG93bjogb25FZGdlVXBkYXRlclNvdXJjZU1vdXNlRG93biwgb25Nb3VzZUVudGVyOiBvbkVkZ2VVcGRhdGVyTW91c2VFbnRlciwgb25Nb3VzZU91dDogb25FZGdlVXBkYXRlck1vdXNlT3V0LCB0eXBlOiBcInNvdXJjZVwiIH0pKSxcbiAgICAgICAgICAgICAgICAoaXNVcGRhdGFibGUgPT09ICd0YXJnZXQnIHx8IGlzVXBkYXRhYmxlID09PSB0cnVlKSAmJiAoUmVhY3QuY3JlYXRlRWxlbWVudChFZGdlQW5jaG9yLCB7IHBvc2l0aW9uOiB0YXJnZXRQb3NpdGlvbiwgY2VudGVyWDogdGFyZ2V0WCwgY2VudGVyWTogdGFyZ2V0WSwgcmFkaXVzOiBlZGdlVXBkYXRlclJhZGl1cywgb25Nb3VzZURvd246IG9uRWRnZVVwZGF0ZXJUYXJnZXRNb3VzZURvd24sIG9uTW91c2VFbnRlcjogb25FZGdlVXBkYXRlck1vdXNlRW50ZXIsIG9uTW91c2VPdXQ6IG9uRWRnZVVwZGF0ZXJNb3VzZU91dCwgdHlwZTogXCJ0YXJnZXRcIiB9KSkpKSkpO1xuICAgIH07XG4gICAgRWRnZVdyYXBwZXIuZGlzcGxheU5hbWUgPSAnRWRnZVdyYXBwZXInO1xuICAgIHJldHVybiBtZW1vKEVkZ2VXcmFwcGVyKTtcbn07XG5cbmZ1bmN0aW9uIGNyZWF0ZUVkZ2VUeXBlcyhlZGdlVHlwZXMpIHtcbiAgICBjb25zdCBzdGFuZGFyZFR5cGVzID0ge1xuICAgICAgICBkZWZhdWx0OiB3cmFwRWRnZSgoZWRnZVR5cGVzLmRlZmF1bHQgfHwgQmV6aWVyRWRnZSkpLFxuICAgICAgICBzdHJhaWdodDogd3JhcEVkZ2UoKGVkZ2VUeXBlcy5iZXppZXIgfHwgU3RyYWlnaHRFZGdlKSksXG4gICAgICAgIHN0ZXA6IHdyYXBFZGdlKChlZGdlVHlwZXMuc3RlcCB8fCBTdGVwRWRnZSkpLFxuICAgICAgICBzbW9vdGhzdGVwOiB3cmFwRWRnZSgoZWRnZVR5cGVzLnN0ZXAgfHwgU21vb3RoU3RlcEVkZ2UpKSxcbiAgICAgICAgc2ltcGxlYmV6aWVyOiB3cmFwRWRnZSgoZWRnZVR5cGVzLnNpbXBsZWJlemllciB8fCBTaW1wbGVCZXppZXJFZGdlKSksXG4gICAgfTtcbiAgICBjb25zdCB3cmFwcGVkVHlwZXMgPSB7fTtcbiAgICBjb25zdCBzcGVjaWFsVHlwZXMgPSBPYmplY3Qua2V5cyhlZGdlVHlwZXMpXG4gICAgICAgIC5maWx0ZXIoKGspID0+ICFbJ2RlZmF1bHQnLCAnYmV6aWVyJ10uaW5jbHVkZXMoaykpXG4gICAgICAgIC5yZWR1Y2UoKHJlcywga2V5KSA9PiB7XG4gICAgICAgIHJlc1trZXldID0gd3JhcEVkZ2UoKGVkZ2VUeXBlc1trZXldIHx8IEJlemllckVkZ2UpKTtcbiAgICAgICAgcmV0dXJuIHJlcztcbiAgICB9LCB3cmFwcGVkVHlwZXMpO1xuICAgIHJldHVybiB7XG4gICAgICAgIC4uLnN0YW5kYXJkVHlwZXMsXG4gICAgICAgIC4uLnNwZWNpYWxUeXBlcyxcbiAgICB9O1xufVxuZnVuY3Rpb24gZ2V0SGFuZGxlUG9zaXRpb24ocG9zaXRpb24sIG5vZGVSZWN0LCBoYW5kbGUgPSBudWxsKSB7XG4gICAgY29uc3QgeCA9IChoYW5kbGU/LnggfHwgMCkgKyBub2RlUmVjdC54O1xuICAgIGNvbnN0IHkgPSAoaGFuZGxlPy55IHx8IDApICsgbm9kZVJlY3QueTtcbiAgICBjb25zdCB3aWR0aCA9IGhhbmRsZT8ud2lkdGggfHwgbm9kZVJlY3Qud2lkdGg7XG4gICAgY29uc3QgaGVpZ2h0ID0gaGFuZGxlPy5oZWlnaHQgfHwgbm9kZVJlY3QuaGVpZ2h0O1xuICAgIHN3aXRjaCAocG9zaXRpb24pIHtcbiAgICAgICAgY2FzZSBQb3NpdGlvbi5Ub3A6XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHg6IHggKyB3aWR0aCAvIDIsXG4gICAgICAgICAgICAgICAgeSxcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgUG9zaXRpb24uUmlnaHQ6XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHg6IHggKyB3aWR0aCxcbiAgICAgICAgICAgICAgICB5OiB5ICsgaGVpZ2h0IC8gMixcbiAgICAgICAgICAgIH07XG4gICAgICAgIGNhc2UgUG9zaXRpb24uQm90dG9tOlxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4OiB4ICsgd2lkdGggLyAyLFxuICAgICAgICAgICAgICAgIHk6IHkgKyBoZWlnaHQsXG4gICAgICAgICAgICB9O1xuICAgICAgICBjYXNlIFBvc2l0aW9uLkxlZnQ6XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIHgsXG4gICAgICAgICAgICAgICAgeTogeSArIGhlaWdodCAvIDIsXG4gICAgICAgICAgICB9O1xuICAgIH1cbn1cbmZ1bmN0aW9uIGdldEhhbmRsZShib3VuZHMsIGhhbmRsZUlkKSB7XG4gICAgaWYgKCFib3VuZHMpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChib3VuZHMubGVuZ3RoID09PSAxIHx8ICFoYW5kbGVJZCkge1xuICAgICAgICByZXR1cm4gYm91bmRzWzBdO1xuICAgIH1cbiAgICBlbHNlIGlmIChoYW5kbGVJZCkge1xuICAgICAgICByZXR1cm4gYm91bmRzLmZpbmQoKGQpID0+IGQuaWQgPT09IGhhbmRsZUlkKSB8fCBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gbnVsbDtcbn1cbmNvbnN0IGdldEVkZ2VQb3NpdGlvbnMgPSAoc291cmNlTm9kZVJlY3QsIHNvdXJjZUhhbmRsZSwgc291cmNlUG9zaXRpb24sIHRhcmdldE5vZGVSZWN0LCB0YXJnZXRIYW5kbGUsIHRhcmdldFBvc2l0aW9uKSA9PiB7XG4gICAgY29uc3Qgc291cmNlSGFuZGxlUG9zID0gZ2V0SGFuZGxlUG9zaXRpb24oc291cmNlUG9zaXRpb24sIHNvdXJjZU5vZGVSZWN0LCBzb3VyY2VIYW5kbGUpO1xuICAgIGNvbnN0IHRhcmdldEhhbmRsZVBvcyA9IGdldEhhbmRsZVBvc2l0aW9uKHRhcmdldFBvc2l0aW9uLCB0YXJnZXROb2RlUmVjdCwgdGFyZ2V0SGFuZGxlKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBzb3VyY2VYOiBzb3VyY2VIYW5kbGVQb3MueCxcbiAgICAgICAgc291cmNlWTogc291cmNlSGFuZGxlUG9zLnksXG4gICAgICAgIHRhcmdldFg6IHRhcmdldEhhbmRsZVBvcy54LFxuICAgICAgICB0YXJnZXRZOiB0YXJnZXRIYW5kbGVQb3MueSxcbiAgICB9O1xufTtcbmZ1bmN0aW9uIGlzRWRnZVZpc2libGUoeyBzb3VyY2VQb3MsIHRhcmdldFBvcywgc291cmNlV2lkdGgsIHNvdXJjZUhlaWdodCwgdGFyZ2V0V2lkdGgsIHRhcmdldEhlaWdodCwgd2lkdGgsIGhlaWdodCwgdHJhbnNmb3JtLCB9KSB7XG4gICAgY29uc3QgZWRnZUJveCA9IHtcbiAgICAgICAgeDogTWF0aC5taW4oc291cmNlUG9zLngsIHRhcmdldFBvcy54KSxcbiAgICAgICAgeTogTWF0aC5taW4oc291cmNlUG9zLnksIHRhcmdldFBvcy55KSxcbiAgICAgICAgeDI6IE1hdGgubWF4KHNvdXJjZVBvcy54ICsgc291cmNlV2lkdGgsIHRhcmdldFBvcy54ICsgdGFyZ2V0V2lkdGgpLFxuICAgICAgICB5MjogTWF0aC5tYXgoc291cmNlUG9zLnkgKyBzb3VyY2VIZWlnaHQsIHRhcmdldFBvcy55ICsgdGFyZ2V0SGVpZ2h0KSxcbiAgICB9O1xuICAgIGlmIChlZGdlQm94LnggPT09IGVkZ2VCb3gueDIpIHtcbiAgICAgICAgZWRnZUJveC54MiArPSAxO1xuICAgIH1cbiAgICBpZiAoZWRnZUJveC55ID09PSBlZGdlQm94LnkyKSB7XG4gICAgICAgIGVkZ2VCb3gueTIgKz0gMTtcbiAgICB9XG4gICAgY29uc3Qgdmlld0JveCA9IHJlY3RUb0JveCh7XG4gICAgICAgIHg6ICgwIC0gdHJhbnNmb3JtWzBdKSAvIHRyYW5zZm9ybVsyXSxcbiAgICAgICAgeTogKDAgLSB0cmFuc2Zvcm1bMV0pIC8gdHJhbnNmb3JtWzJdLFxuICAgICAgICB3aWR0aDogd2lkdGggLyB0cmFuc2Zvcm1bMl0sXG4gICAgICAgIGhlaWdodDogaGVpZ2h0IC8gdHJhbnNmb3JtWzJdLFxuICAgIH0pO1xuICAgIGNvbnN0IHhPdmVybGFwID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odmlld0JveC54MiwgZWRnZUJveC54MikgLSBNYXRoLm1heCh2aWV3Qm94LngsIGVkZ2VCb3gueCkpO1xuICAgIGNvbnN0IHlPdmVybGFwID0gTWF0aC5tYXgoMCwgTWF0aC5taW4odmlld0JveC55MiwgZWRnZUJveC55MikgLSBNYXRoLm1heCh2aWV3Qm94LnksIGVkZ2VCb3gueSkpO1xuICAgIGNvbnN0IG92ZXJsYXBwaW5nQXJlYSA9IE1hdGguY2VpbCh4T3ZlcmxhcCAqIHlPdmVybGFwKTtcbiAgICByZXR1cm4gb3ZlcmxhcHBpbmdBcmVhID4gMDtcbn1cbmZ1bmN0aW9uIGdldE5vZGVEYXRhKG5vZGUpIHtcbiAgICBjb25zdCBoYW5kbGVCb3VuZHMgPSBub2RlPy5baW50ZXJuYWxzU3ltYm9sXT8uaGFuZGxlQm91bmRzIHx8IG51bGw7XG4gICAgY29uc3QgaXNWYWxpZCA9IGhhbmRsZUJvdW5kcyAmJlxuICAgICAgICBub2RlPy53aWR0aCAmJlxuICAgICAgICBub2RlPy5oZWlnaHQgJiZcbiAgICAgICAgdHlwZW9mIG5vZGU/LnBvc2l0aW9uQWJzb2x1dGU/LnggIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIHR5cGVvZiBub2RlPy5wb3NpdGlvbkFic29sdXRlPy55ICE9PSAndW5kZWZpbmVkJztcbiAgICByZXR1cm4gW1xuICAgICAgICB7XG4gICAgICAgICAgICB4OiBub2RlPy5wb3NpdGlvbkFic29sdXRlPy54IHx8IDAsXG4gICAgICAgICAgICB5OiBub2RlPy5wb3NpdGlvbkFic29sdXRlPy55IHx8IDAsXG4gICAgICAgICAgICB3aWR0aDogbm9kZT8ud2lkdGggfHwgMCxcbiAgICAgICAgICAgIGhlaWdodDogbm9kZT8uaGVpZ2h0IHx8IDAsXG4gICAgICAgIH0sXG4gICAgICAgIGhhbmRsZUJvdW5kcyxcbiAgICAgICAgISFpc1ZhbGlkLFxuICAgIF07XG59XG5cbmNvbnN0IGRlZmF1bHRFZGdlVHJlZSA9IFt7IGxldmVsOiAwLCBpc01heExldmVsOiB0cnVlLCBlZGdlczogW10gfV07XG5mdW5jdGlvbiBncm91cEVkZ2VzQnlaTGV2ZWwoZWRnZXMsIG5vZGVJbnRlcm5hbHMsIGVsZXZhdGVFZGdlc09uU2VsZWN0ID0gZmFsc2UpIHtcbiAgICBsZXQgbWF4TGV2ZWwgPSAtMTtcbiAgICBjb25zdCBsZXZlbExvb2t1cCA9IGVkZ2VzLnJlZHVjZSgodHJlZSwgZWRnZSkgPT4ge1xuICAgICAgICBjb25zdCBoYXNaSW5kZXggPSBpc051bWVyaWMoZWRnZS56SW5kZXgpO1xuICAgICAgICBsZXQgeiA9IGhhc1pJbmRleCA/IGVkZ2UuekluZGV4IDogMDtcbiAgICAgICAgaWYgKGVsZXZhdGVFZGdlc09uU2VsZWN0KSB7XG4gICAgICAgICAgICBjb25zdCB0YXJnZXROb2RlID0gbm9kZUludGVybmFscy5nZXQoZWRnZS50YXJnZXQpO1xuICAgICAgICAgICAgY29uc3Qgc291cmNlTm9kZSA9IG5vZGVJbnRlcm5hbHMuZ2V0KGVkZ2Uuc291cmNlKTtcbiAgICAgICAgICAgIGNvbnN0IGVkZ2VPckNvbm5lY3RlZE5vZGVTZWxlY3RlZCA9IGVkZ2Uuc2VsZWN0ZWQgfHwgdGFyZ2V0Tm9kZT8uc2VsZWN0ZWQgfHwgc291cmNlTm9kZT8uc2VsZWN0ZWQ7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3RlZFpJbmRleCA9IE1hdGgubWF4KHNvdXJjZU5vZGU/LltpbnRlcm5hbHNTeW1ib2xdPy56IHx8IDAsIHRhcmdldE5vZGU/LltpbnRlcm5hbHNTeW1ib2xdPy56IHx8IDAsIDEwMDApO1xuICAgICAgICAgICAgeiA9IChoYXNaSW5kZXggPyBlZGdlLnpJbmRleCA6IDApICsgKGVkZ2VPckNvbm5lY3RlZE5vZGVTZWxlY3RlZCA/IHNlbGVjdGVkWkluZGV4IDogMCk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRyZWVbel0pIHtcbiAgICAgICAgICAgIHRyZWVbel0ucHVzaChlZGdlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRyZWVbel0gPSBbZWRnZV07XG4gICAgICAgIH1cbiAgICAgICAgbWF4TGV2ZWwgPSB6ID4gbWF4TGV2ZWwgPyB6IDogbWF4TGV2ZWw7XG4gICAgICAgIHJldHVybiB0cmVlO1xuICAgIH0sIHt9KTtcbiAgICBjb25zdCBlZGdlVHJlZSA9IE9iamVjdC5lbnRyaWVzKGxldmVsTG9va3VwKS5tYXAoKFtrZXksIGVkZ2VzXSkgPT4ge1xuICAgICAgICBjb25zdCBsZXZlbCA9ICtrZXk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBlZGdlcyxcbiAgICAgICAgICAgIGxldmVsLFxuICAgICAgICAgICAgaXNNYXhMZXZlbDogbGV2ZWwgPT09IG1heExldmVsLFxuICAgICAgICB9O1xuICAgIH0pO1xuICAgIGlmIChlZGdlVHJlZS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuIGRlZmF1bHRFZGdlVHJlZTtcbiAgICB9XG4gICAgcmV0dXJuIGVkZ2VUcmVlO1xufVxuZnVuY3Rpb24gdXNlVmlzaWJsZUVkZ2VzKG9ubHlSZW5kZXJWaXNpYmxlLCBub2RlSW50ZXJuYWxzLCBlbGV2YXRlRWRnZXNPblNlbGVjdCkge1xuICAgIGNvbnN0IGVkZ2VzID0gdXNlU3RvcmUodXNlQ2FsbGJhY2soKHMpID0+IHtcbiAgICAgICAgaWYgKCFvbmx5UmVuZGVyVmlzaWJsZSkge1xuICAgICAgICAgICAgcmV0dXJuIHMuZWRnZXM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHMuZWRnZXMuZmlsdGVyKChlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBzb3VyY2VOb2RlID0gbm9kZUludGVybmFscy5nZXQoZS5zb3VyY2UpO1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0Tm9kZSA9IG5vZGVJbnRlcm5hbHMuZ2V0KGUudGFyZ2V0KTtcbiAgICAgICAgICAgIHJldHVybiAoc291cmNlTm9kZT8ud2lkdGggJiZcbiAgICAgICAgICAgICAgICBzb3VyY2VOb2RlPy5oZWlnaHQgJiZcbiAgICAgICAgICAgICAgICB0YXJnZXROb2RlPy53aWR0aCAmJlxuICAgICAgICAgICAgICAgIHRhcmdldE5vZGU/LmhlaWdodCAmJlxuICAgICAgICAgICAgICAgIGlzRWRnZVZpc2libGUoe1xuICAgICAgICAgICAgICAgICAgICBzb3VyY2VQb3M6IHNvdXJjZU5vZGUucG9zaXRpb25BYnNvbHV0ZSB8fCB7IHg6IDAsIHk6IDAgfSxcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0UG9zOiB0YXJnZXROb2RlLnBvc2l0aW9uQWJzb2x1dGUgfHwgeyB4OiAwLCB5OiAwIH0sXG4gICAgICAgICAgICAgICAgICAgIHNvdXJjZVdpZHRoOiBzb3VyY2VOb2RlLndpZHRoLFxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VIZWlnaHQ6IHNvdXJjZU5vZGUuaGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICB0YXJnZXRXaWR0aDogdGFyZ2V0Tm9kZS53aWR0aCxcbiAgICAgICAgICAgICAgICAgICAgdGFyZ2V0SGVpZ2h0OiB0YXJnZXROb2RlLmhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgd2lkdGg6IHMud2lkdGgsXG4gICAgICAgICAgICAgICAgICAgIGhlaWdodDogcy5oZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybTogcy50cmFuc2Zvcm0sXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICB9KTtcbiAgICB9LCBbb25seVJlbmRlclZpc2libGUsIG5vZGVJbnRlcm5hbHNdKSk7XG4gICAgcmV0dXJuIGdyb3VwRWRnZXNCeVpMZXZlbChlZGdlcywgbm9kZUludGVybmFscywgZWxldmF0ZUVkZ2VzT25TZWxlY3QpO1xufVxuXG5jb25zdCBBcnJvd1N5bWJvbCA9ICh7IGNvbG9yID0gJ25vbmUnLCBzdHJva2VXaWR0aCA9IDEgfSkgPT4ge1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChcInBvbHlsaW5lXCIsIHsgc3R5bGU6IHtcbiAgICAgICAgICAgIHN0cm9rZTogY29sb3IsXG4gICAgICAgICAgICBzdHJva2VXaWR0aCxcbiAgICAgICAgfSwgc3Ryb2tlTGluZWNhcDogXCJyb3VuZFwiLCBzdHJva2VMaW5lam9pbjogXCJyb3VuZFwiLCBmaWxsOiBcIm5vbmVcIiwgcG9pbnRzOiBcIi01LC00IDAsMCAtNSw0XCIgfSkpO1xufTtcbmNvbnN0IEFycm93Q2xvc2VkU3ltYm9sID0gKHsgY29sb3IgPSAnbm9uZScsIHN0cm9rZVdpZHRoID0gMSB9KSA9PiB7XG4gICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KFwicG9seWxpbmVcIiwgeyBzdHlsZToge1xuICAgICAgICAgICAgc3Ryb2tlOiBjb2xvcixcbiAgICAgICAgICAgIGZpbGw6IGNvbG9yLFxuICAgICAgICAgICAgc3Ryb2tlV2lkdGgsXG4gICAgICAgIH0sIHN0cm9rZUxpbmVjYXA6IFwicm91bmRcIiwgc3Ryb2tlTGluZWpvaW46IFwicm91bmRcIiwgcG9pbnRzOiBcIi01LC00IDAsMCAtNSw0IC01LC00XCIgfSkpO1xufTtcbmNvbnN0IE1hcmtlclN5bWJvbHMgPSB7XG4gICAgW01hcmtlclR5cGUuQXJyb3ddOiBBcnJvd1N5bWJvbCxcbiAgICBbTWFya2VyVHlwZS5BcnJvd0Nsb3NlZF06IEFycm93Q2xvc2VkU3ltYm9sLFxufTtcbmZ1bmN0aW9uIHVzZU1hcmtlclN5bWJvbCh0eXBlKSB7XG4gICAgY29uc3Qgc3RvcmUgPSB1c2VTdG9yZUFwaSgpO1xuICAgIGNvbnN0IHN5bWJvbCA9IHVzZU1lbW8oKCkgPT4ge1xuICAgICAgICBjb25zdCBzeW1ib2xFeGlzdHMgPSBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoTWFya2VyU3ltYm9scywgdHlwZSk7XG4gICAgICAgIGlmICghc3ltYm9sRXhpc3RzKSB7XG4gICAgICAgICAgICBzdG9yZS5nZXRTdGF0ZSgpLm9uRXJyb3I/LignMDA5JywgZXJyb3JNZXNzYWdlc1snZXJyb3IwMDknXSh0eXBlKSk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gTWFya2VyU3ltYm9sc1t0eXBlXTtcbiAgICB9LCBbdHlwZV0pO1xuICAgIHJldHVybiBzeW1ib2w7XG59XG5cbmNvbnN0IE1hcmtlciA9ICh7IGlkLCB0eXBlLCBjb2xvciwgd2lkdGggPSAxMi41LCBoZWlnaHQgPSAxMi41LCBtYXJrZXJVbml0cyA9ICdzdHJva2VXaWR0aCcsIHN0cm9rZVdpZHRoLCBvcmllbnQgPSAnYXV0by1zdGFydC1yZXZlcnNlJywgfSkgPT4ge1xuICAgIGNvbnN0IFN5bWJvbCA9IHVzZU1hcmtlclN5bWJvbCh0eXBlKTtcbiAgICBpZiAoIVN5bWJvbCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KFwibWFya2VyXCIsIHsgY2xhc3NOYW1lOiBcInJlYWN0LWZsb3dfX2Fycm93aGVhZFwiLCBpZDogaWQsIG1hcmtlcldpZHRoOiBgJHt3aWR0aH1gLCBtYXJrZXJIZWlnaHQ6IGAke2hlaWdodH1gLCB2aWV3Qm94OiBcIi0xMCAtMTAgMjAgMjBcIiwgbWFya2VyVW5pdHM6IG1hcmtlclVuaXRzLCBvcmllbnQ6IG9yaWVudCwgcmVmWDogXCIwXCIsIHJlZlk6IFwiMFwiIH0sXG4gICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoU3ltYm9sLCB7IGNvbG9yOiBjb2xvciwgc3Ryb2tlV2lkdGg6IHN0cm9rZVdpZHRoIH0pKSk7XG59O1xuY29uc3QgbWFya2VyU2VsZWN0b3IgPSAoeyBkZWZhdWx0Q29sb3IsIHJmSWQgfSkgPT4gKHMpID0+IHtcbiAgICBjb25zdCBpZHMgPSBbXTtcbiAgICByZXR1cm4gcy5lZGdlc1xuICAgICAgICAucmVkdWNlKChtYXJrZXJzLCBlZGdlKSA9PiB7XG4gICAgICAgIFtlZGdlLm1hcmtlclN0YXJ0LCBlZGdlLm1hcmtlckVuZF0uZm9yRWFjaCgobWFya2VyKSA9PiB7XG4gICAgICAgICAgICBpZiAobWFya2VyICYmIHR5cGVvZiBtYXJrZXIgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgbWFya2VySWQgPSBnZXRNYXJrZXJJZChtYXJrZXIsIHJmSWQpO1xuICAgICAgICAgICAgICAgIGlmICghaWRzLmluY2x1ZGVzKG1hcmtlcklkKSkge1xuICAgICAgICAgICAgICAgICAgICBtYXJrZXJzLnB1c2goeyBpZDogbWFya2VySWQsIGNvbG9yOiBtYXJrZXIuY29sb3IgfHwgZGVmYXVsdENvbG9yLCAuLi5tYXJrZXIgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlkcy5wdXNoKG1hcmtlcklkKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbWFya2VycztcbiAgICB9LCBbXSlcbiAgICAgICAgLnNvcnQoKGEsIGIpID0+IGEuaWQubG9jYWxlQ29tcGFyZShiLmlkKSk7XG59O1xuLy8gd2hlbiB5b3UgaGF2ZSBtdWx0aXBsZSBmbG93cyBvbiBhIHBhZ2UgYW5kIHlvdSBoaWRlIHRoZSBmaXJzdCBvbmUsIHRoZSBvdGhlciBvbmVzIGhhdmUgbm8gbWFya2VycyBhbnltb3JlXG4vLyB3aGVuIHRoZXkgZG8gaGF2ZSBtYXJrZXJzIHdpdGggdGhlIHNhbWUgaWRzLiBUbyBwcmV2ZW50IHRoaXMgdGhlIHVzZXIgY2FuIHBhc3MgYSB1bmlxdWUgaWQgdG8gdGhlIHJlYWN0IGZsb3cgd3JhcHBlclxuLy8gdGhhdCB3ZSBjYW4gdGhlbiB1c2UgZm9yIGNyZWF0aW5nIG91ciB1bmlxdWUgbWFya2VyIGlkc1xuY29uc3QgTWFya2VyRGVmaW5pdGlvbnMgPSAoeyBkZWZhdWx0Q29sb3IsIHJmSWQgfSkgPT4ge1xuICAgIGNvbnN0IG1hcmtlcnMgPSB1c2VTdG9yZSh1c2VDYWxsYmFjayhtYXJrZXJTZWxlY3Rvcih7IGRlZmF1bHRDb2xvciwgcmZJZCB9KSwgW2RlZmF1bHRDb2xvciwgcmZJZF0pLCBcbiAgICAvLyB0aGUgaWQgaW5jbHVkZXMgYWxsIG1hcmtlciBvcHRpb25zLCBzbyB3ZSBqdXN0IG5lZWQgdG8gbG9vayBhdCB0aGF0IHBhcnQgb2YgdGhlIG1hcmtlclxuICAgIChhLCBiKSA9PiAhKGEubGVuZ3RoICE9PSBiLmxlbmd0aCB8fCBhLnNvbWUoKG0sIGkpID0+IG0uaWQgIT09IGJbaV0uaWQpKSk7XG4gICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGVmc1wiLCBudWxsLCBtYXJrZXJzLm1hcCgobWFya2VyKSA9PiAoUmVhY3QuY3JlYXRlRWxlbWVudChNYXJrZXIsIHsgaWQ6IG1hcmtlci5pZCwga2V5OiBtYXJrZXIuaWQsIHR5cGU6IG1hcmtlci50eXBlLCBjb2xvcjogbWFya2VyLmNvbG9yLCB3aWR0aDogbWFya2VyLndpZHRoLCBoZWlnaHQ6IG1hcmtlci5oZWlnaHQsIG1hcmtlclVuaXRzOiBtYXJrZXIubWFya2VyVW5pdHMsIHN0cm9rZVdpZHRoOiBtYXJrZXIuc3Ryb2tlV2lkdGgsIG9yaWVudDogbWFya2VyLm9yaWVudCB9KSkpKSk7XG59O1xuTWFya2VyRGVmaW5pdGlvbnMuZGlzcGxheU5hbWUgPSAnTWFya2VyRGVmaW5pdGlvbnMnO1xudmFyIE1hcmtlckRlZmluaXRpb25zJDEgPSBtZW1vKE1hcmtlckRlZmluaXRpb25zKTtcblxuY29uc3Qgc2VsZWN0b3IkNCA9IChzKSA9PiAoe1xuICAgIG5vZGVzQ29ubmVjdGFibGU6IHMubm9kZXNDb25uZWN0YWJsZSxcbiAgICBlZGdlc0ZvY3VzYWJsZTogcy5lZGdlc0ZvY3VzYWJsZSxcbiAgICBlZGdlc1VwZGF0YWJsZTogcy5lZGdlc1VwZGF0YWJsZSxcbiAgICBlbGVtZW50c1NlbGVjdGFibGU6IHMuZWxlbWVudHNTZWxlY3RhYmxlLFxuICAgIHdpZHRoOiBzLndpZHRoLFxuICAgIGhlaWdodDogcy5oZWlnaHQsXG4gICAgY29ubmVjdGlvbk1vZGU6IHMuY29ubmVjdGlvbk1vZGUsXG4gICAgbm9kZUludGVybmFsczogcy5ub2RlSW50ZXJuYWxzLFxuICAgIG9uRXJyb3I6IHMub25FcnJvcixcbn0pO1xuY29uc3QgRWRnZVJlbmRlcmVyID0gKHsgZGVmYXVsdE1hcmtlckNvbG9yLCBvbmx5UmVuZGVyVmlzaWJsZUVsZW1lbnRzLCBlbGV2YXRlRWRnZXNPblNlbGVjdCwgcmZJZCwgZWRnZVR5cGVzLCBub1BhbkNsYXNzTmFtZSwgb25FZGdlVXBkYXRlLCBvbkVkZ2VDb250ZXh0TWVudSwgb25FZGdlTW91c2VFbnRlciwgb25FZGdlTW91c2VNb3ZlLCBvbkVkZ2VNb3VzZUxlYXZlLCBvbkVkZ2VDbGljaywgZWRnZVVwZGF0ZXJSYWRpdXMsIG9uRWRnZURvdWJsZUNsaWNrLCBvbkVkZ2VVcGRhdGVTdGFydCwgb25FZGdlVXBkYXRlRW5kLCBjaGlsZHJlbiwgfSkgPT4ge1xuICAgIGNvbnN0IHsgZWRnZXNGb2N1c2FibGUsIGVkZ2VzVXBkYXRhYmxlLCBlbGVtZW50c1NlbGVjdGFibGUsIHdpZHRoLCBoZWlnaHQsIGNvbm5lY3Rpb25Nb2RlLCBub2RlSW50ZXJuYWxzLCBvbkVycm9yIH0gPSB1c2VTdG9yZShzZWxlY3RvciQ0LCBzaGFsbG93KTtcbiAgICBjb25zdCBlZGdlVHJlZSA9IHVzZVZpc2libGVFZGdlcyhvbmx5UmVuZGVyVmlzaWJsZUVsZW1lbnRzLCBub2RlSW50ZXJuYWxzLCBlbGV2YXRlRWRnZXNPblNlbGVjdCk7XG4gICAgaWYgKCF3aWR0aCkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KFJlYWN0LkZyYWdtZW50LCBudWxsLFxuICAgICAgICBlZGdlVHJlZS5tYXAoKHsgbGV2ZWwsIGVkZ2VzLCBpc01heExldmVsIH0pID0+IChSZWFjdC5jcmVhdGVFbGVtZW50KFwic3ZnXCIsIHsga2V5OiBsZXZlbCwgc3R5bGU6IHsgekluZGV4OiBsZXZlbCB9LCB3aWR0aDogd2lkdGgsIGhlaWdodDogaGVpZ2h0LCBjbGFzc05hbWU6IFwicmVhY3QtZmxvd19fZWRnZXMgcmVhY3QtZmxvd19fY29udGFpbmVyXCIgfSxcbiAgICAgICAgICAgIGlzTWF4TGV2ZWwgJiYgUmVhY3QuY3JlYXRlRWxlbWVudChNYXJrZXJEZWZpbml0aW9ucyQxLCB7IGRlZmF1bHRDb2xvcjogZGVmYXVsdE1hcmtlckNvbG9yLCByZklkOiByZklkIH0pLFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChcImdcIiwgbnVsbCwgZWRnZXMubWFwKChlZGdlKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgW3NvdXJjZU5vZGVSZWN0LCBzb3VyY2VIYW5kbGVCb3VuZHMsIHNvdXJjZUlzVmFsaWRdID0gZ2V0Tm9kZURhdGEobm9kZUludGVybmFscy5nZXQoZWRnZS5zb3VyY2UpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBbdGFyZ2V0Tm9kZVJlY3QsIHRhcmdldEhhbmRsZUJvdW5kcywgdGFyZ2V0SXNWYWxpZF0gPSBnZXROb2RlRGF0YShub2RlSW50ZXJuYWxzLmdldChlZGdlLnRhcmdldCkpO1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlSXNWYWxpZCB8fCAhdGFyZ2V0SXNWYWxpZCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbGV0IGVkZ2VUeXBlID0gZWRnZS50eXBlIHx8ICdkZWZhdWx0JztcbiAgICAgICAgICAgICAgICBpZiAoIWVkZ2VUeXBlc1tlZGdlVHlwZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgb25FcnJvcj8uKCcwMTEnLCBlcnJvck1lc3NhZ2VzWydlcnJvcjAxMSddKGVkZ2VUeXBlKSk7XG4gICAgICAgICAgICAgICAgICAgIGVkZ2VUeXBlID0gJ2RlZmF1bHQnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBFZGdlQ29tcG9uZW50ID0gZWRnZVR5cGVzW2VkZ2VUeXBlXSB8fCBlZGdlVHlwZXMuZGVmYXVsdDtcbiAgICAgICAgICAgICAgICAvLyB3aGVuIGNvbm5lY3Rpb24gdHlwZSBpcyBsb29zZSB3ZSBjYW4gZGVmaW5lIGFsbCBoYW5kbGVzIGFzIHNvdXJjZXMgYW5kIGNvbm5lY3Qgc291cmNlIC0+IHNvdXJjZVxuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldE5vZGVIYW5kbGVzID0gY29ubmVjdGlvbk1vZGUgPT09IENvbm5lY3Rpb25Nb2RlLlN0cmljdFxuICAgICAgICAgICAgICAgICAgICA/IHRhcmdldEhhbmRsZUJvdW5kcy50YXJnZXRcbiAgICAgICAgICAgICAgICAgICAgOiAodGFyZ2V0SGFuZGxlQm91bmRzLnRhcmdldCA/PyBbXSkuY29uY2F0KHRhcmdldEhhbmRsZUJvdW5kcy5zb3VyY2UgPz8gW10pO1xuICAgICAgICAgICAgICAgIGNvbnN0IHNvdXJjZUhhbmRsZSA9IGdldEhhbmRsZShzb3VyY2VIYW5kbGVCb3VuZHMuc291cmNlLCBlZGdlLnNvdXJjZUhhbmRsZSk7XG4gICAgICAgICAgICAgICAgY29uc3QgdGFyZ2V0SGFuZGxlID0gZ2V0SGFuZGxlKHRhcmdldE5vZGVIYW5kbGVzLCBlZGdlLnRhcmdldEhhbmRsZSk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc291cmNlUG9zaXRpb24gPSBzb3VyY2VIYW5kbGU/LnBvc2l0aW9uIHx8IFBvc2l0aW9uLkJvdHRvbTtcbiAgICAgICAgICAgICAgICBjb25zdCB0YXJnZXRQb3NpdGlvbiA9IHRhcmdldEhhbmRsZT8ucG9zaXRpb24gfHwgUG9zaXRpb24uVG9wO1xuICAgICAgICAgICAgICAgIGNvbnN0IGlzRm9jdXNhYmxlID0gISEoZWRnZS5mb2N1c2FibGUgfHwgKGVkZ2VzRm9jdXNhYmxlICYmIHR5cGVvZiBlZGdlLmZvY3VzYWJsZSA9PT0gJ3VuZGVmaW5lZCcpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBpc1VwZGF0YWJsZSA9IHR5cGVvZiBvbkVkZ2VVcGRhdGUgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgICAgICAgICAgICAgIChlZGdlLnVwZGF0YWJsZSB8fCAoZWRnZXNVcGRhdGFibGUgJiYgdHlwZW9mIGVkZ2UudXBkYXRhYmxlID09PSAndW5kZWZpbmVkJykpO1xuICAgICAgICAgICAgICAgIGlmICghc291cmNlSGFuZGxlIHx8ICF0YXJnZXRIYW5kbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgb25FcnJvcj8uKCcwMDgnLCBlcnJvck1lc3NhZ2VzWydlcnJvcjAwOCddKHNvdXJjZUhhbmRsZSwgZWRnZSkpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY29uc3QgeyBzb3VyY2VYLCBzb3VyY2VZLCB0YXJnZXRYLCB0YXJnZXRZIH0gPSBnZXRFZGdlUG9zaXRpb25zKHNvdXJjZU5vZGVSZWN0LCBzb3VyY2VIYW5kbGUsIHNvdXJjZVBvc2l0aW9uLCB0YXJnZXROb2RlUmVjdCwgdGFyZ2V0SGFuZGxlLCB0YXJnZXRQb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KEVkZ2VDb21wb25lbnQsIHsga2V5OiBlZGdlLmlkLCBpZDogZWRnZS5pZCwgY2xhc3NOYW1lOiBjYyhbZWRnZS5jbGFzc05hbWUsIG5vUGFuQ2xhc3NOYW1lXSksIHR5cGU6IGVkZ2VUeXBlLCBkYXRhOiBlZGdlLmRhdGEsIHNlbGVjdGVkOiAhIWVkZ2Uuc2VsZWN0ZWQsIGFuaW1hdGVkOiAhIWVkZ2UuYW5pbWF0ZWQsIGhpZGRlbjogISFlZGdlLmhpZGRlbiwgbGFiZWw6IGVkZ2UubGFiZWwsIGxhYmVsU3R5bGU6IGVkZ2UubGFiZWxTdHlsZSwgbGFiZWxTaG93Qmc6IGVkZ2UubGFiZWxTaG93QmcsIGxhYmVsQmdTdHlsZTogZWRnZS5sYWJlbEJnU3R5bGUsIGxhYmVsQmdQYWRkaW5nOiBlZGdlLmxhYmVsQmdQYWRkaW5nLCBsYWJlbEJnQm9yZGVyUmFkaXVzOiBlZGdlLmxhYmVsQmdCb3JkZXJSYWRpdXMsIHN0eWxlOiBlZGdlLnN0eWxlLCBzb3VyY2U6IGVkZ2Uuc291cmNlLCB0YXJnZXQ6IGVkZ2UudGFyZ2V0LCBzb3VyY2VIYW5kbGVJZDogZWRnZS5zb3VyY2VIYW5kbGUsIHRhcmdldEhhbmRsZUlkOiBlZGdlLnRhcmdldEhhbmRsZSwgbWFya2VyRW5kOiBlZGdlLm1hcmtlckVuZCwgbWFya2VyU3RhcnQ6IGVkZ2UubWFya2VyU3RhcnQsIHNvdXJjZVg6IHNvdXJjZVgsIHNvdXJjZVk6IHNvdXJjZVksIHRhcmdldFg6IHRhcmdldFgsIHRhcmdldFk6IHRhcmdldFksIHNvdXJjZVBvc2l0aW9uOiBzb3VyY2VQb3NpdGlvbiwgdGFyZ2V0UG9zaXRpb246IHRhcmdldFBvc2l0aW9uLCBlbGVtZW50c1NlbGVjdGFibGU6IGVsZW1lbnRzU2VsZWN0YWJsZSwgb25FZGdlVXBkYXRlOiBvbkVkZ2VVcGRhdGUsIG9uQ29udGV4dE1lbnU6IG9uRWRnZUNvbnRleHRNZW51LCBvbk1vdXNlRW50ZXI6IG9uRWRnZU1vdXNlRW50ZXIsIG9uTW91c2VNb3ZlOiBvbkVkZ2VNb3VzZU1vdmUsIG9uTW91c2VMZWF2ZTogb25FZGdlTW91c2VMZWF2ZSwgb25DbGljazogb25FZGdlQ2xpY2ssIGVkZ2VVcGRhdGVyUmFkaXVzOiBlZGdlVXBkYXRlclJhZGl1cywgb25FZGdlRG91YmxlQ2xpY2s6IG9uRWRnZURvdWJsZUNsaWNrLCBvbkVkZ2VVcGRhdGVTdGFydDogb25FZGdlVXBkYXRlU3RhcnQsIG9uRWRnZVVwZGF0ZUVuZDogb25FZGdlVXBkYXRlRW5kLCByZklkOiByZklkLCBhcmlhTGFiZWw6IGVkZ2UuYXJpYUxhYmVsLCBpc0ZvY3VzYWJsZTogaXNGb2N1c2FibGUsIGlzVXBkYXRhYmxlOiBpc1VwZGF0YWJsZSwgcGF0aE9wdGlvbnM6ICdwYXRoT3B0aW9ucycgaW4gZWRnZSA/IGVkZ2UucGF0aE9wdGlvbnMgOiB1bmRlZmluZWQsIGludGVyYWN0aW9uV2lkdGg6IGVkZ2UuaW50ZXJhY3Rpb25XaWR0aCB9KSk7XG4gICAgICAgICAgICB9KSkpKSksXG4gICAgICAgIGNoaWxkcmVuKSk7XG59O1xuRWRnZVJlbmRlcmVyLmRpc3BsYXlOYW1lID0gJ0VkZ2VSZW5kZXJlcic7XG52YXIgRWRnZVJlbmRlcmVyJDEgPSBtZW1vKEVkZ2VSZW5kZXJlcik7XG5cbmNvbnN0IHNlbGVjdG9yJDMgPSAocykgPT4gYHRyYW5zbGF0ZSgke3MudHJhbnNmb3JtWzBdfXB4LCR7cy50cmFuc2Zvcm1bMV19cHgpIHNjYWxlKCR7cy50cmFuc2Zvcm1bMl19KWA7XG5mdW5jdGlvbiBWaWV3cG9ydCh7IGNoaWxkcmVuIH0pIHtcbiAgICBjb25zdCB0cmFuc2Zvcm0gPSB1c2VTdG9yZShzZWxlY3RvciQzKTtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIiwgeyBjbGFzc05hbWU6IFwicmVhY3QtZmxvd19fdmlld3BvcnQgcmVhY3QtZmxvd19fY29udGFpbmVyXCIsIHN0eWxlOiB7IHRyYW5zZm9ybSB9IH0sIGNoaWxkcmVuKSk7XG59XG5cbmZ1bmN0aW9uIHVzZU9uSW5pdEhhbmRsZXIob25Jbml0KSB7XG4gICAgY29uc3QgcmZJbnN0YW5jZSA9IHVzZVJlYWN0RmxvdygpO1xuICAgIGNvbnN0IGlzSW5pdGlhbGl6ZWQgPSB1c2VSZWYoZmFsc2UpO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmICghaXNJbml0aWFsaXplZC5jdXJyZW50ICYmIHJmSW5zdGFuY2Uudmlld3BvcnRJbml0aWFsaXplZCAmJiBvbkluaXQpIHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gb25Jbml0KHJmSW5zdGFuY2UpLCAxKTtcbiAgICAgICAgICAgIGlzSW5pdGlhbGl6ZWQuY3VycmVudCA9IHRydWU7XG4gICAgICAgIH1cbiAgICB9LCBbb25Jbml0LCByZkluc3RhbmNlLnZpZXdwb3J0SW5pdGlhbGl6ZWRdKTtcbn1cblxuY29uc3Qgb3Bwb3NpdGVQb3NpdGlvbiA9IHtcbiAgICBbUG9zaXRpb24uTGVmdF06IFBvc2l0aW9uLlJpZ2h0LFxuICAgIFtQb3NpdGlvbi5SaWdodF06IFBvc2l0aW9uLkxlZnQsXG4gICAgW1Bvc2l0aW9uLlRvcF06IFBvc2l0aW9uLkJvdHRvbSxcbiAgICBbUG9zaXRpb24uQm90dG9tXTogUG9zaXRpb24uVG9wLFxufTtcbmNvbnN0IENvbm5lY3Rpb25MaW5lID0gKHsgbm9kZUlkLCBoYW5kbGVUeXBlLCBzdHlsZSwgdHlwZSA9IENvbm5lY3Rpb25MaW5lVHlwZS5CZXppZXIsIEN1c3RvbUNvbXBvbmVudCwgY29ubmVjdGlvblN0YXR1cywgfSkgPT4ge1xuICAgIGNvbnN0IHsgZnJvbU5vZGUsIGhhbmRsZUlkLCB0b1gsIHRvWSwgY29ubmVjdGlvbk1vZGUgfSA9IHVzZVN0b3JlKHVzZUNhbGxiYWNrKChzKSA9PiAoe1xuICAgICAgICBmcm9tTm9kZTogcy5ub2RlSW50ZXJuYWxzLmdldChub2RlSWQpLFxuICAgICAgICBoYW5kbGVJZDogcy5jb25uZWN0aW9uSGFuZGxlSWQsXG4gICAgICAgIHRvWDogKHMuY29ubmVjdGlvblBvc2l0aW9uLnggLSBzLnRyYW5zZm9ybVswXSkgLyBzLnRyYW5zZm9ybVsyXSxcbiAgICAgICAgdG9ZOiAocy5jb25uZWN0aW9uUG9zaXRpb24ueSAtIHMudHJhbnNmb3JtWzFdKSAvIHMudHJhbnNmb3JtWzJdLFxuICAgICAgICBjb25uZWN0aW9uTW9kZTogcy5jb25uZWN0aW9uTW9kZSxcbiAgICB9KSwgW25vZGVJZF0pLCBzaGFsbG93KTtcbiAgICBjb25zdCBmcm9tSGFuZGxlQm91bmRzID0gZnJvbU5vZGU/LltpbnRlcm5hbHNTeW1ib2xdPy5oYW5kbGVCb3VuZHM7XG4gICAgbGV0IGhhbmRsZUJvdW5kcyA9IGZyb21IYW5kbGVCb3VuZHM/LltoYW5kbGVUeXBlXTtcbiAgICBpZiAoY29ubmVjdGlvbk1vZGUgPT09IENvbm5lY3Rpb25Nb2RlLkxvb3NlKSB7XG4gICAgICAgIGhhbmRsZUJvdW5kcyA9IGhhbmRsZUJvdW5kcyA/IGhhbmRsZUJvdW5kcyA6IGZyb21IYW5kbGVCb3VuZHM/LltoYW5kbGVUeXBlID09PSAnc291cmNlJyA/ICd0YXJnZXQnIDogJ3NvdXJjZSddO1xuICAgIH1cbiAgICBpZiAoIWZyb21Ob2RlIHx8ICFoYW5kbGVCb3VuZHMpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGNvbnN0IGZyb21IYW5kbGUgPSBoYW5kbGVJZCA/IGhhbmRsZUJvdW5kcy5maW5kKChkKSA9PiBkLmlkID09PSBoYW5kbGVJZCkgOiBoYW5kbGVCb3VuZHNbMF07XG4gICAgY29uc3QgZnJvbUhhbmRsZVggPSBmcm9tSGFuZGxlID8gZnJvbUhhbmRsZS54ICsgZnJvbUhhbmRsZS53aWR0aCAvIDIgOiAoZnJvbU5vZGUud2lkdGggPz8gMCkgLyAyO1xuICAgIGNvbnN0IGZyb21IYW5kbGVZID0gZnJvbUhhbmRsZSA/IGZyb21IYW5kbGUueSArIGZyb21IYW5kbGUuaGVpZ2h0IC8gMiA6IGZyb21Ob2RlLmhlaWdodCA/PyAwO1xuICAgIGNvbnN0IGZyb21YID0gKGZyb21Ob2RlLnBvc2l0aW9uQWJzb2x1dGU/LnggPz8gMCkgKyBmcm9tSGFuZGxlWDtcbiAgICBjb25zdCBmcm9tWSA9IChmcm9tTm9kZS5wb3NpdGlvbkFic29sdXRlPy55ID8/IDApICsgZnJvbUhhbmRsZVk7XG4gICAgY29uc3QgZnJvbVBvc2l0aW9uID0gZnJvbUhhbmRsZT8ucG9zaXRpb247XG4gICAgY29uc3QgdG9Qb3NpdGlvbiA9IGZyb21Qb3NpdGlvbiA/IG9wcG9zaXRlUG9zaXRpb25bZnJvbVBvc2l0aW9uXSA6IG51bGw7XG4gICAgaWYgKCFmcm9tUG9zaXRpb24gfHwgIXRvUG9zaXRpb24pIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIGlmIChDdXN0b21Db21wb25lbnQpIHtcbiAgICAgICAgcmV0dXJuIChSZWFjdC5jcmVhdGVFbGVtZW50KEN1c3RvbUNvbXBvbmVudCwgeyBjb25uZWN0aW9uTGluZVR5cGU6IHR5cGUsIGNvbm5lY3Rpb25MaW5lU3R5bGU6IHN0eWxlLCBmcm9tTm9kZTogZnJvbU5vZGUsIGZyb21IYW5kbGU6IGZyb21IYW5kbGUsIGZyb21YOiBmcm9tWCwgZnJvbVk6IGZyb21ZLCB0b1g6IHRvWCwgdG9ZOiB0b1ksIGZyb21Qb3NpdGlvbjogZnJvbVBvc2l0aW9uLCB0b1Bvc2l0aW9uOiB0b1Bvc2l0aW9uLCBjb25uZWN0aW9uU3RhdHVzOiBjb25uZWN0aW9uU3RhdHVzIH0pKTtcbiAgICB9XG4gICAgbGV0IGRBdHRyID0gJyc7XG4gICAgY29uc3QgcGF0aFBhcmFtcyA9IHtcbiAgICAgICAgc291cmNlWDogZnJvbVgsXG4gICAgICAgIHNvdXJjZVk6IGZyb21ZLFxuICAgICAgICBzb3VyY2VQb3NpdGlvbjogZnJvbVBvc2l0aW9uLFxuICAgICAgICB0YXJnZXRYOiB0b1gsXG4gICAgICAgIHRhcmdldFk6IHRvWSxcbiAgICAgICAgdGFyZ2V0UG9zaXRpb246IHRvUG9zaXRpb24sXG4gICAgfTtcbiAgICBpZiAodHlwZSA9PT0gQ29ubmVjdGlvbkxpbmVUeXBlLkJlemllcikge1xuICAgICAgICAvLyB3ZSBhc3N1bWUgdGhlIGRlc3RpbmF0aW9uIHBvc2l0aW9uIGlzIG9wcG9zaXRlIHRvIHRoZSBzb3VyY2UgcG9zaXRpb25cbiAgICAgICAgW2RBdHRyXSA9IGdldEJlemllclBhdGgocGF0aFBhcmFtcyk7XG4gICAgfVxuICAgIGVsc2UgaWYgKHR5cGUgPT09IENvbm5lY3Rpb25MaW5lVHlwZS5TdGVwKSB7XG4gICAgICAgIFtkQXR0cl0gPSBnZXRTbW9vdGhTdGVwUGF0aCh7XG4gICAgICAgICAgICAuLi5wYXRoUGFyYW1zLFxuICAgICAgICAgICAgYm9yZGVyUmFkaXVzOiAwLFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgZWxzZSBpZiAodHlwZSA9PT0gQ29ubmVjdGlvbkxpbmVUeXBlLlNtb290aFN0ZXApIHtcbiAgICAgICAgW2RBdHRyXSA9IGdldFNtb290aFN0ZXBQYXRoKHBhdGhQYXJhbXMpO1xuICAgIH1cbiAgICBlbHNlIGlmICh0eXBlID09PSBDb25uZWN0aW9uTGluZVR5cGUuU2ltcGxlQmV6aWVyKSB7XG4gICAgICAgIFtkQXR0cl0gPSBnZXRTaW1wbGVCZXppZXJQYXRoKHBhdGhQYXJhbXMpO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgICAgZEF0dHIgPSBgTSR7ZnJvbVh9LCR7ZnJvbVl9ICR7dG9YfSwke3RvWX1gO1xuICAgIH1cbiAgICByZXR1cm4gUmVhY3QuY3JlYXRlRWxlbWVudChcInBhdGhcIiwgeyBkOiBkQXR0ciwgZmlsbDogXCJub25lXCIsIGNsYXNzTmFtZTogXCJyZWFjdC1mbG93X19jb25uZWN0aW9uLXBhdGhcIiwgc3R5bGU6IHN0eWxlIH0pO1xufTtcbkNvbm5lY3Rpb25MaW5lLmRpc3BsYXlOYW1lID0gJ0Nvbm5lY3Rpb25MaW5lJztcbmNvbnN0IHNlbGVjdG9yJDIgPSAocykgPT4gKHtcbiAgICBub2RlSWQ6IHMuY29ubmVjdGlvbk5vZGVJZCxcbiAgICBoYW5kbGVUeXBlOiBzLmNvbm5lY3Rpb25IYW5kbGVUeXBlLFxuICAgIG5vZGVzQ29ubmVjdGFibGU6IHMubm9kZXNDb25uZWN0YWJsZSxcbiAgICBjb25uZWN0aW9uU3RhdHVzOiBzLmNvbm5lY3Rpb25TdGF0dXMsXG4gICAgd2lkdGg6IHMud2lkdGgsXG4gICAgaGVpZ2h0OiBzLmhlaWdodCxcbn0pO1xuZnVuY3Rpb24gQ29ubmVjdGlvbkxpbmVXcmFwcGVyKHsgY29udGFpbmVyU3R5bGUsIHN0eWxlLCB0eXBlLCBjb21wb25lbnQgfSkge1xuICAgIGNvbnN0IHsgbm9kZUlkLCBoYW5kbGVUeXBlLCBub2Rlc0Nvbm5lY3RhYmxlLCB3aWR0aCwgaGVpZ2h0LCBjb25uZWN0aW9uU3RhdHVzIH0gPSB1c2VTdG9yZShzZWxlY3RvciQyLCBzaGFsbG93KTtcbiAgICBjb25zdCBpc1ZhbGlkID0gISEobm9kZUlkICYmIGhhbmRsZVR5cGUgJiYgd2lkdGggJiYgbm9kZXNDb25uZWN0YWJsZSk7XG4gICAgaWYgKCFpc1ZhbGlkKSB7XG4gICAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJzdmdcIiwgeyBzdHlsZTogY29udGFpbmVyU3R5bGUsIHdpZHRoOiB3aWR0aCwgaGVpZ2h0OiBoZWlnaHQsIGNsYXNzTmFtZTogXCJyZWFjdC1mbG93X19lZGdlcyByZWFjdC1mbG93X19jb25uZWN0aW9ubGluZSByZWFjdC1mbG93X19jb250YWluZXJcIiB9LFxuICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZ1wiLCB7IGNsYXNzTmFtZTogY2MoWydyZWFjdC1mbG93X19jb25uZWN0aW9uJywgY29ubmVjdGlvblN0YXR1c10pIH0sXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KENvbm5lY3Rpb25MaW5lLCB7IG5vZGVJZDogbm9kZUlkLCBoYW5kbGVUeXBlOiBoYW5kbGVUeXBlLCBzdHlsZTogc3R5bGUsIHR5cGU6IHR5cGUsIEN1c3RvbUNvbXBvbmVudDogY29tcG9uZW50LCBjb25uZWN0aW9uU3RhdHVzOiBjb25uZWN0aW9uU3RhdHVzIH0pKSkpO1xufVxuXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueVxuZnVuY3Rpb24gdXNlTm9kZU9yRWRnZVR5cGVzKG5vZGVPckVkZ2VUeXBlcywgY3JlYXRlVHlwZXMpIHtcbiAgICBjb25zdCB0eXBlc0tleXNSZWYgPSB1c2VSZWYobnVsbCk7XG4gICAgY29uc3Qgc3RvcmUgPSB1c2VTdG9yZUFwaSgpO1xuICAgIGNvbnN0IHR5cGVzUGFyc2VkID0gdXNlTWVtbygoKSA9PiB7XG4gICAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ2RldmVsb3BtZW50Jykge1xuICAgICAgICAgICAgY29uc3QgdHlwZUtleXMgPSBPYmplY3Qua2V5cyhub2RlT3JFZGdlVHlwZXMpO1xuICAgICAgICAgICAgaWYgKHNoYWxsb3codHlwZXNLZXlzUmVmLmN1cnJlbnQsIHR5cGVLZXlzKSkge1xuICAgICAgICAgICAgICAgIHN0b3JlLmdldFN0YXRlKCkub25FcnJvcj8uKCcwMDInLCBlcnJvck1lc3NhZ2VzWydlcnJvcjAwMiddKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdHlwZXNLZXlzUmVmLmN1cnJlbnQgPSB0eXBlS2V5cztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY3JlYXRlVHlwZXMobm9kZU9yRWRnZVR5cGVzKTtcbiAgICB9LCBbbm9kZU9yRWRnZVR5cGVzXSk7XG4gICAgcmV0dXJuIHR5cGVzUGFyc2VkO1xufVxuXG5jb25zdCBHcmFwaFZpZXcgPSAoeyBub2RlVHlwZXMsIGVkZ2VUeXBlcywgb25Nb3ZlLCBvbk1vdmVTdGFydCwgb25Nb3ZlRW5kLCBvbkluaXQsIG9uTm9kZUNsaWNrLCBvbkVkZ2VDbGljaywgb25Ob2RlRG91YmxlQ2xpY2ssIG9uRWRnZURvdWJsZUNsaWNrLCBvbk5vZGVNb3VzZUVudGVyLCBvbk5vZGVNb3VzZU1vdmUsIG9uTm9kZU1vdXNlTGVhdmUsIG9uTm9kZUNvbnRleHRNZW51LCBvblNlbGVjdGlvbkNvbnRleHRNZW51LCBvblNlbGVjdGlvblN0YXJ0LCBvblNlbGVjdGlvbkVuZCwgY29ubmVjdGlvbkxpbmVUeXBlLCBjb25uZWN0aW9uTGluZVN0eWxlLCBjb25uZWN0aW9uTGluZUNvbXBvbmVudCwgY29ubmVjdGlvbkxpbmVDb250YWluZXJTdHlsZSwgc2VsZWN0aW9uS2V5Q29kZSwgc2VsZWN0aW9uT25EcmFnLCBzZWxlY3Rpb25Nb2RlLCBtdWx0aVNlbGVjdGlvbktleUNvZGUsIHBhbkFjdGl2YXRpb25LZXlDb2RlLCB6b29tQWN0aXZhdGlvbktleUNvZGUsIGRlbGV0ZUtleUNvZGUsIG9ubHlSZW5kZXJWaXNpYmxlRWxlbWVudHMsIGVsZW1lbnRzU2VsZWN0YWJsZSwgc2VsZWN0Tm9kZXNPbkRyYWcsIGRlZmF1bHRWaWV3cG9ydCwgdHJhbnNsYXRlRXh0ZW50LCBtaW5ab29tLCBtYXhab29tLCBwcmV2ZW50U2Nyb2xsaW5nLCBkZWZhdWx0TWFya2VyQ29sb3IsIHpvb21PblNjcm9sbCwgem9vbU9uUGluY2gsIHBhbk9uU2Nyb2xsLCBwYW5PblNjcm9sbFNwZWVkLCBwYW5PblNjcm9sbE1vZGUsIHpvb21PbkRvdWJsZUNsaWNrLCBwYW5PbkRyYWcsIG9uUGFuZUNsaWNrLCBvblBhbmVNb3VzZUVudGVyLCBvblBhbmVNb3VzZU1vdmUsIG9uUGFuZU1vdXNlTGVhdmUsIG9uUGFuZVNjcm9sbCwgb25QYW5lQ29udGV4dE1lbnUsIG9uRWRnZVVwZGF0ZSwgb25FZGdlQ29udGV4dE1lbnUsIG9uRWRnZU1vdXNlRW50ZXIsIG9uRWRnZU1vdXNlTW92ZSwgb25FZGdlTW91c2VMZWF2ZSwgZWRnZVVwZGF0ZXJSYWRpdXMsIG9uRWRnZVVwZGF0ZVN0YXJ0LCBvbkVkZ2VVcGRhdGVFbmQsIG5vRHJhZ0NsYXNzTmFtZSwgbm9XaGVlbENsYXNzTmFtZSwgbm9QYW5DbGFzc05hbWUsIGVsZXZhdGVFZGdlc09uU2VsZWN0LCBkaXNhYmxlS2V5Ym9hcmRBMTF5LCBub2RlT3JpZ2luLCBub2RlRXh0ZW50LCByZklkLCB9KSA9PiB7XG4gICAgY29uc3Qgbm9kZVR5cGVzV3JhcHBlZCA9IHVzZU5vZGVPckVkZ2VUeXBlcyhub2RlVHlwZXMsIGNyZWF0ZU5vZGVUeXBlcyk7XG4gICAgY29uc3QgZWRnZVR5cGVzV3JhcHBlZCA9IHVzZU5vZGVPckVkZ2VUeXBlcyhlZGdlVHlwZXMsIGNyZWF0ZUVkZ2VUeXBlcyk7XG4gICAgdXNlT25Jbml0SGFuZGxlcihvbkluaXQpO1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChGbG93UmVuZGVyZXIkMSwgeyBvblBhbmVDbGljazogb25QYW5lQ2xpY2ssIG9uUGFuZU1vdXNlRW50ZXI6IG9uUGFuZU1vdXNlRW50ZXIsIG9uUGFuZU1vdXNlTW92ZTogb25QYW5lTW91c2VNb3ZlLCBvblBhbmVNb3VzZUxlYXZlOiBvblBhbmVNb3VzZUxlYXZlLCBvblBhbmVDb250ZXh0TWVudTogb25QYW5lQ29udGV4dE1lbnUsIG9uUGFuZVNjcm9sbDogb25QYW5lU2Nyb2xsLCBkZWxldGVLZXlDb2RlOiBkZWxldGVLZXlDb2RlLCBzZWxlY3Rpb25LZXlDb2RlOiBzZWxlY3Rpb25LZXlDb2RlLCBzZWxlY3Rpb25PbkRyYWc6IHNlbGVjdGlvbk9uRHJhZywgc2VsZWN0aW9uTW9kZTogc2VsZWN0aW9uTW9kZSwgb25TZWxlY3Rpb25TdGFydDogb25TZWxlY3Rpb25TdGFydCwgb25TZWxlY3Rpb25FbmQ6IG9uU2VsZWN0aW9uRW5kLCBtdWx0aVNlbGVjdGlvbktleUNvZGU6IG11bHRpU2VsZWN0aW9uS2V5Q29kZSwgcGFuQWN0aXZhdGlvbktleUNvZGU6IHBhbkFjdGl2YXRpb25LZXlDb2RlLCB6b29tQWN0aXZhdGlvbktleUNvZGU6IHpvb21BY3RpdmF0aW9uS2V5Q29kZSwgZWxlbWVudHNTZWxlY3RhYmxlOiBlbGVtZW50c1NlbGVjdGFibGUsIG9uTW92ZTogb25Nb3ZlLCBvbk1vdmVTdGFydDogb25Nb3ZlU3RhcnQsIG9uTW92ZUVuZDogb25Nb3ZlRW5kLCB6b29tT25TY3JvbGw6IHpvb21PblNjcm9sbCwgem9vbU9uUGluY2g6IHpvb21PblBpbmNoLCB6b29tT25Eb3VibGVDbGljazogem9vbU9uRG91YmxlQ2xpY2ssIHBhbk9uU2Nyb2xsOiBwYW5PblNjcm9sbCwgcGFuT25TY3JvbGxTcGVlZDogcGFuT25TY3JvbGxTcGVlZCwgcGFuT25TY3JvbGxNb2RlOiBwYW5PblNjcm9sbE1vZGUsIHBhbk9uRHJhZzogcGFuT25EcmFnLCBkZWZhdWx0Vmlld3BvcnQ6IGRlZmF1bHRWaWV3cG9ydCwgdHJhbnNsYXRlRXh0ZW50OiB0cmFuc2xhdGVFeHRlbnQsIG1pblpvb206IG1pblpvb20sIG1heFpvb206IG1heFpvb20sIG9uU2VsZWN0aW9uQ29udGV4dE1lbnU6IG9uU2VsZWN0aW9uQ29udGV4dE1lbnUsIHByZXZlbnRTY3JvbGxpbmc6IHByZXZlbnRTY3JvbGxpbmcsIG5vRHJhZ0NsYXNzTmFtZTogbm9EcmFnQ2xhc3NOYW1lLCBub1doZWVsQ2xhc3NOYW1lOiBub1doZWVsQ2xhc3NOYW1lLCBub1BhbkNsYXNzTmFtZTogbm9QYW5DbGFzc05hbWUsIGRpc2FibGVLZXlib2FyZEExMXk6IGRpc2FibGVLZXlib2FyZEExMXkgfSxcbiAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChWaWV3cG9ydCwgbnVsbCxcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoRWRnZVJlbmRlcmVyJDEsIHsgZWRnZVR5cGVzOiBlZGdlVHlwZXNXcmFwcGVkLCBvbkVkZ2VDbGljazogb25FZGdlQ2xpY2ssIG9uRWRnZURvdWJsZUNsaWNrOiBvbkVkZ2VEb3VibGVDbGljaywgb25FZGdlVXBkYXRlOiBvbkVkZ2VVcGRhdGUsIG9ubHlSZW5kZXJWaXNpYmxlRWxlbWVudHM6IG9ubHlSZW5kZXJWaXNpYmxlRWxlbWVudHMsIG9uRWRnZUNvbnRleHRNZW51OiBvbkVkZ2VDb250ZXh0TWVudSwgb25FZGdlTW91c2VFbnRlcjogb25FZGdlTW91c2VFbnRlciwgb25FZGdlTW91c2VNb3ZlOiBvbkVkZ2VNb3VzZU1vdmUsIG9uRWRnZU1vdXNlTGVhdmU6IG9uRWRnZU1vdXNlTGVhdmUsIG9uRWRnZVVwZGF0ZVN0YXJ0OiBvbkVkZ2VVcGRhdGVTdGFydCwgb25FZGdlVXBkYXRlRW5kOiBvbkVkZ2VVcGRhdGVFbmQsIGVkZ2VVcGRhdGVyUmFkaXVzOiBlZGdlVXBkYXRlclJhZGl1cywgZGVmYXVsdE1hcmtlckNvbG9yOiBkZWZhdWx0TWFya2VyQ29sb3IsIG5vUGFuQ2xhc3NOYW1lOiBub1BhbkNsYXNzTmFtZSwgZWxldmF0ZUVkZ2VzT25TZWxlY3Q6ICEhZWxldmF0ZUVkZ2VzT25TZWxlY3QsIGRpc2FibGVLZXlib2FyZEExMXk6IGRpc2FibGVLZXlib2FyZEExMXksIHJmSWQ6IHJmSWQgfSxcbiAgICAgICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KENvbm5lY3Rpb25MaW5lV3JhcHBlciwgeyBzdHlsZTogY29ubmVjdGlvbkxpbmVTdHlsZSwgdHlwZTogY29ubmVjdGlvbkxpbmVUeXBlLCBjb21wb25lbnQ6IGNvbm5lY3Rpb25MaW5lQ29tcG9uZW50LCBjb250YWluZXJTdHlsZTogY29ubmVjdGlvbkxpbmVDb250YWluZXJTdHlsZSB9KSksXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFwiZGl2XCIsIHsgY2xhc3NOYW1lOiBcInJlYWN0LWZsb3dfX2VkZ2VsYWJlbC1yZW5kZXJlclwiIH0pLFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChOb2RlUmVuZGVyZXIkMSwgeyBub2RlVHlwZXM6IG5vZGVUeXBlc1dyYXBwZWQsIG9uTm9kZUNsaWNrOiBvbk5vZGVDbGljaywgb25Ob2RlRG91YmxlQ2xpY2s6IG9uTm9kZURvdWJsZUNsaWNrLCBvbk5vZGVNb3VzZUVudGVyOiBvbk5vZGVNb3VzZUVudGVyLCBvbk5vZGVNb3VzZU1vdmU6IG9uTm9kZU1vdXNlTW92ZSwgb25Ob2RlTW91c2VMZWF2ZTogb25Ob2RlTW91c2VMZWF2ZSwgb25Ob2RlQ29udGV4dE1lbnU6IG9uTm9kZUNvbnRleHRNZW51LCBzZWxlY3ROb2Rlc09uRHJhZzogc2VsZWN0Tm9kZXNPbkRyYWcsIG9ubHlSZW5kZXJWaXNpYmxlRWxlbWVudHM6IG9ubHlSZW5kZXJWaXNpYmxlRWxlbWVudHMsIG5vUGFuQ2xhc3NOYW1lOiBub1BhbkNsYXNzTmFtZSwgbm9EcmFnQ2xhc3NOYW1lOiBub0RyYWdDbGFzc05hbWUsIGRpc2FibGVLZXlib2FyZEExMXk6IGRpc2FibGVLZXlib2FyZEExMXksIG5vZGVPcmlnaW46IG5vZGVPcmlnaW4sIG5vZGVFeHRlbnQ6IG5vZGVFeHRlbnQsIHJmSWQ6IHJmSWQgfSkpKSk7XG59O1xuR3JhcGhWaWV3LmRpc3BsYXlOYW1lID0gJ0dyYXBoVmlldyc7XG52YXIgR3JhcGhWaWV3JDEgPSBtZW1vKEdyYXBoVmlldyk7XG5cbmNvbnN0IGluZmluaXRlRXh0ZW50ID0gW1xuICAgIFtOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFksIE51bWJlci5ORUdBVElWRV9JTkZJTklUWV0sXG4gICAgW051bWJlci5QT1NJVElWRV9JTkZJTklUWSwgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZXSxcbl07XG5jb25zdCBpbml0aWFsU3RhdGUgPSB7XG4gICAgcmZJZDogJzEnLFxuICAgIHdpZHRoOiAwLFxuICAgIGhlaWdodDogMCxcbiAgICB0cmFuc2Zvcm06IFswLCAwLCAxXSxcbiAgICBub2RlSW50ZXJuYWxzOiBuZXcgTWFwKCksXG4gICAgZWRnZXM6IFtdLFxuICAgIG9uTm9kZXNDaGFuZ2U6IG51bGwsXG4gICAgb25FZGdlc0NoYW5nZTogbnVsbCxcbiAgICBoYXNEZWZhdWx0Tm9kZXM6IGZhbHNlLFxuICAgIGhhc0RlZmF1bHRFZGdlczogZmFsc2UsXG4gICAgZDNab29tOiBudWxsLFxuICAgIGQzU2VsZWN0aW9uOiBudWxsLFxuICAgIGQzWm9vbUhhbmRsZXI6IHVuZGVmaW5lZCxcbiAgICBtaW5ab29tOiAwLjUsXG4gICAgbWF4Wm9vbTogMixcbiAgICB0cmFuc2xhdGVFeHRlbnQ6IGluZmluaXRlRXh0ZW50LFxuICAgIG5vZGVFeHRlbnQ6IGluZmluaXRlRXh0ZW50LFxuICAgIG5vZGVzU2VsZWN0aW9uQWN0aXZlOiBmYWxzZSxcbiAgICB1c2VyU2VsZWN0aW9uQWN0aXZlOiBmYWxzZSxcbiAgICB1c2VyU2VsZWN0aW9uUmVjdDogbnVsbCxcbiAgICBjb25uZWN0aW9uTm9kZUlkOiBudWxsLFxuICAgIGNvbm5lY3Rpb25IYW5kbGVJZDogbnVsbCxcbiAgICBjb25uZWN0aW9uSGFuZGxlVHlwZTogJ3NvdXJjZScsXG4gICAgY29ubmVjdGlvblBvc2l0aW9uOiB7IHg6IDAsIHk6IDAgfSxcbiAgICBjb25uZWN0aW9uU3RhdHVzOiBudWxsLFxuICAgIGNvbm5lY3Rpb25Nb2RlOiBDb25uZWN0aW9uTW9kZS5TdHJpY3QsXG4gICAgZG9tTm9kZTogbnVsbCxcbiAgICBwYW5lRHJhZ2dpbmc6IGZhbHNlLFxuICAgIG5vUGFuQ2xhc3NOYW1lOiAnbm9wYW4nLFxuICAgIG5vZGVPcmlnaW46IFswLCAwXSxcbiAgICBub2RlRHJhZ1RocmVzaG9sZDogMCxcbiAgICBzbmFwR3JpZDogWzE1LCAxNV0sXG4gICAgc25hcFRvR3JpZDogZmFsc2UsXG4gICAgbm9kZXNEcmFnZ2FibGU6IHRydWUsXG4gICAgbm9kZXNDb25uZWN0YWJsZTogdHJ1ZSxcbiAgICBub2Rlc0ZvY3VzYWJsZTogdHJ1ZSxcbiAgICBlZGdlc0ZvY3VzYWJsZTogdHJ1ZSxcbiAgICBlZGdlc1VwZGF0YWJsZTogdHJ1ZSxcbiAgICBlbGVtZW50c1NlbGVjdGFibGU6IHRydWUsXG4gICAgZWxldmF0ZU5vZGVzT25TZWxlY3Q6IHRydWUsXG4gICAgZml0Vmlld09uSW5pdDogZmFsc2UsXG4gICAgZml0Vmlld09uSW5pdERvbmU6IGZhbHNlLFxuICAgIGZpdFZpZXdPbkluaXRPcHRpb25zOiB1bmRlZmluZWQsXG4gICAgb25TZWxlY3Rpb25DaGFuZ2U6IFtdLFxuICAgIG11bHRpU2VsZWN0aW9uQWN0aXZlOiBmYWxzZSxcbiAgICBjb25uZWN0aW9uU3RhcnRIYW5kbGU6IG51bGwsXG4gICAgY29ubmVjdGlvbkVuZEhhbmRsZTogbnVsbCxcbiAgICBjb25uZWN0aW9uQ2xpY2tTdGFydEhhbmRsZTogbnVsbCxcbiAgICBjb25uZWN0T25DbGljazogdHJ1ZSxcbiAgICBhcmlhTGl2ZU1lc3NhZ2U6ICcnLFxuICAgIGF1dG9QYW5PbkNvbm5lY3Q6IHRydWUsXG4gICAgYXV0b1Bhbk9uTm9kZURyYWc6IHRydWUsXG4gICAgY29ubmVjdGlvblJhZGl1czogMjAsXG4gICAgb25FcnJvcjogZGV2V2FybixcbiAgICBpc1ZhbGlkQ29ubmVjdGlvbjogdW5kZWZpbmVkLFxufTtcblxuY29uc3QgY3JlYXRlUkZTdG9yZSA9ICgpID0+IGNyZWF0ZVdpdGhFcXVhbGl0eUZuKChzZXQsIGdldCkgPT4gKHtcbiAgICAuLi5pbml0aWFsU3RhdGUsXG4gICAgc2V0Tm9kZXM6IChub2RlcykgPT4ge1xuICAgICAgICBjb25zdCB7IG5vZGVJbnRlcm5hbHMsIG5vZGVPcmlnaW4sIGVsZXZhdGVOb2Rlc09uU2VsZWN0IH0gPSBnZXQoKTtcbiAgICAgICAgc2V0KHsgbm9kZUludGVybmFsczogY3JlYXRlTm9kZUludGVybmFscyhub2Rlcywgbm9kZUludGVybmFscywgbm9kZU9yaWdpbiwgZWxldmF0ZU5vZGVzT25TZWxlY3QpIH0pO1xuICAgIH0sXG4gICAgZ2V0Tm9kZXM6ICgpID0+IHtcbiAgICAgICAgcmV0dXJuIEFycmF5LmZyb20oZ2V0KCkubm9kZUludGVybmFscy52YWx1ZXMoKSk7XG4gICAgfSxcbiAgICBzZXRFZGdlczogKGVkZ2VzKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZGVmYXVsdEVkZ2VPcHRpb25zID0ge30gfSA9IGdldCgpO1xuICAgICAgICBzZXQoeyBlZGdlczogZWRnZXMubWFwKChlKSA9PiAoeyAuLi5kZWZhdWx0RWRnZU9wdGlvbnMsIC4uLmUgfSkpIH0pO1xuICAgIH0sXG4gICAgc2V0RGVmYXVsdE5vZGVzQW5kRWRnZXM6IChub2RlcywgZWRnZXMpID0+IHtcbiAgICAgICAgY29uc3QgaGFzRGVmYXVsdE5vZGVzID0gdHlwZW9mIG5vZGVzICE9PSAndW5kZWZpbmVkJztcbiAgICAgICAgY29uc3QgaGFzRGVmYXVsdEVkZ2VzID0gdHlwZW9mIGVkZ2VzICE9PSAndW5kZWZpbmVkJztcbiAgICAgICAgY29uc3Qgbm9kZUludGVybmFscyA9IGhhc0RlZmF1bHROb2Rlc1xuICAgICAgICAgICAgPyBjcmVhdGVOb2RlSW50ZXJuYWxzKG5vZGVzLCBuZXcgTWFwKCksIGdldCgpLm5vZGVPcmlnaW4sIGdldCgpLmVsZXZhdGVOb2Rlc09uU2VsZWN0KVxuICAgICAgICAgICAgOiBuZXcgTWFwKCk7XG4gICAgICAgIGNvbnN0IG5leHRFZGdlcyA9IGhhc0RlZmF1bHRFZGdlcyA/IGVkZ2VzIDogW107XG4gICAgICAgIHNldCh7IG5vZGVJbnRlcm5hbHMsIGVkZ2VzOiBuZXh0RWRnZXMsIGhhc0RlZmF1bHROb2RlcywgaGFzRGVmYXVsdEVkZ2VzIH0pO1xuICAgIH0sXG4gICAgdXBkYXRlTm9kZURpbWVuc2lvbnM6ICh1cGRhdGVzKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgb25Ob2Rlc0NoYW5nZSwgbm9kZUludGVybmFscywgZml0Vmlld09uSW5pdCwgZml0Vmlld09uSW5pdERvbmUsIGZpdFZpZXdPbkluaXRPcHRpb25zLCBkb21Ob2RlLCBub2RlT3JpZ2luLCB9ID0gZ2V0KCk7XG4gICAgICAgIGNvbnN0IHZpZXdwb3J0Tm9kZSA9IGRvbU5vZGU/LnF1ZXJ5U2VsZWN0b3IoJy5yZWFjdC1mbG93X192aWV3cG9ydCcpO1xuICAgICAgICBpZiAoIXZpZXdwb3J0Tm9kZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUodmlld3BvcnROb2RlKTtcbiAgICAgICAgY29uc3QgeyBtMjI6IHpvb20gfSA9IG5ldyB3aW5kb3cuRE9NTWF0cml4UmVhZE9ubHkoc3R5bGUudHJhbnNmb3JtKTtcbiAgICAgICAgY29uc3QgY2hhbmdlcyA9IHVwZGF0ZXMucmVkdWNlKChyZXMsIHVwZGF0ZSkgPT4ge1xuICAgICAgICAgICAgY29uc3Qgbm9kZSA9IG5vZGVJbnRlcm5hbHMuZ2V0KHVwZGF0ZS5pZCk7XG4gICAgICAgICAgICBpZiAobm9kZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGRpbWVuc2lvbnMgPSBnZXREaW1lbnNpb25zKHVwZGF0ZS5ub2RlRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgY29uc3QgZG9VcGRhdGUgPSAhIShkaW1lbnNpb25zLndpZHRoICYmXG4gICAgICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMuaGVpZ2h0ICYmXG4gICAgICAgICAgICAgICAgICAgIChub2RlLndpZHRoICE9PSBkaW1lbnNpb25zLndpZHRoIHx8IG5vZGUuaGVpZ2h0ICE9PSBkaW1lbnNpb25zLmhlaWdodCB8fCB1cGRhdGUuZm9yY2VVcGRhdGUpKTtcbiAgICAgICAgICAgICAgICBpZiAoZG9VcGRhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZUludGVybmFscy5zZXQobm9kZS5pZCwge1xuICAgICAgICAgICAgICAgICAgICAgICAgLi4ubm9kZSxcbiAgICAgICAgICAgICAgICAgICAgICAgIFtpbnRlcm5hbHNTeW1ib2xdOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4ubm9kZVtpbnRlcm5hbHNTeW1ib2xdLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhhbmRsZUJvdW5kczoge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2U6IGdldEhhbmRsZUJvdW5kcygnLnNvdXJjZScsIHVwZGF0ZS5ub2RlRWxlbWVudCwgem9vbSwgbm9kZU9yaWdpbiksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldDogZ2V0SGFuZGxlQm91bmRzKCcudGFyZ2V0JywgdXBkYXRlLm5vZGVFbGVtZW50LCB6b29tLCBub2RlT3JpZ2luKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIC4uLmRpbWVuc2lvbnMsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICByZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZDogbm9kZS5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdkaW1lbnNpb25zJyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGRpbWVuc2lvbnMsXG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH0sIFtdKTtcbiAgICAgICAgdXBkYXRlQWJzb2x1dGVOb2RlUG9zaXRpb25zKG5vZGVJbnRlcm5hbHMsIG5vZGVPcmlnaW4pO1xuICAgICAgICBjb25zdCBuZXh0Rml0Vmlld09uSW5pdERvbmUgPSBmaXRWaWV3T25Jbml0RG9uZSB8fFxuICAgICAgICAgICAgKGZpdFZpZXdPbkluaXQgJiYgIWZpdFZpZXdPbkluaXREb25lICYmIGZpdFZpZXcoZ2V0LCB7IGluaXRpYWw6IHRydWUsIC4uLmZpdFZpZXdPbkluaXRPcHRpb25zIH0pKTtcbiAgICAgICAgc2V0KHsgbm9kZUludGVybmFsczogbmV3IE1hcChub2RlSW50ZXJuYWxzKSwgZml0Vmlld09uSW5pdERvbmU6IG5leHRGaXRWaWV3T25Jbml0RG9uZSB9KTtcbiAgICAgICAgaWYgKGNoYW5nZXM/Lmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIG9uTm9kZXNDaGFuZ2U/LihjaGFuZ2VzKTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgdXBkYXRlTm9kZVBvc2l0aW9uczogKG5vZGVEcmFnSXRlbXMsIHBvc2l0aW9uQ2hhbmdlZCA9IHRydWUsIGRyYWdnaW5nID0gZmFsc2UpID0+IHtcbiAgICAgICAgY29uc3QgeyB0cmlnZ2VyTm9kZUNoYW5nZXMgfSA9IGdldCgpO1xuICAgICAgICBjb25zdCBjaGFuZ2VzID0gbm9kZURyYWdJdGVtcy5tYXAoKG5vZGUpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNoYW5nZSA9IHtcbiAgICAgICAgICAgICAgICBpZDogbm9kZS5pZCxcbiAgICAgICAgICAgICAgICB0eXBlOiAncG9zaXRpb24nLFxuICAgICAgICAgICAgICAgIGRyYWdnaW5nLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbkNoYW5nZWQpIHtcbiAgICAgICAgICAgICAgICBjaGFuZ2UucG9zaXRpb25BYnNvbHV0ZSA9IG5vZGUucG9zaXRpb25BYnNvbHV0ZTtcbiAgICAgICAgICAgICAgICBjaGFuZ2UucG9zaXRpb24gPSBub2RlLnBvc2l0aW9uO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGNoYW5nZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRyaWdnZXJOb2RlQ2hhbmdlcyhjaGFuZ2VzKTtcbiAgICB9LFxuICAgIHRyaWdnZXJOb2RlQ2hhbmdlczogKGNoYW5nZXMpID0+IHtcbiAgICAgICAgY29uc3QgeyBvbk5vZGVzQ2hhbmdlLCBub2RlSW50ZXJuYWxzLCBoYXNEZWZhdWx0Tm9kZXMsIG5vZGVPcmlnaW4sIGdldE5vZGVzLCBlbGV2YXRlTm9kZXNPblNlbGVjdCB9ID0gZ2V0KCk7XG4gICAgICAgIGlmIChjaGFuZ2VzPy5sZW5ndGgpIHtcbiAgICAgICAgICAgIGlmIChoYXNEZWZhdWx0Tm9kZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBub2RlcyA9IGFwcGx5Tm9kZUNoYW5nZXMoY2hhbmdlcywgZ2V0Tm9kZXMoKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dE5vZGVJbnRlcm5hbHMgPSBjcmVhdGVOb2RlSW50ZXJuYWxzKG5vZGVzLCBub2RlSW50ZXJuYWxzLCBub2RlT3JpZ2luLCBlbGV2YXRlTm9kZXNPblNlbGVjdCk7XG4gICAgICAgICAgICAgICAgc2V0KHsgbm9kZUludGVybmFsczogbmV4dE5vZGVJbnRlcm5hbHMgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvbk5vZGVzQ2hhbmdlPy4oY2hhbmdlcyk7XG4gICAgICAgIH1cbiAgICB9LFxuICAgIGFkZFNlbGVjdGVkTm9kZXM6IChzZWxlY3RlZE5vZGVJZHMpID0+IHtcbiAgICAgICAgY29uc3QgeyBtdWx0aVNlbGVjdGlvbkFjdGl2ZSwgZWRnZXMsIGdldE5vZGVzIH0gPSBnZXQoKTtcbiAgICAgICAgbGV0IGNoYW5nZWROb2RlcztcbiAgICAgICAgbGV0IGNoYW5nZWRFZGdlcyA9IG51bGw7XG4gICAgICAgIGlmIChtdWx0aVNlbGVjdGlvbkFjdGl2ZSkge1xuICAgICAgICAgICAgY2hhbmdlZE5vZGVzID0gc2VsZWN0ZWROb2RlSWRzLm1hcCgobm9kZUlkKSA9PiBjcmVhdGVTZWxlY3Rpb25DaGFuZ2Uobm9kZUlkLCB0cnVlKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjaGFuZ2VkTm9kZXMgPSBnZXRTZWxlY3Rpb25DaGFuZ2VzKGdldE5vZGVzKCksIHNlbGVjdGVkTm9kZUlkcyk7XG4gICAgICAgICAgICBjaGFuZ2VkRWRnZXMgPSBnZXRTZWxlY3Rpb25DaGFuZ2VzKGVkZ2VzLCBbXSk7XG4gICAgICAgIH1cbiAgICAgICAgdXBkYXRlTm9kZXNBbmRFZGdlc1NlbGVjdGlvbnMoe1xuICAgICAgICAgICAgY2hhbmdlZE5vZGVzLFxuICAgICAgICAgICAgY2hhbmdlZEVkZ2VzLFxuICAgICAgICAgICAgZ2V0LFxuICAgICAgICAgICAgc2V0LFxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIGFkZFNlbGVjdGVkRWRnZXM6IChzZWxlY3RlZEVkZ2VJZHMpID0+IHtcbiAgICAgICAgY29uc3QgeyBtdWx0aVNlbGVjdGlvbkFjdGl2ZSwgZWRnZXMsIGdldE5vZGVzIH0gPSBnZXQoKTtcbiAgICAgICAgbGV0IGNoYW5nZWRFZGdlcztcbiAgICAgICAgbGV0IGNoYW5nZWROb2RlcyA9IG51bGw7XG4gICAgICAgIGlmIChtdWx0aVNlbGVjdGlvbkFjdGl2ZSkge1xuICAgICAgICAgICAgY2hhbmdlZEVkZ2VzID0gc2VsZWN0ZWRFZGdlSWRzLm1hcCgoZWRnZUlkKSA9PiBjcmVhdGVTZWxlY3Rpb25DaGFuZ2UoZWRnZUlkLCB0cnVlKSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjaGFuZ2VkRWRnZXMgPSBnZXRTZWxlY3Rpb25DaGFuZ2VzKGVkZ2VzLCBzZWxlY3RlZEVkZ2VJZHMpO1xuICAgICAgICAgICAgY2hhbmdlZE5vZGVzID0gZ2V0U2VsZWN0aW9uQ2hhbmdlcyhnZXROb2RlcygpLCBbXSk7XG4gICAgICAgIH1cbiAgICAgICAgdXBkYXRlTm9kZXNBbmRFZGdlc1NlbGVjdGlvbnMoe1xuICAgICAgICAgICAgY2hhbmdlZE5vZGVzLFxuICAgICAgICAgICAgY2hhbmdlZEVkZ2VzLFxuICAgICAgICAgICAgZ2V0LFxuICAgICAgICAgICAgc2V0LFxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHVuc2VsZWN0Tm9kZXNBbmRFZGdlczogKHsgbm9kZXMsIGVkZ2VzIH0gPSB7fSkgPT4ge1xuICAgICAgICBjb25zdCB7IGVkZ2VzOiBzdG9yZUVkZ2VzLCBnZXROb2RlcyB9ID0gZ2V0KCk7XG4gICAgICAgIGNvbnN0IG5vZGVzVG9VbnNlbGVjdCA9IG5vZGVzID8gbm9kZXMgOiBnZXROb2RlcygpO1xuICAgICAgICBjb25zdCBlZGdlc1RvVW5zZWxlY3QgPSBlZGdlcyA/IGVkZ2VzIDogc3RvcmVFZGdlcztcbiAgICAgICAgY29uc3QgY2hhbmdlZE5vZGVzID0gbm9kZXNUb1Vuc2VsZWN0Lm1hcCgobikgPT4ge1xuICAgICAgICAgICAgbi5zZWxlY3RlZCA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIGNyZWF0ZVNlbGVjdGlvbkNoYW5nZShuLmlkLCBmYWxzZSk7XG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCBjaGFuZ2VkRWRnZXMgPSBlZGdlc1RvVW5zZWxlY3QubWFwKChlZGdlKSA9PiBjcmVhdGVTZWxlY3Rpb25DaGFuZ2UoZWRnZS5pZCwgZmFsc2UpKTtcbiAgICAgICAgdXBkYXRlTm9kZXNBbmRFZGdlc1NlbGVjdGlvbnMoe1xuICAgICAgICAgICAgY2hhbmdlZE5vZGVzLFxuICAgICAgICAgICAgY2hhbmdlZEVkZ2VzLFxuICAgICAgICAgICAgZ2V0LFxuICAgICAgICAgICAgc2V0LFxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHNldE1pblpvb206IChtaW5ab29tKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZDNab29tLCBtYXhab29tIH0gPSBnZXQoKTtcbiAgICAgICAgZDNab29tPy5zY2FsZUV4dGVudChbbWluWm9vbSwgbWF4Wm9vbV0pO1xuICAgICAgICBzZXQoeyBtaW5ab29tIH0pO1xuICAgIH0sXG4gICAgc2V0TWF4Wm9vbTogKG1heFpvb20pID0+IHtcbiAgICAgICAgY29uc3QgeyBkM1pvb20sIG1pblpvb20gfSA9IGdldCgpO1xuICAgICAgICBkM1pvb20/LnNjYWxlRXh0ZW50KFttaW5ab29tLCBtYXhab29tXSk7XG4gICAgICAgIHNldCh7IG1heFpvb20gfSk7XG4gICAgfSxcbiAgICBzZXRUcmFuc2xhdGVFeHRlbnQ6ICh0cmFuc2xhdGVFeHRlbnQpID0+IHtcbiAgICAgICAgZ2V0KCkuZDNab29tPy50cmFuc2xhdGVFeHRlbnQodHJhbnNsYXRlRXh0ZW50KTtcbiAgICAgICAgc2V0KHsgdHJhbnNsYXRlRXh0ZW50IH0pO1xuICAgIH0sXG4gICAgcmVzZXRTZWxlY3RlZEVsZW1lbnRzOiAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgZWRnZXMsIGdldE5vZGVzIH0gPSBnZXQoKTtcbiAgICAgICAgY29uc3Qgbm9kZXMgPSBnZXROb2RlcygpO1xuICAgICAgICBjb25zdCBub2Rlc1RvVW5zZWxlY3QgPSBub2Rlc1xuICAgICAgICAgICAgLmZpbHRlcigoZSkgPT4gZS5zZWxlY3RlZClcbiAgICAgICAgICAgIC5tYXAoKG4pID0+IGNyZWF0ZVNlbGVjdGlvbkNoYW5nZShuLmlkLCBmYWxzZSkpO1xuICAgICAgICBjb25zdCBlZGdlc1RvVW5zZWxlY3QgPSBlZGdlc1xuICAgICAgICAgICAgLmZpbHRlcigoZSkgPT4gZS5zZWxlY3RlZClcbiAgICAgICAgICAgIC5tYXAoKGUpID0+IGNyZWF0ZVNlbGVjdGlvbkNoYW5nZShlLmlkLCBmYWxzZSkpO1xuICAgICAgICB1cGRhdGVOb2Rlc0FuZEVkZ2VzU2VsZWN0aW9ucyh7XG4gICAgICAgICAgICBjaGFuZ2VkTm9kZXM6IG5vZGVzVG9VbnNlbGVjdCxcbiAgICAgICAgICAgIGNoYW5nZWRFZGdlczogZWRnZXNUb1Vuc2VsZWN0LFxuICAgICAgICAgICAgZ2V0LFxuICAgICAgICAgICAgc2V0LFxuICAgICAgICB9KTtcbiAgICB9LFxuICAgIHNldE5vZGVFeHRlbnQ6IChub2RlRXh0ZW50KSA9PiB7XG4gICAgICAgIGNvbnN0IHsgbm9kZUludGVybmFscyB9ID0gZ2V0KCk7XG4gICAgICAgIG5vZGVJbnRlcm5hbHMuZm9yRWFjaCgobm9kZSkgPT4ge1xuICAgICAgICAgICAgbm9kZS5wb3NpdGlvbkFic29sdXRlID0gY2xhbXBQb3NpdGlvbihub2RlLnBvc2l0aW9uLCBub2RlRXh0ZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHNldCh7XG4gICAgICAgICAgICBub2RlRXh0ZW50LFxuICAgICAgICAgICAgbm9kZUludGVybmFsczogbmV3IE1hcChub2RlSW50ZXJuYWxzKSxcbiAgICAgICAgfSk7XG4gICAgfSxcbiAgICBwYW5CeTogKGRlbHRhKSA9PiB7XG4gICAgICAgIGNvbnN0IHsgdHJhbnNmb3JtLCB3aWR0aCwgaGVpZ2h0LCBkM1pvb20sIGQzU2VsZWN0aW9uLCB0cmFuc2xhdGVFeHRlbnQgfSA9IGdldCgpO1xuICAgICAgICBpZiAoIWQzWm9vbSB8fCAhZDNTZWxlY3Rpb24gfHwgKCFkZWx0YS54ICYmICFkZWx0YS55KSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IG5leHRUcmFuc2Zvcm0gPSB6b29tSWRlbnRpdHlcbiAgICAgICAgICAgIC50cmFuc2xhdGUodHJhbnNmb3JtWzBdICsgZGVsdGEueCwgdHJhbnNmb3JtWzFdICsgZGVsdGEueSlcbiAgICAgICAgICAgIC5zY2FsZSh0cmFuc2Zvcm1bMl0pO1xuICAgICAgICBjb25zdCBleHRlbnQgPSBbXG4gICAgICAgICAgICBbMCwgMF0sXG4gICAgICAgICAgICBbd2lkdGgsIGhlaWdodF0sXG4gICAgICAgIF07XG4gICAgICAgIGNvbnN0IGNvbnN0cmFpbmVkVHJhbnNmb3JtID0gZDNab29tPy5jb25zdHJhaW4oKShuZXh0VHJhbnNmb3JtLCBleHRlbnQsIHRyYW5zbGF0ZUV4dGVudCk7XG4gICAgICAgIGQzWm9vbS50cmFuc2Zvcm0oZDNTZWxlY3Rpb24sIGNvbnN0cmFpbmVkVHJhbnNmb3JtKTtcbiAgICAgICAgY29uc3QgdHJhbnNmb3JtQ2hhbmdlZCA9IHRyYW5zZm9ybVswXSAhPT0gY29uc3RyYWluZWRUcmFuc2Zvcm0ueCB8fFxuICAgICAgICAgICAgdHJhbnNmb3JtWzFdICE9PSBjb25zdHJhaW5lZFRyYW5zZm9ybS55IHx8XG4gICAgICAgICAgICB0cmFuc2Zvcm1bMl0gIT09IGNvbnN0cmFpbmVkVHJhbnNmb3JtLms7XG4gICAgICAgIHJldHVybiB0cmFuc2Zvcm1DaGFuZ2VkO1xuICAgIH0sXG4gICAgY2FuY2VsQ29ubmVjdGlvbjogKCkgPT4gc2V0KHtcbiAgICAgICAgY29ubmVjdGlvbk5vZGVJZDogaW5pdGlhbFN0YXRlLmNvbm5lY3Rpb25Ob2RlSWQsXG4gICAgICAgIGNvbm5lY3Rpb25IYW5kbGVJZDogaW5pdGlhbFN0YXRlLmNvbm5lY3Rpb25IYW5kbGVJZCxcbiAgICAgICAgY29ubmVjdGlvbkhhbmRsZVR5cGU6IGluaXRpYWxTdGF0ZS5jb25uZWN0aW9uSGFuZGxlVHlwZSxcbiAgICAgICAgY29ubmVjdGlvblN0YXR1czogaW5pdGlhbFN0YXRlLmNvbm5lY3Rpb25TdGF0dXMsXG4gICAgICAgIGNvbm5lY3Rpb25TdGFydEhhbmRsZTogaW5pdGlhbFN0YXRlLmNvbm5lY3Rpb25TdGFydEhhbmRsZSxcbiAgICAgICAgY29ubmVjdGlvbkVuZEhhbmRsZTogaW5pdGlhbFN0YXRlLmNvbm5lY3Rpb25FbmRIYW5kbGUsXG4gICAgfSksXG4gICAgcmVzZXQ6ICgpID0+IHNldCh7IC4uLmluaXRpYWxTdGF0ZSB9KSxcbn0pLCBPYmplY3QuaXMpO1xuXG5jb25zdCBSZWFjdEZsb3dQcm92aWRlciA9ICh7IGNoaWxkcmVuIH0pID0+IHtcbiAgICBjb25zdCBzdG9yZVJlZiA9IHVzZVJlZihudWxsKTtcbiAgICBpZiAoIXN0b3JlUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgc3RvcmVSZWYuY3VycmVudCA9IGNyZWF0ZVJGU3RvcmUoKTtcbiAgICB9XG4gICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoUHJvdmlkZXIkMSwgeyB2YWx1ZTogc3RvcmVSZWYuY3VycmVudCB9LCBjaGlsZHJlbik7XG59O1xuUmVhY3RGbG93UHJvdmlkZXIuZGlzcGxheU5hbWUgPSAnUmVhY3RGbG93UHJvdmlkZXInO1xuXG5jb25zdCBXcmFwcGVyID0gKHsgY2hpbGRyZW4gfSkgPT4ge1xuICAgIGNvbnN0IGlzV3JhcHBlZCA9IHVzZUNvbnRleHQoU3RvcmVDb250ZXh0KTtcbiAgICBpZiAoaXNXcmFwcGVkKSB7XG4gICAgICAgIC8vIHdlIG5lZWQgdG8gd3JhcCBpdCB3aXRoIGEgZnJhZ21lbnQgYmVjYXVzZSBpdCdzIG5vdCBhbGxvd2VkIGZvciBjaGlsZHJlbiB0byBiZSBhIFJlYWN0Tm9kZVxuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vRGVmaW5pdGVseVR5cGVkL0RlZmluaXRlbHlUeXBlZC9pc3N1ZXMvMTgwNTFcbiAgICAgICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoUmVhY3QuRnJhZ21lbnQsIG51bGwsIGNoaWxkcmVuKTtcbiAgICB9XG4gICAgcmV0dXJuIFJlYWN0LmNyZWF0ZUVsZW1lbnQoUmVhY3RGbG93UHJvdmlkZXIsIG51bGwsIGNoaWxkcmVuKTtcbn07XG5XcmFwcGVyLmRpc3BsYXlOYW1lID0gJ1JlYWN0Rmxvd1dyYXBwZXInO1xuXG5jb25zdCBkZWZhdWx0Tm9kZVR5cGVzID0ge1xuICAgIGlucHV0OiBJbnB1dE5vZGUkMSxcbiAgICBkZWZhdWx0OiBEZWZhdWx0Tm9kZSQxLFxuICAgIG91dHB1dDogT3V0cHV0Tm9kZSQxLFxuICAgIGdyb3VwOiBHcm91cE5vZGUsXG59O1xuY29uc3QgZGVmYXVsdEVkZ2VUeXBlcyA9IHtcbiAgICBkZWZhdWx0OiBCZXppZXJFZGdlLFxuICAgIHN0cmFpZ2h0OiBTdHJhaWdodEVkZ2UsXG4gICAgc3RlcDogU3RlcEVkZ2UsXG4gICAgc21vb3Roc3RlcDogU21vb3RoU3RlcEVkZ2UsXG4gICAgc2ltcGxlYmV6aWVyOiBTaW1wbGVCZXppZXJFZGdlLFxufTtcbmNvbnN0IGluaXROb2RlT3JpZ2luID0gWzAsIDBdO1xuY29uc3QgaW5pdFNuYXBHcmlkID0gWzE1LCAxNV07XG5jb25zdCBpbml0RGVmYXVsdFZpZXdwb3J0ID0geyB4OiAwLCB5OiAwLCB6b29tOiAxIH07XG5jb25zdCB3cmFwcGVyU3R5bGUgPSB7XG4gICAgd2lkdGg6ICcxMDAlJyxcbiAgICBoZWlnaHQ6ICcxMDAlJyxcbiAgICBvdmVyZmxvdzogJ2hpZGRlbicsXG4gICAgcG9zaXRpb246ICdyZWxhdGl2ZScsXG4gICAgekluZGV4OiAwLFxufTtcbmNvbnN0IFJlYWN0RmxvdyA9IGZvcndhcmRSZWYoKHsgbm9kZXMsIGVkZ2VzLCBkZWZhdWx0Tm9kZXMsIGRlZmF1bHRFZGdlcywgY2xhc3NOYW1lLCBub2RlVHlwZXMgPSBkZWZhdWx0Tm9kZVR5cGVzLCBlZGdlVHlwZXMgPSBkZWZhdWx0RWRnZVR5cGVzLCBvbk5vZGVDbGljaywgb25FZGdlQ2xpY2ssIG9uSW5pdCwgb25Nb3ZlLCBvbk1vdmVTdGFydCwgb25Nb3ZlRW5kLCBvbkNvbm5lY3QsIG9uQ29ubmVjdFN0YXJ0LCBvbkNvbm5lY3RFbmQsIG9uQ2xpY2tDb25uZWN0U3RhcnQsIG9uQ2xpY2tDb25uZWN0RW5kLCBvbk5vZGVNb3VzZUVudGVyLCBvbk5vZGVNb3VzZU1vdmUsIG9uTm9kZU1vdXNlTGVhdmUsIG9uTm9kZUNvbnRleHRNZW51LCBvbk5vZGVEb3VibGVDbGljaywgb25Ob2RlRHJhZ1N0YXJ0LCBvbk5vZGVEcmFnLCBvbk5vZGVEcmFnU3RvcCwgb25Ob2Rlc0RlbGV0ZSwgb25FZGdlc0RlbGV0ZSwgb25TZWxlY3Rpb25DaGFuZ2UsIG9uU2VsZWN0aW9uRHJhZ1N0YXJ0LCBvblNlbGVjdGlvbkRyYWcsIG9uU2VsZWN0aW9uRHJhZ1N0b3AsIG9uU2VsZWN0aW9uQ29udGV4dE1lbnUsIG9uU2VsZWN0aW9uU3RhcnQsIG9uU2VsZWN0aW9uRW5kLCBjb25uZWN0aW9uTW9kZSA9IENvbm5lY3Rpb25Nb2RlLlN0cmljdCwgY29ubmVjdGlvbkxpbmVUeXBlID0gQ29ubmVjdGlvbkxpbmVUeXBlLkJlemllciwgY29ubmVjdGlvbkxpbmVTdHlsZSwgY29ubmVjdGlvbkxpbmVDb21wb25lbnQsIGNvbm5lY3Rpb25MaW5lQ29udGFpbmVyU3R5bGUsIGRlbGV0ZUtleUNvZGUgPSAnQmFja3NwYWNlJywgc2VsZWN0aW9uS2V5Q29kZSA9ICdTaGlmdCcsIHNlbGVjdGlvbk9uRHJhZyA9IGZhbHNlLCBzZWxlY3Rpb25Nb2RlID0gU2VsZWN0aW9uTW9kZS5GdWxsLCBwYW5BY3RpdmF0aW9uS2V5Q29kZSA9ICdTcGFjZScsIG11bHRpU2VsZWN0aW9uS2V5Q29kZSA9IGlzTWFjT3MoKSA/ICdNZXRhJyA6ICdDb250cm9sJywgem9vbUFjdGl2YXRpb25LZXlDb2RlID0gaXNNYWNPcygpID8gJ01ldGEnIDogJ0NvbnRyb2wnLCBzbmFwVG9HcmlkID0gZmFsc2UsIHNuYXBHcmlkID0gaW5pdFNuYXBHcmlkLCBvbmx5UmVuZGVyVmlzaWJsZUVsZW1lbnRzID0gZmFsc2UsIHNlbGVjdE5vZGVzT25EcmFnID0gdHJ1ZSwgbm9kZXNEcmFnZ2FibGUsIG5vZGVzQ29ubmVjdGFibGUsIG5vZGVzRm9jdXNhYmxlLCBub2RlT3JpZ2luID0gaW5pdE5vZGVPcmlnaW4sIGVkZ2VzRm9jdXNhYmxlLCBlZGdlc1VwZGF0YWJsZSwgZWxlbWVudHNTZWxlY3RhYmxlLCBkZWZhdWx0Vmlld3BvcnQgPSBpbml0RGVmYXVsdFZpZXdwb3J0LCBtaW5ab29tID0gMC41LCBtYXhab29tID0gMiwgdHJhbnNsYXRlRXh0ZW50ID0gaW5maW5pdGVFeHRlbnQsIHByZXZlbnRTY3JvbGxpbmcgPSB0cnVlLCBub2RlRXh0ZW50LCBkZWZhdWx0TWFya2VyQ29sb3IgPSAnI2IxYjFiNycsIHpvb21PblNjcm9sbCA9IHRydWUsIHpvb21PblBpbmNoID0gdHJ1ZSwgcGFuT25TY3JvbGwgPSBmYWxzZSwgcGFuT25TY3JvbGxTcGVlZCA9IDAuNSwgcGFuT25TY3JvbGxNb2RlID0gUGFuT25TY3JvbGxNb2RlLkZyZWUsIHpvb21PbkRvdWJsZUNsaWNrID0gdHJ1ZSwgcGFuT25EcmFnID0gdHJ1ZSwgb25QYW5lQ2xpY2ssIG9uUGFuZU1vdXNlRW50ZXIsIG9uUGFuZU1vdXNlTW92ZSwgb25QYW5lTW91c2VMZWF2ZSwgb25QYW5lU2Nyb2xsLCBvblBhbmVDb250ZXh0TWVudSwgY2hpbGRyZW4sIG9uRWRnZVVwZGF0ZSwgb25FZGdlQ29udGV4dE1lbnUsIG9uRWRnZURvdWJsZUNsaWNrLCBvbkVkZ2VNb3VzZUVudGVyLCBvbkVkZ2VNb3VzZU1vdmUsIG9uRWRnZU1vdXNlTGVhdmUsIG9uRWRnZVVwZGF0ZVN0YXJ0LCBvbkVkZ2VVcGRhdGVFbmQsIGVkZ2VVcGRhdGVyUmFkaXVzID0gMTAsIG9uTm9kZXNDaGFuZ2UsIG9uRWRnZXNDaGFuZ2UsIG5vRHJhZ0NsYXNzTmFtZSA9ICdub2RyYWcnLCBub1doZWVsQ2xhc3NOYW1lID0gJ25vd2hlZWwnLCBub1BhbkNsYXNzTmFtZSA9ICdub3BhbicsIGZpdFZpZXcgPSBmYWxzZSwgZml0Vmlld09wdGlvbnMsIGNvbm5lY3RPbkNsaWNrID0gdHJ1ZSwgYXR0cmlidXRpb25Qb3NpdGlvbiwgcHJvT3B0aW9ucywgZGVmYXVsdEVkZ2VPcHRpb25zLCBlbGV2YXRlTm9kZXNPblNlbGVjdCA9IHRydWUsIGVsZXZhdGVFZGdlc09uU2VsZWN0ID0gZmFsc2UsIGRpc2FibGVLZXlib2FyZEExMXkgPSBmYWxzZSwgYXV0b1Bhbk9uQ29ubmVjdCA9IHRydWUsIGF1dG9QYW5Pbk5vZGVEcmFnID0gdHJ1ZSwgY29ubmVjdGlvblJhZGl1cyA9IDIwLCBpc1ZhbGlkQ29ubmVjdGlvbiwgb25FcnJvciwgc3R5bGUsIGlkLCBub2RlRHJhZ1RocmVzaG9sZCwgLi4ucmVzdCB9LCByZWYpID0+IHtcbiAgICBjb25zdCByZklkID0gaWQgfHwgJzEnO1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChcImRpdlwiLCB7IC4uLnJlc3QsIHN0eWxlOiB7IC4uLnN0eWxlLCAuLi53cmFwcGVyU3R5bGUgfSwgcmVmOiByZWYsIGNsYXNzTmFtZTogY2MoWydyZWFjdC1mbG93JywgY2xhc3NOYW1lXSksIFwiZGF0YS10ZXN0aWRcIjogXCJyZl9fd3JhcHBlclwiLCBpZDogaWQgfSxcbiAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChXcmFwcGVyLCBudWxsLFxuICAgICAgICAgICAgUmVhY3QuY3JlYXRlRWxlbWVudChHcmFwaFZpZXckMSwgeyBvbkluaXQ6IG9uSW5pdCwgb25Nb3ZlOiBvbk1vdmUsIG9uTW92ZVN0YXJ0OiBvbk1vdmVTdGFydCwgb25Nb3ZlRW5kOiBvbk1vdmVFbmQsIG9uTm9kZUNsaWNrOiBvbk5vZGVDbGljaywgb25FZGdlQ2xpY2s6IG9uRWRnZUNsaWNrLCBvbk5vZGVNb3VzZUVudGVyOiBvbk5vZGVNb3VzZUVudGVyLCBvbk5vZGVNb3VzZU1vdmU6IG9uTm9kZU1vdXNlTW92ZSwgb25Ob2RlTW91c2VMZWF2ZTogb25Ob2RlTW91c2VMZWF2ZSwgb25Ob2RlQ29udGV4dE1lbnU6IG9uTm9kZUNvbnRleHRNZW51LCBvbk5vZGVEb3VibGVDbGljazogb25Ob2RlRG91YmxlQ2xpY2ssIG5vZGVUeXBlczogbm9kZVR5cGVzLCBlZGdlVHlwZXM6IGVkZ2VUeXBlcywgY29ubmVjdGlvbkxpbmVUeXBlOiBjb25uZWN0aW9uTGluZVR5cGUsIGNvbm5lY3Rpb25MaW5lU3R5bGU6IGNvbm5lY3Rpb25MaW5lU3R5bGUsIGNvbm5lY3Rpb25MaW5lQ29tcG9uZW50OiBjb25uZWN0aW9uTGluZUNvbXBvbmVudCwgY29ubmVjdGlvbkxpbmVDb250YWluZXJTdHlsZTogY29ubmVjdGlvbkxpbmVDb250YWluZXJTdHlsZSwgc2VsZWN0aW9uS2V5Q29kZTogc2VsZWN0aW9uS2V5Q29kZSwgc2VsZWN0aW9uT25EcmFnOiBzZWxlY3Rpb25PbkRyYWcsIHNlbGVjdGlvbk1vZGU6IHNlbGVjdGlvbk1vZGUsIGRlbGV0ZUtleUNvZGU6IGRlbGV0ZUtleUNvZGUsIG11bHRpU2VsZWN0aW9uS2V5Q29kZTogbXVsdGlTZWxlY3Rpb25LZXlDb2RlLCBwYW5BY3RpdmF0aW9uS2V5Q29kZTogcGFuQWN0aXZhdGlvbktleUNvZGUsIHpvb21BY3RpdmF0aW9uS2V5Q29kZTogem9vbUFjdGl2YXRpb25LZXlDb2RlLCBvbmx5UmVuZGVyVmlzaWJsZUVsZW1lbnRzOiBvbmx5UmVuZGVyVmlzaWJsZUVsZW1lbnRzLCBzZWxlY3ROb2Rlc09uRHJhZzogc2VsZWN0Tm9kZXNPbkRyYWcsIGRlZmF1bHRWaWV3cG9ydDogZGVmYXVsdFZpZXdwb3J0LCB0cmFuc2xhdGVFeHRlbnQ6IHRyYW5zbGF0ZUV4dGVudCwgbWluWm9vbTogbWluWm9vbSwgbWF4Wm9vbTogbWF4Wm9vbSwgcHJldmVudFNjcm9sbGluZzogcHJldmVudFNjcm9sbGluZywgem9vbU9uU2Nyb2xsOiB6b29tT25TY3JvbGwsIHpvb21PblBpbmNoOiB6b29tT25QaW5jaCwgem9vbU9uRG91YmxlQ2xpY2s6IHpvb21PbkRvdWJsZUNsaWNrLCBwYW5PblNjcm9sbDogcGFuT25TY3JvbGwsIHBhbk9uU2Nyb2xsU3BlZWQ6IHBhbk9uU2Nyb2xsU3BlZWQsIHBhbk9uU2Nyb2xsTW9kZTogcGFuT25TY3JvbGxNb2RlLCBwYW5PbkRyYWc6IHBhbk9uRHJhZywgb25QYW5lQ2xpY2s6IG9uUGFuZUNsaWNrLCBvblBhbmVNb3VzZUVudGVyOiBvblBhbmVNb3VzZUVudGVyLCBvblBhbmVNb3VzZU1vdmU6IG9uUGFuZU1vdXNlTW92ZSwgb25QYW5lTW91c2VMZWF2ZTogb25QYW5lTW91c2VMZWF2ZSwgb25QYW5lU2Nyb2xsOiBvblBhbmVTY3JvbGwsIG9uUGFuZUNvbnRleHRNZW51OiBvblBhbmVDb250ZXh0TWVudSwgb25TZWxlY3Rpb25Db250ZXh0TWVudTogb25TZWxlY3Rpb25Db250ZXh0TWVudSwgb25TZWxlY3Rpb25TdGFydDogb25TZWxlY3Rpb25TdGFydCwgb25TZWxlY3Rpb25FbmQ6IG9uU2VsZWN0aW9uRW5kLCBvbkVkZ2VVcGRhdGU6IG9uRWRnZVVwZGF0ZSwgb25FZGdlQ29udGV4dE1lbnU6IG9uRWRnZUNvbnRleHRNZW51LCBvbkVkZ2VEb3VibGVDbGljazogb25FZGdlRG91YmxlQ2xpY2ssIG9uRWRnZU1vdXNlRW50ZXI6IG9uRWRnZU1vdXNlRW50ZXIsIG9uRWRnZU1vdXNlTW92ZTogb25FZGdlTW91c2VNb3ZlLCBvbkVkZ2VNb3VzZUxlYXZlOiBvbkVkZ2VNb3VzZUxlYXZlLCBvbkVkZ2VVcGRhdGVTdGFydDogb25FZGdlVXBkYXRlU3RhcnQsIG9uRWRnZVVwZGF0ZUVuZDogb25FZGdlVXBkYXRlRW5kLCBlZGdlVXBkYXRlclJhZGl1czogZWRnZVVwZGF0ZXJSYWRpdXMsIGRlZmF1bHRNYXJrZXJDb2xvcjogZGVmYXVsdE1hcmtlckNvbG9yLCBub0RyYWdDbGFzc05hbWU6IG5vRHJhZ0NsYXNzTmFtZSwgbm9XaGVlbENsYXNzTmFtZTogbm9XaGVlbENsYXNzTmFtZSwgbm9QYW5DbGFzc05hbWU6IG5vUGFuQ2xhc3NOYW1lLCBlbGV2YXRlRWRnZXNPblNlbGVjdDogZWxldmF0ZUVkZ2VzT25TZWxlY3QsIHJmSWQ6IHJmSWQsIGRpc2FibGVLZXlib2FyZEExMXk6IGRpc2FibGVLZXlib2FyZEExMXksIG5vZGVPcmlnaW46IG5vZGVPcmlnaW4sIG5vZGVFeHRlbnQ6IG5vZGVFeHRlbnQgfSksXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFN0b3JlVXBkYXRlciwgeyBub2Rlczogbm9kZXMsIGVkZ2VzOiBlZGdlcywgZGVmYXVsdE5vZGVzOiBkZWZhdWx0Tm9kZXMsIGRlZmF1bHRFZGdlczogZGVmYXVsdEVkZ2VzLCBvbkNvbm5lY3Q6IG9uQ29ubmVjdCwgb25Db25uZWN0U3RhcnQ6IG9uQ29ubmVjdFN0YXJ0LCBvbkNvbm5lY3RFbmQ6IG9uQ29ubmVjdEVuZCwgb25DbGlja0Nvbm5lY3RTdGFydDogb25DbGlja0Nvbm5lY3RTdGFydCwgb25DbGlja0Nvbm5lY3RFbmQ6IG9uQ2xpY2tDb25uZWN0RW5kLCBub2Rlc0RyYWdnYWJsZTogbm9kZXNEcmFnZ2FibGUsIG5vZGVzQ29ubmVjdGFibGU6IG5vZGVzQ29ubmVjdGFibGUsIG5vZGVzRm9jdXNhYmxlOiBub2Rlc0ZvY3VzYWJsZSwgZWRnZXNGb2N1c2FibGU6IGVkZ2VzRm9jdXNhYmxlLCBlZGdlc1VwZGF0YWJsZTogZWRnZXNVcGRhdGFibGUsIGVsZW1lbnRzU2VsZWN0YWJsZTogZWxlbWVudHNTZWxlY3RhYmxlLCBlbGV2YXRlTm9kZXNPblNlbGVjdDogZWxldmF0ZU5vZGVzT25TZWxlY3QsIG1pblpvb206IG1pblpvb20sIG1heFpvb206IG1heFpvb20sIG5vZGVFeHRlbnQ6IG5vZGVFeHRlbnQsIG9uTm9kZXNDaGFuZ2U6IG9uTm9kZXNDaGFuZ2UsIG9uRWRnZXNDaGFuZ2U6IG9uRWRnZXNDaGFuZ2UsIHNuYXBUb0dyaWQ6IHNuYXBUb0dyaWQsIHNuYXBHcmlkOiBzbmFwR3JpZCwgY29ubmVjdGlvbk1vZGU6IGNvbm5lY3Rpb25Nb2RlLCB0cmFuc2xhdGVFeHRlbnQ6IHRyYW5zbGF0ZUV4dGVudCwgY29ubmVjdE9uQ2xpY2s6IGNvbm5lY3RPbkNsaWNrLCBkZWZhdWx0RWRnZU9wdGlvbnM6IGRlZmF1bHRFZGdlT3B0aW9ucywgZml0VmlldzogZml0VmlldywgZml0Vmlld09wdGlvbnM6IGZpdFZpZXdPcHRpb25zLCBvbk5vZGVzRGVsZXRlOiBvbk5vZGVzRGVsZXRlLCBvbkVkZ2VzRGVsZXRlOiBvbkVkZ2VzRGVsZXRlLCBvbk5vZGVEcmFnU3RhcnQ6IG9uTm9kZURyYWdTdGFydCwgb25Ob2RlRHJhZzogb25Ob2RlRHJhZywgb25Ob2RlRHJhZ1N0b3A6IG9uTm9kZURyYWdTdG9wLCBvblNlbGVjdGlvbkRyYWc6IG9uU2VsZWN0aW9uRHJhZywgb25TZWxlY3Rpb25EcmFnU3RhcnQ6IG9uU2VsZWN0aW9uRHJhZ1N0YXJ0LCBvblNlbGVjdGlvbkRyYWdTdG9wOiBvblNlbGVjdGlvbkRyYWdTdG9wLCBub1BhbkNsYXNzTmFtZTogbm9QYW5DbGFzc05hbWUsIG5vZGVPcmlnaW46IG5vZGVPcmlnaW4sIHJmSWQ6IHJmSWQsIGF1dG9QYW5PbkNvbm5lY3Q6IGF1dG9QYW5PbkNvbm5lY3QsIGF1dG9QYW5Pbk5vZGVEcmFnOiBhdXRvUGFuT25Ob2RlRHJhZywgb25FcnJvcjogb25FcnJvciwgY29ubmVjdGlvblJhZGl1czogY29ubmVjdGlvblJhZGl1cywgaXNWYWxpZENvbm5lY3Rpb246IGlzVmFsaWRDb25uZWN0aW9uLCBub2RlRHJhZ1RocmVzaG9sZDogbm9kZURyYWdUaHJlc2hvbGQgfSksXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KFdyYXBwZXIkMSwgeyBvblNlbGVjdGlvbkNoYW5nZTogb25TZWxlY3Rpb25DaGFuZ2UgfSksXG4gICAgICAgICAgICBjaGlsZHJlbixcbiAgICAgICAgICAgIFJlYWN0LmNyZWF0ZUVsZW1lbnQoQXR0cmlidXRpb24sIHsgcHJvT3B0aW9uczogcHJvT3B0aW9ucywgcG9zaXRpb246IGF0dHJpYnV0aW9uUG9zaXRpb24gfSksXG4gICAgICAgICAgICBSZWFjdC5jcmVhdGVFbGVtZW50KEExMXlEZXNjcmlwdGlvbnMsIHsgcmZJZDogcmZJZCwgZGlzYWJsZUtleWJvYXJkQTExeTogZGlzYWJsZUtleWJvYXJkQTExeSB9KSkpKTtcbn0pO1xuUmVhY3RGbG93LmRpc3BsYXlOYW1lID0gJ1JlYWN0Rmxvdyc7XG5cbmNvbnN0IHNlbGVjdG9yJDEgPSAocykgPT4gcy5kb21Ob2RlPy5xdWVyeVNlbGVjdG9yKCcucmVhY3QtZmxvd19fZWRnZWxhYmVsLXJlbmRlcmVyJyk7XG5mdW5jdGlvbiBFZGdlTGFiZWxSZW5kZXJlcih7IGNoaWxkcmVuIH0pIHtcbiAgICBjb25zdCBlZGdlTGFiZWxSZW5kZXJlciA9IHVzZVN0b3JlKHNlbGVjdG9yJDEpO1xuICAgIGlmICghZWRnZUxhYmVsUmVuZGVyZXIpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBjcmVhdGVQb3J0YWwoY2hpbGRyZW4sIGVkZ2VMYWJlbFJlbmRlcmVyKTtcbn1cblxuZnVuY3Rpb24gdXNlVXBkYXRlTm9kZUludGVybmFscygpIHtcbiAgICBjb25zdCBzdG9yZSA9IHVzZVN0b3JlQXBpKCk7XG4gICAgcmV0dXJuIHVzZUNhbGxiYWNrKChpZCkgPT4ge1xuICAgICAgICBjb25zdCB7IGRvbU5vZGUsIHVwZGF0ZU5vZGVEaW1lbnNpb25zIH0gPSBzdG9yZS5nZXRTdGF0ZSgpO1xuICAgICAgICBjb25zdCB1cGRhdGVJZHMgPSBBcnJheS5pc0FycmF5KGlkKSA/IGlkIDogW2lkXTtcbiAgICAgICAgY29uc3QgdXBkYXRlcyA9IHVwZGF0ZUlkcy5yZWR1Y2UoKHJlcywgdXBkYXRlSWQpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG5vZGVFbGVtZW50ID0gZG9tTm9kZT8ucXVlcnlTZWxlY3RvcihgLnJlYWN0LWZsb3dfX25vZGVbZGF0YS1pZD1cIiR7dXBkYXRlSWR9XCJdYCk7XG4gICAgICAgICAgICBpZiAobm9kZUVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICByZXMucHVzaCh7IGlkOiB1cGRhdGVJZCwgbm9kZUVsZW1lbnQsIGZvcmNlVXBkYXRlOiB0cnVlIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlcztcbiAgICAgICAgfSwgW10pO1xuICAgICAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gdXBkYXRlTm9kZURpbWVuc2lvbnModXBkYXRlcykpO1xuICAgIH0sIFtdKTtcbn1cblxuY29uc3Qgbm9kZXNTZWxlY3RvciA9IChzdGF0ZSkgPT4gc3RhdGUuZ2V0Tm9kZXMoKTtcbmZ1bmN0aW9uIHVzZU5vZGVzKCkge1xuICAgIGNvbnN0IG5vZGVzID0gdXNlU3RvcmUobm9kZXNTZWxlY3Rvciwgc2hhbGxvdyk7XG4gICAgcmV0dXJuIG5vZGVzO1xufVxuXG5jb25zdCBlZGdlc1NlbGVjdG9yID0gKHN0YXRlKSA9PiBzdGF0ZS5lZGdlcztcbmZ1bmN0aW9uIHVzZUVkZ2VzKCkge1xuICAgIGNvbnN0IGVkZ2VzID0gdXNlU3RvcmUoZWRnZXNTZWxlY3Rvciwgc2hhbGxvdyk7XG4gICAgcmV0dXJuIGVkZ2VzO1xufVxuXG5jb25zdCB2aWV3cG9ydFNlbGVjdG9yID0gKHN0YXRlKSA9PiAoe1xuICAgIHg6IHN0YXRlLnRyYW5zZm9ybVswXSxcbiAgICB5OiBzdGF0ZS50cmFuc2Zvcm1bMV0sXG4gICAgem9vbTogc3RhdGUudHJhbnNmb3JtWzJdLFxufSk7XG5mdW5jdGlvbiB1c2VWaWV3cG9ydCgpIHtcbiAgICBjb25zdCB2aWV3cG9ydCA9IHVzZVN0b3JlKHZpZXdwb3J0U2VsZWN0b3IsIHNoYWxsb3cpO1xuICAgIHJldHVybiB2aWV3cG9ydDtcbn1cblxuLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLWV4cGxpY2l0LWFueSAqL1xuZnVuY3Rpb24gY3JlYXRlVXNlSXRlbXNTdGF0ZShhcHBseUNoYW5nZXMpIHtcbiAgICByZXR1cm4gKGluaXRpYWxJdGVtcykgPT4ge1xuICAgICAgICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKGluaXRpYWxJdGVtcyk7XG4gICAgICAgIGNvbnN0IG9uSXRlbXNDaGFuZ2UgPSB1c2VDYWxsYmFjaygoY2hhbmdlcykgPT4gc2V0SXRlbXMoKGl0ZW1zKSA9PiBhcHBseUNoYW5nZXMoY2hhbmdlcywgaXRlbXMpKSwgW10pO1xuICAgICAgICByZXR1cm4gW2l0ZW1zLCBzZXRJdGVtcywgb25JdGVtc0NoYW5nZV07XG4gICAgfTtcbn1cbmNvbnN0IHVzZU5vZGVzU3RhdGUgPSBjcmVhdGVVc2VJdGVtc1N0YXRlKGFwcGx5Tm9kZUNoYW5nZXMpO1xuY29uc3QgdXNlRWRnZXNTdGF0ZSA9IGNyZWF0ZVVzZUl0ZW1zU3RhdGUoYXBwbHlFZGdlQ2hhbmdlcyk7XG5cbmZ1bmN0aW9uIHVzZU9uVmlld3BvcnRDaGFuZ2UoeyBvblN0YXJ0LCBvbkNoYW5nZSwgb25FbmQgfSkge1xuICAgIGNvbnN0IHN0b3JlID0gdXNlU3RvcmVBcGkoKTtcbiAgICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBzdG9yZS5zZXRTdGF0ZSh7IG9uVmlld3BvcnRDaGFuZ2VTdGFydDogb25TdGFydCB9KTtcbiAgICB9LCBbb25TdGFydF0pO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIHN0b3JlLnNldFN0YXRlKHsgb25WaWV3cG9ydENoYW5nZTogb25DaGFuZ2UgfSk7XG4gICAgfSwgW29uQ2hhbmdlXSk7XG4gICAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgc3RvcmUuc2V0U3RhdGUoeyBvblZpZXdwb3J0Q2hhbmdlRW5kOiBvbkVuZCB9KTtcbiAgICB9LCBbb25FbmRdKTtcbn1cblxuZnVuY3Rpb24gdXNlT25TZWxlY3Rpb25DaGFuZ2UoeyBvbkNoYW5nZSB9KSB7XG4gICAgY29uc3Qgc3RvcmUgPSB1c2VTdG9yZUFwaSgpO1xuICAgIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IG5leHRTZWxlY3Rpb25DaGFuZ2VIYW5kbGVycyA9IFsuLi5zdG9yZS5nZXRTdGF0ZSgpLm9uU2VsZWN0aW9uQ2hhbmdlLCBvbkNoYW5nZV07XG4gICAgICAgIHN0b3JlLnNldFN0YXRlKHsgb25TZWxlY3Rpb25DaGFuZ2U6IG5leHRTZWxlY3Rpb25DaGFuZ2VIYW5kbGVycyB9KTtcbiAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IG5leHRIYW5kbGVycyA9IHN0b3JlLmdldFN0YXRlKCkub25TZWxlY3Rpb25DaGFuZ2UuZmlsdGVyKChmbikgPT4gZm4gIT09IG9uQ2hhbmdlKTtcbiAgICAgICAgICAgIHN0b3JlLnNldFN0YXRlKHsgb25TZWxlY3Rpb25DaGFuZ2U6IG5leHRIYW5kbGVycyB9KTtcbiAgICAgICAgfTtcbiAgICB9LCBbb25DaGFuZ2VdKTtcbn1cblxuY29uc3Qgc2VsZWN0b3IgPSAob3B0aW9ucykgPT4gKHMpID0+IHtcbiAgICBpZiAocy5ub2RlSW50ZXJuYWxzLnNpemUgPT09IDApIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gc1xuICAgICAgICAuZ2V0Tm9kZXMoKVxuICAgICAgICAuZmlsdGVyKChuKSA9PiAob3B0aW9ucy5pbmNsdWRlSGlkZGVuTm9kZXMgPyB0cnVlIDogIW4uaGlkZGVuKSlcbiAgICAgICAgLmV2ZXJ5KChuKSA9PiBuW2ludGVybmFsc1N5bWJvbF0/LmhhbmRsZUJvdW5kcyAhPT0gdW5kZWZpbmVkKTtcbn07XG5jb25zdCBkZWZhdWx0T3B0aW9ucyA9IHtcbiAgICBpbmNsdWRlSGlkZGVuTm9kZXM6IGZhbHNlLFxufTtcbmZ1bmN0aW9uIHVzZU5vZGVzSW5pdGlhbGl6ZWQob3B0aW9ucyA9IGRlZmF1bHRPcHRpb25zKSB7XG4gICAgY29uc3QgaW5pdGlhbGl6ZWQgPSB1c2VTdG9yZShzZWxlY3RvcihvcHRpb25zKSk7XG4gICAgcmV0dXJuIGluaXRpYWxpemVkO1xufVxuXG4vLyBzcGFya19kZXZfbm90ZTogZ2V0SG9zdEZvckVsZW1lbnQgYW5kIGdldEVkZ2VDZW50ZXIgYWRkZWQgdG8gZXhwb3J0IGxpc3RcbmV4cG9ydCB7IEJhc2VFZGdlLCBCZXppZXJFZGdlLCBDb25uZWN0aW9uTGluZVR5cGUsIENvbm5lY3Rpb25Nb2RlLCBFZGdlTGFiZWxSZW5kZXJlciwgRWRnZVRleHQkMSBhcyBFZGdlVGV4dCwgSGFuZGxlJDEgYXMgSGFuZGxlLCBNYXJrZXJUeXBlLCBQYW5PblNjcm9sbE1vZGUsIFBhbmVsLCBQb3NpdGlvbiwgUmVhY3RGbG93LCBSZWFjdEZsb3dQcm92aWRlciwgU2VsZWN0aW9uTW9kZSwgU2ltcGxlQmV6aWVyRWRnZSwgU21vb3RoU3RlcEVkZ2UsIFN0ZXBFZGdlLCBTdHJhaWdodEVkZ2UsIGFkZEVkZ2UsIGFwcGx5RWRnZUNoYW5nZXMsIGFwcGx5Tm9kZUNoYW5nZXMsIGJveFRvUmVjdCwgY2xhbXAsIGdldEJlemllclBhdGgsIGdldEJvdW5kc09mUmVjdHMsIGdldENvbm5lY3RlZEVkZ2VzLCBnZXRJbmNvbWVycywgZ2V0TWFya2VyRW5kLCBnZXROb2RlUG9zaXRpb25XaXRoT3JpZ2luLCBnZXROb2Rlc0JvdW5kcywgZ2V0T3V0Z29lcnMsIGdldFJlY3RPZk5vZGVzLCBnZXRTaW1wbGVCZXppZXJQYXRoLCBnZXRTbW9vdGhTdGVwUGF0aCwgZ2V0U3RyYWlnaHRQYXRoLCBnZXRUcmFuc2Zvcm1Gb3JCb3VuZHMsIGdldFZpZXdwb3J0Rm9yQm91bmRzLCBoYW5kbGVQYXJlbnRFeHBhbmQsIGludGVybmFsc1N5bWJvbCwgaXNFZGdlLCBpc05vZGUsIHJlY3RUb0JveCwgdXBkYXRlRWRnZSwgdXNlRWRnZXMsIHVzZUVkZ2VzU3RhdGUsIHVzZUdldFBvaW50ZXJQb3NpdGlvbiwgdXNlS2V5UHJlc3MsIHVzZU5vZGVJZCwgdXNlTm9kZXMsIHVzZU5vZGVzSW5pdGlhbGl6ZWQsIHVzZU5vZGVzU3RhdGUsIHVzZU9uU2VsZWN0aW9uQ2hhbmdlLCB1c2VPblZpZXdwb3J0Q2hhbmdlLCB1c2VSZWFjdEZsb3csIHVzZVN0b3JlLCB1c2VTdG9yZUFwaSwgdXNlVXBkYXRlTm9kZUludGVybmFscywgdXNlVmlld3BvcnQsIGdldEhvc3RGb3JFbGVtZW50LCBnZXRFZGdlQ2VudGVyIH07XG4iXSwibmFtZXMiOltdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/core/dist/esm/index.mjs\n\n}");
22760
-
22761
- /***/ }),
22762
-
22763
22753
  /***/ "./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/reactflow/dist/style.css":
22764
22754
  /*!*******************************************************************************************!*\
22765
22755
  !*** ./src/api/leafui/elements/floweditor/lib/reactflow.11.10.4/reactflow/dist/style.css ***!